@@ -198,6 +198,71 @@ module_repr(PyModuleObject *m)
198198 return PyString_FromFormat ("<module '%s' from '%s'>" , name , filename );
199199}
200200
201+ static PyObject *
202+ find_builtin_names (void )
203+ {
204+ PyObject * builtins , * names , * key , * value ;
205+ int pos = 0 ;
206+ builtins = PyEval_GetBuiltins ();
207+ if (builtins == NULL || !PyDict_Check (builtins )) {
208+ PyErr_SetString (PyExc_SystemError , "no builtins dict!" );
209+ return NULL ;
210+ }
211+ names = PyDict_New ();
212+ if (names == NULL )
213+ return NULL ;
214+ while (PyDict_Next (builtins , & pos , & key , & value )) {
215+ if (PyString_Check (key ) &&
216+ PyString_Size (key ) > 0 &&
217+ PyString_AS_STRING (key )[0 ] != '_' ) {
218+ if (PyDict_SetItem (names , key , Py_None ) < 0 ) {
219+ Py_DECREF (names );
220+ return NULL ;
221+ }
222+ }
223+ }
224+ return names ;
225+ }
226+
227+ /* returns 0 or 1 (and -1 on error) */
228+ static int
229+ shadows_builtin (PyObject * globals , PyObject * name )
230+ {
231+ static PyObject * builtin_names = NULL ;
232+ if (builtin_names == NULL ) {
233+ builtin_names = find_builtin_names ();
234+ if (builtin_names == NULL )
235+ return -1 ;
236+ }
237+ if (!PyString_Check (name ))
238+ return 0 ;
239+ if (PyDict_GetItem (globals , name ) == NULL &&
240+ PyDict_GetItem (builtin_names , name ) != NULL ) {
241+ return 1 ;
242+ }
243+ else {
244+ return 0 ;
245+ }
246+ }
247+
248+ static int
249+ module_setattr (PyObject * m , PyObject * name , PyObject * value )
250+ {
251+ PyObject * globals = ((PyModuleObject * )m )-> md_dict ;
252+ PyObject * builtins = PyEval_GetBuiltins ();
253+ if (globals != NULL && globals != builtins ) {
254+ int shadows = shadows_builtin (globals , name );
255+ if (shadows == 1 ) {
256+ if (PyErr_Warn (PyExc_DeprecationWarning ,
257+ "assignment shadows builtin" ) < 0 )
258+ return -1 ;
259+ }
260+ else if (shadows == -1 )
261+ return -1 ;
262+ }
263+ return PyObject_GenericSetAttr (m , name , value );
264+ }
265+
201266/* We only need a traverse function, no clear function: If the module
202267 is in a cycle, md_dict will be cleared as well, which will break
203268 the cycle. */
@@ -234,7 +299,7 @@ PyTypeObject PyModule_Type = {
234299 0 , /* tp_call */
235300 0 , /* tp_str */
236301 PyObject_GenericGetAttr , /* tp_getattro */
237- PyObject_GenericSetAttr , /* tp_setattro */
302+ module_setattr , /* tp_setattro */
238303 0 , /* tp_as_buffer */
239304 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
240305 Py_TPFLAGS_BASETYPE , /* tp_flags */
0 commit comments