| Index: tools/telemetry/third_party/rope/rope/base/pyobjects.py
|
| diff --git a/tools/telemetry/third_party/rope/rope/base/pyobjects.py b/tools/telemetry/third_party/rope/rope/base/pyobjects.py
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..76be304036b8338a037697b74185af8700dc9e04
|
| --- /dev/null
|
| +++ b/tools/telemetry/third_party/rope/rope/base/pyobjects.py
|
| @@ -0,0 +1,311 @@
|
| +from rope.base.fscommands import _decode_data
|
| +from rope.base import ast, exceptions, utils
|
| +
|
| +
|
| +class PyObject(object):
|
| +
|
| + def __init__(self, type_):
|
| + if type_ is None:
|
| + type_ = self
|
| + self.type = type_
|
| +
|
| + def get_attributes(self):
|
| + if self.type is self:
|
| + return {}
|
| + return self.type.get_attributes()
|
| +
|
| + def get_attribute(self, name):
|
| + if name not in self.get_attributes():
|
| + raise exceptions.AttributeNotFoundError(
|
| + 'Attribute %s not found' % name)
|
| + return self.get_attributes()[name]
|
| +
|
| + def get_type(self):
|
| + return self.type
|
| +
|
| + def __getitem__(self, key):
|
| + """The same as ``get_attribute(key)``"""
|
| + return self.get_attribute(key)
|
| +
|
| + def __contains__(self, key):
|
| + """The same as ``key in self.get_attributes()``"""
|
| + return key in self.get_attributes()
|
| +
|
| + def __eq__(self, obj):
|
| + """Check the equality of two `PyObject`\s
|
| +
|
| + Currently it is assumed that instances (the direct instances
|
| + of `PyObject`, not the instances of its subclasses) are equal
|
| + if their types are equal. For every other object like
|
| + defineds or builtins rope assumes objects are reference
|
| + objects and their identities should match.
|
| +
|
| + """
|
| + if self.__class__ != obj.__class__:
|
| + return False
|
| + if type(self) == PyObject:
|
| + if self is not self.type:
|
| + return self.type == obj.type
|
| + else:
|
| + return self.type is obj.type
|
| + return self is obj
|
| +
|
| + def __ne__(self, obj):
|
| + return not self.__eq__(obj)
|
| +
|
| + def __hash__(self):
|
| + """See docs for `__eq__()` method"""
|
| + if type(self) == PyObject and self != self.type:
|
| + return hash(self.type) + 1
|
| + else:
|
| + return super(PyObject, self).__hash__()
|
| +
|
| + def __iter__(self):
|
| + """The same as ``iter(self.get_attributes())``"""
|
| + return iter(self.get_attributes())
|
| +
|
| + _types = None
|
| + _unknown = None
|
| +
|
| + @staticmethod
|
| + def _get_base_type(name):
|
| + if PyObject._types is None:
|
| + PyObject._types = {}
|
| + base_type = PyObject(None)
|
| + PyObject._types['Type'] = base_type
|
| + PyObject._types['Module'] = PyObject(base_type)
|
| + PyObject._types['Function'] = PyObject(base_type)
|
| + PyObject._types['Unknown'] = PyObject(base_type)
|
| + return PyObject._types[name]
|
| +
|
| +
|
| +def get_base_type(name):
|
| + """Return the base type with name `name`.
|
| +
|
| + The base types are 'Type', 'Function', 'Module' and 'Unknown'. It
|
| + was used to check the type of a `PyObject` but currently its use
|
| + is discouraged. Use classes defined in this module instead.
|
| + For example instead of
|
| + ``pyobject.get_type() == get_base_type('Function')`` use
|
| + ``isinstance(pyobject, AbstractFunction)``.
|
| +
|
| + You can use `AbstractClass` for classes, `AbstractFunction` for
|
| + functions, and `AbstractModule` for modules. You can also use
|
| + `PyFunction` and `PyClass` for testing if an object is
|
| + defined somewhere and rope can access its source. These classes
|
| + provide more methods.
|
| +
|
| + """
|
| + return PyObject._get_base_type(name)
|
| +
|
| +
|
| +def get_unknown():
|
| + """Return a pyobject whose type is unknown
|
| +
|
| + Note that two unknown objects are equal. So for example you can
|
| + write::
|
| +
|
| + if pyname.get_object() == get_unknown():
|
| + print 'cannot determine what this pyname holds'
|
| +
|
| + Rope could have used `None` for indicating unknown objects but
|
| + we had to check that in many places. So actually this method
|
| + returns a null object.
|
| +
|
| + """
|
| + if PyObject._unknown is None:
|
| + PyObject._unknown = PyObject(get_base_type('Unknown'))
|
| + return PyObject._unknown
|
| +
|
| +
|
| +class AbstractClass(PyObject):
|
| +
|
| + def __init__(self):
|
| + super(AbstractClass, self).__init__(get_base_type('Type'))
|
| +
|
| + def get_name(self):
|
| + pass
|
| +
|
| + def get_doc(self):
|
| + pass
|
| +
|
| + def get_superclasses(self):
|
| + return []
|
| +
|
| +
|
| +class AbstractFunction(PyObject):
|
| +
|
| + def __init__(self):
|
| + super(AbstractFunction, self).__init__(get_base_type('Function'))
|
| +
|
| + def get_name(self):
|
| + pass
|
| +
|
| + def get_doc(self):
|
| + pass
|
| +
|
| + def get_param_names(self, special_args=True):
|
| + return []
|
| +
|
| + def get_returned_object(self, args):
|
| + return get_unknown()
|
| +
|
| +
|
| +class AbstractModule(PyObject):
|
| +
|
| + def __init__(self, doc=None):
|
| + super(AbstractModule, self).__init__(get_base_type('Module'))
|
| +
|
| + def get_doc(self):
|
| + pass
|
| +
|
| + def get_resource(self):
|
| + pass
|
| +
|
| +
|
| +class PyDefinedObject(object):
|
| + """Python defined names that rope can access their sources"""
|
| +
|
| + def __init__(self, pycore, ast_node, parent):
|
| + self.pycore = pycore
|
| + self.ast_node = ast_node
|
| + self.scope = None
|
| + self.parent = parent
|
| + self.structural_attributes = None
|
| + self.concluded_attributes = self.get_module()._get_concluded_data()
|
| + self.attributes = self.get_module()._get_concluded_data()
|
| + self.defineds = None
|
| +
|
| + visitor_class = None
|
| +
|
| + @utils.prevent_recursion(lambda: {})
|
| + def _get_structural_attributes(self):
|
| + if self.structural_attributes is None:
|
| + self.structural_attributes = self._create_structural_attributes()
|
| + return self.structural_attributes
|
| +
|
| + @utils.prevent_recursion(lambda: {})
|
| + def _get_concluded_attributes(self):
|
| + if self.concluded_attributes.get() is None:
|
| + self._get_structural_attributes()
|
| + self.concluded_attributes.set(self._create_concluded_attributes())
|
| + return self.concluded_attributes.get()
|
| +
|
| + def get_attributes(self):
|
| + if self.attributes.get() is None:
|
| + result = dict(self._get_concluded_attributes())
|
| + result.update(self._get_structural_attributes())
|
| + self.attributes.set(result)
|
| + return self.attributes.get()
|
| +
|
| + def get_attribute(self, name):
|
| + if name in self._get_structural_attributes():
|
| + return self._get_structural_attributes()[name]
|
| + if name in self._get_concluded_attributes():
|
| + return self._get_concluded_attributes()[name]
|
| + raise exceptions.AttributeNotFoundError('Attribute %s not found' %
|
| + name)
|
| +
|
| + def get_scope(self):
|
| + if self.scope is None:
|
| + self.scope = self._create_scope()
|
| + return self.scope
|
| +
|
| + def get_module(self):
|
| + current_object = self
|
| + while current_object.parent is not None:
|
| + current_object = current_object.parent
|
| + return current_object
|
| +
|
| + def get_doc(self):
|
| + if len(self.get_ast().body) > 0:
|
| + expr = self.get_ast().body[0]
|
| + if isinstance(expr, ast.Expr) and \
|
| + isinstance(expr.value, ast.Str):
|
| + docstring = expr.value.s
|
| + coding = self.get_module().coding
|
| + return _decode_data(docstring, coding)
|
| +
|
| + def _get_defined_objects(self):
|
| + if self.defineds is None:
|
| + self._get_structural_attributes()
|
| + return self.defineds
|
| +
|
| + def _create_structural_attributes(self):
|
| + if self.visitor_class is None:
|
| + return {}
|
| + new_visitor = self.visitor_class(self.pycore, self)
|
| + for child in ast.get_child_nodes(self.ast_node):
|
| + ast.walk(child, new_visitor)
|
| + self.defineds = new_visitor.defineds
|
| + return new_visitor.names
|
| +
|
| + def _create_concluded_attributes(self):
|
| + return {}
|
| +
|
| + def get_ast(self):
|
| + return self.ast_node
|
| +
|
| + def _create_scope(self):
|
| + pass
|
| +
|
| +
|
| +class PyFunction(PyDefinedObject, AbstractFunction):
|
| + """Only a placeholder"""
|
| +
|
| +
|
| +class PyClass(PyDefinedObject, AbstractClass):
|
| + """Only a placeholder"""
|
| +
|
| +
|
| +class _ConcludedData(object):
|
| +
|
| + def __init__(self):
|
| + self.data_ = None
|
| +
|
| + def set(self, data):
|
| + self.data_ = data
|
| +
|
| + def get(self):
|
| + return self.data_
|
| +
|
| + data = property(get, set)
|
| +
|
| + def _invalidate(self):
|
| + self.data = None
|
| +
|
| + def __str__(self):
|
| + return '<' + str(self.data) + '>'
|
| +
|
| +
|
| +class _PyModule(PyDefinedObject, AbstractModule):
|
| +
|
| + def __init__(self, pycore, ast_node, resource):
|
| + self.resource = resource
|
| + self.concluded_data = []
|
| + AbstractModule.__init__(self)
|
| + PyDefinedObject.__init__(self, pycore, ast_node, None)
|
| +
|
| + def _get_concluded_data(self):
|
| + new_data = _ConcludedData()
|
| + self.concluded_data.append(new_data)
|
| + return new_data
|
| +
|
| + def _forget_concluded_data(self):
|
| + for data in self.concluded_data:
|
| + data._invalidate()
|
| +
|
| + def get_resource(self):
|
| + return self.resource
|
| +
|
| +
|
| +class PyModule(_PyModule):
|
| + """Only a placeholder"""
|
| +
|
| +
|
| +class PyPackage(_PyModule):
|
| + """Only a placeholder"""
|
| +
|
| +
|
| +class IsBeingInferredError(exceptions.RopeError):
|
| + pass
|
|
|