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/objectinfo.py
1421 views
1
import warnings
2
3
from rope.base import exceptions, resourceobserver
4
from rope.base.oi import objectdb, memorydb, transform
5
6
7
class ObjectInfoManager(object):
8
"""Stores object information
9
10
It uses an instance of `objectdb.ObjectDB` for storing
11
information.
12
13
"""
14
15
def __init__(self, project):
16
self.project = project
17
self.to_textual = transform.PyObjectToTextual(project)
18
self.to_pyobject = transform.TextualToPyObject(project)
19
self.doi_to_pyobject = transform.DOITextualToPyObject(project)
20
self._init_objectdb()
21
if project.prefs.get('validate_objectdb', False):
22
self._init_validation()
23
24
def _init_objectdb(self):
25
dbtype = self.project.get_prefs().get('objectdb_type', None)
26
persist = None
27
if dbtype is not None:
28
warnings.warn(
29
'"objectdb_type" project config is deprecated;\n'
30
'Use "save_objectdb" instead in your project '
31
'config file.\n(".ropeproject/config.py" by default)\n',
32
DeprecationWarning)
33
if dbtype != 'memory' and self.project.ropefolder is not None:
34
persist = True
35
self.validation = TextualValidation(self.to_pyobject)
36
db = memorydb.MemoryDB(self.project, persist=persist)
37
self.objectdb = objectdb.ObjectDB(db, self.validation)
38
39
def _init_validation(self):
40
self.objectdb.validate_files()
41
observer = resourceobserver.ResourceObserver(
42
changed=self._resource_changed, moved=self._resource_moved,
43
removed=self._resource_moved)
44
files = []
45
for path in self.objectdb.get_files():
46
resource = self.to_pyobject.path_to_resource(path)
47
if resource is not None and resource.project == self.project:
48
files.append(resource)
49
self.observer = resourceobserver.FilteredResourceObserver(observer,
50
files)
51
self.objectdb.add_file_list_observer(_FileListObserver(self))
52
self.project.add_observer(self.observer)
53
54
def _resource_changed(self, resource):
55
try:
56
self.objectdb.validate_file(
57
self.to_textual.resource_to_path(resource))
58
except exceptions.ModuleSyntaxError:
59
pass
60
61
def _resource_moved(self, resource, new_resource=None):
62
self.observer.remove_resource(resource)
63
if new_resource is not None:
64
old = self.to_textual.resource_to_path(resource)
65
new = self.to_textual.resource_to_path(new_resource)
66
self.objectdb.file_moved(old, new)
67
self.observer.add_resource(new_resource)
68
69
def get_returned(self, pyobject, args):
70
result = self.get_exact_returned(pyobject, args)
71
if result is not None:
72
return result
73
path, key = self._get_scope(pyobject)
74
if path is None:
75
return None
76
for call_info in self.objectdb.get_callinfos(path, key):
77
returned = call_info.get_returned()
78
if returned and returned[0] not in ('unknown', 'none'):
79
result = returned
80
break
81
if result is None:
82
result = returned
83
if result is not None:
84
return self.to_pyobject(result)
85
86
def get_exact_returned(self, pyobject, args):
87
path, key = self._get_scope(pyobject)
88
if path is not None:
89
returned = self.objectdb.get_returned(
90
path, key, self._args_to_textual(pyobject, args))
91
if returned is not None:
92
return self.to_pyobject(returned)
93
94
def _args_to_textual(self, pyfunction, args):
95
parameters = list(pyfunction.get_param_names(special_args=False))
96
arguments = args.get_arguments(parameters)[:len(parameters)]
97
textual_args = tuple([self.to_textual(arg)
98
for arg in arguments])
99
return textual_args
100
101
def get_parameter_objects(self, pyobject):
102
path, key = self._get_scope(pyobject)
103
if path is None:
104
return None
105
arg_count = len(pyobject.get_param_names(special_args=False))
106
unknowns = arg_count
107
parameters = [None] * arg_count
108
for call_info in self.objectdb.get_callinfos(path, key):
109
args = call_info.get_parameters()
110
for index, arg in enumerate(args[:arg_count]):
111
old = parameters[index]
112
if self.validation.is_more_valid(arg, old):
113
parameters[index] = arg
114
if self.validation.is_value_valid(arg):
115
unknowns -= 1
116
if unknowns == 0:
117
break
118
if unknowns < arg_count:
119
return [self.to_pyobject(parameter)
120
for parameter in parameters]
121
122
def get_passed_objects(self, pyfunction, parameter_index):
123
path, key = self._get_scope(pyfunction)
124
if path is None:
125
return []
126
result = []
127
for call_info in self.objectdb.get_callinfos(path, key):
128
args = call_info.get_parameters()
129
if len(args) > parameter_index:
130
parameter = self.to_pyobject(args[parameter_index])
131
if parameter is not None:
132
result.append(parameter)
133
return result
134
135
def doa_data_received(self, data):
136
def doi_to_normal(textual):
137
pyobject = self.doi_to_pyobject(textual)
138
return self.to_textual(pyobject)
139
function = doi_to_normal(data[0])
140
args = tuple([doi_to_normal(textual) for textual in data[1]])
141
returned = doi_to_normal(data[2])
142
if function[0] == 'defined' and len(function) == 3:
143
self._save_data(function, args, returned)
144
145
def function_called(self, pyfunction, params, returned=None):
146
function_text = self.to_textual(pyfunction)
147
params_text = tuple([self.to_textual(param)
148
for param in params])
149
returned_text = ('unknown',)
150
if returned is not None:
151
returned_text = self.to_textual(returned)
152
self._save_data(function_text, params_text, returned_text)
153
154
def save_per_name(self, scope, name, data):
155
path, key = self._get_scope(scope.pyobject)
156
if path is not None:
157
self.objectdb.add_pername(path, key, name, self.to_textual(data))
158
159
def get_per_name(self, scope, name):
160
path, key = self._get_scope(scope.pyobject)
161
if path is not None:
162
result = self.objectdb.get_pername(path, key, name)
163
if result is not None:
164
return self.to_pyobject(result)
165
166
def _save_data(self, function, args, returned=('unknown',)):
167
self.objectdb.add_callinfo(function[1], function[2], args, returned)
168
169
def _get_scope(self, pyobject):
170
resource = pyobject.get_module().get_resource()
171
if resource is None:
172
return None, None
173
textual = self.to_textual(pyobject)
174
if textual[0] == 'defined':
175
path = textual[1]
176
if len(textual) == 3:
177
key = textual[2]
178
else:
179
key = ''
180
return path, key
181
return None, None
182
183
def sync(self):
184
self.objectdb.sync()
185
186
def __str__(self):
187
return str(self.objectdb)
188
189
190
class TextualValidation(object):
191
192
def __init__(self, to_pyobject):
193
self.to_pyobject = to_pyobject
194
195
def is_value_valid(self, value):
196
# ???: Should none and unknown be considered valid?
197
if value is None or value[0] in ('none', 'unknown'):
198
return False
199
return self.to_pyobject(value) is not None
200
201
def is_more_valid(self, new, old):
202
if old is None:
203
return True
204
return new[0] not in ('unknown', 'none')
205
206
def is_file_valid(self, path):
207
return self.to_pyobject.path_to_resource(path) is not None
208
209
def is_scope_valid(self, path, key):
210
if key == '':
211
textual = ('defined', path)
212
else:
213
textual = ('defined', path, key)
214
return self.to_pyobject(textual) is not None
215
216
217
class _FileListObserver(object):
218
219
def __init__(self, object_info):
220
self.object_info = object_info
221
self.observer = self.object_info.observer
222
self.to_pyobject = self.object_info.to_pyobject
223
224
def removed(self, path):
225
resource = self.to_pyobject.path_to_resource(path)
226
if resource is not None:
227
self.observer.remove_resource(resource)
228
229
def added(self, path):
230
resource = self.to_pyobject.path_to_resource(path)
231
if resource is not None:
232
self.observer.add_resource(resource)
233
234