Commit 16ee10c4 authored by Jason R. Coombs's avatar Jason R. Coombs

Merge with 10.2.1

--HG--
branch : feature/issue-229
parents 866ff739 41f2c5ec
......@@ -160,3 +160,24 @@ bc6655b4acf205dd9f25c702955645656077398a 6.0.1
01271e84e5125fcc4f0f368a6e21116a5722953c 6.0.2
7ea80190d494a766c6356fce85c844703964b6cc 6.1
df26609c2f614f5fc9110342e4003ee8bd95cf84 7.0
850a5c155c48b6ecfbb83b961586ea359b561522 8.0b1
7ea0e7498e4ddbf63b6929ee83c75a9207996b08 8.0
1af3a5f24f7dd4e51d117f701918052b7de65c99 8.1b1
d62bf4e407b3b9b5bedcc1396a9ba46f35571902 8.0.1
1c03d512e39d5cfd711ae3ed7e316769f427e43b 8.0.2
6c3467488123ce70b1dd009145a02f51fb78cdcc 8.0.3
2c467afffe9fe1e14618b576fac6b4f7c412a61e 8.0.4
3f87370b6863e5a4e831b394ef1a58e0e97a4336 8.1
995f6d9651312cd481ca1e5ddb271cbdd0474c57 8.2
efbe39dae0aba9a7db399f6442758ae94e315c93 8.2.1
cd14b2a72e51c7d13873ab6c2041f901b1a7a1cd 8.3
0eee586a153f068142c1a0df4bc2635ed2c1a1cc 9.0b1
921e60a0f9067311571fde9ccf2f35223159d9f6 8.4
0d7b9b63d06ab7f68bc8edd56cb2034e6395d7fc 9.0
fa069bf2411a150c9379d31a04d1c3836e2d3027 9.0.1
3ed27d68d3f41bb5daa2afecfa9180d5958fe9d3 9.1
0c4d18a747a6d39bff8e194a58af949a960d674a 10.0
4c41e2cdd70beb0da556d71f46a67734c14f2bc2 10.0.1
26b00011ec65b8f7b4f3d51078ec0a694701a45c 10.1
651d41db58849d4fc50e466f4dc458d448480c4e 10.2
1f5de53c079d577ead9d80265c9e006503b16457 10.2.1
......@@ -8,7 +8,8 @@ python:
- pypy
# command to run tests
script:
- python setup.py egg_info
- python setup.py test
- python setup.py ptr
- python ez_setup.py --version 5.4.1
# update egg_info based on setup.py in checkout
- python bootstrap.py
- python setup.py ptr --addopts='-rs'
- python ez_setup.py --version 10.2.1
......@@ -2,6 +2,147 @@
CHANGES
=======
------
10.2.1
------
* Issue #323: Fix regression in entry point name parsing.
----
10.2
----
* Deprecated use of EntryPoint.load(require=False).
* Substantial refactoring of all unit tests. Tests are now much leaner and
re-use a lot of fixtures and contexts for better clarity of purpose.
----
10.1
----
* Issue #320: Added a compatibility implementation of
``sdist._default_revctrl``
so that systems relying on that interface do not fail (namely, Ubuntu 12.04
and similar Debian releases).
------
10.0.1
------
* Issue #319: Fixed issue installing pure distutils packages.
----
10.0
----
* Issue #313: Removed built-in support for subversion. Projects wishing to
retain support for subversion will need to use a third party library. The
extant implementation is being ported to `setuptools_svn
<https://pypi.python.org/pypi/setuptools_svn>`_.
* Issue #315: Updated setuptools to hide its own loaded modules during
installation of another package. This change will enable setuptools to
upgrade (or downgrade) itself even when its own metadata and implementation
change.
---
9.1
---
* Prefer vendored packaging library `as recommended
<https://github.com/jaraco/setuptools/commit/170657b68f4b92e7e1bf82f5e19a831f5744af67#commitcomment-9109448>`_.
-----
9.0.1
-----
* Issue #312: Restored presence of pkg_resources API tests (doctest) to sdist.
---
9.0
---
* Issue #314: Disabled support for ``setup_requires`` metadata to avoid issue
where Setuptools was unable to upgrade over earlier versions.
---
8.4
---
* Pull Request #106: Now write ``setup_requires`` metadata.
---
8.3
---
* Issue #311: Decoupled pkg_resources from setuptools once again.
``pkg_resources`` is now a package instead of a module.
-----
8.2.1
-----
* Issue #306: Suppress warnings about Version format except in select scenarios
(such as installation).
---
8.2
---
* Pull Request #85: Search egg-base when adding egg-info to manifest.
---
8.1
---
* Upgrade ``packaging`` to 14.5, giving preference to "rc" as designator for
release candidates over "c".
* PEP-440 warnings are now raised as their own class,
``pkg_resources.PEP440Warning``, instead of RuntimeWarning.
* Disabled warnings on empty versions.
-----
8.0.4
-----
* Upgrade ``packaging`` to 14.4, fixing an error where there is a
different result for if 2.0.5 is contained within >2.0dev and >2.0.dev even
though normalization rules should have made them equal.
* Issue #296: Add warning when a version is parsed as legacy. This warning will
make it easier for developers to recognize deprecated version numbers.
-----
8.0.3
-----
* Issue #296: Restored support for ``__hash__`` on parse_version results.
-----
8.0.2
-----
* Issue #296: Restored support for ``__getitem__`` and sort operations on
parse_version result.
-----
8.0.1
-----
* Issue #296: Restore support for iteration over parse_version result, but
deprecated that usage with a warning. Fixes failure with buildout.
---
8.0
---
* Implement `PEP 440 <http://legacy.python.org/dev/peps/pep-0440/>`_ within
pkg_resources and setuptools. This change
deprecates some version numbers such that they will no longer be installable
without using the ``===`` escape hatch. See `the changes to test_resources
<https://bitbucket.org/pypa/setuptools/commits/dcd552da643c4448056de84c73d56da6d70769d5#chg-setuptools/tests/test_resources.py>`_
for specific examples of version numbers and specifiers that are no longer
supported. Setuptools now "vendors" the `packaging
<https://github.com/pypa/packaging>`_ library.
---
7.0
---
......
recursive-include setuptools *.py *.txt *.exe *.xml
recursive-include tests *.py *.c *.pyx *.txt
recursive-include setuptools/tests *.html entries*
recursive-include setuptools/tests/svn_data *.zip
recursive-include setuptools *.py *.exe *.xml
recursive-include tests *.py *.c *.pyx
recursive-include setuptools/tests *.html
recursive-include docs *.py *.txt *.conf *.css *.css_t Makefile indexsidebar.html
recursive-include _markerlib *.py
recursive-include setuptools/_vendor *
recursive-include pkg_resources *.py *.txt
include *.py
include *.txt
include MANIFEST.in
......
empty:
exit 1
update-vendored:
rm -rf setuptools/_vendor/packaging
pip install -r setuptools/_vendor/vendored.txt -t setuptools/_vendor/
rm -rf setuptools/_vendor/*.{egg,dist}-info
......@@ -5,6 +5,8 @@ Installing and Using Setuptools
.. contents:: **Table of Contents**
`Change History <https://pythonhosted.org/setuptools/history.html>`_.
-------------------------
Installation Instructions
-------------------------
......@@ -83,6 +85,18 @@ Alternatively, Setuptools may be installed to a user-local path::
> wget https://bootstrap.pypa.io/ez_setup.py -O - | python - --user
Note that on some older systems (noted on Debian 6 and CentOS 5 installations),
`wget` may refuse to download `ez_setup.py`, complaining that the certificate common name `*.c.ssl.fastly.net`
does not match the host name `bootstrap.pypa.io`. In addition, the `ez_setup.py` script may then encounter similar problems using
`wget` internally to download `setuptools-x.y.zip`, complaining that the certificate common name of `www.python.org` does not match the
host name `pypi.python.org`. Those are known issues, related to a bug in the older versions of `wget`
(see `Issue 59 <https://bitbucket.org/pypa/pypi/issue/59#comment-5881915>`_). If you happen to encounter them,
install Setuptools as follows::
> wget --no-check-certificate https://bootstrap.pypa.io/ez_setup.py
> python ez_setup.py --insecure
Unix including Mac OS X (curl)
==============================
......
pytest_plugins = 'setuptools.tests.fixtures'
......@@ -28,7 +28,7 @@ import setup as setup_script
# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = []
extensions = ['linkify']
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
......@@ -44,7 +44,7 @@ master_doc = 'index'
# General information about the project.
project = 'Setuptools'
copyright = '2009-2013, The fellowship of the packaging'
copyright = '2009-2014, The fellowship of the packaging'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
......
......@@ -45,7 +45,7 @@ ticket already exists for your issue. If not, create one. Try to think from
the perspective of the reader. Explain what behavior you expected, what you
got instead, and what factors might have contributed to the unexpected
behavior. In Bitbucket, surround a block of code or traceback with the triple
backtick "```" so that it is formatted nicely.
backtick "\`\`\`" so that it is formatted nicely.
Filing a ticket provides a forum for justification, discussion, and
clarification. The ticket provides a record of the purpose for the change and
......
......@@ -286,6 +286,12 @@ that can be used to obtain ``Requirement`` objects describing the
project's core and optional dependencies.
``setup_requires.txt``
----------------------
Much like ``requires.txt`` except represents the requirements
specified by the ``setup_requires`` parameter to the Distribution.
``dependency_links.txt``
------------------------
......
:tocdepth: 2
.. _changes:
History
*******
.. include:: ../CHANGES (links).txt
......@@ -16,6 +16,7 @@ Documentation content:
.. toctree::
:maxdepth: 2
history
roadmap
python3
using
......
......@@ -594,7 +594,7 @@ Requirements Parsing
requirement ::= project_name versionspec? extras?
versionspec ::= comparison version (',' comparison version)*
comparison ::= '<' | '<=' | '!=' | '==' | '>=' | '>'
comparison ::= '<' | '<=' | '!=' | '==' | '>=' | '>' | '~=' | '==='
extras ::= '[' extralist? ']'
extralist ::= identifier (',' identifier)*
project_name ::= identifier
......@@ -646,13 +646,10 @@ Requirements Parsing
The ``Requirement`` object's version specifiers (``.specs``) are internally
sorted into ascending version order, and used to establish what ranges of
versions are acceptable. Adjacent redundant conditions are effectively
consolidated (e.g. ``">1, >2"`` produces the same results as ``">1"``, and
``"<2,<3"`` produces the same results as``"<3"``). ``"!="`` versions are
consolidated (e.g. ``">1, >2"`` produces the same results as ``">2"``, and
``"<2,<3"`` produces the same results as``"<2"``). ``"!="`` versions are
excised from the ranges they fall within. The version being tested for
acceptability is then checked for membership in the resulting ranges.
(Note that providing conflicting conditions for the same version (e.g.
``"<2,>=2"`` or ``"==2,!=2"``) is meaningless and may therefore produce
bizarre results when compared with actual version number(s).)
``__eq__(other_requirement)``
A requirement compares equal to another requirement if they have
......@@ -681,10 +678,7 @@ Requirements Parsing
``specs``
A list of ``(op,version)`` tuples, sorted in ascending parsed-version
order. The `op` in each tuple is a comparison operator, represented as
a string. The `version` is the (unparsed) version number. The relative
order of tuples containing the same version numbers is undefined, since
having more than one operator for a given version is either redundant or
self-contradictory.
a string. The `version` is the (unparsed) version number.
Entry Points
......@@ -967,7 +961,7 @@ version
``ValueError`` is raised.
parsed_version
The ``parsed_version`` is a tuple representing a "parsed" form of the
The ``parsed_version`` is an object representing a "parsed" form of the
distribution's ``version``. ``dist.parsed_version`` is a shortcut for
calling ``parse_version(dist.version)``. It is used to compare or sort
distributions by version. (See the `Parsing Utilities`_ section below for
......@@ -1541,40 +1535,12 @@ Parsing Utilities
-----------------
``parse_version(version)``
Parse a project's version string, returning a value that can be used to
compare versions by chronological order. Semantically, the format is a
rough cross between distutils' ``StrictVersion`` and ``LooseVersion``
classes; if you give it versions that would work with ``StrictVersion``,
then they will compare the same way. Otherwise, comparisons are more like
a "smarter" form of ``LooseVersion``. It is *possible* to create
pathological version coding schemes that will fool this parser, but they
should be very rare in practice.
The returned value will be a tuple of strings. Numeric portions of the
version are padded to 8 digits so they will compare numerically, but
without relying on how numbers compare relative to strings. Dots are
dropped, but dashes are retained. Trailing zeros between alpha segments
or dashes are suppressed, so that e.g. "2.4.0" is considered the same as
"2.4". Alphanumeric parts are lower-cased.
The algorithm assumes that strings like "-" and any alpha string that
alphabetically follows "final" represents a "patch level". So, "2.4-1"
is assumed to be a branch or patch of "2.4", and therefore "2.4.1" is
considered newer than "2.4-1", which in turn is newer than "2.4".
Strings like "a", "b", "c", "alpha", "beta", "candidate" and so on (that
come before "final" alphabetically) are assumed to be pre-release versions,
so that the version "2.4" is considered newer than "2.4a1". Any "-"
characters preceding a pre-release indicator are removed. (In versions of
setuptools prior to 0.6a9, "-" characters were not removed, leading to the
unintuitive result that "0.2-rc1" was considered a newer version than
"0.2".)
Finally, to handle miscellaneous cases, the strings "pre", "preview", and
"rc" are treated as if they were "c", i.e. as though they were release
candidates, and therefore are not as new as a version string that does not
contain them. And the string "dev" is treated as if it were an "@" sign;
that is, a version coming before even "a" or "alpha".
Parsed a project's version string as defined by PEP 440. The returned
value will be an object that represents the version. These objects may
be compared to each other and sorted. The sorting algorithm is as defined
by PEP 440 with the addition that any version which is not a valid PEP 440
version will be considered less than any valid PEP 440 version and the
invalid versions will continue sorting using the original algorithm.
.. _yield_lines():
......@@ -1629,10 +1595,12 @@ Parsing Utilities
See ``to_filename()``.
``safe_version(version)``
Similar to ``safe_name()`` except that spaces in the input become dots, and
dots are allowed to exist in the output. As with ``safe_name()``, if you
are generating a filename from this you should replace any "-" characters
in the output with underscores.
This will return the normalized form of any PEP 440 version, if the version
string is not PEP 440 compatible than it is similar to ``safe_name()``
except that spaces in the input become dots, and dots are allowed to exist
in the output. As with ``safe_name()``, if you are generating a filename
from this you should replace any "-" characters in the output with
underscores.
``safe_extra(extra)``
Return a "safe" form of an extra's name, suitable for use in a requirement
......
......@@ -17,6 +17,43 @@ revision slated for release::
python -m jaraco.packaging.release
Bootstrap Bookmark
------------------
Setuptools has a bootstrap script (ez_setup.py) which is hosted in the
repository and must be updated with each release (to bump the default version).
The "published" version of the script is the one indicated by the ``bootstrap``
bookmark (Mercurial) or branch (Git).
Therefore, the latest bootstrap script can be retrieved by checking out the
repository at that bookmark. It's also possible to get the bootstrap script for
any particular release by grabbing the script from that tagged release.
The officially-published location of the bootstrap script is hosted on Python
infrastructure (#python-infra on freenode) at https://bootstrap.pypa.io and
is updated every fifteen minutes from the bootstrap script. Sometimes,
especially when the bootstrap script is rolled back, this
process doesn't work as expected and requires manual intervention.
Release Frequency
-----------------
Some have asked why Setuptools is released so frequently. Because Setuptools
uses a mechanical release process, it's very easy to make releases whenever the
code is stable (tests are passing). As a result, the philosophy is to release
early and often.
While some find the frequent releases somewhat surprising, they only empower
the user. Although releases are made frequently, users can choose the frequency
at which they use those releases. If instead Setuptools contributions were only
released in batches, the user would be constrained to only use Setuptools when
those official releases were made. With frequent releases, the user can govern
exactly how often he wishes to update.
Frequent releases also then obviate the need for dev or beta releases in most
cases. Because releases are made early and often, bugs are discovered and
corrected quickly, in many cases before other users have yet to encounter them.
Release Managers
----------------
......
......@@ -308,7 +308,7 @@ unless you need the associated ``setuptools`` feature.
(Note: projects listed in ``setup_requires`` will NOT be automatically
installed on the system where the setup script is being run. They are
simply downloaded to the setup directory if they're not locally available
simply downloaded to the ./.eggs directory if they're not locally available
already. If you want them to be installed, as well as being available
when the setup script is run, you should add them to ``install_requires``
**and** ``setup_requires``.)
......
......@@ -8,3 +8,6 @@ it at the very beginning of `setup.py` like this::
from ez_setup import use_setuptools
use_setuptools()
More info on `ez_setup.py` can be found at `the project home page
<https://pypy.python.org/pypi/setuptools>`_.
......@@ -36,7 +36,7 @@ try:
except ImportError:
USER_SITE = None
DEFAULT_VERSION = "7.1"
DEFAULT_VERSION = "10.2.2"
DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/"
def _python_cmd(*args):
......
"""
Sphinx plugin to add links to the changelog.
"""
import re
import os
link_patterns = [
r"(Issue )?#(?P<issue>\d+)",
r"Pull Request ?#(?P<pull_request>\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(
pull_request='https://bitbucket.org'
'/pypa/setuptools/pull-request/{pull_request}',
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}',
)
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 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)
def setup(app):
_linkify('CHANGES.txt', 'CHANGES (links).txt')
app.connect('build-finished', remove_file)
def remove_file(app, exception):
os.remove('CHANGES (links).txt')
# Copyright 2014 Donald Stufft
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from __future__ import absolute_import, division, print_function
__all__ = [
"__title__", "__summary__", "__uri__", "__version__", "__author__",
"__email__", "__license__", "__copyright__",
]
__title__ = "packaging"
__summary__ = "Core utilities for Python packages"
__uri__ = "https://github.com/pypa/packaging"
__version__ = "14.5"
__author__ = "Donald Stufft"
__email__ = "donald@stufft.io"
__license__ = "Apache License, Version 2.0"
__copyright__ = "Copyright 2014 %s" % __author__
# Copyright 2014 Donald Stufft
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from __future__ import absolute_import, division, print_function
from .__about__ import (
__author__, __copyright__, __email__, __license__, __summary__, __title__,
__uri__, __version__
)
__all__ = [
"__title__", "__summary__", "__uri__", "__version__", "__author__",
"__email__", "__license__", "__copyright__",
]
# Copyright 2014 Donald Stufft
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from __future__ import absolute_import, division, print_function
import sys
PY2 = sys.version_info[0] == 2
PY3 = sys.version_info[0] == 3
# flake8: noqa
if PY3:
string_types = str,
else:
string_types = basestring,
def with_metaclass(meta, *bases):
"""
Create a base class with a metaclass.
"""
# This requires a bit of explanation: the basic idea is to make a dummy
# metaclass for one level of class instantiation that replaces itself with
# the actual metaclass.
class metaclass(meta):
def __new__(cls, name, this_bases, d):
return meta(name, bases, d)
return type.__new__(metaclass, 'temporary_class', (), {})
# Copyright 2014 Donald Stufft
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from __future__ import absolute_import, division, print_function
class Infinity(object):
def __repr__(self):
return "Infinity"
def __hash__(self):
return hash(repr(self))
def __lt__(self, other):
return False
def __le__(self, other):
return False
def __eq__(self, other):
return isinstance(other, self.__class__)
def __ne__(self, other):
return not isinstance(other, self.__class__)
def __gt__(self, other):
return True
def __ge__(self, other):
return True
def __neg__(self):
return NegativeInfinity
Infinity = Infinity()
class NegativeInfinity(object):
def __repr__(self):
return "-Infinity"
def __hash__(self):
return hash(repr(self))
def __lt__(self, other):
return True
def __le__(self, other):
return True
def __eq__(self, other):
return isinstance(other, self.__class__)
def __ne__(self, other):
return not isinstance(other, self.__class__)
def __gt__(self, other):
return False
def __ge__(self, other):
return False
def __neg__(self):
return Infinity
NegativeInfinity = NegativeInfinity()
This diff is collapsed.
This diff is collapsed.
......@@ -171,7 +171,7 @@ You can append a path entry to a working set using ``add_entry()``::
['http://example.com/something']
>>> ws.add_entry(pkg_resources.__file__)
>>> ws.entries
['http://example.com/something', '...pkg_resources.py...']
['http://example.com/something', '...pkg_resources...']
Multiple additions result in multiple entries, even if the entry is already in
the working set (because ``sys.path`` can contain the same entry more than
......
......@@ -3,7 +3,6 @@ Setuptools is released using 'jaraco.packaging.release'. To make a release,
install jaraco.packaging and run 'python -m jaraco.packaging.release'
"""
import re
import os
import subprocess
......@@ -14,12 +13,10 @@ pkg_resources.require('wheel')
def before_upload():
_linkify('CHANGES.txt', 'CHANGES (links).txt')
BootstrapBookmark.add()
def after_push():
os.remove('CHANGES (links).txt')
BootstrapBookmark.push()
files_with_versions = (
......@@ -33,44 +30,6 @@ 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"Pull Request ?#(?P<pull_request>\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(
pull_request='https://bitbucket.org'
'/pypa/setuptools/pull-request/{pull_request}',
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}',
)
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 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)
class BootstrapBookmark:
name = 'bootstrap'
......
......@@ -21,5 +21,5 @@ formats = gztar zip
universal=1
[pytest]
addopts=--doctest-modules --ignore release.py --ignore setuptools/lib2to3_ex.py --ignore tests/manual_test.py --ignore tests/shlib_test
addopts=--doctest-modules --ignore release.py --ignore setuptools/lib2to3_ex.py --ignore tests/manual_test.py --ignore tests/shlib_test --doctest-glob=pkg_resources/api_tests.txt
norecursedirs=dist build *.egg
......@@ -4,7 +4,6 @@ import io
import os
import sys
import textwrap
import contextlib
# Allow to run setup.py from another directory.
os.chdir(os.path.dirname(os.path.abspath(__file__)))
......@@ -27,7 +26,6 @@ with open(ver_path) as ver_file:
import setuptools
from setuptools.command.build_py import build_py as _build_py
from setuptools.command.test import test as _test
scripts = []
......@@ -61,44 +59,11 @@ class build_py(_build_py):
outf, copied = self.copy_file(srcfile, target)
srcfile = os.path.abspath(srcfile)
class test(_test):
"""Specific test class to avoid rewriting the entry_points.txt"""
def run(self):
with self._save_entry_points():
_test.run(self)
@contextlib.contextmanager
def _save_entry_points(self):
entry_points = os.path.join('setuptools.egg-info', 'entry_points.txt')
if not os.path.exists(entry_points):
yield
return
# save the content
with open(entry_points, 'rb') as f:
ep_content = f.read()
# run the tests
try:
yield
finally:
# restore the file
with open(entry_points, 'wb') as f:
f.write(ep_content)
readme_file = io.open('README.txt', encoding='utf-8')
# The release script adds hyperlinks to issues,
# but if the release script has not run, fall back to the source file
changes_names = 'CHANGES (links).txt', 'CHANGES.txt'
changes_fn = next(iter(filter(os.path.exists, changes_names)))
changes_file = io.open(changes_fn, encoding='utf-8')
with readme_file:
with changes_file:
long_description = readme_file.read() + '\n' + changes_file.read()
long_description = readme_file.read()
package_data = {
'setuptools': ['script (dev).tmpl', 'script.tmpl', 'site-patch.py']}
......@@ -123,16 +88,14 @@ setup_params = dict(
long_description=long_description,
keywords="CPAN PyPI distutils eggs package management",
url="https://bitbucket.org/pypa/setuptools",
test_suite='setuptools.tests',
src_root=src_root,
packages=setuptools.find_packages(),
package_data=package_data,
py_modules=['pkg_resources', 'easy_install'],
py_modules=['easy_install'],
zip_safe=True,
cmdclass={'test': test},
entry_points={
"distutils.commands": [
"%(cmd)s = setuptools.command.%(cmd)s:%(cmd)s" % locals()
......@@ -172,9 +135,6 @@ setup_params = dict(
],
"console_scripts": console_scripts,
"setuptools.file_finders":
["svn_cvs = setuptools.command.sdist:_default_revctrl"],
"setuptools.installation":
['eggsecutable = setuptools.command.easy_install:bootstrap'],
},
......@@ -213,6 +173,7 @@ setup_params = dict(
tests_require=[
'setuptools[ssl]',
'pytest',
'mock',
],
setup_requires=[
] + pytest_runner,
......
......@@ -3,7 +3,6 @@
__import__('setuptools.bootstrap').bootstrap.ensure_deps()
import os
import sys
import distutils.core
import distutils.filelist
from distutils.core import Command as _Command
......
......@@ -64,20 +64,23 @@ def unpack_directory(filename, extract_dir, progress_filter=default_filter):
Raises ``UnrecognizedFormat`` if `filename` is not a directory
"""
if not os.path.isdir(filename):
raise UnrecognizedFormat("%s is not a directory" % (filename,))
raise UnrecognizedFormat("%s is not a directory" % filename)
paths = {filename:('',extract_dir)}
paths = {
filename: ('', extract_dir),
}
for base, dirs, files in os.walk(filename):
src,dst = paths[base]
src, dst = paths[base]
for d in dirs:
paths[os.path.join(base,d)] = src+d+'/', os.path.join(dst,d)
paths[os.path.join(base, d)] = src + d + '/', os.path.join(dst, d)
for f in files:
target = os.path.join(dst,f)
target = progress_filter(src+f, target)
target = os.path.join(dst, f)
target = progress_filter(src + f, target)
if not target:
continue # skip non-files
# skip non-files
continue
ensure_directory(target)
f = os.path.join(base,f)
f = os.path.join(base, f)
shutil.copyfile(f, target)
shutil.copystat(f, target)
......@@ -112,12 +115,8 @@ def unpack_zipfile(filename, extract_dir, progress_filter=default_filter):
# file
ensure_directory(target)
data = z.read(info.filename)
f = open(target,'wb')
try:
with open(target, 'wb') as f:
f.write(data)
finally:
f.close()
del data
unix_attributes = info.external_attr >> 16
if unix_attributes:
os.chmod(target, unix_attributes)
......@@ -137,18 +136,21 @@ def unpack_tarfile(filename, extract_dir, progress_filter=default_filter):
"%s is not a compressed or uncompressed tar file" % (filename,)
)
with contextlib.closing(tarobj):
tarobj.chown = lambda *args: None # don't do any chowning!
# don't do any chowning!
tarobj.chown = lambda *args: None
for member in tarobj:
name = member.name
# don't extract absolute paths or ones with .. in them
if not name.startswith('/') and '..' not in name.split('/'):
prelim_dst = os.path.join(extract_dir, *name.split('/'))
# resolve any links and to extract the link targets as normal files
# resolve any links and to extract the link targets as normal
# files
while member is not None and (member.islnk() or member.issym()):
linkpath = member.linkname
if member.issym():
linkpath = posixpath.join(posixpath.dirname(member.name), linkpath)
base = posixpath.dirname(member.name)
linkpath = posixpath.join(base, linkpath)
linkpath = posixpath.normpath(linkpath)
member = tarobj._getmember(linkpath)
......@@ -158,9 +160,11 @@ def unpack_tarfile(filename, extract_dir, progress_filter=default_filter):
if final_dst.endswith(os.sep):
final_dst = final_dst[:-1]
try:
tarobj._extract_member(member, final_dst) # XXX Ugh
# XXX Ugh
tarobj._extract_member(member, final_dst)
except tarfile.ExtractError:
pass # chown/chmod/mkfifo/mknode/makedev failed
# chown/chmod/mkfifo/mknode/makedev failed
pass
return True
extraction_drivers = unpack_directory, unpack_zipfile, unpack_tarfile
......@@ -6,6 +6,7 @@ from distutils.errors import DistutilsError
from distutils import log
import os
import sys
import itertools
from setuptools.extension import Library
......@@ -33,18 +34,13 @@ if sys.platform == "darwin":
use_stubs = True
elif os.name != 'nt':
try:
from dl import RTLD_NOW
have_rtld = True
use_stubs = True
import dl
use_stubs = have_rtld = hasattr(dl, 'RTLD_NOW')
except ImportError:
pass
def if_dl(s):
if have_rtld:
return s
return ''
if_dl = lambda s: s if have_rtld else ''
class build_ext(_build_ext):
......@@ -123,10 +119,10 @@ class build_ext(_build_ext):
# XXX what to do with conflicts?
self.ext_map[fullname.split('.')[-1]] = ext
ltd = ext._links_to_dynamic = \
self.shlibs and self.links_to_dynamic(ext) or False
ext._needs_stub = ltd and use_stubs and not isinstance(ext,
Library)
ltd = self.shlibs and self.links_to_dynamic(ext) or False
ns = ltd and use_stubs and not isinstance(ext, Library)
ext._links_to_dynamic = ltd
ext._needs_stub = ns
filename = ext._file_name = self.get_ext_filename(fullname)
libdir = os.path.dirname(os.path.join(self.build_lib, filename))
if ltd and libdir not in ext.library_dirs:
......@@ -186,9 +182,8 @@ class build_ext(_build_ext):
self.compiler = self.shlib_compiler
_build_ext.build_extension(self, ext)
if ext._needs_stub:
self.write_stub(
self.get_finalized_command('build_py').build_lib, ext
)
cmd = self.get_finalized_command('build_py').build_lib
self.write_stub(cmd, ext)
finally:
self.compiler = _compiler
......@@ -199,22 +194,27 @@ class build_ext(_build_ext):
# XXX static-compiled version
libnames = dict.fromkeys([lib._full_name for lib in self.shlibs])
pkg = '.'.join(ext._full_name.split('.')[:-1] + [''])
for libname in ext.libraries:
if pkg + libname in libnames:
return True
return False
return any(pkg + libname in libnames for libname in ext.libraries)
def get_outputs(self):
outputs = _build_ext.get_outputs(self)
optimize = self.get_finalized_command('build_py').optimize
for ext in self.extensions:
if ext._needs_stub:
base = os.path.join(self.build_lib, *ext._full_name.split('.'))
outputs.append(base + '.py')
outputs.append(base + '.pyc')
if optimize:
outputs.append(base + '.pyo')
return outputs
return _build_ext.get_outputs(self) + self.__get_stubs_outputs()
def __get_stubs_outputs(self):
# assemble the base name for each extension that needs a stub
ns_ext_bases = (
os.path.join(self.build_lib, *ext._full_name.split('.'))
for ext in self.extensions
if ext._needs_stub
)
# pair each base with the extension
pairs = itertools.product(ns_ext_bases, self.__get_output_extensions())
return list(base + fnext for base, fnext in pairs)
def __get_output_extensions(self):
yield '.py'
yield '.pyc'
if self.get_finalized_command('build_py').optimize:
yield '.pyo'
def write_stub(self, output_dir, ext, compile=False):
log.info("writing stub loader for %s to %s", ext._full_name,
......
......@@ -34,6 +34,7 @@ import textwrap
import warnings
import site
import struct
import contextlib
import six
from six.moves import configparser
......@@ -55,9 +56,14 @@ from pkg_resources import (
import pkg_resources
# Turn on PEP440Warnings
warnings.filterwarnings("default", category=pkg_resources.PEP440Warning)
sys_executable = os.environ.get('__PYVENV_LAUNCHER__',
os.path.normpath(sys.executable))
__all__ = [
'samefile', 'easy_install', 'PthDistributions', 'extract_wininst_cfg',
'main', 'get_exe_prefixes',
......@@ -1541,10 +1547,14 @@ class PthDistributions(Environment):
def add(self, dist):
"""Add `dist` to the distribution map"""
if (dist.location not in self.paths and (
dist.location not in self.sitedirs or
dist.location == os.getcwd() # account for '.' being in PYTHONPATH
)):
new_path = (
dist.location not in self.paths and (
dist.location not in self.sitedirs or
# account for '.' being in PYTHONPATH
dist.location == os.getcwd()
)
)
if new_path:
self.paths.append(dist.location)
self.dirty = True
Environment.add(self, dist)
......@@ -2112,39 +2122,42 @@ def bootstrap():
def main(argv=None, **kw):
from setuptools import setup
from setuptools.dist import Distribution
import distutils.core
USAGE = """\
usage: %(script)s [options] requirement_or_url ...
or: %(script)s --help
"""
def gen_usage(script_name):
return USAGE % dict(
script=os.path.basename(script_name),
)
def with_ei_usage(f):
old_gen_usage = distutils.core.gen_usage
try:
distutils.core.gen_usage = gen_usage
return f()
finally:
distutils.core.gen_usage = old_gen_usage
class DistributionWithoutHelpCommands(Distribution):
common_usage = ""
def _show_help(self, *args, **kw):
with_ei_usage(lambda: Distribution._show_help(self, *args, **kw))
with _patch_usage():
Distribution._show_help(self, *args, **kw)
if argv is None:
argv = sys.argv[1:]
with_ei_usage(
lambda: setup(
with _patch_usage():
setup(
script_args=['-q', 'easy_install', '-v'] + argv,
script_name=sys.argv[0] or 'easy_install',
distclass=DistributionWithoutHelpCommands, **kw
)
)
@contextlib.contextmanager
def _patch_usage():
import distutils.core
USAGE = textwrap.dedent("""
usage: %(script)s [options] requirement_or_url ...
or: %(script)s --help
""").lstrip()
def gen_usage(script_name):
return USAGE % dict(
script=os.path.basename(script_name),
)
saved = distutils.core.gen_usage
distutils.core.gen_usage = gen_usage
try:
yield
finally:
distutils.core.gen_usage = saved
......@@ -6,21 +6,27 @@ from distutils.filelist import FileList as _FileList
from distutils.util import convert_path
from distutils import log
import distutils.errors
import distutils.filelist
import os
import re
import sys
import six
try:
from setuptools_svn import svn_utils
except ImportError:
pass
from setuptools import Command
from setuptools.command.sdist import sdist
from setuptools import svn_utils
from setuptools.command.sdist import walk_revctrl
from pkg_resources import (
parse_requirements, safe_name, parse_version,
safe_version, yield_lines, EntryPoint, iter_entry_points, to_filename)
import setuptools.unicode_utils as unicode_utils
from pkg_resources import packaging
class egg_info(Command):
description = "create a distribution's .egg-info directory"
......@@ -69,10 +75,15 @@ class egg_info(Command):
self.vtags = self.tags()
self.egg_version = self.tagged_version()
parsed_version = parse_version(self.egg_version)
try:
is_version = isinstance(parsed_version, packaging.version.Version)
spec = (
"%s==%s" if is_version else "%s===%s"
)
list(
parse_requirements('%s==%s' % (self.egg_name,
self.egg_version))
parse_requirements(spec % (self.egg_name, self.egg_version))
)
except ValueError:
raise distutils.errors.DistutilsOptionError(
......@@ -184,6 +195,8 @@ class egg_info(Command):
@staticmethod
def get_svn_revision():
if 'svn_utils' not in globals():
return "0"
return str(svn_utils.SvnInfo.load(os.curdir).get_revision())
def find_sources(self):
......@@ -313,8 +326,33 @@ class manifest_maker(sdist):
elif os.path.exists(self.manifest):
self.read_manifest()
ei_cmd = self.get_finalized_command('egg_info')
self._add_egg_info(cmd=ei_cmd)
self.filelist.include_pattern("*", prefix=ei_cmd.egg_info)
def _add_egg_info(self, cmd):
"""
Add paths for egg-info files for an external egg-base.
The egg-info files are written to egg-base. If egg-base is
outside the current working directory, this method
searchs the egg-base directory for files to include
in the manifest. Uses distutils.filelist.findall (which is
really the version monkeypatched in by setuptools/__init__.py)
to perform the search.
Since findall records relative paths, prefix the returned
paths with cmd.egg_base, so add_default's include_pattern call
(which is looking for the absolute cmd.egg_info) will match
them.
"""
if cmd.egg_base == os.curdir:
# egg-info files were already added by something else
return
discovered = distutils.filelist.findall(cmd.egg_base)
resolved = (os.path.join(cmd.egg_base, path) for path in discovered)
self.filelist.allfiles.extend(resolved)
def prune_file_list(self):
build = self.get_finalized_command('build')
base_dir = self.distribution.get_fullname()
......@@ -383,6 +421,12 @@ def write_requirements(cmd, basename, filename):
cmd.write_or_delete_file("requirements", filename, data.getvalue())
def write_setup_requirements(cmd, basename, filename):
data = StringIO()
_write_requirements(data, cmd.distribution.setup_requires)
cmd.write_or_delete_file("setup-requirements", filename, data.getvalue())
def write_toplevel_names(cmd, basename, filename):
pkgs = dict.fromkeys(
[
......
from glob import glob
from distutils.util import convert_path
from distutils import log
import distutils.command.sdist as orig
import os
import re
import sys
import six
from setuptools import svn_utils
from setuptools.utils import cs_path_exists
import pkg_resources
READMES = ('README', 'README.rst', 'README.txt')
READMES = 'README', 'README.rst', 'README.txt'
_default_revctrl = list
def walk_revctrl(dirname=''):
"""Find all files under revision control"""
......@@ -23,60 +21,6 @@ def walk_revctrl(dirname=''):
yield item
# TODO will need test case
class re_finder(object):
"""
Finder that locates files based on entries in a file matched by a
regular expression.
"""
def __init__(self, path, pattern, postproc=lambda x: x):
self.pattern = pattern
self.postproc = postproc
self.entries_path = convert_path(path)
def _finder(self, dirname, filename):
f = open(filename, 'rU')
try:
data = f.read()
finally:
f.close()
for match in self.pattern.finditer(data):
path = match.group(1)
# postproc was formerly used when the svn finder
# was an re_finder for calling unescape
path = self.postproc(path)
yield svn_utils.joinpath(dirname, path)
def find(self, dirname=''):
path = svn_utils.joinpath(dirname, self.entries_path)
if not os.path.isfile(path):
# entries file doesn't exist
return
for path in self._finder(dirname, path):
if os.path.isfile(path):
yield path
elif os.path.isdir(path):
for item in self.find(path):
yield item
__call__ = find
def _default_revctrl(dirname=''):
'Primary svn_cvs entry point'
for finder in finders:
for item in finder(dirname):
yield item
finders = [
re_finder('CVS/Entries', re.compile(r"^\w?/([^/]+)/", re.M)),
svn_utils.svn_finder,
]
class sdist(orig.sdist):
"""Smart sdist that finds anything supported by revision control"""
......
......@@ -173,4 +173,4 @@ class test(Command):
if val is None:
return
parsed = EntryPoint.parse("x=" + val)
return parsed.load(require=False)()
return parsed._load()()
......@@ -19,6 +19,9 @@ from setuptools.depends import Require
from setuptools import windows_support
import pkg_resources
packaging = pkg_resources.packaging
def _get_unpatched(cls):
"""Protect against re-patching the distutils if reloaded
......@@ -270,6 +273,27 @@ class Distribution(_Distribution):
# Some people apparently take "version number" too literally :)
self.metadata.version = str(self.metadata.version)
if self.metadata.version is not None:
try:
ver = packaging.version.Version(self.metadata.version)
normalized_version = str(ver)
if self.metadata.version != normalized_version:
warnings.warn(
"The version specified requires normalization, "
"consider using '%s' instead of '%s'." % (
normalized_version,
self.metadata.version,
)
)
self.metadata.version = normalized_version
except (packaging.version.InvalidVersion, TypeError):
warnings.warn(
"The version specified (%r) is an invalid version, this "
"may not work as expected with newer versions of "
"setuptools, pip, and PyPI. Please see PEP 440 for more "
"details." % self.metadata.version
)
def parse_command_line(self):
"""Process features after parsing command line options"""
result = _Distribution.parse_command_line(self)
......@@ -411,7 +435,8 @@ class Distribution(_Distribution):
def print_commands(self):
for ep in pkg_resources.iter_entry_points('distutils.commands'):
if ep.name not in self.cmdclass:
cmdclass = ep.load(False) # don't require extras, we're not running
# don't require extras as the commands won't be invoked
cmdclass = ep._load()
self.cmdclass[ep.name] = cmdclass
return _Distribution.print_commands(self)
......
......@@ -5,7 +5,10 @@ import operator
import functools
import itertools
import re
import contextlib
import pickle
import six
from six.moves import builtins
import pkg_resources
......@@ -42,20 +45,150 @@ def _execfile(filename, globals, locals=None):
code = compile(script, filename, 'exec')
exec(code, globals, locals)
@contextlib.contextmanager
def save_argv():
saved = sys.argv[:]
try:
yield saved
finally:
sys.argv[:] = saved
@contextlib.contextmanager
def save_path():
saved = sys.path[:]
try:
yield saved
finally:
sys.path[:] = saved
@contextlib.contextmanager
def override_temp(replacement):
"""
Monkey-patch tempfile.tempdir with replacement, ensuring it exists
"""
if not os.path.isdir(replacement):
os.makedirs(replacement)
saved = tempfile.tempdir
tempfile.tempdir = replacement
try:
yield
finally:
tempfile.tempdir = saved
@contextlib.contextmanager
def pushd(target):
saved = os.getcwd()
os.chdir(target)
try:
yield saved
finally:
os.chdir(saved)
@contextlib.contextmanager
def save_modules():
"""
Context in which imported modules are saved.
Translates exceptions internal to the context into the equivalent exception
outside the context.
"""
saved = sys.modules.copy()
try:
try:
yield saved
except:
# dump any exception
class_, exc, tb = sys.exc_info()
saved_cls = pickle.dumps(class_)
saved_exc = pickle.dumps(exc)
raise
finally:
sys.modules.update(saved)
# remove any modules imported since
del_modules = (
mod_name for mod_name in sys.modules
if mod_name not in saved
# exclude any encodings modules. See #285
and not mod_name.startswith('encodings.')
)
_clear_modules(del_modules)
except:
# reload and re-raise any exception, using restored modules
class_, exc, tb = sys.exc_info()
new_cls = pickle.loads(saved_cls)
new_exc = pickle.loads(saved_exc)
six.reraise(new_cls, new_exc, tb)
def _clear_modules(module_names):
for mod_name in list(module_names):
del sys.modules[mod_name]
@contextlib.contextmanager
def save_pkg_resources_state():
saved = pkg_resources.__getstate__()
try:
yield saved
finally:
pkg_resources.__setstate__(saved)
@contextlib.contextmanager
def setup_context(setup_dir):
temp_dir = os.path.join(setup_dir, 'temp')
with save_pkg_resources_state():
with save_modules():
hide_setuptools()
with save_path():
with save_argv():
with override_temp(temp_dir):
with pushd(setup_dir):
# ensure setuptools commands are available
__import__('setuptools')
yield
def _needs_hiding(mod_name):
"""
>>> _needs_hiding('setuptools')
True
>>> _needs_hiding('pkg_resources')
True
>>> _needs_hiding('setuptools_plugin')
False
>>> _needs_hiding('setuptools.__init__')
True
>>> _needs_hiding('distutils')
True
"""
pattern = re.compile('(setuptools|pkg_resources|distutils)(\.|$)')
return bool(pattern.match(mod_name))
def hide_setuptools():
"""
Remove references to setuptools' modules from sys.modules to allow the
invocation to import the most appropriate setuptools. This technique is
necessary to avoid issues such as #315 where setuptools upgrading itself
would fail to find a function declared in the metadata.
"""
modules = filter(_needs_hiding, sys.modules)
_clear_modules(modules)
def run_setup(setup_script, args):
"""Run a distutils setup script, sandboxed in its directory"""
old_dir = os.getcwd()
save_argv = sys.argv[:]
save_path = sys.path[:]
setup_dir = os.path.abspath(os.path.dirname(setup_script))
temp_dir = os.path.join(setup_dir,'temp')
if not os.path.isdir(temp_dir): os.makedirs(temp_dir)
save_tmp = tempfile.tempdir
save_modules = sys.modules.copy()
pr_state = pkg_resources.__getstate__()
try:
tempfile.tempdir = temp_dir
os.chdir(setup_dir)
with setup_context(setup_dir):
try:
sys.argv[:] = [setup_script]+list(args)
sys.path.insert(0, setup_dir)
......@@ -71,21 +204,6 @@ def run_setup(setup_script, args):
if v.args and v.args[0]:
raise
# Normal exit, just return
finally:
pkg_resources.__setstate__(pr_state)
sys.modules.update(save_modules)
# remove any modules imported within the sandbox
del_modules = [
mod_name for mod_name in sys.modules
if mod_name not in save_modules
# exclude any encodings modules. See #285
and not mod_name.startswith('encodings.')
]
list(map(sys.modules.__delitem__, del_modules))
os.chdir(old_dir)
sys.path[:] = save_path
sys.argv[:] = save_argv
tempfile.tempdir = save_tmp
class AbstractSandbox:
......
This diff is collapsed.
This diff is collapsed.
import tempfile
import os
import shutil
import sys
import contextlib
import site
import six
@contextlib.contextmanager
def tempdir(cd=lambda dir:None, **kwargs):
temp_dir = tempfile.mkdtemp(**kwargs)
orig_dir = os.getcwd()
try:
cd(temp_dir)
yield temp_dir
finally:
cd(orig_dir)
shutil.rmtree(temp_dir)
@contextlib.contextmanager
def environment(**replacements):
"""
In a context, patch the environment with replacements. Pass None values
to clear the values.
"""
saved = dict(
(key, os.environ['key'])
for key in replacements
if key in os.environ
)
# remove values that are null
remove = (key for (key, value) in replacements.items() if value is None)
for key in list(remove):
os.environ.pop(key, None)
replacements.pop(key)
os.environ.update(replacements)
try:
yield saved
finally:
for key in replacements:
os.environ.pop(key, None)
os.environ.update(saved)
@contextlib.contextmanager
def argv(repl):
old_argv = sys.argv[:]
sys.argv[:] = repl
yield
sys.argv[:] = old_argv
@contextlib.contextmanager
def quiet():
"""
Redirect stdout/stderr to StringIO objects to prevent console output from
distutils commands.
"""
old_stdout = sys.stdout
old_stderr = sys.stderr
new_stdout = sys.stdout = six.StringIO()
new_stderr = sys.stderr = six.StringIO()
try:
yield new_stdout, new_stderr
finally:
new_stdout.seek(0)
new_stderr.seek(0)
sys.stdout = old_stdout
sys.stderr = old_stderr
@contextlib.contextmanager
def save_user_site_setting():
saved = site.ENABLE_USER_SITE
try:
yield saved
finally:
site.ENABLE_USER_SITE = saved
@contextlib.contextmanager
def suppress_exceptions(*excs):
try:
yield
except excs:
pass
10
dir
89001
http://svn.python.org/projects/sandbox/branches/setuptools-0.6
http://svn.python.org/projects
2013-06-03T17:26:03.052972Z
89000
phillip.eby
6015fed2-1504-0410-9fe1-9d1591cc4771
api_tests.txt
file
2013-06-19T13:20:47.948712Z
dec366372ca14fbeaeb26f492bcf5725
2013-05-15T22:04:59.389374Z
88997
phillip.eby
has-props
12312
setuptools.egg-info
dir
README.txt
file
2013-06-19T13:20:47.948712Z
26f0dd5d095522ba3ad999b6b6777b92
2011-05-31T20:10:56.416725Z
88846
phillip.eby
has-props
7615
easy_install.py
file
2013-06-19T13:20:47.948712Z
97b52fe7253bf4683f9f626f015eb72e
2006-09-20T20:48:18.716070Z
51935
phillip.eby
has-props
126
setuptools
dir
launcher.c
file
2013-06-19T13:20:47.924700Z
e5a8e77de9022688b80f77fc6d742fee
2009-10-19T21:03:29.785400Z
75544
phillip.eby
has-props
7476
ez_setup.py
file
2013-06-19T13:20:47.924700Z
17e8ec5e08faccfcb08b5f8d5167ca14
2011-01-20T18:50:00.815420Z
88124
phillip.eby
has-props
8350
version
file
2013-06-19T13:20:47.924700Z
e456da09e0c9e224a56302f8316b6dbf
2007-01-09T19:21:05.921317Z
53317
phillip.eby
has-props
1143
setup.py
file
2013-06-19T13:20:47.924700Z
d4e5b3c16bd61bfef6c0bb9377a3a3ea
2013-05-15T22:04:59.389374Z
88997
phillip.eby
has-props
5228
release.sh
file
2013-06-19T13:20:47.932704Z
b1fd4054a1c107ff0f27baacd97be94c
2009-10-28T17:12:45.227140Z
75925
phillip.eby
has-props
1044
pkg_resources.txt
file
2013-06-19T13:20:47.928702Z
f497e7c92a4de207cbd9ab1943f93388
2009-10-12T20:00:02.336146Z
75385
phillip.eby
has-props
94518
site.py
file
2013-06-19T13:20:47.932704Z
ebaac6fb6525f77ca950d22e6f8315df
2006-03-11T00:39:09.666740Z
42965
phillip.eby
has-props
2362
version.dat
file
2013-06-19T13:20:47.932704Z
8e14ecea32b9874cd7d29277494554c0
2009-10-28T17:12:45.227140Z
75925
phillip.eby
has-props
80
virtual-python.py
file
2013-06-19T13:20:47.932704Z
aa857add3b5563238f0a904187f5ded9
2005-10-17T02:26:39.000000Z
41262
pje
has-props
3898
setup.cfg
file
2013-06-19T13:20:47.932704Z
eda883e744fce83f8107ad8dc8303536
2006-09-21T22:26:48.050256Z
51965
phillip.eby
has-props
296
setuptools.txt
file
2013-06-19T13:20:47.940708Z
11926256f06046b196eaf814772504e7
2013-05-15T22:04:59.389374Z
88997
phillip.eby
has-props
149832
pkg_resources.py
file
2013-06-19T13:20:47.940708Z
b63a30f5f0f0225a788c2c0e3430b3cf
2013-05-15T22:04:59.389374Z
88997
phillip.eby
has-props
90397
tests
dir
wikiup.cfg
file
2013-06-19T13:20:47.944710Z
34ad845a5e0a0b46458557fa910bf429
2008-08-21T17:23:50.797633Z
65935
phillip.eby
has-props
136
EasyInstall.txt
file
2013-06-19T13:20:47.944710Z
e97387c517f70fc18a377e42d19d64d4
2013-05-15T22:04:59.389374Z
88997
phillip.eby
has-props
82495
import os
import zipfile
import sys
import tempfile
import unittest
import shutil
import stat
import unicodedata
from subprocess import Popen as _Popen, PIPE as _PIPE
def _remove_dir(target):
#on windows this seems to a problem
for dir_path, dirs, files in os.walk(target):
os.chmod(dir_path, stat.S_IWRITE)
for filename in files:
os.chmod(os.path.join(dir_path, filename), stat.S_IWRITE)
shutil.rmtree(target)
class ZippedEnvironment(unittest.TestCase):
datafile = None
dataname = None
old_cwd = None
def setUp(self):
if self.datafile is None or self.dataname is None:
return
if not os.path.isfile(self.datafile):
self.old_cwd = None
return
self.old_cwd = os.getcwd()
self.temp_dir = tempfile.mkdtemp()
zip_file, source, target = [None, None, None]
try:
zip_file = zipfile.ZipFile(self.datafile)
for files in zip_file.namelist():
zip_file.extract(files, self.temp_dir)
finally:
if zip_file:
zip_file.close()
del zip_file
os.chdir(os.path.join(self.temp_dir, self.dataname))
def tearDown(self):
#Assume setUp was never completed
if self.dataname is None or self.datafile is None:
return
try:
if self.old_cwd:
os.chdir(self.old_cwd)
_remove_dir(self.temp_dir)
except OSError:
#sigh?
pass
def _which_dirs(cmd):
result = set()
for path in os.environ.get('PATH', '').split(os.pathsep):
......
import mock
import pytest
from . import contexts
@pytest.yield_fixture
def user_override():
"""
Override site.USER_BASE and site.USER_SITE with temporary directories in
a context.
"""
with contexts.tempdir() as user_base:
with mock.patch('site.USER_BASE', user_base):
with contexts.tempdir() as user_site:
with mock.patch('site.USER_SITE', user_site):
with contexts.save_user_site_setting():
yield
@pytest.yield_fixture
def tmpdir_cwd(tmpdir):
with tmpdir.as_cwd() as orig:
yield orig
This diff is collapsed.
This diff is collapsed.
third_party3 file:///C:/development/svn_example/repos/svn13/extra1
third_party2 -r3 file:///C:/development/svn_example/repos/svn13/extra1
third_party -r1 file:///C:/development/svn_example/repos/svn13/extra1
This diff is collapsed.
third_party3 file:///C:/development/svn_example/repos/svn13/extra1
third_party2 -r3 file:///C:/development/svn_example/repos/svn13/extra1
third_party -r1 file:///C:/development/svn_example/repos/svn13/extra1
This diff is collapsed.
third_party3 file:///C:/development/svn_example/repos/svn15/extra1
-r3 file:///C:/development/svn_example/repos/svn15/extra1 third_party2
file:///C:/development/svn_example/repos/svn15/extra1@r1 third_party
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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