From: DongHun Kwak Date: Tue, 29 Dec 2020 22:04:48 +0000 (+0900) Subject: Imported Upstream version 44.1.0 X-Git-Tag: upstream/44.1.0^0 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=90b3ab56723f046982cc57a2d7252597e4c80f69;p=platform%2Fupstream%2Fpython-setuptools.git Imported Upstream version 44.1.0 --- diff --git a/.bumpversion.cfg b/.bumpversion.cfg index e1bfa89..c8c9f54 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,7 +1,6 @@ [bumpversion] -current_version = 44.0.0 +current_version = 44.1.0 commit = True tag = True [bumpversion:file:setup.cfg] - diff --git a/.travis.yml b/.travis.yml index 501a0b6..3ce1bf0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -27,6 +27,9 @@ jobs: if: tag IS present script: tox -e release after_success: skip + allow_failures: + # suppress failures due to pypa/setuptools#2000 + - python: pypy3 cache: pip @@ -41,8 +44,6 @@ install: - pip freeze --all - env -# update egg_info based on setup.py in checkout -- python bootstrap.py - "! grep pyc setuptools.egg-info/SOURCES.txt" script: diff --git a/CHANGES.rst b/CHANGES.rst index 109a3f4..83cd8c7 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,3 +1,11 @@ +v44.1.0 +------- + +* #1704: Set sys.argv[0] in setup script run by build_meta.__legacy__ +* #1959: Fix for Python 4: replace unsafe six.PY3 with six.PY2 +* #1994: Fixed a bug in the "setuptools.finalize_distribution_options" hook that lead to ignoring the order attribute of entry points managed by this hook. + + v44.0.0 ------- diff --git a/appveyor.yml b/appveyor.yml index 0881806..02fe1ee 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -28,7 +28,6 @@ test_script: - python -m pip install --disable-pip-version-check --upgrade pip setuptools wheel - pip install --upgrade tox tox-venv virtualenv - pip freeze --all - - python bootstrap.py - tox -- --cov after_test: diff --git a/azure-pipelines.yml b/azure-pipelines.yml new file mode 100644 index 0000000..3e80bf4 --- /dev/null +++ b/azure-pipelines.yml @@ -0,0 +1,71 @@ +# Create the project in Azure with: +# az devops project create --name $name --organization https://dev.azure.com/$org/ --visibility public +# then configure the pipelines (through web UI) + +trigger: + branches: + include: + - '*' + tags: + include: + - '*' + +pool: + vmimage: 'Ubuntu-18.04' + +variables: +- group: Azure secrets + +stages: +- stage: Test + jobs: + + - job: 'Test' + strategy: + matrix: + Python36: + python.version: '3.6' + Python38: + python.version: '3.8' + maxParallel: 4 + + steps: + - task: UsePythonVersion@0 + inputs: + versionSpec: '$(python.version)' + architecture: 'x64' + + - script: python -m pip install tox + displayName: 'Install tox' + + - script: | + tox -- --junit-xml=test-results.xml + displayName: 'run tests' + + - task: PublishTestResults@2 + inputs: + testResultsFiles: '**/test-results.xml' + testRunTitle: 'Python $(python.version)' + condition: succeededOrFailed() + +- stage: Publish + dependsOn: Test + jobs: + - job: 'Publish' + + steps: + - task: UsePythonVersion@0 + inputs: + versionSpec: '3.8' + architecture: 'x64' + + - script: python -m pip install tox + displayName: 'Install tox' + + - script: | + tox -e release + env: + TWINE_PASSWORD: $(PyPI-token) + displayName: 'publish to PyPI' + + condition: contains(variables['Build.SourceBranch'], 'tags') diff --git a/docs/conf.py b/docs/conf.py index cbd19fb..6f6ae13 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -26,7 +26,7 @@ import os # hack to run the bootstrap script so that jaraco.packaging.sphinx # can invoke setup.py 'READTHEDOCS' in os.environ and subprocess.check_call( - [sys.executable, 'bootstrap.py'], + [sys.executable, '-m', 'bootstrap'], cwd=os.path.join(os.path.dirname(__file__), os.path.pardir), ) diff --git a/docs/developer-guide.txt b/docs/developer-guide.txt index d145fba..0b4ae4d 100644 --- a/docs/developer-guide.txt +++ b/docs/developer-guide.txt @@ -104,12 +104,8 @@ from the command line after pushing a new branch. Testing ------- -The primary tests are run using tox. To run the tests, first create the metadata -needed to run the tests:: - - $ python bootstrap.py - -Then make sure you have tox installed, and invoke it:: +The primary tests are run using tox. Make sure you have tox installed, +and invoke it:: $ tox diff --git a/docs/releases.txt b/docs/releases.txt index 98ba39e..35b415c 100644 --- a/docs/releases.txt +++ b/docs/releases.txt @@ -3,39 +3,13 @@ Release Process =============== In order to allow for rapid, predictable releases, Setuptools uses a -mechanical technique for releases, enacted by Travis following a -successful build of a tagged release per -`PyPI deployment `_. - -Prior to cutting a release, please use `towncrier`_ to update -``CHANGES.rst`` to summarize the changes since the last release. -To update the changelog: - -1. Install towncrier via ``pip install towncrier`` if not already installed. -2. Preview the new ``CHANGES.rst`` entry by running - ``towncrier --draft --version {new.version.number}`` (enter the desired - version number for the next release). If any changes are needed, make - them and generate a new preview until the output is acceptable. Run - ``git add`` for any modified files. -3. Run ``towncrier --version {new.version.number}`` to stage the changelog - updates in git. -4. Verify that there are no remaining ``changelog.d/*.rst`` files. If a - file was named incorrectly, it may be ignored by towncrier. -5. Review the updated ``CHANGES.rst`` file. If any changes are needed, - make the edits and stage them via ``git add CHANGES.rst``. - -Once the changelog edits are staged and ready to commit, cut a release by -installing and running ``bump2version --allow-dirty {part}`` where ``part`` -is major, minor, or patch based on the scope of the changes in the -release. Then, push the commits to the master branch:: - - $ git push origin master - $ git push --tags - -If tests pass, the release will be uploaded to PyPI (from the Python 3.6 -tests). - -.. _towncrier: https://pypi.org/project/towncrier/ +mechanical technique for releases, enacted on tagged commits by +continuous integration. + +To finalize a release, run ``tox -e finalize``, review, then push +the changes. + +If tests pass, the release will be uploaded to PyPI. Release Frequency ----------------- diff --git a/setup.cfg b/setup.cfg index ecef860..cb5ae73 100644 --- a/setup.cfg +++ b/setup.cfg @@ -19,7 +19,7 @@ universal = 1 [metadata] name = setuptools -version = 44.0.0 +version = 44.1.0 description = Easily download, build, install, upgrade, and uninstall Python packages author = Python Packaging Authority author_email = distutils-sig@python.org diff --git a/setuptools/build_meta.py b/setuptools/build_meta.py index 10c4b52..eb9e815 100644 --- a/setuptools/build_meta.py +++ b/setuptools/build_meta.py @@ -232,6 +232,12 @@ class _BuildMetaLegacyBackend(_BuildMetaBackend): if script_dir not in sys.path: sys.path.insert(0, script_dir) + # Some setup.py scripts (e.g. in pygame and numpy) use sys.argv[0] to + # get the directory of the source code. They expect it to refer to the + # setup.py script. + sys_argv_0 = sys.argv[0] + sys.argv[0] = setup_script + try: super(_BuildMetaLegacyBackend, self).run_setup(setup_script=setup_script) @@ -242,6 +248,7 @@ class _BuildMetaLegacyBackend(_BuildMetaBackend): # the original path so that the path manipulation does not persist # within the hook after run_setup is called. sys.path[:] = sys_path + sys.argv[0] = sys_argv_0 # The primary backend _BACKEND = _BuildMetaBackend() diff --git a/setuptools/command/build_ext.py b/setuptools/command/build_ext.py index daa8e4f..1b51e04 100644 --- a/setuptools/command/build_ext.py +++ b/setuptools/command/build_ext.py @@ -113,7 +113,7 @@ class build_ext(_build_ext): if fullname in self.ext_map: ext = self.ext_map[fullname] use_abi3 = ( - six.PY3 + not six.PY2 and getattr(ext, 'py_limited_api') and get_abi3_suffix() ) diff --git a/setuptools/command/develop.py b/setuptools/command/develop.py index 009e4f9..b561924 100644 --- a/setuptools/command/develop.py +++ b/setuptools/command/develop.py @@ -108,7 +108,7 @@ class develop(namespaces.DevelopInstaller, easy_install): return path_to_setup def install_for_development(self): - if six.PY3 and getattr(self.distribution, 'use_2to3', False): + if not six.PY2 and getattr(self.distribution, 'use_2to3', False): # If we run 2to3 we can not do this inplace: # Ensure metadata is up-to-date diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py index 09066f8..426301d 100644 --- a/setuptools/command/easy_install.py +++ b/setuptools/command/easy_install.py @@ -1567,7 +1567,7 @@ def get_exe_prefixes(exe_filename): continue if parts[0].upper() in ('PURELIB', 'PLATLIB'): contents = z.read(name) - if six.PY3: + if not six.PY2: contents = contents.decode() for pth in yield_lines(contents): pth = pth.strip().replace('\\', '/') diff --git a/setuptools/command/egg_info.py b/setuptools/command/egg_info.py index 5d8f451..a5c5a2f 100644 --- a/setuptools/command/egg_info.py +++ b/setuptools/command/egg_info.py @@ -266,7 +266,7 @@ class egg_info(InfoCommon, Command): to the file. """ log.info("writing %s to %s", what, filename) - if six.PY3: + if not six.PY2: data = data.encode("utf-8") if not self.dry_run: f = open(filename, 'wb') diff --git a/setuptools/command/sdist.py b/setuptools/command/sdist.py index a851453..8c3438e 100644 --- a/setuptools/command/sdist.py +++ b/setuptools/command/sdist.py @@ -207,7 +207,7 @@ class sdist(sdist_add_defaults, orig.sdist): manifest = open(self.manifest, 'rb') for line in manifest: # The manifest must contain UTF-8. See #303. - if six.PY3: + if not six.PY2: try: line = line.decode('UTF-8') except UnicodeDecodeError: diff --git a/setuptools/command/test.py b/setuptools/command/test.py index c148b38..f6470e9 100644 --- a/setuptools/command/test.py +++ b/setuptools/command/test.py @@ -129,7 +129,7 @@ class test(Command): @contextlib.contextmanager def project_on_sys_path(self, include_dists=[]): - with_2to3 = six.PY3 and getattr(self.distribution, 'use_2to3', False) + with_2to3 = not six.PY2 and getattr(self.distribution, 'use_2to3', False) if with_2to3: # If we run 2to3 we can not do this inplace: @@ -240,7 +240,7 @@ class test(Command): # Purge modules under test from sys.modules. The test loader will # re-import them from the build location. Required when 2to3 is used # with namespace packages. - if six.PY3 and getattr(self.distribution, 'use_2to3', False): + if not six.PY2 and getattr(self.distribution, 'use_2to3', False): module = self.test_suite.split('.')[0] if module in _namespace_packages: del_modules = [] diff --git a/setuptools/command/upload_docs.py b/setuptools/command/upload_docs.py index 07aa564..130a0cb 100644 --- a/setuptools/command/upload_docs.py +++ b/setuptools/command/upload_docs.py @@ -24,7 +24,7 @@ from .upload import upload def _encode(s): - errors = 'surrogateescape' if six.PY3 else 'strict' + errors = 'strict' if six.PY2 else 'surrogateescape' return s.encode('utf-8', errors) @@ -153,7 +153,7 @@ class upload_docs(upload): # set up the authentication credentials = _encode(self.username + ':' + self.password) credentials = standard_b64encode(credentials) - if six.PY3: + if not six.PY2: credentials = credentials.decode('ascii') auth = "Basic " + credentials diff --git a/setuptools/dist.py b/setuptools/dist.py index 1ba262e..f6453a0 100644 --- a/setuptools/dist.py +++ b/setuptools/dist.py @@ -571,7 +571,7 @@ class Distribution(_Distribution): from setuptools.extern.six.moves.configparser import ConfigParser # Ignore install directory options if we have a venv - if six.PY3 and sys.prefix != sys.base_prefix: + if not six.PY2 and sys.prefix != sys.base_prefix: ignore_options = [ 'install-base', 'install-platbase', 'install-lib', 'install-platlib', 'install-purelib', 'install-headers', @@ -593,7 +593,7 @@ class Distribution(_Distribution): with io.open(filename, encoding='utf-8') as reader: if DEBUG: self.announce(" reading {filename}".format(**locals())) - (parser.read_file if six.PY3 else parser.readfp)(reader) + (parser.readfp if six.PY2 else parser.read_file)(reader) for section in parser.sections(): options = parser.options(section) opt_dict = self.get_option_dict(section) @@ -636,7 +636,7 @@ class Distribution(_Distribution): Ref #1653 """ - if six.PY3: + if not six.PY2: return val try: return val.encode() @@ -731,13 +731,13 @@ class Distribution(_Distribution): to influence the order of execution. Smaller numbers go first and the default is 0. """ - hook_key = 'setuptools.finalize_distribution_options' + group = 'setuptools.finalize_distribution_options' def by_order(hook): return getattr(hook, 'order', 0) - eps = pkg_resources.iter_entry_points(hook_key) + eps = map(lambda e: e.load(), pkg_resources.iter_entry_points(group)) for ep in sorted(eps, key=by_order): - ep.load()(self) + ep(self) def _finalize_setup_keywords(self): for ep in pkg_resources.iter_entry_points('distutils.setup_keywords'): diff --git a/setuptools/tests/test_build_meta.py b/setuptools/tests/test_build_meta.py index 326b4f5..d68444f 100644 --- a/setuptools/tests/test_build_meta.py +++ b/setuptools/tests/test_build_meta.py @@ -406,6 +406,28 @@ class TestBuildMetaBackend: assert expected == sorted(actual) + _sys_argv_0_passthrough = { + 'setup.py': DALS(""" + import os + import sys + + __import__('setuptools').setup( + name='foo', + version='0.0.0', + ) + + sys_argv = os.path.abspath(sys.argv[0]) + file_path = os.path.abspath('setup.py') + assert sys_argv == file_path + """) + } + + def test_sys_argv_passthrough(self, tmpdir_cwd): + build_files(self._sys_argv_0_passthrough) + build_backend = self.get_build_backend() + with pytest.raises(AssertionError): + build_backend.build_sdist("temp") + class TestBuildMetaLegacyBackend(TestBuildMetaBackend): backend_name = 'setuptools.build_meta:__legacy__' @@ -417,3 +439,9 @@ class TestBuildMetaLegacyBackend(TestBuildMetaBackend): build_backend = self.get_build_backend() build_backend.build_sdist("temp") + + def test_sys_argv_passthrough(self, tmpdir_cwd): + build_files(self._sys_argv_0_passthrough) + + build_backend = self.get_build_backend() + build_backend.build_sdist("temp") diff --git a/setuptools/tests/test_develop.py b/setuptools/tests/test_develop.py index 00d4bd9..792975f 100644 --- a/setuptools/tests/test_develop.py +++ b/setuptools/tests/test_develop.py @@ -95,7 +95,7 @@ class TestDevelop: with io.open(fn) as init_file: init = init_file.read().strip() - expected = 'print("foo")' if six.PY3 else 'print "foo"' + expected = 'print "foo"' if six.PY2 else 'print("foo")' assert init == expected def test_console_scripts(self, tmpdir): @@ -161,7 +161,7 @@ class TestNamespaces: reason="https://github.com/pypa/setuptools/issues/851", ) @pytest.mark.skipif( - platform.python_implementation() == 'PyPy' and six.PY3, + platform.python_implementation() == 'PyPy' and not six.PY2, reason="https://github.com/pypa/setuptools/issues/1202", ) def test_namespace_package_importable(self, tmpdir): diff --git a/setuptools/tests/test_sdist.py b/setuptools/tests/test_sdist.py index 8538dd2..0bea53d 100644 --- a/setuptools/tests/test_sdist.py +++ b/setuptools/tests/test_sdist.py @@ -51,7 +51,7 @@ def quiet(): # Convert to POSIX path def posix(path): - if six.PY3 and not isinstance(path, str): + if not six.PY2 and not isinstance(path, str): return path.replace(os.sep.encode('ascii'), b'/') else: return path.replace(os.sep, '/') @@ -329,7 +329,7 @@ class TestSdistTest: cmd.read_manifest() # The filelist should contain the UTF-8 filename - if six.PY3: + if not six.PY2: filename = filename.decode('utf-8') assert filename in cmd.filelist.files @@ -383,7 +383,7 @@ class TestSdistTest: if sys.platform == 'darwin': filename = decompose(filename) - if six.PY3: + if not six.PY2: fs_enc = sys.getfilesystemencoding() if sys.platform == 'win32': @@ -425,7 +425,19 @@ class TestSdistTest: with quiet(): cmd.run() - if six.PY3: + if six.PY2: + # Under Python 2 there seems to be no decoded string in the + # filelist. However, due to decode and encoding of the + # file name to get utf-8 Manifest the latin1 maybe excluded + try: + # fs_enc should match how one is expect the decoding to + # be proformed for the manifest output. + fs_enc = sys.getfilesystemencoding() + filename.decode(fs_enc) + assert filename in cmd.filelist.files + except UnicodeDecodeError: + filename not in cmd.filelist.files + else: # not all windows systems have a default FS encoding of cp1252 if sys.platform == 'win32': # Latin-1 is similar to Windows-1252 however @@ -440,18 +452,6 @@ class TestSdistTest: # The Latin-1 filename should have been skipped filename = filename.decode('latin-1') filename not in cmd.filelist.files - else: - # Under Python 2 there seems to be no decoded string in the - # filelist. However, due to decode and encoding of the - # file name to get utf-8 Manifest the latin1 maybe excluded - try: - # fs_enc should match how one is expect the decoding to - # be proformed for the manifest output. - fs_enc = sys.getfilesystemencoding() - filename.decode(fs_enc) - assert filename in cmd.filelist.files - except UnicodeDecodeError: - filename not in cmd.filelist.files def test_pyproject_toml_in_sdist(self, tmpdir): """ diff --git a/setuptools/tests/test_setopt.py b/setuptools/tests/test_setopt.py index 3fb04fb..1b03895 100644 --- a/setuptools/tests/test_setopt.py +++ b/setuptools/tests/test_setopt.py @@ -15,7 +15,7 @@ class TestEdit: def parse_config(filename): parser = configparser.ConfigParser() with io.open(filename, encoding='utf-8') as reader: - (parser.read_file if six.PY3 else parser.readfp)(reader) + (parser.readfp if six.PY2 else parser.read_file)(reader) return parser @staticmethod diff --git a/tools/finalize.py b/tools/finalize.py new file mode 100644 index 0000000..3b66341 --- /dev/null +++ b/tools/finalize.py @@ -0,0 +1,59 @@ +""" +Finalize the repo for a release. Invokes towncrier and bumpversion. +""" + +__requires__ = ['bump2version', 'towncrier'] + + +import subprocess +import pathlib +import re +import sys + + +def release_kind(): + """ + Determine which release to make based on the files in the + changelog. + """ + # use min here as 'major' < 'minor' < 'patch' + return min( + 'major' if 'breaking' in file.name else + 'minor' if 'change' in file.name else + 'patch' + for file in pathlib.Path('changelog.d').iterdir() + ) + + +bump_version_command = [ + sys.executable, + '-m', 'bumpversion', + release_kind(), +] + + +def get_version(): + cmd = bump_version_command + ['--dry-run', '--verbose'] + out = subprocess.check_output(cmd, text=True) + return re.search('^new_version=(.*)', out, re.MULTILINE).group(1) + + +def update_changelog(): + cmd = [ + sys.executable, '-m', + 'towncrier', + '--version', get_version(), + '--yes', + ] + subprocess.check_call(cmd) + + +def bump_version(): + cmd = bump_version_command + ['--allow-dirty'] + subprocess.check_call(cmd) + + +if __name__ == '__main__': + print("Cutting release at", get_version()) + update_changelog() + bump_version() diff --git a/tools/tox_pip.py b/tools/tox_pip.py index 63518f9..ba77663 100644 --- a/tools/tox_pip.py +++ b/tools/tox_pip.py @@ -1,31 +1,31 @@ -import os -import shutil import subprocess import sys -from glob import glob -VIRTUAL_ENV = os.environ['VIRTUAL_ENV'] -TOX_PIP_DIR = os.path.join(VIRTUAL_ENV, 'pip') + +def remove_setuptools(): + """ + Remove setuptools from the current environment. + """ + print("Removing setuptools") + cmd = [sys.executable, '-m', 'pip', 'uninstall', '-y', 'setuptools'] + # set cwd to something other than '.' to avoid detecting + # '.' as the installed package. + subprocess.check_call(cmd, cwd='.tox') + + +def bootstrap(): + print("Running bootstrap") + cmd = [sys.executable, '-m', 'bootstrap'] + subprocess.check_call(cmd) def pip(args): - # First things first, get a recent (stable) version of pip. - if not os.path.exists(TOX_PIP_DIR): - subprocess.check_call([sys.executable, '-m', 'pip', - '--disable-pip-version-check', - 'install', '-t', TOX_PIP_DIR, - 'pip']) - shutil.rmtree(glob(os.path.join(TOX_PIP_DIR, 'pip-*.dist-info'))[0]) - # And use that version. - pypath = os.environ.get('PYTHONPATH') - pypath = pypath.split(os.pathsep) if pypath is not None else [] - pypath.insert(0, TOX_PIP_DIR) - os.environ['PYTHONPATH'] = os.pathsep.join(pypath) - # Fix call for setuptools editable install. - for n, a in enumerate(args): - if a == '.': - args[n] = os.getcwd() - subprocess.check_call([sys.executable, '-m', 'pip'] + args, cwd=TOX_PIP_DIR) + if '.' in args: + remove_setuptools() + bootstrap() + + cmd = [sys.executable, '-m', 'pip'] + args + subprocess.check_call(cmd) if __name__ == '__main__': diff --git a/tox.ini b/tox.ini index 6a1af56..3fc6a56 100644 --- a/tox.ini +++ b/tox.ini @@ -1,20 +1,22 @@ -# Note: Run "python bootstrap.py" before running Tox, to generate metadata. -# # To run Tox against all supported Python interpreters, you can set: # # export TOXENV='py27,py3{5,6,7,8},pypy,pypy3' [tox] envlist=python +minversion = 3.2 +requires = + tox-pip-version >= 0.0.6 + # workaround for #1998 + virtualenv < 20 [helpers] -# Wrapper for calls to pip that make sure the version being used is a -# up-to-date, and to prevent the current working directory from being -# added to `sys.path`. +# Custom pip behavior pip = python {toxinidir}/tools/tox_pip.py [testenv] deps=-r{toxinidir}/tests/requirements.txt +pip_version = pip install_command = {[helpers]pip} install {opts} {packages} list_dependencies_command = {[helpers]pip} freeze --all setenv=COVERAGE_FILE={toxworkdir}/.coverage.{envname} @@ -45,7 +47,7 @@ commands=codecov -X gcov --file {toxworkdir}/coverage.xml deps = -r{toxinidir}/docs/requirements.txt skip_install=True commands = - python {toxinidir}/bootstrap.py + python -m bootstrap sphinx-build -W -b html -d {envtmpdir}/doctrees docs docs/build/html sphinx-build -W -b man -d {envtmpdir}/doctrees docs docs/build/man @@ -56,6 +58,14 @@ source= omit= */_vendor/* +[testenv:finalize] +skip_install = True +deps = + towncrier + bump2version +commands = + python tools/finalize.py + [testenv:release] skip_install = True deps =