From e9c0f72997c754148f2c5aec8819ba4e6fd64bb7 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Tue, 28 Apr 2020 20:28:41 -0400 Subject: [PATCH 1/3] Add "python -m setuptools" invocation method This fully replaces the use of "python setup.py " with the equivalent "python -m setuptools ". In the process, we guarantee that a setup.py which imported only distutils will still get the enhanced setuptools treatment previously provided only by pip install. This opens the way for future improvements to setuptools, such as validating setup_requires (if listed in setup.cfg) before invoking the setup() function and running code. It is also the only way to invoke setuptools to build and install packages which fully moved to setup.cfg and no longer provide a stub setup.py with the content: ``` from setuptool import setup setup() ``` --- setuptools/__main__.py | 10 ++++++++++ setuptools/launch.py | 38 ++++++++++++++++++++++++-------------- 2 files changed, 34 insertions(+), 14 deletions(-) create mode 100644 setuptools/__main__.py diff --git a/setuptools/__main__.py b/setuptools/__main__.py new file mode 100644 index 0000000000..f71f47e6ac --- /dev/null +++ b/setuptools/__main__.py @@ -0,0 +1,10 @@ +""" +Command-line interface for running setup.py or new-fashioned setup.cfg after +setuptools is monkey-patched into distutils. +""" + +if __name__ == '__main__': + import sys + from setuptools.launch import run_setup + sys.argv[0] = 'setuptools' + run_setup() diff --git a/setuptools/launch.py b/setuptools/launch.py index 308283ea93..c1ec06b4be 100644 --- a/setuptools/launch.py +++ b/setuptools/launch.py @@ -6,30 +6,40 @@ # Note that setuptools gets imported implicitly by the # invocation of this script using python -m setuptools.launch -import tokenize +import io +import os import sys +import tokenize + +def _open_setup_script(setup_script, fallback): + if fallback and not os.path.exists(setup_script): + # Supply a default setup.py + return io.StringIO(u"from setuptools import setup; setup()") + + return getattr(tokenize, 'open', open)(setup_script) + +def run_setup(setup_script='setup.py', fallback=True): + namespace = { + '__file__' : setup_script, + '__name__' : '__main__', + '__doc__' : None + } + + with _open_setup_script(setup_script, fallback) as f: + code = f.read().replace(r'\r\n', r'\n') + exec(compile(code, setup_script, 'exec'), namespace) -def run(): +def run_script(): """ Run the script in sys.argv[1] as if it had been invoked naturally. """ - __builtins__ script_name = sys.argv[1] - namespace = dict( - __file__=script_name, - __name__='__main__', - __doc__=None, - ) sys.argv[:] = sys.argv[1:] - open_ = getattr(tokenize, 'open', open) - script = open_(script_name).read() - norm_script = script.replace('\\r\\n', '\\n') - code = compile(norm_script, script_name, 'exec') - exec(code, namespace) + run_setup(script_name, fallback=False) if __name__ == '__main__': - run() + run_script() From 7ea2b82ebe6fee57fc00676984d6d43526d88140 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Tue, 28 Apr 2020 22:15:07 -0400 Subject: [PATCH 2/3] fixup! Add "python -m setuptools" invocation method Add news fragment. --- changelog.d/2080.change.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/2080.change.rst diff --git a/changelog.d/2080.change.rst b/changelog.d/2080.change.rst new file mode 100644 index 0000000000..d5878f4926 --- /dev/null +++ b/changelog.d/2080.change.rst @@ -0,0 +1 @@ +Add support for running `python -m setuptools cmd` as a setup.py alternative. From d68b2b0a801321ee02399e23b5bedbe16781f283 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Tue, 28 Apr 2020 22:33:24 -0400 Subject: [PATCH 3/3] fixup! Add "python -m setuptools" invocation method flake errors --- setuptools/launch.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/setuptools/launch.py b/setuptools/launch.py index c1ec06b4be..b456913b06 100644 --- a/setuptools/launch.py +++ b/setuptools/launch.py @@ -11,6 +11,7 @@ import sys import tokenize + def _open_setup_script(setup_script, fallback): if fallback and not os.path.exists(setup_script): # Supply a default setup.py @@ -18,11 +19,12 @@ def _open_setup_script(setup_script, fallback): return getattr(tokenize, 'open', open)(setup_script) + def run_setup(setup_script='setup.py', fallback=True): namespace = { - '__file__' : setup_script, - '__name__' : '__main__', - '__doc__' : None + '__file__': setup_script, + '__name__': '__main__', + '__doc__': None } with _open_setup_script(setup_script, fallback) as f: @@ -30,6 +32,7 @@ def run_setup(setup_script='setup.py', fallback=True): exec(compile(code, setup_script, 'exec'), namespace) + def run_script(): """ Run the script in sys.argv[1] as if it had