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/oi/transform.py
1421 views
1
"""Provides classes for persisting `PyObject`\s"""
2
import os
3
import re
4
5
import rope.base.builtins
6
from rope.base import exceptions
7
8
9
class PyObjectToTextual(object):
10
"""For transforming `PyObject` to textual form
11
12
This can be used for storing `PyObjects` in files. Use
13
`TextualToPyObject` for converting back.
14
15
"""
16
17
def __init__(self, project):
18
self.project = project
19
20
def transform(self, pyobject):
21
"""Transform a `PyObject` to textual form"""
22
if pyobject is None:
23
return ('none',)
24
object_type = type(pyobject)
25
try:
26
method = getattr(self, object_type.__name__ + '_to_textual')
27
return method(pyobject)
28
except AttributeError:
29
return ('unknown',)
30
31
def __call__(self, pyobject):
32
return self.transform(pyobject)
33
34
def PyObject_to_textual(self, pyobject):
35
if isinstance(pyobject.get_type(), rope.base.pyobjects.AbstractClass):
36
result = self.transform(pyobject.get_type())
37
if result[0] == 'defined':
38
return ('instance', result)
39
return result
40
return ('unknown',)
41
42
def PyFunction_to_textual(self, pyobject):
43
return self._defined_to_textual(pyobject)
44
45
def PyClass_to_textual(self, pyobject):
46
return self._defined_to_textual(pyobject)
47
48
def _defined_to_textual(self, pyobject):
49
address = []
50
while pyobject.parent is not None:
51
address.insert(0, pyobject.get_name())
52
pyobject = pyobject.parent
53
return ('defined', self._get_pymodule_path(pyobject.get_module()),
54
'.'.join(address))
55
56
def PyModule_to_textual(self, pyobject):
57
return ('defined', self._get_pymodule_path(pyobject))
58
59
def PyPackage_to_textual(self, pyobject):
60
return ('defined', self._get_pymodule_path(pyobject))
61
62
def List_to_textual(self, pyobject):
63
return ('builtin', 'list', self.transform(pyobject.holding))
64
65
def Dict_to_textual(self, pyobject):
66
return ('builtin', 'dict', self.transform(pyobject.keys),
67
self.transform(pyobject.values))
68
69
def Tuple_to_textual(self, pyobject):
70
objects = [self.transform(holding)
71
for holding in pyobject.get_holding_objects()]
72
return tuple(['builtin', 'tuple'] + objects)
73
74
def Set_to_textual(self, pyobject):
75
return ('builtin', 'set', self.transform(pyobject.holding))
76
77
def Iterator_to_textual(self, pyobject):
78
return ('builtin', 'iter', self.transform(pyobject.holding))
79
80
def Generator_to_textual(self, pyobject):
81
return ('builtin', 'generator', self.transform(pyobject.holding))
82
83
def Str_to_textual(self, pyobject):
84
return ('builtin', 'str')
85
86
def File_to_textual(self, pyobject):
87
return ('builtin', 'file')
88
89
def BuiltinFunction_to_textual(self, pyobject):
90
return ('builtin', 'function', pyobject.get_name())
91
92
def _get_pymodule_path(self, pymodule):
93
return self.resource_to_path(pymodule.get_resource())
94
95
def resource_to_path(self, resource):
96
if resource.project == self.project:
97
return resource.path
98
else:
99
return resource.real_path
100
101
102
class TextualToPyObject(object):
103
"""For transforming textual form to `PyObject`"""
104
105
def __init__(self, project, allow_in_project_absolutes=False):
106
self.project = project
107
108
def __call__(self, textual):
109
return self.transform(textual)
110
111
def transform(self, textual):
112
"""Transform an object from textual form to `PyObject`"""
113
if textual is None:
114
return None
115
type = textual[0]
116
try:
117
method = getattr(self, type + '_to_pyobject')
118
return method(textual)
119
except AttributeError:
120
return None
121
122
def builtin_to_pyobject(self, textual):
123
name = textual[1]
124
method = getattr(self, 'builtin_%s_to_pyobject' % textual[1], None)
125
if method is not None:
126
return method(textual)
127
128
def builtin_str_to_pyobject(self, textual):
129
return rope.base.builtins.get_str()
130
131
def builtin_list_to_pyobject(self, textual):
132
holding = self.transform(textual[2])
133
return rope.base.builtins.get_list(holding)
134
135
def builtin_dict_to_pyobject(self, textual):
136
keys = self.transform(textual[2])
137
values = self.transform(textual[3])
138
return rope.base.builtins.get_dict(keys, values)
139
140
def builtin_tuple_to_pyobject(self, textual):
141
objects = []
142
for holding in textual[2:]:
143
objects.append(self.transform(holding))
144
return rope.base.builtins.get_tuple(*objects)
145
146
def builtin_set_to_pyobject(self, textual):
147
holding = self.transform(textual[2])
148
return rope.base.builtins.get_set(holding)
149
150
def builtin_iter_to_pyobject(self, textual):
151
holding = self.transform(textual[2])
152
return rope.base.builtins.get_iterator(holding)
153
154
def builtin_generator_to_pyobject(self, textual):
155
holding = self.transform(textual[2])
156
return rope.base.builtins.get_generator(holding)
157
158
def builtin_file_to_pyobject(self, textual):
159
return rope.base.builtins.get_file()
160
161
def builtin_function_to_pyobject(self, textual):
162
if textual[2] in rope.base.builtins.builtins:
163
return rope.base.builtins.builtins[textual[2]].get_object()
164
165
def unknown_to_pyobject(self, textual):
166
return None
167
168
def none_to_pyobject(self, textual):
169
return None
170
171
def _module_to_pyobject(self, textual):
172
path = textual[1]
173
return self._get_pymodule(path)
174
175
def _hierarchical_defined_to_pyobject(self, textual):
176
path = textual[1]
177
names = textual[2].split('.')
178
pymodule = self._get_pymodule(path)
179
pyobject = pymodule
180
for name in names:
181
if pyobject is None:
182
return None
183
if isinstance(pyobject, rope.base.pyobjects.PyDefinedObject):
184
try:
185
pyobject = pyobject.get_scope()[name].get_object()
186
except exceptions.NameNotFoundError:
187
return None
188
else:
189
return None
190
return pyobject
191
192
def defined_to_pyobject(self, textual):
193
if len(textual) == 2 or textual[2] == '':
194
return self._module_to_pyobject(textual)
195
else:
196
return self._hierarchical_defined_to_pyobject(textual)
197
198
def instance_to_pyobject(self, textual):
199
type = self.transform(textual[1])
200
if type is not None:
201
return rope.base.pyobjects.PyObject(type)
202
203
def _get_pymodule(self, path):
204
resource = self.path_to_resource(path)
205
if resource is not None:
206
return self.project.pycore.resource_to_pyobject(resource)
207
208
def path_to_resource(self, path):
209
try:
210
root = self.project.address
211
if not os.path.isabs(path):
212
return self.project.get_resource(path)
213
if path == root or path.startswith(root + os.sep):
214
# INFO: This is a project file; should not be absolute
215
return None
216
import rope.base.project
217
return rope.base.project.get_no_project().get_resource(path)
218
except exceptions.ResourceNotFoundError:
219
return None
220
221
222
class DOITextualToPyObject(TextualToPyObject):
223
"""For transforming textual form to `PyObject`
224
225
The textual form DOI uses is different from rope's standard
226
textual form. The reason is that we cannot find the needed
227
information by analyzing live objects. This class can be
228
used to transform DOI textual form to `PyObject` and later
229
we can convert it to standard textual form using
230
`TextualToPyObject` class.
231
232
"""
233
234
def _function_to_pyobject(self, textual):
235
path = textual[1]
236
lineno = int(textual[2])
237
pymodule = self._get_pymodule(path)
238
if pymodule is not None:
239
scope = pymodule.get_scope()
240
inner_scope = scope.get_inner_scope_for_line(lineno)
241
return inner_scope.pyobject
242
243
def _class_to_pyobject(self, textual):
244
path, name = textual[1:]
245
pymodule = self._get_pymodule(path)
246
if pymodule is None:
247
return None
248
module_scope = pymodule.get_scope()
249
suspected = None
250
if name in module_scope.get_names():
251
suspected = module_scope[name].get_object()
252
if suspected is not None and \
253
isinstance(suspected, rope.base.pyobjects.PyClass):
254
return suspected
255
else:
256
lineno = self._find_occurrence(name, pymodule.get_resource().read())
257
if lineno is not None:
258
inner_scope = module_scope.get_inner_scope_for_line(lineno)
259
return inner_scope.pyobject
260
261
def defined_to_pyobject(self, textual):
262
if len(textual) == 2:
263
return self._module_to_pyobject(textual)
264
else:
265
if textual[2].isdigit():
266
result = self._function_to_pyobject(textual)
267
else:
268
result = self._class_to_pyobject(textual)
269
if not isinstance(result, rope.base.pyobjects.PyModule):
270
return result
271
272
def _find_occurrence(self, name, source):
273
pattern = re.compile(r'^\s*class\s*' + name + r'\b')
274
lines = source.split('\n')
275
for i in range(len(lines)):
276
if pattern.match(lines[i]):
277
return i + 1
278
279
def path_to_resource(self, path):
280
import rope.base.libutils
281
root = self.project.address
282
relpath = rope.base.libutils.relative(root, path)
283
if relpath is not None:
284
path = relpath
285
return super(DOITextualToPyObject, self).path_to_resource(path)
286
287