-
Simplicity. This package exports only a single definition: the
adt
class decorator:
from adt import adt
-
Concision. Constructors are specified via class annotations,
allowing for syntax comparable to Rust's enum
s:
@adt
class Event:
MouseClick: [int, int]
KeyPress: {'key': str, 'modifiers': list[str]}
-
Pattern Matching via match
is fully supported (Python >= 3.10):
event = Event.KeyPress(key='a', modifiers=['shift'])
match event:
case Event.MouseClick(x, y): print(f"Clicked at ({x}, {y}).")
case Event.KeyPress(key, mods): print(f"Pressed key {key}.")
-
Named and unnamed constructor fields are supported:
- Constructors with named fields, like
KeyPress
, are specified as a dict[str, type]
; - Constructors with unnamed fields, like
MouseClick
, are specified as a list[type]
; - Constructors with a single unnamed field can also be specified as a
type
; - Constructors with no fields are specified as the empty list.
-
Getters, Setters, and Instance-Checking methods are derived as an alternative to pattern matching, e.g.
if event.is_mouse_click():
print(f"Clicked at ({event._1}, {event._2}).")
elif event.is_key_press():
print(f"Pressed key {event.key}.")
-
Constructors are customizable dataclasses.
The dataclass
decorator derives many useful method implementations,
e.g. structural equality and string-conversion.
Additonal keyword arguments to adt
are forwarded as keyword
arguments to the dataclass
annotations of all constructors:
@adt(frozen=True)
class Event:
MouseClick: [int, int]
KeyPress: {'key': str, 'modifiers': list[str]}
event = Event.MouseClick(5, 10)
event._0 = 42
-
Constructors inherit from the decorated type.
Making the constructors inherit from the decorated class, allows to
define methods with pattern matching directly in the decorated class
and call them on objects of the constructor classes:
@adt
class Event:
MouseClick: [int, int]
KeyPress: {'key': str, 'modifiers': list[str]}
def print(self):
match self:
case Event.MouseClick(x, y): print(f"Clicked at ({event._1}, {event._2}).")
case Event.KeyPress(key, mods): print(f"Pressed key {event.key}.")
Event.MouseClick(5, 10).print()
-
Constructors can be exported into the global namespace.
@adt(export=True)
class Event:
MouseClick: [int, int]
KeyPress: {'key': str, 'modifiers': list[str]}
def print(self):
match self:
case MouseClick(x, y): ...
case KeyPress(key, mods): ...
-
Reflection.
The decorated class has a static field constructors: dict[str, type]
which maps the constructor names to their classes, e.g.
key_event = Event.constructors['KeyPress'](key='a', modifiers=['shift'])
The following compares this package to packages which aim to provide similar functionality: