importwarningsfromrope.baseimportexceptions,resourceobserverfromrope.base.oiimportobjectdb,memorydb,transformclassObjectInfoManager(object):"""Stores object information It uses an instance of `objectdb.ObjectDB` for storing information. """def__init__(self,project):self.project=projectself.to_textual=transform.PyObjectToTextual(project)self.to_pyobject=transform.TextualToPyObject(project)self.doi_to_pyobject=transform.DOITextualToPyObject(project)self._init_objectdb()ifproject.prefs.get('validate_objectdb',False):self._init_validation()def_init_objectdb(self):dbtype=self.project.get_prefs().get('objectdb_type',None)persist=NoneifdbtypeisnotNone:warnings.warn('"objectdb_type" project config is deprecated;\n''Use "save_objectdb" instead in your project ''config file.\n(".ropeproject/config.py" by default)\n',DeprecationWarning)ifdbtype!='memory'andself.project.ropefolderisnotNone:persist=Trueself.validation=TextualValidation(self.to_pyobject)db=memorydb.MemoryDB(self.project,persist=persist)self.objectdb=objectdb.ObjectDB(db,self.validation)def_init_validation(self):self.objectdb.validate_files()observer=resourceobserver.ResourceObserver(changed=self._resource_changed,moved=self._resource_moved,removed=self._resource_moved)files=[]forpathinself.objectdb.get_files():resource=self.to_pyobject.path_to_resource(path)ifresourceisnotNoneandresource.project==self.project:files.append(resource)self.observer=resourceobserver.FilteredResourceObserver(observer,files)self.objectdb.add_file_list_observer(_FileListObserver(self))self.project.add_observer(self.observer)def_resource_changed(self,resource):try:self.objectdb.validate_file(self.to_textual.resource_to_path(resource))exceptexceptions.ModuleSyntaxError:passdef_resource_moved(self,resource,new_resource=None):self.observer.remove_resource(resource)ifnew_resourceisnotNone:old=self.to_textual.resource_to_path(resource)new=self.to_textual.resource_to_path(new_resource)self.objectdb.file_moved(old,new)self.observer.add_resource(new_resource)defget_returned(self,pyobject,args):result=self.get_exact_returned(pyobject,args)ifresultisnotNone:returnresultpath,key=self._get_scope(pyobject)ifpathisNone:returnNoneforcall_infoinself.objectdb.get_callinfos(path,key):returned=call_info.get_returned()ifreturnedandreturned[0]notin('unknown','none'):result=returnedbreakifresultisNone:result=returnedifresultisnotNone:returnself.to_pyobject(result)defget_exact_returned(self,pyobject,args):path,key=self._get_scope(pyobject)ifpathisnotNone:returned=self.objectdb.get_returned(path,key,self._args_to_textual(pyobject,args))ifreturnedisnotNone:returnself.to_pyobject(returned)def_args_to_textual(self,pyfunction,args):parameters=list(pyfunction.get_param_names(special_args=False))arguments=args.get_arguments(parameters)[:len(parameters)]textual_args=tuple([self.to_textual(arg)forarginarguments])returntextual_argsdefget_parameter_objects(self,pyobject):path,key=self._get_scope(pyobject)ifpathisNone:returnNonearg_count=len(pyobject.get_param_names(special_args=False))unknowns=arg_countparameters=[None]*arg_countforcall_infoinself.objectdb.get_callinfos(path,key):args=call_info.get_parameters()forindex,arginenumerate(args[:arg_count]):old=parameters[index]ifself.validation.is_more_valid(arg,old):parameters[index]=argifself.validation.is_value_valid(arg):unknowns-=1ifunknowns==0:breakifunknowns<arg_count:return[self.to_pyobject(parameter)forparameterinparameters]defget_passed_objects(self,pyfunction,parameter_index):path,key=self._get_scope(pyfunction)ifpathisNone:return[]result=[]forcall_infoinself.objectdb.get_callinfos(path,key):args=call_info.get_parameters()iflen(args)>parameter_index:parameter=self.to_pyobject(args[parameter_index])ifparameterisnotNone:result.append(parameter)returnresultdefdoa_data_received(self,data):defdoi_to_normal(textual):pyobject=self.doi_to_pyobject(textual)returnself.to_textual(pyobject)function=doi_to_normal(data[0])args=tuple([doi_to_normal(textual)fortextualindata[1]])returned=doi_to_normal(data[2])iffunction[0]=='defined'andlen(function)==3:self._save_data(function,args,returned)deffunction_called(self,pyfunction,params,returned=None):function_text=self.to_textual(pyfunction)params_text=tuple([self.to_textual(param)forparaminparams])returned_text=('unknown',)ifreturnedisnotNone:returned_text=self.to_textual(returned)self._save_data(function_text,params_text,returned_text)defsave_per_name(self,scope,name,data):path,key=self._get_scope(scope.pyobject)ifpathisnotNone:self.objectdb.add_pername(path,key,name,self.to_textual(data))defget_per_name(self,scope,name):path,key=self._get_scope(scope.pyobject)ifpathisnotNone:result=self.objectdb.get_pername(path,key,name)ifresultisnotNone:returnself.to_pyobject(result)def_save_data(self,function,args,returned=('unknown',)):self.objectdb.add_callinfo(function[1],function[2],args,returned)def_get_scope(self,pyobject):resource=pyobject.get_module().get_resource()ifresourceisNone:returnNone,Nonetextual=self.to_textual(pyobject)iftextual[0]=='defined':path=textual[1]iflen(textual)==3:key=textual[2]else:key=''returnpath,keyreturnNone,Nonedefsync(self):self.objectdb.sync()def__str__(self):returnstr(self.objectdb)classTextualValidation(object):def__init__(self,to_pyobject):self.to_pyobject=to_pyobjectdefis_value_valid(self,value):# ???: Should none and unknown be considered valid?ifvalueisNoneorvalue[0]in('none','unknown'):returnFalsereturnself.to_pyobject(value)isnotNonedefis_more_valid(self,new,old):ifoldisNone:returnTruereturnnew[0]notin('unknown','none')defis_file_valid(self,path):returnself.to_pyobject.path_to_resource(path)isnotNonedefis_scope_valid(self,path,key):ifkey=='':textual=('defined',path)else:textual=('defined',path,key)returnself.to_pyobject(textual)isnotNoneclass_FileListObserver(object):def__init__(self,object_info):self.object_info=object_infoself.observer=self.object_info.observerself.to_pyobject=self.object_info.to_pyobjectdefremoved(self,path):resource=self.to_pyobject.path_to_resource(path)ifresourceisnotNone:self.observer.remove_resource(resource)defadded(self,path):resource=self.to_pyobject.path_to_resource(path)ifresourceisnotNone:self.observer.add_resource(resource)