[pygobject] Fix the __dir__() methods on DynamicModule and IntrospectionModule



commit c36fbf4918c8557a8e274a12004a412da3b22b2c
Author: Laszlo Pandy <git laszlopandy com>
Date:   Tue Jan 11 21:41:47 2011 +0100

    Fix the __dir__() methods on DynamicModule and IntrospectionModule
    
    Previously the __dir__() methods did not list all attributes.
    A simple test case is included. It does not test to see if
    every attribute is listed, it just tests a few of each kind:
    - (wrapped) typelib attributes
    - class attributes and methods
    - instance attributes
    
    A set() is used to avoid returning duplicate attributes.
    The test case checks for this as well.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=639229

 gi/module.py             |   28 +++++++++++++++++++++-------
 tests/test_everything.py |   18 ++++++++++++++++++
 2 files changed, 39 insertions(+), 7 deletions(-)
---
diff --git a/gi/module.py b/gi/module.py
index 126d2d7..f19dfb6 100644
--- a/gi/module.py
+++ b/gi/module.py
@@ -178,8 +178,17 @@ class IntrospectionModule(object):
         return "<IntrospectionModule %r from %r>" % (self._namespace, path)
 
     def __dir__ (self):
-        attribs_list = repository.get_infos(self._namespace)
-        return list(map(lambda x: x.get_name(), attribs_list))
+        # Python's default dir() is just dir(self.__class__) + self.__dict__.keys()
+        result = set(dir(self.__class__))
+        result.update(self.__dict__.keys())
+
+        # update *set* because some repository attributes have already been
+        # wrapped by __getattr__() and included in self.__dict__
+        namespace_infos = repository.get_infos(self._namespace)
+        result.update(info.get_name() for info in namespace_infos)
+
+        return list(result)
+
 
 class DynamicGObjectModule(IntrospectionModule):
     """Wrapper for the GObject module
@@ -254,12 +263,17 @@ class DynamicModule(object):
         return getattr(self.introspection_module, name)
 
     def __dir__ (self):
-        repository.require(self._namespace, self._version)
+        if self.introspection_module is None:
+            self._import()
+            
+        # Python's default dir() is just dir(self.__class__) + self.__dict__.keys()
+        result = set(dir(self.__class__))
+        result.update(self.__dict__.keys())
         
-        namespace_infos = repository.get_infos(self._namespace)
-        result = [info.get_name() for info in namespace_infos]
-        result.extend(self.__dict__.keys())
-        return result
+        result.update(dir(self.introspection_module))
+        override_exports = getattr(self._overrides_module, '__all__', ())
+        result.update(override_exports)
+        return list(result)
 
     def __repr__(self):
         repository.require(self._namespace, self._version)
diff --git a/tests/test_everything.py b/tests/test_everything.py
index f72a27c..b2f2463 100644
--- a/tests/test_everything.py
+++ b/tests/test_everything.py
@@ -131,6 +131,24 @@ class TestEverything(unittest.TestCase):
         gtype = Everything.test_gtype(ARegisteredClass)
         self.assertEquals(ARegisteredClass.__gtype__, gtype)
         self.assertRaises(TypeError, Everything.test_gtype, 'ARegisteredClass')
+        
+    def test_dir(self):
+        attr_list = dir(Everything)
+        
+        # test that typelib attributes are listed
+        self.assertTrue('TestStructA' in attr_list)
+        
+        # test that class attributes and methods are listed
+        self.assertTrue('__class__' in attr_list)
+        self.assertTrue('__dir__' in attr_list)
+        self.assertTrue('__repr__' in attr_list)
+        
+        # test that instance members are listed
+        self.assertTrue('_namespace' in attr_list)
+        self.assertTrue('version' in attr_list)
+        
+        # test that there are no duplicates returned
+        self.assertEqual(len(attr_list), len(set(attr_list)))
 
 class TestNullableArgs(unittest.TestCase):
     def test_in_nullable_hash(self):



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]