diff options
author | Eli Collins <elic@assurancetechnologies.com> | 2012-01-18 20:36:38 -0500 |
---|---|---|
committer | Eli Collins <elic@assurancetechnologies.com> | 2012-01-18 20:36:38 -0500 |
commit | 6f816a3d7f1f3a394fedcc0aa410792a95b9ece6 (patch) | |
tree | 66308581e5b36a60198cd8a0c8b8916ba271eda5 | |
parent | a4a4d20ec8245f0e2763d08e6f00acbe343c854d (diff) | |
download | passlib-6f816a3d7f1f3a394fedcc0aa410792a95b9ece6.tar.gz |
split exceptions/warnings to separate module; added some additional warning classes to make filtering easier
-rw-r--r-- | CHANGES | 2 | ||||
-rw-r--r-- | admin/benchmarks.py | 8 | ||||
-rw-r--r-- | docs/contents.rst | 1 | ||||
-rw-r--r-- | docs/lib/passlib.exc.rst | 20 | ||||
-rw-r--r-- | docs/lib/passlib.utils.rst | 4 | ||||
-rw-r--r-- | passlib/context.py | 13 | ||||
-rw-r--r-- | passlib/exc.py | 58 | ||||
-rw-r--r-- | passlib/ext/django/utils.py | 10 | ||||
-rw-r--r-- | passlib/handlers/bcrypt.py | 11 | ||||
-rw-r--r-- | passlib/handlers/scram.py | 4 | ||||
-rw-r--r-- | passlib/hosts.py | 4 | ||||
-rw-r--r-- | passlib/registry.py | 4 | ||||
-rw-r--r-- | passlib/tests/test_context.py | 17 | ||||
-rw-r--r-- | passlib/tests/test_utils_handlers.py | 3 | ||||
-rw-r--r-- | passlib/tests/utils.py | 8 | ||||
-rw-r--r-- | passlib/utils/__init__.py | 31 | ||||
-rw-r--r-- | passlib/utils/handlers.py | 18 | ||||
-rw-r--r-- | passlib/utils/md4.py | 4 | ||||
-rw-r--r-- | passlib/utils/pbkdf2.py | 4 |
19 files changed, 152 insertions, 72 deletions
@@ -256,7 +256,7 @@ Release History * Various minor changes to :class:`passlib.utils.handlers.HasManyBackends`; main change is that multi-backend handlers now raise - :exc:`~passlib.utils.MissingBackendError` + :exc:`~passlib.exc.MissingBackendError` if no backends are available. Other diff --git a/admin/benchmarks.py b/admin/benchmarks.py index d68d599..bc88cf0 100644 --- a/admin/benchmarks.py +++ b/admin/benchmarks.py @@ -19,9 +19,9 @@ import warnings # site # pkg try: - from passlib.utils import PasslibPolicyWarning + from passlib.exc import PasslibContextWarning except ImportError: - PasslibPolicyWarning = None + PasslibContextWarning = None import passlib.utils.handlers as uh from passlib.utils.compat import u, print_, unicode # local @@ -102,8 +102,8 @@ def setup_context(): yield test_context_init ctx = test_context_init() -# if PasslibPolicyWarning: -# warnings.filterwarnings("ignore", category=PasslibPolicyWarning) +# if PasslibContextWarning: +# warnings.filterwarnings("ignore", category=PasslibContextWarning) def test_context_calls(): hash = ctx.encrypt(secret, rounds=2001) ctx.verify(secret, hash) diff --git a/docs/contents.rst b/docs/contents.rst index 2cfe258..a4f3cc4 100644 --- a/docs/contents.rst +++ b/docs/contents.rst @@ -19,6 +19,7 @@ Table Of Contents lib/passlib.apache lib/passlib.hosts + lib/passlib.exc lib/passlib.registry lib/passlib.utils diff --git a/docs/lib/passlib.exc.rst b/docs/lib/passlib.exc.rst new file mode 100644 index 0000000..8be1b0a --- /dev/null +++ b/docs/lib/passlib.exc.rst @@ -0,0 +1,20 @@ +=============================================================== +:mod:`passlib.exc` - exceptions and warnings raised by Passlib +=============================================================== + +.. module:: passlib.exc + :synopsis: exceptions & warnings raised by Passlib + +This module contains all the custom exceptions & warnings that +may be raised by Passlib. + +Exceptions +========== +.. autoexception:: MissingBackendError + +Warnings +======== +.. autoexception:: PasslibWarning +.. autoexception:: PasslibContextWarning +.. autoexception:: PasslibHandlerWarning +.. autoexception:: PasslibRuntimeWarning diff --git a/docs/lib/passlib.utils.rst b/docs/lib/passlib.utils.rst index 404e9f5..9ecd913 100644 --- a/docs/lib/passlib.utils.rst +++ b/docs/lib/passlib.utils.rst @@ -34,10 +34,6 @@ Constants See :ref:`mcf-identifiers` for a table of which OSes are known to support which hashes. -.. autoexception:: MissingBackendError - -.. autoexception:: PasslibPolicyWarning - .. PYPY diff --git a/passlib/context.py b/passlib/context.py index 6466903..da9e1dd 100644 --- a/passlib/context.py +++ b/passlib/context.py @@ -21,9 +21,10 @@ except ImportError: #not available eg: under GAE resource_string = None #libs +from passlib.exc import PasslibContextWarning from passlib.registry import get_crypt_handler, _validate_handler_name from passlib.utils import is_crypt_handler, rng, saslprep, tick, to_bytes, \ - to_unicode, PasslibPolicyWarning + to_unicode from passlib.utils.compat import bytes, is_mapping, iteritems, num_types, \ PY3, PY_MIN_32, unicode, SafeConfigParser, \ StringIO, BytesIO @@ -852,10 +853,10 @@ class _CryptRecord(object): "issue warnings if value outside of handler limits" if hmn is not None and value < hmn: warn("%s: %s value is below handler minimum %d: %d" % - (self._ident, name, hmn, value), PasslibPolicyWarning) + (self._ident, name, hmn, value), PasslibContextWarning) if hmx is not None and value > hmx: warn("%s: %s value is above handler maximum %d: %d" % - (self._ident, name, hmx, value), PasslibPolicyWarning) + (self._ident, name, hmx, value), PasslibContextWarning) def clip(value): "clip value to policy & handler limits" @@ -1007,12 +1008,12 @@ class _CryptRecord(object): mn = self._min_rounds if mn is not None and rounds < mn: warn("%s requires rounds >= %d, increasing value from %d" % - (self._ident, mn, rounds), PasslibPolicyWarning, 4) + (self._ident, mn, rounds), PasslibContextWarning, 4) rounds = mn mx = self._max_rounds if mx and rounds > mx: warn("%s requires rounds <= %d, decreasing value from %d" % - (self._ident, mx, rounds), PasslibPolicyWarning, 4) + (self._ident, mx, rounds), PasslibContextWarning, 4) rounds = mx kwds['rounds'] = rounds @@ -1041,7 +1042,7 @@ class _CryptRecord(object): #warn app they aren't being protected against timing attacks... warn("CryptContext: verify exceeded min_verify_time: " "scheme=%r min_verify_time=%r elapsed=%r" % - (self.scheme, mvt, end-start)) + (self.scheme, mvt, end-start), PasslibContextWarning) return ok #================================================================ diff --git a/passlib/exc.py b/passlib/exc.py new file mode 100644 index 0000000..8e60b90 --- /dev/null +++ b/passlib/exc.py @@ -0,0 +1,58 @@ +"""passlib.exc -- exceptions & warnings raised by passlib""" +#========================================================================== +# exceptions +#========================================================================== +class MissingBackendError(RuntimeError): + """Error raised if multi-backend handler has no available backends; + or if specifically requested backend is not available. + + :exc:`!MissingBackendError` derives + from :exc:`RuntimeError`, since this usually indicates + lack of an external library or OS feature. + + This is primarily used by handlers which derive + from :class:`~passlib.utils.handlers.HasManyBackends`. + """ + +#========================================================================== +# warnings +#========================================================================== +class PasslibWarning(UserWarning): + """base class for Passlib's user warnings""" + +class PasslibContextWarning(PasslibWarning): + """Warning issued when non-fatal issue is found related to the configuration + of a :class:`~passlib.context.CryptContext` instance. + + This occurs primarily in one of two cases: + + * the policy contains rounds limits which exceed the hard limits + imposed by the underlying algorithm. + * an explicit rounds value was provided which exceeds the limits + imposed by the policy. + + In both of these cases, the code will perform correctly & securely; + but the warning is issued as a sign the configuration may need updating. + """ + +class PasslibHandlerWarning(PasslibWarning): + """Warning issued when non-fatal issue is found with parameters + or hash string passed to a passlib hash class. + + This occurs primarily in one of two cases: + + * a rounds value or other setting was explicitly provided which + exceeded the handler's limits (and has been clamped). + + * a hash malformed hash string was encountered, which while parsable, + should be re-encoded. + """ + +class PasslibRuntimeWarning(PasslibWarning): + """Warning issued when something strange but correctable happens during + runtime. These are generally ok, but the developers would love to hear + the conditions under which it occurred.""" + +#========================================================================== +# eof +#========================================================================== diff --git a/passlib/ext/django/utils.py b/passlib/ext/django/utils.py index fc7c713..be8771c 100644 --- a/passlib/ext/django/utils.py +++ b/passlib/ext/django/utils.py @@ -12,6 +12,7 @@ #site from warnings import warn #pkg +from passlib.exc import PasslibRuntimeWarning from passlib.utils import is_crypt_context from passlib.utils.compat import bytes, get_method_function as um #local @@ -149,13 +150,16 @@ def set_django_password_context(context=None, get_category=get_category): if state is not None: if um(User.set_password) is not state['user_set_password']: warn("another library has patched " - "django.contrib.auth.models:User.set_password") + "django.contrib.auth.models:User.set_password", + PasslibRuntimeWarning) if um(User.check_password) is not state['user_check_password']: warn("another library has patched" - "django.contrib.auth.models:User.check_password") + "django.contrib.auth.models:User.check_password", + PasslibRuntimeWarning) if _dam.check_password is not state['models_check_password']: warn("another library has patched" - "django.contrib.auth.models:check_password") + "django.contrib.auth.models:check_password", + PasslibRuntimeWarning) #check if we should just restore original state if context is None: diff --git a/passlib/handlers/bcrypt.py b/passlib/handlers/bcrypt.py index e30ffc3..9a1f595 100644 --- a/passlib/handlers/bcrypt.py +++ b/passlib/handlers/bcrypt.py @@ -26,6 +26,7 @@ try: except ImportError: #pragma: no cover - though should run whole suite w/o bcryptor installed bcryptor_engine = None #libs +from passlib.exc import PasslibHandlerWarning from passlib.utils import BCRYPT_CHARS as BCHARS, safe_os_crypt, \ classproperty, rng, getrandstr from passlib.utils.compat import bytes, u, uascii_to_str, unicode @@ -84,7 +85,7 @@ class bcrypt(uh.HasManyIdents, uh.HasRounds, uh.HasSalt, uh.HasManyBackends, uh. 3. stdlib's :func:`crypt.crypt()`, if the host OS supports BCrypt (eg: BSD). If no backends are available at runtime, - :exc:`~passlib.utils.MissingBackendError` will be raised + :exc:`~passlib.exc.MissingBackendError` will be raised whenever :meth:`encrypt` or :meth:`verify` are called. You can see which backend is in use by calling the :meth:`~passlib.utils.handlers.HasManyBackends.get_backend()` method. @@ -187,8 +188,8 @@ class bcrypt(uh.HasManyIdents, uh.HasRounds, uh.HasSalt, uh.HasManyBackends, uh. warn( "encountered a bcrypt hash with incorrectly set padding bits; " "you may want to use bcrypt.normhash() " - "to fix this; see Passlib 1.5.3 changelog." - ) + "to fix this; see Passlib 1.5.3 changelog.", + PasslibHandlerWarning) return salt @classmethod @@ -200,8 +201,8 @@ class bcrypt(uh.HasManyIdents, uh.HasRounds, uh.HasSalt, uh.HasManyBackends, uh. warn( "encountered a bcrypt hash with incorrectly set padding bits; " "you may want to use bcrypt.normhash() " - "to fix this; see Passlib 1.5.3 changelog." - ) + "to fix this; see Passlib 1.5.3 changelog.", + PasslibHandlerWarning) return checksum #========================================================= diff --git a/passlib/handlers/scram.py b/passlib/handlers/scram.py index 1ff33b1..af3481f 100644 --- a/passlib/handlers/scram.py +++ b/passlib/handlers/scram.py @@ -23,6 +23,7 @@ import logging; log = logging.getLogger(__name__) from warnings import warn #site #libs +from passlib.exc import PasslibHandlerWarning from passlib.utils import ab64_decode, ab64_encode, consteq, saslprep, \ to_native_str, xor_bytes from passlib.utils.compat import b, bytes, bascii_to_str, iteritems, \ @@ -110,7 +111,8 @@ def norm_digest_name(name): # (and digest probably won't be found) m = re.match("^([a-z]{2,}\d?)(-\d{3,4})?$", name) if not m: - warn("encountered oddly named digest: %r" % (name,)) + warn("encountered oddly named digest: %r" % (name,), + PasslibWarning) # store in cache _ndn_cache[key] = name diff --git a/passlib/hosts.py b/passlib/hosts.py index 38b3bf6..a88e599 100644 --- a/passlib/hosts.py +++ b/passlib/hosts.py @@ -7,6 +7,7 @@ import sys from warnings import warn #pkg from passlib.context import LazyCryptContext +from passlib.exc import PasslibRuntimeWarning from passlib.registry import get_crypt_handler from passlib.utils import has_os_crypt, unix_crypt_schemes #local @@ -75,7 +76,8 @@ if has_os_crypt: yield "unix_fallback" else: #no idea what OS this could happen on, but just in case... - warn("crypt.crypt() function is present, but doesn't support any formats known to passlib!") + warn("crypt.crypt() function is present, but doesn't support any " + "formats known to passlib!", PasslibRuntimeWarning) host_context = LazyCryptContext(_iter_os_crypt_schemes()) diff --git a/passlib/registry.py b/passlib/registry.py index ba4b2a0..4a61d76 100644 --- a/passlib/registry.py +++ b/passlib/registry.py @@ -9,6 +9,7 @@ import logging; log = logging.getLogger(__name__) from warnings import warn #site #libs +from passlib.exc import PasslibWarning from passlib.utils import is_crypt_handler #pkg #local @@ -286,7 +287,8 @@ def get_crypt_handler(name, default=_NOTSET): #normalize name (and if changed, check dict again) alt = name.replace("-","_").lower() if alt != name: - warn("handler names should be lower-case, and use underscores instead of hyphens: %r => %r" % (name, alt)) + warn("handler names should be lower-case, and use underscores instead " + "of hyphens: %r => %r" % (name, alt), PasslibWarning) name = alt #check if handler loaded diff --git a/passlib/tests/test_context.py b/passlib/tests/test_context.py index 0e5d637..f92e783 100644 --- a/passlib/tests/test_context.py +++ b/passlib/tests/test_context.py @@ -18,7 +18,8 @@ except ImportError: #pkg from passlib import hash from passlib.context import CryptContext, CryptPolicy, LazyCryptContext -from passlib.utils import tick, to_bytes, to_unicode, PasslibPolicyWarning +from passlib.exc import PasslibContextWarning +from passlib.utils import tick, to_bytes, to_unicode from passlib.utils.compat import irange, u import passlib.utils.handlers as uh from passlib.tests.utils import TestCase, mktemp, catch_warnings, \ @@ -621,8 +622,8 @@ class CryptContextTest(TestCase): # set below handler min c2 = cc.replace(all__min_rounds=500, all__max_rounds=None, all__default_rounds=500) - self.assertWarningMatches(wlog.pop(), category=PasslibPolicyWarning) - self.assertWarningMatches(wlog.pop(), category=PasslibPolicyWarning) + self.assertWarningMatches(wlog.pop(), category=PasslibContextWarning) + self.assertWarningMatches(wlog.pop(), category=PasslibContextWarning) self.assertEqual(c2.genconfig(salt="nacl"), "$5$rounds=1000$nacl$") self.assertNoWarnings(wlog) @@ -631,7 +632,7 @@ class CryptContextTest(TestCase): cc.genconfig(rounds=1999, salt="nacl"), '$5$rounds=2000$nacl$', ) - self.assertWarningMatches(wlog.pop(), category=PasslibPolicyWarning) + self.assertWarningMatches(wlog.pop(), category=PasslibContextWarning) self.assertNoWarnings(wlog) # equal @@ -653,8 +654,8 @@ class CryptContextTest(TestCase): # set above handler max c2 = cc.replace(all__max_rounds=int(1e9)+500, all__min_rounds=None, all__default_rounds=int(1e9)+500) - self.assertWarningMatches(wlog.pop(), category=PasslibPolicyWarning) - self.assertWarningMatches(wlog.pop(), category=PasslibPolicyWarning) + self.assertWarningMatches(wlog.pop(), category=PasslibContextWarning) + self.assertWarningMatches(wlog.pop(), category=PasslibContextWarning) self.assertEqual(c2.genconfig(salt="nacl"), "$5$rounds=999999999$nacl$") self.assertNoWarnings(wlog) @@ -664,7 +665,7 @@ class CryptContextTest(TestCase): cc.genconfig(rounds=3001, salt="nacl"), '$5$rounds=3000$nacl$' ) - self.assertWarningMatches(wlog.pop(), category=PasslibPolicyWarning) + self.assertWarningMatches(wlog.pop(), category=PasslibContextWarning) self.assertNoWarnings(wlog) # equal @@ -816,7 +817,7 @@ class CryptContextTest(TestCase): cc.encrypt("password", rounds=1999, salt="nacl"), '$5$rounds=2000$nacl$9/lTZ5nrfPuz8vphznnmHuDGFuvjSNvOEDsGmGfsS97', ) - self.assertWarningMatches(wlog.pop(), category=PasslibPolicyWarning) + self.assertWarningMatches(wlog.pop(), category=PasslibContextWarning) self.assertFalse(wlog) self.assertEqual( diff --git a/passlib/tests/test_utils_handlers.py b/passlib/tests/test_utils_handlers.py index af7d540..630e1a0 100644 --- a/passlib/tests/test_utils_handlers.py +++ b/passlib/tests/test_utils_handlers.py @@ -13,7 +13,8 @@ import warnings 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 getrandstr, JYTHON, rng, to_unicode, MissingBackendError +from passlib.exc import MissingBackendError +from passlib.utils import getrandstr, JYTHON, rng, to_unicode from passlib.utils.compat import b, bytes, bascii_to_str, str_to_uascii, \ uascii_to_str, unicode import passlib.utils.handlers as uh diff --git a/passlib/tests/utils.py b/passlib/tests/utils.py index 85c9ea0..fc53edc 100644 --- a/passlib/tests/utils.py +++ b/passlib/tests/utils.py @@ -30,9 +30,10 @@ if ut_version < 2: #used to provide replacement skipTest() method from nose.plugins.skip import SkipTest #pkg +from passlib.exc import MissingBackendError import passlib.registry as registry -from passlib.utils import has_rounds_info, has_salt_info, MissingBackendError,\ - rounds_cost_values, classproperty +from passlib.utils import has_rounds_info, has_salt_info, rounds_cost_values, \ + classproperty from passlib.utils.compat import b, bytes, iteritems, irange, callable, \ sb_types, exc_err, u, unicode import passlib.utils.handlers as uh @@ -617,7 +618,8 @@ class HandlerCase(TestCase): (not mx_set or cls.min_salt_size < cls.max_salt_size): #NOTE: for now, only bothering to issue warning if default_salt_size isn't maxed out if (not mx_set or cls.default_salt_size < cls.max_salt_size): - warn("%s: hash handler supports range of salt sizes, but doesn't offer 'salt_size' setting" % (cls.name,)) + warn("%s: hash handler supports range of salt sizes, " + "but doesn't offer 'salt_size' setting" % (cls.name,)) #check salt_chars & default_salt_chars if cls.salt_chars: diff --git a/passlib/utils/__init__.py b/passlib/utils/__init__.py index a8e3d9c..c0161f0 100644 --- a/passlib/utils/__init__.py +++ b/passlib/utils/__init__.py @@ -94,31 +94,8 @@ unix_crypt_schemes = [ # list of rounds_cost constants rounds_cost_values = [ "linear", "log2" ] -class MissingBackendError(RuntimeError): - """Error raised if multi-backend handler has no available backends; - or if specifically requested backend is not available. - - :exc:`!MissingBackendError` derives - from :exc:`RuntimeError`, since this usually indicates - lack of an external library or OS feature. - - This is primarily used by handlers which derive - from :class:`~passlib.utils.handlers.HasManyBackends`. - """ - -class PasslibPolicyWarning(UserWarning): - """Warning issued when non-fatal issue is found in policy configuration. - - This occurs primarily in one of two cases: - - * the policy contains rounds limits which exceed the hard limits - imposed by the underlying algorithm. - * an explicit rounds value was provided which exceeds the limits - imposed by the policy. - - In both of these cases, the code will perform correctly & securely; - but the warning is issued as a sign the configuration may need updating. - """ +# legacy import, will be removed in 1.8 +from passlib.exc import MissingBackendError # internal helpers _BEMPTY = b('') @@ -1173,7 +1150,9 @@ else: # just in case original encoding wouldn't be reproduced # during call to os_crypt. not sure if/how this could # happen, but being paranoid. - warn("utf-8 password didn't re-encode correctly!") + from passlib.exc import PasslibRuntimeWarning + warn("utf-8 password didn't re-encode correctly!", + PasslibRuntimeWarning) return False, None result = os_crypt(secret, hash) return (result is not None), result diff --git a/passlib/utils/handlers.py b/passlib/utils/handlers.py index c46b473..6e2763b 100644 --- a/passlib/utils/handlers.py +++ b/passlib/utils/handlers.py @@ -13,10 +13,12 @@ import os from warnings import warn #site #libs +from passlib.exc import MissingBackendError, PasslibHandlerWarning, \ + PasslibRuntimeWarning from passlib.registry import get_crypt_handler from passlib.utils import is_crypt_handler from passlib.utils import classproperty, consteq, getrandstr, getrandbytes,\ - BASE64_CHARS, HASH64_CHARS, rng, to_native_str, MissingBackendError + BASE64_CHARS, HASH64_CHARS, rng, to_native_str from passlib.utils.compat import b, bjoin_ints, bytes, irange, u, \ uascii_to_str, unicode #pkg @@ -998,14 +1000,16 @@ class HasRounds(GenericHandler): if rounds < mn: if strict: raise ValueError("%s rounds must be >= %d" % (cls.name, mn)) - warn("%s does not allow less than %d rounds: %d" % (cls.name, mn, rounds)) + warn("%s does not allow less than %d rounds: %d" % + (cls.name, mn, rounds), PasslibHandlerWarning) rounds = mn mx = cls.max_rounds if mx and rounds > mx: if strict: raise ValueError("%s rounds must be <= %d" % (cls.name, mx)) - warn("%s does not allow more than %d rounds: %d" % (cls.name, mx, rounds)) + warn("%s does not allow more than %d rounds: %d" % + (cls.name, mx, rounds), PasslibHandlerWarning) rounds = mx return rounds @@ -1082,7 +1086,7 @@ class HasManyBackends(GenericHandler): if no backend has been loaded, loads and returns name of default backend. - :raises passlib.utils.MissingBackendError: if no backends are available. + :raises passlib.exc.MissingBackendError: if no backends are available. :returns: name of active backend """ @@ -1145,7 +1149,7 @@ class HasManyBackends(GenericHandler): the current backend if one has been loaded, else acts like ``"default"``. - :raises passlib.utils.MissingBackendError: + :raises passlib.exc.MissingBackendError: * ... if a specific backend was requested, but is not currently available. @@ -1238,7 +1242,9 @@ class PrefixWrapper(object): def _check_handler(self, handler): if 'ident' in handler.setting_kwds and self.orig_prefix: #TODO: look into way to fix the issues. - warn("PrefixWrapper: 'orig_prefix' option may not work correctly for handlers which have multiple identifiers: %r" % (handler.name,)) + warn("PrefixWrapper: 'orig_prefix' option may not work correctly " + "for handlers which have multiple identifiers: %r" % + (handler.name,), PasslibRuntimeWarning) def _get_wrapped(self): handler = self._wrapped_handler diff --git a/passlib/utils/md4.py b/passlib/utils/md4.py index a63ad11..cd3d012 100644 --- a/passlib/utils/md4.py +++ b/passlib/utils/md4.py @@ -252,7 +252,9 @@ def _has_native_md4(): #since this is expected, don't bother w/ warning. return False #anything else should alert user - warn("native md4 support disabled, incorrect value returned") + from passlib.exc import PasslibRuntimeWarning + warn("native md4 support disabled, incorrect value returned!", + PasslibRuntimeWarning) return False if _has_native_md4(): diff --git a/passlib/utils/pbkdf2.py b/passlib/utils/pbkdf2.py index c880457..9592a81 100644 --- a/passlib/utils/pbkdf2.py +++ b/passlib/utils/pbkdf2.py @@ -43,7 +43,9 @@ if _EVP: result = _EVP.hmac(b('x'),b('y')) except ValueError: #pragma: no cover #this is probably not a good sign if it happens. - warn("PassLib: M2Crypt.EVP.hmac() unexpected threw value error during passlib startup test") + from passlib.exc import PasslibRuntimeWarning + warn("PassLib: M2Crypt.EVP.hmac() unexpected threw value error during " + "passlib startup test", PasslibRuntimeWarning) else: if result == b(',\x1cb\xe0H\xa5\x82M\xfb>\xd6\x98\xef\x8e\xf9oQ\x85\xa3i'): hmac_sha1 = _EVP.hmac |