Skip to content

Commit

Permalink
Merge pull request statsmodels#1432 from jseabold/fix-loose-version
Browse files Browse the repository at this point in the history
COMPAT: Add NumpyVersion from scipy
  • Loading branch information
jseabold committed Apr 3, 2014
2 parents 08fbd68 + 1bf9228 commit ccc2ecb
Show file tree
Hide file tree
Showing 3 changed files with 152 additions and 5 deletions.
7 changes: 3 additions & 4 deletions statsmodels/base/model.py
@@ -1,5 +1,3 @@
import distutils.version

import numpy as np
import scipy
from scipy import optimize, stats
Expand Down Expand Up @@ -566,8 +564,9 @@ def _fit_mle_lbfgs(f, score, start_params, fargs, kwargs, disp=True,

# Customize the fmin_l_bfgs_b call according to the scipy version.
# Old scipy does not support maxiter and callback.
scipy_version_curr = distutils.version.LooseVersion(scipy.__version__)
scipy_version_12 = distutils.version.LooseVersion('0.12.0')
from statsmodels.compatnp.np_compat import NumpyVersion
scipy_version_curr = NumpyVersion(scipy.__version__)
scipy_version_12 = NumpyVersion('0.12.0')
if scipy_version_curr < scipy_version_12:
retvals = optimize.fmin_l_bfgs_b(func, start_params, args=fargs,
bounds=bounds, disp=disp,
Expand Down
148 changes: 147 additions & 1 deletion statsmodels/compatnp/np_compat.py
Expand Up @@ -49,7 +49,153 @@

import numpy as np

if np.__version__ < '1.6.2':
try:
from scipy.lib.version import NumpyVersion
except ImportError:
import re
from statsmodels.compatnp.py3k import string_types

class NumpyVersion():
"""Parse and compare numpy version strings.
Numpy has the following versioning scheme (numbers given are examples; they
can be >9) in principle):
- Released version: '1.8.0', '1.8.1', etc.
- Alpha: '1.8.0a1', '1.8.0a2', etc.
- Beta: '1.8.0b1', '1.8.0b2', etc.
- Release candidates: '1.8.0rc1', '1.8.0rc2', etc.
- Development versions: '1.8.0.dev-f1234afa' (git commit hash appended)
- Development versions after a1: '1.8.0a1.dev-f1234afa',
'1.8.0b2.dev-f1234afa',
'1.8.1rc1.dev-f1234afa', etc.
- Development versions (no git hash available): '1.8.0.dev-Unknown'
Comparing needs to be done against a valid version string or other
`NumpyVersion` instance.
Parameters
----------
vstring : str
Numpy version string (``np.__version__``).
Notes
-----
All dev versions of the same (pre-)release compare equal.
Examples
--------
>>> from scipy.lib._version import NumpyVersion
>>> if NumpyVersion(np.__version__) < '1.7.0':
... print('skip')
skip
>>> NumpyVersion('1.7') # raises ValueError, add ".0"
"""
def __init__(self, vstring):
self.vstring = vstring
ver_main = re.match(r'\d[.]\d+[.]\d+', vstring)
if not ver_main:
raise ValueError("Not a valid numpy version string")

self.version = ver_main.group()
self.major, self.minor, self.bugfix = [int(x) for x in
self.version.split('.')]
if len(vstring) == ver_main.end():
self.pre_release = 'final'
else:
alpha = re.match(r'a\d', vstring[ver_main.end():])
beta = re.match(r'b\d', vstring[ver_main.end():])
rc = re.match(r'rc\d', vstring[ver_main.end():])
pre_rel = [m for m in [alpha, beta, rc] if m is not None]
if pre_rel:
self.pre_release = pre_rel[0].group()
else:
self.pre_release = ''

self.is_devversion = bool(re.search(r'.dev-', vstring))

def _compare_version(self, other):
"""Compare major.minor.bugfix"""
if self.major == other.major:
if self.minor == other.minor:
if self.bugfix == other.bugfix:
vercmp = 0
elif self.bugfix > other.bugfix:
vercmp = 1
else:
vercmp = -1
elif self.minor > other.minor:
vercmp = 1
else:
vercmp = -1
elif self.major > other.major:
vercmp = 1
else:
vercmp = -1

return vercmp

def _compare_pre_release(self, other):
"""Compare alpha/beta/rc/final."""
if self.pre_release == other.pre_release:
vercmp = 0
elif self.pre_release == 'final':
vercmp = 1
elif other.pre_release == 'final':
vercmp = -1
elif self.pre_release > other.pre_release:
vercmp = 1
else:
vercmp = -1

return vercmp

def _compare(self, other):
if not isinstance(other, (string_types, NumpyVersion)):
raise ValueError("Invalid object to compare with NumpyVersion.")

if isinstance(other, string_types):
other = NumpyVersion(other)

vercmp = self._compare_version(other)
if vercmp == 0:
# Same x.y.z version, check for alpha/beta/rc
vercmp = self._compare_pre_release(other)
if vercmp == 0:
# Same version and same pre-release, check if dev version
if self.is_devversion is other.is_devversion:
vercmp = 0
elif self.is_devversion:
vercmp = -1
else:
vercmp = 1

return vercmp

def __lt__(self, other):
return self._compare(other) < 0

def __le__(self, other):
return self._compare(other) <= 0

def __eq__(self, other):
return self._compare(other) == 0

def __ne__(self, other):
return self._compare(other) != 0

def __gt__(self, other):
return self._compare(other) > 0

def __ge__(self, other):
return self._compare(other) >= 0

def __repr(self):
return "NumpyVersion(%s)" % self.vstring

if NumpyVersion(np.__version__) < '1.6.2':
npc_unique = np.unique
else:

Expand Down
2 changes: 2 additions & 0 deletions statsmodels/compatnp/py3k.py
Expand Up @@ -11,6 +11,7 @@

if sys.version_info[0] >= 3:
import io
string_types = basestring
bytes = bytes
unicode = str
asunicode = str
Expand All @@ -36,6 +37,7 @@ def open_latin1(filename, mode='r'):
strchar = 'U'
from io import BytesIO, StringIO #statsmodels
else:
string_types = str
bytes = str
unicode = unicode
asbytes = str
Expand Down

0 comments on commit ccc2ecb

Please sign in to comment.