Skip to content

Instantly share code, notes, and snippets.

@jstasiak

jstasiak/output Secret

Last active May 17, 2021 19:54
Show Gist options
  • Select an option

  • Save jstasiak/7f1687100ec7b2000b5206a537b1a0b0 to your computer and use it in GitHub Desktop.

Select an option

Save jstasiak/7f1687100ec7b2000b5206a537b1a0b0 to your computer and use it in GitHub Desktop.
Python enum pattern matching draft
WebEvent.PageLoad
Page loaded
WebEvent.KeyPress('x')
Pressed key x
WebEvent.Click(x=1, y=3)
Clicked on 1/3
Option.Something('admin')
admin
False
True
Option.Nothing
Can not unwrap
True
False
from dataclasses import dataclass
from typing import get_type_hints, TypedDict, get_origin, get_args
def enum(cls):
hints = get_type_hints(cls)
names_values = [(name, getattr(cls, name)) for name in dir(cls)]
for name, value in names_values:
if isinstance(value, type) and hasattr(value, '__annotations__'):
replacement = type(f"{cls.__name__}.{name}", (cls,), {"__annotations__": value.__annotations__})
replacement = dataclass(replacement)
setattr(cls, name, replacement)
for name, type_ in hints.items():
if type_ is type(None):
local_name = name
class Singleton(cls):
def __repr__(self):
return f"{cls.__name__}.{local_name}"
replacement = Singleton()
elif get_origin(type_) is tuple:
args = get_args(type_)
parameter_count = len(args)
def __repr__(self):
content = ", ".join(repr(getattr(self, f"param{i}")) for i in range(parameter_count))
return f"{cls.__name__}.{name}({content})"
replacement = type(f"{cls.__name__}.{name}", (cls,), {"__annotations__": {f"param{i}": t for (i, t) in enumerate(args)}, "__repr__": __repr__})
replacement = dataclass(replacement)
else:
raise AssertionError(f"Unsupported type: {type_}")
setattr(cls, name, replacement)
return cls
@enum
class WebEvent:
PageLoad: None
KeyPress: tuple[str]
class Click:
x: int
y: int
def inspect(event: WebEvent) -> None:
match event:
case WebEvent.PageLoad:
print("Page loaded")
case WebEvent.KeyPress(c):
print(f"Pressed key {c}")
case WebEvent.Click(x=x, y=y):
print(f"Clicked on {x}/{y}")
print(WebEvent.PageLoad)
inspect(WebEvent.PageLoad)
print(WebEvent.KeyPress("x"))
inspect(WebEvent.KeyPress("x"))
print(WebEvent.Click(x=1, y=3))
inspect(WebEvent.Click(x=1, y=3))
print()
print()
from typing import Generic, TypeVar
T = TypeVar("T")
@enum
class Option(Generic[T]):
Nothing: None
Something: tuple[T]
def is_nothing(self):
return self is Option.Nothing
def is_something(self):
return isinstance(self, Option.Something)
def unwrap(self):
if isinstance(self, Option.Something):
return self.param0
raise RuntimeError(f"Can't unwrap {self}")
def return_user_maybe(condition: bool) -> Option["str"]:
if condition:
return Option.Something("admin")
else:
return Option.Nothing
user = return_user_maybe(True)
print(user)
print(user.unwrap())
print(user.is_nothing())
print(user.is_something())
user = Option.Nothing
print(user)
try:
print(user.unwrap())
except RuntimeError:
print("Can not unwrap")
print(user.is_nothing())
print(user.is_something())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment