@@ -848,39 +848,103 @@ _Py_module_getattro_impl(PyModuleObject *m, PyObject *name, int suppress)
848
848
Py_DECREF (origin );
849
849
}
850
850
851
- int rc = _PyModuleSpec_IsInitializing (spec );
852
- if (rc > 0 ) {
853
- if (valid_origin == 1 ) {
854
- PyErr_Format (PyExc_AttributeError ,
855
- "partially initialized "
856
- "module '%U' from '%U' has no attribute '%U' "
857
- "(most likely due to a circular import)" ,
858
- mod_name , origin , name );
859
- }
860
- else {
861
- PyErr_Format (PyExc_AttributeError ,
862
- "partially initialized "
863
- "module '%U' has no attribute '%U' "
864
- "(most likely due to a circular import)" ,
865
- mod_name , name );
851
+ int is_script_shadowing_stdlib = 0 ;
852
+ // Check mod.__name__ in sys.stdlib_module_names
853
+ // and os.path.dirname(mod.__spec__.origin) == os.getcwd()
854
+ PyObject * stdlib = NULL ;
855
+ if (valid_origin == 1 ) {
856
+ if (
857
+ // avoid bad recursion
858
+ PyUnicode_CompareWithASCIIString (mod_name , "sys" ) != 0
859
+ && PyUnicode_CompareWithASCIIString (mod_name , "os" ) != 0
860
+ && PyUnicode_CompareWithASCIIString (mod_name , "builtins" ) != 0
861
+ ) {
862
+ stdlib = _PyImport_GetModuleAttrString ("sys" , "stdlib_module_names" );
863
+ if (!stdlib ) {
864
+ goto done ;
865
+ }
866
+ if (PySet_Contains (stdlib , mod_name )) {
867
+ PyObject * os_path = _PyImport_GetModuleAttrString ("os" , "path" );
868
+ if (!os_path ) {
869
+ goto done ;
870
+ }
871
+ PyObject * dirname = PyObject_GetAttrString (os_path , "dirname" );
872
+ Py_DECREF (os_path );
873
+ if (!dirname ) {
874
+ goto done ;
875
+ }
876
+ PyObject * origin_dir = _PyObject_CallOneArg (dirname , origin );
877
+ Py_DECREF (dirname );
878
+ if (!origin_dir ) {
879
+ goto done ;
880
+ }
881
+
882
+ PyObject * getcwd = _PyImport_GetModuleAttrString ("os" , "getcwd" );
883
+ if (!getcwd ) {
884
+ Py_DECREF (origin_dir );
885
+ goto done ;
886
+ }
887
+ PyObject * cwd = _PyObject_CallNoArgs (getcwd );
888
+ Py_DECREF (getcwd );
889
+ if (!cwd ) {
890
+ Py_DECREF (origin_dir );
891
+ goto done ;
892
+ }
893
+
894
+ is_script_shadowing_stdlib = PyObject_RichCompareBool (origin_dir , cwd , Py_EQ );
895
+ Py_DECREF (origin_dir );
896
+ Py_DECREF (cwd );
897
+ if (is_script_shadowing_stdlib < 0 ) {
898
+ goto done ;
899
+ }
900
+ }
866
901
}
867
902
}
868
- else if (rc == 0 ) {
869
- rc = _PyModuleSpec_IsUninitializedSubmodule (spec , name );
903
+
904
+ if (is_script_shadowing_stdlib == 1 ) {
905
+ PyErr_Format (PyExc_AttributeError ,
906
+ "module '%U' has no attribute '%U' "
907
+ "(most likely due to '%U' shadowing the standard library "
908
+ "module named '%U')" ,
909
+ mod_name , name , origin , mod_name );
910
+ } else {
911
+ int rc = _PyModuleSpec_IsInitializing (spec );
870
912
if (rc > 0 ) {
871
- PyErr_Format (PyExc_AttributeError ,
872
- "cannot access submodule '%U' of module '%U' "
873
- "(most likely due to a circular import)" ,
874
- name , mod_name );
913
+ if (valid_origin == 1 ) {
914
+ PyErr_Format (PyExc_AttributeError ,
915
+ "partially initialized "
916
+ "module '%U' from '%U' has no attribute '%U' "
917
+ "(most likely due to a circular import)" ,
918
+ mod_name , origin , name );
919
+ }
920
+ else {
921
+ PyErr_Format (PyExc_AttributeError ,
922
+ "partially initialized "
923
+ "module '%U' has no attribute '%U' "
924
+ "(most likely due to a circular import)" ,
925
+ mod_name , name );
926
+ }
875
927
}
876
928
else if (rc == 0 ) {
877
- PyErr_Format (PyExc_AttributeError ,
878
- "module '%U' has no attribute '%U'" ,
879
- mod_name , name );
929
+ rc = _PyModuleSpec_IsUninitializedSubmodule (spec , name );
930
+ if (rc > 0 ) {
931
+ PyErr_Format (PyExc_AttributeError ,
932
+ "cannot access submodule '%U' of module '%U' "
933
+ "(most likely due to a circular import)" ,
934
+ name , mod_name );
935
+ }
936
+ else if (rc == 0 ) {
937
+ PyErr_Format (PyExc_AttributeError ,
938
+ "module '%U' has no attribute '%U'" ,
939
+ mod_name , name );
940
+ }
880
941
}
881
942
}
943
+
944
+ done :
882
945
Py_XDECREF (spec );
883
946
Py_XDECREF (origin );
947
+ Py_XDECREF (stdlib );
884
948
Py_DECREF (mod_name );
885
949
return NULL ;
886
950
}
0 commit comments