Source code for verschemes.pep440

# -*- coding: utf-8 -*-
"""verschemes.pep440 module

The PEP 440 verschemes module implements standard
`PEP 440 <http://legacy.python.org/dev/peps/pep-0440/>`_
`public <http://legacy.python.org/dev/peps/pep-0440/#public-version-identifiers>`_
versioning.  PEP 440
`local <http://legacy.python.org/dev/peps/pep-0440/#local-version-identifiers>`_
versions are not supported by this module; they are just public versions with a
hyphen and a numeric version (as implemented by the defaults in the base
`verschemes.Version` class) appended.

This implementation is limited to six release-number segments, which should
handle any reasonable scheme.

"""

# Support Python 2 & 3.
from __future__ import (absolute_import, division, print_function,
                        unicode_literals)
from verschemes.future import *

from verschemes import SegmentDefinition, SegmentField, Version
from verschemes._types import int_empty_zero


__all__ = []

__all__.extend(['SEGMENTS', 'EPOCH', 'RELEASE1', 'RELEASE2', 'RELEASE3',
                'RELEASE4', 'RELEASE5', 'RELEASE6', 'PRE_RELEASE',
                'POST_RELEASE', 'DEVELOPMENT'])
SEGMENTS = (
    EPOCH,
    RELEASE1,
    RELEASE2,
    RELEASE3,
    RELEASE4,
    RELEASE5,
    RELEASE6,
    PRE_RELEASE,
    POST_RELEASE,
    DEVELOPMENT,
) = tuple(range(10))

__all__.append('RELEASE_SEGMENTS')
RELEASE_SEGMENTS = SEGMENTS[:PRE_RELEASE]

__all__.append('NONRELEASE_SEGMENTS')
NONRELEASE_SEGMENTS = SEGMENTS[PRE_RELEASE:]


def _pre_release_level_render(value):
    value = value.lower()
    if len(value) > 1:
        if value == 'rc':
            value = 'c'
        else:
            value = value[0]
    return value


__all__.append('Pep440Version')
[docs]class Pep440Version(Version): """A PEP 440 public version. The version scheme has an optional `epoch` segment followed by up to six release-number segments (named 'releaseX', where X is 1-6) followed by the optional `pre_release`, `post_release`, and `development` segments. `~verschemes.Version.SEGMENT_DEFINITIONS` contains the following named segments in order: * epoch: optional=True, default=0 * release1: default=0, separator='!' * release2: optional=True, default=0 * release3: optional=True, default=0 * release4: optional=True, default=0 * release5: optional=True, default=0 * release6: optional=True, default=0 * pre_release: optional=True, separator='', separator_re_pattern='[.-]?' * field 'level': type=str (case-insensitive input) * normal form 'a' accepts 'a' or 'alpha' * normal form 'b' accepts 'b' or 'beta' * normal form 'c' accepts 'c' or 'rc' * field 'serial': type=int_empty_zero, re_pattern='[0-9]*' * post_release: optional=True, separator='.post', separator_re_pattern='[.-]?post' * field: type=int_empty_zero, re_pattern='[0-9]*' * development: optional=True, separator='.dev', separator_re_pattern='[.-]?dev' * field: type=int_empty_zero, re_pattern='[0-9]*' """ SEGMENT_DEFINITIONS = ( SegmentDefinition( name='epoch', optional=True, default=0, ), SegmentDefinition( name='release1', default=0, separator='!', ), SegmentDefinition( name='release2', optional=True, default=0, ), SegmentDefinition( name='release3', optional=True, default=0, ), SegmentDefinition( name='release4', optional=True, default=0, ), SegmentDefinition( name='release5', optional=True, default=0, ), SegmentDefinition( name='release6', optional=True, default=0, ), SegmentDefinition( name='pre_release', optional=True, separator='', separator_re_pattern='[.-]?', fields=( SegmentField( type=str, name='level', re_pattern=('[aAbBcC]|' '[aA][lL][pP][hH][aA]|' '[bB][eE][tT][aA]|' '[rR][cC]'), render=_pre_release_level_render ), SegmentField( type=int_empty_zero, name='serial', re_pattern='[0-9]*', ), ), ), SegmentDefinition( name='post_release', optional=True, separator='.post', separator_re_pattern='[.-]?post', fields=( SegmentField( type=int_empty_zero, re_pattern='[0-9]*', ), ), ), SegmentDefinition( name='development', optional=True, separator='.dev', separator_re_pattern='[.-]?dev', fields=( SegmentField( type=int_empty_zero, re_pattern='[0-9]*', ), ), ), ) @property
[docs] def is_release(self): """Whether this version represents a final release. Return `True` if all of the 'pre_release', 'post_release', and 'development' segments have no value. """ return all(self[x] is None for x in NONRELEASE_SEGMENTS)
def _render_exclude_defaults_callback(self, index, scope=None): if scope is None: scope = list(RELEASE_SEGMENTS) scope.remove(EPOCH) return super()._render_exclude_defaults_callback(index, scope) def _render_include_min_release_callback(self, index, min_release_segments): return RELEASE1 <= index < RELEASE1 + min_release_segments
[docs] def render(self, exclude_defaults=True, include_callbacks=(), exclude_callbacks=(), min_release_segments=1): """Override to provide the `min_release_segments` option.""" include_callbacks = list(include_callbacks) include_callbacks.append( (type(self)._render_include_min_release_callback, min_release_segments)) return super().render(exclude_defaults, include_callbacks, exclude_callbacks)