diff options
-rw-r--r-- | pym/euscan/helpers.py | 15 | ||||
-rw-r--r-- | pym/euscan/version.py | 60 |
2 files changed, 66 insertions, 9 deletions
diff --git a/pym/euscan/helpers.py b/pym/euscan/helpers.py index 5629b7b..e50267a 100644 --- a/pym/euscan/helpers.py +++ b/pym/euscan/helpers.py @@ -1,8 +1,6 @@ import os import re -import pkg_resources import errno - import urllib2 import portage @@ -15,10 +13,9 @@ except ImportError: import robotparser import urlparse - -from euscan import CONFIG, BLACKLIST_VERSIONS, ROBOTS_TXT_BLACKLIST_DOMAINS import euscan - +from euscan import CONFIG, BLACKLIST_VERSIONS, ROBOTS_TXT_BLACKLIST_DOMAINS +from euscan.version import parse_version def htop_vercmp(a, b): def fixver(v): @@ -182,8 +179,8 @@ def simple_vercmp(a, b): return r # Fallback - a = pkg_resources.parse_version(a) - b = pkg_resources.parse_version(b) + a = pkg_parse_version(a) + b = pkg_parse_version(b) if a < b: return -1 @@ -198,8 +195,8 @@ def vercmp(package, a, b): def version_is_nightly(a, b): - a = pkg_resources.parse_version(a) - b = pkg_resources.parse_version(b) + a = parse_version(a) + b = parse_version(b) ''' Try to skip nightly builds when not wanted (www-apps/moodle) ''' if len(a) != len(b) and len(b) == 2 and len(b[0]) == len('yyyymmdd'): diff --git a/pym/euscan/version.py b/pym/euscan/version.py new file mode 100644 index 0000000..d836c7e --- /dev/null +++ b/pym/euscan/version.py @@ -0,0 +1,60 @@ +import re + +# Stolen from pkg_resources, but importing it is not a good idea + +component_re = re.compile(r'(\d+ | [a-z]+ | \.| -)', re.VERBOSE) +replace = {'pre':'c', 'preview':'c','-':'final-','rc':'c','dev':'@'}.get + +def _parse_version_parts(s): + for part in component_re.split(s): + part = replace(part,part) + if not part or part=='.': + continue + if part[:1] in '0123456789': + yield part.zfill(8) # pad for numeric comparison + else: + yield '*'+part + + yield '*final' # ensure that alpha/beta/candidate are before final + +def parse_version(s): + """Convert a version string to a chronologically-sortable key + + This is a rough cross between distutils' StrictVersion and LooseVersion; + if you give it versions that would work with StrictVersion, then it behaves + the same; otherwise it acts like a slightly-smarter LooseVersion. It is + *possible* to create pathological version coding schemes that will fool + this parser, but they should be very rare in practice. + + The returned value will be a tuple of strings. Numeric portions of the + version are padded to 8 digits so they will compare numerically, but + without relying on how numbers compare relative to strings. Dots are + dropped, but dashes are retained. Trailing zeros between alpha segments + or dashes are suppressed, so that e.g. "2.4.0" is considered the same as + "2.4". Alphanumeric parts are lower-cased. + + The algorithm assumes that strings like "-" and any alpha string that + alphabetically follows "final" represents a "patch level". So, "2.4-1" + is assumed to be a branch or patch of "2.4", and therefore "2.4.1" is + considered newer than "2.4-1", which in turn is newer than "2.4". + + Strings like "a", "b", "c", "alpha", "beta", "candidate" and so on (that + come before "final" alphabetically) are assumed to be pre-release versions, + so that the version "2.4" is considered newer than "2.4a1". + + Finally, to handle miscellaneous cases, the strings "pre", "preview", and + "rc" are treated as if they were "c", i.e. as though they were release + candidates, and therefore are not as new as a version string that does not + contain them, and "dev" is replaced with an '@' so that it sorts lower than + than any other pre-release tag. + """ + parts = [] + for part in _parse_version_parts(s.lower()): + if part.startswith('*'): + if part<'*final': # remove '-' before a prerelease tag + while parts and parts[-1]=='*final-': parts.pop() + # remove trailing zeros from each series of numeric parts + while parts and parts[-1]=='00000000': + parts.pop() + parts.append(part) + return tuple(parts) |