_version.py 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. """Utility to compare (NumPy) version strings.
  2. The NumpyVersion class allows properly comparing numpy version strings.
  3. The LooseVersion and StrictVersion classes that distutils provides don't
  4. work; they don't recognize anything like alpha/beta/rc/dev versions.
  5. """
  6. import re
  7. __all__ = ['NumpyVersion']
  8. class NumpyVersion():
  9. """Parse and compare numpy version strings.
  10. NumPy has the following versioning scheme (numbers given are examples; they
  11. can be > 9 in principle):
  12. - Released version: '1.8.0', '1.8.1', etc.
  13. - Alpha: '1.8.0a1', '1.8.0a2', etc.
  14. - Beta: '1.8.0b1', '1.8.0b2', etc.
  15. - Release candidates: '1.8.0rc1', '1.8.0rc2', etc.
  16. - Development versions: '1.8.0.dev-f1234afa' (git commit hash appended)
  17. - Development versions after a1: '1.8.0a1.dev-f1234afa',
  18. '1.8.0b2.dev-f1234afa',
  19. '1.8.1rc1.dev-f1234afa', etc.
  20. - Development versions (no git hash available): '1.8.0.dev-Unknown'
  21. Comparing needs to be done against a valid version string or other
  22. `NumpyVersion` instance. Note that all development versions of the same
  23. (pre-)release compare equal.
  24. .. versionadded:: 1.9.0
  25. Parameters
  26. ----------
  27. vstring : str
  28. NumPy version string (``np.__version__``).
  29. Examples
  30. --------
  31. >>> from numpy.lib import NumpyVersion
  32. >>> if NumpyVersion(np.__version__) < '1.7.0':
  33. ... print('skip')
  34. >>> # skip
  35. >>> NumpyVersion('1.7') # raises ValueError, add ".0"
  36. Traceback (most recent call last):
  37. ...
  38. ValueError: Not a valid numpy version string
  39. """
  40. def __init__(self, vstring):
  41. self.vstring = vstring
  42. ver_main = re.match(r'\d+\.\d+\.\d+', vstring)
  43. if not ver_main:
  44. raise ValueError("Not a valid numpy version string")
  45. self.version = ver_main.group()
  46. self.major, self.minor, self.bugfix = [int(x) for x in
  47. self.version.split('.')]
  48. if len(vstring) == ver_main.end():
  49. self.pre_release = 'final'
  50. else:
  51. alpha = re.match(r'a\d', vstring[ver_main.end():])
  52. beta = re.match(r'b\d', vstring[ver_main.end():])
  53. rc = re.match(r'rc\d', vstring[ver_main.end():])
  54. pre_rel = [m for m in [alpha, beta, rc] if m is not None]
  55. if pre_rel:
  56. self.pre_release = pre_rel[0].group()
  57. else:
  58. self.pre_release = ''
  59. self.is_devversion = bool(re.search(r'.dev', vstring))
  60. def _compare_version(self, other):
  61. """Compare major.minor.bugfix"""
  62. if self.major == other.major:
  63. if self.minor == other.minor:
  64. if self.bugfix == other.bugfix:
  65. vercmp = 0
  66. elif self.bugfix > other.bugfix:
  67. vercmp = 1
  68. else:
  69. vercmp = -1
  70. elif self.minor > other.minor:
  71. vercmp = 1
  72. else:
  73. vercmp = -1
  74. elif self.major > other.major:
  75. vercmp = 1
  76. else:
  77. vercmp = -1
  78. return vercmp
  79. def _compare_pre_release(self, other):
  80. """Compare alpha/beta/rc/final."""
  81. if self.pre_release == other.pre_release:
  82. vercmp = 0
  83. elif self.pre_release == 'final':
  84. vercmp = 1
  85. elif other.pre_release == 'final':
  86. vercmp = -1
  87. elif self.pre_release > other.pre_release:
  88. vercmp = 1
  89. else:
  90. vercmp = -1
  91. return vercmp
  92. def _compare(self, other):
  93. if not isinstance(other, (str, NumpyVersion)):
  94. raise ValueError("Invalid object to compare with NumpyVersion.")
  95. if isinstance(other, str):
  96. other = NumpyVersion(other)
  97. vercmp = self._compare_version(other)
  98. if vercmp == 0:
  99. # Same x.y.z version, check for alpha/beta/rc
  100. vercmp = self._compare_pre_release(other)
  101. if vercmp == 0:
  102. # Same version and same pre-release, check if dev version
  103. if self.is_devversion is other.is_devversion:
  104. vercmp = 0
  105. elif self.is_devversion:
  106. vercmp = -1
  107. else:
  108. vercmp = 1
  109. return vercmp
  110. def __lt__(self, other):
  111. return self._compare(other) < 0
  112. def __le__(self, other):
  113. return self._compare(other) <= 0
  114. def __eq__(self, other):
  115. return self._compare(other) == 0
  116. def __ne__(self, other):
  117. return self._compare(other) != 0
  118. def __gt__(self, other):
  119. return self._compare(other) > 0
  120. def __ge__(self, other):
  121. return self._compare(other) >= 0
  122. def __repr__(self):
  123. return "NumpyVersion(%s)" % self.vstring