From 250ee413e9f37e36e91ccc5ffec8fb294faf1620 Mon Sep 17 00:00:00 2001 From: "Adam J. Stewart" Date: Mon, 24 Jul 2017 15:02:13 -0500 Subject: Change Version formatting properties and functions to return Version objects (#4834) * Change version.up_to() to return Version() object * Add unit tests for Version.up_to() * Fix packages that expected up_to() to return a string * Ensure that up_to() preserves separator characters * Use version indexing instead of up_to * Make all Version formatting properties return Version objects * Update docs * Tests need to test string representation --- lib/spack/docs/packaging_guide.rst | 15 ++++ lib/spack/spack/test/versions.py | 56 ++++++++++++--- lib/spack/spack/version.py | 82 ++++++++++++++++++---- var/spack/repos/builtin/packages/lua/package.py | 4 +- var/spack/repos/builtin/packages/magics/package.py | 2 +- var/spack/repos/builtin/packages/qt/package.py | 4 +- .../repos/builtin/packages/sublime-text/package.py | 2 +- 7 files changed, 138 insertions(+), 27 deletions(-) diff --git a/lib/spack/docs/packaging_guide.rst b/lib/spack/docs/packaging_guide.rst index b90a0eea17..e4b10cdf53 100644 --- a/lib/spack/docs/packaging_guide.rst +++ b/lib/spack/docs/packaging_guide.rst @@ -490,6 +490,21 @@ version.joined 123 Python properties don't need parentheses. ``version.dashed`` is correct. ``version.dashed()`` is incorrect. +In addition, these version properties can be combined with ``up_to()``. +For example: + +.. code-block:: python + + >>> version = Version('1.2.3') + >>> version.up_to(2).dashed + Version('1-2') + >>> version.underscored.up_to(2) + Version('1_2') + + +As you can see, order is not important. Just keep in mind that ``up_to()`` and +the other version properties return ``Version`` objects, not strings. + If a URL cannot be derived systematically, or there is a special URL for one of its versions, you can add an explicit URL for a particular version: diff --git a/lib/spack/spack/test/versions.py b/lib/spack/spack/test/versions.py index 3b04e1d4aa..72292e4dcd 100644 --- a/lib/spack/spack/test/versions.py +++ b/lib/spack/spack/test/versions.py @@ -204,6 +204,8 @@ def test_underscores(): assert_ver_eq('2_0', '2_0') assert_ver_eq('2.0', '2_0') assert_ver_eq('2_0', '2.0') + assert_ver_eq('2-0', '2_0') + assert_ver_eq('2_0', '2-0') def test_rpm_oddities(): @@ -426,20 +428,56 @@ def test_satisfaction_with_lists(): def test_formatted_strings(): - versions = '1.2.3', '1_2_3', '1-2-3' + versions = ( + '1.2.3b', '1_2_3b', '1-2-3b', + '1.2-3b', '1.2_3b', '1-2.3b', + '1-2_3b', '1_2.3b', '1_2-3b' + ) for item in versions: v = Version(item) - assert v.dotted == '1.2.3' - assert v.dashed == '1-2-3' - assert v.underscored == '1_2_3' - assert v.joined == '123' + assert v.dotted.string == '1.2.3b' + assert v.dashed.string == '1-2-3b' + assert v.underscored.string == '1_2_3b' + assert v.joined.string == '123b' + + assert v.dotted.dashed.string == '1-2-3b' + assert v.dotted.underscored.string == '1_2_3b' + assert v.dotted.dotted.string == '1.2.3b' + assert v.dotted.joined.string == '123b' + + +def test_up_to(): + v = Version('1.23-4_5b') + + assert v.up_to(1).string == '1' + assert v.up_to(2).string == '1.23' + assert v.up_to(3).string == '1.23-4' + assert v.up_to(4).string == '1.23-4_5' + assert v.up_to(5).string == '1.23-4_5b' + + assert v.up_to(-1).string == '1.23-4_5' + assert v.up_to(-2).string == '1.23-4' + assert v.up_to(-3).string == '1.23' + assert v.up_to(-4).string == '1' + + assert v.up_to(2).dotted.string == '1.23' + assert v.up_to(2).dashed.string == '1-23' + assert v.up_to(2).underscored.string == '1_23' + assert v.up_to(2).joined.string == '123' + + assert v.dotted.up_to(2).string == '1.23' == v.up_to(2).dotted.string + assert v.dashed.up_to(2).string == '1-23' == v.up_to(2).dashed.string + assert v.underscored.up_to(2).string == '1_23' + assert v.up_to(2).underscored.string == '1_23' + + assert v.up_to(2).up_to(1).string == '1' def test_repr_and_str(): def check_repr_and_str(vrs): a = Version(vrs) - assert repr(a) == 'Version(\'' + vrs + '\')' + assert repr(a) == "Version('" + vrs + "')" b = eval(repr(a)) assert a == b assert str(a) == vrs @@ -457,17 +495,17 @@ def test_get_item(): b = a[0:2] assert isinstance(b, Version) assert b == Version('0.1') - assert repr(b) == 'Version(\'0.1\')' + assert repr(b) == "Version('0.1')" assert str(b) == '0.1' b = a[0:3] assert isinstance(b, Version) assert b == Version('0.1_2') - assert repr(b) == 'Version(\'0.1_2\')' + assert repr(b) == "Version('0.1_2')" assert str(b) == '0.1_2' b = a[1:] assert isinstance(b, Version) assert b == Version('1_2-3') - assert repr(b) == 'Version(\'1_2-3\')' + assert repr(b) == "Version('1_2-3')" assert str(b) == '1_2-3' # Raise TypeError on tuples with pytest.raises(TypeError): diff --git a/lib/spack/spack/version.py b/lib/spack/spack/version.py index 10fac49e9d..0d8520a0e0 100644 --- a/lib/spack/spack/version.py +++ b/lib/spack/spack/version.py @@ -130,30 +130,90 @@ class Version(object): self.version = tuple(int_if_int(seg) for seg in segments) # Store the separators from the original version string as well. - # last element of separators is '' - self.separators = tuple(re.split(segment_regex, string)[1:-1]) + self.separators = tuple(re.split(segment_regex, string)[1:]) @property def dotted(self): - return '.'.join(str(x) for x in self.version) + """The dotted representation of the version. + + Example: + >>> version = Version('1-2-3b') + >>> version.dotted + Version('1.2.3b') + + Returns: + Version: The version with separator characters replaced by dots + """ + return Version(self.string.replace('-', '.').replace('_', '.')) @property def underscored(self): - return '_'.join(str(x) for x in self.version) + """The underscored representation of the version. + + Example: + >>> version = Version('1.2.3b') + >>> version.underscored + Version('1_2_3b') + + Returns: + Version: The version with separator characters replaced by + underscores + """ + return Version(self.string.replace('.', '_').replace('-', '_')) @property def dashed(self): - return '-'.join(str(x) for x in self.version) + """The dashed representation of the version. + + Example: + >>> version = Version('1.2.3b') + >>> version.dashed + Version('1-2-3b') + + Returns: + Version: The version with separator characters replaced by dashes + """ + return Version(self.string.replace('.', '-').replace('_', '-')) @property def joined(self): - return ''.join(str(x) for x in self.version) + """The joined representation of the version. + + Example: + >>> version = Version('1.2.3b') + >>> version.joined + Version('123b') + + Returns: + Version: The version with separator characters removed + """ + return Version( + self.string.replace('.', '').replace('-', '').replace('_', '')) def up_to(self, index): - """Return a version string up to the specified component, exclusive. - e.g., if this is 10.8.2, self.up_to(2) will return '10.8'. + """The version up to the specified component. + + Examples: + >>> version = Version('1.23-4b') + >>> version.up_to(1) + Version('1') + >>> version.up_to(2) + Version('1.23') + >>> version.up_to(3) + Version('1.23-4') + >>> version.up_to(4) + Version('1.23-4b') + >>> version.up_to(-1) + Version('1.23-4') + >>> version.up_to(-2) + Version('1.23') + >>> version.up_to(-3) + Version('1') + + Returns: + Version: The first index components of the version """ - return '.'.join(str(x) for x in self[:index]) + return self[:index] def lowest(self): return self @@ -204,11 +264,9 @@ class Version(object): return self.version[idx] elif isinstance(idx, slice): - # Currently len(self.separators) == len(self.version) - 1 - extendend_separators = self.separators + ('',) string_arg = [] - pairs = zip(self.version[idx], extendend_separators[idx]) + pairs = zip(self.version[idx], self.separators[idx]) for token, sep in pairs: string_arg.append(str(token)) string_arg.append(str(sep)) diff --git a/var/spack/repos/builtin/packages/lua/package.py b/var/spack/repos/builtin/packages/lua/package.py index 0680e1a3b5..ecb2a8b543 100644 --- a/var/spack/repos/builtin/packages/lua/package.py +++ b/var/spack/repos/builtin/packages/lua/package.py @@ -145,11 +145,11 @@ class Lua(Package): @property def lua_lib_dir(self): - return os.path.join('lib', 'lua', self.version.up_to(2)) + return os.path.join('lib', 'lua', str(self.version.up_to(2))) @property def lua_share_dir(self): - return os.path.join('share', 'lua', self.version.up_to(2)) + return os.path.join('share', 'lua', str(self.version.up_to(2))) def setup_dependent_package(self, module, dependent_spec): """ diff --git a/var/spack/repos/builtin/packages/magics/package.py b/var/spack/repos/builtin/packages/magics/package.py index d69dedf3ea..33a6bb5640 100644 --- a/var/spack/repos/builtin/packages/magics/package.py +++ b/var/spack/repos/builtin/packages/magics/package.py @@ -109,7 +109,7 @@ class Magics(Package): if '+metview' in spec: if '+qt' in spec: options.append('-DENABLE_METVIEW=ON') - if spec['qt'].version.up_to(1) == '5': + if spec['qt'].version[0] == 5: options.append('-DENABLE_QT5=ON') else: options.append('-DENABLE_METVIEW_NO_QT=ON') diff --git a/var/spack/repos/builtin/packages/qt/package.py b/var/spack/repos/builtin/packages/qt/package.py index 551f87b5d7..89e821b68f 100644 --- a/var/spack/repos/builtin/packages/qt/package.py +++ b/var/spack/repos/builtin/packages/qt/package.py @@ -131,9 +131,9 @@ class Qt(Package): url = self.list_url if version >= Version('4.0'): - url += version.up_to(2) + '/' + url += str(version.up_to(2)) + '/' else: - url += version.up_to(1) + '/' + url += str(version.up_to(1)) + '/' if version >= Version('4.8'): url += str(version) + '/' diff --git a/var/spack/repos/builtin/packages/sublime-text/package.py b/var/spack/repos/builtin/packages/sublime-text/package.py index 3d7fb65005..e7605b40be 100644 --- a/var/spack/repos/builtin/packages/sublime-text/package.py +++ b/var/spack/repos/builtin/packages/sublime-text/package.py @@ -49,7 +49,7 @@ class SublimeText(Package): depends_on('libxau', type='run') def url_for_version(self, version): - if version.up_to(1) == '2': + if version[0] == 2: return "https://download.sublimetext.com/Sublime%20Text%20{0}%20x64.tar.bz2".format(version) else: return "https://download.sublimetext.com/sublime_text_3_build_{0}_x64.tar.bz2".format(version) -- cgit v1.2.3-60-g2f50