Nuitka-winsvc 2.1.6__cp311-cp311-win_amd64.whl → 2.2.2__cp311-cp311-win_amd64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of Nuitka-winsvc might be problematic. Click here for more details.

Files changed (234) hide show
  1. {Nuitka_winsvc-2.1.6.dist-info → Nuitka_winsvc-2.2.2.dist-info}/METADATA +1 -1
  2. {Nuitka_winsvc-2.1.6.dist-info → Nuitka_winsvc-2.2.2.dist-info}/RECORD +234 -225
  3. nuitka/Errors.py +4 -0
  4. nuitka/HardImportRegistry.py +18 -1
  5. nuitka/MainControl.py +27 -30
  6. nuitka/OptionParsing.py +32 -30
  7. nuitka/Options.py +26 -13
  8. nuitka/OutputDirectories.py +7 -4
  9. nuitka/PostProcessing.py +9 -7
  10. nuitka/Progress.py +3 -3
  11. nuitka/PythonVersions.py +2 -2
  12. nuitka/TreeXML.py +1 -1
  13. nuitka/Version.py +1 -1
  14. nuitka/build/Backend.scons +2 -1
  15. nuitka/build/DataComposerInterface.py +1 -0
  16. nuitka/build/Onefile.scons +2 -1
  17. nuitka/build/SconsCaching.py +64 -46
  18. nuitka/build/SconsCompilerSettings.py +19 -6
  19. nuitka/build/SconsHacks.py +0 -1
  20. nuitka/build/SconsInterface.py +84 -5
  21. nuitka/build/SconsProgress.py +0 -1
  22. nuitka/build/SconsUtils.py +8 -4
  23. nuitka/build/include/nuitka/allocator.h +8 -3
  24. nuitka/build/include/nuitka/compiled_cell.h +8 -0
  25. nuitka/build/include/nuitka/exceptions.h +554 -179
  26. nuitka/build/include/nuitka/helper/dictionaries.h +1 -1
  27. nuitka/build/include/nuitka/helper/import_hard.h +3 -0
  28. nuitka/build/include/nuitka/helper/ints.h +15 -2
  29. nuitka/build/include/nuitka/helper/lists.h +4 -1
  30. nuitka/build/include/nuitka/helper/raising.h +12 -0
  31. nuitka/build/include/nuitka/helper/tuples.h +5 -1
  32. nuitka/build/include/nuitka/helpers.h +4 -0
  33. nuitka/build/include/nuitka/importing.h +3 -4
  34. nuitka/build/include/nuitka/jit_sources.h +25 -0
  35. nuitka/build/include/nuitka/prelude.h +38 -11
  36. nuitka/build/include/nuitka/printing.h +3 -0
  37. nuitka/build/include/nuitka/threading.h +2 -6
  38. nuitka/build/include/nuitka/type_aliases.h +27 -0
  39. nuitka/build/inline_copy/pkg_resources/pkg_resources/__init__.py +0 -3
  40. nuitka/build/inline_copy/tqdm/tqdm/version.py +1 -4
  41. nuitka/build/static_src/CompiledAsyncgenType.c +99 -114
  42. nuitka/build/static_src/CompiledCodeHelpers.c +23 -14
  43. nuitka/build/static_src/CompiledCoroutineType.c +96 -114
  44. nuitka/build/static_src/CompiledFrameType.c +14 -11
  45. nuitka/build/static_src/CompiledFunctionType.c +34 -7
  46. nuitka/build/static_src/CompiledGeneratorType.c +248 -142
  47. nuitka/build/static_src/CompiledGeneratorTypeUncompiledIntegration.c +60 -70
  48. nuitka/build/static_src/CompiledMethodType.c +8 -7
  49. nuitka/build/static_src/HelpersAttributes.c +2 -19
  50. nuitka/build/static_src/HelpersBuiltin.c +2 -1
  51. nuitka/build/static_src/HelpersComparisonEq.c +32 -18
  52. nuitka/build/static_src/HelpersComparisonGe.c +50 -36
  53. nuitka/build/static_src/HelpersComparisonGt.c +50 -36
  54. nuitka/build/static_src/HelpersComparisonLe.c +50 -36
  55. nuitka/build/static_src/HelpersComparisonLt.c +50 -36
  56. nuitka/build/static_src/HelpersComparisonNe.c +32 -18
  57. nuitka/build/static_src/HelpersDeepcopy.c +6 -8
  58. nuitka/build/static_src/HelpersDictionaries.c +8 -3
  59. nuitka/build/static_src/HelpersExceptions.c +42 -28
  60. nuitka/build/static_src/HelpersFilesystemPaths.c +7 -7
  61. nuitka/build/static_src/HelpersImportHard.c +15 -0
  62. nuitka/build/static_src/HelpersJitSources.c +46 -0
  63. nuitka/build/static_src/HelpersLists.c +40 -0
  64. nuitka/build/static_src/HelpersOperationBinaryAdd.c +66 -66
  65. nuitka/build/static_src/HelpersOperationBinaryAddUtils.c +80 -33
  66. nuitka/build/static_src/HelpersOperationBinaryMultUtils.c +16 -13
  67. nuitka/build/static_src/HelpersOperationBinarySub.c +39 -39
  68. nuitka/build/static_src/HelpersOperationInplaceAdd.c +54 -54
  69. nuitka/build/static_src/HelpersOperationInplaceAddUtils.c +1 -1
  70. nuitka/build/static_src/HelpersOperationInplaceSub.c +50 -50
  71. nuitka/build/static_src/HelpersProfiling.c +3 -4
  72. nuitka/build/static_src/HelpersRaising.c +62 -1
  73. nuitka/build/static_src/HelpersStrings.c +203 -8
  74. nuitka/build/static_src/HelpersTypes.c +42 -0
  75. nuitka/build/static_src/MainProgram.c +1 -1
  76. nuitka/build/static_src/MetaPathBasedLoader.c +2 -1
  77. nuitka/build/static_src/OnefileBootstrap.c +3 -3
  78. nuitka/code_generation/BinaryOperationHelperDefinitions.py +5 -3
  79. nuitka/code_generation/BuiltinCodes.py +1 -0
  80. nuitka/code_generation/CodeGeneration.py +11 -0
  81. nuitka/code_generation/CodeHelpers.py +5 -3
  82. nuitka/code_generation/CodeObjectCodes.py +10 -6
  83. nuitka/code_generation/ComparisonCodes.py +19 -3
  84. nuitka/code_generation/ConstantCodes.py +5 -0
  85. nuitka/code_generation/Contexts.py +22 -6
  86. nuitka/code_generation/Emission.py +1 -0
  87. nuitka/code_generation/ErrorCodes.py +8 -16
  88. nuitka/code_generation/EvalCodes.py +5 -3
  89. nuitka/code_generation/ExceptionCodes.py +8 -1
  90. nuitka/code_generation/ExpressionCTypeSelectionHelpers.py +1 -0
  91. nuitka/code_generation/FrameCodes.py +5 -3
  92. nuitka/code_generation/FunctionCodes.py +0 -1
  93. nuitka/code_generation/GeneratorCodes.py +3 -3
  94. nuitka/code_generation/GlobalConstants.py +0 -2
  95. nuitka/code_generation/ImportCodes.py +2 -0
  96. nuitka/code_generation/JitCodes.py +44 -0
  97. nuitka/code_generation/ListCodes.py +11 -17
  98. nuitka/code_generation/MatchCodes.py +0 -1
  99. nuitka/code_generation/ModuleCodes.py +2 -1
  100. nuitka/code_generation/Namify.py +0 -1
  101. nuitka/code_generation/NetworkxCodes.py +51 -0
  102. nuitka/code_generation/OperationCodes.py +8 -6
  103. nuitka/code_generation/PackageResourceCodes.py +7 -5
  104. nuitka/code_generation/TensorflowCodes.py +54 -0
  105. nuitka/code_generation/TypeAliasCodes.py +71 -0
  106. nuitka/code_generation/VariableCodes.py +7 -5
  107. nuitka/code_generation/VariableDeclarations.py +1 -0
  108. nuitka/code_generation/c_types/CTypeCLongs.py +0 -1
  109. nuitka/code_generation/c_types/CTypeNuitkaInts.py +0 -1
  110. nuitka/code_generation/c_types/CTypeVoids.py +1 -0
  111. nuitka/code_generation/templates/CodeTemplatesConstants.py +14 -0
  112. nuitka/code_generation/templates/CodeTemplatesExceptions.py +1 -1
  113. nuitka/code_generation/templates/CodeTemplatesIterators.py +0 -1
  114. nuitka/code_generation/templates/CodeTemplatesLoader.py +0 -1
  115. nuitka/code_generation/templates/CodeTemplatesModules.py +9 -4
  116. nuitka/code_generation/templates/CodeTemplatesVariables.py +8 -8
  117. nuitka/code_generation/templates/TemplateDebugWrapper.py +0 -1
  118. nuitka/code_generation/templates_c/HelperOperationComparisonUnicode.c.j2 +4 -0
  119. nuitka/code_generation/templates_c/HelperSlotsLong.c.j2 +9 -7
  120. nuitka/containers/Namedtuples.py +0 -1
  121. nuitka/finalizations/Finalization.py +1 -0
  122. nuitka/finalizations/FinalizeMarkups.py +0 -1
  123. nuitka/freezer/DllDependenciesMacOS.py +60 -13
  124. nuitka/freezer/DllDependenciesPosix.py +0 -1
  125. nuitka/freezer/DllDependenciesWin32.py +2 -1
  126. nuitka/freezer/IncludedDataFiles.py +46 -15
  127. nuitka/freezer/IncludedEntryPoints.py +5 -3
  128. nuitka/freezer/Standalone.py +6 -1
  129. nuitka/importing/ImportCache.py +2 -2
  130. nuitka/importing/ImportResolving.py +80 -78
  131. nuitka/importing/Importing.py +34 -1
  132. nuitka/nodes/AttributeNodesGenerated.py +21 -6
  133. nuitka/nodes/BuiltinComplexNodes.py +1 -0
  134. nuitka/nodes/BuiltinFormatNodes.py +1 -0
  135. nuitka/nodes/BuiltinIteratorNodes.py +5 -3
  136. nuitka/nodes/BuiltinOperationNodeBasesGenerated.py +21 -6
  137. nuitka/nodes/BuiltinRefNodes.py +8 -1
  138. nuitka/nodes/BuiltinVarsNodes.py +0 -1
  139. nuitka/nodes/ChildrenHavingMixins.py +906 -186
  140. nuitka/nodes/CodeObjectSpecs.py +1 -1
  141. nuitka/nodes/ConditionalNodes.py +2 -6
  142. nuitka/nodes/ConstantRefNodes.py +38 -0
  143. nuitka/nodes/CtypesNodes.py +0 -1
  144. nuitka/nodes/DictionaryNodes.py +0 -1
  145. nuitka/nodes/ExceptionNodes.py +10 -0
  146. nuitka/nodes/ExpressionBases.py +15 -9
  147. nuitka/nodes/ExpressionBasesGenerated.py +32 -15
  148. nuitka/nodes/FunctionNodes.py +50 -5
  149. nuitka/nodes/HardImportNodesGenerated.py +245 -60
  150. nuitka/nodes/ImportHardNodes.py +27 -13
  151. nuitka/nodes/ImportNodes.py +92 -70
  152. nuitka/nodes/InjectCNodes.py +0 -1
  153. nuitka/nodes/ModuleNodes.py +10 -5
  154. nuitka/nodes/NetworkxNodes.py +45 -0
  155. nuitka/nodes/OperatorNodesUnary.py +1 -0
  156. nuitka/nodes/OsSysNodes.py +0 -1
  157. nuitka/nodes/PackageMetadataNodes.py +0 -1
  158. nuitka/nodes/PackageResourceNodes.py +10 -6
  159. nuitka/nodes/StatementBasesGenerated.py +107 -60
  160. nuitka/nodes/StringConcatenationNodes.py +1 -0
  161. nuitka/nodes/TensorflowNodes.py +38 -0
  162. nuitka/nodes/TypeNodes.py +21 -0
  163. nuitka/nodes/VariableRefNodes.py +1 -0
  164. nuitka/nodes/shapes/BuiltinTypeShapes.py +25 -15
  165. nuitka/optimizations/Optimization.py +7 -6
  166. nuitka/optimizations/OptimizeBuiltinCalls.py +11 -9
  167. nuitka/optimizations/Tags.py +0 -1
  168. nuitka/optimizations/TraceCollections.py +6 -55
  169. nuitka/optimizations/ValueTraces.py +49 -1
  170. nuitka/plugins/PluginBase.py +26 -4
  171. nuitka/plugins/Plugins.py +49 -12
  172. nuitka/plugins/standard/AntiBloatPlugin.py +12 -2
  173. nuitka/plugins/standard/ConsiderPyLintAnnotationsPlugin.py +0 -1
  174. nuitka/plugins/standard/DataFilesPlugin.py +2 -6
  175. nuitka/plugins/standard/DillPlugin.py +3 -3
  176. nuitka/plugins/standard/DllFilesPlugin.py +29 -23
  177. nuitka/plugins/standard/GiPlugin.py +1 -0
  178. nuitka/plugins/standard/ImplicitImports.py +8 -7
  179. nuitka/plugins/standard/MatplotlibPlugin.py +1 -0
  180. nuitka/plugins/standard/OptionsNannyPlugin.py +3 -7
  181. nuitka/plugins/standard/PkgResourcesPlugin.py +0 -1
  182. nuitka/plugins/standard/PmwPlugin.py +10 -9
  183. nuitka/plugins/standard/PySidePyQtPlugin.py +0 -28
  184. nuitka/plugins/standard/TensorflowPlugin.py +1 -0
  185. nuitka/plugins/standard/TorchPlugin.py +1 -0
  186. nuitka/plugins/standard/TrioPlugin.py +1 -0
  187. nuitka/plugins/standard/standard.nuitka-package.config.yml +249 -34
  188. nuitka/reports/CompilationReportReader.py +0 -1
  189. nuitka/reports/Reports.py +49 -5
  190. nuitka/specs/BuiltinParameterSpecs.py +10 -2
  191. nuitka/specs/BuiltinStrOperationSpecs.py +1 -1
  192. nuitka/specs/BuiltinTypeOperationSpecs.py +0 -1
  193. nuitka/specs/HardImportSpecs.py +34 -1
  194. nuitka/specs/ParameterSpecs.py +11 -9
  195. nuitka/tools/environments/Virtualenv.py +0 -1
  196. nuitka/tools/specialize/CTypeDescriptions.py +15 -11
  197. nuitka/tools/specialize/SpecializeC.py +11 -9
  198. nuitka/tools/specialize/SpecializePython.py +57 -30
  199. nuitka/tools/testing/Common.py +24 -7
  200. nuitka/tools/testing/OutputComparison.py +4 -0
  201. nuitka/tools/testing/Pythons.py +0 -1
  202. nuitka/tools/testing/compare_with_cpython/__main__.py +0 -4
  203. nuitka/tools/watch/GitHub.py +4 -1
  204. nuitka/tools/watch/__main__.py +22 -1
  205. nuitka/tree/Building.py +3 -0
  206. nuitka/tree/InternalModule.py +0 -1
  207. nuitka/tree/ReformulationAssertStatements.py +1 -0
  208. nuitka/tree/ReformulationAssignmentStatements.py +26 -3
  209. nuitka/tree/ReformulationClasses3.py +23 -26
  210. nuitka/tree/ReformulationContractionExpressions.py +5 -3
  211. nuitka/tree/ReformulationDictionaryCreation.py +6 -5
  212. nuitka/tree/ReformulationExecStatements.py +8 -6
  213. nuitka/tree/ReformulationFunctionStatements.py +10 -6
  214. nuitka/tree/SourceHandling.py +8 -0
  215. nuitka/tree/TreeHelpers.py +6 -3
  216. nuitka/utils/AppDirs.py +6 -2
  217. nuitka/utils/CStrings.py +1 -1
  218. nuitka/utils/CommandLineOptions.py +0 -1
  219. nuitka/utils/Distributions.py +3 -3
  220. nuitka/utils/Download.py +5 -1
  221. nuitka/utils/Execution.py +6 -3
  222. nuitka/utils/FileOperations.py +61 -34
  223. nuitka/utils/Importing.py +4 -4
  224. nuitka/utils/InstanceCounters.py +1 -0
  225. nuitka/utils/MacOSApp.py +1 -0
  226. nuitka/utils/Shebang.py +1 -0
  227. nuitka/utils/Utils.py +39 -1
  228. nuitka/utils/WindowsFileUsage.py +4 -3
  229. {Nuitka_winsvc-2.1.6.data → Nuitka_winsvc-2.2.2.data}/scripts/nuitka-run.bat +0 -0
  230. {Nuitka_winsvc-2.1.6.data → Nuitka_winsvc-2.2.2.data}/scripts/nuitka.bat +0 -0
  231. {Nuitka_winsvc-2.1.6.dist-info → Nuitka_winsvc-2.2.2.dist-info}/LICENSE.txt +0 -0
  232. {Nuitka_winsvc-2.1.6.dist-info → Nuitka_winsvc-2.2.2.dist-info}/WHEEL +0 -0
  233. {Nuitka_winsvc-2.1.6.dist-info → Nuitka_winsvc-2.2.2.dist-info}/entry_points.txt +0 -0
  234. {Nuitka_winsvc-2.1.6.dist-info → Nuitka_winsvc-2.2.2.dist-info}/top_level.txt +0 -0
@@ -11,7 +11,7 @@
11
11
  #include "nuitka/printing.h"
12
12
 
13
13
  // Did an error occur.
14
- NUITKA_MAY_BE_UNUSED static inline bool HAS_ERROR_OCCURRED(PyThreadState *tstate) {
14
+ NUITKA_MAY_BE_UNUSED static inline bool HAS_ERROR_OCCURRED(PyThreadState const *tstate) {
15
15
  #if PYTHON_VERSION < 0x3c0
16
16
  return tstate->curexc_type != NULL;
17
17
  #else
@@ -19,16 +19,57 @@ NUITKA_MAY_BE_UNUSED static inline bool HAS_ERROR_OCCURRED(PyThreadState *tstate
19
19
  #endif
20
20
  }
21
21
 
22
- // Get the error type occurred.
23
- NUITKA_MAY_BE_UNUSED static inline PyObject *GET_ERROR_OCCURRED(PyThreadState *tstate) {
22
+ // Get the error type occurred, no reference given.
23
+ NUITKA_MAY_BE_UNUSED static inline PyObject *GET_ERROR_OCCURRED(PyThreadState const *const tstate) {
24
24
  #if PYTHON_VERSION < 0x3c0
25
25
  return tstate->curexc_type;
26
26
  #else
27
- return (PyObject *)Py_TYPE(tstate->current_exception);
27
+ return tstate->current_exception ? (PyObject *)PyExceptionInstance_Class(tstate->current_exception) : NULL;
28
28
  #endif
29
29
  }
30
30
 
31
- // Clear error, which likely set, similar to _PyErr_Clear(tstate)
31
+ // Checks that an exception value is normalized or NULL.
32
+ NUITKA_MAY_BE_UNUSED static inline void ASSERT_NORMALIZED_EXCEPTION_VALUE_X(PyObject const *const exception_value) {
33
+ CHECK_OBJECT_X(exception_value);
34
+ assert(exception_value == NULL || PyExceptionInstance_Check(exception_value));
35
+ }
36
+
37
+ // Checks that an exception value is normalized and not NULL.
38
+ NUITKA_MAY_BE_UNUSED static inline void ASSERT_NORMALIZED_EXCEPTION_VALUE(PyObject *exception_value) {
39
+ CHECK_OBJECT(exception_value);
40
+ assert(PyExceptionInstance_Check(exception_value));
41
+ }
42
+
43
+ extern void Nuitka_Err_NormalizeException(PyThreadState *tstate, PyObject **exc, PyObject **val,
44
+ PyTracebackObject **tb);
45
+
46
+ // Normalize an exception, may release old values and replace them, expects
47
+ // references passed and returns them.
48
+ NUITKA_MAY_BE_UNUSED static inline void NORMALIZE_EXCEPTION(PyThreadState *tstate, PyObject **exception_type,
49
+ PyObject **exception_value,
50
+ PyTracebackObject **exception_tb) {
51
+ #if _DEBUG_EXCEPTIONS
52
+ PRINT_STRING("NORMALIZE_EXCEPTION: Enter\n");
53
+ PRINT_EXCEPTION(*exception_type, *exception_value, *exception_tb);
54
+ #endif
55
+ CHECK_OBJECT_X(*exception_type);
56
+ CHECK_OBJECT_X(*exception_value);
57
+ if (exception_tb) {
58
+ CHECK_OBJECT_X(*exception_tb);
59
+ }
60
+
61
+ // TODO: Often we already know this to be true.
62
+ if (*exception_type != Py_None && *exception_type != NULL) {
63
+ Nuitka_Err_NormalizeException(tstate, exception_type, exception_value, exception_tb);
64
+ }
65
+
66
+ #if _DEBUG_EXCEPTIONS
67
+ PRINT_STRING("NORMALIZE_EXCEPTION: Leave\n");
68
+ PRINT_EXCEPTION(*exception_type, *exception_value, exception_tb ? *exception_tb : NULL);
69
+ #endif
70
+ }
71
+
72
+ // Clear error, which likely set, similar to "_PyErr_Clear(tstate)" and "PyErr_Clear"
32
73
  NUITKA_MAY_BE_UNUSED static inline void CLEAR_ERROR_OCCURRED(PyThreadState *tstate) {
33
74
  #if PYTHON_VERSION < 0x3c0
34
75
  PyObject *old_type = tstate->curexc_type;
@@ -43,13 +84,16 @@ NUITKA_MAY_BE_UNUSED static inline void CLEAR_ERROR_OCCURRED(PyThreadState *tsta
43
84
  Py_XDECREF(old_value);
44
85
  Py_XDECREF(old_tb);
45
86
  #else
46
- PyObject *old_exception = tstate->current_exception;
87
+ PyObject *old_exception_value = tstate->current_exception;
88
+ ASSERT_NORMALIZED_EXCEPTION_VALUE_X(old_exception_value);
89
+
47
90
  tstate->current_exception = NULL;
48
- Py_XDECREF(old_exception);
91
+
92
+ Py_XDECREF(old_exception_value);
49
93
  #endif
50
94
  }
51
95
 
52
- // Clear error, which is not likely set, use CLEAR_ERROR_OCCURRED not sure there is an error.
96
+ // Clear error, which is not likely set, use "CLEAR_ERROR_OCCURRED" not sure there is an error.
53
97
  NUITKA_MAY_BE_UNUSED static inline bool DROP_ERROR_OCCURRED(PyThreadState *tstate) {
54
98
 
55
99
  #if PYTHON_VERSION < 0x3c0
@@ -70,11 +114,12 @@ NUITKA_MAY_BE_UNUSED static inline bool DROP_ERROR_OCCURRED(PyThreadState *tstat
70
114
  }
71
115
  #else
72
116
  if (unlikely(tstate->current_exception != NULL)) {
73
- PyObject *old_exception = tstate->current_exception;
117
+ PyObject *old_exception_value = tstate->current_exception;
118
+ ASSERT_NORMALIZED_EXCEPTION_VALUE(old_exception_value);
74
119
 
75
120
  tstate->current_exception = NULL;
76
121
 
77
- Py_DECREF(old_exception);
122
+ Py_DECREF(old_exception_value);
78
123
 
79
124
  return true;
80
125
  }
@@ -82,9 +127,8 @@ NUITKA_MAY_BE_UNUSED static inline bool DROP_ERROR_OCCURRED(PyThreadState *tstat
82
127
  return false;
83
128
  }
84
129
 
85
- // Python3.12: TODO, fetching into a structure is probably needed.
86
130
  #if PYTHON_VERSION < 0x3c0
87
- // Fetch the current error into object variables.
131
+ // Fetch the current error into object variables, transfers reference coming from tstate ownership
88
132
  NUITKA_MAY_BE_UNUSED static void FETCH_ERROR_OCCURRED(PyThreadState *tstate, PyObject **exception_type,
89
133
  PyObject **exception_value,
90
134
  PyTracebackObject **exception_traceback) {
@@ -300,7 +344,7 @@ NUITKA_MAY_BE_UNUSED inline static void SET_CURRENT_EXCEPTION(PyThreadState *tst
300
344
  #endif
301
345
 
302
346
  #if _NUITKA_MAINTAIN_SYS_EXC_VARS
303
- // Set sys attributes in the fastest possible way.
347
+ // Set sys attributes in the fastest possible way, spell-checker: ignore sysdict
304
348
  PyObject *sys_dict = tstate->interp->sysdict;
305
349
  CHECK_OBJECT(sys_dict);
306
350
 
@@ -323,7 +367,7 @@ NUITKA_MAY_BE_UNUSED inline static void SET_CURRENT_EXCEPTION(PyThreadState *tst
323
367
  }
324
368
 
325
369
  // Helper that sets the current thread exception, and has no reference passed.
326
- // Similar to PyErr_SetNone.
370
+ // Similar to "PyErr_SetNone".
327
371
  NUITKA_MAY_BE_UNUSED inline static void SET_CURRENT_EXCEPTION_TYPE0(PyThreadState *tstate, PyObject *exception_type) {
328
372
  CHECK_OBJECT(exception_type);
329
373
 
@@ -347,9 +391,12 @@ NUITKA_MAY_BE_UNUSED inline static void SET_CURRENT_EXCEPTION_TYPE0(PyThreadStat
347
391
  Py_XDECREF(old_exception_traceback);
348
392
  #else
349
393
  PyObject *old_exception = tstate->current_exception;
350
-
351
- tstate->current_exception = exception_type;
352
- Py_INCREF(exception_type);
394
+ ASSERT_NORMALIZED_EXCEPTION_VALUE_X(old_exception);
395
+ PyObject *exception_value = NULL;
396
+ NORMALIZE_EXCEPTION(tstate, &exception_type, &exception_value, NULL);
397
+ ASSERT_NORMALIZED_EXCEPTION_VALUE(exception_value);
398
+ tstate->current_exception = exception_value;
399
+ Py_DECREF(exception_type);
353
400
 
354
401
  #if _DEBUG_EXCEPTIONS
355
402
  PRINT_STRING("SET_CURRENT_EXCEPTION_TYPE0:\n");
@@ -363,6 +410,9 @@ NUITKA_MAY_BE_UNUSED inline static void SET_CURRENT_EXCEPTION_TYPE0(PyThreadStat
363
410
  // Same as "PyErr_SetObject" CPython API, use this instead.
364
411
  NUITKA_MAY_BE_UNUSED inline static void
365
412
  SET_CURRENT_EXCEPTION_TYPE0_VALUE0(PyThreadState *tstate, PyObject *exception_type, PyObject *exception_value) {
413
+ CHECK_OBJECT(exception_type);
414
+ CHECK_OBJECT(exception_value);
415
+
366
416
  #if PYTHON_VERSION < 0x3c0
367
417
  PyObject *old_exception_type = tstate->curexc_type;
368
418
  PyObject *old_exception_value = tstate->curexc_value;
@@ -383,8 +433,11 @@ SET_CURRENT_EXCEPTION_TYPE0_VALUE0(PyThreadState *tstate, PyObject *exception_ty
383
433
  Py_XDECREF(old_exception_value);
384
434
  Py_XDECREF(old_exception_traceback);
385
435
  #else
386
- PyObject *old_exception = tstate->current_exception;
436
+ PyObject *old_exception_value = tstate->current_exception;
437
+ ASSERT_NORMALIZED_EXCEPTION_VALUE_X(old_exception_value);
387
438
 
439
+ NORMALIZE_EXCEPTION(tstate, &exception_type, &exception_value, NULL);
440
+ ASSERT_NORMALIZED_EXCEPTION_VALUE(exception_value);
388
441
  tstate->current_exception = exception_value;
389
442
  Py_INCREF(exception_value);
390
443
 
@@ -393,7 +446,7 @@ SET_CURRENT_EXCEPTION_TYPE0_VALUE0(PyThreadState *tstate, PyObject *exception_ty
393
446
  PRINT_CURRENT_EXCEPTION();
394
447
  #endif
395
448
 
396
- Py_XDECREF(old_exception);
449
+ Py_XDECREF(old_exception_value);
397
450
  #endif
398
451
  }
399
452
 
@@ -418,8 +471,11 @@ SET_CURRENT_EXCEPTION_TYPE0_VALUE1(PyThreadState *tstate, PyObject *exception_ty
418
471
  Py_XDECREF(old_exception_value);
419
472
  Py_XDECREF(old_exception_traceback);
420
473
  #else
421
- PyObject *old_exception = tstate->current_exception;
474
+ PyObject *old_exception_value = tstate->current_exception;
475
+ ASSERT_NORMALIZED_EXCEPTION_VALUE_X(old_exception_value);
422
476
 
477
+ NORMALIZE_EXCEPTION(tstate, &exception_type, &exception_value, NULL);
478
+ ASSERT_NORMALIZED_EXCEPTION_VALUE_X(exception_value);
423
479
  tstate->current_exception = exception_value;
424
480
 
425
481
  #if _DEBUG_EXCEPTIONS
@@ -427,7 +483,7 @@ SET_CURRENT_EXCEPTION_TYPE0_VALUE1(PyThreadState *tstate, PyObject *exception_ty
427
483
  PRINT_CURRENT_EXCEPTION();
428
484
  #endif
429
485
 
430
- Py_XDECREF(old_exception);
486
+ Py_XDECREF(old_exception_value);
431
487
  #endif
432
488
  }
433
489
 
@@ -438,6 +494,10 @@ NUITKA_MAY_BE_UNUSED inline static void SET_CURRENT_EXCEPTION_TYPE0_STR(PyThread
438
494
  char const *value) {
439
495
  PyObject *exception_value = Nuitka_String_FromString(value);
440
496
 
497
+ #if PYTHON_VERSION >= 0x3c0
498
+ NORMALIZE_EXCEPTION(tstate, &exception_type, &exception_value, NULL);
499
+ #endif
500
+
441
501
  SET_CURRENT_EXCEPTION_TYPE0_VALUE1(tstate, exception_type, exception_value);
442
502
  }
443
503
 
@@ -526,32 +586,33 @@ NUITKA_MAY_BE_UNUSED static inline void RESTORE_FRAME_EXCEPTION(PyThreadState *t
526
586
 
527
587
  #endif
528
588
 
529
- // Similar to PyException_SetTraceback, only done for Python3.
589
+ // Similar to "PyException_SetTraceback", only done for Python3.
530
590
  #if PYTHON_VERSION < 0x300
531
591
  #define ATTACH_TRACEBACK_TO_EXCEPTION_VALUE(exception_value, exception_tb) ;
532
592
  #else
533
593
  NUITKA_MAY_BE_UNUSED static inline void ATTACH_TRACEBACK_TO_EXCEPTION_VALUE(PyObject *exception_value,
534
594
  PyTracebackObject *exception_tb) {
535
595
  CHECK_OBJECT(exception_value);
536
- CHECK_OBJECT(exception_tb);
596
+ CHECK_OBJECT_X(exception_tb);
537
597
 
538
- if (exception_tb == (PyTracebackObject *)Py_None || exception_tb == NULL) {
539
- return;
598
+ if (exception_tb == (PyTracebackObject *)Py_None) {
599
+ exception_tb = NULL;
540
600
  }
541
601
 
542
602
  assert(PyExceptionInstance_Check(exception_value));
543
- assert(PyTraceBack_Check(exception_tb));
603
+ assert(exception_tb == NULL || PyTraceBack_Check(exception_tb));
544
604
 
545
605
  PyBaseExceptionObject *e = (PyBaseExceptionObject *)exception_value;
546
606
 
547
607
  PyObject *old = e->traceback;
548
- Py_INCREF(exception_tb);
608
+ Py_XINCREF(exception_tb);
549
609
  e->traceback = (PyObject *)exception_tb;
550
610
  Py_XDECREF(old);
551
611
  }
552
612
 
553
613
  // Much like "PyException_GetTraceback", but does not give a reference.
554
614
  NUITKA_MAY_BE_UNUSED static inline PyTracebackObject *GET_EXCEPTION_TRACEBACK(PyObject *exception_value) {
615
+ CHECK_OBJECT(exception_value);
555
616
  assert(PyExceptionInstance_Check(exception_value));
556
617
 
557
618
  PyBaseExceptionObject *exc_object = (PyBaseExceptionObject *)(exception_value);
@@ -559,36 +620,6 @@ NUITKA_MAY_BE_UNUSED static inline PyTracebackObject *GET_EXCEPTION_TRACEBACK(Py
559
620
  }
560
621
  #endif
561
622
 
562
- #if PYTHON_VERSION < 0x3c0
563
- extern void Nuitka_Err_NormalizeException(PyThreadState *tstate, PyObject **exc, PyObject **val,
564
- PyTracebackObject **tb);
565
-
566
- // Normalize an exception.
567
- NUITKA_MAY_BE_UNUSED static inline void NORMALIZE_EXCEPTION(PyThreadState *tstate, PyObject **exception_type,
568
- PyObject **exception_value,
569
- PyTracebackObject **exception_tb) {
570
- #if _DEBUG_EXCEPTIONS
571
- PRINT_STRING("NORMALIZE_EXCEPTION: Enter\n");
572
- PRINT_EXCEPTION(*exception_type, *exception_value, *exception_tb);
573
- #endif
574
- CHECK_OBJECT_X(*exception_type);
575
- CHECK_OBJECT_X(*exception_value);
576
- if (exception_tb) {
577
- CHECK_OBJECT_X(*exception_tb);
578
- }
579
-
580
- // TODO: Often we already know this to be true.
581
- if (*exception_type != Py_None && *exception_type != NULL) {
582
- Nuitka_Err_NormalizeException(tstate, exception_type, exception_value, exception_tb);
583
- }
584
-
585
- #if _DEBUG_EXCEPTIONS
586
- PRINT_STRING("NORMALIZE_EXCEPTION: Leave\n");
587
- PRINT_EXCEPTION(*exception_type, *exception_value, exception_tb ? *exception_tb : NULL);
588
- #endif
589
- }
590
- #endif
591
-
592
623
  // Publish an exception, erasing the values of the variables.
593
624
  NUITKA_MAY_BE_UNUSED static inline void PUBLISH_CURRENT_EXCEPTION(PyThreadState *tstate, PyObject **exception_type,
594
625
  PyObject **exception_value,
@@ -623,6 +654,444 @@ NUITKA_MAY_BE_UNUSED static inline void PUBLISH_CURRENT_EXCEPTION(PyThreadState
623
654
  *exception_tb = NULL;
624
655
  }
625
656
 
657
+ #if PYTHON_VERSION >= 0x300
658
+ // Attach the exception context if necessary.
659
+ NUITKA_MAY_BE_UNUSED static inline void ADD_EXCEPTION_CONTEXT(PyThreadState *tstate, PyObject **exception_type,
660
+ PyObject **exception_value) {
661
+ PyObject *context = EXC_VALUE(tstate);
662
+
663
+ if (context != NULL) {
664
+ NORMALIZE_EXCEPTION(tstate, exception_type, exception_value, NULL);
665
+
666
+ Py_INCREF(context);
667
+ PyException_SetContext(*exception_value, context);
668
+ }
669
+ }
670
+ #endif
671
+
672
+ NUITKA_MAY_BE_UNUSED static bool EXCEPTION_MATCH_BOOL_SINGLE(PyThreadState *tstate, PyObject *exception_value,
673
+ PyObject *exception_checked);
674
+
675
+ NUITKA_MAY_BE_UNUSED static bool _CHECK_AND_CLEAR_EXCEPTION_OCCURRED(PyThreadState *tstate, PyObject *exception_type) {
676
+ #if PYTHON_VERSION < 0x3c0
677
+ PyObject *exception_current = tstate->curexc_type;
678
+ #else
679
+ PyObject *exception_current = tstate->current_exception;
680
+ ASSERT_NORMALIZED_EXCEPTION_VALUE_X(exception_current);
681
+ #endif
682
+ if (exception_current == NULL) {
683
+ return true;
684
+ } else if (EXCEPTION_MATCH_BOOL_SINGLE(tstate, exception_current, exception_type)) {
685
+ CHECK_OBJECT(exception_current);
686
+
687
+ #if PYTHON_VERSION < 0x3c0
688
+ // Clear the exception first, we believe we know it doesn't have side effects.
689
+ Py_DECREF(exception_current);
690
+ tstate->curexc_type = NULL;
691
+
692
+ PyObject *old_value = tstate->curexc_value;
693
+ PyObject *old_tb = tstate->curexc_traceback;
694
+
695
+ tstate->curexc_value = NULL;
696
+ tstate->curexc_traceback = NULL;
697
+
698
+ Py_XDECREF(old_value);
699
+ Py_XDECREF(old_tb);
700
+ #else
701
+ tstate->current_exception = NULL;
702
+ Py_DECREF(exception_current);
703
+ #endif
704
+
705
+ return true;
706
+ } else {
707
+ return false;
708
+ }
709
+ }
710
+
711
+ /* Special helper that checks for StopIteration and if so clears it, only
712
+ indicating if it was set in the return value.
713
+
714
+ Equivalent to if(PyErr_ExceptionMatches(PyExc_StopIteration) PyErr_Clear();
715
+
716
+ If error is raised by built-in function next() and an iterator’s __next__()
717
+ method to signal that there are no further items produced by the iterator then
718
+ it resets the TSTATE to NULL and returns True else return False
719
+
720
+ */
721
+ NUITKA_MAY_BE_UNUSED static bool CHECK_AND_CLEAR_STOP_ITERATION_OCCURRED(PyThreadState *tstate) {
722
+ return _CHECK_AND_CLEAR_EXCEPTION_OCCURRED(tstate, PyExc_StopIteration);
723
+ }
724
+
725
+ /* Special helper that checks for KeyError and if so clears it, only
726
+ indicating if it was set in the return value.
727
+
728
+ Equivalent to if(PyErr_ExceptionMatches(PyExc_KeyError) PyErr_Clear();
729
+
730
+ */
731
+ NUITKA_MAY_BE_UNUSED static bool CHECK_AND_CLEAR_KEY_ERROR_OCCURRED(PyThreadState *tstate) {
732
+ return _CHECK_AND_CLEAR_EXCEPTION_OCCURRED(tstate, PyExc_KeyError);
733
+ }
734
+
735
+ NUITKA_MAY_BE_UNUSED static bool CHECK_AND_CLEAR_ATTRIBUTE_ERROR_OCCURRED(PyThreadState *tstate) {
736
+ return _CHECK_AND_CLEAR_EXCEPTION_OCCURRED(tstate, PyExc_AttributeError);
737
+ }
738
+
739
+ // Format a NameError exception for a variable name, chains with existing exception.
740
+ extern void SET_CURRENT_EXCEPTION_NAME_ERROR(PyThreadState *tstate, PyObject *variable_name);
741
+
742
+ #if PYTHON_VERSION < 0x340
743
+ // Same as SET_CURRENT_EXCEPTION_NAME_ERROR with different wording, sometimes for Python2.
744
+ extern void SET_CURRENT_EXCEPTION_GLOBAL_NAME_ERROR(PyThreadState *tstate, PyObject *variable_name);
745
+ #endif
746
+
747
+ // Format a UnboundLocalError exception for a variable name.
748
+ extern void FORMAT_UNBOUND_LOCAL_ERROR(PyObject **exception_type, PyObject **exception_value, PyObject *variable_name);
749
+
750
+ extern void FORMAT_UNBOUND_CLOSURE_ERROR(PyObject **exception_type, PyObject **exception_value,
751
+ PyObject *variable_name);
752
+
753
+ #if PYTHON_VERSION >= 0x3c0
754
+ NUITKA_MAY_BE_UNUSED static PyObject *MAKE_TUPLE1(PyObject *element1);
755
+
756
+ NUITKA_MAY_BE_UNUSED static PyObject *MAKE_EXCEPTION_FROM_TYPE_ARG0(PyThreadState *tstate, PyObject *type,
757
+ PyObject *arg) {
758
+ PyBaseExceptionObject *self;
759
+
760
+ PyTypeObject *type_object = (PyTypeObject *)type;
761
+
762
+ self = (PyBaseExceptionObject *)(type_object->tp_alloc(type_object, 0));
763
+
764
+ self->dict = NULL;
765
+ self->notes = NULL;
766
+ self->traceback = self->cause = self->context = NULL;
767
+ self->suppress_context = 0;
768
+
769
+ assert(arg != NULL);
770
+
771
+ if (!PyTuple_Check(arg)) {
772
+ self->args = MAKE_TUPLE1(arg);
773
+ } else {
774
+ self->args = Py_NewRef(arg);
775
+ }
776
+
777
+ return (PyObject *)self;
778
+ }
779
+ #else
780
+
781
+ extern PyObject *CALL_FUNCTION_WITH_SINGLE_ARG(PyThreadState *tstate, PyObject *called, PyObject *arg);
782
+
783
+ NUITKA_MAY_BE_UNUSED static PyObject *MAKE_EXCEPTION_FROM_TYPE_ARG0(PyThreadState *tstate, PyObject *type,
784
+ PyObject *arg) {
785
+ return CALL_FUNCTION_WITH_SINGLE_ARG(tstate, type, arg);
786
+ }
787
+
788
+ #endif
789
+
790
+ #if PYTHON_VERSION < 0x3c0
791
+ struct Nuitka_ExceptionPreservationItem {
792
+ PyObject *exception_type;
793
+ PyObject *exception_value;
794
+ PyTracebackObject *exception_tb;
795
+ };
796
+
797
+ // Fetch the current exception into state, transfers reference coming from tstate ownership. Old values are overwritten.
798
+ NUITKA_MAY_BE_UNUSED static void FETCH_ERROR_OCCURRED_STATE(PyThreadState *tstate,
799
+ struct Nuitka_ExceptionPreservationItem *exception_state) {
800
+ FETCH_ERROR_OCCURRED(tstate, &exception_state->exception_type, &exception_state->exception_value,
801
+ &exception_state->exception_tb);
802
+ }
803
+
804
+ // Restore the current exception from state, transfers reference from state to tstate ownership.
805
+ NUITKA_MAY_BE_UNUSED static void
806
+ RESTORE_ERROR_OCCURRED_STATE(PyThreadState *tstate, struct Nuitka_ExceptionPreservationItem *exception_state) {
807
+ RESTORE_ERROR_OCCURRED(tstate, exception_state->exception_type, exception_state->exception_value,
808
+ exception_state->exception_tb);
809
+ }
810
+
811
+ NUITKA_MAY_BE_UNUSED static void
812
+ FETCH_ERROR_OCCURRED_STATE_UNTRACED(PyThreadState *tstate, struct Nuitka_ExceptionPreservationItem *exception_state) {
813
+ FETCH_ERROR_OCCURRED_UNTRACED(tstate, &exception_state->exception_type, &exception_state->exception_value,
814
+ &exception_state->exception_tb);
815
+ }
816
+
817
+ NUITKA_MAY_BE_UNUSED static void
818
+ RESTORE_ERROR_OCCURRED_STATE_UNTRACED(PyThreadState *tstate, struct Nuitka_ExceptionPreservationItem *exception_state) {
819
+ RESTORE_ERROR_OCCURRED_UNTRACED(tstate, exception_state->exception_type, exception_state->exception_value,
820
+ exception_state->exception_tb);
821
+ }
822
+
823
+ NUITKA_MAY_BE_UNUSED static void
824
+ ASSERT_SAME_EXCEPTION_STATE(struct Nuitka_ExceptionPreservationItem const *exception_state1,
825
+ struct Nuitka_ExceptionPreservationItem const *exception_state2) {
826
+ assert(exception_state1->exception_type == exception_state2->exception_type);
827
+ assert(exception_state1->exception_value == exception_state2->exception_value);
828
+ assert(exception_state1->exception_tb == exception_state2->exception_tb);
829
+ }
830
+
831
+ NUITKA_MAY_BE_UNUSED static void
832
+ ASSERT_EMPTY_EXCEPTION_STATE(struct Nuitka_ExceptionPreservationItem const *exception_state) {
833
+ assert(exception_state->exception_type == NULL);
834
+ assert(exception_state->exception_value == NULL);
835
+ assert(exception_state->exception_tb == NULL);
836
+ }
837
+
838
+ NUITKA_MAY_BE_UNUSED static void INIT_ERROR_OCCURRED_STATE(struct Nuitka_ExceptionPreservationItem *exception_state) {
839
+ exception_state->exception_type = NULL;
840
+ exception_state->exception_value = NULL;
841
+ exception_state->exception_tb = NULL;
842
+ }
843
+
844
+ NUITKA_MAY_BE_UNUSED static void
845
+ RELEASE_ERROR_OCCURRED_STATE(struct Nuitka_ExceptionPreservationItem *exception_state) {
846
+ CHECK_OBJECT(exception_state->exception_type);
847
+ CHECK_OBJECT_X(exception_state->exception_value);
848
+ CHECK_OBJECT_X(exception_state->exception_tb);
849
+ Py_DECREF(exception_state->exception_type);
850
+ Py_XDECREF(exception_state->exception_value);
851
+ Py_XDECREF(exception_state->exception_tb);
852
+ }
853
+
854
+ NUITKA_MAY_BE_UNUSED static void
855
+ RELEASE_ERROR_OCCURRED_STATE_X(struct Nuitka_ExceptionPreservationItem *exception_state) {
856
+ CHECK_OBJECT_X(exception_state->exception_type);
857
+ CHECK_OBJECT_X(exception_state->exception_value);
858
+ CHECK_OBJECT_X(exception_state->exception_tb);
859
+
860
+ Py_XDECREF(exception_state->exception_type);
861
+ Py_XDECREF(exception_state->exception_value);
862
+ Py_XDECREF(exception_state->exception_tb);
863
+ }
864
+
865
+ NUITKA_MAY_BE_UNUSED static void SET_EXCEPTION_PRESERVATION_STATE_FROM_ARGS(
866
+ PyThreadState *tstate, struct Nuitka_ExceptionPreservationItem *exception_state, PyObject *exception_type,
867
+ PyObject *exception_value, PyTracebackObject *exception_tb) {
868
+ Py_INCREF(exception_type);
869
+ Py_XINCREF(exception_value);
870
+ Py_XINCREF(exception_tb);
871
+
872
+ exception_state->exception_type = exception_type;
873
+ exception_state->exception_value = exception_value;
874
+ exception_state->exception_tb = exception_tb;
875
+ }
876
+
877
+ NUITKA_MAY_BE_UNUSED static void
878
+ ASSIGN_ARGS_FROM_EXCEPTION_PRESERVATION_STATE(struct Nuitka_ExceptionPreservationItem *exception_state,
879
+ PyObject **exception_type, PyObject **exception_value,
880
+ PyTracebackObject **exception_tb) {
881
+
882
+ *exception_type = exception_state->exception_type;
883
+ Py_INCREF(*exception_type);
884
+ *exception_value = exception_state->exception_value;
885
+ Py_XINCREF(*exception_value);
886
+ *exception_tb = exception_state->exception_tb;
887
+ Py_XINCREF(*exception_tb);
888
+ }
889
+
890
+ NUITKA_MAY_BE_UNUSED static PyTracebackObject *
891
+ GET_EXCEPTION_STATE_TRACEBACK(struct Nuitka_ExceptionPreservationItem const *exception_state) {
892
+ return exception_state->exception_tb;
893
+ }
894
+
895
+ // Transfer ownership of the traceback to the exception state.
896
+ NUITKA_MAY_BE_UNUSED static void SET_EXCEPTION_STATE_TRACEBACK(struct Nuitka_ExceptionPreservationItem *exception_state,
897
+ PyTracebackObject *exception_tb) {
898
+ CHECK_OBJECT_X(exception_state->exception_tb);
899
+ CHECK_OBJECT_X(exception_tb);
900
+ Py_XDECREF(exception_state->exception_tb);
901
+ exception_state->exception_tb = exception_tb;
902
+ }
903
+
904
+ NUITKA_MAY_BE_UNUSED static bool HAS_EXCEPTION_STATE(struct Nuitka_ExceptionPreservationItem const *exception_state) {
905
+ return exception_state->exception_type != NULL;
906
+ }
907
+
908
+ NUITKA_MAY_BE_UNUSED static bool
909
+ EXCEPTION_STATE_MATCH_BOOL_SINGLE(PyThreadState *tstate, struct Nuitka_ExceptionPreservationItem *exception_state,
910
+ PyObject *exception_checked) {
911
+ return EXCEPTION_MATCH_BOOL_SINGLE(tstate, exception_state->exception_type, exception_checked);
912
+ }
913
+
914
+ NUITKA_MAY_BE_UNUSED inline static void
915
+ CHECK_EXCEPTION_STATE(struct Nuitka_ExceptionPreservationItem const *exception_state) {
916
+ CHECK_OBJECT(exception_state->exception_type);
917
+ CHECK_OBJECT_X(exception_state->exception_value);
918
+ CHECK_OBJECT_X(exception_state->exception_tb);
919
+ }
920
+
921
+ NUITKA_MAY_BE_UNUSED inline static void
922
+ CHECK_EXCEPTION_STATE_X(struct Nuitka_ExceptionPreservationItem const *exception_state) {
923
+ CHECK_OBJECT_X(exception_state->exception_type);
924
+ CHECK_OBJECT_X(exception_state->exception_value);
925
+ CHECK_OBJECT_X(exception_state->exception_tb);
926
+ }
927
+
928
+ #else
929
+ struct Nuitka_ExceptionPreservationItem {
930
+ PyObject *exception_value;
931
+ };
932
+
933
+ // Fetch the current exception into state, transfers reference coming from tstate ownership. Old value is overwritten.
934
+ NUITKA_MAY_BE_UNUSED static void FETCH_ERROR_OCCURRED_STATE(PyThreadState *tstate,
935
+ struct Nuitka_ExceptionPreservationItem *exception_state) {
936
+ exception_state->exception_value = tstate->current_exception;
937
+ ASSERT_NORMALIZED_EXCEPTION_VALUE_X(exception_state->exception_value);
938
+
939
+ #if _DEBUG_EXCEPTIONS
940
+ PRINT_STRING("FETCH_ERROR_OCCURRED_STATE:\n");
941
+ PRINT_CURRENT_EXCEPTION();
942
+ #endif
943
+
944
+ tstate->current_exception = NULL;
945
+ }
946
+
947
+ NUITKA_MAY_BE_UNUSED static void
948
+ FETCH_ERROR_OCCURRED_STATE_UNTRACED(PyThreadState *tstate, struct Nuitka_ExceptionPreservationItem *exception_state) {
949
+ exception_state->exception_value = tstate->current_exception;
950
+ tstate->current_exception = NULL;
951
+
952
+ ASSERT_NORMALIZED_EXCEPTION_VALUE_X(exception_state->exception_value);
953
+ }
954
+
955
+ NUITKA_MAY_BE_UNUSED static void
956
+ RESTORE_ERROR_OCCURRED_STATE(PyThreadState *tstate, struct Nuitka_ExceptionPreservationItem *exception_state) {
957
+ PyObject *old_exception_value = tstate->current_exception;
958
+ ASSERT_NORMALIZED_EXCEPTION_VALUE_X(old_exception_value);
959
+
960
+ ASSERT_NORMALIZED_EXCEPTION_VALUE_X(exception_state->exception_value);
961
+ tstate->current_exception = exception_state->exception_value;
962
+
963
+ #if _DEBUG_EXCEPTIONS
964
+ PRINT_STRING("RESTORE_ERROR_OCCURRED:\n");
965
+ PRINT_CURRENT_EXCEPTION();
966
+ #endif
967
+
968
+ Py_XDECREF(old_exception_value);
969
+ }
970
+
971
+ NUITKA_MAY_BE_UNUSED static void
972
+ RESTORE_ERROR_OCCURRED_STATE_UNTRACED(PyThreadState *tstate, struct Nuitka_ExceptionPreservationItem *exception_state) {
973
+ PyObject *old_exception_value = tstate->current_exception;
974
+ ASSERT_NORMALIZED_EXCEPTION_VALUE_X(old_exception_value);
975
+
976
+ ASSERT_NORMALIZED_EXCEPTION_VALUE_X(exception_state->exception_value);
977
+ tstate->current_exception = exception_state->exception_value;
978
+
979
+ Py_XDECREF(old_exception_value);
980
+ }
981
+
982
+ NUITKA_MAY_BE_UNUSED static void
983
+ ASSERT_SAME_EXCEPTION_STATE(struct Nuitka_ExceptionPreservationItem *exception_state1,
984
+ struct Nuitka_ExceptionPreservationItem *exception_state2) {
985
+ assert(exception_state1->exception_value == exception_state2->exception_value);
986
+ }
987
+
988
+ NUITKA_MAY_BE_UNUSED static void
989
+ ASSERT_EMPTY_EXCEPTION_STATE(struct Nuitka_ExceptionPreservationItem const *exception_state) {
990
+ assert(exception_state->exception_value == NULL);
991
+ }
992
+
993
+ NUITKA_MAY_BE_UNUSED static void INIT_ERROR_OCCURRED_STATE(struct Nuitka_ExceptionPreservationItem *exception_state) {
994
+ exception_state->exception_value = NULL;
995
+ }
996
+
997
+ NUITKA_MAY_BE_UNUSED static void
998
+ RELEASE_ERROR_OCCURRED_STATE(struct Nuitka_ExceptionPreservationItem *exception_state) {
999
+ CHECK_OBJECT(exception_state->exception_value);
1000
+ Py_DECREF(exception_state->exception_value);
1001
+ }
1002
+
1003
+ NUITKA_MAY_BE_UNUSED static void
1004
+ RELEASE_ERROR_OCCURRED_STATE_X(struct Nuitka_ExceptionPreservationItem *exception_state) {
1005
+ CHECK_OBJECT_X(exception_state->exception_value);
1006
+ Py_XDECREF(exception_state->exception_value);
1007
+ }
1008
+
1009
+ NUITKA_MAY_BE_UNUSED static void SET_EXCEPTION_PRESERVATION_STATE_FROM_ARGS(
1010
+ PyThreadState *tstate, struct Nuitka_ExceptionPreservationItem *exception_state, PyObject *exception_type,
1011
+ PyObject *exception_value, PyTracebackObject *exception_tb) {
1012
+
1013
+ Py_XINCREF(exception_type);
1014
+ Py_XINCREF(exception_value);
1015
+ Py_XINCREF(exception_tb);
1016
+
1017
+ NORMALIZE_EXCEPTION(tstate, &exception_type, &exception_value, &exception_tb);
1018
+ ASSERT_NORMALIZED_EXCEPTION_VALUE(exception_value);
1019
+
1020
+ exception_state->exception_value = exception_value;
1021
+ Py_INCREF(exception_value);
1022
+
1023
+ ATTACH_TRACEBACK_TO_EXCEPTION_VALUE(exception_value, exception_tb);
1024
+
1025
+ Py_XDECREF(exception_type);
1026
+ Py_XDECREF(exception_value);
1027
+ Py_XDECREF(exception_tb);
1028
+ }
1029
+
1030
+ NUITKA_MAY_BE_UNUSED static void
1031
+ ASSIGN_ARGS_FROM_EXCEPTION_PRESERVATION_STATE(struct Nuitka_ExceptionPreservationItem *exception_state,
1032
+ PyObject **exception_type, PyObject **exception_value,
1033
+ PyTracebackObject **exception_tb) {
1034
+
1035
+ *exception_value = exception_state->exception_value;
1036
+
1037
+ if (*exception_value) {
1038
+ Py_INCREF(*exception_value);
1039
+
1040
+ *exception_type = (PyObject *)PyExceptionInstance_Class(*exception_value);
1041
+ Py_INCREF(*exception_type);
1042
+ *exception_tb = GET_EXCEPTION_TRACEBACK(*exception_value);
1043
+ Py_XINCREF(*exception_tb);
1044
+ } else {
1045
+ *exception_type = NULL;
1046
+ *exception_tb = NULL;
1047
+ }
1048
+ }
1049
+
1050
+ NUITKA_MAY_BE_UNUSED static PyTracebackObject *
1051
+ GET_EXCEPTION_STATE_TRACEBACK(struct Nuitka_ExceptionPreservationItem *exception_state) {
1052
+ return GET_EXCEPTION_TRACEBACK(exception_state->exception_value);
1053
+ }
1054
+
1055
+ // Transfer ownership of the traceback to the exception state.
1056
+ NUITKA_MAY_BE_UNUSED static void SET_EXCEPTION_STATE_TRACEBACK(struct Nuitka_ExceptionPreservationItem *exception_state,
1057
+ PyTracebackObject *exception_tb) {
1058
+ ATTACH_TRACEBACK_TO_EXCEPTION_VALUE(exception_state->exception_value, exception_tb);
1059
+ Py_XDECREF(exception_tb);
1060
+ CHECK_OBJECT_X(exception_tb);
1061
+ }
1062
+
1063
+ NUITKA_MAY_BE_UNUSED static bool HAS_EXCEPTION_STATE(struct Nuitka_ExceptionPreservationItem const *exception_state) {
1064
+ return exception_state->exception_value != NULL;
1065
+ }
1066
+
1067
+ NUITKA_MAY_BE_UNUSED static bool
1068
+ EXCEPTION_STATE_MATCH_BOOL_SINGLE(PyThreadState *tstate, struct Nuitka_ExceptionPreservationItem const *exception_state,
1069
+ PyObject *exception_checked) {
1070
+ return EXCEPTION_MATCH_BOOL_SINGLE(tstate, exception_state->exception_value, exception_checked);
1071
+ }
1072
+
1073
+ NUITKA_MAY_BE_UNUSED inline static void
1074
+ CHECK_EXCEPTION_STATE(struct Nuitka_ExceptionPreservationItem const *exception_state) {
1075
+ ASSERT_NORMALIZED_EXCEPTION_VALUE(exception_state->exception_value);
1076
+ }
1077
+
1078
+ NUITKA_MAY_BE_UNUSED inline static void
1079
+ CHECK_EXCEPTION_STATE_X(struct Nuitka_ExceptionPreservationItem const *exception_state) {
1080
+ ASSERT_NORMALIZED_EXCEPTION_VALUE_X(exception_state->exception_value);
1081
+ }
1082
+
1083
+ #endif
1084
+
1085
+ NUITKA_MAY_BE_UNUSED inline static void
1086
+ SET_EXCEPTION_PRESERVATION_STATE_FROM_TYPE0_STR(PyThreadState *tstate,
1087
+ struct Nuitka_ExceptionPreservationItem *exception_state,
1088
+ PyObject *exception_type, char const *value) {
1089
+ PyObject *exception_value = Nuitka_String_FromString(value);
1090
+
1091
+ SET_EXCEPTION_PRESERVATION_STATE_FROM_ARGS(tstate, exception_state, exception_type, exception_value, NULL);
1092
+ Py_DECREF(exception_value);
1093
+ }
1094
+
626
1095
  NUITKA_MAY_BE_UNUSED static bool EXCEPTION_MATCH_GENERATOR(PyThreadState *tstate, PyObject *exception_value) {
627
1096
  CHECK_OBJECT(exception_value);
628
1097
 
@@ -638,9 +1107,8 @@ NUITKA_MAY_BE_UNUSED static bool EXCEPTION_MATCH_GENERATOR(PyThreadState *tstate
638
1107
 
639
1108
  if (PyExceptionClass_Check(exception_value)) {
640
1109
  // Save the current exception, if any, we must preserve it.
641
- PyObject *save_exception_type, *save_exception_value;
642
- PyTracebackObject *save_exception_tb;
643
- FETCH_ERROR_OCCURRED(tstate, &save_exception_type, &save_exception_value, &save_exception_tb);
1110
+ struct Nuitka_ExceptionPreservationItem saved_exception_state;
1111
+ FETCH_ERROR_OCCURRED_STATE(tstate, &saved_exception_state);
644
1112
 
645
1113
  int res = PyObject_IsSubclass(exception_value, PyExc_GeneratorExit);
646
1114
 
@@ -660,7 +1128,7 @@ NUITKA_MAY_BE_UNUSED static bool EXCEPTION_MATCH_GENERATOR(PyThreadState *tstate
660
1128
  PyErr_WriteUnraisable(exception_value);
661
1129
  }
662
1130
 
663
- RESTORE_ERROR_OCCURRED(tstate, save_exception_type, save_exception_value, save_exception_tb);
1131
+ RESTORE_ERROR_OCCURRED_STATE(tstate, &saved_exception_state);
664
1132
 
665
1133
  return res == 1;
666
1134
  }
@@ -685,9 +1153,8 @@ NUITKA_MAY_BE_UNUSED static bool EXCEPTION_MATCH_BOOL_SINGLE(PyThreadState *tsta
685
1153
 
686
1154
  if (PyExceptionClass_Check(exception_value)) {
687
1155
  // Save the current exception, if any, we must preserve it.
688
- PyObject *save_exception_type, *save_exception_value;
689
- PyTracebackObject *save_exception_tb;
690
- FETCH_ERROR_OCCURRED(tstate, &save_exception_type, &save_exception_value, &save_exception_tb);
1156
+ struct Nuitka_ExceptionPreservationItem saved_exception_state;
1157
+ FETCH_ERROR_OCCURRED_STATE(tstate, &saved_exception_state);
691
1158
 
692
1159
  int res = PyObject_IsSubclass(exception_value, exception_checked);
693
1160
 
@@ -696,7 +1163,7 @@ NUITKA_MAY_BE_UNUSED static bool EXCEPTION_MATCH_BOOL_SINGLE(PyThreadState *tsta
696
1163
  PyErr_WriteUnraisable(exception_value);
697
1164
  }
698
1165
 
699
- RESTORE_ERROR_OCCURRED(tstate, save_exception_type, save_exception_value, save_exception_tb);
1166
+ RESTORE_ERROR_OCCURRED_STATE(tstate, &saved_exception_state);
700
1167
 
701
1168
  return res == 1;
702
1169
  }
@@ -720,9 +1187,8 @@ NUITKA_MAY_BE_UNUSED static inline int _EXCEPTION_MATCH_BOOL(PyThreadState *tsta
720
1187
  #if PYTHON_VERSION < 0x300
721
1188
  if (PyExceptionClass_Check(exception_class) && PyExceptionClass_Check(exception_checked)) {
722
1189
  // Save the current exception, if any, we must preserve it.
723
- PyObject *save_exception_type, *save_exception_value;
724
- PyTracebackObject *save_exception_tb;
725
- FETCH_ERROR_OCCURRED(tstate, &save_exception_type, &save_exception_value, &save_exception_tb);
1190
+ struct Nuitka_ExceptionPreservationItem saved_exception_state;
1191
+ FETCH_ERROR_OCCURRED_STATE(tstate, &saved_exception_state);
726
1192
 
727
1193
  // Avoid recursion limit being exceeded just then
728
1194
  int recursion_limit = Py_GetRecursionLimit();
@@ -740,7 +1206,7 @@ NUITKA_MAY_BE_UNUSED static inline int _EXCEPTION_MATCH_BOOL(PyThreadState *tsta
740
1206
  res = 0;
741
1207
  }
742
1208
 
743
- RESTORE_ERROR_OCCURRED(tstate, save_exception_type, save_exception_value, save_exception_tb);
1209
+ RESTORE_ERROR_OCCURRED_STATE(tstate, &saved_exception_state);
744
1210
 
745
1211
  return res;
746
1212
  } else {
@@ -804,124 +1270,33 @@ NUITKA_MAY_BE_UNUSED static inline int EXCEPTION_MATCH_BOOL(PyThreadState *tstat
804
1270
  }
805
1271
  }
806
1272
 
807
- #if PYTHON_VERSION >= 0x300
808
- // Attach the exception context if necessary.
809
- NUITKA_MAY_BE_UNUSED static inline void ADD_EXCEPTION_CONTEXT(PyThreadState *tstate, PyObject **exception_type,
810
- PyObject **exception_value) {
811
- PyObject *context = EXC_VALUE(tstate);
812
-
813
- if (context != NULL) {
814
- NORMALIZE_EXCEPTION(tstate, exception_type, exception_value, NULL);
815
-
816
- Py_INCREF(context);
817
- PyException_SetContext(*exception_value, context);
818
- }
819
- }
820
- #endif
821
-
822
- NUITKA_MAY_BE_UNUSED static bool _CHECK_AND_CLEAR_EXCEPTION_OCCURRED(PyThreadState *tstate, PyObject *exception_type) {
823
- #if PYTHON_VERSION < 0x3c0
824
- PyObject *exception_current = tstate->curexc_type;
825
- #else
826
- PyObject *exception_current = tstate->current_exception;
827
-
828
- #endif
829
- if (exception_current == NULL) {
830
- return true;
831
- } else if (EXCEPTION_MATCH_BOOL_SINGLE(tstate, exception_current, exception_type)) {
832
- // Clear the exception first, we believe we know it doesn't have side effects.
833
- Py_DECREF(exception_current);
834
-
835
- #if PYTHON_VERSION < 0x3c0
836
- tstate->curexc_type = NULL;
837
-
838
- PyObject *old_value = tstate->curexc_value;
839
- PyObject *old_tb = tstate->curexc_traceback;
840
-
841
- tstate->curexc_value = NULL;
842
- tstate->curexc_traceback = NULL;
843
-
844
- Py_XDECREF(old_value);
845
- Py_XDECREF(old_tb);
846
- #else
847
- tstate->current_exception = NULL;
848
- #endif
849
-
850
- return true;
851
- } else {
852
- return false;
853
- }
854
- }
855
-
856
- /* Special helper that checks for StopIteration and if so clears it, only
857
- indicating if it was set in the return value.
858
-
859
- Equivalent to if(PyErr_ExceptionMatches(PyExc_StopIteration) PyErr_Clear();
860
-
861
- If error is raised by built-in function next() and an iterator’s __next__()
862
- method to signal that there are no further items produced by the iterator then
863
- it resets the TSTATE to NULL and returns True else return False
864
-
865
- */
866
- NUITKA_MAY_BE_UNUSED static bool CHECK_AND_CLEAR_STOP_ITERATION_OCCURRED(PyThreadState *tstate) {
867
- return _CHECK_AND_CLEAR_EXCEPTION_OCCURRED(tstate, PyExc_StopIteration);
868
- }
869
-
870
- /* Special helper that checks for KeyError and if so clears it, only
871
- indicating if it was set in the return value.
1273
+ #if PYTHON_VERSION >= 0x3c0
872
1274
 
873
- Equivalent to if(PyErr_ExceptionMatches(PyExc_KeyError) PyErr_Clear();
1275
+ // Python3.12: TODO: Must get rid of those by generating code with exception_state
1276
+ NUITKA_MAY_BE_UNUSED static void FETCH_ERROR_OCCURRED(PyThreadState *tstate, PyObject **exception_type,
1277
+ PyObject **exception_value,
1278
+ PyTracebackObject **exception_traceback) {
874
1279
 
875
- */
876
- NUITKA_MAY_BE_UNUSED static bool CHECK_AND_CLEAR_KEY_ERROR_OCCURRED(PyThreadState *tstate) {
877
- return _CHECK_AND_CLEAR_EXCEPTION_OCCURRED(tstate, PyExc_KeyError);
1280
+ struct Nuitka_ExceptionPreservationItem exception_state;
1281
+ FETCH_ERROR_OCCURRED_STATE(tstate, &exception_state);
1282
+ ASSIGN_ARGS_FROM_EXCEPTION_PRESERVATION_STATE(&exception_state, exception_type, exception_value,
1283
+ exception_traceback);
1284
+ RELEASE_ERROR_OCCURRED_STATE_X(&exception_state);
878
1285
  }
879
1286
 
880
- NUITKA_MAY_BE_UNUSED static bool CHECK_AND_CLEAR_ATTRIBUTE_ERROR_OCCURRED(PyThreadState *tstate) {
881
- return _CHECK_AND_CLEAR_EXCEPTION_OCCURRED(tstate, PyExc_AttributeError);
1287
+ NUITKA_MAY_BE_UNUSED static void RESTORE_ERROR_OCCURRED(PyThreadState *tstate, PyObject *exception_type,
1288
+ PyObject *exception_value, PyTracebackObject *exception_tb) {
1289
+ struct Nuitka_ExceptionPreservationItem exception_state;
1290
+ SET_EXCEPTION_PRESERVATION_STATE_FROM_ARGS(tstate, &exception_state, exception_type, exception_value, exception_tb);
1291
+ Py_XDECREF(exception_type);
1292
+ Py_XDECREF(exception_value);
1293
+ Py_XDECREF(exception_tb);
1294
+
1295
+ RESTORE_ERROR_OCCURRED_STATE(tstate, &exception_state);
882
1296
  }
883
1297
 
884
- // Format a NameError exception for a variable name.
885
- extern void FORMAT_NAME_ERROR(PyObject **exception_type, PyObject **exception_value, PyObject *variable_name);
886
-
887
- #if PYTHON_VERSION < 0x340
888
- // Same as FORMAT_NAME_ERROR with different wording, sometimes used for older Python version.
889
- extern void FORMAT_GLOBAL_NAME_ERROR(PyObject **exception_type, PyObject **exception_value, PyObject *variable_name);
890
- #endif
891
-
892
- // Format a UnboundLocalError exception for a variable name.
893
- extern void FORMAT_UNBOUND_LOCAL_ERROR(PyObject **exception_type, PyObject **exception_value, PyObject *variable_name);
894
-
895
- extern void FORMAT_UNBOUND_CLOSURE_ERROR(PyObject **exception_type, PyObject **exception_value,
896
- PyObject *variable_name);
897
-
898
1298
  #endif
899
1299
 
900
- #if PYTHON_VERSION >= 0x3c0
901
- NUITKA_MAY_BE_UNUSED static PyObject *MAKE_TUPLE1(PyObject *element1);
902
-
903
- static PyObject *_MAKE_EXCEPTION_FROM_TYPE_ARG0(PyObject *type, PyObject *arg) {
904
- PyBaseExceptionObject *self;
905
-
906
- PyTypeObject *type_object = (PyTypeObject *)type;
907
-
908
- self = (PyBaseExceptionObject *)(type_object->tp_alloc(type_object, 0));
909
-
910
- self->dict = NULL;
911
- self->notes = NULL;
912
- self->traceback = self->cause = self->context = NULL;
913
- self->suppress_context = 0;
914
-
915
- assert(arg != NULL);
916
-
917
- if (!PyTuple_Check(arg)) {
918
- self->args = MAKE_TUPLE1(arg);
919
- } else {
920
- self->args = Py_NewRef(arg);
921
- }
922
-
923
- return (PyObject *)self;
924
- }
925
1300
  #endif
926
1301
 
927
1302
  // Part of "Nuitka", an optimizing Python compiler that is compatible and