Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
marvel
GitHub Repository: marvel/qnf
Path: blob/master/elisp/emacs-for-python/rope-dist/rope/base/evaluate.py
1418 views
1
import rope.base.builtins
2
import rope.base.pynames
3
import rope.base.pyobjects
4
from rope.base import ast, astutils, exceptions, pyobjects, arguments, worder
5
6
7
BadIdentifierError = exceptions.BadIdentifierError
8
9
def eval_location(pymodule, offset):
10
"""Find the pyname at the offset"""
11
return eval_location2(pymodule, offset)[1]
12
13
14
def eval_location2(pymodule, offset):
15
"""Find the primary and pyname at offset"""
16
pyname_finder = ScopeNameFinder(pymodule)
17
return pyname_finder.get_primary_and_pyname_at(offset)
18
19
20
def eval_node(scope, node):
21
"""Evaluate a `ast.AST` node and return a PyName
22
23
Return `None` if the expression cannot be evaluated.
24
"""
25
return eval_node2(scope, node)[1]
26
27
28
def eval_node2(scope, node):
29
evaluator = StatementEvaluator(scope)
30
ast.walk(node, evaluator)
31
return evaluator.old_result, evaluator.result
32
33
34
def eval_str(holding_scope, name):
35
return eval_str2(holding_scope, name)[1]
36
37
38
def eval_str2(holding_scope, name):
39
try:
40
# parenthesizing for handling cases like 'a_var.\nattr'
41
node = ast.parse('(%s)' % name)
42
except SyntaxError:
43
raise BadIdentifierError('Not a resolvable python identifier selected.')
44
return eval_node2(holding_scope, node)
45
46
47
class ScopeNameFinder(object):
48
49
def __init__(self, pymodule):
50
self.module_scope = pymodule.get_scope()
51
self.lines = pymodule.lines
52
self.worder = worder.Worder(pymodule.source_code, True)
53
54
def _is_defined_in_class_body(self, holding_scope, offset, lineno):
55
if lineno == holding_scope.get_start() and \
56
holding_scope.parent is not None and \
57
holding_scope.parent.get_kind() == 'Class' and \
58
self.worder.is_a_class_or_function_name_in_header(offset):
59
return True
60
if lineno != holding_scope.get_start() and \
61
holding_scope.get_kind() == 'Class' and \
62
self.worder.is_name_assigned_in_class_body(offset):
63
return True
64
return False
65
66
def _is_function_name_in_function_header(self, scope, offset, lineno):
67
if scope.get_start() <= lineno <= scope.get_body_start() and \
68
scope.get_kind() == 'Function' and \
69
self.worder.is_a_class_or_function_name_in_header(offset):
70
return True
71
return False
72
73
def get_pyname_at(self, offset):
74
return self.get_primary_and_pyname_at(offset)[1]
75
76
def get_primary_and_pyname_at(self, offset):
77
lineno = self.lines.get_line_number(offset)
78
holding_scope = self.module_scope.get_inner_scope_for_line(lineno)
79
# function keyword parameter
80
if self.worder.is_function_keyword_parameter(offset):
81
keyword_name = self.worder.get_word_at(offset)
82
pyobject = self.get_enclosing_function(offset)
83
if isinstance(pyobject, pyobjects.PyFunction):
84
return (None, pyobject.get_parameters().get(keyword_name, None))
85
# class body
86
if self._is_defined_in_class_body(holding_scope, offset, lineno):
87
class_scope = holding_scope
88
if lineno == holding_scope.get_start():
89
class_scope = holding_scope.parent
90
name = self.worder.get_primary_at(offset).strip()
91
try:
92
return (None, class_scope.pyobject[name])
93
except rope.base.exceptions.AttributeNotFoundError:
94
return (None, None)
95
# function header
96
if self._is_function_name_in_function_header(holding_scope, offset, lineno):
97
name = self.worder.get_primary_at(offset).strip()
98
return (None, holding_scope.parent[name])
99
# from statement module
100
if self.worder.is_from_statement_module(offset):
101
module = self.worder.get_primary_at(offset)
102
module_pyname = self._find_module(module)
103
return (None, module_pyname)
104
if self.worder.is_from_aliased(offset):
105
name = self.worder.get_from_aliased(offset)
106
else:
107
name = self.worder.get_primary_at(offset)
108
return eval_str2(holding_scope, name)
109
110
def get_enclosing_function(self, offset):
111
function_parens = self.worder.find_parens_start_from_inside(offset)
112
try:
113
function_pyname = self.get_pyname_at(function_parens - 1)
114
except BadIdentifierError:
115
function_pyname = None
116
if function_pyname is not None:
117
pyobject = function_pyname.get_object()
118
if isinstance(pyobject, pyobjects.AbstractFunction):
119
return pyobject
120
elif isinstance(pyobject, pyobjects.AbstractClass) and \
121
'__init__' in pyobject:
122
return pyobject['__init__'].get_object()
123
elif '__call__' in pyobject:
124
return pyobject['__call__'].get_object()
125
return None
126
127
def _find_module(self, module_name):
128
dots = 0
129
while module_name[dots] == '.':
130
dots += 1
131
return rope.base.pynames.ImportedModule(
132
self.module_scope.pyobject, module_name[dots:], dots)
133
134
135
class StatementEvaluator(object):
136
137
def __init__(self, scope):
138
self.scope = scope
139
self.result = None
140
self.old_result = None
141
142
def _Name(self, node):
143
self.result = self.scope.lookup(node.id)
144
145
def _Attribute(self, node):
146
pyname = eval_node(self.scope, node.value)
147
if pyname is None:
148
pyname = rope.base.pynames.UnboundName()
149
self.old_result = pyname
150
if pyname.get_object() != rope.base.pyobjects.get_unknown():
151
try:
152
self.result = pyname.get_object()[node.attr]
153
except exceptions.AttributeNotFoundError:
154
self.result = None
155
156
def _Call(self, node):
157
primary, pyobject = self._get_primary_and_object_for_node(node.func)
158
if pyobject is None:
159
return
160
def _get_returned(pyobject):
161
args = arguments.create_arguments(primary, pyobject,
162
node, self.scope)
163
return pyobject.get_returned_object(args)
164
if isinstance(pyobject, rope.base.pyobjects.AbstractClass):
165
result = None
166
if '__new__' in pyobject:
167
new_function = pyobject['__new__'].get_object()
168
result = _get_returned(new_function)
169
if result is None or \
170
result == rope.base.pyobjects.get_unknown():
171
result = rope.base.pyobjects.PyObject(pyobject)
172
self.result = rope.base.pynames.UnboundName(pyobject=result)
173
return
174
175
pyfunction = None
176
if isinstance(pyobject, rope.base.pyobjects.AbstractFunction):
177
pyfunction = pyobject
178
elif '__call__' in pyobject:
179
pyfunction = pyobject['__call__'].get_object()
180
if pyfunction is not None:
181
self.result = rope.base.pynames.UnboundName(
182
pyobject=_get_returned(pyfunction))
183
184
def _Str(self, node):
185
self.result = rope.base.pynames.UnboundName(
186
pyobject=rope.base.builtins.get_str())
187
188
def _Num(self, node):
189
type_name = type(node.n).__name__
190
self.result = self._get_builtin_name(type_name)
191
192
def _get_builtin_name(self, type_name):
193
pytype = rope.base.builtins.builtins[type_name].get_object()
194
return rope.base.pynames.UnboundName(
195
rope.base.pyobjects.PyObject(pytype))
196
197
def _BinOp(self, node):
198
self.result = rope.base.pynames.UnboundName(
199
self._get_object_for_node(node.left))
200
201
def _BoolOp(self, node):
202
self.result = rope.base.pynames.UnboundName(
203
self._get_object_for_node(node.values[0]))
204
205
def _Repr(self, node):
206
self.result = self._get_builtin_name('str')
207
208
def _UnaryOp(self, node):
209
self.result = rope.base.pynames.UnboundName(
210
self._get_object_for_node(node.operand))
211
212
def _Compare(self, node):
213
self.result = self._get_builtin_name('bool')
214
215
def _Dict(self, node):
216
keys = None
217
values = None
218
if node.keys:
219
keys = self._get_object_for_node(node.keys[0])
220
values = self._get_object_for_node(node.values[0])
221
self.result = rope.base.pynames.UnboundName(
222
pyobject=rope.base.builtins.get_dict(keys, values))
223
224
def _List(self, node):
225
holding = None
226
if node.elts:
227
holding = self._get_object_for_node(node.elts[0])
228
self.result = rope.base.pynames.UnboundName(
229
pyobject=rope.base.builtins.get_list(holding))
230
231
def _ListComp(self, node):
232
pyobject = self._what_does_comprehension_hold(node)
233
self.result = rope.base.pynames.UnboundName(
234
pyobject=rope.base.builtins.get_list(pyobject))
235
236
def _GeneratorExp(self, node):
237
pyobject = self._what_does_comprehension_hold(node)
238
self.result = rope.base.pynames.UnboundName(
239
pyobject=rope.base.builtins.get_iterator(pyobject))
240
241
def _what_does_comprehension_hold(self, node):
242
scope = self._make_comprehension_scope(node)
243
pyname = eval_node(scope, node.elt)
244
return pyname.get_object() if pyname is not None else None
245
246
def _make_comprehension_scope(self, node):
247
scope = self.scope
248
module = scope.pyobject.get_module()
249
names = {}
250
for comp in node.generators:
251
new_names = _get_evaluated_names(comp.target, comp.iter, module,
252
'.__iter__().next()', node.lineno)
253
names.update(new_names)
254
return rope.base.pyscopes.TemporaryScope(scope.pycore, scope, names)
255
256
def _Tuple(self, node):
257
objects = []
258
if len(node.elts) < 4:
259
for stmt in node.elts:
260
pyobject = self._get_object_for_node(stmt)
261
objects.append(pyobject)
262
else:
263
objects.append(self._get_object_for_node(node.elts[0]))
264
self.result = rope.base.pynames.UnboundName(
265
pyobject=rope.base.builtins.get_tuple(*objects))
266
267
def _get_object_for_node(self, stmt):
268
pyname = eval_node(self.scope, stmt)
269
pyobject = None
270
if pyname is not None:
271
pyobject = pyname.get_object()
272
return pyobject
273
274
def _get_primary_and_object_for_node(self, stmt):
275
primary, pyname = eval_node2(self.scope, stmt)
276
pyobject = None
277
if pyname is not None:
278
pyobject = pyname.get_object()
279
return primary, pyobject
280
281
def _Subscript(self, node):
282
if isinstance(node.slice, ast.Index):
283
self._call_function(node.value, '__getitem__',
284
[node.slice.value])
285
elif isinstance(node.slice, ast.Slice):
286
self._call_function(node.value, '__getslice__')
287
288
def _call_function(self, node, function_name, other_args=None):
289
pyname = eval_node(self.scope, node)
290
if pyname is not None:
291
pyobject = pyname.get_object()
292
else:
293
return
294
if function_name in pyobject:
295
called = pyobject[function_name].get_object()
296
if not called or not isinstance(called, pyobjects.AbstractFunction):
297
return
298
args = [node]
299
if other_args:
300
args += other_args
301
arguments_ = arguments.Arguments(args, self.scope)
302
self.result = rope.base.pynames.UnboundName(
303
pyobject=called.get_returned_object(arguments_))
304
305
def _Lambda(self, node):
306
self.result = rope.base.pynames.UnboundName(
307
pyobject=rope.base.builtins.Lambda(node, self.scope))
308
309
310
def _get_evaluated_names(targets, assigned, module, evaluation, lineno):
311
result = {}
312
for name, levels in astutils.get_name_levels(targets):
313
assignment = rope.base.pynames.AssignmentValue(assigned, levels,
314
evaluation)
315
# XXX: this module should not access `rope.base.pynamesdef`!
316
pyname = rope.base.pynamesdef.AssignedName(lineno, module)
317
pyname.assignments.append(assignment)
318
result[name] = pyname
319
return result
320
321