0x0000000000000000
  $   	lm_J	4 \P.i4-eǜo ?     	"""passlib.utils -- helpers for writing password hashes"""
#=============================================================================
# imports
#=============================================================================
from passlib.utils.compat import JYTHON
# core
from binascii import b2a_base64, a2b_base64, Error as _BinAsciiError
from base64 import b64encode, b64decode
import collections
from codecs import lookup as _lookup_codec
from functools import update_wrapper
import itertools
import inspect
import logging; log = logging.getLogger(__name__)
import math
import os
import sys
import random
import re
if JYTHON: # pragma: no cover -- runtime detection
    # Jython 2.5.2 lacks stringprep module -
    # see http://bugs.jython.org/issue1758320
    try:
        import stringprep
    except ImportError:
        stringprep = None
        _stringprep_missing_reason = "not present under Jython"
else:
    import stringprep
import time
if stringprep:
    import unicodedata
import types
from warnings import warn
# site
# pkg
from passlib.utils.binary import (
    # [remove these aliases in 2.0]
    BASE64_CHARS, AB64_CHARS, HASH64_CHARS, BCRYPT_CHARS,
    Base64Engine, LazyBase64Engine, h64, h64big, bcrypt64,
    ab64_encode, ab64_decode, b64s_encode, b64s_decode
)
from passlib.utils.decor import (
    # [remove these aliases in 2.0]
    deprecated_function,
    deprecated_method,
    memoized_property,
    classproperty,
    hybrid_method,
)
from passlib.exc import ExpectedStringError
from passlib.utils.compat import (add_doc, join_bytes, join_byte_values,
                                  join_byte_elems, irange, imap, PY3, u,
                                  join_unicode, unicode, byte_elem_value, nextgetter,
                                  unicode_or_bytes_types,
                                  get_method_function, suppress_cause)
# local
__all__ = [
    # constants
    'JYTHON',
    'sys_bits',
    'unix_crypt_schemes',
    'rounds_cost_values',

    # unicode helpers
    'consteq',
    'saslprep',

    # bytes helpers
    "xor_bytes",
    "render_bytes",

    # encoding helpers
    'is_same_codec',
    'is_ascii_safe',
    'to_bytes',
    'to_unicode',
    'to_native_str',

    # host OS
    'has_crypt',
    'test_crypt',
    'safe_crypt',
    'tick',

    # randomness
    'rng',
    'getrandbytes',
    'getrandstr',
    'generate_password',

    # object type / interface tests
    'is_crypt_handler',
    'is_crypt_context',
    'has_rounds_info',
    'has_salt_info',
]

#=============================================================================
# constants
#=============================================================================

# bitsize of system architecture (32 or 64)
sys_bits = int(math.log(sys.maxsize if PY3 else sys.maxint, 2) + 1.5)

# list of hashes algs supported by crypt() on at least one OS.
# XXX: move to .registry for passlib 2.0?
unix_crypt_schemes = [
    "sha512_crypt", "sha256_crypt",
    "sha1_crypt", "bcrypt",
    "md5_crypt",
    # "bsd_nthash",
    "bsdi_crypt", "des_crypt",
    ]

# list of rounds_cost constants
rounds_cost_values = [ "linear", "log2" ]

# legacy import, will be removed in 1.8
from passlib.exc import MissingBackendError

# internal helpers
_BEMPTY = b''
_UEMPTY = u("")
_USPACE = u(" ")

# maximum password size which passlib will allow; see exc.PasswordSizeError
MAX_PASSWORD_SIZE = int(os.environ.get("PASSLIB_MAX_PASSWORD_SIZE") or 4096)

#=============================================================================
# type helpers
#=============================================================================

class SequenceMixin(object):
    """
    helper which lets result object act like a fixed-length sequence.
    subclass just needs to provide :meth:`_as_tuple()`.
    """
    def _as_tuple(self):
        raise NotImplemented("implement in subclass")

    def __repr__(self):
        return repr(self._as_tuple())

    def __getitem__(self, idx):
        return self._as_tuple()[idx]

   