GNOME Bugzilla – Bug 639229
dir(module) does not list all available attributes
Last modified: 2011-01-13 16:43:16 UTC
In the DynamicModule class, the __dir__() method only returns the attributes available in the loaded typelib. It does not return the class attributes. This leads to the case where some attributes can be accessed, but do not show up in dir().
To make them more consistent, __dir__() should return the dynamic attributes from the typelib, as well as the keys from self.__dict__.
As an aside to this bug, it is also possible to access class members of IntrospectionModule, though they are not reported by DynamicModule.__dir__() either. This is because DynamicModule.__getattr__() calls getattr() on the IntrospectionModule instance. This should be changed to call IntrospectionModule.__getattr__ directly to avoid the case where a class variable has the same name as an attribute in the typelib. With the current call to getattr(IntrospectionModule, ...) instead of IntrospectionModule.__getattr__(...), the class variable would be returned instead of the typelib attribute.
Created attachment 178063 [details] [review]
Change __dir__() to report all the attributes that __getattr__ supports.
Change DynamicModule.__dir__() to return the local class members as well as the typelib attributes.
Change DynamicModule.__getattr__() to call IntrospectionModule.__getattr__() directly, so that it won't inadvertently return class attributes from IntrospectionModule.
Created attachment 178086 [details] [review]
Fixes __dir__() method for DynamicModule and IntrospectionModule, without breaking tests.
Here is an updated patch, applied to master, after the getattr() which broke the tests was reverted.
The previous patch made tests fail because calling __getattr__ directly skips the check of __dict__. IntrospectionModule was caching wrapped objects in __dict__, and the patch caused it to create and register a new type each time, instead of using the wrapped one from previous calls.
Thus, we cannot avoid __dict__, so all class methods will be available to applications importing from gi.repository. If there any any name collisions, a prefix would have to be (used such as _pygi_...) for all class methods.
This patch does not try to hide the class methods, it simply puts those that are already accessible in DynamicModule and IntrospectionModule in the list returned by __dir__().
Created attachment 178230 [details] [review]
new patch for __dir__() method in DynamicModule and IntrospectionModule
This patch fixes two things that the previous patch didn't:
- For DynamicModule, overrides are included in the __dir__() output.
- For both IntrospectionModule and DynamicModule, dir(self.__class__) is included, so method names of the classes are returned as well.
In this patch set() is used to avoid reporting duplicate elements.
dir(self.__class__) and self.__dict__.keys() are included to match what Python does by default for classes without a __dir__ method. With this patch, the __dir__() method includes all of attributes the default dir() does (ie, nothing is hidden by having a custom __dir__() method).
Created attachment 178242 [details] [review]
Simple test case for __dir__()
Add a simple test case to test __dir__() method. It does not test to see if every attribute is listed, just a few of each kind:
- (wrapped) typelib attributes
- class attributes and methods
- instance attributes
Created attachment 178244 [details] [review]
new patch for __dir__() with test case included
This patch includes both of the previous patches for the fix and test case together in one patch.