diff --git a/.authors b/.authors
new file mode 100644
index 0000000..697b7ae
--- /dev/null
+++ b/.authors
@@ -0,0 +1,4 @@
+embray = Erik M. Bray <embray@stsci.edu>
+sienkiew = Mark Sienkiewicz <sienkiew@stsci.edu>
+sontag = Chris Sontag <sontag@stsci.edu>
+iraf = iraf <iraf@stsci.edu>
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..24f0fdd
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,27 @@
+# Compiled files
+*.py[co]
+*.a
+*.o
+*.so
+
+# Sphinx
+_build
+
+# Packages/installer info
+*.egg
+*.egg-info
+dist
+build
+eggs
+parts
+bin
+var
+sdist
+develop-eggs
+.installed.cfg
+
+# Other
+.tox
+.*.swp
+.coverage
+cover
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..dcc33ac
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,8 @@
+language: python
+python:
+  - "3.4"
+  - "3.3"
+  - "3.2"
+  - "2.7"
+  - "2.6"
+script: python setup.py test
diff --git a/CHANGES.rst b/CHANGES.rst
index 8d5673a..99277de 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -2,6 +2,12 @@ Changes
 =========
 
 
+0.2.13 (unreleased)
+-------------------
+
+- Nothing changed yet.
+
+
 0.2.12 (2015-07-16)
 -------------------
 
diff --git a/PKG-INFO b/PKG-INFO
deleted file mode 100644
index c665114..0000000
--- a/PKG-INFO
+++ /dev/null
@@ -1,394 +0,0 @@
-Metadata-Version: 1.1
-Name: d2to1
-Version: 0.2.12
-Summary: Allows using distutils2-like setup.cfg files for a package's metadata with a distribute/setuptools setup.py
-Home-page: http://pypi.python.org/pypi/d2to1
-Author: Erik M. Bray
-Author-email: embray@stsci.edu
-License: UNKNOWN
-Description: Introduction
-        ==============
-        .. image:: https://travis-ci.org/embray/d2to1.png?branch=master
-           :alt: travis build status
-           :target: https://travis-ci.org/embray/d2to1
-        
-        d2to1 (the 'd' is for 'distutils') allows using distutils2-like setup.cfg files
-        for a package's metadata with a distribute/setuptools setup.py script.  It
-        works by providing a distutils2-formatted setup.cfg file containing all of a
-        package's metadata, and a very minimal setup.py which will slurp its arguments
-        from the setup.cfg.
-        
-        Note: distutils2 has been merged into the CPython standard library, where it is
-        now known as 'packaging'.  This project was started before that change was
-        finalized.  So all references to distutils2 should also be assumed to refer to
-        packaging.
-        
-        Rationale
-        ===========
-        I'm currently in the progress of redoing the packaging of a sizeable number of
-        projects.  I wanted to use distutils2-like setup.cfg files for all these
-        projects, as they will hopefully be the future, and I much prefer them overall
-        to using an executable setup.py.  So forward-support for distutils2 is
-        appealing both as future-proofing, and simply the aesthetics of using a flat text file to describe a project's metadata.
-        
-        However, I did not want any of these projects to require distutils2 for
-        installation yet--it is too unstable, and not widely installed.  So projects
-        should still be installable using the familiar `./setup.py install`, for
-        example.  Furthermore, not all use cases required by some of the packages I
-        support are fully supported by distutils2 yet.  Hopefully they will be
-        eventually, either through the distutils2 core or through extensions.  But in
-        the meantime d2to1 will try to keep up with the state of the art and "best
-        practices" for distutils2 distributions, while adding support in areas that
-        it's lacking.
-        
-        Usage
-        =======
-        d2to1 requires a distribution to use distribute or setuptools.  Your
-        distribution must include a distutils2-like setup.cfg file, and a minimal
-        setup.py script.  For details on writing the setup.cfg, see the `distutils2
-        documentation`_.  A simple sample can be found in d2to1's own setup.cfg (it
-        uses its own machinery to install itself)::
-        
-            [metadata]
-            name = d2to1
-            version = 0.2.12
-            author = Erik M. Bray
-            author-email = embray@stsci.edu
-            summary = Allows using distutils2-like setup.cfg files for a package's metadata with a distribute/setuptools setup.py
-            description-file =
-                README.rst
-                CHANGES.rst
-            home-page = http://pypi.python.org/pypi/d2to1
-            requires-dist = setuptools
-            classifier = 
-                Development Status :: 5 - Production/Stable
-                Environment :: Plugins
-                Framework :: Setuptools Plugin
-                Intended Audience :: Developers
-                License :: OSI Approved :: BSD License
-                Operating System :: OS Independent
-                Programming Language :: Python
-                Programming Language :: Python :: 3
-                Topic :: Software Development :: Build Tools
-                Topic :: Software Development :: Libraries :: Python Modules
-                Topic :: System :: Archiving :: Packaging
-        
-            [files]
-            packages =
-                d2to1
-                d2to1.extern
-            extra_files =
-                CHANGES.rst
-                LICENSE
-                ez_setup.py
-        
-            [backwards_compat]
-            zip-safe = False
-            tests-require = nose
-        
-            [entry_points]
-            distutils.setup_keywords = 
-                d2to1 = d2to1.core:d2to1
-            zest.releaser.prereleaser.middle = 
-                d2_version = d2to1.zestreleaser:prereleaser_middle
-            zest.releaser.postreleaser.middle = 
-                d2_version = d2to1.zestreleaser:postreleaser_middle
-        
-        The minimal setup.py should look something like this::
-        
-         #!/usr/bin/env python
-        
-         try:
-             from setuptools import setup
-         except ImportError:
-             from distribute_setup import use_setuptools
-             use_setuptools()
-             from setuptools import setup
-        
-         setup(
-             setup_requires=['d2to1'],
-             d2to1=True
-         )
-        
-        Note that it's important to specify d2to1=True or else the d2to1 functionality
-        will not be enabled.  It is also possible to set d2to1='some_file.cfg' to
-        specify the (relative) path of the setup.cfg file to use.  But in general this
-        functionality should not be necessary.
-        
-        It should also work fine if additional arguments are passed to `setup()`,
-        but it should be noted that they will be clobbered by any options in the
-        setup.cfg file.
-        
-        Caveats
-        =======
-        - The requires-dist option in setup.cfg is implemented through the
-          distribute/setuptools install_requires option, rather than the broken
-          "requires" keyword in normal distutils.
-        - Not all features of distutils2 are supported yet.  If something doesn't seem
-          to be working, it's probably not implemented yet.
-        - Does not support distutils2 resources, and probably won't since it relies
-          heavily on the sysconfig module only available in Python 3.2 and up.  This is
-          one area in which d2to1 should really be seen as a transitional tool.  I
-          don't really want to include a backport like distutils2 does.  In the
-          meantime, package_data and data_files may still be used under the [files]
-          section of setup.cfg.
-        
-        .. _distutils2 documentation: http://alexis.notmyidea.org/distutils2/setupcfg.html
-        
-        Changes
-        =========
-        
-        
-        0.2.12 (2015-07-16)
-        -------------------
-        
-        - Fixed a corner case where depending on the order of events when installing
-          multiple packages (i.e. when installing packages with dependencies, some
-          of which might also use d2to1) we would end up calling the incorrect
-          Distribution class (the patched version from setuptools, where d2to1
-          needs to get to the unpatched version from distutils for some cases).
-        
-        - Upgraded bundled copy of the ``six`` module to the current version
-          (1.9.0).  This fixes incompatibility between d2to1 and other packages
-          that import different versions of ``six`` during their setup (the older
-          version of ``six`` had a habit of fighting with other ``six`` instances
-          over ``sys.modules``, which is fixed in newer versions).
-        
-        - Upgraded to latest ``ez_setup.py`` so that the most up to date version
-          of setuptools will be correctly bootstrapped in the rare cases that it
-          is needed.
-        
-        - Included some miscellaneous hacks to keep d2to1 working, nominally, with
-          Python 2.5 despite the broad move away from Python 2.5 support in the
-          Python community.  The d2to1 v0.2.x releases will be the last to continue
-          Python 2.5 support, given that testing it has become more difficult (and
-          the overhead is probably no longer worth it).
-        
-        
-        0.2.11 (2013-08-29)
-        -------------------
-        
-        - Replaced ``distribute_setup.py`` with ``ez_setup.py`` in order to bootstrap
-          with modern setuptools when necessary.
-        
-        - Fixed a couple minor Python 3-specific issues. In particular the
-          ``data_files`` option could be passed to ``setup()`` as a ``dict_items``
-          object instead of a ``list`` which is what would normally be expected.
-        
-        - Added a tox.ini (frankly I thought there already was one).
-        
-        
-        0.2.10 (2013-04-10)
-        -------------------
-        
-        - Added support for the ``setup-requires-dist`` option in the ``[metadata]``
-          section of setup.cfg.  This is analogous to the Setup-Requires-Dist metadata
-          field supported by PEP-426 and uses the ``setup_requires`` argument to
-          setuptools' ``setup()`` to implement it.
-        
-        - Added support for the ``dependency_links`` and ``include_package_data``
-          arguments to setuptools' ``setup()`` in the ``[backwards_compat]`` section of
-          setup.cfg.
-        
-        - When a setup_hook calls sys.exit() don't show a traceback for the
-          SystemExit exception.
-        
-        - Fixed a bug in the exception formatting when exceptions occur in setup.cfg
-          handling.
-        
-        
-        0.2.9 (2013-03-05)
-        ------------------
-        
-        - Fixed a bug in the extra-files supported added in 0.2.8.  Makes sure that
-          monkey-patches can't be installed more than once and that the log
-          reference is properly encapsulated.
-        
-        
-        0.2.8 (2013-03-05)
-        ------------------
-        
-        - Improved handling of packages where the packages_root option is set. That is,
-          the Python package is not directly in the root of the source tree, but is in
-          some sub-directory.  Now the packages_root directory is prepended to
-          sys.path while processing the setup.cfg and running setup hooks.
-        
-        - Added support for the Keywords metadata field via the keywords option in the
-          ``[metadata]`` section of setup.cfg.
-        
-        - Fixed a missing import that caused a misleading exception when setup.cfg is
-          missing.
-        
-        - Upgraded the shipped distribute_setup.py to the latest for distribute 0.6.28
-        
-        - Added a few basic functional tests, along with an infrastructure to add more
-          as needed.  They can be run with nose and possibly with py.test though the
-          latter hasn't been tested.
-        
-        - Improved hook imports to work better with namespace packages.
-        
-        - Added support for the extra_files option of the ``[files]`` section in
-          setup.cfg.  This was a feature from distutils2 that provided an alternative
-          to MANIFEST.in for including additional files in source distributions (it
-          does not yet support wildcard patterns but maybe it should?)
-        
-        - Added support for the tests_require setup argument from setuptools via
-          the [backwards_compat] section in setup.cfg.
-        
-        - Supports Python 3 natively without 2to3.  This makes Python 3 testing of
-          d2to1 easier to support.
-        
-        
-        0.2.7 (2012-02-20)
-        ------------------
-        
-        - If no extension modules or entry points are defined in the setup.cfg, don't
-          clobber any extension modules/entry points that may be defined in setup.py.
-        
-        
-        0.2.6 (2012-02-17)
-        ------------------
-        
-        - Added support for setuptools entry points in an ``[entry_points]`` section of
-          setup.cfg--this is just for backwards-compatibility purposes, as
-          packaging/distutils2 does not yet have a standard replacement for the entry
-          points system.
-        
-        - Added a [backwards_compat] section for setup.cfg for other options that are
-          supported by setuptools/distribute, but that aren't part of the distutils2
-          standard.  So far the only options supported here are zip_safe and use_2to3.
-          (Note: packaging does support a use-2to3 option to the build command, but if
-          we tried to use that, distutils would not recognize it as a valid build
-          option.)
-        
-        - Added support for the new (and presumably final) extension section format
-          used by packaging.  In this format, extensions should be specified in config
-          sections of the format ``[extension: ext_mod_name]``, where any whitespace is
-          optional.  The old format used an ``=`` instead of ``:`` and is still
-          supported, but should be considered deprecated.
-        
-        - Added support for the new syntax used by packaging for the package_data
-          option (which is deprecated in packaging in favor of the resources system,
-          but still supported).  The new syntax is like::
-        
-              package_data =
-                  packagename = pattern1 pattern2 pattern3
-                  packagename.subpack = 
-                      pattern1
-                      pattern2
-                      pattern3
-        
-          That is, after ``package_data =``, give the name of a package, followed by
-          an ``=``, followed by any number of whitespace separated wildcard patterns (or
-          actual filenames relative to the package).  Under this scheme, whitespace is
-          not allowed in the patterns themselves.
-        
-        
-        0.2.5 (2011-07-21)
-        ------------------
-        
-        - Made the call to pkg_resources.get_distribution() to set __version__ more
-          robust, so that it doesn't fail on, for example, VersionConflict errors
-        
-        
-        0.2.4 (2011-07-05)
-        ------------------
-        
-        - Fixed some bugs with installation on Python 3
-        
-        
-        0.2.3 (2011-06-23)
-        ------------------
-        
-        - Renamed 'setup_hook' to 'setup_hooks' as is now the case in the packaging
-          module.  Added support for multiple setup_hooks
-        
-        
-        0.2.2 (2011-06-15)
-        ------------------
-        
-        - Fixed a bug in DefaultGetDict where it didn't actually save the returned
-          default in the dictionary--so any command options would get lost
-        - Fixed a KeyError when the distribution does not have any custom commands
-          specified
-        
-        
-        0.2.1 (2011-06-15)
-        ------------------
-        
-        - Reimplemented command hooks without monkey-patching and more reliably in
-          general (though it's still a flaming hack).  The previous monkey patch-based
-          solution would break if d2to1 were entered multiple times, which could happen
-          in some scenarios
-        
-        
-        0.2.0 (2011-06-14)
-        ------------------
-        
-        - Version bump to start using micro-version numbers for bug fixes only, now
-          that the my primary feature goals are complete
-        
-        
-        0.1.5 (2011-06-02)
-        ------------------
-        
-        - Adds support for the data_files option under [files].  Though this is
-          considered deprecated and may go away at some point, it can be useful in the
-          absence of resources support
-        - Adds support for command pre/post-hooks.  Warning: this monkey-patches
-          distutils.dist.Distribution a little bit... :(
-        - Adds (slightly naive) support for PEP 345-style version specifiers in
-          requires-dist (environment markers not supported yet)
-        - Fixed a bug where not enough newlines were inserted between description files
-        
-        
-        0.1.4 (2011-05-24)
-        ------------------
-        
-        - Adds support for custom command classes specified in the 'commands' option
-          under the [global] section in setup.cfg
-        - Adds preliminary support for custom compilers specified in the 'compilers'
-          option under the [global] section in setup.cfg.  This functionality doesn't
-          exist in distutils/setuptools/distribute, so adding support for it is a
-          flaming hack.  It hasn't really been tested beyond seeing that the custom
-          compilers come up in `setup.py build_ext --help-compiler`, so any real-world
-          testing of this feature would be appreciated
-        
-        
-        0.1.3 (2011-04-20)
-        ------------------
-        
-        - Adds zest.releaser entry points for updating the version number in a
-          setup.cfg file; only useful if you use zest.releaser--otherwise harmless
-          (might eventually move this functionality out into a separate product)
-        - Though version 0.1.2 worked in Python3, use_2to3 wasn't added to the setup.py
-          so 2to3 had to be run manually
-        - Fixed a crash on projects that don't have a description-file option
-        
-        0.1.2 (2011-04-13)
-        ------------------
-        
-        - Fixed the self-installation--it did not work if a d2to1 version was not
-          already installed, due to the use of `pkg_resources.require()`
-        - Adds nominal Python3 support
-        - Fixes the 'classifier' option in setup.cfg
-        
-        0.1.1 (2011-04-12)
-        ------------------
-        
-        - Fixed an unhelpful error message when a setup_hook fails to import
-        - Made d2to1 able to use its own machinery to install itself
-        
-        
-Platform: UNKNOWN
-Classifier: Development Status :: 5 - Production/Stable
-Classifier: Environment :: Plugins
-Classifier: Framework :: Setuptools Plugin
-Classifier: Intended Audience :: Developers
-Classifier: License :: OSI Approved :: BSD License
-Classifier: Operating System :: OS Independent
-Classifier: Programming Language :: Python
-Classifier: Programming Language :: Python :: 3
-Classifier: Topic :: Software Development :: Build Tools
-Classifier: Topic :: Software Development :: Libraries :: Python Modules
-Classifier: Topic :: System :: Archiving :: Packaging
diff --git a/d2to1.egg-info/PKG-INFO b/d2to1.egg-info/PKG-INFO
deleted file mode 100644
index c665114..0000000
--- a/d2to1.egg-info/PKG-INFO
+++ /dev/null
@@ -1,394 +0,0 @@
-Metadata-Version: 1.1
-Name: d2to1
-Version: 0.2.12
-Summary: Allows using distutils2-like setup.cfg files for a package's metadata with a distribute/setuptools setup.py
-Home-page: http://pypi.python.org/pypi/d2to1
-Author: Erik M. Bray
-Author-email: embray@stsci.edu
-License: UNKNOWN
-Description: Introduction
-        ==============
-        .. image:: https://travis-ci.org/embray/d2to1.png?branch=master
-           :alt: travis build status
-           :target: https://travis-ci.org/embray/d2to1
-        
-        d2to1 (the 'd' is for 'distutils') allows using distutils2-like setup.cfg files
-        for a package's metadata with a distribute/setuptools setup.py script.  It
-        works by providing a distutils2-formatted setup.cfg file containing all of a
-        package's metadata, and a very minimal setup.py which will slurp its arguments
-        from the setup.cfg.
-        
-        Note: distutils2 has been merged into the CPython standard library, where it is
-        now known as 'packaging'.  This project was started before that change was
-        finalized.  So all references to distutils2 should also be assumed to refer to
-        packaging.
-        
-        Rationale
-        ===========
-        I'm currently in the progress of redoing the packaging of a sizeable number of
-        projects.  I wanted to use distutils2-like setup.cfg files for all these
-        projects, as they will hopefully be the future, and I much prefer them overall
-        to using an executable setup.py.  So forward-support for distutils2 is
-        appealing both as future-proofing, and simply the aesthetics of using a flat text file to describe a project's metadata.
-        
-        However, I did not want any of these projects to require distutils2 for
-        installation yet--it is too unstable, and not widely installed.  So projects
-        should still be installable using the familiar `./setup.py install`, for
-        example.  Furthermore, not all use cases required by some of the packages I
-        support are fully supported by distutils2 yet.  Hopefully they will be
-        eventually, either through the distutils2 core or through extensions.  But in
-        the meantime d2to1 will try to keep up with the state of the art and "best
-        practices" for distutils2 distributions, while adding support in areas that
-        it's lacking.
-        
-        Usage
-        =======
-        d2to1 requires a distribution to use distribute or setuptools.  Your
-        distribution must include a distutils2-like setup.cfg file, and a minimal
-        setup.py script.  For details on writing the setup.cfg, see the `distutils2
-        documentation`_.  A simple sample can be found in d2to1's own setup.cfg (it
-        uses its own machinery to install itself)::
-        
-            [metadata]
-            name = d2to1
-            version = 0.2.12
-            author = Erik M. Bray
-            author-email = embray@stsci.edu
-            summary = Allows using distutils2-like setup.cfg files for a package's metadata with a distribute/setuptools setup.py
-            description-file =
-                README.rst
-                CHANGES.rst
-            home-page = http://pypi.python.org/pypi/d2to1
-            requires-dist = setuptools
-            classifier = 
-                Development Status :: 5 - Production/Stable
-                Environment :: Plugins
-                Framework :: Setuptools Plugin
-                Intended Audience :: Developers
-                License :: OSI Approved :: BSD License
-                Operating System :: OS Independent
-                Programming Language :: Python
-                Programming Language :: Python :: 3
-                Topic :: Software Development :: Build Tools
-                Topic :: Software Development :: Libraries :: Python Modules
-                Topic :: System :: Archiving :: Packaging
-        
-            [files]
-            packages =
-                d2to1
-                d2to1.extern
-            extra_files =
-                CHANGES.rst
-                LICENSE
-                ez_setup.py
-        
-            [backwards_compat]
-            zip-safe = False
-            tests-require = nose
-        
-            [entry_points]
-            distutils.setup_keywords = 
-                d2to1 = d2to1.core:d2to1
-            zest.releaser.prereleaser.middle = 
-                d2_version = d2to1.zestreleaser:prereleaser_middle
-            zest.releaser.postreleaser.middle = 
-                d2_version = d2to1.zestreleaser:postreleaser_middle
-        
-        The minimal setup.py should look something like this::
-        
-         #!/usr/bin/env python
-        
-         try:
-             from setuptools import setup
-         except ImportError:
-             from distribute_setup import use_setuptools
-             use_setuptools()
-             from setuptools import setup
-        
-         setup(
-             setup_requires=['d2to1'],
-             d2to1=True
-         )
-        
-        Note that it's important to specify d2to1=True or else the d2to1 functionality
-        will not be enabled.  It is also possible to set d2to1='some_file.cfg' to
-        specify the (relative) path of the setup.cfg file to use.  But in general this
-        functionality should not be necessary.
-        
-        It should also work fine if additional arguments are passed to `setup()`,
-        but it should be noted that they will be clobbered by any options in the
-        setup.cfg file.
-        
-        Caveats
-        =======
-        - The requires-dist option in setup.cfg is implemented through the
-          distribute/setuptools install_requires option, rather than the broken
-          "requires" keyword in normal distutils.
-        - Not all features of distutils2 are supported yet.  If something doesn't seem
-          to be working, it's probably not implemented yet.
-        - Does not support distutils2 resources, and probably won't since it relies
-          heavily on the sysconfig module only available in Python 3.2 and up.  This is
-          one area in which d2to1 should really be seen as a transitional tool.  I
-          don't really want to include a backport like distutils2 does.  In the
-          meantime, package_data and data_files may still be used under the [files]
-          section of setup.cfg.
-        
-        .. _distutils2 documentation: http://alexis.notmyidea.org/distutils2/setupcfg.html
-        
-        Changes
-        =========
-        
-        
-        0.2.12 (2015-07-16)
-        -------------------
-        
-        - Fixed a corner case where depending on the order of events when installing
-          multiple packages (i.e. when installing packages with dependencies, some
-          of which might also use d2to1) we would end up calling the incorrect
-          Distribution class (the patched version from setuptools, where d2to1
-          needs to get to the unpatched version from distutils for some cases).
-        
-        - Upgraded bundled copy of the ``six`` module to the current version
-          (1.9.0).  This fixes incompatibility between d2to1 and other packages
-          that import different versions of ``six`` during their setup (the older
-          version of ``six`` had a habit of fighting with other ``six`` instances
-          over ``sys.modules``, which is fixed in newer versions).
-        
-        - Upgraded to latest ``ez_setup.py`` so that the most up to date version
-          of setuptools will be correctly bootstrapped in the rare cases that it
-          is needed.
-        
-        - Included some miscellaneous hacks to keep d2to1 working, nominally, with
-          Python 2.5 despite the broad move away from Python 2.5 support in the
-          Python community.  The d2to1 v0.2.x releases will be the last to continue
-          Python 2.5 support, given that testing it has become more difficult (and
-          the overhead is probably no longer worth it).
-        
-        
-        0.2.11 (2013-08-29)
-        -------------------
-        
-        - Replaced ``distribute_setup.py`` with ``ez_setup.py`` in order to bootstrap
-          with modern setuptools when necessary.
-        
-        - Fixed a couple minor Python 3-specific issues. In particular the
-          ``data_files`` option could be passed to ``setup()`` as a ``dict_items``
-          object instead of a ``list`` which is what would normally be expected.
-        
-        - Added a tox.ini (frankly I thought there already was one).
-        
-        
-        0.2.10 (2013-04-10)
-        -------------------
-        
-        - Added support for the ``setup-requires-dist`` option in the ``[metadata]``
-          section of setup.cfg.  This is analogous to the Setup-Requires-Dist metadata
-          field supported by PEP-426 and uses the ``setup_requires`` argument to
-          setuptools' ``setup()`` to implement it.
-        
-        - Added support for the ``dependency_links`` and ``include_package_data``
-          arguments to setuptools' ``setup()`` in the ``[backwards_compat]`` section of
-          setup.cfg.
-        
-        - When a setup_hook calls sys.exit() don't show a traceback for the
-          SystemExit exception.
-        
-        - Fixed a bug in the exception formatting when exceptions occur in setup.cfg
-          handling.
-        
-        
-        0.2.9 (2013-03-05)
-        ------------------
-        
-        - Fixed a bug in the extra-files supported added in 0.2.8.  Makes sure that
-          monkey-patches can't be installed more than once and that the log
-          reference is properly encapsulated.
-        
-        
-        0.2.8 (2013-03-05)
-        ------------------
-        
-        - Improved handling of packages where the packages_root option is set. That is,
-          the Python package is not directly in the root of the source tree, but is in
-          some sub-directory.  Now the packages_root directory is prepended to
-          sys.path while processing the setup.cfg and running setup hooks.
-        
-        - Added support for the Keywords metadata field via the keywords option in the
-          ``[metadata]`` section of setup.cfg.
-        
-        - Fixed a missing import that caused a misleading exception when setup.cfg is
-          missing.
-        
-        - Upgraded the shipped distribute_setup.py to the latest for distribute 0.6.28
-        
-        - Added a few basic functional tests, along with an infrastructure to add more
-          as needed.  They can be run with nose and possibly with py.test though the
-          latter hasn't been tested.
-        
-        - Improved hook imports to work better with namespace packages.
-        
-        - Added support for the extra_files option of the ``[files]`` section in
-          setup.cfg.  This was a feature from distutils2 that provided an alternative
-          to MANIFEST.in for including additional files in source distributions (it
-          does not yet support wildcard patterns but maybe it should?)
-        
-        - Added support for the tests_require setup argument from setuptools via
-          the [backwards_compat] section in setup.cfg.
-        
-        - Supports Python 3 natively without 2to3.  This makes Python 3 testing of
-          d2to1 easier to support.
-        
-        
-        0.2.7 (2012-02-20)
-        ------------------
-        
-        - If no extension modules or entry points are defined in the setup.cfg, don't
-          clobber any extension modules/entry points that may be defined in setup.py.
-        
-        
-        0.2.6 (2012-02-17)
-        ------------------
-        
-        - Added support for setuptools entry points in an ``[entry_points]`` section of
-          setup.cfg--this is just for backwards-compatibility purposes, as
-          packaging/distutils2 does not yet have a standard replacement for the entry
-          points system.
-        
-        - Added a [backwards_compat] section for setup.cfg for other options that are
-          supported by setuptools/distribute, but that aren't part of the distutils2
-          standard.  So far the only options supported here are zip_safe and use_2to3.
-          (Note: packaging does support a use-2to3 option to the build command, but if
-          we tried to use that, distutils would not recognize it as a valid build
-          option.)
-        
-        - Added support for the new (and presumably final) extension section format
-          used by packaging.  In this format, extensions should be specified in config
-          sections of the format ``[extension: ext_mod_name]``, where any whitespace is
-          optional.  The old format used an ``=`` instead of ``:`` and is still
-          supported, but should be considered deprecated.
-        
-        - Added support for the new syntax used by packaging for the package_data
-          option (which is deprecated in packaging in favor of the resources system,
-          but still supported).  The new syntax is like::
-        
-              package_data =
-                  packagename = pattern1 pattern2 pattern3
-                  packagename.subpack = 
-                      pattern1
-                      pattern2
-                      pattern3
-        
-          That is, after ``package_data =``, give the name of a package, followed by
-          an ``=``, followed by any number of whitespace separated wildcard patterns (or
-          actual filenames relative to the package).  Under this scheme, whitespace is
-          not allowed in the patterns themselves.
-        
-        
-        0.2.5 (2011-07-21)
-        ------------------
-        
-        - Made the call to pkg_resources.get_distribution() to set __version__ more
-          robust, so that it doesn't fail on, for example, VersionConflict errors
-        
-        
-        0.2.4 (2011-07-05)
-        ------------------
-        
-        - Fixed some bugs with installation on Python 3
-        
-        
-        0.2.3 (2011-06-23)
-        ------------------
-        
-        - Renamed 'setup_hook' to 'setup_hooks' as is now the case in the packaging
-          module.  Added support for multiple setup_hooks
-        
-        
-        0.2.2 (2011-06-15)
-        ------------------
-        
-        - Fixed a bug in DefaultGetDict where it didn't actually save the returned
-          default in the dictionary--so any command options would get lost
-        - Fixed a KeyError when the distribution does not have any custom commands
-          specified
-        
-        
-        0.2.1 (2011-06-15)
-        ------------------
-        
-        - Reimplemented command hooks without monkey-patching and more reliably in
-          general (though it's still a flaming hack).  The previous monkey patch-based
-          solution would break if d2to1 were entered multiple times, which could happen
-          in some scenarios
-        
-        
-        0.2.0 (2011-06-14)
-        ------------------
-        
-        - Version bump to start using micro-version numbers for bug fixes only, now
-          that the my primary feature goals are complete
-        
-        
-        0.1.5 (2011-06-02)
-        ------------------
-        
-        - Adds support for the data_files option under [files].  Though this is
-          considered deprecated and may go away at some point, it can be useful in the
-          absence of resources support
-        - Adds support for command pre/post-hooks.  Warning: this monkey-patches
-          distutils.dist.Distribution a little bit... :(
-        - Adds (slightly naive) support for PEP 345-style version specifiers in
-          requires-dist (environment markers not supported yet)
-        - Fixed a bug where not enough newlines were inserted between description files
-        
-        
-        0.1.4 (2011-05-24)
-        ------------------
-        
-        - Adds support for custom command classes specified in the 'commands' option
-          under the [global] section in setup.cfg
-        - Adds preliminary support for custom compilers specified in the 'compilers'
-          option under the [global] section in setup.cfg.  This functionality doesn't
-          exist in distutils/setuptools/distribute, so adding support for it is a
-          flaming hack.  It hasn't really been tested beyond seeing that the custom
-          compilers come up in `setup.py build_ext --help-compiler`, so any real-world
-          testing of this feature would be appreciated
-        
-        
-        0.1.3 (2011-04-20)
-        ------------------
-        
-        - Adds zest.releaser entry points for updating the version number in a
-          setup.cfg file; only useful if you use zest.releaser--otherwise harmless
-          (might eventually move this functionality out into a separate product)
-        - Though version 0.1.2 worked in Python3, use_2to3 wasn't added to the setup.py
-          so 2to3 had to be run manually
-        - Fixed a crash on projects that don't have a description-file option
-        
-        0.1.2 (2011-04-13)
-        ------------------
-        
-        - Fixed the self-installation--it did not work if a d2to1 version was not
-          already installed, due to the use of `pkg_resources.require()`
-        - Adds nominal Python3 support
-        - Fixes the 'classifier' option in setup.cfg
-        
-        0.1.1 (2011-04-12)
-        ------------------
-        
-        - Fixed an unhelpful error message when a setup_hook fails to import
-        - Made d2to1 able to use its own machinery to install itself
-        
-        
-Platform: UNKNOWN
-Classifier: Development Status :: 5 - Production/Stable
-Classifier: Environment :: Plugins
-Classifier: Framework :: Setuptools Plugin
-Classifier: Intended Audience :: Developers
-Classifier: License :: OSI Approved :: BSD License
-Classifier: Operating System :: OS Independent
-Classifier: Programming Language :: Python
-Classifier: Programming Language :: Python :: 3
-Classifier: Topic :: Software Development :: Build Tools
-Classifier: Topic :: Software Development :: Libraries :: Python Modules
-Classifier: Topic :: System :: Archiving :: Packaging
diff --git a/d2to1.egg-info/SOURCES.txt b/d2to1.egg-info/SOURCES.txt
deleted file mode 100644
index db6da5a..0000000
--- a/d2to1.egg-info/SOURCES.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-CHANGES.rst
-CONTRIBUTORS
-LICENSE
-README.rst
-ez_setup.py
-ez_setup25.py
-setup.cfg
-setup.py
-d2to1/__init__.py
-d2to1/core.py
-d2to1/util.py
-d2to1/zestreleaser.py
-d2to1.egg-info/PKG-INFO
-d2to1.egg-info/SOURCES.txt
-d2to1.egg-info/dependency_links.txt
-d2to1.egg-info/entry_points.txt
-d2to1.egg-info/not-zip-safe
-d2to1.egg-info/requires.txt
-d2to1.egg-info/top_level.txt
-d2to1/extern/__init__.py
-d2to1/extern/six.py
\ No newline at end of file
diff --git a/d2to1.egg-info/dependency_links.txt b/d2to1.egg-info/dependency_links.txt
deleted file mode 100644
index 8b13789..0000000
--- a/d2to1.egg-info/dependency_links.txt
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/d2to1.egg-info/entry_points.txt b/d2to1.egg-info/entry_points.txt
deleted file mode 100644
index f2dd197..0000000
--- a/d2to1.egg-info/entry_points.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-[distutils.setup_keywords]
-d2to1 = d2to1.core:d2to1
-
-[zest.releaser.postreleaser.before]
-d2to1_dev_version = d2to1.zestreleaser:postreleaser_before
-
-[zest.releaser.prereleaser.before]
-d2to1_version = d2to1.zestreleaser:prereleaser_before
-
-[zest.releaser.releaser.middle]
-d2to1_git_tag = d2to1.zestreleaser:prereleaser_middle
-
diff --git a/d2to1.egg-info/not-zip-safe b/d2to1.egg-info/not-zip-safe
deleted file mode 100644
index 8b13789..0000000
--- a/d2to1.egg-info/not-zip-safe
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/d2to1.egg-info/requires.txt b/d2to1.egg-info/requires.txt
deleted file mode 100644
index 49fe098..0000000
--- a/d2to1.egg-info/requires.txt
+++ /dev/null
@@ -1 +0,0 @@
-setuptools
diff --git a/d2to1.egg-info/top_level.txt b/d2to1.egg-info/top_level.txt
deleted file mode 100644
index 0302b71..0000000
--- a/d2to1.egg-info/top_level.txt
+++ /dev/null
@@ -1 +0,0 @@
-d2to1
diff --git a/d2to1/tests/__init__.py b/d2to1/tests/__init__.py
new file mode 100644
index 0000000..26fb380
--- /dev/null
+++ b/d2to1/tests/__init__.py
@@ -0,0 +1,99 @@
+from __future__ import with_statement
+import os
+import shutil
+import subprocess
+import sys
+import tempfile
+
+import pkg_resources
+
+from ..extern.six.moves import configparser
+from .util import rmtree, open_config
+
+
+D2TO1_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__),
+                                         os.pardir, os.pardir))
+
+
+def fake_d2to1_dist():
+    # Fake a d2to1 distribution from the d2to1 package that these tests reside
+    # in and make sure it's active on the path with the appropriate entry
+    # points installed
+
+    # TODO: I can't exactly remember why this is needed as opposed to,
+    # say, actually building a d2to1 egg and activating it
+    cfg = configparser.ConfigParser()
+    cfg.read(os.path.join(D2TO1_DIR, 'setup.cfg'))
+    d2to1_version = cfg.get('metadata', 'version')
+
+    class _FakeProvider(pkg_resources.EmptyProvider):
+        """A fake metadata provider that does almost nothing except to return
+        entry point metadata.
+        """
+
+        def has_metadata(self, name):
+            return name in ('entry_points.txt', 'PKG-INFO')
+
+        def get_metadata(self, name):
+            if name == 'entry_points.txt':
+                return '[distutils.setup_keywords]\nd2to1 = d2to1.core:d2to1\n'
+            elif name == 'PKG-INFO':
+                # This is needed just for Distribution.version
+                return 'Version: ' + d2to1_version
+            else:
+                return ''
+
+    sys.path.insert(0, D2TO1_DIR)
+    if 'd2to1' in sys.modules:
+        del sys.modules['d2to1']
+    if 'd2to1' in pkg_resources.working_set.by_key:
+        del pkg_resources.working_set.by_key['d2to1']
+    dist = pkg_resources.Distribution(location=D2TO1_DIR, project_name='d2to1',
+                                      metadata=_FakeProvider())
+    pkg_resources.working_set.add(dist)
+
+
+class D2to1TestCase(object):
+    def setup(self):
+        self.temp_dir = tempfile.mkdtemp(prefix='d2to1-test-')
+        self.package_dir = os.path.join(self.temp_dir, 'testpackage')
+        shutil.copytree(os.path.join(os.path.dirname(__file__), 'testpackage'),
+                        self.package_dir)
+        self.oldcwd = os.getcwd()
+        os.chdir(self.package_dir)
+
+    def teardown(self):
+        os.chdir(self.oldcwd)
+        # Remove d2to1.testpackage from sys.modules so that it can be freshly
+        # re-imported by the next test
+        for k in list(sys.modules):
+            if (k == 'd2to1_testpackage' or
+                k.startswith('d2to1_testpackage.')):
+                del sys.modules[k]
+        rmtree(self.temp_dir)
+
+    def run_setup(self, *args):
+        cmd = ('-c',
+               'import sys;sys.path.insert(0, %r);'
+               'from d2to1.tests import fake_d2to1_dist;'
+               'from d2to1.extern.six import exec_;'
+               'fake_d2to1_dist();exec_(open("setup.py").read())' % D2TO1_DIR)
+        return self._run_cmd(sys.executable, cmd + args)
+
+    def run_svn(self, *args):
+        return self._run_cmd('svn', args)
+
+    def _run_cmd(self, cmd, args):
+        """
+        Runs a command, with the given argument list, in the root of the test
+        working copy--returns the stdout and stderr streams and the exit code
+        from the subprocess.
+        """
+
+        os.chdir(self.package_dir)
+        p = subprocess.Popen([cmd] + list(args), stdout=subprocess.PIPE,
+                             stderr=subprocess.PIPE)
+
+        streams = tuple(s.decode('latin1').strip() for s in p.communicate())
+        print(streams)
+        return (streams) + (p.returncode,)
diff --git a/d2to1/tests/test_commands.py b/d2to1/tests/test_commands.py
new file mode 100644
index 0000000..29342da
--- /dev/null
+++ b/d2to1/tests/test_commands.py
@@ -0,0 +1,13 @@
+from . import D2to1TestCase
+
+
+class TestCommands(D2to1TestCase):
+    def test_custom_build_py_command(self):
+        """
+        Test that a custom subclass of the build_py command runs when listed in
+        the commands [global] option, rather than the normal build command.
+        """
+
+        stdout, _, return_code = self.run_setup('build_py')
+        assert 'Running custom build_py command.' in stdout
+        assert return_code == 0
diff --git a/d2to1/tests/test_core.py b/d2to1/tests/test_core.py
new file mode 100644
index 0000000..751ee24
--- /dev/null
+++ b/d2to1/tests/test_core.py
@@ -0,0 +1,48 @@
+import glob
+import os
+import tarfile
+
+from . import D2to1TestCase
+
+
+VERSION = '0.1.dev0'
+
+
+class TestCore(D2to1TestCase):
+    def test_setup_py_version(self):
+        """
+        Test that the `./setup.py --version` command returns the correct
+        value without balking.
+        """
+
+        self.run_setup('egg_info')
+        stdout, _, _ = self.run_setup('--version')
+        assert stdout == VERSION
+
+    def test_setup_py_keywords(self):
+        """
+        Test that the `./setup.py --keywords` command returns the correct
+        value without balking.
+        """
+
+        self.run_setup('egg_info')
+        stdout, _, _ = self.run_setup('--keywords')
+        assert stdout == 'packaging,distutils,setuptools'
+
+    def test_sdist_extra_files(self):
+        """
+        Test that the extra files are correctly added.
+        """
+
+        stdout, _, return_code = self.run_setup('sdist', '--formats=gztar')
+
+        # There can be only one
+        try:
+            tf_path = glob.glob(os.path.join('dist', '*.tar.gz'))[0]
+        except IndexError:
+            assert False, 'source dist not found'
+
+        tf = tarfile.open(tf_path)
+        names = ['/'.join(p.split('/')[1:]) for p in tf.getnames()]
+
+        assert 'extra-file.txt' in names
diff --git a/d2to1/tests/test_hooks.py b/d2to1/tests/test_hooks.py
new file mode 100644
index 0000000..047e0b9
--- /dev/null
+++ b/d2to1/tests/test_hooks.py
@@ -0,0 +1,52 @@
+from __future__ import with_statement
+
+import os
+import textwrap
+
+from . import D2to1TestCase
+from .util import open_config
+
+
+class TestHooks(D2to1TestCase):
+    def setup(self):
+        super(TestHooks, self).setup()
+        with open_config(os.path.join(self.package_dir, 'setup.cfg')) as cfg:
+            cfg.set('global', 'setup-hooks',
+                    'd2to1_testpackage._setup_hooks.test_hook_1\n'
+                    'd2to1_testpackage._setup_hooks.test_hook_2')
+            cfg.set('build_ext', 'pre-hook.test_pre_hook',
+                    'd2to1_testpackage._setup_hooks.test_pre_hook')
+            cfg.set('build_ext', 'post-hook.test_post_hook',
+                    'd2to1_testpackage._setup_hooks.test_post_hook')
+
+    def test_global_setup_hooks(self):
+        """
+        Test that setup_hooks listed in the [global] section of setup.cfg are
+        executed in order.
+        """
+
+        stdout, _, return_code = self.run_setup('egg_info')
+        assert 'test_hook_1\ntest_hook_2' in stdout
+        assert return_code == 0
+
+    def test_command_hooks(self):
+        """
+        Simple test that the appropriate command hooks run at the
+        beginning/end of the appropriate command.
+        """
+
+        stdout, _, return_code = self.run_setup('egg_info')
+        assert 'build_ext pre-hook' not in stdout
+        assert 'build_ext post-hook' not in stdout
+        assert return_code == 0
+
+        stdout, _, return_code = self.run_setup('build_ext')
+        assert textwrap.dedent("""
+            running build_ext
+            running pre_hook d2to1_testpackage._setup_hooks.test_pre_hook for command build_ext
+            build_ext pre-hook
+        """) in stdout
+        assert stdout.endswith('build_ext post-hook')
+        assert return_code == 0
+
+
diff --git a/d2to1/tests/testpackage/CHANGES.txt b/d2to1/tests/testpackage/CHANGES.txt
new file mode 100644
index 0000000..709b9d4
--- /dev/null
+++ b/d2to1/tests/testpackage/CHANGES.txt
@@ -0,0 +1,86 @@
+Changelog
+===========
+
+0.3 (unreleased)
+------------------
+
+- The ``glob_data_files`` hook became a pre-command hook for the install_data
+  command instead of being a setup-hook.  This is to support the additional
+  functionality of requiring data_files with relative destination paths to be
+  install relative to the package's install path (i.e. site-packages).
+
+- Dropped support for and deprecated the easier_install custom command.
+  Although it should still work, it probably won't be used anymore for
+  stsci_python packages.
+
+- Added support for the ``build_optional_ext`` command, which replaces/extends
+  the default ``build_ext`` command.  See the README for more details.
+
+- Added the ``tag_svn_revision`` setup_hook as a replacement for the
+  setuptools-specific tag_svn_revision option to the egg_info command.  This
+  new hook is easier to use than the old tag_svn_revision option: It's
+  automatically enabled by the presence of ``.dev`` in the version string, and
+  disabled otherwise.
+
+- The ``svn_info_pre_hook`` and ``svn_info_post_hook`` have been replaced with
+  ``version_pre_command_hook`` and ``version_post_command_hook`` respectively.
+  However, a new ``version_setup_hook``, which has the same purpose, has been
+  added.  It is generally easier to use and will give more consistent results
+  in that it will run every time setup.py is run, regardless of which command
+  is used.  ``stsci.distutils`` itself uses this hook--see the `setup.cfg` file
+  and `stsci/distutils/__init__.py` for example usage.
+
+- Instead of creating an `svninfo.py` module, the new ``version_`` hooks create
+  a file called `version.py`.  In addition to the SVN info that was included
+  in `svninfo.py`, it includes a ``__version__`` variable to be used by the
+  package's `__init__.py`.  This allows there to be a hard-coded
+  ``__version__`` variable included in the source code, rather than using
+  pkg_resources to get the version.
+
+- In `version.py`, the variables previously named ``__svn_version__`` and
+  ``__full_svn_info__`` are now named ``__svn_revision__`` and
+  ``__svn_full_info__``.
+
+- Fixed a bug when using stsci.distutils in the installation of other packages
+  in the ``stsci.*`` namespace package.  If stsci.distutils was not already
+  installed, and was downloaded automatically by distribute through the
+  setup_requires option, then ``stsci.distutils`` would fail to import.  This
+  is because the way the namespace package (nspkg) mechanism currently works,
+  all packages belonging to the nspkg *must* be on the import path at initial
+  import time.
+
+  So when installing stsci.tools, for example, if ``stsci.tools`` is imported
+  from within the source code at install time, but before ``stsci.distutils``
+  is downloaded and added to the path, the ``stsci`` package is already
+  imported and can't be extended to include the path of ``stsci.distutils``
+  after the fact.  The easiest way of dealing with this, it seems, is to
+  delete ``stsci`` from ``sys.modules``, which forces it to be reimported, now
+  the its ``__path__`` extended to include ``stsci.distutil``'s path.
+
+
+0.2.2 (2011-11-09)
+------------------
+
+- Fixed check for the issue205 bug on actual setuptools installs; before it
+  only worked on distribute.  setuptools has the issue205 bug prior to version
+  0.6c10.
+
+- Improved the fix for the issue205 bug, especially on setuptools.
+  setuptools, prior to 0.6c10, did not back of sys.modules either before
+  sandboxing, which causes serious problems.  In fact, it's so bad that it's
+  not enough to add a sys.modules backup to the current sandbox: It's in fact
+  necessary to monkeypatch setuptools.sandbox.run_setup so that any subsequent
+  calls to it also back up sys.modules.
+
+
+0.2.1 (2011-09-02)
+------------------
+
+- Fixed the dependencies so that setuptools is requirement but 'distribute'
+  specifically.  Previously installation could fail if users had plain
+  setuptools installed and not distribute
+
+0.2 (2011-08-23)
+------------------
+
+- Initial public release
diff --git a/d2to1/tests/testpackage/LICENSE.txt b/d2to1/tests/testpackage/LICENSE.txt
new file mode 100644
index 0000000..7e8019a
--- /dev/null
+++ b/d2to1/tests/testpackage/LICENSE.txt
@@ -0,0 +1,29 @@
+Copyright (C) 2005 Association of Universities for Research in Astronomy (AURA)
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    1. Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    2. Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    3. The name of AURA and its representatives may not be used to
+      endorse or promote products derived from this software without
+      specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY AURA ``AS IS'' AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL AURA BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGE.
+
diff --git a/d2to1/tests/testpackage/MANIFEST.in b/d2to1/tests/testpackage/MANIFEST.in
new file mode 100644
index 0000000..cdc95ea
--- /dev/null
+++ b/d2to1/tests/testpackage/MANIFEST.in
@@ -0,0 +1 @@
+include data_files/*
diff --git a/d2to1/tests/testpackage/README.txt b/d2to1/tests/testpackage/README.txt
new file mode 100644
index 0000000..4f00d32
--- /dev/null
+++ b/d2to1/tests/testpackage/README.txt
@@ -0,0 +1,148 @@
+Introduction
+============
+This package contains utilities used to package some of STScI's Python
+projects; specifically those projects that comprise stsci_python_ and
+Astrolib_.
+
+It currently consists mostly of some setup_hook scripts meant for use with
+`distutils2/packaging`_ and/or d2to1_, and a customized easy_install command
+meant for use with distribute_.
+
+This package is not meant for general consumption, though it might be worth
+looking at for examples of how to do certain things with your own packages, but
+YMMV.
+
+Features
+========
+
+Hook Scripts
+------------
+Currently the main features of this package are a couple of setup_hook scripts.
+In distutils2, a setup_hook is a script that runs at the beginning of any
+pysetup command, and can modify the package configuration read from setup.cfg.
+There are also pre- and post-command hooks that only run before/after a
+specific setup command (eg. build_ext, install) is run.
+
+stsci.distutils.hooks.use_packages_root
+'''''''''''''''''''''''''''''''''''''''
+If using the ``packages_root`` option under the ``[files]`` section of
+setup.cfg, this hook will add that path to ``sys.path`` so that modules in your
+package can be imported and used in setup.  This can be used even if
+``packages_root`` is not specified--in this case it adds ``''`` to
+``sys.path``.
+
+stsci.distutils.hooks.version_setup_hook
+''''''''''''''''''''''''''''''''''''''''
+Creates a Python module called version.py which currently contains four
+variables:
+
+* ``__version__`` (the release version)
+* ``__svn_revision__`` (the SVN revision info as returned by the ``svnversion``
+  command)
+* ``__svn_full_info__`` (as returned by the ``svn info`` command)
+* ``__setup_datetime__`` (the date and time that setup.py was last run).
+
+These variables can be imported in the package's `__init__.py` for degugging
+purposes.  The version.py module will *only* be created in a package that
+imports from the version module in its `__init__.py`.  It should be noted that
+this is generally preferable to writing these variables directly into
+`__init__.py`, since this provides more control and is less likely to
+unexpectedly break things in `__init__.py`.
+
+stsci.distutils.hooks.version_pre_command_hook
+''''''''''''''''''''''''''''''''''''''''''''''
+Identical to version_setup_hook, but designed to be used as a pre-command
+hook.
+
+stsci.distutils.hooks.version_post_command_hook
+'''''''''''''''''''''''''''''''''''''''''''''''
+The complement to version_pre_command_hook.  This will delete any version.py
+files created during a build in order to prevent them from cluttering an SVN
+working copy (note, however, that version.py is *not* deleted from the build/
+directory, so a copy of it is still preserved).  It will also not be deleted
+if the current directory is not an SVN working copy.  For example, if source
+code extracted from a source tarball it will be preserved.
+
+stsci.distutils.hooks.tag_svn_revision
+''''''''''''''''''''''''''''''''''''''
+A setup_hook to add the SVN revision of the current working copy path to the
+package version string, but only if the version ends in .dev.
+
+For example, ``mypackage-1.0.dev`` becomes ``mypackage-1.0.dev1234``.  This is
+in accordance with the version string format standardized by PEP 386.
+
+This should be used as a replacement for the ``tag_svn_revision`` option to
+the egg_info command.  This hook is more compatible with packaging/distutils2,
+which does not include any VCS support.  This hook is also more flexible in
+that it turns the revision number on/off depending on the presence of ``.dev``
+in the version string, so that it's not automatically added to the version in
+final releases.
+
+This hook does require the ``svnversion`` command to be available in order to
+work.  It does not examine the working copy metadata directly.
+
+stsci.distutils.hooks.numpy_extension_hook
+''''''''''''''''''''''''''''''''''''''''''
+This is a pre-command hook for the build_ext command.  To use it, add a
+``[build_ext]`` section to your setup.cfg, and add to it::
+
+    pre-hook.numpy-extension-hook = stsci.distutils.hooks.numpy_extension_hook
+
+This hook must be used to build extension modules that use Numpy.   The primary
+side-effect of this hook is to add the correct numpy include directories to
+`include_dirs`.  To use it, add 'numpy' to the 'include-dirs' option of each
+extension module that requires numpy to build.  The value 'numpy' will be
+replaced with the actual path to the numpy includes.
+
+stsci.distutils.hooks.is_display_option
+'''''''''''''''''''''''''''''''''''''''
+This is not actually a hook, but is a useful utility function that can be used
+in writing other hooks.  Basically, it returns ``True`` if setup.py was run
+with a "display option" such as --version or --help.  This can be used to
+prevent your hook from running in such cases.
+
+stsci.distutils.hooks.glob_data_files
+'''''''''''''''''''''''''''''''''''''
+A pre-command hook for the install_data command.  Allows filename wildcards as
+understood by ``glob.glob()`` to be used in the data_files option.  This hook
+must be used in order to have this functionality since it does not normally
+exist in distutils.
+
+This hook also ensures that data files are installed relative to the package
+path.  data_files shouldn't normally be installed this way, but the
+functionality is required for a few special cases.
+
+
+Commands
+--------
+build_optional_ext
+''''''''''''''''''
+This serves as an optional replacement for the default built_ext command,
+which compiles C extension modules.  Its purpose is to allow extension modules
+to be *optional*, so that if their build fails the rest of the package is
+still allowed to be built and installed.  This can be used when an extension
+module is not definitely required to use the package.
+
+To use this custom command, add::
+
+    commands = stsci.distutils.command.build_optional_ext.build_optional_ext
+
+under the ``[global]`` section of your package's setup.cfg.  Then, to mark
+an individual extension module as optional, under the setup.cfg section for
+that extension add::
+
+    optional = True
+
+Optionally, you may also add a custom failure message by adding::
+
+    fail_message = The foobar extension module failed to compile.
+                   This could be because you lack such and such headers.
+                   This package will still work, but such and such features
+                   will be disabled.
+
+
+.. _stsci_python: http://www.stsci.edu/resources/software_hardware/pyraf/stsci_python
+.. _Astrolib: http://www.scipy.org/AstroLib/
+.. _distutils2/packaging: http://distutils2.notmyidea.org/
+.. _d2to1: http://pypi.python.org/pypi/d2to1
+.. _distribute: http://pypi.python.org/pypi/distribute
diff --git a/d2to1/tests/testpackage/d2to1_testpackage/__init__.py b/d2to1/tests/testpackage/d2to1_testpackage/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/d2to1/tests/testpackage/d2to1_testpackage/_setup_hooks.py b/d2to1/tests/testpackage/d2to1_testpackage/_setup_hooks.py
new file mode 100644
index 0000000..77005b2
--- /dev/null
+++ b/d2to1/tests/testpackage/d2to1_testpackage/_setup_hooks.py
@@ -0,0 +1,25 @@
+from distutils.command.build_py import build_py
+
+
+def test_hook_1(config):
+    print('test_hook_1')
+
+
+def test_hook_2(config):
+    print('test_hook_2')
+
+
+class test_command(build_py):
+    command_name = 'build_py'
+
+    def run(self):
+        print('Running custom build_py command.')
+        return build_py.run(self)
+
+
+def test_pre_hook(cmdobj):
+    print('build_ext pre-hook')
+
+
+def test_post_hook(cmdobj):
+    print('build_ext post-hook')
diff --git a/d2to1/tests/testpackage/d2to1_testpackage/package_data/1.txt b/d2to1/tests/testpackage/d2to1_testpackage/package_data/1.txt
new file mode 100644
index 0000000..e69de29
diff --git a/d2to1/tests/testpackage/d2to1_testpackage/package_data/2.txt b/d2to1/tests/testpackage/d2to1_testpackage/package_data/2.txt
new file mode 100644
index 0000000..e69de29
diff --git a/d2to1/tests/testpackage/data_files/a.txt b/d2to1/tests/testpackage/data_files/a.txt
new file mode 100644
index 0000000..e69de29
diff --git a/d2to1/tests/testpackage/data_files/b.txt b/d2to1/tests/testpackage/data_files/b.txt
new file mode 100644
index 0000000..e69de29
diff --git a/d2to1/tests/testpackage/data_files/c.rst b/d2to1/tests/testpackage/data_files/c.rst
new file mode 100644
index 0000000..e69de29
diff --git a/d2to1/tests/testpackage/distribute_setup.py b/d2to1/tests/testpackage/distribute_setup.py
new file mode 100644
index 0000000..bbb6f3c
--- /dev/null
+++ b/d2to1/tests/testpackage/distribute_setup.py
@@ -0,0 +1,485 @@
+#!python
+"""Bootstrap distribute installation
+
+If you want to use setuptools in your package's setup.py, just include this
+file in the same directory with it, and add this to the top of your setup.py::
+
+    from distribute_setup import use_setuptools
+    use_setuptools()
+
+If you want to require a specific version of setuptools, set a download
+mirror, or use an alternate download directory, you can do so by supplying
+the appropriate options to ``use_setuptools()``.
+
+This file can also be run as a script to install or upgrade setuptools.
+"""
+import os
+import sys
+import time
+import fnmatch
+import tempfile
+import tarfile
+from distutils import log
+
+try:
+    from site import USER_SITE
+except ImportError:
+    USER_SITE = None
+
+try:
+    import subprocess
+
+    def _python_cmd(*args):
+        args = (sys.executable,) + args
+        return subprocess.call(args) == 0
+
+except ImportError:
+    # will be used for python 2.3
+    def _python_cmd(*args):
+        args = (sys.executable,) + args
+        # quoting arguments if windows
+        if sys.platform == 'win32':
+            def quote(arg):
+                if ' ' in arg:
+                    return '"%s"' % arg
+                return arg
+            args = [quote(arg) for arg in args]
+        return os.spawnl(os.P_WAIT, sys.executable, *args) == 0
+
+DEFAULT_VERSION = "0.6.19"
+DEFAULT_URL = "http://pypi.python.org/packages/source/d/distribute/"
+SETUPTOOLS_FAKED_VERSION = "0.6c11"
+
+SETUPTOOLS_PKG_INFO = """\
+Metadata-Version: 1.0
+Name: setuptools
+Version: %s
+Summary: xxxx
+Home-page: xxx
+Author: xxx
+Author-email: xxx
+License: xxx
+Description: xxx
+""" % SETUPTOOLS_FAKED_VERSION
+
+
+def _install(tarball):
+    # extracting the tarball
+    tmpdir = tempfile.mkdtemp()
+    log.warn('Extracting in %s', tmpdir)
+    old_wd = os.getcwd()
+    try:
+        os.chdir(tmpdir)
+        tar = tarfile.open(tarball)
+        _extractall(tar)
+        tar.close()
+
+        # going in the directory
+        subdir = os.path.join(tmpdir, os.listdir(tmpdir)[0])
+        os.chdir(subdir)
+        log.warn('Now working in %s', subdir)
+
+        # installing
+        log.warn('Installing Distribute')
+        if not _python_cmd('setup.py', 'install'):
+            log.warn('Something went wrong during the installation.')
+            log.warn('See the error message above.')
+    finally:
+        os.chdir(old_wd)
+
+
+def _build_egg(egg, tarball, to_dir):
+    # extracting the tarball
+    tmpdir = tempfile.mkdtemp()
+    log.warn('Extracting in %s', tmpdir)
+    old_wd = os.getcwd()
+    try:
+        os.chdir(tmpdir)
+        tar = tarfile.open(tarball)
+        _extractall(tar)
+        tar.close()
+
+        # going in the directory
+        subdir = os.path.join(tmpdir, os.listdir(tmpdir)[0])
+        os.chdir(subdir)
+        log.warn('Now working in %s', subdir)
+
+        # building an egg
+        log.warn('Building a Distribute egg in %s', to_dir)
+        _python_cmd('setup.py', '-q', 'bdist_egg', '--dist-dir', to_dir)
+
+    finally:
+        os.chdir(old_wd)
+    # returning the result
+    log.warn(egg)
+    if not os.path.exists(egg):
+        raise IOError('Could not build the egg.')
+
+
+def _do_download(version, download_base, to_dir, download_delay):
+    egg = os.path.join(to_dir, 'distribute-%s-py%d.%d.egg'
+                       % (version, sys.version_info[0], sys.version_info[1]))
+    if not os.path.exists(egg):
+        tarball = download_setuptools(version, download_base,
+                                      to_dir, download_delay)
+        _build_egg(egg, tarball, to_dir)
+    sys.path.insert(0, egg)
+    import setuptools
+    setuptools.bootstrap_install_from = egg
+
+
+def use_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL,
+                   to_dir=os.curdir, download_delay=15, no_fake=True):
+    # making sure we use the absolute path
+    to_dir = os.path.abspath(to_dir)
+    was_imported = 'pkg_resources' in sys.modules or \
+        'setuptools' in sys.modules
+    try:
+        try:
+            import pkg_resources
+            if not hasattr(pkg_resources, '_distribute'):
+                if not no_fake:
+                    _fake_setuptools()
+                raise ImportError
+        except ImportError:
+            return _do_download(version, download_base, to_dir, download_delay)
+        try:
+            pkg_resources.require("distribute>="+version)
+            return
+        except pkg_resources.VersionConflict:
+            e = sys.exc_info()[1]
+            if was_imported:
+                sys.stderr.write(
+                "The required version of distribute (>=%s) is not available,\n"
+                "and can't be installed while this script is running. Please\n"
+                "install a more recent version first, using\n"
+                "'easy_install -U distribute'."
+                "\n\n(Currently using %r)\n" % (version, e.args[0]))
+                sys.exit(2)
+            else:
+                del pkg_resources, sys.modules['pkg_resources']    # reload ok
+                return _do_download(version, download_base, to_dir,
+                                    download_delay)
+        except pkg_resources.DistributionNotFound:
+            return _do_download(version, download_base, to_dir,
+                                download_delay)
+    finally:
+        if not no_fake:
+            _create_fake_setuptools_pkg_info(to_dir)
+
+def download_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL,
+                        to_dir=os.curdir, delay=15):
+    """Download distribute from a specified location and return its filename
+
+    `version` should be a valid distribute version number that is available
+    as an egg for download under the `download_base` URL (which should end
+    with a '/'). `to_dir` is the directory where the egg will be downloaded.
+    `delay` is the number of seconds to pause before an actual download
+    attempt.
+    """
+    # making sure we use the absolute path
+    to_dir = os.path.abspath(to_dir)
+    try:
+        from urllib.request import urlopen
+    except ImportError:
+        from urllib2 import urlopen
+    tgz_name = "distribute-%s.tar.gz" % version
+    url = download_base + tgz_name
+    saveto = os.path.join(to_dir, tgz_name)
+    src = dst = None
+    if not os.path.exists(saveto):  # Avoid repeated downloads
+        try:
+            log.warn("Downloading %s", url)
+            src = urlopen(url)
+            # Read/write all in one block, so we don't create a corrupt file
+            # if the download is interrupted.
+            data = src.read()
+            dst = open(saveto, "wb")
+            dst.write(data)
+        finally:
+            if src:
+                src.close()
+            if dst:
+                dst.close()
+    return os.path.realpath(saveto)
+
+def _no_sandbox(function):
+    def __no_sandbox(*args, **kw):
+        try:
+            from setuptools.sandbox import DirectorySandbox
+            if not hasattr(DirectorySandbox, '_old'):
+                def violation(*args):
+                    pass
+                DirectorySandbox._old = DirectorySandbox._violation
+                DirectorySandbox._violation = violation
+                patched = True
+            else:
+                patched = False
+        except ImportError:
+            patched = False
+
+        try:
+            return function(*args, **kw)
+        finally:
+            if patched:
+                DirectorySandbox._violation = DirectorySandbox._old
+                del DirectorySandbox._old
+
+    return __no_sandbox
+
+def _patch_file(path, content):
+    """Will backup the file then patch it"""
+    existing_content = open(path).read()
+    if existing_content == content:
+        # already patched
+        log.warn('Already patched.')
+        return False
+    log.warn('Patching...')
+    _rename_path(path)
+    f = open(path, 'w')
+    try:
+        f.write(content)
+    finally:
+        f.close()
+    return True
+
+_patch_file = _no_sandbox(_patch_file)
+
+def _same_content(path, content):
+    return open(path).read() == content
+
+def _rename_path(path):
+    new_name = path + '.OLD.%s' % time.time()
+    log.warn('Renaming %s into %s', path, new_name)
+    os.rename(path, new_name)
+    return new_name
+
+def _remove_flat_installation(placeholder):
+    if not os.path.isdir(placeholder):
+        log.warn('Unkown installation at %s', placeholder)
+        return False
+    found = False
+    for file in os.listdir(placeholder):
+        if fnmatch.fnmatch(file, 'setuptools*.egg-info'):
+            found = True
+            break
+    if not found:
+        log.warn('Could not locate setuptools*.egg-info')
+        return
+
+    log.warn('Removing elements out of the way...')
+    pkg_info = os.path.join(placeholder, file)
+    if os.path.isdir(pkg_info):
+        patched = _patch_egg_dir(pkg_info)
+    else:
+        patched = _patch_file(pkg_info, SETUPTOOLS_PKG_INFO)
+
+    if not patched:
+        log.warn('%s already patched.', pkg_info)
+        return False
+    # now let's move the files out of the way
+    for element in ('setuptools', 'pkg_resources.py', 'site.py'):
+        element = os.path.join(placeholder, element)
+        if os.path.exists(element):
+            _rename_path(element)
+        else:
+            log.warn('Could not find the %s element of the '
+                     'Setuptools distribution', element)
+    return True
+
+_remove_flat_installation = _no_sandbox(_remove_flat_installation)
+
+def _after_install(dist):
+    log.warn('After install bootstrap.')
+    placeholder = dist.get_command_obj('install').install_purelib
+    _create_fake_setuptools_pkg_info(placeholder)
+
+def _create_fake_setuptools_pkg_info(placeholder):
+    if not placeholder or not os.path.exists(placeholder):
+        log.warn('Could not find the install location')
+        return
+    pyver = '%s.%s' % (sys.version_info[0], sys.version_info[1])
+    setuptools_file = 'setuptools-%s-py%s.egg-info' % \
+            (SETUPTOOLS_FAKED_VERSION, pyver)
+    pkg_info = os.path.join(placeholder, setuptools_file)
+    if os.path.exists(pkg_info):
+        log.warn('%s already exists', pkg_info)
+        return
+
+    log.warn('Creating %s', pkg_info)
+    f = open(pkg_info, 'w')
+    try:
+        f.write(SETUPTOOLS_PKG_INFO)
+    finally:
+        f.close()
+
+    pth_file = os.path.join(placeholder, 'setuptools.pth')
+    log.warn('Creating %s', pth_file)
+    f = open(pth_file, 'w')
+    try:
+        f.write(os.path.join(os.curdir, setuptools_file))
+    finally:
+        f.close()
+
+_create_fake_setuptools_pkg_info = _no_sandbox(_create_fake_setuptools_pkg_info)
+
+def _patch_egg_dir(path):
+    # let's check if it's already patched
+    pkg_info = os.path.join(path, 'EGG-INFO', 'PKG-INFO')
+    if os.path.exists(pkg_info):
+        if _same_content(pkg_info, SETUPTOOLS_PKG_INFO):
+            log.warn('%s already patched.', pkg_info)
+            return False
+    _rename_path(path)
+    os.mkdir(path)
+    os.mkdir(os.path.join(path, 'EGG-INFO'))
+    pkg_info = os.path.join(path, 'EGG-INFO', 'PKG-INFO')
+    f = open(pkg_info, 'w')
+    try:
+        f.write(SETUPTOOLS_PKG_INFO)
+    finally:
+        f.close()
+    return True
+
+_patch_egg_dir = _no_sandbox(_patch_egg_dir)
+
+def _before_install():
+    log.warn('Before install bootstrap.')
+    _fake_setuptools()
+
+
+def _under_prefix(location):
+    if 'install' not in sys.argv:
+        return True
+    args = sys.argv[sys.argv.index('install')+1:]
+    for index, arg in enumerate(args):
+        for option in ('--root', '--prefix'):
+            if arg.startswith('%s=' % option):
+                top_dir = arg.split('root=')[-1]
+                return location.startswith(top_dir)
+            elif arg == option:
+                if len(args) > index:
+                    top_dir = args[index+1]
+                    return location.startswith(top_dir)
+        if arg == '--user' and USER_SITE is not None:
+            return location.startswith(USER_SITE)
+    return True
+
+
+def _fake_setuptools():
+    log.warn('Scanning installed packages')
+    try:
+        import pkg_resources
+    except ImportError:
+        # we're cool
+        log.warn('Setuptools or Distribute does not seem to be installed.')
+        return
+    ws = pkg_resources.working_set
+    try:
+        setuptools_dist = ws.find(pkg_resources.Requirement.parse('setuptools',
+                                  replacement=False))
+    except TypeError:
+        # old distribute API
+        setuptools_dist = ws.find(pkg_resources.Requirement.parse('setuptools'))
+
+    if setuptools_dist is None:
+        log.warn('No setuptools distribution found')
+        return
+    # detecting if it was already faked
+    setuptools_location = setuptools_dist.location
+    log.warn('Setuptools installation detected at %s', setuptools_location)
+
+    # if --root or --preix was provided, and if
+    # setuptools is not located in them, we don't patch it
+    if not _under_prefix(setuptools_location):
+        log.warn('Not patching, --root or --prefix is installing Distribute'
+                 ' in another location')
+        return
+
+    # let's see if its an egg
+    if not setuptools_location.endswith('.egg'):
+        log.warn('Non-egg installation')
+        res = _remove_flat_installation(setuptools_location)
+        if not res:
+            return
+    else:
+        log.warn('Egg installation')
+        pkg_info = os.path.join(setuptools_location, 'EGG-INFO', 'PKG-INFO')
+        if (os.path.exists(pkg_info) and
+            _same_content(pkg_info, SETUPTOOLS_PKG_INFO)):
+            log.warn('Already patched.')
+            return
+        log.warn('Patching...')
+        # let's create a fake egg replacing setuptools one
+        res = _patch_egg_dir(setuptools_location)
+        if not res:
+            return
+    log.warn('Patched done.')
+    _relaunch()
+
+
+def _relaunch():
+    log.warn('Relaunching...')
+    # we have to relaunch the process
+    # pip marker to avoid a relaunch bug
+    if sys.argv[:3] == ['-c', 'install', '--single-version-externally-managed']:
+        sys.argv[0] = 'setup.py'
+    args = [sys.executable] + sys.argv
+    sys.exit(subprocess.call(args))
+
+
+def _extractall(self, path=".", members=None):
+    """Extract all members from the archive to the current working
+       directory and set owner, modification time and permissions on
+       directories afterwards. `path' specifies a different directory
+       to extract to. `members' is optional and must be a subset of the
+       list returned by getmembers().
+    """
+    import copy
+    import operator
+    from tarfile import ExtractError
+    directories = []
+
+    if members is None:
+        members = self
+
+    for tarinfo in members:
+        if tarinfo.isdir():
+            # Extract directories with a safe mode.
+            directories.append(tarinfo)
+            tarinfo = copy.copy(tarinfo)
+            tarinfo.mode = 448 # decimal for oct 0700
+        self.extract(tarinfo, path)
+
+    # Reverse sort directories.
+    if sys.version_info < (2, 4):
+        def sorter(dir1, dir2):
+            return cmp(dir1.name, dir2.name)
+        directories.sort(sorter)
+        directories.reverse()
+    else:
+        directories.sort(key=operator.attrgetter('name'), reverse=True)
+
+    # Set correct owner, mtime and filemode on directories.
+    for tarinfo in directories:
+        dirpath = os.path.join(path, tarinfo.name)
+        try:
+            self.chown(tarinfo, dirpath)
+            self.utime(tarinfo, dirpath)
+            self.chmod(tarinfo, dirpath)
+        except ExtractError:
+            e = sys.exc_info()[1]
+            if self.errorlevel > 1:
+                raise
+            else:
+                self._dbg(1, "tarfile: %s" % e)
+
+
+def main(argv, version=DEFAULT_VERSION):
+    """Install or upgrade setuptools and EasyInstall"""
+    tarball = download_setuptools()
+    _install(tarball)
+
+
+if __name__ == '__main__':
+    main(sys.argv[1:])
diff --git a/d2to1/tests/testpackage/extra-file.txt b/d2to1/tests/testpackage/extra-file.txt
new file mode 100644
index 0000000..e69de29
diff --git a/d2to1/tests/testpackage/setup.cfg b/d2to1/tests/testpackage/setup.cfg
new file mode 100644
index 0000000..41a8fdf
--- /dev/null
+++ b/d2to1/tests/testpackage/setup.cfg
@@ -0,0 +1,46 @@
+[metadata]
+name = d2to1_testpackage
+version = 0.1.dev0
+author = Erik M. Bray
+author-email = embray@stsci.edu
+home-page = http://www.stsci.edu/resources/software_hardware/stsci_python
+summary = Test package for testing d2to1
+description-file =
+    README.txt
+    CHANGES.txt
+requires-python = >=2.5
+
+requires-dist =
+    setuptools
+
+classifier =
+    Development Status :: 3 - Alpha
+    Intended Audience :: Developers
+    License :: OSI Approved :: BSD License
+    Programming Language :: Python
+    Topic :: Scientific/Engineering
+    Topic :: Software Development :: Build Tools
+    Topic :: Software Development :: Libraries :: Python Modules
+    Topic :: System :: Archiving :: Packaging
+
+keywords = packaging, distutils, setuptools
+
+[files]
+packages = d2to1_testpackage
+package-data = testpackage = package_data/*.txt
+data-files = testpackage/data_files = data_files/*.txt
+extra-files = extra-file.txt
+
+[extension=d2to1_testpackage.testext]
+sources = src/testext.c
+optional = True
+
+[global]
+#setup-hooks =
+#    d2to1_testpackage._setup_hooks.test_hook_1
+#    d2to1_testpackage._setup_hooks.test_hook_2
+commands = d2to1_testpackage._setup_hooks.test_command
+
+[build_ext]
+#pre-hook.test_pre_hook = d2to1_testpackage._setup_hooks.test_pre_hook
+#post-hook.test_post_hook = d2to1_testpackage._setup_hooks.test_post_hook
diff --git a/d2to1/tests/testpackage/setup.py b/d2to1/tests/testpackage/setup.py
new file mode 100755
index 0000000..dbaba47
--- /dev/null
+++ b/d2to1/tests/testpackage/setup.py
@@ -0,0 +1,12 @@
+#!/usr/bin/env python
+try:
+    from setuptools import setup
+except ImportError:
+    from distribute_setup import use_setuptools
+    use_setuptools()
+    from setuptools import setup
+
+setup(
+    setup_requires=['d2to1'],
+    d2to1=True,
+)
diff --git a/d2to1/tests/testpackage/src/testext.c b/d2to1/tests/testpackage/src/testext.c
new file mode 100644
index 0000000..872d43c
--- /dev/null
+++ b/d2to1/tests/testpackage/src/testext.c
@@ -0,0 +1,28 @@
+#include <Python.h>
+
+
+static PyMethodDef TestextMethods[] = {
+    {NULL, NULL, 0, NULL}
+};
+
+
+#if PY_MAJOR_VERSION >=3
+static struct PyModuleDef testextmodule = {
+    PyModuleDef_HEAD_INIT,
+    "testext",
+    -1,
+    TestextMethods
+};
+
+PyObject*
+PyInit_testext(void)
+{
+    return PyModule_Create(&testextmodule);
+}
+#else
+PyMODINIT_FUNC
+inittestext(void)
+{
+    Py_InitModule("testext", TestextMethods);
+}
+#endif
diff --git a/d2to1/tests/util.py b/d2to1/tests/util.py
new file mode 100644
index 0000000..fa55587
--- /dev/null
+++ b/d2to1/tests/util.py
@@ -0,0 +1,35 @@
+from __future__ import with_statement
+
+import contextlib
+import os
+import shutil
+import stat
+
+
+from ..extern.six import moves as m
+ConfigParser = m.configparser.ConfigParser
+
+
+@contextlib.contextmanager
+def open_config(filename):
+    cfg = ConfigParser()
+    cfg.read(filename)
+    yield cfg
+    with open(filename, 'w') as fp:
+        cfg.write(fp)
+
+
+def rmtree(path):
+    """
+    shutil.rmtree() with error handler for 'access denied' from trying to
+    delete read-only files.
+    """
+
+    def onerror(func, path, exc_info):
+        if not os.access(path, os.W_OK):
+            os.chmod(path, stat.S_IWUSR)
+            func(path)
+        else:
+            raise
+
+    return shutil.rmtree(path, onerror=onerror)
diff --git a/debian/changelog b/debian/changelog
index 7843b21..5cf41bc 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,8 +1,9 @@
-d2to1 (0.2.12-3) UNRELEASED; urgency=medium
+d2to1 (0.2.12+git20151002.d16d8fd-1) UNRELEASED; urgency=medium
 
   * Bump debhelper from deprecated 7 to 12.
+  * New upstream snapshot.
 
- -- Debian Janitor <janitor@jelmer.uk>  Mon, 04 Nov 2019 20:50:41 +0000
+ -- Debian Janitor <janitor@jelmer.uk>  Sat, 28 Dec 2019 17:47:04 +0000
 
 d2to1 (0.2.12-2) unstable; urgency=medium
 
diff --git a/setup.cfg b/setup.cfg
index 37b6f7e..36b63e2 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -1,16 +1,16 @@
 [metadata]
 name = d2to1
-version = 0.2.12
+version = 0.2.13.dev
 author = Erik M. Bray
 author-email = embray@stsci.edu
 summary = Allows using distutils2-like setup.cfg files for a package's metadata with a distribute/setuptools setup.py
-description-file = 
-	README.rst
-	CHANGES.rst
-home-page = http://pypi.python.org/pypi/d2to1
+description-file =
+    README.rst
+    CHANGES.rst
+home-page = https://github.com/embray/d2to1
 requires-dist = setuptools
 classifier = 
-	Development Status :: 5 - Production/Stable
+    Development Status :: 5 - Production/Stable
 	Environment :: Plugins
 	Framework :: Setuptools Plugin
 	Intended Audience :: Developers
@@ -23,15 +23,15 @@ classifier =
 	Topic :: System :: Archiving :: Packaging
 
 [files]
-packages = 
-	d2to1
-	d2to1.extern
-extra_files = 
-	CHANGES.rst
-	CONTRIBUTORS
-	LICENSE
-	ez_setup.py
-	ez_setup25.py
+packages =
+    d2to1
+    d2to1.extern
+extra_files =
+    CHANGES.rst
+    CONTRIBUTORS
+    LICENSE
+    ez_setup.py
+    ez_setup25.py
 
 [backwards_compat]
 zip-safe = False
@@ -42,8 +42,8 @@ distutils.setup_keywords =
 	d2to1 = d2to1.core:d2to1
 zest.releaser.prereleaser.before = 
 	d2to1_version = d2to1.zestreleaser:prereleaser_before
-zest.releaser.releaser.middle = 
-	d2to1_git_tag = d2to1.zestreleaser:prereleaser_middle
+zest.releaser.releaser.middle =
+    d2to1_git_tag = d2to1.zestreleaser:prereleaser_middle
 zest.releaser.postreleaser.before = 
 	d2to1_dev_version = d2to1.zestreleaser:postreleaser_before
 
@@ -51,12 +51,12 @@ zest.releaser.postreleaser.before =
 test-suite = nose.collector
 
 [zest.releaser]
+# These zest.releaser hooks are not installed as entry points as they are only
+# used for d2to1 itself--the ones that are installed as entry points are useful
+# to any project that uses d2to1
 prereleaser.before = d2to1.zestreleaser.prereleaser_before
 releaser.middle = d2to1.zestreleaser.releaser_middle
 postreleaser.before = d2to1.zestreleaser.postreleaser_before
 
-[egg_info]
-tag_svn_revision = 0
-tag_build = 
-tag_date = 0
-
+[bdist_wheel]
+universal = 1
diff --git a/tox.ini b/tox.ini
new file mode 100644
index 0000000..fc6e3d4
--- /dev/null
+++ b/tox.ini
@@ -0,0 +1,11 @@
+[tox]
+envlist = py26,py27,py32,py33,py34
+
+[testenv]
+deps =
+    nose
+    numpy
+    setuptools-subversion
+commands =
+    python setup.py test
+sitepackages = True