summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEli Collins <elic@assurancetechnologies.com>2012-01-18 16:37:53 -0500
committerEli Collins <elic@assurancetechnologies.com>2012-01-18 16:37:53 -0500
commit8cc56a03f05fac2d5717394ced5f53cf71b17814 (patch)
tree69e8f5907537cc93558c16d141720560533d7a6c
parentffb343b6bb0ba8b6015f19493347c7aae65739fd (diff)
downloadpasslib-8cc56a03f05fac2d5717394ced5f53cf71b17814.tar.gz
cleanups to utils
-rw-r--r--passlib/apps.py2
-rw-r--r--passlib/hosts.py4
-rw-r--r--passlib/tests/test_utils_handlers.py4
-rw-r--r--passlib/utils/__init__.py150
-rw-r--r--passlib/utils/compat.py15
-rw-r--r--passlib/utils/md4.py4
6 files changed, 82 insertions, 97 deletions
diff --git a/passlib/apps.py b/passlib/apps.py
index be16090..8040b46 100644
--- a/passlib/apps.py
+++ b/passlib/apps.py
@@ -9,7 +9,7 @@ from itertools import chain
#libs
from passlib import hash
from passlib.context import LazyCryptContext
-from passlib.utils.compat import sys_bits
+from passlib.utils import sys_bits
#pkg
#local
__all__ = [
diff --git a/passlib/hosts.py b/passlib/hosts.py
index 4ef2bca..38b3bf6 100644
--- a/passlib/hosts.py
+++ b/passlib/hosts.py
@@ -8,7 +8,7 @@ from warnings import warn
#pkg
from passlib.context import LazyCryptContext
from passlib.registry import get_crypt_handler
-from passlib.utils import os_crypt, unix_crypt_schemes
+from passlib.utils import has_os_crypt, unix_crypt_schemes
#local
__all__ = [
"linux_context", "linux2_context",
@@ -56,7 +56,7 @@ netbsd_context = LazyCryptContext([ "bcrypt", "sha1_crypt", "md5_crypt", "bsdi_c
#=========================================================
#current host
#=========================================================
-if os_crypt:
+if has_os_crypt:
#NOTE: this is basically mimicing the output of os crypt(),
#except that it uses passlib's (usually stronger) defaults settings,
#and can be introspected and used much more flexibly.
diff --git a/passlib/tests/test_utils_handlers.py b/passlib/tests/test_utils_handlers.py
index 3f4fb60..838d016 100644
--- a/passlib/tests/test_utils_handlers.py
+++ b/passlib/tests/test_utils_handlers.py
@@ -14,8 +14,8 @@ from passlib.hash import ldap_md5, sha256_crypt
from passlib.registry import _unload_handler_name as unload_handler_name, \
register_crypt_handler, get_crypt_handler
from passlib.utils import rng, getrandstr, handlers as uh, bytes, b, \
- to_native_str, to_unicode, MissingBackendError
-from passlib.utils.compat import unicode, JYTHON
+ to_native_str, to_unicode, MissingBackendError, JYTHON
+from passlib.utils.compat import unicode
from passlib.tests.utils import HandlerCase, TestCase, catch_warnings, \
dummy_handler_in_registry
from passlib.utils.compat import u
diff --git a/passlib/utils/__init__.py b/passlib/utils/__init__.py
index 6a6409b..0f53a09 100644
--- a/passlib/utils/__init__.py
+++ b/passlib/utils/__init__.py
@@ -1,13 +1,13 @@
-"""passlib utility functions"""
-#=================================================================================
+"""passlib.utils -- helpers for writing password hashes"""
+#=============================================================================
#imports
-#=================================================================================
+#=============================================================================
#core
from base64 import b64encode, b64decode
from codecs import lookup as _lookup_codec
from functools import update_wrapper
import logging; log = logging.getLogger(__name__)
-from math import log as logb
+import math
import os
import sys
import random
@@ -17,16 +17,17 @@ import unicodedata
from warnings import warn
#site
#pkg
-from passlib.utils.compat import irange, PY3, sys_bits, unicode, bytes, u, b, \
- _add_doc
+from passlib.utils.compat import irange, PY3, unicode, bytes, u, b, _add_doc
#local
__all__ = [
# constants
+ 'PYPY',
+ 'JYTHON',
'sys_bits',
'unix_crypt_schemes',
'rounds_cost_values',
- #decorators
+ # decorators
"classproperty",
## "deprecated_function",
## "relocated_function",
@@ -35,17 +36,20 @@ __all__ = [
#byte compat aliases
'bytes',
- # string manipulation
+ # unicode helpers
'consteq',
'saslprep',
- #byte manipulation
+ # bytes helpers
"xor_bytes",
+ "render_bytes",
- #bytes<->unicode
+ # encoding helpers
+ 'is_same_codec',
+ 'is_ascii_safe',
'to_bytes',
'to_unicode',
- 'is_same_codec',
+ 'to_native_str',
# base64 helpers
"BASE64_CHARS", "HASH64_CHARS", "BCRYPT_CHARS", "AB64_CHARS",
@@ -73,6 +77,13 @@ __all__ = [
# constants
#=================================================================================
+# Python VM identification
+PYPY = hasattr(sys, "pypy_version_info")
+JYTHON = sys.platform.startswith('java')
+
+# bitsize of system architecture (32 or 64)
+sys_bits = int(math.log(sys.maxsize if PY3 else sys.maxint, 2) + 1.5)
+
# list of hashes supported by os.crypt() on at least one OS.
unix_crypt_schemes = [
"sha512_crypt", "sha256_crypt",
@@ -231,9 +242,9 @@ def relocated_function(target, msg=None, name=None, deprecated=None, mod=None,
## def __func__(self):
## "py3 compatible alias"
-#=================================================================================
-#string helpers
-#=================================================================================
+#=============================================================================
+# unicode helpers
+#=============================================================================
ujoin = _UEMPTY.join
def consteq(left, right):
@@ -421,7 +432,7 @@ def saslprep(source, errname="value"):
return data
#==========================================================
-#bytes helpers
+# bytes helpers
#==========================================================
#helpers for joining / extracting elements
@@ -483,12 +494,11 @@ else:
if PY3:
def xor_bytes(left, right):
- "perform bitwise-xor of two byte-strings"
return bytes(l ^ r for l, r in zip(left, right))
else:
def xor_bytes(left, right):
- "perform bitwise-xor of two byte-strings"
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")
def render_bytes(source, *args):
"""helper for using formatting operator with bytes.
@@ -498,22 +508,18 @@ def render_bytes(source, *args):
this function is an attempt to provide a replacement
that will work uniformly under python 2 & 3.
- it converts everything to unicode (including bytes arguments),
- then encodes the result to latin-1.
+ it converts everything to unicode (decode bytes instances as latin-1),
+ performs the required formatting, then encodes the result to latin-1.
+
+ calling ``render_bytes(source, *args)`` should function the same as
+ ``source % args`` under python 2.
"""
if isinstance(source, bytes):
source = source.decode("latin-1")
- def adapt(arg):
- if isinstance(arg, bytes):
- return arg.decode("latin-1")
- return arg
- result = source % tuple(adapt(arg) for arg in args)
+ result = source % tuple(arg.decode("latin-1") if isinstance(arg, bytes)
+ else arg for arg in args)
return result.encode("latin-1")
-#=================================================================================
-#numeric helpers
-#=================================================================================
-
# NOTE: deprecating bytes<->int in favor of just using struct module.
@deprecated_function(deprecated="1.6", removed="1.8")
@@ -533,19 +539,18 @@ def int_to_bytes(value, count):
for s in irange(8*count-8,-8,-8)
)
-#==========================================================
-# bytes <-> unicode conversion helpers
-#==========================================================
-
+#=============================================================================
+# encoding helpers
+#=============================================================================
def is_same_codec(left, right):
- "check if two codecs names are aliases for same codec"
+ "check if two codec names are aliases for same codec"
if left == right:
return True
if not (left and right):
return False
return _lookup_codec(left).name == _lookup_codec(right).name
-_B80 = 128 if PY3 else b('\x80')
+_B80 = b('\x80')[0]
_U80 = u('\x80')
def is_ascii_safe(source):
"check if source (bytes or unicode) contains only 7-bit ascii"
@@ -553,70 +558,65 @@ def is_ascii_safe(source):
return all(c < r for c in source)
def to_bytes(source, encoding="utf-8", source_encoding=None, errname="value"):
- """helper to encoding unicode -> bytes
+ """helper to normalize input to bytes.
- this function takes in a ``source`` string.
- if unicode, encodes it using the specified ``encoding``.
- if bytes, returns unchanged - unless ``source_encoding``
- is specified, in which case the bytes are transcoded
- if and only if the source encoding doesn't match
- the desired encoding.
- all other types result in a :exc:`TypeError`.
+ :arg source:
+ Source bytes/unicode to process.
- :arg source: source bytes/unicode to process
- :arg encoding: target character encoding or ``None``.
- :param source_encoding: optional source encoding
- :param errname: optional name of variable/noun to reference when raising errors
+ :arg encoding:
+ Target encoding (defaults to ``"utf-8"``).
- :raises TypeError: if unicode encountered but ``encoding=None`` specified;
- or if source is not unicode or bytes.
+ :param source_encoding:
+ Source encoding (if known), used for transcoding.
- :returns: bytes object
+ :param errname:
+ Optional name of variable/noun to reference when raising errors
- .. note::
+ :raises TypeError: if source is not unicode or bytes.
- if ``encoding`` is set to ``None``, then unicode strings
- will be rejected, and only byte strings will be allowed through.
+ :returns:
+ * unicode strings will be encoded using *encoding*, and returned.
+ * if *source_encoding* is not specified, byte strings will be
+ returned unchanged.
+ * if *source_encoding* is specified, byte strings will be transcoded
+ to *encoding*.
"""
if isinstance(source, bytes):
- if source_encoding and encoding and \
- not is_same_codec(source_encoding, encoding):
+ if source_encoding and not is_same_codec(source_encoding, encoding):
return source.decode(source_encoding).encode(encoding)
else:
return source
- elif not encoding:
- raise TypeError("%s must be bytes, not %s" % (errname, type(source)))
elif isinstance(source, unicode):
return source.encode(encoding)
- elif source_encoding:
- raise TypeError("%s must be unicode or %s-encoded bytes, not %s" %
- (errname, source_encoding, type(source)))
else:
- raise TypeError("%s must be unicode or bytes, not %s" % (errname, type(source)))
+ raise TypeError("%s must be unicode or bytes, not %s" % (errname,
+ type(source)))
def to_unicode(source, source_encoding="utf-8", errname="value"):
- """take in unicode or bytes, return unicode
+ """helper to normalize input to unicode.
+
+ :arg source:
+ source bytes/unicode to process.
- if bytes provided, decodes using specified encoding.
- leaves unicode alone.
+ :arg source_encoding:
+ encoding to use when decoding bytes instances.
- :raises TypeError: if source is not unicode or bytes.
+ :param errname:
+ optional name of variable/noun to reference when raising errors.
- :arg source: source bytes/unicode to process
- :arg source_encoding: encoding to use when decoding bytes instances
- :param errname: optional name of variable/noun to reference when raising errors
+ :raises TypeError: if source is not unicode or bytes.
- :returns: unicode object
+ :returns:
+ * returns unicode strings unchanged.
+ * returns bytes strings decoded using *source_encoding*
"""
if isinstance(source, unicode):
return source
- elif not source_encoding:
- raise TypeError("%s must be unicode, not %s" % (errname, type(source)))
elif isinstance(source, bytes):
return source.decode(source_encoding)
else:
- raise TypeError("%s must be unicode or %s-encoded bytes, not %s" %
- (errname, source_encoding, type(source)))
+ raise TypeError("%s must be unicode or bytes, not %s" % (errname,
+ type(source)))
if PY3:
def to_native_str(source, encoding="utf-8", errname="value"):
@@ -638,10 +638,10 @@ else:
(errname, type(source)))
_add_doc(to_native_str,
- """take in unicode or bytes, return native string
+ """take in unicode or bytes, return native string.
python 2: encodes unicode using specified encoding, leaves bytes alone.
- python 3: decodes bytes using specified encoding, leaves unicode alone.
+ python 3: leaves unicode alone, decodes bytes using specified encoding.
:raises TypeError: if source is not unicode or bytes.
@@ -1208,8 +1208,10 @@ try:
from crypt import crypt as os_crypt
except ImportError: #pragma: no cover
safe_os_crypt = os_crypt = None
+ has_os_crypt = False
else:
# NOTE: see docstring below as to why we're wrapping os_crypt()
+ has_os_crypt = True
if PY3:
def safe_os_crypt(secret, hash):
if isinstance(secret, bytes):
diff --git a/passlib/utils/compat.py b/passlib/utils/compat.py
index bd39a5b..5b7750c 100644
--- a/passlib/utils/compat.py
+++ b/passlib/utils/compat.py
@@ -28,21 +28,6 @@ __all__ = [
]
#=============================================================================
-# host/vm configuration info
-#=============================================================================
-from math import log as logb
-if PY3:
- sys_bits = int(logb(sys.maxsize,2)+1.5)
-else:
- sys_bits = int(logb(sys.maxint,2)+1.5)
-del logb
-assert sys_bits in (32,64), "unexpected system bitsize: %r" % (sys_bits,)
-
-# VM identification
-PYPY = hasattr(sys, "pypy_version_info")
-JYTHON = sys.platform.startswith('java')
-
-#=============================================================================
# lazy import aliases
#=============================================================================
if PY3:
diff --git a/passlib/utils/md4.py b/passlib/utils/md4.py
index 435f98e..df3be70 100644
--- a/passlib/utils/md4.py
+++ b/passlib/utils/md4.py
@@ -237,8 +237,8 @@ _builtin_md4 = md4
#=========================================================================
#check if hashlib provides accelarated md4
#=========================================================================
-from passlib.utils.compat import PYPY
import hashlib
+from passlib.utils import PYPY
def _has_native_md4():
try:
@@ -262,8 +262,6 @@ if _has_native_md4():
def md4(content=None):
"wrapper for hashlib.new('md4')"
return hashlib.new('md4', content or b(''))
-else:
- del hashlib
#=========================================================================
#eof