pyflyby 1.10.4__cp311-cp311-macosx_11_0_arm64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pyflyby/__init__.py +61 -0
- pyflyby/__main__.py +9 -0
- pyflyby/_autoimp.py +2228 -0
- pyflyby/_cmdline.py +591 -0
- pyflyby/_comms.py +221 -0
- pyflyby/_dbg.py +1383 -0
- pyflyby/_dynimp.py +154 -0
- pyflyby/_fast_iter_modules.cpython-311-darwin.so +0 -0
- pyflyby/_file.py +771 -0
- pyflyby/_flags.py +230 -0
- pyflyby/_format.py +186 -0
- pyflyby/_idents.py +227 -0
- pyflyby/_import_sorting.py +165 -0
- pyflyby/_importclns.py +658 -0
- pyflyby/_importdb.py +535 -0
- pyflyby/_imports2s.py +643 -0
- pyflyby/_importstmt.py +723 -0
- pyflyby/_interactive.py +2113 -0
- pyflyby/_livepatch.py +793 -0
- pyflyby/_log.py +107 -0
- pyflyby/_modules.py +646 -0
- pyflyby/_parse.py +1396 -0
- pyflyby/_py.py +2165 -0
- pyflyby/_saveframe.py +1145 -0
- pyflyby/_saveframe_reader.py +471 -0
- pyflyby/_util.py +458 -0
- pyflyby/_version.py +8 -0
- pyflyby/autoimport.py +20 -0
- pyflyby/etc/pyflyby/canonical.py +10 -0
- pyflyby/etc/pyflyby/common.py +27 -0
- pyflyby/etc/pyflyby/forget.py +10 -0
- pyflyby/etc/pyflyby/mandatory.py +10 -0
- pyflyby/etc/pyflyby/numpy.py +156 -0
- pyflyby/etc/pyflyby/std.py +335 -0
- pyflyby/importdb.py +19 -0
- pyflyby/libexec/pyflyby/colordiff +34 -0
- pyflyby/libexec/pyflyby/diff-colorize +148 -0
- pyflyby/share/emacs/site-lisp/pyflyby.el +112 -0
- pyflyby-1.10.4.data/scripts/collect-exports +76 -0
- pyflyby-1.10.4.data/scripts/collect-imports +58 -0
- pyflyby-1.10.4.data/scripts/find-import +38 -0
- pyflyby-1.10.4.data/scripts/prune-broken-imports +34 -0
- pyflyby-1.10.4.data/scripts/pyflyby-diff +34 -0
- pyflyby-1.10.4.data/scripts/reformat-imports +27 -0
- pyflyby-1.10.4.data/scripts/replace-star-imports +37 -0
- pyflyby-1.10.4.data/scripts/saveframe +299 -0
- pyflyby-1.10.4.data/scripts/tidy-imports +170 -0
- pyflyby-1.10.4.data/scripts/transform-imports +47 -0
- pyflyby-1.10.4.dist-info/METADATA +605 -0
- pyflyby-1.10.4.dist-info/RECORD +53 -0
- pyflyby-1.10.4.dist-info/WHEEL +6 -0
- pyflyby-1.10.4.dist-info/entry_points.txt +4 -0
- pyflyby-1.10.4.dist-info/licenses/LICENSE.txt +19 -0
|
@@ -0,0 +1,471 @@
|
|
|
1
|
+
"""
|
|
2
|
+
pyflyby/_saveframe_reader.py
|
|
3
|
+
|
|
4
|
+
This module provides the ``SaveframeReader`` class, which is used to read data
|
|
5
|
+
saved by the ``saveframe`` utility.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import logging
|
|
11
|
+
import pickle
|
|
12
|
+
|
|
13
|
+
from pyflyby._saveframe import ExceptionInfo, FrameMetadata
|
|
14
|
+
|
|
15
|
+
class SaveframeReader:
|
|
16
|
+
"""
|
|
17
|
+
A class for reading data saved by the ``saveframe`` utility.
|
|
18
|
+
|
|
19
|
+
The ``saveframe`` utility saves data as a pickled Python dictionary.
|
|
20
|
+
Reading this raw data and extracting values of specific variables or metadata
|
|
21
|
+
fields can be complex.
|
|
22
|
+
|
|
23
|
+
The ``SaveframeReader`` class provides an easy and efficient way to read this
|
|
24
|
+
raw data and extract specific items. This class has a user-friendly ``repr``
|
|
25
|
+
for visualizing the data and provides various helpful methods to extract
|
|
26
|
+
different items.
|
|
27
|
+
|
|
28
|
+
**Usage Example:**
|
|
29
|
+
|
|
30
|
+
**Creating an instance**
|
|
31
|
+
|
|
32
|
+
First, create an instance of this class by passing the path of the file that
|
|
33
|
+
contains the ``saveframe`` data.
|
|
34
|
+
|
|
35
|
+
::
|
|
36
|
+
|
|
37
|
+
>> from pyflyby import SaveframeReader
|
|
38
|
+
>> reader = SaveframeReader('/path/to/file')
|
|
39
|
+
|
|
40
|
+
**Extracting all available metadata fields**
|
|
41
|
+
|
|
42
|
+
To extract all available metadata fields, use the ``SaveframeReader.metadata``
|
|
43
|
+
property. Example:
|
|
44
|
+
|
|
45
|
+
::
|
|
46
|
+
|
|
47
|
+
>> reader.metadata
|
|
48
|
+
['frame_index', 'filename', 'lineno', 'function_name', 'function_qualname',
|
|
49
|
+
'function_object', 'module_name', 'code', 'frame_identifier',
|
|
50
|
+
'exception_string', 'exception_full_string', 'exception_class_name',
|
|
51
|
+
'exception_class_qualname', 'exception_object', 'traceback']
|
|
52
|
+
|
|
53
|
+
**Extracting all stored local variables**
|
|
54
|
+
|
|
55
|
+
To extract the names of all local variables stored in the frames, use the
|
|
56
|
+
``SaveframeReader.variables`` property. Example:
|
|
57
|
+
|
|
58
|
+
::
|
|
59
|
+
|
|
60
|
+
>> reader.variables
|
|
61
|
+
{
|
|
62
|
+
1: ['var1', 'var2', ...],
|
|
63
|
+
2: ['var5', 'var8', 'var9', ...],
|
|
64
|
+
...
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
**Extracting the value of a specific metadata field**
|
|
68
|
+
|
|
69
|
+
To extract the value of a specific metadata field, use the
|
|
70
|
+
`SaveframeReader.get_metadata` method. Example:
|
|
71
|
+
|
|
72
|
+
::
|
|
73
|
+
|
|
74
|
+
>> reader.get_metadata("filename")
|
|
75
|
+
{1: '/dir1/mod1.py', 2: '/dir2/mod2.py', ...}
|
|
76
|
+
|
|
77
|
+
>> reader.get_metadata("filename", frame_idx=2)
|
|
78
|
+
'/dir2/mod2.py'
|
|
79
|
+
|
|
80
|
+
>> reader.get_metadata("exception_string")
|
|
81
|
+
"Error is raised"
|
|
82
|
+
|
|
83
|
+
**Extracting the value of specific local variables**
|
|
84
|
+
|
|
85
|
+
To extract the value of specific local variable(s), use the
|
|
86
|
+
`SaveframeReader.get_variables` method. Example:
|
|
87
|
+
|
|
88
|
+
::
|
|
89
|
+
|
|
90
|
+
>> reader.get_variables('var1')
|
|
91
|
+
{2: var1_value2, 4: var1_value4}
|
|
92
|
+
|
|
93
|
+
>> reader.get_variables('var1', frame_idx=4)
|
|
94
|
+
var1_value4
|
|
95
|
+
|
|
96
|
+
>> reader.get_variables('var2')
|
|
97
|
+
var2_value3
|
|
98
|
+
|
|
99
|
+
>> reader.get_variables(['var1', 'var3'])
|
|
100
|
+
{2: {'var1': var1_value2, 'var3': var3_value2},
|
|
101
|
+
4: {'var1': var1_value4}, 5: {'var3': var3_value5}}
|
|
102
|
+
|
|
103
|
+
>> reader.get_variables(['var1', 'var3'], frame_idx=2)
|
|
104
|
+
{'var1': var1_value2, 'var3': var3_value2}
|
|
105
|
+
|
|
106
|
+
Raw data can be extracted using ``SaveframeReader.data`` property.
|
|
107
|
+
"""
|
|
108
|
+
|
|
109
|
+
def __init__(self, filename):
|
|
110
|
+
"""
|
|
111
|
+
Initializes the ``SaveframeReader`` class.
|
|
112
|
+
|
|
113
|
+
:param filename:
|
|
114
|
+
The file path where the ``saveframe`` data is stored.
|
|
115
|
+
"""
|
|
116
|
+
self._filename = filename
|
|
117
|
+
with open(filename, 'rb') as f:
|
|
118
|
+
self._data = pickle.load(f)
|
|
119
|
+
if not isinstance(self._data, dict):
|
|
120
|
+
raise ValueError(
|
|
121
|
+
f"The data in the file '{filename}' is of type "
|
|
122
|
+
f"'{type(self._data).__name__}', which is not valid saveframe "
|
|
123
|
+
"data.")
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
@property
|
|
127
|
+
def filename(self):
|
|
128
|
+
"""
|
|
129
|
+
The file path where the ``saveframe`` data is stored.
|
|
130
|
+
"""
|
|
131
|
+
return self._filename
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
@property
|
|
135
|
+
def data(self):
|
|
136
|
+
"""
|
|
137
|
+
Returns the raw ``saveframe`` data as a Python dictionary.
|
|
138
|
+
"""
|
|
139
|
+
return self._data
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
@property
|
|
143
|
+
def metadata(self):
|
|
144
|
+
"""
|
|
145
|
+
Returns a list of all metadata items present in the data.
|
|
146
|
+
|
|
147
|
+
This includes both frame metadata and exception metadata. The returned
|
|
148
|
+
list contains the names of all metadata fields. For example:
|
|
149
|
+
['frame_index', 'filename', ..., 'exception_object', 'traceback'].
|
|
150
|
+
|
|
151
|
+
To obtain the value of a specific metadata field, use the
|
|
152
|
+
`SaveframeReader.get_metadata` method.
|
|
153
|
+
"""
|
|
154
|
+
metadata = []
|
|
155
|
+
metadata.extend([field for field in FrameMetadata.__dataclass_fields__])
|
|
156
|
+
metadata.extend([field for field in ExceptionInfo.__dataclass_fields__])
|
|
157
|
+
return metadata
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
@property
|
|
161
|
+
def variables(self):
|
|
162
|
+
"""
|
|
163
|
+
Returns the local variables present in each frame.
|
|
164
|
+
|
|
165
|
+
The returned value is a dictionary where the keys are frame indices and
|
|
166
|
+
the values are lists of local variable names in those frames. For example:
|
|
167
|
+
|
|
168
|
+
::
|
|
169
|
+
|
|
170
|
+
{
|
|
171
|
+
1: ['variable1', 'variable2', ...],
|
|
172
|
+
2: ['variable5', 'variable6', 'variable8'],
|
|
173
|
+
...
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
To obtain the value of specific variable(s), use the
|
|
177
|
+
`SaveframeReader.get_variables` method.
|
|
178
|
+
"""
|
|
179
|
+
frame_idx_to_variables_map = {}
|
|
180
|
+
for key_item in self._data:
|
|
181
|
+
if not isinstance(key_item, int):
|
|
182
|
+
continue
|
|
183
|
+
frame_idx_to_variables_map[key_item] = list(
|
|
184
|
+
self._data[key_item]['variables'].keys())
|
|
185
|
+
return frame_idx_to_variables_map
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
def get_metadata(self, metadata, *, frame_idx=None):
|
|
189
|
+
"""
|
|
190
|
+
Retrieve the value of a specific metadata field.
|
|
191
|
+
|
|
192
|
+
**Example usage:**
|
|
193
|
+
|
|
194
|
+
::
|
|
195
|
+
|
|
196
|
+
>> reader = SaveframeReader("/path/to/file")
|
|
197
|
+
|
|
198
|
+
>> reader.get_metadata("filename")
|
|
199
|
+
{1: '/dir1/mod1.py', 2: '/dir2/mod2.py', ...}
|
|
200
|
+
|
|
201
|
+
>> reader.get_metadata("filename", frame_idx=2)
|
|
202
|
+
'/dir2/mod2.py'
|
|
203
|
+
|
|
204
|
+
>> reader.get_metadata("exception_string")
|
|
205
|
+
"Error is raised"
|
|
206
|
+
|
|
207
|
+
:param metadata:
|
|
208
|
+
The metadata field for which to get the value.
|
|
209
|
+
:param frame_idx:
|
|
210
|
+
The index of the frame from which to get the metadata value. Default is
|
|
211
|
+
None, which means metadata from all frames is returned. This parameter
|
|
212
|
+
is only supported for frame metadata, not exception metadata.
|
|
213
|
+
:return:
|
|
214
|
+
- If ``frame_idx`` is None (default):
|
|
215
|
+
- If ``metadata`` is a frame metadata field, a dictionary is returned
|
|
216
|
+
with the frame index as the key and the metadata value as the value.
|
|
217
|
+
- If ``metadata`` is an exception metadata field, the value of the
|
|
218
|
+
metadata is returned.
|
|
219
|
+
- If ``frame_idx`` is specified:
|
|
220
|
+
- If ``metadata`` is a frame metadata field, the metadata value for
|
|
221
|
+
the specified frame is returned.
|
|
222
|
+
- If ``metadata`` is an exception metadata field, an error is raised.
|
|
223
|
+
"""
|
|
224
|
+
# Sanity checks.
|
|
225
|
+
all_metadata_entries = self.metadata
|
|
226
|
+
if metadata not in all_metadata_entries:
|
|
227
|
+
raise ValueError(
|
|
228
|
+
f"Invalid metadata requested: {metadata!a}. Allowed metadata "
|
|
229
|
+
f"entries are: {all_metadata_entries}.")
|
|
230
|
+
exception_metadata = ([field for field in ExceptionInfo.__dataclass_fields__])
|
|
231
|
+
# Handle exception metadata.
|
|
232
|
+
if metadata in exception_metadata:
|
|
233
|
+
if frame_idx:
|
|
234
|
+
raise ValueError(
|
|
235
|
+
"'frame_idx' is not supported for querying exception "
|
|
236
|
+
f"metadata: {metadata!a}.")
|
|
237
|
+
return self._data[metadata]
|
|
238
|
+
# frame_idx is not passed.
|
|
239
|
+
if frame_idx is None:
|
|
240
|
+
frame_idx_to_metadata_value_map = {}
|
|
241
|
+
for key_item in self._data:
|
|
242
|
+
if key_item in exception_metadata:
|
|
243
|
+
continue
|
|
244
|
+
metadata_value = self._data[key_item][metadata]
|
|
245
|
+
# Unpickle the 'function_object' metadata value.
|
|
246
|
+
if metadata == "function_object":
|
|
247
|
+
try:
|
|
248
|
+
if not isinstance(metadata_value, str):
|
|
249
|
+
metadata_value = pickle.loads(metadata_value)
|
|
250
|
+
except Exception as err:
|
|
251
|
+
logging.warning("Can't unpickle the 'function_object' "
|
|
252
|
+
"value for frame: %a. Error: %s",
|
|
253
|
+
key_item, err)
|
|
254
|
+
metadata_value = (
|
|
255
|
+
f"Can't unpickle the 'function_object'. Error: {err}")
|
|
256
|
+
frame_idx_to_metadata_value_map[key_item] = metadata_value
|
|
257
|
+
return frame_idx_to_metadata_value_map
|
|
258
|
+
|
|
259
|
+
# frame_idx is passed.
|
|
260
|
+
if not isinstance(frame_idx, int):
|
|
261
|
+
raise TypeError(
|
|
262
|
+
"'frame_idx' must be of type 'int', not "
|
|
263
|
+
f"'{type(frame_idx).__name__}'.")
|
|
264
|
+
try:
|
|
265
|
+
metadata_value = self._data[frame_idx][metadata]
|
|
266
|
+
if metadata == "function_object":
|
|
267
|
+
try:
|
|
268
|
+
if not isinstance(metadata_value, str):
|
|
269
|
+
metadata_value = pickle.loads(metadata_value)
|
|
270
|
+
except Exception as err:
|
|
271
|
+
logging.warning("Can't unpickle the 'function_object' "
|
|
272
|
+
"value for frame: %a. Error: %s",
|
|
273
|
+
frame_idx, err)
|
|
274
|
+
return metadata_value
|
|
275
|
+
except KeyError:
|
|
276
|
+
allowed_frame_idx = list(
|
|
277
|
+
set(self._data.keys()) - set(exception_metadata))
|
|
278
|
+
raise ValueError(
|
|
279
|
+
f"Invalid value for 'frame_idx': '{frame_idx}'. Allowed values "
|
|
280
|
+
f"are: {allowed_frame_idx}.")
|
|
281
|
+
|
|
282
|
+
|
|
283
|
+
def get_variables(self, variables, *, frame_idx=None):
|
|
284
|
+
"""
|
|
285
|
+
Retrieve the value of local variable(s) from specific frames.
|
|
286
|
+
|
|
287
|
+
**Example usage:**
|
|
288
|
+
|
|
289
|
+
::
|
|
290
|
+
|
|
291
|
+
>> reader = SaveframeReader('/path/to/file')
|
|
292
|
+
|
|
293
|
+
>> reader.get_variables('var1')
|
|
294
|
+
{2: var1_value2, 4: var1_value4}
|
|
295
|
+
|
|
296
|
+
>> reader.get_variables('var1', frame_idx=4)
|
|
297
|
+
var1_value4
|
|
298
|
+
|
|
299
|
+
>> reader.get_variables(('var1',), frame_idx=4)
|
|
300
|
+
{'var1': var1_value4}
|
|
301
|
+
|
|
302
|
+
>> reader.get_variables('var2')
|
|
303
|
+
var2_value3 # 'var2' is only present in frame 3
|
|
304
|
+
|
|
305
|
+
>> reader.get_variables(['var1', 'var3'])
|
|
306
|
+
{2: {'var1': var1_value2, 'var3': var3_value2},
|
|
307
|
+
4: {'var1': var1_value4}, 5: {'var3': var3_value5}}
|
|
308
|
+
|
|
309
|
+
>> reader.get_variables(['var1', 'var3'], frame_idx=2)
|
|
310
|
+
{'var1': var1_value2, 'var3': var3_value2}
|
|
311
|
+
|
|
312
|
+
:param variables:
|
|
313
|
+
One or more variable names for which to retrieve the values. You can
|
|
314
|
+
pass a single variable name as a string or a list / tuple of variable
|
|
315
|
+
names.
|
|
316
|
+
|
|
317
|
+
:param frame_idx:
|
|
318
|
+
The index of the frame from which to retrieve the value(s) of the
|
|
319
|
+
variable(s). Default is None, which means values from all frames are
|
|
320
|
+
returned.
|
|
321
|
+
:return:
|
|
322
|
+
- If ``frame_idx`` is None (default):
|
|
323
|
+
- For a single variable:
|
|
324
|
+
- A dictionary with frame indices as keys and variable values
|
|
325
|
+
as values.
|
|
326
|
+
- If the variable is present in only one frame, the value is
|
|
327
|
+
returned directly.
|
|
328
|
+
- For a list / tuple of variables:
|
|
329
|
+
- A dictionary with frame indices as keys and dictionaries as
|
|
330
|
+
values, where each inner dictionary contains the queried
|
|
331
|
+
variables and their values for that frame.
|
|
332
|
+
- If the queried variables are present in only one frame, a
|
|
333
|
+
dictionary of those variables and their values is returned.
|
|
334
|
+
- If ``frame_idx`` is specified:
|
|
335
|
+
- For a single variable:
|
|
336
|
+
- The value of the variable in the specified frame.
|
|
337
|
+
- If the variable is not present in that frame, an error is raised.
|
|
338
|
+
- For a list / tuple of variables:
|
|
339
|
+
- A dictionary with the variable names as keys and their values
|
|
340
|
+
as values, for the specified frame.
|
|
341
|
+
- If none of the queried variables are present in that frame,
|
|
342
|
+
an error is raised.
|
|
343
|
+
"""
|
|
344
|
+
# Boolean to denote if variables are passed as a list or tuple.
|
|
345
|
+
variables_passed_as_list_or_tuple = False
|
|
346
|
+
# Sanity checks.
|
|
347
|
+
if isinstance(variables, (list, tuple)):
|
|
348
|
+
variables_passed_as_list_or_tuple = True
|
|
349
|
+
for variable in variables:
|
|
350
|
+
if not isinstance(variable, str):
|
|
351
|
+
raise TypeError(
|
|
352
|
+
f"Invalid type for variable name: {type(variable).__name__}. "
|
|
353
|
+
"Expected string type instead.")
|
|
354
|
+
elif isinstance(variables, str):
|
|
355
|
+
variables = (variables,)
|
|
356
|
+
else:
|
|
357
|
+
raise TypeError(
|
|
358
|
+
f"'variables' must either be a string or a list/tuple. "
|
|
359
|
+
f"Got '{type(variables).__name__}'.")
|
|
360
|
+
if len(variables) == 0:
|
|
361
|
+
raise ValueError("No 'variables' passed.")
|
|
362
|
+
|
|
363
|
+
def _get_variable_value_on_unpickle_error(err):
|
|
364
|
+
"""
|
|
365
|
+
Get variable's value when it fails to unpickle due to error ``err``.
|
|
366
|
+
"""
|
|
367
|
+
return f"Can't un-pickle the variable. Error: {err}"
|
|
368
|
+
|
|
369
|
+
# frame_idx is not passed.
|
|
370
|
+
if frame_idx is None:
|
|
371
|
+
frame_idx_to_variables_map = {}
|
|
372
|
+
for key_item in self._data:
|
|
373
|
+
if not isinstance(key_item, int):
|
|
374
|
+
continue
|
|
375
|
+
variables_map = self._data[key_item]['variables']
|
|
376
|
+
for variable in variables:
|
|
377
|
+
try:
|
|
378
|
+
variable_value = variables_map[variable]
|
|
379
|
+
except KeyError:
|
|
380
|
+
continue
|
|
381
|
+
try:
|
|
382
|
+
variable_value = pickle.loads(variable_value)
|
|
383
|
+
except Exception as err:
|
|
384
|
+
logging.warning(
|
|
385
|
+
"Can't un-pickle the value of variable %a for frame "
|
|
386
|
+
"%a. Error: %s", variable, key_item, err)
|
|
387
|
+
variable_value = _get_variable_value_on_unpickle_error(err)
|
|
388
|
+
if len(variables) == 1 and not variables_passed_as_list_or_tuple:
|
|
389
|
+
# Single variable is queried.
|
|
390
|
+
frame_idx_to_variables_map[key_item] = variable_value
|
|
391
|
+
else:
|
|
392
|
+
# Multiple variables are queried. The result would be
|
|
393
|
+
# a dict where keys would be the frame indices and values
|
|
394
|
+
# would the dicts containing the queried variables and
|
|
395
|
+
# their values for that frame.
|
|
396
|
+
if not key_item in frame_idx_to_variables_map:
|
|
397
|
+
frame_idx_to_variables_map[key_item] = {}
|
|
398
|
+
frame_idx_to_variables_map[key_item][variable] = variable_value
|
|
399
|
+
if not frame_idx_to_variables_map:
|
|
400
|
+
raise ValueError(f"Local variable(s) {variables} not found in "
|
|
401
|
+
"any of the saved frames.")
|
|
402
|
+
# If there is only 1 frame in the result, return the value directly.
|
|
403
|
+
if len(frame_idx_to_variables_map) == 1:
|
|
404
|
+
return frame_idx_to_variables_map.popitem()[1]
|
|
405
|
+
return frame_idx_to_variables_map
|
|
406
|
+
|
|
407
|
+
# frame_idx is passed.
|
|
408
|
+
if not isinstance(frame_idx, int):
|
|
409
|
+
raise TypeError(
|
|
410
|
+
"'frame_idx' must be of type 'int', not "
|
|
411
|
+
f"'{type(frame_idx).__name__}'.")
|
|
412
|
+
try:
|
|
413
|
+
variables_map = self._data[frame_idx]['variables']
|
|
414
|
+
except KeyError:
|
|
415
|
+
allowed_frame_idx = list(
|
|
416
|
+
set(self._data.keys()) - set(self.metadata))
|
|
417
|
+
raise ValueError(
|
|
418
|
+
f"Invalid value for 'frame_idx': '{frame_idx}'. Allowed values "
|
|
419
|
+
f"are: {allowed_frame_idx}.")
|
|
420
|
+
variable_key_to_value_map = {}
|
|
421
|
+
for variable in variables:
|
|
422
|
+
try:
|
|
423
|
+
variable_value = variables_map[variable]
|
|
424
|
+
except KeyError:
|
|
425
|
+
continue
|
|
426
|
+
try:
|
|
427
|
+
variable_value = pickle.loads(variable_value)
|
|
428
|
+
except Exception as err:
|
|
429
|
+
logging.warning(
|
|
430
|
+
"Can't un-pickle the value of variable %a for frame "
|
|
431
|
+
"%a. Error: %s", variable, frame_idx, err)
|
|
432
|
+
if len(variables) > 1:
|
|
433
|
+
variable_value = _get_variable_value_on_unpickle_error(err)
|
|
434
|
+
if len(variables) == 1 and not variables_passed_as_list_or_tuple:
|
|
435
|
+
# Single variable is queried. Directly return the value.
|
|
436
|
+
return variable_value
|
|
437
|
+
variable_key_to_value_map[variable] = variable_value
|
|
438
|
+
if not variable_key_to_value_map:
|
|
439
|
+
raise ValueError(f"Local variable(s) {variables} not found in "
|
|
440
|
+
f"frame {frame_idx}")
|
|
441
|
+
return variable_key_to_value_map
|
|
442
|
+
|
|
443
|
+
|
|
444
|
+
def __str__(self):
|
|
445
|
+
frames_info = []
|
|
446
|
+
for frame_idx, frame_data in self._data.items():
|
|
447
|
+
if isinstance(frame_idx, int):
|
|
448
|
+
frame_info = (
|
|
449
|
+
f"Frame {frame_idx}:\n"
|
|
450
|
+
f" Filename: '{frame_data.get('filename')}'\n"
|
|
451
|
+
f" Line Number: {frame_data.get('lineno')}\n"
|
|
452
|
+
f" Function: {frame_data.get('function_qualname')}\n"
|
|
453
|
+
f" Module: {frame_data.get('module_name')}\n"
|
|
454
|
+
f" Frame ID: '{frame_data.get('frame_identifier')}'\n"
|
|
455
|
+
f" Code: {frame_data.get('code')}\n"
|
|
456
|
+
f" Variables: {list(frame_data.get('variables', {}).keys())}\n"
|
|
457
|
+
)
|
|
458
|
+
frames_info.append(frame_info)
|
|
459
|
+
|
|
460
|
+
exception_info = (
|
|
461
|
+
f"Exception:\n"
|
|
462
|
+
f" Full String: {self._data.get('exception_full_string')}\n"
|
|
463
|
+
f" String: {self._data.get('exception_string')}\n"
|
|
464
|
+
f" Class Name: {self._data.get('exception_class_name')}\n"
|
|
465
|
+
f" Qualified Name: {self._data.get('exception_class_qualname')}\n"
|
|
466
|
+
)
|
|
467
|
+
|
|
468
|
+
return "Frames:\n" + "\n".join(frames_info) + "\n" + exception_info
|
|
469
|
+
|
|
470
|
+
def __repr__(self):
|
|
471
|
+
return f"{self.__class__.__name__}(\nfilename: {self._filename!a} \n\n{str(self)})"
|