Skip to content

RF: Improve fallback version check, require PyPA packaging module #856

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 15, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 11 additions & 38 deletions nibabel/pkg_info.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,10 @@
import sys
import re
from distutils.version import StrictVersion
from packaging.version import Version
from . import _version

__version__ = _version.get_versions()['version']


def _parse_version(version_str):
""" Parse version string `version_str` in our format
"""
match = re.match(r'([0-9.]*\d)(.*)', version_str)
if match is None:
raise ValueError('Invalid version ' + version_str)
return match.groups()


def _cmp(a, b):
""" Implementation of ``cmp`` for Python 3
"""
Expand All @@ -24,18 +14,19 @@ def _cmp(a, b):
def cmp_pkg_version(version_str, pkg_version_str=__version__):
""" Compare ``version_str`` to current package version

To be valid, a version must have a numerical major version followed by a
dot, followed by a numerical minor version. It may optionally be followed
by a dot and a numerical micro version, and / or by an "extra" string.
This comparator follows `PEP-440`_ conventions for determining version
ordering.

To be valid, a version must have a numerical major version. It may be
optionally followed by a dot and a numerical minor version, which may,
in turn, optionally be followed by a dot and a numerical micro version,
and / or by an "extra" string.
The extra string may further contain a "+". Any value to the left of a "+"
labels the version as pre-release, while values to the right indicate a
post-release relative to the values to the left. That is,
``1.2.0+1`` is post-release for ``1.2.0``, while ``1.2.0rc1+1`` is
post-release for ``1.2.0rc1`` and pre-release for ``1.2.0``.

This is an approximation of `PEP-440`_, and future versions will fully
implement PEP-440.

Parameters
----------
version_str : str
Expand Down Expand Up @@ -63,30 +54,12 @@ def cmp_pkg_version(version_str, pkg_version_str=__version__):
1
>>> cmp_pkg_version('1.2.0rc1+1', '1.2.0')
-1
>>> cmp_pkg_version('1.2.0.post1', '1.2.0')
1

.. _`PEP-440`: https://www.python.org/dev/peps/pep-0440/
"""
version, extra = _parse_version(version_str)
pkg_version, pkg_extra = _parse_version(pkg_version_str)

# Normalize versions
quick_check = _cmp(StrictVersion(version), StrictVersion(pkg_version))
# Nothing further to check
if quick_check != 0 or extra == pkg_extra == '':
return quick_check

# Before + is pre-release, after + is additional increment
pre, _, post = extra.partition('+')
pkg_pre, _, pkg_post = pkg_extra.partition('+')
quick_check = _cmp(pre, pkg_pre)
if quick_check != 0: # Excludes case where pre and pkg_pre == ''
# Pre-releases are ordered but strictly less than non-pre
return (1 if pre == ''
else -1 if pkg_pre == ''
else quick_check)

# All else being equal, compare additional information lexically
return _cmp(post, pkg_post)
return _cmp(Version(version_str), Version(pkg_version_str))


def pkg_commit_hash(pkg_path=None):
Expand Down
18 changes: 13 additions & 5 deletions nibabel/tests/test_pkg_info.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
""" Testing package info
"""

from packaging.version import Version

import nibabel as nib
from nibabel.pkg_info import cmp_pkg_version
from ..info import VERSION
Expand Down Expand Up @@ -30,12 +32,14 @@ def test_fallback_version():
This should only fail if we fail to bump nibabel.info.VERSION immediately
after release
"""
ver = Version(nib.__version__)
fallback = Version(VERSION)
assert (
# Releases have no local information, archive matches versioneer
ver.local is None or
# dev version should be larger than tag+commit-githash
cmp_pkg_version(VERSION) >= 0 or
# Allow VERSION bump to lag releases by one commit
VERSION == nib.__version__ + 'dev'), \
"nibabel.info.VERSION does not match current tag information"
fallback >= ver), \
"nibabel.info.VERSION does not match latest tag information"


def test_cmp_pkg_version():
Expand Down Expand Up @@ -76,6 +80,10 @@ def test_cmp_pkg_version():
assert_raises(ValueError, cmp_pkg_version, 'foo.2')
assert_raises(ValueError, cmp_pkg_version, 'foo.2', '1.0')
assert_raises(ValueError, cmp_pkg_version, '1.0', 'foo.2')
assert_raises(ValueError, cmp_pkg_version, '1')
assert_raises(ValueError, cmp_pkg_version, 'foo')

# Check dev/RC sequence
seq = ('3.0.0dev', '3.0.0rc1', '3.0.0rc1.post.dev', '3.0.0rc2', '3.0.0rc2.post.dev', '3.0.0')
for stage1, stage2 in zip(seq[:-1], seq[1:]):
assert_equal(cmp_pkg_version(stage1, stage2), -1)
assert_equal(cmp_pkg_version(stage2, stage1), 1)
1 change: 1 addition & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ provides =
python_requires = >=3.5.1
install_requires =
numpy >=1.12
packaging
tests_require =
nose >=0.11
pytest
Expand Down