From accd0b6bf7d9d6a059d202059ada06aa37b4b061 Mon Sep 17 00:00:00 2001 From: Mateusz Bysiek Date: Tue, 20 May 2025 19:08:53 +0900 Subject: [PATCH 1/5] docs: reword and expand usage information --- README.rst | 79 +++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 61 insertions(+), 18 deletions(-) diff --git a/README.rst b/README.rst index 3b720a3..82d13b4 100644 --- a/README.rst +++ b/README.rst @@ -41,34 +41,43 @@ for easier development, testing and pre-release deployment?! Search no more! -As long as you mark your releases using git tags, instead of hardcoding: +As long as you use git and you mark your releases using git tags, version-query will do the rest. -.. code:: python +It's 21st century, stop hardcoding version numbers! - __version__ = '1.5.0.dev2' +.. contents:: + :backlinks: none -You can do: -.. code:: python +Overview +======== - from version_query import predict_version_str +There are two main ways of using version-query - at runtime or at build time. - __version__ = predict_version_str() +Using at runtime +---------------- -It's 21st century, stop hardcoding version numbers! +When using this way, version-query is needed as a runtime dependency of your package. -This will set the version to release version when you really release a new version, -and it will automatically generate a suitable development version at development/pre-release phase. +If, for example, you have a constant storing the version of your package in some Python module: +.. code:: python -.. contents:: - :backlinks: none + VERSION = '1.5.0.dev2' +You can do the following instead of hardcoding it: -Overview -======== +.. code:: python + + from version_query import predict_version_str -At development time, the current version number is automatically generated based on: + VERSION = predict_version_str() + +This will set the version to release version when you really release a new version, +and it will automatically generate a suitable development version at development/pre-release phase. + +When your package is imported while running from inside the repository, such as during development, +the current version number is automatically generated based on: * tags * current commit SHA @@ -81,9 +90,43 @@ or at runtime) then the script relies on metadata generated at packaging time. That's why, regardless if package is installed from PyPI (from source or wheel distribution) or cloned from GitHub, the version query will work. -Additionally, version numbers in version-query are mutable objects and they can be conveniently -incremented, compared with each other, as well as converted to/from other popular -versioning formats. +Using at build time +------------------- + +This is the way to go if you want to use version-query only as a dependency when building +the package, in such case it's not necessary to to add it to runtime dependencies. + +There are many build systems avialable for Python, and version-query may not be compatible +with all of them. Below are some examples. + +setuptools with ``setup.py`` script +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This is a legacy way of building Python packages, but it is still widely used. + +In such setup, you just need to add the following to your ``setup.py`` file: + +.. code:: python + + from version_query import predict_version_str + + setup( + ..., + version=predict_version_str() + ) + +If you are already using version-query at runtime in your package to set a constant +(for example ``my_package.VERSION``, please see "Using at runtime" section above for details), +you may instead reuse the same constant in your ``setup.py`` file: + +.. code:: python + + from my_package import VERSION + + setup( + ..., + version=VERSION + ) Versioning scheme ================= From 97aec8f52d9da39571c581901728e30ac717e329 Mon Sep 17 00:00:00 2001 From: Mateusz Bysiek Date: Tue, 20 May 2025 19:16:37 +0900 Subject: [PATCH 2/5] chore: small readme fixes --- README.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.rst b/README.rst index 82d13b4..b1457ad 100644 --- a/README.rst +++ b/README.rst @@ -133,7 +133,7 @@ Versioning scheme Version scheme used by version-query is a relaxed mixture of: -* `Semantic Versioning 2.0.0 `_ and +* `Semantic Versioning 2.0.0 `__ and * `PEP 440 -- Version Identification and Dependency Specification `_. @@ -318,7 +318,7 @@ The base specification of the comparison scheme is: * `PEP 508 -- Dependency specification for Python Software Packages `_ as well as -* `Semantic Versioning 2.0.0 `_. +* `Semantic Versioning 2.0.0 `__. With the notable difference to both that all version components are taken into account when establishing version precedence. @@ -416,7 +416,7 @@ The Version objects are mutable, hashable and comparable. version = version_query.query_caller(stack_level=1) version = version_query.predict_caller(2) -Version object can be obtained for any supported path, as well as for any python code +Version object can be obtained for any supported path, as well as for any Python code currently being executed -- as long as it is located in a supported location. From 3c35ec42d9cdcc86d035cddbe6082d4625e459c5 Mon Sep 17 00:00:00 2001 From: Mateusz Bysiek Date: Tue, 20 May 2025 19:24:44 +0900 Subject: [PATCH 3/5] feat: support pyproject.toml dynamic version from attribute --- test/test_local_git_version.py | 21 +++++++++++++++++++++ version_query/local_git_version.py | 22 ++++++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 test/test_local_git_version.py create mode 100644 version_query/local_git_version.py diff --git a/test/test_local_git_version.py b/test/test_local_git_version.py new file mode 100644 index 0000000..384578d --- /dev/null +++ b/test/test_local_git_version.py @@ -0,0 +1,21 @@ +"""Tests of local_git_version module.""" + +import logging + +import unittest + + +from version_query.local_git_version import QUERIED, PREDICTED + +_LOG = logging.getLogger(__name__) + + +class Tests(unittest.TestCase): + + def test_queried(self): + _LOG.debug('QUERIED: %s', QUERIED) + self.assertIsInstance(QUERIED, str) + + def test_predicted(self): + _LOG.debug('PREDICTED: %s', PREDICTED) + self.assertIsInstance(PREDICTED, str) diff --git a/version_query/local_git_version.py b/version_query/local_git_version.py new file mode 100644 index 0000000..8908d25 --- /dev/null +++ b/version_query/local_git_version.py @@ -0,0 +1,22 @@ +"""Use this module when reading the version from an attribute is needed without Python code. + +For example, when using setuptools in pyproject.toml, +one can set the version dynamically as follows: + +[project] +dynamic = ["version"] +... + +[tool.setuptools.dynamic] +version = {attr = "version_query.local_git_version.PREDICTED"} +""" + +import os +import pathlib + +from .git_query import query_git_repo, predict_git_repo + +_CURRENT_FOLDER: pathlib.Path = pathlib.Path() +_PROJECT_FOLDER: pathlib.Path = pathlib.Path(os.environ.get('PROJECT_FOLDER', _CURRENT_FOLDER)) +QUERIED: str = query_git_repo(_PROJECT_FOLDER).to_str() +PREDICTED: str = predict_git_repo(_PROJECT_FOLDER).to_str() From 278d65554b8735e28c0a355e0b8728c337f5b9fd Mon Sep 17 00:00:00 2001 From: Mateusz Bysiek Date: Tue, 20 May 2025 19:47:13 +0900 Subject: [PATCH 4/5] docs: document new feature --- README.rst | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/README.rst b/README.rst index b1457ad..822df67 100644 --- a/README.rst +++ b/README.rst @@ -128,6 +128,39 @@ you may instead reuse the same constant in your ``setup.py`` file: version=VERSION ) +dynamic version attribute in ``pyproject.toml`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +A more modern approach in Python is to use ``pyproject.toml`` for building packages. + +Some build systems that use ``pyproject.toml`` allow setting the version dynamically +by allowing users to point to an attribute of some module in order to get the version. + +One of such packages is setuptools. When using it, one can use the following: + +.. code:: toml + + [project] + dynamic = ["version"] + ... + + [build-system] + requires = ["setuptools >= 70.0"] + build-backend = "setuptools.build_meta" + + [tool.setuptools.dynamic] + version = {attr = "version_query.local_git_version.PREDICTED"} + +Depending on how you build your package, the build system may copy files to a temporary folder +when building. In such case, you need to set ``PROJECT_FOLDER`` environment variable +to the current working directory before running the build command. + +For example, when using ``build`` package: + +.. code:: bash + + PROJECT_FOLDER=$(pwd) python3 -m build + Versioning scheme ================= From 80cc375305aed5f3ea1e855b34a081a23f3a2d16 Mon Sep 17 00:00:00 2001 From: Mateusz Bysiek Date: Tue, 20 May 2025 20:05:02 +0900 Subject: [PATCH 5/5] chore: housekeeping --- README.rst | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/README.rst b/README.rst index 822df67..28ab667 100644 --- a/README.rst +++ b/README.rst @@ -96,7 +96,7 @@ Using at build time This is the way to go if you want to use version-query only as a dependency when building the package, in such case it's not necessary to to add it to runtime dependencies. -There are many build systems avialable for Python, and version-query may not be compatible +There are many build systems available for Python, and version-query may not be compatible with all of them. Below are some examples. setuptools with ``setup.py`` script @@ -108,9 +108,11 @@ In such setup, you just need to add the following to your ``setup.py`` file: .. code:: python + import setuptools from version_query import predict_version_str - setup( + + setuptools.setup( ..., version=predict_version_str() ) @@ -121,9 +123,12 @@ you may instead reuse the same constant in your ``setup.py`` file: .. code:: python + import setuptools + from my_package import VERSION - setup( + + setuptools.setup( ..., version=VERSION ) @@ -133,10 +138,10 @@ dynamic version attribute in ``pyproject.toml`` A more modern approach in Python is to use ``pyproject.toml`` for building packages. -Some build systems that use ``pyproject.toml`` allow setting the version dynamically +Some build systems that use ``pyproject.toml`` support setting the version dynamically by allowing users to point to an attribute of some module in order to get the version. -One of such packages is setuptools. When using it, one can use the following: +One of such packages is setuptools. When using it, one can do the following: .. code:: toml