summaryrefslogtreecommitdiff
path: root/passlib/utils
diff options
context:
space:
mode:
authorEli Collins <elic@assurancetechnologies.com>2012-01-18 17:51:32 -0500
committerEli Collins <elic@assurancetechnologies.com>2012-01-18 17:51:32 -0500
commit666aa14bf15ed898472463d2ec890de0b8c60923 (patch)
treef4ad79fb817cdca19e64dbb1abfe86c1a2c8ffc1 /passlib/utils
parentb6d904be92c77bce061c78034145958401bba381 (diff)
downloadpasslib-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__.py73
-rw-r--r--passlib/utils/_blowfish/__init__.py5
-rw-r--r--passlib/utils/compat.py115
-rw-r--r--passlib/utils/des.py5
-rw-r--r--passlib/utils/handlers.py16
-rw-r--r--passlib/utils/md4.py6
-rw-r--r--passlib/utils/pbkdf2.py5
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",