diff options
| author | Eli Collins <elic@assurancetechnologies.com> | 2012-04-17 21:58:54 -0400 |
|---|---|---|
| committer | Eli Collins <elic@assurancetechnologies.com> | 2012-04-17 21:58:54 -0400 |
| commit | 2ad8463a456796300df5340a2bc511e290e62072 (patch) | |
| tree | 116a85776ae75ecde4c72c29b12c13d777b53c0f | |
| parent | ceb7a00ddae502624d609bc63a9048f0de9f1b23 (diff) | |
| download | passlib-2ad8463a456796300df5340a2bc511e290e62072.tar.gz | |
disabling saslprep() support under Jython - it lacks the stringprep module
| -rw-r--r-- | docs/lib/passlib.context-options.rst | 5 | ||||
| -rw-r--r-- | passlib/tests/test_context.py | 2 | ||||
| -rw-r--r-- | passlib/tests/test_context_deprecated.py | 56 | ||||
| -rw-r--r-- | passlib/tests/test_handlers.py | 6 | ||||
| -rw-r--r-- | passlib/tests/test_utils.py | 1 | ||||
| -rw-r--r-- | passlib/tests/utils.py | 7 | ||||
| -rw-r--r-- | passlib/utils/__init__.py | 31 | ||||
| -rw-r--r-- | passlib/utils/compat.py | 6 |
8 files changed, 51 insertions, 63 deletions
diff --git a/docs/lib/passlib.context-options.rst b/docs/lib/passlib.context-options.rst index 36cb89e..ece9033 100644 --- a/docs/lib/passlib.context-options.rst +++ b/docs/lib/passlib.context-options.rst @@ -169,6 +169,11 @@ and :samp:`{option}` is the name of the specific options being set. It is recommended to set this for all hashes via ``all__passprep``, instead of settings it per algorithm. + .. note:: + + Due to a missing :mod:`!stringprep` module, this feature + is not available on Jython. + :samp:`{hash}__{setting}` Any other option values, which match the name of a parameter listed diff --git a/passlib/tests/test_context.py b/passlib/tests/test_context.py index b1c7828..d039ac6 100644 --- a/passlib/tests/test_context.py +++ b/passlib/tests/test_context.py @@ -1263,6 +1263,8 @@ sha512_crypt__min_rounds = 45000 def test_61_passprep(self): "test passprep option" + self.require_stringprep() + # saslprep should normalize pu -> pn pu = u("a\u0300") # unnormalized unicode pn = u("\u00E0") # normalized unicode diff --git a/passlib/tests/test_context_deprecated.py b/passlib/tests/test_context_deprecated.py index e6aaffa..f6d33d8 100644 --- a/passlib/tests/test_context_deprecated.py +++ b/passlib/tests/test_context_deprecated.py @@ -1105,62 +1105,6 @@ class CryptContextTest(TestCase): res = ctx.verify_and_update(PASS1, BAD1) self.assertTrue(res[0] and res[1] and res[1] != BAD1) - def test_91_passprep(self): - "test passprep option" - # saslprep should normalize pu -> pn - pu = u("a\u0300") # unnormalized unicode - pn = u("\u00E0") # normalized unicode - - # create contexts w/ various options - craw = CryptContext(["md5_crypt"]) - cnorm = CryptContext(["md5_crypt"], all__passprep="saslprep") - cback = CryptContext(["md5_crypt"], all__passprep="saslprep,raw") - clst = [craw,cnorm,cback] - - # check raw encrypt against verify methods - h = craw.encrypt(pu) - - self.assertTrue(craw.verify(pu, h)) - self.assertFalse(cnorm.verify(pu, h)) - self.assertTrue(cback.verify(pu, h)) - - self.assertFalse(craw.verify(pn, h)) - self.assertFalse(craw.verify(pn, h)) - self.assertFalse(craw.verify(pn, h)) - - # check normalized encrypt against verify methods - for ctx in [cnorm, cback]: - h = ctx.encrypt(pu) - - self.assertFalse(craw.verify(pu, h)) - self.assertTrue(cnorm.verify(pu, h)) - self.assertTrue(cback.verify(pu, h)) - - for ctx2 in clst: - self.assertTrue(ctx2.verify(pn, h)) - - # check all encrypts leave normalized input alone - for ctx in clst: - h = ctx.encrypt(pn) - - self.assertFalse(craw.verify(pu, h)) - self.assertTrue(cnorm.verify(pu, h)) - self.assertTrue(cback.verify(pu, h)) - - for ctx2 in clst: - self.assertTrue(ctx2.verify(pn, h)) - - # test invalid name - self.assertRaises(KeyError, CryptContext, ["md5_crypt"], - all__passprep="xxx") - - # test per-hash passprep - ctx = CryptContext(["md5_crypt", "sha256_crypt"], - all__passprep="raw", sha256_crypt__passprep="saslprep", - ) - self.assertFalse(ctx.verify(pu, ctx.encrypt(pn, scheme="md5_crypt"))) - self.assertTrue(ctx.verify(pu, ctx.encrypt(pn, scheme="sha256_crypt"))) - #========================================================= #eoc #========================================================= diff --git a/passlib/tests/test_handlers.py b/passlib/tests/test_handlers.py index d045e94..102a3dc 100644 --- a/passlib/tests/test_handlers.py +++ b/passlib/tests/test_handlers.py @@ -1919,9 +1919,13 @@ class scram_test(HandlerCase): '$scram$4096$QSXCR.Q6sek8bf92$sha1=HZbuOlKbWl.eR8AfIposuKbhX30', ] - # silence norm_hash_name() warning def setUp(self): super(scram_test, self).setUp() + + # some platforms lack stringprep (e.g. Jython, IronPython) + self.require_stringprep() + + # silence norm_hash_name() warning warnings.filterwarnings("ignore", r"norm_hash_name\(\): unknown hash") def test_90_algs(self): diff --git a/passlib/tests/test_utils.py b/passlib/tests/test_utils.py index 001524d..a468ecf 100644 --- a/passlib/tests/test_utils.py +++ b/passlib/tests/test_utils.py @@ -295,6 +295,7 @@ class MiscTest(TestCase): def test_saslprep(self): "test saslprep() unicode normalizer" + self.require_stringprep() from passlib.utils import saslprep as sp # invalid types diff --git a/passlib/tests/utils.py b/passlib/tests/utils.py index eb8f3a7..ba439b7 100644 --- a/passlib/tests/utils.py +++ b/passlib/tests/utils.py @@ -505,6 +505,13 @@ class TestCase(unittest.TestCase): msg = "error for case %r:" % (elem.render(1),) self.assertEqual(result, correct, msg) + def require_stringprep(self): + "helper to skip test if stringprep is missing" + from passlib.utils import stringprep + if not stringprep: + from passlib.utils import _stringprep_missing_reason + raise self.skipTest("not available - stringprep module is " + + _stringprep_missing_reason) #============================================================ #eoc #============================================================ diff --git a/passlib/utils/__init__.py b/passlib/utils/__init__.py index d2fe9a5..dc89e4d 100644 --- a/passlib/utils/__init__.py +++ b/passlib/utils/__init__.py @@ -2,6 +2,7 @@ #============================================================================= #imports #============================================================================= +from passlib.utils.compat import PYPY, JYTHON #core from base64 import b64encode, b64decode from codecs import lookup as _lookup_codec @@ -11,9 +12,19 @@ import math import os import sys import random -import stringprep +if JYTHON: + # Jython 2.5.2 lacks stringprep module - + # see http://bugs.jython.org/issue1758320 + try: + import stringprep + except ImportError: + stringprep = None + _stringprep_missing_reason = "not present under Jython" +else: + import stringprep import time -import unicodedata +if stringprep: + import unicodedata from warnings import warn #site #pkg @@ -79,10 +90,6 @@ __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) @@ -371,6 +378,11 @@ def saslprep(source, errname="value"): :returns: normalized unicode string + + .. note:: + + Due to a missing :mod:`!stringprep` module, this feature + is not available on Jython. """ # saslprep - http://tools.ietf.org/html/rfc4013 # stringprep - http://tools.ietf.org/html/rfc3454 @@ -460,6 +472,13 @@ def saslprep(source, errname="value"): return data +# replace saslprep() with stub when stringprep is missing +if stringprep is None: + def saslprep(source, errname="value"): + "stub for saslprep()" + raise NotImplementedError("saslprep() support requires the 'stringprep' " + "module, which is " + _stringprep_missing_reason) + #============================================================================= # bytes helpers #============================================================================= diff --git a/passlib/utils/compat.py b/passlib/utils/compat.py index 77f9c3c..1d88f75 100644 --- a/passlib/utils/compat.py +++ b/passlib/utils/compat.py @@ -10,6 +10,12 @@ 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') + +#============================================================================= # common imports #============================================================================= import logging; log = logging.getLogger(__name__) |
