diff options
Diffstat (limited to 'passlib/tests')
29 files changed, 413 insertions, 1646 deletions
diff --git a/passlib/tests/backports.py b/passlib/tests/backports.py deleted file mode 100644 index 5058cec..0000000 --- a/passlib/tests/backports.py +++ /dev/null @@ -1,67 +0,0 @@ -"""backports of needed unittest2 features""" -#============================================================================= -# imports -#============================================================================= -from __future__ import with_statement -# core -import logging; log = logging.getLogger(__name__) -import re -import sys -##from warnings import warn -# site -# pkg -from passlib.utils.compat import PY26 -# local -__all__ = [ - "TestCase", - "unittest", - # TODO: deprecate these exports in favor of "unittest.XXX" - "skip", "skipIf", "skipUnless", -] - -#============================================================================= -# import latest unittest module available -#============================================================================= -try: - import unittest2 as unittest -except ImportError: - if PY26: - raise ImportError("Passlib's tests require 'unittest2' under Python 2.6 (as of Passlib 1.7)") - # python 2.7 and python 3.2 both have unittest2 features (at least, the ones we use) - import unittest - -#============================================================================= -# unittest aliases -#============================================================================= -skip = unittest.skip -skipIf = unittest.skipIf -skipUnless = unittest.skipUnless -SkipTest = unittest.SkipTest - -#============================================================================= -# custom test harness -#============================================================================= -class TestCase(unittest.TestCase): - """backports a number of unittest2 features in TestCase""" - - #=================================================================== - # backport some unittest2 names - #=================================================================== - - #--------------------------------------------------------------- - # backport assertRegex() alias from 3.2 to 2.7 - # was present in 2.7 under an alternate name - #--------------------------------------------------------------- - if not hasattr(unittest.TestCase, "assertRegex"): - assertRegex = unittest.TestCase.assertRegexpMatches - - if not hasattr(unittest.TestCase, "assertRaisesRegex"): - assertRaisesRegex = unittest.TestCase.assertRaisesRegexp - - #=================================================================== - # eoc - #=================================================================== - -#============================================================================= -# eof -#============================================================================= diff --git a/passlib/tests/test_apache.py b/passlib/tests/test_apache.py index 198b425..fcdbbc6 100644 --- a/passlib/tests/test_apache.py +++ b/passlib/tests/test_apache.py @@ -2,19 +2,16 @@ #============================================================================= # imports #============================================================================= -from __future__ import with_statement # core from logging import getLogger +import unittest import os import subprocess # site # pkg from passlib import apache, registry from passlib.exc import MissingBackendError -from passlib.utils.compat import irange -from passlib.tests.backports import unittest from passlib.tests.utils import TestCase, get_file, set_file, ensure_mtime_changed -from passlib.utils.compat import u from passlib.utils import to_bytes from passlib.utils.handlers import to_unicode_for_identify # module @@ -122,8 +119,8 @@ class HtpasswdFileTest(TestCase): b'user6:$5$rounds=110000$cCRp/xUUGVgwR4aP$' b'p0.QKFS5qLNRqw1/47lXYiAcgIjJK.WjCO8nrEKuUK.\n') - def test_00_constructor_autoload(self): - """test constructor autoload""" + def test_00_constructor_new(self): + """constructor -- 'new' keyword""" # check with existing file path = self.mktemp() set_file(path, self.sample_01) @@ -143,13 +140,6 @@ class HtpasswdFileTest(TestCase): self.assertEqual(ht.path, path) self.assertFalse(ht.mtime) - # check autoload=False (deprecated alias for new=True) - with self.assertWarningList("``autoload=False`` is deprecated"): - ht = apache.HtpasswdFile(path, autoload=False) - self.assertEqual(ht.to_string(), b"") - self.assertEqual(ht.path, path) - self.assertFalse(ht.mtime) - # check missing file os.remove(path) self.assertRaises(IOError, apache.HtpasswdFile, path) @@ -196,21 +186,9 @@ class HtpasswdFileTest(TestCase): self.assertFalse(ht.set_password("user5", "pass5")) self.assertEqual(ht.to_string(), self.sample_03) - # test legacy default kwd - with self.assertWarningList("``default`` is deprecated"): - ht = apache.HtpasswdFile.from_string(self.sample_01, default="plaintext") - self.assertTrue(ht.set_password("user2", "pass2x")) - self.assertFalse(ht.set_password("user5", "pass5")) - self.assertEqual(ht.to_string(), self.sample_03) - # invalid user self.assertRaises(ValueError, ht.set_password, "user:", "pass") - # test that legacy update() still works - with self.assertWarningList("update\(\) is deprecated"): - ht.update("user2", "test") - self.assertTrue(ht.check_password("user2", "test")) - def test_02_set_password_autosave(self): path = self.mktemp() sample = b'user1:pass1\n' @@ -263,7 +241,7 @@ class HtpasswdFileTest(TestCase): # users 1..6 of sample_01 run through all the main hash formats, # to make sure they're recognized. - for i in irange(1, 7): + for i in range(1, 7): i = str(i) try: self.assertTrue(ht.check_password("user"+i, "pass"+i)) @@ -276,11 +254,6 @@ class HtpasswdFileTest(TestCase): self.assertRaises(ValueError, ht.check_password, "user:", "pass") - # test that legacy verify() still works - with self.assertWarningList(["verify\(\) is deprecated"]*2): - self.assertTrue(ht.verify("user1", "pass1")) - self.assertFalse(ht.verify("user1", "pass2")) - def test_05_load(self): """test load()""" # setup empty file @@ -348,17 +321,16 @@ class HtpasswdFileTest(TestCase): # check sample utf-8 ht = apache.HtpasswdFile.from_string(self.sample_04_utf8, encoding="utf-8", return_unicode=True) - self.assertEqual(ht.users(), [ u("user\u00e6") ]) + self.assertEqual(ht.users(), [ u"user\u00e6" ]) - # test deprecated encoding=None - with self.assertWarningList("``encoding=None`` is deprecated"): - ht = apache.HtpasswdFile.from_string(self.sample_04_utf8, encoding=None) - self.assertEqual(ht.users(), [ b'user\xc3\xa6' ]) + # encoding=None should throw error + self.assertRaises(TypeError, apache.HtpasswdFile.from_string, + self.sample_04_utf8, encoding=None) # check sample latin-1 ht = apache.HtpasswdFile.from_string(self.sample_04_latin1, encoding="latin-1", return_unicode=True) - self.assertEqual(ht.users(), [ u("user\u00e6") ]) + self.assertEqual(ht.users(), [ u"user\u00e6" ]) def test_08_get_hash(self): """test get_hash()""" @@ -367,9 +339,6 @@ class HtpasswdFileTest(TestCase): self.assertEqual(ht.get_hash("user4"), b"pass4") self.assertEqual(ht.get_hash("user5"), None) - with self.assertWarningList("find\(\) is deprecated"): - self.assertEqual(ht.find("user4"), b"pass4") - def test_09_to_string(self): """test to_string""" @@ -602,11 +571,6 @@ class HtdigestFileTest(TestCase): self.assertRaises(ValueError, ht.set_password, "user", "realm:", "pass") self.assertRaises(ValueError, ht.set_password, "user", "r"*256, "pass") - # test that legacy update() still works - with self.assertWarningList("update\(\) is deprecated"): - ht.update("user2", "realm2", "test") - self.assertTrue(ht.check_password("user2", "test")) - # TODO: test set_password autosave def test_03_users(self): @@ -625,7 +589,7 @@ class HtdigestFileTest(TestCase): self.assertRaises(TypeError, ht.check_password, 1, 'realm', 'pass5') self.assertRaises(TypeError, ht.check_password, 'user', 1, 'pass5') self.assertIs(ht.check_password("user5", "realm","pass5"), None) - for i in irange(1,5): + for i in range(1, 5): i = str(i) self.assertTrue(ht.check_password("user"+i, "realm", "pass"+i)) self.assertIs(ht.check_password("user"+i, "realm", "pass5"), False) @@ -636,11 +600,6 @@ class HtdigestFileTest(TestCase): self.assertTrue(ht.check_password("user1", "pass1")) self.assertIs(ht.check_password("user5", "pass5"), None) - # test that legacy verify() still works - with self.assertWarningList(["verify\(\) is deprecated"]*2): - self.assertTrue(ht.verify("user1", "realm", "pass1")) - self.assertFalse(ht.verify("user1", "realm", "pass2")) - # invalid user self.assertRaises(ValueError, ht.check_password, "user:", "realm", "pass") @@ -678,13 +637,6 @@ class HtdigestFileTest(TestCase): hc.load(path) self.assertEqual(hc.to_string(), self.sample_01) - # change file, test deprecated force=False kwd - ensure_mtime_changed(path) - set_file(path, "") - with self.assertWarningList(r"load\(force=False\) is deprecated"): - ha.load(force=False) - self.assertEqual(ha.to_string(), b"") - def test_06_save(self): """test save()""" # load from file @@ -725,9 +677,6 @@ class HtdigestFileTest(TestCase): self.assertEqual(ht.get_hash("user4", "realm"), "ab7b5d5f28ccc7666315f508c7358519") self.assertEqual(ht.get_hash("user5", "realm"), None) - with self.assertWarningList("find\(\) is deprecated"): - self.assertEqual(ht.find("user4", "realm"), "ab7b5d5f28ccc7666315f508c7358519") - def test_09_encodings(self): """test encoding parameter""" # test bad encodings cause failure in constructor @@ -735,13 +684,13 @@ class HtdigestFileTest(TestCase): # check sample utf-8 ht = apache.HtdigestFile.from_string(self.sample_04_utf8, encoding="utf-8", return_unicode=True) - self.assertEqual(ht.realms(), [ u("realm\u00e6") ]) - self.assertEqual(ht.users(u("realm\u00e6")), [ u("user\u00e6") ]) + self.assertEqual(ht.realms(), [ u"realm\u00e6" ]) + self.assertEqual(ht.users(u"realm\u00e6"), [ u"user\u00e6" ]) # check sample latin-1 ht = apache.HtdigestFile.from_string(self.sample_04_latin1, encoding="latin-1", return_unicode=True) - self.assertEqual(ht.realms(), [ u("realm\u00e6") ]) - self.assertEqual(ht.users(u("realm\u00e6")), [ u("user\u00e6") ]) + self.assertEqual(ht.realms(), [ u"realm\u00e6" ]) + self.assertEqual(ht.users(u"realm\u00e6"), [ u"user\u00e6" ]) def test_10_to_string(self): """test to_string()""" diff --git a/passlib/tests/test_apps.py b/passlib/tests/test_apps.py index 167437f..3a2b0d3 100644 --- a/passlib/tests/test_apps.py +++ b/passlib/tests/test_apps.py @@ -2,7 +2,6 @@ #============================================================================= # imports #============================================================================= -from __future__ import with_statement # core import logging; log = logging.getLogger(__name__) # site diff --git a/passlib/tests/test_context.py b/passlib/tests/test_context.py index 09b52c0..d7f90c6 100644 --- a/passlib/tests/test_context.py +++ b/passlib/tests/test_context.py @@ -3,12 +3,7 @@ # imports #============================================================================= # core -from __future__ import with_statement -from passlib.utils.compat import PY3 -if PY3: - from configparser import NoSectionError -else: - from ConfigParser import NoSectionError +from configparser import NoSectionError import datetime from functools import partial import logging; log = logging.getLogger(__name__) @@ -20,7 +15,6 @@ from passlib import hash from passlib.context import CryptContext, LazyCryptContext from passlib.exc import PasslibConfigWarning, PasslibHashWarning from passlib.utils import tick, to_unicode -from passlib.utils.compat import irange, u, unicode, str_to_uascii, PY2, PY26 import passlib.utils.handlers as uh from passlib.tests.utils import (TestCase, set_file, TICK_RESOLUTION, quicksleep, time_call, handler_derived_from) @@ -75,7 +69,7 @@ class CryptContextTest(TestCase): sample_1_resolved_dict = merge_dicts(sample_1_dict, schemes = sample_1_handlers) - sample_1_unnormalized = u("""\ + sample_1_unnormalized = u"""\ [passlib] schemes = des_crypt, md5_crypt, bsdi_crypt, sha512_crypt default = md5_crypt @@ -85,9 +79,9 @@ bsdi_crypt__default_rounds = 25001 bsdi_crypt__max_rounds = 30001 sha512_crypt__max_rounds = 50000 sha512_crypt__min_rounds = 40000 -""") +""" - sample_1_unicode = u("""\ + sample_1_unicode = u"""\ [passlib] schemes = des_crypt, md5_crypt, bsdi_crypt, sha512_crypt default = md5_crypt @@ -97,7 +91,7 @@ bsdi_crypt__max_rounds = 30001 sha512_crypt__max_rounds = 50000 sha512_crypt__min_rounds = 40000 -""") +""" #--------------------------------------------------------------- # sample 1 external files @@ -107,12 +101,12 @@ sha512_crypt__min_rounds = 40000 sample_1_path = os.path.join(here, "sample1.cfg") # sample 1 with '\r\n' linesep - sample_1b_unicode = sample_1_unicode.replace(u("\n"), u("\r\n")) + sample_1b_unicode = sample_1_unicode.replace(u"\n", u"\r\n") sample_1b_path = os.path.join(here, "sample1b.cfg") # sample 1 using UTF-16 and alt section - sample_1c_bytes = sample_1_unicode.replace(u("[passlib]"), - u("[mypolicy]")).encode("utf-16") + sample_1c_bytes = sample_1_unicode.replace(u"[passlib]", + u"[mypolicy]").encode("utf-16") sample_1c_path = os.path.join(here, "sample1c.cfg") # enable to regenerate sample files @@ -176,7 +170,7 @@ sha512_crypt__min_rounds = 45000 # setup #=================================================================== def setUp(self): - super(CryptContextTest, self).setUp() + super().setUp() warnings.filterwarnings("ignore", "The 'all' scheme is deprecated.*") warnings.filterwarnings("ignore", ".*'scheme' keyword is deprecated as of Passlib 1.7.*") @@ -207,7 +201,7 @@ sha512_crypt__min_rounds = 45000 self.assertEqual(ctx.to_dict(), self.sample_3_dict) # test unicode scheme names (issue 54) - ctx = CryptContext(schemes=[u("sha256_crypt")]) + ctx = CryptContext(schemes=[u"sha256_crypt"]) self.assertEqual(ctx.schemes(), ("sha256_crypt",)) def test_02_from_string(self): @@ -748,11 +742,6 @@ sha512_crypt__min_rounds = 45000 self.assertEqual(ctx.handler(category="admin", unconfigured=True), hash.md5_crypt) self.assertHandlerDerivedFrom(ctx.handler(category="staff"), hash.sha256_crypt) - # test unicode category strings are accepted under py2 - if PY2: - self.assertEqual(ctx.handler(category=u("staff"), unconfigured=True), hash.sha256_crypt) - self.assertEqual(ctx.handler(category=u("admin"), unconfigured=True), hash.md5_crypt) - def test_33_options(self): """test internal _get_record_options() method""" @@ -847,11 +836,7 @@ sha512_crypt__min_rounds = 45000 dump = ctx.to_string() # check ctx->string returns canonical format. - # NOTE: ConfigParser for PY26 doesn't use OrderedDict, - # making to_string()'s ordering unpredictable... - # so we skip this test under PY26. - if not PY26: - self.assertEqual(dump, self.sample_1_unicode) + self.assertEqual(dump, self.sample_1_unicode) # check ctx->string->ctx->dict returns original ctx2 = CryptContext.from_string(dump) @@ -933,14 +918,6 @@ sha512_crypt__min_rounds = 45000 # border cases #-------------------------------------------------------------- - # test unicode category strings are accepted under py2 - # this tests basic _get_record() used by hash/genhash/verify. - # we have to omit scheme=xxx so codepath is tested fully - if PY2: - c2 = cc.copy(default="phpass") - self.assertTrue(c2.genconfig(category=u("admin")).startswith("$P$5")) - self.assertTrue(c2.genconfig(category=u("staff")).startswith("$H$5")) - # throws error without schemes self.assertRaises(KeyError, CryptContext().genconfig) self.assertRaises(KeyError, CryptContext().genconfig, scheme='md5_crypt') @@ -1175,9 +1152,9 @@ sha512_crypt__min_rounds = 45000 def _calc_checksum(self, secret): from hashlib import md5 - if isinstance(secret, unicode): + if isinstance(secret, str): secret = secret.encode("utf-8") - return str_to_uascii(md5(secret).hexdigest()) + return md5(secret).hexdigest() # calling needs_update should query callback ctx = CryptContext([dummy]) @@ -1568,7 +1545,7 @@ sha512_crypt__min_rounds = 45000 handler = context.handler(scheme) salt = handler.default_salt_chars[0:1] * handler.max_salt_size seen = set() - for i in irange(300): + for i in range(300): h = context.genconfig(scheme, salt=salt) r = handler.from_string(h).rounds seen.add(r) @@ -1576,20 +1553,8 @@ sha512_crypt__min_rounds = 45000 self.assertEqual(max(seen), upper, "vary_rounds had wrong upper limit:") #=================================================================== - # harden_verify / min_verify_time + # dummy_verify() #=================================================================== - def test_harden_verify_parsing(self): - """harden_verify -- parsing""" - warnings.filterwarnings("ignore", ".*harden_verify.*", - category=DeprecationWarning) - - # valid values - ctx = CryptContext(schemes=["sha256_crypt"]) - self.assertEqual(ctx.harden_verify, None) - self.assertEqual(ctx.using(harden_verify="").harden_verify, None) - self.assertEqual(ctx.using(harden_verify="true").harden_verify, None) - self.assertEqual(ctx.using(harden_verify="false").harden_verify, None) - def test_dummy_verify(self): """ dummy_verify() method @@ -1728,13 +1693,13 @@ class DelayHash(uh.StaticHandler): checksum_chars = uh.LOWER_HEX_CHARS checksum_size = 40 delay = 0 - _hash_prefix = u("$x$") + _hash_prefix = u"$x$" def _calc_checksum(self, secret): time.sleep(self.delay) - if isinstance(secret, unicode): + if isinstance(secret, str): secret = secret.encode("utf-8") - return str_to_uascii(hashlib.sha1(b"prefix" + secret).hexdigest()) + return hashlib.sha1(b"prefix" + secret).hexdigest() #============================================================================= # LazyCryptContext diff --git a/passlib/tests/test_context_deprecated.py b/passlib/tests/test_context_deprecated.py deleted file mode 100644 index 0f76624..0000000 --- a/passlib/tests/test_context_deprecated.py +++ /dev/null @@ -1,743 +0,0 @@ -"""tests for passlib.context - -this file is a clone of the 1.5 test_context.py, -containing the tests using the legacy CryptPolicy api. -it's being preserved here to ensure the old api doesn't break -(until Passlib 1.8, when this and the legacy api will be removed). -""" -#============================================================================= -# imports -#============================================================================= -from __future__ import with_statement -# core -from logging import getLogger -import os -import warnings -# site -try: - from pkg_resources import resource_filename -except ImportError: - resource_filename = None -# pkg -from passlib import hash -from passlib.context import CryptContext, CryptPolicy, LazyCryptContext -from passlib.utils import to_bytes, to_unicode -import passlib.utils.handlers as uh -from passlib.tests.utils import TestCase, set_file -from passlib.registry import (register_crypt_handler_path, - _has_crypt_handler as has_crypt_handler, - _unload_handler_name as unload_handler_name, - ) -# module -log = getLogger(__name__) - -#============================================================================= -# -#============================================================================= -class CryptPolicyTest(TestCase): - """test CryptPolicy object""" - - # TODO: need to test user categories w/in all this - - descriptionPrefix = "CryptPolicy" - - #=================================================================== - # sample crypt policies used for testing - #=================================================================== - - #--------------------------------------------------------------- - # sample 1 - average config file - #--------------------------------------------------------------- - # NOTE: copy of this is stored in file passlib/tests/sample_config_1s.cfg - sample_config_1s = """\ -[passlib] -schemes = des_crypt, md5_crypt, bsdi_crypt, sha512_crypt -default = md5_crypt -all.vary_rounds = 10%% -bsdi_crypt.max_rounds = 30000 -bsdi_crypt.default_rounds = 25000 -sha512_crypt.max_rounds = 50000 -sha512_crypt.min_rounds = 40000 -""" - sample_config_1s_path = os.path.abspath(os.path.join( - os.path.dirname(__file__), "sample_config_1s.cfg")) - if not os.path.exists(sample_config_1s_path) and resource_filename: - # in case we're zipped up in an egg. - sample_config_1s_path = resource_filename("passlib.tests", - "sample_config_1s.cfg") - - # make sure sample_config_1s uses \n linesep - tests rely on this - assert sample_config_1s.startswith("[passlib]\nschemes") - - sample_config_1pd = dict( - schemes = [ "des_crypt", "md5_crypt", "bsdi_crypt", "sha512_crypt"], - default = "md5_crypt", - # NOTE: not maintaining backwards compat for rendering to "10%" - all__vary_rounds = 0.1, - bsdi_crypt__max_rounds = 30000, - bsdi_crypt__default_rounds = 25000, - sha512_crypt__max_rounds = 50000, - sha512_crypt__min_rounds = 40000, - ) - - sample_config_1pid = { - "schemes": "des_crypt, md5_crypt, bsdi_crypt, sha512_crypt", - "default": "md5_crypt", - # NOTE: not maintaining backwards compat for rendering to "10%" - "all.vary_rounds": 0.1, - "bsdi_crypt.max_rounds": 30000, - "bsdi_crypt.default_rounds": 25000, - "sha512_crypt.max_rounds": 50000, - "sha512_crypt.min_rounds": 40000, - } - - sample_config_1prd = dict( - schemes = [ hash.des_crypt, hash.md5_crypt, hash.bsdi_crypt, hash.sha512_crypt], - default = "md5_crypt", # NOTE: passlib <= 1.5 was handler obj. - # NOTE: not maintaining backwards compat for rendering to "10%" - all__vary_rounds = 0.1, - bsdi_crypt__max_rounds = 30000, - bsdi_crypt__default_rounds = 25000, - sha512_crypt__max_rounds = 50000, - sha512_crypt__min_rounds = 40000, - ) - - #--------------------------------------------------------------- - # sample 2 - partial policy & result of overlay on sample 1 - #--------------------------------------------------------------- - sample_config_2s = """\ -[passlib] -bsdi_crypt.min_rounds = 29000 -bsdi_crypt.max_rounds = 35000 -bsdi_crypt.default_rounds = 31000 -sha512_crypt.min_rounds = 45000 -""" - - sample_config_2pd = dict( - # using this to test full replacement of existing options - bsdi_crypt__min_rounds = 29000, - bsdi_crypt__max_rounds = 35000, - bsdi_crypt__default_rounds = 31000, - # using this to test partial replacement of existing options - sha512_crypt__min_rounds=45000, - ) - - sample_config_12pd = dict( - schemes = [ "des_crypt", "md5_crypt", "bsdi_crypt", "sha512_crypt"], - default = "md5_crypt", - # NOTE: not maintaining backwards compat for rendering to "10%" - all__vary_rounds = 0.1, - bsdi_crypt__min_rounds = 29000, - bsdi_crypt__max_rounds = 35000, - bsdi_crypt__default_rounds = 31000, - sha512_crypt__max_rounds = 50000, - sha512_crypt__min_rounds=45000, - ) - - #--------------------------------------------------------------- - # sample 3 - just changing default - #--------------------------------------------------------------- - sample_config_3pd = dict( - default="sha512_crypt", - ) - - sample_config_123pd = dict( - schemes = [ "des_crypt", "md5_crypt", "bsdi_crypt", "sha512_crypt"], - default = "sha512_crypt", - # NOTE: not maintaining backwards compat for rendering to "10%" - all__vary_rounds = 0.1, - bsdi_crypt__min_rounds = 29000, - bsdi_crypt__max_rounds = 35000, - bsdi_crypt__default_rounds = 31000, - sha512_crypt__max_rounds = 50000, - sha512_crypt__min_rounds=45000, - ) - - #--------------------------------------------------------------- - # sample 4 - category specific - #--------------------------------------------------------------- - sample_config_4s = """ -[passlib] -schemes = sha512_crypt -all.vary_rounds = 10%% -default.sha512_crypt.max_rounds = 20000 -admin.all.vary_rounds = 5%% -admin.sha512_crypt.max_rounds = 40000 -""" - - sample_config_4pd = dict( - schemes = [ "sha512_crypt" ], - # NOTE: not maintaining backwards compat for rendering to "10%" - all__vary_rounds = 0.1, - sha512_crypt__max_rounds = 20000, - # NOTE: not maintaining backwards compat for rendering to "5%" - admin__all__vary_rounds = 0.05, - admin__sha512_crypt__max_rounds = 40000, - ) - - #--------------------------------------------------------------- - # sample 5 - to_string & deprecation testing - #--------------------------------------------------------------- - sample_config_5s = sample_config_1s + """\ -deprecated = des_crypt -admin__context__deprecated = des_crypt, bsdi_crypt -""" - - sample_config_5pd = sample_config_1pd.copy() - sample_config_5pd.update( - deprecated = [ "des_crypt" ], - admin__context__deprecated = [ "des_crypt", "bsdi_crypt" ], - ) - - sample_config_5pid = sample_config_1pid.copy() - sample_config_5pid.update({ - "deprecated": "des_crypt", - "admin.context.deprecated": "des_crypt, bsdi_crypt", - }) - - sample_config_5prd = sample_config_1prd.copy() - sample_config_5prd.update({ - # XXX: should deprecated return the actual handlers in this case? - # would have to modify how policy stores info, for one. - "deprecated": ["des_crypt"], - "admin__context__deprecated": ["des_crypt", "bsdi_crypt"], - }) - - #=================================================================== - # constructors - #=================================================================== - def setUp(self): - TestCase.setUp(self) - warnings.filterwarnings("ignore", - r"The CryptPolicy class has been deprecated") - warnings.filterwarnings("ignore", - r"the method.*hash_needs_update.*is deprecated") - warnings.filterwarnings("ignore", "The 'all' scheme is deprecated.*") - warnings.filterwarnings("ignore", "bsdi_crypt rounds should be odd") - - def test_00_constructor(self): - """test CryptPolicy() constructor""" - policy = CryptPolicy(**self.sample_config_1pd) - self.assertEqual(policy.to_dict(), self.sample_config_1pd) - - policy = CryptPolicy(self.sample_config_1pd) - self.assertEqual(policy.to_dict(), self.sample_config_1pd) - - self.assertRaises(TypeError, CryptPolicy, {}, {}) - self.assertRaises(TypeError, CryptPolicy, {}, dummy=1) - - # check key with too many separators is rejected - self.assertRaises(TypeError, CryptPolicy, - schemes = [ "des_crypt", "md5_crypt", "bsdi_crypt", "sha512_crypt"], - bad__key__bsdi_crypt__max_rounds = 30000, - ) - - # check nameless handler rejected - class nameless(uh.StaticHandler): - name = None - self.assertRaises(ValueError, CryptPolicy, schemes=[nameless]) - - # check scheme must be name or crypt handler - self.assertRaises(TypeError, CryptPolicy, schemes=[uh.StaticHandler]) - - # check name conflicts are rejected - class dummy_1(uh.StaticHandler): - name = 'dummy_1' - self.assertRaises(KeyError, CryptPolicy, schemes=[dummy_1, dummy_1]) - - # with unknown deprecated value - self.assertRaises(KeyError, CryptPolicy, - schemes=['des_crypt'], - deprecated=['md5_crypt']) - - # with unknown default value - self.assertRaises(KeyError, CryptPolicy, - schemes=['des_crypt'], - default='md5_crypt') - - def test_01_from_path_simple(self): - """test CryptPolicy.from_path() constructor""" - # NOTE: this is separate so it can also run under GAE - - # test preset stored in existing file - path = self.sample_config_1s_path - policy = CryptPolicy.from_path(path) - self.assertEqual(policy.to_dict(), self.sample_config_1pd) - - # test if path missing - self.assertRaises(EnvironmentError, CryptPolicy.from_path, path + 'xxx') - - def test_01_from_path(self): - """test CryptPolicy.from_path() constructor with encodings""" - path = self.mktemp() - - # test "\n" linesep - set_file(path, self.sample_config_1s) - policy = CryptPolicy.from_path(path) - self.assertEqual(policy.to_dict(), self.sample_config_1pd) - - # test "\r\n" linesep - set_file(path, self.sample_config_1s.replace("\n","\r\n")) - policy = CryptPolicy.from_path(path) - self.assertEqual(policy.to_dict(), self.sample_config_1pd) - - # test with custom encoding - uc2 = to_bytes(self.sample_config_1s, "utf-16", source_encoding="utf-8") - set_file(path, uc2) - policy = CryptPolicy.from_path(path, encoding="utf-16") - self.assertEqual(policy.to_dict(), self.sample_config_1pd) - - def test_02_from_string(self): - """test CryptPolicy.from_string() constructor""" - # test "\n" linesep - policy = CryptPolicy.from_string(self.sample_config_1s) - self.assertEqual(policy.to_dict(), self.sample_config_1pd) - - # test "\r\n" linesep - policy = CryptPolicy.from_string( - self.sample_config_1s.replace("\n","\r\n")) - self.assertEqual(policy.to_dict(), self.sample_config_1pd) - - # test with unicode - data = to_unicode(self.sample_config_1s) - policy = CryptPolicy.from_string(data) - self.assertEqual(policy.to_dict(), self.sample_config_1pd) - - # test with non-ascii-compatible encoding - uc2 = to_bytes(self.sample_config_1s, "utf-16", source_encoding="utf-8") - policy = CryptPolicy.from_string(uc2, encoding="utf-16") - self.assertEqual(policy.to_dict(), self.sample_config_1pd) - - # test category specific options - policy = CryptPolicy.from_string(self.sample_config_4s) - self.assertEqual(policy.to_dict(), self.sample_config_4pd) - - def test_03_from_source(self): - """test CryptPolicy.from_source() constructor""" - # pass it a path - policy = CryptPolicy.from_source(self.sample_config_1s_path) - self.assertEqual(policy.to_dict(), self.sample_config_1pd) - - # pass it a string - policy = CryptPolicy.from_source(self.sample_config_1s) - self.assertEqual(policy.to_dict(), self.sample_config_1pd) - - # pass it a dict (NOTE: make a copy to detect in-place modifications) - policy = CryptPolicy.from_source(self.sample_config_1pd.copy()) - self.assertEqual(policy.to_dict(), self.sample_config_1pd) - - # pass it existing policy - p2 = CryptPolicy.from_source(policy) - self.assertIs(policy, p2) - - # pass it something wrong - self.assertRaises(TypeError, CryptPolicy.from_source, 1) - self.assertRaises(TypeError, CryptPolicy.from_source, []) - - def test_04_from_sources(self): - """test CryptPolicy.from_sources() constructor""" - - # pass it empty list - self.assertRaises(ValueError, CryptPolicy.from_sources, []) - - # pass it one-element list - policy = CryptPolicy.from_sources([self.sample_config_1s]) - self.assertEqual(policy.to_dict(), self.sample_config_1pd) - - # pass multiple sources - policy = CryptPolicy.from_sources( - [ - self.sample_config_1s_path, - self.sample_config_2s, - self.sample_config_3pd, - ]) - self.assertEqual(policy.to_dict(), self.sample_config_123pd) - - def test_05_replace(self): - """test CryptPolicy.replace() constructor""" - - p1 = CryptPolicy(**self.sample_config_1pd) - - # check overlaying sample 2 - p2 = p1.replace(**self.sample_config_2pd) - self.assertEqual(p2.to_dict(), self.sample_config_12pd) - - # check repeating overlay makes no change - p2b = p2.replace(**self.sample_config_2pd) - self.assertEqual(p2b.to_dict(), self.sample_config_12pd) - - # check overlaying sample 3 - p3 = p2.replace(self.sample_config_3pd) - self.assertEqual(p3.to_dict(), self.sample_config_123pd) - - def test_06_forbidden(self): - """test CryptPolicy() forbidden kwds""" - - # salt not allowed to be set - self.assertRaises(KeyError, CryptPolicy, - schemes=["des_crypt"], - des_crypt__salt="xx", - ) - self.assertRaises(KeyError, CryptPolicy, - schemes=["des_crypt"], - all__salt="xx", - ) - - # schemes not allowed for category - self.assertRaises(KeyError, CryptPolicy, - schemes=["des_crypt"], - user__context__schemes=["md5_crypt"], - ) - - #=================================================================== - # reading - #=================================================================== - def test_10_has_schemes(self): - """test has_schemes() method""" - - p1 = CryptPolicy(**self.sample_config_1pd) - self.assertTrue(p1.has_schemes()) - - p3 = CryptPolicy(**self.sample_config_3pd) - self.assertTrue(not p3.has_schemes()) - - def test_11_iter_handlers(self): - """test iter_handlers() method""" - - p1 = CryptPolicy(**self.sample_config_1pd) - s = self.sample_config_1prd['schemes'] - self.assertEqual(list(p1.iter_handlers()), s) - - p3 = CryptPolicy(**self.sample_config_3pd) - self.assertEqual(list(p3.iter_handlers()), []) - - def test_12_get_handler(self): - """test get_handler() method""" - - p1 = CryptPolicy(**self.sample_config_1pd) - - # check by name - self.assertIs(p1.get_handler("bsdi_crypt"), hash.bsdi_crypt) - - # check by missing name - self.assertIs(p1.get_handler("sha256_crypt"), None) - self.assertRaises(KeyError, p1.get_handler, "sha256_crypt", required=True) - - # check default - self.assertIs(p1.get_handler(), hash.md5_crypt) - - def test_13_get_options(self): - """test get_options() method""" - - p12 = CryptPolicy(**self.sample_config_12pd) - - self.assertEqual(p12.get_options("bsdi_crypt"),dict( - # NOTE: not maintaining backwards compat for rendering to "10%" - vary_rounds = 0.1, - min_rounds = 29000, - max_rounds = 35000, - default_rounds = 31000, - )) - - self.assertEqual(p12.get_options("sha512_crypt"),dict( - # NOTE: not maintaining backwards compat for rendering to "10%" - vary_rounds = 0.1, - min_rounds = 45000, - max_rounds = 50000, - )) - - p4 = CryptPolicy.from_string(self.sample_config_4s) - self.assertEqual(p4.get_options("sha512_crypt"), dict( - # NOTE: not maintaining backwards compat for rendering to "10%" - vary_rounds=0.1, - max_rounds=20000, - )) - - self.assertEqual(p4.get_options("sha512_crypt", "user"), dict( - # NOTE: not maintaining backwards compat for rendering to "10%" - vary_rounds=0.1, - max_rounds=20000, - )) - - self.assertEqual(p4.get_options("sha512_crypt", "admin"), dict( - # NOTE: not maintaining backwards compat for rendering to "5%" - vary_rounds=0.05, - max_rounds=40000, - )) - - def test_14_handler_is_deprecated(self): - """test handler_is_deprecated() method""" - pa = CryptPolicy(**self.sample_config_1pd) - pb = CryptPolicy(**self.sample_config_5pd) - - self.assertFalse(pa.handler_is_deprecated("des_crypt")) - self.assertFalse(pa.handler_is_deprecated(hash.bsdi_crypt)) - self.assertFalse(pa.handler_is_deprecated("sha512_crypt")) - - self.assertTrue(pb.handler_is_deprecated("des_crypt")) - self.assertFalse(pb.handler_is_deprecated(hash.bsdi_crypt)) - self.assertFalse(pb.handler_is_deprecated("sha512_crypt")) - - # check categories as well - self.assertTrue(pb.handler_is_deprecated("des_crypt", "user")) - self.assertFalse(pb.handler_is_deprecated("bsdi_crypt", "user")) - self.assertTrue(pb.handler_is_deprecated("des_crypt", "admin")) - self.assertTrue(pb.handler_is_deprecated("bsdi_crypt", "admin")) - - # check deprecation is overridden per category - pc = CryptPolicy( - schemes=["md5_crypt", "des_crypt"], - deprecated=["md5_crypt"], - user__context__deprecated=["des_crypt"], - ) - self.assertTrue(pc.handler_is_deprecated("md5_crypt")) - self.assertFalse(pc.handler_is_deprecated("des_crypt")) - self.assertFalse(pc.handler_is_deprecated("md5_crypt", "user")) - self.assertTrue(pc.handler_is_deprecated("des_crypt", "user")) - - def test_15_min_verify_time(self): - """test get_min_verify_time() method""" - # silence deprecation warnings for min verify time - warnings.filterwarnings("ignore", category=DeprecationWarning) - - pa = CryptPolicy() - self.assertEqual(pa.get_min_verify_time(), 0) - self.assertEqual(pa.get_min_verify_time('admin'), 0) - - pb = pa.replace(min_verify_time=.1) - self.assertEqual(pb.get_min_verify_time(), 0) - self.assertEqual(pb.get_min_verify_time('admin'), 0) - - #=================================================================== - # serialization - #=================================================================== - def test_20_iter_config(self): - """test iter_config() method""" - p5 = CryptPolicy(**self.sample_config_5pd) - self.assertEqual(dict(p5.iter_config()), self.sample_config_5pd) - self.assertEqual(dict(p5.iter_config(resolve=True)), self.sample_config_5prd) - self.assertEqual(dict(p5.iter_config(ini=True)), self.sample_config_5pid) - - def test_21_to_dict(self): - """test to_dict() method""" - p5 = CryptPolicy(**self.sample_config_5pd) - self.assertEqual(p5.to_dict(), self.sample_config_5pd) - self.assertEqual(p5.to_dict(resolve=True), self.sample_config_5prd) - - def test_22_to_string(self): - """test to_string() method""" - pa = CryptPolicy(**self.sample_config_5pd) - s = pa.to_string() # NOTE: can't compare string directly, ordering etc may not match - pb = CryptPolicy.from_string(s) - self.assertEqual(pb.to_dict(), self.sample_config_5pd) - - s = pa.to_string(encoding="latin-1") - self.assertIsInstance(s, bytes) - - #=================================================================== - # - #=================================================================== - -#============================================================================= -# CryptContext -#============================================================================= -class CryptContextTest(TestCase): - """test CryptContext class""" - descriptionPrefix = "CryptContext" - - def setUp(self): - TestCase.setUp(self) - warnings.filterwarnings("ignore", - r"CryptContext\(\)\.replace\(\) has been deprecated.*") - warnings.filterwarnings("ignore", - r"The CryptContext ``policy`` keyword has been deprecated.*") - warnings.filterwarnings("ignore", ".*(CryptPolicy|context\.policy).*(has|have) been deprecated.*") - warnings.filterwarnings("ignore", - r"the method.*hash_needs_update.*is deprecated") - - #=================================================================== - # constructor - #=================================================================== - def test_00_constructor(self): - """test constructor""" - # create crypt context using handlers - cc = CryptContext([hash.md5_crypt, hash.bsdi_crypt, hash.des_crypt]) - c,b,a = cc.policy.iter_handlers() - self.assertIs(a, hash.des_crypt) - self.assertIs(b, hash.bsdi_crypt) - self.assertIs(c, hash.md5_crypt) - - # create context using names - cc = CryptContext(["md5_crypt", "bsdi_crypt", "des_crypt"]) - c,b,a = cc.policy.iter_handlers() - self.assertIs(a, hash.des_crypt) - self.assertIs(b, hash.bsdi_crypt) - self.assertIs(c, hash.md5_crypt) - - # policy kwd - policy = cc.policy - cc = CryptContext(policy=policy) - self.assertEqual(cc.to_dict(), policy.to_dict()) - - cc = CryptContext(policy=policy, default="bsdi_crypt") - self.assertNotEqual(cc.to_dict(), policy.to_dict()) - self.assertEqual(cc.to_dict(), dict(schemes=["md5_crypt","bsdi_crypt","des_crypt"], - default="bsdi_crypt")) - - self.assertRaises(TypeError, setattr, cc, 'policy', None) - self.assertRaises(TypeError, CryptContext, policy='x') - - def test_01_replace(self): - """test replace()""" - - cc = CryptContext(["md5_crypt", "bsdi_crypt", "des_crypt"]) - self.assertIs(cc.policy.get_handler(), hash.md5_crypt) - - cc2 = cc.replace() - self.assertIsNot(cc2, cc) - # NOTE: was not able to maintain backward compatibility with this... - ##self.assertIs(cc2.policy, cc.policy) - - cc3 = cc.replace(default="bsdi_crypt") - self.assertIsNot(cc3, cc) - # NOTE: was not able to maintain backward compatibility with this... - ##self.assertIs(cc3.policy, cc.policy) - self.assertIs(cc3.policy.get_handler(), hash.bsdi_crypt) - - def test_02_no_handlers(self): - """test no handlers""" - - # check constructor... - cc = CryptContext() - self.assertRaises(KeyError, cc.identify, 'hash', required=True) - self.assertRaises(KeyError, cc.hash, 'secret') - self.assertRaises(KeyError, cc.verify, 'secret', 'hash') - - # check updating policy after the fact... - cc = CryptContext(['md5_crypt']) - p = CryptPolicy(schemes=[]) - cc.policy = p - - self.assertRaises(KeyError, cc.identify, 'hash', required=True) - self.assertRaises(KeyError, cc.hash, 'secret') - self.assertRaises(KeyError, cc.verify, 'secret', 'hash') - - #=================================================================== - # policy adaptation - #=================================================================== - sample_policy_1 = dict( - schemes = [ "des_crypt", "md5_crypt", "phpass", "bsdi_crypt", - "sha256_crypt"], - deprecated = [ "des_crypt", ], - default = "sha256_crypt", - bsdi_crypt__max_rounds = 30, - bsdi_crypt__default_rounds = 25, - bsdi_crypt__vary_rounds = 0, - sha256_crypt__max_rounds = 3000, - sha256_crypt__min_rounds = 2000, - sha256_crypt__default_rounds = 3000, - phpass__ident = "H", - phpass__default_rounds = 7, - ) - - def test_12_hash_needs_update(self): - """test hash_needs_update() method""" - cc = CryptContext(**self.sample_policy_1) - - # check deprecated scheme - self.assertTrue(cc.hash_needs_update('9XXD4trGYeGJA')) - self.assertFalse(cc.hash_needs_update('$1$J8HC2RCr$HcmM.7NxB2weSvlw2FgzU0')) - - # check min rounds - self.assertTrue(cc.hash_needs_update('$5$rounds=1999$jD81UCoo.zI.UETs$Y7qSTQ6mTiU9qZB4fRr43wRgQq4V.5AAf7F97Pzxey/')) - self.assertFalse(cc.hash_needs_update('$5$rounds=2000$228SSRje04cnNCaQ$YGV4RYu.5sNiBvorQDlO0WWQjyJVGKBcJXz3OtyQ2u8')) - - # check max rounds - self.assertFalse(cc.hash_needs_update('$5$rounds=3000$fS9iazEwTKi7QPW4$VasgBC8FqlOvD7x2HhABaMXCTh9jwHclPA9j5YQdns.')) - self.assertTrue(cc.hash_needs_update('$5$rounds=3001$QlFHHifXvpFX4PLs$/0ekt7lSs/lOikSerQ0M/1porEHxYq7W/2hdFpxA3fA')) - - #=================================================================== - # border cases - #=================================================================== - def test_30_nonstring_hash(self): - """test non-string hash values cause error""" - warnings.filterwarnings("ignore", ".*needs_update.*'scheme' keyword is deprecated.*") - - # - # test hash=None or some other non-string causes TypeError - # and that explicit-scheme code path behaves the same. - # - cc = CryptContext(["des_crypt"]) - for hash, kwds in [ - (None, {}), - # NOTE: 'scheme' kwd is deprecated... - (None, {"scheme": "des_crypt"}), - (1, {}), - ((), {}), - ]: - - self.assertRaises(TypeError, cc.hash_needs_update, hash, **kwds) - - cc2 = CryptContext(["mysql323"]) - self.assertRaises(TypeError, cc2.hash_needs_update, None) - - #=================================================================== - # eoc - #=================================================================== - -#============================================================================= -# LazyCryptContext -#============================================================================= -class dummy_2(uh.StaticHandler): - name = "dummy_2" - -class LazyCryptContextTest(TestCase): - descriptionPrefix = "LazyCryptContext" - - def setUp(self): - TestCase.setUp(self) - - # make sure this isn't registered before OR after - unload_handler_name("dummy_2") - self.addCleanup(unload_handler_name, "dummy_2") - - # silence some warnings - warnings.filterwarnings("ignore", - r"CryptContext\(\)\.replace\(\) has been deprecated") - warnings.filterwarnings("ignore", ".*(CryptPolicy|context\.policy).*(has|have) been deprecated.*") - - def test_kwd_constructor(self): - """test plain kwds""" - self.assertFalse(has_crypt_handler("dummy_2")) - register_crypt_handler_path("dummy_2", "passlib.tests.test_context") - - cc = LazyCryptContext(iter(["dummy_2", "des_crypt"]), deprecated=["des_crypt"]) - - self.assertFalse(has_crypt_handler("dummy_2", True)) - - self.assertTrue(cc.policy.handler_is_deprecated("des_crypt")) - self.assertEqual(cc.policy.schemes(), ["dummy_2", "des_crypt"]) - - self.assertTrue(has_crypt_handler("dummy_2", True)) - - def test_callable_constructor(self): - """test create_policy() hook, returning CryptPolicy""" - self.assertFalse(has_crypt_handler("dummy_2")) - register_crypt_handler_path("dummy_2", "passlib.tests.test_context") - - def create_policy(flag=False): - self.assertTrue(flag) - return CryptPolicy(schemes=iter(["dummy_2", "des_crypt"]), deprecated=["des_crypt"]) - - cc = LazyCryptContext(create_policy=create_policy, flag=True) - - self.assertFalse(has_crypt_handler("dummy_2", True)) - - self.assertTrue(cc.policy.handler_is_deprecated("des_crypt")) - self.assertEqual(cc.policy.schemes(), ["dummy_2", "des_crypt"]) - - self.assertTrue(has_crypt_handler("dummy_2", True)) - -#============================================================================= -# eof -#============================================================================= diff --git a/passlib/tests/test_crypto_builtin_md4.py b/passlib/tests/test_crypto_builtin_md4.py index 0aca1eb..e74b924 100644 --- a/passlib/tests/test_crypto_builtin_md4.py +++ b/passlib/tests/test_crypto_builtin_md4.py @@ -2,16 +2,16 @@ #============================================================================= # imports #============================================================================= -from __future__ import with_statement, division # core from binascii import hexlify import hashlib +from unittest import skipUnless # site # pkg # module -from passlib.utils.compat import bascii_to_str, PY3, u +from passlib.utils.compat import bascii_to_str from passlib.crypto.digest import lookup_hash -from passlib.tests.utils import TestCase, skipUnless +from passlib.tests.utils import TestCase # local __all__ = [ "_Common_MD4_Test", @@ -62,16 +62,10 @@ class _Common_MD4_Test(TestCase): h.update(b'bcdefghijklmnopqrstuvwxyz') self.assertEqual(h.hexdigest(), "d79e1c308aa5bbcdeea8ed63df412da9") - if PY3: - # reject unicode, hash should return digest of b'' - h = md4() - self.assertRaises(TypeError, h.update, u('a')) - self.assertEqual(h.hexdigest(), "31d6cfe0d16ae931b73c59d7e0c089c0") - else: - # coerce unicode to ascii, hash should return digest of b'a' - h = md4() - h.update(u('a')) - self.assertEqual(h.hexdigest(), "bde52cb31de33e46245e05fbdbd6fb24") + # reject unicode, hash should return digest of b'' + h = md4() + self.assertRaises(TypeError, h.update, u'a') + self.assertEqual(h.hexdigest(), "31d6cfe0d16ae931b73c59d7e0c089c0") def test_md4_hexdigest(self): """hexdigest() method""" @@ -124,7 +118,7 @@ class MD4_SSL_Test(_Common_MD4_Test): # this is more to test our test is correct :) def setUp(self): - super(MD4_SSL_Test, self).setUp() + super().setUp() # make sure we're using right constructor. self.assertEqual(self.get_md4_const().__module__, "hashlib") @@ -134,7 +128,7 @@ class MD4_Builtin_Test(_Common_MD4_Test): descriptionPrefix = "passlib.crypto._md4.md4()" def setUp(self): - super(MD4_Builtin_Test, self).setUp() + super().setUp() if has_native_md4(): diff --git a/passlib/tests/test_crypto_des.py b/passlib/tests/test_crypto_des.py index ab31845..20f3681 100644 --- a/passlib/tests/test_crypto_des.py +++ b/passlib/tests/test_crypto_des.py @@ -2,7 +2,6 @@ #============================================================================= # imports #============================================================================= -from __future__ import with_statement, division # core from functools import partial # site diff --git a/passlib/tests/test_crypto_digest.py b/passlib/tests/test_crypto_digest.py index 461d209..66f781c 100644 --- a/passlib/tests/test_crypto_digest.py +++ b/passlib/tests/test_crypto_digest.py @@ -2,17 +2,17 @@ #============================================================================= # imports #============================================================================= -from __future__ import with_statement, division # core from binascii import hexlify import hashlib +from unittest import skipUnless import warnings # site # pkg # module from passlib.exc import UnknownHashError -from passlib.utils.compat import PY3, u, JYTHON -from passlib.tests.utils import TestCase, TEST_MODE, skipUnless, hb +from passlib.utils.compat import JYTHON +from passlib.tests.utils import TestCase, TEST_MODE, hb #============================================================================= # test assorted crypto helpers @@ -56,7 +56,7 @@ class HashInfoTest(TestCase): warnings.filterwarnings("ignore", '.*unsupported hash') # test string types - self.assertEqual(norm_hash_name(u("MD4")), "md4") + self.assertEqual(norm_hash_name(u"MD4"), "md4") self.assertEqual(norm_hash_name(b"MD4"), "md4") self.assertRaises(TypeError, norm_hash_name, None) @@ -497,12 +497,7 @@ class Pbkdf2Test(TestCase): self.assertEqual("hashlib-ssl" in PBKDF2_BACKENDS, has_hashlib_ssl) # check for appropriate builtin - from passlib.utils.compat import PY3 - if PY3: - self.assertIn("builtin-from-bytes", PBKDF2_BACKENDS) - else: - # XXX: only true as long as this is preferred over hexlify - self.assertIn("builtin-unpack", PBKDF2_BACKENDS) + self.assertIn("builtin-from-bytes", PBKDF2_BACKENDS) def test_border(self): """test border cases""" diff --git a/passlib/tests/test_crypto_scrypt.py b/passlib/tests/test_crypto_scrypt.py index 73ff1fa..5009db0 100644 --- a/passlib/tests/test_crypto_scrypt.py +++ b/passlib/tests/test_crypto_scrypt.py @@ -7,15 +7,16 @@ from binascii import hexlify import hashlib import logging; log = logging.getLogger(__name__) import struct +from unittest import skipUnless import warnings warnings.filterwarnings("ignore", ".*using builtin scrypt backend.*") # site # pkg from passlib import exc from passlib.utils import getrandbytes -from passlib.utils.compat import PYPY, u, bascii_to_str +from passlib.utils.compat import PYPY, bascii_to_str from passlib.utils.decor import classproperty -from passlib.tests.utils import TestCase, skipUnless, TEST_MODE, hb +from passlib.tests.utils import TestCase, TEST_MODE, hb # subject from passlib.crypto import scrypt as scrypt_mod # local @@ -312,7 +313,7 @@ class _CommonScryptTest(TestCase): def setUp(self): assert self.backend scrypt_mod._set_backend(self.backend) - super(_CommonScryptTest, self).setUp() + super().setUp() #============================================================================= # reference vectors @@ -450,7 +451,7 @@ class _CommonScryptTest(TestCase): return hexstr(scrypt_mod.scrypt(secret, "salt", 2, 2, 2, 16)) # unicode - TEXT = u("abc\u00defg") + TEXT = u"abc\u00defg" self.assertEqual(run_scrypt(TEXT), '05717106997bfe0da42cf4779a2f8bd8') # utf8 bytes @@ -475,7 +476,7 @@ class _CommonScryptTest(TestCase): return hexstr(scrypt_mod.scrypt("secret", salt, 2, 2, 2, 16)) # unicode - TEXT = u("abc\u00defg") + TEXT = u"abc\u00defg" self.assertEqual(run_scrypt(TEXT), 'a748ec0f4613929e9e5f03d1ab741d88') # utf8 bytes @@ -597,7 +598,7 @@ class BuiltinScryptTest(_CommonScryptTest): backend = "builtin" def setUp(self): - super(BuiltinScryptTest, self).setUp() + super().setUp() warnings.filterwarnings("ignore", "(?i)using builtin scrypt backend", category=exc.PasslibSecurityWarning) diff --git a/passlib/tests/test_ext_django.py b/passlib/tests/test_ext_django.py index 2a0b418..4a2d4c9 100644 --- a/passlib/tests/test_ext_django.py +++ b/passlib/tests/test_ext_django.py @@ -3,7 +3,6 @@ # imports #============================================================================= # core -from __future__ import absolute_import, division, print_function import logging; log = logging.getLogger(__name__) import sys import re @@ -15,7 +14,7 @@ from passlib.context import CryptContext from passlib.ext.django.utils import ( DJANGO_VERSION, MIN_DJANGO_VERSION, DjangoTranslator, quirks, ) -from passlib.utils.compat import iteritems, get_method_function, u +from passlib.utils.compat import get_method_function from passlib.utils.decor import memoized_property # tests from passlib.tests.utils import TestCase, TEST_MODE, handler_derived_from @@ -77,7 +76,7 @@ UNSET = object() def update_settings(**kwds): """helper to update django settings from kwds""" - for k,v in iteritems(kwds): + for k,v in kwds.items(): if v is UNSET: if hasattr(settings, k): delattr(settings, k) @@ -347,7 +346,7 @@ class _ExtensionTest(TestCase, _ExtensionSupport): #============================================================================= def setUp(self): - super(_ExtensionTest, self).setUp() + super().setUp() self.require_TEST_MODE("default") @@ -844,7 +843,7 @@ class ExtensionBehaviorTest(DjangoBehaviorTest): ) def setUp(self): - super(ExtensionBehaviorTest, self).setUp() + super().setUp() # always load extension before each test self.load_extension(PASSLIB_CONFIG=self.config) @@ -875,9 +874,9 @@ class DjangoExtensionTest(_ExtensionTest): self.load_extension(PASSLIB_CONFIG="disabled", check=False) self.assert_unpatched() - # check legacy config=None - with self.assertWarningList("PASSLIB_CONFIG=None is deprecated"): - self.load_extension(PASSLIB_CONFIG=None, check=False) + # check onfig=None is rejected + self.assertRaises(TypeError, self.load_extension, PASSLIB_CONFIG=None, + check=False) self.assert_unpatched() # try stock django 1.0 context @@ -960,9 +959,9 @@ class DjangoExtensionTest(_ExtensionTest): "v2RWkZQzctPdejyRqmmTDQpZN6wTh7.RUy9zF2LftT6") self.assertEqual(hasher.safe_summary(encoded), {'algorithm': 'sha256_crypt', - 'salt': u('abcdab**********'), + 'salt': u'abcdab**********', 'rounds': 1234, - 'hash': u('v2RWkZ*************************************'), + 'hash': u'v2RWkZ*************************************', }) # made up name should throw error @@ -974,9 +973,9 @@ class DjangoExtensionTest(_ExtensionTest): #=================================================================== def test_11_config_disabled(self): """test PASSLIB_CONFIG='disabled'""" - # test config=None (deprecated) - with self.assertWarningList("PASSLIB_CONFIG=None is deprecated"): - self.load_extension(PASSLIB_CONFIG=None, check=False) + # test config=None is rejected + self.assertRaises(TypeError, self.load_extension, PASSLIB_CONFIG=None, + check=False) self.assert_unpatched() # test disabled config diff --git a/passlib/tests/test_ext_django_source.py b/passlib/tests/test_ext_django_source.py index 4b42e59..a6da6b6 100644 --- a/passlib/tests/test_ext_django_source.py +++ b/passlib/tests/test_ext_django_source.py @@ -4,12 +4,10 @@ test passlib.ext.django against django source tests #============================================================================= # imports #============================================================================= -from __future__ import absolute_import, division, print_function # core import logging; log = logging.getLogger(__name__) # site # pkg -from passlib.utils.compat import suppress_cause from passlib.ext.django.utils import DJANGO_VERSION, DjangoTranslator, _PasslibHasherWrapper # tests from passlib.tests.utils import TestCase, TEST_MODE @@ -60,10 +58,8 @@ elif has_min_django: try: from auth_tests import test_hashers as test_hashers_mod except ImportError as err: - raise suppress_cause( - EnvironmentError("error trying to import django tests " - "from source path (%r): %r" % - (source_path, err))) + raise EnvironmentError("error trying to import django tests " + "from source path (%r): %r" % (source_path, err)) from None finally: sys.path.remove(tests_path) @@ -89,7 +85,6 @@ if test_hashers_mod: from django.core.signals import setting_changed from django.dispatch import receiver from django.utils.module_loading import import_string - from passlib.utils.compat import get_unbound_method_function class HashersTest(test_hashers_mod.TestUtilsHashPass, _ExtensionSupport): """ @@ -102,7 +97,7 @@ if test_hashers_mod: #================================================================== # port patchAttr() helper method from passlib.tests.utils.TestCase - patchAttr = get_unbound_method_function(TestCase.patchAttr) + patchAttr = TestCase.patchAttr #================================================================== # custom setup @@ -212,7 +207,7 @@ if test_hashers_mod: def tearDown(self): # NOTE: could rely on addCleanup() instead, but need py26 compat self.unload_extension() - super(HashersTest, self).tearDown() + super().tearDown() #================================================================== # skip a few methods that can't be replicated properly diff --git a/passlib/tests/test_handlers.py b/passlib/tests/test_handlers.py index cad5ef9..e3a3e30 100644 --- a/passlib/tests/test_handlers.py +++ b/passlib/tests/test_handlers.py @@ -2,18 +2,15 @@ #============================================================================= # imports #============================================================================= -from __future__ import with_statement # core -import logging; log = logging.getLogger(__name__) -import os +import logging +log = logging.getLogger(__name__) import sys import warnings # site # pkg from passlib import exc, hash -from passlib.utils import repeat_string -from passlib.utils.compat import irange, PY3, u, get_method_function -from passlib.tests.utils import TestCase, HandlerCase, skipUnless, \ +from passlib.tests.utils import TestCase, HandlerCase, \ TEST_MODE, UserHandlerMixin, EncodingHandlerMixin # module @@ -22,9 +19,9 @@ from passlib.tests.utils import TestCase, HandlerCase, skipUnless, \ #============================================================================= # some common unicode passwords which used as test cases -UPASS_WAV = u('\u0399\u03c9\u03b1\u03bd\u03bd\u03b7\u03c2') -UPASS_USD = u("\u20AC\u00A5$") -UPASS_TABLE = u("t\u00e1\u0411\u2113\u0259") +UPASS_WAV = u'\u0399\u03c9\u03b1\u03bd\u03bd\u03b7\u03c2' +UPASS_USD = u"\u20AC\u00A5$" +UPASS_TABLE = u"t\u00e1\u0411\u2113\u0259" PASS_TABLE_UTF8 = b't\xc3\xa1\xd0\x91\xe2\x84\x93\xc9\x99' # utf-8 @@ -150,7 +147,7 @@ class bigcrypt_test(HandlerCase): # check that _norm_checksum() also validates checksum size. # (current code uses regex in parser) self.assertRaises(ValueError, hash.bigcrypt, use_defaults=True, - checksum=u('yh4XPJGsOZ')) + checksum=u'yh4XPJGsOZ') #============================================================================= # bsdi crypt @@ -208,7 +205,7 @@ class _bsdi_crypt_test(HandlerCase): def test_77_fuzz_input(self, **kwds): # we want to generate even rounds to verify it's correct, but want to ignore warnings warnings.filterwarnings("ignore", "bsdi_crypt rounds should be odd.*") - super(_bsdi_crypt_test, self).test_77_fuzz_input(**kwds) + super().test_77_fuzz_input(**kwds) def test_needs_update_w_even_rounds(self): """needs_update() should flag even rounds""" @@ -289,7 +286,7 @@ class _des_crypt_test(HandlerCase): ('AlOtBsOl', 'cEpWz5IUCShqM'), # ensures utf-8 used for unicode - (u('hell\u00D6'), 'saykDgk3BPZ9E'), + (u'hell\u00D6', 'saykDgk3BPZ9E'), ] known_unidentified_hashes = [ # bad char in otherwise correctly formatted hash @@ -379,11 +376,11 @@ class fshp_test(HandlerCase): handler(variant=1, **kwds) # accepts bytes or unicode - handler(variant=u('1'), **kwds) + handler(variant=u'1', **kwds) handler(variant=b'1', **kwds) # aliases - handler(variant=u('sha256'), **kwds) + handler(variant=u'sha256', **kwds) handler(variant=b'sha256', **kwds) # rejects None @@ -585,7 +582,7 @@ class ldap_salted_sha256_test(HandlerCase): ("password", '{SSHA256}x1tymSTVjozxQ2PtT46ysrzhZxbcskK0o2f8hEFx7fAQQmhtDSEkJA=='), ("test", '{SSHA256}xfqc9aOR6z15YaEk3/Ufd7UL9+JozB/1EPmCDTizL0GkdA7BuNda6w=='), ("toomanysecrets", '{SSHA256}RrTKrg6HFXcjJ+eDAq4UtbODxOr9RLeG+I69FoJvutcbY0zpfU+p1Q=='), - (u('letm\xe8\xefn'), '{SSHA256}km7UjUTBZN8a+gf1ND2/qn15N7LsO/jmGYJXvyTfJKAbI0RoLWWslQ=='), + (u'letm\xe8\xefn', '{SSHA256}km7UjUTBZN8a+gf1ND2/qn15N7LsO/jmGYJXvyTfJKAbI0RoLWWslQ=='), # alternate salt sizes (4, 15, 16) # generated locally @@ -612,7 +609,7 @@ class ldap_salted_sha512_test(HandlerCase): # generated by testing ldap server web interface (see issue 124 comments) # salt size = 8 ("toomanysecrets", '{SSHA512}wExp4xjiCHS0zidJDC4UJq9EEeIebAQPJ1PWSwfhxWjfutI9XiiKuHm2AE41cEFfK+8HyI8bh+ztbczUGsvVFIgICWWPt7qu'), - (u('letm\xe8\xefn'), '{SSHA512}mpNUSmZc3TNx+RnPwkIAVMf7ocEKLPrIoQNsg4Eu8dHvyCeb2xzHp5A6n4tF7ntknSvfvRZaJII4ImvNJlYsgiwAm0FMqR+3'), + (u'letm\xe8\xefn', '{SSHA512}mpNUSmZc3TNx+RnPwkIAVMf7ocEKLPrIoQNsg4Eu8dHvyCeb2xzHp5A6n4tF7ntknSvfvRZaJII4ImvNJlYsgiwAm0FMqR+3'), # generated locally # salt size = 8 @@ -642,8 +639,8 @@ class ldap_plaintext_test(HandlerCase): handler = hash.ldap_plaintext known_correct_hashes = [ ("password", 'password'), - (UPASS_TABLE, UPASS_TABLE if PY3 else PASS_TABLE_UTF8), - (PASS_TABLE_UTF8, UPASS_TABLE if PY3 else PASS_TABLE_UTF8), + (UPASS_TABLE, UPASS_TABLE), + (PASS_TABLE_UTF8, UPASS_TABLE), ] known_unidentified_hashes = [ "{FOO}bar", @@ -706,7 +703,7 @@ class _ldap_sha1_crypt_test(HandlerCase): def populate_settings(self, kwds): kwds.setdefault("rounds", 10) - super(_ldap_sha1_crypt_test, self).populate_settings(kwds) + super().populate_settings(kwds) def test_77_fuzz_input(self, **ignored): raise self.skipTest("unneeded") @@ -738,14 +735,14 @@ class lmhash_test(EncodingHandlerMixin, HandlerCase): ('Yokohama', '5ecd9236d21095ce7584248b8d2c9f9e'), # ensures cp437 used for unicode - (u('ENCYCLOP\xC6DIA'), 'fed6416bffc9750d48462b9d7aaac065'), - (u('encyclop\xE6dia'), 'fed6416bffc9750d48462b9d7aaac065'), + (u'ENCYCLOP\xC6DIA', 'fed6416bffc9750d48462b9d7aaac065'), + (u'encyclop\xE6dia', 'fed6416bffc9750d48462b9d7aaac065'), # test various encoding values - ((u("\xC6"), None), '25d8ab4a0659c97aaad3b435b51404ee'), - ((u("\xC6"), "cp437"), '25d8ab4a0659c97aaad3b435b51404ee'), - ((u("\xC6"), "latin-1"), '184eecbbe9991b44aad3b435b51404ee'), - ((u("\xC6"), "utf-8"), '00dd240fcfab20b8aad3b435b51404ee'), + ((u"\xC6", None), '25d8ab4a0659c97aaad3b435b51404ee'), + ((u"\xC6", "cp437"), '25d8ab4a0659c97aaad3b435b51404ee'), + ((u"\xC6", "latin-1"), '184eecbbe9991b44aad3b435b51404ee'), + ((u"\xC6", "utf-8"), '00dd240fcfab20b8aad3b435b51404ee'), ] known_unidentified_hashes = [ @@ -795,7 +792,7 @@ class _md5_crypt_test(HandlerCase): ('4lpHa N|_|M3r1K W/ Cur5Es: #$%(*)(*%#', '$1$jQS7o98J$V6iTcr71CGgwW2laf17pi1'), ('test', '$1$SuMrG47N$ymvzYjr7QcEQjaK5m1PGx1'), (b'test', '$1$SuMrG47N$ymvzYjr7QcEQjaK5m1PGx1'), - (u('s'), '$1$ssssssss$YgmLTApYTv12qgTwBoj8i/'), + (u's', '$1$ssssssss$YgmLTApYTv12qgTwBoj8i/'), # ensures utf-8 used for unicode (UPASS_TABLE, '$1$d6/Ky1lU$/xpf8m7ftmWLF.TjHCqel0'), @@ -866,9 +863,9 @@ class msdcc_test(UserHandlerMixin, HandlerCase): (("", "root"), "176a4c2bd45ac73687676c2f09045353"), (("test1", "TEST1"), "64cd29e36a8431a2b111378564a10631"), (("okolada", "nineteen_characters"), "290efa10307e36a79b3eebf2a6b29455"), - ((u("\u00FC"), u("\u00FC")), "48f84e6f73d6d5305f6558a33fa2c9bb"), - ((u("\u00FC\u00FC"), u("\u00FC\u00FC")), "593246a8335cf0261799bda2a2a9c623"), - ((u("\u20AC\u20AC"), "user"), "9121790702dda0fa5d353014c334c2ce"), + ((u"\u00FC", u"\u00FC"), "48f84e6f73d6d5305f6558a33fa2c9bb"), + ((u"\u00FC\u00FC", u"\u00FC\u00FC"), "593246a8335cf0261799bda2a2a9c623"), + ((u"\u20AC\u20AC", "user"), "9121790702dda0fa5d353014c334c2ce"), # # custom @@ -904,9 +901,9 @@ class msdcc2_test(UserHandlerMixin, HandlerCase): (("test2", "TEST2"), "c6758e5be7fc943d00b97972a8a97620"), (("test3", "test3"), "360e51304a2d383ea33467ab0b639cc4"), (("test4", "test4"), "6f79ee93518306f071c47185998566ae"), - ((u("\u00FC"), "joe"), "bdb80f2c4656a8b8591bd27d39064a54"), - ((u("\u20AC\u20AC"), "joe"), "1e1e20f482ff748038e47d801d0d1bda"), - ((u("\u00FC\u00FC"), "admin"), "0839e4a07c00f18a8c65cf5b985b9e73"), + ((u"\u00FC", "joe"), "bdb80f2c4656a8b8591bd27d39064a54"), + ((u"\u20AC\u20AC", "joe"), "1e1e20f482ff748038e47d801d0d1bda"), + ((u"\u00FC\u00FC", "admin"), "0839e4a07c00f18a8c65cf5b985b9e73"), # # custom @@ -999,7 +996,7 @@ class mssql2000_test(HandlerCase): known_malformed_hashes = [ # non-hex char -----\/ b'0x01005B200543327G2E1BC2E7C5DF0F9EBFE486E9BEE063E8D3B332752E1BC2E7C5DF0F9EBFE486E9BEE063E8D3B3', - u('0x01005B200543327G2E1BC2E7C5DF0F9EBFE486E9BEE063E8D3B332752E1BC2E7C5DF0F9EBFE486E9BEE063E8D3B3'), + u'0x01005B200543327G2E1BC2E7C5DF0F9EBFE486E9BEE063E8D3B332752E1BC2E7C5DF0F9EBFE486E9BEE063E8D3B3', ] class mssql2005_test(HandlerCase): @@ -1160,8 +1157,8 @@ class nthash_test(HandlerCase): # # http://msdn.microsoft.com/en-us/library/cc245828(v=prot.10).aspx # - ("OLDPASSWORD", u("6677b2c394311355b54f25eec5bfacf5")), - ("NEWPASSWORD", u("256781a62031289d3c2c98c14f1efc8c")), + ("OLDPASSWORD", u"6677b2c394311355b54f25eec5bfacf5"), + ("NEWPASSWORD", u"256781a62031289d3c2c98c14f1efc8c"), # # from JTR 1.7.9 @@ -1217,7 +1214,7 @@ class oracle10_test(UserHandlerMixin, HandlerCase): # http://www.petefinnigan.com/default/default_password_list.htm # (('tiger', 'scott'), 'F894844C34402B67'), - ((u('ttTiGGeR'), u('ScO')), '7AA1A84E31ED7771'), + ((u'ttTiGGeR', u'ScO'), '7AA1A84E31ED7771'), (("d_syspw", "SYSTEM"), '1B9F1F9A5CB9EB31'), (("strat_passwd", "strat_user"), 'AEBEDBB4EFB5225B'), @@ -1322,8 +1319,8 @@ class plaintext_test(HandlerCase): ('password', 'password'), # ensure unicode uses utf-8 - (UPASS_TABLE, UPASS_TABLE if PY3 else PASS_TABLE_UTF8), - (PASS_TABLE_UTF8, UPASS_TABLE if PY3 else PASS_TABLE_UTF8), + (UPASS_TABLE, UPASS_TABLE), + (PASS_TABLE_UTF8, UPASS_TABLE), ] #============================================================================= @@ -1456,7 +1453,7 @@ class _sha256_crypt_test(HandlerCase): ('test', '$5$rounds=11858$WH1ABM5sKhxbkgCK$aTQsjPkz0rBsH3lQlJxw9HDTDXPKBxC0LlVeV69P.t1'), ('Compl3X AlphaNu3meric', '$5$rounds=10350$o.pwkySLCzwTdmQX$nCMVsnF3TXWcBPOympBUUSQi6LGGloZoOsVJMGJ09UB'), ('4lpHa N|_|M3r1K W/ Cur5Es: #$%(*)(*%#', '$5$rounds=11944$9dhlu07dQMRWvTId$LyUI5VWkGFwASlzntk1RLurxX54LUhgAcJZIt0pYGT7'), - (u('with unic\u00D6de'), '$5$rounds=1000$IbG0EuGQXw5EkMdP$LQ5AfPf13KufFsKtmazqnzSGZ4pxtUNw3woQ.ELRDF4'), + (u'with unic\u00D6de', '$5$rounds=1000$IbG0EuGQXw5EkMdP$LQ5AfPf13KufFsKtmazqnzSGZ4pxtUNw3woQ.ELRDF4'), ] if TEST_MODE("full"): @@ -1754,7 +1751,7 @@ class unix_disabled_test(HandlerCase): def test_76_hash_border(self): # so empty strings pass self.accepts_all_hashes = True - super(unix_disabled_test, self).test_76_hash_border() + super().test_76_hash_border() def test_90_special(self): """test marker option & special behavior""" @@ -1779,41 +1776,6 @@ class unix_disabled_test(HandlerCase): self.assertRaises(ValueError, handler.hash, 'stub', marker='abc') self.assertRaises(ValueError, handler.using, marker='abc') -class unix_fallback_test(HandlerCase): - handler = hash.unix_fallback - accepts_all_hashes = True - - known_correct_hashes = [ - # *everything* should hash to "!", and nothing should verify - ("password", "!"), - (UPASS_TABLE, "!"), - ] - - # silence annoying deprecation warning - def setUp(self): - super(unix_fallback_test, self).setUp() - warnings.filterwarnings("ignore", "'unix_fallback' is deprecated") - - def test_90_wildcard(self): - """test enable_wildcard flag""" - h = self.handler - self.assertTrue(h.verify('password','', enable_wildcard=True)) - self.assertFalse(h.verify('password','')) - for c in "!*x": - self.assertFalse(h.verify('password',c, enable_wildcard=True)) - self.assertFalse(h.verify('password',c)) - - def test_91_preserves_existing(self): - """test preserves existing disabled hash""" - handler = self.handler - - # use marker if no hash - self.assertEqual(handler.genhash("stub", ""), "!") - self.assertEqual(handler.hash("stub"), "!") - - # use hash if provided and valid - self.assertEqual(handler.genhash("stub", "!asd"), "!asd") - #============================================================================= # eof #============================================================================= diff --git a/passlib/tests/test_handlers_argon2.py b/passlib/tests/test_handlers_argon2.py index e771769..3f800ba 100644 --- a/passlib/tests/test_handlers_argon2.py +++ b/passlib/tests/test_handlers_argon2.py @@ -10,7 +10,6 @@ import warnings # site # pkg from passlib import hash -from passlib.utils.compat import unicode from passlib.tests.utils import HandlerCase, TEST_MODE from passlib.tests.test_handlers import UPASS_TABLE, PASS_TABLE_UTF8 # module @@ -200,7 +199,7 @@ class _base_argon2_test(HandlerCase): ] def setUpWarnings(self): - super(_base_argon2_test, self).setUpWarnings() + super().setUpWarnings() warnings.filterwarnings("ignore", ".*Using argon2pure backend.*") def do_stub_encrypt(self, handler=None, **settings): @@ -213,7 +212,7 @@ class _base_argon2_test(HandlerCase): assert self.checksum return self.to_string() else: - return super(_base_argon2_test, self).do_stub_encrypt(handler, **settings) + return super().do_stub_encrypt(handler, **settings) def test_03_legacy_hash_workflow(self): # override base method @@ -303,7 +302,7 @@ class _base_argon2_test(HandlerCase): # check supported type_values for value in cls.type_values: - self.assertIsInstance(value, unicode) + self.assertIsInstance(value, str) self.assertTrue("i" in cls.type_values) self.assertTrue("d" in cls.type_values) diff --git a/passlib/tests/test_handlers_bcrypt.py b/passlib/tests/test_handlers_bcrypt.py index 64fc8bf..abe44ec 100644 --- a/passlib/tests/test_handlers_bcrypt.py +++ b/passlib/tests/test_handlers_bcrypt.py @@ -2,7 +2,6 @@ #============================================================================= # imports #============================================================================= -from __future__ import with_statement # core import logging; log = logging.getLogger(__name__) import os @@ -12,7 +11,6 @@ import warnings from passlib import hash from passlib.handlers.bcrypt import IDENT_2, IDENT_2X from passlib.utils import repeat_string, to_bytes, is_safe_crypt_input -from passlib.utils.compat import irange, PY3 from passlib.tests.utils import HandlerCase, TEST_MODE from passlib.tests.test_handlers import UPASS_TABLE # module @@ -179,7 +177,7 @@ class _bcrypt_test(HandlerCase): self.addCleanup(os.environ.__delitem__, key) os.environ[key] = "true" - super(_bcrypt_test, self).setUp() + super().setUp() # silence this warning, will come up a bunch during testing of old 2a hashes. warnings.filterwarnings("ignore", ".*backend is vulnerable to the bsd wraparound bug.*") @@ -188,7 +186,7 @@ class _bcrypt_test(HandlerCase): # builtin is still just way too slow. if self.backend == "builtin": kwds.setdefault("rounds", 4) - super(_bcrypt_test, self).populate_settings(kwds) + super().populate_settings(kwds) #=================================================================== # fuzz testing @@ -202,8 +200,6 @@ class _bcrypt_test(HandlerCase): fuzz_verifiers = HandlerCase.fuzz_verifiers + ( "fuzz_verifier_bcrypt", - "fuzz_verifier_pybcrypt", - "fuzz_verifier_bcryptor", ) def fuzz_verifier_bcrypt(self): @@ -238,61 +234,6 @@ class _bcrypt_test(HandlerCase): raise ValueError("bcrypt rejected hash: %r (secret=%r)" % (hash, secret)) return check_bcrypt - def fuzz_verifier_pybcrypt(self): - # test against py-bcrypt, if available - from passlib.handlers.bcrypt import ( - IDENT_2, IDENT_2A, IDENT_2B, IDENT_2X, IDENT_2Y, - _PyBcryptBackend, - ) - from passlib.utils import to_native_str - - loaded = _PyBcryptBackend._load_backend_mixin("pybcrypt", False) - if not loaded: - return - - from passlib.handlers.bcrypt import _pybcrypt as bcrypt_mod - - lock = _PyBcryptBackend._calc_lock # reuse threadlock workaround for pybcrypt 0.2 - - def check_pybcrypt(secret, hash): - """pybcrypt""" - secret = to_native_str(secret, self.FuzzHashGenerator.password_encoding) - if len(secret) > 200: # vulnerable to wraparound bug - secret = secret[:200] - if hash.startswith((IDENT_2B, IDENT_2Y)): - hash = IDENT_2A + hash[4:] - try: - if lock: - with lock: - return bcrypt_mod.hashpw(secret, hash) == hash - else: - return bcrypt_mod.hashpw(secret, hash) == hash - except ValueError: - raise ValueError("py-bcrypt rejected hash: %r" % (hash,)) - return check_pybcrypt - - def fuzz_verifier_bcryptor(self): - # test against bcryptor if available - from passlib.handlers.bcrypt import IDENT_2, IDENT_2A, IDENT_2Y, IDENT_2B - from passlib.utils import to_native_str - try: - from bcryptor.engine import Engine - except ImportError: - return - def check_bcryptor(secret, hash): - """bcryptor""" - secret = to_native_str(secret, self.FuzzHashGenerator.password_encoding) - if hash.startswith((IDENT_2B, IDENT_2Y)): - hash = IDENT_2A + hash[4:] - elif hash.startswith(IDENT_2): - # bcryptor doesn't support $2$ hashes; but we can fake it - # using the $2a$ algorithm, by repeating the password until - # it's 72 chars in length. - hash = IDENT_2A + hash[3:] - if secret: - secret = repeat_string(secret, 72) - return Engine(False).hash_key(secret, hash) == hash - return check_bcryptor class FuzzHashGenerator(HandlerCase.FuzzHashGenerator): @@ -366,9 +307,9 @@ class _bcrypt_test(HandlerCase): "unexpectedly malformed hash: %r" % (hash,) self.assertTrue(hash[28] in '.Oeu', "unused bits incorrectly set in hash: %r" % (hash,)) - for i in irange(6): + for i in range(6): check_padding(bcrypt.genconfig()) - for i in irange(3): + for i in range(3): check_padding(bcrypt.using(rounds=bcrypt.min_rounds).hash("bob")) # @@ -425,8 +366,7 @@ class _bcrypt_test(HandlerCase): # create test cases for specific backends bcrypt_bcrypt_test = _bcrypt_test.create_backend_case("bcrypt") -bcrypt_pybcrypt_test = _bcrypt_test.create_backend_case("pybcrypt") -bcrypt_bcryptor_test = _bcrypt_test.create_backend_case("bcryptor") + class bcrypt_os_crypt_test(_bcrypt_test.create_backend_case("os_crypt")): @@ -583,14 +523,14 @@ class _bcrypt_sha256_test(HandlerCase): else: self.addCleanup(os.environ.__delitem__, key) os.environ[key] = "enabled" - super(_bcrypt_sha256_test, self).setUp() + super().setUp() warnings.filterwarnings("ignore", ".*backend is vulnerable to the bsd wraparound bug.*") def populate_settings(self, kwds): # builtin is still just way too slow. if self.backend == "builtin": kwds.setdefault("rounds", 4) - super(_bcrypt_sha256_test, self).populate_settings(kwds) + super().populate_settings(kwds) #=================================================================== # override ident tests for now @@ -670,8 +610,7 @@ class _bcrypt_sha256_test(HandlerCase): # create test cases for specific backends bcrypt_sha256_bcrypt_test = _bcrypt_sha256_test.create_backend_case("bcrypt") -bcrypt_sha256_pybcrypt_test = _bcrypt_sha256_test.create_backend_case("pybcrypt") -bcrypt_sha256_bcryptor_test = _bcrypt_sha256_test.create_backend_case("bcryptor") + class bcrypt_sha256_os_crypt_test(_bcrypt_sha256_test.create_backend_case("os_crypt")): diff --git a/passlib/tests/test_handlers_cisco.py b/passlib/tests/test_handlers_cisco.py index ea6594b..bc23c52 100644 --- a/passlib/tests/test_handlers_cisco.py +++ b/passlib/tests/test_handlers_cisco.py @@ -4,14 +4,12 @@ passlib.tests.test_handlers_cisco - tests for Cisco-specific algorithms #============================================================================= # imports #============================================================================= -from __future__ import absolute_import, division, print_function # core import logging log = logging.getLogger(__name__) # site # pkg from passlib import hash, exc -from passlib.utils.compat import u from .utils import UserHandlerMixin, HandlerCase, repeat_string from .test_handlers import UPASS_TABLE # module @@ -151,8 +149,8 @@ class _PixAsaSharedTest(UserHandlerMixin, HandlerCase): # observed behaviors include: # * ssh cli stripping non-ascii chars entirely # * ASDM web iface double-encoding utf-8 strings - ((u("t\xe1ble").encode("utf-8"), 'user'), 'Og8fB4NyF0m5Ed9c'), - ((u("t\xe1ble").encode("utf-8").decode("latin-1").encode("utf-8"), + ((u"t\xe1ble".encode("utf-8"), 'user'), 'Og8fB4NyF0m5Ed9c'), + ((u"t\xe1ble".encode("utf-8").decode("latin-1").encode("utf-8"), 'user'), 'cMvFC2XVBmK/68yB'), # confirmed ASA 9.6 when typed into ASDM ] diff --git a/passlib/tests/test_handlers_django.py b/passlib/tests/test_handlers_django.py index f7c9a0d..9d03a98 100644 --- a/passlib/tests/test_handlers_django.py +++ b/passlib/tests/test_handlers_django.py @@ -2,17 +2,16 @@ #============================================================================= # imports #============================================================================= -from __future__ import with_statement # core import logging; log = logging.getLogger(__name__) import re +from unittest import skipUnless, SkipTest import warnings # site # pkg from passlib import hash from passlib.utils import repeat_string -from passlib.utils.compat import u -from passlib.tests.utils import TestCase, HandlerCase, skipUnless, SkipTest +from passlib.tests.utils import TestCase, HandlerCase from passlib.tests.test_handlers import UPASS_USD, UPASS_TABLE from passlib.tests.test_ext_django import DJANGO_VERSION, MIN_DJANGO_VERSION, \ check_django_hasher_has_backend @@ -23,7 +22,7 @@ from passlib.tests.test_ext_django import DJANGO_VERSION, MIN_DJANGO_VERSION, \ #============================================================================= # standard string django uses -UPASS_LETMEIN = u('l\xe8tmein') +UPASS_LETMEIN = u'l\xe8tmein' def vstr(version): return ".".join(str(e) for e in version) @@ -146,7 +145,7 @@ class django_des_crypt_test(HandlerCase, _DjangoHelper): # ensures utf-8 used for unicode (UPASS_USD, 'crypt$c2e86$c2hN1Bxd6ZiWs'), (UPASS_TABLE, 'crypt$0.aQs$0.wB.TT0Czvlo'), - (u("hell\u00D6"), "crypt$sa$saykDgk3BPZ9E"), + (u"hell\u00D6", "crypt$sa$saykDgk3BPZ9E"), # prevent regression of issue 22 ("foo", 'crypt$MNVY.9ajgdvDQ$MNVY.9ajgdvDQ'), @@ -298,7 +297,7 @@ class django_bcrypt_test(HandlerCase, _DjangoHelper): def populate_settings(self, kwds): # speed up test w/ lower rounds kwds.setdefault("rounds", 4) - super(django_bcrypt_test, self).populate_settings(kwds) + super().populate_settings(kwds) class FuzzHashGenerator(HandlerCase.FuzzHashGenerator): @@ -348,7 +347,7 @@ class django_bcrypt_sha256_test(HandlerCase, _DjangoHelper): def populate_settings(self, kwds): # speed up test w/ lower rounds kwds.setdefault("rounds", 4) - super(django_bcrypt_sha256_test, self).populate_settings(kwds) + super().populate_settings(kwds) class FuzzHashGenerator(HandlerCase.FuzzHashGenerator): @@ -382,7 +381,7 @@ class django_argon2_test(HandlerCase, _DjangoHelper): ] def setUpWarnings(self): - super(django_argon2_test, self).setUpWarnings() + super().setUpWarnings() warnings.filterwarnings("ignore", ".*Using argon2pure backend.*") def do_stub_encrypt(self, handler=None, **settings): diff --git a/passlib/tests/test_handlers_pbkdf2.py b/passlib/tests/test_handlers_pbkdf2.py index 4d2f048..658f2ce 100644 --- a/passlib/tests/test_handlers_pbkdf2.py +++ b/passlib/tests/test_handlers_pbkdf2.py @@ -9,7 +9,6 @@ import warnings # site # pkg from passlib import hash -from passlib.utils.compat import u from passlib.tests.utils import TestCase, HandlerCase from passlib.tests.test_handlers import UPASS_WAV # module @@ -123,7 +122,7 @@ class cta_pbkdf2_sha1_test(HandlerCase): # # test vectors from original implementation # - (u("hashy the \N{SNOWMAN}"), '$p5k2$1000$ZxK4ZBJCfQg=$jJZVscWtO--p1-xIZl6jhO2LKR0='), + (u"hashy the \N{SNOWMAN}", '$p5k2$1000$ZxK4ZBJCfQg=$jJZVscWtO--p1-xIZl6jhO2LKR0='), # # custom @@ -201,11 +200,11 @@ class scram_test(HandlerCase): # test unicode passwords & saslprep (all the passwords below # should normalize to the same value: 'IX \xE0') - (u('IX \xE0'), '$scram$6400$0BojBCBE6P2/N4bQ$' + (u'IX \xE0', '$scram$6400$0BojBCBE6P2/N4bQ$' 'sha-1=YniLes.b8WFMvBhtSACZyyvxeCc'), - (u('\u2168\u3000a\u0300'), '$scram$6400$0BojBCBE6P2/N4bQ$' + (u'\u2168\u3000a\u0300', '$scram$6400$0BojBCBE6P2/N4bQ$' 'sha-1=YniLes.b8WFMvBhtSACZyyvxeCc'), - (u('\u00ADIX \xE0'), '$scram$6400$0BojBCBE6P2/N4bQ$' + (u'\u00ADIX \xE0', '$scram$6400$0BojBCBE6P2/N4bQ$' 'sha-1=YniLes.b8WFMvBhtSACZyyvxeCc'), ] @@ -245,7 +244,7 @@ class scram_test(HandlerCase): ] def setUp(self): - super(scram_test, self).setUp() + super().setUp() # some platforms lack stringprep (e.g. Jython, IronPython) self.require_stringprep() @@ -287,7 +286,7 @@ class scram_test(HandlerCase): """test internal parsing of 'checksum' keyword""" # check non-bytes checksum values are rejected self.assertRaises(TypeError, self.handler, use_defaults=True, - checksum={'sha-1': u('X')*20}) + checksum={'sha-1': u'X'*20}) # check sha-1 is required self.assertRaises(ValueError, self.handler, use_defaults=True, @@ -340,9 +339,9 @@ class scram_test(HandlerCase): # check various encodings of password work. s1 = b'\x01\x02\x03' d1 = b'\xb2\xfb\xab\x82[tNuPnI\x8aZZ\x19\x87\xcen\xe9\xd3' - self.assertEqual(hash(u("\u2168"), s1, 1000, 'sha-1'), d1) + self.assertEqual(hash(u"\u2168", s1, 1000, 'sha-1'), d1) self.assertEqual(hash(b"\xe2\x85\xa8", s1, 1000, 'SHA-1'), d1) - self.assertEqual(hash(u("IX"), s1, 1000, 'sha1'), d1) + self.assertEqual(hash(u"IX", s1, 1000, 'sha1'), d1) self.assertEqual(hash(b"IX", s1, 1000, 'SHA1'), d1) # check algs @@ -354,7 +353,7 @@ class scram_test(HandlerCase): self.assertRaises(ValueError, hash, "IX", s1, 0, 'sha-1') # unicode salts accepted as of passlib 1.7 (previous caused TypeError) - self.assertEqual(hash(u("IX"), s1.decode("latin-1"), 1000, 'sha1'), d1) + self.assertEqual(hash(u"IX", s1.decode("latin-1"), 1000, 'sha1'), d1) def test_94_saslprep(self): """test hash/verify use saslprep""" @@ -363,18 +362,18 @@ class scram_test(HandlerCase): # to verify full normalization behavior. # hash unnormalized - h = self.do_encrypt(u("I\u00ADX")) - self.assertTrue(self.do_verify(u("IX"), h)) - self.assertTrue(self.do_verify(u("\u2168"), h)) + h = self.do_encrypt(u"I\u00ADX") + self.assertTrue(self.do_verify(u"IX", h)) + self.assertTrue(self.do_verify(u"\u2168", h)) # hash normalized - h = self.do_encrypt(u("\xF3")) - self.assertTrue(self.do_verify(u("o\u0301"), h)) - self.assertTrue(self.do_verify(u("\u200Do\u0301"), h)) + h = self.do_encrypt(u"\xF3") + self.assertTrue(self.do_verify(u"o\u0301", h)) + self.assertTrue(self.do_verify(u"\u200Do\u0301", h)) # throws error if forbidden char provided - self.assertRaises(ValueError, self.do_encrypt, u("\uFDD0")) - self.assertRaises(ValueError, self.do_verify, u("\uFDD0"), h) + self.assertRaises(ValueError, self.do_encrypt, u"\uFDD0") + self.assertRaises(ValueError, self.do_verify, u"\uFDD0", h) def test_94_using_w_default_algs(self, param="default_algs"): """using() -- 'default_algs' parameter""" diff --git a/passlib/tests/test_handlers_scrypt.py b/passlib/tests/test_handlers_scrypt.py index 5ab6d9f..2ce6463 100644 --- a/passlib/tests/test_handlers_scrypt.py +++ b/passlib/tests/test_handlers_scrypt.py @@ -86,14 +86,14 @@ class _scrypt_test(HandlerCase): ] def setUpWarnings(self): - super(_scrypt_test, self).setUpWarnings() + super().setUpWarnings() warnings.filterwarnings("ignore", ".*using builtin scrypt backend.*") def populate_settings(self, kwds): # builtin is still just way too slow. if self.backend == "builtin": kwds.setdefault("rounds", 6) - super(_scrypt_test, self).populate_settings(kwds) + super().populate_settings(kwds) class FuzzHashGenerator(HandlerCase.FuzzHashGenerator): diff --git a/passlib/tests/test_hosts.py b/passlib/tests/test_hosts.py index cbf93ab..b8e6e5e 100644 --- a/passlib/tests/test_hosts.py +++ b/passlib/tests/test_hosts.py @@ -2,7 +2,6 @@ #============================================================================= # imports #============================================================================= -from __future__ import with_statement # core import logging; log = logging.getLogger(__name__) # site diff --git a/passlib/tests/test_pwd.py b/passlib/tests/test_pwd.py index 2c983cd..cc7bad3 100644 --- a/passlib/tests/test_pwd.py +++ b/passlib/tests/test_pwd.py @@ -66,7 +66,7 @@ class WordGeneratorTest(TestCase): descriptionPrefix = "passlib.pwd.genword()" def setUp(self): - super(WordGeneratorTest, self).setUp() + super().setUp() # patch some RNG references so they're reproducible. from passlib.pwd import SequenceGenerator diff --git a/passlib/tests/test_registry.py b/passlib/tests/test_registry.py index 8cec48d..09d8dfd 100644 --- a/passlib/tests/test_registry.py +++ b/passlib/tests/test_registry.py @@ -2,7 +2,6 @@ #============================================================================= # imports #============================================================================= -from __future__ import with_statement # core from logging import getLogger import warnings @@ -40,7 +39,7 @@ class RegistryTest(TestCase): descriptionPrefix = "passlib.registry" def setUp(self): - super(RegistryTest, self).setUp() + super().setUp() # backup registry state & restore it after test. locations = dict(registry._locations) diff --git a/passlib/tests/test_totp.py b/passlib/tests/test_totp.py index 604d2e9..e9c6dd9 100644 --- a/passlib/tests/test_totp.py +++ b/passlib/tests/test_totp.py @@ -3,6 +3,7 @@ # imports #============================================================================= # core +from binascii import Error as DecodeError import datetime from functools import partial import logging; log = logging.getLogger(__name__) @@ -11,7 +12,6 @@ import time as _time # site # pkg from passlib import exc -from passlib.utils.compat import unicode, u from passlib.tests.utils import TestCase, time_call # subject from passlib import totp as totp_module @@ -25,16 +25,6 @@ __all__ = [ # helpers #============================================================================= -# XXX: python 3 changed what error base64.b16decode() throws, from TypeError to base64.Error(). -# it wasn't until 3.3 that base32decode() also got changed. -# really should normalize this in the code to a single BinaryDecodeError, -# predicting this cross-version is getting unmanagable. -Base32DecodeError = Base16DecodeError = TypeError -if sys.version_info >= (3,0): - from binascii import Error as Base16DecodeError -if sys.version_info >= (3,3): - from binascii import Error as Base32DecodeError - PASS1 = "abcdef" PASS2 = b"\x00\xFF" KEY1 = '4AOGGDBBQSYHNTUZ' @@ -174,7 +164,7 @@ class AppWalletTest(TestCase): self.assertEqual(wallet._secrets, ref) # accept unicode - wallet = AppWallet({u("1"): b"aaa", u("02"): b"bbb", u("C"): b"ccc"}) + wallet = AppWallet({u"1": b"aaa", u"02": b"bbb", u"C": b"ccc"}) self.assertEqual(wallet._secrets, ref) # normalize int tags @@ -192,7 +182,7 @@ class AppWalletTest(TestCase): self.assertRaises(ValueError, AppWallet, {"ab*$": "aaa"}) # coerce value to bytes - wallet = AppWallet({"1": u("aaa"), "02": "bbb", "C": b"ccc"}) + wallet = AppWallet({"1": u"aaa", "02": "bbb", "C": b"ccc"}) self.assertEqual(wallet._secrets, ref) # forbid invalid value types @@ -406,7 +396,7 @@ class TotpTest(TestCase): # setup #============================================================================= def setUp(self): - super(TotpTest, self).setUp() + super().setUp() # clear norm_hash_name() cache so 'unknown hash' warnings get emitted each time from passlib.crypto.digest import lookup_hash @@ -629,13 +619,13 @@ class TotpTest(TestCase): self.assertEqual(TOTP(' 4aog gdbb qsyh ntuz ').key, KEY1_RAW) # .. w/ invalid char - self.assertRaises(Base32DecodeError, TOTP, 'ao!ggdbbqsyhntuz') + self.assertRaises(DecodeError, TOTP, 'ao!ggdbbqsyhntuz') # handle hex encoding self.assertEqual(TOTP('e01c630c2184b076ce99', 'hex').key, KEY1_RAW) # .. w/ invalid char - self.assertRaises(Base16DecodeError, TOTP, 'X01c630c2184b076ce99', 'hex') + self.assertRaises(DecodeError, TOTP, 'X01c630c2184b076ce99', 'hex') # handle raw bytes self.assertEqual(TOTP(KEY1_RAW, "raw").key, KEY1_RAW) @@ -749,7 +739,7 @@ class TotpTest(TestCase): otp = self.randotp(digits=7) # unicode & bytes - self.assertEqual(otp.normalize_token(u('1234567')), '1234567') + self.assertEqual(otp.normalize_token(u'1234567'), '1234567') self.assertEqual(otp.normalize_token(b'1234567'), '1234567') # int @@ -880,7 +870,7 @@ class TotpTest(TestCase): time = self.randtime() result = otp.generate(time) token = result.token - self.assertIsInstance(token, unicode) + self.assertIsInstance(token, str) start_time = result.counter * 30 # should generate same token for next 29s @@ -1204,8 +1194,8 @@ class TotpTest(TestCase): from_source = TOTP.from_source # uri (unicode) - otp = from_source(u("otpauth://totp/Example:alice@google.com?secret=JBSWY3DPEHPK3PXP&" - "issuer=Example")) + otp = from_source(u"otpauth://totp/Example:alice@google.com?secret=JBSWY3DPEHPK3PXP&" + "issuer=Example") self.assertEqual(otp.key, KEY4_RAW) # uri (bytes) @@ -1218,7 +1208,7 @@ class TotpTest(TestCase): self.assertEqual(otp.key, KEY4_RAW) # json (unicode) - otp = from_source(u('{"v": 1, "type": "totp", "key": "JBSWY3DPEHPK3PXP"}')) + otp = from_source(u'{"v": 1, "type": "totp", "key": "JBSWY3DPEHPK3PXP"}') self.assertEqual(otp.key, KEY4_RAW) # json (bytes) @@ -1239,7 +1229,7 @@ class TotpTest(TestCase): self.assertIs(otp2, otp1) # random string - self.assertRaises(ValueError, from_source, u("foo")) + self.assertRaises(ValueError, from_source, u"foo") self.assertRaises(ValueError, from_source, b"foo") #============================================================================= @@ -1278,8 +1268,8 @@ class TotpTest(TestCase): self.assertRaises(ValueError, from_uri, "otpauth://totp/Example:alice@google.com?digits=6") # undecodable secret - self.assertRaises(Base32DecodeError, from_uri, "otpauth://totp/Example:alice@google.com?" - "secret=JBSWY3DPEHP@3PXP") + self.assertRaises(DecodeError, from_uri, "otpauth://totp/Example:alice@google.com?" + "secret=JBSWY3DPEHP@3PXP") #-------------------------------------------------------------------------------- # label param @@ -1468,8 +1458,7 @@ class TotpTest(TestCase): self.assertRaises(ValueError, from_dict, dict(v=1, type="totp")) # undecodable secret - self.assertRaises(Base32DecodeError, from_dict, - dict(v=1, type="totp", key="JBSWY3DPEHP@3PXP")) + self.assertRaises(DecodeError, from_dict, dict(v=1, type="totp", key="JBSWY3DPEHP@3PXP")) #-------------------------------------------------------------------------------- # label & issuer params diff --git a/passlib/tests/test_utils.py b/passlib/tests/test_utils.py index 59ba160..2bc5c48 100644 --- a/passlib/tests/test_utils.py +++ b/passlib/tests/test_utils.py @@ -2,7 +2,6 @@ #============================================================================= # imports #============================================================================= -from __future__ import with_statement # core from functools import partial import warnings @@ -10,7 +9,7 @@ import warnings # pkg # module from passlib.utils import is_ascii_safe, to_bytes -from passlib.utils.compat import irange, PY2, PY3, u, unicode, join_bytes, PYPY +from passlib.utils.compat import join_bytes, PYPY from passlib.tests.utils import TestCase, hb, run_with_fixed_seeds #============================================================================= @@ -30,21 +29,24 @@ class MiscTest(TestCase): # test synthentic dir() dir(compat) - self.assertTrue('UnicodeIO' in dir(compat)) - self.assertTrue('irange' in dir(compat)) + # FIXME: find another lazy-loaded attr to check, all current ones removed after py2 comapt gone. + # self.assertTrue('UnicodeIO' in dir(compat)) def test_classproperty(self): from passlib.utils.decor import classproperty + def xprop_func(cls): + return cls.xvar + class test(object): xvar = 1 - @classproperty - def xprop(cls): - return cls.xvar + + xprop = classproperty(xprop_func) self.assertEqual(test.xprop, 1) + prop = test.__dict__['xprop'] - self.assertIs(prop.im_func, prop.__func__) + self.assertIs(prop.__func__, xprop_func) def test_deprecated_function(self): from passlib.utils.decor import deprecated_function @@ -81,10 +83,6 @@ class MiscTest(TestCase): self.assertEqual(d.value, 0) self.assertEqual(d.counter, 1) - prop = dummy.value - if not PY3: - self.assertIs(prop.im_func, prop.__func__) - def test_getrandbytes(self): """getrandbytes()""" from passlib.utils import getrandbytes @@ -124,11 +122,11 @@ class MiscTest(TestCase): # and hope that they're sufficient to test the range of behavior. # letters - x = wrapper(u('abc'), 32) - y = wrapper(u('abc'), 32) - self.assertIsInstance(x, unicode) + x = wrapper(u'abc', 32) + y = wrapper(u'abc', 32) + self.assertIsInstance(x, str) self.assertNotEqual(x,y) - self.assertEqual(sorted(set(x)), [u('a'),u('b'),u('c')]) + self.assertEqual(sorted(set(x)), [u'a',u'b',u'c']) # bytes x = wrapper(b'abc', 32) @@ -136,7 +134,7 @@ class MiscTest(TestCase): self.assertIsInstance(x, bytes) self.assertNotEqual(x,y) # NOTE: decoding this due to py3 bytes - self.assertEqual(sorted(set(x.decode("ascii"))), [u('a'),u('b'),u('c')]) + self.assertEqual(sorted(set(x.decode("ascii"))), [u'a',u'b',u'c']) def test_generate_password(self): """generate_password()""" @@ -200,18 +198,18 @@ class MiscTest(TestCase): # helpers to generate hashes & config strings to work with def get_hash(secret): - assert isinstance(secret, unicode) + assert isinstance(secret, str) hash = hasher.hash(secret) if isinstance(hash, bytes): # py2 hash = hash.decode("utf-8") - assert isinstance(hash, unicode) + assert isinstance(hash, str) return hash # test ascii password & return type - s1 = u("test") + s1 = u"test" h1 = get_hash(s1) result = safe_crypt(s1, h1) - self.assertIsInstance(result, unicode) + self.assertIsInstance(result, str) self.assertEqual(result, h1) self.assertEqual(safe_crypt(to_bytes(s1), to_bytes(h1)), h1) @@ -220,7 +218,7 @@ class MiscTest(TestCase): self.assertEqual(safe_crypt(s1, h1x), h1) # test utf-8 / unicode password - s2 = u('test\u1234') + s2 = u'test\u1234' h2 = get_hash(s2) self.assertEqual(safe_crypt(s2, h2), h2) self.assertEqual(safe_crypt(to_bytes(s2), to_bytes(h2)), h2) @@ -259,30 +257,29 @@ class MiscTest(TestCase): from passlib.utils import consteq, str_consteq # ensure error raises for wrong types - self.assertRaises(TypeError, consteq, u(''), b'') - self.assertRaises(TypeError, consteq, u(''), 1) - self.assertRaises(TypeError, consteq, u(''), None) + self.assertRaises(TypeError, consteq, u'', b'') + self.assertRaises(TypeError, consteq, u'', 1) + self.assertRaises(TypeError, consteq, u'', None) - self.assertRaises(TypeError, consteq, b'', u('')) + self.assertRaises(TypeError, consteq, b'', u'') self.assertRaises(TypeError, consteq, b'', 1) self.assertRaises(TypeError, consteq, b'', None) - self.assertRaises(TypeError, consteq, None, u('')) + self.assertRaises(TypeError, consteq, None, u'') self.assertRaises(TypeError, consteq, None, b'') - self.assertRaises(TypeError, consteq, 1, u('')) + self.assertRaises(TypeError, consteq, 1, u'') self.assertRaises(TypeError, consteq, 1, b'') def consteq_supports_string(value): - # under PY2, it supports all unicode strings (when present at all), - # under PY3, compare_digest() only supports ascii unicode strings. - # confirmed for: cpython 2.7.9, cpython 3.4, pypy, pypy3, pyston - return (consteq is str_consteq or PY2 or is_ascii_safe(value)) + # compare_digest() only supports ascii unicode strings. + # confirmed for: cpython 3.4, pypy3, pyston + return (consteq is str_consteq or is_ascii_safe(value)) # check equal inputs compare correctly for value in [ - u("a"), - u("abc"), - u("\xff\xa2\x12\x00")*10, + u"a", + u"abc", + u"\xff\xa2\x12\x00"*10, ]: if consteq_supports_string(value): self.assertTrue(consteq(value, value), "value %r:" % (value,)) @@ -296,18 +293,18 @@ class MiscTest(TestCase): # check non-equal inputs compare correctly for l,r in [ # check same-size comparisons with differing contents fail. - (u("a"), u("c")), - (u("abcabc"), u("zbaabc")), - (u("abcabc"), u("abzabc")), - (u("abcabc"), u("abcabz")), - ((u("\xff\xa2\x12\x00")*10)[:-1] + u("\x01"), - u("\xff\xa2\x12\x00")*10), + (u"a", u"c"), + (u"abcabc", u"zbaabc"), + (u"abcabc", u"abzabc"), + (u"abcabc", u"abcabz"), + ((u"\xff\xa2\x12\x00"*10)[:-1] + u"\x01", + u"\xff\xa2\x12\x00"*10), # check different-size comparisons fail. - (u(""), u("a")), - (u("abc"), u("abcdef")), - (u("abc"), u("defabc")), - (u("qwertyuiopasdfghjklzxcvbnm"), u("abc")), + (u"", u"a"), + (u"abc", u"abcdef"), + (u"abc", u"defabc"), + (u"qwertyuiopasdfghjklzxcvbnm", u"abc"), ]: if consteq_supports_string(l) and consteq_supports_string(r): self.assertFalse(consteq(l, r), "values %r %r:" % (l,r)) @@ -328,12 +325,12 @@ class MiscTest(TestCase): # NOTE: below code was used to generate stats for analysis ##from math import log as logb ##import timeit - ##multipliers = [ 1<<s for s in irange(9)] + ##multipliers = [ 1<<s for s in range(9)] ##correct = u"abcdefgh"*(1<<4) ##incorrect = u"abcdxfgh" ##print ##first = True - ##for run in irange(1): + ##for run in range(1): ## times = [] ## chars = [] ## for m in multipliers: @@ -365,73 +362,73 @@ class MiscTest(TestCase): self.assertRaises(TypeError, sp, b'') # empty strings - self.assertEqual(sp(u('')), u('')) - self.assertEqual(sp(u('\u00AD')), u('')) + self.assertEqual(sp(u''), u'') + self.assertEqual(sp(u'\u00AD'), u'') # verify B.1 chars are stripped, - self.assertEqual(sp(u("$\u00AD$\u200D$")), u("$$$")) + self.assertEqual(sp(u"$\u00AD$\u200D$"), u"$$$") # verify C.1.2 chars are replaced with space - self.assertEqual(sp(u("$ $\u00A0$\u3000$")), u("$ $ $ $")) + self.assertEqual(sp(u"$ $\u00A0$\u3000$"), u"$ $ $ $") # verify normalization to KC - self.assertEqual(sp(u("a\u0300")), u("\u00E0")) - self.assertEqual(sp(u("\u00E0")), u("\u00E0")) + self.assertEqual(sp(u"a\u0300"), u"\u00E0") + self.assertEqual(sp(u"\u00E0"), u"\u00E0") # verify various forbidden characters # control chars - self.assertRaises(ValueError, sp, u("\u0000")) - self.assertRaises(ValueError, sp, u("\u007F")) - self.assertRaises(ValueError, sp, u("\u180E")) - self.assertRaises(ValueError, sp, u("\uFFF9")) + self.assertRaises(ValueError, sp, u"\u0000") + self.assertRaises(ValueError, sp, u"\u007F") + self.assertRaises(ValueError, sp, u"\u180E") + self.assertRaises(ValueError, sp, u"\uFFF9") # private use - self.assertRaises(ValueError, sp, u("\uE000")) + self.assertRaises(ValueError, sp, u"\uE000") # non-characters - self.assertRaises(ValueError, sp, u("\uFDD0")) + self.assertRaises(ValueError, sp, u"\uFDD0") # surrogates - self.assertRaises(ValueError, sp, u("\uD800")) + self.assertRaises(ValueError, sp, u"\uD800") # non-plaintext chars - self.assertRaises(ValueError, sp, u("\uFFFD")) + self.assertRaises(ValueError, sp, u"\uFFFD") # non-canon - self.assertRaises(ValueError, sp, u("\u2FF0")) + self.assertRaises(ValueError, sp, u"\u2FF0") # change display properties - self.assertRaises(ValueError, sp, u("\u200E")) - self.assertRaises(ValueError, sp, u("\u206F")) + self.assertRaises(ValueError, sp, u"\u200E") + self.assertRaises(ValueError, sp, u"\u206F") # unassigned code points (as of unicode 3.2) - self.assertRaises(ValueError, sp, u("\u0900")) - self.assertRaises(ValueError, sp, u("\uFFF8")) + self.assertRaises(ValueError, sp, u"\u0900") + self.assertRaises(ValueError, sp, u"\uFFF8") # tagging characters - self.assertRaises(ValueError, sp, u("\U000e0001")) + self.assertRaises(ValueError, sp, u"\U000e0001") # verify bidi behavior # if starts with R/AL -- must end with R/AL - self.assertRaises(ValueError, sp, u("\u0627\u0031")) - self.assertEqual(sp(u("\u0627")), u("\u0627")) - self.assertEqual(sp(u("\u0627\u0628")), u("\u0627\u0628")) - self.assertEqual(sp(u("\u0627\u0031\u0628")), u("\u0627\u0031\u0628")) + self.assertRaises(ValueError, sp, u"\u0627\u0031") + self.assertEqual(sp(u"\u0627"), u"\u0627") + self.assertEqual(sp(u"\u0627\u0628"), u"\u0627\u0628") + self.assertEqual(sp(u"\u0627\u0031\u0628"), u"\u0627\u0031\u0628") # if starts with R/AL -- cannot contain L - self.assertRaises(ValueError, sp, u("\u0627\u0041\u0628")) + self.assertRaises(ValueError, sp, u"\u0627\u0041\u0628") # if doesn't start with R/AL -- can contain R/AL, but L & EN allowed - self.assertRaises(ValueError, sp, u("x\u0627z")) - self.assertEqual(sp(u("x\u0041z")), u("x\u0041z")) + self.assertRaises(ValueError, sp, u"x\u0627z") + self.assertEqual(sp(u"x\u0041z"), u"x\u0041z") #------------------------------------------------------ # examples pulled from external sources, to be thorough #------------------------------------------------------ # rfc 4031 section 3 examples - self.assertEqual(sp(u("I\u00ADX")), u("IX")) # strip SHY - self.assertEqual(sp(u("user")), u("user")) # unchanged - self.assertEqual(sp(u("USER")), u("USER")) # case preserved - self.assertEqual(sp(u("\u00AA")), u("a")) # normalize to KC form - self.assertEqual(sp(u("\u2168")), u("IX")) # normalize to KC form - self.assertRaises(ValueError, sp, u("\u0007")) # forbid control chars - self.assertRaises(ValueError, sp, u("\u0627\u0031")) # invalid bidi + self.assertEqual(sp(u"I\u00ADX"), u"IX") # strip SHY + self.assertEqual(sp(u"user"), u"user") # unchanged + self.assertEqual(sp(u"USER"), u"USER") # case preserved + self.assertEqual(sp(u"\u00AA"), u"a") # normalize to KC form + self.assertEqual(sp(u"\u2168"), u"IX") # normalize to KC form + self.assertRaises(ValueError, sp, u"\u0007") # forbid control chars + self.assertRaises(ValueError, sp, u"\u0627\u0031") # invalid bidi # rfc 3454 section 6 examples # starts with RAL char, must end with RAL char - self.assertRaises(ValueError, sp, u("\u0627\u0031")) - self.assertEqual(sp(u("\u0627\u0031\u0628")), u("\u0627\u0031\u0628")) + self.assertRaises(ValueError, sp, u"\u0627\u0031") + self.assertEqual(sp(u"\u0627\u0031\u0628"), u"\u0627\u0031\u0628") def test_splitcomma(self): from passlib.utils import splitcomma @@ -569,31 +566,24 @@ class CodecTest(TestCase): def test_bytes(self): """test b() helper, bytes and native str type""" - if PY3: - import builtins - self.assertIs(bytes, builtins.bytes) - else: - import __builtin__ as builtins - self.assertIs(bytes, builtins.str) + import builtins + self.assertIs(bytes, builtins.bytes) self.assertIsInstance(b'', bytes) self.assertIsInstance(b'\x00\xff', bytes) - if PY3: - self.assertEqual(b'\x00\xff'.decode("latin-1"), "\x00\xff") - else: - self.assertEqual(b'\x00\xff', "\x00\xff") + self.assertEqual(b'\x00\xff'.decode("latin-1"), "\x00\xff") def test_to_bytes(self): """test to_bytes()""" from passlib.utils import to_bytes # check unicode inputs - self.assertEqual(to_bytes(u('abc')), b'abc') - self.assertEqual(to_bytes(u('\x00\xff')), b'\x00\xc3\xbf') + self.assertEqual(to_bytes(u'abc'), b'abc') + self.assertEqual(to_bytes(u'\x00\xff'), b'\x00\xc3\xbf') # check unicode w/ encodings - self.assertEqual(to_bytes(u('\x00\xff'), 'latin-1'), b'\x00\xff') - self.assertRaises(ValueError, to_bytes, u('\x00\xff'), 'ascii') + self.assertEqual(to_bytes(u'\x00\xff', 'latin-1'), b'\x00\xff') + self.assertRaises(ValueError, to_bytes, u'\x00\xff', 'ascii') # check bytes inputs self.assertEqual(to_bytes(b'abc'), b'abc') @@ -617,17 +607,17 @@ class CodecTest(TestCase): from passlib.utils import to_unicode # check unicode inputs - self.assertEqual(to_unicode(u('abc')), u('abc')) - self.assertEqual(to_unicode(u('\x00\xff')), u('\x00\xff')) + self.assertEqual(to_unicode(u'abc'), u'abc') + self.assertEqual(to_unicode(u'\x00\xff'), u'\x00\xff') # check unicode input ignores encoding - self.assertEqual(to_unicode(u('\x00\xff'), "ascii"), u('\x00\xff')) + self.assertEqual(to_unicode(u'\x00\xff', "ascii"), u'\x00\xff') # check bytes input - self.assertEqual(to_unicode(b'abc'), u('abc')) - self.assertEqual(to_unicode(b'\x00\xc3\xbf'), u('\x00\xff')) + self.assertEqual(to_unicode(b'abc'), u'abc') + self.assertEqual(to_unicode(b'\x00\xc3\xbf'), u'\x00\xff') self.assertEqual(to_unicode(b'\x00\xff', 'latin-1'), - u('\x00\xff')) + u'\x00\xff') self.assertRaises(ValueError, to_unicode, b'\x00\xff') # check other @@ -639,28 +629,21 @@ class CodecTest(TestCase): from passlib.utils import to_native_str # test plain ascii - self.assertEqual(to_native_str(u('abc'), 'ascii'), 'abc') + self.assertEqual(to_native_str(u'abc', 'ascii'), 'abc') self.assertEqual(to_native_str(b'abc', 'ascii'), 'abc') # test invalid ascii - if PY3: - self.assertEqual(to_native_str(u('\xE0'), 'ascii'), '\xE0') - self.assertRaises(UnicodeDecodeError, to_native_str, b'\xC3\xA0', - 'ascii') - else: - self.assertRaises(UnicodeEncodeError, to_native_str, u('\xE0'), - 'ascii') - self.assertEqual(to_native_str(b'\xC3\xA0', 'ascii'), '\xC3\xA0') + self.assertEqual(to_native_str(u'\xE0', 'ascii'), '\xE0') + self.assertRaises(UnicodeDecodeError, to_native_str, b'\xC3\xA0', + 'ascii') # test latin-1 - self.assertEqual(to_native_str(u('\xE0'), 'latin-1'), '\xE0') + self.assertEqual(to_native_str(u'\xE0', 'latin-1'), '\xE0') self.assertEqual(to_native_str(b'\xE0', 'latin-1'), '\xE0') # test utf-8 - self.assertEqual(to_native_str(u('\xE0'), 'utf-8'), - '\xE0' if PY3 else '\xC3\xA0') - self.assertEqual(to_native_str(b'\xC3\xA0', 'utf-8'), - '\xE0' if PY3 else '\xC3\xA0') + self.assertEqual(to_native_str(u'\xE0', 'utf-8'), '\xE0') + self.assertEqual(to_native_str(b'\xC3\xA0', 'utf-8'), '\xE0') # other types rejected self.assertRaises(TypeError, to_native_str, None, 'ascii') @@ -669,9 +652,9 @@ class CodecTest(TestCase): """test is_ascii_safe()""" from passlib.utils import is_ascii_safe self.assertTrue(is_ascii_safe(b"\x00abc\x7f")) - self.assertTrue(is_ascii_safe(u("\x00abc\x7f"))) + self.assertTrue(is_ascii_safe(u"\x00abc\x7f")) self.assertFalse(is_ascii_safe(b"\x00abc\x80")) - self.assertFalse(is_ascii_safe(u("\x00abc\x80"))) + self.assertFalse(is_ascii_safe(u"\x00abc\x80")) def test_is_same_codec(self): """test is_same_codec()""" @@ -714,15 +697,15 @@ class Base64EngineTest(TestCase): # accept bytes or unicode self.assertEqual(ab64_decode(b"abc"), hb("69b7")) - self.assertEqual(ab64_decode(u("abc")), hb("69b7")) + self.assertEqual(ab64_decode(u"abc"), hb("69b7")) # reject non-ascii unicode - self.assertRaises(ValueError, ab64_decode, u("ab\xff")) + self.assertRaises(ValueError, ab64_decode, u"ab\xff") # underlying a2b_ascii treats non-base64 chars as "Incorrect padding" self.assertRaises(TypeError, ab64_decode, b"ab\xff") self.assertRaises(TypeError, ab64_decode, b"ab!") - self.assertRaises(TypeError, ab64_decode, u("ab!")) + self.assertRaises(TypeError, ab64_decode, u"ab!") # insert correct padding, handle dirty padding bits self.assertEqual(ab64_decode(b"abcd"), hb("69b71d")) # 0 mod 4 @@ -744,8 +727,7 @@ class Base64EngineTest(TestCase): self.assertEqual(ab64_encode(hb("69b7")), b"abc") # reject unicode - self.assertRaises(TypeError if PY3 else UnicodeEncodeError, - ab64_encode, hb("69b7").decode("latin-1")) + self.assertRaises(TypeError, ab64_encode, hb("69b7").decode("latin-1")) # insert correct padding before decoding self.assertEqual(ab64_encode(hb("69b71d")), b"abcd") # 0 mod 4 @@ -761,15 +743,15 @@ class Base64EngineTest(TestCase): # accept bytes or unicode self.assertEqual(b64s_decode(b"abc"), hb("69b7")) - self.assertEqual(b64s_decode(u("abc")), hb("69b7")) + self.assertEqual(b64s_decode(u"abc"), hb("69b7")) # reject non-ascii unicode - self.assertRaises(ValueError, b64s_decode, u("ab\xff")) + self.assertRaises(ValueError, b64s_decode, u"ab\xff") # underlying a2b_ascii treats non-base64 chars as "Incorrect padding" self.assertRaises(TypeError, b64s_decode, b"ab\xff") self.assertRaises(TypeError, b64s_decode, b"ab!") - self.assertRaises(TypeError, b64s_decode, u("ab!")) + self.assertRaises(TypeError, b64s_decode, u"ab!") # insert correct padding, handle dirty padding bits self.assertEqual(b64s_decode(b"abcd"), hb("69b71d")) # 0 mod 4 @@ -786,8 +768,7 @@ class Base64EngineTest(TestCase): self.assertEqual(b64s_encode(hb("69b7")), b"abc") # reject unicode - self.assertRaises(TypeError if PY3 else UnicodeEncodeError, - b64s_encode, hb("69b7").decode("latin-1")) + self.assertRaises(TypeError, b64s_encode, hb("69b7").decode("latin-1")) # insert correct padding before decoding self.assertEqual(b64s_encode(hb("69b71d")), b"abcd") # 0 mod 4 @@ -835,7 +816,7 @@ class _Base64Test(TestCase): """test encode_bytes() with bad input""" engine = self.engine encode = engine.encode_bytes - self.assertRaises(TypeError, encode, u('\x00')) + self.assertRaises(TypeError, encode, u'\x00') self.assertRaises(TypeError, encode, None) #=================================================================== @@ -851,7 +832,7 @@ class _Base64Test(TestCase): def test_decode_bytes_padding(self): """test decode_bytes() ignores padding bits""" - bchr = (lambda v: bytes([v])) if PY3 else chr + bchr = lambda v: bytes([v]) engine = self.engine m = self.m decode = engine.decode_bytes @@ -901,7 +882,7 @@ class _Base64Test(TestCase): from passlib.utils import getrandbytes, getrandstr rng = self.getRandom() saw_zero = False - for i in irange(500): + for i in range(500): # # test raw -> encode() -> decode() -> raw # @@ -999,7 +980,7 @@ class _Base64Test(TestCase): out = engine.decode_bytes(tmp) self.assertEqual(out, result) - self.assertRaises(TypeError, engine.encode_transposed_bytes, u("a"), []) + self.assertRaises(TypeError, engine.encode_transposed_bytes, u"a", []) def test_decode_transposed_bytes(self): """test decode_transposed_bytes()""" @@ -1050,7 +1031,7 @@ class _Base64Test(TestCase): # do random testing. from passlib.utils import getrandstr - for i in irange(100): + for i in range(100): # generate random value, encode, and then decode value = rng.randint(0, upper-1) encoded = encode(value) diff --git a/passlib/tests/test_utils_handlers.py b/passlib/tests/test_utils_handlers.py index 19cd4ca..f665aac 100644 --- a/passlib/tests/test_utils_handlers.py +++ b/passlib/tests/test_utils_handlers.py @@ -2,7 +2,6 @@ #============================================================================= # imports #============================================================================= -from __future__ import with_statement # core import re import hashlib @@ -12,11 +11,8 @@ import warnings # pkg from passlib.hash import ldap_md5, sha256_crypt from passlib.exc import MissingBackendError, PasslibHashWarning -from passlib.utils.compat import str_to_uascii, \ - uascii_to_str, unicode import passlib.utils.handlers as uh from passlib.tests.utils import HandlerCase, TestCase -from passlib.utils.compat import u # module log = getLogger(__name__) @@ -50,27 +46,27 @@ class SkeletonTest(TestCase): class d1(uh.StaticHandler): name = "d1" context_kwds = ("flag",) - _hash_prefix = u("_") - checksum_chars = u("ab") + _hash_prefix = u"_" + checksum_chars = u"ab" checksum_size = 1 def __init__(self, flag=False, **kwds): - super(d1, self).__init__(**kwds) + super().__init__(**kwds) self.flag = flag def _calc_checksum(self, secret): - return u('b') if self.flag else u('a') + return u'b' if self.flag else u'a' # check default identify method - self.assertTrue(d1.identify(u('_a'))) + self.assertTrue(d1.identify(u'_a')) self.assertTrue(d1.identify(b'_a')) - self.assertTrue(d1.identify(u('_b'))) + self.assertTrue(d1.identify(u'_b')) - self.assertFalse(d1.identify(u('_c'))) + self.assertFalse(d1.identify(u'_c')) self.assertFalse(d1.identify(b'_c')) - self.assertFalse(d1.identify(u('a'))) - self.assertFalse(d1.identify(u('b'))) - self.assertFalse(d1.identify(u('c'))) + self.assertFalse(d1.identify(u'a')) + self.assertFalse(d1.identify(u'b')) + self.assertFalse(d1.identify(u'c')) self.assertRaises(TypeError, d1.identify, None) self.assertRaises(TypeError, d1.identify, 1) @@ -79,65 +75,17 @@ class SkeletonTest(TestCase): # check default verify method self.assertTrue(d1.verify('s', b'_a')) - self.assertTrue(d1.verify('s',u('_a'))) + self.assertTrue(d1.verify('s',u'_a')) self.assertFalse(d1.verify('s', b'_b')) - self.assertFalse(d1.verify('s',u('_b'))) + self.assertFalse(d1.verify('s',u'_b')) self.assertTrue(d1.verify('s', b'_b', flag=True)) self.assertRaises(ValueError, d1.verify, 's', b'_c') - self.assertRaises(ValueError, d1.verify, 's', u('_c')) + self.assertRaises(ValueError, d1.verify, 's', u'_c') # check default hash method self.assertEqual(d1.hash('s'), '_a') self.assertEqual(d1.hash('s', flag=True), '_b') - def test_01_calc_checksum_hack(self): - """test StaticHandler legacy attr""" - # release 1.5 StaticHandler required genhash(), - # not _calc_checksum, be implemented. we have backward compat wrapper, - # this tests that it works. - - class d1(uh.StaticHandler): - name = "d1" - - @classmethod - def identify(cls, hash): - if not hash or len(hash) != 40: - return False - try: - int(hash, 16) - except ValueError: - return False - return True - - @classmethod - def genhash(cls, secret, hash): - if secret is None: - raise TypeError("no secret provided") - if isinstance(secret, unicode): - secret = secret.encode("utf-8") - # NOTE: have to support hash=None since this is test of legacy 1.5 api - if hash is not None and not cls.identify(hash): - raise ValueError("invalid hash") - return hashlib.sha1(b"xyz" + secret).hexdigest() - - @classmethod - def verify(cls, secret, hash): - if hash is None: - raise ValueError("no hash specified") - return cls.genhash(secret, hash) == hash.lower() - - # hash should issue api warnings, but everything else should be fine. - with self.assertWarningList("d1.*should be updated.*_calc_checksum"): - hash = d1.hash("test") - self.assertEqual(hash, '7c622762588a0e5cc786ad0a143156f9fd38eea3') - - self.assertTrue(d1.verify("test", hash)) - self.assertFalse(d1.verify("xtest", hash)) - - # not defining genhash either, however, should cause NotImplementedError - del d1.genhash - self.assertRaises(NotImplementedError, d1.hash, 'test') - #=================================================================== # GenericHandler & mixins #=================================================================== @@ -148,7 +96,7 @@ class SkeletonTest(TestCase): def from_string(cls, hash): if isinstance(hash, bytes): hash = hash.decode("ascii") - if hash == u('a'): + if hash == u'a': return cls(checksum=hash) else: raise ValueError @@ -161,7 +109,7 @@ class SkeletonTest(TestCase): self.assertFalse(d1.identify('b')) # check regexp - d1._hash_regex = re.compile(u('@.')) + d1._hash_regex = re.compile(u'@.') self.assertRaises(TypeError, d1.identify, None) self.assertRaises(TypeError, d1.identify, 1) self.assertTrue(d1.identify('@a')) @@ -169,7 +117,7 @@ class SkeletonTest(TestCase): del d1._hash_regex # check ident-based - d1.ident = u('!') + d1.ident = u'!' self.assertRaises(TypeError, d1.identify, None) self.assertRaises(TypeError, d1.identify, 1) self.assertTrue(d1.identify('!a')) @@ -182,35 +130,35 @@ class SkeletonTest(TestCase): class d1(uh.GenericHandler): name = 'd1' checksum_size = 4 - checksum_chars = u('xz') + checksum_chars = u'xz' def norm_checksum(checksum=None, **k): return d1(checksum=checksum, **k).checksum # too small - self.assertRaises(ValueError, norm_checksum, u('xxx')) + self.assertRaises(ValueError, norm_checksum, u'xxx') # right size - self.assertEqual(norm_checksum(u('xxxx')), u('xxxx')) - self.assertEqual(norm_checksum(u('xzxz')), u('xzxz')) + self.assertEqual(norm_checksum(u'xxxx'), u'xxxx') + self.assertEqual(norm_checksum(u'xzxz'), u'xzxz') # too large - self.assertRaises(ValueError, norm_checksum, u('xxxxx')) + self.assertRaises(ValueError, norm_checksum, u'xxxxx') # wrong chars - self.assertRaises(ValueError, norm_checksum, u('xxyx')) + self.assertRaises(ValueError, norm_checksum, u'xxyx') # wrong type self.assertRaises(TypeError, norm_checksum, b'xxyx') # relaxed # NOTE: this could be turned back on if we test _norm_checksum() directly... - #with self.assertWarningList("checksum should be unicode"): - # self.assertEqual(norm_checksum(b'xxzx', relaxed=True), u('xxzx')) + #with self.assertWarningList("checksum should be str"): + # self.assertEqual(norm_checksum(b'xxzx', relaxed=True), u'xxzx') #self.assertRaises(TypeError, norm_checksum, 1, relaxed=True) # test _stub_checksum behavior - self.assertEqual(d1()._stub_checksum, u('xxxx')) + self.assertEqual(d1()._stub_checksum, u'xxxx') def test_12_norm_checksum_raw(self): """test GenericHandler + HasRawChecksum mixin""" @@ -224,11 +172,11 @@ class SkeletonTest(TestCase): # test bytes self.assertEqual(norm_checksum(b'1234'), b'1234') - # test unicode - self.assertRaises(TypeError, norm_checksum, u('xxyx')) + # test str + self.assertRaises(TypeError, norm_checksum, u'xxyx') # NOTE: this could be turned back on if we test _norm_checksum() directly... - # self.assertRaises(TypeError, norm_checksum, u('xxyx'), relaxed=True) + # self.assertRaises(TypeError, norm_checksum, u'xxyx', relaxed=True) # test _stub_checksum behavior self.assertEqual(d1()._stub_checksum, b'\x00'*4) @@ -487,9 +435,9 @@ class SkeletonTest(TestCase): class d1(uh.HasManyIdents, uh.GenericHandler): name = 'd1' setting_kwds = ('ident',) - default_ident = u("!A") - ident_values = (u("!A"), u("!B")) - ident_aliases = { u("A"): u("!A")} + default_ident = u"!A" + ident_values = (u"!A", u"!B") + ident_aliases = { u"A": u"!A"} def norm_ident(**k): return d1(**k).ident @@ -497,25 +445,25 @@ class SkeletonTest(TestCase): # check ident=None self.assertRaises(TypeError, norm_ident) self.assertRaises(TypeError, norm_ident, ident=None) - self.assertEqual(norm_ident(use_defaults=True), u('!A')) + self.assertEqual(norm_ident(use_defaults=True), u'!A') # check valid idents - self.assertEqual(norm_ident(ident=u('!A')), u('!A')) - self.assertEqual(norm_ident(ident=u('!B')), u('!B')) - self.assertRaises(ValueError, norm_ident, ident=u('!C')) + self.assertEqual(norm_ident(ident=u'!A'), u'!A') + self.assertEqual(norm_ident(ident=u'!B'), u'!B') + self.assertRaises(ValueError, norm_ident, ident=u'!C') # check aliases - self.assertEqual(norm_ident(ident=u('A')), u('!A')) + self.assertEqual(norm_ident(ident=u'A'), u'!A') # check invalid idents - self.assertRaises(ValueError, norm_ident, ident=u('B')) + self.assertRaises(ValueError, norm_ident, ident=u'B') # check identify is honoring ident system - self.assertTrue(d1.identify(u("!Axxx"))) - self.assertTrue(d1.identify(u("!Bxxx"))) - self.assertFalse(d1.identify(u("!Cxxx"))) - self.assertFalse(d1.identify(u("A"))) - self.assertFalse(d1.identify(u(""))) + self.assertTrue(d1.identify(u"!Axxx")) + self.assertTrue(d1.identify(u"!Bxxx")) + self.assertFalse(d1.identify(u"!Cxxx")) + self.assertFalse(d1.identify(u"A")) + self.assertFalse(d1.identify(u"")) self.assertRaises(TypeError, d1.identify, None) self.assertRaises(TypeError, d1.identify, 1) @@ -538,12 +486,12 @@ class SkeletonTest(TestCase): # simple hash w/ salt result = hash.des_crypt.parsehash("OgAwTx2l6NADI") - self.assertEqual(result, {'checksum': u('AwTx2l6NADI'), 'salt': u('Og')}) + self.assertEqual(result, {'checksum': u'AwTx2l6NADI', 'salt': u'Og'}) # parse rounds and extra implicit_rounds flag h = '$5$LKO/Ute40T3FNF95$U0prpBQd4PloSGU0pnpM4z9wKn4vZ1.jsrzQfPqxph9' - s = u('LKO/Ute40T3FNF95') - c = u('U0prpBQd4PloSGU0pnpM4z9wKn4vZ1.jsrzQfPqxph9') + s = u'LKO/Ute40T3FNF95' + c = u'U0prpBQd4PloSGU0pnpM4z9wKn4vZ1.jsrzQfPqxph9' result = hash.sha256_crypt.parsehash(h) self.assertEqual(result, dict(salt=s, rounds=5000, implicit_rounds=True, checksum=c)) @@ -555,14 +503,14 @@ class SkeletonTest(TestCase): # sanitize result = hash.sha256_crypt.parsehash(h, sanitize=True) self.assertEqual(result, dict(rounds=5000, implicit_rounds=True, - salt=u('LK**************'), - checksum=u('U0pr***************************************'))) + salt=u'LK**************', + checksum=u'U0pr***************************************')) # parse w/o implicit rounds flag result = hash.sha256_crypt.parsehash('$5$rounds=10428$uy/jIAhCetNCTtb0$YWvUOXbkqlqhyoPMpN8BMe.ZGsGx2aBvxTvDFI613c3') self.assertEqual(result, dict( - checksum=u('YWvUOXbkqlqhyoPMpN8BMe.ZGsGx2aBvxTvDFI613c3'), - salt=u('uy/jIAhCetNCTtb0'), + checksum=u'YWvUOXbkqlqhyoPMpN8BMe.ZGsGx2aBvxTvDFI613c3', + salt=u'uy/jIAhCetNCTtb0', rounds=10428, )) @@ -578,9 +526,9 @@ class SkeletonTest(TestCase): # sanitizing of raw checksums & salts result = hash.pbkdf2_sha1.parsehash(h1, sanitize=True) self.assertEqual(result, dict( - checksum=u('O26************************'), + checksum=u'O26************************', rounds=60000, - salt=u('Do********************'), + salt=u'Do********************', )) def test_92_bitsize(self): @@ -722,7 +670,7 @@ class PrefixWrapperTest(TestCase): def test_12_ident(self): # test ident is proxied h = uh.PrefixWrapper("h2", "ldap_md5", "{XXX}") - self.assertEqual(h.ident, u("{XXX}{MD5}")) + self.assertEqual(h.ident, u"{XXX}{MD5}") self.assertIs(h.ident_values, None) # test lack of ident means no proxy @@ -737,7 +685,7 @@ class PrefixWrapperTest(TestCase): # test custom ident overrides default h = uh.PrefixWrapper("h3", "ldap_md5", "{XXX}", ident="{X") - self.assertEqual(h.ident, u("{X")) + self.assertEqual(h.ident, u"{X") self.assertIs(h.ident_values, None) # test custom ident must match @@ -750,11 +698,11 @@ class PrefixWrapperTest(TestCase): # test ident_values is proxied h = uh.PrefixWrapper("h4", "phpass", "{XXX}") self.assertIs(h.ident, None) - self.assertEqual(h.ident_values, (u("{XXX}$P$"), u("{XXX}$H$"))) + self.assertEqual(h.ident_values, (u"{XXX}$P$", u"{XXX}$H$")) # test ident=True means use prefix even if hash has no ident. h = uh.PrefixWrapper("h5", "des_crypt", "{XXX}", ident=True) - self.assertEqual(h.ident, u("{XXX}")) + self.assertEqual(h.ident, u"{XXX}") self.assertIs(h.ident_values, None) # ... but requires prefix @@ -763,7 +711,7 @@ class PrefixWrapperTest(TestCase): # orig_prefix + HasManyIdent - warning with self.assertWarningList("orig_prefix.*may not work correctly"): h = uh.PrefixWrapper("h7", "phpass", orig_prefix="$", prefix="?") - self.assertEqual(h.ident_values, None) # TODO: should output (u("?P$"), u("?H$"))) + self.assertEqual(h.ident_values, None) # TODO: should output (u"?P$", u"?H$")) self.assertEqual(h.ident, None) def test_13_repr(self): @@ -796,10 +744,11 @@ class UnsaltedHash(uh.StaticHandler): checksum_size = 40 def _calc_checksum(self, secret): - if isinstance(secret, unicode): + if isinstance(secret, str): secret = secret.encode("utf-8") data = b"boblious" + secret - return str_to_uascii(hashlib.sha1(data).hexdigest()) + return hashlib.sha1(data).hexdigest() + class SaltedHash(uh.HasSalt, uh.GenericHandler): """test algorithm with a salt""" @@ -811,7 +760,7 @@ class SaltedHash(uh.HasSalt, uh.GenericHandler): checksum_size = 40 salt_chars = checksum_chars = uh.LOWER_HEX_CHARS - _hash_regex = re.compile(u("^@salt[0-9a-f]{42,44}$")) + _hash_regex = re.compile(u"^@salt[0-9a-f]{42,44}$") @classmethod def from_string(cls, hash): @@ -822,14 +771,15 @@ class SaltedHash(uh.HasSalt, uh.GenericHandler): return cls(salt=hash[5:-40], checksum=hash[-40:]) def to_string(self): - hash = u("@salt%s%s") % (self.salt, self.checksum) - return uascii_to_str(hash) + hash = u"@salt%s%s" % (self.salt, self.checksum) + return hash def _calc_checksum(self, secret): - if isinstance(secret, unicode): + if isinstance(secret, str): secret = secret.encode("utf-8") data = self.salt.encode("ascii") + secret + self.salt.encode("ascii") - return str_to_uascii(hashlib.sha1(data).hexdigest()) + return hashlib.sha1(data).hexdigest() + #============================================================================= # test sample algorithms - really a self-test of HandlerCase @@ -838,7 +788,7 @@ class SaltedHash(uh.HasSalt, uh.GenericHandler): # TODO: provide data samples for algorithms # (positive knowns, negative knowns, invalid identify) -UPASS_TEMP = u('\u0399\u03c9\u03b1\u03bd\u03bd\u03b7\u03c2') +UPASS_TEMP = u'\u0399\u03c9\u03b1\u03bd\u03bd\u03b7\u03c2' class UnsaltedHashTest(HandlerCase): handler = UnsaltedHash diff --git a/passlib/tests/test_utils_md4.py b/passlib/tests/test_utils_md4.py index 5d824a1..e3e04d4 100644 --- a/passlib/tests/test_utils_md4.py +++ b/passlib/tests/test_utils_md4.py @@ -29,7 +29,7 @@ class Legacy_MD4_Test(_Common_MD4_Test): descriptionPrefix = "passlib.utils.md4.md4()" def setUp(self): - super(Legacy_MD4_Test, self).setUp() + super().setUp() warnings.filterwarnings("ignore", ".*passlib.utils.md4.*deprecated", DeprecationWarning) def get_md4_const(self): diff --git a/passlib/tests/test_utils_pbkdf2.py b/passlib/tests/test_utils_pbkdf2.py index 443eb53..0e10248 100644 --- a/passlib/tests/test_utils_pbkdf2.py +++ b/passlib/tests/test_utils_pbkdf2.py @@ -12,72 +12,16 @@ passlib.tests -- tests for passlib.utils.pbkdf2 #============================================================================= # imports #============================================================================= -from __future__ import with_statement # core import hashlib import warnings # site # pkg # module -from passlib.utils.compat import u, JYTHON +from passlib.utils.compat import JYTHON from passlib.tests.utils import TestCase, hb #============================================================================= -# test assorted crypto helpers -#============================================================================= -class UtilsTest(TestCase): - """test various utils functions""" - descriptionPrefix = "passlib.utils.pbkdf2" - - ndn_formats = ["hashlib", "iana"] - ndn_values = [ - # (iana name, hashlib name, ... other unnormalized names) - ("md5", "md5", "SCRAM-MD5-PLUS", "MD-5"), - ("sha1", "sha-1", "SCRAM-SHA-1", "SHA1"), - ("sha256", "sha-256", "SHA_256", "sha2-256"), - ("ripemd160", "ripemd-160", "SCRAM-RIPEMD-160", "RIPEmd160", - # NOTE: there was an older "RIPEMD" & "RIPEMD-128", but python treates "RIPEMD" - # as alias for "RIPEMD-160" - "ripemd", "SCRAM-RIPEMD"), - ("test128", "test-128", "TEST128"), - ("test2", "test2", "TEST-2"), - ("test3_128", "test3-128", "TEST-3-128"), - ] - - def setUp(self): - super(UtilsTest, self).setUp() - warnings.filterwarnings("ignore", ".*passlib.utils.pbkdf2.*deprecated", DeprecationWarning) - - def test_norm_hash_name(self): - """norm_hash_name()""" - from itertools import chain - from passlib.utils.pbkdf2 import norm_hash_name - from passlib.crypto.digest import _known_hash_names - - # test formats - for format in self.ndn_formats: - norm_hash_name("md4", format) - self.assertRaises(ValueError, norm_hash_name, "md4", None) - self.assertRaises(ValueError, norm_hash_name, "md4", "fake") - - # test types - self.assertEqual(norm_hash_name(u("MD4")), "md4") - self.assertEqual(norm_hash_name(b"MD4"), "md4") - self.assertRaises(TypeError, norm_hash_name, None) - - # test selected results - with warnings.catch_warnings(): - warnings.filterwarnings("ignore", '.*unknown hash') - for row in chain(_known_hash_names, self.ndn_values): - for idx, format in enumerate(self.ndn_formats): - correct = row[idx] - for value in row: - result = norm_hash_name(value, format) - self.assertEqual(result, correct, - "name=%r, format=%r:" % (value, - format)) - -#============================================================================= # test PBKDF1 support #============================================================================= class Pbkdf1_Test(TestCase): @@ -108,7 +52,7 @@ class Pbkdf1_Test(TestCase): ) def setUp(self): - super(Pbkdf1_Test, self).setUp() + super().setUp() warnings.filterwarnings("ignore", ".*passlib.utils.pbkdf2.*deprecated", DeprecationWarning) def test_known(self): @@ -263,7 +207,7 @@ class Pbkdf2_Test(TestCase): ] def setUp(self): - super(Pbkdf2_Test, self).setUp() + super().setUp() warnings.filterwarnings("ignore", ".*passlib.utils.pbkdf2.*deprecated", DeprecationWarning) def test_known(self): diff --git a/passlib/tests/test_win32.py b/passlib/tests/test_win32.py deleted file mode 100644 index e818b62..0000000 --- a/passlib/tests/test_win32.py +++ /dev/null @@ -1,50 +0,0 @@ -"""tests for passlib.win32 -- (c) Assurance Technologies 2003-2009""" -#============================================================================= -# imports -#============================================================================= -# core -import warnings -# site -# pkg -from passlib.tests.utils import TestCase -# module -from passlib.utils.compat import u - -#============================================================================= -# -#============================================================================= -class UtilTest(TestCase): - """test util funcs in passlib.win32""" - - ##test hashes from http://msdn.microsoft.com/en-us/library/cc245828(v=prot.10).aspx - ## among other places - - def setUp(self): - super(UtilTest, self).setUp() - warnings.filterwarnings("ignore", - "the 'passlib.win32' module is deprecated") - - def test_lmhash(self): - from passlib.win32 import raw_lmhash - for secret, hash in [ - ("OLDPASSWORD", u("c9b81d939d6fd80cd408e6b105741864")), - ("NEWPASSWORD", u('09eeab5aa415d6e4d408e6b105741864')), - ("welcome", u("c23413a8a1e7665faad3b435b51404ee")), - ]: - result = raw_lmhash(secret, hex=True) - self.assertEqual(result, hash) - - def test_nthash(self): - warnings.filterwarnings("ignore", - r"nthash\.raw_nthash\(\) is deprecated") - from passlib.win32 import raw_nthash - for secret, hash in [ - ("OLDPASSWORD", u("6677b2c394311355b54f25eec5bfacf5")), - ("NEWPASSWORD", u("256781a62031289d3c2c98c14f1efc8c")), - ]: - result = raw_nthash(secret, hex=True) - self.assertEqual(result, hash) - -#============================================================================= -# eof -#============================================================================= diff --git a/passlib/tests/tox_support.py b/passlib/tests/tox_support.py index 43170bc..d0dcd4e 100644 --- a/passlib/tests/tox_support.py +++ b/passlib/tests/tox_support.py @@ -14,7 +14,6 @@ import re import logging; log = logging.getLogger(__name__) # site # pkg -from passlib.utils.compat import print_ # local __all__ = [ ] @@ -40,7 +39,7 @@ def do_hash_tests(*args): from passlib.tests import test_handlers names = [TH_PATH + ":" + name + suffix for name in dir(test_handlers) if not name.startswith("_") and any(re.match(arg,name) for arg in args)] - print_("\n".join(names)) + print("\n".join(names)) return not names def do_preset_tests(name): @@ -48,7 +47,7 @@ def do_preset_tests(name): if name == "django" or name == "django-hashes": do_hash_tests("django_.*_test", "hex_md5_test") if name == "django": - print_("passlib.tests.test_ext_django") + print("passlib.tests.test_ext_django") else: raise ValueError("unknown name: %r" % name) diff --git a/passlib/tests/utils.py b/passlib/tests/utils.py index 79a9f9f..9ade9de 100644 --- a/passlib/tests/utils.py +++ b/passlib/tests/utils.py @@ -2,7 +2,6 @@ #============================================================================= # imports #============================================================================= -from __future__ import with_statement # core from binascii import unhexlify import contextlib @@ -16,8 +15,9 @@ import sys import tempfile import threading import time +import unittest from passlib.exc import PasslibHashWarning, PasslibConfigWarning -from passlib.utils.compat import PY3, JYTHON +from passlib.utils.compat import JYTHON import warnings from warnings import warn # site @@ -25,11 +25,9 @@ from warnings import warn from passlib import exc from passlib.exc import MissingBackendError import passlib.registry as registry -from passlib.tests.backports import TestCase as _TestCase, skip, skipIf, skipUnless, SkipTest from passlib.utils import has_rounds_info, has_salt_info, rounds_cost_values, \ rng as sys_rng, getrandstr, is_ascii_safe, to_native_str, \ repeat_string, tick, batch -from passlib.utils.compat import iteritems, irange, u, unicode, PY2, nullcontext from passlib.utils.decor import classproperty import passlib.utils.handlers as uh # local @@ -219,7 +217,7 @@ def patch_calc_min_rounds(handler): #============================================================================= def set_file(path, content): """set file to specified bytes""" - if isinstance(content, unicode): + if isinstance(content, str): content = content.encode("utf-8") with open(path, "wb") as fh: fh.write(content) @@ -231,15 +229,10 @@ def get_file(path): def tonn(source): """convert native string to non-native string""" - if not isinstance(source, str): - return source - elif PY3: + if isinstance(source, str): return source.encode("utf-8") else: - try: - return source.decode("utf-8") - except UnicodeDecodeError: - return source.decode("latin-1") + return source def hb(source): """ @@ -288,7 +281,7 @@ def run_with_fixed_seeds(count=128, master_seed=0x243F6A8885A308D3): @wraps(func) def wrapper(*args, **kwds): rng = random.Random(master_seed) - for _ in irange(count): + for _ in range(count): kwds['seed'] = rng.getrandbits(32) func(*args, **kwds) return wrapper @@ -298,7 +291,7 @@ def run_with_fixed_seeds(count=128, master_seed=0x243F6A8885A308D3): # custom test harness #============================================================================= -class TestCase(_TestCase): +class TestCase(unittest.TestCase): """passlib-specific test case class this class adds a number of features to the standard TestCase... @@ -321,7 +314,7 @@ class TestCase(_TestCase): def shortDescription(self): """wrap shortDescription() method to prepend descriptionPrefix""" - desc = super(TestCase, self).shortDescription() + desc = super().shortDescription() prefix = self.descriptionPrefix if prefix: desc = "%s: %s" % (prefix, desc or str(self)) @@ -333,7 +326,7 @@ class TestCase(_TestCase): #--------------------------------------------------------------- @classproperty def __unittest_skip__(cls): - # NOTE: this attr is technically a unittest2 internal detail. + # NOTE: this attr is technically a unittest internal detail. name = cls.__name__ return name.startswith("_") or \ getattr(cls, "_%s__unittest_skip" % name, False) @@ -354,7 +347,7 @@ class TestCase(_TestCase): resetWarningState = True def setUp(self): - super(TestCase, self).setUp() + super().setUp() self.setUpWarnings() # have uh.debug_only_repr() return real values for duration of test self.patchAttr(exc, "ENABLE_DEBUG_ONLY_REPR", True) @@ -375,7 +368,6 @@ class TestCase(_TestCase): # should be kept until then, so we test the legacy paths. warnings.filterwarnings("ignore", r"the method .*\.(encrypt|genconfig|genhash)\(\) is deprecated") warnings.filterwarnings("ignore", r"the 'vary_rounds' option is deprecated") - warnings.filterwarnings("ignore", r"Support for `(py-bcrypt|bcryptor)` is deprecated") #--------------------------------------------------------------- # tweak message formatting so longMessage mode is only enabled @@ -397,7 +389,7 @@ class TestCase(_TestCase): msg = kwds.pop("__msg__", None) if _callable is None: # FIXME: this ignores 'msg' - return super(TestCase, self).assertRaises(_exc_type, None, + return super().assertRaises(_exc_type, None, *args, **kwds) try: result = _callable(*args, **kwds) @@ -411,7 +403,7 @@ class TestCase(_TestCase): # forbid a bunch of deprecated aliases so I stop using them #--------------------------------------------------------------- def assertEquals(self, *a, **k): - raise AssertionError("this alias is deprecated by unittest2") + raise AssertionError("this alias is deprecated by stdlib unittest") assertNotEquals = assertRegexMatches = assertEquals #=================================================================== @@ -470,14 +462,13 @@ class TestCase(_TestCase): def __init__(self, case, **kwds): self.case = case self.kwds = kwds - self.__super = super(TestCase._AssertWarningList, self) - self.__super.__init__(record=True) + super().__init__(record=True) def __enter__(self): - self.log = self.__super.__enter__() + self.log = super().__enter__() def __exit__(self, *exc_info): - self.__super.__exit__(*exc_info) + super().__exit__(*exc_info) if exc_info[0] is None: self.case.assertWarningList(self.log, **self.kwds) @@ -631,20 +622,14 @@ class TestCase(_TestCase): # subtests #=================================================================== - has_real_subtest = hasattr(_TestCase, "subTest") - @contextlib.contextmanager def subTest(self, *args, **kwds): """ - wrapper/backport for .subTest() which also traps SkipTest errors. + wrapper for .subTest() which traps SkipTest errors. (see source for details) """ - # this function works around two things: - # * TestCase.subTest() wasn't added until Py34; so for older python versions, - # we either need unittest2 installed, or provide stub of our own. - # this method provides a stub if needed (based on .has_real_subtest check) - # - # * as 2020-10-08, .subTest() doesn't play nicely w/ .skipTest(); + # this function works around issue that as 2020-10-08, + # .subTest() doesn't play nicely w/ .skipTest(); # and also makes it hard to debug which subtest had a failure. # (see https://bugs.python.org/issue25894 and https://bugs.python.org/issue35327) # this method traps skipTest exceptions, and adds some logging to help debug @@ -663,13 +648,8 @@ class TestCase(_TestCase): test_log = self.getLogger() title = _render_title(*args, **kwds) - # use real subtest manager if available - if self.has_real_subtest: - ctx = super(TestCase, self).subTest(*args, **kwds) - else: - ctx = nullcontext() - # run the subtest + ctx = super().subTest(*args, **kwds) with ctx: test_log.info("running subtest: %s", title) try: @@ -677,7 +657,9 @@ class TestCase(_TestCase): except SkipTest: # silence "SkipTest" exceptions, want to keep running next subtest. test_log.info("subtest skipped: %s", title) - pass + # XXX: should revisit whether latest py3 version of UTs handle this ok, + # meaning it's safe to re-raise this. + return except Exception as err: # log unhandled exception occurred # (assuming traceback will be reported up higher, so not bothering here) @@ -734,8 +716,7 @@ class TestCase(_TestCase): return logger named after current test. """ cls = type(self) - # NOTE: conditional on qualname for PY2 compat - path = cls.__module__ + "." + getattr(cls, "__qualname__", cls.__name__) + path = cls.__module__ + "." + cls.__qualname__ name = self._testMethodName if name: path = path + "." + name @@ -778,8 +759,7 @@ class HandlerCase(TestCase): .. note:: - This is subclass of :class:`unittest.TestCase` - (or :class:`unittest2.TestCase` if available). + This is subclass of :class:`unittest.TestCase`. """ #=================================================================== # class attrs - should be filled in by subclass @@ -831,8 +811,8 @@ class HandlerCase(TestCase): # passwords used to test basic hash behavior - generally # don't need to be overidden. stock_passwords = [ - u("test"), - u("\u20AC\u00A5$"), + u"test", + u"\u20AC\u00A5$", b'\xe2\x82\xac\xc2\xa5$' ] @@ -1065,7 +1045,7 @@ class HandlerCase(TestCase): if test_requires_backend and self._skip_backend_reason: raise self.skipTest(self._skip_backend_reason) - super(HandlerCase, self).setUp() + super().setUp() # if needed, select specific backend for duration of test # NOTE: skipping this if create_backend_case() signalled we're skipping backend @@ -1384,7 +1364,7 @@ class HandlerCase(TestCase): def sampler(func): value1 = func() - for _ in irange(samples): + for _ in range(samples): value2 = func() if value1 != value2: return @@ -1500,7 +1480,7 @@ class HandlerCase(TestCase): self.do_stub_encrypt(salt=salt) # check some invalid salt chars, make sure they're rejected - source = u('\x00\xff') + source = u'\x00\xff' if raw: source = source.encode("latin-1") chunk = max(mn, 1) @@ -1516,7 +1496,7 @@ class HandlerCase(TestCase): if getattr(self.handler, "_salt_is_bytes", False): return bytes else: - return unicode + return str def test_15_salt_type(self): """test non-string salt values""" @@ -1530,12 +1510,11 @@ class HandlerCase(TestCase): self.assertRaises(TypeError, self.do_encrypt, 'stub', salt=fake()) # unicode should be accepted only if salt_type is unicode. - if salt_type is not unicode: - self.assertRaises(TypeError, self.do_encrypt, 'stub', salt=u('x') * salt_size) + if salt_type is not str: + self.assertRaises(TypeError, self.do_encrypt, 'stub', salt=u'x' * salt_size) - # bytes should be accepted only if salt_type is bytes, - # OR if salt type is unicode and running PY2 - to allow native strings. - if not (salt_type is bytes or (PY2 and salt_type is unicode)): + # bytes should be accepted only if salt_type is bytes + if salt_type is not bytes: self.assertRaises(TypeError, self.do_encrypt, 'stub', salt=b'x' * salt_size) def test_using_salt_size(self): @@ -1936,7 +1915,7 @@ class HandlerCase(TestCase): handler, subcls, small, medium, large, adj = self._create_using_rounds_helper() def get_effective_range(cls): - seen = set(get_effective_rounds(cls) for _ in irange(1000)) + seen = set(get_effective_rounds(cls) for _ in range(1000)) return min(seen), max(seen) def assert_rounds_range(vary_rounds, lower, upper): @@ -2011,24 +1990,24 @@ class HandlerCase(TestCase): # check ident_values list for value in cls.ident_values: - self.assertIsInstance(value, unicode, - "cls.ident_values must be unicode:") + self.assertIsInstance(value, str, + "cls.ident_values must be str:") self.assertTrue(len(cls.ident_values)>1, "cls.ident_values must have 2+ elements:") # check default_ident value - self.assertIsInstance(cls.default_ident, unicode, - "cls.default_ident must be unicode:") + self.assertIsInstance(cls.default_ident, str, + "cls.default_ident must be str:") self.assertTrue(cls.default_ident in cls.ident_values, "cls.default_ident must specify member of cls.ident_values") # check optional aliases list if cls.ident_aliases: - for alias, ident in iteritems(cls.ident_aliases): - self.assertIsInstance(alias, unicode, - "cls.ident_aliases keys must be unicode:") # XXX: allow ints? - self.assertIsInstance(ident, unicode, - "cls.ident_aliases values must be unicode:") + for alias, ident in cls.ident_aliases.items(): + self.assertIsInstance(alias, str, + "cls.ident_aliases keys must be str:") # XXX: allow ints? + self.assertIsInstance(ident, str, + "cls.ident_aliases values must be str:") self.assertTrue(ident in cls.ident_values, "cls.ident_aliases must map to cls.ident_values members: %r" % (ident,)) @@ -2347,7 +2326,7 @@ class HandlerCase(TestCase): chars = self.forbidden_characters if not chars: raise self.skipTest("none listed") - base = u('stub') + base = u'stub' if isinstance(chars, bytes): from passlib.utils.compat import iter_byte_chars chars = iter_byte_chars(chars) @@ -2366,7 +2345,7 @@ class HandlerCase(TestCase): """ check if we're expecting potential verify failure due to crypt.crypt() encoding limitation """ - if PY3 and self.backend == "os_crypt" and isinstance(secret, bytes): + if self.backend == "os_crypt" and isinstance(secret, bytes): try: secret.decode("utf-8") except UnicodeDecodeError: @@ -2578,7 +2557,7 @@ class HandlerCase(TestCase): # # test hash='' is rejected for all but the plaintext hashes # - for hash in [u(''), b'']: + for hash in [u'', b'']: if self.accepts_all_hashes: # then it accepts empty string as well. self.assertTrue(self.do_identify(hash)) @@ -2609,7 +2588,7 @@ class HandlerCase(TestCase): def require_parsehash(self): if not hasattr(self.handler, "parsehash"): - raise SkipTest("parsehash() not implemented") + raise self.skipTest("parsehash() not implemented") def test_70_parsehash(self): """ @@ -2638,11 +2617,6 @@ class HandlerCase(TestCase): # but all else should be the same result3 = handler.parsehash(hash, sanitize=True) correct3 = result.copy() - if PY2: - # silence warning about bytes & unicode not comparing - # (sanitize may convert bytes into base64 text) - warnings.filterwarnings("ignore", ".*unequal comparison failed to convert.*", - category=UnicodeWarning) for key in ("salt", "checksum"): if key in result3: self.assertNotEqual(result3[key], correct3[key]) @@ -2656,7 +2630,7 @@ class HandlerCase(TestCase): """ if value is None: return - self.assertIsInstance(value, unicode) + self.assertIsInstance(value, str) # assumes mask_value() defaults will never show more than <show> chars (4); # and show nothing if size less than 1/<pct> (8). ref = value if len(value) < 8 else value[4:] @@ -2797,7 +2771,7 @@ class HandlerCase(TestCase): def wrapper(): try: self.test_77_fuzz_input(threaded=True) - except SkipTest: + except unittest.SkipTest: pass except: with failed_lock: @@ -2811,7 +2785,7 @@ class HandlerCase(TestCase): thread.setDaemon(True) thread.start() return thread - threads = [launch(n) for n in irange(thread_count)] + threads = [launch(n) for n in range(thread_count)] # wait until all threads exit timeout = self.max_fuzz_time * thread_count * 4 @@ -2874,7 +2848,7 @@ class HandlerCase(TestCase): used by fuzz testing. verifiers should be callable with signature - ``func(password: unicode, hash: ascii str) -> ok: bool``. + ``func(password: str, hash: ascii str) -> ok: bool``. """ handler = self.handler verifiers = [] @@ -2929,7 +2903,7 @@ class HandlerCase(TestCase): #========================================================== # alphabet for randomly generated passwords - password_alphabet = u('qwertyASDF1234<>.@*#! \u00E1\u0259\u0411\u2113') + password_alphabet = u'qwertyASDF1234<>.@*#! \u00E1\u0259\u0411\u2113' # encoding when testing bytes password_encoding = "utf-8" @@ -3039,7 +3013,7 @@ class HandlerCase(TestCase): # occasionally try an empty password rng = self.rng if rng.random() < .0001: - return u('') + return u'' # check if truncate size needs to be considered handler = self.handler @@ -3058,7 +3032,7 @@ class HandlerCase(TestCase): result = getrandstr(rng, self.password_alphabet, size) # trim ones that encode past truncate point. - if truncate_size and isinstance(result, unicode): + if truncate_size and isinstance(result, str): while len(result.encode("utf-8")) > truncate_size: result = result[:-1] @@ -3210,7 +3184,7 @@ class OsCryptMixin(HandlerCase): if not self.handler.has_backend("os_crypt"): # XXX: currently, any tests that use this are skipped entirely! (see issue 120) self._patch_safe_crypt() - super(OsCryptMixin, self).setUp() + super().setUp() @classmethod def _get_safe_crypt_handler_backend(cls): @@ -3267,7 +3241,7 @@ class OsCryptMixin(HandlerCase): when it's known os_crypt will be faked by _patch_safe_crypt() """ assert backend == "os_crypt" - reason = super(OsCryptMixin, cls)._get_skip_backend_reason(backend) + reason = super()._get_skip_backend_reason(backend) from passlib.utils import has_crypt if reason == cls._BACKEND_NOT_AVAILABLE and has_crypt: @@ -3515,7 +3489,7 @@ class UserHandlerMixin(HandlerCase): context_map = HandlerCase.FuzzHashGenerator.context_map.copy() context_map.update(user="random_user") - user_alphabet = u("asdQWE123") + user_alphabet = u"asdQWE123" def random_user(self): rng = self.rng @@ -3543,14 +3517,14 @@ class EncodingHandlerMixin(HandlerCase): # restrict stock passwords & fuzz alphabet to latin-1, # so different encodings can be tested safely. stock_passwords = [ - u("test"), + u"test", b"test", - u("\u00AC\u00BA"), + u"\u00AC\u00BA", ] class FuzzHashGenerator(HandlerCase.FuzzHashGenerator): - password_alphabet = u('qwerty1234<>.@*#! \u00AC') + password_alphabet = u'qwerty1234<>.@*#! \u00AC' def populate_context(self, secret, kwds): """insert encoding into kwds""" @@ -3569,13 +3543,13 @@ class reset_warnings(warnings.catch_warnings): """catch_warnings() wrapper which clears warning registry & filters""" def __init__(self, reset_filter="always", reset_registry=".*", **kwds): - super(reset_warnings, self).__init__(**kwds) + super().__init__(**kwds) self._reset_filter = reset_filter self._reset_registry = re.compile(reset_registry) if reset_registry else None def __enter__(self): # let parent class archive filter state - ret = super(reset_warnings, self).__enter__() + ret = super().__enter__() # reset the filter to list everything if self._reset_filter: @@ -3614,7 +3588,7 @@ class reset_warnings(warnings.catch_warnings): setattr(mod, "__warningregistry__", orig) else: reg.update(orig) - super(reset_warnings, self).__exit__(*exc_info) + super().__exit__(*exc_info) #============================================================================= # eof |