Versio


NameVersio JSON
Version 0.5.0 PyPI version JSON
download
home_pagehttps://github.com/royw/Versio
SummaryVersion manipulation library.
upload_time2022-01-11 22:43:05
maintainer
docs_urlhttps://pythonhosted.org/Versio/
authorRoy Wright
requires_python
licenselicense.txt
keywords version pep 440
VCS
bugtrack_url
requirements None coverage flake8 pytest-cov pytest radon
Travis-CI No Travis.
coveralls test coverage No coveralls.
            Versio
======

Latin

    Noun
    1. a turning, change, version


Versio is a generic version class that supports comparison and version bumping (incrementing by part, for example
you may bump the minor part of '1.2.3' yielding '1.3.0').

Four version schemes are included:

    * **Simple3VersionScheme** which supports 3 numerical part versions (A.B.C where A, B, and C are integers)
    * **Simple4VersionScheme** which supports 4 numerical part versions (A.B.C.D where A, B, C, and D are integers)
    * **Pep440VersionScheme** which supports PEP 440 (http://www.python.org/dev/peps/pep-0440/) versions
      (N[.N]+[{a|b|c|rc}N][.postN][.devN][+local])
    * **PerlVersionScheme** which supports 2 numerical part versions where the second part is at least two digits
      (A.BB where A and B are integers and B is zero padded on the left.  For example:  1.02, 1.34, 1.567)

If you don't specify which version scheme the version instance uses, then it will use the first scheme from the
**SupportedVersionSchemes** list that successfully parses the version string

By default, **Pep440VersionScheme** is the supported scheme.  To change to a different list of schemes, use the
**Version.set_supported_version_schemes(schemes)**.  For example::

    from versio.version_scheme import Simple3VersionScheme, PerlVersionScheme
    Version.set_supported_version_schemes([Simple3VersionScheme, PerlVersionScheme])

In addition, you may define your own version scheme by creating a new VersionScheme instance.

The VersionScheme class defines the version scheme.

A version scheme consists of:

    * a name,
    * a regular expression used to parse the version string,
    * the regular expression flags to use (mainly to allow verbose regexes),
    * a format string used to reassemble the parsed version into a string,
    * an optional list of field types (if not specified, assumes all fields are strings),
    * a list of field names used for accessing the components of the version.
    * an optional subfield dictionary with the key being a field name and the value being a list of sub field names.
      For example, in the **Pep440VersionScheme**, the "Release" field may contain multiple parts, so we use
      subfield names for the parts.  Say we have a version of "1.2.3rc1", the "1.2.3" is the release field, then
      "1" is the "major" subfield, "2" is the "minor" subfield, and "3" is the "tiny" subfield.
    * a "clear" value used to set the field values to the right of the field being bumped,
    * a sequence dictionary where the keys are the field names and the values are a list of allowed values.
      The list must be in bump order.  Bumping the last value in the list has no effect.

Note, you need to manually maintain consistency between the regular expression,
the format string, the optional field types, and the fields list.  For example,
if your version scheme has N parts, then the regular expression should match
into N groups, the format string should expect N arguments to the str.format()
method, and there must be N unique names in the fields list.

Installation
============

From pypi::

    pip install Versio


Usage
=====

First let's just play with the comparing and bumping versions::

    >>> from versio.version import Version
    >>> from versio.version_scheme import Pep440VersionScheme
    >>> v1 = Version('1.2.3rc4.post5.dev6', scheme=Pep440VersionScheme)
    >>> v2 = Version('1.2.3rc4.post5.dev7', scheme=Pep440VersionScheme)
    >>> v1 == v2
    False
    >>> v1 < v2
    True
    >>> v1.bump('dev')
    True
    >>> str(v1)
    '1.2.3rc4.post5.dev7'
    >>> v1 == v2
    True
    >>> v1.bump('pre')
    True

Now let's look in the PEP 440 scheme::

    >>> Pep440VersionScheme.fields
    ['release', 'pre', 'post', 'dev', 'local']
    >>> Pep440VersionScheme.format_str
    '{0}{1}{2}{3}{4}'

The fields are used by the **bump(field)** method in the above example.  We skipped bumping the release above so let's
do it here::

    >>> v1 = Version('1.2.3rc4.post5.dev6', scheme=Pep440VersionScheme)
    >>> str(v1)
    '1.2.3rc4.post5.dev6'
    >>> v1.bump('release')
    True
    >>> str(v1)
    '1.2.4'

For PEP 440, the release part is defined as "N[.N]+".  We can bump specific parts of the release by using an
index like::

    >>> v1.bump('release', 2)
    True
    >>> str(v1)
    '1.2.5'
    >>> v1.bump('release', 1)
    True
    >>> str(v1)
    '1.3.0'
    >>> v1.bump('release', 0)
    True
    >>> str(v1)
    '2.0.0'

To use a name directly, we use the concept of subfields which are mapped to a field/index pair::

    >>> Pep440VersionScheme.subfields
    {'tiny2': ['Release', 3], 'major': ['Release', 0], 'tiny': ['Release', 2], 'minor': ['Release', 1]}

    >>> v1 = Version('1.2.3rc4.post5.dev6', scheme=Pep440VersionScheme)
    >>> str(v1)
    '1.2.3rc4.post5.dev6'
    >>> v1.bump('tiny')
    True
    >>> str(v1)
    '1.2.4'
    >>> v1.bump('minor')
    True
    >>> str(v1)
    '1.3.0'
    >>> v1.bump('major')
    True
    >>> str(v1)
    '2.0.0'

Now that you've seen the version scheme in action, let's take a look at how it is defined::

    Pep440VersionScheme = VersionScheme(name="pep440",
                                        parse_regex=r"""
                                        ^
                                        (\d[\.\d]*(?<= \d))
                                        ((?:[abc]|rc)\d+)?
                                        (?:(\.post\d+))?
                                        (?:(\.dev\d+))?
                                        (?:(\+(?![.])[a-zA-Z0-9\.]*[a-zA-Z0-9]))?
                                        $
                                        """,
                                        compare_order=[0, 1, 2, 3, 4],
                                        compare_fill=['~', '~', '', '~', ''],
                                        parse_flags=re.VERBOSE,
                                        clear_value=None,
                                        format_str='{0}{1}{2}{3}{4}',
                                        fields=['Release', 'Pre', 'Post', 'Dev', 'Local'],
                                        subfields={'Release': ['Major', 'Minor', 'Tiny', 'Tiny2']},
                                        sequences={'Pre': ['a', 'b', 'c', 'rc'],
                                                   'Post': ['.post'],
                                                   'Dev': ['.dev'],
                                                   'Local': ['+']},
                                        description=dedent("""\
                                            PEP 440
                                            Public version identifiers MUST comply with the following scheme:

                                            N[.N]+[{a|b|c|rc}N][.postN][.devN][+local]

                                            Public version identifiers MUST NOT include leading or trailing whitespace.

                                            Public version identifiers MUST be unique within a given distribution.

                                            Public version identifiers are separated into up to five segments:

                                                Release segment: N[.N]+
                                                Pre-release segment: {a|b|c|rc}N
                                                Post-release segment: .postN
                                                Development release segment: .devN
                                                Local release segment: +local

                                            The local version labels MUST be limited to the following set of permitted
                                            characters:

                                                ASCII letters ( [a-zA-Z] )
                                                ASCII digits ( [0-9] )
                                                periods ( . )

                                            Local version labels MUST start and end with an ASCII letter or digit.
                                        """))

The **parse_regex** and **parse_flags** do what you think by parsing a string into a list containing regex groups,
except the group list is zero indexed to the first matching group.

The **format_str** and **format_types** control how the version is converted to a string in **__str__()**.  Basically
**format_str.format(*args)** is called where the args is a list built by casting each of the version's groups using
the corresponding type from the  **format_types** list.  If you don't specify a **format_types**, then each group
is cast as a str.

The **clear_value** typically should be '0' for numeric versions and None for non-numeric.  Basically it specifies
what to put in the groups to the right of the group being bumped.

The **sequences** dictionary maps text to prepend to a group when formatting.  The dictionary keys must be in the
**fields** list.  To progress thru the sequence, bump the field with an index of 0.  An index of 1 bumps the numeric
part of the group.  For example::

    >>> v1 = Version('1.2.3a4.post5.dev6', scheme=Pep440VersionScheme)
    >>> str(v1)
    '1.2.3a4.post5.dev6'
    >>> v1.bump('pre', 0)
    True
    >>> str(v1)
    '1.2.3b1'
    >>> v1.bump('pre', 1)
    True
    >>> str(v1)
    '1.2.3b2'
    >>> v1.bump('pre', 0)
    True
    >>> str(v1)
    '1.2.3c1'
    >>> v1.bump('pre', 0)
    True
    >>> str(v1)
    '1.2.3rc1'
    >>> v1.bump('pre', 0)
    False
    >>> str(v1)
    '1.2.3rc1'

Notice that bumping fails at the end of the sequence and the version is not changed.  You can override this behavior
by setting the promote argument to True, resulting in the field being removed at the end of the field's sequence.
For example:


    >>> v1 = Version('1.2.3rc1', scheme=Pep440VersionScheme)
    >>> str(v1)
    '1.2.3rc1'
    >>> v1.bump('pre', 0)
    False
    >>> str(v1)
    '1.2.3rc1'
    >>> v1.bump('pre', 0, promote=True)
    True
    >>> str(v1)
    '1.2.3'

That's it.

There are more examples in *tests/version_test.py*.  You may test directly with *py.test* or against multiple
python versions with *tox*.

Enjoy!



            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/royw/Versio",
    "name": "Versio",
    "maintainer": "",
    "docs_url": "https://pythonhosted.org/Versio/",
    "requires_python": "",
    "maintainer_email": "",
    "keywords": "version,PEP 440",
    "author": "Roy Wright",
    "author_email": "roy@wright.org",
    "download_url": "https://files.pythonhosted.org/packages/89/83/7a7d329cb8939b3b8c05c45cbf2c2af73499a417aa6306da2ccbf2be8638/Versio-0.5.0.tar.gz",
    "platform": "",
    "description": "Versio\n======\n\nLatin\n\n    Noun\n    1. a turning, change, version\n\n\nVersio is a generic version class that supports comparison and version bumping (incrementing by part, for example\nyou may bump the minor part of '1.2.3' yielding '1.3.0').\n\nFour version schemes are included:\n\n    * **Simple3VersionScheme** which supports 3 numerical part versions (A.B.C where A, B, and C are integers)\n    * **Simple4VersionScheme** which supports 4 numerical part versions (A.B.C.D where A, B, C, and D are integers)\n    * **Pep440VersionScheme** which supports PEP 440 (http://www.python.org/dev/peps/pep-0440/) versions\n      (N[.N]+[{a|b|c|rc}N][.postN][.devN][+local])\n    * **PerlVersionScheme** which supports 2 numerical part versions where the second part is at least two digits\n      (A.BB where A and B are integers and B is zero padded on the left.  For example:  1.02, 1.34, 1.567)\n\nIf you don't specify which version scheme the version instance uses, then it will use the first scheme from the\n**SupportedVersionSchemes** list that successfully parses the version string\n\nBy default, **Pep440VersionScheme** is the supported scheme.  To change to a different list of schemes, use the\n**Version.set_supported_version_schemes(schemes)**.  For example::\n\n    from versio.version_scheme import Simple3VersionScheme, PerlVersionScheme\n    Version.set_supported_version_schemes([Simple3VersionScheme, PerlVersionScheme])\n\nIn addition, you may define your own version scheme by creating a new VersionScheme instance.\n\nThe VersionScheme class defines the version scheme.\n\nA version scheme consists of:\n\n    * a name,\n    * a regular expression used to parse the version string,\n    * the regular expression flags to use (mainly to allow verbose regexes),\n    * a format string used to reassemble the parsed version into a string,\n    * an optional list of field types (if not specified, assumes all fields are strings),\n    * a list of field names used for accessing the components of the version.\n    * an optional subfield dictionary with the key being a field name and the value being a list of sub field names.\n      For example, in the **Pep440VersionScheme**, the \"Release\" field may contain multiple parts, so we use\n      subfield names for the parts.  Say we have a version of \"1.2.3rc1\", the \"1.2.3\" is the release field, then\n      \"1\" is the \"major\" subfield, \"2\" is the \"minor\" subfield, and \"3\" is the \"tiny\" subfield.\n    * a \"clear\" value used to set the field values to the right of the field being bumped,\n    * a sequence dictionary where the keys are the field names and the values are a list of allowed values.\n      The list must be in bump order.  Bumping the last value in the list has no effect.\n\nNote, you need to manually maintain consistency between the regular expression,\nthe format string, the optional field types, and the fields list.  For example,\nif your version scheme has N parts, then the regular expression should match\ninto N groups, the format string should expect N arguments to the str.format()\nmethod, and there must be N unique names in the fields list.\n\nInstallation\n============\n\nFrom pypi::\n\n    pip install Versio\n\n\nUsage\n=====\n\nFirst let's just play with the comparing and bumping versions::\n\n    >>> from versio.version import Version\n    >>> from versio.version_scheme import Pep440VersionScheme\n    >>> v1 = Version('1.2.3rc4.post5.dev6', scheme=Pep440VersionScheme)\n    >>> v2 = Version('1.2.3rc4.post5.dev7', scheme=Pep440VersionScheme)\n    >>> v1 == v2\n    False\n    >>> v1 < v2\n    True\n    >>> v1.bump('dev')\n    True\n    >>> str(v1)\n    '1.2.3rc4.post5.dev7'\n    >>> v1 == v2\n    True\n    >>> v1.bump('pre')\n    True\n\nNow let's look in the PEP 440 scheme::\n\n    >>> Pep440VersionScheme.fields\n    ['release', 'pre', 'post', 'dev', 'local']\n    >>> Pep440VersionScheme.format_str\n    '{0}{1}{2}{3}{4}'\n\nThe fields are used by the **bump(field)** method in the above example.  We skipped bumping the release above so let's\ndo it here::\n\n    >>> v1 = Version('1.2.3rc4.post5.dev6', scheme=Pep440VersionScheme)\n    >>> str(v1)\n    '1.2.3rc4.post5.dev6'\n    >>> v1.bump('release')\n    True\n    >>> str(v1)\n    '1.2.4'\n\nFor PEP 440, the release part is defined as \"N[.N]+\".  We can bump specific parts of the release by using an\nindex like::\n\n    >>> v1.bump('release', 2)\n    True\n    >>> str(v1)\n    '1.2.5'\n    >>> v1.bump('release', 1)\n    True\n    >>> str(v1)\n    '1.3.0'\n    >>> v1.bump('release', 0)\n    True\n    >>> str(v1)\n    '2.0.0'\n\nTo use a name directly, we use the concept of subfields which are mapped to a field/index pair::\n\n    >>> Pep440VersionScheme.subfields\n    {'tiny2': ['Release', 3], 'major': ['Release', 0], 'tiny': ['Release', 2], 'minor': ['Release', 1]}\n\n    >>> v1 = Version('1.2.3rc4.post5.dev6', scheme=Pep440VersionScheme)\n    >>> str(v1)\n    '1.2.3rc4.post5.dev6'\n    >>> v1.bump('tiny')\n    True\n    >>> str(v1)\n    '1.2.4'\n    >>> v1.bump('minor')\n    True\n    >>> str(v1)\n    '1.3.0'\n    >>> v1.bump('major')\n    True\n    >>> str(v1)\n    '2.0.0'\n\nNow that you've seen the version scheme in action, let's take a look at how it is defined::\n\n    Pep440VersionScheme = VersionScheme(name=\"pep440\",\n                                        parse_regex=r\"\"\"\n                                        ^\n                                        (\\d[\\.\\d]*(?<= \\d))\n                                        ((?:[abc]|rc)\\d+)?\n                                        (?:(\\.post\\d+))?\n                                        (?:(\\.dev\\d+))?\n                                        (?:(\\+(?![.])[a-zA-Z0-9\\.]*[a-zA-Z0-9]))?\n                                        $\n                                        \"\"\",\n                                        compare_order=[0, 1, 2, 3, 4],\n                                        compare_fill=['~', '~', '', '~', ''],\n                                        parse_flags=re.VERBOSE,\n                                        clear_value=None,\n                                        format_str='{0}{1}{2}{3}{4}',\n                                        fields=['Release', 'Pre', 'Post', 'Dev', 'Local'],\n                                        subfields={'Release': ['Major', 'Minor', 'Tiny', 'Tiny2']},\n                                        sequences={'Pre': ['a', 'b', 'c', 'rc'],\n                                                   'Post': ['.post'],\n                                                   'Dev': ['.dev'],\n                                                   'Local': ['+']},\n                                        description=dedent(\"\"\"\\\n                                            PEP 440\n                                            Public version identifiers MUST comply with the following scheme:\n\n                                            N[.N]+[{a|b|c|rc}N][.postN][.devN][+local]\n\n                                            Public version identifiers MUST NOT include leading or trailing whitespace.\n\n                                            Public version identifiers MUST be unique within a given distribution.\n\n                                            Public version identifiers are separated into up to five segments:\n\n                                                Release segment: N[.N]+\n                                                Pre-release segment: {a|b|c|rc}N\n                                                Post-release segment: .postN\n                                                Development release segment: .devN\n                                                Local release segment: +local\n\n                                            The local version labels MUST be limited to the following set of permitted\n                                            characters:\n\n                                                ASCII letters ( [a-zA-Z] )\n                                                ASCII digits ( [0-9] )\n                                                periods ( . )\n\n                                            Local version labels MUST start and end with an ASCII letter or digit.\n                                        \"\"\"))\n\nThe **parse_regex** and **parse_flags** do what you think by parsing a string into a list containing regex groups,\nexcept the group list is zero indexed to the first matching group.\n\nThe **format_str** and **format_types** control how the version is converted to a string in **__str__()**.  Basically\n**format_str.format(*args)** is called where the args is a list built by casting each of the version's groups using\nthe corresponding type from the  **format_types** list.  If you don't specify a **format_types**, then each group\nis cast as a str.\n\nThe **clear_value** typically should be '0' for numeric versions and None for non-numeric.  Basically it specifies\nwhat to put in the groups to the right of the group being bumped.\n\nThe **sequences** dictionary maps text to prepend to a group when formatting.  The dictionary keys must be in the\n**fields** list.  To progress thru the sequence, bump the field with an index of 0.  An index of 1 bumps the numeric\npart of the group.  For example::\n\n    >>> v1 = Version('1.2.3a4.post5.dev6', scheme=Pep440VersionScheme)\n    >>> str(v1)\n    '1.2.3a4.post5.dev6'\n    >>> v1.bump('pre', 0)\n    True\n    >>> str(v1)\n    '1.2.3b1'\n    >>> v1.bump('pre', 1)\n    True\n    >>> str(v1)\n    '1.2.3b2'\n    >>> v1.bump('pre', 0)\n    True\n    >>> str(v1)\n    '1.2.3c1'\n    >>> v1.bump('pre', 0)\n    True\n    >>> str(v1)\n    '1.2.3rc1'\n    >>> v1.bump('pre', 0)\n    False\n    >>> str(v1)\n    '1.2.3rc1'\n\nNotice that bumping fails at the end of the sequence and the version is not changed.  You can override this behavior\nby setting the promote argument to True, resulting in the field being removed at the end of the field's sequence.\nFor example:\n\n\n    >>> v1 = Version('1.2.3rc1', scheme=Pep440VersionScheme)\n    >>> str(v1)\n    '1.2.3rc1'\n    >>> v1.bump('pre', 0)\n    False\n    >>> str(v1)\n    '1.2.3rc1'\n    >>> v1.bump('pre', 0, promote=True)\n    True\n    >>> str(v1)\n    '1.2.3'\n\nThat's it.\n\nThere are more examples in *tests/version_test.py*.  You may test directly with *py.test* or against multiple\npython versions with *tox*.\n\nEnjoy!\n\n\n",
    "bugtrack_url": null,
    "license": "license.txt",
    "summary": "Version manipulation library.",
    "version": "0.5.0",
    "split_keywords": [
        "version",
        "pep 440"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "cd122b9ca783aea66cb246b2997448a0842e11953037427e39731541cf439692",
                "md5": "2d0baca95a40b0367c9a1885788ee100",
                "sha256": "68fde9c516bf352d9912a401202555dd9d7c4e2626f578fe41a7079159e43003"
            },
            "downloads": -1,
            "filename": "Versio-0.5.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "2d0baca95a40b0367c9a1885788ee100",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": null,
            "size": 12920,
            "upload_time": "2022-01-11T22:43:04",
            "upload_time_iso_8601": "2022-01-11T22:43:04.013211Z",
            "url": "https://files.pythonhosted.org/packages/cd/12/2b9ca783aea66cb246b2997448a0842e11953037427e39731541cf439692/Versio-0.5.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "89837a7d329cb8939b3b8c05c45cbf2c2af73499a417aa6306da2ccbf2be8638",
                "md5": "44744ba6eca0c12b8add40b294d46a69",
                "sha256": "64b3bb4cc285b5c7cf3afb3ea63bc6b0df1e7cb1db14e77a8b7ec81b8c8b058e"
            },
            "downloads": -1,
            "filename": "Versio-0.5.0.tar.gz",
            "has_sig": false,
            "md5_digest": "44744ba6eca0c12b8add40b294d46a69",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": null,
            "size": 31327,
            "upload_time": "2022-01-11T22:43:05",
            "upload_time_iso_8601": "2022-01-11T22:43:05.657466Z",
            "url": "https://files.pythonhosted.org/packages/89/83/7a7d329cb8939b3b8c05c45cbf2c2af73499a417aa6306da2ccbf2be8638/Versio-0.5.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2022-01-11 22:43:05",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "github_user": "royw",
    "github_project": "Versio",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "requirements": [
        {
            "name": null,
            "specs": []
        },
        {
            "name": "coverage",
            "specs": []
        },
        {
            "name": "flake8",
            "specs": []
        },
        {
            "name": "pytest-cov",
            "specs": []
        },
        {
            "name": "pytest",
            "specs": []
        },
        {
            "name": "radon",
            "specs": []
        }
    ],
    "tox": true,
    "lcname": "versio"
}
        
Elapsed time: 0.03631s