summaryrefslogtreecommitdiff
path: root/passlib/context.py
diff options
context:
space:
mode:
Diffstat (limited to 'passlib/context.py')
-rw-r--r--passlib/context.py61
1 files changed, 54 insertions, 7 deletions
diff --git a/passlib/context.py b/passlib/context.py
index c83f815..867add6 100644
--- a/passlib/context.py
+++ b/passlib/context.py
@@ -996,6 +996,9 @@ class _CryptConfig(object):
# tuple of categories in alphabetical order (not including None)
categories = None
+ # dict mapping category -> default scheme
+ _default_schemes = None
+
# dict mapping (scheme, category) -> _CryptRecord
_records = None
@@ -1009,6 +1012,7 @@ class _CryptConfig(object):
def __init__(self, source):
self._init_scheme_list(source.get((None,None,"schemes")))
self._init_options(source)
+ self._init_default_schemes()
self._init_records()
def _init_scheme_list(self, data):
@@ -1226,11 +1230,54 @@ class _CryptConfig(object):
return kwds, has_cat_options
#===================================================================
- # deprecated & default maps
+ # deprecated & default schemes
#===================================================================
+ def _init_default_schemes(self):
+ """initialize maps containing default scheme for each category.
+
+ have to do this after _init_options(), since the default scheme
+ is affected by the list of deprecated schemes.
+ """
+ # init maps & locals
+ get_optionmap = self.get_context_optionmap
+ default_map = self._default_schemes = get_optionmap("default").copy()
+ dep_map = get_optionmap("deprecated")
+ schemes = self.schemes
+ if not schemes:
+ return
+
+ # figure out default scheme
+ deps = dep_map.get(None) or ()
+ default = default_map.get(None)
+ if not default:
+ for scheme in schemes:
+ if scheme not in deps:
+ default_map[None] = scheme
+ break
+ else:
+ raise ValueError("must have at least one non-deprecated scheme")
+ elif default in deps:
+ raise ValueError("default scheme cannot be deprecated")
+
+ # figure out per-category default schemes,
+ for cat in self.categories:
+ cdeps = dep_map.get(cat, deps)
+ cdefault = default_map.get(cat, default)
+ if not cdefault:
+ for scheme in schemes:
+ if scheme not in cdeps:
+ default_map[cat] = scheme
+ break
+ else:
+ raise ValueError("must have at least one non-deprecated "
+ "scheme for %r category" % cat)
+ elif cdefault in cdeps:
+ raise ValueError("default scheme for %r category "
+ "cannot be deprecated" % cat)
+
def default_scheme(self, category):
- "return default scheme for specific category"
- defaults = self.get_context_optionmap("default")
+ "return default scheme for specific category"
+ defaults = self._default_schemes
try:
return defaults[category]
except KeyError:
@@ -1238,8 +1285,8 @@ class _CryptConfig(object):
if not self.schemes:
raise KeyError("no hash schemes configured for this "
"CryptContext instance")
- return defaults.get(None, self.schemes[0])
-
+ return defaults[None]
+
def is_deprecated_with_flag(self, scheme, category):
"is scheme deprecated under particular category?"
depmap = self.get_context_optionmap("deprecated")
@@ -1251,12 +1298,12 @@ class _CryptConfig(object):
return scheme != self.default_scheme(cat)
else:
return scheme in source
- value = test(None)
+ value = test(None) or False
if category:
alt = test(category)
if alt is not None and value != alt:
return alt, True
- return (value or False), False
+ return value, False
#===================================================================
# CryptRecord objects