From 52158d9316aabd9c02a719825928607cb5204377 Mon Sep 17 00:00:00 2001 From: "Adam J. Stewart" Date: Fri, 21 Oct 2016 09:49:36 -0500 Subject: Add new Version property to handle joined version numbers (#2062) * Add new version property to handle joined version numbers * Add unit test for new joined property * Add documentation on version.up_to() and version.joined --- lib/spack/docs/packaging_guide.rst | 59 +++++++++++++++++++++++++++----------- lib/spack/spack/test/versions.py | 1 + lib/spack/spack/version.py | 4 +++ 3 files changed, 47 insertions(+), 17 deletions(-) (limited to 'lib') diff --git a/lib/spack/docs/packaging_guide.rst b/lib/spack/docs/packaging_guide.rst index efd4c459a2..bf5763f4f8 100644 --- a/lib/spack/docs/packaging_guide.rst +++ b/lib/spack/docs/packaging_guide.rst @@ -526,32 +526,57 @@ in the package. For example, Spack is smart enough to download version ``8.2.1.`` of the ``Foo`` package above from ``http://example.com/foo-8.2.1.tar.gz``. -If spack *cannot* extrapolate the URL from the ``url`` field by -default, you can write your own URL generation algorithm in place of -the ``url`` declaration. For example: +If the URL is particularly complicated or changes based on the release, +you can override the default URL generation algorithm by defining your +own ``url_for_version()`` function. For example, the developers of HDF5 +keep changing the archive layout, so the ``url_for_version()`` function +looks like: + +.. literalinclude:: ../../../var/spack/repos/builtin/packages/hdf5/package.py + :pyobject: Hdf5.url_for_version + +With the use of this ``url_for_version()``, Spack knows to download HDF5 ``1.8.16`` +from ``http://www.hdfgroup.org/ftp/HDF5/releases/hdf5-1.8.16/src/hdf5-1.8.16.tar.gz`` +but download HDF5 ``1.10.0`` from ``http://www.hdfgroup.org/ftp/HDF5/releases/hdf5-1.10/hdf5-1.10.0/src/hdf5-1.10.0.tar.gz``. + +You'll notice that HDF5's ``url_for_version()`` function makes use of a special +``Version`` function called ``up_to()``. When you call ``version.up_to(2)`` on a +version like ``1.10.0``, it returns ``1.10``. ``version.up_to(1)`` would return +``1``. This can be very useful for packages that place all ``X.Y.*`` versions in +a single directory and then places all ``X.Y.Z`` versions in a subdirectory. + +There are a few ``Version`` properties you should be aware of. We generally +prefer numeric versions to be separated by dots for uniformity, but not all +tarballs are named that way. For example, ``icu4c`` separates its major and minor +versions with underscores, like ``icu4c-57_1-src.tgz``. The value ``57_1`` can be +obtained with the use of the ``version.underscored`` property. Note that Python +properties don't need parentheses. There are other separator properties as well: + +=================== ====== +Property Result +=================== ====== +version.dotted 1.2.3 +version.dashed 1-2-3 +version.underscored 1_2_3 +version.joined 123 +=================== ====== -.. code-block:: python - :linenos: +.. note:: - class Foo(Package): - version('8.2.1', '4136d7b4c04df68b686570afa26988ac') - ... - def url_for_version(self, version): - return 'http://example.com/version_%s/foo-%s.tar.gz' \ - % (version, version) - ... + Python properties don't need parentheses. ``version.dashed`` is correct. + ``version.dashed()`` is incorrect. -If a URL cannot be derived systematically, you can add an explicit URL -for a particular version: +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: .. code-block:: python version('8.2.1', '4136d7b4c04df68b686570afa26988ac', url='http://example.com/foo-8.2.1-special-version.tar.gz') -For the URL above, you might have to add an explicit URL because the -version can't simply be substituted in the original ``url`` to -construct the new one for ``8.2.1``. +This is common for Python packages that download from PyPi. Since newer +download URLs often contain a unique hash for each version, there is no +way to guess the URL systematically. When you supply a custom URL for a version, Spack uses that URL *verbatim* and does not perform extrapolation. diff --git a/lib/spack/spack/test/versions.py b/lib/spack/spack/test/versions.py index 9b4dc29f35..c1d427783c 100644 --- a/lib/spack/spack/test/versions.py +++ b/lib/spack/spack/test/versions.py @@ -392,6 +392,7 @@ class VersionsTest(unittest.TestCase): self.assertEqual(v.dotted, '1.2.3') self.assertEqual(v.dashed, '1-2-3') self.assertEqual(v.underscored, '1_2_3') + self.assertEqual(v.joined, '123') def test_repr_and_str(self): diff --git a/lib/spack/spack/version.py b/lib/spack/spack/version.py index 67a22f4660..0d68a709e8 100644 --- a/lib/spack/spack/version.py +++ b/lib/spack/spack/version.py @@ -146,6 +146,10 @@ class Version(object): def dashed(self): return '-'.join(str(x) for x in self.version) + @property + def joined(self): + return ''.join(str(x) for x in self.version) + 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'. -- cgit v1.2.3-70-g09d2