hey team. I am migrating a legacy project that rel...
# general
f
hey team. I am migrating a legacy project that relied on using
pkg_resources
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
get_distribution("my_project").version
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 🙂
e
(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
.
f
Were you using the latter style and then removed that when moving the project to Pants / Pex?
Right, the project was using
setup.py
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
setup.py
. I think I’ll go with defining the version in the
version.py
and then reading it at runtime if needed and importing it into a
setup.py
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
pkg_resources.get_distribution
to get? I.e. the wheel comes with metadata:
Copy code
>>> from pkg_resources import get_distribution
>>> get_distribution("click").version
'7.0'
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 🙂
e
It makes sense. Pex chooses to make the code authoritative; so the version is stored in the
pex.version
module as the
__version__
global. The distribution is built using flit instead of setuptools. Flit expects the distribution's main package (
pex
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
pex.version.__version__
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.