Imported Upstream version 65.0.1 upstream/65.0.1
authorJinWang An <jinwang.an@samsung.com>
Mon, 27 Mar 2023 08:02:55 +0000 (17:02 +0900)
committerJinWang An <jinwang.an@samsung.com>
Mon, 27 Mar 2023 08:02:55 +0000 (17:02 +0900)
.bumpversion.cfg
CHANGES.rst
docs/pkg_resources.rst
docs/userguide/quickstart.rst
setup.cfg
setuptools/build_meta.py
setuptools/command/editable_wheel.py
setuptools/tests/test_build_meta.py
setuptools/tests/test_editable_install.py

index 05e78cde6809605c84e662f3dc2a1b6b4b9d7215..bbfad4b68909fdab0af8bdfff3e14b31dc7fae81 100644 (file)
@@ -1,5 +1,5 @@
 [bumpversion]
-current_version = 65.0.0
+current_version = 65.0.1
 commit = True
 tag = True
 
index d4d6437964ce17b0098257bc104fc507d600852d..185697c6f873be96e18bec1e36eac42051ec2f20 100644 (file)
@@ -1,3 +1,20 @@
+v65.0.1
+-------
+
+
+Documentation changes
+^^^^^^^^^^^^^^^^^^^^^
+* #3529: Added clarification to :doc:`/userguide/quickstart` about support
+  to ``setup.py``.
+
+Misc
+^^^^
+* #3526: Fix backward compatibility of editable installs and custom ``build_ext``
+  commands inheriting directly from ``distutils``.
+* #3528: Fixed ``buid_meta.prepare_metadata_for_build_wheel`` when
+  given ``metadata_directory`` is ``"."``.
+
+
 v65.0.0
 -------
 
index 21ff6dc1989e635f715bcb8a3bd4d40229e3c25f..40e5e6f8adfff9418a93c46bd4b293de48cbf3ff 100644 (file)
@@ -10,12 +10,13 @@ eggs, support for merging packages that have separately-distributed modules or
 subpackages, and APIs for managing Python's current "working set" of active
 packages.
 
-Use of ``pkg_resources`` is discouraged in favor of
-`importlib.resources <https://docs.python.org/3/library/importlib.html#module-importlib.resources>`_,
-`importlib.metadata <https://docs.python.org/3/library/importlib.metadata.html>`_,
-and their backports (:pypi:`importlib_resources`,
-:pypi:`importlib_metadata`).
-Please consider using those libraries instead of pkg_resources.
+.. attention::
+   Use of ``pkg_resources`` is discouraged in favor of
+   `importlib.resources <https://docs.python.org/3/library/importlib.html#module-importlib.resources>`_,
+   `importlib.metadata <https://docs.python.org/3/library/importlib.metadata.html>`_,
+   and their backports (:pypi:`importlib_resources`,
+   :pypi:`importlib_metadata`).
+   Please consider using those libraries instead of pkg_resources.
 
 
 --------
index bf76f2c899b81a8a13c38b733c263bc04eba7d7a..352a37bdd3e594be34196ea62c90c2d849497fdd 100644 (file)
@@ -59,8 +59,7 @@ library will be used to actually do the packaging.
 In addition to specifying a build system, you also will need to add
 some package information such as metadata, contents, dependencies, etc.
 This can be done in the same ``pyproject.toml`` [#beta]_ file,
-or in a separated one: ``setup.cfg`` or ``setup.py`` (please note however
-that configuring new projects via ``setup.py`` is discouraged [#setup.py]_).
+or in a separated one: ``setup.cfg`` or ``setup.py`` [#setup.py]_.
 
 The following example demonstrates a minimum configuration
 (which assumes the project depends on :pypi:`requests` and
@@ -149,6 +148,27 @@ to specify to properly package your project.
    could have a diagram for that (explaining for example that "wheels" are
    built from "sdists" not the source tree).
 
+.. _setuppy_discouraged:
+.. admonition:: Info: Using ``setup.py``
+  :class: seealso
+
+  Setuptools offers first class support for ``setup.py`` files as a configuration
+  mechanism.
+
+  It is important to remember, however, that running this file as a
+  script (e.g. ``python setup.py sdist``) is strongly **discouraged**, and
+  that the majority of the command line interfaces are (or will be) **deprecated**
+  (e.g. ``python setup.py install``, ``python setup.py bdist_wininst``, ...).
+
+  We also recommend users to expose as much as possible configuration in a
+  more *declarative* way via the :doc:`pyproject.toml <pyproject_config>` or
+  :doc:`setup.cfg <declarative_config>`, 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.  
+
+.. _Why you shouldn't invoke setup.py directly: https://blog.ganssle.io/articles/2021/10/setup-py-deprecated.html
+
 
 Overview
 ========
@@ -438,14 +458,15 @@ up-to-date references that can help you when it is time to distribute your work.
 .. rubric:: Notes
 
 .. [#setup.py]
-   The ``setup.py`` file should be used only when custom scripting during the
-   build is necessary.
+   New projects are advised to avoid ``setup.py`` configurations (beyond the minimal stub)
+   when custom scripting during the build is not necessary.
    Examples are kept in this document to help people interested in maintaining or
    contributing to existing packages that use ``setup.py``.
    Note that you can still keep most of configuration declarative in
    :doc:`setup.cfg <declarative_config>` or :doc:`pyproject.toml
    <pyproject_config>` and use ``setup.py`` only for the parts not
    supported in those files (e.g. C extensions).
+   See :ref:`note <setuppy_discouraged>`.
 
 .. [#beta]
    Support for adding build configuration options via the ``[tool.setuptools]``
index 25a0541c9b082884de035fa52df12c594f10ad8d..3346b1f72bf125e90531c29f139cce9867c09ec5 100644 (file)
--- a/setup.cfg
+++ b/setup.cfg
@@ -1,6 +1,6 @@
 [metadata]
 name = setuptools
-version = 65.0.0
+version = 65.0.1
 author = Python Packaging Authority
 author_email = distutils-sig@python.org
 description = Easily download, build, install, upgrade, and uninstall Python packages
index 98fb148a5dc62471892c15fe740fcb3531a6428b..8ff9a5ceca70bd827e1d0620e5d5cc9beea3c092 100644 (file)
@@ -40,6 +40,7 @@ from typing import Dict, Iterator, List, Optional, Union
 
 import setuptools
 import distutils
+from . import errors
 from ._path import same_path
 from ._reqs import parse_strings
 from ._deprecation_warning import SetuptoolsDeprecationWarning
@@ -346,16 +347,23 @@ class _BuildMetaBackend(_ConfigSettingsTranslator):
 
         Returns the basename of the info directory, e.g. `proj-0.0.0.dist-info`.
         """
-        candidates = list(Path(metadata_directory).glob(f"**/*{suffix}/"))
-        assert len(candidates) == 1, f"Exactly one {suffix} should have been produced"
-        info_dir = candidates[0]
-
+        info_dir = self._find_info_directory(metadata_directory, suffix)
         if not same_path(info_dir.parent, metadata_directory):
             shutil.move(str(info_dir), metadata_directory)
             # PEP 517 allow other files and dirs to exist in metadata_directory
-
         return info_dir.name
 
+    def _find_info_directory(self, metadata_directory: str, suffix: str) -> Path:
+        for parent, dirs, _ in os.walk(metadata_directory):
+            candidates = [f for f in dirs if f.endswith(suffix)]
+
+            if len(candidates) != 0 or len(dirs) != 1:
+                assert len(candidates) == 1, f"Multiple {suffix} directories found"
+                return Path(parent, candidates[0])
+
+        msg = f"No {suffix} directory found in {metadata_directory}"
+        raise errors.InternalError(msg)
+
     def prepare_metadata_for_build_wheel(self, metadata_directory,
                                          config_settings=None):
         sys.argv = [
index 560efebdac17c4c2d6ea826ae61b092ee4e00fee..ea2148412f6042f84228ec5142c12027fd7b031d 100644 (file)
@@ -237,6 +237,8 @@ class editable_wheel(Command):
             cmd = dist.get_command_obj(cmd_name)
             if hasattr(cmd, "editable_mode"):
                 cmd.editable_mode = True
+            elif hasattr(cmd, "inplace"):
+                cmd.inplace = True  # backward compatibility with distutils
 
     def _collect_build_outputs(self) -> Tuple[List[str], Dict[str, str]]:
         files: List[str] = []
index e70c71bdd0d479b7e0ebc36910ff04d52fb3bcfd..bf1c27ff1d4f349d3466e9311e7e16fd840f2923 100644 (file)
@@ -485,6 +485,23 @@ class TestBuildMetaBackend:
 
         assert os.path.isfile(os.path.join(dist_dir, dist_info, 'METADATA'))
 
+    def test_prepare_metadata_inplace(self, build_backend):
+        """
+        Some users might pass metadata_directory pre-populated with `.tox` or `.venv`.
+        See issue #3523.
+        """
+        for pre_existing in [
+            ".tox/python/lib/python3.10/site-packages/attrs-22.1.0.dist-info",
+            ".tox/python/lib/python3.10/site-packages/autocommand-2.2.1.dist-info",
+            ".nox/python/lib/python3.10/site-packages/build-0.8.0.dist-info",
+            ".venv/python3.10/site-packages/click-8.1.3.dist-info",
+            "venv/python3.10/site-packages/distlib-0.3.5.dist-info",
+            "env/python3.10/site-packages/docutils-0.19.dist-info",
+        ]:
+            os.makedirs(pre_existing, exist_ok=True)
+        dist_info = build_backend.prepare_metadata_for_build_wheel(".")
+        assert os.path.isfile(os.path.join(dist_info, 'METADATA'))
+
     def test_build_sdist_explicit_dist(self, build_backend):
         # explicitly specifying the dist folder should work
         # the folder sdist_directory and the ``--dist-dir`` can be the same
index 900ec1b3ccd56e47ff1926215dddcd50a652e5aa..6b5cdd1c0e2d1bfb574f4043ac0afec0e30e4c33 100644 (file)
@@ -5,6 +5,7 @@ import subprocess
 import platform
 from copy import deepcopy
 from importlib import import_module
+from importlib.machinery import EXTENSION_SUFFIXES
 from pathlib import Path
 from textwrap import dedent
 from unittest.mock import Mock
@@ -28,6 +29,7 @@ from setuptools.command.editable_wheel import (
     editable_wheel,
 )
 from setuptools.dist import Distribution
+from setuptools.extension import Extension
 
 
 @pytest.fixture(params=["strict", "lenient"])
@@ -872,9 +874,40 @@ class TestCustomBuildWheel:
         cmd = editable_wheel(dist)
         cmd.ensure_finalized()
         cmd.run()
-        wheel_file = str(next(Path().glob('dist/*')))
+        wheel_file = str(next(Path().glob('dist/*.whl')))
         assert "editable" in wheel_file
-        assert wheel_file.endswith(".whl")
+
+
+class TestCustomBuildExt:
+    def install_custom_build_ext_distutils(self, dist):
+        from distutils.command.build_ext import build_ext as build_ext_cls
+
+        class MyBuildExt(build_ext_cls):
+            pass
+
+        dist.cmdclass["build_ext"] = MyBuildExt
+
+    @pytest.mark.skipif(
+        sys.platform != "linux", reason="compilers may fail without correct setup"
+    )
+    def test_distutils_leave_inplace_files(self, tmpdir_cwd):
+        jaraco.path.build({"module.c": ""})
+        attrs = {
+            "ext_modules": [Extension("module", ["module.c"])],
+        }
+        dist = Distribution(attrs)
+        dist.script_name = "setup.py"
+        dist.set_defaults()
+        self.install_custom_build_ext_distutils(dist)
+        cmd = editable_wheel(dist)
+        cmd.ensure_finalized()
+        cmd.run()
+        wheel_file = str(next(Path().glob('dist/*.whl')))
+        assert "editable" in wheel_file
+        files = [p for p in Path().glob("module.*") if p.suffix != ".c"]
+        assert len(files) == 1
+        name = files[0].name
+        assert any(name.endswith(ext) for ext in EXTENSION_SUFFIXES)
 
 
 def install_project(name, venv, tmp_path, files, *opts):