Changeset 83

Show
Ignore:
Timestamp:
07/09/06 13:05:49 (7 years ago)
Author:
mk
Message:

Imported newest version of model.py from pydoctor.
Adapted UnitTests? index to new interface (closes tickets #40 and #41).

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • branches/mk/cheesecake/cheesecake_index.py

    r82 r83  
    5252        return new_list 
    5353 
     54if 'set' not in dir(__builtins__): 
     55    from sets import Set as set 
     56 
    5457def isiterable(obj): 
    5558    """Check whether object is iterable. 
     
    111114            if dir in ['test', 'tests']: 
    112115                return 'test' 
    113             elif dir in ['docs', 'demo', 'example']: 
     116            elif dir in ['doc', 'docs', 'demo', 'example', 'examples']: 
    114117                return 'demo' 
    115118        return 'module' 
     
    788791    max_value = 50 
    789792 
    790     def compute(self, files_list, functions, package_dir): 
     793    def compute(self, files_list, functions, classes, package_dir): 
    791794        unittest_cnt = 0 
    792         self.functions_tested = {} 
    793  
     795        functions_tested = set() 
     796 
     797        # Gather all function names called from test files. 
    794798        for testfile in get_files_of_type(files_list, 'test'): 
    795799            fullpath = os.path.join(package_dir, testfile) 
    796800            code = CodeParser(fullpath, self.cheesecake.log.debug) 
    797801 
    798             func_called = code.functions_called() 
    799  
    800             for func in func_called: 
    801                 self.functions_tested[func] = 1 
    802  
    803         for funcname in functions: 
    804             if self.is_unit_tested(funcname): 
     802            functions_tested = functions_tested.union(code.functions_called) 
     803 
     804        for name in functions + classes: 
     805            if name in functions_tested: 
    805806                unittest_cnt += 1 
    806                 self.log.cheesecake.debug("%s is unit tested" % funcname) 
    807  
     807                self.cheesecake.log.debug("%s is unit tested" % name) 
     808 
     809        functions_classes_cnt = len(functions) + len(classes) 
    808810        percent = 0 
    809         if len(functions) > 0: 
    810             percent = float(unittest_cnt)/float(len(functions)
     811        if functions_classes_cnt > 0: 
     812            percent = float(unittest_cnt)/float(functions_classes_cnt
    811813 
    812814        # Scale the result. 
    813815        self.value = int(ceil(percent * self.max_value)) 
    814816 
    815         self.details = "found %d/%d=%.2f%% unit tested methods/functions." %\ 
    816                  (unittest_cnt, len(functions), percent*100) 
     817        self.details = "found %d/%d=%.2f%% unit tested classes/methods/functions." %\ 
     818                 (unittest_cnt, functions_classes_cnt, percent*100) 
    817819 
    818820        return self.value 
    819  
    820     def is_unit_tested(self, funcname): 
    821         elem = funcname.split(".") 
    822         n1 = elem[-1] 
    823         n2 = "" 
    824         if len(elem) > 1: 
    825             n2 = elem[-2] + "." + elem[-1] 
    826         for key in self.functions_tested.keys(): 
    827             if key.startswith(n1) or (n2 and key.startswith(n2)): 
    828                 return True 
    829         return False 
    830821 
    831822class IndexPyLint(Index): 
     
    893884    subindices = [ 
    894885        IndexPyLint, 
    895         #IndexUnitTests, TODO 
     886        IndexUnitTests, 
    896887    ] 
    897888 
     
    12991290          functions : list 
    13001291              List of all functions defined in package sources. 
     1292          classes : list 
     1293              List of all classes defined in package sources. 
    13011294          object_cnt : int 
    13021295              Number of documentable objects found in all package modules. 
     
    13121305        self.docformat_cnt = 0 
    13131306        self.functions = [] 
     1307        self.classes = [] 
    13141308 
    13151309        # Parse all application files and count objects 
     
    13231317            self.docformat_cnt += code.formatted_docstrings_count 
    13241318            self.functions += code.functions 
     1319            self.classes += code.classes 
    13251320 
    13261321        # Log a bit of debugging info. 
  • branches/mk/cheesecake/codeparser.py

    r44 r83  
    187187        return len(self.docstrings_by_format[type]) 
    188188 
    189     def functions_called(self): 
     189    def _functions_called(self): 
    190190        """Return list of functions called by functions/methods 
    191191        defined in this module. 
    192192        """ 
    193193        return self.system.func_called.keys() 
     194 
     195    functions_called = property(_functions_called) 
  • branches/mk/cheesecake/model.py

    r40 r83  
     1""" 
     2Code borrowed from Michael Hudson's docextractor package with the author's 
     3permission. 
     4 
     5The original code is available at http://codespeak.net/svn/user/mwh/docextractor/. 
     6 
     7Changes: 
     8  * do not print warnings to stdout (in System.warning) 
     9  * collect all function calls 
     10""" 
     11 
     12 
    113from compiler import ast 
    214import sys 
     
    1022 
    1123import ast_pp 
     24 
     25 
     26def get_call_name(node): 
     27    assert isinstance(node, ast.CallFunc) 
     28 
     29    def get_name(node): 
     30        if isinstance(node, ast.Name): 
     31            return node.name 
     32        elif isinstance(node, str): 
     33            return node 
     34        elif isinstance(node, tuple): 
     35            if len(node) == 1: 
     36                return node[0] 
     37            else: 
     38                return "%s.%s" % (get_name(node[:-1][0]), node[-1]) 
     39        elif isinstance(node, ast.Getattr): 
     40            return get_name(node.asList()) 
     41        else: 
     42            raise TypeError("Bad function name type: %s." % node) 
     43 
     44    return get_name(node.node) 
     45 
     46def get_function_calls(node, fc): 
     47    if not isinstance(node, ast.Node): 
     48        return  
     49 
     50    for child in node.getChildren(): 
     51        if isinstance(child, ast.CallFunc): 
     52            func_called = get_call_name(child) 
     53            fc[func_called] = 1 
     54 
     55        get_function_calls(child, fc) 
     56 
    1257 
    1358class Documentable(object): 
     
    5095                    obj = system.allobjects[parts[0]] 
    5196                    break 
    52                 if verbose: 
    53                     print "1 didn't find %r from %r"%(dottedname, 
     97                for othersys in system.moresystems: 
     98                    if parts[0] in othersys.allobjects: 
     99                        obj = othersys.allobjects[parts[0]] 
     100                        break 
     101                else: 
     102                    if verbose: 
     103                        print "1 didn't find %r from %r"%(dottedname, 
    54104                                                      self.fullName()) 
    55                 return None 
     105                    return None 
     106                break 
    56107        else: 
    57108            fn = obj._name2fullname[parts[0]] 
     
    171222            assert m.docstring is None 
    172223            m.docstring = node.doc 
    173             self.system.push(m
     224            self.system.push(m, node
    174225            self.default(node) 
    175226            self.system.pop(m) 
     
    179230                if roots: 
    180231                    mod, = roots 
    181                     self.system.push(mod
     232                    self.system.push(mod, node
    182233                    self.default(node) 
    183234                    self.system.pop(mod) 
     
    244295 
    245296    def visitFunction(self, node): 
    246         func = self.system.pushFunction(node.name, node.doc) 
     297        fc = {} 
     298        get_function_calls(node, fc) 
     299        func = self.system.pushFunction(node.name, node.doc, fc) 
    247300        if node.lineno is not None: 
    248301            func.linenumber = node.lineno 
     
    304357        # for import * statements 
    305358        self.importstargraph = {} 
     359        self.func_called = {} 
    306360        self.state = 'blank' 
    307361        self.packages = [] 
     362        self.moresystems = [] 
     363        self.urlprefix = '' 
    308364 
    309365    def _push(self, cls, name, docstring): 
     
    365421        self.current = self.current.parent 
    366422 
    367     def push(self, obj): 
     423    def push(self, obj, node=None): 
    368424        self._stack.append(self.current) 
    369425        self.current = obj 
     
    383439        self._pop(self.Module) 
    384440 
    385     def pushFunction(self, name, docstring): 
     441    def pushFunction(self, name, docstring, func_called): 
     442        self.func_called.update(func_called) 
    386443        return self._push(self.Function, name, docstring) 
    387444    def popFunction(self): 
     
    431488        else: 
    432489            fn = '<None>' 
    433         #print fn, type, detail 
    434490        self.warnings.setdefault(type, []).append((fn, detail)) 
    435491 
     
    444500    def recordBasesAndSubclasses(self): 
    445501        for cls in self.objectsOfType(Class): 
    446             for n in cls.rawbases: 
     502            for n in cls.bases: 
    447503                o = cls.parent.resolveDottedName(n) 
    448504                cls.baseobjects.append(o) 
     
    450506                    o.subclasses.append(cls) 
    451507 
     508    def __getstate__(self): 
     509        state = self.__dict__.copy() 
     510        del state['moresystems'] 
     511        return state 
     512 
    452513    def __setstate__(self, state): 
     514        self.moresystems = [] 
    453515        # this is so very, very evil. 
    454516        # see doc/extreme-pickling-pain.txt for more. 
     
    512574    while mv.morenodes: 
    513575        obj, node = mv.morenodes.pop(0) 
    514         system.push(obj
     576        system.push(obj, node
    515577        mv.visit(node) 
    516578        system.pop(obj)