textual icon indicating copy to clipboard operation
textual copied to clipboard

Decorator madness

Open willmcgugan opened this issue 4 months ago • 2 comments

Decorators for watch, compute, and validate. Works like this:

class MyWidget(Widget):

    count = reactive(0)
    double_count = reactive(0)

    @count.watch
    def count_changed(self, new_count:int):
        ...

    @count.validate
    def _max_ten(self, value:int) -> int:
        return min(10, value)

    @double_count.compute
    def _double(self) -> int:
        return self.count * 2

willmcgugan avatar Feb 24 '24 15:02 willmcgugan

With this change, how would we override what a watcher does in a widget subclass?

If I have a count reactive declared in a widget which has a watcher defined, then I subclass that and I want my own watcher, how would I achieve this? In the child class, @count.watch doesn't work because count is not defined.

For example, this fails to run because NameError: name 'count' is not defined

    class Parent(Widget):
        count: Reactive[int] = reactive(0, init=False)

        @count.watch
        def _count_parent(self, new_value: int) -> None:
            print("parent watcher")

    class Child(Parent):

        @count.watch
        def _count_parent(self, new_value: int) -> None:
            print("child watcher")

@Parent.count.watch doesn't work because of the "only a single method may be decorated with watch".

Even if that's solved, there's still a bit of a developer experience issue that @davep mentioned, whereby we no longer know what the parent watch method is called without going looking for it.

darrenburns avatar Feb 28 '24 13:02 darrenburns

Going to park this for now. @darrenburns 's observation re inheritance may kill this idea entirely.

willmcgugan avatar Feb 28 '24 13:02 willmcgugan