702
702
_PyModuleSpec_IsInitializing (PyObject * spec )
703
703
{
704
704
if (spec != NULL ) {
705
- PyObject * value = PyObject_GetAttr (spec , & _Py_ID (_initializing ));
705
+ PyObject * value ;
706
+ int ok = _PyObject_LookupAttr (spec , & _Py_ID (_initializing ), & value );
707
+ if (ok == 0 ) {
708
+ return 0 ;
709
+ }
706
710
if (value != NULL ) {
707
711
int initializing = PyObject_IsTrue (value );
708
712
Py_DECREF (value );
@@ -738,19 +742,37 @@ _PyModuleSpec_IsUninitializedSubmodule(PyObject *spec, PyObject *name)
738
742
return is_uninitialized ;
739
743
}
740
744
741
- static PyObject *
742
- module_getattro (PyModuleObject * m , PyObject * name )
745
+ PyObject *
746
+ _Py_module_getattro_impl (PyModuleObject * m , PyObject * name , int suppress )
743
747
{
748
+ // When suppress=1, this function suppresses AttributeError.
744
749
PyObject * attr , * mod_name , * getattr ;
745
- attr = PyObject_GenericGetAttr ((PyObject * )m , name );
746
- if (attr || ! PyErr_ExceptionMatches ( PyExc_AttributeError ) ) {
750
+ attr = _PyObject_GenericGetAttrWithDict ((PyObject * )m , name , NULL , suppress );
751
+ if (attr ) {
747
752
return attr ;
748
753
}
749
- PyErr_Clear ();
754
+ if (suppress == 1 ) {
755
+ if (PyErr_Occurred ()) {
756
+ // pass up non-AttributeError exception
757
+ return NULL ;
758
+ }
759
+ }
760
+ else {
761
+ if (!PyErr_ExceptionMatches (PyExc_AttributeError )) {
762
+ // pass up non-AttributeError exception
763
+ return NULL ;
764
+ }
765
+ PyErr_Clear ();
766
+ }
750
767
assert (m -> md_dict != NULL );
751
768
getattr = PyDict_GetItemWithError (m -> md_dict , & _Py_ID (__getattr__ ));
752
769
if (getattr ) {
753
- return PyObject_CallOneArg (getattr , name );
770
+ PyObject * result = PyObject_CallOneArg (getattr , name );
771
+ if (result == NULL && suppress == 1 && PyErr_ExceptionMatches (PyExc_AttributeError )) {
772
+ // suppress AttributeError
773
+ PyErr_Clear ();
774
+ }
775
+ return result ;
754
776
}
755
777
if (PyErr_Occurred ()) {
756
778
return NULL ;
@@ -763,37 +785,48 @@ module_getattro(PyModuleObject *m, PyObject *name)
763
785
Py_DECREF (mod_name );
764
786
return NULL ;
765
787
}
766
- Py_XINCREF (spec );
767
- if (_PyModuleSpec_IsInitializing (spec )) {
768
- PyErr_Format (PyExc_AttributeError ,
769
- "partially initialized "
770
- "module '%U' has no attribute '%U' "
771
- "(most likely due to a circular import)" ,
772
- mod_name , name );
773
- }
774
- else if (_PyModuleSpec_IsUninitializedSubmodule (spec , name )) {
775
- PyErr_Format (PyExc_AttributeError ,
776
- "cannot access submodule '%U' of module '%U' "
777
- "(most likely due to a circular import)" ,
778
- name , mod_name );
779
- }
780
- else {
781
- PyErr_Format (PyExc_AttributeError ,
782
- "module '%U' has no attribute '%U'" ,
783
- mod_name , name );
788
+ if (suppress != 1 ) {
789
+ Py_XINCREF (spec );
790
+ if (_PyModuleSpec_IsInitializing (spec )) {
791
+ PyErr_Format (PyExc_AttributeError ,
792
+ "partially initialized "
793
+ "module '%U' has no attribute '%U' "
794
+ "(most likely due to a circular import)" ,
795
+ mod_name , name );
796
+ }
797
+ else if (_PyModuleSpec_IsUninitializedSubmodule (spec , name )) {
798
+ PyErr_Format (PyExc_AttributeError ,
799
+ "cannot access submodule '%U' of module '%U' "
800
+ "(most likely due to a circular import)" ,
801
+ name , mod_name );
802
+ }
803
+ else {
804
+ PyErr_Format (PyExc_AttributeError ,
805
+ "module '%U' has no attribute '%U'" ,
806
+ mod_name , name );
807
+ }
808
+ Py_XDECREF (spec );
784
809
}
785
- Py_XDECREF (spec );
786
810
Py_DECREF (mod_name );
787
811
return NULL ;
788
812
}
789
813
else if (PyErr_Occurred ()) {
790
814
return NULL ;
791
815
}
792
- PyErr_Format (PyExc_AttributeError ,
793
- "module has no attribute '%U'" , name );
816
+ if (suppress != 1 ) {
817
+ PyErr_Format (PyExc_AttributeError ,
818
+ "module has no attribute '%U'" , name );
819
+ }
794
820
return NULL ;
795
821
}
796
822
823
+
824
+ PyObject *
825
+ _Py_module_getattro (PyModuleObject * m , PyObject * name )
826
+ {
827
+ return _Py_module_getattro_impl (m , name , 0 );
828
+ }
829
+
797
830
static int
798
831
module_traverse (PyModuleObject * m , visitproc visit , void * arg )
799
832
{
@@ -951,7 +984,7 @@ PyTypeObject PyModule_Type = {
951
984
0 , /* tp_hash */
952
985
0 , /* tp_call */
953
986
0 , /* tp_str */
954
- (getattrofunc )module_getattro , /* tp_getattro */
987
+ (getattrofunc )_Py_module_getattro , /* tp_getattro */
955
988
PyObject_GenericSetAttr , /* tp_setattro */
956
989
0 , /* tp_as_buffer */
957
990
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
0 commit comments