Skip to content

Commit

Permalink
Change Version formatting properties and functions to return Version …
Browse files Browse the repository at this point in the history
…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
  • Loading branch information
adamjstewart authored and tgamblin committed Jul 24, 2017
1 parent df2fc25 commit 250ee41
Show file tree
Hide file tree
Showing 7 changed files with 138 additions and 27 deletions.
15 changes: 15 additions & 0 deletions lib/spack/docs/packaging_guide.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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:

Expand Down
56 changes: 47 additions & 9 deletions lib/spack/spack/test/versions.py
Original file line number Diff line number Diff line change
Expand Up @@ -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():
Expand Down Expand Up @@ -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
Expand All @@ -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):
Expand Down
82 changes: 70 additions & 12 deletions lib/spack/spack/version.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,30 +130,90 @@ def __init__(self, string):
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
Expand Down Expand Up @@ -204,11 +264,9 @@ def __getitem__(self, idx):
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))
Expand Down
4 changes: 2 additions & 2 deletions var/spack/repos/builtin/packages/lua/package.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,11 +145,11 @@ def setup_environment(self, spack_env, run_env):

@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):
"""
Expand Down
2 changes: 1 addition & 1 deletion var/spack/repos/builtin/packages/magics/package.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ def install(self, spec, prefix):
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')
Expand Down
4 changes: 2 additions & 2 deletions var/spack/repos/builtin/packages/qt/package.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,9 +131,9 @@ def url_for_version(self, version):
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) + '/'
Expand Down
2 changes: 1 addition & 1 deletion var/spack/repos/builtin/packages/sublime-text/package.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down

0 comments on commit 250ee41

Please sign in to comment.