import six
diff --git a/.hgignore b/.hgignore
new file mode 100644
index 0000000..cb1c3aa
--- /dev/null
+++ b/.hgignore
@@ -0,0 +1,5 @@
+syntax: glob
+*.pyc
+dist
+MANIFEST
+documentation/_build
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..653ab52
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,19 @@
+ Copyright (c) 2010 Benjamin Peterson
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
diff --git a/MANIFEST.in b/MANIFEST.in
new file mode 100644
index 0000000..09d81fb
--- /dev/null
+++ b/MANIFEST.in
@@ -0,0 +1,4 @@
+include LICENSE
+
+recursive-include documentation *
+prune documentation/_build
diff --git a/README b/README
new file mode 100644
index 0000000..df1b868
--- /dev/null
+++ b/README
@@ -0,0 +1,12 @@
+Six is a Python 2 and 3 compatibility library.  It provides utility functions
+for smoothing over the differences between the Python versions with the goal of
+writing Python code that is compatible on both Python versions.  See the
+documentation for more information on what is provided.
+
+Six supports Python 2.4+.
+
+Online documentation is at http://packages.python.org/six/.
+
+Bugs can be reported to http://bugs.launchpad.net/python-six.
+
+Code is at http://code.launchpad.net/python-six.
diff --git a/documentation/Makefile b/documentation/Makefile
new file mode 100644
index 0000000..eebafcd
--- /dev/null
+++ b/documentation/Makefile
@@ -0,0 +1,130 @@
+# Makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line.
+SPHINXOPTS    =
+SPHINXBUILD   = sphinx-build
+PAPER         =
+BUILDDIR      = _build
+
+# Internal variables.
+PAPEROPT_a4     = -D latex_paper_size=a4
+PAPEROPT_letter = -D latex_paper_size=letter
+ALLSPHINXOPTS   = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+
+.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest
+
+help:
+	@echo "Please use \`make <target>' where <target> is one of"
+	@echo "  html       to make standalone HTML files"
+	@echo "  dirhtml    to make HTML files named index.html in directories"
+	@echo "  singlehtml to make a single large HTML file"
+	@echo "  pickle     to make pickle files"
+	@echo "  json       to make JSON files"
+	@echo "  htmlhelp   to make HTML files and a HTML help project"
+	@echo "  qthelp     to make HTML files and a qthelp project"
+	@echo "  devhelp    to make HTML files and a Devhelp project"
+	@echo "  epub       to make an epub"
+	@echo "  latex      to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
+	@echo "  latexpdf   to make LaTeX files and run them through pdflatex"
+	@echo "  text       to make text files"
+	@echo "  man        to make manual pages"
+	@echo "  changes    to make an overview of all changed/added/deprecated items"
+	@echo "  linkcheck  to check all external links for integrity"
+	@echo "  doctest    to run all doctests embedded in the documentation (if enabled)"
+
+clean:
+	-rm -rf $(BUILDDIR)/*
+
+html:
+	$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
+	@echo
+	@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
+
+dirhtml:
+	$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
+	@echo
+	@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
+
+singlehtml:
+	$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
+	@echo
+	@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
+
+pickle:
+	$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
+	@echo
+	@echo "Build finished; now you can process the pickle files."
+
+json:
+	$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
+	@echo
+	@echo "Build finished; now you can process the JSON files."
+
+htmlhelp:
+	$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
+	@echo
+	@echo "Build finished; now you can run HTML Help Workshop with the" \
+	      ".hhp project file in $(BUILDDIR)/htmlhelp."
+
+qthelp:
+	$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
+	@echo
+	@echo "Build finished; now you can run "qcollectiongenerator" with the" \
+	      ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
+	@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/six.qhcp"
+	@echo "To view the help file:"
+	@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/six.qhc"
+
+devhelp:
+	$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
+	@echo
+	@echo "Build finished."
+	@echo "To view the help file:"
+	@echo "# mkdir -p $$HOME/.local/share/devhelp/six"
+	@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/six"
+	@echo "# devhelp"
+
+epub:
+	$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
+	@echo
+	@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
+
+latex:
+	$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+	@echo
+	@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
+	@echo "Run \`make' in that directory to run these through (pdf)latex" \
+	      "(use \`make latexpdf' here to do that automatically)."
+
+latexpdf:
+	$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+	@echo "Running LaTeX files through pdflatex..."
+	make -C $(BUILDDIR)/latex all-pdf
+	@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
+
+text:
+	$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
+	@echo
+	@echo "Build finished. The text files are in $(BUILDDIR)/text."
+
+man:
+	$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
+	@echo
+	@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
+
+changes:
+	$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
+	@echo
+	@echo "The overview file is in $(BUILDDIR)/changes."
+
+linkcheck:
+	$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
+	@echo
+	@echo "Link check complete; look for any errors in the above output " \
+	      "or in $(BUILDDIR)/linkcheck/output.txt."
+
+doctest:
+	$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
+	@echo "Testing of doctests in the sources finished, look at the " \
+	      "results in $(BUILDDIR)/doctest/output.txt."
diff --git a/documentation/conf.py b/documentation/conf.py
new file mode 100644
index 0000000..7872444
--- /dev/null
+++ b/documentation/conf.py
@@ -0,0 +1,217 @@
+# -*- coding: utf-8 -*-
+#
+# six documentation build configuration file
+
+import os
+import sys
+
+# If extensions (or modules to document with autodoc) are in another directory,
+# add these directories to sys.path here. If the directory is relative to the
+# documentation root, use os.path.abspath to make it absolute, like shown here.
+#sys.path.append(os.path.abspath('.'))
+
+# -- General configuration -----------------------------------------------------
+
+# If your documentation needs a minimal Sphinx version, state it here.
+needs_sphinx = "1.0"
+
+# Add any Sphinx extension module names here, as strings. They can be extensions
+# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
+extensions = ["sphinx.ext.intersphinx"]
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ["_templates"]
+
+# The suffix of source filenames.
+source_suffix = ".rst"
+
+# The encoding of source files.
+#source_encoding = "utf-8-sig"
+
+# The master toctree document.
+master_doc = "index"
+
+# General information about the project.
+project = u"six"
+copyright = u"2010, Benjamin Peterson"
+
+sys.path.append(os.path.abspath(os.path.join(".", "..")))
+from six import __version__ as six_version
+sys.path.pop()
+
+# The version info for the project you're documenting, acts as replacement for
+# |version| and |release|, also used in various other places throughout the
+# built documents.
+#
+# The short X.Y version.
+version = six_version[:-2]
+# The full version, including alpha/beta/rc tags.
+release = six_version
+
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+#language = None
+
+# There are two options for replacing |today|: either, you set today to some
+# non-false value, then it is used:
+#today = ''
+# Else, today_fmt is used as the format for a strftime call.
+#today_fmt = '%B %d, %Y'
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+exclude_patterns = ["_build"]
+
+# The reST default role (used for this markup: `text`) to use for all documents.
+#default_role = None
+
+# If true, '()' will be appended to :func: etc. cross-reference text.
+#add_function_parentheses = True
+
+# If true, the current module name will be prepended to all description
+# unit titles (such as .. function::).
+#add_module_names = True
+
+# If true, sectionauthor and moduleauthor directives will be shown in the
+# output. They are ignored by default.
+#show_authors = False
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = "sphinx"
+
+# A list of ignored prefixes for module index sorting.
+#modindex_common_prefix = []
+
+
+# -- Options for HTML output ---------------------------------------------------
+
+# The theme to use for HTML and HTML Help pages.  See the documentation for
+# a list of builtin themes.
+html_theme = "default"
+
+# Theme options are theme-specific and customize the look and feel of a theme
+# further.  For a list of options available for each theme, see the
+# documentation.
+#html_theme_options = {}
+
+# Add any paths that contain custom themes here, relative to this directory.
+#html_theme_path = []
+
+# The name for this set of Sphinx documents.  If None, it defaults to
+# "<project> v<release> documentation".
+#html_title = None
+
+# A shorter title for the navigation bar.  Default is the same as html_title.
+#html_short_title = None
+
+# The name of an image file (relative to this directory) to place at the top
+# of the sidebar.
+#html_logo = None
+
+# The name of an image file (within the static path) to use as favicon of the
+# docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32
+# pixels large.
+#html_favicon = None
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = ["_static"]
+
+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
+# using the given strftime format.
+#html_last_updated_fmt = '%b %d, %Y'
+
+# If true, SmartyPants will be used to convert quotes and dashes to
+# typographically correct entities.
+#html_use_smartypants = True
+
+# Custom sidebar templates, maps document names to template names.
+#html_sidebars = {}
+
+# Additional templates that should be rendered to pages, maps page names to
+# template names.
+#html_additional_pages = {}
+
+# If false, no module index is generated.
+#html_domain_indices = True
+
+# If false, no index is generated.
+#html_use_index = True
+
+# If true, the index is split into individual pages for each letter.
+#html_split_index = False
+
+# If true, links to the reST sources are added to the pages.
+#html_show_sourcelink = True
+
+# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
+#html_show_sphinx = True
+
+# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
+#html_show_copyright = True
+
+# If true, an OpenSearch description file will be output, and all pages will
+# contain a <link> tag referring to it.  The value of this option must be the
+# base URL from which the finished HTML is served.
+#html_use_opensearch = ''
+
+# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml").
+#html_file_suffix = ''
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'sixdoc'
+
+
+# -- Options for LaTeX output --------------------------------------------------
+
+# The paper size ('letter' or 'a4').
+#latex_paper_size = 'letter'
+
+# The font size ('10pt', '11pt' or '12pt').
+#latex_font_size = '10pt'
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title, author, documentclass [howto/manual]).
+latex_documents = [
+  ("index", "six.tex", u"six Documentation",
+   u"Benjamin Peterson", "manual"),
+]
+
+# The name of an image file (relative to this directory) to place at the top of
+# the title page.
+#latex_logo = None
+
+# For "manual" documents, if this is true, then toplevel headings are parts,
+# not chapters.
+#latex_use_parts = False
+
+# If true, show page references after internal links.
+#latex_show_pagerefs = False
+
+# If true, show URL addresses after external links.
+#latex_show_urls = False
+
+# Additional stuff for the LaTeX preamble.
+#latex_preamble = ''
+
+# Documents to append as an appendix to all manuals.
+#latex_appendices = []
+
+# If false, no module index is generated.
+#latex_domain_indices = True
+
+
+# -- Options for manual page output --------------------------------------------
+
+# One entry per manual page. List of tuples
+# (source start file, name, description, authors, manual section).
+man_pages = [
+    ("index", "six", u"six Documentation",
+     [u"Benjamin Peterson"], 1)
+]
+
+# -- Intersphinx ---------------------------------------------------------------
+
+intersphinx_mapping = {"py2" : ("http://docs.python.org/", None),
+                       "py3" : ("http://docs.python.org/py3k/", None)}
diff --git a/documentation/index.rst b/documentation/index.rst
new file mode 100644
index 0000000..c366337
--- /dev/null
+++ b/documentation/index.rst
@@ -0,0 +1,346 @@
+Six: Python 2 and 3 Compatibility Library
+=========================================
+
+.. module:: six
+   :synopsis: Python 2 and 3 compatibility
+
+.. moduleauthor:: Benjamin Peterson <[email protected]>
+.. sectionauthor:: Benjamin Peterson <[email protected]>
+
+
+Six provides simple utilities for wrapping over differences between Python 2 and
+Python 3.
+
+Six can be downloaded on `PyPi <http://pypi.python.org/pypi/six/>`_.  Its bug
+tracker and code hosting is on `Launchpad <http://launchpad.net/python-six>`_.
+
+The name, "six", comes from the fact that 2*3 equals 6.  Why not addition?
+Multiplication is more powerful, and, anyway, "five" has already been `snatched
+away <http://codespeak.net/z3/five/>`_.
+
+
+Indices and tables
+------------------
+
+* :ref:`genindex`
+* :ref:`search`
+
+
+Package contents
+----------------
+
+.. data:: PY3
+
+   A boolean indicating if the code is running on Python 3.
+
+
+Constants
+>>>>>>>>>
+
+Six provides constants that may differ between Python versions.  Ones ending
+``_types`` are mostly useful as the second argument to ``isinstance`` or
+``issubclass``.
+
+
+.. data:: class_types
+
+   Possible class types.  In Python 2, this encompasses old-style and new-style
+   classes.  In Python 3, this is just new-styles.
+
+
+.. data:: integer_types
+
+   Possible integer types.  In Python 2, this is :func:`py2:long` and
+   :func:`py2:int`, and in Python 3, just :func:`py3:int`.
+
+
+.. data:: string_types
+
+   Possible types for text data.  This is :func:`py2:basestring` in Python 2 and
+   :func:`py3:str` in Python 3.
+
+
+.. data:: text_type
+
+   Type for representing textual data in Unicode.  This is :func:`py2:unicode`
+   in Python 2 and :func:`py3:str` in Python 3.
+
+
+.. data:: binary_type
+
+   Type for representing binary data.  This is :func:`py2:str` in Python 2 and
+   :func:`py3:bytes` in Python 3.
+
+
+.. data:: MAXSIZE
+
+   The maximum size of a container.
+
+
+Here's example usage of the module::
+
+   import six
+
+   def dispatch_types(value):
+       if isinstance(value, six.integer_types):
+           handle_integer(value)
+       elif isinstance(value, six.class_types):
+           handle_class(value)
+       elif isinstance(value, six.string_types):
+           handle_string(value)
+
+
+Object model compatibility
+>>>>>>>>>>>>>>>>>>>>>>>>>>
+
+Python 3 renamed the attributes of several intepreter data structures.  The
+following accessors are available.  Note that the recommended way to inspect
+functions and methods is the stdlib :mod:`py3:inspect` module.
+
+
+.. function:: get_unbound_function(meth)
+
+   Get the function out of unbound method *meth*.  In Python 3, unbound methods
+   don't exist, so this function just returns *meth* unchanged.  Example
+   usage::
+
+      from six import get_unbound_function
+
+      class X(object):
+          def method(self):
+              pass
+      method_function = get_unbound_function(X.method)
+
+
+.. function:: get_method_function(meth)
+
+   Get the function out of method object *meth*.
+
+
+.. function:: get_method_self(meth)
+
+   Get the ``self`` of bound method *meth*.
+
+
+.. function:: get_function_code(func)
+
+   Get the code object associated with *func*.
+
+
+.. function:: get_function_defaults(func)
+
+   Get the defaults tuple associated with *func*.
+
+
+.. function:: advance_iterator(it)
+
+   Get the next item of iterator *it*.  :exc:`py3:StopIteration` is raised if
+   the iterator is exhausted.  This is a replacement for calling ``it.next()``
+   in Python 2 and ``next(it)`` in Python 3.
+
+
+.. function:: callable(obj)
+
+   Check if *obj* can be called.
+
+
+Syntax compatibility
+>>>>>>>>>>>>>>>>>>>>
+
+These functions smooth over operations which have different syntaxes between
+Python 2 and 3.
+
+
+.. function:: exec_(code, globals=None, locals=None)
+
+   Execute *code* in the scope of *globals* and *locals*.  *code* can be a
+   string or a code object.  If *globals* or *locals* is not given, they will
+   default to the scope of the caller.  If just *globals* is given, it will also
+   be used as *locals*.
+
+
+.. function:: print_(*args, *, file=sys.stdout, end="\n", sep=" ")
+
+   Print *args* into *file*.  Each argument will be separated with *sep* and
+   *end* will be written to the file at the last.
+
+   .. note::
+
+      In Python 2, this function imitates Python 3's :func:`py3:print` by not
+      having softspace support.  If you don't know what that is, you're probably
+      ok. :)
+
+
+.. function:: reraise(exc_type, exc_value, exc_traceback=None)
+
+   Reraise an exception, possibly with a different traceback.  In the simple
+   case, ``reraise(*sys.exc_info())`` with an active exception (in an except
+   block) reraises the current exception with the last traceback.  A different
+   traceback can be specified with the *exc_traceback* parameter.
+
+
+.. function:: with_metaclass(metaclass, base=object)
+
+   Create a new class with base class *base* and metaclass *metaclass*.  This is
+   designed to be used in class declarations like this: ::
+
+      from six import with_metaclass
+
+      class Meta(type):
+          pass
+
+      class Base(object):
+          pass
+
+      class MyClass(with_metaclass(Meta, Base)):
+          pass
+
+
+Binary and text data
+>>>>>>>>>>>>>>>>>>>>
+
+Python 3 enforces the distinction between far more rigoriously than does Python
+2; binary data cannot be automatically coerced text data.  six provides the
+several functions to assist in classifying string data in all Python versions.
+
+
+.. function:: b(data)
+
+   A "fake" bytes literal.  *data* should always be a normal string literal.  In
+   Python 2, :func:`b` returns a 8-bit string.  In Python 3, *data* is encoded
+   with the latin-1 encoding to bytes.
+
+
+.. function:: u(text)
+
+   A "fake" unicode literal.  *text* should always be a normal string literal.
+   In Python 2, :func:`u` returns unicode, and in Python 3, a string.
+
+
+.. data:: StringIO
+
+   This is an fake file object for textual data.  It's an alias for
+   :class:`py2:StringIO.StringIO` in Python 2 and :class:`py3:io.StringIO` in
+   Python 3.
+
+
+.. data:: BytesIO
+
+   This is a fake file object for binary data.  In Python 2, it's an alias for
+   :class:`py2:StringIO.StringIO`, but in Python 3, it's an alias for
+   :class:`py3:io.BytesIO`.
+
+
+Renamed modules and attributes compatibility
+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+
+.. module:: six.moves
+   :synopsis: Renamed modules and attributes compatibility
+
+Python 3 reorganized the standard library and moved several functions to
+different modules.  This module provides a consistent interface to them.  For
+example, to load the module for parsing HTML on Python 2 or 3, write::
+
+   from six.moves import html_parser
+
+Similarly, to get the function to reload modules, which was moved from the
+builtin module to the ``imp`` module, use::
+
+   from six.moves import reload_module
+
+For the most part, :mod:`six.moves` aliases are the names of the modules in
+Python 3.  When the new Python 3 name is a package, the components of the name
+are separated by underscores.  For example, ``html.parser`` becomes
+``html_parser``.  In some cases where several modules have been combined, the
+Python 2 name is retained.  This is so the appropiate modules can be found when
+running on Python 2.  For example, ``BaseHTTPServer`` which is in
+``http.server`` in Python 3 is aliased as ``BaseHTTPServer``.
+
+Some modules which had two implementations have been merged in Python 3.  For
+example, ``cPickle`` no longer exists in Python 3.  It's been merged with
+``pickle``.  In these cases, fetching the fast version will load the fast one on
+Python 2 and the merged module in Python 3.
+
+
+.. note::
+
+   The :mod:`py2:urllib`, :mod:`py2:urllib2`, and :mod:`py2:urlparse` modules
+   have been combined in the :mod:`py3:urllib` package in Python 3.
+   :mod:`six.moves` doesn't not support their renaming because their members
+   have been mixed across several modules in that package.
+
+Supported renames:
+
++------------------------------+-------------------------------------+---------------------------------+
+| Name                         | Python 2 name                       | Python 3 name                   |
++==============================+=====================================+=================================+
+| ``builtins``                 | :mod:`py2:__builtin__`              | :mod:`py3:builtins`             |
++------------------------------+-------------------------------------+---------------------------------+
+| ``configparser``             | :mod:`py2:ConfigParser`             | :mod:`py3:configparser`         |
++------------------------------+-------------------------------------+---------------------------------+
+| ``copyreg``                  | :mod:`py2:copy_reg`                 | :mod:`py3:copyreg`              |
++------------------------------+-------------------------------------+---------------------------------+
+| ``cPickle``                  | :mod:`py2:cPickle`                  | :mod:`py3:pickle`               |
++------------------------------+-------------------------------------+---------------------------------+
+| ``cStringIO``                | :func:`py2:cStringIO.StringIO`      | :class:`py3:io.StringIO`        |
++------------------------------+-------------------------------------+---------------------------------+
+| ``http_cookiejar``           | :mod:`py2:cookielib`                | :mod:`py3:http.cookiejar`       |
++------------------------------+-------------------------------------+---------------------------------+
+| ``http_cookies``             | :mod:`py2:Cookie`                   | :mod:`py3:http.cookies`         |
++------------------------------+-------------------------------------+---------------------------------+
+| ``html_entities``            | :mod:`py2:htmlentitydefs`           | :mod:`py3:html.entities`        |
++------------------------------+-------------------------------------+---------------------------------+
+| ``html_parser``              | :mod:`py2:HTMLParser`               | :mod:`py3:html.parser`          |
++------------------------------+-------------------------------------+---------------------------------+
+| ``http_client``              | :mod:`py2:httplib`                  | :mod:`py3:http.client`          |
++------------------------------+-------------------------------------+---------------------------------+
+| ``BaseHTTPServer``           | :mod:`py2:BaseHTTPServer`           | :mod:`py3:http.server`          |
++------------------------------+-------------------------------------+---------------------------------+
+| ``CGIHTTPServer``            | :mod:`py2:CGIHTTPServer`            | :mod:`py3:http.server`          |
++------------------------------+-------------------------------------+---------------------------------+
+| ``SimpleHTTPServer``         | :mod:`py2:SimpleHTTPServer`         | :mod:`py3:http.server`          |
++------------------------------+-------------------------------------+---------------------------------+
+| ``queue``                    | :mod:`py2:Queue`                    | :mod:`py3:queue`                |
++------------------------------+-------------------------------------+---------------------------------+
+| ``reduce``                   | :func:`py2:reduce`                  | :func:`py3:functools.reduce`    |
++------------------------------+-------------------------------------+---------------------------------+
+| ``reload_module``            | :func:`py2:reload`                  | :func:`py3:imp.reload`          |
++------------------------------+-------------------------------------+---------------------------------+
+| ``reprlib``                  | :mod:`py2:repr`                     | :mod:`py3:reprlib`              |
++------------------------------+-------------------------------------+---------------------------------+
+| ``socketserver``             | :mod:`py2:SocketServer`             | :mod:`py3:socketserver`         |
++------------------------------+-------------------------------------+---------------------------------+
+| ``tkinter``                  | :mod:`py2:Tkinter`                  | :mod:`py3:tkinter`              |
++------------------------------+-------------------------------------+---------------------------------+
+| ``tkinter_dialog``           | :mod:`py2:Dialog`                   | :mod:`py3:tkinter.dialog`       |
++------------------------------+-------------------------------------+---------------------------------+
+| ``tkinter_filedialog``       | :mod:`py2:FileDialog`               | :mod:`py3:tkinter.FileDialog`   |
++------------------------------+-------------------------------------+---------------------------------+
+| ``tkinter_scrolledtext``     | :mod:`py2:ScrolledText`             | :mod:`py3:tkinter.scolledtext`  |
++------------------------------+-------------------------------------+---------------------------------+
+| ``tkinter_simpledialog``     | :mod:`py2:SimpleDialog`             | :mod:`py2:tkinter.simpledialog` |
++------------------------------+-------------------------------------+---------------------------------+
+| ``tkinter_tix``              | :mod:`py2:Tix`                      | :mod:`py3:tkinter.tix`          |
++------------------------------+-------------------------------------+---------------------------------+
+| ``tkinter_constants``        | :mod:`py2:Tkconstants`              | :mod:`py3:tkinter.constants`    |
++------------------------------+-------------------------------------+---------------------------------+
+| ``tkinter_dnd``              | :mod:`py2:Tkdnd`                    | :mod:`py3:tkinter.dnd`          |
++------------------------------+-------------------------------------+---------------------------------+
+| ``tkinter_colorchooser``     | :mod:`py2:tkColorChooser`           | :mod:`py3:tkinter.colorchooser` |
++------------------------------+-------------------------------------+---------------------------------+
+| ``tkinter_commondialog``     | :mod:`py2:tkCommonDialog`           | :mod:`py3:tkinter.commondialog` |
++------------------------------+-------------------------------------+---------------------------------+
+| ``tkinter_tkfiledialog``     | :mod:`py2:tkFileDialog`             | :mod:`py3:tkinter.filedialog`   |
++------------------------------+-------------------------------------+---------------------------------+
+| ``tkinter_font``             | :mod:`py2:tkFont`                   | :mod:`py3:tkinter.font`         |
++------------------------------+-------------------------------------+---------------------------------+
+| ``tkinter_messagebox``       | :mod:`py2:tkMessageBox`             | :mod:`py3:tkinter.messagebox`   |
++------------------------------+-------------------------------------+---------------------------------+
+| ``tkinter_tksimpledialog``   | :mod:`py2:tkSimpleDialog`           | :mod:`py3:tkinter.simpledialog` |
++------------------------------+-------------------------------------+---------------------------------+
+| ``urllib_robotparser``       | :mod:`py2:robotparser`              | :mod:`py3:urllib.robotparser`   |
++------------------------------+-------------------------------------+---------------------------------+
+| ``winreg``                   | :mod:`py2:_winreg`                  | :mod:`py3:winreg`               |
++------------------------------+-------------------------------------+---------------------------------+
+| ``xrange``                   | :func:`py2:xrange`                  | :func:`py3:range`               |
++------------------------------+-------------------------------------+---------------------------------+
diff --git a/setup.py b/setup.py
new file mode 100644
index 0000000..90aee09
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,27 @@
+from distutils.core import setup
+
+import six
+
+six_classifiers = [
+    "Programming Language :: Python :: 2",
+    "Programming Language :: Python :: 3",
+    "Intended Audience :: Developers",
+    "License :: OSI Approved :: MIT License",
+    "Topic :: Software Development :: Libraries",
+    "Topic :: Utilities",
+]
+
+with open("README", "r") as fp:
+    six_long_description = fp.read()
+
+
+setup(name="six",
+      version=six.__version__,
+      author="Benjamin Peterson",
+      author_email="[email protected]",
+      url="http://pypi.python.org/pypi/six/",
+      py_modules=["six"],
+      description="Python 2 and 3 compatibility utilities",
+      long_description=six_long_description,
+      classifiers=six_classifiers
+      )
diff --git a/six.py b/six.py
new file mode 100644
index 0000000..f55914b
--- /dev/null
+++ b/six.py
@@ -0,0 +1,313 @@
+"""Utilities for writing code that runs on Python 2 and 3"""
+
+import sys
+import types
+
+
+__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""")
diff --git a/test_six.py b/test_six.py
new file mode 100644
index 0000000..651ed02
--- /dev/null
+++ b/test_six.py
@@ -0,0 +1,285 @@
+import operator
+import sys
+import types
+
+import py
+
+import six
+
+
+def test_add_doc():
+    def f():
+        """Icky doc"""
+        pass
+    six._add_doc(f, """New doc""")
+    assert f.__doc__ == "New doc"
+
+
+def test_import_module():
+    from email import errors
+    m = six._import_module("email.errors")
+    assert m is errors
+
+
+def test_integer_types():
+    assert isinstance(1, six.integer_types)
+    assert isinstance(-1, six.integer_types)
+    assert isinstance(six.MAXSIZE + 23, six.integer_types)
+    assert not isinstance(.1, six.integer_types)
+
+
+def test_string_types():
+    assert isinstance("hi", six.string_types)
+    assert isinstance(six.u("hi"), six.string_types)
+    assert issubclass(six.text_type, six.string_types)
+
+
+def test_class_types():
+    class X:
+        pass
+    class Y(object):
+        pass
+    assert isinstance(X, six.class_types)
+    assert isinstance(Y, six.class_types)
+    assert not isinstance(X(), six.class_types)
+
+
+def test_text_type():
+    assert type(six.u("hi")) is six.text_type
+
+
+def test_binary_type():
+    assert type(six.b("hi")) is six.binary_type
+
+
+def test_MAXSIZE():
+    py.test.raises(OverflowError, operator.mul, [None], six.MAXSIZE + 1)
+
+
+def test_lazy():
+    if six.PY3:
+        html_name = "html.parser"
+    else:
+        html_name = "HTMLParser"
+    assert html_name not in sys.modules
+    mod = six.moves.html_parser
+    assert sys.modules[html_name] is mod
+    assert "htmlparser" not in six._MovedItems.__dict__
+
+
+def pytest_generate_tests(metafunc):
+    if "item_name" in metafunc.funcargnames:
+        for value in six._moved_attributes:
+            if value.name == "winreg" and not sys.platform.startswith("win"):
+                continue
+            metafunc.addcall({"item_name" : value.name})
+
+
+def test_move_items(item_name):
+    """Ensure that everything loads correctly."""
+    getattr(six.moves, item_name)
+
+
+def test_get_unbound_function():
+    class X(object):
+        def m(self):
+            pass
+    assert six.get_unbound_function(X.m) is X.__dict__["m"]
+
+
+def test_get_method_self():
+    class X(object):
+        def m(self):
+            pass
+    x = X()
+    assert six.get_method_self(x.m) is x
+    py.test.raises(AttributeError, six.get_method_self, 42)
+
+
+def test_get_method_function():
+    class X(object):
+        def m(self):
+            pass
+    x = X()
+    assert six.get_method_function(x.m) is X.__dict__["m"]
+    py.test.raises(AttributeError, six.get_method_function, hasattr)
+
+
+def test_get_function_code():
+    def f():
+        pass
+    assert isinstance(six.get_function_code(f), types.CodeType)
+    py.test.raises(AttributeError, six.get_function_code, hasattr)
+
+
+def test_get_function_defaults():
+    def f(x, y=3, b=4):
+        pass
+    assert six.get_function_defaults(f) == (3, 4)
+
+
+def test_advance_iterator():
+    l = [1, 2]
+    it = iter(l)
+    assert six.advance_iterator(it) == 1
+    assert six.advance_iterator(it) == 2
+    py.test.raises(StopIteration, six.advance_iterator, it)
+    py.test.raises(StopIteration, six.advance_iterator, it)
+
+
+def test_callable():
+    class X:
+        def __call__(self):
+            pass
+        def method(self):
+            pass
+    assert six.callable(X)
+    assert six.callable(X())
+    assert six.callable(test_callable)
+    assert six.callable(hasattr)
+    assert six.callable(X.method)
+    assert six.callable(X().method)
+    assert not six.callable(4)
+    assert not six.callable("string")
+
+
+if six.PY3:
+
+    def test_b():
+        data = six.b("\xff")
+        assert isinstance(data, bytes)
+        assert len(data) == 1
+        assert data == bytes([255])
+
+
+    def test_u():
+        s = six.u("hi")
+        assert isinstance(s, str)
+        assert s == "hi"
+
+else:
+
+    def test_b():
+        data = six.b("\xff")
+        assert isinstance(data, str)
+        assert len(data) == 1
+        assert data == "\xff"
+
+
+    def test_u():
+        s = six.u("hi")
+        assert isinstance(s, unicode)
+        assert s == "hi"
+
+
+def test_StringIO():
+    fp = six.StringIO()
+    fp.write(six.u("hello"))
+    assert fp.getvalue() == six.u("hello")
+
+
+def test_BytesIO():
+    fp = six.BytesIO()
+    fp.write(six.b("hello"))
+    assert fp.getvalue() == six.b("hello")
+
+
+def test_exec_():
+    def f():
+        l = []
+        six.exec_("l.append(1)")
+        assert l == [1]
+    f()
+    ns = {}
+    six.exec_("x = 42", ns)
+    assert ns["x"] == 42
+    glob = {}
+    loc = {}
+    six.exec_("global y; y = 42; x = 12", glob, loc)
+    assert glob["y"] == 42
+    assert "x" not in glob
+    assert loc["x"] == 12
+    assert "y" not in loc
+
+
+def test_reraise():
+    def get_next(tb):
+        if six.PY3:
+            return tb.tb_next.tb_next
+        else:
+            return tb.tb_next
+    e = Exception("blah")
+    try:
+        raise e
+    except Exception:
+        tp, val, tb = sys.exc_info()
+    try:
+        six.reraise(tp, val, tb)
+    except Exception:
+        tp2, value2, tb2 = sys.exc_info()
+        assert tp2 is Exception
+        assert value2 is e
+        assert tb is get_next(tb2)
+    try:
+        six.reraise(tp, val)
+    except Exception:
+        tp2, value2, tb2 = sys.exc_info()
+        assert tp2 is Exception
+        assert value2 is e
+        assert tb2 is not tb
+    try:
+        six.reraise(tp, val, tb2)
+    except Exception:
+        tp2, value2, tb3 = sys.exc_info()
+        assert tp2 is Exception
+        assert value2 is e
+        assert get_next(tb3) is tb2
+
+
+def test_print_():
+    save = sys.stdout
+    out = sys.stdout = six.moves.StringIO()
+    try:
+        six.print_("Hello,", "person!")
+    finally:
+        sys.stdout = save
+    assert out.getvalue() == "Hello, person!\n"
+    out = six.StringIO()
+    six.print_("Hello,", "person!", file=out)
+    assert out.getvalue() == "Hello, person!\n"
+    out = six.StringIO()
+    six.print_("Hello,", "person!", file=out, end="")
+    assert out.getvalue() == "Hello, person!"
+    out = six.StringIO()
+    six.print_("Hello,", "person!", file=out, sep="X")
+    assert out.getvalue() == "Hello,Xperson!\n"
+    out = six.StringIO()
+    six.print_(six.u("Hello,"), six.u("person!"), file=out)
+    result = out.getvalue()
+    assert isinstance(result, six.text_type)
+    assert result == six.u("Hello, person!\n")
+    six.print_("Hello", file=None) # This works.
+    out = six.StringIO()
+    six.print_(None, file=out)
+    assert out.getvalue() == "None\n"
+
+
+def test_print_exceptions():
+    py.test.raises(TypeError, six.print_, x=3)
+    py.test.raises(TypeError, six.print_, end=3)
+    py.test.raises(TypeError, six.print_, sep=42)
+
+
+def test_with_metaclass():
+    class Meta(type):
+        pass
+    class X(six.with_metaclass(Meta)):
+        pass
+    assert type(X) is Meta
+    assert issubclass(X, object)
+    class Base(object):
+        pass
+    class X(six.with_metaclass(Meta, Base)):
+        pass
+    assert type(X) is Meta
+    assert issubclass(X, Base)