Anonymous avatar Anonymous committed 6ee24df

Handling __call__ in staticoi

Comments (0)

Files changed (7)

docs/dev/workingon.txt

 Small Stories
 =============
 
-- Updating docs in ``rope.base.oi.__init__.py``
+- Handling `__call__` in staticoi
 
 * Handling strings in following lines in `patchedast`
 * Extracting subexpressions; look at `extracttest` for more info
 * Refactorings
 
   * Rename everything!
-  * Extract method
-  * Extract local variable
+  * Extract method/local variable
   * Move class/function/module/package/method
   * Inline method/local variable
   * Change method signature

rope/base/evaluate.py

     args.extend(call_node.keywords)
     called = call_node.func
     # XXX: Handle constructors
-    if _is_method_call(primary, pyfunction):
+    if _is_method_call(primary, pyfunction) and \
+       isinstance(called, ast.Attribute):
         args.insert(0, called.value)
     return Arguments(args, scope)
 

rope/base/oi/staticoi.py

         if pyname is None:
             return
         pyfunction = pyname.get_object()
-        if not isinstance(pyfunction, pyobjects.PyClass) and \
-           '__call__' in pyfunction.get_attributes():
-            pyfunction = pyfunction.get_attribute('__call__')
         if isinstance(pyfunction, pyobjects.AbstractFunction):
             args = evaluate.create_arguments(primary, pyfunction,
                                              node, self.scope)
             if '__init__' in pyfunction.get_attributes():
                 pyfunction = pyfunction.get_attribute('__init__').get_object()
             pyname = pynames.UnboundName(pyobjects.PyObject(pyclass))
-            base_args = evaluate.create_arguments(primary, pyfunction,
-                                                  node, self.scope)
-            args = evaluate.MixedArguments(pyname, base_args, self.scope)
+            args = self._args_with_self(primary, pyname, pyfunction, node)
+        elif '__call__' in pyfunction.get_attributes():
+            pyfunction = pyfunction.get_attribute('__call__').get_object()
+            args = self._args_with_self(primary, pyname, pyfunction, node)
         else:
             return
         self._call(pyfunction, args)
 
+    def _args_with_self(self, primary, self_pyname, pyfunction, node):
+        base_args = evaluate.create_arguments(primary, pyfunction,
+                                              node, self.scope)
+        return evaluate.MixedArguments(self_pyname, base_args, self.scope)
+
     def _call(self, pyfunction, args):
         if isinstance(pyfunction, pyobjects.PyFunction):
             self.pycore.object_info.function_called(

rope/refactor/extract.py

         if self.info.one_line:
             return 'return ' + _join_lines(self.info.extracted)
         extracted_body = self.info.extracted
-        unindented_body = sourceutils.indent_lines(
-            extracted_body, -sourceutils.find_minimum_indents(extracted_body))
+        unindented_body = sourceutils.fix_indentation(extracted_body, 0)
         if returns:
             unindented_body += '\nreturn %s' % self._get_comma_form(returns)
         return unindented_body
     def find_reads_and_writes(code):
         if code.strip() == '':
             return set(), set()
-        min_indents = sourceutils.find_minimum_indents(code)
-        indented_code = sourceutils.indent_lines(code, -min_indents)
+        indented_code = sourceutils.fix_indentation(code, 0)
         if isinstance(indented_body, unicode):
             indented_body = indented_body.encode('utf-8')
         node = _parse_text(indented_code)
     def does_it_return(code):
         if code.strip() == '':
             return False
-        min_indents = sourceutils.find_minimum_indents(code)
-        indented_code = sourceutils.indent_lines(code, -min_indents)
+        indented_code = sourceutils.fix_indentation(code, 0)
         node = _parse_text(indented_code)
         visitor = _ReturnOrYieldFinder()
         ast.walk(node, visitor)
     def has_errors(code):
         if code.strip() == '':
             return False
-        min_indents = sourceutils.find_minimum_indents(code)
-        indented_code = sourceutils.indent_lines(code, -min_indents)
+        indented_code = sourceutils.fix_indentation(code, 0)
         node = _parse_text(indented_code)
         visitor = _UnmatchedBreakOrContinueFinder()
         ast.walk(node, visitor)

rope/refactor/sourceutils.py

 
 
 def fix_indentation(code, new_indents):
+    """Change the indentation of `code` to `new_indents`"""
     min_indents = find_minimum_indents(code)
     return indent_lines(code, new_indents - min_indents)
 

ropetest/advanced_oi_test.py

         arg2 = f_scope.get_name('arg2').get_object()
         self.assertEquals(c1_class, arg2.get_type())
 
+    def test_call_function_and_parameters(self):
+        code = 'class A(object):\n    def __call__(self, p):\n        pass\n' \
+               'A()("")\n'
+        self.mod.write(code)
+        self.pycore.analyze_module(self.mod)
+        scope = self.pycore.resource_to_pyobject(self.mod).get_scope()
+        p_object = scope.get_scopes()[0].get_scopes()[0].\
+                   get_name('p').get_object()
+        self.assertTrue(isinstance(p_object.get_type(),
+                                   rope.base.builtins.Str))
+
 
 def suite():
     result = unittest.TestSuite()
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.