# Path: werkzeug/_compat.py
# PY2 = sys.version_info[0] == 2
#     def fix_tuple_repr(obj):
#         def __repr__(self):
#     def implements_iterator(cls):
#     def implements_to_string(cls):
#     def native_string_result(func):
#         def wrapper(*args, **kwargs):
#     def implements_bool(cls):
#     def make_literal_wrapper(reference):
#     def normalize_string_tuple(tup):
#     def try_coerce_native(s):
#     def wsgi_decoding_dance(s, charset='utf-8', errors='replace'):
#     def wsgi_encoding_dance(s, charset='utf-8', errors='replace'):
#     def to_bytes(x, charset=sys.getdefaultencoding(), errors='strict'):
#     def to_native(x, charset=sys.getdefaultencoding(), errors='strict'):
#     def iter_bytes(b):
#     def reraise(tp, value, tb=None):
#     def make_literal_wrapper(reference):
#     def normalize_string_tuple(tup):
#     def wsgi_get_bytes(s):
#     def wsgi_decoding_dance(s, charset='utf-8', errors='replace'):
#     def wsgi_encoding_dance(s, charset='utf-8', errors='replace'):
#     def to_bytes(x, charset=sys.getdefaultencoding(), errors='strict'):
#     def to_native(x, charset=sys.getdefaultencoding(), errors='strict'):
# def to_unicode(x, charset=sys.getdefaultencoding(), errors='strict',
#                allow_none_charset=False):


import os
import hmac
import hashlib
import posixpath
import codecs
from struct import Struct
from random import SystemRandom
from operator import xor
from itertools import starmap
from werkzeug._compat import range_type, PY2, text_type, izip, to_bytes, \
     string_types, to_native
    """
    if _builtin_safe_str_cmp is not None:
        return _builtin_safe_str_cmp(a, b)
    if len(a) != len(b):
        return False
    rv = 0
    if isinstance(a, bytes) and isinstance(b, bytes) and not PY2:
        for x, y in izip(a, b):
            rv |= x ^ y
    else:
        for x, y in izip(a, b):
            rv |= ord(x) ^ ord(y)
    return rv == 0


def gen_salt(length):
    """Generate a random string of SALT_CHARS with specified ``length``."""
    if length <= 0:
        raise ValueError('Salt length must be positive')
    return ''.join(_sys_rng.choice(SALT_CHARS) for _ in range_type(length))


def _hash_internal(method, salt, password):
    """Internal password hash helper.  Supports plaintext without salt,
    unsalted and salted passwords.  In case salted passwords are used
    hmac is used.
    """
    if method == 'plain':
        return password, method


# Path: werkzeug/_compat.py
# PY2 = sys.version_info[0] == 2
#     def fix_tuple_repr(obj):
#         def __repr__(self):
#     def implements_iterator(cls):
#     def implements_to_string(cls):
#     def native_string_result(func):
#         def wrapper(*args, **kwargs):
#     def implements_bool(cls):
#     def make_literal_wrapper(reference):
#     def normalize_string_tuple(tup):
#     def try_coerce_native(s):
#     def wsgi_decoding_dance(s, charset='utf-8', errors='replace'):
#     def wsgi_encoding_dance(s, charset='utf-8', errors='replace'):
#     def to_bytes(x, charset=sys.getdefaultencoding(), errors='strict'):
#     def to_native(x, charset=sys.getdefaultencoding(), errors='strict'):
#     def iter_bytes(b):
#     def reraise(tp, value, tb=None):
#     def make_literal_wrapper(reference):
#     def normalize_string_tuple(tup):
#     def wsgi_get_bytes(s):
#     def wsgi_decoding_dance(s, charset='utf-8', errors='replace'):
#     def wsgi_encoding_dance(s, charset='utf-8', errors='replace'):
#     def to_bytes(x, charset=sys.getdefaultencoding(), errors='strict'):
#     def to_native(x, charset=sys.getdefaultencoding(), errors='strict'):
# def to_unicode(x, charset=sys.getdefaultencoding(), errors='strict',
#                allow_none_charset=False):


# Path: werkzeug/security.py
import os
import hmac
import hashlib
import posixpath
import codecs
from struct import Struct
from random import SystemRandom
from operator import xor
from itertools import starmap
from werkzeug._compat import range_type, PY2, text_type, izip, to_bytes, \
     string_types, to_native

    """
    if _builtin_safe_str_cmp is not None:
        return _builtin_safe_str_cmp(a, b)
    if len(a) != len(b):
        return False
    rv = 0
    if isinstance(a, bytes) and isinstance(b, bytes) and not PY2:
        for x, y in izip(a, b):
            rv |= x ^ y
    else:
        for x, y in izip(a, b):
            rv |= ord(x) ^ ord(y)
    return rv == 0


def gen_salt(length):
    """Generate a random string of SALT_CHARS with specified ``length``."""
    if length <= 0:
        raise ValueError('Salt length must be positive')
    return ''.join(_sys_rng.choice(SALT_CHARS) for _ in range_type(length))


def _hash_internal(method, salt, password):
    """Internal password hash helper.  Supports plaintext without salt,
    unsalted and salted passwords.  In case salted passwords are used
    hmac is used.
    """
    if method == 'plain':
        return password, method


    if isinstance(password, text_type):