[Python-checkins] bpo-46417: Factorize _PyExc_InitTypes() code (GH-30804)
vstinner
webhook-mailer at python.org
Sat Jan 22 15:49:12 EST 2022
https://github.com/python/cpython/commit/f1bcdeaca6e912a2bec1fbcff76cc49e7f761d38
commit: f1bcdeaca6e912a2bec1fbcff76cc49e7f761d38
branch: main
author: Victor Stinner <vstinner at python.org>
committer: vstinner <vstinner at python.org>
date: 2022-01-22T21:48:56+01:00
summary:
bpo-46417: Factorize _PyExc_InitTypes() code (GH-30804)
Add 'static_exceptions' list to factorize code between
_PyExc_InitTypes() and _PyBuiltins_AddExceptions().
_PyExc_InitTypes() does nothing if it's not the main interpreter.
Sort exceptions in Lib/test/exception_hierarchy.txt.
files:
M Include/internal/pycore_exceptions.h
M Include/internal/pycore_pylifecycle.h
M Lib/test/exception_hierarchy.txt
M Objects/exceptions.c
M Python/pylifecycle.c
diff --git a/Include/internal/pycore_exceptions.h b/Include/internal/pycore_exceptions.h
index 1651966dad936..4a9df70913199 100644
--- a/Include/internal/pycore_exceptions.h
+++ b/Include/internal/pycore_exceptions.h
@@ -13,7 +13,7 @@ extern "C" {
extern PyStatus _PyExc_InitState(PyInterpreterState *);
extern PyStatus _PyExc_InitGlobalObjects(PyInterpreterState *);
-extern PyStatus _PyExc_InitTypes(PyInterpreterState *);
+extern int _PyExc_InitTypes(PyInterpreterState *);
extern void _PyExc_Fini(PyInterpreterState *);
diff --git a/Include/internal/pycore_pylifecycle.h b/Include/internal/pycore_pylifecycle.h
index dfa8fd6bd0d28..35e560b42ee0a 100644
--- a/Include/internal/pycore_pylifecycle.h
+++ b/Include/internal/pycore_pylifecycle.h
@@ -59,7 +59,7 @@ extern PyStatus _PySys_ReadPreinitWarnOptions(PyWideStringList *options);
extern PyStatus _PySys_ReadPreinitXOptions(PyConfig *config);
extern int _PySys_UpdateConfig(PyThreadState *tstate);
extern void _PySys_Fini(PyInterpreterState *interp);
-extern PyStatus _PyBuiltins_AddExceptions(PyObject * bltinmod);
+extern int _PyBuiltins_AddExceptions(PyObject * bltinmod);
extern PyStatus _Py_HashRandomization_Init(const PyConfig *);
extern PyStatus _PyImportZip_Init(PyThreadState *tstate);
diff --git a/Lib/test/exception_hierarchy.txt b/Lib/test/exception_hierarchy.txt
index 5c0bfda373794..1eca123be0fec 100644
--- a/Lib/test/exception_hierarchy.txt
+++ b/Lib/test/exception_hierarchy.txt
@@ -1,12 +1,9 @@
BaseException
- ├── SystemExit
- ├── KeyboardInterrupt
- ├── GeneratorExit
├── BaseExceptionGroup
+ ├── GeneratorExit
+ ├── KeyboardInterrupt
+ ├── SystemExit
└── Exception
- ├── ExceptionGroup [BaseExceptionGroup]
- ├── StopIteration
- ├── StopAsyncIteration
├── ArithmeticError
│ ├── FloatingPointError
│ ├── OverflowError
@@ -15,6 +12,7 @@ BaseException
├── AttributeError
├── BufferError
├── EOFError
+ ├── ExceptionGroup [BaseExceptionGroup]
├── ImportError
│ └── ModuleNotFoundError
├── LookupError
@@ -43,6 +41,8 @@ BaseException
├── RuntimeError
│ ├── NotImplementedError
│ └── RecursionError
+ ├── StopAsyncIteration
+ ├── StopIteration
├── SyntaxError
│ └── IndentationError
│ └── TabError
@@ -54,14 +54,14 @@ BaseException
│ ├── UnicodeEncodeError
│ └── UnicodeTranslateError
└── Warning
+ ├── BytesWarning
├── DeprecationWarning
+ ├── EncodingWarning
+ ├── FutureWarning
+ ├── ImportWarning
├── PendingDeprecationWarning
+ ├── ResourceWarning
├── RuntimeWarning
├── SyntaxWarning
- ├── UserWarning
- ├── FutureWarning
- ├── ImportWarning
├── UnicodeWarning
- ├── BytesWarning
- ├── EncodingWarning
- └── ResourceWarning
+ └── UserWarning
diff --git a/Objects/exceptions.c b/Objects/exceptions.c
index 22a47131aa12c..f8f727c673c02 100644
--- a/Objects/exceptions.c
+++ b/Objects/exceptions.c
@@ -3421,92 +3421,121 @@ SimpleExtendsException(PyExc_Warning, ResourceWarning,
#endif
#endif /* MS_WINDOWS */
-PyStatus
+struct static_exception {
+ PyTypeObject *exc;
+ const char *name;
+};
+
+static struct static_exception static_exceptions[] = {
+#define ITEM(NAME) {&_PyExc_##NAME, #NAME}
+ // Level 1
+ ITEM(BaseException),
+
+ // Level 2: BaseException subclasses
+ ITEM(BaseExceptionGroup),
+ ITEM(Exception),
+ ITEM(GeneratorExit),
+ ITEM(KeyboardInterrupt),
+ ITEM(SystemExit),
+
+ // Level 3: Exception(BaseException) subclasses
+ ITEM(ArithmeticError),
+ ITEM(AssertionError),
+ ITEM(AttributeError),
+ ITEM(BufferError),
+ ITEM(EOFError),
+ //ITEM(ExceptionGroup),
+ ITEM(ImportError),
+ ITEM(LookupError),
+ ITEM(MemoryError),
+ ITEM(NameError),
+ ITEM(OSError),
+ ITEM(ReferenceError),
+ ITEM(RuntimeError),
+ ITEM(StopAsyncIteration),
+ ITEM(StopIteration),
+ ITEM(SyntaxError),
+ ITEM(SystemError),
+ ITEM(TypeError),
+ ITEM(ValueError),
+ ITEM(Warning),
+
+ // Level 4: ArithmeticError(Exception) subclasses
+ ITEM(FloatingPointError),
+ ITEM(OverflowError),
+ ITEM(ZeroDivisionError),
+
+ // Level 4: Warning(Exception) subclasses
+ ITEM(BytesWarning),
+ ITEM(DeprecationWarning),
+ ITEM(EncodingWarning),
+ ITEM(FutureWarning),
+ ITEM(ImportWarning),
+ ITEM(PendingDeprecationWarning),
+ ITEM(ResourceWarning),
+ ITEM(RuntimeWarning),
+ ITEM(SyntaxWarning),
+ ITEM(UnicodeWarning),
+ ITEM(UserWarning),
+
+ // Level 4: OSError(Exception) subclasses
+ ITEM(BlockingIOError),
+ ITEM(ChildProcessError),
+ ITEM(ConnectionError),
+ ITEM(FileExistsError),
+ ITEM(FileNotFoundError),
+ ITEM(InterruptedError),
+ ITEM(IsADirectoryError),
+ ITEM(NotADirectoryError),
+ ITEM(PermissionError),
+ ITEM(ProcessLookupError),
+ ITEM(TimeoutError),
+
+ // Level 4: Other subclasses
+ ITEM(IndentationError), // base: SyntaxError(Exception)
+ ITEM(IndexError), // base: LookupError(Exception)
+ ITEM(KeyError), // base: LookupError(Exception)
+ ITEM(ModuleNotFoundError), // base: ImportError(Exception)
+ ITEM(NotImplementedError), // base: RuntimeError(Exception)
+ ITEM(RecursionError), // base: RuntimeError(Exception)
+ ITEM(UnboundLocalError), // base: NameError(Exception)
+ ITEM(UnicodeError), // base: ValueError(Exception)
+
+ // Level 5: ConnectionError(OSError) subclasses
+ ITEM(BrokenPipeError),
+ ITEM(ConnectionAbortedError),
+ ITEM(ConnectionRefusedError),
+ ITEM(ConnectionResetError),
+
+ // Level 5: IndentationError(SyntaxError) subclasses
+ ITEM(TabError), // base: IndentationError
+
+ // Level 5: UnicodeError(ValueError) subclasses
+ ITEM(UnicodeDecodeError),
+ ITEM(UnicodeEncodeError),
+ ITEM(UnicodeTranslateError),
+#undef ITEM
+};
+
+
+int
_PyExc_InitTypes(PyInterpreterState *interp)
{
-#define PRE_INIT(TYPE) \
- if (!(_PyExc_ ## TYPE.tp_flags & Py_TPFLAGS_READY)) { \
- if (PyType_Ready(&_PyExc_ ## TYPE) < 0) { \
- return _PyStatus_ERR("exceptions bootstrapping error."); \
- } \
- Py_INCREF(PyExc_ ## TYPE); \
+ if (!_Py_IsMainInterpreter(interp)) {
+ return 0;
}
- PRE_INIT(BaseException);
- PRE_INIT(BaseExceptionGroup);
- PRE_INIT(Exception);
- PRE_INIT(TypeError);
- PRE_INIT(StopAsyncIteration);
- PRE_INIT(StopIteration);
- PRE_INIT(GeneratorExit);
- PRE_INIT(SystemExit);
- PRE_INIT(KeyboardInterrupt);
- PRE_INIT(ImportError);
- PRE_INIT(ModuleNotFoundError);
- PRE_INIT(OSError);
- PRE_INIT(EOFError);
- PRE_INIT(RuntimeError);
- PRE_INIT(RecursionError);
- PRE_INIT(NotImplementedError);
- PRE_INIT(NameError);
- PRE_INIT(UnboundLocalError);
- PRE_INIT(AttributeError);
- PRE_INIT(SyntaxError);
- PRE_INIT(IndentationError);
- PRE_INIT(TabError);
- PRE_INIT(LookupError);
- PRE_INIT(IndexError);
- PRE_INIT(KeyError);
- PRE_INIT(ValueError);
- PRE_INIT(UnicodeError);
- PRE_INIT(UnicodeEncodeError);
- PRE_INIT(UnicodeDecodeError);
- PRE_INIT(UnicodeTranslateError);
- PRE_INIT(AssertionError);
- PRE_INIT(ArithmeticError);
- PRE_INIT(FloatingPointError);
- PRE_INIT(OverflowError);
- PRE_INIT(ZeroDivisionError);
- PRE_INIT(SystemError);
- PRE_INIT(ReferenceError);
- PRE_INIT(MemoryError);
- PRE_INIT(BufferError);
- PRE_INIT(Warning);
- PRE_INIT(UserWarning);
- PRE_INIT(EncodingWarning);
- PRE_INIT(DeprecationWarning);
- PRE_INIT(PendingDeprecationWarning);
- PRE_INIT(SyntaxWarning);
- PRE_INIT(RuntimeWarning);
- PRE_INIT(FutureWarning);
- PRE_INIT(ImportWarning);
- PRE_INIT(UnicodeWarning);
- PRE_INIT(BytesWarning);
- PRE_INIT(ResourceWarning);
-
- /* OSError subclasses */
- PRE_INIT(ConnectionError);
-
- PRE_INIT(BlockingIOError);
- PRE_INIT(BrokenPipeError);
- PRE_INIT(ChildProcessError);
- PRE_INIT(ConnectionAbortedError);
- PRE_INIT(ConnectionRefusedError);
- PRE_INIT(ConnectionResetError);
- PRE_INIT(FileExistsError);
- PRE_INIT(FileNotFoundError);
- PRE_INIT(IsADirectoryError);
- PRE_INIT(NotADirectoryError);
- PRE_INIT(InterruptedError);
- PRE_INIT(PermissionError);
- PRE_INIT(ProcessLookupError);
- PRE_INIT(TimeoutError);
+ for (size_t i=0; i < Py_ARRAY_LENGTH(static_exceptions); i++) {
+ PyTypeObject *exc = static_exceptions[i].exc;
- return _PyStatus_OK();
-
-#undef PRE_INIT
+ if (PyType_Ready(exc) < 0) {
+ return -1;
+ }
+ }
+ return 0;
}
+
PyStatus
_PyExc_InitGlobalObjects(PyInterpreterState *interp)
{
@@ -3569,12 +3598,28 @@ _PyExc_InitState(PyInterpreterState *interp)
/* Add exception types to the builtins module */
-PyStatus
+int
_PyBuiltins_AddExceptions(PyObject *bltinmod)
{
-#define POST_INIT(TYPE) \
- if (PyDict_SetItemString(bdict, # TYPE, PyExc_ ## TYPE)) { \
- return _PyStatus_ERR("Module dictionary insertion problem."); \
+ PyObject *mod_dict = PyModule_GetDict(bltinmod);
+ if (mod_dict == NULL) {
+ return -1;
+ }
+
+ for (size_t i=0; i < Py_ARRAY_LENGTH(static_exceptions); i++) {
+ struct static_exception item = static_exceptions[i];
+
+ if (PyDict_SetItemString(mod_dict, item.name, (PyObject*)item.exc)) {
+ return -1;
+ }
+ }
+
+ PyObject *PyExc_ExceptionGroup = create_exception_group_class();
+ if (!PyExc_ExceptionGroup) {
+ return -1;
+ }
+ if (PyDict_SetItemString(mod_dict, "ExceptionGroup", PyExc_ExceptionGroup)) {
+ return -1;
}
#define INIT_ALIAS(NAME, TYPE) \
@@ -3582,103 +3627,20 @@ _PyBuiltins_AddExceptions(PyObject *bltinmod)
Py_INCREF(PyExc_ ## TYPE); \
Py_XDECREF(PyExc_ ## NAME); \
PyExc_ ## NAME = PyExc_ ## TYPE; \
- if (PyDict_SetItemString(bdict, # NAME, PyExc_ ## NAME)) { \
- return _PyStatus_ERR("Module dictionary insertion problem."); \
+ if (PyDict_SetItemString(mod_dict, # NAME, PyExc_ ## NAME)) { \
+ return -1; \
} \
} while (0)
- PyObject *bdict;
-
- bdict = PyModule_GetDict(bltinmod);
- if (bdict == NULL) {
- return _PyStatus_ERR("exceptions bootstrapping error.");
- }
-
- PyObject *PyExc_ExceptionGroup = create_exception_group_class();
- if (!PyExc_ExceptionGroup) {
- return _PyStatus_ERR("exceptions bootstrapping error.");
- }
-
- POST_INIT(BaseException);
- POST_INIT(Exception);
- POST_INIT(BaseExceptionGroup);
- POST_INIT(ExceptionGroup);
- POST_INIT(TypeError);
- POST_INIT(StopAsyncIteration);
- POST_INIT(StopIteration);
- POST_INIT(GeneratorExit);
- POST_INIT(SystemExit);
- POST_INIT(KeyboardInterrupt);
- POST_INIT(ImportError);
- POST_INIT(ModuleNotFoundError);
- POST_INIT(OSError);
INIT_ALIAS(EnvironmentError, OSError);
INIT_ALIAS(IOError, OSError);
#ifdef MS_WINDOWS
INIT_ALIAS(WindowsError, OSError);
#endif
- POST_INIT(EOFError);
- POST_INIT(RuntimeError);
- POST_INIT(RecursionError);
- POST_INIT(NotImplementedError);
- POST_INIT(NameError);
- POST_INIT(UnboundLocalError);
- POST_INIT(AttributeError);
- POST_INIT(SyntaxError);
- POST_INIT(IndentationError);
- POST_INIT(TabError);
- POST_INIT(LookupError);
- POST_INIT(IndexError);
- POST_INIT(KeyError);
- POST_INIT(ValueError);
- POST_INIT(UnicodeError);
- POST_INIT(UnicodeEncodeError);
- POST_INIT(UnicodeDecodeError);
- POST_INIT(UnicodeTranslateError);
- POST_INIT(AssertionError);
- POST_INIT(ArithmeticError);
- POST_INIT(FloatingPointError);
- POST_INIT(OverflowError);
- POST_INIT(ZeroDivisionError);
- POST_INIT(SystemError);
- POST_INIT(ReferenceError);
- POST_INIT(MemoryError);
- POST_INIT(BufferError);
- POST_INIT(Warning);
- POST_INIT(UserWarning);
- POST_INIT(EncodingWarning);
- POST_INIT(DeprecationWarning);
- POST_INIT(PendingDeprecationWarning);
- POST_INIT(SyntaxWarning);
- POST_INIT(RuntimeWarning);
- POST_INIT(FutureWarning);
- POST_INIT(ImportWarning);
- POST_INIT(UnicodeWarning);
- POST_INIT(BytesWarning);
- POST_INIT(ResourceWarning);
-
- /* OSError subclasses */
- POST_INIT(ConnectionError);
-
- POST_INIT(BlockingIOError);
- POST_INIT(BrokenPipeError);
- POST_INIT(ChildProcessError);
- POST_INIT(ConnectionAbortedError);
- POST_INIT(ConnectionRefusedError);
- POST_INIT(ConnectionResetError);
- POST_INIT(FileExistsError);
- POST_INIT(FileNotFoundError);
- POST_INIT(IsADirectoryError);
- POST_INIT(NotADirectoryError);
- POST_INIT(InterruptedError);
- POST_INIT(PermissionError);
- POST_INIT(ProcessLookupError);
- POST_INIT(TimeoutError);
-
- return _PyStatus_OK();
-#undef POST_INIT
#undef INIT_ALIAS
+
+ return 0;
}
void
diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c
index a53f532e9e202..aca3b1a5fd1a4 100644
--- a/Python/pylifecycle.c
+++ b/Python/pylifecycle.c
@@ -740,9 +740,8 @@ pycore_init_types(PyInterpreterState *interp)
return status;
}
- status = _PyExc_InitTypes(interp);
- if (_PyStatus_EXCEPTION(status)) {
- return status;
+ if (_PyExc_InitTypes(interp) < 0) {
+ return _PyStatus_ERR("failed to initialize an exception type");
}
status = _PyExc_InitGlobalObjects(interp);
@@ -790,9 +789,8 @@ pycore_init_builtins(PyThreadState *tstate)
Py_INCREF(builtins_dict);
interp->builtins = builtins_dict;
- PyStatus status = _PyBuiltins_AddExceptions(bimod);
- if (_PyStatus_EXCEPTION(status)) {
- return status;
+ if (_PyBuiltins_AddExceptions(bimod) < 0) {
+ return _PyStatus_ERR("failed to add exceptions to builtins");
}
interp->builtins_copy = PyDict_Copy(interp->builtins);
More information about the Python-checkins
mailing list