Imported Upstream version 59.3.0 upstream/59.3.0
authorJinWang An <jinwang.an@samsung.com>
Mon, 27 Mar 2023 08:02:39 +0000 (17:02 +0900)
committerJinWang An <jinwang.an@samsung.com>
Mon, 27 Mar 2023 08:02:39 +0000 (17:02 +0900)
.bumpversion.cfg
CHANGES.rst
_distutils_hack/__init__.py
setup.cfg
setuptools/_distutils/core.py
setuptools/_distutils/tests/test_core.py
setuptools/tests/test_test.py

index a9d31cd265e224a533b11d9f5a40221c32d929cf..67dc08513f4f1ed142c46c3d73f0f207b681ea60 100644 (file)
@@ -1,5 +1,5 @@
 [bumpversion]
-current_version = 59.2.0
+current_version = 59.3.0
 commit = True
 tag = True
 
index 3206647a0e9664f28fd239c6c4bbe290e44c913e..8fbae4f0f585def864cfdb4f7ad9ef54282233e1 100644 (file)
@@ -1,3 +1,16 @@
+v59.3.0
+-------
+
+
+Changes
+^^^^^^^
+* #2902: Merge with pypa/distutils@85db7a41242.
+
+Misc
+^^^^
+* #2906: In ensure_local_distutils, re-use DistutilsMetaFinder to load the module. Avoids race conditions when _distutils_system_mod is employed.
+
+
 v59.2.0
 -------
 
index 5f40996a67efe9e38a6b68242efc2f10fc89e471..f707416286b22ddbdcf84f60b6ad38ded604bdfc 100644 (file)
@@ -48,11 +48,15 @@ def enabled():
 
 def ensure_local_distutils():
     clear_distutils()
-    distutils = importlib.import_module('setuptools._distutils')
-    distutils.__name__ = 'distutils'
-    sys.modules['distutils'] = distutils
 
-    # sanity check that submodules load as expected
+    # With the DistutilsMetaFinder in place,
+    # perform an import to cause distutils to be
+    # loaded from setuptools._distutils. Ref #2906.
+    add_shim()
+    importlib.import_module('distutils')
+    remove_shim()
+
+    # check that submodules load as expected
     core = importlib.import_module('distutils.core')
     assert '_distutils' in core.__file__, core.__file__
 
index 7909ea10df830c01c9f3d0309856bcfaf2f061b3..6aabb1a322c830a688cb927b35be2642343a5517 100644 (file)
--- a/setup.cfg
+++ b/setup.cfg
@@ -1,6 +1,6 @@
 [metadata]
 name = setuptools
-version = 59.2.0
+version = 59.3.0
 author = Python Packaging Authority
 author_email = distutils-sig@python.org
 description = Easily download, build, install, upgrade, and uninstall Python packages
index d603d4a45a73ee4f373fbd1ef934738bda0a1991..f43888ea609dca16f2e6e7d2e758da2dd9e47864 100644 (file)
@@ -8,6 +8,7 @@ really defined in distutils.dist and distutils.cmd.
 
 import os
 import sys
+import tokenize
 
 from distutils.debug import DEBUG
 from distutils.errors import *
@@ -144,29 +145,41 @@ def setup (**attrs):
 
     # And finally, run all the commands found on the command line.
     if ok:
-        try:
-            dist.run_commands()
-        except KeyboardInterrupt:
-            raise SystemExit("interrupted")
-        except OSError as exc:
-            if DEBUG:
-                sys.stderr.write("error: %s\n" % (exc,))
-                raise
-            else:
-                raise SystemExit("error: %s" % (exc,))
-
-        except (DistutilsError,
-                CCompilerError) as msg:
-            if DEBUG:
-                raise
-            else:
-                raise SystemExit("error: " + str(msg))
+        return run_commands(dist)
 
     return dist
 
 # setup ()
 
 
+def run_commands (dist):
+    """Given a Distribution object run all the commands,
+    raising ``SystemExit`` errors in the case of failure.
+
+    This function assumes that either ``sys.argv`` or ``dist.script_args``
+    is already set accordingly.
+    """
+    try:
+        dist.run_commands()
+    except KeyboardInterrupt:
+        raise SystemExit("interrupted")
+    except OSError as exc:
+        if DEBUG:
+            sys.stderr.write("error: %s\n" % (exc,))
+            raise
+        else:
+            raise SystemExit("error: %s" % (exc,))
+
+    except (DistutilsError,
+            CCompilerError) as msg:
+        if DEBUG:
+            raise
+        else:
+            raise SystemExit("error: " + str(msg))
+
+    return dist
+
+
 def run_setup (script_name, script_args=None, stop_after="run"):
     """Run a setup script in a somewhat controlled environment, and
     return the Distribution instance that drives things.  This is useful
@@ -205,14 +218,16 @@ def run_setup (script_name, script_args=None, stop_after="run"):
     _setup_stop_after = stop_after
 
     save_argv = sys.argv.copy()
-    g = {'__file__': script_name}
+    g = {'__file__': script_name, '__name__': '__main__'}
     try:
         try:
             sys.argv[0] = script_name
             if script_args is not None:
                 sys.argv[1:] = script_args
-            with open(script_name, 'rb') as f:
-                exec(f.read(), g)
+            # tokenize.open supports automatic encoding detection
+            with tokenize.open(script_name) as f:
+                code = f.read().replace(r'\r\n', r'\n')
+                exec(code, g)
         finally:
             sys.argv = save_argv
             _setup_stop_after = None
index 666ff4a3cde927c961c7641a13268aa9c156a21c..d99cfd26c3db7515f9c4ad1bfe67be866020d94a 100644 (file)
@@ -10,6 +10,7 @@ from . import py38compat as os_helper
 import unittest
 from distutils.tests import support
 from distutils import log
+from distutils.dist import Distribution
 
 # setup script that uses __file__
 setup_using___file__ = """\
@@ -45,6 +46,16 @@ class install(_install):
 setup(cmdclass={'install': install})
 """
 
+setup_within_if_main = """\
+from distutils.core import setup
+
+def main():
+    return setup(name="setup_within_if_main")
+
+if __name__ == "__main__":
+    main()
+"""
+
 class CoreTestCase(support.EnvironGuard, unittest.TestCase):
 
     def setUp(self):
@@ -115,6 +126,20 @@ class CoreTestCase(support.EnvironGuard, unittest.TestCase):
             output = output[:-1]
         self.assertEqual(cwd, output)
 
+    def test_run_setup_within_if_main(self):
+        dist = distutils.core.run_setup(
+            self.write_setup(setup_within_if_main), stop_after="config")
+        self.assertIsInstance(dist, Distribution)
+        self.assertEqual(dist.get_name(), "setup_within_if_main")
+
+    def test_run_commands(self):
+        sys.argv = ['setup.py', 'build']
+        dist = distutils.core.run_setup(
+            self.write_setup(setup_within_if_main), stop_after="commandline")
+        self.assertNotIn('build', dist.have_run)
+        distutils.core.run_commands(dist)
+        self.assertIn('build', dist.have_run)
+
     def test_debug_mode(self):
         # this covers the code called when DEBUG is set
         sys.argv = ['setup.py', '--name']
index 6bce8e2063f2177e09959d89177adfa218615d70..8b8d9e6c4e4eee6e9b9960ae45f09503a0b1e600 100644 (file)
@@ -1,7 +1,5 @@
-from distutils import log
-import os
-
 import pytest
+from jaraco import path
 
 from setuptools.command.test import test
 from setuptools.dist import Distribution
@@ -9,100 +7,35 @@ from setuptools.dist import Distribution
 from .textwrap import DALS
 
 
-SETUP_PY = DALS(
-    """
-    from setuptools import setup
-
-    setup(name='foo',
-        packages=['name', 'name.space', 'name.space.tests'],
-        namespace_packages=['name'],
-        test_suite='name.space.tests.test_suite',
-    )
-    """
-)
-
-NS_INIT = DALS(
-    """
-    # -*- coding: Latin-1 -*-
-    # Söme Arbiträry Ünicode to test Distribute Issüé 310
-    try:
-        __import__('pkg_resources').declare_namespace(__name__)
-    except ImportError:
-        from pkgutil import extend_path
-        __path__ = extend_path(__path__, __name__)
-    """
-)
-
-TEST_PY = DALS(
-    """
-    import unittest
-
-    class TestTest(unittest.TestCase):
-        def test_test(self):
-            print "Foo" # Should fail under Python 3
-
-    test_suite = unittest.makeSuite(TestTest)
-    """
-)
-
-
-@pytest.fixture
-def sample_test(tmpdir_cwd):
-    os.makedirs('name/space/tests')
-
-    # setup.py
-    with open('setup.py', 'wt') as f:
-        f.write(SETUP_PY)
-
-    # name/__init__.py
-    with open('name/__init__.py', 'wb') as f:
-        f.write(NS_INIT.encode('Latin-1'))
-
-    # name/space/__init__.py
-    with open('name/space/__init__.py', 'wt') as f:
-        f.write('#empty\n')
-
-    # name/space/tests/__init__.py
-    with open('name/space/tests/__init__.py', 'wt') as f:
-        f.write(TEST_PY)
-
-
-@pytest.fixture
-def quiet_log():
-    # Running some of the other tests will automatically
-    # change the log level to info, messing our output.
-    log.set_verbosity(0)
-
-
-@pytest.mark.usefixtures('tmpdir_cwd', 'quiet_log')
+@pytest.mark.usefixtures('tmpdir_cwd')
 def test_tests_are_run_once(capfd):
     params = dict(
         name='foo',
         packages=['dummy'],
     )
-    with open('setup.py', 'wt') as f:
-        f.write('from setuptools import setup; setup(\n')
-        for k, v in sorted(params.items()):
-            f.write('    %s=%r,\n' % (k, v))
-        f.write(')\n')
-    os.makedirs('dummy')
-    with open('dummy/__init__.py', 'wt'):
-        pass
-    with open('dummy/test_dummy.py', 'wt') as f:
-        f.write(
-            DALS(
+    files = {
+        'setup.py':
+            'from setuptools import setup; setup('
+            + ','.join(f'{name}={params[name]!r}' for name in params)
+            + ')',
+        'dummy': {
+            '__init__.py': '',
+            'test_dummy.py': DALS(
+                """
+                import unittest
+                class TestTest(unittest.TestCase):
+                    def test_test(self):
+                        print('Foo')
                 """
-            import unittest
-            class TestTest(unittest.TestCase):
-                def test_test(self):
-                    print('Foo')
-             """
-            )
-        )
+                ),
+            },
+    }
+    path.build(files)
     dist = Distribution(params)
     dist.script_name = 'setup.py'
     cmd = test(dist)
     cmd.ensure_finalized()
     cmd.run()
     out, err = capfd.readouterr()
-    assert out == 'Foo\n'
+    assert out.endswith('Foo\n')
+    assert len(out.split('Foo')) == 2