The principle of least surprise suggests that run_setup() should behave equivalently to a command line invocation of setup.py. However there are currently (at least) two issues preventing this: (a) When calling exec(), both a globals and a locals dict is passed. According to the documentation: "If exec gets two separate objects as globals and locals, the code will be executed as if it were embedded in a class definition." [1] Consequence: "The scope of names defined in a class block is limited to the class block; it does not extend to the code blocks of methods". [2] One example where this is relevant is the "MarkupSafe" PyPI package [3]: Its setup.py defines a class BuildFailed which is used in other methods defined in setup.py. Calling run_setup() with this setup.py will therefore fail. Calling setup.py from the command line works. Solution: Only pass a globals dict to exec(). (b) The globals dict does not contain '__name__':'__main__'. Many setup.py scripts use the idiomatic 'conditional script' stanza "if __name__ == '__main__'". An example is the "PyYAML" PyPI package. [4] In these cases, run_setup() will raise a RuntimeError exception ("'distutils.core.setup()' was never called"). Solution: Add '__name__':'__main__' to the globals dict. Attached are patches to fix these issues in Python 2.6 to 3.4. [1] http://docs.python.org/3/library/functions.html#exec [2] http://docs.python.org/reference/executionmodel.html#naming-and-binding [3] https://pypi.python.org/pypi/MarkupSafe [4] https://pypi.python.org/pypi/PyYAML
> The principle of least surprise suggests that run_setup() should behave equivalently > to a command line invocation of setup.py. That’s debatable: distutils.core.setup corresponds to a command-line invocation of setup.py, but run_setup is documented as something else: http://docs.python.org/3.4/distutils/apiref#distutils.core.run_setup In general, distutils lends itself poorly to programmatic usage. Can you tell more about your use case for calling run_setup directly? > Many setup.py scripts use the idiomatic 'conditional script' stanza > "if __name__ == '__main__'". That’s surprising to me: setup.py scripts are not modules-that-also-work-as-scripts, only scripts.
Distutils is now deprecated (see PEP 632) and all tagged issues are being closed. From now until removal, only release blocking issues will be considered for distutils. If this issue does not relate to distutils, please remove the component and reopen it. If you believe it still requires a fix, most likely the issue should be re-reported at https://github.com/pypa/setuptools
History
Date
User
Action
Args
2022-04-11 14:57:50
admin
set
github: 63170
2021-02-03 18:30:33
steve.dower
set
status: open -> closednosy: + steve.dowermessages: + resolution: out of datestage: resolved