-
Notifications
You must be signed in to change notification settings - Fork 192
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
add slots to base classes, @add_slots takes bases into account #605
Conversation
mock.visited_a() | ||
object.__setattr__(node, "a_attr", True) | ||
def visit_Del(self, node: cst.Del) -> None: | ||
object.__setattr__(node, "target", mock.visited_a()) |
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 had to change to using Del
, because Pass
didn't have two fields available to reproduce the original test.
due to the slots, arbitrary fields can no longer be set. Existing fields need to be (ab)used.
def visit_Pass(self, node: cst.Pass) -> None: | ||
mock.visit_Pass() | ||
object.__setattr__(node, "visit_Pass", True) | ||
def visit_If(self, node: cst.If) -> 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.
I had to change to using If
, because Pass
didn't have four fields available to reproduce the original test.
due to the slots, arbitrary fields can no longer be set. Existing fields need to be (ab)used.
Wow, I did a rough benchmark: from pympler.asizeof import asizeof
from libcst import parse_module
from pathlib import Path
parsed = parse_module(Path('libcst/_typed_visitor.py').read_text())
print(asizeof(parsed)) without patched slots: 15_240_816 This cuts memory usage by a factor 3 :) |
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.
Thanks for the high quality PR! Much appreciated. All of this looks good to me. There's just one change I'd like to request before merging: can you please add a unit test that exercises the new logic in add_slots
?
libcst/_nodes/base.py
Outdated
# pyre-ignore[4]: Attribute `__slots__` of class `CSTNode` | ||
# has type `typing.Tuple[]` but no type is specified. | ||
# But we know it's str | ||
__slots__ = () |
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 think you can remove this pyre-ignore by doing
# pyre-ignore[4]: Attribute `__slots__` of class `CSTNode` | |
# has type `typing.Tuple[]` but no type is specified. | |
# But we know it's str | |
__slots__ = () | |
__slots__: Sequence[str] = () |
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 needed an additional ClassVar
to prevent it from being picked up as a dataclass field
Codecov Report
@@ Coverage Diff @@
## main #605 +/- ##
==========================================
+ Coverage 94.72% 94.76% +0.04%
==========================================
Files 244 245 +1
Lines 24916 25038 +122
==========================================
+ Hits 23602 23728 +126
+ Misses 1314 1310 -4
Continue to review full report at Codecov.
|
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.
Let's go🚀! Thanks for the contribution
Summary
See #574: many slots were missing in base classes, meaning we didn't get the full memory savings or the ability to block arbitrary attribute setting.
Additionally, I found some slots overlapping where
add_slots
dataclasses inherited from each other. I think this isn't even done right in the stdlib...Some changes were needed to the tests now that arbitrary attributes could not be set. Here I was less sure of the desired outcome.
Test Plan
Future violations can be prevented with slotscheck (which I developed).
See here a recent PR where I added it to the returns library.
I'm of course happy to include in dev/CI plan as you indidated