Skip to content

Commit 86b5e42

Browse files
committed
Merge branch 'main' into data_view_meta
* main: bug(output transformer): fix transformer auto-registration (#1394) fix: Add wait till pulse animation has started (#1393) bug(test-deploy): Add retries for deploy tests (#1392) Add busy indicator tests (#1391) Yield to give "synchronous" writes a chance to complete (#1388) chore(busy indicator): Update busy indicator css files (#1389) feat(cli): Add `shiny --version` (#1387) fix(selectize): Accept jsonifiable values in `options` dictionary (#1382) bug(data frame): Use `<ID>_data_view_rows` (#1386)
2 parents 46ad96b + 2dc1e77 commit 86b5e42

File tree

24 files changed

+263
-21
lines changed

24 files changed

+263
-21
lines changed

setup.cfg

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ test =
6565
pytest>=6.2.4
6666
pytest-asyncio>=0.17.2
6767
pytest-playwright>=0.3.0
68+
playwright>=1.43.0
6869
pytest-xdist
6970
pytest-timeout
7071
pytest-rerunfailures

shiny/_main.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,15 @@
1818

1919
import shiny
2020

21-
from . import _autoreload, _hostenv, _static, _utils
21+
from . import __version__, _autoreload, _hostenv, _static, _utils
2222
from ._docstring import no_example
2323
from ._typing_extensions import NotRequired, TypedDict
2424
from .express import is_express_app
2525
from .express._utils import escape_to_var_name
2626

2727

2828
@click.group("main")
29+
@click.version_option(__version__)
2930
def main() -> None:
3031
pass
3132

shiny/reactive/_reactives.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
"event",
1616
)
1717

18+
import asyncio
1819
import functools
1920
import traceback
2021
import warnings
@@ -575,6 +576,10 @@ async def _run(self) -> None:
575576
try:
576577
with ctx():
577578
await self._fn()
579+
580+
# Yield so that messages can be sent to the client if necessary.
581+
# https://github.com/posit-dev/py-shiny/issues/1381
582+
await asyncio.sleep(0)
578583
except SilentException:
579584
# It's OK for SilentException to cause an Effect to stop running
580585
pass

shiny/render/transformer/_transformer.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -266,8 +266,8 @@ def __init__(
266266
self._default_ui_args: tuple[object, ...] = tuple()
267267
self._default_ui_kwargs: dict[str, object] = dict()
268268

269-
# Allow for App authors to not require `@output`
270-
self._auto_register()
269+
# Register the value function with the parent Renderer class
270+
self(value_fn)
271271

272272
def _meta(self) -> TransformerMetadata:
273273
"""

shiny/session/_session.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
__all__ = ("Session", "Inputs", "Outputs")
66

7+
import asyncio
78
import contextlib
89
import dataclasses
910
import enum
@@ -653,6 +654,12 @@ def verify_state(expected_state: ConnectionState) -> None:
653654
f"Unrecognized method {message_obj['method']}"
654655
)
655656

657+
# Progress messages (of the "{binding: {id: xxx}}"" variety) may
658+
# have queued up at this point; let them drain before we send
659+
# the next message.
660+
# https://github.com/posit-dev/py-shiny/issues/1381
661+
await asyncio.sleep(0)
662+
656663
self._request_flush()
657664

658665
await flush()

shiny/ui/_input_select.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
from __future__ import annotations
44

5+
from ..types import Jsonifiable
6+
57
__all__ = (
68
"input_select",
79
"input_selectize",
@@ -57,7 +59,7 @@ def input_selectize(
5759
multiple: bool = False,
5860
width: Optional[str] = None,
5961
remove_button: Optional[bool] = None,
60-
options: Optional[dict[str, str | float | JSEval]] = None,
62+
options: Optional[dict[str, Jsonifiable | JSEval]] = None,
6163
) -> Tag:
6264
"""
6365
Create a select list that can be used to choose a single or multiple items from a
@@ -137,7 +139,7 @@ def input_select(
137139
width: Optional[str] = None,
138140
size: Optional[str] = None,
139141
remove_button: Optional[bool] = None,
140-
options: Optional[dict[str, str | float | JSEval]] = None,
142+
options: Optional[dict[str, Jsonifiable | JSEval]] = None,
141143
) -> Tag:
142144
"""
143145
Create a select list that can be used to choose a single or multiple items from a

shiny/www/shared/_version.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
22
"note!": "This file is auto-generated by scripts/htmlDependencies.R",
33
"package": "shiny",
4-
"version": "Github (rstudio/shiny@3d6694040208055dc32e845ac3a93a0e68e47585)"
4+
"version": "Github (rstudio/shiny@733a4e898369892f553191a4d8cf67086333a8bf)"
55
}

shiny/www/shared/bootstrap/_version.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"note!": "This file is auto-generated by scripts/htmlDependencies.R",
3-
"shiny_version": "Github (rstudio/shiny@3d6694040208055dc32e845ac3a93a0e68e47585)",
3+
"shiny_version": "Github (rstudio/shiny@733a4e898369892f553191a4d8cf67086333a8bf)",
44
"bslib_version": "Github (rstudio/bslib@3dd55fd7249d30ecddac8f98ba8dc70aee0b3459)",
55
"htmltools_version": "Github (rstudio/htmltools@487aa0bed7313d7597b6edd5810e53cab0061198)",
66
"bootstrap_version": "5.3.1"

shiny/www/shared/busy-indicators/busy-indicators.css

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/playwright/deploys/express-accordion/test_deploys_express_accordion.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,18 @@
1+
import pytest
12
from controls import Accordion
23
from playwright.sync_api import Page
3-
from utils.deploy_utils import create_deploys_app_url_fixture, skip_if_not_chrome
4+
from utils.deploy_utils import (
5+
create_deploys_app_url_fixture,
6+
reruns,
7+
reruns_delay,
8+
skip_if_not_chrome,
9+
)
410

511
app_url = create_deploys_app_url_fixture("shiny_express_accordion")
612

713

814
@skip_if_not_chrome
15+
@pytest.mark.flaky(reruns=reruns, reruns_delay=reruns_delay)
916
def test_express_accordion(page: Page, app_url: str) -> None:
1017
page.goto(app_url)
1118

tests/playwright/deploys/express-dataframe/test_deploys_express_dataframe.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,18 @@
1+
import pytest
12
from controls import OutputDataFrame
23
from playwright.sync_api import Page
3-
from utils.deploy_utils import create_deploys_app_url_fixture, skip_if_not_chrome
4+
from utils.deploy_utils import (
5+
create_deploys_app_url_fixture,
6+
reruns,
7+
reruns_delay,
8+
skip_if_not_chrome,
9+
)
410

511
app_url = create_deploys_app_url_fixture("shiny-express-dataframe")
612

713

814
@skip_if_not_chrome
15+
@pytest.mark.flaky(reruns=reruns, reruns_delay=reruns_delay)
916
def test_express_dataframe_deploys(page: Page, app_url: str) -> None:
1017
page.goto(app_url)
1118

tests/playwright/deploys/express-folium/test_deploys_express_folium.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,17 @@
1+
import pytest
12
from playwright.sync_api import Page, expect
2-
from utils.deploy_utils import create_deploys_app_url_fixture, skip_if_not_chrome
3+
from utils.deploy_utils import (
4+
create_deploys_app_url_fixture,
5+
reruns,
6+
reruns_delay,
7+
skip_if_not_chrome,
8+
)
39

410
app_url = create_deploys_app_url_fixture("shiny-express-folium")
511

612

713
@skip_if_not_chrome
14+
@pytest.mark.flaky(reruns=reruns, reruns_delay=reruns_delay)
815
def test_folium_map(page: Page, app_url: str) -> None:
916
page.goto(app_url)
1017

tests/playwright/deploys/express-page_default/test_deploys_express_page_default.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,20 @@
1+
import pytest
12
from controls import LayoutNavsetTab
23
from playwright.sync_api import Page, expect
3-
from utils.deploy_utils import create_deploys_app_url_fixture, skip_if_not_chrome
4+
from utils.deploy_utils import (
5+
create_deploys_app_url_fixture,
6+
reruns,
7+
reruns_delay,
8+
skip_if_not_chrome,
9+
)
410

511
TIMEOUT = 2 * 60 * 1000
612

713
app_url = create_deploys_app_url_fixture("shiny_express_page_default")
814

915

1016
@skip_if_not_chrome
17+
@pytest.mark.flaky(reruns=reruns, reruns_delay=reruns_delay)
1118
def test_page_default(page: Page, app_url: str) -> None:
1219
page.goto(app_url)
1320

tests/playwright/deploys/express-page_fillable/test_deploys_express_page_fillable.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,18 @@
1+
import pytest
12
from controls import Card, OutputTextVerbatim
23
from playwright.sync_api import Page
3-
from utils.deploy_utils import create_deploys_app_url_fixture, skip_if_not_chrome
4+
from utils.deploy_utils import (
5+
create_deploys_app_url_fixture,
6+
reruns,
7+
reruns_delay,
8+
skip_if_not_chrome,
9+
)
410

511
app_url = create_deploys_app_url_fixture("express_page_fillable")
612

713

814
@skip_if_not_chrome
15+
@pytest.mark.flaky(reruns=reruns, reruns_delay=reruns_delay)
916
def test_express_page_fillable(page: Page, app_url: str) -> None:
1017
page.goto(app_url)
1118

tests/playwright/deploys/express-page_fluid/test_deploys_express_page_fluid.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,18 @@
1+
import pytest
12
from controls import Card, OutputTextVerbatim
23
from playwright.sync_api import Page
3-
from utils.deploy_utils import create_deploys_app_url_fixture, skip_if_not_chrome
4+
from utils.deploy_utils import (
5+
create_deploys_app_url_fixture,
6+
reruns,
7+
reruns_delay,
8+
skip_if_not_chrome,
9+
)
410

511
app_url = create_deploys_app_url_fixture("express_page_fluid")
612

713

814
@skip_if_not_chrome
15+
@pytest.mark.flaky(reruns=reruns, reruns_delay=reruns_delay)
916
def test_express_page_fluid(page: Page, app_url: str) -> None:
1017
page.goto(app_url)
1118

tests/playwright/deploys/express-page_sidebar/test_deploys_express_page_sidebar.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,18 @@
1+
import pytest
12
from controls import OutputTextVerbatim, Sidebar
23
from playwright.sync_api import Page
3-
from utils.deploy_utils import create_deploys_app_url_fixture, skip_if_not_chrome
4+
from utils.deploy_utils import (
5+
create_deploys_app_url_fixture,
6+
reruns,
7+
reruns_delay,
8+
skip_if_not_chrome,
9+
)
410

511
app_url = create_deploys_app_url_fixture("express_page_sidebar")
612

713

814
@skip_if_not_chrome
15+
@pytest.mark.flaky(reruns=reruns, reruns_delay=reruns_delay)
916
def test_express_page_sidebar(page: Page, app_url: str) -> None:
1017
page.goto(app_url)
1118

tests/playwright/deploys/plotly/test_plotly_app.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,18 @@
1+
import pytest
12
from playwright.sync_api import Page, expect
2-
from utils.deploy_utils import create_deploys_app_url_fixture, skip_if_not_chrome
3+
from utils.deploy_utils import (
4+
create_deploys_app_url_fixture,
5+
reruns,
6+
reruns_delay,
7+
skip_if_not_chrome,
8+
)
39

410
TIMEOUT = 2 * 60 * 1000
511
app_url = create_deploys_app_url_fixture("example_deploy_app_A")
612

713

814
@skip_if_not_chrome
15+
@pytest.mark.flaky(reruns=reruns, reruns_delay=reruns_delay)
916
def test_deploys(page: Page, app_url: str) -> None:
1017
page.goto(app_url)
1118

tests/playwright/deploys/shiny-client-console-error/test_shiny_client_error.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,17 @@
1+
import pytest
12
from playwright.sync_api import Page, expect
2-
from utils.deploy_utils import create_deploys_app_url_fixture, skip_if_not_chrome
3+
from utils.deploy_utils import (
4+
create_deploys_app_url_fixture,
5+
reruns,
6+
reruns_delay,
7+
skip_if_not_chrome,
8+
)
39

410
app_url = create_deploys_app_url_fixture("shiny_client_console_error")
511

612

713
@skip_if_not_chrome
14+
@pytest.mark.flaky(reruns=reruns, reruns_delay=reruns_delay)
815
def test_shiny_client_console_error(page: Page, app_url: str) -> None:
916
page.goto(app_url)
1017

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
# pyright:basic
2+
import time
3+
4+
import numpy as np
5+
import seaborn as sns
6+
7+
from shiny import App, module, reactive, render, ui
8+
9+
10+
# -- Reusable card module --
11+
@module.ui
12+
def card_ui(spinner_type, spinner_color, spinner_size):
13+
return ui.card(
14+
ui.busy_indicators.options(
15+
spinner_type=spinner_type,
16+
spinner_color=spinner_color,
17+
spinner_size=spinner_size,
18+
),
19+
ui.card_header("Spinner: " + spinner_type),
20+
ui.output_plot("plot"),
21+
)
22+
23+
24+
@module.server
25+
def card_server(input, output, session, rerender):
26+
@render.plot
27+
def plot():
28+
rerender()
29+
time.sleep(0.5)
30+
sns.lineplot(x=np.arange(100), y=np.random.randn(100))
31+
32+
33+
# -- Main app --
34+
app_ui = ui.page_fillable(
35+
ui.busy_indicators.options(
36+
pulse_background="linear-gradient(45deg, blue, red)",
37+
pulse_height="100px",
38+
pulse_speed="4s",
39+
),
40+
# ui.busy_indicators.use(spinners=False, pulse=True),
41+
ui.input_radio_buttons(
42+
"busy_indicator_type",
43+
"Choose the indicator type",
44+
["spinners", "pulse"],
45+
inline=True,
46+
),
47+
ui.input_task_button("rerender", "Re-render"),
48+
ui.output_text_verbatim("counter", placeholder=True),
49+
ui.layout_columns(
50+
card_ui("ring", "ring", "red", "10px"),
51+
card_ui("bars", "bars", "green", "20px"),
52+
card_ui("dots", "dots", "blue", "30px"),
53+
card_ui("pulse", "pulse", "olive", "50px"),
54+
col_widths=6,
55+
),
56+
ui.output_ui("indicator_types_ui"),
57+
)
58+
59+
60+
def server(input, output, session):
61+
62+
@reactive.calc
63+
@reactive.event(input.rerender, ignore_none=False)
64+
def rerender():
65+
return input.rerender()
66+
67+
card_server("ring", rerender=rerender)
68+
card_server("bars", rerender=rerender)
69+
card_server("dots", rerender=rerender)
70+
card_server("pulse", rerender=rerender)
71+
72+
@render.ui
73+
def indicator_types_ui():
74+
selected_busy_indicator_type = input.busy_indicator_type()
75+
return ui.busy_indicators.use(
76+
spinners=(selected_busy_indicator_type == "spinners"),
77+
pulse=(selected_busy_indicator_type != "spinners"),
78+
)
79+
80+
@render.text
81+
def counter():
82+
return str(rerender())
83+
84+
85+
app = App(app_ui, server)

0 commit comments

Comments
 (0)