Path: blob/master/elisp/emacs-for-python/rope-dist/rope/base/oi/objectinfo.py
1421 views
import warnings12from rope.base import exceptions, resourceobserver3from rope.base.oi import objectdb, memorydb, transform456class ObjectInfoManager(object):7"""Stores object information89It uses an instance of `objectdb.ObjectDB` for storing10information.1112"""1314def __init__(self, project):15self.project = project16self.to_textual = transform.PyObjectToTextual(project)17self.to_pyobject = transform.TextualToPyObject(project)18self.doi_to_pyobject = transform.DOITextualToPyObject(project)19self._init_objectdb()20if project.prefs.get('validate_objectdb', False):21self._init_validation()2223def _init_objectdb(self):24dbtype = self.project.get_prefs().get('objectdb_type', None)25persist = None26if dbtype is not None:27warnings.warn(28'"objectdb_type" project config is deprecated;\n'29'Use "save_objectdb" instead in your project '30'config file.\n(".ropeproject/config.py" by default)\n',31DeprecationWarning)32if dbtype != 'memory' and self.project.ropefolder is not None:33persist = True34self.validation = TextualValidation(self.to_pyobject)35db = memorydb.MemoryDB(self.project, persist=persist)36self.objectdb = objectdb.ObjectDB(db, self.validation)3738def _init_validation(self):39self.objectdb.validate_files()40observer = resourceobserver.ResourceObserver(41changed=self._resource_changed, moved=self._resource_moved,42removed=self._resource_moved)43files = []44for path in self.objectdb.get_files():45resource = self.to_pyobject.path_to_resource(path)46if resource is not None and resource.project == self.project:47files.append(resource)48self.observer = resourceobserver.FilteredResourceObserver(observer,49files)50self.objectdb.add_file_list_observer(_FileListObserver(self))51self.project.add_observer(self.observer)5253def _resource_changed(self, resource):54try:55self.objectdb.validate_file(56self.to_textual.resource_to_path(resource))57except exceptions.ModuleSyntaxError:58pass5960def _resource_moved(self, resource, new_resource=None):61self.observer.remove_resource(resource)62if new_resource is not None:63old = self.to_textual.resource_to_path(resource)64new = self.to_textual.resource_to_path(new_resource)65self.objectdb.file_moved(old, new)66self.observer.add_resource(new_resource)6768def get_returned(self, pyobject, args):69result = self.get_exact_returned(pyobject, args)70if result is not None:71return result72path, key = self._get_scope(pyobject)73if path is None:74return None75for call_info in self.objectdb.get_callinfos(path, key):76returned = call_info.get_returned()77if returned and returned[0] not in ('unknown', 'none'):78result = returned79break80if result is None:81result = returned82if result is not None:83return self.to_pyobject(result)8485def get_exact_returned(self, pyobject, args):86path, key = self._get_scope(pyobject)87if path is not None:88returned = self.objectdb.get_returned(89path, key, self._args_to_textual(pyobject, args))90if returned is not None:91return self.to_pyobject(returned)9293def _args_to_textual(self, pyfunction, args):94parameters = list(pyfunction.get_param_names(special_args=False))95arguments = args.get_arguments(parameters)[:len(parameters)]96textual_args = tuple([self.to_textual(arg)97for arg in arguments])98return textual_args99100def get_parameter_objects(self, pyobject):101path, key = self._get_scope(pyobject)102if path is None:103return None104arg_count = len(pyobject.get_param_names(special_args=False))105unknowns = arg_count106parameters = [None] * arg_count107for call_info in self.objectdb.get_callinfos(path, key):108args = call_info.get_parameters()109for index, arg in enumerate(args[:arg_count]):110old = parameters[index]111if self.validation.is_more_valid(arg, old):112parameters[index] = arg113if self.validation.is_value_valid(arg):114unknowns -= 1115if unknowns == 0:116break117if unknowns < arg_count:118return [self.to_pyobject(parameter)119for parameter in parameters]120121def get_passed_objects(self, pyfunction, parameter_index):122path, key = self._get_scope(pyfunction)123if path is None:124return []125result = []126for call_info in self.objectdb.get_callinfos(path, key):127args = call_info.get_parameters()128if len(args) > parameter_index:129parameter = self.to_pyobject(args[parameter_index])130if parameter is not None:131result.append(parameter)132return result133134def doa_data_received(self, data):135def doi_to_normal(textual):136pyobject = self.doi_to_pyobject(textual)137return self.to_textual(pyobject)138function = doi_to_normal(data[0])139args = tuple([doi_to_normal(textual) for textual in data[1]])140returned = doi_to_normal(data[2])141if function[0] == 'defined' and len(function) == 3:142self._save_data(function, args, returned)143144def function_called(self, pyfunction, params, returned=None):145function_text = self.to_textual(pyfunction)146params_text = tuple([self.to_textual(param)147for param in params])148returned_text = ('unknown',)149if returned is not None:150returned_text = self.to_textual(returned)151self._save_data(function_text, params_text, returned_text)152153def save_per_name(self, scope, name, data):154path, key = self._get_scope(scope.pyobject)155if path is not None:156self.objectdb.add_pername(path, key, name, self.to_textual(data))157158def get_per_name(self, scope, name):159path, key = self._get_scope(scope.pyobject)160if path is not None:161result = self.objectdb.get_pername(path, key, name)162if result is not None:163return self.to_pyobject(result)164165def _save_data(self, function, args, returned=('unknown',)):166self.objectdb.add_callinfo(function[1], function[2], args, returned)167168def _get_scope(self, pyobject):169resource = pyobject.get_module().get_resource()170if resource is None:171return None, None172textual = self.to_textual(pyobject)173if textual[0] == 'defined':174path = textual[1]175if len(textual) == 3:176key = textual[2]177else:178key = ''179return path, key180return None, None181182def sync(self):183self.objectdb.sync()184185def __str__(self):186return str(self.objectdb)187188189class TextualValidation(object):190191def __init__(self, to_pyobject):192self.to_pyobject = to_pyobject193194def is_value_valid(self, value):195# ???: Should none and unknown be considered valid?196if value is None or value[0] in ('none', 'unknown'):197return False198return self.to_pyobject(value) is not None199200def is_more_valid(self, new, old):201if old is None:202return True203return new[0] not in ('unknown', 'none')204205def is_file_valid(self, path):206return self.to_pyobject.path_to_resource(path) is not None207208def is_scope_valid(self, path, key):209if key == '':210textual = ('defined', path)211else:212textual = ('defined', path, key)213return self.to_pyobject(textual) is not None214215216class _FileListObserver(object):217218def __init__(self, object_info):219self.object_info = object_info220self.observer = self.object_info.observer221self.to_pyobject = self.object_info.to_pyobject222223def removed(self, path):224resource = self.to_pyobject.path_to_resource(path)225if resource is not None:226self.observer.remove_resource(resource)227228def added(self, path):229resource = self.to_pyobject.path_to_resource(path)230if resource is not None:231self.observer.add_resource(resource)232233234