N
  :   ˆl–äY>”*i?u ¸ ¸ÛWÊ˜´oÅ„i× a–ßi~”Še¶¥8 Ep/\eµ1hßÄ ?÷     """passlib.ext.django.utils - helper functions used by this plugin"""
#=============================================================================
# imports
#=============================================================================
# core
from functools import update_wrapper, wraps
import logging; log = logging.getLogger(__name__)
import sys
import weakref
from warnings import warn
# site
try:
    from django import VERSION as DJANGO_VERSION
    log.debug("found django %r installation", DJANGO_VERSION)
except ImportError:
    log.debug("django installation not found")
    DJANGO_VERSION = ()
# pkg
from passlib import exc, registry
from passlib.context import CryptContext
from passlib.exc import PasslibRuntimeWarning
from passlib.utils.compat import get_method_function, iteritems, OrderedDict, unicode
from passlib.utils.decor import memoized_property
# local
__all__ = [
    "DJANGO_VERSION",
    "MIN_DJANGO_VERSION",
    "get_preset_config",
    "get_django_hasher",
]

#: minimum version supported by passlib.ext.django
MIN_DJANGO_VERSION = (1, 8)

#=============================================================================
# default policies
#=============================================================================

# map preset names -> passlib.app attrs
_preset_map = {
    "django-1.0": "django10_context",
    "django-1.4": "django14_context",
    "django-1.6": "django16_context",
    "django-latest": "django_context",
}

def get_preset_config(name):
    """Returns configuration string for one of the preset strings
    supported by the ``PASSLIB_CONFIG`` setting.
    Currently supported presets:

    * ``"passlib-default"`` - default config used by this release of passlib.
    * ``"django-default"`` - config matching currently installed django version.
    * ``"django-latest"`` - config matching newest django version (currently same as ``"django-1.6"``).
    * ``"django-1.0"`` - config used by stock Django 1.0 - 1.3 installs
    * ``"django-1.4"`` - config used by stock Django 1.4 installs
    * ``"django-1.6"`` - config used by stock Django 1.6 installs
    """
    # TODO: add preset which includes HASHERS + PREFERRED_HASHERS,
    #       after having imported any custom hashers. e.g. "django-current"
    if name == "django-default":
        if not DJANGO_VERSION:
            raise ValueError("can't resolve django-default preset, "
                             "django not installed")
        name = "django-1.6"
    if name == "passlib-default":
        return PASSLIB_DEFAULT
    try:
        attr = _preset_map[name]
    except KeyError:
        raise ValueError("unknown preset config name: %r" % name)
    import passlib.apps
    return getattr(passlib.apps, attr).to_string()

# default context used by passlib 1.6
PASSLIB_DEFAULT = """
[passlib]

; list of schemes supported by configuration
; currently all django 1.6, 1.4, and 1.0 hashes,
; and three common modular crypt format hashes.
schemes =
    django_pbkdf2_sha256, django_pbkdf2_sha1, django_bcrypt, django_bcrypt_sha256,
    django_salted_sha1, django_salted_md5, django_des_crypt, hex_md5,
    sha512_crypt, bcrypt, phpass

; default scheme to use for new hashes
default = django_pbkdf2_sha256

; hashes using these schemes will automatically be re-hashed
; when the user logs in (currently all django 1.0 hashes)
deprecated =
    django_pbkdf2_sha1, django_salted_sha1, django_salted_md5,
    django_des_crypt, hex_md5

; sets some common options, including minimum rounds for two primary hashes.
; if a hash has less than this number of rounds, it will be re-hashed.
sha512_crypt__min_rounds = 80000
django_pbkdf2_sha256__min_rounds = 10000

; set somewhat stronger iteration counts for ``User.is_staff``
staff__sha512_crypt__default_rounds = 100000
staff__django_pbkdf2_sha256__default_rounds = 12500

; and even stronger ones for ``User.is_superuser``
superuser__sha512_crypt__default_rounds = 120000
superuser__django_pbkdf2_sha256__default_rounds = 15000
"""

#==========================