pgossa
pgossa

Reputation: 285

Get app version from pyproject.toml inside python code

I am not very familiar with python, I only done automation with so I am a new with packages and everything.
I am creating an API with Flask, Gunicorn and Poetry.
I noticed that there is a version number inside the pyproject.toml and I would like to create a route /version which returns the version of my app.
My app structure look like this atm:

├── README.md
├── __init__.py
├── poetry.lock
├── pyproject.toml
├── tests
│   └── __init__.py
└── wsgi.py

Where wsgi.py is my main file which run the app.

I saw peoples using importlib but I didn't find how to make it work as it is used with:
__version__ = importlib.metadata.version("__package__")
But I have no clue what this package mean.

Upvotes: 13

Views: 13715

Answers (6)

sinoroc
sinoroc

Reputation: 22438

You should not use __package__, which is the name of the "import package" (or maybe import module, depending on where this line of code is located), because this is not what is expected here.

importlib.metadata.version() expects the name of the "distribution package" (the thing that you pip-install), which is the one you write in the [project] table of pyproject.toml as name = "my-distribution-package-name".

So if the application or library whose version string you want to get is named my-foo-lib, then you only need to call the following

import importlib.metadata

version_string_of_foo = importlib.metadata.version('my-foo-lib')

Upvotes: 26

Giorgos Myrianthous
Giorgos Myrianthous

Reputation: 39930

If you are using Poetry to manage dependencies, you will have to specify package-mode = true under [tool.poetry] section in order for importlib.metadata to be able to report the correct package version, as listed in the pyproject.toml file.

Here's how your pyproject.toml file should look like:

[tool.poetry]
name = "mypackage"
version = "0.44.0"
description = "My package"
package-mode = true

You can then use importlib.metadata to infer the version programmatically:

import importlib.metadata

version_string_of_foo = importlib.metadata.version('mypackage')
print(version_string_of_foo)
# '0.44.0'

Upvotes: 1

Maxim Suslov
Maxim Suslov

Reputation: 5485

In the project.toml you can specify version in different ways:

  • Poetry expects version in the [tool.poetry]:
[tool.poetry]
name = "my-package"
version = "0.1.0"
[project]
name = "my-package"
version = "2020.0.0"

The next point is that you may want to see the version of installed packages (e.g. via pip or poetry) or your application. The next:

import importlib.metadata

version = importlib.metadata.version("my-package")
print(version)

This code works fine with installed packages. To make working it with your project, you should install it using pip install -e . or something similar.

If you want to check version of your project without installing, then you can use the following snippet:

from pathlib import Path
import toml

version = "unknown"
# adopt path to your pyproject.toml
pyproject_toml_file = Path(__file__).parent / "pyproject.toml"
if pyproject_toml_file.exists() and pyproject_toml_file.is_file():
    data = toml.load(pyproject_toml_file)
    # check project.version
    if "project" in data and "version" in data["project"]:
        version = data["project"]["version"]
    # check tool.poetry.version
    elif "tool" in data and "poetry" in data["tool"] and "version" in data["tool"]["poetry"]:
        version = data["tool"]["poetry"]["version"]
print(version)

To make it working you should install toml package in advance.

Upvotes: 10

Joe B
Joe B

Reputation: 760

I am doing this:

from poetry.core.factory import Factory

def display_version():

    __thisScript__ = os.path.realpath(__file__)
    __thisFolder__ = os.path.dirname(__thisScript__)
    factory = Factory()
    this_project = factory.create_poetry(__thisFolder__)
    print(f"{this_project.package.name} version {this_project.package.version}")
    print(f"{this_project.package.description}")

    sys.exit(0)
# end def

I also added the included statemetn the pyproject.toml file into my pyproject.toml file as mentioned by Haoqi Chen

[tool.poetry]
name = "myApp"
version = "0.1.5"
description = "A faster alternative to Windows `rmdir /s /q` for large directories."
authors = ["Joe B"]
readme = "README.md"
include = [{path = "./pyproject.toml"}]

I used a relative path to pyproject.toml as I always use poetry build from the same folder as pyproject.toml.

Upvotes: -2

Haoqi Chen
Haoqi Chen

Reputation: 1

I had the same question.

One of the solution I could come up is to ship the pyproject.toml file together with the project, as a data file. This can be done by putting pyproject.toml inside your_package/data, and put include = [{path = "phuego/data/pyproject.toml"}]under [tool.poetry] in pyproject.toml. Then, you can use toml package to access it.

But I'm not convinced by this solution. Perhaps there is a better idea out there.

Upvotes: -2

Jurakin
Jurakin

Reputation: 1094

You can extract version from pyproject.toml using toml package to read toml file and then display it in a webpage.

Upvotes: 0

Related Questions