setuptools: [BUG] sys.exit(0) in setup.py breaks PEP 517 hooks API
setuptools version
68.0.0
Python version
3.11
OS
Linux
Additional environment information
I believe this will affect any OS and any Python version.
Description
If a setup.py file calls sys.exit(0)
, building it through the PEP 517 hooks interface will fail. sys.exit()
raises a SystemExit
exception, which propagates up out of the hook function. Normally, unhandled exceptions indicate that something went wrong, and that’s OK - the frontend sees that the backend exited with an error, and displays its stdout/stderr for debugging. But in this case the exception is used even though nothing is wrong.
PEP 517 says:
If a hook raises an exception, or causes the process to terminate, then this indicates an error.
We could interpret that 100% literally: an exception was raised, therefore the backend has failed, but that’s clearly not the intention - sys.exit(0)
indicates that execution of setup.py
completed successfully. Edit: it’s like return
for scripts. 🙂
This issue has been bounced around several packaging related projects already, most recently https://github.com/pypa/pyproject-hooks/issues/173 .
Expected behavior
I think setuptools hooks implementation should catch and ignore SystemExit
with an err.code
attribute of 0 or None (the non-error cases), on the assumption that this means running setup.py
finished successfully.
I had a go at doing this in pyproject-hooks
, the machinery that calls the hooks, but the hooks have to return something, so catching the error outside setuptools isn’t enough - we don’t know what it would have returned.
How to Reproduce
Save the following code as setup.py
in a folder by itself and then run python -m build path/to/folder/
:
from setuptools import setup
import sys
setup(
name="pep517-test-setup-py-support",
version="1.0",
)
sys.exit(0)
Output
$ python -m build tests/samples/setup-py/
* Creating virtualenv isolated environment...
* Installing packages in isolated environment... (setuptools, wheel)
* Getting build dependencies for sdist...
running egg_info
writing pep517_test_setup_py_support.egg-info/PKG-INFO
writing dependency_links to pep517_test_setup_py_support.egg-info/dependency_links.txt
writing top-level names to pep517_test_setup_py_support.egg-info/top_level.txt
reading manifest file 'pep517_test_setup_py_support.egg-info/SOURCES.txt'
writing manifest file 'pep517_test_setup_py_support.egg-info/SOURCES.txt'
Traceback (most recent call last):
File "/home/takluyver/.local/lib/python3.11/site-packages/pyproject_hooks/_impl.py", line 19, in read_json
with open(path, encoding='utf-8') as f:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
FileNotFoundError: [Errno 2] No such file or directory: '/tmp/tmpe0ghw0d1/output.json'
ERROR Backend operation failed: FileNotFoundError(2, 'No such file or directory')
About this issue
- Original URL
- State: closed
- Created a year ago
- Comments: 17 (17 by maintainers)
Commits related to this issue
- Handle `setup.py` possibly using `sys.exit` Since `setup.py` is an arbitrary Python script legacy scripts my be complex and may use `sys.exit`. To adhere to PEP 517 handle `SystemExit` exception by i... — committed to arcivanov/setuptools by arcivanov a year ago
- Handle `setup.py` possibly using `sys.exit` Since `setup.py` is an arbitrary Python script legacy scripts may be complex and may use `sys.exit`. To adhere to PEP 517 handle `SystemExit` exception by ... — committed to arcivanov/setuptools by arcivanov a year ago
- Handle `setup.py` possibly using `sys.exit` Since `setup.py` is an arbitrary Python script legacy scripts may be complex and may use `sys.exit`. To adhere to PEP 517 handle `SystemExit` exception by ... — committed to arcivanov/setuptools by arcivanov a year ago
- Handle `setup.py` possibly using `sys.exit` Since `setup.py` is an arbitrary Python script legacy scripts may be complex and may use `sys.exit`. To adhere to PEP 517 handle `SystemExit` exception by ... — committed to arcivanov/setuptools by arcivanov a year ago
- Handle `setup.py` possibly using `sys.exit` Since `setup.py` is an arbitrary Python script legacy scripts may be complex and may use `sys.exit`. To adhere to PEP 517 handle `SystemExit` exception by ... — committed to arcivanov/setuptools by arcivanov a year ago
- Handle `setup.py` possibly using `sys.exit` Since `setup.py` is an arbitrary Python script legacy scripts may be complex and may use `sys.exit`. To adhere to PEP 517 handle `SystemExit` exception by ... — committed to arcivanov/setuptools by arcivanov a year ago
OK, so I guess the consensus is to let
SystemExit
fall through if exit code is non-zero and only handlesys.main(0)
?