Загрузить файлы в «venv/Lib/site-packages/passlib/tests»
This commit is contained in:
97
venv/Lib/site-packages/passlib/tests/test_hosts.py
Normal file
97
venv/Lib/site-packages/passlib/tests/test_hosts.py
Normal file
@@ -0,0 +1,97 @@
|
||||
"""test passlib.hosts"""
|
||||
#=============================================================================
|
||||
# imports
|
||||
#=============================================================================
|
||||
from __future__ import with_statement
|
||||
# core
|
||||
import logging; log = logging.getLogger(__name__)
|
||||
# site
|
||||
# pkg
|
||||
from passlib import hosts, hash as hashmod
|
||||
from passlib.utils import unix_crypt_schemes
|
||||
from passlib.tests.utils import TestCase
|
||||
# module
|
||||
|
||||
#=============================================================================
|
||||
# test predefined app contexts
|
||||
#=============================================================================
|
||||
class HostsTest(TestCase):
|
||||
"""perform general tests to make sure contexts work"""
|
||||
# NOTE: these tests are not really comprehensive,
|
||||
# since they would do little but duplicate
|
||||
# the presets in apps.py
|
||||
#
|
||||
# they mainly try to ensure no typos
|
||||
# or dynamic behavior foul-ups.
|
||||
|
||||
def check_unix_disabled(self, ctx):
|
||||
for hash in [
|
||||
"",
|
||||
"!",
|
||||
"*",
|
||||
"!$1$TXl/FX/U$BZge.lr.ux6ekjEjxmzwz0",
|
||||
]:
|
||||
self.assertEqual(ctx.identify(hash), 'unix_disabled')
|
||||
self.assertFalse(ctx.verify('test', hash))
|
||||
|
||||
def test_linux_context(self):
|
||||
ctx = hosts.linux_context
|
||||
for hash in [
|
||||
('$6$rounds=41128$VoQLvDjkaZ6L6BIE$4pt.1Ll1XdDYduEwEYPCMOBiR6W6'
|
||||
'znsyUEoNlcVXpv2gKKIbQolgmTGe6uEEVJ7azUxuc8Tf7zV9SD2z7Ij751'),
|
||||
('$5$rounds=31817$iZGmlyBQ99JSB5n6$p4E.pdPBWx19OajgjLRiOW0itGny'
|
||||
'xDGgMlDcOsfaI17'),
|
||||
'$1$TXl/FX/U$BZge.lr.ux6ekjEjxmzwz0',
|
||||
'kAJJz.Rwp0A/I',
|
||||
]:
|
||||
self.assertTrue(ctx.verify("test", hash))
|
||||
self.check_unix_disabled(ctx)
|
||||
|
||||
def test_bsd_contexts(self):
|
||||
for ctx in [
|
||||
hosts.freebsd_context,
|
||||
hosts.openbsd_context,
|
||||
hosts.netbsd_context,
|
||||
]:
|
||||
for hash in [
|
||||
'$1$TXl/FX/U$BZge.lr.ux6ekjEjxmzwz0',
|
||||
'kAJJz.Rwp0A/I',
|
||||
]:
|
||||
self.assertTrue(ctx.verify("test", hash))
|
||||
h1 = "$2a$04$yjDgE74RJkeqC0/1NheSSOrvKeu9IbKDpcQf/Ox3qsrRS/Kw42qIS"
|
||||
if hashmod.bcrypt.has_backend():
|
||||
self.assertTrue(ctx.verify("test", h1))
|
||||
else:
|
||||
self.assertEqual(ctx.identify(h1), "bcrypt")
|
||||
self.check_unix_disabled(ctx)
|
||||
|
||||
def test_host_context(self):
|
||||
ctx = getattr(hosts, "host_context", None)
|
||||
if not ctx:
|
||||
return self.skipTest("host_context not available on this platform")
|
||||
|
||||
# validate schemes is non-empty,
|
||||
# and contains unix_disabled + at least one real scheme
|
||||
schemes = list(ctx.schemes())
|
||||
self.assertTrue(schemes, "appears to be unix system, but no known schemes supported by crypt")
|
||||
self.assertTrue('unix_disabled' in schemes)
|
||||
schemes.remove("unix_disabled")
|
||||
self.assertTrue(schemes, "should have schemes beside fallback scheme")
|
||||
self.assertTrue(set(unix_crypt_schemes).issuperset(schemes))
|
||||
|
||||
# check for hash support
|
||||
self.check_unix_disabled(ctx)
|
||||
for scheme, hash in [
|
||||
("sha512_crypt", ('$6$rounds=41128$VoQLvDjkaZ6L6BIE$4pt.1Ll1XdDYduEwEYPCMOBiR6W6'
|
||||
'znsyUEoNlcVXpv2gKKIbQolgmTGe6uEEVJ7azUxuc8Tf7zV9SD2z7Ij751')),
|
||||
("sha256_crypt", ('$5$rounds=31817$iZGmlyBQ99JSB5n6$p4E.pdPBWx19OajgjLRiOW0itGny'
|
||||
'xDGgMlDcOsfaI17')),
|
||||
("md5_crypt", '$1$TXl/FX/U$BZge.lr.ux6ekjEjxmzwz0'),
|
||||
("des_crypt", 'kAJJz.Rwp0A/I'),
|
||||
]:
|
||||
if scheme in schemes:
|
||||
self.assertTrue(ctx.verify("test", hash))
|
||||
|
||||
#=============================================================================
|
||||
# eof
|
||||
#=============================================================================
|
||||
205
venv/Lib/site-packages/passlib/tests/test_pwd.py
Normal file
205
venv/Lib/site-packages/passlib/tests/test_pwd.py
Normal file
@@ -0,0 +1,205 @@
|
||||
"""passlib.tests -- tests for passlib.pwd"""
|
||||
#=============================================================================
|
||||
# imports
|
||||
#=============================================================================
|
||||
# core
|
||||
import itertools
|
||||
import logging; log = logging.getLogger(__name__)
|
||||
# site
|
||||
# pkg
|
||||
from passlib.tests.utils import TestCase
|
||||
# local
|
||||
__all__ = [
|
||||
"UtilsTest",
|
||||
"GenerateTest",
|
||||
"StrengthTest",
|
||||
]
|
||||
|
||||
#=============================================================================
|
||||
#
|
||||
#=============================================================================
|
||||
class UtilsTest(TestCase):
|
||||
"""test internal utilities"""
|
||||
descriptionPrefix = "passlib.pwd"
|
||||
|
||||
def test_self_info_rate(self):
|
||||
"""_self_info_rate()"""
|
||||
from passlib.pwd import _self_info_rate
|
||||
|
||||
self.assertEqual(_self_info_rate(""), 0)
|
||||
|
||||
self.assertEqual(_self_info_rate("a" * 8), 0)
|
||||
|
||||
self.assertEqual(_self_info_rate("ab"), 1)
|
||||
self.assertEqual(_self_info_rate("ab" * 8), 1)
|
||||
|
||||
self.assertEqual(_self_info_rate("abcd"), 2)
|
||||
self.assertEqual(_self_info_rate("abcd" * 8), 2)
|
||||
self.assertAlmostEqual(_self_info_rate("abcdaaaa"), 1.5488, places=4)
|
||||
|
||||
# def test_total_self_info(self):
|
||||
# """_total_self_info()"""
|
||||
# from passlib.pwd import _total_self_info
|
||||
#
|
||||
# self.assertEqual(_total_self_info(""), 0)
|
||||
#
|
||||
# self.assertEqual(_total_self_info("a" * 8), 0)
|
||||
#
|
||||
# self.assertEqual(_total_self_info("ab"), 2)
|
||||
# self.assertEqual(_total_self_info("ab" * 8), 16)
|
||||
#
|
||||
# self.assertEqual(_total_self_info("abcd"), 8)
|
||||
# self.assertEqual(_total_self_info("abcd" * 8), 64)
|
||||
# self.assertAlmostEqual(_total_self_info("abcdaaaa"), 12.3904, places=4)
|
||||
|
||||
#=============================================================================
|
||||
# word generation
|
||||
#=============================================================================
|
||||
|
||||
# import subject
|
||||
from passlib.pwd import genword, default_charsets
|
||||
ascii_62 = default_charsets['ascii_62']
|
||||
hex = default_charsets['hex']
|
||||
|
||||
class WordGeneratorTest(TestCase):
|
||||
"""test generation routines"""
|
||||
descriptionPrefix = "passlib.pwd.genword()"
|
||||
|
||||
def setUp(self):
|
||||
super(WordGeneratorTest, self).setUp()
|
||||
|
||||
# patch some RNG references so they're reproducible.
|
||||
from passlib.pwd import SequenceGenerator
|
||||
self.patchAttr(SequenceGenerator, "rng",
|
||||
self.getRandom("pwd generator"))
|
||||
|
||||
def assertResultContents(self, results, count, chars, unique=True):
|
||||
"""check result list matches expected count & charset"""
|
||||
self.assertEqual(len(results), count)
|
||||
if unique:
|
||||
if unique is True:
|
||||
unique = count
|
||||
self.assertEqual(len(set(results)), unique)
|
||||
self.assertEqual(set("".join(results)), set(chars))
|
||||
|
||||
def test_general(self):
|
||||
"""general behavior"""
|
||||
|
||||
# basic usage
|
||||
result = genword()
|
||||
self.assertEqual(len(result), 9)
|
||||
|
||||
# malformed keyword should have useful error.
|
||||
self.assertRaisesRegex(TypeError, "(?i)unexpected keyword.*badkwd", genword, badkwd=True)
|
||||
|
||||
def test_returns(self):
|
||||
"""'returns' keyword"""
|
||||
# returns=int option
|
||||
results = genword(returns=5000)
|
||||
self.assertResultContents(results, 5000, ascii_62)
|
||||
|
||||
# returns=iter option
|
||||
gen = genword(returns=iter)
|
||||
results = [next(gen) for _ in range(5000)]
|
||||
self.assertResultContents(results, 5000, ascii_62)
|
||||
|
||||
# invalid returns option
|
||||
self.assertRaises(TypeError, genword, returns='invalid-type')
|
||||
|
||||
def test_charset(self):
|
||||
"""'charset' & 'chars' options"""
|
||||
# charset option
|
||||
results = genword(charset="hex", returns=5000)
|
||||
self.assertResultContents(results, 5000, hex)
|
||||
|
||||
# chars option
|
||||
# there are 3**3=27 possible combinations
|
||||
results = genword(length=3, chars="abc", returns=5000)
|
||||
self.assertResultContents(results, 5000, "abc", unique=27)
|
||||
|
||||
# chars + charset
|
||||
self.assertRaises(TypeError, genword, chars='abc', charset='hex')
|
||||
|
||||
# TODO: test rng option
|
||||
|
||||
#=============================================================================
|
||||
# phrase generation
|
||||
#=============================================================================
|
||||
|
||||
# import subject
|
||||
from passlib.pwd import genphrase
|
||||
simple_words = ["alpha", "beta", "gamma"]
|
||||
|
||||
class PhraseGeneratorTest(TestCase):
|
||||
"""test generation routines"""
|
||||
descriptionPrefix = "passlib.pwd.genphrase()"
|
||||
|
||||
def assertResultContents(self, results, count, words, unique=True, sep=" "):
|
||||
"""check result list matches expected count & charset"""
|
||||
self.assertEqual(len(results), count)
|
||||
if unique:
|
||||
if unique is True:
|
||||
unique = count
|
||||
self.assertEqual(len(set(results)), unique)
|
||||
out = set(itertools.chain.from_iterable(elem.split(sep) for elem in results))
|
||||
self.assertEqual(out, set(words))
|
||||
|
||||
def test_general(self):
|
||||
"""general behavior"""
|
||||
|
||||
# basic usage
|
||||
result = genphrase()
|
||||
self.assertEqual(len(result.split(" ")), 4) # 48 / log(7776, 2) ~= 3.7 -> 4
|
||||
|
||||
# malformed keyword should have useful error.
|
||||
self.assertRaisesRegex(TypeError, "(?i)unexpected keyword.*badkwd", genphrase, badkwd=True)
|
||||
|
||||
def test_entropy(self):
|
||||
"""'length' & 'entropy' keywords"""
|
||||
|
||||
# custom entropy
|
||||
result = genphrase(entropy=70)
|
||||
self.assertEqual(len(result.split(" ")), 6) # 70 / log(7776, 2) ~= 5.4 -> 6
|
||||
|
||||
# custom length
|
||||
result = genphrase(length=3)
|
||||
self.assertEqual(len(result.split(" ")), 3)
|
||||
|
||||
# custom length < entropy
|
||||
result = genphrase(length=3, entropy=48)
|
||||
self.assertEqual(len(result.split(" ")), 4)
|
||||
|
||||
# custom length > entropy
|
||||
result = genphrase(length=4, entropy=12)
|
||||
self.assertEqual(len(result.split(" ")), 4)
|
||||
|
||||
def test_returns(self):
|
||||
"""'returns' keyword"""
|
||||
# returns=int option
|
||||
results = genphrase(returns=1000, words=simple_words)
|
||||
self.assertResultContents(results, 1000, simple_words)
|
||||
|
||||
# returns=iter option
|
||||
gen = genphrase(returns=iter, words=simple_words)
|
||||
results = [next(gen) for _ in range(1000)]
|
||||
self.assertResultContents(results, 1000, simple_words)
|
||||
|
||||
# invalid returns option
|
||||
self.assertRaises(TypeError, genphrase, returns='invalid-type')
|
||||
|
||||
def test_wordset(self):
|
||||
"""'wordset' & 'words' options"""
|
||||
# wordset option
|
||||
results = genphrase(words=simple_words, returns=5000)
|
||||
self.assertResultContents(results, 5000, simple_words)
|
||||
|
||||
# words option
|
||||
results = genphrase(length=3, words=simple_words, returns=5000)
|
||||
self.assertResultContents(results, 5000, simple_words, unique=3**3)
|
||||
|
||||
# words + wordset
|
||||
self.assertRaises(TypeError, genphrase, words=simple_words, wordset='bip39')
|
||||
|
||||
#=============================================================================
|
||||
# eof
|
||||
#=============================================================================
|
||||
228
venv/Lib/site-packages/passlib/tests/test_registry.py
Normal file
228
venv/Lib/site-packages/passlib/tests/test_registry.py
Normal file
@@ -0,0 +1,228 @@
|
||||
"""tests for passlib.hash -- (c) Assurance Technologies 2003-2009"""
|
||||
#=============================================================================
|
||||
# imports
|
||||
#=============================================================================
|
||||
from __future__ import with_statement
|
||||
# core
|
||||
from logging import getLogger
|
||||
import warnings
|
||||
import sys
|
||||
# site
|
||||
# pkg
|
||||
from passlib import hash, registry, exc
|
||||
from passlib.registry import register_crypt_handler, register_crypt_handler_path, \
|
||||
get_crypt_handler, list_crypt_handlers, _unload_handler_name as unload_handler_name
|
||||
import passlib.utils.handlers as uh
|
||||
from passlib.tests.utils import TestCase
|
||||
# module
|
||||
log = getLogger(__name__)
|
||||
|
||||
#=============================================================================
|
||||
# dummy handlers
|
||||
#
|
||||
# NOTE: these are defined outside of test case
|
||||
# since they're used by test_register_crypt_handler_path(),
|
||||
# which needs them to be available as module globals.
|
||||
#=============================================================================
|
||||
class dummy_0(uh.StaticHandler):
|
||||
name = "dummy_0"
|
||||
|
||||
class alt_dummy_0(uh.StaticHandler):
|
||||
name = "dummy_0"
|
||||
|
||||
dummy_x = 1
|
||||
|
||||
#=============================================================================
|
||||
# test registry
|
||||
#=============================================================================
|
||||
class RegistryTest(TestCase):
|
||||
|
||||
descriptionPrefix = "passlib.registry"
|
||||
|
||||
def setUp(self):
|
||||
super(RegistryTest, self).setUp()
|
||||
|
||||
# backup registry state & restore it after test.
|
||||
locations = dict(registry._locations)
|
||||
handlers = dict(registry._handlers)
|
||||
def restore():
|
||||
registry._locations.clear()
|
||||
registry._locations.update(locations)
|
||||
registry._handlers.clear()
|
||||
registry._handlers.update(handlers)
|
||||
self.addCleanup(restore)
|
||||
|
||||
def test_hash_proxy(self):
|
||||
"""test passlib.hash proxy object"""
|
||||
# check dir works
|
||||
dir(hash)
|
||||
|
||||
# check repr works
|
||||
repr(hash)
|
||||
|
||||
# check non-existent attrs raise error
|
||||
self.assertRaises(AttributeError, getattr, hash, 'fooey')
|
||||
|
||||
# GAE tries to set __loader__,
|
||||
# make sure that doesn't call register_crypt_handler.
|
||||
old = getattr(hash, "__loader__", None)
|
||||
test = object()
|
||||
hash.__loader__ = test
|
||||
self.assertIs(hash.__loader__, test)
|
||||
if old is None:
|
||||
del hash.__loader__
|
||||
self.assertFalse(hasattr(hash, "__loader__"))
|
||||
else:
|
||||
hash.__loader__ = old
|
||||
self.assertIs(hash.__loader__, old)
|
||||
|
||||
# check storing attr calls register_crypt_handler
|
||||
class dummy_1(uh.StaticHandler):
|
||||
name = "dummy_1"
|
||||
hash.dummy_1 = dummy_1
|
||||
self.assertIs(get_crypt_handler("dummy_1"), dummy_1)
|
||||
|
||||
# check storing under wrong name results in error
|
||||
self.assertRaises(ValueError, setattr, hash, "dummy_1x", dummy_1)
|
||||
|
||||
def test_register_crypt_handler_path(self):
|
||||
"""test register_crypt_handler_path()"""
|
||||
# NOTE: this messes w/ internals of registry, shouldn't be used publically.
|
||||
paths = registry._locations
|
||||
|
||||
# check namespace is clear
|
||||
self.assertTrue('dummy_0' not in paths)
|
||||
self.assertFalse(hasattr(hash, 'dummy_0'))
|
||||
|
||||
# check invalid names are rejected
|
||||
self.assertRaises(ValueError, register_crypt_handler_path,
|
||||
"dummy_0", ".test_registry")
|
||||
self.assertRaises(ValueError, register_crypt_handler_path,
|
||||
"dummy_0", __name__ + ":dummy_0:xxx")
|
||||
self.assertRaises(ValueError, register_crypt_handler_path,
|
||||
"dummy_0", __name__ + ":dummy_0.xxx")
|
||||
|
||||
# try lazy load
|
||||
register_crypt_handler_path('dummy_0', __name__)
|
||||
self.assertTrue('dummy_0' in list_crypt_handlers())
|
||||
self.assertTrue('dummy_0' not in list_crypt_handlers(loaded_only=True))
|
||||
self.assertIs(hash.dummy_0, dummy_0)
|
||||
self.assertTrue('dummy_0' in list_crypt_handlers(loaded_only=True))
|
||||
unload_handler_name('dummy_0')
|
||||
|
||||
# try lazy load w/ alt
|
||||
register_crypt_handler_path('dummy_0', __name__ + ':alt_dummy_0')
|
||||
self.assertIs(hash.dummy_0, alt_dummy_0)
|
||||
unload_handler_name('dummy_0')
|
||||
|
||||
# check lazy load w/ wrong type fails
|
||||
register_crypt_handler_path('dummy_x', __name__)
|
||||
self.assertRaises(TypeError, get_crypt_handler, 'dummy_x')
|
||||
|
||||
# check lazy load w/ wrong name fails
|
||||
register_crypt_handler_path('alt_dummy_0', __name__)
|
||||
self.assertRaises(ValueError, get_crypt_handler, "alt_dummy_0")
|
||||
unload_handler_name("alt_dummy_0")
|
||||
|
||||
# TODO: check lazy load which calls register_crypt_handler (warning should be issued)
|
||||
sys.modules.pop("passlib.tests._test_bad_register", None)
|
||||
register_crypt_handler_path("dummy_bad", "passlib.tests._test_bad_register")
|
||||
with warnings.catch_warnings():
|
||||
warnings.filterwarnings("ignore", "xxxxxxxxxx", DeprecationWarning)
|
||||
h = get_crypt_handler("dummy_bad")
|
||||
from passlib.tests import _test_bad_register as tbr
|
||||
self.assertIs(h, tbr.alt_dummy_bad)
|
||||
|
||||
def test_register_crypt_handler(self):
|
||||
"""test register_crypt_handler()"""
|
||||
|
||||
self.assertRaises(TypeError, register_crypt_handler, {})
|
||||
|
||||
self.assertRaises(ValueError, register_crypt_handler, type('x', (uh.StaticHandler,), dict(name=None)))
|
||||
self.assertRaises(ValueError, register_crypt_handler, type('x', (uh.StaticHandler,), dict(name="AB_CD")))
|
||||
self.assertRaises(ValueError, register_crypt_handler, type('x', (uh.StaticHandler,), dict(name="ab-cd")))
|
||||
self.assertRaises(ValueError, register_crypt_handler, type('x', (uh.StaticHandler,), dict(name="ab__cd")))
|
||||
self.assertRaises(ValueError, register_crypt_handler, type('x', (uh.StaticHandler,), dict(name="default")))
|
||||
|
||||
class dummy_1(uh.StaticHandler):
|
||||
name = "dummy_1"
|
||||
|
||||
class dummy_1b(uh.StaticHandler):
|
||||
name = "dummy_1"
|
||||
|
||||
self.assertTrue('dummy_1' not in list_crypt_handlers())
|
||||
|
||||
register_crypt_handler(dummy_1)
|
||||
register_crypt_handler(dummy_1)
|
||||
self.assertIs(get_crypt_handler("dummy_1"), dummy_1)
|
||||
|
||||
self.assertRaises(KeyError, register_crypt_handler, dummy_1b)
|
||||
self.assertIs(get_crypt_handler("dummy_1"), dummy_1)
|
||||
|
||||
register_crypt_handler(dummy_1b, force=True)
|
||||
self.assertIs(get_crypt_handler("dummy_1"), dummy_1b)
|
||||
|
||||
self.assertTrue('dummy_1' in list_crypt_handlers())
|
||||
|
||||
def test_get_crypt_handler(self):
|
||||
"""test get_crypt_handler()"""
|
||||
|
||||
class dummy_1(uh.StaticHandler):
|
||||
name = "dummy_1"
|
||||
|
||||
# without available handler
|
||||
self.assertRaises(KeyError, get_crypt_handler, "dummy_1")
|
||||
self.assertIs(get_crypt_handler("dummy_1", None), None)
|
||||
|
||||
# already loaded handler
|
||||
register_crypt_handler(dummy_1)
|
||||
self.assertIs(get_crypt_handler("dummy_1"), dummy_1)
|
||||
|
||||
with warnings.catch_warnings():
|
||||
warnings.filterwarnings("ignore", "handler names should be lower-case, and use underscores instead of hyphens:.*", UserWarning)
|
||||
|
||||
# already loaded handler, using incorrect name
|
||||
self.assertIs(get_crypt_handler("DUMMY-1"), dummy_1)
|
||||
|
||||
# lazy load of unloaded handler, using incorrect name
|
||||
register_crypt_handler_path('dummy_0', __name__)
|
||||
self.assertIs(get_crypt_handler("DUMMY-0"), dummy_0)
|
||||
|
||||
# check system & private names aren't returned
|
||||
from passlib import hash
|
||||
hash.__dict__["_fake"] = "dummy"
|
||||
for name in ["_fake", "__package__"]:
|
||||
self.assertRaises(KeyError, get_crypt_handler, name)
|
||||
self.assertIs(get_crypt_handler(name, None), None)
|
||||
|
||||
def test_list_crypt_handlers(self):
|
||||
"""test list_crypt_handlers()"""
|
||||
from passlib.registry import list_crypt_handlers
|
||||
|
||||
# check system & private names aren't returned
|
||||
hash.__dict__["_fake"] = "dummy"
|
||||
for name in list_crypt_handlers():
|
||||
self.assertFalse(name.startswith("_"), "%r: " % name)
|
||||
unload_handler_name("_fake")
|
||||
|
||||
def test_handlers(self):
|
||||
"""verify we have tests for all builtin handlers"""
|
||||
from passlib.registry import list_crypt_handlers
|
||||
from passlib.tests.test_handlers import get_handler_case, conditionally_available_hashes
|
||||
for name in list_crypt_handlers():
|
||||
# skip some wrappers that don't need independant testing
|
||||
if name.startswith("ldap_") and name[5:] in list_crypt_handlers():
|
||||
continue
|
||||
if name in ["roundup_plaintext"]:
|
||||
continue
|
||||
# check the remaining ones all have a handler
|
||||
try:
|
||||
self.assertTrue(get_handler_case(name))
|
||||
except exc.MissingBackendError:
|
||||
if name in conditionally_available_hashes: # expected to fail on some setups
|
||||
continue
|
||||
raise
|
||||
|
||||
#=============================================================================
|
||||
# eof
|
||||
#=============================================================================
|
||||
1604
venv/Lib/site-packages/passlib/tests/test_totp.py
Normal file
1604
venv/Lib/site-packages/passlib/tests/test_totp.py
Normal file
File diff suppressed because it is too large
Load Diff
1171
venv/Lib/site-packages/passlib/tests/test_utils.py
Normal file
1171
venv/Lib/site-packages/passlib/tests/test_utils.py
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user