Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(140)

Unified Diff: tools/telemetry/third_party/rope/rope/base/pyobjects.py

Issue 1132103009: Example of refactoring using rope library. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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
« no previous file with comments | « tools/telemetry/third_party/rope/rope/base/pynamesdef.py ('k') | tools/telemetry/third_party/rope/rope/base/pyobjectsdef.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698