1. Benjamin Peterson
  2. six

Source

six / six.py

"""Utilities for writing code that runs on Python 2 and 3"""

import sys
import types

__author__ = "Benjamin Peterson <benjamin@python.org>"
__version__ = "1.0b1"


# True if we are running on Python 3.
PY3 = sys.version_info[0] == 3

if PY3:
    string_types = str,
    integer_types = int,
    class_types = type,
    text_type = str
    binary_type = bytes

    MAXSIZE = sys.maxsize
else:
    string_types = basestring,
    integer_types = (int, long)
    class_types = (type, types.ClassType)
    text_type = unicode
    binary_type = str

    MAXSIZE = sys.maxint


def _add_doc(func, doc):
    """Add documentation to a function."""
    func.__doc__ = doc


def _import_module(name):
    """Import module, returning last module in string."""
    __import__(name)
    return sys.modules[name]


class _LazyDescr(object):

    def __init__(self, name):
        self.name = name

    def __get__(self, obj, tp):
        result = self._resolve()
        setattr(obj, self.name, result)
        # This is a bit ugly, but it avoids running this again.
        delattr(tp, self.name)
        return result


class _Module(_LazyDescr):

    def __init__(self, name, old, new=None):
        super(_Module, self).__init__(name)
        if PY3:
            if new is None:
                new = name
            self.mod = new
        else:
            self.mod = old

    def _resolve(self):
        return _import_module(self.mod)


class _Attribute(_LazyDescr):

    def __init__(self, name, old_mod, new_mod, old_attr=None, new_attr=None):
        super(_Attribute, self).__init__(name)
        if PY3:
            if new_mod is None:
                new_mod = name
            self.mod = new_mod
            if new_attr is None:
                if old_attr is None:
                    new_attr = name
                else:
                    new_attr = old_attr
            self.attr = new_attr
        else:
            self.mod = old_mod
            if old_attr is None:
                old_attr = name
            self.attr = old_attr

    def _resolve(self):
        module = _import_module(self.mod)
        return getattr(module, self.attr)



class _MovedItems(types.ModuleType):
    """Lazy loading of moved objects"""


_moved_attributes = [
    _Attribute("cStringIO", "cStringIO", "io", "StringIO"),
    _Attribute("reload_module", "__builtin__", "imp", "reload"),
    _Attribute("reduce", "__builtin__", "functools"),
    _Attribute("StringIO", "StringIO", "io"),
    _Attribute("xrange", "__builtin__", "builtins", "xrange", "range"),

    _Module("builtins", "__builtin__"),
    _Module("configparser", "ConfigParser"),
    _Module("copyreg", "copy_reg"),
    _Module("http_cookiejar", "cookielib", "http.cookiejar"),
    _Module("http_cookies", "Cookie", "http.cookies"),
    _Module("html_entities", "htmlentitydefs", "html.entities"),
    _Module("html_parser", "HTMLParser", "html.parser"),
    _Module("http_client", "httplib", "http.client"),
    _Module("BaseHTTPServer", "BaseHTTPServer", "http.server"),
    _Module("CGIHTTPServer", "CGIHTTPServer", "http.server"),
    _Module("SimpleHTTPServer", "SimpleHTTPServer", "http.server"),
    _Module("cPickle", "cPickle", "pickle"),
    _Module("queue", "Queue"),
    _Module("reprlib", "repr"),
    _Module("socketserver", "SocketServer"),
    _Module("tkinter", "Tkinter"),
    _Module("tkinter_dialog", "Dialog", "tkinter.dialog"),
    _Module("tkinter_filedialog", "FileDialog", "tkinter.filedialog"),
    _Module("tkinter_scrolledtext", "ScrolledText", "tkinter.scrolledtext"),
    _Module("tkinter_simpledialog", "SimpleDialog", "tkinter.simpledialog"),
    _Module("tkinter_tix", "Tix", "tkinter.tix"),
    _Module("tkinter_constants", "Tkconstants", "tkinter.constants"),
    _Module("tkinter_dnd", "Tkdnd", "tkinter.dnd"),
    _Module("tkinter_colorchooser", "tkColorChooser", "tkinter.colorchooser"),
    _Module("tkinter_commondialog", "tkCommonDialog", "tkinter.commondialog"),
    _Module("tkinter_tkfiledialog", "tkFileDialog", "tkinter.filedialog"),
    _Module("tkinter_font", "tkFont", "tkinter.font"),
    _Module("tkinter_messagebox", "tkMessageBox", "tkinter.messagebox"),
    _Module("tkinter_tksimpledialog", "tkSimpleDialog", "tkinter.simpledialog"),
    _Module("urllib_robotparser", "robotparser", "urllib.robotparser"),
    _Module("winreg", "_winreg"),
]
for attr in _moved_attributes:
    setattr(_MovedItems, attr.name, attr)
del attr

moves = sys.modules["six.moves"] = _MovedItems("moves")


if PY3:
    _meth_func = "__func__"
    _meth_self = "__self__"

    _func_code = "__code__"
    _func_defaults = "__defaults__"
else:
    _meth_func = "im_func"
    _meth_self = "im_self"

    _func_code = "func_code"
    _func_defaults = "func_defaults"


if PY3:
    def get_unbound_function(unbound):
        return unbound


    advance_iterator = next

    def callable(obj):
        return any("__call__" in klass.__dict__ for klass in type(obj).__mro__)
else:
    def get_unbound_function(unbound):
        return unbound.im_func


    def advance_iterator(it):
        return it.next()

    callable = callable
_add_doc(get_unbound_function,
         """Get the function out of a possibly unbound function""")


def get_method_function(meth):
    """Get the underlying function of a bound method."""
    return getattr(meth, _meth_func)


def get_method_self(meth):
    """Get the self of a bound method."""
    return getattr(meth, _meth_self)


def get_function_code(func):
    """Get code object of a function."""
    return getattr(func, _func_code)


def get_function_defaults(func):
    """Get defaults of a function."""
    return getattr(func, _func_defaults)


if PY3:
    def b(s):
        return s.encode("latin-1")
    def u(s):
        return s
    import io
    StringIO = io.StringIO
    BytesIO = io.BytesIO
else:
    def b(s):
        return s
    def u(s):
        return unicode(s)
    import StringIO
    StringIO = BytesIO = StringIO.StringIO
_add_doc(b, """Byte literal""")
_add_doc(u, """Text literal""")


if PY3:
    exec_ = eval("exec")


    def reraise(tp, value, tb=None):
        if value.__traceback__ is not tb:
            raise value.with_traceback(tb)
        raise value


    print_ = eval("print")


    def with_metaclass(meta, base=object):
        ns = dict(base=base, meta=meta)
        exec_("""class NewBase(base, metaclass=meta):
    pass""", ns)
        return ns["NewBase"]


else:
    def exec_(code, globs=None, locs=None):
        """Execute code in a namespace."""
        if globs is None:
            frame = sys._getframe(1)
            globs = frame.f_globals
            if locs is None:
                locs = frame.f_locals
            del frame
        elif locs is None:
            locs = globs
        exec("""exec code in globs, locs""")


    exec_("""def reraise(tp, value, tb=None):
    raise tp, value, tb
""")


    def print_(*args, **kwargs):
        """The new-style print function."""
        fp = kwargs.pop("file", sys.stdout)
        if fp is None:
            return
        def write(data):
            if not isinstance(data, basestring):
                data = str(data)
            fp.write(data)
        want_unicode = False
        sep = kwargs.pop("sep", None)
        if sep is not None:
            if isinstance(sep, unicode):
                want_unicode = True
            elif not isinstance(sep, str):
                raise TypeError("sep must be None or a string")
        end = kwargs.pop("end", None)
        if end is not None:
            if isinstance(end, unicode):
                want_unicode = True
            elif not isinstance(end, str):
                raise TypeError("end must be None or a string")
        if kwargs:
            raise TypeError("invalid keyword arguments to print()")
        if not want_unicode:
            for arg in args:
                if isinstance(arg, unicode):
                    want_unicode = True
                    break
        if want_unicode:
            newline = unicode("\n")
            space = unicode(" ")
        else:
            newline = "\n"
            space = " "
        if sep is None:
            sep = space
        if end is None:
            end = newline
        for i, arg in enumerate(args):
            if i:
                write(sep)
            write(arg)
        write(end)


    def with_metaclass(meta, base=object):
        class NewBase(base):
            __metaclass__ = meta
        return NewBase


_add_doc(reraise, """Reraise an exception.""")
_add_doc(with_metaclass, """Create a base class with a metaclass""")