Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
marvel
GitHub Repository: marvel/qnf
Path: blob/master/elisp/emacs-for-python/rope-dist/rope/refactor/functionutils.py
1415 views
1
import rope.base.exceptions
2
import rope.base.pyobjects
3
from rope.base.builtins import Lambda
4
from rope.base import worder
5
6
7
class DefinitionInfo(object):
8
9
def __init__(self, function_name, is_method, args_with_defaults,
10
args_arg, keywords_arg):
11
self.function_name = function_name
12
self.is_method = is_method
13
self.args_with_defaults = args_with_defaults
14
self.args_arg = args_arg
15
self.keywords_arg = keywords_arg
16
17
def to_string(self):
18
return '%s(%s)' % (self.function_name, self.arguments_to_string())
19
20
def arguments_to_string(self, from_index=0):
21
params = []
22
for arg, default in self.args_with_defaults:
23
if default is not None:
24
params.append('%s=%s' % (arg, default))
25
else:
26
params.append(arg)
27
if self.args_arg is not None:
28
params.append('*' + self.args_arg)
29
if self.keywords_arg:
30
params.append('**' + self.keywords_arg)
31
return ', '.join(params[from_index:])
32
33
@staticmethod
34
def _read(pyfunction, code):
35
scope = pyfunction.get_scope()
36
parent = scope.parent
37
parameter_names = pyfunction.get_param_names()
38
kind = pyfunction.get_kind()
39
is_method = kind == 'method'
40
is_lambda = kind == 'lambda'
41
info = _FunctionParser(code, is_method, is_lambda)
42
args, keywords = info.get_parameters()
43
args_arg = None
44
keywords_arg = None
45
if args and args[-1].startswith('**'):
46
keywords_arg = args[-1][2:]
47
del args[-1]
48
if args and args[-1].startswith('*'):
49
args_arg = args[-1][1:]
50
del args[-1]
51
args_with_defaults = [(name, None) for name in args]
52
args_with_defaults.extend(keywords)
53
return DefinitionInfo(info.get_function_name(), is_method,
54
args_with_defaults, args_arg, keywords_arg)
55
56
@staticmethod
57
def read(pyfunction):
58
pymodule = pyfunction.get_module()
59
word_finder = worder.Worder(pymodule.source_code)
60
lineno = pyfunction.get_ast().lineno
61
start = pymodule.lines.get_line_start(lineno)
62
if isinstance(pyfunction, Lambda):
63
call = word_finder.get_lambda_and_args(start)
64
else:
65
call = word_finder.get_function_and_args_in_header(start)
66
return DefinitionInfo._read(pyfunction, call)
67
68
69
class CallInfo(object):
70
71
def __init__(self, function_name, args, keywords, args_arg,
72
keywords_arg, implicit_arg, constructor):
73
self.function_name = function_name
74
self.args = args
75
self.keywords = keywords
76
self.args_arg = args_arg
77
self.keywords_arg = keywords_arg
78
self.implicit_arg = implicit_arg
79
self.constructor = constructor
80
81
def to_string(self):
82
function = self.function_name
83
if self.implicit_arg:
84
function = self.args[0] + '.' + self.function_name
85
params = []
86
start = 0
87
if self.implicit_arg or self.constructor:
88
start = 1
89
if self.args[start:]:
90
params.extend(self.args[start:])
91
if self.keywords:
92
params.extend(['%s=%s' % (name, value) for name, value in self.keywords])
93
if self.args_arg is not None:
94
params.append('*' + self.args_arg)
95
if self.keywords_arg:
96
params.append('**' + self.keywords_arg)
97
return '%s(%s)' % (function, ', '.join(params))
98
99
@staticmethod
100
def read(primary, pyname, definition_info, code):
101
is_method_call = CallInfo._is_method_call(primary, pyname)
102
is_constructor = CallInfo._is_class(pyname)
103
is_classmethod = CallInfo._is_classmethod(pyname)
104
info = _FunctionParser(code, is_method_call or is_classmethod)
105
args, keywords = info.get_parameters()
106
args_arg = None
107
keywords_arg = None
108
if args and args[-1].startswith('**'):
109
keywords_arg = args[-1][2:]
110
del args[-1]
111
if args and args[-1].startswith('*'):
112
args_arg = args[-1][1:]
113
del args[-1]
114
if is_constructor:
115
args.insert(0, definition_info.args_with_defaults[0][0])
116
return CallInfo(info.get_function_name(), args, keywords, args_arg,
117
keywords_arg, is_method_call or is_classmethod,
118
is_constructor)
119
120
@staticmethod
121
def _is_method_call(primary, pyname):
122
return primary is not None and \
123
isinstance(primary.get_object().get_type(),
124
rope.base.pyobjects.PyClass) and \
125
CallInfo._is_method(pyname)
126
127
@staticmethod
128
def _is_class(pyname):
129
return pyname is not None and \
130
isinstance(pyname.get_object(),
131
rope.base.pyobjects.PyClass)
132
133
@staticmethod
134
def _is_method(pyname):
135
if pyname is not None and \
136
isinstance(pyname.get_object(), rope.base.pyobjects.PyFunction):
137
return pyname.get_object().get_kind() == 'method'
138
return False
139
140
@staticmethod
141
def _is_classmethod(pyname):
142
if pyname is not None and \
143
isinstance(pyname.get_object(), rope.base.pyobjects.PyFunction):
144
return pyname.get_object().get_kind() == 'classmethod'
145
return False
146
147
148
class ArgumentMapping(object):
149
150
def __init__(self, definition_info, call_info):
151
self.call_info = call_info
152
self.param_dict = {}
153
self.keyword_args = []
154
self.args_arg = []
155
for index, value in enumerate(call_info.args):
156
if index < len(definition_info.args_with_defaults):
157
name = definition_info.args_with_defaults[index][0]
158
self.param_dict[name] = value
159
else:
160
self.args_arg.append(value)
161
for name, value in call_info.keywords:
162
index = -1
163
for pair in definition_info.args_with_defaults:
164
if pair[0] == name:
165
self.param_dict[name] = value
166
break
167
else:
168
self.keyword_args.append((name, value))
169
170
def to_call_info(self, definition_info):
171
args = []
172
keywords = []
173
for index in range(len(definition_info.args_with_defaults)):
174
name = definition_info.args_with_defaults[index][0]
175
if name in self.param_dict:
176
args.append(self.param_dict[name])
177
else:
178
for i in range(index, len(definition_info.args_with_defaults)):
179
name = definition_info.args_with_defaults[i][0]
180
if name in self.param_dict:
181
keywords.append((name, self.param_dict[name]))
182
break
183
args.extend(self.args_arg)
184
keywords.extend(self.keyword_args)
185
return CallInfo(self.call_info.function_name, args, keywords,
186
self.call_info.args_arg, self.call_info.keywords_arg,
187
self.call_info.implicit_arg, self.call_info.constructor)
188
189
190
class _FunctionParser(object):
191
192
def __init__(self, call, implicit_arg, is_lambda=False):
193
self.call = call
194
self.implicit_arg = implicit_arg
195
self.word_finder = worder.Worder(self.call)
196
if is_lambda:
197
self.last_parens = self.call.rindex(':')
198
else:
199
self.last_parens = self.call.rindex(')')
200
self.first_parens = self.word_finder._find_parens_start(self.last_parens)
201
202
def get_parameters(self):
203
args, keywords = self.word_finder.get_parameters(self.first_parens,
204
self.last_parens)
205
if self.is_called_as_a_method():
206
instance = self.call[:self.call.rindex('.', 0, self.first_parens)]
207
args.insert(0, instance.strip())
208
return args, keywords
209
210
def get_instance(self):
211
if self.is_called_as_a_method():
212
return self.word_finder.get_primary_at(
213
self.call.rindex('.', 0, self.first_parens) - 1)
214
215
def get_function_name(self):
216
if self.is_called_as_a_method():
217
return self.word_finder.get_word_at(self.first_parens - 1)
218
else:
219
return self.word_finder.get_primary_at(self.first_parens - 1)
220
221
def is_called_as_a_method(self):
222
return self.implicit_arg and '.' in self.call[:self.first_parens]
223
224