Skip to content

Commit 40e71af

Browse files
Replace declare with reacttrs (#30)
1 parent ff68f8c commit 40e71af

6 files changed

Lines changed: 37 additions & 56 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,6 @@
55
`ypywidgets` is a communication backend between a Jupyter kernel and clients. It allows to synchronize data structures that can be modified concurrently, and automatically resolves conflicts. To do so, it uses:
66
- the Jupyter kernel [Comm](https://jupyter-client.readthedocs.io/en/stable/messaging.html#custom-messages) protocol as the transport layer, and the [comm](https://github.com/ipython/comm) implementation of it.
77
- the [pycrdt](https://github.com/davidbrochart/pycrdt) CRDT implementation.
8-
- the [declare](https://github.com/willmcgugan/declare) library that implements the observer pattern and validation.
8+
- the [reacttrs](https://github.com/davidbrochart/reacttrs) library that implements the observer pattern and validation.
99

1010
It is a replacement for (a part of) [ipywidgets](https://ipywidgets.readthedocs.io). When used with [yjs-widgets](https://github.com/davidbrochart/yjs-widgets), it supports JupyterLab clients that implement widgets. The difference with `ipywidgets` is that these widgets are collaborative: they can be manipulated concurrently from the kernel or from any client. The CRDT algorithm ensures that a widget state will eventually be consistent across all clients.

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ keywords = [
2020
dependencies = [
2121
"comm >=0.1.4,<1",
2222
"pycrdt >=0.8.30,<0.9.0",
23-
"declare >=1.0.1,<2.0.0",
23+
"reacttrs >=0.2.1,<0.3.0",
2424
]
2525

2626
[project.urls]

tests/test_attributes.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,18 @@
33

44
import pytest
55
from pycrdt import Text
6-
from ypywidgets import Declare
6+
from ypywidgets import Reactive
77
from ypywidgets.comm import CommWidget
88

99

1010
class Widget1(CommWidget):
11-
foo = Declare[str]("foo1")
12-
bar = Declare[str]("bar1")
13-
baz = Declare[Optional[str]](None)
11+
foo = Reactive[str]("foo1")
12+
bar = Reactive[str]("bar1")
13+
baz = Reactive[Optional[str]](None)
1414

1515

1616
class Widget2(CommWidget):
17-
foo = Declare[str]("")
17+
foo = Reactive[str]("")
1818

1919
@foo.watch
2020
def _watch_foo(self, old, new):

ypywidgets/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from .widget import Widget as Widget
2-
from .declare import Declare as Declare
2+
from .reactive import Reactive as Reactive
33

44

55
__version__ = "0.8.1"

ypywidgets/declare.py

Lines changed: 0 additions & 48 deletions
This file was deleted.

ypywidgets/reactive.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
from __future__ import annotations
2+
3+
from typing import Generic
4+
5+
from pycrdt import ReadTransaction
6+
from reacttrs import Reactive as _Reactive
7+
from reacttrs.reactive import Validator, ValueType, Watcher
8+
9+
from .widget import Widget
10+
11+
12+
class Reactive(_Reactive, Generic[ValueType]):
13+
14+
def __init__(
15+
self,
16+
default: ValueType,
17+
*,
18+
validate: Validator | None = None,
19+
watchers: set[Watcher] | None = None,
20+
) -> None:
21+
super().__init__(default, validate=validate, watchers=watchers)
22+
23+
@self.watch
24+
def _set_attr(obj: Widget, old: ValueType, new: ValueType) -> None:
25+
with obj.ydoc.transaction() as txn:
26+
# if we set the attribute, we are observing our own change: do nothing
27+
# we know it's the case because callbacks provide read-only transactions
28+
if not isinstance(txn, ReadTransaction):
29+
obj._attrs[self._name] = new

0 commit comments

Comments
 (0)