Commit 2faf1e9a authored by Jason R. Coombs's avatar Jason R. Coombs

Merge changes from distribute 0.6.41

--HG--
rename : distribute_setup.py => ez_setup.py
parents efc915b3 cf2a2832
......@@ -50,3 +50,5 @@ be6f65eea9c10ce78b6698d8c220b6e5de577292 0.6.37
f0d502a83f6c83ba38ad21c15a849c2daf389ec7 0.6.38
d737b2039c5f92af8000f78bbc80b6a5183caa97 0.6.39
9b2e2aa06e058c63e06c5e42a7f279ddae2dfb7d 0.7b1
0a783fa0dceb95b5fc743e47c2d89c1523d0afb7 0.6.40
ad107e9b4beea24516ac4e1e854696e586fe279d 0.6.41
......@@ -20,6 +20,22 @@ Added several features that were slated for setuptools 0.6c12:
* Added support for SSL certificate validation when installing packages from
an HTTPS service.
------
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
------
......
......@@ -22,6 +22,7 @@ Contributors
* Pete Hollobon
* Phillip J. Eby
* Philip Jenvey
* Philip Thiem
* Reinout van Rees
* Robert Myers
* Stefan H. Holek
......
......@@ -19,6 +19,12 @@ if "%ERRORLEVEL%"=="0" (
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 Use the x86_amd64 profile, which is the 32-bit cross compiler for amd64
call VCVARSx86_amd64
......
......@@ -13,7 +13,7 @@ The package resource API is designed to work with normal filesystem packages,
method.
"""
import sys, os, zipimport, time, re, imp
import sys, os, time, re, imp, types, zipfile, zipimport
from urlparse import urlparse, urlunparse
try:
......@@ -1464,6 +1464,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):
......@@ -1473,7 +1504,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):
......@@ -1509,11 +1540,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
......@@ -1725,7 +1754,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:
......@@ -2912,3 +2941,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
......@@ -67,7 +67,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 +101,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'):
......@@ -157,14 +157,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():
......
......@@ -1832,26 +1832,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 platform.machine().lower()=='arm':
launcher = launcher.replace(".", "-arm.")
if is_64bit():
launcher = launcher.replace(".", "-64.")
else:
launcher = launcher.replace(".", "-32.")
if os.path.exists(new_header[2:-1].strip('"')) 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():
......@@ -1867,6 +1863,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:
......
......@@ -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
......
......@@ -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,7 +37,7 @@ 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(
>>> 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(
>>> 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(
>>> 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()
......
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