hey team. I am migrating a legacy project that rel...
# general
hey team. I am migrating a legacy project that relied on using
to get the version of the package at the runtime (to be put into some logs/reports — to tell what version was used for producing the outputs).
Copy code
from pkg_resources import get_distribution
Now, the package is not installed any longer as a wheel and instead is run as a PEX file (and of course it doesn’t have a “version” any longer). What approach do people take when they need to access the version dynamically when running the code? I see https://github.com/pantsbuild/pants/blob/main/src/python/pants/version.py#L13-L18 but curious what other clever tricks others have came up with 🙂
(and of course it doesn’t have a “version” any longer)
Can you explain that? As far as I know the "of course" doesn't follow at all. Either you have a file in a project that contains the version number - in which case you can read that file via pkg_resources or pkgutil in a PEX or when installed in a venv, or else you use something like https://pypi.org/project/setuptools-scm to get the version directly from git (say), and that gets embedded in your distribution's metadata. Were you using the latter style and then removed that when moving the project to Pants / Pex?
Um, ok - re-read even more. That is basically the only trick there is besides simply providing an API. I.E.:
from myproj import version
Were you using the latter style and then removed that when moving the project to Pants / Pex?
Right, the project was using
with version there and then when it’s installed, the code used
from pkg_resources import get_distribution
to get the version at runtime. As you say, it’s still storing the version somewhere and just reading it. I also remember doing
git tag -a v$(python3 setup.py --version)
at a previous place where the version was imported into the
. I think I’ll go with defining the version in the
and then reading it at runtime if needed and importing it into a
just for convenience if any other tool needs to get the version quickly with
python setup.py --version
instead of reading and parsing or importing the file. Out of curiosity, when PEX is generated and then run, will it have this information about the version embedded for
to get? I.e. the wheel comes with metadata:
Copy code
>>> from pkg_resources import get_distribution
>>> get_distribution("click").version
and if I run a project in REPL with
./pants repl my-project
, I can get the versions of the 3rd party dependencies:
Copy code
In [3]: get_distribution("pyyaml").version
Out[3]: '6.0'
but what about the version of the project source code? Is it possible to embed it somehow? Please let me know if this doesn’t make sense 🙂
It makes sense. Pex chooses to make the code authoritative; so the version is stored in the
module as the
global. The distribution is built using flit instead of setuptools. Flit expects the distribution's main package (
in this case) to have the distribution description and version defined there, so: https://github.com/pantsbuild/pex/blob/7480ed6263d0f5d71ab95ca18f6f0c33a60ef36f/pex/__init__.py#L4-L10 . When you
flit build
it reads the version and description from the package and embeds that in the distribution metadata. In that way Pex has its version both available via the ~"API" of
fundamentally and then also as part of its sdist and wheel distributions. That said - you can do this with setuptools too. Old Pex did it by having setup.py add the local project to the sys.path: https://github.com/pantsbuild/pex/blob/e5317cbc94a49d5129144806ce4117ccd926fb6a/setup.py#L7-L11; then importing the version via ~"API": https://github.com/pantsbuild/pex/blob/e5317cbc94a49d5129144806ce4117ccd926fb6a/setup.py#L28 and finally using that in the setup kwargs: https://github.com/pantsbuild/pex/blob/v1.6.12/setup.py#L33. The end story is the same though; it proably pays to keep the version defined in code or a resource file and have the packaging system read the version via code or by reading the resource file.