summaryrefslogtreecommitdiff
path: root/.venv/lib/python3.12/site-packages/numpy/_utils
diff options
context:
space:
mode:
Diffstat (limited to '.venv/lib/python3.12/site-packages/numpy/_utils')
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/_utils/__init__.py95
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/_utils/__init__.pyi30
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/_utils/__pycache__/__init__.cpython-312.pycbin0 -> 4182 bytes
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/_utils/__pycache__/_convertions.cpython-312.pycbin0 -> 836 bytes
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/_utils/__pycache__/_inspect.cpython-312.pycbin0 -> 9433 bytes
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/_utils/__pycache__/_pep440.cpython-312.pycbin0 -> 18748 bytes
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/_utils/_convertions.py18
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/_utils/_convertions.pyi4
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/_utils/_inspect.py192
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/_utils/_inspect.pyi71
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/_utils/_pep440.py486
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/_utils/_pep440.pyi121
12 files changed, 1017 insertions, 0 deletions
diff --git a/.venv/lib/python3.12/site-packages/numpy/_utils/__init__.py b/.venv/lib/python3.12/site-packages/numpy/_utils/__init__.py
new file mode 100644
index 0000000..84ee99d
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/_utils/__init__.py
@@ -0,0 +1,95 @@
+"""
+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 asbytes, asunicode
+
+
+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:
+ if isinstance(func, type):
+ try:
+ func._module_source = func.__module__
+ except (AttributeError):
+ pass
+
+ 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):
+ __tracebackhide__ = True # Hide traceback for py.test
+ 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
diff --git a/.venv/lib/python3.12/site-packages/numpy/_utils/__init__.pyi b/.venv/lib/python3.12/site-packages/numpy/_utils/__init__.pyi
new file mode 100644
index 0000000..f3472df
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/_utils/__init__.pyi
@@ -0,0 +1,30 @@
+from collections.abc import Callable, Iterable
+from typing import Protocol, TypeVar, overload, type_check_only
+
+from _typeshed import IdentityFunction
+
+from ._convertions import asbytes as asbytes
+from ._convertions import asunicode as asunicode
+
+###
+
+_T = TypeVar("_T")
+_HasModuleT = TypeVar("_HasModuleT", bound=_HasModule)
+
+@type_check_only
+class _HasModule(Protocol):
+ __module__: str
+
+###
+
+@overload
+def set_module(module: None) -> IdentityFunction: ...
+@overload
+def set_module(module: str) -> Callable[[_HasModuleT], _HasModuleT]: ...
+
+#
+def _rename_parameter(
+ old_names: Iterable[str],
+ new_names: Iterable[str],
+ dep_version: str | None = None,
+) -> Callable[[Callable[..., _T]], Callable[..., _T]]: ...
diff --git a/.venv/lib/python3.12/site-packages/numpy/_utils/__pycache__/__init__.cpython-312.pyc b/.venv/lib/python3.12/site-packages/numpy/_utils/__pycache__/__init__.cpython-312.pyc
new file mode 100644
index 0000000..8abeda7
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/_utils/__pycache__/__init__.cpython-312.pyc
Binary files differ
diff --git a/.venv/lib/python3.12/site-packages/numpy/_utils/__pycache__/_convertions.cpython-312.pyc b/.venv/lib/python3.12/site-packages/numpy/_utils/__pycache__/_convertions.cpython-312.pyc
new file mode 100644
index 0000000..282ceac
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/_utils/__pycache__/_convertions.cpython-312.pyc
Binary files differ
diff --git a/.venv/lib/python3.12/site-packages/numpy/_utils/__pycache__/_inspect.cpython-312.pyc b/.venv/lib/python3.12/site-packages/numpy/_utils/__pycache__/_inspect.cpython-312.pyc
new file mode 100644
index 0000000..3d69f9b
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/_utils/__pycache__/_inspect.cpython-312.pyc
Binary files differ
diff --git a/.venv/lib/python3.12/site-packages/numpy/_utils/__pycache__/_pep440.cpython-312.pyc b/.venv/lib/python3.12/site-packages/numpy/_utils/__pycache__/_pep440.cpython-312.pyc
new file mode 100644
index 0000000..96f0304
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/_utils/__pycache__/_pep440.cpython-312.pyc
Binary files differ
diff --git a/.venv/lib/python3.12/site-packages/numpy/_utils/_convertions.py b/.venv/lib/python3.12/site-packages/numpy/_utils/_convertions.py
new file mode 100644
index 0000000..ab15a8b
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/_utils/_convertions.py
@@ -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')
diff --git a/.venv/lib/python3.12/site-packages/numpy/_utils/_convertions.pyi b/.venv/lib/python3.12/site-packages/numpy/_utils/_convertions.pyi
new file mode 100644
index 0000000..6cc599a
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/_utils/_convertions.pyi
@@ -0,0 +1,4 @@
+__all__ = ["asbytes", "asunicode"]
+
+def asunicode(s: bytes | str) -> str: ...
+def asbytes(s: bytes | str) -> str: ...
diff --git a/.venv/lib/python3.12/site-packages/numpy/_utils/_inspect.py b/.venv/lib/python3.12/site-packages/numpy/_utils/_inspect.py
new file mode 100644
index 0000000..b499f58
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/_utils/_inspect.py
@@ -0,0 +1,192 @@
+"""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) + ')'
diff --git a/.venv/lib/python3.12/site-packages/numpy/_utils/_inspect.pyi b/.venv/lib/python3.12/site-packages/numpy/_utils/_inspect.pyi
new file mode 100644
index 0000000..d53c3c4
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/_utils/_inspect.pyi
@@ -0,0 +1,71 @@
+import types
+from collections.abc import Callable, Mapping
+from typing import Any, Final, TypeAlias, TypeVar, overload
+
+from _typeshed import SupportsLenAndGetItem
+from typing_extensions import TypeIs
+
+__all__ = ["formatargspec", "getargspec"]
+
+###
+
+_T = TypeVar("_T")
+_RT = TypeVar("_RT")
+
+_StrSeq: TypeAlias = SupportsLenAndGetItem[str]
+_NestedSeq: TypeAlias = list[_T | _NestedSeq[_T]] | tuple[_T | _NestedSeq[_T], ...]
+
+_JoinFunc: TypeAlias = Callable[[list[_T]], _T]
+_FormatFunc: TypeAlias = Callable[[_T], str]
+
+###
+
+CO_OPTIMIZED: Final = 1
+CO_NEWLOCALS: Final = 2
+CO_VARARGS: Final = 4
+CO_VARKEYWORDS: Final = 8
+
+###
+
+def ismethod(object: object) -> TypeIs[types.MethodType]: ...
+def isfunction(object: object) -> TypeIs[types.FunctionType]: ...
+def iscode(object: object) -> TypeIs[types.CodeType]: ...
+
+###
+
+def getargs(co: types.CodeType) -> tuple[list[str], str | None, str | None]: ...
+def getargspec(func: types.MethodType | types.FunctionType) -> tuple[list[str], str | None, str | None, tuple[Any, ...]]: ...
+def getargvalues(frame: types.FrameType) -> tuple[list[str], str | None, str | None, dict[str, Any]]: ...
+
+#
+def joinseq(seq: _StrSeq) -> str: ...
+
+#
+@overload
+def strseq(object: _NestedSeq[str], convert: Callable[[Any], Any], join: _JoinFunc[str] = ...) -> str: ...
+@overload
+def strseq(object: _NestedSeq[_T], convert: Callable[[_T], _RT], join: _JoinFunc[_RT]) -> _RT: ...
+
+#
+def formatargspec(
+ args: _StrSeq,
+ varargs: str | None = None,
+ varkw: str | None = None,
+ defaults: SupportsLenAndGetItem[object] | None = None,
+ formatarg: _FormatFunc[str] = ..., # str
+ formatvarargs: _FormatFunc[str] = ..., # "*{}".format
+ formatvarkw: _FormatFunc[str] = ..., # "**{}".format
+ formatvalue: _FormatFunc[object] = ..., # "={!r}".format
+ join: _JoinFunc[str] = ..., # joinseq
+) -> str: ...
+def formatargvalues(
+ args: _StrSeq,
+ varargs: str | None,
+ varkw: str | None,
+ locals: Mapping[str, object] | None,
+ formatarg: _FormatFunc[str] = ..., # str
+ formatvarargs: _FormatFunc[str] = ..., # "*{}".format
+ formatvarkw: _FormatFunc[str] = ..., # "**{}".format
+ formatvalue: _FormatFunc[object] = ..., # "={!r}".format
+ join: _JoinFunc[str] = ..., # joinseq
+) -> str: ...
diff --git a/.venv/lib/python3.12/site-packages/numpy/_utils/_pep440.py b/.venv/lib/python3.12/site-packages/numpy/_utils/_pep440.py
new file mode 100644
index 0000000..035a069
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/_utils/_pep440.py
@@ -0,0 +1,486 @@
+"""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 f"<LegacyVersion({str(self)!r})>"
+
+ @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(f"Invalid version: '{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 f"<Version({str(self)!r})>"
+
+ def __str__(self):
+ parts = []
+
+ # Epoch
+ if self._version.epoch != 0:
+ parts.append(f"{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(f".post{self._version.post[1]}")
+
+ # Development release
+ if self._version.dev is not None:
+ parts.append(f".dev{self._version.dev[1]}")
+
+ # Local version segment
+ if self._version.local is not None:
+ parts.append(
+ f"+{'.'.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(f"{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
diff --git a/.venv/lib/python3.12/site-packages/numpy/_utils/_pep440.pyi b/.venv/lib/python3.12/site-packages/numpy/_utils/_pep440.pyi
new file mode 100644
index 0000000..29dd4c9
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/_utils/_pep440.pyi
@@ -0,0 +1,121 @@
+import re
+from collections.abc import Callable
+from typing import (
+ Any,
+ ClassVar,
+ Final,
+ Generic,
+ NamedTuple,
+ TypeVar,
+ final,
+ type_check_only,
+)
+from typing import (
+ Literal as L,
+)
+
+from typing_extensions import TypeIs
+
+__all__ = ["VERSION_PATTERN", "InvalidVersion", "LegacyVersion", "Version", "parse"]
+
+###
+
+_CmpKeyT = TypeVar("_CmpKeyT", bound=tuple[object, ...])
+_CmpKeyT_co = TypeVar("_CmpKeyT_co", bound=tuple[object, ...], default=tuple[Any, ...], covariant=True)
+
+###
+
+VERSION_PATTERN: Final[str] = ...
+
+class InvalidVersion(ValueError): ...
+
+@type_check_only
+@final
+class _InfinityType:
+ def __hash__(self) -> int: ...
+ def __eq__(self, other: object, /) -> TypeIs[_InfinityType]: ...
+ def __ne__(self, other: object, /) -> bool: ...
+ def __lt__(self, other: object, /) -> L[False]: ...
+ def __le__(self, other: object, /) -> L[False]: ...
+ def __gt__(self, other: object, /) -> L[True]: ...
+ def __ge__(self, other: object, /) -> L[True]: ...
+ def __neg__(self) -> _NegativeInfinityType: ...
+
+Infinity: Final[_InfinityType] = ...
+
+@type_check_only
+@final
+class _NegativeInfinityType:
+ def __hash__(self) -> int: ...
+ def __eq__(self, other: object, /) -> TypeIs[_NegativeInfinityType]: ...
+ def __ne__(self, other: object, /) -> bool: ...
+ def __lt__(self, other: object, /) -> L[True]: ...
+ def __le__(self, other: object, /) -> L[True]: ...
+ def __gt__(self, other: object, /) -> L[False]: ...
+ def __ge__(self, other: object, /) -> L[False]: ...
+ def __neg__(self) -> _InfinityType: ...
+
+NegativeInfinity: Final[_NegativeInfinityType] = ...
+
+class _Version(NamedTuple):
+ epoch: int
+ release: tuple[int, ...]
+ dev: tuple[str, int] | None
+ pre: tuple[str, int] | None
+ post: tuple[str, int] | None
+ local: tuple[str | int, ...] | None
+
+class _BaseVersion(Generic[_CmpKeyT_co]):
+ _key: _CmpKeyT_co
+ def __hash__(self) -> int: ...
+ def __eq__(self, other: _BaseVersion, /) -> bool: ... # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride]
+ def __ne__(self, other: _BaseVersion, /) -> bool: ... # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride]
+ def __lt__(self, other: _BaseVersion, /) -> bool: ...
+ def __le__(self, other: _BaseVersion, /) -> bool: ...
+ def __ge__(self, other: _BaseVersion, /) -> bool: ...
+ def __gt__(self, other: _BaseVersion, /) -> bool: ...
+ def _compare(self, /, other: _BaseVersion[_CmpKeyT], method: Callable[[_CmpKeyT_co, _CmpKeyT], bool]) -> bool: ...
+
+class LegacyVersion(_BaseVersion[tuple[L[-1], tuple[str, ...]]]):
+ _version: Final[str]
+ def __init__(self, /, version: str) -> None: ...
+ @property
+ def public(self) -> str: ...
+ @property
+ def base_version(self) -> str: ...
+ @property
+ def local(self) -> None: ...
+ @property
+ def is_prerelease(self) -> L[False]: ...
+ @property
+ def is_postrelease(self) -> L[False]: ...
+
+class Version(
+ _BaseVersion[
+ tuple[
+ int, # epoch
+ tuple[int, ...], # release
+ tuple[str, int] | _InfinityType | _NegativeInfinityType, # pre
+ tuple[str, int] | _NegativeInfinityType, # post
+ tuple[str, int] | _InfinityType, # dev
+ tuple[tuple[int, L[""]] | tuple[_NegativeInfinityType, str], ...] | _NegativeInfinityType, # local
+ ],
+ ],
+):
+ _regex: ClassVar[re.Pattern[str]] = ...
+ _version: Final[str]
+
+ def __init__(self, /, version: str) -> None: ...
+ @property
+ def public(self) -> str: ...
+ @property
+ def base_version(self) -> str: ...
+ @property
+ def local(self) -> str | None: ...
+ @property
+ def is_prerelease(self) -> bool: ...
+ @property
+ def is_postrelease(self) -> bool: ...
+
+#
+def parse(version: str) -> Version | LegacyVersion: ...