Some Suggestions
Closed this issue · 0 comments
Saw this on Twitter, cool project! It's great to see experienced developers experimenting with things (I'm a big fan of building experimental things), there's not enough fun with software these days. With that being said, I have a few suggestions:
I do realize that this library is not supposed to replace dataclasses
or pydantic
, but adding an __init__
could pave the way for some new features in the future. A new decorator could be introduced to build a type at runtime via an automatically generated __init__
:
import declare
@declare.init
class Color:
"""A color object with RGB, and alpha components."""
red = declare.Int(0)
green = declare.Int(0)
blue = declare.Int(0)
alpha = declare.Float(1.0)
@red.validate
@green.validate
@blue.validate
def _validate_component(self, component: int) -> int:
"""Restrict RGB to 0 -> 255."""
return max(0, min(255, component))
@alpha.validate
def _validate_alpha(self, alpha: float) -> float:
return max(0.0, min(1.0, alpha))
color = Color(0, 0, 255, 1.0)
If you decide to go that route, than you could also introduce a way to parse a type from a given input:
import declare
@declare.init
class Point:
x = declare.Int(0)
y = declare.Int(0)
@x.parse
def _parse_x(self, obj: Any) -> int:
return int(obj)
point = Point('1', 2)
Alternatively, instead of using parse
for __init__
only, maybe just call it every time the value is changed? This could be similar to how watch
works, but it takes whatever type was passed instead of an old and new type, then whatever type the parser returns can be sent to the watcher and validator:
import declare
class Point:
x = declare.Int(0)
y = declare.Int(0)
@x.parse
def _parse_x(self, obj: Any) -> int:
return int(obj)
point = Point()
point.x = '1'
If you want to go the route of heading away from dataclass-like libraries instead, then maybe this could be used to make some debugging tools inside of Textual or something other? I think you could track where and when attributes were changed via some magic with Frame
objects:
import declare
class Foo:
bar = declare.Str("spam")
foo = Foo()
foo.bar = "hello"
print(declare.stack(foo))
"""
{
"bar": [AttributeCreated(frame=..., value="spam", when=...), AttributeChanged(frame=..., old_value="spam", value="hello", when=...)]
}
"""
Anyways, this is all speculation. This project came out like what, an hour ago? Keep up the good work!