Index: tools/telemetry/third_party/rope/rope/base/oi/objectinfo.py |
diff --git a/tools/telemetry/third_party/rope/rope/base/oi/objectinfo.py b/tools/telemetry/third_party/rope/rope/base/oi/objectinfo.py |
new file mode 100644 |
index 0000000000000000000000000000000000000000..f86d72e0b5cc26f2432aa678f7e5144451f5e8fa |
--- /dev/null |
+++ b/tools/telemetry/third_party/rope/rope/base/oi/objectinfo.py |
@@ -0,0 +1,232 @@ |
+import warnings |
+ |
+from rope.base import exceptions, resourceobserver |
+from rope.base.oi import objectdb, memorydb, transform |
+ |
+ |
+class ObjectInfoManager(object): |
+ """Stores object information |
+ |
+ It uses an instance of `objectdb.ObjectDB` for storing |
+ information. |
+ |
+ """ |
+ |
+ def __init__(self, project): |
+ self.project = project |
+ self.to_textual = transform.PyObjectToTextual(project) |
+ self.to_pyobject = transform.TextualToPyObject(project) |
+ self.doi_to_pyobject = transform.DOITextualToPyObject(project) |
+ self._init_objectdb() |
+ if project.prefs.get('validate_objectdb', False): |
+ self._init_validation() |
+ |
+ def _init_objectdb(self): |
+ dbtype = self.project.get_prefs().get('objectdb_type', None) |
+ persist = None |
+ if dbtype is not None: |
+ 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) |
+ if dbtype != 'memory' and self.project.ropefolder is not None: |
+ persist = True |
+ self.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 = [] |
+ for path in self.objectdb.get_files(): |
+ resource = self.to_pyobject.path_to_resource(path) |
+ if resource is not None and resource.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)) |
+ except exceptions.ModuleSyntaxError: |
+ pass |
+ |
+ def _resource_moved(self, resource, new_resource=None): |
+ self.observer.remove_resource(resource) |
+ if new_resource is not None: |
+ 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) |
+ |
+ def get_returned(self, pyobject, args): |
+ result = self.get_exact_returned(pyobject, args) |
+ if result is not None: |
+ return result |
+ path, key = self._get_scope(pyobject) |
+ if path is None: |
+ return None |
+ for call_info in self.objectdb.get_callinfos(path, key): |
+ returned = call_info.get_returned() |
+ if returned and returned[0] not in ('unknown', 'none'): |
+ result = returned |
+ break |
+ if result is None: |
+ result = returned |
+ if result is not None: |
+ return self.to_pyobject(result) |
+ |
+ def get_exact_returned(self, pyobject, args): |
+ path, key = self._get_scope(pyobject) |
+ if path is not None: |
+ returned = self.objectdb.get_returned( |
+ path, key, self._args_to_textual(pyobject, args)) |
+ if returned is not None: |
+ return self.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) |
+ for arg in arguments]) |
+ return textual_args |
+ |
+ def get_parameter_objects(self, pyobject): |
+ path, key = self._get_scope(pyobject) |
+ if path is None: |
+ return None |
+ arg_count = len(pyobject.get_param_names(special_args=False)) |
+ unknowns = arg_count |
+ parameters = [None] * arg_count |
+ for call_info in self.objectdb.get_callinfos(path, key): |
+ args = call_info.get_parameters() |
+ for index, arg in enumerate(args[:arg_count]): |
+ old = parameters[index] |
+ if self.validation.is_more_valid(arg, old): |
+ parameters[index] = arg |
+ if self.validation.is_value_valid(arg): |
+ unknowns -= 1 |
+ if unknowns == 0: |
+ break |
+ if unknowns < arg_count: |
+ return [self.to_pyobject(parameter) |
+ for parameter in parameters] |
+ |
+ def get_passed_objects(self, pyfunction, parameter_index): |
+ path, key = self._get_scope(pyfunction) |
+ if path is None: |
+ return [] |
+ result = [] |
+ for call_info in self.objectdb.get_callinfos(path, key): |
+ args = call_info.get_parameters() |
+ if len(args) > parameter_index: |
+ parameter = self.to_pyobject(args[parameter_index]) |
+ if parameter is not None: |
+ result.append(parameter) |
+ return result |
+ |
+ def doa_data_received(self, data): |
+ def doi_to_normal(textual): |
+ pyobject = self.doi_to_pyobject(textual) |
+ return self.to_textual(pyobject) |
+ function = doi_to_normal(data[0]) |
+ args = tuple([doi_to_normal(textual) for textual in data[1]]) |
+ returned = doi_to_normal(data[2]) |
+ if function[0] == 'defined' and len(function) == 3: |
+ self._save_data(function, args, returned) |
+ |
+ def function_called(self, pyfunction, params, returned=None): |
+ function_text = self.to_textual(pyfunction) |
+ params_text = tuple([self.to_textual(param) |
+ for param in params]) |
+ returned_text = ('unknown',) |
+ if returned is not None: |
+ returned_text = self.to_textual(returned) |
+ self._save_data(function_text, params_text, returned_text) |
+ |
+ def save_per_name(self, scope, name, data): |
+ path, key = self._get_scope(scope.pyobject) |
+ if path is not None: |
+ self.objectdb.add_pername(path, key, name, self.to_textual(data)) |
+ |
+ def get_per_name(self, scope, name): |
+ path, key = self._get_scope(scope.pyobject) |
+ if path is not None: |
+ result = self.objectdb.get_pername(path, key, name) |
+ if result is not None: |
+ return self.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() |
+ if resource is None: |
+ return None, None |
+ textual = self.to_textual(pyobject) |
+ if textual[0] == 'defined': |
+ path = textual[1] |
+ if len(textual) == 3: |
+ key = textual[2] |
+ else: |
+ key = '' |
+ return path, key |
+ return None, None |
+ |
+ def sync(self): |
+ self.objectdb.sync() |
+ |
+ def __str__(self): |
+ return str(self.objectdb) |
+ |
+ |
+class TextualValidation(object): |
+ |
+ def __init__(self, to_pyobject): |
+ self.to_pyobject = to_pyobject |
+ |
+ def is_value_valid(self, value): |
+ # ???: Should none and unknown be considered valid? |
+ if value is None or value[0] in ('none', 'unknown'): |
+ return False |
+ return self.to_pyobject(value) is not None |
+ |
+ def is_more_valid(self, new, old): |
+ if old is None: |
+ return True |
+ return new[0] not in ('unknown', 'none') |
+ |
+ def is_file_valid(self, path): |
+ return self.to_pyobject.path_to_resource(path) is not None |
+ |
+ def is_scope_valid(self, path, key): |
+ if key == '': |
+ textual = ('defined', path) |
+ else: |
+ textual = ('defined', path, key) |
+ return self.to_pyobject(textual) is not None |
+ |
+ |
+class _FileListObserver(object): |
+ |
+ def __init__(self, object_info): |
+ self.object_info = object_info |
+ self.observer = self.object_info.observer |
+ self.to_pyobject = self.object_info.to_pyobject |
+ |
+ def removed(self, path): |
+ resource = self.to_pyobject.path_to_resource(path) |
+ if resource is not None: |
+ self.observer.remove_resource(resource) |
+ |
+ def added(self, path): |
+ resource = self.to_pyobject.path_to_resource(path) |
+ if resource is not None: |
+ self.observer.add_resource(resource) |