Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[New] SaveframeReader class (PyInf#13916) #384

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

saharan-deshaw
Copy link
Collaborator

@saharan-deshaw saharan-deshaw commented Dec 10, 2024

Background:
In #356, we added a new utility named saveframe in Pyflyby, that can be used to save information for debugging / reproducing an issue.

Issue:
The saveframe utility saves data as a pickled Python dictionary. Reading this raw data and extracting values of specific variables or metadata fields can be complex.

This commit adds a new class named SaveframeReader, for reading data saved by the saveframe utility.

The SaveframeReader class provides an easy and efficient way to read the raw data and extract specific items. This class has a user-friendly repr for visualizing the data and provides various helpful methods to extract different items.

Usage Example:

Creating an instance

First, create an instance of this class by passing the path of the file that contains the saveframe data.

>>> from pyflyby import SaveframeReader
>>> reader = SaveframeReader('/path/to/file')

Extracting all available metadata fields

To extract all available metadata fields, use the SaveframeReader.metadata property. Example:

>>> reader.metadata
['frame_index', 'filename', 'lineno', 'function_name', 'function_qualname',
'function_object', 'module_name', 'code', 'frame_identifier',
'exception_string', 'exception_full_string', 'exception_class_name',
'exception_class_qualname', 'exception_object', 'traceback']

Extracting all stored local variables

To extract the names of all local variables stored in the frames, use the SaveframeReader.variables property. Example:

>>> reader.variables
{
   1: ['var1', 'var2', ...],
   2: ['var5', 'var8', 'var9', ...],
   ...
}

Extracting the value of a specific metadata field

To extract the value of a specific metadata field, use the SaveframeReader.get_metadata method. Example:

>> reader.get_metadata("filename")
{1: '/dir1/mod1.py', 2: '/dir2/mod2.py', ...}

>> reader.get_metadata("filename", frame_idx=2)
'/dir2/mod2.py'

>> reader.get_metadata("exception_string")
"Error is raised"

Extracting the value of specific local variables

To extract the value of specific local variable(s), use the SaveframeReader.get_variables method. Example:

>> reader.get_variables('var1')
{2: var1_value2, 4: var1_value4}

>>  reader.get_variables('var1', frame_idx=4)
var1_value4

>> reader.get_variables('var2')
var2_value3

>> reader.get_variables('var1', 'var3')
{2: {'var1': var1_value2, 'var3': var3_value2},
4: {'var1': var1_value4}, 5: {'var3': var3_value5}}

>> reader.get_variables('var1', 'var3', frame_idx=2)
{'var1': var1_value2, 'var3': var3_value2}

>> reader.get_variables(['var1', 'var3'])
{2: {'var1': var1_value2, 'var3': var3_value2},
4: {'var1': var1_value4}, 5: {'var3': var3_value5}}

>> reader.get_variables(['var1', 'var3'], frame_idx=2)
{'var1': var1_value2, 'var3': var3_value2}

NOTE: Raw data can be extracted using SaveframeReader.data property.

Request: PyInf#13916

**Background:**
In deshaw#356, we added a new utility named `saveframe` in Pyflyby, that can
be used to save information for debugging / reproducing an issue.

**Issue:**
The `saveframe` utility saves data as a pickled Python dictionary.
Reading this raw data and extracting values of specific variables or metadata
fields can be complex.

This commit adds a new class named `SaveframeReader`, for reading data saved by
the `saveframe` utility.

The `SaveframeReader` class provides an easy and efficient way to read the
raw data and extract specific items. This class has a user-friendly `repr`
for visualizing the data and provides various helpful methods to extract
different items.

**Usage Example:**

**Creating an instance**

First, create an instance of this class by passing the path of the file that
contains the `saveframe` data.
```
>>> from pyflyby import SaveframeReader
>>> reader = SaveframeReader('/path/to/file')
```

**Extracting all available metadata fields**

To extract all available metadata fields, use the `SaveframeReader.metadata`
property. Example:
```
>>> reader.metadata
['frame_index', 'filename', 'lineno', 'function_name', 'function_qualname',
'function_object', 'module_name', 'code', 'frame_identifier',
'exception_string', 'exception_full_string', 'exception_class_name',
'exception_class_qualname', 'exception_object', 'traceback']
```

**Extracting all stored local variables**

To extract the names of all local variables stored in the frames, use the
`SaveframeReader.variables` property. Example:
```
>>> reader.variables
{
   1: ['var1', 'var2', ...],
   2: ['var5', 'var8', 'var9', ...],
   ...
}
```

**Extracting the value of a specific metadata field**

To extract the value of a specific metadata field, use the
`SaveframeReader.get_metadata` method. Example:
```
>> reader.get_metadata("filename")
{1: '/dir1/mod1.py', 2: '/dir2/mod2.py', ...}

>> reader.get_metadata("filename", frame_idx=2)
'/dir2/mod2.py'

>> reader.get_metadata("exception_string")
"Error is raised"
```

**Extracting the value of specific local variables**

To extract the value of specific local variable(s), use the
`SaveframeReader.get_variables` method. Example:
```
>> reader.get_variables('var1')
{2: var1_value2, 4: var1_value4}

>>  reader.get_variables('var1', frame_idx=4)
var1_value4

>> reader.get_variables('var2')
var2_value3

>> reader.get_variables(['var1', 'var3'])
{2: {'var1': var1_value2, 'var3': var3_value2},
4: {'var1': var1_value4}, 5: {'var3': var3_value5}}

>> reader.get_variables(['var1', 'var3'], frame_idx=2)
{'var1': var1_value2, 'var3': var3_value2}
```

**NOTE:** Raw data can be extracted using `SaveframeReader.data` property.

Request: PyInf#13916
@saharan-deshaw
Copy link
Collaborator Author

cc @sac111gp

@dshivashankar1994
Copy link
Collaborator

Adding @rakh-deshaw for review

@dshivashankar1994 dshivashankar1994 removed their request for review January 6, 2025 07:34
lib/python/pyflyby/_saveframe_reader.py Outdated Show resolved Hide resolved
lib/python/pyflyby/_saveframe_reader.py Outdated Show resolved Hide resolved
>> reader.get_variables('var1')
{2: var1_value2, 4: var1_value4}

>> reader.get_variables('var1', frame_idx=4)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the case where frame_idx is not None,

Depending on the frame_idx value, get_variables either returns a "str" (actual value) or "dict" (variable-indexed value).

Thoughts on always returning a dict?

>>> reader.get_variable('var1', frame_idx=10)
{'var1': 'var1_value'}

>>> reader.get_variable(['var1', 'var2'], frame_idx=10)
{'var1': 'var1_value', 'var2': 'var2_value'}

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given that this class will be used in interactive fashion, I think it's better if it's more convenient for the users. So users should directly get the variable's value when they do reader.get_variable('var1', frame_idx=10), rather than users having to do reader.get_variable('var1', frame_idx=10)['var1']

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This feels more like "convenience vs consistence" now.

I am raising the consistence issue because if a user comes back writing a automation job on top of the SaveFrameReader class asking it to return a dict, we shouldn't make it a hassle for other users to switch.

lib/python/pyflyby/_saveframe_reader.py Show resolved Hide resolved
lib/python/pyflyby/_saveframe_reader.py Outdated Show resolved Hide resolved
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants