Skip to main content

Extract your project's __version__ variable

Project description

Project Status: Inactive – The project has reached a stable, usable state but is no longer being actively developed; support/maintenance will be provided as time allows. CI Status https://codecov.io/gh/jwodder/read_version/branch/master/graph/badge.svg https://img.shields.io/pypi/pyversions/read_version.svg MIT License

GitHub | PyPI | Issues | Changelog

Note: As of the release of setuptools 46.4.0, setuptools natively supports using the attr: directive in setup.cfg to set the project version based on static analysis of the project source. This makes the bulk of read_version’s use cases obsolete, and so it will not receive further development.

When creating a setup.py for a new project, do you find yourself always writing the same block of code for parsing __version__ from your project’s source? Something like this?

with open(join(dirname(__file__), 'package_name', '__init__.py')) as fp:
    for line in fp:
        m = re.search(r'^\s*__version__\s*=\s*([\'"])([^\'"]+)\1\s*$', line)
        if m:
            version = m.group(2)
            break
    else:
        raise RuntimeError('Unable to find own __version__ string')

setup(
    version = version,
    ...
)

Someone needs to put all that into a reusable package, am I right? Well, someone did, and this is that package. It exports a single function that does the above, perfect for importing into your setup.py, and (New in v0.2.0!) this package even lets you map Python variables to supported metadata fields via your pyproject.toml.

Installation

read_version requires Python 3.6 or higher. Just use pip for Python 3 (You have pip, right?) to install read_version and its dependencies:

python3 -m pip install read_version

read_version also has a toml extra that provides support for reading configuration from pyproject.toml. Install it with:

python3 -m pip install "read_version[toml]"

Usage

The Functional Way

  1. Install read_version in your development environment.

  2. Add a pyproject.toml file to your project declaring read_version as a build dependency. (This is needed so that other people can build your package from source; see PEP 518 for more information.) The contents of the file should look like:

    [build-system]
    requires = [
        "read_version ~= 0.3.0",
        "setuptools",
        "wheel"
    ]
    build-backend = "setuptools.build_meta"
  3. In your setup.py, get rid of your boilerplate __version__-finding code and replace it with:

    from read_version import read_version
    
    setup(
        version = read_version('packagename', '__init__.py'),
        ...
    )
  4. Build your project and double-check that the version is set to the correct value.

  5. Done!

The Declarative Way

New in version 0.2.0!

  1. Install read_version in your development environment with the toml extra:

    pip install 'read_version[toml]'

    You will also need version 42.0.0 or later of setuptools:

    pip install -U 'setuptools>=42'
  2. Add a pyproject.toml file to your project declaring read_version[toml] as a build dependency and also requiring version 42.0.0 or later of setuptools. The relevant section of the file should look like:

    [build-system]
    requires = [
        "read_version[toml] ~= 0.3.0",
        "setuptools >= 42.0.0",
        "wheel"
    ]
    build-backend = "setuptools.build_meta"
  3. Get rid of your boilerplate __version__-finding code in your setup.py. Instead, add a tool.read_version table to your pyproject.toml file, and for each metadata field that you want to be read from a variable in a Python source file, add an entry to this table of the form FIELD = "dotted.file.path:varname", where:

    • FIELD is replaced by the lowercase name of the field. Supported fields are:

      • author

      • author_email

      • description (Note that this is the short description or summary, not the long description!)

      • keywords (It is recommended to use a list of strings as the value or else setuptools might mangle it)

      • license

      • maintainer

      • maintainer_email

      • url

      • version

      Entries with unsupported or unknown field names are ignored.

    • dotted.file.path is replaced by the path (relative to the project root) to the file containing the variable, with path components separated by dots and the .py at the end of the last path component dropped

    • varname is replaced by the name of the variable to read

    Examples:

    [tool.read_version]
    
    # Set the project's version to the value of __version__ in foobar.py:
    version = "foobar:__version__"
    
    # Set the project's author to the value of author_name in
    # foobar/__init__.py
    author = "foobar.__init__:author_name"
    
    # Set the project's license to the value of LICENSE in
    # src/foobar/about.py:
    license = "src.foobar.about:LICENSE"

    If this syntax doesn’t work for you — say, because one of your path components contains a period or colon in its name, or because the file doesn’t have a .py extension — or if you want to set a default value for when the variable isn’t found, then make tool.read_version.FIELD into a table, like so:

    # Set the project's version to the value of __version__ in
    # foo.bar/__init__.pyq:
    [tool.read_version.version]
    path = ["foo.bar", "__init__.pyq"]
    variable = "__version__"
    
    # Set the project's author_email to the value of EMAIL in foobar.py.
    # If the variable isn't found, use the value "me@example.com" instead
    # of erroring
    [tool.read_version.author_email]
    path = ["foobar.py"]
    variable = "EMAIL"
    default = "me@example.com"

    tool.read_version.FIELD tables may contain the following keys:

    path:

    (Required) The path to the source file containing the variable to read, relative to the project root, as a list of path components

    variable:

    (Required) The name of the Python variable to get the value from

    default:

    (Optional) If the variable cannot be found in the source file, use the given value instead; if the variable cannot be found and default is not set, an error will occur

  4. Build your project and double-check that the metadata has all the relevant fields set to their correct values.

  5. Done!

API

read_version exports a single function, also named read_version, whose signature is:

read_version(*filepath, variable='__version__', default=NOTHING)

read_version() takes one or more file path components pointing to a Python source file to parse. The path components will be joined together with os.path.join(), and then, if the path isn’t absolute, the path to the directory containing the script calling read_version() will be prepended to the path. (No more join(dirname(__file__), ...) boilerplate needed!) read_version() then parses the given Python file and searches through the parse tree for any assignments to a variable named __version__, returning the last value assigned.

The variable keyword argument can be set to the name of a variable other than __version__ to search for assignments to a different variable instead. Setting it to "__doc__" causes the function to return the module docstring.

If no assignments to the variable are found, a ValueError is raised. To instead return a default value when this happens, set the default keyword argument.

Restrictions

read_variable only finds assignments that occur at the top level of the module, outside of any blocks.

Only assignments of literal values are supported; assignments to the searched-for variable involving more complicated expressions will cause an error to be raised.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

read_version-0.3.2.tar.gz (17.4 kB view details)

Uploaded Source

Built Distribution

read_version-0.3.2-py3-none-any.whl (8.6 kB view details)

Uploaded Python 3

File details

Details for the file read_version-0.3.2.tar.gz.

File metadata

  • Download URL: read_version-0.3.2.tar.gz
  • Upload date:
  • Size: 17.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.4.1 importlib_metadata/4.5.0 pkginfo/1.7.0 requests/2.25.1 requests-toolbelt/0.9.1 tqdm/4.61.1 CPython/3.9.6

File hashes

Hashes for read_version-0.3.2.tar.gz
Algorithm Hash digest
SHA256 3f2d30852bce9174b244f7f29aaebf4e79904c6ed51a19716325015ff306ce3f
MD5 0be44e6819eb039c86cf55a413733645
BLAKE2b-256 9c2fe6ed7dd2e34706b7b04f08204f425ea16deb949f4374e5e445fd20a7702f

See more details on using hashes here.

File details

Details for the file read_version-0.3.2-py3-none-any.whl.

File metadata

  • Download URL: read_version-0.3.2-py3-none-any.whl
  • Upload date:
  • Size: 8.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.4.1 importlib_metadata/4.5.0 pkginfo/1.7.0 requests/2.25.1 requests-toolbelt/0.9.1 tqdm/4.61.1 CPython/3.9.6

File hashes

Hashes for read_version-0.3.2-py3-none-any.whl
Algorithm Hash digest
SHA256 e34c9890aa653b129a862120841b0823da57535d5ac4934253d5087e79b00b1d
MD5 a3dc57e56b5bc5c5a6a9f6da26bca861
BLAKE2b-256 65bbc203ddde5f133b4dfe1f5f431168991698438da8f5915ea8cd26655bcceb

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page