diff options
-rw-r--r-- | .hgtags | 10 | ||||
-rw-r--r-- | .travis.yml | 1 | ||||
-rw-r--r-- | CHANGES.txt | 59 | ||||
-rw-r--r-- | CONTRIBUTORS.txt | 3 | ||||
-rwxr-xr-x | README.txt | 42 | ||||
-rw-r--r-- | distribute_setup.py | 12 | ||||
-rw-r--r-- | docs/conf.py | 4 | ||||
-rwxr-xr-x | launcher.c | 8 | ||||
-rw-r--r-- | msvc-build-launcher.cmd | 58 | ||||
-rw-r--r-- | pkg_resources.py | 46 | ||||
-rw-r--r-- | release.py | 25 | ||||
-rwxr-xr-x | setup.py | 12 | ||||
-rw-r--r-- | setuptools/cli-32.exe | bin | 69632 -> 65536 bytes | |||
-rw-r--r-- | setuptools/cli-64.exe | bin | 75264 -> 74752 bytes | |||
-rw-r--r-- | setuptools/cli-arm-32.exe | bin | 0 -> 69120 bytes | |||
-rw-r--r-- | setuptools/cli.exe | bin | 69632 -> 65536 bytes | |||
-rwxr-xr-x | setuptools/command/easy_install.py | 32 | ||||
-rw-r--r-- | setuptools/gui-32.exe | bin | 65536 -> 65536 bytes | |||
-rw-r--r-- | setuptools/gui-64.exe | bin | 75264 -> 75264 bytes | |||
-rw-r--r-- | setuptools/gui-arm-32.exe | bin | 0 -> 69120 bytes | |||
-rw-r--r-- | setuptools/gui.exe | bin | 65536 -> 65536 bytes | |||
-rwxr-xr-x | setuptools/package_index.py | 33 | ||||
-rw-r--r-- | setuptools/py24compat.py | 11 | ||||
-rw-r--r--[-rwxr-xr-x] | setuptools/site-patch.py (renamed from site.py) | 0 | ||||
-rw-r--r-- | setuptools/tests/test_sdist.py | 27 | ||||
-rw-r--r-- | setuptools/tests/win_script_wrapper.txt | 85 |
26 files changed, 355 insertions, 113 deletions
@@ -48,3 +48,13 @@ 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 +b57e5ba934767dd498669b17551678081b3047b5 0.6.46 +ee2c967017024197b38e39ced852808265387a4b 0.6.47 +cae9127e0534fc46d7ddbc11f68dc88fd9311459 0.6.48 diff --git a/.travis.yml b/.travis.yml index cbc671e7..83efa5a4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,5 +4,6 @@ python: - 2.6 - 2.7 - 3.2 + - 3.3 # command to run tests script: python setup.py test diff --git a/CHANGES.txt b/CHANGES.txt index c22effd5..67430518 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -3,7 +3,7 @@ CHANGES ======= ------ -next.. +0.6.49 ------ * Move warning check in ``get_cache_path`` to follow the directory creation @@ -11,6 +11,13 @@ next.. reported in #375. ------ +0.6.48 +------ + +* Correct AttributeError in ``ResourceManager.get_cache_path`` introduced in + 0.6.46 (redo). + +------ 0.6.47 ------ @@ -26,13 +33,62 @@ next.. world-writable. ------ +0.6.45 +------ + +* Issue #379: ``distribute_setup.py`` now traps VersionConflict as well, + restoring ability to upgrade from an older setuptools version. + +------ +0.6.44 +------ + +* ``distribute_setup.py`` has been updated to allow Setuptools 0.7 to + satisfy use_setuptools. + +------ +0.6.43 +------ + +* Issue #378: Restore support for Python 2.4 Syntax (regression in 0.6.42). + +------ +0.6.42 +------ + +* External links finder no longer yields duplicate links. +* Issue #337: Moved site.py to setuptools/site-patch.py (graft of very old + patch from setuptools trunk which inspired PR #31). + +------ +0.6.41 +------ + +* Issue #27: Use public api for loading resources from zip files rather than + the private method `_zip_directory_cache`. +* Added a new function ``easy_install.get_win_launcher`` which may be used by + third-party libraries such as buildout to get a suitable script launcher. + +------ +0.6.40 +------ + +* Issue #376: brought back cli.exe and gui.exe that were deleted in the + previous release. + +------ 0.6.39 ------ +* Add support for console launchers on ARM platforms. +* Fix possible issue in GUI launchers where the subsystem was not supplied to + the linker. +* Launcher build script now refactored for robustness. * Issue #375: Resources extracted from a zip egg to the file system now also check the contents of the file against the zip contents during each invocation of get_resource_filename. +------ 0.6.38 ------ @@ -63,6 +119,7 @@ next.. 0.6.35 ------ + Note this release is backward-incompatible with distribute 0.6.23-0.6.34 in how it parses version numbers. diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt index 22c90aba..d6aa151d 100644 --- a/CONTRIBUTORS.txt +++ b/CONTRIBUTORS.txt @@ -8,6 +8,8 @@ Contributors * Christophe Combelles * Daniel Stutzbach * Daniel Holth +* Dirley Rodrigues +* Grigory Petrov * Hanno Schlichting * Jannis Leidel * Jason R. Coombs @@ -20,6 +22,7 @@ Contributors * Noufal Ibrahim * Pete Hollobon * Philip Jenvey +* Philip Thiem * Reinout van Rees * Robert Myers * Stefan H. Holek @@ -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.39.tar.gz - $ tar -xzvf distribute-0.6.39.tar.gz - $ cd distribute-0.6.39 + $ curl -O http://pypi.python.org/packages/source/d/distribute/distribute-0.6.49.tar.gz + $ tar -xzvf distribute-0.6.49.tar.gz + $ cd distribute-0.6.49 $ 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 diff --git a/distribute_setup.py b/distribute_setup.py index f9dc2d74..3553b213 100644 --- a/distribute_setup.py +++ b/distribute_setup.py @@ -49,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.39" +DEFAULT_VERSION = "0.6.49" DEFAULT_URL = "http://pypi.python.org/packages/source/d/distribute/" SETUPTOOLS_FAKED_VERSION = "0.6c11" @@ -144,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() diff --git a/docs/conf.py b/docs/conf.py index fc60a008..4146dcaa 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -48,9 +48,9 @@ copyright = u'2009-2011, The fellowship of the packaging' # built documents. # # The short X.Y version. -version = '0.6.39' +version = '0.6.49' # The full version, including alpha/beta/rc tags. -release = '0.6.39' +release = '0.6.49' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. @@ -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 diff --git a/msvc-build-launcher.cmd b/msvc-build-launcher.cmd index 3666d723..e54c4f6c 100644 --- a/msvc-build-launcher.cmd +++ b/msvc-build-launcher.cmd @@ -1,15 +1,55 @@ @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%
+
diff --git a/pkg_resources.py b/pkg_resources.py index 025a1162..41c73d42 100644 --- a/pkg_resources.py +++ b/pkg_resources.py @@ -13,7 +13,7 @@ The package resource API is designed to work with normal filesystem packages, method. """ -import sys, os, zipimport, time, re, imp, types +import sys, os, time, re, imp, types, zipfile, zipimport import warnings import stat from urlparse import urlparse, urlunparse @@ -1376,6 +1376,37 @@ class EmptyProvider(NullProvider): empty_provider = EmptyProvider() +def build_zipmanifest(path): + """ + This builds a similar dictionary to the zipimport directory + caches. However instead of tuples, ZipInfo objects are stored. + + The translation of the tuple is as follows: + * [0] - zipinfo.filename on stock pythons this needs "/" --> os.sep + on pypy it is the same (one reason why distribute did work + in some cases on pypy and win32). + * [1] - zipinfo.compress_type + * [2] - zipinfo.compress_size + * [3] - zipinfo.file_size + * [4] - len(utf-8 encoding of filename) if zipinfo & 0x800 + len(ascii encoding of filename) otherwise + * [5] - (zipinfo.date_time[0] - 1980) << 9 | + zipinfo.date_time[1] << 5 | zipinfo.date_time[2] + * [6] - (zipinfo.date_time[3] - 1980) << 11 | + zipinfo.date_time[4] << 5 | (zipinfo.date_time[5] // 2) + * [7] - zipinfo.CRC + """ + zipinfo = dict() + zfile = zipfile.ZipFile(path) + #Got ZipFile has not __exit__ on python 3.1 + try: + for zitem in zfile.namelist(): + zpath = zitem.replace('/', os.sep) + zipinfo[zpath] = zfile.getinfo(zitem) + assert zipinfo[zpath] is not None + finally: + zfile.close() + return zipinfo class ZipProvider(EggProvider): @@ -1385,7 +1416,7 @@ class ZipProvider(EggProvider): def __init__(self, module): EggProvider.__init__(self,module) - self.zipinfo = zipimport._zip_directory_cache[self.loader.archive] + self.zipinfo = build_zipmanifest(self.loader.archive) self.zip_pre = self.loader.archive+os.sep def _zipinfo_name(self, fspath): @@ -1421,11 +1452,9 @@ class ZipProvider(EggProvider): @staticmethod def _get_date_and_size(zip_stat): - t,d,size = zip_stat[5], zip_stat[6], zip_stat[3] - date_time = ( - (d>>9)+1980, (d>>5)&0xF, d&0x1F, # ymd - (t&0xFFFF)>>11, (t>>5)&0x3F, (t&0x1F) * 2, 0, 0, -1 # hms, etc. - ) + size = zip_stat.file_size + date_time = zip_stat.date_time + (0, 0, -1) # ymdhms+wday, yday, dst + #1980 offset already done timestamp = time.mktime(date_time) return timestamp, size @@ -1637,7 +1666,7 @@ class EggMetadata(ZipProvider): def __init__(self, importer): """Create a metadata provider from a zipimporter""" - self.zipinfo = zipimport._zip_directory_cache[importer.archive] + self.zipinfo = build_zipmanifest(importer.archive) self.zip_pre = importer.archive+os.sep self.loader = importer if importer.prefix: @@ -2868,3 +2897,4 @@ run_main = run_script # backward compatibility add_activation_listener(lambda dist: dist.activate()) working_set.entries=[]; map(working_set.add_entry,sys.path) # match order + @@ -22,7 +22,9 @@ try: except Exception: pass -VERSION = '0.6.39' +VERSION = '0.6.49' +PACKAGE_INDEX = 'https://pypi.python.org/pypi' +PACKAGE_INDEX = 'https://pypi.python.org/pypi' def get_next_version(): digits = map(int, VERSION.split('.')) @@ -67,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}' @@ -101,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'): @@ -117,10 +119,15 @@ def do_release(): 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() @@ -152,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(): @@ -46,7 +46,7 @@ exec(init_file.read(), d) init_file.close() SETUP_COMMANDS = d['__all__'] -VERSION = "0.6.39" +VERSION = "0.6.49" from setuptools import setup, find_packages from setuptools.command.build_py import build_py as _build_py @@ -158,20 +158,18 @@ dist = setup( test_suite = 'setuptools.tests', src_root = src_root, packages = find_packages(), - package_data = {'setuptools':['*.exe'], 'setuptools.command':['*.xml']}, + 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", @@ -192,7 +190,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", @@ -203,7 +200,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": @@ -211,7 +207,7 @@ dist = setup( "setuptools.installation": ['eggsecutable = setuptools.command.easy_install:bootstrap'], - }, + }, classifiers = textwrap.dedent(""" diff --git a/setuptools/cli-32.exe b/setuptools/cli-32.exe Binary files differindex 9b7717b7..b1487b78 100644 --- a/setuptools/cli-32.exe +++ b/setuptools/cli-32.exe diff --git a/setuptools/cli-64.exe b/setuptools/cli-64.exe Binary files differindex 265585af..675e6bf3 100644 --- a/setuptools/cli-64.exe +++ b/setuptools/cli-64.exe diff --git a/setuptools/cli-arm-32.exe b/setuptools/cli-arm-32.exe Binary files differnew file mode 100644 index 00000000..2f40402d --- /dev/null +++ b/setuptools/cli-arm-32.exe diff --git a/setuptools/cli.exe b/setuptools/cli.exe Binary files differindex 9b7717b7..b1487b78 100644 --- a/setuptools/cli.exe +++ b/setuptools/cli.exe diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py index dc851d1e..77b0bc31 100755 --- a/setuptools/command/easy_install.py +++ b/setuptools/command/easy_install.py @@ -19,6 +19,7 @@ import zipfile import re import stat import random +import platform from glob import glob import pkg_resources from setuptools import Command, _dont_write_bytecode @@ -1276,7 +1277,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): @@ -1832,24 +1833,22 @@ 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(): @@ -1865,6 +1864,23 @@ def get_script_args(dist, executable=sys_executable, wininst=False): # 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: diff --git a/setuptools/gui-32.exe b/setuptools/gui-32.exe Binary files differindex 3f64af7d..f8d35096 100644 --- a/setuptools/gui-32.exe +++ b/setuptools/gui-32.exe diff --git a/setuptools/gui-64.exe b/setuptools/gui-64.exe Binary files differindex 3ab4378e..330c51a5 100644 --- a/setuptools/gui-64.exe +++ b/setuptools/gui-64.exe diff --git a/setuptools/gui-arm-32.exe b/setuptools/gui-arm-32.exe Binary files differnew file mode 100644 index 00000000..537aff37 --- /dev/null +++ b/setuptools/gui-arm-32.exe diff --git a/setuptools/gui.exe b/setuptools/gui.exe Binary files differindex 3f64af7d..f8d35096 100644 --- a/setuptools/gui.exe +++ b/setuptools/gui.exe diff --git a/setuptools/package_index.py b/setuptools/package_index.py index 0ee21e3b..b0388628 100755 --- a/setuptools/package_index.py +++ b/setuptools/package_index.py @@ -1,5 +1,6 @@ """PyPI and direct package downloading""" import sys, os.path, re, urlparse, urllib, urllib2, shutil, random, socket, cStringIO +import itertools import base64 import httplib from pkg_resources import * @@ -11,6 +12,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 @@ -134,9 +137,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""" @@ -154,6 +186,7 @@ def find_external_links(url, page): if match: yield urlparse.urljoin(url, htmldecode(match.group(1))) + user_agent = "Python-urllib/%s distribute/%s" % ( sys.version[:3], require('distribute')[0].version ) diff --git a/setuptools/py24compat.py b/setuptools/py24compat.py new file mode 100644 index 00000000..c5d7d204 --- /dev/null +++ b/setuptools/py24compat.py @@ -0,0 +1,11 @@ +""" +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 diff --git a/site.py b/setuptools/site-patch.py index a7166f14..a7166f14 100755..100644 --- a/site.py +++ b/setuptools/site-patch.py diff --git a/setuptools/tests/test_sdist.py b/setuptools/tests/test_sdist.py index a9d5d6e5..f51d4567 100644 --- a/setuptools/tests/test_sdist.py +++ b/setuptools/tests/test_sdist.py @@ -337,10 +337,16 @@ class TestSdistTest(unittest.TestCase): filename = decompose(filename) if sys.version_info >= (3,): - if sys.platform == 'win32': - # Python 3 mangles the UTF-8 filename - filename = filename.decode('cp1252') - self.assertTrue(filename in cmd.filelist.files) + fs_enc = sys.getfilesystemencoding() + + if sys.platform == 'win32': + if fs_enc == 'cp1252': + # Python 3 mangles the UTF-8 filename + filename = filename.decode('cp1252') + self.assertTrue(filename in cmd.filelist.files) + else: + filename = filename.decode('mbcs') + self.assertTrue(filename in cmd.filelist.files) else: filename = filename.decode('utf-8') self.assertTrue(filename in cmd.filelist.files) @@ -357,6 +363,7 @@ class TestSdistTest(unittest.TestCase): # Latin-1 filename filename = os.path.join(b('sdist_test'), LATIN1_FILENAME) open(filename, 'w').close() + self.assertTrue(os.path.isfile(filename)) quiet() try: @@ -365,12 +372,20 @@ class TestSdistTest(unittest.TestCase): unquiet() if sys.version_info >= (3,): - filename = filename.decode('latin-1') + #not all windows systems have a default FS encoding of cp1252 if sys.platform == 'win32': - # Latin-1 is similar to Windows-1252 + # Latin-1 is similar to Windows-1252 however + # on mbcs filesys it is not in latin-1 encoding + fs_enc = sys.getfilesystemencoding() + if fs_enc == 'mbcs': + filename = filename.decode('mbcs') + else: + filename = filename.decode('latin-1') + self.assertTrue(filename in cmd.filelist.files) else: # The Latin-1 filename should have been skipped + filename = filename.decode('latin-1') self.assertFalse(filename in cmd.filelist.files) else: # No conversion takes place under Python 2 and the file diff --git a/setuptools/tests/win_script_wrapper.txt b/setuptools/tests/win_script_wrapper.txt index 9f7c81d6..db1daf6b 100644 --- a/setuptools/tests/win_script_wrapper.txt +++ b/setuptools/tests/win_script_wrapper.txt @@ -17,15 +17,15 @@ 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') - >>> f.write( + >>> bytes_written = f.write( ... """#!%(python_exe)s ... import sys ... input = repr(sys.stdin.read()) - ... print sys.argv[0][-14:] - ... print sys.argv[1:] - ... print input + ... print(sys.argv[0][-14:]) + ... print(sys.argv[1:]) + ... print(input) ... if __debug__: - ... print 'non-optimized' + ... print('non-optimized') ... """ % dict(python_exe=nt_quote_arg(sys.executable))) >>> f.close() @@ -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') - >>> f.write( - ... pkg_resources.resource_string('setuptools', 'cli.exe') + >>> bytes_written = f.write( + ... pkg_resources.resource_string('setuptools', 'cli-32.exe') ... ) >>> f.close() @@ -49,16 +49,37 @@ GUI programs, the suffix '-script-pyw' is added.) This is why we named out script the way we did. Now we can run out script by running the wrapper: - >>> import os - >>> input, output = os.popen4('"'+nt_quote_arg(os.path.join(sample_directory, 'foo.exe')) - ... + r' arg1 "arg 2" "arg \"2\\\"" "arg 4\\" "arg5 a\\b"') - >>> input.write('hello\nworld\n') + >>> from subprocess import Popen, PIPE, STDOUT + >>> try: + ... unicode=unicode + ... except: + ... unicode=str + >>> def popen4(cmd, *args): + ... if hasattr(os, 'popen4'): + ... input, output = os.popen4(cmd + " ".join(args)) + ... return input, output + ... else: + ... #emulate popen4 in python 3 + ... if cmd[0] == '"' and cmd[-1] != '"': + ... cmd = cmd[1:] + ... cmd += " ".join(args) + ... p = Popen(cmd, shell=True, bufsize=0, + ... stdin=PIPE, stdout=PIPE, stderr=STDOUT) + ... return p.stdin, p.stdout + + >>> input, output = popen4('"' + nt_quote_arg(os.path.join(sample_directory, 'foo.exe')), + ... r' arg1', r'"arg 2"', r'"arg \"2\\\""', r'"arg 4\\"', r'"arg5 a\\b"') + >>> bytes_written = input.write('hello\nworld\n'.encode('utf-8')) >>> input.close() - >>> print output.read(), + >>> # This is needed for line ending differences between py2 and py3 on win32 + >>> msg = unicode(output.read(), encoding='utf-8').split("\n") + >>> for line in msg: + ... print(line.strip()) \foo-script.py ['arg1', 'arg 2', 'arg "2\\"', 'arg 4\\', 'arg5 a\\\\b'] 'hello\nworld\n' non-optimized + <BLANKLINE> This example was a little pathological in that it exercised windows (MS C runtime) quoting rules: @@ -82,26 +103,30 @@ 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') - >>> f.write( - ... """#!%(python_exe)s -Oi + >>> bytes_written = f.write( + ... """#!%(python_exe)s -Oi ... import sys ... input = repr(sys.stdin.read()) - ... print sys.argv[0][-14:] - ... print sys.argv[1:] - ... print input + ... print(sys.argv[0][-14:]) + ... print(sys.argv[1:]) + ... print(input) ... if __debug__: - ... print 'non-optimized' + ... print('non-optimized') ... sys.ps1 = '---' ... """ % dict(python_exe=nt_quote_arg(sys.executable))) >>> f.close() - >>> input, output = os.popen4(nt_quote_arg(os.path.join(sample_directory, 'foo.exe'))) + >>> input, output = popen4(nt_quote_arg(os.path.join(sample_directory, 'foo.exe'))) >>> input.close() - >>> print output.read(), + >>> # This is needed for line ending differences between py2 and py3 on win32 + >>> msg = unicode(output.read(), encoding='utf-8').split("\n") + >>> for line in msg: + ... print(line.strip()) \foo-script.py [] '' --- + <BLANKLINE> Testing the GUI Version ----------------------- @@ -112,11 +137,11 @@ 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') - >>> f.write( + >>> bytes_written = f.write( ... """#!%(python_exe)s ... import sys ... f = open(sys.argv[1], 'wb') - ... f.write(repr(sys.argv[2])) + ... bytes_written = f.write(repr(sys.argv[2]).encode('utf-8')) ... f.close() ... """ % dict(python_exe=nt_quote_arg(sys.executable))) >>> f.close() @@ -125,21 +150,23 @@ 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') - >>> f.write( - ... pkg_resources.resource_string('setuptools', 'gui.exe') + >>> bytes_written = f.write( + ... pkg_resources.resource_string('setuptools', 'gui-32.exe') ... ) >>> f.close() Finally, we'll run the script and check the result: - >>> import os - >>> input, output = os.popen4('"'+nt_quote_arg(os.path.join(sample_directory, 'bar.exe')) - ... + r' "%s" "Test Argument"' % os.path.join(sample_directory, 'test_output.txt')) + >>> input, output = popen4('"'+nt_quote_arg(os.path.join(sample_directory, 'bar.exe')), + ... r' "%s" "Test Argument"' % os.path.join(sample_directory, 'test_output.txt')) >>> input.close() - >>> print output.read() + >>> # This is needed for line ending differences between py2 and py3 on win32 + >>> msg = unicode(output.read(), encoding='utf-8').split("\n") + >>> for line in msg: + ... print(line.strip()) <BLANKLINE> >>> f = open(os.path.join(sample_directory, 'test_output.txt'), 'rb') - >>> print f.read() + >>> print(unicode(f.read(), encoding='utf-8')) 'Test Argument' >>> f.close() |