diff options
| author | Eli Collins <elic@assurancetechnologies.com> | 2012-01-18 17:51:32 -0500 |
|---|---|---|
| committer | Eli Collins <elic@assurancetechnologies.com> | 2012-01-18 17:51:32 -0500 |
| commit | 666aa14bf15ed898472463d2ec890de0b8c60923 (patch) | |
| tree | f4ad79fb817cdca19e64dbb1abfe86c1a2c8ffc1 /passlib/utils | |
| parent | b6d904be92c77bce061c78034145958401bba381 (diff) | |
| download | passlib-666aa14bf15ed898472463d2ec890de0b8c60923.tar.gz | |
import cleanups
* moved bytes compat functions from utils to utils.compat
(bord, bjoin, bjoin_ints, bjoin_elems, ujoin)
* renamed bord -> belem_ord for clarify
* a bunch of to_native_str() always use ascii, and
have fixed input types (always bytes or always unicode).
these don't need overhead of to_native_str(), so replaced
those calls with two new funcs: compat.bascii_to_str() /
compat.uascii_to_str()
* cleaned up a lot of imports from utils/utils.compat to
pull from correct module
* simplified the to_string() logic of a bunch of handlers
to reduce unicode<->byte transitions
Diffstat (limited to 'passlib/utils')
| -rw-r--r-- | passlib/utils/__init__.py | 73 | ||||
| -rw-r--r-- | passlib/utils/_blowfish/__init__.py | 5 | ||||
| -rw-r--r-- | passlib/utils/compat.py | 115 | ||||
| -rw-r--r-- | passlib/utils/des.py | 5 | ||||
| -rw-r--r-- | passlib/utils/handlers.py | 16 | ||||
| -rw-r--r-- | passlib/utils/md4.py | 6 | ||||
| -rw-r--r-- | passlib/utils/pbkdf2.py | 5 |
7 files changed, 114 insertions, 111 deletions
diff --git a/passlib/utils/__init__.py b/passlib/utils/__init__.py index 0f53a09..74d53c2 100644 --- a/passlib/utils/__init__.py +++ b/passlib/utils/__init__.py @@ -17,7 +17,9 @@ import unicodedata from warnings import warn #site #pkg -from passlib.utils.compat import irange, PY3, unicode, bytes, u, b, _add_doc +from passlib.utils.compat import _add_doc, b, bytes, bjoin, bjoin_ints, \ + bjoin_elems, exc_err, irange, imap, PY3, u, \ + ujoin, unicode #local __all__ = [ # constants @@ -33,9 +35,6 @@ __all__ = [ ## "relocated_function", ## "memoized_class_property", - #byte compat aliases - 'bytes', - # unicode helpers 'consteq', 'saslprep', @@ -245,7 +244,6 @@ def relocated_function(target, msg=None, name=None, deprecated=None, mod=None, #============================================================================= # unicode helpers #============================================================================= -ujoin = _UEMPTY.join def consteq(left, right): """check two strings/bytes for equality, taking constant time relative @@ -431,67 +429,9 @@ def saslprep(source, errname="value"): return data -#========================================================== +#============================================================================= # bytes helpers -#========================================================== - -#helpers for joining / extracting elements -bjoin = _BEMPTY.join - -#def bjoin_elems(elems): -# """takes series of bytes elements, returns bytes. -# -# elem should be result of bytes[x]. -# this is another bytes instance under py2, -# but it int under py3. -# -# returns bytes. -# -# this is bytes() constructor under py3, -# but b"".join() under py2. -# """ -# if PY3: -# return bytes(elems) -# else: -# return bjoin(elems) -# -#for efficiency, don't bother with above wrapper... -if PY3: - bjoin_elems = bytes -else: - bjoin_elems = bjoin - -#def bord(elem): -# """takes bytes element, returns integer. -# -# elem should be result of bytes[x]. -# this is another bytes instance under py2, -# but it int under py3. -# -# returns int in range(0,256). -# -# this is ord() under py2, and noop under py3. -# """ -# if PY3: -# assert isinstance(elem, int) -# return elem -# else: -# assert isinstance(elem, bytes) -# return ord(elem) -# -#for efficiency, don't bother with above wrapper... -if PY3: - def bord(elem): - return elem -else: - bord = ord - -if PY3: - bjoin_ints = bytes -else: - def bjoin_ints(values): - return bjoin(chr(v) for v in values) - +#============================================================================= if PY3: def xor_bytes(left, right): return bytes(l ^ r for l, r in zip(left, right)) @@ -525,9 +465,10 @@ 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 out = 0 for v in value: - out = (out<<8) | bord(v) + out = (out<<8) | belem_ord(v) return out @deprecated_function(deprecated="1.6", removed="1.8") diff --git a/passlib/utils/_blowfish/__init__.py b/passlib/utils/_blowfish/__init__.py index 41914dd..407b78f 100644 --- a/passlib/utils/_blowfish/__init__.py +++ b/passlib/utils/_blowfish/__init__.py @@ -54,9 +54,8 @@ released under the BSD license:: from itertools import chain import struct #pkg -from passlib.utils import Base64Engine, BCRYPT_CHARS, rng, getrandbytes, bytes, bord -from passlib.utils.compat import b, unicode, u -from passlib.utils.compat.aliases import BytesIO +from passlib.utils import Base64Engine, BCRYPT_CHARS, getrandbytes, rng +from passlib.utils.compat import b, bytes, BytesIO, unicode, u from passlib.utils._blowfish.unrolled import BlowfishEngine #local __all__ = [ diff --git a/passlib/utils/compat.py b/passlib/utils/compat.py index 5b7750c..26892ea 100644 --- a/passlib/utils/compat.py +++ b/passlib/utils/compat.py @@ -12,19 +12,46 @@ PY_MIN_32 = sys.version_info >= (3,2) # py 3.2 or later #============================================================================= # 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__ = [ - "u", "b", - "irange", "srange", ##"lrange", - "lmap", - "iteritems", + # python versions + 'PY2', 'PY3', 'PY_MAX_25', 'PY27', 'PY_MIN_32', + + # io + 'print_', + + # type detection + 'is_mapping', + 'callable', + 'int_types', + 'num_types', + + # unicode/bytes types & helpers + 'u', 'b', + 'unicode', 'bytes', 'sb_types', + 'uascii_to_str', 'bascii_to_str', + 'ujoin', 'bjoin', 'bjoin_ints', 'bjoin_elems', 'belem_ord', + + # iteration helpers + 'irange', 'trange', #'lrange', + 'imap', 'lmap', + 'iteritems', 'itervalues', + + # introspection + 'exc_err', 'get_method_function', '_add_doc', ] #============================================================================= @@ -85,7 +112,6 @@ if (3,0) <= sys.version_info < (3,2): from collections import Callable def callable(obj): return isinstance(obj, Callable) - __all__.append("callable") else: callable = builtins.callable @@ -97,36 +123,81 @@ else: num_types = (int, long, float) #============================================================================= -# unicode / bytes helpers +# unicode & bytes types #============================================================================= if PY3: + unicode = str + bytes = builtins.bytes +# string_types = (unicode,) + def u(s): + assert isinstance(s, str) return s + def b(s): assert isinstance(s, str) return s.encode("latin-1") - unicode = str - bytes = builtins.bytes - __all__.append("unicode") -# string_types = (unicode,) else: def u(s): + assert isinstance(s, str) return s.decode("unicode_escape") + def b(s): assert isinstance(s, str) return s - if PY_MAX_25: - bytes = str - __all__.append("bytes") - else: - bytes = builtins.bytes - unicode = builtins.unicode -# string_types = (unicode, bytes) sb_types = (unicode, bytes) -# bytes format +#============================================================================= +# unicode & bytes helpers +#============================================================================= +# function to join list of unicode strings +ujoin = u('').join + +# function to join list of byte strings +bjoin = 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") + + bjoin_ints = bjoin_elems = bytes + + def belem_ord(elem): + return elem + +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 bjoin_ints(values): + return bjoin(chr(v) for v in values) + + bjoin_elems = bjoin + + belem_ord = ord + +_add_doc(uascii_to_str, "helper to convert ascii unicode -> native str") +_add_doc(bascii_to_str, "helper to convert ascii bytes -> native str") + +# bjoin_ints -- function to convert list of ordinal integers to byte string. + +# bjoin_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 #============================================================================= # iteration helpers @@ -144,7 +215,7 @@ if PY3: def lmap(*a, **k): return list(map(*a,**k)) - # imap = map + imap = map else: irange = xrange @@ -152,7 +223,7 @@ else: ##lrange = range lmap = map - # from itertools import imap + from itertools import imap if PY3: def iteritems(d): @@ -179,10 +250,6 @@ else: def get_method_function(method): return method.im_func -def _add_doc(obj, doc): - """add docstring to an object""" - obj.__doc__ = doc - #============================================================================= # input/output #============================================================================= diff --git a/passlib/utils/des.py b/passlib/utils/des.py index ea01048..67c6d93 100644 --- a/passlib/utils/des.py +++ b/passlib/utils/des.py @@ -45,8 +45,7 @@ which has some nice notes on how this all works - # core import struct # pkg -from passlib.utils import bytes, bord, bjoin_ints -from passlib.utils.compat import trange, irange +from passlib.utils.compat import bytes, bjoin_ints, belem_ord, irange, trange # local __all__ = [ "expand_des_key", @@ -589,7 +588,7 @@ def expand_des_key(key): def iter_bits(source): for c in source: - v = bord(c) + v = belem_ord(c) for i in irange(7,-1,-1): yield (v>>i) & 1 diff --git a/passlib/utils/handlers.py b/passlib/utils/handlers.py index 52ab2cc..7643c01 100644 --- a/passlib/utils/handlers.py +++ b/passlib/utils/handlers.py @@ -14,11 +14,11 @@ from warnings import warn #site #libs from passlib.registry import get_crypt_handler -from passlib.utils import to_native_str, bytes, b, consteq, \ - classproperty, h64, getrandstr, getrandbytes, bjoin_ints, \ - rng, is_crypt_handler, ALL_BYTE_VALUES, MissingBackendError, \ - BASE64_CHARS, HASH64_CHARS -from passlib.utils.compat import unicode, u, irange +from passlib.utils import is_crypt_handler +from passlib.utils import classproperty, consteq, getrandstr, getrandbytes,\ + BASE64_CHARS, HASH64_CHARS, rng, to_native_str, MissingBackendError +from passlib.utils.compat import b, bjoin_ints, bytes, irange, u, \ + uascii_to_str, unicode #pkg #local __all__ = [ @@ -136,7 +136,7 @@ def render_mc2(ident, salt, checksum, sep=u("$")): hash = u("%s%s%s%s") % (ident, salt, sep, checksum) else: hash = u("%s%s") % (ident, salt) - return to_native_str(hash) + return uascii_to_str(hash) def render_mc3(ident, rounds, salt, checksum, sep=u("$")): "format hash using 3-part modular crypt format; inverse of parse_mc3" @@ -144,7 +144,7 @@ def render_mc3(ident, rounds, salt, checksum, sep=u("$")): hash = u("%s%s%s%s%s%s") % (ident, rounds, sep, salt, sep, checksum) else: hash = u("%s%s%s%s") % (ident, rounds, sep, salt) - return to_native_str(hash) + return uascii_to_str(hash) #===================================================== #StaticHandler @@ -1335,7 +1335,7 @@ class PrefixWrapper(object): if not hash.startswith(orig_prefix): raise ValueError("not a valid %s hash" % (self.wrapped.name,)) wrapped = self.prefix + hash[len(orig_prefix):] - return to_native_str(wrapped) + return uascii_to_str(wrapped) def identify(self, hash): if not hash: diff --git a/passlib/utils/md4.py b/passlib/utils/md4.py index df3be70..a63ad11 100644 --- a/passlib/utils/md4.py +++ b/passlib/utils/md4.py @@ -15,8 +15,7 @@ from binascii import hexlify import struct from warnings import warn #site -from passlib.utils import b, bytes, to_native_str -from passlib.utils.compat import irange, PY3 +from passlib.utils.compat import b, bytes, bascii_to_str, irange, PY3 #local __all__ = [ "md4" ] #========================================================================= @@ -224,8 +223,7 @@ class md4(object): return out def hexdigest(self): - # PY3: hexlify returns bytes, but hexdigest should return str. - return to_native_str(hexlify(self.digest())) + return bascii_to_str(hexlify(self.digest())) #========================================================================= #eoc diff --git a/passlib/utils/pbkdf2.py b/passlib/utils/pbkdf2.py index c48f751..c880457 100644 --- a/passlib/utils/pbkdf2.py +++ b/passlib/utils/pbkdf2.py @@ -20,9 +20,8 @@ try: except ImportError: _EVP = None #pkg -from passlib.utils import xor_bytes, to_bytes, b, bytes -from passlib.utils.compat import irange, callable, int_types -from passlib.utils.compat.aliases import BytesIO +from passlib.utils import to_bytes, xor_bytes +from passlib.utils.compat import b, bytes, BytesIO, irange, callable, int_types #local __all__ = [ "hmac_sha1", |
