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/pyobjects.py
1415 views
1
from rope.base.fscommands import _decode_data
2
from rope.base import ast, exceptions, utils
3
4
5
class PyObject(object):
6
7
def __init__(self, type_):
8
if type_ is None:
9
type_ = self
10
self.type = type_
11
12
def get_attributes(self):
13
if self.type is self:
14
return {}
15
return self.type.get_attributes()
16
17
def get_attribute(self, name):
18
if name not in self.get_attributes():
19
raise exceptions.AttributeNotFoundError(
20
'Attribute %s not found' % name)
21
return self.get_attributes()[name]
22
23
def get_type(self):
24
return self.type
25
26
def __getitem__(self, key):
27
"""The same as ``get_attribute(key)``"""
28
return self.get_attribute(key)
29
30
def __contains__(self, key):
31
"""The same as ``key in self.get_attributes()``"""
32
return key in self.get_attributes()
33
34
def __eq__(self, obj):
35
"""Check the equality of two `PyObject`\s
36
37
Currently it is assumed that instances (the direct instances
38
of `PyObject`, not the instances of its subclasses) are equal
39
if their types are equal. For every other object like
40
defineds or builtins rope assumes objects are reference
41
objects and their identities should match.
42
43
"""
44
if self.__class__ != obj.__class__:
45
return False
46
if type(self) == PyObject:
47
if self is not self.type:
48
return self.type == obj.type
49
else:
50
return self.type is obj.type
51
return self is obj
52
53
def __ne__(self, obj):
54
return not self.__eq__(obj)
55
56
def __hash__(self):
57
"""See docs for `__eq__()` method"""
58
if type(self) == PyObject and self != self.type:
59
return hash(self.type) + 1
60
else:
61
return super(PyObject, self).__hash__()
62
63
def __iter__(self):
64
"""The same as ``iter(self.get_attributes())``"""
65
return iter(self.get_attributes())
66
67
_types = None
68
_unknown = None
69
70
@staticmethod
71
def _get_base_type(name):
72
if PyObject._types is None:
73
PyObject._types = {}
74
base_type = PyObject(None)
75
PyObject._types['Type'] = base_type
76
PyObject._types['Module'] = PyObject(base_type)
77
PyObject._types['Function'] = PyObject(base_type)
78
PyObject._types['Unknown'] = PyObject(base_type)
79
return PyObject._types[name]
80
81
82
def get_base_type(name):
83
"""Return the base type with name `name`.
84
85
The base types are 'Type', 'Function', 'Module' and 'Unknown'. It
86
was used to check the type of a `PyObject` but currently its use
87
is discouraged. Use classes defined in this module instead.
88
For example instead of
89
``pyobject.get_type() == get_base_type('Function')`` use
90
``isinstance(pyobject, AbstractFunction)``.
91
92
You can use `AbstractClass` for classes, `AbstractFunction` for
93
functions, and `AbstractModule` for modules. You can also use
94
`PyFunction` and `PyClass` for testing if an object is
95
defined somewhere and rope can access its source. These classes
96
provide more methods.
97
98
"""
99
return PyObject._get_base_type(name)
100
101
102
def get_unknown():
103
"""Return a pyobject whose type is unknown
104
105
Note that two unknown objects are equal. So for example you can
106
write::
107
108
if pyname.get_object() == get_unknown():
109
print 'cannot determine what this pyname holds'
110
111
Rope could have used `None` for indicating unknown objects but
112
we had to check that in many places. So actually this method
113
returns a null object.
114
115
"""
116
if PyObject._unknown is None:
117
PyObject._unknown = PyObject(get_base_type('Unknown'))
118
return PyObject._unknown
119
120
121
class AbstractClass(PyObject):
122
123
def __init__(self):
124
super(AbstractClass, self).__init__(get_base_type('Type'))
125
126
def get_name(self):
127
pass
128
129
def get_doc(self):
130
pass
131
132
def get_superclasses(self):
133
return []
134
135
136
class AbstractFunction(PyObject):
137
138
def __init__(self):
139
super(AbstractFunction, self).__init__(get_base_type('Function'))
140
141
def get_name(self):
142
pass
143
144
def get_doc(self):
145
pass
146
147
def get_param_names(self, special_args=True):
148
return []
149
150
def get_returned_object(self, args):
151
return get_unknown()
152
153
154
class AbstractModule(PyObject):
155
156
def __init__(self, doc=None):
157
super(AbstractModule, self).__init__(get_base_type('Module'))
158
159
def get_doc(self):
160
pass
161
162
def get_resource(self):
163
pass
164
165
166
class PyDefinedObject(object):
167
"""Python defined names that rope can access their sources"""
168
169
def __init__(self, pycore, ast_node, parent):
170
self.pycore = pycore
171
self.ast_node = ast_node
172
self.scope = None
173
self.parent = parent
174
self.structural_attributes = None
175
self.concluded_attributes = self.get_module()._get_concluded_data()
176
self.attributes = self.get_module()._get_concluded_data()
177
self.defineds = None
178
179
visitor_class = None
180
181
@utils.prevent_recursion(lambda: {})
182
def _get_structural_attributes(self):
183
if self.structural_attributes is None:
184
self.structural_attributes = self._create_structural_attributes()
185
return self.structural_attributes
186
187
@utils.prevent_recursion(lambda: {})
188
def _get_concluded_attributes(self):
189
if self.concluded_attributes.get() is None:
190
self._get_structural_attributes()
191
self.concluded_attributes.set(self._create_concluded_attributes())
192
return self.concluded_attributes.get()
193
194
def get_attributes(self):
195
if self.attributes.get() is None:
196
result = dict(self._get_concluded_attributes())
197
result.update(self._get_structural_attributes())
198
self.attributes.set(result)
199
return self.attributes.get()
200
201
def get_attribute(self, name):
202
if name in self._get_structural_attributes():
203
return self._get_structural_attributes()[name]
204
if name in self._get_concluded_attributes():
205
return self._get_concluded_attributes()[name]
206
raise exceptions.AttributeNotFoundError('Attribute %s not found' %
207
name)
208
209
def get_scope(self):
210
if self.scope is None:
211
self.scope = self._create_scope()
212
return self.scope
213
214
def get_module(self):
215
current_object = self
216
while current_object.parent is not None:
217
current_object = current_object.parent
218
return current_object
219
220
def get_doc(self):
221
if len(self.get_ast().body) > 0:
222
expr = self.get_ast().body[0]
223
if isinstance(expr, ast.Expr) and \
224
isinstance(expr.value, ast.Str):
225
docstring = expr.value.s
226
coding = self.get_module().coding
227
return _decode_data(docstring, coding)
228
229
def _get_defined_objects(self):
230
if self.defineds is None:
231
self._get_structural_attributes()
232
return self.defineds
233
234
def _create_structural_attributes(self):
235
if self.visitor_class is None:
236
return {}
237
new_visitor = self.visitor_class(self.pycore, self)
238
for child in ast.get_child_nodes(self.ast_node):
239
ast.walk(child, new_visitor)
240
self.defineds = new_visitor.defineds
241
return new_visitor.names
242
243
def _create_concluded_attributes(self):
244
return {}
245
246
def get_ast(self):
247
return self.ast_node
248
249
def _create_scope(self):
250
pass
251
252
253
class PyFunction(PyDefinedObject, AbstractFunction):
254
"""Only a placeholder"""
255
256
257
class PyClass(PyDefinedObject, AbstractClass):
258
"""Only a placeholder"""
259
260
261
class _ConcludedData(object):
262
263
def __init__(self):
264
self.data_ = None
265
266
def set(self, data):
267
self.data_ = data
268
269
def get(self):
270
return self.data_
271
272
data = property(get, set)
273
274
def _invalidate(self):
275
self.data = None
276
277
def __str__(self):
278
return '<' + str(self.data) + '>'
279
280
281
class _PyModule(PyDefinedObject, AbstractModule):
282
283
def __init__(self, pycore, ast_node, resource):
284
self.resource = resource
285
self.concluded_data = []
286
AbstractModule.__init__(self)
287
PyDefinedObject.__init__(self, pycore, ast_node, None)
288
289
def _get_concluded_data(self):
290
new_data = _ConcludedData()
291
self.concluded_data.append(new_data)
292
return new_data
293
294
def _forget_concluded_data(self):
295
for data in self.concluded_data:
296
data._invalidate()
297
298
def get_resource(self):
299
return self.resource
300
301
302
class PyModule(_PyModule):
303
"""Only a placeholder"""
304
305
306
class PyPackage(_PyModule):
307
"""Only a placeholder"""
308
309
310
class IsBeingInferredError(exceptions.RopeError):
311
pass
312
313