summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTarek Ziade <tarek@ziade.org>2010-09-19 10:15:10 +0200
committerTarek Ziade <tarek@ziade.org>2010-09-19 10:15:10 +0200
commit5afe5844d0b204e55801b6a02fab6b2e18254448 (patch)
treea65ade5921380d541e2cc30ad307a30917b54d27 /src
parentaddfd74a36216143ed49f25da1cd6030902dad91 (diff)
downloaddisutils2-5afe5844d0b204e55801b6a02fab6b2e18254448.tar.gz
moved everything in the same dir - we want to include docs/ in the release
Diffstat (limited to 'src')
-rw-r--r--src/CHANGES.txt38
-rw-r--r--src/CONTRIBUTORS.txt33
-rw-r--r--src/DEVNOTES.txt14
-rw-r--r--src/README.txt15
-rwxr-xr-xsrc/check.sh2
-rw-r--r--src/distutils2/README13
-rw-r--r--src/distutils2/__init__.py26
-rw-r--r--src/distutils2/_backport/__init__.py8
-rw-r--r--src/distutils2/_backport/_hashopenssl.c524
-rw-r--r--src/distutils2/_backport/hashlib.py143
-rw-r--r--src/distutils2/_backport/md5.c381
-rw-r--r--src/distutils2/_backport/md5.h91
-rw-r--r--src/distutils2/_backport/md5module.c312
-rw-r--r--src/distutils2/_backport/pkgutil.py1155
-rw-r--r--src/distutils2/_backport/sha256module.c701
-rw-r--r--src/distutils2/_backport/sha512module.c769
-rw-r--r--src/distutils2/_backport/shamodule.c593
-rw-r--r--src/distutils2/_backport/shutil.py570
-rw-r--r--src/distutils2/_backport/sysconfig.cfg111
-rw-r--r--src/distutils2/_backport/sysconfig.py718
-rw-r--r--src/distutils2/_backport/tarfile.py2573
-rw-r--r--src/distutils2/_backport/tests/__init__.py20
-rw-r--r--src/distutils2/_backport/tests/fake_dists/bacon-0.1.egg-info/PKG-INFO6
-rw-r--r--src/distutils2/_backport/tests/fake_dists/banana-0.4.egg/EGG-INFO/PKG-INFO18
-rw-r--r--src/distutils2/_backport/tests/fake_dists/banana-0.4.egg/EGG-INFO/SOURCES.txt0
-rw-r--r--src/distutils2/_backport/tests/fake_dists/banana-0.4.egg/EGG-INFO/dependency_links.txt1
-rw-r--r--src/distutils2/_backport/tests/fake_dists/banana-0.4.egg/EGG-INFO/entry_points.txt3
-rw-r--r--src/distutils2/_backport/tests/fake_dists/banana-0.4.egg/EGG-INFO/not-zip-safe1
-rw-r--r--src/distutils2/_backport/tests/fake_dists/banana-0.4.egg/EGG-INFO/requires.txt6
-rw-r--r--src/distutils2/_backport/tests/fake_dists/banana-0.4.egg/EGG-INFO/top_level.txt0
-rw-r--r--src/distutils2/_backport/tests/fake_dists/cheese-2.0.2.egg-info5
-rw-r--r--src/distutils2/_backport/tests/fake_dists/choxie-2.0.0.9.dist-info/INSTALLER0
-rw-r--r--src/distutils2/_backport/tests/fake_dists/choxie-2.0.0.9.dist-info/METADATA8
-rw-r--r--src/distutils2/_backport/tests/fake_dists/choxie-2.0.0.9.dist-info/RECORD0
-rw-r--r--src/distutils2/_backport/tests/fake_dists/choxie-2.0.0.9.dist-info/REQUESTED0
-rw-r--r--src/distutils2/_backport/tests/fake_dists/choxie-2.0.0.9/choxie/__init__.py2
-rw-r--r--src/distutils2/_backport/tests/fake_dists/choxie-2.0.0.9/choxie/chocolate.py10
-rw-r--r--src/distutils2/_backport/tests/fake_dists/choxie-2.0.0.9/truffles.py5
-rw-r--r--src/distutils2/_backport/tests/fake_dists/grammar-1.0a4.dist-info/INSTALLER0
-rw-r--r--src/distutils2/_backport/tests/fake_dists/grammar-1.0a4.dist-info/METADATA5
-rw-r--r--src/distutils2/_backport/tests/fake_dists/grammar-1.0a4.dist-info/RECORD0
-rw-r--r--src/distutils2/_backport/tests/fake_dists/grammar-1.0a4.dist-info/REQUESTED0
-rw-r--r--src/distutils2/_backport/tests/fake_dists/grammar-1.0a4/grammar/__init__.py2
-rw-r--r--src/distutils2/_backport/tests/fake_dists/grammar-1.0a4/grammar/utils.py8
-rw-r--r--src/distutils2/_backport/tests/fake_dists/strawberry-0.6.eggbin1402 -> 0 bytes
-rw-r--r--src/distutils2/_backport/tests/fake_dists/towel_stuff-0.1.dist-info/INSTALLER0
-rw-r--r--src/distutils2/_backport/tests/fake_dists/towel_stuff-0.1.dist-info/METADATA7
-rw-r--r--src/distutils2/_backport/tests/fake_dists/towel_stuff-0.1.dist-info/RECORD0
-rw-r--r--src/distutils2/_backport/tests/fake_dists/towel_stuff-0.1.dist-info/REQUESTED0
-rw-r--r--src/distutils2/_backport/tests/fake_dists/towel_stuff-0.1/towel_stuff/__init__.py18
-rw-r--r--src/distutils2/_backport/tests/fake_dists/truffles-5.0.egg-info3
-rw-r--r--src/distutils2/_backport/tests/test_pkgutil.py610
-rw-r--r--src/distutils2/_backport/tests/test_sysconfig.py305
-rw-r--r--src/distutils2/_trove.py552
-rw-r--r--src/distutils2/command/__init__.py28
-rw-r--r--src/distutils2/command/bdist.py140
-rw-r--r--src/distutils2/command/bdist_dumb.py142
-rw-r--r--src/distutils2/command/bdist_msi.py735
-rw-r--r--src/distutils2/command/bdist_wininst.py359
-rw-r--r--src/distutils2/command/build.py156
-rw-r--r--src/distutils2/command/build_clib.py207
-rw-r--r--src/distutils2/command/build_ext.py740
-rw-r--r--src/distutils2/command/build_py.py436
-rw-r--r--src/distutils2/command/build_scripts.py139
-rw-r--r--src/distutils2/command/check.py88
-rw-r--r--src/distutils2/command/clean.py82
-rw-r--r--src/distutils2/command/cmd.py494
-rw-r--r--src/distutils2/command/command_template45
-rw-r--r--src/distutils2/command/config.py357
-rw-r--r--src/distutils2/command/install.py626
-rw-r--r--src/distutils2/command/install_data.py94
-rw-r--r--src/distutils2/command/install_distinfo.py174
-rw-r--r--src/distutils2/command/install_headers.py50
-rw-r--r--src/distutils2/command/install_lib.py215
-rw-r--r--src/distutils2/command/install_scripts.py62
-rw-r--r--src/distutils2/command/register.py298
-rw-r--r--src/distutils2/command/sdist.py360
-rw-r--r--src/distutils2/command/test.py75
-rw-r--r--src/distutils2/command/upload.py207
-rw-r--r--src/distutils2/command/upload_docs.py156
-rw-r--r--src/distutils2/command/wininst-6.0.exebin61440 -> 0 bytes
-rw-r--r--src/distutils2/command/wininst-7.1.exebin65536 -> 0 bytes
-rw-r--r--src/distutils2/command/wininst-8.0.exebin61440 -> 0 bytes
-rw-r--r--src/distutils2/command/wininst-9.0-amd64.exebin223744 -> 0 bytes
-rw-r--r--src/distutils2/command/wininst-9.0.exebin196096 -> 0 bytes
-rw-r--r--src/distutils2/compat.py64
-rw-r--r--src/distutils2/compiler/__init__.py2
-rw-r--r--src/distutils2/compiler/bcppcompiler.py394
-rw-r--r--src/distutils2/compiler/ccompiler.py1158
-rw-r--r--src/distutils2/compiler/cygwinccompiler.py385
-rw-r--r--src/distutils2/compiler/emxccompiler.py305
-rw-r--r--src/distutils2/compiler/msvc9compiler.py740
-rw-r--r--src/distutils2/compiler/msvccompiler.py659
-rw-r--r--src/distutils2/compiler/unixccompiler.py345
-rw-r--r--src/distutils2/converter/__init__.py0
-rw-r--r--src/distutils2/converter/fixers/__init__.py4
-rw-r--r--src/distutils2/converter/fixers/fix_imports.py52
-rw-r--r--src/distutils2/converter/fixers/fix_setup_options.py85
-rw-r--r--src/distutils2/converter/refactor.py12
-rw-r--r--src/distutils2/core.py219
-rw-r--r--src/distutils2/depgraph.py188
-rw-r--r--src/distutils2/dist.py1032
-rw-r--r--src/distutils2/errors.py134
-rw-r--r--src/distutils2/extension.py137
-rw-r--r--src/distutils2/fancy_getopt.py467
-rw-r--r--src/distutils2/index/__init__.py11
-rw-r--r--src/distutils2/index/base.py46
-rw-r--r--src/distutils2/index/dist.py544
-rw-r--r--src/distutils2/index/errors.py41
-rw-r--r--src/distutils2/index/mirrors.py52
-rw-r--r--src/distutils2/index/simple.py434
-rw-r--r--src/distutils2/index/wrapper.py93
-rw-r--r--src/distutils2/index/xmlrpc.py179
-rw-r--r--src/distutils2/install_tools.py95
-rw-r--r--src/distutils2/log.py71
-rw-r--r--src/distutils2/manifest.py376
-rw-r--r--src/distutils2/metadata.py670
-rw-r--r--src/distutils2/mkpkg.py417
-rw-r--r--src/distutils2/tests/LONG_DESC.txt44
-rw-r--r--src/distutils2/tests/PKG-INFO57
-rw-r--r--src/distutils2/tests/SETUPTOOLS-PKG-INFO182
-rw-r--r--src/distutils2/tests/SETUPTOOLS-PKG-INFO2183
-rw-r--r--src/distutils2/tests/__init__.py135
-rw-r--r--src/distutils2/tests/conversions/01_after.py4
-rw-r--r--src/distutils2/tests/conversions/01_before.py4
-rw-r--r--src/distutils2/tests/conversions/02_after.py46
-rw-r--r--src/distutils2/tests/conversions/02_before.py46
-rw-r--r--src/distutils2/tests/conversions/03_after.py93
-rw-r--r--src/distutils2/tests/conversions/03_before.py93
-rw-r--r--src/distutils2/tests/conversions/04_after.py69
-rw-r--r--src/distutils2/tests/conversions/04_before.py69
-rw-r--r--src/distutils2/tests/conversions/05_after.py137
-rwxr-xr-xsrc/distutils2/tests/conversions/05_before.py137
-rw-r--r--src/distutils2/tests/fixer/__init__.py0
-rw-r--r--src/distutils2/tests/fixer/fix_idioms.py134
-rw-r--r--src/distutils2/tests/pypi_server.py428
-rw-r--r--src/distutils2/tests/pypiserver/downloads_with_md5/simple/badmd5/badmd5-0.1.tar.gz0
-rw-r--r--src/distutils2/tests/pypiserver/downloads_with_md5/simple/badmd5/index.html3
-rw-r--r--src/distutils2/tests/pypiserver/downloads_with_md5/simple/foobar/foobar-0.1.tar.gz0
-rw-r--r--src/distutils2/tests/pypiserver/downloads_with_md5/simple/foobar/index.html3
-rw-r--r--src/distutils2/tests/pypiserver/downloads_with_md5/simple/index.html2
-rw-r--r--src/distutils2/tests/pypiserver/foo_bar_baz/simple/bar/index.html6
-rw-r--r--src/distutils2/tests/pypiserver/foo_bar_baz/simple/baz/index.html6
-rw-r--r--src/distutils2/tests/pypiserver/foo_bar_baz/simple/foo/index.html6
-rw-r--r--src/distutils2/tests/pypiserver/foo_bar_baz/simple/index.html3
-rw-r--r--src/distutils2/tests/pypiserver/project_list/simple/index.html5
-rw-r--r--src/distutils2/tests/pypiserver/test_found_links/simple/foobar/index.html6
-rw-r--r--src/distutils2/tests/pypiserver/test_found_links/simple/index.html1
-rw-r--r--src/distutils2/tests/pypiserver/test_pypi_server/external/index.html1
-rw-r--r--src/distutils2/tests/pypiserver/test_pypi_server/simple/index.html1
-rw-r--r--src/distutils2/tests/pypiserver/with_externals/external/external.html3
-rw-r--r--src/distutils2/tests/pypiserver/with_externals/simple/foobar/index.html4
-rw-r--r--src/distutils2/tests/pypiserver/with_externals/simple/index.html1
-rw-r--r--src/distutils2/tests/pypiserver/with_norel_links/external/homepage.html7
-rw-r--r--src/distutils2/tests/pypiserver/with_norel_links/external/nonrel.html1
-rw-r--r--src/distutils2/tests/pypiserver/with_norel_links/simple/foobar/index.html6
-rw-r--r--src/distutils2/tests/pypiserver/with_norel_links/simple/index.html1
-rw-r--r--src/distutils2/tests/pypiserver/with_real_externals/simple/foobar/index.html4
-rw-r--r--src/distutils2/tests/pypiserver/with_real_externals/simple/index.html1
-rw-r--r--src/distutils2/tests/support.py235
-rw-r--r--src/distutils2/tests/test_Mixin2to3.py73
-rw-r--r--src/distutils2/tests/test_bdist.py41
-rw-r--r--src/distutils2/tests/test_bdist_dumb.py105
-rw-r--r--src/distutils2/tests/test_bdist_msi.py25
-rw-r--r--src/distutils2/tests/test_bdist_wininst.py32
-rw-r--r--src/distutils2/tests/test_build.py57
-rw-r--r--src/distutils2/tests/test_build_clib.py143
-rw-r--r--src/distutils2/tests/test_build_ext.py366
-rw-r--r--src/distutils2/tests/test_build_py.py122
-rw-r--r--src/distutils2/tests/test_build_scripts.py117
-rw-r--r--src/distutils2/tests/test_ccompiler.py60
-rw-r--r--src/distutils2/tests/test_check.py85
-rw-r--r--src/distutils2/tests/test_clean.py50
-rw-r--r--src/distutils2/tests/test_cmd.py110
-rw-r--r--src/distutils2/tests/test_config_cmd.py89
-rw-r--r--src/distutils2/tests/test_core.py98
-rw-r--r--src/distutils2/tests/test_cygwinccompiler.py99
-rw-r--r--src/distutils2/tests/test_depgraph.py187
-rw-r--r--src/distutils2/tests/test_dist.py533
-rw-r--r--src/distutils2/tests/test_emxccompiler.py22
-rw-r--r--src/distutils2/tests/test_extension.py15
-rw-r--r--src/distutils2/tests/test_index_dist.py248
-rw-r--r--src/distutils2/tests/test_index_simple.py316
-rw-r--r--src/distutils2/tests/test_index_xmlrpc.py92
-rw-r--r--src/distutils2/tests/test_install.py220
-rw-r--r--src/distutils2/tests/test_install_data.py76
-rw-r--r--src/distutils2/tests/test_install_distinfo.py202
-rw-r--r--src/distutils2/tests/test_install_headers.py40
-rw-r--r--src/distutils2/tests/test_install_lib.py107
-rw-r--r--src/distutils2/tests/test_install_scripts.py81
-rw-r--r--src/distutils2/tests/test_install_tools.py160
-rw-r--r--src/distutils2/tests/test_manifest.py58
-rw-r--r--src/distutils2/tests/test_metadata.py291
-rw-r--r--src/distutils2/tests/test_msvc9compiler.py143
-rw-r--r--src/distutils2/tests/test_pypi_server.py69
-rw-r--r--src/distutils2/tests/test_pypi_versions.py127
-rw-r--r--src/distutils2/tests/test_register.py262
-rw-r--r--src/distutils2/tests/test_sdist.py423
-rw-r--r--src/distutils2/tests/test_test.py198
-rw-r--r--src/distutils2/tests/test_unixccompiler.py133
-rw-r--r--src/distutils2/tests/test_upload.py140
-rw-r--r--src/distutils2/tests/test_upload_docs.py201
-rw-r--r--src/distutils2/tests/test_util.py484
-rw-r--r--src/distutils2/tests/test_version.py226
-rw-r--r--src/distutils2/tests/xxmodule.c379
-rw-r--r--src/distutils2/util.py1129
-rw-r--r--src/distutils2/version.py433
-rwxr-xr-xsrc/runtests-cov.py136
-rw-r--r--src/runtests.py36
-rw-r--r--src/setup.cfg3
-rw-r--r--src/setup.py230
-rwxr-xr-xsrc/tests.sh40
212 files changed, 0 insertions, 37540 deletions
diff --git a/src/CHANGES.txt b/src/CHANGES.txt
deleted file mode 100644
index 8bc3e6e..0000000
--- a/src/CHANGES.txt
+++ /dev/null
@@ -1,38 +0,0 @@
-=======
-CHANGES
-=======
-
-1.0a2 - ?
----------
-
-- Add a converter for distutils/setuptools-based setup scripts [tarek]
-- Factor out MANIFEST[.in] support into disutils2.manifest [tarek]
-- Implement pkgutil APIs described in PEP 376 [josip]
-- Add PEP 376 .dist-info support in Distribute [josip]
-- Add distutils2.depgraph, a dependency graph builder [josip]
-- Add a mock server to test network-using code [alexis, konrad]
-- Add distutils2.index, a comprehensive subpackage to query PyPI [alexis]
-- Add 2to3 support to the build command [zubin]
-- Enhance the check command (sanity tests) [konrad]
-- Make sdist include source files used by other commands [jeremy]
-- Change install_egg_info to install_distinfo (PEP 376) [josip]
-- Import the upload_docs command from distribute [konrad]
-- Add a test command [konrad]
-- Add post and pre-hooks for build and install [konrad]
-- Remove PyPIRCCommand, move its helper code into util [tarek]
-- Remove Mac OS 9 support [éric]
-- Start adding docstrings to interface methods [jeremy]
-- Move documentation from the stdlib [ali, éric]
-- Lots of bug fixes, cleanups, tests [everyone]
-
-
-1.0a1 - 2010-05-06
-------------------
-
-- Initial import from the stdlib [tarek]
-- Add support for PEP 386 in distutils2.version [tarek]
-- Add support for PEP 345 in distutils2.metadata [tarek]
-- Add mkpkg, a helper script to create a setup.py [sean]
-- Remove bdist_rpm command [tarek]
-- Add some PEP 376 functions to pkgutil [michael]
-- Add distutils2.util.find_packages [tarek]
diff --git a/src/CONTRIBUTORS.txt b/src/CONTRIBUTORS.txt
deleted file mode 100644
index f501efc..0000000
--- a/src/CONTRIBUTORS.txt
+++ /dev/null
@@ -1,33 +0,0 @@
-============
-Contributors
-============
-
-Distutils2 is a project that was started and that is maintained by
-Tarek Ziadé, and many people are contributing to the project.
-
-If you did, please add your name below in alphabetical order!
-
-Thanks to:
-
-- Ali Afshar
-- Éric Araujo
-- Pior Bastida
-- Anthony Baxter
-- Titus Brown
-- Nicolas Cadou
-- Konrad Delong
-- Josip Djolonga
-- Yannick Gingras
-- Jeremy Kloth
-- Martin von Löwis
-- Carl Meyer
-- Alexis Métaireau
-- Zubin Mithra
-- Michael Mulich
-- George Peristerakis
-- Sean Reifschneider
-- Antoine Reversat
-- Luis Rojas
-- Erik Rose
-- Brian Rosner
-- Alexandre Vassalotti
diff --git a/src/DEVNOTES.txt b/src/DEVNOTES.txt
deleted file mode 100644
index e0753df..0000000
--- a/src/DEVNOTES.txt
+++ /dev/null
@@ -1,14 +0,0 @@
-Notes for developers
-====================
-
-- Distutils2 runs on Python from 2.4 to 3.2 (3.x not implemented yet),
- so make sure you don't use a syntax that doesn't work under
- one of these Python versions.
-
-- Always run tests.sh before you push a change. This implies
- that you have all Python versions installed from 2.4 to 2.7.
-
-- With Python 2.4, if you want to run tests with runtests.py, or run
- just one test directly, be sure to run python2.4 setup.py build_ext
- first, else tests won't find _hashlib or _md5. When using tests.sh,
- build_ext is automatically done.
diff --git a/src/README.txt b/src/README.txt
deleted file mode 100644
index 32f8a7e..0000000
--- a/src/README.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-==========
-Distutils2
-==========
-
-Welcome to Distutils2!
-
-Distutils2 is the new version of Distutils. It's not backward compatible with
-Distutils but provides more features, and implement most new packaging
-standards.
-
-See the documentation at http://packages.python.org/Distutils2 for more info.
-
-**Beware that Distutils2 is in its early stage and should not be used in
-production. Its API is subject to changes**
-
diff --git a/src/check.sh b/src/check.sh
deleted file mode 100755
index bc77bf9..0000000
--- a/src/check.sh
+++ /dev/null
@@ -1,2 +0,0 @@
-pep8 distutils2
-pyflakes distutils2
diff --git a/src/distutils2/README b/src/distutils2/README
deleted file mode 100644
index 4afd700..0000000
--- a/src/distutils2/README
+++ /dev/null
@@ -1,13 +0,0 @@
-This directory contains the Distutils2 package.
-
-There's a full documentation available at:
-
- http://docs.python.org/distutils/
-
-The Distutils-SIG web page is also a good starting point:
-
- http://www.python.org/sigs/distutils-sig/
-
-WARNING: Distutils2 must remain compatible with Python 2.4
-
-$Id: README 70017 2009-02-27 12:53:34Z tarek.ziade $
diff --git a/src/distutils2/__init__.py b/src/distutils2/__init__.py
deleted file mode 100644
index 4d330b3..0000000
--- a/src/distutils2/__init__.py
+++ /dev/null
@@ -1,26 +0,0 @@
-"""distutils
-
-The main package for the Python Distribution Utilities 2. Setup
-scripts should import the setup function from distutils2.core:
-
- from distutils2.core import setup
-
- setup(name=..., version=..., ...)
-
-Third-party tools can use parts of Distutils2 as building blocks
-without causing the other modules to be imported:
-
- import distutils2.version
- import distutils2.pypi.simple
- import distutils2.tests.pypi_server
-"""
-__all__ = ['__version__']
-
-__revision__ = "$Id: __init__.py 78020 2010-02-06 16:37:32Z benjamin.peterson $"
-__version__ = "1.0a2"
-
-
-# when set to True, converts doctests by default too
-run_2to3_on_doctests = True
-# Standard package names for fixer packages
-lib2to3_fixer_packages = ['lib2to3.fixes']
diff --git a/src/distutils2/_backport/__init__.py b/src/distutils2/_backport/__init__.py
deleted file mode 100644
index bfbf6ec..0000000
--- a/src/distutils2/_backport/__init__.py
+++ /dev/null
@@ -1,8 +0,0 @@
-"""Things that will land in the Python 3.3 std lib but which we must drag along
-with us for now to support 2.x."""
-
-def any(seq):
- for elem in seq:
- if elem:
- return True
- return False
diff --git a/src/distutils2/_backport/_hashopenssl.c b/src/distutils2/_backport/_hashopenssl.c
deleted file mode 100644
index fdcae5d..0000000
--- a/src/distutils2/_backport/_hashopenssl.c
+++ /dev/null
@@ -1,524 +0,0 @@
-/* Module that wraps all OpenSSL hash algorithms */
-
-/*
- * Copyright (C) 2005 Gregory P. Smith (greg@krypto.org)
- * Licensed to PSF under a Contributor Agreement.
- *
- * Derived from a skeleton of shamodule.c containing work performed by:
- *
- * Andrew Kuchling (amk@amk.ca)
- * Greg Stein (gstein@lyra.org)
- *
- */
-
-#define PY_SSIZE_T_CLEAN
-
-#include "Python.h"
-#include "structmember.h"
-
-#if (PY_VERSION_HEX < 0x02050000)
-#define Py_ssize_t int
-#endif
-
-/* EVP is the preferred interface to hashing in OpenSSL */
-#include <openssl/evp.h>
-
-#define MUNCH_SIZE INT_MAX
-
-
-#ifndef HASH_OBJ_CONSTRUCTOR
-#define HASH_OBJ_CONSTRUCTOR 0
-#endif
-
-typedef struct {
- PyObject_HEAD
- PyObject *name; /* name of this hash algorithm */
- EVP_MD_CTX ctx; /* OpenSSL message digest context */
-} EVPobject;
-
-
-static PyTypeObject EVPtype;
-
-
-#define DEFINE_CONSTS_FOR_NEW(Name) \
- static PyObject *CONST_ ## Name ## _name_obj; \
- static EVP_MD_CTX CONST_new_ ## Name ## _ctx; \
- static EVP_MD_CTX *CONST_new_ ## Name ## _ctx_p = NULL;
-
-DEFINE_CONSTS_FOR_NEW(md5)
-DEFINE_CONSTS_FOR_NEW(sha1)
-DEFINE_CONSTS_FOR_NEW(sha224)
-DEFINE_CONSTS_FOR_NEW(sha256)
-DEFINE_CONSTS_FOR_NEW(sha384)
-DEFINE_CONSTS_FOR_NEW(sha512)
-
-
-static EVPobject *
-newEVPobject(PyObject *name)
-{
- EVPobject *retval = (EVPobject *)PyObject_New(EVPobject, &EVPtype);
-
- /* save the name for .name to return */
- if (retval != NULL) {
- Py_INCREF(name);
- retval->name = name;
- }
-
- return retval;
-}
-
-/* Internal methods for a hash object */
-
-static void
-EVP_dealloc(PyObject *ptr)
-{
- EVP_MD_CTX_cleanup(&((EVPobject *)ptr)->ctx);
- Py_XDECREF(((EVPobject *)ptr)->name);
- PyObject_Del(ptr);
-}
-
-
-/* External methods for a hash object */
-
-PyDoc_STRVAR(EVP_copy__doc__, "Return a copy of the hash object.");
-
-static PyObject *
-EVP_copy(EVPobject *self, PyObject *unused)
-{
- EVPobject *newobj;
-
- if ( (newobj = newEVPobject(self->name))==NULL)
- return NULL;
-
- EVP_MD_CTX_copy(&newobj->ctx, &self->ctx);
- return (PyObject *)newobj;
-}
-
-PyDoc_STRVAR(EVP_digest__doc__,
-"Return the digest value as a string of binary data.");
-
-static PyObject *
-EVP_digest(EVPobject *self, PyObject *unused)
-{
- unsigned char digest[EVP_MAX_MD_SIZE];
- EVP_MD_CTX temp_ctx;
- PyObject *retval;
- unsigned int digest_size;
-
- EVP_MD_CTX_copy(&temp_ctx, &self->ctx);
- digest_size = EVP_MD_CTX_size(&temp_ctx);
- EVP_DigestFinal(&temp_ctx, digest, NULL);
-
- retval = PyString_FromStringAndSize((const char *)digest, digest_size);
- EVP_MD_CTX_cleanup(&temp_ctx);
- return retval;
-}
-
-PyDoc_STRVAR(EVP_hexdigest__doc__,
-"Return the digest value as a string of hexadecimal digits.");
-
-static PyObject *
-EVP_hexdigest(EVPobject *self, PyObject *unused)
-{
- unsigned char digest[EVP_MAX_MD_SIZE];
- EVP_MD_CTX temp_ctx;
- PyObject *retval;
- char *hex_digest;
- unsigned int i, j, digest_size;
-
- /* Get the raw (binary) digest value */
- EVP_MD_CTX_copy(&temp_ctx, &self->ctx);
- digest_size = EVP_MD_CTX_size(&temp_ctx);
- EVP_DigestFinal(&temp_ctx, digest, NULL);
-
- EVP_MD_CTX_cleanup(&temp_ctx);
-
- /* Create a new string */
- /* NOTE: not thread safe! modifying an already created string object */
- /* (not a problem because we hold the GIL by default) */
- retval = PyString_FromStringAndSize(NULL, digest_size * 2);
- if (!retval)
- return NULL;
- hex_digest = PyString_AsString(retval);
- if (!hex_digest) {
- Py_DECREF(retval);
- return NULL;
- }
-
- /* Make hex version of the digest */
- for(i=j=0; i<digest_size; i++) {
- char c;
- c = (digest[i] >> 4) & 0xf;
- c = (c>9) ? c+'a'-10 : c + '0';
- hex_digest[j++] = c;
- c = (digest[i] & 0xf);
- c = (c>9) ? c+'a'-10 : c + '0';
- hex_digest[j++] = c;
- }
- return retval;
-}
-
-PyDoc_STRVAR(EVP_update__doc__,
-"Update this hash object's state with the provided string.");
-
-static PyObject *
-EVP_update(EVPobject *self, PyObject *args)
-{
- unsigned char *cp;
- Py_ssize_t len;
-
- if (!PyArg_ParseTuple(args, "s#:update", &cp, &len))
- return NULL;
-
- if (len > 0 && len <= MUNCH_SIZE) {
- EVP_DigestUpdate(&self->ctx, cp, Py_SAFE_DOWNCAST(len, Py_ssize_t,
- unsigned int));
- } else {
- Py_ssize_t offset = 0;
- while (len) {
- unsigned int process = len > MUNCH_SIZE ? MUNCH_SIZE : len;
- EVP_DigestUpdate(&self->ctx, cp + offset, process);
- len -= process;
- offset += process;
- }
- }
- Py_INCREF(Py_None);
- return Py_None;
-}
-
-static PyMethodDef EVP_methods[] = {
- {"update", (PyCFunction)EVP_update, METH_VARARGS, EVP_update__doc__},
- {"digest", (PyCFunction)EVP_digest, METH_NOARGS, EVP_digest__doc__},
- {"hexdigest", (PyCFunction)EVP_hexdigest, METH_NOARGS, EVP_hexdigest__doc__},
- {"copy", (PyCFunction)EVP_copy, METH_NOARGS, EVP_copy__doc__},
- {NULL, NULL} /* sentinel */
-};
-
-static PyObject *
-EVP_get_block_size(EVPobject *self, void *closure)
-{
- return PyInt_FromLong(EVP_MD_CTX_block_size(&((EVPobject *)self)->ctx));
-}
-
-static PyObject *
-EVP_get_digest_size(EVPobject *self, void *closure)
-{
- return PyInt_FromLong(EVP_MD_CTX_size(&((EVPobject *)self)->ctx));
-}
-
-static PyMemberDef EVP_members[] = {
- {"name", T_OBJECT, offsetof(EVPobject, name), READONLY, PyDoc_STR("algorithm name.")},
- {NULL} /* Sentinel */
-};
-
-static PyGetSetDef EVP_getseters[] = {
- {"digest_size",
- (getter)EVP_get_digest_size, NULL,
- NULL,
- NULL},
- {"block_size",
- (getter)EVP_get_block_size, NULL,
- NULL,
- NULL},
- /* the old md5 and sha modules support 'digest_size' as in PEP 247.
- * the old sha module also supported 'digestsize'. ugh. */
- {"digestsize",
- (getter)EVP_get_digest_size, NULL,
- NULL,
- NULL},
- {NULL} /* Sentinel */
-};
-
-
-static PyObject *
-EVP_repr(PyObject *self)
-{
- char buf[100];
- PyOS_snprintf(buf, sizeof(buf), "<%s HASH object @ %p>",
- PyString_AsString(((EVPobject *)self)->name), self);
- return PyString_FromString(buf);
-}
-
-#if HASH_OBJ_CONSTRUCTOR
-static int
-EVP_tp_init(EVPobject *self, PyObject *args, PyObject *kwds)
-{
- static char *kwlist[] = {"name", "string", NULL};
- PyObject *name_obj = NULL;
- char *nameStr;
- unsigned char *cp = NULL;
- Py_ssize_t len = 0;
- const EVP_MD *digest;
-
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|s#:HASH", kwlist,
- &name_obj, &cp, &len)) {
- return -1;
- }
-
- if (!PyArg_Parse(name_obj, "s", &nameStr)) {
- PyErr_SetString(PyExc_TypeError, "name must be a string");
- return -1;
- }
-
- digest = EVP_get_digestbyname(nameStr);
- if (!digest) {
- PyErr_SetString(PyExc_ValueError, "unknown hash function");
- return -1;
- }
- EVP_DigestInit(&self->ctx, digest);
-
- self->name = name_obj;
- Py_INCREF(self->name);
-
- if (cp && len) {
- if (len > 0 && len <= MUNCH_SIZE) {
- EVP_DigestUpdate(&self->ctx, cp, Py_SAFE_DOWNCAST(len, Py_ssize_t,
- unsigned int));
- } else {
- Py_ssize_t offset = 0;
- while (len) {
- unsigned int process = len > MUNCH_SIZE ? MUNCH_SIZE : len;
- EVP_DigestUpdate(&self->ctx, cp + offset, process);
- len -= process;
- offset += process;
- }
- }
- }
-
- return 0;
-}
-#endif
-
-
-PyDoc_STRVAR(hashtype_doc,
-"A hash represents the object used to calculate a checksum of a\n\
-string of information.\n\
-\n\
-Methods:\n\
-\n\
-update() -- updates the current digest with an additional string\n\
-digest() -- return the current digest value\n\
-hexdigest() -- return the current digest as a string of hexadecimal digits\n\
-copy() -- return a copy of the current hash object\n\
-\n\
-Attributes:\n\
-\n\
-name -- the hash algorithm being used by this object\n\
-digest_size -- number of bytes in this hashes output\n");
-
-static PyTypeObject EVPtype = {
- PyObject_HEAD_INIT(NULL)
- 0, /*ob_size*/
- "_hashlib.HASH", /*tp_name*/
- sizeof(EVPobject), /*tp_basicsize*/
- 0, /*tp_itemsize*/
- /* methods */
- EVP_dealloc, /*tp_dealloc*/
- 0, /*tp_print*/
- 0, /*tp_getattr*/
- 0, /*tp_setattr*/
- 0, /*tp_compare*/
- EVP_repr, /*tp_repr*/
- 0, /*tp_as_number*/
- 0, /*tp_as_sequence*/
- 0, /*tp_as_mapping*/
- 0, /*tp_hash*/
- 0, /*tp_call*/
- 0, /*tp_str*/
- 0, /*tp_getattro*/
- 0, /*tp_setattro*/
- 0, /*tp_as_buffer*/
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
- hashtype_doc, /*tp_doc*/
- 0, /*tp_traverse*/
- 0, /*tp_clear*/
- 0, /*tp_richcompare*/
- 0, /*tp_weaklistoffset*/
- 0, /*tp_iter*/
- 0, /*tp_iternext*/
- EVP_methods, /* tp_methods */
- EVP_members, /* tp_members */
- EVP_getseters, /* tp_getset */
-#if 1
- 0, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
-#endif
-#if HASH_OBJ_CONSTRUCTOR
- (initproc)EVP_tp_init, /* tp_init */
-#endif
-};
-
-static PyObject *
-EVPnew(PyObject *name_obj,
- const EVP_MD *digest, const EVP_MD_CTX *initial_ctx,
- const unsigned char *cp, Py_ssize_t len)
-{
- EVPobject *self;
-
- if (!digest && !initial_ctx) {
- PyErr_SetString(PyExc_ValueError, "unsupported hash type");
- return NULL;
- }
-
- if ((self = newEVPobject(name_obj)) == NULL)
- return NULL;
-
- if (initial_ctx) {
- EVP_MD_CTX_copy(&self->ctx, initial_ctx);
- } else {
- EVP_DigestInit(&self->ctx, digest);
- }
-
- if (cp && len) {
- if (len > 0 && len <= MUNCH_SIZE) {
- EVP_DigestUpdate(&self->ctx, cp, Py_SAFE_DOWNCAST(len, Py_ssize_t,
- unsigned int));
- } else {
- Py_ssize_t offset = 0;
- while (len) {
- unsigned int process = len > MUNCH_SIZE ? MUNCH_SIZE : len;
- EVP_DigestUpdate(&self->ctx, cp + offset, process);
- len -= process;
- offset += process;
- }
- }
- }
-
- return (PyObject *)self;
-}
-
-
-/* The module-level function: new() */
-
-PyDoc_STRVAR(EVP_new__doc__,
-"Return a new hash object using the named algorithm.\n\
-An optional string argument may be provided and will be\n\
-automatically hashed.\n\
-\n\
-The MD5 and SHA1 algorithms are always supported.\n");
-
-static PyObject *
-EVP_new(PyObject *self, PyObject *args, PyObject *kwdict)
-{
- static char *kwlist[] = {"name", "string", NULL};
- PyObject *name_obj = NULL;
- char *name;
- const EVP_MD *digest;
- unsigned char *cp = NULL;
- Py_ssize_t len = 0;
-
- if (!PyArg_ParseTupleAndKeywords(args, kwdict, "O|s#:new", kwlist,
- &name_obj, &cp, &len)) {
- return NULL;
- }
-
- if (!PyArg_Parse(name_obj, "s", &name)) {
- PyErr_SetString(PyExc_TypeError, "name must be a string");
- return NULL;
- }
-
- digest = EVP_get_digestbyname(name);
-
- return EVPnew(name_obj, digest, NULL, cp, len);
-}
-
-/*
- * This macro generates constructor function definitions for specific
- * hash algorithms. These constructors are much faster than calling
- * the generic one passing it a python string and are noticably
- * faster than calling a python new() wrapper. Thats important for
- * code that wants to make hashes of a bunch of small strings.
- */
-#define GEN_CONSTRUCTOR(NAME) \
- static PyObject * \
- EVP_new_ ## NAME (PyObject *self, PyObject *args) \
- { \
- unsigned char *cp = NULL; \
- Py_ssize_t len = 0; \
- \
- if (!PyArg_ParseTuple(args, "|s#:" #NAME , &cp, &len)) { \
- return NULL; \
- } \
- \
- return EVPnew( \
- CONST_ ## NAME ## _name_obj, \
- NULL, \
- CONST_new_ ## NAME ## _ctx_p, \
- cp, len); \
- }
-
-/* a PyMethodDef structure for the constructor */
-#define CONSTRUCTOR_METH_DEF(NAME) \
- {"openssl_" #NAME, (PyCFunction)EVP_new_ ## NAME, METH_VARARGS, \
- PyDoc_STR("Returns a " #NAME \
- " hash object; optionally initialized with a string") \
- }
-
-/* used in the init function to setup a constructor */
-#define INIT_CONSTRUCTOR_CONSTANTS(NAME) do { \
- CONST_ ## NAME ## _name_obj = PyString_FromString(#NAME); \
- if (EVP_get_digestbyname(#NAME)) { \
- CONST_new_ ## NAME ## _ctx_p = &CONST_new_ ## NAME ## _ctx; \
- EVP_DigestInit(CONST_new_ ## NAME ## _ctx_p, EVP_get_digestbyname(#NAME)); \
- } \
-} while (0);
-
-GEN_CONSTRUCTOR(md5)
-GEN_CONSTRUCTOR(sha1)
-GEN_CONSTRUCTOR(sha224)
-GEN_CONSTRUCTOR(sha256)
-GEN_CONSTRUCTOR(sha384)
-GEN_CONSTRUCTOR(sha512)
-
-/* List of functions exported by this module */
-
-static struct PyMethodDef EVP_functions[] = {
- {"new", (PyCFunction)EVP_new, METH_VARARGS|METH_KEYWORDS, EVP_new__doc__},
- CONSTRUCTOR_METH_DEF(md5),
- CONSTRUCTOR_METH_DEF(sha1),
- CONSTRUCTOR_METH_DEF(sha224),
- CONSTRUCTOR_METH_DEF(sha256),
- CONSTRUCTOR_METH_DEF(sha384),
- CONSTRUCTOR_METH_DEF(sha512),
- {NULL, NULL} /* Sentinel */
-};
-
-
-/* Initialize this module. */
-
-PyMODINIT_FUNC
-init_hashlib(void)
-{
- PyObject *m;
-
- OpenSSL_add_all_digests();
-
- /* TODO build EVP_functions openssl_* entries dynamically based
- * on what hashes are supported rather than listing many
- * but having some be unsupported. Only init appropriate
- * constants. */
-
- EVPtype.ob_type = &PyType_Type;
- if (PyType_Ready(&EVPtype) < 0)
- return;
-
- m = Py_InitModule("_hashlib", EVP_functions);
- if (m == NULL)
- return;
-
-#if HASH_OBJ_CONSTRUCTOR
- Py_INCREF(&EVPtype);
- PyModule_AddObject(m, "HASH", (PyObject *)&EVPtype);
-#endif
-
- /* these constants are used by the convenience constructors */
- INIT_CONSTRUCTOR_CONSTANTS(md5);
- INIT_CONSTRUCTOR_CONSTANTS(sha1);
- INIT_CONSTRUCTOR_CONSTANTS(sha224);
- INIT_CONSTRUCTOR_CONSTANTS(sha256);
- INIT_CONSTRUCTOR_CONSTANTS(sha384);
- INIT_CONSTRUCTOR_CONSTANTS(sha512);
-}
diff --git a/src/distutils2/_backport/hashlib.py b/src/distutils2/_backport/hashlib.py
deleted file mode 100644
index dd2b02a..0000000
--- a/src/distutils2/_backport/hashlib.py
+++ /dev/null
@@ -1,143 +0,0 @@
-# $Id$
-#
-# Copyright (C) 2005 Gregory P. Smith (greg@krypto.org)
-# Licensed to PSF under a Contributor Agreement.
-#
-
-__doc__ = """hashlib module - A common interface to many hash functions.
-
-new(name, string='') - returns a new hash object implementing the
- given hash function; initializing the hash
- using the given string data.
-
-Named constructor functions are also available, these are much faster
-than using new():
-
-md5(), sha1(), sha224(), sha256(), sha384(), and sha512()
-
-More algorithms may be available on your platform but the above are
-guaranteed to exist.
-
-NOTE: If you want the adler32 or crc32 hash functions they are available in
-the zlib module.
-
-Choose your hash function wisely. Some have known collision weaknesses.
-sha384 and sha512 will be slow on 32 bit platforms.
-
-Hash objects have these methods:
- - update(arg): Update the hash object with the string arg. Repeated calls
- are equivalent to a single call with the concatenation of all
- the arguments.
- - digest(): Return the digest of the strings passed to the update() method
- so far. This may contain non-ASCII characters, including
- NUL bytes.
- - hexdigest(): Like digest() except the digest is returned as a string of
- double length, containing only hexadecimal digits.
- - copy(): Return a copy (clone) of the hash object. This can be used to
- efficiently compute the digests of strings that share a common
- initial substring.
-
-For example, to obtain the digest of the string 'Nobody inspects the
-spammish repetition':
-
- >>> import hashlib
- >>> m = hashlib.md5()
- >>> m.update("Nobody inspects")
- >>> m.update(" the spammish repetition")
- >>> m.digest()
- '\\xbbd\\x9c\\x83\\xdd\\x1e\\xa5\\xc9\\xd9\\xde\\xc9\\xa1\\x8d\\xf0\\xff\\xe9'
-
-More condensed:
-
- >>> hashlib.sha224("Nobody inspects the spammish repetition").hexdigest()
- 'a4337bc45a8fc544c03f52dc550cd6e1e87021bc896588bd79e901e2'
-
-"""
-
-# This tuple and __get_builtin_constructor() must be modified if a new
-# always available algorithm is added.
-__always_supported = ('md5', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512')
-
-algorithms = __always_supported
-
-__all__ = __always_supported + ('new', 'algorithms')
-
-
-def __get_builtin_constructor(name):
- if name in ('SHA1', 'sha1'):
- from distutils2._backport import _sha
- return _sha.new
- elif name in ('MD5', 'md5'):
- from distutils2._backport import _md5
- return _md5.new
- elif name in ('SHA256', 'sha256', 'SHA224', 'sha224'):
- from distutils2._backport import _sha256
- bs = name[3:]
- if bs == '256':
- return _sha256.sha256
- elif bs == '224':
- return _sha256.sha224
- elif name in ('SHA512', 'sha512', 'SHA384', 'sha384'):
- from distutils2._backport import _sha512
- bs = name[3:]
- if bs == '512':
- return _sha512.sha512
- elif bs == '384':
- return _sha512.sha384
-
- raise ValueError('unsupported hash type %s' % name)
-
-
-def __get_openssl_constructor(name):
- try:
- f = getattr(_hashlib, 'openssl_' + name)
- # Allow the C module to raise ValueError. The function will be
- # defined but the hash not actually available thanks to OpenSSL.
- f()
- # Use the C function directly (very fast)
- return f
- except (AttributeError, ValueError):
- return __get_builtin_constructor(name)
-
-
-def __py_new(name, string=''):
- """new(name, string='') - Return a new hashing object using the named algorithm;
- optionally initialized with a string.
- """
- return __get_builtin_constructor(name)(string)
-
-
-def __hash_new(name, string=''):
- """new(name, string='') - Return a new hashing object using the named algorithm;
- optionally initialized with a string.
- """
- try:
- return _hashlib.new(name, string)
- except ValueError:
- # If the _hashlib module (OpenSSL) doesn't support the named
- # hash, try using our builtin implementations.
- # This allows for SHA224/256 and SHA384/512 support even though
- # the OpenSSL library prior to 0.9.8 doesn't provide them.
- return __get_builtin_constructor(name)(string)
-
-
-try:
- from distutils2._backport import _hashlib
- new = __hash_new
- __get_hash = __get_openssl_constructor
-except ImportError:
- new = __py_new
- __get_hash = __get_builtin_constructor
-
-for __func_name in __always_supported:
- # try them all, some may not work due to the OpenSSL
- # version not supporting that algorithm.
- try:
- globals()[__func_name] = __get_hash(__func_name)
- except ValueError:
- import logging
- logging.exception('code for hash %s was not found.', __func_name)
-
-# Cleanup locals()
-del __always_supported, __func_name, __get_hash
-del __py_new, __hash_new, __get_openssl_constructor
diff --git a/src/distutils2/_backport/md5.c b/src/distutils2/_backport/md5.c
deleted file mode 100644
index c35d96c..0000000
--- a/src/distutils2/_backport/md5.c
+++ /dev/null
@@ -1,381 +0,0 @@
-/*
- Copyright (C) 1999, 2000, 2002 Aladdin Enterprises. All rights reserved.
-
- This software is provided 'as-is', without any express or implied
- warranty. In no event will the authors be held liable for any damages
- arising from the use of this software.
-
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it
- freely, subject to the following restrictions:
-
- 1. The origin of this software must not be misrepresented; you must not
- claim that you wrote the original software. If you use this software
- in a product, an acknowledgment in the product documentation would be
- appreciated but is not required.
- 2. Altered source versions must be plainly marked as such, and must not be
- misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source distribution.
-
- L. Peter Deutsch
- ghost@aladdin.com
-
- */
-/* $Id: md5.c,v 1.6 2002/04/13 19:20:28 lpd Exp $ */
-/*
- Independent implementation of MD5 (RFC 1321).
-
- This code implements the MD5 Algorithm defined in RFC 1321, whose
- text is available at
- http://www.ietf.org/rfc/rfc1321.txt
- The code is derived from the text of the RFC, including the test suite
- (section A.5) but excluding the rest of Appendix A. It does not include
- any code or documentation that is identified in the RFC as being
- copyrighted.
-
- The original and principal author of md5.c is L. Peter Deutsch
- <ghost@aladdin.com>. Other authors are noted in the change history
- that follows (in reverse chronological order):
-
- 2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order
- either statically or dynamically; added missing #include <string.h>
- in library.
- 2002-03-11 lpd Corrected argument list for main(), and added int return
- type, in test program and T value program.
- 2002-02-21 lpd Added missing #include <stdio.h> in test program.
- 2000-07-03 lpd Patched to eliminate warnings about "constant is
- unsigned in ANSI C, signed in traditional"; made test program
- self-checking.
- 1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
- 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5).
- 1999-05-03 lpd Original version.
- */
-
-#include "md5.h"
-#include <string.h>
-
-#undef BYTE_ORDER /* 1 = big-endian, -1 = little-endian, 0 = unknown */
-#ifdef ARCH_IS_BIG_ENDIAN
-# define BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1)
-#else
-# define BYTE_ORDER 0
-#endif
-
-#define T_MASK ((md5_word_t)~0)
-#define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87)
-#define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9)
-#define T3 0x242070db
-#define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111)
-#define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050)
-#define T6 0x4787c62a
-#define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec)
-#define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe)
-#define T9 0x698098d8
-#define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850)
-#define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e)
-#define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841)
-#define T13 0x6b901122
-#define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c)
-#define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71)
-#define T16 0x49b40821
-#define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d)
-#define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf)
-#define T19 0x265e5a51
-#define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855)
-#define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2)
-#define T22 0x02441453
-#define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e)
-#define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437)
-#define T25 0x21e1cde6
-#define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829)
-#define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278)
-#define T28 0x455a14ed
-#define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa)
-#define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07)
-#define T31 0x676f02d9
-#define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375)
-#define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd)
-#define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e)
-#define T35 0x6d9d6122
-#define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3)
-#define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb)
-#define T38 0x4bdecfa9
-#define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f)
-#define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f)
-#define T41 0x289b7ec6
-#define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805)
-#define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a)
-#define T44 0x04881d05
-#define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6)
-#define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a)
-#define T47 0x1fa27cf8
-#define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a)
-#define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb)
-#define T50 0x432aff97
-#define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58)
-#define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6)
-#define T53 0x655b59c3
-#define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d)
-#define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82)
-#define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e)
-#define T57 0x6fa87e4f
-#define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f)
-#define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb)
-#define T60 0x4e0811a1
-#define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d)
-#define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca)
-#define T63 0x2ad7d2bb
-#define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e)
-
-
-static void
-md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/)
-{
- md5_word_t
- a = pms->abcd[0], b = pms->abcd[1],
- c = pms->abcd[2], d = pms->abcd[3];
- md5_word_t t;
-#if BYTE_ORDER > 0
- /* Define storage only for big-endian CPUs. */
- md5_word_t X[16];
-#else
- /* Define storage for little-endian or both types of CPUs. */
- md5_word_t xbuf[16];
- const md5_word_t *X;
-#endif
-
- {
-#if BYTE_ORDER == 0
- /*
- * Determine dynamically whether this is a big-endian or
- * little-endian machine, since we can use a more efficient
- * algorithm on the latter.
- */
- static const int w = 1;
-
- if (*((const md5_byte_t *)&w)) /* dynamic little-endian */
-#endif
-#if BYTE_ORDER <= 0 /* little-endian */
- {
- /*
- * On little-endian machines, we can process properly aligned
- * data without copying it.
- */
- if (!((data - (const md5_byte_t *)0) & 3)) {
- /* data are properly aligned */
- X = (const md5_word_t *)data;
- } else {
- /* not aligned */
- memcpy(xbuf, data, 64);
- X = xbuf;
- }
- }
-#endif
-#if BYTE_ORDER == 0
- else /* dynamic big-endian */
-#endif
-#if BYTE_ORDER >= 0 /* big-endian */
- {
- /*
- * On big-endian machines, we must arrange the bytes in the
- * right order.
- */
- const md5_byte_t *xp = data;
- int i;
-
-# if BYTE_ORDER == 0
- X = xbuf; /* (dynamic only) */
-# else
-# define xbuf X /* (static only) */
-# endif
- for (i = 0; i < 16; ++i, xp += 4)
- xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);
- }
-#endif
- }
-
-#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
-
- /* Round 1. */
- /* Let [abcd k s i] denote the operation
- a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
-#define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
-#define SET(a, b, c, d, k, s, Ti)\
- t = a + F(b,c,d) + X[k] + Ti;\
- a = ROTATE_LEFT(t, s) + b
- /* Do the following 16 operations. */
- SET(a, b, c, d, 0, 7, T1);
- SET(d, a, b, c, 1, 12, T2);
- SET(c, d, a, b, 2, 17, T3);
- SET(b, c, d, a, 3, 22, T4);
- SET(a, b, c, d, 4, 7, T5);
- SET(d, a, b, c, 5, 12, T6);
- SET(c, d, a, b, 6, 17, T7);
- SET(b, c, d, a, 7, 22, T8);
- SET(a, b, c, d, 8, 7, T9);
- SET(d, a, b, c, 9, 12, T10);
- SET(c, d, a, b, 10, 17, T11);
- SET(b, c, d, a, 11, 22, T12);
- SET(a, b, c, d, 12, 7, T13);
- SET(d, a, b, c, 13, 12, T14);
- SET(c, d, a, b, 14, 17, T15);
- SET(b, c, d, a, 15, 22, T16);
-#undef SET
-
- /* Round 2. */
- /* Let [abcd k s i] denote the operation
- a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
-#define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
-#define SET(a, b, c, d, k, s, Ti)\
- t = a + G(b,c,d) + X[k] + Ti;\
- a = ROTATE_LEFT(t, s) + b
- /* Do the following 16 operations. */
- SET(a, b, c, d, 1, 5, T17);
- SET(d, a, b, c, 6, 9, T18);
- SET(c, d, a, b, 11, 14, T19);
- SET(b, c, d, a, 0, 20, T20);
- SET(a, b, c, d, 5, 5, T21);
- SET(d, a, b, c, 10, 9, T22);
- SET(c, d, a, b, 15, 14, T23);
- SET(b, c, d, a, 4, 20, T24);
- SET(a, b, c, d, 9, 5, T25);
- SET(d, a, b, c, 14, 9, T26);
- SET(c, d, a, b, 3, 14, T27);
- SET(b, c, d, a, 8, 20, T28);
- SET(a, b, c, d, 13, 5, T29);
- SET(d, a, b, c, 2, 9, T30);
- SET(c, d, a, b, 7, 14, T31);
- SET(b, c, d, a, 12, 20, T32);
-#undef SET
-
- /* Round 3. */
- /* Let [abcd k s t] denote the operation
- a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */
-#define H(x, y, z) ((x) ^ (y) ^ (z))
-#define SET(a, b, c, d, k, s, Ti)\
- t = a + H(b,c,d) + X[k] + Ti;\
- a = ROTATE_LEFT(t, s) + b
- /* Do the following 16 operations. */
- SET(a, b, c, d, 5, 4, T33);
- SET(d, a, b, c, 8, 11, T34);
- SET(c, d, a, b, 11, 16, T35);
- SET(b, c, d, a, 14, 23, T36);
- SET(a, b, c, d, 1, 4, T37);
- SET(d, a, b, c, 4, 11, T38);
- SET(c, d, a, b, 7, 16, T39);
- SET(b, c, d, a, 10, 23, T40);
- SET(a, b, c, d, 13, 4, T41);
- SET(d, a, b, c, 0, 11, T42);
- SET(c, d, a, b, 3, 16, T43);
- SET(b, c, d, a, 6, 23, T44);
- SET(a, b, c, d, 9, 4, T45);
- SET(d, a, b, c, 12, 11, T46);
- SET(c, d, a, b, 15, 16, T47);
- SET(b, c, d, a, 2, 23, T48);
-#undef SET
-
- /* Round 4. */
- /* Let [abcd k s t] denote the operation
- a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
-#define I(x, y, z) ((y) ^ ((x) | ~(z)))
-#define SET(a, b, c, d, k, s, Ti)\
- t = a + I(b,c,d) + X[k] + Ti;\
- a = ROTATE_LEFT(t, s) + b
- /* Do the following 16 operations. */
- SET(a, b, c, d, 0, 6, T49);
- SET(d, a, b, c, 7, 10, T50);
- SET(c, d, a, b, 14, 15, T51);
- SET(b, c, d, a, 5, 21, T52);
- SET(a, b, c, d, 12, 6, T53);
- SET(d, a, b, c, 3, 10, T54);
- SET(c, d, a, b, 10, 15, T55);
- SET(b, c, d, a, 1, 21, T56);
- SET(a, b, c, d, 8, 6, T57);
- SET(d, a, b, c, 15, 10, T58);
- SET(c, d, a, b, 6, 15, T59);
- SET(b, c, d, a, 13, 21, T60);
- SET(a, b, c, d, 4, 6, T61);
- SET(d, a, b, c, 11, 10, T62);
- SET(c, d, a, b, 2, 15, T63);
- SET(b, c, d, a, 9, 21, T64);
-#undef SET
-
- /* Then perform the following additions. (That is increment each
- of the four registers by the value it had before this block
- was started.) */
- pms->abcd[0] += a;
- pms->abcd[1] += b;
- pms->abcd[2] += c;
- pms->abcd[3] += d;
-}
-
-void
-md5_init(md5_state_t *pms)
-{
- pms->count[0] = pms->count[1] = 0;
- pms->abcd[0] = 0x67452301;
- pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476;
- pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301;
- pms->abcd[3] = 0x10325476;
-}
-
-void
-md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes)
-{
- const md5_byte_t *p = data;
- int left = nbytes;
- int offset = (pms->count[0] >> 3) & 63;
- md5_word_t nbits = (md5_word_t)(nbytes << 3);
-
- if (nbytes <= 0)
- return;
-
- /* Update the message length. */
- pms->count[1] += nbytes >> 29;
- pms->count[0] += nbits;
- if (pms->count[0] < nbits)
- pms->count[1]++;
-
- /* Process an initial partial block. */
- if (offset) {
- int copy = (offset + nbytes > 64 ? 64 - offset : nbytes);
-
- memcpy(pms->buf + offset, p, copy);
- if (offset + copy < 64)
- return;
- p += copy;
- left -= copy;
- md5_process(pms, pms->buf);
- }
-
- /* Process full blocks. */
- for (; left >= 64; p += 64, left -= 64)
- md5_process(pms, p);
-
- /* Process a final partial block. */
- if (left)
- memcpy(pms->buf, p, left);
-}
-
-void
-md5_finish(md5_state_t *pms, md5_byte_t digest[16])
-{
- static const md5_byte_t pad[64] = {
- 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
- };
- md5_byte_t data[8];
- int i;
-
- /* Save the length before padding. */
- for (i = 0; i < 8; ++i)
- data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3));
- /* Pad to 56 bytes mod 64. */
- md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1);
- /* Append the length. */
- md5_append(pms, data, 8);
- for (i = 0; i < 16; ++i)
- digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3));
-}
diff --git a/src/distutils2/_backport/md5.h b/src/distutils2/_backport/md5.h
deleted file mode 100644
index 1718401..0000000
--- a/src/distutils2/_backport/md5.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- Copyright (C) 1999, 2002 Aladdin Enterprises. All rights reserved.
-
- This software is provided 'as-is', without any express or implied
- warranty. In no event will the authors be held liable for any damages
- arising from the use of this software.
-
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it
- freely, subject to the following restrictions:
-
- 1. The origin of this software must not be misrepresented; you must not
- claim that you wrote the original software. If you use this software
- in a product, an acknowledgment in the product documentation would be
- appreciated but is not required.
- 2. Altered source versions must be plainly marked as such, and must not be
- misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source distribution.
-
- L. Peter Deutsch
- ghost@aladdin.com
-
- */
-/* $Id: md5.h 43594 2006-04-03 16:27:50Z matthias.klose $ */
-/*
- Independent implementation of MD5 (RFC 1321).
-
- This code implements the MD5 Algorithm defined in RFC 1321, whose
- text is available at
- http://www.ietf.org/rfc/rfc1321.txt
- The code is derived from the text of the RFC, including the test suite
- (section A.5) but excluding the rest of Appendix A. It does not include
- any code or documentation that is identified in the RFC as being
- copyrighted.
-
- The original and principal author of md5.h is L. Peter Deutsch
- <ghost@aladdin.com>. Other authors are noted in the change history
- that follows (in reverse chronological order):
-
- 2002-04-13 lpd Removed support for non-ANSI compilers; removed
- references to Ghostscript; clarified derivation from RFC 1321;
- now handles byte order either statically or dynamically.
- 1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
- 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5);
- added conditionalization for C++ compilation from Martin
- Purschke <purschke@bnl.gov>.
- 1999-05-03 lpd Original version.
- */
-
-#ifndef md5_INCLUDED
-# define md5_INCLUDED
-
-/*
- * This package supports both compile-time and run-time determination of CPU
- * byte order. If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be
- * compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is
- * defined as non-zero, the code will be compiled to run only on big-endian
- * CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to
- * run on either big- or little-endian CPUs, but will run slightly less
- * efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined.
- */
-
-typedef unsigned char md5_byte_t; /* 8-bit byte */
-typedef unsigned int md5_word_t; /* 32-bit word */
-
-/* Define the state of the MD5 Algorithm. */
-typedef struct md5_state_s {
- md5_word_t count[2]; /* message length in bits, lsw first */
- md5_word_t abcd[4]; /* digest buffer */
- md5_byte_t buf[64]; /* accumulate block */
-} md5_state_t;
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-/* Initialize the algorithm. */
-void md5_init(md5_state_t *pms);
-
-/* Append a string to the message. */
-void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes);
-
-/* Finish the message and return the digest. */
-void md5_finish(md5_state_t *pms, md5_byte_t digest[16]);
-
-#ifdef __cplusplus
-} /* end extern "C" */
-#endif
-
-#endif /* md5_INCLUDED */
diff --git a/src/distutils2/_backport/md5module.c b/src/distutils2/_backport/md5module.c
deleted file mode 100644
index 5e4f116..0000000
--- a/src/distutils2/_backport/md5module.c
+++ /dev/null
@@ -1,312 +0,0 @@
-
-/* MD5 module */
-
-/* This module provides an interface to the RSA Data Security,
- Inc. MD5 Message-Digest Algorithm, described in RFC 1321.
- It requires the files md5c.c and md5.h (which are slightly changed
- from the versions in the RFC to avoid the "global.h" file.) */
-
-
-/* MD5 objects */
-
-#include "Python.h"
-#include "structmember.h"
-#include "md5.h"
-
-typedef struct {
- PyObject_HEAD
- md5_state_t md5; /* the context holder */
-} md5object;
-
-static PyTypeObject MD5type;
-
-#define is_md5object(v) ((v)->ob_type == &MD5type)
-
-static md5object *
-newmd5object(void)
-{
- md5object *md5p;
-
- md5p = PyObject_New(md5object, &MD5type);
- if (md5p == NULL)
- return NULL;
-
- md5_init(&md5p->md5); /* actual initialisation */
- return md5p;
-}
-
-
-/* MD5 methods */
-
-static void
-md5_dealloc(md5object *md5p)
-{
- PyObject_Del(md5p);
-}
-
-
-/* MD5 methods-as-attributes */
-
-static PyObject *
-md5_update(md5object *self, PyObject *args)
-{
- unsigned char *cp;
- int len;
-
- if (!PyArg_ParseTuple(args, "s#:update", &cp, &len))
- return NULL;
-
- md5_append(&self->md5, cp, len);
-
- Py_INCREF(Py_None);
- return Py_None;
-}
-
-PyDoc_STRVAR(update_doc,
-"update (arg)\n\
-\n\
-Update the md5 object with the string arg. Repeated calls are\n\
-equivalent to a single call with the concatenation of all the\n\
-arguments.");
-
-
-static PyObject *
-md5_digest(md5object *self)
-{
- md5_state_t mdContext;
- unsigned char aDigest[16];
-
- /* make a temporary copy, and perform the final */
- mdContext = self->md5;
- md5_finish(&mdContext, aDigest);
-
- return PyString_FromStringAndSize((char *)aDigest, 16);
-}
-
-PyDoc_STRVAR(digest_doc,
-"digest() -> string\n\
-\n\
-Return the digest of the strings passed to the update() method so\n\
-far. This is a 16-byte string which may contain non-ASCII characters,\n\
-including null bytes.");
-
-
-static PyObject *
-md5_hexdigest(md5object *self)
-{
- md5_state_t mdContext;
- unsigned char digest[16];
- unsigned char hexdigest[32];
- int i, j;
-
- /* make a temporary copy, and perform the final */
- mdContext = self->md5;
- md5_finish(&mdContext, digest);
-
- /* Make hex version of the digest */
- for(i=j=0; i<16; i++) {
- char c;
- c = (digest[i] >> 4) & 0xf;
- c = (c>9) ? c+'a'-10 : c + '0';
- hexdigest[j++] = c;
- c = (digest[i] & 0xf);
- c = (c>9) ? c+'a'-10 : c + '0';
- hexdigest[j++] = c;
- }
- return PyString_FromStringAndSize((char*)hexdigest, 32);
-}
-
-
-PyDoc_STRVAR(hexdigest_doc,
-"hexdigest() -> string\n\
-\n\
-Like digest(), but returns the digest as a string of hexadecimal digits.");
-
-
-static PyObject *
-md5_copy(md5object *self)
-{
- md5object *md5p;
-
- if ((md5p = newmd5object()) == NULL)
- return NULL;
-
- md5p->md5 = self->md5;
-
- return (PyObject *)md5p;
-}
-
-PyDoc_STRVAR(copy_doc,
-"copy() -> md5 object\n\
-\n\
-Return a copy (``clone'') of the md5 object.");
-
-
-static PyMethodDef md5_methods[] = {
- {"update", (PyCFunction)md5_update, METH_VARARGS, update_doc},
- {"digest", (PyCFunction)md5_digest, METH_NOARGS, digest_doc},
- {"hexdigest", (PyCFunction)md5_hexdigest, METH_NOARGS, hexdigest_doc},
- {"copy", (PyCFunction)md5_copy, METH_NOARGS, copy_doc},
- {NULL, NULL} /* sentinel */
-};
-
-static PyObject *
-md5_get_block_size(PyObject *self, void *closure)
-{
- return PyInt_FromLong(64);
-}
-
-static PyObject *
-md5_get_digest_size(PyObject *self, void *closure)
-{
- return PyInt_FromLong(16);
-}
-
-static PyObject *
-md5_get_name(PyObject *self, void *closure)
-{
- return PyString_FromStringAndSize("MD5", 3);
-}
-
-static PyGetSetDef md5_getseters[] = {
- {"digest_size",
- (getter)md5_get_digest_size, NULL,
- NULL,
- NULL},
- {"block_size",
- (getter)md5_get_block_size, NULL,
- NULL,
- NULL},
- {"name",
- (getter)md5_get_name, NULL,
- NULL,
- NULL},
- /* the old md5 and sha modules support 'digest_size' as in PEP 247.
- * the old sha module also supported 'digestsize'. ugh. */
- {"digestsize",
- (getter)md5_get_digest_size, NULL,
- NULL,
- NULL},
- {NULL} /* Sentinel */
-};
-
-
-PyDoc_STRVAR(module_doc,
-"This module implements the interface to RSA's MD5 message digest\n\
-algorithm (see also Internet RFC 1321). Its use is quite\n\
-straightforward: use the new() to create an md5 object. You can now\n\
-feed this object with arbitrary strings using the update() method, and\n\
-at any point you can ask it for the digest (a strong kind of 128-bit\n\
-checksum, a.k.a. ``fingerprint'') of the concatenation of the strings\n\
-fed to it so far using the digest() method.\n\
-\n\
-Functions:\n\
-\n\
-new([arg]) -- return a new md5 object, initialized with arg if provided\n\
-md5([arg]) -- DEPRECATED, same as new, but for compatibility\n\
-\n\
-Special Objects:\n\
-\n\
-MD5Type -- type object for md5 objects");
-
-PyDoc_STRVAR(md5type_doc,
-"An md5 represents the object used to calculate the MD5 checksum of a\n\
-string of information.\n\
-\n\
-Methods:\n\
-\n\
-update() -- updates the current digest with an additional string\n\
-digest() -- return the current digest value\n\
-hexdigest() -- return the current digest as a string of hexadecimal digits\n\
-copy() -- return a copy of the current md5 object");
-
-static PyTypeObject MD5type = {
- PyObject_HEAD_INIT(NULL)
- 0, /*ob_size*/
- "_md5.md5", /*tp_name*/
- sizeof(md5object), /*tp_size*/
- 0, /*tp_itemsize*/
- /* methods */
- (destructor)md5_dealloc, /*tp_dealloc*/
- 0, /*tp_print*/
- 0, /*tp_getattr*/
- 0, /*tp_setattr*/
- 0, /*tp_compare*/
- 0, /*tp_repr*/
- 0, /*tp_as_number*/
- 0, /*tp_as_sequence*/
- 0, /*tp_as_mapping*/
- 0, /*tp_hash*/
- 0, /*tp_call*/
- 0, /*tp_str*/
- 0, /*tp_getattro*/
- 0, /*tp_setattro*/
- 0, /*tp_as_buffer*/
- Py_TPFLAGS_DEFAULT, /*tp_flags*/
- md5type_doc, /*tp_doc*/
- 0, /*tp_traverse*/
- 0, /*tp_clear*/
- 0, /*tp_richcompare*/
- 0, /*tp_weaklistoffset*/
- 0, /*tp_iter*/
- 0, /*tp_iternext*/
- md5_methods, /*tp_methods*/
- 0, /*tp_members*/
- md5_getseters, /*tp_getset*/
-};
-
-
-/* MD5 functions */
-
-static PyObject *
-MD5_new(PyObject *self, PyObject *args)
-{
- md5object *md5p;
- unsigned char *cp = NULL;
- int len = 0;
-
- if (!PyArg_ParseTuple(args, "|s#:new", &cp, &len))
- return NULL;
-
- if ((md5p = newmd5object()) == NULL)
- return NULL;
-
- if (cp)
- md5_append(&md5p->md5, cp, len);
-
- return (PyObject *)md5p;
-}
-
-PyDoc_STRVAR(new_doc,
-"new([arg]) -> md5 object\n\
-\n\
-Return a new md5 object. If arg is present, the method call update(arg)\n\
-is made.");
-
-
-/* List of functions exported by this module */
-
-static PyMethodDef md5_functions[] = {
- {"new", (PyCFunction)MD5_new, METH_VARARGS, new_doc},
- {NULL, NULL} /* Sentinel */
-};
-
-
-/* Initialize this module. */
-
-PyMODINIT_FUNC
-init_md5(void)
-{
- PyObject *m, *d;
-
- MD5type.ob_type = &PyType_Type;
- if (PyType_Ready(&MD5type) < 0)
- return;
- m = Py_InitModule3("_md5", md5_functions, module_doc);
- if (m == NULL)
- return;
- d = PyModule_GetDict(m);
- PyDict_SetItemString(d, "MD5Type", (PyObject *)&MD5type);
- PyModule_AddIntConstant(m, "digest_size", 16);
- /* No need to check the error here, the caller will do that */
-}
diff --git a/src/distutils2/_backport/pkgutil.py b/src/distutils2/_backport/pkgutil.py
deleted file mode 100644
index c53bd22..0000000
--- a/src/distutils2/_backport/pkgutil.py
+++ /dev/null
@@ -1,1155 +0,0 @@
-"""Utilities to support packages."""
-
-# NOTE: This module must remain compatible with Python 2.3, as it is shared
-# by setuptools for distribution with Python 2.3 and up.
-
-import os
-import sys
-import imp
-import os.path
-from csv import reader as csv_reader
-from types import ModuleType
-from distutils2.errors import DistutilsError
-from distutils2.metadata import DistributionMetadata
-from distutils2.version import suggest_normalized_version, VersionPredicate
-import zipimport
-try:
- import cStringIO as StringIO
-except ImportError:
- import StringIO
-import re
-import warnings
-
-
-__all__ = [
- 'get_importer', 'iter_importers', 'get_loader', 'find_loader',
- 'walk_packages', 'iter_modules', 'get_data',
- 'ImpImporter', 'ImpLoader', 'read_code', 'extend_path',
- 'Distribution', 'EggInfoDistribution', 'distinfo_dirname',
- 'get_distributions', 'get_distribution', 'get_file_users',
- 'provides_distribution', 'obsoletes_distribution',
- 'enable_cache', 'disable_cache', 'clear_cache'
-]
-
-
-def read_code(stream):
- # This helper is needed in order for the :pep:`302` emulation to
- # correctly handle compiled files
- import marshal
-
- magic = stream.read(4)
- if magic != imp.get_magic():
- return None
-
- stream.read(4) # Skip timestamp
- return marshal.load(stream)
-
-
-def simplegeneric(func):
- """Make a trivial single-dispatch generic function"""
- registry = {}
-
- def wrapper(*args, **kw):
- ob = args[0]
- try:
- cls = ob.__class__
- except AttributeError:
- cls = type(ob)
- try:
- mro = cls.__mro__
- except AttributeError:
- try:
-
- class cls(cls, object):
- pass
- mro = cls.__mro__[1:]
- except TypeError:
- mro = object, # must be an ExtensionClass or some such :(
- for t in mro:
- if t in registry:
- return registry[t](*args, **kw)
- else:
- return func(*args, **kw)
- try:
- wrapper.__name__ = func.__name__
- except (TypeError, AttributeError):
- pass # Python 2.3 doesn't allow functions to be renamed
-
- def register(typ, func=None):
- if func is None:
- return lambda f: register(typ, f)
- registry[typ] = func
- return func
-
- wrapper.__dict__ = func.__dict__
- wrapper.__doc__ = func.__doc__
- wrapper.register = register
- return wrapper
-
-
-def walk_packages(path=None, prefix='', onerror=None):
- """Yields ``(module_loader, name, ispkg)`` for all modules recursively
- on *path*, or, if *path* is ``None``, all accessible modules.
-
- :parameter path: should be either ``None`` or a list of paths to look for
- modules in.
- :parameter prefix: is a string to output on the front of every module name
- on output.
-
- Note that this function must import all packages (NOT all
- modules!) on the given path, in order to access the ``__path__``
- attribute to find submodules.
-
- *onerror* is a function which gets called with one argument (the
- name of the package which was being imported) if any exception
- occurs while trying to import a package. If no onerror function is
- supplied, ``ImportErrors`` are caught and ignored, while all other
- exceptions are propagated, terminating the search.
-
- Examples:
-
- * list all modules python can access::
-
- walk_packages()
-
- * list all submodules of ctypes::
-
- walk_packages(ctypes.__path__, ctypes.__name__+'.')
-
- """
-
- def seen(p, m={}):
- if p in m:
- return True
- m[p] = True
-
- for importer, name, ispkg in iter_modules(path, prefix):
- yield importer, name, ispkg
-
- if ispkg:
- try:
- __import__(name)
- except ImportError:
- if onerror is not None:
- onerror(name)
- except Exception:
- if onerror is not None:
- onerror(name)
- else:
- raise
- else:
- path = getattr(sys.modules[name], '__path__', None) or []
-
- # don't traverse path items we've seen before
- path = [p for p in path if not seen(p)]
-
- for item in walk_packages(path, name + '.', onerror):
- yield item
-
-
-def iter_modules(path=None, prefix=''):
- """Yields ``(module_loader, name, ispkg)`` for all submodules on path,
- or, if *path* is ``None``, all top-level modules on ``sys.path``.
-
- :parameter path: should be either None or a list of paths to look for
- modules in.
- :parameter prefix: is a string to output on the front of every module name
- on output.
-
- """
-
- if path is None:
- importers = iter_importers()
- else:
- importers = map(get_importer, path)
-
- yielded = {}
- for i in importers:
- for name, ispkg in iter_importer_modules(i, prefix):
- if name not in yielded:
- yielded[name] = 1
- yield i, name, ispkg
-
-
-#@simplegeneric
-def iter_importer_modules(importer, prefix=''):
- ""
- if not hasattr(importer, 'iter_modules'):
- return []
- return importer.iter_modules(prefix)
-
-iter_importer_modules = simplegeneric(iter_importer_modules)
-
-
-class ImpImporter(object):
- """:pep:`302` Importer that wraps Python's "classic" import algorithm
-
- ``ImpImporter(dirname)`` produces a :pep:`302` importer that searches that
- directory. ``ImpImporter(None)`` produces a :pep:`302` importer that
- searches the current ``sys.path``, plus any modules that are frozen
- or built-in.
-
- Note that :class:`ImpImporter` does not currently support being used by
- placement on ``sys.meta_path``.
- """
-
- def __init__(self, path=None):
- self.path = path
-
- def find_module(self, fullname, path=None):
- # Note: we ignore 'path' argument since it is only used via meta_path
- subname = fullname.split(".")[-1]
- if subname != fullname and self.path is None:
- return None
- if self.path is None:
- path = None
- else:
- path = [os.path.realpath(self.path)]
- try:
- file, filename, etc = imp.find_module(subname, path)
- except ImportError:
- return None
- return ImpLoader(fullname, file, filename, etc)
-
- def iter_modules(self, prefix=''):
- if self.path is None or not os.path.isdir(self.path):
- return
-
- yielded = {}
- import inspect
-
- filenames = os.listdir(self.path)
- filenames.sort() # handle packages before same-named modules
-
- for fn in filenames:
- modname = inspect.getmodulename(fn)
- if modname == '__init__' or modname in yielded:
- continue
-
- path = os.path.join(self.path, fn)
- ispkg = False
-
- if not modname and os.path.isdir(path) and '.' not in fn:
- modname = fn
- for fn in os.listdir(path):
- subname = inspect.getmodulename(fn)
- if subname == '__init__':
- ispkg = True
- break
- else:
- continue # not a package
-
- if modname and '.' not in modname:
- yielded[modname] = 1
- yield prefix + modname, ispkg
-
-
-class ImpLoader(object):
- """:pep:`302` Loader that wraps Python's "classic" import algorithm """
-
- code = source = None
-
- def __init__(self, fullname, file, filename, etc):
- self.file = file
- self.filename = filename
- self.fullname = fullname
- self.etc = etc
-
- def load_module(self, fullname):
- self._reopen()
- try:
- mod = imp.load_module(fullname, self.file, self.filename, self.etc)
- finally:
- if self.file:
- self.file.close()
- # Note: we don't set __loader__ because we want the module to look
- # normal; i.e. this is just a wrapper for standard import machinery
- return mod
-
- def get_data(self, pathname):
- return open(pathname, "rb").read()
-
- def _reopen(self):
- if self.file and self.file.closed:
- mod_type = self.etc[2]
- if mod_type == imp.PY_SOURCE:
- self.file = open(self.filename, 'rU')
- elif mod_type in (imp.PY_COMPILED, imp.C_EXTENSION):
- self.file = open(self.filename, 'rb')
-
- def _fix_name(self, fullname):
- if fullname is None:
- fullname = self.fullname
- elif fullname != self.fullname:
- raise ImportError("Loader for module %s cannot handle "
- "module %s" % (self.fullname, fullname))
- return fullname
-
- def is_package(self, fullname):
- fullname = self._fix_name(fullname)
- return self.etc[2] == imp.PKG_DIRECTORY
-
- def get_code(self, fullname=None):
- fullname = self._fix_name(fullname)
- if self.code is None:
- mod_type = self.etc[2]
- if mod_type == imp.PY_SOURCE:
- source = self.get_source(fullname)
- self.code = compile(source, self.filename, 'exec')
- elif mod_type == imp.PY_COMPILED:
- self._reopen()
- try:
- self.code = read_code(self.file)
- finally:
- self.file.close()
- elif mod_type == imp.PKG_DIRECTORY:
- self.code = self._get_delegate().get_code()
- return self.code
-
- def get_source(self, fullname=None):
- fullname = self._fix_name(fullname)
- if self.source is None:
- mod_type = self.etc[2]
- if mod_type == imp.PY_SOURCE:
- self._reopen()
- try:
- self.source = self.file.read()
- finally:
- self.file.close()
- elif mod_type == imp.PY_COMPILED:
- if os.path.exists(self.filename[:-1]):
- f = open(self.filename[:-1], 'rU')
- self.source = f.read()
- f.close()
- elif mod_type == imp.PKG_DIRECTORY:
- self.source = self._get_delegate().get_source()
- return self.source
-
- def _get_delegate(self):
- return ImpImporter(self.filename).find_module('__init__')
-
- def get_filename(self, fullname=None):
- fullname = self._fix_name(fullname)
- mod_type = self.etc[2]
- if self.etc[2] == imp.PKG_DIRECTORY:
- return self._get_delegate().get_filename()
- elif self.etc[2] in (imp.PY_SOURCE, imp.PY_COMPILED, imp.C_EXTENSION):
- return self.filename
- return None
-
-
-try:
- import zipimport
- from zipimport import zipimporter
-
- def iter_zipimport_modules(importer, prefix=''):
- dirlist = zipimport._zip_directory_cache[importer.archive].keys()
- dirlist.sort()
- _prefix = importer.prefix
- plen = len(_prefix)
- yielded = {}
- import inspect
- for fn in dirlist:
- if not fn.startswith(_prefix):
- continue
-
- fn = fn[plen:].split(os.sep)
-
- if len(fn) == 2 and fn[1].startswith('__init__.py'):
- if fn[0] not in yielded:
- yielded[fn[0]] = 1
- yield fn[0], True
-
- if len(fn) != 1:
- continue
-
- modname = inspect.getmodulename(fn[0])
- if modname == '__init__':
- continue
-
- if modname and '.' not in modname and modname not in yielded:
- yielded[modname] = 1
- yield prefix + modname, False
-
- iter_importer_modules.register(zipimporter, iter_zipimport_modules)
-
-except ImportError:
- pass
-
-
-def get_importer(path_item):
- """Retrieve a :pep:`302` importer for the given path item
-
- The returned importer is cached in ``sys.path_importer_cache``
- if it was newly created by a path hook.
-
- If there is no importer, a wrapper around the basic import
- machinery is returned. This wrapper is never inserted into
- the importer cache (``None`` is inserted instead).
-
- The cache (or part of it) can be cleared manually if a
- rescan of ``sys.path_hooks`` is necessary.
- """
- try:
- importer = sys.path_importer_cache[path_item]
- except KeyError:
- for path_hook in sys.path_hooks:
- try:
- importer = path_hook(path_item)
- break
- except ImportError:
- pass
- else:
- importer = None
- sys.path_importer_cache.setdefault(path_item, importer)
-
- if importer is None:
- try:
- importer = ImpImporter(path_item)
- except ImportError:
- importer = None
- return importer
-
-
-def iter_importers(fullname=""):
- """Yield :pep:`302` importers for the given module name
-
- If fullname contains a '.', the importers will be for the package
- containing fullname, otherwise they will be importers for sys.meta_path,
- sys.path, and Python's "classic" import machinery, in that order. If
- the named module is in a package, that package is imported as a side
- effect of invoking this function.
-
- Non :pep:`302` mechanisms (e.g. the Windows registry) used by the
- standard import machinery to find files in alternative locations
- are partially supported, but are searched AFTER ``sys.path``. Normally,
- these locations are searched BEFORE sys.path, preventing ``sys.path``
- entries from shadowing them.
-
- For this to cause a visible difference in behaviour, there must
- be a module or package name that is accessible via both sys.path
- and one of the non :pep:`302` file system mechanisms. In this case,
- the emulation will find the former version, while the builtin
- import mechanism will find the latter.
-
- Items of the following types can be affected by this discrepancy:
- ``imp.C_EXTENSION, imp.PY_SOURCE, imp.PY_COMPILED, imp.PKG_DIRECTORY``
- """
- if fullname.startswith('.'):
- raise ImportError("Relative module names not supported")
- if '.' in fullname:
- # Get the containing package's __path__
- pkg = '.'.join(fullname.split('.')[:-1])
- if pkg not in sys.modules:
- __import__(pkg)
- path = getattr(sys.modules[pkg], '__path__', None) or []
- else:
- for importer in sys.meta_path:
- yield importer
- path = sys.path
- for item in path:
- yield get_importer(item)
- if '.' not in fullname:
- yield ImpImporter()
-
-
-def get_loader(module_or_name):
- """Get a :pep:`302` "loader" object for module_or_name
-
- If the module or package is accessible via the normal import
- mechanism, a wrapper around the relevant part of that machinery
- is returned. Returns None if the module cannot be found or imported.
- If the named module is not already imported, its containing package
- (if any) is imported, in order to establish the package ``__path__``.
-
- This function uses :func:`iter_importers`, and is thus subject to the same
- limitations regarding platform-specific special import locations such
- as the Windows registry.
- """
- if module_or_name in sys.modules:
- module_or_name = sys.modules[module_or_name]
- if isinstance(module_or_name, ModuleType):
- module = module_or_name
- loader = getattr(module, '__loader__', None)
- if loader is not None:
- return loader
- fullname = module.__name__
- else:
- fullname = module_or_name
- return find_loader(fullname)
-
-
-def find_loader(fullname):
- """Find a :pep:`302` "loader" object for fullname
-
- If fullname contains dots, path must be the containing package's
- ``__path__``. Returns ``None`` if the module cannot be found or imported.
- This function uses :func:`iter_importers`, and is thus subject to the same
- limitations regarding platform-specific special import locations such as
- the Windows registry.
- """
- for importer in iter_importers(fullname):
- loader = importer.find_module(fullname)
- if loader is not None:
- return loader
-
- return None
-
-
-def extend_path(path, name):
- """Extend a package's path.
-
- Intended use is to place the following code in a package's
- ``__init__.py``::
-
- from pkgutil import extend_path
- __path__ = extend_path(__path__, __name__)
-
- This will add to the package's ``__path__`` all subdirectories of
- directories on ``sys.path`` named after the package. This is useful
- if one wants to distribute different parts of a single logical
- package as multiple directories.
-
- It also looks for ``*.pkg`` files beginning where ``*`` matches the name
- argument. This feature is similar to ``*.pth`` files (see ``site.py``),
- except that it doesn't special-case lines starting with ``import``.
- A ``*.pkg`` file is trusted at face value: apart from checking for
- duplicates, all entries found in a ``*.pkg`` file are added to the
- path, regardless of whether they are exist the filesystem. (This
- is a feature.)
-
- If the input path is not a list (as is the case for frozen
- packages) it is returned unchanged. The input path is not
- modified; an extended copy is returned. Items are only appended
- to the copy at the end.
-
- It is assumed that sys.path is a sequence. Items of sys.path that
- are not (unicode or 8-bit) strings referring to existing
- directories are ignored. Unicode items of sys.path that cause
- errors when used as filenames may cause this function to raise an
- exception (in line with ``os.path.isdir()`` behavior).
- """
-
- if not isinstance(path, list):
- # This could happen e.g. when this is called from inside a
- # frozen package. Return the path unchanged in that case.
- return path
-
- pname = os.path.join(*name.split('.')) # Reconstitute as relative path
- # Just in case os.extsep != '.'
- sname = os.extsep.join(name.split('.'))
- sname_pkg = sname + os.extsep + "pkg"
- init_py = "__init__" + os.extsep + "py"
-
- path = path[:] # Start with a copy of the existing path
-
- for dir in sys.path:
- if not isinstance(dir, basestring) or not os.path.isdir(dir):
- continue
- subdir = os.path.join(dir, pname)
- # XXX This may still add duplicate entries to path on
- # case-insensitive filesystems
- initfile = os.path.join(subdir, init_py)
- if subdir not in path and os.path.isfile(initfile):
- path.append(subdir)
- # XXX Is this the right thing for subpackages like zope.app?
- # It looks for a file named "zope.app.pkg"
- pkgfile = os.path.join(dir, sname_pkg)
- if os.path.isfile(pkgfile):
- try:
- f = open(pkgfile)
- except IOError, msg:
- sys.stderr.write("Can't open %s: %s\n" %
- (pkgfile, msg))
- else:
- for line in f:
- line = line.rstrip('\n')
- if not line or line.startswith('#'):
- continue
- path.append(line) # Don't check for existence!
- f.close()
-
- return path
-
-
-def get_data(package, resource):
- """Get a resource from a package.
-
- This is a wrapper round the :pep:`302` loader get_data API. The package
- argument should be the name of a package, in standard module format
- (``foo.bar``). The resource argument should be in the form of a relative
- filename, using ``'/'`` as the path separator. The parent directory name
- ``'..'`` is not allowed, and nor is a rooted name (starting with a
- ``'/'``).
-
- The function returns a binary string, which is the contents of the
- specified resource.
-
- For packages located in the filesystem, which have already been imported,
- this is the rough equivalent of::
-
- d = os.path.dirname(sys.modules[package].__file__)
- data = open(os.path.join(d, resource), 'rb').read()
-
- If the package cannot be located or loaded, or it uses a :pep:`302` loader
- which does not support :func:`get_data`, then ``None`` is returned.
- """
-
- loader = get_loader(package)
- if loader is None or not hasattr(loader, 'get_data'):
- return None
- mod = sys.modules.get(package) or loader.load_module(package)
- if mod is None or not hasattr(mod, '__file__'):
- return None
-
- # Modify the resource name to be compatible with the loader.get_data
- # signature - an os.path format "filename" starting with the dirname of
- # the package's __file__
- parts = resource.split('/')
- parts.insert(0, os.path.dirname(mod.__file__))
- resource_name = os.path.join(*parts)
- return loader.get_data(resource_name)
-
-##########################
-# PEP 376 Implementation #
-##########################
-
-DIST_FILES = ('INSTALLER', 'METADATA', 'RECORD', 'REQUESTED',)
-
-# Cache
-_cache_name = {} # maps names to Distribution instances
-_cache_name_egg = {} # maps names to EggInfoDistribution instances
-_cache_path = {} # maps paths to Distribution instances
-_cache_path_egg = {} # maps paths to EggInfoDistribution instances
-_cache_generated = False # indicates if .dist-info distributions are cached
-_cache_generated_egg = False # indicates if .dist-info and .egg are cached
-_cache_enabled = True
-
-
-def enable_cache():
- """
- Enables the internal cache.
-
- Note that this function will not clear the cache in any case, for that
- functionality see :func:`clear_cache`.
- """
- global _cache_enabled
-
- _cache_enabled = True
-
-def disable_cache():
- """
- Disables the internal cache.
-
- Note that this function will not clear the cache in any case, for that
- functionality see :func:`clear_cache`.
- """
- global _cache_enabled
-
- _cache_enabled = False
-
-def clear_cache():
- """ Clears the internal cache. """
- global _cache_name, _cache_name_egg, cache_path, _cache_path_egg, \
- _cache_generated, _cache_generated_egg
-
- _cache_name = {}
- _cache_name_egg = {}
- _cache_path = {}
- _cache_path_egg = {}
- _cache_generated = False
- _cache_generated_egg = False
-
-
-def _yield_distributions(include_dist, include_egg):
- """
- Yield .dist-info and .egg(-info) distributions, based on the arguments
-
- :parameter include_dist: yield .dist-info distributions
- :parameter include_egg: yield .egg(-info) distributions
- """
- for path in sys.path:
- realpath = os.path.realpath(path)
- if not os.path.isdir(realpath):
- continue
- for dir in os.listdir(realpath):
- dist_path = os.path.join(realpath, dir)
- if include_dist and dir.endswith('.dist-info'):
- yield Distribution(dist_path)
- elif include_egg and (dir.endswith('.egg-info') or
- dir.endswith('.egg')):
- yield EggInfoDistribution(dist_path)
-
-
-def _generate_cache(use_egg_info=False):
- global _cache_generated, _cache_generated_egg
-
- if _cache_generated_egg or (_cache_generated and not use_egg_info):
- return
- else:
- gen_dist = not _cache_generated
- gen_egg = use_egg_info
-
- for dist in _yield_distributions(gen_dist, gen_egg):
- if isinstance(dist, Distribution):
- _cache_path[dist.path] = dist
- if not dist.name in _cache_name:
- _cache_name[dist.name] = []
- _cache_name[dist.name].append(dist)
- else:
- _cache_path_egg[dist.path] = dist
- if not dist.name in _cache_name_egg:
- _cache_name_egg[dist.name] = []
- _cache_name_egg[dist.name].append(dist)
-
- if gen_dist:
- _cache_generated = True
- if gen_egg:
- _cache_generated_egg = True
-
-
-class Distribution(object):
- """Created with the *path* of the ``.dist-info`` directory provided to the
- constructor. It reads the metadata contained in ``METADATA`` when it is
- instantiated."""
-
- # Attribute documenting for Sphinx style documentation, see for more info:
- # http://sphinx.pocoo.org/ext/autodoc.html#dir-autoattribute
- name = ''
- """The name of the distribution."""
- metadata = None
- """A :class:`distutils2.metadata.DistributionMetadata` instance loaded with
- the distribution's ``METADATA`` file."""
- requested = False
- """A boolean that indicates whether the ``REQUESTED`` metadata file is
- present (in other words, whether the package was installed by user
- request or it was installed as a dependency)."""
-
- def __init__(self, path):
- if _cache_enabled and path in _cache_path:
- self.metadata = _cache_path[path].metadata
- else:
- metadata_path = os.path.join(path, 'METADATA')
- self.metadata = DistributionMetadata(path=metadata_path)
-
- self.path = path
- self.name = self.metadata['name']
-
- if _cache_enabled and not path in _cache_path:
- _cache_path[path] = self
-
- def _get_records(self, local=False):
- RECORD = os.path.join(self.path, 'RECORD')
- record_reader = csv_reader(open(RECORD, 'rb'), delimiter=',')
- for row in record_reader:
- path, md5, size = row[:] + [None for i in xrange(len(row), 3)]
- if local:
- path = path.replace('/', os.sep)
- path = os.path.join(sys.prefix, path)
- yield path, md5, size
-
- def get_installed_files(self, local=False):
- """
- Iterates over the ``RECORD`` entries and returns a tuple
- ``(path, md5, size)`` for each line. If *local* is ``True``,
- the returned path is transformed into a local absolute path.
- Otherwise the raw value from RECORD is returned.
-
- A local absolute path is an absolute path in which occurrences of
- ``'/'`` have been replaced by the system separator given by ``os.sep``.
-
- :parameter local: flag to say if the path should be returned a local
- absolute path
-
- :type local: boolean
- :returns: iterator of (path, md5, size)
- """
- return self._get_records(local)
-
- def uses(self, path):
- """
- Returns ``True`` if path is listed in ``RECORD``. *path* can be a local
- absolute path or a relative ``'/'``-separated path.
-
- :rtype: boolean
- """
- for p, md5, size in self._get_records():
- local_absolute = os.path.join(sys.prefix, p)
- if path == p or path == local_absolute:
- return True
- return False
-
- def get_distinfo_file(self, path, binary=False):
- """
- Returns a file located under the ``.dist-info`` directory. Returns a
- ``file`` instance for the file pointed by *path*.
-
- :parameter path: a ``'/'``-separated path relative to the
- ``.dist-info`` directory or an absolute path;
- If *path* is an absolute path and doesn't start
- with the ``.dist-info`` directory path,
- a :class:`DistutilsError` is raised
- :type path: string
- :parameter binary: If *binary* is ``True``, opens the file in read-only
- binary mode (``rb``), otherwise opens it in
- read-only mode (``r``).
- :rtype: file object
- """
- open_flags = 'r'
- if binary:
- open_flags += 'b'
-
- # Check if it is an absolute path
- if path.find(os.sep) >= 0:
- # it's an absolute path?
- distinfo_dirname, path = path.split(os.sep)[-2:]
- if distinfo_dirname != self.path.split(os.sep)[-1]:
- raise DistutilsError("Requested dist-info file does not "
- "belong to the %s distribution. '%s' was requested." \
- % (self.name, os.sep.join([distinfo_dirname, path])))
-
- # The file must be relative
- if path not in DIST_FILES:
- raise DistutilsError("Requested an invalid dist-info file: "
- "%s" % path)
-
- # Convert the relative path back to absolute
- path = os.path.join(self.path, path)
- return open(path, open_flags)
-
- def get_distinfo_files(self, local=False):
- """
- Iterates over the ``RECORD`` entries and returns paths for each line if
- the path is pointing to a file located in the ``.dist-info`` directory
- or one of its subdirectories.
-
- :parameter local: If *local* is ``True``, each returned path is
- transformed into a local absolute path. Otherwise the
- raw value from ``RECORD`` is returned.
- :type local: boolean
- :returns: iterator of paths
- """
- for path, md5, size in self._get_records(local):
- yield path
-
- def __eq__(self, other):
- return isinstance(other, Distribution) and self.path == other.path
-
- # See http://docs.python.org/reference/datamodel#object.__hash__
- __hash__ = object.__hash__
-
-
-class EggInfoDistribution(object):
- """Created with the *path* of the ``.egg-info`` directory or file provided
- to the constructor. It reads the metadata contained in the file itself, or
- if the given path happens to be a directory, the metadata is read from the
- file ``PKG-INFO`` under that directory."""
-
- name = ''
- """The name of the distribution."""
- metadata = None
- """A :class:`distutils2.metadata.DistributionMetadata` instance loaded with
- the distribution's ``METADATA`` file."""
- _REQUIREMENT = re.compile( \
- r'(?P<name>[-A-Za-z0-9_.]+)\s*' \
- r'(?P<first>(?:<|<=|!=|==|>=|>)[-A-Za-z0-9_.]+)?\s*' \
- r'(?P<rest>(?:\s*,\s*(?:<|<=|!=|==|>=|>)[-A-Za-z0-9_.]+)*)\s*' \
- r'(?P<extras>\[.*\])?')
-
- def __init__(self, path):
- self.path = path
-
- if _cache_enabled and path in _cache_path_egg:
- self.metadata = _cache_path_egg[path].metadata
- self.name = self.metadata['Name']
- return
-
- # reused from Distribute's pkg_resources
- def yield_lines(strs):
- """Yield non-empty/non-comment lines of a ``basestring``
- or sequence"""
- if isinstance(strs, basestring):
- for s in strs.splitlines():
- s = s.strip()
- if s and not s.startswith('#'): # skip blank lines/comments
- yield s
- else:
- for ss in strs:
- for s in yield_lines(ss):
- yield s
-
- requires = None
- if path.endswith('.egg'):
- if os.path.isdir(path):
- meta_path = os.path.join(path, 'EGG-INFO', 'PKG-INFO')
- self.metadata = DistributionMetadata(path=meta_path)
- try:
- req_path = os.path.join(path, 'EGG-INFO', 'requires.txt')
- requires = open(req_path, 'r').read()
- except IOError:
- requires = None
- else:
- zipf = zipimport.zipimporter(path)
- fileobj = StringIO.StringIO(zipf.get_data('EGG-INFO/PKG-INFO'))
- self.metadata = DistributionMetadata(fileobj=fileobj)
- try:
- requires = zipf.get_data('EGG-INFO/requires.txt')
- except IOError:
- requires = None
- self.name = self.metadata['Name']
- elif path.endswith('.egg-info'):
- if os.path.isdir(path):
- path = os.path.join(path, 'PKG-INFO')
- try:
- req_f = open(os.path.join(path, 'requires.txt'), 'r')
- requires = req_f.read()
- except IOError:
- requires = None
- self.metadata = DistributionMetadata(path=path)
- self.name = self.metadata['name']
- else:
- raise ValueError('The path must end with .egg-info or .egg')
-
- provides = "%s (%s)" % (self.metadata['name'],
- self.metadata['version'])
- if self.metadata['Metadata-Version'] == '1.2':
- self.metadata['Provides-Dist'] += (provides,)
- else:
- self.metadata['Provides'] += (provides,)
- reqs = []
- if requires is not None:
- for line in yield_lines(requires):
- if line[0] == '[':
- warnings.warn('distutils2 does not support extensions '
- 'in requires.txt')
- break
- else:
- match = self._REQUIREMENT.match(line.strip())
- if not match:
- raise ValueError('Distribution %s has ill formed '
- 'requires.txt file (%s)' %
- (self.name, line))
- else:
- if match.group('extras'):
- s = (('Distribution %s uses extra requirements '
- 'which are not supported in distutils') \
- % (self.name))
- warnings.warn(s)
- name = match.group('name')
- version = None
- if match.group('first'):
- version = match.group('first')
- if match.group('rest'):
- version += match.group('rest')
- version = version.replace(' ', '') # trim spaces
- if version is None:
- reqs.append(name)
- else:
- reqs.append('%s (%s)' % (name, version))
- if self.metadata['Metadata-Version'] == '1.2':
- self.metadata['Requires-Dist'] += reqs
- else:
- self.metadata['Requires'] += reqs
-
- if _cache_enabled:
- _cache_path_egg[self.path] = self
-
- def get_installed_files(self, local=False):
- return []
-
- def uses(self, path):
- return False
-
- def __eq__(self, other):
- return isinstance(other, EggInfoDistribution) and \
- self.path == other.path
-
- # See http://docs.python.org/reference/datamodel#object.__hash__
- __hash__ = object.__hash__
-
-
-def _normalize_dist_name(name):
- """Returns a normalized name from the given *name*.
- :rtype: string"""
- return name.replace('-', '_')
-
-
-def distinfo_dirname(name, version):
- """
- The *name* and *version* parameters are converted into their
- filename-escaped form, i.e. any ``'-'`` characters are replaced
- with ``'_'`` other than the one in ``'dist-info'`` and the one
- separating the name from the version number.
-
- :parameter name: is converted to a standard distribution name by replacing
- any runs of non- alphanumeric characters with a single
- ``'-'``.
- :type name: string
- :parameter version: is converted to a standard version string. Spaces
- become dots, and all other non-alphanumeric characters
- (except dots) become dashes, with runs of multiple
- dashes condensed to a single dash.
- :type version: string
- :returns: directory name
- :rtype: string"""
- file_extension = '.dist-info'
- name = _normalize_dist_name(name)
- normalized_version = suggest_normalized_version(version)
- # Because this is a lookup procedure, something will be returned even if
- # it is a version that cannot be normalized
- if normalized_version is None:
- # Unable to achieve normality?
- normalized_version = version
- return '-'.join([name, normalized_version]) + file_extension
-
-
-def get_distributions(use_egg_info=False):
- """
- Provides an iterator that looks for ``.dist-info`` directories in
- ``sys.path`` and returns :class:`Distribution` instances for each one of
- them. If the parameters *use_egg_info* is ``True``, then the ``.egg-info``
- files and directores are iterated as well.
-
- :rtype: iterator of :class:`Distribution` and :class:`EggInfoDistribution`
- instances
- """
- if not _cache_enabled:
- for dist in _yield_distributions(True, use_egg_info):
- yield dist
- else:
- _generate_cache(use_egg_info)
-
- for dist in _cache_path.itervalues():
- yield dist
-
- if use_egg_info:
- for dist in _cache_path_egg.itervalues():
- yield dist
-
-
-def get_distribution(name, use_egg_info=False):
- """
- Scans all elements in ``sys.path`` and looks for all directories
- ending with ``.dist-info``. Returns a :class:`Distribution`
- corresponding to the ``.dist-info`` directory that contains the
- ``METADATA`` that matches *name* for the *name* metadata field.
- If no distribution exists with the given *name* and the parameter
- *use_egg_info* is set to ``True``, then all files and directories ending
- with ``.egg-info`` are scanned. A :class:`EggInfoDistribution` instance is
- returned if one is found that has metadata that matches *name* for the
- *name* metadata field.
-
- This function only returns the first result found, as no more than one
- value is expected. If the directory is not found, ``None`` is returned.
-
- :rtype: :class:`Distribution` or :class:`EggInfoDistribution` or None
- """
- if not _cache_enabled:
- for dist in _yield_distributions(True, use_egg_info):
- if dist.name == name:
- return dist
- else:
- _generate_cache(use_egg_info)
-
- if name in _cache_name:
- return _cache_name[name][0]
- elif use_egg_info and name in _cache_name_egg:
- return _cache_name_egg[name][0]
- else:
- return None
-
-
-def obsoletes_distribution(name, version=None, use_egg_info=False):
- """
- Iterates over all distributions to find which distributions obsolete
- *name*.
-
- If a *version* is provided, it will be used to filter the results.
- If the argument *use_egg_info* is set to ``True``, then ``.egg-info``
- distributions will be considered as well.
-
- :type name: string
- :type version: string
- :parameter name:
- """
- for dist in get_distributions(use_egg_info):
- obsoleted = (dist.metadata['Obsoletes-Dist'] +
- dist.metadata['Obsoletes'])
- for obs in obsoleted:
- o_components = obs.split(' ', 1)
- if len(o_components) == 1 or version is None:
- if name == o_components[0]:
- yield dist
- break
- else:
- try:
- predicate = VersionPredicate(obs)
- except ValueError:
- raise DistutilsError(('Distribution %s has ill formed' +
- ' obsoletes field') % (dist.name,))
- if name == o_components[0] and predicate.match(version):
- yield dist
- break
-
-
-def provides_distribution(name, version=None, use_egg_info=False):
- """
- Iterates over all distributions to find which distributions provide *name*.
- If a *version* is provided, it will be used to filter the results. Scans
- all elements in ``sys.path`` and looks for all directories ending with
- ``.dist-info``. Returns a :class:`Distribution` corresponding to the
- ``.dist-info`` directory that contains a ``METADATA`` that matches *name*
- for the name metadata. If the argument *use_egg_info* is set to ``True``,
- then all files and directories ending with ``.egg-info`` are considered
- as well and returns an :class:`EggInfoDistribution` instance.
-
- This function only returns the first result found, since no more than
- one values are expected. If the directory is not found, returns ``None``.
-
- :parameter version: a version specifier that indicates the version
- required, conforming to the format in ``PEP-345``
-
- :type name: string
- :type version: string
- """
- predicate = None
- if not version is None:
- try:
- predicate = VersionPredicate(name + ' (' + version + ')')
- except ValueError:
- raise DistutilsError('Invalid name or version')
-
- for dist in get_distributions(use_egg_info):
- provided = dist.metadata['Provides-Dist'] + dist.metadata['Provides']
-
- for p in provided:
- p_components = p.rsplit(' ', 1)
- if len(p_components) == 1 or predicate is None:
- if name == p_components[0]:
- yield dist
- break
- else:
- p_name, p_ver = p_components
- if len(p_ver) < 2 or p_ver[0] != '(' or p_ver[-1] != ')':
- raise DistutilsError(('Distribution %s has invalid ' +
- 'provides field: %s') \
- % (dist.name, p))
- p_ver = p_ver[1:-1] # trim off the parenthesis
- if p_name == name and predicate.match(p_ver):
- yield dist
- break
-
-
-def get_file_users(path):
- """
- Iterates over all distributions to find out which distributions uses
- *path*.
-
- :parameter path: can be a local absolute path or a relative
- ``'/'``-separated path.
- :type path: string
- :rtype: iterator of :class:`Distribution` instances
- """
- for dist in get_distributions():
- if dist.uses(path):
- yield dist
diff --git a/src/distutils2/_backport/sha256module.c b/src/distutils2/_backport/sha256module.c
deleted file mode 100644
index 96cbd10..0000000
--- a/src/distutils2/_backport/sha256module.c
+++ /dev/null
@@ -1,701 +0,0 @@
-/* SHA256 module */
-
-/* This module provides an interface to NIST's SHA-256 and SHA-224 Algorithms */
-
-/* See below for information about the original code this module was
- based upon. Additional work performed by:
-
- Andrew Kuchling (amk@amk.ca)
- Greg Stein (gstein@lyra.org)
- Trevor Perrin (trevp@trevp.net)
-
- Copyright (C) 2005 Gregory P. Smith (greg@krypto.org)
- Licensed to PSF under a Contributor Agreement.
-
-*/
-
-/* SHA objects */
-
-#include "Python.h"
-#include "structmember.h"
-
-
-/* Endianness testing and definitions */
-#define TestEndianness(variable) {int i=1; variable=PCT_BIG_ENDIAN;\
- if (*((char*)&i)==1) variable=PCT_LITTLE_ENDIAN;}
-
-#define PCT_LITTLE_ENDIAN 1
-#define PCT_BIG_ENDIAN 0
-
-/* Some useful types */
-
-typedef unsigned char SHA_BYTE;
-
-#if SIZEOF_INT == 4
-typedef unsigned int SHA_INT32; /* 32-bit integer */
-#else
-/* not defined. compilation will die. */
-#endif
-
-/* The SHA block size and message digest sizes, in bytes */
-
-#define SHA_BLOCKSIZE 64
-#define SHA_DIGESTSIZE 32
-
-/* The structure for storing SHA info */
-
-typedef struct {
- PyObject_HEAD
- SHA_INT32 digest[8]; /* Message digest */
- SHA_INT32 count_lo, count_hi; /* 64-bit bit count */
- SHA_BYTE data[SHA_BLOCKSIZE]; /* SHA data buffer */
- int Endianness;
- int local; /* unprocessed amount in data */
- int digestsize;
-} SHAobject;
-
-/* When run on a little-endian CPU we need to perform byte reversal on an
- array of longwords. */
-
-static void longReverse(SHA_INT32 *buffer, int byteCount, int Endianness)
-{
- SHA_INT32 value;
-
- if ( Endianness == PCT_BIG_ENDIAN )
- return;
-
- byteCount /= sizeof(*buffer);
- while (byteCount--) {
- value = *buffer;
- value = ( ( value & 0xFF00FF00L ) >> 8 ) | \
- ( ( value & 0x00FF00FFL ) << 8 );
- *buffer++ = ( value << 16 ) | ( value >> 16 );
- }
-}
-
-static void SHAcopy(SHAobject *src, SHAobject *dest)
-{
- dest->Endianness = src->Endianness;
- dest->local = src->local;
- dest->digestsize = src->digestsize;
- dest->count_lo = src->count_lo;
- dest->count_hi = src->count_hi;
- memcpy(dest->digest, src->digest, sizeof(src->digest));
- memcpy(dest->data, src->data, sizeof(src->data));
-}
-
-
-/* ------------------------------------------------------------------------
- *
- * This code for the SHA-256 algorithm was noted as public domain. The
- * original headers are pasted below.
- *
- * Several changes have been made to make it more compatible with the
- * Python environment and desired interface.
- *
- */
-
-/* LibTomCrypt, modular cryptographic library -- Tom St Denis
- *
- * LibTomCrypt is a library that provides various cryptographic
- * algorithms in a highly modular and flexible manner.
- *
- * The library is free for all purposes without any express
- * gurantee it works.
- *
- * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
- */
-
-
-/* SHA256 by Tom St Denis */
-
-/* Various logical functions */
-#define ROR(x, y)\
-( ((((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)((y)&31)) | \
-((unsigned long)(x)<<(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL)
-#define Ch(x,y,z) (z ^ (x & (y ^ z)))
-#define Maj(x,y,z) (((x | y) & z) | (x & y))
-#define S(x, n) ROR((x),(n))
-#define R(x, n) (((x)&0xFFFFFFFFUL)>>(n))
-#define Sigma0(x) (S(x, 2) ^ S(x, 13) ^ S(x, 22))
-#define Sigma1(x) (S(x, 6) ^ S(x, 11) ^ S(x, 25))
-#define Gamma0(x) (S(x, 7) ^ S(x, 18) ^ R(x, 3))
-#define Gamma1(x) (S(x, 17) ^ S(x, 19) ^ R(x, 10))
-
-
-static void
-sha_transform(SHAobject *sha_info)
-{
- int i;
- SHA_INT32 S[8], W[64], t0, t1;
-
- memcpy(W, sha_info->data, sizeof(sha_info->data));
- longReverse(W, (int)sizeof(sha_info->data), sha_info->Endianness);
-
- for (i = 16; i < 64; ++i) {
- W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16];
- }
- for (i = 0; i < 8; ++i) {
- S[i] = sha_info->digest[i];
- }
-
- /* Compress */
-#define RND(a,b,c,d,e,f,g,h,i,ki) \
- t0 = h + Sigma1(e) + Ch(e, f, g) + ki + W[i]; \
- t1 = Sigma0(a) + Maj(a, b, c); \
- d += t0; \
- h = t0 + t1;
-
- RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],0,0x428a2f98);
- RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],1,0x71374491);
- RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],2,0xb5c0fbcf);
- RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],3,0xe9b5dba5);
- RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],4,0x3956c25b);
- RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],5,0x59f111f1);
- RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],6,0x923f82a4);
- RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],7,0xab1c5ed5);
- RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],8,0xd807aa98);
- RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],9,0x12835b01);
- RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],10,0x243185be);
- RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],11,0x550c7dc3);
- RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],12,0x72be5d74);
- RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],13,0x80deb1fe);
- RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],14,0x9bdc06a7);
- RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],15,0xc19bf174);
- RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],16,0xe49b69c1);
- RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],17,0xefbe4786);
- RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],18,0x0fc19dc6);
- RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],19,0x240ca1cc);
- RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],20,0x2de92c6f);
- RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],21,0x4a7484aa);
- RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],22,0x5cb0a9dc);
- RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],23,0x76f988da);
- RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],24,0x983e5152);
- RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],25,0xa831c66d);
- RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],26,0xb00327c8);
- RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],27,0xbf597fc7);
- RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],28,0xc6e00bf3);
- RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],29,0xd5a79147);
- RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],30,0x06ca6351);
- RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],31,0x14292967);
- RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],32,0x27b70a85);
- RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],33,0x2e1b2138);
- RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],34,0x4d2c6dfc);
- RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],35,0x53380d13);
- RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],36,0x650a7354);
- RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],37,0x766a0abb);
- RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],38,0x81c2c92e);
- RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],39,0x92722c85);
- RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],40,0xa2bfe8a1);
- RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],41,0xa81a664b);
- RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],42,0xc24b8b70);
- RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],43,0xc76c51a3);
- RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],44,0xd192e819);
- RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],45,0xd6990624);
- RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],46,0xf40e3585);
- RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],47,0x106aa070);
- RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],48,0x19a4c116);
- RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],49,0x1e376c08);
- RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],50,0x2748774c);
- RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],51,0x34b0bcb5);
- RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],52,0x391c0cb3);
- RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],53,0x4ed8aa4a);
- RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],54,0x5b9cca4f);
- RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],55,0x682e6ff3);
- RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],56,0x748f82ee);
- RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],57,0x78a5636f);
- RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],58,0x84c87814);
- RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],59,0x8cc70208);
- RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],60,0x90befffa);
- RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],61,0xa4506ceb);
- RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],62,0xbef9a3f7);
- RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],63,0xc67178f2);
-
-#undef RND
-
- /* feedback */
- for (i = 0; i < 8; i++) {
- sha_info->digest[i] = sha_info->digest[i] + S[i];
- }
-
-}
-
-
-
-/* initialize the SHA digest */
-
-static void
-sha_init(SHAobject *sha_info)
-{
- TestEndianness(sha_info->Endianness)
- sha_info->digest[0] = 0x6A09E667L;
- sha_info->digest[1] = 0xBB67AE85L;
- sha_info->digest[2] = 0x3C6EF372L;
- sha_info->digest[3] = 0xA54FF53AL;
- sha_info->digest[4] = 0x510E527FL;
- sha_info->digest[5] = 0x9B05688CL;
- sha_info->digest[6] = 0x1F83D9ABL;
- sha_info->digest[7] = 0x5BE0CD19L;
- sha_info->count_lo = 0L;
- sha_info->count_hi = 0L;
- sha_info->local = 0;
- sha_info->digestsize = 32;
-}
-
-static void
-sha224_init(SHAobject *sha_info)
-{
- TestEndianness(sha_info->Endianness)
- sha_info->digest[0] = 0xc1059ed8L;
- sha_info->digest[1] = 0x367cd507L;
- sha_info->digest[2] = 0x3070dd17L;
- sha_info->digest[3] = 0xf70e5939L;
- sha_info->digest[4] = 0xffc00b31L;
- sha_info->digest[5] = 0x68581511L;
- sha_info->digest[6] = 0x64f98fa7L;
- sha_info->digest[7] = 0xbefa4fa4L;
- sha_info->count_lo = 0L;
- sha_info->count_hi = 0L;
- sha_info->local = 0;
- sha_info->digestsize = 28;
-}
-
-
-/* update the SHA digest */
-
-static void
-sha_update(SHAobject *sha_info, SHA_BYTE *buffer, int count)
-{
- int i;
- SHA_INT32 clo;
-
- clo = sha_info->count_lo + ((SHA_INT32) count << 3);
- if (clo < sha_info->count_lo) {
- ++sha_info->count_hi;
- }
- sha_info->count_lo = clo;
- sha_info->count_hi += (SHA_INT32) count >> 29;
- if (sha_info->local) {
- i = SHA_BLOCKSIZE - sha_info->local;
- if (i > count) {
- i = count;
- }
- memcpy(((SHA_BYTE *) sha_info->data) + sha_info->local, buffer, i);
- count -= i;
- buffer += i;
- sha_info->local += i;
- if (sha_info->local == SHA_BLOCKSIZE) {
- sha_transform(sha_info);
- }
- else {
- return;
- }
- }
- while (count >= SHA_BLOCKSIZE) {
- memcpy(sha_info->data, buffer, SHA_BLOCKSIZE);
- buffer += SHA_BLOCKSIZE;
- count -= SHA_BLOCKSIZE;
- sha_transform(sha_info);
- }
- memcpy(sha_info->data, buffer, count);
- sha_info->local = count;
-}
-
-/* finish computing the SHA digest */
-
-static void
-sha_final(unsigned char digest[SHA_DIGESTSIZE], SHAobject *sha_info)
-{
- int count;
- SHA_INT32 lo_bit_count, hi_bit_count;
-
- lo_bit_count = sha_info->count_lo;
- hi_bit_count = sha_info->count_hi;
- count = (int) ((lo_bit_count >> 3) & 0x3f);
- ((SHA_BYTE *) sha_info->data)[count++] = 0x80;
- if (count > SHA_BLOCKSIZE - 8) {
- memset(((SHA_BYTE *) sha_info->data) + count, 0,
- SHA_BLOCKSIZE - count);
- sha_transform(sha_info);
- memset((SHA_BYTE *) sha_info->data, 0, SHA_BLOCKSIZE - 8);
- }
- else {
- memset(((SHA_BYTE *) sha_info->data) + count, 0,
- SHA_BLOCKSIZE - 8 - count);
- }
-
- /* GJS: note that we add the hi/lo in big-endian. sha_transform will
- swap these values into host-order. */
- sha_info->data[56] = (hi_bit_count >> 24) & 0xff;
- sha_info->data[57] = (hi_bit_count >> 16) & 0xff;
- sha_info->data[58] = (hi_bit_count >> 8) & 0xff;
- sha_info->data[59] = (hi_bit_count >> 0) & 0xff;
- sha_info->data[60] = (lo_bit_count >> 24) & 0xff;
- sha_info->data[61] = (lo_bit_count >> 16) & 0xff;
- sha_info->data[62] = (lo_bit_count >> 8) & 0xff;
- sha_info->data[63] = (lo_bit_count >> 0) & 0xff;
- sha_transform(sha_info);
- digest[ 0] = (unsigned char) ((sha_info->digest[0] >> 24) & 0xff);
- digest[ 1] = (unsigned char) ((sha_info->digest[0] >> 16) & 0xff);
- digest[ 2] = (unsigned char) ((sha_info->digest[0] >> 8) & 0xff);
- digest[ 3] = (unsigned char) ((sha_info->digest[0] ) & 0xff);
- digest[ 4] = (unsigned char) ((sha_info->digest[1] >> 24) & 0xff);
- digest[ 5] = (unsigned char) ((sha_info->digest[1] >> 16) & 0xff);
- digest[ 6] = (unsigned char) ((sha_info->digest[1] >> 8) & 0xff);
- digest[ 7] = (unsigned char) ((sha_info->digest[1] ) & 0xff);
- digest[ 8] = (unsigned char) ((sha_info->digest[2] >> 24) & 0xff);
- digest[ 9] = (unsigned char) ((sha_info->digest[2] >> 16) & 0xff);
- digest[10] = (unsigned char) ((sha_info->digest[2] >> 8) & 0xff);
- digest[11] = (unsigned char) ((sha_info->digest[2] ) & 0xff);
- digest[12] = (unsigned char) ((sha_info->digest[3] >> 24) & 0xff);
- digest[13] = (unsigned char) ((sha_info->digest[3] >> 16) & 0xff);
- digest[14] = (unsigned char) ((sha_info->digest[3] >> 8) & 0xff);
- digest[15] = (unsigned char) ((sha_info->digest[3] ) & 0xff);
- digest[16] = (unsigned char) ((sha_info->digest[4] >> 24) & 0xff);
- digest[17] = (unsigned char) ((sha_info->digest[4] >> 16) & 0xff);
- digest[18] = (unsigned char) ((sha_info->digest[4] >> 8) & 0xff);
- digest[19] = (unsigned char) ((sha_info->digest[4] ) & 0xff);
- digest[20] = (unsigned char) ((sha_info->digest[5] >> 24) & 0xff);
- digest[21] = (unsigned char) ((sha_info->digest[5] >> 16) & 0xff);
- digest[22] = (unsigned char) ((sha_info->digest[5] >> 8) & 0xff);
- digest[23] = (unsigned char) ((sha_info->digest[5] ) & 0xff);
- digest[24] = (unsigned char) ((sha_info->digest[6] >> 24) & 0xff);
- digest[25] = (unsigned char) ((sha_info->digest[6] >> 16) & 0xff);
- digest[26] = (unsigned char) ((sha_info->digest[6] >> 8) & 0xff);
- digest[27] = (unsigned char) ((sha_info->digest[6] ) & 0xff);
- digest[28] = (unsigned char) ((sha_info->digest[7] >> 24) & 0xff);
- digest[29] = (unsigned char) ((sha_info->digest[7] >> 16) & 0xff);
- digest[30] = (unsigned char) ((sha_info->digest[7] >> 8) & 0xff);
- digest[31] = (unsigned char) ((sha_info->digest[7] ) & 0xff);
-}
-
-/*
- * End of copied SHA code.
- *
- * ------------------------------------------------------------------------
- */
-
-static PyTypeObject SHA224type;
-static PyTypeObject SHA256type;
-
-
-static SHAobject *
-newSHA224object(void)
-{
- return (SHAobject *)PyObject_New(SHAobject, &SHA224type);
-}
-
-static SHAobject *
-newSHA256object(void)
-{
- return (SHAobject *)PyObject_New(SHAobject, &SHA256type);
-}
-
-/* Internal methods for a hash object */
-
-static void
-SHA_dealloc(PyObject *ptr)
-{
- PyObject_Del(ptr);
-}
-
-
-/* External methods for a hash object */
-
-PyDoc_STRVAR(SHA256_copy__doc__, "Return a copy of the hash object.");
-
-static PyObject *
-SHA256_copy(SHAobject *self, PyObject *unused)
-{
- SHAobject *newobj;
-
- if (((PyObject*)self)->ob_type == &SHA256type) {
- if ( (newobj = newSHA256object())==NULL)
- return NULL;
- } else {
- if ( (newobj = newSHA224object())==NULL)
- return NULL;
- }
-
- SHAcopy(self, newobj);
- return (PyObject *)newobj;
-}
-
-PyDoc_STRVAR(SHA256_digest__doc__,
-"Return the digest value as a string of binary data.");
-
-static PyObject *
-SHA256_digest(SHAobject *self, PyObject *unused)
-{
- unsigned char digest[SHA_DIGESTSIZE];
- SHAobject temp;
-
- SHAcopy(self, &temp);
- sha_final(digest, &temp);
- return PyString_FromStringAndSize((const char *)digest, self->digestsize);
-}
-
-PyDoc_STRVAR(SHA256_hexdigest__doc__,
-"Return the digest value as a string of hexadecimal digits.");
-
-static PyObject *
-SHA256_hexdigest(SHAobject *self, PyObject *unused)
-{
- unsigned char digest[SHA_DIGESTSIZE];
- SHAobject temp;
- PyObject *retval;
- char *hex_digest;
- int i, j;
-
- /* Get the raw (binary) digest value */
- SHAcopy(self, &temp);
- sha_final(digest, &temp);
-
- /* Create a new string */
- retval = PyString_FromStringAndSize(NULL, self->digestsize * 2);
- if (!retval)
- return NULL;
- hex_digest = PyString_AsString(retval);
- if (!hex_digest) {
- Py_DECREF(retval);
- return NULL;
- }
-
- /* Make hex version of the digest */
- for(i=j=0; i<self->digestsize; i++) {
- char c;
- c = (digest[i] >> 4) & 0xf;
- c = (c>9) ? c+'a'-10 : c + '0';
- hex_digest[j++] = c;
- c = (digest[i] & 0xf);
- c = (c>9) ? c+'a'-10 : c + '0';
- hex_digest[j++] = c;
- }
- return retval;
-}
-
-PyDoc_STRVAR(SHA256_update__doc__,
-"Update this hash object's state with the provided string.");
-
-static PyObject *
-SHA256_update(SHAobject *self, PyObject *args)
-{
- unsigned char *cp;
- int len;
-
- if (!PyArg_ParseTuple(args, "s#:update", &cp, &len))
- return NULL;
-
- sha_update(self, cp, len);
-
- Py_INCREF(Py_None);
- return Py_None;
-}
-
-static PyMethodDef SHA_methods[] = {
- {"copy", (PyCFunction)SHA256_copy, METH_NOARGS, SHA256_copy__doc__},
- {"digest", (PyCFunction)SHA256_digest, METH_NOARGS, SHA256_digest__doc__},
- {"hexdigest", (PyCFunction)SHA256_hexdigest, METH_NOARGS, SHA256_hexdigest__doc__},
- {"update", (PyCFunction)SHA256_update, METH_VARARGS, SHA256_update__doc__},
- {NULL, NULL} /* sentinel */
-};
-
-static PyObject *
-SHA256_get_block_size(PyObject *self, void *closure)
-{
- return PyInt_FromLong(SHA_BLOCKSIZE);
-}
-
-static PyObject *
-SHA256_get_name(PyObject *self, void *closure)
-{
- if (((SHAobject *)self)->digestsize == 32)
- return PyString_FromStringAndSize("SHA256", 6);
- else
- return PyString_FromStringAndSize("SHA224", 6);
-}
-
-static PyGetSetDef SHA_getseters[] = {
- {"block_size",
- (getter)SHA256_get_block_size, NULL,
- NULL,
- NULL},
- {"name",
- (getter)SHA256_get_name, NULL,
- NULL,
- NULL},
- {NULL} /* Sentinel */
-};
-
-static PyMemberDef SHA_members[] = {
- {"digest_size", T_INT, offsetof(SHAobject, digestsize), READONLY, NULL},
- /* the old md5 and sha modules support 'digest_size' as in PEP 247.
- * the old sha module also supported 'digestsize'. ugh. */
- {"digestsize", T_INT, offsetof(SHAobject, digestsize), READONLY, NULL},
- {NULL} /* Sentinel */
-};
-
-static PyTypeObject SHA224type = {
- PyObject_HEAD_INIT(NULL)
- 0, /*ob_size*/
- "_sha256.sha224", /*tp_name*/
- sizeof(SHAobject), /*tp_size*/
- 0, /*tp_itemsize*/
- /* methods */
- SHA_dealloc, /*tp_dealloc*/
- 0, /*tp_print*/
- 0, /*tp_getattr*/
- 0, /*tp_setattr*/
- 0, /*tp_compare*/
- 0, /*tp_repr*/
- 0, /*tp_as_number*/
- 0, /*tp_as_sequence*/
- 0, /*tp_as_mapping*/
- 0, /*tp_hash*/
- 0, /*tp_call*/
- 0, /*tp_str*/
- 0, /*tp_getattro*/
- 0, /*tp_setattro*/
- 0, /*tp_as_buffer*/
- Py_TPFLAGS_DEFAULT, /*tp_flags*/
- 0, /*tp_doc*/
- 0, /*tp_traverse*/
- 0, /*tp_clear*/
- 0, /*tp_richcompare*/
- 0, /*tp_weaklistoffset*/
- 0, /*tp_iter*/
- 0, /*tp_iternext*/
- SHA_methods, /* tp_methods */
- SHA_members, /* tp_members */
- SHA_getseters, /* tp_getset */
-};
-
-static PyTypeObject SHA256type = {
- PyObject_HEAD_INIT(NULL)
- 0, /*ob_size*/
- "_sha256.sha256", /*tp_name*/
- sizeof(SHAobject), /*tp_size*/
- 0, /*tp_itemsize*/
- /* methods */
- SHA_dealloc, /*tp_dealloc*/
- 0, /*tp_print*/
- 0, /*tp_getattr*/
- 0, /*tp_setattr*/
- 0, /*tp_compare*/
- 0, /*tp_repr*/
- 0, /*tp_as_number*/
- 0, /*tp_as_sequence*/
- 0, /*tp_as_mapping*/
- 0, /*tp_hash*/
- 0, /*tp_call*/
- 0, /*tp_str*/
- 0, /*tp_getattro*/
- 0, /*tp_setattro*/
- 0, /*tp_as_buffer*/
- Py_TPFLAGS_DEFAULT, /*tp_flags*/
- 0, /*tp_doc*/
- 0, /*tp_traverse*/
- 0, /*tp_clear*/
- 0, /*tp_richcompare*/
- 0, /*tp_weaklistoffset*/
- 0, /*tp_iter*/
- 0, /*tp_iternext*/
- SHA_methods, /* tp_methods */
- SHA_members, /* tp_members */
- SHA_getseters, /* tp_getset */
-};
-
-
-/* The single module-level function: new() */
-
-PyDoc_STRVAR(SHA256_new__doc__,
-"Return a new SHA-256 hash object; optionally initialized with a string.");
-
-static PyObject *
-SHA256_new(PyObject *self, PyObject *args, PyObject *kwdict)
-{
- static char *kwlist[] = {"string", NULL};
- SHAobject *new;
- unsigned char *cp = NULL;
- int len;
-
- if (!PyArg_ParseTupleAndKeywords(args, kwdict, "|s#:new", kwlist,
- &cp, &len)) {
- return NULL;
- }
-
- if ((new = newSHA256object()) == NULL)
- return NULL;
-
- sha_init(new);
-
- if (PyErr_Occurred()) {
- Py_DECREF(new);
- return NULL;
- }
- if (cp)
- sha_update(new, cp, len);
-
- return (PyObject *)new;
-}
-
-PyDoc_STRVAR(SHA224_new__doc__,
-"Return a new SHA-224 hash object; optionally initialized with a string.");
-
-static PyObject *
-SHA224_new(PyObject *self, PyObject *args, PyObject *kwdict)
-{
- static char *kwlist[] = {"string", NULL};
- SHAobject *new;
- unsigned char *cp = NULL;
- int len;
-
- if (!PyArg_ParseTupleAndKeywords(args, kwdict, "|s#:new", kwlist,
- &cp, &len)) {
- return NULL;
- }
-
- if ((new = newSHA224object()) == NULL)
- return NULL;
-
- sha224_init(new);
-
- if (PyErr_Occurred()) {
- Py_DECREF(new);
- return NULL;
- }
- if (cp)
- sha_update(new, cp, len);
-
- return (PyObject *)new;
-}
-
-
-/* List of functions exported by this module */
-
-static struct PyMethodDef SHA_functions[] = {
- {"sha256", (PyCFunction)SHA256_new, METH_VARARGS|METH_KEYWORDS, SHA256_new__doc__},
- {"sha224", (PyCFunction)SHA224_new, METH_VARARGS|METH_KEYWORDS, SHA224_new__doc__},
- {NULL, NULL} /* Sentinel */
-};
-
-
-/* Initialize this module. */
-
-#define insint(n,v) { PyModule_AddIntConstant(m,n,v); }
-
-PyMODINIT_FUNC
-init_sha256(void)
-{
- PyObject *m;
-
- SHA224type.ob_type = &PyType_Type;
- if (PyType_Ready(&SHA224type) < 0)
- return;
- SHA256type.ob_type = &PyType_Type;
- if (PyType_Ready(&SHA256type) < 0)
- return;
- m = Py_InitModule("_sha256", SHA_functions);
- if (m == NULL)
- return;
-}
diff --git a/src/distutils2/_backport/sha512module.c b/src/distutils2/_backport/sha512module.c
deleted file mode 100644
index dbaec17..0000000
--- a/src/distutils2/_backport/sha512module.c
+++ /dev/null
@@ -1,769 +0,0 @@
-/* SHA512 module */
-
-/* This module provides an interface to NIST's SHA-512 and SHA-384 Algorithms */
-
-/* See below for information about the original code this module was
- based upon. Additional work performed by:
-
- Andrew Kuchling (amk@amk.ca)
- Greg Stein (gstein@lyra.org)
- Trevor Perrin (trevp@trevp.net)
-
- Copyright (C) 2005 Gregory P. Smith (greg@krypto.org)
- Licensed to PSF under a Contributor Agreement.
-
-*/
-
-/* SHA objects */
-
-#include "Python.h"
-#include "structmember.h"
-
-#ifdef PY_LONG_LONG /* If no PY_LONG_LONG, don't compile anything! */
-
-/* Endianness testing and definitions */
-#define TestEndianness(variable) {int i=1; variable=PCT_BIG_ENDIAN;\
- if (*((char*)&i)==1) variable=PCT_LITTLE_ENDIAN;}
-
-#define PCT_LITTLE_ENDIAN 1
-#define PCT_BIG_ENDIAN 0
-
-/* Some useful types */
-
-typedef unsigned char SHA_BYTE;
-
-#if SIZEOF_INT == 4
-typedef unsigned int SHA_INT32; /* 32-bit integer */
-typedef unsigned PY_LONG_LONG SHA_INT64; /* 64-bit integer */
-#else
-/* not defined. compilation will die. */
-#endif
-
-/* The SHA block size and message digest sizes, in bytes */
-
-#define SHA_BLOCKSIZE 128
-#define SHA_DIGESTSIZE 64
-
-/* The structure for storing SHA info */
-
-typedef struct {
- PyObject_HEAD
- SHA_INT64 digest[8]; /* Message digest */
- SHA_INT32 count_lo, count_hi; /* 64-bit bit count */
- SHA_BYTE data[SHA_BLOCKSIZE]; /* SHA data buffer */
- int Endianness;
- int local; /* unprocessed amount in data */
- int digestsize;
-} SHAobject;
-
-/* When run on a little-endian CPU we need to perform byte reversal on an
- array of longwords. */
-
-static void longReverse(SHA_INT64 *buffer, int byteCount, int Endianness)
-{
- SHA_INT64 value;
-
- if ( Endianness == PCT_BIG_ENDIAN )
- return;
-
- byteCount /= sizeof(*buffer);
- while (byteCount--) {
- value = *buffer;
-
- ((unsigned char*)buffer)[0] = (unsigned char)(value >> 56) & 0xff;
- ((unsigned char*)buffer)[1] = (unsigned char)(value >> 48) & 0xff;
- ((unsigned char*)buffer)[2] = (unsigned char)(value >> 40) & 0xff;
- ((unsigned char*)buffer)[3] = (unsigned char)(value >> 32) & 0xff;
- ((unsigned char*)buffer)[4] = (unsigned char)(value >> 24) & 0xff;
- ((unsigned char*)buffer)[5] = (unsigned char)(value >> 16) & 0xff;
- ((unsigned char*)buffer)[6] = (unsigned char)(value >> 8) & 0xff;
- ((unsigned char*)buffer)[7] = (unsigned char)(value ) & 0xff;
-
- buffer++;
- }
-}
-
-static void SHAcopy(SHAobject *src, SHAobject *dest)
-{
- dest->Endianness = src->Endianness;
- dest->local = src->local;
- dest->digestsize = src->digestsize;
- dest->count_lo = src->count_lo;
- dest->count_hi = src->count_hi;
- memcpy(dest->digest, src->digest, sizeof(src->digest));
- memcpy(dest->data, src->data, sizeof(src->data));
-}
-
-
-/* ------------------------------------------------------------------------
- *
- * This code for the SHA-512 algorithm was noted as public domain. The
- * original headers are pasted below.
- *
- * Several changes have been made to make it more compatible with the
- * Python environment and desired interface.
- *
- */
-
-/* LibTomCrypt, modular cryptographic library -- Tom St Denis
- *
- * LibTomCrypt is a library that provides various cryptographic
- * algorithms in a highly modular and flexible manner.
- *
- * The library is free for all purposes without any express
- * gurantee it works.
- *
- * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
- */
-
-
-/* SHA512 by Tom St Denis */
-
-/* Various logical functions */
-#define ROR64(x, y) \
- ( ((((x) & 0xFFFFFFFFFFFFFFFFULL)>>((unsigned PY_LONG_LONG)(y) & 63)) | \
- ((x)<<((unsigned PY_LONG_LONG)(64-((y) & 63))))) & 0xFFFFFFFFFFFFFFFFULL)
-#define Ch(x,y,z) (z ^ (x & (y ^ z)))
-#define Maj(x,y,z) (((x | y) & z) | (x & y))
-#define S(x, n) ROR64((x),(n))
-#define R(x, n) (((x) & 0xFFFFFFFFFFFFFFFFULL) >> ((unsigned PY_LONG_LONG)n))
-#define Sigma0(x) (S(x, 28) ^ S(x, 34) ^ S(x, 39))
-#define Sigma1(x) (S(x, 14) ^ S(x, 18) ^ S(x, 41))
-#define Gamma0(x) (S(x, 1) ^ S(x, 8) ^ R(x, 7))
-#define Gamma1(x) (S(x, 19) ^ S(x, 61) ^ R(x, 6))
-
-
-static void
-sha512_transform(SHAobject *sha_info)
-{
- int i;
- SHA_INT64 S[8], W[80], t0, t1;
-
- memcpy(W, sha_info->data, sizeof(sha_info->data));
- longReverse(W, (int)sizeof(sha_info->data), sha_info->Endianness);
-
- for (i = 16; i < 80; ++i) {
- W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16];
- }
- for (i = 0; i < 8; ++i) {
- S[i] = sha_info->digest[i];
- }
-
- /* Compress */
-#define RND(a,b,c,d,e,f,g,h,i,ki) \
- t0 = h + Sigma1(e) + Ch(e, f, g) + ki + W[i]; \
- t1 = Sigma0(a) + Maj(a, b, c); \
- d += t0; \
- h = t0 + t1;
-
- RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],0,0x428a2f98d728ae22ULL);
- RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],1,0x7137449123ef65cdULL);
- RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],2,0xb5c0fbcfec4d3b2fULL);
- RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],3,0xe9b5dba58189dbbcULL);
- RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],4,0x3956c25bf348b538ULL);
- RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],5,0x59f111f1b605d019ULL);
- RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],6,0x923f82a4af194f9bULL);
- RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],7,0xab1c5ed5da6d8118ULL);
- RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],8,0xd807aa98a3030242ULL);
- RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],9,0x12835b0145706fbeULL);
- RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],10,0x243185be4ee4b28cULL);
- RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],11,0x550c7dc3d5ffb4e2ULL);
- RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],12,0x72be5d74f27b896fULL);
- RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],13,0x80deb1fe3b1696b1ULL);
- RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],14,0x9bdc06a725c71235ULL);
- RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],15,0xc19bf174cf692694ULL);
- RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],16,0xe49b69c19ef14ad2ULL);
- RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],17,0xefbe4786384f25e3ULL);
- RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],18,0x0fc19dc68b8cd5b5ULL);
- RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],19,0x240ca1cc77ac9c65ULL);
- RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],20,0x2de92c6f592b0275ULL);
- RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],21,0x4a7484aa6ea6e483ULL);
- RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],22,0x5cb0a9dcbd41fbd4ULL);
- RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],23,0x76f988da831153b5ULL);
- RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],24,0x983e5152ee66dfabULL);
- RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],25,0xa831c66d2db43210ULL);
- RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],26,0xb00327c898fb213fULL);
- RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],27,0xbf597fc7beef0ee4ULL);
- RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],28,0xc6e00bf33da88fc2ULL);
- RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],29,0xd5a79147930aa725ULL);
- RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],30,0x06ca6351e003826fULL);
- RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],31,0x142929670a0e6e70ULL);
- RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],32,0x27b70a8546d22ffcULL);
- RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],33,0x2e1b21385c26c926ULL);
- RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],34,0x4d2c6dfc5ac42aedULL);
- RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],35,0x53380d139d95b3dfULL);
- RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],36,0x650a73548baf63deULL);
- RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],37,0x766a0abb3c77b2a8ULL);
- RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],38,0x81c2c92e47edaee6ULL);
- RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],39,0x92722c851482353bULL);
- RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],40,0xa2bfe8a14cf10364ULL);
- RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],41,0xa81a664bbc423001ULL);
- RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],42,0xc24b8b70d0f89791ULL);
- RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],43,0xc76c51a30654be30ULL);
- RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],44,0xd192e819d6ef5218ULL);
- RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],45,0xd69906245565a910ULL);
- RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],46,0xf40e35855771202aULL);
- RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],47,0x106aa07032bbd1b8ULL);
- RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],48,0x19a4c116b8d2d0c8ULL);
- RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],49,0x1e376c085141ab53ULL);
- RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],50,0x2748774cdf8eeb99ULL);
- RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],51,0x34b0bcb5e19b48a8ULL);
- RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],52,0x391c0cb3c5c95a63ULL);
- RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],53,0x4ed8aa4ae3418acbULL);
- RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],54,0x5b9cca4f7763e373ULL);
- RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],55,0x682e6ff3d6b2b8a3ULL);
- RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],56,0x748f82ee5defb2fcULL);
- RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],57,0x78a5636f43172f60ULL);
- RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],58,0x84c87814a1f0ab72ULL);
- RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],59,0x8cc702081a6439ecULL);
- RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],60,0x90befffa23631e28ULL);
- RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],61,0xa4506cebde82bde9ULL);
- RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],62,0xbef9a3f7b2c67915ULL);
- RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],63,0xc67178f2e372532bULL);
- RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],64,0xca273eceea26619cULL);
- RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],65,0xd186b8c721c0c207ULL);
- RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],66,0xeada7dd6cde0eb1eULL);
- RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],67,0xf57d4f7fee6ed178ULL);
- RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],68,0x06f067aa72176fbaULL);
- RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],69,0x0a637dc5a2c898a6ULL);
- RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],70,0x113f9804bef90daeULL);
- RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],71,0x1b710b35131c471bULL);
- RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],72,0x28db77f523047d84ULL);
- RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],73,0x32caab7b40c72493ULL);
- RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],74,0x3c9ebe0a15c9bebcULL);
- RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],75,0x431d67c49c100d4cULL);
- RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],76,0x4cc5d4becb3e42b6ULL);
- RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],77,0x597f299cfc657e2aULL);
- RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],78,0x5fcb6fab3ad6faecULL);
- RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],79,0x6c44198c4a475817ULL);
-
-#undef RND
-
- /* feedback */
- for (i = 0; i < 8; i++) {
- sha_info->digest[i] = sha_info->digest[i] + S[i];
- }
-
-}
-
-
-
-/* initialize the SHA digest */
-
-static void
-sha512_init(SHAobject *sha_info)
-{
- TestEndianness(sha_info->Endianness)
- sha_info->digest[0] = 0x6a09e667f3bcc908ULL;
- sha_info->digest[1] = 0xbb67ae8584caa73bULL;
- sha_info->digest[2] = 0x3c6ef372fe94f82bULL;
- sha_info->digest[3] = 0xa54ff53a5f1d36f1ULL;
- sha_info->digest[4] = 0x510e527fade682d1ULL;
- sha_info->digest[5] = 0x9b05688c2b3e6c1fULL;
- sha_info->digest[6] = 0x1f83d9abfb41bd6bULL;
- sha_info->digest[7] = 0x5be0cd19137e2179ULL;
- sha_info->count_lo = 0L;
- sha_info->count_hi = 0L;
- sha_info->local = 0;
- sha_info->digestsize = 64;
-}
-
-static void
-sha384_init(SHAobject *sha_info)
-{
- TestEndianness(sha_info->Endianness)
- sha_info->digest[0] = 0xcbbb9d5dc1059ed8ULL;
- sha_info->digest[1] = 0x629a292a367cd507ULL;
- sha_info->digest[2] = 0x9159015a3070dd17ULL;
- sha_info->digest[3] = 0x152fecd8f70e5939ULL;
- sha_info->digest[4] = 0x67332667ffc00b31ULL;
- sha_info->digest[5] = 0x8eb44a8768581511ULL;
- sha_info->digest[6] = 0xdb0c2e0d64f98fa7ULL;
- sha_info->digest[7] = 0x47b5481dbefa4fa4ULL;
- sha_info->count_lo = 0L;
- sha_info->count_hi = 0L;
- sha_info->local = 0;
- sha_info->digestsize = 48;
-}
-
-
-/* update the SHA digest */
-
-static void
-sha512_update(SHAobject *sha_info, SHA_BYTE *buffer, int count)
-{
- int i;
- SHA_INT32 clo;
-
- clo = sha_info->count_lo + ((SHA_INT32) count << 3);
- if (clo < sha_info->count_lo) {
- ++sha_info->count_hi;
- }
- sha_info->count_lo = clo;
- sha_info->count_hi += (SHA_INT32) count >> 29;
- if (sha_info->local) {
- i = SHA_BLOCKSIZE - sha_info->local;
- if (i > count) {
- i = count;
- }
- memcpy(((SHA_BYTE *) sha_info->data) + sha_info->local, buffer, i);
- count -= i;
- buffer += i;
- sha_info->local += i;
- if (sha_info->local == SHA_BLOCKSIZE) {
- sha512_transform(sha_info);
- }
- else {
- return;
- }
- }
- while (count >= SHA_BLOCKSIZE) {
- memcpy(sha_info->data, buffer, SHA_BLOCKSIZE);
- buffer += SHA_BLOCKSIZE;
- count -= SHA_BLOCKSIZE;
- sha512_transform(sha_info);
- }
- memcpy(sha_info->data, buffer, count);
- sha_info->local = count;
-}
-
-/* finish computing the SHA digest */
-
-static void
-sha512_final(unsigned char digest[SHA_DIGESTSIZE], SHAobject *sha_info)
-{
- int count;
- SHA_INT32 lo_bit_count, hi_bit_count;
-
- lo_bit_count = sha_info->count_lo;
- hi_bit_count = sha_info->count_hi;
- count = (int) ((lo_bit_count >> 3) & 0x7f);
- ((SHA_BYTE *) sha_info->data)[count++] = 0x80;
- if (count > SHA_BLOCKSIZE - 16) {
- memset(((SHA_BYTE *) sha_info->data) + count, 0,
- SHA_BLOCKSIZE - count);
- sha512_transform(sha_info);
- memset((SHA_BYTE *) sha_info->data, 0, SHA_BLOCKSIZE - 16);
- }
- else {
- memset(((SHA_BYTE *) sha_info->data) + count, 0,
- SHA_BLOCKSIZE - 16 - count);
- }
-
- /* GJS: note that we add the hi/lo in big-endian. sha512_transform will
- swap these values into host-order. */
- sha_info->data[112] = 0;
- sha_info->data[113] = 0;
- sha_info->data[114] = 0;
- sha_info->data[115] = 0;
- sha_info->data[116] = 0;
- sha_info->data[117] = 0;
- sha_info->data[118] = 0;
- sha_info->data[119] = 0;
- sha_info->data[120] = (hi_bit_count >> 24) & 0xff;
- sha_info->data[121] = (hi_bit_count >> 16) & 0xff;
- sha_info->data[122] = (hi_bit_count >> 8) & 0xff;
- sha_info->data[123] = (hi_bit_count >> 0) & 0xff;
- sha_info->data[124] = (lo_bit_count >> 24) & 0xff;
- sha_info->data[125] = (lo_bit_count >> 16) & 0xff;
- sha_info->data[126] = (lo_bit_count >> 8) & 0xff;
- sha_info->data[127] = (lo_bit_count >> 0) & 0xff;
- sha512_transform(sha_info);
- digest[ 0] = (unsigned char) ((sha_info->digest[0] >> 56) & 0xff);
- digest[ 1] = (unsigned char) ((sha_info->digest[0] >> 48) & 0xff);
- digest[ 2] = (unsigned char) ((sha_info->digest[0] >> 40) & 0xff);
- digest[ 3] = (unsigned char) ((sha_info->digest[0] >> 32) & 0xff);
- digest[ 4] = (unsigned char) ((sha_info->digest[0] >> 24) & 0xff);
- digest[ 5] = (unsigned char) ((sha_info->digest[0] >> 16) & 0xff);
- digest[ 6] = (unsigned char) ((sha_info->digest[0] >> 8) & 0xff);
- digest[ 7] = (unsigned char) ((sha_info->digest[0] ) & 0xff);
- digest[ 8] = (unsigned char) ((sha_info->digest[1] >> 56) & 0xff);
- digest[ 9] = (unsigned char) ((sha_info->digest[1] >> 48) & 0xff);
- digest[10] = (unsigned char) ((sha_info->digest[1] >> 40) & 0xff);
- digest[11] = (unsigned char) ((sha_info->digest[1] >> 32) & 0xff);
- digest[12] = (unsigned char) ((sha_info->digest[1] >> 24) & 0xff);
- digest[13] = (unsigned char) ((sha_info->digest[1] >> 16) & 0xff);
- digest[14] = (unsigned char) ((sha_info->digest[1] >> 8) & 0xff);
- digest[15] = (unsigned char) ((sha_info->digest[1] ) & 0xff);
- digest[16] = (unsigned char) ((sha_info->digest[2] >> 56) & 0xff);
- digest[17] = (unsigned char) ((sha_info->digest[2] >> 48) & 0xff);
- digest[18] = (unsigned char) ((sha_info->digest[2] >> 40) & 0xff);
- digest[19] = (unsigned char) ((sha_info->digest[2] >> 32) & 0xff);
- digest[20] = (unsigned char) ((sha_info->digest[2] >> 24) & 0xff);
- digest[21] = (unsigned char) ((sha_info->digest[2] >> 16) & 0xff);
- digest[22] = (unsigned char) ((sha_info->digest[2] >> 8) & 0xff);
- digest[23] = (unsigned char) ((sha_info->digest[2] ) & 0xff);
- digest[24] = (unsigned char) ((sha_info->digest[3] >> 56) & 0xff);
- digest[25] = (unsigned char) ((sha_info->digest[3] >> 48) & 0xff);
- digest[26] = (unsigned char) ((sha_info->digest[3] >> 40) & 0xff);
- digest[27] = (unsigned char) ((sha_info->digest[3] >> 32) & 0xff);
- digest[28] = (unsigned char) ((sha_info->digest[3] >> 24) & 0xff);
- digest[29] = (unsigned char) ((sha_info->digest[3] >> 16) & 0xff);
- digest[30] = (unsigned char) ((sha_info->digest[3] >> 8) & 0xff);
- digest[31] = (unsigned char) ((sha_info->digest[3] ) & 0xff);
- digest[32] = (unsigned char) ((sha_info->digest[4] >> 56) & 0xff);
- digest[33] = (unsigned char) ((sha_info->digest[4] >> 48) & 0xff);
- digest[34] = (unsigned char) ((sha_info->digest[4] >> 40) & 0xff);
- digest[35] = (unsigned char) ((sha_info->digest[4] >> 32) & 0xff);
- digest[36] = (unsigned char) ((sha_info->digest[4] >> 24) & 0xff);
- digest[37] = (unsigned char) ((sha_info->digest[4] >> 16) & 0xff);
- digest[38] = (unsigned char) ((sha_info->digest[4] >> 8) & 0xff);
- digest[39] = (unsigned char) ((sha_info->digest[4] ) & 0xff);
- digest[40] = (unsigned char) ((sha_info->digest[5] >> 56) & 0xff);
- digest[41] = (unsigned char) ((sha_info->digest[5] >> 48) & 0xff);
- digest[42] = (unsigned char) ((sha_info->digest[5] >> 40) & 0xff);
- digest[43] = (unsigned char) ((sha_info->digest[5] >> 32) & 0xff);
- digest[44] = (unsigned char) ((sha_info->digest[5] >> 24) & 0xff);
- digest[45] = (unsigned char) ((sha_info->digest[5] >> 16) & 0xff);
- digest[46] = (unsigned char) ((sha_info->digest[5] >> 8) & 0xff);
- digest[47] = (unsigned char) ((sha_info->digest[5] ) & 0xff);
- digest[48] = (unsigned char) ((sha_info->digest[6] >> 56) & 0xff);
- digest[49] = (unsigned char) ((sha_info->digest[6] >> 48) & 0xff);
- digest[50] = (unsigned char) ((sha_info->digest[6] >> 40) & 0xff);
- digest[51] = (unsigned char) ((sha_info->digest[6] >> 32) & 0xff);
- digest[52] = (unsigned char) ((sha_info->digest[6] >> 24) & 0xff);
- digest[53] = (unsigned char) ((sha_info->digest[6] >> 16) & 0xff);
- digest[54] = (unsigned char) ((sha_info->digest[6] >> 8) & 0xff);
- digest[55] = (unsigned char) ((sha_info->digest[6] ) & 0xff);
- digest[56] = (unsigned char) ((sha_info->digest[7] >> 56) & 0xff);
- digest[57] = (unsigned char) ((sha_info->digest[7] >> 48) & 0xff);
- digest[58] = (unsigned char) ((sha_info->digest[7] >> 40) & 0xff);
- digest[59] = (unsigned char) ((sha_info->digest[7] >> 32) & 0xff);
- digest[60] = (unsigned char) ((sha_info->digest[7] >> 24) & 0xff);
- digest[61] = (unsigned char) ((sha_info->digest[7] >> 16) & 0xff);
- digest[62] = (unsigned char) ((sha_info->digest[7] >> 8) & 0xff);
- digest[63] = (unsigned char) ((sha_info->digest[7] ) & 0xff);
-}
-
-/*
- * End of copied SHA code.
- *
- * ------------------------------------------------------------------------
- */
-
-static PyTypeObject SHA384type;
-static PyTypeObject SHA512type;
-
-
-static SHAobject *
-newSHA384object(void)
-{
- return (SHAobject *)PyObject_New(SHAobject, &SHA384type);
-}
-
-static SHAobject *
-newSHA512object(void)
-{
- return (SHAobject *)PyObject_New(SHAobject, &SHA512type);
-}
-
-/* Internal methods for a hash object */
-
-static void
-SHA512_dealloc(PyObject *ptr)
-{
- PyObject_Del(ptr);
-}
-
-
-/* External methods for a hash object */
-
-PyDoc_STRVAR(SHA512_copy__doc__, "Return a copy of the hash object.");
-
-static PyObject *
-SHA512_copy(SHAobject *self, PyObject *unused)
-{
- SHAobject *newobj;
-
- if (((PyObject*)self)->ob_type == &SHA512type) {
- if ( (newobj = newSHA512object())==NULL)
- return NULL;
- } else {
- if ( (newobj = newSHA384object())==NULL)
- return NULL;
- }
-
- SHAcopy(self, newobj);
- return (PyObject *)newobj;
-}
-
-PyDoc_STRVAR(SHA512_digest__doc__,
-"Return the digest value as a string of binary data.");
-
-static PyObject *
-SHA512_digest(SHAobject *self, PyObject *unused)
-{
- unsigned char digest[SHA_DIGESTSIZE];
- SHAobject temp;
-
- SHAcopy(self, &temp);
- sha512_final(digest, &temp);
- return PyString_FromStringAndSize((const char *)digest, self->digestsize);
-}
-
-PyDoc_STRVAR(SHA512_hexdigest__doc__,
-"Return the digest value as a string of hexadecimal digits.");
-
-static PyObject *
-SHA512_hexdigest(SHAobject *self, PyObject *unused)
-{
- unsigned char digest[SHA_DIGESTSIZE];
- SHAobject temp;
- PyObject *retval;
- char *hex_digest;
- int i, j;
-
- /* Get the raw (binary) digest value */
- SHAcopy(self, &temp);
- sha512_final(digest, &temp);
-
- /* Create a new string */
- retval = PyString_FromStringAndSize(NULL, self->digestsize * 2);
- if (!retval)
- return NULL;
- hex_digest = PyString_AsString(retval);
- if (!hex_digest) {
- Py_DECREF(retval);
- return NULL;
- }
-
- /* Make hex version of the digest */
- for (i=j=0; i<self->digestsize; i++) {
- char c;
- c = (digest[i] >> 4) & 0xf;
- c = (c>9) ? c+'a'-10 : c + '0';
- hex_digest[j++] = c;
- c = (digest[i] & 0xf);
- c = (c>9) ? c+'a'-10 : c + '0';
- hex_digest[j++] = c;
- }
- return retval;
-}
-
-PyDoc_STRVAR(SHA512_update__doc__,
-"Update this hash object's state with the provided string.");
-
-static PyObject *
-SHA512_update(SHAobject *self, PyObject *args)
-{
- unsigned char *cp;
- int len;
-
- if (!PyArg_ParseTuple(args, "s#:update", &cp, &len))
- return NULL;
-
- sha512_update(self, cp, len);
-
- Py_INCREF(Py_None);
- return Py_None;
-}
-
-static PyMethodDef SHA_methods[] = {
- {"copy", (PyCFunction)SHA512_copy, METH_NOARGS, SHA512_copy__doc__},
- {"digest", (PyCFunction)SHA512_digest, METH_NOARGS, SHA512_digest__doc__},
- {"hexdigest", (PyCFunction)SHA512_hexdigest, METH_NOARGS, SHA512_hexdigest__doc__},
- {"update", (PyCFunction)SHA512_update, METH_VARARGS, SHA512_update__doc__},
- {NULL, NULL} /* sentinel */
-};
-
-static PyObject *
-SHA512_get_block_size(PyObject *self, void *closure)
-{
- return PyInt_FromLong(SHA_BLOCKSIZE);
-}
-
-static PyObject *
-SHA512_get_name(PyObject *self, void *closure)
-{
- if (((SHAobject *)self)->digestsize == 64)
- return PyString_FromStringAndSize("SHA512", 6);
- else
- return PyString_FromStringAndSize("SHA384", 6);
-}
-
-static PyGetSetDef SHA_getseters[] = {
- {"block_size",
- (getter)SHA512_get_block_size, NULL,
- NULL,
- NULL},
- {"name",
- (getter)SHA512_get_name, NULL,
- NULL,
- NULL},
- {NULL} /* Sentinel */
-};
-
-static PyMemberDef SHA_members[] = {
- {"digest_size", T_INT, offsetof(SHAobject, digestsize), READONLY, NULL},
- /* the old md5 and sha modules support 'digest_size' as in PEP 247.
- * the old sha module also supported 'digestsize'. ugh. */
- {"digestsize", T_INT, offsetof(SHAobject, digestsize), READONLY, NULL},
- {NULL} /* Sentinel */
-};
-
-static PyTypeObject SHA384type = {
- PyObject_HEAD_INIT(NULL)
- 0, /*ob_size*/
- "_sha512.sha384", /*tp_name*/
- sizeof(SHAobject), /*tp_size*/
- 0, /*tp_itemsize*/
- /* methods */
- SHA512_dealloc, /*tp_dealloc*/
- 0, /*tp_print*/
- 0, /*tp_getattr*/
- 0, /*tp_setattr*/
- 0, /*tp_compare*/
- 0, /*tp_repr*/
- 0, /*tp_as_number*/
- 0, /*tp_as_sequence*/
- 0, /*tp_as_mapping*/
- 0, /*tp_hash*/
- 0, /*tp_call*/
- 0, /*tp_str*/
- 0, /*tp_getattro*/
- 0, /*tp_setattro*/
- 0, /*tp_as_buffer*/
- Py_TPFLAGS_DEFAULT, /*tp_flags*/
- 0, /*tp_doc*/
- 0, /*tp_traverse*/
- 0, /*tp_clear*/
- 0, /*tp_richcompare*/
- 0, /*tp_weaklistoffset*/
- 0, /*tp_iter*/
- 0, /*tp_iternext*/
- SHA_methods, /* tp_methods */
- SHA_members, /* tp_members */
- SHA_getseters, /* tp_getset */
-};
-
-static PyTypeObject SHA512type = {
- PyObject_HEAD_INIT(NULL)
- 0, /*ob_size*/
- "_sha512.sha512", /*tp_name*/
- sizeof(SHAobject), /*tp_size*/
- 0, /*tp_itemsize*/
- /* methods */
- SHA512_dealloc, /*tp_dealloc*/
- 0, /*tp_print*/
- 0, /*tp_getattr*/
- 0, /*tp_setattr*/
- 0, /*tp_compare*/
- 0, /*tp_repr*/
- 0, /*tp_as_number*/
- 0, /*tp_as_sequence*/
- 0, /*tp_as_mapping*/
- 0, /*tp_hash*/
- 0, /*tp_call*/
- 0, /*tp_str*/
- 0, /*tp_getattro*/
- 0, /*tp_setattro*/
- 0, /*tp_as_buffer*/
- Py_TPFLAGS_DEFAULT, /*tp_flags*/
- 0, /*tp_doc*/
- 0, /*tp_traverse*/
- 0, /*tp_clear*/
- 0, /*tp_richcompare*/
- 0, /*tp_weaklistoffset*/
- 0, /*tp_iter*/
- 0, /*tp_iternext*/
- SHA_methods, /* tp_methods */
- SHA_members, /* tp_members */
- SHA_getseters, /* tp_getset */
-};
-
-
-/* The single module-level function: new() */
-
-PyDoc_STRVAR(SHA512_new__doc__,
-"Return a new SHA-512 hash object; optionally initialized with a string.");
-
-static PyObject *
-SHA512_new(PyObject *self, PyObject *args, PyObject *kwdict)
-{
- static char *kwlist[] = {"string", NULL};
- SHAobject *new;
- unsigned char *cp = NULL;
- int len;
-
- if (!PyArg_ParseTupleAndKeywords(args, kwdict, "|s#:new", kwlist,
- &cp, &len)) {
- return NULL;
- }
-
- if ((new = newSHA512object()) == NULL)
- return NULL;
-
- sha512_init(new);
-
- if (PyErr_Occurred()) {
- Py_DECREF(new);
- return NULL;
- }
- if (cp)
- sha512_update(new, cp, len);
-
- return (PyObject *)new;
-}
-
-PyDoc_STRVAR(SHA384_new__doc__,
-"Return a new SHA-384 hash object; optionally initialized with a string.");
-
-static PyObject *
-SHA384_new(PyObject *self, PyObject *args, PyObject *kwdict)
-{
- static char *kwlist[] = {"string", NULL};
- SHAobject *new;
- unsigned char *cp = NULL;
- int len;
-
- if (!PyArg_ParseTupleAndKeywords(args, kwdict, "|s#:new", kwlist,
- &cp, &len)) {
- return NULL;
- }
-
- if ((new = newSHA384object()) == NULL)
- return NULL;
-
- sha384_init(new);
-
- if (PyErr_Occurred()) {
- Py_DECREF(new);
- return NULL;
- }
- if (cp)
- sha512_update(new, cp, len);
-
- return (PyObject *)new;
-}
-
-
-/* List of functions exported by this module */
-
-static struct PyMethodDef SHA_functions[] = {
- {"sha512", (PyCFunction)SHA512_new, METH_VARARGS|METH_KEYWORDS, SHA512_new__doc__},
- {"sha384", (PyCFunction)SHA384_new, METH_VARARGS|METH_KEYWORDS, SHA384_new__doc__},
- {NULL, NULL} /* Sentinel */
-};
-
-
-/* Initialize this module. */
-
-#define insint(n,v) { PyModule_AddIntConstant(m,n,v); }
-
-PyMODINIT_FUNC
-init_sha512(void)
-{
- PyObject *m;
-
- SHA384type.ob_type = &PyType_Type;
- if (PyType_Ready(&SHA384type) < 0)
- return;
- SHA512type.ob_type = &PyType_Type;
- if (PyType_Ready(&SHA512type) < 0)
- return;
- m = Py_InitModule("_sha512", SHA_functions);
- if (m == NULL)
- return;
-}
-
-#endif
diff --git a/src/distutils2/_backport/shamodule.c b/src/distutils2/_backport/shamodule.c
deleted file mode 100644
index 171dfa1..0000000
--- a/src/distutils2/_backport/shamodule.c
+++ /dev/null
@@ -1,593 +0,0 @@
-/* SHA module */
-
-/* This module provides an interface to NIST's Secure Hash Algorithm */
-
-/* See below for information about the original code this module was
- based upon. Additional work performed by:
-
- Andrew Kuchling (amk@amk.ca)
- Greg Stein (gstein@lyra.org)
-
- Copyright (C) 2005 Gregory P. Smith (greg@krypto.org)
- Licensed to PSF under a Contributor Agreement.
-
-*/
-
-/* SHA objects */
-
-#include "Python.h"
-#include "structmember.h"
-
-
-/* Endianness testing and definitions */
-#define TestEndianness(variable) {int i=1; variable=PCT_BIG_ENDIAN;\
- if (*((char*)&i)==1) variable=PCT_LITTLE_ENDIAN;}
-
-#define PCT_LITTLE_ENDIAN 1
-#define PCT_BIG_ENDIAN 0
-
-/* Some useful types */
-
-typedef unsigned char SHA_BYTE;
-
-#if SIZEOF_INT == 4
-typedef unsigned int SHA_INT32; /* 32-bit integer */
-#else
-/* not defined. compilation will die. */
-#endif
-
-/* The SHA block size and message digest sizes, in bytes */
-
-#define SHA_BLOCKSIZE 64
-#define SHA_DIGESTSIZE 20
-
-/* The structure for storing SHS info */
-
-typedef struct {
- PyObject_HEAD
- SHA_INT32 digest[5]; /* Message digest */
- SHA_INT32 count_lo, count_hi; /* 64-bit bit count */
- SHA_BYTE data[SHA_BLOCKSIZE]; /* SHA data buffer */
- int Endianness;
- int local; /* unprocessed amount in data */
-} SHAobject;
-
-/* When run on a little-endian CPU we need to perform byte reversal on an
- array of longwords. */
-
-static void longReverse(SHA_INT32 *buffer, int byteCount, int Endianness)
-{
- SHA_INT32 value;
-
- if ( Endianness == PCT_BIG_ENDIAN )
- return;
-
- byteCount /= sizeof(*buffer);
- while (byteCount--) {
- value = *buffer;
- value = ( ( value & 0xFF00FF00L ) >> 8 ) | \
- ( ( value & 0x00FF00FFL ) << 8 );
- *buffer++ = ( value << 16 ) | ( value >> 16 );
- }
-}
-
-static void SHAcopy(SHAobject *src, SHAobject *dest)
-{
- dest->Endianness = src->Endianness;
- dest->local = src->local;
- dest->count_lo = src->count_lo;
- dest->count_hi = src->count_hi;
- memcpy(dest->digest, src->digest, sizeof(src->digest));
- memcpy(dest->data, src->data, sizeof(src->data));
-}
-
-
-/* ------------------------------------------------------------------------
- *
- * This code for the SHA algorithm was noted as public domain. The original
- * headers are pasted below.
- *
- * Several changes have been made to make it more compatible with the
- * Python environment and desired interface.
- *
- */
-
-/* NIST Secure Hash Algorithm */
-/* heavily modified by Uwe Hollerbach <uh@alumni.caltech edu> */
-/* from Peter C. Gutmann's implementation as found in */
-/* Applied Cryptography by Bruce Schneier */
-/* Further modifications to include the "UNRAVEL" stuff, below */
-
-/* This code is in the public domain */
-
-/* UNRAVEL should be fastest & biggest */
-/* UNROLL_LOOPS should be just as big, but slightly slower */
-/* both undefined should be smallest and slowest */
-
-#define UNRAVEL
-/* #define UNROLL_LOOPS */
-
-/* The SHA f()-functions. The f1 and f3 functions can be optimized to
- save one boolean operation each - thanks to Rich Schroeppel,
- rcs@cs.arizona.edu for discovering this */
-
-/*#define f1(x,y,z) ((x & y) | (~x & z)) // Rounds 0-19 */
-#define f1(x,y,z) (z ^ (x & (y ^ z))) /* Rounds 0-19 */
-#define f2(x,y,z) (x ^ y ^ z) /* Rounds 20-39 */
-/*#define f3(x,y,z) ((x & y) | (x & z) | (y & z)) // Rounds 40-59 */
-#define f3(x,y,z) ((x & y) | (z & (x | y))) /* Rounds 40-59 */
-#define f4(x,y,z) (x ^ y ^ z) /* Rounds 60-79 */
-
-/* SHA constants */
-
-#define CONST1 0x5a827999L /* Rounds 0-19 */
-#define CONST2 0x6ed9eba1L /* Rounds 20-39 */
-#define CONST3 0x8f1bbcdcL /* Rounds 40-59 */
-#define CONST4 0xca62c1d6L /* Rounds 60-79 */
-
-/* 32-bit rotate */
-
-#define R32(x,n) ((x << n) | (x >> (32 - n)))
-
-/* the generic case, for when the overall rotation is not unraveled */
-
-#define FG(n) \
- T = R32(A,5) + f##n(B,C,D) + E + *WP++ + CONST##n; \
- E = D; D = C; C = R32(B,30); B = A; A = T
-
-/* specific cases, for when the overall rotation is unraveled */
-
-#define FA(n) \
- T = R32(A,5) + f##n(B,C,D) + E + *WP++ + CONST##n; B = R32(B,30)
-
-#define FB(n) \
- E = R32(T,5) + f##n(A,B,C) + D + *WP++ + CONST##n; A = R32(A,30)
-
-#define FC(n) \
- D = R32(E,5) + f##n(T,A,B) + C + *WP++ + CONST##n; T = R32(T,30)
-
-#define FD(n) \
- C = R32(D,5) + f##n(E,T,A) + B + *WP++ + CONST##n; E = R32(E,30)
-
-#define FE(n) \
- B = R32(C,5) + f##n(D,E,T) + A + *WP++ + CONST##n; D = R32(D,30)
-
-#define FT(n) \
- A = R32(B,5) + f##n(C,D,E) + T + *WP++ + CONST##n; C = R32(C,30)
-
-/* do SHA transformation */
-
-static void
-sha_transform(SHAobject *sha_info)
-{
- int i;
- SHA_INT32 T, A, B, C, D, E, W[80], *WP;
-
- memcpy(W, sha_info->data, sizeof(sha_info->data));
- longReverse(W, (int)sizeof(sha_info->data), sha_info->Endianness);
-
- for (i = 16; i < 80; ++i) {
- W[i] = W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16];
-
- /* extra rotation fix */
- W[i] = R32(W[i], 1);
- }
- A = sha_info->digest[0];
- B = sha_info->digest[1];
- C = sha_info->digest[2];
- D = sha_info->digest[3];
- E = sha_info->digest[4];
- WP = W;
-#ifdef UNRAVEL
- FA(1); FB(1); FC(1); FD(1); FE(1); FT(1); FA(1); FB(1); FC(1); FD(1);
- FE(1); FT(1); FA(1); FB(1); FC(1); FD(1); FE(1); FT(1); FA(1); FB(1);
- FC(2); FD(2); FE(2); FT(2); FA(2); FB(2); FC(2); FD(2); FE(2); FT(2);
- FA(2); FB(2); FC(2); FD(2); FE(2); FT(2); FA(2); FB(2); FC(2); FD(2);
- FE(3); FT(3); FA(3); FB(3); FC(3); FD(3); FE(3); FT(3); FA(3); FB(3);
- FC(3); FD(3); FE(3); FT(3); FA(3); FB(3); FC(3); FD(3); FE(3); FT(3);
- FA(4); FB(4); FC(4); FD(4); FE(4); FT(4); FA(4); FB(4); FC(4); FD(4);
- FE(4); FT(4); FA(4); FB(4); FC(4); FD(4); FE(4); FT(4); FA(4); FB(4);
- sha_info->digest[0] += E;
- sha_info->digest[1] += T;
- sha_info->digest[2] += A;
- sha_info->digest[3] += B;
- sha_info->digest[4] += C;
-#else /* !UNRAVEL */
-#ifdef UNROLL_LOOPS
- FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1);
- FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1);
- FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2);
- FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2);
- FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3);
- FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3);
- FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4);
- FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4);
-#else /* !UNROLL_LOOPS */
- for (i = 0; i < 20; ++i) { FG(1); }
- for (i = 20; i < 40; ++i) { FG(2); }
- for (i = 40; i < 60; ++i) { FG(3); }
- for (i = 60; i < 80; ++i) { FG(4); }
-#endif /* !UNROLL_LOOPS */
- sha_info->digest[0] += A;
- sha_info->digest[1] += B;
- sha_info->digest[2] += C;
- sha_info->digest[3] += D;
- sha_info->digest[4] += E;
-#endif /* !UNRAVEL */
-}
-
-/* initialize the SHA digest */
-
-static void
-sha_init(SHAobject *sha_info)
-{
- TestEndianness(sha_info->Endianness)
-
- sha_info->digest[0] = 0x67452301L;
- sha_info->digest[1] = 0xefcdab89L;
- sha_info->digest[2] = 0x98badcfeL;
- sha_info->digest[3] = 0x10325476L;
- sha_info->digest[4] = 0xc3d2e1f0L;
- sha_info->count_lo = 0L;
- sha_info->count_hi = 0L;
- sha_info->local = 0;
-}
-
-/* update the SHA digest */
-
-static void
-sha_update(SHAobject *sha_info, SHA_BYTE *buffer, int count)
-{
- int i;
- SHA_INT32 clo;
-
- clo = sha_info->count_lo + ((SHA_INT32) count << 3);
- if (clo < sha_info->count_lo) {
- ++sha_info->count_hi;
- }
- sha_info->count_lo = clo;
- sha_info->count_hi += (SHA_INT32) count >> 29;
- if (sha_info->local) {
- i = SHA_BLOCKSIZE - sha_info->local;
- if (i > count) {
- i = count;
- }
- memcpy(((SHA_BYTE *) sha_info->data) + sha_info->local, buffer, i);
- count -= i;
- buffer += i;
- sha_info->local += i;
- if (sha_info->local == SHA_BLOCKSIZE) {
- sha_transform(sha_info);
- }
- else {
- return;
- }
- }
- while (count >= SHA_BLOCKSIZE) {
- memcpy(sha_info->data, buffer, SHA_BLOCKSIZE);
- buffer += SHA_BLOCKSIZE;
- count -= SHA_BLOCKSIZE;
- sha_transform(sha_info);
- }
- memcpy(sha_info->data, buffer, count);
- sha_info->local = count;
-}
-
-/* finish computing the SHA digest */
-
-static void
-sha_final(unsigned char digest[20], SHAobject *sha_info)
-{
- int count;
- SHA_INT32 lo_bit_count, hi_bit_count;
-
- lo_bit_count = sha_info->count_lo;
- hi_bit_count = sha_info->count_hi;
- count = (int) ((lo_bit_count >> 3) & 0x3f);
- ((SHA_BYTE *) sha_info->data)[count++] = 0x80;
- if (count > SHA_BLOCKSIZE - 8) {
- memset(((SHA_BYTE *) sha_info->data) + count, 0,
- SHA_BLOCKSIZE - count);
- sha_transform(sha_info);
- memset((SHA_BYTE *) sha_info->data, 0, SHA_BLOCKSIZE - 8);
- }
- else {
- memset(((SHA_BYTE *) sha_info->data) + count, 0,
- SHA_BLOCKSIZE - 8 - count);
- }
-
- /* GJS: note that we add the hi/lo in big-endian. sha_transform will
- swap these values into host-order. */
- sha_info->data[56] = (hi_bit_count >> 24) & 0xff;
- sha_info->data[57] = (hi_bit_count >> 16) & 0xff;
- sha_info->data[58] = (hi_bit_count >> 8) & 0xff;
- sha_info->data[59] = (hi_bit_count >> 0) & 0xff;
- sha_info->data[60] = (lo_bit_count >> 24) & 0xff;
- sha_info->data[61] = (lo_bit_count >> 16) & 0xff;
- sha_info->data[62] = (lo_bit_count >> 8) & 0xff;
- sha_info->data[63] = (lo_bit_count >> 0) & 0xff;
- sha_transform(sha_info);
- digest[ 0] = (unsigned char) ((sha_info->digest[0] >> 24) & 0xff);
- digest[ 1] = (unsigned char) ((sha_info->digest[0] >> 16) & 0xff);
- digest[ 2] = (unsigned char) ((sha_info->digest[0] >> 8) & 0xff);
- digest[ 3] = (unsigned char) ((sha_info->digest[0] ) & 0xff);
- digest[ 4] = (unsigned char) ((sha_info->digest[1] >> 24) & 0xff);
- digest[ 5] = (unsigned char) ((sha_info->digest[1] >> 16) & 0xff);
- digest[ 6] = (unsigned char) ((sha_info->digest[1] >> 8) & 0xff);
- digest[ 7] = (unsigned char) ((sha_info->digest[1] ) & 0xff);
- digest[ 8] = (unsigned char) ((sha_info->digest[2] >> 24) & 0xff);
- digest[ 9] = (unsigned char) ((sha_info->digest[2] >> 16) & 0xff);
- digest[10] = (unsigned char) ((sha_info->digest[2] >> 8) & 0xff);
- digest[11] = (unsigned char) ((sha_info->digest[2] ) & 0xff);
- digest[12] = (unsigned char) ((sha_info->digest[3] >> 24) & 0xff);
- digest[13] = (unsigned char) ((sha_info->digest[3] >> 16) & 0xff);
- digest[14] = (unsigned char) ((sha_info->digest[3] >> 8) & 0xff);
- digest[15] = (unsigned char) ((sha_info->digest[3] ) & 0xff);
- digest[16] = (unsigned char) ((sha_info->digest[4] >> 24) & 0xff);
- digest[17] = (unsigned char) ((sha_info->digest[4] >> 16) & 0xff);
- digest[18] = (unsigned char) ((sha_info->digest[4] >> 8) & 0xff);
- digest[19] = (unsigned char) ((sha_info->digest[4] ) & 0xff);
-}
-
-/*
- * End of copied SHA code.
- *
- * ------------------------------------------------------------------------
- */
-
-static PyTypeObject SHAtype;
-
-
-static SHAobject *
-newSHAobject(void)
-{
- return (SHAobject *)PyObject_New(SHAobject, &SHAtype);
-}
-
-/* Internal methods for a hashing object */
-
-static void
-SHA_dealloc(PyObject *ptr)
-{
- PyObject_Del(ptr);
-}
-
-
-/* External methods for a hashing object */
-
-PyDoc_STRVAR(SHA_copy__doc__, "Return a copy of the hashing object.");
-
-static PyObject *
-SHA_copy(SHAobject *self, PyObject *unused)
-{
- SHAobject *newobj;
-
- if ( (newobj = newSHAobject())==NULL)
- return NULL;
-
- SHAcopy(self, newobj);
- return (PyObject *)newobj;
-}
-
-PyDoc_STRVAR(SHA_digest__doc__,
-"Return the digest value as a string of binary data.");
-
-static PyObject *
-SHA_digest(SHAobject *self, PyObject *unused)
-{
- unsigned char digest[SHA_DIGESTSIZE];
- SHAobject temp;
-
- SHAcopy(self, &temp);
- sha_final(digest, &temp);
- return PyString_FromStringAndSize((const char *)digest, sizeof(digest));
-}
-
-PyDoc_STRVAR(SHA_hexdigest__doc__,
-"Return the digest value as a string of hexadecimal digits.");
-
-static PyObject *
-SHA_hexdigest(SHAobject *self, PyObject *unused)
-{
- unsigned char digest[SHA_DIGESTSIZE];
- SHAobject temp;
- PyObject *retval;
- char *hex_digest;
- int i, j;
-
- /* Get the raw (binary) digest value */
- SHAcopy(self, &temp);
- sha_final(digest, &temp);
-
- /* Create a new string */
- retval = PyString_FromStringAndSize(NULL, sizeof(digest) * 2);
- if (!retval)
- return NULL;
- hex_digest = PyString_AsString(retval);
- if (!hex_digest) {
- Py_DECREF(retval);
- return NULL;
- }
-
- /* Make hex version of the digest */
- for(i=j=0; i<sizeof(digest); i++) {
- char c;
- c = (digest[i] >> 4) & 0xf;
- c = (c>9) ? c+'a'-10 : c + '0';
- hex_digest[j++] = c;
- c = (digest[i] & 0xf);
- c = (c>9) ? c+'a'-10 : c + '0';
- hex_digest[j++] = c;
- }
- return retval;
-}
-
-PyDoc_STRVAR(SHA_update__doc__,
-"Update this hashing object's state with the provided string.");
-
-static PyObject *
-SHA_update(SHAobject *self, PyObject *args)
-{
- unsigned char *cp;
- int len;
-
- if (!PyArg_ParseTuple(args, "s#:update", &cp, &len))
- return NULL;
-
- sha_update(self, cp, len);
-
- Py_INCREF(Py_None);
- return Py_None;
-}
-
-static PyMethodDef SHA_methods[] = {
- {"copy", (PyCFunction)SHA_copy, METH_NOARGS, SHA_copy__doc__},
- {"digest", (PyCFunction)SHA_digest, METH_NOARGS, SHA_digest__doc__},
- {"hexdigest", (PyCFunction)SHA_hexdigest, METH_NOARGS, SHA_hexdigest__doc__},
- {"update", (PyCFunction)SHA_update, METH_VARARGS, SHA_update__doc__},
- {NULL, NULL} /* sentinel */
-};
-
-static PyObject *
-SHA_get_block_size(PyObject *self, void *closure)
-{
- return PyInt_FromLong(SHA_BLOCKSIZE);
-}
-
-static PyObject *
-SHA_get_digest_size(PyObject *self, void *closure)
-{
- return PyInt_FromLong(SHA_DIGESTSIZE);
-}
-
-static PyObject *
-SHA_get_name(PyObject *self, void *closure)
-{
- return PyString_FromStringAndSize("SHA1", 4);
-}
-
-static PyGetSetDef SHA_getseters[] = {
- {"digest_size",
- (getter)SHA_get_digest_size, NULL,
- NULL,
- NULL},
- {"block_size",
- (getter)SHA_get_block_size, NULL,
- NULL,
- NULL},
- {"name",
- (getter)SHA_get_name, NULL,
- NULL,
- NULL},
- /* the old md5 and sha modules support 'digest_size' as in PEP 247.
- * the old sha module also supported 'digestsize'. ugh. */
- {"digestsize",
- (getter)SHA_get_digest_size, NULL,
- NULL,
- NULL},
- {NULL} /* Sentinel */
-};
-
-static PyTypeObject SHAtype = {
- PyObject_HEAD_INIT(NULL)
- 0, /*ob_size*/
- "_sha.sha", /*tp_name*/
- sizeof(SHAobject), /*tp_size*/
- 0, /*tp_itemsize*/
- /* methods */
- SHA_dealloc, /*tp_dealloc*/
- 0, /*tp_print*/
- 0, /*tp_getattr*/
- 0, /*tp_setattr*/
- 0, /*tp_compare*/
- 0, /*tp_repr*/
- 0, /*tp_as_number*/
- 0, /*tp_as_sequence*/
- 0, /*tp_as_mapping*/
- 0, /*tp_hash*/
- 0, /*tp_call*/
- 0, /*tp_str*/
- 0, /*tp_getattro*/
- 0, /*tp_setattro*/
- 0, /*tp_as_buffer*/
- Py_TPFLAGS_DEFAULT, /*tp_flags*/
- 0, /*tp_doc*/
- 0, /*tp_traverse*/
- 0, /*tp_clear*/
- 0, /*tp_richcompare*/
- 0, /*tp_weaklistoffset*/
- 0, /*tp_iter*/
- 0, /*tp_iternext*/
- SHA_methods, /* tp_methods */
- 0, /* tp_members */
- SHA_getseters, /* tp_getset */
-};
-
-
-/* The single module-level function: new() */
-
-PyDoc_STRVAR(SHA_new__doc__,
-"Return a new SHA hashing object. An optional string argument\n\
-may be provided; if present, this string will be automatically\n\
-hashed.");
-
-static PyObject *
-SHA_new(PyObject *self, PyObject *args, PyObject *kwdict)
-{
- static char *kwlist[] = {"string", NULL};
- SHAobject *new;
- unsigned char *cp = NULL;
- int len;
-
- if (!PyArg_ParseTupleAndKeywords(args, kwdict, "|s#:new", kwlist,
- &cp, &len)) {
- return NULL;
- }
-
- if ((new = newSHAobject()) == NULL)
- return NULL;
-
- sha_init(new);
-
- if (PyErr_Occurred()) {
- Py_DECREF(new);
- return NULL;
- }
- if (cp)
- sha_update(new, cp, len);
-
- return (PyObject *)new;
-}
-
-
-/* List of functions exported by this module */
-
-static struct PyMethodDef SHA_functions[] = {
- {"new", (PyCFunction)SHA_new, METH_VARARGS|METH_KEYWORDS, SHA_new__doc__},
- {NULL, NULL} /* Sentinel */
-};
-
-
-/* Initialize this module. */
-
-#define insint(n,v) { PyModule_AddIntConstant(m,n,v); }
-
-PyMODINIT_FUNC
-init_sha(void)
-{
- PyObject *m;
-
- SHAtype.ob_type = &PyType_Type;
- if (PyType_Ready(&SHAtype) < 0)
- return;
- m = Py_InitModule("_sha", SHA_functions);
- if (m == NULL)
- return;
-
- /* Add some symbolic constants to the module */
- insint("blocksize", 1); /* For future use, in case some hash
- functions require an integral number of
- blocks */
- insint("digestsize", 20);
- insint("digest_size", 20);
-}
diff --git a/src/distutils2/_backport/shutil.py b/src/distutils2/_backport/shutil.py
deleted file mode 100644
index b9e6a77..0000000
--- a/src/distutils2/_backport/shutil.py
+++ /dev/null
@@ -1,570 +0,0 @@
-"""Utility functions for copying files and directory trees.
-
-XXX The functions here don't copy the resource fork or other metadata on Mac.
-
-"""
-
-import os
-import sys
-import stat
-from os.path import abspath
-import fnmatch
-from warnings import warn
-
-try:
- from pwd import getpwnam
-except ImportError:
- getpwnam = None
-
-try:
- from grp import getgrnam
-except ImportError:
- getgrnam = None
-
-__all__ = ["copyfileobj","copyfile","copymode","copystat","copy","copy2",
- "copytree","move","rmtree","Error", "SpecialFileError",
- "ExecError","make_archive"]
-
-class Error(EnvironmentError):
- pass
-
-class SpecialFileError(EnvironmentError):
- """Raised when trying to do a kind of operation (e.g. copying) which is
- not supported on a special file (e.g. a named pipe)"""
-
-class ExecError(EnvironmentError):
- """Raised when a command could not be executed"""
-
-try:
- WindowsError
-except NameError:
- WindowsError = None
-
-def copyfileobj(fsrc, fdst, length=16*1024):
- """copy data from file-like object fsrc to file-like object fdst"""
- while 1:
- buf = fsrc.read(length)
- if not buf:
- break
- fdst.write(buf)
-
-def _samefile(src, dst):
- # Macintosh, Unix.
- if hasattr(os.path,'samefile'):
- try:
- return os.path.samefile(src, dst)
- except OSError:
- return False
-
- # All other platforms: check for same pathname.
- return (os.path.normcase(os.path.abspath(src)) ==
- os.path.normcase(os.path.abspath(dst)))
-
-def copyfile(src, dst):
- """Copy data from src to dst"""
- if _samefile(src, dst):
- raise Error, "`%s` and `%s` are the same file" % (src, dst)
-
- fsrc = None
- fdst = None
- for fn in [src, dst]:
- try:
- st = os.stat(fn)
- except OSError:
- # File most likely does not exist
- pass
- else:
- # XXX What about other special files? (sockets, devices...)
- if stat.S_ISFIFO(st.st_mode):
- raise SpecialFileError("`%s` is a named pipe" % fn)
- try:
- fsrc = open(src, 'rb')
- fdst = open(dst, 'wb')
- copyfileobj(fsrc, fdst)
- finally:
- if fdst:
- fdst.close()
- if fsrc:
- fsrc.close()
-
-def copymode(src, dst):
- """Copy mode bits from src to dst"""
- if hasattr(os, 'chmod'):
- st = os.stat(src)
- mode = stat.S_IMODE(st.st_mode)
- os.chmod(dst, mode)
-
-def copystat(src, dst):
- """Copy all stat info (mode bits, atime, mtime, flags) from src to dst"""
- st = os.stat(src)
- mode = stat.S_IMODE(st.st_mode)
- if hasattr(os, 'utime'):
- os.utime(dst, (st.st_atime, st.st_mtime))
- if hasattr(os, 'chmod'):
- os.chmod(dst, mode)
- if hasattr(os, 'chflags') and hasattr(st, 'st_flags'):
- os.chflags(dst, st.st_flags)
-
-
-def copy(src, dst):
- """Copy data and mode bits ("cp src dst").
-
- The destination may be a directory.
-
- """
- if os.path.isdir(dst):
- dst = os.path.join(dst, os.path.basename(src))
- copyfile(src, dst)
- copymode(src, dst)
-
-def copy2(src, dst):
- """Copy data and all stat info ("cp -p src dst").
-
- The destination may be a directory.
-
- """
- if os.path.isdir(dst):
- dst = os.path.join(dst, os.path.basename(src))
- copyfile(src, dst)
- copystat(src, dst)
-
-def ignore_patterns(*patterns):
- """Function that can be used as copytree() ignore parameter.
-
- Patterns is a sequence of glob-style patterns
- that are used to exclude files"""
- def _ignore_patterns(path, names):
- ignored_names = []
- for pattern in patterns:
- ignored_names.extend(fnmatch.filter(names, pattern))
- return set(ignored_names)
- return _ignore_patterns
-
-def copytree(src, dst, symlinks=False, ignore=None):
- """Recursively copy a directory tree using copy2().
-
- The destination directory must not already exist.
- If exception(s) occur, an Error is raised with a list of reasons.
-
- If the optional symlinks flag is true, symbolic links in the
- source tree result in symbolic links in the destination tree; if
- it is false, the contents of the files pointed to by symbolic
- links are copied.
-
- The optional ignore argument is a callable. If given, it
- is called with the `src` parameter, which is the directory
- being visited by copytree(), and `names` which is the list of
- `src` contents, as returned by os.listdir():
-
- callable(src, names) -> ignored_names
-
- Since copytree() is called recursively, the callable will be
- called once for each directory that is copied. It returns a
- list of names relative to the `src` directory that should
- not be copied.
-
- XXX Consider this example code rather than the ultimate tool.
-
- """
- names = os.listdir(src)
- if ignore is not None:
- ignored_names = ignore(src, names)
- else:
- ignored_names = set()
-
- if not os.path.exists(dst):
- os.makedirs(dst)
-
- errors = []
- for name in names:
- if name in ignored_names:
- continue
- srcname = os.path.join(src, name)
- dstname = os.path.join(dst, name)
- try:
- if symlinks and os.path.islink(srcname):
- linkto = os.readlink(srcname)
- os.symlink(linkto, dstname)
- elif os.path.isdir(srcname):
- copytree(srcname, dstname, symlinks, ignore)
- else:
- # Will raise a SpecialFileError for unsupported file types
- copy2(srcname, dstname)
- # catch the Error from the recursive copytree so that we can
- # continue with other files
- except Error, err:
- errors.extend(err.args[0])
- except EnvironmentError, why:
- errors.append((srcname, dstname, str(why)))
- try:
- copystat(src, dst)
- except OSError, why:
- if WindowsError is not None and isinstance(why, WindowsError):
- # Copying file access times may fail on Windows
- pass
- else:
- errors.extend((src, dst, str(why)))
- if errors:
- raise Error, errors
-
-def rmtree(path, ignore_errors=False, onerror=None):
- """Recursively delete a directory tree.
-
- If ignore_errors is set, errors are ignored; otherwise, if onerror
- is set, it is called to handle the error with arguments (func,
- path, exc_info) where func is os.listdir, os.remove, or os.rmdir;
- path is the argument to that function that caused it to fail; and
- exc_info is a tuple returned by sys.exc_info(). If ignore_errors
- is false and onerror is None, an exception is raised.
-
- """
- if ignore_errors:
- def onerror(*args):
- pass
- elif onerror is None:
- def onerror(*args):
- raise
- try:
- if os.path.islink(path):
- # symlinks to directories are forbidden, see bug #1669
- raise OSError("Cannot call rmtree on a symbolic link")
- except OSError:
- onerror(os.path.islink, path, sys.exc_info())
- # can't continue even if onerror hook returns
- return
- names = []
- try:
- names = os.listdir(path)
- except os.error, err:
- onerror(os.listdir, path, sys.exc_info())
- for name in names:
- fullname = os.path.join(path, name)
- try:
- mode = os.lstat(fullname).st_mode
- except os.error:
- mode = 0
- if stat.S_ISDIR(mode):
- rmtree(fullname, ignore_errors, onerror)
- else:
- try:
- os.remove(fullname)
- except os.error, err:
- onerror(os.remove, fullname, sys.exc_info())
- try:
- os.rmdir(path)
- except os.error:
- onerror(os.rmdir, path, sys.exc_info())
-
-
-def _basename(path):
- # A basename() variant which first strips the trailing slash, if present.
- # Thus we always get the last component of the path, even for directories.
- return os.path.basename(path.rstrip(os.path.sep))
-
-def move(src, dst):
- """Recursively move a file or directory to another location. This is
- similar to the Unix "mv" command.
-
- If the destination is a directory or a symlink to a directory, the source
- is moved inside the directory. The destination path must not already
- exist.
-
- If the destination already exists but is not a directory, it may be
- overwritten depending on os.rename() semantics.
-
- If the destination is on our current filesystem, then rename() is used.
- Otherwise, src is copied to the destination and then removed.
- A lot more could be done here... A look at a mv.c shows a lot of
- the issues this implementation glosses over.
-
- """
- real_dst = dst
- if os.path.isdir(dst):
- real_dst = os.path.join(dst, _basename(src))
- if os.path.exists(real_dst):
- raise Error, "Destination path '%s' already exists" % real_dst
- try:
- os.rename(src, real_dst)
- except OSError:
- if os.path.isdir(src):
- if _destinsrc(src, dst):
- raise Error, "Cannot move a directory '%s' into itself '%s'." % (src, dst)
- copytree(src, real_dst, symlinks=True)
- rmtree(src)
- else:
- copy2(src, real_dst)
- os.unlink(src)
-
-def _destinsrc(src, dst):
- src = abspath(src)
- dst = abspath(dst)
- if not src.endswith(os.path.sep):
- src += os.path.sep
- if not dst.endswith(os.path.sep):
- dst += os.path.sep
- return dst.startswith(src)
-
-def _get_gid(name):
- """Returns a gid, given a group name."""
- if getgrnam is None or name is None:
- return None
- try:
- result = getgrnam(name)
- except KeyError:
- result = None
- if result is not None:
- return result[2]
- return None
-
-def _get_uid(name):
- """Returns an uid, given a user name."""
- if getpwnam is None or name is None:
- return None
- try:
- result = getpwnam(name)
- except KeyError:
- result = None
- if result is not None:
- return result[2]
- return None
-
-def _make_tarball(base_name, base_dir, compress="gzip", verbose=0, dry_run=0,
- owner=None, group=None, logger=None):
- """Create a (possibly compressed) tar file from all the files under
- 'base_dir'.
-
- 'compress' must be "gzip" (the default), "compress", "bzip2", or None.
- (compress will be deprecated in Python 3.2)
-
- 'owner' and 'group' can be used to define an owner and a group for the
- archive that is being built. If not provided, the current owner and group
- will be used.
-
- The output tar file will be named 'base_dir' + ".tar", possibly plus
- the appropriate compression extension (".gz", ".bz2" or ".Z").
-
- Returns the output filename.
- """
- tar_compression = {'gzip': 'gz', 'bzip2': 'bz2', None: '', 'compress': ''}
- compress_ext = {'gzip': '.gz', 'bzip2': '.bz2', 'compress': '.Z'}
-
- # flags for compression program, each element of list will be an argument
- if compress is not None and compress not in compress_ext.keys():
- raise ValueError, \
- ("bad value for 'compress': must be None, 'gzip', 'bzip2' "
- "or 'compress'")
-
- archive_name = base_name + '.tar'
- if compress != 'compress':
- archive_name += compress_ext.get(compress, '')
-
- archive_dir = os.path.dirname(archive_name)
- if not os.path.exists(archive_dir):
- if logger is not None:
- logger.info("creating %s" % archive_dir)
- if not dry_run:
- os.makedirs(archive_dir)
-
-
- # creating the tarball
- from distutils2._backport import tarfile
-
- if logger is not None:
- logger.info('Creating tar archive')
-
- uid = _get_uid(owner)
- gid = _get_gid(group)
-
- def _set_uid_gid(tarinfo):
- if gid is not None:
- tarinfo.gid = gid
- tarinfo.gname = group
- if uid is not None:
- tarinfo.uid = uid
- tarinfo.uname = owner
- return tarinfo
-
- if not dry_run:
- tar = tarfile.open(archive_name, 'w|%s' % tar_compression[compress])
- try:
- tar.add(base_dir, filter=_set_uid_gid)
- finally:
- tar.close()
-
- # compression using `compress`
- # XXX this block will be removed in Python 3.2
- if compress == 'compress':
- warn("'compress' will be deprecated.", PendingDeprecationWarning)
- # the option varies depending on the platform
- compressed_name = archive_name + compress_ext[compress]
- if sys.platform == 'win32':
- cmd = [compress, archive_name, compressed_name]
- else:
- cmd = [compress, '-f', archive_name]
- from distutils2.spawn import spawn
- spawn(cmd, dry_run=dry_run)
- return compressed_name
-
- return archive_name
-
-def _call_external_zip(directory, verbose=False):
- # XXX see if we want to keep an external call here
- if verbose:
- zipoptions = "-r"
- else:
- zipoptions = "-rq"
- from distutils2.errors import DistutilsExecError
- from distutils2.spawn import spawn
- try:
- spawn(["zip", zipoptions, zip_filename, base_dir], dry_run=dry_run)
- except DistutilsExecError:
- # XXX really should distinguish between "couldn't find
- # external 'zip' command" and "zip failed".
- raise ExecError, \
- ("unable to create zip file '%s': "
- "could neither import the 'zipfile' module nor "
- "find a standalone zip utility") % zip_filename
-
-def _make_zipfile(base_name, base_dir, verbose=0, dry_run=0, logger=None):
- """Create a zip file from all the files under 'base_dir'.
-
- The output zip file will be named 'base_dir' + ".zip". Uses either the
- "zipfile" Python module (if available) or the InfoZIP "zip" utility
- (if installed and found on the default search path). If neither tool is
- available, raises ExecError. Returns the name of the output zip
- file.
- """
- zip_filename = base_name + ".zip"
- archive_dir = os.path.dirname(base_name)
-
- if not os.path.exists(archive_dir):
- if logger is not None:
- logger.info("creating %s", archive_dir)
- if not dry_run:
- os.makedirs(archive_dir)
-
- # If zipfile module is not available, try spawning an external 'zip'
- # command.
- try:
- import zipfile
- except ImportError:
- zipfile = None
-
- if zipfile is None:
- _call_external_zip(base_dir, verbose)
- else:
- if logger is not None:
- logger.info("creating '%s' and adding '%s' to it",
- zip_filename, base_dir)
-
- if not dry_run:
- zip = zipfile.ZipFile(zip_filename, "w",
- compression=zipfile.ZIP_DEFLATED)
-
- for dirpath, dirnames, filenames in os.walk(base_dir):
- for name in filenames:
- path = os.path.normpath(os.path.join(dirpath, name))
- if os.path.isfile(path):
- zip.write(path, path)
- if logger is not None:
- logger.info("adding '%s'", path)
- zip.close()
-
- return zip_filename
-
-_ARCHIVE_FORMATS = {
- 'gztar': (_make_tarball, [('compress', 'gzip')], "gzip'ed tar-file"),
- 'bztar': (_make_tarball, [('compress', 'bzip2')], "bzip2'ed tar-file"),
- 'ztar': (_make_tarball, [('compress', 'compress')],
- "compressed tar file"),
- 'tar': (_make_tarball, [('compress', None)], "uncompressed tar file"),
- 'zip': (_make_zipfile, [],"ZIP file")
- }
-
-def get_archive_formats():
- """Returns a list of supported formats for archiving and unarchiving.
-
- Each element of the returned sequence is a tuple (name, description)
- """
- formats = [(name, registry[2]) for name, registry in
- _ARCHIVE_FORMATS.items()]
- formats.sort()
- return formats
-
-def register_archive_format(name, function, extra_args=None, description=''):
- """Registers an archive format.
-
- name is the name of the format. function is the callable that will be
- used to create archives. If provided, extra_args is a sequence of
- (name, value) tuples that will be passed as arguments to the callable.
- description can be provided to describe the format, and will be returned
- by the get_archive_formats() function.
- """
- if extra_args is None:
- extra_args = []
- if not callable(function):
- raise TypeError('The %s object is not callable' % function)
- if not isinstance(extra_args, (tuple, list)):
- raise TypeError('extra_args needs to be a sequence')
- for element in extra_args:
- if not isinstance(element, (tuple, list)) or len(element) !=2 :
- raise TypeError('extra_args elements are : (arg_name, value)')
-
- _ARCHIVE_FORMATS[name] = (function, extra_args, description)
-
-def unregister_archive_format(name):
- del _ARCHIVE_FORMATS[name]
-
-def make_archive(base_name, format, root_dir=None, base_dir=None, verbose=0,
- dry_run=0, owner=None, group=None, logger=None):
- """Create an archive file (eg. zip or tar).
-
- 'base_name' is the name of the file to create, minus any format-specific
- extension; 'format' is the archive format: one of "zip", "tar", "ztar",
- or "gztar".
-
- 'root_dir' is a directory that will be the root directory of the
- archive; ie. we typically chdir into 'root_dir' before creating the
- archive. 'base_dir' is the directory where we start archiving from;
- ie. 'base_dir' will be the common prefix of all files and
- directories in the archive. 'root_dir' and 'base_dir' both default
- to the current directory. Returns the name of the archive file.
-
- 'owner' and 'group' are used when creating a tar archive. By default,
- uses the current owner and group.
- """
- save_cwd = os.getcwd()
- if root_dir is not None:
- if logger is not None:
- logger.debug("changing into '%s'", root_dir)
- base_name = os.path.abspath(base_name)
- if not dry_run:
- os.chdir(root_dir)
-
- if base_dir is None:
- base_dir = os.curdir
-
- kwargs = {'dry_run': dry_run, 'logger': logger}
-
- try:
- format_info = _ARCHIVE_FORMATS[format]
- except KeyError:
- raise ValueError, "unknown archive format '%s'" % format
-
- func = format_info[0]
- for arg, val in format_info[1]:
- kwargs[arg] = val
-
- if format != 'zip':
- kwargs['owner'] = owner
- kwargs['group'] = group
-
- try:
- filename = func(base_name, base_dir, **kwargs)
- finally:
- if root_dir is not None:
- if logger is not None:
- logger.debug("changing back to '%s'", save_cwd)
- os.chdir(save_cwd)
-
- return filename
diff --git a/src/distutils2/_backport/sysconfig.cfg b/src/distutils2/_backport/sysconfig.cfg
deleted file mode 100644
index a5d3c94..0000000
--- a/src/distutils2/_backport/sysconfig.cfg
+++ /dev/null
@@ -1,111 +0,0 @@
-[globals]
-# These are the useful categories that are sometimes referenced at runtime,
-# using pkgutil.open():
-# Configuration files
-config = {confdir}/{distribution.name}
-# Non-writable data that is independent of architecture (images, many xml/text files)
-appdata = {datadir}/{distribution.name}
-# Non-writable data that is architecture-dependent (some binary data formats)
-appdata.arch = {libdir}/{distribution.name}
-# Data, written by the package, that must be preserved (databases)
-appdata.persistent = {statedir}/lib/{distribution.name}
-# Data, written by the package, that can be safely discarded (cache)
-appdata.disposable = {statedir}/cache/{distribution.name}
-# Help or documentation files referenced at runtime
-help = {datadir}/{distribution.name}
-icon = {datadir}/pixmaps
-scripts = {base}/bin
-
-# Non-runtime files. These are valid categories for marking files for
-# install, but they should not be referenced by the app at runtime:
-# Help or documentation files not referenced by the package at runtime
-doc = {datadir}/doc/{distribution.name}
-# GNU info documentation files
-info = {datadir}/info
-# man pages
-man = {datadir}/man
-
-[posix_prefix]
-# Configuration directories. Some of these come straight out of the
-# configure script. They are for implementing the other variables, not to
-# be used directly in [resource_locations].
-confdir = /etc
-datadir = /usr/share
-libdir = /usr/lib ; or /usr/lib64 on a multilib system
-statedir = /var
-# User resource directory
-local = ~/.local/{distribution.name}
-
-stdlib = {base}/lib/python{py_version_short}
-platstdlib = {platbase}/lib/python{py_version_short}
-purelib = {base}/lib/python{py_version_short}/site-packages
-platlib = {platbase}/lib/python{py_version_short}/site-packages
-include = {base}/include/python{py_version_short}
-platinclude = {platbase}/include/python{py_version_short}
-data = {base}
-
-[posix_home]
-stdlib = {base}/lib/python
-platstdlib = {base}/lib/python
-purelib = {base}/lib/python
-platlib = {base}/lib/python
-include = {base}/include/python
-platinclude = {base}/include/python
-scripts = {base}/bin
-data = {base}
-
-[nt]
-stdlib = {base}/Lib
-platstdlib = {base}/Lib
-purelib = {base}/Lib/site-packages
-platlib = {base}/Lib/site-packages
-include = {base}/Include
-platinclude = {base}/Include
-scripts = {base}/Scripts
-data = {base}
-
-[os2]
-stdlib = {base}/Lib
-platstdlib = {base}/Lib
-purelib = {base}/Lib/site-packages
-platlib = {base}/Lib/site-packages
-include = {base}/Include
-platinclude = {base}/Include
-scripts = {base}/Scripts
-data = {base}
-
-[os2_home]
-stdlib = {userbase}/lib/python{py_version_short}
-platstdlib = {userbase}/lib/python{py_version_short}
-purelib = {userbase}/lib/python{py_version_short}/site-packages
-platlib = {userbase}/lib/python{py_version_short}/site-packages
-include = {userbase}/include/python{py_version_short}
-scripts = {userbase}/bin
-data = {userbase}
-
-[nt_user]
-stdlib = {userbase}/Python{py_version_nodot}
-platstdlib = {userbase}/Python{py_version_nodot}
-purelib = {userbase}/Python{py_version_nodot}/site-packages
-platlib = {userbase}/Python{py_version_nodot}/site-packages
-include = {userbase}/Python{py_version_nodot}/Include
-scripts = {userbase}/Scripts
-data = {userbase}
-
-[posix_user]
-stdlib = {userbase}/lib/python{py_version_short}
-platstdlib = {userbase}/lib/python{py_version_short}
-purelib = {userbase}/lib/python{py_version_short}/site-packages
-platlib = {userbase}/lib/python{py_version_short}/site-packages
-include = {userbase}/include/python{py_version_short}
-scripts = {userbase}/bin
-data = {userbase}
-
-[osx_framework_user]
-stdlib = {userbase}/lib/python
-platstdlib = {userbase}/lib/python
-purelib = {userbase}/lib/python/site-packages
-platlib = {userbase}/lib/python/site-packages
-include = {userbase}/include
-scripts = {userbase}/bin
-data = {userbase}
diff --git a/src/distutils2/_backport/sysconfig.py b/src/distutils2/_backport/sysconfig.py
deleted file mode 100644
index a5661df..0000000
--- a/src/distutils2/_backport/sysconfig.py
+++ /dev/null
@@ -1,718 +0,0 @@
-"""Provide access to Python's configuration information.
-
-"""
-import sys
-import os
-import re
-from os.path import pardir, realpath
-from ConfigParser import RawConfigParser
-
-_PREFIX = os.path.normpath(sys.prefix)
-_EXEC_PREFIX = os.path.normpath(sys.exec_prefix)
-
-# let's read the configuration file
-# XXX _CONFIG_DIR will be set by the Makefile later
-_CONFIG_DIR = os.path.normpath(os.path.dirname(__file__))
-_CONFIG_FILE = os.path.join(_CONFIG_DIR, 'sysconfig.cfg')
-_SCHEMES = RawConfigParser()
-_SCHEMES.read(_CONFIG_FILE)
-_VAR_REPL = re.compile(r'\{([^{]*?)\}')
-
-def _expand_globals(config):
- if config.has_section('globals'):
- globals = config.items('globals')
- else:
- globals = tuple()
-
- sections = config.sections()
- for section in sections:
- if section == 'globals':
- continue
- for option, value in globals:
- if config.has_option(section, option):
- continue
- config.set(section, option, value)
- config.remove_section('globals')
-
- # now expanding local variables defined in the cfg file
- #
- for section in config.sections():
- variables = dict(config.items(section))
- def _replacer(matchobj):
- name = matchobj.group(1)
- if name in variables:
- return variables[name]
- return matchobj.group(0)
- for option, value in config.items(section):
- config.set(section, option, _VAR_REPL.sub(_replacer, value))
-
-_expand_globals(_SCHEMES)
-
-_PY_VERSION = sys.version.split()[0]
-_PY_VERSION_SHORT = sys.version[:3]
-_PY_VERSION_SHORT_NO_DOT = _PY_VERSION[0] + _PY_VERSION[2]
-_CONFIG_VARS = None
-_USER_BASE = None
-if sys.executable:
- _PROJECT_BASE = os.path.dirname(realpath(sys.executable))
-else:
- # sys.executable can be empty if argv[0] has been changed and Python is
- # unable to retrieve the real program name
- _PROJECT_BASE = realpath(os.getcwd())
-
-if os.name == "nt" and "pcbuild" in _PROJECT_BASE[-8:].lower():
- _PROJECT_BASE = realpath(os.path.join(_PROJECT_BASE, pardir))
-# PC/VS7.1
-if os.name == "nt" and "\\pc\\v" in _PROJECT_BASE[-10:].lower():
- _PROJECT_BASE = realpath(os.path.join(_PROJECT_BASE, pardir, pardir))
-# PC/AMD64
-if os.name == "nt" and "\\pcbuild\\amd64" in _PROJECT_BASE[-14:].lower():
- _PROJECT_BASE = realpath(os.path.join(_PROJECT_BASE, pardir, pardir))
-
-def is_python_build():
- for fn in ("Setup.dist", "Setup.local"):
- if os.path.isfile(os.path.join(_PROJECT_BASE, "Modules", fn)):
- return True
- return False
-
-_PYTHON_BUILD = is_python_build()
-
-if _PYTHON_BUILD:
- for scheme in ('posix_prefix', 'posix_home'):
- _SCHEMES.set(scheme, 'include', '{srcdir}/Include')
- _SCHEMES.set(scheme, 'platinclude', '{projectbase}/.')
-
-
-def _subst_vars(path, local_vars):
- """In the string `path`, replace tokens like {some.thing} with the corresponding value from the map `local_vars`.
-
- If there is no corresponding value, leave the token unchanged.
-
- """
- def _replacer(matchobj):
- name = matchobj.group(1)
- if name in local_vars:
- return local_vars[name]
- elif name in os.environ:
- return os.environ[name]
- return matchobj.group(0)
- return _VAR_REPL.sub(_replacer, path)
-
-def _extend_dict(target_dict, other_dict):
- target_keys = target_dict.keys()
- for key, value in other_dict.items():
- if key in target_keys:
- continue
- target_dict[key] = value
-
-def _expand_vars(scheme, vars):
- res = {}
- if vars is None:
- vars = {}
- _extend_dict(vars, get_config_vars())
-
- for key, value in _SCHEMES.items(scheme):
- if os.name in ('posix', 'nt'):
- value = os.path.expanduser(value)
- res[key] = os.path.normpath(_subst_vars(value, vars))
- return res
-
-def _get_default_scheme():
- if os.name == 'posix':
- # the default scheme for posix is posix_prefix
- return 'posix_prefix'
- return os.name
-
-def _getuserbase():
- env_base = os.environ.get("PYTHONUSERBASE", None)
- def joinuser(*args):
- return os.path.expanduser(os.path.join(*args))
-
- # what about 'os2emx', 'riscos' ?
- if os.name == "nt":
- base = os.environ.get("APPDATA") or "~"
- if env_base:
- return env_base
- else:
- return joinuser(base, "Python")
-
- if sys.platform == "darwin":
- framework = get_config_var("PYTHONFRAMEWORK")
- if framework:
- if env_base:
- return env_base
- else:
- return joinuser("~", "Library", framework, "%d.%d" %
- sys.version_info[:2])
-
- if env_base:
- return env_base
- else:
- return joinuser("~", ".local")
-
-
-def _parse_makefile(filename, vars=None):
- """Parse a Makefile-style file.
-
- A dictionary containing name/value pairs is returned. If an
- optional dictionary is passed in as the second argument, it is
- used instead of a new dictionary.
- """
- import re
- # Regexes needed for parsing Makefile (and similar syntaxes,
- # like old-style Setup files).
- _variable_rx = re.compile("([a-zA-Z][a-zA-Z0-9_]+)\s*=\s*(.*)")
- _findvar1_rx = re.compile(r"\$\(([A-Za-z][A-Za-z0-9_]*)\)")
- _findvar2_rx = re.compile(r"\${([A-Za-z][A-Za-z0-9_]*)}")
-
- if vars is None:
- vars = {}
- done = {}
- notdone = {}
-
- f = open(filename)
- try:
- lines = f.readlines()
- finally:
- f.close()
-
- for line in lines:
- if line.startswith('#') or line.strip() == '':
- continue
- m = _variable_rx.match(line)
- if m:
- n, v = m.group(1, 2)
- v = v.strip()
- # `$$' is a literal `$' in make
- tmpv = v.replace('$$', '')
-
- if "$" in tmpv:
- notdone[n] = v
- else:
- try:
- v = int(v)
- except ValueError:
- # insert literal `$'
- done[n] = v.replace('$$', '$')
- else:
- done[n] = v
-
- # do variable interpolation here
- variables = notdone.keys()
-
- # Variables with a 'PY_' prefix in the makefile. These need to
- # be made available without that prefix through sysconfig.
- # Special care is needed to ensure that variable expansion works, even
- # if the expansion uses the name without a prefix.
- renamed_variables = ('CFLAGS', 'LDFLAGS', 'CPPFLAGS')
-
- while len(variables) > 0:
- for name in tuple(variables):
- value = notdone[name]
- m = _findvar1_rx.search(value) or _findvar2_rx.search(value)
- if m is not None:
- n = m.group(1)
- found = True
- if n in done:
- item = str(done[n])
- elif n in notdone:
- # get it on a subsequent round
- found = False
- elif n in os.environ:
- # do it like make: fall back to environment
- item = os.environ[n]
-
- elif n in renamed_variables:
- if name.startswith('PY_') and name[3:] in renamed_variables:
- item = ""
-
- elif 'PY_' + n in notdone:
- found = False
-
- else:
- item = str(done['PY_' + n])
-
- else:
- done[n] = item = ""
-
- if found:
- after = value[m.end():]
- value = value[:m.start()] + item + after
- if "$" in after:
- notdone[name] = value
- else:
- try:
- value = int(value)
- except ValueError:
- done[name] = value.strip()
- else:
- done[name] = value
- variables.remove(name)
-
- if name.startswith('PY_') \
- and name[3:] in renamed_variables:
-
- name = name[3:]
- if name not in done:
- done[name] = value
-
-
- else:
- # bogus variable reference; just drop it since we can't deal
- variables.remove(name)
-
- # save the results in the global dictionary
- vars.update(done)
- return vars
-
-
-def _get_makefile_filename():
- if _PYTHON_BUILD:
- return os.path.join(_PROJECT_BASE, "Makefile")
- return os.path.join(get_path('stdlib'), "config", "Makefile")
-
-
-def _init_posix(vars):
- """Initialize the module as appropriate for POSIX systems."""
- # load the installed Makefile:
- makefile = _get_makefile_filename()
- try:
- _parse_makefile(makefile, vars)
- except IOError, e:
- msg = "invalid Python installation: unable to open %s" % makefile
- if hasattr(e, "strerror"):
- msg = msg + " (%s)" % e.strerror
- raise IOError(msg)
-
- # load the installed pyconfig.h:
- config_h = get_config_h_filename()
- try:
- parse_config_h(open(config_h), vars)
- except IOError, e:
- msg = "invalid Python installation: unable to open %s" % config_h
- if hasattr(e, "strerror"):
- msg = msg + " (%s)" % e.strerror
- raise IOError(msg)
-
- # On MacOSX we need to check the setting of the environment variable
- # MACOSX_DEPLOYMENT_TARGET: configure bases some choices on it so
- # it needs to be compatible.
- # If it isn't set we set it to the configure-time value
- if sys.platform == 'darwin' and 'MACOSX_DEPLOYMENT_TARGET' in vars:
- cfg_target = vars['MACOSX_DEPLOYMENT_TARGET']
- cur_target = os.getenv('MACOSX_DEPLOYMENT_TARGET', '')
- if cur_target == '':
- cur_target = cfg_target
- os.putenv('MACOSX_DEPLOYMENT_TARGET', cfg_target)
- elif map(int, cfg_target.split('.')) > map(int, cur_target.split('.')):
- msg = ('$MACOSX_DEPLOYMENT_TARGET mismatch: now "%s" but "%s" '
- 'during configure' % (cur_target, cfg_target))
- raise IOError(msg)
-
- # On AIX, there are wrong paths to the linker scripts in the Makefile
- # -- these paths are relative to the Python source, but when installed
- # the scripts are in another directory.
- if _PYTHON_BUILD:
- vars['LDSHARED'] = vars['BLDSHARED']
-
-def _init_non_posix(vars):
- """Initialize the module as appropriate for NT"""
- # set basic install directories
- vars['LIBDEST'] = get_path('stdlib')
- vars['BINLIBDEST'] = get_path('platstdlib')
- vars['INCLUDEPY'] = get_path('include')
- vars['SO'] = '.pyd'
- vars['EXE'] = '.exe'
- vars['VERSION'] = _PY_VERSION_SHORT_NO_DOT
- vars['BINDIR'] = os.path.dirname(realpath(sys.executable))
-
-#
-# public APIs
-#
-
-
-def parse_config_h(fp, vars=None):
- """Parse a config.h-style file.
-
- A dictionary containing name/value pairs is returned. If an
- optional dictionary is passed in as the second argument, it is
- used instead of a new dictionary.
- """
- import re
- if vars is None:
- vars = {}
- define_rx = re.compile("#define ([A-Z][A-Za-z0-9_]+) (.*)\n")
- undef_rx = re.compile("/[*] #undef ([A-Z][A-Za-z0-9_]+) [*]/\n")
-
- while True:
- line = fp.readline()
- if not line:
- break
- m = define_rx.match(line)
- if m:
- n, v = m.group(1, 2)
- try: v = int(v)
- except ValueError: pass
- vars[n] = v
- else:
- m = undef_rx.match(line)
- if m:
- vars[m.group(1)] = 0
- return vars
-
-def get_config_h_filename():
- """Returns the path of pyconfig.h."""
- if _PYTHON_BUILD:
- if os.name == "nt":
- inc_dir = os.path.join(_PROJECT_BASE, "PC")
- else:
- inc_dir = _PROJECT_BASE
- else:
- inc_dir = get_path('platinclude')
- return os.path.join(inc_dir, 'pyconfig.h')
-
-def get_scheme_names():
- """Returns a tuple containing the schemes names."""
- return tuple(sorted(_SCHEMES.sections()))
-
-def get_path_names():
- """Returns a tuple containing the paths names."""
- # xxx see if we want a static list
- return _SCHEMES.options('posix_prefix')
-
-def get_paths(scheme=_get_default_scheme(), vars=None, expand=True):
- """Returns a mapping containing an install scheme.
-
- ``scheme`` is the install scheme name. If not provided, it will
- return the default scheme for the current platform.
- """
- if expand:
- return _expand_vars(scheme, vars)
- else:
- return dict(_SCHEMES.items(scheme))
-
-def get_path(name, scheme=_get_default_scheme(), vars=None, expand=True):
- """Returns a path corresponding to the scheme.
-
- ``scheme`` is the install scheme name.
- """
- return get_paths(scheme, vars, expand)[name]
-
-def get_config_vars(*args):
- """With no arguments, return a dictionary of all configuration
- variables relevant for the current platform.
-
- On Unix, this means every variable defined in Python's installed Makefile;
- On Windows and Mac OS it's a much smaller set.
-
- With arguments, return a list of values that result from looking up
- each argument in the configuration variable dictionary.
- """
- import re
- global _CONFIG_VARS
- if _CONFIG_VARS is None:
- _CONFIG_VARS = {}
- # Normalized versions of prefix and exec_prefix are handy to have;
- # in fact, these are the standard versions used most places in the
- # Distutils.
- _CONFIG_VARS['prefix'] = _PREFIX
- _CONFIG_VARS['exec_prefix'] = _EXEC_PREFIX
- _CONFIG_VARS['py_version'] = _PY_VERSION
- _CONFIG_VARS['py_version_short'] = _PY_VERSION_SHORT
- _CONFIG_VARS['py_version_nodot'] = _PY_VERSION[0] + _PY_VERSION[2]
- _CONFIG_VARS['base'] = _PREFIX
- _CONFIG_VARS['platbase'] = _EXEC_PREFIX
- _CONFIG_VARS['projectbase'] = _PROJECT_BASE
-
- if os.name in ('nt', 'os2'):
- _init_non_posix(_CONFIG_VARS)
- if os.name == 'posix':
- _init_posix(_CONFIG_VARS)
-
- # Setting 'userbase' is done below the call to the
- # init function to enable using 'get_config_var' in
- # the init-function.
- if sys.version >= '2.6':
- _CONFIG_VARS['userbase'] = _getuserbase()
-
- if 'srcdir' not in _CONFIG_VARS:
- _CONFIG_VARS['srcdir'] = _PROJECT_BASE
- else:
- _CONFIG_VARS['srcdir'] = realpath(_CONFIG_VARS['srcdir'])
-
-
- # Convert srcdir into an absolute path if it appears necessary.
- # Normally it is relative to the build directory. However, during
- # testing, for example, we might be running a non-installed python
- # from a different directory.
- if _PYTHON_BUILD and os.name == "posix":
- base = _PROJECT_BASE
- if (not os.path.isabs(_CONFIG_VARS['srcdir']) and
- base != os.getcwd()):
- # srcdir is relative and we are not in the same directory
- # as the executable. Assume executable is in the build
- # directory and make srcdir absolute.
- srcdir = os.path.join(base, _CONFIG_VARS['srcdir'])
- _CONFIG_VARS['srcdir'] = os.path.normpath(srcdir)
-
- if sys.platform == 'darwin':
- kernel_version = os.uname()[2] # Kernel version (8.4.3)
- major_version = int(kernel_version.split('.')[0])
-
- if major_version < 8:
- # On Mac OS X before 10.4, check if -arch and -isysroot
- # are in CFLAGS or LDFLAGS and remove them if they are.
- # This is needed when building extensions on a 10.3 system
- # using a universal build of python.
- for key in ('LDFLAGS', 'BASECFLAGS',
- # a number of derived variables. These need to be
- # patched up as well.
- 'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'):
- flags = _CONFIG_VARS[key]
- flags = re.sub('-arch\s+\w+\s', ' ', flags)
- flags = re.sub('-isysroot [^ \t]*', ' ', flags)
- _CONFIG_VARS[key] = flags
- else:
- # Allow the user to override the architecture flags using
- # an environment variable.
- # NOTE: This name was introduced by Apple in OSX 10.5 and
- # is used by several scripting languages distributed with
- # that OS release.
- if 'ARCHFLAGS' in os.environ:
- arch = os.environ['ARCHFLAGS']
- for key in ('LDFLAGS', 'BASECFLAGS',
- # a number of derived variables. These need to be
- # patched up as well.
- 'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'):
-
- flags = _CONFIG_VARS[key]
- flags = re.sub('-arch\s+\w+\s', ' ', flags)
- flags = flags + ' ' + arch
- _CONFIG_VARS[key] = flags
-
- # If we're on OSX 10.5 or later and the user tries to
- # compiles an extension using an SDK that is not present
- # on the current machine it is better to not use an SDK
- # than to fail.
- #
- # The major usecase for this is users using a Python.org
- # binary installer on OSX 10.6: that installer uses
- # the 10.4u SDK, but that SDK is not installed by default
- # when you install Xcode.
- #
- CFLAGS = _CONFIG_VARS.get('CFLAGS', '')
- m = re.search('-isysroot\s+(\S+)', CFLAGS)
- if m is not None:
- sdk = m.group(1)
- if not os.path.exists(sdk):
- for key in ('LDFLAGS', 'BASECFLAGS',
- # a number of derived variables. These need to be
- # patched up as well.
- 'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'):
-
- flags = _CONFIG_VARS[key]
- flags = re.sub('-isysroot\s+\S+(\s|$)', ' ', flags)
- _CONFIG_VARS[key] = flags
-
- if args:
- vals = []
- for name in args:
- vals.append(_CONFIG_VARS.get(name))
- return vals
- else:
- return _CONFIG_VARS
-
-def get_config_var(name):
- """Return the value of a single variable using the dictionary returned by
- 'get_config_vars()'.
-
- Equivalent to get_config_vars().get(name)
- """
- return get_config_vars().get(name)
-
-def get_platform():
- """Return a string that identifies the current platform.
-
- This is used mainly to distinguish platform-specific build directories and
- platform-specific built distributions. Typically includes the OS name
- and version and the architecture (as supplied by 'os.uname()'),
- although the exact information included depends on the OS; eg. for IRIX
- the architecture isn't particularly important (IRIX only runs on SGI
- hardware), but for Linux the kernel version isn't particularly
- important.
-
- Examples of returned values:
- linux-i586
- linux-alpha (?)
- solaris-2.6-sun4u
- irix-5.3
- irix64-6.2
-
- Windows will return one of:
- win-amd64 (64bit Windows on AMD64 (aka x86_64, Intel64, EM64T, etc)
- win-ia64 (64bit Windows on Itanium)
- win32 (all others - specifically, sys.platform is returned)
-
- For other non-POSIX platforms, currently just returns 'sys.platform'.
- """
- import re
- if os.name == 'nt':
- # sniff sys.version for architecture.
- prefix = " bit ("
- i = sys.version.find(prefix)
- if i == -1:
- return sys.platform
- j = sys.version.find(")", i)
- look = sys.version[i+len(prefix):j].lower()
- if look == 'amd64':
- return 'win-amd64'
- if look == 'itanium':
- return 'win-ia64'
- return sys.platform
-
- if os.name != "posix" or not hasattr(os, 'uname'):
- # XXX what about the architecture? NT is Intel or Alpha,
- # Mac OS is M68k or PPC, etc.
- return sys.platform
-
- # Try to distinguish various flavours of Unix
- osname, host, release, version, machine = os.uname()
-
- # Convert the OS name to lowercase, remove '/' characters
- # (to accommodate BSD/OS), and translate spaces (for "Power Macintosh")
- osname = osname.lower().replace('/', '')
- machine = machine.replace(' ', '_')
- machine = machine.replace('/', '-')
-
- if osname[:5] == "linux":
- # At least on Linux/Intel, 'machine' is the processor --
- # i386, etc.
- # XXX what about Alpha, SPARC, etc?
- return "%s-%s" % (osname, machine)
- elif osname[:5] == "sunos":
- if release[0] >= "5": # SunOS 5 == Solaris 2
- osname = "solaris"
- release = "%d.%s" % (int(release[0]) - 3, release[2:])
- # fall through to standard osname-release-machine representation
- elif osname[:4] == "irix": # could be "irix64"!
- return "%s-%s" % (osname, release)
- elif osname[:3] == "aix":
- return "%s-%s.%s" % (osname, version, release)
- elif osname[:6] == "cygwin":
- osname = "cygwin"
- rel_re = re.compile (r'[\d.]+')
- m = rel_re.match(release)
- if m:
- release = m.group()
- elif osname[:6] == "darwin":
- #
- # For our purposes, we'll assume that the system version from
- # distutils' perspective is what MACOSX_DEPLOYMENT_TARGET is set
- # to. This makes the compatibility story a bit more sane because the
- # machine is going to compile and link as if it were
- # MACOSX_DEPLOYMENT_TARGET.
- cfgvars = get_config_vars()
- macver = os.environ.get('MACOSX_DEPLOYMENT_TARGET')
- if not macver:
- macver = cfgvars.get('MACOSX_DEPLOYMENT_TARGET')
-
- if 1:
- # Always calculate the release of the running machine,
- # needed to determine if we can build fat binaries or not.
-
- macrelease = macver
- # Get the system version. Reading this plist is a documented
- # way to get the system version (see the documentation for
- # the Gestalt Manager)
- try:
- f = open('/System/Library/CoreServices/SystemVersion.plist')
- except IOError:
- # We're on a plain darwin box, fall back to the default
- # behaviour.
- pass
- else:
- try:
- m = re.search(r'<key>ProductUserVisibleVersion</key>\s*'
- r'<string>(.*?)</string>', f.read())
- finally:
- f.close()
- if m is not None:
- macrelease = '.'.join(m.group(1).split('.')[:2])
- # else: fall back to the default behaviour
-
- if not macver:
- macver = macrelease
-
- if macver:
- release = macver
- osname = "macosx"
-
- if (macrelease + '.') >= '10.4.' and \
- '-arch' in get_config_vars().get('CFLAGS', '').strip():
- # The universal build will build fat binaries, but not on
- # systems before 10.4
- #
- # Try to detect 4-way universal builds, those have machine-type
- # 'universal' instead of 'fat'.
-
- machine = 'fat'
- cflags = get_config_vars().get('CFLAGS')
-
- archs = re.findall('-arch\s+(\S+)', cflags)
- archs = tuple(sorted(set(archs)))
-
- if len(archs) == 1:
- machine = archs[0]
- elif archs == ('i386', 'ppc'):
- machine = 'fat'
- elif archs == ('i386', 'x86_64'):
- machine = 'intel'
- elif archs == ('i386', 'ppc', 'x86_64'):
- machine = 'fat3'
- elif archs == ('ppc64', 'x86_64'):
- machine = 'fat64'
- elif archs == ('i386', 'ppc', 'ppc64', 'x86_64'):
- machine = 'universal'
- else:
- raise ValueError(
- "Don't know machine value for archs=%r"%(archs,))
-
- elif machine == 'i386':
- # On OSX the machine type returned by uname is always the
- # 32-bit variant, even if the executable architecture is
- # the 64-bit variant
- if sys.maxint >= 2**32:
- machine = 'x86_64'
-
- elif machine in ('PowerPC', 'Power_Macintosh'):
- # Pick a sane name for the PPC architecture.
- # See 'i386' case
- if sys.maxint >= 2**32:
- machine = 'ppc64'
- else:
- machine = 'ppc'
-
- return "%s-%s-%s" % (osname, release, machine)
-
-
-def get_python_version():
- return _PY_VERSION_SHORT
-
-def _print_dict(title, data):
- for index, (key, value) in enumerate(sorted(data.items())):
- if index == 0:
- print '%s: ' % (title)
- print '\t%s = "%s"' % (key, value)
-
-def _main():
- """Display all information sysconfig detains."""
- print 'Platform: "%s"' % get_platform()
- print 'Python version: "%s"' % get_python_version()
- print 'Current installation scheme: "%s"' % _get_default_scheme()
- print ''
- _print_dict('Paths', get_paths())
- print
- _print_dict('Variables', get_config_vars())
-
-if __name__ == '__main__':
- _main()
diff --git a/src/distutils2/_backport/tarfile.py b/src/distutils2/_backport/tarfile.py
deleted file mode 100644
index 3c95868..0000000
--- a/src/distutils2/_backport/tarfile.py
+++ /dev/null
@@ -1,2573 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: iso-8859-1 -*-
-#-------------------------------------------------------------------
-# tarfile.py
-#-------------------------------------------------------------------
-# Copyright (C) 2002 Lars Gustäbel <lars@gustaebel.de>
-# All rights reserved.
-#
-# 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.
-#
-"""Read from and write to tar format archives.
-"""
-
-__version__ = "$Revision: 76780 $"
-# $Source$
-
-version = "0.9.0"
-__author__ = "Lars Gustäbel (lars@gustaebel.de)"
-__date__ = "$Date: 2009-12-13 12:32:27 +0100 (Dim 13 déc 2009) $"
-__cvsid__ = "$Id: tarfile.py 76780 2009-12-13 11:32:27Z lars.gustaebel $"
-__credits__ = "Gustavo Niemeyer, Niels Gustäbel, Richard Townsend."
-
-#---------
-# Imports
-#---------
-import sys
-import os
-import shutil
-import stat
-import errno
-import time
-import struct
-import copy
-import re
-import operator
-
-if not hasattr(os, 'SEEK_SET'):
- os.SEEK_SET = 0
-
-try:
- import grp, pwd
-except ImportError:
- grp = pwd = None
-
-# from tarfile import *
-__all__ = ["TarFile", "TarInfo", "is_tarfile", "TarError"]
-
-#---------------------------------------------------------
-# tar constants
-#---------------------------------------------------------
-NUL = "\0" # the null character
-BLOCKSIZE = 512 # length of processing blocks
-RECORDSIZE = BLOCKSIZE * 20 # length of records
-GNU_MAGIC = "ustar \0" # magic gnu tar string
-POSIX_MAGIC = "ustar\x0000" # magic posix tar string
-
-LENGTH_NAME = 100 # maximum length of a filename
-LENGTH_LINK = 100 # maximum length of a linkname
-LENGTH_PREFIX = 155 # maximum length of the prefix field
-
-REGTYPE = "0" # regular file
-AREGTYPE = "\0" # regular file
-LNKTYPE = "1" # link (inside tarfile)
-SYMTYPE = "2" # symbolic link
-CHRTYPE = "3" # character special device
-BLKTYPE = "4" # block special device
-DIRTYPE = "5" # directory
-FIFOTYPE = "6" # fifo special device
-CONTTYPE = "7" # contiguous file
-
-GNUTYPE_LONGNAME = "L" # GNU tar longname
-GNUTYPE_LONGLINK = "K" # GNU tar longlink
-GNUTYPE_SPARSE = "S" # GNU tar sparse file
-
-XHDTYPE = "x" # POSIX.1-2001 extended header
-XGLTYPE = "g" # POSIX.1-2001 global header
-SOLARIS_XHDTYPE = "X" # Solaris extended header
-
-USTAR_FORMAT = 0 # POSIX.1-1988 (ustar) format
-GNU_FORMAT = 1 # GNU tar format
-PAX_FORMAT = 2 # POSIX.1-2001 (pax) format
-DEFAULT_FORMAT = GNU_FORMAT
-
-#---------------------------------------------------------
-# tarfile constants
-#---------------------------------------------------------
-# File types that tarfile supports:
-SUPPORTED_TYPES = (REGTYPE, AREGTYPE, LNKTYPE,
- SYMTYPE, DIRTYPE, FIFOTYPE,
- CONTTYPE, CHRTYPE, BLKTYPE,
- GNUTYPE_LONGNAME, GNUTYPE_LONGLINK,
- GNUTYPE_SPARSE)
-
-# File types that will be treated as a regular file.
-REGULAR_TYPES = (REGTYPE, AREGTYPE,
- CONTTYPE, GNUTYPE_SPARSE)
-
-# File types that are part of the GNU tar format.
-GNU_TYPES = (GNUTYPE_LONGNAME, GNUTYPE_LONGLINK,
- GNUTYPE_SPARSE)
-
-# Fields from a pax header that override a TarInfo attribute.
-PAX_FIELDS = ("path", "linkpath", "size", "mtime",
- "uid", "gid", "uname", "gname")
-
-# Fields in a pax header that are numbers, all other fields
-# are treated as strings.
-PAX_NUMBER_FIELDS = {
- "atime": float,
- "ctime": float,
- "mtime": float,
- "uid": int,
- "gid": int,
- "size": int
-}
-
-#---------------------------------------------------------
-# Bits used in the mode field, values in octal.
-#---------------------------------------------------------
-S_IFLNK = 0120000 # symbolic link
-S_IFREG = 0100000 # regular file
-S_IFBLK = 0060000 # block device
-S_IFDIR = 0040000 # directory
-S_IFCHR = 0020000 # character device
-S_IFIFO = 0010000 # fifo
-
-TSUID = 04000 # set UID on execution
-TSGID = 02000 # set GID on execution
-TSVTX = 01000 # reserved
-
-TUREAD = 0400 # read by owner
-TUWRITE = 0200 # write by owner
-TUEXEC = 0100 # execute/search by owner
-TGREAD = 0040 # read by group
-TGWRITE = 0020 # write by group
-TGEXEC = 0010 # execute/search by group
-TOREAD = 0004 # read by other
-TOWRITE = 0002 # write by other
-TOEXEC = 0001 # execute/search by other
-
-#---------------------------------------------------------
-# initialization
-#---------------------------------------------------------
-ENCODING = sys.getfilesystemencoding()
-if ENCODING is None:
- ENCODING = sys.getdefaultencoding()
-
-#---------------------------------------------------------
-# Some useful functions
-#---------------------------------------------------------
-
-def stn(s, length):
- """Convert a python string to a null-terminated string buffer.
- """
- return s[:length] + (length - len(s)) * NUL
-
-def nts(s):
- """Convert a null-terminated string field to a python string.
- """
- # Use the string up to the first null char.
- p = s.find("\0")
- if p == -1:
- return s
- return s[:p]
-
-def nti(s):
- """Convert a number field to a python number.
- """
- # There are two possible encodings for a number field, see
- # itn() below.
- if s[0] != chr(0200):
- try:
- n = int(nts(s) or "0", 8)
- except ValueError:
- raise InvalidHeaderError("invalid header")
- else:
- n = 0L
- for i in xrange(len(s) - 1):
- n <<= 8
- n += ord(s[i + 1])
- return n
-
-def itn(n, digits=8, format=DEFAULT_FORMAT):
- """Convert a python number to a number field.
- """
- # POSIX 1003.1-1988 requires numbers to be encoded as a string of
- # octal digits followed by a null-byte, this allows values up to
- # (8**(digits-1))-1. GNU tar allows storing numbers greater than
- # that if necessary. A leading 0200 byte indicates this particular
- # encoding, the following digits-1 bytes are a big-endian
- # representation. This allows values up to (256**(digits-1))-1.
- if 0 <= n < 8 ** (digits - 1):
- s = "%0*o" % (digits - 1, n) + NUL
- else:
- if format != GNU_FORMAT or n >= 256 ** (digits - 1):
- raise ValueError("overflow in number field")
-
- if n < 0:
- # XXX We mimic GNU tar's behaviour with negative numbers,
- # this could raise OverflowError.
- n = struct.unpack("L", struct.pack("l", n))[0]
-
- s = ""
- for i in xrange(digits - 1):
- s = chr(n & 0377) + s
- n >>= 8
- s = chr(0200) + s
- return s
-
-def uts(s, encoding, errors):
- """Convert a unicode object to a string.
- """
- if errors == "utf-8":
- # An extra error handler similar to the -o invalid=UTF-8 option
- # in POSIX.1-2001. Replace untranslatable characters with their
- # UTF-8 representation.
- try:
- return s.encode(encoding, "strict")
- except UnicodeEncodeError:
- x = []
- for c in s:
- try:
- x.append(c.encode(encoding, "strict"))
- except UnicodeEncodeError:
- x.append(c.encode("utf8"))
- return "".join(x)
- else:
- return s.encode(encoding, errors)
-
-def calc_chksums(buf):
- """Calculate the checksum for a member's header by summing up all
- characters except for the chksum field which is treated as if
- it was filled with spaces. According to the GNU tar sources,
- some tars (Sun and NeXT) calculate chksum with signed char,
- which will be different if there are chars in the buffer with
- the high bit set. So we calculate two checksums, unsigned and
- signed.
- """
- unsigned_chksum = 256 + sum(struct.unpack("148B", buf[:148]) + struct.unpack("356B", buf[156:512]))
- signed_chksum = 256 + sum(struct.unpack("148b", buf[:148]) + struct.unpack("356b", buf[156:512]))
- return unsigned_chksum, signed_chksum
-
-def copyfileobj(src, dst, length=None):
- """Copy length bytes from fileobj src to fileobj dst.
- If length is None, copy the entire content.
- """
- if length == 0:
- return
- if length is None:
- shutil.copyfileobj(src, dst)
- return
-
- BUFSIZE = 16 * 1024
- blocks, remainder = divmod(length, BUFSIZE)
- for b in xrange(blocks):
- buf = src.read(BUFSIZE)
- if len(buf) < BUFSIZE:
- raise IOError("end of file reached")
- dst.write(buf)
-
- if remainder != 0:
- buf = src.read(remainder)
- if len(buf) < remainder:
- raise IOError("end of file reached")
- dst.write(buf)
- return
-
-filemode_table = (
- ((S_IFLNK, "l"),
- (S_IFREG, "-"),
- (S_IFBLK, "b"),
- (S_IFDIR, "d"),
- (S_IFCHR, "c"),
- (S_IFIFO, "p")),
-
- ((TUREAD, "r"),),
- ((TUWRITE, "w"),),
- ((TUEXEC|TSUID, "s"),
- (TSUID, "S"),
- (TUEXEC, "x")),
-
- ((TGREAD, "r"),),
- ((TGWRITE, "w"),),
- ((TGEXEC|TSGID, "s"),
- (TSGID, "S"),
- (TGEXEC, "x")),
-
- ((TOREAD, "r"),),
- ((TOWRITE, "w"),),
- ((TOEXEC|TSVTX, "t"),
- (TSVTX, "T"),
- (TOEXEC, "x"))
-)
-
-def filemode(mode):
- """Convert a file's mode to a string of the form
- -rwxrwxrwx.
- Used by TarFile.list()
- """
- perm = []
- for table in filemode_table:
- for bit, char in table:
- if mode & bit == bit:
- perm.append(char)
- break
- else:
- perm.append("-")
- return "".join(perm)
-
-class TarError(Exception):
- """Base exception."""
- pass
-class ExtractError(TarError):
- """General exception for extract errors."""
- pass
-class ReadError(TarError):
- """Exception for unreadble tar archives."""
- pass
-class CompressionError(TarError):
- """Exception for unavailable compression methods."""
- pass
-class StreamError(TarError):
- """Exception for unsupported operations on stream-like TarFiles."""
- pass
-class HeaderError(TarError):
- """Base exception for header errors."""
- pass
-class EmptyHeaderError(HeaderError):
- """Exception for empty headers."""
- pass
-class TruncatedHeaderError(HeaderError):
- """Exception for truncated headers."""
- pass
-class EOFHeaderError(HeaderError):
- """Exception for end of file headers."""
- pass
-class InvalidHeaderError(HeaderError):
- """Exception for invalid headers."""
- pass
-class SubsequentHeaderError(HeaderError):
- """Exception for missing and invalid extended headers."""
- pass
-
-#---------------------------
-# internal stream interface
-#---------------------------
-class _LowLevelFile(object):
- """Low-level file object. Supports reading and writing.
- It is used instead of a regular file object for streaming
- access.
- """
-
- def __init__(self, name, mode):
- mode = {
- "r": os.O_RDONLY,
- "w": os.O_WRONLY | os.O_CREAT | os.O_TRUNC,
- }[mode]
- if hasattr(os, "O_BINARY"):
- mode |= os.O_BINARY
- self.fd = os.open(name, mode)
-
- def close(self):
- os.close(self.fd)
-
- def read(self, size):
- return os.read(self.fd, size)
-
- def write(self, s):
- os.write(self.fd, s)
-
-class _Stream(object):
- """Class that serves as an adapter between TarFile and
- a stream-like object. The stream-like object only
- needs to have a read() or write() method and is accessed
- blockwise. Use of gzip or bzip2 compression is possible.
- A stream-like object could be for example: sys.stdin,
- sys.stdout, a socket, a tape device etc.
-
- _Stream is intended to be used only internally.
- """
-
- def __init__(self, name, mode, comptype, fileobj, bufsize):
- """Construct a _Stream object.
- """
- self._extfileobj = True
- if fileobj is None:
- fileobj = _LowLevelFile(name, mode)
- self._extfileobj = False
-
- if comptype == '*':
- # Enable transparent compression detection for the
- # stream interface
- fileobj = _StreamProxy(fileobj)
- comptype = fileobj.getcomptype()
-
- self.name = name or ""
- self.mode = mode
- self.comptype = comptype
- self.fileobj = fileobj
- self.bufsize = bufsize
- self.buf = ""
- self.pos = 0L
- self.closed = False
-
- if comptype == "gz":
- try:
- import zlib
- except ImportError:
- raise CompressionError("zlib module is not available")
- self.zlib = zlib
- self.crc = zlib.crc32("") & 0xffffffffL
- if mode == "r":
- self._init_read_gz()
- else:
- self._init_write_gz()
-
- if comptype == "bz2":
- try:
- import bz2
- except ImportError:
- raise CompressionError("bz2 module is not available")
- if mode == "r":
- self.dbuf = ""
- self.cmp = bz2.BZ2Decompressor()
- else:
- self.cmp = bz2.BZ2Compressor()
-
- def __del__(self):
- if hasattr(self, "closed") and not self.closed:
- self.close()
-
- def _init_write_gz(self):
- """Initialize for writing with gzip compression.
- """
- self.cmp = self.zlib.compressobj(9, self.zlib.DEFLATED,
- -self.zlib.MAX_WBITS,
- self.zlib.DEF_MEM_LEVEL,
- 0)
- timestamp = struct.pack("<L", long(time.time()))
- self.__write("\037\213\010\010%s\002\377" % timestamp)
- if self.name.endswith(".gz"):
- self.name = self.name[:-3]
- self.__write(self.name + NUL)
-
- def write(self, s):
- """Write string s to the stream.
- """
- if self.comptype == "gz":
- self.crc = self.zlib.crc32(s, self.crc) & 0xffffffffL
- self.pos += len(s)
- if self.comptype != "tar":
- s = self.cmp.compress(s)
- self.__write(s)
-
- def __write(self, s):
- """Write string s to the stream if a whole new block
- is ready to be written.
- """
- self.buf += s
- while len(self.buf) > self.bufsize:
- self.fileobj.write(self.buf[:self.bufsize])
- self.buf = self.buf[self.bufsize:]
-
- def close(self):
- """Close the _Stream object. No operation should be
- done on it afterwards.
- """
- if self.closed:
- return
-
- if self.mode == "w" and self.comptype != "tar":
- self.buf += self.cmp.flush()
-
- if self.mode == "w" and self.buf:
- self.fileobj.write(self.buf)
- self.buf = ""
- if self.comptype == "gz":
- # The native zlib crc is an unsigned 32-bit integer, but
- # the Python wrapper implicitly casts that to a signed C
- # long. So, on a 32-bit box self.crc may "look negative",
- # while the same crc on a 64-bit box may "look positive".
- # To avoid irksome warnings from the `struct` module, force
- # it to look positive on all boxes.
- self.fileobj.write(struct.pack("<L", self.crc & 0xffffffffL))
- self.fileobj.write(struct.pack("<L", self.pos & 0xffffFFFFL))
-
- if not self._extfileobj:
- self.fileobj.close()
-
- self.closed = True
-
- def _init_read_gz(self):
- """Initialize for reading a gzip compressed fileobj.
- """
- self.cmp = self.zlib.decompressobj(-self.zlib.MAX_WBITS)
- self.dbuf = ""
-
- # taken from gzip.GzipFile with some alterations
- if self.__read(2) != "\037\213":
- raise ReadError("not a gzip file")
- if self.__read(1) != "\010":
- raise CompressionError("unsupported compression method")
-
- flag = ord(self.__read(1))
- self.__read(6)
-
- if flag & 4:
- xlen = ord(self.__read(1)) + 256 * ord(self.__read(1))
- self.read(xlen)
- if flag & 8:
- while True:
- s = self.__read(1)
- if not s or s == NUL:
- break
- if flag & 16:
- while True:
- s = self.__read(1)
- if not s or s == NUL:
- break
- if flag & 2:
- self.__read(2)
-
- def tell(self):
- """Return the stream's file pointer position.
- """
- return self.pos
-
- def seek(self, pos=0):
- """Set the stream's file pointer to pos. Negative seeking
- is forbidden.
- """
- if pos - self.pos >= 0:
- blocks, remainder = divmod(pos - self.pos, self.bufsize)
- for i in xrange(blocks):
- self.read(self.bufsize)
- self.read(remainder)
- else:
- raise StreamError("seeking backwards is not allowed")
- return self.pos
-
- def read(self, size=None):
- """Return the next size number of bytes from the stream.
- If size is not defined, return all bytes of the stream
- up to EOF.
- """
- if size is None:
- t = []
- while True:
- buf = self._read(self.bufsize)
- if not buf:
- break
- t.append(buf)
- buf = "".join(t)
- else:
- buf = self._read(size)
- self.pos += len(buf)
- return buf
-
- def _read(self, size):
- """Return size bytes from the stream.
- """
- if self.comptype == "tar":
- return self.__read(size)
-
- c = len(self.dbuf)
- t = [self.dbuf]
- while c < size:
- buf = self.__read(self.bufsize)
- if not buf:
- break
- try:
- buf = self.cmp.decompress(buf)
- except IOError:
- raise ReadError("invalid compressed data")
- t.append(buf)
- c += len(buf)
- t = "".join(t)
- self.dbuf = t[size:]
- return t[:size]
-
- def __read(self, size):
- """Return size bytes from stream. If internal buffer is empty,
- read another block from the stream.
- """
- c = len(self.buf)
- t = [self.buf]
- while c < size:
- buf = self.fileobj.read(self.bufsize)
- if not buf:
- break
- t.append(buf)
- c += len(buf)
- t = "".join(t)
- self.buf = t[size:]
- return t[:size]
-# class _Stream
-
-class _StreamProxy(object):
- """Small proxy class that enables transparent compression
- detection for the Stream interface (mode 'r|*').
- """
-
- def __init__(self, fileobj):
- self.fileobj = fileobj
- self.buf = self.fileobj.read(BLOCKSIZE)
-
- def read(self, size):
- self.read = self.fileobj.read
- return self.buf
-
- def getcomptype(self):
- if self.buf.startswith("\037\213\010"):
- return "gz"
- if self.buf.startswith("BZh91"):
- return "bz2"
- return "tar"
-
- def close(self):
- self.fileobj.close()
-# class StreamProxy
-
-class _BZ2Proxy(object):
- """Small proxy class that enables external file object
- support for "r:bz2" and "w:bz2" modes. This is actually
- a workaround for a limitation in bz2 module's BZ2File
- class which (unlike gzip.GzipFile) has no support for
- a file object argument.
- """
-
- blocksize = 16 * 1024
-
- def __init__(self, fileobj, mode):
- self.fileobj = fileobj
- self.mode = mode
- self.name = getattr(self.fileobj, "name", None)
- self.init()
-
- def init(self):
- import bz2
- self.pos = 0
- if self.mode == "r":
- self.bz2obj = bz2.BZ2Decompressor()
- self.fileobj.seek(0)
- self.buf = ""
- else:
- self.bz2obj = bz2.BZ2Compressor()
-
- def read(self, size):
- b = [self.buf]
- x = len(self.buf)
- while x < size:
- raw = self.fileobj.read(self.blocksize)
- if not raw:
- break
- data = self.bz2obj.decompress(raw)
- b.append(data)
- x += len(data)
- self.buf = "".join(b)
-
- buf = self.buf[:size]
- self.buf = self.buf[size:]
- self.pos += len(buf)
- return buf
-
- def seek(self, pos):
- if pos < self.pos:
- self.init()
- self.read(pos - self.pos)
-
- def tell(self):
- return self.pos
-
- def write(self, data):
- self.pos += len(data)
- raw = self.bz2obj.compress(data)
- self.fileobj.write(raw)
-
- def close(self):
- if self.mode == "w":
- raw = self.bz2obj.flush()
- self.fileobj.write(raw)
-# class _BZ2Proxy
-
-#------------------------
-# Extraction file object
-#------------------------
-class _FileInFile(object):
- """A thin wrapper around an existing file object that
- provides a part of its data as an individual file
- object.
- """
-
- def __init__(self, fileobj, offset, size, sparse=None):
- self.fileobj = fileobj
- self.offset = offset
- self.size = size
- self.sparse = sparse
- self.position = 0
-
- def tell(self):
- """Return the current file position.
- """
- return self.position
-
- def seek(self, position):
- """Seek to a position in the file.
- """
- self.position = position
-
- def read(self, size=None):
- """Read data from the file.
- """
- if size is None:
- size = self.size - self.position
- else:
- size = min(size, self.size - self.position)
-
- if self.sparse is None:
- return self.readnormal(size)
- else:
- return self.readsparse(size)
-
- def readnormal(self, size):
- """Read operation for regular files.
- """
- self.fileobj.seek(self.offset + self.position)
- self.position += size
- return self.fileobj.read(size)
-
- def readsparse(self, size):
- """Read operation for sparse files.
- """
- data = []
- while size > 0:
- buf = self.readsparsesection(size)
- if not buf:
- break
- size -= len(buf)
- data.append(buf)
- return "".join(data)
-
- def readsparsesection(self, size):
- """Read a single section of a sparse file.
- """
- section = self.sparse.find(self.position)
-
- if section is None:
- return ""
-
- size = min(size, section.offset + section.size - self.position)
-
- if isinstance(section, _data):
- realpos = section.realpos + self.position - section.offset
- self.fileobj.seek(self.offset + realpos)
- self.position += size
- return self.fileobj.read(size)
- else:
- self.position += size
- return NUL * size
-#class _FileInFile
-
-
-class ExFileObject(object):
- """File-like object for reading an archive member.
- Is returned by TarFile.extractfile().
- """
- blocksize = 1024
-
- def __init__(self, tarfile, tarinfo):
- self.fileobj = _FileInFile(tarfile.fileobj,
- tarinfo.offset_data,
- tarinfo.size,
- getattr(tarinfo, "sparse", None))
- self.name = tarinfo.name
- self.mode = "r"
- self.closed = False
- self.size = tarinfo.size
-
- self.position = 0
- self.buffer = ""
-
- def read(self, size=None):
- """Read at most size bytes from the file. If size is not
- present or None, read all data until EOF is reached.
- """
- if self.closed:
- raise ValueError("I/O operation on closed file")
-
- buf = ""
- if self.buffer:
- if size is None:
- buf = self.buffer
- self.buffer = ""
- else:
- buf = self.buffer[:size]
- self.buffer = self.buffer[size:]
-
- if size is None:
- buf += self.fileobj.read()
- else:
- buf += self.fileobj.read(size - len(buf))
-
- self.position += len(buf)
- return buf
-
- def readline(self, size=-1):
- """Read one entire line from the file. If size is present
- and non-negative, return a string with at most that
- size, which may be an incomplete line.
- """
- if self.closed:
- raise ValueError("I/O operation on closed file")
-
- if "\n" in self.buffer:
- pos = self.buffer.find("\n") + 1
- else:
- buffers = [self.buffer]
- while True:
- buf = self.fileobj.read(self.blocksize)
- buffers.append(buf)
- if not buf or "\n" in buf:
- self.buffer = "".join(buffers)
- pos = self.buffer.find("\n") + 1
- if pos == 0:
- # no newline found.
- pos = len(self.buffer)
- break
-
- if size != -1:
- pos = min(size, pos)
-
- buf = self.buffer[:pos]
- self.buffer = self.buffer[pos:]
- self.position += len(buf)
- return buf
-
- def readlines(self):
- """Return a list with all remaining lines.
- """
- result = []
- while True:
- line = self.readline()
- if not line: break
- result.append(line)
- return result
-
- def tell(self):
- """Return the current file position.
- """
- if self.closed:
- raise ValueError("I/O operation on closed file")
-
- return self.position
-
- def seek(self, pos, whence=os.SEEK_SET):
- """Seek to a position in the file.
- """
- if self.closed:
- raise ValueError("I/O operation on closed file")
-
- if whence == os.SEEK_SET:
- self.position = min(max(pos, 0), self.size)
- elif whence == os.SEEK_CUR:
- if pos < 0:
- self.position = max(self.position + pos, 0)
- else:
- self.position = min(self.position + pos, self.size)
- elif whence == os.SEEK_END:
- self.position = max(min(self.size + pos, self.size), 0)
- else:
- raise ValueError("Invalid argument")
-
- self.buffer = ""
- self.fileobj.seek(self.position)
-
- def close(self):
- """Close the file object.
- """
- self.closed = True
-
- def __iter__(self):
- """Get an iterator over the file's lines.
- """
- while True:
- line = self.readline()
- if not line:
- break
- yield line
-#class ExFileObject
-
-#------------------
-# Exported Classes
-#------------------
-class TarInfo(object):
- """Informational class which holds the details about an
- archive member given by a tar header block.
- TarInfo objects are returned by TarFile.getmember(),
- TarFile.getmembers() and TarFile.gettarinfo() and are
- usually created internally.
- """
-
- def __init__(self, name=""):
- """Construct a TarInfo object. name is the optional name
- of the member.
- """
- self.name = name # member name
- self.mode = 0644 # file permissions
- self.uid = 0 # user id
- self.gid = 0 # group id
- self.size = 0 # file size
- self.mtime = 0 # modification time
- self.chksum = 0 # header checksum
- self.type = REGTYPE # member type
- self.linkname = "" # link name
- self.uname = "root" # user name
- self.gname = "root" # group name
- self.devmajor = 0 # device major number
- self.devminor = 0 # device minor number
-
- self.offset = 0 # the tar header starts here
- self.offset_data = 0 # the file's data starts here
-
- self.pax_headers = {} # pax header information
-
- # In pax headers the "name" and "linkname" field are called
- # "path" and "linkpath".
- def _getpath(self):
- return self.name
- def _setpath(self, name):
- self.name = name
- path = property(_getpath, _setpath)
-
- def _getlinkpath(self):
- return self.linkname
- def _setlinkpath(self, linkname):
- self.linkname = linkname
- linkpath = property(_getlinkpath, _setlinkpath)
-
- def __repr__(self):
- return "<%s %r at %#x>" % (self.__class__.__name__,self.name,id(self))
-
- def get_info(self, encoding, errors):
- """Return the TarInfo's attributes as a dictionary.
- """
- info = {
- "name": self.name,
- "mode": self.mode & 07777,
- "uid": self.uid,
- "gid": self.gid,
- "size": self.size,
- "mtime": self.mtime,
- "chksum": self.chksum,
- "type": self.type,
- "linkname": self.linkname,
- "uname": self.uname,
- "gname": self.gname,
- "devmajor": self.devmajor,
- "devminor": self.devminor
- }
-
- if info["type"] == DIRTYPE and not info["name"].endswith("/"):
- info["name"] += "/"
-
- for key in ("name", "linkname", "uname", "gname"):
- if type(info[key]) is unicode:
- info[key] = info[key].encode(encoding, errors)
-
- return info
-
- def tobuf(self, format=DEFAULT_FORMAT, encoding=ENCODING, errors="strict"):
- """Return a tar header as a string of 512 byte blocks.
- """
- info = self.get_info(encoding, errors)
-
- if format == USTAR_FORMAT:
- return self.create_ustar_header(info)
- elif format == GNU_FORMAT:
- return self.create_gnu_header(info)
- elif format == PAX_FORMAT:
- return self.create_pax_header(info, encoding, errors)
- else:
- raise ValueError("invalid format")
-
- def create_ustar_header(self, info):
- """Return the object as a ustar header block.
- """
- info["magic"] = POSIX_MAGIC
-
- if len(info["linkname"]) > LENGTH_LINK:
- raise ValueError("linkname is too long")
-
- if len(info["name"]) > LENGTH_NAME:
- info["prefix"], info["name"] = self._posix_split_name(info["name"])
-
- return self._create_header(info, USTAR_FORMAT)
-
- def create_gnu_header(self, info):
- """Return the object as a GNU header block sequence.
- """
- info["magic"] = GNU_MAGIC
-
- buf = ""
- if len(info["linkname"]) > LENGTH_LINK:
- buf += self._create_gnu_long_header(info["linkname"], GNUTYPE_LONGLINK)
-
- if len(info["name"]) > LENGTH_NAME:
- buf += self._create_gnu_long_header(info["name"], GNUTYPE_LONGNAME)
-
- return buf + self._create_header(info, GNU_FORMAT)
-
- def create_pax_header(self, info, encoding, errors):
- """Return the object as a ustar header block. If it cannot be
- represented this way, prepend a pax extended header sequence
- with supplement information.
- """
- info["magic"] = POSIX_MAGIC
- pax_headers = self.pax_headers.copy()
-
- # Test string fields for values that exceed the field length or cannot
- # be represented in ASCII encoding.
- for name, hname, length in (
- ("name", "path", LENGTH_NAME), ("linkname", "linkpath", LENGTH_LINK),
- ("uname", "uname", 32), ("gname", "gname", 32)):
-
- if hname in pax_headers:
- # The pax header has priority.
- continue
-
- val = info[name].decode(encoding, errors)
-
- # Try to encode the string as ASCII.
- try:
- val.encode("ascii")
- except UnicodeEncodeError:
- pax_headers[hname] = val
- continue
-
- if len(info[name]) > length:
- pax_headers[hname] = val
-
- # Test number fields for values that exceed the field limit or values
- # that like to be stored as float.
- for name, digits in (("uid", 8), ("gid", 8), ("size", 12), ("mtime", 12)):
- if name in pax_headers:
- # The pax header has priority. Avoid overflow.
- info[name] = 0
- continue
-
- val = info[name]
- if not 0 <= val < 8 ** (digits - 1) or isinstance(val, float):
- pax_headers[name] = unicode(val)
- info[name] = 0
-
- # Create a pax extended header if necessary.
- if pax_headers:
- buf = self._create_pax_generic_header(pax_headers)
- else:
- buf = ""
-
- return buf + self._create_header(info, USTAR_FORMAT)
-
- @classmethod
- def create_pax_global_header(cls, pax_headers):
- """Return the object as a pax global header block sequence.
- """
- return cls._create_pax_generic_header(pax_headers, type=XGLTYPE)
-
- def _posix_split_name(self, name):
- """Split a name longer than 100 chars into a prefix
- and a name part.
- """
- prefix = name[:LENGTH_PREFIX + 1]
- while prefix and prefix[-1] != "/":
- prefix = prefix[:-1]
-
- name = name[len(prefix):]
- prefix = prefix[:-1]
-
- if not prefix or len(name) > LENGTH_NAME:
- raise ValueError("name is too long")
- return prefix, name
-
- @staticmethod
- def _create_header(info, format):
- """Return a header block. info is a dictionary with file
- information, format must be one of the *_FORMAT constants.
- """
- parts = [
- stn(info.get("name", ""), 100),
- itn(info.get("mode", 0) & 07777, 8, format),
- itn(info.get("uid", 0), 8, format),
- itn(info.get("gid", 0), 8, format),
- itn(info.get("size", 0), 12, format),
- itn(info.get("mtime", 0), 12, format),
- " ", # checksum field
- info.get("type", REGTYPE),
- stn(info.get("linkname", ""), 100),
- stn(info.get("magic", POSIX_MAGIC), 8),
- stn(info.get("uname", "root"), 32),
- stn(info.get("gname", "root"), 32),
- itn(info.get("devmajor", 0), 8, format),
- itn(info.get("devminor", 0), 8, format),
- stn(info.get("prefix", ""), 155)
- ]
-
- buf = struct.pack("%ds" % BLOCKSIZE, "".join(parts))
- chksum = calc_chksums(buf[-BLOCKSIZE:])[0]
- buf = buf[:-364] + "%06o\0" % chksum + buf[-357:]
- return buf
-
- @staticmethod
- def _create_payload(payload):
- """Return the string payload filled with zero bytes
- up to the next 512 byte border.
- """
- blocks, remainder = divmod(len(payload), BLOCKSIZE)
- if remainder > 0:
- payload += (BLOCKSIZE - remainder) * NUL
- return payload
-
- @classmethod
- def _create_gnu_long_header(cls, name, type):
- """Return a GNUTYPE_LONGNAME or GNUTYPE_LONGLINK sequence
- for name.
- """
- name += NUL
-
- info = {}
- info["name"] = "././@LongLink"
- info["type"] = type
- info["size"] = len(name)
- info["magic"] = GNU_MAGIC
-
- # create extended header + name blocks.
- return cls._create_header(info, USTAR_FORMAT) + \
- cls._create_payload(name)
-
- @classmethod
- def _create_pax_generic_header(cls, pax_headers, type=XHDTYPE):
- """Return a POSIX.1-2001 extended or global header sequence
- that contains a list of keyword, value pairs. The values
- must be unicode objects.
- """
- records = []
- for keyword, value in pax_headers.iteritems():
- keyword = keyword.encode("utf8")
- value = value.encode("utf8")
- l = len(keyword) + len(value) + 3 # ' ' + '=' + '\n'
- n = p = 0
- while True:
- n = l + len(str(p))
- if n == p:
- break
- p = n
- records.append("%d %s=%s\n" % (p, keyword, value))
- records = "".join(records)
-
- # We use a hardcoded "././@PaxHeader" name like star does
- # instead of the one that POSIX recommends.
- info = {}
- info["name"] = "././@PaxHeader"
- info["type"] = type
- info["size"] = len(records)
- info["magic"] = POSIX_MAGIC
-
- # Create pax header + record blocks.
- return cls._create_header(info, USTAR_FORMAT) + \
- cls._create_payload(records)
-
- @classmethod
- def frombuf(cls, buf):
- """Construct a TarInfo object from a 512 byte string buffer.
- """
- if len(buf) == 0:
- raise EmptyHeaderError("empty header")
- if len(buf) != BLOCKSIZE:
- raise TruncatedHeaderError("truncated header")
- if buf.count(NUL) == BLOCKSIZE:
- raise EOFHeaderError("end of file header")
-
- chksum = nti(buf[148:156])
- if chksum not in calc_chksums(buf):
- raise InvalidHeaderError("bad checksum")
-
- obj = cls()
- obj.buf = buf
- obj.name = nts(buf[0:100])
- obj.mode = nti(buf[100:108])
- obj.uid = nti(buf[108:116])
- obj.gid = nti(buf[116:124])
- obj.size = nti(buf[124:136])
- obj.mtime = nti(buf[136:148])
- obj.chksum = chksum
- obj.type = buf[156:157]
- obj.linkname = nts(buf[157:257])
- obj.uname = nts(buf[265:297])
- obj.gname = nts(buf[297:329])
- obj.devmajor = nti(buf[329:337])
- obj.devminor = nti(buf[337:345])
- prefix = nts(buf[345:500])
-
- # Old V7 tar format represents a directory as a regular
- # file with a trailing slash.
- if obj.type == AREGTYPE and obj.name.endswith("/"):
- obj.type = DIRTYPE
-
- # Remove redundant slashes from directories.
- if obj.isdir():
- obj.name = obj.name.rstrip("/")
-
- # Reconstruct a ustar longname.
- if prefix and obj.type not in GNU_TYPES:
- obj.name = prefix + "/" + obj.name
- return obj
-
- @classmethod
- def fromtarfile(cls, tarfile):
- """Return the next TarInfo object from TarFile object
- tarfile.
- """
- buf = tarfile.fileobj.read(BLOCKSIZE)
- obj = cls.frombuf(buf)
- obj.offset = tarfile.fileobj.tell() - BLOCKSIZE
- return obj._proc_member(tarfile)
-
- #--------------------------------------------------------------------------
- # The following are methods that are called depending on the type of a
- # member. The entry point is _proc_member() which can be overridden in a
- # subclass to add custom _proc_*() methods. A _proc_*() method MUST
- # implement the following
- # operations:
- # 1. Set self.offset_data to the position where the data blocks begin,
- # if there is data that follows.
- # 2. Set tarfile.offset to the position where the next member's header will
- # begin.
- # 3. Return self or another valid TarInfo object.
- def _proc_member(self, tarfile):
- """Choose the right processing method depending on
- the type and call it.
- """
- if self.type in (GNUTYPE_LONGNAME, GNUTYPE_LONGLINK):
- return self._proc_gnulong(tarfile)
- elif self.type == GNUTYPE_SPARSE:
- return self._proc_sparse(tarfile)
- elif self.type in (XHDTYPE, XGLTYPE, SOLARIS_XHDTYPE):
- return self._proc_pax(tarfile)
- else:
- return self._proc_builtin(tarfile)
-
- def _proc_builtin(self, tarfile):
- """Process a builtin type or an unknown type which
- will be treated as a regular file.
- """
- self.offset_data = tarfile.fileobj.tell()
- offset = self.offset_data
- if self.isreg() or self.type not in SUPPORTED_TYPES:
- # Skip the following data blocks.
- offset += self._block(self.size)
- tarfile.offset = offset
-
- # Patch the TarInfo object with saved global
- # header information.
- self._apply_pax_info(tarfile.pax_headers, tarfile.encoding, tarfile.errors)
-
- return self
-
- def _proc_gnulong(self, tarfile):
- """Process the blocks that hold a GNU longname
- or longlink member.
- """
- buf = tarfile.fileobj.read(self._block(self.size))
-
- # Fetch the next header and process it.
- try:
- next = self.fromtarfile(tarfile)
- except HeaderError:
- raise SubsequentHeaderError("missing or bad subsequent header")
-
- # Patch the TarInfo object from the next header with
- # the longname information.
- next.offset = self.offset
- if self.type == GNUTYPE_LONGNAME:
- next.name = nts(buf)
- elif self.type == GNUTYPE_LONGLINK:
- next.linkname = nts(buf)
-
- return next
-
- def _proc_sparse(self, tarfile):
- """Process a GNU sparse header plus extra headers.
- """
- buf = self.buf
- sp = _ringbuffer()
- pos = 386
- lastpos = 0L
- realpos = 0L
- # There are 4 possible sparse structs in the
- # first header.
- for i in xrange(4):
- try:
- offset = nti(buf[pos:pos + 12])
- numbytes = nti(buf[pos + 12:pos + 24])
- except ValueError:
- break
- if offset > lastpos:
- sp.append(_hole(lastpos, offset - lastpos))
- sp.append(_data(offset, numbytes, realpos))
- realpos += numbytes
- lastpos = offset + numbytes
- pos += 24
-
- isextended = ord(buf[482])
- origsize = nti(buf[483:495])
-
- # If the isextended flag is given,
- # there are extra headers to process.
- while isextended == 1:
- buf = tarfile.fileobj.read(BLOCKSIZE)
- pos = 0
- for i in xrange(21):
- try:
- offset = nti(buf[pos:pos + 12])
- numbytes = nti(buf[pos + 12:pos + 24])
- except ValueError:
- break
- if offset > lastpos:
- sp.append(_hole(lastpos, offset - lastpos))
- sp.append(_data(offset, numbytes, realpos))
- realpos += numbytes
- lastpos = offset + numbytes
- pos += 24
- isextended = ord(buf[504])
-
- if lastpos < origsize:
- sp.append(_hole(lastpos, origsize - lastpos))
-
- self.sparse = sp
-
- self.offset_data = tarfile.fileobj.tell()
- tarfile.offset = self.offset_data + self._block(self.size)
- self.size = origsize
-
- return self
-
- def _proc_pax(self, tarfile):
- """Process an extended or global header as described in
- POSIX.1-2001.
- """
- # Read the header information.
- buf = tarfile.fileobj.read(self._block(self.size))
-
- # A pax header stores supplemental information for either
- # the following file (extended) or all following files
- # (global).
- if self.type == XGLTYPE:
- pax_headers = tarfile.pax_headers
- else:
- pax_headers = tarfile.pax_headers.copy()
-
- # Parse pax header information. A record looks like that:
- # "%d %s=%s\n" % (length, keyword, value). length is the size
- # of the complete record including the length field itself and
- # the newline. keyword and value are both UTF-8 encoded strings.
- regex = re.compile(r"(\d+) ([^=]+)=", re.U)
- pos = 0
- while True:
- match = regex.match(buf, pos)
- if not match:
- break
-
- length, keyword = match.groups()
- length = int(length)
- value = buf[match.end(2) + 1:match.start(1) + length - 1]
-
- keyword = keyword.decode("utf8")
- value = value.decode("utf8")
-
- pax_headers[keyword] = value
- pos += length
-
- # Fetch the next header.
- try:
- next = self.fromtarfile(tarfile)
- except HeaderError:
- raise SubsequentHeaderError("missing or bad subsequent header")
-
- if self.type in (XHDTYPE, SOLARIS_XHDTYPE):
- # Patch the TarInfo object with the extended header info.
- next._apply_pax_info(pax_headers, tarfile.encoding, tarfile.errors)
- next.offset = self.offset
-
- if "size" in pax_headers:
- # If the extended header replaces the size field,
- # we need to recalculate the offset where the next
- # header starts.
- offset = next.offset_data
- if next.isreg() or next.type not in SUPPORTED_TYPES:
- offset += next._block(next.size)
- tarfile.offset = offset
-
- return next
-
- def _apply_pax_info(self, pax_headers, encoding, errors):
- """Replace fields with supplemental information from a previous
- pax extended or global header.
- """
- for keyword, value in pax_headers.iteritems():
- if keyword not in PAX_FIELDS:
- continue
-
- if keyword == "path":
- value = value.rstrip("/")
-
- if keyword in PAX_NUMBER_FIELDS:
- try:
- value = PAX_NUMBER_FIELDS[keyword](value)
- except ValueError:
- value = 0
- else:
- value = uts(value, encoding, errors)
-
- setattr(self, keyword, value)
-
- self.pax_headers = pax_headers.copy()
-
- def _block(self, count):
- """Round up a byte count by BLOCKSIZE and return it,
- e.g. _block(834) => 1024.
- """
- blocks, remainder = divmod(count, BLOCKSIZE)
- if remainder:
- blocks += 1
- return blocks * BLOCKSIZE
-
- def isreg(self):
- return self.type in REGULAR_TYPES
- def isfile(self):
- return self.isreg()
- def isdir(self):
- return self.type == DIRTYPE
- def issym(self):
- return self.type == SYMTYPE
- def islnk(self):
- return self.type == LNKTYPE
- def ischr(self):
- return self.type == CHRTYPE
- def isblk(self):
- return self.type == BLKTYPE
- def isfifo(self):
- return self.type == FIFOTYPE
- def issparse(self):
- return self.type == GNUTYPE_SPARSE
- def isdev(self):
- return self.type in (CHRTYPE, BLKTYPE, FIFOTYPE)
-# class TarInfo
-
-class TarFile(object):
- """The TarFile Class provides an interface to tar archives.
- """
-
- debug = 0 # May be set from 0 (no msgs) to 3 (all msgs)
-
- dereference = False # If true, add content of linked file to the
- # tar file, else the link.
-
- ignore_zeros = False # If true, skips empty or invalid blocks and
- # continues processing.
-
- errorlevel = 1 # If 0, fatal errors only appear in debug
- # messages (if debug >= 0). If > 0, errors
- # are passed to the caller as exceptions.
-
- format = DEFAULT_FORMAT # The format to use when creating an archive.
-
- encoding = ENCODING # Encoding for 8-bit character strings.
-
- errors = None # Error handler for unicode conversion.
-
- tarinfo = TarInfo # The default TarInfo class to use.
-
- fileobject = ExFileObject # The default ExFileObject class to use.
-
- def __init__(self, name=None, mode="r", fileobj=None, format=None,
- tarinfo=None, dereference=None, ignore_zeros=None, encoding=None,
- errors=None, pax_headers=None, debug=None, errorlevel=None):
- """Open an (uncompressed) tar archive `name'. `mode' is either 'r' to
- read from an existing archive, 'a' to append data to an existing
- file or 'w' to create a new file overwriting an existing one. `mode'
- defaults to 'r'.
- If `fileobj' is given, it is used for reading or writing data. If it
- can be determined, `mode' is overridden by `fileobj's mode.
- `fileobj' is not closed, when TarFile is closed.
- """
- if len(mode) > 1 or mode not in "raw":
- raise ValueError("mode must be 'r', 'a' or 'w'")
- self.mode = mode
- self._mode = {"r": "rb", "a": "r+b", "w": "wb"}[mode]
-
- if not fileobj:
- if self.mode == "a" and not os.path.exists(name):
- # Create nonexistent files in append mode.
- self.mode = "w"
- self._mode = "wb"
- fileobj = bltn_open(name, self._mode)
- self._extfileobj = False
- else:
- if name is None and hasattr(fileobj, "name"):
- name = fileobj.name
- if hasattr(fileobj, "mode"):
- self._mode = fileobj.mode
- self._extfileobj = True
- if name:
- self.name = os.path.abspath(name)
- else:
- self.name = None
- self.fileobj = fileobj
-
- # Init attributes.
- if format is not None:
- self.format = format
- if tarinfo is not None:
- self.tarinfo = tarinfo
- if dereference is not None:
- self.dereference = dereference
- if ignore_zeros is not None:
- self.ignore_zeros = ignore_zeros
- if encoding is not None:
- self.encoding = encoding
-
- if errors is not None:
- self.errors = errors
- elif mode == "r":
- self.errors = "utf-8"
- else:
- self.errors = "strict"
-
- if pax_headers is not None and self.format == PAX_FORMAT:
- self.pax_headers = pax_headers
- else:
- self.pax_headers = {}
-
- if debug is not None:
- self.debug = debug
- if errorlevel is not None:
- self.errorlevel = errorlevel
-
- # Init datastructures.
- self.closed = False
- self.members = [] # list of members as TarInfo objects
- self._loaded = False # flag if all members have been read
- self.offset = self.fileobj.tell()
- # current position in the archive file
- self.inodes = {} # dictionary caching the inodes of
- # archive members already added
-
- try:
- if self.mode == "r":
- self.firstmember = None
- self.firstmember = self.next()
-
- if self.mode == "a":
- # Move to the end of the archive,
- # before the first empty block.
- while True:
- self.fileobj.seek(self.offset)
- try:
- tarinfo = self.tarinfo.fromtarfile(self)
- self.members.append(tarinfo)
- except EOFHeaderError:
- self.fileobj.seek(self.offset)
- break
- except HeaderError, e:
- raise ReadError(str(e))
-
- if self.mode in "aw":
- self._loaded = True
-
- if self.pax_headers:
- buf = self.tarinfo.create_pax_global_header(self.pax_headers.copy())
- self.fileobj.write(buf)
- self.offset += len(buf)
- except:
- if not self._extfileobj:
- self.fileobj.close()
- self.closed = True
- raise
-
- def _getposix(self):
- return self.format == USTAR_FORMAT
- def _setposix(self, value):
- import warnings
- warnings.warn("use the format attribute instead", DeprecationWarning,
- 2)
- if value:
- self.format = USTAR_FORMAT
- else:
- self.format = GNU_FORMAT
- posix = property(_getposix, _setposix)
-
- #--------------------------------------------------------------------------
- # Below are the classmethods which act as alternate constructors to the
- # TarFile class. The open() method is the only one that is needed for
- # public use; it is the "super"-constructor and is able to select an
- # adequate "sub"-constructor for a particular compression using the mapping
- # from OPEN_METH.
- #
- # This concept allows one to subclass TarFile without losing the comfort of
- # the super-constructor. A sub-constructor is registered and made available
- # by adding it to the mapping in OPEN_METH.
-
- @classmethod
- def open(cls, name=None, mode="r", fileobj=None, bufsize=RECORDSIZE, **kwargs):
- """Open a tar archive for reading, writing or appending. Return
- an appropriate TarFile class.
-
- mode:
- 'r' or 'r:*' open for reading with transparent compression
- 'r:' open for reading exclusively uncompressed
- 'r:gz' open for reading with gzip compression
- 'r:bz2' open for reading with bzip2 compression
- 'a' or 'a:' open for appending, creating the file if necessary
- 'w' or 'w:' open for writing without compression
- 'w:gz' open for writing with gzip compression
- 'w:bz2' open for writing with bzip2 compression
-
- 'r|*' open a stream of tar blocks with transparent compression
- 'r|' open an uncompressed stream of tar blocks for reading
- 'r|gz' open a gzip compressed stream of tar blocks
- 'r|bz2' open a bzip2 compressed stream of tar blocks
- 'w|' open an uncompressed stream for writing
- 'w|gz' open a gzip compressed stream for writing
- 'w|bz2' open a bzip2 compressed stream for writing
- """
-
- if not name and not fileobj:
- raise ValueError("nothing to open")
-
- if mode in ("r", "r:*"):
- # Find out which *open() is appropriate for opening the file.
- for comptype in cls.OPEN_METH:
- func = getattr(cls, cls.OPEN_METH[comptype])
- if fileobj is not None:
- saved_pos = fileobj.tell()
- try:
- return func(name, "r", fileobj, **kwargs)
- except (ReadError, CompressionError), e:
- if fileobj is not None:
- fileobj.seek(saved_pos)
- continue
- raise ReadError("file could not be opened successfully")
-
- elif ":" in mode:
- filemode, comptype = mode.split(":", 1)
- filemode = filemode or "r"
- comptype = comptype or "tar"
-
- # Select the *open() function according to
- # given compression.
- if comptype in cls.OPEN_METH:
- func = getattr(cls, cls.OPEN_METH[comptype])
- else:
- raise CompressionError("unknown compression type %r" % comptype)
- return func(name, filemode, fileobj, **kwargs)
-
- elif "|" in mode:
- filemode, comptype = mode.split("|", 1)
- filemode = filemode or "r"
- comptype = comptype or "tar"
-
- if filemode not in "rw":
- raise ValueError("mode must be 'r' or 'w'")
-
- t = cls(name, filemode,
- _Stream(name, filemode, comptype, fileobj, bufsize),
- **kwargs)
- t._extfileobj = False
- return t
-
- elif mode in "aw":
- return cls.taropen(name, mode, fileobj, **kwargs)
-
- raise ValueError("undiscernible mode")
-
- @classmethod
- def taropen(cls, name, mode="r", fileobj=None, **kwargs):
- """Open uncompressed tar archive name for reading or writing.
- """
- if len(mode) > 1 or mode not in "raw":
- raise ValueError("mode must be 'r', 'a' or 'w'")
- return cls(name, mode, fileobj, **kwargs)
-
- @classmethod
- def gzopen(cls, name, mode="r", fileobj=None, compresslevel=9, **kwargs):
- """Open gzip compressed tar archive name for reading or writing.
- Appending is not allowed.
- """
- if len(mode) > 1 or mode not in "rw":
- raise ValueError("mode must be 'r' or 'w'")
-
- try:
- import gzip
- gzip.GzipFile
- except (ImportError, AttributeError):
- raise CompressionError("gzip module is not available")
-
- if fileobj is None:
- fileobj = bltn_open(name, mode + "b")
-
- try:
- t = cls.taropen(name, mode,
- gzip.GzipFile(name, mode, compresslevel, fileobj),
- **kwargs)
- except IOError:
- raise ReadError("not a gzip file")
- t._extfileobj = False
- return t
-
- @classmethod
- def bz2open(cls, name, mode="r", fileobj=None, compresslevel=9, **kwargs):
- """Open bzip2 compressed tar archive name for reading or writing.
- Appending is not allowed.
- """
- if len(mode) > 1 or mode not in "rw":
- raise ValueError("mode must be 'r' or 'w'.")
-
- try:
- import bz2
- except ImportError:
- raise CompressionError("bz2 module is not available")
-
- if fileobj is not None:
- fileobj = _BZ2Proxy(fileobj, mode)
- else:
- fileobj = bz2.BZ2File(name, mode, compresslevel=compresslevel)
-
- try:
- t = cls.taropen(name, mode, fileobj, **kwargs)
- except (IOError, EOFError):
- raise ReadError("not a bzip2 file")
- t._extfileobj = False
- return t
-
- # All *open() methods are registered here.
- OPEN_METH = {
- "tar": "taropen", # uncompressed tar
- "gz": "gzopen", # gzip compressed tar
- "bz2": "bz2open" # bzip2 compressed tar
- }
-
- #--------------------------------------------------------------------------
- # The public methods which TarFile provides:
-
- def close(self):
- """Close the TarFile. In write-mode, two finishing zero blocks are
- appended to the archive.
- """
- if self.closed:
- return
-
- if self.mode in "aw":
- self.fileobj.write(NUL * (BLOCKSIZE * 2))
- self.offset += (BLOCKSIZE * 2)
- # fill up the end with zero-blocks
- # (like option -b20 for tar does)
- blocks, remainder = divmod(self.offset, RECORDSIZE)
- if remainder > 0:
- self.fileobj.write(NUL * (RECORDSIZE - remainder))
-
- if not self._extfileobj:
- self.fileobj.close()
- self.closed = True
-
- def getmember(self, name):
- """Return a TarInfo object for member `name'. If `name' can not be
- found in the archive, KeyError is raised. If a member occurs more
- than once in the archive, its last occurrence is assumed to be the
- most up-to-date version.
- """
- tarinfo = self._getmember(name)
- if tarinfo is None:
- raise KeyError("filename %r not found" % name)
- return tarinfo
-
- def getmembers(self):
- """Return the members of the archive as a list of TarInfo objects. The
- list has the same order as the members in the archive.
- """
- self._check()
- if not self._loaded: # if we want to obtain a list of
- self._load() # all members, we first have to
- # scan the whole archive.
- return self.members
-
- def getnames(self):
- """Return the members of the archive as a list of their names. It has
- the same order as the list returned by getmembers().
- """
- return [tarinfo.name for tarinfo in self.getmembers()]
-
- def gettarinfo(self, name=None, arcname=None, fileobj=None):
- """Create a TarInfo object for either the file `name' or the file
- object `fileobj' (using os.fstat on its file descriptor). You can
- modify some of the TarInfo's attributes before you add it using
- addfile(). If given, `arcname' specifies an alternative name for the
- file in the archive.
- """
- self._check("aw")
-
- # When fileobj is given, replace name by
- # fileobj's real name.
- if fileobj is not None:
- name = fileobj.name
-
- # Building the name of the member in the archive.
- # Backward slashes are converted to forward slashes,
- # Absolute paths are turned to relative paths.
- if arcname is None:
- arcname = name
- drv, arcname = os.path.splitdrive(arcname)
- arcname = arcname.replace(os.sep, "/")
- arcname = arcname.lstrip("/")
-
- # Now, fill the TarInfo object with
- # information specific for the file.
- tarinfo = self.tarinfo()
- tarinfo.tarfile = self
-
- # Use os.stat or os.lstat, depending on platform
- # and if symlinks shall be resolved.
- if fileobj is None:
- if hasattr(os, "lstat") and not self.dereference:
- statres = os.lstat(name)
- else:
- statres = os.stat(name)
- else:
- statres = os.fstat(fileobj.fileno())
- linkname = ""
-
- stmd = statres.st_mode
- if stat.S_ISREG(stmd):
- inode = (statres.st_ino, statres.st_dev)
- if not self.dereference and statres.st_nlink > 1 and \
- inode in self.inodes and arcname != self.inodes[inode]:
- # Is it a hardlink to an already
- # archived file?
- type = LNKTYPE
- linkname = self.inodes[inode]
- else:
- # The inode is added only if its valid.
- # For win32 it is always 0.
- type = REGTYPE
- if inode[0]:
- self.inodes[inode] = arcname
- elif stat.S_ISDIR(stmd):
- type = DIRTYPE
- elif stat.S_ISFIFO(stmd):
- type = FIFOTYPE
- elif stat.S_ISLNK(stmd):
- type = SYMTYPE
- linkname = os.readlink(name)
- elif stat.S_ISCHR(stmd):
- type = CHRTYPE
- elif stat.S_ISBLK(stmd):
- type = BLKTYPE
- else:
- return None
-
- # Fill the TarInfo object with all
- # information we can get.
- tarinfo.name = arcname
- tarinfo.mode = stmd
- tarinfo.uid = statres.st_uid
- tarinfo.gid = statres.st_gid
- if stat.S_ISREG(stmd):
- tarinfo.size = statres.st_size
- else:
- tarinfo.size = 0L
- tarinfo.mtime = statres.st_mtime
- tarinfo.type = type
- tarinfo.linkname = linkname
- if pwd:
- try:
- tarinfo.uname = pwd.getpwuid(tarinfo.uid)[0]
- except KeyError:
- pass
- if grp:
- try:
- tarinfo.gname = grp.getgrgid(tarinfo.gid)[0]
- except KeyError:
- pass
-
- if type in (CHRTYPE, BLKTYPE):
- if hasattr(os, "major") and hasattr(os, "minor"):
- tarinfo.devmajor = os.major(statres.st_rdev)
- tarinfo.devminor = os.minor(statres.st_rdev)
- return tarinfo
-
- def list(self, verbose=True):
- """Print a table of contents to sys.stdout. If `verbose' is False, only
- the names of the members are printed. If it is True, an `ls -l'-like
- output is produced.
- """
- self._check()
-
- for tarinfo in self:
- if verbose:
- print filemode(tarinfo.mode),
- print "%s/%s" % (tarinfo.uname or tarinfo.uid,
- tarinfo.gname or tarinfo.gid),
- if tarinfo.ischr() or tarinfo.isblk():
- print "%10s" % ("%d,%d" \
- % (tarinfo.devmajor, tarinfo.devminor)),
- else:
- print "%10d" % tarinfo.size,
- print "%d-%02d-%02d %02d:%02d:%02d" \
- % time.localtime(tarinfo.mtime)[:6],
-
- if tarinfo.isdir():
- sep = "/"
- else:
- sep = ""
- print tarinfo.name + (sep),
-
- if verbose:
- if tarinfo.issym():
- print "->", tarinfo.linkname,
- if tarinfo.islnk():
- print "link to", tarinfo.linkname,
- print
-
- def add(self, name, arcname=None, recursive=True, exclude=None, filter=None):
- """Add the file `name' to the archive. `name' may be any type of file
- (directory, fifo, symbolic link, etc.). If given, `arcname'
- specifies an alternative name for the file in the archive.
- Directories are added recursively by default. This can be avoided by
- setting `recursive' to False. `exclude' is a function that should
- return True for each filename to be excluded. `filter' is a function
- that expects a TarInfo object argument and returns the changed
- TarInfo object, if it returns None the TarInfo object will be
- excluded from the archive.
- """
- self._check("aw")
-
- if arcname is None:
- arcname = name
-
- # Exclude pathnames.
- if exclude is not None:
- import warnings
- warnings.warn("use the filter argument instead",
- DeprecationWarning, 2)
- if exclude(name):
- self._dbg(2, "tarfile: Excluded %r" % name)
- return
-
- # Skip if somebody tries to archive the archive...
- if self.name is not None and os.path.abspath(name) == self.name:
- self._dbg(2, "tarfile: Skipped %r" % name)
- return
-
- self._dbg(1, name)
-
- # Create a TarInfo object from the file.
- tarinfo = self.gettarinfo(name, arcname)
-
- if tarinfo is None:
- self._dbg(1, "tarfile: Unsupported type %r" % name)
- return
-
- # Change or exclude the TarInfo object.
- if filter is not None:
- tarinfo = filter(tarinfo)
- if tarinfo is None:
- self._dbg(2, "tarfile: Excluded %r" % name)
- return
-
- # Append the tar header and data to the archive.
- if tarinfo.isreg():
- f = bltn_open(name, "rb")
- try:
- self.addfile(tarinfo, f)
- finally:
- f.close()
-
- elif tarinfo.isdir():
- self.addfile(tarinfo)
- if recursive:
- for f in os.listdir(name):
- self.add(os.path.join(name, f), os.path.join(arcname, f),
- recursive, exclude, filter)
-
- else:
- self.addfile(tarinfo)
-
- def addfile(self, tarinfo, fileobj=None):
- """Add the TarInfo object `tarinfo' to the archive. If `fileobj' is
- given, tarinfo.size bytes are read from it and added to the archive.
- You can create TarInfo objects using gettarinfo().
- On Windows platforms, `fileobj' should always be opened with mode
- 'rb' to avoid irritation about the file size.
- """
- self._check("aw")
-
- tarinfo = copy.copy(tarinfo)
-
- buf = tarinfo.tobuf(self.format, self.encoding, self.errors)
- self.fileobj.write(buf)
- self.offset += len(buf)
-
- # If there's data to follow, append it.
- if fileobj is not None:
- copyfileobj(fileobj, self.fileobj, tarinfo.size)
- blocks, remainder = divmod(tarinfo.size, BLOCKSIZE)
- if remainder > 0:
- self.fileobj.write(NUL * (BLOCKSIZE - remainder))
- blocks += 1
- self.offset += blocks * BLOCKSIZE
-
- self.members.append(tarinfo)
-
- 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().
- """
- 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 = 0700
- self.extract(tarinfo, path)
-
- # Reverse sort directories.
- directories.sort(key=operator.attrgetter('name'))
- directories.reverse()
-
- # 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:
- if self.errorlevel > 1:
- raise
- else:
- self._dbg(1, "tarfile: %s" % e)
-
- def extract(self, member, path=""):
- """Extract a member from the archive to the current working directory,
- using its full name. Its file information is extracted as accurately
- as possible. `member' may be a filename or a TarInfo object. You can
- specify a different directory using `path'.
- """
- self._check("r")
-
- if isinstance(member, basestring):
- tarinfo = self.getmember(member)
- else:
- tarinfo = member
-
- # Prepare the link target for makelink().
- if tarinfo.islnk():
- tarinfo._link_target = os.path.join(path, tarinfo.linkname)
-
- try:
- self._extract_member(tarinfo, os.path.join(path, tarinfo.name))
- except EnvironmentError, e:
- if self.errorlevel > 0:
- raise
- else:
- if e.filename is None:
- self._dbg(1, "tarfile: %s" % e.strerror)
- else:
- self._dbg(1, "tarfile: %s %r" % (e.strerror, e.filename))
- except ExtractError, e:
- if self.errorlevel > 1:
- raise
- else:
- self._dbg(1, "tarfile: %s" % e)
-
- def extractfile(self, member):
- """Extract a member from the archive as a file object. `member' may be
- a filename or a TarInfo object. If `member' is a regular file, a
- file-like object is returned. If `member' is a link, a file-like
- object is constructed from the link's target. If `member' is none of
- the above, None is returned.
- The file-like object is read-only and provides the following
- methods: read(), readline(), readlines(), seek() and tell()
- """
- self._check("r")
-
- if isinstance(member, basestring):
- tarinfo = self.getmember(member)
- else:
- tarinfo = member
-
- if tarinfo.isreg():
- return self.fileobject(self, tarinfo)
-
- elif tarinfo.type not in SUPPORTED_TYPES:
- # If a member's type is unknown, it is treated as a
- # regular file.
- return self.fileobject(self, tarinfo)
-
- elif tarinfo.islnk() or tarinfo.issym():
- if isinstance(self.fileobj, _Stream):
- # A small but ugly workaround for the case that someone tries
- # to extract a (sym)link as a file-object from a non-seekable
- # stream of tar blocks.
- raise StreamError("cannot extract (sym)link as file object")
- else:
- # A (sym)link's file object is its target's file object.
- return self.extractfile(self._getmember(tarinfo.linkname,
- tarinfo))
- else:
- # If there's no data associated with the member (directory, chrdev,
- # blkdev, etc.), return None instead of a file object.
- return None
-
- def _extract_member(self, tarinfo, targetpath):
- """Extract the TarInfo object tarinfo to a physical
- file called targetpath.
- """
- # Fetch the TarInfo object for the given name
- # and build the destination pathname, replacing
- # forward slashes to platform specific separators.
- targetpath = targetpath.rstrip("/")
- targetpath = targetpath.replace("/", os.sep)
-
- # Create all upper directories.
- upperdirs = os.path.dirname(targetpath)
- if upperdirs and not os.path.exists(upperdirs):
- # Create directories that are not part of the archive with
- # default permissions.
- os.makedirs(upperdirs)
-
- if tarinfo.islnk() or tarinfo.issym():
- self._dbg(1, "%s -> %s" % (tarinfo.name, tarinfo.linkname))
- else:
- self._dbg(1, tarinfo.name)
-
- if tarinfo.isreg():
- self.makefile(tarinfo, targetpath)
- elif tarinfo.isdir():
- self.makedir(tarinfo, targetpath)
- elif tarinfo.isfifo():
- self.makefifo(tarinfo, targetpath)
- elif tarinfo.ischr() or tarinfo.isblk():
- self.makedev(tarinfo, targetpath)
- elif tarinfo.islnk() or tarinfo.issym():
- self.makelink(tarinfo, targetpath)
- elif tarinfo.type not in SUPPORTED_TYPES:
- self.makeunknown(tarinfo, targetpath)
- else:
- self.makefile(tarinfo, targetpath)
-
- self.chown(tarinfo, targetpath)
- if not tarinfo.issym():
- self.chmod(tarinfo, targetpath)
- self.utime(tarinfo, targetpath)
-
- #--------------------------------------------------------------------------
- # Below are the different file methods. They are called via
- # _extract_member() when extract() is called. They can be replaced in a
- # subclass to implement other functionality.
-
- def makedir(self, tarinfo, targetpath):
- """Make a directory called targetpath.
- """
- try:
- # Use a safe mode for the directory, the real mode is set
- # later in _extract_member().
- os.mkdir(targetpath, 0700)
- except EnvironmentError, e:
- if e.errno != errno.EEXIST:
- raise
-
- def makefile(self, tarinfo, targetpath):
- """Make a file called targetpath.
- """
- source = self.extractfile(tarinfo)
- target = bltn_open(targetpath, "wb")
- try:
- copyfileobj(source, target)
- finally:
- source.close()
- target.close()
-
- def makeunknown(self, tarinfo, targetpath):
- """Make a file from a TarInfo object with an unknown type
- at targetpath.
- """
- self.makefile(tarinfo, targetpath)
- self._dbg(1, "tarfile: Unknown file type %r, " \
- "extracted as regular file." % tarinfo.type)
-
- def makefifo(self, tarinfo, targetpath):
- """Make a fifo called targetpath.
- """
- if hasattr(os, "mkfifo"):
- os.mkfifo(targetpath)
- else:
- raise ExtractError("fifo not supported by system")
-
- def makedev(self, tarinfo, targetpath):
- """Make a character or block device called targetpath.
- """
- if not hasattr(os, "mknod") or not hasattr(os, "makedev"):
- raise ExtractError("special devices not supported by system")
-
- mode = tarinfo.mode
- if tarinfo.isblk():
- mode |= stat.S_IFBLK
- else:
- mode |= stat.S_IFCHR
-
- os.mknod(targetpath, mode,
- os.makedev(tarinfo.devmajor, tarinfo.devminor))
-
- def makelink(self, tarinfo, targetpath):
- """Make a (symbolic) link called targetpath. If it cannot be created
- (platform limitation), we try to make a copy of the referenced file
- instead of a link.
- """
- try:
- if tarinfo.issym():
- os.symlink(tarinfo.linkname, targetpath)
- else:
- # See extract().
- os.link(tarinfo._link_target, targetpath)
- except AttributeError:
- if tarinfo.issym():
- linkpath = os.path.dirname(tarinfo.name) + "/" + \
- tarinfo.linkname
- else:
- linkpath = tarinfo.linkname
-
- try:
- self._extract_member(self.getmember(linkpath), targetpath)
- except (EnvironmentError, KeyError), e:
- linkpath = linkpath.replace("/", os.sep)
- try:
- shutil.copy2(linkpath, targetpath)
- except EnvironmentError, e:
- raise IOError("link could not be created")
-
- def chown(self, tarinfo, targetpath):
- """Set owner of targetpath according to tarinfo.
- """
- if pwd and hasattr(os, "geteuid") and os.geteuid() == 0:
- # We have to be root to do so.
- try:
- g = grp.getgrnam(tarinfo.gname)[2]
- except KeyError:
- try:
- g = grp.getgrgid(tarinfo.gid)[2]
- except KeyError:
- g = os.getgid()
- try:
- u = pwd.getpwnam(tarinfo.uname)[2]
- except KeyError:
- try:
- u = pwd.getpwuid(tarinfo.uid)[2]
- except KeyError:
- u = os.getuid()
- try:
- if tarinfo.issym() and hasattr(os, "lchown"):
- os.lchown(targetpath, u, g)
- else:
- if sys.platform != "os2emx":
- os.chown(targetpath, u, g)
- except EnvironmentError, e:
- raise ExtractError("could not change owner")
-
- def chmod(self, tarinfo, targetpath):
- """Set file permissions of targetpath according to tarinfo.
- """
- if hasattr(os, 'chmod'):
- try:
- os.chmod(targetpath, tarinfo.mode)
- except EnvironmentError, e:
- raise ExtractError("could not change mode")
-
- def utime(self, tarinfo, targetpath):
- """Set modification time of targetpath according to tarinfo.
- """
- if not hasattr(os, 'utime'):
- return
- try:
- os.utime(targetpath, (tarinfo.mtime, tarinfo.mtime))
- except EnvironmentError, e:
- raise ExtractError("could not change modification time")
-
- #--------------------------------------------------------------------------
- def next(self):
- """Return the next member of the archive as a TarInfo object, when
- TarFile is opened for reading. Return None if there is no more
- available.
- """
- self._check("ra")
- if self.firstmember is not None:
- m = self.firstmember
- self.firstmember = None
- return m
-
- # Read the next block.
- self.fileobj.seek(self.offset)
- tarinfo = None
- while True:
- try:
- tarinfo = self.tarinfo.fromtarfile(self)
- except EOFHeaderError, e:
- if self.ignore_zeros:
- self._dbg(2, "0x%X: %s" % (self.offset, e))
- self.offset += BLOCKSIZE
- continue
- except InvalidHeaderError, e:
- if self.ignore_zeros:
- self._dbg(2, "0x%X: %s" % (self.offset, e))
- self.offset += BLOCKSIZE
- continue
- elif self.offset == 0:
- raise ReadError(str(e))
- except EmptyHeaderError:
- if self.offset == 0:
- raise ReadError("empty file")
- except TruncatedHeaderError, e:
- if self.offset == 0:
- raise ReadError(str(e))
- except SubsequentHeaderError, e:
- raise ReadError(str(e))
- break
-
- if tarinfo is not None:
- self.members.append(tarinfo)
- else:
- self._loaded = True
-
- return tarinfo
-
- #--------------------------------------------------------------------------
- # Little helper methods:
-
- def _getmember(self, name, tarinfo=None):
- """Find an archive member by name from bottom to top.
- If tarinfo is given, it is used as the starting point.
- """
- # Ensure that all members have been loaded.
- members = self.getmembers()
-
- if tarinfo is None:
- end = len(members)
- else:
- end = members.index(tarinfo)
-
- for i in xrange(end - 1, -1, -1):
- if name == members[i].name:
- return members[i]
-
- def _load(self):
- """Read through the entire archive file and look for readable
- members.
- """
- while True:
- tarinfo = self.next()
- if tarinfo is None:
- break
- self._loaded = True
-
- def _check(self, mode=None):
- """Check if TarFile is still open, and if the operation's mode
- corresponds to TarFile's mode.
- """
- if self.closed:
- raise IOError("%s is closed" % self.__class__.__name__)
- if mode is not None and self.mode not in mode:
- raise IOError("bad operation for mode %r" % self.mode)
-
- def __iter__(self):
- """Provide an iterator object.
- """
- if self._loaded:
- return iter(self.members)
- else:
- return TarIter(self)
-
- def _dbg(self, level, msg):
- """Write debugging output to sys.stderr.
- """
- if level <= self.debug:
- print >> sys.stderr, msg
-# class TarFile
-
-class TarIter(object):
- """Iterator Class.
-
- for tarinfo in TarFile(...):
- suite...
- """
-
- def __init__(self, tarfile):
- """Construct a TarIter object.
- """
- self.tarfile = tarfile
- self.index = 0
- def __iter__(self):
- """Return iterator object.
- """
- return self
- def next(self):
- """Return the next item using TarFile's next() method.
- When all members have been read, set TarFile as _loaded.
- """
- # Fix for SF #1100429: Under rare circumstances it can
- # happen that getmembers() is called during iteration,
- # which will cause TarIter to stop prematurely.
- if not self.tarfile._loaded:
- tarinfo = self.tarfile.next()
- if not tarinfo:
- self.tarfile._loaded = True
- raise StopIteration
- else:
- try:
- tarinfo = self.tarfile.members[self.index]
- except IndexError:
- raise StopIteration
- self.index += 1
- return tarinfo
-
-# Helper classes for sparse file support
-class _section(object):
- """Base class for _data and _hole.
- """
- def __init__(self, offset, size):
- self.offset = offset
- self.size = size
- def __contains__(self, offset):
- return self.offset <= offset < self.offset + self.size
-
-class _data(_section):
- """Represent a data section in a sparse file.
- """
- def __init__(self, offset, size, realpos):
- _section.__init__(self, offset, size)
- self.realpos = realpos
-
-class _hole(_section):
- """Represent a hole section in a sparse file.
- """
- pass
-
-class _ringbuffer(list):
- """Ringbuffer class which increases performance
- over a regular list.
- """
- def __init__(self):
- self.idx = 0
- def find(self, offset):
- idx = self.idx
- while True:
- item = self[idx]
- if offset in item:
- break
- idx += 1
- if idx == len(self):
- idx = 0
- if idx == self.idx:
- # End of File
- return None
- self.idx = idx
- return item
-
-#---------------------------------------------
-# zipfile compatible TarFile class
-#---------------------------------------------
-TAR_PLAIN = 0 # zipfile.ZIP_STORED
-TAR_GZIPPED = 8 # zipfile.ZIP_DEFLATED
-class TarFileCompat(object):
- """TarFile class compatible with standard module zipfile's
- ZipFile class.
- """
- def __init__(self, file, mode="r", compression=TAR_PLAIN):
- from warnings import warnpy3k
- warnpy3k("the TarFileCompat class has been removed in Python 3.0",
- stacklevel=2)
- if compression == TAR_PLAIN:
- self.tarfile = TarFile.taropen(file, mode)
- elif compression == TAR_GZIPPED:
- self.tarfile = TarFile.gzopen(file, mode)
- else:
- raise ValueError("unknown compression constant")
- if mode[0:1] == "r":
- members = self.tarfile.getmembers()
- for m in members:
- m.filename = m.name
- m.file_size = m.size
- m.date_time = time.gmtime(m.mtime)[:6]
- def namelist(self):
- return map(lambda m: m.name, self.infolist())
- def infolist(self):
- return filter(lambda m: m.type in REGULAR_TYPES,
- self.tarfile.getmembers())
- def printdir(self):
- self.tarfile.list()
- def testzip(self):
- return
- def getinfo(self, name):
- return self.tarfile.getmember(name)
- def read(self, name):
- return self.tarfile.extractfile(self.tarfile.getmember(name)).read()
- def write(self, filename, arcname=None, compress_type=None):
- self.tarfile.add(filename, arcname)
- def writestr(self, zinfo, bytes):
- try:
- from cStringIO import StringIO
- except ImportError:
- from StringIO import StringIO
- import calendar
- tinfo = TarInfo(zinfo.filename)
- tinfo.size = len(bytes)
- tinfo.mtime = calendar.timegm(zinfo.date_time)
- self.tarfile.addfile(tinfo, StringIO(bytes))
- def close(self):
- self.tarfile.close()
-#class TarFileCompat
-
-#--------------------
-# exported functions
-#--------------------
-def is_tarfile(name):
- """Return True if name points to a tar archive that we
- are able to handle, else return False.
- """
- try:
- try:
- t = open(name)
- finally:
- t.close()
- return True
- except TarError:
- return False
-
-bltn_open = open
-open = TarFile.open
diff --git a/src/distutils2/_backport/tests/__init__.py b/src/distutils2/_backport/tests/__init__.py
deleted file mode 100644
index 78c8142..0000000
--- a/src/distutils2/_backport/tests/__init__.py
+++ /dev/null
@@ -1,20 +0,0 @@
-import os
-import sys
-
-from distutils2.tests.support import unittest
-
-
-here = os.path.dirname(__file__) or os.curdir
-
-def test_suite():
- suite = unittest.TestSuite()
- for fn in os.listdir(here):
- if fn.startswith("test") and fn.endswith(".py"):
- modname = "distutils2._backport.tests." + fn[:-3]
- __import__(modname)
- module = sys.modules[modname]
- suite.addTest(module.test_suite())
- return suite
-
-if __name__ == '__main__':
- unittest.main(defaultTest='test_suite')
diff --git a/src/distutils2/_backport/tests/fake_dists/bacon-0.1.egg-info/PKG-INFO b/src/distutils2/_backport/tests/fake_dists/bacon-0.1.egg-info/PKG-INFO
deleted file mode 100644
index a176dfd..0000000
--- a/src/distutils2/_backport/tests/fake_dists/bacon-0.1.egg-info/PKG-INFO
+++ /dev/null
@@ -1,6 +0,0 @@
-Metadata-Version: 1.2
-Name: bacon
-Version: 0.1
-Provides-Dist: truffles (2.0)
-Provides-Dist: bacon (0.1)
-Obsoletes-Dist: truffles (>=0.9,<=1.5)
diff --git a/src/distutils2/_backport/tests/fake_dists/banana-0.4.egg/EGG-INFO/PKG-INFO b/src/distutils2/_backport/tests/fake_dists/banana-0.4.egg/EGG-INFO/PKG-INFO
deleted file mode 100644
index a7e118a..0000000
--- a/src/distutils2/_backport/tests/fake_dists/banana-0.4.egg/EGG-INFO/PKG-INFO
+++ /dev/null
@@ -1,18 +0,0 @@
-Metadata-Version: 1.0
-Name: banana
-Version: 0.4
-Summary: A yellow fruit
-Home-page: http://en.wikipedia.org/wiki/Banana
-Author: Josip Djolonga
-Author-email: foo@nbar.com
-License: BSD
-Description: A fruit
-Keywords: foo bar
-Platform: UNKNOWN
-Classifier: Development Status :: 4 - Beta
-Classifier: Intended Audience :: Developers
-Classifier: Intended Audience :: Science/Research
-Classifier: License :: OSI Approved :: BSD License
-Classifier: Operating System :: OS Independent
-Classifier: Programming Language :: Python
-Classifier: Topic :: Scientific/Engineering :: GIS
diff --git a/src/distutils2/_backport/tests/fake_dists/banana-0.4.egg/EGG-INFO/SOURCES.txt b/src/distutils2/_backport/tests/fake_dists/banana-0.4.egg/EGG-INFO/SOURCES.txt
deleted file mode 100644
index e69de29..0000000
--- a/src/distutils2/_backport/tests/fake_dists/banana-0.4.egg/EGG-INFO/SOURCES.txt
+++ /dev/null
diff --git a/src/distutils2/_backport/tests/fake_dists/banana-0.4.egg/EGG-INFO/dependency_links.txt b/src/distutils2/_backport/tests/fake_dists/banana-0.4.egg/EGG-INFO/dependency_links.txt
deleted file mode 100644
index 8b13789..0000000
--- a/src/distutils2/_backport/tests/fake_dists/banana-0.4.egg/EGG-INFO/dependency_links.txt
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/src/distutils2/_backport/tests/fake_dists/banana-0.4.egg/EGG-INFO/entry_points.txt b/src/distutils2/_backport/tests/fake_dists/banana-0.4.egg/EGG-INFO/entry_points.txt
deleted file mode 100644
index 5d3e5f6..0000000
--- a/src/distutils2/_backport/tests/fake_dists/banana-0.4.egg/EGG-INFO/entry_points.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-
- # -*- Entry points: -*-
- \ No newline at end of file
diff --git a/src/distutils2/_backport/tests/fake_dists/banana-0.4.egg/EGG-INFO/not-zip-safe b/src/distutils2/_backport/tests/fake_dists/banana-0.4.egg/EGG-INFO/not-zip-safe
deleted file mode 100644
index 8b13789..0000000
--- a/src/distutils2/_backport/tests/fake_dists/banana-0.4.egg/EGG-INFO/not-zip-safe
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/src/distutils2/_backport/tests/fake_dists/banana-0.4.egg/EGG-INFO/requires.txt b/src/distutils2/_backport/tests/fake_dists/banana-0.4.egg/EGG-INFO/requires.txt
deleted file mode 100644
index 4354305..0000000
--- a/src/distutils2/_backport/tests/fake_dists/banana-0.4.egg/EGG-INFO/requires.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-# this should be ignored
-
-strawberry >=0.5
-
-[section ignored]
-foo ==0.5
diff --git a/src/distutils2/_backport/tests/fake_dists/banana-0.4.egg/EGG-INFO/top_level.txt b/src/distutils2/_backport/tests/fake_dists/banana-0.4.egg/EGG-INFO/top_level.txt
deleted file mode 100644
index e69de29..0000000
--- a/src/distutils2/_backport/tests/fake_dists/banana-0.4.egg/EGG-INFO/top_level.txt
+++ /dev/null
diff --git a/src/distutils2/_backport/tests/fake_dists/cheese-2.0.2.egg-info b/src/distutils2/_backport/tests/fake_dists/cheese-2.0.2.egg-info
deleted file mode 100644
index 27cbe30..0000000
--- a/src/distutils2/_backport/tests/fake_dists/cheese-2.0.2.egg-info
+++ /dev/null
@@ -1,5 +0,0 @@
-Metadata-Version: 1.2
-Name: cheese
-Version: 2.0.2
-Provides-Dist: truffles (1.0.2)
-Obsoletes-Dist: truffles (!=1.2,<=2.0)
diff --git a/src/distutils2/_backport/tests/fake_dists/choxie-2.0.0.9.dist-info/INSTALLER b/src/distutils2/_backport/tests/fake_dists/choxie-2.0.0.9.dist-info/INSTALLER
deleted file mode 100644
index e69de29..0000000
--- a/src/distutils2/_backport/tests/fake_dists/choxie-2.0.0.9.dist-info/INSTALLER
+++ /dev/null
diff --git a/src/distutils2/_backport/tests/fake_dists/choxie-2.0.0.9.dist-info/METADATA b/src/distutils2/_backport/tests/fake_dists/choxie-2.0.0.9.dist-info/METADATA
deleted file mode 100644
index 00c3674..0000000
--- a/src/distutils2/_backport/tests/fake_dists/choxie-2.0.0.9.dist-info/METADATA
+++ /dev/null
@@ -1,8 +0,0 @@
-Metadata-Version: 1.2
-Name: choxie
-Version: 2.0.0.9
-Summary: Chocolate with a kick!
-Requires-Dist: towel-stuff (0.1)
-Provides-Dist: truffles (1.0)
-Obsoletes-Dist: truffles (<=0.8,>=0.5)
-Obsoletes-Dist: truffles (<=0.9,>=0.6)
diff --git a/src/distutils2/_backport/tests/fake_dists/choxie-2.0.0.9.dist-info/RECORD b/src/distutils2/_backport/tests/fake_dists/choxie-2.0.0.9.dist-info/RECORD
deleted file mode 100644
index e69de29..0000000
--- a/src/distutils2/_backport/tests/fake_dists/choxie-2.0.0.9.dist-info/RECORD
+++ /dev/null
diff --git a/src/distutils2/_backport/tests/fake_dists/choxie-2.0.0.9.dist-info/REQUESTED b/src/distutils2/_backport/tests/fake_dists/choxie-2.0.0.9.dist-info/REQUESTED
deleted file mode 100644
index e69de29..0000000
--- a/src/distutils2/_backport/tests/fake_dists/choxie-2.0.0.9.dist-info/REQUESTED
+++ /dev/null
diff --git a/src/distutils2/_backport/tests/fake_dists/choxie-2.0.0.9/choxie/__init__.py b/src/distutils2/_backport/tests/fake_dists/choxie-2.0.0.9/choxie/__init__.py
deleted file mode 100644
index 633f866..0000000
--- a/src/distutils2/_backport/tests/fake_dists/choxie-2.0.0.9/choxie/__init__.py
+++ /dev/null
@@ -1,2 +0,0 @@
-# -*- coding: utf-8 -*-
-
diff --git a/src/distutils2/_backport/tests/fake_dists/choxie-2.0.0.9/choxie/chocolate.py b/src/distutils2/_backport/tests/fake_dists/choxie-2.0.0.9/choxie/chocolate.py
deleted file mode 100644
index c4027f3..0000000
--- a/src/distutils2/_backport/tests/fake_dists/choxie-2.0.0.9/choxie/chocolate.py
+++ /dev/null
@@ -1,10 +0,0 @@
-# -*- coding: utf-8 -*-
-from towel_stuff import Towel
-
-class Chocolate(object):
- """A piece of chocolate."""
-
- def wrap_with_towel(self):
- towel = Towel()
- towel.wrap(self)
- return towel
diff --git a/src/distutils2/_backport/tests/fake_dists/choxie-2.0.0.9/truffles.py b/src/distutils2/_backport/tests/fake_dists/choxie-2.0.0.9/truffles.py
deleted file mode 100644
index 342b8ea..0000000
--- a/src/distutils2/_backport/tests/fake_dists/choxie-2.0.0.9/truffles.py
+++ /dev/null
@@ -1,5 +0,0 @@
-# -*- coding: utf-8 -*-
-from choxie.chocolate import Chocolate
-
-class Truffle(Chocolate):
- """A truffle."""
diff --git a/src/distutils2/_backport/tests/fake_dists/grammar-1.0a4.dist-info/INSTALLER b/src/distutils2/_backport/tests/fake_dists/grammar-1.0a4.dist-info/INSTALLER
deleted file mode 100644
index e69de29..0000000
--- a/src/distutils2/_backport/tests/fake_dists/grammar-1.0a4.dist-info/INSTALLER
+++ /dev/null
diff --git a/src/distutils2/_backport/tests/fake_dists/grammar-1.0a4.dist-info/METADATA b/src/distutils2/_backport/tests/fake_dists/grammar-1.0a4.dist-info/METADATA
deleted file mode 100644
index 0b99f52..0000000
--- a/src/distutils2/_backport/tests/fake_dists/grammar-1.0a4.dist-info/METADATA
+++ /dev/null
@@ -1,5 +0,0 @@
-Metadata-Version: 1.2
-Name: grammar
-Version: 1.0a4
-Requires-Dist: truffles (>=1.2)
-Author: Sherlock Holmes
diff --git a/src/distutils2/_backport/tests/fake_dists/grammar-1.0a4.dist-info/RECORD b/src/distutils2/_backport/tests/fake_dists/grammar-1.0a4.dist-info/RECORD
deleted file mode 100644
index e69de29..0000000
--- a/src/distutils2/_backport/tests/fake_dists/grammar-1.0a4.dist-info/RECORD
+++ /dev/null
diff --git a/src/distutils2/_backport/tests/fake_dists/grammar-1.0a4.dist-info/REQUESTED b/src/distutils2/_backport/tests/fake_dists/grammar-1.0a4.dist-info/REQUESTED
deleted file mode 100644
index e69de29..0000000
--- a/src/distutils2/_backport/tests/fake_dists/grammar-1.0a4.dist-info/REQUESTED
+++ /dev/null
diff --git a/src/distutils2/_backport/tests/fake_dists/grammar-1.0a4/grammar/__init__.py b/src/distutils2/_backport/tests/fake_dists/grammar-1.0a4/grammar/__init__.py
deleted file mode 100644
index 633f866..0000000
--- a/src/distutils2/_backport/tests/fake_dists/grammar-1.0a4/grammar/__init__.py
+++ /dev/null
@@ -1,2 +0,0 @@
-# -*- coding: utf-8 -*-
-
diff --git a/src/distutils2/_backport/tests/fake_dists/grammar-1.0a4/grammar/utils.py b/src/distutils2/_backport/tests/fake_dists/grammar-1.0a4/grammar/utils.py
deleted file mode 100644
index 66ba796..0000000
--- a/src/distutils2/_backport/tests/fake_dists/grammar-1.0a4/grammar/utils.py
+++ /dev/null
@@ -1,8 +0,0 @@
-# -*- coding: utf-8 -*-
-from random import randint
-
-def is_valid_grammar(sentence):
- if randint(0, 10) < 2:
- return False
- else:
- return True
diff --git a/src/distutils2/_backport/tests/fake_dists/strawberry-0.6.egg b/src/distutils2/_backport/tests/fake_dists/strawberry-0.6.egg
deleted file mode 100644
index 6d160e8..0000000
--- a/src/distutils2/_backport/tests/fake_dists/strawberry-0.6.egg
+++ /dev/null
Binary files differ
diff --git a/src/distutils2/_backport/tests/fake_dists/towel_stuff-0.1.dist-info/INSTALLER b/src/distutils2/_backport/tests/fake_dists/towel_stuff-0.1.dist-info/INSTALLER
deleted file mode 100644
index e69de29..0000000
--- a/src/distutils2/_backport/tests/fake_dists/towel_stuff-0.1.dist-info/INSTALLER
+++ /dev/null
diff --git a/src/distutils2/_backport/tests/fake_dists/towel_stuff-0.1.dist-info/METADATA b/src/distutils2/_backport/tests/fake_dists/towel_stuff-0.1.dist-info/METADATA
deleted file mode 100644
index ca46d0a..0000000
--- a/src/distutils2/_backport/tests/fake_dists/towel_stuff-0.1.dist-info/METADATA
+++ /dev/null
@@ -1,7 +0,0 @@
-Metadata-Version: 1.2
-Name: towel-stuff
-Version: 0.1
-Provides-Dist: truffles (1.1.2)
-Provides-Dist: towel-stuff (0.1)
-Obsoletes-Dist: truffles (!=0.8,<1.0)
-Requires-Dist: bacon (<=0.2)
diff --git a/src/distutils2/_backport/tests/fake_dists/towel_stuff-0.1.dist-info/RECORD b/src/distutils2/_backport/tests/fake_dists/towel_stuff-0.1.dist-info/RECORD
deleted file mode 100644
index e69de29..0000000
--- a/src/distutils2/_backport/tests/fake_dists/towel_stuff-0.1.dist-info/RECORD
+++ /dev/null
diff --git a/src/distutils2/_backport/tests/fake_dists/towel_stuff-0.1.dist-info/REQUESTED b/src/distutils2/_backport/tests/fake_dists/towel_stuff-0.1.dist-info/REQUESTED
deleted file mode 100644
index e69de29..0000000
--- a/src/distutils2/_backport/tests/fake_dists/towel_stuff-0.1.dist-info/REQUESTED
+++ /dev/null
diff --git a/src/distutils2/_backport/tests/fake_dists/towel_stuff-0.1/towel_stuff/__init__.py b/src/distutils2/_backport/tests/fake_dists/towel_stuff-0.1/towel_stuff/__init__.py
deleted file mode 100644
index 191f895..0000000
--- a/src/distutils2/_backport/tests/fake_dists/towel_stuff-0.1/towel_stuff/__init__.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# -*- coding: utf-8 -*-
-
-class Towel(object):
- """A towel, that one should never be without."""
-
- def __init__(self, color='tie-dye'):
- self.color = color
- self.wrapped_obj = None
-
- def wrap(self, obj):
- """Wrap an object up in our towel."""
- self.wrapped_obj = obj
-
- def unwrap(self):
- """Unwrap whatever is in our towel and return whatever it is."""
- obj = self.wrapped_obj
- self.wrapped_obj = None
- return obj
diff --git a/src/distutils2/_backport/tests/fake_dists/truffles-5.0.egg-info b/src/distutils2/_backport/tests/fake_dists/truffles-5.0.egg-info
deleted file mode 100644
index 45f0cf8..0000000
--- a/src/distutils2/_backport/tests/fake_dists/truffles-5.0.egg-info
+++ /dev/null
@@ -1,3 +0,0 @@
-Metadata-Version: 1.2
-Name: truffles
-Version: 5.0
diff --git a/src/distutils2/_backport/tests/test_pkgutil.py b/src/distutils2/_backport/tests/test_pkgutil.py
deleted file mode 100644
index c052b4d..0000000
--- a/src/distutils2/_backport/tests/test_pkgutil.py
+++ /dev/null
@@ -1,610 +0,0 @@
-# -*- coding: utf-8 -*-
-"""Tests for PEP 376 pkgutil functionality"""
-import sys
-import os
-import csv
-import imp
-import tempfile
-import shutil
-import zipfile
-try:
- from hashlib import md5
-except ImportError:
- from distutils2._backport.hashlib import md5
-
-from test.test_support import run_unittest, TESTFN
-from distutils2.tests.support import unittest
-
-from distutils2._backport import pkgutil
-
-try:
- from os.path import relpath
-except ImportError:
- try:
- from unittest.compatibility import relpath
- except ImportError:
- from unittest2.compatibility import relpath
-
-# Adapted from Python 2.7's trunk
-
-# TODO Add a test for getting a distribution that is provided by another
-# distribution.
-
-# TODO Add a test for absolute pathed RECORD items (e.g. /etc/myapp/config.ini)
-
-
-class TestPkgUtilData(unittest.TestCase):
-
- def setUp(self):
- super(TestPkgUtilData, self).setUp()
- self.dirname = tempfile.mkdtemp()
- sys.path.insert(0, self.dirname)
-
- def tearDown(self):
- super(TestPkgUtilData, self).tearDown()
- del sys.path[0]
- shutil.rmtree(self.dirname)
-
- def test_getdata_filesys(self):
- pkg = 'test_getdata_filesys'
-
- # Include a LF and a CRLF, to test that binary data is read back
- RESOURCE_DATA = 'Hello, world!\nSecond line\r\nThird line'
-
- # Make a package with some resources
- package_dir = os.path.join(self.dirname, pkg)
- os.mkdir(package_dir)
- # Empty init.py
- f = open(os.path.join(package_dir, '__init__.py'), "wb")
- try:
- pass
- finally:
- f.close()
- # Resource files, res.txt, sub/res.txt
- f = open(os.path.join(package_dir, 'res.txt'), "wb")
- try:
- f.write(RESOURCE_DATA)
- finally:
- f.close()
- os.mkdir(os.path.join(package_dir, 'sub'))
- f = open(os.path.join(package_dir, 'sub', 'res.txt'), "wb")
- try:
- f.write(RESOURCE_DATA)
- finally:
- f.close()
-
- # Check we can read the resources
- res1 = pkgutil.get_data(pkg, 'res.txt')
- self.assertEqual(res1, RESOURCE_DATA)
- res2 = pkgutil.get_data(pkg, 'sub/res.txt')
- self.assertEqual(res2, RESOURCE_DATA)
-
- del sys.modules[pkg]
-
- def test_getdata_zipfile(self):
- zip = 'test_getdata_zipfile.zip'
- pkg = 'test_getdata_zipfile'
-
- # Include a LF and a CRLF, to test that binary data is read back
- RESOURCE_DATA = 'Hello, world!\nSecond line\r\nThird line'
-
- # Make a package with some resources
- zip_file = os.path.join(self.dirname, zip)
- z = zipfile.ZipFile(zip_file, 'w')
- try:
- # Empty init.py
- z.writestr(pkg + '/__init__.py', "")
- # Resource files, res.txt, sub/res.txt
- z.writestr(pkg + '/res.txt', RESOURCE_DATA)
- z.writestr(pkg + '/sub/res.txt', RESOURCE_DATA)
- finally:
- z.close()
-
- # Check we can read the resources
- sys.path.insert(0, zip_file)
- res1 = pkgutil.get_data(pkg, 'res.txt')
- self.assertEqual(res1, RESOURCE_DATA)
- res2 = pkgutil.get_data(pkg, 'sub/res.txt')
- self.assertEqual(res2, RESOURCE_DATA)
- del sys.path[0]
-
- del sys.modules[pkg]
-
-
-# Adapted from Python 2.7's trunk
-
-
-class TestPkgUtilPEP302(unittest.TestCase):
-
- class MyTestLoader(object):
-
- def load_module(self, fullname):
- # Create an empty module
- mod = sys.modules.setdefault(fullname, imp.new_module(fullname))
- mod.__file__ = "<%s>" % self.__class__.__name__
- mod.__loader__ = self
- # Make it a package
- mod.__path__ = []
- # Count how many times the module is reloaded
- mod.__dict__['loads'] = mod.__dict__.get('loads', 0) + 1
- return mod
-
- def get_data(self, path):
- return "Hello, world!"
-
- class MyTestImporter(object):
-
- def find_module(self, fullname, path=None):
- return TestPkgUtilPEP302.MyTestLoader()
-
- def setUp(self):
- super(TestPkgUtilPEP302, self).setUp()
- sys.meta_path.insert(0, self.MyTestImporter())
-
- def tearDown(self):
- del sys.meta_path[0]
- super(TestPkgUtilPEP302, self).tearDown()
-
- def test_getdata_pep302(self):
- # Use a dummy importer/loader
- self.assertEqual(pkgutil.get_data('foo', 'dummy'), "Hello, world!")
- del sys.modules['foo']
-
- def test_alreadyloaded(self):
- # Ensure that get_data works without reloading - the "loads" module
- # variable in the example loader should count how many times a reload
- # occurs.
- import foo
- self.assertEqual(foo.loads, 1)
- self.assertEqual(pkgutil.get_data('foo', 'dummy'), "Hello, world!")
- self.assertEqual(foo.loads, 1)
- del sys.modules['foo']
-
-
-class TestPkgUtilDistribution(unittest.TestCase):
- # Tests the pkgutil.Distribution class
-
- def setUp(self):
- super(TestPkgUtilDistribution, self).setUp()
- self.fake_dists_path = os.path.abspath(
- os.path.join(os.path.dirname(__file__), 'fake_dists'))
-
- self.distinfo_dirs = [os.path.join(self.fake_dists_path, dir)
- for dir in os.listdir(self.fake_dists_path)
- if dir.endswith('.dist-info')]
-
- def get_hexdigest(file):
- md5_hash = md5()
- md5_hash.update(open(file).read())
- return md5_hash.hexdigest()
-
- def record_pieces(file):
- path = relpath(file, sys.prefix)
- digest = get_hexdigest(file)
- size = os.path.getsize(file)
- return [path, digest, size]
-
- self.records = {}
- for distinfo_dir in self.distinfo_dirs:
- # Setup the RECORD file for this dist
- record_file = os.path.join(distinfo_dir, 'RECORD')
- record_writer = csv.writer(open(record_file, 'w'), delimiter=',',
- quoting=csv.QUOTE_NONE)
- dist_location = distinfo_dir.replace('.dist-info', '')
-
- for path, dirs, files in os.walk(dist_location):
- for f in files:
- record_writer.writerow(record_pieces(
- os.path.join(path, f)))
- for file in ['INSTALLER', 'METADATA', 'REQUESTED']:
- record_writer.writerow(record_pieces(
- os.path.join(distinfo_dir, file)))
- record_writer.writerow([relpath(record_file, sys.prefix)])
- del record_writer # causes the RECORD file to close
- record_reader = csv.reader(open(record_file, 'rb'))
- record_data = []
- for row in record_reader:
- path, md5_, size = row[:] + \
- [None for i in xrange(len(row), 3)]
- record_data.append([path, (md5_, size,)])
- self.records[distinfo_dir] = dict(record_data)
-
- def tearDown(self):
- self.records = None
- for distinfo_dir in self.distinfo_dirs:
- record_file = os.path.join(distinfo_dir, 'RECORD')
- open(record_file, 'w').close()
- super(TestPkgUtilDistribution, self).tearDown()
-
- def test_instantiation(self):
- # Test the Distribution class's instantiation provides us with usable
- # attributes.
- # Import the Distribution class
- from distutils2._backport.pkgutil import distinfo_dirname, Distribution
-
- here = os.path.abspath(os.path.dirname(__file__))
- name = 'choxie'
- version = '2.0.0.9'
- dist_path = os.path.join(here, 'fake_dists',
- distinfo_dirname(name, version))
- dist = Distribution(dist_path)
-
- self.assertEqual(dist.name, name)
- from distutils2.metadata import DistributionMetadata
- self.assertTrue(isinstance(dist.metadata, DistributionMetadata))
- self.assertEqual(dist.metadata['version'], version)
- self.assertTrue(isinstance(dist.requested, type(bool())))
-
- def test_installed_files(self):
- # Test the iteration of installed files.
- # Test the distribution's installed files
- from distutils2._backport.pkgutil import Distribution
- for distinfo_dir in self.distinfo_dirs:
- dist = Distribution(distinfo_dir)
- for path, md5_, size in dist.get_installed_files():
- record_data = self.records[dist.path]
- self.assertTrue(path in record_data.keys())
- self.assertEqual(md5_, record_data[path][0])
- self.assertEqual(size, record_data[path][1])
-
- def test_uses(self):
- # Test to determine if a distribution uses a specified file.
- # Criteria to test against
- distinfo_name = 'grammar-1.0a4'
- distinfo_dir = os.path.join(self.fake_dists_path,
- distinfo_name + '.dist-info')
- true_path = [self.fake_dists_path, distinfo_name, \
- 'grammar', 'utils.py']
- true_path = relpath(os.path.join(*true_path), sys.prefix)
- false_path = [self.fake_dists_path, 'towel_stuff-0.1', 'towel_stuff',
- '__init__.py']
- false_path = relpath(os.path.join(*false_path), sys.prefix)
-
- # Test if the distribution uses the file in question
- from distutils2._backport.pkgutil import Distribution
- dist = Distribution(distinfo_dir)
- self.assertTrue(dist.uses(true_path))
- self.assertFalse(dist.uses(false_path))
-
- def test_get_distinfo_file(self):
- # Test the retrieval of dist-info file objects.
- from distutils2._backport.pkgutil import Distribution
- distinfo_name = 'choxie-2.0.0.9'
- other_distinfo_name = 'grammar-1.0a4'
- distinfo_dir = os.path.join(self.fake_dists_path,
- distinfo_name + '.dist-info')
- dist = Distribution(distinfo_dir)
- # Test for known good file matches
- distinfo_files = [
- # Relative paths
- 'INSTALLER', 'METADATA',
- # Absolute paths
- os.path.join(distinfo_dir, 'RECORD'),
- os.path.join(distinfo_dir, 'REQUESTED'),
- ]
-
- for distfile in distinfo_files:
- value = dist.get_distinfo_file(distfile)
- self.assertTrue(isinstance(value, file))
- # Is it the correct file?
- self.assertEqual(value.name, os.path.join(distinfo_dir, distfile))
-
- from distutils2.errors import DistutilsError
- # Test an absolute path that is part of another distributions dist-info
- other_distinfo_file = os.path.join(self.fake_dists_path,
- other_distinfo_name + '.dist-info', 'REQUESTED')
- self.assertRaises(DistutilsError, dist.get_distinfo_file,
- other_distinfo_file)
- # Test for a file that does not exist and should not exist
- self.assertRaises(DistutilsError, dist.get_distinfo_file, \
- 'ENTRYPOINTS')
-
- def test_get_distinfo_files(self):
- # Test for the iteration of RECORD path entries.
- from distutils2._backport.pkgutil import Distribution
- distinfo_name = 'towel_stuff-0.1'
- distinfo_dir = os.path.join(self.fake_dists_path,
- distinfo_name + '.dist-info')
- dist = Distribution(distinfo_dir)
- # Test for the iteration of the raw path
- distinfo_record_paths = self.records[distinfo_dir].keys()
- found = [path for path in dist.get_distinfo_files()]
- self.assertEqual(sorted(found), sorted(distinfo_record_paths))
- # Test for the iteration of local absolute paths
- distinfo_record_paths = [os.path.join(sys.prefix, path)
- for path in self.records[distinfo_dir].keys()]
- found = [path for path in dist.get_distinfo_files(local=True)]
- self.assertEqual(sorted(found), sorted(distinfo_record_paths))
-
-
-class TestPkgUtilPEP376(unittest.TestCase):
- # Tests for the new functionality added in PEP 376.
-
- def setUp(self):
- super(TestPkgUtilPEP376, self).setUp()
- # Setup the path environment with our fake distributions
- current_path = os.path.abspath(os.path.dirname(__file__))
- self.sys_path = sys.path[:]
- self.fake_dists_path = os.path.join(current_path, 'fake_dists')
- sys.path.insert(0, self.fake_dists_path)
-
- def tearDown(self):
- sys.path[:] = self.sys_path
- super(TestPkgUtilPEP376, self).tearDown()
-
- def test_distinfo_dirname(self):
- # Given a name and a version, we expect the distinfo_dirname function
- # to return a standard distribution information directory name.
-
- items = [# (name, version, standard_dirname)
- # Test for a very simple single word name and decimal
- # version number
- ('docutils', '0.5', 'docutils-0.5.dist-info'),
- # Test for another except this time with a '-' in the name, which
- # needs to be transformed during the name lookup
- ('python-ldap', '2.5', 'python_ldap-2.5.dist-info'),
- # Test for both '-' in the name and a funky version number
- ('python-ldap', '2.5 a---5', 'python_ldap-2.5 a---5.dist-info'),
- ]
-
- # Import the function in question
- from distutils2._backport.pkgutil import distinfo_dirname
-
- # Loop through the items to validate the results
- for name, version, standard_dirname in items:
- dirname = distinfo_dirname(name, version)
- self.assertEqual(dirname, standard_dirname)
-
- def test_get_distributions(self):
- # Lookup all distributions found in the ``sys.path``.
- # This test could potentially pick up other installed distributions
- fake_dists = [('grammar', '1.0a4'), ('choxie', '2.0.0.9'),
- ('towel-stuff', '0.1')]
- found_dists = []
-
- # Import the function in question
- from distutils2._backport.pkgutil import get_distributions, \
- Distribution, \
- EggInfoDistribution
-
- # Verify the fake dists have been found.
- dists = [dist for dist in get_distributions()]
- for dist in dists:
- if not isinstance(dist, Distribution):
- self.fail("item received was not a Distribution instance: "
- "%s" % type(dist))
- if dist.name in dict(fake_dists).keys() and \
- dist.path.startswith(self.fake_dists_path):
- found_dists.append((dist.name, dist.metadata['version'],))
- else:
- # check that it doesn't find anything more than this
- self.assertFalse(dist.path.startswith(self.fake_dists_path))
- # otherwise we don't care what other distributions are found
-
- # Finally, test that we found all that we were looking for
- self.assertListEqual(sorted(found_dists), sorted(fake_dists))
-
- # Now, test if the egg-info distributions are found correctly as well
- fake_dists += [('bacon', '0.1'), ('cheese', '2.0.2'),
- ('banana', '0.4'), ('strawberry', '0.6'),
- ('truffles', '5.0')]
- found_dists = []
-
- dists = [dist for dist in get_distributions(use_egg_info=True)]
- for dist in dists:
- if not (isinstance(dist, Distribution) or \
- isinstance(dist, EggInfoDistribution)):
- self.fail("item received was not a Distribution or "
- "EggInfoDistribution instance: %s" % type(dist))
- if dist.name in dict(fake_dists).keys() and \
- dist.path.startswith(self.fake_dists_path):
- found_dists.append((dist.name, dist.metadata['version']))
- else:
- self.assertFalse(dist.path.startswith(self.fake_dists_path))
-
- self.assertListEqual(sorted(fake_dists), sorted(found_dists))
-
- def test_get_distribution(self):
- # Test for looking up a distribution by name.
- # Test the lookup of the towel-stuff distribution
- name = 'towel-stuff' # Note: This is different from the directory name
-
- # Import the function in question
- from distutils2._backport.pkgutil import get_distribution, \
- Distribution, \
- EggInfoDistribution
-
- # Lookup the distribution
- dist = get_distribution(name)
- self.assertTrue(isinstance(dist, Distribution))
- self.assertEqual(dist.name, name)
-
- # Verify that an unknown distribution returns None
- self.assertEqual(None, get_distribution('bogus'))
-
- # Verify partial name matching doesn't work
- self.assertEqual(None, get_distribution('towel'))
-
- # Verify that it does not find egg-info distributions, when not
- # instructed to
- self.assertEqual(None, get_distribution('bacon'))
- self.assertEqual(None, get_distribution('cheese'))
- self.assertEqual(None, get_distribution('strawberry'))
- self.assertEqual(None, get_distribution('banana'))
-
- # Now check that it works well in both situations, when egg-info
- # is a file and directory respectively.
- dist = get_distribution('cheese', use_egg_info=True)
- self.assertTrue(isinstance(dist, EggInfoDistribution))
- self.assertEqual(dist.name, 'cheese')
-
- dist = get_distribution('bacon', use_egg_info=True)
- self.assertTrue(isinstance(dist, EggInfoDistribution))
- self.assertEqual(dist.name, 'bacon')
-
- dist = get_distribution('banana', use_egg_info=True)
- self.assertTrue(isinstance(dist, EggInfoDistribution))
- self.assertEqual(dist.name, 'banana')
-
- dist = get_distribution('strawberry', use_egg_info=True)
- self.assertTrue(isinstance(dist, EggInfoDistribution))
- self.assertEqual(dist.name, 'strawberry')
-
- def test_get_file_users(self):
- # Test the iteration of distributions that use a file.
- from distutils2._backport.pkgutil import get_file_users, Distribution
- name = 'towel_stuff-0.1'
- path = os.path.join(self.fake_dists_path, name,
- 'towel_stuff', '__init__.py')
- for dist in get_file_users(path):
- self.assertTrue(isinstance(dist, Distribution))
- self.assertEqual(dist.name, name)
-
- def test_provides(self):
- # Test for looking up distributions by what they provide
- from distutils2._backport.pkgutil import provides_distribution
- from distutils2.errors import DistutilsError
-
- checkLists = lambda x, y: self.assertListEqual(sorted(x), sorted(y))
-
- l = [dist.name for dist in provides_distribution('truffles')]
- checkLists(l, ['choxie', 'towel-stuff'])
-
- l = [dist.name for dist in provides_distribution('truffles', '1.0')]
- checkLists(l, ['choxie'])
-
- l = [dist.name for dist in provides_distribution('truffles', '1.0',
- use_egg_info=True)]
- checkLists(l, ['choxie', 'cheese'])
-
- l = [dist.name for dist in provides_distribution('truffles', '1.1.2')]
- checkLists(l, ['towel-stuff'])
-
- l = [dist.name for dist in provides_distribution('truffles', '1.1')]
- checkLists(l, ['towel-stuff'])
-
- l = [dist.name for dist in provides_distribution('truffles', \
- '!=1.1,<=2.0')]
- checkLists(l, ['choxie'])
-
- l = [dist.name for dist in provides_distribution('truffles', \
- '!=1.1,<=2.0',
- use_egg_info=True)]
- checkLists(l, ['choxie', 'bacon', 'cheese'])
-
- l = [dist.name for dist in provides_distribution('truffles', '>1.0')]
- checkLists(l, ['towel-stuff'])
-
- l = [dist.name for dist in provides_distribution('truffles', '>1.5')]
- checkLists(l, [])
-
- l = [dist.name for dist in provides_distribution('truffles', '>1.5',
- use_egg_info=True)]
- checkLists(l, ['bacon', 'truffles'])
-
- l = [dist.name for dist in provides_distribution('truffles', '>=1.0')]
- checkLists(l, ['choxie', 'towel-stuff'])
-
- l = [dist.name for dist in provides_distribution('strawberry', '0.6',
- use_egg_info=True)]
- checkLists(l, ['strawberry'])
-
- l = [dist.name for dist in provides_distribution('strawberry', '>=0.5',
- use_egg_info=True)]
- checkLists(l, ['strawberry'])
-
-
- l = [dist.name for dist in provides_distribution('strawberry', '>0.6',
- use_egg_info=True)]
- checkLists(l, [])
-
-
- l = [dist.name for dist in provides_distribution('banana', '0.4',
- use_egg_info=True)]
- checkLists(l, ['banana'])
-
- l = [dist.name for dist in provides_distribution('banana', '>=0.3',
- use_egg_info=True)]
- checkLists(l, ['banana'])
-
-
- l = [dist.name for dist in provides_distribution('banana', '!=0.4',
- use_egg_info=True)]
- checkLists(l, [])
-
- def test_obsoletes(self):
- # Test looking for distributions based on what they obsolete
- from distutils2._backport.pkgutil import obsoletes_distribution
- from distutils2.errors import DistutilsError
-
- checkLists = lambda x, y: self.assertListEqual(sorted(x), sorted(y))
-
- l = [dist.name for dist in obsoletes_distribution('truffles', '1.0')]
- checkLists(l, [])
-
- l = [dist.name for dist in obsoletes_distribution('truffles', '1.0',
- use_egg_info=True)]
- checkLists(l, ['cheese', 'bacon'])
-
-
- l = [dist.name for dist in obsoletes_distribution('truffles', '0.8')]
- checkLists(l, ['choxie'])
-
- l = [dist.name for dist in obsoletes_distribution('truffles', '0.8',
- use_egg_info=True)]
- checkLists(l, ['choxie', 'cheese'])
-
- l = [dist.name for dist in obsoletes_distribution('truffles', '0.9.6')]
- checkLists(l, ['choxie', 'towel-stuff'])
-
- l = [dist.name for dist in obsoletes_distribution('truffles', \
- '0.5.2.3')]
- checkLists(l, ['choxie', 'towel-stuff'])
-
- l = [dist.name for dist in obsoletes_distribution('truffles', '0.2')]
- checkLists(l, ['towel-stuff'])
-
- def test_yield_distribution(self):
- # tests the internal function _yield_distributions
- from distutils2._backport.pkgutil import _yield_distributions
- checkLists = lambda x, y: self.assertListEqual(sorted(x), sorted(y))
-
- eggs = [('bacon', '0.1'), ('banana', '0.4'), ('strawberry', '0.6'),
- ('truffles', '5.0'), ('cheese', '2.0.2')]
- dists = [('choxie', '2.0.0.9'), ('grammar', '1.0a4'),
- ('towel-stuff', '0.1')]
-
- checkLists([], _yield_distributions(False, False))
-
- found = [(dist.name, dist.metadata['Version'])
- for dist in _yield_distributions(False, True)
- if dist.path.startswith(self.fake_dists_path)]
- checkLists(eggs, found)
-
- found = [(dist.name, dist.metadata['Version'])
- for dist in _yield_distributions(True, False)
- if dist.path.startswith(self.fake_dists_path)]
- checkLists(dists, found)
-
- found = [(dist.name, dist.metadata['Version'])
- for dist in _yield_distributions(True, True)
- if dist.path.startswith(self.fake_dists_path)]
- checkLists(dists + eggs, found)
-
-
-def test_suite():
- suite = unittest.TestSuite()
- load = unittest.defaultTestLoader.loadTestsFromTestCase
- suite.addTest(load(TestPkgUtilData))
- suite.addTest(load(TestPkgUtilDistribution))
- suite.addTest(load(TestPkgUtilPEP302))
- suite.addTest(load(TestPkgUtilPEP376))
- return suite
-
-
-def test_main():
- run_unittest(test_suite())
-
-
-if __name__ == "__main__":
- test_main()
diff --git a/src/distutils2/_backport/tests/test_sysconfig.py b/src/distutils2/_backport/tests/test_sysconfig.py
deleted file mode 100644
index 3b51098..0000000
--- a/src/distutils2/_backport/tests/test_sysconfig.py
+++ /dev/null
@@ -1,305 +0,0 @@
-"""Tests for sysconfig."""
-
-import os
-import sys
-import subprocess
-import shutil
-from copy import copy, deepcopy
-from ConfigParser import RawConfigParser
-from StringIO import StringIO
-
-from distutils2._backport import sysconfig
-from distutils2._backport.sysconfig import (
- _expand_globals, _expand_vars, _get_default_scheme, _subst_vars,
- get_config_var, get_config_vars, get_path, get_paths, get_platform,
- get_scheme_names, _main, _SCHEMES)
-
-from distutils2.tests.support import unittest, EnvironGuard
-from test.test_support import TESTFN, unlink
-try:
- from test.test_support import skip_unless_symlink
-except ImportError:
- skip_unless_symlink = unittest.skip(
- 'requires test.test_support.skip_unless_symlink')
-
-class TestSysConfig(EnvironGuard, unittest.TestCase):
-
- def setUp(self):
- super(TestSysConfig, self).setUp()
- self.sys_path = sys.path[:]
- self.makefile = None
- # patching os.uname
- if hasattr(os, 'uname'):
- self.uname = os.uname
- self._uname = os.uname()
- else:
- self.uname = None
- self._uname = None
- os.uname = self._get_uname
- # saving the environment
- self.name = os.name
- self.platform = sys.platform
- self.version = sys.version
- self.maxint = sys.maxint
- self.sep = os.sep
- self.join = os.path.join
- self.isabs = os.path.isabs
- self.splitdrive = os.path.splitdrive
- self._config_vars = copy(sysconfig._CONFIG_VARS)
-
- def tearDown(self):
- sys.path[:] = self.sys_path
- if self.makefile is not None:
- os.unlink(self.makefile)
- self._cleanup_testfn()
- if self.uname is not None:
- os.uname = self.uname
- else:
- del os.uname
- os.name = self.name
- sys.platform = self.platform
- sys.version = self.version
- sys.maxint = self.maxint
- os.sep = self.sep
- os.path.join = self.join
- os.path.isabs = self.isabs
- os.path.splitdrive = self.splitdrive
- sysconfig._CONFIG_VARS = copy(self._config_vars)
- super(TestSysConfig, self).tearDown()
-
- def _set_uname(self, uname):
- self._uname = uname
-
- def _get_uname(self):
- return self._uname
-
- def _cleanup_testfn(self):
- path = TESTFN
- if os.path.isfile(path):
- os.remove(path)
- elif os.path.isdir(path):
- shutil.rmtree(path)
-
- # TODO use a static list or remove the test
- #def test_get_path_names(self):
- # self.assertEqual(get_path_names(), sysconfig._SCHEME_KEYS)
-
- def test_nested_var_substitution(self):
- # Assert that the {curly brace token} expansion pattern will replace
- # only the inner {something} on nested expressions like {py{something}} on
- # the first pass.
-
- # We have no plans to make use of this, but it keeps the option open for
- # the future, at the cost only of disallowing { itself as a piece of a
- # substitution key (which would be weird).
- self.assertEqual(_subst_vars('{py{version}}', {'version': '31'}), '{py31}')
-
- def test_get_paths(self):
- scheme = get_paths()
- default_scheme = _get_default_scheme()
- wanted = _expand_vars(default_scheme, None)
- wanted = sorted(wanted.items())
- scheme = sorted(scheme.items())
- self.assertEqual(scheme, wanted)
-
- def test_get_path(self):
- # xxx make real tests here
- for scheme in _SCHEMES.sections():
- for name, _ in _SCHEMES.items(scheme):
- get_path(name, scheme)
-
- def test_get_config_vars(self):
- cvars = get_config_vars()
- self.assertIsInstance(cvars, dict)
- self.assertTrue(cvars)
-
- def test_get_platform(self):
- # windows XP, 32bits
- os.name = 'nt'
- sys.version = ('2.4.4 (#71, Oct 18 2006, 08:34:43) '
- '[MSC v.1310 32 bit (Intel)]')
- sys.platform = 'win32'
- self.assertEqual(get_platform(), 'win32')
-
- # windows XP, amd64
- os.name = 'nt'
- sys.version = ('2.4.4 (#71, Oct 18 2006, 08:34:43) '
- '[MSC v.1310 32 bit (Amd64)]')
- sys.platform = 'win32'
- self.assertEqual(get_platform(), 'win-amd64')
-
- # windows XP, itanium
- os.name = 'nt'
- sys.version = ('2.4.4 (#71, Oct 18 2006, 08:34:43) '
- '[MSC v.1310 32 bit (Itanium)]')
- sys.platform = 'win32'
- self.assertEqual(get_platform(), 'win-ia64')
-
- # macbook
- os.name = 'posix'
- sys.version = ('2.5 (r25:51918, Sep 19 2006, 08:49:13) '
- '\n[GCC 4.0.1 (Apple Computer, Inc. build 5341)]')
- sys.platform = 'darwin'
- self._set_uname(('Darwin', 'macziade', '8.11.1',
- ('Darwin Kernel Version 8.11.1: '
- 'Wed Oct 10 18:23:28 PDT 2007; '
- 'root:xnu-792.25.20~1/RELEASE_I386'), 'PowerPC'))
- os.environ['MACOSX_DEPLOYMENT_TARGET'] = '10.3'
-
- get_config_vars()['CFLAGS'] = ('-fno-strict-aliasing -DNDEBUG -g '
- '-fwrapv -O3 -Wall -Wstrict-prototypes')
-
- sys.maxint = 2147483647
- self.assertEqual(get_platform(), 'macosx-10.3-ppc')
- sys.maxint = 9223372036854775807
- self.assertEqual(get_platform(), 'macosx-10.3-ppc64')
-
-
- self._set_uname(('Darwin', 'macziade', '8.11.1',
- ('Darwin Kernel Version 8.11.1: '
- 'Wed Oct 10 18:23:28 PDT 2007; '
- 'root:xnu-792.25.20~1/RELEASE_I386'), 'i386'))
- get_config_vars()['MACOSX_DEPLOYMENT_TARGET'] = '10.3'
- os.environ['MACOSX_DEPLOYMENT_TARGET'] = '10.3'
-
- get_config_vars()['CFLAGS'] = ('-fno-strict-aliasing -DNDEBUG -g '
- '-fwrapv -O3 -Wall -Wstrict-prototypes')
-
- sys.maxint = 2147483647
- self.assertEqual(get_platform(), 'macosx-10.3-i386')
- sys.maxint = 9223372036854775807
- self.assertEqual(get_platform(), 'macosx-10.3-x86_64')
-
- # macbook with fat binaries (fat, universal or fat64)
- os.environ['MACOSX_DEPLOYMENT_TARGET'] = '10.4'
- get_config_vars()['CFLAGS'] = ('-arch ppc -arch i386 -isysroot '
- '/Developer/SDKs/MacOSX10.4u.sdk '
- '-fno-strict-aliasing -fno-common '
- '-dynamic -DNDEBUG -g -O3')
-
- self.assertEqual(get_platform(), 'macosx-10.4-fat')
-
- get_config_vars()['CFLAGS'] = ('-arch x86_64 -arch i386 -isysroot '
- '/Developer/SDKs/MacOSX10.4u.sdk '
- '-fno-strict-aliasing -fno-common '
- '-dynamic -DNDEBUG -g -O3')
-
- self.assertEqual(get_platform(), 'macosx-10.4-intel')
-
- get_config_vars()['CFLAGS'] = ('-arch x86_64 -arch ppc -arch i386 -isysroot '
- '/Developer/SDKs/MacOSX10.4u.sdk '
- '-fno-strict-aliasing -fno-common '
- '-dynamic -DNDEBUG -g -O3')
- self.assertEqual(get_platform(), 'macosx-10.4-fat3')
-
- get_config_vars()['CFLAGS'] = ('-arch ppc64 -arch x86_64 -arch ppc -arch i386 -isysroot '
- '/Developer/SDKs/MacOSX10.4u.sdk '
- '-fno-strict-aliasing -fno-common '
- '-dynamic -DNDEBUG -g -O3')
- self.assertEqual(get_platform(), 'macosx-10.4-universal')
-
- get_config_vars()['CFLAGS'] = ('-arch x86_64 -arch ppc64 -isysroot '
- '/Developer/SDKs/MacOSX10.4u.sdk '
- '-fno-strict-aliasing -fno-common '
- '-dynamic -DNDEBUG -g -O3')
-
- self.assertEqual(get_platform(), 'macosx-10.4-fat64')
-
- for arch in ('ppc', 'i386', 'x86_64', 'ppc64'):
- get_config_vars()['CFLAGS'] = ('-arch %s -isysroot '
- '/Developer/SDKs/MacOSX10.4u.sdk '
- '-fno-strict-aliasing -fno-common '
- '-dynamic -DNDEBUG -g -O3'%(arch,))
-
- self.assertEqual(get_platform(), 'macosx-10.4-%s'%(arch,))
-
- # linux debian sarge
- os.name = 'posix'
- sys.version = ('2.3.5 (#1, Jul 4 2007, 17:28:59) '
- '\n[GCC 4.1.2 20061115 (prerelease) (Debian 4.1.1-21)]')
- sys.platform = 'linux2'
- self._set_uname(('Linux', 'aglae', '2.6.21.1dedibox-r7',
- '#1 Mon Apr 30 17:25:38 CEST 2007', 'i686'))
-
- self.assertEqual(get_platform(), 'linux-i686')
-
- # XXX more platforms to tests here
-
- def test_get_config_h_filename(self):
- config_h = sysconfig.get_config_h_filename()
- self.assertTrue(os.path.isfile(config_h), config_h)
-
- def test_get_scheme_names(self):
- wanted = ('nt', 'nt_user', 'os2', 'os2_home', 'osx_framework_user',
- 'posix_home', 'posix_prefix', 'posix_user')
- self.assertEqual(get_scheme_names(), wanted)
-
- @skip_unless_symlink
- def test_symlink(self):
- # On Windows, the EXE needs to know where pythonXY.dll is at so we have
- # to add the directory to the path.
- if sys.platform == 'win32':
- os.environ['Path'] = ';'.join((
- os.path.dirname(sys.executable), os.environ['Path']))
-
- # Issue 7880
- def get(python):
- cmd = [python, '-c',
- 'import sysconfig; print(sysconfig.get_platform())']
- p = subprocess.Popen(cmd, stdout=subprocess.PIPE, env=os.environ)
- return p.communicate()
- real = os.path.realpath(sys.executable)
- link = os.path.abspath(TESTFN)
- os.symlink(real, link)
- try:
- self.assertEqual(get(real), get(link))
- finally:
- unlink(link)
-
- @unittest.skipIf(sys.version < '2.6', 'requires Python 2.6 or higher')
- def test_user_similar(self):
- # Issue 8759 : make sure the posix scheme for the users
- # is similar to the global posix_prefix one
- base = get_config_var('base')
- user = get_config_var('userbase')
- for name in ('stdlib', 'platstdlib', 'purelib', 'platlib'):
- global_path = get_path(name, 'posix_prefix')
- user_path = get_path(name, 'posix_user')
- self.assertEqual(user_path, global_path.replace(base, user))
-
- def test_main(self):
- # just making sure _main() runs and returns things in the stdout
- self.addCleanup(setattr, sys, 'stdout', sys.stdout)
- sys.stdout = StringIO()
- _main()
- self.assertGreater(len(sys.stdout.getvalue().split('\n')), 0)
-
- @unittest.skipIf(sys.platform == 'win32', 'does not apply to Windows')
- def test_ldshared_value(self):
- ldflags = sysconfig.get_config_var('LDFLAGS')
- ldshared = sysconfig.get_config_var('LDSHARED')
-
- self.assertIn(ldflags, ldshared)
-
- def test_expand_globals(self):
- config = RawConfigParser()
- config.add_section('globals')
- config.set('globals', 'foo', 'ok')
- config.add_section('posix')
- config.set('posix', 'config', '/etc')
- config.set('posix', 'more', '{config}/ok')
-
- _expand_globals(config)
-
- self.assertEqual(config.get('posix', 'foo'), 'ok')
- self.assertEqual(config.get('posix', 'more'), '/etc/ok')
-
- # we might not have globals after all
- # extending again (==no more globals section)
- _expand_globals(config)
-
-def test_suite():
- return unittest.makeSuite(TestSysConfig)
-
-if __name__ == '__main__':
- unittest.main(defaultTest='test_suite')
diff --git a/src/distutils2/_trove.py b/src/distutils2/_trove.py
deleted file mode 100644
index a215e9d..0000000
--- a/src/distutils2/_trove.py
+++ /dev/null
@@ -1,552 +0,0 @@
-# Temporary helper for mkpkg.
-
-# XXX get the list from PyPI and cache it instead of hardcoding
-
-# XXX see if it would be more useful to store it as another structure
-# than a list of strings
-
-all_classifiers = [
- 'Development Status :: 1 - Planning',
- 'Development Status :: 2 - Pre-Alpha',
- 'Development Status :: 3 - Alpha',
- 'Development Status :: 4 - Beta',
- 'Development Status :: 5 - Production/Stable',
- 'Development Status :: 6 - Mature',
- 'Development Status :: 7 - Inactive',
- 'Environment :: Console',
- 'Environment :: Console :: Curses',
- 'Environment :: Console :: Framebuffer',
- 'Environment :: Console :: Newt',
- 'Environment :: Console :: svgalib',
- "Environment :: Handhelds/PDA's",
- 'Environment :: MacOS X',
- 'Environment :: MacOS X :: Aqua',
- 'Environment :: MacOS X :: Carbon',
- 'Environment :: MacOS X :: Cocoa',
- 'Environment :: No Input/Output (Daemon)',
- 'Environment :: Other Environment',
- 'Environment :: Plugins',
- 'Environment :: Web Environment',
- 'Environment :: Web Environment :: Buffet',
- 'Environment :: Web Environment :: Mozilla',
- 'Environment :: Web Environment :: ToscaWidgets',
- 'Environment :: Win32 (MS Windows)',
- 'Environment :: X11 Applications',
- 'Environment :: X11 Applications :: Gnome',
- 'Environment :: X11 Applications :: GTK',
- 'Environment :: X11 Applications :: KDE',
- 'Environment :: X11 Applications :: Qt',
- 'Framework :: BFG',
- 'Framework :: Buildout',
- 'Framework :: Chandler',
- 'Framework :: CubicWeb',
- 'Framework :: Django',
- 'Framework :: IDLE',
- 'Framework :: Paste',
- 'Framework :: Plone',
- 'Framework :: Pylons',
- 'Framework :: Setuptools Plugin',
- 'Framework :: Trac',
- 'Framework :: TurboGears',
- 'Framework :: TurboGears :: Applications',
- 'Framework :: TurboGears :: Widgets',
- 'Framework :: Twisted',
- 'Framework :: ZODB',
- 'Framework :: Zope2',
- 'Framework :: Zope3',
- 'Intended Audience :: Customer Service',
- 'Intended Audience :: Developers',
- 'Intended Audience :: Education',
- 'Intended Audience :: End Users/Desktop',
- 'Intended Audience :: Financial and Insurance Industry',
- 'Intended Audience :: Healthcare Industry',
- 'Intended Audience :: Information Technology',
- 'Intended Audience :: Legal Industry',
- 'Intended Audience :: Manufacturing',
- 'Intended Audience :: Other Audience',
- 'Intended Audience :: Religion',
- 'Intended Audience :: Science/Research',
- 'Intended Audience :: System Administrators',
- 'Intended Audience :: Telecommunications Industry',
- 'License :: Aladdin Free Public License (AFPL)',
- 'License :: DFSG approved',
- 'License :: Eiffel Forum License (EFL)',
- 'License :: Free For Educational Use',
- 'License :: Free For Home Use',
- 'License :: Free for non-commercial use',
- 'License :: Freely Distributable',
- 'License :: Free To Use But Restricted',
- 'License :: Freeware',
- 'License :: Netscape Public License (NPL)',
- 'License :: Nokia Open Source License (NOKOS)',
- 'License :: OSI Approved',
- 'License :: OSI Approved :: Academic Free License (AFL)',
- 'License :: OSI Approved :: Apache Software License',
- 'License :: OSI Approved :: Apple Public Source License',
- 'License :: OSI Approved :: Artistic License',
- 'License :: OSI Approved :: Attribution Assurance License',
- 'License :: OSI Approved :: BSD License',
- 'License :: OSI Approved :: Common Public License',
- 'License :: OSI Approved :: Eiffel Forum License',
- 'License :: OSI Approved :: European Union Public Licence 1.0 (EUPL 1.0)',
- 'License :: OSI Approved :: European Union Public Licence 1.1 (EUPL 1.1)',
- 'License :: OSI Approved :: GNU Affero General Public License v3',
- 'License :: OSI Approved :: GNU Free Documentation License (FDL)',
- 'License :: OSI Approved :: GNU General Public License (GPL)',
- 'License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL)',
- 'License :: OSI Approved :: IBM Public License',
- 'License :: OSI Approved :: Intel Open Source License',
- 'License :: OSI Approved :: ISC License (ISCL)',
- 'License :: OSI Approved :: Jabber Open Source License',
- 'License :: OSI Approved :: MIT License',
- 'License :: OSI Approved :: MITRE Collaborative Virtual Workspace License (CVW)',
- 'License :: OSI Approved :: Motosoto License',
- 'License :: OSI Approved :: Mozilla Public License 1.0 (MPL)',
- 'License :: OSI Approved :: Mozilla Public License 1.1 (MPL 1.1)',
- 'License :: OSI Approved :: Nethack General Public License',
- 'License :: OSI Approved :: Nokia Open Source License',
- 'License :: OSI Approved :: Open Group Test Suite License',
- 'License :: OSI Approved :: Python License (CNRI Python License)',
- 'License :: OSI Approved :: Python Software Foundation License',
- 'License :: OSI Approved :: Qt Public License (QPL)',
- 'License :: OSI Approved :: Ricoh Source Code Public License',
- 'License :: OSI Approved :: Sleepycat License',
- 'License :: OSI Approved :: Sun Industry Standards Source License (SISSL)',
- 'License :: OSI Approved :: Sun Public License',
- 'License :: OSI Approved :: University of Illinois/NCSA Open Source License',
- 'License :: OSI Approved :: Vovida Software License 1.0',
- 'License :: OSI Approved :: W3C License',
- 'License :: OSI Approved :: X.Net License',
- 'License :: OSI Approved :: zlib/libpng License',
- 'License :: OSI Approved :: Zope Public License',
- 'License :: Other/Proprietary License',
- 'License :: Public Domain',
- 'License :: Repoze Public License',
- 'Natural Language :: Afrikaans',
- 'Natural Language :: Arabic',
- 'Natural Language :: Bengali',
- 'Natural Language :: Bosnian',
- 'Natural Language :: Bulgarian',
- 'Natural Language :: Catalan',
- 'Natural Language :: Chinese (Simplified)',
- 'Natural Language :: Chinese (Traditional)',
- 'Natural Language :: Croatian',
- 'Natural Language :: Czech',
- 'Natural Language :: Danish',
- 'Natural Language :: Dutch',
- 'Natural Language :: English',
- 'Natural Language :: Esperanto',
- 'Natural Language :: Finnish',
- 'Natural Language :: French',
- 'Natural Language :: German',
- 'Natural Language :: Greek',
- 'Natural Language :: Hebrew',
- 'Natural Language :: Hindi',
- 'Natural Language :: Hungarian',
- 'Natural Language :: Icelandic',
- 'Natural Language :: Indonesian',
- 'Natural Language :: Italian',
- 'Natural Language :: Japanese',
- 'Natural Language :: Javanese',
- 'Natural Language :: Korean',
- 'Natural Language :: Latin',
- 'Natural Language :: Latvian',
- 'Natural Language :: Macedonian',
- 'Natural Language :: Malay',
- 'Natural Language :: Marathi',
- 'Natural Language :: Norwegian',
- 'Natural Language :: Panjabi',
- 'Natural Language :: Persian',
- 'Natural Language :: Polish',
- 'Natural Language :: Portuguese',
- 'Natural Language :: Portuguese (Brazilian)',
- 'Natural Language :: Romanian',
- 'Natural Language :: Russian',
- 'Natural Language :: Serbian',
- 'Natural Language :: Slovak',
- 'Natural Language :: Slovenian',
- 'Natural Language :: Spanish',
- 'Natural Language :: Swedish',
- 'Natural Language :: Tamil',
- 'Natural Language :: Telugu',
- 'Natural Language :: Thai',
- 'Natural Language :: Turkish',
- 'Natural Language :: Ukranian',
- 'Natural Language :: Urdu',
- 'Natural Language :: Vietnamese',
- 'Operating System :: BeOS',
- 'Operating System :: MacOS',
- 'Operating System :: MacOS :: MacOS 9',
- 'Operating System :: MacOS :: MacOS X',
- 'Operating System :: Microsoft',
- 'Operating System :: Microsoft :: MS-DOS',
- 'Operating System :: Microsoft :: Windows',
- 'Operating System :: Microsoft :: Windows :: Windows 3.1 or Earlier',
- 'Operating System :: Microsoft :: Windows :: Windows 95/98/2000',
- 'Operating System :: Microsoft :: Windows :: Windows CE',
- 'Operating System :: Microsoft :: Windows :: Windows NT/2000',
- 'Operating System :: OS/2',
- 'Operating System :: OS Independent',
- 'Operating System :: Other OS',
- 'Operating System :: PalmOS',
- 'Operating System :: PDA Systems',
- 'Operating System :: POSIX',
- 'Operating System :: POSIX :: AIX',
- 'Operating System :: POSIX :: BSD',
- 'Operating System :: POSIX :: BSD :: BSD/OS',
- 'Operating System :: POSIX :: BSD :: FreeBSD',
- 'Operating System :: POSIX :: BSD :: NetBSD',
- 'Operating System :: POSIX :: BSD :: OpenBSD',
- 'Operating System :: POSIX :: GNU Hurd',
- 'Operating System :: POSIX :: HP-UX',
- 'Operating System :: POSIX :: IRIX',
- 'Operating System :: POSIX :: Linux',
- 'Operating System :: POSIX :: Other',
- 'Operating System :: POSIX :: SCO',
- 'Operating System :: POSIX :: SunOS/Solaris',
- 'Operating System :: Unix',
- 'Programming Language :: Ada',
- 'Programming Language :: APL',
- 'Programming Language :: ASP',
- 'Programming Language :: Assembly',
- 'Programming Language :: Awk',
- 'Programming Language :: Basic',
- 'Programming Language :: C',
- 'Programming Language :: C#',
- 'Programming Language :: C++',
- 'Programming Language :: Cold Fusion',
- 'Programming Language :: Cython',
- 'Programming Language :: Delphi/Kylix',
- 'Programming Language :: Dylan',
- 'Programming Language :: Eiffel',
- 'Programming Language :: Emacs-Lisp',
- 'Programming Language :: Erlang',
- 'Programming Language :: Euler',
- 'Programming Language :: Euphoria',
- 'Programming Language :: Forth',
- 'Programming Language :: Fortran',
- 'Programming Language :: Haskell',
- 'Programming Language :: Java',
- 'Programming Language :: JavaScript',
- 'Programming Language :: Lisp',
- 'Programming Language :: Logo',
- 'Programming Language :: ML',
- 'Programming Language :: Modula',
- 'Programming Language :: Objective C',
- 'Programming Language :: Object Pascal',
- 'Programming Language :: OCaml',
- 'Programming Language :: Other',
- 'Programming Language :: Other Scripting Engines',
- 'Programming Language :: Pascal',
- 'Programming Language :: Perl',
- 'Programming Language :: PHP',
- 'Programming Language :: Pike',
- 'Programming Language :: Pliant',
- 'Programming Language :: PL/SQL',
- 'Programming Language :: PROGRESS',
- 'Programming Language :: Prolog',
- 'Programming Language :: Python',
- 'Programming Language :: Python :: 2',
- 'Programming Language :: Python :: 2.3',
- 'Programming Language :: Python :: 2.4',
- 'Programming Language :: Python :: 2.5',
- 'Programming Language :: Python :: 2.6',
- 'Programming Language :: Python :: 2.7',
- 'Programming Language :: Python :: 3',
- 'Programming Language :: Python :: 3.0',
- 'Programming Language :: Python :: 3.1',
- 'Programming Language :: Python :: 3.2',
- 'Programming Language :: REBOL',
- 'Programming Language :: Rexx',
- 'Programming Language :: Ruby',
- 'Programming Language :: Scheme',
- 'Programming Language :: Simula',
- 'Programming Language :: Smalltalk',
- 'Programming Language :: SQL',
- 'Programming Language :: Tcl',
- 'Programming Language :: Unix Shell',
- 'Programming Language :: Visual Basic',
- 'Programming Language :: XBasic',
- 'Programming Language :: YACC',
- 'Programming Language :: Zope',
- 'Topic :: Adaptive Technologies',
- 'Topic :: Artistic Software',
- 'Topic :: Communications',
- 'Topic :: Communications :: BBS',
- 'Topic :: Communications :: Chat',
- 'Topic :: Communications :: Chat :: AOL Instant Messenger',
- 'Topic :: Communications :: Chat :: ICQ',
- 'Topic :: Communications :: Chat :: Internet Relay Chat',
- 'Topic :: Communications :: Chat :: Unix Talk',
- 'Topic :: Communications :: Conferencing',
- 'Topic :: Communications :: Email',
- 'Topic :: Communications :: Email :: Address Book',
- 'Topic :: Communications :: Email :: Email Clients (MUA)',
- 'Topic :: Communications :: Email :: Filters',
- 'Topic :: Communications :: Email :: Mailing List Servers',
- 'Topic :: Communications :: Email :: Mail Transport Agents',
- 'Topic :: Communications :: Email :: Post-Office',
- 'Topic :: Communications :: Email :: Post-Office :: IMAP',
- 'Topic :: Communications :: Email :: Post-Office :: POP3',
- 'Topic :: Communications :: Fax',
- 'Topic :: Communications :: FIDO',
- 'Topic :: Communications :: File Sharing',
- 'Topic :: Communications :: File Sharing :: Gnutella',
- 'Topic :: Communications :: File Sharing :: Napster',
- 'Topic :: Communications :: Ham Radio',
- 'Topic :: Communications :: Internet Phone',
- 'Topic :: Communications :: Telephony',
- 'Topic :: Communications :: Usenet News',
- 'Topic :: Database',
- 'Topic :: Database :: Database Engines/Servers',
- 'Topic :: Database :: Front-Ends',
- 'Topic :: Desktop Environment',
- 'Topic :: Desktop Environment :: File Managers',
- 'Topic :: Desktop Environment :: Gnome',
- 'Topic :: Desktop Environment :: GNUstep',
- 'Topic :: Desktop Environment :: K Desktop Environment (KDE)',
- 'Topic :: Desktop Environment :: K Desktop Environment (KDE) :: Themes',
- 'Topic :: Desktop Environment :: PicoGUI',
- 'Topic :: Desktop Environment :: PicoGUI :: Applications',
- 'Topic :: Desktop Environment :: PicoGUI :: Themes',
- 'Topic :: Desktop Environment :: Screen Savers',
- 'Topic :: Desktop Environment :: Window Managers',
- 'Topic :: Desktop Environment :: Window Managers :: Afterstep',
- 'Topic :: Desktop Environment :: Window Managers :: Afterstep :: Themes',
- 'Topic :: Desktop Environment :: Window Managers :: Applets',
- 'Topic :: Desktop Environment :: Window Managers :: Blackbox',
- 'Topic :: Desktop Environment :: Window Managers :: Blackbox :: Themes',
- 'Topic :: Desktop Environment :: Window Managers :: CTWM',
- 'Topic :: Desktop Environment :: Window Managers :: CTWM :: Themes',
- 'Topic :: Desktop Environment :: Window Managers :: Enlightenment',
- 'Topic :: Desktop Environment :: Window Managers :: Enlightenment :: Epplets',
- 'Topic :: Desktop Environment :: Window Managers :: Enlightenment :: Themes DR15',
- 'Topic :: Desktop Environment :: Window Managers :: Enlightenment :: Themes DR16',
- 'Topic :: Desktop Environment :: Window Managers :: Enlightenment :: Themes DR17',
- 'Topic :: Desktop Environment :: Window Managers :: Fluxbox',
- 'Topic :: Desktop Environment :: Window Managers :: Fluxbox :: Themes',
- 'Topic :: Desktop Environment :: Window Managers :: FVWM',
- 'Topic :: Desktop Environment :: Window Managers :: FVWM :: Themes',
- 'Topic :: Desktop Environment :: Window Managers :: IceWM',
- 'Topic :: Desktop Environment :: Window Managers :: IceWM :: Themes',
- 'Topic :: Desktop Environment :: Window Managers :: MetaCity',
- 'Topic :: Desktop Environment :: Window Managers :: MetaCity :: Themes',
- 'Topic :: Desktop Environment :: Window Managers :: Oroborus',
- 'Topic :: Desktop Environment :: Window Managers :: Oroborus :: Themes',
- 'Topic :: Desktop Environment :: Window Managers :: Sawfish',
- 'Topic :: Desktop Environment :: Window Managers :: Sawfish :: Themes 0.30',
- 'Topic :: Desktop Environment :: Window Managers :: Sawfish :: Themes pre-0.30',
- 'Topic :: Desktop Environment :: Window Managers :: Waimea',
- 'Topic :: Desktop Environment :: Window Managers :: Waimea :: Themes',
- 'Topic :: Desktop Environment :: Window Managers :: Window Maker',
- 'Topic :: Desktop Environment :: Window Managers :: Window Maker :: Applets',
- 'Topic :: Desktop Environment :: Window Managers :: Window Maker :: Themes',
- 'Topic :: Desktop Environment :: Window Managers :: XFCE',
- 'Topic :: Desktop Environment :: Window Managers :: XFCE :: Themes',
- 'Topic :: Documentation',
- 'Topic :: Education',
- 'Topic :: Education :: Computer Aided Instruction (CAI)',
- 'Topic :: Education :: Testing',
- 'Topic :: Games/Entertainment',
- 'Topic :: Games/Entertainment :: Arcade',
- 'Topic :: Games/Entertainment :: Board Games',
- 'Topic :: Games/Entertainment :: First Person Shooters',
- 'Topic :: Games/Entertainment :: Fortune Cookies',
- 'Topic :: Games/Entertainment :: Multi-User Dungeons (MUD)',
- 'Topic :: Games/Entertainment :: Puzzle Games',
- 'Topic :: Games/Entertainment :: Real Time Strategy',
- 'Topic :: Games/Entertainment :: Role-Playing',
- 'Topic :: Games/Entertainment :: Side-Scrolling/Arcade Games',
- 'Topic :: Games/Entertainment :: Simulation',
- 'Topic :: Games/Entertainment :: Turn Based Strategy',
- 'Topic :: Home Automation',
- 'Topic :: Internet',
- 'Topic :: Internet :: File Transfer Protocol (FTP)',
- 'Topic :: Internet :: Finger',
- 'Topic :: Internet :: Log Analysis',
- 'Topic :: Internet :: Name Service (DNS)',
- 'Topic :: Internet :: Proxy Servers',
- 'Topic :: Internet :: WAP',
- 'Topic :: Internet :: WWW/HTTP',
- 'Topic :: Internet :: WWW/HTTP :: Browsers',
- 'Topic :: Internet :: WWW/HTTP :: Dynamic Content',
- 'Topic :: Internet :: WWW/HTTP :: Dynamic Content :: CGI Tools/Libraries',
- 'Topic :: Internet :: WWW/HTTP :: Dynamic Content :: Message Boards',
- 'Topic :: Internet :: WWW/HTTP :: Dynamic Content :: News/Diary',
- 'Topic :: Internet :: WWW/HTTP :: Dynamic Content :: Page Counters',
- 'Topic :: Internet :: WWW/HTTP :: HTTP Servers',
- 'Topic :: Internet :: WWW/HTTP :: Indexing/Search',
- 'Topic :: Internet :: WWW/HTTP :: Site Management',
- 'Topic :: Internet :: WWW/HTTP :: Site Management :: Link Checking',
- 'Topic :: Internet :: WWW/HTTP :: WSGI',
- 'Topic :: Internet :: WWW/HTTP :: WSGI :: Application',
- 'Topic :: Internet :: WWW/HTTP :: WSGI :: Middleware',
- 'Topic :: Internet :: WWW/HTTP :: WSGI :: Server',
- 'Topic :: Internet :: Z39.50',
- 'Topic :: Multimedia',
- 'Topic :: Multimedia :: Graphics',
- 'Topic :: Multimedia :: Graphics :: 3D Modeling',
- 'Topic :: Multimedia :: Graphics :: 3D Rendering',
- 'Topic :: Multimedia :: Graphics :: Capture',
- 'Topic :: Multimedia :: Graphics :: Capture :: Digital Camera',
- 'Topic :: Multimedia :: Graphics :: Capture :: Scanners',
- 'Topic :: Multimedia :: Graphics :: Capture :: Screen Capture',
- 'Topic :: Multimedia :: Graphics :: Editors',
- 'Topic :: Multimedia :: Graphics :: Editors :: Raster-Based',
- 'Topic :: Multimedia :: Graphics :: Editors :: Vector-Based',
- 'Topic :: Multimedia :: Graphics :: Graphics Conversion',
- 'Topic :: Multimedia :: Graphics :: Presentation',
- 'Topic :: Multimedia :: Graphics :: Viewers',
- 'Topic :: Multimedia :: Sound/Audio',
- 'Topic :: Multimedia :: Sound/Audio :: Analysis',
- 'Topic :: Multimedia :: Sound/Audio :: Capture/Recording',
- 'Topic :: Multimedia :: Sound/Audio :: CD Audio',
- 'Topic :: Multimedia :: Sound/Audio :: CD Audio :: CD Playing',
- 'Topic :: Multimedia :: Sound/Audio :: CD Audio :: CD Ripping',
- 'Topic :: Multimedia :: Sound/Audio :: CD Audio :: CD Writing',
- 'Topic :: Multimedia :: Sound/Audio :: Conversion',
- 'Topic :: Multimedia :: Sound/Audio :: Editors',
- 'Topic :: Multimedia :: Sound/Audio :: MIDI',
- 'Topic :: Multimedia :: Sound/Audio :: Mixers',
- 'Topic :: Multimedia :: Sound/Audio :: Players',
- 'Topic :: Multimedia :: Sound/Audio :: Players :: MP3',
- 'Topic :: Multimedia :: Sound/Audio :: Sound Synthesis',
- 'Topic :: Multimedia :: Sound/Audio :: Speech',
- 'Topic :: Multimedia :: Video',
- 'Topic :: Multimedia :: Video :: Capture',
- 'Topic :: Multimedia :: Video :: Conversion',
- 'Topic :: Multimedia :: Video :: Display',
- 'Topic :: Multimedia :: Video :: Non-Linear Editor',
- 'Topic :: Office/Business',
- 'Topic :: Office/Business :: Financial',
- 'Topic :: Office/Business :: Financial :: Accounting',
- 'Topic :: Office/Business :: Financial :: Investment',
- 'Topic :: Office/Business :: Financial :: Point-Of-Sale',
- 'Topic :: Office/Business :: Financial :: Spreadsheet',
- 'Topic :: Office/Business :: Groupware',
- 'Topic :: Office/Business :: News/Diary',
- 'Topic :: Office/Business :: Office Suites',
- 'Topic :: Office/Business :: Scheduling',
- 'Topic :: Other/Nonlisted Topic',
- 'Topic :: Printing',
- 'Topic :: Religion',
- 'Topic :: Scientific/Engineering',
- 'Topic :: Scientific/Engineering :: Artificial Intelligence',
- 'Topic :: Scientific/Engineering :: Astronomy',
- 'Topic :: Scientific/Engineering :: Atmospheric Science',
- 'Topic :: Scientific/Engineering :: Bio-Informatics',
- 'Topic :: Scientific/Engineering :: Chemistry',
- 'Topic :: Scientific/Engineering :: Electronic Design Automation (EDA)',
- 'Topic :: Scientific/Engineering :: GIS',
- 'Topic :: Scientific/Engineering :: Human Machine Interfaces',
- 'Topic :: Scientific/Engineering :: Image Recognition',
- 'Topic :: Scientific/Engineering :: Information Analysis',
- 'Topic :: Scientific/Engineering :: Interface Engine/Protocol Translator',
- 'Topic :: Scientific/Engineering :: Mathematics',
- 'Topic :: Scientific/Engineering :: Medical Science Apps.',
- 'Topic :: Scientific/Engineering :: Physics',
- 'Topic :: Scientific/Engineering :: Visualization',
- 'Topic :: Security',
- 'Topic :: Security :: Cryptography',
- 'Topic :: Sociology',
- 'Topic :: Sociology :: Genealogy',
- 'Topic :: Sociology :: History',
- 'Topic :: Software Development',
- 'Topic :: Software Development :: Assemblers',
- 'Topic :: Software Development :: Bug Tracking',
- 'Topic :: Software Development :: Build Tools',
- 'Topic :: Software Development :: Code Generators',
- 'Topic :: Software Development :: Compilers',
- 'Topic :: Software Development :: Debuggers',
- 'Topic :: Software Development :: Disassemblers',
- 'Topic :: Software Development :: Documentation',
- 'Topic :: Software Development :: Embedded Systems',
- 'Topic :: Software Development :: Internationalization',
- 'Topic :: Software Development :: Interpreters',
- 'Topic :: Software Development :: Libraries',
- 'Topic :: Software Development :: Libraries :: Application Frameworks',
- 'Topic :: Software Development :: Libraries :: Java Libraries',
- 'Topic :: Software Development :: Libraries :: Perl Modules',
- 'Topic :: Software Development :: Libraries :: PHP Classes',
- 'Topic :: Software Development :: Libraries :: Pike Modules',
- 'Topic :: Software Development :: Libraries :: pygame',
- 'Topic :: Software Development :: Libraries :: Python Modules',
- 'Topic :: Software Development :: Libraries :: Ruby Modules',
- 'Topic :: Software Development :: Libraries :: Tcl Extensions',
- 'Topic :: Software Development :: Localization',
- 'Topic :: Software Development :: Object Brokering',
- 'Topic :: Software Development :: Object Brokering :: CORBA',
- 'Topic :: Software Development :: Pre-processors',
- 'Topic :: Software Development :: Quality Assurance',
- 'Topic :: Software Development :: Testing',
- 'Topic :: Software Development :: Testing :: Traffic Generation',
- 'Topic :: Software Development :: User Interfaces',
- 'Topic :: Software Development :: Version Control',
- 'Topic :: Software Development :: Version Control :: CVS',
- 'Topic :: Software Development :: Version Control :: RCS',
- 'Topic :: Software Development :: Version Control :: SCCS',
- 'Topic :: Software Development :: Widget Sets',
- 'Topic :: System',
- 'Topic :: System :: Archiving',
- 'Topic :: System :: Archiving :: Backup',
- 'Topic :: System :: Archiving :: Compression',
- 'Topic :: System :: Archiving :: Mirroring',
- 'Topic :: System :: Archiving :: Packaging',
- 'Topic :: System :: Benchmark',
- 'Topic :: System :: Boot',
- 'Topic :: System :: Boot :: Init',
- 'Topic :: System :: Clustering',
- 'Topic :: System :: Console Fonts',
- 'Topic :: System :: Distributed Computing',
- 'Topic :: System :: Emulators',
- 'Topic :: System :: Filesystems',
- 'Topic :: System :: Hardware',
- 'Topic :: System :: Hardware :: Hardware Drivers',
- 'Topic :: System :: Hardware :: Mainframes',
- 'Topic :: System :: Hardware :: Symmetric Multi-processing',
- 'Topic :: System :: Installation/Setup',
- 'Topic :: System :: Logging',
- 'Topic :: System :: Monitoring',
- 'Topic :: System :: Networking',
- 'Topic :: System :: Networking :: Firewalls',
- 'Topic :: System :: Networking :: Monitoring',
- 'Topic :: System :: Networking :: Monitoring :: Hardware Watchdog',
- 'Topic :: System :: Networking :: Time Synchronization',
- 'Topic :: System :: Operating System',
- 'Topic :: System :: Operating System Kernels',
- 'Topic :: System :: Operating System Kernels :: BSD',
- 'Topic :: System :: Operating System Kernels :: GNU Hurd',
- 'Topic :: System :: Operating System Kernels :: Linux',
- 'Topic :: System :: Power (UPS)',
- 'Topic :: System :: Recovery Tools',
- 'Topic :: System :: Shells',
- 'Topic :: System :: Software Distribution',
- 'Topic :: System :: Systems Administration',
- 'Topic :: System :: Systems Administration :: Authentication/Directory',
- 'Topic :: System :: Systems Administration :: Authentication/Directory :: LDAP',
- 'Topic :: System :: Systems Administration :: Authentication/Directory :: NIS',
- 'Topic :: System :: System Shells',
- 'Topic :: Terminals',
- 'Topic :: Terminals :: Serial',
- 'Topic :: Terminals :: Telnet',
- 'Topic :: Terminals :: Terminal Emulators/X Terminals',
- 'Topic :: Text Editors',
- 'Topic :: Text Editors :: Documentation',
- 'Topic :: Text Editors :: Emacs',
- 'Topic :: Text Editors :: Integrated Development Environments (IDE)',
- 'Topic :: Text Editors :: Text Processing',
- 'Topic :: Text Editors :: Word Processors',
- 'Topic :: Text Processing',
- 'Topic :: Text Processing :: Filters',
- 'Topic :: Text Processing :: Fonts',
- 'Topic :: Text Processing :: General',
- 'Topic :: Text Processing :: Indexing',
- 'Topic :: Text Processing :: Linguistic',
- 'Topic :: Text Processing :: Markup',
- 'Topic :: Text Processing :: Markup :: HTML',
- 'Topic :: Text Processing :: Markup :: LaTeX',
- 'Topic :: Text Processing :: Markup :: SGML',
- 'Topic :: Text Processing :: Markup :: VRML',
- 'Topic :: Text Processing :: Markup :: XML',
- 'Topic :: Utilities',
-]
diff --git a/src/distutils2/command/__init__.py b/src/distutils2/command/__init__.py
deleted file mode 100644
index 4ae17ae..0000000
--- a/src/distutils2/command/__init__.py
+++ /dev/null
@@ -1,28 +0,0 @@
-"""distutils.command
-
-Package containing implementation of all the standard Distutils
-commands."""
-
-__revision__ = "$Id: __init__.py 71473 2009-04-11 14:55:07Z tarek.ziade $"
-
-__all__ = ['check',
- 'test',
- 'build',
- 'build_py',
- 'build_ext',
- 'build_clib',
- 'build_scripts',
- 'clean',
- 'install',
- 'install_lib',
- 'install_headers',
- 'install_scripts',
- 'install_data',
- 'install_distinfo',
- 'sdist',
- 'bdist',
- 'bdist_dumb',
- 'bdist_wininst',
- 'register',
- 'upload',
- ]
diff --git a/src/distutils2/command/bdist.py b/src/distutils2/command/bdist.py
deleted file mode 100644
index 147a31e..0000000
--- a/src/distutils2/command/bdist.py
+++ /dev/null
@@ -1,140 +0,0 @@
-"""distutils.command.bdist
-
-Implements the Distutils 'bdist' command (create a built [binary]
-distribution)."""
-
-__revision__ = "$Id: bdist.py 77761 2010-01-26 22:46:15Z tarek.ziade $"
-
-import os
-
-from distutils2.util import get_platform
-from distutils2.core import Command
-from distutils2.errors import DistutilsPlatformError, DistutilsOptionError
-
-
-def show_formats():
- """Print list of available formats (arguments to "--format" option).
- """
- from distutils2.fancy_getopt import FancyGetopt
- formats = []
- for format in bdist.format_commands:
- formats.append(("formats=" + format, None,
- bdist.format_command[format][1]))
- pretty_printer = FancyGetopt(formats)
- pretty_printer.print_help("List of available distribution formats:")
-
-
-class bdist(Command):
-
- description = "create a built (binary) distribution"
-
- user_options = [('bdist-base=', 'b',
- "temporary directory for creating built distributions"),
- ('plat-name=', 'p',
- "platform name to embed in generated filenames "
- "(default: %s)" % get_platform()),
- ('formats=', None,
- "formats for distribution (comma-separated list)"),
- ('dist-dir=', 'd',
- "directory to put final built distributions in "
- "[default: dist]"),
- ('skip-build', None,
- "skip rebuilding everything (for testing/debugging)"),
- ('owner=', 'u',
- "Owner name used when creating a tar file"
- " [default: current user]"),
- ('group=', 'g',
- "Group name used when creating a tar file"
- " [default: current group]"),
- ]
-
- boolean_options = ['skip-build']
-
- help_options = [
- ('help-formats', None,
- "lists available distribution formats", show_formats),
- ]
-
- # This won't do in reality: will need to distinguish RPM-ish Linux,
- # Debian-ish Linux, Solaris, FreeBSD, ..., Windows, Mac OS.
- default_format = {'posix': 'gztar',
- 'nt': 'zip',
- 'os2': 'zip'}
-
- # Establish the preferred order (for the --help-formats option).
- format_commands = ['gztar', 'bztar', 'ztar', 'tar',
- 'wininst', 'zip', 'msi']
-
- # And the real information.
- format_command = {'gztar': ('bdist_dumb', "gzip'ed tar file"),
- 'bztar': ('bdist_dumb', "bzip2'ed tar file"),
- 'ztar': ('bdist_dumb', "compressed tar file"),
- 'tar': ('bdist_dumb', "tar file"),
- 'wininst': ('bdist_wininst',
- "Windows executable installer"),
- 'zip': ('bdist_dumb', "ZIP file"),
- 'msi': ('bdist_msi', "Microsoft Installer")
- }
-
-
- def initialize_options(self):
- self.bdist_base = None
- self.plat_name = None
- self.formats = None
- self.dist_dir = None
- self.skip_build = 0
- self.group = None
- self.owner = None
-
- def finalize_options(self):
- # have to finalize 'plat_name' before 'bdist_base'
- if self.plat_name is None:
- if self.skip_build:
- self.plat_name = get_platform()
- else:
- self.plat_name = self.get_finalized_command('build').plat_name
-
- # 'bdist_base' -- parent of per-built-distribution-format
- # temporary directories (eg. we'll probably have
- # "build/bdist.<plat>/dumb", etc.)
- if self.bdist_base is None:
- build_base = self.get_finalized_command('build').build_base
- self.bdist_base = os.path.join(build_base,
- 'bdist.' + self.plat_name)
-
- self.ensure_string_list('formats')
- if self.formats is None:
- try:
- self.formats = [self.default_format[os.name]]
- except KeyError:
- raise DistutilsPlatformError, \
- "don't know how to create built distributions " + \
- "on platform %s" % os.name
-
- if self.dist_dir is None:
- self.dist_dir = "dist"
-
- def run(self):
- # Figure out which sub-commands we need to run.
- commands = []
- for format in self.formats:
- try:
- commands.append(self.format_command[format][0])
- except KeyError:
- raise DistutilsOptionError, "invalid format '%s'" % format
-
- # Reinitialize and run each command.
- for i in range(len(self.formats)):
- cmd_name = commands[i]
- sub_cmd = self.get_reinitialized_command(cmd_name)
-
- # passing the owner and group names for tar archiving
- if cmd_name == 'bdist_dumb':
- sub_cmd.owner = self.owner
- sub_cmd.group = self.group
-
- # If we're going to need to run this command again, tell it to
- # keep its temporary files around so subsequent runs go faster.
- if cmd_name in commands[i+1:]:
- sub_cmd.keep_temp = 1
- self.run_command(cmd_name)
diff --git a/src/distutils2/command/bdist_dumb.py b/src/distutils2/command/bdist_dumb.py
deleted file mode 100644
index 4113a1e..0000000
--- a/src/distutils2/command/bdist_dumb.py
+++ /dev/null
@@ -1,142 +0,0 @@
-"""distutils.command.bdist_dumb
-
-Implements the Distutils 'bdist_dumb' command (create a "dumb" built
-distribution -- i.e., just an archive to be unpacked under $prefix or
-$exec_prefix)."""
-
-__revision__ = "$Id: bdist_dumb.py 77761 2010-01-26 22:46:15Z tarek.ziade $"
-
-import os
-from shutil import rmtree
-try:
- from sysconfig import get_python_version
-except ImportError:
- from distutils2._backport.sysconfig import get_python_version
-from distutils2.util import get_platform
-from distutils2.core import Command
-from distutils2.errors import DistutilsPlatformError
-from distutils2 import log
-
-class bdist_dumb (Command):
-
- description = 'create a "dumb" built distribution'
-
- user_options = [('bdist-dir=', 'd',
- "temporary directory for creating the distribution"),
- ('plat-name=', 'p',
- "platform name to embed in generated filenames "
- "(default: %s)" % get_platform()),
- ('format=', 'f',
- "archive format to create (tar, ztar, gztar, zip)"),
- ('keep-temp', 'k',
- "keep the pseudo-installation tree around after " +
- "creating the distribution archive"),
- ('dist-dir=', 'd',
- "directory to put final built distributions in"),
- ('skip-build', None,
- "skip rebuilding everything (for testing/debugging)"),
- ('relative', None,
- "build the archive using relative paths"
- "(default: false)"),
- ('owner=', 'u',
- "Owner name used when creating a tar file"
- " [default: current user]"),
- ('group=', 'g',
- "Group name used when creating a tar file"
- " [default: current group]"),
- ]
-
- boolean_options = ['keep-temp', 'skip-build', 'relative']
-
- default_format = { 'posix': 'gztar',
- 'nt': 'zip',
- 'os2': 'zip' }
-
-
- def initialize_options (self):
- self.bdist_dir = None
- self.plat_name = None
- self.format = None
- self.keep_temp = 0
- self.dist_dir = None
- self.skip_build = 0
- self.relative = 0
- self.owner = None
- self.group = None
-
- def finalize_options(self):
- if self.bdist_dir is None:
- bdist_base = self.get_finalized_command('bdist').bdist_base
- self.bdist_dir = os.path.join(bdist_base, 'dumb')
-
- if self.format is None:
- try:
- self.format = self.default_format[os.name]
- except KeyError:
- raise DistutilsPlatformError, \
- ("don't know how to create dumb built distributions " +
- "on platform %s") % os.name
-
- self.set_undefined_options('bdist', 'dist_dir', 'plat_name')
-
- def run(self):
- if not self.skip_build:
- self.run_command('build')
-
- install = self.get_reinitialized_command('install', reinit_subcommands=1)
- install.root = self.bdist_dir
- install.skip_build = self.skip_build
- install.warn_dir = 0
-
- log.info("installing to %s" % self.bdist_dir)
- self.run_command('install')
-
- # And make an archive relative to the root of the
- # pseudo-installation tree.
- archive_basename = "%s.%s" % (self.distribution.get_fullname(),
- self.plat_name)
-
- # OS/2 objects to any ":" characters in a filename (such as when
- # a timestamp is used in a version) so change them to hyphens.
- if os.name == "os2":
- archive_basename = archive_basename.replace(":", "-")
-
- pseudoinstall_root = os.path.join(self.dist_dir, archive_basename)
- if not self.relative:
- archive_root = self.bdist_dir
- else:
- if (self.distribution.has_ext_modules() and
- (install.install_base != install.install_platbase)):
- raise DistutilsPlatformError, \
- ("can't make a dumb built distribution where "
- "base and platbase are different (%s, %s)"
- % (repr(install.install_base),
- repr(install.install_platbase)))
- else:
- archive_root = os.path.join(
- self.bdist_dir,
- self._ensure_relative(install.install_base))
-
- # Make the archive
- filename = self.make_archive(pseudoinstall_root,
- self.format, root_dir=archive_root,
- owner=self.owner, group=self.group)
- if self.distribution.has_ext_modules():
- pyversion = get_python_version()
- else:
- pyversion = 'any'
- self.distribution.dist_files.append(('bdist_dumb', pyversion,
- filename))
-
- if not self.keep_temp:
- if self.dry_run:
- log.info('Removing %s' % self.bdist_dir)
- else:
- rmtree(self.bdist_dir)
-
- def _ensure_relative(self, path):
- # copied from dir_util, deleted
- drive, path = os.path.splitdrive(path)
- if path[0:1] == os.sep:
- path = drive + path[1:]
- return path
diff --git a/src/distutils2/command/bdist_msi.py b/src/distutils2/command/bdist_msi.py
deleted file mode 100644
index 61968ad..0000000
--- a/src/distutils2/command/bdist_msi.py
+++ /dev/null
@@ -1,735 +0,0 @@
-# -*- coding: iso-8859-1 -*-
-# Copyright (C) 2005, 2006 Martin von Löwis
-# Licensed to PSF under a Contributor Agreement.
-# The bdist_wininst command proper
-# based on bdist_wininst
-"""
-Implements the bdist_msi command.
-"""
-import sys, os
-from sysconfig import get_python_version
-
-from distutils2.core import Command
-from distutils2.dir_util import remove_tree
-from distutils2.version import StrictVersion
-from distutils2.errors import DistutilsOptionError
-from distutils2 import log
-from distutils2.util import get_platform
-
-import msilib
-from msilib import schema, sequence, text
-from msilib import Directory, Feature, Dialog, add_data
-
-class PyDialog(Dialog):
- """Dialog class with a fixed layout: controls at the top, then a ruler,
- then a list of buttons: back, next, cancel. Optionally a bitmap at the
- left."""
- def __init__(self, *args, **kw):
- """Dialog(database, name, x, y, w, h, attributes, title, first,
- default, cancel, bitmap=true)"""
- Dialog.__init__(self, *args)
- ruler = self.h - 36
- #if kw.get("bitmap", True):
- # self.bitmap("Bitmap", 0, 0, bmwidth, ruler, "PythonWin")
- self.line("BottomLine", 0, ruler, self.w, 0)
-
- def title(self, title):
- "Set the title text of the dialog at the top."
- # name, x, y, w, h, flags=Visible|Enabled|Transparent|NoPrefix,
- # text, in VerdanaBold10
- self.text("Title", 15, 10, 320, 60, 0x30003,
- r"{\VerdanaBold10}%s" % title)
-
- def back(self, title, next, name = "Back", active = 1):
- """Add a back button with a given title, the tab-next button,
- its name in the Control table, possibly initially disabled.
-
- Return the button, so that events can be associated"""
- if active:
- flags = 3 # Visible|Enabled
- else:
- flags = 1 # Visible
- return self.pushbutton(name, 180, self.h-27 , 56, 17, flags, title, next)
-
- def cancel(self, title, next, name = "Cancel", active = 1):
- """Add a cancel button with a given title, the tab-next button,
- its name in the Control table, possibly initially disabled.
-
- Return the button, so that events can be associated"""
- if active:
- flags = 3 # Visible|Enabled
- else:
- flags = 1 # Visible
- return self.pushbutton(name, 304, self.h-27, 56, 17, flags, title, next)
-
- def next(self, title, next, name = "Next", active = 1):
- """Add a Next button with a given title, the tab-next button,
- its name in the Control table, possibly initially disabled.
-
- Return the button, so that events can be associated"""
- if active:
- flags = 3 # Visible|Enabled
- else:
- flags = 1 # Visible
- return self.pushbutton(name, 236, self.h-27, 56, 17, flags, title, next)
-
- def xbutton(self, name, title, next, xpos):
- """Add a button with a given title, the tab-next button,
- its name in the Control table, giving its x position; the
- y-position is aligned with the other buttons.
-
- Return the button, so that events can be associated"""
- return self.pushbutton(name, int(self.w*xpos - 28), self.h-27, 56, 17, 3, title, next)
-
-class bdist_msi (Command):
-
- description = "create a Microsoft Installer (.msi) binary distribution"
-
- user_options = [('bdist-dir=', None,
- "temporary directory for creating the distribution"),
- ('plat-name=', 'p',
- "platform name to embed in generated filenames "
- "(default: %s)" % get_platform()),
- ('keep-temp', 'k',
- "keep the pseudo-installation tree around after " +
- "creating the distribution archive"),
- ('target-version=', None,
- "require a specific python version" +
- " on the target system"),
- ('no-target-compile', 'c',
- "do not compile .py to .pyc on the target system"),
- ('no-target-optimize', 'o',
- "do not compile .py to .pyo (optimized)"
- "on the target system"),
- ('dist-dir=', 'd',
- "directory to put final built distributions in"),
- ('skip-build', None,
- "skip rebuilding everything (for testing/debugging)"),
- ('install-script=', None,
- "basename of installation script to be run after"
- "installation or before deinstallation"),
- ('pre-install-script=', None,
- "Fully qualified filename of a script to be run before "
- "any files are installed. This script need not be in the "
- "distribution"),
- ]
-
- boolean_options = ['keep-temp', 'no-target-compile', 'no-target-optimize',
- 'skip-build']
-
- all_versions = ['2.0', '2.1', '2.2', '2.3', '2.4',
- '2.5', '2.6', '2.7', '2.8', '2.9',
- '3.0', '3.1', '3.2', '3.3', '3.4',
- '3.5', '3.6', '3.7', '3.8', '3.9']
- other_version = 'X'
-
- def initialize_options (self):
- self.bdist_dir = None
- self.plat_name = None
- self.keep_temp = 0
- self.no_target_compile = 0
- self.no_target_optimize = 0
- self.target_version = None
- self.dist_dir = None
- self.skip_build = 0
- self.install_script = None
- self.pre_install_script = None
- self.versions = None
-
- def finalize_options (self):
- if self.bdist_dir is None:
- bdist_base = self.get_finalized_command('bdist').bdist_base
- self.bdist_dir = os.path.join(bdist_base, 'msi')
- short_version = get_python_version()
- if (not self.target_version) and self.distribution.has_ext_modules():
- self.target_version = short_version
- if self.target_version:
- self.versions = [self.target_version]
- if not self.skip_build and self.distribution.has_ext_modules()\
- and self.target_version != short_version:
- raise DistutilsOptionError, \
- "target version can only be %s, or the '--skip-build'" \
- " option must be specified" % (short_version,)
- else:
- self.versions = list(self.all_versions)
-
- self.set_undefined_options('bdist', 'dist_dir', 'plat_name')
-
- if self.pre_install_script:
- raise DistutilsOptionError, "the pre-install-script feature is not yet implemented"
-
- if self.install_script:
- for script in self.distribution.scripts:
- if self.install_script == os.path.basename(script):
- break
- else:
- raise DistutilsOptionError, \
- "install_script '%s' not found in scripts" % \
- self.install_script
- self.install_script_key = None
- # finalize_options()
-
-
- def run (self):
- if not self.skip_build:
- self.run_command('build')
-
- install = self.get_reinitialized_command('install', reinit_subcommands=1)
- install.prefix = self.bdist_dir
- install.skip_build = self.skip_build
- install.warn_dir = 0
-
- install_lib = self.get_reinitialized_command('install_lib')
- # we do not want to include pyc or pyo files
- install_lib.compile = 0
- install_lib.optimize = 0
-
- if self.distribution.has_ext_modules():
- # If we are building an installer for a Python version other
- # than the one we are currently running, then we need to ensure
- # our build_lib reflects the other Python version rather than ours.
- # Note that for target_version!=sys.version, we must have skipped the
- # build step, so there is no issue with enforcing the build of this
- # version.
- target_version = self.target_version
- if not target_version:
- assert self.skip_build, "Should have already checked this"
- target_version = sys.version[0:3]
- plat_specifier = ".%s-%s" % (self.plat_name, target_version)
- build = self.get_finalized_command('build')
- build.build_lib = os.path.join(build.build_base,
- 'lib' + plat_specifier)
-
- log.info("installing to %s", self.bdist_dir)
- install.ensure_finalized()
-
- # avoid warning of 'install_lib' about installing
- # into a directory not in sys.path
- sys.path.insert(0, os.path.join(self.bdist_dir, 'PURELIB'))
-
- install.run()
-
- del sys.path[0]
-
- self.mkpath(self.dist_dir)
- fullname = self.distribution.get_fullname()
- installer_name = self.get_installer_filename(fullname)
- installer_name = os.path.abspath(installer_name)
- if os.path.exists(installer_name): os.unlink(installer_name)
-
- metadata = self.distribution.metadata
- author = metadata.author
- if not author:
- author = metadata.maintainer
- if not author:
- author = "UNKNOWN"
- version = metadata.get_version()
- # ProductVersion must be strictly numeric
- # XXX need to deal with prerelease versions
- sversion = "%d.%d.%d" % StrictVersion(version).version
- # Prefix ProductName with Python x.y, so that
- # it sorts together with the other Python packages
- # in Add-Remove-Programs (APR)
- fullname = self.distribution.get_fullname()
- if self.target_version:
- product_name = "Python %s %s" % (self.target_version, fullname)
- else:
- product_name = "Python %s" % (fullname)
- self.db = msilib.init_database(installer_name, schema,
- product_name, msilib.gen_uuid(),
- sversion, author)
- msilib.add_tables(self.db, sequence)
- props = [('DistVersion', version)]
- email = metadata.author_email or metadata.maintainer_email
- if email:
- props.append(("ARPCONTACT", email))
- if metadata.url:
- props.append(("ARPURLINFOABOUT", metadata.url))
- if props:
- add_data(self.db, 'Property', props)
-
- self.add_find_python()
- self.add_files()
- self.add_scripts()
- self.add_ui()
- self.db.Commit()
-
- if hasattr(self.distribution, 'dist_files'):
- tup = 'bdist_msi', self.target_version or 'any', fullname
- self.distribution.dist_files.append(tup)
-
- if not self.keep_temp:
- remove_tree(self.bdist_dir, dry_run=self.dry_run)
-
- def add_files(self):
- db = self.db
- cab = msilib.CAB("distfiles")
- rootdir = os.path.abspath(self.bdist_dir)
-
- root = Directory(db, cab, None, rootdir, "TARGETDIR", "SourceDir")
- f = Feature(db, "Python", "Python", "Everything",
- 0, 1, directory="TARGETDIR")
-
- items = [(f, root, '')]
- for version in self.versions + [self.other_version]:
- target = "TARGETDIR" + version
- name = default = "Python" + version
- desc = "Everything"
- if version is self.other_version:
- title = "Python from another location"
- level = 2
- else:
- title = "Python %s from registry" % version
- level = 1
- f = Feature(db, name, title, desc, 1, level, directory=target)
- dir = Directory(db, cab, root, rootdir, target, default)
- items.append((f, dir, version))
- db.Commit()
-
- seen = {}
- for feature, dir, version in items:
- todo = [dir]
- while todo:
- dir = todo.pop()
- for file in os.listdir(dir.absolute):
- afile = os.path.join(dir.absolute, file)
- if os.path.isdir(afile):
- short = "%s|%s" % (dir.make_short(file), file)
- default = file + version
- newdir = Directory(db, cab, dir, file, default, short)
- todo.append(newdir)
- else:
- if not dir.component:
- dir.start_component(dir.logical, feature, 0)
- if afile not in seen:
- key = seen[afile] = dir.add_file(file)
- if file==self.install_script:
- if self.install_script_key:
- raise DistutilsOptionError(
- "Multiple files with name %s" % file)
- self.install_script_key = '[#%s]' % key
- else:
- key = seen[afile]
- add_data(self.db, "DuplicateFile",
- [(key + version, dir.component, key, None, dir.logical)])
- db.Commit()
- cab.commit(db)
-
- def add_find_python(self):
- """Adds code to the installer to compute the location of Python.
-
- Properties PYTHON.MACHINE.X.Y and PYTHON.USER.X.Y will be set from the
- registry for each version of Python.
-
- Properties TARGETDIRX.Y will be set from PYTHON.USER.X.Y if defined,
- else from PYTHON.MACHINE.X.Y.
-
- Properties PYTHONX.Y will be set to TARGETDIRX.Y\\python.exe"""
-
- start = 402
- for ver in self.versions:
- install_path = r"SOFTWARE\Python\PythonCore\%s\InstallPath" % ver
- machine_reg = "python.machine." + ver
- user_reg = "python.user." + ver
- machine_prop = "PYTHON.MACHINE." + ver
- user_prop = "PYTHON.USER." + ver
- machine_action = "PythonFromMachine" + ver
- user_action = "PythonFromUser" + ver
- exe_action = "PythonExe" + ver
- target_dir_prop = "TARGETDIR" + ver
- exe_prop = "PYTHON" + ver
- if msilib.Win64:
- # type: msidbLocatorTypeRawValue + msidbLocatorType64bit
- Type = 2+16
- else:
- Type = 2
- add_data(self.db, "RegLocator",
- [(machine_reg, 2, install_path, None, Type),
- (user_reg, 1, install_path, None, Type)])
- add_data(self.db, "AppSearch",
- [(machine_prop, machine_reg),
- (user_prop, user_reg)])
- add_data(self.db, "CustomAction",
- [(machine_action, 51+256, target_dir_prop, "[" + machine_prop + "]"),
- (user_action, 51+256, target_dir_prop, "[" + user_prop + "]"),
- (exe_action, 51+256, exe_prop, "[" + target_dir_prop + "]\\python.exe"),
- ])
- add_data(self.db, "InstallExecuteSequence",
- [(machine_action, machine_prop, start),
- (user_action, user_prop, start + 1),
- (exe_action, None, start + 2),
- ])
- add_data(self.db, "InstallUISequence",
- [(machine_action, machine_prop, start),
- (user_action, user_prop, start + 1),
- (exe_action, None, start + 2),
- ])
- add_data(self.db, "Condition",
- [("Python" + ver, 0, "NOT TARGETDIR" + ver)])
- start += 4
- assert start < 500
-
- def add_scripts(self):
- if self.install_script:
- start = 6800
- for ver in self.versions + [self.other_version]:
- install_action = "install_script." + ver
- exe_prop = "PYTHON" + ver
- add_data(self.db, "CustomAction",
- [(install_action, 50, exe_prop, self.install_script_key)])
- add_data(self.db, "InstallExecuteSequence",
- [(install_action, "&Python%s=3" % ver, start)])
- start += 1
- # XXX pre-install scripts are currently refused in finalize_options()
- # but if this feature is completed, it will also need to add
- # entries for each version as the above code does
- if self.pre_install_script:
- scriptfn = os.path.join(self.bdist_dir, "preinstall.bat")
- f = open(scriptfn, "w")
- # The batch file will be executed with [PYTHON], so that %1
- # is the path to the Python interpreter; %0 will be the path
- # of the batch file.
- # rem ="""
- # %1 %0
- # exit
- # """
- # <actual script>
- f.write('rem ="""\n%1 %0\nexit\n"""\n')
- f.write(open(self.pre_install_script).read())
- f.close()
- add_data(self.db, "Binary",
- [("PreInstall", msilib.Binary(scriptfn))
- ])
- add_data(self.db, "CustomAction",
- [("PreInstall", 2, "PreInstall", None)
- ])
- add_data(self.db, "InstallExecuteSequence",
- [("PreInstall", "NOT Installed", 450)])
-
-
- def add_ui(self):
- db = self.db
- x = y = 50
- w = 370
- h = 300
- title = "[ProductName] Setup"
-
- # see "Dialog Style Bits"
- modal = 3 # visible | modal
- modeless = 1 # visible
-
- # UI customization properties
- add_data(db, "Property",
- # See "DefaultUIFont Property"
- [("DefaultUIFont", "DlgFont8"),
- # See "ErrorDialog Style Bit"
- ("ErrorDialog", "ErrorDlg"),
- ("Progress1", "Install"), # modified in maintenance type dlg
- ("Progress2", "installs"),
- ("MaintenanceForm_Action", "Repair"),
- # possible values: ALL, JUSTME
- ("WhichUsers", "ALL")
- ])
-
- # Fonts, see "TextStyle Table"
- add_data(db, "TextStyle",
- [("DlgFont8", "Tahoma", 9, None, 0),
- ("DlgFontBold8", "Tahoma", 8, None, 1), #bold
- ("VerdanaBold10", "Verdana", 10, None, 1),
- ("VerdanaRed9", "Verdana", 9, 255, 0),
- ])
-
- # UI Sequences, see "InstallUISequence Table", "Using a Sequence Table"
- # Numbers indicate sequence; see sequence.py for how these action integrate
- add_data(db, "InstallUISequence",
- [("PrepareDlg", "Not Privileged or Windows9x or Installed", 140),
- ("WhichUsersDlg", "Privileged and not Windows9x and not Installed", 141),
- # In the user interface, assume all-users installation if privileged.
- ("SelectFeaturesDlg", "Not Installed", 1230),
- # XXX no support for resume installations yet
- #("ResumeDlg", "Installed AND (RESUME OR Preselected)", 1240),
- ("MaintenanceTypeDlg", "Installed AND NOT RESUME AND NOT Preselected", 1250),
- ("ProgressDlg", None, 1280)])
-
- add_data(db, 'ActionText', text.ActionText)
- add_data(db, 'UIText', text.UIText)
- #####################################################################
- # Standard dialogs: FatalError, UserExit, ExitDialog
- fatal=PyDialog(db, "FatalError", x, y, w, h, modal, title,
- "Finish", "Finish", "Finish")
- fatal.title("[ProductName] Installer ended prematurely")
- fatal.back("< Back", "Finish", active = 0)
- fatal.cancel("Cancel", "Back", active = 0)
- fatal.text("Description1", 15, 70, 320, 80, 0x30003,
- "[ProductName] setup ended prematurely because of an error. Your system has not been modified. To install this program at a later time, please run the installation again.")
- fatal.text("Description2", 15, 155, 320, 20, 0x30003,
- "Click the Finish button to exit the Installer.")
- c=fatal.next("Finish", "Cancel", name="Finish")
- c.event("EndDialog", "Exit")
-
- user_exit=PyDialog(db, "UserExit", x, y, w, h, modal, title,
- "Finish", "Finish", "Finish")
- user_exit.title("[ProductName] Installer was interrupted")
- user_exit.back("< Back", "Finish", active = 0)
- user_exit.cancel("Cancel", "Back", active = 0)
- user_exit.text("Description1", 15, 70, 320, 80, 0x30003,
- "[ProductName] setup was interrupted. Your system has not been modified. "
- "To install this program at a later time, please run the installation again.")
- user_exit.text("Description2", 15, 155, 320, 20, 0x30003,
- "Click the Finish button to exit the Installer.")
- c = user_exit.next("Finish", "Cancel", name="Finish")
- c.event("EndDialog", "Exit")
-
- exit_dialog = PyDialog(db, "ExitDialog", x, y, w, h, modal, title,
- "Finish", "Finish", "Finish")
- exit_dialog.title("Completing the [ProductName] Installer")
- exit_dialog.back("< Back", "Finish", active = 0)
- exit_dialog.cancel("Cancel", "Back", active = 0)
- exit_dialog.text("Description", 15, 235, 320, 20, 0x30003,
- "Click the Finish button to exit the Installer.")
- c = exit_dialog.next("Finish", "Cancel", name="Finish")
- c.event("EndDialog", "Return")
-
- #####################################################################
- # Required dialog: FilesInUse, ErrorDlg
- inuse = PyDialog(db, "FilesInUse",
- x, y, w, h,
- 19, # KeepModeless|Modal|Visible
- title,
- "Retry", "Retry", "Retry", bitmap=False)
- inuse.text("Title", 15, 6, 200, 15, 0x30003,
- r"{\DlgFontBold8}Files in Use")
- inuse.text("Description", 20, 23, 280, 20, 0x30003,
- "Some files that need to be updated are currently in use.")
- inuse.text("Text", 20, 55, 330, 50, 3,
- "The following applications are using files that need to be updated by this setup. Close these applications and then click Retry to continue the installation or Cancel to exit it.")
- inuse.control("List", "ListBox", 20, 107, 330, 130, 7, "FileInUseProcess",
- None, None, None)
- c=inuse.back("Exit", "Ignore", name="Exit")
- c.event("EndDialog", "Exit")
- c=inuse.next("Ignore", "Retry", name="Ignore")
- c.event("EndDialog", "Ignore")
- c=inuse.cancel("Retry", "Exit", name="Retry")
- c.event("EndDialog","Retry")
-
- # See "Error Dialog". See "ICE20" for the required names of the controls.
- error = Dialog(db, "ErrorDlg",
- 50, 10, 330, 101,
- 65543, # Error|Minimize|Modal|Visible
- title,
- "ErrorText", None, None)
- error.text("ErrorText", 50,9,280,48,3, "")
- #error.control("ErrorIcon", "Icon", 15, 9, 24, 24, 5242881, None, "py.ico", None, None)
- error.pushbutton("N",120,72,81,21,3,"No",None).event("EndDialog","ErrorNo")
- error.pushbutton("Y",240,72,81,21,3,"Yes",None).event("EndDialog","ErrorYes")
- error.pushbutton("A",0,72,81,21,3,"Abort",None).event("EndDialog","ErrorAbort")
- error.pushbutton("C",42,72,81,21,3,"Cancel",None).event("EndDialog","ErrorCancel")
- error.pushbutton("I",81,72,81,21,3,"Ignore",None).event("EndDialog","ErrorIgnore")
- error.pushbutton("O",159,72,81,21,3,"Ok",None).event("EndDialog","ErrorOk")
- error.pushbutton("R",198,72,81,21,3,"Retry",None).event("EndDialog","ErrorRetry")
-
- #####################################################################
- # Global "Query Cancel" dialog
- cancel = Dialog(db, "CancelDlg", 50, 10, 260, 85, 3, title,
- "No", "No", "No")
- cancel.text("Text", 48, 15, 194, 30, 3,
- "Are you sure you want to cancel [ProductName] installation?")
- #cancel.control("Icon", "Icon", 15, 15, 24, 24, 5242881, None,
- # "py.ico", None, None)
- c=cancel.pushbutton("Yes", 72, 57, 56, 17, 3, "Yes", "No")
- c.event("EndDialog", "Exit")
-
- c=cancel.pushbutton("No", 132, 57, 56, 17, 3, "No", "Yes")
- c.event("EndDialog", "Return")
-
- #####################################################################
- # Global "Wait for costing" dialog
- costing = Dialog(db, "WaitForCostingDlg", 50, 10, 260, 85, modal, title,
- "Return", "Return", "Return")
- costing.text("Text", 48, 15, 194, 30, 3,
- "Please wait while the installer finishes determining your disk space requirements.")
- c = costing.pushbutton("Return", 102, 57, 56, 17, 3, "Return", None)
- c.event("EndDialog", "Exit")
-
- #####################################################################
- # Preparation dialog: no user input except cancellation
- prep = PyDialog(db, "PrepareDlg", x, y, w, h, modeless, title,
- "Cancel", "Cancel", "Cancel")
- prep.text("Description", 15, 70, 320, 40, 0x30003,
- "Please wait while the Installer prepares to guide you through the installation.")
- prep.title("Welcome to the [ProductName] Installer")
- c=prep.text("ActionText", 15, 110, 320, 20, 0x30003, "Pondering...")
- c.mapping("ActionText", "Text")
- c=prep.text("ActionData", 15, 135, 320, 30, 0x30003, None)
- c.mapping("ActionData", "Text")
- prep.back("Back", None, active=0)
- prep.next("Next", None, active=0)
- c=prep.cancel("Cancel", None)
- c.event("SpawnDialog", "CancelDlg")
-
- #####################################################################
- # Feature (Python directory) selection
- seldlg = PyDialog(db, "SelectFeaturesDlg", x, y, w, h, modal, title,
- "Next", "Next", "Cancel")
- seldlg.title("Select Python Installations")
-
- seldlg.text("Hint", 15, 30, 300, 20, 3,
- "Select the Python locations where %s should be installed."
- % self.distribution.get_fullname())
-
- seldlg.back("< Back", None, active=0)
- c = seldlg.next("Next >", "Cancel")
- order = 1
- c.event("[TARGETDIR]", "[SourceDir]", ordering=order)
- for version in self.versions + [self.other_version]:
- order += 1
- c.event("[TARGETDIR]", "[TARGETDIR%s]" % version,
- "FEATURE_SELECTED AND &Python%s=3" % version,
- ordering=order)
- c.event("SpawnWaitDialog", "WaitForCostingDlg", ordering=order + 1)
- c.event("EndDialog", "Return", ordering=order + 2)
- c = seldlg.cancel("Cancel", "Features")
- c.event("SpawnDialog", "CancelDlg")
-
- c = seldlg.control("Features", "SelectionTree", 15, 60, 300, 120, 3,
- "FEATURE", None, "PathEdit", None)
- c.event("[FEATURE_SELECTED]", "1")
- ver = self.other_version
- install_other_cond = "FEATURE_SELECTED AND &Python%s=3" % ver
- dont_install_other_cond = "FEATURE_SELECTED AND &Python%s<>3" % ver
-
- c = seldlg.text("Other", 15, 200, 300, 15, 3,
- "Provide an alternate Python location")
- c.condition("Enable", install_other_cond)
- c.condition("Show", install_other_cond)
- c.condition("Disable", dont_install_other_cond)
- c.condition("Hide", dont_install_other_cond)
-
- c = seldlg.control("PathEdit", "PathEdit", 15, 215, 300, 16, 1,
- "TARGETDIR" + ver, None, "Next", None)
- c.condition("Enable", install_other_cond)
- c.condition("Show", install_other_cond)
- c.condition("Disable", dont_install_other_cond)
- c.condition("Hide", dont_install_other_cond)
-
- #####################################################################
- # Disk cost
- cost = PyDialog(db, "DiskCostDlg", x, y, w, h, modal, title,
- "OK", "OK", "OK", bitmap=False)
- cost.text("Title", 15, 6, 200, 15, 0x30003,
- "{\DlgFontBold8}Disk Space Requirements")
- cost.text("Description", 20, 20, 280, 20, 0x30003,
- "The disk space required for the installation of the selected features.")
- cost.text("Text", 20, 53, 330, 60, 3,
- "The highlighted volumes (if any) do not have enough disk space "
- "available for the currently selected features. You can either "
- "remove some files from the highlighted volumes, or choose to "
- "install less features onto local drive(s), or select different "
- "destination drive(s).")
- cost.control("VolumeList", "VolumeCostList", 20, 100, 330, 150, 393223,
- None, "{120}{70}{70}{70}{70}", None, None)
- cost.xbutton("OK", "Ok", None, 0.5).event("EndDialog", "Return")
-
- #####################################################################
- # WhichUsers Dialog. Only available on NT, and for privileged users.
- # This must be run before FindRelatedProducts, because that will
- # take into account whether the previous installation was per-user
- # or per-machine. We currently don't support going back to this
- # dialog after "Next" was selected; to support this, we would need to
- # find how to reset the ALLUSERS property, and how to re-run
- # FindRelatedProducts.
- # On Windows9x, the ALLUSERS property is ignored on the command line
- # and in the Property table, but installer fails according to the documentation
- # if a dialog attempts to set ALLUSERS.
- whichusers = PyDialog(db, "WhichUsersDlg", x, y, w, h, modal, title,
- "AdminInstall", "Next", "Cancel")
- whichusers.title("Select whether to install [ProductName] for all users of this computer.")
- # A radio group with two options: allusers, justme
- g = whichusers.radiogroup("AdminInstall", 15, 60, 260, 50, 3,
- "WhichUsers", "", "Next")
- g.add("ALL", 0, 5, 150, 20, "Install for all users")
- g.add("JUSTME", 0, 25, 150, 20, "Install just for me")
-
- whichusers.back("Back", None, active=0)
-
- c = whichusers.next("Next >", "Cancel")
- c.event("[ALLUSERS]", "1", 'WhichUsers="ALL"', 1)
- c.event("EndDialog", "Return", ordering = 2)
-
- c = whichusers.cancel("Cancel", "AdminInstall")
- c.event("SpawnDialog", "CancelDlg")
-
- #####################################################################
- # Installation Progress dialog (modeless)
- progress = PyDialog(db, "ProgressDlg", x, y, w, h, modeless, title,
- "Cancel", "Cancel", "Cancel", bitmap=False)
- progress.text("Title", 20, 15, 200, 15, 0x30003,
- "{\DlgFontBold8}[Progress1] [ProductName]")
- progress.text("Text", 35, 65, 300, 30, 3,
- "Please wait while the Installer [Progress2] [ProductName]. "
- "This may take several minutes.")
- progress.text("StatusLabel", 35, 100, 35, 20, 3, "Status:")
-
- c=progress.text("ActionText", 70, 100, w-70, 20, 3, "Pondering...")
- c.mapping("ActionText", "Text")
-
- #c=progress.text("ActionData", 35, 140, 300, 20, 3, None)
- #c.mapping("ActionData", "Text")
-
- c=progress.control("ProgressBar", "ProgressBar", 35, 120, 300, 10, 65537,
- None, "Progress done", None, None)
- c.mapping("SetProgress", "Progress")
-
- progress.back("< Back", "Next", active=False)
- progress.next("Next >", "Cancel", active=False)
- progress.cancel("Cancel", "Back").event("SpawnDialog", "CancelDlg")
-
- ###################################################################
- # Maintenance type: repair/uninstall
- maint = PyDialog(db, "MaintenanceTypeDlg", x, y, w, h, modal, title,
- "Next", "Next", "Cancel")
- maint.title("Welcome to the [ProductName] Setup Wizard")
- maint.text("BodyText", 15, 63, 330, 42, 3,
- "Select whether you want to repair or remove [ProductName].")
- g=maint.radiogroup("RepairRadioGroup", 15, 108, 330, 60, 3,
- "MaintenanceForm_Action", "", "Next")
- #g.add("Change", 0, 0, 200, 17, "&Change [ProductName]")
- g.add("Repair", 0, 18, 200, 17, "&Repair [ProductName]")
- g.add("Remove", 0, 36, 200, 17, "Re&move [ProductName]")
-
- maint.back("< Back", None, active=False)
- c=maint.next("Finish", "Cancel")
- # Change installation: Change progress dialog to "Change", then ask
- # for feature selection
- #c.event("[Progress1]", "Change", 'MaintenanceForm_Action="Change"', 1)
- #c.event("[Progress2]", "changes", 'MaintenanceForm_Action="Change"', 2)
-
- # Reinstall: Change progress dialog to "Repair", then invoke reinstall
- # Also set list of reinstalled features to "ALL"
- c.event("[REINSTALL]", "ALL", 'MaintenanceForm_Action="Repair"', 5)
- c.event("[Progress1]", "Repairing", 'MaintenanceForm_Action="Repair"', 6)
- c.event("[Progress2]", "repairs", 'MaintenanceForm_Action="Repair"', 7)
- c.event("Reinstall", "ALL", 'MaintenanceForm_Action="Repair"', 8)
-
- # Uninstall: Change progress to "Remove", then invoke uninstall
- # Also set list of removed features to "ALL"
- c.event("[REMOVE]", "ALL", 'MaintenanceForm_Action="Remove"', 11)
- c.event("[Progress1]", "Removing", 'MaintenanceForm_Action="Remove"', 12)
- c.event("[Progress2]", "removes", 'MaintenanceForm_Action="Remove"', 13)
- c.event("Remove", "ALL", 'MaintenanceForm_Action="Remove"', 14)
-
- # Close dialog when maintenance action scheduled
- c.event("EndDialog", "Return", 'MaintenanceForm_Action<>"Change"', 20)
- #c.event("NewDialog", "SelectFeaturesDlg", 'MaintenanceForm_Action="Change"', 21)
-
- maint.cancel("Cancel", "RepairRadioGroup").event("SpawnDialog", "CancelDlg")
-
- def get_installer_filename(self, fullname):
- # Factored out to allow overriding in subclasses
- if self.target_version:
- base_name = "%s.%s-py%s.msi" % (fullname, self.plat_name,
- self.target_version)
- else:
- base_name = "%s.%s.msi" % (fullname, self.plat_name)
- installer_name = os.path.join(self.dist_dir, base_name)
- return installer_name
diff --git a/src/distutils2/command/bdist_wininst.py b/src/distutils2/command/bdist_wininst.py
deleted file mode 100644
index 562c4ed..0000000
--- a/src/distutils2/command/bdist_wininst.py
+++ /dev/null
@@ -1,359 +0,0 @@
-"""distutils.command.bdist_wininst
-
-Implements the Distutils 'bdist_wininst' command: create a windows installer
-exe-program."""
-
-__revision__ = "$Id: bdist_wininst.py 77761 2010-01-26 22:46:15Z tarek.ziade $"
-
-import sys
-import os
-import string
-from shutil import rmtree
-try:
- from sysconfig import get_python_version
-except ImportError:
- from distutils2._backport.sysconfig import get_python_version
-from distutils2.core import Command
-from distutils2.errors import DistutilsOptionError, DistutilsPlatformError
-from distutils2 import log
-from distutils2.util import get_platform
-
-class bdist_wininst (Command):
-
- description = "create an executable installer for MS Windows"
-
- user_options = [('bdist-dir=', None,
- "temporary directory for creating the distribution"),
- ('plat-name=', 'p',
- "platform name to embed in generated filenames "
- "(default: %s)" % get_platform()),
- ('keep-temp', 'k',
- "keep the pseudo-installation tree around after " +
- "creating the distribution archive"),
- ('target-version=', None,
- "require a specific python version" +
- " on the target system"),
- ('no-target-compile', 'c',
- "do not compile .py to .pyc on the target system"),
- ('no-target-optimize', 'o',
- "do not compile .py to .pyo (optimized)"
- "on the target system"),
- ('dist-dir=', 'd',
- "directory to put final built distributions in"),
- ('bitmap=', 'b',
- "bitmap to use for the installer instead of python-powered logo"),
- ('title=', 't',
- "title to display on the installer background instead of default"),
- ('skip-build', None,
- "skip rebuilding everything (for testing/debugging)"),
- ('install-script=', None,
- "basename of installation script to be run after"
- "installation or before deinstallation"),
- ('pre-install-script=', None,
- "Fully qualified filename of a script to be run before "
- "any files are installed. This script need not be in the "
- "distribution"),
- ('user-access-control=', None,
- "specify Vista's UAC handling - 'none'/default=no "
- "handling, 'auto'=use UAC if target Python installed for "
- "all users, 'force'=always use UAC"),
- ]
-
- boolean_options = ['keep-temp', 'no-target-compile', 'no-target-optimize',
- 'skip-build']
-
- def initialize_options (self):
- self.bdist_dir = None
- self.plat_name = None
- self.keep_temp = 0
- self.no_target_compile = 0
- self.no_target_optimize = 0
- self.target_version = None
- self.dist_dir = None
- self.bitmap = None
- self.title = None
- self.skip_build = 0
- self.install_script = None
- self.pre_install_script = None
- self.user_access_control = None
-
- # initialize_options()
-
-
- def finalize_options (self):
- if self.bdist_dir is None:
- if self.skip_build and self.plat_name:
- # If build is skipped and plat_name is overridden, bdist will
- # not see the correct 'plat_name' - so set that up manually.
- bdist = self.distribution.get_command_obj('bdist')
- bdist.plat_name = self.plat_name
- # next the command will be initialized using that name
- bdist_base = self.get_finalized_command('bdist').bdist_base
- self.bdist_dir = os.path.join(bdist_base, 'wininst')
- if not self.target_version:
- self.target_version = ""
- if not self.skip_build and self.distribution.has_ext_modules():
- short_version = get_python_version()
- if self.target_version and self.target_version != short_version:
- raise DistutilsOptionError, \
- "target version can only be %s, or the '--skip-build'" \
- " option must be specified" % (short_version,)
- self.target_version = short_version
-
- self.set_undefined_options('bdist', 'dist_dir', 'plat_name')
-
- if self.install_script:
- for script in self.distribution.scripts:
- if self.install_script == os.path.basename(script):
- break
- else:
- raise DistutilsOptionError, \
- "install_script '%s' not found in scripts" % \
- self.install_script
- # finalize_options()
-
-
- def run (self):
- if (sys.platform != "win32" and
- (self.distribution.has_ext_modules() or
- self.distribution.has_c_libraries())):
- raise DistutilsPlatformError \
- ("distribution contains extensions and/or C libraries; "
- "must be compiled on a Windows 32 platform")
-
- if not self.skip_build:
- self.run_command('build')
-
- install = self.get_reinitialized_command('install', reinit_subcommands=1)
- install.root = self.bdist_dir
- install.skip_build = self.skip_build
- install.warn_dir = 0
- install.plat_name = self.plat_name
-
- install_lib = self.get_reinitialized_command('install_lib')
- # we do not want to include pyc or pyo files
- install_lib.compile = 0
- install_lib.optimize = 0
-
- if self.distribution.has_ext_modules():
- # If we are building an installer for a Python version other
- # than the one we are currently running, then we need to ensure
- # our build_lib reflects the other Python version rather than ours.
- # Note that for target_version!=sys.version, we must have skipped the
- # build step, so there is no issue with enforcing the build of this
- # version.
- target_version = self.target_version
- if not target_version:
- assert self.skip_build, "Should have already checked this"
- target_version = sys.version[0:3]
- plat_specifier = ".%s-%s" % (self.plat_name, target_version)
- build = self.get_finalized_command('build')
- build.build_lib = os.path.join(build.build_base,
- 'lib' + plat_specifier)
-
- # Use a custom scheme for the zip-file, because we have to decide
- # at installation time which scheme to use.
- for key in ('purelib', 'platlib', 'headers', 'scripts', 'data'):
- value = string.upper(key)
- if key == 'headers':
- value = value + '/Include/$dist_name'
- setattr(install,
- 'install_' + key,
- value)
-
- log.info("installing to %s", self.bdist_dir)
- install.ensure_finalized()
-
- # avoid warning of 'install_lib' about installing
- # into a directory not in sys.path
- sys.path.insert(0, os.path.join(self.bdist_dir, 'PURELIB'))
-
- install.run()
-
- del sys.path[0]
-
- # And make an archive relative to the root of the
- # pseudo-installation tree.
- from tempfile import NamedTemporaryFile
- archive_basename = NamedTemporaryFile().name
- fullname = self.distribution.get_fullname()
- arcname = self.make_archive(archive_basename, "zip",
- root_dir=self.bdist_dir)
- # create an exe containing the zip-file
- self.create_exe(arcname, fullname, self.bitmap)
- if self.distribution.has_ext_modules():
- pyversion = get_python_version()
- else:
- pyversion = 'any'
- self.distribution.dist_files.append(('bdist_wininst', pyversion,
- self.get_installer_filename(fullname)))
- # remove the zip-file again
- log.debug("removing temporary file '%s'", arcname)
- os.remove(arcname)
-
- if not self.keep_temp:
- if self.dry_run:
- log.info('Removing %s' % self.bdist_dir)
- else:
- rmtree(self.bdist_dir)
-
- def get_inidata (self):
- # Return data describing the installation.
-
- lines = []
- metadata = self.distribution.metadata
-
- # Write the [metadata] section.
- lines.append("[metadata]")
-
- # 'info' will be displayed in the installer's dialog box,
- # describing the items to be installed.
- info = (metadata.long_description or '') + '\n'
-
- # Escape newline characters
- def escape(s):
- return string.replace(s, "\n", "\\n")
-
- for name in ["author", "author_email", "description", "maintainer",
- "maintainer_email", "name", "url", "version"]:
- data = getattr(metadata, name, "")
- if data:
- info = info + ("\n %s: %s" % \
- (string.capitalize(name), escape(data)))
- lines.append("%s=%s" % (name, escape(data)))
-
- # The [setup] section contains entries controlling
- # the installer runtime.
- lines.append("\n[Setup]")
- if self.install_script:
- lines.append("install_script=%s" % self.install_script)
- lines.append("info=%s" % escape(info))
- lines.append("target_compile=%d" % (not self.no_target_compile))
- lines.append("target_optimize=%d" % (not self.no_target_optimize))
- if self.target_version:
- lines.append("target_version=%s" % self.target_version)
- if self.user_access_control:
- lines.append("user_access_control=%s" % self.user_access_control)
-
- title = self.title or self.distribution.get_fullname()
- lines.append("title=%s" % escape(title))
- import time
- import distutils2
- build_info = "Built %s with distutils2-%s" % \
- (time.ctime(time.time()), distutils2.__version__)
- lines.append("build_info=%s" % build_info)
- return string.join(lines, "\n")
-
- # get_inidata()
-
- def create_exe (self, arcname, fullname, bitmap=None):
- import struct
-
- self.mkpath(self.dist_dir)
-
- cfgdata = self.get_inidata()
-
- installer_name = self.get_installer_filename(fullname)
- self.announce("creating %s" % installer_name)
-
- if bitmap:
- bitmapdata = open(bitmap, "rb").read()
- bitmaplen = len(bitmapdata)
- else:
- bitmaplen = 0
-
- file = open(installer_name, "wb")
- file.write(self.get_exe_bytes())
- if bitmap:
- file.write(bitmapdata)
-
- # Convert cfgdata from unicode to ascii, mbcs encoded
- try:
- unicode
- except NameError:
- pass
- else:
- if isinstance(cfgdata, unicode):
- cfgdata = cfgdata.encode("mbcs")
-
- # Append the pre-install script
- cfgdata = cfgdata + "\0"
- if self.pre_install_script:
- script_data = open(self.pre_install_script, "r").read()
- cfgdata = cfgdata + script_data + "\n\0"
- else:
- # empty pre-install script
- cfgdata = cfgdata + "\0"
- file.write(cfgdata)
-
- # The 'magic number' 0x1234567B is used to make sure that the
- # binary layout of 'cfgdata' is what the wininst.exe binary
- # expects. If the layout changes, increment that number, make
- # the corresponding changes to the wininst.exe sources, and
- # recompile them.
- header = struct.pack("<iii",
- 0x1234567B, # tag
- len(cfgdata), # length
- bitmaplen, # number of bytes in bitmap
- )
- file.write(header)
- file.write(open(arcname, "rb").read())
-
- # create_exe()
-
- def get_installer_filename(self, fullname):
- # Factored out to allow overriding in subclasses
- if self.target_version:
- # if we create an installer for a specific python version,
- # it's better to include this in the name
- installer_name = os.path.join(self.dist_dir,
- "%s.%s-py%s.exe" %
- (fullname, self.plat_name, self.target_version))
- else:
- installer_name = os.path.join(self.dist_dir,
- "%s.%s.exe" % (fullname, self.plat_name))
- return installer_name
- # get_installer_filename()
-
- def get_exe_bytes (self):
- from distutils2.compiler.msvccompiler import get_build_version
- # If a target-version other than the current version has been
- # specified, then using the MSVC version from *this* build is no good.
- # Without actually finding and executing the target version and parsing
- # its sys.version, we just hard-code our knowledge of old versions.
- # NOTE: Possible alternative is to allow "--target-version" to
- # specify a Python executable rather than a simple version string.
- # We can then execute this program to obtain any info we need, such
- # as the real sys.version string for the build.
- cur_version = get_python_version()
- if self.target_version and self.target_version != cur_version:
- # If the target version is *later* than us, then we assume they
- # use what we use
- # string compares seem wrong, but are what sysconfig.py itself uses
- if self.target_version > cur_version:
- bv = get_build_version()
- else:
- if self.target_version < "2.4":
- bv = 6.0
- else:
- bv = 7.1
- else:
- # for current version - use authoritative check.
- bv = get_build_version()
-
- # wininst-x.y.exe is in the same directory as this file
- directory = os.path.dirname(__file__)
- # we must use a wininst-x.y.exe built with the same C compiler
- # used for python. XXX What about mingw, borland, and so on?
-
- # if plat_name starts with "win" but is not "win32"
- # we want to strip "win" and leave the rest (e.g. -amd64)
- # for all other cases, we don't want any suffix
- if self.plat_name != 'win32' and self.plat_name[:3] == 'win':
- sfix = self.plat_name[3:]
- else:
- sfix = ''
-
- filename = os.path.join(directory, "wininst-%.1f%s.exe" % (bv, sfix))
- return open(filename, "rb").read()
-# class bdist_wininst
diff --git a/src/distutils2/command/build.py b/src/distutils2/command/build.py
deleted file mode 100644
index 3f7aad7..0000000
--- a/src/distutils2/command/build.py
+++ /dev/null
@@ -1,156 +0,0 @@
-"""distutils.command.build
-
-Implements the Distutils 'build' command."""
-
-__revision__ = "$Id: build.py 77761 2010-01-26 22:46:15Z tarek.ziade $"
-
-import sys, os
-
-from distutils2.util import get_platform
-from distutils2.core import Command
-from distutils2.errors import DistutilsOptionError
-
-def show_compilers():
- from distutils2.compiler.ccompiler import show_compilers
- show_compilers()
-
-class build(Command):
-
- description = "build everything needed to install"
-
- user_options = [
- ('build-base=', 'b',
- "base directory for build library"),
- ('build-purelib=', None,
- "build directory for platform-neutral distributions"),
- ('build-platlib=', None,
- "build directory for platform-specific distributions"),
- ('build-lib=', None,
- "build directory for all distribution (defaults to either " +
- "build-purelib or build-platlib"),
- ('build-scripts=', None,
- "build directory for scripts"),
- ('build-temp=', 't',
- "temporary build directory"),
- ('plat-name=', 'p',
- "platform name to build for, if supported "
- "(default: %s)" % get_platform()),
- ('compiler=', 'c',
- "specify the compiler type"),
- ('debug', 'g',
- "compile extensions and libraries with debugging information"),
- ('force', 'f',
- "forcibly build everything (ignore file timestamps)"),
- ('executable=', 'e',
- "specify final destination interpreter path (build.py)"),
- ('use-2to3', None,
- "use 2to3 to make source python 3.x compatible"),
- ('convert-2to3-doctests', None,
- "use 2to3 to convert doctests in seperate text files"),
- ('use-2to3-fixers', None,
- "list additional fixers opted for during 2to3 conversion"),
- ]
-
- boolean_options = ['debug', 'force']
-
- help_options = [
- ('help-compiler', None,
- "list available compilers", show_compilers),
- ]
-
- def initialize_options(self):
- self.build_base = 'build'
- # these are decided only after 'build_base' has its final value
- # (unless overridden by the user or client)
- self.build_purelib = None
- self.build_platlib = None
- self.build_lib = None
- self.build_temp = None
- self.build_scripts = None
- self.compiler = None
- self.plat_name = None
- self.debug = None
- self.force = 0
- self.executable = None
- self.use_2to3 = False
- self.convert_2to3_doctests = None
- self.use_2to3_fixers = None
-
- def finalize_options(self):
- if self.plat_name is None:
- self.plat_name = get_platform()
- else:
- # plat-name only supported for windows (other platforms are
- # supported via ./configure flags, if at all). Avoid misleading
- # other platforms.
- if os.name != 'nt':
- raise DistutilsOptionError(
- "--plat-name only supported on Windows (try "
- "using './configure --help' on your platform)")
-
- plat_specifier = ".%s-%s" % (self.plat_name, sys.version[0:3])
-
- # Make it so Python 2.x and Python 2.x with --with-pydebug don't
- # share the same build directories. Doing so confuses the build
- # process for C modules
- if hasattr(sys, 'gettotalrefcount'):
- plat_specifier += '-pydebug'
-
- # 'build_purelib' and 'build_platlib' just default to 'lib' and
- # 'lib.<plat>' under the base build directory. We only use one of
- # them for a given distribution, though --
- if self.build_purelib is None:
- self.build_purelib = os.path.join(self.build_base, 'lib')
- if self.build_platlib is None:
- self.build_platlib = os.path.join(self.build_base,
- 'lib' + plat_specifier)
-
- # 'build_lib' is the actual directory that we will use for this
- # particular module distribution -- if user didn't supply it, pick
- # one of 'build_purelib' or 'build_platlib'.
- if self.build_lib is None:
- if self.distribution.ext_modules:
- self.build_lib = self.build_platlib
- else:
- self.build_lib = self.build_purelib
-
- # 'build_temp' -- temporary directory for compiler turds,
- # "build/temp.<plat>"
- if self.build_temp is None:
- self.build_temp = os.path.join(self.build_base,
- 'temp' + plat_specifier)
- if self.build_scripts is None:
- self.build_scripts = os.path.join(self.build_base,
- 'scripts-' + sys.version[0:3])
-
- if self.executable is None:
- self.executable = os.path.normpath(sys.executable)
-
- def run(self):
- # Run all relevant sub-commands. This will be some subset of:
- # - build_py - pure Python modules
- # - build_clib - standalone C libraries
- # - build_ext - Python extensions
- # - build_scripts - (Python) scripts
- for cmd_name in self.get_sub_commands():
- self.run_command(cmd_name)
-
- # -- Predicates for the sub-command list ---------------------------
-
- def has_pure_modules (self):
- return self.distribution.has_pure_modules()
-
- def has_c_libraries (self):
- return self.distribution.has_c_libraries()
-
- def has_ext_modules (self):
- return self.distribution.has_ext_modules()
-
- def has_scripts (self):
- return self.distribution.has_scripts()
-
- sub_commands = [('build_py', has_pure_modules),
- ('build_clib', has_c_libraries),
- ('build_ext', has_ext_modules),
- ('build_scripts', has_scripts),
- ]
diff --git a/src/distutils2/command/build_clib.py b/src/distutils2/command/build_clib.py
deleted file mode 100644
index e470b7e..0000000
--- a/src/distutils2/command/build_clib.py
+++ /dev/null
@@ -1,207 +0,0 @@
-"""distutils.command.build_clib
-
-Implements the Distutils 'build_clib' command, to build a C/C++ library
-that is included in the module distribution and needed by an extension
-module."""
-
-__revision__ = "$Id: build_clib.py 77704 2010-01-23 09:23:15Z tarek.ziade $"
-
-
-# XXX this module has *lots* of code ripped-off quite transparently from
-# build_ext.py -- not surprisingly really, as the work required to build
-# a static library from a collection of C source files is not really all
-# that different from what's required to build a shared object file from
-# a collection of C source files. Nevertheless, I haven't done the
-# necessary refactoring to account for the overlap in code between the
-# two modules, mainly because a number of subtle details changed in the
-# cut 'n paste. Sigh.
-
-import os
-from distutils2.core import Command
-from distutils2.errors import DistutilsSetupError
-from distutils2.compiler.ccompiler import customize_compiler
-from distutils2 import log
-
-def show_compilers():
- from distutils2.compiler.ccompiler import show_compilers
- show_compilers()
-
-
-class build_clib(Command):
-
- description = "build C/C++ libraries used by Python extensions"
-
- user_options = [
- ('build-clib=', 'b',
- "directory to build C/C++ libraries to"),
- ('build-temp=', 't',
- "directory to put temporary build by-products"),
- ('debug', 'g',
- "compile with debugging information"),
- ('force', 'f',
- "forcibly build everything (ignore file timestamps)"),
- ('compiler=', 'c',
- "specify the compiler type"),
- ]
-
- boolean_options = ['debug', 'force']
-
- help_options = [
- ('help-compiler', None,
- "list available compilers", show_compilers),
- ]
-
- def initialize_options(self):
- self.build_clib = None
- self.build_temp = None
-
- # List of libraries to build
- self.libraries = None
-
- # Compilation options for all libraries
- self.include_dirs = None
- self.define = None
- self.undef = None
- self.debug = None
- self.force = 0
- self.compiler = None
-
-
- def finalize_options(self):
- # This might be confusing: both build-clib and build-temp default
- # to build-temp as defined by the "build" command. This is because
- # I think that C libraries are really just temporary build
- # by-products, at least from the point of view of building Python
- # extensions -- but I want to keep my options open.
- self.set_undefined_options('build',
- ('build_temp', 'build_clib'),
- ('build_temp', 'build_temp'),
- 'compiler', 'debug', 'force')
-
- self.libraries = self.distribution.libraries
- if self.libraries:
- self.check_library_list(self.libraries)
-
- if self.include_dirs is None:
- self.include_dirs = self.distribution.include_dirs or []
- if isinstance(self.include_dirs, str):
- self.include_dirs = self.include_dirs.split(os.pathsep)
-
- # XXX same as for build_ext -- what about 'self.define' and
- # 'self.undef' ?
-
- def run(self):
- if not self.libraries:
- return
-
- # Yech -- this is cut 'n pasted from build_ext.py!
- from distutils2.compiler.ccompiler import new_compiler
- self.compiler = new_compiler(compiler=self.compiler,
- dry_run=self.dry_run,
- force=self.force)
- customize_compiler(self.compiler)
-
- if self.include_dirs is not None:
- self.compiler.set_include_dirs(self.include_dirs)
- if self.define is not None:
- # 'define' option is a list of (name,value) tuples
- for (name,value) in self.define:
- self.compiler.define_macro(name, value)
- if self.undef is not None:
- for macro in self.undef:
- self.compiler.undefine_macro(macro)
-
- self.build_libraries(self.libraries)
-
-
- def check_library_list(self, libraries):
- """Ensure that the list of libraries is valid.
-
- `library` is presumably provided as a command option 'libraries'.
- This method checks that it is a list of 2-tuples, where the tuples
- are (library_name, build_info_dict).
-
- Raise DistutilsSetupError if the structure is invalid anywhere;
- just returns otherwise.
- """
- if not isinstance(libraries, list):
- raise DistutilsSetupError, \
- "'libraries' option must be a list of tuples"
-
- for lib in libraries:
- if not isinstance(lib, tuple) and len(lib) != 2:
- raise DistutilsSetupError, \
- "each element of 'libraries' must a 2-tuple"
-
- name, build_info = lib
-
- if not isinstance(name, str):
- raise DistutilsSetupError, \
- "first element of each tuple in 'libraries' " + \
- "must be a string (the library name)"
- if '/' in name or (os.sep != '/' and os.sep in name):
- raise DistutilsSetupError, \
- ("bad library name '%s': " +
- "may not contain directory separators") % \
- lib[0]
-
- if not isinstance(build_info, dict):
- raise DistutilsSetupError, \
- "second element of each tuple in 'libraries' " + \
- "must be a dictionary (build info)"
-
- def get_library_names(self):
- # Assume the library list is valid -- 'check_library_list()' is
- # called from 'finalize_options()', so it should be!
- if not self.libraries:
- return None
-
- lib_names = []
- for (lib_name, build_info) in self.libraries:
- lib_names.append(lib_name)
- return lib_names
-
-
- def get_source_files(self):
- self.check_library_list(self.libraries)
- filenames = []
- for (lib_name, build_info) in self.libraries:
- sources = build_info.get('sources')
- if sources is None or not isinstance(sources, (list, tuple)):
- raise DistutilsSetupError, \
- ("in 'libraries' option (library '%s'), "
- "'sources' must be present and must be "
- "a list of source filenames") % lib_name
-
- filenames.extend(sources)
- return filenames
-
- def build_libraries(self, libraries):
- for (lib_name, build_info) in libraries:
- sources = build_info.get('sources')
- if sources is None or not isinstance(sources, (list, tuple)):
- raise DistutilsSetupError, \
- ("in 'libraries' option (library '%s'), " +
- "'sources' must be present and must be " +
- "a list of source filenames") % lib_name
- sources = list(sources)
-
- log.info("building '%s' library", lib_name)
-
- # First, compile the source code to object files in the library
- # directory. (This should probably change to putting object
- # files in a temporary build directory.)
- macros = build_info.get('macros')
- include_dirs = build_info.get('include_dirs')
- objects = self.compiler.compile(sources,
- output_dir=self.build_temp,
- macros=macros,
- include_dirs=include_dirs,
- debug=self.debug)
-
- # Now "link" the object files together into a static library.
- # (On Unix at least, this isn't really linking -- it just
- # builds an archive. Whatever.)
- self.compiler.create_static_lib(objects, lib_name,
- output_dir=self.build_clib,
- debug=self.debug)
diff --git a/src/distutils2/command/build_ext.py b/src/distutils2/command/build_ext.py
deleted file mode 100644
index 405c594..0000000
--- a/src/distutils2/command/build_ext.py
+++ /dev/null
@@ -1,740 +0,0 @@
-"""distutils.command.build_ext
-
-Implements the Distutils 'build_ext' command, for building extension
-modules (currently limited to C extensions, should accommodate C++
-extensions ASAP)."""
-
-__revision__ = "$Id: build_ext.py 77761 2010-01-26 22:46:15Z tarek.ziade $"
-
-import sys, os, re
-from warnings import warn
-
-from distutils2.util import get_platform
-from distutils2.core import Command
-from distutils2.errors import (CCompilerError, CompileError, DistutilsError,
- DistutilsPlatformError, DistutilsSetupError)
-from distutils2.compiler.ccompiler import customize_compiler
-from distutils2.util import newer_group
-from distutils2.extension import Extension
-from distutils2 import log
-try:
- import sysconfig
-except ImportError:
- from distutils2._backport import sysconfig
-
-# this keeps compatibility from 2.3 to 2.5
-if sys.version < "2.6":
- USER_BASE = None
- HAS_USER_SITE = False
-else:
- from site import USER_BASE
- HAS_USER_SITE = True
-
-if os.name == 'nt':
- from distutils2.msvccompiler import get_build_version
- MSVC_VERSION = int(get_build_version())
-
-# An extension name is just a dot-separated list of Python NAMEs (ie.
-# the same as a fully-qualified module name).
-extension_name_re = re.compile \
- (r'^[a-zA-Z_][a-zA-Z_0-9]*(\.[a-zA-Z_][a-zA-Z_0-9]*)*$')
-
-
-def show_compilers ():
- from distutils2.compiler.ccompiler import show_compilers
- show_compilers()
-
-
-class build_ext(Command):
-
- description = "build C/C++ extensions (compile/link to build directory)"
-
- # XXX thoughts on how to deal with complex command-line options like
- # these, i.e. how to make it so fancy_getopt can suck them off the
- # command line and make it look like setup.py defined the appropriate
- # lists of tuples of what-have-you.
- # - each command needs a callback to process its command-line options
- # - Command.__init__() needs access to its share of the whole
- # command line (must ultimately come from
- # Distribution.parse_command_line())
- # - it then calls the current command class' option-parsing
- # callback to deal with weird options like -D, which have to
- # parse the option text and churn out some custom data
- # structure
- # - that data structure (in this case, a list of 2-tuples)
- # will then be present in the command object by the time
- # we get to finalize_options() (i.e. the constructor
- # takes care of both command-line and client options
- # in between initialize_options() and finalize_options())
-
- sep_by = " (separated by '%s')" % os.pathsep
- user_options = [
- ('build-lib=', 'b',
- "directory for compiled extension modules"),
- ('build-temp=', 't',
- "directory for temporary files (build by-products)"),
- ('plat-name=', 'p',
- "platform name to cross-compile for, if supported "
- "(default: %s)" % get_platform()),
- ('inplace', 'i',
- "ignore build-lib and put compiled extensions into the source " +
- "directory alongside your pure Python modules"),
- ('include-dirs=', 'I',
- "list of directories to search for header files" + sep_by),
- ('define=', 'D',
- "C preprocessor macros to define"),
- ('undef=', 'U',
- "C preprocessor macros to undefine"),
- ('libraries=', 'l',
- "external C libraries to link with"),
- ('library-dirs=', 'L',
- "directories to search for external C libraries" + sep_by),
- ('rpath=', 'R',
- "directories to search for shared C libraries at runtime"),
- ('link-objects=', 'O',
- "extra explicit link objects to include in the link"),
- ('debug', 'g',
- "compile/link with debugging information"),
- ('force', 'f',
- "forcibly build everything (ignore file timestamps)"),
- ('compiler=', 'c',
- "specify the compiler type"),
- ('swig-cpp', None,
- "make SWIG create C++ files (default is C)"),
- ('swig-opts=', None,
- "list of SWIG command-line options"),
- ('swig=', None,
- "path to the SWIG executable"),
- ]
-
- boolean_options = ['inplace', 'debug', 'force', 'swig-cpp']
-
- if HAS_USER_SITE:
- user_options.append(('user', None,
- "add user include, library and rpath"))
- boolean_options.append('user')
-
- help_options = [
- ('help-compiler', None,
- "list available compilers", show_compilers),
- ]
-
-
- # making 'compiler' a property to deprecate
- # its usage as something else than a compiler type
- # e.g. like a compiler instance
- def __init__(self, dist):
- self._compiler = None
- Command.__init__(self, dist)
-
- def __setattr__(self, name, value):
- # need this to make sure setattr() (used in distutils)
- # doesn't kill our property
- if name == 'compiler':
- self._set_compiler(value)
- else:
- self.__dict__[name] = value
-
- def _set_compiler(self, compiler):
- if not isinstance(compiler, str) and compiler is not None:
- # we don't want to allow that anymore in the future
- warn("'compiler' specifies the compiler type in build_ext. "
- "If you want to get the compiler object itself, "
- "use 'compiler_obj'", DeprecationWarning)
- self._compiler = compiler
-
- def _get_compiler(self):
- if not isinstance(self._compiler, str) and self._compiler is not None:
- # we don't want to allow that anymore in the future
- warn("'compiler' specifies the compiler type in build_ext. "
- "If you want to get the compiler object itself, "
- "use 'compiler_obj'", DeprecationWarning)
- return self._compiler
-
- compiler = property(_get_compiler, _set_compiler)
-
- def initialize_options(self):
- self.extensions = None
- self.build_lib = None
- self.plat_name = None
- self.build_temp = None
- self.inplace = 0
- self.package = None
-
- self.include_dirs = None
- self.define = None
- self.undef = None
- self.libraries = None
- self.library_dirs = None
- self.rpath = None
- self.link_objects = None
- self.debug = None
- self.force = None
- self.compiler = None
- self.swig = None
- self.swig_cpp = None
- self.swig_opts = None
- if HAS_USER_SITE:
- self.user = None
-
- def finalize_options(self):
- self.set_undefined_options('build',
- 'build_lib', 'build_temp', 'compiler',
- 'debug', 'force', 'plat_name')
-
- if self.package is None:
- self.package = self.distribution.ext_package
-
- # Ensure that the list of extensions is valid, i.e. it is a list of
- # Extension objects.
- self.extensions = self.distribution.ext_modules
- if self.extensions:
- if not isinstance(self.extensions, (list, tuple)):
- type_name = (self.extensions is None and 'None'
- or type(self.extensions).__name__)
- raise DistutilsSetupError(
- "'ext_modules' must be a sequence of Extension instances,"
- " not %s" % (type_name,))
- for i, ext in enumerate(self.extensions):
- if isinstance(ext, Extension):
- continue # OK! (assume type-checking done
- # by Extension constructor)
- type_name = (ext is None and 'None' or type(ext).__name__)
- raise DistutilsSetupError(
- "'ext_modules' item %d must be an Extension instance,"
- " not %s" % (i, type_name))
-
- # Make sure Python's include directories (for Python.h, pyconfig.h,
- # etc.) are in the include search path.
- py_include = sysconfig.get_path('include')
- plat_py_include = sysconfig.get_path('platinclude')
- if self.include_dirs is None:
- self.include_dirs = self.distribution.include_dirs or []
- if isinstance(self.include_dirs, str):
- self.include_dirs = self.include_dirs.split(os.pathsep)
-
- # Put the Python "system" include dir at the end, so that
- # any local include dirs take precedence.
- self.include_dirs.append(py_include)
- if plat_py_include != py_include:
- self.include_dirs.append(plat_py_include)
-
- if isinstance(self.libraries, str):
- self.libraries = [self.libraries]
-
- # Life is easier if we're not forever checking for None, so
- # simplify these options to empty lists if unset
- if self.libraries is None:
- self.libraries = []
- if self.library_dirs is None:
- self.library_dirs = []
- elif isinstance(self.library_dirs, str):
- self.library_dirs = self.library_dirs.split(os.pathsep)
-
- if self.rpath is None:
- self.rpath = []
- elif isinstance(self.rpath, str):
- self.rpath = self.rpath.split(os.pathsep)
-
- # for extensions under windows use different directories
- # for Release and Debug builds.
- # also Python's library directory must be appended to library_dirs
- if os.name == 'nt':
- # the 'libs' directory is for binary installs - we assume that
- # must be the *native* platform. But we don't really support
- # cross-compiling via a binary install anyway, so we let it go.
- self.library_dirs.append(os.path.join(sys.exec_prefix, 'libs'))
- if self.debug:
- self.build_temp = os.path.join(self.build_temp, "Debug")
- else:
- self.build_temp = os.path.join(self.build_temp, "Release")
-
- # Append the source distribution include and library directories,
- # this allows distutils on windows to work in the source tree
- self.include_dirs.append(os.path.join(sys.exec_prefix, 'PC'))
- if MSVC_VERSION == 9:
- # Use the .lib files for the correct architecture
- if self.plat_name == 'win32':
- suffix = ''
- else:
- # win-amd64 or win-ia64
- suffix = self.plat_name[4:]
- new_lib = os.path.join(sys.exec_prefix, 'PCbuild')
- if suffix:
- new_lib = os.path.join(new_lib, suffix)
- self.library_dirs.append(new_lib)
-
- elif MSVC_VERSION == 8:
- self.library_dirs.append(os.path.join(sys.exec_prefix,
- 'PC', 'VS8.0', 'win32release'))
- elif MSVC_VERSION == 7:
- self.library_dirs.append(os.path.join(sys.exec_prefix,
- 'PC', 'VS7.1'))
- else:
- self.library_dirs.append(os.path.join(sys.exec_prefix,
- 'PC', 'VC6'))
-
- # OS/2 (EMX) doesn't support Debug vs Release builds, but has the
- # import libraries in its "Config" subdirectory
- if os.name == 'os2':
- self.library_dirs.append(os.path.join(sys.exec_prefix, 'Config'))
-
- # for extensions under Cygwin and AtheOS Python's library directory must be
- # appended to library_dirs
- if sys.platform[:6] == 'cygwin' or sys.platform[:6] == 'atheos':
- if sys.executable.startswith(os.path.join(sys.exec_prefix, "bin")):
- # building third party extensions
- self.library_dirs.append(os.path.join(sys.prefix, "lib",
- "python" + sysconfig.get_python_version(),
- "config"))
- else:
- # building python standard extensions
- self.library_dirs.append(os.curdir)
-
- # for extensions under Linux or Solaris with a shared Python library,
- # Python's library directory must be appended to library_dirs
- sysconfig.get_config_var('Py_ENABLE_SHARED')
- if ((sys.platform.startswith('linux') or sys.platform.startswith('gnu')
- or sys.platform.startswith('sunos'))
- and sysconfig.get_config_var('Py_ENABLE_SHARED')):
- if sys.executable.startswith(os.path.join(sys.exec_prefix, "bin")):
- # building third party extensions
- self.library_dirs.append(sysconfig.get_config_var('LIBDIR'))
- else:
- # building python standard extensions
- self.library_dirs.append(os.curdir)
-
- # The argument parsing will result in self.define being a string, but
- # it has to be a list of 2-tuples. All the preprocessor symbols
- # specified by the 'define' option will be set to '1'. Multiple
- # symbols can be separated with commas.
-
- if self.define:
- defines = self.define.split(',')
- self.define = [(symbol, '1') for symbol in defines]
-
- # The option for macros to undefine is also a string from the
- # option parsing, but has to be a list. Multiple symbols can also
- # be separated with commas here.
- if self.undef:
- self.undef = self.undef.split(',')
-
- if self.swig_opts is None:
- self.swig_opts = []
- else:
- self.swig_opts = self.swig_opts.split(' ')
-
- # Finally add the user include and library directories if requested
- if HAS_USER_SITE and self.user:
- user_include = os.path.join(USER_BASE, "include")
- user_lib = os.path.join(USER_BASE, "lib")
- if os.path.isdir(user_include):
- self.include_dirs.append(user_include)
- if os.path.isdir(user_lib):
- self.library_dirs.append(user_lib)
- self.rpath.append(user_lib)
-
- def run(self):
- from distutils2.compiler.ccompiler import new_compiler
-
- # 'self.extensions', as supplied by setup.py, is a list of
- # Extension instances. See the documentation for Extension (in
- # distutils.extension) for details.
- #
- # For backwards compatibility with Distutils 0.8.2 and earlier, we
- # also allow the 'extensions' list to be a list of tuples:
- # (ext_name, build_info)
- # where build_info is a dictionary containing everything that
- # Extension instances do except the name, with a few things being
- # differently named. We convert these 2-tuples to Extension
- # instances as needed.
-
- if not self.extensions:
- return
-
- # If we were asked to build any C/C++ libraries, make sure that the
- # directory where we put them is in the library search path for
- # linking extensions.
- if self.distribution.has_c_libraries():
- build_clib = self.get_finalized_command('build_clib')
- self.libraries.extend(build_clib.get_library_names() or [])
- self.library_dirs.append(build_clib.build_clib)
-
- # Setup the CCompiler object that we'll use to do all the
- # compiling and linking
-
- # used to prevent the usage of an existing compiler for the
- # compiler option when calling new_compiler()
- # this will be removed in 3.3 and 2.8
- if not isinstance(self._compiler, str):
- self._compiler = None
-
- self.compiler_obj = new_compiler(compiler=self._compiler,
- verbose=self.verbose,
- dry_run=self.dry_run,
- force=self.force)
-
- # used to keep the compiler object reachable with
- # "self.compiler". this will be removed in 3.3 and 2.8
- self._compiler = self.compiler_obj
-
- customize_compiler(self.compiler_obj)
- # If we are cross-compiling, init the compiler now (if we are not
- # cross-compiling, init would not hurt, but people may rely on
- # late initialization of compiler even if they shouldn't...)
- if os.name == 'nt' and self.plat_name != get_platform():
- self.compiler_obj.initialize(self.plat_name)
-
- # And make sure that any compile/link-related options (which might
- # come from the command line or from the setup script) are set in
- # that CCompiler object -- that way, they automatically apply to
- # all compiling and linking done here.
- if self.include_dirs is not None:
- self.compiler_obj.set_include_dirs(self.include_dirs)
- if self.define is not None:
- # 'define' option is a list of (name,value) tuples
- for (name, value) in self.define:
- self.compiler_obj.define_macro(name, value)
- if self.undef is not None:
- for macro in self.undef:
- self.compiler_obj.undefine_macro(macro)
- if self.libraries is not None:
- self.compiler_obj.set_libraries(self.libraries)
- if self.library_dirs is not None:
- self.compiler_obj.set_library_dirs(self.library_dirs)
- if self.rpath is not None:
- self.compiler_obj.set_runtime_library_dirs(self.rpath)
- if self.link_objects is not None:
- self.compiler_obj.set_link_objects(self.link_objects)
-
- # Now actually compile and link everything.
- self.build_extensions()
-
- def get_source_files(self):
- filenames = []
-
- # Wouldn't it be neat if we knew the names of header files too...
- for ext in self.extensions:
- filenames.extend(ext.sources)
-
- return filenames
-
- def get_outputs(self):
- # And build the list of output (built) filenames. Note that this
- # ignores the 'inplace' flag, and assumes everything goes in the
- # "build" tree.
- outputs = []
- for ext in self.extensions:
- outputs.append(self.get_ext_fullpath(ext.name))
- return outputs
-
- def build_extensions(self):
- for ext in self.extensions:
- try:
- self.build_extension(ext)
- except (CCompilerError, DistutilsError, CompileError), e:
- if not ext.optional:
- raise
- self.warn('building extension "%s" failed: %s' %
- (ext.name, e))
-
- def build_extension(self, ext):
- sources = ext.sources
- if sources is None or not isinstance(sources, (list, tuple)):
- raise DistutilsSetupError, \
- ("in 'ext_modules' option (extension '%s'), " +
- "'sources' must be present and must be " +
- "a list of source filenames") % ext.name
- sources = list(sources)
-
- ext_path = self.get_ext_fullpath(ext.name)
- depends = sources + ext.depends
- if not (self.force or newer_group(depends, ext_path, 'newer')):
- log.debug("skipping '%s' extension (up-to-date)", ext.name)
- return
- else:
- log.info("building '%s' extension", ext.name)
-
- # First, scan the sources for SWIG definition files (.i), run
- # SWIG on 'em to create .c files, and modify the sources list
- # accordingly.
- sources = self.swig_sources(sources, ext)
-
- # Next, compile the source code to object files.
-
- # XXX not honouring 'define_macros' or 'undef_macros' -- the
- # CCompiler API needs to change to accommodate this, and I
- # want to do one thing at a time!
-
- # Two possible sources for extra compiler arguments:
- # - 'extra_compile_args' in Extension object
- # - CFLAGS environment variable (not particularly
- # elegant, but people seem to expect it and I
- # guess it's useful)
- # The environment variable should take precedence, and
- # any sensible compiler will give precedence to later
- # command-line args. Hence we combine them in order:
- extra_args = ext.extra_compile_args or []
-
- macros = ext.define_macros[:]
- for undef in ext.undef_macros:
- macros.append((undef,))
-
- objects = self.compiler_obj.compile(sources,
- output_dir=self.build_temp,
- macros=macros,
- include_dirs=ext.include_dirs,
- debug=self.debug,
- extra_postargs=extra_args,
- depends=ext.depends)
-
- # XXX -- this is a Vile HACK!
- #
- # The setup.py script for Python on Unix needs to be able to
- # get this list so it can perform all the clean up needed to
- # avoid keeping object files around when cleaning out a failed
- # build of an extension module. Since Distutils does not
- # track dependencies, we have to get rid of intermediates to
- # ensure all the intermediates will be properly re-built.
- #
- self._built_objects = objects[:]
-
- # Now link the object files together into a "shared object" --
- # of course, first we have to figure out all the other things
- # that go into the mix.
- if ext.extra_objects:
- objects.extend(ext.extra_objects)
- extra_args = ext.extra_link_args or []
-
- # Detect target language, if not provided
- language = ext.language or self.compiler_obj.detect_language(sources)
-
- self.compiler_obj.link_shared_object(
- objects, ext_path,
- libraries=self.get_libraries(ext),
- library_dirs=ext.library_dirs,
- runtime_library_dirs=ext.runtime_library_dirs,
- extra_postargs=extra_args,
- export_symbols=self.get_export_symbols(ext),
- debug=self.debug,
- build_temp=self.build_temp,
- target_lang=language)
-
-
- def swig_sources(self, sources, extension):
- """Walk the list of source files in 'sources', looking for SWIG
- interface (.i) files. Run SWIG on all that are found, and
- return a modified 'sources' list with SWIG source files replaced
- by the generated C (or C++) files.
- """
- new_sources = []
- swig_sources = []
- swig_targets = {}
-
- # XXX this drops generated C/C++ files into the source tree, which
- # is fine for developers who want to distribute the generated
- # source -- but there should be an option to put SWIG output in
- # the temp dir.
-
- if self.swig_cpp:
- log.warn("--swig-cpp is deprecated - use --swig-opts=-c++")
-
- if self.swig_cpp or ('-c++' in self.swig_opts) or \
- ('-c++' in extension.swig_opts):
- target_ext = '.cpp'
- else:
- target_ext = '.c'
-
- for source in sources:
- (base, ext) = os.path.splitext(source)
- if ext == ".i": # SWIG interface file
- new_sources.append(base + '_wrap' + target_ext)
- swig_sources.append(source)
- swig_targets[source] = new_sources[-1]
- else:
- new_sources.append(source)
-
- if not swig_sources:
- return new_sources
-
- swig = self.swig or self.find_swig()
- swig_cmd = [swig, "-python"]
- swig_cmd.extend(self.swig_opts)
- if self.swig_cpp:
- swig_cmd.append("-c++")
-
- # Do not override commandline arguments
- if not self.swig_opts:
- for o in extension.swig_opts:
- swig_cmd.append(o)
-
- for source in swig_sources:
- target = swig_targets[source]
- log.info("swigging %s to %s", source, target)
- self.spawn(swig_cmd + ["-o", target, source])
-
- return new_sources
-
- def find_swig(self):
- """Return the name of the SWIG executable. On Unix, this is
- just "swig" -- it should be in the PATH. Tries a bit harder on
- Windows.
- """
-
- if os.name == "posix":
- return "swig"
- elif os.name == "nt":
-
- # Look for SWIG in its standard installation directory on
- # Windows (or so I presume!). If we find it there, great;
- # if not, act like Unix and assume it's in the PATH.
- for vers in ("1.3", "1.2", "1.1"):
- fn = os.path.join("c:\\swig%s" % vers, "swig.exe")
- if os.path.isfile(fn):
- return fn
- else:
- return "swig.exe"
-
- elif os.name == "os2":
- # assume swig available in the PATH.
- return "swig.exe"
-
- else:
- raise DistutilsPlatformError, \
- ("I don't know how to find (much less run) SWIG "
- "on platform '%s'") % os.name
-
- # -- Name generators -----------------------------------------------
- # (extension names, filenames, whatever)
- def get_ext_fullpath(self, ext_name):
- """Returns the path of the filename for a given extension.
-
- The file is located in `build_lib` or directly in the package
- (inplace option).
- """
- fullname = self.get_ext_fullname(ext_name)
- modpath = fullname.split('.')
- filename = self.get_ext_filename(modpath[-1])
-
- if not self.inplace:
- # no further work needed
- # returning :
- # build_dir/package/path/filename
- filename = os.path.join(*modpath[:-1]+[filename])
- return os.path.join(self.build_lib, filename)
-
- # the inplace option requires to find the package directory
- # using the build_py command for that
- package = '.'.join(modpath[0:-1])
- build_py = self.get_finalized_command('build_py')
- package_dir = os.path.abspath(build_py.get_package_dir(package))
-
- # returning
- # package_dir/filename
- return os.path.join(package_dir, filename)
-
- def get_ext_fullname(self, ext_name):
- """Returns the fullname of a given extension name.
-
- Adds the `package.` prefix"""
- if self.package is None:
- return ext_name
- else:
- return self.package + '.' + ext_name
-
- def get_ext_filename(self, ext_name):
- r"""Convert the name of an extension (eg. "foo.bar") into the name
- of the file from which it will be loaded (eg. "foo/bar.so", or
- "foo\bar.pyd").
- """
- ext_path = ext_name.split('.')
- # OS/2 has an 8 character module (extension) limit :-(
- if os.name == "os2":
- ext_path[len(ext_path) - 1] = ext_path[len(ext_path) - 1][:8]
- # extensions in debug_mode are named 'module_d.pyd' under windows
- so_ext = sysconfig.get_config_var('SO')
- if os.name == 'nt' and self.debug:
- return os.path.join(*ext_path) + '_d' + so_ext
- return os.path.join(*ext_path) + so_ext
-
- def get_export_symbols(self, ext):
- """Return the list of symbols that a shared extension has to
- export. This either uses 'ext.export_symbols' or, if it's not
- provided, "init" + module_name. Only relevant on Windows, where
- the .pyd file (DLL) must export the module "init" function.
- """
- initfunc_name = "init" + ext.name.split('.')[-1]
- if initfunc_name not in ext.export_symbols:
- ext.export_symbols.append(initfunc_name)
- return ext.export_symbols
-
- def get_libraries(self, ext):
- """Return the list of libraries to link against when building a
- shared extension. On most platforms, this is just 'ext.libraries';
- on Windows and OS/2, we add the Python library (eg. python20.dll).
- """
- # The python library is always needed on Windows. For MSVC, this
- # is redundant, since the library is mentioned in a pragma in
- # pyconfig.h that MSVC groks. The other Windows compilers all seem
- # to need it mentioned explicitly, though, so that's what we do.
- # Append '_d' to the python import library on debug builds.
- if sys.platform == "win32":
- from distutils2.msvccompiler import MSVCCompiler
- if not isinstance(self.compiler_obj, MSVCCompiler):
- template = "python%d%d"
- if self.debug:
- template = template + '_d'
- pythonlib = (template %
- (sys.hexversion >> 24, (sys.hexversion >> 16) & 0xff))
- # don't extend ext.libraries, it may be shared with other
- # extensions, it is a reference to the original list
- return ext.libraries + [pythonlib]
- else:
- return ext.libraries
- elif sys.platform == "os2emx":
- # EMX/GCC requires the python library explicitly, and I
- # believe VACPP does as well (though not confirmed) - AIM Apr01
- template = "python%d%d"
- # debug versions of the main DLL aren't supported, at least
- # not at this time - AIM Apr01
- #if self.debug:
- # template = template + '_d'
- pythonlib = (template %
- (sys.hexversion >> 24, (sys.hexversion >> 16) & 0xff))
- # don't extend ext.libraries, it may be shared with other
- # extensions, it is a reference to the original list
- return ext.libraries + [pythonlib]
- elif sys.platform[:6] == "cygwin":
- template = "python%d.%d"
- pythonlib = (template %
- (sys.hexversion >> 24, (sys.hexversion >> 16) & 0xff))
- # don't extend ext.libraries, it may be shared with other
- # extensions, it is a reference to the original list
- return ext.libraries + [pythonlib]
- elif sys.platform[:6] == "atheos":
- template = "python%d.%d"
- pythonlib = (template %
- (sys.hexversion >> 24, (sys.hexversion >> 16) & 0xff))
- # Get SHLIBS from Makefile
- extra = []
- for lib in sysconfig.get_config_var('SHLIBS').split():
- if lib.startswith('-l'):
- extra.append(lib[2:])
- else:
- extra.append(lib)
- # don't extend ext.libraries, it may be shared with other
- # extensions, it is a reference to the original list
- return ext.libraries + [pythonlib, "m"] + extra
-
- elif sys.platform == 'darwin':
- # Don't use the default code below
- return ext.libraries
-
- else:
- if sysconfig.get_config_var('Py_ENABLE_SHARED'):
- template = "python%d.%d"
- pythonlib = (template %
- (sys.hexversion >> 24, (sys.hexversion >> 16) & 0xff))
- return ext.libraries + [pythonlib]
- else:
- return ext.libraries
diff --git a/src/distutils2/command/build_py.py b/src/distutils2/command/build_py.py
deleted file mode 100644
index 98b1619..0000000
--- a/src/distutils2/command/build_py.py
+++ /dev/null
@@ -1,436 +0,0 @@
-"""distutils.command.build_py
-
-Implements the Distutils 'build_py' command."""
-
-__revision__ = "$Id: build_py.py 76956 2009-12-21 01:22:46Z tarek.ziade $"
-
-import os
-import sys
-import logging
-from glob import glob
-
-import distutils2
-from distutils2.core import Command
-from distutils2.errors import DistutilsOptionError, DistutilsFileError
-from distutils2.util import convert_path
-from distutils2.compat import Mixin2to3
-
-# marking public APIs
-__all__ = ['build_py']
-
-class build_py(Command, Mixin2to3):
-
- description = "\"build\" pure Python modules (copy to build directory)"
-
- user_options = [
- ('build-lib=', 'd', "directory to \"build\" (copy) to"),
- ('compile', 'c', "compile .py to .pyc"),
- ('no-compile', None, "don't compile .py files [default]"),
- ('optimize=', 'O',
- "also compile with optimization: -O1 for \"python -O\", "
- "-O2 for \"python -OO\", and -O0 to disable [default: -O0]"),
- ('force', 'f', "forcibly build everything (ignore file timestamps)"),
- ('use-2to3', None,
- "use 2to3 to make source python 3.x compatible"),
- ('convert-2to3-doctests', None,
- "use 2to3 to convert doctests in seperate text files"),
- ('use-2to3-fixers', None,
- "list additional fixers opted for during 2to3 conversion"),
- ]
-
- boolean_options = ['compile', 'force']
- negative_opt = {'no-compile' : 'compile'}
-
- def initialize_options(self):
- self.build_lib = None
- self.py_modules = None
- self.package = None
- self.package_data = None
- self.package_dir = None
- self.compile = 0
- self.optimize = 0
- self.force = None
- self._updated_files = []
- self._doctests_2to3 = []
- self.use_2to3 = False
- self.convert_2to3_doctests = None
- self.use_2to3_fixers = None
-
- def finalize_options(self):
- self.set_undefined_options('build',
- 'use_2to3', 'use_2to3_fixers',
- 'convert_2to3_doctests', 'build_lib',
- 'force')
-
- # Get the distribution options that are aliases for build_py
- # options -- list of packages and list of modules.
- self.packages = self.distribution.packages
- self.py_modules = self.distribution.py_modules
- self.package_data = self.distribution.package_data
- self.package_dir = {}
- if self.distribution.package_dir:
- for name, path in self.distribution.package_dir.items():
- self.package_dir[name] = convert_path(path)
- self.data_files = self.get_data_files()
-
- # Ick, copied straight from install_lib.py (fancy_getopt needs a
- # type system! Hell, *everything* needs a type system!!!)
- if not isinstance(self.optimize, int):
- try:
- self.optimize = int(self.optimize)
- assert 0 <= self.optimize <= 2
- except (ValueError, AssertionError):
- raise DistutilsOptionError("optimize must be 0, 1, or 2")
-
- def run(self):
- # XXX copy_file by default preserves atime and mtime. IMHO this is
- # the right thing to do, but perhaps it should be an option -- in
- # particular, a site administrator might want installed files to
- # reflect the time of installation rather than the last
- # modification time before the installed release.
-
- # XXX copy_file by default preserves mode, which appears to be the
- # wrong thing to do: if a file is read-only in the working
- # directory, we want it to be installed read/write so that the next
- # installation of the same module distribution can overwrite it
- # without problems. (This might be a Unix-specific issue.) Thus
- # we turn off 'preserve_mode' when copying to the build directory,
- # since the build directory is supposed to be exactly what the
- # installation will look like (ie. we preserve mode when
- # installing).
-
- # Two options control which modules will be installed: 'packages'
- # and 'py_modules'. The former lets us work with whole packages, not
- # specifying individual modules at all; the latter is for
- # specifying modules one-at-a-time.
-
- if self.py_modules:
- self.build_modules()
- if self.packages:
- self.build_packages()
- self.build_package_data()
-
- if self.use_2to3 and self._updated_files:
- self.run_2to3(self._updated_files, self._doctests_2to3,
- self.use_2to3_fixers)
-
- self.byte_compile(self.get_outputs(include_bytecode=0))
-
- # -- Top-level worker functions ------------------------------------
-
- def get_data_files(self):
- """Generate list of '(package,src_dir,build_dir,filenames)' tuples.
-
- Helper function for `finalize_options()`.
- """
- data = []
- if not self.packages:
- return data
- for package in self.packages:
- # Locate package source directory
- src_dir = self.get_package_dir(package)
-
- # Compute package build directory
- build_dir = os.path.join(*([self.build_lib] + package.split('.')))
-
- # Length of path to strip from found files
- plen = 0
- if src_dir:
- plen = len(src_dir)+1
-
- # Strip directory from globbed filenames
- filenames = [
- file[plen:] for file in self.find_data_files(package, src_dir)
- ]
- data.append((package, src_dir, build_dir, filenames))
- return data
-
- def find_data_files(self, package, src_dir):
- """Return filenames for package's data files in 'src_dir'.
-
- Helper function for `get_data_files()`.
- """
- globs = (self.package_data.get('', [])
- + self.package_data.get(package, []))
- files = []
- for pattern in globs:
- # Each pattern has to be converted to a platform-specific path
- filelist = glob(os.path.join(src_dir, convert_path(pattern)))
- # Files that match more than one pattern are only added once
- files.extend([fn for fn in filelist if fn not in files])
- return files
-
- def build_package_data(self):
- """Copy data files into build directory.
-
- Helper function for `run()`.
- """
- for package, src_dir, build_dir, filenames in self.data_files:
- for filename in filenames:
- target = os.path.join(build_dir, filename)
- self.mkpath(os.path.dirname(target))
- outf, copied = self.copy_file(os.path.join(src_dir, filename),
- target, preserve_mode=False)
- if copied and srcfile in self.distribution.convert_2to3.doctests:
- self._doctests_2to3.append(outf)
-
- # XXX - this should be moved to the Distribution class as it is not
- # only needed for build_py. It also has no dependencies on this class.
- def get_package_dir(self, package):
- """Return the directory, relative to the top of the source
- distribution, where package 'package' should be found
- (at least according to the 'package_dir' option, if any)."""
-
- path = package.split('.')
-
- if not self.package_dir:
- if path:
- return os.path.join(*path)
- else:
- return ''
- else:
- tail = []
- while path:
- try:
- pdir = self.package_dir['.'.join(path)]
- except KeyError:
- tail.insert(0, path[-1])
- del path[-1]
- else:
- tail.insert(0, pdir)
- return os.path.join(*tail)
- else:
- # Oops, got all the way through 'path' without finding a
- # match in package_dir. If package_dir defines a directory
- # for the root (nameless) package, then fallback on it;
- # otherwise, we might as well have not consulted
- # package_dir at all, as we just use the directory implied
- # by 'tail' (which should be the same as the original value
- # of 'path' at this point).
- pdir = self.package_dir.get('')
- if pdir is not None:
- tail.insert(0, pdir)
-
- if tail:
- return os.path.join(*tail)
- else:
- return ''
-
- def check_package(self, package, package_dir):
- """Helper function for `find_package_modules()` and `find_modules()'.
- """
- # Empty dir name means current directory, which we can probably
- # assume exists. Also, os.path.exists and isdir don't know about
- # my "empty string means current dir" convention, so we have to
- # circumvent them.
- if package_dir != "":
- if not os.path.exists(package_dir):
- raise DistutilsFileError(
- "package directory '%s' does not exist" % package_dir)
- if not os.path.isdir(package_dir):
- raise DistutilsFileError(
- "supposed package directory '%s' exists, "
- "but is not a directory" % package_dir)
-
- # Require __init__.py for all but the "root package"
- if package:
- init_py = os.path.join(package_dir, "__init__.py")
- if os.path.isfile(init_py):
- return init_py
- else:
- logging.warning(("package init file '%s' not found " +
- "(or not a regular file)"), init_py)
-
- # Either not in a package at all (__init__.py not expected), or
- # __init__.py doesn't exist -- so don't return the filename.
- return None
-
- def check_module(self, module, module_file):
- if not os.path.isfile(module_file):
- logging.warning("file %s (for module %s) not found",
- module_file, module)
- return False
- else:
- return True
-
- def find_package_modules(self, package, package_dir):
- self.check_package(package, package_dir)
- module_files = glob(os.path.join(package_dir, "*.py"))
- modules = []
- setup_script = os.path.abspath(self.distribution.script_name)
-
- for f in module_files:
- abs_f = os.path.abspath(f)
- if abs_f != setup_script:
- module = os.path.splitext(os.path.basename(f))[0]
- modules.append((package, module, f))
- else:
- self.debug_print("excluding %s" % setup_script)
- return modules
-
- def find_modules(self):
- """Finds individually-specified Python modules, ie. those listed by
- module name in 'self.py_modules'. Returns a list of tuples (package,
- module_base, filename): 'package' is a tuple of the path through
- package-space to the module; 'module_base' is the bare (no
- packages, no dots) module name, and 'filename' is the path to the
- ".py" file (relative to the distribution root) that implements the
- module.
- """
- # Map package names to tuples of useful info about the package:
- # (package_dir, checked)
- # package_dir - the directory where we'll find source files for
- # this package
- # checked - true if we have checked that the package directory
- # is valid (exists, contains __init__.py, ... ?)
- packages = {}
-
- # List of (package, module, filename) tuples to return
- modules = []
-
- # We treat modules-in-packages almost the same as toplevel modules,
- # just the "package" for a toplevel is empty (either an empty
- # string or empty list, depending on context). Differences:
- # - don't check for __init__.py in directory for empty package
- for module in self.py_modules:
- path = module.split('.')
- package = '.'.join(path[0:-1])
- module_base = path[-1]
-
- try:
- (package_dir, checked) = packages[package]
- except KeyError:
- package_dir = self.get_package_dir(package)
- checked = 0
-
- if not checked:
- init_py = self.check_package(package, package_dir)
- packages[package] = (package_dir, 1)
- if init_py:
- modules.append((package, "__init__", init_py))
-
- # XXX perhaps we should also check for just .pyc files
- # (so greedy closed-source bastards can distribute Python
- # modules too)
- module_file = os.path.join(package_dir, module_base + ".py")
- if not self.check_module(module, module_file):
- continue
-
- modules.append((package, module_base, module_file))
-
- return modules
-
- def find_all_modules(self):
- """Compute the list of all modules that will be built, whether
- they are specified one-module-at-a-time ('self.py_modules') or
- by whole packages ('self.packages'). Return a list of tuples
- (package, module, module_file), just like 'find_modules()' and
- 'find_package_modules()' do."""
- modules = []
- if self.py_modules:
- modules.extend(self.find_modules())
- if self.packages:
- for package in self.packages:
- package_dir = self.get_package_dir(package)
- m = self.find_package_modules(package, package_dir)
- modules.extend(m)
- return modules
-
- def get_source_files(self):
- sources = [module[-1] for module in self.find_all_modules()]
- sources += [
- os.path.join(src_dir, filename)
- for package, src_dir, build_dir, filenames in self.data_files
- for filename in filenames]
- return sources
-
- def get_module_outfile(self, build_dir, package, module):
- outfile_path = [build_dir] + list(package) + [module + ".py"]
- return os.path.join(*outfile_path)
-
- def get_outputs(self, include_bytecode=1):
- modules = self.find_all_modules()
- outputs = []
- for (package, module, module_file) in modules:
- package = package.split('.')
- filename = self.get_module_outfile(self.build_lib, package, module)
- outputs.append(filename)
- if include_bytecode:
- if self.compile:
- outputs.append(filename + "c")
- if self.optimize > 0:
- outputs.append(filename + "o")
-
- outputs += [
- os.path.join(build_dir, filename)
- for package, src_dir, build_dir, filenames in self.data_files
- for filename in filenames]
-
- return outputs
-
- def build_module(self, module, module_file, package):
- if isinstance(package, str):
- package = package.split('.')
- elif not isinstance(package, (list, tuple)):
- raise TypeError(
- "'package' must be a string (dot-separated), list, or tuple")
-
- # Now put the module source file into the "build" area -- this is
- # easy, we just copy it somewhere under self.build_lib (the build
- # directory for Python source).
- outfile = self.get_module_outfile(self.build_lib, package, module)
- dir = os.path.dirname(outfile)
- self.mkpath(dir)
- return self.copy_file(module_file, outfile, preserve_mode=0)
-
- def build_modules(self):
- modules = self.find_modules()
- for (package, module, module_file) in modules:
-
- # Now "build" the module -- ie. copy the source file to
- # self.build_lib (the build directory for Python source).
- # (Actually, it gets copied to the directory for this package
- # under self.build_lib.)
- self.build_module(module, module_file, package)
-
- def build_packages(self):
- for package in self.packages:
-
- # Get list of (package, module, module_file) tuples based on
- # scanning the package directory. 'package' is only included
- # in the tuple so that 'find_modules()' and
- # 'find_package_tuples()' have a consistent interface; it's
- # ignored here (apart from a sanity check). Also, 'module' is
- # the *unqualified* module name (ie. no dots, no package -- we
- # already know its package!), and 'module_file' is the path to
- # the .py file, relative to the current directory
- # (ie. including 'package_dir').
- package_dir = self.get_package_dir(package)
- modules = self.find_package_modules(package, package_dir)
-
- # Now loop over the modules we found, "building" each one (just
- # copy it to self.build_lib).
- for (package_, module, module_file) in modules:
- assert package == package_
- self.build_module(module, module_file, package)
-
- def byte_compile(self, files):
- if hasattr(sys, 'dont_write_bytecode') and sys.dont_write_bytecode:
- self.warn('byte-compiling is disabled, skipping.')
- return
-
- from distutils2.util import byte_compile
- prefix = self.build_lib
- if prefix[-1] != os.sep:
- prefix = prefix + os.sep
-
- # XXX this code is essentially the same as the 'byte_compile()
- # method of the "install_lib" command, except for the determination
- # of the 'prefix' string. Hmmm.
-
- if self.compile:
- byte_compile(files, optimize=0,
- force=self.force, prefix=prefix, dry_run=self.dry_run)
- if self.optimize > 0:
- byte_compile(files, optimize=self.optimize,
- force=self.force, prefix=prefix, dry_run=self.dry_run)
diff --git a/src/distutils2/command/build_scripts.py b/src/distutils2/command/build_scripts.py
deleted file mode 100644
index 758e4d6..0000000
--- a/src/distutils2/command/build_scripts.py
+++ /dev/null
@@ -1,139 +0,0 @@
-"""distutils.command.build_scripts
-
-Implements the Distutils 'build_scripts' command."""
-
-__revision__ = "$Id: build_scripts.py 77704 2010-01-23 09:23:15Z tarek.ziade $"
-
-import os, re
-from stat import ST_MODE
-from distutils2.core import Command
-from distutils2.util import convert_path, newer
-from distutils2 import log
-try:
- import sysconfig
-except ImportError:
- from distutils2._backport import sysconfig
-from distutils2.compat import Mixin2to3
-
-# check if Python is called on the first line with this expression
-first_line_re = re.compile('^#!.*python[0-9.]*([ \t].*)?$')
-
-class build_scripts (Command, Mixin2to3):
-
- description = "\"build\" scripts (copy and fixup #! line)"
-
- user_options = [
- ('build-dir=', 'd', "directory to \"build\" (copy) to"),
- ('force', 'f', "forcibly build everything (ignore file timestamps"),
- ('executable=', 'e', "specify final destination interpreter path"),
- ]
-
- boolean_options = ['force']
-
-
- def initialize_options (self):
- self.build_dir = None
- self.scripts = None
- self.force = None
- self.executable = None
- self.outfiles = None
- self.use_2to3 = False
- self.convert_2to3_doctests = None
- self.use_2to3_fixers = None
-
- def finalize_options (self):
- self.set_undefined_options('build',
- ('build_scripts', 'build_dir'),
- 'use_2to3', 'use_2to3_fixers',
- 'convert_2to3_doctests', 'force',
- 'executable')
- self.scripts = self.distribution.scripts
-
- def get_source_files(self):
- return self.scripts
-
- def run (self):
- if not self.scripts:
- return
- copied_files = self.copy_scripts()
- if self.use_2to3 and self.copied_files:
- self._run_2to3(self.copied_files, fixers=self.use_2to3_fixers)
-
- def copy_scripts (self):
- """Copy each script listed in 'self.scripts'; if it's marked as a
- Python script in the Unix way (first line matches 'first_line_re',
- ie. starts with "\#!" and contains "python"), then adjust the first
- line to refer to the current Python interpreter as we copy.
- """
- self.mkpath(self.build_dir)
- outfiles = []
- for script in self.scripts:
- adjust = 0
- script = convert_path(script)
- outfile = os.path.join(self.build_dir, os.path.basename(script))
- outfiles.append(outfile)
-
- if not self.force and not newer(script, outfile):
- log.debug("not copying %s (up-to-date)", script)
- continue
-
- # Always open the file, but ignore failures in dry-run mode --
- # that way, we'll get accurate feedback if we can read the
- # script.
- try:
- f = open(script, "r")
- except IOError:
- if not self.dry_run:
- raise
- f = None
- else:
- first_line = f.readline()
- if not first_line:
- self.warn("%s is an empty file (skipping)" % script)
- continue
-
- match = first_line_re.match(first_line)
- if match:
- adjust = 1
- post_interp = match.group(1) or ''
-
- if adjust:
- log.info("copying and adjusting %s -> %s", script,
- self.build_dir)
- if not self.dry_run:
- outf = open(outfile, "w")
- if not sysconfig.is_python_build():
- outf.write("#!%s%s\n" %
- (self.executable,
- post_interp))
- else:
- outf.write("#!%s%s\n" %
- (os.path.join(
- sysconfig.get_config_var("BINDIR"),
- "python%s%s" % (sysconfig.get_config_var("VERSION"),
- sysconfig.get_config_var("EXE"))),
- post_interp))
- outf.writelines(f.readlines())
- outf.close()
- if f:
- f.close()
- else:
- if f:
- f.close()
- self.copy_file(script, outfile)
-
- if os.name == 'posix':
- for file in outfiles:
- if self.dry_run:
- log.info("changing mode of %s", file)
- else:
- oldmode = os.stat(file)[ST_MODE] & 07777
- newmode = (oldmode | 0555) & 07777
- if newmode != oldmode:
- log.info("changing mode of %s from %o to %o",
- file, oldmode, newmode)
- os.chmod(file, newmode)
- return outfiles
- # copy_scripts ()
-
-# class build_scripts
diff --git a/src/distutils2/command/check.py b/src/distutils2/command/check.py
deleted file mode 100644
index cfb6694..0000000
--- a/src/distutils2/command/check.py
+++ /dev/null
@@ -1,88 +0,0 @@
-"""distutils.command.check
-
-Implements the Distutils 'check' command.
-"""
-__revision__ = "$Id: check.py 75266 2009-10-05 22:32:48Z andrew.kuchling $"
-
-from distutils2.core import Command
-from distutils2.errors import DistutilsSetupError
-from distutils2.util import resolve_name
-
-class check(Command):
- """This command checks the metadata of the package.
- """
- description = ("perform some checks on the package")
- user_options = [('metadata', 'm', 'Verify metadata'),
- ('all', 'a',
- ('runs extended set of checks')),
- ('strict', 's',
- 'Will exit with an error if a check fails')]
-
- boolean_options = ['metadata', 'all', 'strict']
-
- def initialize_options(self):
- """Sets default values for options."""
- self.all = 0
- self.metadata = 1
- self.strict = 0
- self._warnings = []
-
- def finalize_options(self):
- pass
-
- def warn(self, msg):
- """Counts the number of warnings that occurs."""
- self._warnings.append(msg)
- return Command.warn(self, msg)
-
- def run(self):
- """Runs the command."""
- # perform the various tests
- if self.metadata:
- self.check_metadata()
- if self.all:
- self.check_restructuredtext()
- self.check_hooks_resolvable()
-
- # let's raise an error in strict mode, if we have at least
- # one warning
- if self.strict and len(self._warnings) > 0:
- msg = '\n'.join(self._warnings)
- raise DistutilsSetupError(msg)
-
- def check_metadata(self):
- """Ensures that all required elements of metadata are supplied.
-
- name, version, URL, (author and author_email) or
- (maintainer and maintainer_email)).
-
- Warns if any are missing.
- """
- missing, __ = self.distribution.metadata.check()
- if missing != []:
- self.warn("missing required metadata: %s" % ', '.join(missing))
-
- def check_restructuredtext(self):
- """Checks if the long string fields are reST-compliant."""
- missing, warnings = self.distribution.metadata.check()
- if self.distribution.metadata.docutils_support:
- for warning in warnings:
- line = warning[-1].get('line')
- if line is None:
- warning = warning[1]
- else:
- warning = '%s (line %s)' % (warning[1], line)
- self.warn(warning)
- elif self.strict:
- raise DistutilsSetupError('The docutils package is needed.')
-
- def check_hooks_resolvable(self):
- for options in self.distribution.command_options.values():
- for hook_kind in ("pre_hook", "post_hook"):
- if hook_kind not in options:
- break
- for hook_name in options[hook_kind][1].values():
- try:
- resolve_name(hook_name)
- except ImportError:
- self.warn("Name '%s' cannot be resolved." % hook_name)
diff --git a/src/distutils2/command/clean.py b/src/distutils2/command/clean.py
deleted file mode 100644
index 8125dcd..0000000
--- a/src/distutils2/command/clean.py
+++ /dev/null
@@ -1,82 +0,0 @@
-"""distutils.command.clean
-
-Implements the Distutils 'clean' command."""
-
-# contributed by Bastian Kleineidam <calvin@cs.uni-sb.de>, added 2000-03-18
-
-__revision__ = "$Id: clean.py 70886 2009-03-31 20:50:59Z tarek.ziade $"
-
-import os
-from shutil import rmtree
-from distutils2.core import Command
-from distutils2 import log
-
-class clean(Command):
-
- description = "clean up temporary files from 'build' command"
- user_options = [
- ('build-base=', 'b',
- "base build directory (default: 'build.build-base')"),
- ('build-lib=', None,
- "build directory for all modules (default: 'build.build-lib')"),
- ('build-temp=', 't',
- "temporary build directory (default: 'build.build-temp')"),
- ('build-scripts=', None,
- "build directory for scripts (default: 'build.build-scripts')"),
- ('bdist-base=', None,
- "temporary directory for built distributions"),
- ('all', 'a',
- "remove all build output, not just temporary by-products")
- ]
-
- boolean_options = ['all']
-
- def initialize_options(self):
- self.build_base = None
- self.build_lib = None
- self.build_temp = None
- self.build_scripts = None
- self.bdist_base = None
- self.all = None
-
- def finalize_options(self):
- self.set_undefined_options('build', 'build_base', 'build_lib',
- 'build_scripts', 'build_temp')
- self.set_undefined_options('bdist', 'bdist_base')
-
- def run(self):
- # remove the build/temp.<plat> directory (unless it's already
- # gone)
- if os.path.exists(self.build_temp):
- if self.dry_run:
- log.info('Removing %s' % self.build_temp)
- else:
- rmtree(self.build_temp)
- else:
- log.debug("'%s' does not exist -- can't clean it",
- self.build_temp)
-
- if self.all:
- # remove build directories
- for directory in (self.build_lib,
- self.bdist_base,
- self.build_scripts):
- if os.path.exists(directory):
- if self.dry_run:
- log.info('Removing %s' % directory)
- else:
- rmtree(directory)
- else:
- log.warn("'%s' does not exist -- can't clean it",
- directory)
-
- # just for the heck of it, try to remove the base build directory:
- # we might have emptied it right now, but if not we don't care
- if not self.dry_run:
- try:
- os.rmdir(self.build_base)
- log.info("removing '%s'", self.build_base)
- except OSError:
- pass
-
-# class clean
diff --git a/src/distutils2/command/cmd.py b/src/distutils2/command/cmd.py
deleted file mode 100644
index 17a4379..0000000
--- a/src/distutils2/command/cmd.py
+++ /dev/null
@@ -1,494 +0,0 @@
-"""distutils.cmd
-
-Provides the Command class, the base class for the command classes
-in the distutils.command package.
-"""
-
-__revision__ = "$Id: cmd.py 75192 2009-10-02 23:49:48Z tarek.ziade $"
-
-import os, re
-from distutils2.errors import DistutilsOptionError
-from distutils2 import util
-from distutils2 import log
-
-# XXX see if we want to backport this
-from distutils2._backport.shutil import copytree, copyfile, move
-
-try:
- from shutil import make_archive
-except ImportError:
- from distutils2._backport.shutil import make_archive
-
-class Command(object):
- """Abstract base class for defining command classes, the "worker bees"
- of the Distutils. A useful analogy for command classes is to think of
- them as subroutines with local variables called "options". The options
- are "declared" in 'initialize_options()' and "defined" (given their
- final values, aka "finalized") in 'finalize_options()', both of which
- must be defined by every command class. The distinction between the
- two is necessary because option values might come from the outside
- world (command line, config file, ...), and any options dependent on
- other options must be computed *after* these outside influences have
- been processed -- hence 'finalize_options()'. The "body" of the
- subroutine, where it does all its work based on the values of its
- options, is the 'run()' method, which must also be implemented by every
- command class.
- """
-
- # 'sub_commands' formalizes the notion of a "family" of commands,
- # eg. "install" as the parent with sub-commands "install_lib",
- # "install_headers", etc. The parent of a family of commands
- # defines 'sub_commands' as a class attribute; it's a list of
- # (command_name : string, predicate : unbound_method | string | None)
- # tuples, where 'predicate' is a method of the parent command that
- # determines whether the corresponding command is applicable in the
- # current situation. (Eg. we "install_headers" is only applicable if
- # we have any C header files to install.) If 'predicate' is None,
- # that command is always applicable.
- #
- # 'sub_commands' is usually defined at the *end* of a class, because
- # predicates can be unbound methods, so they must already have been
- # defined. The canonical example is the "install" command.
- sub_commands = []
-
- # Pre and post command hooks are run just before or just after the command
- # itself. They are simple functions that receive the command instance. They
- # are specified as callable objects or dotted strings (for lazy loading).
- pre_hook = None
- post_hook = None
-
-
- # -- Creation/initialization methods -------------------------------
-
- def __init__(self, dist):
- """Create and initialize a new Command object. Most importantly,
- invokes the 'initialize_options()' method, which is the real
- initializer and depends on the actual command being instantiated.
- """
- # late import because of mutual dependence between these classes
- from distutils2.dist import Distribution
-
- if not isinstance(dist, Distribution):
- raise TypeError, "dist must be a Distribution instance"
- if self.__class__ is Command:
- raise RuntimeError, "Command is an abstract class"
-
- self.distribution = dist
- self.initialize_options()
-
- # Per-command versions of the global flags, so that the user can
- # customize Distutils' behaviour command-by-command and let some
- # commands fall back on the Distribution's behaviour. None means
- # "not defined, check self.distribution's copy", while 0 or 1 mean
- # false and true (duh). Note that this means figuring out the real
- # value of each flag is a touch complicated -- hence "self._dry_run"
- # will be handled by a property, below.
- # XXX This needs to be fixed. [I changed it to a property--does that
- # "fix" it?]
- self._dry_run = None
-
- # verbose is largely ignored, but needs to be set for
- # backwards compatibility (I think)?
- self.verbose = dist.verbose
-
- # Some commands define a 'self.force' option to ignore file
- # timestamps, but methods defined *here* assume that
- # 'self.force' exists for all commands. So define it here
- # just to be safe.
- self.force = None
-
- # The 'help' flag is just used for command line parsing, so
- # none of that complicated bureaucracy is needed.
- self.help = 0
-
- # 'finalized' records whether or not 'finalize_options()' has been
- # called. 'finalize_options()' itself should not pay attention to
- # this flag: it is the business of 'ensure_finalized()', which
- # always calls 'finalize_options()', to respect/update it.
- self.finalized = 0
-
- # XXX A more explicit way to customize dry_run would be better.
- @property
- def dry_run(self):
- if self._dry_run is None:
- return getattr(self.distribution, 'dry_run')
- else:
- return self._dry_run
-
- def ensure_finalized(self):
- if not self.finalized:
- self.finalize_options()
- self.finalized = 1
-
- # Subclasses must define:
- # initialize_options()
- # provide default values for all options; may be customized by
- # setup script, by options from config file(s), or by command-line
- # options
- # finalize_options()
- # decide on the final values for all options; this is called
- # after all possible intervention from the outside world
- # (command line, option file, etc.) has been processed
- # run()
- # run the command: do whatever it is we're here to do,
- # controlled by the command's various option values
-
- def initialize_options(self):
- """Set default values for all the options that this command
- supports. Note that these defaults may be overridden by other
- commands, by the setup script, by config files, or by the
- command line. Thus, this is not the place to code dependencies
- between options; generally, 'initialize_options()' implementations
- are just a bunch of "self.foo = None" assignments.
-
- This method must be implemented by all command classes.
- """
- raise RuntimeError, \
- "abstract method -- subclass %s must override" % self.__class__
-
- def finalize_options(self):
- """Set final values for all the options that this command supports.
- This is always called as late as possible, ie. after any option
- assignments from the command line or from other commands have been
- done. Thus, this is the place to code option dependencies: if
- 'foo' depends on 'bar', then it is safe to set 'foo' from 'bar' as
- long as 'foo' still has the same value it was assigned in
- 'initialize_options()'.
-
- This method must be implemented by all command classes.
- """
- raise RuntimeError, \
- "abstract method -- subclass %s must override" % self.__class__
-
-
- def dump_options(self, header=None, indent=""):
- if header is None:
- header = "command options for '%s':" % self.get_command_name()
- self.announce(indent + header, level=log.INFO)
- indent = indent + " "
- for (option, _, _) in self.user_options:
- option = option.replace('-', '_')
- if option[-1] == "=":
- option = option[:-1]
- value = getattr(self, option)
- self.announce(indent + "%s = %s" % (option, value),
- level=log.INFO)
-
- def run(self):
- """A command's raison d'etre: carry out the action it exists to
- perform, controlled by the options initialized in
- 'initialize_options()', customized by other commands, the setup
- script, the command line and config files, and finalized in
- 'finalize_options()'. All terminal output and filesystem
- interaction should be done by 'run()'.
-
- This method must be implemented by all command classes.
- """
- raise RuntimeError, \
- "abstract method -- subclass %s must override" % self.__class__
-
- def announce(self, msg, level=1):
- """If the current verbosity level is of greater than or equal to
- 'level' print 'msg' to stdout.
- """
- log.log(level, msg)
-
- # -- External interface --------------------------------------------
- # (called by outsiders)
-
- def get_source_files(self):
- """Return the list of files that are used as inputs to this command,
- i.e. the files used to generate the output files. The result is used
- by the `sdist` command in determining the set of default files.
-
- Command classes should implement this method if they operate on files
- from the source tree.
- """
- return []
-
- def get_outputs(self):
- """Return the list of files that would be produced if this command
- were actually run. Not affected by the "dry-run" flag or whether
- any other commands have been run.
-
- Command classes should implement this method if they produce any
- output files that get consumed by another command. e.g., `build_ext`
- returns the list of built extension modules, but not any temporary
- files used in the compilation process.
- """
- return []
-
- # -- Option validation methods -------------------------------------
- # (these are very handy in writing the 'finalize_options()' method)
- #
- # NB. the general philosophy here is to ensure that a particular option
- # value meets certain type and value constraints. If not, we try to
- # force it into conformance (eg. if we expect a list but have a string,
- # split the string on comma and/or whitespace). If we can't force the
- # option into conformance, raise DistutilsOptionError. Thus, command
- # classes need do nothing more than (eg.)
- # self.ensure_string_list('foo')
- # and they can be guaranteed that thereafter, self.foo will be
- # a list of strings.
-
- def _ensure_stringlike(self, option, what, default=None):
- val = getattr(self, option)
- if val is None:
- setattr(self, option, default)
- return default
- elif not isinstance(val, str):
- raise DistutilsOptionError, \
- "'%s' must be a %s (got `%s`)" % (option, what, val)
- return val
-
- def ensure_string(self, option, default=None):
- """Ensure that 'option' is a string; if not defined, set it to
- 'default'.
- """
- self._ensure_stringlike(option, "string", default)
-
- def ensure_string_list(self, option):
- """Ensure that 'option' is a list of strings. If 'option' is
- currently a string, we split it either on /,\s*/ or /\s+/, so
- "foo bar baz", "foo,bar,baz", and "foo, bar baz" all become
- ["foo", "bar", "baz"].
- """
- val = getattr(self, option)
- if val is None:
- return
- elif isinstance(val, str):
- setattr(self, option, re.split(r',\s*|\s+', val))
- else:
- if isinstance(val, list):
- # checks if all elements are str
- ok = 1
- for element in val:
- if not isinstance(element, str):
- ok = 0
- break
- else:
- ok = 0
-
- if not ok:
- raise DistutilsOptionError, \
- "'%s' must be a list of strings (got %r)" % \
- (option, val)
-
-
- def _ensure_tested_string(self, option, tester,
- what, error_fmt, default=None):
- val = self._ensure_stringlike(option, what, default)
- if val is not None and not tester(val):
- raise DistutilsOptionError, \
- ("error in '%s' option: " + error_fmt) % (option, val)
-
- def ensure_filename(self, option):
- """Ensure that 'option' is the name of an existing file."""
- self._ensure_tested_string(option, os.path.isfile,
- "filename",
- "'%s' does not exist or is not a file")
-
- def ensure_dirname(self, option):
- self._ensure_tested_string(option, os.path.isdir,
- "directory name",
- "'%s' does not exist or is not a directory")
-
-
- # -- Convenience methods for commands ------------------------------
-
- def get_command_name(self):
- if hasattr(self, 'command_name'):
- return self.command_name
- else:
- return self.__class__.__name__
-
- def set_undefined_options(self, src_cmd, *options):
- """Set values of undefined options from another command.
-
- Undefined options are options set to None, which is the convention
- used to indicate that an option has not been changed between
- 'initialize_options()' and 'finalize_options()'. This method is
- usually called from 'finalize_options()' for options that depend on
- some other command rather than another option of the same command,
- typically subcommands.
-
- The 'src_cmd' argument is the other command from which option values
- will be taken (a command object will be created for it if necessary);
- the remaining positional arguments are strings that give the name of
- the option to set. If the name is different on the source and target
- command, you can pass a tuple with '(name_on_source, name_on_dest)' so
- that 'self.name_on_dest' will be set from 'src_cmd.name_on_source'.
- """
- src_cmd_obj = self.distribution.get_command_obj(src_cmd)
- src_cmd_obj.ensure_finalized()
- for obj in options:
- if isinstance(obj, tuple):
- src_option, dst_option = obj
- else:
- src_option, dst_option = obj, obj
- if getattr(self, dst_option) is None:
- setattr(self, dst_option,
- getattr(src_cmd_obj, src_option))
-
- def get_finalized_command(self, command, create=1):
- """Wrapper around Distribution's 'get_command_obj()' method: find
- (create if necessary and 'create' is true) the command object for
- 'command', call its 'ensure_finalized()' method, and return the
- finalized command object.
- """
- cmd_obj = self.distribution.get_command_obj(command, create)
- cmd_obj.ensure_finalized()
- return cmd_obj
-
- def get_reinitialized_command(self, command, reinit_subcommands=0):
- return self.distribution.get_reinitialized_command(
- command, reinit_subcommands)
-
- def run_command(self, command):
- """Run some other command: uses the 'run_command()' method of
- Distribution, which creates and finalizes the command object if
- necessary and then invokes its 'run()' method.
- """
- self.distribution.run_command(command)
-
- def get_sub_commands(self):
- """Determine the sub-commands that are relevant in the current
- distribution (ie., that need to be run). This is based on the
- 'sub_commands' class attribute: each tuple in that list may include
- a method that we call to determine if the subcommand needs to be
- run for the current distribution. Return a list of command names.
- """
- commands = []
- for (cmd_name, method) in self.sub_commands:
- if method is None or method(self):
- commands.append(cmd_name)
- return commands
-
-
- # -- External world manipulation -----------------------------------
-
- def warn(self, msg):
- log.warn("warning: %s: %s\n" %
- (self.get_command_name(), msg))
-
- def execute(self, func, args, msg=None, level=1):
- util.execute(func, args, msg, dry_run=self.dry_run)
-
- def mkpath(self, name, mode=0777, dry_run=None, verbose=0):
- if dry_run is None:
- dry_run = self.dry_run
- name = os.path.normpath(name)
- if os.path.isdir(name) or name == '':
- return
- if dry_run:
- head = ''
- for part in name.split(os.sep):
- log.info("created directory %s%s", head, part)
- head += part + os.sep
- return
- os.makedirs(name, mode)
-
- def copy_file(self, infile, outfile,
- preserve_mode=1, preserve_times=1, link=None, level=1):
- """Copy a file respecting verbose, dry-run and force flags. (The
- former two default to whatever is in the Distribution object, and
- the latter defaults to false for commands that don't define it.)"""
- if self.dry_run:
- # XXX add a comment
- return
- if os.path.isdir(outfile):
- outfile = os.path.join(outfile, os.path.split(infile)[-1])
- copyfile(infile, outfile)
- return outfile, None # XXX
-
- def copy_tree(self, infile, outfile,
- preserve_mode=1, preserve_times=1, preserve_symlinks=0,
- level=1):
- """Copy an entire directory tree respecting verbose, dry-run,
- and force flags.
- """
- if self.dry_run:
- return # see if we want to display something
- return copytree(infile, outfile, preserve_symlinks)
-
- def move_file(self, src, dst, level=1):
- """Move a file respectin dry-run flag."""
- if self.dry_run:
- return # XXX log ?
- return move(src, dst)
-
- def spawn(self, cmd, search_path=1, level=1):
- """Spawn an external command respecting dry-run flag."""
- from distutils2.util import spawn
- spawn(cmd, search_path, dry_run= self.dry_run)
-
- def make_archive(self, base_name, format, root_dir=None, base_dir=None,
- owner=None, group=None):
- return make_archive(base_name, format, root_dir,
- base_dir, dry_run=self.dry_run,
- owner=owner, group=group)
-
- def make_file(self, infiles, outfile, func, args,
- exec_msg=None, skip_msg=None, level=1):
- """Special case of 'execute()' for operations that process one or
- more input files and generate one output file. Works just like
- 'execute()', except the operation is skipped and a different
- message printed if 'outfile' already exists and is newer than all
- files listed in 'infiles'. If the command defined 'self.force',
- and it is true, then the command is unconditionally run -- does no
- timestamp checks.
- """
- if skip_msg is None:
- skip_msg = "skipping %s (inputs unchanged)" % outfile
-
- # Allow 'infiles' to be a single string
- if isinstance(infiles, str):
- infiles = (infiles,)
- elif not isinstance(infiles, (list, tuple)):
- raise TypeError, \
- "'infiles' must be a string, or a list or tuple of strings"
-
- if exec_msg is None:
- exec_msg = "generating %s from %s" % \
- (outfile, ', '.join(infiles))
-
- # If 'outfile' must be regenerated (either because it doesn't
- # exist, is out-of-date, or the 'force' flag is true) then
- # perform the action that presumably regenerates it
- if self.force or util.newer_group(infiles, outfile):
- self.execute(func, args, exec_msg, level)
-
- # Otherwise, print the "skip" message
- else:
- log.debug(skip_msg)
-
-# XXX 'install_misc' class not currently used -- it was the base class for
-# both 'install_scripts' and 'install_data', but they outgrew it. It might
-# still be useful for 'install_headers', though, so I'm keeping it around
-# for the time being.
-
-class install_misc(Command):
- """Common base class for installing some files in a subdirectory.
- Currently used by install_data and install_scripts.
- """
-
- user_options = [('install-dir=', 'd', "directory to install the files to")]
-
- def initialize_options (self):
- self.install_dir = None
- self.outfiles = []
-
- def _install_dir_from(self, dirname):
- self.set_undefined_options('install', (dirname, 'install_dir'))
-
- def _copy_files(self, filelist):
- self.outfiles = []
- if not filelist:
- return
- self.mkpath(self.install_dir)
- for f in filelist:
- self.copy_file(f, self.install_dir)
- self.outfiles.append(os.path.join(self.install_dir, f))
-
- def get_outputs(self):
- return self.outfiles
diff --git a/src/distutils2/command/command_template b/src/distutils2/command/command_template
deleted file mode 100644
index 50bbab7..0000000
--- a/src/distutils2/command/command_template
+++ /dev/null
@@ -1,45 +0,0 @@
-"""distutils.command.x
-
-Implements the Distutils 'x' command.
-"""
-
-# created 2000/mm/dd, John Doe
-
-__revision__ = "$Id$"
-
-from distutils.core import Command
-
-
-class x (Command):
-
- # Brief (40-50 characters) description of the command
- description = ""
-
- # List of option tuples: long name, short name (None if no short
- # name), and help string.
- user_options = [('', '',
- ""),
- ]
-
-
- def initialize_options (self):
- self. = None
- self. = None
- self. = None
-
- # initialize_options()
-
-
- def finalize_options (self):
- if self.x is None:
- self.x =
-
- # finalize_options()
-
-
- def run (self):
-
-
- # run()
-
-# class x
diff --git a/src/distutils2/command/config.py b/src/distutils2/command/config.py
deleted file mode 100644
index ab26f77..0000000
--- a/src/distutils2/command/config.py
+++ /dev/null
@@ -1,357 +0,0 @@
-"""distutils.command.config
-
-Implements the Distutils 'config' command, a (mostly) empty command class
-that exists mainly to be sub-classed by specific module distributions and
-applications. The idea is that while every "config" command is different,
-at least they're all named the same, and users always see "config" in the
-list of standard commands. Also, this is a good place to put common
-configure-like tasks: "try to compile this C code", or "figure out where
-this header file lives".
-"""
-
-__revision__ = "$Id: config.py 77704 2010-01-23 09:23:15Z tarek.ziade $"
-
-import os
-import re
-
-from distutils2.core import Command
-from distutils2.errors import DistutilsExecError
-from distutils2.compiler.ccompiler import customize_compiler
-from distutils2 import log
-
-LANG_EXT = {'c': '.c', 'c++': '.cxx'}
-
-class config(Command):
-
- description = "prepare to build"
-
- user_options = [
- ('compiler=', None,
- "specify the compiler type"),
- ('cc=', None,
- "specify the compiler executable"),
- ('include-dirs=', 'I',
- "list of directories to search for header files"),
- ('define=', 'D',
- "C preprocessor macros to define"),
- ('undef=', 'U',
- "C preprocessor macros to undefine"),
- ('libraries=', 'l',
- "external C libraries to link with"),
- ('library-dirs=', 'L',
- "directories to search for external C libraries"),
-
- ('noisy', None,
- "show every action (compile, link, run, ...) taken"),
- ('dump-source', None,
- "dump generated source files before attempting to compile them"),
- ]
-
-
- # The three standard command methods: since the "config" command
- # does nothing by default, these are empty.
-
- def initialize_options(self):
- self.compiler = None
- self.cc = None
- self.include_dirs = None
- self.libraries = None
- self.library_dirs = None
-
- # maximal output for now
- self.noisy = 1
- self.dump_source = 1
-
- # list of temporary files generated along-the-way that we have
- # to clean at some point
- self.temp_files = []
-
- def finalize_options(self):
- if self.include_dirs is None:
- self.include_dirs = self.distribution.include_dirs or []
- elif isinstance(self.include_dirs, str):
- self.include_dirs = self.include_dirs.split(os.pathsep)
-
- if self.libraries is None:
- self.libraries = []
- elif isinstance(self.libraries, str):
- self.libraries = [self.libraries]
-
- if self.library_dirs is None:
- self.library_dirs = []
- elif isinstance(self.library_dirs, str):
- self.library_dirs = self.library_dirs.split(os.pathsep)
-
- def run(self):
- pass
-
-
- # Utility methods for actual "config" commands. The interfaces are
- # loosely based on Autoconf macros of similar names. Sub-classes
- # may use these freely.
-
- def _check_compiler(self):
- """Check that 'self.compiler' really is a CCompiler object;
- if not, make it one.
- """
- # We do this late, and only on-demand, because this is an expensive
- # import.
- from distutils2.compiler.ccompiler import CCompiler, new_compiler
- if not isinstance(self.compiler, CCompiler):
- self.compiler = new_compiler(compiler=self.compiler,
- dry_run=self.dry_run, force=1)
- customize_compiler(self.compiler)
- if self.include_dirs:
- self.compiler.set_include_dirs(self.include_dirs)
- if self.libraries:
- self.compiler.set_libraries(self.libraries)
- if self.library_dirs:
- self.compiler.set_library_dirs(self.library_dirs)
-
-
- def _gen_temp_sourcefile(self, body, headers, lang):
- filename = "_configtest" + LANG_EXT[lang]
- file = open(filename, "w")
- if headers:
- for header in headers:
- file.write("#include <%s>\n" % header)
- file.write("\n")
- file.write(body)
- if body[-1] != "\n":
- file.write("\n")
- file.close()
- return filename
-
- def _preprocess(self, body, headers, include_dirs, lang):
- src = self._gen_temp_sourcefile(body, headers, lang)
- out = "_configtest.i"
- self.temp_files.extend([src, out])
- self.compiler.preprocess(src, out, include_dirs=include_dirs)
- return (src, out)
-
- def _compile(self, body, headers, include_dirs, lang):
- src = self._gen_temp_sourcefile(body, headers, lang)
- if self.dump_source:
- dump_file(src, "compiling '%s':" % src)
- (obj,) = self.compiler.object_filenames([src])
- self.temp_files.extend([src, obj])
- self.compiler.compile([src], include_dirs=include_dirs)
- return (src, obj)
-
- def _link(self, body, headers, include_dirs, libraries, library_dirs,
- lang):
- (src, obj) = self._compile(body, headers, include_dirs, lang)
- prog = os.path.splitext(os.path.basename(src))[0]
- self.compiler.link_executable([obj], prog,
- libraries=libraries,
- library_dirs=library_dirs,
- target_lang=lang)
-
- if self.compiler.exe_extension is not None:
- prog = prog + self.compiler.exe_extension
- self.temp_files.append(prog)
-
- return (src, obj, prog)
-
- def _clean(self, *filenames):
- if not filenames:
- filenames = self.temp_files
- self.temp_files = []
- log.info("removing: %s", ' '.join(filenames))
- for filename in filenames:
- try:
- os.remove(filename)
- except OSError:
- pass
-
-
- # XXX these ignore the dry-run flag: what to do, what to do? even if
- # you want a dry-run build, you still need some sort of configuration
- # info. My inclination is to make it up to the real config command to
- # consult 'dry_run', and assume a default (minimal) configuration if
- # true. The problem with trying to do it here is that you'd have to
- # return either true or false from all the 'try' methods, neither of
- # which is correct.
-
- # XXX need access to the header search path and maybe default macros.
-
- def try_cpp(self, body=None, headers=None, include_dirs=None, lang="c"):
- """Construct a source file from 'body' (a string containing lines
- of C/C++ code) and 'headers' (a list of header files to include)
- and run it through the preprocessor. Return true if the
- preprocessor succeeded, false if there were any errors.
- ('body' probably isn't of much use, but what the heck.)
- """
- from distutils2.compiler.ccompiler import CompileError
- self._check_compiler()
- ok = 1
- try:
- self._preprocess(body, headers, include_dirs, lang)
- except CompileError:
- ok = 0
-
- self._clean()
- return ok
-
- def search_cpp(self, pattern, body=None, headers=None, include_dirs=None,
- lang="c"):
- """Construct a source file (just like 'try_cpp()'), run it through
- the preprocessor, and return true if any line of the output matches
- 'pattern'. 'pattern' should either be a compiled regex object or a
- string containing a regex. If both 'body' and 'headers' are None,
- preprocesses an empty file -- which can be useful to determine the
- symbols the preprocessor and compiler set by default.
- """
- self._check_compiler()
- src, out = self._preprocess(body, headers, include_dirs, lang)
-
- if isinstance(pattern, str):
- pattern = re.compile(pattern)
-
- file = open(out)
- match = 0
- while 1:
- line = file.readline()
- if line == '':
- break
- if pattern.search(line):
- match = 1
- break
-
- file.close()
- self._clean()
- return match
-
- def try_compile(self, body, headers=None, include_dirs=None, lang="c"):
- """Try to compile a source file built from 'body' and 'headers'.
- Return true on success, false otherwise.
- """
- from distutils2.compiler.ccompiler import CompileError
- self._check_compiler()
- try:
- self._compile(body, headers, include_dirs, lang)
- ok = 1
- except CompileError:
- ok = 0
-
- log.info(ok and "success!" or "failure.")
- self._clean()
- return ok
-
- def try_link(self, body, headers=None, include_dirs=None, libraries=None,
- library_dirs=None, lang="c"):
- """Try to compile and link a source file, built from 'body' and
- 'headers', to executable form. Return true on success, false
- otherwise.
- """
- from distutils2.compiler.ccompiler import CompileError, LinkError
- self._check_compiler()
- try:
- self._link(body, headers, include_dirs,
- libraries, library_dirs, lang)
- ok = 1
- except (CompileError, LinkError):
- ok = 0
-
- log.info(ok and "success!" or "failure.")
- self._clean()
- return ok
-
- def try_run(self, body, headers=None, include_dirs=None, libraries=None,
- library_dirs=None, lang="c"):
- """Try to compile, link to an executable, and run a program
- built from 'body' and 'headers'. Return true on success, false
- otherwise.
- """
- from distutils2.compiler.ccompiler import CompileError, LinkError
- self._check_compiler()
- try:
- src, obj, exe = self._link(body, headers, include_dirs,
- libraries, library_dirs, lang)
- self.spawn([exe])
- ok = 1
- except (CompileError, LinkError, DistutilsExecError):
- ok = 0
-
- log.info(ok and "success!" or "failure.")
- self._clean()
- return ok
-
-
- # -- High-level methods --------------------------------------------
- # (these are the ones that are actually likely to be useful
- # when implementing a real-world config command!)
-
- def check_func(self, func, headers=None, include_dirs=None,
- libraries=None, library_dirs=None, decl=0, call=0):
-
- """Determine if function 'func' is available by constructing a
- source file that refers to 'func', and compiles and links it.
- If everything succeeds, returns true; otherwise returns false.
-
- The constructed source file starts out by including the header
- files listed in 'headers'. If 'decl' is true, it then declares
- 'func' (as "int func()"); you probably shouldn't supply 'headers'
- and set 'decl' true in the same call, or you might get errors about
- a conflicting declarations for 'func'. Finally, the constructed
- 'main()' function either references 'func' or (if 'call' is true)
- calls it. 'libraries' and 'library_dirs' are used when
- linking.
- """
-
- self._check_compiler()
- body = []
- if decl:
- body.append("int %s ();" % func)
- body.append("int main () {")
- if call:
- body.append(" %s();" % func)
- else:
- body.append(" %s;" % func)
- body.append("}")
- body = "\n".join(body) + "\n"
-
- return self.try_link(body, headers, include_dirs,
- libraries, library_dirs)
-
- # check_func ()
-
- def check_lib(self, library, library_dirs=None, headers=None,
- include_dirs=None, other_libraries=[]):
- """Determine if 'library' is available to be linked against,
- without actually checking that any particular symbols are provided
- by it. 'headers' will be used in constructing the source file to
- be compiled, but the only effect of this is to check if all the
- header files listed are available. Any libraries listed in
- 'other_libraries' will be included in the link, in case 'library'
- has symbols that depend on other libraries.
- """
- self._check_compiler()
- return self.try_link("int main (void) { }",
- headers, include_dirs,
- [library]+other_libraries, library_dirs)
-
- def check_header(self, header, include_dirs=None, library_dirs=None,
- lang="c"):
- """Determine if the system header file named by 'header_file'
- exists and can be found by the preprocessor; return true if so,
- false otherwise.
- """
- return self.try_cpp(body="/* No body */", headers=[header],
- include_dirs=include_dirs)
-
-
-def dump_file(filename, head=None):
- """Dumps a file content into log.info.
-
- If head is not None, will be dumped before the file content.
- """
- if head is None:
- log.info('%s' % filename)
- else:
- log.info(head)
- file = open(filename)
- try:
- log.info(file.read())
- finally:
- file.close()
diff --git a/src/distutils2/command/install.py b/src/distutils2/command/install.py
deleted file mode 100644
index 5692a93..0000000
--- a/src/distutils2/command/install.py
+++ /dev/null
@@ -1,626 +0,0 @@
-"""distutils.command.install
-
-Implements the Distutils 'install' command."""
-
-__revision__ = "$Id: install.py 77949 2010-02-03 15:38:12Z tarek.ziade $"
-
-import sys
-import os
-
-from distutils2._backport import sysconfig
-from distutils2._backport.sysconfig import (get_config_vars, get_paths,
- get_path, get_config_var)
-
-from distutils2 import log
-from distutils2.core import Command
-from distutils2.errors import DistutilsPlatformError
-from distutils2.util import write_file
-from distutils2.util import convert_path, change_root, get_platform
-from distutils2.errors import DistutilsOptionError
-
-# compatibility with 2.4 and 2.5
-if sys.version < '2.6':
- HAS_USER_SITE = False
-else:
- HAS_USER_SITE = True
-
-
-class install(Command):
-
- description = "install everything from build directory"
-
- user_options = [
- # Select installation scheme and set base director(y|ies)
- ('prefix=', None,
- "installation prefix"),
- ('exec-prefix=', None,
- "(Unix only) prefix for platform-specific files"),
- ('home=', None,
- "(Unix only) home directory to install under"),
-
- # Or just set the base director(y|ies)
- ('install-base=', None,
- "base installation directory (instead of --prefix or --home)"),
- ('install-platbase=', None,
- "base installation directory for platform-specific files " +
- "(instead of --exec-prefix or --home)"),
- ('root=', None,
- "install everything relative to this alternate root directory"),
-
- # Or explicitly set the installation scheme
- ('install-purelib=', None,
- "installation directory for pure Python module distributions"),
- ('install-platlib=', None,
- "installation directory for non-pure module distributions"),
- ('install-lib=', None,
- "installation directory for all module distributions " +
- "(overrides --install-purelib and --install-platlib)"),
-
- ('install-headers=', None,
- "installation directory for C/C++ headers"),
- ('install-scripts=', None,
- "installation directory for Python scripts"),
- ('install-data=', None,
- "installation directory for data files"),
-
- # Byte-compilation options -- see install_lib.py for details, as
- # these are duplicated from there (but only install_lib does
- # anything with them).
- ('compile', 'c', "compile .py to .pyc [default]"),
- ('no-compile', None, "don't compile .py files"),
- ('optimize=', 'O',
- 'also compile with optimization: -O1 for "python -O", '
- '-O2 for "python -OO", and -O0 to disable [default: -O0]'),
-
- # Miscellaneous control options
- ('force', 'f',
- "force installation (overwrite any existing files)"),
- ('skip-build', None,
- "skip rebuilding everything (for testing/debugging)"),
-
- # Where to install documentation (eventually!)
- #('doc-format=', None, "format of documentation to generate"),
- #('install-man=', None, "directory for Unix man pages"),
- #('install-html=', None, "directory for HTML documentation"),
- #('install-info=', None, "directory for GNU info files"),
-
- # XXX use a name that makes clear this is the old format
- ('record=', None,
- "filename in which to record a list of installed files "
- "(not PEP 376-compliant)"),
-
- # .dist-info related arguments, read by install_dist_info
- ('no-distinfo', None,
- "do not create a .dist-info directory"),
- ('installer=', None,
- "the name of the installer"),
- ('requested', None,
- "generate a REQUESTED file (i.e."),
- ('no-requested', None,
- "do not generate a REQUESTED file"),
- ('no-record', None,
- "do not generate a RECORD file"),
- ]
-
- boolean_options = ['compile', 'force', 'skip-build', 'no-distinfo',
- 'requested', 'no-record']
-
- if HAS_USER_SITE:
- user_options.append(
- ('user', None,
- "install in user site-packages directory [%s]" %
- get_path('purelib', '%s_user' % os.name)))
-
- boolean_options.append('user')
-
- negative_opt = {'no-compile': 'compile', 'no-requested': 'requested'}
-
- def initialize_options(self):
- # High-level options: these select both an installation base
- # and scheme.
- self.prefix = None
- self.exec_prefix = None
- self.home = None
- if HAS_USER_SITE:
- self.user = 0
-
- # These select only the installation base; it's up to the user to
- # specify the installation scheme (currently, that means supplying
- # the --install-{platlib,purelib,scripts,data} options).
- self.install_base = None
- self.install_platbase = None
- self.root = None
-
- # These options are the actual installation directories; if not
- # supplied by the user, they are filled in using the installation
- # scheme implied by prefix/exec-prefix/home and the contents of
- # that installation scheme.
- self.install_purelib = None # for pure module distributions
- self.install_platlib = None # non-pure (dists w/ extensions)
- self.install_headers = None # for C/C++ headers
- self.install_lib = None # set to either purelib or platlib
- self.install_scripts = None
- self.install_data = None
- if HAS_USER_SITE:
- self.install_userbase = get_config_var('userbase')
- self.install_usersite = get_path('purelib', '%s_user' % os.name)
-
- self.compile = None
- self.optimize = None
-
- # These two are for putting non-packagized distributions into their
- # own directory and creating a .pth file if it makes sense.
- # 'extra_path' comes from the setup file; 'install_path_file' can
- # be turned off if it makes no sense to install a .pth file. (But
- # better to install it uselessly than to guess wrong and not
- # install it when it's necessary and would be used!) Currently,
- # 'install_path_file' is always true unless some outsider meddles
- # with it.
- self.extra_path = None
- self.install_path_file = 1
-
- # 'force' forces installation, even if target files are not
- # out-of-date. 'skip_build' skips running the "build" command,
- # handy if you know it's not necessary. 'warn_dir' (which is *not*
- # a user option, it's just there so the bdist_* commands can turn
- # it off) determines whether we warn about installing to a
- # directory not in sys.path.
- self.force = 0
- self.skip_build = 0
- self.warn_dir = 1
-
- # These are only here as a conduit from the 'build' command to the
- # 'install_*' commands that do the real work. ('build_base' isn't
- # actually used anywhere, but it might be useful in future.) They
- # are not user options, because if the user told the install
- # command where the build directory is, that wouldn't affect the
- # build command.
- self.build_base = None
- self.build_lib = None
-
- # Not defined yet because we don't know anything about
- # documentation yet.
- #self.install_man = None
- #self.install_html = None
- #self.install_info = None
-
- self.record = None
-
- # .dist-info related options
- self.no_distinfo = None
- self.installer = None
- self.requested = None
- self.no_record = None
-
- # -- Option finalizing methods -------------------------------------
- # (This is rather more involved than for most commands,
- # because this is where the policy for installing third-
- # party Python modules on various platforms given a wide
- # array of user input is decided. Yes, it's quite complex!)
-
- def finalize_options(self):
- # This method (and its pliant slaves, like 'finalize_unix()',
- # 'finalize_other()', and 'select_scheme()') is where the default
- # installation directories for modules, extension modules, and
- # anything else we care to install from a Python module
- # distribution. Thus, this code makes a pretty important policy
- # statement about how third-party stuff is added to a Python
- # installation! Note that the actual work of installation is done
- # by the relatively simple 'install_*' commands; they just take
- # their orders from the installation directory options determined
- # here.
-
- # Check for errors/inconsistencies in the options; first, stuff
- # that's wrong on any platform.
-
- if ((self.prefix or self.exec_prefix or self.home) and
- (self.install_base or self.install_platbase)):
- raise DistutilsOptionError(
- "must supply either prefix/exec-prefix/home or "
- "install-base/install-platbase -- not both")
-
- if self.home and (self.prefix or self.exec_prefix):
- raise DistutilsOptionError(
- "must supply either home or prefix/exec-prefix -- not both")
-
- if HAS_USER_SITE and self.user and (
- self.prefix or self.exec_prefix or self.home or
- self.install_base or self.install_platbase):
- raise DistutilsOptionError(
- "can't combine user with prefix/exec_prefix/home or "
- "install_base/install_platbase")
-
- # Next, stuff that's wrong (or dubious) only on certain platforms.
- if os.name != "posix":
- if self.exec_prefix:
- self.warn("exec-prefix option ignored on this platform")
- self.exec_prefix = None
-
- # Now the interesting logic -- so interesting that we farm it out
- # to other methods. The goal of these methods is to set the final
- # values for the install_{lib,scripts,data,...} options, using as
- # input a heady brew of prefix, exec_prefix, home, install_base,
- # install_platbase, user-supplied versions of
- # install_{purelib,platlib,lib,scripts,data,...}, and the
- # INSTALL_SCHEME dictionary above. Phew!
-
- self.dump_dirs("pre-finalize_{unix,other}")
-
- if os.name == 'posix':
- self.finalize_unix()
- else:
- self.finalize_other()
-
- self.dump_dirs("post-finalize_{unix,other}()")
-
- # Expand configuration variables, tilde, etc. in self.install_base
- # and self.install_platbase -- that way, we can use $base or
- # $platbase in the other installation directories and not worry
- # about needing recursive variable expansion (shudder).
-
- py_version = sys.version.split()[0]
- prefix, exec_prefix, srcdir, projectbase = get_config_vars(
- 'prefix', 'exec_prefix', 'srcdir', 'projectbase')
-
- metadata = self.distribution.metadata
- self.config_vars = {
- 'dist_name': metadata['Name'],
- 'dist_version': metadata['Version'],
- 'dist_fullname': metadata.get_fullname(),
- 'py_version': py_version,
- 'py_version_short': py_version[:3],
- 'py_version_nodot': py_version[:3:2],
- 'sys_prefix': prefix,
- 'prefix': prefix,
- 'sys_exec_prefix': exec_prefix,
- 'exec_prefix': exec_prefix,
- 'srcdir': srcdir,
- 'projectbase': projectbase,
- }
-
- if HAS_USER_SITE:
- self.config_vars['userbase'] = self.install_userbase
- self.config_vars['usersite'] = self.install_usersite
-
- self.expand_basedirs()
-
- self.dump_dirs("post-expand_basedirs()")
-
- # Now define config vars for the base directories so we can expand
- # everything else.
- self.config_vars['base'] = self.install_base
- self.config_vars['platbase'] = self.install_platbase
-
- # Expand "~" and configuration variables in the installation
- # directories.
- self.expand_dirs()
-
- self.dump_dirs("post-expand_dirs()")
-
- # Create directories in the home dir:
- if HAS_USER_SITE and self.user:
- self.create_home_path()
-
- # Pick the actual directory to install all modules to: either
- # install_purelib or install_platlib, depending on whether this
- # module distribution is pure or not. Of course, if the user
- # already specified install_lib, use their selection.
- if self.install_lib is None:
- if self.distribution.ext_modules: # has extensions: non-pure
- self.install_lib = self.install_platlib
- else:
- self.install_lib = self.install_purelib
-
- # Convert directories from Unix /-separated syntax to the local
- # convention.
- self.convert_paths('lib', 'purelib', 'platlib',
- 'scripts', 'data', 'headers')
- if HAS_USER_SITE:
- self.convert_paths('userbase', 'usersite')
-
- # Well, we're not actually fully completely finalized yet: we still
- # have to deal with 'extra_path', which is the hack for allowing
- # non-packagized module distributions (hello, Numerical Python!) to
- # get their own directories.
- self.handle_extra_path()
- self.install_libbase = self.install_lib # needed for .pth file
- self.install_lib = os.path.join(self.install_lib, self.extra_dirs)
-
- # If a new root directory was supplied, make all the installation
- # dirs relative to it.
- if self.root is not None:
- self.change_roots('libbase', 'lib', 'purelib', 'platlib',
- 'scripts', 'data', 'headers')
-
- self.dump_dirs("after prepending root")
-
- # Find out the build directories, ie. where to install from.
- self.set_undefined_options('build', 'build_base', 'build_lib')
-
- # Punt on doc directories for now -- after all, we're punting on
- # documentation completely!
-
- if self.no_distinfo is None:
- self.no_distinfo = False
-
- def finalize_unix(self):
- """Finalize options for posix platforms."""
- if self.install_base is not None or self.install_platbase is not None:
- if ((self.install_lib is None and
- self.install_purelib is None and
- self.install_platlib is None) or
- self.install_headers is None or
- self.install_scripts is None or
- self.install_data is None):
- raise DistutilsOptionError(
- "install-base or install-platbase supplied, but "
- "installation scheme is incomplete")
- return
-
- if HAS_USER_SITE and self.user:
- if self.install_userbase is None:
- raise DistutilsPlatformError(
- "user base directory is not specified")
- self.install_base = self.install_platbase = self.install_userbase
- self.select_scheme("posix_user")
- elif self.home is not None:
- self.install_base = self.install_platbase = self.home
- self.select_scheme("posix_home")
- else:
- if self.prefix is None:
- if self.exec_prefix is not None:
- raise DistutilsOptionError(
- "must not supply exec-prefix without prefix")
-
- self.prefix = os.path.normpath(sys.prefix)
- self.exec_prefix = os.path.normpath(sys.exec_prefix)
-
- else:
- if self.exec_prefix is None:
- self.exec_prefix = self.prefix
-
- self.install_base = self.prefix
- self.install_platbase = self.exec_prefix
- self.select_scheme("posix_prefix")
-
- def finalize_other(self):
- """Finalize options for non-posix platforms"""
- if HAS_USER_SITE and self.user:
- if self.install_userbase is None:
- raise DistutilsPlatformError(
- "user base directory is not specified")
- self.install_base = self.install_platbase = self.install_userbase
- self.select_scheme(os.name + "_user")
- elif self.home is not None:
- self.install_base = self.install_platbase = self.home
- self.select_scheme("posix_home")
- else:
- if self.prefix is None:
- self.prefix = os.path.normpath(sys.prefix)
-
- self.install_base = self.install_platbase = self.prefix
- try:
- self.select_scheme(os.name)
- except KeyError:
- raise DistutilsPlatformError(
- "no support for installation on '%s'" % os.name)
-
- def dump_dirs(self, msg):
- """Dump the list of user options."""
- log.debug(msg + ":")
- for opt in self.user_options:
- opt_name = opt[0]
- if opt_name[-1] == "=":
- opt_name = opt_name[0:-1]
- if opt_name in self.negative_opt:
- opt_name = self.negative_opt[opt_name]
- opt_name = opt_name.replace('-', '_')
- val = not getattr(self, opt_name)
- else:
- opt_name = opt_name.replace('-', '_')
- val = getattr(self, opt_name)
- log.debug(" %s: %s" % (opt_name, val))
-
- def select_scheme(self, name):
- """Set the install directories by applying the install schemes."""
- # it's the caller's problem if they supply a bad name!
- scheme = get_paths(name, expand=False)
- for key, value in scheme.items():
- if key == 'platinclude':
- key = 'headers'
- value = os.path.join(value, self.distribution.metadata['Name'])
- attrname = 'install_' + key
- if hasattr(self, attrname):
- if getattr(self, attrname) is None:
- setattr(self, attrname, value)
-
- def _expand_attrs(self, attrs):
- for attr in attrs:
- val = getattr(self, attr)
- if val is not None:
- if os.name == 'posix' or os.name == 'nt':
- val = os.path.expanduser(val)
- # see if we want to push this work in sysconfig XXX
- val = sysconfig._subst_vars(val, self.config_vars)
- setattr(self, attr, val)
-
- def expand_basedirs(self):
- """Call `os.path.expanduser` on install_{base,platbase} and root."""
- self._expand_attrs(['install_base', 'install_platbase', 'root'])
-
- def expand_dirs(self):
- """Call `os.path.expanduser` on install dirs."""
- self._expand_attrs(['install_purelib', 'install_platlib',
- 'install_lib', 'install_headers',
- 'install_scripts', 'install_data'])
-
- def convert_paths(self, *names):
- """Call `convert_path` over `names`."""
- for name in names:
- attr = "install_" + name
- setattr(self, attr, convert_path(getattr(self, attr)))
-
- def handle_extra_path(self):
- """Set `path_file` and `extra_dirs` using `extra_path`."""
- if self.extra_path is None:
- self.extra_path = self.distribution.extra_path
-
- if self.extra_path is not None:
- if isinstance(self.extra_path, str):
- self.extra_path = self.extra_path.split(',')
-
- if len(self.extra_path) == 1:
- path_file = extra_dirs = self.extra_path[0]
- elif len(self.extra_path) == 2:
- path_file, extra_dirs = self.extra_path
- else:
- raise DistutilsOptionError(
- "'extra_path' option must be a list, tuple, or "
- "comma-separated string with 1 or 2 elements")
-
- # convert to local form in case Unix notation used (as it
- # should be in setup scripts)
- extra_dirs = convert_path(extra_dirs)
- else:
- path_file = None
- extra_dirs = ''
-
- # XXX should we warn if path_file and not extra_dirs? (in which
- # case the path file would be harmless but pointless)
- self.path_file = path_file
- self.extra_dirs = extra_dirs
-
- def change_roots(self, *names):
- """Change the install direcories pointed by name using root."""
- for name in names:
- attr = "install_" + name
- setattr(self, attr, change_root(self.root, getattr(self, attr)))
-
- def create_home_path(self):
- """Create directories under ~."""
- if HAS_USER_SITE and not self.user:
- return
- home = convert_path(os.path.expanduser("~"))
- for name, path in self.config_vars.iteritems():
- if path.startswith(home) and not os.path.isdir(path):
- os.makedirs(path, 0700)
-
- # -- Command execution methods -------------------------------------
-
- def run(self):
- """Runs the command."""
- # Obviously have to build before we can install
- if not self.skip_build:
- self.run_command('build')
- # If we built for any other platform, we can't install.
- build_plat = self.distribution.get_command_obj('build').plat_name
- # check warn_dir - it is a clue that the 'install' is happening
- # internally, and not to sys.path, so we don't check the platform
- # matches what we are running.
- if self.warn_dir and build_plat != get_platform():
- raise DistutilsPlatformError("Can't install when "
- "cross-compiling")
-
- # Run all sub-commands (at least those that need to be run)
- for cmd_name in self.get_sub_commands():
- self.run_command(cmd_name)
-
- if self.path_file:
- self.create_path_file()
-
- # write list of installed files, if requested.
- if self.record:
- outputs = self.get_outputs()
- if self.root: # strip any package prefix
- root_len = len(self.root)
- for counter in xrange(len(outputs)):
- outputs[counter] = outputs[counter][root_len:]
- self.execute(write_file,
- (self.record, outputs),
- "writing list of installed files to '%s'" %
- self.record)
-
- sys_path = map(os.path.normpath, sys.path)
- sys_path = map(os.path.normcase, sys_path)
- install_lib = os.path.normcase(os.path.normpath(self.install_lib))
- if (self.warn_dir and
- not (self.path_file and self.install_path_file) and
- install_lib not in sys_path):
- log.debug(("modules installed to '%s', which is not in "
- "Python's module search path (sys.path) -- "
- "you'll have to change the search path yourself"),
- self.install_lib)
-
- def create_path_file(self):
- """Creates the .pth file"""
- filename = os.path.join(self.install_libbase,
- self.path_file + ".pth")
- if self.install_path_file:
- self.execute(write_file,
- (filename, [self.extra_dirs]),
- "creating %s" % filename)
- else:
- self.warn("path file '%s' not created" % filename)
-
- # -- Reporting methods ---------------------------------------------
-
- def get_outputs(self):
- """Assembles the outputs of all the sub-commands."""
- outputs = []
- for cmd_name in self.get_sub_commands():
- cmd = self.get_finalized_command(cmd_name)
- # Add the contents of cmd.get_outputs(), ensuring
- # that outputs doesn't contain duplicate entries
- for filename in cmd.get_outputs():
- if filename not in outputs:
- outputs.append(filename)
-
- if self.path_file and self.install_path_file:
- outputs.append(os.path.join(self.install_libbase,
- self.path_file + ".pth"))
-
- return outputs
-
- def get_inputs(self):
- """Returns the inputs of all the sub-commands"""
- # XXX gee, this looks familiar ;-(
- inputs = []
- for cmd_name in self.get_sub_commands():
- cmd = self.get_finalized_command(cmd_name)
- inputs.extend(cmd.get_inputs())
-
- return inputs
-
- # -- Predicates for sub-command list -------------------------------
-
- def has_lib(self):
- """Returns true if the current distribution has any Python
- modules to install."""
- return (self.distribution.has_pure_modules() or
- self.distribution.has_ext_modules())
-
- def has_headers(self):
- """Returns true if the current distribution has any headers to
- install."""
- return self.distribution.has_headers()
-
- def has_scripts(self):
- """Returns true if the current distribution has any scripts to.
- install."""
- return self.distribution.has_scripts()
-
- def has_data(self):
- """Returns true if the current distribution has any data to.
- install."""
- return self.distribution.has_data_files()
-
- # 'sub_commands': a list of commands this command might have to run to
- # get its work done. See cmd.py for more info.
- sub_commands = [('install_lib', has_lib),
- ('install_headers', has_headers),
- ('install_scripts', has_scripts),
- ('install_data', has_data),
- # keep install_distinfo last, as it needs the record
- # with files to be completely generated
- ('install_distinfo', lambda self: not self.no_distinfo),
- ]
diff --git a/src/distutils2/command/install_data.py b/src/distutils2/command/install_data.py
deleted file mode 100644
index 1256a0d..0000000
--- a/src/distutils2/command/install_data.py
+++ /dev/null
@@ -1,94 +0,0 @@
-"""distutils.command.install_data
-
-Implements the Distutils 'install_data' command, for installing
-platform-independent data files."""
-
-# contributed by Bastian Kleineidam
-
-__revision__ = "$Id: install_data.py 76849 2009-12-15 06:29:19Z tarek.ziade $"
-
-import os
-from distutils2.core import Command
-from distutils2.util import change_root, convert_path
-
-class install_data(Command):
-
- description = "install data files"
-
- user_options = [
- ('install-dir=', 'd',
- "base directory for installing data files "
- "(default: installation base dir)"),
- ('root=', None,
- "install everything relative to this alternate root directory"),
- ('force', 'f', "force installation (overwrite existing files)"),
- ]
-
- boolean_options = ['force']
-
- def initialize_options(self):
- self.install_dir = None
- self.outfiles = []
- self.root = None
- self.force = 0
- self.data_files = self.distribution.data_files
- self.warn_dir = 1
-
- def finalize_options(self):
- self.set_undefined_options('install',
- ('install_data', 'install_dir'),
- 'root', 'force')
-
- def run(self):
- self.mkpath(self.install_dir)
- for f in self.data_files:
- if isinstance(f, str):
- # it's a simple file, so copy it
- f = convert_path(f)
- if self.warn_dir:
- self.warn("setup script did not provide a directory for "
- "'%s' -- installing right in '%s'" %
- (f, self.install_dir))
- (out, _) = self.copy_file(f, self.install_dir)
- self.outfiles.append(out)
- else:
- # it's a tuple with path to install to and a list of files
- dir = convert_path(f[0])
- if not os.path.isabs(dir):
- dir = os.path.join(self.install_dir, dir)
- elif self.root:
- dir = change_root(self.root, dir)
- self.mkpath(dir)
-
- if f[1] == []:
- # If there are no files listed, the user must be
- # trying to create an empty directory, so add the
- # directory to the list of output files.
- self.outfiles.append(dir)
- else:
- # Copy files, adding them to the list of output files.
- for data in f[1]:
- data = convert_path(data)
- (out, _) = self.copy_file(data, dir)
- self.outfiles.append(out)
-
- def get_source_files(self):
- sources = []
- for item in self.data_files:
- if isinstance(item, str): # plain file
- item = convert_path(item)
- if os.path.isfile(item):
- sources.append(item)
- else: # a (dirname, filenames) tuple
- dirname, filenames = item
- for f in filenames:
- f = convert_path(f)
- if os.path.isfile(f):
- sources.append(f)
- return sources
-
- def get_inputs(self):
- return self.data_files or []
-
- def get_outputs(self):
- return self.outfiles
diff --git a/src/distutils2/command/install_distinfo.py b/src/distutils2/command/install_distinfo.py
deleted file mode 100644
index 64174dd..0000000
--- a/src/distutils2/command/install_distinfo.py
+++ /dev/null
@@ -1,174 +0,0 @@
-"""
-distutils.command.install_distinfo
-==================================
-
-:Author: Josip Djolonga
-
-This module implements the ``install_distinfo`` command that creates the
-``.dist-info`` directory for the distribution, as specified in :pep:`376`.
-Usually, you do not have to call this command directly, it gets called
-automatically by the ``install`` command.
-"""
-
-# This file was created from the code for the former command install_egg_info
-
-import os
-import csv
-import re
-from distutils2.command.cmd import Command
-from distutils2 import log
-from distutils2._backport.shutil import rmtree
-try:
- import hashlib
-except ImportError:
- from distutils2._backport import hashlib
-
-
-class install_distinfo(Command):
-
- description = 'create a .dist-info directory for the distribution'
-
- user_options = [
- ('distinfo-dir=', None,
- "directory where the the .dist-info directory will be installed"),
- ('installer=', None,
- "the name of the installer"),
- ('requested', None,
- "generate a REQUESTED file"),
- ('no-requested', None,
- "do not generate a REQUESTED file"),
- ('no-record', None,
- "do not generate a RECORD file"),
- ]
-
- boolean_options = ['requested', 'no-record']
-
- negative_opt = {'no-requested': 'requested'}
-
- def initialize_options(self):
- self.distinfo_dir = None
- self.installer = None
- self.requested = None
- self.no_record = None
-
- def finalize_options(self):
- self.set_undefined_options('install',
- 'installer', 'requested', 'no_record')
-
- self.set_undefined_options('install_lib',
- ('install_dir', 'distinfo_dir'))
-
- if self.installer is None:
- # FIXME distutils or distutils2?
- # + document default in the option help text above and in install
- self.installer = 'distutils'
- if self.requested is None:
- self.requested = True
- if self.no_record is None:
- self.no_record = False
-
- metadata = self.distribution.metadata
-
- basename = "%s-%s.dist-info" % (
- to_filename(safe_name(metadata['Name'])),
- to_filename(safe_version(metadata['Version'])),
- )
-
- self.distinfo_dir = os.path.join(self.distinfo_dir, basename)
- self.outputs = []
-
- def run(self):
- # FIXME dry-run should be used at a finer level, so that people get
- # useful logging output and can have an idea of what the command would
- # have done
- if not self.dry_run:
- target = self.distinfo_dir
-
- if os.path.isdir(target) and not os.path.islink(target):
- rmtree(target)
- elif os.path.exists(target):
- self.execute(os.unlink, (self.distinfo_dir,),
- "removing " + target)
-
- self.execute(os.makedirs, (target,), "creating " + target)
-
- metadata_path = os.path.join(self.distinfo_dir, 'METADATA')
- log.info('creating %s', metadata_path)
- self.distribution.metadata.write(metadata_path)
- self.outputs.append(metadata_path)
-
- installer_path = os.path.join(self.distinfo_dir, 'INSTALLER')
- log.info('creating %s', installer_path)
- f = open(installer_path, 'w')
- try:
- f.write(self.installer)
- finally:
- f.close()
- self.outputs.append(installer_path)
-
- if self.requested:
- requested_path = os.path.join(self.distinfo_dir, 'REQUESTED')
- log.info('creating %s', requested_path)
- f = open(requested_path, 'w')
- f.close()
- self.outputs.append(requested_path)
-
- if not self.no_record:
- record_path = os.path.join(self.distinfo_dir, 'RECORD')
- log.info('creating %s', record_path)
- f = open(record_path, 'wb')
- try:
- writer = csv.writer(f, delimiter=',',
- lineterminator=os.linesep,
- quotechar='"')
-
- install = self.get_finalized_command('install')
-
- for fpath in install.get_outputs():
- if fpath.endswith('.pyc') or fpath.endswith('.pyo'):
- # do not put size and md5 hash, as in PEP-376
- writer.writerow((fpath, '', ''))
- else:
- size = os.path.getsize(fpath)
- fd = open(fpath, 'r')
- hash = hashlib.md5()
- hash.update(fd.read())
- md5sum = hash.hexdigest()
- writer.writerow((fpath, md5sum, size))
-
- # add the RECORD file itself
- writer.writerow((record_path, '', ''))
- self.outputs.append(record_path)
- finally:
- f.close()
-
- def get_outputs(self):
- return self.outputs
-
-
-# The following functions are taken from setuptools' pkg_resources module.
-
-def safe_name(name):
- """Convert an arbitrary string to a standard distribution name
-
- Any runs of non-alphanumeric/. characters are replaced with a single '-'.
- """
- return re.sub('[^A-Za-z0-9.]+', '-', name)
-
-
-def safe_version(version):
- """Convert an arbitrary string to a standard version string
-
- Spaces become dots, and all other non-alphanumeric characters become
- dashes, with runs of multiple dashes condensed to a single dash.
- """
- version = version.replace(' ', '.')
- return re.sub('[^A-Za-z0-9.]+', '-', version)
-
-
-def to_filename(name):
- """Convert a project or version name to its filename-escaped form
-
- Any '-' characters are currently replaced with '_'.
- """
- return name.replace('-', '_')
diff --git a/src/distutils2/command/install_headers.py b/src/distutils2/command/install_headers.py
deleted file mode 100644
index dd63128..0000000
--- a/src/distutils2/command/install_headers.py
+++ /dev/null
@@ -1,50 +0,0 @@
-"""distutils.command.install_headers
-
-Implements the Distutils 'install_headers' command, to install C/C++ header
-files to the Python include directory."""
-
-__revision__ = "$Id: install_headers.py 70891 2009-03-31 20:55:21Z tarek.ziade $"
-
-from distutils2.core import Command
-
-
-# XXX force is never used
-class install_headers(Command):
-
- description = "install C/C++ header files"
-
- user_options = [('install-dir=', 'd',
- "directory to install header files to"),
- ('force', 'f',
- "force installation (overwrite existing files)"),
- ]
-
- boolean_options = ['force']
-
- def initialize_options(self):
- self.install_dir = None
- self.force = 0
- self.outfiles = []
-
- def finalize_options(self):
- self.set_undefined_options('install',
- ('install_headers', 'install_dir'),
- 'force')
-
- def run(self):
- headers = self.distribution.headers
- if not headers:
- return
-
- self.mkpath(self.install_dir)
- for header in headers:
- (out, _) = self.copy_file(header, self.install_dir)
- self.outfiles.append(out)
-
- def get_inputs(self):
- return self.distribution.headers or []
-
- def get_outputs(self):
- return self.outfiles
-
-# class install_headers
diff --git a/src/distutils2/command/install_lib.py b/src/distutils2/command/install_lib.py
deleted file mode 100644
index c5e78f7..0000000
--- a/src/distutils2/command/install_lib.py
+++ /dev/null
@@ -1,215 +0,0 @@
-"""distutils.command.install_lib
-
-Implements the Distutils 'install_lib' command
-(install all Python modules)."""
-
-__revision__ = "$Id: install_lib.py 75671 2009-10-24 15:51:30Z tarek.ziade $"
-
-import os
-import sys
-
-from distutils2.core import Command
-from distutils2.errors import DistutilsOptionError
-
-
-# Extension for Python source files.
-if hasattr(os, 'extsep'):
- PYTHON_SOURCE_EXTENSION = os.extsep + "py"
-else:
- PYTHON_SOURCE_EXTENSION = ".py"
-
-class install_lib(Command):
-
- description = "install all Python modules (extensions and pure Python)"
-
- # The byte-compilation options are a tad confusing. Here are the
- # possible scenarios:
- # 1) no compilation at all (--no-compile --no-optimize)
- # 2) compile .pyc only (--compile --no-optimize; default)
- # 3) compile .pyc and "level 1" .pyo (--compile --optimize)
- # 4) compile "level 1" .pyo only (--no-compile --optimize)
- # 5) compile .pyc and "level 2" .pyo (--compile --optimize-more)
- # 6) compile "level 2" .pyo only (--no-compile --optimize-more)
- #
- # The UI for this is two option, 'compile' and 'optimize'.
- # 'compile' is strictly boolean, and only decides whether to
- # generate .pyc files. 'optimize' is three-way (0, 1, or 2), and
- # decides both whether to generate .pyo files and what level of
- # optimization to use.
-
- user_options = [
- ('install-dir=', 'd', "directory to install to"),
- ('build-dir=','b', "build directory (where to install from)"),
- ('force', 'f', "force installation (overwrite existing files)"),
- ('compile', 'c', "compile .py to .pyc [default]"),
- ('no-compile', None, "don't compile .py files"),
- ('optimize=', 'O',
- "also compile with optimization: -O1 for \"python -O\", "
- "-O2 for \"python -OO\", and -O0 to disable [default: -O0]"),
- ('skip-build', None, "skip the build steps"),
- ]
-
- boolean_options = ['force', 'compile', 'skip-build']
- negative_opt = {'no-compile' : 'compile'}
-
- def initialize_options(self):
- # let the 'install' command dictate our installation directory
- self.install_dir = None
- self.build_dir = None
- self.force = 0
- self.compile = None
- self.optimize = None
- self.skip_build = None
-
- def finalize_options(self):
- # Get all the information we need to install pure Python modules
- # from the umbrella 'install' command -- build (source) directory,
- # install (target) directory, and whether to compile .py files.
- self.set_undefined_options('install',
- ('build_lib', 'build_dir'),
- ('install_lib', 'install_dir'),
- 'force', 'compile', 'optimize', 'skip_build')
-
- if self.compile is None:
- self.compile = 1
- if self.optimize is None:
- self.optimize = 0
-
- if not isinstance(self.optimize, int):
- try:
- self.optimize = int(self.optimize)
- if self.optimize not in (0, 1, 2):
- raise AssertionError
- except (ValueError, AssertionError):
- raise DistutilsOptionError, "optimize must be 0, 1, or 2"
-
- def run(self):
- # Make sure we have built everything we need first
- self.build()
-
- # Install everything: simply dump the entire contents of the build
- # directory to the installation directory (that's the beauty of
- # having a build directory!)
- outfiles = self.install()
-
- # (Optionally) compile .py to .pyc
- if outfiles is not None and self.distribution.has_pure_modules():
- self.byte_compile(outfiles)
-
- # -- Top-level worker functions ------------------------------------
- # (called from 'run()')
-
- def build(self):
- if not self.skip_build:
- if self.distribution.has_pure_modules():
- self.run_command('build_py')
- if self.distribution.has_ext_modules():
- self.run_command('build_ext')
-
- def install(self):
- if os.path.isdir(self.build_dir):
- outfiles = self.copy_tree(self.build_dir, self.install_dir)
- else:
- self.warn("'%s' does not exist -- no Python modules to install" %
- self.build_dir)
- return
- return outfiles
-
- def byte_compile(self, files):
- if hasattr(sys, 'dont_write_bytecode') and sys.dont_write_bytecode:
- self.warn('byte-compiling is disabled, skipping.')
- return
-
- from distutils2.util import byte_compile
-
- # Get the "--root" directory supplied to the "install" command,
- # and use it as a prefix to strip off the purported filename
- # encoded in bytecode files. This is far from complete, but it
- # should at least generate usable bytecode in RPM distributions.
- install_root = self.get_finalized_command('install').root
-
- if self.compile:
- byte_compile(files, optimize=0,
- force=self.force, prefix=install_root,
- dry_run=self.dry_run)
- if self.optimize > 0:
- byte_compile(files, optimize=self.optimize,
- force=self.force, prefix=install_root,
- verbose=self.verbose, dry_run=self.dry_run)
-
-
- # -- Utility methods -----------------------------------------------
-
- def _mutate_outputs(self, has_any, build_cmd, cmd_option, output_dir):
- if not has_any:
- return []
-
- build_cmd = self.get_finalized_command(build_cmd)
- build_files = build_cmd.get_outputs()
- build_dir = getattr(build_cmd, cmd_option)
-
- prefix_len = len(build_dir) + len(os.sep)
- outputs = []
- for file in build_files:
- outputs.append(os.path.join(output_dir, file[prefix_len:]))
-
- return outputs
-
- def _bytecode_filenames(self, py_filenames):
- bytecode_files = []
- for py_file in py_filenames:
- # Since build_py handles package data installation, the
- # list of outputs can contain more than just .py files.
- # Make sure we only report bytecode for the .py files.
- ext = os.path.splitext(os.path.normcase(py_file))[1]
- if ext != PYTHON_SOURCE_EXTENSION:
- continue
- if self.compile:
- bytecode_files.append(py_file + "c")
- if self.optimize > 0:
- bytecode_files.append(py_file + "o")
-
- return bytecode_files
-
-
- # -- External interface --------------------------------------------
- # (called by outsiders)
-
- def get_outputs(self):
- """Return the list of files that would be installed if this command
- were actually run. Not affected by the "dry-run" flag or whether
- modules have actually been built yet.
- """
- pure_outputs = \
- self._mutate_outputs(self.distribution.has_pure_modules(),
- 'build_py', 'build_lib',
- self.install_dir)
- if self.compile:
- bytecode_outputs = self._bytecode_filenames(pure_outputs)
- else:
- bytecode_outputs = []
-
- ext_outputs = \
- self._mutate_outputs(self.distribution.has_ext_modules(),
- 'build_ext', 'build_lib',
- self.install_dir)
-
- return pure_outputs + bytecode_outputs + ext_outputs
-
- def get_inputs(self):
- """Get the list of files that are input to this command, ie. the
- files that get installed as they are named in the build tree.
- The files in this list correspond one-to-one to the output
- filenames returned by 'get_outputs()'.
- """
- inputs = []
-
- if self.distribution.has_pure_modules():
- build_py = self.get_finalized_command('build_py')
- inputs.extend(build_py.get_outputs())
-
- if self.distribution.has_ext_modules():
- build_ext = self.get_finalized_command('build_ext')
- inputs.extend(build_ext.get_outputs())
-
- return inputs
diff --git a/src/distutils2/command/install_scripts.py b/src/distutils2/command/install_scripts.py
deleted file mode 100644
index fa7587e..0000000
--- a/src/distutils2/command/install_scripts.py
+++ /dev/null
@@ -1,62 +0,0 @@
-"""distutils.command.install_scripts
-
-Implements the Distutils 'install_scripts' command, for installing
-Python scripts."""
-
-# contributed by Bastian Kleineidam
-
-__revision__ = "$Id: install_scripts.py 68943 2009-01-25 22:09:10Z tarek.ziade $"
-
-import os
-from distutils2.core import Command
-from distutils2 import log
-from stat import ST_MODE
-
-class install_scripts (Command):
-
- description = "install scripts (Python or otherwise)"
-
- user_options = [
- ('install-dir=', 'd', "directory to install scripts to"),
- ('build-dir=','b', "build directory (where to install from)"),
- ('force', 'f', "force installation (overwrite existing files)"),
- ('skip-build', None, "skip the build steps"),
- ]
-
- boolean_options = ['force', 'skip-build']
-
-
- def initialize_options (self):
- self.install_dir = None
- self.force = 0
- self.build_dir = None
- self.skip_build = None
-
- def finalize_options (self):
- self.set_undefined_options('build', ('build_scripts', 'build_dir'))
- self.set_undefined_options('install',
- ('install_scripts', 'install_dir'),
- 'force', 'skip_build')
-
- def run (self):
- if not self.skip_build:
- self.run_command('build_scripts')
- self.outfiles = self.copy_tree(self.build_dir, self.install_dir)
- if os.name == 'posix':
- # Set the executable bits (owner, group, and world) on
- # all the scripts we just installed.
- for file in self.get_outputs():
- if self.dry_run:
- log.info("changing mode of %s", file)
- else:
- mode = ((os.stat(file)[ST_MODE]) | 0555) & 07777
- log.info("changing mode of %s to %o", file, mode)
- os.chmod(file, mode)
-
- def get_inputs (self):
- return self.distribution.scripts or []
-
- def get_outputs(self):
- return self.outfiles or []
-
-# class install_scripts
diff --git a/src/distutils2/command/register.py b/src/distutils2/command/register.py
deleted file mode 100644
index bb97936..0000000
--- a/src/distutils2/command/register.py
+++ /dev/null
@@ -1,298 +0,0 @@
-"""distutils.command.register
-
-Implements the Distutils 'register' command (register with the repository).
-"""
-
-# created 2002/10/21, Richard Jones
-
-__revision__ = "$Id: register.py 77717 2010-01-24 00:33:32Z tarek.ziade $"
-
-import urllib2
-import getpass
-import urlparse
-import StringIO
-from warnings import warn
-
-from distutils2.command.cmd import Command
-from distutils2 import log
-from distutils2.util import (metadata_to_dict, read_pypirc, generate_pypirc,
- DEFAULT_REPOSITORY, DEFAULT_REALM,
- get_pypirc_path)
-
-class register(Command):
-
- description = "register the distribution with the Python package index"
- user_options = [
- ('repository=', 'r',
- "repository URL [default: %s]" % DEFAULT_REPOSITORY),
- ('show-response', None,
- "display full response text from server"),
- ('list-classifiers', None,
- "list valid Trove classifiers"),
- ('strict', None ,
- "stop the registration if the metadata is not fully compliant")
- ]
-
- boolean_options = ['show-response', 'verify', 'list-classifiers',
- 'strict']
-
- def initialize_options(self):
- self.repository = None
- self.realm = None
- self.show_response = 0
- self.list_classifiers = 0
- self.strict = 0
-
- def finalize_options(self):
- if self.repository is None:
- self.repository = DEFAULT_REPOSITORY
- if self.realm is None:
- self.realm = DEFAULT_REALM
- # setting options for the `check` subcommand
- check_options = {'strict': ('register', self.strict),
- 'all': ('register', 1)}
- self.distribution.command_options['check'] = check_options
-
- def run(self):
- self.finalize_options()
- self._set_config()
-
- # Check the package metadata
- self.run_command('check')
-
- if self.dry_run:
- self.verify_metadata()
- elif self.list_classifiers:
- self.classifiers()
- else:
- self.send_metadata()
-
- def check_metadata(self):
- """Deprecated API."""
- warn("distutils.command.register.check_metadata is deprecated, \
- use the check command instead", PendingDeprecationWarning)
- check = self.distribution.get_command_obj('check')
- check.ensure_finalized()
- check.strict = self.strict
- check.all = 1
- check.run()
-
- def _set_config(self):
- ''' Reads the configuration file and set attributes.
- '''
- config = read_pypirc(self.repository, self.realm)
- if config != {}:
- self.username = config['username']
- self.password = config['password']
- self.repository = config['repository']
- self.realm = config['realm']
- self.has_config = True
- else:
- if self.repository not in ('pypi', DEFAULT_REPOSITORY):
- raise ValueError('%s not found in .pypirc' % self.repository)
- if self.repository == 'pypi':
- self.repository = DEFAULT_REPOSITORY
- self.has_config = False
-
- def classifiers(self):
- ''' Fetch the list of classifiers from the server.
- '''
- response = urllib2.urlopen(self.repository+'?:action=list_classifiers')
- log.info(response.read())
-
- def verify_metadata(self):
- ''' Send the metadata to the package index server to be checked.
- '''
- # send the info to the server and report the result
- (code, result) = self.post_to_server(self.build_post_data('verify'))
- log.info('Server response (%s): %s' % (code, result))
-
-
- def send_metadata(self):
- ''' Send the metadata to the package index server.
-
- Well, do the following:
- 1. figure who the user is, and then
- 2. send the data as a Basic auth'ed POST.
-
- First we try to read the username/password from $HOME/.pypirc,
- which is a ConfigParser-formatted file with a section
- [distutils] containing username and password entries (both
- in clear text). Eg:
-
- [distutils]
- index-servers =
- pypi
-
- [pypi]
- username: fred
- password: sekrit
-
- Otherwise, to figure who the user is, we offer the user three
- choices:
-
- 1. use existing login,
- 2. register as a new user, or
- 3. set the password to a random string and email the user.
-
- '''
- # see if we can short-cut and get the username/password from the
- # config
- if self.has_config:
- choice = '1'
- username = self.username
- password = self.password
- else:
- choice = 'x'
- username = password = ''
-
- # get the user's login info
- choices = '1 2 3 4'.split()
- while choice not in choices:
- self.announce('''\
-We need to know who you are, so please choose either:
- 1. use your existing login,
- 2. register as a new user,
- 3. have the server generate a new password for you (and email it to you), or
- 4. quit
-Your selection [default 1]: ''', log.INFO)
-
- choice = raw_input()
- if not choice:
- choice = '1'
- elif choice not in choices:
- print 'Please choose one of the four options!'
-
- if choice == '1':
- # get the username and password
- while not username:
- username = raw_input('Username: ')
- while not password:
- password = getpass.getpass('Password: ')
-
- # set up the authentication
- auth = urllib2.HTTPPasswordMgr()
- host = urlparse.urlparse(self.repository)[1]
- auth.add_password(self.realm, host, username, password)
- # send the info to the server and report the result
- code, result = self.post_to_server(self.build_post_data('submit'),
- auth)
- self.announce('Server response (%s): %s' % (code, result),
- log.INFO)
-
- # possibly save the login
- if code == 200:
- if self.has_config:
- # sharing the password in the distribution instance
- # so the upload command can reuse it
- self.distribution.password = password
- else:
- self.announce(('I can store your PyPI login so future '
- 'submissions will be faster.'), log.INFO)
- self.announce('(the login will be stored in %s)' % \
- get_pypirc_path(), log.INFO)
- choice = 'X'
- while choice.lower() not in 'yn':
- choice = raw_input('Save your login (y/N)?')
- if not choice:
- choice = 'n'
- if choice.lower() == 'y':
- generate_pypirc(username, password)
-
- elif choice == '2':
- data = {':action': 'user'}
- data['name'] = data['password'] = data['email'] = ''
- data['confirm'] = None
- while not data['name']:
- data['name'] = raw_input('Username: ')
- while data['password'] != data['confirm']:
- while not data['password']:
- data['password'] = getpass.getpass('Password: ')
- while not data['confirm']:
- data['confirm'] = getpass.getpass(' Confirm: ')
- if data['password'] != data['confirm']:
- data['password'] = ''
- data['confirm'] = None
- print "Password and confirm don't match!"
- while not data['email']:
- data['email'] = raw_input(' EMail: ')
- code, result = self.post_to_server(data)
- if code != 200:
- log.info('Server response (%s): %s' % (code, result))
- else:
- log.info('You will receive an email shortly.')
- log.info(('Follow the instructions in it to '
- 'complete registration.'))
- elif choice == '3':
- data = {':action': 'password_reset'}
- data['email'] = ''
- while not data['email']:
- data['email'] = raw_input('Your email address: ')
- code, result = self.post_to_server(data)
- log.info('Server response (%s): %s' % (code, result))
-
- def build_post_data(self, action):
- # figure the data to send - the metadata plus some additional
- # information used by the package server
- data = metadata_to_dict(self.distribution.metadata)
- data[':action'] = action
- return data
-
- # XXX to be refactored with upload.upload_file
- def post_to_server(self, data, auth=None):
- ''' Post a query to the server, and return a string response.
- '''
- if 'name' in data:
- self.announce('Registering %s to %s' % (data['name'],
- self.repository),
- log.INFO)
- # Build up the MIME payload for the urllib2 POST data
- boundary = '--------------GHSKFJDLGDS7543FJKLFHRE75642756743254'
- sep_boundary = '\n--' + boundary
- end_boundary = sep_boundary + '--'
- body = StringIO.StringIO()
- for key, value in data.items():
- # handle multiple entries for the same name
- if not isinstance(value, (tuple, list)):
- value = [value]
-
- for value in value:
- body.write(sep_boundary)
- body.write('\nContent-Disposition: form-data; name="%s"'%key)
- body.write("\n\n")
- body.write(value)
- if value and value[-1] == '\r':
- body.write('\n') # write an extra newline (lurve Macs)
- body.write(end_boundary)
- body.write("\n")
- body = body.getvalue()
-
- # build the Request
- headers = {
- 'Content-type': 'multipart/form-data; boundary=%s; charset=utf-8'%boundary,
- 'Content-length': str(len(body))
- }
- req = urllib2.Request(self.repository, body, headers)
-
- # handle HTTP and include the Basic Auth handler
- opener = urllib2.build_opener(
- urllib2.HTTPBasicAuthHandler(password_mgr=auth)
- )
- data = ''
- try:
- result = opener.open(req)
- except urllib2.HTTPError, e:
- if self.show_response:
- data = e.fp.read()
- result = e.code, e.msg
- except urllib2.URLError, e:
- result = 500, str(e)
- else:
- if self.show_response:
- data = result.read()
- result = 200, 'OK'
- if self.show_response:
- dashes = '-' * 75
- self.announce('%s%s%s' % (dashes, data, dashes))
-
- return result
diff --git a/src/distutils2/command/sdist.py b/src/distutils2/command/sdist.py
deleted file mode 100644
index 4e7764c..0000000
--- a/src/distutils2/command/sdist.py
+++ /dev/null
@@ -1,360 +0,0 @@
-"""distutils.command.sdist
-
-Implements the Distutils 'sdist' command (create a source distribution)."""
-
-__revision__ = "$Id: sdist.py 76956 2009-12-21 01:22:46Z tarek.ziade $"
-
-import os
-import string
-import sys
-from glob import glob
-from warnings import warn
-from shutil import rmtree
-import re
-
-try:
- from shutil import get_archive_formats
-except ImportError:
- from distutils2._backport.shutil import get_archive_formats
-
-from distutils2.core import Command
-from distutils2.errors import (DistutilsPlatformError, DistutilsOptionError,
- DistutilsTemplateError)
-from distutils2.manifest import Manifest
-from distutils2 import log
-from distutils2.util import convert_path
-
-def show_formats():
- """Print all possible values for the 'formats' option (used by
- the "--help-formats" command-line option).
- """
- from distutils2.fancy_getopt import FancyGetopt
- formats = []
- for name, desc in get_archive_formats():
- formats.append(("formats=" + name, None, desc))
- formats.sort()
- FancyGetopt(formats).print_help(
- "List of available source distribution formats:")
-
-# a \ followed by some spaces + EOL
-_COLLAPSE_PATTERN = re.compile('\\\w\n', re.M)
-_COMMENTED_LINE = re.compile('^#.*\n$|^\w*\n$', re.M)
-
-class sdist(Command):
-
- description = "create a source distribution (tarball, zip file, etc.)"
-
- user_options = [
- ('template=', 't',
- "name of manifest template file [default: MANIFEST.in]"),
- ('manifest=', 'm',
- "name of manifest file [default: MANIFEST]"),
- ('use-defaults', None,
- "include the default file set in the manifest "
- "[default; disable with --no-defaults]"),
- ('no-defaults', None,
- "don't include the default file set"),
- ('prune', None,
- "specifically exclude files/directories that should not be "
- "distributed (build tree, RCS/CVS dirs, etc.) "
- "[default; disable with --no-prune]"),
- ('no-prune', None,
- "don't automatically exclude anything"),
- ('manifest-only', 'o',
- "just regenerate the manifest and then stop "),
- ('formats=', None,
- "formats for source distribution (comma-separated list)"),
- ('keep-temp', 'k',
- "keep the distribution tree around after creating " +
- "archive file(s)"),
- ('dist-dir=', 'd',
- "directory to put the source distribution archive(s) in "
- "[default: dist]"),
- ('check-metadata', None,
- "Ensure that all required elements of metadata "
- "are supplied. Warn if any missing. [default]"),
- ('owner=', 'u',
- "Owner name used when creating a tar file [default: current user]"),
- ('group=', 'g',
- "Group name used when creating a tar file [default: current group]"),
- ]
-
- boolean_options = ['use-defaults', 'prune',
- 'manifest-only', 'keep-temp', 'check-metadata']
-
- help_options = [
- ('help-formats', None,
- "list available distribution formats", show_formats),
- ]
-
- negative_opt = {'no-defaults': 'use-defaults',
- 'no-prune': 'prune' }
-
- default_format = {'posix': 'gztar',
- 'nt': 'zip' }
-
- def initialize_options(self):
- # 'template' and 'manifest' are, respectively, the names of
- # the manifest template and manifest file.
- self.template = None
- self.manifest = None
-
- # 'use_defaults': if true, we will include the default file set
- # in the manifest
- self.use_defaults = 1
- self.prune = 1
- self.manifest_only = 0
- self.formats = None
- self.keep_temp = 0
- self.dist_dir = None
-
- self.archive_files = None
- self.metadata_check = 1
- self.owner = None
- self.group = None
- self.filelist = None
-
- def _check_archive_formats(self, formats):
- supported_formats = [name for name, desc in get_archive_formats()]
- for format in formats:
- if format not in supported_formats:
- return format
- return None
-
- def finalize_options(self):
- if self.manifest is None:
- self.manifest = "MANIFEST"
- if self.template is None:
- self.template = "MANIFEST.in"
-
- self.ensure_string_list('formats')
- if self.formats is None:
- try:
- self.formats = [self.default_format[os.name]]
- except KeyError:
- raise DistutilsPlatformError, \
- "don't know how to create source distributions " + \
- "on platform %s" % os.name
-
- bad_format = self._check_archive_formats(self.formats)
- if bad_format:
- raise DistutilsOptionError, \
- "unknown archive format '%s'" % bad_format
-
- if self.dist_dir is None:
- self.dist_dir = "dist"
-
- if self.filelist is None:
- self.filelist = Manifest()
-
-
- def run(self):
- # 'filelist' contains the list of files that will make up the
- # manifest
- self.filelist.clear()
-
- # Check the package metadata
- if self.metadata_check:
- self.run_command('check')
-
- # Do whatever it takes to get the list of files to process
- # (process the manifest template, read an existing manifest,
- # whatever). File list is accumulated in 'self.filelist'.
- self.get_file_list()
-
- # If user just wanted us to regenerate the manifest, stop now.
- if self.manifest_only:
- return
-
- # Otherwise, go ahead and create the source distribution tarball,
- # or zipfile, or whatever.
- self.make_distribution()
-
- def get_file_list(self):
- """Figure out the list of files to include in the source
- distribution, and put it in 'self.filelist'. This might involve
- reading the manifest template (and writing the manifest), or just
- reading the manifest, or just using the default file set -- it all
- depends on the user's options.
- """
- template_exists = os.path.isfile(self.template)
- if not template_exists:
- self.warn(("manifest template '%s' does not exist " +
- "(using default file list)") %
- self.template)
-
- self.filelist.findall()
-
- if self.use_defaults:
- self.add_defaults()
- if template_exists:
- self.filelist.read_template(self.template)
- if self.prune:
- self.prune_file_list()
-
- self.filelist.write(self.manifest)
-
- def add_defaults(self):
- """Add all the default files to self.filelist:
- - README or README.txt
- - setup.py
- - test/test*.py
- - all pure Python modules mentioned in setup script
- - all files pointed by package_data (build_py)
- - all files defined in data_files.
- - all files defined as scripts.
- - all C sources listed as part of extensions or C libraries
- in the setup script (doesn't catch C headers!)
- Warns if (README or README.txt) or setup.py are missing; everything
- else is optional.
- """
-
- standards = [('README', 'README.txt'), self.distribution.script_name]
- for fn in standards:
- if isinstance(fn, tuple):
- alts = fn
- got_it = 0
- for fn in alts:
- if os.path.exists(fn):
- got_it = 1
- self.filelist.append(fn)
- break
-
- if not got_it:
- self.warn("standard file not found: should have one of " +
- string.join(alts, ', '))
- else:
- if os.path.exists(fn):
- self.filelist.append(fn)
- else:
- self.warn("standard file '%s' not found" % fn)
-
- optional = ['test/test*.py', 'setup.cfg']
- for pattern in optional:
- files = filter(os.path.isfile, glob(pattern))
- if files:
- self.filelist.extend(files)
-
- for cmd_name in self.distribution.get_command_names():
- cmd_obj = self.get_finalized_command(cmd_name)
- self.filelist.extend(cmd_obj.get_source_files())
-
- def prune_file_list(self):
- """Prune off branches that might slip into the file list as created
- by 'read_template()', but really don't belong there:
- * the build tree (typically "build")
- * the release tree itself (only an issue if we ran "sdist"
- previously with --keep-temp, or it aborted)
- * any RCS, CVS, .svn, .hg, .git, .bzr, _darcs directories
- """
- build = self.get_finalized_command('build')
- base_dir = self.distribution.get_fullname()
-
- self.filelist.exclude_pattern(None, prefix=build.build_base)
- self.filelist.exclude_pattern(None, prefix=base_dir)
-
- # pruning out vcs directories
- # both separators are used under win32
- if sys.platform == 'win32':
- seps = r'/|\\'
- else:
- seps = '/'
-
- vcs_dirs = ['RCS', 'CVS', r'\.svn', r'\.hg', r'\.git', r'\.bzr',
- '_darcs']
- vcs_ptrn = r'(^|%s)(%s)(%s).*' % (seps, '|'.join(vcs_dirs), seps)
- self.filelist.exclude_pattern(vcs_ptrn, is_regex=1)
-
-
- def make_release_tree(self, base_dir, files):
- """Create the directory tree that will become the source
- distribution archive. All directories implied by the filenames in
- 'files' are created under 'base_dir', and then we hard link or copy
- (if hard linking is unavailable) those files into place.
- Essentially, this duplicates the developer's source tree, but in a
- directory named after the distribution, containing only the files
- to be distributed.
- """
- # Create all the directories under 'base_dir' necessary to
- # put 'files' there; the 'mkpath()' is just so we don't die
- # if the manifest happens to be empty.
- self.mkpath(base_dir)
- self.create_tree(base_dir, files, dry_run=self.dry_run)
-
- # And walk over the list of files, either making a hard link (if
- # os.link exists) to each one that doesn't already exist in its
- # corresponding location under 'base_dir', or copying each file
- # that's out-of-date in 'base_dir'. (Usually, all files will be
- # out-of-date, because by default we blow away 'base_dir' when
- # we're done making the distribution archives.)
-
- if hasattr(os, 'link'): # can make hard links on this system
- link = 'hard'
- msg = "making hard links in %s..." % base_dir
- else: # nope, have to copy
- link = None
- msg = "copying files to %s..." % base_dir
-
- if not files:
- log.warn("no files to distribute -- empty manifest?")
- else:
- log.info(msg)
- for file in files:
- if not os.path.isfile(file):
- log.warn("'%s' not a regular file -- skipping" % file)
- else:
- dest = os.path.join(base_dir, file)
- self.copy_file(file, dest, link=link)
-
- self.distribution.metadata.write(os.path.join(base_dir, 'PKG-INFO'))
-
- def make_distribution(self):
- """Create the source distribution(s). First, we create the release
- tree with 'make_release_tree()'; then, we create all required
- archive files (according to 'self.formats') from the release tree.
- Finally, we clean up by blowing away the release tree (unless
- 'self.keep_temp' is true). The list of archive files created is
- stored so it can be retrieved later by 'get_archive_files()'.
- """
- # Don't warn about missing metadata here -- should be (and is!)
- # done elsewhere.
- base_dir = self.distribution.get_fullname()
- base_name = os.path.join(self.dist_dir, base_dir)
-
- self.make_release_tree(base_dir, self.filelist.files)
- archive_files = [] # remember names of files we create
- # tar archive must be created last to avoid overwrite and remove
- if 'tar' in self.formats:
- self.formats.append(self.formats.pop(self.formats.index('tar')))
-
- for fmt in self.formats:
- file = self.make_archive(base_name, fmt, base_dir=base_dir,
- owner=self.owner, group=self.group)
- archive_files.append(file)
- self.distribution.dist_files.append(('sdist', '', file))
-
- self.archive_files = archive_files
-
- if not self.keep_temp:
- if self.dry_run:
- log.info('Removing %s' % base_dir)
- else:
- rmtree(base_dir)
-
- def get_archive_files(self):
- """Return the list of archive files created when the command
- was run, or None if the command hasn't run yet.
- """
- return self.archive_files
-
- def create_tree(self, base_dir, files, mode=0777, verbose=1, dry_run=0):
- need_dir = {}
- for file in files:
- need_dir[os.path.join(base_dir, os.path.dirname(file))] = 1
- need_dirs = need_dir.keys()
- need_dirs.sort()
-
- # Now create them
- for dir in need_dirs:
- self.mkpath(dir, mode, verbose=verbose, dry_run=dry_run)
-
diff --git a/src/distutils2/command/test.py b/src/distutils2/command/test.py
deleted file mode 100644
index d64ebd3..0000000
--- a/src/distutils2/command/test.py
+++ /dev/null
@@ -1,75 +0,0 @@
-import os
-import sys
-import unittest
-
-from distutils2.core import Command
-from distutils2.errors import DistutilsOptionError
-from distutils2.util import resolve_name
-
-try:
- from pkgutil import get_distribution
-except ImportError:
- from distutils2._backport.pkgutil import get_distribution
-
-
-class test(Command):
-
- description = "run the distribution's test suite"
-
- user_options = [
- ('suite=', 's',
- "test suite to run (for example: 'some_module.test_suite')"),
- ('runner=', None,
- "test runner to be called."),
- ('tests-require=', None,
- "list of distributions required to run the test suite."),
- ]
-
- def initialize_options(self):
- self.suite = None
- self.runner = None
- self.tests_require = []
-
- def finalize_options(self):
- self.build_lib = self.get_finalized_command("build").build_lib
- for requirement in self.tests_require:
- if get_distribution(requirement) is None:
- self.announce("test dependency %s is not installed, "
- "tests may fail" % requirement)
- if (not self.suite and not self.runner and
- self.get_ut_with_discovery() is None):
- raise DistutilsOptionError(
- "no test discovery available, please give a 'suite' or "
- "'runner' option or install unittest2")
-
- def get_ut_with_discovery(self):
- if hasattr(unittest.TestLoader, "discover"):
- return unittest
- else:
- try:
- import unittest2
- return unittest2
- except ImportError:
- return None
-
- def run(self):
- prev_syspath = sys.path[:]
- try:
- # build release
- build = self.get_reinitialized_command('build')
- self.run_command('build')
- sys.path.insert(0, build.build_lib)
-
- # run the tests
- if self.runner:
- resolve_name(self.runner)()
- elif self.suite:
- runner = unittest.TextTestRunner(verbosity=self.verbose + 1)
- runner.run(resolve_name(self.suite)())
- elif self.get_ut_with_discovery():
- ut = self.get_ut_with_discovery()
- test_suite = ut.TestLoader().discover(os.curdir)
- runner = ut.TextTestRunner(verbosity=self.verbose + 1)
- runner.run(test_suite)
- finally:
- sys.path[:] = prev_syspath
diff --git a/src/distutils2/command/upload.py b/src/distutils2/command/upload.py
deleted file mode 100644
index 3fdb5b3..0000000
--- a/src/distutils2/command/upload.py
+++ /dev/null
@@ -1,207 +0,0 @@
-"""distutils.command.upload
-
-Implements the Distutils 'upload' subcommand (upload package to PyPI)."""
-import os
-import socket
-import platform
-from urllib2 import urlopen, Request, HTTPError
-from base64 import standard_b64encode
-import urlparse
-try:
- from cStringIO import StringIO
-except ImportError:
- from StringIO import StringIO
-try:
- from hashlib import md5
-except ImportError:
- from distutils2._backport.hashlib import md5
-
-from distutils2.errors import DistutilsOptionError
-from distutils2.util import spawn
-from distutils2 import log
-from distutils2.command.cmd import Command
-from distutils2 import log
-from distutils2.util import (metadata_to_dict, read_pypirc,
- DEFAULT_REPOSITORY, DEFAULT_REALM)
-
-
-class upload(Command):
-
- description = "upload distribution to PyPI"
-
- user_options = [
- ('repository=', 'r',
- "repository URL [default: %s]" % DEFAULT_REPOSITORY),
- ('show-response', None,
- "display full response text from server"),
- ('sign', 's',
- "sign files to upload using gpg"),
- ('identity=', 'i',
- "GPG identity used to sign files"),
- ('upload-docs', None,
- "upload documentation too"),
- ]
-
- boolean_options = ['show-response', 'sign']
-
- def initialize_options(self):
- self.repository = None
- self.realm = None
- self.show_response = 0
- self.username = ''
- self.password = ''
- self.show_response = 0
- self.sign = False
- self.identity = None
- self.upload_docs = False
-
- def finalize_options(self):
- if self.repository is None:
- self.repository = DEFAULT_REPOSITORY
- if self.realm is None:
- self.realm = DEFAULT_REALM
- if self.identity and not self.sign:
- raise DistutilsOptionError(
- "Must use --sign for --identity to have meaning"
- )
- config = read_pypirc(self.repository, self.realm)
- if config != {}:
- self.username = config['username']
- self.password = config['password']
- self.repository = config['repository']
- self.realm = config['realm']
-
- # getting the password from the distribution
- # if previously set by the register command
- if not self.password and self.distribution.password:
- self.password = self.distribution.password
-
- def run(self):
- if not self.distribution.dist_files:
- raise DistutilsOptionError("No dist file created in earlier command")
- for command, pyversion, filename in self.distribution.dist_files:
- self.upload_file(command, pyversion, filename)
- if self.upload_docs:
- upload_docs = self.get_finalized_command("upload_docs")
- upload_docs.repository = self.repository
- upload_docs.username = self.username
- upload_docs.password = self.password
- upload_docs.run()
-
- # XXX to be refactored with register.post_to_server
- def upload_file(self, command, pyversion, filename):
- # Makes sure the repository URL is compliant
- schema, netloc, url, params, query, fragments = \
- urlparse.urlparse(self.repository)
- if params or query or fragments:
- raise AssertionError("Incompatible url %s" % self.repository)
-
- if schema not in ('http', 'https'):
- raise AssertionError("unsupported schema " + schema)
-
- # Sign if requested
- if self.sign:
- gpg_args = ["gpg", "--detach-sign", "-a", filename]
- if self.identity:
- gpg_args[2:2] = ["--local-user", self.identity]
- spawn(gpg_args,
- dry_run=self.dry_run)
-
- # Fill in the data - send all the metadata in case we need to
- # register a new release
- content = open(filename,'rb').read()
-
- data = metadata_to_dict(self.distribution.metadata)
-
- # extra upload infos
- data[':action'] = 'file_upload'
- data['protcol_version'] = '1'
- data['content'] = [os.path.basename(filename), content]
- data['filetype'] = command
- data['pyversion'] = pyversion
- data['md5_digest'] = md5(content).hexdigest()
-
- comment = ''
- if command == 'bdist_dumb':
- comment = 'built for %s' % platform.platform(terse=1)
- data['comment'] = comment
-
- if self.sign:
- data['gpg_signature'] = [(os.path.basename(filename) + ".asc",
- open(filename+".asc").read())]
-
- # set up the authentication
- auth = "Basic " + standard_b64encode(self.username + ":" +
- self.password)
-
- # Build up the MIME payload for the POST data
- boundary = '--------------GHSKFJDLGDS7543FJKLFHRE75642756743254'
- sep_boundary = '\n--' + boundary
- end_boundary = sep_boundary + '--'
- body = StringIO()
- file_fields = ('content', 'gpg_signature')
-
- for key, values in data.items():
- # handle multiple entries for the same name
- if not isinstance(values, (tuple, list)):
- values = [values]
-
- content_dispo = 'Content-Disposition: form-data; name="%s"' % key
-
- if key in file_fields:
- filename_, content = values
- filename_ = ';filename="%s"' % filename_
- body.write(sep_boundary)
- body.write("\n")
- body.write(content_dispo)
- body.write(filename_)
- body.write("\n\n")
- body.write(content)
- else:
- for value in values:
- body.write(sep_boundary)
- body.write("\n")
- body.write(content_dispo)
- body.write("\n\n")
- body.write(value)
- if value and value[-1] == '\r':
- # write an extra newline (lurve Macs)
- body.write('\n')
-
- body.write(end_boundary)
- body.write("\n")
- body = body.getvalue()
-
- self.announce("Submitting %s to %s" % (filename, self.repository),
- log.INFO)
-
- # build the Request
- headers = {'Content-type':
- 'multipart/form-data; boundary=%s' % boundary,
- 'Content-length': str(len(body)),
- 'Authorization': auth}
-
- request = Request(self.repository, data=body,
- headers=headers)
- # send the data
- try:
- result = urlopen(request)
- status = result.code
- reason = result.msg
- except socket.error, e:
- self.announce(str(e), log.ERROR)
- return
- except HTTPError, e:
- status = e.code
- reason = e.msg
-
- if status == 200:
- self.announce('Server response (%s): %s' % (status, reason),
- log.INFO)
- else:
- self.announce('Upload failed (%s): %s' % (status, reason),
- log.ERROR)
-
- if self.show_response:
- msg = '\n'.join(('-' * 75, result.read(), '-' * 75))
- self.announce(msg, log.INFO)
diff --git a/src/distutils2/command/upload_docs.py b/src/distutils2/command/upload_docs.py
deleted file mode 100644
index d53dd03..0000000
--- a/src/distutils2/command/upload_docs.py
+++ /dev/null
@@ -1,156 +0,0 @@
-import os
-import base64
-import httplib
-import socket
-import urlparse
-import zipfile
-try:
- from cStringIO import StringIO
-except ImportError:
- from StringIO import StringIO
-
-from distutils2 import log
-from distutils2.command.upload import upload
-from distutils2.command.cmd import Command
-from distutils2.errors import DistutilsFileError
-from distutils2.util import read_pypirc, DEFAULT_REPOSITORY, DEFAULT_REALM
-
-def zip_dir(directory):
- """Compresses recursively contents of directory into a StringIO object"""
- destination = StringIO()
- zip_file = zipfile.ZipFile(destination, "w")
- for root, dirs, files in os.walk(directory):
- for name in files:
- full = os.path.join(root, name)
- relative = root[len(directory):].lstrip(os.path.sep)
- dest = os.path.join(relative, name)
- zip_file.write(full, dest)
- zip_file.close()
- return destination
-
-# grabbed from
-# http://code.activestate.com/recipes/146306-http-client-to-post-using-multipartform-data/
-def encode_multipart(fields, files, boundary=None):
- """
- fields is a sequence of (name, value) elements for regular form fields.
- files is a sequence of (name, filename, value) elements for data to be uploaded as files
- Return (content_type, body) ready for httplib.HTTP instance
- """
- if boundary is None:
- boundary = '--------------GHSKFJDLGDS7543FJKLFHRE75642756743254'
- l = []
- for (key, value) in fields:
- l.extend([
- '--' + boundary,
- 'Content-Disposition: form-data; name="%s"' % key,
- '',
- value])
- for (key, filename, value) in files:
- l.extend([
- '--' + boundary,
- 'Content-Disposition: form-data; name="%s"; filename="%s"' % (key, filename),
- '',
- value])
- l.append('--' + boundary + '--')
- l.append('')
- body = '\r\n'.join(l)
- content_type = 'multipart/form-data; boundary=%s' % boundary
- return content_type, body
-
-class upload_docs(Command):
-
- user_options = [
- ('repository=', 'r',
- "repository URL [default: %s]" % DEFAULT_REPOSITORY),
- ('show-response', None,
- "display full response text from server"),
- ('upload-dir=', None,
- "directory to upload"),
- ]
-
- def initialize_options(self):
- self.repository = None
- self.realm = None
- self.show_response = 0
- self.upload_dir = None
- self.username = ''
- self.password = ''
-
- def finalize_options(self):
- if self.repository is None:
- self.repository = DEFAULT_REPOSITORY
- if self.realm is None:
- self.realm = DEFAULT_REALM
- if self.upload_dir is None:
- build = self.get_finalized_command('build')
- self.upload_dir = os.path.join(build.build_base, "docs")
- self.announce('Using upload directory %s' % self.upload_dir)
- self.verify_upload_dir(self.upload_dir)
- config = read_pypirc(self.repository, self.realm)
- if config != {}:
- self.username = config['username']
- self.password = config['password']
- self.repository = config['repository']
- self.realm = config['realm']
-
- def verify_upload_dir(self, upload_dir):
- self.ensure_dirname('upload_dir')
- index_location = os.path.join(upload_dir, "index.html")
- if not os.path.exists(index_location):
- mesg = "No 'index.html found in docs directory (%s)"
- raise DistutilsFileError(mesg % upload_dir)
-
- def run(self):
- name = self.distribution.metadata['Name']
- version = self.distribution.metadata['Version']
- zip_file = zip_dir(self.upload_dir)
-
- fields = [(':action', 'doc_upload'), ('name', name), ('version', version)]
- files = [('content', name, zip_file.getvalue())]
- content_type, body = encode_multipart(fields, files)
-
- credentials = self.username + ':' + self.password
- auth = "Basic " + base64.encodestring(credentials).strip()
-
- self.announce("Submitting documentation to %s" % (self.repository),
- log.INFO)
-
- schema, netloc, url, params, query, fragments = \
- urlparse.urlparse(self.repository)
- if schema == "http":
- conn = httplib.HTTPConnection(netloc)
- elif schema == "https":
- conn = httplib.HTTPSConnection(netloc)
- else:
- raise AssertionError("unsupported schema "+schema)
-
- try:
- conn.connect()
- conn.putrequest("POST", url)
- conn.putheader('Content-type', content_type)
- conn.putheader('Content-length', str(len(body)))
- conn.putheader('Authorization', auth)
- conn.endheaders()
- conn.send(body)
- except socket.error, e:
- self.announce(str(e), log.ERROR)
- return
-
- r = conn.getresponse()
-
- if r.status == 200:
- self.announce('Server response (%s): %s' % (r.status, r.reason),
- log.INFO)
- elif r.status == 301:
- location = r.getheader('Location')
- if location is None:
- location = 'http://packages.python.org/%s/' % name
- self.announce('Upload successful. Visit %s' % location,
- log.INFO)
- else:
- self.announce('Upload failed (%s): %s' % (r.status, r.reason),
- log.ERROR)
-
- if self.show_response:
- msg = '\n'.join(('-' * 75, r.read(), '-' * 75))
- self.announce(msg, log.INFO)
diff --git a/src/distutils2/command/wininst-6.0.exe b/src/distutils2/command/wininst-6.0.exe
deleted file mode 100644
index f57c855..0000000
--- a/src/distutils2/command/wininst-6.0.exe
+++ /dev/null
Binary files differ
diff --git a/src/distutils2/command/wininst-7.1.exe b/src/distutils2/command/wininst-7.1.exe
deleted file mode 100644
index 1433bc1..0000000
--- a/src/distutils2/command/wininst-7.1.exe
+++ /dev/null
Binary files differ
diff --git a/src/distutils2/command/wininst-8.0.exe b/src/distutils2/command/wininst-8.0.exe
deleted file mode 100644
index 7403bfa..0000000
--- a/src/distutils2/command/wininst-8.0.exe
+++ /dev/null
Binary files differ
diff --git a/src/distutils2/command/wininst-9.0-amd64.exe b/src/distutils2/command/wininst-9.0-amd64.exe
deleted file mode 100644
index 11d8011..0000000
--- a/src/distutils2/command/wininst-9.0-amd64.exe
+++ /dev/null
Binary files differ
diff --git a/src/distutils2/command/wininst-9.0.exe b/src/distutils2/command/wininst-9.0.exe
deleted file mode 100644
index dadb31d..0000000
--- a/src/distutils2/command/wininst-9.0.exe
+++ /dev/null
Binary files differ
diff --git a/src/distutils2/compat.py b/src/distutils2/compat.py
deleted file mode 100644
index 86c733a..0000000
--- a/src/distutils2/compat.py
+++ /dev/null
@@ -1,64 +0,0 @@
-""" distutils2.compat
-
-Used to provide classes, variables and imports which can be used to
-support distutils2 across versions(2.x and 3.x)
-"""
-
-import logging
-
-
-try:
- from distutils2.util import Mixin2to3 as _Mixin2to3
- from distutils2 import run_2to3_on_doctests
- from lib2to3.refactor import get_fixers_from_package
- _CONVERT = True
- _KLASS = _Mixin2to3
-except ImportError:
- _CONVERT = False
- _KLASS = object
-
-# marking public APIs
-__all__ = ['Mixin2to3']
-
-class Mixin2to3(_KLASS):
- """ The base class which can be used for refactoring. When run under
- Python 3.0, the run_2to3 method provided by Mixin2to3 is overridden.
- When run on Python 2.x, it merely creates a class which overrides run_2to3,
- yet does nothing in particular with it.
- """
- if _CONVERT:
- def _run_2to3(self, files, doctests=[], fixers=[]):
- """ Takes a list of files and doctests, and performs conversion
- on those.
- - First, the files which contain the code(`files`) are converted.
- - Second, the doctests in `files` are converted.
- - Thirdly, the doctests in `doctests` are converted.
- """
- # if additional fixers are present, use them
- if fixers:
- self.fixer_names = fixers
-
- # Convert the ".py" files.
- logging.info("Converting Python code")
- _KLASS.run_2to3(self, files)
-
- # Convert the doctests in the ".py" files.
- logging.info("Converting doctests with '.py' files")
- _KLASS.run_2to3(self, files, doctests_only=True)
-
- # If the following conditions are met, then convert:-
- # 1. User has specified the 'convert_2to3_doctests' option. So, we
- # can expect that the list 'doctests' is not empty.
- # 2. The default is allow distutils2 to allow conversion of text files
- # containing doctests. It is set as
- # distutils2.run_2to3_on_doctests
-
- if doctests != [] and run_2to3_on_doctests:
- logging.info("Converting text files which contain doctests")
- _KLASS.run_2to3(self, doctests, doctests_only=True)
- else:
- # If run on Python 2.x, there is nothing to do.
- def _run_2to3(self, files, doctests=[], fixers=[]):
- pass
-
-
diff --git a/src/distutils2/compiler/__init__.py b/src/distutils2/compiler/__init__.py
deleted file mode 100644
index 139597f..0000000
--- a/src/distutils2/compiler/__init__.py
+++ /dev/null
@@ -1,2 +0,0 @@
-
-
diff --git a/src/distutils2/compiler/bcppcompiler.py b/src/distutils2/compiler/bcppcompiler.py
deleted file mode 100644
index 71100df..0000000
--- a/src/distutils2/compiler/bcppcompiler.py
+++ /dev/null
@@ -1,394 +0,0 @@
-"""distutils.bcppcompiler
-
-Contains BorlandCCompiler, an implementation of the abstract CCompiler class
-for the Borland C++ compiler.
-"""
-
-# This implementation by Lyle Johnson, based on the original msvccompiler.py
-# module and using the directions originally published by Gordon Williams.
-
-# XXX looks like there's a LOT of overlap between these two classes:
-# someone should sit down and factor out the common code as
-# WindowsCCompiler! --GPW
-
-__revision__ = "$Id: bcppcompiler.py 76956 2009-12-21 01:22:46Z tarek.ziade $"
-
-import os
-
-from distutils2.errors import (DistutilsExecError, CompileError, LibError,
- LinkError, UnknownFileError)
-from distutils2.compiler.ccompiler import CCompiler, gen_preprocess_options
-from distutils2.file_util import write_file
-from distutils2.dep_util import newer
-from distutils2 import log
-
-class BCPPCompiler(CCompiler) :
- """Concrete class that implements an interface to the Borland C/C++
- compiler, as defined by the CCompiler abstract class.
- """
-
- compiler_type = 'bcpp'
-
- # Just set this so CCompiler's constructor doesn't barf. We currently
- # don't use the 'set_executables()' bureaucracy provided by CCompiler,
- # as it really isn't necessary for this sort of single-compiler class.
- # Would be nice to have a consistent interface with UnixCCompiler,
- # though, so it's worth thinking about.
- executables = {}
-
- # Private class data (need to distinguish C from C++ source for compiler)
- _c_extensions = ['.c']
- _cpp_extensions = ['.cc', '.cpp', '.cxx']
-
- # Needed for the filename generation methods provided by the
- # base class, CCompiler.
- src_extensions = _c_extensions + _cpp_extensions
- obj_extension = '.obj'
- static_lib_extension = '.lib'
- shared_lib_extension = '.dll'
- static_lib_format = shared_lib_format = '%s%s'
- exe_extension = '.exe'
-
-
- def __init__ (self,
- verbose=0,
- dry_run=0,
- force=0):
-
- CCompiler.__init__ (self, verbose, dry_run, force)
-
- # These executables are assumed to all be in the path.
- # Borland doesn't seem to use any special registry settings to
- # indicate their installation locations.
-
- self.cc = "bcc32.exe"
- self.linker = "ilink32.exe"
- self.lib = "tlib.exe"
-
- self.preprocess_options = None
- self.compile_options = ['/tWM', '/O2', '/q', '/g0']
- self.compile_options_debug = ['/tWM', '/Od', '/q', '/g0']
-
- self.ldflags_shared = ['/Tpd', '/Gn', '/q', '/x']
- self.ldflags_shared_debug = ['/Tpd', '/Gn', '/q', '/x']
- self.ldflags_static = []
- self.ldflags_exe = ['/Gn', '/q', '/x']
- self.ldflags_exe_debug = ['/Gn', '/q', '/x','/r']
-
-
- # -- Worker methods ------------------------------------------------
-
- def compile(self, sources,
- output_dir=None, macros=None, include_dirs=None, debug=0,
- extra_preargs=None, extra_postargs=None, depends=None):
-
- macros, objects, extra_postargs, pp_opts, build = \
- self._setup_compile(output_dir, macros, include_dirs, sources,
- depends, extra_postargs)
- compile_opts = extra_preargs or []
- compile_opts.append ('-c')
- if debug:
- compile_opts.extend (self.compile_options_debug)
- else:
- compile_opts.extend (self.compile_options)
-
- for obj in objects:
- try:
- src, ext = build[obj]
- except KeyError:
- continue
- # XXX why do the normpath here?
- src = os.path.normpath(src)
- obj = os.path.normpath(obj)
- # XXX _setup_compile() did a mkpath() too but before the normpath.
- # Is it possible to skip the normpath?
- self.mkpath(os.path.dirname(obj))
-
- if ext == '.res':
- # This is already a binary file -- skip it.
- continue # the 'for' loop
- if ext == '.rc':
- # This needs to be compiled to a .res file -- do it now.
- try:
- self.spawn (["brcc32", "-fo", obj, src])
- except DistutilsExecError, msg:
- raise CompileError, msg
- continue # the 'for' loop
-
- # The next two are both for the real compiler.
- if ext in self._c_extensions:
- input_opt = ""
- elif ext in self._cpp_extensions:
- input_opt = "-P"
- else:
- # Unknown file type -- no extra options. The compiler
- # will probably fail, but let it just in case this is a
- # file the compiler recognizes even if we don't.
- input_opt = ""
-
- output_opt = "-o" + obj
-
- # Compiler command line syntax is: "bcc32 [options] file(s)".
- # Note that the source file names must appear at the end of
- # the command line.
- try:
- self.spawn ([self.cc] + compile_opts + pp_opts +
- [input_opt, output_opt] +
- extra_postargs + [src])
- except DistutilsExecError, msg:
- raise CompileError, msg
-
- return objects
-
- # compile ()
-
-
- def create_static_lib (self,
- objects,
- output_libname,
- output_dir=None,
- debug=0,
- target_lang=None):
-
- (objects, output_dir) = self._fix_object_args (objects, output_dir)
- output_filename = \
- self.library_filename (output_libname, output_dir=output_dir)
-
- if self._need_link (objects, output_filename):
- lib_args = [output_filename, '/u'] + objects
- if debug:
- pass # XXX what goes here?
- try:
- self.spawn ([self.lib] + lib_args)
- except DistutilsExecError, msg:
- raise LibError, msg
- else:
- log.debug("skipping %s (up-to-date)", output_filename)
-
- # create_static_lib ()
-
-
- def link (self,
- target_desc,
- objects,
- output_filename,
- output_dir=None,
- libraries=None,
- library_dirs=None,
- runtime_library_dirs=None,
- export_symbols=None,
- debug=0,
- extra_preargs=None,
- extra_postargs=None,
- build_temp=None,
- target_lang=None):
-
- # XXX this ignores 'build_temp'! should follow the lead of
- # msvccompiler.py
-
- (objects, output_dir) = self._fix_object_args (objects, output_dir)
- (libraries, library_dirs, runtime_library_dirs) = \
- self._fix_lib_args (libraries, library_dirs, runtime_library_dirs)
-
- if runtime_library_dirs:
- log.warn("I don't know what to do with 'runtime_library_dirs': %s",
- str(runtime_library_dirs))
-
- if output_dir is not None:
- output_filename = os.path.join (output_dir, output_filename)
-
- if self._need_link (objects, output_filename):
-
- # Figure out linker args based on type of target.
- if target_desc == CCompiler.EXECUTABLE:
- startup_obj = 'c0w32'
- if debug:
- ld_args = self.ldflags_exe_debug[:]
- else:
- ld_args = self.ldflags_exe[:]
- else:
- startup_obj = 'c0d32'
- if debug:
- ld_args = self.ldflags_shared_debug[:]
- else:
- ld_args = self.ldflags_shared[:]
-
-
- # Create a temporary exports file for use by the linker
- if export_symbols is None:
- def_file = ''
- else:
- head, tail = os.path.split (output_filename)
- modname, ext = os.path.splitext (tail)
- temp_dir = os.path.dirname(objects[0]) # preserve tree structure
- def_file = os.path.join (temp_dir, '%s.def' % modname)
- contents = ['EXPORTS']
- for sym in (export_symbols or []):
- contents.append(' %s=_%s' % (sym, sym))
- self.execute(write_file, (def_file, contents),
- "writing %s" % def_file)
-
- # Borland C++ has problems with '/' in paths
- objects2 = map(os.path.normpath, objects)
- # split objects in .obj and .res files
- # Borland C++ needs them at different positions in the command line
- objects = [startup_obj]
- resources = []
- for file in objects2:
- (base, ext) = os.path.splitext(os.path.normcase(file))
- if ext == '.res':
- resources.append(file)
- else:
- objects.append(file)
-
-
- for l in library_dirs:
- ld_args.append("/L%s" % os.path.normpath(l))
- ld_args.append("/L.") # we sometimes use relative paths
-
- # list of object files
- ld_args.extend(objects)
-
- # XXX the command line syntax for Borland C++ is a bit wonky;
- # certain filenames are jammed together in one big string, but
- # comma-delimited. This doesn't mesh too well with the
- # Unix-centric attitude (with a DOS/Windows quoting hack) of
- # 'spawn()', so constructing the argument list is a bit
- # awkward. Note that doing the obvious thing and jamming all
- # the filenames and commas into one argument would be wrong,
- # because 'spawn()' would quote any filenames with spaces in
- # them. Arghghh!. Apparently it works fine as coded...
-
- # name of dll/exe file
- ld_args.extend([',',output_filename])
- # no map file and start libraries
- ld_args.append(',,')
-
- for lib in libraries:
- # see if we find it and if there is a bcpp specific lib
- # (xxx_bcpp.lib)
- libfile = self.find_library_file(library_dirs, lib, debug)
- if libfile is None:
- ld_args.append(lib)
- # probably a BCPP internal library -- don't warn
- else:
- # full name which prefers bcpp_xxx.lib over xxx.lib
- ld_args.append(libfile)
-
- # some default libraries
- ld_args.append ('import32')
- ld_args.append ('cw32mt')
-
- # def file for export symbols
- ld_args.extend([',',def_file])
- # add resource files
- ld_args.append(',')
- ld_args.extend(resources)
-
-
- if extra_preargs:
- ld_args[:0] = extra_preargs
- if extra_postargs:
- ld_args.extend(extra_postargs)
-
- self.mkpath (os.path.dirname (output_filename))
- try:
- self.spawn ([self.linker] + ld_args)
- except DistutilsExecError, msg:
- raise LinkError, msg
-
- else:
- log.debug("skipping %s (up-to-date)", output_filename)
-
- # link ()
-
- # -- Miscellaneous methods -----------------------------------------
-
-
- def find_library_file (self, dirs, lib, debug=0):
- # List of effective library names to try, in order of preference:
- # xxx_bcpp.lib is better than xxx.lib
- # and xxx_d.lib is better than xxx.lib if debug is set
- #
- # The "_bcpp" suffix is to handle a Python installation for people
- # with multiple compilers (primarily Distutils hackers, I suspect
- # ;-). The idea is they'd have one static library for each
- # compiler they care about, since (almost?) every Windows compiler
- # seems to have a different format for static libraries.
- if debug:
- dlib = (lib + "_d")
- try_names = (dlib + "_bcpp", lib + "_bcpp", dlib, lib)
- else:
- try_names = (lib + "_bcpp", lib)
-
- for dir in dirs:
- for name in try_names:
- libfile = os.path.join(dir, self.library_filename(name))
- if os.path.exists(libfile):
- return libfile
- else:
- # Oops, didn't find it in *any* of 'dirs'
- return None
-
- # overwrite the one from CCompiler to support rc and res-files
- def object_filenames (self,
- source_filenames,
- strip_dir=0,
- output_dir=''):
- if output_dir is None: output_dir = ''
- obj_names = []
- for src_name in source_filenames:
- # use normcase to make sure '.rc' is really '.rc' and not '.RC'
- (base, ext) = os.path.splitext (os.path.normcase(src_name))
- if ext not in (self.src_extensions + ['.rc','.res']):
- raise UnknownFileError, \
- "unknown file type '%s' (from '%s')" % \
- (ext, src_name)
- if strip_dir:
- base = os.path.basename (base)
- if ext == '.res':
- # these can go unchanged
- obj_names.append (os.path.join (output_dir, base + ext))
- elif ext == '.rc':
- # these need to be compiled to .res-files
- obj_names.append (os.path.join (output_dir, base + '.res'))
- else:
- obj_names.append (os.path.join (output_dir,
- base + self.obj_extension))
- return obj_names
-
- # object_filenames ()
-
- def preprocess (self,
- source,
- output_file=None,
- macros=None,
- include_dirs=None,
- extra_preargs=None,
- extra_postargs=None):
-
- (_, macros, include_dirs) = \
- self._fix_compile_args(None, macros, include_dirs)
- pp_opts = gen_preprocess_options(macros, include_dirs)
- pp_args = ['cpp32.exe'] + pp_opts
- if output_file is not None:
- pp_args.append('-o' + output_file)
- if extra_preargs:
- pp_args[:0] = extra_preargs
- if extra_postargs:
- pp_args.extend(extra_postargs)
- pp_args.append(source)
-
- # We need to preprocess: either we're being forced to, or the
- # source file is newer than the target (or the target doesn't
- # exist).
- if self.force or output_file is None or newer(source, output_file):
- if output_file:
- self.mkpath(os.path.dirname(output_file))
- try:
- self.spawn(pp_args)
- except DistutilsExecError, msg:
- print msg
- raise CompileError, msg
-
- # preprocess()
diff --git a/src/distutils2/compiler/ccompiler.py b/src/distutils2/compiler/ccompiler.py
deleted file mode 100644
index 3a8d8dd..0000000
--- a/src/distutils2/compiler/ccompiler.py
+++ /dev/null
@@ -1,1158 +0,0 @@
-"""distutils.ccompiler
-
-Contains CCompiler, an abstract base class that defines the interface
-for the Distutils compiler abstraction model."""
-
-__revision__ = "$Id: ccompiler.py 77704 2010-01-23 09:23:15Z tarek.ziade $"
-
-import sys
-import os
-import re
-
-from distutils2.errors import (CompileError, LinkError, UnknownFileError,
- DistutilsPlatformError, DistutilsModuleError)
-from distutils2.util import split_quoted, execute, newer_group, spawn
-from distutils2 import log
-from shutil import move
-
-try:
- import sysconfig
-except ImportError:
- from distutils2._backport import sysconfig
-
-def customize_compiler(compiler):
- """Do any platform-specific customization of a CCompiler instance.
-
- Mainly needed on Unix, so we can plug in the information that
- varies across Unices and is stored in Python's Makefile.
- """
- if compiler.compiler_type == "unix":
- (cc, cxx, opt, cflags, ccshared, ldshared, so_ext, ar, ar_flags) = \
- sysconfig.get_config_vars('CC', 'CXX', 'OPT', 'CFLAGS',
- 'CCSHARED', 'LDSHARED', 'SO', 'AR',
- 'ARFLAGS')
-
- if 'CC' in os.environ:
- cc = os.environ['CC']
- if 'CXX' in os.environ:
- cxx = os.environ['CXX']
- if 'LDSHARED' in os.environ:
- ldshared = os.environ['LDSHARED']
- if 'CPP' in os.environ:
- cpp = os.environ['CPP']
- else:
- cpp = cc + " -E" # not always
- if 'LDFLAGS' in os.environ:
- ldshared = ldshared + ' ' + os.environ['LDFLAGS']
- if 'CFLAGS' in os.environ:
- cflags = opt + ' ' + os.environ['CFLAGS']
- ldshared = ldshared + ' ' + os.environ['CFLAGS']
- if 'CPPFLAGS' in os.environ:
- cpp = cpp + ' ' + os.environ['CPPFLAGS']
- cflags = cflags + ' ' + os.environ['CPPFLAGS']
- ldshared = ldshared + ' ' + os.environ['CPPFLAGS']
- if 'AR' in os.environ:
- ar = os.environ['AR']
- if 'ARFLAGS' in os.environ:
- archiver = ar + ' ' + os.environ['ARFLAGS']
- else:
- if ar_flags is not None:
- archiver = ar + ' ' + ar_flags
- else:
- # see if its the proper default value
- # mmm I don't want to backport the makefile
- archiver = ar + ' rc'
-
- cc_cmd = cc + ' ' + cflags
- compiler.set_executables(
- preprocessor=cpp,
- compiler=cc_cmd,
- compiler_so=cc_cmd + ' ' + ccshared,
- compiler_cxx=cxx,
- linker_so=ldshared,
- linker_exe=cc,
- archiver=archiver)
-
- compiler.shared_lib_extension = so_ext
-
-class CCompiler(object):
- """Abstract base class to define the interface that must be implemented
- by real compiler classes. Also has some utility methods used by
- several compiler classes.
-
- The basic idea behind a compiler abstraction class is that each
- instance can be used for all the compile/link steps in building a
- single project. Thus, attributes common to all of those compile and
- link steps -- include directories, macros to define, libraries to link
- against, etc. -- are attributes of the compiler instance. To allow for
- variability in how individual files are treated, most of those
- attributes may be varied on a per-compilation or per-link basis.
- """
-
- # 'compiler_type' is a class attribute that identifies this class. It
- # keeps code that wants to know what kind of compiler it's dealing with
- # from having to import all possible compiler classes just to do an
- # 'isinstance'. In concrete CCompiler subclasses, 'compiler_type'
- # should really, really be one of the keys of the 'compiler_class'
- # dictionary (see below -- used by the 'new_compiler()' factory
- # function) -- authors of new compiler interface classes are
- # responsible for updating 'compiler_class'!
- compiler_type = None
-
- # XXX things not handled by this compiler abstraction model:
- # * client can't provide additional options for a compiler,
- # e.g. warning, optimization, debugging flags. Perhaps this
- # should be the domain of concrete compiler abstraction classes
- # (UnixCCompiler, MSVCCompiler, etc.) -- or perhaps the base
- # class should have methods for the common ones.
- # * can't completely override the include or library searchg
- # path, ie. no "cc -I -Idir1 -Idir2" or "cc -L -Ldir1 -Ldir2".
- # I'm not sure how widely supported this is even by Unix
- # compilers, much less on other platforms. And I'm even less
- # sure how useful it is; maybe for cross-compiling, but
- # support for that is a ways off. (And anyways, cross
- # compilers probably have a dedicated binary with the
- # right paths compiled in. I hope.)
- # * can't do really freaky things with the library list/library
- # dirs, e.g. "-Ldir1 -lfoo -Ldir2 -lfoo" to link against
- # different versions of libfoo.a in different locations. I
- # think this is useless without the ability to null out the
- # library search path anyways.
-
-
- # Subclasses that rely on the standard filename generation methods
- # implemented below should override these; see the comment near
- # those methods ('object_filenames()' et. al.) for details:
- src_extensions = None # list of strings
- obj_extension = None # string
- static_lib_extension = None
- shared_lib_extension = None # string
- static_lib_format = None # format string
- shared_lib_format = None # prob. same as static_lib_format
- exe_extension = None # string
-
- # Default language settings. language_map is used to detect a source
- # file or Extension target language, checking source filenames.
- # language_order is used to detect the language precedence, when deciding
- # what language to use when mixing source types. For example, if some
- # extension has two files with ".c" extension, and one with ".cpp", it
- # is still linked as c++.
- language_map = {".c" : "c",
- ".cc" : "c++",
- ".cpp" : "c++",
- ".cxx" : "c++",
- ".m" : "objc",
- }
- language_order = ["c++", "objc", "c"]
-
- def __init__ (self, verbose=0, dry_run=0, force=0):
- self.dry_run = dry_run
- self.force = force
- self.verbose = verbose
-
- # 'output_dir': a common output directory for object, library,
- # shared object, and shared library files
- self.output_dir = None
-
- # 'macros': a list of macro definitions (or undefinitions). A
- # macro definition is a 2-tuple (name, value), where the value is
- # either a string or None (no explicit value). A macro
- # undefinition is a 1-tuple (name,).
- self.macros = []
-
- # 'include_dirs': a list of directories to search for include files
- self.include_dirs = []
-
- # 'libraries': a list of libraries to include in any link
- # (library names, not filenames: eg. "foo" not "libfoo.a")
- self.libraries = []
-
- # 'library_dirs': a list of directories to search for libraries
- self.library_dirs = []
-
- # 'runtime_library_dirs': a list of directories to search for
- # shared libraries/objects at runtime
- self.runtime_library_dirs = []
-
- # 'objects': a list of object files (or similar, such as explicitly
- # named library files) to include on any link
- self.objects = []
-
- for key in self.executables.keys():
- self.set_executable(key, self.executables[key])
-
- def set_executables(self, **args):
- """Define the executables (and options for them) that will be run
- to perform the various stages of compilation. The exact set of
- executables that may be specified here depends on the compiler
- class (via the 'executables' class attribute), but most will have:
- compiler the C/C++ compiler
- linker_so linker used to create shared objects and libraries
- linker_exe linker used to create binary executables
- archiver static library creator
-
- On platforms with a command line (Unix, DOS/Windows), each of these
- is a string that will be split into executable name and (optional)
- list of arguments. (Splitting the string is done similarly to how
- Unix shells operate: words are delimited by spaces, but quotes and
- backslashes can override this. See
- 'distutils.util.split_quoted()'.)
- """
-
- # Note that some CCompiler implementation classes will define class
- # attributes 'cpp', 'cc', etc. with hard-coded executable names;
- # this is appropriate when a compiler class is for exactly one
- # compiler/OS combination (eg. MSVCCompiler). Other compiler
- # classes (UnixCCompiler, in particular) are driven by information
- # discovered at run-time, since there are many different ways to do
- # basically the same things with Unix C compilers.
-
- for key in args.keys():
- if key not in self.executables:
- raise ValueError, \
- "unknown executable '%s' for class %s" % \
- (key, self.__class__.__name__)
- self.set_executable(key, args[key])
-
- def set_executable(self, key, value):
- if isinstance(value, str):
- setattr(self, key, split_quoted(value))
- else:
- setattr(self, key, value)
-
- def _find_macro(self, name):
- i = 0
- for defn in self.macros:
- if defn[0] == name:
- return i
- i = i + 1
- return None
-
- def _check_macro_definitions(self, definitions):
- """Ensures that every element of 'definitions' is a valid macro
- definition, ie. either (name,value) 2-tuple or a (name,) tuple. Do
- nothing if all definitions are OK, raise TypeError otherwise.
- """
- for defn in definitions:
- if not (isinstance(defn, tuple) and
- (len (defn) == 1 or
- (len (defn) == 2 and
- (isinstance(defn[1], str) or defn[1] is None))) and
- isinstance(defn[0], str)):
- raise TypeError, \
- ("invalid macro definition '%s': " % defn) + \
- "must be tuple (string,), (string, string), or " + \
- "(string, None)"
-
-
- # -- Bookkeeping methods -------------------------------------------
-
- def define_macro(self, name, value=None):
- """Define a preprocessor macro for all compilations driven by this
- compiler object. The optional parameter 'value' should be a
- string; if it is not supplied, then the macro will be defined
- without an explicit value and the exact outcome depends on the
- compiler used (XXX true? does ANSI say anything about this?)
- """
- # Delete from the list of macro definitions/undefinitions if
- # already there (so that this one will take precedence).
- i = self._find_macro (name)
- if i is not None:
- del self.macros[i]
-
- defn = (name, value)
- self.macros.append (defn)
-
- def undefine_macro(self, name):
- """Undefine a preprocessor macro for all compilations driven by
- this compiler object. If the same macro is defined by
- 'define_macro()' and undefined by 'undefine_macro()' the last call
- takes precedence (including multiple redefinitions or
- undefinitions). If the macro is redefined/undefined on a
- per-compilation basis (ie. in the call to 'compile()'), then that
- takes precedence.
- """
- # Delete from the list of macro definitions/undefinitions if
- # already there (so that this one will take precedence).
- i = self._find_macro (name)
- if i is not None:
- del self.macros[i]
-
- undefn = (name,)
- self.macros.append (undefn)
-
- def add_include_dir(self, dir):
- """Add 'dir' to the list of directories that will be searched for
- header files. The compiler is instructed to search directories in
- the order in which they are supplied by successive calls to
- 'add_include_dir()'.
- """
- self.include_dirs.append (dir)
-
- def set_include_dirs(self, dirs):
- """Set the list of directories that will be searched to 'dirs' (a
- list of strings). Overrides any preceding calls to
- 'add_include_dir()'; subsequence calls to 'add_include_dir()' add
- to the list passed to 'set_include_dirs()'. This does not affect
- any list of standard include directories that the compiler may
- search by default.
- """
- self.include_dirs = dirs[:]
-
- def add_library(self, libname):
- """Add 'libname' to the list of libraries that will be included in
- all links driven by this compiler object. Note that 'libname'
- should *not* be the name of a file containing a library, but the
- name of the library itself: the actual filename will be inferred by
- the linker, the compiler, or the compiler class (depending on the
- platform).
-
- The linker will be instructed to link against libraries in the
- order they were supplied to 'add_library()' and/or
- 'set_libraries()'. It is perfectly valid to duplicate library
- names; the linker will be instructed to link against libraries as
- many times as they are mentioned.
- """
- self.libraries.append (libname)
-
- def set_libraries(self, libnames):
- """Set the list of libraries to be included in all links driven by
- this compiler object to 'libnames' (a list of strings). This does
- not affect any standard system libraries that the linker may
- include by default.
- """
- self.libraries = libnames[:]
-
-
- def add_library_dir(self, dir):
- """Add 'dir' to the list of directories that will be searched for
- libraries specified to 'add_library()' and 'set_libraries()'. The
- linker will be instructed to search for libraries in the order they
- are supplied to 'add_library_dir()' and/or 'set_library_dirs()'.
- """
- self.library_dirs.append(dir)
-
- def set_library_dirs(self, dirs):
- """Set the list of library search directories to 'dirs' (a list of
- strings). This does not affect any standard library search path
- that the linker may search by default.
- """
- self.library_dirs = dirs[:]
-
- def add_runtime_library_dir(self, dir):
- """Add 'dir' to the list of directories that will be searched for
- shared libraries at runtime.
- """
- self.runtime_library_dirs.append(dir)
-
- def set_runtime_library_dirs(self, dirs):
- """Set the list of directories to search for shared libraries at
- runtime to 'dirs' (a list of strings). This does not affect any
- standard search path that the runtime linker may search by
- default.
- """
- self.runtime_library_dirs = dirs[:]
-
- def add_link_object(self, object):
- """Add 'object' to the list of object files (or analogues, such as
- explicitly named library files or the output of "resource
- compilers") to be included in every link driven by this compiler
- object.
- """
- self.objects.append(object)
-
- def set_link_objects(self, objects):
- """Set the list of object files (or analogues) to be included in
- every link to 'objects'. This does not affect any standard object
- files that the linker may include by default (such as system
- libraries).
- """
- self.objects = objects[:]
-
-
- # -- Private utility methods --------------------------------------
- # (here for the convenience of subclasses)
-
- # Helper method to prep compiler in subclass compile() methods
-
- def _setup_compile(self, outdir, macros, incdirs, sources, depends,
- extra):
- """Process arguments and decide which source files to compile."""
- if outdir is None:
- outdir = self.output_dir
- elif not isinstance(outdir, str):
- raise TypeError, "'output_dir' must be a string or None"
-
- if macros is None:
- macros = self.macros
- elif isinstance(macros, list):
- macros = macros + (self.macros or [])
- else:
- raise TypeError, "'macros' (if supplied) must be a list of tuples"
-
- if incdirs is None:
- incdirs = self.include_dirs
- elif isinstance(incdirs, (list, tuple)):
- incdirs = list(incdirs) + (self.include_dirs or [])
- else:
- raise TypeError, \
- "'include_dirs' (if supplied) must be a list of strings"
-
- if extra is None:
- extra = []
-
- # Get the list of expected output (object) files
- objects = self.object_filenames(sources,
- strip_dir=0,
- output_dir=outdir)
- assert len(objects) == len(sources)
-
- pp_opts = gen_preprocess_options(macros, incdirs)
-
- build = {}
- for i in range(len(sources)):
- src = sources[i]
- obj = objects[i]
- ext = os.path.splitext(src)[1]
- self.mkpath(os.path.dirname(obj))
- build[obj] = (src, ext)
-
- return macros, objects, extra, pp_opts, build
-
- def _get_cc_args(self, pp_opts, debug, before):
- # works for unixccompiler, emxccompiler, cygwinccompiler
- cc_args = pp_opts + ['-c']
- if debug:
- cc_args[:0] = ['-g']
- if before:
- cc_args[:0] = before
- return cc_args
-
- def _fix_compile_args(self, output_dir, macros, include_dirs):
- """Typecheck and fix-up some of the arguments to the 'compile()'
- method, and return fixed-up values. Specifically: if 'output_dir'
- is None, replaces it with 'self.output_dir'; ensures that 'macros'
- is a list, and augments it with 'self.macros'; ensures that
- 'include_dirs' is a list, and augments it with 'self.include_dirs'.
- Guarantees that the returned values are of the correct type,
- i.e. for 'output_dir' either string or None, and for 'macros' and
- 'include_dirs' either list or None.
- """
- if output_dir is None:
- output_dir = self.output_dir
- elif not isinstance(output_dir, str):
- raise TypeError, "'output_dir' must be a string or None"
-
- if macros is None:
- macros = self.macros
- elif isinstance(macros, list):
- macros = macros + (self.macros or [])
- else:
- raise TypeError, "'macros' (if supplied) must be a list of tuples"
-
- if include_dirs is None:
- include_dirs = self.include_dirs
- elif isinstance(include_dirs, (list, tuple)):
- include_dirs = list (include_dirs) + (self.include_dirs or [])
- else:
- raise TypeError, \
- "'include_dirs' (if supplied) must be a list of strings"
-
- return output_dir, macros, include_dirs
-
- def _fix_object_args(self, objects, output_dir):
- """Typecheck and fix up some arguments supplied to various methods.
- Specifically: ensure that 'objects' is a list; if output_dir is
- None, replace with self.output_dir. Return fixed versions of
- 'objects' and 'output_dir'.
- """
- if not isinstance(objects, (list, tuple)):
- raise TypeError, \
- "'objects' must be a list or tuple of strings"
- objects = list (objects)
-
- if output_dir is None:
- output_dir = self.output_dir
- elif not isinstance(output_dir, str):
- raise TypeError, "'output_dir' must be a string or None"
-
- return (objects, output_dir)
-
- def _fix_lib_args(self, libraries, library_dirs, runtime_library_dirs):
- """Typecheck and fix up some of the arguments supplied to the
- 'link_*' methods. Specifically: ensure that all arguments are
- lists, and augment them with their permanent versions
- (eg. 'self.libraries' augments 'libraries'). Return a tuple with
- fixed versions of all arguments.
- """
- if libraries is None:
- libraries = self.libraries
- elif isinstance(libraries, (list, tuple)):
- libraries = list (libraries) + (self.libraries or [])
- else:
- raise TypeError, \
- "'libraries' (if supplied) must be a list of strings"
-
- if library_dirs is None:
- library_dirs = self.library_dirs
- elif isinstance(library_dirs, (list, tuple)):
- library_dirs = list (library_dirs) + (self.library_dirs or [])
- else:
- raise TypeError, \
- "'library_dirs' (if supplied) must be a list of strings"
-
- if runtime_library_dirs is None:
- runtime_library_dirs = self.runtime_library_dirs
- elif isinstance(runtime_library_dirs, (list, tuple)):
- runtime_library_dirs = (list (runtime_library_dirs) +
- (self.runtime_library_dirs or []))
- else:
- raise TypeError, \
- "'runtime_library_dirs' (if supplied) " + \
- "must be a list of strings"
-
- return (libraries, library_dirs, runtime_library_dirs)
-
- def _need_link(self, objects, output_file):
- """Return true if we need to relink the files listed in 'objects'
- to recreate 'output_file'.
- """
- if self.force:
- return 1
- else:
- if self.dry_run:
- newer = newer_group(objects, output_file, missing='newer')
- else:
- newer = newer_group(objects, output_file)
- return newer
-
- def detect_language(self, sources):
- """Detect the language of a given file, or list of files. Uses
- language_map, and language_order to do the job.
- """
- if not isinstance(sources, list):
- sources = [sources]
- lang = None
- index = len(self.language_order)
- for source in sources:
- base, ext = os.path.splitext(source)
- extlang = self.language_map.get(ext)
- try:
- extindex = self.language_order.index(extlang)
- if extindex < index:
- lang = extlang
- index = extindex
- except ValueError:
- pass
- return lang
-
- # -- Worker methods ------------------------------------------------
- # (must be implemented by subclasses)
-
- def preprocess(self, source, output_file=None, macros=None,
- include_dirs=None, extra_preargs=None, extra_postargs=None):
- """Preprocess a single C/C++ source file, named in 'source'.
- Output will be written to file named 'output_file', or stdout if
- 'output_file' not supplied. 'macros' is a list of macro
- definitions as for 'compile()', which will augment the macros set
- with 'define_macro()' and 'undefine_macro()'. 'include_dirs' is a
- list of directory names that will be added to the default list.
-
- Raises PreprocessError on failure.
- """
- pass
-
- def compile(self, sources, output_dir=None, macros=None,
- include_dirs=None, debug=0, extra_preargs=None,
- extra_postargs=None, depends=None):
- """Compile one or more source files.
-
- 'sources' must be a list of filenames, most likely C/C++
- files, but in reality anything that can be handled by a
- particular compiler and compiler class (eg. MSVCCompiler can
- handle resource files in 'sources'). Return a list of object
- filenames, one per source filename in 'sources'. Depending on
- the implementation, not all source files will necessarily be
- compiled, but all corresponding object filenames will be
- returned.
-
- If 'output_dir' is given, object files will be put under it, while
- retaining their original path component. That is, "foo/bar.c"
- normally compiles to "foo/bar.o" (for a Unix implementation); if
- 'output_dir' is "build", then it would compile to
- "build/foo/bar.o".
-
- 'macros', if given, must be a list of macro definitions. A macro
- definition is either a (name, value) 2-tuple or a (name,) 1-tuple.
- The former defines a macro; if the value is None, the macro is
- defined without an explicit value. The 1-tuple case undefines a
- macro. Later definitions/redefinitions/ undefinitions take
- precedence.
-
- 'include_dirs', if given, must be a list of strings, the
- directories to add to the default include file search path for this
- compilation only.
-
- 'debug' is a boolean; if true, the compiler will be instructed to
- output debug symbols in (or alongside) the object file(s).
-
- 'extra_preargs' and 'extra_postargs' are implementation- dependent.
- On platforms that have the notion of a command line (e.g. Unix,
- DOS/Windows), they are most likely lists of strings: extra
- command-line arguments to prepand/append to the compiler command
- line. On other platforms, consult the implementation class
- documentation. In any event, they are intended as an escape hatch
- for those occasions when the abstract compiler framework doesn't
- cut the mustard.
-
- 'depends', if given, is a list of filenames that all targets
- depend on. If a source file is older than any file in
- depends, then the source file will be recompiled. This
- supports dependency tracking, but only at a coarse
- granularity.
-
- Raises CompileError on failure.
- """
- # A concrete compiler class can either override this method
- # entirely or implement _compile().
-
- macros, objects, extra_postargs, pp_opts, build = \
- self._setup_compile(output_dir, macros, include_dirs, sources,
- depends, extra_postargs)
- cc_args = self._get_cc_args(pp_opts, debug, extra_preargs)
-
- for obj in objects:
- try:
- src, ext = build[obj]
- except KeyError:
- continue
- self._compile(obj, src, ext, cc_args, extra_postargs, pp_opts)
-
- # Return *all* object filenames, not just the ones we just built.
- return objects
-
- def _compile(self, obj, src, ext, cc_args, extra_postargs, pp_opts):
- """Compile 'src' to product 'obj'."""
-
- # A concrete compiler class that does not override compile()
- # should implement _compile().
- pass
-
- def create_static_lib(self, objects, output_libname, output_dir=None,
- debug=0, target_lang=None):
- """Link a bunch of stuff together to create a static library file.
- The "bunch of stuff" consists of the list of object files supplied
- as 'objects', the extra object files supplied to
- 'add_link_object()' and/or 'set_link_objects()', the libraries
- supplied to 'add_library()' and/or 'set_libraries()', and the
- libraries supplied as 'libraries' (if any).
-
- 'output_libname' should be a library name, not a filename; the
- filename will be inferred from the library name. 'output_dir' is
- the directory where the library file will be put.
-
- 'debug' is a boolean; if true, debugging information will be
- included in the library (note that on most platforms, it is the
- compile step where this matters: the 'debug' flag is included here
- just for consistency).
-
- 'target_lang' is the target language for which the given objects
- are being compiled. This allows specific linkage time treatment of
- certain languages.
-
- Raises LibError on failure.
- """
- pass
-
- # values for target_desc parameter in link()
- SHARED_OBJECT = "shared_object"
- SHARED_LIBRARY = "shared_library"
- EXECUTABLE = "executable"
-
- def link(self, target_desc, objects, output_filename, output_dir=None,
- libraries=None, library_dirs=None, runtime_library_dirs=None,
- export_symbols=None, debug=0, extra_preargs=None,
- extra_postargs=None, build_temp=None, target_lang=None):
- """Link a bunch of stuff together to create an executable or
- shared library file.
-
- The "bunch of stuff" consists of the list of object files supplied
- as 'objects'. 'output_filename' should be a filename. If
- 'output_dir' is supplied, 'output_filename' is relative to it
- (i.e. 'output_filename' can provide directory components if
- needed).
-
- 'libraries' is a list of libraries to link against. These are
- library names, not filenames, since they're translated into
- filenames in a platform-specific way (eg. "foo" becomes "libfoo.a"
- on Unix and "foo.lib" on DOS/Windows). However, they can include a
- directory component, which means the linker will look in that
- specific directory rather than searching all the normal locations.
-
- 'library_dirs', if supplied, should be a list of directories to
- search for libraries that were specified as bare library names
- (ie. no directory component). These are on top of the system
- default and those supplied to 'add_library_dir()' and/or
- 'set_library_dirs()'. 'runtime_library_dirs' is a list of
- directories that will be embedded into the shared library and used
- to search for other shared libraries that *it* depends on at
- run-time. (This may only be relevant on Unix.)
-
- 'export_symbols' is a list of symbols that the shared library will
- export. (This appears to be relevant only on Windows.)
-
- 'debug' is as for 'compile()' and 'create_static_lib()', with the
- slight distinction that it actually matters on most platforms (as
- opposed to 'create_static_lib()', which includes a 'debug' flag
- mostly for form's sake).
-
- 'extra_preargs' and 'extra_postargs' are as for 'compile()' (except
- of course that they supply command-line arguments for the
- particular linker being used).
-
- 'target_lang' is the target language for which the given objects
- are being compiled. This allows specific linkage time treatment of
- certain languages.
-
- Raises LinkError on failure.
- """
- raise NotImplementedError
-
-
- # Old 'link_*()' methods, rewritten to use the new 'link()' method.
-
- def link_shared_lib(self, objects, output_libname, output_dir=None,
- libraries=None, library_dirs=None,
- runtime_library_dirs=None, export_symbols=None,
- debug=0, extra_preargs=None, extra_postargs=None,
- build_temp=None, target_lang=None):
- self.link(CCompiler.SHARED_LIBRARY, objects,
- self.library_filename(output_libname, lib_type='shared'),
- output_dir,
- libraries, library_dirs, runtime_library_dirs,
- export_symbols, debug,
- extra_preargs, extra_postargs, build_temp, target_lang)
-
-
- def link_shared_object(self, objects, output_filename, output_dir=None,
- libraries=None, library_dirs=None,
- runtime_library_dirs=None, export_symbols=None,
- debug=0, extra_preargs=None, extra_postargs=None,
- build_temp=None, target_lang=None):
- self.link(CCompiler.SHARED_OBJECT, objects,
- output_filename, output_dir,
- libraries, library_dirs, runtime_library_dirs,
- export_symbols, debug,
- extra_preargs, extra_postargs, build_temp, target_lang)
-
- def link_executable(self, objects, output_progname, output_dir=None,
- libraries=None, library_dirs=None,
- runtime_library_dirs=None, debug=0, extra_preargs=None,
- extra_postargs=None, target_lang=None):
- self.link(CCompiler.EXECUTABLE, objects,
- self.executable_filename(output_progname), output_dir,
- libraries, library_dirs, runtime_library_dirs, None,
- debug, extra_preargs, extra_postargs, None, target_lang)
-
-
- # -- Miscellaneous methods -----------------------------------------
- # These are all used by the 'gen_lib_options() function; there is
- # no appropriate default implementation so subclasses should
- # implement all of these.
-
- def library_dir_option(self, dir):
- """Return the compiler option to add 'dir' to the list of
- directories searched for libraries.
- """
- raise NotImplementedError
-
- def runtime_library_dir_option(self, dir):
- """Return the compiler option to add 'dir' to the list of
- directories searched for runtime libraries.
- """
- raise NotImplementedError
-
- def library_option(self, lib):
- """Return the compiler option to add 'dir' to the list of libraries
- linked into the shared library or executable.
- """
- raise NotImplementedError
-
- def has_function(self, funcname, includes=None, include_dirs=None,
- libraries=None, library_dirs=None):
- """Return a boolean indicating whether funcname is supported on
- the current platform. The optional arguments can be used to
- augment the compilation environment.
- """
-
- # this can't be included at module scope because it tries to
- # import math which might not be available at that point - maybe
- # the necessary logic should just be inlined?
- import tempfile
- if includes is None:
- includes = []
- if include_dirs is None:
- include_dirs = []
- if libraries is None:
- libraries = []
- if library_dirs is None:
- library_dirs = []
- fd, fname = tempfile.mkstemp(".c", funcname, text=True)
- f = os.fdopen(fd, "w")
- try:
- for incl in includes:
- f.write("""#include "%s"\n""" % incl)
- f.write("""\
-main (int argc, char **argv) {
- %s();
-}
-""" % funcname)
- finally:
- f.close()
- try:
- objects = self.compile([fname], include_dirs=include_dirs)
- except CompileError:
- return False
-
- try:
- self.link_executable(objects, "a.out",
- libraries=libraries,
- library_dirs=library_dirs)
- except (LinkError, TypeError):
- return False
- return True
-
- def find_library_file (self, dirs, lib, debug=0):
- """Search the specified list of directories for a static or shared
- library file 'lib' and return the full path to that file. If
- 'debug' true, look for a debugging version (if that makes sense on
- the current platform). Return None if 'lib' wasn't found in any of
- the specified directories.
- """
- raise NotImplementedError
-
- # -- Filename generation methods -----------------------------------
-
- # The default implementation of the filename generating methods are
- # prejudiced towards the Unix/DOS/Windows view of the world:
- # * object files are named by replacing the source file extension
- # (eg. .c/.cpp -> .o/.obj)
- # * library files (shared or static) are named by plugging the
- # library name and extension into a format string, eg.
- # "lib%s.%s" % (lib_name, ".a") for Unix static libraries
- # * executables are named by appending an extension (possibly
- # empty) to the program name: eg. progname + ".exe" for
- # Windows
- #
- # To reduce redundant code, these methods expect to find
- # several attributes in the current object (presumably defined
- # as class attributes):
- # * src_extensions -
- # list of C/C++ source file extensions, eg. ['.c', '.cpp']
- # * obj_extension -
- # object file extension, eg. '.o' or '.obj'
- # * static_lib_extension -
- # extension for static library files, eg. '.a' or '.lib'
- # * shared_lib_extension -
- # extension for shared library/object files, eg. '.so', '.dll'
- # * static_lib_format -
- # format string for generating static library filenames,
- # eg. 'lib%s.%s' or '%s.%s'
- # * shared_lib_format
- # format string for generating shared library filenames
- # (probably same as static_lib_format, since the extension
- # is one of the intended parameters to the format string)
- # * exe_extension -
- # extension for executable files, eg. '' or '.exe'
-
- def object_filenames(self, source_filenames, strip_dir=0, output_dir=''):
- if output_dir is None:
- output_dir = ''
- obj_names = []
- for src_name in source_filenames:
- base, ext = os.path.splitext(src_name)
- base = os.path.splitdrive(base)[1] # Chop off the drive
- base = base[os.path.isabs(base):] # If abs, chop off leading /
- if ext not in self.src_extensions:
- raise UnknownFileError, \
- "unknown file type '%s' (from '%s')" % (ext, src_name)
- if strip_dir:
- base = os.path.basename(base)
- obj_names.append(os.path.join(output_dir,
- base + self.obj_extension))
- return obj_names
-
- def shared_object_filename(self, basename, strip_dir=0, output_dir=''):
- assert output_dir is not None
- if strip_dir:
- basename = os.path.basename (basename)
- return os.path.join(output_dir, basename + self.shared_lib_extension)
-
- def executable_filename(self, basename, strip_dir=0, output_dir=''):
- assert output_dir is not None
- if strip_dir:
- basename = os.path.basename (basename)
- return os.path.join(output_dir, basename + (self.exe_extension or ''))
-
- def library_filename(self, libname, lib_type='static', # or 'shared'
- strip_dir=0, output_dir=''):
- assert output_dir is not None
- if lib_type not in ("static", "shared", "dylib"):
- raise ValueError, "'lib_type' must be \"static\", \"shared\" or \"dylib\""
- fmt = getattr(self, lib_type + "_lib_format")
- ext = getattr(self, lib_type + "_lib_extension")
-
- dir, base = os.path.split (libname)
- filename = fmt % (base, ext)
- if strip_dir:
- dir = ''
-
- return os.path.join(output_dir, dir, filename)
-
-
- # -- Utility methods -----------------------------------------------
-
- def announce(self, msg, level=1):
- log.debug(msg)
-
- def debug_print(self, msg):
- from distutils2.debug import DEBUG
- if DEBUG:
- print msg
-
- def warn(self, msg):
- sys.stderr.write("warning: %s\n" % msg)
-
- def execute(self, func, args, msg=None, level=1):
- execute(func, args, msg, self.dry_run)
-
- def spawn(self, cmd):
- spawn(cmd, dry_run=self.dry_run)
-
- def move_file(self, src, dst):
- if self.dry_run:
- return # XXX log ?
- return move(src, dst)
-
- def mkpath(self, name, mode=0777):
- name = os.path.normpath(name)
- if os.path.isdir(name) or name == '':
- return
- if self.dry_run:
- head = ''
- for part in name.split(os.sep):
- log.info("created directory %s%s", head, part)
- head += part + os.sep
- return
- os.makedirs(name, mode)
-
-
-# Map a sys.platform/os.name ('posix', 'nt') to the default compiler
-# type for that platform. Keys are interpreted as re match
-# patterns. Order is important; platform mappings are preferred over
-# OS names.
-_default_compilers = (
-
- # Platform string mappings
-
- # on a cygwin built python we can use gcc like an ordinary UNIXish
- # compiler
- ('cygwin.*', 'unix'),
- ('os2emx', 'emx'),
-
- # OS name mappings
- ('posix', 'unix'),
- ('nt', 'msvc'),
-
- )
-
-def get_default_compiler(osname=None, platform=None):
- """ Determine the default compiler to use for the given platform.
-
- osname should be one of the standard Python OS names (i.e. the
- ones returned by os.name) and platform the common value
- returned by sys.platform for the platform in question.
-
- The default values are os.name and sys.platform in case the
- parameters are not given.
-
- """
- if osname is None:
- osname = os.name
- if platform is None:
- platform = sys.platform
- for pattern, compiler in _default_compilers:
- if re.match(pattern, platform) is not None or \
- re.match(pattern, osname) is not None:
- return compiler
- # Default to Unix compiler
- return 'unix'
-
-# Map compiler types to (module_name, class_name) pairs -- ie. where to
-# find the code that implements an interface to this compiler. (The module
-# is assumed to be in the 'distutils' package.)
-compiler_class = { 'unix': ('unixccompiler', 'UnixCCompiler',
- "standard UNIX-style compiler"),
- 'msvc': ('msvccompiler', 'MSVCCompiler',
- "Microsoft Visual C++"),
- 'cygwin': ('cygwinccompiler', 'CygwinCCompiler',
- "Cygwin port of GNU C Compiler for Win32"),
- 'mingw32': ('cygwinccompiler', 'Mingw32CCompiler',
- "Mingw32 port of GNU C Compiler for Win32"),
- 'bcpp': ('bcppcompiler', 'BCPPCompiler',
- "Borland C++ Compiler"),
- 'emx': ('emxccompiler', 'EMXCCompiler',
- "EMX port of GNU C Compiler for OS/2"),
- }
-
-def show_compilers():
- """Print list of available compilers (used by the "--help-compiler"
- options to "build", "build_ext", "build_clib").
- """
- # XXX this "knows" that the compiler option it's describing is
- # "--compiler", which just happens to be the case for the three
- # commands that use it.
- from distutils2.fancy_getopt import FancyGetopt
- compilers = []
- for compiler in compiler_class.keys():
- compilers.append(("compiler="+compiler, None,
- compiler_class[compiler][2]))
- compilers.sort()
- pretty_printer = FancyGetopt(compilers)
- pretty_printer.print_help("List of available compilers:")
-
-
-def new_compiler(plat=None, compiler=None, verbose=0, dry_run=0, force=0):
- """Generate an instance of some CCompiler subclass for the supplied
- platform/compiler combination. 'plat' defaults to 'os.name'
- (eg. 'posix', 'nt'), and 'compiler' defaults to the default compiler
- for that platform. Currently only 'posix' and 'nt' are supported, and
- the default compilers are "traditional Unix interface" (UnixCCompiler
- class) and Visual C++ (MSVCCompiler class). Note that it's perfectly
- possible to ask for a Unix compiler object under Windows, and a
- Microsoft compiler object under Unix -- if you supply a value for
- 'compiler', 'plat' is ignored.
- """
- if plat is None:
- plat = os.name
-
- try:
- if compiler is None:
- compiler = get_default_compiler(plat)
-
- (module_name, class_name, long_description) = compiler_class[compiler]
- except KeyError:
- msg = "don't know how to compile C/C++ code on platform '%s'" % plat
- if compiler is not None:
- msg = msg + " with '%s' compiler" % compiler
- raise DistutilsPlatformError, msg
-
- try:
- module_name = "distutils2.compiler." + module_name
- __import__ (module_name)
- module = sys.modules[module_name]
- cls = vars(module)[class_name]
- except ImportError:
- raise DistutilsModuleError, \
- "can't compile C/C++ code: unable to load module '%s'" % \
- module_name
- except KeyError:
- raise DistutilsModuleError, \
- ("can't compile C/C++ code: unable to find class '%s' " +
- "in module '%s'") % (class_name, module_name)
-
- # XXX The None is necessary to preserve backwards compatibility
- # with classes that expect verbose to be the first positional
- # argument.
- return cls(None, dry_run, force)
-
-
-def gen_preprocess_options(macros, include_dirs):
- """Generate C pre-processor options (-D, -U, -I) as used by at least
- two types of compilers: the typical Unix compiler and Visual C++.
- 'macros' is the usual thing, a list of 1- or 2-tuples, where (name,)
- means undefine (-U) macro 'name', and (name,value) means define (-D)
- macro 'name' to 'value'. 'include_dirs' is just a list of directory
- names to be added to the header file search path (-I). Returns a list
- of command-line options suitable for either Unix compilers or Visual
- C++.
- """
- # XXX it would be nice (mainly aesthetic, and so we don't generate
- # stupid-looking command lines) to go over 'macros' and eliminate
- # redundant definitions/undefinitions (ie. ensure that only the
- # latest mention of a particular macro winds up on the command
- # line). I don't think it's essential, though, since most (all?)
- # Unix C compilers only pay attention to the latest -D or -U
- # mention of a macro on their command line. Similar situation for
- # 'include_dirs'. I'm punting on both for now. Anyways, weeding out
- # redundancies like this should probably be the province of
- # CCompiler, since the data structures used are inherited from it
- # and therefore common to all CCompiler classes.
-
- pp_opts = []
- for macro in macros:
-
- if not (isinstance(macro, tuple) and
- 1 <= len (macro) <= 2):
- raise TypeError, \
- ("bad macro definition '%s': " +
- "each element of 'macros' list must be a 1- or 2-tuple") % \
- macro
-
- if len (macro) == 1: # undefine this macro
- pp_opts.append ("-U%s" % macro[0])
- elif len (macro) == 2:
- if macro[1] is None: # define with no explicit value
- pp_opts.append ("-D%s" % macro[0])
- else:
- # XXX *don't* need to be clever about quoting the
- # macro value here, because we're going to avoid the
- # shell at all costs when we spawn the command!
- pp_opts.append ("-D%s=%s" % macro)
-
- for dir in include_dirs:
- pp_opts.append ("-I%s" % dir)
-
- return pp_opts
-
-
-def gen_lib_options(compiler, library_dirs, runtime_library_dirs, libraries):
- """Generate linker options for searching library directories and
- linking with specific libraries.
-
- 'libraries' and 'library_dirs' are, respectively, lists of library names
- (not filenames!) and search directories. Returns a list of command-line
- options suitable for use with some compiler (depending on the two format
- strings passed in).
- """
- lib_opts = []
-
- for dir in library_dirs:
- lib_opts.append(compiler.library_dir_option(dir))
-
- for dir in runtime_library_dirs:
- opt = compiler.runtime_library_dir_option(dir)
- if isinstance(opt, list):
- lib_opts.extend(opt)
- else:
- lib_opts.append(opt)
-
- # XXX it's important that we *not* remove redundant library mentions!
- # sometimes you really do have to say "-lfoo -lbar -lfoo" in order to
- # resolve all symbols. I just hope we never have to say "-lfoo obj.o
- # -lbar" to get things to work -- that's certainly a possibility, but a
- # pretty nasty way to arrange your C code.
-
- for lib in libraries:
- lib_dir, lib_name = os.path.split(lib)
- if lib_dir != '':
- lib_file = compiler.find_library_file([lib_dir], lib_name)
- if lib_file is not None:
- lib_opts.append(lib_file)
- else:
- compiler.warn("no library file corresponding to "
- "'%s' found (skipping)" % lib)
- else:
- lib_opts.append(compiler.library_option(lib))
-
- return lib_opts
diff --git a/src/distutils2/compiler/cygwinccompiler.py b/src/distutils2/compiler/cygwinccompiler.py
deleted file mode 100644
index 9f5ce77..0000000
--- a/src/distutils2/compiler/cygwinccompiler.py
+++ /dev/null
@@ -1,385 +0,0 @@
-"""distutils.cygwinccompiler
-
-Provides the CygwinCCompiler class, a subclass of UnixCCompiler that
-handles the Cygwin port of the GNU C compiler to Windows. It also contains
-the Mingw32CCompiler class which handles the mingw32 port of GCC (same as
-cygwin in no-cygwin mode).
-"""
-
-# problems:
-#
-# * if you use a msvc compiled python version (1.5.2)
-# 1. you have to insert a __GNUC__ section in its config.h
-# 2. you have to generate a import library for its dll
-# - create a def-file for python??.dll
-# - create a import library using
-# dlltool --dllname python15.dll --def python15.def \
-# --output-lib libpython15.a
-#
-# see also http://starship.python.net/crew/kernr/mingw32/Notes.html
-#
-# * We put export_symbols in a def-file, and don't use
-# --export-all-symbols because it doesn't worked reliable in some
-# tested configurations. And because other windows compilers also
-# need their symbols specified this no serious problem.
-#
-# tested configurations:
-#
-# * cygwin gcc 2.91.57/ld 2.9.4/dllwrap 0.2.4 works
-# (after patching python's config.h and for C++ some other include files)
-# see also http://starship.python.net/crew/kernr/mingw32/Notes.html
-# * mingw32 gcc 2.95.2/ld 2.9.4/dllwrap 0.2.4 works
-# (ld doesn't support -shared, so we use dllwrap)
-# * cygwin gcc 2.95.2/ld 2.10.90/dllwrap 2.10.90 works now
-# - its dllwrap doesn't work, there is a bug in binutils 2.10.90
-# see also http://sources.redhat.com/ml/cygwin/2000-06/msg01274.html
-# - using gcc -mdll instead dllwrap doesn't work without -static because
-# it tries to link against dlls instead their import libraries. (If
-# it finds the dll first.)
-# By specifying -static we force ld to link against the import libraries,
-# this is windows standard and there are normally not the necessary symbols
-# in the dlls.
-# *** only the version of June 2000 shows these problems
-# * cygwin gcc 3.2/ld 2.13.90 works
-# (ld supports -shared)
-# * mingw gcc 3.2/ld 2.13 works
-# (ld supports -shared)
-
-__revision__ = "$Id: cygwinccompiler.py 77704 2010-01-23 09:23:15Z tarek.ziade $"
-
-import os
-import sys
-import copy
-import re
-from warnings import warn
-
-from distutils2.compiler.unixccompiler import UnixCCompiler
-from distutils2.util import write_file
-from distutils2.errors import DistutilsExecError, CompileError, UnknownFileError
-from distutils2.util import get_compiler_versions
-try:
- import sysconfig
-except ImportError:
- from distutils2._backport import sysconfig
-
-def get_msvcr():
- """Include the appropriate MSVC runtime library if Python was built
- with MSVC 7.0 or later.
- """
- msc_pos = sys.version.find('MSC v.')
- if msc_pos != -1:
- msc_ver = sys.version[msc_pos+6:msc_pos+10]
- if msc_ver == '1300':
- # MSVC 7.0
- return ['msvcr70']
- elif msc_ver == '1310':
- # MSVC 7.1
- return ['msvcr71']
- elif msc_ver == '1400':
- # VS2005 / MSVC 8.0
- return ['msvcr80']
- elif msc_ver == '1500':
- # VS2008 / MSVC 9.0
- return ['msvcr90']
- else:
- raise ValueError("Unknown MS Compiler version %s " % msc_ver)
-
-
-class CygwinCCompiler(UnixCCompiler):
- """ Handles the Cygwin port of the GNU C compiler to Windows.
- """
- compiler_type = 'cygwin'
- obj_extension = ".o"
- static_lib_extension = ".a"
- shared_lib_extension = ".dll"
- static_lib_format = "lib%s%s"
- shared_lib_format = "%s%s"
- exe_extension = ".exe"
-
- def __init__(self, verbose=0, dry_run=0, force=0):
-
- UnixCCompiler.__init__(self, verbose, dry_run, force)
-
- status, details = check_config_h()
- self.debug_print("Python's GCC status: %s (details: %s)" %
- (status, details))
- if status is not CONFIG_H_OK:
- self.warn(
- "Python's pyconfig.h doesn't seem to support your compiler. "
- "Reason: %s. "
- "Compiling may fail because of undefined preprocessor macros."
- % details)
-
- self.gcc_version, self.ld_version, self.dllwrap_version = \
- get_compiler_versions()
- self.debug_print(self.compiler_type + ": gcc %s, ld %s, dllwrap %s\n" %
- (self.gcc_version,
- self.ld_version,
- self.dllwrap_version) )
-
- # ld_version >= "2.10.90" and < "2.13" should also be able to use
- # gcc -mdll instead of dllwrap
- # Older dllwraps had own version numbers, newer ones use the
- # same as the rest of binutils ( also ld )
- # dllwrap 2.10.90 is buggy
- if self.ld_version >= "2.10.90":
- self.linker_dll = "gcc"
- else:
- self.linker_dll = "dllwrap"
-
- # ld_version >= "2.13" support -shared so use it instead of
- # -mdll -static
- if self.ld_version >= "2.13":
- shared_option = "-shared"
- else:
- shared_option = "-mdll -static"
-
- # Hard-code GCC because that's what this is all about.
- # XXX optimization, warnings etc. should be customizable.
- self.set_executables(compiler='gcc -mcygwin -O -Wall',
- compiler_so='gcc -mcygwin -mdll -O -Wall',
- compiler_cxx='g++ -mcygwin -O -Wall',
- linker_exe='gcc -mcygwin',
- linker_so=('%s -mcygwin %s' %
- (self.linker_dll, shared_option)))
-
- # cygwin and mingw32 need different sets of libraries
- if self.gcc_version == "2.91.57":
- # cygwin shouldn't need msvcrt, but without the dlls will crash
- # (gcc version 2.91.57) -- perhaps something about initialization
- self.dll_libraries=["msvcrt"]
- self.warn(
- "Consider upgrading to a newer version of gcc")
- else:
- # Include the appropriate MSVC runtime library if Python was built
- # with MSVC 7.0 or later.
- self.dll_libraries = get_msvcr()
-
- def _compile(self, obj, src, ext, cc_args, extra_postargs, pp_opts):
- """Compiles the source by spawing GCC and windres if needed."""
- if ext == '.rc' or ext == '.res':
- # gcc needs '.res' and '.rc' compiled to object files !!!
- try:
- self.spawn(["windres", "-i", src, "-o", obj])
- except DistutilsExecError, msg:
- raise CompileError, msg
- else: # for other files use the C-compiler
- try:
- self.spawn(self.compiler_so + cc_args + [src, '-o', obj] +
- extra_postargs)
- except DistutilsExecError, msg:
- raise CompileError, msg
-
- def link(self, target_desc, objects, output_filename, output_dir=None,
- libraries=None, library_dirs=None, runtime_library_dirs=None,
- export_symbols=None, debug=0, extra_preargs=None,
- extra_postargs=None, build_temp=None, target_lang=None):
- """Link the objects."""
- # use separate copies, so we can modify the lists
- extra_preargs = copy.copy(extra_preargs or [])
- libraries = copy.copy(libraries or [])
- objects = copy.copy(objects or [])
-
- # Additional libraries
- libraries.extend(self.dll_libraries)
-
- # handle export symbols by creating a def-file
- # with executables this only works with gcc/ld as linker
- if ((export_symbols is not None) and
- (target_desc != self.EXECUTABLE or self.linker_dll == "gcc")):
- # (The linker doesn't do anything if output is up-to-date.
- # So it would probably better to check if we really need this,
- # but for this we had to insert some unchanged parts of
- # UnixCCompiler, and this is not what we want.)
-
- # we want to put some files in the same directory as the
- # object files are, build_temp doesn't help much
- # where are the object files
- temp_dir = os.path.dirname(objects[0])
- # name of dll to give the helper files the same base name
- (dll_name, dll_extension) = os.path.splitext(
- os.path.basename(output_filename))
-
- # generate the filenames for these files
- def_file = os.path.join(temp_dir, dll_name + ".def")
- lib_file = os.path.join(temp_dir, 'lib' + dll_name + ".a")
-
- # Generate .def file
- contents = [
- "LIBRARY %s" % os.path.basename(output_filename),
- "EXPORTS"]
- for sym in export_symbols:
- contents.append(sym)
- self.execute(write_file, (def_file, contents),
- "writing %s" % def_file)
-
- # next add options for def-file and to creating import libraries
-
- # dllwrap uses different options than gcc/ld
- if self.linker_dll == "dllwrap":
- extra_preargs.extend(["--output-lib", lib_file])
- # for dllwrap we have to use a special option
- extra_preargs.extend(["--def", def_file])
- # we use gcc/ld here and can be sure ld is >= 2.9.10
- else:
- # doesn't work: bfd_close build\...\libfoo.a: Invalid operation
- #extra_preargs.extend(["-Wl,--out-implib,%s" % lib_file])
- # for gcc/ld the def-file is specified as any object files
- objects.append(def_file)
-
- #end: if ((export_symbols is not None) and
- # (target_desc != self.EXECUTABLE or self.linker_dll == "gcc")):
-
- # who wants symbols and a many times larger output file
- # should explicitly switch the debug mode on
- # otherwise we let dllwrap/ld strip the output file
- # (On my machine: 10KB < stripped_file < ??100KB
- # unstripped_file = stripped_file + XXX KB
- # ( XXX=254 for a typical python extension))
- if not debug:
- extra_preargs.append("-s")
-
- UnixCCompiler.link(self, target_desc, objects, output_filename,
- output_dir, libraries, library_dirs,
- runtime_library_dirs,
- None, # export_symbols, we do this in our def-file
- debug, extra_preargs, extra_postargs, build_temp,
- target_lang)
-
- # -- Miscellaneous methods -----------------------------------------
-
- def object_filenames(self, source_filenames, strip_dir=0, output_dir=''):
- """Adds supports for rc and res files."""
- if output_dir is None:
- output_dir = ''
- obj_names = []
- for src_name in source_filenames:
- # use normcase to make sure '.rc' is really '.rc' and not '.RC'
- base, ext = os.path.splitext(os.path.normcase(src_name))
- if ext not in (self.src_extensions + ['.rc','.res']):
- raise UnknownFileError, \
- "unknown file type '%s' (from '%s')" % (ext, src_name)
- if strip_dir:
- base = os.path.basename (base)
- if ext in ('.res', '.rc'):
- # these need to be compiled to object files
- obj_names.append (os.path.join(output_dir,
- base + ext + self.obj_extension))
- else:
- obj_names.append (os.path.join(output_dir,
- base + self.obj_extension))
- return obj_names
-
-# the same as cygwin plus some additional parameters
-class Mingw32CCompiler(CygwinCCompiler):
- """ Handles the Mingw32 port of the GNU C compiler to Windows.
- """
- compiler_type = 'mingw32'
-
- def __init__(self, verbose=0, dry_run=0, force=0):
-
- CygwinCCompiler.__init__ (self, verbose, dry_run, force)
-
- # ld_version >= "2.13" support -shared so use it instead of
- # -mdll -static
- if self.ld_version >= "2.13":
- shared_option = "-shared"
- else:
- shared_option = "-mdll -static"
-
- # A real mingw32 doesn't need to specify a different entry point,
- # but cygwin 2.91.57 in no-cygwin-mode needs it.
- if self.gcc_version <= "2.91.57":
- entry_point = '--entry _DllMain@12'
- else:
- entry_point = ''
-
- self.set_executables(compiler='gcc -mno-cygwin -O -Wall',
- compiler_so='gcc -mno-cygwin -mdll -O -Wall',
- compiler_cxx='g++ -mno-cygwin -O -Wall',
- linker_exe='gcc -mno-cygwin',
- linker_so='%s -mno-cygwin %s %s'
- % (self.linker_dll, shared_option,
- entry_point))
- # Maybe we should also append -mthreads, but then the finished
- # dlls need another dll (mingwm10.dll see Mingw32 docs)
- # (-mthreads: Support thread-safe exception handling on `Mingw32')
-
- # no additional libraries needed
- self.dll_libraries=[]
-
- # Include the appropriate MSVC runtime library if Python was built
- # with MSVC 7.0 or later.
- self.dll_libraries = get_msvcr()
-
-# Because these compilers aren't configured in Python's pyconfig.h file by
-# default, we should at least warn the user if he is using a unmodified
-# version.
-
-CONFIG_H_OK = "ok"
-CONFIG_H_NOTOK = "not ok"
-CONFIG_H_UNCERTAIN = "uncertain"
-
-def check_config_h():
- """Check if the current Python installation appears amenable to building
- extensions with GCC.
-
- Returns a tuple (status, details), where 'status' is one of the following
- constants:
-
- - CONFIG_H_OK: all is well, go ahead and compile
- - CONFIG_H_NOTOK: doesn't look good
- - CONFIG_H_UNCERTAIN: not sure -- unable to read pyconfig.h
-
- 'details' is a human-readable string explaining the situation.
-
- Note there are two ways to conclude "OK": either 'sys.version' contains
- the string "GCC" (implying that this Python was built with GCC), or the
- installed "pyconfig.h" contains the string "__GNUC__".
- """
-
- # XXX since this function also checks sys.version, it's not strictly a
- # "pyconfig.h" check -- should probably be renamed...
- # if sys.version contains GCC then python was compiled with GCC, and the
- # pyconfig.h file should be OK
- if "GCC" in sys.version:
- return CONFIG_H_OK, "sys.version mentions 'GCC'"
-
- # let's see if __GNUC__ is mentioned in python.h
- fn = sysconfig.get_config_h_filename()
- try:
- config_h = open(fn)
- try:
- if "__GNUC__" in config_h.read():
- return CONFIG_H_OK, "'%s' mentions '__GNUC__'" % fn
- else:
- return CONFIG_H_NOTOK, "'%s' does not mention '__GNUC__'" % fn
- finally:
- config_h.close()
- except IOError, exc:
- return (CONFIG_H_UNCERTAIN,
- "couldn't read '%s': %s" % (fn, exc.strerror))
-
-class _Deprecated_SRE_Pattern(object):
- def __init__(self, pattern):
- self.pattern = pattern
-
- def __getattr__(self, name):
- if name in ('findall', 'finditer', 'match', 'scanner', 'search',
- 'split', 'sub', 'subn'):
- warn("'distutils.cygwinccompiler.RE_VERSION' is deprecated "
- "and will be removed in the next version", DeprecationWarning)
- return getattr(self.pattern, name)
-
-RE_VERSION = _Deprecated_SRE_Pattern(re.compile('(\d+\.\d+(\.\d+)*)'))
-
-def get_versions():
- """ Try to find out the versions of gcc, ld and dllwrap.
-
- If not possible it returns None for it.
- """
- warn("'distutils.cygwinccompiler.get_versions' is deprecated "
- "use 'distutils.util.get_compiler_versions' instead",
- DeprecationWarning)
-
- return get_compiler_versions()
diff --git a/src/distutils2/compiler/emxccompiler.py b/src/distutils2/compiler/emxccompiler.py
deleted file mode 100644
index 6247c00..0000000
--- a/src/distutils2/compiler/emxccompiler.py
+++ /dev/null
@@ -1,305 +0,0 @@
-"""distutils.emxccompiler
-
-Provides the EMXCCompiler class, a subclass of UnixCCompiler that
-handles the EMX port of the GNU C compiler to OS/2.
-"""
-
-# issues:
-#
-# * OS/2 insists that DLLs can have names no longer than 8 characters
-# We put export_symbols in a def-file, as though the DLL can have
-# an arbitrary length name, but truncate the output filename.
-#
-# * only use OMF objects and use LINK386 as the linker (-Zomf)
-#
-# * always build for multithreading (-Zmt) as the accompanying OS/2 port
-# of Python is only distributed with threads enabled.
-#
-# tested configurations:
-#
-# * EMX gcc 2.81/EMX 0.9d fix03
-
-__revision__ = "$Id: emxccompiler.py 76956 2009-12-21 01:22:46Z tarek.ziade $"
-
-import os, sys, copy
-from warnings import warn
-
-from distutils2.compiler.unixccompiler import UnixCCompiler
-from distutils2.errors import DistutilsExecError, CompileError, UnknownFileError
-from distutils2.util import get_compiler_versions, write_file
-
-class EMXCCompiler (UnixCCompiler):
-
- compiler_type = 'emx'
- obj_extension = ".obj"
- static_lib_extension = ".lib"
- shared_lib_extension = ".dll"
- static_lib_format = "%s%s"
- shared_lib_format = "%s%s"
- res_extension = ".res" # compiled resource file
- exe_extension = ".exe"
-
- def __init__ (self,
- verbose=0,
- dry_run=0,
- force=0):
-
- UnixCCompiler.__init__ (self, verbose, dry_run, force)
-
- (status, details) = check_config_h()
- self.debug_print("Python's GCC status: %s (details: %s)" %
- (status, details))
- if status is not CONFIG_H_OK:
- self.warn(
- "Python's pyconfig.h doesn't seem to support your compiler. " +
- ("Reason: %s." % details) +
- "Compiling may fail because of undefined preprocessor macros.")
-
- gcc_version, ld_version, dllwrap_version = get_compiler_versions()
- self.gcc_version, self.ld_version = gcc_version, ld_version
- self.debug_print(self.compiler_type + ": gcc %s, ld %s\n" %
- (self.gcc_version,
- self.ld_version) )
-
- # Hard-code GCC because that's what this is all about.
- # XXX optimization, warnings etc. should be customizable.
- self.set_executables(compiler='gcc -Zomf -Zmt -O3 -fomit-frame-pointer -mprobe -Wall',
- compiler_so='gcc -Zomf -Zmt -O3 -fomit-frame-pointer -mprobe -Wall',
- linker_exe='gcc -Zomf -Zmt -Zcrtdll',
- linker_so='gcc -Zomf -Zmt -Zcrtdll -Zdll')
-
- # want the gcc library statically linked (so that we don't have
- # to distribute a version dependent on the compiler we have)
- self.dll_libraries=["gcc"]
-
- # __init__ ()
-
- def _compile(self, obj, src, ext, cc_args, extra_postargs, pp_opts):
- if ext == '.rc':
- # gcc requires '.rc' compiled to binary ('.res') files !!!
- try:
- self.spawn(["rc", "-r", src])
- except DistutilsExecError, msg:
- raise CompileError, msg
- else: # for other files use the C-compiler
- try:
- self.spawn(self.compiler_so + cc_args + [src, '-o', obj] +
- extra_postargs)
- except DistutilsExecError, msg:
- raise CompileError, msg
-
- def link (self,
- target_desc,
- objects,
- output_filename,
- output_dir=None,
- libraries=None,
- library_dirs=None,
- runtime_library_dirs=None,
- export_symbols=None,
- debug=0,
- extra_preargs=None,
- extra_postargs=None,
- build_temp=None,
- target_lang=None):
-
- # use separate copies, so we can modify the lists
- extra_preargs = copy.copy(extra_preargs or [])
- libraries = copy.copy(libraries or [])
- objects = copy.copy(objects or [])
-
- # Additional libraries
- libraries.extend(self.dll_libraries)
-
- # handle export symbols by creating a def-file
- # with executables this only works with gcc/ld as linker
- if ((export_symbols is not None) and
- (target_desc != self.EXECUTABLE)):
- # (The linker doesn't do anything if output is up-to-date.
- # So it would probably better to check if we really need this,
- # but for this we had to insert some unchanged parts of
- # UnixCCompiler, and this is not what we want.)
-
- # we want to put some files in the same directory as the
- # object files are, build_temp doesn't help much
- # where are the object files
- temp_dir = os.path.dirname(objects[0])
- # name of dll to give the helper files the same base name
- (dll_name, dll_extension) = os.path.splitext(
- os.path.basename(output_filename))
-
- # generate the filenames for these files
- def_file = os.path.join(temp_dir, dll_name + ".def")
-
- # Generate .def file
- contents = [
- "LIBRARY %s INITINSTANCE TERMINSTANCE" % \
- os.path.splitext(os.path.basename(output_filename))[0],
- "DATA MULTIPLE NONSHARED",
- "EXPORTS"]
- for sym in export_symbols:
- contents.append(' "%s"' % sym)
- self.execute(write_file, (def_file, contents),
- "writing %s" % def_file)
-
- # next add options for def-file and to creating import libraries
- # for gcc/ld the def-file is specified as any other object files
- objects.append(def_file)
-
- #end: if ((export_symbols is not None) and
- # (target_desc != self.EXECUTABLE or self.linker_dll == "gcc")):
-
- # who wants symbols and a many times larger output file
- # should explicitly switch the debug mode on
- # otherwise we let dllwrap/ld strip the output file
- # (On my machine: 10KB < stripped_file < ??100KB
- # unstripped_file = stripped_file + XXX KB
- # ( XXX=254 for a typical python extension))
- if not debug:
- extra_preargs.append("-s")
-
- UnixCCompiler.link(self,
- target_desc,
- objects,
- output_filename,
- output_dir,
- libraries,
- library_dirs,
- runtime_library_dirs,
- None, # export_symbols, we do this in our def-file
- debug,
- extra_preargs,
- extra_postargs,
- build_temp,
- target_lang)
-
- # link ()
-
- # -- Miscellaneous methods -----------------------------------------
-
- # override the object_filenames method from CCompiler to
- # support rc and res-files
- def object_filenames (self,
- source_filenames,
- strip_dir=0,
- output_dir=''):
- if output_dir is None: output_dir = ''
- obj_names = []
- for src_name in source_filenames:
- # use normcase to make sure '.rc' is really '.rc' and not '.RC'
- (base, ext) = os.path.splitext (os.path.normcase(src_name))
- if ext not in (self.src_extensions + ['.rc']):
- raise UnknownFileError, \
- "unknown file type '%s' (from '%s')" % \
- (ext, src_name)
- if strip_dir:
- base = os.path.basename (base)
- if ext == '.rc':
- # these need to be compiled to object files
- obj_names.append (os.path.join (output_dir,
- base + self.res_extension))
- else:
- obj_names.append (os.path.join (output_dir,
- base + self.obj_extension))
- return obj_names
-
- # object_filenames ()
-
- # override the find_library_file method from UnixCCompiler
- # to deal with file naming/searching differences
- def find_library_file(self, dirs, lib, debug=0):
- shortlib = '%s.lib' % lib
- longlib = 'lib%s.lib' % lib # this form very rare
-
- # get EMX's default library directory search path
- try:
- emx_dirs = os.environ['LIBRARY_PATH'].split(';')
- except KeyError:
- emx_dirs = []
-
- for dir in dirs + emx_dirs:
- shortlibp = os.path.join(dir, shortlib)
- longlibp = os.path.join(dir, longlib)
- if os.path.exists(shortlibp):
- return shortlibp
- elif os.path.exists(longlibp):
- return longlibp
-
- # Oops, didn't find it in *any* of 'dirs'
- return None
-
-# class EMXCCompiler
-
-
-# Because these compilers aren't configured in Python's pyconfig.h file by
-# default, we should at least warn the user if he is using a unmodified
-# version.
-
-CONFIG_H_OK = "ok"
-CONFIG_H_NOTOK = "not ok"
-CONFIG_H_UNCERTAIN = "uncertain"
-
-def check_config_h():
-
- """Check if the current Python installation (specifically, pyconfig.h)
- appears amenable to building extensions with GCC. Returns a tuple
- (status, details), where 'status' is one of the following constants:
- CONFIG_H_OK
- all is well, go ahead and compile
- CONFIG_H_NOTOK
- doesn't look good
- CONFIG_H_UNCERTAIN
- not sure -- unable to read pyconfig.h
- 'details' is a human-readable string explaining the situation.
-
- Note there are two ways to conclude "OK": either 'sys.version' contains
- the string "GCC" (implying that this Python was built with GCC), or the
- installed "pyconfig.h" contains the string "__GNUC__".
- """
-
- # XXX since this function also checks sys.version, it's not strictly a
- # "pyconfig.h" check -- should probably be renamed...
-
- from distutils2 import sysconfig
- import string
- # if sys.version contains GCC then python was compiled with
- # GCC, and the pyconfig.h file should be OK
- if string.find(sys.version,"GCC") >= 0:
- return (CONFIG_H_OK, "sys.version mentions 'GCC'")
-
- fn = sysconfig.get_config_h_filename()
- try:
- # It would probably better to read single lines to search.
- # But we do this only once, and it is fast enough
- f = open(fn)
- try:
- s = f.read()
- finally:
- f.close()
-
- except IOError, exc:
- # if we can't read this file, we cannot say it is wrong
- # the compiler will complain later about this file as missing
- return (CONFIG_H_UNCERTAIN,
- "couldn't read '%s': %s" % (fn, exc.strerror))
-
- else:
- # "pyconfig.h" contains an "#ifdef __GNUC__" or something similar
- if string.find(s,"__GNUC__") >= 0:
- return (CONFIG_H_OK, "'%s' mentions '__GNUC__'" % fn)
- else:
- return (CONFIG_H_NOTOK, "'%s' does not mention '__GNUC__'" % fn)
-
-
-def get_versions():
- """ Try to find out the versions of gcc and ld.
- If not possible it returns None for it.
- """
- warn("'distutils.emxccompiler.get_versions' is deprecated "
- "use 'distutils.util.get_compiler_versions' instead",
- DeprecationWarning)
-
- # EMX ld has no way of reporting version number, and we use GCC
- # anyway - so we can link OMF DLLs
- gcc_version, ld_version, dllwrap_version = get_compiler_versions()
- return gcc_version, None
diff --git a/src/distutils2/compiler/msvc9compiler.py b/src/distutils2/compiler/msvc9compiler.py
deleted file mode 100644
index 46cffa5..0000000
--- a/src/distutils2/compiler/msvc9compiler.py
+++ /dev/null
@@ -1,740 +0,0 @@
-"""distutils.msvc9compiler
-
-Contains MSVCCompiler, an implementation of the abstract CCompiler class
-for the Microsoft Visual Studio 2008.
-
-The module is compatible with VS 2005 and VS 2008. You can find legacy support
-for older versions of VS in distutils.msvccompiler.
-"""
-
-# Written by Perry Stoll
-# hacked by Robin Becker and Thomas Heller to do a better job of
-# finding DevStudio (through the registry)
-# ported to VS2005 and VS 2008 by Christian Heimes
-
-__revision__ = "$Id: msvc9compiler.py 77761 2010-01-26 22:46:15Z tarek.ziade $"
-
-import os
-import subprocess
-import sys
-import re
-
-from distutils2.errors import (DistutilsExecError, DistutilsPlatformError,
- CompileError, LibError, LinkError)
-from distutils2.compiler.ccompiler import CCompiler, gen_lib_options
-from distutils2 import log
-from distutils2.util import get_platform
-
-import _winreg
-
-RegOpenKeyEx = _winreg.OpenKeyEx
-RegEnumKey = _winreg.EnumKey
-RegEnumValue = _winreg.EnumValue
-RegError = _winreg.error
-
-HKEYS = (_winreg.HKEY_USERS,
- _winreg.HKEY_CURRENT_USER,
- _winreg.HKEY_LOCAL_MACHINE,
- _winreg.HKEY_CLASSES_ROOT)
-
-VS_BASE = r"Software\Microsoft\VisualStudio\%0.1f"
-WINSDK_BASE = r"Software\Microsoft\Microsoft SDKs\Windows"
-NET_BASE = r"Software\Microsoft\.NETFramework"
-
-# A map keyed by get_platform() return values to values accepted by
-# 'vcvarsall.bat'. Note a cross-compile may combine these (eg, 'x86_amd64' is
-# the param to cross-compile on x86 targetting amd64.)
-PLAT_TO_VCVARS = {
- 'win32' : 'x86',
- 'win-amd64' : 'amd64',
- 'win-ia64' : 'ia64',
-}
-
-class Reg(object):
- """Helper class to read values from the registry
- """
-
- def get_value(cls, path, key):
- for base in HKEYS:
- d = cls.read_values(base, path)
- if d and key in d:
- return d[key]
- raise KeyError(key)
- get_value = classmethod(get_value)
-
- def read_keys(cls, base, key):
- """Return list of registry keys."""
- try:
- handle = RegOpenKeyEx(base, key)
- except RegError:
- return None
- L = []
- i = 0
- while True:
- try:
- k = RegEnumKey(handle, i)
- except RegError:
- break
- L.append(k)
- i += 1
- return L
- read_keys = classmethod(read_keys)
-
- def read_values(cls, base, key):
- """Return dict of registry keys and values.
-
- All names are converted to lowercase.
- """
- try:
- handle = RegOpenKeyEx(base, key)
- except RegError:
- return None
- d = {}
- i = 0
- while True:
- try:
- name, value, type = RegEnumValue(handle, i)
- except RegError:
- break
- name = name.lower()
- d[cls.convert_mbcs(name)] = cls.convert_mbcs(value)
- i += 1
- return d
- read_values = classmethod(read_values)
-
- def convert_mbcs(s):
- dec = getattr(s, "decode", None)
- if dec is not None:
- try:
- s = dec("mbcs")
- except UnicodeError:
- pass
- return s
- convert_mbcs = staticmethod(convert_mbcs)
-
-class MacroExpander(object):
-
- def __init__(self, version):
- self.macros = {}
- self.vsbase = VS_BASE % version
- self.load_macros(version)
-
- def set_macro(self, macro, path, key):
- self.macros["$(%s)" % macro] = Reg.get_value(path, key)
-
- def load_macros(self, version):
- self.set_macro("VCInstallDir", self.vsbase + r"\Setup\VC", "productdir")
- self.set_macro("VSInstallDir", self.vsbase + r"\Setup\VS", "productdir")
- self.set_macro("FrameworkDir", NET_BASE, "installroot")
- try:
- if version >= 8.0:
- self.set_macro("FrameworkSDKDir", NET_BASE,
- "sdkinstallrootv2.0")
- else:
- raise KeyError("sdkinstallrootv2.0")
- except KeyError:
- raise DistutilsPlatformError(
- """Python was built with Visual Studio 2008;
-extensions must be built with a compiler than can generate compatible binaries.
-Visual Studio 2008 was not found on this system. If you have Cygwin installed,
-you can try compiling with MingW32, by passing "-c mingw32" to setup.py.""")
-
- if version >= 9.0:
- self.set_macro("FrameworkVersion", self.vsbase, "clr version")
- self.set_macro("WindowsSdkDir", WINSDK_BASE, "currentinstallfolder")
- else:
- p = r"Software\Microsoft\NET Framework Setup\Product"
- for base in HKEYS:
- try:
- h = RegOpenKeyEx(base, p)
- except RegError:
- continue
- key = RegEnumKey(h, 0)
- d = Reg.get_value(base, r"%s\%s" % (p, key))
- self.macros["$(FrameworkVersion)"] = d["version"]
-
- def sub(self, s):
- for k, v in self.macros.items():
- s = s.replace(k, v)
- return s
-
-def get_build_version():
- """Return the version of MSVC that was used to build Python.
-
- For Python 2.3 and up, the version number is included in
- sys.version. For earlier versions, assume the compiler is MSVC 6.
- """
- prefix = "MSC v."
- i = sys.version.find(prefix)
- if i == -1:
- return 6
- i = i + len(prefix)
- s, rest = sys.version[i:].split(" ", 1)
- majorVersion = int(s[:-2]) - 6
- minorVersion = int(s[2:3]) / 10.0
- # I don't think paths are affected by minor version in version 6
- if majorVersion == 6:
- minorVersion = 0
- if majorVersion >= 6:
- return majorVersion + minorVersion
- # else we don't know what version of the compiler this is
- return None
-
-def normalize_and_reduce_paths(paths):
- """Return a list of normalized paths with duplicates removed.
-
- The current order of paths is maintained.
- """
- # Paths are normalized so things like: /a and /a/ aren't both preserved.
- reduced_paths = []
- for p in paths:
- np = os.path.normpath(p)
- # XXX(nnorwitz): O(n**2), if reduced_paths gets long perhaps use a set.
- if np not in reduced_paths:
- reduced_paths.append(np)
- return reduced_paths
-
-def removeDuplicates(variable):
- """Remove duplicate values of an environment variable.
- """
- oldList = variable.split(os.pathsep)
- newList = []
- for i in oldList:
- if i not in newList:
- newList.append(i)
- newVariable = os.pathsep.join(newList)
- return newVariable
-
-def find_vcvarsall(version):
- """Find the vcvarsall.bat file
-
- At first it tries to find the productdir of VS 2008 in the registry. If
- that fails it falls back to the VS90COMNTOOLS env var.
- """
- vsbase = VS_BASE % version
- try:
- productdir = Reg.get_value(r"%s\Setup\VC" % vsbase,
- "productdir")
- except KeyError:
- log.debug("Unable to find productdir in registry")
- productdir = None
-
- if not productdir or not os.path.isdir(productdir):
- toolskey = "VS%0.f0COMNTOOLS" % version
- toolsdir = os.environ.get(toolskey, None)
-
- if toolsdir and os.path.isdir(toolsdir):
- productdir = os.path.join(toolsdir, os.pardir, os.pardir, "VC")
- productdir = os.path.abspath(productdir)
- if not os.path.isdir(productdir):
- log.debug("%s is not a valid directory" % productdir)
- return None
- else:
- log.debug("Env var %s is not set or invalid" % toolskey)
- if not productdir:
- log.debug("No productdir found")
- return None
- vcvarsall = os.path.join(productdir, "vcvarsall.bat")
- if os.path.isfile(vcvarsall):
- return vcvarsall
- log.debug("Unable to find vcvarsall.bat")
- return None
-
-def query_vcvarsall(version, arch="x86"):
- """Launch vcvarsall.bat and read the settings from its environment
- """
- vcvarsall = find_vcvarsall(version)
- interesting = set(("include", "lib", "libpath", "path"))
- result = {}
-
- if vcvarsall is None:
- raise DistutilsPlatformError("Unable to find vcvarsall.bat")
- log.debug("Calling 'vcvarsall.bat %s' (version=%s)", arch, version)
- popen = subprocess.Popen('"%s" %s & set' % (vcvarsall, arch),
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE)
-
- stdout, stderr = popen.communicate()
- if popen.wait() != 0:
- raise DistutilsPlatformError(stderr.decode("mbcs"))
-
- stdout = stdout.decode("mbcs")
- for line in stdout.split("\n"):
- line = Reg.convert_mbcs(line)
- if '=' not in line:
- continue
- line = line.strip()
- key, value = line.split('=', 1)
- key = key.lower()
- if key in interesting:
- if value.endswith(os.pathsep):
- value = value[:-1]
- result[key] = removeDuplicates(value)
-
- if len(result) != len(interesting):
- raise ValueError(str(list(result.keys())))
-
- return result
-
-# More globals
-VERSION = get_build_version()
-if VERSION < 8.0:
- raise DistutilsPlatformError("VC %0.1f is not supported by this module" % VERSION)
-# MACROS = MacroExpander(VERSION)
-
-class MSVCCompiler(CCompiler) :
- """Concrete class that implements an interface to Microsoft Visual C++,
- as defined by the CCompiler abstract class."""
-
- compiler_type = 'msvc'
-
- # Just set this so CCompiler's constructor doesn't barf. We currently
- # don't use the 'set_executables()' bureaucracy provided by CCompiler,
- # as it really isn't necessary for this sort of single-compiler class.
- # Would be nice to have a consistent interface with UnixCCompiler,
- # though, so it's worth thinking about.
- executables = {}
-
- # Private class data (need to distinguish C from C++ source for compiler)
- _c_extensions = ['.c']
- _cpp_extensions = ['.cc', '.cpp', '.cxx']
- _rc_extensions = ['.rc']
- _mc_extensions = ['.mc']
-
- # Needed for the filename generation methods provided by the
- # base class, CCompiler.
- src_extensions = (_c_extensions + _cpp_extensions +
- _rc_extensions + _mc_extensions)
- res_extension = '.res'
- obj_extension = '.obj'
- static_lib_extension = '.lib'
- shared_lib_extension = '.dll'
- static_lib_format = shared_lib_format = '%s%s'
- exe_extension = '.exe'
-
- def __init__(self, verbose=0, dry_run=0, force=0):
- CCompiler.__init__ (self, verbose, dry_run, force)
- self.__version = VERSION
- self.__root = r"Software\Microsoft\VisualStudio"
- # self.__macros = MACROS
- self.__paths = []
- # target platform (.plat_name is consistent with 'bdist')
- self.plat_name = None
- self.__arch = None # deprecated name
- self.initialized = False
-
- def initialize(self, plat_name=None):
- # multi-init means we would need to check platform same each time...
- assert not self.initialized, "don't init multiple times"
- if plat_name is None:
- plat_name = get_platform()
- # sanity check for platforms to prevent obscure errors later.
- ok_plats = 'win32', 'win-amd64', 'win-ia64'
- if plat_name not in ok_plats:
- raise DistutilsPlatformError("--plat-name must be one of %s" %
- (ok_plats,))
-
- if "DISTUTILS_USE_SDK" in os.environ and "MSSdk" in os.environ and self.find_exe("cl.exe"):
- # Assume that the SDK set up everything alright; don't try to be
- # smarter
- self.cc = "cl.exe"
- self.linker = "link.exe"
- self.lib = "lib.exe"
- self.rc = "rc.exe"
- self.mc = "mc.exe"
- else:
- # On x86, 'vcvars32.bat amd64' creates an env that doesn't work;
- # to cross compile, you use 'x86_amd64'.
- # On AMD64, 'vcvars32.bat amd64' is a native build env; to cross
- # compile use 'x86' (ie, it runs the x86 compiler directly)
- # No idea how itanium handles this, if at all.
- if plat_name == get_platform() or plat_name == 'win32':
- # native build or cross-compile to win32
- plat_spec = PLAT_TO_VCVARS[plat_name]
- else:
- # cross compile from win32 -> some 64bit
- plat_spec = PLAT_TO_VCVARS[get_platform()] + '_' + \
- PLAT_TO_VCVARS[plat_name]
-
- vc_env = query_vcvarsall(VERSION, plat_spec)
-
- # take care to only use strings in the environment.
- self.__paths = vc_env['path'].encode('mbcs').split(os.pathsep)
- os.environ['lib'] = vc_env['lib'].encode('mbcs')
- os.environ['include'] = vc_env['include'].encode('mbcs')
-
- if len(self.__paths) == 0:
- raise DistutilsPlatformError("Python was built with %s, "
- "and extensions need to be built with the same "
- "version of the compiler, but it isn't installed."
- % self.__product)
-
- self.cc = self.find_exe("cl.exe")
- self.linker = self.find_exe("link.exe")
- self.lib = self.find_exe("lib.exe")
- self.rc = self.find_exe("rc.exe") # resource compiler
- self.mc = self.find_exe("mc.exe") # message compiler
- #self.set_path_env_var('lib')
- #self.set_path_env_var('include')
-
- # extend the MSVC path with the current path
- try:
- for p in os.environ['path'].split(';'):
- self.__paths.append(p)
- except KeyError:
- pass
- self.__paths = normalize_and_reduce_paths(self.__paths)
- os.environ['path'] = ";".join(self.__paths)
-
- self.preprocess_options = None
- if self.__arch == "x86":
- self.compile_options = [ '/nologo', '/Ox', '/MD', '/W3',
- '/DNDEBUG']
- self.compile_options_debug = ['/nologo', '/Od', '/MDd', '/W3',
- '/Z7', '/D_DEBUG']
- else:
- # Win64
- self.compile_options = [ '/nologo', '/Ox', '/MD', '/W3', '/GS-' ,
- '/DNDEBUG']
- self.compile_options_debug = ['/nologo', '/Od', '/MDd', '/W3', '/GS-',
- '/Z7', '/D_DEBUG']
-
- self.ldflags_shared = ['/DLL', '/nologo', '/INCREMENTAL:NO']
- if self.__version >= 7:
- self.ldflags_shared_debug = [
- '/DLL', '/nologo', '/INCREMENTAL:no', '/DEBUG', '/pdb:None'
- ]
- self.ldflags_static = [ '/nologo']
-
- self.initialized = True
-
- # -- Worker methods ------------------------------------------------
-
- def object_filenames(self,
- source_filenames,
- strip_dir=0,
- output_dir=''):
- # Copied from ccompiler.py, extended to return .res as 'object'-file
- # for .rc input file
- if output_dir is None: output_dir = ''
- obj_names = []
- for src_name in source_filenames:
- (base, ext) = os.path.splitext (src_name)
- base = os.path.splitdrive(base)[1] # Chop off the drive
- base = base[os.path.isabs(base):] # If abs, chop off leading /
- if ext not in self.src_extensions:
- # Better to raise an exception instead of silently continuing
- # and later complain about sources and targets having
- # different lengths
- raise CompileError ("Don't know how to compile %s" % src_name)
- if strip_dir:
- base = os.path.basename (base)
- if ext in self._rc_extensions:
- obj_names.append (os.path.join (output_dir,
- base + self.res_extension))
- elif ext in self._mc_extensions:
- obj_names.append (os.path.join (output_dir,
- base + self.res_extension))
- else:
- obj_names.append (os.path.join (output_dir,
- base + self.obj_extension))
- return obj_names
-
-
- def compile(self, sources,
- output_dir=None, macros=None, include_dirs=None, debug=0,
- extra_preargs=None, extra_postargs=None, depends=None):
-
- if not self.initialized:
- self.initialize()
- compile_info = self._setup_compile(output_dir, macros, include_dirs,
- sources, depends, extra_postargs)
- macros, objects, extra_postargs, pp_opts, build = compile_info
-
- compile_opts = extra_preargs or []
- compile_opts.append ('/c')
- if debug:
- compile_opts.extend(self.compile_options_debug)
- else:
- compile_opts.extend(self.compile_options)
-
- for obj in objects:
- try:
- src, ext = build[obj]
- except KeyError:
- continue
- if debug:
- # pass the full pathname to MSVC in debug mode,
- # this allows the debugger to find the source file
- # without asking the user to browse for it
- src = os.path.abspath(src)
-
- if ext in self._c_extensions:
- input_opt = "/Tc" + src
- elif ext in self._cpp_extensions:
- input_opt = "/Tp" + src
- elif ext in self._rc_extensions:
- # compile .RC to .RES file
- input_opt = src
- output_opt = "/fo" + obj
- try:
- self.spawn([self.rc] + pp_opts +
- [output_opt] + [input_opt])
- except DistutilsExecError, msg:
- raise CompileError(msg)
- continue
- elif ext in self._mc_extensions:
- # Compile .MC to .RC file to .RES file.
- # * '-h dir' specifies the directory for the
- # generated include file
- # * '-r dir' specifies the target directory of the
- # generated RC file and the binary message resource
- # it includes
- #
- # For now (since there are no options to change this),
- # we use the source-directory for the include file and
- # the build directory for the RC file and message
- # resources. This works at least for win32all.
- h_dir = os.path.dirname(src)
- rc_dir = os.path.dirname(obj)
- try:
- # first compile .MC to .RC and .H file
- self.spawn([self.mc] +
- ['-h', h_dir, '-r', rc_dir] + [src])
- base, _ = os.path.splitext (os.path.basename (src))
- rc_file = os.path.join (rc_dir, base + '.rc')
- # then compile .RC to .RES file
- self.spawn([self.rc] +
- ["/fo" + obj] + [rc_file])
-
- except DistutilsExecError, msg:
- raise CompileError(msg)
- continue
- else:
- # how to handle this file?
- raise CompileError("Don't know how to compile %s to %s"
- % (src, obj))
-
- output_opt = "/Fo" + obj
- try:
- self.spawn([self.cc] + compile_opts + pp_opts +
- [input_opt, output_opt] +
- extra_postargs)
- except DistutilsExecError, msg:
- raise CompileError(msg)
-
- return objects
-
-
- def create_static_lib(self,
- objects,
- output_libname,
- output_dir=None,
- debug=0,
- target_lang=None):
-
- if not self.initialized:
- self.initialize()
- (objects, output_dir) = self._fix_object_args(objects, output_dir)
- output_filename = self.library_filename(output_libname,
- output_dir=output_dir)
-
- if self._need_link(objects, output_filename):
- lib_args = objects + ['/OUT:' + output_filename]
- if debug:
- pass # XXX what goes here?
- try:
- self.spawn([self.lib] + lib_args)
- except DistutilsExecError, msg:
- raise LibError(msg)
- else:
- log.debug("skipping %s (up-to-date)", output_filename)
-
-
- def link(self,
- target_desc,
- objects,
- output_filename,
- output_dir=None,
- libraries=None,
- library_dirs=None,
- runtime_library_dirs=None,
- export_symbols=None,
- debug=0,
- extra_preargs=None,
- extra_postargs=None,
- build_temp=None,
- target_lang=None):
-
- if not self.initialized:
- self.initialize()
- (objects, output_dir) = self._fix_object_args(objects, output_dir)
- fixed_args = self._fix_lib_args(libraries, library_dirs,
- runtime_library_dirs)
- (libraries, library_dirs, runtime_library_dirs) = fixed_args
-
- if runtime_library_dirs:
- self.warn ("I don't know what to do with 'runtime_library_dirs': "
- + str (runtime_library_dirs))
-
- lib_opts = gen_lib_options(self,
- library_dirs, runtime_library_dirs,
- libraries)
- if output_dir is not None:
- output_filename = os.path.join(output_dir, output_filename)
-
- if self._need_link(objects, output_filename):
- if target_desc == CCompiler.EXECUTABLE:
- if debug:
- ldflags = self.ldflags_shared_debug[1:]
- else:
- ldflags = self.ldflags_shared[1:]
- else:
- if debug:
- ldflags = self.ldflags_shared_debug
- else:
- ldflags = self.ldflags_shared
-
- export_opts = []
- for sym in (export_symbols or []):
- export_opts.append("/EXPORT:" + sym)
-
- ld_args = (ldflags + lib_opts + export_opts +
- objects + ['/OUT:' + output_filename])
-
- # The MSVC linker generates .lib and .exp files, which cannot be
- # suppressed by any linker switches. The .lib files may even be
- # needed! Make sure they are generated in the temporary build
- # directory. Since they have different names for debug and release
- # builds, they can go into the same directory.
- build_temp = os.path.dirname(objects[0])
- if export_symbols is not None:
- (dll_name, dll_ext) = os.path.splitext(
- os.path.basename(output_filename))
- implib_file = os.path.join(
- build_temp,
- self.library_filename(dll_name))
- ld_args.append ('/IMPLIB:' + implib_file)
-
- # Embedded manifests are recommended - see MSDN article titled
- # "How to: Embed a Manifest Inside a C/C++ Application"
- # (currently at http://msdn2.microsoft.com/en-us/library/ms235591(VS.80).aspx)
- # Ask the linker to generate the manifest in the temp dir, so
- # we can embed it later.
- temp_manifest = os.path.join(
- build_temp,
- os.path.basename(output_filename) + ".manifest")
- ld_args.append('/MANIFESTFILE:' + temp_manifest)
-
- if extra_preargs:
- ld_args[:0] = extra_preargs
- if extra_postargs:
- ld_args.extend(extra_postargs)
-
- self.mkpath(os.path.dirname(output_filename))
- try:
- self.spawn([self.linker] + ld_args)
- except DistutilsExecError, msg:
- raise LinkError(msg)
-
- # embed the manifest
- # XXX - this is somewhat fragile - if mt.exe fails, distutils
- # will still consider the DLL up-to-date, but it will not have a
- # manifest. Maybe we should link to a temp file? OTOH, that
- # implies a build environment error that shouldn't go undetected.
- if target_desc == CCompiler.EXECUTABLE:
- mfid = 1
- else:
- mfid = 2
- self._remove_visual_c_ref(temp_manifest)
- out_arg = '-outputresource:%s;%s' % (output_filename, mfid)
- try:
- self.spawn(['mt.exe', '-nologo', '-manifest',
- temp_manifest, out_arg])
- except DistutilsExecError, msg:
- raise LinkError(msg)
- else:
- log.debug("skipping %s (up-to-date)", output_filename)
-
- def _remove_visual_c_ref(self, manifest_file):
- try:
- # Remove references to the Visual C runtime, so they will
- # fall through to the Visual C dependency of Python.exe.
- # This way, when installed for a restricted user (e.g.
- # runtimes are not in WinSxS folder, but in Python's own
- # folder), the runtimes do not need to be in every folder
- # with .pyd's.
- manifest_f = open(manifest_file)
- try:
- manifest_buf = manifest_f.read()
- finally:
- manifest_f.close()
- pattern = re.compile(
- r"""<assemblyIdentity.*?name=("|')Microsoft\."""\
- r"""VC\d{2}\.CRT("|').*?(/>|</assemblyIdentity>)""",
- re.DOTALL)
- manifest_buf = re.sub(pattern, "", manifest_buf)
- pattern = "<dependentAssembly>\s*</dependentAssembly>"
- manifest_buf = re.sub(pattern, "", manifest_buf)
- manifest_f = open(manifest_file, 'w')
- try:
- manifest_f.write(manifest_buf)
- finally:
- manifest_f.close()
- except IOError:
- pass
-
- # -- Miscellaneous methods -----------------------------------------
- # These are all used by the 'gen_lib_options() function, in
- # ccompiler.py.
-
- def library_dir_option(self, dir):
- return "/LIBPATH:" + dir
-
- def runtime_library_dir_option(self, dir):
- raise DistutilsPlatformError(
- "don't know how to set runtime library search path for MSVC++")
-
- def library_option(self, lib):
- return self.library_filename(lib)
-
-
- def find_library_file(self, dirs, lib, debug=0):
- # Prefer a debugging library if found (and requested), but deal
- # with it if we don't have one.
- if debug:
- try_names = [lib + "_d", lib]
- else:
- try_names = [lib]
- for dir in dirs:
- for name in try_names:
- libfile = os.path.join(dir, self.library_filename (name))
- if os.path.exists(libfile):
- return libfile
- else:
- # Oops, didn't find it in *any* of 'dirs'
- return None
-
- # Helper methods for using the MSVC registry settings
-
- def find_exe(self, exe):
- """Return path to an MSVC executable program.
-
- Tries to find the program in several places: first, one of the
- MSVC program search paths from the registry; next, the directories
- in the PATH environment variable. If any of those work, return an
- absolute path that is known to exist. If none of them work, just
- return the original program name, 'exe'.
- """
- for p in self.__paths:
- fn = os.path.join(os.path.abspath(p), exe)
- if os.path.isfile(fn):
- return fn
-
- # didn't find it; try existing path
- for p in os.environ['Path'].split(';'):
- fn = os.path.join(os.path.abspath(p),exe)
- if os.path.isfile(fn):
- return fn
-
- return exe
diff --git a/src/distutils2/compiler/msvccompiler.py b/src/distutils2/compiler/msvccompiler.py
deleted file mode 100644
index d2b049f..0000000
--- a/src/distutils2/compiler/msvccompiler.py
+++ /dev/null
@@ -1,659 +0,0 @@
-"""distutils.msvccompiler
-
-Contains MSVCCompiler, an implementation of the abstract CCompiler class
-for the Microsoft Visual Studio.
-"""
-
-# Written by Perry Stoll
-# hacked by Robin Becker and Thomas Heller to do a better job of
-# finding DevStudio (through the registry)
-
-__revision__ = "$Id: msvccompiler.py 76956 2009-12-21 01:22:46Z tarek.ziade $"
-
-import sys
-import os
-import string
-
-from distutils2.errors import (DistutilsExecError, DistutilsPlatformError,
- CompileError, LibError, LinkError)
-from distutils2.compiler.ccompiler import CCompiler, gen_lib_options
-from distutils2 import log
-
-_can_read_reg = 0
-try:
- import _winreg
-
- _can_read_reg = 1
- hkey_mod = _winreg
-
- RegOpenKeyEx = _winreg.OpenKeyEx
- RegEnumKey = _winreg.EnumKey
- RegEnumValue = _winreg.EnumValue
- RegError = _winreg.error
-
-except ImportError:
- try:
- import win32api
- import win32con
- _can_read_reg = 1
- hkey_mod = win32con
-
- RegOpenKeyEx = win32api.RegOpenKeyEx
- RegEnumKey = win32api.RegEnumKey
- RegEnumValue = win32api.RegEnumValue
- RegError = win32api.error
-
- except ImportError:
- log.info("Warning: Can't read registry to find the "
- "necessary compiler setting\n"
- "Make sure that Python modules _winreg, "
- "win32api or win32con are installed.")
- pass
-
-if _can_read_reg:
- HKEYS = (hkey_mod.HKEY_USERS,
- hkey_mod.HKEY_CURRENT_USER,
- hkey_mod.HKEY_LOCAL_MACHINE,
- hkey_mod.HKEY_CLASSES_ROOT)
-
-def read_keys(base, key):
- """Return list of registry keys."""
-
- try:
- handle = RegOpenKeyEx(base, key)
- except RegError:
- return None
- L = []
- i = 0
- while 1:
- try:
- k = RegEnumKey(handle, i)
- except RegError:
- break
- L.append(k)
- i = i + 1
- return L
-
-def read_values(base, key):
- """Return dict of registry keys and values.
-
- All names are converted to lowercase.
- """
- try:
- handle = RegOpenKeyEx(base, key)
- except RegError:
- return None
- d = {}
- i = 0
- while 1:
- try:
- name, value, type = RegEnumValue(handle, i)
- except RegError:
- break
- name = name.lower()
- d[convert_mbcs(name)] = convert_mbcs(value)
- i = i + 1
- return d
-
-def convert_mbcs(s):
- enc = getattr(s, "encode", None)
- if enc is not None:
- try:
- s = enc("mbcs")
- except UnicodeError:
- pass
- return s
-
-class MacroExpander(object):
-
- def __init__(self, version):
- self.macros = {}
- self.load_macros(version)
-
- def set_macro(self, macro, path, key):
- for base in HKEYS:
- d = read_values(base, path)
- if d:
- self.macros["$(%s)" % macro] = d[key]
- break
-
- def load_macros(self, version):
- vsbase = r"Software\Microsoft\VisualStudio\%0.1f" % version
- self.set_macro("VCInstallDir", vsbase + r"\Setup\VC", "productdir")
- self.set_macro("VSInstallDir", vsbase + r"\Setup\VS", "productdir")
- net = r"Software\Microsoft\.NETFramework"
- self.set_macro("FrameworkDir", net, "installroot")
- try:
- if version > 7.0:
- self.set_macro("FrameworkSDKDir", net, "sdkinstallrootv1.1")
- else:
- self.set_macro("FrameworkSDKDir", net, "sdkinstallroot")
- except KeyError:
- raise DistutilsPlatformError, \
- ("""Python was built with Visual Studio 2003;
-extensions must be built with a compiler than can generate compatible binaries.
-Visual Studio 2003 was not found on this system. If you have Cygwin installed,
-you can try compiling with MingW32, by passing "-c mingw32" to setup.py.""")
-
- p = r"Software\Microsoft\NET Framework Setup\Product"
- for base in HKEYS:
- try:
- h = RegOpenKeyEx(base, p)
- except RegError:
- continue
- key = RegEnumKey(h, 0)
- d = read_values(base, r"%s\%s" % (p, key))
- self.macros["$(FrameworkVersion)"] = d["version"]
-
- def sub(self, s):
- for k, v in self.macros.items():
- s = string.replace(s, k, v)
- return s
-
-def get_build_version():
- """Return the version of MSVC that was used to build Python.
-
- For Python 2.3 and up, the version number is included in
- sys.version. For earlier versions, assume the compiler is MSVC 6.
- """
-
- prefix = "MSC v."
- i = string.find(sys.version, prefix)
- if i == -1:
- return 6
- i = i + len(prefix)
- s, rest = sys.version[i:].split(" ", 1)
- majorVersion = int(s[:-2]) - 6
- minorVersion = int(s[2:3]) / 10.0
- # I don't think paths are affected by minor version in version 6
- if majorVersion == 6:
- minorVersion = 0
- if majorVersion >= 6:
- return majorVersion + minorVersion
- # else we don't know what version of the compiler this is
- return None
-
-def get_build_architecture():
- """Return the processor architecture.
-
- Possible results are "Intel", "Itanium", or "AMD64".
- """
-
- prefix = " bit ("
- i = string.find(sys.version, prefix)
- if i == -1:
- return "Intel"
- j = string.find(sys.version, ")", i)
- return sys.version[i+len(prefix):j]
-
-def normalize_and_reduce_paths(paths):
- """Return a list of normalized paths with duplicates removed.
-
- The current order of paths is maintained.
- """
- # Paths are normalized so things like: /a and /a/ aren't both preserved.
- reduced_paths = []
- for p in paths:
- np = os.path.normpath(p)
- # XXX(nnorwitz): O(n**2), if reduced_paths gets long perhaps use a set.
- if np not in reduced_paths:
- reduced_paths.append(np)
- return reduced_paths
-
-
-class MSVCCompiler (CCompiler) :
- """Concrete class that implements an interface to Microsoft Visual C++,
- as defined by the CCompiler abstract class."""
-
- compiler_type = 'msvc'
-
- # Just set this so CCompiler's constructor doesn't barf. We currently
- # don't use the 'set_executables()' bureaucracy provided by CCompiler,
- # as it really isn't necessary for this sort of single-compiler class.
- # Would be nice to have a consistent interface with UnixCCompiler,
- # though, so it's worth thinking about.
- executables = {}
-
- # Private class data (need to distinguish C from C++ source for compiler)
- _c_extensions = ['.c']
- _cpp_extensions = ['.cc', '.cpp', '.cxx']
- _rc_extensions = ['.rc']
- _mc_extensions = ['.mc']
-
- # Needed for the filename generation methods provided by the
- # base class, CCompiler.
- src_extensions = (_c_extensions + _cpp_extensions +
- _rc_extensions + _mc_extensions)
- res_extension = '.res'
- obj_extension = '.obj'
- static_lib_extension = '.lib'
- shared_lib_extension = '.dll'
- static_lib_format = shared_lib_format = '%s%s'
- exe_extension = '.exe'
-
- def __init__ (self, verbose=0, dry_run=0, force=0):
- CCompiler.__init__ (self, verbose, dry_run, force)
- self.__version = get_build_version()
- self.__arch = get_build_architecture()
- if self.__arch == "Intel":
- # x86
- if self.__version >= 7:
- self.__root = r"Software\Microsoft\VisualStudio"
- self.__macros = MacroExpander(self.__version)
- else:
- self.__root = r"Software\Microsoft\Devstudio"
- self.__product = "Visual Studio version %s" % self.__version
- else:
- # Win64. Assume this was built with the platform SDK
- self.__product = "Microsoft SDK compiler %s" % (self.__version + 6)
-
- self.initialized = False
-
- def initialize(self):
- self.__paths = []
- if "DISTUTILS_USE_SDK" in os.environ and "MSSdk" in os.environ and self.find_exe("cl.exe"):
- # Assume that the SDK set up everything alright; don't try to be
- # smarter
- self.cc = "cl.exe"
- self.linker = "link.exe"
- self.lib = "lib.exe"
- self.rc = "rc.exe"
- self.mc = "mc.exe"
- else:
- self.__paths = self.get_msvc_paths("path")
-
- if len (self.__paths) == 0:
- raise DistutilsPlatformError, \
- ("Python was built with %s, "
- "and extensions need to be built with the same "
- "version of the compiler, but it isn't installed." % self.__product)
-
- self.cc = self.find_exe("cl.exe")
- self.linker = self.find_exe("link.exe")
- self.lib = self.find_exe("lib.exe")
- self.rc = self.find_exe("rc.exe") # resource compiler
- self.mc = self.find_exe("mc.exe") # message compiler
- self.set_path_env_var('lib')
- self.set_path_env_var('include')
-
- # extend the MSVC path with the current path
- try:
- for p in string.split(os.environ['path'], ';'):
- self.__paths.append(p)
- except KeyError:
- pass
- self.__paths = normalize_and_reduce_paths(self.__paths)
- os.environ['path'] = string.join(self.__paths, ';')
-
- self.preprocess_options = None
- if self.__arch == "Intel":
- self.compile_options = [ '/nologo', '/Ox', '/MD', '/W3', '/GX' ,
- '/DNDEBUG']
- self.compile_options_debug = ['/nologo', '/Od', '/MDd', '/W3', '/GX',
- '/Z7', '/D_DEBUG']
- else:
- # Win64
- self.compile_options = [ '/nologo', '/Ox', '/MD', '/W3', '/GS-' ,
- '/DNDEBUG']
- self.compile_options_debug = ['/nologo', '/Od', '/MDd', '/W3', '/GS-',
- '/Z7', '/D_DEBUG']
-
- self.ldflags_shared = ['/DLL', '/nologo', '/INCREMENTAL:NO']
- if self.__version >= 7:
- self.ldflags_shared_debug = [
- '/DLL', '/nologo', '/INCREMENTAL:no', '/DEBUG'
- ]
- else:
- self.ldflags_shared_debug = [
- '/DLL', '/nologo', '/INCREMENTAL:no', '/pdb:None', '/DEBUG'
- ]
- self.ldflags_static = [ '/nologo']
-
- self.initialized = True
-
- # -- Worker methods ------------------------------------------------
-
- def object_filenames (self,
- source_filenames,
- strip_dir=0,
- output_dir=''):
- # Copied from ccompiler.py, extended to return .res as 'object'-file
- # for .rc input file
- if output_dir is None: output_dir = ''
- obj_names = []
- for src_name in source_filenames:
- (base, ext) = os.path.splitext (src_name)
- base = os.path.splitdrive(base)[1] # Chop off the drive
- base = base[os.path.isabs(base):] # If abs, chop off leading /
- if ext not in self.src_extensions:
- # Better to raise an exception instead of silently continuing
- # and later complain about sources and targets having
- # different lengths
- raise CompileError ("Don't know how to compile %s" % src_name)
- if strip_dir:
- base = os.path.basename (base)
- if ext in self._rc_extensions:
- obj_names.append (os.path.join (output_dir,
- base + self.res_extension))
- elif ext in self._mc_extensions:
- obj_names.append (os.path.join (output_dir,
- base + self.res_extension))
- else:
- obj_names.append (os.path.join (output_dir,
- base + self.obj_extension))
- return obj_names
-
- # object_filenames ()
-
-
- def compile(self, sources,
- output_dir=None, macros=None, include_dirs=None, debug=0,
- extra_preargs=None, extra_postargs=None, depends=None):
-
- if not self.initialized: self.initialize()
- macros, objects, extra_postargs, pp_opts, build = \
- self._setup_compile(output_dir, macros, include_dirs, sources,
- depends, extra_postargs)
-
- compile_opts = extra_preargs or []
- compile_opts.append ('/c')
- if debug:
- compile_opts.extend(self.compile_options_debug)
- else:
- compile_opts.extend(self.compile_options)
-
- for obj in objects:
- try:
- src, ext = build[obj]
- except KeyError:
- continue
- if debug:
- # pass the full pathname to MSVC in debug mode,
- # this allows the debugger to find the source file
- # without asking the user to browse for it
- src = os.path.abspath(src)
-
- if ext in self._c_extensions:
- input_opt = "/Tc" + src
- elif ext in self._cpp_extensions:
- input_opt = "/Tp" + src
- elif ext in self._rc_extensions:
- # compile .RC to .RES file
- input_opt = src
- output_opt = "/fo" + obj
- try:
- self.spawn ([self.rc] + pp_opts +
- [output_opt] + [input_opt])
- except DistutilsExecError, msg:
- raise CompileError, msg
- continue
- elif ext in self._mc_extensions:
-
- # Compile .MC to .RC file to .RES file.
- # * '-h dir' specifies the directory for the
- # generated include file
- # * '-r dir' specifies the target directory of the
- # generated RC file and the binary message resource
- # it includes
- #
- # For now (since there are no options to change this),
- # we use the source-directory for the include file and
- # the build directory for the RC file and message
- # resources. This works at least for win32all.
-
- h_dir = os.path.dirname (src)
- rc_dir = os.path.dirname (obj)
- try:
- # first compile .MC to .RC and .H file
- self.spawn ([self.mc] +
- ['-h', h_dir, '-r', rc_dir] + [src])
- base, _ = os.path.splitext (os.path.basename (src))
- rc_file = os.path.join (rc_dir, base + '.rc')
- # then compile .RC to .RES file
- self.spawn ([self.rc] +
- ["/fo" + obj] + [rc_file])
-
- except DistutilsExecError, msg:
- raise CompileError, msg
- continue
- else:
- # how to handle this file?
- raise CompileError (
- "Don't know how to compile %s to %s" % \
- (src, obj))
-
- output_opt = "/Fo" + obj
- try:
- self.spawn ([self.cc] + compile_opts + pp_opts +
- [input_opt, output_opt] +
- extra_postargs)
- except DistutilsExecError, msg:
- raise CompileError, msg
-
- return objects
-
- # compile ()
-
-
- def create_static_lib (self,
- objects,
- output_libname,
- output_dir=None,
- debug=0,
- target_lang=None):
-
- if not self.initialized: self.initialize()
- (objects, output_dir) = self._fix_object_args (objects, output_dir)
- output_filename = \
- self.library_filename (output_libname, output_dir=output_dir)
-
- if self._need_link (objects, output_filename):
- lib_args = objects + ['/OUT:' + output_filename]
- if debug:
- pass # XXX what goes here?
- try:
- self.spawn ([self.lib] + lib_args)
- except DistutilsExecError, msg:
- raise LibError, msg
-
- else:
- log.debug("skipping %s (up-to-date)", output_filename)
-
- # create_static_lib ()
-
- def link (self,
- target_desc,
- objects,
- output_filename,
- output_dir=None,
- libraries=None,
- library_dirs=None,
- runtime_library_dirs=None,
- export_symbols=None,
- debug=0,
- extra_preargs=None,
- extra_postargs=None,
- build_temp=None,
- target_lang=None):
-
- if not self.initialized: self.initialize()
- (objects, output_dir) = self._fix_object_args (objects, output_dir)
- (libraries, library_dirs, runtime_library_dirs) = \
- self._fix_lib_args (libraries, library_dirs, runtime_library_dirs)
-
- if runtime_library_dirs:
- self.warn ("I don't know what to do with 'runtime_library_dirs': "
- + str (runtime_library_dirs))
-
- lib_opts = gen_lib_options (self,
- library_dirs, runtime_library_dirs,
- libraries)
- if output_dir is not None:
- output_filename = os.path.join (output_dir, output_filename)
-
- if self._need_link (objects, output_filename):
-
- if target_desc == CCompiler.EXECUTABLE:
- if debug:
- ldflags = self.ldflags_shared_debug[1:]
- else:
- ldflags = self.ldflags_shared[1:]
- else:
- if debug:
- ldflags = self.ldflags_shared_debug
- else:
- ldflags = self.ldflags_shared
-
- export_opts = []
- for sym in (export_symbols or []):
- export_opts.append("/EXPORT:" + sym)
-
- ld_args = (ldflags + lib_opts + export_opts +
- objects + ['/OUT:' + output_filename])
-
- # The MSVC linker generates .lib and .exp files, which cannot be
- # suppressed by any linker switches. The .lib files may even be
- # needed! Make sure they are generated in the temporary build
- # directory. Since they have different names for debug and release
- # builds, they can go into the same directory.
- if export_symbols is not None:
- (dll_name, dll_ext) = os.path.splitext(
- os.path.basename(output_filename))
- implib_file = os.path.join(
- os.path.dirname(objects[0]),
- self.library_filename(dll_name))
- ld_args.append ('/IMPLIB:' + implib_file)
-
- if extra_preargs:
- ld_args[:0] = extra_preargs
- if extra_postargs:
- ld_args.extend(extra_postargs)
-
- self.mkpath (os.path.dirname (output_filename))
- try:
- self.spawn ([self.linker] + ld_args)
- except DistutilsExecError, msg:
- raise LinkError, msg
-
- else:
- log.debug("skipping %s (up-to-date)", output_filename)
-
- # link ()
-
-
- # -- Miscellaneous methods -----------------------------------------
- # These are all used by the 'gen_lib_options() function, in
- # ccompiler.py.
-
- def library_dir_option (self, dir):
- return "/LIBPATH:" + dir
-
- def runtime_library_dir_option (self, dir):
- raise DistutilsPlatformError, \
- "don't know how to set runtime library search path for MSVC++"
-
- def library_option (self, lib):
- return self.library_filename (lib)
-
-
- def find_library_file (self, dirs, lib, debug=0):
- # Prefer a debugging library if found (and requested), but deal
- # with it if we don't have one.
- if debug:
- try_names = [lib + "_d", lib]
- else:
- try_names = [lib]
- for dir in dirs:
- for name in try_names:
- libfile = os.path.join(dir, self.library_filename (name))
- if os.path.exists(libfile):
- return libfile
- else:
- # Oops, didn't find it in *any* of 'dirs'
- return None
-
- # find_library_file ()
-
- # Helper methods for using the MSVC registry settings
-
- def find_exe(self, exe):
- """Return path to an MSVC executable program.
-
- Tries to find the program in several places: first, one of the
- MSVC program search paths from the registry; next, the directories
- in the PATH environment variable. If any of those work, return an
- absolute path that is known to exist. If none of them work, just
- return the original program name, 'exe'.
- """
-
- for p in self.__paths:
- fn = os.path.join(os.path.abspath(p), exe)
- if os.path.isfile(fn):
- return fn
-
- # didn't find it; try existing path
- for p in string.split(os.environ['Path'],';'):
- fn = os.path.join(os.path.abspath(p),exe)
- if os.path.isfile(fn):
- return fn
-
- return exe
-
- def get_msvc_paths(self, path, platform='x86'):
- """Get a list of devstudio directories (include, lib or path).
-
- Return a list of strings. The list will be empty if unable to
- access the registry or appropriate registry keys not found.
- """
-
- if not _can_read_reg:
- return []
-
- path = path + " dirs"
- if self.__version >= 7:
- key = (r"%s\%0.1f\VC\VC_OBJECTS_PLATFORM_INFO\Win32\Directories"
- % (self.__root, self.__version))
- else:
- key = (r"%s\6.0\Build System\Components\Platforms"
- r"\Win32 (%s)\Directories" % (self.__root, platform))
-
- for base in HKEYS:
- d = read_values(base, key)
- if d:
- if self.__version >= 7:
- return string.split(self.__macros.sub(d[path]), ";")
- else:
- return string.split(d[path], ";")
- # MSVC 6 seems to create the registry entries we need only when
- # the GUI is run.
- if self.__version == 6:
- for base in HKEYS:
- if read_values(base, r"%s\6.0" % self.__root) is not None:
- self.warn("It seems you have Visual Studio 6 installed, "
- "but the expected registry settings are not present.\n"
- "You must at least run the Visual Studio GUI once "
- "so that these entries are created.")
- break
- return []
-
- def set_path_env_var(self, name):
- """Set environment variable 'name' to an MSVC path type value.
-
- This is equivalent to a SET command prior to execution of spawned
- commands.
- """
-
- if name == "lib":
- p = self.get_msvc_paths("library")
- else:
- p = self.get_msvc_paths(name)
- if p:
- os.environ[name] = string.join(p, ';')
-
-
-if get_build_version() >= 8.0:
- log.debug("Importing new compiler from distutils.msvc9compiler")
- OldMSVCCompiler = MSVCCompiler
- from distutils2.msvc9compiler import MSVCCompiler
- # get_build_architecture not really relevant now we support cross-compile
- from distutils2.msvc9compiler import MacroExpander
diff --git a/src/distutils2/compiler/unixccompiler.py b/src/distutils2/compiler/unixccompiler.py
deleted file mode 100644
index 7e52959..0000000
--- a/src/distutils2/compiler/unixccompiler.py
+++ /dev/null
@@ -1,345 +0,0 @@
-"""distutils.unixccompiler
-
-Contains the UnixCCompiler class, a subclass of CCompiler that handles
-the "typical" Unix-style command-line C compiler:
- * macros defined with -Dname[=value]
- * macros undefined with -Uname
- * include search directories specified with -Idir
- * libraries specified with -lllib
- * library search directories specified with -Ldir
- * compile handled by 'cc' (or similar) executable with -c option:
- compiles .c to .o
- * link static library handled by 'ar' command (possibly with 'ranlib')
- * link shared library handled by 'cc -shared'
-"""
-
-__revision__ = "$Id: unixccompiler.py 77704 2010-01-23 09:23:15Z tarek.ziade $"
-
-import os, sys
-from types import StringType, NoneType
-
-from distutils2.util import newer
-from distutils2.compiler.ccompiler import (CCompiler, gen_preprocess_options,
- gen_lib_options)
-from distutils2.errors import (DistutilsExecError, CompileError,
- LibError, LinkError)
-from distutils2 import log
-
-try:
- import sysconfig
-except ImportError:
- from distutils2._backport import sysconfig
-
-
-# XXX Things not currently handled:
-# * optimization/debug/warning flags; we just use whatever's in Python's
-# Makefile and live with it. Is this adequate? If not, we might
-# have to have a bunch of subclasses GNUCCompiler, SGICCompiler,
-# SunCCompiler, and I suspect down that road lies madness.
-# * even if we don't know a warning flag from an optimization flag,
-# we need some way for outsiders to feed preprocessor/compiler/linker
-# flags in to us -- eg. a sysadmin might want to mandate certain flags
-# via a site config file, or a user might want to set something for
-# compiling this module distribution only via the setup.py command
-# line, whatever. As long as these options come from something on the
-# current system, they can be as system-dependent as they like, and we
-# should just happily stuff them into the preprocessor/compiler/linker
-# options and carry on.
-
-def _darwin_compiler_fixup(compiler_so, cc_args):
- """
- This function will strip '-isysroot PATH' and '-arch ARCH' from the
- compile flags if the user has specified one them in extra_compile_flags.
-
- This is needed because '-arch ARCH' adds another architecture to the
- build, without a way to remove an architecture. Furthermore GCC will
- barf if multiple '-isysroot' arguments are present.
- """
- stripArch = stripSysroot = 0
-
- compiler_so = list(compiler_so)
- kernel_version = os.uname()[2] # 8.4.3
- major_version = int(kernel_version.split('.')[0])
-
- if major_version < 8:
- # OSX before 10.4.0, these don't support -arch and -isysroot at
- # all.
- stripArch = stripSysroot = True
- else:
- stripArch = '-arch' in cc_args
- stripSysroot = '-isysroot' in cc_args
-
- if stripArch or 'ARCHFLAGS' in os.environ:
- while 1:
- try:
- index = compiler_so.index('-arch')
- # Strip this argument and the next one:
- del compiler_so[index:index+2]
- except ValueError:
- break
-
- if 'ARCHFLAGS' in os.environ and not stripArch:
- # User specified different -arch flags in the environ,
- # see also the sysconfig
- compiler_so = compiler_so + os.environ['ARCHFLAGS'].split()
-
- if stripSysroot:
- try:
- index = compiler_so.index('-isysroot')
- # Strip this argument and the next one:
- del compiler_so[index:index+2]
- except ValueError:
- pass
-
- # Check if the SDK that is used during compilation actually exists,
- # the universal build requires the usage of a universal SDK and not all
- # users have that installed by default.
- sysroot = None
- if '-isysroot' in cc_args:
- idx = cc_args.index('-isysroot')
- sysroot = cc_args[idx+1]
- elif '-isysroot' in compiler_so:
- idx = compiler_so.index('-isysroot')
- sysroot = compiler_so[idx+1]
-
- if sysroot and not os.path.isdir(sysroot):
- log.warn("Compiling with an SDK that doesn't seem to exist: %s",
- sysroot)
- log.warn("Please check your Xcode installation")
-
- return compiler_so
-
-class UnixCCompiler(CCompiler):
-
- compiler_type = 'unix'
-
- # These are used by CCompiler in two places: the constructor sets
- # instance attributes 'preprocessor', 'compiler', etc. from them, and
- # 'set_executable()' allows any of these to be set. The defaults here
- # are pretty generic; they will probably have to be set by an outsider
- # (eg. using information discovered by the sysconfig about building
- # Python extensions).
- executables = {'preprocessor' : None,
- 'compiler' : ["cc"],
- 'compiler_so' : ["cc"],
- 'compiler_cxx' : ["cc"],
- 'linker_so' : ["cc", "-shared"],
- 'linker_exe' : ["cc"],
- 'archiver' : ["ar", "-cr"],
- 'ranlib' : None,
- }
-
- if sys.platform[:6] == "darwin":
- executables['ranlib'] = ["ranlib"]
-
- # Needed for the filename generation methods provided by the base
- # class, CCompiler. NB. whoever instantiates/uses a particular
- # UnixCCompiler instance should set 'shared_lib_ext' -- we set a
- # reasonable common default here, but it's not necessarily used on all
- # Unices!
-
- src_extensions = [".c",".C",".cc",".cxx",".cpp",".m"]
- obj_extension = ".o"
- static_lib_extension = ".a"
- shared_lib_extension = ".so"
- dylib_lib_extension = ".dylib"
- static_lib_format = shared_lib_format = dylib_lib_format = "lib%s%s"
- if sys.platform == "cygwin":
- exe_extension = ".exe"
-
- def preprocess(self, source,
- output_file=None, macros=None, include_dirs=None,
- extra_preargs=None, extra_postargs=None):
- ignore, macros, include_dirs = \
- self._fix_compile_args(None, macros, include_dirs)
- pp_opts = gen_preprocess_options(macros, include_dirs)
- pp_args = self.preprocessor + pp_opts
- if output_file:
- pp_args.extend(['-o', output_file])
- if extra_preargs:
- pp_args[:0] = extra_preargs
- if extra_postargs:
- pp_args.extend(extra_postargs)
- pp_args.append(source)
-
- # We need to preprocess: either we're being forced to, or we're
- # generating output to stdout, or there's a target output file and
- # the source file is newer than the target (or the target doesn't
- # exist).
- if self.force or output_file is None or newer(source, output_file):
- if output_file:
- self.mkpath(os.path.dirname(output_file))
- try:
- self.spawn(pp_args)
- except DistutilsExecError, msg:
- raise CompileError, msg
-
- def _compile(self, obj, src, ext, cc_args, extra_postargs, pp_opts):
- compiler_so = self.compiler_so
- if sys.platform == 'darwin':
- compiler_so = _darwin_compiler_fixup(compiler_so, cc_args + extra_postargs)
- try:
- self.spawn(compiler_so + cc_args + [src, '-o', obj] +
- extra_postargs)
- except DistutilsExecError, msg:
- raise CompileError, msg
-
- def create_static_lib(self, objects, output_libname,
- output_dir=None, debug=0, target_lang=None):
- objects, output_dir = self._fix_object_args(objects, output_dir)
-
- output_filename = \
- self.library_filename(output_libname, output_dir=output_dir)
-
- if self._need_link(objects, output_filename):
- self.mkpath(os.path.dirname(output_filename))
- self.spawn(self.archiver +
- [output_filename] +
- objects + self.objects)
-
- # Not many Unices required ranlib anymore -- SunOS 4.x is, I
- # think the only major Unix that does. Maybe we need some
- # platform intelligence here to skip ranlib if it's not
- # needed -- or maybe Python's configure script took care of
- # it for us, hence the check for leading colon.
- if self.ranlib:
- try:
- self.spawn(self.ranlib + [output_filename])
- except DistutilsExecError, msg:
- raise LibError, msg
- else:
- log.debug("skipping %s (up-to-date)", output_filename)
-
- def link(self, target_desc, objects,
- output_filename, output_dir=None, libraries=None,
- library_dirs=None, runtime_library_dirs=None,
- export_symbols=None, debug=0, extra_preargs=None,
- extra_postargs=None, build_temp=None, target_lang=None):
- objects, output_dir = self._fix_object_args(objects, output_dir)
- libraries, library_dirs, runtime_library_dirs = \
- self._fix_lib_args(libraries, library_dirs, runtime_library_dirs)
-
- lib_opts = gen_lib_options(self, library_dirs, runtime_library_dirs,
- libraries)
- if type(output_dir) not in (StringType, NoneType):
- raise TypeError, "'output_dir' must be a string or None"
- if output_dir is not None:
- output_filename = os.path.join(output_dir, output_filename)
-
- if self._need_link(objects, output_filename):
- ld_args = (objects + self.objects +
- lib_opts + ['-o', output_filename])
- if debug:
- ld_args[:0] = ['-g']
- if extra_preargs:
- ld_args[:0] = extra_preargs
- if extra_postargs:
- ld_args.extend(extra_postargs)
- self.mkpath(os.path.dirname(output_filename))
- try:
- if target_desc == CCompiler.EXECUTABLE:
- linker = self.linker_exe[:]
- else:
- linker = self.linker_so[:]
- if target_lang == "c++" and self.compiler_cxx:
- # skip over environment variable settings if /usr/bin/env
- # is used to set up the linker's environment.
- # This is needed on OSX. Note: this assumes that the
- # normal and C++ compiler have the same environment
- # settings.
- i = 0
- if os.path.basename(linker[0]) == "env":
- i = 1
- while '=' in linker[i]:
- i = i + 1
-
- linker[i] = self.compiler_cxx[i]
-
- if sys.platform == 'darwin':
- linker = _darwin_compiler_fixup(linker, ld_args)
-
- self.spawn(linker + ld_args)
- except DistutilsExecError, msg:
- raise LinkError, msg
- else:
- log.debug("skipping %s (up-to-date)", output_filename)
-
- # -- Miscellaneous methods -----------------------------------------
- # These are all used by the 'gen_lib_options() function, in
- # ccompiler.py.
-
- def library_dir_option(self, dir):
- return "-L" + dir
-
- def _is_gcc(self, compiler_name):
- return "gcc" in compiler_name or "g++" in compiler_name
-
- def runtime_library_dir_option(self, dir):
- # XXX Hackish, at the very least. See Python bug #445902:
- # http://sourceforge.net/tracker/index.php
- # ?func=detail&aid=445902&group_id=5470&atid=105470
- # Linkers on different platforms need different options to
- # specify that directories need to be added to the list of
- # directories searched for dependencies when a dynamic library
- # is sought. GCC on GNU systems (Linux, FreeBSD, ...) has to
- # be told to pass the -R option through to the linker, whereas
- # other compilers and gcc on other systems just know this.
- # Other compilers may need something slightly different. At
- # this time, there's no way to determine this information from
- # the configuration data stored in the Python installation, so
- # we use this hack.
-
- compiler = os.path.basename(sysconfig.get_config_var("CC"))
- if sys.platform[:6] == "darwin":
- # MacOSX's linker doesn't understand the -R flag at all
- return "-L" + dir
- elif sys.platform[:5] == "hp-ux":
- if self._is_gcc(compiler):
- return ["-Wl,+s", "-L" + dir]
- return ["+s", "-L" + dir]
- elif sys.platform[:7] == "irix646" or sys.platform[:6] == "osf1V5":
- return ["-rpath", dir]
- elif self._is_gcc(compiler):
- # gcc on non-GNU systems does not need -Wl, but can
- # use it anyway. Since distutils has always passed in
- # -Wl whenever gcc was used in the past it is probably
- # safest to keep doing so.
- if sysconfig.get_config_var("GNULD") == "yes":
- # GNU ld needs an extra option to get a RUNPATH
- # instead of just an RPATH.
- return "-Wl,--enable-new-dtags,-R" + dir
- else:
- return "-Wl,-R" + dir
- elif sys.platform[:3] == "aix":
- return "-blibpath:" + dir
- else:
- # No idea how --enable-new-dtags would be passed on to
- # ld if this system was using GNU ld. Don't know if a
- # system like this even exists.
- return "-R" + dir
-
- def library_option(self, lib):
- return "-l" + lib
-
- def find_library_file(self, dirs, lib, debug=0):
- shared_f = self.library_filename(lib, lib_type='shared')
- dylib_f = self.library_filename(lib, lib_type='dylib')
- static_f = self.library_filename(lib, lib_type='static')
-
- for dir in dirs:
- shared = os.path.join(dir, shared_f)
- dylib = os.path.join(dir, dylib_f)
- static = os.path.join(dir, static_f)
- # We're second-guessing the linker here, with not much hard
- # data to go on: GCC seems to prefer the shared library, so I'm
- # assuming that *all* Unix C compilers do. And of course I'm
- # ignoring even GCC's "-static" option. So sue me.
- if os.path.exists(dylib):
- return dylib
- elif os.path.exists(shared):
- return shared
- elif os.path.exists(static):
- return static
-
- # Oops, didn't find it in *any* of 'dirs'
- return None
diff --git a/src/distutils2/converter/__init__.py b/src/distutils2/converter/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/src/distutils2/converter/__init__.py
+++ /dev/null
diff --git a/src/distutils2/converter/fixers/__init__.py b/src/distutils2/converter/fixers/__init__.py
deleted file mode 100644
index cd6acf4..0000000
--- a/src/distutils2/converter/fixers/__init__.py
+++ /dev/null
@@ -1,4 +0,0 @@
-"""distutils2.converter.fixers
-
-Contains all fixers for the converter.
-"""
diff --git a/src/distutils2/converter/fixers/fix_imports.py b/src/distutils2/converter/fixers/fix_imports.py
deleted file mode 100644
index 38d185e..0000000
--- a/src/distutils2/converter/fixers/fix_imports.py
+++ /dev/null
@@ -1,52 +0,0 @@
-"""distutils2.converter.fixers.fix_imports
-
-Fixer for import statements in setup.py
-"""
-from lib2to3.fixer_base import BaseFix
-from lib2to3.fixer_util import syms
-
-
-class FixImports(BaseFix):
- """Makes sure all import in setup.py are translated"""
-
- PATTERN = """
- import_from< 'from' imp=any 'import' ['('] any [')'] >
- |
- import_name< 'import' imp=any >
- """
-
- def transform(self, node, results):
- imp = results['imp']
- if node.type != syms.import_from:
- return
-
- if not hasattr(imp, "next_sibling"):
- imp.next_sibling = imp.get_next_sibling()
-
- while not hasattr(imp, 'value'):
- imp = imp.children[0]
-
- if imp.value == 'distutils':
- imp.value = 'distutils2'
- imp.changed()
- return node
-
- if imp.value == 'setuptools':
- # catching "from setuptools import setup"
- pattern = []
- next = imp.next_sibling
- while next is not None:
- # Get the first child if we have a Node
- if not hasattr(next, "value"):
- next = next.children[0]
- pattern.append(next.value)
- if not hasattr(next, "next_sibling"):
- next.next_sibling = next.get_next_sibling()
- next = next.next_sibling
-
- if set(pattern).issubset(set(
- ['import', ',', 'setup', 'find_packages'])):
- imp.value = 'distutils2.core'
- imp.changed()
-
- return node
diff --git a/src/distutils2/converter/fixers/fix_setup_options.py b/src/distutils2/converter/fixers/fix_setup_options.py
deleted file mode 100644
index 7d319fb..0000000
--- a/src/distutils2/converter/fixers/fix_setup_options.py
+++ /dev/null
@@ -1,85 +0,0 @@
-"""Fixer for setup() options.
-
-All distutils or setuptools options are translated
-into PEP 345-style options.
-"""
-from lib2to3.pytree import Leaf, Node
-from lib2to3.pgen2 import token
-from lib2to3.fixer_base import BaseFix
-
-# XXX where is that defined ?
-_ARG = 260
-
-# name mapping : we want to convert
-# all old-style options to distutils2 style
-_OLD_NAMES = {'url': 'home_page',
- 'long_description': 'description',
- 'description': 'summary',
- 'install_requires': 'requires_dist'}
-
-_SEQUENCE_NAMES = ['requires_dist']
-
-
-class FixSetupOptions(BaseFix):
-
- # XXX need to find something better here :
- # identify a setup call, whatever alias is used
- PATTERN = """
- power< name='setup' trailer< '(' [any] ')' > any* >
- """
-
- def _get_list(self, *nodes):
- """A List node, filled"""
- lbrace = Leaf(token.LBRACE, u"[")
- lbrace.prefix = u" "
- if len(nodes) > 0:
- nodes[0].prefix = u""
- return Node(self.syms.trailer,
- [lbrace] +
- [node.clone() for node in nodes] +
- [Leaf(token.RBRACE, u"]")])
-
- def _fix_name(self, argument, remove_list):
- name = argument.children[0]
-
- if not hasattr(name, "next_sibling"):
- name.next_sibling = name.get_next_sibling()
-
- sibling = name.next_sibling
- if sibling is None or sibling.type != token.EQUAL:
- return False
-
- if name.value in _OLD_NAMES:
- name.value = _OLD_NAMES[name.value]
- if name.value in _SEQUENCE_NAMES:
- if not hasattr(sibling, "next_sibling"):
- sibling.next_sibling = sibling.get_next_sibling()
- right_operand = sibling.next_sibling
- # replacing string -> list[string]
- if right_operand.type == token.STRING:
- # we want this to be a list now
- new_node = self._get_list(right_operand)
- right_operand.replace(new_node)
-
-
- return True
-
- return False
-
- def transform(self, node, results):
- arglist = node.children[1].children[1]
- remove_list = []
- changed = False
-
- for subnode in arglist.children:
- if subnode.type != _ARG:
- continue
- if self._fix_name(subnode, remove_list) and not changed:
- changed = True
-
- for subnode in remove_list:
- subnode.remove()
-
- if changed:
- node.changed()
- return node
diff --git a/src/distutils2/converter/refactor.py b/src/distutils2/converter/refactor.py
deleted file mode 100644
index 28fbd44..0000000
--- a/src/distutils2/converter/refactor.py
+++ /dev/null
@@ -1,12 +0,0 @@
-"""distutils2.converter.refactor
-
-"""
-try:
- from lib2to3.refactor import RefactoringTool
- _LIB2TO3 = True
-except ImportError:
- # we need 2.6 at least to run this
- _LIB2TO3 = False
-
-_DISTUTILS_FIXERS = ['distutils2.converter.fixers.fix_imports',
- 'distutils2.converter.fixers.fix_setup_options'] \ No newline at end of file
diff --git a/src/distutils2/core.py b/src/distutils2/core.py
deleted file mode 100644
index 2a76a70..0000000
--- a/src/distutils2/core.py
+++ /dev/null
@@ -1,219 +0,0 @@
-"""distutils2.core
-
-The only module that needs to be imported to use the Distutils; provides
-the 'setup' function (which is to be called from the setup script). Also
-exports useful classes so that setup scripts can import them from here
-although they are really defined in other modules: Distribution, Command,
-PyPIRCommand, Extension, find_packages.
-"""
-
-__revision__ = "$Id: core.py 77704 2010-01-23 09:23:15Z tarek.ziade $"
-
-import sys
-import os
-
-from distutils2.errors import (DistutilsSetupError, DistutilsArgError,
- DistutilsError, CCompilerError)
-from distutils2.util import grok_environment_error
-
-# Mainly import these so setup scripts can "from distutils2.core import" them.
-from distutils2.dist import Distribution
-from distutils2.command.cmd import Command
-from distutils2.extension import Extension
-from distutils2.util import find_packages
-
-# This is a barebones help message generated displayed when the user
-# runs the setup script with no arguments at all. More useful help
-# is generated with various --help options: global help, list commands,
-# and per-command help.
-USAGE = """\
-usage: %(script)s [global_opts] cmd1 [cmd1_opts] [cmd2 [cmd2_opts] ...]
- or: %(script)s --help [cmd1 cmd2 ...]
- or: %(script)s --help-commands
- or: %(script)s cmd --help
-"""
-
-
-def gen_usage(script_name):
- script = os.path.basename(script_name)
- return USAGE % {'script': script}
-
-
-# Some mild magic to control the behaviour of 'setup()' from 'run_setup()'.
-_setup_stop_after = None
-_setup_distribution = None
-
-# Legal keyword arguments for the setup() function
-setup_keywords = ('distclass', 'script_name', 'script_args', 'options',
- 'name', 'version', 'author', 'author_email',
- 'maintainer', 'maintainer_email', 'url', 'license',
- 'description', 'long_description', 'keywords',
- 'platforms', 'classifiers', 'download_url',
- 'requires', 'provides', 'obsoletes', 'use_2to3_fixers',
- 'convert_2to3_doctests', 'use_2to3_fixers'
- )
-
-# Legal keyword arguments for the Extension constructor
-extension_keywords = ('name', 'sources', 'include_dirs',
- 'define_macros', 'undef_macros',
- 'library_dirs', 'libraries', 'runtime_library_dirs',
- 'extra_objects', 'extra_compile_args', 'extra_link_args',
- 'swig_opts', 'export_symbols', 'depends', 'language')
-
-
-def setup(**attrs):
- """The gateway to the Distutils: do everything your setup script needs
- to do, in a highly flexible and user-driven way. Briefly: create a
- Distribution instance; find and parse config files; parse the command
- line; run each Distutils command found there, customized by the options
- supplied to 'setup()' (as keyword arguments), in config files, and on
- the command line.
-
- The Distribution instance might be an instance of a class supplied via
- the 'distclass' keyword argument to 'setup'; if no such class is
- supplied, then the Distribution class (in dist.py) is instantiated.
- All other arguments to 'setup' (except for 'cmdclass') are used to set
- attributes of the Distribution instance.
-
- The 'cmdclass' argument, if supplied, is a dictionary mapping command
- names to command classes. Each command encountered on the command line
- will be turned into a command class, which is in turn instantiated; any
- class found in 'cmdclass' is used in place of the default, which is
- (for command 'foo_bar') class 'foo_bar' in module
- 'distutils2.command.foo_bar'. The command class must provide a
- 'user_options' attribute which is a list of option specifiers for
- 'distutils2.fancy_getopt'. Any command-line options between the current
- and the next command are used to set attributes of the current command
- object.
-
- When the entire command line has been successfully parsed, calls the
- 'run()' method on each command object in turn. This method will be
- driven entirely by the Distribution object (which each command object
- has a reference to, thanks to its constructor), and the
- command-specific options that became attributes of each command
- object.
- """
-
- global _setup_stop_after, _setup_distribution
-
- # Determine the distribution class -- either caller-supplied or
- # our Distribution (see below).
- distclass = attrs.pop('distclass', Distribution)
-
- if 'script_name' not in attrs:
- attrs['script_name'] = os.path.basename(sys.argv[0])
- if 'script_args' not in attrs:
- attrs['script_args'] = sys.argv[1:]
-
- # Create the Distribution instance, using the remaining arguments
- # (ie. everything except distclass) to initialize it
- try:
- _setup_distribution = dist = distclass(attrs)
- except DistutilsSetupError, msg:
- if 'name' in attrs:
- raise SystemExit, "error in %s setup command: %s" % \
- (attrs['name'], msg)
- else:
- raise SystemExit, "error in setup command: %s" % msg
-
- if _setup_stop_after == "init":
- return dist
-
- # Find and parse the config file(s): they will override options from
- # the setup script, but be overridden by the command line.
- dist.parse_config_files()
-
- if _setup_stop_after == "config":
- return dist
-
- # Parse the command line and override config files; any
- # command line errors are the end user's fault, so turn them into
- # SystemExit to suppress tracebacks.
- try:
- ok = dist.parse_command_line()
- except DistutilsArgError, msg:
- raise SystemExit, gen_usage(dist.script_name) + "\nerror: %s" % msg
-
- if _setup_stop_after == "commandline":
- return dist
-
- # And finally, run all the commands found on the command line.
- if ok:
- try:
- dist.run_commands()
- except KeyboardInterrupt:
- raise SystemExit, "interrupted"
- except (IOError, os.error), exc:
- error = grok_environment_error(exc)
- raise SystemExit, error
-
- except (DistutilsError,
- CCompilerError), msg:
- raise SystemExit, "error: " + str(msg)
-
- return dist
-
-
-def run_setup(script_name, script_args=None, stop_after="run"):
- """Run a setup script in a somewhat controlled environment, and
- return the Distribution instance that drives things. This is useful
- if you need to find out the distribution metadata (passed as
- keyword args from 'script' to 'setup()', or the contents of the
- config files or command line.
-
- 'script_name' is a file that will be run with 'execfile()';
- 'sys.argv[0]' will be replaced with 'script' for the duration of the
- call. 'script_args' is a list of strings; if supplied,
- 'sys.argv[1:]' will be replaced by 'script_args' for the duration of
- the call.
-
- 'stop_after' tells 'setup()' when to stop processing; possible
- values:
- init
- stop after the Distribution instance has been created and
- populated with the keyword arguments to 'setup()'
- config
- stop after config files have been parsed (and their data
- stored in the Distribution instance)
- commandline
- stop after the command line ('sys.argv[1:]' or 'script_args')
- has been parsed (and the data stored in the Distribution)
- run [default]
- stop after all commands have been run (the same as if 'setup()'
- had been called in the usual way
-
- Returns the Distribution instance, which provides all information
- used to drive the Distutils.
- """
- if stop_after not in ('init', 'config', 'commandline', 'run'):
- raise ValueError, "invalid value for 'stop_after': %r" % (stop_after,)
-
- global _setup_stop_after, _setup_distribution
- _setup_stop_after = stop_after
-
- save_argv = sys.argv
- g = {'__file__': script_name}
- l = {}
- try:
- try:
- sys.argv[0] = script_name
- if script_args is not None:
- sys.argv[1:] = script_args
- exec open(script_name, 'r').read() in g, l
- finally:
- sys.argv = save_argv
- _setup_stop_after = None
- except SystemExit:
- # Hmm, should we do something if exiting with a non-zero code
- # (ie. error)?
- pass
-
- if _setup_distribution is None:
- raise RuntimeError, \
- ("'distutils2.core.setup()' was never called -- "
- "perhaps '%s' is not a Distutils setup script?") % \
- script_name
-
- # I wonder if the setup script's namespace -- g and l -- would be of
- # any interest to callers?
- return _setup_distribution
diff --git a/src/distutils2/depgraph.py b/src/distutils2/depgraph.py
deleted file mode 100644
index 2d66a39..0000000
--- a/src/distutils2/depgraph.py
+++ /dev/null
@@ -1,188 +0,0 @@
-"""Analyse the relationships between the distributions in the system
-and generate a dependency graph.
-"""
-
-from distutils2.errors import DistutilsError
-from distutils2.version import VersionPredicate
-
-__all__ = ['DependencyGraph', 'generate_graph', 'dependent_dists',
- 'graph_to_dot']
-
-
-class DependencyGraph(object):
- """
- Represents a dependency graph between distributions.
-
- The dependency relationships are stored in an ``adjacency_list`` that maps
- distributions to a list of ``(other, label)`` tuples where ``other``
- is a distribution and the edge is labelled with ``label`` (i.e. the version
- specifier, if such was provided). Also, for more efficient traversal, for
- every distribution ``x``, a list of predecessors is kept in
- ``reverse_list[x]``. An edge from distribution ``a`` to
- distribution ``b`` means that ``a`` depends on ``b``. If any missing
- depencies are found, they are stored in ``missing``, which is a dictionary
- that maps distributions to a list of requirements that were not provided by
- any other distributions.
- """
-
- def __init__(self):
- self.adjacency_list = {}
- self.reverse_list = {}
- self.missing = {}
-
- def add_distribution(self, distribution):
- """Add the *distribution* to the graph.
-
- :type distribution: :class:`pkgutil.Distribution` or
- :class:`pkgutil.EggInfoDistribution`
- """
- self.adjacency_list[distribution] = list()
- self.reverse_list[distribution] = list()
- self.missing[distribution] = list()
-
- def add_edge(self, x, y, label=None):
- """Add an edge from distribution *x* to distribution *y* with the given
- *label*.
-
- :type x: :class:`pkgutil.Distribution` or
- :class:`pkgutil.EggInfoDistribution`
- :type y: :class:`pkgutil.Distribution` or
- :class:`pkgutil.EggInfoDistribution`
- :type label: ``str`` or ``None``
- """
- self.adjacency_list[x].append((y, label))
- # multiple edges are allowed, so be careful
- if not x in self.reverse_list[y]:
- self.reverse_list[y].append(x)
-
- def add_missing(self, distribution, requirement):
- """
- Add a missing *requirement* for the given *distribution*.
-
- :type distribution: :class:`pkgutil.Distribution` or
- :class:`pkgutil.EggInfoDistribution`
- :type requirement: ``str``
- """
- self.missing[distribution].append(requirement)
-
-
-def graph_to_dot(graph, f, skip_disconnected=True):
- """Writes a DOT output for the graph to the provided file *f*.
-
- If *skip_disconnected* is set to ``True``, then all distributions
- that are not dependent on any other distribution are skipped.
-
- :type f: has to support ``file``-like operations
- :type skip_disconnected: ``bool``
- """
- disconnected = []
-
- f.write("digraph dependencies {\n")
- for dist, adjs in graph.adjacency_list.iteritems():
- if len(adjs) == 0 and not skip_disconnected:
- disconnected.append(dist)
- for (other, label) in adjs:
- if not label is None:
- f.write('"%s" -> "%s" [label="%s"]\n' %
- (dist.name, other.name, label))
- else:
- f.write('"%s" -> "%s"\n' % (dist.name, other.name))
- if not skip_disconnected and len(disconnected) > 0:
- f.write('subgraph disconnected {\n')
- f.write('label = "Disconnected"\n')
- f.write('bgcolor = red\n')
-
- for dist in disconnected:
- f.write('"%s"' % dist.name)
- f.write('\n')
- f.write('}\n')
- f.write('}\n')
-
-
-def generate_graph(dists):
- """Generates a dependency graph from the given distributions.
-
- :parameter dists: a list of distributions
- :type dists: list of :class:`pkgutil.Distribution` and
- :class:`pkgutil.EggInfoDistribution` instances
- :rtype: an :class:`DependencyGraph` instance
- """
- graph = DependencyGraph()
- provided = {} # maps names to lists of (version, dist) tuples
- dists = list(dists) # maybe use generator_tools in future
-
- # first, build the graph and find out the provides
- for dist in dists:
- graph.add_distribution(dist)
- provides = dist.metadata['Provides-Dist'] + dist.metadata['Provides']
-
- for p in provides:
- comps = p.strip().rsplit(" ", 1)
- name = comps[0]
- version = None
- if len(comps) == 2:
- version = comps[1]
- if len(version) < 3 or version[0] != '(' or version[-1] != ')':
- raise DistutilsError('Distribution %s has ill formed' \
- 'provides field: %s' % (dist.name, p))
- version = version[1:-1] # trim off parenthesis
- if not name in provided:
- provided[name] = []
- provided[name].append((version, dist))
-
- # now make the edges
- for dist in dists:
- requires = dist.metadata['Requires-Dist'] + dist.metadata['Requires']
- for req in requires:
- predicate = VersionPredicate(req)
- name = predicate.name
-
- if not name in provided:
- graph.add_missing(dist, req)
- else:
- matched = False
- for (version, provider) in provided[name]:
- if predicate.match(version):
- graph.add_edge(dist, provider, req)
- matched = True
- break
- if not matched:
- graph.add_missing(dist, req)
-
- return graph
-
-
-def dependent_dists(dists, dist):
- """Recursively generate a list of distributions from *dists* that are
- dependent on *dist*.
-
- :param dists: a list of distributions
- :param dist: a distribution, member of *dists* for which we are interested
- """
- if not dist in dists:
- raise ValueError('The given distribution is not a member of the list')
- graph = generate_graph(dists)
-
- dep = [dist] # dependent distributions
- fringe = graph.reverse_list[dist] # list of nodes we should inspect
-
- while not len(fringe) == 0:
- node = fringe.pop()
- dep.append(node)
- for prev in graph.reverse_list[node]:
- if not prev in dep:
- fringe.append(prev)
-
- dep.pop(0) # remove dist from dep, was there to prevent infinite loops
- return dep
-
-if __name__ == '__main__':
- from distutils2._backport.pkgutil import get_distributions
- dists = list(get_distributions(use_egg_info=True))
- graph = generate_graph(dists)
- for dist, reqs in graph.missing.iteritems():
- if len(reqs) > 0:
- print("Missing dependencies for %s: %s" % (dist.name,
- ", ".join(reqs)))
- f = open('output.dot', 'w')
- graph_to_dot(graph, f, True)
diff --git a/src/distutils2/dist.py b/src/distutils2/dist.py
deleted file mode 100644
index 2f491ca..0000000
--- a/src/distutils2/dist.py
+++ /dev/null
@@ -1,1032 +0,0 @@
-"""distutils.dist
-
-Provides the Distribution class, which represents the module distribution
-being built/installed/distributed.
-"""
-
-__revision__ = "$Id: dist.py 77717 2010-01-24 00:33:32Z tarek.ziade $"
-
-import sys
-import os
-import re
-import warnings
-
-from ConfigParser import RawConfigParser
-
-from distutils2.errors import (DistutilsOptionError, DistutilsArgError,
- DistutilsModuleError, DistutilsClassError)
-from distutils2.fancy_getopt import FancyGetopt
-from distutils2.util import check_environ, strtobool, resolve_name
-from distutils2 import log
-from distutils2.metadata import DistributionMetadata
-
-# Regex to define acceptable Distutils command names. This is not *quite*
-# the same as a Python NAME -- I don't allow leading underscores. The fact
-# that they're very similar is no coincidence; the default naming scheme is
-# to look for a Python module named after the command.
-command_re = re.compile(r'^[a-zA-Z]([a-zA-Z0-9_]*)$')
-
-
-class Distribution(object):
- """The core of the Distutils. Most of the work hiding behind 'setup'
- is really done within a Distribution instance, which farms the work out
- to the Distutils commands specified on the command line.
-
- Setup scripts will almost never instantiate Distribution directly,
- unless the 'setup()' function is totally inadequate to their needs.
- However, it is conceivable that a setup script might wish to subclass
- Distribution for some specialized purpose, and then pass the subclass
- to 'setup()' as the 'distclass' keyword argument. If so, it is
- necessary to respect the expectations that 'setup' has of Distribution.
- See the code for 'setup()', in core.py, for details.
- """
-
- # 'global_options' describes the command-line options that may be
- # supplied to the setup script prior to any actual commands.
- # Eg. "./setup.py -n" or "./setup.py --quiet" both take advantage of
- # these global options. This list should be kept to a bare minimum,
- # since every global option is also valid as a command option -- and we
- # don't want to pollute the commands with too many options that they
- # have minimal control over.
- # The fourth entry for verbose means that it can be repeated.
- global_options = [('verbose', 'v', "run verbosely (default)", 1),
- ('quiet', 'q', "run quietly (turns verbosity off)"),
- ('dry-run', 'n', "don't actually do anything"),
- ('help', 'h', "show detailed help message"),
- ('no-user-cfg', None,
- 'ignore pydistutils.cfg in your home directory'),
- ]
-
- # 'common_usage' is a short (2-3 line) string describing the common
- # usage of the setup script.
- common_usage = """\
-Common commands: (see '--help-commands' for more)
-
- setup.py build will build the package underneath 'build/'
- setup.py install will install the package
-"""
-
- # options that are not propagated to the commands
- display_options = [
- ('help-commands', None,
- "list all available commands"),
- ('name', None,
- "print package name"),
- ('version', 'V',
- "print package version"),
- ('fullname', None,
- "print <package name>-<version>"),
- ('author', None,
- "print the author's name"),
- ('author-email', None,
- "print the author's email address"),
- ('maintainer', None,
- "print the maintainer's name"),
- ('maintainer-email', None,
- "print the maintainer's email address"),
- ('contact', None,
- "print the maintainer's name if known, else the author's"),
- ('contact-email', None,
- "print the maintainer's email address if known, else the author's"),
- ('url', None,
- "print the URL for this package"),
- ('license', None,
- "print the license of the package"),
- ('licence', None,
- "alias for --license"),
- ('description', None,
- "print the package description"),
- ('long-description', None,
- "print the long package description"),
- ('platforms', None,
- "print the list of platforms"),
- ('classifier', None,
- "print the list of classifiers"),
- ('keywords', None,
- "print the list of keywords"),
- ('provides', None,
- "print the list of packages/modules provided"),
- ('requires', None,
- "print the list of packages/modules required"),
- ('obsoletes', None,
- "print the list of packages/modules made obsolete"),
- ('use-2to3', None,
- "use 2to3 to make source python 3.x compatible"),
- ('convert-2to3-doctests', None,
- "use 2to3 to convert doctests in seperate text files"),
- ]
- display_option_names = [x[0].replace('-', '_') for x in display_options]
-
- # negative options are options that exclude other options
- negative_opt = {'quiet': 'verbose'}
-
- # -- Creation/initialization methods -------------------------------
- def __init__(self, attrs=None):
- """Construct a new Distribution instance: initialize all the
- attributes of a Distribution, and then use 'attrs' (a dictionary
- mapping attribute names to values) to assign some of those
- attributes their "real" values. (Any attributes not mentioned in
- 'attrs' will be assigned to some null value: 0, None, an empty list
- or dictionary, etc.) Most importantly, initialize the
- 'command_obj' attribute to the empty dictionary; this will be
- filled in with real command objects by 'parse_command_line()'.
- """
-
- # Default values for our command-line options
- self.verbose = 1
- self.dry_run = 0
- self.help = 0
- for attr in self.display_option_names:
- setattr(self, attr, 0)
-
- # Store the distribution metadata (name, version, author, and so
- # forth) in a separate object -- we're getting to have enough
- # information here (and enough command-line options) that it's
- # worth it.
- self.metadata = DistributionMetadata()
-
- # 'cmdclass' maps command names to class objects, so we
- # can 1) quickly figure out which class to instantiate when
- # we need to create a new command object, and 2) have a way
- # for the setup script to override command classes
- self.cmdclass = {}
-
- # 'command_packages' is a list of packages in which commands
- # are searched for. The factory for command 'foo' is expected
- # to be named 'foo' in the module 'foo' in one of the packages
- # named here. This list is searched from the left; an error
- # is raised if no named package provides the command being
- # searched for. (Always access using get_command_packages().)
- self.command_packages = None
-
- # 'script_name' and 'script_args' are usually set to sys.argv[0]
- # and sys.argv[1:], but they can be overridden when the caller is
- # not necessarily a setup script run from the command line.
- self.script_name = None
- self.script_args = None
-
- # 'command_options' is where we store command options between
- # parsing them (from config files, the command line, etc.) and when
- # they are actually needed -- ie. when the command in question is
- # instantiated. It is a dictionary of dictionaries of 2-tuples:
- # command_options = { command_name : { option : (source, value) } }
- self.command_options = {}
-
- # 'dist_files' is the list of (command, pyversion, file) that
- # have been created by any dist commands run so far. This is
- # filled regardless of whether the run is dry or not. pyversion
- # gives sysconfig.get_python_version() if the dist file is
- # specific to a Python version, 'any' if it is good for all
- # Python versions on the target platform, and '' for a source
- # file. pyversion should not be used to specify minimum or
- # maximum required Python versions; use the metainfo for that
- # instead.
- self.dist_files = []
-
- # These options are really the business of various commands, rather
- # than of the Distribution itself. We provide aliases for them in
- # Distribution as a convenience to the developer.
- self.packages = []
- self.package_data = {}
- self.package_dir = None
- self.py_modules = []
- self.libraries = []
- self.headers = []
- self.ext_modules = []
- self.ext_package = None
- self.include_dirs = []
- self.extra_path = None
- self.scripts = []
- self.data_files = []
- self.password = ''
- self.use_2to3 = False
- self.convert_2to3_doctests = []
-
- # And now initialize bookkeeping stuff that can't be supplied by
- # the caller at all. 'command_obj' maps command names to
- # Command instances -- that's how we enforce that every command
- # class is a singleton.
- self.command_obj = {}
-
- # 'have_run' maps command names to boolean values; it keeps track
- # of whether we have actually run a particular command, to make it
- # cheap to "run" a command whenever we think we might need to -- if
- # it's already been done, no need for expensive filesystem
- # operations, we just check the 'have_run' dictionary and carry on.
- # It's only safe to query 'have_run' for a command class that has
- # been instantiated -- a false value will be inserted when the
- # command object is created, and replaced with a true value when
- # the command is successfully run. Thus it's probably best to use
- # '.get()' rather than a straight lookup.
- self.have_run = {}
-
- # Now we'll use the attrs dictionary (ultimately, keyword args from
- # the setup script) to possibly override any or all of these
- # distribution options.
-
- if attrs is not None:
- # Pull out the set of command options and work on them
- # specifically. Note that this order guarantees that aliased
- # command options will override any supplied redundantly
- # through the general options dictionary.
- options = attrs.get('options')
- if options is not None:
- del attrs['options']
- for (command, cmd_options) in options.items():
- opt_dict = self.get_option_dict(command)
- for (opt, val) in cmd_options.items():
- opt_dict[opt] = ("setup script", val)
-
- # Now work on the rest of the attributes. Any attribute that's
- # not already defined is invalid!
- for key, val in attrs.items():
- if self.metadata.is_metadata_field(key):
- self.metadata[key] = val
- elif hasattr(self, key):
- setattr(self, key, val)
- else:
- msg = "Unknown distribution option: %r" % key
- warnings.warn(msg)
-
- # no-user-cfg is handled before other command line args
- # because other args override the config files, and this
- # one is needed before we can load the config files.
- # If attrs['script_args'] wasn't passed, assume false.
- #
- # This also make sure we just look at the global options
- self.want_user_cfg = True
-
- if self.script_args is not None:
- for arg in self.script_args:
- if not arg.startswith('-'):
- break
- if arg == '--no-user-cfg':
- self.want_user_cfg = False
- break
-
- self.finalize_options()
-
- def get_option_dict(self, command):
- """Get the option dictionary for a given command. If that
- command's option dictionary hasn't been created yet, then create it
- and return the new dictionary; otherwise, return the existing
- option dictionary.
- """
- d = self.command_options.get(command)
- if d is None:
- d = self.command_options[command] = {}
- return d
-
- def get_fullname(self):
- return self.metadata.get_fullname()
-
- def dump_option_dicts(self, header=None, commands=None, indent=""):
- from pprint import pformat
-
- if commands is None: # dump all command option dicts
- commands = self.command_options.keys()
- commands.sort()
-
- if header is not None:
- self.announce(indent + header)
- indent = indent + " "
-
- if not commands:
- self.announce(indent + "no commands known yet")
- return
-
- for cmd_name in commands:
- opt_dict = self.command_options.get(cmd_name)
- if opt_dict is None:
- self.announce(indent +
- "no option dict for '%s' command" % cmd_name)
- else:
- self.announce(indent +
- "option dict for '%s' command:" % cmd_name)
- out = pformat(opt_dict)
- for line in out.split('\n'):
- self.announce(indent + " " + line)
-
- # -- Config file finding/parsing methods ---------------------------
-
- def find_config_files(self):
- """Find as many configuration files as should be processed for this
- platform, and return a list of filenames in the order in which they
- should be parsed. The filenames returned are guaranteed to exist
- (modulo nasty race conditions).
-
- There are three possible config files: distutils.cfg in the
- Distutils installation directory (ie. where the top-level
- Distutils __inst__.py file lives), a file in the user's home
- directory named .pydistutils.cfg on Unix and pydistutils.cfg
- on Windows/Mac; and setup.cfg in the current directory.
-
- The file in the user's home directory can be disabled with the
- --no-user-cfg option.
- """
- files = []
- check_environ()
-
- # Where to look for the system-wide Distutils config file
- sys_dir = os.path.dirname(sys.modules['distutils2'].__file__)
-
- # Look for the system config file
- sys_file = os.path.join(sys_dir, "distutils.cfg")
- if os.path.isfile(sys_file):
- files.append(sys_file)
-
- # What to call the per-user config file
- if os.name == 'posix':
- user_filename = ".pydistutils.cfg"
- else:
- user_filename = "pydistutils.cfg"
-
- # And look for the user config file
- if self.want_user_cfg:
- user_file = os.path.join(os.path.expanduser('~'), user_filename)
- if os.path.isfile(user_file):
- files.append(user_file)
-
- # All platforms support local setup.cfg
- local_file = "setup.cfg"
- if os.path.isfile(local_file):
- files.append(local_file)
-
- log.debug("using config files: %s" % ', '.join(files))
- return files
-
- def parse_config_files(self, filenames=None):
- if filenames is None:
- filenames = self.find_config_files()
-
- log.debug("Distribution.parse_config_files():")
-
- parser = RawConfigParser()
- for filename in filenames:
- log.debug(" reading %s" % filename)
- parser.read(filename)
- for section in parser.sections():
- options = parser.options(section)
- opt_dict = self.get_option_dict(section)
-
- for opt in options:
- if opt != '__name__':
- val = parser.get(section, opt)
- opt = opt.replace('-', '_')
-
- # Hooks use a suffix system to prevent being overriden
- # by a config file processed later (i.e. a hook set in
- # the user config file cannot be replaced by a hook
- # set in a project config file, unless they have the
- # same suffix).
- if opt.startswith("pre_hook.") or opt.startswith("post_hook."):
- hook_type, alias = opt.split(".")
- hook_dict = opt_dict.setdefault(hook_type, (filename, {}))[1]
- hook_dict[alias] = val
- else:
- opt_dict[opt] = (filename, val)
-
- # Make the RawConfigParser forget everything (so we retain
- # the original filenames that options come from)
- parser.__init__()
-
- # If there was a "global" section in the config file, use it
- # to set Distribution options.
-
- if 'global' in self.command_options:
- for (opt, (src, val)) in self.command_options['global'].items():
- alias = self.negative_opt.get(opt)
- try:
- if alias:
- setattr(self, alias, not strtobool(val))
- elif opt in ('verbose', 'dry_run'): # ugh!
- setattr(self, opt, strtobool(val))
- else:
- setattr(self, opt, val)
- except ValueError, msg:
- raise DistutilsOptionError(msg)
-
- # -- Command-line parsing methods ----------------------------------
-
- def parse_command_line(self):
- """Parse the setup script's command line, taken from the
- 'script_args' instance attribute (which defaults to 'sys.argv[1:]'
- -- see 'setup()' in core.py). This list is first processed for
- "global options" -- options that set attributes of the Distribution
- instance. Then, it is alternately scanned for Distutils commands
- and options for that command. Each new command terminates the
- options for the previous command. The allowed options for a
- command are determined by the 'user_options' attribute of the
- command class -- thus, we have to be able to load command classes
- in order to parse the command line. Any error in that 'options'
- attribute raises DistutilsGetoptError; any error on the
- command line raises DistutilsArgError. If no Distutils commands
- were found on the command line, raises DistutilsArgError. Return
- true if command line was successfully parsed and we should carry
- on with executing commands; false if no errors but we shouldn't
- execute commands (currently, this only happens if user asks for
- help).
- """
- #
- # We now have enough information to show the Macintosh dialog
- # that allows the user to interactively specify the "command line".
- #
- toplevel_options = self._get_toplevel_options()
-
- # We have to parse the command line a bit at a time -- global
- # options, then the first command, then its options, and so on --
- # because each command will be handled by a different class, and
- # the options that are valid for a particular class aren't known
- # until we have loaded the command class, which doesn't happen
- # until we know what the command is.
-
- self.commands = []
- parser = FancyGetopt(toplevel_options + self.display_options)
- parser.set_negative_aliases(self.negative_opt)
- parser.set_aliases({'licence': 'license'})
- args = parser.getopt(args=self.script_args, object=self)
- option_order = parser.get_option_order()
- log.set_verbosity(self.verbose)
-
- # for display options we return immediately
- if self.handle_display_options(option_order):
- return
-
- while args:
- args = self._parse_command_opts(parser, args)
- if args is None: # user asked for help (and got it)
- return
-
- # Handle the cases of --help as a "global" option, ie.
- # "setup.py --help" and "setup.py --help command ...". For the
- # former, we show global options (--verbose, --dry-run, etc.)
- # and display-only options (--name, --version, etc.); for the
- # latter, we omit the display-only options and show help for
- # each command listed on the command line.
- if self.help:
- self._show_help(parser,
- display_options=len(self.commands) == 0,
- commands=self.commands)
- return
-
- # Oops, no commands found -- an end-user error
- if not self.commands:
- raise DistutilsArgError("no commands supplied")
-
- # All is well: return true
- return 1
-
- def _get_toplevel_options(self):
- """Return the non-display options recognized at the top level.
-
- This includes options that are recognized *only* at the top
- level as well as options recognized for commands.
- """
- return self.global_options + [
- ("command-packages=", None,
- "list of packages that provide distutils commands"),
- ]
-
- def _parse_command_opts(self, parser, args):
- """Parse the command-line options for a single command.
- 'parser' must be a FancyGetopt instance; 'args' must be the list
- of arguments, starting with the current command (whose options
- we are about to parse). Returns a new version of 'args' with
- the next command at the front of the list; will be the empty
- list if there are no more commands on the command line. Returns
- None if the user asked for help on this command.
- """
- # late import because of mutual dependence between these modules
- from distutils2.command.cmd import Command
-
- # Pull the current command from the head of the command line
- command = args[0]
- if not command_re.match(command):
- raise SystemExit("invalid command name '%s'" % command)
- self.commands.append(command)
-
- # Dig up the command class that implements this command, so we
- # 1) know that it's a valid command, and 2) know which options
- # it takes.
- try:
- cmd_class = self.get_command_class(command)
- except DistutilsModuleError, msg:
- raise DistutilsArgError(msg)
-
- # Require that the command class be derived from Command -- want
- # to be sure that the basic "command" interface is implemented.
- if not issubclass(cmd_class, Command):
- raise DistutilsClassError(
- "command class %s must subclass Command" % cmd_class)
-
- # Also make sure that the command object provides a list of its
- # known options.
- if not (hasattr(cmd_class, 'user_options') and
- isinstance(cmd_class.user_options, list)):
- raise DistutilsClassError(
- ("command class %s must provide "
- "'user_options' attribute (a list of tuples)") % cmd_class)
-
- # If the command class has a list of negative alias options,
- # merge it in with the global negative aliases.
- negative_opt = self.negative_opt
- if hasattr(cmd_class, 'negative_opt'):
- negative_opt = negative_opt.copy()
- negative_opt.update(cmd_class.negative_opt)
-
- # Check for help_options in command class. They have a different
- # format (tuple of four) so we need to preprocess them here.
- if (hasattr(cmd_class, 'help_options') and
- isinstance(cmd_class.help_options, list)):
- help_options = fix_help_options(cmd_class.help_options)
- else:
- help_options = []
-
- # All commands support the global options too, just by adding
- # in 'global_options'.
- parser.set_option_table(self.global_options +
- cmd_class.user_options +
- help_options)
- parser.set_negative_aliases(negative_opt)
- (args, opts) = parser.getopt(args[1:])
- if hasattr(opts, 'help') and opts.help:
- self._show_help(parser, display_options=0, commands=[cmd_class])
- return
-
- if (hasattr(cmd_class, 'help_options') and
- isinstance(cmd_class.help_options, list)):
- help_option_found = 0
- for (help_option, short, desc, func) in cmd_class.help_options:
- if hasattr(opts, help_option.replace('-', '_')):
- help_option_found = 1
- if hasattr(func, '__call__'):
- func()
- else:
- raise DistutilsClassError(
- "invalid help function %r for help option '%s': "
- "must be a callable object (function, etc.)"
- % (func, help_option))
-
- if help_option_found:
- return
-
- # Put the options from the command line into their official
- # holding pen, the 'command_options' dictionary.
- opt_dict = self.get_option_dict(command)
- for (name, value) in vars(opts).items():
- opt_dict[name] = ("command line", value)
-
- return args
-
- def finalize_options(self):
- """Set final values for all the options on the Distribution
- instance, analogous to the .finalize_options() method of Command
- objects.
- """
- if getattr(self, 'convert_2to3_doctests', None):
- self.convert_2to3_doctests = [os.path.join(p)
- for p in self.convert_2to3_doctests]
- else:
- self.convert_2to3_doctests = []
-
- def _show_help(self, parser, global_options=1, display_options=1,
- commands=[]):
- """Show help for the setup script command line in the form of
- several lists of command-line options. 'parser' should be a
- FancyGetopt instance; do not expect it to be returned in the
- same state, as its option table will be reset to make it
- generate the correct help text.
-
- If 'global_options' is true, lists the global options:
- --verbose, --dry-run, etc. If 'display_options' is true, lists
- the "display-only" options: --name, --version, etc. Finally,
- lists per-command help for every command name or command class
- in 'commands'.
- """
- # late import because of mutual dependence between these modules
- from distutils2.core import gen_usage
- from distutils2.command.cmd import Command
-
- if global_options:
- if display_options:
- options = self._get_toplevel_options()
- else:
- options = self.global_options
- parser.set_option_table(options)
- parser.print_help(self.common_usage + "\nGlobal options:")
- print('')
-
- if display_options:
- parser.set_option_table(self.display_options)
- parser.print_help(
- "Information display options (just display " +
- "information, ignore any commands)")
- print('')
-
- for command in self.commands:
- if isinstance(command, type) and issubclass(command, Command):
- cls = command
- else:
- cls = self.get_command_class(command)
- if (hasattr(cls, 'help_options') and
- isinstance(cls.help_options, list)):
- parser.set_option_table(cls.user_options +
- fix_help_options(cls.help_options))
- else:
- parser.set_option_table(cls.user_options)
- parser.print_help("Options for '%s' command:" % cls.__name__)
- print('')
-
- print(gen_usage(self.script_name))
-
- def handle_display_options(self, option_order):
- """If there were any non-global "display-only" options
- (--help-commands or the metadata display options) on the command
- line, display the requested info and return true; else return
- false.
- """
- from distutils2.core import gen_usage
-
- # User just wants a list of commands -- we'll print it out and stop
- # processing now (ie. if they ran "setup --help-commands foo bar",
- # we ignore "foo bar").
- if self.help_commands:
- self.print_commands()
- print('')
- print(gen_usage(self.script_name))
- return 1
-
- # If user supplied any of the "display metadata" options, then
- # display that metadata in the order in which the user supplied the
- # metadata options.
- any_display_options = 0
- is_display_option = {}
- for option in self.display_options:
- is_display_option[option[0]] = 1
-
- for opt, val in option_order:
- if val and is_display_option.get(opt):
- opt = opt.replace('-', '_')
- value = self.metadata[opt]
- if opt in ['keywords', 'platform']:
- print(','.join(value))
- elif opt in ('classifier', 'provides', 'requires',
- 'obsoletes'):
- print('\n'.join(value))
- else:
- print(value)
- any_display_options = 1
-
- return any_display_options
-
- def print_command_list(self, commands, header, max_length):
- """Print a subset of the list of all commands -- used by
- 'print_commands()'.
- """
- print(header + ":")
-
- for cmd in commands:
- cls = self.cmdclass.get(cmd)
- if not cls:
- cls = self.get_command_class(cmd)
- try:
- description = cls.description
- except AttributeError:
- description = "(no description available)"
-
- print(" %-*s %s" % (max_length, cmd, description))
-
- def _get_command_groups(self):
- """Helper function to retrieve all the command class names divided
- into standard commands (listed in distutils2.command.__all__)
- and extra commands (given in self.cmdclass and not standard
- commands).
- """
- from distutils2.command import __all__ as std_commands
- extra_commands = [cmd for cmd in self.cmdclass
- if cmd not in std_commands]
- return std_commands, extra_commands
-
- def print_commands(self):
- """Print out a help message listing all available commands with a
- description of each. The list is divided into standard commands
- (listed in distutils2.command.__all__) and extra commands
- (given in self.cmdclass and not standard commands). The
- descriptions come from the command class attribute
- 'description'.
- """
- std_commands, extra_commands = self._get_command_groups()
- max_length = 0
- for cmd in (std_commands + extra_commands):
- if len(cmd) > max_length:
- max_length = len(cmd)
-
- self.print_command_list(std_commands,
- "Standard commands",
- max_length)
- if extra_commands:
- print
- self.print_command_list(extra_commands,
- "Extra commands",
- max_length)
-
- def get_command_list(self):
- """Get a list of (command, description) tuples.
-
- The list is divided into standard commands (listed in
- distutils2.command.__all__) and extra commands (given in
- self.cmdclass and not standard commands). The descriptions come
- from the command class attribute 'description'.
- """
- # Currently this is only used on Mac OS, for the Mac-only GUI
- # Distutils interface (by Jack Jansen)
-
- rv = []
- for cls in self.get_command_classes():
- try:
- description = cls.description
- except AttributeError:
- description = "(no description available)"
- rv.append((cmd, description))
- return rv
-
- # -- Command class/object methods ----------------------------------
-
- def get_command_packages(self):
- """Return a list of packages from which commands are loaded."""
- pkgs = self.command_packages
- if not isinstance(pkgs, list):
- if pkgs is None:
- pkgs = ''
- pkgs = [pkg.strip() for pkg in pkgs.split(',') if pkg != '']
- if "distutils2.command" not in pkgs:
- pkgs.insert(0, "distutils2.command")
- self.command_packages = pkgs
- return pkgs
-
- def get_command_names(self):
- """Return a list of all command names."""
- return [getattr(cls, 'command_name', cls.__name__)
- for cls in self.get_command_classes()]
-
- def get_command_classes(self):
- """Return a list of all command classes."""
- std_commands, extra_commands = self._get_command_groups()
- classes = []
- for cmd in (std_commands + extra_commands):
- try:
- cls = self.cmdclass[cmd]
- except KeyError:
- cls = self.get_command_class(cmd)
- classes.append(cls)
- return classes
-
- def get_command_class(self, command):
- """Return the class that implements the Distutils command named by
- 'command'. First we check the 'cmdclass' dictionary; if the
- command is mentioned there, we fetch the class object from the
- dictionary and return it. Otherwise we load the command module
- ("distutils.command." + command) and fetch the command class from
- the module. The loaded class is also stored in 'cmdclass'
- to speed future calls to 'get_command_class()'.
-
- Raises DistutilsModuleError if the expected module could not be
- found, or if that module does not define the expected class.
- """
- cls = self.cmdclass.get(command)
- if cls:
- return cls
-
- for pkgname in self.get_command_packages():
- module_name = "%s.%s" % (pkgname, command)
- class_name = command
-
- try:
- __import__(module_name)
- module = sys.modules[module_name]
- except ImportError:
- continue
-
- try:
- cls = getattr(module, class_name)
- except AttributeError:
- raise DistutilsModuleError(
- "invalid command '%s' (no class '%s' in module '%s')" %
- (command, class_name, module_name))
-
- self.cmdclass[command] = cls
- return cls
-
- raise DistutilsModuleError("invalid command '%s'" % command)
-
- def get_command_obj(self, command, create=1):
- """Return the command object for 'command'. Normally this object
- is cached on a previous call to 'get_command_obj()'; if no command
- object for 'command' is in the cache, then we either create and
- return it (if 'create' is true) or return None.
- """
- cmd_obj = self.command_obj.get(command)
- if not cmd_obj and create:
- log.debug("Distribution.get_command_obj(): " \
- "creating '%s' command object" % command)
-
- cls = self.get_command_class(command)
- cmd_obj = self.command_obj[command] = cls(self)
- self.have_run[command] = 0
-
- # Set any options that were supplied in config files
- # or on the command line. (NB. support for error
- # reporting is lame here: any errors aren't reported
- # until 'finalize_options()' is called, which means
- # we won't report the source of the error.)
- options = self.command_options.get(command)
- if options:
- self._set_command_options(cmd_obj, options)
-
- return cmd_obj
-
- def _set_command_options(self, command_obj, option_dict=None):
- """Set the options for 'command_obj' from 'option_dict'. Basically
- this means copying elements of a dictionary ('option_dict') to
- attributes of an instance ('command').
-
- 'command_obj' must be a Command instance. If 'option_dict' is not
- supplied, uses the standard option dictionary for this command
- (from 'self.command_options').
- """
- command_name = command_obj.get_command_name()
- if option_dict is None:
- option_dict = self.get_option_dict(command_name)
-
- log.debug(" setting options for '%s' command:" % command_name)
-
- for (option, (source, value)) in option_dict.items():
- log.debug(" %s = %s (from %s)" % (option, value,
- source))
- try:
- bool_opts = [x.replace('-', '_')
- for x in command_obj.boolean_options]
- except AttributeError:
- bool_opts = []
- try:
- neg_opt = command_obj.negative_opt
- except AttributeError:
- neg_opt = {}
-
- try:
- is_string = isinstance(value, str)
- if option in neg_opt and is_string:
- setattr(command_obj, neg_opt[option], not strtobool(value))
- elif option in bool_opts and is_string:
- setattr(command_obj, option, strtobool(value))
- elif hasattr(command_obj, option):
- setattr(command_obj, option, value)
- else:
- raise DistutilsOptionError(
- "error in %s: command '%s' has no such option '%s'" %
- (source, command_name, option))
- except ValueError, msg:
- raise DistutilsOptionError(msg)
-
- def get_reinitialized_command(self, command, reinit_subcommands=0):
- """Reinitializes a command to the state it was in when first
- returned by 'get_command_obj()': ie., initialized but not yet
- finalized. This provides the opportunity to sneak option
- values in programmatically, overriding or supplementing
- user-supplied values from the config files and command line.
- You'll have to re-finalize the command object (by calling
- 'finalize_options()' or 'ensure_finalized()') before using it for
- real.
-
- 'command' should be a command name (string) or command object. If
- 'reinit_subcommands' is true, also reinitializes the command's
- sub-commands, as declared by the 'sub_commands' class attribute (if
- it has one). See the "install" command for an example. Only
- reinitializes the sub-commands that actually matter, ie. those
- whose test predicates return true.
-
- Returns the reinitialized command object.
- """
- from distutils2.command.cmd import Command
- if not isinstance(command, Command):
- command_name = command
- command = self.get_command_obj(command_name)
- else:
- command_name = command.get_command_name()
-
- if not command.finalized:
- return command
- command.initialize_options()
- command.finalized = 0
- self.have_run[command_name] = 0
- self._set_command_options(command)
-
- if reinit_subcommands:
- for sub in command.get_sub_commands():
- self.get_reinitialized_command(sub, reinit_subcommands)
-
- return command
-
- # -- Methods that operate on the Distribution ----------------------
-
- def announce(self, msg, level=log.INFO):
- log.log(level, msg)
-
- def run_commands(self):
- """Run each command that was seen on the setup script command line.
- Uses the list of commands found and cache of command objects
- created by 'get_command_obj()'.
- """
- for cmd in self.commands:
- self.run_command(cmd)
-
- # -- Methods that operate on its Commands --------------------------
-
- def run_command(self, command):
- """Do whatever it takes to run a command (including nothing at all,
- if the command has already been run). Specifically: if we have
- already created and run the command named by 'command', return
- silently without doing anything. If the command named by 'command'
- doesn't even have a command object yet, create one. Then invoke
- 'run()' on that command object (or an existing one).
- """
- # Already been here, done that? then return silently.
- if self.have_run.get(command):
- return
-
- cmd_obj = self.get_command_obj(command)
- cmd_obj.ensure_finalized()
- self.run_command_hooks(cmd_obj, 'pre_hook')
- log.info("running %s", command)
- cmd_obj.run()
- self.run_command_hooks(cmd_obj, 'post_hook')
- self.have_run[command] = 1
-
- def run_command_hooks(self, cmd_obj, hook_kind):
- """Run hooks registered for that command and phase.
-
- *cmd_obj* is a finalized command object; *hook_kind* is either
- 'pre_hook' or 'post_hook'.
- """
- if hook_kind not in ('pre_hook', 'post_hook'):
- raise ValueError('invalid hook kind: %r' % hook_kind)
-
- hooks = getattr(cmd_obj, hook_kind)
-
- if hooks is None:
- return
-
- for hook in hooks.itervalues():
- if isinstance(hook, basestring):
- try:
- hook_obj = resolve_name(hook)
- except ImportError, e:
- raise DistutilsModuleError(e)
- else:
- hook_obj = hook
-
- if not hasattr(hook_obj, '__call__'):
- raise DistutilsOptionError('hook %r is not callable' % hook)
-
- log.info('running %s %s for command %s',
- hook_kind, hook, cmd_obj.get_command_name())
- hook_obj(cmd_obj)
-
- # -- Distribution query methods ------------------------------------
- def has_pure_modules(self):
- return len(self.packages or self.py_modules or []) > 0
-
- def has_ext_modules(self):
- return self.ext_modules and len(self.ext_modules) > 0
-
- def has_c_libraries(self):
- return self.libraries and len(self.libraries) > 0
-
- def has_modules(self):
- return self.has_pure_modules() or self.has_ext_modules()
-
- def has_headers(self):
- return self.headers and len(self.headers) > 0
-
- def has_scripts(self):
- return self.scripts and len(self.scripts) > 0
-
- def has_data_files(self):
- return self.data_files and len(self.data_files) > 0
-
- def is_pure(self):
- return (self.has_pure_modules() and
- not self.has_ext_modules() and
- not self.has_c_libraries())
-
-
-# XXX keep for compat or remove?
-
-def fix_help_options(options):
- """Convert a 4-tuple 'help_options' list as found in various command
- classes to the 3-tuple form required by FancyGetopt.
- """
- new_options = []
- for help_tuple in options:
- new_options.append(help_tuple[0:3])
- return new_options
diff --git a/src/distutils2/errors.py b/src/distutils2/errors.py
deleted file mode 100644
index 43469ce..0000000
--- a/src/distutils2/errors.py
+++ /dev/null
@@ -1,134 +0,0 @@
-"""distutils.errors
-
-Provides exceptions used by the Distutils modules. Note that Distutils
-modules may raise standard exceptions; in particular, SystemExit is
-usually raised for errors that are obviously the end-user's fault
-(eg. bad command-line arguments).
-
-This module is safe to use in "from ... import *" mode; it only exports
-symbols whose names start with "Distutils" and end with "Error"."""
-
-__revision__ = "$Id: errors.py 75901 2009-10-28 06:45:18Z tarek.ziade $"
-
-
-class DistutilsError(Exception):
- """The root of all Distutils evil."""
-
-
-class DistutilsModuleError(DistutilsError):
- """Unable to load an expected module, or to find an expected class
- within some module (in particular, command modules and classes)."""
-
-
-class DistutilsClassError(DistutilsError):
- """Some command class (or possibly distribution class, if anyone
- feels a need to subclass Distribution) is found not to be holding
- up its end of the bargain, ie. implementing some part of the
- "command "interface."""
-
-
-class DistutilsGetoptError(DistutilsError):
- """The option table provided to 'fancy_getopt()' is bogus."""
-
-
-class DistutilsArgError(DistutilsError):
- """Raised by fancy_getopt in response to getopt.error -- ie. an
- error in the command line usage."""
-
-
-class DistutilsFileError(DistutilsError):
- """Any problems in the filesystem: expected file not found, etc.
- Typically this is for problems that we detect before IOError or
- OSError could be raised."""
-
-
-class DistutilsOptionError(DistutilsError):
- """Syntactic/semantic errors in command options, such as use of
- mutually conflicting options, or inconsistent options,
- badly-spelled values, etc. No distinction is made between option
- values originating in the setup script, the command line, config
- files, or what-have-you -- but if we *know* something originated in
- the setup script, we'll raise DistutilsSetupError instead."""
-
-
-class DistutilsSetupError(DistutilsError):
- """For errors that can be definitely blamed on the setup script,
- such as invalid keyword arguments to 'setup()'."""
-
-
-class DistutilsPlatformError(DistutilsError):
- """We don't know how to do something on the current platform (but
- we do know how to do it on some platform) -- eg. trying to compile
- C files on a platform not supported by a CCompiler subclass."""
-
-
-class DistutilsExecError(DistutilsError):
- """Any problems executing an external program (such as the C
- compiler, when compiling C files)."""
-
-
-class DistutilsInternalError(DistutilsError):
- """Internal inconsistencies or impossibilities (obviously, this
- should never be seen if the code is working!)."""
-
-
-class DistutilsTemplateError(DistutilsError):
- """Syntax error in a file list template."""
-
-
-class DistutilsByteCompileError(DistutilsError):
- """Byte compile error."""
-
-
-class DistutilsIndexError(DistutilsError):
- """Any problem occuring during using the indexes."""
-
-
-# Exception classes used by the CCompiler implementation classes
-class CCompilerError(Exception):
- """Some compile/link operation failed."""
-
-
-class PreprocessError(CCompilerError):
- """Failure to preprocess one or more C/C++ files."""
-
-
-class CompileError(CCompilerError):
- """Failure to compile one or more C/C++ source files."""
-
-
-class LibError(CCompilerError):
- """Failure to create a static library from one or more C/C++ object
- files."""
-
-
-class LinkError(CCompilerError):
- """Failure to link one or more C/C++ object files into an executable
- or shared library file."""
-
-
-class UnknownFileError(CCompilerError):
- """Attempt to process an unknown file type."""
-
-
-class MetadataConflictError(DistutilsError):
- """Attempt to read or write metadata fields that are conflictual."""
-
-
-class MetadataUnrecognizedVersionError(DistutilsError):
- """Unknown metadata version number."""
-
-
-class IrrationalVersionError(Exception):
- """This is an irrational version."""
- pass
-
-
-class HugeMajorVersionNumError(IrrationalVersionError):
- """An irrational version because the major version number is huge
- (often because a year or date was used).
-
- See `error_on_huge_major_num` option in `NormalizedVersion` for details.
- This guard can be disabled by setting that option False.
- """
- pass
diff --git a/src/distutils2/extension.py b/src/distutils2/extension.py
deleted file mode 100644
index f38bf60..0000000
--- a/src/distutils2/extension.py
+++ /dev/null
@@ -1,137 +0,0 @@
-"""distutils.extension
-
-Provides the Extension class, used to describe C/C++ extension
-modules in setup scripts."""
-
-__revision__ = "$Id: extension.py 77704 2010-01-23 09:23:15Z tarek.ziade $"
-
-import warnings
-
-# This class is really only used by the "build_ext" command, so it might
-# make sense to put it in distutils.command.build_ext. However, that
-# module is already big enough, and I want to make this class a bit more
-# complex to simplify some common cases ("foo" module in "foo.c") and do
-# better error-checking ("foo.c" actually exists).
-#
-# Also, putting this in build_ext.py means every setup script would have to
-# import that large-ish module (indirectly, through distutils.core) in
-# order to do anything.
-
-
-class Extension(object):
- """Just a collection of attributes that describes an extension
- module and everything needed to build it (hopefully in a portable
- way, but there are hooks that let you be as unportable as you need).
-
- Instance attributes:
- name : string
- the full name of the extension, including any packages -- ie.
- *not* a filename or pathname, but Python dotted name
- sources : [string]
- list of source filenames, relative to the distribution root
- (where the setup script lives), in Unix form (slash-separated)
- for portability. Source files may be C, C++, SWIG (.i),
- platform-specific resource files, or whatever else is recognized
- by the "build_ext" command as source for a Python extension.
- include_dirs : [string]
- list of directories to search for C/C++ header files (in Unix
- form for portability)
- define_macros : [(name : string, value : string|None)]
- list of macros to define; each macro is defined using a 2-tuple,
- where 'value' is either the string to define it to or None to
- define it without a particular value (equivalent of "#define
- FOO" in source or -DFOO on Unix C compiler command line)
- undef_macros : [string]
- list of macros to undefine explicitly
- library_dirs : [string]
- list of directories to search for C/C++ libraries at link time
- libraries : [string]
- list of library names (not filenames or paths) to link against
- runtime_library_dirs : [string]
- list of directories to search for C/C++ libraries at run time
- (for shared extensions, this is when the extension is loaded)
- extra_objects : [string]
- list of extra files to link with (eg. object files not implied
- by 'sources', static library that must be explicitly specified,
- binary resource files, etc.)
- extra_compile_args : [string]
- any extra platform- and compiler-specific information to use
- when compiling the source files in 'sources'. For platforms and
- compilers where "command line" makes sense, this is typically a
- list of command-line arguments, but for other platforms it could
- be anything.
- extra_link_args : [string]
- any extra platform- and compiler-specific information to use
- when linking object files together to create the extension (or
- to create a new static Python interpreter). Similar
- interpretation as for 'extra_compile_args'.
- export_symbols : [string]
- list of symbols to be exported from a shared extension. Not
- used on all platforms, and not generally necessary for Python
- extensions, which typically export exactly one symbol: "init" +
- extension_name.
- swig_opts : [string]
- any extra options to pass to SWIG if a source file has the .i
- extension.
- depends : [string]
- list of files that the extension depends on
- language : string
- extension language (i.e. "c", "c++", "objc"). Will be detected
- from the source extensions if not provided.
- optional : boolean
- specifies that a build failure in the extension should not abort the
- build process, but simply not install the failing extension.
- """
-
- # When adding arguments to this constructor, be sure to update
- # setup_keywords in core.py.
- def __init__(self, name, sources,
- include_dirs=None,
- define_macros=None,
- undef_macros=None,
- library_dirs=None,
- libraries=None,
- runtime_library_dirs=None,
- extra_objects=None,
- extra_compile_args=None,
- extra_link_args=None,
- export_symbols=None,
- swig_opts=None,
- depends=None,
- language=None,
- optional=None,
- **kw # To catch unknown keywords
- ):
- if not isinstance(name, str):
- raise AssertionError("'name' must be a string")
-
- if not isinstance(sources, list):
- raise AssertionError("'sources' must be a list of strings")
-
- for v in sources:
- if not isinstance(v, str):
- raise AssertionError("'sources' must be a list of strings")
-
- self.name = name
- self.sources = sources
- self.include_dirs = include_dirs or []
- self.define_macros = define_macros or []
- self.undef_macros = undef_macros or []
- self.library_dirs = library_dirs or []
- self.libraries = libraries or []
- self.runtime_library_dirs = runtime_library_dirs or []
- self.extra_objects = extra_objects or []
- self.extra_compile_args = extra_compile_args or []
- self.extra_link_args = extra_link_args or []
- self.export_symbols = export_symbols or []
- self.swig_opts = swig_opts or []
- self.depends = depends or []
- self.language = language
- self.optional = optional
-
- # If there are unknown keyword options, warn about them
- if len(kw) > 0:
- options = [repr(option) for option in kw]
- options = ', '.join(sorted(options))
- msg = "Unknown Extension options: %s" % options
- warnings.warn(msg)
diff --git a/src/distutils2/fancy_getopt.py b/src/distutils2/fancy_getopt.py
deleted file mode 100644
index 304fb8a..0000000
--- a/src/distutils2/fancy_getopt.py
+++ /dev/null
@@ -1,467 +0,0 @@
-"""distutils.fancy_getopt
-
-Wrapper around the standard getopt module that provides the following
-additional features:
- * short and long options are tied together
- * options have help strings, so fancy_getopt could potentially
- create a complete usage summary
- * options set attributes of a passed-in object
-"""
-
-__revision__ = "$Id: fancy_getopt.py 76956 2009-12-21 01:22:46Z tarek.ziade $"
-
-import sys
-import string
-import re
-import getopt
-from distutils2.errors import DistutilsGetoptError, DistutilsArgError
-
-# Much like command_re in distutils.core, this is close to but not quite
-# the same as a Python NAME -- except, in the spirit of most GNU
-# utilities, we use '-' in place of '_'. (The spirit of LISP lives on!)
-# The similarities to NAME are again not a coincidence...
-longopt_pat = r'[a-zA-Z](?:[a-zA-Z0-9-]*)'
-longopt_re = re.compile(r'^%s$' % longopt_pat)
-
-# For recognizing "negative alias" options, eg. "quiet=!verbose"
-neg_alias_re = re.compile("^(%s)=!(%s)$" % (longopt_pat, longopt_pat))
-
-class FancyGetopt(object):
- """Wrapper around the standard 'getopt()' module that provides some
- handy extra functionality:
- * short and long options are tied together
- * options have help strings, and help text can be assembled
- from them
- * options set attributes of a passed-in object
- * boolean options can have "negative aliases" -- eg. if
- --quiet is the "negative alias" of --verbose, then "--quiet"
- on the command line sets 'verbose' to false
- """
-
- def __init__(self, option_table=None):
-
- # The option table is (currently) a list of tuples. The
- # tuples may have 3 or four values:
- # (long_option, short_option, help_string [, repeatable])
- # if an option takes an argument, its long_option should have '='
- # appended; short_option should just be a single character, no ':'
- # in any case. If a long_option doesn't have a corresponding
- # short_option, short_option should be None. All option tuples
- # must have long options.
- self.option_table = option_table
-
- # 'option_index' maps long option names to entries in the option
- # table (ie. those 3-tuples).
- self.option_index = {}
- if self.option_table:
- self._build_index()
-
- # 'alias' records (duh) alias options; {'foo': 'bar'} means
- # --foo is an alias for --bar
- self.alias = {}
-
- # 'negative_alias' keeps track of options that are the boolean
- # opposite of some other option
- self.negative_alias = {}
-
- # These keep track of the information in the option table. We
- # don't actually populate these structures until we're ready to
- # parse the command line, since the 'option_table' passed in here
- # isn't necessarily the final word.
- self.short_opts = []
- self.long_opts = []
- self.short2long = {}
- self.attr_name = {}
- self.takes_arg = {}
-
- # And 'option_order' is filled up in 'getopt()'; it records the
- # original order of options (and their values) on the command line,
- # but expands short options, converts aliases, etc.
- self.option_order = []
-
- # __init__ ()
-
-
- def _build_index (self):
- self.option_index.clear()
- for option in self.option_table:
- self.option_index[option[0]] = option
-
- def set_option_table (self, option_table):
- self.option_table = option_table
- self._build_index()
-
- def add_option (self, long_option, short_option=None, help_string=None):
- if long_option in self.option_index:
- raise DistutilsGetoptError, \
- "option conflict: already an option '%s'" % long_option
- else:
- option = (long_option, short_option, help_string)
- self.option_table.append(option)
- self.option_index[long_option] = option
-
-
- def has_option (self, long_option):
- """Return true if the option table for this parser has an
- option with long name 'long_option'."""
- return long_option in self.option_index
-
- def _check_alias_dict (self, aliases, what):
- assert isinstance(aliases, dict)
- for (alias, opt) in aliases.items():
- if alias not in self.option_index:
- raise DistutilsGetoptError, \
- ("invalid %s '%s': "
- "option '%s' not defined") % (what, alias, alias)
- if opt not in self.option_index:
- raise DistutilsGetoptError, \
- ("invalid %s '%s': "
- "aliased option '%s' not defined") % (what, alias, opt)
-
- def set_aliases (self, alias):
- """Set the aliases for this option parser."""
- self._check_alias_dict(alias, "alias")
- self.alias = alias
-
- def set_negative_aliases (self, negative_alias):
- """Set the negative aliases for this option parser.
- 'negative_alias' should be a dictionary mapping option names to
- option names, both the key and value must already be defined
- in the option table."""
- self._check_alias_dict(negative_alias, "negative alias")
- self.negative_alias = negative_alias
-
-
- def _grok_option_table (self):
- """Populate the various data structures that keep tabs on the
- option table. Called by 'getopt()' before it can do anything
- worthwhile.
- """
- self.long_opts = []
- self.short_opts = []
- self.short2long.clear()
- self.repeat = {}
-
- for option in self.option_table:
- if len(option) == 3:
- long, short, help = option
- repeat = 0
- elif len(option) == 4:
- long, short, help, repeat = option
- else:
- # the option table is part of the code, so simply
- # assert that it is correct
- raise ValueError, "invalid option tuple: %r" % (option,)
-
- # Type- and value-check the option names
- if not isinstance(long, str) or len(long) < 2:
- raise DistutilsGetoptError, \
- ("invalid long option '%s': "
- "must be a string of length >= 2") % long
-
- if (not ((short is None) or
- (isinstance(short, str) and len(short) == 1))):
- raise DistutilsGetoptError, \
- ("invalid short option '%s': "
- "must a single character or None") % short
-
- self.repeat[long] = repeat
- self.long_opts.append(long)
-
- if long[-1] == '=': # option takes an argument?
- if short:
- short = short + ':'
- long = long[0:-1]
- self.takes_arg[long] = 1
- else:
-
- # Is option is a "negative alias" for some other option (eg.
- # "quiet" == "!verbose")?
- alias_to = self.negative_alias.get(long)
- if alias_to is not None:
- if self.takes_arg[alias_to]:
- raise DistutilsGetoptError, \
- ("invalid negative alias '%s': "
- "aliased option '%s' takes a value") % \
- (long, alias_to)
-
- self.long_opts[-1] = long # XXX redundant?!
- self.takes_arg[long] = 0
-
- else:
- self.takes_arg[long] = 0
-
- # If this is an alias option, make sure its "takes arg" flag is
- # the same as the option it's aliased to.
- alias_to = self.alias.get(long)
- if alias_to is not None:
- if self.takes_arg[long] != self.takes_arg[alias_to]:
- raise DistutilsGetoptError, \
- ("invalid alias '%s': inconsistent with "
- "aliased option '%s' (one of them takes a value, "
- "the other doesn't") % (long, alias_to)
-
-
- # Now enforce some bondage on the long option name, so we can
- # later translate it to an attribute name on some object. Have
- # to do this a bit late to make sure we've removed any trailing
- # '='.
- if not longopt_re.match(long):
- raise DistutilsGetoptError, \
- ("invalid long option name '%s' " +
- "(must be letters, numbers, hyphens only") % long
-
- self.attr_name[long] = long.replace('-', '_')
- if short:
- self.short_opts.append(short)
- self.short2long[short[0]] = long
-
- # for option_table
-
- # _grok_option_table()
-
-
- def getopt (self, args=None, object=None):
- """Parse command-line options in args. Store as attributes on object.
-
- If 'args' is None or not supplied, uses 'sys.argv[1:]'. If
- 'object' is None or not supplied, creates a new OptionDummy
- object, stores option values there, and returns a tuple (args,
- object). If 'object' is supplied, it is modified in place and
- 'getopt()' just returns 'args'; in both cases, the returned
- 'args' is a modified copy of the passed-in 'args' list, which
- is left untouched.
- """
- if args is None:
- args = sys.argv[1:]
- if object is None:
- object = OptionDummy()
- created_object = 1
- else:
- created_object = 0
-
- self._grok_option_table()
-
- short_opts = string.join(self.short_opts)
- try:
- opts, args = getopt.getopt(args, short_opts, self.long_opts)
- except getopt.error, msg:
- raise DistutilsArgError, msg
-
- for opt, val in opts:
- if len(opt) == 2 and opt[0] == '-': # it's a short option
- opt = self.short2long[opt[1]]
- else:
- assert len(opt) > 2 and opt[:2] == '--'
- opt = opt[2:]
-
- alias = self.alias.get(opt)
- if alias:
- opt = alias
-
- if not self.takes_arg[opt]: # boolean option?
- assert val == '', "boolean option can't have value"
- alias = self.negative_alias.get(opt)
- if alias:
- opt = alias
- val = 0
- else:
- val = 1
-
- attr = self.attr_name[opt]
- # The only repeating option at the moment is 'verbose'.
- # It has a negative option -q quiet, which should set verbose = 0.
- if val and self.repeat.get(attr) is not None:
- val = getattr(object, attr, 0) + 1
- setattr(object, attr, val)
- self.option_order.append((opt, val))
-
- # for opts
- if created_object:
- return args, object
- else:
- return args
-
- # getopt()
-
-
- def get_option_order (self):
- """Returns the list of (option, value) tuples processed by the
- previous run of 'getopt()'. Raises RuntimeError if
- 'getopt()' hasn't been called yet.
- """
- if self.option_order is None:
- raise RuntimeError, "'getopt()' hasn't been called yet"
- else:
- return self.option_order
-
-
- def generate_help (self, header=None):
- """Generate help text (a list of strings, one per suggested line of
- output) from the option table for this FancyGetopt object.
- """
- # Blithely assume the option table is good: probably wouldn't call
- # 'generate_help()' unless you've already called 'getopt()'.
-
- # First pass: determine maximum length of long option names
- max_opt = 0
- for option in self.option_table:
- long = option[0]
- short = option[1]
- l = len(long)
- if long[-1] == '=':
- l = l - 1
- if short is not None:
- l = l + 5 # " (-x)" where short == 'x'
- if l > max_opt:
- max_opt = l
-
- opt_width = max_opt + 2 + 2 + 2 # room for indent + dashes + gutter
-
- # Typical help block looks like this:
- # --foo controls foonabulation
- # Help block for longest option looks like this:
- # --flimflam set the flim-flam level
- # and with wrapped text:
- # --flimflam set the flim-flam level (must be between
- # 0 and 100, except on Tuesdays)
- # Options with short names will have the short name shown (but
- # it doesn't contribute to max_opt):
- # --foo (-f) controls foonabulation
- # If adding the short option would make the left column too wide,
- # we push the explanation off to the next line
- # --flimflam (-l)
- # set the flim-flam level
- # Important parameters:
- # - 2 spaces before option block start lines
- # - 2 dashes for each long option name
- # - min. 2 spaces between option and explanation (gutter)
- # - 5 characters (incl. space) for short option name
-
- # Now generate lines of help text. (If 80 columns were good enough
- # for Jesus, then 78 columns are good enough for me!)
- line_width = 78
- text_width = line_width - opt_width
- big_indent = ' ' * opt_width
- if header:
- lines = [header]
- else:
- lines = ['Option summary:']
-
- for option in self.option_table:
- long, short, help = option[:3]
- text = wrap_text(help, text_width)
- if long[-1] == '=':
- long = long[0:-1]
-
- # Case 1: no short option at all (makes life easy)
- if short is None:
- if text:
- lines.append(" --%-*s %s" % (max_opt, long, text[0]))
- else:
- lines.append(" --%-*s " % (max_opt, long))
-
- # Case 2: we have a short option, so we have to include it
- # just after the long option
- else:
- opt_names = "%s (-%s)" % (long, short)
- if text:
- lines.append(" --%-*s %s" %
- (max_opt, opt_names, text[0]))
- else:
- lines.append(" --%-*s" % opt_names)
-
- for l in text[1:]:
- lines.append(big_indent + l)
-
- # for self.option_table
-
- return lines
-
- # generate_help ()
-
- def print_help (self, header=None, file=None):
- if file is None:
- file = sys.stdout
- for line in self.generate_help(header):
- file.write(line + "\n")
-
-# class FancyGetopt
-
-
-def fancy_getopt (options, negative_opt, object, args):
- parser = FancyGetopt(options)
- parser.set_negative_aliases(negative_opt)
- return parser.getopt(args, object)
-
-
-WS_TRANS = string.maketrans(string.whitespace, ' ' * len(string.whitespace))
-
-def wrap_text (text, width):
- """wrap_text(text : string, width : int) -> [string]
-
- Split 'text' into multiple lines of no more than 'width' characters
- each, and return the list of strings that results.
- """
-
- if text is None:
- return []
- if len(text) <= width:
- return [text]
-
- text = string.expandtabs(text)
- text = string.translate(text, WS_TRANS)
- chunks = re.split(r'( +|-+)', text)
- chunks = filter(None, chunks) # ' - ' results in empty strings
- lines = []
-
- while chunks:
-
- cur_line = [] # list of chunks (to-be-joined)
- cur_len = 0 # length of current line
-
- while chunks:
- l = len(chunks[0])
- if cur_len + l <= width: # can squeeze (at least) this chunk in
- cur_line.append(chunks[0])
- del chunks[0]
- cur_len = cur_len + l
- else: # this line is full
- # drop last chunk if all space
- if cur_line and cur_line[-1][0] == ' ':
- del cur_line[-1]
- break
-
- if chunks: # any chunks left to process?
-
- # if the current line is still empty, then we had a single
- # chunk that's too big too fit on a line -- so we break
- # down and break it up at the line width
- if cur_len == 0:
- cur_line.append(chunks[0][0:width])
- chunks[0] = chunks[0][width:]
-
- # all-whitespace chunks at the end of a line can be discarded
- # (and we know from the re.split above that if a chunk has
- # *any* whitespace, it is *all* whitespace)
- if chunks[0][0] == ' ':
- del chunks[0]
-
- # and store this line in the list-of-all-lines -- as a single
- # string, of course!
- lines.append(string.join(cur_line, ''))
-
- # while chunks
-
- return lines
-
-
-class OptionDummy(object):
- """Dummy class just used as a place to hold command-line option
- values as instance attributes."""
-
- def __init__ (self, options=[]):
- """Create a new OptionDummy instance. The attributes listed in
- 'options' will be initialized to None."""
- for opt in options:
- setattr(self, opt, None)
diff --git a/src/distutils2/index/__init__.py b/src/distutils2/index/__init__.py
deleted file mode 100644
index 312662f..0000000
--- a/src/distutils2/index/__init__.py
+++ /dev/null
@@ -1,11 +0,0 @@
-"""Package containing ways to interact with Index APIs.
-
-"""
-
-__all__ = ['simple',
- 'xmlrpc',
- 'dist',
- 'errors',
- 'mirrors',]
-
-from dist import ReleaseInfo, ReleasesList, DistInfo
diff --git a/src/distutils2/index/base.py b/src/distutils2/index/base.py
deleted file mode 100644
index 04582a3..0000000
--- a/src/distutils2/index/base.py
+++ /dev/null
@@ -1,46 +0,0 @@
-from distutils2.index.dist import ReleasesList
-
-
-class BaseClient(object):
- """Base class containing common methods for the index crawlers/clients"""
-
- def __init__(self, prefer_final, prefer_source):
- self._prefer_final = prefer_final
- self._prefer_source = prefer_source
- self._index = self
-
- def _get_prefer_final(self, prefer_final=None):
- """Return the prefer_final internal parameter or the specified one if
- provided"""
- if prefer_final:
- return prefer_final
- else:
- return self._prefer_final
-
- def _get_prefer_source(self, prefer_source=None):
- """Return the prefer_source internal parameter or the specified one if
- provided"""
- if prefer_source:
- return prefer_source
- else:
- return self._prefer_source
-
- def _get_project(self, project_name):
- """Return an project instance, create it if necessary"""
- return self._projects.setdefault(project_name.lower(),
- ReleasesList(project_name, index=self._index))
-
- def download_distribution(self, requirements, temp_path=None,
- prefer_source=None, prefer_final=None):
- """Download a distribution from the last release according to the
- requirements.
-
- If temp_path is provided, download to this path, otherwise, create a
- temporary location for the download and return it.
- """
- prefer_final = self._get_prefer_final(prefer_final)
- prefer_source = self._get_prefer_source(prefer_source)
- release = self.get_release(requirements, prefer_final)
- if release:
- dist = release.get_distribution(prefer_source=prefer_source)
- return dist.download(temp_path)
diff --git a/src/distutils2/index/dist.py b/src/distutils2/index/dist.py
deleted file mode 100644
index f5d0fd9..0000000
--- a/src/distutils2/index/dist.py
+++ /dev/null
@@ -1,544 +0,0 @@
-"""distutils2.index.dist
-
-Provides useful classes to represent the release and distributions retrieved
-from indexes.
-
-A project can have several releases (=versions) and each release can have
-several distributions (sdist, bdist).
-
-The release contains the metadata related informations (see PEP 384), and the
-distributions contains download related informations.
-
-"""
-import mimetypes
-import re
-import tarfile
-import tempfile
-import urllib
-import urlparse
-import zipfile
-
-try:
- import hashlib
-except ImportError:
- from distutils2._backport import hashlib
-
-from distutils2.errors import IrrationalVersionError
-from distutils2.index.errors import (HashDoesNotMatch, UnsupportedHashName,
- CantParseArchiveName)
-from distutils2.version import (suggest_normalized_version, NormalizedVersion,
- get_version_predicate)
-from distutils2.metadata import DistributionMetadata
-from distutils2.util import untar_file, unzip_file, splitext
-
-__all__ = ['ReleaseInfo', 'DistInfo', 'ReleasesList', 'get_infos_from_url']
-
-EXTENSIONS = ".tar.gz .tar.bz2 .tar .zip .tgz .egg".split()
-MD5_HASH = re.compile(r'^.*#md5=([a-f0-9]+)$')
-DIST_TYPES = ['bdist', 'sdist']
-
-
-class IndexReference(object):
- """Mixin used to store the index reference"""
- def set_index(self, index=None):
- self._index = index
-
-
-class ReleaseInfo(IndexReference):
- """Represent a release of a project (a project with a specific version).
- The release contain the _metadata informations related to this specific
- version, and is also a container for distribution related informations.
-
- See the DistInfo class for more information about distributions.
- """
-
- def __init__(self, name, version, metadata=None, hidden=False,
- index=None, **kwargs):
- """
- :param name: the name of the distribution
- :param version: the version of the distribution
- :param metadata: the metadata fields of the release.
- :type metadata: dict
- :param kwargs: optional arguments for a new distribution.
- """
- self.set_index(index)
- self.name = name
- self._version = None
- self.version = version
- if metadata:
- self.metadata = DistributionMetadata(mapping=metadata)
- else:
- self.metadata = None
- self.dists = {}
- self.hidden = hidden
-
- if 'dist_type' in kwargs:
- dist_type = kwargs.pop('dist_type')
- self.add_distribution(dist_type, **kwargs)
-
- def set_version(self, version):
- try:
- self._version = NormalizedVersion(version)
- except IrrationalVersionError:
- suggestion = suggest_normalized_version(version)
- if suggestion:
- self.version = suggestion
- else:
- raise IrrationalVersionError(version)
-
- def get_version(self):
- return self._version
-
- version = property(get_version, set_version)
-
- def fetch_metadata(self):
- """If the metadata is not set, use the indexes to get it"""
- if not self.metadata:
- self._index.get_metadata(self.name, '%s' % self.version)
- return self.metadata
-
- @property
- def is_final(self):
- """proxy to version.is_final"""
- return self.version.is_final
-
- def fetch_distributions(self):
- if self.dists is None:
- self._index.get_distributions(self.name, '%s' % self.version)
- if self.dists is None:
- self.dists = {}
- return self.dists
-
- def add_distribution(self, dist_type='sdist', python_version=None, **params):
- """Add distribution informations to this release.
- If distribution information is already set for this distribution type,
- add the given url paths to the distribution. This can be useful while
- some of them fails to download.
-
- :param dist_type: the distribution type (eg. "sdist", "bdist", etc.)
- :param params: the fields to be passed to the distribution object
- (see the :class:DistInfo constructor).
- """
- if dist_type not in DIST_TYPES:
- raise ValueError(dist_type)
- if dist_type in self.dists:
- self.dists[dist_type].add_url(**params)
- else:
- self.dists[dist_type] = DistInfo(self, dist_type,
- index=self._index, **params)
- if python_version:
- self.dists[dist_type].python_version = python_version
-
- def get_distribution(self, dist_type=None, prefer_source=True):
- """Return a distribution.
-
- If dist_type is set, find first for this distribution type, and just
- act as an alias of __get_item__.
-
- If prefer_source is True, search first for source distribution, and if
- not return one existing distribution.
- """
- if len(self.dists) == 0:
- raise LookupError()
- if dist_type:
- return self[dist_type]
- if prefer_source:
- if "sdist" in self.dists:
- dist = self["sdist"]
- else:
- dist = self.dists.values()[0]
- return dist
-
- def download(self, temp_path=None, prefer_source=True):
- """Download the distribution, using the requirements.
-
- If more than one distribution match the requirements, use the last
- version.
- Download the distribution, and put it in the temp_path. If no temp_path
- is given, creates and return one.
-
- Returns the complete absolute path to the downloaded archive.
- """
- return self.get_distribution(prefer_source=prefer_source)\
- .download(path=temp_path)
-
- def set_metadata(self, metadata):
- if not self.metadata:
- self.metadata = DistributionMetadata()
- self.metadata.update(metadata)
-
- def __getitem__(self, item):
- """distributions are available using release["sdist"]"""
- return self.dists[item]
-
- def _check_is_comparable(self, other):
- if not isinstance(other, ReleaseInfo):
- raise TypeError("cannot compare %s and %s"
- % (type(self).__name__, type(other).__name__))
- elif self.name != other.name:
- raise TypeError("cannot compare %s and %s"
- % (self.name, other.name))
-
- def __repr__(self):
- return "<%s %s>" % (self.name, self.version)
-
- def __eq__(self, other):
- self._check_is_comparable(other)
- return self.version == other.version
-
- def __lt__(self, other):
- self._check_is_comparable(other)
- return self.version < other.version
-
- def __ne__(self, other):
- return not self.__eq__(other)
-
- def __gt__(self, other):
- return not (self.__lt__(other) or self.__eq__(other))
-
- def __le__(self, other):
- return self.__eq__(other) or self.__lt__(other)
-
- def __ge__(self, other):
- return self.__eq__(other) or self.__gt__(other)
-
- # See http://docs.python.org/reference/datamodel#object.__hash__
- __hash__ = object.__hash__
-
-
-class DistInfo(IndexReference):
- """Represents a distribution retrieved from an index (sdist, bdist, ...)
- """
-
- def __init__(self, release, dist_type=None, url=None, hashname=None,
- hashval=None, is_external=True, python_version=None,
- index=None):
- """Create a new instance of DistInfo.
-
- :param release: a DistInfo class is relative to a release.
- :param dist_type: the type of the dist (eg. source, bin-*, etc.)
- :param url: URL where we found this distribution
- :param hashname: the name of the hash we want to use. Refer to the
- hashlib.new documentation for more information.
- :param hashval: the hash value.
- :param is_external: we need to know if the provided url comes from
- an index browsing, or from an external resource.
-
- """
- self.set_index(index)
- self.release = release
- self.dist_type = dist_type
- self.python_version = python_version
- self._unpacked_dir = None
- # set the downloaded path to None by default. The goal here
- # is to not download distributions multiple times
- self.downloaded_location = None
- # We store urls in dict, because we need to have a bit more infos
- # than the simple URL. It will be used later to find the good url to
- # use.
- # We have two _url* attributes: _url and urls. urls contains a list
- # of dict for the different urls, and _url contains the choosen url, in
- # order to dont make the selection process multiple times.
- self.urls = []
- self._url = None
- self.add_url(url, hashname, hashval, is_external)
-
- def add_url(self, url, hashname=None, hashval=None, is_external=True):
- """Add a new url to the list of urls"""
- if hashname is not None:
- try:
- hashlib.new(hashname)
- except ValueError:
- raise UnsupportedHashName(hashname)
- if not url in [u['url'] for u in self.urls]:
- self.urls.append({
- 'url': url,
- 'hashname': hashname,
- 'hashval': hashval,
- 'is_external': is_external,
- })
- # reset the url selection process
- self._url = None
-
- @property
- def url(self):
- """Pick up the right url for the list of urls in self.urls"""
- # We return internal urls over externals.
- # If there is more than one internal or external, return the first
- # one.
- if self._url is None:
- if len(self.urls) > 1:
- internals_urls = [u for u in self.urls \
- if u['is_external'] == False]
- if len(internals_urls) >= 1:
- self._url = internals_urls[0]
- if self._url is None:
- self._url = self.urls[0]
- return self._url
-
- @property
- def is_source(self):
- """return if the distribution is a source one or not"""
- return self.dist_type == 'sdist'
-
- def download(self, path=None):
- """Download the distribution to a path, and return it.
-
- If the path is given in path, use this, otherwise, generates a new one
- Return the download location.
- """
- if path is None:
- path = tempfile.mkdtemp()
-
- # if we do not have downloaded it yet, do it.
- if self.downloaded_location is None:
- url = self.url['url']
- archive_name = urlparse.urlparse(url)[2].split('/')[-1]
- filename, headers = urllib.urlretrieve(url,
- path + "/" + archive_name)
- self.downloaded_location = filename
- self._check_md5(filename)
- return self.downloaded_location
-
- def unpack(self, path=None):
- """Unpack the distribution to the given path.
-
- If not destination is given, creates a temporary location.
-
- Returns the location of the extracted files (root).
- """
- if not self._unpacked_dir:
- if path is None:
- path = tempfile.mkdtemp()
-
- filename = self.download()
- content_type = mimetypes.guess_type(filename)[0]
-
- if (content_type == 'application/zip'
- or filename.endswith('.zip')
- or filename.endswith('.pybundle')
- or zipfile.is_zipfile(filename)):
- unzip_file(filename, path, flatten=not filename.endswith('.pybundle'))
- elif (content_type == 'application/x-gzip'
- or tarfile.is_tarfile(filename)
- or splitext(filename)[1].lower() in ('.tar', '.tar.gz', '.tar.bz2', '.tgz', '.tbz')):
- untar_file(filename, path)
- self._unpacked_dir = path
- return self._unpacked_dir
-
- def _check_md5(self, filename):
- """Check that the md5 checksum of the given file matches the one in
- url param"""
- hashname = self.url['hashname']
- expected_hashval = self.url['hashval']
- if not None in (expected_hashval, hashname):
- f = open(filename)
- hashval = hashlib.new(hashname)
- hashval.update(f.read())
- if hashval.hexdigest() != expected_hashval:
- raise HashDoesNotMatch("got %s instead of %s"
- % (hashval.hexdigest(), expected_hashval))
-
- def __repr__(self):
- return "<%s %s %s>" % (
- self.release.name, self.release.version, self.dist_type or "")
-
-
-class ReleasesList(IndexReference):
- """A container of Release.
-
- Provides useful methods and facilities to sort and filter releases.
- """
- def __init__(self, name, releases=None, contains_hidden=False, index=None):
- self.set_index(index)
- self.releases = []
- self.name = name
- self.contains_hidden = contains_hidden
- if releases:
- self.add_releases(releases)
-
- def fetch_releases(self):
- self._index.get_releases(self.name)
- return self.releases
-
- def filter(self, predicate):
- """Filter and return a subset of releases matching the given predicate.
- """
- return ReleasesList(self.name, [release for release in self.releases
- if predicate.match(release.version)],
- index=self._index)
-
- def get_last(self, requirements, prefer_final=None):
- """Return the "last" release, that satisfy the given predicates.
-
- "last" is defined by the version number of the releases, you also could
- set prefer_final parameter to True or False to change the order results
- """
- predicate = get_version_predicate(requirements)
- releases = self.filter(predicate)
- releases.sort_releases(prefer_final, reverse=True)
- return releases[0]
-
- def add_releases(self, releases):
- """Add releases in the release list.
-
- :param: releases is a list of ReleaseInfo objects.
- """
- for r in releases:
- self.add_release(release=r)
-
- def add_release(self, version=None, dist_type='sdist', release=None,
- **dist_args):
- """Add a release to the list.
-
- The release can be passed in the `release` parameter, and in this case,
- it will be crawled to extract the useful informations if necessary, or
- the release informations can be directly passed in the `version` and
- `dist_type` arguments.
-
- Other keywords arguments can be provided, and will be forwarded to the
- distribution creation (eg. the arguments of the DistInfo constructor).
- """
- if release:
- if release.name.lower() != self.name.lower():
- raise ValueError("%s is not the same project than %s" %
- (release.name, self.name))
- version = '%s' % release.version
-
- if not version in self.get_versions():
- # append only if not already exists
- self.releases.append(release)
- for dist in release.dists.values():
- for url in dist.urls:
- self.add_release(version, dist.dist_type, **url)
- else:
- matches = [r for r in self.releases if '%s' % r.version == version
- and r.name == self.name]
- if not matches:
- release = ReleaseInfo(self.name, version, index=self._index)
- self.releases.append(release)
- else:
- release = matches[0]
-
- release.add_distribution(dist_type=dist_type, **dist_args)
-
- def sort_releases(self, prefer_final=False, reverse=True, *args, **kwargs):
- """Sort the results with the given properties.
-
- The `prefer_final` argument can be used to specify if final
- distributions (eg. not dev, bet or alpha) would be prefered or not.
-
- Results can be inverted by using `reverse`.
-
- Any other parameter provided will be forwarded to the sorted call. You
- cannot redefine the key argument of "sorted" here, as it is used
- internally to sort the releases.
- """
-
- sort_by = []
- if prefer_final:
- sort_by.append("is_final")
- sort_by.append("version")
-
- self.releases.sort(
- key=lambda i: [getattr(i, arg) for arg in sort_by],
- reverse=reverse, *args, **kwargs)
-
- def get_release(self, version):
- """Return a release from it's version.
- """
- matches = [r for r in self.releases if "%s" % r.version == version]
- if len(matches) != 1:
- raise KeyError(version)
- return matches[0]
-
- def get_versions(self):
- """Return a list of releases versions contained"""
- return ["%s" % r.version for r in self.releases]
-
- def __getitem__(self, key):
- return self.releases[key]
-
- def __len__(self):
- return len(self.releases)
-
- def __repr__(self):
- string = 'Project "%s"' % self.name
- if self.get_versions():
- string += ' versions: %s' % ', '.join(self.get_versions())
- return '<%s>' % string
-
-
-def get_infos_from_url(url, probable_dist_name=None, is_external=True):
- """Get useful informations from an URL.
-
- Return a dict of (name, version, url, hashtype, hash, is_external)
-
- :param url: complete url of the distribution
- :param probable_dist_name: A probable name of the project.
- :param is_external: Tell if the url commes from an index or from
- an external URL.
- """
- # if the url contains a md5 hash, get it.
- md5_hash = None
- match = MD5_HASH.match(url)
- if match is not None:
- md5_hash = match.group(1)
- # remove the hash
- url = url.replace("#md5=%s" % md5_hash, "")
-
- # parse the archive name to find dist name and version
- archive_name = urlparse.urlparse(url)[2].split('/')[-1]
- extension_matched = False
- # remove the extension from the name
- for ext in EXTENSIONS:
- if archive_name.endswith(ext):
- archive_name = archive_name[:-len(ext)]
- extension_matched = True
-
- name, version = split_archive_name(archive_name)
- if extension_matched is True:
- return {'name': name,
- 'version': version,
- 'url': url,
- 'hashname': "md5",
- 'hashval': md5_hash,
- 'is_external': is_external,
- 'dist_type': 'sdist'}
-
-
-def split_archive_name(archive_name, probable_name=None):
- """Split an archive name into two parts: name and version.
-
- Return the tuple (name, version)
- """
- # Try to determine wich part is the name and wich is the version using the
- # "-" separator. Take the larger part to be the version number then reduce
- # if this not works.
- def eager_split(str, maxsplit=2):
- # split using the "-" separator
- splits = str.rsplit("-", maxsplit)
- name = splits[0]
- version = "-".join(splits[1:])
- if version.startswith("-"):
- version = version[1:]
- if suggest_normalized_version(version) is None and maxsplit >= 0:
- # we dont get a good version number: recurse !
- return eager_split(str, maxsplit - 1)
- else:
- return (name, version)
- if probable_name is not None:
- probable_name = probable_name.lower()
- name = None
- if probable_name is not None and probable_name in archive_name:
- # we get the name from probable_name, if given.
- name = probable_name
- version = archive_name.lstrip(name)
- else:
- name, version = eager_split(archive_name)
-
- version = suggest_normalized_version(version)
- if version is not None and name != "":
- return (name.lower(), version)
- else:
- raise CantParseArchiveName(archive_name)
diff --git a/src/distutils2/index/errors.py b/src/distutils2/index/errors.py
deleted file mode 100644
index e6e5870..0000000
--- a/src/distutils2/index/errors.py
+++ /dev/null
@@ -1,41 +0,0 @@
-"""distutils2.pypi.errors
-
-All errors and exceptions raised by PyPiIndex classes.
-"""
-from distutils2.errors import DistutilsIndexError
-
-
-class ProjectNotFound(DistutilsIndexError):
- """Project has not been found"""
-
-
-class DistributionNotFound(DistutilsIndexError):
- """The release has not been found"""
-
-
-class ReleaseNotFound(DistutilsIndexError):
- """The release has not been found"""
-
-
-class CantParseArchiveName(DistutilsIndexError):
- """An archive name can't be parsed to find distribution name and version"""
-
-
-class DownloadError(DistutilsIndexError):
- """An error has occurs while downloading"""
-
-
-class HashDoesNotMatch(DownloadError):
- """Compared hashes does not match"""
-
-
-class UnsupportedHashName(DistutilsIndexError):
- """A unsupported hashname has been used"""
-
-
-class UnableToDownload(DistutilsIndexError):
- """All mirrors have been tried, without success"""
-
-
-class InvalidSearchField(DistutilsIndexError):
- """An invalid search field has been used"""
diff --git a/src/distutils2/index/mirrors.py b/src/distutils2/index/mirrors.py
deleted file mode 100644
index 49d5dd1..0000000
--- a/src/distutils2/index/mirrors.py
+++ /dev/null
@@ -1,52 +0,0 @@
-"""Utilities related to the mirror infrastructure defined in PEP 381.
-See http://www.python.org/dev/peps/pep-0381/
-"""
-
-from string import ascii_lowercase
-import socket
-
-DEFAULT_MIRROR_URL = "last.pypi.python.org"
-
-def get_mirrors(hostname=None):
- """Return the list of mirrors from the last record found on the DNS
- entry::
-
- >>> from distutils2.index.mirrors import get_mirrors
- >>> get_mirrors()
- ['a.pypi.python.org', 'b.pypi.python.org', 'c.pypi.python.org',
- 'd.pypi.python.org']
-
- """
- if hostname is None:
- hostname = DEFAULT_MIRROR_URL
-
- # return the last mirror registered on PyPI.
- try:
- hostname = socket.gethostbyname_ex(hostname)[0]
- except socket.gaierror:
- return []
- end_letter = hostname.split(".", 1)
-
- # determine the list from the last one.
- return ["%s.%s" % (s, end_letter[1]) for s in string_range(end_letter[0])]
-
-def string_range(last):
- """Compute the range of string between "a" and last.
-
- This works for simple "a to z" lists, but also for "a to zz" lists.
- """
- for k in range(len(last)):
- for x in product(ascii_lowercase, repeat=k+1):
- result = ''.join(x)
- yield result
- if result == last:
- return
-
-def product(*args, **kwds):
- pools = map(tuple, args) * kwds.get('repeat', 1)
- result = [[]]
- for pool in pools:
- result = [x+[y] for x in result for y in pool]
- for prod in result:
- yield tuple(prod)
-
diff --git a/src/distutils2/index/simple.py b/src/distutils2/index/simple.py
deleted file mode 100644
index 75fb851..0000000
--- a/src/distutils2/index/simple.py
+++ /dev/null
@@ -1,434 +0,0 @@
-"""index.simple
-
-Contains the class "SimpleIndexCrawler", a simple spider to find and retrieve
-distributions on the Python Package Index, using it's "simple" API,
-avalaible at http://pypi.python.org/simple/
-"""
-from fnmatch import translate
-import httplib
-import re
-import socket
-import sys
-import urllib2
-import urlparse
-import logging
-import os
-
-from distutils2.index.base import BaseClient
-from distutils2.index.dist import (ReleasesList, EXTENSIONS,
- get_infos_from_url, MD5_HASH)
-from distutils2.index.errors import (DistutilsIndexError, DownloadError,
- UnableToDownload, CantParseArchiveName,
- ReleaseNotFound, ProjectNotFound)
-from distutils2.index.mirrors import get_mirrors
-from distutils2.metadata import DistributionMetadata
-from distutils2.version import get_version_predicate
-from distutils2 import __version__ as __distutils2_version__
-
-__all__ = ['Crawler', 'DEFAULT_SIMPLE_INDEX_URL']
-
-# -- Constants -----------------------------------------------
-DEFAULT_SIMPLE_INDEX_URL = "http://a.pypi.python.org/simple/"
-DEFAULT_HOSTS = ("*",)
-SOCKET_TIMEOUT = 15
-USER_AGENT = "Python-urllib/%s distutils2/%s" % (
- sys.version[:3], __distutils2_version__)
-
-# -- Regexps -------------------------------------------------
-EGG_FRAGMENT = re.compile(r'^egg=([-A-Za-z0-9_.]+)$')
-HREF = re.compile("""href\\s*=\\s*['"]?([^'"> ]+)""", re.I)
-URL_SCHEME = re.compile('([-+.a-z0-9]{2,}):', re.I).match
-
-# This pattern matches a character entity reference (a decimal numeric
-# references, a hexadecimal numeric reference, or a named reference).
-ENTITY_SUB = re.compile(r'&(#(\d+|x[\da-fA-F]+)|[\w.:-]+);?').sub
-REL = re.compile("""<([^>]*\srel\s*=\s*['"]?([^'">]+)[^>]*)>""", re.I)
-
-
-def socket_timeout(timeout=SOCKET_TIMEOUT):
- """Decorator to add a socket timeout when requesting pages on PyPI.
- """
- def _socket_timeout(func):
- def _socket_timeout(self, *args, **kwargs):
- old_timeout = socket.getdefaulttimeout()
- if hasattr(self, "_timeout"):
- timeout = self._timeout
- socket.setdefaulttimeout(timeout)
- try:
- return func(self, *args, **kwargs)
- finally:
- socket.setdefaulttimeout(old_timeout)
- return _socket_timeout
- return _socket_timeout
-
-
-def with_mirror_support():
- """Decorator that makes the mirroring support easier"""
- def wrapper(func):
- def wrapped(self, *args, **kwargs):
- try:
- return func(self, *args, **kwargs)
- except DownloadError:
- # if an error occurs, try with the next index_url
- if self._mirrors_tries >= self._mirrors_max_tries:
- try:
- self._switch_to_next_mirror()
- except KeyError:
- raise UnableToDownload("Tried all mirrors")
- else:
- self._mirrors_tries += 1
- self._projects.clear()
- return wrapped(self, *args, **kwargs)
- return wrapped
- return wrapper
-
-
-class Crawler(BaseClient):
- """Provides useful tools to request the Python Package Index simple API.
-
- You can specify both mirrors and mirrors_url, but mirrors_url will only be
- used if mirrors is set to None.
-
- :param index_url: the url of the simple index to search on.
- :param prefer_final: if the version is not mentioned, and the last
- version is not a "final" one (alpha, beta, etc.),
- pick up the last final version.
- :param prefer_source: if the distribution type is not mentioned, pick up
- the source one if available.
- :param follow_externals: tell if following external links is needed or
- not. Default is False.
- :param hosts: a list of hosts allowed to be processed while using
- follow_externals=True. Default behavior is to follow all
- hosts.
- :param follow_externals: tell if following external links is needed or
- not. Default is False.
- :param mirrors_url: the url to look on for DNS records giving mirror
- adresses.
- :param mirrors: a list of mirrors (see PEP 381).
- :param timeout: time in seconds to consider a url has timeouted.
- :param mirrors_max_tries": number of times to try requesting informations
- on mirrors before switching.
- """
-
- def __init__(self, index_url=DEFAULT_SIMPLE_INDEX_URL, prefer_final=False,
- prefer_source=True, hosts=DEFAULT_HOSTS,
- follow_externals=False, mirrors_url=None, mirrors=None,
- timeout=SOCKET_TIMEOUT, mirrors_max_tries=0):
- super(Crawler, self).__init__(prefer_final, prefer_source)
- self.follow_externals = follow_externals
-
- # mirroring attributes.
- if not index_url.endswith("/"):
- index_url += "/"
- # if no mirrors are defined, use the method described in PEP 381.
- if mirrors is None:
- mirrors = get_mirrors(mirrors_url)
- self._mirrors = set(mirrors)
- self._mirrors_used = set()
- self.index_url = index_url
- self._mirrors_max_tries = mirrors_max_tries
- self._mirrors_tries = 0
- self._timeout = timeout
-
- # create a regexp to match all given hosts
- self._allowed_hosts = re.compile('|'.join(map(translate, hosts))).match
-
- # we keep an index of pages we have processed, in order to avoid
- # scanning them multple time (eg. if there is multiple pages pointing
- # on one)
- self._processed_urls = []
- self._projects = {}
-
- @with_mirror_support()
- def search_projects(self, name=None, **kwargs):
- """Search the index for projects containing the given name.
-
- Return a list of names.
- """
- index = self._open_url(self.index_url)
- projectname = re.compile("""<a[^>]*>(.?[^<]*%s.?[^<]*)</a>""" % name,
- flags=re.I)
- matching_projects = []
- for match in projectname.finditer(index.read()):
- project_name = match.group(1)
- matching_projects.append(self._get_project(project_name))
- return matching_projects
-
- def get_releases(self, requirements, prefer_final=None,
- force_update=False):
- """Search for releases and return a ReleaseList object containing
- the results.
- """
- predicate = get_version_predicate(requirements)
- if predicate.name.lower() in self._projects and not force_update:
- return self._projects.get(predicate.name.lower())
- prefer_final = self._get_prefer_final(prefer_final)
- self._process_index_page(predicate.name)
-
- if predicate.name.lower() not in self._projects:
- raise ProjectNotFound()
-
- releases = self._projects.get(predicate.name.lower())
- releases.sort_releases(prefer_final=prefer_final)
- return releases
-
- def get_release(self, requirements, prefer_final=None):
- """Return only one release that fulfill the given requirements"""
- predicate = get_version_predicate(requirements)
- release = self.get_releases(predicate, prefer_final)\
- .get_last(predicate)
- if not release:
- raise ReleaseNotFound("No release matches the given criterias")
- return release
-
- def get_distributions(self, project_name, version):
- """Return the distributions found on the index for the specific given
- release"""
- # as the default behavior of get_release is to return a release
- # containing the distributions, just alias it.
- return self.get_release("%s (%s)" % (project_name, version))
-
- def get_metadata(self, project_name, version):
- """Return the metadatas from the simple index.
-
- Currently, download one archive, extract it and use the PKG-INFO file.
- """
- release = self.get_distributions(project_name, version)
- if not release._metadata:
- location = release.get_distribution().unpack()
- pkg_info = os.path.join(location, 'PKG-INFO')
- release._metadata = DistributionMetadata(pkg_info)
- return release
-
- def _switch_to_next_mirror(self):
- """Switch to the next mirror (eg. point self.index_url to the next
- mirror url.
-
- Raise a KeyError if all mirrors have been tried.
- """
- self._mirrors_used.add(self.index_url)
- index_url = self._mirrors.pop()
- if not ("http://" or "https://" or "file://") in index_url:
- index_url = "http://%s" % index_url
-
- if not index_url.endswith("/simple"):
- index_url = "%s/simple/" % index_url
-
- self.index_url = index_url
-
- def _is_browsable(self, url):
- """Tell if the given URL can be browsed or not.
-
- It uses the follow_externals and the hosts list to tell if the given
- url is browsable or not.
- """
- # if _index_url is contained in the given URL, we are browsing the
- # index, and it's always "browsable".
- # local files are always considered browable resources
- if self.index_url in url or urlparse.urlparse(url)[0] == "file":
- return True
- elif self.follow_externals:
- if self._allowed_hosts(urlparse.urlparse(url)[1]): # 1 is netloc
- return True
- else:
- return False
- return False
-
- def _is_distribution(self, link):
- """Tell if the given URL matches to a distribution name or not.
- """
- #XXX find a better way to check that links are distributions
- # Using a regexp ?
- for ext in EXTENSIONS:
- if ext in link:
- return True
- return False
-
- def _register_release(self, release=None, release_info={}):
- """Register a new release.
-
- Both a release or a dict of release_info can be provided, the prefered
- way (eg. the quicker) is the dict one.
-
- Return the list of existing releases for the given project.
- """
- # Check if the project already has a list of releases (refering to
- # the project name). If not, create a new release list.
- # Then, add the release to the list.
- if release:
- name = release.name
- else:
- name = release_info['name']
- if not name.lower() in self._projects:
- self._projects[name.lower()] = ReleasesList(name,
- index=self._index)
-
- if release:
- self._projects[name.lower()].add_release(release=release)
- else:
- name = release_info.pop('name')
- version = release_info.pop('version')
- dist_type = release_info.pop('dist_type')
- self._projects[name.lower()].add_release(version, dist_type,
- **release_info)
- return self._projects[name.lower()]
-
- def _process_url(self, url, project_name=None, follow_links=True):
- """Process an url and search for distributions packages.
-
- For each URL found, if it's a download, creates a PyPIdistribution
- object. If it's a homepage and we can follow links, process it too.
-
- :param url: the url to process
- :param project_name: the project name we are searching for.
- :param follow_links: Do not want to follow links more than from one
- level. This parameter tells if we want to follow
- the links we find (eg. run recursively this
- method on it)
- """
- f = self._open_url(url)
- base_url = f.url
- if url not in self._processed_urls:
- self._processed_urls.append(url)
- link_matcher = self._get_link_matcher(url)
- for link, is_download in link_matcher(f.read(), base_url):
- if link not in self._processed_urls:
- if self._is_distribution(link) or is_download:
- self._processed_urls.append(link)
- # it's a distribution, so create a dist object
- try:
- infos = get_infos_from_url(link, project_name,
- is_external=not self.index_url in url)
- except CantParseArchiveName, e:
- logging.warning("version has not been parsed: %s"
- % e)
- else:
- self._register_release(release_info=infos)
- else:
- if self._is_browsable(link) and follow_links:
- self._process_url(link, project_name,
- follow_links=False)
-
- def _get_link_matcher(self, url):
- """Returns the right link matcher function of the given url
- """
- if self.index_url in url:
- return self._simple_link_matcher
- else:
- return self._default_link_matcher
-
- def _get_full_url(self, url, base_url):
- return urlparse.urljoin(base_url, self._htmldecode(url))
-
- def _simple_link_matcher(self, content, base_url):
- """Yield all links with a rel="download" or rel="homepage".
-
- This matches the simple index requirements for matching links.
- If follow_externals is set to False, dont yeld the external
- urls.
- """
- for match in HREF.finditer(content):
- url = self._get_full_url(match.group(1), base_url)
- if MD5_HASH.match(url):
- yield (url, True)
-
- for match in REL.finditer(content):
- # search for rel links.
- tag, rel = match.groups()
- rels = map(str.strip, rel.lower().split(','))
- if 'homepage' in rels or 'download' in rels:
- for match in HREF.finditer(tag):
- url = self._get_full_url(match.group(1), base_url)
- if 'download' in rels or self._is_browsable(url):
- # yield a list of (url, is_download)
- yield (url, 'download' in rels)
-
- def _default_link_matcher(self, content, base_url):
- """Yield all links found on the page.
- """
- for match in HREF.finditer(content):
- url = self._get_full_url(match.group(1), base_url)
- if self._is_browsable(url):
- yield (url, False)
-
- @with_mirror_support()
- def _process_index_page(self, name):
- """Find and process a PyPI page for the given project name.
-
- :param name: the name of the project to find the page
- """
- # Browse and index the content of the given PyPI page.
- url = self.index_url + name + "/"
- self._process_url(url, name)
-
- @socket_timeout()
- def _open_url(self, url):
- """Open a urllib2 request, handling HTTP authentication, and local
- files support.
-
- """
- scheme, netloc, path, params, query, frag = urlparse.urlparse(url)
-
- # authentication stuff
- if scheme in ('http', 'https'):
- auth, host = urllib2.splituser(netloc)
- else:
- auth = None
-
- # add index.html automatically for filesystem paths
- if scheme == 'file':
- if url.endswith('/'):
- url += "index.html"
-
- # add authorization headers if auth is provided
- if auth:
- auth = "Basic " + \
- urllib2.unquote(auth).encode('base64').strip()
- new_url = urlparse.urlunparse((
- scheme, host, path, params, query, frag))
- request = urllib2.Request(new_url)
- request.add_header("Authorization", auth)
- else:
- request = urllib2.Request(url)
- request.add_header('User-Agent', USER_AGENT)
- try:
- fp = urllib2.urlopen(request)
- except (ValueError, httplib.InvalidURL), v:
- msg = ' '.join([str(arg) for arg in v.args])
- raise DistutilsIndexError('%s %s' % (url, msg))
- except urllib2.HTTPError, v:
- return v
- except urllib2.URLError, v:
- raise DownloadError("Download error for %s: %s" % (url, v.reason))
- except httplib.BadStatusLine, v:
- raise DownloadError('%s returned a bad status line. '
- 'The server might be down, %s' % (url, v.line))
- except httplib.HTTPException, v:
- raise DownloadError("Download error for %s: %s" % (url, v))
- except socket.timeout:
- raise DownloadError("The server timeouted")
-
- if auth:
- # Put authentication info back into request URL if same host,
- # so that links found on the page will work
- s2, h2, path2, param2, query2, frag2 = \
- urlparse.urlparse(fp.url)
- if s2 == scheme and h2 == host:
- fp.url = urlparse.urlunparse(
- (s2, netloc, path2, param2, query2, frag2))
- return fp
-
- def _decode_entity(self, match):
- what = match.group(1)
- if what.startswith('#x'):
- what = int(what[2:], 16)
- elif what.startswith('#'):
- what = int(what[1:])
- else:
- from htmlentitydefs import name2codepoint
- what = name2codepoint.get(what, match.group(0))
- return unichr(what)
-
- def _htmldecode(self, text):
- """Decode HTML entities in the given text."""
- return ENTITY_SUB(self._decode_entity, text)
diff --git a/src/distutils2/index/wrapper.py b/src/distutils2/index/wrapper.py
deleted file mode 100644
index e3c4551..0000000
--- a/src/distutils2/index/wrapper.py
+++ /dev/null
@@ -1,93 +0,0 @@
-import xmlrpc
-import simple
-
-_WRAPPER_MAPPINGS = {'get_release': 'simple',
- 'get_releases': 'simple',
- 'search_projects': 'simple',
- 'get_metadata': 'xmlrpc',
- 'get_distributions': 'simple'}
-
-_WRAPPER_INDEXES = {'xmlrpc': xmlrpc.Client,
- 'simple': simple.Crawler}
-
-def switch_index_if_fails(func, wrapper):
- """Decorator that switch of index (for instance from xmlrpc to simple)
- if the first mirror return an empty list or raises an exception.
- """
- def decorator(*args, **kwargs):
- retry = True
- exception = None
- methods = [func]
- for f in wrapper._indexes.values():
- if f != func.im_self and hasattr(f, func.__name__):
- methods.append(getattr(f, func.__name__))
- for method in methods:
- try:
- response = method(*args, **kwargs)
- retry = False
- except Exception, e:
- exception = e
- if not retry:
- break
- if retry and exception:
- raise exception
- else:
- return response
- return decorator
-
-
-class ClientWrapper(object):
- """Wrapper around simple and xmlrpc clients,
-
- Choose the best implementation to use depending the needs, using the given
- mappings.
- If one of the indexes returns an error, tries to use others indexes.
-
- :param index: tell wich index to rely on by default.
- :param index_classes: a dict of name:class to use as indexes.
- :param indexes: a dict of name:index already instantiated
- :param mappings: the mappings to use for this wrapper
- """
-
- def __init__(self, default_index='simple', index_classes=_WRAPPER_INDEXES,
- indexes={}, mappings=_WRAPPER_MAPPINGS):
- self._projects = {}
- self._mappings = mappings
- self._indexes = indexes
- self._default_index = default_index
-
- # instantiate the classes and set their _project attribute to the one
- # of the wrapper.
- for name, cls in index_classes.items():
- obj = self._indexes.setdefault(name, cls())
- obj._projects = self._projects
- obj._index = self
-
- def __getattr__(self, method_name):
- """When asking for methods of the wrapper, return the implementation of
- the wrapped classes, depending the mapping.
-
- Decorate the methods to switch of implementation if an error occurs
- """
- real_method = None
- if method_name in _WRAPPER_MAPPINGS:
- obj = self._indexes[_WRAPPER_MAPPINGS[method_name]]
- real_method = getattr(obj, method_name)
- else:
- # the method is not defined in the mappings, so we try first to get
- # it via the default index, and rely on others if needed.
- try:
- real_method = getattr(self._indexes[self._default_index],
- method_name)
- except AttributeError:
- other_indexes = [i for i in self._indexes
- if i != self._default_index]
- for index in other_indexes:
- real_method = getattr(self._indexes[index], method_name, None)
- if real_method:
- break
- if real_method:
- return switch_index_if_fails(real_method, self)
- else:
- raise AttributeError("No index have attribute '%s'" % method_name)
-
diff --git a/src/distutils2/index/xmlrpc.py b/src/distutils2/index/xmlrpc.py
deleted file mode 100644
index b9d66e0..0000000
--- a/src/distutils2/index/xmlrpc.py
+++ /dev/null
@@ -1,179 +0,0 @@
-import logging
-import xmlrpclib
-
-from distutils2.errors import IrrationalVersionError
-from distutils2.index.base import BaseClient
-from distutils2.index.errors import (ProjectNotFound, InvalidSearchField,
- ReleaseNotFound)
-from distutils2.index.dist import ReleaseInfo
-from distutils2.version import get_version_predicate
-
-__all__ = ['Client', 'DEFAULT_XMLRPC_INDEX_URL']
-
-DEFAULT_XMLRPC_INDEX_URL = 'http://python.org/pypi'
-
-_SEARCH_FIELDS = ['name', 'version', 'author', 'author_email', 'maintainer',
- 'maintainer_email', 'home_page', 'license', 'summary',
- 'description', 'keywords', 'platform', 'download_url']
-
-
-class Client(BaseClient):
- """Client to query indexes using XML-RPC method calls.
-
- If no server_url is specified, use the default PyPI XML-RPC URL,
- defined in the DEFAULT_XMLRPC_INDEX_URL constant::
-
- >>> client = XMLRPCClient()
- >>> client.server_url == DEFAULT_XMLRPC_INDEX_URL
- True
-
- >>> client = XMLRPCClient("http://someurl/")
- >>> client.server_url
- 'http://someurl/'
- """
-
- def __init__(self, server_url=DEFAULT_XMLRPC_INDEX_URL, prefer_final=False,
- prefer_source=True):
- super(Client, self).__init__(prefer_final, prefer_source)
- self.server_url = server_url
- self._projects = {}
-
- def get_release(self, requirements, prefer_final=False):
- """Return a release with all complete metadata and distribution
- related informations.
- """
- prefer_final = self._get_prefer_final(prefer_final)
- predicate = get_version_predicate(requirements)
- releases = self.get_releases(predicate.name)
- release = releases.get_last(predicate, prefer_final)
- self.get_metadata(release.name, "%s" % release.version)
- self.get_distributions(release.name, "%s" % release.version)
- return release
-
- def get_releases(self, requirements, prefer_final=None, show_hidden=True,
- force_update=False):
- """Return the list of existing releases for a specific project.
-
- Cache the results from one call to another.
-
- If show_hidden is True, return the hidden releases too.
- If force_update is True, reprocess the index to update the
- informations (eg. make a new XML-RPC call).
- ::
-
- >>> client = XMLRPCClient()
- >>> client.get_releases('Foo')
- ['1.1', '1.2', '1.3']
-
- If no such project exists, raise a ProjectNotFound exception::
-
- >>> client.get_project_versions('UnexistingProject')
- ProjectNotFound: UnexistingProject
-
- """
- def get_versions(project_name, show_hidden):
- return self.proxy.package_releases(project_name, show_hidden)
-
- predicate = get_version_predicate(requirements)
- prefer_final = self._get_prefer_final(prefer_final)
- project_name = predicate.name
- if not force_update and (project_name.lower() in self._projects):
- project = self._projects[project_name.lower()]
- if not project.contains_hidden and show_hidden:
- # if hidden releases are requested, and have an existing
- # list of releases that does not contains hidden ones
- all_versions = get_versions(project_name, show_hidden)
- existing_versions = project.get_versions()
- hidden_versions = list(set(all_versions) -
- set(existing_versions))
- for version in hidden_versions:
- project.add_release(release=ReleaseInfo(project_name,
- version, index=self._index))
- else:
- versions = get_versions(project_name, show_hidden)
- if not versions:
- raise ProjectNotFound(project_name)
- project = self._get_project(project_name)
- project.add_releases([ReleaseInfo(project_name, version,
- index=self._index)
- for version in versions])
- project = project.filter(predicate)
- if len(project) == 0:
- raise ReleaseNotFound("%s" % predicate)
- project.sort_releases(prefer_final)
- return project
-
-
- def get_distributions(self, project_name, version):
- """Grab informations about distributions from XML-RPC.
-
- Return a ReleaseInfo object, with distribution-related informations
- filled in.
- """
- url_infos = self.proxy.release_urls(project_name, version)
- project = self._get_project(project_name)
- if version not in project.get_versions():
- project.add_release(release=ReleaseInfo(project_name, version,
- index=self._index))
- release = project.get_release(version)
- for info in url_infos:
- packagetype = info['packagetype']
- dist_infos = {'url': info['url'],
- 'hashval': info['md5_digest'],
- 'hashname': 'md5',
- 'is_external': False,
- 'python_version': info['python_version']}
- release.add_distribution(packagetype, **dist_infos)
- return release
-
- def get_metadata(self, project_name, version):
- """Retreive project metadatas.
-
- Return a ReleaseInfo object, with metadata informations filled in.
- """
- metadata = self.proxy.release_data(project_name, version)
- project = self._get_project(project_name)
- if version not in project.get_versions():
- project.add_release(release=ReleaseInfo(project_name, version,
- index=self._index))
- release = project.get_release(version)
- release.set_metadata(metadata)
- return release
-
- def search_projects(self, name=None, operator="or", **kwargs):
- """Find using the keys provided in kwargs.
-
- You can set operator to "and" or "or".
- """
- for key in kwargs:
- if key not in _SEARCH_FIELDS:
- raise InvalidSearchField(key)
- if name:
- kwargs["name"] = name
- projects = self.proxy.search(kwargs, operator)
- for p in projects:
- project = self._get_project(p['name'])
- try:
- project.add_release(release=ReleaseInfo(p['name'],
- p['version'], metadata={'summary': p['summary']},
- index=self._index))
- except IrrationalVersionError, e:
- logging.warn("Irrational version error found: %s" % e)
-
- return [self._projects[p['name'].lower()] for p in projects]
-
- @property
- def proxy(self):
- """Property used to return the XMLRPC server proxy.
-
- If no server proxy is defined yet, creates a new one::
-
- >>> client = XmlRpcClient()
- >>> client.proxy()
- <ServerProxy for python.org/pypi>
-
- """
- if not hasattr(self, '_server_proxy'):
- self._server_proxy = xmlrpclib.ServerProxy(self.server_url)
-
- return self._server_proxy
diff --git a/src/distutils2/install_tools.py b/src/distutils2/install_tools.py
deleted file mode 100644
index 1efeb64..0000000
--- a/src/distutils2/install_tools.py
+++ /dev/null
@@ -1,95 +0,0 @@
-import logging
-from distutils2.index import wrapper
-from distutils2.index.errors import ProjectNotFound, ReleaseNotFound
-from distutils2.depgraph import generate_graph
-from distutils2._backport.pkgutil import get_distributions
-
-
-"""Provides installations scripts.
-
-The goal of this script is to install a release from the indexes (eg.
-PyPI), including the dependencies of the releases if needed.
-
-It uses the work made in pkgutil and by the index crawlers to browse the
-installed distributions, and rely on the instalation commands to install.
-"""
-
-
-class InstallationException(Exception):
- pass
-
-
-def _update_infos(infos, new_infos):
- """extends the lists contained in the `info` dict with those contained
- in the `new_info` one
- """
- for key, value in infos.items():
- if key in new_infos:
- infos[key].extend(new_infos[key])
-
-
-def get_infos(requirements, index=None, installed=None,
- prefer_final=True):
- """Return the informations on what's going to be installed and upgraded.
-
- :param requirements: is a *string* containing the requirements for this
- project (for instance "FooBar 1.1" or "BarBaz (<1.2)")
- :param index: If an index is specified, use this one, otherwise, use
- :class index.ClientWrapper: to get project metadatas.
- :param installed: a list of already installed distributions.
- :param prefer_final: when picking up the releases, prefer a "final" one
- over a beta/alpha/etc one.
-
- The results are returned in a dict, containing all the operations
- needed to install the given requirements::
-
- >>> get_install_info("FooBar (<=1.2)")
- {'install': [<FooBar 1.1>], 'remove': [], 'conflict': []}
-
- Conflict contains all the conflicting distributions, if there is a
- conflict.
- """
-
- if not index:
- index = wrapper.ClientWrapper()
-
- if not installed:
- installed = get_distributions()
-
- # Get all the releases that match the requirements
- try:
- releases = index.get_releases(requirements)
- except (ReleaseNotFound, ProjectNotFound), e:
- raise InstallationException('Release not found: "%s"' % requirements)
-
- # Pick up a release, and try to get the dependency tree
- release = releases.get_last(requirements, prefer_final=prefer_final)
-
- # Iter since we found something without conflicts
- metadata = release.fetch_metadata()
-
- # Get the distributions already_installed on the system
- # and add the one we want to install
-
- distributions = installed + [release]
- depgraph = generate_graph(distributions)
-
- # Store all the already_installed packages in a list, in case of rollback.
- infos = {'install': [], 'remove': [], 'conflict': []}
-
- # Get what the missing deps are
- for dists in depgraph.missing.values():
- if dists:
- logging.info("missing dependencies found, installing them")
- # we have missing deps
- for dist in dists:
- _update_infos(infos,
- get_infos(dist, index, installed))
-
- # Fill in the infos
- existing = [d for d in installed if d.name == release.name]
- if existing:
- infos['remove'].append(existing[0])
- infos['conflict'].extend(depgraph.reverse_list[existing[0]])
- infos['install'].append(release)
- return infos
diff --git a/src/distutils2/log.py b/src/distutils2/log.py
deleted file mode 100644
index 1293bf4..0000000
--- a/src/distutils2/log.py
+++ /dev/null
@@ -1,71 +0,0 @@
-"""A simple log mechanism styled after PEP 282."""
-
-# The class here is styled after PEP 282 so that it could later be
-# replaced with a standard Python logging implementation.
-
-DEBUG = 1
-INFO = 2
-WARN = 3
-ERROR = 4
-FATAL = 5
-
-import sys
-
-class Log(object):
-
- def __init__(self, threshold=WARN):
- self.threshold = threshold
-
- def _log(self, level, msg, args):
- if level not in (DEBUG, INFO, WARN, ERROR, FATAL):
- raise ValueError('%s wrong log level' % level)
-
- if level >= self.threshold:
- if args:
- msg = msg % args
- if level in (WARN, ERROR, FATAL):
- stream = sys.stderr
- else:
- stream = sys.stdout
- stream.write('%s\n' % msg)
- stream.flush()
-
- def log(self, level, msg, *args):
- self._log(level, msg, args)
-
- def debug(self, msg, *args):
- self._log(DEBUG, msg, args)
-
- def info(self, msg, *args):
- self._log(INFO, msg, args)
-
- def warn(self, msg, *args):
- self._log(WARN, msg, args)
-
- def error(self, msg, *args):
- self._log(ERROR, msg, args)
-
- def fatal(self, msg, *args):
- self._log(FATAL, msg, args)
-
-_global_log = Log()
-log = _global_log.log
-debug = _global_log.debug
-info = _global_log.info
-warn = _global_log.warn
-error = _global_log.error
-fatal = _global_log.fatal
-
-def set_threshold(level):
- # return the old threshold for use from tests
- old = _global_log.threshold
- _global_log.threshold = level
- return old
-
-def set_verbosity(v):
- if v <= 0:
- set_threshold(WARN)
- elif v == 1:
- set_threshold(INFO)
- elif v >= 2:
- set_threshold(DEBUG)
diff --git a/src/distutils2/manifest.py b/src/distutils2/manifest.py
deleted file mode 100644
index 27b3dce..0000000
--- a/src/distutils2/manifest.py
+++ /dev/null
@@ -1,376 +0,0 @@
-"""distutils2.manifest
-
-Provides a Manifest class that can be used to:
-
- - read or write a MANIFEST file
- - read a template file and find out the file list
-
-Basically, Manifest *is* the file list.
-
-XXX todo: document + add tests
-"""
-import re
-import os
-import fnmatch
-import logging
-
-from distutils2.util import write_file, convert_path
-from distutils2.errors import (DistutilsTemplateError,
- DistutilsInternalError)
-
-__all__ = ['Manifest']
-
-# a \ followed by some spaces + EOL
-_COLLAPSE_PATTERN = re.compile('\\\w*\n', re.M)
-_COMMENTED_LINE = re.compile('#.*?(?=\n)|^\w*\n|\n(?=$)', re.M | re.S)
-
-class Manifest(object):
- """A list of files built by on exploring the filesystem and filtered by
- applying various patterns to what we find there.
- """
-
- def __init__(self):
- self.allfiles = None
- self.files = []
-
- #
- # Public API
- #
-
- def findall(self, dir=os.curdir):
- self.allfiles = _findall(dir)
-
- def append(self, item):
- self.files.append(item)
-
- def extend(self, items):
- self.files.extend(items)
-
- def sort(self):
- # Not a strict lexical sort!
- sortable_files = map(os.path.split, self.files)
- sortable_files.sort()
- self.files = []
- for sort_tuple in sortable_files:
- self.files.append(os.path.join(*sort_tuple))
-
- def clear(self):
- """Clear all collected files."""
- self.files = []
- if self.allfiles is not None:
- self.allfiles = []
-
- def remove_duplicates(self):
- # Assumes list has been sorted!
- for i in range(len(self.files) - 1, 0, -1):
- if self.files[i] == self.files[i - 1]:
- del self.files[i]
-
- def read_template(self, path):
- """Read and parse a manifest template file.
-
- Updates the list accordingly.
- """
- f = open(path)
- try:
- content = f.read()
- # first, let's unwrap collapsed lines
- content = _COLLAPSE_PATTERN.sub('', content)
-
- # next, let's remove commented lines and empty lines
- content = _COMMENTED_LINE.sub('', content)
-
- # now we have our cleaned up lines
- lines = [line.strip() for line in content.split('\n')]
- finally:
- f.close()
-
- for line in lines:
- try:
- self._process_template_line(line)
- except DistutilsTemplateError, msg:
- logging.warning("%s, %s" % (path, msg))
-
- def write(self, path):
- """Write the file list in 'self.filelist' (presumably as filled in
- by 'add_defaults()' and 'read_template()') to the manifest file
- named by 'self.manifest'.
- """
- if os.path.isfile(path):
- fp = open(path)
- try:
- first_line = fp.readline()
- finally:
- fp.close()
-
- if first_line != '# file GENERATED by distutils, do NOT edit\n':
- logging.info("not writing to manually maintained "
- "manifest file '%s'", path)
- return
-
- self.sort()
- self.remove_duplicates()
- content = self.files[:]
- content.insert(0, '# file GENERATED by distutils, do NOT edit')
- logging.info("writing manifest file '%s'", path)
- write_file(path, content)
-
- def read(self, path):
- """Read the manifest file (named by 'self.manifest') and use it to
- fill in 'self.filelist', the list of files to include in the source
- distribution.
- """
- logging.info("reading manifest file '%s'" % path)
- manifest = open(path)
- try:
- for line in manifest.readlines():
- self.append(line)
- finally:
- manifest.close()
-
- def exclude_pattern(self, pattern, anchor=1, prefix=None, is_regex=0):
- """Remove strings (presumably filenames) from 'files' that match
- 'pattern'.
-
- Other parameters are the same as for 'include_pattern()', above.
- The list 'self.files' is modified in place. Return 1 if files are
- found.
- """
- files_found = 0
- pattern_re = _translate_pattern(pattern, anchor, prefix, is_regex)
- for i in range(len(self.files)-1, -1, -1):
- if pattern_re.search(self.files[i]):
- del self.files[i]
- files_found = 1
-
- return files_found
-
- #
- # Private API
- #
-
- def _parse_template_line(self, line):
- words = line.split()
- action = words[0]
-
- patterns = dir = dir_pattern = None
-
- if action in ('include', 'exclude',
- 'global-include', 'global-exclude'):
- if len(words) < 2:
- raise DistutilsTemplateError(
- "'%s' expects <pattern1> <pattern2> ..." % action)
-
- patterns = map(convert_path, words[1:])
-
- elif action in ('recursive-include', 'recursive-exclude'):
- if len(words) < 3:
- raise DistutilsTemplateError(
- "'%s' expects <dir> <pattern1> <pattern2> ..." % action)
-
- dir = convert_path(words[1])
- patterns = map(convert_path, words[2:])
-
- elif action in ('graft', 'prune'):
- if len(words) != 2:
- raise DistutilsTemplateError(
- "'%s' expects a single <dir_pattern>" % action)
-
- dir_pattern = convert_path(words[1])
-
- else:
- raise DistutilsTemplateError("unknown action '%s'" % action)
-
- return action, patterns, dir, dir_pattern
-
- def _process_template_line(self, line):
- # Parse the line: split it up, make sure the right number of words
- # is there, and return the relevant words. 'action' is always
- # defined: it's the first word of the line. Which of the other
- # three are defined depends on the action; it'll be either
- # patterns, (dir and patterns), or (dir_pattern).
- action, patterns, dir, dir_pattern = self._parse_template_line(line)
-
- # OK, now we know that the action is valid and we have the
- # right number of words on the line for that action -- so we
- # can proceed with minimal error-checking.
- if action == 'include':
- for pattern in patterns:
- if not self._include_pattern(pattern, anchor=1):
- logging.warning("warning: no files found matching '%s'" %
- pattern)
-
- elif action == 'exclude':
- for pattern in patterns:
- if not self.exclude_pattern(pattern, anchor=1):
- logging.warning(("warning: no previously-included files "
- "found matching '%s'") % pattern)
-
- elif action == 'global-include':
- for pattern in patterns:
- if not self._include_pattern(pattern, anchor=0):
- logging.warning(("warning: no files found matching '%s' " +
- "anywhere in distribution") % pattern)
-
- elif action == 'global-exclude':
- for pattern in patterns:
- if not self.exclude_pattern(pattern, anchor=0):
- logging.warning(("warning: no previously-included files "
- "matching '%s' found anywhere in distribution") %
- pattern)
-
- elif action == 'recursive-include':
- for pattern in patterns:
- if not self._include_pattern(pattern, prefix=dir):
- logging.warning(("warning: no files found matching '%s' "
- "under directory '%s'" % (pattern, dir)))
-
- elif action == 'recursive-exclude':
- for pattern in patterns:
- if not self.exclude_pattern(pattern, prefix=dir):
- logging.warning(("warning: no previously-included files "
- "matching '%s' found under directory '%s'") %
- (pattern, dir))
-
- elif action == 'graft':
- if not self._include_pattern(None, prefix=dir_pattern):
- logging.warning("warning: no directories found matching '%s'" %
- dir_pattern)
-
- elif action == 'prune':
- if not self.exclude_pattern(None, prefix=dir_pattern):
- logging.warning(("no previously-included directories found " +
- "matching '%s'") % dir_pattern)
- else:
- raise DistutilsInternalError(
- "this cannot happen: invalid action '%s'" % action)
-
- def _include_pattern(self, pattern, anchor=1, prefix=None, is_regex=0):
- """Select strings (presumably filenames) from 'self.files' that
- match 'pattern', a Unix-style wildcard (glob) pattern.
-
- Patterns are not quite the same as implemented by the 'fnmatch'
- module: '*' and '?' match non-special characters, where "special"
- is platform-dependent: slash on Unix; colon, slash, and backslash on
- DOS/Windows; and colon on Mac OS.
-
- If 'anchor' is true (the default), then the pattern match is more
- stringent: "*.py" will match "foo.py" but not "foo/bar.py". If
- 'anchor' is false, both of these will match.
-
- If 'prefix' is supplied, then only filenames starting with 'prefix'
- (itself a pattern) and ending with 'pattern', with anything in between
- them, will match. 'anchor' is ignored in this case.
-
- If 'is_regex' is true, 'anchor' and 'prefix' are ignored, and
- 'pattern' is assumed to be either a string containing a regex or a
- regex object -- no translation is done, the regex is just compiled
- and used as-is.
-
- Selected strings will be added to self.files.
-
- Return 1 if files are found.
- """
- files_found = 0
- pattern_re = _translate_pattern(pattern, anchor, prefix, is_regex)
-
- # delayed loading of allfiles list
- if self.allfiles is None:
- self.findall()
-
- for name in self.allfiles:
- if pattern_re.search(name):
- self.files.append(name)
- files_found = 1
-
- return files_found
-
-
-
-#
-# Utility functions
-#
-
-def _findall(dir=os.curdir):
- """Find all files under 'dir' and return the list of full filenames
- (relative to 'dir').
- """
- from stat import ST_MODE, S_ISREG, S_ISDIR, S_ISLNK
-
- list = []
- stack = [dir]
- pop = stack.pop
- push = stack.append
-
- while stack:
- dir = pop()
- names = os.listdir(dir)
-
- for name in names:
- if dir != os.curdir: # avoid the dreaded "./" syndrome
- fullname = os.path.join(dir, name)
- else:
- fullname = name
-
- # Avoid excess stat calls -- just one will do, thank you!
- stat = os.stat(fullname)
- mode = stat[ST_MODE]
- if S_ISREG(mode):
- list.append(fullname)
- elif S_ISDIR(mode) and not S_ISLNK(mode):
- push(fullname)
-
- return list
-
-
-
-def _glob_to_re(pattern):
- """Translate a shell-like glob pattern to a regular expression.
-
- Return a string containing the regex. Differs from
- 'fnmatch.translate()' in that '*' does not match "special characters"
- (which are platform-specific).
- """
- pattern_re = fnmatch.translate(pattern)
-
- # '?' and '*' in the glob pattern become '.' and '.*' in the RE, which
- # IMHO is wrong -- '?' and '*' aren't supposed to match slash in Unix,
- # and by extension they shouldn't match such "special characters" under
- # any OS. So change all non-escaped dots in the RE to match any
- # character except the special characters.
- # XXX currently the "special characters" are just slash -- i.e. this is
- # Unix-only.
- pattern_re = re.sub(r'((?<!\\)(\\\\)*)\.', r'\1[^/]', pattern_re)
-
- return pattern_re
-
-
-def _translate_pattern(pattern, anchor=1, prefix=None, is_regex=0):
- """Translate a shell-like wildcard pattern to a compiled regular
- expression.
-
- Return the compiled regex. If 'is_regex' true,
- then 'pattern' is directly compiled to a regex (if it's a string)
- or just returned as-is (assumes it's a regex object).
- """
- if is_regex:
- if isinstance(pattern, str):
- return re.compile(pattern)
- else:
- return pattern
-
- if pattern:
- pattern_re = _glob_to_re(pattern)
- else:
- pattern_re = ''
-
- if prefix is not None:
- # ditch end of pattern character
- empty_pattern = _glob_to_re('')
- prefix_re = _glob_to_re(prefix)[:-len(empty_pattern)]
- pattern_re = "^" + os.path.join(prefix_re, ".*" + pattern_re)
- else: # no prefix -- respect anchor flag
- if anchor:
- pattern_re = "^" + pattern_re
-
- return re.compile(pattern_re)
diff --git a/src/distutils2/metadata.py b/src/distutils2/metadata.py
deleted file mode 100644
index 3743d0e..0000000
--- a/src/distutils2/metadata.py
+++ /dev/null
@@ -1,670 +0,0 @@
-"""Implementation of the Metadata for Python packages PEPs.
-
-Supports all metadata formats (1.0, 1.1, 1.2).
-"""
-
-import os
-import sys
-import platform
-import re
-from StringIO import StringIO
-from email import message_from_file
-from tokenize import tokenize, NAME, OP, STRING, ENDMARKER
-
-from distutils2.log import warn
-from distutils2.version import (is_valid_predicate, is_valid_version,
- is_valid_versions)
-from distutils2.errors import (MetadataConflictError,
- MetadataUnrecognizedVersionError)
-
-try:
- # docutils is installed
- from docutils.utils import Reporter
- from docutils.parsers.rst import Parser
- from docutils import frontend
- from docutils import nodes
-
- class SilentReporter(Reporter):
-
- def __init__(self, source, report_level, halt_level, stream=None,
- debug=0, encoding='ascii', error_handler='replace'):
- self.messages = []
- Reporter.__init__(self, source, report_level, halt_level, stream,
- debug, encoding, error_handler)
-
- def system_message(self, level, message, *children, **kwargs):
- self.messages.append((level, message, children, kwargs))
-
- _HAS_DOCUTILS = True
-except ImportError:
- # docutils is not installed
- _HAS_DOCUTILS = False
-
-# public API of this module
-__all__ = ('DistributionMetadata', 'PKG_INFO_ENCODING',
- 'PKG_INFO_PREFERRED_VERSION')
-
-# Encoding used for the PKG-INFO files
-PKG_INFO_ENCODING = 'utf-8'
-
-# preferred version. Hopefully will be changed
-# to 1.2 once PEP 345 is supported everywhere
-PKG_INFO_PREFERRED_VERSION = '1.0'
-
-_LINE_PREFIX = re.compile('\n \|')
-_241_FIELDS = ('Metadata-Version', 'Name', 'Version', 'Platform',
- 'Summary', 'Description',
- 'Keywords', 'Home-page', 'Author', 'Author-email',
- 'License')
-
-_314_FIELDS = ('Metadata-Version', 'Name', 'Version', 'Platform',
- 'Supported-Platform', 'Summary', 'Description',
- 'Keywords', 'Home-page', 'Author', 'Author-email',
- 'License', 'Classifier', 'Download-URL', 'Obsoletes',
- 'Provides', 'Requires')
-
-_314_MARKERS = ('Obsoletes', 'Provides', 'Requires')
-
-_345_FIELDS = ('Metadata-Version', 'Name', 'Version', 'Platform',
- 'Supported-Platform', 'Summary', 'Description',
- 'Keywords', 'Home-page', 'Author', 'Author-email',
- 'Maintainer', 'Maintainer-email', 'License',
- 'Classifier', 'Download-URL', 'Obsoletes-Dist',
- 'Project-URL', 'Provides-Dist', 'Requires-Dist',
- 'Requires-Python', 'Requires-External')
-
-_345_MARKERS = ('Provides-Dist', 'Requires-Dist', 'Requires-Python',
- 'Obsoletes-Dist', 'Requires-External', 'Maintainer',
- 'Maintainer-email', 'Project-URL')
-
-_ALL_FIELDS = set()
-_ALL_FIELDS.update(_241_FIELDS)
-_ALL_FIELDS.update(_314_FIELDS)
-_ALL_FIELDS.update(_345_FIELDS)
-
-
-def _version2fieldlist(version):
- if version == '1.0':
- return _241_FIELDS
- elif version == '1.1':
- return _314_FIELDS
- elif version == '1.2':
- return _345_FIELDS
- raise MetadataUnrecognizedVersionError(version)
-
-
-def _best_version(fields):
- """Detect the best version depending on the fields used."""
- def _has_marker(keys, markers):
- for marker in markers:
- if marker in keys:
- return True
- return False
-
- keys = fields.keys()
- possible_versions = ['1.0', '1.1', '1.2']
-
- # first let's try to see if a field is not part of one of the version
- for key in keys:
- if key not in _241_FIELDS and '1.0' in possible_versions:
- possible_versions.remove('1.0')
- if key not in _314_FIELDS and '1.1' in possible_versions:
- possible_versions.remove('1.1')
- if key not in _345_FIELDS and '1.2' in possible_versions:
- possible_versions.remove('1.2')
-
- # possible_version contains qualified versions
- if len(possible_versions) == 1:
- return possible_versions[0] # found !
- elif len(possible_versions) == 0:
- raise MetadataConflictError('Unknown metadata set')
-
- # let's see if one unique marker is found
- is_1_1 = '1.1' in possible_versions and _has_marker(keys, _314_MARKERS)
- is_1_2 = '1.2' in possible_versions and _has_marker(keys, _345_MARKERS)
- if is_1_1 and is_1_2:
- raise MetadataConflictError('You used incompatible 1.1 and 1.2 fields')
-
- # we have the choice, either 1.0, or 1.2
- # - 1.0 has a broken Summary field but works with all tools
- # - 1.1 is to avoid
- # - 1.2 fixes Summary but is not widespread yet
- if not is_1_1 and not is_1_2:
- # we couldn't find any specific marker
- if PKG_INFO_PREFERRED_VERSION in possible_versions:
- return PKG_INFO_PREFERRED_VERSION
- if is_1_1:
- return '1.1'
-
- # default marker when 1.0 is disqualified
- return '1.2'
-
-_ATTR2FIELD = {'metadata_version': 'Metadata-Version',
- 'name': 'Name',
- 'version': 'Version',
- 'platform': 'Platform',
- 'supported_platform': 'Supported-Platform',
- 'summary': 'Summary',
- 'description': 'Description',
- 'keywords': 'Keywords',
- 'home_page': 'Home-page',
- 'author': 'Author',
- 'author_email': 'Author-email',
- 'maintainer': 'Maintainer',
- 'maintainer_email': 'Maintainer-email',
- 'license': 'License',
- 'classifier': 'Classifier',
- 'download_url': 'Download-URL',
- 'obsoletes_dist': 'Obsoletes-Dist',
- 'provides_dist': 'Provides-Dist',
- 'requires_dist': 'Requires-Dist',
- 'requires_python': 'Requires-Python',
- 'requires_external': 'Requires-External',
- 'requires': 'Requires',
- 'provides': 'Provides',
- 'obsoletes': 'Obsoletes',
- 'project_url': 'Project-URL',
- }
-
-_PREDICATE_FIELDS = ('Requires-Dist', 'Obsoletes-Dist', 'Provides-Dist')
-_VERSIONS_FIELDS = ('Requires-Python',)
-_VERSION_FIELDS = ('Version',)
-_LISTFIELDS = ('Platform', 'Classifier', 'Obsoletes',
- 'Requires', 'Provides', 'Obsoletes-Dist',
- 'Provides-Dist', 'Requires-Dist', 'Requires-External',
- 'Project-URL')
-_LISTTUPLEFIELDS = ('Project-URL',)
-
-_ELEMENTSFIELD = ('Keywords',)
-
-_UNICODEFIELDS = ('Author', 'Maintainer', 'Summary', 'Description')
-
-
-class DistributionMetadata(object):
- """The metadata of a release.
-
- Supports versions 1.0, 1.1 and 1.2 (auto-detected). You can
- instantiate the class with one of these arguments (or none):
- - *path*, the path to a METADATA file
- - *fileobj* give a file-like object with METADATA as content
- - *mapping* is a dict-like object
- """
- # TODO document that execution_context and platform_dependent are used
- # to filter on query, not when setting a key
- # also document the mapping API and UNKNOWN default key
-
- def __init__(self, path=None, platform_dependent=False,
- execution_context=None, fileobj=None, mapping=None):
- self._fields = {}
- self.version = None
- self.docutils_support = _HAS_DOCUTILS
- self.platform_dependent = platform_dependent
- self.execution_context = execution_context
- if [path, fileobj, mapping].count(None) < 2:
- raise TypeError('path, fileobj and mapping are exclusive')
- if path is not None:
- self.read(path)
- elif fileobj is not None:
- self.read_file(fileobj)
- elif mapping is not None:
- self.update(mapping)
-
- def _set_best_version(self):
- self.version = _best_version(self._fields)
- self._fields['Metadata-Version'] = self.version
-
- def _write_field(self, file, name, value):
- file.write('%s: %s\n' % (name, value))
-
- def _encode_field(self, value):
- if isinstance(value, unicode):
- return value.encode(PKG_INFO_ENCODING)
- return str(value)
-
- def __getitem__(self, name):
- return self.get(name)
-
- def __setitem__(self, name, value):
- return self.set(name, value)
-
- def __delitem__(self, name):
- del self._fields[name]
- self._set_best_version()
-
- def _convert_name(self, name):
- if name in _ALL_FIELDS:
- return name
- name = name.replace('-', '_').lower()
- return _ATTR2FIELD.get(name, name)
-
- def _default_value(self, name):
- if name in _LISTFIELDS or name in _ELEMENTSFIELD:
- return []
- return 'UNKNOWN'
-
- def _check_rst_data(self, data):
- """Return warnings when the provided data has syntax errors."""
- source_path = StringIO()
- parser = Parser()
- settings = frontend.OptionParser().get_default_values()
- settings.tab_width = 4
- settings.pep_references = None
- settings.rfc_references = None
- reporter = SilentReporter(source_path,
- settings.report_level,
- settings.halt_level,
- stream=settings.warning_stream,
- debug=settings.debug,
- encoding=settings.error_encoding,
- error_handler=settings.error_encoding_error_handler)
-
- document = nodes.document(settings, reporter, source=source_path)
- document.note_source(source_path, -1)
- try:
- parser.parse(data, document)
- except AttributeError:
- reporter.messages.append((-1, 'Could not finish the parsing.',
- '', {}))
-
- return reporter.messages
-
- def _platform(self, value):
- if not self.platform_dependent or ';' not in value:
- return True, value
- value, marker = value.split(';')
- return _interpret(marker, self.execution_context), value
-
- def _remove_line_prefix(self, value):
- return _LINE_PREFIX.sub('\n', value)
-
- #
- # Public API
- #
- def get_fullname(self):
- return '%s-%s' % (self['Name'], self['Version'])
-
- def is_metadata_field(self, name):
- name = self._convert_name(name)
- return name in _ALL_FIELDS
-
- def read(self, filepath):
- self.read_file(open(filepath))
-
- def read_file(self, fileob):
- """Read the metadata values from a file object."""
- msg = message_from_file(fileob)
- self.version = msg['metadata-version']
-
- for field in _version2fieldlist(self.version):
- if field in _LISTFIELDS:
- # we can have multiple lines
- values = msg.get_all(field)
- if field in _LISTTUPLEFIELDS and values is not None:
- values = [tuple(value.split(',')) for value in values]
- self.set(field, values)
- else:
- # single line
- value = msg[field]
- if value is not None:
- self.set(field, value)
-
- def write(self, filepath):
- """Write the metadata fields to filepath."""
- pkg_info = open(filepath, 'w')
- try:
- self.write_file(pkg_info)
- finally:
- pkg_info.close()
-
- def write_file(self, fileobject):
- """Write the PKG-INFO format data to a file object."""
- self._set_best_version()
- for field in _version2fieldlist(self.version):
- values = self.get(field)
- if field in _ELEMENTSFIELD:
- self._write_field(fileobject, field, ','.join(values))
- continue
- if field not in _LISTFIELDS:
- if field == 'Description':
- values = values.replace('\n', '\n |')
- values = [values]
-
- if field in _LISTTUPLEFIELDS:
- values = [','.join(value) for value in values]
-
- for value in values:
- self._write_field(fileobject, field, value)
-
- def update(self, other=None, **kwargs):
- """Set metadata values from the given iterable `other` and kwargs.
-
- Behavior is like `dict.update`: If `other` has a ``keys`` method,
- they are looped over and ``self[key]`` is assigned ``other[key]``.
- Else, ``other`` is an iterable of ``(key, value)`` iterables.
-
- Keys that don't match a metadata field or that have an empty value are
- dropped.
- """
- def _set(key, value):
- if key in _ATTR2FIELD and value:
- self.set(self._convert_name(key), value)
-
- if other is None:
- pass
- elif hasattr(other, 'keys'):
- for k in other.keys():
- _set(k, other[k])
- else:
- for k, v in other:
- _set(k, v)
-
- if kwargs:
- self.update(kwargs)
-
- def set(self, name, value):
- """Control then set a metadata field."""
- name = self._convert_name(name)
-
- if ((name in _ELEMENTSFIELD or name == 'Platform') and
- not isinstance(value, (list, tuple))):
- if isinstance(value, str):
- value = value.split(',')
- else:
- value = []
- elif (name in _LISTFIELDS and
- not isinstance(value, (list, tuple))):
- if isinstance(value, str):
- value = [value]
- else:
- value = None
-
- if name in _PREDICATE_FIELDS and value is not None:
- for v in value:
- # check that the values are valid predicates
- if not is_valid_predicate(v.split(';')[0]):
- warn('"%s" is not a valid predicate (field "%s")' %
- (v, name))
- # FIXME this rejects UNKNOWN, is that right?
- elif name in _VERSIONS_FIELDS and value is not None:
- if not is_valid_versions(value):
- warn('"%s" is not a valid version (field "%s")' %
- (value, name))
- elif name in _VERSION_FIELDS and value is not None:
- if not is_valid_version(value):
- warn('"%s" is not a valid version (field "%s")' %
- (value, name))
-
- if name in _UNICODEFIELDS:
- value = self._encode_field(value)
- if name == 'Description':
- value = self._remove_line_prefix(value)
-
- self._fields[name] = value
- self._set_best_version()
-
- def get(self, name):
- """Get a metadata field."""
- name = self._convert_name(name)
- if name not in self._fields:
- return self._default_value(name)
- if name in _UNICODEFIELDS:
- value = self._fields[name]
- return self._encode_field(value)
- elif name in _LISTFIELDS:
- value = self._fields[name]
- if value is None:
- return []
- res = []
- for val in value:
- valid, val = self._platform(val)
- if not valid:
- continue
- if name not in _LISTTUPLEFIELDS:
- res.append(self._encode_field(val))
- else:
- # That's for Project-URL
- res.append((self._encode_field(val[0]), val[1]))
- return res
-
- elif name in _ELEMENTSFIELD:
- valid, value = self._platform(self._fields[name])
- if not valid:
- return []
- if isinstance(value, str):
- return value.split(',')
- valid, value = self._platform(self._fields[name])
- if not valid:
- return None
- return value
-
- def check(self):
- """Check if the metadata is compliant."""
- # XXX should check the versions (if the file was loaded)
- missing, warnings = [], []
- for attr in ('Name', 'Version', 'Home-page'):
- value = self[attr]
- if value == 'UNKNOWN':
- missing.append(attr)
-
- if _HAS_DOCUTILS:
- warnings.extend(self._check_rst_data(self['Description']))
-
- # checking metadata 1.2 (XXX needs to check 1.1, 1.0)
- if self['Metadata-Version'] != '1.2':
- return missing, warnings
-
- def is_valid_predicates(value):
- for v in value:
- if not is_valid_predicate(v.split(';')[0]):
- return False
- return True
-
- for fields, controller in ((_PREDICATE_FIELDS, is_valid_predicates),
- (_VERSIONS_FIELDS, is_valid_versions),
- (_VERSION_FIELDS, is_valid_version)):
- for field in fields:
- value = self[field]
- if value == 'UNKNOWN':
- continue
-
- if not controller(value):
- warnings.append('Wrong value for %r: %s' % (field, value))
-
- return missing, warnings
-
- def keys(self):
- return _version2fieldlist(self.version)
-
- def values(self):
- return [self[key] for key in self.keys()]
-
- def items(self):
- return [(key, self[key]) for key in self.keys()]
-
-
-#
-# micro-language for PEP 345 environment markers
-#
-
-# allowed operators
-_OPERATORS = {'==': lambda x, y: x == y,
- '!=': lambda x, y: x != y,
- '>': lambda x, y: x > y,
- '>=': lambda x, y: x >= y,
- '<': lambda x, y: x < y,
- '<=': lambda x, y: x <= y,
- 'in': lambda x, y: x in y,
- 'not in': lambda x, y: x not in y}
-
-
-def _operate(operation, x, y):
- return _OPERATORS[operation](x, y)
-
-# restricted set of variables
-_VARS = {'sys.platform': sys.platform,
- 'python_version': sys.version[:3],
- 'python_full_version': sys.version.split(' ', 1)[0],
- 'os.name': os.name,
- 'platform.version': platform.version(),
- 'platform.machine': platform.machine()}
-
-
-class _Operation(object):
-
- def __init__(self, execution_context=None):
- self.left = None
- self.op = None
- self.right = None
- if execution_context is None:
- execution_context = {}
- self.execution_context = execution_context
-
- def _get_var(self, name):
- if name in self.execution_context:
- return self.execution_context[name]
- return _VARS[name]
-
- def __repr__(self):
- return '%s %s %s' % (self.left, self.op, self.right)
-
- def _is_string(self, value):
- if value is None or len(value) < 2:
- return False
- for delimiter in '"\'':
- if value[0] == value[-1] == delimiter:
- return True
- return False
-
- def _is_name(self, value):
- return value in _VARS
-
- def _convert(self, value):
- if value in _VARS:
- return self._get_var(value)
- return value.strip('"\'')
-
- def _check_name(self, value):
- if value not in _VARS:
- raise NameError(value)
-
- def _nonsense_op(self):
- msg = 'This operation is not supported : "%s"' % self
- raise SyntaxError(msg)
-
- def __call__(self):
- # make sure we do something useful
- if self._is_string(self.left):
- if self._is_string(self.right):
- self._nonsense_op()
- self._check_name(self.right)
- else:
- if not self._is_string(self.right):
- self._nonsense_op()
- self._check_name(self.left)
-
- if self.op not in _OPERATORS:
- raise TypeError('Operator not supported "%s"' % self.op)
-
- left = self._convert(self.left)
- right = self._convert(self.right)
- return _operate(self.op, left, right)
-
-
-class _OR(object):
- def __init__(self, left, right=None):
- self.left = left
- self.right = right
-
- def filled(self):
- return self.right is not None
-
- def __repr__(self):
- return 'OR(%r, %r)' % (self.left, self.right)
-
- def __call__(self):
- return self.left() or self.right()
-
-
-class _AND(object):
- def __init__(self, left, right=None):
- self.left = left
- self.right = right
-
- def filled(self):
- return self.right is not None
-
- def __repr__(self):
- return 'AND(%r, %r)' % (self.left, self.right)
-
- def __call__(self):
- return self.left() and self.right()
-
-
-class _CHAIN(object):
-
- def __init__(self, execution_context=None):
- self.ops = []
- self.op_starting = True
- self.execution_context = execution_context
-
- def eat(self, toktype, tokval, rowcol, line, logical_line):
- if toktype not in (NAME, OP, STRING, ENDMARKER):
- raise SyntaxError('Type not supported "%s"' % tokval)
-
- if self.op_starting:
- op = _Operation(self.execution_context)
- if len(self.ops) > 0:
- last = self.ops[-1]
- if isinstance(last, (_OR, _AND)) and not last.filled():
- last.right = op
- else:
- self.ops.append(op)
- else:
- self.ops.append(op)
- self.op_starting = False
- else:
- op = self.ops[-1]
-
- if (toktype == ENDMARKER or
- (toktype == NAME and tokval in ('and', 'or'))):
- if toktype == NAME and tokval == 'and':
- self.ops.append(_AND(self.ops.pop()))
- elif toktype == NAME and tokval == 'or':
- self.ops.append(_OR(self.ops.pop()))
- self.op_starting = True
- return
-
- if isinstance(op, (_OR, _AND)) and op.right is not None:
- op = op.right
-
- if ((toktype in (NAME, STRING) and tokval not in ('in', 'not'))
- or (toktype == OP and tokval == '.')):
- if op.op is None:
- if op.left is None:
- op.left = tokval
- else:
- op.left += tokval
- else:
- if op.right is None:
- op.right = tokval
- else:
- op.right += tokval
- elif toktype == OP or tokval in ('in', 'not'):
- if tokval == 'in' and op.op == 'not':
- op.op = 'not in'
- else:
- op.op = tokval
-
- def result(self):
- for op in self.ops:
- if not op():
- return False
- return True
-
-
-def _interpret(marker, execution_context=None):
- """Interpret a marker and return a result depending on environment."""
- marker = marker.strip()
- operations = _CHAIN(execution_context)
- tokenize(StringIO(marker).readline, operations.eat)
- return operations.result()
diff --git a/src/distutils2/mkpkg.py b/src/distutils2/mkpkg.py
deleted file mode 100644
index 438fb87..0000000
--- a/src/distutils2/mkpkg.py
+++ /dev/null
@@ -1,417 +0,0 @@
-#!/usr/bin/env python
-#
-# Helper for automating the creation of a package by looking at you
-# current directory and asking the user questions.
-#
-# Available as either a stand-alone file or callable from the distutils2
-# package:
-#
-# python -m distutils2.mkpkg
-# or:
-# python mkpkg.py
-#
-# Written by Sean Reifschneider <jafo@tummy.com>
-#
-# Original TODO list:
-# Look for a license file and automatically add the category.
-# When a .c file is found during the walk, can we add it as an extension?
-# Ask if there is a maintainer different that the author
-# Ask for the platform (can we detect this via "import win32" or something?)
-# Ask for the dependencies.
-# Ask for the Requires-Dist
-# Ask for the Provides-Dist
-# Detect scripts (not sure how. #! outside of package?)
-
-import os
-import sys
-import re
-import shutil
-from ConfigParser import RawConfigParser
-from textwrap import dedent
-# importing this with an underscore as it should be replaced by the
-# dict form or another structures for all purposes
-from distutils2._trove import all_classifiers as _CLASSIFIERS_LIST
-
-
-_helptext = {
- 'name': '''
-The name of the program to be packaged, usually a single word composed
-of lower-case characters such as "python", "sqlalchemy", or "CherryPy".
-''',
- 'version': '''
-Version number of the software, typically 2 or 3 numbers separated by dots
-such as "1.00", "0.6", or "3.02.01". "0.1.0" is recommended for initial
-development.
-''',
- 'description': '''
-A short summary of what this package is or does, typically a sentence 80
-characters or less in length.
-''',
- 'author': '''
-The full name of the author (typically you).
-''',
- 'author_email': '''
-E-mail address of the package author (typically you).
-''',
- 'do_classifier': '''
-Trove classifiers are optional identifiers that allow you to specify the
-intended audience by saying things like "Beta software with a text UI
-for Linux under the PSF license. However, this can be a somewhat involved
-process.
-''',
- 'url': '''
-The home page for the package, typically starting with "http://".
-''',
- 'trove_license': '''
-Optionally you can specify a license. Type a string that identifies a common
-license, and then you can select a list of license specifiers.
-''',
- 'trove_generic': '''
-Optionally, you can set other trove identifiers for things such as the
-human language, programming language, user interface, etc...
-''',
-}
-
-# XXX everything needs docstrings and tests (both low-level tests of various
-# methods and functional tests of running the script)
-
-
-def ask_yn(question, default=None, helptext=None):
- while True:
- answer = ask(question, default, helptext, required=True)
- if answer and answer[0].lower() in 'yn':
- return answer[0].lower()
-
- print '\nERROR: You must select "Y" or "N".\n'
-
-
-def ask(question, default=None, helptext=None, required=True,
- lengthy=False, multiline=False):
- prompt = '%s: ' % (question,)
- if default:
- prompt = '%s [%s]: ' % (question, default)
- if default and len(question) + len(default) > 70:
- prompt = '%s\n [%s]: ' % (question, default)
- if lengthy or multiline:
- prompt += '\n >'
-
- if not helptext:
- helptext = 'No additional help available.'
-
- helptext = helptext.strip("\n")
-
- while True:
- sys.stdout.write(prompt)
- sys.stdout.flush()
-
- line = sys.stdin.readline().strip()
- if line == '?':
- print '=' * 70
- print helptext
- print '=' * 70
- continue
- if default and not line:
- return default
- if not line and required:
- print '*' * 70
- print 'This value cannot be empty.'
- print '==========================='
- if helptext:
- print helptext
- print '*' * 70
- continue
- return line
-
-
-def _build_classifiers_dict(classifiers):
- d = {}
- for key in classifiers:
- subDict = d
- for subkey in key.split(' :: '):
- if not subkey in subDict:
- subDict[subkey] = {}
- subDict = subDict[subkey]
- return d
-
-CLASSIFIERS = _build_classifiers_dict(_CLASSIFIERS_LIST)
-
-
-class MainProgram(object):
- def __init__(self):
- self.configparser = None
- self.classifiers = {}
- self.data = {}
- self.data['classifier'] = self.classifiers
- self.data['packages'] = {}
- self.load_config_file()
-
- def lookup_option(self, key):
- if not self.configparser.has_option('DEFAULT', key):
- return None
- return self.configparser.get('DEFAULT', key)
-
- def load_config_file(self):
- self.configparser = RawConfigParser()
- # TODO replace with section in distutils config file
- self.configparser.read(os.path.expanduser('~/.mkpkgpy'))
- self.data['author'] = self.lookup_option('author')
- self.data['author_email'] = self.lookup_option('author_email')
-
- def update_config_file(self):
- valuesDifferent = False
- # FIXME looking only for those two fields seems wrong
- for compareKey in ('author', 'author_email'):
- if self.lookup_option(compareKey) != self.data[compareKey]:
- valuesDifferent = True
- self.configparser.set('DEFAULT', compareKey,
- self.data[compareKey])
-
- if not valuesDifferent:
- return
-
- fp = open(os.path.expanduser('~/.mkpkgpy'), 'w')
- try:
- self.configparser.write(fp)
- finally:
- fp.close()
-
- def load_existing_setup_script(self):
- raise NotImplementedError
- # Ideas:
- # - define a mock module to assign to sys.modules['distutils'] before
- # importing the setup script as a module (or executing it); it would
- # provide setup (a function that just returns its args as a dict),
- # Extension (ditto), find_packages (the real function)
- # - we could even mock Distribution and commands to handle more setup
- # scripts
- # - we could use a sandbox (http://bugs.python.org/issue8680)
- # - the cleanest way is to parse the file, not import it, but there is
- # no way to do that across versions (the compiler package is
- # deprecated or removed in recent Pythons, the ast module is not
- # present before 2.6)
-
- def inspect_file(self, path):
- fp = open(path, 'r')
- try:
- for line in [fp.readline() for _ in range(10)]:
- m = re.match(r'^#!.*python((?P<major>\d)(\.\d+)?)?$', line)
- if m:
- if m.group('major') == '3':
- self.classifiers['Programming Language :: Python :: 3'] = 1
- else:
- self.classifiers['Programming Language :: Python :: 2'] = 1
- finally:
- fp.close()
-
- def inspect_directory(self):
- dirName = os.path.basename(os.getcwd())
- self.data['name'] = dirName
- m = re.match(r'(.*)-(\d.+)', dirName)
- if m:
- self.data['name'] = m.group(1)
- self.data['version'] = m.group(2)
-
- for root, dirs, files in os.walk(os.curdir):
- for filename in files:
- if root == os.curdir and filename == 'setup.py':
- continue
- self.inspect_file(os.path.join(root, filename))
-
- if filename == '__init__.py':
- trySrc = os.path.join(os.curdir, 'src')
- tmpRoot = root
- if tmpRoot.startswith(trySrc):
- tmpRoot = tmpRoot[len(trySrc):]
- if tmpRoot.startswith(os.path.sep):
- tmpRoot = tmpRoot[len(os.path.sep):]
-
- self.data['packages'][tmpRoot] = root[1 + len(os.path.sep):]
-
- def query_user(self):
- self.data['name'] = ask('Package name', self.data['name'],
- _helptext['name'])
- self.data['version'] = ask('Current version number',
- self.data.get('version'), _helptext['version'])
- self.data['description'] = ask('Package description',
- self.data.get('description'), _helptext['description'],
- lengthy=True)
- self.data['author'] = ask('Author name',
- self.data.get('author'), _helptext['author'])
- self.data['author_email'] = ask('Author e-mail address',
- self.data.get('author_email'), _helptext['author_email'])
- self.data['url'] = ask('Project URL',
- self.data.get('url'), _helptext['url'], required=False)
-
- if ask_yn('Do you want to set Trove classifiers?',
- helptext=_helptext['do_classifier']) == 'y':
- self.set_classifier()
-
- def set_classifier(self):
- self.set_devel_status(self.classifiers)
- self.set_license(self.classifiers)
- self.set_other_classifier(self.classifiers)
-
- def set_other_classifier(self, classifiers):
- if ask_yn('Do you want to set other trove identifiers', 'n',
- _helptext['trove_generic']) != 'y':
- return
- self.walk_classifiers(classifiers, [CLASSIFIERS], '')
-
- def walk_classifiers(self, classifiers, trovepath, desc):
- trove = trovepath[-1]
-
- if not trove:
- return
-
- for key in sorted(trove.keys()):
- if len(trove[key]) == 0:
- if ask_yn('Add "%s"' % desc[4:] + ' :: ' + key, 'n') == 'y':
- classifiers[desc[4:] + ' :: ' + key] = 1
- continue
-
- if ask_yn('Do you want to set items under\n "%s" (%d sub-items)'
- % (key, len(trove[key])), 'n',
- _helptext['trove_generic']) == 'y':
- self.walk_classifiers(classifiers, trovepath + [trove[key]],
- desc + ' :: ' + key)
-
- def set_license(self, classifiers):
- while True:
- license = ask('What license do you use',
- helptext=_helptext['trove_license'], required=False)
- if not license:
- return
-
- licenseWords = license.lower().split(' ')
-
- foundList = []
- # TODO use enumerate
- for index in range(len(_CLASSIFIERS_LIST)):
- troveItem = _CLASSIFIERS_LIST[index]
- if not troveItem.startswith('License :: '):
- continue
- troveItem = troveItem[11:].lower()
-
- allMatch = True
- for word in licenseWords:
- if not word in troveItem:
- allMatch = False
- break
- if allMatch:
- foundList.append(index)
-
- question = 'Matching licenses:\n\n'
- # TODO use enumerate?
- for i in xrange(1, len(foundList) + 1):
- question += ' %s) %s\n' % (i, _CLASSIFIERS_LIST[foundList[i - 1]])
- question += ('\nType the number of the license you wish to use or '
- '? to try again:')
- troveLicense = ask(question, required=False)
-
- if troveLicense == '?':
- continue
- if troveLicense == '':
- return
- # FIXME the int conversion can fail
- foundIndex = foundList[int(troveLicense) - 1]
- classifiers[_CLASSIFIERS_LIST[foundIndex]] = 1
- try:
- return
- except IndexError:
- print ("ERROR: Invalid selection, type a number from the list "
- "above.")
-
- def set_devel_status(self, classifiers):
- while True:
- choice = ask(dedent('''\
- Please select the project status:
-
- 1 - Planning
- 2 - Pre-Alpha
- 3 - Alpha
- 4 - Beta
- 5 - Production/Stable
- 6 - Mature
- 7 - Inactive
-
- Status'''), required=False)
- if choice:
- try:
- choice = int(choice) - 1
- key = ['Development Status :: 1 - Planning',
- 'Development Status :: 2 - Pre-Alpha',
- 'Development Status :: 3 - Alpha',
- 'Development Status :: 4 - Beta',
- 'Development Status :: 5 - Production/Stable',
- 'Development Status :: 6 - Mature',
- 'Development Status :: 7 - Inactive'][choice]
- classifiers[key] = 1
- return
- except (IndexError, ValueError):
- print ("ERROR: Invalid selection, type a single digit "
- "number.")
-
- def _dotted_packages(self, data):
- packages = sorted(data.keys())
- modified_pkgs = []
- for pkg in packages:
- pkg = pkg.lstrip('./')
- pkg = pkg.replace('/', '.')
- modified_pkgs.append(pkg)
- return modified_pkgs
-
- def write_setup_script(self):
- if os.path.exists('setup.py'):
- if os.path.exists('setup.py.old'):
- print ("ERROR: setup.py.old backup exists, please check that "
- "current setup.py is correct and remove setup.py.old")
- return
- shutil.move('setup.py', 'setup.py.old')
-
- fp = open('setup.py', 'w')
- try:
- # XXX do LFs work on all platforms?
- fp.write('#!/usr/bin/env python\n\n')
- fp.write('from distutils2.core import setup\n\n')
- fp.write('setup(name=%s,\n' % repr(self.data['name']))
- fp.write(' version=%s,\n' % repr(self.data['version']))
- fp.write(' description=%s,\n'
- % repr(self.data['description']))
- fp.write(' author=%s,\n' % repr(self.data['author']))
- fp.write(' author_email=%s,\n'
- % repr(self.data['author_email']))
- if self.data['url']:
- fp.write(' url=%s,\n' % repr(self.data['url']))
- if self.data['classifier']:
- fp.write(' classifier=[\n')
- for classifier in sorted(self.data['classifier'].keys()):
- fp.write(' %s,\n' % repr(classifier))
- fp.write(' ],\n')
- if self.data['packages']:
- fp.write(' packages=%s,\n'
- % repr(self._dotted_packages(self.data['packages'])))
- fp.write(' package_dir=%s,\n'
- % repr(self.data['packages']))
- fp.write(' #scripts=[\'path/to/script\']\n')
-
- fp.write(' )\n')
- finally:
- fp.close()
- os.chmod('setup.py', 0755)
-
- print 'Wrote "setup.py".'
-
-
-def main():
- """Main entry point."""
- program = MainProgram()
- # uncomment when implemented
- #program.load_existing_setup_script()
- program.inspect_directory()
- program.query_user()
- program.update_config_file()
- program.write_setup()
-
-
-if __name__ == '__main__':
- main()
diff --git a/src/distutils2/tests/LONG_DESC.txt b/src/distutils2/tests/LONG_DESC.txt
deleted file mode 100644
index 2b4358a..0000000
--- a/src/distutils2/tests/LONG_DESC.txt
+++ /dev/null
@@ -1,44 +0,0 @@
-CLVault
-=======
-
-CLVault uses Keyring to provide a command-line utility to safely store
-and retrieve passwords.
-
-Install it using pip or the setup.py script::
-
- $ python setup.py install
-
- $ pip install clvault
-
-Once it's installed, you will have three scripts installed in your
-Python scripts folder, you can use to list, store and retrieve passwords::
-
- $ clvault-set blog
- Set your password:
- Set the associated username (can be blank): tarek
- Set a description (can be blank): My blog password
- Password set.
-
- $ clvault-get blog
- The username is "tarek"
- The password has been copied in your clipboard
-
- $ clvault-list
- Registered services:
- blog My blog password
-
-
-*clvault-set* takes a service name then prompt you for a password, and some
-optional information about your service. The password is safely stored in
-a keyring while the description is saved in a ``.clvault`` file in your
-home directory. This file is created automatically the first time the command
-is used.
-
-*clvault-get* copies the password for a given service in your clipboard, and
-displays the associated user if any.
-
-*clvault-list* lists all registered services, with their description when
-given.
-
-
-Project page: http://bitbucket.org/tarek/clvault
diff --git a/src/distutils2/tests/PKG-INFO b/src/distutils2/tests/PKG-INFO
deleted file mode 100644
index f48546e..0000000
--- a/src/distutils2/tests/PKG-INFO
+++ /dev/null
@@ -1,57 +0,0 @@
-Metadata-Version: 1.2
-Name: CLVault
-Version: 0.5
-Summary: Command-Line utility to store and retrieve passwords
-Home-page: http://bitbucket.org/tarek/clvault
-Author: Tarek Ziade
-Author-email: tarek@ziade.org
-License: PSF
-Keywords: keyring,password,crypt
-Requires-Dist: foo; sys.platform == 'okook'
-Requires-Dist: bar; sys.platform == '%s'
-Platform: UNKNOWN
-Description: CLVault
- |=======
- |
- |CLVault uses Keyring to provide a command-line utility to safely store
- |and retrieve passwords.
- |
- |Install it using pip or the setup.py script::
- |
- | $ python setup.py install
- |
- | $ pip install clvault
- |
- |Once it's installed, you will have three scripts installed in your
- |Python scripts folder, you can use to list, store and retrieve passwords::
- |
- | $ clvault-set blog
- | Set your password:
- | Set the associated username (can be blank): tarek
- | Set a description (can be blank): My blog password
- | Password set.
- |
- | $ clvault-get blog
- | The username is "tarek"
- | The password has been copied in your clipboard
- |
- | $ clvault-list
- | Registered services:
- | blog My blog password
- |
- |
- |*clvault-set* takes a service name then prompt you for a password, and some
- |optional information about your service. The password is safely stored in
- |a keyring while the description is saved in a ``.clvault`` file in your
- |home directory. This file is created automatically the first time the command
- |is used.
- |
- |*clvault-get* copies the password for a given service in your clipboard, and
- |displays the associated user if any.
- |
- |*clvault-list* lists all registered services, with their description when
- |given.
- |
- |
- |Project page: http://bitbucket.org/tarek/clvault
- |
diff --git a/src/distutils2/tests/SETUPTOOLS-PKG-INFO b/src/distutils2/tests/SETUPTOOLS-PKG-INFO
deleted file mode 100644
index dff8d00..0000000
--- a/src/distutils2/tests/SETUPTOOLS-PKG-INFO
+++ /dev/null
@@ -1,182 +0,0 @@
-Metadata-Version: 1.0
-Name: setuptools
-Version: 0.6c9
-Summary: Download, build, install, upgrade, and uninstall Python packages -- easily!
-Home-page: http://pypi.python.org/pypi/setuptools
-Author: Phillip J. Eby
-Author-email: distutils-sig@python.org
-License: PSF or ZPL
-Description: ===============================
- Installing and Using Setuptools
- ===============================
-
- .. contents:: **Table of Contents**
-
-
- -------------------------
- Installation Instructions
- -------------------------
-
- Windows
- =======
-
- Install setuptools using the provided ``.exe`` installer. If you've previously
- installed older versions of setuptools, please delete all ``setuptools*.egg``
- and ``setuptools.pth`` files from your system's ``site-packages`` directory
- (and any other ``sys.path`` directories) FIRST.
-
- If you are upgrading a previous version of setuptools that was installed using
- an ``.exe`` installer, please be sure to also *uninstall that older version*
- via your system's "Add/Remove Programs" feature, BEFORE installing the newer
- version.
-
- Once installation is complete, you will find an ``easy_install.exe`` program in
- your Python ``Scripts`` subdirectory. Be sure to add this directory to your
- ``PATH`` environment variable, if you haven't already done so.
-
-
- RPM-Based Systems
- =================
-
- Install setuptools using the provided source RPM. The included ``.spec`` file
- assumes you are installing using the default ``python`` executable, and is not
- specific to a particular Python version. The ``easy_install`` executable will
- be installed to a system ``bin`` directory such as ``/usr/bin``.
-
- If you wish to install to a location other than the default Python
- installation's default ``site-packages`` directory (and ``$prefix/bin`` for
- scripts), please use the ``.egg``-based installation approach described in the
- following section.
-
-
- Cygwin, Mac OS X, Linux, Other
- ==============================
-
- 1. Download the appropriate egg for your version of Python (e.g.
- ``setuptools-0.6c9-py2.4.egg``). Do NOT rename it.
-
- 2. Run it as if it were a shell script, e.g. ``sh setuptools-0.6c9-py2.4.egg``.
- Setuptools will install itself using the matching version of Python (e.g.
- ``python2.4``), and will place the ``easy_install`` executable in the
- default location for installing Python scripts (as determined by the
- standard distutils configuration files, or by the Python installation).
-
- If you want to install setuptools to somewhere other than ``site-packages`` or
- your default distutils installation locations for libraries and scripts, you
- may include EasyInstall command-line options such as ``--prefix``,
- ``--install-dir``, and so on, following the ``.egg`` filename on the same
- command line. For example::
-
- sh setuptools-0.6c9-py2.4.egg --prefix=~
-
- You can use ``--help`` to get a full options list, but we recommend consulting
- the `EasyInstall manual`_ for detailed instructions, especially `the section
- on custom installation locations`_.
-
- .. _EasyInstall manual: http://peak.telecommunity.com/DevCenter/EasyInstall
- .. _the section on custom installation locations: http://peak.telecommunity.com/DevCenter/EasyInstall#custom-installation-locations
-
-
- Cygwin Note
- -----------
-
- If you are trying to install setuptools for the **Windows** version of Python
- (as opposed to the Cygwin version that lives in ``/usr/bin``), you must make
- sure that an appropriate executable (``python2.3``, ``python2.4``, or
- ``python2.5``) is on your **Cygwin** ``PATH`` when invoking the egg. For
- example, doing the following at a Cygwin bash prompt will install setuptools
- for the **Windows** Python found at ``C:\\Python24``::
-
- ln -s /cygdrive/c/Python24/python.exe python2.4
- PATH=.:$PATH sh setuptools-0.6c9-py2.4.egg
- rm python2.4
-
-
- Downloads
- =========
-
- All setuptools downloads can be found at `the project's home page in the Python
- Package Index`_. Scroll to the very bottom of the page to find the links.
-
- .. _the project's home page in the Python Package Index: http://pypi.python.org/pypi/setuptools
-
- In addition to the PyPI downloads, the development version of ``setuptools``
- is available from the `Python SVN sandbox`_, and in-development versions of the
- `0.6 branch`_ are available as well.
-
- .. _0.6 branch: http://svn.python.org/projects/sandbox/branches/setuptools-0.6/#egg=setuptools-dev06
-
- .. _Python SVN sandbox: http://svn.python.org/projects/sandbox/trunk/setuptools/#egg=setuptools-dev
-
- --------------------------------
- Using Setuptools and EasyInstall
- --------------------------------
-
- Here are some of the available manuals, tutorials, and other resources for
- learning about Setuptools, Python Eggs, and EasyInstall:
-
- * `The EasyInstall user's guide and reference manual`_
- * `The setuptools Developer's Guide`_
- * `The pkg_resources API reference`_
- * `Package Compatibility Notes`_ (user-maintained)
- * `The Internal Structure of Python Eggs`_
-
- Questions, comments, and bug reports should be directed to the `distutils-sig
- mailing list`_. If you have written (or know of) any tutorials, documentation,
- plug-ins, or other resources for setuptools users, please let us know about
- them there, so this reference list can be updated. If you have working,
- *tested* patches to correct problems or add features, you may submit them to
- the `setuptools bug tracker`_.
-
- .. _setuptools bug tracker: http://bugs.python.org/setuptools/
- .. _Package Compatibility Notes: http://peak.telecommunity.com/DevCenter/PackageNotes
- .. _The Internal Structure of Python Eggs: http://peak.telecommunity.com/DevCenter/EggFormats
- .. _The setuptools Developer's Guide: http://peak.telecommunity.com/DevCenter/setuptools
- .. _The pkg_resources API reference: http://peak.telecommunity.com/DevCenter/PkgResources
- .. _The EasyInstall user's guide and reference manual: http://peak.telecommunity.com/DevCenter/EasyInstall
- .. _distutils-sig mailing list: http://mail.python.org/pipermail/distutils-sig/
-
-
- -------
- Credits
- -------
-
- * The original design for the ``.egg`` format and the ``pkg_resources`` API was
- co-created by Phillip Eby and Bob Ippolito. Bob also implemented the first
- version of ``pkg_resources``, and supplied the OS X operating system version
- compatibility algorithm.
-
- * Ian Bicking implemented many early "creature comfort" features of
- easy_install, including support for downloading via Sourceforge and
- Subversion repositories. Ian's comments on the Web-SIG about WSGI
- application deployment also inspired the concept of "entry points" in eggs,
- and he has given talks at PyCon and elsewhere to inform and educate the
- community about eggs and setuptools.
-
- * Jim Fulton contributed time and effort to build automated tests of various
- aspects of ``easy_install``, and supplied the doctests for the command-line
- ``.exe`` wrappers on Windows.
-
- * Phillip J. Eby is the principal author and maintainer of setuptools, and
- first proposed the idea of an importable binary distribution format for
- Python application plug-ins.
-
- * Significant parts of the implementation of setuptools were funded by the Open
- Source Applications Foundation, to provide a plug-in infrastructure for the
- Chandler PIM application. In addition, many OSAF staffers (such as Mike
- "Code Bear" Taylor) contributed their time and stress as guinea pigs for the
- use of eggs and setuptools, even before eggs were "cool". (Thanks, guys!)
-
-
-Keywords: CPAN PyPI distutils eggs package management
-Platform: UNKNOWN
-Classifier: Development Status :: 3 - Alpha
-Classifier: Intended Audience :: Developers
-Classifier: License :: OSI Approved :: Python Software Foundation License
-Classifier: License :: OSI Approved :: Zope Public License
-Classifier: Operating System :: OS Independent
-Classifier: Programming Language :: Python
-Classifier: Topic :: Software Development :: Libraries :: Python Modules
-Classifier: Topic :: System :: Archiving :: Packaging
-Classifier: Topic :: System :: Systems Administration
-Classifier: Topic :: Utilities
diff --git a/src/distutils2/tests/SETUPTOOLS-PKG-INFO2 b/src/distutils2/tests/SETUPTOOLS-PKG-INFO2
deleted file mode 100644
index 4b3906a..0000000
--- a/src/distutils2/tests/SETUPTOOLS-PKG-INFO2
+++ /dev/null
@@ -1,183 +0,0 @@
-Metadata-Version: 1.1
-Name: setuptools
-Version: 0.6c9
-Summary: Download, build, install, upgrade, and uninstall Python packages -- easily!
-Home-page: http://pypi.python.org/pypi/setuptools
-Author: Phillip J. Eby
-Author-email: distutils-sig@python.org
-License: PSF or ZPL
-Description: ===============================
- Installing and Using Setuptools
- ===============================
-
- .. contents:: **Table of Contents**
-
-
- -------------------------
- Installation Instructions
- -------------------------
-
- Windows
- =======
-
- Install setuptools using the provided ``.exe`` installer. If you've previously
- installed older versions of setuptools, please delete all ``setuptools*.egg``
- and ``setuptools.pth`` files from your system's ``site-packages`` directory
- (and any other ``sys.path`` directories) FIRST.
-
- If you are upgrading a previous version of setuptools that was installed using
- an ``.exe`` installer, please be sure to also *uninstall that older version*
- via your system's "Add/Remove Programs" feature, BEFORE installing the newer
- version.
-
- Once installation is complete, you will find an ``easy_install.exe`` program in
- your Python ``Scripts`` subdirectory. Be sure to add this directory to your
- ``PATH`` environment variable, if you haven't already done so.
-
-
- RPM-Based Systems
- =================
-
- Install setuptools using the provided source RPM. The included ``.spec`` file
- assumes you are installing using the default ``python`` executable, and is not
- specific to a particular Python version. The ``easy_install`` executable will
- be installed to a system ``bin`` directory such as ``/usr/bin``.
-
- If you wish to install to a location other than the default Python
- installation's default ``site-packages`` directory (and ``$prefix/bin`` for
- scripts), please use the ``.egg``-based installation approach described in the
- following section.
-
-
- Cygwin, Mac OS X, Linux, Other
- ==============================
-
- 1. Download the appropriate egg for your version of Python (e.g.
- ``setuptools-0.6c9-py2.4.egg``). Do NOT rename it.
-
- 2. Run it as if it were a shell script, e.g. ``sh setuptools-0.6c9-py2.4.egg``.
- Setuptools will install itself using the matching version of Python (e.g.
- ``python2.4``), and will place the ``easy_install`` executable in the
- default location for installing Python scripts (as determined by the
- standard distutils configuration files, or by the Python installation).
-
- If you want to install setuptools to somewhere other than ``site-packages`` or
- your default distutils installation locations for libraries and scripts, you
- may include EasyInstall command-line options such as ``--prefix``,
- ``--install-dir``, and so on, following the ``.egg`` filename on the same
- command line. For example::
-
- sh setuptools-0.6c9-py2.4.egg --prefix=~
-
- You can use ``--help`` to get a full options list, but we recommend consulting
- the `EasyInstall manual`_ for detailed instructions, especially `the section
- on custom installation locations`_.
-
- .. _EasyInstall manual: http://peak.telecommunity.com/DevCenter/EasyInstall
- .. _the section on custom installation locations: http://peak.telecommunity.com/DevCenter/EasyInstall#custom-installation-locations
-
-
- Cygwin Note
- -----------
-
- If you are trying to install setuptools for the **Windows** version of Python
- (as opposed to the Cygwin version that lives in ``/usr/bin``), you must make
- sure that an appropriate executable (``python2.3``, ``python2.4``, or
- ``python2.5``) is on your **Cygwin** ``PATH`` when invoking the egg. For
- example, doing the following at a Cygwin bash prompt will install setuptools
- for the **Windows** Python found at ``C:\\Python24``::
-
- ln -s /cygdrive/c/Python24/python.exe python2.4
- PATH=.:$PATH sh setuptools-0.6c9-py2.4.egg
- rm python2.4
-
-
- Downloads
- =========
-
- All setuptools downloads can be found at `the project's home page in the Python
- Package Index`_. Scroll to the very bottom of the page to find the links.
-
- .. _the project's home page in the Python Package Index: http://pypi.python.org/pypi/setuptools
-
- In addition to the PyPI downloads, the development version of ``setuptools``
- is available from the `Python SVN sandbox`_, and in-development versions of the
- `0.6 branch`_ are available as well.
-
- .. _0.6 branch: http://svn.python.org/projects/sandbox/branches/setuptools-0.6/#egg=setuptools-dev06
-
- .. _Python SVN sandbox: http://svn.python.org/projects/sandbox/trunk/setuptools/#egg=setuptools-dev
-
- --------------------------------
- Using Setuptools and EasyInstall
- --------------------------------
-
- Here are some of the available manuals, tutorials, and other resources for
- learning about Setuptools, Python Eggs, and EasyInstall:
-
- * `The EasyInstall user's guide and reference manual`_
- * `The setuptools Developer's Guide`_
- * `The pkg_resources API reference`_
- * `Package Compatibility Notes`_ (user-maintained)
- * `The Internal Structure of Python Eggs`_
-
- Questions, comments, and bug reports should be directed to the `distutils-sig
- mailing list`_. If you have written (or know of) any tutorials, documentation,
- plug-ins, or other resources for setuptools users, please let us know about
- them there, so this reference list can be updated. If you have working,
- *tested* patches to correct problems or add features, you may submit them to
- the `setuptools bug tracker`_.
-
- .. _setuptools bug tracker: http://bugs.python.org/setuptools/
- .. _Package Compatibility Notes: http://peak.telecommunity.com/DevCenter/PackageNotes
- .. _The Internal Structure of Python Eggs: http://peak.telecommunity.com/DevCenter/EggFormats
- .. _The setuptools Developer's Guide: http://peak.telecommunity.com/DevCenter/setuptools
- .. _The pkg_resources API reference: http://peak.telecommunity.com/DevCenter/PkgResources
- .. _The EasyInstall user's guide and reference manual: http://peak.telecommunity.com/DevCenter/EasyInstall
- .. _distutils-sig mailing list: http://mail.python.org/pipermail/distutils-sig/
-
-
- -------
- Credits
- -------
-
- * The original design for the ``.egg`` format and the ``pkg_resources`` API was
- co-created by Phillip Eby and Bob Ippolito. Bob also implemented the first
- version of ``pkg_resources``, and supplied the OS X operating system version
- compatibility algorithm.
-
- * Ian Bicking implemented many early "creature comfort" features of
- easy_install, including support for downloading via Sourceforge and
- Subversion repositories. Ian's comments on the Web-SIG about WSGI
- application deployment also inspired the concept of "entry points" in eggs,
- and he has given talks at PyCon and elsewhere to inform and educate the
- community about eggs and setuptools.
-
- * Jim Fulton contributed time and effort to build automated tests of various
- aspects of ``easy_install``, and supplied the doctests for the command-line
- ``.exe`` wrappers on Windows.
-
- * Phillip J. Eby is the principal author and maintainer of setuptools, and
- first proposed the idea of an importable binary distribution format for
- Python application plug-ins.
-
- * Significant parts of the implementation of setuptools were funded by the Open
- Source Applications Foundation, to provide a plug-in infrastructure for the
- Chandler PIM application. In addition, many OSAF staffers (such as Mike
- "Code Bear" Taylor) contributed their time and stress as guinea pigs for the
- use of eggs and setuptools, even before eggs were "cool". (Thanks, guys!)
-
-
-Keywords: CPAN PyPI distutils eggs package management
-Platform: UNKNOWN
-Classifier: Development Status :: 3 - Alpha
-Classifier: Intended Audience :: Developers
-Classifier: License :: OSI Approved :: Python Software Foundation License
-Classifier: License :: OSI Approved :: Zope Public License
-Classifier: Operating System :: OS Independent
-Classifier: Programming Language :: Python
-Classifier: Topic :: Software Development :: Libraries :: Python Modules
-Classifier: Topic :: System :: Archiving :: Packaging
-Classifier: Topic :: System :: Systems Administration
-Classifier: Topic :: Utilities
-Requires: Foo
diff --git a/src/distutils2/tests/__init__.py b/src/distutils2/tests/__init__.py
deleted file mode 100644
index a459bda..0000000
--- a/src/distutils2/tests/__init__.py
+++ /dev/null
@@ -1,135 +0,0 @@
-"""Test suite for distutils2.
-
-This test suite consists of a collection of test modules in the
-distutils2.tests package. Each test module has a name starting with
-'test' and contains a function test_suite(). The function is expected
-to return an initialized unittest.TestSuite instance.
-
-Tests for the command classes in the distutils2.command package are
-included in distutils2.tests as well, instead of using a separate
-distutils2.command.tests package, since command identification is done
-by import rather than matching pre-defined names.
-
-Utility code is included in distutils2.tests.support. Always import
-unittest from that module, it will be the right version (standard
-library unittest for 2.7 and higher, third-party unittest2 release for
-older versions).
-"""
-
-import os
-import sys
-from distutils2.tests.support import unittest
-
-from test.test_support import TESTFN # use TESTFN from stdlib/test_support.
-
-here = os.path.dirname(__file__) or os.curdir
-
-verbose = 1
-
-def test_suite():
- suite = unittest.TestSuite()
- for fn in os.listdir(here):
- if fn.startswith("test") and fn.endswith(".py"):
- modname = "distutils2.tests." + fn[:-3]
- __import__(modname)
- module = sys.modules[modname]
- suite.addTest(module.test_suite())
- return suite
-
-class Error(Exception):
- """Base class for regression test exceptions."""
-
-
-class TestFailed(Error):
- """Test failed."""
-
-
-class BasicTestRunner(object):
- def run(self, test):
- result = unittest.TestResult()
- test(result)
- return result
-
-
-def _run_suite(suite, verbose_=1):
- """Run tests from a unittest.TestSuite-derived class."""
- global verbose
- verbose = verbose_
- if verbose_:
- runner = unittest.TextTestRunner(sys.stdout, verbosity=2)
- else:
- runner = BasicTestRunner()
-
- result = runner.run(suite)
- if not result.wasSuccessful():
- if len(result.errors) == 1 and not result.failures:
- err = result.errors[0][1]
- elif len(result.failures) == 1 and not result.errors:
- err = result.failures[0][1]
- else:
- err = "errors occurred; run in verbose mode for details"
- raise TestFailed(err)
-
-
-def run_unittest(classes, verbose_=1):
- """Run tests from unittest.TestCase-derived classes.
-
- Extracted from stdlib test.test_support and modified to support unittest.
- """
- valid_types = (unittest.TestSuite, unittest.TestCase)
- suite = unittest.TestSuite()
- for cls in classes:
- if isinstance(cls, str):
- if cls in sys.modules:
- suite.addTest(unittest.findTestCases(sys.modules[cls]))
- else:
- raise ValueError("str arguments must be keys in sys.modules")
- elif isinstance(cls, valid_types):
- suite.addTest(cls)
- else:
- suite.addTest(unittest.makeSuite(cls))
- _run_suite(suite, verbose_)
-
-
-def reap_children():
- """Use this function at the end of test_main() whenever sub-processes
- are started. This will help ensure that no extra children (zombies)
- stick around to hog resources and create problems when looking
- for refleaks.
-
- Extracted from stdlib test.test_support.
- """
-
- # Reap all our dead child processes so we don't leave zombies around.
- # These hog resources and might be causing some of the buildbots to die.
- if hasattr(os, 'waitpid'):
- any_process = -1
- while True:
- try:
- # This will raise an exception on Windows. That's ok.
- pid, status = os.waitpid(any_process, os.WNOHANG)
- if pid == 0:
- break
- except:
- break
-
-def captured_stdout(func, *args, **kw):
- import StringIO
- orig_stdout = getattr(sys, 'stdout')
- setattr(sys, 'stdout', StringIO.StringIO())
- try:
- res = func(*args, **kw)
- sys.stdout.seek(0)
- return res, sys.stdout.read()
- finally:
- setattr(sys, 'stdout', orig_stdout)
-
-def unload(name):
- try:
- del sys.modules[name]
- except KeyError:
- pass
-
-
-if __name__ == "__main__":
- unittest.main(defaultTest="test_suite")
diff --git a/src/distutils2/tests/conversions/01_after.py b/src/distutils2/tests/conversions/01_after.py
deleted file mode 100644
index 93f818a..0000000
--- a/src/distutils2/tests/conversions/01_after.py
+++ /dev/null
@@ -1,4 +0,0 @@
-from distutils2.core import setup
-
-setup(name='Foo')
-
diff --git a/src/distutils2/tests/conversions/01_before.py b/src/distutils2/tests/conversions/01_before.py
deleted file mode 100644
index 3e818d8..0000000
--- a/src/distutils2/tests/conversions/01_before.py
+++ /dev/null
@@ -1,4 +0,0 @@
-from distutils.core import setup
-
-setup(name='Foo')
-
diff --git a/src/distutils2/tests/conversions/02_after.py b/src/distutils2/tests/conversions/02_after.py
deleted file mode 100644
index bfc2d8f..0000000
--- a/src/distutils2/tests/conversions/02_after.py
+++ /dev/null
@@ -1,46 +0,0 @@
-# -*- encoding: utf-8 -*-
-import sys
-import os
-from distutils2.core import setup, Extension
-from distutils2.errors import CCompilerError, DistutilsError, CompileError
-from distutils2.command.build_ext import build_ext as distutils_build_ext
-
-VERSION = "0.1"
-
-class build_ext(distutils_build_ext):
-
- def build_extension(self, ext):
- try:
- return distutils_build_ext.build_extension(self, ext)
- except (CCompilerError, DistutilsError, CompileError), e:
- pass
-
-def _get_ext_modules():
- levenshtein = Extension('_levenshtein',
- sources=[os.path.join('texttools',
- '_levenshtein.c')])
- return [levenshtein]
-
-with open('README.txt') as f:
- LONG_DESCRIPTION = f.read()
-
-setup(name="TextTools", version=VERSION, author="Tarek Ziade",
- author_email="tarek@ziade.org",
- home_page="http://bitbucket.org/tarek/texttools",
- summary="Text manipulation utilities",
- description=LONG_DESCRIPTION,
- keywords="text,guess,levenshtein",
- classifiers=[
- 'Development Status :: 4 - Beta',
- 'Intended Audience :: Developers',
- 'License :: OSI Approved :: Python Software Foundation License'
- ],
- cmdclass={'build_ext': build_ext},
- packages=['texttools'],
- package_dir={'texttools': 'texttools'},
- package_data={'texttools': [os.path.join('samples', '*.txt')]},
- scripts=[os.path.join('scripts', 'levenshtein.py'),
- os.path.join('scripts', 'guesslang.py')],
- ext_modules=_get_ext_modules()
- )
-
diff --git a/src/distutils2/tests/conversions/02_before.py b/src/distutils2/tests/conversions/02_before.py
deleted file mode 100644
index f7ccc12..0000000
--- a/src/distutils2/tests/conversions/02_before.py
+++ /dev/null
@@ -1,46 +0,0 @@
-# -*- encoding: utf-8 -*-
-import sys
-import os
-from distutils.core import setup, Extension
-from distutils.errors import CCompilerError, DistutilsError, CompileError
-from distutils.command.build_ext import build_ext as distutils_build_ext
-
-VERSION = "0.1"
-
-class build_ext(distutils_build_ext):
-
- def build_extension(self, ext):
- try:
- return distutils_build_ext.build_extension(self, ext)
- except (CCompilerError, DistutilsError, CompileError), e:
- pass
-
-def _get_ext_modules():
- levenshtein = Extension('_levenshtein',
- sources=[os.path.join('texttools',
- '_levenshtein.c')])
- return [levenshtein]
-
-with open('README.txt') as f:
- LONG_DESCRIPTION = f.read()
-
-setup(name="TextTools", version=VERSION, author="Tarek Ziade",
- author_email="tarek@ziade.org",
- url="http://bitbucket.org/tarek/texttools",
- description="Text manipulation utilities",
- long_description=LONG_DESCRIPTION,
- keywords="text,guess,levenshtein",
- classifiers=[
- 'Development Status :: 4 - Beta',
- 'Intended Audience :: Developers',
- 'License :: OSI Approved :: Python Software Foundation License'
- ],
- cmdclass={'build_ext': build_ext},
- packages=['texttools'],
- package_dir={'texttools': 'texttools'},
- package_data={'texttools': [os.path.join('samples', '*.txt')]},
- scripts=[os.path.join('scripts', 'levenshtein.py'),
- os.path.join('scripts', 'guesslang.py')],
- ext_modules=_get_ext_modules()
- )
-
diff --git a/src/distutils2/tests/conversions/03_after.py b/src/distutils2/tests/conversions/03_after.py
deleted file mode 100644
index 3d4dafa..0000000
--- a/src/distutils2/tests/conversions/03_after.py
+++ /dev/null
@@ -1,93 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2006-2009 Zope Corporation and Contributors.
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
-# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
-# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE.
-#
-##############################################################################
-name = "zc.buildout"
-version = "1.5.0dev"
-
-import os
-from distutils2.core import setup
-
-def read(*rnames):
- return open(os.path.join(os.path.dirname(__file__), *rnames)).read()
-
-long_description=(
- read('README.txt')
- + '\n' +
- 'Detailed Documentation\n'
- '**********************\n'
- + '\n' +
- read('src', 'zc', 'buildout', 'buildout.txt')
- + '\n' +
- read('src', 'zc', 'buildout', 'unzip.txt')
- + '\n' +
- read('src', 'zc', 'buildout', 'repeatable.txt')
- + '\n' +
- read('src', 'zc', 'buildout', 'download.txt')
- + '\n' +
- read('src', 'zc', 'buildout', 'downloadcache.txt')
- + '\n' +
- read('src', 'zc', 'buildout', 'extends-cache.txt')
- + '\n' +
- read('src', 'zc', 'buildout', 'setup.txt')
- + '\n' +
- read('src', 'zc', 'buildout', 'update.txt')
- + '\n' +
- read('src', 'zc', 'buildout', 'debugging.txt')
- + '\n' +
- read('src', 'zc', 'buildout', 'testing.txt')
- + '\n' +
- read('src', 'zc', 'buildout', 'easy_install.txt')
- + '\n' +
- read('src', 'zc', 'buildout', 'distribute.txt')
- + '\n' +
- read('CHANGES.txt')
- + '\n' +
- 'Download\n'
- '**********************\n'
- )
-
-entry_points = """
-[console_scripts]
-buildout = %(name)s.buildout:main
-
-[zc.buildout]
-debug = %(name)s.testrecipes:Debug
-
-""" % dict(name=name)
-
-setup(
- name = name,
- version = version,
- author = "Jim Fulton",
- author_email = "jim@zope.com",
- summary = "System for managing development buildouts",
- description=long_description,
- license = "ZPL 2.1",
- keywords = "development build",
- home_page='http://buildout.org',
-
- data_files = [('.', ['README.txt'])],
- packages = ['zc', 'zc.buildout'],
- package_dir = {'': 'src'},
- namespace_packages = ['zc'],
- requires_dist = ['setuptools'],
- include_package_data = True,
- entry_points = entry_points,
- zip_safe=False,
- classifiers = [
- 'Intended Audience :: Developers',
- 'License :: OSI Approved :: Zope Public License',
- 'Topic :: Software Development :: Build Tools',
- 'Topic :: Software Development :: Libraries :: Python Modules',
- ],
- )
diff --git a/src/distutils2/tests/conversions/03_before.py b/src/distutils2/tests/conversions/03_before.py
deleted file mode 100644
index 31a99fc..0000000
--- a/src/distutils2/tests/conversions/03_before.py
+++ /dev/null
@@ -1,93 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2006-2009 Zope Corporation and Contributors.
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
-# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
-# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE.
-#
-##############################################################################
-name = "zc.buildout"
-version = "1.5.0dev"
-
-import os
-from setuptools import setup
-
-def read(*rnames):
- return open(os.path.join(os.path.dirname(__file__), *rnames)).read()
-
-long_description=(
- read('README.txt')
- + '\n' +
- 'Detailed Documentation\n'
- '**********************\n'
- + '\n' +
- read('src', 'zc', 'buildout', 'buildout.txt')
- + '\n' +
- read('src', 'zc', 'buildout', 'unzip.txt')
- + '\n' +
- read('src', 'zc', 'buildout', 'repeatable.txt')
- + '\n' +
- read('src', 'zc', 'buildout', 'download.txt')
- + '\n' +
- read('src', 'zc', 'buildout', 'downloadcache.txt')
- + '\n' +
- read('src', 'zc', 'buildout', 'extends-cache.txt')
- + '\n' +
- read('src', 'zc', 'buildout', 'setup.txt')
- + '\n' +
- read('src', 'zc', 'buildout', 'update.txt')
- + '\n' +
- read('src', 'zc', 'buildout', 'debugging.txt')
- + '\n' +
- read('src', 'zc', 'buildout', 'testing.txt')
- + '\n' +
- read('src', 'zc', 'buildout', 'easy_install.txt')
- + '\n' +
- read('src', 'zc', 'buildout', 'distribute.txt')
- + '\n' +
- read('CHANGES.txt')
- + '\n' +
- 'Download\n'
- '**********************\n'
- )
-
-entry_points = """
-[console_scripts]
-buildout = %(name)s.buildout:main
-
-[zc.buildout]
-debug = %(name)s.testrecipes:Debug
-
-""" % dict(name=name)
-
-setup(
- name = name,
- version = version,
- author = "Jim Fulton",
- author_email = "jim@zope.com",
- description = "System for managing development buildouts",
- long_description=long_description,
- license = "ZPL 2.1",
- keywords = "development build",
- url='http://buildout.org',
-
- data_files = [('.', ['README.txt'])],
- packages = ['zc', 'zc.buildout'],
- package_dir = {'': 'src'},
- namespace_packages = ['zc'],
- install_requires = 'setuptools',
- include_package_data = True,
- entry_points = entry_points,
- zip_safe=False,
- classifiers = [
- 'Intended Audience :: Developers',
- 'License :: OSI Approved :: Zope Public License',
- 'Topic :: Software Development :: Build Tools',
- 'Topic :: Software Development :: Libraries :: Python Modules',
- ],
- )
diff --git a/src/distutils2/tests/conversions/04_after.py b/src/distutils2/tests/conversions/04_after.py
deleted file mode 100644
index f366a48..0000000
--- a/src/distutils2/tests/conversions/04_after.py
+++ /dev/null
@@ -1,69 +0,0 @@
-import sys, os
-try:
- from distutils2.core import setup
- kw = {'entry_points':
- """[console_scripts]\nvirtualenv = virtualenv:main\n""",
- 'zip_safe': False}
-except ImportError:
- from distutils2.core import setup
- if sys.platform == 'win32':
- print('Note: without Setuptools installed you will have to use "python -m virtualenv ENV"')
- else:
- kw = {'scripts': ['scripts/virtualenv']}
-import re
-
-here = os.path.dirname(os.path.abspath(__file__))
-
-## Figure out the version from virtualenv.py:
-version_re = re.compile(
- r'virtualenv_version = "(.*?)"')
-fp = open(os.path.join(here, 'virtualenv.py'))
-version = None
-for line in fp:
- match = version_re.search(line)
- if match:
- version = match.group(1)
- break
-else:
- raise Exception("Cannot find version in virtualenv.py")
-fp.close()
-
-## Get long_description from index.txt:
-f = open(os.path.join(here, 'docs', 'index.txt'))
-long_description = f.read().strip()
-long_description = long_description.split('split here', 1)[1]
-f.close()
-
-## A warning just for Ian (related to distribution):
-try:
- import getpass
-except ImportError:
- is_ianb = False
-else:
- is_ianb = getpass.getuser() == 'ianb'
-
-if is_ianb and 'register' in sys.argv:
- if 'hg tip\n~~~~~~' in long_description:
- print >> sys.stderr, (
- "WARNING: hg tip is in index.txt")
-
-setup(name='virtualenv',
- version=version,
- summary="Virtual Python Environment builder",
- description=long_description,
- classifiers=[
- 'Development Status :: 4 - Beta',
- 'Intended Audience :: Developers',
- 'License :: OSI Approved :: MIT License',
- ],
- keywords='setuptools deployment installation distutils',
- author='Ian Bicking',
- author_email='ianb@colorstudy.com',
- home_page='http://virtualenv.openplans.org',
- license='MIT',
- use_2to3=True,
- py_modules=['virtualenv'],
- packages=['virtualenv_support'],
- package_data={'virtualenv_support': ['*-py%s.egg' % sys.version[:3], '*.tar.gz']},
- **kw
- )
diff --git a/src/distutils2/tests/conversions/04_before.py b/src/distutils2/tests/conversions/04_before.py
deleted file mode 100644
index 4792595..0000000
--- a/src/distutils2/tests/conversions/04_before.py
+++ /dev/null
@@ -1,69 +0,0 @@
-import sys, os
-try:
- from setuptools import setup
- kw = {'entry_points':
- """[console_scripts]\nvirtualenv = virtualenv:main\n""",
- 'zip_safe': False}
-except ImportError:
- from distutils.core import setup
- if sys.platform == 'win32':
- print('Note: without Setuptools installed you will have to use "python -m virtualenv ENV"')
- else:
- kw = {'scripts': ['scripts/virtualenv']}
-import re
-
-here = os.path.dirname(os.path.abspath(__file__))
-
-## Figure out the version from virtualenv.py:
-version_re = re.compile(
- r'virtualenv_version = "(.*?)"')
-fp = open(os.path.join(here, 'virtualenv.py'))
-version = None
-for line in fp:
- match = version_re.search(line)
- if match:
- version = match.group(1)
- break
-else:
- raise Exception("Cannot find version in virtualenv.py")
-fp.close()
-
-## Get long_description from index.txt:
-f = open(os.path.join(here, 'docs', 'index.txt'))
-long_description = f.read().strip()
-long_description = long_description.split('split here', 1)[1]
-f.close()
-
-## A warning just for Ian (related to distribution):
-try:
- import getpass
-except ImportError:
- is_ianb = False
-else:
- is_ianb = getpass.getuser() == 'ianb'
-
-if is_ianb and 'register' in sys.argv:
- if 'hg tip\n~~~~~~' in long_description:
- print >> sys.stderr, (
- "WARNING: hg tip is in index.txt")
-
-setup(name='virtualenv',
- version=version,
- description="Virtual Python Environment builder",
- long_description=long_description,
- classifiers=[
- 'Development Status :: 4 - Beta',
- 'Intended Audience :: Developers',
- 'License :: OSI Approved :: MIT License',
- ],
- keywords='setuptools deployment installation distutils',
- author='Ian Bicking',
- author_email='ianb@colorstudy.com',
- url='http://virtualenv.openplans.org',
- license='MIT',
- use_2to3=True,
- py_modules=['virtualenv'],
- packages=['virtualenv_support'],
- package_data={'virtualenv_support': ['*-py%s.egg' % sys.version[:3], '*.tar.gz']},
- **kw
- )
diff --git a/src/distutils2/tests/conversions/05_after.py b/src/distutils2/tests/conversions/05_after.py
deleted file mode 100644
index 2f6a7b3..0000000
--- a/src/distutils2/tests/conversions/05_after.py
+++ /dev/null
@@ -1,137 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-#
-# Copyright (C) 2003-2009 Edgewall Software
-# All rights reserved.
-#
-# This software is licensed as described in the file COPYING, which
-# you should have received as part of this distribution. The terms
-# are also available at http://trac.edgewall.org/wiki/TracLicense.
-#
-# This software consists of voluntary contributions made by many
-# individuals. For the exact contribution history, see the revision
-# history and logs, available at http://trac.edgewall.org/log/.
-
-from distutils2.core import setup, find_packages
-
-extra = {}
-
-try:
- import babel
-
- extractors = [
- ('**.py', 'python', None),
- ('**/templates/**.html', 'genshi', None),
- ('**/templates/**.txt', 'genshi',
- {'template_class': 'genshi.template:NewTextTemplate'}),
- ]
- extra['message_extractors'] = {
- 'trac': extractors,
- 'tracopt': extractors,
- }
-
- from trac.util.dist import get_l10n_js_cmdclass
- extra['cmdclass'] = get_l10n_js_cmdclass()
-
-except ImportError, e:
- pass
-
-setup(
- name = 'Trac',
- version = '0.12.1',
- summary = 'Integrated SCM, wiki, issue tracker and project environment',
- description = """
-Trac is a minimalistic web-based software project management and bug/issue
-tracking system. It provides an interface to the Subversion revision control
-systems, an integrated wiki, flexible issue tracking and convenient report
-facilities.
-""",
- author = 'Edgewall Software',
- author_email = 'info@edgewall.com',
- license = 'BSD',
- home_page = 'http://trac.edgewall.org/',
- download_url = 'http://trac.edgewall.org/wiki/TracDownload',
- classifiers = [
- 'Environment :: Web Environment',
- 'Framework :: Trac',
- 'Intended Audience :: Developers',
- 'License :: OSI Approved :: BSD License',
- 'Operating System :: OS Independent',
- 'Programming Language :: Python',
- 'Topic :: Software Development :: Bug Tracking',
- 'Topic :: Software Development :: Version Control',
- ],
-
- packages = find_packages(exclude=['*.tests']),
- package_data = {
- '': ['templates/*'],
- 'trac': ['htdocs/*.*', 'htdocs/README', 'htdocs/js/*.*',
- 'htdocs/js/messages/*.*', 'htdocs/css/*.*',
- 'htdocs/guide/*', 'locale/*/LC_MESSAGES/messages.mo'],
- 'trac.wiki': ['default-pages/*'],
- 'trac.ticket': ['workflows/*.ini'],
- },
-
- test_suite = 'trac.test.suite',
- zip_safe = True,
-
- requires_dist = [
- 'setuptools>=0.6b1',
- 'Genshi>=0.6',
- ],
- extras_require = {
- 'Babel': ['Babel>=0.9.5'],
- 'Pygments': ['Pygments>=0.6'],
- 'reST': ['docutils>=0.3'],
- 'SilverCity': ['SilverCity>=0.9.4'],
- 'Textile': ['textile>=2.0'],
- },
-
- entry_points = """
- [console_scripts]
- trac-admin = trac.admin.console:run
- tracd = trac.web.standalone:main
-
- [trac.plugins]
- trac.about = trac.about
- trac.admin.console = trac.admin.console
- trac.admin.web_ui = trac.admin.web_ui
- trac.attachment = trac.attachment
- trac.db.mysql = trac.db.mysql_backend
- trac.db.postgres = trac.db.postgres_backend
- trac.db.sqlite = trac.db.sqlite_backend
- trac.mimeview.patch = trac.mimeview.patch
- trac.mimeview.pygments = trac.mimeview.pygments[Pygments]
- trac.mimeview.rst = trac.mimeview.rst[reST]
- trac.mimeview.silvercity = trac.mimeview.silvercity[SilverCity]
- trac.mimeview.txtl = trac.mimeview.txtl[Textile]
- trac.prefs = trac.prefs.web_ui
- trac.search = trac.search.web_ui
- trac.ticket.admin = trac.ticket.admin
- trac.ticket.query = trac.ticket.query
- trac.ticket.report = trac.ticket.report
- trac.ticket.roadmap = trac.ticket.roadmap
- trac.ticket.web_ui = trac.ticket.web_ui
- trac.timeline = trac.timeline.web_ui
- trac.versioncontrol.admin = trac.versioncontrol.admin
- trac.versioncontrol.svn_authz = trac.versioncontrol.svn_authz
- trac.versioncontrol.svn_fs = trac.versioncontrol.svn_fs
- trac.versioncontrol.svn_prop = trac.versioncontrol.svn_prop
- trac.versioncontrol.web_ui = trac.versioncontrol.web_ui
- trac.web.auth = trac.web.auth
- trac.web.session = trac.web.session
- trac.wiki.admin = trac.wiki.admin
- trac.wiki.interwiki = trac.wiki.interwiki
- trac.wiki.macros = trac.wiki.macros
- trac.wiki.web_ui = trac.wiki.web_ui
- trac.wiki.web_api = trac.wiki.web_api
- tracopt.mimeview.enscript = tracopt.mimeview.enscript
- tracopt.mimeview.php = tracopt.mimeview.php
- tracopt.perm.authz_policy = tracopt.perm.authz_policy
- tracopt.perm.config_perm_provider = tracopt.perm.config_perm_provider
- tracopt.ticket.commit_updater = tracopt.ticket.commit_updater
- tracopt.ticket.deleter = tracopt.ticket.deleter
- """,
-
- **extra
-)
diff --git a/src/distutils2/tests/conversions/05_before.py b/src/distutils2/tests/conversions/05_before.py
deleted file mode 100755
index ccce17b..0000000
--- a/src/distutils2/tests/conversions/05_before.py
+++ /dev/null
@@ -1,137 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-#
-# Copyright (C) 2003-2009 Edgewall Software
-# All rights reserved.
-#
-# This software is licensed as described in the file COPYING, which
-# you should have received as part of this distribution. The terms
-# are also available at http://trac.edgewall.org/wiki/TracLicense.
-#
-# This software consists of voluntary contributions made by many
-# individuals. For the exact contribution history, see the revision
-# history and logs, available at http://trac.edgewall.org/log/.
-
-from setuptools import setup, find_packages
-
-extra = {}
-
-try:
- import babel
-
- extractors = [
- ('**.py', 'python', None),
- ('**/templates/**.html', 'genshi', None),
- ('**/templates/**.txt', 'genshi',
- {'template_class': 'genshi.template:NewTextTemplate'}),
- ]
- extra['message_extractors'] = {
- 'trac': extractors,
- 'tracopt': extractors,
- }
-
- from trac.util.dist import get_l10n_js_cmdclass
- extra['cmdclass'] = get_l10n_js_cmdclass()
-
-except ImportError, e:
- pass
-
-setup(
- name = 'Trac',
- version = '0.12.1',
- description = 'Integrated SCM, wiki, issue tracker and project environment',
- long_description = """
-Trac is a minimalistic web-based software project management and bug/issue
-tracking system. It provides an interface to the Subversion revision control
-systems, an integrated wiki, flexible issue tracking and convenient report
-facilities.
-""",
- author = 'Edgewall Software',
- author_email = 'info@edgewall.com',
- license = 'BSD',
- url = 'http://trac.edgewall.org/',
- download_url = 'http://trac.edgewall.org/wiki/TracDownload',
- classifiers = [
- 'Environment :: Web Environment',
- 'Framework :: Trac',
- 'Intended Audience :: Developers',
- 'License :: OSI Approved :: BSD License',
- 'Operating System :: OS Independent',
- 'Programming Language :: Python',
- 'Topic :: Software Development :: Bug Tracking',
- 'Topic :: Software Development :: Version Control',
- ],
-
- packages = find_packages(exclude=['*.tests']),
- package_data = {
- '': ['templates/*'],
- 'trac': ['htdocs/*.*', 'htdocs/README', 'htdocs/js/*.*',
- 'htdocs/js/messages/*.*', 'htdocs/css/*.*',
- 'htdocs/guide/*', 'locale/*/LC_MESSAGES/messages.mo'],
- 'trac.wiki': ['default-pages/*'],
- 'trac.ticket': ['workflows/*.ini'],
- },
-
- test_suite = 'trac.test.suite',
- zip_safe = True,
-
- install_requires = [
- 'setuptools>=0.6b1',
- 'Genshi>=0.6',
- ],
- extras_require = {
- 'Babel': ['Babel>=0.9.5'],
- 'Pygments': ['Pygments>=0.6'],
- 'reST': ['docutils>=0.3'],
- 'SilverCity': ['SilverCity>=0.9.4'],
- 'Textile': ['textile>=2.0'],
- },
-
- entry_points = """
- [console_scripts]
- trac-admin = trac.admin.console:run
- tracd = trac.web.standalone:main
-
- [trac.plugins]
- trac.about = trac.about
- trac.admin.console = trac.admin.console
- trac.admin.web_ui = trac.admin.web_ui
- trac.attachment = trac.attachment
- trac.db.mysql = trac.db.mysql_backend
- trac.db.postgres = trac.db.postgres_backend
- trac.db.sqlite = trac.db.sqlite_backend
- trac.mimeview.patch = trac.mimeview.patch
- trac.mimeview.pygments = trac.mimeview.pygments[Pygments]
- trac.mimeview.rst = trac.mimeview.rst[reST]
- trac.mimeview.silvercity = trac.mimeview.silvercity[SilverCity]
- trac.mimeview.txtl = trac.mimeview.txtl[Textile]
- trac.prefs = trac.prefs.web_ui
- trac.search = trac.search.web_ui
- trac.ticket.admin = trac.ticket.admin
- trac.ticket.query = trac.ticket.query
- trac.ticket.report = trac.ticket.report
- trac.ticket.roadmap = trac.ticket.roadmap
- trac.ticket.web_ui = trac.ticket.web_ui
- trac.timeline = trac.timeline.web_ui
- trac.versioncontrol.admin = trac.versioncontrol.admin
- trac.versioncontrol.svn_authz = trac.versioncontrol.svn_authz
- trac.versioncontrol.svn_fs = trac.versioncontrol.svn_fs
- trac.versioncontrol.svn_prop = trac.versioncontrol.svn_prop
- trac.versioncontrol.web_ui = trac.versioncontrol.web_ui
- trac.web.auth = trac.web.auth
- trac.web.session = trac.web.session
- trac.wiki.admin = trac.wiki.admin
- trac.wiki.interwiki = trac.wiki.interwiki
- trac.wiki.macros = trac.wiki.macros
- trac.wiki.web_ui = trac.wiki.web_ui
- trac.wiki.web_api = trac.wiki.web_api
- tracopt.mimeview.enscript = tracopt.mimeview.enscript
- tracopt.mimeview.php = tracopt.mimeview.php
- tracopt.perm.authz_policy = tracopt.perm.authz_policy
- tracopt.perm.config_perm_provider = tracopt.perm.config_perm_provider
- tracopt.ticket.commit_updater = tracopt.ticket.commit_updater
- tracopt.ticket.deleter = tracopt.ticket.deleter
- """,
-
- **extra
-)
diff --git a/src/distutils2/tests/fixer/__init__.py b/src/distutils2/tests/fixer/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/src/distutils2/tests/fixer/__init__.py
+++ /dev/null
diff --git a/src/distutils2/tests/fixer/fix_idioms.py b/src/distutils2/tests/fixer/fix_idioms.py
deleted file mode 100644
index 9cfac51..0000000
--- a/src/distutils2/tests/fixer/fix_idioms.py
+++ /dev/null
@@ -1,134 +0,0 @@
-"""Adjust some old Python 2 idioms to their modern counterparts.
-
-* Change some type comparisons to isinstance() calls:
- type(x) == T -> isinstance(x, T)
- type(x) is T -> isinstance(x, T)
- type(x) != T -> not isinstance(x, T)
- type(x) is not T -> not isinstance(x, T)
-
-* Change "while 1:" into "while True:".
-
-* Change both
-
- v = list(EXPR)
- v.sort()
- foo(v)
-
-and the more general
-
- v = EXPR
- v.sort()
- foo(v)
-
-into
-
- v = sorted(EXPR)
- foo(v)
-"""
-# Author: Jacques Frechet, Collin Winter
-
-# Local imports
-from lib2to3 import fixer_base
-from lib2to3.fixer_util import Call, Comma, Name, Node, syms
-
-CMP = "(n='!=' | '==' | 'is' | n=comp_op< 'is' 'not' >)"
-TYPE = "power< 'type' trailer< '(' x=any ')' > >"
-
-class FixIdioms(fixer_base.BaseFix):
-
- explicit = False # The user must ask for this fixer
-
- PATTERN = r"""
- isinstance=comparison< %s %s T=any >
- |
- isinstance=comparison< T=any %s %s >
- |
- while_stmt< 'while' while='1' ':' any+ >
- |
- sorted=any<
- any*
- simple_stmt<
- expr_stmt< id1=any '='
- power< list='list' trailer< '(' (not arglist<any+>) any ')' > >
- >
- '\n'
- >
- sort=
- simple_stmt<
- power< id2=any
- trailer< '.' 'sort' > trailer< '(' ')' >
- >
- '\n'
- >
- next=any*
- >
- |
- sorted=any<
- any*
- simple_stmt< expr_stmt< id1=any '=' expr=any > '\n' >
- sort=
- simple_stmt<
- power< id2=any
- trailer< '.' 'sort' > trailer< '(' ')' >
- >
- '\n'
- >
- next=any*
- >
- """ % (TYPE, CMP, CMP, TYPE)
-
- def match(self, node):
- r = super(FixIdioms, self).match(node)
- # If we've matched one of the sort/sorted subpatterns above, we
- # want to reject matches where the initial assignment and the
- # subsequent .sort() call involve different identifiers.
- if r and "sorted" in r:
- if r["id1"] == r["id2"]:
- return r
- return None
- return r
-
- def transform(self, node, results):
- if "isinstance" in results:
- return self.transform_isinstance(node, results)
- elif "while" in results:
- return self.transform_while(node, results)
- elif "sorted" in results:
- return self.transform_sort(node, results)
- else:
- raise RuntimeError("Invalid match")
-
- def transform_isinstance(self, node, results):
- x = results["x"].clone() # The thing inside of type()
- T = results["T"].clone() # The type being compared against
- x.set_prefix("")
- T.set_prefix(" ")
- test = Call(Name("isinstance"), [x, Comma(), T])
- if "n" in results:
- test.set_prefix(" ")
- test = Node(syms.not_test, [Name("not"), test])
- test.set_prefix(node.get_prefix())
- return test
-
- def transform_while(self, node, results):
- one = results["while"]
- one.replace(Name("True", prefix=one.get_prefix()))
-
- def transform_sort(self, node, results):
- sort_stmt = results["sort"]
- next_stmt = results["next"]
- list_call = results.get("list")
- simple_expr = results.get("expr")
-
- if list_call:
- list_call.replace(Name("sorted", prefix=list_call.get_prefix()))
- elif simple_expr:
- new = simple_expr.clone()
- new.set_prefix("")
- simple_expr.replace(Call(Name("sorted"), [new],
- prefix=simple_expr.get_prefix()))
- else:
- raise RuntimeError("should not have reached here")
- sort_stmt.remove()
- if next_stmt:
- next_stmt[0].set_prefix(sort_stmt.get_prefix())
diff --git a/src/distutils2/tests/pypi_server.py b/src/distutils2/tests/pypi_server.py
deleted file mode 100644
index 2db4577..0000000
--- a/src/distutils2/tests/pypi_server.py
+++ /dev/null
@@ -1,428 +0,0 @@
-"""Mock PyPI Server implementation, to use in tests.
-
-This module also provides a simple test case to extend if you need to use
-the PyPIServer all along your test case. Be sure to read the documentation
-before any use.
-
-XXX TODO:
-
-The mock server can handle simple HTTP request (to simulate a simple index) or
-XMLRPC requests, over HTTP. Both does not have the same intergface to deal
-with, and I think it's a pain.
-
-A good idea could be to re-think a bit the way dstributions are handled in the
-mock server. As it should return malformed HTML pages, we need to keep the
-static behavior.
-
-I think of something like that:
-
- >>> server = PyPIMockServer()
- >>> server.startHTTP()
- >>> server.startXMLRPC()
-
-Then, the server must have only one port to rely on, eg.
-
- >>> server.fulladress()
- "http://ip:port/"
-
-It could be simple to have one HTTP server, relaying the requests to the two
-implementations (static HTTP and XMLRPC over HTTP).
-"""
-
-import Queue
-import SocketServer
-import os.path
-import select
-import socket
-import threading
-
-from BaseHTTPServer import HTTPServer
-from SimpleHTTPServer import SimpleHTTPRequestHandler
-from SimpleXMLRPCServer import SimpleXMLRPCServer
-
-from distutils2.tests.support import unittest
-
-PYPI_DEFAULT_STATIC_PATH = os.path.dirname(os.path.abspath(__file__)) + "/pypiserver"
-
-def use_xmlrpc_server(*server_args, **server_kwargs):
- server_kwargs['serve_xmlrpc'] = True
- return use_pypi_server(*server_args, **server_kwargs)
-
-def use_http_server(*server_args, **server_kwargs):
- server_kwargs['serve_xmlrpc'] = False
- return use_pypi_server(*server_args, **server_kwargs)
-
-def use_pypi_server(*server_args, **server_kwargs):
- """Decorator to make use of the PyPIServer for test methods,
- just when needed, and not for the entire duration of the testcase.
- """
- def wrapper(func):
- def wrapped(*args, **kwargs):
- server = PyPIServer(*server_args, **server_kwargs)
- server.start()
- try:
- func(server=server, *args, **kwargs)
- finally:
- server.stop()
- return wrapped
- return wrapper
-
-class PyPIServerTestCase(unittest.TestCase):
-
- def setUp(self):
- super(PyPIServerTestCase, self).setUp()
- self.pypi = PyPIServer()
- self.pypi.start()
-
- def tearDown(self):
- super(PyPIServerTestCase, self).tearDown()
- self.pypi.stop()
-
-class PyPIServer(threading.Thread):
- """PyPI Mocked server.
- Provides a mocked version of the PyPI API's, to ease tests.
-
- Support serving static content and serving previously given text.
- """
-
- def __init__(self, test_static_path=None,
- static_filesystem_paths=["default"],
- static_uri_paths=["simple"], serve_xmlrpc=False) :
- """Initialize the server.
-
- Default behavior is to start the HTTP server. You can either start the
- xmlrpc server by setting xmlrpc to True. Caution: Only one server will
- be started.
-
- static_uri_paths and static_base_path are parameters used to provides
- respectively the http_paths to serve statically, and where to find the
- matching files on the filesystem.
- """
- # we want to launch the server in a new dedicated thread, to not freeze
- # tests.
- threading.Thread.__init__(self)
- self._run = True
- self._serve_xmlrpc = serve_xmlrpc
-
- #TODO allow to serve XMLRPC and HTTP static files at the same time.
- if not self._serve_xmlrpc:
- self.server = HTTPServer(('', 0), PyPIRequestHandler)
- self.server.RequestHandlerClass.pypi_server = self
-
- self.request_queue = Queue.Queue()
- self._requests = []
- self.default_response_status = 200
- self.default_response_headers = [('Content-type', 'text/plain')]
- self.default_response_data = "hello"
-
- # initialize static paths / filesystems
- self.static_uri_paths = static_uri_paths
- if test_static_path is not None:
- static_filesystem_paths.append(test_static_path)
- self.static_filesystem_paths = [PYPI_DEFAULT_STATIC_PATH + "/" + path
- for path in static_filesystem_paths]
- else:
- # XMLRPC server
- self.server = PyPIXMLRPCServer(('', 0))
- self.xmlrpc = XMLRPCMockIndex()
- # register the xmlrpc methods
- self.server.register_introspection_functions()
- self.server.register_instance(self.xmlrpc)
-
- self.address = (self.server.server_name, self.server.server_port)
- # to not have unwanted outputs.
- self.server.RequestHandlerClass.log_request = lambda *_: None
-
- def run(self):
- # loop because we can't stop it otherwise, for python < 2.6
- while self._run:
- r, w, e = select.select([self.server], [], [], 0.5)
- if r:
- self.server.handle_request()
-
- def stop(self):
- """self shutdown is not supported for python < 2.6"""
- self._run = False
-
- def get_next_response(self):
- return (self.default_response_status,
- self.default_response_headers,
- self.default_response_data)
-
- @property
- def requests(self):
- """Use this property to get all requests that have been made
- to the server
- """
- while True:
- try:
- self._requests.append(self.request_queue.get_nowait())
- except Queue.Empty:
- break
- return self._requests
-
- @property
- def full_address(self):
- return "http://%s:%s" % self.address
-
-
-class PyPIRequestHandler(SimpleHTTPRequestHandler):
- # we need to access the pypi server while serving the content
- pypi_server = None
-
- def do_POST(self):
- return self.serve_request()
- def do_GET(self):
- return self.serve_request()
- def do_DELETE(self):
- return self.serve_request()
- def do_PUT(self):
- return self.serve_request()
-
- def serve_request(self):
- """Serve the content.
-
- Also record the requests to be accessed later. If trying to access an
- url matching a static uri, serve static content, otherwise serve
- what is provided by the `get_next_response` method.
- """
- # record the request. Read the input only on PUT or POST requests
- if self.command in ("PUT", "POST"):
- if 'content-length' in self.headers.dict:
- request_data = self.rfile.read(
- int(self.headers['content-length']))
- else:
- request_data = self.rfile.read()
- elif self.command in ("GET", "DELETE"):
- request_data = ''
-
- self.pypi_server.request_queue.put((self, request_data))
-
- # serve the content from local disc if we request an URL beginning
- # by a pattern defined in `static_paths`
- url_parts = self.path.split("/")
- if (len(url_parts) > 1 and
- url_parts[1] in self.pypi_server.static_uri_paths):
- data = None
- # always take the last first.
- fs_paths = []
- fs_paths.extend(self.pypi_server.static_filesystem_paths)
- fs_paths.reverse()
- relative_path = self.path
- for fs_path in fs_paths:
- try:
- if self.path.endswith("/"):
- relative_path += "index.html"
- file = open(fs_path + relative_path)
- data = file.read()
- if relative_path.endswith('.tar.gz'):
- headers=[('Content-type', 'application/x-gtar')]
- else:
- headers=[('Content-type', 'text/html')]
- self.make_response(data, headers=headers)
- except IOError:
- pass
-
- if data is None:
- self.make_response("Not found", 404)
-
- # otherwise serve the content from get_next_response
- else:
- # send back a response
- status, headers, data = self.pypi_server.get_next_response()
- self.make_response(data, status, headers)
-
- def make_response(self, data, status=200,
- headers=[('Content-type', 'text/html')]):
- """Send the response to the HTTP client"""
- if not isinstance(status, int):
- try:
- status = int(status)
- except ValueError:
- # we probably got something like YYY Codename.
- # Just get the first 3 digits
- status = int(status[:3])
-
- self.send_response(status)
- for header, value in headers:
- self.send_header(header, value)
- self.end_headers()
- self.wfile.write(data)
-
-class PyPIXMLRPCServer(SimpleXMLRPCServer):
- def server_bind(self):
- """Override server_bind to store the server name."""
- SocketServer.TCPServer.server_bind(self)
- host, port = self.socket.getsockname()[:2]
- self.server_name = socket.getfqdn(host)
- self.server_port = port
-
-class MockDist(object):
- """Fake distribution, used in the Mock PyPI Server"""
- def __init__(self, name, version="1.0", hidden=False, url="http://url/",
- type="sdist", filename="", size=10000,
- digest="123456", downloads=7, has_sig=False,
- python_version="source", comment="comment",
- author="John Doe", author_email="john@doe.name",
- maintainer="Main Tayner", maintainer_email="maintainer_mail",
- project_url="http://project_url/", homepage="http://homepage/",
- keywords="", platform="UNKNOWN", classifiers=[], licence="",
- description="Description", summary="Summary", stable_version="",
- ordering="", documentation_id="", code_kwalitee_id="",
- installability_id="", obsoletes=[], obsoletes_dist=[],
- provides=[], provides_dist=[], requires=[], requires_dist=[],
- requires_external=[], requires_python=""):
-
- # basic fields
- self.name = name
- self.version = version
- self.hidden = hidden
-
- # URL infos
- self.url = url
- self.digest = digest
- self.downloads = downloads
- self.has_sig = has_sig
- self.python_version = python_version
- self.comment = comment
- self.type = type
-
- # metadata
- self.author = author
- self.author_email = author_email
- self.maintainer = maintainer
- self.maintainer_email = maintainer_email
- self.project_url = project_url
- self.homepage = homepage
- self.keywords = keywords
- self.platform = platform
- self.classifiers = classifiers
- self.licence = licence
- self.description = description
- self.summary = summary
- self.stable_version = stable_version
- self.ordering = ordering
- self.cheesecake_documentation_id = documentation_id
- self.cheesecake_code_kwalitee_id = code_kwalitee_id
- self.cheesecake_installability_id = installability_id
-
- self.obsoletes = obsoletes
- self.obsoletes_dist = obsoletes_dist
- self.provides = provides
- self.provides_dist = provides_dist
- self.requires = requires
- self.requires_dist = requires_dist
- self.requires_external = requires_external
- self.requires_python = requires_python
-
- def url_infos(self):
- return {
- 'url': self.url,
- 'packagetype': self.type,
- 'filename': 'filename.tar.gz',
- 'size': '6000',
- 'md5_digest': self.digest,
- 'downloads': self.downloads,
- 'has_sig': self.has_sig,
- 'python_version': self.python_version,
- 'comment_text': self.comment,
- }
-
- def metadata(self):
- return {
- 'maintainer': self.maintainer,
- 'project_url': [self.project_url],
- 'maintainer_email': self.maintainer_email,
- 'cheesecake_code_kwalitee_id': self.cheesecake_code_kwalitee_id,
- 'keywords': self.keywords,
- 'obsoletes_dist': self.obsoletes_dist,
- 'requires_external': self.requires_external,
- 'author': self.author,
- 'author_email': self.author_email,
- 'download_url': self.url,
- 'platform': self.platform,
- 'version': self.version,
- 'obsoletes': self.obsoletes,
- 'provides': self.provides,
- 'cheesecake_documentation_id': self.cheesecake_documentation_id,
- '_pypi_hidden': self.hidden,
- 'description': self.description,
- '_pypi_ordering': 19,
- 'requires_dist': self.requires_dist,
- 'requires_python': self.requires_python,
- 'classifiers': [],
- 'name': self.name,
- 'licence': self.licence,
- 'summary': self.summary,
- 'home_page': self.homepage,
- 'stable_version': self.stable_version,
- 'provides_dist': self.provides_dist or "%s (%s)" % (self.name,
- self.version),
- 'requires': self.requires,
- 'cheesecake_installability_id': self.cheesecake_installability_id,
- }
-
- def search_result(self):
- return {
- '_pypi_ordering': 0,
- 'version': self.version,
- 'name': self.name,
- 'summary': self.summary,
- }
-
-class XMLRPCMockIndex(object):
- """Mock XMLRPC server"""
-
- def __init__(self, dists=[]):
- self._dists = dists
-
- def add_distributions(self, dists):
- for dist in dists:
- self._dists.append(MockDist(**dist))
-
- def set_distributions(self, dists):
- self._dists = []
- self.add_distributions(dists)
-
- def set_search_result(self, result):
- """set a predefined search result"""
- self._search_result = result
-
- def _get_search_results(self):
- results = []
- for name in self._search_result:
- found_dist = [d for d in self._dists if d.name == name]
- if found_dist:
- results.append(found_dist[0])
- else:
- dist = MockDist(name)
- results.append(dist)
- self._dists.append(dist)
- return [r.search_result() for r in results]
-
- def list_package(self):
- return [d.name for d in self._dists]
-
- def package_releases(self, package_name, show_hidden=False):
- if show_hidden:
- # return all
- return [d.version for d in self._dists if d.name == package_name]
- else:
- # return only un-hidden
- return [d.version for d in self._dists if d.name == package_name
- and not d.hidden]
-
- def release_urls(self, package_name, version):
- return [d.url_infos() for d in self._dists
- if d.name == package_name and d.version == version]
-
- def release_data(self, package_name, version):
- release = [d for d in self._dists
- if d.name == package_name and d.version == version]
- if release:
- return release[0].metadata()
- else:
- return {}
-
- def search(self, spec, operator="and"):
- return self._get_search_results()
diff --git a/src/distutils2/tests/pypiserver/downloads_with_md5/simple/badmd5/badmd5-0.1.tar.gz b/src/distutils2/tests/pypiserver/downloads_with_md5/simple/badmd5/badmd5-0.1.tar.gz
deleted file mode 100644
index e69de29..0000000
--- a/src/distutils2/tests/pypiserver/downloads_with_md5/simple/badmd5/badmd5-0.1.tar.gz
+++ /dev/null
diff --git a/src/distutils2/tests/pypiserver/downloads_with_md5/simple/badmd5/index.html b/src/distutils2/tests/pypiserver/downloads_with_md5/simple/badmd5/index.html
deleted file mode 100644
index b89f1bd..0000000
--- a/src/distutils2/tests/pypiserver/downloads_with_md5/simple/badmd5/index.html
+++ /dev/null
@@ -1,3 +0,0 @@
-<html><body>
-<a href="badmd5-0.1.tar.gz#md5=3e3d86693d6564c807272b11b3069dfe" rel="download">badmd5-0.1.tar.gz</a><br/>
-</body></html>
diff --git a/src/distutils2/tests/pypiserver/downloads_with_md5/simple/foobar/foobar-0.1.tar.gz b/src/distutils2/tests/pypiserver/downloads_with_md5/simple/foobar/foobar-0.1.tar.gz
deleted file mode 100644
index e69de29..0000000
--- a/src/distutils2/tests/pypiserver/downloads_with_md5/simple/foobar/foobar-0.1.tar.gz
+++ /dev/null
diff --git a/src/distutils2/tests/pypiserver/downloads_with_md5/simple/foobar/index.html b/src/distutils2/tests/pypiserver/downloads_with_md5/simple/foobar/index.html
deleted file mode 100644
index add0b85..0000000
--- a/src/distutils2/tests/pypiserver/downloads_with_md5/simple/foobar/index.html
+++ /dev/null
@@ -1,3 +0,0 @@
-<html><body>
-<a href="foobar-0.1.tar.gz#md5=d41d8cd98f00b204e9800998ecf8427e" rel="download">foobar-0.1.tar.gz</a><br/>
-</body></html>
diff --git a/src/distutils2/tests/pypiserver/downloads_with_md5/simple/index.html b/src/distutils2/tests/pypiserver/downloads_with_md5/simple/index.html
deleted file mode 100644
index 9baee04..0000000
--- a/src/distutils2/tests/pypiserver/downloads_with_md5/simple/index.html
+++ /dev/null
@@ -1,2 +0,0 @@
-<a href="foobar/">foobar/</a>
-<a href="badmd5/">badmd5/</a>
diff --git a/src/distutils2/tests/pypiserver/foo_bar_baz/simple/bar/index.html b/src/distutils2/tests/pypiserver/foo_bar_baz/simple/bar/index.html
deleted file mode 100644
index c3d42c5..0000000
--- a/src/distutils2/tests/pypiserver/foo_bar_baz/simple/bar/index.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<html><head><title>Links for bar</title></head><body><h1>Links for bar</h1>
-<a rel="download" href="../../packages/source/F/bar/bar-1.0.tar.gz">bar-1.0.tar.gz</a><br/>
-<a rel="download" href="../../packages/source/F/bar/bar-1.0.1.tar.gz">bar-1.0.1.tar.gz</a><br/>
-<a rel="download" href="../../packages/source/F/bar/bar-2.0.tar.gz">bar-2.0.tar.gz</a><br/>
-<a rel="download" href="../../packages/source/F/bar/bar-2.0.1.tar.gz">bar-2.0.1.tar.gz</a><br/>
-</body></html>
diff --git a/src/distutils2/tests/pypiserver/foo_bar_baz/simple/baz/index.html b/src/distutils2/tests/pypiserver/foo_bar_baz/simple/baz/index.html
deleted file mode 100644
index 4f34312..0000000
--- a/src/distutils2/tests/pypiserver/foo_bar_baz/simple/baz/index.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<html><head><title>Links for baz</title></head><body><h1>Links for baz</h1>
-<a rel="download" href="../../packages/source/F/baz/baz-1.0.tar.gz">baz-1.0.tar.gz</a><br/>
-<a rel="download" href="../../packages/source/F/baz/baz-1.0.1.tar.gz">baz-1.0.1.tar.gz</a><br/>
-<a rel="download" href="../../packages/source/F/baz/baz-2.0.tar.gz">baz-2.0.tar.gz</a><br/>
-<a rel="download" href="../../packages/source/F/baz/baz-2.0.1.tar.gz">baz-2.0.1.tar.gz</a><br/>
-</body></html>
diff --git a/src/distutils2/tests/pypiserver/foo_bar_baz/simple/foo/index.html b/src/distutils2/tests/pypiserver/foo_bar_baz/simple/foo/index.html
deleted file mode 100644
index 0565e11..0000000
--- a/src/distutils2/tests/pypiserver/foo_bar_baz/simple/foo/index.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<html><head><title>Links for foo</title></head><body><h1>Links for foo</h1>
-<a rel="download" href="../../packages/source/F/foo/foo-1.0.tar.gz">foo-1.0.tar.gz</a><br/>
-<a rel="download" href="../../packages/source/F/foo/foo-1.0.1.tar.gz">foo-1.0.1.tar.gz</a><br/>
-<a rel="download" href="../../packages/source/F/foo/foo-2.0.tar.gz">foo-2.0.tar.gz</a><br/>
-<a rel="download" href="../../packages/source/F/foo/foo-2.0.1.tar.gz">foo-2.0.1.tar.gz</a><br/>
-</body></html>
diff --git a/src/distutils2/tests/pypiserver/foo_bar_baz/simple/index.html b/src/distutils2/tests/pypiserver/foo_bar_baz/simple/index.html
deleted file mode 100644
index a70cfd3..0000000
--- a/src/distutils2/tests/pypiserver/foo_bar_baz/simple/index.html
+++ /dev/null
@@ -1,3 +0,0 @@
-<a href="foo/">foo/</a>
-<a href="bar/">bar/</a>
-<a href="baz/">baz/</a>
diff --git a/src/distutils2/tests/pypiserver/project_list/simple/index.html b/src/distutils2/tests/pypiserver/project_list/simple/index.html
deleted file mode 100644
index b36d728..0000000
--- a/src/distutils2/tests/pypiserver/project_list/simple/index.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<a class="test" href="yeah">FooBar-bar</a>
-<a class="test" href="yeah">Foobar-baz</a>
-<a class="test" href="yeah">Baz-FooBar</a>
-<a class="test" href="yeah">Baz</a>
-<a class="test" href="yeah">Foo</a>
diff --git a/src/distutils2/tests/pypiserver/test_found_links/simple/foobar/index.html b/src/distutils2/tests/pypiserver/test_found_links/simple/foobar/index.html
deleted file mode 100644
index a282a4e..0000000
--- a/src/distutils2/tests/pypiserver/test_found_links/simple/foobar/index.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<html><head><title>Links for Foobar</title></head><body><h1>Links for Foobar</h1>
-<a rel="download" href="../../packages/source/F/Foobar/Foobar-1.0.tar.gz#md5=98fa833fdabcdd78d00245aead66c174">Foobar-1.0.tar.gz</a><br/>
-<a rel="download" href="../../packages/source/F/Foobar/Foobar-1.0.1.tar.gz#md5=2351efb20f6b7b5d9ce80fa4cb1bd9ca">Foobar-1.0.1.tar.gz</a><br/>
-<a rel="download" href="../../packages/source/F/Foobar/Foobar-2.0.tar.gz#md5=98fa833fdabcdd78d00245aead66c274">Foobar-2.0.tar.gz</a><br/>
-<a rel="download" href="../../packages/source/F/Foobar/Foobar-2.0.1.tar.gz#md5=2352efb20f6b7b5d9ce80fa4cb2bd9ca">Foobar-2.0.1.tar.gz</a><br/>
-</body></html>
diff --git a/src/distutils2/tests/pypiserver/test_found_links/simple/index.html b/src/distutils2/tests/pypiserver/test_found_links/simple/index.html
deleted file mode 100644
index a1a7bb7..0000000
--- a/src/distutils2/tests/pypiserver/test_found_links/simple/index.html
+++ /dev/null
@@ -1 +0,0 @@
-<a href="foobar/">foobar/</a>
diff --git a/src/distutils2/tests/pypiserver/test_pypi_server/external/index.html b/src/distutils2/tests/pypiserver/test_pypi_server/external/index.html
deleted file mode 100644
index 265ee0a..0000000
--- a/src/distutils2/tests/pypiserver/test_pypi_server/external/index.html
+++ /dev/null
@@ -1 +0,0 @@
-index.html from external server
diff --git a/src/distutils2/tests/pypiserver/test_pypi_server/simple/index.html b/src/distutils2/tests/pypiserver/test_pypi_server/simple/index.html
deleted file mode 100644
index 6f97667..0000000
--- a/src/distutils2/tests/pypiserver/test_pypi_server/simple/index.html
+++ /dev/null
@@ -1 +0,0 @@
-Yeah
diff --git a/src/distutils2/tests/pypiserver/with_externals/external/external.html b/src/distutils2/tests/pypiserver/with_externals/external/external.html
deleted file mode 100644
index 92e4702..0000000
--- a/src/distutils2/tests/pypiserver/with_externals/external/external.html
+++ /dev/null
@@ -1,3 +0,0 @@
-<html><body>
-<a href="/foobar-0.1.tar.gz#md5=1__bad_md5___">bad old link</a>
-</body></html>
diff --git a/src/distutils2/tests/pypiserver/with_externals/simple/foobar/index.html b/src/distutils2/tests/pypiserver/with_externals/simple/foobar/index.html
deleted file mode 100644
index b100a26..0000000
--- a/src/distutils2/tests/pypiserver/with_externals/simple/foobar/index.html
+++ /dev/null
@@ -1,4 +0,0 @@
-<html><body>
-<a rel ="download" href="/foobar-0.1.tar.gz#md5=12345678901234567">foobar-0.1.tar.gz</a><br/>
-<a href="../../external/external.html" rel="homepage">external homepage</a><br/>
-</body></html>
diff --git a/src/distutils2/tests/pypiserver/with_externals/simple/index.html b/src/distutils2/tests/pypiserver/with_externals/simple/index.html
deleted file mode 100644
index a1a7bb7..0000000
--- a/src/distutils2/tests/pypiserver/with_externals/simple/index.html
+++ /dev/null
@@ -1 +0,0 @@
-<a href="foobar/">foobar/</a>
diff --git a/src/distutils2/tests/pypiserver/with_norel_links/external/homepage.html b/src/distutils2/tests/pypiserver/with_norel_links/external/homepage.html
deleted file mode 100644
index 1cc0c32..0000000
--- a/src/distutils2/tests/pypiserver/with_norel_links/external/homepage.html
+++ /dev/null
@@ -1,7 +0,0 @@
-<html>
-<body>
-<p>a rel=homepage HTML page</p>
-<a href="/foobar-2.0.tar.gz">foobar 2.0</a>
-</body>
-</html>
-
diff --git a/src/distutils2/tests/pypiserver/with_norel_links/external/nonrel.html b/src/distutils2/tests/pypiserver/with_norel_links/external/nonrel.html
deleted file mode 100644
index f6ace22..0000000
--- a/src/distutils2/tests/pypiserver/with_norel_links/external/nonrel.html
+++ /dev/null
@@ -1 +0,0 @@
-A page linked without rel="download" or rel="homepage" link.
diff --git a/src/distutils2/tests/pypiserver/with_norel_links/simple/foobar/index.html b/src/distutils2/tests/pypiserver/with_norel_links/simple/foobar/index.html
deleted file mode 100644
index 171df93..0000000
--- a/src/distutils2/tests/pypiserver/with_norel_links/simple/foobar/index.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<html><body>
-<a rel="download" href="/foobar-0.1.tar.gz" rel="download">foobar-0.1.tar.gz</a><br/>
-<a href="../../external/homepage.html" rel="homepage">external homepage</a><br/>
-<a href="../../external/nonrel.html">unrelated link</a><br/>
-<a href="/unrelated-0.2.tar.gz">unrelated download</a></br/>
-</body></html>
diff --git a/src/distutils2/tests/pypiserver/with_norel_links/simple/index.html b/src/distutils2/tests/pypiserver/with_norel_links/simple/index.html
deleted file mode 100644
index a1a7bb7..0000000
--- a/src/distutils2/tests/pypiserver/with_norel_links/simple/index.html
+++ /dev/null
@@ -1 +0,0 @@
-<a href="foobar/">foobar/</a>
diff --git a/src/distutils2/tests/pypiserver/with_real_externals/simple/foobar/index.html b/src/distutils2/tests/pypiserver/with_real_externals/simple/foobar/index.html
deleted file mode 100644
index b2885ae..0000000
--- a/src/distutils2/tests/pypiserver/with_real_externals/simple/foobar/index.html
+++ /dev/null
@@ -1,4 +0,0 @@
-<html><body>
-<a rel="download" href="/foobar-0.1.tar.gz#md5=0_correct_md5">foobar-0.1.tar.gz</a><br/>
-<a href="http://a-really-external-website/external/external.html" rel="homepage">external homepage</a><br/>
-</body></html>
diff --git a/src/distutils2/tests/pypiserver/with_real_externals/simple/index.html b/src/distutils2/tests/pypiserver/with_real_externals/simple/index.html
deleted file mode 100644
index a1a7bb7..0000000
--- a/src/distutils2/tests/pypiserver/with_real_externals/simple/index.html
+++ /dev/null
@@ -1 +0,0 @@
-<a href="foobar/">foobar/</a>
diff --git a/src/distutils2/tests/support.py b/src/distutils2/tests/support.py
deleted file mode 100644
index a365548..0000000
--- a/src/distutils2/tests/support.py
+++ /dev/null
@@ -1,235 +0,0 @@
-"""Support code for distutils2 test cases.
-
-Always import unittest from this module, it will be the right version
-(standard library unittest for 3.2 and higher, third-party unittest2
-release for older versions).
-
-Four helper classes are provided: LoggingCatcher, TempdirManager,
-EnvironGuard and WarningsCatcher. They are written to be used as mixins,
-e.g. ::
-
- from distutils2.tests.support import unittest
- from distutils2.tests.support import LoggingCatcher
-
- class SomeTestCase(LoggingCatcher, unittest.TestCase):
-
-If you need to define a setUp method on your test class, you have to
-call the mixin class' setUp method or it won't work (same thing for
-tearDown):
-
- def setUp(self):
- super(SomeTestCase, self).setUp()
- ... # other setup code
-
-Read each class' docstring to see its purpose and usage.
-
-Also provided is a DummyCommand class, useful to mock commands in the
-tests of another command that needs them (see docstring).
-"""
-
-import os
-import sys
-import shutil
-import tempfile
-import warnings
-from copy import deepcopy
-
-from distutils2 import log
-from distutils2.dist import Distribution
-from distutils2.log import DEBUG, INFO, WARN, ERROR, FATAL
-
-if sys.version_info >= (3, 2):
- # improved unittest package from 3.2's standard library
- import unittest
-else:
- # external release of same package for older versions
- import unittest2 as unittest
-
-__all__ = ['LoggingCatcher', 'WarningsCatcher', 'TempdirManager',
- 'EnvironGuard', 'DummyCommand', 'unittest']
-
-
-class LoggingCatcher(object):
- """TestCase-compatible mixin to catch logging calls.
-
- Every log message that goes through distutils2.log will get appended to
- self.logs instead of being printed. You can check that your code logs
- warnings and errors as documented by inspecting that list; helper methods
- get_logs and clear_logs are also provided.
- """
-
- def setUp(self):
- super(LoggingCatcher, self).setUp()
- self.threshold = log.set_threshold(FATAL)
- # when log is replaced by logging we won't need
- # such monkey-patching anymore
- self._old_log = log.Log._log
- log.Log._log = self._log
- self.logs = []
-
- def tearDown(self):
- log.set_threshold(self.threshold)
- log.Log._log = self._old_log
- super(LoggingCatcher, self).tearDown()
-
- def _log(self, level, msg, args):
- if level not in (DEBUG, INFO, WARN, ERROR, FATAL):
- raise ValueError('%s wrong log level' % level)
- self.logs.append((level, msg, args))
-
- def get_logs(self, *levels):
- """Return a list of caught messages with level in `levels`.
-
- Example: self.get_logs(log.WARN, log.DEBUG) -> list
- """
- def _format(msg, args):
- if len(args) == 0:
- return msg
- return msg % args
- return [_format(msg, args) for level, msg, args
- in self.logs if level in levels]
-
- def clear_logs(self):
- """Empty the internal list of caught messages."""
- del self.logs[:]
-
-
-class LoggingSilencer(object):
- "Class that raises an exception to make sure the renaming is noticed."
-
- def __init__(self, *args):
- raise DeprecationWarning("LoggingSilencer renamed to LoggingCatcher")
-
-
-class WarningsCatcher(object):
-
- def setUp(self):
- self._orig_showwarning = warnings.showwarning
- warnings.showwarning = self._record_showwarning
- self.warnings = []
-
- def _record_showwarning(self, message, category, filename, lineno,
- file=None, line=None):
- self.warnings.append({"message": message, "category": category,
- "filename": filename, "lineno": lineno,
- "file": file, "line": line})
-
- def tearDown(self):
- warnings.showwarning = self._orig_showwarning
-
-
-class TempdirManager(object):
- """TestCase-compatible mixin to create temporary directories and files.
-
- Directories and files created in a test_* method will be removed after it
- has run.
- """
-
- def setUp(self):
- super(TempdirManager, self).setUp()
- self._basetempdir = tempfile.mkdtemp()
-
- def tearDown(self):
- super(TempdirManager, self).tearDown()
- shutil.rmtree(self._basetempdir, os.name in ('nt', 'cygwin'))
-
- def mktempfile(self):
- """Create a read-write temporary file and return it."""
- fd, fn = tempfile.mkstemp(dir=self._basetempdir)
- os.close(fd)
- return open(fn, 'w+')
-
- def mkdtemp(self):
- """Create a temporary directory and return its path."""
- d = tempfile.mkdtemp(dir=self._basetempdir)
- return d
-
- def write_file(self, path, content='xxx'):
- """Write a file at the given path.
-
- path can be a string, a tuple or a list; if it's a tuple or list,
- os.path.join will be used to produce a path.
- """
- if isinstance(path, (list, tuple)):
- path = os.path.join(*path)
- f = open(path, 'w')
- try:
- f.write(content)
- finally:
- f.close()
-
- def create_dist(self, pkg_name='foo', **kw):
- """Create a stub distribution object and files.
-
- This function creates a Distribution instance (use keyword arguments
- to customize it) and a temporary directory with a project structure
- (currently an empty directory).
-
- It returns the path to the directory and the Distribution instance.
- You can use TempdirManager.write_file to write any file in that
- directory, e.g. setup scripts or Python modules.
- """
- # Late import so that third parties can import support without
- # loading a ton of distutils2 modules in memory.
- from distutils2.dist import Distribution
- tmp_dir = self.mkdtemp()
- pkg_dir = os.path.join(tmp_dir, pkg_name)
- os.mkdir(pkg_dir)
- dist = Distribution(attrs=kw)
- return pkg_dir, dist
-
-
-class EnvironGuard(object):
- """TestCase-compatible mixin to save and restore the environment."""
-
- def setUp(self):
- super(EnvironGuard, self).setUp()
- self.old_environ = deepcopy(os.environ)
-
- def tearDown(self):
- for key, value in self.old_environ.iteritems():
- if os.environ.get(key) != value:
- os.environ[key] = value
-
- for key in os.environ.keys():
- if key not in self.old_environ:
- del os.environ[key]
-
- super(EnvironGuard, self).tearDown()
-
-
-class DummyCommand(object):
- """Class to store options for retrieval via set_undefined_options().
-
- Useful for mocking one dependency command in the tests for another
- command, see e.g. the dummy build command in test_build_scripts.
- """
-
- def __init__(self, **kwargs):
- for kw, val in kwargs.iteritems():
- setattr(self, kw, val)
-
- def ensure_finalized(self):
- pass
-
-
-class TestDistribution(Distribution):
- """Distribution subclasses that avoids the default search for
- configuration files.
-
- The ._config_files attribute must be set before
- .parse_config_files() is called.
- """
-
- def find_config_files(self):
- return self._config_files
-
-
-def create_distribution(configfiles=()):
- """Prepares a distribution with given config files parsed."""
- d = TestDistribution()
- d._config_files = configfiles
- d.parse_config_files()
- d.parse_command_line()
- return d
-
diff --git a/src/distutils2/tests/test_Mixin2to3.py b/src/distutils2/tests/test_Mixin2to3.py
deleted file mode 100644
index 186d128..0000000
--- a/src/distutils2/tests/test_Mixin2to3.py
+++ /dev/null
@@ -1,73 +0,0 @@
-"""Tests for distutils.command.build_py."""
-import sys
-import logging
-
-import distutils2
-from distutils2.tests import support
-from distutils2.tests.support import unittest
-from distutils2.compat import Mixin2to3
-
-
-class Mixin2to3TestCase(support.TempdirManager, unittest.TestCase):
-
- @unittest.skipIf(sys.version < '2.6', 'requires Python 2.6 or higher')
- def test_convert_code_only(self):
- # used to check if code gets converted properly.
- code_content = "print 'test'\n"
- code_handle = self.mktempfile()
- code_name = code_handle.name
-
- code_handle.write(code_content)
- code_handle.flush()
-
- mixin2to3 = Mixin2to3()
- mixin2to3._run_2to3([code_name])
- converted_code_content = "print('test')\n"
- new_code_content = "".join(open(code_name).readlines())
-
- self.assertEquals(new_code_content, converted_code_content)
-
- @unittest.skipIf(sys.version < '2.6', 'requires Python 2.6 or higher')
- def test_doctests_only(self):
- # used to check if doctests gets converted properly.
- doctest_content = '"""\n>>> print test\ntest\n"""\nprint test\n\n'
- doctest_handle = self.mktempfile()
- doctest_name = doctest_handle.name
-
- doctest_handle.write(doctest_content)
- doctest_handle.flush()
-
- mixin2to3 = Mixin2to3()
- mixin2to3._run_2to3([doctest_name])
-
- converted_doctest_content = ['"""', '>>> print(test)', 'test', '"""',
- 'print(test)', '', '', '']
- converted_doctest_content = '\n'.join(converted_doctest_content)
- new_doctest_content = "".join(open(doctest_name).readlines())
-
- self.assertEquals(new_doctest_content, converted_doctest_content)
-
- @unittest.skipIf(sys.version < '2.6', 'requires Python 2.6 or higher')
- def test_additional_fixers(self):
- # used to check if use_2to3_fixers works
- from distutils2.tests import fixer
- code_content = "type(x) is T"
- code_handle = self.mktempfile()
- code_name = code_handle.name
-
- code_handle.write(code_content)
- code_handle.flush()
-
- mixin2to3 = Mixin2to3()
-
- mixin2to3._run_2to3(files=[code_name],
- fixers=['distutils2.tests.fixer'])
- converted_code_content = "isinstance(x, T)"
- new_code_content = "".join(open(code_name).readlines())
- self.assertEquals(new_code_content, converted_code_content)
-
-def test_suite():
- return unittest.makeSuite(Mixin2to3TestCase)
-
-if __name__ == "__main__":
- unittest.main(defaultTest="test_suite")
diff --git a/src/distutils2/tests/test_bdist.py b/src/distutils2/tests/test_bdist.py
deleted file mode 100644
index 2be01e1..0000000
--- a/src/distutils2/tests/test_bdist.py
+++ /dev/null
@@ -1,41 +0,0 @@
-"""Tests for distutils.command.bdist."""
-import sys
-import os
-
-from distutils2.tests import run_unittest
-
-from distutils2.core import Distribution
-from distutils2.command.bdist import bdist
-from distutils2.tests import support
-from distutils2.tests.support import unittest
-from distutils2.util import find_executable
-from distutils2.errors import DistutilsExecError
-
-class BuildTestCase(support.TempdirManager,
- unittest.TestCase):
-
- def test_formats(self):
-
- # let's create a command and make sure
- # we can fix the format
- pkg_pth, dist = self.create_dist()
- cmd = bdist(dist)
- cmd.formats = ['msi']
- cmd.ensure_finalized()
- self.assertEqual(cmd.formats, ['msi'])
-
- # what format bdist offers ?
- # XXX an explicit list in bdist is
- # not the best way to bdist_* commands
- # we should add a registry
- formats = ['zip', 'gztar', 'bztar', 'ztar', 'tar', 'wininst', 'msi']
- formats.sort()
- found = cmd.format_command.keys()
- found.sort()
- self.assertEqual(found, formats)
-
-def test_suite():
- return unittest.makeSuite(BuildTestCase)
-
-if __name__ == '__main__':
- run_unittest(test_suite())
diff --git a/src/distutils2/tests/test_bdist_dumb.py b/src/distutils2/tests/test_bdist_dumb.py
deleted file mode 100644
index a33210e..0000000
--- a/src/distutils2/tests/test_bdist_dumb.py
+++ /dev/null
@@ -1,105 +0,0 @@
-"""Tests for distutils.command.bdist_dumb."""
-
-import sys
-import os
-
-# zlib is not used here, but if it's not available
-# test_simple_built will fail
-try:
- import zlib
-except ImportError:
- zlib = None
-
-from distutils2.tests import run_unittest
-from distutils2.tests.support import unittest
-
-from distutils2.core import Distribution
-from distutils2.command.bdist_dumb import bdist_dumb
-from distutils2.tests import support
-
-SETUP_PY = """\
-from distutils.core import setup
-import foo
-
-setup(name='foo', version='0.1', py_modules=['foo'],
- url='xxx', author='xxx', author_email='xxx')
-
-"""
-
-class BuildDumbTestCase(support.TempdirManager,
- support.LoggingCatcher,
- support.EnvironGuard,
- unittest.TestCase):
-
- def setUp(self):
- super(BuildDumbTestCase, self).setUp()
- self.old_location = os.getcwd()
- self.old_sys_argv = sys.argv, sys.argv[:]
-
- def tearDown(self):
- os.chdir(self.old_location)
- sys.argv = self.old_sys_argv[0]
- sys.argv[:] = self.old_sys_argv[1]
- super(BuildDumbTestCase, self).tearDown()
-
- @unittest.skipUnless(zlib, "requires zlib")
- def test_simple_built(self):
-
- # let's create a simple package
- tmp_dir = self.mkdtemp()
- pkg_dir = os.path.join(tmp_dir, 'foo')
- os.mkdir(pkg_dir)
- self.write_file((pkg_dir, 'setup.py'), SETUP_PY)
- self.write_file((pkg_dir, 'foo.py'), '#')
- self.write_file((pkg_dir, 'MANIFEST.in'), 'include foo.py')
- self.write_file((pkg_dir, 'README'), '')
-
- dist = Distribution({'name': 'foo', 'version': '0.1',
- 'py_modules': ['foo'],
- 'url': 'xxx', 'author': 'xxx',
- 'author_email': 'xxx'})
- dist.script_name = 'setup.py'
- os.chdir(pkg_dir)
-
- sys.argv = ['setup.py']
- cmd = bdist_dumb(dist)
-
- # so the output is the same no matter
- # what is the platform
- cmd.format = 'zip'
-
- cmd.ensure_finalized()
- cmd.run()
-
- # see what we have
- dist_created = os.listdir(os.path.join(pkg_dir, 'dist'))
- base = "%s.%s" % (dist.get_fullname(), cmd.plat_name)
- if os.name == 'os2':
- base = base.replace(':', '-')
-
- wanted = ['%s.zip' % base]
- self.assertEqual(dist_created, wanted)
-
- # now let's check what we have in the zip file
- # XXX to be done
-
- def test_finalize_options(self):
- pkg_dir, dist = self.create_dist()
- os.chdir(pkg_dir)
- cmd = bdist_dumb(dist)
- self.assertEqual(cmd.bdist_dir, None)
- cmd.finalize_options()
-
- # bdist_dir is initialized to bdist_base/dumb if not set
- base = cmd.get_finalized_command('bdist').bdist_base
- self.assertEqual(cmd.bdist_dir, os.path.join(base, 'dumb'))
-
- # the format is set to a default value depending on the os.name
- default = cmd.default_format[os.name]
- self.assertEqual(cmd.format, default)
-
-def test_suite():
- return unittest.makeSuite(BuildDumbTestCase)
-
-if __name__ == '__main__':
- run_unittest(test_suite())
diff --git a/src/distutils2/tests/test_bdist_msi.py b/src/distutils2/tests/test_bdist_msi.py
deleted file mode 100644
index 0d3bda8..0000000
--- a/src/distutils2/tests/test_bdist_msi.py
+++ /dev/null
@@ -1,25 +0,0 @@
-"""Tests for distutils.command.bdist_msi."""
-import sys
-
-from distutils2.tests import run_unittest
-
-from distutils2.tests import support
-from distutils2.tests.support import unittest
-
-class BDistMSITestCase(support.TempdirManager,
- support.LoggingCatcher,
- unittest.TestCase):
-
- @unittest.skipUnless(sys.platform == "win32", "runs only on win32")
- def test_minimal(self):
- # minimal test XXX need more tests
- from distutils2.command.bdist_msi import bdist_msi
- pkg_pth, dist = self.create_dist()
- cmd = bdist_msi(dist)
- cmd.ensure_finalized()
-
-def test_suite():
- return unittest.makeSuite(BDistMSITestCase)
-
-if __name__ == '__main__':
- run_unittest(test_suite())
diff --git a/src/distutils2/tests/test_bdist_wininst.py b/src/distutils2/tests/test_bdist_wininst.py
deleted file mode 100644
index f154463..0000000
--- a/src/distutils2/tests/test_bdist_wininst.py
+++ /dev/null
@@ -1,32 +0,0 @@
-"""Tests for distutils.command.bdist_wininst."""
-
-from distutils2.tests import run_unittest
-
-from distutils2.command.bdist_wininst import bdist_wininst
-from distutils2.tests import support
-from distutils2.tests.support import unittest
-
-class BuildWinInstTestCase(support.TempdirManager,
- support.LoggingCatcher,
- unittest.TestCase):
-
- def test_get_exe_bytes(self):
-
- # issue5731: command was broken on non-windows platforms
- # this test makes sure it works now for every platform
- # let's create a command
- pkg_pth, dist = self.create_dist()
- cmd = bdist_wininst(dist)
- cmd.ensure_finalized()
-
- # let's run the code that finds the right wininst*.exe file
- # and make sure it finds it and returns its content
- # no matter what platform we have
- exe_file = cmd.get_exe_bytes()
- self.assertTrue(len(exe_file) > 10)
-
-def test_suite():
- return unittest.makeSuite(BuildWinInstTestCase)
-
-if __name__ == '__main__':
- run_unittest(test_suite())
diff --git a/src/distutils2/tests/test_build.py b/src/distutils2/tests/test_build.py
deleted file mode 100644
index 1245111..0000000
--- a/src/distutils2/tests/test_build.py
+++ /dev/null
@@ -1,57 +0,0 @@
-"""Tests for distutils.command.build."""
-import os
-import sys
-
-from distutils2.command.build import build
-from distutils2.tests import support
-from distutils2.tests.support import unittest
-try:
- from sysconfig import get_platform
-except ImportError:
- from distutils2._backport.sysconfig import get_platform
-
-class BuildTestCase(support.TempdirManager,
- support.LoggingCatcher,
- unittest.TestCase):
-
- def test_finalize_options(self):
- pkg_dir, dist = self.create_dist()
- cmd = build(dist)
- cmd.finalize_options()
-
- # if not specified, plat_name gets the current platform
- self.assertEqual(cmd.plat_name, get_platform())
-
- # build_purelib is build + lib
- wanted = os.path.join(cmd.build_base, 'lib')
- self.assertEqual(cmd.build_purelib, wanted)
-
- # build_platlib is 'build/lib.platform-x.x[-pydebug]'
- # examples:
- # build/lib.macosx-10.3-i386-2.7
- plat_spec = '.%s-%s' % (cmd.plat_name, sys.version[0:3])
- if hasattr(sys, 'gettotalrefcount'):
- self.assertTrue(cmd.build_platlib.endswith('-pydebug'))
- plat_spec += '-pydebug'
- wanted = os.path.join(cmd.build_base, 'lib' + plat_spec)
- self.assertEqual(cmd.build_platlib, wanted)
-
- # by default, build_lib = build_purelib
- self.assertEqual(cmd.build_lib, cmd.build_purelib)
-
- # build_temp is build/temp.<plat>
- wanted = os.path.join(cmd.build_base, 'temp' + plat_spec)
- self.assertEqual(cmd.build_temp, wanted)
-
- # build_scripts is build/scripts-x.x
- wanted = os.path.join(cmd.build_base, 'scripts-' + sys.version[0:3])
- self.assertEqual(cmd.build_scripts, wanted)
-
- # executable is os.path.normpath(sys.executable)
- self.assertEqual(cmd.executable, os.path.normpath(sys.executable))
-
-def test_suite():
- return unittest.makeSuite(BuildTestCase)
-
-if __name__ == "__main__":
- unittest.main(defaultTest="test_suite")
diff --git a/src/distutils2/tests/test_build_clib.py b/src/distutils2/tests/test_build_clib.py
deleted file mode 100644
index b8d51d4..0000000
--- a/src/distutils2/tests/test_build_clib.py
+++ /dev/null
@@ -1,143 +0,0 @@
-"""Tests for distutils.command.build_clib."""
-import os
-import sys
-
-from distutils2.command.build_clib import build_clib
-from distutils2.errors import DistutilsSetupError
-from distutils2.tests import support
-from distutils2.util import find_executable
-from distutils2.tests.support import unittest
-
-class BuildCLibTestCase(support.TempdirManager,
- support.LoggingCatcher,
- unittest.TestCase):
-
- def test_check_library_dist(self):
- pkg_dir, dist = self.create_dist()
- cmd = build_clib(dist)
-
- # 'libraries' option must be a list
- self.assertRaises(DistutilsSetupError, cmd.check_library_list, 'foo')
-
- # each element of 'libraries' must a 2-tuple
- self.assertRaises(DistutilsSetupError, cmd.check_library_list,
- ['foo1', 'foo2'])
-
- # first element of each tuple in 'libraries'
- # must be a string (the library name)
- self.assertRaises(DistutilsSetupError, cmd.check_library_list,
- [(1, 'foo1'), ('name', 'foo2')])
-
- # library name may not contain directory separators
- self.assertRaises(DistutilsSetupError, cmd.check_library_list,
- [('name', 'foo1'),
- ('another/name', 'foo2')])
-
- # second element of each tuple must be a dictionary (build info)
- self.assertRaises(DistutilsSetupError, cmd.check_library_list,
- [('name', {}),
- ('another', 'foo2')])
-
- # those work
- libs = [('name', {}), ('name', {'ok': 'good'})]
- cmd.check_library_list(libs)
-
- def test_get_source_files(self):
- pkg_dir, dist = self.create_dist()
- cmd = build_clib(dist)
-
- # "in 'libraries' option 'sources' must be present and must be
- # a list of source filenames
- cmd.libraries = [('name', {})]
- self.assertRaises(DistutilsSetupError, cmd.get_source_files)
-
- cmd.libraries = [('name', {'sources': 1})]
- self.assertRaises(DistutilsSetupError, cmd.get_source_files)
-
- cmd.libraries = [('name', {'sources': ['a', 'b']})]
- self.assertEqual(cmd.get_source_files(), ['a', 'b'])
-
- cmd.libraries = [('name', {'sources': ('a', 'b')})]
- self.assertEqual(cmd.get_source_files(), ['a', 'b'])
-
- cmd.libraries = [('name', {'sources': ('a', 'b')}),
- ('name2', {'sources': ['c', 'd']})]
- self.assertEqual(cmd.get_source_files(), ['a', 'b', 'c', 'd'])
-
- def test_build_libraries(self):
-
- pkg_dir, dist = self.create_dist()
- cmd = build_clib(dist)
- class FakeCompiler:
- def compile(*args, **kw):
- pass
- create_static_lib = compile
-
- cmd.compiler = FakeCompiler()
-
- # build_libraries is also doing a bit of typoe checking
- lib = [('name', {'sources': 'notvalid'})]
- self.assertRaises(DistutilsSetupError, cmd.build_libraries, lib)
-
- lib = [('name', {'sources': list()})]
- cmd.build_libraries(lib)
-
- lib = [('name', {'sources': tuple()})]
- cmd.build_libraries(lib)
-
- def test_finalize_options(self):
- pkg_dir, dist = self.create_dist()
- cmd = build_clib(dist)
-
- cmd.include_dirs = 'one-dir'
- cmd.finalize_options()
- self.assertEqual(cmd.include_dirs, ['one-dir'])
-
- cmd.include_dirs = None
- cmd.finalize_options()
- self.assertEqual(cmd.include_dirs, [])
-
- cmd.distribution.libraries = 'WONTWORK'
- self.assertRaises(DistutilsSetupError, cmd.finalize_options)
-
- def test_run(self):
- # can't test on windows
- if sys.platform == 'win32':
- return
-
- pkg_dir, dist = self.create_dist()
- cmd = build_clib(dist)
-
- foo_c = os.path.join(pkg_dir, 'foo.c')
- self.write_file(foo_c, 'int main(void) { return 1;}\n')
- cmd.libraries = [('foo', {'sources': [foo_c]})]
-
- build_temp = os.path.join(pkg_dir, 'build')
- os.mkdir(build_temp)
- cmd.build_temp = build_temp
- cmd.build_clib = build_temp
-
- # before we run the command, we want to make sure
- # all commands are present on the system
- # by creating a compiler and checking its executables
- from distutils2.compiler.ccompiler import new_compiler, customize_compiler
-
- compiler = new_compiler()
- customize_compiler(compiler)
- for ccmd in compiler.executables.values():
- if ccmd is None:
- continue
- if find_executable(ccmd[0]) is None:
- return # can't test
-
- # this should work
- cmd.run()
-
- # let's check the result
- self.assertTrue('libfoo.a' in os.listdir(build_temp))
-
-def test_suite():
- return unittest.makeSuite(BuildCLibTestCase)
-
-if __name__ == "__main__":
- unittest.main(defaultTest="test_suite")
diff --git a/src/distutils2/tests/test_build_ext.py b/src/distutils2/tests/test_build_ext.py
deleted file mode 100644
index 9b1ee45..0000000
--- a/src/distutils2/tests/test_build_ext.py
+++ /dev/null
@@ -1,366 +0,0 @@
-import sys
-import os
-import shutil
-from StringIO import StringIO
-
-import distutils2.tests
-from distutils2.tests.support import unittest
-from distutils2.core import Extension, Distribution
-from distutils2.command.build_ext import build_ext
-from distutils2.tests import support
-from distutils2.extension import Extension
-from distutils2.errors import (UnknownFileError, DistutilsSetupError,
- CompileError)
-try:
- import sysconfig
-except ImportError:
- from distutils2._backport import sysconfig
-
-
-# http://bugs.python.org/issue4373
-# Don't load the xx module more than once.
-ALREADY_TESTED = False
-CURDIR = os.path.abspath(os.path.dirname(__file__))
-
-def _get_source_filename():
- return os.path.join(CURDIR, 'xxmodule.c')
-
-class BuildExtTestCase(support.TempdirManager,
- support.LoggingCatcher,
- unittest.TestCase):
- def setUp(self):
- # Create a simple test environment
- # Note that we're making changes to sys.path
- super(BuildExtTestCase, self).setUp()
- self.tmp_dir = self.mkdtemp()
- self.sys_path = sys.path, sys.path[:]
- sys.path.append(self.tmp_dir)
- shutil.copy(_get_source_filename(), self.tmp_dir)
- if sys.version > "2.6":
- import site
- self.old_user_base = site.USER_BASE
- site.USER_BASE = self.mkdtemp()
- from distutils2.command import build_ext
- build_ext.USER_BASE = site.USER_BASE
-
- # XXX only works with 2.6 > -- dunno why yet
- @unittest.skipIf(sys.version < '2.6', 'requires Python 2.6 or higher')
- def test_build_ext(self):
- global ALREADY_TESTED
- xx_c = os.path.join(self.tmp_dir, 'xxmodule.c')
- xx_ext = Extension('xx', [xx_c])
- dist = Distribution({'name': 'xx', 'ext_modules': [xx_ext]})
- dist.package_dir = self.tmp_dir
- cmd = build_ext(dist)
- if os.name == "nt":
- # On Windows, we must build a debug version iff running
- # a debug build of Python
- cmd.debug = sys.executable.endswith("_d.exe")
- cmd.build_lib = self.tmp_dir
- cmd.build_temp = self.tmp_dir
-
- old_stdout = sys.stdout
- if not distutils2.tests.verbose:
- # silence compiler output
- sys.stdout = StringIO()
- try:
- cmd.ensure_finalized()
- cmd.run()
- finally:
- sys.stdout = old_stdout
-
- if ALREADY_TESTED:
- return
- else:
- ALREADY_TESTED = True
-
- import xx
-
- for attr in ('error', 'foo', 'new', 'roj'):
- self.assertTrue(hasattr(xx, attr))
-
- self.assertEqual(xx.foo(2, 5), 7)
- self.assertEqual(xx.foo(13,15), 28)
- self.assertEqual(xx.new().demo(), None)
- doc = 'This is a template module just for instruction.'
- self.assertEqual(xx.__doc__, doc)
- self.assertTrue(isinstance(xx.Null(), xx.Null))
- self.assertTrue(isinstance(xx.Str(), xx.Str))
-
- def tearDown(self):
- # Get everything back to normal
- distutils2.tests.unload('xx')
- sys.path = self.sys_path[0]
- sys.path[:] = self.sys_path[1]
- if sys.version > "2.6":
- import site
- site.USER_BASE = self.old_user_base
- from distutils2.command import build_ext
- build_ext.USER_BASE = self.old_user_base
-
- super(BuildExtTestCase, self).tearDown()
-
- def test_solaris_enable_shared(self):
- dist = Distribution({'name': 'xx'})
- cmd = build_ext(dist)
- old = sys.platform
-
- sys.platform = 'sunos' # fooling finalize_options
- try:
- from sysconfig import _CONFIG_VARS
- except ImportError:
- from distutils2._backport.sysconfig import _CONFIG_VARS
-
- old_var = _CONFIG_VARS.get('Py_ENABLE_SHARED')
- _CONFIG_VARS['Py_ENABLE_SHARED'] = 1
- try:
- cmd.ensure_finalized()
- finally:
- sys.platform = old
- if old_var is None:
- del _CONFIG_VARS['Py_ENABLE_SHARED']
- else:
- _CONFIG_VARS['Py_ENABLE_SHARED'] = old_var
-
- # make sure we get some library dirs under solaris
- self.assertTrue(len(cmd.library_dirs) > 0)
-
- @unittest.skipIf(sys.version < '2.6', 'requires Python 2.6 or higher')
- def test_user_site(self):
- import site
- dist = Distribution({'name': 'xx'})
- cmd = build_ext(dist)
-
- # making sure the user option is there
- options = [name for name, short, lable in
- cmd.user_options]
- self.assertTrue('user' in options)
-
- # setting a value
- cmd.user = 1
-
- # setting user based lib and include
- lib = os.path.join(site.USER_BASE, 'lib')
- incl = os.path.join(site.USER_BASE, 'include')
- os.mkdir(lib)
- os.mkdir(incl)
-
- # let's run finalize
- cmd.ensure_finalized()
-
- # see if include_dirs and library_dirs
- # were set
- self.assertTrue(lib in cmd.library_dirs)
- self.assertTrue(lib in cmd.rpath)
- self.assertTrue(incl in cmd.include_dirs)
-
- def test_optional_extension(self):
-
- # this extension will fail, but let's ignore this failure
- # with the optional argument.
- modules = [Extension('foo', ['xxx'], optional=False)]
- dist = Distribution({'name': 'xx', 'ext_modules': modules})
- cmd = build_ext(dist)
- cmd.ensure_finalized()
- self.assertRaises((UnknownFileError, CompileError),
- cmd.run) # should raise an error
-
- modules = [Extension('foo', ['xxx'], optional=True)]
- dist = Distribution({'name': 'xx', 'ext_modules': modules})
- cmd = build_ext(dist)
- cmd.ensure_finalized()
- cmd.run() # should pass
-
- def test_finalize_options(self):
- # Make sure Python's include directories (for Python.h, pyconfig.h,
- # etc.) are in the include search path.
- modules = [Extension('foo', ['xxx'], optional=False)]
- dist = Distribution({'name': 'xx', 'ext_modules': modules})
- cmd = build_ext(dist)
- cmd.finalize_options()
-
- py_include = sysconfig.get_path('include')
- self.assertTrue(py_include in cmd.include_dirs)
-
- plat_py_include = sysconfig.get_path('platinclude')
- self.assertTrue(plat_py_include in cmd.include_dirs)
-
- # make sure cmd.libraries is turned into a list
- # if it's a string
- cmd = build_ext(dist)
- cmd.libraries = 'my_lib'
- cmd.finalize_options()
- self.assertEqual(cmd.libraries, ['my_lib'])
-
- # make sure cmd.library_dirs is turned into a list
- # if it's a string
- cmd = build_ext(dist)
- cmd.library_dirs = 'my_lib_dir'
- cmd.finalize_options()
- self.assertTrue('my_lib_dir' in cmd.library_dirs)
-
- # make sure rpath is turned into a list
- # if it's a list of os.pathsep's paths
- cmd = build_ext(dist)
- cmd.rpath = os.pathsep.join(['one', 'two'])
- cmd.finalize_options()
- self.assertEqual(cmd.rpath, ['one', 'two'])
-
- # XXX more tests to perform for win32
-
- # make sure define is turned into 2-tuples
- # strings if they are ','-separated strings
- cmd = build_ext(dist)
- cmd.define = 'one,two'
- cmd.finalize_options()
- self.assertEqual(cmd.define, [('one', '1'), ('two', '1')])
-
- # make sure undef is turned into a list of
- # strings if they are ','-separated strings
- cmd = build_ext(dist)
- cmd.undef = 'one,two'
- cmd.finalize_options()
- self.assertEqual(cmd.undef, ['one', 'two'])
-
- # make sure swig_opts is turned into a list
- cmd = build_ext(dist)
- cmd.swig_opts = None
- cmd.finalize_options()
- self.assertEqual(cmd.swig_opts, [])
-
- cmd = build_ext(dist)
- cmd.swig_opts = '1 2'
- cmd.finalize_options()
- self.assertEqual(cmd.swig_opts, ['1', '2'])
-
- def test_get_source_files(self):
- modules = [Extension('foo', ['xxx'], optional=False)]
- dist = Distribution({'name': 'xx', 'ext_modules': modules})
- cmd = build_ext(dist)
- cmd.ensure_finalized()
- self.assertEqual(cmd.get_source_files(), ['xxx'])
-
- def test_compiler_option(self):
- # cmd.compiler is an option and
- # should not be overriden by a compiler instance
- # when the command is run
- dist = Distribution()
- cmd = build_ext(dist)
- cmd.compiler = 'unix'
- cmd.ensure_finalized()
- cmd.run()
- self.assertEqual(cmd.compiler, 'unix')
-
- def test_get_outputs(self):
- tmp_dir = self.mkdtemp()
- c_file = os.path.join(tmp_dir, 'foo.c')
- self.write_file(c_file, 'void initfoo(void) {};\n')
- ext = Extension('foo', [c_file], optional=False)
- dist = Distribution({'name': 'xx',
- 'ext_modules': [ext]})
- cmd = build_ext(dist)
- cmd.ensure_finalized()
- self.assertEqual(len(cmd.get_outputs()), 1)
-
- if os.name == "nt":
- cmd.debug = sys.executable.endswith("_d.exe")
-
- cmd.build_lib = os.path.join(self.tmp_dir, 'build')
- cmd.build_temp = os.path.join(self.tmp_dir, 'tempt')
-
- # issue #5977 : distutils build_ext.get_outputs
- # returns wrong result with --inplace
- other_tmp_dir = os.path.realpath(self.mkdtemp())
- old_wd = os.getcwd()
- os.chdir(other_tmp_dir)
- try:
- cmd.inplace = 1
- cmd.run()
- so_file = cmd.get_outputs()[0]
- finally:
- os.chdir(old_wd)
- self.assertTrue(os.path.exists(so_file))
- so_ext = sysconfig.get_config_var('SO')
- self.assertTrue(so_file.endswith(so_ext))
- so_dir = os.path.dirname(so_file)
- self.assertEqual(so_dir, other_tmp_dir)
-
- cmd.inplace = 0
- cmd.run()
- so_file = cmd.get_outputs()[0]
- self.assertTrue(os.path.exists(so_file))
- self.assertTrue(so_file.endswith(so_ext))
- so_dir = os.path.dirname(so_file)
- self.assertEqual(so_dir, cmd.build_lib)
-
- # inplace = 0, cmd.package = 'bar'
- build_py = cmd.get_finalized_command('build_py')
- build_py.package_dir = {'': 'bar'}
- path = cmd.get_ext_fullpath('foo')
- # checking that the last directory is the build_dir
- path = os.path.split(path)[0]
- self.assertEqual(path, cmd.build_lib)
-
- # inplace = 1, cmd.package = 'bar'
- cmd.inplace = 1
- other_tmp_dir = os.path.realpath(self.mkdtemp())
- old_wd = os.getcwd()
- os.chdir(other_tmp_dir)
- try:
- path = cmd.get_ext_fullpath('foo')
- finally:
- os.chdir(old_wd)
- # checking that the last directory is bar
- path = os.path.split(path)[0]
- lastdir = os.path.split(path)[-1]
- self.assertEqual(lastdir, 'bar')
-
- def test_ext_fullpath(self):
- ext = sysconfig.get_config_vars()['SO']
- # building lxml.etree inplace
- #etree_c = os.path.join(self.tmp_dir, 'lxml.etree.c')
- #etree_ext = Extension('lxml.etree', [etree_c])
- #dist = Distribution({'name': 'lxml', 'ext_modules': [etree_ext]})
- dist = Distribution()
- cmd = build_ext(dist)
- cmd.inplace = 1
- cmd.distribution.package_dir = {'': 'src'}
- cmd.distribution.packages = ['lxml', 'lxml.html']
- curdir = os.getcwd()
- wanted = os.path.join(curdir, 'src', 'lxml', 'etree' + ext)
- path = cmd.get_ext_fullpath('lxml.etree')
- self.assertEqual(wanted, path)
-
- # building lxml.etree not inplace
- cmd.inplace = 0
- cmd.build_lib = os.path.join(curdir, 'tmpdir')
- wanted = os.path.join(curdir, 'tmpdir', 'lxml', 'etree' + ext)
- path = cmd.get_ext_fullpath('lxml.etree')
- self.assertEqual(wanted, path)
-
- # building twisted.runner.portmap not inplace
- build_py = cmd.get_finalized_command('build_py')
- build_py.package_dir = {}
- cmd.distribution.packages = ['twisted', 'twisted.runner.portmap']
- path = cmd.get_ext_fullpath('twisted.runner.portmap')
- wanted = os.path.join(curdir, 'tmpdir', 'twisted', 'runner',
- 'portmap' + ext)
- self.assertEqual(wanted, path)
-
- # building twisted.runner.portmap inplace
- cmd.inplace = 1
- path = cmd.get_ext_fullpath('twisted.runner.portmap')
- wanted = os.path.join(curdir, 'twisted', 'runner', 'portmap' + ext)
- self.assertEqual(wanted, path)
-
-def test_suite():
- src = _get_source_filename()
- if not os.path.exists(src):
- if distutils2.tests.verbose:
- print ('test_build_ext: Cannot find source code (test'
- ' must run in python build dir)')
- return unittest.TestSuite()
- else: return unittest.makeSuite(BuildExtTestCase)
-
-if __name__ == '__main__':
- distutils2.tests.run_unittest(test_suite())
diff --git a/src/distutils2/tests/test_build_py.py b/src/distutils2/tests/test_build_py.py
deleted file mode 100644
index 4ee15f1..0000000
--- a/src/distutils2/tests/test_build_py.py
+++ /dev/null
@@ -1,122 +0,0 @@
-"""Tests for distutils.command.build_py."""
-
-import os
-import sys
-import StringIO
-
-from distutils2.command.build_py import build_py
-from distutils2.core import Distribution
-from distutils2.errors import DistutilsFileError
-
-from distutils2.tests import support
-from distutils2.tests.support import unittest
-
-
-class BuildPyTestCase(support.TempdirManager,
- support.LoggingCatcher,
- unittest.TestCase):
-
- def test_package_data(self):
- sources = self.mkdtemp()
- f = open(os.path.join(sources, "__init__.py"), "w")
- try:
- f.write("# Pretend this is a package.")
- finally:
- f.close()
- f = open(os.path.join(sources, "README.txt"), "w")
- try:
- f.write("Info about this package")
- finally:
- f.close()
-
- destination = self.mkdtemp()
-
- dist = Distribution({"packages": ["pkg"],
- "package_dir": {"pkg": sources}})
- # script_name need not exist, it just need to be initialized
- dist.script_name = os.path.join(sources, "setup.py")
- dist.command_obj["build"] = support.DummyCommand(
- force=0,
- build_lib=destination,
- use_2to3_fixers=None,
- convert_2to3_doctests=None,
- use_2to3=False)
- dist.packages = ["pkg"]
- dist.package_data = {"pkg": ["README.txt"]}
- dist.package_dir = {"pkg": sources}
-
- cmd = build_py(dist)
- cmd.compile = 1
- cmd.ensure_finalized()
- self.assertEqual(cmd.package_data, dist.package_data)
-
- cmd.run()
-
- # This makes sure the list of outputs includes byte-compiled
- # files for Python modules but not for package data files
- # (there shouldn't *be* byte-code files for those!).
- #
- self.assertEqual(len(cmd.get_outputs()), 3)
- pkgdest = os.path.join(destination, "pkg")
- files = os.listdir(pkgdest)
- self.assertTrue("__init__.py" in files)
- self.assertTrue("__init__.pyc" in files)
- self.assertTrue("README.txt" in files)
-
- def test_empty_package_dir (self):
- # See SF 1668596/1720897.
- cwd = os.getcwd()
-
- # create the distribution files.
- sources = self.mkdtemp()
- open(os.path.join(sources, "__init__.py"), "w").close()
-
- testdir = os.path.join(sources, "doc")
- os.mkdir(testdir)
- open(os.path.join(testdir, "testfile"), "w").close()
-
- os.chdir(sources)
- old_stdout = sys.stdout
- sys.stdout = StringIO.StringIO()
-
- try:
- dist = Distribution({"packages": ["pkg"],
- "package_dir": {"pkg": ""},
- "package_data": {"pkg": ["doc/*"]}})
- # script_name need not exist, it just need to be initialized
- dist.script_name = os.path.join(sources, "setup.py")
- dist.script_args = ["build"]
- dist.parse_command_line()
-
- try:
- dist.run_commands()
- except DistutilsFileError:
- self.fail("failed package_data test when package_dir is ''")
- finally:
- # Restore state.
- os.chdir(cwd)
- sys.stdout = old_stdout
-
- @unittest.skipUnless(hasattr(sys, 'dont_write_bytecode'),
- 'sys.dont_write_bytecode not supported')
- def test_dont_write_bytecode(self):
- # makes sure byte_compile is not used
- pkg_dir, dist = self.create_dist()
- cmd = build_py(dist)
- cmd.compile = 1
- cmd.optimize = 1
-
- old_dont_write_bytecode = sys.dont_write_bytecode
- sys.dont_write_bytecode = True
- try:
- cmd.byte_compile([])
- finally:
- sys.dont_write_bytecode = old_dont_write_bytecode
-
- self.assertTrue('byte-compiling is disabled' in self.logs[0][1])
-
-def test_suite():
- return unittest.makeSuite(BuildPyTestCase)
-
-if __name__ == "__main__":
- unittest.main(defaultTest="test_suite")
diff --git a/src/distutils2/tests/test_build_scripts.py b/src/distutils2/tests/test_build_scripts.py
deleted file mode 100644
index 3982d99..0000000
--- a/src/distutils2/tests/test_build_scripts.py
+++ /dev/null
@@ -1,117 +0,0 @@
-"""Tests for distutils.command.build_scripts."""
-
-import os
-
-from distutils2.command.build_scripts import build_scripts
-from distutils2.core import Distribution
-try:
- import sysconfig
-except ImportError:
- from distutils2._backport import sysconfig
-
-from distutils2.tests import support
-from distutils2.tests.support import unittest
-
-
-class BuildScriptsTestCase(support.TempdirManager,
- support.LoggingCatcher,
- unittest.TestCase):
-
- def test_default_settings(self):
- cmd = self.get_build_scripts_cmd("/foo/bar", [])
- self.assertTrue(not cmd.force)
- self.assertTrue(cmd.build_dir is None)
-
- cmd.finalize_options()
-
- self.assertTrue(cmd.force)
- self.assertEqual(cmd.build_dir, "/foo/bar")
-
- def test_build(self):
- source = self.mkdtemp()
- target = self.mkdtemp()
- expected = self.write_sample_scripts(source)
-
- cmd = self.get_build_scripts_cmd(target,
- [os.path.join(source, fn)
- for fn in expected])
- cmd.finalize_options()
- cmd.run()
-
- built = os.listdir(target)
- for name in expected:
- self.assertTrue(name in built)
-
- def get_build_scripts_cmd(self, target, scripts):
- import sys
- dist = Distribution()
- dist.scripts = scripts
- dist.command_obj["build"] = support.DummyCommand(
- build_scripts=target,
- force=1,
- executable=sys.executable,
- use_2to3=False,
- use_2to3_fixers=None,
- convert_2to3_doctests=None
- )
- return build_scripts(dist)
-
- def write_sample_scripts(self, dir):
- expected = []
- expected.append("script1.py")
- self.write_script(dir, "script1.py",
- ("#! /usr/bin/env python2.3\n"
- "# bogus script w/ Python sh-bang\n"
- "pass\n"))
- expected.append("script2.py")
- self.write_script(dir, "script2.py",
- ("#!/usr/bin/python\n"
- "# bogus script w/ Python sh-bang\n"
- "pass\n"))
- expected.append("shell.sh")
- self.write_script(dir, "shell.sh",
- ("#!/bin/sh\n"
- "# bogus shell script w/ sh-bang\n"
- "exit 0\n"))
- return expected
-
- def write_script(self, dir, name, text):
- f = open(os.path.join(dir, name), "w")
- try:
- f.write(text)
- finally:
- f.close()
-
- def test_version_int(self):
- source = self.mkdtemp()
- target = self.mkdtemp()
- expected = self.write_sample_scripts(source)
-
-
- cmd = self.get_build_scripts_cmd(target,
- [os.path.join(source, fn)
- for fn in expected])
- cmd.finalize_options()
-
- # http://bugs.python.org/issue4524
- #
- # On linux-g++-32 with command line `./configure --enable-ipv6
- # --with-suffix=3`, python is compiled okay but the build scripts
- # failed when writing the name of the executable
- old = sysconfig.get_config_vars().get('VERSION')
- sysconfig._CONFIG_VARS['VERSION'] = 4
- try:
- cmd.run()
- finally:
- if old is not None:
- sysconfig._CONFIG_VARS['VERSION'] = old
-
- built = os.listdir(target)
- for name in expected:
- self.assertTrue(name in built)
-
-def test_suite():
- return unittest.makeSuite(BuildScriptsTestCase)
-
-if __name__ == "__main__":
- unittest.main(defaultTest="test_suite")
diff --git a/src/distutils2/tests/test_ccompiler.py b/src/distutils2/tests/test_ccompiler.py
deleted file mode 100644
index df25253..0000000
--- a/src/distutils2/tests/test_ccompiler.py
+++ /dev/null
@@ -1,60 +0,0 @@
-"""Tests for distutils.ccompiler."""
-import os
-from distutils2.tests import captured_stdout
-
-from distutils2.compiler.ccompiler import (gen_lib_options, CCompiler,
- get_default_compiler, customize_compiler)
-from distutils2.tests import support
-from distutils2.tests.support import unittest
-
-class FakeCompiler(object):
- def library_dir_option(self, dir):
- return "-L" + dir
-
- def runtime_library_dir_option(self, dir):
- return ["-cool", "-R" + dir]
-
- def find_library_file(self, dirs, lib, debug=0):
- return 'found'
-
- def library_option(self, lib):
- return "-l" + lib
-
-class CCompilerTestCase(support.EnvironGuard, unittest.TestCase):
-
- def test_gen_lib_options(self):
- compiler = FakeCompiler()
- libdirs = ['lib1', 'lib2']
- runlibdirs = ['runlib1']
- libs = [os.path.join('dir', 'name'), 'name2']
-
- opts = gen_lib_options(compiler, libdirs, runlibdirs, libs)
- wanted = ['-Llib1', '-Llib2', '-cool', '-Rrunlib1', 'found',
- '-lname2']
- self.assertEqual(opts, wanted)
-
- def test_customize_compiler(self):
-
- # not testing if default compiler is not unix
- if get_default_compiler() != 'unix':
- return
-
- os.environ['AR'] = 'my_ar'
- os.environ['ARFLAGS'] = '-arflags'
-
- # make sure AR gets caught
- class compiler:
- compiler_type = 'unix'
-
- def set_executables(self, **kw):
- self.exes = kw
-
- comp = compiler()
- customize_compiler(comp)
- self.assertEqual(comp.exes['archiver'], 'my_ar -arflags')
-
-def test_suite():
- return unittest.makeSuite(CCompilerTestCase)
-
-if __name__ == "__main__":
- unittest.main(defaultTest="test_suite")
diff --git a/src/distutils2/tests/test_check.py b/src/distutils2/tests/test_check.py
deleted file mode 100644
index 02e2484..0000000
--- a/src/distutils2/tests/test_check.py
+++ /dev/null
@@ -1,85 +0,0 @@
-"""Tests for distutils.command.check."""
-
-from distutils2.command.check import check
-from distutils2.metadata import _HAS_DOCUTILS
-from distutils2.tests import support
-from distutils2.tests.support import unittest
-from distutils2.errors import DistutilsSetupError
-
-class CheckTestCase(support.LoggingCatcher,
- support.TempdirManager,
- unittest.TestCase):
-
- def _run(self, metadata=None, **options):
- if metadata is None:
- metadata = {}
- pkg_info, dist = self.create_dist(**metadata)
- cmd = check(dist)
- cmd.initialize_options()
- for name, value in options.items():
- setattr(cmd, name, value)
- cmd.ensure_finalized()
- cmd.run()
- return cmd
-
- def test_check_metadata(self):
- # let's run the command with no metadata at all
- # by default, check is checking the metadata
- # should have some warnings
- cmd = self._run()
- self.assertTrue(len(cmd._warnings) > 0)
-
- # now let's add the required fields
- # and run it again, to make sure we don't get
- # any warning anymore
- metadata = {'home_page': 'xxx', 'author': 'xxx',
- 'author_email': 'xxx',
- 'name': 'xxx', 'version': 'xxx'
- }
- cmd = self._run(metadata)
- self.assertEqual(len(cmd._warnings), 0)
-
- # now with the strict mode, we should
- # get an error if there are missing metadata
- self.assertRaises(DistutilsSetupError, self._run, {}, **{'strict': 1})
-
- # and of course, no error when all metadata fields are present
- cmd = self._run(metadata, strict=1)
- self.assertEqual(len(cmd._warnings), 0)
-
- @unittest.skipUnless(_HAS_DOCUTILS, "requires docutils")
- def test_check_restructuredtext(self):
- # let's see if it detects broken rest in long_description
- broken_rest = 'title\n===\n\ntest'
- pkg_info, dist = self.create_dist(description=broken_rest)
- cmd = check(dist)
- cmd.check_restructuredtext()
- self.assertEqual(len(cmd._warnings), 1)
-
- pkg_info, dist = self.create_dist(description='title\n=====\n\ntest')
- cmd = check(dist)
- cmd.check_restructuredtext()
- self.assertEqual(len(cmd._warnings), 0)
-
- def test_check_all(self):
-
- metadata = {'home_page': 'xxx', 'author': 'xxx'}
- self.assertRaises(DistutilsSetupError, self._run,
- {}, **{'strict': 1,
- 'all': 1})
-
- def test_check_hooks(self):
- pkg_info, dist = self.create_dist()
- dist.command_options['install'] = {
- 'pre_hook': ('file', {"a": 'some.nonextistant.hook.ghrrraarrhll'}),
- }
- cmd = check(dist)
- cmd.check_hooks_resolvable()
- self.assertEqual(len(cmd._warnings), 1)
-
-
-def test_suite():
- return unittest.makeSuite(CheckTestCase)
-
-if __name__ == "__main__":
- unittest.main(defaultTest="test_suite")
diff --git a/src/distutils2/tests/test_clean.py b/src/distutils2/tests/test_clean.py
deleted file mode 100644
index acc5b66..0000000
--- a/src/distutils2/tests/test_clean.py
+++ /dev/null
@@ -1,50 +0,0 @@
-"""Tests for distutils.command.clean."""
-import sys
-import os
-import getpass
-
-from distutils2.command.clean import clean
-from distutils2.tests import support
-from distutils2.tests.support import unittest
-
-class cleanTestCase(support.TempdirManager,
- support.LoggingCatcher,
- unittest.TestCase):
-
- def test_simple_run(self):
- pkg_dir, dist = self.create_dist()
- cmd = clean(dist)
-
- # let's add some elements clean should remove
- dirs = [(d, os.path.join(pkg_dir, d))
- for d in ('build_temp', 'build_lib', 'bdist_base',
- 'build_scripts', 'build_base')]
-
- for name, path in dirs:
- os.mkdir(path)
- setattr(cmd, name, path)
- if name == 'build_base':
- continue
- for f in ('one', 'two', 'three'):
- self.write_file(os.path.join(path, f))
-
- # let's run the command
- cmd.all = 1
- cmd.ensure_finalized()
- cmd.run()
-
- # make sure the files where removed
- for name, path in dirs:
- self.assertTrue(not os.path.exists(path),
- '%s was not removed' % path)
-
- # let's run the command again (should spit warnings but suceed)
- cmd.all = 1
- cmd.ensure_finalized()
- cmd.run()
-
-def test_suite():
- return unittest.makeSuite(cleanTestCase)
-
-if __name__ == "__main__":
- unittest.main(defaultTest="test_suite")
diff --git a/src/distutils2/tests/test_cmd.py b/src/distutils2/tests/test_cmd.py
deleted file mode 100644
index c768f79..0000000
--- a/src/distutils2/tests/test_cmd.py
+++ /dev/null
@@ -1,110 +0,0 @@
-"""Tests for distutils.cmd."""
-import os
-from distutils2.tests import captured_stdout, run_unittest
-
-from distutils2.command.cmd import Command
-from distutils2.dist import Distribution
-from distutils2.errors import DistutilsOptionError
-from distutils2.tests.support import unittest
-
-class MyCmd(Command):
- def initialize_options(self):
- pass
-
-class CommandTestCase(unittest.TestCase):
-
- def setUp(self):
- dist = Distribution()
- self.cmd = MyCmd(dist)
-
- def test_ensure_string_list(self):
-
- cmd = self.cmd
- cmd.not_string_list = ['one', 2, 'three']
- cmd.yes_string_list = ['one', 'two', 'three']
- cmd.not_string_list2 = object()
- cmd.yes_string_list2 = 'ok'
- cmd.ensure_string_list('yes_string_list')
- cmd.ensure_string_list('yes_string_list2')
-
- self.assertRaises(DistutilsOptionError,
- cmd.ensure_string_list, 'not_string_list')
-
- self.assertRaises(DistutilsOptionError,
- cmd.ensure_string_list, 'not_string_list2')
-
- def test_make_file(self):
-
- cmd = self.cmd
-
- # making sure it raises when infiles is not a string or a list/tuple
- self.assertRaises(TypeError, cmd.make_file,
- infiles=1, outfile='', func='func', args=())
-
- # making sure execute gets called properly
- def _execute(func, args, exec_msg, level):
- self.assertEqual(exec_msg, 'generating out from in')
- cmd.force = True
- cmd.execute = _execute
- cmd.make_file(infiles='in', outfile='out', func='func', args=())
-
- def test_dump_options(self):
-
- msgs = []
- def _announce(msg, level):
- msgs.append(msg)
- cmd = self.cmd
- cmd.announce = _announce
- cmd.option1 = 1
- cmd.option2 = 1
- cmd.user_options = [('option1', '', ''), ('option2', '', '')]
- cmd.dump_options()
-
- wanted = ["command options for 'MyCmd':", ' option1 = 1',
- ' option2 = 1']
- self.assertEqual(msgs, wanted)
-
- def test_ensure_string(self):
- cmd = self.cmd
- cmd.option1 = 'ok'
- cmd.ensure_string('option1')
-
- cmd.option2 = None
- cmd.ensure_string('option2', 'xxx')
- self.assertTrue(hasattr(cmd, 'option2'))
-
- cmd.option3 = 1
- self.assertRaises(DistutilsOptionError, cmd.ensure_string, 'option3')
-
- def test_ensure_string_list(self):
- cmd = self.cmd
- cmd.option1 = 'ok,dok'
- cmd.ensure_string_list('option1')
- self.assertEqual(cmd.option1, ['ok', 'dok'])
-
- cmd.option2 = ['xxx', 'www']
- cmd.ensure_string_list('option2')
-
- cmd.option3 = ['ok', 2]
- self.assertRaises(DistutilsOptionError, cmd.ensure_string_list,
- 'option3')
-
- def test_ensure_filename(self):
- cmd = self.cmd
- cmd.option1 = __file__
- cmd.ensure_filename('option1')
- cmd.option2 = 'xxx'
- self.assertRaises(DistutilsOptionError, cmd.ensure_filename, 'option2')
-
- def test_ensure_dirname(self):
- cmd = self.cmd
- cmd.option1 = os.path.dirname(__file__) or os.curdir
- cmd.ensure_dirname('option1')
- cmd.option2 = 'xxx'
- self.assertRaises(DistutilsOptionError, cmd.ensure_dirname, 'option2')
-
-def test_suite():
- return unittest.makeSuite(CommandTestCase)
-
-if __name__ == '__main__':
- run_unittest(test_suite())
diff --git a/src/distutils2/tests/test_config_cmd.py b/src/distutils2/tests/test_config_cmd.py
deleted file mode 100644
index eab12fd..0000000
--- a/src/distutils2/tests/test_config_cmd.py
+++ /dev/null
@@ -1,89 +0,0 @@
-"""Tests for distutils.command.config."""
-import os
-import sys
-
-from distutils2.command.config import dump_file, config
-from distutils2.tests import support
-from distutils2.tests.support import unittest
-from distutils2 import log
-
-class ConfigTestCase(support.LoggingCatcher,
- support.TempdirManager,
- unittest.TestCase):
-
- def _info(self, msg, *args):
- for line in msg.splitlines():
- self._logs.append(line)
-
- def setUp(self):
- super(ConfigTestCase, self).setUp()
- self._logs = []
- self.old_log = log.info
- log.info = self._info
-
- def tearDown(self):
- log.info = self.old_log
- super(ConfigTestCase, self).tearDown()
-
- def test_dump_file(self):
- this_file = os.path.splitext(__file__)[0] + '.py'
- f = open(this_file)
- try:
- numlines = len(f.readlines())
- finally:
- f.close()
-
- dump_file(this_file, 'I am the header')
- self.assertEqual(len(self._logs), numlines+1)
-
- def test_search_cpp(self):
- if sys.platform == 'win32':
- return
- pkg_dir, dist = self.create_dist()
- cmd = config(dist)
-
- # simple pattern searches
- match = cmd.search_cpp(pattern='xxx', body='// xxx')
- self.assertEqual(match, 0)
-
- match = cmd.search_cpp(pattern='_configtest', body='// xxx')
- self.assertEqual(match, 1)
-
- def test_finalize_options(self):
- # finalize_options does a bit of transformation
- # on options
- pkg_dir, dist = self.create_dist()
- cmd = config(dist)
- cmd.include_dirs = 'one%stwo' % os.pathsep
- cmd.libraries = 'one'
- cmd.library_dirs = 'three%sfour' % os.pathsep
- cmd.ensure_finalized()
-
- self.assertEqual(cmd.include_dirs, ['one', 'two'])
- self.assertEqual(cmd.libraries, ['one'])
- self.assertEqual(cmd.library_dirs, ['three', 'four'])
-
- def test_clean(self):
- # _clean removes files
- tmp_dir = self.mkdtemp()
- f1 = os.path.join(tmp_dir, 'one')
- f2 = os.path.join(tmp_dir, 'two')
-
- self.write_file(f1, 'xxx')
- self.write_file(f2, 'xxx')
-
- for f in (f1, f2):
- self.assertTrue(os.path.exists(f))
-
- pkg_dir, dist = self.create_dist()
- cmd = config(dist)
- cmd._clean(f1, f2)
-
- for f in (f1, f2):
- self.assertTrue(not os.path.exists(f))
-
-def test_suite():
- return unittest.makeSuite(ConfigTestCase)
-
-if __name__ == "__main__":
- unittest.main(defaultTest="test_suite")
diff --git a/src/distutils2/tests/test_core.py b/src/distutils2/tests/test_core.py
deleted file mode 100644
index 883187e..0000000
--- a/src/distutils2/tests/test_core.py
+++ /dev/null
@@ -1,98 +0,0 @@
-"""Tests for distutils2.core."""
-
-import StringIO
-import distutils2.core
-import os
-import shutil
-import sys
-from distutils2.tests import captured_stdout
-from distutils2.tests import support
-from distutils2.tests.support import unittest
-
-# setup script that uses __file__
-setup_using___file__ = """\
-
-__file__
-
-from distutils2.core import setup
-setup()
-"""
-
-setup_prints_cwd = """\
-
-import os
-print os.getcwd()
-
-from distutils2.core import setup
-setup()
-"""
-
-
-class CoreTestCase(support.EnvironGuard, unittest.TestCase):
-
- def setUp(self):
- super(CoreTestCase, self).setUp()
- self.old_stdout = sys.stdout
- self.cleanup_testfn()
- self.old_argv = sys.argv, sys.argv[:]
-
- def tearDown(self):
- sys.stdout = self.old_stdout
- self.cleanup_testfn()
- sys.argv = self.old_argv[0]
- sys.argv[:] = self.old_argv[1]
- super(CoreTestCase, self).tearDown()
-
- def cleanup_testfn(self):
- path = distutils2.tests.TESTFN
- if os.path.isfile(path):
- os.remove(path)
- elif os.path.isdir(path):
- shutil.rmtree(path)
-
- def write_setup(self, text, path=distutils2.tests.TESTFN):
- open(path, "w").write(text)
- return path
-
- def test_run_setup_provides_file(self):
- # Make sure the script can use __file__; if that's missing, the test
- # setup.py script will raise NameError.
- distutils2.core.run_setup(
- self.write_setup(setup_using___file__))
-
- def test_run_setup_stop_after(self):
- f = self.write_setup(setup_using___file__)
- for s in ['init', 'config', 'commandline', 'run']:
- distutils2.core.run_setup(f, stop_after=s)
- self.assertRaises(ValueError, distutils2.core.run_setup,
- f, stop_after='bob')
-
- def test_run_setup_args(self):
- f = self.write_setup(setup_using___file__)
- d = distutils2.core.run_setup(f, script_args=["--help"],
- stop_after="init")
- self.assertEqual(['--help'], d.script_args)
-
- def test_run_setup_uses_current_dir(self):
- # This tests that the setup script is run with the current directory
- # as its own current directory; this was temporarily broken by a
- # previous patch when TESTFN did not use the current directory.
- sys.stdout = StringIO.StringIO()
- cwd = os.getcwd()
-
- # Create a directory and write the setup.py file there:
- os.mkdir(distutils2.tests.TESTFN)
- setup_py = os.path.join(distutils2.tests.TESTFN, "setup.py")
- distutils2.core.run_setup(
- self.write_setup(setup_prints_cwd, path=setup_py))
-
- output = sys.stdout.getvalue()
- if output.endswith("\n"):
- output = output[:-1]
- self.assertEqual(cwd, output)
-
-def test_suite():
- return unittest.makeSuite(CoreTestCase)
-
-if __name__ == "__main__":
- unittest.main(defaultTest="test_suite")
diff --git a/src/distutils2/tests/test_cygwinccompiler.py b/src/distutils2/tests/test_cygwinccompiler.py
deleted file mode 100644
index 5516fbd..0000000
--- a/src/distutils2/tests/test_cygwinccompiler.py
+++ /dev/null
@@ -1,99 +0,0 @@
-"""Tests for distutils.cygwinccompiler."""
-import sys
-import os
-try:
- import sysconfig
-except ImportError:
- from distutils2._backport import sysconfig
-
-from distutils2.tests import run_unittest
-from distutils2.tests import captured_stdout
-
-from distutils2.compiler import cygwinccompiler
-from distutils2.compiler.cygwinccompiler import (CygwinCCompiler, check_config_h,
- CONFIG_H_OK, CONFIG_H_NOTOK,
- CONFIG_H_UNCERTAIN, get_versions,
- get_msvcr, RE_VERSION)
-from distutils2.util import get_compiler_versions
-from distutils2.tests import support
-from distutils2.tests.support import unittest
-
-class CygwinCCompilerTestCase(support.TempdirManager,
- unittest.TestCase):
-
- def setUp(self):
- super(CygwinCCompilerTestCase, self).setUp()
- self.version = sys.version
- self.python_h = os.path.join(self.mkdtemp(), 'python.h')
- self.old_get_config_h_filename = sysconfig.get_config_h_filename
- sysconfig.get_config_h_filename = self._get_config_h_filename
-
- def tearDown(self):
- sys.version = self.version
- sysconfig.get_config_h_filename = self.old_get_config_h_filename
- super(CygwinCCompilerTestCase, self).tearDown()
-
- def _get_config_h_filename(self):
- return self.python_h
-
- def test_check_config_h(self):
-
- # check_config_h looks for "GCC" in sys.version first
- # returns CONFIG_H_OK if found
- sys.version = ('2.6.1 (r261:67515, Dec 6 2008, 16:42:21) \n[GCC '
- '4.0.1 (Apple Computer, Inc. build 5370)]')
-
- self.assertEqual(check_config_h()[0], CONFIG_H_OK)
-
- # then it tries to see if it can find "__GNUC__" in pyconfig.h
- sys.version = 'something without the *CC word'
-
- # if the file doesn't exist it returns CONFIG_H_UNCERTAIN
- self.assertEqual(check_config_h()[0], CONFIG_H_UNCERTAIN)
-
- # if it exists but does not contain __GNUC__, it returns CONFIG_H_NOTOK
- self.write_file(self.python_h, 'xxx')
- self.assertEqual(check_config_h()[0], CONFIG_H_NOTOK)
-
- # and CONFIG_H_OK if __GNUC__ is found
- self.write_file(self.python_h, 'xxx __GNUC__ xxx')
- self.assertEqual(check_config_h()[0], CONFIG_H_OK)
-
- def test_get_msvcr(self):
-
- # none
- sys.version = ('2.6.1 (r261:67515, Dec 6 2008, 16:42:21) '
- '\n[GCC 4.0.1 (Apple Computer, Inc. build 5370)]')
- self.assertEqual(get_msvcr(), None)
-
- # MSVC 7.0
- sys.version = ('2.5.1 (r251:54863, Apr 18 2007, 08:51:08) '
- '[MSC v.1300 32 bits (Intel)]')
- self.assertEqual(get_msvcr(), ['msvcr70'])
-
- # MSVC 7.1
- sys.version = ('2.5.1 (r251:54863, Apr 18 2007, 08:51:08) '
- '[MSC v.1310 32 bits (Intel)]')
- self.assertEqual(get_msvcr(), ['msvcr71'])
-
- # VS2005 / MSVC 8.0
- sys.version = ('2.5.1 (r251:54863, Apr 18 2007, 08:51:08) '
- '[MSC v.1400 32 bits (Intel)]')
- self.assertEqual(get_msvcr(), ['msvcr80'])
-
- # VS2008 / MSVC 9.0
- sys.version = ('2.5.1 (r251:54863, Apr 18 2007, 08:51:08) '
- '[MSC v.1500 32 bits (Intel)]')
- self.assertEqual(get_msvcr(), ['msvcr90'])
-
- # unknown
- sys.version = ('2.5.1 (r251:54863, Apr 18 2007, 08:51:08) '
- '[MSC v.1999 32 bits (Intel)]')
- self.assertRaises(ValueError, get_msvcr)
-
-
-def test_suite():
- return unittest.makeSuite(CygwinCCompilerTestCase)
-
-if __name__ == '__main__':
- run_unittest(test_suite())
diff --git a/src/distutils2/tests/test_depgraph.py b/src/distutils2/tests/test_depgraph.py
deleted file mode 100644
index fa38b91..0000000
--- a/src/distutils2/tests/test_depgraph.py
+++ /dev/null
@@ -1,187 +0,0 @@
-"""Tests for distutils.depgraph """
-
-from distutils2.tests import support
-from distutils2.tests.support import unittest
-from distutils2 import depgraph
-from distutils2._backport import pkgutil
-
-import os
-import sys
-import re
-try:
- import cStringIO as StringIO
-except ImportError:
- import StringIO
-
-class DepGraphTestCase(support.LoggingCatcher,
- unittest.TestCase):
-
- DISTROS_DIST = ('choxie', 'grammar', 'towel-stuff')
- DISTROS_EGG = ('bacon', 'banana', 'strawberry', 'cheese')
- EDGE = re.compile(
- r'"(?P<from>.*)" -> "(?P<to>.*)" \[label="(?P<label>.*)"\]'
- )
-
- def checkLists(self, l1, l2):
- """ Compare two lists without taking the order into consideration """
- self.assertListEqual(sorted(l1), sorted(l2))
-
- def setUp(self):
- super(DepGraphTestCase, self).setUp()
- path = os.path.join(os.path.dirname(__file__), '..', '_backport',
- 'tests', 'fake_dists')
- path = os.path.abspath(path)
- self.sys_path = sys.path[:]
- sys.path[0:0] = [path]
-
- def test_generate_graph(self):
- dists = []
- for name in self.DISTROS_DIST:
- dist = pkgutil.get_distribution(name)
- self.assertNotEqual(dist, None)
- dists.append(dist)
-
- choxie, grammar, towel = dists
-
- graph = depgraph.generate_graph(dists)
-
- deps = [(x.name, y) for (x,y) in graph.adjacency_list[choxie]]
- self.checkLists([('towel-stuff', 'towel-stuff (0.1)')], deps)
- self.assertTrue(choxie in graph.reverse_list[towel])
- self.checkLists(graph.missing[choxie], [])
-
- deps = [(x.name, y) for (x,y) in graph.adjacency_list[grammar]]
- self.checkLists([], deps)
- self.checkLists(graph.missing[grammar], ['truffles (>=1.2)'])
-
- deps = [(x.name, y) for (x,y) in graph.adjacency_list[towel]]
- self.checkLists([], deps)
- self.checkLists(graph.missing[towel], ['bacon (<=0.2)'])
-
- def test_generate_graph_egg(self):
- dists = []
- for name in self.DISTROS_DIST + self.DISTROS_EGG:
- dist = pkgutil.get_distribution(name, use_egg_info=True)
- self.assertNotEqual(dist, None)
- dists.append(dist)
-
- choxie, grammar, towel, bacon, banana, strawberry, cheese = dists
-
- graph = depgraph.generate_graph(dists)
-
- deps = [(x.name, y) for (x,y) in graph.adjacency_list[choxie]]
- self.checkLists([('towel-stuff', 'towel-stuff (0.1)')], deps)
- self.assertTrue(choxie in graph.reverse_list[towel])
- self.checkLists(graph.missing[choxie], [])
-
- deps = [(x.name, y) for (x,y) in graph.adjacency_list[grammar]]
- self.checkLists([('bacon', 'truffles (>=1.2)')], deps)
- self.checkLists(graph.missing[grammar], [])
- self.assertTrue(grammar in graph.reverse_list[bacon])
-
- deps = [(x.name, y) for (x,y) in graph.adjacency_list[towel]]
- self.checkLists([('bacon', 'bacon (<=0.2)')], deps)
- self.checkLists(graph.missing[towel], [])
- self.assertTrue(towel in graph.reverse_list[bacon])
-
- deps = [(x.name, y) for (x,y) in graph.adjacency_list[bacon]]
- self.checkLists([], deps)
- self.checkLists(graph.missing[bacon], [])
-
- deps = [(x.name, y) for (x,y) in graph.adjacency_list[banana]]
- self.checkLists([('strawberry', 'strawberry (>=0.5)')], deps)
- self.checkLists(graph.missing[banana], [])
- self.assertTrue(banana in graph.reverse_list[strawberry])
-
- deps = [(x.name, y) for (x,y) in graph.adjacency_list[strawberry]]
- self.checkLists([], deps)
- self.checkLists(graph.missing[strawberry], [])
-
- deps = [(x.name, y) for (x,y) in graph.adjacency_list[cheese]]
- self.checkLists([], deps)
- self.checkLists(graph.missing[cheese], [])
-
- def test_dependent_dists(self):
- dists = []
- for name in self.DISTROS_DIST:
- dist = pkgutil.get_distribution(name)
- self.assertNotEqual(dist, None)
- dists.append(dist)
-
- choxie, grammar, towel = dists
-
- deps = [d.name for d in depgraph.dependent_dists(dists, choxie)]
- self.checkLists([], deps)
-
- deps = [d.name for d in depgraph.dependent_dists(dists, grammar)]
- self.checkLists([], deps)
-
- deps = [d.name for d in depgraph.dependent_dists(dists, towel)]
- self.checkLists(['choxie'], deps)
-
-
- def test_dependent_dists_egg(self):
- dists = []
- for name in self.DISTROS_DIST + self.DISTROS_EGG:
- dist = pkgutil.get_distribution(name, use_egg_info=True)
- self.assertNotEqual(dist, None)
- dists.append(dist)
-
- choxie, grammar, towel, bacon, banana, strawberry, cheese = dists
-
- deps = [d.name for d in depgraph.dependent_dists(dists, choxie)]
- self.checkLists([], deps)
-
- deps = [d.name for d in depgraph.dependent_dists(dists, grammar)]
- self.checkLists([], deps)
-
- deps = [d.name for d in depgraph.dependent_dists(dists, towel)]
- self.checkLists(['choxie'], deps)
-
- deps = [d.name for d in depgraph.dependent_dists(dists, bacon)]
- self.checkLists(['choxie', 'towel-stuff', 'grammar'], deps)
-
- deps = [d.name for d in depgraph.dependent_dists(dists, strawberry)]
- self.checkLists(['banana'], deps)
-
- deps = [d.name for d in depgraph.dependent_dists(dists, cheese)]
- self.checkLists([], deps)
-
- def test_graph_to_dot(self):
- expected = (
- ('towel-stuff', 'bacon', 'bacon (<=0.2)'),
- ('grammar', 'bacon', 'truffles (>=1.2)'),
- ('choxie', 'towel-stuff', 'towel-stuff (0.1)'),
- ('banana', 'strawberry', 'strawberry (>=0.5)')
- )
-
- dists = []
- for name in self.DISTROS_DIST + self.DISTROS_EGG:
- dist = pkgutil.get_distribution(name, use_egg_info=True)
- self.assertNotEqual(dist, None)
- dists.append(dist)
-
- graph = depgraph.generate_graph(dists)
- buf = StringIO.StringIO()
- depgraph.graph_to_dot(graph, buf)
- buf.seek(0)
- matches = []
- lines = buf.readlines()
- for line in lines[1:-1]: # skip the first and the last lines
- if line[-1] == '\n':
- line = line[:-1]
- match = self.EDGE.match(line.strip())
- self.assertTrue(match is not None)
- matches.append(match.groups())
-
- self.checkLists(matches, expected)
-
- def tearDown(self):
- super(DepGraphTestCase, self).tearDown()
- sys.path = self.sys_path
-
-def test_suite():
- return unittest.makeSuite(DepGraphTestCase)
-
-if __name__ == "__main__":
- unittest.main(defaultTest="test_suite")
diff --git a/src/distutils2/tests/test_dist.py b/src/distutils2/tests/test_dist.py
deleted file mode 100644
index 4cbcbad..0000000
--- a/src/distutils2/tests/test_dist.py
+++ /dev/null
@@ -1,533 +0,0 @@
-# -*- coding: utf-8 -*-
-
-"""Tests for distutils2.dist."""
-import os
-import StringIO
-import sys
-import textwrap
-
-import distutils2.dist
-from distutils2.dist import Distribution, fix_help_options
-from distutils2.command.cmd import Command
-from distutils2.errors import DistutilsModuleError, DistutilsOptionError
-from distutils2.tests import TESTFN, captured_stdout
-from distutils2.tests import support
-from distutils2.tests.support import unittest, create_distribution
-
-
-class test_dist(Command):
- """Sample distutils2 extension command."""
-
- user_options = [
- ("sample-option=", "S", "help text"),
- ]
-
- def initialize_options(self):
- self.sample_option = None
-
- def finalize_options(self):
- pass
-
-
-class DistributionTestCase(support.TempdirManager,
- support.LoggingCatcher,
- support.WarningsCatcher,
- support.EnvironGuard,
- unittest.TestCase):
-
- def setUp(self):
- super(DistributionTestCase, self).setUp()
- self.argv = sys.argv, sys.argv[:]
- del sys.argv[1:]
-
- def tearDown(self):
- sys.argv = self.argv[0]
- sys.argv[:] = self.argv[1]
- super(DistributionTestCase, self).tearDown()
-
- def test_debug_mode(self):
- self.addCleanup(os.unlink, TESTFN)
- f = open(TESTFN, "w")
- try:
- f.write("[global]\n")
- f.write("command_packages = foo.bar, splat")
- finally:
- f.close()
-
- files = [TESTFN]
- sys.argv.append("build")
-
- __, stdout = captured_stdout(create_distribution, files)
- self.assertEqual(stdout, '')
- distutils2.dist.DEBUG = True
- try:
- __, stdout = captured_stdout(create_distribution, files)
- self.assertEqual(stdout, '')
- finally:
- distutils2.dist.DEBUG = False
-
- def test_command_packages_unspecified(self):
- sys.argv.append("build")
- d = create_distribution()
- self.assertEqual(d.get_command_packages(), ["distutils2.command"])
-
- def test_command_packages_cmdline(self):
- from distutils2.tests.test_dist import test_dist
- sys.argv.extend(["--command-packages",
- "foo.bar,distutils2.tests",
- "test_dist",
- "-Ssometext",
- ])
- d = create_distribution()
- # let's actually try to load our test command:
- self.assertEqual(d.get_command_packages(),
- ["distutils2.command", "foo.bar", "distutils2.tests"])
- cmd = d.get_command_obj("test_dist")
- self.assertTrue(isinstance(cmd, test_dist))
- self.assertEqual(cmd.sample_option, "sometext")
-
- def test_command_packages_configfile(self):
- sys.argv.append("build")
- f = open(TESTFN, "w")
- try:
- print >> f, "[global]"
- print >> f, "command_packages = foo.bar, splat"
- f.close()
- d = create_distribution([TESTFN])
- self.assertEqual(d.get_command_packages(),
- ["distutils2.command", "foo.bar", "splat"])
-
- # ensure command line overrides config:
- sys.argv[1:] = ["--command-packages", "spork", "build"]
- d = create_distribution([TESTFN])
- self.assertEqual(d.get_command_packages(),
- ["distutils2.command", "spork"])
-
- # Setting --command-packages to '' should cause the default to
- # be used even if a config file specified something else:
- sys.argv[1:] = ["--command-packages", "", "build"]
- d = create_distribution([TESTFN])
- self.assertEqual(d.get_command_packages(), ["distutils2.command"])
-
- finally:
- os.unlink(TESTFN)
-
- def test_write_pkg_file(self):
- # Check DistributionMetadata handling of Unicode fields
- tmp_dir = self.mkdtemp()
- my_file = os.path.join(tmp_dir, 'f')
- cls = Distribution
-
- dist = cls(attrs={'author': u'Mister Café',
- 'name': 'my.package',
- 'maintainer': u'Café Junior',
- 'summary': u'Café torréfié',
- 'description': u'Héhéhé'})
-
- # let's make sure the file can be written
- # with Unicode fields. they are encoded with
- # PKG_INFO_ENCODING
- dist.metadata.write_file(open(my_file, 'w'))
-
- # regular ascii is of course always usable
- dist = cls(attrs={'author': 'Mister Cafe',
- 'name': 'my.package',
- 'maintainer': 'Cafe Junior',
- 'summary': 'Cafe torrefie',
- 'description': 'Hehehe'})
-
- dist.metadata.write_file(open(my_file, 'w'))
-
- def test_bad_attr(self):
- Distribution(attrs={'author': 'xxx',
- 'name': 'xxx',
- 'version': 'xxx',
- 'url': 'xxxx',
- 'badoptname': 'xxx'})
-
- self.assertEqual(len(self.warnings), 1)
- self.assertIn("Unknown distribution",
- self.warnings[0]['message'].args[0])
-
- def test_empty_options(self):
- # an empty options dictionary should not stay in the
- # list of attributes
- Distribution(attrs={'author': 'xxx',
- 'name': 'xxx',
- 'version': 'xxx',
- 'url': 'xxxx',
- 'options': {}})
-
- self.assertEqual(len(self.warnings), 0)
-
- def test_non_empty_options(self):
- # TODO: how to actually use options is not documented except
- # for a few cryptic comments in dist.py. If this is to stay
- # in the public API, it deserves some better documentation.
-
- # Here is an example of how it's used out there:
- # http://svn.pythonmac.org/py2app/py2app/trunk/doc/
- # index.html#specifying-customizations
- dist = Distribution(attrs={'author': 'xxx',
- 'name': 'xxx',
- 'version': 'xxx',
- 'url': 'xxxx',
- 'options': {'sdist': {'owner': 'root'}}})
-
- self.assertIn('owner', dist.get_option_dict('sdist'))
-
- def test_finalize_options(self):
-
- attrs = {'keywords': 'one,two',
- 'platform': 'one,two'}
-
- dist = Distribution(attrs=attrs)
- dist.finalize_options()
-
- # finalize_option splits platforms and keywords
- self.assertEqual(dist.metadata['platform'], ['one', 'two'])
- self.assertEqual(dist.metadata['keywords'], ['one', 'two'])
-
- def test_get_command_packages(self):
- dist = Distribution()
- self.assertEqual(dist.command_packages, None)
- cmds = dist.get_command_packages()
- self.assertEqual(cmds, ['distutils2.command'])
- self.assertEqual(dist.command_packages,
- ['distutils2.command'])
-
- dist.command_packages = 'one,two'
- cmds = dist.get_command_packages()
- self.assertEqual(cmds, ['distutils2.command', 'one', 'two'])
-
- def test_announce(self):
- # make sure the level is known
- dist = Distribution()
- args = ('ok',)
- kwargs = {'level': 'ok2'}
- self.assertRaises(ValueError, dist.announce, args, kwargs)
-
- def test_find_config_files_disable(self):
- # Bug #1180: Allow users to disable their own config file.
- temp_home = self.mkdtemp()
- if os.name == 'posix':
- user_filename = os.path.join(temp_home, ".pydistutils.cfg")
- else:
- user_filename = os.path.join(temp_home, "pydistutils.cfg")
-
- f = open(user_filename, 'w')
- try:
- f.write('[distutils2]\n')
- finally:
- f.close()
-
- def _expander(path):
- return temp_home
-
- old_expander = os.path.expanduser
- os.path.expanduser = _expander
- try:
- d = distutils2.dist.Distribution()
- all_files = d.find_config_files()
-
- d = distutils2.dist.Distribution(attrs={'script_args':
- ['--no-user-cfg']})
- files = d.find_config_files()
- finally:
- os.path.expanduser = old_expander
-
- # make sure --no-user-cfg disables the user cfg file
- self.assertEqual(len(all_files) - 1, len(files))
-
- def test_special_hooks_parsing(self):
- temp_home = self.mkdtemp()
- config_files = [os.path.join(temp_home, "config1.cfg"),
- os.path.join(temp_home, "config2.cfg")]
-
- # Store two aliased hooks in config files
- self.write_file((temp_home, "config1.cfg"),
- '[test_dist]\npre-hook.a = type')
- self.write_file((temp_home, "config2.cfg"),
- '[test_dist]\npre-hook.b = type')
-
- sys.argv.extend(["--command-packages",
- "distutils2.tests",
- "test_dist"])
- dist = create_distribution(config_files)
- cmd = dist.get_command_obj("test_dist")
-
- self.assertEqual(cmd.pre_hook, {"a": 'type', "b": 'type'})
-
- def test_hooks_get_run(self):
- temp_home = self.mkdtemp()
- config_file = os.path.join(temp_home, "config1.cfg")
- hooks_module = os.path.join(temp_home, "testhooks.py")
-
- self.write_file(config_file, textwrap.dedent('''
- [test_dist]
- pre-hook.test = testhooks.log_pre_call
- post-hook.test = testhooks.log_post_call'''))
-
- self.write_file(hooks_module, textwrap.dedent('''
- record = []
-
- def log_pre_call(cmd):
- record.append('pre-%s' % cmd.get_command_name())
-
- def log_post_call(cmd):
- record.append('post-%s' % cmd.get_command_name())
- '''))
-
- sys.argv.extend(["--command-packages",
- "distutils2.tests",
- "test_dist"])
-
- d = create_distribution([config_file])
- cmd = d.get_command_obj("test_dist")
-
- # prepare the call recorders
- sys.path.append(temp_home)
- from testhooks import record
-
- self.addCleanup(setattr, cmd, 'run', cmd.run)
- self.addCleanup(setattr, cmd, 'finalize_options',
- cmd.finalize_options)
-
- cmd.run = lambda: record.append('run')
- cmd.finalize_options = lambda: record.append('finalize')
-
- d.run_command('test_dist')
-
- self.assertEqual(record, ['finalize',
- 'pre-test_dist',
- 'run',
- 'post-test_dist'])
-
- def test_hooks_importable(self):
- temp_home = self.mkdtemp()
- config_file = os.path.join(temp_home, "config1.cfg")
-
- self.write_file(config_file, textwrap.dedent('''
- [test_dist]
- pre-hook.test = nonexistent.dotted.name'''))
-
- sys.argv.extend(["--command-packages",
- "distutils2.tests",
- "test_dist"])
-
- d = create_distribution([config_file])
- cmd = d.get_command_obj("test_dist")
- cmd.ensure_finalized()
-
- self.assertRaises(DistutilsModuleError, d.run_command, 'test_dist')
-
- def test_hooks_callable(self):
- temp_home = self.mkdtemp()
- config_file = os.path.join(temp_home, "config1.cfg")
-
- self.write_file(config_file, textwrap.dedent('''
- [test_dist]
- pre-hook.test = distutils2.tests.test_dist.__doc__'''))
-
- sys.argv.extend(["--command-packages",
- "distutils2.tests",
- "test_dist"])
-
- d = create_distribution([config_file])
- cmd = d.get_command_obj("test_dist")
- cmd.ensure_finalized()
-
- self.assertRaises(DistutilsOptionError, d.run_command, 'test_dist')
-
-
-class MetadataTestCase(support.TempdirManager, support.EnvironGuard,
- support.LoggingCatcher, unittest.TestCase):
-
- def setUp(self):
- super(MetadataTestCase, self).setUp()
- self.argv = sys.argv, sys.argv[:]
-
- def tearDown(self):
- sys.argv = self.argv[0]
- sys.argv[:] = self.argv[1]
- super(MetadataTestCase, self).tearDown()
-
- def test_simple_metadata(self):
- attrs = {"name": "package",
- "version": "1.0"}
- dist = Distribution(attrs)
- meta = self.format_metadata(dist)
- self.assertTrue("Metadata-Version: 1.0" in meta)
- self.assertTrue("provides:" not in meta.lower())
- self.assertTrue("requires:" not in meta.lower())
- self.assertTrue("obsoletes:" not in meta.lower())
-
- def test_provides_dist(self):
- attrs = {"name": "package",
- "version": "1.0",
- "provides_dist": ["package", "package.sub"]}
- dist = Distribution(attrs)
- self.assertEqual(dist.metadata['Provides-Dist'],
- ["package", "package.sub"])
- meta = self.format_metadata(dist)
- self.assertTrue("Metadata-Version: 1.2" in meta)
- self.assertTrue("requires:" not in meta.lower())
- self.assertTrue("obsoletes:" not in meta.lower())
-
- def _test_provides_illegal(self):
- # XXX to do: check the versions
- self.assertRaises(ValueError, Distribution,
- {"name": "package",
- "version": "1.0",
- "provides_dist": ["my.pkg (splat)"]})
-
- def test_requires_dist(self):
- attrs = {"name": "package",
- "version": "1.0",
- "requires_dist": ["other", "another (==1.0)"]}
- dist = Distribution(attrs)
- self.assertEqual(dist.metadata['Requires-Dist'],
- ["other", "another (==1.0)"])
- meta = self.format_metadata(dist)
- self.assertTrue("Metadata-Version: 1.2" in meta)
- self.assertTrue("provides:" not in meta.lower())
- self.assertTrue("Requires-Dist: other" in meta)
- self.assertTrue("Requires-Dist: another (==1.0)" in meta)
- self.assertTrue("obsoletes:" not in meta.lower())
-
- def _test_requires_illegal(self):
- # XXX
- self.assertRaises(ValueError, Distribution,
- {"name": "package",
- "version": "1.0",
- "requires": ["my.pkg (splat)"]})
-
- def test_obsoletes_dist(self):
- attrs = {"name": "package",
- "version": "1.0",
- "obsoletes_dist": ["other", "another (<1.0)"]}
- dist = Distribution(attrs)
- self.assertEqual(dist.metadata['Obsoletes-Dist'],
- ["other", "another (<1.0)"])
- meta = self.format_metadata(dist)
- self.assertTrue("Metadata-Version: 1.2" in meta)
- self.assertTrue("provides:" not in meta.lower())
- self.assertTrue("requires:" not in meta.lower())
- self.assertTrue("Obsoletes-Dist: other" in meta)
- self.assertTrue("Obsoletes-Dist: another (<1.0)" in meta)
-
- def _test_obsoletes_illegal(self):
- # XXX
- self.assertRaises(ValueError, Distribution,
- {"name": "package",
- "version": "1.0",
- "obsoletes": ["my.pkg (splat)"]})
-
- def format_metadata(self, dist):
- sio = StringIO.StringIO()
- dist.metadata.write_file(sio)
- return sio.getvalue()
-
- def test_custom_pydistutils(self):
- # fixes #2166
- # make sure pydistutils.cfg is found
- if os.name == 'posix':
- user_filename = ".pydistutils.cfg"
- else:
- user_filename = "pydistutils.cfg"
-
- temp_dir = self.mkdtemp()
- user_filename = os.path.join(temp_dir, user_filename)
- f = open(user_filename, 'w')
- try:
- f.write('.')
- finally:
- f.close()
-
- try:
- dist = Distribution()
-
- # linux-style
- if sys.platform in ('linux', 'darwin'):
- os.environ['HOME'] = temp_dir
- files = dist.find_config_files()
- self.assertTrue(user_filename in files)
-
- # win32-style
- if sys.platform == 'win32':
- # home drive should be found
- os.environ['HOME'] = temp_dir
- files = dist.find_config_files()
- self.assertTrue(user_filename in files,
- '%r not found in %r' % (user_filename, files))
- finally:
- os.remove(user_filename)
-
- def test_fix_help_options(self):
- help_tuples = [('a', 'b', 'c', 'd'), (1, 2, 3, 4)]
- fancy_options = fix_help_options(help_tuples)
- self.assertEqual(fancy_options[0], ('a', 'b', 'c'))
- self.assertEqual(fancy_options[1], (1, 2, 3))
-
- def test_show_help(self):
- # smoke test, just makes sure some help is displayed
- dist = Distribution()
- sys.argv = []
- dist.help = 1
- dist.script_name = 'setup.py'
- __, stdout = captured_stdout(dist.parse_command_line)
- output = [line for line in stdout.split('\n')
- if line.strip() != '']
- self.assertTrue(len(output) > 0)
-
- def test_description(self):
- desc = textwrap.dedent("""\
- example::
- We start here
- and continue here
- and end here.""")
- attrs = {"name": "package",
- "version": "1.0",
- "description": desc}
-
- dist = distutils2.dist.Distribution(attrs)
- meta = self.format_metadata(dist)
- meta = meta.replace('\n' + 7 * ' ' + '|', '\n')
- self.assertTrue(desc in meta)
-
- def test_read_metadata(self):
- attrs = {"name": "package",
- "version": "1.0",
- "description": "desc",
- "summary": "xxx",
- "download_url": "http://example.com",
- "keywords": ['one', 'two'],
- "requires_dist": ['foo']}
-
- dist = Distribution(attrs)
- metadata = dist.metadata
-
- # write it then reloads it
- PKG_INFO = StringIO.StringIO()
- metadata.write_file(PKG_INFO)
- PKG_INFO.seek(0)
-
- metadata.read_file(PKG_INFO)
- self.assertEqual(metadata['name'], "package")
- self.assertEqual(metadata['version'], "1.0")
- self.assertEqual(metadata['summary'], "xxx")
- self.assertEqual(metadata['download_url'], 'http://example.com')
- self.assertEqual(metadata['keywords'], ['one', 'two'])
- self.assertEqual(metadata['platform'], [])
- self.assertEqual(metadata['obsoletes'], [])
- self.assertEqual(metadata['requires-dist'], ['foo'])
-
-
-def test_suite():
- suite = unittest.TestSuite()
- suite.addTest(unittest.makeSuite(DistributionTestCase))
- suite.addTest(unittest.makeSuite(MetadataTestCase))
- return suite
-
-if __name__ == "__main__":
- unittest.main(defaultTest="test_suite")
diff --git a/src/distutils2/tests/test_emxccompiler.py b/src/distutils2/tests/test_emxccompiler.py
deleted file mode 100644
index 5b042dc..0000000
--- a/src/distutils2/tests/test_emxccompiler.py
+++ /dev/null
@@ -1,22 +0,0 @@
-"""Tests for distutils.emxccompiler."""
-import sys
-import os
-
-from distutils2.tests import run_unittest
-from distutils2.tests import captured_stdout
-
-from distutils2.compiler.emxccompiler import get_versions
-from distutils2.util import get_compiler_versions
-from distutils2.tests import support
-from distutils2.tests.support import unittest
-
-class EmxCCompilerTestCase(support.TempdirManager,
- unittest.TestCase):
-
- pass
-
-def test_suite():
- return unittest.makeSuite(EmxCCompilerTestCase)
-
-if __name__ == '__main__':
- run_unittest(test_suite())
diff --git a/src/distutils2/tests/test_extension.py b/src/distutils2/tests/test_extension.py
deleted file mode 100644
index d98ce43..0000000
--- a/src/distutils2/tests/test_extension.py
+++ /dev/null
@@ -1,15 +0,0 @@
-"""Tests for distutils.extension."""
-import os
-
-from distutils2.extension import Extension
-from distutils2.tests.support import unittest
-
-class ExtensionTestCase(unittest.TestCase):
-
- pass
-
-def test_suite():
- return unittest.makeSuite(ExtensionTestCase)
-
-if __name__ == "__main__":
- unittest.main(defaultTest="test_suite")
diff --git a/src/distutils2/tests/test_index_dist.py b/src/distutils2/tests/test_index_dist.py
deleted file mode 100644
index 9020635..0000000
--- a/src/distutils2/tests/test_index_dist.py
+++ /dev/null
@@ -1,248 +0,0 @@
-"""Tests for the distutils2.index.dist module."""
-
-import os
-
-from distutils2.tests.pypi_server import use_pypi_server
-from distutils2.tests import run_unittest
-from distutils2.tests.support import unittest, TempdirManager
-from distutils2.version import VersionPredicate
-from distutils2.index.errors import HashDoesNotMatch, UnsupportedHashName
-from distutils2.index.dist import (ReleaseInfo, ReleasesList, DistInfo,
- split_archive_name, get_infos_from_url)
-
-
-def Dist(*args, **kwargs):
- # DistInfo takes a release as a first parameter, avoid this in tests.
- return DistInfo(None, *args, **kwargs)
-
-
-class TestReleaseInfo(unittest.TestCase):
-
- def test_instantiation(self):
- # Test the DistInfo class provides us the good attributes when
- # given on construction
- release = ReleaseInfo("FooBar", "1.1")
- self.assertEqual("FooBar", release.name)
- self.assertEqual("1.1", "%s" % release.version)
-
- def test_add_dist(self):
- # empty distribution type should assume "sdist"
- release = ReleaseInfo("FooBar", "1.1")
- release.add_distribution(url="http://example.org/")
- # should not fail
- release['sdist']
-
- def test_get_unknown_distribution(self):
- # should raise a KeyError
- pass
-
- def test_get_infos_from_url(self):
- # Test that the the URLs are parsed the right way
- url_list = {
- 'FooBar-1.1.0.tar.gz': {
- 'name': 'foobar', # lowercase the name
- 'version': '1.1.0',
- },
- 'Foo-Bar-1.1.0.zip': {
- 'name': 'foo-bar', # keep the dash
- 'version': '1.1.0',
- },
- 'foobar-1.1b2.tar.gz#md5=123123123123123': {
- 'name': 'foobar',
- 'version': '1.1b2',
- 'url': 'http://example.org/foobar-1.1b2.tar.gz', # no hash
- 'hashval': '123123123123123',
- 'hashname': 'md5',
- },
- 'foobar-1.1-rc2.tar.gz': { # use suggested name
- 'name': 'foobar',
- 'version': '1.1c2',
- 'url': 'http://example.org/foobar-1.1-rc2.tar.gz',
- }
- }
-
- for url, attributes in url_list.items():
- # for each url
- infos = get_infos_from_url("http://example.org/" + url)
- for attribute, expected in attributes.items():
- got = infos.get(attribute)
- if attribute == "version":
- self.assertEqual("%s" % got, expected)
- else:
- self.assertEqual(got, expected)
-
- def test_split_archive_name(self):
- # Test we can split the archive names
- names = {
- 'foo-bar-baz-1.0-rc2': ('foo-bar-baz', '1.0c2'),
- 'foo-bar-baz-1.0': ('foo-bar-baz', '1.0'),
- 'foobarbaz-1.0': ('foobarbaz', '1.0'),
- }
- for name, results in names.items():
- self.assertEqual(results, split_archive_name(name))
-
-
-class TestDistInfo(TempdirManager, unittest.TestCase):
-
- def test_get_url(self):
- # Test that the url property works well
-
- d = Dist(url="test_url")
- self.assertDictEqual(d.url, {
- "url": "test_url",
- "is_external": True,
- "hashname": None,
- "hashval": None,
- })
-
- # add a new url
- d.add_url(url="internal_url", is_external=False)
- self.assertEqual(d._url, None)
- self.assertDictEqual(d.url, {
- "url": "internal_url",
- "is_external": False,
- "hashname": None,
- "hashval": None,
- })
- self.assertEqual(2, len(d.urls))
-
- def test_comparison(self):
- # Test that we can compare DistInfoributionInfoList
- foo1 = ReleaseInfo("foo", "1.0")
- foo2 = ReleaseInfo("foo", "2.0")
- bar = ReleaseInfo("bar", "2.0")
- # assert we use the version to compare
- self.assertTrue(foo1 < foo2)
- self.assertFalse(foo1 > foo2)
- self.assertFalse(foo1 == foo2)
-
- # assert we can't compare dists with different names
- self.assertRaises(TypeError, foo1.__eq__, bar)
-
- @use_pypi_server("downloads_with_md5")
- def test_download(self, server):
- # Download is possible, and the md5 is checked if given
-
- url = "%s/simple/foobar/foobar-0.1.tar.gz" % server.full_address
- # check md5 if given
- dist = Dist(url=url, hashname="md5",
- hashval="d41d8cd98f00b204e9800998ecf8427e")
- dist.download(self.mkdtemp())
-
- # a wrong md5 fails
- dist2 = Dist(url=url, hashname="md5", hashval="wrongmd5")
-
- self.assertRaises(HashDoesNotMatch, dist2.download, self.mkdtemp())
-
- # we can omit the md5 hash
- dist3 = Dist(url=url)
- dist3.download(self.mkdtemp())
-
- # and specify a temporary location
- # for an already downloaded dist
- path1 = self.mkdtemp()
- dist3.download(path=path1)
- # and for a new one
- path2_base = self.mkdtemp()
- dist4 = Dist(url=url)
- path2 = dist4.download(path=path2_base)
- self.assertTrue(path2_base in path2)
-
- def test_hashname(self):
- # Invalid hashnames raises an exception on assignation
- Dist(hashname="md5", hashval="value")
-
- self.assertRaises(UnsupportedHashName, Dist,
- hashname="invalid_hashname",
- hashval="value")
-
-
-class TestReleasesList(unittest.TestCase):
-
- def test_filter(self):
- # Test we filter the distributions the right way, using version
- # predicate match method
- releases = ReleasesList('FooBar', (
- ReleaseInfo("FooBar", "1.1"),
- ReleaseInfo("FooBar", "1.1.1"),
- ReleaseInfo("FooBar", "1.2"),
- ReleaseInfo("FooBar", "1.2.1"),
- ))
- filtered = releases.filter(VersionPredicate("FooBar (<1.2)"))
- self.assertNotIn(releases[2], filtered)
- self.assertNotIn(releases[3], filtered)
- self.assertIn(releases[0], filtered)
- self.assertIn(releases[1], filtered)
-
- def test_append(self):
- # When adding a new item to the list, the behavior is to test if
- # a release with the same name and version number already exists,
- # and if so, to add a new distribution for it. If the distribution type
- # is already defined too, add url informations to the existing DistInfo
- # object.
-
- releases = ReleasesList("FooBar", [
- ReleaseInfo("FooBar", "1.1", url="external_url",
- dist_type="sdist"),
- ])
- self.assertEqual(1, len(releases))
- releases.add_release(release=ReleaseInfo("FooBar", "1.1",
- url="internal_url",
- is_external=False,
- dist_type="sdist"))
- self.assertEqual(1, len(releases))
- self.assertEqual(2, len(releases[0]['sdist'].urls))
-
- releases.add_release(release=ReleaseInfo("FooBar", "1.1.1",
- dist_type="sdist"))
- self.assertEqual(2, len(releases))
-
- # when adding a distribution whith a different type, a new distribution
- # has to be added.
- releases.add_release(release=ReleaseInfo("FooBar", "1.1.1",
- dist_type="bdist"))
- self.assertEqual(2, len(releases))
- self.assertEqual(2, len(releases[1].dists))
-
- def test_prefer_final(self):
- # Can order the distributions using prefer_final
-
- fb10 = ReleaseInfo("FooBar", "1.0") # final distribution
- fb11a = ReleaseInfo("FooBar", "1.1a1") # alpha
- fb12a = ReleaseInfo("FooBar", "1.2a1") # alpha
- fb12b = ReleaseInfo("FooBar", "1.2b1") # beta
- dists = ReleasesList("FooBar", [fb10, fb11a, fb12a, fb12b])
-
- dists.sort_releases(prefer_final=True)
- self.assertEqual(fb10, dists[0])
-
- dists.sort_releases(prefer_final=False)
- self.assertEqual(fb12b, dists[0])
-
-# def test_prefer_source(self):
-# # Ordering support prefer_source
-# fb_source = Dist("FooBar", "1.0", type="source")
-# fb_binary = Dist("FooBar", "1.0", type="binary")
-# fb2_binary = Dist("FooBar", "2.0", type="binary")
-# dists = ReleasesList([fb_binary, fb_source])
-#
-# dists.sort_distributions(prefer_source=True)
-# self.assertEqual(fb_source, dists[0])
-#
-# dists.sort_distributions(prefer_source=False)
-# self.assertEqual(fb_binary, dists[0])
-#
-# dists.append(fb2_binary)
-# dists.sort_distributions(prefer_source=True)
-# self.assertEqual(fb2_binary, dists[0])
-
-
-def test_suite():
- suite = unittest.TestSuite()
- suite.addTest(unittest.makeSuite(TestDistInfo))
- suite.addTest(unittest.makeSuite(TestReleaseInfo))
- suite.addTest(unittest.makeSuite(TestReleasesList))
- return suite
-
-if __name__ == '__main__':
- run_unittest(test_suite())
diff --git a/src/distutils2/tests/test_index_simple.py b/src/distutils2/tests/test_index_simple.py
deleted file mode 100644
index d21bda5..0000000
--- a/src/distutils2/tests/test_index_simple.py
+++ /dev/null
@@ -1,316 +0,0 @@
-"""Tests for the pypi.simple module.
-
-"""
-import sys
-import os
-import urllib2
-
-from distutils2.index.simple import Crawler
-from distutils2.tests import support
-from distutils2.tests.support import unittest
-from distutils2.tests.pypi_server import (use_pypi_server, PyPIServer,
- PYPI_DEFAULT_STATIC_PATH)
-
-
-class SimpleCrawlerTestCase(support.TempdirManager, unittest.TestCase):
-
- def _get_simple_crawler(self, server, base_url="/simple/", hosts=None,
- *args, **kwargs):
- """Build and return a SimpleIndex instance, with the test server
- urls
- """
- if hosts is None:
- hosts = (server.full_address.strip("http://"),)
- kwargs['hosts'] = hosts
- return Crawler(server.full_address + base_url, *args,
- **kwargs)
-
- @use_pypi_server()
- def test_bad_urls(self, server):
- crawler = Crawler()
- url = 'http://127.0.0.1:0/nonesuch/test_simple'
- try:
- v = crawler._open_url(url)
- except Exception, v:
- self.assertTrue(url in str(v))
- else:
- self.assertTrue(isinstance(v, urllib2.HTTPError))
-
- # issue 16
- # easy_install inquant.contentmirror.plone breaks because of a typo
- # in its home URL
- crawler = Crawler(hosts=('example.org',))
- url = 'url:%20https://svn.plone.org/svn/collective/inquant.contentmirror.plone/trunk'
- try:
- v = crawler._open_url(url)
- except Exception, v:
- self.assertTrue(url in str(v))
- else:
- self.assertTrue(isinstance(v, urllib2.HTTPError))
-
- def _urlopen(*args):
- import httplib
- raise httplib.BadStatusLine('line')
-
- old_urlopen = urllib2.urlopen
- urllib2.urlopen = _urlopen
- url = 'http://example.org'
- try:
- try:
- v = crawler._open_url(url)
- except Exception, v:
- self.assertTrue('line' in str(v))
- else:
- raise AssertionError('Should have raise here!')
- finally:
- urllib2.urlopen = old_urlopen
-
- # issue 20
- url = 'http://http://svn.pythonpaste.org/Paste/wphp/trunk'
- try:
- crawler._open_url(url)
- except Exception, v:
- self.assertTrue('nonnumeric port' in str(v))
-
- # issue #160
- if sys.version_info[0] == 2 and sys.version_info[1] == 7:
- # this should not fail
- url = server.full_address
- page = ('<a href="http://www.famfamfam.com]('
- 'http://www.famfamfam.com/">')
- crawler._process_url(url, page)
-
- @use_pypi_server("test_found_links")
- def test_found_links(self, server):
- # Browse the index, asking for a specified release version
- # The PyPI index contains links for version 1.0, 1.1, 2.0 and 2.0.1
- crawler = self._get_simple_crawler(server)
- last_release = crawler.get_release("foobar")
-
- # we have scanned the index page
- self.assertIn(server.full_address + "/simple/foobar/",
- crawler._processed_urls)
-
- # we have found 4 releases in this page
- self.assertEqual(len(crawler._projects["foobar"]), 4)
-
- # and returned the most recent one
- self.assertEqual("%s" % last_release.version, '2.0.1')
-
- def test_is_browsable(self):
- crawler = Crawler(follow_externals=False)
- self.assertTrue(crawler._is_browsable(crawler.index_url + "test"))
-
- # Now, when following externals, we can have a list of hosts to trust.
- # and don't follow other external links than the one described here.
- crawler = Crawler(hosts=["pypi.python.org", "example.org"],
- follow_externals=True)
- good_urls = (
- "http://pypi.python.org/foo/bar",
- "http://pypi.python.org/simple/foobar",
- "http://example.org",
- "http://example.org/",
- "http://example.org/simple/",
- )
- bad_urls = (
- "http://python.org",
- "http://example.tld",
- )
-
- for url in good_urls:
- self.assertTrue(crawler._is_browsable(url))
-
- for url in bad_urls:
- self.assertFalse(crawler._is_browsable(url))
-
- # allow all hosts
- crawler = Crawler(follow_externals=True, hosts=("*",))
- self.assertTrue(crawler._is_browsable("http://an-external.link/path"))
- self.assertTrue(crawler._is_browsable("pypi.example.org/a/path"))
-
- # specify a list of hosts we want to allow
- crawler = Crawler(follow_externals=True,
- hosts=("*.example.org",))
- self.assertFalse(crawler._is_browsable("http://an-external.link/path"))
- self.assertTrue(crawler._is_browsable("http://pypi.example.org/a/path"))
-
- @use_pypi_server("with_externals")
- def test_follow_externals(self, server):
- # Include external pages
- # Try to request the package index, wich contains links to "externals"
- # resources. They have to be scanned too.
- crawler = self._get_simple_crawler(server, follow_externals=True)
- crawler.get_release("foobar")
- self.assertIn(server.full_address + "/external/external.html",
- crawler._processed_urls)
-
- @use_pypi_server("with_real_externals")
- def test_restrict_hosts(self, server):
- # Only use a list of allowed hosts is possible
- # Test that telling the simple pyPI client to not retrieve external
- # works
- crawler = self._get_simple_crawler(server, follow_externals=False)
- crawler.get_release("foobar")
- self.assertNotIn(server.full_address + "/external/external.html",
- crawler._processed_urls)
-
- @use_pypi_server(static_filesystem_paths=["with_externals"],
- static_uri_paths=["simple", "external"])
- def test_links_priority(self, server):
- # Download links from the pypi simple index should be used before
- # external download links.
- # http://bitbucket.org/tarek/distribute/issue/163/md5-validation-error
- #
- # Usecase :
- # - someone uploads a package on pypi, a md5 is generated
- # - someone manually coindexes this link (with the md5 in the url) onto
- # an external page accessible from the package page.
- # - someone reuploads the package (with a different md5)
- # - while easy_installing, an MD5 error occurs because the external
- # link is used
- # -> The index should use the link from pypi, not the external one.
-
- # start an index server
- index_url = server.full_address + '/simple/'
-
- # scan a test index
- crawler = Crawler(index_url, follow_externals=True)
- releases = crawler.get_releases("foobar")
- server.stop()
-
- # we have only one link, because links are compared without md5
- self.assertEqual(1, len(releases))
- self.assertEqual(1, len(releases[0].dists))
- # the link should be from the index
- self.assertEqual(2, len(releases[0].dists['sdist'].urls))
- self.assertEqual('12345678901234567',
- releases[0].dists['sdist'].url['hashval'])
- self.assertEqual('md5', releases[0].dists['sdist'].url['hashname'])
-
- @use_pypi_server(static_filesystem_paths=["with_norel_links"],
- static_uri_paths=["simple", "external"])
- def test_not_scan_all_links(self, server):
- # Do not follow all index page links.
- # The links not tagged with rel="download" and rel="homepage" have
- # to not be processed by the package index, while processing "pages".
-
- # process the pages
- crawler = self._get_simple_crawler(server, follow_externals=True)
- crawler.get_releases("foobar")
- # now it should have processed only pages with links rel="download"
- # and rel="homepage"
- self.assertIn("%s/simple/foobar/" % server.full_address,
- crawler._processed_urls) # it's the simple index page
- self.assertIn("%s/external/homepage.html" % server.full_address,
- crawler._processed_urls) # the external homepage is rel="homepage"
- self.assertNotIn("%s/external/nonrel.html" % server.full_address,
- crawler._processed_urls) # this link contains no rel=*
- self.assertNotIn("%s/unrelated-0.2.tar.gz" % server.full_address,
- crawler._processed_urls) # linked from simple index (no rel)
- self.assertIn("%s/foobar-0.1.tar.gz" % server.full_address,
- crawler._processed_urls) # linked from simple index (rel)
- self.assertIn("%s/foobar-2.0.tar.gz" % server.full_address,
- crawler._processed_urls) # linked from external homepage (rel)
-
- def test_uses_mirrors(self):
- # When the main repository seems down, try using the given mirrors"""
- server = PyPIServer("foo_bar_baz")
- mirror = PyPIServer("foo_bar_baz")
- mirror.start() # we dont start the server here
-
- try:
- # create the index using both servers
- crawler = Crawler(server.full_address + "/simple/",
- hosts=('*',), timeout=1, # set the timeout to 1s for the tests
- mirrors=[mirror.full_address])
-
- # this should not raise a timeout
- self.assertEqual(4, len(crawler.get_releases("foo")))
- finally:
- mirror.stop()
-
- def test_simple_link_matcher(self):
- # Test that the simple link matcher yields the right links"""
- crawler = Crawler(follow_externals=False)
-
- # Here, we define:
- # 1. one link that must be followed, cause it's a download one
- # 2. one link that must *not* be followed, cause the is_browsable
- # returns false for it.
- # 3. one link that must be followed cause it's a homepage that is
- # browsable
- # 4. one link that must be followed, because it contain a md5 hash
- self.assertTrue(crawler._is_browsable("%stest" % crawler.index_url))
- self.assertFalse(crawler._is_browsable("http://dl-link2"))
- content = """
- <a href="http://dl-link1" rel="download">download_link1</a>
- <a href="http://dl-link2" rel="homepage">homepage_link1</a>
- <a href="%(index_url)stest" rel="homepage">homepage_link2</a>
- <a href="%(index_url)stest/foobar-1.tar.gz#md5=abcdef>download_link2</a>
- """ % {'index_url': crawler.index_url }
-
- # Test that the simple link matcher yield the good links.
- generator = crawler._simple_link_matcher(content, crawler.index_url)
- self.assertEqual(('%stest/foobar-1.tar.gz#md5=abcdef' % crawler.index_url,
- True), generator.next())
- self.assertEqual(('http://dl-link1', True), generator.next())
- self.assertEqual(('%stest' % crawler.index_url, False),
- generator.next())
- self.assertRaises(StopIteration, generator.next)
-
- # Follow the external links is possible (eg. homepages)
- crawler.follow_externals = True
- generator = crawler._simple_link_matcher(content, crawler.index_url)
- self.assertEqual(('%stest/foobar-1.tar.gz#md5=abcdef' % crawler.index_url,
- True), generator.next())
- self.assertEqual(('http://dl-link1', True), generator.next())
- self.assertEqual(('http://dl-link2', False), generator.next())
- self.assertEqual(('%stest' % crawler.index_url, False),
- generator.next())
- self.assertRaises(StopIteration, generator.next)
-
- def test_browse_local_files(self):
- # Test that we can browse local files"""
- index_path = os.sep.join(["file://" + PYPI_DEFAULT_STATIC_PATH,
- "test_found_links", "simple"])
- crawler = Crawler(index_path)
- dists = crawler.get_releases("foobar")
- self.assertEqual(4, len(dists))
-
- def test_get_link_matcher(self):
- crawler = Crawler("http://example.org")
- self.assertEqual('_simple_link_matcher', crawler._get_link_matcher(
- "http://example.org/some/file").__name__)
- self.assertEqual('_default_link_matcher', crawler._get_link_matcher(
- "http://other-url").__name__)
-
- def test_default_link_matcher(self):
- crawler = Crawler("http://example.org", mirrors=[])
- crawler.follow_externals = True
- crawler._is_browsable = lambda *args:True
- base_url = "http://example.org/some/file/"
- content = """
-<a href="../homepage" rel="homepage">link</a>
-<a href="../download" rel="download">link2</a>
-<a href="../simpleurl">link2</a>
- """
- found_links = dict(crawler._default_link_matcher(content,
- base_url)).keys()
- self.assertIn('http://example.org/some/homepage', found_links)
- self.assertIn('http://example.org/some/simpleurl', found_links)
- self.assertIn('http://example.org/some/download', found_links)
-
- @use_pypi_server("project_list")
- def test_search_projects(self, server):
- # we can search the index for some projects, on their names
- # the case used no matters here
- crawler = self._get_simple_crawler(server)
- projects = [p.name for p in crawler.search_projects("Foobar")]
- self.assertListEqual(['FooBar-bar', 'Foobar-baz', 'Baz-FooBar'],
- projects)
-
-def test_suite():
- return unittest.makeSuite(SimpleCrawlerTestCase)
-
-if __name__ == '__main__':
- unittest.main(defaultTest="test_suite")
diff --git a/src/distutils2/tests/test_index_xmlrpc.py b/src/distutils2/tests/test_index_xmlrpc.py
deleted file mode 100644
index 50ea739..0000000
--- a/src/distutils2/tests/test_index_xmlrpc.py
+++ /dev/null
@@ -1,92 +0,0 @@
-"""Tests for the distutils2.index.xmlrpc module."""
-
-from distutils2.tests.pypi_server import use_xmlrpc_server
-from distutils2.tests import run_unittest
-from distutils2.tests.support import unittest
-from distutils2.index.xmlrpc import Client, InvalidSearchField, ProjectNotFound
-
-
-class TestXMLRPCClient(unittest.TestCase):
- def _get_client(self, server, *args, **kwargs):
- return Client(server.full_address, *args, **kwargs)
-
- @use_xmlrpc_server()
- def test_search_projects(self, server):
- client = self._get_client(server)
- server.xmlrpc.set_search_result(['FooBar', 'Foo', 'FooFoo'])
- results = [r.name for r in client.search_projects(name='Foo')]
- self.assertEqual(3, len(results))
- self.assertIn('FooBar', results)
- self.assertIn('Foo', results)
- self.assertIn('FooFoo', results)
-
- def test_search_projects_bad_fields(self):
- client = Client()
- self.assertRaises(InvalidSearchField, client.search_projects,
- invalid="test")
-
- @use_xmlrpc_server()
- def test_get_releases(self, server):
- client = self._get_client(server)
- server.xmlrpc.set_distributions([
- {'name': 'FooBar', 'version': '1.1'},
- {'name': 'FooBar', 'version': '1.2', 'url': 'http://some/url/'},
- {'name': 'FooBar', 'version': '1.3', 'url': 'http://other/url/'},
- ])
-
- # use a lambda here to avoid an useless mock call
- server.xmlrpc.list_releases = lambda *a, **k: ['1.1', '1.2', '1.3']
-
- releases = client.get_releases('FooBar (<=1.2)')
- # dont call release_data and release_url; just return name and version.
- self.assertEqual(2, len(releases))
- versions = releases.get_versions()
- self.assertIn('1.1', versions)
- self.assertIn('1.2', versions)
- self.assertNotIn('1.3', versions)
-
- self.assertRaises(ProjectNotFound, client.get_releases,'Foo')
-
- @use_xmlrpc_server()
- def test_get_distributions(self, server):
- client = self._get_client(server)
- server.xmlrpc.set_distributions([
- {'name':'FooBar', 'version': '1.1', 'url':
- 'http://example.org/foobar-1.1-sdist.tar.gz',
- 'digest': '1234567', 'type': 'sdist', 'python_version':'source'},
- {'name':'FooBar', 'version': '1.1', 'url':
- 'http://example.org/foobar-1.1-bdist.tar.gz',
- 'digest': '8912345', 'type': 'bdist'},
- ])
-
- releases = client.get_releases('FooBar', '1.1')
- client.get_distributions('FooBar', '1.1')
- release = releases.get_release('1.1')
- self.assertTrue('http://example.org/foobar-1.1-sdist.tar.gz',
- release['sdist'].url['url'])
- self.assertTrue('http://example.org/foobar-1.1-bdist.tar.gz',
- release['bdist'].url['url'])
- self.assertEqual(release['sdist'].python_version, 'source')
-
- @use_xmlrpc_server()
- def test_get_metadata(self, server):
- client = self._get_client(server)
- server.xmlrpc.set_distributions([
- {'name':'FooBar',
- 'version': '1.1',
- 'keywords': '',
- 'obsoletes_dist': ['FooFoo'],
- 'requires_external': ['Foo'],
- }])
- release = client.get_metadata('FooBar', '1.1')
- self.assertEqual(['Foo'], release.metadata['requires_external'])
- self.assertEqual(['FooFoo'], release.metadata['obsoletes_dist'])
-
-
-def test_suite():
- suite = unittest.TestSuite()
- suite.addTest(unittest.makeSuite(TestXMLRPCClient))
- return suite
-
-if __name__ == '__main__':
- run_unittest(test_suite())
diff --git a/src/distutils2/tests/test_install.py b/src/distutils2/tests/test_install.py
deleted file mode 100644
index 783d3fc..0000000
--- a/src/distutils2/tests/test_install.py
+++ /dev/null
@@ -1,220 +0,0 @@
-"""Tests for distutils.command.install."""
-
-import os
-import sys
-
-from distutils2._backport.sysconfig import (get_scheme_names,
- get_config_vars,
- _SCHEMES,
- get_config_var, get_path)
-
-_CONFIG_VARS = get_config_vars()
-
-from distutils2.tests import captured_stdout
-
-from distutils2.command.install import install
-from distutils2.command import install as install_module
-from distutils2.core import Distribution
-from distutils2.errors import DistutilsOptionError
-
-from distutils2.tests import support
-from distutils2.tests.support import unittest
-
-class InstallTestCase(support.TempdirManager,
- support.EnvironGuard,
- support.LoggingCatcher,
- unittest.TestCase):
-
- def test_home_installation_scheme(self):
- # This ensure two things:
- # - that --home generates the desired set of directory names
- # - test --home is supported on all platforms
- builddir = self.mkdtemp()
- destination = os.path.join(builddir, "installation")
-
- dist = Distribution({"name": "foopkg"})
- # script_name need not exist, it just need to be initialized
- dist.script_name = os.path.join(builddir, "setup.py")
- dist.command_obj["build"] = support.DummyCommand(
- build_base=builddir,
- build_lib=os.path.join(builddir, "lib"),
- )
-
- old_posix_prefix = _SCHEMES.get('posix_prefix', 'platinclude')
- old_posix_home = _SCHEMES.get('posix_home', 'platinclude')
-
- new_path = '{platbase}/include/python{py_version_short}'
- _SCHEMES.set('posix_prefix', 'platinclude', new_path)
- _SCHEMES.set('posix_home', 'platinclude', '{platbase}/include/python')
-
- try:
- cmd = install(dist)
- cmd.home = destination
- cmd.ensure_finalized()
- finally:
- _SCHEMES.set('posix_prefix', 'platinclude', old_posix_prefix)
- _SCHEMES.set('posix_home', 'platinclude', old_posix_home)
-
- self.assertEqual(cmd.install_base, destination)
- self.assertEqual(cmd.install_platbase, destination)
-
- def check_path(got, expected):
- got = os.path.normpath(got)
- expected = os.path.normpath(expected)
- self.assertEqual(got, expected)
-
- libdir = os.path.join(destination, "lib", "python")
- check_path(cmd.install_lib, libdir)
- check_path(cmd.install_platlib, libdir)
- check_path(cmd.install_purelib, libdir)
- check_path(cmd.install_headers,
- os.path.join(destination, "include", "python", "foopkg"))
- check_path(cmd.install_scripts, os.path.join(destination, "bin"))
- check_path(cmd.install_data, destination)
-
- @unittest.skipIf(sys.version < '2.6', 'requires Python 2.6 or higher')
- def test_user_site(self):
- # test install with --user
- # preparing the environment for the test
- self.old_user_base = get_config_var('userbase')
- self.old_user_site = get_path('purelib', '%s_user' % os.name)
- self.tmpdir = self.mkdtemp()
- self.user_base = os.path.join(self.tmpdir, 'B')
- self.user_site = os.path.join(self.tmpdir, 'S')
- _CONFIG_VARS['userbase'] = self.user_base
- scheme = '%s_user' % os.name
- _SCHEMES.set(scheme, 'purelib', self.user_site)
- def _expanduser(path):
- if path[0] == '~':
- path = os.path.normpath(self.tmpdir) + path[1:]
- return path
- self.old_expand = os.path.expanduser
- os.path.expanduser = _expanduser
-
- try:
- # this is the actual test
- self._test_user_site()
- finally:
- _CONFIG_VARS['userbase'] = self.old_user_base
- _SCHEMES.set(scheme, 'purelib', self.old_user_site)
- os.path.expanduser = self.old_expand
-
- def _test_user_site(self):
- schemes = get_scheme_names()
- for key in ('nt_user', 'posix_user', 'os2_home'):
- self.assertTrue(key in schemes)
-
- dist = Distribution({'name': 'xx'})
- cmd = install(dist)
- # making sure the user option is there
- options = [name for name, short, lable in
- cmd.user_options]
- self.assertTrue('user' in options)
-
- # setting a value
- cmd.user = 1
-
- # user base and site shouldn't be created yet
- self.assertTrue(not os.path.exists(self.user_base))
- self.assertTrue(not os.path.exists(self.user_site))
-
- # let's run finalize
- cmd.ensure_finalized()
-
- # now they should
- self.assertTrue(os.path.exists(self.user_base))
- self.assertTrue(os.path.exists(self.user_site))
-
- self.assertTrue('userbase' in cmd.config_vars)
- self.assertTrue('usersite' in cmd.config_vars)
-
- def test_handle_extra_path(self):
- dist = Distribution({'name': 'xx', 'extra_path': 'path,dirs'})
- cmd = install(dist)
-
- # two elements
- cmd.handle_extra_path()
- self.assertEqual(cmd.extra_path, ['path', 'dirs'])
- self.assertEqual(cmd.extra_dirs, 'dirs')
- self.assertEqual(cmd.path_file, 'path')
-
- # one element
- cmd.extra_path = ['path']
- cmd.handle_extra_path()
- self.assertEqual(cmd.extra_path, ['path'])
- self.assertEqual(cmd.extra_dirs, 'path')
- self.assertEqual(cmd.path_file, 'path')
-
- # none
- dist.extra_path = cmd.extra_path = None
- cmd.handle_extra_path()
- self.assertEqual(cmd.extra_path, None)
- self.assertEqual(cmd.extra_dirs, '')
- self.assertEqual(cmd.path_file, None)
-
- # three elements (no way !)
- cmd.extra_path = 'path,dirs,again'
- self.assertRaises(DistutilsOptionError, cmd.handle_extra_path)
-
- def test_finalize_options(self):
- dist = Distribution({'name': 'xx'})
- cmd = install(dist)
-
- # must supply either prefix/exec-prefix/home or
- # install-base/install-platbase -- not both
- cmd.prefix = 'prefix'
- cmd.install_base = 'base'
- self.assertRaises(DistutilsOptionError, cmd.finalize_options)
-
- # must supply either home or prefix/exec-prefix -- not both
- cmd.install_base = None
- cmd.home = 'home'
- self.assertRaises(DistutilsOptionError, cmd.finalize_options)
-
- if sys.version >= '2.6':
- # can't combine user with with prefix/exec_prefix/home or
- # install_(plat)base
- cmd.prefix = None
- cmd.user = 'user'
- self.assertRaises(DistutilsOptionError, cmd.finalize_options)
-
- def test_record(self):
-
- install_dir = self.mkdtemp()
- pkgdir, dist = self.create_dist()
-
- dist = Distribution()
- cmd = install(dist)
- dist.command_obj['install'] = cmd
- cmd.root = install_dir
- cmd.record = os.path.join(pkgdir, 'RECORD')
- cmd.ensure_finalized()
- cmd.run()
-
- # let's check the RECORD file was created with four
- # lines, one for each .dist-info entry: METADATA,
- # INSTALLER, REQUSTED, RECORD
- f = open(cmd.record)
- try:
- self.assertEqual(len(f.readlines()), 4)
- finally:
- f.close()
-
- # XXX test that fancy_getopt is okay with options named
- # record and no-record but unrelated
-
- def _test_debug_mode(self):
- # this covers the code called when DEBUG is set
- old_logs_len = len(self.logs)
- install_module.DEBUG = True
- try:
- __, stdout = captured_stdout(self.test_record)
- finally:
- install_module.DEBUG = False
- self.assertTrue(len(self.logs) > old_logs_len)
-
-def test_suite():
- return unittest.makeSuite(InstallTestCase)
-
-if __name__ == "__main__":
- unittest.main(defaultTest="test_suite")
diff --git a/src/distutils2/tests/test_install_data.py b/src/distutils2/tests/test_install_data.py
deleted file mode 100644
index 9cae44a..0000000
--- a/src/distutils2/tests/test_install_data.py
+++ /dev/null
@@ -1,76 +0,0 @@
-"""Tests for distutils.command.install_data."""
-import sys
-import os
-import getpass
-
-from distutils2.command.install_data import install_data
-from distutils2.tests import support
-from distutils2.tests.support import unittest
-
-class InstallDataTestCase(support.TempdirManager,
- support.LoggingCatcher,
- support.EnvironGuard,
- unittest.TestCase):
-
- def test_simple_run(self):
- pkg_dir, dist = self.create_dist()
- cmd = install_data(dist)
- cmd.install_dir = inst = os.path.join(pkg_dir, 'inst')
-
- # data_files can contain
- # - simple files
- # - a tuple with a path, and a list of file
- one = os.path.join(pkg_dir, 'one')
- self.write_file(one, 'xxx')
- inst2 = os.path.join(pkg_dir, 'inst2')
- two = os.path.join(pkg_dir, 'two')
- self.write_file(two, 'xxx')
-
- cmd.data_files = [one, (inst2, [two])]
- self.assertEqual(cmd.get_inputs(), [one, (inst2, [two])])
-
- # let's run the command
- cmd.ensure_finalized()
- cmd.run()
-
- # let's check the result
- self.assertEqual(len(cmd.get_outputs()), 2)
- rtwo = os.path.split(two)[-1]
- self.assertTrue(os.path.exists(os.path.join(inst2, rtwo)))
- rone = os.path.split(one)[-1]
- self.assertTrue(os.path.exists(os.path.join(inst, rone)))
- cmd.outfiles = []
-
- # let's try with warn_dir one
- cmd.warn_dir = 1
- cmd.ensure_finalized()
- cmd.run()
-
- # let's check the result
- self.assertEqual(len(cmd.get_outputs()), 2)
- self.assertTrue(os.path.exists(os.path.join(inst2, rtwo)))
- self.assertTrue(os.path.exists(os.path.join(inst, rone)))
- cmd.outfiles = []
-
- # now using root and empty dir
- cmd.root = os.path.join(pkg_dir, 'root')
- inst3 = os.path.join(cmd.install_dir, 'inst3')
- inst4 = os.path.join(pkg_dir, 'inst4')
- three = os.path.join(cmd.install_dir, 'three')
- self.write_file(three, 'xx')
- cmd.data_files = [one, (inst2, [two]),
- ('inst3', [three]),
- (inst4, [])]
- cmd.ensure_finalized()
- cmd.run()
-
- # let's check the result
- self.assertEqual(len(cmd.get_outputs()), 4)
- self.assertTrue(os.path.exists(os.path.join(inst2, rtwo)))
- self.assertTrue(os.path.exists(os.path.join(inst, rone)))
-
-def test_suite():
- return unittest.makeSuite(InstallDataTestCase)
-
-if __name__ == "__main__":
- unittest.main(defaultTest="test_suite")
diff --git a/src/distutils2/tests/test_install_distinfo.py b/src/distutils2/tests/test_install_distinfo.py
deleted file mode 100644
index 1bad24b..0000000
--- a/src/distutils2/tests/test_install_distinfo.py
+++ /dev/null
@@ -1,202 +0,0 @@
-"""Tests for ``distutils2.command.install_distinfo``. """
-
-import os
-import sys
-import csv
-
-from distutils2.command.install_distinfo import install_distinfo
-from distutils2.core import Command
-from distutils2.metadata import DistributionMetadata
-from distutils2.tests import support
-from distutils2.tests.support import unittest
-
-try:
- import hashlib
-except ImportError:
- from distutils2._backport import hashlib
-
-
-class DummyInstallCmd(Command):
-
- def __init__(self, dist=None):
- self.outputs = []
- self.distribution = dist
-
- def __getattr__(self, name):
- return None
-
- def ensure_finalized(self):
- pass
-
- def get_outputs(self):
- return self.outputs + \
- self.get_finalized_command('install_distinfo').get_outputs()
-
-
-class InstallDistinfoTestCase(support.TempdirManager,
- support.LoggingCatcher,
- support.EnvironGuard,
- unittest.TestCase):
-
- checkLists = lambda self, x, y: self.assertListEqual(sorted(x), sorted(y))
-
- def test_empty_install(self):
- pkg_dir, dist = self.create_dist(name='foo',
- version='1.0')
- install_dir = self.mkdtemp()
-
- install = DummyInstallCmd(dist)
- dist.command_obj['install'] = install
-
- cmd = install_distinfo(dist)
- dist.command_obj['install_distinfo'] = cmd
-
- cmd.initialize_options()
- cmd.distinfo_dir = install_dir
- cmd.ensure_finalized()
- cmd.run()
-
- self.checkLists(os.listdir(install_dir), ['foo-1.0.dist-info'])
-
- dist_info = os.path.join(install_dir, 'foo-1.0.dist-info')
- self.checkLists(os.listdir(dist_info),
- ['METADATA', 'RECORD', 'REQUESTED', 'INSTALLER'])
- self.assertEqual(open(os.path.join(dist_info, 'INSTALLER')).read(),
- 'distutils')
- self.assertEqual(open(os.path.join(dist_info, 'REQUESTED')).read(),
- '')
- meta_path = os.path.join(dist_info, 'METADATA')
- self.assertTrue(DistributionMetadata(path=meta_path).check())
-
- def test_installer(self):
- pkg_dir, dist = self.create_dist(name='foo',
- version='1.0')
- install_dir = self.mkdtemp()
-
- install = DummyInstallCmd(dist)
- dist.command_obj['install'] = install
-
- cmd = install_distinfo(dist)
- dist.command_obj['install_distinfo'] = cmd
-
- cmd.initialize_options()
- cmd.distinfo_dir = install_dir
- cmd.installer = 'bacon-python'
- cmd.ensure_finalized()
- cmd.run()
-
- dist_info = os.path.join(install_dir, 'foo-1.0.dist-info')
- self.assertEqual(open(os.path.join(dist_info, 'INSTALLER')).read(),
- 'bacon-python')
-
- def test_requested(self):
- pkg_dir, dist = self.create_dist(name='foo',
- version='1.0')
- install_dir = self.mkdtemp()
-
- install = DummyInstallCmd(dist)
- dist.command_obj['install'] = install
-
- cmd = install_distinfo(dist)
- dist.command_obj['install_distinfo'] = cmd
-
- cmd.initialize_options()
- cmd.distinfo_dir = install_dir
- cmd.requested = False
- cmd.ensure_finalized()
- cmd.run()
-
- dist_info = os.path.join(install_dir, 'foo-1.0.dist-info')
- self.checkLists(os.listdir(dist_info),
- ['METADATA', 'RECORD', 'INSTALLER'])
-
- def test_no_record(self):
- pkg_dir, dist = self.create_dist(name='foo',
- version='1.0')
- install_dir = self.mkdtemp()
-
- install = DummyInstallCmd(dist)
- dist.command_obj['install'] = install
-
- cmd = install_distinfo(dist)
- dist.command_obj['install_distinfo'] = cmd
-
- cmd.initialize_options()
- cmd.distinfo_dir = install_dir
- cmd.no_record = True
- cmd.ensure_finalized()
- cmd.run()
-
- dist_info = os.path.join(install_dir, 'foo-1.0.dist-info')
- self.checkLists(os.listdir(dist_info),
- ['METADATA', 'REQUESTED', 'INSTALLER'])
-
- def test_record(self):
- pkg_dir, dist = self.create_dist(name='foo',
- version='1.0')
- install_dir = self.mkdtemp()
-
- install = DummyInstallCmd(dist)
- dist.command_obj['install'] = install
-
- fake_dists = os.path.join(os.path.dirname(__file__), '..',
- '_backport', 'tests', 'fake_dists')
- fake_dists = os.path.realpath(fake_dists)
-
- # for testing, we simply add all files from _backport's fake_dists
- dirs = []
- for dir in os.listdir(fake_dists):
- full_path = os.path.join(fake_dists, dir)
- if (not dir.endswith('.egg') or dir.endswith('.egg-info') or
- dir.endswith('.dist-info')) and os.path.isdir(full_path):
- dirs.append(full_path)
-
- for dir in dirs:
- for (path, subdirs, files) in os.walk(dir):
- install.outputs += [os.path.join(path, f) for f in files]
- install.outputs += [os.path.join('path', f + 'c')
- for f in files if f.endswith('.py')]
-
-
- cmd = install_distinfo(dist)
- dist.command_obj['install_distinfo'] = cmd
-
- cmd.initialize_options()
- cmd.distinfo_dir = install_dir
- cmd.ensure_finalized()
- cmd.run()
-
- dist_info = os.path.join(install_dir, 'foo-1.0.dist-info')
-
- expected = []
- for f in install.get_outputs():
- if f.endswith('.pyc') or \
- f == os.path.join(install_dir, 'foo-1.0.dist-info', 'RECORD'):
- expected.append([f, '', ''])
- else:
- size = os.path.getsize(f)
- md5 = hashlib.md5()
- md5.update(open(f).read())
- hash = md5.hexdigest()
- expected.append([f, hash, str(size)])
-
- parsed = []
- f = open(os.path.join(dist_info, 'RECORD'), 'rb')
- try:
- reader = csv.reader(f, delimiter=',',
- lineterminator=os.linesep,
- quotechar='"')
- parsed = list(reader)
- finally:
- f.close()
-
- self.maxDiff = None
- self.checkLists(parsed, expected)
-
-
-def test_suite():
- return unittest.makeSuite(InstallDistinfoTestCase)
-
-
-if __name__ == "__main__":
- unittest.main(defaultTest="test_suite")
diff --git a/src/distutils2/tests/test_install_headers.py b/src/distutils2/tests/test_install_headers.py
deleted file mode 100644
index 5e40257..0000000
--- a/src/distutils2/tests/test_install_headers.py
+++ /dev/null
@@ -1,40 +0,0 @@
-"""Tests for distutils.command.install_headers."""
-import sys
-import os
-import getpass
-
-from distutils2.command.install_headers import install_headers
-from distutils2.tests import support
-from distutils2.tests.support import unittest
-
-class InstallHeadersTestCase(support.TempdirManager,
- support.LoggingCatcher,
- support.EnvironGuard,
- unittest.TestCase):
-
- def test_simple_run(self):
- # we have two headers
- header_list = self.mkdtemp()
- header1 = os.path.join(header_list, 'header1')
- header2 = os.path.join(header_list, 'header2')
- self.write_file(header1)
- self.write_file(header2)
- headers = [header1, header2]
-
- pkg_dir, dist = self.create_dist(headers=headers)
- cmd = install_headers(dist)
- self.assertEqual(cmd.get_inputs(), headers)
-
- # let's run the command
- cmd.install_dir = os.path.join(pkg_dir, 'inst')
- cmd.ensure_finalized()
- cmd.run()
-
- # let's check the results
- self.assertEqual(len(cmd.get_outputs()), 2)
-
-def test_suite():
- return unittest.makeSuite(InstallHeadersTestCase)
-
-if __name__ == "__main__":
- unittest.main(defaultTest="test_suite")
diff --git a/src/distutils2/tests/test_install_lib.py b/src/distutils2/tests/test_install_lib.py
deleted file mode 100644
index 75eb69e..0000000
--- a/src/distutils2/tests/test_install_lib.py
+++ /dev/null
@@ -1,107 +0,0 @@
-"""Tests for distutils.command.install_data."""
-import sys
-import os
-
-from distutils2.command.install_lib import install_lib
-from distutils2.extension import Extension
-from distutils2.tests import support
-from distutils2.errors import DistutilsOptionError
-from distutils2.tests.support import unittest
-
-try:
- no_bytecode = sys.dont_write_bytecode
- bytecode_support = True
-except AttributeError:
- no_bytecode = False
- bytecode_support = False
-
-class InstallLibTestCase(support.TempdirManager,
- support.LoggingCatcher,
- support.EnvironGuard,
- unittest.TestCase):
-
- def test_finalize_options(self):
- pkg_dir, dist = self.create_dist()
- cmd = install_lib(dist)
-
- cmd.finalize_options()
- self.assertEqual(cmd.compile, 1)
- self.assertEqual(cmd.optimize, 0)
-
- # optimize must be 0, 1, or 2
- cmd.optimize = 'foo'
- self.assertRaises(DistutilsOptionError, cmd.finalize_options)
- cmd.optimize = '4'
- self.assertRaises(DistutilsOptionError, cmd.finalize_options)
-
- cmd.optimize = '2'
- cmd.finalize_options()
- self.assertEqual(cmd.optimize, 2)
-
- @unittest.skipIf(no_bytecode, 'byte-compile not supported')
- def test_byte_compile(self):
- pkg_dir, dist = self.create_dist()
- cmd = install_lib(dist)
- cmd.compile = cmd.optimize = 1
-
- f = os.path.join(pkg_dir, 'foo.py')
- self.write_file(f, '# python file')
- cmd.byte_compile([f])
- self.assertTrue(os.path.exists(os.path.join(pkg_dir, 'foo.pyc')))
- self.assertTrue(os.path.exists(os.path.join(pkg_dir, 'foo.pyo')))
-
- def test_get_outputs(self):
- pkg_dir, dist = self.create_dist()
- cmd = install_lib(dist)
-
- # setting up a dist environment
- cmd.compile = cmd.optimize = 1
- cmd.install_dir = pkg_dir
- f = os.path.join(pkg_dir, '__init__.py')
- self.write_file(f, '# python package')
- cmd.distribution.ext_modules = [Extension('foo', ['xxx'])]
- cmd.distribution.packages = [pkg_dir]
- cmd.distribution.script_name = 'setup.py'
-
- # get_output should return 4 elements
- self.assertTrue(len(cmd.get_outputs()) >= 2)
-
- def test_get_inputs(self):
- pkg_dir, dist = self.create_dist()
- cmd = install_lib(dist)
-
- # setting up a dist environment
- cmd.compile = cmd.optimize = 1
- cmd.install_dir = pkg_dir
- f = os.path.join(pkg_dir, '__init__.py')
- self.write_file(f, '# python package')
- cmd.distribution.ext_modules = [Extension('foo', ['xxx'])]
- cmd.distribution.packages = [pkg_dir]
- cmd.distribution.script_name = 'setup.py'
-
- # get_input should return 2 elements
- self.assertEqual(len(cmd.get_inputs()), 2)
-
- @unittest.skipUnless(bytecode_support,
- 'sys.dont_write_bytecode not supported')
- def test_dont_write_bytecode(self):
- # makes sure byte_compile is not used
- pkg_dir, dist = self.create_dist()
- cmd = install_lib(dist)
- cmd.compile = 1
- cmd.optimize = 1
-
- old_dont_write_bytecode = sys.dont_write_bytecode
- sys.dont_write_bytecode = True
- try:
- cmd.byte_compile([])
- finally:
- sys.dont_write_bytecode = old_dont_write_bytecode
-
- self.assertTrue('byte-compiling is disabled' in self.logs[0][1])
-
-def test_suite():
- return unittest.makeSuite(InstallLibTestCase)
-
-if __name__ == "__main__":
- unittest.main(defaultTest="test_suite")
diff --git a/src/distutils2/tests/test_install_scripts.py b/src/distutils2/tests/test_install_scripts.py
deleted file mode 100644
index 2cfab03..0000000
--- a/src/distutils2/tests/test_install_scripts.py
+++ /dev/null
@@ -1,81 +0,0 @@
-"""Tests for distutils.command.install_scripts."""
-
-import os
-
-from distutils2.command.install_scripts import install_scripts
-from distutils2.core import Distribution
-
-from distutils2.tests import support
-from distutils2.tests.support import unittest
-
-
-class InstallScriptsTestCase(support.TempdirManager,
- support.LoggingCatcher,
- unittest.TestCase):
-
- def test_default_settings(self):
- dist = Distribution()
- dist.command_obj["build"] = support.DummyCommand(
- build_scripts="/foo/bar")
- dist.command_obj["install"] = support.DummyCommand(
- install_scripts="/splat/funk",
- force=1,
- skip_build=1,
- )
- cmd = install_scripts(dist)
- self.assertTrue(not cmd.force)
- self.assertTrue(not cmd.skip_build)
- self.assertTrue(cmd.build_dir is None)
- self.assertTrue(cmd.install_dir is None)
-
- cmd.finalize_options()
-
- self.assertTrue(cmd.force)
- self.assertTrue(cmd.skip_build)
- self.assertEqual(cmd.build_dir, "/foo/bar")
- self.assertEqual(cmd.install_dir, "/splat/funk")
-
- def test_installation(self):
- source = self.mkdtemp()
- expected = []
-
- def write_script(name, text):
- expected.append(name)
- f = open(os.path.join(source, name), "w")
- try:
- f.write(text)
- finally:
- f.close()
-
- write_script("script1.py", ("#! /usr/bin/env python2.3\n"
- "# bogus script w/ Python sh-bang\n"
- "pass\n"))
- write_script("script2.py", ("#!/usr/bin/python\n"
- "# bogus script w/ Python sh-bang\n"
- "pass\n"))
- write_script("shell.sh", ("#!/bin/sh\n"
- "# bogus shell script w/ sh-bang\n"
- "exit 0\n"))
-
- target = self.mkdtemp()
- dist = Distribution()
- dist.command_obj["build"] = support.DummyCommand(build_scripts=source)
- dist.command_obj["install"] = support.DummyCommand(
- install_scripts=target,
- force=1,
- skip_build=1,
- )
- cmd = install_scripts(dist)
- cmd.finalize_options()
- cmd.run()
-
- installed = os.listdir(target)
- for name in expected:
- self.assertTrue(name in installed)
-
-
-def test_suite():
- return unittest.makeSuite(InstallScriptsTestCase)
-
-if __name__ == "__main__":
- unittest.main(defaultTest="test_suite")
diff --git a/src/distutils2/tests/test_install_tools.py b/src/distutils2/tests/test_install_tools.py
deleted file mode 100644
index 2db4add..0000000
--- a/src/distutils2/tests/test_install_tools.py
+++ /dev/null
@@ -1,160 +0,0 @@
-"""Tests for the distutils2.index.xmlrpc module."""
-
-from distutils2.tests.pypi_server import use_xmlrpc_server
-from distutils2.tests import run_unittest
-from distutils2.tests.support import unittest
-from distutils2.index.xmlrpc import Client
-from distutils2.install_tools import (get_infos,
- InstallationException)
-from distutils2.metadata import DistributionMetadata
-
-
-class FakeDist(object):
- """A fake distribution object, for tests"""
- def __init__(self, name, version, deps):
- self.name = name
- self.version = version
- self.metadata = DistributionMetadata()
- self.metadata['Requires-Dist'] = deps
- self.metadata['Provides-Dist'] = ['%s (%s)' % (name, version)]
-
- def __repr__(self):
- return '<FakeDist %s>' % self.name
-
-
-def get_fake_dists(dists):
- objects = []
- for (name, version, deps) in dists:
- objects.append(FakeDist(name, version, deps))
- return objects
-
-
-class TestInstallWithDeps(unittest.TestCase):
- def _get_client(self, server, *args, **kwargs):
- return Client(server.full_address, *args, **kwargs)
-
- def _get_results(self, output):
- """return a list of results"""
- installed = [(o.name, '%s' % o.version) for o in output['install']]
- remove = [(o.name, '%s' % o.version) for o in output['remove']]
- conflict = [(o.name, '%s' % o.version) for o in output['conflict']]
- return (installed, remove, conflict)
-
- @use_xmlrpc_server()
- def test_existing_deps(self, server):
- # Test that the installer get the dependencies from the metadatas
- # and ask the index for this dependencies.
- # In this test case, we have choxie that is dependent from towel-stuff
- # 0.1, which is in-turn dependent on bacon <= 0.2:
- # choxie -> towel-stuff -> bacon.
- # Each release metadata is not provided in metadata 1.2.
- client = self._get_client(server)
- archive_path = '%s/distribution.tar.gz' % server.full_address
- server.xmlrpc.set_distributions([
- {'name':'choxie',
- 'version': '2.0.0.9',
- 'requires_dist': ['towel-stuff (0.1)',],
- 'url': archive_path},
- {'name':'towel-stuff',
- 'version': '0.1',
- 'requires_dist': ['bacon (<= 0.2)',],
- 'url': archive_path},
- {'name':'bacon',
- 'version': '0.1',
- 'requires_dist': [],
- 'url': archive_path},
- ])
- installed = get_fake_dists([('bacon', '0.1', []),])
- output = get_infos("choxie", index=client,
- installed=installed)
-
- # we dont have installed bacon as it's already installed on the system.
- self.assertEqual(0, len(output['remove']))
- self.assertEqual(2, len(output['install']))
- readable_output = [(o.name, '%s' % o.version)
- for o in output['install']]
- self.assertIn(('towel-stuff', '0.1'), readable_output)
- self.assertIn(('choxie', '2.0.0.9'), readable_output)
-
- @use_xmlrpc_server()
- def test_upgrade_existing_deps(self, server):
- # Tests that the existing distributions can be upgraded if needed.
- client = self._get_client(server)
- archive_path = '%s/distribution.tar.gz' % server.full_address
- server.xmlrpc.set_distributions([
- {'name':'choxie',
- 'version': '2.0.0.9',
- 'requires_dist': ['towel-stuff (0.1)',],
- 'url': archive_path},
- {'name':'towel-stuff',
- 'version': '0.1',
- 'requires_dist': ['bacon (>= 0.2)',],
- 'url': archive_path},
- {'name':'bacon',
- 'version': '0.2',
- 'requires_dist': [],
- 'url': archive_path},
- ])
-
- output = get_infos("choxie", index=client, installed=
- get_fake_dists([('bacon', '0.1', []),]))
- installed = [(o.name, '%s' % o.version) for o in output['install']]
-
- # we need bacon 0.2, but 0.1 is installed.
- # So we expect to remove 0.1 and to install 0.2 instead.
- remove = [(o.name, '%s' % o.version) for o in output['remove']]
- self.assertIn(('choxie', '2.0.0.9'), installed)
- self.assertIn(('towel-stuff', '0.1'), installed)
- self.assertIn(('bacon', '0.2'), installed)
- self.assertIn(('bacon', '0.1'), remove)
- self.assertEqual(0, len(output['conflict']))
-
- @use_xmlrpc_server()
- def test_conflicts(self, server):
- # Tests that conflicts are detected
- client = self._get_client(server)
- archive_path = '%s/distribution.tar.gz' % server.full_address
- server.xmlrpc.set_distributions([
- {'name':'choxie',
- 'version': '2.0.0.9',
- 'requires_dist': ['towel-stuff (0.1)',],
- 'url': archive_path},
- {'name':'towel-stuff',
- 'version': '0.1',
- 'requires_dist': ['bacon (>= 0.2)',],
- 'url': archive_path},
- {'name':'bacon',
- 'version': '0.2',
- 'requires_dist': [],
- 'url': archive_path},
- ])
- already_installed = [('bacon', '0.1', []),
- ('chicken', '1.1', ['bacon (0.1)'])]
- output = get_infos("choxie", index=client, installed=
- get_fake_dists(already_installed))
-
- # we need bacon 0.2, but 0.1 is installed.
- # So we expect to remove 0.1 and to install 0.2 instead.
- installed, remove, conflict = self._get_results(output)
- self.assertIn(('choxie', '2.0.0.9'), installed)
- self.assertIn(('towel-stuff', '0.1'), installed)
- self.assertIn(('bacon', '0.2'), installed)
- self.assertIn(('bacon', '0.1'), remove)
- self.assertIn(('chicken', '1.1'), conflict)
-
- @use_xmlrpc_server()
- def test_installation_unexisting_project(self, server):
- # Test that the isntalled raises an exception if the project does not
- # exists.
- client = self._get_client(server)
- self.assertRaises(InstallationException, get_infos,
- 'unexistant project', index=client)
-
-
-def test_suite():
- suite = unittest.TestSuite()
- suite.addTest(unittest.makeSuite(TestInstallWithDeps))
- return suite
-
-if __name__ == '__main__':
- run_unittest(test_suite())
diff --git a/src/distutils2/tests/test_manifest.py b/src/distutils2/tests/test_manifest.py
deleted file mode 100644
index 13893eb..0000000
--- a/src/distutils2/tests/test_manifest.py
+++ /dev/null
@@ -1,58 +0,0 @@
-"""Tests for distutils.manifest."""
-import os
-import sys
-import logging
-
-from distutils2.tests import run_unittest
-from distutils2.tests import support
-from distutils2.tests.support import unittest
-from distutils2.manifest import Manifest
-
-_MANIFEST = """\
-recursive-include foo *.py # ok
-# nothing here
-
-#
-
-recursive-include bar \\
- *.dat *.txt
-"""
-
-class ManifestTestCase(support.TempdirManager,
- unittest.TestCase):
-
- def test_manifest_reader(self):
-
- tmpdir = self.mkdtemp()
- MANIFEST = os.path.join(tmpdir, 'MANIFEST.in')
- f = open(MANIFEST, 'w')
- try:
- f.write(_MANIFEST)
- finally:
- f.close()
- manifest = Manifest()
-
- warns = []
- def _warn(msg):
- warns.append(msg)
-
- old_warn = logging.warning
- logging.warning = _warn
- try:
- manifest.read_template(MANIFEST)
- finally:
- logging.warning = old_warn
-
- # the manifest should have been read
- # and 3 warnings issued (we ddidn't provided the files)
- self.assertEqual(len(warns), 3)
- for warn in warns:
- self.assertIn('warning: no files found matching', warn)
-
-
-
-def test_suite():
- return unittest.makeSuite(ManifestTestCase)
-
-if __name__ == '__main__':
- run_unittest(test_suite())
diff --git a/src/distutils2/tests/test_metadata.py b/src/distutils2/tests/test_metadata.py
deleted file mode 100644
index 931f1ba..0000000
--- a/src/distutils2/tests/test_metadata.py
+++ /dev/null
@@ -1,291 +0,0 @@
-"""Tests for distutils.command.bdist."""
-import os
-import sys
-import platform
-from StringIO import StringIO
-
-from distutils2.metadata import (DistributionMetadata, _interpret,
- PKG_INFO_PREFERRED_VERSION)
-from distutils2.tests import run_unittest
-from distutils2.tests.support import unittest, LoggingCatcher
-from distutils2.errors import (MetadataConflictError,
- MetadataUnrecognizedVersionError)
-
-class DistributionMetadataTestCase(LoggingCatcher, unittest.TestCase):
-
- def test_instantiation(self):
- PKG_INFO = os.path.join(os.path.dirname(__file__), 'PKG-INFO')
- fp = open(PKG_INFO)
- try:
- contents = fp.read()
- finally:
- fp.close()
- fp = StringIO(contents)
-
- m = DistributionMetadata()
- self.assertRaises(MetadataUnrecognizedVersionError, m.items)
-
- m = DistributionMetadata(PKG_INFO)
- self.assertEqual(len(m.items()), 22)
-
- m = DistributionMetadata(fileobj=fp)
- self.assertEqual(len(m.items()), 22)
-
- m = DistributionMetadata(mapping=dict(name='Test', version='1.0'))
- self.assertEqual(len(m.items()), 11)
-
- d = dict(m.items())
- self.assertRaises(TypeError, DistributionMetadata,
- PKG_INFO, fileobj=fp)
- self.assertRaises(TypeError, DistributionMetadata,
- PKG_INFO, mapping=d)
- self.assertRaises(TypeError, DistributionMetadata,
- fileobj=fp, mapping=d)
- self.assertRaises(TypeError, DistributionMetadata,
- PKG_INFO, mapping=m, fileobj=fp)
-
- def test_interpret(self):
- sys_platform = sys.platform
- version = sys.version.split()[0]
- os_name = os.name
- platform_version = platform.version()
- platform_machine = platform.machine()
-
- self.assertTrue(_interpret("sys.platform == '%s'" % sys_platform))
- self.assertTrue(_interpret(
- "sys.platform == '%s' or python_version == '2.4'" % sys_platform))
- self.assertTrue(_interpret(
- "sys.platform == '%s' and python_full_version == '%s'" %
- (sys_platform, version)))
- self.assertTrue(_interpret("'%s' == sys.platform" % sys_platform))
- self.assertTrue(_interpret('os.name == "%s"' % os_name))
- self.assertTrue(_interpret(
- 'platform.version == "%s" and platform.machine == "%s"' %
- (platform_version, platform_machine)))
-
- # stuff that need to raise a syntax error
- ops = ('os.name == os.name', 'os.name == 2', "'2' == '2'",
- 'okpjonon', '', 'os.name ==', 'python_version == 2.4')
- for op in ops:
- self.assertRaises(SyntaxError, _interpret, op)
-
- # combined operations
- OP = 'os.name == "%s"' % os_name
- AND = ' and '
- OR = ' or '
- self.assertTrue(_interpret(OP + AND + OP))
- self.assertTrue(_interpret(OP + AND + OP + AND + OP))
- self.assertTrue(_interpret(OP + OR + OP))
- self.assertTrue(_interpret(OP + OR + OP + OR + OP))
-
- # other operators
- self.assertTrue(_interpret("os.name != 'buuuu'"))
- self.assertTrue(_interpret("python_version > '1.0'"))
- self.assertTrue(_interpret("python_version < '5.0'"))
- self.assertTrue(_interpret("python_version <= '5.0'"))
- self.assertTrue(_interpret("python_version >= '1.0'"))
- self.assertTrue(_interpret("'%s' in os.name" % os_name))
- self.assertTrue(_interpret("'buuuu' not in os.name"))
- self.assertTrue(_interpret(
- "'buuuu' not in os.name and '%s' in os.name" % os_name))
-
- # execution context
- self.assertTrue(_interpret('python_version == "0.1"',
- {'python_version': '0.1'}))
-
- def test_metadata_read_write(self):
-
- PKG_INFO = os.path.join(os.path.dirname(__file__), 'PKG-INFO')
- metadata = DistributionMetadata(PKG_INFO)
- out = StringIO()
- metadata.write_file(out)
- out.seek(0)
- res = DistributionMetadata()
- res.read_file(out)
- for k in metadata.keys():
- self.assertTrue(metadata[k] == res[k])
-
- def test_metadata_markers(self):
- # see if we can be platform-aware
- PKG_INFO = os.path.join(os.path.dirname(__file__), 'PKG-INFO')
- content = open(PKG_INFO).read()
- content = content % sys.platform
- metadata = DistributionMetadata(platform_dependent=True)
- metadata.read_file(StringIO(content))
- self.assertEqual(metadata['Requires-Dist'], ['bar'])
- metadata['Name'] = "baz; sys.platform == 'blah'"
- # FIXME is None or 'UNKNOWN' correct here?
- # where is that documented?
- self.assertEquals(metadata['Name'], None)
-
- # test with context
- context = {'sys.platform': 'okook'}
- metadata = DistributionMetadata(platform_dependent=True,
- execution_context=context)
- metadata.read_file(StringIO(content))
- self.assertEqual(metadata['Requires-Dist'], ['foo'])
-
- def test_description(self):
- PKG_INFO = os.path.join(os.path.dirname(__file__), 'PKG-INFO')
- content = open(PKG_INFO).read()
- content = content % sys.platform
- metadata = DistributionMetadata()
- metadata.read_file(StringIO(content))
-
- # see if we can read the description now
- DESC = os.path.join(os.path.dirname(__file__), 'LONG_DESC.txt')
- wanted = open(DESC).read()
- self.assertEqual(wanted, metadata['Description'])
-
- # save the file somewhere and make sure we can read it back
- out = StringIO()
- metadata.write_file(out)
- out.seek(0)
- metadata.read_file(out)
- self.assertEqual(wanted, metadata['Description'])
-
- def test_mapping_api(self):
- PKG_INFO = os.path.join(os.path.dirname(__file__), 'PKG-INFO')
- content = open(PKG_INFO).read()
- content = content % sys.platform
- metadata = DistributionMetadata(fileobj=StringIO(content))
- self.assertIn('Version', metadata.keys())
- self.assertIn('0.5', metadata.values())
- self.assertIn(('Version', '0.5'), metadata.items())
-
- metadata.update({'version': '0.6'})
- self.assertEqual(metadata['Version'], '0.6')
- metadata.update([('version', '0.7')])
- self.assertEqual(metadata['Version'], '0.7')
-
- def test_versions(self):
- metadata = DistributionMetadata()
- metadata['Obsoletes'] = 'ok'
- self.assertEqual(metadata['Metadata-Version'], '1.1')
-
- del metadata['Obsoletes']
- metadata['Obsoletes-Dist'] = 'ok'
- self.assertEqual(metadata['Metadata-Version'], '1.2')
-
- self.assertRaises(MetadataConflictError, metadata.set,
- 'Obsoletes', 'ok')
-
- del metadata['Obsoletes']
- del metadata['Obsoletes-Dist']
- metadata['Version'] = '1'
- self.assertEqual(metadata['Metadata-Version'], '1.0')
-
- PKG_INFO = os.path.join(os.path.dirname(__file__),
- 'SETUPTOOLS-PKG-INFO')
- metadata.read_file(StringIO(open(PKG_INFO).read()))
- self.assertEqual(metadata['Metadata-Version'], '1.0')
-
- PKG_INFO = os.path.join(os.path.dirname(__file__),
- 'SETUPTOOLS-PKG-INFO2')
- metadata.read_file(StringIO(open(PKG_INFO).read()))
- self.assertEqual(metadata['Metadata-Version'], '1.1')
-
- metadata.version = '1.618'
- self.assertRaises(MetadataUnrecognizedVersionError, metadata.keys)
-
- def test_warnings(self):
- metadata = DistributionMetadata()
-
- # these should raise a warning
- values = (('Requires-Dist', 'Funky (Groovie)'),
- ('Requires-Python', '1-4'))
-
- from distutils2 import metadata as m
- old = m.warn
- m.warns = 0
-
- def _warn(*args):
- m.warns += 1
-
- m.warn = _warn
-
- try:
- for name, value in values:
- metadata.set(name, value)
- finally:
- m.warn = old
- res = m.warns
- del m.warns
-
- # we should have a certain amount of warnings
- num_wanted = len(values)
- self.assertEqual(num_wanted, res)
-
- def test_multiple_predicates(self):
- metadata = DistributionMetadata()
-
- from distutils2 import metadata as m
- old = m.warn
- m.warns = 0
-
- def _warn(*args):
- m.warns += 1
-
- # see for "3" instead of "3.0" ???
- # its seems like the MINOR VERSION can be omitted
- m.warn = _warn
- try:
- metadata['Requires-Python'] = '>=2.6, <3.0'
- metadata['Requires-Dist'] = ['Foo (>=2.6, <3.0)']
- finally:
- m.warn = old
- res = m.warns
- del m.warns
-
- self.assertEqual(res, 0)
-
- def test_project_url(self):
- metadata = DistributionMetadata()
- metadata['Project-URL'] = [('one', 'http://ok')]
- self.assertEqual(metadata['Project-URL'],
- [('one', 'http://ok')])
- self.assertEqual(metadata.version, '1.2')
-
- def test_check(self):
- metadata = DistributionMetadata()
- metadata['Version'] = 'rr'
- metadata['Requires-dist'] = ['Foo (a)']
- if metadata.docutils_support:
- missing, warnings = metadata.check()
- self.assertEqual(len(warnings), 2)
- metadata.docutils_support = False
- missing, warnings = metadata.check()
- self.assertEqual(missing, ['Name', 'Home-page'])
- self.assertEqual(len(warnings), 2)
-
- def test_best_choice(self):
- metadata = DistributionMetadata()
- metadata['Version'] = '1.0'
- self.assertEqual(metadata.version, PKG_INFO_PREFERRED_VERSION)
- metadata['Classifier'] = ['ok']
- self.assertEqual(metadata.version, '1.2')
-
- def test_project_urls(self):
- # project-url is a bit specific, make sure we write it
- # properly in PKG-INFO
- metadata = DistributionMetadata()
- metadata['Version'] = '1.0'
- metadata['Project-Url'] = [('one', 'http://ok')]
- self.assertEqual(metadata['Project-Url'], [('one', 'http://ok')])
- file_ = StringIO()
- metadata.write_file(file_)
- file_.seek(0)
- res = file_.read().split('\n')
- self.assertIn('Project-URL: one,http://ok', res)
-
- file_.seek(0)
- metadata = DistributionMetadata()
- metadata.read_file(file_)
- self.assertEqual(metadata['Project-Url'], [('one', 'http://ok')])
-
-
-def test_suite():
- return unittest.makeSuite(DistributionMetadataTestCase)
-
-if __name__ == '__main__':
- run_unittest(test_suite())
diff --git a/src/distutils2/tests/test_msvc9compiler.py b/src/distutils2/tests/test_msvc9compiler.py
deleted file mode 100644
index eea83fa..0000000
--- a/src/distutils2/tests/test_msvc9compiler.py
+++ /dev/null
@@ -1,143 +0,0 @@
-"""Tests for distutils.msvc9compiler."""
-import sys
-import os
-
-from distutils2.errors import DistutilsPlatformError
-from distutils2.tests import support
-from distutils2.tests.support import unittest
-
-_MANIFEST = """\
-<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
-<assembly xmlns="urn:schemas-microsoft-com:asm.v1"
- manifestVersion="1.0">
- <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
- <security>
- <requestedPrivileges>
- <requestedExecutionLevel level="asInvoker" uiAccess="false">
- </requestedExecutionLevel>
- </requestedPrivileges>
- </security>
- </trustInfo>
- <dependency>
- <dependentAssembly>
- <assemblyIdentity type="win32" name="Microsoft.VC90.CRT"
- version="9.0.21022.8" processorArchitecture="x86"
- publicKeyToken="XXXX">
- </assemblyIdentity>
- </dependentAssembly>
- </dependency>
- <dependency>
- <dependentAssembly>
- <assemblyIdentity type="win32" name="Microsoft.VC90.MFC"
- version="9.0.21022.8" processorArchitecture="x86"
- publicKeyToken="XXXX"></assemblyIdentity>
- </dependentAssembly>
- </dependency>
-</assembly>
-"""
-
-_CLEANED_MANIFEST = """\
-<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
-<assembly xmlns="urn:schemas-microsoft-com:asm.v1"
- manifestVersion="1.0">
- <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
- <security>
- <requestedPrivileges>
- <requestedExecutionLevel level="asInvoker" uiAccess="false">
- </requestedExecutionLevel>
- </requestedPrivileges>
- </security>
- </trustInfo>
- <dependency>
-
- </dependency>
- <dependency>
- <dependentAssembly>
- <assemblyIdentity type="win32" name="Microsoft.VC90.MFC"
- version="9.0.21022.8" processorArchitecture="x86"
- publicKeyToken="XXXX"></assemblyIdentity>
- </dependentAssembly>
- </dependency>
-</assembly>"""
-
-
-class msvc9compilerTestCase(support.TempdirManager,
- unittest.TestCase):
-
- @unittest.skipUnless(sys.platform == "win32", "runs only on win32")
- def test_no_compiler(self):
- # makes sure query_vcvarsall throws
- # a DistutilsPlatformError if the compiler
- # is not found
- from distutils2.msvccompiler import get_build_version
- if get_build_version() < 8.0:
- # this test is only for MSVC8.0 or above
- return
- from distutils2.msvc9compiler import query_vcvarsall
- def _find_vcvarsall(version):
- return None
-
- from distutils2 import msvc9compiler
- old_find_vcvarsall = msvc9compiler.find_vcvarsall
- msvc9compiler.find_vcvarsall = _find_vcvarsall
- try:
- self.assertRaises(DistutilsPlatformError, query_vcvarsall,
- 'wont find this version')
- finally:
- msvc9compiler.find_vcvarsall = old_find_vcvarsall
-
- @unittest.skipUnless(sys.platform == "win32", "runs only on win32")
- def test_reg_class(self):
- from distutils2.msvccompiler import get_build_version
- if get_build_version() < 8.0:
- # this test is only for MSVC8.0 or above
- return
-
- from distutils2.msvc9compiler import Reg
- self.assertRaises(KeyError, Reg.get_value, 'xxx', 'xxx')
-
- # looking for values that should exist on all
- # windows registeries versions.
- path = r'Control Panel\Desktop'
- v = Reg.get_value(path, u'dragfullwindows')
- self.assertTrue(v in (u'0', u'1', u'2'))
-
- import _winreg
- HKCU = _winreg.HKEY_CURRENT_USER
- keys = Reg.read_keys(HKCU, 'xxxx')
- self.assertEqual(keys, None)
-
- keys = Reg.read_keys(HKCU, r'Control Panel')
- self.assertTrue('Desktop' in keys)
-
- @unittest.skipUnless(sys.platform == "win32", "runs only on win32")
- def test_remove_visual_c_ref(self):
- from distutils2.msvc9compiler import MSVCCompiler
- tempdir = self.mkdtemp()
- manifest = os.path.join(tempdir, 'manifest')
- f = open(manifest, 'w')
- try:
- f.write(_MANIFEST)
- finally:
- f.close()
-
- compiler = MSVCCompiler()
- compiler._remove_visual_c_ref(manifest)
-
- # see what we got
- f = open(manifest)
- try:
- # removing trailing spaces
- content = '\n'.join([line.rstrip() for line in f.readlines()])
- finally:
- f.close()
-
- # makes sure the manifest was properly cleaned
- self.assertEqual(content, _CLEANED_MANIFEST)
-
-
-def test_suite():
- return unittest.makeSuite(msvc9compilerTestCase)
-
-if __name__ == "__main__":
- unittest.main(defaultTest="test_suite")
diff --git a/src/distutils2/tests/test_pypi_server.py b/src/distutils2/tests/test_pypi_server.py
deleted file mode 100644
index 65061ec..0000000
--- a/src/distutils2/tests/test_pypi_server.py
+++ /dev/null
@@ -1,69 +0,0 @@
-"""Tests for distutils.command.bdist."""
-import urllib
-import urllib2
-import os.path
-
-from distutils2.tests.pypi_server import PyPIServer, PYPI_DEFAULT_STATIC_PATH
-from distutils2.tests.support import unittest
-
-
-class PyPIServerTest(unittest.TestCase):
-
- def test_records_requests(self):
- # We expect that PyPIServer can log our requests
- server = PyPIServer()
- server.start()
- self.assertEqual(len(server.requests), 0)
-
- data = "Rock Around The Bunker"
- headers = {"X-test-header": "Mister Iceberg"}
-
- request = urllib2.Request(server.full_address, data, headers)
- urllib2.urlopen(request)
- self.assertEqual(len(server.requests), 1)
- handler, request_data = server.requests[-1]
- self.assertIn("Rock Around The Bunker", request_data)
- self.assertIn("x-test-header", handler.headers.dict)
- self.assertEqual(handler.headers.dict["x-test-header"],
- "Mister Iceberg")
- server.stop()
-
- def test_serve_static_content(self):
- # PYPI Mocked server can serve static content from disk.
-
- def uses_local_files_for(server, url_path):
- """Test that files are served statically (eg. the output from the
- server is the same than the one made by a simple file read.
- """
- url = server.full_address + url_path
- request = urllib2.Request(url)
- response = urllib2.urlopen(request)
- file = open(PYPI_DEFAULT_STATIC_PATH + "/test_pypi_server" +
- url_path)
- return response.read() == file.read()
-
- server = PyPIServer(static_uri_paths=["simple", "external"],
- static_filesystem_paths=["test_pypi_server"])
- server.start()
-
- # the file does not exists on the disc, so it might not be served
- url = server.full_address + "/simple/unexisting_page"
- request = urllib2.Request(url)
- try:
- urllib2.urlopen(request)
- except urllib2.HTTPError,e:
- self.assertEqual(e.code, 404)
-
- # now try serving a content that do exists
- self.assertTrue(uses_local_files_for(server, "/simple/index.html"))
-
- # and another one in another root path
- self.assertTrue(uses_local_files_for(server, "/external/index.html"))
- server.stop()
-
-
-def test_suite():
- return unittest.makeSuite(PyPIServerTest)
-
-if __name__ == '__main__':
- unittest.main(defaultTest="test_suite")
diff --git a/src/distutils2/tests/test_pypi_versions.py b/src/distutils2/tests/test_pypi_versions.py
deleted file mode 100644
index bbb9395..0000000
--- a/src/distutils2/tests/test_pypi_versions.py
+++ /dev/null
@@ -1,127 +0,0 @@
-"""PEP 386 compatibility test with current distributions on PyPI.
-
-A very simple test to see what percentage of the current PyPI packages
-have versions that can be converted automatically by distutils2's new
-suggest_normalized_version into PEP 386-compatible versions.
-"""
-
-# XXX This file does not actually run tests, move it to a script
-
-# Written by ssteinerX@gmail.com
-
-import os
-import xmlrpclib
-
-try:
- import cPickle as pickle
-except ImportError:
- import pickle
-
-from distutils2.version import suggest_normalized_version
-from distutils2.tests import run_unittest
-from distutils2.tests.support import unittest
-
-def test_pypi():
- # FIXME need a better way to do that
- # To re-run from scratch, just delete these two .pkl files
- INDEX_PICKLE_FILE = 'pypi-index.pkl'
- VERSION_PICKLE_FILE = 'pypi-version.pkl'
-
- package_info = version_info = []
-
- # if there's a saved version of the package list
- # restore it
- # else:
- # pull the list down from pypi
- # save a pickled version of it
- if os.path.exists(INDEX_PICKLE_FILE):
- print "Loading saved pypi data..."
- f = open(INDEX_PICKLE_FILE, 'rb')
- try:
- package_info = pickle.load(f)
- finally:
- f.close()
- else:
- print "Retrieving pypi packages..."
- server = xmlrpclib.Server('http://pypi.python.org/pypi')
- package_info = server.search({'name': ''})
-
- print "Saving package info..."
- f = open(INDEX_PICKLE_FILE, 'wb')
- try:
- pickle.dump(package_info, f)
- finally:
- f.close()
-
- # If there's a saved list of the versions from the packages
- # restore it
- # else
- # extract versions from the package list
- # save a pickled version of it
- versions = []
- if os.path.exists(VERSION_PICKLE_FILE):
- print "Loading saved version info..."
- f = open(VERSION_PICKLE_FILE, 'rb')
- try:
- versions = pickle.load(f)
- finally:
- f.close()
- else:
- print "Extracting and saving version info..."
- versions = [p['version'] for p in package_info]
- o = open(VERSION_PICKLE_FILE, 'wb')
- try:
- pickle.dump(versions, o)
- finally:
- o.close()
-
- total_versions = len(versions)
- matches = 0.00
- no_sugg = 0.00
- have_sugg = 0.00
-
- suggs = []
- no_suggs = []
-
- for ver in versions:
- sugg = suggest_normalized_version(ver)
- if sugg == ver:
- matches += 1
- elif sugg == None:
- no_sugg += 1
- no_suggs.append(ver)
- else:
- have_sugg += 1
- suggs.append((ver, sugg))
-
- pct = "(%2.2f%%)"
- print "Results:"
- print "--------"
- print ""
- print "Suggestions"
- print "-----------"
- print ""
- for ver, sugg in suggs:
- print "%s -> %s" % (ver, sugg)
- print ""
- print "No suggestions"
- print "--------------"
- for ver in no_suggs:
- print ver
- print ""
- print "Summary:"
- print "--------"
- print "Total Packages : ", total_versions
- print "Already Match : ", matches, pct % (matches/total_versions*100,)
- print "Have Suggestion : ", have_sugg, pct % (have_sugg/total_versions*100,)
- print "No Suggestion : ", no_sugg, pct % (no_sugg/total_versions*100,)
-
-class TestPyPI(unittest.TestCase):
- pass
-
-def test_suite():
- return unittest.makeSuite(TestPyPI)
-
-if __name__ == '__main__':
- run_unittest(test_suite())
-
diff --git a/src/distutils2/tests/test_register.py b/src/distutils2/tests/test_register.py
deleted file mode 100644
index d232978..0000000
--- a/src/distutils2/tests/test_register.py
+++ /dev/null
@@ -1,262 +0,0 @@
-# -*- encoding: utf-8 -*-
-"""Tests for distutils.command.register."""
-import sys
-import os
-import getpass
-import urllib2
-
-try:
- import docutils
- DOCUTILS_SUPPORT = True
-except ImportError:
- DOCUTILS_SUPPORT = False
-
-from distutils2.command import register as register_module
-from distutils2.command.register import register
-from distutils2.core import Distribution
-from distutils2.errors import DistutilsSetupError
-
-from distutils2.tests import support
-from distutils2.tests.support import unittest
-
-
-PYPIRC_NOPASSWORD = """\
-[distutils]
-
-index-servers =
- server1
-
-[server1]
-username:me
-"""
-
-WANTED_PYPIRC = """\
-[distutils]
-index-servers =
- pypi
-
-[pypi]
-username:tarek
-password:password
-"""
-
-class RawInputs(object):
- """Fakes user inputs."""
- def __init__(self, *answers):
- self.answers = answers
- self.index = 0
-
- def __call__(self, prompt=''):
- try:
- return self.answers[self.index]
- finally:
- self.index += 1
-
-class FakeOpener(object):
- """Fakes a PyPI server"""
- def __init__(self):
- self.reqs = []
-
- def __call__(self, *args):
- return self
-
- def open(self, req):
- self.reqs.append(req)
- return self
-
- def read(self):
- return 'xxx'
-
-class RegisterTestCase(support.TempdirManager, support.EnvironGuard,
- unittest.TestCase):
-
- def setUp(self):
- super(RegisterTestCase, self).setUp()
- self.tmp_dir = self.mkdtemp()
- self.rc = os.path.join(self.tmp_dir, '.pypirc')
- os.environ['HOME'] = self.tmp_dir
-
- # patching the password prompt
- self._old_getpass = getpass.getpass
- def _getpass(prompt):
- return 'password'
- getpass.getpass = _getpass
- self.old_opener = urllib2.build_opener
- self.conn = urllib2.build_opener = FakeOpener()
-
- def tearDown(self):
- getpass.getpass = self._old_getpass
- urllib2.build_opener = self.old_opener
- super(RegisterTestCase, self).tearDown()
-
- def _get_cmd(self, metadata=None):
- if metadata is None:
- metadata = {'url': 'xxx', 'author': 'xxx',
- 'author_email': 'xxx',
- 'name': 'xxx', 'version': 'xxx'}
- pkg_info, dist = self.create_dist(**metadata)
- return register(dist)
-
- def test_create_pypirc(self):
- # this test makes sure a .pypirc file
- # is created when requested.
-
- # let's create a register instance
- cmd = self._get_cmd()
-
- # we shouldn't have a .pypirc file yet
- self.assertTrue(not os.path.exists(self.rc))
-
- # patching raw_input and getpass.getpass
- # so register gets happy
- #
- # Here's what we are faking :
- # use your existing login (choice 1.)
- # Username : 'tarek'
- # Password : 'password'
- # Save your login (y/N)? : 'y'
- inputs = RawInputs('1', 'tarek', 'y')
- register_module.raw_input = inputs.__call__
- # let's run the command
- try:
- cmd.run()
- finally:
- del register_module.raw_input
-
- # we should have a brand new .pypirc file
- self.assertTrue(os.path.exists(self.rc))
-
- # with the content similar to WANTED_PYPIRC
- content = open(self.rc).read()
- self.assertEqual(content, WANTED_PYPIRC)
-
- # now let's make sure the .pypirc file generated
- # really works : we shouldn't be asked anything
- # if we run the command again
- def _no_way(prompt=''):
- raise AssertionError(prompt)
- register_module.raw_input = _no_way
-
- cmd.show_response = 1
- cmd.run()
-
- # let's see what the server received : we should
- # have 2 similar requests
- self.assertTrue(self.conn.reqs, 2)
- req1 = dict(self.conn.reqs[0].headers)
- req2 = dict(self.conn.reqs[1].headers)
- self.assertEqual(req2['Content-length'], req1['Content-length'])
- self.assertTrue('xxx' in self.conn.reqs[1].data)
-
- def test_password_not_in_file(self):
-
- self.write_file(self.rc, PYPIRC_NOPASSWORD)
- cmd = self._get_cmd()
- cmd.finalize_options()
- cmd._set_config()
- cmd.send_metadata()
-
- # dist.password should be set
- # therefore used afterwards by other commands
- self.assertEqual(cmd.distribution.password, 'password')
-
- def test_registration(self):
- # this test runs choice 2
- cmd = self._get_cmd()
- inputs = RawInputs('2', 'tarek', 'tarek@ziade.org')
- register_module.raw_input = inputs.__call__
- try:
- # let's run the command
- # FIXME does this send a real request? use a mock server
- # also, silence self.announce (with LoggingCatcher)
- cmd.run()
- finally:
- del register_module.raw_input
-
- # we should have send a request
- self.assertTrue(self.conn.reqs, 1)
- req = self.conn.reqs[0]
- headers = dict(req.headers)
- self.assertEqual(headers['Content-length'], '608')
- self.assertTrue('tarek' in req.data)
-
- def test_password_reset(self):
- # this test runs choice 3
- cmd = self._get_cmd()
- inputs = RawInputs('3', 'tarek@ziade.org')
- register_module.raw_input = inputs.__call__
- try:
- # let's run the command
- cmd.run()
- finally:
- del register_module.raw_input
-
- # we should have send a request
- self.assertTrue(self.conn.reqs, 1)
- req = self.conn.reqs[0]
- headers = dict(req.headers)
- self.assertEqual(headers['Content-length'], '290')
- self.assertTrue('tarek' in req.data)
-
- @unittest.skipUnless(DOCUTILS_SUPPORT, 'needs docutils')
- def test_strict(self):
- # testing the script option
- # when on, the register command stops if
- # the metadata is incomplete or if
- # long_description is not reSt compliant
-
- # empty metadata
- cmd = self._get_cmd({})
- cmd.ensure_finalized()
- cmd.strict = 1
- self.assertRaises(DistutilsSetupError, cmd.run)
-
- # metadata is OK but long_description is broken
- metadata = {'home_page': 'xxx', 'author': 'xxx',
- 'author_email': u'éxéxé',
- 'name': 'xxx', 'version': 'xxx',
- 'description': 'title\n==\n\ntext'}
-
- cmd = self._get_cmd(metadata)
- cmd.ensure_finalized()
- cmd.strict = 1
-
- self.assertRaises(DistutilsSetupError, cmd.run)
-
- # now something that works
- metadata['description'] = 'title\n=====\n\ntext'
- cmd = self._get_cmd(metadata)
- cmd.ensure_finalized()
- cmd.strict = 1
- inputs = RawInputs('1', 'tarek', 'y')
- register_module.raw_input = inputs.__call__
- # let's run the command
- try:
- cmd.run()
- finally:
- del register_module.raw_input
-
- # strict is not by default
- cmd = self._get_cmd()
- cmd.ensure_finalized()
- inputs = RawInputs('1', 'tarek', 'y')
- register_module.raw_input = inputs.__call__
- # let's run the command
- try:
- cmd.run()
- finally:
- del register_module.raw_input
-
- def test_register_pep345(self):
- cmd = self._get_cmd({})
- cmd.ensure_finalized()
- cmd.distribution.metadata['Requires-Dist'] = ['lxml']
- data = cmd.build_post_data('submit')
- self.assertEqual(data['metadata_version'], '1.2')
- self.assertEqual(data['requires_dist'], ['lxml'])
-
-def test_suite():
- return unittest.makeSuite(RegisterTestCase)
-
-if __name__ == "__main__":
- unittest.main(defaultTest="test_suite")
diff --git a/src/distutils2/tests/test_sdist.py b/src/distutils2/tests/test_sdist.py
deleted file mode 100644
index 2bd1dfd..0000000
--- a/src/distutils2/tests/test_sdist.py
+++ /dev/null
@@ -1,423 +0,0 @@
-"""Tests for distutils.command.sdist."""
-import os
-import shutil
-import zipfile
-import tarfile
-
-# zlib is not used here, but if it's not available
-# the tests that use zipfile may fail
-try:
- import zlib
-except ImportError:
- zlib = None
-
-try:
- import grp
- import pwd
- UID_GID_SUPPORT = True
-except ImportError:
- UID_GID_SUPPORT = False
-
-from os.path import join
-import sys
-
-from distutils2.tests import captured_stdout
-
-from distutils2.command.sdist import sdist
-from distutils2.command.sdist import show_formats
-from distutils2.core import Distribution
-from distutils2.tests.support import unittest
-from distutils2.errors import DistutilsExecError, DistutilsOptionError
-from distutils2.util import find_executable
-from distutils2.tests import support
-from distutils2.log import WARN
-try:
- from shutil import get_archive_formats
-except ImportError:
- from distutils2._backport.shutil import get_archive_formats
-
-SETUP_PY = """
-from distutils.core import setup
-import somecode
-
-setup(name='fake')
-"""
-
-MANIFEST = """\
-# file GENERATED by distutils, do NOT edit
-README
-inroot.txt
-setup.py
-data%(sep)sdata.dt
-scripts%(sep)sscript.py
-some%(sep)sfile.txt
-some%(sep)sother_file.txt
-somecode%(sep)s__init__.py
-somecode%(sep)sdoc.dat
-somecode%(sep)sdoc.txt
-"""
-
-class SDistTestCase(support.TempdirManager, support.LoggingCatcher,
- support.EnvironGuard, unittest.TestCase):
-
- def setUp(self):
- # PyPIRCCommandTestCase creates a temp dir already
- # and put it in self.tmp_dir
- super(SDistTestCase, self).setUp()
- self.tmp_dir = self.mkdtemp()
- os.environ['HOME'] = self.tmp_dir
- # setting up an environment
- self.old_path = os.getcwd()
- os.mkdir(join(self.tmp_dir, 'somecode'))
- os.mkdir(join(self.tmp_dir, 'dist'))
- # a package, and a README
- self.write_file((self.tmp_dir, 'README'), 'xxx')
- self.write_file((self.tmp_dir, 'somecode', '__init__.py'), '#')
- self.write_file((self.tmp_dir, 'setup.py'), SETUP_PY)
- os.chdir(self.tmp_dir)
-
- def tearDown(self):
- # back to normal
- os.chdir(self.old_path)
- super(SDistTestCase, self).tearDown()
-
- def get_cmd(self, metadata=None):
- """Returns a cmd"""
- if metadata is None:
- metadata = {'name': 'fake', 'version': '1.0',
- 'url': 'xxx', 'author': 'xxx',
- 'author_email': 'xxx'}
- dist = Distribution(metadata)
- dist.script_name = 'setup.py'
- dist.packages = ['somecode']
- dist.include_package_data = True
- cmd = sdist(dist)
- cmd.dist_dir = 'dist'
- def _warn(*args):
- pass
- cmd.warn = _warn
- return dist, cmd
-
- @unittest.skipUnless(zlib, "requires zlib")
- def test_prune_file_list(self):
- # this test creates a package with some vcs dirs in it
- # and launch sdist to make sure they get pruned
- # on all systems
-
- # creating VCS directories with some files in them
- os.mkdir(join(self.tmp_dir, 'somecode', '.svn'))
- self.write_file((self.tmp_dir, 'somecode', '.svn', 'ok.py'), 'xxx')
-
- os.mkdir(join(self.tmp_dir, 'somecode', '.hg'))
- self.write_file((self.tmp_dir, 'somecode', '.hg',
- 'ok'), 'xxx')
-
- os.mkdir(join(self.tmp_dir, 'somecode', '.git'))
- self.write_file((self.tmp_dir, 'somecode', '.git',
- 'ok'), 'xxx')
-
- # now building a sdist
- dist, cmd = self.get_cmd()
-
- # zip is available universally
- # (tar might not be installed under win32)
- cmd.formats = ['zip']
-
- cmd.ensure_finalized()
- cmd.run()
-
- # now let's check what we have
- dist_folder = join(self.tmp_dir, 'dist')
- files = os.listdir(dist_folder)
- self.assertEqual(files, ['fake-1.0.zip'])
-
- zip_file = zipfile.ZipFile(join(dist_folder, 'fake-1.0.zip'))
- try:
- content = zip_file.namelist()
- finally:
- zip_file.close()
-
- # making sure everything has been pruned correctly
- self.assertEqual(len(content), 4)
-
- @unittest.skipUnless(zlib, "requires zlib")
- def test_make_distribution(self):
-
- # check if tar and gzip are installed
- if (find_executable('tar') is None or
- find_executable('gzip') is None):
- return
-
- # now building a sdist
- dist, cmd = self.get_cmd()
-
- # creating a gztar then a tar
- cmd.formats = ['gztar', 'tar']
- cmd.ensure_finalized()
- cmd.run()
-
- # making sure we have two files
- dist_folder = join(self.tmp_dir, 'dist')
- result = os.listdir(dist_folder)
- result.sort()
- self.assertEqual(result,
- ['fake-1.0.tar', 'fake-1.0.tar.gz'] )
-
- os.remove(join(dist_folder, 'fake-1.0.tar'))
- os.remove(join(dist_folder, 'fake-1.0.tar.gz'))
-
- # now trying a tar then a gztar
- cmd.formats = ['tar', 'gztar']
-
- cmd.ensure_finalized()
- cmd.run()
-
- result = os.listdir(dist_folder)
- result.sort()
- self.assertEqual(result,
- ['fake-1.0.tar', 'fake-1.0.tar.gz'])
-
- @unittest.skipUnless(zlib, "requires zlib")
- def test_add_defaults(self):
-
- # http://bugs.python.org/issue2279
-
- # add_default should also include
- # data_files and package_data
- dist, cmd = self.get_cmd()
-
- # filling data_files by pointing files
- # in package_data
- dist.package_data = {'': ['*.cfg', '*.dat'],
- 'somecode': ['*.txt']}
- self.write_file((self.tmp_dir, 'somecode', 'doc.txt'), '#')
- self.write_file((self.tmp_dir, 'somecode', 'doc.dat'), '#')
-
- # adding some data in data_files
- data_dir = join(self.tmp_dir, 'data')
- os.mkdir(data_dir)
- self.write_file((data_dir, 'data.dt'), '#')
- some_dir = join(self.tmp_dir, 'some')
- os.mkdir(some_dir)
- self.write_file((self.tmp_dir, 'inroot.txt'), '#')
- self.write_file((some_dir, 'file.txt'), '#')
- self.write_file((some_dir, 'other_file.txt'), '#')
-
- dist.data_files = [('data', ['data/data.dt',
- 'inroot.txt',
- 'notexisting']),
- 'some/file.txt',
- 'some/other_file.txt']
-
- # adding a script
- script_dir = join(self.tmp_dir, 'scripts')
- os.mkdir(script_dir)
- self.write_file((script_dir, 'script.py'), '#')
- dist.scripts = [join('scripts', 'script.py')]
-
- cmd.formats = ['zip']
- cmd.use_defaults = True
-
- cmd.ensure_finalized()
- cmd.run()
-
- # now let's check what we have
- dist_folder = join(self.tmp_dir, 'dist')
- files = os.listdir(dist_folder)
- self.assertEqual(files, ['fake-1.0.zip'])
-
- zip_file = zipfile.ZipFile(join(dist_folder, 'fake-1.0.zip'))
- try:
- content = zip_file.namelist()
- finally:
- zip_file.close()
-
- # making sure everything was added
- self.assertEqual(len(content), 11)
-
- # checking the MANIFEST
- manifest = open(join(self.tmp_dir, 'MANIFEST')).read()
- self.assertEqual(manifest, MANIFEST % {'sep': os.sep})
-
- @unittest.skipUnless(zlib, "requires zlib")
- def test_metadata_check_option(self):
- # testing the `check-metadata` option
- dist, cmd = self.get_cmd(metadata={})
-
- # this should raise some warnings !
- # with the `check` subcommand
- cmd.ensure_finalized()
- cmd.run()
- warnings = self.get_logs(WARN)
- self.assertEqual(len(warnings), 1)
-
- # trying with a complete set of metadata
- self.clear_logs()
- dist, cmd = self.get_cmd()
- cmd.ensure_finalized()
- cmd.metadata_check = 0
- cmd.run()
- warnings = self.get_logs(WARN)
- # removing manifest generated warnings
- warnings = [warn for warn in warnings if
- not warn.endswith('-- skipping')]
- self.assertEqual(len(warnings), 0)
-
-
- def test_show_formats(self):
- __, stdout = captured_stdout(show_formats)
-
- # the output should be a header line + one line per format
- num_formats = len(get_archive_formats())
- output = [line for line in stdout.split('\n')
- if line.strip().startswith('--formats=')]
- self.assertEqual(len(output), num_formats)
-
- def test_finalize_options(self):
-
- dist, cmd = self.get_cmd()
- cmd.finalize_options()
-
- # default options set by finalize
- self.assertEqual(cmd.manifest, 'MANIFEST')
- self.assertEqual(cmd.template, 'MANIFEST.in')
- self.assertEqual(cmd.dist_dir, 'dist')
-
- # formats has to be a string splitable on (' ', ',') or
- # a stringlist
- cmd.formats = 1
- self.assertRaises(DistutilsOptionError, cmd.finalize_options)
- cmd.formats = ['zip']
- cmd.finalize_options()
-
- # formats has to be known
- cmd.formats = 'supazipa'
- self.assertRaises(DistutilsOptionError, cmd.finalize_options)
-
- @unittest.skipUnless(zlib, "requires zlib")
- @unittest.skipUnless(UID_GID_SUPPORT, "requires grp and pwd support")
- def test_make_distribution_owner_group(self):
-
- # check if tar and gzip are installed
- if (find_executable('tar') is None or
- find_executable('gzip') is None):
- return
-
- # now building a sdist
- dist, cmd = self.get_cmd()
-
- # creating a gztar and specifying the owner+group
- cmd.formats = ['gztar']
- cmd.owner = pwd.getpwuid(0)[0]
- cmd.group = grp.getgrgid(0)[0]
- cmd.ensure_finalized()
- cmd.run()
-
- # making sure we have the good rights
- archive_name = join(self.tmp_dir, 'dist', 'fake-1.0.tar.gz')
- archive = tarfile.open(archive_name)
- try:
- for member in archive.getmembers():
- self.assertEqual(member.uid, 0)
- self.assertEqual(member.gid, 0)
- finally:
- archive.close()
-
- # building a sdist again
- dist, cmd = self.get_cmd()
-
- # creating a gztar
- cmd.formats = ['gztar']
- cmd.ensure_finalized()
- cmd.run()
-
- # making sure we have the good rights
- archive_name = join(self.tmp_dir, 'dist', 'fake-1.0.tar.gz')
- archive = tarfile.open(archive_name)
-
- # note that we are not testing the group ownership here
- # because, depending on the platforms and the container
- # rights (see #7408)
- try:
- for member in archive.getmembers():
- self.assertEqual(member.uid, os.getuid())
- finally:
- archive.close()
-
- def test_get_file_list(self):
- # make sure MANIFEST is recalculated
- dist, cmd = self.get_cmd()
-
- # filling data_files by pointing files in package_data
- dist.package_data = {'somecode': ['*.txt']}
- self.write_file((self.tmp_dir, 'somecode', 'doc.txt'), '#')
- cmd.ensure_finalized()
- cmd.run()
-
- f = open(cmd.manifest)
- try:
- manifest = [line.strip() for line in f.read().split('\n')
- if line.strip() != '']
- finally:
- f.close()
-
- self.assertEquals(len(manifest), 5)
-
- # adding a file
- self.write_file((self.tmp_dir, 'somecode', 'doc2.txt'), '#')
-
- # make sure build_py is reinitinialized, like a fresh run
- build_py = dist.get_command_obj('build_py')
- build_py.finalized = False
- build_py.ensure_finalized()
-
- cmd.run()
-
- f = open(cmd.manifest)
- try:
- manifest2 = [line.strip() for line in f.read().split('\n')
- if line.strip() != '']
- finally:
- f.close()
-
- # do we have the new file in MANIFEST ?
- self.assertEquals(len(manifest2), 6)
- self.assertIn('doc2.txt', manifest2[-1])
-
- def test_manifest_marker(self):
- # check that autogenerated MANIFESTs have a marker
- dist, cmd = self.get_cmd()
- cmd.ensure_finalized()
- cmd.run()
-
- f = open(cmd.manifest)
- try:
- manifest = [line.strip() for line in f.read().split('\n')
- if line.strip() != '']
- finally:
- f.close()
-
- self.assertEqual(manifest[0],
- '# file GENERATED by distutils, do NOT edit')
-
- def test_manual_manifest(self):
- # check that a MANIFEST without a marker is left alone
- dist, cmd = self.get_cmd()
- cmd.ensure_finalized()
- self.write_file((self.tmp_dir, cmd.manifest), 'README.manual')
- cmd.run()
-
- f = open(cmd.manifest)
- try:
- manifest = [line.strip() for line in f.read().split('\n')
- if line.strip() != '']
- finally:
- f.close()
-
- self.assertEqual(manifest, ['README.manual'])
-
-def test_suite():
- return unittest.makeSuite(SDistTestCase)
-
-if __name__ == "__main__":
- unittest.main(defaultTest="test_suite")
diff --git a/src/distutils2/tests/test_test.py b/src/distutils2/tests/test_test.py
deleted file mode 100644
index 68cd5f3..0000000
--- a/src/distutils2/tests/test_test.py
+++ /dev/null
@@ -1,198 +0,0 @@
-import os
-import re
-import sys
-import shutil
-import unittest as ut1
-
-from copy import copy
-from os.path import join
-from operator import getitem, setitem, delitem
-from StringIO import StringIO
-from distutils2.core import Command
-from distutils2.tests.support import unittest, TempdirManager
-from distutils2.command.test import test
-from distutils2.dist import Distribution
-
-try:
- any
-except NameError:
- from distutils2._backport import any
-
-EXPECTED_OUTPUT_RE = r'''FAIL: test_blah \(myowntestmodule.SomeTest\)
-----------------------------------------------------------------------
-Traceback \(most recent call last\):
- File ".+/myowntestmodule.py", line \d+, in test_blah
- self.fail\("horribly"\)
-AssertionError: horribly
-'''
-
-here = os.path.dirname(os.path.abspath(__file__))
-
-class TestTest(TempdirManager,
- unittest.TestCase):
-
- def setUp(self):
- super(TestTest, self).setUp()
-
- distutils2path = os.path.dirname(os.path.dirname(here))
- self.old_pythonpath = os.environ.get('PYTHONPATH', '')
- os.environ['PYTHONPATH'] = distutils2path + os.pathsep + self.old_pythonpath
-
- def tearDown(self):
- os.environ['PYTHONPATH'] = self.old_pythonpath
- super(TestTest, self).tearDown()
-
- def assert_re_match(self, pattern, string):
- def quote(s):
- lines = ['## ' + line for line in s.split('\n')]
- sep = ["#" * 60]
- return [''] + sep + lines + sep
- msg = quote(pattern) + ["didn't match"] + quote(string)
- msg = "\n".join(msg)
- if not re.search(pattern, string):
- self.fail(msg)
-
- def prepare_dist(self, dist_name):
- pkg_dir = join(os.path.dirname(__file__), "dists", dist_name)
- temp_pkg_dir = join(self.mkdtemp(), dist_name)
- shutil.copytree(pkg_dir, temp_pkg_dir)
- return temp_pkg_dir
-
- def safely_replace(self, obj, attr, new_val=None, delete=False, dictionary=False):
- """Replace a object's attribute returning to its original state at the
- end of the test run. Creates the attribute if not present before
- (deleting afterwards). When delete=True, makes sure the value is del'd
- for the test run. If dictionary is set to True, operates of its items
- rather than attributes."""
- if dictionary:
- _setattr, _getattr, _delattr = setitem, getitem, delitem
- def _hasattr(_dict, value):
- return value in _dict
- else:
- _setattr, _getattr, _delattr, _hasattr = setattr, getattr, delattr, hasattr
-
- orig_has_attr = _hasattr(obj, attr)
- if orig_has_attr:
- orig_val = _getattr(obj, attr)
-
- if delete is False:
- _setattr(obj, attr, new_val)
- elif orig_has_attr:
- _delattr(obj, attr)
-
- def do_cleanup():
- if orig_has_attr:
- _setattr(obj, attr, orig_val)
- elif _hasattr(obj, attr):
- _delattr(obj, attr)
-
- self.addCleanup(do_cleanup)
-
- def test_runs_unittest(self):
- module_name, a_module = self.prepare_a_module()
- record = []
- a_module.recorder = lambda *args: record.append("suite")
-
- class MockTextTestRunner(object):
- def __init__(*_, **__): pass
- def run(_self, suite):
- record.append("run")
- self.safely_replace(ut1, "TextTestRunner", MockTextTestRunner)
-
- dist = Distribution()
- cmd = test(dist)
- cmd.suite = "%s.recorder" % module_name
- cmd.run()
- self.assertEqual(record, ["suite", "run"])
-
- def test_builds_before_running_tests(self):
- dist = Distribution()
- cmd = test(dist)
- cmd.runner = self.prepare_named_function(lambda: None)
- record = []
- class MockBuildCmd(Command):
- build_lib = "mock build lib"
- def initialize_options(self): pass
- def finalize_options(self): pass
- def run(self): record.append("build run")
- dist.cmdclass['build'] = MockBuildCmd
-
- cmd.ensure_finalized()
- cmd.run()
- self.assertEqual(record, ['build run'])
-
- def _test_works_with_2to3(self):
- pass
-
- def test_checks_requires(self):
- dist = Distribution()
- cmd = test(dist)
- phony_project = 'ohno_ohno-impossible_1234-name_stop-that!'
- cmd.tests_require = [phony_project]
- record = []
- cmd.announce = lambda *args: record.append(args)
- cmd.ensure_finalized()
- self.assertEqual(1, len(record))
- self.assertIn(phony_project, record[0][0])
-
- def prepare_a_module(self):
- tmp_dir = self.mkdtemp()
- sys.path.append(tmp_dir)
- self.addCleanup(lambda: sys.path.remove(tmp_dir))
-
- self.write_file((tmp_dir, 'distutils2_tests_a.py'), '')
- import distutils2_tests_a as a_module
- return "distutils2_tests_a", a_module
-
- def prepare_named_function(self, func):
- module_name, a_module = self.prepare_a_module()
- a_module.recorder = func
- return "%s.recorder" % module_name
-
- def test_custom_runner(self):
- dist = Distribution()
- cmd = test(dist)
-
- record = []
- cmd.runner = self.prepare_named_function(lambda: record.append("runner called"))
- cmd.ensure_finalized()
- cmd.run()
- self.assertEqual(["runner called"], record)
-
- def prepare_mock_ut2(self):
- class MockUTClass(object):
- def __init__(*_, **__): pass
- def discover(self): pass
- def run(self, _): pass
- class MockUTModule(object):
- TestLoader = MockUTClass
- TextTestRunner = MockUTClass
- mock_ut2 = MockUTModule()
- self.safely_replace(sys.modules, "unittest2", mock_ut2, dictionary=True)
- return mock_ut2
-
- def test_gets_unittest_discovery(self):
- mock_ut2 = self.prepare_mock_ut2()
- dist = Distribution()
- cmd = test(dist)
- self.safely_replace(ut1.TestLoader, "discover", lambda: None)
- self.assertEqual(cmd.get_ut_with_discovery(), ut1)
-
- del ut1.TestLoader.discover
- self.assertEqual(cmd.get_ut_with_discovery(), mock_ut2)
-
- def test_calls_discover(self):
- self.safely_replace(ut1.TestLoader, "discover", delete=True)
- mock_ut2 = self.prepare_mock_ut2()
- record = []
- mock_ut2.TestLoader.discover = lambda self, path: record.append(path)
- dist = Distribution()
- cmd = test(dist)
- cmd.run()
- self.assertEqual(record, [os.curdir])
-
-def test_suite():
- return unittest.makeSuite(TestTest)
-
-if __name__ == "__main__":
- unittest.main(defaultTest="test_suite")
diff --git a/src/distutils2/tests/test_unixccompiler.py b/src/distutils2/tests/test_unixccompiler.py
deleted file mode 100644
index 6de616a..0000000
--- a/src/distutils2/tests/test_unixccompiler.py
+++ /dev/null
@@ -1,133 +0,0 @@
-"""Tests for distutils.unixccompiler."""
-import sys
-
-try:
- import sysconfig
-except ImportError:
- from distutils2._backport import sysconfig
-
-from distutils2.compiler.unixccompiler import UnixCCompiler
-from distutils2.tests.support import unittest
-
-class UnixCCompilerTestCase(unittest.TestCase):
-
- def setUp(self):
- self._backup_platform = sys.platform
- self._backup_get_config_var = sysconfig.get_config_var
- class CompilerWrapper(UnixCCompiler):
- def rpath_foo(self):
- return self.runtime_library_dir_option('/foo')
- self.cc = CompilerWrapper()
-
- def tearDown(self):
- sys.platform = self._backup_platform
- sysconfig.get_config_var = self._backup_get_config_var
-
- def test_runtime_libdir_option(self):
-
- # not tested under windows
- if sys.platform == 'win32':
- return
-
- # Issue#5900
- #
- # Ensure RUNPATH is added to extension modules with RPATH if
- # GNU ld is used
-
- # darwin
- sys.platform = 'darwin'
- self.assertEqual(self.cc.rpath_foo(), '-L/foo')
-
- # hp-ux
- sys.platform = 'hp-ux'
- old_gcv = sysconfig.get_config_var
- def gcv(v):
- return 'xxx'
- sysconfig.get_config_var = gcv
- self.assertEqual(self.cc.rpath_foo(), ['+s', '-L/foo'])
-
- def gcv(v):
- return 'gcc'
- sysconfig.get_config_var = gcv
- self.assertEqual(self.cc.rpath_foo(), ['-Wl,+s', '-L/foo'])
-
- def gcv(v):
- return 'g++'
- sysconfig.get_config_var = gcv
- self.assertEqual(self.cc.rpath_foo(), ['-Wl,+s', '-L/foo'])
-
- sysconfig.get_config_var = old_gcv
-
- # irix646
- sys.platform = 'irix646'
- self.assertEqual(self.cc.rpath_foo(), ['-rpath', '/foo'])
-
- # osf1V5
- sys.platform = 'osf1V5'
- self.assertEqual(self.cc.rpath_foo(), ['-rpath', '/foo'])
-
- # GCC GNULD
- sys.platform = 'bar'
- def gcv(v):
- if v == 'CC':
- return 'gcc'
- elif v == 'GNULD':
- return 'yes'
- sysconfig.get_config_var = gcv
- self.assertEqual(self.cc.rpath_foo(), '-Wl,--enable-new-dtags,-R/foo')
-
- # GCC non-GNULD
- sys.platform = 'bar'
- def gcv(v):
- if v == 'CC':
- return 'gcc'
- elif v == 'GNULD':
- return 'no'
- sysconfig.get_config_var = gcv
- self.assertEqual(self.cc.rpath_foo(), '-Wl,-R/foo')
-
- # GCC GNULD with fully qualified configuration prefix
- # see #7617
- sys.platform = 'bar'
- def gcv(v):
- if v == 'CC':
- return 'x86_64-pc-linux-gnu-gcc-4.4.2'
- elif v == 'GNULD':
- return 'yes'
- sysconfig.get_config_var = gcv
- self.assertEqual(self.cc.rpath_foo(), '-Wl,--enable-new-dtags,-R/foo')
-
-
- # non-GCC GNULD
- sys.platform = 'bar'
- def gcv(v):
- if v == 'CC':
- return 'cc'
- elif v == 'GNULD':
- return 'yes'
- sysconfig.get_config_var = gcv
- self.assertEqual(self.cc.rpath_foo(), '-R/foo')
-
- # non-GCC non-GNULD
- sys.platform = 'bar'
- def gcv(v):
- if v == 'CC':
- return 'cc'
- elif v == 'GNULD':
- return 'no'
- sysconfig.get_config_var = gcv
- self.assertEqual(self.cc.rpath_foo(), '-R/foo')
-
- # AIX C/C++ linker
- sys.platform = 'aix'
- def gcv(v):
- return 'xxx'
- sysconfig.get_config_var = gcv
- self.assertEqual(self.cc.rpath_foo(), '-blibpath:/foo')
-
-
-def test_suite():
- return unittest.makeSuite(UnixCCompilerTestCase)
-
-if __name__ == "__main__":
- unittest.main(defaultTest="test_suite")
diff --git a/src/distutils2/tests/test_upload.py b/src/distutils2/tests/test_upload.py
deleted file mode 100644
index a12e227..0000000
--- a/src/distutils2/tests/test_upload.py
+++ /dev/null
@@ -1,140 +0,0 @@
-# -*- encoding: utf-8 -*-
-"""Tests for distutils.command.upload."""
-import os
-import sys
-
-from distutils2.command.upload import upload
-from distutils2.core import Distribution
-
-from distutils2.tests import support
-from distutils2.tests.pypi_server import PyPIServer, PyPIServerTestCase
-from distutils2.tests.support import unittest
-
-
-PYPIRC_NOPASSWORD = """\
-[distutils]
-
-index-servers =
- server1
-
-[server1]
-username:me
-"""
-
-PYPIRC = """\
-[distutils]
-
-index-servers =
- server1
- server2
-
-[server1]
-username:me
-password:secret
-
-[server2]
-username:meagain
-password: secret
-realm:acme
-repository:http://another.pypi/
-"""
-
-
-class UploadTestCase(support.TempdirManager, support.EnvironGuard,
- support.LoggingCatcher, PyPIServerTestCase):
-
- def setUp(self):
- super(UploadTestCase, self).setUp()
- self.tmp_dir = self.mkdtemp()
- self.rc = os.path.join(self.tmp_dir, '.pypirc')
- os.environ['HOME'] = self.tmp_dir
-
- def test_finalize_options(self):
- # new format
- self.write_file(self.rc, PYPIRC)
- dist = Distribution()
- cmd = upload(dist)
- cmd.finalize_options()
- for attr, expected in (('username', 'me'), ('password', 'secret'),
- ('realm', 'pypi'),
- ('repository', 'http://pypi.python.org/pypi')):
- self.assertEqual(getattr(cmd, attr), expected)
-
- def test_saved_password(self):
- # file with no password
- self.write_file(self.rc, PYPIRC_NOPASSWORD)
-
- # make sure it passes
- dist = Distribution()
- cmd = upload(dist)
- cmd.ensure_finalized()
- self.assertEqual(cmd.password, None)
-
- # make sure we get it as well, if another command
- # initialized it at the dist level
- dist.password = 'xxx'
- cmd = upload(dist)
- cmd.finalize_options()
- self.assertEqual(cmd.password, 'xxx')
-
- def test_upload(self):
- path = os.path.join(self.tmp_dir, 'xxx')
- self.write_file(path)
- command, pyversion, filename = 'xxx', '2.6', path
- dist_files = [(command, pyversion, filename)]
-
- # lets run it
- pkg_dir, dist = self.create_dist(dist_files=dist_files, author=u'dédé')
- cmd = upload(dist)
- cmd.ensure_finalized()
- cmd.repository = self.pypi.full_address
- cmd.run()
-
- # what did we send ?
- handler, request_data = self.pypi.requests[-1]
- headers = handler.headers.dict
- self.assertIn('dédé', request_data)
- self.assertIn('xxx', request_data)
- self.assertEqual(int(headers['content-length']), len(request_data))
- self.assertTrue(int(headers['content-length']) < 2000)
- self.assertTrue(headers['content-type'].startswith('multipart/form-data'))
- self.assertEqual(handler.command, 'POST')
- self.assertNotIn('\n', headers['authorization'])
-
- def test_upload_docs(self):
- path = os.path.join(self.tmp_dir, 'xxx')
- self.write_file(path)
- command, pyversion, filename = 'xxx', '2.6', path
- dist_files = [(command, pyversion, filename)]
- docs_path = os.path.join(self.tmp_dir, "build", "docs")
- os.makedirs(docs_path)
- self.write_file(os.path.join(docs_path, "index.html"), "yellow")
- self.write_file(self.rc, PYPIRC)
-
- # lets run it
- pkg_dir, dist = self.create_dist(dist_files=dist_files, author=u'dédé')
-
- cmd = upload(dist)
- cmd.get_finalized_command("build").run()
- cmd.upload_docs = True
- cmd.ensure_finalized()
- cmd.repository = self.pypi.full_address
- try:
- prev_dir = os.getcwd()
- os.chdir(self.tmp_dir)
- cmd.run()
- finally:
- os.chdir(prev_dir)
-
- handler, request_data = self.pypi.requests[-1]
- action, name, content =\
- request_data.split("----------------GHSKFJDLGDS7543FJKLFHRE75642756743254")[1:4]
-
- self.assertIn('name=":action"', action)
- self.assertIn("doc_upload", action)
-
-def test_suite():
- return unittest.makeSuite(UploadTestCase)
-
-if __name__ == "__main__":
- unittest.main(defaultTest="test_suite")
diff --git a/src/distutils2/tests/test_upload_docs.py b/src/distutils2/tests/test_upload_docs.py
deleted file mode 100644
index f7e323d..0000000
--- a/src/distutils2/tests/test_upload_docs.py
+++ /dev/null
@@ -1,201 +0,0 @@
-# -*- encoding: utf-8 -*-
-"""Tests for distutils.command.upload_docs."""
-import os
-import sys
-import httplib
-import shutil
-import zipfile
-try:
- from cStringIO import StringIO
-except ImportError:
- from StringIO import StringIO
-
-from distutils2.command import upload_docs as upload_docs_mod
-from distutils2.command.upload_docs import (upload_docs, zip_dir,
- encode_multipart)
-from distutils2.core import Distribution
-from distutils2.errors import DistutilsFileError, DistutilsOptionError
-
-from distutils2.tests import support
-from distutils2.tests.pypi_server import PyPIServer, PyPIServerTestCase
-from distutils2.tests.support import unittest
-
-
-EXPECTED_MULTIPART_OUTPUT = "\r\n".join([
-'---x',
-'Content-Disposition: form-data; name="a"',
-'',
-'b',
-'---x',
-'Content-Disposition: form-data; name="c"',
-'',
-'d',
-'---x',
-'Content-Disposition: form-data; name="e"; filename="f"',
-'',
-'g',
-'---x',
-'Content-Disposition: form-data; name="h"; filename="i"',
-'',
-'j',
-'---x--',
-'',
-])
-
-PYPIRC = """\
-[distutils]
-index-servers = server1
-
-[server1]
-repository = %s
-username = real_slim_shady
-password = long_island
-"""
-
-class UploadDocsTestCase(support.TempdirManager, support.EnvironGuard,
- support.LoggingCatcher, PyPIServerTestCase):
-
- def setUp(self):
- super(UploadDocsTestCase, self).setUp()
- self.tmp_dir = self.mkdtemp()
- self.rc = os.path.join(self.tmp_dir, '.pypirc')
- os.environ['HOME'] = self.tmp_dir
- self.dist = Distribution()
- self.dist.metadata['Name'] = "distr-name"
- self.cmd = upload_docs(self.dist)
-
- def test_default_uploaddir(self):
- sandbox = self.mkdtemp()
- previous = os.getcwd()
- os.chdir(sandbox)
- try:
- os.mkdir("build")
- self.prepare_sample_dir("build")
- self.cmd.ensure_finalized()
- self.assertEqual(self.cmd.upload_dir, os.path.join("build", "docs"))
- finally:
- os.chdir(previous)
-
- def prepare_sample_dir(self, sample_dir=None):
- if sample_dir is None:
- sample_dir = self.mkdtemp()
- os.mkdir(os.path.join(sample_dir, "docs"))
- self.write_file(os.path.join(sample_dir, "docs", "index.html"), "Ce mortel ennui")
- self.write_file(os.path.join(sample_dir, "index.html"), "Oh la la")
- return sample_dir
-
- def test_zip_dir(self):
- source_dir = self.prepare_sample_dir()
- compressed = zip_dir(source_dir)
-
- zip_f = zipfile.ZipFile(compressed)
- self.assertEqual(zip_f.namelist(), ['index.html', 'docs/index.html'])
-
- def test_encode_multipart(self):
- fields = [("a", "b"), ("c", "d")]
- files = [("e", "f", "g"), ("h", "i", "j")]
- content_type, body = encode_multipart(fields, files, "-x")
- self.assertEqual(content_type, "multipart/form-data; boundary=-x")
- self.assertEqual(body, EXPECTED_MULTIPART_OUTPUT)
-
- def prepare_command(self):
- self.cmd.upload_dir = self.prepare_sample_dir()
- self.cmd.ensure_finalized()
- self.cmd.repository = self.pypi.full_address
- self.cmd.username = "username"
- self.cmd.password = "password"
-
- def test_upload(self):
- self.prepare_command()
- self.cmd.run()
-
- self.assertEqual(len(self.pypi.requests), 1)
- handler, request_data = self.pypi.requests[-1]
- self.assertIn("content", request_data)
- self.assertIn("Basic", handler.headers.dict['authorization'])
- self.assertTrue(handler.headers.dict['content-type']
- .startswith('multipart/form-data;'))
-
- action, name, version, content =\
- request_data.split("----------------GHSKFJDLGDS7543FJKLFHRE75642756743254")[1:5]
-
- # check that we picked the right chunks
- self.assertIn('name=":action"', action)
- self.assertIn('name="name"', name)
- self.assertIn('name="version"', version)
- self.assertIn('name="content"', content)
-
- # check their contents
- self.assertIn("doc_upload", action)
- self.assertIn("distr-name", name)
- self.assertIn("docs/index.html", content)
- self.assertIn("Ce mortel ennui", content)
-
- def test_https_connection(self):
- https_called = False
- orig_https = upload_docs_mod.httplib.HTTPSConnection
- def https_conn_wrapper(*args):
- https_called = True
- return upload_docs_mod.httplib.HTTPConnection(*args) # the testing server is http
- upload_docs_mod.httplib.HTTPSConnection = https_conn_wrapper
- try:
- self.prepare_command()
- self.cmd.run()
- self.assertFalse(https_called)
-
- self.cmd.repository = self.cmd.repository.replace("http", "https")
- self.cmd.run()
- self.assertFalse(https_called)
- finally:
- upload_docs_mod.httplib.HTTPSConnection = orig_https
-
- def test_handling_response(self):
- calls = []
- def aggr(*args):
- calls.append(args)
- self.pypi.default_response_status = '403 Forbidden'
- self.prepare_command()
- self.cmd.announce = aggr
- self.cmd.run()
- message, _ = calls[-1]
- self.assertIn('Upload failed (403): Forbidden', message)
-
- calls = []
- self.pypi.default_response_status = '301 Moved Permanently'
- self.pypi.default_response_headers.append(("Location", "brand_new_location"))
- self.cmd.run()
- message, _ = calls[-1]
- self.assertIn('brand_new_location', message)
-
- def test_reads_pypirc_data(self):
- self.write_file(self.rc, PYPIRC % self.pypi.full_address)
- self.cmd.repository = self.pypi.full_address
- self.cmd.upload_dir = self.prepare_sample_dir()
- self.cmd.ensure_finalized()
- self.assertEqual(self.cmd.username, "real_slim_shady")
- self.assertEqual(self.cmd.password, "long_island")
-
- def test_checks_index_html_presence(self):
- self.cmd.upload_dir = self.prepare_sample_dir()
- os.remove(os.path.join(self.cmd.upload_dir, "index.html"))
- self.assertRaises(DistutilsFileError, self.cmd.ensure_finalized)
-
- def test_checks_upload_dir(self):
- self.cmd.upload_dir = self.prepare_sample_dir()
- shutil.rmtree(os.path.join(self.cmd.upload_dir))
- self.assertRaises(DistutilsOptionError, self.cmd.ensure_finalized)
-
- def test_show_response(self):
- self.prepare_command()
- self.cmd.show_response = True
- self.cmd.run()
- record = self.logs[-1][1]
-
- self.assertTrue(record, "should report the response")
- self.assertIn(self.pypi.default_response_data, record)
-
-def test_suite():
- return unittest.makeSuite(UploadDocsTestCase)
-
-if __name__ == "__main__":
- unittest.main(defaultTest="test_suite")
diff --git a/src/distutils2/tests/test_util.py b/src/distutils2/tests/test_util.py
deleted file mode 100644
index 0907433..0000000
--- a/src/distutils2/tests/test_util.py
+++ /dev/null
@@ -1,484 +0,0 @@
-"""Tests for distutils.util."""
-import os
-import sys
-from copy import copy
-from StringIO import StringIO
-import subprocess
-import time
-
-from distutils2.tests import captured_stdout
-from distutils2.tests.support import unittest
-from distutils2.errors import (DistutilsPlatformError,
- DistutilsByteCompileError,
- DistutilsFileError,
- DistutilsExecError)
-from distutils2.util import (convert_path, change_root,
- check_environ, split_quoted, strtobool,
- rfc822_escape, get_compiler_versions,
- _find_exe_version, _MAC_OS_X_LD_VERSION,
- byte_compile, find_packages, spawn, find_executable,
- _nt_quote_args, get_pypirc_path, generate_pypirc,
- read_pypirc, resolve_name)
-
-from distutils2 import util
-from distutils2.tests import support
-from distutils2.tests.support import unittest
-
-
-PYPIRC = """\
-[distutils]
-index-servers =
- pypi
- server1
-
-[pypi]
-username:me
-password:xxxx
-
-[server1]
-repository:http://example.com
-username:tarek
-password:secret
-"""
-
-PYPIRC_OLD = """\
-[server-login]
-username:tarek
-password:secret
-"""
-
-WANTED = """\
-[distutils]
-index-servers =
- pypi
-
-[pypi]
-username:tarek
-password:xxx
-"""
-
-
-class FakePopen(object):
- test_class = None
- def __init__(self, cmd, shell, stdout, stderr):
- self.cmd = cmd.split()[0]
- exes = self.test_class._exes
- if self.cmd not in exes:
- # we don't want to call the system, returning an empty
- # output so it doesn't match
- self.stdout = StringIO()
- self.stderr = StringIO()
- else:
- self.stdout = StringIO(exes[self.cmd])
- self.stderr = StringIO()
-
-class UtilTestCase(support.EnvironGuard,
- support.TempdirManager,
- support.LoggingCatcher,
- unittest.TestCase):
-
- def setUp(self):
- super(UtilTestCase, self).setUp()
- self.tmp_dir = self.mkdtemp()
- self.rc = os.path.join(self.tmp_dir, '.pypirc')
- os.environ['HOME'] = self.tmp_dir
- # saving the environment
- self.name = os.name
- self.platform = sys.platform
- self.version = sys.version
- self.sep = os.sep
- self.join = os.path.join
- self.isabs = os.path.isabs
- self.splitdrive = os.path.splitdrive
- #self._config_vars = copy(sysconfig._config_vars)
-
- # patching os.uname
- if hasattr(os, 'uname'):
- self.uname = os.uname
- self._uname = os.uname()
- else:
- self.uname = None
- self._uname = None
- os.uname = self._get_uname
-
- # patching POpen
- self.old_find_executable = util.find_executable
- util.find_executable = self._find_executable
- self._exes = {}
- self.old_popen = subprocess.Popen
- self.old_stdout = sys.stdout
- self.old_stderr = sys.stderr
- FakePopen.test_class = self
- subprocess.Popen = FakePopen
-
- def tearDown(self):
- # getting back the environment
- os.name = self.name
- sys.platform = self.platform
- sys.version = self.version
- os.sep = self.sep
- os.path.join = self.join
- os.path.isabs = self.isabs
- os.path.splitdrive = self.splitdrive
- if self.uname is not None:
- os.uname = self.uname
- else:
- del os.uname
- #sysconfig._config_vars = copy(self._config_vars)
- util.find_executable = self.old_find_executable
- subprocess.Popen = self.old_popen
- sys.old_stdout = self.old_stdout
- sys.old_stderr = self.old_stderr
- super(UtilTestCase, self).tearDown()
-
- def _set_uname(self, uname):
- self._uname = uname
-
- def _get_uname(self):
- return self._uname
-
- def test_convert_path(self):
- # linux/mac
- os.sep = '/'
- def _join(path):
- return '/'.join(path)
- os.path.join = _join
-
- self.assertEqual(convert_path('/home/to/my/stuff'),
- '/home/to/my/stuff')
-
- # win
- os.sep = '\\'
- def _join(*path):
- return '\\'.join(path)
- os.path.join = _join
-
- self.assertRaises(ValueError, convert_path, '/home/to/my/stuff')
- self.assertRaises(ValueError, convert_path, 'home/to/my/stuff/')
-
- self.assertEqual(convert_path('home/to/my/stuff'),
- 'home\\to\\my\\stuff')
- self.assertEqual(convert_path('.'),
- os.curdir)
-
- def test_change_root(self):
- # linux/mac
- os.name = 'posix'
- def _isabs(path):
- return path[0] == '/'
- os.path.isabs = _isabs
- def _join(*path):
- return '/'.join(path)
- os.path.join = _join
-
- self.assertEqual(change_root('/root', '/old/its/here'),
- '/root/old/its/here')
- self.assertEqual(change_root('/root', 'its/here'),
- '/root/its/here')
-
- # windows
- os.name = 'nt'
- def _isabs(path):
- return path.startswith('c:\\')
- os.path.isabs = _isabs
- def _splitdrive(path):
- if path.startswith('c:'):
- return ('', path.replace('c:', ''))
- return ('', path)
- os.path.splitdrive = _splitdrive
- def _join(*path):
- return '\\'.join(path)
- os.path.join = _join
-
- self.assertEqual(change_root('c:\\root', 'c:\\old\\its\\here'),
- 'c:\\root\\old\\its\\here')
- self.assertEqual(change_root('c:\\root', 'its\\here'),
- 'c:\\root\\its\\here')
-
- # BugsBunny os (it's a great os)
- os.name = 'BugsBunny'
- self.assertRaises(DistutilsPlatformError,
- change_root, 'c:\\root', 'its\\here')
-
- # XXX platforms to be covered: os2, mac
-
- def test_split_quoted(self):
- self.assertEqual(split_quoted('""one"" "two" \'three\' \\four'),
- ['one', 'two', 'three', 'four'])
-
- def test_strtobool(self):
- yes = ('y', 'Y', 'yes', 'True', 't', 'true', 'True', 'On', 'on', '1')
- no = ('n', 'no', 'f', 'false', 'off', '0', 'Off', 'No', 'N')
-
- for y in yes:
- self.assertTrue(strtobool(y))
-
- for n in no:
- self.assertTrue(not strtobool(n))
-
- def test_rfc822_escape(self):
- header = 'I am a\npoor\nlonesome\nheader\n'
- res = rfc822_escape(header)
- wanted = ('I am a%(8s)spoor%(8s)slonesome%(8s)s'
- 'header%(8s)s') % {'8s': '\n'+8*' '}
- self.assertEqual(res, wanted)
-
- def test_find_exe_version(self):
- # the ld version scheme under MAC OS is:
- # ^@(#)PROGRAM:ld PROJECT:ld64-VERSION
- #
- # where VERSION is a 2-digit number for major
- # revisions. For instance under Leopard, it's
- # currently 77
- #
- # Dots are used when branching is done.
- #
- # The SnowLeopard ld64 is currently 95.2.12
-
- for output, version in (('@(#)PROGRAM:ld PROJECT:ld64-77', '77'),
- ('@(#)PROGRAM:ld PROJECT:ld64-95.2.12',
- '95.2.12')):
- result = _MAC_OS_X_LD_VERSION.search(output)
- self.assertEqual(result.group(1), version)
-
- def _find_executable(self, name):
- if name in self._exes:
- return name
- return None
-
- def test_get_compiler_versions(self):
- # get_versions calls distutils.spawn.find_executable on
- # 'gcc', 'ld' and 'dllwrap'
- self.assertEqual(get_compiler_versions(), (None, None, None))
-
- # Let's fake we have 'gcc' and it returns '3.4.5'
- self._exes['gcc'] = 'gcc (GCC) 3.4.5 (mingw special)\nFSF'
- res = get_compiler_versions()
- self.assertEqual(str(res[0]), '3.4.5')
-
- # and let's see what happens when the version
- # doesn't match the regular expression
- # (\d+\.\d+(\.\d+)*)
- self._exes['gcc'] = 'very strange output'
- res = get_compiler_versions()
- self.assertEqual(res[0], None)
-
- # same thing for ld
- if sys.platform != 'darwin':
- self._exes['ld'] = 'GNU ld version 2.17.50 20060824'
- res = get_compiler_versions()
- self.assertEqual(str(res[1]), '2.17.50')
- self._exes['ld'] = '@(#)PROGRAM:ld PROJECT:ld64-77'
- res = get_compiler_versions()
- self.assertEqual(res[1], None)
- else:
- self._exes['ld'] = 'GNU ld version 2.17.50 20060824'
- res = get_compiler_versions()
- self.assertEqual(res[1], None)
- self._exes['ld'] = '@(#)PROGRAM:ld PROJECT:ld64-77'
- res = get_compiler_versions()
- self.assertEqual(str(res[1]), '77')
-
- # and dllwrap
- self._exes['dllwrap'] = 'GNU dllwrap 2.17.50 20060824\nFSF'
- res = get_compiler_versions()
- self.assertEqual(str(res[2]), '2.17.50')
- self._exes['dllwrap'] = 'Cheese Wrap'
- res = get_compiler_versions()
- self.assertEqual(res[2], None)
-
- @unittest.skipUnless(hasattr(sys, 'dont_write_bytecode'),
- 'sys.dont_write_bytecode not supported')
- def test_dont_write_bytecode(self):
- # makes sure byte_compile raise a DistutilsError
- # if sys.dont_write_bytecode is True
- old_dont_write_bytecode = sys.dont_write_bytecode
- sys.dont_write_bytecode = True
- try:
- self.assertRaises(DistutilsByteCompileError, byte_compile, [])
- finally:
- sys.dont_write_bytecode = old_dont_write_bytecode
-
- def test_newer(self):
- self.assertRaises(DistutilsFileError, util.newer, 'xxx', 'xxx')
- self.newer_f1 = self.mktempfile()
- time.sleep(1)
- self.newer_f2 = self.mktempfile()
- self.assertTrue(util.newer(self.newer_f2.name, self.newer_f1.name))
-
- def test_find_packages(self):
- # let's create a structure we want to scan:
- #
- # pkg1
- # __init__
- # pkg2
- # __init__
- # pkg3
- # __init__
- # pkg6
- # __init__
- # pkg4 <--- not a pkg
- # pkg8
- # __init__
- # pkg5
- # __init__
- #
- root = self.mkdtemp()
- pkg1 = os.path.join(root, 'pkg1')
- os.mkdir(pkg1)
- self.write_file(os.path.join(pkg1, '__init__.py'))
- os.mkdir(os.path.join(pkg1, 'pkg2'))
- self.write_file(os.path.join(pkg1, 'pkg2', '__init__.py'))
- os.mkdir(os.path.join(pkg1, 'pkg3'))
- self.write_file(os.path.join(pkg1, 'pkg3', '__init__.py'))
- os.mkdir(os.path.join(pkg1, 'pkg3', 'pkg6'))
- self.write_file(os.path.join(pkg1, 'pkg3', 'pkg6', '__init__.py'))
- os.mkdir(os.path.join(pkg1, 'pkg4'))
- os.mkdir(os.path.join(pkg1, 'pkg4', 'pkg8'))
- self.write_file(os.path.join(pkg1, 'pkg4', 'pkg8', '__init__.py'))
- pkg5 = os.path.join(root, 'pkg5')
- os.mkdir(pkg5)
- self.write_file(os.path.join(pkg5, '__init__.py'))
-
- res = find_packages([root], ['pkg1.pkg2'])
- self.assertEqual(set(res), set(['pkg1', 'pkg5', 'pkg1.pkg3', 'pkg1.pkg3.pkg6']))
-
- def test_resolve_name(self):
- self.assertEqual(str(42), resolve_name('__builtin__.str')(42))
- self.assertEqual(
- UtilTestCase.__name__,
- resolve_name("distutils2.tests.test_util.UtilTestCase").__name__)
- self.assertEqual(
- UtilTestCase.test_resolve_name.__name__,
- resolve_name("distutils2.tests.test_util.UtilTestCase.test_resolve_name").__name__)
-
- self.assertRaises(ImportError, resolve_name,
- "distutils2.tests.test_util.UtilTestCaseNot")
- self.assertRaises(ImportError, resolve_name,
- "distutils2.tests.test_util.UtilTestCase.nonexistent_attribute")
-
- def test_import_nested_first_time(self):
- tmp_dir = self.mkdtemp()
- os.makedirs(os.path.join(tmp_dir, 'a', 'b'))
- self.write_file(os.path.join(tmp_dir, 'a', '__init__.py'), '')
- self.write_file(os.path.join(tmp_dir, 'a', 'b', '__init__.py'), '')
- self.write_file(os.path.join(tmp_dir, 'a', 'b', 'c.py'), 'class Foo: pass')
-
- try:
- sys.path.append(tmp_dir)
- resolve_name("a.b.c.Foo")
- # assert nothing raised
- finally:
- sys.path.remove(tmp_dir)
-
- @unittest.skipIf(sys.version < '2.6', 'requires Python 2.6 or higher')
- def test_run_2to3_on_code(self):
- content = "print 'test'"
- converted_content = "print('test')"
- file_handle = self.mktempfile()
- file_name = file_handle.name
- file_handle.write(content)
- file_handle.flush()
- file_handle.seek(0)
- from distutils2.util import run_2to3
- run_2to3([file_name])
- new_content = "".join(file_handle.read())
- file_handle.close()
- self.assertEquals(new_content, converted_content)
-
- @unittest.skipIf(sys.version < '2.6', 'requires Python 2.6 or higher')
- def test_run_2to3_on_doctests(self):
- # to check if text files containing doctests only get converted.
- content = ">>> print 'test'\ntest\n"
- converted_content = ">>> print('test')\ntest\n\n"
- file_handle = self.mktempfile()
- file_name = file_handle.name
- file_handle.write(content)
- file_handle.flush()
- file_handle.seek(0)
- from distutils2.util import run_2to3
- run_2to3([file_name], doctests_only=True)
- new_content = "".join(file_handle.readlines())
- file_handle.close()
- self.assertEquals(new_content, converted_content)
-
- def test_nt_quote_args(self):
-
- for (args, wanted) in ((['with space', 'nospace'],
- ['"with space"', 'nospace']),
- (['nochange', 'nospace'],
- ['nochange', 'nospace'])):
- res = _nt_quote_args(args)
- self.assertEqual(res, wanted)
-
-
- @unittest.skipUnless(os.name in ('nt', 'posix'),
- 'runs only under posix or nt')
- def test_spawn(self):
- tmpdir = self.mkdtemp()
-
- # creating something executable
- # through the shell that returns 1
- if os.name == 'posix':
- exe = os.path.join(tmpdir, 'foo.sh')
- self.write_file(exe, '#!/bin/sh\nexit 1')
- os.chmod(exe, 0777)
- else:
- exe = os.path.join(tmpdir, 'foo.bat')
- self.write_file(exe, 'exit 1')
-
- os.chmod(exe, 0777)
- self.assertRaises(DistutilsExecError, spawn, [exe])
-
- # now something that works
- if os.name == 'posix':
- exe = os.path.join(tmpdir, 'foo.sh')
- self.write_file(exe, '#!/bin/sh\nexit 0')
- os.chmod(exe, 0777)
- else:
- exe = os.path.join(tmpdir, 'foo.bat')
- self.write_file(exe, 'exit 0')
-
- os.chmod(exe, 0777)
- spawn([exe]) # should work without any error
-
- def test_server_registration(self):
- # This test makes sure we know how to:
- # 1. handle several sections in .pypirc
- # 2. handle the old format
-
- # new format
- self.write_file(self.rc, PYPIRC)
- config = read_pypirc()
-
- config = config.items()
- config.sort()
- expected = [('password', 'xxxx'), ('realm', 'pypi'),
- ('repository', 'http://pypi.python.org/pypi'),
- ('server', 'pypi'), ('username', 'me')]
- self.assertEqual(config, expected)
-
- # old format
- self.write_file(self.rc, PYPIRC_OLD)
- config = read_pypirc()
- config = config.items()
- config.sort()
- expected = [('password', 'secret'), ('realm', 'pypi'),
- ('repository', 'http://pypi.python.org/pypi'),
- ('server', 'server-login'), ('username', 'tarek')]
- self.assertEqual(config, expected)
-
- def test_server_empty_registration(self):
- rc = get_pypirc_path()
- self.assertTrue(not os.path.exists(rc))
- generate_pypirc('tarek', 'xxx')
- self.assertTrue(os.path.exists(rc))
- content = open(rc).read()
- self.assertEqual(content, WANTED)
-
-
-def test_suite():
- return unittest.makeSuite(UtilTestCase)
-
-if __name__ == "__main__":
- unittest.main(defaultTest="test_suite")
diff --git a/src/distutils2/tests/test_version.py b/src/distutils2/tests/test_version.py
deleted file mode 100644
index 1e392f2..0000000
--- a/src/distutils2/tests/test_version.py
+++ /dev/null
@@ -1,226 +0,0 @@
-"""Tests for distutils.version."""
-import doctest
-import os
-
-from distutils2.version import NormalizedVersion as V
-from distutils2.version import HugeMajorVersionNumError, IrrationalVersionError
-from distutils2.version import suggest_normalized_version as suggest
-from distutils2.version import VersionPredicate
-from distutils2.tests.support import unittest
-
-class VersionTestCase(unittest.TestCase):
-
- versions = ((V('1.0'), '1.0'),
- (V('1.1'), '1.1'),
- (V('1.2.3'), '1.2.3'),
- (V('1.2'), '1.2'),
- (V('1.2.3a4'), '1.2.3a4'),
- (V('1.2c4'), '1.2c4'),
- (V('1.2.3.4'), '1.2.3.4'),
- (V('1.2.3.4.0b3'), '1.2.3.4b3'),
- (V('1.2.0.0.0'), '1.2'),
- (V('1.0.dev345'), '1.0.dev345'),
- (V('1.0.post456.dev623'), '1.0.post456.dev623'))
-
- def test_repr(self):
-
- self.assertEqual(repr(V('1.0')), "NormalizedVersion('1.0')")
-
- def test_basic_versions(self):
-
- for v, s in self.versions:
- self.assertEqual(str(v), s)
-
- def test_from_parts(self):
-
- for v, s in self.versions:
- parts = v.parts
- v2 = V.from_parts(*v.parts)
- self.assertEqual(v, v2)
- self.assertEqual(str(v), str(v2))
-
- def test_irrational_versions(self):
-
- irrational = ('1', '1.2a', '1.2.3b', '1.02', '1.2a03',
- '1.2a3.04', '1.2.dev.2', '1.2dev', '1.2.dev',
- '1.2.dev2.post2', '1.2.post2.dev3.post4')
-
- for s in irrational:
- self.assertRaises(IrrationalVersionError, V, s)
-
- def test_huge_version(self):
-
- self.assertEquals(str(V('1980.0')), '1980.0')
- self.assertRaises(HugeMajorVersionNumError, V, '1981.0')
- self.assertEquals(str(V('1981.0', error_on_huge_major_num=False)), '1981.0')
-
- def test_comparison(self):
- r"""
- >>> V('1.2.0') == '1.2'
- Traceback (most recent call last):
- ...
- TypeError: cannot compare NormalizedVersion and str
-
- >>> V('1.2') < '1.3'
- Traceback (most recent call last):
- ...
- TypeError: cannot compare NormalizedVersion and str
-
- >>> V('1.2.0') == V('1.2')
- True
- >>> V('1.2.0') == V('1.2.3')
- False
- >>> V('1.2.0') != V('1.2.3')
- True
- >>> V('1.2.0') < V('1.2.3')
- True
- >>> V('1.2.0') < V('1.2.0')
- False
- >>> V('1.2.0') <= V('1.2.0')
- True
- >>> V('1.2.0') <= V('1.2.3')
- True
- >>> V('1.2.3') <= V('1.2.0')
- False
- >>> V('1.2.0') >= V('1.2.0')
- True
- >>> V('1.2.3') >= V('1.2.0')
- True
- >>> V('1.2.0') >= V('1.2.3')
- False
- >>> (V('1.0') > V('1.0b2'))
- True
- >>> (V('1.0') > V('1.0c2') > V('1.0c1') > V('1.0b2') > V('1.0b1')
- ... > V('1.0a2') > V('1.0a1'))
- True
- >>> (V('1.0.0') > V('1.0.0c2') > V('1.0.0c1') > V('1.0.0b2') > V('1.0.0b1')
- ... > V('1.0.0a2') > V('1.0.0a1'))
- True
-
- >>> V('1.0') < V('1.0.post456.dev623')
- True
-
- >>> V('1.0.post456.dev623') < V('1.0.post456') < V('1.0.post1234')
- True
-
- >>> (V('1.0a1')
- ... < V('1.0a2.dev456')
- ... < V('1.0a2')
- ... < V('1.0a2.1.dev456') # e.g. need to do a quick post release on 1.0a2
- ... < V('1.0a2.1')
- ... < V('1.0b1.dev456')
- ... < V('1.0b2')
- ... < V('1.0c1.dev456')
- ... < V('1.0c1')
- ... < V('1.0.dev7')
- ... < V('1.0.dev18')
- ... < V('1.0.dev456')
- ... < V('1.0.dev1234')
- ... < V('1.0')
- ... < V('1.0.post456.dev623') # development version of a post release
- ... < V('1.0.post456'))
- True
- """
- # must be a simpler way to call the docstrings
- doctest.run_docstring_examples(self.test_comparison, globals(),
- name='test_comparison')
-
- def test_suggest_normalized_version(self):
-
- self.assertEqual(suggest('1.0'), '1.0')
- self.assertEqual(suggest('1.0-alpha1'), '1.0a1')
- self.assertEqual(suggest('1.0c2'), '1.0c2')
- self.assertEqual(suggest('walla walla washington'), None)
- self.assertEqual(suggest('2.4c1'), '2.4c1')
- self.assertEqual(suggest('v1.0'), '1.0')
-
- # from setuptools
- self.assertEqual(suggest('0.4a1.r10'), '0.4a1.post10')
- self.assertEqual(suggest('0.7a1dev-r66608'), '0.7a1.dev66608')
- self.assertEqual(suggest('0.6a9.dev-r41475'), '0.6a9.dev41475')
- self.assertEqual(suggest('2.4preview1'), '2.4c1')
- self.assertEqual(suggest('2.4pre1') , '2.4c1')
- self.assertEqual(suggest('2.1-rc2'), '2.1c2')
-
- # from pypi
- self.assertEqual(suggest('0.1dev'), '0.1.dev0')
- self.assertEqual(suggest('0.1.dev'), '0.1.dev0')
-
- # we want to be able to parse Twisted
- # development versions are like post releases in Twisted
- self.assertEqual(suggest('9.0.0+r2363'), '9.0.0.post2363')
-
- # pre-releases are using markers like "pre1"
- self.assertEqual(suggest('9.0.0pre1'), '9.0.0c1')
-
- # we want to be able to parse Tcl-TK
- # they us "p1" "p2" for post releases
- self.assertEqual(suggest('1.4p1'), '1.4.post1')
-
- def test_predicate(self):
- # VersionPredicate knows how to parse stuff like:
- #
- # Project (>=version, ver2)
-
- predicates = ('zope.interface (>3.5.0)',
- 'AnotherProject (3.4)',
- 'OtherProject (<3.0)',
- 'NoVersion',
- 'Hey (>=2.5,<2.7)')
-
- for predicate in predicates:
- v = VersionPredicate(predicate)
-
- self.assertTrue(VersionPredicate('Hey (>=2.5,<2.7)').match('2.6'))
- self.assertTrue(VersionPredicate('Ho').match('2.6'))
- self.assertFalse(VersionPredicate('Hey (>=2.5,!=2.6,<2.7)').match('2.6'))
- self.assertTrue(VersionPredicate('Ho (<3.0)').match('2.6'))
- self.assertTrue(VersionPredicate('Ho (<3.0,!=2.5)').match('2.6.0'))
- self.assertFalse(VersionPredicate('Ho (<3.0,!=2.6)').match('2.6.0'))
- self.assertTrue(VersionPredicate('Ho (2.5)').match('2.5.4'))
- self.assertFalse(VersionPredicate('Ho (!=2.5)').match('2.5.2'))
- self.assertTrue(VersionPredicate('Hey (<=2.5)').match('2.5.9'))
- self.assertFalse(VersionPredicate('Hey (<=2.5)').match('2.6.0'))
- self.assertTrue(VersionPredicate('Hey (>=2.5)').match('2.5.1'))
-
- self.assertRaises(ValueError, VersionPredicate, '')
-
- # XXX need to silent the micro version in this case
- #assert not VersionPredicate('Ho (<3.0,!=2.6)').match('2.6.3')
-
- def test_predicate_name(self):
- # Test that names are parsed the right way
-
- self.assertEqual('Hey', VersionPredicate('Hey (<1.1)').name)
- self.assertEqual('Foo-Bar', VersionPredicate('Foo-Bar (1.1)').name)
- self.assertEqual('Foo Bar', VersionPredicate('Foo Bar (1.1)').name)
-
- def test_is_final(self):
- # VersionPredicate knows is a distribution is a final one or not.
- final_versions = ('1.0', '1.0.post456')
- other_versions = ('1.0.dev1', '1.0a2', '1.0c3')
-
- for version in final_versions:
- self.assertTrue(V(version).is_final)
- for version in other_versions:
- self.assertFalse(V(version).is_final)
-
-class VersionWhiteBoxTestCase(unittest.TestCase):
-
- def test_parse_numdots(self):
- # For code coverage completeness, as pad_zeros_length can't be set or
- # influenced from the public interface
- self.assertEquals(V('1.0')._parse_numdots('1.0', '1.0',
- pad_zeros_length=3),
- [1, 0, 0])
-
-
-def test_suite():
- #README = os.path.join(os.path.dirname(__file__), 'README.txt')
- #suite = [doctest.DocFileSuite(README), unittest.makeSuite(VersionTestCase)]
- suite = [unittest.makeSuite(VersionTestCase),
- unittest.makeSuite(VersionWhiteBoxTestCase)]
- return unittest.TestSuite(suite)
-
-if __name__ == "__main__":
- unittest.main(defaultTest="test_suite")
diff --git a/src/distutils2/tests/xxmodule.c b/src/distutils2/tests/xxmodule.c
deleted file mode 100644
index 6b498dd..0000000
--- a/src/distutils2/tests/xxmodule.c
+++ /dev/null
@@ -1,379 +0,0 @@
-
-/* Use this file as a template to start implementing a module that
- also declares object types. All occurrences of 'Xxo' should be changed
- to something reasonable for your objects. After that, all other
- occurrences of 'xx' should be changed to something reasonable for your
- module. If your module is named foo your sourcefile should be named
- foomodule.c.
-
- You will probably want to delete all references to 'x_attr' and add
- your own types of attributes instead. Maybe you want to name your
- local variables other than 'self'. If your object type is needed in
- other files, you'll have to create a file "foobarobject.h"; see
- intobject.h for an example. */
-
-/* Xxo objects */
-
-#include "Python.h"
-
-static PyObject *ErrorObject;
-
-typedef struct {
- PyObject_HEAD
- PyObject *x_attr; /* Attributes dictionary */
-} XxoObject;
-
-static PyTypeObject Xxo_Type;
-
-#define XxoObject_Check(v) (Py_TYPE(v) == &Xxo_Type)
-
-static XxoObject *
-newXxoObject(PyObject *arg)
-{
- XxoObject *self;
- self = PyObject_New(XxoObject, &Xxo_Type);
- if (self == NULL)
- return NULL;
- self->x_attr = NULL;
- return self;
-}
-
-/* Xxo methods */
-
-static void
-Xxo_dealloc(XxoObject *self)
-{
- Py_XDECREF(self->x_attr);
- PyObject_Del(self);
-}
-
-static PyObject *
-Xxo_demo(XxoObject *self, PyObject *args)
-{
- if (!PyArg_ParseTuple(args, ":demo"))
- return NULL;
- Py_INCREF(Py_None);
- return Py_None;
-}
-
-static PyMethodDef Xxo_methods[] = {
- {"demo", (PyCFunction)Xxo_demo, METH_VARARGS,
- PyDoc_STR("demo() -> None")},
- {NULL, NULL} /* sentinel */
-};
-
-static PyObject *
-Xxo_getattr(XxoObject *self, char *name)
-{
- if (self->x_attr != NULL) {
- PyObject *v = PyDict_GetItemString(self->x_attr, name);
- if (v != NULL) {
- Py_INCREF(v);
- return v;
- }
- }
- return Py_FindMethod(Xxo_methods, (PyObject *)self, name);
-}
-
-static int
-Xxo_setattr(XxoObject *self, char *name, PyObject *v)
-{
- if (self->x_attr == NULL) {
- self->x_attr = PyDict_New();
- if (self->x_attr == NULL)
- return -1;
- }
- if (v == NULL) {
- int rv = PyDict_DelItemString(self->x_attr, name);
- if (rv < 0)
- PyErr_SetString(PyExc_AttributeError,
- "delete non-existing Xxo attribute");
- return rv;
- }
- else
- return PyDict_SetItemString(self->x_attr, name, v);
-}
-
-static PyTypeObject Xxo_Type = {
- /* The ob_type field must be initialized in the module init function
- * to be portable to Windows without using C++. */
- PyVarObject_HEAD_INIT(NULL, 0)
- "xxmodule.Xxo", /*tp_name*/
- sizeof(XxoObject), /*tp_basicsize*/
- 0, /*tp_itemsize*/
- /* methods */
- (destructor)Xxo_dealloc, /*tp_dealloc*/
- 0, /*tp_print*/
- (getattrfunc)Xxo_getattr, /*tp_getattr*/
- (setattrfunc)Xxo_setattr, /*tp_setattr*/
- 0, /*tp_compare*/
- 0, /*tp_repr*/
- 0, /*tp_as_number*/
- 0, /*tp_as_sequence*/
- 0, /*tp_as_mapping*/
- 0, /*tp_hash*/
- 0, /*tp_call*/
- 0, /*tp_str*/
- 0, /*tp_getattro*/
- 0, /*tp_setattro*/
- 0, /*tp_as_buffer*/
- Py_TPFLAGS_DEFAULT, /*tp_flags*/
- 0, /*tp_doc*/
- 0, /*tp_traverse*/
- 0, /*tp_clear*/
- 0, /*tp_richcompare*/
- 0, /*tp_weaklistoffset*/
- 0, /*tp_iter*/
- 0, /*tp_iternext*/
- 0, /*tp_methods*/
- 0, /*tp_members*/
- 0, /*tp_getset*/
- 0, /*tp_base*/
- 0, /*tp_dict*/
- 0, /*tp_descr_get*/
- 0, /*tp_descr_set*/
- 0, /*tp_dictoffset*/
- 0, /*tp_init*/
- 0, /*tp_alloc*/
- 0, /*tp_new*/
- 0, /*tp_free*/
- 0, /*tp_is_gc*/
-};
-/* --------------------------------------------------------------------- */
-
-/* Function of two integers returning integer */
-
-PyDoc_STRVAR(xx_foo_doc,
-"foo(i,j)\n\
-\n\
-Return the sum of i and j.");
-
-static PyObject *
-xx_foo(PyObject *self, PyObject *args)
-{
- long i, j;
- long res;
- if (!PyArg_ParseTuple(args, "ll:foo", &i, &j))
- return NULL;
- res = i+j; /* XXX Do something here */
- return PyInt_FromLong(res);
-}
-
-
-/* Function of no arguments returning new Xxo object */
-
-static PyObject *
-xx_new(PyObject *self, PyObject *args)
-{
- XxoObject *rv;
-
- if (!PyArg_ParseTuple(args, ":new"))
- return NULL;
- rv = newXxoObject(args);
- if (rv == NULL)
- return NULL;
- return (PyObject *)rv;
-}
-
-/* Example with subtle bug from extensions manual ("Thin Ice"). */
-
-static PyObject *
-xx_bug(PyObject *self, PyObject *args)
-{
- PyObject *list, *item;
-
- if (!PyArg_ParseTuple(args, "O:bug", &list))
- return NULL;
-
- item = PyList_GetItem(list, 0);
- /* Py_INCREF(item); */
- PyList_SetItem(list, 1, PyInt_FromLong(0L));
- PyObject_Print(item, stdout, 0);
- printf("\n");
- /* Py_DECREF(item); */
-
- Py_INCREF(Py_None);
- return Py_None;
-}
-
-/* Test bad format character */
-
-static PyObject *
-xx_roj(PyObject *self, PyObject *args)
-{
- PyObject *a;
- long b;
- if (!PyArg_ParseTuple(args, "O#:roj", &a, &b))
- return NULL;
- Py_INCREF(Py_None);
- return Py_None;
-}
-
-
-/* ---------- */
-
-static PyTypeObject Str_Type = {
- /* The ob_type field must be initialized in the module init function
- * to be portable to Windows without using C++. */
- PyVarObject_HEAD_INIT(NULL, 0)
- "xxmodule.Str", /*tp_name*/
- 0, /*tp_basicsize*/
- 0, /*tp_itemsize*/
- /* methods */
- 0, /*tp_dealloc*/
- 0, /*tp_print*/
- 0, /*tp_getattr*/
- 0, /*tp_setattr*/
- 0, /*tp_compare*/
- 0, /*tp_repr*/
- 0, /*tp_as_number*/
- 0, /*tp_as_sequence*/
- 0, /*tp_as_mapping*/
- 0, /*tp_hash*/
- 0, /*tp_call*/
- 0, /*tp_str*/
- 0, /*tp_getattro*/
- 0, /*tp_setattro*/
- 0, /*tp_as_buffer*/
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
- 0, /*tp_doc*/
- 0, /*tp_traverse*/
- 0, /*tp_clear*/
- 0, /*tp_richcompare*/
- 0, /*tp_weaklistoffset*/
- 0, /*tp_iter*/
- 0, /*tp_iternext*/
- 0, /*tp_methods*/
- 0, /*tp_members*/
- 0, /*tp_getset*/
- 0, /* see initxx */ /*tp_base*/
- 0, /*tp_dict*/
- 0, /*tp_descr_get*/
- 0, /*tp_descr_set*/
- 0, /*tp_dictoffset*/
- 0, /*tp_init*/
- 0, /*tp_alloc*/
- 0, /*tp_new*/
- 0, /*tp_free*/
- 0, /*tp_is_gc*/
-};
-
-/* ---------- */
-
-static PyObject *
-null_richcompare(PyObject *self, PyObject *other, int op)
-{
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
-}
-
-static PyTypeObject Null_Type = {
- /* The ob_type field must be initialized in the module init function
- * to be portable to Windows without using C++. */
- PyVarObject_HEAD_INIT(NULL, 0)
- "xxmodule.Null", /*tp_name*/
- 0, /*tp_basicsize*/
- 0, /*tp_itemsize*/
- /* methods */
- 0, /*tp_dealloc*/
- 0, /*tp_print*/
- 0, /*tp_getattr*/
- 0, /*tp_setattr*/
- 0, /*tp_compare*/
- 0, /*tp_repr*/
- 0, /*tp_as_number*/
- 0, /*tp_as_sequence*/
- 0, /*tp_as_mapping*/
- 0, /*tp_hash*/
- 0, /*tp_call*/
- 0, /*tp_str*/
- 0, /*tp_getattro*/
- 0, /*tp_setattro*/
- 0, /*tp_as_buffer*/
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
- 0, /*tp_doc*/
- 0, /*tp_traverse*/
- 0, /*tp_clear*/
- null_richcompare, /*tp_richcompare*/
- 0, /*tp_weaklistoffset*/
- 0, /*tp_iter*/
- 0, /*tp_iternext*/
- 0, /*tp_methods*/
- 0, /*tp_members*/
- 0, /*tp_getset*/
- 0, /* see initxx */ /*tp_base*/
- 0, /*tp_dict*/
- 0, /*tp_descr_get*/
- 0, /*tp_descr_set*/
- 0, /*tp_dictoffset*/
- 0, /*tp_init*/
- 0, /*tp_alloc*/
- 0, /* see initxx */ /*tp_new*/
- 0, /*tp_free*/
- 0, /*tp_is_gc*/
-};
-
-
-/* ---------- */
-
-
-/* List of functions defined in the module */
-
-static PyMethodDef xx_methods[] = {
- {"roj", xx_roj, METH_VARARGS,
- PyDoc_STR("roj(a,b) -> None")},
- {"foo", xx_foo, METH_VARARGS,
- xx_foo_doc},
- {"new", xx_new, METH_VARARGS,
- PyDoc_STR("new() -> new Xx object")},
- {"bug", xx_bug, METH_VARARGS,
- PyDoc_STR("bug(o) -> None")},
- {NULL, NULL} /* sentinel */
-};
-
-PyDoc_STRVAR(module_doc,
-"This is a template module just for instruction.");
-
-/* Initialization function for the module (*must* be called initxx) */
-
-PyMODINIT_FUNC
-initxx(void)
-{
- PyObject *m;
-
- /* Due to cross platform compiler issues the slots must be filled
- * here. It's required for portability to Windows without requiring
- * C++. */
- Null_Type.tp_base = &PyBaseObject_Type;
- Null_Type.tp_new = PyType_GenericNew;
- Str_Type.tp_base = &PyUnicode_Type;
-
- /* Finalize the type object including setting type of the new type
- * object; doing it here is required for portability, too. */
- if (PyType_Ready(&Xxo_Type) < 0)
- return;
-
- /* Create the module and add the functions */
- m = Py_InitModule3("xx", xx_methods, module_doc);
- if (m == NULL)
- return;
-
- /* Add some symbolic constants to the module */
- if (ErrorObject == NULL) {
- ErrorObject = PyErr_NewException("xx.error", NULL, NULL);
- if (ErrorObject == NULL)
- return;
- }
- Py_INCREF(ErrorObject);
- PyModule_AddObject(m, "error", ErrorObject);
-
- /* Add Str */
- if (PyType_Ready(&Str_Type) < 0)
- return;
- PyModule_AddObject(m, "Str", (PyObject *)&Str_Type);
-
- /* Add Null */
- if (PyType_Ready(&Null_Type) < 0)
- return;
- PyModule_AddObject(m, "Null", (PyObject *)&Null_Type);
-}
diff --git a/src/distutils2/util.py b/src/distutils2/util.py
deleted file mode 100644
index 12b1022..0000000
--- a/src/distutils2/util.py
+++ /dev/null
@@ -1,1129 +0,0 @@
-"""distutils.util
-
-Miscellaneous utility functions.
-"""
-
-__revision__ = "$Id: util.py 77761 2010-01-26 22:46:15Z tarek.ziade $"
-
-import os
-import posixpath
-import re
-import string
-import sys
-import shutil
-import tarfile
-import zipfile
-from copy import copy
-from fnmatch import fnmatchcase
-from ConfigParser import RawConfigParser
-
-from distutils2.errors import (DistutilsPlatformError, DistutilsFileError,
- DistutilsByteCompileError, DistutilsExecError)
-from distutils2 import log
-from distutils2._backport import sysconfig as _sysconfig
-
-_PLATFORM = None
-
-
-def newer(source, target):
- """Tells if the target is newer than the source.
-
- Return true if 'source' exists and is more recently modified than
- 'target', or if 'source' exists and 'target' doesn't.
-
- Return false if both exist and 'target' is the same age or younger
- than 'source'. Raise DistutilsFileError if 'source' does not exist.
-
- Note that this test is not very accurate: files created in the same second
- will have the same "age".
- """
- if not os.path.exists(source):
- raise DistutilsFileError("file '%s' does not exist" %
- os.path.abspath(source))
- if not os.path.exists(target):
- return True
-
- return os.stat(source).st_mtime > os.stat(target).st_mtime
-
-
-def get_platform():
- """Return a string that identifies the current platform.
-
- By default, will return the value returned by sysconfig.get_platform(),
- but it can be changed by calling set_platform().
- """
- global _PLATFORM
- if _PLATFORM is None:
- _PLATFORM = _sysconfig.get_platform()
- return _PLATFORM
-
-
-def set_platform(identifier):
- """Sets the platform string identifier returned by get_platform().
-
- Note that this change doesn't impact the value returned by
- sysconfig.get_platform() and is local to Distutils
- """
- global _PLATFORM
- _PLATFORM = identifier
-
-
-def convert_path(pathname):
- """Return 'pathname' as a name that will work on the native filesystem.
-
- i.e. split it on '/' and put it back together again using the current
- directory separator. Needed because filenames in the setup script are
- always supplied in Unix style, and have to be converted to the local
- convention before we can actually use them in the filesystem. Raises
- ValueError on non-Unix-ish systems if 'pathname' either starts or
- ends with a slash.
- """
- if os.sep == '/':
- return pathname
- if not pathname:
- return pathname
- if pathname[0] == '/':
- raise ValueError("path '%s' cannot be absolute" % pathname)
- if pathname[-1] == '/':
- raise ValueError("path '%s' cannot end with '/'" % pathname)
-
- paths = pathname.split('/')
- while os.curdir in paths:
- paths.remove(os.curdir)
- if not paths:
- return os.curdir
- return os.path.join(*paths)
-
-
-def change_root(new_root, pathname):
- """Return 'pathname' with 'new_root' prepended.
-
- If 'pathname' is relative, this is equivalent to
- "os.path.join(new_root,pathname)".
- Otherwise, it requires making 'pathname' relative and then joining the
- two, which is tricky on DOS/Windows and Mac OS.
- """
- if os.name == 'posix':
- if not os.path.isabs(pathname):
- return os.path.join(new_root, pathname)
- else:
- return os.path.join(new_root, pathname[1:])
-
- elif os.name == 'nt':
- (drive, path) = os.path.splitdrive(pathname)
- if path[0] == '\\':
- path = path[1:]
- return os.path.join(new_root, path)
-
- elif os.name == 'os2':
- (drive, path) = os.path.splitdrive(pathname)
- if path[0] == os.sep:
- path = path[1:]
- return os.path.join(new_root, path)
-
- else:
- raise DistutilsPlatformError("nothing known about "
- "platform '%s'" % os.name)
-
-_environ_checked = 0
-
-
-def check_environ():
- """Ensure that 'os.environ' has all the environment variables needed.
-
- We guarantee that users can use in config files, command-line options,
- etc. Currently this includes:
- HOME - user's home directory (Unix only)
- PLAT - description of the current platform, including hardware
- and OS (see 'get_platform()')
- """
- global _environ_checked
- if _environ_checked:
- return
-
- if os.name == 'posix' and 'HOME' not in os.environ:
- import pwd
- os.environ['HOME'] = pwd.getpwuid(os.getuid())[5]
-
- if 'PLAT' not in os.environ:
- os.environ['PLAT'] = _sysconfig.get_platform()
-
- _environ_checked = 1
-
-
-def subst_vars(s, local_vars):
- """Perform shell/Perl-style variable substitution on 'string'.
-
- Every occurrence of '$' followed by a name is considered a variable, and
- variable is substituted by the value found in the 'local_vars'
- dictionary, or in 'os.environ' if it's not in 'local_vars'.
- 'os.environ' is first checked/augmented to guarantee that it contains
- certain values: see 'check_environ()'. Raise ValueError for any
- variables not found in either 'local_vars' or 'os.environ'.
- """
- check_environ()
-
- def _subst(match, local_vars=local_vars):
- var_name = match.group(1)
- if var_name in local_vars:
- return str(local_vars[var_name])
- else:
- return os.environ[var_name]
-
- try:
- return re.sub(r'\$([a-zA-Z_][a-zA-Z_0-9]*)', _subst, s)
- except KeyError, var:
- raise ValueError("invalid variable '$%s'" % var)
-
-
-def grok_environment_error(exc, prefix="error: "):
- """Generate a useful error message from an EnvironmentError.
-
- This will generate an IOError or an OSError exception object.
- Handles Python 1.5.1 and 1.5.2 styles, and
- does what it can to deal with exception objects that don't have a
- filename (which happens when the error is due to a two-file operation,
- such as 'rename()' or 'link()'. Returns the error message as a string
- prefixed with 'prefix'.
- """
- # check for Python 1.5.2-style {IO,OS}Error exception objects
- if hasattr(exc, 'filename') and hasattr(exc, 'strerror'):
- if exc.filename:
- error = prefix + "%s: %s" % (exc.filename, exc.strerror)
- else:
- # two-argument functions in posix module don't
- # include the filename in the exception object!
- error = prefix + "%s" % exc.strerror
- else:
- error = prefix + str(exc[-1])
-
- return error
-
-# Needed by 'split_quoted()'
-_wordchars_re = _squote_re = _dquote_re = None
-
-
-def _init_regex():
- global _wordchars_re, _squote_re, _dquote_re
- _wordchars_re = re.compile(r'[^\\\'\"%s ]*' % string.whitespace)
- _squote_re = re.compile(r"'(?:[^'\\]|\\.)*'")
- _dquote_re = re.compile(r'"(?:[^"\\]|\\.)*"')
-
-
-def split_quoted(s):
- """Split a string up according to Unix shell-like rules for quotes and
- backslashes.
-
- In short: words are delimited by spaces, as long as those
- spaces are not escaped by a backslash, or inside a quoted string.
- Single and double quotes are equivalent, and the quote characters can
- be backslash-escaped. The backslash is stripped from any two-character
- escape sequence, leaving only the escaped character. The quote
- characters are stripped from any quoted string. Returns a list of
- words.
- """
- # This is a nice algorithm for splitting up a single string, since it
- # doesn't require character-by-character examination. It was a little
- # bit of a brain-bender to get it working right, though...
- if _wordchars_re is None:
- _init_regex()
-
- s = s.strip()
- words = []
- pos = 0
-
- while s:
- m = _wordchars_re.match(s, pos)
- end = m.end()
- if end == len(s):
- words.append(s[:end])
- break
-
- if s[end] in string.whitespace: # unescaped, unquoted whitespace: now
- words.append(s[:end]) # we definitely have a word delimiter
- s = s[end:].lstrip()
- pos = 0
-
- elif s[end] == '\\': # preserve whatever is being escaped;
- # will become part of the current word
- s = s[:end] + s[end + 1:]
- pos = end + 1
-
- else:
- if s[end] == "'": # slurp singly-quoted string
- m = _squote_re.match(s, end)
- elif s[end] == '"': # slurp doubly-quoted string
- m = _dquote_re.match(s, end)
- else:
- raise RuntimeError("this can't happen "
- "(bad char '%c')" % s[end])
-
- if m is None:
- raise ValueError("bad string (mismatched %s quotes?)" % s[end])
-
- (beg, end) = m.span()
- s = s[:beg] + s[beg + 1:end - 1] + s[end:]
- pos = m.end() - 2
-
- if pos >= len(s):
- words.append(s)
- break
-
- return words
-
-
-def execute(func, args, msg=None, verbose=0, dry_run=0):
- """Perform some action that affects the outside world.
-
- eg. by writing to the filesystem). Such actions are special because
- they are disabled by the 'dry_run' flag. This method takes care of all
- that bureaucracy for you; all you have to do is supply the
- function to call and an argument tuple for it (to embody the
- "external action" being performed), and an optional message to
- print.
- """
- if msg is None:
- msg = "%s%r" % (func.__name__, args)
- if msg[-2:] == ',)': # correct for singleton tuple
- msg = msg[0:-2] + ')'
-
- log.info(msg)
- if not dry_run:
- func(*args)
-
-
-def strtobool(val):
- """Convert a string representation of truth to true (1) or false (0).
-
- True values are 'y', 'yes', 't', 'true', 'on', and '1'; false values
- are 'n', 'no', 'f', 'false', 'off', and '0'. Raises ValueError if
- 'val' is anything else.
- """
- val = val.lower()
- if val in ('y', 'yes', 't', 'true', 'on', '1'):
- return 1
- elif val in ('n', 'no', 'f', 'false', 'off', '0'):
- return 0
- else:
- raise ValueError("invalid truth value %r" % (val,))
-
-
-def byte_compile(py_files, optimize=0, force=0, prefix=None, base_dir=None,
- verbose=1, dry_run=0, direct=None):
- """Byte-compile a collection of Python source files to either .pyc
- or .pyo files in the same directory.
-
- 'py_files' is a list of files to compile; any files that don't end in
- ".py" are silently skipped. 'optimize' must be one of the following:
- 0 - don't optimize (generate .pyc)
- 1 - normal optimization (like "python -O")
- 2 - extra optimization (like "python -OO")
- If 'force' is true, all files are recompiled regardless of
- timestamps.
-
- The source filename encoded in each bytecode file defaults to the
- filenames listed in 'py_files'; you can modify these with 'prefix' and
- 'basedir'. 'prefix' is a string that will be stripped off of each
- source filename, and 'base_dir' is a directory name that will be
- prepended (after 'prefix' is stripped). You can supply either or both
- (or neither) of 'prefix' and 'base_dir', as you wish.
-
- If 'dry_run' is true, doesn't actually do anything that would
- affect the filesystem.
-
- Byte-compilation is either done directly in this interpreter process
- with the standard py_compile module, or indirectly by writing a
- temporary script and executing it. Normally, you should let
- 'byte_compile()' figure out to use direct compilation or not (see
- the source for details). The 'direct' flag is used by the script
- generated in indirect mode; unless you know what you're doing, leave
- it set to None.
- """
- # nothing is done if sys.dont_write_bytecode is True
- if hasattr(sys, 'dont_write_bytecode') and sys.dont_write_bytecode:
- raise DistutilsByteCompileError('byte-compiling is disabled.')
-
- # First, if the caller didn't force us into direct or indirect mode,
- # figure out which mode we should be in. We take a conservative
- # approach: choose direct mode *only* if the current interpreter is
- # in debug mode and optimize is 0. If we're not in debug mode (-O
- # or -OO), we don't know which level of optimization this
- # interpreter is running with, so we can't do direct
- # byte-compilation and be certain that it's the right thing. Thus,
- # always compile indirectly if the current interpreter is in either
- # optimize mode, or if either optimization level was requested by
- # the caller.
- if direct is None:
- direct = (__debug__ and optimize == 0)
-
- # "Indirect" byte-compilation: write a temporary script and then
- # run it with the appropriate flags.
- if not direct:
- from tempfile import mkstemp
- script_fd, script_name = mkstemp(".py")
- log.info("writing byte-compilation script '%s'", script_name)
- if not dry_run:
- if script_fd is not None:
- script = os.fdopen(script_fd, "w")
- else:
- script = open(script_name, "w")
-
- try:
- script.write("""\
-from distutils2.util import byte_compile
-files = [
-""")
-
- # XXX would be nice to write absolute filenames, just for
- # safety's sake (script should be more robust in the face of
- # chdir'ing before running it). But this requires abspath'ing
- # 'prefix' as well, and that breaks the hack in build_lib's
- # 'byte_compile()' method that carefully tacks on a trailing
- # slash (os.sep really) to make sure the prefix here is "just
- # right". This whole prefix business is rather delicate -- the
- # problem is that it's really a directory, but I'm treating it
- # as a dumb string, so trailing slashes and so forth matter.
-
- #py_files = map(os.path.abspath, py_files)
- #if prefix:
- # prefix = os.path.abspath(prefix)
-
- script.write(",\n".join(map(repr, py_files)) + "]\n")
- script.write("""
-byte_compile(files, optimize=%r, force=%r,
- prefix=%r, base_dir=%r,
- verbose=%r, dry_run=0,
- direct=1)
-""" % (optimize, force, prefix, base_dir, verbose))
-
- finally:
- script.close()
-
- cmd = [sys.executable, script_name]
- if optimize == 1:
- cmd.insert(1, "-O")
- elif optimize == 2:
- cmd.insert(1, "-OO")
-
- env = copy(os.environ)
- env['PYTHONPATH'] = ':'.join(sys.path)
- try:
- spawn(cmd, dry_run=dry_run, env=env)
- finally:
- execute(os.remove, (script_name,), "removing %s" % script_name,
- dry_run=dry_run)
-
- # "Direct" byte-compilation: use the py_compile module to compile
- # right here, right now. Note that the script generated in indirect
- # mode simply calls 'byte_compile()' in direct mode, a weird sort of
- # cross-process recursion. Hey, it works!
- else:
- from py_compile import compile
-
- for file in py_files:
- if file[-3:] != ".py":
- # This lets us be lazy and not filter filenames in
- # the "install_lib" command.
- continue
-
- # Terminology from the py_compile module:
- # cfile - byte-compiled file
- # dfile - purported source filename (same as 'file' by default)
- cfile = file + (__debug__ and "c" or "o")
- dfile = file
- if prefix:
- if file[:len(prefix)] != prefix:
- raise ValueError("invalid prefix: filename %r doesn't "
- "start with %r" % (file, prefix))
- dfile = dfile[len(prefix):]
- if base_dir:
- dfile = os.path.join(base_dir, dfile)
-
- cfile_base = os.path.basename(cfile)
- if direct:
- if force or newer(file, cfile):
- log.info("byte-compiling %s to %s", file, cfile_base)
- if not dry_run:
- compile(file, cfile, dfile)
- else:
- log.debug("skipping byte-compilation of %s to %s",
- file, cfile_base)
-
-
-def rfc822_escape(header):
- """Return a version of the string escaped for inclusion in an
- RFC-822 header, by ensuring there are 8 spaces space after each newline.
- """
- lines = header.split('\n')
- sep = '\n' + 8 * ' '
- return sep.join(lines)
-
-_RE_VERSION = re.compile('(\d+\.\d+(\.\d+)*)')
-_MAC_OS_X_LD_VERSION = re.compile('^@\(#\)PROGRAM:ld '
- 'PROJECT:ld64-((\d+)(\.\d+)*)')
-
-
-def _find_ld_version():
- """Finds the ld version. The version scheme differs under Mac OSX."""
- if sys.platform == 'darwin':
- return _find_exe_version('ld -v', _MAC_OS_X_LD_VERSION)
- else:
- return _find_exe_version('ld -v')
-
-
-def _find_exe_version(cmd, pattern=_RE_VERSION):
- """Find the version of an executable by running `cmd` in the shell.
-
- `pattern` is a compiled regular expression. If not provided, default
- to _RE_VERSION. If the command is not found, or the output does not
- match the mattern, returns None.
- """
- from subprocess import Popen, PIPE
- executable = cmd.split()[0]
- if find_executable(executable) is None:
- return None
- pipe = Popen(cmd, shell=True, stdout=PIPE, stderr=PIPE)
- try:
- stdout, stderr = pipe.stdout.read(), pipe.stderr.read()
- finally:
- pipe.stdout.close()
- pipe.stderr.close()
- # some commands like ld under MacOS X, will give the
- # output in the stderr, rather than stdout.
- if stdout != '':
- out_string = stdout
- else:
- out_string = stderr
-
- result = pattern.search(out_string)
- if result is None:
- return None
- return result.group(1)
-
-
-def get_compiler_versions():
- """Returns a tuple providing the versions of gcc, ld and dllwrap
-
- For each command, if a command is not found, None is returned.
- Otherwise a string with the version is returned.
- """
- gcc = _find_exe_version('gcc -dumpversion')
- ld = _find_ld_version()
- dllwrap = _find_exe_version('dllwrap --version')
- return gcc, ld, dllwrap
-
-
-def newer_group(sources, target, missing='error'):
- """Return true if 'target' is out-of-date with respect to any file
- listed in 'sources'.
-
- In other words, if 'target' exists and is newer
- than every file in 'sources', return false; otherwise return true.
- 'missing' controls what we do when a source file is missing; the
- default ("error") is to blow up with an OSError from inside 'stat()';
- if it is "ignore", we silently drop any missing source files; if it is
- "newer", any missing source files make us assume that 'target' is
- out-of-date (this is handy in "dry-run" mode: it'll make you pretend to
- carry out commands that wouldn't work because inputs are missing, but
- that doesn't matter because you're not actually going to run the
- commands).
- """
- # If the target doesn't even exist, then it's definitely out-of-date.
- if not os.path.exists(target):
- return True
-
- # Otherwise we have to find out the hard way: if *any* source file
- # is more recent than 'target', then 'target' is out-of-date and
- # we can immediately return true. If we fall through to the end
- # of the loop, then 'target' is up-to-date and we return false.
- target_mtime = os.stat(target).st_mtime
-
- for source in sources:
- if not os.path.exists(source):
- if missing == 'error': # blow up when we stat() the file
- pass
- elif missing == 'ignore': # missing source dropped from
- continue # target's dependency list
- elif missing == 'newer': # missing source means target is
- return True # out-of-date
-
- if os.stat(source).st_mtime > target_mtime:
- return True
-
- return False
-
-
-def write_file(filename, contents):
- """Create a file with the specified name and write 'contents' (a
- sequence of strings without line terminators) to it.
- """
- try:
- f = open(filename, "w")
- for line in contents:
- f.write(line + "\n")
- finally:
- f.close()
-
-
-def _is_package(path):
- """Returns True if path is a package (a dir with an __init__ file."""
- if not os.path.isdir(path):
- return False
- return os.path.isfile(os.path.join(path, '__init__.py'))
-
-
-def _under(path, root):
- path = path.split(os.sep)
- root = root.split(os.sep)
- if len(root) > len(path):
- return False
- for pos, part in enumerate(root):
- if path[pos] != part:
- return False
- return True
-
-
-def _package_name(root_path, path):
- """Returns a dotted package name, given a subpath."""
- if not _under(path, root_path):
- raise ValueError('"%s" is not a subpath of "%s"' % (path, root_path))
- return path[len(root_path) + 1:].replace(os.sep, '.')
-
-
-def find_packages(paths=(os.curdir,), exclude=()):
- """Return a list all Python packages found recursively within
- directories 'paths'
-
- 'paths' should be supplied as a sequence of "cross-platform"
- (i.e. URL-style) path; it will be converted to the appropriate local
- path syntax.
-
- 'exclude' is a sequence of package names to exclude; '*' can be used as
- a wildcard in the names, such that 'foo.*' will exclude all subpackages
- of 'foo' (but not 'foo' itself).
- """
- packages = []
- discarded = []
-
- def _discarded(path):
- for discard in discarded:
- if _under(path, discard):
- return True
- return False
-
- for path in paths:
- path = convert_path(path)
- for root, dirs, files in os.walk(path):
- for dir_ in dirs:
- fullpath = os.path.join(root, dir_)
- if _discarded(fullpath):
- continue
- # we work only with Python packages
- if not _is_package(fullpath):
- discarded.append(fullpath)
- continue
- # see if it's excluded
- excluded = False
- package_name = _package_name(path, fullpath)
- for pattern in exclude:
- if fnmatchcase(package_name, pattern):
- excluded = True
- break
- if excluded:
- continue
-
- # adding it to the list
- packages.append(package_name)
- return packages
-
-def resolve_name(name):
- """Resolve a name like ``module.object`` to an object and return it.
-
- Raise ImportError if the module or name is not found.
- """
- parts = name.split('.')
- cursor = len(parts)
- module_name, rest = parts[:cursor], parts[cursor:]
-
- while cursor > 0:
- try:
- ret = __import__('.'.join(module_name))
- break
- except ImportError:
- if cursor == 0:
- raise
- cursor -= 1
- module_name = parts[:cursor]
- rest = parts[cursor:]
- ret = ''
-
- for part in parts[1:]:
- try:
- ret = getattr(ret, part)
- except AttributeError:
- raise ImportError
-
- return ret
-
-def splitext(path):
- """Like os.path.splitext, but take off .tar too"""
- base, ext = posixpath.splitext(path)
- if base.lower().endswith('.tar'):
- ext = base[-4:] + ext
- base = base[:-4]
- return base, ext
-
-
-def unzip_file(filename, location, flatten=True):
- """Unzip the file (zip file located at filename) to the destination
- location"""
- if not os.path.exists(location):
- os.makedirs(location)
- zipfp = open(filename, 'rb')
- try:
- zip = zipfile.ZipFile(zipfp)
- leading = has_leading_dir(zip.namelist()) and flatten
- for name in zip.namelist():
- data = zip.read(name)
- fn = name
- if leading:
- fn = split_leading_dir(name)[1]
- fn = os.path.join(location, fn)
- dir = os.path.dirname(fn)
- if not os.path.exists(dir):
- os.makedirs(dir)
- if fn.endswith('/') or fn.endswith('\\'):
- # A directory
- if not os.path.exists(fn):
- os.makedirs(fn)
- else:
- fp = open(fn, 'wb')
- try:
- fp.write(data)
- finally:
- fp.close()
- finally:
- zipfp.close()
-
-
-def untar_file(filename, location):
- """Untar the file (tar file located at filename) to the destination
- location
- """
- if not os.path.exists(location):
- os.makedirs(location)
- if filename.lower().endswith('.gz') or filename.lower().endswith('.tgz'):
- mode = 'r:gz'
- elif (filename.lower().endswith('.bz2')
- or filename.lower().endswith('.tbz')):
- mode = 'r:bz2'
- elif filename.lower().endswith('.tar'):
- mode = 'r'
- else:
- mode = 'r:*'
- tar = tarfile.open(filename, mode)
- try:
- leading = has_leading_dir([member.name for member in tar.getmembers()])
- for member in tar.getmembers():
- fn = member.name
- if leading:
- fn = split_leading_dir(fn)[1]
- path = os.path.join(location, fn)
- if member.isdir():
- if not os.path.exists(path):
- os.makedirs(path)
- else:
- try:
- fp = tar.extractfile(member)
- except (KeyError, AttributeError), e:
- # Some corrupt tar files seem to produce this
- # (specifically bad symlinks)
- continue
- if not os.path.exists(os.path.dirname(path)):
- os.makedirs(os.path.dirname(path))
- destfp = open(path, 'wb')
- try:
- shutil.copyfileobj(fp, destfp)
- finally:
- destfp.close()
- fp.close()
- finally:
- tar.close()
-
-
-def has_leading_dir(paths):
- """Returns true if all the paths have the same leading path name
- (i.e., everything is in one subdirectory in an archive)"""
- common_prefix = None
- for path in paths:
- prefix, rest = split_leading_dir(path)
- if not prefix:
- return False
- elif common_prefix is None:
- common_prefix = prefix
- elif prefix != common_prefix:
- return False
- return True
-
-
-def split_leading_dir(path):
- path = str(path)
- path = path.lstrip('/').lstrip('\\')
- if '/' in path and (('\\' in path and path.find('/') < path.find('\\'))
- or '\\' not in path):
- return path.split('/', 1)
- elif '\\' in path:
- return path.split('\\', 1)
- else:
- return path, ''
-
-
-def spawn(cmd, search_path=1, verbose=0, dry_run=0, env=None):
- """Run another program specified as a command list 'cmd' in a new process.
-
- 'cmd' is just the argument list for the new process, ie.
- cmd[0] is the program to run and cmd[1:] are the rest of its arguments.
- There is no way to run a program with a name different from that of its
- executable.
-
- If 'search_path' is true (the default), the system's executable
- search path will be used to find the program; otherwise, cmd[0]
- must be the exact path to the executable. If 'dry_run' is true,
- the command will not actually be run.
-
- If 'env' is given, it's a environment dictionary used for the execution
- environment.
-
- Raise DistutilsExecError if running the program fails in any way; just
- return on success.
- """
- if os.name == 'posix':
- _spawn_posix(cmd, search_path, dry_run=dry_run, env=env)
- elif os.name == 'nt':
- _spawn_nt(cmd, search_path, dry_run=dry_run, env=env)
- elif os.name == 'os2':
- _spawn_os2(cmd, search_path, dry_run=dry_run, env=env)
- else:
- raise DistutilsPlatformError(
- "don't know how to spawn programs on platform '%s'" % os.name)
-
-
-def _nt_quote_args(args):
- """Quote command-line arguments for DOS/Windows conventions.
-
- Just wraps every argument which contains blanks in double quotes, and
- returns a new argument list.
- """
- # XXX this doesn't seem very robust to me -- but if the Windows guys
- # say it'll work, I guess I'll have to accept it. (What if an arg
- # contains quotes? What other magic characters, other than spaces,
- # have to be escaped? Is there an escaping mechanism other than
- # quoting?)
- for i, arg in enumerate(args):
- if ' ' in arg:
- args[i] = '"%s"' % arg
- return args
-
-
-def _spawn_nt(cmd, search_path=1, verbose=0, dry_run=0, env=None):
- executable = cmd[0]
- cmd = _nt_quote_args(cmd)
- if search_path:
- # either we find one or it stays the same
- executable = find_executable(executable) or executable
- log.info(' '.join([executable] + cmd[1:]))
- if not dry_run:
- # spawn for NT requires a full path to the .exe
- try:
- if env is None:
- rc = os.spawnv(os.P_WAIT, executable, cmd)
- else:
- rc = os.spawnve(os.P_WAIT, executable, cmd, env)
-
- except OSError, exc:
- # this seems to happen when the command isn't found
- raise DistutilsExecError(
- "command '%s' failed: %s" % (cmd[0], exc[-1]))
- if rc != 0:
- # and this reflects the command running but failing
- raise DistutilsExecError(
- "command '%s' failed with exit status %d" % (cmd[0], rc))
-
-
-def _spawn_os2(cmd, search_path=1, verbose=0, dry_run=0, env=None):
- executable = cmd[0]
- if search_path:
- # either we find one or it stays the same
- executable = find_executable(executable) or executable
- log.info(' '.join([executable] + cmd[1:]))
- if not dry_run:
- # spawnv for OS/2 EMX requires a full path to the .exe
- try:
- if env is None:
- rc = os.spawnv(os.P_WAIT, executable, cmd)
- else:
- rc = os.spawnve(os.P_WAIT, executable, cmd, env)
-
- except OSError, exc:
- # this seems to happen when the command isn't found
- raise DistutilsExecError(
- "command '%s' failed: %s" % (cmd[0], exc[-1]))
- if rc != 0:
- # and this reflects the command running but failing
- log.debug("command '%s' failed with exit status %d" % (cmd[0], rc))
- raise DistutilsExecError(
- "command '%s' failed with exit status %d" % (cmd[0], rc))
-
-
-def _spawn_posix(cmd, search_path=1, verbose=0, dry_run=0, env=None):
- log.info(' '.join(cmd))
- if dry_run:
- return
-
- if env is None:
- exec_fn = search_path and os.execvp or os.execv
- else:
- exec_fn = search_path and os.execvpe or os.execve
-
- pid = os.fork()
-
- if pid == 0: # in the child
- try:
- if env is None:
- exec_fn(cmd[0], cmd)
- else:
- exec_fn(cmd[0], cmd, env)
- except OSError, e:
- sys.stderr.write("unable to execute %s: %s\n" %
- (cmd[0], e.strerror))
- os._exit(1)
-
- sys.stderr.write("unable to execute %s for unknown reasons" % cmd[0])
- os._exit(1)
- else: # in the parent
- # Loop until the child either exits or is terminated by a signal
- # (ie. keep waiting if it's merely stopped)
- while 1:
- try:
- pid, status = os.waitpid(pid, 0)
- except OSError, exc:
- import errno
- if exc.errno == errno.EINTR:
- continue
- raise DistutilsExecError(
- "command '%s' failed: %s" % (cmd[0], exc[-1]))
- if os.WIFSIGNALED(status):
- raise DistutilsExecError(
- "command '%s' terminated by signal %d" % \
- (cmd[0], os.WTERMSIG(status)))
-
- elif os.WIFEXITED(status):
- exit_status = os.WEXITSTATUS(status)
- if exit_status == 0:
- return # hey, it succeeded!
- else:
- raise DistutilsExecError(
- "command '%s' failed with exit status %d" % \
- (cmd[0], exit_status))
-
- elif os.WIFSTOPPED(status):
- continue
-
- else:
- raise DistutilsExecError(
- "unknown error executing '%s': termination status %d" % \
- (cmd[0], status))
-
-
-def find_executable(executable, path=None):
- """Tries to find 'executable' in the directories listed in 'path'.
-
- A string listing directories separated by 'os.pathsep'; defaults to
- os.environ['PATH']. Returns the complete filename or None if not found.
- """
- if path is None:
- path = os.environ['PATH']
- paths = path.split(os.pathsep)
- base, ext = os.path.splitext(executable)
-
- if (sys.platform == 'win32' or os.name == 'os2') and (ext != '.exe'):
- executable = executable + '.exe'
-
- if not os.path.isfile(executable):
- for p in paths:
- f = os.path.join(p, executable)
- if os.path.isfile(f):
- # the file exists, we have a shot at spawn working
- return f
- return None
- else:
- return executable
-
-
-DEFAULT_REPOSITORY = 'http://pypi.python.org/pypi'
-DEFAULT_REALM = 'pypi'
-DEFAULT_PYPIRC = """\
-[distutils]
-index-servers =
- pypi
-
-[pypi]
-username:%s
-password:%s
-"""
-
-def get_pypirc_path():
- """Returns rc file path."""
- return os.path.join(os.path.expanduser('~'), '.pypirc')
-
-
-def generate_pypirc(username, password):
- """Creates a default .pypirc file."""
- rc = get_pypirc_path()
- f = open(rc, 'w')
- try:
- f.write(DEFAULT_PYPIRC % (username, password))
- finally:
- f.close()
- try:
- os.chmod(rc, 0600)
- except OSError:
- # should do something better here
- pass
-
-
-def read_pypirc(repository=DEFAULT_REPOSITORY, realm=DEFAULT_REALM):
- """Reads the .pypirc file."""
- rc = get_pypirc_path()
- if os.path.exists(rc):
- config = RawConfigParser()
- config.read(rc)
- sections = config.sections()
- if 'distutils' in sections:
- # let's get the list of servers
- index_servers = config.get('distutils', 'index-servers')
- _servers = [server.strip() for server in
- index_servers.split('\n')
- if server.strip() != '']
- if _servers == []:
- # nothing set, let's try to get the default pypi
- if 'pypi' in sections:
- _servers = ['pypi']
- else:
- # the file is not properly defined, returning
- # an empty dict
- return {}
- for server in _servers:
- current = {'server': server}
- current['username'] = config.get(server, 'username')
-
- # optional params
- for key, default in (('repository',
- DEFAULT_REPOSITORY),
- ('realm', DEFAULT_REALM),
- ('password', None)):
- if config.has_option(server, key):
- current[key] = config.get(server, key)
- else:
- current[key] = default
- if (current['server'] == repository or
- current['repository'] == repository):
- return current
- elif 'server-login' in sections:
- # old format
- server = 'server-login'
- if config.has_option(server, 'repository'):
- repository = config.get(server, 'repository')
- else:
- repository = DEFAULT_REPOSITORY
-
- return {'username': config.get(server, 'username'),
- 'password': config.get(server, 'password'),
- 'repository': repository,
- 'server': server,
- 'realm': DEFAULT_REALM}
-
- return {}
-
-
-def metadata_to_dict(meta):
- """XXX might want to move it to the Metadata class."""
- data = {
- 'metadata_version' : meta.version,
- 'name': meta['Name'],
- 'version': meta['Version'],
- 'summary': meta['Summary'],
- 'home_page': meta['Home-page'],
- 'author': meta['Author'],
- 'author_email': meta['Author-email'],
- 'license': meta['License'],
- 'description': meta['Description'],
- 'keywords': meta['Keywords'],
- 'platform': meta['Platform'],
- 'classifier': meta['Classifier'],
- 'download_url': meta['Download-URL'],
- }
-
- if meta.version == '1.2':
- data['requires_dist'] = meta['Requires-Dist']
- data['requires_python'] = meta['Requires-Python']
- data['requires_external'] = meta['Requires-External']
- data['provides_dist'] = meta['Provides-Dist']
- data['obsoletes_dist'] = meta['Obsoletes-Dist']
- data['project_url'] = [','.join(url) for url in
- meta['Project-URL']]
-
- elif meta.version == '1.1':
- data['provides'] = meta['Provides']
- data['requires'] = meta['Requires']
- data['obsoletes'] = meta['Obsoletes']
-
- return data
-
-# utility functions for 2to3 support
-
-def run_2to3(files, doctests_only=False, fixer_names=None, options=None,
- explicit=None):
- """ Wrapper function around the refactor() class which
- performs the conversions on a list of python files.
- Invoke 2to3 on a list of Python files. The files should all come
- from the build area, as the modification is done in-place."""
-
- #if not files:
- # return
-
- # Make this class local, to delay import of 2to3
- from lib2to3.refactor import get_fixers_from_package, RefactoringTool
- fixers = []
- fixers = get_fixers_from_package('lib2to3.fixes')
-
-
- if fixer_names:
- for fixername in fixer_names:
- fixers.extend([fixer for fixer in get_fixers_from_package(fixername)])
- r = RefactoringTool(fixers, options=options)
- if doctests_only:
- r.refactor(files, doctests_only=True, write=True)
- else:
- r.refactor(files, write=True)
-
-class Mixin2to3:
- """ Wrapper class for commands that run 2to3.
- To configure 2to3, setup scripts may either change
- the class variables, or inherit from this class
- to override how 2to3 is invoked.
- """
- # provide list of fixers to run.
- # defaults to all from lib2to3.fixers
- fixer_names = None
-
- # options dictionary
- options = None
-
- # list of fixers to invoke even though they are marked as explicit
- explicit = None
-
- def run_2to3(self, files, doctests_only=False):
- """ Issues a call to util.run_2to3. """
- return run_2to3(files, doctests_only, self.fixer_names,
- self.options, self.explicit)
diff --git a/src/distutils2/version.py b/src/distutils2/version.py
deleted file mode 100644
index 64c33f7..0000000
--- a/src/distutils2/version.py
+++ /dev/null
@@ -1,433 +0,0 @@
-import re
-
-from distutils2.errors import IrrationalVersionError, HugeMajorVersionNumError
-
-__all__ = ['NormalizedVersion', 'suggest_normalized_version',
- 'VersionPredicate', 'is_valid_version', 'is_valid_versions',
- 'is_valid_predicate']
-
-# A marker used in the second and third parts of the `parts` tuple, for
-# versions that don't have those segments, to sort properly. An example
-# of versions in sort order ('highest' last):
-# 1.0b1 ((1,0), ('b',1), ('f',))
-# 1.0.dev345 ((1,0), ('f',), ('dev', 345))
-# 1.0 ((1,0), ('f',), ('f',))
-# 1.0.post256.dev345 ((1,0), ('f',), ('f', 'post', 256, 'dev', 345))
-# 1.0.post345 ((1,0), ('f',), ('f', 'post', 345, 'f'))
-# ^ ^ ^
-# 'b' < 'f' ---------------------/ | |
-# | |
-# 'dev' < 'f' < 'post' -------------------/ |
-# |
-# 'dev' < 'f' ----------------------------------------------/
-# Other letters would do, but 'f' for 'final' is kind of nice.
-_FINAL_MARKER = ('f',)
-
-_VERSION_RE = re.compile(r'''
- ^
- (?P<version>\d+\.\d+) # minimum 'N.N'
- (?P<extraversion>(?:\.\d+)*) # any number of extra '.N' segments
- (?:
- (?P<prerel>[abc]|rc) # 'a'=alpha, 'b'=beta, 'c'=release candidate
- # 'rc'= alias for release candidate
- (?P<prerelversion>\d+(?:\.\d+)*)
- )?
- (?P<postdev>(\.post(?P<post>\d+))?(\.dev(?P<dev>\d+))?)?
- $''', re.VERBOSE)
-
-
-class NormalizedVersion(object):
- """A rational version.
-
- Good:
- 1.2 # equivalent to "1.2.0"
- 1.2.0
- 1.2a1
- 1.2.3a2
- 1.2.3b1
- 1.2.3c1
- 1.2.3.4
- TODO: fill this out
-
- Bad:
- 1 # mininum two numbers
- 1.2a # release level must have a release serial
- 1.2.3b
- """
- def __init__(self, s, error_on_huge_major_num=True):
- """Create a NormalizedVersion instance from a version string.
-
- @param s {str} The version string.
- @param error_on_huge_major_num {bool} Whether to consider an
- apparent use of a year or full date as the major version number
- an error. Default True. One of the observed patterns on PyPI before
- the introduction of `NormalizedVersion` was version numbers like
- this:
- 2009.01.03
- 20040603
- 2005.01
- This guard is here to strongly encourage the package author to
- use an alternate version, because a release deployed into PyPI
- and, e.g. downstream Linux package managers, will forever remove
- the possibility of using a version number like "1.0" (i.e.
- where the major number is less than that huge major number).
- """
- self.is_final = True # by default, consider a version as final.
- self._parse(s, error_on_huge_major_num)
-
- @classmethod
- def from_parts(cls, version, prerelease=_FINAL_MARKER,
- devpost=_FINAL_MARKER):
- return cls(cls.parts_to_str((version, prerelease, devpost)))
-
- def _parse(self, s, error_on_huge_major_num=True):
- """Parses a string version into parts."""
- match = _VERSION_RE.search(s)
- if not match:
- raise IrrationalVersionError(s)
-
- groups = match.groupdict()
- parts = []
-
- # main version
- block = self._parse_numdots(groups['version'], s, False, 2)
- extraversion = groups.get('extraversion')
- if extraversion not in ('', None):
- block += self._parse_numdots(extraversion[1:], s)
- parts.append(tuple(block))
-
- # prerelease
- prerel = groups.get('prerel')
- if prerel is not None:
- block = [prerel]
- block += self._parse_numdots(groups.get('prerelversion'), s,
- pad_zeros_length=1)
- parts.append(tuple(block))
- self.is_final = False
- else:
- parts.append(_FINAL_MARKER)
-
- # postdev
- if groups.get('postdev'):
- post = groups.get('post')
- dev = groups.get('dev')
- postdev = []
- if post is not None:
- postdev.extend([_FINAL_MARKER[0], 'post', int(post)])
- if dev is None:
- postdev.append(_FINAL_MARKER[0])
- if dev is not None:
- postdev.extend(['dev', int(dev)])
- self.is_final = False
- parts.append(tuple(postdev))
- else:
- parts.append(_FINAL_MARKER)
- self.parts = tuple(parts)
- if error_on_huge_major_num and self.parts[0][0] > 1980:
- raise HugeMajorVersionNumError("huge major version number, %r, "
- "which might cause future problems: %r" % (self.parts[0][0], s))
-
- def _parse_numdots(self, s, full_ver_str, drop_trailing_zeros=True,
- pad_zeros_length=0):
- """Parse 'N.N.N' sequences, return a list of ints.
-
- @param s {str} 'N.N.N..." sequence to be parsed
- @param full_ver_str {str} The full version string from which this
- comes. Used for error strings.
- @param drop_trailing_zeros {bool} Whether to drop trailing zeros
- from the returned list. Default True.
- @param pad_zeros_length {int} The length to which to pad the
- returned list with zeros, if necessary. Default 0.
- """
- nums = []
- for n in s.split("."):
- if len(n) > 1 and n[0] == '0':
- raise IrrationalVersionError("cannot have leading zero in "
- "version number segment: '%s' in %r" % (n, full_ver_str))
- nums.append(int(n))
- if drop_trailing_zeros:
- while nums and nums[-1] == 0:
- nums.pop()
- while len(nums) < pad_zeros_length:
- nums.append(0)
- return nums
-
- def __str__(self):
- return self.parts_to_str(self.parts)
-
- @classmethod
- def parts_to_str(cls, parts):
- """Transforms a version expressed in tuple into its string
- representation."""
- # XXX This doesn't check for invalid tuples
- main, prerel, postdev = parts
- s = '.'.join(str(v) for v in main)
- if prerel is not _FINAL_MARKER:
- s += prerel[0]
- s += '.'.join(str(v) for v in prerel[1:])
- if postdev and postdev is not _FINAL_MARKER:
- if postdev[0] == 'f':
- postdev = postdev[1:]
- i = 0
- while i < len(postdev):
- if i % 2 == 0:
- s += '.'
- s += str(postdev[i])
- i += 1
- return s
-
- def __repr__(self):
- return "%s('%s')" % (self.__class__.__name__, self)
-
- def _cannot_compare(self, other):
- raise TypeError("cannot compare %s and %s"
- % (type(self).__name__, type(other).__name__))
-
- def __eq__(self, other):
- if not isinstance(other, NormalizedVersion):
- self._cannot_compare(other)
- return self.parts == other.parts
-
- def __lt__(self, other):
- if not isinstance(other, NormalizedVersion):
- self._cannot_compare(other)
- return self.parts < other.parts
-
- def __ne__(self, other):
- return not self.__eq__(other)
-
- def __gt__(self, other):
- return not (self.__lt__(other) or self.__eq__(other))
-
- def __le__(self, other):
- return self.__eq__(other) or self.__lt__(other)
-
- def __ge__(self, other):
- return self.__eq__(other) or self.__gt__(other)
-
- # See http://docs.python.org/reference/datamodel#object.__hash__
- __hash__ = object.__hash__
-
-
-def suggest_normalized_version(s):
- """Suggest a normalized version close to the given version string.
-
- If you have a version string that isn't rational (i.e. NormalizedVersion
- doesn't like it) then you might be able to get an equivalent (or close)
- rational version from this function.
-
- This does a number of simple normalizations to the given string, based
- on observation of versions currently in use on PyPI. Given a dump of
- those version during PyCon 2009, 4287 of them:
- - 2312 (53.93%) match NormalizedVersion without change
- with the automatic suggestion
- - 3474 (81.04%) match when using this suggestion method
-
- @param s {str} An irrational version string.
- @returns A rational version string, or None, if couldn't determine one.
- """
- try:
- NormalizedVersion(s)
- return s # already rational
- except IrrationalVersionError:
- pass
-
- rs = s.lower()
-
- # part of this could use maketrans
- for orig, repl in (('-alpha', 'a'), ('-beta', 'b'), ('alpha', 'a'),
- ('beta', 'b'), ('rc', 'c'), ('-final', ''),
- ('-pre', 'c'),
- ('-release', ''), ('.release', ''), ('-stable', ''),
- ('+', '.'), ('_', '.'), (' ', ''), ('.final', ''),
- ('final', '')):
- rs = rs.replace(orig, repl)
-
- # if something ends with dev or pre, we add a 0
- rs = re.sub(r"pre$", r"pre0", rs)
- rs = re.sub(r"dev$", r"dev0", rs)
-
- # if we have something like "b-2" or "a.2" at the end of the
- # version, that is pobably beta, alpha, etc
- # let's remove the dash or dot
- rs = re.sub(r"([abc|rc])[\-\.](\d+)$", r"\1\2", rs)
-
- # 1.0-dev-r371 -> 1.0.dev371
- # 0.1-dev-r79 -> 0.1.dev79
- rs = re.sub(r"[\-\.](dev)[\-\.]?r?(\d+)$", r".\1\2", rs)
-
- # Clean: 2.0.a.3, 2.0.b1, 0.9.0~c1
- rs = re.sub(r"[.~]?([abc])\.?", r"\1", rs)
-
- # Clean: v0.3, v1.0
- if rs.startswith('v'):
- rs = rs[1:]
-
- # Clean leading '0's on numbers.
- #TODO: unintended side-effect on, e.g., "2003.05.09"
- # PyPI stats: 77 (~2%) better
- rs = re.sub(r"\b0+(\d+)(?!\d)", r"\1", rs)
-
- # Clean a/b/c with no version. E.g. "1.0a" -> "1.0a0". Setuptools infers
- # zero.
- # PyPI stats: 245 (7.56%) better
- rs = re.sub(r"(\d+[abc])$", r"\g<1>0", rs)
-
- # the 'dev-rNNN' tag is a dev tag
- rs = re.sub(r"\.?(dev-r|dev\.r)\.?(\d+)$", r".dev\2", rs)
-
- # clean the - when used as a pre delimiter
- rs = re.sub(r"-(a|b|c)(\d+)$", r"\1\2", rs)
-
- # a terminal "dev" or "devel" can be changed into ".dev0"
- rs = re.sub(r"[\.\-](dev|devel)$", r".dev0", rs)
-
- # a terminal "dev" can be changed into ".dev0"
- rs = re.sub(r"(?![\.\-])dev$", r".dev0", rs)
-
- # a terminal "final" or "stable" can be removed
- rs = re.sub(r"(final|stable)$", "", rs)
-
- # The 'r' and the '-' tags are post release tags
- # 0.4a1.r10 -> 0.4a1.post10
- # 0.9.33-17222 -> 0.9.3.post17222
- # 0.9.33-r17222 -> 0.9.3.post17222
- rs = re.sub(r"\.?(r|-|-r)\.?(\d+)$", r".post\2", rs)
-
- # Clean 'r' instead of 'dev' usage:
- # 0.9.33+r17222 -> 0.9.3.dev17222
- # 1.0dev123 -> 1.0.dev123
- # 1.0.git123 -> 1.0.dev123
- # 1.0.bzr123 -> 1.0.dev123
- # 0.1a0dev.123 -> 0.1a0.dev123
- # PyPI stats: ~150 (~4%) better
- rs = re.sub(r"\.?(dev|git|bzr)\.?(\d+)$", r".dev\2", rs)
-
- # Clean '.pre' (normalized from '-pre' above) instead of 'c' usage:
- # 0.2.pre1 -> 0.2c1
- # 0.2-c1 -> 0.2c1
- # 1.0preview123 -> 1.0c123
- # PyPI stats: ~21 (0.62%) better
- rs = re.sub(r"\.?(pre|preview|-c)(\d+)$", r"c\g<2>", rs)
-
- # Tcl/Tk uses "px" for their post release markers
- rs = re.sub(r"p(\d+)$", r".post\1", rs)
-
- try:
- NormalizedVersion(rs)
- return rs # already rational
- except IrrationalVersionError:
- pass
- return None
-
-
-_PREDICATE = re.compile(r"(?i)^\s*([a-z_][\sa-zA-Z_-]*(?:\.[a-z_]\w*)*)(.*)")
-_VERSIONS = re.compile(r"^\s*\((.*)\)\s*$")
-_PLAIN_VERSIONS = re.compile(r"^\s*(.*)\s*$")
-_SPLIT_CMP = re.compile(r"^\s*(<=|>=|<|>|!=|==)\s*([^\s,]+)\s*$")
-
-
-def _split_predicate(predicate):
- match = _SPLIT_CMP.match(predicate)
- if match is None:
- # probably no op, we'll use "=="
- comp, version = '==', predicate
- else:
- comp, version = match.groups()
- return comp, NormalizedVersion(version)
-
-
-class VersionPredicate(object):
- """Defines a predicate: ProjectName (>ver1,ver2, ..)"""
-
- _operators = {"<": lambda x, y: x < y,
- ">": lambda x, y: x > y,
- "<=": lambda x, y: str(x).startswith(str(y)) or x < y,
- ">=": lambda x, y: str(x).startswith(str(y)) or x > y,
- "==": lambda x, y: str(x).startswith(str(y)),
- "!=": lambda x, y: not str(x).startswith(str(y)),
- }
-
- def __init__(self, predicate):
- self._string = predicate
- predicate = predicate.strip()
- match = _PREDICATE.match(predicate)
- if match is None:
- raise ValueError('Bad predicate "%s"' % predicate)
-
- name, predicates = match.groups()
- self.name = name.strip()
- predicates = predicates.strip()
- predicates = _VERSIONS.match(predicates)
- if predicates is not None:
- predicates = predicates.groups()[0]
- self.predicates = [_split_predicate(pred.strip())
- for pred in predicates.split(',')]
- else:
- self.predicates = []
-
- def match(self, version):
- """Check if the provided version matches the predicates."""
- if isinstance(version, str):
- version = NormalizedVersion(version)
- for operator, predicate in self.predicates:
- if not self._operators[operator](version, predicate):
- return False
- return True
-
- def __repr__(self):
- return self._string
-
-
-class _Versions(VersionPredicate):
- def __init__(self, predicate):
- predicate = predicate.strip()
- match = _PLAIN_VERSIONS.match(predicate)
- self.name = None
- predicates = match.groups()[0]
- self.predicates = [_split_predicate(pred.strip())
- for pred in predicates.split(',')]
-
-
-class _Version(VersionPredicate):
- def __init__(self, predicate):
- predicate = predicate.strip()
- match = _PLAIN_VERSIONS.match(predicate)
- self.name = None
- self.predicates = _split_predicate(match.groups()[0])
-
-
-def is_valid_predicate(predicate):
- try:
- VersionPredicate(predicate)
- except (ValueError, IrrationalVersionError):
- return False
- else:
- return True
-
-
-def is_valid_versions(predicate):
- try:
- _Versions(predicate)
- except (ValueError, IrrationalVersionError):
- return False
- else:
- return True
-
-
-def is_valid_version(predicate):
- try:
- _Version(predicate)
- except (ValueError, IrrationalVersionError):
- return False
- else:
- return True
-
-
-def get_version_predicate(requirements):
- """Return a VersionPredicate object, from a string or an already
- existing object.
- """
- if isinstance(requirements, str):
- requirements = VersionPredicate(requirements)
- return requirements
diff --git a/src/runtests-cov.py b/src/runtests-cov.py
deleted file mode 100755
index d6678b4..0000000
--- a/src/runtests-cov.py
+++ /dev/null
@@ -1,136 +0,0 @@
-#!/usr/bin/env python
-"""Tests for distutils2.
-
-The tests for distutils2 are defined in the distutils2.tests package.
-"""
-
-import sys
-from os.path import dirname, islink, realpath, join, abspath
-from optparse import OptionParser
-
-COVERAGE_FILE = join(dirname(abspath(__file__)), '.coverage')
-
-def get_coverage():
- """ Return a usable coverage object. """
- # deferred import because coverage is optional
- import coverage
- cov = getattr(coverage, "the_coverage", None)
- if not cov:
- cov = coverage.coverage(COVERAGE_FILE)
- return cov
-
-def ignore_prefixes(module):
- """ Return a list of prefixes to ignore in the coverage report if
- we want to completely skip `module`.
- """
- # A function like that is needed because some GNU/Linux
- # distributions, such a Ubuntu, really like to build link farm in
- # /usr/lib in order to save a few bytes on the disk.
- dirnames = [dirname(module.__file__)]
-
- pymod = module.__file__.rstrip("c")
- if islink(pymod):
- dirnames.append(dirname(realpath(pymod)))
- return dirnames
-
-
-def parse_opts():
- parser = OptionParser(usage="%prog [OPTIONS]",
- description="run the distutils2 unittests")
-
- parser.add_option("-q", "--quiet", help="do not print verbose messages",
- action="store_true", default=False)
- parser.add_option("-c", "--coverage", action="store_true", default=False,
- help="produce a coverage report at the end of the run")
- parser.add_option("-r", "--report", action="store_true", default=False,
- help="produce a coverage report from the last test run")
- parser.add_option("-m", "--show-missing", action="store_true",
- default=False,
- help=("Show line numbers of statements in each module "
- "that weren't executed."))
-
- opts, args = parser.parse_args()
- return opts, args
-
-
-def coverage_report(opts):
- from distutils2.tests.support import unittest
- cov = get_coverage()
- if hasattr(cov, "load"):
- # running coverage 3.x
- cov.load()
- morfs = None
- else:
- # running coverage 2.x
- cov.cache = COVERAGE_FILE
- cov.restore()
- morfs = [m for m in cov.cexecuted.keys() if "distutils2" in m]
-
- prefixes = ["runtests", "distutils2/tests", "distutils2/_backport"]
- prefixes += ignore_prefixes(unittest)
-
- try:
- import docutils
- prefixes += ignore_prefixes(docutils)
- except ImportError:
- # that module is completely optional
- pass
-
- try:
- import roman
- prefixes += ignore_prefixes(roman)
- except ImportError:
- # that module is also completely optional
- pass
-
- cov.report(morfs, omit_prefixes=prefixes, show_missing=opts.show_missing)
-
-
-def test_main():
- opts, args = parse_opts()
- verbose = not opts.quiet
- ret = 0
-
- if opts.coverage:
- cov = get_coverage()
- cov.erase()
- cov.start()
- if not opts.report:
- ret = run_tests(verbose)
- if opts.coverage:
- cov.stop()
- cov.save()
-
- if opts.report or opts.coverage:
- coverage_report(opts)
-
- return ret
-
-
-def run_tests(verbose):
- import distutils2.tests
- from distutils2.tests import run_unittest, reap_children, TestFailed
- from distutils2._backport.tests import test_suite as btest_suite
- # XXX just supporting -q right now to enable detailed/quiet output
- if len(sys.argv) > 1:
- verbose = sys.argv[-1] != '-q'
- else:
- verbose = 1
- try:
- try:
- run_unittest([distutils2.tests.test_suite(), btest_suite()],
- verbose_=verbose)
- return 0
- except TestFailed:
- return 1
- finally:
- reap_children()
-
-
-if __name__ == "__main__":
- try:
- from distutils2.tests.support import unittest
- except ImportError:
- sys.stderr.write('Error: You have to install unittest2')
- sys.exit(1)
- sys.exit(test_main())
diff --git a/src/runtests.py b/src/runtests.py
deleted file mode 100644
index 415d37a..0000000
--- a/src/runtests.py
+++ /dev/null
@@ -1,36 +0,0 @@
-#!/usr/bin/env python
-"""Tests for distutils2.
-
-The tests for distutils2 are defined in the distutils2.tests package.
-"""
-
-import sys
-
-
-def test_main():
- import distutils2.tests
- from distutils2.tests import run_unittest, reap_children, TestFailed
- from distutils2._backport.tests import test_suite as btest_suite
- # XXX just supporting -q right now to enable detailed/quiet output
- if len(sys.argv) > 1:
- verbose = sys.argv[-1] != '-q'
- else:
- verbose = 1
- try:
- try:
- run_unittest([distutils2.tests.test_suite(), btest_suite()],
- verbose_=verbose)
- return 0
- except TestFailed:
- return 1
- finally:
- reap_children()
-
-
-if __name__ == "__main__":
- try:
- from distutils2.tests.support import unittest
- except ImportError:
- sys.stderr.write('Error: You have to install unittest2')
- sys.exit(1)
- sys.exit(test_main())
diff --git a/src/setup.cfg b/src/setup.cfg
deleted file mode 100644
index 169aaf6..0000000
--- a/src/setup.cfg
+++ /dev/null
@@ -1,3 +0,0 @@
-[build_ext]
-# needed so that tests work without mucking with sys.path
-inplace = 1
diff --git a/src/setup.py b/src/setup.py
deleted file mode 100644
index 4a1794d..0000000
--- a/src/setup.py
+++ /dev/null
@@ -1,230 +0,0 @@
-#!/usr/bin/env python
-# -*- encoding: utf8 -*-
-__revision__ = "$Id$"
-import sys
-import os
-import re
-
-from distutils2 import __version__ as VERSION
-from distutils2 import log
-from distutils2.core import setup, Extension
-from distutils2.compiler.ccompiler import new_compiler
-from distutils2.command.sdist import sdist
-from distutils2.command.install import install
-from distutils2.util import find_packages
-
-f = open('README.txt')
-try:
- README = f.read()
-finally:
- f.close()
-
-def get_tip_revision(path=os.getcwd()):
- from subprocess import Popen, PIPE
- try:
- cmd = Popen(['hg', 'tip', '--template', '{rev}', '-R', path],
- stdout=PIPE, stderr=PIPE)
- except OSError:
- return 0
- rev = cmd.stdout.read()
- if rev == '':
- # there has been an error in the command
- return 0
- return int(rev)
-
-DEV_SUFFIX = '.dev%d' % get_tip_revision('..')
-
-
-class install_hg(install):
-
- user_options = install.user_options + [
- ('dev', None, "Add a dev marker")
- ]
-
- def initialize_options(self):
- install.initialize_options(self)
- self.dev = 0
-
- def run(self):
- if self.dev:
- self.distribution.metadata.version += DEV_SUFFIX
- install.run(self)
-
-
-class sdist_hg(sdist):
-
- user_options = sdist.user_options + [
- ('dev', None, "Add a dev marker")
- ]
-
- def initialize_options(self):
- sdist.initialize_options(self)
- self.dev = 0
-
- def run(self):
- if self.dev:
- self.distribution.metadata.version += DEV_SUFFIX
- sdist.run(self)
-
-
-# additional paths to check, set from the command line
-SSL_INCDIR = '' # --openssl-incdir=
-SSL_LIBDIR = '' # --openssl-libdir=
-SSL_DIR = '' # --openssl-prefix=
-
-def add_dir_to_list(dirlist, dir):
- """Add the directory 'dir' to the list 'dirlist' (at the front) if
- 'dir' actually exists and is a directory. If 'dir' is already in
- 'dirlist' it is moved to the front.
- """
- if dir is not None and os.path.isdir(dir) and dir not in dirlist:
- if dir in dirlist:
- dirlist.remove(dir)
- dirlist.insert(0, dir)
-
-
-def prepare_hashlib_extensions():
- """Decide which C extensions to build and create the appropriate
- Extension objects to build them. Return a list of Extensions.
- """
- # this CCompiler object is only used to locate include files
- compiler = new_compiler()
-
- # Ensure that these paths are always checked
- if os.name == 'posix':
- add_dir_to_list(compiler.library_dirs, '/usr/local/lib')
- add_dir_to_list(compiler.include_dirs, '/usr/local/include')
-
- add_dir_to_list(compiler.library_dirs, '/usr/local/ssl/lib')
- add_dir_to_list(compiler.include_dirs, '/usr/local/ssl/include')
-
- add_dir_to_list(compiler.library_dirs, '/usr/contrib/ssl/lib')
- add_dir_to_list(compiler.include_dirs, '/usr/contrib/ssl/include')
-
- add_dir_to_list(compiler.library_dirs, '/usr/lib')
- add_dir_to_list(compiler.include_dirs, '/usr/include')
-
- # look in paths supplied on the command line
- if SSL_LIBDIR:
- add_dir_to_list(compiler.library_dirs, SSL_LIBDIR)
- if SSL_INCDIR:
- add_dir_to_list(compiler.include_dirs, SSL_INCDIR)
- if SSL_DIR:
- if os.name == 'nt':
- add_dir_to_list(compiler.library_dirs, os.path.join(SSL_DIR, 'out32dll'))
- # prefer the static library
- add_dir_to_list(compiler.library_dirs, os.path.join(SSL_DIR, 'out32'))
- else:
- add_dir_to_list(compiler.library_dirs, os.path.join(SSL_DIR, 'lib'))
- add_dir_to_list(compiler.include_dirs, os.path.join(SSL_DIR, 'include'))
-
- oslibs = {'posix': ['ssl', 'crypto'],
- 'nt': ['libeay32', 'gdi32', 'advapi32', 'user32']}
-
- if os.name not in oslibs:
- sys.stderr.write(
- 'unknown operating system, impossible to compile _hashlib')
- sys.exit(1)
-
- exts = []
-
- ssl_inc_dirs = []
- ssl_incs = []
- for inc_dir in compiler.include_dirs:
- f = os.path.join(inc_dir, 'openssl', 'ssl.h')
- if os.path.exists(f):
- ssl_incs.append(f)
- ssl_inc_dirs.append(inc_dir)
-
- ssl_lib = compiler.find_library_file(compiler.library_dirs, oslibs[os.name][0])
-
- # find out which version of OpenSSL we have
- openssl_ver = 0
- openssl_ver_re = re.compile(
- '^\s*#\s*define\s+OPENSSL_VERSION_NUMBER\s+(0x[0-9a-fA-F]+)' )
- ssl_inc_dir = ''
- for ssl_inc_dir in ssl_inc_dirs:
- name = os.path.join(ssl_inc_dir, 'openssl', 'opensslv.h')
- if os.path.isfile(name):
- try:
- incfile = open(name, 'r')
- for line in incfile:
- m = openssl_ver_re.match(line)
- if m:
- openssl_ver = int(m.group(1), 16)
- break
- except IOError:
- pass
-
- # first version found is what we'll use
- if openssl_ver:
- break
-
- if (ssl_inc_dir and ssl_lib is not None and openssl_ver >= 0x00907000):
-
- log.info('Using OpenSSL version 0x%08x from', openssl_ver)
- log.info(' Headers:\t%s', ssl_inc_dir)
- log.info(' Library:\t%s', ssl_lib)
-
- # The _hashlib module wraps optimized implementations
- # of hash functions from the OpenSSL library.
- exts.append(Extension('distutils2._backport._hashlib',
- ['distutils2/_backport/_hashopenssl.c'],
- include_dirs = [ssl_inc_dir],
- library_dirs = [os.path.dirname(ssl_lib)],
- libraries = oslibs[os.name]))
- else:
- exts.append(Extension('distutils2._backport._sha',
- ['distutils2/_backport/shamodule.c']))
- exts.append(Extension('distutils2._backport._md5',
- sources=['distutils2/_backport/md5module.c',
- 'distutils2/_backport/md5.c'],
- depends=['distutils2/_backport/md5.h']) )
-
- if (not ssl_lib or openssl_ver < 0x00908000):
- # OpenSSL doesn't do these until 0.9.8 so we'll bring our own
- exts.append(Extension('distutils2._backport._sha256',
- ['distutils2/_backport/sha256module.c']))
- exts.append(Extension('distutils2._backport._sha512',
- ['distutils2/_backport/sha512module.c']))
-
- return exts
-
-setup_kwargs = {}
-if sys.version < '2.6':
- setup_kwargs['scripts'] = ['distutils2/mkpkg.py']
-
-if sys.version < '2.5':
- setup_kwargs['ext_modules'] = prepare_hashlib_extensions()
-
-_CLASSIFIERS = """\
-Development Status :: 3 - Alpha
-Intended Audience :: Developers
-License :: OSI Approved :: Python Software Foundation License
-Operating System :: OS Independent
-Programming Language :: Python
-Topic :: Software Development :: Libraries :: Python Modules
-Topic :: System :: Archiving :: Packaging
-Topic :: System :: Systems Administration
-Topic :: Utilities"""
-
-setup(name="Distutils2",
- version=VERSION,
- summary="Python Distribution Utilities",
- keywords=['packaging', 'distutils'],
- author="Tarek Ziade",
- author_email="tarek@ziade.org",
- home_page="http://bitbucket.org/tarek/distutils2/wiki/Home",
- license="PSF",
- description=README,
- classifier=_CLASSIFIERS.split('\n'),
- packages=find_packages(),
- cmdclass={'sdist': sdist_hg, 'install': install_hg},
- package_data={'distutils2._backport': ['sysconfig.cfg']},
- project_url=[('Mailing list',
- 'http://mail.python.org/mailman/listinfo/distutils-sig/'),
- ('Documentation',
- 'http://packages.python.org/Distutils2'),
- ('Repository', 'http://hg.python.org/distutils2'),
- ('Bug tracker', 'http://bugs.python.org')],
- **setup_kwargs)
diff --git a/src/tests.sh b/src/tests.sh
deleted file mode 100755
index a78c005..0000000
--- a/src/tests.sh
+++ /dev/null
@@ -1,40 +0,0 @@
-#!/bin/sh
-echo -n "Running tests for Python 2.4... "
-rm -f distutils2/_backport/_hashlib.so
-python2.4 setup.py build_ext -f -q 2> /dev/null > /dev/null
-python2.4 -Wd runtests.py -q 2> /dev/null
-if [ $? -ne 0 ];then
- echo Failed
- rm -f distutils2/_backport/_hashlib.so
- exit 1
-else
- echo Success
-fi
-
-echo -n "Running tests for Python 2.5... "
-python2.5 -Wd runtests.py -q 2> /dev/null
-if [ $? -ne 0 ];then
- echo Failed
- exit 1
-else
- echo Success
-fi
-
-echo -n "Running tests for Python 2.6... "
-python2.6 -Wd runtests.py -q 2> /dev/null
-if [ $? -ne 0 ];then
- echo Failed
- exit 1
-else
- echo Success
-fi
-
-echo -n "Running tests for Python 2.7... "
-python2.7 -Wd -bb -3 runtests.py -q 2> /dev/null
-if [ $? -ne 0 ];then
- echo Failed
- exit 1
-else
- echo Success
-fi
-echo "Good job, commit now! (or add tests)"