On Wed, Apr 14, 2021 at 12:10 PM Barry Warsaw <barry@python.org> wrote:

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-versions

Barry,

You wrote the original PEP, so of course you can withdraw it (or reject it), but...

Are you sure? See this discussion, I don't think it's as simple as all that.

Honestly, I'm still kind of confused about a "distribution" vs a package or module, but in general, it seems to me that the packaging community has done a great job of building a system that can accommodate a lot of complexity, but as they say:

The easy things should be easy, and the hard things should be possible.

And the full process of using packaging and distributions, and a Version object and all that is not so easy anymore --at least compared to putting:

__version__ = "1.2.3" 

in a package __init__.py. 

Anyway, a couple points:

1) it seems self-evident that it would be easier for the whole community if "how to declare", and "how to find" the version of a package was standardized: "there's only one way to do it"

1b) It seems like a really good idea that the (or one of the) official recommended way to do it is supported in the standard library itself, and using a string is pretty easy to support :-) -- do we really want people to have to install a third party package to set or get the version of a simple module?

2) __version__ strings are already pretty darn common -- maybe more common than proper distribution metadata? -- are we saying that everyone should stop doing that?

3) I don't know that having __version__ strings is incompatible with packging.version.Version or importlib.metadata.version

4) Yes, there are real advantages to the more complex system for programmatically working with versions. But there are real advantages to something simple for human readability / interactive use -- and, frankly, simple scripting. See David Mertz's recent post -- I went through a similar process in iPython.

Consider this analogy: if I want to know what version of git I have installed, I can run:

$ git --version

And that's a convention adhered to by many *nix command line tools. Would we all really be happier if we had to go use an rpm or deb or homebrew, or ?? command to see what package i have installed? I think this is similar -- while a good distribution management system is a good thing, it's also good if I can tell something about the version of a package/module from the package itself.

With regard to having both __version__ and importlib.metadata.version, see beautiful soup for example:

In [10]: import beautifulsoup4
...
ModuleNotFoundError: No module named 'beautifulsoup4'

oops, that's not what the importable module is called. So:

In [11]: import bs4

That worked -- now, what version is it?

In [12]: importlib.metadata.version('bs4')
---------------------------------------------------------------------------
PackageNotFoundError                      Traceback (most recent call last)
...
PackageNotFoundError: bs4

[*]

That didn't work -- I guess I need to use the distribution name:

In [13]: importlib.metadata.version('beautifulsoup4')
Out[13]: '4.9.3'

OK, that worked.

But I imported "bs4", so what if I do this?

In [14]: bs4.__version__
Out[14]: '4.9.3'

Ah yes, that worked too.

So I guess what I'm suggesting is that we officially recommend that folks do what the BeautifulSoup folks, and many others, are already doing. In many (most) cases, the distribution name and the importable package name are the same, but this does accommodate both.

[*] One other annoyance to importlib.metadata.version is that in addition to having to import importlib to use it, I also need to use importlib.metadata.PackageNotFoundError if I want to trap the exception.

BTW: I'm not making that last point up -- I recently updated some in-house code (that someone else had written) in a web app that presented the version of various packages core to the system. We had just refactor and one of these packages what now optional, but the whole system was crashing on that darn PackageNotFoundError. I ended up jsut commenting out that package, rather than dealing with how to catch the exception and deal with it properly. I would have so much rathered a simple:

try:
    import the_package
    the_pacakge_version = the_package.__version__
except
    the_package_version = None

Granted, it's not that hard to "do it right", but I still like things simple :-)
 
Anyway, as the original PEP author is no longer supportive, this is dead in the water unless another core dev is interested in sponsoring this (or a new) PEP. If not, I can stop wasting my and everyone else's time.

-Chris

--
Christopher Barker, PhD (Chris)

Python Language Consulting
  - Teaching
  - Scientific Software Development
  - Desktop GUI and Web Development
  - wxPython, numpy, scipy, Cython