Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
__init__.py475 linesDownload Raw Back to compat
1"""passlib.utils.compat - python 2/3 compatibility helpers"""2#=============================================================================3# figure out what we're running4#=============================================================================5 6#------------------------------------------------------------------------7# python version8#------------------------------------------------------------------------9import sys10PY2 = sys.version_info < (3,0)11PY3 = sys.version_info >= (3,0)12 13# make sure it's not an unsupported version, even if we somehow got this far14if sys.version_info < (2,6) or (3,0) <= sys.version_info < (3,2):15    raise RuntimeError("Passlib requires Python 2.6, 2.7, or >= 3.2 (as of passlib 1.7)")16 17PY26 = sys.version_info < (2,7)18 19#------------------------------------------------------------------------20# python implementation21#------------------------------------------------------------------------22JYTHON = sys.platform.startswith('java')23 24PYPY = hasattr(sys, "pypy_version_info")25 26if PYPY and sys.pypy_version_info < (2,0):27    raise RuntimeError("passlib requires pypy >= 2.0 (as of passlib 1.7)")28 29# e.g. '2.7.7\n[Pyston 0.5.1]'30# NOTE: deprecated support 2019-1131PYSTON = "Pyston" in sys.version32 33#=============================================================================34# common imports35#=============================================================================36import logging; log = logging.getLogger(__name__)37if PY3:38    import builtins39else:40    import __builtin__ as builtins41 42def add_doc(obj, doc):43    """add docstring to an object"""44    obj.__doc__ = doc45 46#=============================================================================47# the default exported vars48#=============================================================================49__all__ = [50    # python versions51    'PY2', 'PY3', 'PY26',52 53    # io54    'BytesIO', 'StringIO', 'NativeStringIO', 'SafeConfigParser',55    'print_',56 57    # type detection58##    'is_mapping',59    'int_types',60    'num_types',61    'unicode_or_bytes_types',62    'native_string_types',63 64    # unicode/bytes types & helpers65    'u',66    'unicode',67    'uascii_to_str', 'bascii_to_str',68    'str_to_uascii', 'str_to_bascii',69    'join_unicode', 'join_bytes',70    'join_byte_values', 'join_byte_elems',71    'byte_elem_value',72    'iter_byte_values',73 74    # iteration helpers75    'irange', #'lrange',76    'imap', 'lmap',77    'iteritems', 'itervalues',78    'next',79 80    # collections81    'OrderedDict',82 83    # context helpers84    'nullcontext',85 86    # introspection87    'get_method_function', 'add_doc',88]89 90# begin accumulating mapping of lazy-loaded attrs,91# 'merged' into module at bottom92_lazy_attrs = dict()93 94#=============================================================================95# unicode & bytes types96#=============================================================================97if PY3:98    unicode = str99 100    # TODO: once we drop python 3.2 support, can use u'' again!101    def u(s):102        assert isinstance(s, str)103        return s104 105    unicode_or_bytes_types = (str, bytes)106    native_string_types = (unicode,)107 108else:109    unicode = builtins.unicode110 111    def u(s):112        assert isinstance(s, str)113        return s.decode("unicode_escape")114 115    unicode_or_bytes_types = (basestring,)116    native_string_types = (basestring,)117 118# shorter preferred aliases119unicode_or_bytes = unicode_or_bytes_types120unicode_or_str = native_string_types121 122# unicode -- unicode type, regardless of python version123# bytes -- bytes type, regardless of python version124# unicode_or_bytes_types -- types that text can occur in, whether encoded or not125# native_string_types -- types that native python strings (dict keys etc) can occur in.126 127#=============================================================================128# unicode & bytes helpers129#=============================================================================130# function to join list of unicode strings131join_unicode = u('').join132 133# function to join list of byte strings134join_bytes = b''.join135 136if PY3:137    def uascii_to_str(s):138        assert isinstance(s, unicode)139        return s140 141    def bascii_to_str(s):142        assert isinstance(s, bytes)143        return s.decode("ascii")144 145    def str_to_uascii(s):146        assert isinstance(s, str)147        return s148 149    def str_to_bascii(s):150        assert isinstance(s, str)151        return s.encode("ascii")152 153    join_byte_values = join_byte_elems = bytes154 155    def byte_elem_value(elem):156        assert isinstance(elem, int)157        return elem158 159    def iter_byte_values(s):160        assert isinstance(s, bytes)161        return s162 163    def iter_byte_chars(s):164        assert isinstance(s, bytes)165        # FIXME: there has to be a better way to do this166        return (bytes([c]) for c in s)167 168else:169    def uascii_to_str(s):170        assert isinstance(s, unicode)171        return s.encode("ascii")172 173    def bascii_to_str(s):174        assert isinstance(s, bytes)175        return s176 177    def str_to_uascii(s):178        assert isinstance(s, str)179        return s.decode("ascii")180 181    def str_to_bascii(s):182        assert isinstance(s, str)183        return s184 185    def join_byte_values(values):186        return join_bytes(chr(v) for v in values)187 188    join_byte_elems = join_bytes189 190    byte_elem_value = ord191 192    def iter_byte_values(s):193        assert isinstance(s, bytes)194        return (ord(c) for c in s)195 196    def iter_byte_chars(s):197        assert isinstance(s, bytes)198        return s199 200add_doc(uascii_to_str, "helper to convert ascii unicode -> native str")201add_doc(bascii_to_str, "helper to convert ascii bytes -> native str")202add_doc(str_to_uascii, "helper to convert ascii native str -> unicode")203add_doc(str_to_bascii, "helper to convert ascii native str -> bytes")204 205# join_byte_values -- function to convert list of ordinal integers to byte string.206 207# join_byte_elems --  function to convert list of byte elements to byte string;208#                 i.e. what's returned by ``b('a')[0]``...209#                 this is b('a') under PY2, but 97 under PY3.210 211# byte_elem_value -- function to convert byte element to integer -- a noop under PY3212 213add_doc(iter_byte_values, "iterate over byte string as sequence of ints 0-255")214add_doc(iter_byte_chars, "iterate over byte string as sequence of 1-byte strings")215 216#=============================================================================217# numeric218#=============================================================================219if PY3:220    int_types = (int,)221    num_types = (int, float)222else:223    int_types = (int, long)224    num_types = (int, long, float)225 226#=============================================================================227# iteration helpers228#229# irange - range iterable / view (xrange under py2, range under py3)230# lrange - range list (range under py2, list(range()) under py3)231#232# imap - map to iterator233# lmap - map to list234#=============================================================================235if PY3:236    irange = range237    ##def lrange(*a,**k):238    ##    return list(range(*a,**k))239 240    def lmap(*a, **k):241        return list(map(*a,**k))242    imap = map243 244    def iteritems(d):245        return d.items()246    def itervalues(d):247        return d.values()248 249    def nextgetter(obj):250        return obj.__next__251 252    izip = zip253 254else:255    irange = xrange256    ##lrange = range257 258    lmap = map259    from itertools import imap, izip260 261    def iteritems(d):262        return d.iteritems()263    def itervalues(d):264        return d.itervalues()265 266    def nextgetter(obj):267        return obj.next268 269add_doc(nextgetter, "return function that yields successive values from iterable")270 271#=============================================================================272# typing273#=============================================================================274##def is_mapping(obj):275##    # non-exhaustive check, enough to distinguish from lists, etc276##    return hasattr(obj, "items")277 278#=============================================================================279# introspection280#=============================================================================281if PY3:282    method_function_attr = "__func__"283else:284    method_function_attr = "im_func"285 286def get_method_function(func):287    """given (potential) method, return underlying function"""288    return getattr(func, method_function_attr, func)289 290def get_unbound_method_function(func):291    """given unbound method, return underlying function"""292    return func if PY3 else func.__func__293 294def error_from(exc,  # *,295               cause=None):296    """297    backward compat hack to suppress exception cause in python3.3+298 299    one python < 3.3 support is dropped, can replace all uses with "raise exc from None"300    """301    exc.__cause__ = cause302    exc.__suppress_context__ = True303    return exc304 305# legacy alias306suppress_cause = error_from307 308#=============================================================================309# input/output310#=============================================================================311if PY3:312    _lazy_attrs = dict(313        BytesIO="io.BytesIO",314        UnicodeIO="io.StringIO",315        NativeStringIO="io.StringIO",316        SafeConfigParser="configparser.ConfigParser",317    )318 319    print_ = getattr(builtins, "print")320 321else:322    _lazy_attrs = dict(323        BytesIO="cStringIO.StringIO",324        UnicodeIO="StringIO.StringIO",325        NativeStringIO="cStringIO.StringIO",326        SafeConfigParser="ConfigParser.SafeConfigParser",327    )328 329    def print_(*args, **kwds):330        """The new-style print function."""331        # extract kwd args332        fp = kwds.pop("file", sys.stdout)333        sep = kwds.pop("sep", None)334        end = kwds.pop("end", None)335        if kwds:336            raise TypeError("invalid keyword arguments")337 338        # short-circuit if no target339        if fp is None:340            return341 342        # use unicode or bytes ?343        want_unicode = isinstance(sep, unicode) or isinstance(end, unicode) or \344                       any(isinstance(arg, unicode) for arg in args)345 346        # pick default end sequence347        if end is None:348            end = u("\n") if want_unicode else "\n"349        elif not isinstance(end, unicode_or_bytes_types):350            raise TypeError("end must be None or a string")351 352        # pick default separator353        if sep is None:354            sep = u(" ") if want_unicode else " "355        elif not isinstance(sep, unicode_or_bytes_types):356            raise TypeError("sep must be None or a string")357 358        # write to buffer359        first = True360        write = fp.write361        for arg in args:362            if first:363                first = False364            else:365                write(sep)366            if not isinstance(arg, basestring):367                arg = str(arg)368            write(arg)369        write(end)370 371#=============================================================================372# collections373#=============================================================================374if PY26:375    _lazy_attrs['OrderedDict'] = 'passlib.utils.compat._ordered_dict.OrderedDict'376else:377    _lazy_attrs['OrderedDict'] = 'collections.OrderedDict'378 379#=============================================================================380# context managers381#=============================================================================382 383try:384    # new in py37385    from contextlib import nullcontext386except ImportError:387 388    class nullcontext(object):389        """390        Context manager that does no additional processing.391        """392        def __init__(self, enter_result=None):393            self.enter_result = enter_result394 395        def __enter__(self):396            return self.enter_result397 398        def __exit__(self, *exc_info):399            pass400 401#=============================================================================402# lazy overlay module403#=============================================================================404from types import ModuleType405 406def _import_object(source):407    """helper to import object from module; accept format `path.to.object`"""408    modname, modattr = source.rsplit(".",1)409    mod = __import__(modname, fromlist=[modattr], level=0)410    return getattr(mod, modattr)411 412class _LazyOverlayModule(ModuleType):413    """proxy module which overlays original module,414    and lazily imports specified attributes.415 416    this is mainly used to prevent importing of resources417    that are only needed by certain password hashes,418    yet allow them to be imported from a single location.419 420    used by :mod:`passlib.utils`, :mod:`passlib.crypto`,421    and :mod:`passlib.utils.compat`.422    """423 424    @classmethod425    def replace_module(cls, name, attrmap):426        orig = sys.modules[name]427        self = cls(name, attrmap, orig)428        sys.modules[name] = self429        return self430 431    def __init__(self, name, attrmap, proxy=None):432        ModuleType.__init__(self, name)433        self.__attrmap = attrmap434        self.__proxy = proxy435        self.__log = logging.getLogger(name)436 437    def __getattr__(self, attr):438        proxy = self.__proxy439        if proxy and hasattr(proxy, attr):440            return getattr(proxy, attr)441        attrmap = self.__attrmap442        if attr in attrmap:443            source = attrmap[attr]444            if callable(source):445                value = source()446            else:447                value = _import_object(source)448            setattr(self, attr, value)449            self.__log.debug("loaded lazy attr %r: %r", attr, value)450            return value451        raise AttributeError("'module' object has no attribute '%s'" % (attr,))452 453    def __repr__(self):454        proxy = self.__proxy455        if proxy:456            return repr(proxy)457        else:458            return ModuleType.__repr__(self)459 460    def __dir__(self):461        attrs = set(dir(self.__class__))462        attrs.update(self.__dict__)463        attrs.update(self.__attrmap)464        proxy = self.__proxy465        if proxy is not None:466            attrs.update(dir(proxy))467        return list(attrs)468 469# replace this module with overlay that will lazily import attributes.470_LazyOverlayModule.replace_module(__name__, _lazy_attrs)471 472#=============================================================================473# eof474#=============================================================================475 
codekingpro/portable-devtools · Team Ai