Regex to match PEP440 compliant version strings
Asked Answered
A

2

15

PEP 440 lays out what is the accepted format for version strings of Python packages.

These can be simple, like: 0.0.1

Or complicated, like: 2016!1.0-alpha1.dev2

What is a suitable regex which could be used for finding and validating such strings?

Agent answered 22/6, 2016 at 15:12 Comment(1)
Where is your regex, and what is the problem with it?Hieratic
N
19

I had the same question. This is the most thorough regex pattern I could find. PEP440 links to the codebase of the packaging library in it's references section.

pip install packaging

To access just the pattern string you can use the global

from packaging import version
version.VERSION_PATTERN

See: https://github.com/pypa/packaging/blob/21.3/packaging/version.py#L225-L254

VERSION_PATTERN = r"""
    v?
    (?:
        (?:(?P<epoch>[0-9]+)!)?                           # epoch
        (?P<release>[0-9]+(?:\.[0-9]+)*)                  # release segment
        (?P<pre>                                          # pre-release
            [-_\.]?
            (?P<pre_l>(a|b|c|rc|alpha|beta|pre|preview))
            [-_\.]?
            (?P<pre_n>[0-9]+)?
        )?
        (?P<post>                                         # post release
            (?:-(?P<post_n1>[0-9]+))
            |
            (?:
                [-_\.]?
                (?P<post_l>post|rev|r)
                [-_\.]?
                (?P<post_n2>[0-9]+)?
            )
        )?
        (?P<dev>                                          # dev release
            [-_\.]?
            (?P<dev_l>dev)
            [-_\.]?
            (?P<dev_n>[0-9]+)?
        )?
    )
    (?:\+(?P<local>[a-z0-9]+(?:[-_\.][a-z0-9]+)*))?       # local version
"""

Of course this example is specific to Python's flavor of regex.

Neutretto answered 24/6, 2016 at 18:55 Comment(5)
Thank you, this is the answer I needed.Agent
you've included your comments in a regular string, so I don't expect this to work as-isDigression
While this may be comprehensive I cannot use it as branch matching pattern in Travis.Bebebebeerine
It can be used with _regex = re.compile(r"^\s*" + VERSION_PATTERN + r"\s*$", re.VERBOSE | re.IGNORECASE)Baese
2024 version is here: github.com/pypa/packaging/blob/24.1/src/packaging/…Lennyleno
A
11

I think this should comply with PEP440:

^(\d+!)?(\d+)(\.\d+)+([\.\-\_])?((a(lpha)?|b(eta)?|c|r(c|ev)?|pre(view)?)\d*)?(\.?(post|dev)\d*)?$

Explained

Epoch, e.g. 2016!:

(\d+!)?

Version parts (major, minor, patch, etc.):

(\d+)(\.\d+)+

Acceptable separators (., - or _):

([\.\-\_])?

Possible pre-release flags (and their normalisations; as well as post release flags r or rev), may have one or more digits following:

((a(lpha)?|b(eta)?|c|r(c|ev)?|pre(view)?)\d*)?

Post-release flags, and one or more digits:

(\.?(post|dev)\d*)?
Agent answered 22/6, 2016 at 15:12 Comment(4)
It was a difficult problem to solve, and could very well be useful to someone working with Python packaging. Does that not make it a decent question?Agent
More to the point, if anyone has a better solution I'd really like to know.Agent
first thing first..ask the entire question..your regex has much more information than you pointed out in the question..Havener
This does not match examples stated in PEP440, for example 1.0+ubuntu.1Lennyleno

© 2022 - 2024 — McMap. All rights reserved.