@@ -151,15 +151,15 @@ calculate_suggestions(PyObject *dir,
151
151
}
152
152
for (int i = 0 ; i < dir_size ; ++ i ) {
153
153
PyObject * item = PyList_GET_ITEM (dir , i );
154
+ if (_PyUnicode_Equal (name , item )) {
155
+ continue ;
156
+ }
154
157
Py_ssize_t item_size ;
155
158
const char * item_str = PyUnicode_AsUTF8AndSize (item , & item_size );
156
159
if (item_str == NULL ) {
157
160
PyMem_Free (buffer );
158
161
return NULL ;
159
162
}
160
- if (PyUnicode_CompareWithASCIIString (name , item_str ) == 0 ) {
161
- continue ;
162
- }
163
163
// No more than 1/3 of the involved characters should need changed.
164
164
Py_ssize_t max_distance = (name_size + item_size + 3 ) * MOVE_COST / 6 ;
165
165
// Don't take matches we've already beaten.
@@ -220,37 +220,48 @@ get_suggestions_for_name_error(PyObject* name, PyFrameObject* frame)
220
220
assert (code != NULL && code -> co_localsplusnames != NULL );
221
221
222
222
PyObject * varnames = _PyCode_GetVarnames (code );
223
+ Py_DECREF (code );
223
224
if (varnames == NULL ) {
224
225
return NULL ;
225
226
}
226
227
PyObject * dir = PySequence_List (varnames );
227
228
Py_DECREF (varnames );
228
- Py_DECREF (code );
229
229
if (dir == NULL ) {
230
230
return NULL ;
231
231
}
232
232
233
233
// Are we inside a method and the instance has an attribute called 'name'?
234
- if (PySequence_Contains (dir , & _Py_ID (self )) > 0 ) {
234
+ int res = PySequence_Contains (dir , & _Py_ID (self ));
235
+ if (res < 0 ) {
236
+ goto error ;
237
+ }
238
+ if (res > 0 ) {
235
239
PyObject * locals = PyFrame_GetLocals (frame );
236
240
if (!locals ) {
237
241
goto error ;
238
242
}
239
- PyObject * self = PyDict_GetItem (locals , & _Py_ID (self )); /* borrowed */
240
- Py_DECREF (locals );
243
+ PyObject * self = PyDict_GetItemWithError (locals , & _Py_ID (self )); /* borrowed */
241
244
if (!self ) {
245
+ Py_DECREF (locals );
242
246
goto error ;
243
247
}
244
248
245
- if (PyObject_HasAttr (self , name )) {
249
+ PyObject * value ;
250
+ res = _PyObject_LookupAttr (self , name , & value );
251
+ Py_DECREF (locals );
252
+ if (res < 0 ) {
253
+ goto error ;
254
+ }
255
+ if (value ) {
256
+ Py_DECREF (value );
246
257
Py_DECREF (dir );
247
- return PyUnicode_FromFormat ("self.%S " , name );
258
+ return PyUnicode_FromFormat ("self.%U " , name );
248
259
}
249
260
}
250
261
251
262
PyObject * suggestions = calculate_suggestions (dir , name );
252
263
Py_DECREF (dir );
253
- if (suggestions != NULL ) {
264
+ if (suggestions != NULL || PyErr_Occurred () ) {
254
265
return suggestions ;
255
266
}
256
267
@@ -260,7 +271,7 @@ get_suggestions_for_name_error(PyObject* name, PyFrameObject* frame)
260
271
}
261
272
suggestions = calculate_suggestions (dir , name );
262
273
Py_DECREF (dir );
263
- if (suggestions != NULL ) {
274
+ if (suggestions != NULL || PyErr_Occurred () ) {
264
275
return suggestions ;
265
276
}
266
277
@@ -319,15 +330,16 @@ offer_suggestions_for_name_error(PyNameErrorObject *exc)
319
330
assert (frame != NULL );
320
331
321
332
PyObject * suggestion = get_suggestions_for_name_error (name , frame );
322
- bool is_stdlib_module = is_name_stdlib_module (name );
323
-
324
- if (suggestion == NULL && !is_stdlib_module ) {
333
+ if (suggestion == NULL && PyErr_Occurred ()) {
325
334
return NULL ;
326
335
}
327
336
328
337
// Add a trailer ". Did you mean: (...)?"
329
338
PyObject * result = NULL ;
330
- if (!is_stdlib_module ) {
339
+ if (!is_name_stdlib_module (name )) {
340
+ if (suggestion == NULL ) {
341
+ return NULL ;
342
+ }
331
343
result = PyUnicode_FromFormat (". Did you mean: %R?" , suggestion );
332
344
} else if (suggestion == NULL ) {
333
345
result = PyUnicode_FromFormat (". Did you forget to import %R?" , name );
0 commit comments