statepatch 0.2.0__tar.gz → 0.2.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: statepatch
3
- Version: 0.2.0
3
+ Version: 0.2.1
4
4
  Summary: Immer-style ops over a plain JSON tree: observables that emit every mutation as an op
5
5
  Project-URL: Repository, https://github.com/assistant-ui/harness-sdk
6
6
  License-Expression: MIT
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "statepatch"
3
- version = "0.2.0"
3
+ version = "0.2.1"
4
4
  description = "Immer-style ops over a plain JSON tree: observables that emit every mutation as an op"
5
5
  readme = "README.md"
6
6
  license = "MIT"
@@ -34,15 +34,16 @@ def _snapshot(node: Any) -> Any:
34
34
 
35
35
 
36
36
  def plain(value: Any) -> Any:
37
- """Resolve a proxy or observable to a plain snapshot; pass anything else through."""
37
+ """Resolve a proxy or observable to its live stored node (mutating it emits no ops); pass anything else through."""
38
38
  from ._core import Observable, Proxy
39
39
 
40
- if isinstance(value, Proxy):
41
- _owner, _rel, node = value._target()
42
- return _snapshot(node)
43
40
  if isinstance(value, Observable):
44
- return _snapshot(value._state)
45
- return value
41
+ value = Proxy(value, ())
42
+ if not isinstance(value, Proxy):
43
+ return value
44
+ owner, rel, node = value._target()
45
+ mounted = any(path[: len(rel)] == rel for _child, path, _unsub in owner._mounts.values())
46
+ return _snapshot(node) if mounted else node
46
47
 
47
48
 
48
49
  def _adopt(value: Any, base: Path) -> tuple[Any, list[tuple[Path, "Observable"]]]:
@@ -4,7 +4,7 @@ mounted observables forward their op streams at the mount path."""
4
4
  from datetime import datetime, timezone
5
5
 
6
6
  import pytest
7
- from statepatch import Op, append, observable
7
+ from statepatch import Observable, Op, append, observable, plain
8
8
 
9
9
 
10
10
  def collect(obs):
@@ -180,6 +180,26 @@ def test_snapshot_ops_carry_plain_values_for_nested_mounts():
180
180
  assert ops[-1] == Op("replace", ("wrap", "inner", "n"), 7)
181
181
 
182
182
 
183
+ def test_plain_returns_the_live_node():
184
+ state = observable({"runs": [{"id": "r1"}]})
185
+ ops = collect(state)
186
+ assert plain(state) is state._state
187
+ assert plain(state["runs"]) is state._state["runs"]
188
+ assert plain(state["runs"][0]["id"]) == "r1"
189
+ plain(state["runs"]).append({"id": "r2"})
190
+ assert state.value == {"runs": [{"id": "r1"}, {"id": "r2"}]}
191
+ assert ops == []
192
+
193
+
194
+ def test_plain_unwraps_mounts_into_a_snapshot():
195
+ child = observable({"n": 0})
196
+ parent = observable({"wrap": {"inner": child}, "other": [1]})
197
+ assert plain(parent["wrap"]) == {"inner": {"n": 0}}
198
+ assert not isinstance(plain(parent["wrap"])["inner"], Observable)
199
+ assert plain(parent["wrap"]["inner"]) is child._state
200
+ assert plain(parent["other"]) is parent._state["other"]
201
+
202
+
183
203
  def test_container_helpers():
184
204
  state = observable({"d": {"a": 1}, "l": [1, 2, 3]})
185
205
  ops = collect(state)
File without changes
File without changes