| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent b954645 commit fe7717c
14 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -116,15 +116,14 @@ Error Handling | |||
| 116 | 116 | ||
| 117 | 117 | Get the *config* exit code. | |
| 118 | 118 | ||
| 119 | - * Set *\*exitcode* and return ``1`` if *config* has an exit code set. | ||
| 120 | - * Return ``0`` if *config* has no exit code set. | ||
| 119 | + Return ``0`` and leave *\*exitcode* unchanged. | ||
| 121 | 120 | ||
| 122 | - Only the ``Py_InitializeFromInitConfig()`` function can set an exit | ||
| 123 | - code if the ``parse_argv`` option is non-zero. | ||
| 121 | + In Python 3.15, :c:func:`Py_InitializeFromInitConfig` sets an exit code if a | ||
| 122 | + command line option wants to exit Python. This is no longer the case in | ||
| 123 | + Python 3.16. Instead, the option is now processed in :c:func:`Py_RunMain`. | ||
| 124 | + This function became useless. | ||
| 124 | 125 | ||
| 125 | - An exit code can be set when parsing the command line failed (exit | ||
| 126 | - code ``2``) or when a command line option asks to display the command | ||
| 127 | - line help (exit code ``0``). | ||
| 126 | + .. deprecated:: next | ||
| 128 | 127 | ||
| 129 | 128 | ||
| 130 | 129 | Get Options | |
@@ -247,10 +246,11 @@ Initialize Python | |||
| 247 | 246 | ||
| 248 | 247 | * Return ``0`` on success. | |
| 249 | 248 | * Set an error in *config* and return ``-1`` on error. | |
| 250 | - * Set an exit code in *config* and return ``-1`` if Python wants to | ||
| 251 | - exit. | ||
| 252 | 249 | ||
| 253 | - See ``PyInitConfig_GetExitcode()`` for the exit code case. | ||
| 250 | + .. versionchanged:: next | ||
| 251 | + The function no longer sets an exit code if a command line option wants | ||
| 252 | + to exit Python. Instead, the option is now processed in | ||
| 253 | + :c:func:`Py_RunMain`. | ||
| 254 | 254 | ||
| 255 | 255 | ||
| 256 | 256 | .. _pyinitconfig-opts: | |
@@ -690,9 +690,6 @@ Example of customized Python always running in isolated mode:: | |||
| 690 | 690 | ||
| 691 | 691 | exception: | |
| 692 | 692 | PyConfig_Clear(&config); | |
| 693 | - if (PyStatus_IsExit(status)) { | ||
| 694 | - return status.exitcode; | ||
| 695 | - } | ||
| 696 | 693 | /* Display the error message and exit the process with | |
| 697 | 694 | non-zero exit code */ | |
| 698 | 695 | Py_ExitStatusException(status); | |
@@ -758,6 +755,8 @@ PyStatus | |||
| 758 | 755 | ||
| 759 | 756 | Exit code. Argument passed to ``exit()``. | |
| 760 | 757 | ||
| 758 | + .. deprecated:: next | ||
| 759 | + | ||
| 761 | 760 | .. c:member:: const char *err_msg | |
| 762 | 761 | ||
| 763 | 762 | Error message. | |
@@ -788,6 +787,11 @@ PyStatus | |||
| 788 | 787 | ||
| 789 | 788 | Exit Python with the specified exit code. | |
| 790 | 789 | ||
| 790 | + .. deprecated:: next | ||
| 791 | + :c:func:`Py_InitializeFromConfig` no longer sets an exit code if a | ||
| 792 | + command line option wants to exit Python. Instead, the option is | ||
| 793 | + now processed in :c:func:`Py_RunMain`. | ||
| 794 | + | ||
| 791 | 795 | Functions to handle a status: | |
| 792 | 796 | ||
| 793 | 797 | .. c:function:: int PyStatus_Exception(PyStatus status) | |
@@ -803,6 +807,11 @@ PyStatus | |||
| 803 | 807 | ||
| 804 | 808 | Is the result an exit? | |
| 805 | 809 | ||
| 810 | + .. deprecated:: next | ||
| 811 | + :c:func:`Py_InitializeFromConfig` no longer sets an exit code if a | ||
| 812 | + command line option wants to exit Python. Instead, the option is | ||
| 813 | + now processed in :c:func:`Py_RunMain`. | ||
| 814 | + | ||
| 806 | 815 | .. c:function:: void Py_ExitStatusException(PyStatus status) | |
| 807 | 816 | ||
| 808 | 817 | Call ``exit(exitcode)`` if *status* is an exit. Print the error | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -127,6 +127,11 @@ Initializing and finalizing the interpreter | |||
| 127 | 127 | interpreter, populating the runtime configuration structure, and querying | |
| 128 | 128 | the returned status structure. | |
| 129 | 129 | ||
| 130 | + .. versionchanged:: next | ||
| 131 | + The function no longer returns an exit code if a command line option | ||
| 132 | + wants to exit Python. Instead, the option is processed in | ||
| 133 | + :c:func:`Py_RunMain`. | ||
| 134 | + | ||
| 130 | 135 | ||
| 131 | 136 | .. c:function:: int Py_IsInitialized() | |
| 132 | 137 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1128,6 +1128,14 @@ Deprecated C APIs | |||
| 1128 | 1128 | and :c:func:`PyAsyncGen_New` are deprecated. | |
| 1129 | 1129 | They are scheduled for removal in 3.18. | |
| 1130 | 1130 | ||
| 1131 | + * Deprecate :c:func:`PyInitConfig_GetExitCode`, :c:func:`PyStatus_Exit`, | ||
| 1132 | + and :c:func:`PyStatus_IsExit` functions, and :c:member:`PyStatus.exitcode` | ||
| 1133 | + member. :c:func:`Py_InitializeFromInitConfig` and | ||
| 1134 | + :c:func:`Py_InitializeFromConfig` can no longer return an exit code. | ||
| 1135 | + Instead, if a command line option wants to exit Python, the option is | ||
| 1136 | + now processed in :c:func:`Py_RunMain`. | ||
| 1137 | + (Contributed by Victor Stinner in :gh:`158080`.) | ||
| 1138 | + | ||
| 1131 | 1139 | * :c:func:`PyModule_GetFilename` is no longer deprecated, but using | |
| 1132 | 1140 | :c:func:`PyModule_GetFilenameObject` instead is still recommended. | |
| 1133 | 1141 | (Contributed by Victor Stinner in :gh:`154757`.) | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -11,19 +11,19 @@ typedef struct { | |||
| 11 | 11 | enum { | |
| 12 | 12 | _PyStatus_TYPE_OK=0, | |
| 13 | 13 | _PyStatus_TYPE_ERROR=1, | |
| 14 | - _PyStatus_TYPE_EXIT=2 | ||
| 14 | + _PyStatus_TYPE_EXIT=2 // deprecated | ||
| 15 | 15 | } _type; | |
| 16 | 16 | const char *func; | |
| 17 | 17 | const char *err_msg; | |
| 18 | - int exitcode; | ||
| 18 | + Py_DEPRECATED(3.16) int exitcode; | ||
| 19 | 19 | } PyStatus; | |
| 20 | 20 | ||
| 21 | 21 | PyAPI_FUNC(PyStatus) PyStatus_Ok(void); | |
| 22 | 22 | PyAPI_FUNC(PyStatus) PyStatus_Error(const char *err_msg); | |
| 23 | 23 | PyAPI_FUNC(PyStatus) PyStatus_NoMemory(void); | |
| 24 | - PyAPI_FUNC(PyStatus) PyStatus_Exit(int exitcode); | ||
| 24 | + Py_DEPRECATED(3.16) PyAPI_FUNC(PyStatus) PyStatus_Exit(int exitcode); | ||
| 25 | 25 | PyAPI_FUNC(int) PyStatus_IsError(PyStatus err); | |
| 26 | - PyAPI_FUNC(int) PyStatus_IsExit(PyStatus err); | ||
| 26 | + Py_DEPRECATED(3.16) PyAPI_FUNC(int) PyStatus_IsExit(PyStatus err); | ||
| 27 | 27 | PyAPI_FUNC(int) PyStatus_Exception(PyStatus err); | |
| 28 | 28 | ||
| 29 | 29 | /* --- PyWideStringList ------------------------------------------------ */ | |
@@ -242,6 +242,11 @@ typedef struct PyConfig { | |||
| 242 | 242 | // PYTHON_PRESITE=package.module or -X presite=package.module | |
| 243 | 243 | wchar_t *run_presite; | |
| 244 | 244 | #endif | |
| 245 | + | ||
| 246 | + // If a command line option wants to exit Python, store it in this member | ||
| 247 | + // and only process the option in Py_RunMain() instead of PyConfig_Read(). | ||
| 248 | + // If equals to 0, there is no option. | ||
| 249 | + int _deferred_cmdline_option; | ||
| 245 | 250 | } PyConfig; | |
| 246 | 251 | ||
| 247 | 252 | PyAPI_FUNC(void) PyConfig_InitPythonConfig(PyConfig *config); | |
@@ -293,7 +298,7 @@ PyAPI_FUNC(void) PyInitConfig_Free(PyInitConfig *config); | |||
| 293 | 298 | ||
| 294 | 299 | PyAPI_FUNC(int) PyInitConfig_GetError(PyInitConfig* config, | |
| 295 | 300 | const char **err_msg); | |
| 296 | - PyAPI_FUNC(int) PyInitConfig_GetExitCode(PyInitConfig* config, | ||
| 301 | + Py_DEPRECATED(3.16) PyAPI_FUNC(int) PyInitConfig_GetExitCode(PyInitConfig* config, | ||
| 297 | 302 | int *exitcode); | |
| 298 | 303 | ||
| 299 | 304 | PyAPI_FUNC(int) PyInitConfig_HasOption(PyInitConfig *config, | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -182,6 +182,8 @@ extern PyObject* _PyConfig_CreateXOptionsDict(const PyConfig *config); | |||
| 182 | 182 | ||
| 183 | 183 | extern void _Py_DumpPathConfig(PyThreadState *tstate); | |
| 184 | 184 | ||
| 185 | + extern int _PyConfig_ProcessDeferredCmdlineOption(PyConfig *config); | ||
| 186 | + | ||
| 185 | 187 | ||
| 186 | 188 | /* --- Function used for testing ---------------------------------- */ | |
| 187 | 189 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -133,11 +133,16 @@ def test_site_flag(self): | |||
| 133 | 133 | ||
| 134 | 134 | @support.cpython_only | |
| 135 | 135 | def test_version(self): | |
| 136 | - version = ('Python %d.%d' % sys.version_info[:2]).encode("ascii") | ||
| 137 | - for switch in '-V', '--version', '-VV': | ||
| 138 | - rc, out, err = assert_python_ok(switch) | ||
| 139 | - self.assertNotStartsWith(err, version) | ||
| 140 | - self.assertStartsWith(out, version) | ||
| 136 | + short_version = ('Python %d.%d' % sys.version_info[:2]) | ||
| 137 | + for switch in ('-V', '--version'): | ||
| 138 | + with self.subTest(switch=switch): | ||
| 139 | + rc, out, err = assert_python_ok(switch) | ||
| 140 | + self.assertStartsWith(out, short_version.encode()) | ||
| 141 | + self.assertEqual(err, b'') | ||
| 142 | + | ||
| 143 | + rc, out, err = assert_python_ok('-VV') | ||
| 144 | + self.assertEqual(out.rstrip(), f"Python {sys.version}".encode()) | ||
| 145 | + self.assertEqual(err, b'') | ||
| 141 | 146 | ||
| 142 | 147 | def test_verbose(self): | |
| 143 | 148 | # -v causes imports to write to stderr. If the write to | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -783,6 +783,7 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase): | |||
| 783 | 783 | 'use_frozen_modules': not support.Py_DEBUG, | |
| 784 | 784 | 'safe_path': False, | |
| 785 | 785 | '_is_python_build': IGNORE_CONFIG, | |
| 786 | + '_deferred_cmdline_option': 0, | ||
| 786 | 787 | } | |
| 787 | 788 | if Py_STATS: | |
| 788 | 789 | CONFIG_COMPAT['_pystats'] = False | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,6 @@ | |||
| 1 | + Deprecate :c:func:`PyInitConfig_GetExitCode`, :c:func:`PyStatus_Exit`, and | ||
| 2 | + :c:func:`PyStatus_IsExit` functions, and :c:member:`PyStatus.exitcode` | ||
| 3 | + member. :c:func:`Py_InitializeFromInitConfig` and | ||
| 4 | + :c:func:`Py_InitializeFromConfig` can no longer return an exit code. | ||
| 5 | + Instead, if a command line option wants to exit Python, the option is | ||
| 6 | + now processed in :c:func:`Py_RunMain`. Patch by Victor Stinner. | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -749,13 +749,21 @@ pymain_set_path0(PyObject *main_importer_path) | |||
| 749 | 749 | static void | |
| 750 | 750 | pymain_run_python(int *exitcode) | |
| 751 | 751 | { | |
| 752 | - int set_running_main = 0; | ||
| 753 | - | ||
| 754 | - PyObject *main_importer_path = NULL; | ||
| 755 | 752 | PyInterpreterState *interp = _PyInterpreterState_GET(); | |
| 756 | 753 | /* pymain_repl() and pymain_run_stdin() modify the config */ | |
| 757 | 754 | PyConfig *config = (PyConfig*)_PyInterpreterState_GetConfig(interp); | |
| 758 | 755 | ||
| 756 | + // Process command line options which want to exit Python | ||
| 757 | + int cmdline_exitcode = _PyConfig_ProcessDeferredCmdlineOption(config); | ||
| 758 | + if (cmdline_exitcode >= 0) { | ||
| 759 | + *exitcode = cmdline_exitcode; | ||
| 760 | + return; | ||
| 761 | + } | ||
| 762 | + | ||
| 763 | + int set_running_main = 0; | ||
| 764 | + | ||
| 765 | + PyObject *main_importer_path = NULL; | ||
| 766 | + | ||
| 759 | 767 | /* ensure path config is written into global variables */ | |
| 760 | 768 | PyStatus status = _PyPathConfig_UpdateGlobal(config); | |
| 761 | 769 | if (_PyStatus_EXCEPTION(status)) { | |
@@ -910,10 +918,7 @@ static int | |||
| 910 | 918 | pymain_main(_PyArgv *args) | |
| 911 | 919 | { | |
| 912 | 920 | PyStatus status = pymain_init(args); | |
| 913 | - if (_PyStatus_IS_EXIT(status)) { | ||
| 914 | - pymain_free(); | ||
| 915 | - return status.exitcode; | ||
| 916 | - } | ||
| 921 | + assert(!_PyStatus_IS_EXIT(status)); | ||
| 917 | 922 | if (_PyStatus_EXCEPTION(status)) { | |
| 918 | 923 | pymain_exit_error(status); | |
| 919 | 924 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -104,9 +104,6 @@ main(int argc, char **argv) | |||
| 104 | 104 | ||
| 105 | 105 | error: | |
| 106 | 106 | PyConfig_Clear(&config); | |
| 107 | - if (PyStatus_IsExit(status)) { | ||
| 108 | - return status.exitcode; | ||
| 109 | - } | ||
| 110 | 107 | Py_ExitStatusException(status); | |
| 111 | 108 | } | |
| 112 | 109 | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments