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
include
\.Python
*.swp
CHANGES (links).txt
......@@ -37,3 +37,21 @@ de44acab3cfce1f5bc811d6c0fa1a88ca0e9533f 0.6.21
b69f072c000237435e17b8bbb304ba6f957283eb 0.6.26
469c3b948e41ef28752b3cdf3c7fb9618355ebf5 0.6.27
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:
- 2.6
- 2.7
- 3.2
- 3.3
# command to run tests
script: python setup.py test
This diff is collapsed.
......@@ -8,16 +8,21 @@ Contributors
* Christophe Combelles
* Daniel Stutzbach
* Daniel Holth
* Dirley Rodrigues
* Grigory Petrov
* Hanno Schlichting
* Jannis Leidel
* Jason R. Coombs
* Jim Fulton
* Jonathan Lange
* Justin Azoff
* Lennart Regebro
* Marc Abramowitz
* Martin von Löwis
* Noufal Ibrahim
* Pete Hollobon
* Philip Jenvey
* Philip Thiem
* Reinout van Rees
* Robert Myers
* 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 setuptools/tests *.html
recursive-include docs *.py *.txt *.conf *.css *.css_t Makefile indexsidebar.html
......
......@@ -11,35 +11,14 @@ Disclaimers
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
for working with Python module distributions.
Distribute was intended to replace Setuptools as the standard method
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:
- 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.
`Distribute` is now being maintained as a branch in the `Setuptools
repository <https://bitbucket.org/pypa/setuptools>`_.
More documentation
==================
......@@ -99,9 +78,9 @@ Source installation
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
$ tar -xzvf distribute-0.6.29.tar.gz
$ cd distribute-0.6.29
$ curl -O http://pypi.python.org/packages/source/d/distribute/distribute-0.6.46.tar.gz
$ tar -xzvf distribute-0.6.46.tar.gz
$ cd distribute-0.6.46
$ python setup.py install
---------------------------
......@@ -224,5 +203,4 @@ Feedback and getting involved
- Mailing list: http://mail.python.org/mailman/listinfo/distutils-sig
- 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:
__all__ = ['default_environment', 'compile', 'interpret']
from ast import Compare, BoolOp, Attribute, Name, Load, Str, cmpop, boolop
from ast import parse, copy_location, NodeTransformer
import ast
import os
import platform
import sys
......@@ -27,7 +25,16 @@ import weakref
_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
_VARS = {'sys.platform': sys.platform,
......@@ -46,27 +53,31 @@ def default_environment():
"""Return copy of default PEP 385 globals dictionary."""
return dict(_VARS)
class ASTWhitelist(NodeTransformer):
class ASTWhitelist(ast.NodeTransformer):
def __init__(self, statement):
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):
"""Ensure statement only contains allowed nodes."""
if not isinstance(node, self.ALLOWED):
raise SyntaxError('Not allowed in environment markers.\n%s\n%s' %
(self.statement,
(self.statement,
(' ' * node.col_offset) + '^'))
return NodeTransformer.visit(self, node)
return ast.NodeTransformer.visit(self, node)
def visit_Attribute(self, node):
"""Flatten one level of attribute access."""
new_node = Name("%s.%s" % (node.value.id, node.attr), node.ctx)
return copy_location(new_node, node)
new_node = ast.Name("%s.%s" % (node.value.id, node.attr), node.ctx)
return ast.copy_location(new_node, node)
def parse_marker(marker):
tree = parse(marker, mode='eval')
tree = ast.parse(marker, mode='eval')
new_tree = ASTWhitelist(marker).generic_visit(tree)
return new_tree
......
......@@ -14,6 +14,7 @@ the appropriate options to ``use_setuptools()``.
This file can also be run as a script to install or upgrade setuptools.
"""
import os
import shutil
import sys
import time
import fnmatch
......@@ -48,7 +49,7 @@ except ImportError:
args = [quote(arg) for arg in args]
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/"
SETUPTOOLS_FAKED_VERSION = "0.6c11"
......@@ -86,8 +87,11 @@ def _install(tarball, install_args=()):
if not _python_cmd('setup.py', 'install', *install_args):
log.warn('Something went wrong during the installation.')
log.warn('See the error message above.')
# exitcode will be 2
return 2
finally:
os.chdir(old_wd)
shutil.rmtree(tmpdir)
def _build_egg(egg, tarball, to_dir):
......@@ -112,6 +116,7 @@ def _build_egg(egg, tarball, to_dir):
finally:
os.chdir(old_wd)
shutil.rmtree(tmpdir)
# returning the result
log.warn(egg)
if not os.path.exists(egg):
......@@ -139,6 +144,16 @@ def use_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL,
try:
try:
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 no_fake:
_fake_setuptools()
......@@ -234,7 +249,9 @@ def _no_sandbox(function):
def _patch_file(path, content):
"""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:
# already patched
log.warn('Already patched.')
......@@ -252,7 +269,10 @@ _patch_file = _no_sandbox(_patch_file)
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):
......@@ -443,8 +463,9 @@ def _relaunch():
log.warn('Relaunching...')
# we have to relaunch the process
# pip marker to avoid a relaunch bug
_cmd = ['-c', 'install', '--single-version-externally-managed']
if sys.argv[:3] == _cmd:
_cmd1 = ['-c', 'install', '--single-version-externally-managed']
_cmd2 = ['-c', 'install', '--record']
if sys.argv[:3] == _cmd1 or sys.argv[:3] == _cmd2:
sys.argv[0] = 'setup.py'
args = [sys.executable] + sys.argv
sys.exit(subprocess.call(args))
......@@ -529,7 +550,7 @@ def main(version=DEFAULT_VERSION):
"""Install or upgrade setuptools and EasyInstall"""
options = _parse_args()
tarball = download_setuptools(download_base=options.download_base)
_install(tarball, _build_install_args(options))
return _install(tarball, _build_install_args(options))
if __name__ == '__main__':
main()
sys.exit(main())
......@@ -48,9 +48,9 @@ copyright = u'2009-2011, The fellowship of the packaging'
# built documents.
#
# The short X.Y version.
version = '0.6.29'
version = '0.6.46'
# 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
# for a list of supported languages.
......
......@@ -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
"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
the prerelease tag if it's immediately after a number, but it's okay to do
so if you prefer. Thus, ``2.4c1`` and ``2.4.c1`` both represent release
candidate 1 of version ``2.4``, and are treated as identical by setuptools.
``a``, ``c``, ``dev``, and so on. You do not have to place a dot or dash
before the prerelease tag if it's immediately after a number, but it's okay to
do so if you prefer. Thus, ``2.4c1`` and ``2.4.c1`` and ``2.4-c1`` all
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
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``.
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:
* 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
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
......@@ -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')
True
>>> parse_version('2.1-rc2') < parse_version('2.1')
False
True
>>> parse_version('0.6a9dev-r41475') < parse_version('0.6a9')
True
......@@ -616,14 +610,20 @@ Dependencies that aren't in PyPI
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
as an egg, in the standard distutils ``sdist`` format, or as a single ``.py``
file. You just need to add some URLs to the ``dependency_links`` argument to
as:
- 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()``.
The URLs must be either:
1. direct download URLs, or
2. the URLs of web pages that contain direct download links
1. direct download URLs,
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
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
and automatically create a trivial ``setup.py`` to wrap the single ``.py`` file
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
example, the below will cause EasyInstall to search the specified page for
eggs or source distributions, if the package's dependencies aren't already
......@@ -2423,7 +2444,12 @@ command::
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.:
.. code-block:: ini
......
......@@ -14,6 +14,14 @@
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
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
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
......
@echo off
REM VCVARSALL may be in Program Files or Program Files (x86)
PATH=C:\Program Files\Microsoft Visual Studio 9.0\VC;%PATH%
PATH=C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC;%PATH%
REM Use old Windows SDK 6.1 so created .exe will be compatible with
REM old Windows versions.
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
call VCVARSALL x86
cl /D "GUI=0" /D "WIN32_LEAN_AND_MEAN" launcher.c /O2 /link /MACHINE:x86 /out:setuptools/cli-32.exe
cl /D "GUI=1" /D "WIN32_LEAN_AND_MEAN" launcher.c /O2 /link /MACHINE:x86 /out:setuptools/gui-32.exe
call VCVARS32
if "%ERRORLEVEL%"=="0" (
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
call VCVARSALL x86_amd64
cl /D "GUI=0" /D "WIN32_LEAN_AND_MEAN" launcher.c /O2 /link /MACHINE:x64 /out:setuptools/cli-64.exe
cl /D "GUI=1" /D "WIN32_LEAN_AND_MEAN" launcher.c /O2 /link /MACHINE:x64 /out:setuptools/gui-64.exe
\ No newline at end of file
REM Use the x86_amd64 profile, which is the 32-bit cross compiler for amd64
call VCVARSx86_amd64
if "%ERRORLEVEL%"=="0" (
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
import urllib2
import getpass
import collections
import itertools
import re
try:
import keyring
except Exception:
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():
digits = map(int, VERSION.split('.'))
......@@ -50,7 +54,7 @@ def get_mercurial_creds(system='https://bitbucket.org', username=None):
# todo: consider getting this from .hgrc
username = username or getpass.getuser()
keyring_username = '@@'.join((username, system))
system = '@'.join((keyring_username, 'Mercurial'))
system = 'Mercurial'
password = (
keyring.get_password(system, keyring_username)
if 'keyring' in globals()
......@@ -65,7 +69,7 @@ def add_milestone_and_version(version=NEXT_VERSION):
auth = 'Basic ' + ':'.join(get_mercurial_creds()).encode('base64').strip()
headers = {
'Authorization': auth,
}
}
base = 'https://api.bitbucket.org'
for type in 'milestones', 'versions':
url = (base + '/1.0/repositories/{repo}/issues/{type}'
......@@ -99,7 +103,7 @@ def do_release():
print("Please do that")
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 '
'pass on this revision? ')
if not res.lower().startswith('y'):
......@@ -110,13 +114,20 @@ def do_release():
subprocess.check_call(['hg', 'update', VERSION])
linkify('CHANGES.txt', 'CHANGES (links).txt')
has_docs = build_docs()
if os.path.isdir('./dist'):
shutil.rmtree('./dist')
cmd = [sys.executable, 'setup.py', '-q', 'egg_info', '-RD', '-b', '',
'sdist', 'register', 'upload']
cmd = [
sys.executable, 'setup.py', '-q',
'egg_info', '-RD', '-b', '',
'sdist',
'register', '-r', PACKAGE_INDEX,
'upload', '-r', PACKAGE_INDEX,
]
if has_docs:
cmd.append('upload_docs')
cmd.extend(['upload_docs', '-r', PACKAGE_INDEX])
subprocess.check_call(cmd)
upload_bootstrap_script()
......@@ -148,14 +159,14 @@ def build_docs():
return
if os.path.isdir('docs/build'):
shutil.rmtree('docs/build')
subprocess.check_call([
cmd = [
'sphinx-build',
'-b', 'html',
'-d', 'build/doctrees',
'.',
'build/html',
],
cwd='docs')
]
subprocess.check_call(cmd, cwd='docs')
return True
def upload_bootstrap_script():
......@@ -166,5 +177,59 @@ def upload_bootstrap_script():
except:
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__':
do_release()
......@@ -3,6 +3,7 @@
import sys
import os
import textwrap
import re
# Allow to run setup.py from another directory.
os.chdir(os.path.dirname(os.path.abspath(__file__)))
......@@ -15,8 +16,10 @@ if sys.version_info >= (3,) and do_2to3:
from distutils import dir_util, file_util, util, log
log.set_verbosity(1)
fl = FileList()
for line in open("MANIFEST.in"):
manifest_file = open("MANIFEST.in")
for line in manifest_file:
fl.process_template_line(line)
manifest_file.close()
dir_util.create_tree(tmp_src, fl.files)
outfiles_2to3 = []
dist_script = os.path.join("build", "src", "distribute_setup.py")
......@@ -39,10 +42,12 @@ from distutils.util import convert_path
d = {}
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__']
VERSION = "0.6.29"
VERSION = "0.6.46"
from setuptools import setup, find_packages
from setuptools.command.build_py import build_py as _build_py
......@@ -82,10 +87,8 @@ class test(_test):
entry_points = os.path.join('distribute.egg-info', 'entry_points.txt')
if not os.path.exists(entry_points):
try:
_test.run(self)
finally:
return
_test.run(self)
return # even though _test.run will raise SystemExit
f = open(entry_points)
......@@ -132,6 +135,16 @@ if _being_installed():
from distribute_setup import _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(
name="distribute",
......@@ -141,26 +154,24 @@ dist = setup(
author="The fellowship of the packaging",
author_email="distutils-sig@python.org",
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",
url = "http://packages.python.org/distribute",
test_suite = 'setuptools.tests',
src_root = src_root,
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
cmdclass = {'test': test},
entry_points = {
"distutils.commands" : [
"%(cmd)s = setuptools.command.%(cmd)s:%(cmd)s" % locals()
for cmd in SETUP_COMMANDS
],
"distutils.setup_keywords": [
"eager_resources = setuptools.dist:assert_string_list",
"namespace_packages = setuptools.dist:check_nsp",
......@@ -181,7 +192,6 @@ dist = setup(
"use_2to3_fixers = setuptools.dist:assert_string_list",
"use_2to3_exclude_fixers = setuptools.dist:assert_string_list",
],
"egg_info.writers": [
"PKG-INFO = setuptools.command.egg_info:write_pkg_info",
"requires.txt = setuptools.command.egg_info:write_requirements",
......@@ -192,7 +202,6 @@ dist = setup(
"depends.txt = setuptools.command.egg_info:warn_depends_obsolete",
"dependency_links.txt = setuptools.command.egg_info:overwrite_arg",
],
"console_scripts": console_scripts,
"setuptools.file_finders":
......@@ -200,7 +209,7 @@ dist = setup(
"setuptools.installation":
['eggsecutable = setuptools.command.easy_install:bootstrap'],
},
},
classifiers = textwrap.dedent("""
......
......@@ -158,6 +158,9 @@ def unpack_zipfile(filename, extract_dir, progress_filter=default_filter):
finally:
f.close()
del data
unix_attributes = info.external_attr >> 16
if unix_attributes:
os.chmod(target, unix_attributes)
finally:
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):
def uninstall_link(self):
if os.path.exists(self.egg_link):
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]):
log.warn("Link points to %s: uninstall aborted", contents)
return
......
......@@ -19,7 +19,9 @@ import zipfile
import re
import stat
import random
import platform
from glob import glob
import pkg_resources
from setuptools import Command, _dont_write_bytecode
from setuptools.sandbox import run_setup
from distutils import log, dir_util
......@@ -493,7 +495,7 @@ Please make the appropriate changes for your system and try again.
self.cant_write_to_target()
else:
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
executable = sys.executable
if os.name=='nt':
......@@ -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"""
if not self.exclude_scripts and dist.metadata_isdir('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(
dist, script_name,
dist.get_metadata('scripts/'+script_name)
......@@ -1276,7 +1282,7 @@ Please make the appropriate changes for your system and try again.""" % (
return # already did it, or don't need to
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 = ""
if os.path.exists(sitepy):
......@@ -1529,7 +1535,10 @@ def get_exe_prefixes(exe_filename):
if name.endswith('-nspkg.pth'):
continue
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('\\','/')
if not pth.startswith('import'):
prefixes.append((('%s/%s/' % (parts[0],pth)), ''))
......@@ -1794,6 +1803,11 @@ def chmod(path, mode):
def fix_jython_executable(executable, options):
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
# shebang line interpreter)
if options:
......@@ -1828,31 +1842,61 @@ def get_script_args(dist, executable=sys_executable, wininst=False):
if sys.platform=='win32' or wininst:
# On Windows/wininst, add a .py extension and an .exe launcher
if group=='gui_scripts':
ext, launcher = '-script.pyw', 'gui.exe'
launcher_type = 'gui'
ext = '-script.pyw'
old = ['.pyw']
new_header = re.sub('(?i)python.exe','pythonw.exe',header)
else:
ext, launcher = '-script.py', 'cli.exe'
launcher_type = 'cli'
ext = '-script.py'
old = ['.py','.pyc','.pyo']
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':
hdr = new_header
else:
hdr = header
yield (name+ext, hdr+script_text, 't', [name+x for x in old])
yield (
name+'.exe', resource_string('setuptools', launcher),
name+'.exe', get_win_launcher(launcher_type),
'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:
# On other platforms, we assume the right thing to do is to
# just write the stub with no extension.
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):
"""Recursively delete a directory tree.
......
......@@ -10,7 +10,7 @@ from distutils import log
from setuptools.command.sdist import sdist
from setuptools.compat import basestring
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, \
safe_version, yield_lines, EntryPoint, iter_entry_points, to_filename
from setuptools.command.sdist import walk_revctrl
......@@ -275,35 +275,34 @@ class egg_info(Command):
self.broken_egg_info = self.egg_info
self.egg_info = bei # make it work for now
class FileList(FileList):
class FileList(_FileList):
"""File list that accepts only existing, platform-independent paths"""
def append(self, item):
if item.endswith('\r'): # Fix older sdists built on Windows
item = item[:-1]
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):
......@@ -330,7 +329,6 @@ class manifest_maker(sdist):
self.prune_file_list()
self.filelist.sort()
self.filelist.remove_duplicates()
self.filelist.files = [compose(path) for path in self.filelist.files]
self.write_manifest()
def write_manifest (self):
......@@ -338,6 +336,18 @@ class manifest_maker(sdist):
by 'add_defaults()' and 'read_template()') to the manifest file
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
if os.sep!='/':
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):
log.info("reading manifest file '%s'", self.manifest)
manifest = open(self.manifest, 'rbU')
for line in manifest:
# The manifest must contain UTF-8. See #303.
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
line = line.strip()
if line.startswith('#') or not line:
......
......@@ -108,8 +108,9 @@ class upload(Command):
data['comment'] = comment
if self.sign:
data['gpg_signature'] = (os.path.basename(filename) + ".asc",
open(filename+".asc").read())
asc_file = open(filename + ".asc")
data['gpg_signature'] = (os.path.basename(filename) + ".asc", asc_file.read())
asc_file.close()
# set up the authentication
auth = "Basic " + base64.encodestring(self.username + ":" + self.password).strip()
......
......@@ -8,9 +8,12 @@ PyPI's packages.python.org).
import os
import socket
import zipfile
import base64
import tempfile
import sys
import shutil
from base64 import standard_b64encode
from pkg_resources import iter_entry_points
from distutils import log
from distutils.errors import DistutilsOptionError
......@@ -24,18 +27,12 @@ from setuptools.compat import httplib, urlparse
_IS_PYTHON3 = sys.version > '3'
try:
bytes
except NameError:
bytes = str
def b(str_or_bytes):
"""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
# This is not just a replacement for byte literals
# but works as a general purpose encoder
def b(s, encoding='utf-8'):
if isinstance(s, unicode):
return s.encode(encoding)
return s
class upload_docs(upload):
......@@ -51,43 +48,67 @@ class upload_docs(upload):
]
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):
upload.initialize_options(self)
self.upload_dir = None
self.target_dir = None
def finalize_options(self):
upload.finalize_options(self)
if self.upload_dir is None:
build = self.get_finalized_command('build')
self.upload_dir = os.path.join(build.build_base, 'docs')
self.mkpath(self.upload_dir)
self.ensure_dirname('upload_dir')
self.announce('Using upload directory %s' % self.upload_dir)
if self.has_sphinx():
build_sphinx = self.get_finalized_command('build_sphinx')
self.target_dir = build_sphinx.builder_target_dir
else:
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):
name = self.distribution.metadata.get_name()
tmp_dir = tempfile.mkdtemp()
tmp_file = os.path.join(tmp_dir, "%s.zip" % name)
zip_file = zipfile.ZipFile(tmp_file, "w")
for root, dirs, files in os.walk(self.upload_dir):
if root == self.upload_dir and not files:
raise DistutilsOptionError(
"no files found in upload directory '%s'"
% self.upload_dir)
for name in files:
full = os.path.join(root, name)
relative = root[len(self.upload_dir):].lstrip(os.path.sep)
dest = os.path.join(relative, name)
zip_file.write(full, dest)
zip_file.close()
return tmp_file
def create_zipfile(self, filename):
zip_file = zipfile.ZipFile(filename, "w")
try:
self.mkpath(self.target_dir) # just in case
for root, dirs, files in os.walk(self.target_dir):
if root == self.target_dir and not files:
raise DistutilsOptionError(
"no files found in upload directory '%s'"
% self.target_dir)
for name in files:
full = os.path.join(root, name)
relative = root[len(self.target_dir):].lstrip(os.path.sep)
dest = os.path.join(relative, name)
zip_file.write(full, dest)
finally:
zip_file.close()
def run(self):
zip_file = self.create_zipfile()
self.upload_file(zip_file)
# Run sub commands
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):
content = open(filename, 'rb').read()
f = open(filename, 'rb')
content = f.read()
f.close()
meta = self.distribution.metadata
data = {
':action': 'doc_upload',
......@@ -95,36 +116,33 @@ class upload_docs(upload):
'content': (os.path.basename(filename), content),
}
# set up the authentication
credentials = self.username + ':' + self.password
if _IS_PYTHON3: # base64 only works with bytes in Python 3.
encoded_creds = base64.encodebytes(credentials.encode('utf8'))
auth = bytes("Basic ")
else:
encoded_creds = base64.encodestring(credentials)
auth = "Basic "
auth += encoded_creds.strip()
credentials = b(self.username + ':' + self.password)
credentials = standard_b64encode(credentials)
if sys.version_info >= (3,):
credentials = credentials.decode('ascii')
auth = "Basic " + credentials
# Build up the MIME payload for the POST data
boundary = b('--------------GHSKFJDLGDS7543FJKLFHRE75642756743254')
sep_boundary = b('\n--') + boundary
boundary = '--------------GHSKFJDLGDS7543FJKLFHRE75642756743254'
sep_boundary = b('\n--') + b(boundary)
end_boundary = sep_boundary + b('--')
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
if type(values) != type([]):
values = [values]
for value in values:
if type(value) is tuple:
fn = b(';filename="%s"' % value[0])
title += '; filename="%s"' % value[0]
value = value[1]
else:
fn = b("")
value = b(value)
body.append(sep_boundary)
body.append(b('\nContent-Disposition: form-data; name="%s"'%key))
body.append(fn)
body.append(b(title))
body.append(b("\n\n"))
body.append(b(value))
if value and value[-1] == b('\r'):
body.append(value)
if value and value[-1:] == b('\r'):
body.append(b('\n')) # write an extra newline (lurve Macs)
body.append(end_boundary)
body.append(b("\n"))
......
......@@ -660,6 +660,11 @@ class Distribution(_Distribution):
if not isinstance(sys.stdout, io.TextIOWrapper):
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
encoding = sys.stdout.encoding
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"""
import sys, os.path, re, shutil, random, socket
import itertools
import base64
from pkg_resources import *
from distutils import log
......@@ -14,6 +15,8 @@ except ImportError:
from md5 import md5
from fnmatch import translate
from setuptools.py24compat import wraps
EGG_FRAGMENT = re.compile(r'^egg=([-A-Za-z0-9_.]+)$')
HREF = re.compile("""href\\s*=\\s*['"]?([^'"> ]+)""", re.I)
# this is here to fix emacs' cruddy broken syntax highlighting
......@@ -137,9 +140,38 @@ def interpret_distro_name(location, basename, metadata,
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)
# this line is here to fix emacs' cruddy broken syntax highlighting
@unique_values
def find_external_links(url, page):
"""Find rel="homepage" and rel="download" links in `page`, yielding URLs"""
......@@ -157,6 +189,7 @@ def find_external_links(url, page):
if match:
yield urljoin(url, htmldecode(match.group(1)))
user_agent = "Python-urllib/%s distribute/%s" % (
sys.version[:3], require('distribute')[0].version
)
......@@ -666,6 +699,10 @@ class PackageIndex(Environment):
#
if scheme=='svn' or scheme.startswith('svn+'):
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':
return url2pathname(urlparse.urlparse(url)[2])
else:
......@@ -706,6 +743,55 @@ class PackageIndex(Environment):
os.system("svn checkout -q %s %s" % (url, 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):
log.debug(msg, *args)
......@@ -789,9 +875,8 @@ def open_with_auth(url):
# Double scheme does not raise on Mac OS X as revealed by a
# failing test. We would expect "nonnumeric port". Refs #20.
if sys.platform == 'darwin':
if netloc.endswith(':'):
raise httplib.InvalidURL("nonnumeric port: ''")
if netloc.endswith(':'):
raise httplib.InvalidURL("nonnumeric port: ''")
if scheme in ('http', 'https'):
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
_os = sys.modules[os.name]
if os.name == "java":
import org.python.modules.posix.PosixModule as _os
else:
_os = sys.modules[os.name]
try:
_file = file
except NameError:
......
......@@ -1968,7 +1968,9 @@ def testfile(filename, module_relative=True, name=None, package=None,
runner = DocTestRunner(verbose=verbose, optionflags=optionflags)
# 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)
runner.run(test)
......@@ -2353,7 +2355,9 @@ def DocFileTest(path, module_relative=True, package=None,
# Find the file and read it.
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.
test = parser.get_doctest(doc, globs, name, path, 0)
......
......@@ -89,16 +89,16 @@ class TestDevelopTest(unittest.TestCase):
self.assertEqual(content, ['easy-install.pth', 'foo.egg-link'])
# 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:
path = f.read().split()[0].strip()
path = egg_link_file.read().split()[0].strip()
finally:
f.close()
f = open(os.path.join(path, 'foo', '__init__.py'), 'rt')
egg_link_file.close()
init_file = open(os.path.join(path, 'foo', '__init__.py'), 'rt')
try:
init = f.read().strip()
init = init_file.read().strip()
finally:
f.close()
init_file.close()
if sys.version < "3":
self.assertEqual(init, 'print "foo"')
else:
......
......@@ -50,9 +50,9 @@ class TestDistInfo(unittest.TestCase):
versioned = os.path.join(self.tmpdir,
'VersionedDistribution-2.718.dist-info')
os.mkdir(versioned)
f = open(os.path.join(versioned, 'METADATA'), 'w+')
metadata_file = open(os.path.join(versioned, 'METADATA'), 'w+')
try:
f.write(DALS(
metadata_file.write(DALS(
"""
Metadata-Version: 1.2
Name: VersionedDistribution
......@@ -61,13 +61,13 @@ class TestDistInfo(unittest.TestCase):
Requires-Dist: quux (>=1.1); extra == 'baz'
"""))
finally:
f.close()
metadata_file.close()
unversioned = os.path.join(self.tmpdir,
'UnversionedDistribution.dist-info')
os.mkdir(unversioned)
f = open(os.path.join(unversioned, 'METADATA'), 'w+')
metadata_file = open(os.path.join(unversioned, 'METADATA'), 'w+')
try:
f.write(DALS(
metadata_file.write(DALS(
"""
Metadata-Version: 1.2
Name: UnversionedDistribution
......@@ -77,7 +77,7 @@ class TestDistInfo(unittest.TestCase):
Requires-Dist: quux (>=1.1); extra == 'baz'
"""))
finally:
f.close()
metadata_file.close()
def tearDown(self):
shutil.rmtree(self.tmpdir)
......@@ -13,7 +13,7 @@ import tarfile
import distutils.core
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 import easy_install as easy_install_pkg
from setuptools.dist import Distribution
......@@ -51,7 +51,7 @@ if __name__ == '__main__':
sys.exit(
load_entry_point('spec', 'console_scripts', 'name')()
)
""" % sys.executable
""" % fix_jython_executable(sys.executable, "")
SETUP_PY = """\
from setuptools import setup
......
......@@ -16,15 +16,15 @@ class TestMarkerlib(unittest.TestCase):
os_name = os.name
self.assert_(interpret(""))
self.assertTrue(interpret(""))
self.assert_(interpret("os.name != 'buuuu'"))
self.assert_(interpret("python_version > '1.0'"))
self.assert_(interpret("python_version < '5.0'"))
self.assert_(interpret("python_version <= '5.0'"))
self.assert_(interpret("python_version >= '1.0'"))
self.assert_(interpret("'%s' in os.name" % os_name))
self.assert_(interpret("'buuuu' not in os.name"))
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.assertFalse(interpret("os.name == 'buuuu'"))
self.assertFalse(interpret("python_version < '1.0'"))
......@@ -36,7 +36,7 @@ class TestMarkerlib(unittest.TestCase):
environment = default_environment()
environment['extra'] = 'test'
self.assert_(interpret("extra == 'test'", environment))
self.assertTrue(interpret("extra == 'test'", environment))
self.assertFalse(interpret("extra == 'doc'", environment))
def raises_nameError():
......
......@@ -478,13 +478,14 @@ class ParseTests(TestCase):
p1, p2 = parse_version(s1),parse_version(s2)
self.assertEqual(p1,p2, (s1,s2,p1,p2))
c('1.2-rc1', '1.2rc1')
c('0.4', '0.4.0')
c('0.4.0.0', '0.4.0')
c('0.4.0-0', '0.4-0')
c('0pl1', '0.0pl1')
c('0pre1', '0.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')
def testVersionOrdering(self):
......@@ -493,14 +494,11 @@ class ParseTests(TestCase):
self.assertTrue(p1<p2, (s1,s2,p1,p2))
c('2.1','2.1.1')
c('2.1.0','2.10')
c('2a1','2b0')
c('2b1','2c0')
c('2a1','2.1')
c('2.3a1', '2.3')
c('2.1-1', '2.1-2')
c('2.1-1', '2.1.1')
c('2.1', '2.1.1-1')
c('2.1', '2.1pl4')
c('2.1a0-20040501', '2.1')
c('1.1', '02.1')
......@@ -511,20 +509,8 @@ class ParseTests(TestCase):
c('0.4', '4.0')
c('0.0.4', '0.4.0')
c('0pl1', '0.4pl1')
c('2.1.0-rc1','2.1.0')
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 ="""
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):
if (sys.version_info >= (3,) and os.environ.get("LC_CTYPE")
in (None, "C", "POSIX")):
return
class java:
class lang:
class System:
@staticmethod
def getProperty(property):
return ""
sys.modules["java"] = java
platform = sys.platform
sys.platform = 'java1.5.0_13'
stdout = sys.stdout
......@@ -585,6 +580,7 @@ class ScriptHeaderTests(TestCase):
'#!%s -x\n' % self.non_ascii_exe)
self.assertTrue('Unable to adapt shebang line' in sys.stdout.getvalue())
finally:
del sys.modules["java"]
sys.platform = platform
sys.stdout = stdout
......
This diff is collapsed.
......@@ -54,12 +54,19 @@ class TestUploadDocsTest(unittest.TestCase):
cmd = upload_docs(dist)
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:
>>> from setuptools.command.easy_install import nt_quote_arg
>>> sample_directory = tempfile.mkdtemp()
>>> f = open(os.path.join(sample_directory, 'foo-script.py'), 'w')
>>> bytes = f.write(
>>> bytes_written = f.write(
... """#!%(python_exe)s
... import sys
... input = repr(sys.stdin.read())
......@@ -37,8 +37,8 @@ We'll also copy cli.exe to the sample-directory with the name foo.exe:
>>> import pkg_resources
>>> f = open(os.path.join(sample_directory, 'foo.exe'), 'wb')
>>> bytes = f.write(
... pkg_resources.resource_string('setuptools', 'cli.exe')
>>> bytes_written = f.write(
... pkg_resources.resource_string('setuptools', 'cli-32.exe')
... )
>>> f.close()
......@@ -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:
>>> f = open(os.path.join(sample_directory, 'foo-script.py'), 'w')
>>> bytes = f.write(
>>> bytes_written = f.write(
... """#!%(python_exe)s -Oi
... import sys
... input = repr(sys.stdin.read())
......@@ -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
>>> sample_directory = tempfile.mkdtemp()
>>> f = open(os.path.join(sample_directory, 'bar-script.pyw'), 'w')
>>> bytes = f.write(
>>> bytes_written = f.write(
... """#!%(python_exe)s
... 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)))
>>> f.close()
......@@ -123,8 +125,8 @@ We'll also copy gui.exe to the sample-directory with the name bar.exe:
>>> import pkg_resources
>>> f = open(os.path.join(sample_directory, 'bar.exe'), 'wb')
>>> bytes = f.write(
... pkg_resources.resource_string('setuptools', 'gui.exe')
>>> bytes_written = f.write(
... pkg_resources.resource_string('setuptools', 'gui-32.exe')
... )
>>> 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