-
Notifications
You must be signed in to change notification settings - Fork 27
Add object tracking functionality for Python 3.13.3+ #153
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
base: main
Are you sure you want to change the base?
Conversation
This commit adds support for tracking Python objects that survive test execution using the new reference tracking API introduced in memray (commit e567c3cf).
| f"{padding}Object types that leaked (total: {len(self.surviving_objects)} objects):" | ||
| ) | ||
| for obj_type, count in type_counts.most_common(10): | ||
| text_lines.append(f"{padding*2}- {obj_type}: {count} instance(s)") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It might be better to do:
| text_lines.append(f"{padding*2}- {obj_type}: {count} instance(s)") | |
| text_lines.append(f"{padding*2}- {count} {obj_type} instance(s)") |
That will make it easier to compare the quantities across different lines. Compare:
- int: 98175 instance(s)
- tuple: 12101 instance(s)
- dict: 8078 instance(s)
versus:
- 98175 int instance(s)
- 12101 tuple instance(s)
- 8078 dict instance(s)
It's a lot easier to compare the numbers when they're aligned. Maybe the counts should even be right aligned?
- 98175 int instance(s)
- 12101 tuple instance(s)
- 8078 dict instance(s)
| # Show a sample of the actual objects (up to 10) | ||
| text_lines.append(f"\n{padding}Sample of leaked objects:") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm. I wonder if it'd be nice to show one of each type, or something... if you imagine someone has leaked ten thousand ints and one dict, it's way more valuable to see the dict than the ints... Eh, or we can leave that as a potential future improvement.
| if _surviving_objects is None: | ||
| return None | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| if _surviving_objects is None: | |
| return None |
the below if already handles everything falsey, so no need to have this check separately.
| if not _surviving_objects: | ||
| return None | ||
|
|
||
| # Filter out frame objects and other internal Python objects |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm. What's the rationale for filtering all of these? I think one of the most frequent types of leaks I see is when someone saves an exception object somewhere, which references a traceback, and frames, and all their locals, etc. Excluding the tracebacks and frames might make it harder to understand the cause of a leak.
| if sys.version_info >= (3, 13, 3): | ||
| pytest.skip("Test for old Python versions", allow_module_level=True) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This won't run at all for an old Python version, because of the file level
pytestmark = pytest.mark.skipif(
sys.version_info < (3, 13, 3),| # Note: The actual implementation would need to inject | ||
| # a function to retrieve the objects |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand how this is meant to work at all 😓
Inject how?
|
|
||
| [tool.mypy] | ||
| python_version = "3.8" | ||
| python_version = "3.14" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm, shouldn't this stay the minimum version we support? Otherwise mypy will fail to tell us if we break 3.8 compatibility. Though I guess you could say that that's fine, we rely on the tests for checking that... Hm, OK, nevermind.
| """Type that holds information about objects that survived tracking.""" | ||
|
|
||
| surviving_objects: list | ||
| surviving_objects: list[Any] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't it be list[object], not list[Any]? Likewise for every occurrence of Any that you've added.
| tracker_kwargs["track_object_lifetimes"] = True | ||
|
|
||
| tracker = Tracker(result_file, **tracker_kwargs) | ||
| tracker = Tracker(result_file, **tracker_kwargs) # type: ignore[call-overload] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Huh, what error is it complaining about here?
This commit adds support for tracking Python objects that survive test execution
using the new reference tracking API introduced in memray (commit e567c3cf).
Issue number of the reported bug or feature request: #
Describe your changes
A clear and concise description of the changes you have made.
Testing performed
Describe the testing you have performed to ensure that the bug has been addressed, or that the new feature works as planned.
Additional context
Add any other context about your contribution here.