Poetry: How to get version from pyproject.toml from python app?

Created on 30 Jun 2018  路  16Comments  路  Source: python-poetry/poetry

  • [x] I have searched the issues of this repo and believe that this is not a duplicate.
  • [x] I have searched the documentation and believe that my question is not covered.

Question

I have a basic python app, and inside this app there's a --version flag.
I want to show the same version as I have in pyproject.toml, but without duplicating this information.

What should I do here?
Thanks!

Most helpful comment

The pkg_resources module enables package information introspection. Here's how it can be used to get the version of an installed package.

>>> import pkg_resources
>>> my_version = pkg_resources.get_distribution('my-package-name').version

All 16 comments

The pkg_resources module enables package information introspection. Here's how it can be used to get the version of an installed package.

>>> import pkg_resources
>>> my_version = pkg_resources.get_distribution('my-package-name').version

Related: Single-sourcing the package version from Python Packaging User Guide

Using pkg_resources.get_distribution() implies a dependency on setuptools, no? I think one of the goals of Poetry is to eliminate the need for setuptools.

For what it's worth, I see that Poetry itself simply duplicates the version.

I think there currently isn't a "proper" solution for single-sourcing the application version in a project packaged by Poetry.

any update on how to do this best? does following how Poetry does it itself really mean updating the __version__.py file by hand?

I am using @roywes solution with a fallback to
https://github.com/wemake-services/wemake-python-styleguide/blob/master/docs/conf.py#L22-L37

when the package is not installed.

You can now use importlib.metadata and its backport importlib_metadata: https://docs.python.org/3/library/importlib.metadata.html#distribution-versions.

It has a convenient function importlib.metadata.version('my-distribution') that will return a str read from your pyproject.toml configuration.

@Eric-Arellano Just for clarity, importlib.metadata isn't reading directly from the pyproject.toml, is it?

The docs seem to say that a package built by poetry and installed will have the metadata version set _from_ the pyproject.toml field

@insysion The metadata is built from the pyproject.toml (into these locations in the sdist: setup.py, pyproject.toml, PKG-INFO), but the importlib.metadata probably gets it from the version set in the poetry-built setup.py.

It seems both pkg_resources.get_distribution('my-package-name').version and importlib.metadata.version('my-package-name') needs the package to be installed which seems odd when you are building the doc for that particular package (from local sources). Is there a way to instead simply get the version that is currently built?

@cglacet You could directly parse the TOML in pyproject.toml.
What is the context exactly? Why can't you install or at least build the project?

@sinoroc Yes I could, but isn't including a package as its own dependency weird?

isn't including a package as its own dependency weird?

@cglacet I am not following.

@sinoroc That's probably not clear because it's not clear in my head haha. If I need to install a package to get its version, then, to get the current version of the package I'm currently building it needs to install itself (so it can read its own version number). In my case, I want to include the version number in the package documentation (sphinx configuration).

And I also want that particular piece of code to run even while in development (because I will build the documentation locally a lot before its built by my CI pipeline)

Like you said, I could very well parse the pyproject.toml file, but I'm surprised my use case doesn't already have a solution. I'm not trying to do anything fancy 馃槃

I'm surprised my use case doesn't already have a solution

I know that it is a question that keeps coming up again and again, and there is still no one true answer. It all depends on what the context and conditions are. There are multiple solutions, all with their pros and cons.


Since you mention building sphinx documentation I will tell here how it is solved in one of my projects...

The conf.py for sphinx contains something like:

import importlib.metadata

_DISTRIBUTION_METADATA = importlib.metadata.metadata('MyProjectName')

author = _DISTRIBUTION_METADATA['Author']
project = _DISTRIBUTION_METADATA['Name']
version = _DISTRIBUTION_METADATA['Version']

and the readthedocs.yml file contains something like:

version: 2
python:
  install:
    - method: 'pip'
      path: '.'

So, yes it means that the project always has to be installed beforehand (at least in _editable_ (aka _develop_) mode). It is a bit of a shame, I reckon, but it works well, so I leave it like that for now.

Although I believe it would be relatively easy, to extract the version string (and other metadata) from a _build_ artefact of the project, instead of from a complete installation.


In the case of poetry projects, since the source of truth for the version string is in pyproject.toml file:
Instead, in _Sphinx_'s conf.py you could import a _toml_ parser and extract the metadata (version string, etc.) out of pyproject.toml. It would avoid building and installing the project itself.


If I need to install a package to get its version, then, to get the current version of the package I'm currently building it needs to install itself (so it can read its own version number)

This bit, I do not understand what you mean. Where is the issue? Usually libraries or applications do not really need to know their own version string. And if they do have this need, then I would definitely think that it is at run-time, meaning that they are already installed. So using version = importlib.metadata.version('MyProjectName') should be straightforward, right?

Was this page helpful?
0 / 5 - 0 ratings