import sys

PYTHON2 = (sys.version_info < (3,))
PYTHON27 = (sys.version_info >= (2, 7))
PYTHON3 = (sys.version_info >= (3,))
PYTHON33 = (sys.version_info >= (3, 3))
PYTHON34 = (sys.version_info >= (3, 4))

try:
    # Check if the patch to test Python without its peephole has been
    # applied
    PyCF_DISABLE_PEEPHOLE = 0x1000
    compile("1+1", "<ast>", "exec", PyCF_DISABLE_PEEPHOLE)
except ValueError:
    # No worry, the patch is optionnal, even for unit tests
    PyCF_DISABLE_PEEPHOLE = 0

_SINGLETONS = set(id(obj) for obj in (None, True, False))
if PYTHON3:
    BYTES_TYPE = bytes
    UNICODE_TYPE = str
    def u(text):
        return text
    def b(text):
        return text.encode('latin1')
else:
    BYTES_TYPE = str
    UNICODE_TYPE = unicode
    def u(text):
        return unicode(text, "unicode_escape")
    def b(text):
        return text
NATIVE_STR = str

NONE_TYPE = type(None)
STR_TYPES = (BYTES_TYPE, UNICODE_TYPE)
if PYTHON3:
    INT_TYPES = (int,)
else:
    INT_TYPES = (int, long)
FLOAT_TYPES = INT_TYPES + (float,)
COMPLEX_TYPES = FLOAT_TYPES + (complex,)

IMMUTABLE_TYPES = COMPLEX_TYPES + STR_TYPES + (bool, NONE_TYPE)
IMMUTABLE_ITERABLE_TYPES = STR_TYPES + (tuple, frozenset)
ITERABLE_TYPES = IMMUTABLE_ITERABLE_TYPES + (set, list)

def is_singleton(config, value):
    return id(value) in _SINGLETONS

def is_immutable(value):
    obj_type = type(value)
    if obj_type in IMMUTABLE_TYPES:
        return True
    if obj_type in IMMUTABLE_ITERABLE_TYPES:
        return all(is_immutable(item) for item in value)
    return False

def is_bytes_ascii(data):
    try:
        data.decode("ascii", "strict")
    except UnicodeDecodeError:
        return False
    else:
        return True

def is_unicode_ascii(data):
    try:
        data.encode("ascii", "strict")
    except UnicodeEncodeError:
        return False
    else:
        return True

