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

Unified Diff: tools/telemetry/third_party/rope/rope/base/pyscopes.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/pyscopes.py
diff --git a/tools/telemetry/third_party/rope/rope/base/pyscopes.py b/tools/telemetry/third_party/rope/rope/base/pyscopes.py
new file mode 100644
index 0000000000000000000000000000000000000000..0bed19a92912ccda603e3f470ca48154c417bb59
--- /dev/null
+++ b/tools/telemetry/third_party/rope/rope/base/pyscopes.py
@@ -0,0 +1,314 @@
+import rope.base.builtins
+import rope.base.codeanalyze
+import rope.base.pynames
+from rope.base import ast, exceptions, utils
+
+
+class Scope(object):
+
+ def __init__(self, pycore, pyobject, parent_scope):
+ self.pycore = pycore
+ self.pyobject = pyobject
+ self.parent = parent_scope
+
+ def get_names(self):
+ """Return the names defined or imported in this scope"""
+ return self.pyobject.get_attributes()
+
+ def get_defined_names(self):
+ """Return the names defined in this scope"""
+ return self.pyobject._get_structural_attributes()
+
+ def get_name(self, name):
+ """Return name `PyName` defined in this scope"""
+ if name not in self.get_names():
+ raise exceptions.NameNotFoundError('name %s not found' % name)
+ return self.get_names()[name]
+
+ def __getitem__(self, key):
+ """The same as ``get_name(key)``"""
+ return self.get_name(key)
+
+ def __contains__(self, key):
+ """The same as ``key in self.get_names()``"""
+ return key in self.get_names()
+
+ @utils.saveit
+ def get_scopes(self):
+ """Return the subscopes of this scope
+
+ The returned scopes should be sorted by the order they appear.
+ """
+ return self._create_scopes()
+
+ def lookup(self, name):
+ if name in self.get_names():
+ return self.get_names()[name]
+ if self.parent is not None:
+ return self.parent._propagated_lookup(name)
+ return None
+
+ def get_propagated_names(self):
+ """Return the visible names of this scope
+
+ Return the names defined in this scope that are visible from
+ scopes containing this scope. This method returns the same
+ dictionary returned by `get_names()` except for `ClassScope`
+ which returns an empty dict.
+ """
+ return self.get_names()
+
+ def _propagated_lookup(self, name):
+ if name in self.get_propagated_names():
+ return self.get_propagated_names()[name]
+ if self.parent is not None:
+ return self.parent._propagated_lookup(name)
+ return None
+
+ def _create_scopes(self):
+ return [pydefined.get_scope()
+ for pydefined in self.pyobject._get_defined_objects()]
+
+ def _get_global_scope(self):
+ current = self
+ while current.parent is not None:
+ current = current.parent
+ return current
+
+ def get_start(self):
+ return self.pyobject.get_ast().lineno
+
+ def get_body_start(self):
+ body = self.pyobject.get_ast().body
+ if body:
+ return body[0].lineno
+ return self.get_start()
+
+ def get_end(self):
+ pymodule = self._get_global_scope().pyobject
+ return pymodule.logical_lines.logical_line_in(self.logical_end)[1]
+
+ @utils.saveit
+ def get_logical_end(self):
+ global_scope = self._get_global_scope()
+ return global_scope._scope_finder.find_scope_end(self)
+
+ start = property(get_start)
+ end = property(get_end)
+ logical_end = property(get_logical_end)
+
+ def get_kind(self):
+ pass
+
+
+class GlobalScope(Scope):
+
+ def __init__(self, pycore, module):
+ super(GlobalScope, self).__init__(pycore, module, None)
+ self.names = module._get_concluded_data()
+
+ def get_start(self):
+ return 1
+
+ def get_kind(self):
+ return 'Module'
+
+ def get_name(self, name):
+ try:
+ return self.pyobject[name]
+ except exceptions.AttributeNotFoundError:
+ if name in self.builtin_names:
+ return self.builtin_names[name]
+ raise exceptions.NameNotFoundError('name %s not found' % name)
+
+ def get_names(self):
+ if self.names.get() is None:
+ result = dict(self.builtin_names)
+ result.update(super(GlobalScope, self).get_names())
+ self.names.set(result)
+ return self.names.get()
+
+ def get_inner_scope_for_line(self, lineno, indents=None):
+ return self._scope_finder.get_holding_scope(self, lineno, indents)
+
+ def get_inner_scope_for_offset(self, offset):
+ return self._scope_finder.get_holding_scope_for_offset(self, offset)
+
+ @property
+ @utils.saveit
+ def _scope_finder(self):
+ return _HoldingScopeFinder(self.pyobject)
+
+ @property
+ def builtin_names(self):
+ return rope.base.builtins.builtins.get_attributes()
+
+
+class FunctionScope(Scope):
+
+ def __init__(self, pycore, pyobject, visitor):
+ super(FunctionScope, self).__init__(pycore, pyobject,
+ pyobject.parent.get_scope())
+ self.names = None
+ self.returned_asts = None
+ self.is_generator = None
+ self.defineds = None
+ self.visitor = visitor
+
+ def _get_names(self):
+ if self.names is None:
+ self._visit_function()
+ return self.names
+
+ def _visit_function(self):
+ if self.names is None:
+ new_visitor = self.visitor(self.pycore, self.pyobject)
+ for n in ast.get_child_nodes(self.pyobject.get_ast()):
+ ast.walk(n, new_visitor)
+ self.names = new_visitor.names
+ self.names.update(self.pyobject.get_parameters())
+ self.returned_asts = new_visitor.returned_asts
+ self.is_generator = new_visitor.generator
+ self.defineds = new_visitor.defineds
+
+ def _get_returned_asts(self):
+ if self.names is None:
+ self._visit_function()
+ return self.returned_asts
+
+ def _is_generator(self):
+ if self.is_generator is None:
+ self._get_returned_asts()
+ return self.is_generator
+
+ def get_names(self):
+ return self._get_names()
+
+ def _create_scopes(self):
+ if self.defineds is None:
+ self._visit_function()
+ return [pydefined.get_scope() for pydefined in self.defineds]
+
+ def get_kind(self):
+ return 'Function'
+
+ def invalidate_data(self):
+ for pyname in self.get_names().values():
+ if isinstance(pyname, (rope.base.pynames.AssignedName,
+ rope.base.pynames.EvaluatedName)):
+ pyname.invalidate()
+
+
+class ClassScope(Scope):
+
+ def __init__(self, pycore, pyobject):
+ super(ClassScope, self).__init__(pycore, pyobject,
+ pyobject.parent.get_scope())
+
+ def get_kind(self):
+ return 'Class'
+
+ def get_propagated_names(self):
+ return {}
+
+
+class _HoldingScopeFinder(object):
+
+ def __init__(self, pymodule):
+ self.pymodule = pymodule
+
+ def get_indents(self, lineno):
+ return rope.base.codeanalyze.count_line_indents(
+ self.lines.get_line(lineno))
+
+ def _get_scope_indents(self, scope):
+ return self.get_indents(scope.get_start())
+
+ def get_holding_scope(self, module_scope, lineno, line_indents=None):
+ if line_indents is None:
+ line_indents = self.get_indents(lineno)
+ current_scope = module_scope
+ new_scope = current_scope
+ while new_scope is not None and \
+ (new_scope.get_kind() == 'Module' or
+ self._get_scope_indents(new_scope) <= line_indents):
+ current_scope = new_scope
+ if current_scope.get_start() == lineno and \
+ current_scope.get_kind() != 'Module':
+ return current_scope
+ new_scope = None
+ for scope in current_scope.get_scopes():
+ if scope.get_start() <= lineno:
+ if lineno <= scope.get_end():
+ new_scope = scope
+ break
+ else:
+ break
+ return current_scope
+
+ def _is_empty_line(self, lineno):
+ line = self.lines.get_line(lineno)
+ return line.strip() == '' or line.lstrip().startswith('#')
+
+ def _get_body_indents(self, scope):
+ return self.get_indents(scope.get_body_start())
+
+ def get_holding_scope_for_offset(self, scope, offset):
+ return self.get_holding_scope(
+ scope, self.lines.get_line_number(offset))
+
+ def find_scope_end(self, scope):
+ if not scope.parent:
+ return self.lines.length()
+ end = scope.pyobject.get_ast().body[-1].lineno
+ scope_start = self.pymodule.logical_lines.logical_line_in(scope.start)
+ if scope_start[1] >= end:
+ # handling one-liners
+ body_indents = self._get_scope_indents(scope) + 4
+ else:
+ body_indents = self._get_body_indents(scope)
+ for l in self.logical_lines.generate_starts(
+ min(end + 1, self.lines.length()), self.lines.length() + 1):
+ if not self._is_empty_line(l):
+ if self.get_indents(l) < body_indents:
+ return end
+ else:
+ end = l
+ return end
+
+ @property
+ def lines(self):
+ return self.pymodule.lines
+
+ @property
+ def code(self):
+ return self.pymodule.source_code
+
+ @property
+ def logical_lines(self):
+ return self.pymodule.logical_lines
+
+
+class TemporaryScope(Scope):
+ """Currently used for list comprehensions and generator expressions
+
+ These scopes do not appear in the `get_scopes()` method of their
+ parent scopes.
+ """
+
+ def __init__(self, pycore, parent_scope, names):
+ super(TemporaryScope, self).__init__(
+ pycore, parent_scope.pyobject, parent_scope)
+ self.names = names
+
+ def get_names(self):
+ return self.names
+
+ def get_defined_names(self):
+ return self.names
+
+ def _create_scopes(self):
+ return []
+
+ def get_kind(self):
+ return 'Temporary'

Powered by Google App Engine
This is Rietveld 408576698