arguments.py 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. import rope.base.evaluate
  2. from rope.base import ast
  3. class Arguments(object):
  4. """A class for evaluating parameters passed to a function
  5. You can use the `create_arguments` factory. It handles implicit
  6. first arguments.
  7. """
  8. def __init__(self, args, scope):
  9. self.args = args
  10. self.scope = scope
  11. self.instance = None
  12. def get_arguments(self, parameters):
  13. result = []
  14. for pyname in self.get_pynames(parameters):
  15. if pyname is None:
  16. result.append(None)
  17. else:
  18. result.append(pyname.get_object())
  19. return result
  20. def get_pynames(self, parameters):
  21. result = [None] * max(len(parameters), len(self.args))
  22. for index, arg in enumerate(self.args):
  23. if isinstance(arg, ast.keyword) and arg.arg in parameters:
  24. result[parameters.index(arg.arg)] = self._evaluate(arg.value)
  25. else:
  26. result[index] = self._evaluate(arg)
  27. return result
  28. def get_instance_pyname(self):
  29. if self.args:
  30. return self._evaluate(self.args[0])
  31. def _evaluate(self, ast_node):
  32. return rope.base.evaluate.eval_node(self.scope, ast_node)
  33. def create_arguments(primary, pyfunction, call_node, scope):
  34. """A factory for creating `Arguments`"""
  35. args = list(call_node.args)
  36. args.extend(call_node.keywords)
  37. called = call_node.func
  38. # XXX: Handle constructors
  39. if _is_method_call(primary, pyfunction) and \
  40. isinstance(called, ast.Attribute):
  41. args.insert(0, called.value)
  42. return Arguments(args, scope)
  43. class ObjectArguments(object):
  44. def __init__(self, pynames):
  45. self.pynames = pynames
  46. def get_arguments(self, parameters):
  47. result = []
  48. for pyname in self.pynames:
  49. if pyname is None:
  50. result.append(None)
  51. else:
  52. result.append(pyname.get_object())
  53. return result
  54. def get_pynames(self, parameters):
  55. return self.pynames
  56. def get_instance_pyname(self):
  57. return self.pynames[0]
  58. class MixedArguments(object):
  59. def __init__(self, pyname, arguments, scope):
  60. """`argumens` is an instance of `Arguments`"""
  61. self.pyname = pyname
  62. self.args = arguments
  63. def get_pynames(self, parameters):
  64. return [self.pyname] + self.args.get_pynames(parameters[1:])
  65. def get_arguments(self, parameters):
  66. result = []
  67. for pyname in self.get_pynames(parameters):
  68. if pyname is None:
  69. result.append(None)
  70. else:
  71. result.append(pyname.get_object())
  72. return result
  73. def get_instance_pyname(self):
  74. return self.pyname
  75. def _is_method_call(primary, pyfunction):
  76. if primary is None:
  77. return False
  78. pyobject = primary.get_object()
  79. if isinstance(pyobject.get_type(), rope.base.pyobjects.PyClass) and \
  80. isinstance(pyfunction, rope.base.pyobjects.PyFunction) and \
  81. isinstance(pyfunction.parent, rope.base.pyobjects.PyClass):
  82. return True
  83. if isinstance(pyobject.get_type(), rope.base.pyobjects.AbstractClass) and \
  84. isinstance(pyfunction, rope.base.builtins.BuiltinFunction):
  85. return True
  86. return False