diff options
| author | Eli Collins <elic@assurancetechnologies.com> | 2012-04-12 14:08:19 -0400 |
|---|---|---|
| committer | Eli Collins <elic@assurancetechnologies.com> | 2012-04-12 14:08:19 -0400 |
| commit | 8eb4c4d3b58eec6802c698ddbf357b2fd243a68c (patch) | |
| tree | ec1163825d3950bb7e5efe76f9b4ec210f2d1dda | |
| parent | a4a2d2414f7fa5d92abbc3f0d71da17425563994 (diff) | |
| download | passlib-8eb4c4d3b58eec6802c698ddbf357b2fd243a68c.tar.gz | |
wrote out all the known issues; made an attempt at deal w/ unicode-v-bytes issues, will try again some other time
| -rw-r--r-- | passlib/utils/__init__.py | 12 | ||||
| -rw-r--r-- | passlib/utils/compat.py | 106 |
2 files changed, 88 insertions, 30 deletions
diff --git a/passlib/utils/__init__.py b/passlib/utils/__init__.py index a283299..8eecec3 100644 --- a/passlib/utils/__init__.py +++ b/passlib/utils/__init__.py @@ -1,13 +1,5 @@ """passlib.utils -- helpers for writing password hashes""" #============================================================================= -# Python VM identification -#============================================================================= -import sys -PYPY = hasattr(sys, "pypy_version_info") -JYTHON = sys.platform.startswith('java') -IRONPYTHON = 'IronPython' in sys.version - -#============================================================================= #imports #============================================================================= #core @@ -17,7 +9,9 @@ from functools import update_wrapper import logging; log = logging.getLogger(__name__) import math import os +import sys import random +from passlib.utils.compat import PYPY, IRONPYTHON, JYTHON _ipy_missing_stringprep = False if IRONPYTHON: try: @@ -606,7 +600,7 @@ def to_unicode(source, source_encoding="utf-8", errname="value"): else: raise ExpectedStringError(source, errname) -if PY3: +if PY3 or IRONPYTHON: def to_native_str(source, encoding="utf-8", errname="value"): if isinstance(source, bytes): return source.decode(encoding) diff --git a/passlib/utils/compat.py b/passlib/utils/compat.py index 7bffb15..3d7b012 100644 --- a/passlib/utils/compat.py +++ b/passlib/utils/compat.py @@ -10,6 +10,54 @@ PY27 = sys.version_info[:2] == (2,7) # supports last 2.x release PY_MIN_32 = sys.version_info >= (3,2) # py 3.2 or later #============================================================================= +# figure out what VM we're running +#============================================================================= +PYPY = hasattr(sys, "pypy_version_info") +JYTHON = sys.platform.startswith('java') +IRONPYTHON = 'IronPython' in sys.version +if IRONPYTHON: + from warnings import warn + warn("All of Passlib's lazy-import features are disabled under IronPython") + # NOTE: this is due to IPY 2.7.2 not supporting __getattr__ and __dir__ + # in ModuleType subclasses that are inserted into sys.modules. + + """ + disabled features under ironpython + ================================== + + * passlib.utils.compat's lazy import behavior doesn't work, + since __getattr__ and __dir__ aren't honor for ModuleType subclasses. + + * saslprep() is disabled, since the 'stringprep' module isn't available. + + remaining issues + ================ + * lazy import behavior for hash object probably won't work either. + + * apparently native str is unicode even under 2.7. + this breaks a bunch of assumptions in passlib. + this will be a real headache. but argues for feature-detection + rather than version-detection. + + made a stab to change all unicode/bytes wrappers accordingly, + and then discovered... + + ``u'abc'.encode("utf-8")`` is u'abc', not b'abc' !?! + + will try to work on this some other time. + """ + +##if PYPY: +## PYVM = "pypy" +##elif JYTHON: +## PYVM = "jython" +##elif IRONPYTHON: +## PYVM = "ironpython" +##else: +## # NOTE: all other vms will show up as this +## PYVM = "cpython" + +#============================================================================= # common imports #============================================================================= import logging; log = logging.getLogger(__name__) @@ -29,6 +77,9 @@ __all__ = [ # python versions 'PY2', 'PY3', 'PY_MAX_25', 'PY27', 'PY_MIN_32', + # python VMs + 'PYPY', 'JYTHON', 'IRONPYTHON', + # io 'BytesIO', 'StringIO', 'NativeStringIO', 'SafeConfigParser', 'print_', @@ -67,9 +118,12 @@ _lazy_attrs = dict() #============================================================================= # unicode & bytes types #============================================================================= -if PY3: +if PY3 or IRONPYTHON: + # IPY 2.7.2 has native unicode strings like PY3. + unicode = str bytes = builtins.bytes + base_string_types = (unicode, bytes) def u(s): assert isinstance(s, str) @@ -79,11 +133,10 @@ if PY3: assert isinstance(s, str) return s.encode("latin-1") - base_string_types = (unicode, bytes) - else: unicode = builtins.unicode bytes = str if PY_MAX_25 else builtins.bytes + base_string_types = basestring def u(s): assert isinstance(s, str) @@ -93,8 +146,6 @@ else: assert isinstance(s, str) return s - base_string_types = basestring - #============================================================================= # unicode & bytes helpers #============================================================================= @@ -104,7 +155,7 @@ join_unicode = u('').join # function to join list of byte strings join_bytes = b('').join -if PY3: +if PY3 or IRONPYTHON: def uascii_to_str(s): assert isinstance(s, unicode) return s @@ -121,17 +172,8 @@ if PY3: assert isinstance(s, str) return s.encode("ascii") - join_byte_values = join_byte_elems = bytes - - def byte_elem_value(elem): - assert isinstance(elem, int) - return elem - - def iter_byte_values(s): - assert isinstance(s, bytes) - return s - else: + def uascii_to_str(s): assert isinstance(s, unicode) return s.encode("ascii") @@ -148,6 +190,19 @@ else: assert isinstance(s, str) return s +if PY3: + join_byte_values = join_byte_elems = bytes + + def byte_elem_value(elem): + assert isinstance(elem, int) + return elem + + def iter_byte_values(s): + assert isinstance(s, bytes) + return s + +else: + def join_byte_values(values): return join_bytes(chr(v) for v in values) @@ -337,6 +392,13 @@ def _import_object(source): mod = __import__(modname, fromlist=[modattr], level=0) return getattr(mod, modattr) +def _resolve_object(source): + "resolve _LazyOverlayModule value" + if callable(source): + value = source() + else: + value = _import_object(source) + class _LazyOverlayModule(ModuleType): """proxy module which overlays original module, and lazily imports specified attributes. @@ -352,6 +414,12 @@ class _LazyOverlayModule(ModuleType): @classmethod def replace_module(cls, name, attrmap): orig = sys.modules[name] + if IRONPYTHON: + # lazy modules don't work under IPY 2.7 (see note at top of this file). + # so we just un-lazy everything! + for attr, source in attrmap.items(): + setattr(orig, attr, _resolve_object(source)) + return orig self = cls(name, attrmap, orig) sys.modules[name] = self return self @@ -368,11 +436,7 @@ class _LazyOverlayModule(ModuleType): return getattr(proxy, attr) attrmap = self.__attrmap if attr in attrmap: - source = attrmap[attr] - if callable(source): - value = source() - else: - value = _import_object(source) + value = _resolve_object(attrmap[attr]) setattr(self, attr, value) self.__log.debug("loaded lazy attr %r: %r", attr, value) return value |
