Commit a85aa143 authored by Jason R. Coombs's avatar Jason R. Coombs

Merge Vinay Sajip's unified Python 2/3 support from distribute 3

--HG--
branch : distribute
parents 94fc39cb 641eac65
...@@ -11,3 +11,4 @@ bin ...@@ -11,3 +11,4 @@ bin
include include
\.Python \.Python
*.swp *.swp
CHANGES (links).txt
...@@ -37,3 +37,21 @@ de44acab3cfce1f5bc811d6c0fa1a88ca0e9533f 0.6.21 ...@@ -37,3 +37,21 @@ de44acab3cfce1f5bc811d6c0fa1a88ca0e9533f 0.6.21
b69f072c000237435e17b8bbb304ba6f957283eb 0.6.26 b69f072c000237435e17b8bbb304ba6f957283eb 0.6.26
469c3b948e41ef28752b3cdf3c7fb9618355ebf5 0.6.27 469c3b948e41ef28752b3cdf3c7fb9618355ebf5 0.6.27
fc379e63586ad3c6838e1bda216548ba8270b8f0 0.6.28 fc379e63586ad3c6838e1bda216548ba8270b8f0 0.6.28
4f82563d0f5d1af1fb215c0ac87f38b16bb5c42d 0.6.29
7464fc916fa4d8308e34e45a1198512fe04c97b4 0.6.30
17bc972d67edd96c7748061910172e1200a73efe 0.6.31
b1a7f86b315a1f8c20036d718d6dc641bb84cac6 0.6.32
6acac3919ae9a7dba2cbecbe3d4b31ece25d5f09 0.6.33
23c310bf4ae8e4616e37027f08891702f5a33bc9 0.6.34
2abe1117543be0edbafb10c7c159d1bcb1cb1b87 0.6.35
c813a29e831f266d427d4a4bce3da97f475a8eee 0.6.36
be6f65eea9c10ce78b6698d8c220b6e5de577292 0.6.37
2b26ec8909bff210f47c5f8fc620bc505e1610b5 0.6.37
f0d502a83f6c83ba38ad21c15a849c2daf389ec7 0.6.38
d737b2039c5f92af8000f78bbc80b6a5183caa97 0.6.39
0a783fa0dceb95b5fc743e47c2d89c1523d0afb7 0.6.40
ad107e9b4beea24516ac4e1e854696e586fe279d 0.6.41
f30167716b659f96c5e0b7ea3d5be2bcff8c0eac 0.6.42
35086ee286732b0f63d2be18d9f26f2734586e2d 0.6.43
73aa98aee6bbc4a9d19a334a8ac928dece7799c6 0.6.44
ddca71ae5ceb9b14512dc60ea83802c10e224cf0 0.6.45
...@@ -4,5 +4,6 @@ python: ...@@ -4,5 +4,6 @@ python:
- 2.6 - 2.6
- 2.7 - 2.7
- 3.2 - 3.2
- 3.3
# command to run tests # command to run tests
script: python setup.py test script: python setup.py test
This diff is collapsed.
...@@ -8,16 +8,21 @@ Contributors ...@@ -8,16 +8,21 @@ Contributors
* Christophe Combelles * Christophe Combelles
* Daniel Stutzbach * Daniel Stutzbach
* Daniel Holth * Daniel Holth
* Dirley Rodrigues
* Grigory Petrov
* Hanno Schlichting * Hanno Schlichting
* Jannis Leidel * Jannis Leidel
* Jason R. Coombs * Jason R. Coombs
* Jim Fulton * Jim Fulton
* Jonathan Lange
* Justin Azoff * Justin Azoff
* Lennart Regebro * Lennart Regebro
* Marc Abramowitz * Marc Abramowitz
* Martin von Löwis * Martin von Löwis
* Noufal Ibrahim * Noufal Ibrahim
* Pete Hollobon
* Philip Jenvey * Philip Jenvey
* Philip Thiem
* Reinout van Rees * Reinout van Rees
* Robert Myers * Robert Myers
* Stefan H. Holek * Stefan H. Holek
......
recursive-include setuptools *.py *.txt *.exe recursive-include setuptools *.py *.txt *.exe *.xml
recursive-include tests *.py *.c *.pyx *.txt recursive-include tests *.py *.c *.pyx *.txt
recursive-include setuptools/tests *.html recursive-include setuptools/tests *.html
recursive-include docs *.py *.txt *.conf *.css *.css_t Makefile indexsidebar.html recursive-include docs *.py *.txt *.conf *.css *.css_t Makefile indexsidebar.html
......
...@@ -11,35 +11,14 @@ Disclaimers ...@@ -11,35 +11,14 @@ Disclaimers
About the fork About the fork
============== ==============
`Distribute` is a fork of the `Setuptools` project. `Distribute` is a now deprecated fork of the `Setuptools` project.
Distribute is intended to replace Setuptools as the standard method Distribute was intended to replace Setuptools as the standard method
for working with Python module distributions. for working with Python module distributions. The code has since been merged
back into the parent project as is being maintained by the community at large.
The fork has two goals: `Distribute` is now being maintained as a branch in the `Setuptools
repository <https://bitbucket.org/pypa/setuptools>`_.
- Providing a backward compatible version to replace Setuptools
and make all distributions that depend on Setuptools work as
before, but with less bugs and behaviorial issues.
This work is done in the 0.6.x series.
Starting with version 0.6.2, Distribute supports Python 3.
Installing and using distribute for Python 3 code works exactly
the same as for Python 2 code, but Distribute also helps you to support
Python 2 and Python 3 from the same source code by letting you run 2to3
on the code as a part of the build process, by setting the keyword parameter
``use_2to3`` to True. See http://packages.python.org/distribute for more
information.
- Refactoring the code, and releasing it in several distributions.
This work is being done in the 0.7.x series but not yet released.
The roadmap is still evolving, and the page that is up-to-date is
located at : `http://packages.python.org/distribute/roadmap`.
If you install `Distribute` and want to switch back for any reason to
`Setuptools`, get to the `Uninstallation instructions`_ section.
More documentation More documentation
================== ==================
...@@ -99,9 +78,9 @@ Source installation ...@@ -99,9 +78,9 @@ Source installation
Download the source tarball, uncompress it, then run the install command:: Download the source tarball, uncompress it, then run the install command::
$ curl -O http://pypi.python.org/packages/source/d/distribute/distribute-0.6.29.tar.gz $ curl -O http://pypi.python.org/packages/source/d/distribute/distribute-0.6.46.tar.gz
$ tar -xzvf distribute-0.6.29.tar.gz $ tar -xzvf distribute-0.6.46.tar.gz
$ cd distribute-0.6.29 $ cd distribute-0.6.46
$ python setup.py install $ python setup.py install
--------------------------- ---------------------------
...@@ -224,5 +203,4 @@ Feedback and getting involved ...@@ -224,5 +203,4 @@ Feedback and getting involved
- Mailing list: http://mail.python.org/mailman/listinfo/distutils-sig - Mailing list: http://mail.python.org/mailman/listinfo/distutils-sig
- Issue tracker: http://bitbucket.org/tarek/distribute/issues/ - Issue tracker: http://bitbucket.org/tarek/distribute/issues/
- Code Repository: http://bitbucket.org/tarek/distribute - Code Repository: http://bitbucket.org/pypa/setuptools?at=distribute
...@@ -17,9 +17,7 @@ where EXPR belongs to any of those: ...@@ -17,9 +17,7 @@ where EXPR belongs to any of those:
__all__ = ['default_environment', 'compile', 'interpret'] __all__ = ['default_environment', 'compile', 'interpret']
from ast import Compare, BoolOp, Attribute, Name, Load, Str, cmpop, boolop import ast
from ast import parse, copy_location, NodeTransformer
import os import os
import platform import platform
import sys import sys
...@@ -27,7 +25,16 @@ import weakref ...@@ -27,7 +25,16 @@ import weakref
_builtin_compile = compile _builtin_compile = compile
from platform import python_implementation try:
from platform import python_implementation
except ImportError:
if os.name == "java":
# Jython 2.5 has ast module, but not platform.python_implementation() function.
def python_implementation():
return "Jython"
else:
raise
# restricted set of variables # restricted set of variables
_VARS = {'sys.platform': sys.platform, _VARS = {'sys.platform': sys.platform,
...@@ -46,27 +53,31 @@ def default_environment(): ...@@ -46,27 +53,31 @@ def default_environment():
"""Return copy of default PEP 385 globals dictionary.""" """Return copy of default PEP 385 globals dictionary."""
return dict(_VARS) return dict(_VARS)
class ASTWhitelist(NodeTransformer): class ASTWhitelist(ast.NodeTransformer):
def __init__(self, statement): def __init__(self, statement):
self.statement = statement # for error messages self.statement = statement # for error messages
ALLOWED = (Compare, BoolOp, Attribute, Name, Load, Str, cmpop, boolop) ALLOWED = (ast.Compare, ast.BoolOp, ast.Attribute, ast.Name, ast.Load, ast.Str)
# Bool operations
ALLOWED += (ast.And, ast.Or)
# Comparison operations
ALLOWED += (ast.Eq, ast.Gt, ast.GtE, ast.In, ast.Is, ast.IsNot, ast.Lt, ast.LtE, ast.NotEq, ast.NotIn)
def visit(self, node): def visit(self, node):
"""Ensure statement only contains allowed nodes.""" """Ensure statement only contains allowed nodes."""
if not isinstance(node, self.ALLOWED): if not isinstance(node, self.ALLOWED):
raise SyntaxError('Not allowed in environment markers.\n%s\n%s' % raise SyntaxError('Not allowed in environment markers.\n%s\n%s' %
(self.statement, (self.statement,
(' ' * node.col_offset) + '^')) (' ' * node.col_offset) + '^'))
return NodeTransformer.visit(self, node) return ast.NodeTransformer.visit(self, node)
def visit_Attribute(self, node): def visit_Attribute(self, node):
"""Flatten one level of attribute access.""" """Flatten one level of attribute access."""
new_node = Name("%s.%s" % (node.value.id, node.attr), node.ctx) new_node = ast.Name("%s.%s" % (node.value.id, node.attr), node.ctx)
return copy_location(new_node, node) return ast.copy_location(new_node, node)
def parse_marker(marker): def parse_marker(marker):
tree = parse(marker, mode='eval') tree = ast.parse(marker, mode='eval')
new_tree = ASTWhitelist(marker).generic_visit(tree) new_tree = ASTWhitelist(marker).generic_visit(tree)
return new_tree return new_tree
......
...@@ -14,6 +14,7 @@ the appropriate options to ``use_setuptools()``. ...@@ -14,6 +14,7 @@ the appropriate options to ``use_setuptools()``.
This file can also be run as a script to install or upgrade setuptools. This file can also be run as a script to install or upgrade setuptools.
""" """
import os import os
import shutil
import sys import sys
import time import time
import fnmatch import fnmatch
...@@ -48,7 +49,7 @@ except ImportError: ...@@ -48,7 +49,7 @@ except ImportError:
args = [quote(arg) for arg in args] args = [quote(arg) for arg in args]
return os.spawnl(os.P_WAIT, sys.executable, *args) == 0 return os.spawnl(os.P_WAIT, sys.executable, *args) == 0
DEFAULT_VERSION = "0.6.29" DEFAULT_VERSION = "0.6.46"
DEFAULT_URL = "http://pypi.python.org/packages/source/d/distribute/" DEFAULT_URL = "http://pypi.python.org/packages/source/d/distribute/"
SETUPTOOLS_FAKED_VERSION = "0.6c11" SETUPTOOLS_FAKED_VERSION = "0.6c11"
...@@ -86,8 +87,11 @@ def _install(tarball, install_args=()): ...@@ -86,8 +87,11 @@ def _install(tarball, install_args=()):
if not _python_cmd('setup.py', 'install', *install_args): if not _python_cmd('setup.py', 'install', *install_args):
log.warn('Something went wrong during the installation.') log.warn('Something went wrong during the installation.')
log.warn('See the error message above.') log.warn('See the error message above.')
# exitcode will be 2
return 2
finally: finally:
os.chdir(old_wd) os.chdir(old_wd)
shutil.rmtree(tmpdir)
def _build_egg(egg, tarball, to_dir): def _build_egg(egg, tarball, to_dir):
...@@ -112,6 +116,7 @@ def _build_egg(egg, tarball, to_dir): ...@@ -112,6 +116,7 @@ def _build_egg(egg, tarball, to_dir):
finally: finally:
os.chdir(old_wd) os.chdir(old_wd)
shutil.rmtree(tmpdir)
# returning the result # returning the result
log.warn(egg) log.warn(egg)
if not os.path.exists(egg): if not os.path.exists(egg):
...@@ -139,6 +144,16 @@ def use_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL, ...@@ -139,6 +144,16 @@ def use_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL,
try: try:
try: try:
import pkg_resources import pkg_resources
# Setuptools 0.7b and later is a suitable (and preferable)
# substitute for any Distribute version.
try:
pkg_resources.require("setuptools>=0.7b")
return
except (pkg_resources.DistributionNotFound,
pkg_resources.VersionConflict):
pass
if not hasattr(pkg_resources, '_distribute'): if not hasattr(pkg_resources, '_distribute'):
if not no_fake: if not no_fake:
_fake_setuptools() _fake_setuptools()
...@@ -234,7 +249,9 @@ def _no_sandbox(function): ...@@ -234,7 +249,9 @@ def _no_sandbox(function):
def _patch_file(path, content): def _patch_file(path, content):
"""Will backup the file then patch it""" """Will backup the file then patch it"""
existing_content = open(path).read() f = open(path)
existing_content = f.read()
f.close()
if existing_content == content: if existing_content == content:
# already patched # already patched
log.warn('Already patched.') log.warn('Already patched.')
...@@ -252,7 +269,10 @@ _patch_file = _no_sandbox(_patch_file) ...@@ -252,7 +269,10 @@ _patch_file = _no_sandbox(_patch_file)
def _same_content(path, content): def _same_content(path, content):
return open(path).read() == content f = open(path)
existing_content = f.read()
f.close()
return existing_content == content
def _rename_path(path): def _rename_path(path):
...@@ -443,8 +463,9 @@ def _relaunch(): ...@@ -443,8 +463,9 @@ def _relaunch():
log.warn('Relaunching...') log.warn('Relaunching...')
# we have to relaunch the process # we have to relaunch the process
# pip marker to avoid a relaunch bug # pip marker to avoid a relaunch bug
_cmd = ['-c', 'install', '--single-version-externally-managed'] _cmd1 = ['-c', 'install', '--single-version-externally-managed']
if sys.argv[:3] == _cmd: _cmd2 = ['-c', 'install', '--record']
if sys.argv[:3] == _cmd1 or sys.argv[:3] == _cmd2:
sys.argv[0] = 'setup.py' sys.argv[0] = 'setup.py'
args = [sys.executable] + sys.argv args = [sys.executable] + sys.argv
sys.exit(subprocess.call(args)) sys.exit(subprocess.call(args))
...@@ -529,7 +550,7 @@ def main(version=DEFAULT_VERSION): ...@@ -529,7 +550,7 @@ def main(version=DEFAULT_VERSION):
"""Install or upgrade setuptools and EasyInstall""" """Install or upgrade setuptools and EasyInstall"""
options = _parse_args() options = _parse_args()
tarball = download_setuptools(download_base=options.download_base) tarball = download_setuptools(download_base=options.download_base)
_install(tarball, _build_install_args(options)) return _install(tarball, _build_install_args(options))
if __name__ == '__main__': if __name__ == '__main__':
main() sys.exit(main())
...@@ -48,9 +48,9 @@ copyright = u'2009-2011, The fellowship of the packaging' ...@@ -48,9 +48,9 @@ copyright = u'2009-2011, The fellowship of the packaging'
# built documents. # built documents.
# #
# The short X.Y version. # The short X.Y version.
version = '0.6.29' version = '0.6.46'
# The full version, including alpha/beta/rc tags. # The full version, including alpha/beta/rc tags.
release = '0.6.29' release = '0.6.46'
# The language for content autogenerated by Sphinx. Refer to documentation # The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages. # for a list of supported languages.
......
...@@ -187,10 +187,11 @@ than ``2.4.1`` (which has a higher release number). ...@@ -187,10 +187,11 @@ than ``2.4.1`` (which has a higher release number).
A pre-release tag is a series of letters that are alphabetically before A pre-release tag is a series of letters that are alphabetically before
"final". Some examples of prerelease tags would include ``alpha``, ``beta``, "final". Some examples of prerelease tags would include ``alpha``, ``beta``,
``a``, ``c``, ``dev``, and so on. You do not have to place a dot before ``a``, ``c``, ``dev``, and so on. You do not have to place a dot or dash
the prerelease tag if it's immediately after a number, but it's okay to do before the prerelease tag if it's immediately after a number, but it's okay to
so if you prefer. Thus, ``2.4c1`` and ``2.4.c1`` both represent release do so if you prefer. Thus, ``2.4c1`` and ``2.4.c1`` and ``2.4-c1`` all
candidate 1 of version ``2.4``, and are treated as identical by setuptools. represent release candidate 1 of version ``2.4``, and are treated as identical
by setuptools.
In addition, there are three special prerelease tags that are treated as if In addition, there are three special prerelease tags that are treated as if
they were the letter ``c``: ``pre``, ``preview``, and ``rc``. So, version they were the letter ``c``: ``pre``, ``preview``, and ``rc``. So, version
...@@ -216,13 +217,6 @@ a post-release tag, so this version is *newer* than ``0.6a9.dev``. ...@@ -216,13 +217,6 @@ a post-release tag, so this version is *newer* than ``0.6a9.dev``.
For the most part, setuptools' interpretation of version numbers is intuitive, For the most part, setuptools' interpretation of version numbers is intuitive,
but here are a few tips that will keep you out of trouble in the corner cases: but here are a few tips that will keep you out of trouble in the corner cases:
* Don't use ``-`` or any other character than ``.`` as a separator, unless you
really want a post-release. Remember that ``2.1-rc2`` means you've
*already* released ``2.1``, whereas ``2.1rc2`` and ``2.1.c2`` are candidates
you're putting out *before* ``2.1``. If you accidentally distribute copies
of a post-release that you meant to be a pre-release, the only safe fix is to
bump your main release number (e.g. to ``2.1.1``) and re-release the project.
* Don't stick adjoining pre-release tags together without a dot or number * Don't stick adjoining pre-release tags together without a dot or number
between them. Version ``1.9adev`` is the ``adev`` prerelease of ``1.9``, between them. Version ``1.9adev`` is the ``adev`` prerelease of ``1.9``,
*not* a development pre-release of ``1.9a``. Use ``.dev`` instead, as in *not* a development pre-release of ``1.9a``. Use ``.dev`` instead, as in
...@@ -239,7 +233,7 @@ but here are a few tips that will keep you out of trouble in the corner cases: ...@@ -239,7 +233,7 @@ but here are a few tips that will keep you out of trouble in the corner cases:
>>> parse_version('1.9.a.dev') == parse_version('1.9a0dev') >>> parse_version('1.9.a.dev') == parse_version('1.9a0dev')
True True
>>> parse_version('2.1-rc2') < parse_version('2.1') >>> parse_version('2.1-rc2') < parse_version('2.1')
False True
>>> parse_version('0.6a9dev-r41475') < parse_version('0.6a9') >>> parse_version('0.6a9dev-r41475') < parse_version('0.6a9')
True True
...@@ -616,14 +610,20 @@ Dependencies that aren't in PyPI ...@@ -616,14 +610,20 @@ Dependencies that aren't in PyPI
If your project depends on packages that aren't registered in PyPI, you may If your project depends on packages that aren't registered in PyPI, you may
still be able to depend on them, as long as they are available for download still be able to depend on them, as long as they are available for download
as an egg, in the standard distutils ``sdist`` format, or as a single ``.py`` as:
file. You just need to add some URLs to the ``dependency_links`` argument to
- an egg, in the standard distutils ``sdist`` format,
- a single ``.py`` file, or
- a VCS repository (Subversion, Mercurial, or Git).
You just need to add some URLs to the ``dependency_links`` argument to
``setup()``. ``setup()``.
The URLs must be either: The URLs must be either:
1. direct download URLs, or 1. direct download URLs,
2. the URLs of web pages that contain direct download links 2. the URLs of web pages that contain direct download links, or
3. the repository's URL
In general, it's better to link to web pages, because it is usually less In general, it's better to link to web pages, because it is usually less
complex to update a web page than to release a new version of your project. complex to update a web page than to release a new version of your project.
...@@ -637,6 +637,27 @@ by replacing them with underscores.) EasyInstall will recognize this suffix ...@@ -637,6 +637,27 @@ by replacing them with underscores.) EasyInstall will recognize this suffix
and automatically create a trivial ``setup.py`` to wrap the single ``.py`` file and automatically create a trivial ``setup.py`` to wrap the single ``.py`` file
as an egg. as an egg.
In the case of a VCS checkout, you should also append ``#egg=project-version``
in order to identify for what package that checkout should be used. You can
append ``@REV`` to the URL's path (before the fragment) to specify a revision.
Additionally, you can also force the VCS being used by prepending the URL with
a certain prefix. Currently available are:
- ``svn+URL`` for Subversion,
- ``git+URL`` for Git, and
- ``hg+URL`` for Mercurial
A more complete example would be:
``vcs+proto://host/path@revision#egg=project-version``
Be careful with the version. It should match the one inside the project files.
If you want do disregard the version, you have to omit it both in the
``requires`` and in the URL's fragment.
This will do a checkout (or a clone, in Git and Mercurial parlance) to a
temporary folder and run ``setup.py bdist_egg``.
The ``dependency_links`` option takes the form of a list of URL strings. For The ``dependency_links`` option takes the form of a list of URL strings. For
example, the below will cause EasyInstall to search the specified page for example, the below will cause EasyInstall to search the specified page for
eggs or source distributions, if the package's dependencies aren't already eggs or source distributions, if the package's dependencies aren't already
...@@ -2423,7 +2444,12 @@ command:: ...@@ -2423,7 +2444,12 @@ command::
python setup.py upload_docs --upload-dir=docs/build/html python setup.py upload_docs --upload-dir=docs/build/html
As with any other ``setuptools`` based command, you can define useful If no ``--upload-dir`` is given, ``upload_docs`` will attempt to run the
``build_sphinx`` command to generate uploadable documentation.
For the command to become available, `Sphinx <http://sphinx.pocoo.org/>`_
must be installed in the same environment as distribute.
As with other ``setuptools``-based commands, you can define useful
defaults in the ``setup.cfg`` of your Python project, e.g.: defaults in the ``setup.cfg`` of your Python project, e.g.:
.. code-block:: ini .. code-block:: ini
......
...@@ -14,6 +14,14 @@ ...@@ -14,6 +14,14 @@
gcc -DGUI=0 -mno-cygwin -O -s -o setuptools/cli.exe launcher.c gcc -DGUI=0 -mno-cygwin -O -s -o setuptools/cli.exe launcher.c
gcc -DGUI=1 -mwindows -mno-cygwin -O -s -o setuptools/gui.exe launcher.c gcc -DGUI=1 -mwindows -mno-cygwin -O -s -o setuptools/gui.exe launcher.c
To build for Windows RT, install both Visual Studio Express for Windows 8
and for Windows Desktop (both freeware), create "win32" application using
"Windows Desktop" version, create new "ARM" target via
"Configuration Manager" menu and modify ".vcxproj" file by adding
"<WindowsSDKDesktopARMSupport>true</WindowsSDKDesktopARMSupport>" tag
as child of "PropertyGroup" tags that has "Debug|ARM" and "Release|ARM"
properties.
It links to msvcrt.dll, but this shouldn't be a problem since it doesn't It links to msvcrt.dll, but this shouldn't be a problem since it doesn't
actually run Python in the same process. Note that using 'exec' instead actually run Python in the same process. Note that using 'exec' instead
of 'spawn' doesn't work, because on Windows this leads to the Python of 'spawn' doesn't work, because on Windows this leads to the Python
......
@echo off @echo off
REM VCVARSALL may be in Program Files or Program Files (x86) REM Use old Windows SDK 6.1 so created .exe will be compatible with
PATH=C:\Program Files\Microsoft Visual Studio 9.0\VC;%PATH% REM old Windows versions.
PATH=C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC;%PATH% REM Windows SDK 6.1 may be downloaded at:
REM http://www.microsoft.com/en-us/download/details.aspx?id=11310
set PATH_OLD=%PATH%
REM The SDK creates a false install of Visual Studio at one of these locations
set PATH=C:\Program Files\Microsoft Visual Studio 9.0\VC\bin;%PATH%
set PATH=C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\bin;%PATH%
REM set up the environment to compile to x86 REM set up the environment to compile to x86
call VCVARSALL x86 call VCVARS32
cl /D "GUI=0" /D "WIN32_LEAN_AND_MEAN" launcher.c /O2 /link /MACHINE:x86 /out:setuptools/cli-32.exe if "%ERRORLEVEL%"=="0" (
cl /D "GUI=1" /D "WIN32_LEAN_AND_MEAN" launcher.c /O2 /link /MACHINE:x86 /out:setuptools/gui-32.exe cl /D "GUI=0" /D "WIN32_LEAN_AND_MEAN" launcher.c /O2 /link /MACHINE:x86 /SUBSYSTEM:CONSOLE /out:setuptools/cli-32.exe
cl /D "GUI=1" /D "WIN32_LEAN_AND_MEAN" launcher.c /O2 /link /MACHINE:x86 /SUBSYSTEM:WINDOWS /out:setuptools/gui-32.exe
) else (
echo Windows SDK 6.1 not found to build Windows 32-bit version
)
REM buildout (and possibly other implementations) currently depend on
REM the 32-bit launcher scripts without the -32 in the filename, so copy them
REM there for now.
copy setuptools/cli-32.exe setuptools/cli.exe
copy setuptools/gui-32.exe setuptools/gui.exe
REM now for 64-bit REM now for 64-bit
call VCVARSALL x86_amd64 REM Use the x86_amd64 profile, which is the 32-bit cross compiler for amd64
cl /D "GUI=0" /D "WIN32_LEAN_AND_MEAN" launcher.c /O2 /link /MACHINE:x64 /out:setuptools/cli-64.exe call VCVARSx86_amd64
cl /D "GUI=1" /D "WIN32_LEAN_AND_MEAN" launcher.c /O2 /link /MACHINE:x64 /out:setuptools/gui-64.exe if "%ERRORLEVEL%"=="0" (
\ No newline at end of file cl /D "GUI=0" /D "WIN32_LEAN_AND_MEAN" launcher.c /O2 /link /MACHINE:x64 /SUBSYSTEM:CONSOLE /out:setuptools/cli-64.exe
cl /D "GUI=1" /D "WIN32_LEAN_AND_MEAN" launcher.c /O2 /link /MACHINE:x64 /SUBSYSTEM:WINDOWS /out:setuptools/gui-64.exe
) else (
echo Windows SDK 6.1 not found to build Windows 64-bit version
)
REM Windows RT ARM build requires both freeware
REM "Visual Studio Express 2012 for Windows 8" and
REM "Visual Studio Express 2012 for Windows Desktop" to be installed from
REM http://www.microsoft.com/visualstudio/eng/products/visual-studio-express-products
set PATH=%PATH_OLD%
set PATH=C:\Program Files\Microsoft Visual Studio 11.0\VC;%PATH%
set PATH=C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC;%PATH%
call VCVARSALL x86_arm >nul 2>&1
if "%ERRORLEVEL%"=="0" (
echo Building Windows RT Version ...
cl /D "GUI=0" /D "WIN32_LEAN_AND_MEAN" /D _ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE launcher.c /O2 /link /MACHINE:ARM /SUBSYSTEM:CONSOLE /out:setuptools/cli-arm-32.exe
cl /D "GUI=1" /D "WIN32_LEAN_AND_MEAN" /D _ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE launcher.c /O2 /link /MACHINE:ARM /SUBSYSTEM:WINDOWS /out:setuptools/gui-arm-32.exe
) else (
echo Visual Studio ^(Express^) 2012 not found to build Windows RT Version
)
set PATH=%PATH_OLD%
This diff is collapsed.
...@@ -14,13 +14,17 @@ import sys ...@@ -14,13 +14,17 @@ import sys
import urllib2 import urllib2
import getpass import getpass
import collections import collections
import itertools
import re
try: try:
import keyring import keyring
except Exception: except Exception:
pass pass
VERSION = '0.6.29' VERSION = '0.6.46'
PACKAGE_INDEX = 'https://pypi.python.org/pypi'
PACKAGE_INDEX = 'https://pypi.python.org/pypi'
def get_next_version(): def get_next_version():
digits = map(int, VERSION.split('.')) digits = map(int, VERSION.split('.'))
...@@ -50,7 +54,7 @@ def get_mercurial_creds(system='https://bitbucket.org', username=None): ...@@ -50,7 +54,7 @@ def get_mercurial_creds(system='https://bitbucket.org', username=None):
# todo: consider getting this from .hgrc # todo: consider getting this from .hgrc
username = username or getpass.getuser() username = username or getpass.getuser()
keyring_username = '@@'.join((username, system)) keyring_username = '@@'.join((username, system))
system = '@'.join((keyring_username, 'Mercurial')) system = 'Mercurial'
password = ( password = (
keyring.get_password(system, keyring_username) keyring.get_password(system, keyring_username)
if 'keyring' in globals() if 'keyring' in globals()
...@@ -65,7 +69,7 @@ def add_milestone_and_version(version=NEXT_VERSION): ...@@ -65,7 +69,7 @@ def add_milestone_and_version(version=NEXT_VERSION):
auth = 'Basic ' + ':'.join(get_mercurial_creds()).encode('base64').strip() auth = 'Basic ' + ':'.join(get_mercurial_creds()).encode('base64').strip()
headers = { headers = {
'Authorization': auth, 'Authorization': auth,
} }
base = 'https://api.bitbucket.org' base = 'https://api.bitbucket.org'
for type in 'milestones', 'versions': for type in 'milestones', 'versions':
url = (base + '/1.0/repositories/{repo}/issues/{type}' url = (base + '/1.0/repositories/{repo}/issues/{type}'
...@@ -99,7 +103,7 @@ def do_release(): ...@@ -99,7 +103,7 @@ def do_release():
print("Please do that") print("Please do that")
raise SystemExit(1) raise SystemExit(1)
print("Travis-CI tests: http://travis-ci.org/#!/jaraco/distribute") print("Travis-CI tests: http://travis-ci.org/#!/jaraco/setuptools")
res = raw_input('Have you or has someone verified that the tests ' res = raw_input('Have you or has someone verified that the tests '
'pass on this revision? ') 'pass on this revision? ')
if not res.lower().startswith('y'): if not res.lower().startswith('y'):
...@@ -110,13 +114,20 @@ def do_release(): ...@@ -110,13 +114,20 @@ def do_release():
subprocess.check_call(['hg', 'update', VERSION]) subprocess.check_call(['hg', 'update', VERSION])
linkify('CHANGES.txt', 'CHANGES (links).txt')
has_docs = build_docs() has_docs = build_docs()
if os.path.isdir('./dist'): if os.path.isdir('./dist'):
shutil.rmtree('./dist') shutil.rmtree('./dist')
cmd = [sys.executable, 'setup.py', '-q', 'egg_info', '-RD', '-b', '', cmd = [
'sdist', 'register', 'upload'] sys.executable, 'setup.py', '-q',
'egg_info', '-RD', '-b', '',
'sdist',
'register', '-r', PACKAGE_INDEX,
'upload', '-r', PACKAGE_INDEX,
]
if has_docs: if has_docs:
cmd.append('upload_docs') cmd.extend(['upload_docs', '-r', PACKAGE_INDEX])
subprocess.check_call(cmd) subprocess.check_call(cmd)
upload_bootstrap_script() upload_bootstrap_script()
...@@ -148,14 +159,14 @@ def build_docs(): ...@@ -148,14 +159,14 @@ def build_docs():
return return
if os.path.isdir('docs/build'): if os.path.isdir('docs/build'):
shutil.rmtree('docs/build') shutil.rmtree('docs/build')
subprocess.check_call([ cmd = [
'sphinx-build', 'sphinx-build',
'-b', 'html', '-b', 'html',
'-d', 'build/doctrees', '-d', 'build/doctrees',
'.', '.',
'build/html', 'build/html',
], ]
cwd='docs') subprocess.check_call(cmd, cwd='docs')
return True return True
def upload_bootstrap_script(): def upload_bootstrap_script():
...@@ -166,5 +177,59 @@ def upload_bootstrap_script(): ...@@ -166,5 +177,59 @@ def upload_bootstrap_script():
except: except:
print("Unable to upload bootstrap script. Ask Tarek to do it.") print("Unable to upload bootstrap script. Ask Tarek to do it.")
def linkify(source, dest):
with open(source) as source:
out = _linkified_text(source.read())
with open(dest, 'w') as dest:
dest.write(out)
def _linkified(rst_path):
"return contents of reStructureText file with linked issue references"
rst_file = open(rst_path)
rst_content = rst_file.read()
rst_file.close()
return _linkified_text(rst_content)
def _linkified_text(rst_content):
# first identify any existing HREFs so they're not changed
HREF_pattern = re.compile('`.*?`_', re.MULTILINE | re.DOTALL)
# split on the HREF pattern, returning the parts to be linkified
plain_text_parts = HREF_pattern.split(rst_content)
anchors = []
linkified_parts = [_linkified_part(part, anchors)
for part in plain_text_parts]
pairs = itertools.izip_longest(
linkified_parts,
HREF_pattern.findall(rst_content),
fillvalue='',
)
rst_content = ''.join(flatten(pairs))
anchors = sorted(anchors)
bitroot = 'http://bitbucket.org/tarek/distribute'
rst_content += "\n"
for x in anchors:
issue = re.findall(r'\d+', x)[0]
rst_content += '.. _`%s`: %s/issue/%s\n' % (x, bitroot, issue)
rst_content += "\n"
return rst_content
def flatten(listOfLists):
"Flatten one level of nesting"
return itertools.chain.from_iterable(listOfLists)
def _linkified_part(text, anchors):
"""
Linkify a part and collect any anchors generated
"""
revision = re.compile(r'\b(issue\s+#?\d+)\b', re.M | re.I)
anchors.extend(revision.findall(text)) # ['Issue #43', ...]
return revision.sub(r'`\1`_', text)
if __name__ == '__main__': if __name__ == '__main__':
do_release() do_release()
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
import sys import sys
import os import os
import textwrap import textwrap
import re
# Allow to run setup.py from another directory. # Allow to run setup.py from another directory.
os.chdir(os.path.dirname(os.path.abspath(__file__))) os.chdir(os.path.dirname(os.path.abspath(__file__)))
...@@ -15,8 +16,10 @@ if sys.version_info >= (3,) and do_2to3: ...@@ -15,8 +16,10 @@ if sys.version_info >= (3,) and do_2to3:
from distutils import dir_util, file_util, util, log from distutils import dir_util, file_util, util, log
log.set_verbosity(1) log.set_verbosity(1)
fl = FileList() fl = FileList()
for line in open("MANIFEST.in"): manifest_file = open("MANIFEST.in")
for line in manifest_file:
fl.process_template_line(line) fl.process_template_line(line)
manifest_file.close()
dir_util.create_tree(tmp_src, fl.files) dir_util.create_tree(tmp_src, fl.files)
outfiles_2to3 = [] outfiles_2to3 = []
dist_script = os.path.join("build", "src", "distribute_setup.py") dist_script = os.path.join("build", "src", "distribute_setup.py")
...@@ -39,10 +42,12 @@ from distutils.util import convert_path ...@@ -39,10 +42,12 @@ from distutils.util import convert_path
d = {} d = {}
init_path = convert_path('setuptools/command/__init__.py') init_path = convert_path('setuptools/command/__init__.py')
exec(open(init_path).read(), d) init_file = open(init_path)
exec(init_file.read(), d)
init_file.close()
SETUP_COMMANDS = d['__all__'] SETUP_COMMANDS = d['__all__']
VERSION = "0.6.29" VERSION = "0.6.46"
from setuptools import setup, find_packages from setuptools import setup, find_packages
from setuptools.command.build_py import build_py as _build_py from setuptools.command.build_py import build_py as _build_py
...@@ -82,10 +87,8 @@ class test(_test): ...@@ -82,10 +87,8 @@ class test(_test):
entry_points = os.path.join('distribute.egg-info', 'entry_points.txt') entry_points = os.path.join('distribute.egg-info', 'entry_points.txt')
if not os.path.exists(entry_points): if not os.path.exists(entry_points):
try: _test.run(self)
_test.run(self) return # even though _test.run will raise SystemExit
finally:
return
f = open(entry_points) f = open(entry_points)
...@@ -132,6 +135,16 @@ if _being_installed(): ...@@ -132,6 +135,16 @@ if _being_installed():
from distribute_setup import _before_install from distribute_setup import _before_install
_before_install() _before_install()
readme_file = open('README.txt')
# the release script adds hyperlinks to issues
if os.path.exists('CHANGES (links).txt'):
changes_file = open('CHANGES (links).txt')
else:
# but if the release script has not run, fall back to the source file
changes_file = open('CHANGES.txt')
long_description = readme_file.read() + changes_file.read()
readme_file.close()
changes_file.close()
dist = setup( dist = setup(
name="distribute", name="distribute",
...@@ -141,26 +154,24 @@ dist = setup( ...@@ -141,26 +154,24 @@ dist = setup(
author="The fellowship of the packaging", author="The fellowship of the packaging",
author_email="distutils-sig@python.org", author_email="distutils-sig@python.org",
license="PSF or ZPL", license="PSF or ZPL",
long_description = open('README.txt').read() + open('CHANGES.txt').read(), long_description = long_description,
keywords = "CPAN PyPI distutils eggs package management", keywords = "CPAN PyPI distutils eggs package management",
url = "http://packages.python.org/distribute", url = "http://packages.python.org/distribute",
test_suite = 'setuptools.tests', test_suite = 'setuptools.tests',
src_root = src_root, src_root = src_root,
packages = find_packages(), packages = find_packages(),
package_data = {'setuptools':['*.exe']}, package_data = {'setuptools':['*.exe', 'site-patch.py'], 'setuptools.command':['*.xml']},
py_modules = ['pkg_resources', 'easy_install', 'site'], py_modules = ['pkg_resources', 'easy_install'],
zip_safe = (sys.version>="2.5"), # <2.5 needs unzipped for -m to work zip_safe = (sys.version>="2.5"), # <2.5 needs unzipped for -m to work
cmdclass = {'test': test}, cmdclass = {'test': test},
entry_points = { entry_points = {
"distutils.commands" : [ "distutils.commands" : [
"%(cmd)s = setuptools.command.%(cmd)s:%(cmd)s" % locals() "%(cmd)s = setuptools.command.%(cmd)s:%(cmd)s" % locals()
for cmd in SETUP_COMMANDS for cmd in SETUP_COMMANDS
], ],
"distutils.setup_keywords": [ "distutils.setup_keywords": [
"eager_resources = setuptools.dist:assert_string_list", "eager_resources = setuptools.dist:assert_string_list",
"namespace_packages = setuptools.dist:check_nsp", "namespace_packages = setuptools.dist:check_nsp",
...@@ -181,7 +192,6 @@ dist = setup( ...@@ -181,7 +192,6 @@ dist = setup(
"use_2to3_fixers = setuptools.dist:assert_string_list", "use_2to3_fixers = setuptools.dist:assert_string_list",
"use_2to3_exclude_fixers = setuptools.dist:assert_string_list", "use_2to3_exclude_fixers = setuptools.dist:assert_string_list",
], ],
"egg_info.writers": [ "egg_info.writers": [
"PKG-INFO = setuptools.command.egg_info:write_pkg_info", "PKG-INFO = setuptools.command.egg_info:write_pkg_info",
"requires.txt = setuptools.command.egg_info:write_requirements", "requires.txt = setuptools.command.egg_info:write_requirements",
...@@ -192,7 +202,6 @@ dist = setup( ...@@ -192,7 +202,6 @@ dist = setup(
"depends.txt = setuptools.command.egg_info:warn_depends_obsolete", "depends.txt = setuptools.command.egg_info:warn_depends_obsolete",
"dependency_links.txt = setuptools.command.egg_info:overwrite_arg", "dependency_links.txt = setuptools.command.egg_info:overwrite_arg",
], ],
"console_scripts": console_scripts, "console_scripts": console_scripts,
"setuptools.file_finders": "setuptools.file_finders":
...@@ -200,7 +209,7 @@ dist = setup( ...@@ -200,7 +209,7 @@ dist = setup(
"setuptools.installation": "setuptools.installation":
['eggsecutable = setuptools.command.easy_install:bootstrap'], ['eggsecutable = setuptools.command.easy_install:bootstrap'],
}, },
classifiers = textwrap.dedent(""" classifiers = textwrap.dedent("""
......
...@@ -158,6 +158,9 @@ def unpack_zipfile(filename, extract_dir, progress_filter=default_filter): ...@@ -158,6 +158,9 @@ def unpack_zipfile(filename, extract_dir, progress_filter=default_filter):
finally: finally:
f.close() f.close()
del data del data
unix_attributes = info.external_attr >> 16
if unix_attributes:
os.chmod(target, unix_attributes)
finally: finally:
z.close() z.close()
......
No preview for this file type
No preview for this file type
No preview for this file type
...@@ -132,7 +132,9 @@ class develop(easy_install): ...@@ -132,7 +132,9 @@ class develop(easy_install):
def uninstall_link(self): def uninstall_link(self):
if os.path.exists(self.egg_link): if os.path.exists(self.egg_link):
log.info("Removing %s (link to %s)", self.egg_link, self.egg_base) log.info("Removing %s (link to %s)", self.egg_link, self.egg_base)
contents = [line.rstrip() for line in open(self.egg_link)] egg_link_file = open(self.egg_link)
contents = [line.rstrip() for line in egg_link_file]
egg_link_file.close()
if contents not in ([self.egg_path], [self.egg_path, self.setup_path]): if contents not in ([self.egg_path], [self.egg_path, self.setup_path]):
log.warn("Link points to %s: uninstall aborted", contents) log.warn("Link points to %s: uninstall aborted", contents)
return return
......
...@@ -19,7 +19,9 @@ import zipfile ...@@ -19,7 +19,9 @@ import zipfile
import re import re
import stat import stat
import random import random
import platform
from glob import glob from glob import glob
import pkg_resources
from setuptools import Command, _dont_write_bytecode from setuptools import Command, _dont_write_bytecode
from setuptools.sandbox import run_setup from setuptools.sandbox import run_setup
from distutils import log, dir_util from distutils import log, dir_util
...@@ -493,7 +495,7 @@ Please make the appropriate changes for your system and try again. ...@@ -493,7 +495,7 @@ Please make the appropriate changes for your system and try again.
self.cant_write_to_target() self.cant_write_to_target()
else: else:
try: try:
f.write("import os;open(%r,'w').write('OK')\n" % (ok_file,)) f.write("import os; f = open(%r, 'w'); f.write('OK'); f.close()\n" % (ok_file,))
f.close(); f=None f.close(); f=None
executable = sys.executable executable = sys.executable
if os.name=='nt': if os.name=='nt':
...@@ -524,6 +526,10 @@ Please make the appropriate changes for your system and try again. ...@@ -524,6 +526,10 @@ Please make the appropriate changes for your system and try again.
"""Write all the scripts for `dist`, unless scripts are excluded""" """Write all the scripts for `dist`, unless scripts are excluded"""
if not self.exclude_scripts and dist.metadata_isdir('scripts'): if not self.exclude_scripts and dist.metadata_isdir('scripts'):
for script_name in dist.metadata_listdir('scripts'): for script_name in dist.metadata_listdir('scripts'):
if dist.metadata_isdir('scripts/' + script_name):
# The "script" is a directory, likely a Python 3
# __pycache__ directory, so skip it.
continue
self.install_script( self.install_script(
dist, script_name, dist, script_name,
dist.get_metadata('scripts/'+script_name) dist.get_metadata('scripts/'+script_name)
...@@ -1276,7 +1282,7 @@ Please make the appropriate changes for your system and try again.""" % ( ...@@ -1276,7 +1282,7 @@ Please make the appropriate changes for your system and try again.""" % (
return # already did it, or don't need to return # already did it, or don't need to
sitepy = os.path.join(self.install_dir, "site.py") sitepy = os.path.join(self.install_dir, "site.py")
source = resource_string(Requirement.parse("distribute"), "site.py") source = resource_string("setuptools", "site-patch.py")
current = "" current = ""
if os.path.exists(sitepy): if os.path.exists(sitepy):
...@@ -1529,7 +1535,10 @@ def get_exe_prefixes(exe_filename): ...@@ -1529,7 +1535,10 @@ def get_exe_prefixes(exe_filename):
if name.endswith('-nspkg.pth'): if name.endswith('-nspkg.pth'):
continue continue
if parts[0].upper() in ('PURELIB','PLATLIB'): if parts[0].upper() in ('PURELIB','PLATLIB'):
for pth in yield_lines(z.read(name)): contents = z.read(name)
if sys.version_info >= (3,):
contents = contents.decode()
for pth in yield_lines(contents):
pth = pth.strip().replace('\\','/') pth = pth.strip().replace('\\','/')
if not pth.startswith('import'): if not pth.startswith('import'):
prefixes.append((('%s/%s/' % (parts[0],pth)), '')) prefixes.append((('%s/%s/' % (parts[0],pth)), ''))
...@@ -1794,6 +1803,11 @@ def chmod(path, mode): ...@@ -1794,6 +1803,11 @@ def chmod(path, mode):
def fix_jython_executable(executable, options): def fix_jython_executable(executable, options):
if sys.platform.startswith('java') and is_sh(executable): if sys.platform.startswith('java') and is_sh(executable):
# Workaround for Jython is not needed on Linux systems.
import java
if java.lang.System.getProperty("os.name") == "Linux":
return executable
# Workaround Jython's sys.executable being a .sh (an invalid # Workaround Jython's sys.executable being a .sh (an invalid
# shebang line interpreter) # shebang line interpreter)
if options: if options:
...@@ -1828,31 +1842,61 @@ def get_script_args(dist, executable=sys_executable, wininst=False): ...@@ -1828,31 +1842,61 @@ def get_script_args(dist, executable=sys_executable, wininst=False):
if sys.platform=='win32' or wininst: if sys.platform=='win32' or wininst:
# On Windows/wininst, add a .py extension and an .exe launcher # On Windows/wininst, add a .py extension and an .exe launcher
if group=='gui_scripts': if group=='gui_scripts':
ext, launcher = '-script.pyw', 'gui.exe' launcher_type = 'gui'
ext = '-script.pyw'
old = ['.pyw'] old = ['.pyw']
new_header = re.sub('(?i)python.exe','pythonw.exe',header) new_header = re.sub('(?i)python.exe','pythonw.exe',header)
else: else:
ext, launcher = '-script.py', 'cli.exe' launcher_type = 'cli'
ext = '-script.py'
old = ['.py','.pyc','.pyo'] old = ['.py','.pyc','.pyo']
new_header = re.sub('(?i)pythonw.exe','python.exe',header) new_header = re.sub('(?i)pythonw.exe','python.exe',header)
if is_64bit():
launcher = launcher.replace(".", "-64.")
else:
launcher = launcher.replace(".", "-32.")
if os.path.exists(new_header[2:-1]) or sys.platform!='win32': if os.path.exists(new_header[2:-1]) or sys.platform!='win32':
hdr = new_header hdr = new_header
else: else:
hdr = header hdr = header
yield (name+ext, hdr+script_text, 't', [name+x for x in old]) yield (name+ext, hdr+script_text, 't', [name+x for x in old])
yield ( yield (
name+'.exe', resource_string('setuptools', launcher), name+'.exe', get_win_launcher(launcher_type),
'b' # write in binary mode 'b' # write in binary mode
) )
if not is_64bit():
# install a manifest for the launcher to prevent Windows
# from detecting it as an installer (which it will for
# launchers like easy_install.exe). Consider only
# adding a manifest for launchers detected as installers.
# See Distribute #143 for details.
m_name = name + '.exe.manifest'
yield (m_name, load_launcher_manifest(name), 't')
else: else:
# On other platforms, we assume the right thing to do is to # On other platforms, we assume the right thing to do is to
# just write the stub with no extension. # just write the stub with no extension.
yield (name, header+script_text) yield (name, header+script_text)
def get_win_launcher(type):
"""
Load the Windows launcher (executable) suitable for launching a script.
`type` should be either 'cli' or 'gui'
Returns the executable as a byte string.
"""
launcher_fn = '%s.exe' % type
if platform.machine().lower()=='arm':
launcher_fn = launcher_fn.replace(".", "-arm.")
if is_64bit():
launcher_fn = launcher_fn.replace(".", "-64.")
else:
launcher_fn = launcher_fn.replace(".", "-32.")
return resource_string('setuptools', launcher_fn)
def load_launcher_manifest(name):
manifest = pkg_resources.resource_string(__name__, 'launcher manifest.xml')
if sys.version_info[0] < 3:
return manifest % vars()
else:
return manifest.decode('utf-8') % vars()
def rmtree(path, ignore_errors=False, onerror=auto_chmod): def rmtree(path, ignore_errors=False, onerror=auto_chmod):
"""Recursively delete a directory tree. """Recursively delete a directory tree.
......
...@@ -10,7 +10,7 @@ from distutils import log ...@@ -10,7 +10,7 @@ from distutils import log
from setuptools.command.sdist import sdist from setuptools.command.sdist import sdist
from setuptools.compat import basestring from setuptools.compat import basestring
from distutils.util import convert_path from distutils.util import convert_path
from distutils.filelist import FileList from distutils.filelist import FileList as _FileList
from pkg_resources import parse_requirements, safe_name, parse_version, \ from pkg_resources import parse_requirements, safe_name, parse_version, \
safe_version, yield_lines, EntryPoint, iter_entry_points, to_filename safe_version, yield_lines, EntryPoint, iter_entry_points, to_filename
from setuptools.command.sdist import walk_revctrl from setuptools.command.sdist import walk_revctrl
...@@ -275,35 +275,34 @@ class egg_info(Command): ...@@ -275,35 +275,34 @@ class egg_info(Command):
self.broken_egg_info = self.egg_info self.broken_egg_info = self.egg_info
self.egg_info = bei # make it work for now self.egg_info = bei # make it work for now
class FileList(FileList): class FileList(_FileList):
"""File list that accepts only existing, platform-independent paths""" """File list that accepts only existing, platform-independent paths"""
def append(self, item): def append(self, item):
if item.endswith('\r'): # Fix older sdists built on Windows if item.endswith('\r'): # Fix older sdists built on Windows
item = item[:-1] item = item[:-1]
path = convert_path(item) path = convert_path(item)
if os.path.exists(path):
self.files.append(path)
if sys.version_info >= (3,):
try:
if os.path.exists(path) or os.path.exists(path.encode('utf-8')):
self.files.append(path)
except UnicodeEncodeError:
# Accept UTF-8 filenames even if LANG=C
if os.path.exists(path.encode('utf-8')):
self.files.append(path)
else:
log.warn("'%s' not %s encodable -- skipping", path,
sys.getfilesystemencoding())
else:
if os.path.exists(path):
self.files.append(path)
def compose(path):
# Apple's HFS Plus returns decomposed UTF-8. Since just about
# everyone else chokes on it, we must make sure to return fully
# composed UTF-8 only.
if sys.getfilesystemencoding().lower() == 'utf-8':
from unicodedata import normalize
if sys.version_info >= (3,):
path = normalize('NFC', path)
else:
path = normalize('NFC', path.decode('utf-8')).encode('utf-8')
return path
class manifest_maker(sdist): class manifest_maker(sdist):
...@@ -330,7 +329,6 @@ class manifest_maker(sdist): ...@@ -330,7 +329,6 @@ class manifest_maker(sdist):
self.prune_file_list() self.prune_file_list()
self.filelist.sort() self.filelist.sort()
self.filelist.remove_duplicates() self.filelist.remove_duplicates()
self.filelist.files = [compose(path) for path in self.filelist.files]
self.write_manifest() self.write_manifest()
def write_manifest (self): def write_manifest (self):
...@@ -338,6 +336,18 @@ class manifest_maker(sdist): ...@@ -338,6 +336,18 @@ class manifest_maker(sdist):
by 'add_defaults()' and 'read_template()') to the manifest file by 'add_defaults()' and 'read_template()') to the manifest file
named by 'self.manifest'. named by 'self.manifest'.
""" """
# The manifest must be UTF-8 encodable. See #303.
if sys.version_info >= (3,):
files = []
for file in self.filelist.files:
try:
file.encode("utf-8")
except UnicodeEncodeError:
log.warn("'%s' not UTF-8 encodable -- skipping" % file)
else:
files.append(file)
self.filelist.files = files
files = self.filelist.files files = self.filelist.files
if os.sep!='/': if os.sep!='/':
files = [f.replace(os.sep,'/') for f in files] files = [f.replace(os.sep,'/') for f in files]
......
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity version="1.0.0.0"
processorArchitecture="X86"
name="%(name)s"
type="win32"/>
<!-- Identify the application security requirements. -->
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="asInvoker" uiAccess="false"/>
</requestedPrivileges>
</security>
</trustInfo>
</assembly>
...@@ -282,8 +282,13 @@ class sdist(_sdist): ...@@ -282,8 +282,13 @@ class sdist(_sdist):
log.info("reading manifest file '%s'", self.manifest) log.info("reading manifest file '%s'", self.manifest)
manifest = open(self.manifest, 'rbU') manifest = open(self.manifest, 'rbU')
for line in manifest: for line in manifest:
# The manifest must contain UTF-8. See #303.
if sys.version_info >= (3,): if sys.version_info >= (3,):
line = line.decode('UTF-8') try:
line = line.decode('UTF-8')
except UnicodeDecodeError:
log.warn("%r not UTF-8 decodable -- skipping" % line)
continue
# ignore comments and blank lines # ignore comments and blank lines
line = line.strip() line = line.strip()
if line.startswith('#') or not line: if line.startswith('#') or not line:
......
...@@ -108,8 +108,9 @@ class upload(Command): ...@@ -108,8 +108,9 @@ class upload(Command):
data['comment'] = comment data['comment'] = comment
if self.sign: if self.sign:
data['gpg_signature'] = (os.path.basename(filename) + ".asc", asc_file = open(filename + ".asc")
open(filename+".asc").read()) data['gpg_signature'] = (os.path.basename(filename) + ".asc", asc_file.read())
asc_file.close()
# set up the authentication # set up the authentication
auth = "Basic " + base64.encodestring(self.username + ":" + self.password).strip() auth = "Basic " + base64.encodestring(self.username + ":" + self.password).strip()
......
...@@ -8,9 +8,12 @@ PyPI's packages.python.org). ...@@ -8,9 +8,12 @@ PyPI's packages.python.org).
import os import os
import socket import socket
import zipfile import zipfile
import base64
import tempfile import tempfile
import sys import sys
import shutil
from base64 import standard_b64encode
from pkg_resources import iter_entry_points
from distutils import log from distutils import log
from distutils.errors import DistutilsOptionError from distutils.errors import DistutilsOptionError
...@@ -24,18 +27,12 @@ from setuptools.compat import httplib, urlparse ...@@ -24,18 +27,12 @@ from setuptools.compat import httplib, urlparse
_IS_PYTHON3 = sys.version > '3' _IS_PYTHON3 = sys.version > '3'
try: # This is not just a replacement for byte literals
bytes # but works as a general purpose encoder
except NameError: def b(s, encoding='utf-8'):
bytes = str if isinstance(s, unicode):
return s.encode(encoding)
def b(str_or_bytes): return s
"""Return bytes by either encoding the argument as ASCII or simply return
the argument as-is."""
if not isinstance(str_or_bytes, bytes):
return str_or_bytes.encode('ascii')
else:
return str_or_bytes
class upload_docs(upload): class upload_docs(upload):
...@@ -51,43 +48,67 @@ class upload_docs(upload): ...@@ -51,43 +48,67 @@ class upload_docs(upload):
] ]
boolean_options = upload.boolean_options boolean_options = upload.boolean_options
def has_sphinx(self):
if self.upload_dir is None:
for ep in iter_entry_points('distutils.commands', 'build_sphinx'):
return True
sub_commands = [('build_sphinx', has_sphinx)]
def initialize_options(self): def initialize_options(self):
upload.initialize_options(self) upload.initialize_options(self)
self.upload_dir = None self.upload_dir = None
self.target_dir = None
def finalize_options(self): def finalize_options(self):
upload.finalize_options(self) upload.finalize_options(self)
if self.upload_dir is None: if self.upload_dir is None:
build = self.get_finalized_command('build') if self.has_sphinx():
self.upload_dir = os.path.join(build.build_base, 'docs') build_sphinx = self.get_finalized_command('build_sphinx')
self.mkpath(self.upload_dir) self.target_dir = build_sphinx.builder_target_dir
self.ensure_dirname('upload_dir') else:
self.announce('Using upload directory %s' % self.upload_dir) build = self.get_finalized_command('build')
self.target_dir = os.path.join(build.build_base, 'docs')
else:
self.ensure_dirname('upload_dir')
self.target_dir = self.upload_dir
self.announce('Using upload directory %s' % self.target_dir)
def create_zipfile(self): def create_zipfile(self, filename):
name = self.distribution.metadata.get_name() zip_file = zipfile.ZipFile(filename, "w")
tmp_dir = tempfile.mkdtemp() try:
tmp_file = os.path.join(tmp_dir, "%s.zip" % name) self.mkpath(self.target_dir) # just in case
zip_file = zipfile.ZipFile(tmp_file, "w") for root, dirs, files in os.walk(self.target_dir):
for root, dirs, files in os.walk(self.upload_dir): if root == self.target_dir and not files:
if root == self.upload_dir and not files: raise DistutilsOptionError(
raise DistutilsOptionError( "no files found in upload directory '%s'"
"no files found in upload directory '%s'" % self.target_dir)
% self.upload_dir) for name in files:
for name in files: full = os.path.join(root, name)
full = os.path.join(root, name) relative = root[len(self.target_dir):].lstrip(os.path.sep)
relative = root[len(self.upload_dir):].lstrip(os.path.sep) dest = os.path.join(relative, name)
dest = os.path.join(relative, name) zip_file.write(full, dest)
zip_file.write(full, dest) finally:
zip_file.close() zip_file.close()
return tmp_file
def run(self): def run(self):
zip_file = self.create_zipfile() # Run sub commands
self.upload_file(zip_file) for cmd_name in self.get_sub_commands():
self.run_command(cmd_name)
tmp_dir = tempfile.mkdtemp()
name = self.distribution.metadata.get_name()
zip_file = os.path.join(tmp_dir, "%s.zip" % name)
try:
self.create_zipfile(zip_file)
self.upload_file(zip_file)
finally:
shutil.rmtree(tmp_dir)
def upload_file(self, filename): def upload_file(self, filename):
content = open(filename, 'rb').read() f = open(filename, 'rb')
content = f.read()
f.close()
meta = self.distribution.metadata meta = self.distribution.metadata
data = { data = {
':action': 'doc_upload', ':action': 'doc_upload',
...@@ -95,36 +116,33 @@ class upload_docs(upload): ...@@ -95,36 +116,33 @@ class upload_docs(upload):
'content': (os.path.basename(filename), content), 'content': (os.path.basename(filename), content),
} }
# set up the authentication # set up the authentication
credentials = self.username + ':' + self.password credentials = b(self.username + ':' + self.password)
if _IS_PYTHON3: # base64 only works with bytes in Python 3. credentials = standard_b64encode(credentials)
encoded_creds = base64.encodebytes(credentials.encode('utf8')) if sys.version_info >= (3,):
auth = bytes("Basic ") credentials = credentials.decode('ascii')
else: auth = "Basic " + credentials
encoded_creds = base64.encodestring(credentials)
auth = "Basic "
auth += encoded_creds.strip()
# Build up the MIME payload for the POST data # Build up the MIME payload for the POST data
boundary = b('--------------GHSKFJDLGDS7543FJKLFHRE75642756743254') boundary = '--------------GHSKFJDLGDS7543FJKLFHRE75642756743254'
sep_boundary = b('\n--') + boundary sep_boundary = b('\n--') + b(boundary)
end_boundary = sep_boundary + b('--') end_boundary = sep_boundary + b('--')
body = [] body = []
for key, values in data.items(): for key, values in data.iteritems():
title = '\nContent-Disposition: form-data; name="%s"' % key
# handle multiple entries for the same name # handle multiple entries for the same name
if type(values) != type([]): if type(values) != type([]):
values = [values] values = [values]
for value in values: for value in values:
if type(value) is tuple: if type(value) is tuple:
fn = b(';filename="%s"' % value[0]) title += '; filename="%s"' % value[0]
value = value[1] value = value[1]
else: else:
fn = b("") value = b(value)
body.append(sep_boundary) body.append(sep_boundary)
body.append(b('\nContent-Disposition: form-data; name="%s"'%key)) body.append(b(title))
body.append(fn)
body.append(b("\n\n")) body.append(b("\n\n"))
body.append(b(value)) body.append(value)
if value and value[-1] == b('\r'): if value and value[-1:] == b('\r'):
body.append(b('\n')) # write an extra newline (lurve Macs) body.append(b('\n')) # write an extra newline (lurve Macs)
body.append(end_boundary) body.append(end_boundary)
body.append(b("\n")) body.append(b("\n"))
......
...@@ -660,6 +660,11 @@ class Distribution(_Distribution): ...@@ -660,6 +660,11 @@ class Distribution(_Distribution):
if not isinstance(sys.stdout, io.TextIOWrapper): if not isinstance(sys.stdout, io.TextIOWrapper):
return _Distribution.handle_display_options(self, option_order) return _Distribution.handle_display_options(self, option_order)
# Don't wrap stdout if utf-8 is already the encoding. Provides
# workaround for #334.
if sys.stdout.encoding.lower() in ('utf-8', 'utf8'):
return _Distribution.handle_display_options(self, option_order)
# Print metadata in UTF-8 no matter the platform # Print metadata in UTF-8 no matter the platform
encoding = sys.stdout.encoding encoding = sys.stdout.encoding
errors = sys.stdout.errors errors = sys.stdout.errors
......
No preview for this file type
No preview for this file type
No preview for this file type
"""PyPI and direct package downloading""" """PyPI and direct package downloading"""
import sys, os.path, re, shutil, random, socket import sys, os.path, re, shutil, random, socket
import itertools
import base64 import base64
from pkg_resources import * from pkg_resources import *
from distutils import log from distutils import log
...@@ -14,6 +15,8 @@ except ImportError: ...@@ -14,6 +15,8 @@ except ImportError:
from md5 import md5 from md5 import md5
from fnmatch import translate from fnmatch import translate
from setuptools.py24compat import wraps
EGG_FRAGMENT = re.compile(r'^egg=([-A-Za-z0-9_.]+)$') EGG_FRAGMENT = re.compile(r'^egg=([-A-Za-z0-9_.]+)$')
HREF = re.compile("""href\\s*=\\s*['"]?([^'"> ]+)""", re.I) HREF = re.compile("""href\\s*=\\s*['"]?([^'"> ]+)""", re.I)
# this is here to fix emacs' cruddy broken syntax highlighting # this is here to fix emacs' cruddy broken syntax highlighting
...@@ -137,9 +140,38 @@ def interpret_distro_name(location, basename, metadata, ...@@ -137,9 +140,38 @@ def interpret_distro_name(location, basename, metadata,
platform = platform platform = platform
) )
# From Python 2.7 docs
def unique_everseen(iterable, key=None):
"List unique elements, preserving order. Remember all elements ever seen."
# unique_everseen('AAAABBBCCDAABBB') --> A B C D
# unique_everseen('ABBCcAD', str.lower) --> A B C D
seen = set()
seen_add = seen.add
if key is None:
for element in itertools.ifilterfalse(seen.__contains__, iterable):
seen_add(element)
yield element
else:
for element in iterable:
k = key(element)
if k not in seen:
seen_add(k)
yield element
def unique_values(func):
"""
Wrap a function returning an iterable such that the resulting iterable
only ever yields unique items.
"""
@wraps(func)
def wrapper(*args, **kwargs):
return unique_everseen(func(*args, **kwargs))
return wrapper
REL = re.compile("""<([^>]*\srel\s*=\s*['"]?([^'">]+)[^>]*)>""", re.I) REL = re.compile("""<([^>]*\srel\s*=\s*['"]?([^'">]+)[^>]*)>""", re.I)
# this line is here to fix emacs' cruddy broken syntax highlighting # this line is here to fix emacs' cruddy broken syntax highlighting
@unique_values
def find_external_links(url, page): def find_external_links(url, page):
"""Find rel="homepage" and rel="download" links in `page`, yielding URLs""" """Find rel="homepage" and rel="download" links in `page`, yielding URLs"""
...@@ -157,6 +189,7 @@ def find_external_links(url, page): ...@@ -157,6 +189,7 @@ def find_external_links(url, page):
if match: if match:
yield urljoin(url, htmldecode(match.group(1))) yield urljoin(url, htmldecode(match.group(1)))
user_agent = "Python-urllib/%s distribute/%s" % ( user_agent = "Python-urllib/%s distribute/%s" % (
sys.version[:3], require('distribute')[0].version sys.version[:3], require('distribute')[0].version
) )
...@@ -666,6 +699,10 @@ class PackageIndex(Environment): ...@@ -666,6 +699,10 @@ class PackageIndex(Environment):
# #
if scheme=='svn' or scheme.startswith('svn+'): if scheme=='svn' or scheme.startswith('svn+'):
return self._download_svn(url, filename) return self._download_svn(url, filename)
elif scheme=='git' or scheme.startswith('git+'):
return self._download_git(url, filename)
elif scheme.startswith('hg+'):
return self._download_hg(url, filename)
elif scheme=='file': elif scheme=='file':
return url2pathname(urlparse.urlparse(url)[2]) return url2pathname(urlparse.urlparse(url)[2])
else: else:
...@@ -706,6 +743,55 @@ class PackageIndex(Environment): ...@@ -706,6 +743,55 @@ class PackageIndex(Environment):
os.system("svn checkout -q %s %s" % (url, filename)) os.system("svn checkout -q %s %s" % (url, filename))
return filename return filename
def _vcs_split_rev_from_url(self, url, pop_prefix=False):
scheme, netloc, path, query, frag = urlparse.urlsplit(url)
scheme = scheme.split('+', 1)[-1]
# Some fragment identification fails
path = path.split('#',1)[0]
rev = None
if '@' in path:
path, rev = path.rsplit('@', 1)
# Also, discard fragment
url = urlparse.urlunsplit((scheme, netloc, path, query, ''))
return url, rev
def _download_git(self, url, filename):
filename = filename.split('#',1)[0]
url, rev = self._vcs_split_rev_from_url(url, pop_prefix=True)
self.info("Doing git clone from %s to %s", url, filename)
os.system("git clone --quiet %s %s" % (url, filename))
if rev is not None:
self.info("Checking out %s", rev)
os.system("(cd %s && git checkout --quiet %s)" % (
filename,
rev,
))
return filename
def _download_hg(self, url, filename):
filename = filename.split('#',1)[0]
url, rev = self._vcs_split_rev_from_url(url, pop_prefix=True)
self.info("Doing hg clone from %s to %s", url, filename)
os.system("hg clone --quiet %s %s" % (url, filename))
if rev is not None:
self.info("Updating to %s", rev)
os.system("(cd %s && hg up -C -r %s >&-)" % (
filename,
rev,
))
return filename
def debug(self, msg, *args): def debug(self, msg, *args):
log.debug(msg, *args) log.debug(msg, *args)
...@@ -789,9 +875,8 @@ def open_with_auth(url): ...@@ -789,9 +875,8 @@ def open_with_auth(url):
# Double scheme does not raise on Mac OS X as revealed by a # Double scheme does not raise on Mac OS X as revealed by a
# failing test. We would expect "nonnumeric port". Refs #20. # failing test. We would expect "nonnumeric port". Refs #20.
if sys.platform == 'darwin': if netloc.endswith(':'):
if netloc.endswith(':'): raise httplib.InvalidURL("nonnumeric port: ''")
raise httplib.InvalidURL("nonnumeric port: ''")
if scheme in ('http', 'https'): if scheme in ('http', 'https'):
auth, host = splituser(netloc) auth, host = splituser(netloc)
......
"""
Forward-compatibility support for Python 2.4 and earlier
"""
# from jaraco.compat 1.2
try:
from functools import wraps
except ImportError:
def wraps(func):
"Just return the function unwrapped"
return lambda x: x
import os, sys, tempfile, operator, pkg_resources import os, sys, tempfile, operator, pkg_resources
_os = sys.modules[os.name] if os.name == "java":
import org.python.modules.posix.PosixModule as _os
else:
_os = sys.modules[os.name]
try: try:
_file = file _file = file
except NameError: except NameError:
......
...@@ -1968,7 +1968,9 @@ def testfile(filename, module_relative=True, name=None, package=None, ...@@ -1968,7 +1968,9 @@ def testfile(filename, module_relative=True, name=None, package=None,
runner = DocTestRunner(verbose=verbose, optionflags=optionflags) runner = DocTestRunner(verbose=verbose, optionflags=optionflags)
# Read the file, convert it to a test, and run it. # Read the file, convert it to a test, and run it.
s = open(filename).read() f = open(filename)
s = f.read()
f.close()
test = parser.get_doctest(s, globs, name, filename, 0) test = parser.get_doctest(s, globs, name, filename, 0)
runner.run(test) runner.run(test)
...@@ -2353,7 +2355,9 @@ def DocFileTest(path, module_relative=True, package=None, ...@@ -2353,7 +2355,9 @@ def DocFileTest(path, module_relative=True, package=None,
# Find the file and read it. # Find the file and read it.
name = os.path.basename(path) name = os.path.basename(path)
doc = open(path).read() f = open(path)
doc = f.read()
f.close()
# Convert it to a test, and wrap it in a DocFileCase. # Convert it to a test, and wrap it in a DocFileCase.
test = parser.get_doctest(doc, globs, name, path, 0) test = parser.get_doctest(doc, globs, name, path, 0)
......
...@@ -89,16 +89,16 @@ class TestDevelopTest(unittest.TestCase): ...@@ -89,16 +89,16 @@ class TestDevelopTest(unittest.TestCase):
self.assertEqual(content, ['easy-install.pth', 'foo.egg-link']) self.assertEqual(content, ['easy-install.pth', 'foo.egg-link'])
# Check that we are using the right code. # Check that we are using the right code.
f = open(os.path.join(site.USER_SITE, 'foo.egg-link'), 'rt') egg_link_file = open(os.path.join(site.USER_SITE, 'foo.egg-link'), 'rt')
try: try:
path = f.read().split()[0].strip() path = egg_link_file.read().split()[0].strip()
finally: finally:
f.close() egg_link_file.close()
f = open(os.path.join(path, 'foo', '__init__.py'), 'rt') init_file = open(os.path.join(path, 'foo', '__init__.py'), 'rt')
try: try:
init = f.read().strip() init = init_file.read().strip()
finally: finally:
f.close() init_file.close()
if sys.version < "3": if sys.version < "3":
self.assertEqual(init, 'print "foo"') self.assertEqual(init, 'print "foo"')
else: else:
......
...@@ -50,9 +50,9 @@ class TestDistInfo(unittest.TestCase): ...@@ -50,9 +50,9 @@ class TestDistInfo(unittest.TestCase):
versioned = os.path.join(self.tmpdir, versioned = os.path.join(self.tmpdir,
'VersionedDistribution-2.718.dist-info') 'VersionedDistribution-2.718.dist-info')
os.mkdir(versioned) os.mkdir(versioned)
f = open(os.path.join(versioned, 'METADATA'), 'w+') metadata_file = open(os.path.join(versioned, 'METADATA'), 'w+')
try: try:
f.write(DALS( metadata_file.write(DALS(
""" """
Metadata-Version: 1.2 Metadata-Version: 1.2
Name: VersionedDistribution Name: VersionedDistribution
...@@ -61,13 +61,13 @@ class TestDistInfo(unittest.TestCase): ...@@ -61,13 +61,13 @@ class TestDistInfo(unittest.TestCase):
Requires-Dist: quux (>=1.1); extra == 'baz' Requires-Dist: quux (>=1.1); extra == 'baz'
""")) """))
finally: finally:
f.close() metadata_file.close()
unversioned = os.path.join(self.tmpdir, unversioned = os.path.join(self.tmpdir,
'UnversionedDistribution.dist-info') 'UnversionedDistribution.dist-info')
os.mkdir(unversioned) os.mkdir(unversioned)
f = open(os.path.join(unversioned, 'METADATA'), 'w+') metadata_file = open(os.path.join(unversioned, 'METADATA'), 'w+')
try: try:
f.write(DALS( metadata_file.write(DALS(
""" """
Metadata-Version: 1.2 Metadata-Version: 1.2
Name: UnversionedDistribution Name: UnversionedDistribution
...@@ -77,7 +77,7 @@ class TestDistInfo(unittest.TestCase): ...@@ -77,7 +77,7 @@ class TestDistInfo(unittest.TestCase):
Requires-Dist: quux (>=1.1); extra == 'baz' Requires-Dist: quux (>=1.1); extra == 'baz'
""")) """))
finally: finally:
f.close() metadata_file.close()
def tearDown(self): def tearDown(self):
shutil.rmtree(self.tmpdir) shutil.rmtree(self.tmpdir)
...@@ -13,7 +13,7 @@ import tarfile ...@@ -13,7 +13,7 @@ import tarfile
import distutils.core import distutils.core
from setuptools.sandbox import run_setup, SandboxViolation from setuptools.sandbox import run_setup, SandboxViolation
from setuptools.command.easy_install import easy_install, get_script_args, main from setuptools.command.easy_install import easy_install, fix_jython_executable, get_script_args, main
from setuptools.command.easy_install import PthDistributions from setuptools.command.easy_install import PthDistributions
from setuptools.command import easy_install as easy_install_pkg from setuptools.command import easy_install as easy_install_pkg
from setuptools.dist import Distribution from setuptools.dist import Distribution
...@@ -51,7 +51,7 @@ if __name__ == '__main__': ...@@ -51,7 +51,7 @@ if __name__ == '__main__':
sys.exit( sys.exit(
load_entry_point('spec', 'console_scripts', 'name')() load_entry_point('spec', 'console_scripts', 'name')()
) )
""" % sys.executable """ % fix_jython_executable(sys.executable, "")
SETUP_PY = """\ SETUP_PY = """\
from setuptools import setup from setuptools import setup
......
...@@ -16,15 +16,15 @@ class TestMarkerlib(unittest.TestCase): ...@@ -16,15 +16,15 @@ class TestMarkerlib(unittest.TestCase):
os_name = os.name os_name = os.name
self.assert_(interpret("")) self.assertTrue(interpret(""))
self.assert_(interpret("os.name != 'buuuu'")) self.assertTrue(interpret("os.name != 'buuuu'"))
self.assert_(interpret("python_version > '1.0'")) self.assertTrue(interpret("python_version > '1.0'"))
self.assert_(interpret("python_version < '5.0'")) self.assertTrue(interpret("python_version < '5.0'"))
self.assert_(interpret("python_version <= '5.0'")) self.assertTrue(interpret("python_version <= '5.0'"))
self.assert_(interpret("python_version >= '1.0'")) self.assertTrue(interpret("python_version >= '1.0'"))
self.assert_(interpret("'%s' in os.name" % os_name)) self.assertTrue(interpret("'%s' in os.name" % os_name))
self.assert_(interpret("'buuuu' not in os.name")) self.assertTrue(interpret("'buuuu' not in os.name"))
self.assertFalse(interpret("os.name == 'buuuu'")) self.assertFalse(interpret("os.name == 'buuuu'"))
self.assertFalse(interpret("python_version < '1.0'")) self.assertFalse(interpret("python_version < '1.0'"))
...@@ -36,7 +36,7 @@ class TestMarkerlib(unittest.TestCase): ...@@ -36,7 +36,7 @@ class TestMarkerlib(unittest.TestCase):
environment = default_environment() environment = default_environment()
environment['extra'] = 'test' environment['extra'] = 'test'
self.assert_(interpret("extra == 'test'", environment)) self.assertTrue(interpret("extra == 'test'", environment))
self.assertFalse(interpret("extra == 'doc'", environment)) self.assertFalse(interpret("extra == 'doc'", environment))
def raises_nameError(): def raises_nameError():
......
...@@ -478,13 +478,14 @@ class ParseTests(TestCase): ...@@ -478,13 +478,14 @@ class ParseTests(TestCase):
p1, p2 = parse_version(s1),parse_version(s2) p1, p2 = parse_version(s1),parse_version(s2)
self.assertEqual(p1,p2, (s1,s2,p1,p2)) self.assertEqual(p1,p2, (s1,s2,p1,p2))
c('1.2-rc1', '1.2rc1')
c('0.4', '0.4.0') c('0.4', '0.4.0')
c('0.4.0.0', '0.4.0') c('0.4.0.0', '0.4.0')
c('0.4.0-0', '0.4-0') c('0.4.0-0', '0.4-0')
c('0pl1', '0.0pl1') c('0pl1', '0.0pl1')
c('0pre1', '0.0c1') c('0pre1', '0.0c1')
c('0.0.0preview1', '0c1') c('0.0.0preview1', '0c1')
c('0.0c1', '0rc1') c('0.0c1', '0-rc1')
c('1.2a1', '1.2.a.1'); c('1.2...a', '1.2a') c('1.2a1', '1.2.a.1'); c('1.2...a', '1.2a')
def testVersionOrdering(self): def testVersionOrdering(self):
...@@ -493,14 +494,11 @@ class ParseTests(TestCase): ...@@ -493,14 +494,11 @@ class ParseTests(TestCase):
self.assertTrue(p1<p2, (s1,s2,p1,p2)) self.assertTrue(p1<p2, (s1,s2,p1,p2))
c('2.1','2.1.1') c('2.1','2.1.1')
c('2.1.0','2.10')
c('2a1','2b0') c('2a1','2b0')
c('2b1','2c0')
c('2a1','2.1') c('2a1','2.1')
c('2.3a1', '2.3') c('2.3a1', '2.3')
c('2.1-1', '2.1-2') c('2.1-1', '2.1-2')
c('2.1-1', '2.1.1') c('2.1-1', '2.1.1')
c('2.1', '2.1.1-1')
c('2.1', '2.1pl4') c('2.1', '2.1pl4')
c('2.1a0-20040501', '2.1') c('2.1a0-20040501', '2.1')
c('1.1', '02.1') c('1.1', '02.1')
...@@ -511,20 +509,8 @@ class ParseTests(TestCase): ...@@ -511,20 +509,8 @@ class ParseTests(TestCase):
c('0.4', '4.0') c('0.4', '4.0')
c('0.0.4', '0.4.0') c('0.0.4', '0.4.0')
c('0pl1', '0.4pl1') c('0pl1', '0.4pl1')
c('2.1.0-rc1','2.1.0')
c('2.1dev','2.1a0') c('2.1dev','2.1a0')
c('2.1.0rc1','2.1.0')
c('2.1.0','2.1.0-rc0')
c('2.1.0','2.1.0-a')
c('2.1.0','2.1.0-alpha')
c('2.1.0','2.1.0-foo')
c('1.0','1.0-1')
c('1.0-1','1.0.1')
c('1.0a','1.0b')
c('1.0dev','1.0rc1')
c('1.0pre','1.0')
c('1.0pre','1.0')
c('1.0a','1.0-a')
c('1.0rc1','1.0-rc1')
torture =""" torture ="""
0.80.1-3 0.80.1-2 0.80.1-1 0.79.9999+0.80.0pre4-1 0.80.1-3 0.80.1-2 0.80.1-1 0.79.9999+0.80.0pre4-1
...@@ -562,6 +548,15 @@ class ScriptHeaderTests(TestCase): ...@@ -562,6 +548,15 @@ class ScriptHeaderTests(TestCase):
if (sys.version_info >= (3,) and os.environ.get("LC_CTYPE") if (sys.version_info >= (3,) and os.environ.get("LC_CTYPE")
in (None, "C", "POSIX")): in (None, "C", "POSIX")):
return return
class java:
class lang:
class System:
@staticmethod
def getProperty(property):
return ""
sys.modules["java"] = java
platform = sys.platform platform = sys.platform
sys.platform = 'java1.5.0_13' sys.platform = 'java1.5.0_13'
stdout = sys.stdout stdout = sys.stdout
...@@ -585,6 +580,7 @@ class ScriptHeaderTests(TestCase): ...@@ -585,6 +580,7 @@ class ScriptHeaderTests(TestCase):
'#!%s -x\n' % self.non_ascii_exe) '#!%s -x\n' % self.non_ascii_exe)
self.assertTrue('Unable to adapt shebang line' in sys.stdout.getvalue()) self.assertTrue('Unable to adapt shebang line' in sys.stdout.getvalue())
finally: finally:
del sys.modules["java"]
sys.platform = platform sys.platform = platform
sys.stdout = stdout sys.stdout = stdout
......
This diff is collapsed.
...@@ -54,12 +54,19 @@ class TestUploadDocsTest(unittest.TestCase): ...@@ -54,12 +54,19 @@ class TestUploadDocsTest(unittest.TestCase):
cmd = upload_docs(dist) cmd = upload_docs(dist)
cmd.upload_dir = self.upload_dir cmd.upload_dir = self.upload_dir
zip_file = cmd.create_zipfile() cmd.target_dir = self.upload_dir
tmp_dir = tempfile.mkdtemp()
tmp_file = os.path.join(tmp_dir, 'foo.zip')
try:
zip_file = cmd.create_zipfile(tmp_file)
assert zipfile.is_zipfile(zip_file) assert zipfile.is_zipfile(tmp_file)
zip_f = zipfile.ZipFile(zip_file) # woh... zip_file = zipfile.ZipFile(tmp_file) # woh...
assert zip_f.namelist() == ['index.html'] assert zip_file.namelist() == ['index.html']
zip_file.close()
finally:
shutil.rmtree(tmp_dir)
...@@ -17,7 +17,7 @@ Let's create a simple script, foo-script.py: ...@@ -17,7 +17,7 @@ Let's create a simple script, foo-script.py:
>>> from setuptools.command.easy_install import nt_quote_arg >>> from setuptools.command.easy_install import nt_quote_arg
>>> sample_directory = tempfile.mkdtemp() >>> sample_directory = tempfile.mkdtemp()
>>> f = open(os.path.join(sample_directory, 'foo-script.py'), 'w') >>> f = open(os.path.join(sample_directory, 'foo-script.py'), 'w')
>>> bytes = f.write( >>> bytes_written = f.write(
... """#!%(python_exe)s ... """#!%(python_exe)s
... import sys ... import sys
... input = repr(sys.stdin.read()) ... input = repr(sys.stdin.read())
...@@ -37,8 +37,8 @@ We'll also copy cli.exe to the sample-directory with the name foo.exe: ...@@ -37,8 +37,8 @@ We'll also copy cli.exe to the sample-directory with the name foo.exe:
>>> import pkg_resources >>> import pkg_resources
>>> f = open(os.path.join(sample_directory, 'foo.exe'), 'wb') >>> f = open(os.path.join(sample_directory, 'foo.exe'), 'wb')
>>> bytes = f.write( >>> bytes_written = f.write(
... pkg_resources.resource_string('setuptools', 'cli.exe') ... pkg_resources.resource_string('setuptools', 'cli-32.exe')
... ) ... )
>>> f.close() >>> f.close()
...@@ -82,7 +82,7 @@ options as usual. For example, to run in optimized mode and ...@@ -82,7 +82,7 @@ options as usual. For example, to run in optimized mode and
enter the interpreter after running the script, you could use -Oi: enter the interpreter after running the script, you could use -Oi:
>>> f = open(os.path.join(sample_directory, 'foo-script.py'), 'w') >>> f = open(os.path.join(sample_directory, 'foo-script.py'), 'w')
>>> bytes = f.write( >>> bytes_written = f.write(
... """#!%(python_exe)s -Oi ... """#!%(python_exe)s -Oi
... import sys ... import sys
... input = repr(sys.stdin.read()) ... input = repr(sys.stdin.read())
...@@ -112,10 +112,12 @@ Now let's test the GUI version with the simple scipt, bar-script.py: ...@@ -112,10 +112,12 @@ Now let's test the GUI version with the simple scipt, bar-script.py:
>>> from setuptools.command.easy_install import nt_quote_arg >>> from setuptools.command.easy_install import nt_quote_arg
>>> sample_directory = tempfile.mkdtemp() >>> sample_directory = tempfile.mkdtemp()
>>> f = open(os.path.join(sample_directory, 'bar-script.pyw'), 'w') >>> f = open(os.path.join(sample_directory, 'bar-script.pyw'), 'w')
>>> bytes = f.write( >>> bytes_written = f.write(
... """#!%(python_exe)s ... """#!%(python_exe)s
... import sys ... import sys
... open(sys.argv[1], 'wb').write(repr(sys.argv[2]).encode('ascii')) ... f = open(sys.argv[1], 'wb')
... bytes_written = f.write(repr(sys.argv[2]).encode('utf-8'))
... f.close()
... """ % dict(python_exe=nt_quote_arg(sys.executable))) ... """ % dict(python_exe=nt_quote_arg(sys.executable)))
>>> f.close() >>> f.close()
...@@ -123,8 +125,8 @@ We'll also copy gui.exe to the sample-directory with the name bar.exe: ...@@ -123,8 +125,8 @@ We'll also copy gui.exe to the sample-directory with the name bar.exe:
>>> import pkg_resources >>> import pkg_resources
>>> f = open(os.path.join(sample_directory, 'bar.exe'), 'wb') >>> f = open(os.path.join(sample_directory, 'bar.exe'), 'wb')
>>> bytes = f.write( >>> bytes_written = f.write(
... pkg_resources.resource_string('setuptools', 'gui.exe') ... pkg_resources.resource_string('setuptools', 'gui-32.exe')
... ) ... )
>>> f.close() >>> f.close()
......
import sys
import tempfile
import os
import zipfile
import pkg_resources
class EggRemover(unicode):
def __call__(self):
if self in sys.path:
sys.path.remove(self)
if os.path.exists(self):
os.remove(self)
class TestZipProvider(object):
finalizers = []
@classmethod
def setup_class(cls):
"create a zip egg and add it to sys.path"
egg = tempfile.NamedTemporaryFile(suffix='.egg', delete=False)
zip_egg = zipfile.ZipFile(egg, 'w')
zip_info = zipfile.ZipInfo()
zip_info.filename = 'mod.py'
zip_info.date_time = 2013, 5, 12, 13, 25, 0
zip_egg.writestr(zip_info, 'x = 3\n')
zip_info = zipfile.ZipInfo()
zip_info.filename = 'data.dat'
zip_info.date_time = 2013, 5, 12, 13, 25, 0
zip_egg.writestr(zip_info, 'hello, world!')
zip_egg.close()
egg.close()
sys.path.append(egg.name)
cls.finalizers.append(EggRemover(egg.name))
@classmethod
def teardown_class(cls):
for finalizer in cls.finalizers:
finalizer()
def test_resource_filename_rewrites_on_change(self):
"""
If a previous call to get_resource_filename has saved the file, but
the file has been subsequently mutated with different file of the
same size and modification time, it should not be overwritten on a
subsequent call to get_resource_filename.
"""
import mod
manager = pkg_resources.ResourceManager()
zp = pkg_resources.ZipProvider(mod)
filename = zp.get_resource_filename(manager, 'data.dat')
assert os.stat(filename).st_mtime == 1368379500
f = open(filename, 'wb')
f.write('hello, world?')
f.close()
os.utime(filename, (1368379500, 1368379500))
filename = zp.get_resource_filename(manager, 'data.dat')
f = open(filename)
assert f.read() == 'hello, world!'
manager.cleanup_resources()
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment