# Path: taipan/_compat.py
# IS_PY26 = sys.version_info[:2] == (2, 6)
# IS_PY3 = sys.version_info[0] == 3
# class MetaclassDecorator(object):
#     def __init__(self, meta):
#     def __call__(self, cls):
# 
# Path: taipan/strings.py
# def ensure_string(s):
#     """Checks whether ``s`` is a string of characters.
#     :return: ``s`` if it is a string of characters
#     :raise TypeError: When ``s` is not a string of characters
#     """
#     if not is_string(s):
#         raise TypeError("expected a string, got %s" % type(s).__name__)
#     return s


import keyword
import re
from numbers import Number
from taipan._compat import IS_PY3, metaclass
from taipan.strings import ensure_string

    :param type_: Type to cast the ``value`` into
    :param value: Value to cast into ``type_``

    :return: ``value`` casted to ``type_``.
             If cast was unsuccessful and ``default`` was provided,
             it is returned instead.

    :raise AssertionError: When ``type_`` is not actually a Python type
    :raise TypeError: When cast was unsuccessful and no ``default`` was given
    """
    # ``type_`` not being a type would theoretically be grounds for TypeError,
    # but since that kind of exception is a valid and expected outcome here
    # in some cases, we use the closest Python has to compilation error instead
    assert isinstance(type_, type)

    # conunterintuitively, invalid conversions to numeric types
    # would raise ValueError rather than the more appropriate TypeError,
    # so we correct this inconsistency
    to_number = issubclass(type_, Number)
    exception = ValueError if to_number else TypeError

    try:
        return type_(value)
    except exception as e:
        if default is ABSENT:
            if to_number:
                # since Python 3 chains exceptions, we can supply slightly
                # more relevant error message while still retaining
                # the original information of ValueError as the cause

# Path: taipan/_compat.py
# IS_PY26 = sys.version_info[:2] == (2, 6)
# IS_PY3 = sys.version_info[0] == 3
# class MetaclassDecorator(object):
#     def __init__(self, meta):
#     def __call__(self, cls):
# 
# Path: taipan/strings.py
# def ensure_string(s):
#     """Checks whether ``s`` is a string of characters.
#     :return: ``s`` if it is a string of characters
#     :raise TypeError: When ``s` is not a string of characters
#     """
#     if not is_string(s):
#         raise TypeError("expected a string, got %s" % type(s).__name__)
#     return s


# Path: taipan/lang.py
import keyword
import re
from numbers import Number
from taipan._compat import IS_PY3, metaclass
from taipan.strings import ensure_string


    :param type_: Type to cast the ``value`` into
    :param value: Value to cast into ``type_``

    :return: ``value`` casted to ``type_``.
             If cast was unsuccessful and ``default`` was provided,
             it is returned instead.

    :raise AssertionError: When ``type_`` is not actually a Python type
    :raise TypeError: When cast was unsuccessful and no ``default`` was given
    """
    # ``type_`` not being a type would theoretically be grounds for TypeError,
    # but since that kind of exception is a valid and expected outcome here
    # in some cases, we use the closest Python has to compilation error instead
    assert isinstance(type_, type)

    # conunterintuitively, invalid conversions to numeric types
    # would raise ValueError rather than the more appropriate TypeError,
    # so we correct this inconsistency
    to_number = issubclass(type_, Number)
    exception = ValueError if to_number else TypeError

    try:
        return type_(value)
    except exception as e:
        if default is ABSENT:
            if to_number:
                # since Python 3 chains exceptions, we can supply slightly
                # more relevant error message while still retaining
                # the original information of ValueError as the cause

                msg = ("cannot convert %r to %r" % (value, type_) if IS_PY3