clarete / forbiddenfruit

Patch built-in python objects
https://clarete.li/forbiddenfruit/
GNU General Public License v3.0
826 stars 52 forks source link

Fix usage of dir() without arg to inspect local scope #13

Closed lukasgraf closed 9 years ago

lukasgraf commented 9 years ago

A call to dir() without arguments is supposed to list the names in the local scope.

Because forbiddenfruit monkey patches __builtin__.dir with its own __filtered_dir__, an additional frame is present in the call stack, making CPythons _dir_locals_ access the wrong frame.

This breaks the use of dir() to inspect the local scope. I noticed this when a 3rd party module's star imports from the pickle module suddenly misbehaved: The pickle module first defines a limited __all__, but then later extends it using dir(), which failed as soon as we imported forbiddenfruit in our tests.

Example:

>>> from pickle import *
>>> PERSID
'P'

Now with importing forbiddenfruit first:

>>> import forbiddenfruit
>>> from pickle import *
>>> PERSID
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'PERSID' is not defined

This change makes __filtered_dir__ account for that additional stack frame and return the names from the local scope of the actual calling frame.

Includes a simple test that was enough to demonstrate the erroneous behavior, and now passes.

clarete commented 9 years ago

Thanks for the patch!

lukasgraf commented 9 years ago

You're welcome, thanks for the quick merge :wink: Would you mind creating a new release on PyPi some time soon?