From 91e2065b61b147af39c106fd796d674b021af37b Mon Sep 17 00:00:00 2001 From: JinWang An Date: Mon, 27 Mar 2023 17:02:57 +0900 Subject: [PATCH] Imported Upstream version 65.6.1 --- .bumpversion.cfg | 2 +- .github/workflows/main.yml | 8 +- CHANGES.rst | 18 ++++ docs/build_meta.rst | 6 +- docs/conf.py | 1 - docs/deprecated/distutils-legacy.rst | 9 ++ docs/deprecated/distutils/commandref.rst | 2 - docs/deprecated/distutils/configfile.rst | 1 - docs/deprecated/distutils/extending.rst | 2 - docs/deprecated/zip_safe.rst | 2 +- docs/userguide/development_mode.rst | 6 +- docs/userguide/entry_point.rst | 2 +- docs/userguide/quickstart.rst | 2 +- launcher.c | 9 +- setup.cfg | 2 +- setuptools/_distutils/log.py | 19 ++++ setuptools/_entry_points.py | 10 +- setuptools/build_meta.py | 3 +- setuptools/command/build_clib.py | 2 +- setuptools/command/upload_docs.py | 1 - setuptools/dist.py | 13 +-- setuptools/tests/script-with-bom.py | 4 +- setuptools/tests/test_build_clib.py | 28 +++++ setuptools/tests/test_build_meta.py | 4 +- setuptools/tests/test_config_discovery.py | 13 +++ setuptools/tests/test_egg_info.py | 75 ++++++++++---- setuptools/tests/test_manifest.py | 119 +++++++++++----------- setuptools/tests/test_msvc14.py | 1 - setuptools/tests/test_wheel.py | 2 - 29 files changed, 234 insertions(+), 132 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 6a4b339..d3921d9 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 65.6.0 +current_version = 65.6.1 commit = True tag = True diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index a877b76..7413fa7 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -131,9 +131,9 @@ jobs: runs-on: ${{ matrix.platform }} timeout-minutes: 75 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Install Cygwin with Python - uses: cygwin/cygwin-install-action@v1 + uses: cygwin/cygwin-install-action@v2 with: platform: x86_64 packages: >- @@ -187,13 +187,13 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 75 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Install OS-level dependencies run: | sudo apt-get update sudo apt-get install build-essential gfortran libopenblas-dev - name: Setup Python - uses: actions/setup-python@v2 + uses: actions/setup-python@v4 with: # Use a release that is not very new but still have a long life: python-version: "3.8" diff --git a/CHANGES.rst b/CHANGES.rst index 5a24ff7..52a8796 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,3 +1,21 @@ +v65.6.1 +------- + + +Documentation changes +^^^^^^^^^^^^^^^^^^^^^ +* #3689: Document that ``distutils.cfg`` might be ignored unless + ``SETUPTOOLS_USE_DISTUTILS=stdlib``. + +Misc +^^^^ +* #3678: Improve clib builds reproducibility by sorting sources -- by :user:`danigm` +* #3684: Improved exception/traceback when invalid entry-points are specified. +* #3690: Fixed logging errors: 'underlying buffer has been detached' (issue #1631). +* #3693: Merge pypa/distutils@3e9d47e with compatibility fix for distutils.log.Log. +* #3704: Fix temporary build directories interference with auto-discovery. + + v65.6.0 ------- diff --git a/docs/build_meta.rst b/docs/build_meta.rst index 3c778d8..37738b8 100644 --- a/docs/build_meta.rst +++ b/docs/build_meta.rst @@ -48,8 +48,8 @@ files, a ``pyproject.toml`` file and a ``setup.cfg`` file:: pyproject.toml setup.cfg meowpkg/ - __init__.py - module.py + __init__.py + module.py The ``pyproject.toml`` file specifies the build system (i.e. what is being used to package your scripts and install from source). To use it with @@ -161,7 +161,7 @@ requirements. and :pypi:`setuptools-svn`), or by correctly setting up :ref:`MANIFEST.in `. - The generated ``.tar.gz`` and ``.whl`` files are compressed archives that + The generated ``.tar.gz`` and ``.whl`` files are compressed archives that can be inspected as follows: On POSIX systems, this can be done with ``tar -tf dist/*.tar.gz`` and ``unzip -l dist/*.whl``. diff --git a/docs/conf.py b/docs/conf.py index a9c9800..64c2625 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -1,5 +1,4 @@ #!/usr/bin/env python3 -# -*- coding: utf-8 -*- extensions = [ 'sphinx.ext.autodoc', diff --git a/docs/deprecated/distutils-legacy.rst b/docs/deprecated/distutils-legacy.rst index e106ce9..63c8ff0 100644 --- a/docs/deprecated/distutils-legacy.rst +++ b/docs/deprecated/distutils-legacy.rst @@ -7,6 +7,15 @@ Since the 60.0.0 release, Setuptools includes a local, vendored copy of distutil SETUPTOOLS_USE_DISTUTILS=stdlib +.. warning:: + Please note that this also affects how ``distutils.cfg`` files inside stdlib's ``distutils`` + package directory are processed. + Unless ``SETUPTOOLS_USE_DISTUTILS=stdlib``, they will have no effect on the build process. + + You can still use a global user config file, ``~/.pydistutils.cfg`` (POSIX) or ``%USERPROFILE%/pydistutils.cfg`` (Windows), + or use the environment variable :doc:`DIST_EXTRA_CONFIG ` to point to another + supplementary configuration file. + Prefer Setuptools ----------------- diff --git a/docs/deprecated/distutils/commandref.rst b/docs/deprecated/distutils/commandref.rst index 3e247e6..d02b38c 100644 --- a/docs/deprecated/distutils/commandref.rst +++ b/docs/deprecated/distutils/commandref.rst @@ -101,5 +101,3 @@ anything except backslash or colon. .. % \subsection{\protect\command{bdist}} .. % \subsection{\protect\command{bdist\_dumb}} .. % \subsection{\protect\command{bdist\_rpm}} - - diff --git a/docs/deprecated/distutils/configfile.rst b/docs/deprecated/distutils/configfile.rst index 2a0fbb3..ab199dc 100644 --- a/docs/deprecated/distutils/configfile.rst +++ b/docs/deprecated/distutils/configfile.rst @@ -142,4 +142,3 @@ split across multiple lines for readability. .. [#] This ideal probably won't be achieved until auto-configuration is fully supported by the Distutils. - diff --git a/docs/deprecated/distutils/extending.rst b/docs/deprecated/distutils/extending.rst index c99d3c7..fc49461 100644 --- a/docs/deprecated/distutils/extending.rst +++ b/docs/deprecated/distutils/extending.rst @@ -94,5 +94,3 @@ to add ``(command, filename)`` pairs to ``self.distribution.dist_files`` so that :command:`upload` can upload it to PyPI. The *filename* in the pair contains no path information, only the name of the file itself. In dry-run mode, pairs should still be added to represent what would have been created. - - diff --git a/docs/deprecated/zip_safe.rst b/docs/deprecated/zip_safe.rst index 08a1333..26b4566 100644 --- a/docs/deprecated/zip_safe.rst +++ b/docs/deprecated/zip_safe.rst @@ -62,7 +62,7 @@ Currently, popular Python package installers (such as :pypi:`pip`) and package indexes (such as PyPI_) consider that distribution packages are always installed as a directory. It is however still possible to load packages from zip files added to -:obj:`sys.path`, thanks to the :mod:`zipimport` module +:obj:`sys.path`, thanks to the :mod:`zipimport` module and the :mod:`importlib` machinery provided by Python standard library. When working with modules loaded from a zip file, it is important to keep in diff --git a/docs/userguide/development_mode.rst b/docs/userguide/development_mode.rst index 1716e0a..6f9f541 100644 --- a/docs/userguide/development_mode.rst +++ b/docs/userguide/development_mode.rst @@ -17,7 +17,7 @@ without requiring a new installation. You can enter this "development mode" by performing an :doc:`editable installation ` inside of a :term:`virtual environment`, -using :doc:`pip's ` ``-e/--editable`` flag, as shown bellow: +using :doc:`pip's ` ``-e/--editable`` flag, as shown below: .. code-block:: bash @@ -69,7 +69,7 @@ Please have a look on the following section if you are looking for a different b sudo apt install python3-venv - Alternatively, you can also try installing :pypi:`virtualenᴠ`. + Alternatively, you can also try installing :pypi:`virtualenv`. More information is available on the Python Packaging User Guide on :doc:`PyPUG:guides/installing-using-pip-and-virtual-environments`. @@ -93,7 +93,7 @@ expectations: Unfortunately these expectations are in conflict with each other. To solve this problem ``setuptools`` allows developers to choose a more *"strict"* mode for the editable installation. This can be done by passing -a special *configuration setting* via :pypi:`pip`, as indicated bellow: +a special *configuration setting* via :pypi:`pip`, as indicated below: .. code-block:: bash diff --git a/docs/userguide/entry_point.rst b/docs/userguide/entry_point.rst index 6ba0028..163ce1d 100644 --- a/docs/userguide/entry_point.rst +++ b/docs/userguide/entry_point.rst @@ -89,7 +89,7 @@ configuration: .. tab:: setup.py .. code-block:: python - + from setuptools import setup setup( diff --git a/docs/userguide/quickstart.rst b/docs/userguide/quickstart.rst index fe5c5bc..bf92f6a 100644 --- a/docs/userguide/quickstart.rst +++ b/docs/userguide/quickstart.rst @@ -165,7 +165,7 @@ to specify to properly package your project. :doc:`setup.cfg `, and keep the ``setup.py`` minimal with only the dynamic parts (or even omit it completely if applicable). - See `Why you shouldn't invoke setup.py directly`_ for more background. + See `Why you shouldn't invoke setup.py directly`_ for more background. .. _Why you shouldn't invoke setup.py directly: https://blog.ganssle.io/articles/2021/10/setup-py-deprecated.html diff --git a/launcher.c b/launcher.c index 23ef3ac..83b4878 100644 --- a/launcher.c +++ b/launcher.c @@ -180,7 +180,7 @@ void pass_control_to_child(DWORD control_type) { } BOOL control_handler(DWORD control_type) { - /* + /* * distribute-issue207 * control event handler callback function */ @@ -204,12 +204,12 @@ int create_and_wait_for_subprocess(char* command) { ZeroMemory(&p_info, sizeof(p_info)); ZeroMemory(&s_info, sizeof(s_info)); s_info.cb = sizeof(STARTUPINFO); - // set-up control handler callback funciotn + // set-up control handler callback function SetConsoleCtrlHandler((PHANDLER_ROUTINE) control_handler, TRUE); if (!CreateProcessA(NULL, commandline, NULL, NULL, TRUE, 0, NULL, NULL, &s_info, &p_info)) { fprintf(stderr, "failed to create process.\n"); return 0; - } + } child_pid = p_info.dwProcessId; // wait for Python to exit WaitForSingleObject(p_info.hProcess, INFINITE); @@ -229,7 +229,7 @@ char* join_executable_and_args(char *executable, char **args, int argc) */ int len,counter; char* cmdline; - + len=strlen(executable)+2; for (counter=1; counter= 2: set_threshold(logging.DEBUG) + + +class Log(logging.Logger): + """distutils.log.Log is deprecated, please use an alternative from `logging`.""" + + def __init__(self, threshold=WARN): + warnings.warn(Log.__doc__) # avoid DeprecationWarning to ensure warn is shown + super().__init__(__name__, level=threshold) + + @property + def threshold(self): + return self.level + + @threshold.setter + def threshold(self, level): + self.setLevel(level) + + warn = logging.Logger.warning diff --git a/setuptools/_entry_points.py b/setuptools/_entry_points.py index f087681..a234634 100644 --- a/setuptools/_entry_points.py +++ b/setuptools/_entry_points.py @@ -2,6 +2,7 @@ import functools import operator import itertools +from .errors import OptionError from .extern.jaraco.text import yield_lines from .extern.jaraco.functools import pass_none from ._importlib import metadata @@ -14,7 +15,14 @@ def ensure_valid(ep): Exercise one of the dynamic properties to trigger the pattern match. """ - ep.extras + try: + ep.extras + except AttributeError as ex: + msg = ( + f"Problems to parse {ep}.\nPlease ensure entry-point follows the spec: " + "https://packaging.python.org/en/latest/specifications/entry-points/" + ) + raise OptionError(msg) from ex def load_group(value, group): diff --git a/setuptools/build_meta.py b/setuptools/build_meta.py index e8f1c72..1fb4c3b 100644 --- a/setuptools/build_meta.py +++ b/setuptools/build_meta.py @@ -385,7 +385,8 @@ class _BuildMetaBackend(_ConfigSettingsTranslator): # Build in a temporary directory, then copy to the target. os.makedirs(result_directory, exist_ok=True) - with tempfile.TemporaryDirectory(dir=result_directory) as tmp_dist_dir: + temp_opts = {"prefix": ".tmp-", "dir": result_directory} + with tempfile.TemporaryDirectory(**temp_opts) as tmp_dist_dir: sys.argv = [ *sys.argv[:1], *self._global_args(config_settings), diff --git a/setuptools/command/build_clib.py b/setuptools/command/build_clib.py index 67ce244..09483e6 100644 --- a/setuptools/command/build_clib.py +++ b/setuptools/command/build_clib.py @@ -28,7 +28,7 @@ class build_clib(orig.build_clib): "in 'libraries' option (library '%s'), " "'sources' must be present and must be " "a list of source filenames" % lib_name) - sources = list(sources) + sources = sorted(list(sources)) log.info("building '%s' library", lib_name) diff --git a/setuptools/command/upload_docs.py b/setuptools/command/upload_docs.py index 3263f07..63eb28c 100644 --- a/setuptools/command/upload_docs.py +++ b/setuptools/command/upload_docs.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """upload_docs Implements a Distutils 'upload_docs' subcommand (upload documentation to diff --git a/setuptools/dist.py b/setuptools/dist.py index 8242354..1c71e5e 100644 --- a/setuptools/dist.py +++ b/setuptools/dist.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- __all__ = ['Distribution'] import io @@ -1195,19 +1194,11 @@ class Distribution(_Distribution): # Print metadata in UTF-8 no matter the platform encoding = sys.stdout.encoding - errors = sys.stdout.errors - newline = sys.platform != 'win32' and '\n' or None - line_buffering = sys.stdout.line_buffering - - sys.stdout = io.TextIOWrapper( - sys.stdout.detach(), 'utf-8', errors, newline, line_buffering - ) + sys.stdout.reconfigure(encoding='utf-8') try: return _Distribution.handle_display_options(self, option_order) finally: - sys.stdout = io.TextIOWrapper( - sys.stdout.detach(), encoding, errors, newline, line_buffering - ) + sys.stdout.reconfigure(encoding=encoding) def run_command(self, command): self.set_defaults() diff --git a/setuptools/tests/script-with-bom.py b/setuptools/tests/script-with-bom.py index 22dee0d..93d28f1 100644 --- a/setuptools/tests/script-with-bom.py +++ b/setuptools/tests/script-with-bom.py @@ -1,3 +1 @@ -# -*- coding: utf-8 -*- - -result = 'passed' +result = 'passed' diff --git a/setuptools/tests/test_build_clib.py b/setuptools/tests/test_build_clib.py index af9e7c6..2d9273c 100644 --- a/setuptools/tests/test_build_clib.py +++ b/setuptools/tests/test_build_clib.py @@ -2,6 +2,7 @@ from unittest import mock import pytest +import random from distutils.errors import DistutilsSetupError from setuptools.command.build_clib import build_clib from setuptools.dist import Distribution @@ -56,3 +57,30 @@ class TestBuildCLib: cmd.build_libraries(libs) assert cmd.compiler.compile.call_count == 1 assert cmd.compiler.create_static_lib.call_count == 1 + + @mock.patch( + 'setuptools.command.build_clib.newer_pairwise_group') + def test_build_libraries_reproducible(self, mock_newer): + dist = Distribution() + cmd = build_clib(dist) + + # with that out of the way, let's see if the crude dependency + # system works + cmd.compiler = mock.MagicMock(spec=cmd.compiler) + mock_newer.return_value = ([], []) + + original_sources = ['a-example.c', 'example.c'] + sources = original_sources + + obj_deps = {'': ('global.h',), 'example.c': ('example.h',)} + libs = [('example', {'sources': sources, 'obj_deps': obj_deps})] + + cmd.build_libraries(libs) + computed_call_args = mock_newer.call_args[0] + + while sources == original_sources: + sources = random.sample(original_sources, len(original_sources)) + libs = [('example', {'sources': sources, 'obj_deps': obj_deps})] + + cmd.build_libraries(libs) + assert computed_call_args == mock_newer.call_args[0] diff --git a/setuptools/tests/test_build_meta.py b/setuptools/tests/test_build_meta.py index bf1c27f..9e55a93 100644 --- a/setuptools/tests/test_build_meta.py +++ b/setuptools/tests/test_build_meta.py @@ -44,7 +44,7 @@ class BuildBackend(BuildBackendBase): self.pool = futures.ProcessPoolExecutor(max_workers=1) def __getattr__(self, name): - """Handles aribrary function invocations on the build backend.""" + """Handles arbitrary function invocations on the build backend.""" def method(*args, **kw): root = os.path.abspath(self.cwd) @@ -79,7 +79,7 @@ class BuildBackendCaller(BuildBackendBase): self.backend_obj) = self.backend_name.partition(':') def __call__(self, name, *args, **kw): - """Handles aribrary function invocations on the build backend.""" + """Handles arbitrary function invocations on the build backend.""" os.chdir(self.cwd) os.environ.update(self.env) mod = importlib.import_module(self.backend_name) diff --git a/setuptools/tests/test_config_discovery.py b/setuptools/tests/test_config_discovery.py index 85b64b3..f65b00b 100644 --- a/setuptools/tests/test_config_discovery.py +++ b/setuptools/tests/test_config_discovery.py @@ -248,6 +248,19 @@ class TestDiscoverPackagesAndPyModules: with pytest.raises(PackageDiscoveryError, match="multiple (packages|modules)"): _get_dist(tmp_path, {}) + def test_py_modules_when_wheel_dir_is_cwd(self, tmp_path): + """Regression for issue 3692""" + from setuptools import build_meta + + pyproject = '[project]\nname = "test"\nversion = "1"' + (tmp_path / "pyproject.toml").write_text(DALS(pyproject), encoding="utf-8") + (tmp_path / "foo.py").touch() + with jaraco.path.DirectoryStack().context(tmp_path): + build_meta.build_wheel(".") + # Ensure py_modules are found + wheel_files = get_wheel_members(next(tmp_path.glob("*.whl"))) + assert "foo.py" in wheel_files + class TestNoConfig: DEFAULT_VERSION = "0.0.0" # Default version given by setuptools diff --git a/setuptools/tests/test_egg_info.py b/setuptools/tests/test_egg_info.py index ee07b5a..387773c 100644 --- a/setuptools/tests/test_egg_info.py +++ b/setuptools/tests/test_egg_info.py @@ -6,12 +6,18 @@ import re import stat import time from typing import List, Tuple +from pathlib import Path import pytest from jaraco import path +from setuptools import errors from setuptools.command.egg_info import ( - egg_info, manifest_maker, EggInfoDeprecationWarning, get_pkg_info_revision, + EggInfoDeprecationWarning, + egg_info, + get_pkg_info_revision, + manifest_maker, + write_entries, ) from setuptools.dist import Distribution @@ -24,6 +30,28 @@ class Environment(str): pass +@pytest.fixture +def env(): + with contexts.tempdir(prefix='setuptools-test.') as env_dir: + env = Environment(env_dir) + os.chmod(env_dir, stat.S_IRWXU) + subs = 'home', 'lib', 'scripts', 'data', 'egg-base' + env.paths = dict( + (dirname, os.path.join(env_dir, dirname)) + for dirname in subs + ) + list(map(os.mkdir, env.paths.values())) + path.build({ + env.paths['home']: { + '.pydistutils.cfg': DALS(""" + [egg_info] + egg-base = %(egg-base)s + """ % env.paths) + } + }) + yield env + + class TestEggInfo: setup_script = DALS(""" @@ -51,27 +79,6 @@ class TestEggInfo: version_str = pkg_info_lines[0].split(' ')[1] return tuple(map(int, version_str.split('.')[:2])) - @pytest.fixture - def env(self): - with contexts.tempdir(prefix='setuptools-test.') as env_dir: - env = Environment(env_dir) - os.chmod(env_dir, stat.S_IRWXU) - subs = 'home', 'lib', 'scripts', 'data', 'egg-base' - env.paths = dict( - (dirname, os.path.join(env_dir, dirname)) - for dirname in subs - ) - list(map(os.mkdir, env.paths.values())) - path.build({ - env.paths['home']: { - '.pydistutils.cfg': DALS(""" - [egg_info] - egg-base = %(egg-base)s - """ % env.paths) - } - }) - yield env - def test_egg_info_save_version_info_setup_empty(self, tmpdir_cwd, env): """ When the egg_info section is empty or not present, running @@ -1084,3 +1091,27 @@ class TestEggInfo: def test_get_pkg_info_revision_deprecated(self): pytest.warns(EggInfoDeprecationWarning, get_pkg_info_revision) + + +class TestWriteEntries: + + def test_invalid_entry_point(self, tmpdir_cwd, env): + dist = Distribution({"name": "foo", "version": "0.0.1"}) + dist.entry_points = {"foo": "foo = invalid-identifier:foo"} + cmd = dist.get_command_obj("egg_info") + expected_msg = r"Problems to parse .*invalid-identifier.*" + with pytest.raises(errors.OptionError, match=expected_msg) as ex: + write_entries(cmd, "entry_points", "entry_points.txt") + assert "ensure entry-point follows the spec" in ex.value.args[0] + + def test_valid_entry_point(self, tmpdir_cwd, env): + dist = Distribution({"name": "foo", "version": "0.0.1"}) + dist.entry_points = { + "abc": "foo = bar:baz", + "def": ["faa = bor:boz"], + } + cmd = dist.get_command_obj("egg_info") + write_entries(cmd, "entry_points", "entry_points.txt") + content = Path("entry_points.txt").read_text(encoding="utf-8") + assert "[abc]\nfoo = bar:baz\n" in content + assert "[def]\nfaa = bor:boz\n" in content diff --git a/setuptools/tests/test_manifest.py b/setuptools/tests/test_manifest.py index ecc83c2..3a973b0 100644 --- a/setuptools/tests/test_manifest.py +++ b/setuptools/tests/test_manifest.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """sdist tests""" import contextlib @@ -8,6 +7,7 @@ import sys import tempfile import itertools import io +import logging from distutils import log from distutils.errors import DistutilsTemplateError @@ -18,6 +18,9 @@ from setuptools.tests.textwrap import DALS import pytest +IS_PYPY = '__pypy__' in sys.builtin_module_names + + def make_local_path(s): """Converts '/' in a string to os.sep""" return s.replace('/', os.sep) @@ -321,43 +324,29 @@ class TestFileListTest(TempDirTestCase): to ensure setuptools' version of FileList keeps parity with distutils. """ - def setup_method(self, method): - if not hasattr(log, 'Log'): - pytest.skip("These tests rely on old logging infra") - super(TestFileListTest, self).setup_method(method) - self.threshold = log.set_threshold(log.FATAL) - self._old_log = log.Log._log - log.Log._log = self._log - self.logs = [] + @pytest.fixture(autouse=os.getenv("SETUPTOOLS_USE_DISTUTILS") == "stdlib") + def _compat_record_logs(self, monkeypatch, caplog): + """Account for stdlib compatibility""" + def _log(_logger, level, msg, args): + exc = sys.exc_info() + rec = logging.LogRecord("distutils", level, "", 0, msg, args, exc) + caplog.records.append(rec) - def teardown_method(self, method): - log.set_threshold(self.threshold) - log.Log._log = self._old_log - super(TestFileListTest, self).teardown_method(method) - - def _log(self, level, msg, args): - if level not in (log.DEBUG, log.INFO, log.WARN, log.ERROR, log.FATAL): - raise ValueError('%s wrong log level' % str(level)) - self.logs.append((level, msg, args)) - - def get_logs(self, *levels): - def _format(msg, args): - if len(args) == 0: - return msg - return msg % args - return [_format(msg, args) for level, msg, args - in self.logs if level in levels] - - def clear_logs(self): - self.logs = [] - - def assertNoWarnings(self): - assert self.get_logs(log.WARN) == [] - self.clear_logs() - - def assertWarnings(self): - assert len(self.get_logs(log.WARN)) > 0 - self.clear_logs() + monkeypatch.setattr(log.Log, "_log", _log) + + def get_records(self, caplog, *levels): + return [r for r in caplog.records if r.levelno in levels] + + def assertNoWarnings(self, caplog): + assert self.get_records(caplog, log.WARN) == [] + caplog.clear() + + def assertWarnings(self, caplog): + if IS_PYPY and not caplog.records: + pytest.xfail("caplog checks may not work well in PyPy") + else: + assert len(self.get_records(caplog, log.WARN)) > 0 + caplog.clear() def make_files(self, files): for file in files: @@ -474,7 +463,8 @@ class TestFileListTest(TempDirTestCase): else: assert False, "Should have thrown an error" - def test_include(self): + def test_include(self, caplog): + caplog.set_level(logging.DEBUG) ml = make_local_path # include file_list = FileList() @@ -483,14 +473,15 @@ class TestFileListTest(TempDirTestCase): file_list.process_template_line('include *.py') file_list.sort() assert file_list.files == ['a.py'] - self.assertNoWarnings() + self.assertNoWarnings(caplog) file_list.process_template_line('include *.rb') file_list.sort() assert file_list.files == ['a.py'] - self.assertWarnings() + self.assertWarnings(caplog) - def test_exclude(self): + def test_exclude(self, caplog): + caplog.set_level(logging.DEBUG) ml = make_local_path # exclude file_list = FileList() @@ -499,14 +490,15 @@ class TestFileListTest(TempDirTestCase): file_list.process_template_line('exclude *.py') file_list.sort() assert file_list.files == ['b.txt', ml('d/c.py')] - self.assertNoWarnings() + self.assertNoWarnings(caplog) file_list.process_template_line('exclude *.rb') file_list.sort() assert file_list.files == ['b.txt', ml('d/c.py')] - self.assertWarnings() + self.assertWarnings(caplog) - def test_global_include(self): + def test_global_include(self, caplog): + caplog.set_level(logging.DEBUG) ml = make_local_path # global-include file_list = FileList() @@ -515,14 +507,15 @@ class TestFileListTest(TempDirTestCase): file_list.process_template_line('global-include *.py') file_list.sort() assert file_list.files == ['a.py', ml('d/c.py')] - self.assertNoWarnings() + self.assertNoWarnings(caplog) file_list.process_template_line('global-include *.rb') file_list.sort() assert file_list.files == ['a.py', ml('d/c.py')] - self.assertWarnings() + self.assertWarnings(caplog) - def test_global_exclude(self): + def test_global_exclude(self, caplog): + caplog.set_level(logging.DEBUG) ml = make_local_path # global-exclude file_list = FileList() @@ -531,14 +524,15 @@ class TestFileListTest(TempDirTestCase): file_list.process_template_line('global-exclude *.py') file_list.sort() assert file_list.files == ['b.txt'] - self.assertNoWarnings() + self.assertNoWarnings(caplog) file_list.process_template_line('global-exclude *.rb') file_list.sort() assert file_list.files == ['b.txt'] - self.assertWarnings() + self.assertWarnings(caplog) - def test_recursive_include(self): + def test_recursive_include(self, caplog): + caplog.set_level(logging.DEBUG) ml = make_local_path # recursive-include file_list = FileList() @@ -547,14 +541,15 @@ class TestFileListTest(TempDirTestCase): file_list.process_template_line('recursive-include d *.py') file_list.sort() assert file_list.files == [ml('d/b.py'), ml('d/d/e.py')] - self.assertNoWarnings() + self.assertNoWarnings(caplog) file_list.process_template_line('recursive-include e *.py') file_list.sort() assert file_list.files == [ml('d/b.py'), ml('d/d/e.py')] - self.assertWarnings() + self.assertWarnings(caplog) - def test_recursive_exclude(self): + def test_recursive_exclude(self, caplog): + caplog.set_level(logging.DEBUG) ml = make_local_path # recursive-exclude file_list = FileList() @@ -563,14 +558,15 @@ class TestFileListTest(TempDirTestCase): file_list.process_template_line('recursive-exclude d *.py') file_list.sort() assert file_list.files == ['a.py', ml('d/c.txt')] - self.assertNoWarnings() + self.assertNoWarnings(caplog) file_list.process_template_line('recursive-exclude e *.py') file_list.sort() assert file_list.files == ['a.py', ml('d/c.txt')] - self.assertWarnings() + self.assertWarnings(caplog) - def test_graft(self): + def test_graft(self, caplog): + caplog.set_level(logging.DEBUG) ml = make_local_path # graft file_list = FileList() @@ -579,14 +575,15 @@ class TestFileListTest(TempDirTestCase): file_list.process_template_line('graft d') file_list.sort() assert file_list.files == [ml('d/b.py'), ml('d/d/e.py')] - self.assertNoWarnings() + self.assertNoWarnings(caplog) file_list.process_template_line('graft e') file_list.sort() assert file_list.files == [ml('d/b.py'), ml('d/d/e.py')] - self.assertWarnings() + self.assertWarnings(caplog) - def test_prune(self): + def test_prune(self, caplog): + caplog.set_level(logging.DEBUG) ml = make_local_path # prune file_list = FileList() @@ -595,9 +592,9 @@ class TestFileListTest(TempDirTestCase): file_list.process_template_line('prune d') file_list.sort() assert file_list.files == ['a.py', ml('f/f.py')] - self.assertNoWarnings() + self.assertNoWarnings(caplog) file_list.process_template_line('prune e') file_list.sort() assert file_list.files == ['a.py', ml('f/f.py')] - self.assertWarnings() + self.assertWarnings(caplog) diff --git a/setuptools/tests/test_msvc14.py b/setuptools/tests/test_msvc14.py index 1aca12d..271d6be 100644 --- a/setuptools/tests/test_msvc14.py +++ b/setuptools/tests/test_msvc14.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """ Tests for msvc support module (msvc14 unit tests). """ diff --git a/setuptools/tests/test_wheel.py b/setuptools/tests/test_wheel.py index 89d65d0..b2bbdfa 100644 --- a/setuptools/tests/test_wheel.py +++ b/setuptools/tests/test_wheel.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - """wheel tests """ -- 2.34.1