-
Notifications
You must be signed in to change notification settings - Fork 124
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
Provide function to get dependencies of package without building #181
Comments
Line 192 in 5d3f89b
Do you need separation between build dependencies and project dependencies? |
If a build system doesn't provide |
This is up for discussion. People have been using |
We're not talking about build/backend dependencies here, but dependencies for the actual package. The low-cost option if the backend supports is to call https://www.python.org/dev/peps/pep-0517/#prepare-metadata-for-build-wheel and pass that to the dist-info parser, alternatively, we need to build a wheel, extract the dist-info, and pass that on. |
Yes I forgot. There should be a fallback so that in this case the package is built in order to get its dependencies. |
Ah, sorry. We can provide |
I agree that perhaps parsing is out of scope, though we're really only talking about a stdlib import: from importlib.metadata import Distribution
dist = Distribution.at("/path/to/metadata.dist-info") However, I don't agree that we need build.get_dist_info(path) That calls from importlib.metadata import Distribution
with ProjectBuilder() as builder:
with TemporaryDirectory() as tmp_dir:
dist = Distribution.at(builder.get_dist_info(tmp_dir))
for req in dist.requires:
print(req) |
I think this is a duplicate of #130 |
It's important to understand the context of this PR. It's a hook for GitHub Dependency Graph.
Of course, the obvious work-around will be that PEP517 build-systems will be forced to provide their own |
I don't think that's relevant. It's one use case, but any IDE/tool that is interested in finding metadata about a python project is just as much a valid use case. What's more the Github team already made it clear that they don't have any plans to do the switch anytime soon (even if we provide a way).
It's not. As you explained this issue goes beyond the scope of just exposing access to the
Doing this dance is spelled out exactly as the responsibility of any frontend per PEP-517 (e.g. this tool). Read the final sentence at https://www.python.org/dev/peps/pep-0517/#prepare-metadata-for-build-wheel. |
I can also see a good use case of this for a project like https://github.com/Arkq/flake8-requirements so it can get dependencies of a project using a single common source, regardless of whether the project uses setuptools, poetry, flit, PEP621, etc. |
Can this be closed on account of #301? |
Could a helper function be created that abstracts the tmpdir creation? |
@jaraco suggested the same. We are considering adding a plumbing module, which could hold these kind of helper functions. |
There's been talk about creating a helper module which would abstract common operations, but until then, creating a tmpdir manually shouldn't be too bad. |
Doh, we replied at the same time 😄 |
Any updates on this helper module? Or is #301 (comment) still the recommended approach for now? If we are using that snippet, is it possible to silence the extra printing to stdout/stderr? |
tldr: The ability to instrument a packages dependencies, pre build (and post build), is critical and that signal is still being lost among the 'packaging noise'. Downstreams, FreeBSD in my case, but many others, including all downstream OS packagers, have had a critical and long time need for a consistent and single point for dependency discovery. This has, over recent years, been complicated by the flurry of new, alternative and (orthogonally) different ways to declare dependencies, including, but not limited to:
Throughout the "packaging dark ages" and to now, almost everyone has grokked at least some understanding of the complexities of dependencies, in particular their dynamic nature (setup vs run time, etc), because these are always the kinds of first responses and conversations that take place. While we all mostly have that understanding, it must also be understood and made clear that requests for these capabilities is not "we need exact, complete and perfect dependency discovery for every case, in all stages, all the time, including for cases that are hard or not even in principle possible", it is "the Python ecosystem and its entire community needs the best dependency discovery that we can muster", with clear descriptions of their limitations and gaps, when and where they apply. If this means at first, only being able to discover what a package statically declares for itself (install_requires, setup_requires, setup, build_requires, tests_require extras_require, whatever), that's a great start. We can then have the conversation about mechanics to refine and improve that discovery/instrumentation, in light of the dynamic (pre build / post build) changes to them. The absolute key needs are:
|
IMHO this has been done, mostly as indicated by @wwuck above. You can load the project dependencies with the following snippet (there's no guarantee it's not going to trigger a build though, that's just not possible). import tempfile
from importlib.metadata import PathDistribution
from pathlib import Path
from packaging.requirements import Requirement
from build import ProjectBuilder
builder = ProjectBuilder('.')
with tempfile.TemporaryDirectory() as tmpdir:
distribution = PathDistribution(Path(builder.metadata_path(tmpdir)))
requires = [Requirement(i) for i in distribution.requires]
build_requires = builder.build_system_requires # also use get_requires_for_build for sdist/wheel build deps We don't offer a way to get requires wrapped in
Out of these only install requires, build requires and extras require is a standardized thing. The rest is not and we cannot offer it in any form. |
@gaborbernat Thanks for pointing that out. I ran a quick test with your snippet against a fresh clone of https://github.com/pypa/sampleproject import tempfile
from importlib.metadata import PathDistribution
from pathlib import Path
from packaging.requirements import Requirement
from build import ProjectBuilder
builder = ProjectBuilder('.')
with tempfile.TemporaryDirectory() as tmpdir:
distribution = PathDistribution(Path(builder.metadata_path(tmpdir)))
requires = [Requirement(i) for i in distribution.requires]
for x in requires:
print(x) It will print out the package dependencies (hooray!), but it also prints out extra build debugging information which I can't see how to disable. How can we disable this extra output to stdout/stderr? It's not really feasible to use that code snippet while there is no control over the stdout/stderr output.
It appears to be |
Set the |
@FFY00 Thanks for that. This means we also have to import from |
Yes, though I would probably import it from |
Thanks. Now that we have a solution to this, is it possible to get it added as a utility function to pypa/build? Maybe something like |
I'm +0.1 on it, so guess other maintainers will have to chime in. |
We have discussed having a helper (plumbing) module previously, and I am fine with it. Such high-level functions, like the one you propose, should be separated from the core API and must be in a separate module. I want to be able to easily split that into a separate package if the maintaining cost gets too high, or we need more dependencies. I am thinking of making a release soon, we can work on this after that. |
It is now available in 0.7.0. https://pypa-build.readthedocs.io/en/latest/api.html#build.util.project_wheel_metadata |
I am closing this, as getting the metadata without building is not possible in several situations, and we now provide the closest helper to that that we can. |
There are cases in which it is needed to get the requirements of a package without having to build it, see for example github's dependabot #2281. There was a discussion in pypa/pyproject-hooks#100 about this and it seems that a good place to provide this functionality is here in build. I open this and close the discussion in pep517.
The text was updated successfully, but these errors were encountered: