From 857ff5ee4f5e1bb923359ce2cdcc1d6f3e794c26 Mon Sep 17 00:00:00 2001 From: Polina Date: Thu, 2 Jul 2026 18:53:13 +0000 Subject: [PATCH] =?UTF-8?q?=D0=97=D0=B0=D0=B3=D1=80=D1=83=D0=B7=D0=B8?= =?UTF-8?q?=D1=82=D1=8C=20=D1=84=D0=B0=D0=B9=D0=BB=D1=8B=20=D0=B2=20=C2=AB?= =?UTF-8?q?venv/Lib/site-packages/passlib/utils/compat=C2=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../passlib/utils/compat/__init__.py | 474 ++++++++++++++++++ .../passlib/utils/compat/_ordered_dict.py | 242 +++++++++ 2 files changed, 716 insertions(+) create mode 100644 venv/Lib/site-packages/passlib/utils/compat/__init__.py create mode 100644 venv/Lib/site-packages/passlib/utils/compat/_ordered_dict.py diff --git a/venv/Lib/site-packages/passlib/utils/compat/__init__.py b/venv/Lib/site-packages/passlib/utils/compat/__init__.py new file mode 100644 index 0000000..f6ead24 --- /dev/null +++ b/venv/Lib/site-packages/passlib/utils/compat/__init__.py @@ -0,0 +1,474 @@ +"""passlib.utils.compat - python 2/3 compatibility helpers""" +#============================================================================= +# figure out what we're running +#============================================================================= + +#------------------------------------------------------------------------ +# python version +#------------------------------------------------------------------------ +import sys +PY2 = sys.version_info < (3,0) +PY3 = sys.version_info >= (3,0) + +# make sure it's not an unsupported version, even if we somehow got this far +if sys.version_info < (2,6) or (3,0) <= sys.version_info < (3,2): + raise RuntimeError("Passlib requires Python 2.6, 2.7, or >= 3.2 (as of passlib 1.7)") + +PY26 = sys.version_info < (2,7) + +#------------------------------------------------------------------------ +# python implementation +#------------------------------------------------------------------------ +JYTHON = sys.platform.startswith('java') + +PYPY = hasattr(sys, "pypy_version_info") + +if PYPY and sys.pypy_version_info < (2,0): + raise RuntimeError("passlib requires pypy >= 2.0 (as of passlib 1.7)") + +# e.g. '2.7.7\n[Pyston 0.5.1]' +# NOTE: deprecated support 2019-11 +PYSTON = "Pyston" in sys.version + +#============================================================================= +# common imports +#============================================================================= +import logging; log = logging.getLogger(__name__) +if PY3: + import builtins +else: + import __builtin__ as builtins + +def add_doc(obj, doc): + """add docstring to an object""" + obj.__doc__ = doc + +#============================================================================= +# the default exported vars +#============================================================================= +__all__ = [ + # python versions + 'PY2', 'PY3', 'PY26', + + # io + 'BytesIO', 'StringIO', 'NativeStringIO', 'SafeConfigParser', + 'print_', + + # type detection +## 'is_mapping', + 'int_types', + 'num_types', + 'unicode_or_bytes_types', + 'native_string_types', + + # unicode/bytes types & helpers + 'u', + 'unicode', + 'uascii_to_str', 'bascii_to_str', + 'str_to_uascii', 'str_to_bascii', + 'join_unicode', 'join_bytes', + 'join_byte_values', 'join_byte_elems', + 'byte_elem_value', + 'iter_byte_values', + + # iteration helpers + 'irange', #'lrange', + 'imap', 'lmap', + 'iteritems', 'itervalues', + 'next', + + # collections + 'OrderedDict', + + # context helpers + 'nullcontext', + + # introspection + 'get_method_function', 'add_doc', +] + +# begin accumulating mapping of lazy-loaded attrs, +# 'merged' into module at bottom +_lazy_attrs = dict() + +#============================================================================= +# unicode & bytes types +#============================================================================= +if PY3: + unicode = str + + # TODO: once we drop python 3.2 support, can use u'' again! + def u(s): + assert isinstance(s, str) + return s + + unicode_or_bytes_types = (str, bytes) + native_string_types = (unicode,) + +else: + unicode = builtins.unicode + + def u(s): + assert isinstance(s, str) + return s.decode("unicode_escape") + + unicode_or_bytes_types = (basestring,) + native_string_types = (basestring,) + +# shorter preferred aliases +unicode_or_bytes = unicode_or_bytes_types +unicode_or_str = native_string_types + +# unicode -- unicode type, regardless of python version +# bytes -- bytes type, regardless of python version +# unicode_or_bytes_types -- types that text can occur in, whether encoded or not +# native_string_types -- types that native python strings (dict keys etc) can occur in. + +#============================================================================= +# unicode & bytes helpers +#============================================================================= +# function to join list of unicode strings +join_unicode = u('').join + +# function to join list of byte strings +join_bytes = b''.join + +if PY3: + def uascii_to_str(s): + assert isinstance(s, unicode) + return s + + def bascii_to_str(s): + assert isinstance(s, bytes) + return s.decode("ascii") + + def str_to_uascii(s): + assert isinstance(s, str) + return s + + def str_to_bascii(s): + assert isinstance(s, str) + return s.encode("ascii") + + join_byte_values = join_byte_elems = bytes + + def byte_elem_value(elem): + assert isinstance(elem, int) + return elem + + def iter_byte_values(s): + assert isinstance(s, bytes) + return s + + def iter_byte_chars(s): + assert isinstance(s, bytes) + # FIXME: there has to be a better way to do this + return (bytes([c]) for c in s) + +else: + def uascii_to_str(s): + assert isinstance(s, unicode) + return s.encode("ascii") + + def bascii_to_str(s): + assert isinstance(s, bytes) + return s + + def str_to_uascii(s): + assert isinstance(s, str) + return s.decode("ascii") + + def str_to_bascii(s): + assert isinstance(s, str) + return s + + def join_byte_values(values): + return join_bytes(chr(v) for v in values) + + join_byte_elems = join_bytes + + byte_elem_value = ord + + def iter_byte_values(s): + assert isinstance(s, bytes) + return (ord(c) for c in s) + + def iter_byte_chars(s): + assert isinstance(s, bytes) + return s + +add_doc(uascii_to_str, "helper to convert ascii unicode -> native str") +add_doc(bascii_to_str, "helper to convert ascii bytes -> native str") +add_doc(str_to_uascii, "helper to convert ascii native str -> unicode") +add_doc(str_to_bascii, "helper to convert ascii native str -> bytes") + +# join_byte_values -- function to convert list of ordinal integers to byte string. + +# join_byte_elems -- function to convert list of byte elements to byte string; +# i.e. what's returned by ``b('a')[0]``... +# this is b('a') under PY2, but 97 under PY3. + +# byte_elem_value -- function to convert byte element to integer -- a noop under PY3 + +add_doc(iter_byte_values, "iterate over byte string as sequence of ints 0-255") +add_doc(iter_byte_chars, "iterate over byte string as sequence of 1-byte strings") + +#============================================================================= +# numeric +#============================================================================= +if PY3: + int_types = (int,) + num_types = (int, float) +else: + int_types = (int, long) + num_types = (int, long, float) + +#============================================================================= +# iteration helpers +# +# irange - range iterable / view (xrange under py2, range under py3) +# lrange - range list (range under py2, list(range()) under py3) +# +# imap - map to iterator +# lmap - map to list +#============================================================================= +if PY3: + irange = range + ##def lrange(*a,**k): + ## return list(range(*a,**k)) + + def lmap(*a, **k): + return list(map(*a,**k)) + imap = map + + def iteritems(d): + return d.items() + def itervalues(d): + return d.values() + + def nextgetter(obj): + return obj.__next__ + + izip = zip + +else: + irange = xrange + ##lrange = range + + lmap = map + from itertools import imap, izip + + def iteritems(d): + return d.iteritems() + def itervalues(d): + return d.itervalues() + + def nextgetter(obj): + return obj.next + +add_doc(nextgetter, "return function that yields successive values from iterable") + +#============================================================================= +# typing +#============================================================================= +##def is_mapping(obj): +## # non-exhaustive check, enough to distinguish from lists, etc +## return hasattr(obj, "items") + +#============================================================================= +# introspection +#============================================================================= +if PY3: + method_function_attr = "__func__" +else: + method_function_attr = "im_func" + +def get_method_function(func): + """given (potential) method, return underlying function""" + return getattr(func, method_function_attr, func) + +def get_unbound_method_function(func): + """given unbound method, return underlying function""" + return func if PY3 else func.__func__ + +def error_from(exc, # *, + cause=None): + """ + backward compat hack to suppress exception cause in python3.3+ + + one python < 3.3 support is dropped, can replace all uses with "raise exc from None" + """ + exc.__cause__ = cause + exc.__suppress_context__ = True + return exc + +# legacy alias +suppress_cause = error_from + +#============================================================================= +# input/output +#============================================================================= +if PY3: + _lazy_attrs = dict( + BytesIO="io.BytesIO", + UnicodeIO="io.StringIO", + NativeStringIO="io.StringIO", + SafeConfigParser="configparser.ConfigParser", + ) + + print_ = getattr(builtins, "print") + +else: + _lazy_attrs = dict( + BytesIO="cStringIO.StringIO", + UnicodeIO="StringIO.StringIO", + NativeStringIO="cStringIO.StringIO", + SafeConfigParser="ConfigParser.SafeConfigParser", + ) + + def print_(*args, **kwds): + """The new-style print function.""" + # extract kwd args + fp = kwds.pop("file", sys.stdout) + sep = kwds.pop("sep", None) + end = kwds.pop("end", None) + if kwds: + raise TypeError("invalid keyword arguments") + + # short-circuit if no target + if fp is None: + return + + # use unicode or bytes ? + want_unicode = isinstance(sep, unicode) or isinstance(end, unicode) or \ + any(isinstance(arg, unicode) for arg in args) + + # pick default end sequence + if end is None: + end = u("\n") if want_unicode else "\n" + elif not isinstance(end, unicode_or_bytes_types): + raise TypeError("end must be None or a string") + + # pick default separator + if sep is None: + sep = u(" ") if want_unicode else " " + elif not isinstance(sep, unicode_or_bytes_types): + raise TypeError("sep must be None or a string") + + # write to buffer + first = True + write = fp.write + for arg in args: + if first: + first = False + else: + write(sep) + if not isinstance(arg, basestring): + arg = str(arg) + write(arg) + write(end) + +#============================================================================= +# collections +#============================================================================= +if PY26: + _lazy_attrs['OrderedDict'] = 'passlib.utils.compat._ordered_dict.OrderedDict' +else: + _lazy_attrs['OrderedDict'] = 'collections.OrderedDict' + +#============================================================================= +# context managers +#============================================================================= + +try: + # new in py37 + from contextlib import nullcontext +except ImportError: + + class nullcontext(object): + """ + Context manager that does no additional processing. + """ + def __init__(self, enter_result=None): + self.enter_result = enter_result + + def __enter__(self): + return self.enter_result + + def __exit__(self, *exc_info): + pass + +#============================================================================= +# lazy overlay module +#============================================================================= +from types import ModuleType + +def _import_object(source): + """helper to import object from module; accept format `path.to.object`""" + modname, modattr = source.rsplit(".",1) + mod = __import__(modname, fromlist=[modattr], level=0) + return getattr(mod, modattr) + +class _LazyOverlayModule(ModuleType): + """proxy module which overlays original module, + and lazily imports specified attributes. + + this is mainly used to prevent importing of resources + that are only needed by certain password hashes, + yet allow them to be imported from a single location. + + used by :mod:`passlib.utils`, :mod:`passlib.crypto`, + and :mod:`passlib.utils.compat`. + """ + + @classmethod + def replace_module(cls, name, attrmap): + orig = sys.modules[name] + self = cls(name, attrmap, orig) + sys.modules[name] = self + return self + + def __init__(self, name, attrmap, proxy=None): + ModuleType.__init__(self, name) + self.__attrmap = attrmap + self.__proxy = proxy + self.__log = logging.getLogger(name) + + def __getattr__(self, attr): + proxy = self.__proxy + if proxy and hasattr(proxy, attr): + return getattr(proxy, attr) + attrmap = self.__attrmap + if attr in attrmap: + source = attrmap[attr] + if callable(source): + value = source() + else: + value = _import_object(source) + setattr(self, attr, value) + self.__log.debug("loaded lazy attr %r: %r", attr, value) + return value + raise AttributeError("'module' object has no attribute '%s'" % (attr,)) + + def __repr__(self): + proxy = self.__proxy + if proxy: + return repr(proxy) + else: + return ModuleType.__repr__(self) + + def __dir__(self): + attrs = set(dir(self.__class__)) + attrs.update(self.__dict__) + attrs.update(self.__attrmap) + proxy = self.__proxy + if proxy is not None: + attrs.update(dir(proxy)) + return list(attrs) + +# replace this module with overlay that will lazily import attributes. +_LazyOverlayModule.replace_module(__name__, _lazy_attrs) + +#============================================================================= +# eof +#============================================================================= diff --git a/venv/Lib/site-packages/passlib/utils/compat/_ordered_dict.py b/venv/Lib/site-packages/passlib/utils/compat/_ordered_dict.py new file mode 100644 index 0000000..cfd766d --- /dev/null +++ b/venv/Lib/site-packages/passlib/utils/compat/_ordered_dict.py @@ -0,0 +1,242 @@ +"""passlib.utils.compat._ordered_dict -- backport of collections.OrderedDict for py26 + +taken from stdlib-suggested recipe at http://code.activestate.com/recipes/576693/ + +this should be imported from passlib.utils.compat.OrderedDict, not here. +""" + +try: + from thread import get_ident as _get_ident +except ImportError: + from dummy_thread import get_ident as _get_ident + +class OrderedDict(dict): + """Dictionary that remembers insertion order""" + # An inherited dict maps keys to values. + # The inherited dict provides __getitem__, __len__, __contains__, and get. + # The remaining methods are order-aware. + # Big-O running times for all methods are the same as for regular dictionaries. + + # The internal self.__map dictionary maps keys to links in a doubly linked list. + # The circular doubly linked list starts and ends with a sentinel element. + # The sentinel element never gets deleted (this simplifies the algorithm). + # Each link is stored as a list of length three: [PREV, NEXT, KEY]. + + def __init__(self, *args, **kwds): + '''Initialize an ordered dictionary. Signature is the same as for + regular dictionaries, but keyword arguments are not recommended + because their insertion order is arbitrary. + + ''' + if len(args) > 1: + raise TypeError('expected at most 1 arguments, got %d' % len(args)) + try: + self.__root + except AttributeError: + self.__root = root = [] # sentinel node + root[:] = [root, root, None] + self.__map = {} + self.__update(*args, **kwds) + + def __setitem__(self, key, value, dict_setitem=dict.__setitem__): + 'od.__setitem__(i, y) <==> od[i]=y' + # Setting a new item creates a new link which goes at the end of the linked + # list, and the inherited dictionary is updated with the new key/value pair. + if key not in self: + root = self.__root + last = root[0] + last[1] = root[0] = self.__map[key] = [last, root, key] + dict_setitem(self, key, value) + + def __delitem__(self, key, dict_delitem=dict.__delitem__): + 'od.__delitem__(y) <==> del od[y]' + # Deleting an existing item uses self.__map to find the link which is + # then removed by updating the links in the predecessor and successor nodes. + dict_delitem(self, key) + link_prev, link_next, key = self.__map.pop(key) + link_prev[1] = link_next + link_next[0] = link_prev + + def __iter__(self): + 'od.__iter__() <==> iter(od)' + root = self.__root + curr = root[1] + while curr is not root: + yield curr[2] + curr = curr[1] + + def __reversed__(self): + 'od.__reversed__() <==> reversed(od)' + root = self.__root + curr = root[0] + while curr is not root: + yield curr[2] + curr = curr[0] + + def clear(self): + 'od.clear() -> None. Remove all items from od.' + try: + for node in self.__map.itervalues(): + del node[:] + root = self.__root + root[:] = [root, root, None] + self.__map.clear() + except AttributeError: + pass + dict.clear(self) + + def popitem(self, last=True): + '''od.popitem() -> (k, v), return and remove a (key, value) pair. + Pairs are returned in LIFO order if last is true or FIFO order if false. + + ''' + if not self: + raise KeyError('dictionary is empty') + root = self.__root + if last: + link = root[0] + link_prev = link[0] + link_prev[1] = root + root[0] = link_prev + else: + link = root[1] + link_next = link[1] + root[1] = link_next + link_next[0] = root + key = link[2] + del self.__map[key] + value = dict.pop(self, key) + return key, value + + # -- the following methods do not depend on the internal structure -- + + def keys(self): + 'od.keys() -> list of keys in od' + return list(self) + + def values(self): + 'od.values() -> list of values in od' + return [self[key] for key in self] + + def items(self): + 'od.items() -> list of (key, value) pairs in od' + return [(key, self[key]) for key in self] + + def iterkeys(self): + 'od.iterkeys() -> an iterator over the keys in od' + return iter(self) + + def itervalues(self): + 'od.itervalues -> an iterator over the values in od' + for k in self: + yield self[k] + + def iteritems(self): + 'od.iteritems -> an iterator over the (key, value) items in od' + for k in self: + yield (k, self[k]) + + def update(*args, **kwds): + '''od.update(E, **F) -> None. Update od from dict/iterable E and F. + + If E is a dict instance, does: for k in E: od[k] = E[k] + If E has a .keys() method, does: for k in E.keys(): od[k] = E[k] + Or if E is an iterable of items, does: for k, v in E: od[k] = v + In either case, this is followed by: for k, v in F.items(): od[k] = v + + ''' + if len(args) > 2: + raise TypeError('update() takes at most 2 positional ' + 'arguments (%d given)' % (len(args),)) + elif not args: + raise TypeError('update() takes at least 1 argument (0 given)') + self = args[0] + # Make progressively weaker assumptions about "other" + other = () + if len(args) == 2: + other = args[1] + if isinstance(other, dict): + for key in other: + self[key] = other[key] + elif hasattr(other, 'keys'): + for key in other.keys(): + self[key] = other[key] + else: + for key, value in other: + self[key] = value + for key, value in kwds.items(): + self[key] = value + + __update = update # let subclasses override update without breaking __init__ + + __marker = object() + + def pop(self, key, default=__marker): + '''od.pop(k[,d]) -> v, remove specified key and return the corresponding value. + If key is not found, d is returned if given, otherwise KeyError is raised. + + ''' + if key in self: + result = self[key] + del self[key] + return result + if default is self.__marker: + raise KeyError(key) + return default + + def setdefault(self, key, default=None): + 'od.setdefault(k[,d]) -> od.get(k,d), also set od[k]=d if k not in od' + if key in self: + return self[key] + self[key] = default + return default + + def __repr__(self, _repr_running={}): + 'od.__repr__() <==> repr(od)' + call_key = id(self), _get_ident() + if call_key in _repr_running: + return '...' + _repr_running[call_key] = 1 + try: + if not self: + return '%s()' % (self.__class__.__name__,) + return '%s(%r)' % (self.__class__.__name__, self.items()) + finally: + del _repr_running[call_key] + + def __reduce__(self): + 'Return state information for pickling' + items = [[k, self[k]] for k in self] + inst_dict = vars(self).copy() + for k in vars(OrderedDict()): + inst_dict.pop(k, None) + if inst_dict: + return (self.__class__, (items,), inst_dict) + return self.__class__, (items,) + + def copy(self): + 'od.copy() -> a shallow copy of od' + return self.__class__(self) + + @classmethod + def fromkeys(cls, iterable, value=None): + '''OD.fromkeys(S[, v]) -> New ordered dictionary with keys from S + and values equal to v (which defaults to None). + + ''' + d = cls() + for key in iterable: + d[key] = value + return d + + def __eq__(self, other): + '''od.__eq__(y) <==> od==y. Comparison to another OD is order-sensitive + while comparison to a regular mapping is order-insensitive. + + ''' + if isinstance(other, OrderedDict): + return len(self)==len(other) and self.items() == other.items() + return dict.__eq__(self, other) + + def __ne__(self, other): + return not self == other