Skip to content

Commit e2177a8

Browse files
wchschloerke
andauthored
Add lowercase reactive.value, calc, effect (#822)
Co-authored-by: Barret Schloerke <[email protected]>
1 parent 351598b commit e2177a8

File tree

22 files changed

+168
-138
lines changed

22 files changed

+168
-138
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1212
- `shiny create` now allows you to select from a list of template apps.
1313
- `shiny create` provides templates which help you build your own custom JavaScript components.
1414

15+
* Closed #814: The functions `reactive.Calc` and `reactive.Effect` have been changed to have lowercase names: `reactive.calc`, and `reactive.effect`. The old capitalized names are now aliases to the new lowercase names, so existing code will continue to work. Similarly, the class `reactive.Value` has a new alias, `reactive.value`, but in this case, since the original was a class, it keeps the original capitalized name as the primary name. The examples have not been changed yet, but will be changed in a future release. (#822)
16+
1517
### Bug fixes
1618

1719
* Fix support for `shiny.ui.accordion(multiple=)` (#799).

docs/_quartodoc.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,9 @@ quartodoc:
208208
- title: Reactive programming
209209
desc: ""
210210
contents:
211+
- reactive.calc
212+
- reactive.effect
213+
- reactive.value
211214
- reactive.Calc
212215
- reactive.Effect
213216
- reactive.Value

shiny/reactive/__init__.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,13 @@
88
)
99
from ._poll import poll, file_reader
1010
from ._reactives import ( # noqa: F401
11+
value,
1112
Value,
13+
calc,
1214
Calc,
1315
Calc_, # pyright: ignore[reportUnusedImport]
1416
CalcAsync_, # pyright: ignore[reportUnusedImport]
17+
effect,
1518
Effect,
1619
Effect_, # pyright: ignore[reportUnusedImport]
1720
event,
@@ -26,8 +29,11 @@
2629
"on_flushed",
2730
"poll",
2831
"file_reader",
32+
"value",
2933
"Value",
34+
"calc",
3035
"Calc",
36+
"effect",
3137
"Effect",
3238
"event",
3339
)

shiny/reactive/_poll.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ def poll(
9999
last_value: reactive.Value[Any] = reactive.Value(poll_func())
100100
last_error: reactive.Value[Optional[Exception]] = reactive.Value(None)
101101

102-
@reactive.Effect(priority=priority, session=session)
102+
@reactive.effect(priority=priority, session=session)
103103
async def _():
104104
try:
105105
if _utils.is_async_callable(poll_func):
@@ -159,7 +159,7 @@ async def _():
159159
def wrapper(fn: Callable[[], T]) -> Callable[[], T]:
160160
if _utils.is_async_callable(fn):
161161

162-
@reactive.Calc(session=session)
162+
@reactive.calc(session=session)
163163
@functools.wraps(fn)
164164
async def result_async() -> T:
165165
# If an error occurred, raise it
@@ -182,7 +182,7 @@ async def result_async() -> T:
182182

183183
else:
184184

185-
@reactive.Calc(session=session)
185+
@reactive.calc(session=session)
186186
@functools.wraps(fn)
187187
def result_sync() -> T:
188188
# If an error occurred, raise it

shiny/reactive/_reactives.py

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,18 @@
22

33
from __future__ import annotations
44

5-
__all__ = ("Value", "Calc", "Calc_", "CalcAsync_", "Effect", "Effect_", "event")
5+
__all__ = (
6+
"value",
7+
"Value",
8+
"calc",
9+
"Calc",
10+
"Calc_",
11+
"CalcAsync_",
12+
"effect",
13+
"Effect",
14+
"Effect_",
15+
"event",
16+
)
617

718
import functools
819
import traceback
@@ -204,6 +215,8 @@ def freeze(self) -> None:
204215
self._value = MISSING
205216

206217

218+
value = Value
219+
207220
# ==============================================================================
208221
# Calc
209222
# ==============================================================================
@@ -343,12 +356,12 @@ async def __call__(self) -> T: # pyright: ignore[reportIncompatibleMethodOverri
343356

344357

345358
@overload
346-
def Calc(fn: CalcFunctionAsync[T]) -> CalcAsync_[T]:
359+
def calc(fn: CalcFunctionAsync[T]) -> CalcAsync_[T]:
347360
...
348361

349362

350363
@overload
351-
def Calc(fn: CalcFunction[T]) -> Calc_[T]:
364+
def calc(fn: CalcFunction[T]) -> Calc_[T]:
352365
...
353366

354367

@@ -373,14 +386,14 @@ def Calc(fn: CalcFunction[T]) -> Calc_[T]:
373386
# __call__ method) or CalcAsync object (which has an async __call__ method), and it
374387
# works out.
375388
@overload
376-
def Calc(
389+
def calc(
377390
*, session: "MISSING_TYPE | Session | None" = MISSING
378391
) -> Callable[[CalcFunction[T]], Calc_[T]]:
379392
...
380393

381394

382395
@add_example()
383-
def Calc(
396+
def calc(
384397
fn: Optional[CalcFunction[T] | CalcFunctionAsync[T]] = None,
385398
*,
386399
session: "MISSING_TYPE | Session | None" = MISSING,
@@ -434,6 +447,9 @@ def create_calc(fn: CalcFunction[T] | CalcFunctionAsync[T]) -> Calc_[T]:
434447
return create_calc(fn)
435448

436449

450+
# Alias for backward compatibility
451+
Calc = calc
452+
437453
# ==============================================================================
438454
# Effect
439455
# ==============================================================================
@@ -630,12 +646,12 @@ def _on_session_ended_cb(self) -> None:
630646

631647

632648
@overload
633-
def Effect(fn: EffectFunction | EffectFunctionAsync) -> Effect_:
649+
def effect(fn: EffectFunction | EffectFunctionAsync) -> Effect_:
634650
...
635651

636652

637653
@overload
638-
def Effect(
654+
def effect(
639655
*,
640656
suspended: bool = False,
641657
priority: int = 0,
@@ -645,7 +661,7 @@ def Effect(
645661

646662

647663
@add_example()
648-
def Effect(
664+
def effect(
649665
fn: Optional[EffectFunction | EffectFunctionAsync] = None,
650666
*,
651667
suspended: bool = False,
@@ -706,6 +722,9 @@ def create_effect(fn: EffectFunction | EffectFunctionAsync) -> Effect_:
706722
return create_effect(fn)
707723

708724

725+
Effect = effect
726+
727+
709728
# ==============================================================================
710729
# event decorator
711730
# ==============================================================================

shiny/session/_session.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
if TYPE_CHECKING:
3838
from .._app import App
3939

40-
from .. import _utils, render
40+
from .. import _utils, reactive, render
4141
from .._connection import Connection, ConnectionClosed
4242
from .._docstring import add_example
4343
from .._fileupload import FileInfo, FileUploadManager
@@ -46,7 +46,7 @@
4646
from .._utils import wrap_async
4747
from ..http_staticfiles import FileResponse
4848
from ..input_handler import input_handlers
49-
from ..reactive import Effect, Effect_, Value, flush, isolate
49+
from ..reactive import Effect_, Value, effect, flush, isolate
5050
from ..reactive._core import lock, on_flushed
5151
from ..render.transformer import OutputRenderer
5252
from ..types import SafeException, SilentCancelOutputException, SilentException
@@ -904,7 +904,7 @@ def __init__(
904904
self._ns = ns
905905

906906
def __setitem__(self, key: str, value: Value[Any]) -> None:
907-
if not isinstance(value, Value):
907+
if not isinstance(value, reactive.Value):
908908
raise TypeError("`value` must be a reactive.Value object.")
909909

910910
self._map[self._ns(key)] = value
@@ -1008,7 +1008,7 @@ def set_renderer(renderer_fn: OutputRenderer[OT]) -> OutputRenderer[OT]:
10081008

10091009
self._suspend_when_hidden[output_name] = suspend_when_hidden
10101010

1011-
@Effect(
1011+
@effect(
10121012
suspended=suspend_when_hidden and self._session._is_hidden(output_name),
10131013
priority=priority,
10141014
)

tests/deploys/apps/plotly_app/app.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ def summary_data():
6161
height="100%",
6262
)
6363

64-
@reactive.Calc
64+
@reactive.calc
6565
def filtered_df():
6666
selected_idx = list(req(input.summary_data_selected_rows()))
6767
countries = summary_df["country"][selected_idx]
@@ -116,7 +116,7 @@ def synchronize_size(output_id):
116116
def wrapper(func):
117117
input = session.get_current_session().input
118118

119-
@reactive.Effect
119+
@reactive.effect
120120
def size_updater():
121121
func(
122122
input[f".clientdata_output_{output_id}_width"](),

tests/e2e/TODO/sidebar/app.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,24 +62,24 @@ def server(input: Inputs, output: Outputs, session: Session) -> None:
6262
def ui_content():
6363
return f"Hello, {input.adjective()} {input.animal()}!"
6464

65-
@reactive.Effect
65+
@reactive.effect
6666
@reactive.event(input.open_all)
6767
def _():
6868
ui.update_sidebar("sidebar_inner", show=True)
6969
ui.update_sidebar("sidebar_outer", show=True)
7070

71-
@reactive.Effect
71+
@reactive.effect
7272
@reactive.event(input.close_all)
7373
def _():
7474
ui.update_sidebar("sidebar_inner", show=False)
7575
ui.update_sidebar("sidebar_outer", show=False)
7676

77-
@reactive.Effect
77+
@reactive.effect
7878
@reactive.event(input.toggle_inner)
7979
def _():
8080
ui.update_sidebar("sidebar_inner", show=not input.sidebar_inner())
8181

82-
@reactive.Effect
82+
@reactive.effect
8383
@reactive.event(input.toggle_outer)
8484
def _():
8585
ui.update_sidebar("sidebar_outer", show=not input.sidebar_outer())

tests/e2e/TODO/update_popover/app.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,12 @@
1414

1515

1616
def server(input: Inputs, output: Outputs, session: Session):
17-
@reactive.Effect
17+
@reactive.effect
1818
def _():
1919
# Immediately display popover
2020
ui.update_popover("popover_id", show=True)
2121

22-
@reactive.Effect
22+
@reactive.effect
2323
@reactive.event(input.btn_update)
2424
def _():
2525
content = (
@@ -33,7 +33,7 @@ def _():
3333
# show=True
3434
)
3535

36-
@reactive.Effect
36+
@reactive.effect
3737
def _():
3838
req(input.btn_w_popover())
3939
ui.notification_show("Button clicked!", duration=3, type="message")

tests/e2e/async/app.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ async def hash_output():
3131
content = await hash_result()
3232
return content
3333

34-
@reactive.Calc()
34+
@reactive.calc()
3535
async def hash_result() -> str:
3636
with ui.Progress() as p:
3737
p.set(message="Calculating...")

0 commit comments

Comments
 (0)