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
This commit is contained in:
Adam J. Stewart 2016-10-21 09:49:36 -05:00 committed by Todd Gamblin
parent c513fd72fb
commit 52158d9316
9 changed files with 68 additions and 39 deletions

View File

@ -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 version ``8.2.1.`` of the ``Foo`` package above from
``http://example.com/foo-8.2.1.tar.gz``. ``http://example.com/foo-8.2.1.tar.gz``.
If spack *cannot* extrapolate the URL from the ``url`` field by If the URL is particularly complicated or changes based on the release,
default, you can write your own URL generation algorithm in place of you can override the default URL generation algorithm by defining your
the ``url`` declaration. For example: own ``url_for_version()`` function. For example, the developers of HDF5
keep changing the archive layout, so the ``url_for_version()`` function
looks like:
.. code-block:: python .. literalinclude:: ../../../var/spack/repos/builtin/packages/hdf5/package.py
:linenos: :pyobject: Hdf5.url_for_version
class Foo(Package): With the use of this ``url_for_version()``, Spack knows to download HDF5 ``1.8.16``
version('8.2.1', '4136d7b4c04df68b686570afa26988ac') 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``.
def url_for_version(self, version):
return 'http://example.com/version_%s/foo-%s.tar.gz' \
% (version, version)
...
If a URL cannot be derived systematically, you can add an explicit URL You'll notice that HDF5's ``url_for_version()`` function makes use of a special
for a particular version: ``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
=================== ======
.. note::
Python properties don't need parentheses. ``version.dashed`` is correct.
``version.dashed()`` is incorrect.
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 .. code-block:: python
version('8.2.1', '4136d7b4c04df68b686570afa26988ac', version('8.2.1', '4136d7b4c04df68b686570afa26988ac',
url='http://example.com/foo-8.2.1-special-version.tar.gz') 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 This is common for Python packages that download from PyPi. Since newer
version can't simply be substituted in the original ``url`` to download URLs often contain a unique hash for each version, there is no
construct the new one for ``8.2.1``. way to guess the URL systematically.
When you supply a custom URL for a version, Spack uses that URL When you supply a custom URL for a version, Spack uses that URL
*verbatim* and does not perform extrapolation. *verbatim* and does not perform extrapolation.

View File

@ -392,6 +392,7 @@ def test_formatted_strings(self):
self.assertEqual(v.dotted, '1.2.3') self.assertEqual(v.dotted, '1.2.3')
self.assertEqual(v.dashed, '1-2-3') self.assertEqual(v.dashed, '1-2-3')
self.assertEqual(v.underscored, '1_2_3') self.assertEqual(v.underscored, '1_2_3')
self.assertEqual(v.joined, '123')
def test_repr_and_str(self): def test_repr_and_str(self):

View File

@ -146,6 +146,10 @@ def underscored(self):
def dashed(self): def dashed(self):
return '-'.join(str(x) for x in self.version) 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): def up_to(self, index):
"""Return a version string up to the specified component, exclusive. """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'. e.g., if this is 10.8.2, self.up_to(2) will return '10.8'.

View File

@ -35,16 +35,16 @@ class Cdd(Package):
homepage = "https://www.inf.ethz.ch/personal/fukudak/cdd_home/cdd.html" homepage = "https://www.inf.ethz.ch/personal/fukudak/cdd_home/cdd.html"
url = "ftp://ftp.ifor.math.ethz.ch/pub/fukuda/cdd/cdd-061a.tar.gz" url = "ftp://ftp.ifor.math.ethz.ch/pub/fukuda/cdd/cdd-061a.tar.gz"
def url_for_version(self, version):
return ("ftp://ftp.ifor.math.ethz.ch/pub/fukuda/cdd/cdd-%s.tar.gz" %
str(version.dotted).replace('.', ''))
version('0.61a', '22c24a7a9349dd7ec0e24531925a02d9') version('0.61a', '22c24a7a9349dd7ec0e24531925a02d9')
depends_on("libtool", type="build") depends_on("libtool", type="build")
patch("Makefile.spack.patch") patch("Makefile.spack.patch")
def url_for_version(self, version):
url = "ftp://ftp.ifor.math.ethz.ch/pub/fukuda/cdd/cdd-{0}.tar.gz"
return url.format(version.joined)
def install(self, spec, prefix): def install(self, spec, prefix):
# The Makefile isn't portable; use our own instead # The Makefile isn't portable; use our own instead
makeargs = ["-f", "Makefile.spack", "PREFIX=%s" % prefix] makeargs = ["-f", "Makefile.spack", "PREFIX=%s" % prefix]

View File

@ -34,9 +34,9 @@ class Cfitsio(Package):
version('3.370', 'abebd2d02ba5b0503c633581e3bfa116') version('3.370', 'abebd2d02ba5b0503c633581e3bfa116')
def url_for_version(self, v): def url_for_version(self, version):
url = 'ftp://heasarc.gsfc.nasa.gov/software/fitsio/c/cfitsio{0}.tar.gz' url = 'ftp://heasarc.gsfc.nasa.gov/software/fitsio/c/cfitsio{0}.tar.gz'
return url.format(str(v).replace('.', '')) return url.format(version.joined)
def install(self, spec, prefix): def install(self, spec, prefix):
configure('--prefix=' + prefix) configure('--prefix=' + prefix)

View File

@ -36,12 +36,15 @@ class Cryptopp(Package):
""" """
homepage = "http://www.cryptopp.com" homepage = "http://www.cryptopp.com"
base_url = "http://www.cryptopp.com"
version('5.6.3', '3c5b70e2ec98b7a24988734446242d07') version('5.6.3', '3c5b70e2ec98b7a24988734446242d07')
version('5.6.2', '7ed022585698df48e65ce9218f6c6a67') version('5.6.2', '7ed022585698df48e65ce9218f6c6a67')
version('5.6.1', '96cbeba0907562b077e26bcffb483828') version('5.6.1', '96cbeba0907562b077e26bcffb483828')
def url_for_version(self, version):
url = "{0}/{1}{2}.zip"
return url.format(self.homepage, self.name, version.joined)
def install(self, spec, prefix): def install(self, spec, prefix):
make() make()
@ -51,7 +54,3 @@ def install(self, spec, prefix):
mkdirp(prefix.lib) mkdirp(prefix.lib)
install('libcryptopp.a', prefix.lib) install('libcryptopp.a', prefix.lib)
def url_for_version(self, version):
version_string = str(version).replace('.', '')
return '%s/cryptopp%s.zip' % (Cryptopp.base_url, version_string)

View File

@ -33,10 +33,6 @@ class Lrslib(Package):
homepage = "http://cgm.cs.mcgill.ca/~avis/C/lrs.html" homepage = "http://cgm.cs.mcgill.ca/~avis/C/lrs.html"
url = "http://cgm.cs.mcgill.ca/~avis/C/lrslib/archive/lrslib-062.tar.gz" url = "http://cgm.cs.mcgill.ca/~avis/C/lrslib/archive/lrslib-062.tar.gz"
def url_for_version(self, version):
return ("http://cgm.cs.mcgill.ca/~avis/C/lrslib/archive/lrslib-%s.tar.gz" %
('0' + str(version).replace('.', '')))
version('6.2', 'be5da7b3b90cc2be628dcade90c5d1b9') version('6.2', 'be5da7b3b90cc2be628dcade90c5d1b9')
version('6.1', '0b3687c8693cd7d1f234a3f65e147551') version('6.1', '0b3687c8693cd7d1f234a3f65e147551')
version('6.0', 'd600a2e62969ad03f7ab2f85f1b3709c') version('6.0', 'd600a2e62969ad03f7ab2f85f1b3709c')
@ -51,6 +47,10 @@ def url_for_version(self, version):
patch("Makefile.spack.patch") patch("Makefile.spack.patch")
def url_for_version(self, version):
url = "http://cgm.cs.mcgill.ca/~avis/C/lrslib/archive/lrslib-0{0}.tar.gz"
return url.format(version.joined)
def install(self, spec, prefix): def install(self, spec, prefix):
# The Makefile isn't portable; use our own instead # The Makefile isn't portable; use our own instead
makeargs = ["-f", "Makefile.spack", makeargs = ["-f", "Makefile.spack",

View File

@ -30,7 +30,7 @@ class Nag(Package):
"""The NAG Fortran Compiler.""" """The NAG Fortran Compiler."""
homepage = "http://www.nag.com/nagware/np.asp" homepage = "http://www.nag.com/nagware/np.asp"
version('6.1', '1e29d9d435b7ccc2842a320150b28ba4') version('6.1', 'f49bd548e0d5e2458b2dabb3ee01341a')
version('6.0', '3fa1e7f7b51ef8a23e6c687cdcad9f96') version('6.0', '3fa1e7f7b51ef8a23e6c687cdcad9f96')
# Licensing # Licensing
@ -43,8 +43,8 @@ class Nag(Package):
def url_for_version(self, version): def url_for_version(self, version):
# TODO: url and checksum are architecture dependent # TODO: url and checksum are architecture dependent
# TODO: We currently only support x86_64 # TODO: We currently only support x86_64
return 'http://www.nag.com/downloads/impl/npl6a%sna_amd64.tgz' % str( url = 'http://www.nag.com/downloads/impl/npl6a{0}na_amd64.tgz'
version).replace('.', '') return url.format(version.joined)
def install(self, spec, prefix): def install(self, spec, prefix):
# Set installation directories # Set installation directories

View File

@ -33,14 +33,14 @@ class Nauty(Package):
homepage = "http://pallini.di.uniroma1.it/index.html" homepage = "http://pallini.di.uniroma1.it/index.html"
url = "http://pallini.di.uniroma1.it/nauty26r7.tar.gz" url = "http://pallini.di.uniroma1.it/nauty26r7.tar.gz"
def url_for_version(self, version):
return ("http://pallini.di.uniroma1.it/nauty%s.tar.gz" %
str(version).replace('.', ''))
version('2.6r7', 'b2b18e03ea7698db3fbe06c5d76ad8fe') version('2.6r7', 'b2b18e03ea7698db3fbe06c5d76ad8fe')
version('2.6r5', '91b03a7b069962e94fc9aac8831ce8d2') version('2.6r5', '91b03a7b069962e94fc9aac8831ce8d2')
version('2.5r9', 'e8ecd08b0892a1fb13329c147f08de6d') version('2.5r9', 'e8ecd08b0892a1fb13329c147f08de6d')
def url_for_version(self, version):
url = "http://pallini.di.uniroma1.it/nauty{0}.tar.gz"
return url.format(version.joined)
def install(self, spec, prefix): def install(self, spec, prefix):
configure('--prefix=%s' % prefix) configure('--prefix=%s' % prefix)
make() make()