Get app version from pyproject.toml inside python code
Asked Answered
T

5

6

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.

Tattoo answered 12/1, 2023 at 17:23 Comment(4)
Does this answer your question? What's the purpose of the "__package__" attribute in Python?Hardboard
Beyond your question about the meaning of __package__ there are suspicious things in your question. -- You should not have a __init__.py right next to pyproject.toml, typically you would want to put all Python code in a sub-directory named after what you want your top-level import package to be.Colombes
@Colombes Should I put my main file a the top or should I create a subfolder like "src" or something and put my main file inside?Tattoo
@Tattoo I recommend the so-called src-layout, but you do not have to. It's best if you let poetry create the project template with poetry new --src name-of-your-new-project.Colombes
C
20

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), and this is not what importlib.metadata.version() expects. This function expects the name of the distribution package (the thing that you pip-install), which is the one you write in pyproject.toml as name = "???".

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

import importlib.metadata

version_string_of_foo = importlib.metadata.version('Foo')
Colombes answered 12/1, 2023 at 18:34 Comment(1)
Ok thank you I just totally missed the purpose.Tattoo
U
2

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.

Undamped answered 29/2 at 15:24 Comment(0)
L
0

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

Linc answered 12/1, 2023 at 17:29 Comment(2)
This will not work, because the pyproject.toml file will not be available once the project is pip-installed (you can also see that the file is not in the wheels).Colombes
@will.mendil stackoverflow.com/a/75100875Colombes
B
-2

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.

Biller answered 29/6, 2023 at 14:44 Comment(2)
This does not really answer the question. If you have a different question, you can ask it by clicking Ask Question. To get notified when this question gets new answers, you can follow this question. Once you have enough reputation, you can also add a bounty to draw more attention to this question. - From ReviewBunkum
Bad idea. Just use importlib.metadata.version('TheNameOfTheAppOrLibrary').Colombes
Q
-2

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.

Quietus answered 10/8, 2023 at 18:26 Comment(1)
Why so complex when there are solutions available in Python's standard library already that are way more robust? Just use importlib.metadata.version('myApp').Colombes

© 2022 - 2024 — McMap. All rights reserved.