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.
This commit is contained in:
Victor Stinner 2022-01-22 21:48:56 +01:00 committed by GitHub
parent a941e5927f
commit f1bcdeaca6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 151 additions and 191 deletions

View File

@ -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 *);

View File

@ -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);

View File

@ -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
├── PendingDeprecationWarning
├── RuntimeWarning
├── SyntaxWarning
├── UserWarning
├── EncodingWarning
├── FutureWarning
├── ImportWarning
├── PendingDeprecationWarning
├── ResourceWarning
├── RuntimeWarning
├── SyntaxWarning
├── UnicodeWarning
├── BytesWarning
├── EncodingWarning
└── ResourceWarning
└── UserWarning

View File

@ -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);
for (size_t i=0; i < Py_ARRAY_LENGTH(static_exceptions); i++) {
PyTypeObject *exc = static_exceptions[i].exc;
/* 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);
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

View File

@ -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);