On Mon, Apr 26, 2021 at 3:25 PM Stestagg
On Mon, Apr 26, 2021 at 10:31 PM Brett Cannon
wrote: On Mon, Apr 26, 2021 at 9:37 AM Baptiste Carvello < devel2021@baptiste-carvello.net> wrote:
Hi,
sorry for being late to the party, but I may not be the only one wondering…
Le 14/04/2021 à 20:56, Barry Warsaw a écrit :
I’d forgotten that this PEP was in Deferred state. I think it should
be rejected and I plan on making that change. importlib.metadata is a much better approach to programmatically determining package versions.
https://docs.python.org/3/library/importlib.metadata.html#distribution-versi...
This is indeed the correct approach, thanks for letting me learn this.
However, I unsuccessfully searched for the canonical way to look up the distribution name based on either a module name or an imported module object. Is there one?
If you mean how to tie a module back to its name on PyPI, you should be able to look up the "Name" in the project's metadata: https://docs.python.org/3/library/importlib.metadata.html#distribution-metad... .
The missing bit here, for me, is how do you map a module back to it's project (distribution)?
For example:
```
import bs4 bs4.__version__ '4.9.1' importlib.metadata.metadata('bs4') PackageNotFoundError: bs4
This is because the distribution calls itself 'beautifulsoup4' instead.
Unfortunately I thought importlib.metadata would have used the module name instead of the metadata details, but in hindsight am guessing that the .dist-info is what it's using to do the lookup and that's based on the package name instead of the project name. This is a long-standing issue with projects that use project names which differ from their module name, but there's no good way without checking what files a project installed (which is what you're doing below). -Brett
The same goes for another package: `umap`, for which the distribution is called `umap-learn`
This is the best I could come up with from reading the docs:
import bs4 #<- This is the module we want the version of
import importlib import sys from itertools import chain from pathlib import Path
loaders = sys.meta_path
target_path = Path(bs4.__file__)
distros = list(chain(*(finder.find_distributions() for finder in loaders if hasattr(finder, 'find_distributions')))) distros_files = chain(*(f for f in (d.files for d in distros))) distro_files = [(d, d.locate_file(f)) for d in distros if d.files for f in d.files] matching = [d for d, f in distro_files if f == target_path]
for match in matching: print("Found Version:", match.version)
Steve