Index: tools/telemetry/third_party/rope/rope/base/oi/soi.py |
diff --git a/tools/telemetry/third_party/rope/rope/base/oi/soi.py b/tools/telemetry/third_party/rope/rope/base/oi/soi.py |
new file mode 100644 |
index 0000000000000000000000000000000000000000..5a11b5efdf30b218a926e54e4051151a4025f91a |
--- /dev/null |
+++ b/tools/telemetry/third_party/rope/rope/base/oi/soi.py |
@@ -0,0 +1,197 @@ |
+"""A module for inferring objects |
+ |
+For more information see the documentation in `rope.base.oi` |
+package. |
+ |
+""" |
+import rope.base.builtins |
+import rope.base.pynames |
+import rope.base.pyobjects |
+from rope.base import evaluate, utils, arguments |
+ |
+ |
+_ignore_inferred = utils.ignore_exception( |
+ rope.base.pyobjects.IsBeingInferredError) |
+ |
+ |
+@_ignore_inferred |
+def infer_returned_object(pyfunction, args): |
+ """Infer the `PyObject` this `PyFunction` returns after calling""" |
+ object_info = pyfunction.pycore.object_info |
+ result = object_info.get_exact_returned(pyfunction, args) |
+ if result is not None: |
+ return result |
+ result = _infer_returned(pyfunction, args) |
+ if result is not None: |
+ if args and pyfunction.get_module().get_resource() is not None: |
+ params = args.get_arguments( |
+ pyfunction.get_param_names(special_args=False)) |
+ object_info.function_called(pyfunction, params, result) |
+ return result |
+ return object_info.get_returned(pyfunction, args) |
+ |
+ |
+@_ignore_inferred |
+def infer_parameter_objects(pyfunction): |
+ """Infer the `PyObject`\s of parameters of this `PyFunction`""" |
+ object_info = pyfunction.pycore.object_info |
+ result = object_info.get_parameter_objects(pyfunction) |
+ if result is None: |
+ result = _parameter_objects(pyfunction) |
+ _handle_first_parameter(pyfunction, result) |
+ return result |
+ |
+ |
+def _handle_first_parameter(pyobject, parameters): |
+ kind = pyobject.get_kind() |
+ if parameters is None or kind not in ['method', 'classmethod']: |
+ pass |
+ if not parameters: |
+ if not pyobject.get_param_names(special_args=False): |
+ return |
+ parameters.append(rope.base.pyobjects.get_unknown()) |
+ if kind == 'method': |
+ parameters[0] = rope.base.pyobjects.PyObject(pyobject.parent) |
+ if kind == 'classmethod': |
+ parameters[0] = pyobject.parent |
+ |
+ |
+@_ignore_inferred |
+def infer_assigned_object(pyname): |
+ if not pyname.assignments: |
+ return |
+ for assignment in reversed(pyname.assignments): |
+ result = _infer_assignment(assignment, pyname.module) |
+ if result is not None: |
+ return result |
+ |
+ |
+def get_passed_objects(pyfunction, parameter_index): |
+ object_info = pyfunction.pycore.object_info |
+ result = object_info.get_passed_objects(pyfunction, |
+ parameter_index) |
+ if not result: |
+ statically_inferred = _parameter_objects(pyfunction) |
+ if len(statically_inferred) > parameter_index: |
+ result.append(statically_inferred[parameter_index]) |
+ return result |
+ |
+ |
+def _infer_returned(pyobject, args): |
+ if args: |
+ # HACK: Setting parameter objects manually |
+ # This is not thread safe and might cause problems if `args` |
+ # does not come from a good call site |
+ pyobject.get_scope().invalidate_data() |
+ pyobject._set_parameter_pyobjects( |
+ args.get_arguments(pyobject.get_param_names(special_args=False))) |
+ scope = pyobject.get_scope() |
+ if not scope._get_returned_asts(): |
+ return |
+ maxtries = 3 |
+ for returned_node in reversed(scope._get_returned_asts()[-maxtries:]): |
+ try: |
+ resulting_pyname = evaluate.eval_node(scope, returned_node) |
+ if resulting_pyname is None: |
+ continue |
+ pyobject = resulting_pyname.get_object() |
+ if pyobject == rope.base.pyobjects.get_unknown(): |
+ continue |
+ if not scope._is_generator(): |
+ return pyobject |
+ else: |
+ return rope.base.builtins.get_generator(pyobject) |
+ except rope.base.pyobjects.IsBeingInferredError: |
+ pass |
+ |
+ |
+def _parameter_objects(pyobject): |
+ params = pyobject.get_param_names(special_args=False) |
+ return [rope.base.pyobjects.get_unknown()] * len(params) |
+ |
+# handling `rope.base.pynames.AssignmentValue` |
+ |
+ |
+@_ignore_inferred |
+def _infer_assignment(assignment, pymodule): |
+ result = _follow_pyname(assignment, pymodule) |
+ if result is None: |
+ return None |
+ pyname, pyobject = result |
+ pyobject = _follow_evaluations(assignment, pyname, pyobject) |
+ if pyobject is None: |
+ return None |
+ return _follow_levels(assignment, pyobject) |
+ |
+ |
+def _follow_levels(assignment, pyobject): |
+ for index in assignment.levels: |
+ if isinstance(pyobject.get_type(), rope.base.builtins.Tuple): |
+ holdings = pyobject.get_type().get_holding_objects() |
+ if holdings: |
+ pyobject = holdings[min(len(holdings) - 1, index)] |
+ else: |
+ pyobject = None |
+ elif isinstance(pyobject.get_type(), rope.base.builtins.List): |
+ pyobject = pyobject.get_type().holding |
+ else: |
+ pyobject = None |
+ if pyobject is None: |
+ break |
+ return pyobject |
+ |
+ |
+@_ignore_inferred |
+def _follow_pyname(assignment, pymodule, lineno=None): |
+ assign_node = assignment.ast_node |
+ if lineno is None: |
+ lineno = _get_lineno_for_node(assign_node) |
+ holding_scope = pymodule.get_scope().get_inner_scope_for_line(lineno) |
+ pyname = evaluate.eval_node(holding_scope, assign_node) |
+ if pyname is not None: |
+ result = pyname.get_object() |
+ if isinstance(result.get_type(), rope.base.builtins.Property) and \ |
+ holding_scope.get_kind() == 'Class': |
+ arg = rope.base.pynames.UnboundName( |
+ rope.base.pyobjects.PyObject(holding_scope.pyobject)) |
+ return pyname, result.get_type().get_property_object( |
+ arguments.ObjectArguments([arg])) |
+ return pyname, result |
+ |
+ |
+@_ignore_inferred |
+def _follow_evaluations(assignment, pyname, pyobject): |
+ new_pyname = pyname |
+ tokens = assignment.evaluation.split('.') |
+ for token in tokens: |
+ call = token.endswith('()') |
+ if call: |
+ token = token[:-2] |
+ if token: |
+ pyname = new_pyname |
+ new_pyname = _get_attribute(pyobject, token) |
+ if new_pyname is not None: |
+ pyobject = new_pyname.get_object() |
+ if pyobject is not None and call: |
+ if isinstance(pyobject, rope.base.pyobjects.AbstractFunction): |
+ args = arguments.ObjectArguments([pyname]) |
+ pyobject = pyobject.get_returned_object(args) |
+ else: |
+ pyobject = None |
+ if pyobject is None: |
+ break |
+ if pyobject is not None and assignment.assign_type: |
+ return rope.base.pyobjects.PyObject(pyobject) |
+ return pyobject |
+ |
+ |
+def _get_lineno_for_node(assign_node): |
+ if hasattr(assign_node, 'lineno') and \ |
+ assign_node.lineno is not None: |
+ return assign_node.lineno |
+ return 1 |
+ |
+ |
+def _get_attribute(pyobject, name): |
+ if pyobject is not None and name in pyobject: |
+ return pyobject[name] |