Circular import cases could be detected by adding an int "state" field (initialized to 0 in PyModule_New) to the module object and PyModule_GetState/PyModule_SetState api functions to access the field. Then: in load_module (import.c) set the state to 1 ,when a module is completly loaded: /*just before return*/ if(m) PyModule_SetState(m,1) return m; ---------------------------------------------------------------------------- -------- in import_from (ceval.c): if (x == NULL && PyErr_ExceptionMatches(PyExc_AttributeError)) { if(!PyModule_GetState(v)) /*raise the error and warn against circular import*/ else /*default error*/ ---------------------------------------------------------------------------- -------- the same in PyGeneric_GetAttr (object.c): /* before raising an error*/ if(PyModule_Check(obj) && !PyModule_GetState(obj)) /*add a circular import warning to the error string*/ else /*default error*/ ---------------------------------------------------------------------------- -------- Probably there are some other places where modules state should be changed or checked but the solution I am proposing would help to localize most of them; A module's dict could be used to mark it's state but in my opinion an additional field is much safer (the same applays to PyModule_GetState/PyModule_SetState vs a new member def) Also: the soluton would enable checking for partially-loaded/broken modules in system.modules dict. Regards, Wiktor Sadowski
At 09:46 PM 5/29/04 +0200, Wiktor Sadowski wrote:
---------------------------------------------------------------------------- -------- in import_from (ceval.c): if (x == NULL && PyErr_ExceptionMatches(PyExc_AttributeError)) { if(!PyModule_GetState(v)) /*raise the error and warn against circular import*/ else /*default error*/ ---------------------------------------------------------------------------- -------- the same in PyGeneric_GetAttr (object.c): /* before raising an error*/ if(PyModule_Check(obj) && !PyModule_GetState(obj)) /*add a circular import warning to the error string*/ else /*default error*/ ---------------------------------------------------------------------------- --------
IMO, if this approach is used, the module type should instead get a custom tp_getattro method that checks the flag, rather than scattering this logic across unrelated functions.
participants (2)
-
Phillip J. Eby
-
Wiktor Sadowski