summaryrefslogtreecommitdiff
path: root/passlib/utils
diff options
context:
space:
mode:
authorEli Collins <elic@assurancetechnologies.com>2012-03-12 21:33:28 -0400
committerEli Collins <elic@assurancetechnologies.com>2012-03-12 21:33:28 -0400
commit3913a59ad033462e6a389544ffcdf8055db7ad9c (patch)
tree63dda089e61a9d8ef4b468a323df8c2ec2ad6c70 /passlib/utils
parentb970d6ee145122005f1e6808466900a94e00dfcc (diff)
downloadpasslib-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__.py44
-rw-r--r--passlib/utils/compat.py178
-rw-r--r--passlib/utils/des.py22
-rw-r--r--passlib/utils/handlers.py6
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