@@ -101,14 +101,14 @@ async def test_reactive_value_unset():
101101 with isolate ():
102102 assert v .is_set () is False
103103 with pytest .raises (SilentException ):
104- v ()
104+ v (warn_if_missing = False )
105105
106106 val : int = 0
107107
108108 @effect ()
109109 def o ():
110110 nonlocal val
111- val = v ()
111+ val = v (warn_if_missing = False )
112112
113113 await flush ()
114114 assert o ._exec_count == 1
@@ -128,7 +128,7 @@ def o():
128128 with isolate ():
129129 assert v .is_set () is False
130130 with pytest .raises (SilentException ):
131- v ()
131+ v (warn_if_missing = False )
132132
133133
134134# ======================================================================
@@ -1021,7 +1021,7 @@ async def test_event_silent_exception():
10211021 x = Value [bool ]()
10221022
10231023 @effect ()
1024- @event (x )
1024+ @event (lambda : x ( warn_if_missing = False ) )
10251025 def _ ():
10261026 nonlocal n_times
10271027 n_times += 1
@@ -1052,7 +1052,7 @@ async def test_event_silent_exception_async():
10521052
10531053 async def req_fn () -> int :
10541054 await asyncio .sleep (0 )
1055- x ()
1055+ x (warn_if_missing = False )
10561056 return 1234
10571057
10581058 @effect ()
@@ -1365,3 +1365,170 @@ async def obs():
13651365 a .set (4 )
13661366 await flush ()
13671367 assert obs ._exec_count == 2
1368+
1369+
1370+ # ======================================================================
1371+ # reactive.Value.get() with default parameter
1372+ # ======================================================================
1373+ @pytest .mark .asyncio
1374+ async def test_reactive_value_get_with_default ():
1375+ # Test with unset value - should return default
1376+ v = Value [int ]()
1377+
1378+ with isolate ():
1379+ assert v .get (default = 42 ) == 42
1380+ assert v .get (default = 0 ) == 0
1381+ assert v .get (default = None ) is None
1382+
1383+ # Test after setting value - should return value, not default
1384+ v .set (100 )
1385+ with isolate ():
1386+ assert v .get (default = 42 ) == 100
1387+ assert v .get (default = 0 ) == 100
1388+
1389+ # Test after unsetting - should return default again
1390+ v .unset ()
1391+ with isolate ():
1392+ assert v .get (default = 99 ) == 99
1393+
1394+
1395+ @pytest .mark .asyncio
1396+ async def test_reactive_value_call_with_default ():
1397+ # Test that __call__ also supports default parameter
1398+ v = Value [str ]()
1399+
1400+ with isolate ():
1401+ assert v (default = "hello" ) == "hello"
1402+ assert v (default = None ) is None
1403+
1404+ v .set ("world" )
1405+ with isolate ():
1406+ assert v (default = "hello" ) == "world"
1407+
1408+ v .unset ()
1409+ with isolate ():
1410+ assert v (default = "fallback" ) == "fallback"
1411+
1412+
1413+ @pytest .mark .asyncio
1414+ async def test_reactive_value_default_in_reactive_context ():
1415+ # Test using default parameter within reactive contexts
1416+ v = Value [int ]()
1417+ result = None
1418+
1419+ @effect ()
1420+ def obs ():
1421+ nonlocal result
1422+ result = v .get (default = 10 )
1423+
1424+ await flush ()
1425+ assert result == 10
1426+ assert obs ._exec_count == 1
1427+
1428+ # Setting the value should invalidate and return new value
1429+ v .set (50 )
1430+ await flush ()
1431+ assert result == 50
1432+ assert obs ._exec_count == 2
1433+
1434+ # Unsetting should use default again
1435+ v .unset ()
1436+ await flush ()
1437+ assert result == 10
1438+ assert obs ._exec_count == 3
1439+
1440+
1441+ @pytest .mark .asyncio
1442+ async def test_reactive_value_no_default_raises_silent_exception ():
1443+ # Test that without default, unset value still raises SilentException
1444+ v = Value [int ]()
1445+
1446+ with isolate ():
1447+ with pytest .raises (SilentException ):
1448+ v .get ()
1449+ with pytest .raises (SilentException ):
1450+ v ()
1451+
1452+
1453+ # ======================================================================
1454+ # reactive.Value warning behavior
1455+ # ======================================================================
1456+ @pytest .mark .asyncio
1457+ async def test_reactive_value_missing_warning ():
1458+ # Test that reading unset value with warn_if_missing=True logs warning
1459+ v = Value [int ]()
1460+
1461+ with isolate ():
1462+ with pytest .warns (
1463+ ReactiveWarning , match = "Attempted to read a `reactive.value`"
1464+ ):
1465+ try :
1466+ v .get ()
1467+ except SilentException :
1468+ pass
1469+
1470+
1471+ @pytest .mark .asyncio
1472+ async def test_reactive_value_suppress_warning ():
1473+ # Test that warn_if_missing=False suppresses the warning
1474+ v = Value [int ]()
1475+
1476+ with isolate ():
1477+ # Should not produce a warning
1478+ with pytest .raises (SilentException ):
1479+ v .get (warn_if_missing = False )
1480+
1481+
1482+ @pytest .mark .asyncio
1483+ async def test_reactive_value_default_no_warning ():
1484+ # Test that providing a default doesn't generate warning
1485+ v = Value [int ]()
1486+
1487+ with isolate ():
1488+ # Should not raise or warn when default is provided
1489+ result = v .get (default = 42 )
1490+ assert result == 42
1491+
1492+
1493+ @pytest .mark .asyncio
1494+ async def test_input_value_missing_warning ():
1495+ # Test that reading unset input value shows input-specific warning
1496+ conn = MockConnection ()
1497+ session = App (ui .TagList (), None )._create_session (conn )
1498+ input = session .input
1499+
1500+ # Access an input that doesn't exist yet
1501+ with isolate ():
1502+ with pytest .warns (
1503+ ReactiveWarning , match = r"Attempted to read `input\.test_input\(\)`"
1504+ ):
1505+ try :
1506+ input .test_input ()
1507+ except SilentException :
1508+ pass
1509+
1510+
1511+ @pytest .mark .asyncio
1512+ async def test_input_value_with_default ():
1513+ # Test that input values can use default parameter
1514+ conn = MockConnection ()
1515+ session = App (ui .TagList (), None )._create_session (conn )
1516+ input = session .input
1517+
1518+ with isolate ():
1519+ # Should return default without warning or exception
1520+ result = input .test_input (default = "fallback" )
1521+ assert result == "fallback"
1522+
1523+
1524+ @pytest .mark .asyncio
1525+ async def test_input_value_suppress_warning ():
1526+ # Test that warn_if_missing=False suppresses input warning
1527+ conn = MockConnection ()
1528+ session = App (ui .TagList (), None )._create_session (conn )
1529+ input = session .input
1530+
1531+ with isolate ():
1532+ # Should not produce a warning
1533+ with pytest .raises (SilentException ):
1534+ input .test_input (warn_if_missing = False )
0 commit comments