Commits

mbrochh committed b9e52dc

Minor changes to make coverage extension more robust against exceptions and false positives..

Comments (0)

Files changed (1)

sphinx/ext/coverage.py

                         if exp.match(name):
                             break
                     else:
-                        if full_name not in objects:
+                        if (full_name not in objects
+                            and not obj.__doc__):
                             # not documented at all
                             classes[name] = []
                             continue
                         attrs = []
 
                         for attr_name in dir(obj):
+                            if attr_name not in obj.__dict__:
+                                continue
                             attr = getattr(obj, attr_name)
-                        for attr_name, attr in inspect.getmembers(
-                                obj, lambda x: inspect.ismethod(x) or \
-                                               inspect.isfunction(x)):
+                            if (not inspect.ismethod(attr)
+                                and not inspect.isfunction(attr)):
+                                continue
                             if attr_name[0] == '_':
                                 # starts with an underscore, ignore it
                                 continue
 
                             full_attr_name = '%s.%s' % (full_name, attr_name)
                             if full_attr_name not in objects:
+                                if not self._is_func_undocumented(
+                                    obj, attr_name):
+                                    continue
                                 attrs.append(attr_name)
 
                         if attrs:
 
             self.py_undoc[mod_name] = {'funcs': funcs, 'classes': classes}
 
+    def _is_func_undocumented(self, obj, attr_name):
+        """Last check looking at the source code. Is function really not documented?"""
+        obj_source = inspect.getsource(obj) or ''
+        obj_source = obj_source.replace(' ', '').replace('\n', '')
+        if not "def%s" % attr_name in obj_source:
+            # Funktion is not defined in this class. No documentation needed.
+            return False
+        m = re.search('def%s\([^\)]*\):"""' %attr_name, obj_source)
+        if not m:
+            return True
+        else:
+            return False
+
     def write_py_coverage(self):
         output_file = path.join(self.outdir, 'python.txt')
         op = open(output_file, 'w')
         failed = []
         try:
-            write_header(op, 'Undocumented Python objects', '=')
-
+            if self.config.coverage_write_headline:
+                write_header(op, 'Undocumented Python objects', '=')
             keys = self.py_undoc.keys()
             keys.sort()
             for name in keys:
     app.add_config_value('coverage_c_path', [], False)
     app.add_config_value('coverage_c_regexes', {}, False)
     app.add_config_value('coverage_ignore_c_items', {}, False)
+    app.add_config_value('coverage_write_headline', {}, False)