Commit a6e7ef0a authored by Philip Thiem's avatar Philip Thiem

Merge with default

--HG--
extra : rebase_source : 15517dca4272e2b088930cb5599f5822cef13bae
parents 37c48a4d 70067439
......@@ -65,3 +65,25 @@ d04c05f035e3a5636006fc34f4be7e6c77035d17 0.7.2
d212e48e0cef689acba57ed017289c027660b23c 0.7.3
74c6c12268059986f9cc0b535399594f1d131201 0.8b1
85640475dda0621f20e11db0995fa07f51744a98 0.7.4
b57e5ba934767dd498669b17551678081b3047b5 0.6.46
dd5bbc116c53d3732d22f983e7ca6d8cfabd3b08 0.7.5
512744f3f306aea0fdde4cfd600af8b2d6e773e7 0.8b2
8af9839a76407eebf3610fcd3e7973f1625abaa2 0.8b3
ee2c967017024197b38e39ced852808265387a4b 0.6.47
48d3d26cbea68e21c96e51f01092e8fdead5cd60 0.7.6
5b3c7981a02b4a86af1b10ae16492899b515d485 0.8b4
cae9127e0534fc46d7ddbc11f68dc88fd9311459 0.6.48
1506fa538fff01e70424530a32a44e070720cf3c 0.7.7
5679393794978a1d3e1e087472b8a0fdf3d8423c 0.8b5
26f59ec0f0f69714d28a891aaad048e3b9fcd6f7 0.8b6
f657df1f1ed46596d236376649c99a470662b4ba 0.6.49
236de1de68b14230036147c7c9e7c09b215b53ee 0.7.8
979d598822bc64b05fb177a2ba221e75ee5b44d3 0.8b7
e3d70539e79f39a97f69674ab038661961a1eb43 0.8
3078b1e566399bf0c5590f3528df03d0c23a0777 0.9
9e5a8f734662dd36e6fd6e4ba9031d0e2d294632 0.9.1
37444bb32e172aaacbc0aeafdf5a778ee471723d 0.9.2
3e9d2e89de3aa499382d6be2ec8b64d2a29f7f13 0.9.3
1aef141fc968113e4c521d1edf6ea863c4ff7e00 0.9.4
88e3d6788facbb2dd6467a23c4f35529a5ce20a1 0.9.5
acc6c5d61d0f82040c237ac7ea010c0fc9e67d66 0.9.6
This diff is collapsed.
......@@ -9,6 +9,7 @@ Contributors
* Daniel Stutzbach
* Daniel Holth
* Dirley Rodrigues
* Donald Stufft
* Grigory Petrov
* Hanno Schlichting
* Jannis Leidel
......
......@@ -29,7 +29,7 @@ The recommended way to install setuptools on Windows is to download
`ez_setup.py`_ and run it. The script will download the appropriate .egg
file and install it for you.
.. _ez_setup.py: https://bitbucket.org/pypa/setuptools/raw/0.8/ez_setup.py
.. _ez_setup.py: https://bitbucket.org/pypa/setuptools/raw/bootstrap/ez_setup.py
For best results, uninstall previous versions FIRST (see `Uninstalling`_).
......@@ -45,7 +45,7 @@ Unix-based Systems including Mac OS X
Download `ez_setup.py`_ and run it using the target Python version. The script
will download the appropriate version and install it for you::
> wget https://bitbucket.org/pypa/setuptools/raw/0.8/ez_setup.py -O - | python
> wget https://bitbucket.org/pypa/setuptools/raw/bootstrap/ez_setup.py -O - | python
Note that you will may need to invoke the command with superuser privileges to
install to the system Python.
......@@ -53,7 +53,7 @@ install to the system Python.
Alternatively, on Python 2.6 and later, Setuptools may be installed to a
user-local path::
> wget https://bitbucket.org/pypa/setuptools/raw/0.8/ez_setup.py
> wget https://bitbucket.org/pypa/setuptools/raw/bootstrap/ez_setup.py
> python ez_setup.py --user
......@@ -66,7 +66,7 @@ tarball from `Setuptools on PyPI <https://pypi.python.org/pypi/setuptools>`_
and run setup.py with any supported distutils and Setuptools options.
For example::
setuptools-0.8$ python setup.py --prefix=/opt/setuptools
setuptools-x.x$ python setup.py --prefix=/opt/setuptools
Use ``--help`` to get a full options list, but we recommend consulting
the `EasyInstall manual`_ for detailed instructions, especially `the section
......@@ -157,7 +157,7 @@ Credits
aspects of ``easy_install``, and supplied the doctests for the command-line
``.exe`` wrappers on Windows.
* Phillip J. Eby is the principal author and maintainer of setuptools, and
* Phillip J. Eby is the seminal author of setuptools, and
first proposed the idea of an importable binary distribution format for
Python application plug-ins.
......@@ -167,4 +167,8 @@ Credits
"Code Bear" Taylor) contributed their time and stress as guinea pigs for the
use of eggs and setuptools, even before eggs were "cool". (Thanks, guys!)
* Since the merge with Distribute, Jason R. Coombs is the
maintainer of setuptools. The project is maintained in coordination with
the Python Packaging Authority (PyPA) and the larger Python community.
.. _files:
......@@ -49,6 +49,10 @@ _VARS = {'sys.platform': sys.platform,
'extra': None # wheel extension
}
for var in list(_VARS.keys()):
if '.' in var:
_VARS[var.replace('.', '_')] = _VARS[var]
def default_environment():
"""Return copy of default PEP 385 globals dictionary."""
return dict(_VARS)
......
......@@ -15,6 +15,7 @@
# serve to show the default.
import sys, os
import setuptools
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
......@@ -48,9 +49,9 @@ copyright = '2009-2013, The fellowship of the packaging'
# built documents.
#
# The short X.Y version.
version = '0.8'
version = setuptools.__version__
# The full version, including alpha/beta/rc tags.
release = '0.8'
release = setuptools.__version__
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
......
......@@ -28,7 +28,7 @@ try:
except ImportError:
USER_SITE = None
DEFAULT_VERSION = "0.8"
DEFAULT_VERSION = "0.9.7"
DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/"
def _python_cmd(*args):
......@@ -100,6 +100,12 @@ def _do_download(version, download_base, to_dir, download_delay):
to_dir, download_delay)
_build_egg(egg, tarball, to_dir)
sys.path.insert(0, egg)
# Remove previously-imported pkg_resources if present (see
# https://bitbucket.org/pypa/setuptools/pull-request/7/ for details).
if 'pkg_resources' in sys.modules:
del sys.modules['pkg_resources']
import setuptools
setuptools.bootstrap_install_from = egg
......
......@@ -14,6 +14,8 @@ method.
"""
import sys, os, time, re, imp, types, zipfile, zipimport
import warnings
import stat
try:
from urlparse import urlparse, urlunparse
except ImportError:
......@@ -26,7 +28,7 @@ except NameError:
try:
basestring
next = lambda o: o.next()
from cStringIO import StringIO
from cStringIO import StringIO as BytesIO
def exec_(code, globs=None, locs=None):
if globs is None:
frame = sys._getframe(1)
......@@ -39,7 +41,7 @@ try:
exec("""exec code in globs, locs""")
except NameError:
basestring = str
from io import StringIO
from io import BytesIO
exec_ = eval("exec")
def execfile(fn, globs=None, locs=None):
if globs is None:
......@@ -1022,9 +1024,34 @@ variable to point to an accessible directory.
except:
self.extraction_error()
self._warn_unsafe_extraction_path(extract_path)
self.cached_files[target_path] = 1
return target_path
@staticmethod
def _warn_unsafe_extraction_path(path):
"""
If the default extraction path is overridden and set to an insecure
location, such as /tmp, it opens up an opportunity for an attacker to
replace an extracted file with an unauthorized payload. Warn the user
if a known insecure location is used.
See Distribute #375 for more details.
"""
if os.name == 'nt' and not path.startswith(os.environ['windir']):
# On Windows, permissions are generally restrictive by default
# and temp directories are not writable by other users, so
# bypass the warning.
return
mode = os.stat(path).st_mode
if mode & stat.S_IWOTH or mode & stat.S_IWGRP:
msg = ("%s is writable by group/others and vulnerable to attack "
"when "
"used with get_resource_filename. Consider a more secure "
"location (set with .set_extraction_path or the "
"PYTHON_EGG_CACHE environment variable)." % path)
warnings.warn(msg, UserWarning)
......@@ -1376,7 +1403,7 @@ class NullProvider:
return self._fn(self.module_path, resource_name)
def get_resource_stream(self, manager, resource_name):
return StringIO(self.get_resource_string(manager, resource_name))
return BytesIO(self.get_resource_string(manager, resource_name))
def get_resource_string(self, manager, resource_name):
return self._get(self._fn(self.module_path, resource_name))
......@@ -1946,15 +1973,6 @@ def find_in_zip(importer, path_item, only=False):
register_finder(zipimport.zipimporter, find_in_zip)
def StringIO(*args, **kw):
"""Thunk to load the real StringIO on demand"""
global StringIO
try:
from cStringIO import StringIO
except ImportError:
from io import StringIO
return StringIO(*args,**kw)
def find_nothing(importer, path_item, only=False):
return ()
register_finder(object,find_nothing)
......
#!/usr/bin/env python
"""
Script to fully automate the release process. Requires Python 2.6+
with sphinx installed and the 'hg' command on the path.
Setuptools is released using 'jaraco.packaging.release'. To make a release,
install jaraco.packaging and run 'python -m jaraco.packaging.release'
"""
from __future__ import print_function
import subprocess
import shutil
import os
import sys
import getpass
import collections
import itertools
import re
import os
import subprocess
try:
import urllib.request as urllib_request
except ImportError:
import urllib2 as urllib_request
try:
input = raw_input
except NameError:
pass
try:
import keyring
except Exception:
pass
VERSION = '0.8'
PACKAGE_INDEX = 'https://pypi.python.org/pypi'
def set_versions():
global VERSION
version = input("Release as version [%s]> " % VERSION) or VERSION
if version != VERSION:
VERSION = bump_versions(version)
def infer_next_version(version):
"""
Infer a next version from the current version by incrementing the last
number or appending a number.
>>> infer_next_version('1.0')
'1.1'
>>> infer_next_version('1.0b')
'1.0b1'
>>> infer_next_version('1.0.9')
'1.0.10'
>>> infer_next_version('1')
'2'
>>> infer_next_version('')
'1'
"""
def incr(match):
ver = int(match.group(0) or '0')
return str(ver + 1)
return re.sub('\d*$', incr, version)
def before_upload():
_linkify('CHANGES.txt', 'CHANGES (links).txt')
_add_bootstrap_bookmark()
files_with_versions = (
'docs/conf.py', 'setup.py', 'release.py', 'ez_setup.py', 'README.txt',
'setuptools/__init__.py',
'ez_setup.py', 'setuptools/__init__.py',
)
def get_repo_name():
"""
Get the repo name from the hgrc default path.
"""
default = subprocess.check_output('hg paths default').strip()
parts = default.split('/')
if parts[-1] == '':
parts.pop()
return '/'.join(parts[-2:])
def get_mercurial_creds(system='https://bitbucket.org', username=None):
"""
Return named tuple of username,password in much the same way that
Mercurial would (from the keyring).
"""
# todo: consider getting this from .hgrc
username = username or getpass.getuser()
keyring_username = '@@'.join((username, system))
system = 'Mercurial'
password = (
keyring.get_password(system, keyring_username)
if 'keyring' in globals()
else None
)
if not password:
password = getpass.getpass()
Credential = collections.namedtuple('Credential', 'username password')
return Credential(username, password)
def add_milestone_and_version(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}'
.format(repo = get_repo_name(), type=type))
req = urllib_request.Request(url = url, headers = headers,
data='name='+version)
try:
urllib_request.urlopen(req)
except urllib_request.HTTPError as e:
print(e.fp.read())
def bump_versions(target_ver):
for filename in files_with_versions:
bump_version(filename, target_ver)
subprocess.check_call(['hg', 'ci', '-m',
'Bumped to {target_ver} in preparation for next '
'release.'.format(**vars())])
return target_ver
def bump_version(filename, target_ver):
with open(filename, 'rb') as f:
lines = [
line.replace(VERSION.encode('ascii'), target_ver.encode('ascii'))
for line in f
]
with open(filename, 'wb') as f:
f.writelines(lines)
def do_release():
assert all(map(os.path.exists, files_with_versions)), (
"Expected file(s) missing")
assert has_sphinx(), "You must have Sphinx installed to release"
set_versions()
res = raw_input('Have you read through the SCM changelog and '
'confirmed the changelog is current for releasing {VERSION}? '
.format(**globals()))
if not res.lower().startswith('y'):
print("Please do that")
raise SystemExit(1)
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'):
print("Please do that")
raise SystemExit(2)
subprocess.check_call(['hg', 'tag', VERSION])
subprocess.check_call(['hg', 'update', VERSION])
upload_to_pypi()
# update to the tip for the next operation
subprocess.check_call(['hg', 'update'])
# we just tagged the current version, bump for the next release.
next_ver = bump_versions(infer_next_version(VERSION))
# push the changes
subprocess.check_call(['hg', 'push'])
add_milestone_and_version(next_ver)
def upload_to_pypi():
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', '-r', PACKAGE_INDEX,
#'upload', '-r', PACKAGE_INDEX,
]
if has_docs:
cmd.extend([
'upload_docs', '-r', PACKAGE_INDEX
])
env = os.environ.copy()
env["SETUPTOOLS_INSTALL_WINDOWS_SPECIFIC_FILES"] = "1"
subprocess.check_call(cmd, env=env)
def has_sphinx():
try:
devnull = open(os.path.devnull, 'wb')
subprocess.Popen(['sphinx-build', '--version'], stdout=devnull,
stderr=subprocess.STDOUT).wait()
except Exception:
return False
return True
def build_docs():
if not os.path.isdir('docs'):
return
if os.path.isdir('docs/build'):
shutil.rmtree('docs/build')
cmd = [
'sphinx-build',
'-b', 'html',
'-d', 'build/doctrees',
'.',
'build/html',
]
subprocess.check_call(cmd, cwd='docs')
return True
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)
test_info = "Travis-CI tests: http://travis-ci.org/#!/jaraco/setuptools"
os.environ["SETUPTOOLS_INSTALL_WINDOWS_SPECIFIC_FILES"] = "1"
link_patterns = [
r"(Issue )?#(?P<issue>\d+)",
r"Distribute #(?P<distribute>\d+)",
r"Buildout #(?P<buildout>\d+)",
r"Old Setuptools #(?P<old_setuptools>\d+)",
r"Jython #(?P<jython>\d+)",
r"Python #(?P<python>\d+)",
]
issue_urls = dict(
issue='https://bitbucket.org/pypa/setuptools/issue/{issue}',
distribute='https://bitbucket.org/tarek/distribute/issue/{distribute}',
buildout='https://github.com/buildout/buildout/issues/{buildout}',
old_setuptools='http://bugs.python.org/setuptools/issue{old_setuptools}',
jython='http://bugs.jython.org/issue{jython}',
python='http://bugs.python.org/issue{python}',
)
bitroot = 'https://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 _linkify(source, dest):
pattern = '|'.join(link_patterns)
with open(source) as source:
out = re.sub(pattern, replacer, source.read())
with open(dest, 'w') as dest:
dest.write(out)
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)
def replacer(match):
text = match.group(0)
match_dict = match.groupdict()
for key in match_dict:
if match_dict[key]:
url = issue_urls[key].format(**match_dict)
return "`{text} <{url}>`_".format(text=text, url=url)
anchors.extend(revision.findall(text)) # ['Issue #43', ...]
return revision.sub(r'`\1`_', text)
if __name__ == '__main__':
do_release()
def _add_bootstrap_bookmark():
cmd = ['hg', 'bookmark', '-i', 'bootstrap', '-f']
subprocess.Popen(cmd)
......@@ -3,59 +3,39 @@
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__)))
src_root = None
do_2to3 = False
if sys.version_info >= (3,) and do_2to3:
tmp_src = os.path.join("build", "src")
from distutils.filelist import FileList
from distutils import dir_util, file_util, util, log
log.set_verbosity(1)
fl = FileList()
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", "ez_setup.py")
for f in fl.files:
outf, copied = file_util.copy_file(f, os.path.join(tmp_src, f), update=1)
if copied and outf.endswith(".py") and outf != dist_script:
outfiles_2to3.append(outf)
if copied and outf.endswith('api_tests.txt'):
# XXX support this in distutils as well
from lib2to3.main import main
main('lib2to3.fixes', ['-wd', os.path.join(tmp_src, 'tests', 'api_tests.txt')])
util.run_2to3(outfiles_2to3)
# arrange setup to use the copy
sys.path.insert(0, os.path.abspath(tmp_src))
src_root = tmp_src
from distutils.util import convert_path
d = {}
command_ns = {}
init_path = convert_path('setuptools/command/__init__.py')
init_file = open(init_path)
exec(init_file.read(), d)
exec(init_file.read(), command_ns)
init_file.close()
SETUP_COMMANDS = d['__all__']
VERSION = "0.8"
SETUP_COMMANDS = command_ns['__all__']
from setuptools import setup, find_packages
main_ns = {}
init_path = convert_path('setuptools/__init__.py')
init_file = open(init_path)
exec(init_file.read(), main_ns)
init_file.close()
import setuptools
from setuptools.command.build_py import build_py as _build_py
from setuptools.command.test import test as _test
scripts = []
console_scripts = ["easy_install = setuptools.command.easy_install:main"]
# Gentoo distributions manage the python-version-specific scripts themselves,
# so they define an environment variable to suppress the creation of the
# version-specific scripts.
if os.environ.get("SETUPTOOLS_DISABLE_VERSIONED_EASY_INSTALL_SCRIPT") in (None, "", "0") and \
os.environ.get("DISTRIBUTE_DISABLE_VERSIONED_EASY_INSTALL_SCRIPT") in (None, "", "0"):
console_scripts.append("easy_install-%s = setuptools.command.easy_install:main" % sys.version[:3])
......@@ -73,15 +53,6 @@ class build_py(_build_py):
outf, copied = self.copy_file(srcfile, target)
srcfile = os.path.abspath(srcfile)
# avoid a bootstrapping issue with easy_install -U (when the
# previous version doesn't have convert_2to3_doctests)
if not hasattr(self.distribution, 'convert_2to3_doctests'):
continue
if not do_2to3:
continue
if copied and srcfile in self.distribution.convert_2to3_doctests:
self.__doctests_2to3.append(outf)
class test(_test):
"""Specific test class to avoid rewriting the entry_points.txt"""
def run(self):
......@@ -126,12 +97,12 @@ if sys.platform == 'win32' or os.environ.get("SETUPTOOLS_INSTALL_WINDOWS_SPECIFI
package_data.setdefault('setuptools', []).extend(['*.exe'])
package_data.setdefault('setuptools.command', []).extend(['*.xml'])
dist = setup(
setup_params = dict(
name="setuptools",
version=VERSION,
version=main_ns['__version__'],
description="Easily download, build, install, upgrade, and uninstall "
"Python packages",
author="The fellowship of the packaging",
author="Python Packaging Authority",
author_email="distutils-sig@python.org",
license="PSF or ZPL",
long_description = long_description,
......@@ -139,7 +110,7 @@ dist = setup(
url = "https://pypi.python.org/pypi/setuptools",
test_suite = 'setuptools.tests',
src_root = src_root,
packages = find_packages(),
packages = setuptools.find_packages(),
package_data = package_data,
py_modules = ['pkg_resources', 'easy_install'],
......@@ -148,7 +119,7 @@ dist = setup(
cmdclass = {'test': test},
entry_points = {
"distutils.commands" : [
"distutils.commands": [
"%(cmd)s = setuptools.command.%(cmd)s:%(cmd)s" % locals()
for cmd in SETUP_COMMANDS
],
......@@ -228,3 +199,6 @@ dist = setup(
scripts = [],
# tests_require = "setuptools[ssl]",
)
if __name__ == '__main__':
dist = setuptools.setup(**setup_params)
[distutils.commands]
bdist_rpm = setuptools.command.bdist_rpm:bdist_rpm
rotate = setuptools.command.rotate:rotate
develop = setuptools.command.develop:develop
setopt = setuptools.command.setopt:setopt
build_py = setuptools.command.build_py:build_py
saveopts = setuptools.command.saveopts:saveopts
egg_info = setuptools.command.egg_info:egg_info
register = setuptools.command.register:register
upload_docs = setuptools.command.upload_docs:upload_docs
install_egg_info = setuptools.command.install_egg_info:install_egg_info
alias = setuptools.command.alias:alias
easy_install = setuptools.command.easy_install:easy_install
install_scripts = setuptools.command.install_scripts:install_scripts
bdist_wininst = setuptools.command.bdist_wininst:bdist_wininst
bdist_egg = setuptools.command.bdist_egg:bdist_egg
install = setuptools.command.install:install
test = setuptools.command.test:test
install_lib = setuptools.command.install_lib:install_lib
build_ext = setuptools.command.build_ext:build_ext
sdist = setuptools.command.sdist:sdist
[egg_info.writers]
dependency_links.txt = setuptools.command.egg_info:overwrite_arg
requires.txt = setuptools.command.egg_info:write_requirements
PKG-INFO = setuptools.command.egg_info:write_pkg_info
eager_resources.txt = setuptools.command.egg_info:overwrite_arg
top_level.txt = setuptools.command.egg_info:write_toplevel_names
namespace_packages.txt = setuptools.command.egg_info:overwrite_arg
entry_points.txt = setuptools.command.egg_info:write_entries
depends.txt = setuptools.command.egg_info:warn_depends_obsolete
[console_scripts]
easy_install = setuptools.command.easy_install:main
easy_install-2.5 = setuptools.command.easy_install:main
[setuptools.file_finders]
svn_cvs = setuptools.command.sdist:_default_revctrl
[distutils.setup_keywords]
dependency_links = setuptools.dist:assert_string_list
entry_points = setuptools.dist:check_entry_points
extras_require = setuptools.dist:check_extras
use_2to3_exclude_fixers = setuptools.dist:assert_string_list
package_data = setuptools.dist:check_package_data
install_requires = setuptools.dist:check_requirements
use_2to3 = setuptools.dist:assert_bool
use_2to3_fixers = setuptools.dist:assert_string_list
include_package_data = setuptools.dist:assert_bool
exclude_package_data = setuptools.dist:check_package_data
namespace_packages = setuptools.dist:check_nsp
test_suite = setuptools.dist:check_test_suite
eager_resources = setuptools.dist:assert_string_list
zip_safe = setuptools.dist:assert_bool
test_loader = setuptools.dist:check_importable
packages = setuptools.dist:check_packages
convert_2to3_doctests = setuptools.dist:assert_string_list
tests_require = setuptools.dist:check_requirements
[setuptools.installation]
eggsecutable = setuptools.command.easy_install:bootstrap
[setuptools.installation]
eggsecutable = setuptools.command.easy_install:bootstrap
[console_scripts]
easy_install = setuptools.command.easy_install:main
easy_install-3.3 = setuptools.command.easy_install:main
[distutils.setup_keywords]
use_2to3 = setuptools.dist:assert_bool
namespace_packages = setuptools.dist:check_nsp
package_data = setuptools.dist:check_package_data
use_2to3_exclude_fixers = setuptools.dist:assert_string_list
dependency_links = setuptools.dist:assert_string_list
use_2to3_fixers = setuptools.dist:assert_string_list
test_suite = setuptools.dist:check_test_suite
exclude_package_data = setuptools.dist:check_package_data
extras_require = setuptools.dist:check_extras
install_requires = setuptools.dist:check_requirements
eager_resources = setuptools.dist:assert_string_list
include_package_data = setuptools.dist:assert_bool
packages = setuptools.dist:check_packages
entry_points = setuptools.dist:check_entry_points
zip_safe = setuptools.dist:assert_bool
tests_require = setuptools.dist:check_requirements
convert_2to3_doctests = setuptools.dist:assert_string_list
test_loader = setuptools.dist:check_importable
[setuptools.file_finders]
svn_cvs = setuptools.command.sdist:_default_revctrl
[egg_info.writers]
top_level.txt = setuptools.command.egg_info:write_toplevel_names
PKG-INFO = setuptools.command.egg_info:write_pkg_info
eager_resources.txt = setuptools.command.egg_info:overwrite_arg
namespace_packages.txt = setuptools.command.egg_info:overwrite_arg
depends.txt = setuptools.command.egg_info:warn_depends_obsolete
dependency_links.txt = setuptools.command.egg_info:overwrite_arg
entry_points.txt = setuptools.command.egg_info:write_entries
requires.txt = setuptools.command.egg_info:write_requirements
[distutils.commands]
test = setuptools.command.test:test
bdist_wininst = setuptools.command.bdist_wininst:bdist_wininst
alias = setuptools.command.alias:alias
sdist = setuptools.command.sdist:sdist
develop = setuptools.command.develop:develop
bdist_egg = setuptools.command.bdist_egg:bdist_egg
setopt = setuptools.command.setopt:setopt
egg_info = setuptools.command.egg_info:egg_info
build_ext = setuptools.command.build_ext:build_ext
upload_docs = setuptools.command.upload_docs:upload_docs
easy_install = setuptools.command.easy_install:easy_install
install = setuptools.command.install:install
install_egg_info = setuptools.command.install_egg_info:install_egg_info
bdist_rpm = setuptools.command.bdist_rpm:bdist_rpm
install_lib = setuptools.command.install_lib:install_lib
rotate = setuptools.command.rotate:rotate
saveopts = setuptools.command.saveopts:saveopts
install_scripts = setuptools.command.install_scripts:install_scripts
build_py = setuptools.command.build_py:build_py
register = setuptools.command.register:register
......@@ -8,7 +8,7 @@ from distutils.util import convert_path
import os
import sys
__version__ = '0.8'
__version__ = '0.9.7'
__all__ = [
'setup', 'Distribution', 'Feature', 'Command', 'Extension', 'Require',
'find_packages'
......
# $Id$
#
# Copyright (C) 2005 Gregory P. Smith (greg@krypto.org)
# Licensed to PSF under a Contributor Agreement.
#
__doc__ = """hashlib module - A common interface to many hash functions.
new(name, string='') - returns a new hash object implementing the
given hash function; initializing the hash
using the given string data.
Named constructor functions are also available, these are much faster
than using new():
md5(), sha1(), sha224(), sha256(), sha384(), and sha512()
More algorithms may be available on your platform but the above are
guaranteed to exist.
NOTE: If you want the adler32 or crc32 hash functions they are available in
the zlib module.
Choose your hash function wisely. Some have known collision weaknesses.
sha384 and sha512 will be slow on 32 bit platforms.
Hash objects have these methods:
- update(arg): Update the hash object with the string arg. Repeated calls
are equivalent to a single call with the concatenation of all
the arguments.
- digest(): Return the digest of the strings passed to the update() method
so far. This may contain non-ASCII characters, including
NUL bytes.
- hexdigest(): Like digest() except the digest is returned as a string of
double length, containing only hexadecimal digits.
- copy(): Return a copy (clone) of the hash object. This can be used to
efficiently compute the digests of strings that share a common
initial substring.
For example, to obtain the digest of the string 'Nobody inspects the
spammish repetition':
>>> import hashlib
>>> m = hashlib.md5()
>>> m.update("Nobody inspects")
>>> m.update(" the spammish repetition")
>>> m.digest()
'\\xbbd\\x9c\\x83\\xdd\\x1e\\xa5\\xc9\\xd9\\xde\\xc9\\xa1\\x8d\\xf0\\xff\\xe9'
More condensed:
>>> hashlib.sha224("Nobody inspects the spammish repetition").hexdigest()
'a4337bc45a8fc544c03f52dc550cd6e1e87021bc896588bd79e901e2'
"""
# This tuple and __get_builtin_constructor() must be modified if a new
# always available algorithm is added.
__always_supported = ('md5', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512')
algorithms = __always_supported
__all__ = __always_supported + ('new', 'algorithms')
def __get_builtin_constructor(name):
try:
if name in ('SHA1', 'sha1'):
import _sha
return _sha.new
elif name in ('MD5', 'md5'):
import md5
return md5.new
elif name in ('SHA256', 'sha256', 'SHA224', 'sha224'):
import _sha256
bs = name[3:]
if bs == '256':
return _sha256.sha256
elif bs == '224':
return _sha256.sha224
elif name in ('SHA512', 'sha512', 'SHA384', 'sha384'):
import _sha512
bs = name[3:]
if bs == '512':
return _sha512.sha512
elif bs == '384':
return _sha512.sha384
except ImportError:
pass # no extension module, this hash is unsupported.
raise ValueError('unsupported hash type %s' % name)
def __get_openssl_constructor(name):
try:
f = getattr(_hashlib, 'openssl_' + name)
# Allow the C module to raise ValueError. The function will be
# defined but the hash not actually available thanks to OpenSSL.
f()
# Use the C function directly (very fast)
return f
except (AttributeError, ValueError):
return __get_builtin_constructor(name)
def __py_new(name, string=''):
"""new(name, string='') - Return a new hashing object using the named algorithm;
optionally initialized with a string.
"""
return __get_builtin_constructor(name)(string)
def __hash_new(name, string=''):
"""new(name, string='') - Return a new hashing object using the named algorithm;
optionally initialized with a string.
"""
try:
return _hashlib.new(name, string)
except ValueError:
# If the _hashlib module (OpenSSL) doesn't support the named
# hash, try using our builtin implementations.
# This allows for SHA224/256 and SHA384/512 support even though
# the OpenSSL library prior to 0.9.8 doesn't provide them.
return __get_builtin_constructor(name)(string)
try:
import _hashlib
new = __hash_new
__get_hash = __get_openssl_constructor
except ImportError:
new = __py_new
__get_hash = __get_builtin_constructor
for __func_name in __always_supported:
# try them all, some may not work due to the OpenSSL
# version not supporting that algorithm.
try:
globals()[__func_name] = __get_hash(__func_name)
except ValueError:
import logging
logging.exception('code for hash %s was not found.', __func_name)
# Cleanup locals()
del __always_supported, __func_name, __get_hash
del __py_new, __hash_new, __get_openssl_constructor
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -11,11 +11,8 @@ from setuptools.compat import (urllib2, httplib, StringIO, HTTPError,
url2pathname, name2codepoint,
unichr, urljoin)
from setuptools.compat import filterfalse
try:
from hashlib import md5
except ImportError:
from md5 import md5
from fnmatch import translate
from setuptools.py24compat import hashlib
from setuptools.py24compat import wraps
from setuptools.py27compat import get_all_headers
......@@ -195,6 +192,76 @@ user_agent = "Python-urllib/%s setuptools/%s" % (
sys.version[:3], require('setuptools')[0].version
)
class ContentChecker(object):
"""
A null content checker that defines the interface for checking content
"""
def feed(self, block):
"""
Feed a block of data to the hash.
"""
return
def is_valid(self):
"""
Check the hash. Return False if validation fails.
"""
return True
def report(self, reporter, template):
"""
Call reporter with information about the checker (hash name)
substituted into the template.
"""
return
class HashChecker(ContentChecker):
pattern = re.compile(
r'(?P<hash_name>sha1|sha224|sha384|sha256|sha512|md5)='
r'(?P<expected>[a-f0-9]+)'
)
def __init__(self, hash_name, expected):
self.hash = hashlib.new(hash_name)
self.expected = expected
@classmethod
def from_url(cls, url):
"Construct a (possibly null) ContentChecker from a URL"
fragment = urlparse(url)[-1]
if not fragment:
return ContentChecker()
match = cls.pattern.search(fragment)
if not match:
return ContentChecker()
return cls(**match.groupdict())
def feed(self, block):
self.hash.update(block)
def is_valid(self):
return self.hash.hexdigest() == self.expected
def _get_hash_name(self):
"""
Python 2.4 implementation of MD5 doesn't supply a .name attribute
so provide that name.
When Python 2.4 is no longer required, replace invocations of this
method with simply 'self.hash.name'.
"""
try:
return self.hash.name
except AttributeError:
if 'md5' in str(type(self.hash)):
return 'md5'
raise
def report(self, reporter, template):
msg = template % self._get_hash_name()
return reporter(msg)
class PackageIndex(Environment):
"""A distribution index that scans web pages for download URLs"""
......@@ -387,16 +454,20 @@ class PackageIndex(Environment):
def check_md5(self, cs, info, filename, tfp):
if re.match('md5=[0-9a-f]{32}$', info):
self.debug("Validating md5 checksum for %s", filename)
if cs.hexdigest() != info[4:]:
tfp.close()
os.unlink(filename)
raise DistutilsError(
"MD5 validation failed for "+os.path.basename(filename)+
"; possible download problem?"
)
def check_hash(self, checker, filename, tfp):
"""
checker is a ContentChecker
"""
checker.report(self.debug,
"Validating %%s checksum for %s" % filename)
if not checker.is_valid():
tfp.close()
os.unlink(filename)
raise DistutilsError(
"%s validation failed for %s; "
"possible download problem?" % (
checker.hash.name, os.path.basename(filename))
)
def add_find_links(self, urls):
"""Add `urls` to the list that will be prescanned for searches"""
......@@ -600,14 +671,12 @@ class PackageIndex(Environment):
# Download the file
fp, tfp, info = None, None, None
try:
if '#' in url:
url, info = url.split('#', 1)
checker = HashChecker.from_url(url)
fp = self.open_url(url)
if isinstance(fp, HTTPError):
raise DistutilsError(
"Can't download %s: %s %s" % (url, fp.code,fp.msg)
)
cs = md5()
headers = fp.info()
blocknum = 0
bs = self.dl_blocksize
......@@ -621,13 +690,13 @@ class PackageIndex(Environment):
while True:
block = fp.read(bs)
if block:
cs.update(block)
checker.feed(block)
tfp.write(block)
blocknum += 1
self.reporthook(url, filename, blocknum, bs, size)
else:
break
if info: self.check_md5(cs, info, filename, tfp)
self.check_hash(checker, filename, tfp)
return headers
finally:
if fp: fp.close()
......@@ -636,7 +705,6 @@ class PackageIndex(Environment):
def reporthook(self, url, filename, blocknum, blksize, size):
pass # no-op
def open_url(self, url, warning=None):
if url.startswith('file:'):
return local_open(url)
......
......@@ -9,3 +9,9 @@ except ImportError:
def wraps(func):
"Just return the function unwrapped"
return lambda x: x
try:
import hashlib
except ImportError:
from setuptools._backport import hashlib
......@@ -270,11 +270,11 @@ class DirectorySandbox(AbstractSandbox):
self._violation(operation, src, dst, *args, **kw)
return (src,dst)
def open(self, file, flags, mode=0x1FF): # 0777
def open(self, file, flags, mode=0x1FF, *args, **kw): # 0777
"""Called for low-level os.open()"""
if flags & WRITE_FLAGS and not self._ok(file):
self._violation("os.open", file, flags, mode)
return _os.open(file,flags,mode)
self._violation("os.open", file, flags, mode, *args, **kw)
return _os.open(file,flags,mode, *args, **kw)
WRITE_FLAGS = reduce(
operator.or_, [getattr(_os, a, 0) for a in
......
......@@ -88,9 +88,16 @@ except ImportError:
class CertificateError(ValueError):
pass
def _dnsname_to_pat(dn):
def _dnsname_to_pat(dn, max_wildcards=1):
pats = []
for frag in dn.split(r'.'):
if frag.count('*') > max_wildcards:
# Issue #17980: avoid denials of service by refusing more
# than one wildcard per fragment. A survery of established
# policy among SSL implementations showed it to be a
# reasonable choice.
raise CertificateError(
"too many wildcards in certificate DNS name: " + repr(dn))
if frag == '*':
# When '*' is a fragment by itself, it matches a non-empty dotless
# fragment.
......
......@@ -19,20 +19,24 @@ class TestMarkerlib(unittest.TestCase):
self.assertTrue(interpret(""))
self.assertTrue(interpret("os.name != 'buuuu'"))
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("'%s' in os_name" % os_name))
self.assertTrue(interpret("'buuuu' not in os.name"))
self.assertFalse(interpret("os.name == 'buuuu'"))
self.assertFalse(interpret("os_name == 'buuuu'"))
self.assertFalse(interpret("python_version < '1.0'"))
self.assertFalse(interpret("python_version > '5.0'"))
self.assertFalse(interpret("python_version >= '5.0'"))
self.assertFalse(interpret("python_version <= '1.0'"))
self.assertFalse(interpret("'%s' not in os.name" % os_name))
self.assertFalse(interpret("'buuuu' in os.name and python_version >= '5.0'"))
self.assertFalse(interpret("'buuuu' in os_name and python_version >= '5.0'"))
environment = default_environment()
environment['extra'] = 'test'
......
......@@ -141,3 +141,42 @@ class TestPackageIndex(unittest.TestCase):
'reportlab-2.5.win-amd64-py2.7.exe'), ('reportlab-2.5', '2.7', 'win-amd64'))
self.assertEqual(setuptools.package_index.parse_bdist_wininst(
'reportlab-2.5.win-amd64.exe'), ('reportlab-2.5', None, 'win-amd64'))
class TestContentCheckers(unittest.TestCase):
def test_md5(self):
checker = setuptools.package_index.HashChecker.from_url(
'http://foo/bar#md5=f12895fdffbd45007040d2e44df98478')
checker.feed('You should probably not be using MD5'.encode('ascii'))
self.assertEqual(checker.hash.hexdigest(),
'f12895fdffbd45007040d2e44df98478')
self.assertTrue(checker.is_valid())
def test_other_fragment(self):
"Content checks should succeed silently if no hash is present"
checker = setuptools.package_index.HashChecker.from_url(
'http://foo/bar#something%20completely%20different')
checker.feed('anything'.encode('ascii'))
self.assertTrue(checker.is_valid())
def test_blank_md5(self):
"Content checks should succeed if a hash is empty"
checker = setuptools.package_index.HashChecker.from_url(
'http://foo/bar#md5=')
checker.feed('anything'.encode('ascii'))
self.assertTrue(checker.is_valid())
def test_get_hash_name_md5(self):
checker = setuptools.package_index.HashChecker.from_url(
'http://foo/bar#md5=f12895fdffbd45007040d2e44df98478')
if sys.version_info >= (2,5):
self.assertEqual(checker.hash.name, 'md5')
else:
# Python 2.4 compatability
self.assertEqual(checker._get_hash_name(), 'md5')
def test_report(self):
checker = setuptools.package_index.HashChecker.from_url(
'http://foo/bar#md5=f12895fdffbd45007040d2e44df98478')
rep = checker.report(lambda x: x, 'My message about %s')
self.assertEqual(rep, 'My message about md5')
......@@ -56,7 +56,7 @@ class TestZipProvider(object):
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 = open(filename, 'w')
f.write('hello, world?')
f.close()
os.utime(filename, (1368379500, 1368379500))
......@@ -64,3 +64,11 @@ class TestZipProvider(object):
f = open(filename)
assert f.read() == 'hello, world!'
manager.cleanup_resources()
class TestResourceManager(object):
def test_get_cache_path(self):
mgr = pkg_resources.ResourceManager()
path = mgr.get_cache_path('foo')
type_ = str(type(path))
message = "Unexpected type from get_cache_path: " + type_
assert isinstance(path, (unicode, str)), message
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