-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Stop vendoring packages #2825
Comments
SolutionRecent advancements in specifications and tooling around packaging promise to help address some of the issues above. The solution proposed herein is that Setuptools should: (a) Declare its own dependencies normally, pinning versions only for known-incompatibilities. This last piece (f) is perhaps the most controversial. Let's think of a concrete example, installing
|
I don't think we can do this yet. Not until pip removes the fallbacks to direct setup.py invocation (https://pip.pypa.io/en/stable/reference/build-system/setup-py/ -- in-progress) and the separation of pkg_resources is completed. Without those, I think this would exceed our available churn budget. :)
setuptools is installed with pip, by all supported mechanisms to install pip -- pypa/pip#10530 (comment). IMO this should be considered a pre-condition for doing this, and it's worthwhile spending a few months or so publicising this change before we actually make it. FWIW, pip's solution for this is something I maintain separately: https://github.com/pradyunsg/vendoring (I'll consistently use If you're curious about how the tool works, my suggestion is to clone pip and run
I think these constraints are non-existent / workable, if you adopt
This is somewhat true -- you still have the caveat of needing to manage evolution, but you can use standard tooling (like dependabot) to manage the upgrading, if you go down the Basically, the moment you start vendoring stuff, you need to start thinking of the project as being managed like an application with pinned dependencies -- all the corresponding dependency management constraints apply (except you run
If you adopt It is possible to include comments in input file to the tool (it's basically a requirements.txt file, that's consumed by pip), which can be useful to describe this nuance.
Yep, and... it shouldn't be too difficult if you use vendoring to bring that package into setuptools.
True. Anything that's non-pure-Python or provides an importable API for plugins is non-vendorable.
Generally, not true; based on my experience with
I'm not quite sure what you mean here -- The only case this can be an issue is if you expect this difference to exist/not exist in some code -- since that'd be fragile. It's often really straightforward to avoid that though. |
The readme for vendoring talks only about how the project is used for pip only and provides no guidance on how to use it. I guess you're proposing that I reverse-engineer the usage from pip's usage and then try to apply that to this project. I guess I can give that a try. |
In pradyunsg/vendoring#37, I learned that the vendoring project is uninterested in supporting the complexity of Setuptools, so if Setuptools were to adopt vendoring, it would need to at the very least provide its own orchestration of invoking vendoring across multiple configurations, which is barely preferable and in some ways more duplicative to the current vendoring technique. Moreover, other issues like pradyunsg/vendoring#38 suggest that vendoring requires supplying default values even for basic operation, so that would bring extra cruft that would need to be copied across multiple configs. At some point, I might consider forking vendoring to satisfy some of these needs, but for now, as long as vendoring is needed, Setuptools can continue to use its own technique. |
I would really love to see making unbundling easier without making bootstrap very hard. That said, as a distro packager I don't need it "perfect" from pure pip standpoint. One possibility that I think might be worth exploring is trying to make a subset of setuptools needed for bootstrap work with smaller number of vendored dependencies, possibly via gracefully handling missing packages and running with limited functionality without them. I think we could at least avoid more-itertools and ordered-set this way. |
Honestly, I don't see this happening anymore, given that every subsequent release of setuptools adds more vendoring, and it literally takes hours to make setuptools work unvendored. On top of this, patched pyproject_validator basically made including new versions of setuptools in Gentoo impossible. |
I'm sorry, nevermind, I can't even read package names right. |
Hi @mgorny I am sorry the latest vendored packages affect Gentoo. Regarding Is this approach still problematic? Would it help if I move the What are the approach you guys use when dealing with projects that use generators? |
The directory doesn't matter much for us, we just mangle all the references to use the external package. As for generators, we prefer to rebuild everything. I don't know whether this is the case here but normally we assume that e.g. updated dependencies (like cython) could result in different output, possibly fixing some bugs that might have been present in the original generated version. |
Thank you very much for the information @mgorny. Let's see how we can solve this. Currently there is a command for re-generating the files from I could also create a separated script for generating the files, does that help? Do you have other suggestion? |
If you don't mind bearing with me for a while more, could we please take a step back and verify whether I'm understanding things correctly? IIUC:
If both points are correct, then I think the best long-term solution would be to actually split If that's a bit much, I think moving I'm sorry about my attitude yesterday. |
Thank you very much for the input @mgorny.
Precisely. The way
This is more or less what happens. The idea for Currently, Regarding the proposed solutions, I think both could work. My preference however would be the second approach (because of the mid-term vision of moving the tool-specific specs to Footnotes
|
Thanks for the explanation. If the end goal is for setuptools to host the schemas, then let's focus on the second option indeed. It'd still be nice to able to easily regen the resulting data but I don't think that's a priority, i.e. something to put on the "far TODO". |
In #4455 (comment), I've been thinking maybe there's a better way to vendor dependencies that's far less intrusive and doesn't require re-writing the vendored packages. I'm exploring that now. |
For the record, one risk I see is that if the user has an incompatible version of the dependency installed, setuptools would use it rather than the "vendored" fallback — but perhaps there's a smart way of avoiding that. |
Good point. On one hand, I was thinking that concern is to be addressed the same way it is for any other application or library - that is, declare the best estimate of what dependencies are compatible, put the onus on the user to supply compatible packages (when things break). There are two problems with that way of thinking:
One way to mitigate this concern could be to (a) require that dependencies follow semver, (b) proactively pin against breaking changes, and (c) lean on the dependencies to yank any unexpected breakages that violate semver. I would like to pursue a world where vendored dependencies are used rarely and there's little to no dependence on their stability. In other words, I'd like for Setuptools to "work at head" of the Python ecosystem (unless explicitly indicated otherwise). |
In #4457, I'm pleased to say I have an initial proof of concept that applies the concept and is largely working. There are some mypy tests failing, but I'm confident those can be fixed or ignored. Thusfar, I've only partially applied the changes. I plan to continue to pursue the approach and replace the |
Oh, one more thing just occurred to me. Some of the setuptools dependencies already avoid the bootstrap problem by using |
Note that if you would install them with pip, you still need setuptools first. |
FTR looks like this broke our CI that does Traceback (most recent call last):
File "/root/ansible/test/results/.tmp/output_dir/venv/lib/python3.10/site-packages/pep517/in_process/_in_process.py", line 351, in <module>
main()
File "/root/ansible/test/results/.tmp/output_dir/venv/lib/python3.10/site-packages/pep517/in_process/_in_process.py", line 333, in main
json_out['return_val'] = hook(**hook_input['kwargs'])
File "/root/ansible/test/results/.tmp/output_dir/venv/lib/python3.10/site-packages/pep517/in_process/_in_process.py", line 118, in get_requires_for_build_wheel
return hook(config_settings)
File "/tmp/pep517-build-env-9dden348/lib/python3.10/site-packages/setuptools/build_meta.py", line 327, in get_requires_for_build_wheel
return self._get_build_requires(config_settings, requirements=[])
File "/tmp/pep517-build-env-9dden348/lib/python3.10/site-packages/setuptools/build_meta.py", line 297, in _get_build_requires
self.run_setup()
File "/tmp/pep517-build-env-9dden348/lib/python3.10/site-packages/setuptools/build_meta.py", line 313, in run_setup
exec(code, locals())
File "<string>", line 1, in <module>
File "/tmp/pep517-build-env-9dden348/lib/python3.10/site-packages/setuptools/__init__.py", line 106, in setup
return distutils.core.setup(**attrs)
File "/tmp/pep517-build-env-9dden348/lib/python3.10/site-packages/setuptools/_distutils/core.py", line 184, in setup
return run_commands(dist)
File "/tmp/pep517-build-env-9dden348/lib/python3.10/site-packages/setuptools/_distutils/core.py", line 200, in run_commands
dist.run_commands()
check_call(cmd, cwd=cwd, env=env)
File "/usr/lib/python3.10/subprocess.py", line 369, in check_call
raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command '['/root/ansible/test/results/.tmp/output_dir/venv/bin/python', '/root/ansible/test/results/.tmp/output_dir/venv/lib/python3.10/site-packages/pep517/in_process/_in_process.py', 'get_requires_for_build_wheel', '/tmp/tmpevxoxxw3']' returned non-zero exit status 1. This is with [build-system]
requires = [
"setuptools >= 44",
"wheel",
]
build-backend = "setuptools.build_meta" This is just a heads-up. It's happening in a packaging-related test. I'm yet to figure out what's happening there since it's only reproducible on one of the stable branches but not in devel. And I don't think it's related to |
I can see the underlying error in the traceback.
That's been reported in #4483. I'll be very interested to learn if it's feasible to work around it by upgrading the dependencies (or removing the offending old versions). |
The tests run against whatever's in the target distro (Ubuntu 20.04 in this case). At least, not the shared system-wide stuff, usually. I can apply the workaround of the |
This is now necessary since `setuptools >= 71` started preferring externally present stdlib deps over the vendored ones. Refs: * pypa/setuptools#4457 * pypa/setuptools#4483 * pypa/setuptools#2825
Thanks! Long-term, I'm hoping that setuptools can declare it's actual dependencies, but the problem is probably one of the hardest ones in the Python ecosystem (pypa/packaging-problems#342). |
The current implementation of Setuptools has its dependencies (separately for
setuptools
andpkg_resources
) vendored into the package. The project implemented this approach because of the bootstrapping problem.Bootstrapping Problem
Setuptools extended distutils, which was designed to sit at the root of a packaging system and presumed to be present and without any dependencies. Over time, Setuptools superseded distutils but inherited these constraints. In particular, when a system integrator wishes to build a system from sources, it requires a directed acyclic graph (DAG) of both build-time and runtime dependencies. As a result, Setuptools cannot depend on any package that uses Setuptools to build (or whose dependencies require Setuptools to build). This bootstrapping problem includes Setuptools itself, as it requires itself to build.
Vendoring
As the ecosystem grew more complex, with standards-based implementations (such as packaging) appearing as third-party packages and not available in the standard library, Setuptools found itself requiring dependencies, but because of the bootstrapping problem, Setuptools adopted a vendoring strategy (copying the packages directly into the project) as a means of requiring that functionality.
However, this approach creates constraints and complications to the project:
pkg_resources
into a separate package, but even thoughpkg_resources
has no dependency onsetuptools
to run, it still must vendor its own dependencies (is this true?).The text was updated successfully, but these errors were encountered: