Updated script that can be controled by Nodejs web app
This commit is contained in:
87
lib/python3.13/site-packages/numpy/_utils/__init__.py
Normal file
87
lib/python3.13/site-packages/numpy/_utils/__init__.py
Normal file
@ -0,0 +1,87 @@
|
||||
"""
|
||||
This is a module for defining private helpers which do not depend on the
|
||||
rest of NumPy.
|
||||
|
||||
Everything in here must be self-contained so that it can be
|
||||
imported anywhere else without creating circular imports.
|
||||
If a utility requires the import of NumPy, it probably belongs
|
||||
in ``numpy._core``.
|
||||
"""
|
||||
|
||||
import functools
|
||||
import warnings
|
||||
from ._convertions import asunicode, asbytes
|
||||
|
||||
|
||||
def set_module(module):
|
||||
"""Private decorator for overriding __module__ on a function or class.
|
||||
|
||||
Example usage::
|
||||
|
||||
@set_module('numpy')
|
||||
def example():
|
||||
pass
|
||||
|
||||
assert example.__module__ == 'numpy'
|
||||
"""
|
||||
def decorator(func):
|
||||
if module is not None:
|
||||
func.__module__ = module
|
||||
return func
|
||||
return decorator
|
||||
|
||||
|
||||
def _rename_parameter(old_names, new_names, dep_version=None):
|
||||
"""
|
||||
Generate decorator for backward-compatible keyword renaming.
|
||||
|
||||
Apply the decorator generated by `_rename_parameter` to functions with a
|
||||
renamed parameter to maintain backward-compatibility.
|
||||
|
||||
After decoration, the function behaves as follows:
|
||||
If only the new parameter is passed into the function, behave as usual.
|
||||
If only the old parameter is passed into the function (as a keyword), raise
|
||||
a DeprecationWarning if `dep_version` is provided, and behave as usual
|
||||
otherwise.
|
||||
If both old and new parameters are passed into the function, raise a
|
||||
DeprecationWarning if `dep_version` is provided, and raise the appropriate
|
||||
TypeError (function got multiple values for argument).
|
||||
|
||||
Parameters
|
||||
----------
|
||||
old_names : list of str
|
||||
Old names of parameters
|
||||
new_name : list of str
|
||||
New names of parameters
|
||||
dep_version : str, optional
|
||||
Version of NumPy in which old parameter was deprecated in the format
|
||||
'X.Y.Z'. If supplied, the deprecation message will indicate that
|
||||
support for the old parameter will be removed in version 'X.Y+2.Z'
|
||||
|
||||
Notes
|
||||
-----
|
||||
Untested with functions that accept *args. Probably won't work as written.
|
||||
|
||||
"""
|
||||
def decorator(fun):
|
||||
@functools.wraps(fun)
|
||||
def wrapper(*args, **kwargs):
|
||||
for old_name, new_name in zip(old_names, new_names):
|
||||
if old_name in kwargs:
|
||||
if dep_version:
|
||||
end_version = dep_version.split('.')
|
||||
end_version[1] = str(int(end_version[1]) + 2)
|
||||
end_version = '.'.join(end_version)
|
||||
msg = (f"Use of keyword argument `{old_name}` is "
|
||||
f"deprecated and replaced by `{new_name}`. "
|
||||
f"Support for `{old_name}` will be removed "
|
||||
f"in NumPy {end_version}.")
|
||||
warnings.warn(msg, DeprecationWarning, stacklevel=2)
|
||||
if new_name in kwargs:
|
||||
msg = (f"{fun.__name__}() got multiple values for "
|
||||
f"argument now known as `{new_name}`")
|
||||
raise TypeError(msg)
|
||||
kwargs[new_name] = kwargs.pop(old_name)
|
||||
return fun(*args, **kwargs)
|
||||
return wrapper
|
||||
return decorator
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
18
lib/python3.13/site-packages/numpy/_utils/_convertions.py
Normal file
18
lib/python3.13/site-packages/numpy/_utils/_convertions.py
Normal file
@ -0,0 +1,18 @@
|
||||
"""
|
||||
A set of methods retained from np.compat module that
|
||||
are still used across codebase.
|
||||
"""
|
||||
|
||||
__all__ = ["asunicode", "asbytes"]
|
||||
|
||||
|
||||
def asunicode(s):
|
||||
if isinstance(s, bytes):
|
||||
return s.decode('latin1')
|
||||
return str(s)
|
||||
|
||||
|
||||
def asbytes(s):
|
||||
if isinstance(s, bytes):
|
||||
return s
|
||||
return str(s).encode('latin1')
|
191
lib/python3.13/site-packages/numpy/_utils/_inspect.py
Normal file
191
lib/python3.13/site-packages/numpy/_utils/_inspect.py
Normal file
@ -0,0 +1,191 @@
|
||||
"""Subset of inspect module from upstream python
|
||||
|
||||
We use this instead of upstream because upstream inspect is slow to import, and
|
||||
significantly contributes to numpy import times. Importing this copy has almost
|
||||
no overhead.
|
||||
|
||||
"""
|
||||
import types
|
||||
|
||||
__all__ = ['getargspec', 'formatargspec']
|
||||
|
||||
# ----------------------------------------------------------- type-checking
|
||||
def ismethod(object):
|
||||
"""Return true if the object is an instance method.
|
||||
|
||||
Instance method objects provide these attributes:
|
||||
__doc__ documentation string
|
||||
__name__ name with which this method was defined
|
||||
im_class class object in which this method belongs
|
||||
im_func function object containing implementation of method
|
||||
im_self instance to which this method is bound, or None
|
||||
|
||||
"""
|
||||
return isinstance(object, types.MethodType)
|
||||
|
||||
def isfunction(object):
|
||||
"""Return true if the object is a user-defined function.
|
||||
|
||||
Function objects provide these attributes:
|
||||
__doc__ documentation string
|
||||
__name__ name with which this function was defined
|
||||
func_code code object containing compiled function bytecode
|
||||
func_defaults tuple of any default values for arguments
|
||||
func_doc (same as __doc__)
|
||||
func_globals global namespace in which this function was defined
|
||||
func_name (same as __name__)
|
||||
|
||||
"""
|
||||
return isinstance(object, types.FunctionType)
|
||||
|
||||
def iscode(object):
|
||||
"""Return true if the object is a code object.
|
||||
|
||||
Code objects provide these attributes:
|
||||
co_argcount number of arguments (not including * or ** args)
|
||||
co_code string of raw compiled bytecode
|
||||
co_consts tuple of constants used in the bytecode
|
||||
co_filename name of file in which this code object was created
|
||||
co_firstlineno number of first line in Python source code
|
||||
co_flags bitmap: 1=optimized | 2=newlocals | 4=*arg | 8=**arg
|
||||
co_lnotab encoded mapping of line numbers to bytecode indices
|
||||
co_name name with which this code object was defined
|
||||
co_names tuple of names of local variables
|
||||
co_nlocals number of local variables
|
||||
co_stacksize virtual machine stack space required
|
||||
co_varnames tuple of names of arguments and local variables
|
||||
|
||||
"""
|
||||
return isinstance(object, types.CodeType)
|
||||
|
||||
# ------------------------------------------------ argument list extraction
|
||||
# These constants are from Python's compile.h.
|
||||
CO_OPTIMIZED, CO_NEWLOCALS, CO_VARARGS, CO_VARKEYWORDS = 1, 2, 4, 8
|
||||
|
||||
def getargs(co):
|
||||
"""Get information about the arguments accepted by a code object.
|
||||
|
||||
Three things are returned: (args, varargs, varkw), where 'args' is
|
||||
a list of argument names (possibly containing nested lists), and
|
||||
'varargs' and 'varkw' are the names of the * and ** arguments or None.
|
||||
|
||||
"""
|
||||
|
||||
if not iscode(co):
|
||||
raise TypeError('arg is not a code object')
|
||||
|
||||
nargs = co.co_argcount
|
||||
names = co.co_varnames
|
||||
args = list(names[:nargs])
|
||||
|
||||
# The following acrobatics are for anonymous (tuple) arguments.
|
||||
# Which we do not need to support, so remove to avoid importing
|
||||
# the dis module.
|
||||
for i in range(nargs):
|
||||
if args[i][:1] in ['', '.']:
|
||||
raise TypeError("tuple function arguments are not supported")
|
||||
varargs = None
|
||||
if co.co_flags & CO_VARARGS:
|
||||
varargs = co.co_varnames[nargs]
|
||||
nargs = nargs + 1
|
||||
varkw = None
|
||||
if co.co_flags & CO_VARKEYWORDS:
|
||||
varkw = co.co_varnames[nargs]
|
||||
return args, varargs, varkw
|
||||
|
||||
def getargspec(func):
|
||||
"""Get the names and default values of a function's arguments.
|
||||
|
||||
A tuple of four things is returned: (args, varargs, varkw, defaults).
|
||||
'args' is a list of the argument names (it may contain nested lists).
|
||||
'varargs' and 'varkw' are the names of the * and ** arguments or None.
|
||||
'defaults' is an n-tuple of the default values of the last n arguments.
|
||||
|
||||
"""
|
||||
|
||||
if ismethod(func):
|
||||
func = func.__func__
|
||||
if not isfunction(func):
|
||||
raise TypeError('arg is not a Python function')
|
||||
args, varargs, varkw = getargs(func.__code__)
|
||||
return args, varargs, varkw, func.__defaults__
|
||||
|
||||
def getargvalues(frame):
|
||||
"""Get information about arguments passed into a particular frame.
|
||||
|
||||
A tuple of four things is returned: (args, varargs, varkw, locals).
|
||||
'args' is a list of the argument names (it may contain nested lists).
|
||||
'varargs' and 'varkw' are the names of the * and ** arguments or None.
|
||||
'locals' is the locals dictionary of the given frame.
|
||||
|
||||
"""
|
||||
args, varargs, varkw = getargs(frame.f_code)
|
||||
return args, varargs, varkw, frame.f_locals
|
||||
|
||||
def joinseq(seq):
|
||||
if len(seq) == 1:
|
||||
return '(' + seq[0] + ',)'
|
||||
else:
|
||||
return '(' + ', '.join(seq) + ')'
|
||||
|
||||
def strseq(object, convert, join=joinseq):
|
||||
"""Recursively walk a sequence, stringifying each element.
|
||||
|
||||
"""
|
||||
if type(object) in [list, tuple]:
|
||||
return join([strseq(_o, convert, join) for _o in object])
|
||||
else:
|
||||
return convert(object)
|
||||
|
||||
def formatargspec(args, varargs=None, varkw=None, defaults=None,
|
||||
formatarg=str,
|
||||
formatvarargs=lambda name: '*' + name,
|
||||
formatvarkw=lambda name: '**' + name,
|
||||
formatvalue=lambda value: '=' + repr(value),
|
||||
join=joinseq):
|
||||
"""Format an argument spec from the 4 values returned by getargspec.
|
||||
|
||||
The first four arguments are (args, varargs, varkw, defaults). The
|
||||
other four arguments are the corresponding optional formatting functions
|
||||
that are called to turn names and values into strings. The ninth
|
||||
argument is an optional function to format the sequence of arguments.
|
||||
|
||||
"""
|
||||
specs = []
|
||||
if defaults:
|
||||
firstdefault = len(args) - len(defaults)
|
||||
for i in range(len(args)):
|
||||
spec = strseq(args[i], formatarg, join)
|
||||
if defaults and i >= firstdefault:
|
||||
spec = spec + formatvalue(defaults[i - firstdefault])
|
||||
specs.append(spec)
|
||||
if varargs is not None:
|
||||
specs.append(formatvarargs(varargs))
|
||||
if varkw is not None:
|
||||
specs.append(formatvarkw(varkw))
|
||||
return '(' + ', '.join(specs) + ')'
|
||||
|
||||
def formatargvalues(args, varargs, varkw, locals,
|
||||
formatarg=str,
|
||||
formatvarargs=lambda name: '*' + name,
|
||||
formatvarkw=lambda name: '**' + name,
|
||||
formatvalue=lambda value: '=' + repr(value),
|
||||
join=joinseq):
|
||||
"""Format an argument spec from the 4 values returned by getargvalues.
|
||||
|
||||
The first four arguments are (args, varargs, varkw, locals). The
|
||||
next four arguments are the corresponding optional formatting functions
|
||||
that are called to turn names and values into strings. The ninth
|
||||
argument is an optional function to format the sequence of arguments.
|
||||
|
||||
"""
|
||||
def convert(name, locals=locals,
|
||||
formatarg=formatarg, formatvalue=formatvalue):
|
||||
return formatarg(name) + formatvalue(locals[name])
|
||||
specs = [strseq(arg, convert, join) for arg in args]
|
||||
|
||||
if varargs:
|
||||
specs.append(formatvarargs(varargs) + formatvalue(locals[varargs]))
|
||||
if varkw:
|
||||
specs.append(formatvarkw(varkw) + formatvalue(locals[varkw]))
|
||||
return '(' + ', '.join(specs) + ')'
|
487
lib/python3.13/site-packages/numpy/_utils/_pep440.py
Normal file
487
lib/python3.13/site-packages/numpy/_utils/_pep440.py
Normal file
@ -0,0 +1,487 @@
|
||||
"""Utility to compare pep440 compatible version strings.
|
||||
|
||||
The LooseVersion and StrictVersion classes that distutils provides don't
|
||||
work; they don't recognize anything like alpha/beta/rc/dev versions.
|
||||
"""
|
||||
|
||||
# Copyright (c) Donald Stufft and individual contributors.
|
||||
# All rights reserved.
|
||||
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
|
||||
# 1. Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
import collections
|
||||
import itertools
|
||||
import re
|
||||
|
||||
|
||||
__all__ = [
|
||||
"parse", "Version", "LegacyVersion", "InvalidVersion", "VERSION_PATTERN",
|
||||
]
|
||||
|
||||
|
||||
# BEGIN packaging/_structures.py
|
||||
|
||||
|
||||
class Infinity:
|
||||
def __repr__(self):
|
||||
return "Infinity"
|
||||
|
||||
def __hash__(self):
|
||||
return hash(repr(self))
|
||||
|
||||
def __lt__(self, other):
|
||||
return False
|
||||
|
||||
def __le__(self, other):
|
||||
return False
|
||||
|
||||
def __eq__(self, other):
|
||||
return isinstance(other, self.__class__)
|
||||
|
||||
def __ne__(self, other):
|
||||
return not isinstance(other, self.__class__)
|
||||
|
||||
def __gt__(self, other):
|
||||
return True
|
||||
|
||||
def __ge__(self, other):
|
||||
return True
|
||||
|
||||
def __neg__(self):
|
||||
return NegativeInfinity
|
||||
|
||||
|
||||
Infinity = Infinity()
|
||||
|
||||
|
||||
class NegativeInfinity:
|
||||
def __repr__(self):
|
||||
return "-Infinity"
|
||||
|
||||
def __hash__(self):
|
||||
return hash(repr(self))
|
||||
|
||||
def __lt__(self, other):
|
||||
return True
|
||||
|
||||
def __le__(self, other):
|
||||
return True
|
||||
|
||||
def __eq__(self, other):
|
||||
return isinstance(other, self.__class__)
|
||||
|
||||
def __ne__(self, other):
|
||||
return not isinstance(other, self.__class__)
|
||||
|
||||
def __gt__(self, other):
|
||||
return False
|
||||
|
||||
def __ge__(self, other):
|
||||
return False
|
||||
|
||||
def __neg__(self):
|
||||
return Infinity
|
||||
|
||||
|
||||
# BEGIN packaging/version.py
|
||||
|
||||
|
||||
NegativeInfinity = NegativeInfinity()
|
||||
|
||||
_Version = collections.namedtuple(
|
||||
"_Version",
|
||||
["epoch", "release", "dev", "pre", "post", "local"],
|
||||
)
|
||||
|
||||
|
||||
def parse(version):
|
||||
"""
|
||||
Parse the given version string and return either a :class:`Version` object
|
||||
or a :class:`LegacyVersion` object depending on if the given version is
|
||||
a valid PEP 440 version or a legacy version.
|
||||
"""
|
||||
try:
|
||||
return Version(version)
|
||||
except InvalidVersion:
|
||||
return LegacyVersion(version)
|
||||
|
||||
|
||||
class InvalidVersion(ValueError):
|
||||
"""
|
||||
An invalid version was found, users should refer to PEP 440.
|
||||
"""
|
||||
|
||||
|
||||
class _BaseVersion:
|
||||
|
||||
def __hash__(self):
|
||||
return hash(self._key)
|
||||
|
||||
def __lt__(self, other):
|
||||
return self._compare(other, lambda s, o: s < o)
|
||||
|
||||
def __le__(self, other):
|
||||
return self._compare(other, lambda s, o: s <= o)
|
||||
|
||||
def __eq__(self, other):
|
||||
return self._compare(other, lambda s, o: s == o)
|
||||
|
||||
def __ge__(self, other):
|
||||
return self._compare(other, lambda s, o: s >= o)
|
||||
|
||||
def __gt__(self, other):
|
||||
return self._compare(other, lambda s, o: s > o)
|
||||
|
||||
def __ne__(self, other):
|
||||
return self._compare(other, lambda s, o: s != o)
|
||||
|
||||
def _compare(self, other, method):
|
||||
if not isinstance(other, _BaseVersion):
|
||||
return NotImplemented
|
||||
|
||||
return method(self._key, other._key)
|
||||
|
||||
|
||||
class LegacyVersion(_BaseVersion):
|
||||
|
||||
def __init__(self, version):
|
||||
self._version = str(version)
|
||||
self._key = _legacy_cmpkey(self._version)
|
||||
|
||||
def __str__(self):
|
||||
return self._version
|
||||
|
||||
def __repr__(self):
|
||||
return "<LegacyVersion({0})>".format(repr(str(self)))
|
||||
|
||||
@property
|
||||
def public(self):
|
||||
return self._version
|
||||
|
||||
@property
|
||||
def base_version(self):
|
||||
return self._version
|
||||
|
||||
@property
|
||||
def local(self):
|
||||
return None
|
||||
|
||||
@property
|
||||
def is_prerelease(self):
|
||||
return False
|
||||
|
||||
@property
|
||||
def is_postrelease(self):
|
||||
return False
|
||||
|
||||
|
||||
_legacy_version_component_re = re.compile(
|
||||
r"(\d+ | [a-z]+ | \.| -)", re.VERBOSE,
|
||||
)
|
||||
|
||||
_legacy_version_replacement_map = {
|
||||
"pre": "c", "preview": "c", "-": "final-", "rc": "c", "dev": "@",
|
||||
}
|
||||
|
||||
|
||||
def _parse_version_parts(s):
|
||||
for part in _legacy_version_component_re.split(s):
|
||||
part = _legacy_version_replacement_map.get(part, part)
|
||||
|
||||
if not part or part == ".":
|
||||
continue
|
||||
|
||||
if part[:1] in "0123456789":
|
||||
# pad for numeric comparison
|
||||
yield part.zfill(8)
|
||||
else:
|
||||
yield "*" + part
|
||||
|
||||
# ensure that alpha/beta/candidate are before final
|
||||
yield "*final"
|
||||
|
||||
|
||||
def _legacy_cmpkey(version):
|
||||
# We hardcode an epoch of -1 here. A PEP 440 version can only have an epoch
|
||||
# greater than or equal to 0. This will effectively put the LegacyVersion,
|
||||
# which uses the defacto standard originally implemented by setuptools,
|
||||
# as before all PEP 440 versions.
|
||||
epoch = -1
|
||||
|
||||
# This scheme is taken from pkg_resources.parse_version setuptools prior to
|
||||
# its adoption of the packaging library.
|
||||
parts = []
|
||||
for part in _parse_version_parts(version.lower()):
|
||||
if part.startswith("*"):
|
||||
# remove "-" before a prerelease tag
|
||||
if part < "*final":
|
||||
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)
|
||||
parts = tuple(parts)
|
||||
|
||||
return epoch, parts
|
||||
|
||||
|
||||
# Deliberately not anchored to the start and end of the string, to make it
|
||||
# easier for 3rd party code to reuse
|
||||
VERSION_PATTERN = r"""
|
||||
v?
|
||||
(?:
|
||||
(?:(?P<epoch>[0-9]+)!)? # epoch
|
||||
(?P<release>[0-9]+(?:\.[0-9]+)*) # release segment
|
||||
(?P<pre> # pre-release
|
||||
[-_\.]?
|
||||
(?P<pre_l>(a|b|c|rc|alpha|beta|pre|preview))
|
||||
[-_\.]?
|
||||
(?P<pre_n>[0-9]+)?
|
||||
)?
|
||||
(?P<post> # post release
|
||||
(?:-(?P<post_n1>[0-9]+))
|
||||
|
|
||||
(?:
|
||||
[-_\.]?
|
||||
(?P<post_l>post|rev|r)
|
||||
[-_\.]?
|
||||
(?P<post_n2>[0-9]+)?
|
||||
)
|
||||
)?
|
||||
(?P<dev> # dev release
|
||||
[-_\.]?
|
||||
(?P<dev_l>dev)
|
||||
[-_\.]?
|
||||
(?P<dev_n>[0-9]+)?
|
||||
)?
|
||||
)
|
||||
(?:\+(?P<local>[a-z0-9]+(?:[-_\.][a-z0-9]+)*))? # local version
|
||||
"""
|
||||
|
||||
|
||||
class Version(_BaseVersion):
|
||||
|
||||
_regex = re.compile(
|
||||
r"^\s*" + VERSION_PATTERN + r"\s*$",
|
||||
re.VERBOSE | re.IGNORECASE,
|
||||
)
|
||||
|
||||
def __init__(self, version):
|
||||
# Validate the version and parse it into pieces
|
||||
match = self._regex.search(version)
|
||||
if not match:
|
||||
raise InvalidVersion("Invalid version: '{0}'".format(version))
|
||||
|
||||
# Store the parsed out pieces of the version
|
||||
self._version = _Version(
|
||||
epoch=int(match.group("epoch")) if match.group("epoch") else 0,
|
||||
release=tuple(int(i) for i in match.group("release").split(".")),
|
||||
pre=_parse_letter_version(
|
||||
match.group("pre_l"),
|
||||
match.group("pre_n"),
|
||||
),
|
||||
post=_parse_letter_version(
|
||||
match.group("post_l"),
|
||||
match.group("post_n1") or match.group("post_n2"),
|
||||
),
|
||||
dev=_parse_letter_version(
|
||||
match.group("dev_l"),
|
||||
match.group("dev_n"),
|
||||
),
|
||||
local=_parse_local_version(match.group("local")),
|
||||
)
|
||||
|
||||
# Generate a key which will be used for sorting
|
||||
self._key = _cmpkey(
|
||||
self._version.epoch,
|
||||
self._version.release,
|
||||
self._version.pre,
|
||||
self._version.post,
|
||||
self._version.dev,
|
||||
self._version.local,
|
||||
)
|
||||
|
||||
def __repr__(self):
|
||||
return "<Version({0})>".format(repr(str(self)))
|
||||
|
||||
def __str__(self):
|
||||
parts = []
|
||||
|
||||
# Epoch
|
||||
if self._version.epoch != 0:
|
||||
parts.append("{0}!".format(self._version.epoch))
|
||||
|
||||
# Release segment
|
||||
parts.append(".".join(str(x) for x in self._version.release))
|
||||
|
||||
# Pre-release
|
||||
if self._version.pre is not None:
|
||||
parts.append("".join(str(x) for x in self._version.pre))
|
||||
|
||||
# Post-release
|
||||
if self._version.post is not None:
|
||||
parts.append(".post{0}".format(self._version.post[1]))
|
||||
|
||||
# Development release
|
||||
if self._version.dev is not None:
|
||||
parts.append(".dev{0}".format(self._version.dev[1]))
|
||||
|
||||
# Local version segment
|
||||
if self._version.local is not None:
|
||||
parts.append(
|
||||
"+{0}".format(".".join(str(x) for x in self._version.local))
|
||||
)
|
||||
|
||||
return "".join(parts)
|
||||
|
||||
@property
|
||||
def public(self):
|
||||
return str(self).split("+", 1)[0]
|
||||
|
||||
@property
|
||||
def base_version(self):
|
||||
parts = []
|
||||
|
||||
# Epoch
|
||||
if self._version.epoch != 0:
|
||||
parts.append("{0}!".format(self._version.epoch))
|
||||
|
||||
# Release segment
|
||||
parts.append(".".join(str(x) for x in self._version.release))
|
||||
|
||||
return "".join(parts)
|
||||
|
||||
@property
|
||||
def local(self):
|
||||
version_string = str(self)
|
||||
if "+" in version_string:
|
||||
return version_string.split("+", 1)[1]
|
||||
|
||||
@property
|
||||
def is_prerelease(self):
|
||||
return bool(self._version.dev or self._version.pre)
|
||||
|
||||
@property
|
||||
def is_postrelease(self):
|
||||
return bool(self._version.post)
|
||||
|
||||
|
||||
def _parse_letter_version(letter, number):
|
||||
if letter:
|
||||
# We assume there is an implicit 0 in a pre-release if there is
|
||||
# no numeral associated with it.
|
||||
if number is None:
|
||||
number = 0
|
||||
|
||||
# We normalize any letters to their lower-case form
|
||||
letter = letter.lower()
|
||||
|
||||
# We consider some words to be alternate spellings of other words and
|
||||
# in those cases we want to normalize the spellings to our preferred
|
||||
# spelling.
|
||||
if letter == "alpha":
|
||||
letter = "a"
|
||||
elif letter == "beta":
|
||||
letter = "b"
|
||||
elif letter in ["c", "pre", "preview"]:
|
||||
letter = "rc"
|
||||
elif letter in ["rev", "r"]:
|
||||
letter = "post"
|
||||
|
||||
return letter, int(number)
|
||||
if not letter and number:
|
||||
# We assume that if we are given a number but not given a letter,
|
||||
# then this is using the implicit post release syntax (e.g., 1.0-1)
|
||||
letter = "post"
|
||||
|
||||
return letter, int(number)
|
||||
|
||||
|
||||
_local_version_seperators = re.compile(r"[\._-]")
|
||||
|
||||
|
||||
def _parse_local_version(local):
|
||||
"""
|
||||
Takes a string like abc.1.twelve and turns it into ("abc", 1, "twelve").
|
||||
"""
|
||||
if local is not None:
|
||||
return tuple(
|
||||
part.lower() if not part.isdigit() else int(part)
|
||||
for part in _local_version_seperators.split(local)
|
||||
)
|
||||
|
||||
|
||||
def _cmpkey(epoch, release, pre, post, dev, local):
|
||||
# When we compare a release version, we want to compare it with all of the
|
||||
# trailing zeros removed. So we'll use a reverse the list, drop all the now
|
||||
# leading zeros until we come to something non-zero, then take the rest,
|
||||
# re-reverse it back into the correct order, and make it a tuple and use
|
||||
# that for our sorting key.
|
||||
release = tuple(
|
||||
reversed(list(
|
||||
itertools.dropwhile(
|
||||
lambda x: x == 0,
|
||||
reversed(release),
|
||||
)
|
||||
))
|
||||
)
|
||||
|
||||
# We need to "trick" the sorting algorithm to put 1.0.dev0 before 1.0a0.
|
||||
# We'll do this by abusing the pre-segment, but we _only_ want to do this
|
||||
# if there is no pre- or a post-segment. If we have one of those, then
|
||||
# the normal sorting rules will handle this case correctly.
|
||||
if pre is None and post is None and dev is not None:
|
||||
pre = -Infinity
|
||||
# Versions without a pre-release (except as noted above) should sort after
|
||||
# those with one.
|
||||
elif pre is None:
|
||||
pre = Infinity
|
||||
|
||||
# Versions without a post-segment should sort before those with one.
|
||||
if post is None:
|
||||
post = -Infinity
|
||||
|
||||
# Versions without a development segment should sort after those with one.
|
||||
if dev is None:
|
||||
dev = Infinity
|
||||
|
||||
if local is None:
|
||||
# Versions without a local segment should sort before those with one.
|
||||
local = -Infinity
|
||||
else:
|
||||
# Versions with a local segment need that segment parsed to implement
|
||||
# the sorting rules in PEP440.
|
||||
# - Alphanumeric segments sort before numeric segments
|
||||
# - Alphanumeric segments sort lexicographically
|
||||
# - Numeric segments sort numerically
|
||||
# - Shorter versions sort before longer versions when the prefixes
|
||||
# match exactly
|
||||
local = tuple(
|
||||
(i, "") if isinstance(i, int) else (-Infinity, i)
|
||||
for i in local
|
||||
)
|
||||
|
||||
return epoch, release, pre, post, dev, local
|
Reference in New Issue
Block a user