summaryrefslogtreecommitdiff
path: root/passlib
diff options
context:
space:
mode:
authorEli Collins <elic@assurancetechnologies.com>2011-12-06 12:40:53 -0500
committerEli Collins <elic@assurancetechnologies.com>2011-12-06 12:40:53 -0500
commitd07f2084c1532c121935cebf92cdbdd41c43bb57 (patch)
tree6b4de725a11627b7dab460ac1e000b4a107daae7 /passlib
parent295e3874293a3697b593f7e15fcbed9f5d580fb4 (diff)
downloadpasslib-d07f2084c1532c121935cebf92cdbdd41c43bb57.tar.gz
added compatibility module (passlib.utils.compat)
exports specialized range & map aliases, and some dict helpers * all dict.iteritems() calls replaced with compat.iteritems(dict) * all xrange() calls replaced with compat.irange() * all range() calls replaced with compat.trange() and compat.lrange() as appropriate * all map() calls replaced with compat.lmap()
Diffstat (limited to 'passlib')
-rw-r--r--passlib/apache.py7
-rw-r--r--passlib/context.py20
-rw-r--r--passlib/handlers/fshp.py3
-rw-r--r--passlib/handlers/sun_md5_crypt.py3
-rw-r--r--passlib/tests/genconfig.py7
-rw-r--r--passlib/tests/test_ext_django.py3
-rw-r--r--passlib/tests/test_utils.py2
-rw-r--r--passlib/tests/utils.py3
-rw-r--r--passlib/utils/_blowfish/_gen_files.py9
-rw-r--r--passlib/utils/compat.py96
-rw-r--r--passlib/utils/des.py19
11 files changed, 136 insertions, 36 deletions
diff --git a/passlib/apache.py b/passlib/apache.py
index 0bf3301..b43e04d 100644
--- a/passlib/apache.py
+++ b/passlib/apache.py
@@ -13,6 +13,7 @@ import sys
from passlib.context import CryptContext
from passlib.utils import render_bytes, bjoin, bytes, b, \
to_unicode, to_bytes, consteq
+from passlib.utils.compat import lmap
#pkg
#local
__all__ = [
@@ -319,7 +320,7 @@ class HtpasswdFile(_CommonFile):
def users(self):
"return list of all users in file"
- return map(self._decode_ident, self._entry_order)
+ return lmap(self._decode_ident, self._entry_order)
def update(self, user, password):
"""update password for user; adds user if needed.
@@ -454,13 +455,13 @@ class HtdigestFile(_CommonFile):
def realms(self):
"return all realms listed in file"
- return map(self._decode_ident,
+ return lmap(self._decode_ident,
set(key[1] for key in self._entry_order))
def users(self, realm):
"return list of all users within specified realm"
realm = self._norm_realm(realm)
- return map(self._decode_ident,
+ return lmap(self._decode_ident,
(key[0] for key in self._entry_order if key[1] == realm))
def update(self, user, realm, password):
diff --git a/passlib/context.py b/passlib/context.py
index adcf467..91441c2 100644
--- a/passlib/context.py
+++ b/passlib/context.py
@@ -29,6 +29,7 @@ except ImportError:
from passlib.registry import get_crypt_handler, _unload_handler_name
from passlib.utils import to_bytes, to_unicode, bytes, Undef, \
is_crypt_handler, splitcomma, rng
+from passlib.utils.compat import is_mapping, iteritems
#pkg
#local
__all__ = [
@@ -103,13 +104,8 @@ def _parse_policy_value(cat, name, opt, value):
def parse_policy_items(source):
"helper to parse CryptPolicy options"
- # py2k #
- if hasattr(source, "iteritems"):
- source = source.iteritems()
- # py3k #
- #if hasattr(source, "items"):
- # source = source.items()
- # end py3k #
+ if is_mapping(source):
+ source = iteritems(source)
for key, value in source:
cat, name, opt = _parse_policy_key(key)
if name == "context":
@@ -405,7 +401,7 @@ class CryptPolicy(object):
dmap = self._deprecated = {}
fmap = self._default = {}
mvmap = self._min_verify_time = {}
- for cat, config in options.iteritems():
+ for cat, config in iteritems(options):
kwds = config.pop("context", None)
if not kwds:
continue
@@ -618,16 +614,16 @@ class CryptPolicy(object):
if value:
yield format_key(None, None, "schemes"), encode_hlist(value)
- for cat, value in self._deprecated.iteritems():
+ for cat, value in iteritems(self._deprecated):
yield format_key(cat, None, "deprecated"), encode_nlist(value)
- for cat, value in self._default.iteritems():
+ for cat, value in iteritems(self._default):
yield format_key(cat, None, "default"), encode_handler(value)
- for cat, value in self._min_verify_time.iteritems():
+ for cat, value in iteritems(self._min_verify_time):
yield format_key(cat, None, "min_verify_time"), value
- for cat, copts in self._options.iteritems():
+ for cat, copts in iteritems(self._options):
for name in sorted(copts):
config = copts[name]
for opt in sorted(config):
diff --git a/passlib/handlers/fshp.py b/passlib/handlers/fshp.py
index 0ca1dd3..e9bc23c 100644
--- a/passlib/handlers/fshp.py
+++ b/passlib/handlers/fshp.py
@@ -12,6 +12,7 @@ from warnings import warn
#site
#libs
from passlib.utils import handlers as uh, bytes, b, to_hash_str
+from passlib.utils.compat import iteritems
from passlib.utils.pbkdf2 import pbkdf1
#pkg
#local
@@ -79,7 +80,7 @@ class fshp(uh.HasRounds, uh.HasRawSalt, uh.HasRawChecksum, uh.GenericHandler):
}
_variant_aliases = dict(
[(unicode(k),k) for k in _variant_info] +
- [(v[0],k) for k,v in _variant_info.items()]
+ [(v[0],k) for k,v in iteritems(_variant_info)]
)
#=========================================================
diff --git a/passlib/handlers/sun_md5_crypt.py b/passlib/handlers/sun_md5_crypt.py
index 79b2872..6bfab75 100644
--- a/passlib/handlers/sun_md5_crypt.py
+++ b/passlib/handlers/sun_md5_crypt.py
@@ -18,6 +18,7 @@ from warnings import warn
#site
#libs
from passlib.utils import h64, handlers as uh, to_hash_str, to_unicode, bytes, b, bord
+from passlib.utils.compat import trange
#pkg
#local
__all__ = [
@@ -70,7 +71,7 @@ MAGIC_HAMLET = b(
)
#NOTE: these sequences are pre-calculated iteration ranges used by X & Y loops w/in rounds function below
-xr = range(7)
+xr = trange(7)
_XY_ROUNDS = [
tuple((i,i,i+3) for i in xr), #xrounds 0
tuple((i,i+1,i+4) for i in xr), #xrounds 1
diff --git a/passlib/tests/genconfig.py b/passlib/tests/genconfig.py
index 0abdaab..e544a7d 100644
--- a/passlib/tests/genconfig.py
+++ b/passlib/tests/genconfig.py
@@ -15,6 +15,7 @@ import time
import sys
#site
#pkg
+from passlib.utils.compat import iteritems
from passlib.registry import get_crypt_handler
#local
log = logging.getLogger(__name__)
@@ -76,7 +77,7 @@ class HashTimer(object):
#
self.samples = samples
self.cache = {}
- self.srange = range(samples)
+ self.srange = trange(samples)
def time_encrypt(self, rounds):
"check how long encryption for a given number of rounds will take"
@@ -121,7 +122,7 @@ class HashTimer(object):
#check if useful lower & upper bounds already exist in cache
#
lower = upper = None
- for rounds, delta in self.cache.iteritems():
+ for rounds, delta in iteritems(self.cache.iteritems):
if delta < target:
if lower is None or rounds > lower:
lower = rounds
@@ -203,7 +204,7 @@ class HashTimer(object):
if not cache:
raise RuntimeError("should not be called until cache populated by find_rounds()")
get_rps = self.get_rps
- rps = sum(r*get_rps(r,d) for r,d in cache.iteritems())/sum(cache)
+ rps = sum(r*get_rps(r,d) for r,d in iteritems(cache))/sum(cache)
if rps > 1000: #for almost all cases, we'd return integer
rps = int(rps)
return rps
diff --git a/passlib/tests/test_ext_django.py b/passlib/tests/test_ext_django.py
index 95ee927..cd53b6f 100644
--- a/passlib/tests/test_ext_django.py
+++ b/passlib/tests/test_ext_django.py
@@ -16,6 +16,7 @@ from passlib.hash import sha256_crypt
from passlib.tests.utils import TestCase, unittest, ut_version, catch_warnings
import passlib.tests.test_drivers as td
from passlib.utils import Undef
+from passlib.utils.compat import iteritems
from passlib.registry import get_crypt_handler
#module
@@ -53,7 +54,7 @@ if has_django:
settings.configure()
def update_settings(**kwds):
- for k,v in kwds.iteritems():
+ for k,v in iteritems(kwds):
if v is Undef:
if hasattr(settings, k):
if has_django0:
diff --git a/passlib/tests/test_utils.py b/passlib/tests/test_utils.py
index 6c19679..b5fe81a 100644
--- a/passlib/tests/test_utils.py
+++ b/passlib/tests/test_utils.py
@@ -200,7 +200,7 @@ class MiscTest(TestCase):
# NOTE: below code was used to generate stats for analysis
##from math import log as logb
##import timeit
- ##multipliers = [ 1<<s for s in range(9)]
+ ##multipliers = [ 1<<s for s in irange(9)]
##correct = u"abcdefgh"*(1<<4)
##incorrect = u"abcdxfgh"
##print
diff --git a/passlib/tests/utils.py b/passlib/tests/utils.py
index 20c95bf..42706d3 100644
--- a/passlib/tests/utils.py
+++ b/passlib/tests/utils.py
@@ -37,6 +37,7 @@ from passlib import registry, utils
from passlib.utils import classproperty, handlers as uh, \
has_rounds_info, has_salt_info, MissingBackendError, \
rounds_cost_values, b, bytes, native_str, NoneType
+from passlib.utils.compat import iteritems
#local
__all__ = [
#util funcs
@@ -662,7 +663,7 @@ class HandlerCase(TestCase):
#check optional aliases list
if cls.ident_aliases:
- for alias, ident in cls.ident_aliases.iteritems():
+ for alias, ident in iteritems(cls.ident_aliases):
self.assertIsInstance(alias, unicode,
"cls.ident_aliases keys must be unicode:") #XXX: allow ints?
self.assertIsInstance(ident, unicode,
diff --git a/passlib/utils/_blowfish/_gen_files.py b/passlib/utils/_blowfish/_gen_files.py
index f02ff39..6256bc5 100644
--- a/passlib/utils/_blowfish/_gen_files.py
+++ b/passlib/utils/_blowfish/_gen_files.py
@@ -6,13 +6,14 @@
import os
import textwrap
# pkg
+from passlib.utils.compat import irange
# local
#==========================================================================
# helpers
#==========================================================================
def varlist(name, count):
- return ", ".join(name + str(x) for x in range(count))
+ return ", ".join(name + str(x) for x in irange(count))
def indent_block(block, padding):
@@ -29,7 +30,7 @@ BFSTR = """\
""".strip()
def render_encipher(write, indent=0):
- for i in range(0, 15, 2):
+ for i in irange(0, 15, 2):
write(indent, """\
# Feistel substitution on left word (round %(i)d)
r ^= %(left)s ^ p%(i1)d
@@ -73,7 +74,7 @@ def write_expand_function(write, indent=0):
# integrate key
#=============================================================
""")
- for i in range(18):
+ for i in irange(18):
write(indent+1, """\
p%(i)d = P[%(i)d] ^ key_words[%(i)d]
""", i=i)
@@ -98,7 +99,7 @@ def write_expand_function(write, indent=0):
""")
- for i in range(2, 18, 2):
+ for i in irange(2, 18, 2):
write(indent+1, """\
#------------------------------------------------
# update P[%(i)d] and P[%(i1)d]
diff --git a/passlib/utils/compat.py b/passlib/utils/compat.py
new file mode 100644
index 0000000..dc6e0c4
--- /dev/null
+++ b/passlib/utils/compat.py
@@ -0,0 +1,96 @@
+"""passlib.utils.compat - python 2/3 compatibility helpers"""
+#=============================================================================
+# figure out what version we're running
+#=============================================================================
+from sys import version as pyver
+PY3 = pyver >= (3,0)
+PY_MAX_25 = pyver < (2,6) # py 2.5 or earlier
+PY_MIN_32 = pyver >= (3,2) # py 3.2 or later
+
+#=============================================================================
+# the default exported vars
+#=============================================================================
+__all__ = [
+ "u", "b",
+ "irange", "srange", ##"lrange",
+ "lmap",
+ "iteritems",
+]
+
+if PY_MAX_25:
+ __all__.append("bytes")
+elif PY3:
+ __all__.append("unicode")
+
+#=============================================================================
+# typing
+#=============================================================================
+if PY_MAX_25:
+ def is_mapping(obj):
+ # non-exhaustive check, enough to distinguish from lists, etc
+ return hasattr(obj, "items")
+else:
+ from collections import Mapping
+ def is_mapping(obj):
+ return isinstance(obj, Mapping)
+
+#=============================================================================
+# unicode / bytes helpers
+#=============================================================================
+if PY3:
+ def u(s):
+ return s
+ def b(s):
+ return s.encode("latin-1")
+ unicode = str
+# string_types = (str,)
+else:
+ def u(s):
+ return s.decode("unicode_escape")
+ def b(s):
+ return s
+ if PY_MAX_25:
+ bytes = str
+# string_types = (unicode,str)
+
+#=============================================================================
+# bytes-specific helpers
+#=============================================================================
+# bytes format
+
+#=============================================================================
+# iteration helpers
+#
+# irange - range iterator
+# trange - immutable range sequence (list under py2, range object under py3)
+# lrange - range list
+#
+# lmap - map to list
+#=============================================================================
+if PY3:
+ irange = trange = range
+ ##def lrange(*a,**k):
+ ## return list(range(*a,**k))
+
+ def lmap(*a, **k):
+ return list(map(*a,**k))
+ # imap = map
+
+else:
+ irange = xrange
+ trange = range
+ ##lrange = range
+
+ lmap = map
+ # from itertools import imap
+
+if PY3:
+ def iteritems(d):
+ return d.items()
+else:
+ def iteritems(d):
+ return d.iteritems()
+
+#=============================================================================
+# eof
+#=============================================================================
diff --git a/passlib/utils/des.py b/passlib/utils/des.py
index 805a265..d9f4694 100644
--- a/passlib/utils/des.py
+++ b/passlib/utils/des.py
@@ -44,6 +44,7 @@ which has some nice notes on how this all works -
#=========================================================
#pkg
from passlib.utils import bytes_to_int, int_to_bytes, bytes, bord, bjoin_ints
+from passlib.utils.compat import trange
#local
__all__ = [
"expand_des_key",
@@ -54,15 +55,15 @@ __all__ = [
#=========================================================
#precalculated iteration ranges & constants
#=========================================================
-R8 = range(8)
-RR8 = range(7, -1, -1)
-RR4 = range(3, -1, -1)
-RR12_1 = range(11, 1, -1)
-RR9_1 = range(9,-1,-1)
-
-RR6_S2 = range(6, -1, -2)
-RR14_S2 = range(14, -1, -2)
-R16_S2 = range(0, 16, 2)
+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)
+
+RR6_S2 = trange(6, -1, -2)
+RR14_S2 = trange(14, -1, -2)
+R16_S2 = trange(0, 16, 2)
INT_24_MAX = 0xffffff
INT_64_MAX = 0xffffffff