Anonymous avatar Anonymous committed 4873be7

added defpyobjects, defpynames and resourceobserver modules

This is the first step to reduce import cycles

Comments (0)

Files changed (13)

rope/base/defpynames.py

+import rope.base.oi.objectinfer
+from rope.base import pynames
+from rope.base.pynames import *
+
+
+class AssignedName(pynames.AssignedName):
+
+    def __init__(self, lineno=None, module=None, pyobject=None):
+        self.lineno = lineno
+        self.module = module
+        self.assignments = []
+        self.pyobject = _Inferred(self._get_inferred,
+                                  pynames._get_concluded_data(module))
+        self.pyobject.set(pyobject)
+
+    def _get_inferred(self):
+        if self.module is not None:
+            return rope.base.oi.objectinfer.infer_assigned_object(self)
+
+    def get_object(self):
+        return self.pyobject.get()
+
+    def get_definition_location(self):
+        """Returns a (module, lineno) tuple"""
+        if self.lineno is None and self.assignments:
+            self.lineno = self.assignments[0].get_lineno()
+        return (self.module, self.lineno)
+
+    def invalidate(self):
+        """Forget the `PyObject` this `PyName` holds"""
+        self.pyobject.set(None)
+
+
+class ParameterName(pynames.ParameterName):
+
+    def __init__(self, pyfunction, index):
+        self.pyfunction = pyfunction
+        self.index = index
+
+    def get_object(self):
+        result = self.pyfunction.get_parameter(self.index)
+        if result is None:
+            result = rope.base.pyobjects.get_unknown()
+        return result
+
+    def get_objects(self):
+        """Returns the list of objects passed as this parameter"""
+        return rope.base.oi.objectinfer.get_passed_objects(
+            self.pyfunction, self.index)
+
+    def get_definition_location(self):
+        return (self.pyfunction.get_module(), self.pyfunction.get_ast().lineno)
+
+
+_Inferred = pynames._Inferred
+_Assigned = pynames._Assigned

rope/base/defpyobjects.py

+import rope.base.evaluate
+import rope.base.oi.objectinfer
+import rope.base.pyscopes
+from rope.base import defpynames as pynames
+from rope.base import exceptions, ast, pyobjects
+from rope.base.pyobjects import *
+
+
+
+class PyFunction(pyobjects.PyFunction):
+
+    def __init__(self, pycore, ast_node, parent):
+        AbstractFunction.__init__(self)
+        PyDefinedObject.__init__(self, pycore, ast_node, parent)
+        self.arguments = self.ast_node.args
+        self.decorators = self.ast_node.decorators
+        self.parameter_pyobjects = pynames._Inferred(
+            self._infer_parameters, self.get_module()._get_concluded_data())
+        self.returned = pynames._Inferred(self._infer_returned)
+        self.parameter_pynames = None
+
+    def _create_structural_attributes(self):
+        return {}
+
+    def _create_concluded_attributes(self):
+        return {}
+
+    def _create_scope(self):
+        return rope.base.pyscopes.FunctionScope(self.pycore, self,
+                                                _FunctionVisitor)
+
+    def _infer_parameters(self):
+        pyobjects = rope.base.oi.objectinfer.infer_parameter_objects(self)
+        self._handle_special_args(pyobjects)
+        return pyobjects
+
+    def _infer_returned(self, args=None):
+        return rope.base.oi.objectinfer.infer_returned_object(self, args)
+
+    def _handle_special_args(self, pyobjects):
+        if len(pyobjects) == len(self.arguments.args):
+            if self.arguments.vararg:
+                pyobjects.append(rope.base.builtins.get_list())
+            if self.arguments.kwarg:
+                pyobjects.append(rope.base.builtins.get_dict())
+
+    def _set_parameter_pyobjects(self, pyobjects):
+        if pyobjects is not None:
+            self._handle_special_args(pyobjects)
+        self.parameter_pyobjects.set(pyobjects)
+
+    def get_parameters(self):
+        if self.parameter_pynames is None:
+            result = {}
+            for index, name in enumerate(self.get_param_names()):
+                # TODO: handle tuple parameters
+                result[name] = pynames.ParameterName(self, index)
+            self.parameter_pynames = result
+        return self.parameter_pynames
+
+    def get_parameter(self, index):
+        if index < len(self.parameter_pyobjects.get()):
+            return self.parameter_pyobjects.get()[index]
+
+    def get_returned_object(self, args):
+        return self.returned.get(args)
+
+    def get_name(self):
+        return self.get_ast().name
+
+    def get_param_names(self, special_args=True):
+        # TODO: handle tuple parameters
+        result = [node.id for node in self.arguments.args
+                  if isinstance(node, ast.Name)]
+        if special_args:
+            if self.arguments.vararg:
+                result.append(self.arguments.vararg)
+            if self.arguments.kwarg:
+                result.append(self.arguments.kwarg)
+        return result
+
+    def get_kind(self):
+        """Get function type
+
+        It returns one of 'function', 'method', 'staticmethod' or
+        'classmethod' strs.
+
+        """
+        import rope.base.evaluate
+        import rope.base.builtins
+        scope = self.parent.get_scope()
+        if isinstance(self.parent, PyClass):
+            for decorator in self.get_ast().decorators:
+                pyname = rope.base.evaluate.get_statement_result(scope,
+                                                                 decorator)
+                if pyname == rope.base.builtins.builtins['staticmethod']:
+                    return 'staticmethod'
+                if pyname == rope.base.builtins.builtins['classmethod']:
+                    return 'classmethod'
+            return 'method'
+        return 'function'
+
+
+class PyClass(pyobjects.PyClass):
+
+    def __init__(self, pycore, ast_node, parent):
+        AbstractClass.__init__(self)
+        PyDefinedObject.__init__(self, pycore, ast_node, parent)
+        self.parent = parent
+        self._superclasses = self.get_module()._get_concluded_data()
+        self.defineds = None
+
+    def get_superclasses(self):
+        if self._superclasses.get() is None:
+            self._superclasses.set(self._get_bases())
+        return self._superclasses.get()
+
+    def get_name(self):
+        return self.get_ast().name
+
+    def _get_defined_objects(self):
+        if self.defineds is None:
+            self._get_structural_attributes()
+        return self.defineds
+
+    def _create_structural_attributes(self):
+        new_visitor = _ClassVisitor(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):
+        result = {}
+        for base in reversed(self.get_superclasses()):
+            result.update(base.get_attributes())
+        return result
+
+    def _get_bases(self):
+        result = []
+        for base_name in self.ast_node.bases:
+            base = rope.base.evaluate.get_statement_result(
+                self.parent.get_scope(), base_name)
+            if base is not None and \
+               base.get_object().get_type() == get_base_type('Type'):
+                result.append(base.get_object())
+        return result
+
+    def _create_scope(self):
+        return rope.base.pyscopes.ClassScope(self.pycore, self)
+
+
+class PyModule(pyobjects.PyModule):
+
+    def __init__(self, pycore, source_code,
+                 resource=None, force_errors=False):
+        if isinstance(source_code, unicode):
+            source_code = source_code.encode('utf-8')
+        self.source_code = source_code
+        try:
+            ast_node = ast.parse(source_code.rstrip(' \t'))
+        except SyntaxError, e:
+            ignore = pycore.project.prefs.get('ignore_syntax_errors', False)
+            if force_errors or not ignore:
+                filename = 'string'
+                if resource:
+                    filename = resource.path
+                raise exceptions.ModuleSyntaxError(filename, e.lineno, e.msg)
+            else:
+                ast_node = ast.parse('\n')
+        self.star_imports = []
+        self.defineds = None
+        super(PyModule, self).__init__(pycore, ast_node, resource)
+
+    def _get_defined_objects(self):
+        if self.defineds is None:
+            self._get_structural_attributes()
+        return self.defineds
+
+    def _create_concluded_attributes(self):
+        result = {}
+        for star_import in self.star_imports:
+            result.update(star_import.get_names())
+        return result
+
+    def _create_structural_attributes(self):
+        visitor = _GlobalVisitor(self.pycore, self)
+        ast.walk(self.ast_node, visitor)
+        self.defineds = visitor.defineds
+        return visitor.names
+
+    def _create_scope(self):
+        return rope.base.pyscopes.GlobalScope(self.pycore, self)
+
+    _lines = None
+    @property
+    def lines(self):
+        """return a `SourceLinesAdapter`"""
+        if self._lines is None:
+            self._lines = rope.base.codeanalyze.\
+                          SourceLinesAdapter(self.source_code)
+        return self._lines
+
+    _logical_lines = None
+    @property
+    def logical_lines(self):
+        """return a `LogicalLinesFinder`"""
+        if self._logical_lines is None:
+            self._logical_lines = \
+                rope.base.codeanalyze.CachingLogicalLineFinder(self.lines)
+        return self._logical_lines
+
+
+class PyPackage(pyobjects.PyPackage):
+
+    def __init__(self, pycore, resource=None):
+        self.resource = resource
+        if resource is not None and resource.has_child('__init__.py'):
+            ast_node = pycore.resource_to_pyobject(
+                resource.get_child('__init__.py')).get_ast()
+        else:
+            ast_node = ast.parse('\n')
+        super(PyPackage, self).__init__(pycore, ast_node, resource)
+
+    def _create_structural_attributes(self):
+        result = {}
+        if self.resource is None:
+            return result
+        for name, resource in self._get_child_resources().items():
+            result[name] = pynames.ImportedModule(self, resource=resource)
+        return result
+
+    def _create_concluded_attributes(self):
+        result = {}
+        init_dot_py = self._get_init_dot_py()
+        if init_dot_py:
+            init_object = self.pycore.resource_to_pyobject(init_dot_py)
+            result.update(init_object.get_attributes())
+        return result
+
+    def _get_child_resources(self):
+        result = {}
+        for child in self.resource.get_children():
+            if child.is_folder():
+                result[child.name] = child
+            elif child.name.endswith('.py') and \
+                 child.name != '__init__.py':
+                name = child.name[:-3]
+                result[name] = child
+        return result
+
+    def _get_init_dot_py(self):
+        if self.resource is not None and self.resource.has_child('__init__.py'):
+            return self.resource.get_child('__init__.py')
+        else:
+            return None
+
+    def _create_scope(self):
+        return self.get_module().get_scope()
+
+    def get_module(self):
+        init_dot_py = self._get_init_dot_py()
+        if init_dot_py:
+            return self.pycore.resource_to_pyobject(init_dot_py)
+        return self
+
+
+class _AssignVisitor(object):
+
+    def __init__(self, scope_visitor):
+        self.scope_visitor = scope_visitor
+        self.assigned_ast = None
+
+    def _Assign(self, node):
+        self.assigned_ast = node.value
+        for child_node in node.targets:
+            ast.walk(child_node, self)
+
+    def _assigned(self, name, assignment=None):
+        old_pyname = self.scope_visitor.names.get(name, None)
+        if not isinstance(old_pyname, pynames.AssignedName):
+            self.scope_visitor.names[name] = pynames.AssignedName(
+                module=self.scope_visitor.get_module())
+        if assignment is not None:
+            self.scope_visitor.names[name].assignments.append(assignment)
+
+    def _Name(self, node):
+        assignment = None
+        if self.assigned_ast is not None:
+            assignment = pynames._Assigned(self.assigned_ast)
+        self._assigned(node.id, assignment)
+
+    def _Tuple(self, node):
+        names = rope.base.evaluate._get_name_levels(node)
+        for name, levels in names:
+            assignment = None
+            if self.assigned_ast is not None:
+                assignment = pynames._Assigned(self.assigned_ast, levels)
+            self._assigned(name, assignment)
+
+    def _Attribute(self, node):
+        pass
+
+    def _Subscript(self, node):
+        pass
+
+    def _Slice(self, node):
+        pass
+
+
+class _ScopeVisitor(object):
+
+    def __init__(self, pycore, owner_object):
+        self.pycore = pycore
+        self.owner_object = owner_object
+        self.names = {}
+        self.defineds = []
+
+    def get_module(self):
+        if self.owner_object is not None:
+            return self.owner_object.get_module()
+        else:
+            return None
+
+    def _ClassDef(self, node):
+        pyclass = PyClass(self.pycore, node, self.owner_object)
+        self.names[node.name] = pynames.DefinedName(pyclass)
+        self.defineds.append(pyclass)
+
+    def _FunctionDef(self, node):
+        pyfunction = PyFunction(self.pycore, node, self.owner_object)
+        self.names[node.name] = pynames.DefinedName(pyfunction)
+        self.defineds.append(pyfunction)
+
+    def _Assign(self, node):
+        ast.walk(node, _AssignVisitor(self))
+
+    def _For(self, node):
+        names = rope.base.evaluate._get_evaluated_names(
+            node.target, node.iter, evaluation='.__iter__().next()',
+            lineno=node.lineno, module=self.get_module())
+        self.names.update(names)
+        for child in node.body + node.orelse:
+            ast.walk(child, self)
+
+    def _With(self, node):
+        # ???: What if there are no optional vars?
+        names = rope.base.evaluate._get_evaluated_names(
+            node.optional_vars, node.context_expr, evaluation='.__enter__()',
+            lineno=node.lineno, module=self.get_module())
+        self.names.update(names)
+        for child in node.body:
+            ast.walk(child, self)
+
+    def _Import(self, node):
+        for import_pair in node.names:
+            module_name = import_pair.name
+            alias = import_pair.asname
+            first_package = module_name.split('.')[0]
+            if alias is not None:
+                self.names[alias] = \
+                    pynames.ImportedModule(self.get_module(), module_name)
+            else:
+                self.names[first_package] = \
+                    pynames.ImportedModule(self.get_module(), first_package)
+
+    def _ImportFrom(self, node):
+        level = 0
+        if node.level:
+            level = node.level
+        imported_module = pynames.ImportedModule(self.get_module(),
+                                                 node.module, level)
+        if len(node.names) == 1 and node.names[0].name == '*':
+            self.owner_object.star_imports.append(
+                pynames.StarImport(imported_module))
+        else:
+            for imported_name in node.names:
+                imported = imported_name.name
+                alias = imported_name.asname
+                if alias is not None:
+                    imported = alias
+                self.names[imported] = pynames.ImportedName(imported_module,
+                                                            imported_name.name)
+
+    def _Global(self, node):
+        module = self.get_module()
+        for name in node.names:
+            if module is not None:
+                try:
+                    pyname = module.get_attribute(name)
+                except exceptions.AttributeNotFoundError:
+                    pyname = pynames.AssignedName(node.lineno)
+            self.names[name] = pyname
+
+
+class _GlobalVisitor(_ScopeVisitor):
+
+    def __init__(self, pycore, owner_object):
+        super(_GlobalVisitor, self).__init__(pycore, owner_object)
+
+
+class _ClassVisitor(_ScopeVisitor):
+
+    def __init__(self, pycore, owner_object):
+        super(_ClassVisitor, self).__init__(pycore, owner_object)
+
+    def _FunctionDef(self, node):
+        pyfunction = PyFunction(self.pycore, node, self.owner_object)
+        self.names[node.name] = pynames.DefinedName(pyfunction)
+        self.defineds.append(pyfunction)
+        if len(node.args.args) > 0:
+            first = node.args.args[0]
+            if isinstance(first, ast.Name):
+                new_visitor = _ClassInitVisitor(self, first.id)
+                for child in ast.get_child_nodes(node):
+                    ast.walk(child, new_visitor)
+
+    def _ClassDef(self, node):
+        pyclass = PyClass(self.pycore, node, self.owner_object)
+        self.names[node.name] = pynames.DefinedName(pyclass)
+        self.defineds.append(pyclass)
+
+
+class _FunctionVisitor(_ScopeVisitor):
+
+    def __init__(self, pycore, owner_object):
+        super(_FunctionVisitor, self).__init__(pycore, owner_object)
+        self.returned_asts = []
+        self.generator = False
+
+    def _Return(self, node):
+        if node.value is not None:
+            self.returned_asts.append(node.value)
+
+    def _Yield(self, node):
+        if node.value is not None:
+            self.returned_asts.append(node.value)
+        self.generator = True
+
+
+class _ClassInitVisitor(_AssignVisitor):
+
+    def __init__(self, scope_visitor, self_name):
+        super(_ClassInitVisitor, self).__init__(scope_visitor)
+        self.self_name = self_name
+
+    def _Attribute(self, node):
+        if not isinstance(node.ctx, ast.Store):
+            return
+        if isinstance(node.value, ast.Name) and \
+           node.value.id == self.self_name:
+            if node.attr not in self.scope_visitor.names:
+                self.scope_visitor.names[node.attr] = pynames.AssignedName(
+                    lineno=node.lineno, module=self.scope_visitor.get_module())
+            self.scope_visitor.names[node.attr].assignments.append(
+                pynames._Assigned(self.assigned_ast))
+
+    def _Tuple(self, node):
+        if not isinstance(node.ctx, ast.Store):
+            return
+        for child in ast.get_child_nodes(node):
+            ast.walk(child, self)
+
+    def _Name(self, node):
+        pass
+
+    def _FunctionDef(self, node):
+        pass
+
+    def _ClassDef(self, node):
+        pass
+
+    def _For(self, node):
+        pass
+
+    def _With(self, node):
+        pass

rope/base/evaluate.py

-import rope.base
+import rope.base.pynames
+import rope.base.exceptions
+import rope.base.pyobjects
 from rope.base import ast, exceptions
 
 
         module = scope.pyobject.get_module()
         names = {}
         for comp in node.generators:
-            new_names = rope.base.pyobjects._get_evaluated_names(
+            new_names = _get_evaluated_names(
                 comp.target, comp.iter, evaluation='.__iter__().next()',
                 lineno=node.lineno, module=module)
             names.update(new_names)
        isinstance(pyfunction, rope.base.builtins.BuiltinFunction):
         return True
     return False
+
+
+def _get_evaluated_names(targets, assigned, **kwds):
+    """Get `pynames.EvaluatedName`\s
+
+    `kwds` is passed to `pynames.EvaluatedName` and should hold
+    things like lineno, evaluation, and module.
+    """
+    result = {}
+    names = _get_name_levels(targets)
+    for name, levels in names:
+        assignment = rope.base.pynames._Assigned(assigned, levels)
+        result[name] = EvaluatedName(assignment=assignment, **kwds)
+    return result
+
+
+class EvaluatedName(rope.base.pynames.EvaluatedName):
+    """A `PyName` that will be assigned an expression"""
+
+    def __init__(self, assignment=None, module=None, evaluation= '',
+                 lineno=None):
+        """
+        `evaluation` is a `str` that specifies what to do with the
+        `assignment`.  For example for a for object the evaluation is
+        '.__iter__().next()'.  That means first call the `__iter__()`
+        method and then call `next()` from the resulting object.  As
+        another example for with variables it is '.__enter__()'
+
+        """
+        self.module = module
+        self.assignment = assignment
+        self.lineno = lineno
+        self.evaluation = evaluation
+        self.pyobject = rope.base.pynames._Inferred(
+            self._get_inferred,
+            rope.base.pynames._get_concluded_data(module))
+
+    def _get_inferred(self):
+        return rope.base.oi.objectinfer.evaluate_object(self)
+
+    def get_object(self):
+        return self.pyobject.get()
+
+    def get_definition_location(self):
+        return (self.module, self.lineno)
+
+    def invalidate(self):
+        """Forget the `PyObject` this `PyName` holds"""
+        self.pyobject.set(None)
+
+
+def _get_name_levels(node):
+    visitor = _NodeNameCollector()
+    ast.walk(node, visitor)
+    return visitor.names
+
+
+class _NodeNameCollector(object):
+
+    def __init__(self, levels=None):
+        self.names = []
+        self.levels = levels
+        self.index = 0
+
+    def _add_node(self, node):
+        new_levels = []
+        if self.levels is not None:
+            new_levels = list(self.levels)
+            new_levels.append(self.index)
+        self.index += 1
+        self._added(node, new_levels)
+
+    def _added(self, node, levels):
+        if hasattr(node, 'id'):
+            self.names.append((node.id, levels))
+
+    def _Name(self, node):
+        self._add_node(node)
+
+    def _Tuple(self, node):
+        new_levels = []
+        if self.levels is not None:
+            new_levels = list(self.levels)
+            new_levels.append(self.index)
+        self.index += 1
+        visitor = _NodeNameCollector(new_levels)
+        for child in ast.get_child_nodes(node):
+            ast.walk(child, visitor)
+        self.names.extend(visitor.names)
+
+    def _Subscript(self, node):
+        self._add_node(node)

rope/base/oi/objectinfo.py

-import sys
 import warnings
 
-import rope.base.project
-from rope.base import exceptions
+from rope.base import exceptions, resourceobserver
 from rope.base.oi import objectdb, memorydb, transform
 
 
 
     def _init_validation(self):
         self.objectdb.validate_files()
-        observer = rope.base.project.ResourceObserver(
+        observer = resourceobserver.ResourceObserver(
             changed=self._resource_changed, moved=self._resource_moved,
             removed=self._resource_moved)
         files = []
             resource = self.to_pyobject.path_to_resource(path)
             if resource is not None and resource.project == self.project:
                 files.append(resource)
-        self.observer = rope.base.project.FilteredResourceObserver(observer,
-                                                                   files)
+        self.observer = resourceobserver.FilteredResourceObserver(observer,
+                                                                  files)
         self.objectdb.add_file_list_observer(_FileListObserver(self))
         self.project.add_observer(self.observer)
 

rope/base/oi/staticoi.py

                 # IDEA: handle `__setslice__`, too
 
 
-class _SOIAssignVisitor(pyobjects._NodeNameCollector):
+class _SOIAssignVisitor(evaluate._NodeNameCollector):
 
     def __init__(self):
         super(_SOIAssignVisitor, self).__init__()

rope/base/oi/transform.py

 import os
 import re
 
+import rope.base.builtins
 import rope.base.project
 from rope.base import exceptions
 

rope/base/project.py

 
 import rope.base.change
 import rope.base.fscommands
-from rope.base import exceptions, taskhandle, prefs, pycore, history
+import rope.base.pycore
+import rope.base.resourceobserver
+from rope.base import exceptions, taskhandle, prefs, history
 from rope.base.resources import File, Folder
 
 
 
     def get_pycore(self):
         if self._pycore is None:
-            self._pycore = pycore.PyCore(self)
+            self._pycore = rope.base.pycore.PyCore(self)
         return self._pycore
 
     def get_file(self, path):
     return NoProject._no_project
 
 
-class ResourceObserver(object):
-    """Provides the interface for observing resources
-
-    `ResourceObserver`\s can be registered using `Project.
-    add_observer()`.  But most of the time `FilteredResourceObserver`
-    should be used.  `ResourceObserver`\s report all changes passed
-    to them and they don't report changes to all resources.  For
-    example if a folder is removed, it only calls `removed()` for that
-    folder and not its contents.  You can use
-    `FilteredResourceObserver` if you are interested in changes only
-    to a list of resources.  And you want changes to be reported on
-    individual resources.
-
-    """
-
-    def __init__(self, changed=None, moved=None, created=None,
-                 removed=None, validate=None):
-        self.changed = changed
-        self.moved = moved
-        self.created = created
-        self.removed = removed
-        self._validate = validate
-
-    def resource_changed(self, resource):
-        """It is called when the resource changes"""
-        if self.changed is not None:
-            self.changed(resource)
-
-    def resource_moved(self, resource, new_resource):
-        """It is called when a resource is moved"""
-        if self.moved is not None:
-            self.moved(resource, new_resource)
-
-    def resource_created(self, resource):
-        """Is called when a new resource is created"""
-        if self.created is not None:
-            self.created(resource)
-
-    def resource_removed(self, resource):
-        """Is called when a new resource is removed"""
-        if self.removed is not None:
-            self.removed(resource)
-
-    def validate(self, resource):
-        """Validate the existence of this resource and its children.
-
-        This function is called when rope need to update its resource
-        cache about the files that might have been changed or removed
-        by other processes.
-
-        """
-        if self._validate is not None:
-            self._validate(resource)
-
-
-class FilteredResourceObserver(object):
-    """A useful decorator for `ResourceObserver`
-
-    Most resource observers have a list of resources and are
-    interested only in changes to those files.  This class satisfies
-    this need.  It dispatches resource changed and removed messages.
-    It performs these tasks:
-
-    * Changes to files and folders are analyzed to check whether any
-      of the interesting resources are changed or not.  If they are,
-      it reports these changes to `resource_observer` passed to the
-      constructor.
-    * When a resource is removed it checks whether any of the
-      interesting resources are contained in that folder and reports
-      them to `resource_observer`.
-    * When validating a folder it validates all of the interesting
-      files in that folder.
-
-    Since most resource observers are interested in a list of
-    resources that change over time, `add_resource` and
-    `remove_resource` might be useful.
-
-    """
-
-    def __init__(self, resource_observer, initial_resources=None,
-                 timekeeper=None):
-        self.observer = resource_observer
-        self.resources = {}
-        if timekeeper is not None:
-            self.timekeeper = timekeeper
-        else:
-            self.timekeeper = ChangeIndicator()
-        if initial_resources is not None:
-            for resource in initial_resources:
-                self.add_resource(resource)
-
-    def add_resource(self, resource):
-        """Add a resource to the list of interesting resources"""
-        if resource.exists():
-            self.resources[resource] = self.timekeeper.get_indicator(resource)
-        else:
-            self.resources[resource] = None
-
-    def remove_resource(self, resource):
-        """Add a resource to the list of interesting resources"""
-        if resource in self.resources:
-            del self.resources[resource]
-
-    def resource_changed(self, resource):
-        changes = _Changes()
-        self._update_changes_caused_by_changed(changes, resource)
-        self._perform_changes(changes)
-
-    def _update_changes_caused_by_changed(self, changes, changed):
-        if changed in self.resources:
-            changes.add_changed(changed)
-        if self._is_parent_changed(changed):
-            changes.add_changed(changed.parent)
-
-    def _update_changes_caused_by_moved(self, changes, resource,
-                                        new_resource=None):
-        if resource in self.resources:
-            changes.add_removed(resource, new_resource)
-        if new_resource in self.resources:
-            changes.add_created(new_resource)
-        if resource.is_folder():
-            for file in list(self.resources):
-                if resource.contains(file):
-                    new_file = self._calculate_new_resource(
-                        resource, new_resource, file)
-                    changes.add_removed(file, new_file)
-        if self._is_parent_changed(resource):
-            changes.add_changed(resource.parent)
-        if new_resource is not None:
-            if self._is_parent_changed(new_resource):
-                changes.add_changed(new_resource.parent)
-
-    def _is_parent_changed(self, child):
-        return child.parent in self.resources
-
-    def resource_moved(self, resource, new_resource):
-        changes = _Changes()
-        self._update_changes_caused_by_moved(changes, resource, new_resource)
-        self._perform_changes(changes)
-
-    def resource_created(self, resource):
-        changes = _Changes()
-        self._update_changes_caused_by_created(changes, resource)
-        self._perform_changes(changes)
-
-    def _update_changes_caused_by_created(self, changes, resource):
-        if resource in self.resources:
-            changes.add_created(resource)
-        if self._is_parent_changed(resource):
-            changes.add_changed(resource.parent)
-
-    def resource_removed(self, resource):
-        changes = _Changes()
-        self._update_changes_caused_by_moved(changes, resource)
-        self._perform_changes(changes)
-
-    def _perform_changes(self, changes):
-        for resource in changes.changes:
-            self.observer.resource_changed(resource)
-            self.resources[resource] = self.timekeeper.get_indicator(resource)
-        for resource, new_resource in changes.moves.items():
-            self.resources[resource] = None
-            if new_resource is not None:
-                self.observer.resource_moved(resource, new_resource)
-            else:
-                self.observer.resource_removed(resource)
-        for resource in changes.creations:
-            self.observer.resource_created(resource)
-            self.resources[resource] = self.timekeeper.get_indicator(resource)
-
-    def validate(self, resource):
-        moved = self._search_resource_moves(resource)
-        changed = self._search_resource_changes(resource)
-        changes = _Changes()
-        for file in moved:
-            if file in self.resources:
-                self._update_changes_caused_by_moved(changes, file)
-        for file in changed:
-            if file in self.resources:
-                self._update_changes_caused_by_changed(changes, file)
-        for file in self._search_resource_creations(resource):
-            if file in self.resources:
-                changes.add_created(file)
-        self._perform_changes(changes)
-
-    def _search_resource_creations(self, resource):
-        creations = set()
-        if resource in self.resources and resource.exists() and \
-           self.resources[resource] == None:
-            creations.add(resource)
-        if resource.is_folder():
-            for file in self.resources:
-                if file.exists() and resource.contains(file) and \
-                   self.resources[file] == None:
-                    creations.add(file)
-        return creations
-
-    def _search_resource_moves(self, resource):
-        all_moved = set()
-        if resource in self.resources and not resource.exists():
-            all_moved.add(resource)
-        if resource.is_folder():
-            for file in self.resources:
-                if resource.contains(file):
-                    if not file.exists():
-                        all_moved.add(file)
-        moved = set(all_moved)
-        for folder in [file for file in all_moved if file.is_folder()]:
-            if folder in moved:
-                for file in list(moved):
-                    if folder.contains(file):
-                        moved.remove(file)
-        return moved
-
-    def _search_resource_changes(self, resource):
-        changed = set()
-        if resource in self.resources and self._is_changed(resource):
-            changed.add(resource)
-        if resource.is_folder():
-            for file in self.resources:
-                if file.exists() and resource.contains(file):
-                    if self._is_changed(file):
-                        changed.add(file)
-        return changed
-
-    def _is_changed(self, resource):
-        if self.resources[resource] is None:
-            return False
-        return self.resources[resource] != self.timekeeper.get_indicator(resource)
-
-    def _calculate_new_resource(self, main, new_main, resource):
-        if new_main is None:
-            return None
-        diff = resource.path[len(main.path):]
-        return resource.project.get_resource(new_main.path + diff)
-
-
-class ChangeIndicator(object):
-
-    def get_indicator(self, resource):
-        """Return the modification time and size of a `Resource`."""
-        return (os.path.getmtime(resource.real_path),
-                os.path.getsize(resource.real_path))
-
-
-class _Changes(object):
-
-    def __init__(self):
-        self.changes = set()
-        self.creations = set()
-        self.moves = {}
-
-    def add_changed(self, resource):
-        self.changes.add(resource)
-
-    def add_removed(self, resource, new_resource=None):
-        self.moves[resource] = new_resource
-
-    def add_created(self, resource):
-        self.creations.add(resource)
-
-
 class _IgnoredResources(object):
 
     def __init__(self):
 
     def _init_observer(self):
         if self.observer is None:
-            self.observer = ResourceObserver(
+            self.observer = rope.base.resourceobserver.ResourceObserver(
                 self._changed, self._moved, self._created,
                 self._removed, self._validate)
             self.project.add_observer(self.observer)

rope/base/pycore.py

 import rope.base.project
 from rope.base import ast, exceptions, taskhandle
 from rope.base.exceptions import ModuleNotFoundError
-from rope.base.pyobjects import PyModule, PyPackage, PyClass
+from rope.base.defpyobjects import PyModule, PyPackage, PyClass
+import rope.base.resourceobserver
 
 
 class PyCore(object):
 
     def _init_resource_observer(self):
         callback = self._invalidate_resource_cache
-        observer = rope.base.project.ResourceObserver(
+        observer = rope.base.resourceobserver.ResourceObserver(
             changed=callback, moved=callback, removed=callback)
-        self.observer = rope.base.project.FilteredResourceObserver(observer)
+        self.observer = rope.base.resourceobserver.FilteredResourceObserver(observer)
         self.project.add_observer(self.observer)
 
     def _init_source_folders(self):
         if not self.project.get_prefs().get('automatic_soi', False):
             return
         callback = self._file_changed_for_soi
-        observer = rope.base.project.ResourceObserver(
+        observer = rope.base.resourceobserver.ResourceObserver(
             changed=callback, moved=callback, removed=callback)
         self.project.add_observer(observer)
 

rope/base/pynames.py

-import rope.base.oi.objectinfer
-from rope.base.exceptions import (ModuleNotFoundError,
-                                  AttributeNotFoundError)
+import rope.base.pyobjects
+from rope.base import exceptions
 
 
 class PyName(object):
 
 class AssignedName(PyName):
 
-    def __init__(self, lineno=None, module=None, pyobject=None):
-        self.lineno = lineno
-        self.module = module
-        self.assignments = []
-        self.pyobject = _Inferred(self._get_inferred,
-                                  _get_concluded_data(module))
-        self.pyobject.set(pyobject)
-
-    def _get_inferred(self):
-        if self.module is not None:
-            return rope.base.oi.objectinfer.infer_assigned_object(self)
-
-    def get_object(self):
-        return self.pyobject.get()
-
-    def get_definition_location(self):
-        """Returns a (module, lineno) tuple"""
-        if self.lineno is None and self.assignments:
-            self.lineno = self.assignments[0].get_lineno()
-        return (self.module, self.lineno)
-
-    def invalidate(self):
-        """Forget the `PyObject` this `PyName` holds"""
-        self.pyobject.set(None)
+    def __init__(self, *args, **kwds):
+        raise RuntimeError('This is not a definition; use defpynames')
 
 
 class UnboundName(PyName):
 class EvaluatedName(PyName):
     """A `PyName` that will be assigned an expression"""
 
-    def __init__(self, assignment=None, module=None, evaluation= '',
-                 lineno=None):
-        """
-        `evaluation` is a `str` that specifies what to do with the
-        `assignment`.  For example for a for object the evaluation is
-        '.__iter__().next()'.  That means first call the `__iter__()`
-        method and then call `next()` from the resulting object.  As
-        another example for with variables it is '.__enter__()'
-
-        """
-        self.module = module
-        self.assignment = assignment
-        self.lineno = lineno
-        self.evaluation = evaluation
-        self.pyobject = _Inferred(self._get_inferred,
-                                  _get_concluded_data(module))
-
-    def _get_inferred(self):
-        return rope.base.oi.objectinfer.evaluate_object(self)
-
-    def get_object(self):
-        return self.pyobject.get()
-
-    def get_definition_location(self):
-        return (self.module, self.lineno)
-
-    def invalidate(self):
-        """Forget the `PyObject` this `PyName` holds"""
-        self.pyobject.set(None)
+    def __init__(self, *args, **kwds):
+        raise RuntimeError('This is not a definition; use evalute')
 
 
 class ParameterName(PyName):
 
-    def __init__(self, pyfunction, index):
-        self.pyfunction = pyfunction
-        self.index = index
-
-    def get_object(self):
-        result = self.pyfunction.get_parameter(self.index)
-        if result is None:
-            result = rope.base.pyobjects.get_unknown()
-        return result
-
-    def get_objects(self):
-        """Returns the list of objects passed as this parameter"""
-        return rope.base.oi.objectinfer.get_passed_objects(
-            self.pyfunction, self.index)
-
-    def get_definition_location(self):
-        return (self.pyfunction.get_module(), self.pyfunction.get_ast().lineno)
+    def __init__(self, *args, **kwds):
+        raise RuntimeError('This is not a definition; use defpynames')
 
 
 class ImportedModule(PyName):
                                           self.module_name,
                                           self._get_current_folder(),
                                           self.level))
-                except ModuleNotFoundError:
+                except exceptions.ModuleNotFoundError:
                     pass
         return self.pymodule.get()
 
         try:
             return self.imported_module.get_object().get_attribute(
                 self.imported_name)
-        except AttributeNotFoundError:
-            return AssignedName()
+        except exceptions.AttributeNotFoundError:
+            return UnboundName()
 
     def get_object(self):
         return self._get_imported_pyname().get_object()

rope/base/pyobjects.py

-import rope.base.evaluate
-import rope.base.oi.objectinfer
-import rope.base.pyscopes
-from rope.base import exceptions, ast, pynames
+from rope.base import exceptions, ast
 
 
 class PyObject(object):
 
 
 class PyFunction(PyDefinedObject, AbstractFunction):
-
-    def __init__(self, pycore, ast_node, parent):
-        AbstractFunction.__init__(self)
-        PyDefinedObject.__init__(self, pycore, ast_node, parent)
-        self.arguments = self.ast_node.args
-        self.decorators = self.ast_node.decorators
-        self.parameter_pyobjects = pynames._Inferred(
-            self._infer_parameters, self.get_module()._get_concluded_data())
-        self.returned = pynames._Inferred(self._infer_returned)
-        self.parameter_pynames = None
-
-    def _create_structural_attributes(self):
-        return {}
-
-    def _create_concluded_attributes(self):
-        return {}
-
-    def _create_scope(self):
-        return rope.base.pyscopes.FunctionScope(self.pycore, self)
-
-    def _infer_parameters(self):
-        pyobjects = rope.base.oi.objectinfer.infer_parameter_objects(self)
-        self._handle_special_args(pyobjects)
-        return pyobjects
-
-    def _infer_returned(self, args=None):
-        return rope.base.oi.objectinfer.infer_returned_object(self, args)
-
-    def _handle_special_args(self, pyobjects):
-        if len(pyobjects) == len(self.arguments.args):
-            if self.arguments.vararg:
-                pyobjects.append(rope.base.builtins.get_list())
-            if self.arguments.kwarg:
-                pyobjects.append(rope.base.builtins.get_dict())
-
-    def _set_parameter_pyobjects(self, pyobjects):
-        if pyobjects is not None:
-            self._handle_special_args(pyobjects)
-        self.parameter_pyobjects.set(pyobjects)
-
-    def get_parameters(self):
-        if self.parameter_pynames is None:
-            result = {}
-            for index, name in enumerate(self.get_param_names()):
-                # TODO: handle tuple parameters
-                result[name] = pynames.ParameterName(self, index)
-            self.parameter_pynames = result
-        return self.parameter_pynames
-
-    def get_parameter(self, index):
-        if index < len(self.parameter_pyobjects.get()):
-            return self.parameter_pyobjects.get()[index]
-
-    def get_returned_object(self, args):
-        return self.returned.get(args)
-
-    def get_name(self):
-        return self.get_ast().name
-
-    def get_param_names(self, special_args=True):
-        # TODO: handle tuple parameters
-        result = [node.id for node in self.arguments.args
-                  if isinstance(node, ast.Name)]
-        if special_args:
-            if self.arguments.vararg:
-                result.append(self.arguments.vararg)
-            if self.arguments.kwarg:
-                result.append(self.arguments.kwarg)
-        return result
-
-    def get_kind(self):
-        """Get function type
-
-        It returns one of 'function', 'method', 'staticmethod' or
-        'classmethod' strs.
-
-        """
-        import rope.base.evaluate
-        import rope.base.builtins
-        scope = self.parent.get_scope()
-        if isinstance(self.parent, PyClass):
-            for decorator in self.get_ast().decorators:
-                pyname = rope.base.evaluate.get_statement_result(scope,
-                                                                 decorator)
-                if pyname == rope.base.builtins.builtins['staticmethod']:
-                    return 'staticmethod'
-                if pyname == rope.base.builtins.builtins['classmethod']:
-                    return 'classmethod'
-            return 'method'
-        return 'function'
+    pass
 
 
 class PyClass(PyDefinedObject, AbstractClass):
-
-    def __init__(self, pycore, ast_node, parent):
-        AbstractClass.__init__(self)
-        PyDefinedObject.__init__(self, pycore, ast_node, parent)
-        self.parent = parent
-        self._superclasses = self.get_module()._get_concluded_data()
-        self.defineds = None
-
-    def get_superclasses(self):
-        if self._superclasses.get() is None:
-            self._superclasses.set(self._get_bases())
-        return self._superclasses.get()
-
-    def get_name(self):
-        return self.get_ast().name
-
-    def _get_defined_objects(self):
-        if self.defineds is None:
-            self._get_structural_attributes()
-        return self.defineds
-
-    def _create_structural_attributes(self):
-        new_visitor = _ClassVisitor(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):
-        result = {}
-        for base in reversed(self.get_superclasses()):
-            result.update(base.get_attributes())
-        return result
-
-    def _get_bases(self):
-        result = []
-        for base_name in self.ast_node.bases:
-            base = rope.base.evaluate.get_statement_result(
-                self.parent.get_scope(), base_name)
-            if base is not None and \
-               base.get_object().get_type() == get_base_type('Type'):
-                result.append(base.get_object())
-        return result
-
-    def _create_scope(self):
-        return rope.base.pyscopes.ClassScope(self.pycore, self)
+    pass
 
 
 class _ConcludedData(object):
 
 
 class PyModule(_PyModule):
-
-    def __init__(self, pycore, source_code,
-                 resource=None, force_errors=False):
-        if isinstance(source_code, unicode):
-            source_code = source_code.encode('utf-8')
-        self.source_code = source_code
-        try:
-            ast_node = ast.parse(source_code.rstrip(' \t'))
-        except SyntaxError, e:
-            ignore = pycore.project.prefs.get('ignore_syntax_errors', False)
-            if force_errors or not ignore:
-                filename = 'string'
-                if resource:
-                    filename = resource.path
-                raise exceptions.ModuleSyntaxError(filename, e.lineno, e.msg)
-            else:
-                ast_node = ast.parse('\n')
-        self.star_imports = []
-        self.defineds = None
-        super(PyModule, self).__init__(pycore, ast_node, resource)
-
-    def _get_defined_objects(self):
-        if self.defineds is None:
-            self._get_structural_attributes()
-        return self.defineds
-
-    def _create_concluded_attributes(self):
-        result = {}
-        for star_import in self.star_imports:
-            result.update(star_import.get_names())
-        return result
-
-    def _create_structural_attributes(self):
-        visitor = _GlobalVisitor(self.pycore, self)
-        ast.walk(self.ast_node, visitor)
-        self.defineds = visitor.defineds
-        return visitor.names
-
-    def _create_scope(self):
-        return rope.base.pyscopes.GlobalScope(self.pycore, self)
-
-    _lines = None
-    @property
-    def lines(self):
-        """return a `SourceLinesAdapter`"""
-        if self._lines is None:
-            self._lines = rope.base.codeanalyze.\
-                          SourceLinesAdapter(self.source_code)
-        return self._lines
-
-    _logical_lines = None
-    @property
-    def logical_lines(self):
-        """return a `LogicalLinesFinder`"""
-        if self._logical_lines is None:
-            self._logical_lines = \
-                rope.base.codeanalyze.CachingLogicalLineFinder(self.lines)
-        return self._logical_lines
+    pass
 
 
 class PyPackage(_PyModule):
-
-    def __init__(self, pycore, resource=None):
-        self.resource = resource
-        if resource is not None and resource.has_child('__init__.py'):
-            ast_node = pycore.resource_to_pyobject(
-                resource.get_child('__init__.py')).get_ast()
-        else:
-            ast_node = ast.parse('\n')
-        super(PyPackage, self).__init__(pycore, ast_node, resource)
-
-    def _create_structural_attributes(self):
-        result = {}
-        if self.resource is None:
-            return result
-        for name, resource in self._get_child_resources().items():
-            result[name] = pynames.ImportedModule(self, resource=resource)
-        return result
-
-    def _create_concluded_attributes(self):
-        result = {}
-        init_dot_py = self._get_init_dot_py()
-        if init_dot_py:
-            init_object = self.pycore.resource_to_pyobject(init_dot_py)
-            result.update(init_object.get_attributes())
-        return result
-
-    def _get_child_resources(self):
-        result = {}
-        for child in self.resource.get_children():
-            if child.is_folder():
-                result[child.name] = child
-            elif child.name.endswith('.py') and \
-                 child.name != '__init__.py':
-                name = child.name[:-3]
-                result[name] = child
-        return result
-
-    def _get_init_dot_py(self):
-        if self.resource is not None and self.resource.has_child('__init__.py'):
-            return self.resource.get_child('__init__.py')
-        else:
-            return None
-
-    def _create_scope(self):
-        return self.get_module().get_scope()
-
-    def get_module(self):
-        init_dot_py = self._get_init_dot_py()
-        if init_dot_py:
-            return self.pycore.resource_to_pyobject(init_dot_py)
-        return self
-
-
-class _AssignVisitor(object):
-
-    def __init__(self, scope_visitor):
-        self.scope_visitor = scope_visitor
-        self.assigned_ast = None
-
-    def _Assign(self, node):
-        self.assigned_ast = node.value
-        for child_node in node.targets:
-            ast.walk(child_node, self)
-
-    def _assigned(self, name, assignment=None):
-        old_pyname = self.scope_visitor.names.get(name, None)
-        if not isinstance(old_pyname, pynames.AssignedName):
-            self.scope_visitor.names[name] = pynames.AssignedName(
-                module=self.scope_visitor.get_module())
-        if assignment is not None:
-            self.scope_visitor.names[name].assignments.append(assignment)
-
-    def _Name(self, node):
-        assignment = None
-        if self.assigned_ast is not None:
-            assignment = pynames._Assigned(self.assigned_ast)
-        self._assigned(node.id, assignment)
-
-    def _Tuple(self, node):
-        names = _get_name_levels(node)
-        for name, levels in names:
-            assignment = None
-            if self.assigned_ast is not None:
-                assignment = pynames._Assigned(self.assigned_ast, levels)
-            self._assigned(name, assignment)
-
-    def _Attribute(self, node):
-        pass
-
-    def _Subscript(self, node):
-        pass
-
-    def _Slice(self, node):
-        pass
-
-
-class _ScopeVisitor(object):
-
-    def __init__(self, pycore, owner_object):
-        self.pycore = pycore
-        self.owner_object = owner_object
-        self.names = {}
-        self.defineds = []
-
-    def get_module(self):
-        if self.owner_object is not None:
-            return self.owner_object.get_module()
-        else:
-            return None
-
-    def _ClassDef(self, node):
-        pyclass = PyClass(self.pycore, node, self.owner_object)
-        self.names[node.name] = pynames.DefinedName(pyclass)
-        self.defineds.append(pyclass)
-
-    def _FunctionDef(self, node):
-        pyfunction = PyFunction(self.pycore, node, self.owner_object)
-        self.names[node.name] = pynames.DefinedName(pyfunction)
-        self.defineds.append(pyfunction)
-
-    def _Assign(self, node):
-        ast.walk(node, _AssignVisitor(self))
-
-    def _For(self, node):
-        names = _get_evaluated_names(
-            node.target, node.iter, evaluation='.__iter__().next()',
-            lineno=node.lineno, module=self.get_module())
-        self.names.update(names)
-        for child in node.body + node.orelse:
-            ast.walk(child, self)
-
-    def _With(self, node):
-        # ???: What if there are no optional vars?
-        names = _get_evaluated_names(
-            node.optional_vars, node.context_expr, evaluation='.__enter__()',
-            lineno=node.lineno, module=self.get_module())
-        self.names.update(names)
-        for child in node.body:
-            ast.walk(child, self)
-
-    def _Import(self, node):
-        for import_pair in node.names:
-            module_name = import_pair.name
-            alias = import_pair.asname
-            first_package = module_name.split('.')[0]
-            if alias is not None:
-                self.names[alias] = \
-                    pynames.ImportedModule(self.get_module(), module_name)
-            else:
-                self.names[first_package] = \
-                    pynames.ImportedModule(self.get_module(), first_package)
-
-    def _ImportFrom(self, node):
-        level = 0
-        if node.level:
-            level = node.level
-        imported_module = pynames.ImportedModule(self.get_module(),
-                                                 node.module, level)
-        if len(node.names) == 1 and node.names[0].name == '*':
-            self.owner_object.star_imports.append(
-                pynames.StarImport(imported_module))
-        else:
-            for imported_name in node.names:
-                imported = imported_name.name
-                alias = imported_name.asname
-                if alias is not None:
-                    imported = alias
-                self.names[imported] = pynames.ImportedName(imported_module,
-                                                            imported_name.name)
-
-    def _Global(self, node):
-        module = self.get_module()
-        for name in node.names:
-            if module is not None:
-                try:
-                    pyname = module.get_attribute(name)
-                except exceptions.AttributeNotFoundError:
-                    pyname = pynames.AssignedName(node.lineno)
-            self.names[name] = pyname
-
-
-def _get_evaluated_names(targets, assigned, **kwds):
-    """Get `pynames.EvaluatedName`\s
-
-    `kwds` is passed to `pynames.EvaluatedName` and should hold
-    things like lineno, evaluation, and module.
-    """
-    result = {}
-    names = _get_name_levels(targets)
-    for name, levels in names:
-        assignment = pynames._Assigned(assigned, levels)
-        result[name] = pynames.EvaluatedName(assignment=assignment, **kwds)
-    return result
-
-
-class _GlobalVisitor(_ScopeVisitor):
-
-    def __init__(self, pycore, owner_object):
-        super(_GlobalVisitor, self).__init__(pycore, owner_object)
-
-
-class _ClassVisitor(_ScopeVisitor):
-
-    def __init__(self, pycore, owner_object):
-        super(_ClassVisitor, self).__init__(pycore, owner_object)
-
-    def _FunctionDef(self, node):
-        pyfunction = PyFunction(self.pycore, node, self.owner_object)
-        self.names[node.name] = pynames.DefinedName(pyfunction)
-        self.defineds.append(pyfunction)
-        if len(node.args.args) > 0:
-            first = node.args.args[0]
-            if isinstance(first, ast.Name):
-                new_visitor = _ClassInitVisitor(self, first.id)
-                for child in ast.get_child_nodes(node):
-                    ast.walk(child, new_visitor)
-
-    def _ClassDef(self, node):
-        pyclass = PyClass(self.pycore, node, self.owner_object)
-        self.names[node.name] = pynames.DefinedName(pyclass)
-        self.defineds.append(pyclass)
-
-
-class _FunctionVisitor(_ScopeVisitor):
-
-    def __init__(self, pycore, owner_object):
-        super(_FunctionVisitor, self).__init__(pycore, owner_object)
-        self.returned_asts = []
-        self.generator = False
-
-    def _Return(self, node):
-        if node.value is not None:
-            self.returned_asts.append(node.value)
-
-    def _Yield(self, node):
-        if node.value is not None:
-            self.returned_asts.append(node.value)
-        self.generator = True
-
-
-class _ClassInitVisitor(_AssignVisitor):
-
-    def __init__(self, scope_visitor, self_name):
-        super(_ClassInitVisitor, self).__init__(scope_visitor)
-        self.self_name = self_name
-
-    def _Attribute(self, node):
-        if not isinstance(node.ctx, ast.Store):
-            return
-        if isinstance(node.value, ast.Name) and \
-           node.value.id == self.self_name:
-            if node.attr not in self.scope_visitor.names:
-                self.scope_visitor.names[node.attr] = pynames.AssignedName(
-                    lineno=node.lineno, module=self.scope_visitor.get_module())
-            self.scope_visitor.names[node.attr].assignments.append(
-                pynames._Assigned(self.assigned_ast))
-
-    def _Tuple(self, node):
-        if not isinstance(node.ctx, ast.Store):
-            return
-        for child in ast.get_child_nodes(node):
-            ast.walk(child, self)
-
-    def _Name(self, node):
-        pass
-
-    def _FunctionDef(self, node):
-        pass
-
-    def _ClassDef(self, node):
-        pass
-
-    def _For(self, node):
-        pass
-
-    def _With(self, node):
-        pass
+    pass
 
 
 class IsBeingInferredError(exceptions.RopeError):
     pass
-
-
-class _NodeNameCollector(object):
-
-    def __init__(self, levels=None):
-        self.names = []
-        self.levels = levels
-        self.index = 0
-
-    def _add_node(self, node):
-        new_levels = []
-        if self.levels is not None:
-            new_levels = list(self.levels)
-            new_levels.append(self.index)
-        self.index += 1
-        self._added(node, new_levels)
-
-    def _added(self, node, levels):
-        if hasattr(node, 'id'):
-            self.names.append((node.id, levels))
-
-    def _Name(self, node):
-        self._add_node(node)
-
-    def _Tuple(self, node):
-        new_levels = []
-        if self.levels is not None:
-            new_levels = list(self.levels)
-            new_levels.append(self.index)
-        self.index += 1
-        visitor = _NodeNameCollector(new_levels)
-        for child in ast.get_child_nodes(node):
-            ast.walk(child, visitor)
-        self.names.extend(visitor.names)
-
-    def _Subscript(self, node):
-        self._add_node(node)
-
-
-def _get_name_levels(node):
-    visitor = _NodeNameCollector()
-    ast.walk(node, visitor)
-    return visitor.names

rope/base/pyscopes.py

 import rope.base.pynames
-import rope.base.pyobjects
 from rope.base import ast, exceptions
 
 
 
 class FunctionScope(Scope):
 
-    def __init__(self, pycore, pyobject):
+    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:
 
     def _visit_function(self):
         if self.names is None:
-            new_visitor = rope.base.pyobjects._FunctionVisitor(self.pycore,
-                                                               self.pyobject)
+            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 = self.pyobject.get_parameters()

rope/base/resourceobserver.py

+import os
+
+
+class ResourceObserver(object):
+    """Provides the interface for observing resources
+
+    `ResourceObserver`\s can be registered using `Project.
+    add_observer()`.  But most of the time `FilteredResourceObserver`
+    should be used.  `ResourceObserver`\s report all changes passed
+    to them and they don't report changes to all resources.  For
+    example if a folder is removed, it only calls `removed()` for that
+    folder and not its contents.  You can use
+    `FilteredResourceObserver` if you are interested in changes only
+    to a list of resources.  And you want changes to be reported on
+    individual resources.
+
+    """
+
+    def __init__(self, changed=None, moved=None, created=None,
+                 removed=None, validate=None):
+        self.changed = changed
+        self.moved = moved
+        self.created = created
+        self.removed = removed
+        self._validate = validate
+
+    def resource_changed(self, resource):
+        """It is called when the resource changes"""
+        if self.changed is not None:
+            self.changed(resource)
+
+    def resource_moved(self, resource, new_resource):
+        """It is called when a resource is moved"""
+        if self.moved is not None:
+            self.moved(resource, new_resource)
+
+    def resource_created(self, resource):
+        """Is called when a new resource is created"""
+        if self.created is not None:
+            self.created(resource)
+
+    def resource_removed(self, resource):
+        """Is called when a new resource is removed"""
+        if self.removed is not None:
+            self.removed(resource)
+
+    def validate(self, resource):
+        """Validate the existence of this resource and its children.
+
+        This function is called when rope need to update its resource
+        cache about the files that might have been changed or removed
+        by other processes.
+
+        """
+        if self._validate is not None:
+            self._validate(resource)
+
+
+class FilteredResourceObserver(object):
+    """A useful decorator for `ResourceObserver`
+
+    Most resource observers have a list of resources and are
+    interested only in changes to those files.  This class satisfies
+    this need.  It dispatches resource changed and removed messages.
+    It performs these tasks:
+
+    * Changes to files and folders are analyzed to check whether any
+      of the interesting resources are changed or not.  If they are,
+      it reports these changes to `resource_observer` passed to the
+      constructor.
+    * When a resource is removed it checks whether any of the
+      interesting resources are contained in that folder and reports
+      them to `resource_observer`.
+    * When validating a folder it validates all of the interesting
+      files in that folder.
+
+    Since most resource observers are interested in a list of
+    resources that change over time, `add_resource` and
+    `remove_resource` might be useful.
+
+    """
+
+    def __init__(self, resource_observer, initial_resources=None,
+                 timekeeper=None):
+        self.observer = resource_observer
+        self.resources = {}
+        if timekeeper is not None:
+            self.timekeeper = timekeeper
+        else:
+            self.timekeeper = ChangeIndicator()
+        if initial_resources is not None:
+            for resource in initial_resources:
+                self.add_resource(resource)
+
+    def add_resource(self, resource):
+        """Add a resource to the list of interesting resources"""
+        if resource.exists():
+            self.resources[resource] = self.timekeeper.get_indicator(resource)
+        else:
+            self.resources[resource] = None
+
+    def remove_resource(self, resource):
+        """Add a resource to the list of interesting resources"""
+        if resource in self.resources:
+            del self.resources[resource]
+
+    def resource_changed(self, resource):
+        changes = _Changes()
+        self._update_changes_caused_by_changed(changes, resource)
+        self._perform_changes(changes)
+
+    def _update_changes_caused_by_changed(self, changes, changed):
+        if changed in self.resources:
+            changes.add_changed(changed)
+        if self._is_parent_changed(changed):
+            changes.add_changed(changed.parent)
+
+    def _update_changes_caused_by_moved(self, changes, resource,
+                                        new_resource=None):
+        if resource in self.resources:
+            changes.add_removed(resource, new_resource)
+        if new_resource in self.resources:
+            changes.add_created(new_resource)
+        if resource.is_folder():
+            for file in list(self.resources):
+                if resource.contains(file):
+                    new_file = self._calculate_new_resource(
+                        resource, new_resource, file)
+                    changes.add_removed(file, new_file)
+        if self._is_parent_changed(resource):
+            changes.add_changed(resource.parent)
+        if new_resource is not None:
+            if self._is_parent_changed(new_resource):
+                changes.add_changed(new_resource.parent)
+
+    def _is_parent_changed(self, child):
+        return child.parent in self.resources
+
+    def resource_moved(self, resource, new_resource):
+        changes = _Changes()
+        self._update_changes_caused_by_moved(changes, resource, new_resource)
+        self._perform_changes(changes)
+
+    def resource_created(self, resource):
+        changes = _Changes()
+        self._update_changes_caused_by_created(changes, resource)
+        self._perform_changes(changes)
+
+    def _update_changes_caused_by_created(self, changes, resource):
+        if resource in self.resources:
+            changes.add_created(resource)
+        if self._is_parent_changed(resource):
+            changes.add_changed(resource.parent)
+
+    def resource_removed(self, resource):
+        changes = _Changes()
+        self._update_changes_caused_by_moved(changes, resource)
+        self._perform_changes(changes)
+
+    def _perform_changes(self, changes):
+        for resource in changes.changes:
+            self.observer.resource_changed(resource)
+            self.resources[resource] = self.timekeeper.get_indicator(resource)
+        for resource, new_resource in changes.moves.items():
+            self.resources[resource] = None
+            if new_resource is not None:
+                self.observer.resource_moved(resource, new_resource)
+            else:
+                self.observer.resource_removed(resource)
+        for resource in changes.creations:
+            self.observer.resource_created(resource)
+            self.resources[resource] = self.timekeeper.get_indicator(resource)
+
+    def validate(self, resource):
+        moved = self._search_resource_moves(resource)
+        changed = self._search_resource_changes(resource)
+        changes = _Changes()
+        for file in moved:
+            if file in self.resources:
+                self._update_changes_caused_by_moved(changes, file)
+        for file in changed:
+            if file in self.resources:
+                self._update_changes_caused_by_changed(changes, file)
+        for file in self._search_resource_creations(resource):
+            if file in self.resources:
+                changes.add_created(file)
+        self._perform_changes(changes)
+
+    def _search_resource_creations(self, resource):
+        creations = set()
+        if resource in self.resources and resource.exists() and \
+           self.resources[resource] == None:
+            creations.add(resource)
+        if resource.is_folder():
+            for file in self.resources:
+                if file.exists() and resource.contains(file) and \
+                   self.resources[file] == None:
+                    creations.add(file)
+        return creations
+
+    def _search_resource_moves(self, resource):
+        all_moved = set()
+        if resource in self.resources and not resource.exists():
+            all_moved.add(resource)
+        if resource.is_folder():
+            for file in self.resources:
+                if resource.contains(file):
+                    if not file.exists():
+                        all_moved.add(file)
+        moved = set(all_moved)
+        for folder in [file for file in all_moved if file.is_folder()]:
+            if folder in moved:
+                for file in list(moved):
+                    if folder.contains(file):
+                        moved.remove(file)
+        return moved
+
+    def _search_resource_changes(self, resource):
+        changed = set()
+        if resource in self.resources and self._is_changed(resource):
+            changed.add(resource)
+        if resource.is_folder():
+            for file in self.resources:
+                if file.exists() and resource.contains(file):
+                    if self._is_changed(file):
+                        changed.add(file)
+        return changed
+
+    def _is_changed(self, resource):
+        if self.resources[resource] is None:
+            return False
+        return self.resources[resource] != self.timekeeper.get_indicator(resource)
+
+    def _calculate_new_resource(self, main, new_main, resource):
+        if new_main is None:
+            return None
+        diff = resource.path[len(main.path):]
+        return resource.project.get_resource(new_main.path + diff)
+
+
+class ChangeIndicator(object):
+
+    def get_indicator(self, resource):
+        """Return the modification time and size of a `Resource`."""
+        return (os.path.getmtime(resource.real_path),
+                os.path.getsize(resource.real_path))
+
+
+class _Changes(object):
+
+    def __init__(self):
+        self.changes = set()
+        self.creations = set()
+        self.moves = {}
+
+    def add_changed(self, resource):
+        self.changes.add(resource)
+
+    def add_removed(self, resource, new_resource=None):
+        self.moves[resource] = new_resource
+
+    def add_created(self, resource):
+        self.creations.add(resource)

ropetest/projecttest.py

 from rope.base.exceptions import RopeError, ResourceNotFoundError
 from rope.base.fscommands import FileSystemCommands
 from rope.base.libutils import path_to_resource
-from rope.base.project import (Project, NoProject,
-                               FilteredResourceObserver, _realpath)
+from rope.base.project import Project, NoProject, _realpath
 from ropetest import testutils
+import rope.base.resourceobserver
 
 
 class ProjectTest(unittest.TestCase):
         sample_file = self.project.root.create_file('my_file.txt')
         sample_file.write('text')
         sample_observer = _SampleObserver()
-        self.project.add_observer(FilteredResourceObserver(sample_observer,
+        self.project.add_observer(rope.base.resourceobserver.FilteredResourceObserver(sample_observer,
                                                            [sample_file]))
         sample_file.remove()
         self.assertEquals(1, sample_observer.change_count)
         my_folder = root_folder.create_folder('my_folder')
         my_folder_observer = _SampleObserver()
         root_folder_observer = _SampleObserver()
-        self.project.add_observer(FilteredResourceObserver(my_folder_observer,
+        self.project.add_observer(rope.base.resourceobserver.FilteredResourceObserver(my_folder_observer,
                                                            [my_folder]))
-        self.project.add_observer(FilteredResourceObserver(root_folder_observer,
+        self.project.add_observer(rope.base.resourceobserver.FilteredResourceObserver(root_folder_observer,
                                                            [root_folder]))
         my_file = my_folder.create_file('my_file.txt')
         self.assertEquals(1, my_folder_observer.change_count)
         root = self.project.root
         my_file = root.create_file('my_file.txt')
         sample_observer = _SampleObserver()
-        self.project.add_observer(FilteredResourceObserver(sample_observer,
+        self.project.add_observer(rope.base.resourceobserver.FilteredResourceObserver(sample_observer,
                                                            [my_file]))
         os.remove(my_file.real_path)
         self.project.validate(root)
         root = self.project.root
         my_file = root.create_file('my_file.txt')
         sample_observer = _SampleObserver()
-        self.project.add_observer(FilteredResourceObserver(sample_observer,
+        self.project.add_observer(rope.base.resourceobserver.FilteredResourceObserver(sample_observer,
                                                            [my_file]))
         self.project.validate(root)
         self.assertEquals(None, sample_observer.last_moved)
         my_folder = root.create_folder('myfolder')
         my_file = my_folder.create_file('myfile.txt')
         sample_observer = _SampleObserver()
-        self.project.add_observer(FilteredResourceObserver(sample_observer,
+        self.project.add_observer(rope.base.resourceobserver.FilteredResourceObserver(sample_observer,
                                                            [my_folder]))
         testutils.remove_recursively(my_folder.real_path)
         self.project.validate(root)
     def test_removing_and_adding_resources_to_filtered_observer(self):
         my_file = self.project.root.create_file('my_file.txt')
         sample_observer = _SampleObserver()
-        filtered_observer = FilteredResourceObserver(sample_observer)
+        filtered_observer = rope.base.resourceobserver.FilteredResourceObserver(sample_observer)
         self.project.add_observer(filtered_observer)
         my_file.write('1')
         self.assertEquals(0, sample_observer.change_count)
         my_file = self.project.root.create_file('my_file.txt')
         sample_observer = _SampleObserver()
         timekeeper = _MockChangeIndicator()
-        filtered_observer = FilteredResourceObserver(sample_observer, [my_file],
+        filtered_observer = rope.base.resourceobserver.FilteredResourceObserver(sample_observer, [my_file],
                                                      timekeeper=timekeeper)
         self.project.add_observer(filtered_observer)
         self._write_file(my_file.real_path)
         my_file = self.project.root.create_file('my_file.txt')
         sample_observer = _SampleObserver()
         timekeeper = _MockChangeIndicator()
-        self.project.add_observer(FilteredResourceObserver(
+        self.project.add_observer(rope.base.resourceobserver.FilteredResourceObserver(
                                   sample_observer, [my_file],
                                   timekeeper=timekeeper))
         timekeeper.set_indicator(my_file, 1)
         file1 = root.create_file('file1.txt')
         file2 = root.create_file('file2.txt')
         sample_observer = _SampleObserver()
-        self.project.add_observer(FilteredResourceObserver(
+        self.project.add_observer(rope.base.resourceobserver.FilteredResourceObserver(
                                   sample_observer, [root, file1, file2]))
         os.remove(file1.real_path)
         os.remove(file2.real_path)
         my_folder = self.project.root.create_folder('my_folder')
         my_file = my_folder.create_file('my_file.txt')
         sample_observer = _SampleObserver()
-        filtered_observer = FilteredResourceObserver(
+        filtered_observer = rope.base.resourceobserver.FilteredResourceObserver(
             sample_observer, [my_folder, my_file])
         self.project.add_observer(filtered_observer)
         my_folder.move('new_folder')
         my_file = self.project.get_file('my_file.txt')
         sample_observer = _SampleObserver()
         self.project.add_observer(
-            FilteredResourceObserver(sample_observer, [my_file]))
+            rope.base.resourceobserver.FilteredResourceObserver(sample_observer, [my_file]))
         file(my_file.real_path, 'w').close()
         self.project.validate(root)
         self.assertEquals(my_file, sample_observer.last_created)
         my_file = self.project.get_file('my_file.txt')
         sample_observer = _SampleObserver()
         self.project.add_observer(
-            FilteredResourceObserver(sample_observer, [my_file]))
+            rope.base.resourceobserver.FilteredResourceObserver(sample_observer, [my_file]))
         file(my_file.real_path, 'w').close()
         self.project.validate(root)
         self.project.validate(root)
         file1.create()
         sample_observer = _SampleObserver()
         self.project.add_observer(
-            FilteredResourceObserver(sample_observer, [file1, file2]))
+            rope.base.resourceobserver.FilteredResourceObserver(sample_observer, [file1, file2]))
         file1.move(file2.path)
         self.assertEquals(2, sample_observer.change_count)
         self.assertEquals(file2, sample_observer.last_created)
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.