Skip to content

Commit

Permalink
bazel: copy in the LooseVersion implementation from setuptools to wor…
Browse files Browse the repository at this point in the history
…k under Python 3.12 (#107)
  • Loading branch information
bpowers authored Apr 6, 2024
1 parent ae77cdb commit bc5cbe2
Showing 1 changed file with 116 additions and 1 deletion.
117 changes: 116 additions & 1 deletion bazel
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ limitations under the License.

import base64
from contextlib import closing
from distutils.version import LooseVersion
import json
import netrc
import os
Expand All @@ -39,6 +38,122 @@ except ImportError:
from urlparse import urlparse
from urllib2 import urlopen, Request


# Version and LooseVersion are from setuptools ( https://github.com/pypa/setuputils )
# and MIT licensed
class Version:
"""Abstract base class for version numbering classes. Just provides
constructor (__init__) and reproducer (__repr__), because those
seem to be the same for all version numbering classes; and route
rich comparisons to _cmp.
"""

def __init__(self, vstring=None):
if vstring:
self.parse(vstring)

def __repr__(self):
return "{} ('{}')".format(self.__class__.__name__, str(self))

def __eq__(self, other):
c = self._cmp(other)
if c is NotImplemented:
return c
return c == 0

def __lt__(self, other):
c = self._cmp(other)
if c is NotImplemented:
return c
return c < 0

def __le__(self, other):
c = self._cmp(other)
if c is NotImplemented:
return c
return c <= 0

def __gt__(self, other):
c = self._cmp(other)
if c is NotImplemented:
return c
return c > 0

def __ge__(self, other):
c = self._cmp(other)
if c is NotImplemented:
return c
return c >= 0

class LooseVersion(Version):

"""Version numbering for anarchists and software realists.
Implements the standard interface for version number classes as
described above. A version number consists of a series of numbers,
separated by either periods or strings of letters. When comparing
version numbers, the numeric components will be compared
numerically, and the alphabetic components lexically. The following
are all valid version numbers, in no particular order:
1.5.1
1.5.2b2
161
3.10a
8.02
3.4j
1996.07.12
3.2.pl0
3.1.1.6
2g6
11g
0.960923
2.2beta29
1.13++
5.5.kw
2.0b1pl0
In fact, there is no such thing as an invalid version number under
this scheme; the rules for comparison are simple and predictable,
but may not always give the results you want (for some definition
of "want").
"""

component_re = re.compile(r'(\d+ | [a-z]+ | \.)', re.VERBOSE)

def parse(self, vstring):
# I've given up on thinking I can reconstruct the version string
# from the parsed tuple -- so I just store the string here for
# use by __str__
self.vstring = vstring
components = [x for x in self.component_re.split(vstring) if x and x != '.']
for i, obj in enumerate(components):
try:
components[i] = int(obj)
except ValueError:
pass

self.version = components

def __str__(self):
return self.vstring

def __repr__(self):
return "LooseVersion ('%s')" % str(self)

def _cmp(self, other):
if isinstance(other, str):
other = LooseVersion(other)
elif not isinstance(other, LooseVersion):
return NotImplemented

if self.version == other.version:
return 0
if self.version < other.version:
return -1
if self.version > other.version:
return 1


ONE_HOUR = 1 * 60 * 60

LATEST_PATTERN = re.compile(r"latest(-(?P<offset>\d+))?$")
Expand Down

0 comments on commit bc5cbe2

Please sign in to comment.