diff options
author | Eli Collins <elic@assurancetechnologies.com> | 2012-03-12 21:33:28 -0400 |
---|---|---|
committer | Eli Collins <elic@assurancetechnologies.com> | 2012-03-12 21:33:28 -0400 |
commit | 3913a59ad033462e6a389544ffcdf8055db7ad9c (patch) | |
tree | 63dda089e61a9d8ef4b468a323df8c2ec2ad6c70 /passlib/utils | |
parent | b970d6ee145122005f1e6808466900a94e00dfcc (diff) | |
download | passlib-3913a59ad033462e6a389544ffcdf8055db7ad9c.tar.gz |
updated test support & py3 compat code from an external library
passlib.tests
-------------
* deprecated support for unittest 1... accumulated too many backports,
planning to require unittest2 in next release.
* case_prefix renamed to shortDescription
* test case now archives & clears warning registry state in addition
to warning filter state
passlib.utils.compat
--------------------
* a bunch of the bytes-related functions were renamed for clarity
* NativeStringIO alias added
* trange alias merged into irange
Diffstat (limited to 'passlib/utils')
-rw-r--r-- | passlib/utils/__init__.py | 44 | ||||
-rw-r--r-- | passlib/utils/compat.py | 178 | ||||
-rw-r--r-- | passlib/utils/des.py | 22 | ||||
-rw-r--r-- | passlib/utils/handlers.py | 6 |
4 files changed, 130 insertions, 120 deletions
diff --git a/passlib/utils/__init__.py b/passlib/utils/__init__.py index b763898..6d26d91 100644 --- a/passlib/utils/__init__.py +++ b/passlib/utils/__init__.py @@ -17,9 +17,9 @@ import unicodedata from warnings import warn #site #pkg -from passlib.utils.compat import _add_doc, b, bytes, bjoin, bjoin_ints, \ - bjoin_elems, exc_err, irange, imap, PY3, u, \ - ujoin, unicode, belem_ord +from passlib.utils.compat import add_doc, b, bytes, join_bytes, join_byte_values, \ + join_byte_elems, exc_err, irange, imap, PY3, u, \ + join_unicode, unicode, byte_elem_value #local __all__ = [ # constants @@ -353,7 +353,7 @@ def saslprep(source, errname="value"): # - strip 'commonly mapped to nothing' chars (stringprep B.1) in_table_c12 = stringprep.in_table_c12 in_table_b1 = stringprep.in_table_b1 - data = ujoin( + data = join_unicode( _USPACE if in_table_c12(c) else c for c in source if not in_table_b1(c) @@ -435,8 +435,8 @@ if PY3: return bytes(l ^ r for l, r in zip(left, right)) else: def xor_bytes(left, right): - return bjoin(chr(ord(l) ^ ord(r)) for l, r in zip(left, right)) -_add_doc(xor_bytes, "perform bitwise-xor of two byte strings") + return join_bytes(chr(ord(l) ^ ord(r)) for l, r in zip(left, right)) +add_doc(xor_bytes, "perform bitwise-xor of two byte strings") def render_bytes(source, *args): """helper for using formatting operator with bytes. @@ -463,17 +463,17 @@ def render_bytes(source, *args): @deprecated_function(deprecated="1.6", removed="1.8") def bytes_to_int(value): "decode string of bytes as single big-endian integer" - from passlib.utils.compat import belem_ord + from passlib.utils.compat import byte_elem_value out = 0 for v in value: - out = (out<<8) | belem_ord(v) + out = (out<<8) | byte_elem_value(v) return out @deprecated_function(deprecated="1.6", removed="1.8") def int_to_bytes(value, count): "encodes integer into single big-endian byte string" assert value < (1<<(8*count)), "value too large for %d bytes: %d" % (count, value) - return bjoin_ints( + return join_byte_values( ((value>>s) & 0xff) for s in irange(8*count-8,-8,-8) ) @@ -586,7 +586,7 @@ else: raise TypeError("%s must be unicode or bytes, not %s" % (errname, type(source))) -_add_doc(to_native_str, +add_doc(to_native_str, """take in unicode or bytes, return native string. python 2: encodes unicode using specified encoding, leaves bytes alone. @@ -732,7 +732,7 @@ class Base64Engine(object): else: next_value = (ord(elem) for elem in source).next gen = self._encode_bytes(next_value, chunks, tail) - out = bjoin_elems(imap(self._encode64, gen)) + out = join_byte_elems(imap(self._encode64, gen)) ##if tail: ## padding = self.padding ## if padding: @@ -841,7 +841,7 @@ class Base64Engine(object): else: next_value = imap(self._decode64, source).next try: - return bjoin_ints(self._decode_bytes(next_value, chunks, tail)) + return join_byte_values(self._decode_bytes(next_value, chunks, tail)) except KeyError: err = exc_err() raise ValueError("invalid character: %r" % (err.args[0],)) @@ -1003,19 +1003,19 @@ class Base64Engine(object): "encode byte string, first transposing source using offset list" if not isinstance(source, bytes): raise TypeError("source must be bytes, not %s" % (type(source),)) - tmp = bjoin_elems(source[off] for off in offsets) + tmp = join_byte_elems(source[off] for off in offsets) return self.encode_bytes(tmp) def decode_transposed_bytes(self, source, offsets): "decode byte string, then reverse transposition described by offset list" # NOTE: if transposition does not use all bytes of source, - # the original can't be recovered... and bjoin_elems() will throw + # the original can't be recovered... and join_byte_elems() will throw # an error because 1+ values in <buf> will be None. tmp = self.decode_bytes(source) buf = [None] * len(offsets) for off, char in zip(offsets, tmp): buf[off] = char - return bjoin_elems(buf) + return join_byte_elems(buf) #============================================================= # integer decoding helpers - mainly used by des_crypt family @@ -1137,7 +1137,7 @@ class Base64Engine(object): else: itr = irange(0, bits, 6) # padding is msb, so no change needed. - return bjoin_elems(imap(self._encode64, + return join_byte_elems(imap(self._encode64, ((value>>off) & 0x3f for off in itr))) #--------------------------------------------- @@ -1160,7 +1160,7 @@ class Base64Engine(object): raw = [value & 0x3f, (value>>6) & 0x3f] if self.big: raw = reversed(raw) - return bjoin_elems(imap(self._encode64, raw)) + return join_byte_elems(imap(self._encode64, raw)) def encode_int24(self, value): "encodes 24-bit integer -> 4 char string" @@ -1170,7 +1170,7 @@ class Base64Engine(object): (value>>12) & 0x3f, (value>>18) & 0x3f] if self.big: raw = reversed(raw) - return bjoin_elems(imap(self._encode64, raw)) + return join_byte_elems(imap(self._encode64, raw)) def encode_int64(self, value): """encode 64-bit integer -> 11 char hash64 string @@ -1319,7 +1319,7 @@ else: return None return result -_add_doc(safe_crypt, """wrapper around stdlib's crypt. +add_doc(safe_crypt, """wrapper around stdlib's crypt. This is a wrapper around stdlib's :func:`!crypt.crypt`, which attempts to provide uniform behavior across Python 2 and 3. @@ -1467,7 +1467,7 @@ def getrandbytes(rng, count): yield value & 0xff value >>= 3 i += 1 - return bjoin_ints(helper()) + return join_byte_values(helper()) def getrandstr(rng, charset, count): """return string containing *count* number of chars/bytes, whose elements are drawn from specified charset, using specified rng""" @@ -1494,9 +1494,9 @@ def getrandstr(rng, charset, count): i += 1 if isinstance(charset, unicode): - return ujoin(helper()) + return join_unicode(helper()) else: - return bjoin_elems(helper()) + return join_byte_elems(helper()) _52charset = '2346789ABCDEFGHJKMNPQRTUVWXYZabcdefghjkmnpqrstuvwxyz' diff --git a/passlib/utils/compat.py b/passlib/utils/compat.py index 6bf8c50..0715f28 100644 --- a/passlib/utils/compat.py +++ b/passlib/utils/compat.py @@ -18,8 +18,7 @@ if PY3: else: import __builtin__ as builtins - -def _add_doc(obj, doc): +def add_doc(obj, doc): """add docstring to an object""" obj.__doc__ = doc @@ -31,7 +30,7 @@ __all__ = [ 'PY2', 'PY3', 'PY_MAX_25', 'PY27', 'PY_MIN_32', # io - 'BytesIO', 'StringIO', 'SafeConfigParser', + 'BytesIO', 'StringIO', 'NativeStringIO', 'SafeConfigParser', 'print_', # type detection @@ -45,57 +44,24 @@ __all__ = [ 'unicode', 'bytes', 'sb_types', 'uascii_to_str', 'bascii_to_str', 'str_to_uascii', 'str_to_bascii', - 'ujoin', 'bjoin', 'bjoin_ints', 'bjoin_elems', 'belem_ord', + 'join_unicode', 'join_bytes', + 'join_byte_values', 'join_byte_elems', + 'byte_elem_value', + 'iter_byte_values', # iteration helpers - 'irange', 'trange', #'lrange', + 'irange', #'lrange', 'imap', 'lmap', 'iteritems', 'itervalues', + 'next', # introspection - 'exc_err', 'get_method_function', '_add_doc', + 'exc_err', 'get_method_function', 'add_doc', ] -#============================================================================= -# lazy-loaded aliases (see LazyOverlayModule at bottom) -#============================================================================= -if PY3: - _lazy_attrs = dict( - BytesIO="io.BytesIO", - StringIO="io.StringIO", - SafeConfigParser="configparser.SafeConfigParser", - ) - if PY_MIN_32: - # py32 renamed this, removing old ConfigParser - _lazy_attrs["SafeConfigParser"] = "configparser.ConfigParser" -else: - _lazy_attrs = dict( - BytesIO="cStringIO.StringIO", - StringIO="StringIO.StringIO", - SafeConfigParser="ConfigParser.SafeConfigParser", - ) - -#============================================================================= -# typing -#============================================================================= -def is_mapping(obj): - # non-exhaustive check, enough to distinguish from lists, etc - return hasattr(obj, "items") - -if (3,0) <= sys.version_info < (3,2): - # callable isn't dead, it's just resting - from collections import Callable - def callable(obj): - return isinstance(obj, Callable) -else: - callable = builtins.callable - -if PY3: - int_types = (int,) - num_types = (int, float) -else: - int_types = (int, long) - num_types = (int, long, float) +# begin accumulating mapping of lazy-loaded attrs, +# 'merged' into module at bottom +_lazy_attrs = dict() #============================================================================= # unicode & bytes types @@ -103,7 +69,6 @@ else: if PY3: unicode = str bytes = builtins.bytes -# string_types = (unicode,) def u(s): assert isinstance(s, str) @@ -116,7 +81,6 @@ if PY3: else: unicode = builtins.unicode bytes = str if PY_MAX_25 else builtins.bytes -# string_types = (unicode, bytes) def u(s): assert isinstance(s, str) @@ -132,10 +96,10 @@ sb_types = (unicode, bytes) # unicode & bytes helpers #============================================================================= # function to join list of unicode strings -ujoin = u('').join +join_unicode = u('').join # function to join list of byte strings -bjoin = b('').join +join_bytes = b('').join if PY3: def uascii_to_str(s): @@ -154,12 +118,13 @@ if PY3: assert isinstance(s, str) return s.encode("ascii") - bjoin_ints = bjoin_elems = bytes + join_byte_values = join_byte_elems = bytes - def belem_ord(elem): + def byte_elem_value(elem): + assert isinstance(elem, int) return elem - def biter_ints(s): + def iter_byte_values(s): assert isinstance(s, bytes) return s @@ -180,43 +145,53 @@ else: assert isinstance(s, str) return s - def bjoin_ints(values): - return bjoin(chr(v) for v in values) + def join_byte_values(values): + return join_bytes(chr(v) for v in values) - bjoin_elems = bjoin + join_byte_elems = join_bytes - belem_ord = ord + byte_elem_value = ord - def biter_ints(s): + def iter_byte_values(s): assert isinstance(s, bytes) return (ord(c) for c in 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") +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") -# bjoin_ints -- function to convert list of ordinal integers to byte string. +# join_byte_values -- function to convert list of ordinal integers to byte string. -# bjoin_elems -- function to convert list of byte elements 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. -# belem_ord -- function to convert byte element to integer -- a noop under PY3 +# byte_elem_value -- function to convert byte element to integer -- a noop under PY3 -_add_doc(biter_ints, "helper to iterate over byte values in byte string") +add_doc(iter_byte_values, "helper to iterate over byte values in byte string") + +#============================================================================= +# numeric +#============================================================================= +if PY3: + int_types = (int,) + num_types = (int, float) +else: + int_types = (int, long) + num_types = (int, long, float) #============================================================================= # iteration helpers # -# irange - range iterator -# trange - immutable range sequence (list under py2, range object under py3) -# lrange - range list +# 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 = trange = range + irange = range ##def lrange(*a,**k): ## return list(range(*a,**k)) @@ -224,34 +199,51 @@ if PY3: return list(map(*a,**k)) imap = map + def iteritems(d): + return d.items() + def itervalues(d): + return d.values() else: irange = xrange - trange = range ##lrange = range lmap = map from itertools import imap -if PY3: - def iteritems(d): - return d.items() - def itervalues(d): - return d.values() -else: def iteritems(d): return d.iteritems() def itervalues(d): return d.itervalues() if PY_MAX_25: - def next(itr): + _undef = object() + def next(itr, default=_undef): "compat wrapper for next()" - # NOTE: omits support for 'default' arg - return itr.next() + if default is _undef: + return itr.next() + try: + return itr.next() + except StopIteration: + return default else: next = builtins.next #============================================================================= +# typing +#============================================================================= +def is_mapping(obj): + # non-exhaustive check, enough to distinguish from lists, etc + return hasattr(obj, "items") + +if (3,0) <= sys.version_info < (3,2): + # callable isn't dead, it's just resting + from collections import Callable + def callable(obj): + return isinstance(obj, Callable) +else: + callable = builtins.callable + +#============================================================================= # introspection #============================================================================= def exc_err(): @@ -269,8 +261,26 @@ else: # input/output #============================================================================= if PY3: + _lazy_attrs = dict( + BytesIO="io.BytesIO", + UnicodeIO="io.StringIO", + NativeStringIO="io.StringIO", + SafeConfigParser="configparser.SafeConfigParser", + ) + if sys.version_info >= (3,2): + # py32 renamed this, removing old ConfigParser + _lazy_attrs["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 @@ -318,13 +328,13 @@ else: #============================================================================= from types import ModuleType -def import_object(source): +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): +class _LazyOverlayModule(ModuleType): """proxy module which overlays original module, and lazily imports specified attributes. @@ -359,7 +369,7 @@ class LazyOverlayModule(ModuleType): if callable(source): value = source() else: - value = import_object(source) + value = _import_object(source) setattr(self, attr, value) self.__log.debug("loaded lazy attr %r: %r", attr, value) return value @@ -382,7 +392,7 @@ class LazyOverlayModule(ModuleType): return list(attrs) # replace this module with overlay that will lazily import attributes. -LazyOverlayModule.replace_module(__name__, _lazy_attrs) +_LazyOverlayModule.replace_module(__name__, _lazy_attrs) #============================================================================= # eof diff --git a/passlib/utils/des.py b/passlib/utils/des.py index 67c6d93..4172a2e 100644 --- a/passlib/utils/des.py +++ b/passlib/utils/des.py @@ -45,7 +45,7 @@ which has some nice notes on how this all works - # core import struct # pkg -from passlib.utils.compat import bytes, bjoin_ints, belem_ord, irange, trange +from passlib.utils.compat import bytes, join_byte_values, byte_elem_value, irange, irange # local __all__ = [ "expand_des_key", @@ -56,15 +56,15 @@ __all__ = [ #========================================================= #precalculated iteration ranges & constants #========================================================= -R8 = trange(8) -RR8 = trange(7, -1, -1) -RR4 = trange(3, -1, -1) -RR12_1 = trange(11, 1, -1) -RR9_1 = trange(9,-1,-1) +R8 = irange(8) +RR8 = irange(7, -1, -1) +RR4 = irange(3, -1, -1) +RR12_1 = irange(11, 1, -1) +RR9_1 = irange(9,-1,-1) -RR6_S2 = trange(6, -1, -2) -RR14_S2 = trange(14, -1, -2) -R16_S2 = trange(0, 16, 2) +RR6_S2 = irange(6, -1, -2) +RR14_S2 = irange(14, -1, -2) +R16_S2 = irange(0, 16, 2) INT_24_MAX = 0xffffff INT_64_MAX = 0xffffffff @@ -588,7 +588,7 @@ def expand_des_key(key): def iter_bits(source): for c in source: - v = belem_ord(c) + v = byte_elem_value(c) for i in irange(7,-1,-1): yield (v>>i) & 1 @@ -601,7 +601,7 @@ def expand_des_key(key): out = (out<<1) + p p = 1 - return bjoin_ints( + return join_byte_values( ((out>>s) & 0xFF) for s in irange(8*7,-8,-8) ) diff --git a/passlib/utils/handlers.py b/passlib/utils/handlers.py index 911bba2..2d283c5 100644 --- a/passlib/utils/handlers.py +++ b/passlib/utils/handlers.py @@ -19,8 +19,8 @@ from passlib.registry import get_crypt_handler from passlib.utils import classproperty, consteq, getrandstr, getrandbytes,\ BASE64_CHARS, HASH64_CHARS, rng, to_native_str, \ is_crypt_handler, deprecated_function, to_unicode -from passlib.utils.compat import b, bjoin_ints, bytes, irange, u, \ - uascii_to_str, ujoin, unicode, str_to_uascii +from passlib.utils.compat import b, join_byte_values, bytes, irange, u, \ + uascii_to_str, join_unicode, unicode, str_to_uascii # local __all__ = [ # helpers for implementing MCF handlers @@ -57,7 +57,7 @@ LOWER_HEX_CHARS = u("0123456789abcdef") #: special byte string containing all possible byte values # XXX: treated as singleton by some of the code for efficiency. -ALL_BYTE_VALUES = bjoin_ints(irange(256)) +ALL_BYTE_VALUES = join_byte_values(irange(256)) # deprecated aliases - will be removed after passlib 1.8 H64_CHARS = HASH64_CHARS |