Skip to content

Instantly share code, notes, and snippets.

@charles-l
Created July 7, 2021 19:52
Show Gist options
  • Save charles-l/c2b113f8fa344ebf57b8facedb184534 to your computer and use it in GitHub Desktop.
Save charles-l/c2b113f8fa344ebf57b8facedb184534 to your computer and use it in GitHub Desktop.
Reactive programming in python
from functools import wraps
from collections import defaultdict
from dataclasses import dataclass, field
from typing import Dict, List
import ast
import inspect
class StateFinder(ast.NodeVisitor):
def __init__(self, state_name):
self.state_name = state_name
self.state_attrs = []
def visit_Attribute(self, node):
if node.value.id == self.state_name:
self.state_attrs.append(node.attr)
@dataclass
class State:
_subscribers: Dict[str, List] = field(default_factory=lambda: defaultdict(list))
x: int = 3
y: int = 1
def __setattr__(self, key, val):
super().__setattr__(key, val)
for s in self._subscribers[key]:
s()
def reactive(state_name):
def wrapper(f):
tree = ast.parse(inspect.getsource(f))
sf = StateFinder(state_name)
sf.visit(tree)
for attr in sf.state_attrs:
state._subscribers[attr].append(f)
return f
return wrapper
## WHOAA REACTIVE PROGRAMMING LETS GOOO
state = State()
@reactive('state')
def doprint():
print(f'{state.x=}, {state.y=}')
state.x = 4
state.x = 5
state.y = 2
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment