def run(self): status = 0 classes_num = len(self._classes) for node in self._classes: print "Complete ",status,"/",classes_num," classes" # ProbUsed will be true, if this class will be detect as candidate for duck field #self._complete_signatures[node.get("id")]={'Attrs':Set([]),'Methods':Set([]),'ProbUsed' : False} for method in self.get_methods(node): if get_visibility(method)=='special': ''' ignore __init__ etc.''' continue if self._assign_method(node,method): if self._methods.has_key(method): self._methods[method].append((node.get("id"),node,method)) else: self._methods[method]=[(node.get("id"),node,method)] status +=1 methods_num = len(self._methods.keys()) status = 0 count = 0 for method in self._methods.keys(): print "Complete ",status,"/",methods_num," method names" if(len(self._methods[method])>1): print "Method ",method," implemented in classes(id): ",[t[0] for t in self._methods[method]] for t in self._methods[method]: if self._classes_info.has_key(t[1]): self._classes_info[t[1]].append(t[2]) else: self._classes_info[t[1]]=[t[2]] count+=1 status +=1 for k in self._classes_info.keys(): print len(self._classes_info[k])*1.0/len(self.get_methods(k)) print count," method names of ",methods_num,"unique method names in project pretend to to be passed to common superclass"
def test_get_visibility(names, expected): for name in names: got = get_visibility(name) assert got == expected, "got %s instead of %s for value %s" % ( got, expected, name, )
def test_protected(self): for name in [ "_", "__", "___", "____", "_____", "___e__", "_nextsimple", "_filter_it_" ]: got = get_visibility(name) self.assertEqual( got, 'protected', 'got %s instead of protected for value %s' % (got, name))
def handle_assattr_self(self,node,ducks): if((node.expr.as_string()=="self") and (get_visibility(node.attrname)!= 'special')): if(not ducks.has_key(node.attrname)): self._ducks_count +=1 self._assigned_ducks +=1 ducks[node.attrname] = {'attrs':{},'methods':{},'type':[],'complex_type':None,'assigned':True} else: if(not ducks[node.attrname]['assigned']): ducks[node.attrname]['assigned'] = True self._assigned_ducks+=1 if(isinstance(node.parent, (Assign,AugAssign))): if(isinstance(node.parent.value, (Tuple,Dict,List))): ducks[node.attrname]['complex_type'] = node.parent.value.__class__.__name__
def handle_getattr_self(self,node,ducks): ''' Handle Getattr node during duck typing for "self" names access ducks - dictionary of processed ducks ''' if((node.expr.as_string()=="self") and (get_visibility(node.attrname)!= 'special')): if isinstance(node.parent, For): if(not ducks.has_key(node.attrname)): self._ducks_count +=1 ducks[node.attrname] = {'attrs':{},'methods':{},'type':[],'complex_type':'Unknown','assigned':False} if isinstance(node.parent.target, AssName): for body in node.parent.body: self._check_cycle(body, node.parent.target.name, node.attrname, ducks) if isinstance(node.parent, Getattr): """ if additional info about attr's field may be obtained """ if(not ducks.has_key(node.attrname)): self._ducks_count += 1 ducks[node.attrname] = {'attrs':{}, 'methods':{}, 'type':[], 'complex_type':None, 'assigned':False} if isinstance(node.parent.parent, CallFunc): """ we get info about attr's method """ self.add_duck_info(ducks[node.attrname],node.parent.attrname,'methods') else: """ we get info about attr's attr """ self.add_duck_info(ducks[node.attrname],node.parent.attrname,'attrs') elif isinstance(node.parent, Subscript): """ attr of complex type (list, dict, tuple etc.) """ if(not ducks.has_key(node.attrname)): self._ducks_count +=1 ducks[node.attrname] = {'attrs':{},'methods':{},'type':[],'complex_type':'Unknown','assigned':False} else: ducks[node.attrname]['complex_type'] = 'Unknown' if(isinstance(node.parent.parent,Getattr)): """ get some info about element of complex type """ if(not ducks[node.attrname].has_key('element_signature')): ducks[node.attrname]['element_signature']={'attrs':{},'methods':{}} if isinstance(node.parent.parent.parent,CallFunc): self.add_duck_info(ducks[node.attrname]['element_signature'],node.parent.parent.attrname,'methods') else: self.add_duck_info(ducks[node.attrname]['element_signature'],node.parent.parent.attrname,'attrs')
def test_private(self): for name in ["__g_", "____dsf", "__23_9"]: got = get_visibility(name) self.assertEqual(got, 'private', 'got %s instead of private for value %s' % (got, name))
def test_public(self): self.assertEqual(get_visibility('simple'), 'public')
def test_private(self): for name in ["__g_", "____dsf", "__23_9"]: got = get_visibility(name) self.assertEqual( got, 'private', 'got %s instead of private for value %s' % (got, name))
def test_special(self): for name in ["__reduce_ex__", "__setattr__"]: self.assertEqual(get_visibility(name), 'special')
def test_protected(self): for name in ["_","__", "___", "____", "_____", "___e__", "_nextsimple", "_filter_it_"]: got = get_visibility(name) self.assertEqual(got, 'protected', 'got %s instead of protected for value %s' % (got, name))
def test_get_visibility(names, expected): for name in names: got = get_visibility(name) assert got == expected, f"got {got} instead of {expected} for value {name}"
def test_public(self): self.assertEqual(get_visibility("simple"), "public")
def run(self, args): """checking arguments and run project""" if not args: print self.help() return project = self.manager.project_from_files(args, astng_wrapper) self.project = project linker = ClassIRLinker(project) linker.visit(project) if self._criteria == 'capacity': found_ducks = {} bad_ducks = {} prob_used_classes = {} for t in numpy.arange(self._treshold,1,0.05): found_ducks[t] = 0 bad_ducks[t] = 0 prob_used_classes[t] = set([]) else: prob_used_classes = set([]) bad_ducks = 0 found_ducks = 0 ducks_num = len(list(linker.get_ducks())) count = 1 dbg = set([]) empty_ducks = 0 """ Handle "duck" information and generate information about types """ for current_class in linker.get_classes(): for duck in current_class.cir_ducks.keys(): print "Processing ", count, " duck of ",ducks_num # print duck,current_class.cir_ducks[duck] count +=1 duck_attrs, duck_methods = self.get_duck_signature(current_class.cir_ducks[duck]) """ ignore empty ducks """ if((not duck_attrs) and (not duck_methods)): empty_ducks+=1 continue if not hasattr(current_class.cir_ducks[duck], 'complex_type'): """ if duck is not detected as complex type on previous stage (according to [],{} etc. usage) we need to check its methods and fields """ complex_type = self._check_complex_type(duck_attrs, duck_methods) if(complex_type): current_class.cir_ducks[duck]['complex_type'] = complex_type if self._criteria == 'capacity': for t in found_ducks.keys(): found_ducks[t]+=1 else: found_ducks+=1 continue if(self._criteria=='capacity'): ''' Results of candidate class search will be saved for different thresholds ''' duck_found = {} for t in numpy.arange(self._treshold,1,0.05): duck_found[t] = False else: duck_found = False for field_candidate in linker.get_classes(): result = self.check_candidate(duck_attrs, duck_methods, field_candidate,self._criteria) if self._criteria == 'capacity': if(result>= self._treshold): current_class.cir_ducks[duck]['type'].append(field_candidate) if self._add_value: ''' save value for candidate ''' if current_class.cir_ducks[duck].has_key('type_values'): current_class.cir_ducks[duck]['type_values'][field_candidate.cir_uid]=result else: current_class.cir_ducks[duck]['type_values']={field_candidate.cir_uid:result} for t in duck_found.keys(): ''' Save probably used classes for different thresholds ''' if(result>=t): prob_used_classes[t] |= set([field_candidate.cir_uid]) duck_found[t] = True else: if(result): current_class.cir_ducks[duck]['type'].append(field_candidate) prob_used_classes |= set([field_candidate.cir_uid]) ''' check if duck not found at all ''' if self._criteria =='capacity': for t in duck_found.keys(): if(not duck_found[t]): bad_ducks[t] += 1 else: found_ducks[t]+=1 else: if(not duck_found): bad_ducks += 1 else: found_ducks+=1 # empty_ducks = len(list(linker.get_empty_ducks())) # print len(dbg) # print dbg print "Project - ",self._project print "Duck typing criteria - ",self._criteria print "Numbers of classes: ",len(list(linker.get_classes())) print "Numbers of ducks(non-empty): ", linker.get_ducks_count()-empty_ducks print "Numbers of ducks with complex type: ", len(list(linker.get_complex_ducks())) if self._criteria == 'capacity': if(linker.get_ducks_count()!=empty_ducks): b = found_ducks.keys() for t in sorted(found_ducks.keys()): print t,"found ducks: ",found_ducks[t], " percentage from non-empty ducks: ",round(100*float(found_ducks[t])/(linker.get_ducks_count()-empty_ducks),1), " %" if(linker.get_attrs_count()!=0): for t in sorted(found_ducks.keys()): print t,"Numbers of all attributes in project: ", linker.get_attrs_count(), " percentage of found attrs: ",round(100*float(found_ducks[t])/linker.get_attrs_count(),1), " %" if(len(list(linker.get_classes()))!=0): for t in sorted(found_ducks.keys()): print t,"Probably used (as field) classes: ",len(prob_used_classes[t])," percentage: ",round(100*float(len(prob_used_classes[t]))/len(list(linker.get_classes())),1), " %" else: if(linker.get_ducks_count()!=empty_ducks): print "Found ducks: ",found_ducks, " percentage from non-empty ducks: ",round(100*float(found_ducks)/(linker.get_ducks_count()-empty_ducks),1), " %" if(linker.get_attrs_count()!=0): print "Numbers of all attributes in project: ", linker.get_attrs_count(), " percentage of found attrs: ",round(100*float(found_ducks)/linker.get_attrs_count(),1), " %" if(len(list(linker.get_classes()))!=0): print "Probably used (as field) classes: ",len(prob_used_classes)," percentage: ",round(100*float(len(prob_used_classes))/len(list(linker.get_classes())),1), " %" # result XML generation mapper = {} root = etree.Element("Classes") for obj in linker.get_classes(): self._all_classes +=1 node = etree.Element("Class",name=obj.name,fromlineno=str(obj.fromlineno),col_offset=str(obj.col_offset),id=str(obj.cir_uid),label=obj.root().name) mapper[obj] = node root.append(node) for attrname in obj.ucr_attrs: attr_node = etree.Element('Attr',name=attrname) mod_node = etree.Element('Modifier',name=get_visibility(attrname)) attr_node.append(mod_node) node.append(attr_node) if(attrname in obj.cir_ducks): if obj.cir_ducks[attrname]['complex_type']: for prob_type in obj.cir_ducks[attrname]['type']: attr_node.append(etree.Element('AggregatedType',name=str(obj.cir_ducks[attrname]['complex_type']),element_type=prob_type.name,element_id=str(prob_type.cir_uid))) else: for prob_type in obj.cir_ducks[attrname]['type']: if(obj.cir_ducks[attrname].has_key('type_values')): common_type_node = etree.Element('CommonType', name=prob_type.name, id=str(prob_type.cir_uid), type_value=str(obj.cir_ducks[attrname]['type_values'][prob_type.cir_uid])) else: common_type_node = etree.Element('CommonType', name=prob_type.name, id=str(prob_type.cir_uid)) attr_node.append(common_type_node) for meth in linker.get_methods(obj): meth_node = etree.Element('Method',name=meth.name) meth_node.set("fromlineno",str(meth.fromlineno)) meth_node.set("col_offset",str(meth.col_offset)) mod_node = etree.Element('Modifier',name=get_visibility(meth.name)) meth_node.append(mod_node) """ This is needed for some native libs(pyx) """ if(meth.args.args == None): continue for arg in meth.args.args: # ignore self arg if not arg.name == 'self': meth_node.append(etree.Element('Arg',name=arg.name)) node.append(meth_node) for rel in linker.get_inheritances(): mapper[rel[0]].append(etree.Element('Parent',name=rel[1].name,id=str(rel[1].cir_uid))) print "Writing ", self._out_file f = open(self._out_file,'w') f.write(etree.tostring(root, pretty_print=True, encoding='utf-8', xml_declaration=True)) f.close()
def handle_attrs(self,node,class_node): if class_node is None: return if isinstance(node, (AssAttr,Getattr)): if((node.expr.as_string()=="self") and (get_visibility(node.attrname)!= 'special')): class_node.ucr_attrs.add(node.attrname)
def visit_class(self,node): self._classes.append(node) node.ucr_attrs = set([item[0] for item in node.items() if (isinstance(item[1], AssName) and (get_visibility(item[0])!= 'special'))]) node.ucr_complete_attrs = node.ucr_attrs.copy()