A user-interface recorder stores millions of small events (clicks, key presses, scrolls), so every event class uses __slots__. Writing __init__, __repr__ and __eq__ for each class by hand is repetitive, and a subclass that forgets its own __slots__ quietly gets a __dict__ again. Write a base class Record that does all of this once:
class Event(Record):
__slots__ = ("time",)
class Click(Event):
__slots__ = ("x", "y")
Recorditself has__slots__ = (). Defining a subclass whose class body has no__slots__raisesTypeError(at the moment the class is defined).fields()(a class method) returns a tuple of all field names of the class: those of the class closest toRecordfirst, and within a class in the order written. A__slots__written as a single string is one field.__init__accepts the fields as positional arguments (in field order) and keyword arguments. Too many positional arguments, an unknown keyword, a field given twice or a missing field raisesTypeError.repr(record)looks likeClick(time=3, x=10, y=20): the class name and every field asname=repr(value).- Two records are equal when they are of the same class and all their fields are equal.
replace(**changes)returns a new record of the same class with some fields changed (an unknown field raisesTypeError).
The tests define the event classes on your Record inside setup helpers you can call with Run: event_classes(), basics(), bad_calls(), forgot_slots(), replaced() and event_log(n, seed). outcome(call) returns a result or the exception's name.
Examples
Input: basics()
Output: (("time", "x", "y"), ("time", "amount"), "Click(time=3, x=10, y=20)", "Key(time=4, key='a', shift=False)", "Scroll(time=9, amount=-2.5)", True, False, False, False, "AttributeError")
Input: forgot_slots()
Output: ("TypeError", "Hover(time=1)")
Constraints
- Field values are plain Python values; records are compared only with
==.
Goals
- Use `__slots__` across a class hierarchy, knowing that every subclass needs its own
- Collect the fields of a class from the `__slots__` of every class in its method resolution order
- Write a generic `__init__`, `__repr__` and `__eq__` once, in a base class, for every record type