diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 4e5328282f1224..7eba212cbb9a6a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -33,6 +33,7 @@ jobs: check_source: name: 'Check for source changes' runs-on: ubuntu-latest + timeout-minutes: 10 outputs: run_tests: ${{ steps.check.outputs.run_tests }} steps: @@ -63,6 +64,7 @@ jobs: check_generated_files: name: 'Check if generated files are up to date' runs-on: ubuntu-latest + timeout-minutes: 60 needs: check_source if: needs.check_source.outputs.run_tests == 'true' steps: @@ -118,6 +120,7 @@ jobs: build_win32: name: 'Windows (x86)' runs-on: windows-latest + timeout-minutes: 60 needs: check_source if: needs.check_source.outputs.run_tests == 'true' env: @@ -126,7 +129,6 @@ jobs: - uses: actions/checkout@v3 - name: Build CPython run: .\PCbuild\build.bat -e -d -p Win32 - timeout-minutes: 30 - name: Display build info run: .\python.bat -m test.pythoninfo - name: Tests @@ -135,6 +137,7 @@ jobs: build_win_amd64: name: 'Windows (x64)' runs-on: windows-latest + timeout-minutes: 60 needs: check_source if: needs.check_source.outputs.run_tests == 'true' env: @@ -145,7 +148,6 @@ jobs: run: echo "::add-matcher::.github/problem-matchers/msvc.json" - name: Build CPython run: .\PCbuild\build.bat -e -d -p x64 - timeout-minutes: 30 - name: Display build info run: .\python.bat -m test.pythoninfo - name: Tests @@ -154,6 +156,7 @@ jobs: build_macos: name: 'macOS' runs-on: macos-latest + timeout-minutes: 60 needs: check_source if: needs.check_source.outputs.run_tests == 'true' env: @@ -184,6 +187,7 @@ jobs: build_ubuntu: name: 'Ubuntu' runs-on: ubuntu-20.04 + timeout-minutes: 60 needs: check_source if: needs.check_source.outputs.run_tests == 'true' env: @@ -241,6 +245,7 @@ jobs: build_ubuntu_ssltests: name: 'Ubuntu SSL tests with OpenSSL' runs-on: ubuntu-20.04 + timeout-minutes: 60 needs: check_source if: needs.check_source.outputs.run_tests == 'true' strategy: @@ -290,6 +295,7 @@ jobs: build_asan: name: 'Address sanitizer' runs-on: ubuntu-20.04 + timeout-minutes: 60 needs: check_source if: needs.check_source.outputs.run_tests == 'true' env: diff --git a/.github/workflows/build_msi.yml b/.github/workflows/build_msi.yml index 5f1dcae190efbc..2bed09014e0ff2 100644 --- a/.github/workflows/build_msi.yml +++ b/.github/workflows/build_msi.yml @@ -26,6 +26,7 @@ jobs: build: name: Windows Installer runs-on: windows-latest + timeout-minutes: 60 strategy: matrix: type: [x86, x64, arm64] diff --git a/.github/workflows/doc.yml b/.github/workflows/doc.yml index 314a7da647ff70..3101b30231c355 100644 --- a/.github/workflows/doc.yml +++ b/.github/workflows/doc.yml @@ -36,6 +36,7 @@ jobs: build_doc: name: 'Docs' runs-on: ubuntu-latest + timeout-minutes: 60 steps: - uses: actions/checkout@v3 - name: Register Sphinx problem matcher @@ -80,6 +81,7 @@ jobs: doctest: name: 'Doctest' runs-on: ubuntu-latest + timeout-minutes: 60 steps: - uses: actions/checkout@v3 - name: Register Sphinx problem matcher diff --git a/.github/workflows/new-bugs-announce-notifier.yml b/.github/workflows/new-bugs-announce-notifier.yml index b2a76ef7d36153..73806c5d6d58af 100644 --- a/.github/workflows/new-bugs-announce-notifier.yml +++ b/.github/workflows/new-bugs-announce-notifier.yml @@ -11,6 +11,7 @@ permissions: jobs: notify-new-bugs-announce: runs-on: ubuntu-latest + timeout-minutes: 10 steps: - uses: actions/setup-node@v3 with: diff --git a/.github/workflows/project-updater.yml b/.github/workflows/project-updater.yml index 99c7a05ae8cab0..dde923b26c2a71 100644 --- a/.github/workflows/project-updater.yml +++ b/.github/workflows/project-updater.yml @@ -13,6 +13,7 @@ jobs: add-to-project: name: Add issues to projects runs-on: ubuntu-latest + timeout-minutes: 10 strategy: matrix: include: @@ -22,7 +23,7 @@ jobs: - { project: 3, label: expert-subinterpreters } - { project: 29, label: expert-asyncio } - { project: 32, label: sprint } - + steps: - uses: actions/add-to-project@v0.1.0 with: diff --git a/.github/workflows/require-pr-label.yml b/.github/workflows/require-pr-label.yml index e847bae155e216..151a60c2c04d26 100644 --- a/.github/workflows/require-pr-label.yml +++ b/.github/workflows/require-pr-label.yml @@ -8,6 +8,7 @@ jobs: label: name: DO-NOT-MERGE runs-on: ubuntu-latest + timeout-minutes: 10 steps: - uses: mheap/github-action-required-labels@v4 diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index d79e856c87e78d..94676f5ee5fffc 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -12,6 +12,7 @@ jobs: if: github.repository_owner == 'python' runs-on: ubuntu-latest + timeout-minutes: 10 steps: - name: "Check PRs" diff --git a/.github/workflows/verify-ensurepip-wheels.yml b/.github/workflows/verify-ensurepip-wheels.yml index 969515ed287b55..d4a2cb6846c1cb 100644 --- a/.github/workflows/verify-ensurepip-wheels.yml +++ b/.github/workflows/verify-ensurepip-wheels.yml @@ -23,6 +23,7 @@ concurrency: jobs: verify: runs-on: ubuntu-latest + timeout-minutes: 10 steps: - uses: actions/checkout@v3 - uses: actions/setup-python@v4 diff --git a/Doc/howto/isolating-extensions.rst b/Doc/howto/isolating-extensions.rst index 2eddb582da7c24..0262054ae2b4a0 100644 --- a/Doc/howto/isolating-extensions.rst +++ b/Doc/howto/isolating-extensions.rst @@ -372,7 +372,7 @@ To save a some tedious error-handling boilerplate code, you can combine these two steps with :c:func:`PyType_GetModuleState`, resulting in:: my_struct *state = (my_struct*)PyType_GetModuleState(type); - if (state === NULL) { + if (state == NULL) { return NULL; } @@ -435,7 +435,7 @@ For example:: PyObject *kwnames) { my_struct *state = (my_struct*)PyType_GetModuleState(defining_class); - if (state === NULL) { + if (state == NULL) { return NULL; } ... // rest of logic @@ -479,7 +479,7 @@ to get the state:: PyObject *module = PyType_GetModuleByDef(Py_TYPE(self), &module_def); my_struct *state = (my_struct*)PyModule_GetState(module); - if (state === NULL) { + if (state == NULL) { return NULL; } diff --git a/Doc/howto/perf_profiling.rst b/Doc/howto/perf_profiling.rst index ad2eb7b4d58aa5..6af5536166f58a 100644 --- a/Doc/howto/perf_profiling.rst +++ b/Doc/howto/perf_profiling.rst @@ -15,9 +15,9 @@ information about the performance of your application. that aid with the analysis of the data that it produces. The main problem with using the ``perf`` profiler with Python applications is that -``perf`` only allows to get information about native symbols, this is, the names of -the functions and procedures written in C. This means that the names and file names -of the Python functions in your code will not appear in the output of the ``perf``. +``perf`` only gets information about native symbols, that is, the names of +functions and procedures written in C. This means that the names and file names +of Python functions in your code will not appear in the output of ``perf``. Since Python 3.12, the interpreter can run in a special mode that allows Python functions to appear in the output of the ``perf`` profiler. When this mode is @@ -28,8 +28,8 @@ relationship between this piece of code and the associated Python function using .. note:: - Support for the ``perf`` profiler is only currently available for Linux on - selected architectures. Check the output of the configure build step or + Support for the ``perf`` profiler is currently only available for Linux on + select architectures. Check the output of the ``configure`` build step or check the output of ``python -m sysconfig | grep HAVE_PERF_TRAMPOLINE`` to see if your system is supported. @@ -52,11 +52,11 @@ For example, consider the following script: if __name__ == "__main__": baz(1000000) -We can run ``perf`` to sample CPU stack traces at 9999 Hertz:: +We can run ``perf`` to sample CPU stack traces at 9999 hertz:: $ perf record -F 9999 -g -o perf.data python my_script.py -Then we can use ``perf`` report to analyze the data: +Then we can use ``perf report`` to analyze the data: .. code-block:: shell-session @@ -97,7 +97,7 @@ Then we can use ``perf`` report to analyze the data: | | | | | |--2.97%--_PyObject_Malloc ... -As you can see here, the Python functions are not shown in the output, only ``_Py_Eval_EvalFrameDefault`` appears +As you can see, the Python functions are not shown in the output, only ``_Py_Eval_EvalFrameDefault`` (the function that evaluates the Python bytecode) shows up. Unfortunately that's not very useful because all Python functions use the same C function to evaluate bytecode so we cannot know which Python function corresponds to which bytecode-evaluating function. @@ -151,7 +151,7 @@ Instead, if we run the same experiment with ``perf`` support enabled we get: How to enable ``perf`` profiling support ---------------------------------------- -``perf`` profiling support can either be enabled from the start using +``perf`` profiling support can be enabled either from the start using the environment variable :envvar:`PYTHONPERFSUPPORT` or the :option:`-X perf <-X>` option, or dynamically using :func:`sys.activate_stack_trampoline` and @@ -192,7 +192,7 @@ Example, using the :mod:`sys` APIs in file :file:`example.py`: How to obtain the best results ------------------------------ -For the best results, Python should be compiled with +For best results, Python should be compiled with ``CFLAGS="-fno-omit-frame-pointer -mno-omit-leaf-frame-pointer"`` as this allows profilers to unwind using only the frame pointer and not on DWARF debug information. This is because as the code that is interposed to allow ``perf`` diff --git a/Lib/importlib/_bootstrap.py b/Lib/importlib/_bootstrap.py index 22fa2469964ab3..e4fcaa61e6de29 100644 --- a/Lib/importlib/_bootstrap.py +++ b/Lib/importlib/_bootstrap.py @@ -1260,7 +1260,7 @@ def _find_and_load_unlocked(name, import_): try: path = parent_module.__path__ except AttributeError: - msg = f'{_ERR_MSG_PREFIX} {name!r}; {parent!r} is not a package' + msg = f'{_ERR_MSG_PREFIX}{name!r}; {parent!r} is not a package' raise ModuleNotFoundError(msg, name=name) from None parent_spec = parent_module.__spec__ child = name.rpartition('.')[2] diff --git a/Lib/ipaddress.py b/Lib/ipaddress.py index 1cb71d8032e173..af1d5c4800cce8 100644 --- a/Lib/ipaddress.py +++ b/Lib/ipaddress.py @@ -1821,9 +1821,6 @@ def _string_from_ip_int(cls, ip_int=None): def _explode_shorthand_ip_string(self): """Expand a shortened IPv6 address. - Args: - ip_str: A string, the IPv6 address. - Returns: A string, the expanded IPv6 address. diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py index 3a3646f1861e80..cfdb992654c252 100644 --- a/Lib/test/test_inspect.py +++ b/Lib/test/test_inspect.py @@ -3044,14 +3044,9 @@ def foo(a=1, b=2, c=3): self.assertEqual(_foo(*ba.args, **ba.kwargs), (12, 10, 20)) - def foo(a, b, c, d, **kwargs): + def foo(a, b, /, c, d, **kwargs): pass sig = inspect.signature(foo) - params = sig.parameters.copy() - params['a'] = params['a'].replace(kind=Parameter.POSITIONAL_ONLY) - params['b'] = params['b'].replace(kind=Parameter.POSITIONAL_ONLY) - foo.__signature__ = inspect.Signature(params.values()) - sig = inspect.signature(foo) self.assertEqual(str(sig), '(a, b, /, c, d, **kwargs)') self.assertEqual(self.signature(partial(foo, 1)), @@ -3556,14 +3551,9 @@ def test_signature_str_positional_only(self): P = inspect.Parameter S = inspect.Signature - def test(a_po, *, b, **kwargs): + def test(a_po, /, *, b, **kwargs): return a_po, kwargs - sig = inspect.signature(test) - new_params = list(sig.parameters.values()) - new_params[0] = new_params[0].replace(kind=P.POSITIONAL_ONLY) - test.__signature__ = sig.replace(parameters=new_params) - self.assertEqual(str(inspect.signature(test)), '(a_po, /, *, b, **kwargs)') @@ -3593,6 +3583,14 @@ def test() -> 42: self.assertEqual(sig.return_annotation, 42) self.assertEqual(sig, inspect.signature(test)) + def test_signature_replaced(self): + def test(): + pass + + spam_param = inspect.Parameter('spam', inspect.Parameter.POSITIONAL_ONLY) + sig = test.__signature__ = inspect.Signature(parameters=(spam_param,)) + self.assertEqual(sig, inspect.signature(test)) + def test_signature_on_mangled_parameters(self): class Spam: def foo(self, __p1:1=2, *, __p2:2=3): @@ -4157,16 +4155,9 @@ def test(a, *args, b, z=100, **kwargs): def test_signature_bind_positional_only(self): P = inspect.Parameter - def test(a_po, b_po, c_po=3, foo=42, *, bar=50, **kwargs): + def test(a_po, b_po, c_po=3, /, foo=42, *, bar=50, **kwargs): return a_po, b_po, c_po, foo, bar, kwargs - sig = inspect.signature(test) - new_params = collections.OrderedDict(tuple(sig.parameters.items())) - for name in ('a_po', 'b_po', 'c_po'): - new_params[name] = new_params[name].replace(kind=P.POSITIONAL_ONLY) - new_sig = sig.replace(parameters=new_params.values()) - test.__signature__ = new_sig - self.assertEqual(self.call(test, 1, 2, 4, 5, bar=6), (1, 2, 4, 5, 6, {})) diff --git a/Modules/_tkinter.c b/Modules/_tkinter.c index 20e01c79668549..385a05932a77ed 100644 --- a/Modules/_tkinter.c +++ b/Modules/_tkinter.c @@ -324,10 +324,6 @@ static int quitMainLoop = 0; static int errorInCmd = 0; static PyObject *excInCmd; -#ifdef TKINTER_PROTECT_LOADTK -static int tk_load_failed = 0; -#endif - static PyObject *Tkapp_UnicodeResult(TkappObject *); @@ -532,17 +528,7 @@ Tcl_AppInit(Tcl_Interp *interp) return TCL_OK; } -#ifdef TKINTER_PROTECT_LOADTK - if (tk_load_failed) { - PySys_WriteStderr("Tk_Init error: %s\n", TKINTER_LOADTK_ERRMSG); - return TCL_ERROR; - } -#endif - if (Tk_Init(interp) == TCL_ERROR) { -#ifdef TKINTER_PROTECT_LOADTK - tk_load_failed = 1; -#endif PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp)); return TCL_ERROR; } @@ -635,12 +621,6 @@ Tkapp_New(const char *screenName, const char *className, Tcl_SetVar(v->interp, "_tkinter_skip_tk_init", "1", TCL_GLOBAL_ONLY); } -#ifdef TKINTER_PROTECT_LOADTK - else if (tk_load_failed) { - Tcl_SetVar(v->interp, - "_tkinter_tk_failed", "1", TCL_GLOBAL_ONLY); - } -#endif /* some initial arguments need to be in argv */ if (sync || use) { @@ -702,18 +682,6 @@ Tkapp_New(const char *screenName, const char *className, if (Tcl_AppInit(v->interp) != TCL_OK) { PyObject *result = Tkinter_Error(v); -#ifdef TKINTER_PROTECT_LOADTK - if (wantTk) { - const char *_tkinter_tk_failed; - _tkinter_tk_failed = Tcl_GetVar(v->interp, - "_tkinter_tk_failed", TCL_GLOBAL_ONLY); - - if ( _tkinter_tk_failed != NULL && - strcmp(_tkinter_tk_failed, "1") == 0) { - tk_load_failed = 1; - } - } -#endif Py_DECREF((PyObject *)v); return (TkappObject *)result; } @@ -2780,18 +2748,6 @@ _tkinter_tkapp_loadtk_impl(TkappObject *self) const char * _tk_exists = NULL; int err; -#ifdef TKINTER_PROTECT_LOADTK - /* Up to Tk 8.4.13, Tk_Init deadlocks on the second call when the - * first call failed. - * To avoid the deadlock, we just refuse the second call through - * a static variable. - */ - if (tk_load_failed) { - PyErr_SetString(Tkinter_TclError, TKINTER_LOADTK_ERRMSG); - return NULL; - } -#endif - /* We want to guard against calling Tk_Init() multiple times */ CHECK_TCL_APPARTMENT; ENTER_TCL @@ -2811,9 +2767,6 @@ _tkinter_tkapp_loadtk_impl(TkappObject *self) if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) { if (Tk_Init(interp) == TCL_ERROR) { Tkinter_Error(self); -#ifdef TKINTER_PROTECT_LOADTK - tk_load_failed = 1; -#endif return NULL; } } diff --git a/Modules/tkappinit.c b/Modules/tkappinit.c index 7616d9d319d228..67d6250318c616 100644 --- a/Modules/tkappinit.c +++ b/Modules/tkappinit.c @@ -18,18 +18,10 @@ #include "tkinter.h" -#ifdef TKINTER_PROTECT_LOADTK -/* See Tkapp_TkInit in _tkinter.c for the usage of tk_load_faile */ -static int tk_load_failed; -#endif - int Tcl_AppInit(Tcl_Interp *interp) { const char *_tkinter_skip_tk_init; -#ifdef TKINTER_PROTECT_LOADTK - const char *_tkinter_tk_failed; -#endif #ifdef TK_AQUA #ifndef MAX_PATH_LEN @@ -90,23 +82,7 @@ Tcl_AppInit(Tcl_Interp *interp) return TCL_OK; } -#ifdef TKINTER_PROTECT_LOADTK - _tkinter_tk_failed = Tcl_GetVar(interp, - "_tkinter_tk_failed", TCL_GLOBAL_ONLY); - - if (tk_load_failed || ( - _tkinter_tk_failed != NULL && - strcmp(_tkinter_tk_failed, "1") == 0)) { - Tcl_SetResult(interp, TKINTER_LOADTK_ERRMSG, TCL_STATIC); - return TCL_ERROR; - } -#endif - if (Tk_Init(interp) == TCL_ERROR) { -#ifdef TKINTER_PROTECT_LOADTK - tk_load_failed = 1; - Tcl_SetVar(interp, "_tkinter_tk_failed", "1", TCL_GLOBAL_ONLY); -#endif return TCL_ERROR; } diff --git a/Modules/tkinter.h b/Modules/tkinter.h index cb5a806b0c4326..40281c21760331 100644 --- a/Modules/tkinter.h +++ b/Modules/tkinter.h @@ -16,12 +16,4 @@ (TK_RELEASE_LEVEL << 8) | \ (TK_RELEASE_SERIAL << 0)) -/* Protect Tk 8.4.13 and older from a deadlock that happens when trying - * to load tk after a failed attempt. */ -#if TK_HEX_VERSION < 0x0804020e -#define TKINTER_PROTECT_LOADTK -#define TKINTER_LOADTK_ERRMSG \ - "Calling Tk_Init again after a previous call failed might deadlock" -#endif - #endif /* !TKINTER_H */ diff --git a/Python/instrumentation.c b/Python/instrumentation.c index 8dc8b01fcb0496..853e8a10e81463 100644 --- a/Python/instrumentation.c +++ b/Python/instrumentation.c @@ -125,6 +125,7 @@ is_instrumented(int opcode) { return opcode >= MIN_INSTRUMENTED_OPCODE; } +#ifndef NDEBUG static inline bool monitors_equals(_Py_Monitors a, _Py_Monitors b) { @@ -135,6 +136,7 @@ monitors_equals(_Py_Monitors a, _Py_Monitors b) } return true; } +#endif static inline _Py_Monitors monitors_sub(_Py_Monitors a, _Py_Monitors b) @@ -146,6 +148,7 @@ monitors_sub(_Py_Monitors a, _Py_Monitors b) return res; } +#ifndef NDEBUG static inline _Py_Monitors monitors_and(_Py_Monitors a, _Py_Monitors b) { @@ -155,6 +158,7 @@ monitors_and(_Py_Monitors a, _Py_Monitors b) } return res; } +#endif static inline _Py_Monitors monitors_or(_Py_Monitors a, _Py_Monitors b)