Skip to content

getversion

Get the version number of any python module or package, reliably.

Python versions Build Status Tests Status codecov

Documentation PyPI Downloads Downloads per week GitHub stars

Do you need a reliable way to get a version number corresponding to a python object ? getversion was made for this. It combines the best existing strategies to cover the broadest possible set of cases. It is easily extensible so that adding new strategies is extremely easy. Do not hesitate to open an issue or a PR if the current 5 built-in strategies do not work for you!

If you wish to know why "yet another package" is necessary, have a look at the motivation section.

Installing

> pip install getversion

Usage

a- Already imported

from getversion import get_module_version

# Get the version of an imported module
from xml import dom
version, details = get_module_version(dom)
print(version)

yields

3.7.3.final.0

Why was this version found ? You can understand it from the details:

> print(details)
Version '3.7.3.final.0' found for module 'xml.dom' by strategy 'get_builtin_module_version', after the following failed attempts:
 - Attempts for module 'xml.dom':
   - <get_module_version_attr>: module 'xml.dom' has no attribute '__version__'
 - Attempts for module 'xml':
   - <get_module_version_attr>: module 'xml' has no attribute '__version__'
   - <get_version_using_pkgresources>: Invalid version number: None
   - <get_builtin_module_version>: SUCCESS: 3.7.3.final.0

b- Not yet imported

TODO

Motivation

Packages, modules, dists

In python: - a module is a file ending with .py, containing some symbols. - a package is a folder containing a __init__.py file, as well as any number of subpackages and submodules.

See also this explanation.

When you distribute python code, you distribute either a single module, or a single package. The name of this "root" module or package is the first name that appears in an import:

import xml              # root package 'xml'
import xml.dom          # subpackage 'dom' of pkg 'xml'
import xml.dom.minidom  # submodule 'minidom' of pkg 'xml.dom'

See distributing python modules.

Why another package ?

Version numbers in python can be in very different places depending on the case:

  • for modules and packages, on the optional __version__ attribute as recommended by PEP396. It should be considered inherited by subpackages and submodules by default if they do not have the attribute.

  • for distributed modules and packages, on the Version Metadata field as indicated by PEP345, that is located:

  • finally, for built-in modules and packages, the default version should be inherited from the python system version except if overridden

In addition to this, at runtime (when you need that version number), packages and modules can be

  • already imported or not
  • built and pip-installed (in debug mode or not), or simply added to the PYTHON PATH (sys.path)
  • non-built and added to the PYTHON PATH (sys.path)

This variety of settings makes it very difficult for existing solutions to tackle all aspects of this problem. pkg_resources is probably the best way to get it as of today (like this), but does not work for example when a package is an unzipped wheel added to the PYTHON PATH. It also does not support built-in modules.

Main features / benefits

  • Get module and package version easily: a single method will get you what you need, whatever the variety of ways needed to get the information
  • Support for multiple strategies: built-in modules, PEP396/version, setuptools/pkg_resources, PEP427/wheel, setuptools/eggs, git...

See Also

Concerning the strategies:

Discussion on PyPa: here.

Other attempts to reach the same target:

Package versioning best practices

If your project uses git, I would recommend the following:

  • in __init__.py

    try:
        # -- Distribution mode --
        # import from _version.py generated by setuptools_scm during release
        from ._version import version as __version__
    except ImportError:
        # -- Source mode --
        # use setuptools_scm to get the current version from src using git
        from setuptools_scm import get_version as _gv
        from os import path as _path
        __version__ = _gv(_path.join(_path.dirname(__file__), _path.pardir))
    
  • then, EITHER in setup.py:

    setup(
      ...
      use_scm_version={'write_to': '%s/_version.py' % <pkgname>}
    )
    
  • OR when you wish to create releases, after git-tagging your project and before publishing it, do

    from setuptools_scm import get_version
    get_version('.', write_to='<pkg_name>/_version.py')
    

for example in your continuous integration engine: python -c "from setuptools_scm import get_version;get_version('.', write_to='<pkg_name>/_version.py')"

Note: the above was inspired by this post and this issue.

Others

Do you like this library ? You might also like my other python libraries

Want to contribute ?

Details on the github page: https://github.com/smarie/python-getversion