diff options
| author | Eli Collins <elic@assurancetechnologies.com> | 2011-12-28 17:15:31 -0500 |
|---|---|---|
| committer | Eli Collins <elic@assurancetechnologies.com> | 2011-12-28 17:15:31 -0500 |
| commit | 9d1ca56acb757a034d66eb0b97acf0ca06245146 (patch) | |
| tree | 4a08b829d3a70d0430aa5dfbb03cac96238dcec5 | |
| parent | dce7529fa18ab75cc42df175abee660836326ea5 (diff) | |
| download | passlib-9d1ca56acb757a034d66eb0b97acf0ca06245146.tar.gz | |
deprecated to_hash_str, replaced all instances with to_native_str
decided that to_hash_str will always return native string,
feature of hashes being returned as unicode under python 2
is better done through a CryptContext option.
28 files changed, 115 insertions, 116 deletions
@@ -69,7 +69,6 @@ Release History should set the environment variable ``PASSLIB_BUILTIN_BCRYPT=enabled`` before loading Passlib. - **1.5.3** (2011-10-08) ====================== diff --git a/docs/password_hash_api.rst b/docs/password_hash_api.rst index 62d29cf..570a636 100644 --- a/docs/password_hash_api.rst +++ b/docs/password_hash_api.rst @@ -592,10 +592,6 @@ and ease of implementation issues: backwards compatibility with Passlib 1.4 and earlier under Python 2. - Handlers should use the :func:`passlib.utils.to_hash_str` function - to coerce their unicode hashes to whatever is appropriate - for the platform before returning them. - .. rubric:: Footnotes .. [#otypes] While this specification is written referring to classes and classmethods, diff --git a/passlib/handlers/bcrypt.py b/passlib/handlers/bcrypt.py index 4aa0f01..3e401e8 100644 --- a/passlib/handlers/bcrypt.py +++ b/passlib/handlers/bcrypt.py @@ -28,7 +28,7 @@ except ImportError: #pragma: no cover - though should run whole suite w/o bcrypt bcryptor_engine = None #libs from passlib.utils import safe_os_crypt, classproperty, handlers as uh, \ - h64, to_hash_str, rng, getrandstr, bytes + h64, to_native_str, rng, getrandstr, bytes from passlib.utils.compat import unicode #pkg @@ -146,7 +146,7 @@ class bcrypt(uh.HasManyIdents, uh.HasRounds, uh.HasSalt, uh.HasManyBackends, uh. def to_string(self, native=True): hash = u("%s%02d$%s%s") % (self.ident, self.rounds, self.salt, self.checksum or u('')) - return to_hash_str(hash) if native else hash + return to_native_str(hash) if native else hash #========================================================= # specialized salt generation - fixes passlib issue 25 diff --git a/passlib/handlers/des_crypt.py b/passlib/handlers/des_crypt.py index ba3c50f..f6dda91 100644 --- a/passlib/handlers/des_crypt.py +++ b/passlib/handlers/des_crypt.py @@ -59,7 +59,7 @@ from warnings import warn #site #libs from passlib.utils import h64, classproperty, safe_os_crypt, b, bytes, \ - to_hash_str, handlers as uh, bord + to_native_str, handlers as uh, bord from passlib.utils.compat import unicode from passlib.utils.des import mdes_encrypt_int_block from passlib.utils.compat import u @@ -196,7 +196,7 @@ class des_crypt(uh.HasManyBackends, uh.HasSalt, uh.GenericHandler): def to_string(self, native=True): hash = u("%s%s") % (self.salt, self.checksum or u('')) - return to_hash_str(hash) if native else hash + return to_native_str(hash) if native else hash #========================================================= #backend @@ -325,7 +325,7 @@ class bsdi_crypt(uh.HasManyBackends, uh.HasRounds, uh.HasSalt, uh.GenericHandler def to_string(self, native=True): hash = u("_%s%s%s") % (h64.encode_int24(self.rounds).decode("ascii"), self.salt, self.checksum or u('')) - return to_hash_str(hash) if native else hash + return to_native_str(hash) if native else hash #========================================================= #backend @@ -417,7 +417,7 @@ class bigcrypt(uh.HasSalt, uh.GenericHandler): def to_string(self, native=True): hash = u("%s%s") % (self.salt, self.checksum or u('')) - return to_hash_str(hash) if native else hash + return to_native_str(hash) if native else hash @classmethod def norm_checksum(cls, value, strict=False): @@ -502,7 +502,7 @@ class crypt16(uh.HasSalt, uh.GenericHandler): def to_string(self, native=True): hash = u("%s%s") % (self.salt, self.checksum or u('')) - return to_hash_str(hash) if native else hash + return to_native_str(hash) if native else hash #========================================================= #backend diff --git a/passlib/handlers/digests.py b/passlib/handlers/digests.py index bbee12f..e3c5a64 100644 --- a/passlib/handlers/digests.py +++ b/passlib/handlers/digests.py @@ -9,7 +9,7 @@ import logging; log = logging.getLogger(__name__) from warnings import warn #site #libs -from passlib.utils import handlers as uh, to_hash_str, bytes +from passlib.utils import handlers as uh, to_native_str, bytes from passlib.utils.compat import unicode from passlib.utils.md4 import md4 #pkg @@ -52,7 +52,7 @@ class HexDigestHash(uh.StaticHandler): raise TypeError("no secret provided") if isinstance(secret, unicode): secret = secret.encode("utf-8") - return to_hash_str(cls._hash_func(secret).hexdigest()) + return to_native_str(cls._hash_func(secret).hexdigest()) @classmethod def _norm_hash(cls, hash): diff --git a/passlib/handlers/django.py b/passlib/handlers/django.py index 87fcb8e..1091359 100644 --- a/passlib/handlers/django.py +++ b/passlib/handlers/django.py @@ -9,7 +9,7 @@ import logging; log = logging.getLogger(__name__) from warnings import warn #site #libs -from passlib.utils import h64, handlers as uh, b, bytes, to_unicode, to_hash_str +from passlib.utils import h64, handlers as uh, b, bytes, to_unicode, to_native_str from passlib.utils.compat import unicode, u #pkg #local @@ -67,7 +67,7 @@ class DjangoSaltedHash(uh.HasSalt, uh.GenericHandler): def to_string(self): chk = self.checksum or self._stub_checksum out = u("%s%s$%s") % (self.ident, self.salt, chk) - return to_hash_str(out) + return to_native_str(out) class django_salted_sha1(DjangoSaltedHash): """This class implements Django's Salted SHA1 hash, and follows the :ref:`password-hash-api`. @@ -211,7 +211,7 @@ class django_disabled(uh.StaticHandler): def genhash(cls, secret, config): if secret is None: raise TypeError("no secret provided") - return to_hash_str(u("!")) + return to_native_str(u("!")) @classmethod def verify(cls, secret, hash): diff --git a/passlib/handlers/fshp.py b/passlib/handlers/fshp.py index fd2bf8d..a687c62 100644 --- a/passlib/handlers/fshp.py +++ b/passlib/handlers/fshp.py @@ -11,7 +11,7 @@ import logging; log = logging.getLogger(__name__) from warnings import warn #site #libs -from passlib.utils import handlers as uh, bytes, b, to_hash_str +from passlib.utils import handlers as uh, bytes, b, to_native_str from passlib.utils.compat import iteritems, unicode from passlib.utils.pbkdf2 import pbkdf1 from passlib.utils.compat import u @@ -164,7 +164,7 @@ class fshp(uh.HasRounds, uh.HasRawSalt, uh.HasRawChecksum, uh.GenericHandler): salt = self.salt data = b64encode(salt+chk).decode("ascii") hash = u("{FSHP%d|%d|%d}%s") % (self.variant, len(salt), self.rounds, data) - return to_hash_str(hash) + return to_native_str(hash) #========================================================= #backend diff --git a/passlib/handlers/ldap_digests.py b/passlib/handlers/ldap_digests.py index fa6da5e..adcf873 100644 --- a/passlib/handlers/ldap_digests.py +++ b/passlib/handlers/ldap_digests.py @@ -11,7 +11,7 @@ import re from warnings import warn #site #libs -from passlib.utils import handlers as uh, unix_crypt_schemes, b, bytes, to_hash_str +from passlib.utils import handlers as uh, unix_crypt_schemes, b, bytes, to_native_str from passlib.utils.compat import unicode, u #pkg #local @@ -60,7 +60,7 @@ class _Base64DigestHelper(uh.StaticHandler): raise ValueError("not a %s hash" % (cls.name,)) chk = cls._hash_func(secret).digest() hash = cls.ident + b64encode(chk).decode("ascii") - return to_hash_str(hash) + return to_native_str(hash) class _SaltedBase64DigestHelper(uh.HasRawSalt, uh.HasRawChecksum, uh.GenericHandler): "helper for ldap_salted_md5 / ldap_salted_sha1" @@ -93,7 +93,7 @@ class _SaltedBase64DigestHelper(uh.HasRawSalt, uh.HasRawChecksum, uh.GenericHand def to_string(self): data = (self.checksum or self._stub_checksum) + self.salt hash = self.ident + b64encode(data).decode("ascii") - return to_hash_str(hash) + return to_native_str(hash) def calc_checksum(self, secret): if secret is None: @@ -196,7 +196,7 @@ class ldap_plaintext(uh.StaticHandler): raise ValueError("not a valid ldap_plaintext hash") if secret is None: raise TypeError("secret must be string") - return to_hash_str(secret, "utf-8") + return to_native_str(secret, "utf-8") @classmethod def _norm_hash(cls, hash): diff --git a/passlib/handlers/misc.py b/passlib/handlers/misc.py index 80910af..3ba83e2 100644 --- a/passlib/handlers/misc.py +++ b/passlib/handlers/misc.py @@ -8,7 +8,7 @@ import logging; log = logging.getLogger(__name__) from warnings import warn #site #libs -from passlib.utils import to_hash_str, handlers as uh, bytes +from passlib.utils import to_native_str, handlers as uh, bytes #pkg #local __all__ = [ @@ -47,7 +47,7 @@ class unix_fallback(uh.StaticHandler): raise TypeError("secret must be string") if hash is None: raise ValueError("no hash provided") - return to_hash_str(hash) + return to_native_str(hash) @classmethod def verify(cls, secret, hash, enable_wildcard=False): @@ -70,7 +70,7 @@ class plaintext(uh.StaticHandler): def genhash(cls, secret, hash): if secret is None: raise TypeError("secret must be string") - return to_hash_str(secret, "utf-8") + return to_native_str(secret, "utf-8") @classmethod def _norm_hash(cls, hash): diff --git a/passlib/handlers/mysql.py b/passlib/handlers/mysql.py index 16f8f3b..9705b9d 100644 --- a/passlib/handlers/mysql.py +++ b/passlib/handlers/mysql.py @@ -30,7 +30,7 @@ from warnings import warn #site #libs #pkg -from passlib.utils import handlers as uh, to_hash_str, b, bord, bytes +from passlib.utils import handlers as uh, to_native_str, b, bord, bytes from passlib.utils.compat import unicode, u #local __all__ = [ @@ -87,7 +87,7 @@ class mysql323(uh.StaticHandler): nr2 = (nr2+((nr2 << 8) ^ nr1)) & MASK_32 add = (add+tmp) & MASK_32 hash = u("%08x%08x") % (nr1 & MASK_31, nr2 & MASK_31) - return to_hash_str(hash) + return to_native_str(hash) @classmethod def _norm_hash(cls, hash): diff --git a/passlib/handlers/nthash.py b/passlib/handlers/nthash.py index 53d4461..d207bc5 100644 --- a/passlib/handlers/nthash.py +++ b/passlib/handlers/nthash.py @@ -8,7 +8,7 @@ import logging; log = logging.getLogger(__name__) from warnings import warn #site #libs -from passlib.utils import handlers as uh, to_unicode, to_hash_str, to_bytes, bytes +from passlib.utils import handlers as uh, to_unicode, to_native_str, to_bytes, bytes from passlib.utils.md4 import md4 from passlib.utils.compat import u #pkg @@ -69,7 +69,7 @@ class nthash(uh.HasManyIdents, uh.GenericHandler): def to_string(self): hash = self.ident + (self.checksum or self._stub_checksum) - return to_hash_str(hash) + return to_native_str(hash) #========================================================= #primary interface diff --git a/passlib/handlers/oracle.py b/passlib/handlers/oracle.py index b31a752..1845881 100644 --- a/passlib/handlers/oracle.py +++ b/passlib/handlers/oracle.py @@ -12,7 +12,7 @@ from warnings import warn #libs #pkg from passlib.utils import xor_bytes, handlers as uh, bytes, to_unicode, \ - to_hash_str, b + to_native_str, b from passlib.utils.compat import irange, unicode from passlib.utils.des import des_encrypt_block from passlib.utils.compat import u @@ -115,7 +115,7 @@ class oracle10(uh.StaticHandler): input = encode(user) + encode(secret) hash = des_cbc_encrypt(ORACLE10_MAGIC, input) hash = des_cbc_encrypt(hash, input) - return to_hash_str(hexlify(hash)).upper() + return to_native_str(hexlify(hash)).upper() @classmethod def _norm_hash(cls, hash): @@ -182,7 +182,7 @@ class oracle11(uh.HasSalt, uh.GenericHandler): def to_string(self): chk = (self.checksum or self._stub_checksum) hash = u("S:%s%s") % (chk.upper(), self.salt.upper()) - return to_hash_str(hash) + return to_native_str(hash) def calc_checksum(self, secret): if isinstance(secret, unicode): diff --git a/passlib/handlers/pbkdf2.py b/passlib/handlers/pbkdf2.py index c893913..8b969a6 100644 --- a/passlib/handlers/pbkdf2.py +++ b/passlib/handlers/pbkdf2.py @@ -11,7 +11,7 @@ from warnings import warn #site #libs from passlib.utils import adapted_b64_encode, adapted_b64_decode, \ - handlers as uh, to_hash_str, to_unicode, bytes, b + handlers as uh, to_native_str, to_unicode, bytes, b from passlib.utils.compat import unicode from passlib.utils.pbkdf2 import pbkdf2 from passlib.utils.compat import u @@ -88,7 +88,7 @@ class Pbkdf2DigestHandler(uh.HasRounds, uh.HasRawSalt, uh.HasRawChecksum, uh.Gen hash = u('%s%d$%s$%s') % (self.ident, self.rounds, salt, chk) else: hash = u('%s%d$%s') % (self.ident, self.rounds, salt) - return to_hash_str(hash) + return to_native_str(hash) def calc_checksum(self, secret): if isinstance(secret, unicode): @@ -227,7 +227,7 @@ class cta_pbkdf2_sha1(uh.HasRounds, uh.HasRawSalt, uh.HasRawChecksum, uh.Generic if withchk and self.checksum: out = u("%s$%s") % (out, b64encode(self.checksum, CTA_ALTCHARS).decode("ascii")) - return to_hash_str(out) + return to_native_str(out) #========================================================= #backend @@ -321,7 +321,7 @@ class dlitz_pbkdf2_sha1(uh.HasRounds, uh.HasSalt, uh.GenericHandler): out = u('$p5k2$%x$%s') % (self.rounds, self.salt) if withchk and self.checksum: out = u("%s$%s") % (out,self.checksum) - return to_hash_str(out) if native else out + return to_native_str(out) if native else out #========================================================= #backend @@ -379,7 +379,7 @@ class atlassian_pbkdf2_sha1(uh.HasRawSalt, uh.HasRawChecksum, uh.GenericHandler) def to_string(self): data = self.salt + (self.checksum or self._stub_checksum) hash = self.ident + b64encode(data).decode("ascii") - return to_hash_str(hash) + return to_native_str(hash) def calc_checksum(self, secret): #TODO: find out what crowd's policy is re: unicode @@ -453,7 +453,7 @@ class grub_pbkdf2_sha512(uh.HasRounds, uh.HasRawSalt, uh.HasRawChecksum, uh.Gene hash = u('%s%d.%s.%s') % (self.ident, self.rounds, salt, chk) else: hash = u('%s%d.%s') % (self.ident, self.rounds, salt) - return to_hash_str(hash) + return to_native_str(hash) def calc_checksum(self, secret): #TODO: find out what grub's policy is re: unicode diff --git a/passlib/handlers/phpass.py b/passlib/handlers/phpass.py index ce3acbc..2c76a92 100644 --- a/passlib/handlers/phpass.py +++ b/passlib/handlers/phpass.py @@ -15,7 +15,7 @@ import logging; log = logging.getLogger(__name__) from warnings import warn #site #libs -from passlib.utils import h64, handlers as uh, bytes, b, to_unicode, to_hash_str +from passlib.utils import h64, handlers as uh, bytes, b, to_unicode, to_native_str from passlib.utils.compat import unicode, u #pkg #local @@ -110,7 +110,7 @@ class phpass(uh.HasManyIdents, uh.HasRounds, uh.HasSalt, uh.GenericHandler): h64.encode_int6(self.rounds).decode("ascii"), self.salt, self.checksum or u('')) - return to_hash_str(hash) + return to_native_str(hash) #========================================================= #backend diff --git a/passlib/handlers/postgres.py b/passlib/handlers/postgres.py index 0bbb70f..bb4c102 100644 --- a/passlib/handlers/postgres.py +++ b/passlib/handlers/postgres.py @@ -10,7 +10,7 @@ from warnings import warn #site #libs #pkg -from passlib.utils import handlers as uh, to_unicode, to_hash_str, bytes, b +from passlib.utils import handlers as uh, to_unicode, to_native_str, bytes, b from passlib.utils.compat import unicode, u #local __all__ = [ @@ -62,7 +62,7 @@ class postgres_md5(uh.StaticHandler): if isinstance(user, unicode): user = user.encode("utf-8") hash = u("md5") + to_unicode(md5(secret + user).hexdigest()) - return to_hash_str(hash) + return to_native_str(hash) #========================================================= #eoc diff --git a/passlib/handlers/sha1_crypt.py b/passlib/handlers/sha1_crypt.py index 17dbe32..dc58901 100644 --- a/passlib/handlers/sha1_crypt.py +++ b/passlib/handlers/sha1_crypt.py @@ -14,7 +14,7 @@ from warnings import warn #site #libs from passlib.utils import h64, handlers as uh, safe_os_crypt, classproperty, \ - to_hash_str, to_unicode, bytes, b + to_native_str, to_unicode, bytes, b from passlib.utils.compat import unicode from passlib.utils.pbkdf2 import hmac_sha1 from passlib.utils.compat import u @@ -95,7 +95,7 @@ class sha1_crypt(uh.HasManyBackends, uh.HasRounds, uh.HasSalt, uh.GenericHandler out = u("$sha1$%d$%s") % (self.rounds, self.salt) if self.checksum: out += u("$") + self.checksum - return to_hash_str(out) if native else out + return to_native_str(out) if native else out #========================================================= #backend diff --git a/passlib/handlers/sha2_crypt.py b/passlib/handlers/sha2_crypt.py index 16ed4d8..dabc495 100644 --- a/passlib/handlers/sha2_crypt.py +++ b/passlib/handlers/sha2_crypt.py @@ -10,7 +10,7 @@ from warnings import warn #site #libs from passlib.utils import h64, safe_os_crypt, classproperty, handlers as uh, \ - to_hash_str, to_unicode, bytes, b, bord + to_native_str, to_unicode, bytes, b, bord from passlib.utils.compat import unicode, u #pkg #local @@ -317,7 +317,7 @@ class sha256_crypt(uh.HasManyBackends, uh.HasRounds, uh.HasSalt, uh.GenericHandl hash = u("$5$%s$%s") % (self.salt, self.checksum or u('')) else: hash = u("$5$rounds=%d$%s$%s") % (self.rounds, self.salt, self.checksum or u('')) - return to_hash_str(hash) if native else hash + return to_native_str(hash) if native else hash #========================================================= #backend @@ -469,7 +469,7 @@ class sha512_crypt(uh.HasManyBackends, uh.HasRounds, uh.HasSalt, uh.GenericHandl hash = u("$6$%s$%s") % (self.salt, self.checksum or u('')) else: hash = u("$6$rounds=%d$%s$%s") % (self.rounds, self.salt, self.checksum or u('')) - return to_hash_str(hash) if native else hash + return to_native_str(hash) if native else hash #========================================================= #backend diff --git a/passlib/handlers/sun_md5_crypt.py b/passlib/handlers/sun_md5_crypt.py index 0ada9e1..386224a 100644 --- a/passlib/handlers/sun_md5_crypt.py +++ b/passlib/handlers/sun_md5_crypt.py @@ -17,7 +17,7 @@ import logging; log = logging.getLogger(__name__) 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 import h64, handlers as uh, to_native_str, to_unicode, bytes, b, bord from passlib.utils.compat import trange, unicode, u #pkg #local @@ -316,7 +316,7 @@ class sun_md5_crypt(uh.HasRounds, uh.HasSalt, uh.GenericHandler): chk = self.checksum if chk: out = u("%s$%s") % (out, chk) - return to_hash_str(out) if native else out + return to_native_str(out) if native else out #========================================================= #primary interface diff --git a/passlib/tests/test_apache.py b/passlib/tests/test_apache.py index 9d69001..fa78a77 100644 --- a/passlib/tests/test_apache.py +++ b/passlib/tests/test_apache.py @@ -11,7 +11,7 @@ import time #site #pkg from passlib import apache -from passlib.utils import b, native_str, bytes +from passlib.utils import b, bytes from passlib.utils.compat import irange, unicode from passlib.tests.utils import TestCase, mktemp, gae_env, get_file, set_file from passlib.utils.compat import u @@ -167,7 +167,7 @@ class HtpasswdFileTest(TestCase): #check users() returns native string by default ht = apache.HtpasswdFile._from_string(self.sample_01) - self.assertIsInstance(ht.users()[0], native_str) + self.assertIsInstance(ht.users()[0], str) #check returns unicode if encoding explicitly set ht = apache.HtpasswdFile._from_string(self.sample_01, encoding="utf-8") @@ -354,8 +354,8 @@ class HtdigestFileTest(TestCase): #check users() returns native string by default ht = apache.HtdigestFile._from_string(self.sample_01) - self.assertIsInstance(ht.realms()[0], native_str) - self.assertIsInstance(ht.users("realm")[0], native_str) + self.assertIsInstance(ht.realms()[0], str) + self.assertIsInstance(ht.users("realm")[0], str) #check returns unicode if encoding explicitly set ht = apache.HtdigestFile._from_string(self.sample_01, encoding="utf-8") diff --git a/passlib/tests/test_drivers.py b/passlib/tests/test_drivers.py index 1890074..5dc8d4f 100644 --- a/passlib/tests/test_drivers.py +++ b/passlib/tests/test_drivers.py @@ -635,7 +635,7 @@ class _Md5CryptTest(HandlerCase): known_correct_hashes = [ #NOTE: would need to patch HandlerCase to coerce hashes - #to_hash_str() for this first one to work under py3. + #to_native_str() for this first one to work under py3. ## ('', b('$1$dOHYPKoP$tnxS1T8Q6VVn3kpV8cN6o.')), ('', '$1$dOHYPKoP$tnxS1T8Q6VVn3kpV8cN6o.'), (' ', '$1$m/5ee7ol$bZn0kIBFipq39e.KDXX8I0'), diff --git a/passlib/tests/test_utils.py b/passlib/tests/test_utils.py index 08dd321..dfd5f39 100644 --- a/passlib/tests/test_utils.py +++ b/passlib/tests/test_utils.py @@ -14,7 +14,7 @@ import warnings from passlib.context import CryptContext from passlib import utils from passlib.utils import h64, des, Undef, bytes, b, \ - native_str, to_bytes, to_unicode, to_native_str, to_hash_str, \ + to_bytes, to_unicode, to_native_str, \ is_same_codec, is_ascii_safe, safe_os_crypt, md4 as md4_mod from passlib.utils.compat import unicode, PY3 from passlib.tests.utils import TestCase, Params as ak, \ @@ -320,7 +320,7 @@ class CodecTest(TestCase): "tests bytes/unicode helpers in passlib.utils" def test_bytes(self): - "test b() helper, bytes and native_str types" + "test b() helper, bytes and native str type" if PY3: import builtins self.assertIs(bytes, builtins.bytes) @@ -328,8 +328,6 @@ class CodecTest(TestCase): import __builtin__ as builtins self.assertIs(bytes, builtins.str) - self.assertIs(native_str, builtins.str) - self.assertIsInstance(b(''), bytes) self.assertIsInstance(b('\x00\xff'), bytes) if PY3: @@ -392,20 +390,29 @@ class CodecTest(TestCase): def test_to_native_str(self): "test to_native_str()" - self.assertEqual(to_native_str(u('abc')), 'abc') - self.assertEqual(to_native_str(b('abc')), 'abc') + # ascii goes to native string w/o problems + self.assertEqual(to_native_str(u('abc')), 'abc') + self.assertEqual(to_native_str(b('abc')), 'abc') + + # other types rejected self.assertRaises(TypeError, to_native_str, None) - self.assertEqual(to_native_str(u('\x00\xff'), 'latin-1'), '\x00\xff') - self.assertEqual(to_native_str(b('\x00\xff'), 'latin-1'), '\x00\xff') + # non-ascii unicode should throw error under py2, unless codec specified + if PY3: + self.assertEqual(to_native_str(u('\x00\xff')), '\x00\xff') + else: + self.assertRaises(UnicodeEncodeError, to_native_str, u('\x00\xff')) + self.assertEqual(to_native_str(u('\x00\xff'), 'utf-8'), '\x00\xc3\xbf') + + # non-ascii bytes should throw error under py3, unless codec specified if PY3: - self.assertEqual(to_native_str(u('\x00\xff')), '\x00\xff') - self.assertEqual(to_native_str(b('\x00\xc3\xbf')), '\x00\xff') + self.assertRaises(UnicodeDecodeError, to_native_str, b('\x00\xff')) else: - self.assertEqual(to_native_str(u('\x00\xff')), '\x00\xc3\xbf') - self.assertEqual(to_native_str(b('\x00\xc3\xbf')), '\x00\xc3\xbf') + self.assertEqual(to_native_str(b('\x00\xff')), '\x00\xff') - #TODO: test to_hash_str() + # latin-1 should work if explicitly chosen + self.assertEqual(to_native_str(u('\x00\xff'), 'latin-1'), '\x00\xff') + self.assertEqual(to_native_str(b('\x00\xff'), 'latin-1'), '\x00\xff') def test_is_ascii_safe(self): "test is_ascii_safe()" @@ -676,8 +683,8 @@ class _MD4_Test(TestCase): "test md4 digest()" md4 = self.hash for input, hex in self.vectors: - out = md4(input).digest() - self.assertEqual(to_native_str(hexlify(out)), hex) + out = to_native_str(hexlify(md4(input).digest())) + self.assertEqual(out, hex) def test_md4_copy(self): "test md4 copy()" diff --git a/passlib/tests/test_utils_handlers.py b/passlib/tests/test_utils_handlers.py index 62ac529..3847745 100644 --- a/passlib/tests/test_utils_handlers.py +++ b/passlib/tests/test_utils_handlers.py @@ -14,7 +14,7 @@ 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_hash_str, to_unicode, MissingBackendError, jython_vm + to_native_str, to_unicode, MissingBackendError, jython_vm from passlib.utils.compat import unicode from passlib.tests.utils import HandlerCase, TestCase, catch_warnings, \ dummy_handler_in_registry @@ -44,7 +44,7 @@ class SkeletonTest(TestCase): hash = hash.decode("ascii") if hash not in (u('a'),u('b')): raise ValueError - return to_hash_str(u('b') if flag else u('a')) + return to_native_str(u('b') if flag else u('a')) #check default identify method self.assertTrue(d1.identify(u('a'))) @@ -58,7 +58,7 @@ class SkeletonTest(TestCase): #check default genconfig method self.assertIs(d1.genconfig(), None) d1._stub_config = u('b') - self.assertEqual(d1.genconfig(), to_hash_str('b')) + self.assertEqual(d1.genconfig(), to_native_str('b')) #check default verify method self.assertTrue(d1.verify('s','a')) @@ -69,9 +69,9 @@ class SkeletonTest(TestCase): self.assertRaises(ValueError, d1.verify, 's', 'c') #check default encrypt method - self.assertEqual(d1.encrypt('s'), to_hash_str('a')) - self.assertEqual(d1.encrypt('s'), to_hash_str('a')) - self.assertEqual(d1.encrypt('s', flag=True), to_hash_str('b')) + self.assertEqual(d1.encrypt('s'), to_native_str('a')) + self.assertEqual(d1.encrypt('s'), to_native_str('a')) + self.assertEqual(d1.encrypt('s', flag=True), to_native_str('b')) #========================================================= #GenericHandler & mixins @@ -411,7 +411,7 @@ class UnsaltedHash(uh.StaticHandler): if isinstance(secret, unicode): secret = secret.encode("utf-8") data = b("boblious") + secret - return to_hash_str(hashlib.sha1(data).hexdigest()) + return to_native_str(hashlib.sha1(data).hexdigest()) class SaltedHash(uh.HasSalt, uh.GenericHandler): "test algorithm with a salt" @@ -439,7 +439,7 @@ class SaltedHash(uh.HasSalt, uh.GenericHandler): def to_string(self): hash = u("@salt%s%s") % (self.salt, self.checksum or self._stub_checksum) - return to_hash_str(hash) + return to_native_str(hash) def calc_checksum(self, secret): if isinstance(secret, unicode): diff --git a/passlib/tests/utils.py b/passlib/tests/utils.py index cb72143..4e5f2fb 100644 --- a/passlib/tests/utils.py +++ b/passlib/tests/utils.py @@ -33,7 +33,7 @@ if ut_version < 2: 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 + rounds_cost_values, b, bytes, NoneType from passlib.utils.compat import iteritems, irange, callable, sb_types, \ exc_err, unicode #local @@ -564,7 +564,7 @@ class HandlerCase(TestCase): name = ga("name") self.assertTrue(name, "name not defined:") - self.assertIsInstance(name, native_str, "name must be native str") + self.assertIsInstance(name, str, "name must be native str") self.assertTrue(name.lower() == name, "name not lower-case:") self.assertTrue(re.match("^[a-z0-9_]+$", name), "name must be alphanum + underscore: %r" % (name,)) @@ -811,8 +811,8 @@ class HandlerCase(TestCase): raise self.skipTest("handler doesn't have salt") c1 = self.do_genconfig() c2 = self.do_genconfig() - self.assertIsInstance(c1, native_str, "genconfig() must return native str:") - self.assertIsInstance(c2, native_str, "genconfig() must return native str:") + self.assertIsInstance(c1, str, "genconfig() must return native str:") + self.assertIsInstance(c2, str, "genconfig() must return native str:") self.assertNotEqual(c1,c2) def test_31_genconfig_minsalt(self): @@ -933,14 +933,14 @@ class HandlerCase(TestCase): #check it handles unicode password secret = u("\u20AC\u00A5$") result = self.do_encrypt(secret) - self.assertIsInstance(result, native_str, "encrypt must return native str:") + self.assertIsInstance(result, str, "encrypt must return native str:") self.assertTrue(self.do_identify(result)) self.assertTrue(self.do_verify(secret, result)) #check it handles bytes password as well secret = b('\xe2\x82\xac\xc2\xa5$') result = self.do_encrypt(secret) - self.assertIsInstance(result, native_str, "encrypt must return native str:") + self.assertIsInstance(result, str, "encrypt must return native str:") self.assertTrue(self.do_identify(result)) self.assertTrue(self.do_verify(secret, result)) diff --git a/passlib/utils/__init__.py b/passlib/utils/__init__.py index 5e182f6..101afd3 100644 --- a/passlib/utils/__init__.py +++ b/passlib/utils/__init__.py @@ -29,7 +29,7 @@ __all__ = [ ## "abstractclassmethod", #byte compat aliases - 'bytes', 'native_str', + 'bytes', #misc 'os_crypt', @@ -41,7 +41,6 @@ __all__ = [ #bytes<->unicode 'to_bytes', 'to_unicode', - 'to_native_str', 'is_same_codec', # string manipulation @@ -136,14 +135,6 @@ class PasslibPolicyWarning(UserWarning): but the warning is issued as a sign the configuration may need updating. """ -#========================================================== -#bytes compat aliases - bytes, native_str, b() -#========================================================== - -# NOTE: most of this has been moved to compat() - -native_str = str - #================================================================================= #os crypt helpers #================================================================================= @@ -390,7 +381,6 @@ def to_unicode(source, source_encoding="utf-8", errname="value"): if PY3: def to_native_str(source, encoding="utf-8", errname="value"): - assert encoding if isinstance(source, bytes): return source.decode(encoding) elif isinstance(source, unicode): @@ -400,7 +390,6 @@ if PY3: (errname, type(source))) else: def to_native_str(source, encoding="utf-8", errname="value"): - assert encoding if isinstance(source, bytes): return source elif isinstance(source, unicode): @@ -409,25 +398,32 @@ else: raise TypeError("%s must be unicode or bytes, not %s" % (errname, type(source))) -_add_doc(to_native_str, """take in unicode or bytes, return native string +_add_doc(to_native_str, + """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. :raises TypeError: if source is not unicode or bytes. - :arg source: source bytes/unicode to process - :arg encoding: encoding to use when encoding unicode / decoding bytes - :param errname: optional name of variable/noun to reference when raising errors + :arg source: + source unicode or bytes string. + + :arg encoding: + encoding to use when encoding unicode or decoding bytes. + this defaults to ``"utf-8"``. + + :param errname: + optional name of variable/noun to reference when raising errors. :returns: :class:`str` instance """) -def to_hash_str(hash, encoding="ascii", errname="hash"): - "given hash string as bytes or unicode; normalize according to hash policy" - #NOTE: for now, policy is ascii-bytes under py2, unicode under py3. - # but plan to make flag allowing apps to enable unicode behavior under py2. - return to_native_str(hash, encoding, errname) +def to_hash_str(source, encoding="ascii"): + "deprecated, use to_native_str() instead" + warn("to_hash_str() is deprecated, and will be removed in passlib 1.7", + DeprecationWarning, stacklevel=2) + return to_native_str(source, encoding, 'hash') #-------------------------------------------------- #support utils @@ -521,7 +517,7 @@ def splitcomma(source, sep=","): .. deprecated:: 1.6, will be removed in 1.7 """ - warn("splitcomma() is deprecated, will be removed in passlib 1.7", + warn("splitcomma() is deprecated, and will be removed in passlib 1.7", DeprecationWarning, stacklevel=2) return [ elem.strip() diff --git a/passlib/utils/handlers.py b/passlib/utils/handlers.py index 98c61fa..53bd476 100644 --- a/passlib/utils/handlers.py +++ b/passlib/utils/handlers.py @@ -14,7 +14,7 @@ from warnings import warn #site #libs from passlib.registry import get_crypt_handler -from passlib.utils import to_hash_str, bytes, b, consteq, \ +from passlib.utils import to_native_str, bytes, b, consteq, \ classproperty, h64, getrandstr, getrandbytes, \ rng, is_crypt_handler, ALL_BYTE_VALUES, MissingBackendError from passlib.utils.compat import unicode, u @@ -126,7 +126,7 @@ def render_mc2(ident, salt, checksum, sep=u("$")): hash = u("%s%s%s%s") % (ident, salt, sep, checksum) else: hash = u("%s%s") % (ident, salt) - return to_hash_str(hash) + return to_native_str(hash) def render_mc3(ident, rounds, salt, checksum, sep=u("$")): "format hash using 3-part modular crypt format; inverse of parse_mc3" @@ -134,7 +134,7 @@ def render_mc3(ident, rounds, salt, checksum, sep=u("$")): hash = u("%s%s%s%s%s%s") % (ident, rounds, sep, salt, sep, checksum) else: hash = u("%s%s%s%s") % (ident, rounds, sep, salt) - return to_hash_str(hash) + return to_native_str(hash) #===================================================== #StaticHandler @@ -1290,7 +1290,7 @@ class PrefixWrapper(object): if not hash.startswith(orig_prefix): raise ValueError("not a valid %s hash" % (self.wrapped.name,)) wrapped = self.prefix + hash[len(orig_prefix):] - return to_hash_str(wrapped) + return to_native_str(wrapped) def identify(self, hash): if not hash: diff --git a/passlib/utils/md4.py b/passlib/utils/md4.py index 4935999..0ee3324 100644 --- a/passlib/utils/md4.py +++ b/passlib/utils/md4.py @@ -16,7 +16,7 @@ import struct from warnings import warn #site from passlib.utils import b, bytes, to_native_str -from passlib.utils.compat import irange +from passlib.utils.compat import irange, PY3 #local __all__ = [ "md4" ] #========================================================================= @@ -224,7 +224,8 @@ class md4(object): return out def hexdigest(self): - return to_native_str(hexlify(self.digest()), "latin-1") + # PY3: hexlify returns bytes, but hexdigest should return str. + return to_native_str(hexlify(self.digest())) #========================================================================= #eoc diff --git a/passlib/utils/pbkdf2.py b/passlib/utils/pbkdf2.py index aa35327..27ccf4c 100644 --- a/passlib/utils/pbkdf2.py +++ b/passlib/utils/pbkdf2.py @@ -20,7 +20,7 @@ try: except ImportError: _EVP = None #pkg -from passlib.utils import xor_bytes, to_bytes, native_str, b, bytes +from passlib.utils import xor_bytes, to_bytes, b, bytes from passlib.utils.compat import irange, callable, int_types from passlib.utils.compat.aliases import BytesIO #local @@ -133,7 +133,7 @@ def get_prf(name): global _prf_cache if name in _prf_cache: return _prf_cache[name] - if isinstance(name, native_str): + if isinstance(name, str): if name.startswith("hmac-") or name.startswith("hmac_"): retval = _get_hmac_prf(name[5:]) else: @@ -191,7 +191,7 @@ def pbkdf1(secret, salt, rounds, keylen, hash="sha1"): raise ValueError("keylen must be at least 0") #resolve hash - if isinstance(hash, native_str): + if isinstance(hash, str): #check for builtin hash hf = getattr(hashlib, hash, None) if hf is None: diff --git a/passlib/win32.py b/passlib/win32.py index f34416e..19b3ced 100644 --- a/passlib/win32.py +++ b/passlib/win32.py @@ -27,7 +27,7 @@ See also :mod:`passlib.hash.nthash`. from binascii import hexlify #site #pkg -from passlib.utils import to_native_str, b +from passlib.utils import b from passlib.utils.compat import unicode from passlib.utils.des import des_encrypt_block from passlib.hash import nthash |
