Skip to content

Commit 1155868

Browse files
committed
Merge branch 'main' into machow-feat-narwhals
* main: CI(deploy): Add more installation configs to surface failure cause (posit-dev#1658) `Chat.messages()` no longer trims messages by default (posit-dev#1657) tests(controllers): Split _controls.py into separate files (posit-dev#1652) Chat tweaks (posit-dev#1607) docs: Add modal_show/remove examples (posit-dev#1628) Delay sending of chat UI messages until reactive graph is flushed (posit-dev#1593) ci(remove future behavior warning): Set the `asyncio_default_fixture_loop_scope` to `fixture` (posit-dev#1655) bug: Verify mypy can run on CI (posit-dev#1650) Fix CI install failures on Windows (posit-dev#1651) Quartodoc 0.7.6 (posit-dev#1636) Allow `@chat.transform_assistant_response` function to return `None` (posit-dev#1641) feat: Support templates with `_template.json` metadata (posit-dev#1631) Fix KeyError when serving static files (posit-dev#1648) tests(navsets): Add navsets kitchensink tests (posit-dev#1602) Change default claude model to 3.5 sonnet
2 parents db83bc7 + 24013f4 commit 1155868

File tree

172 files changed

+9232
-8044
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

172 files changed

+9232
-8044
lines changed

.github/workflows/deploy-tests.yaml

Lines changed: 84 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,63 @@ jobs:
99
playwright-deploys:
1010
# Only allow one `playwright-deploys` job to run at a time. (Independent of branch / PR)
1111
# Only one is allowed to run at a time because it is deploying to the same server location.
12-
concurrency: playwright-deploys
12+
concurrency: playwright-deploys-${{ matrix.config.name }}
1313
runs-on: ${{ matrix.os }}
14+
name: ${{ matrix.config.name }}
1415
strategy:
1516
matrix:
1617
# Matches deploy server python version
1718
python-version: ["3.10"]
1819
os: [ubuntu-latest]
20+
config:
21+
# Released server, shiny, and rsconnect
22+
- name: "pypi-shiny-rsconnect-connect"
23+
released_connect_server: true
24+
pypi_shiny: true
25+
pypi_rsconnect: true
26+
base_test_dir: "./tests/playwright/deploys/express-page_sidebar"
27+
app_name: "pypi-shiny-rsconnect"
28+
test_shinyappsio: false
29+
30+
# Released shiny and rsconnect
31+
# Dev server
32+
- name: "pypi-shiny-rsconnect-dogfood"
33+
released_connect_server: false
34+
pypi_shiny: true
35+
pypi_rsconnect: true
36+
base_test_dir: "./tests/playwright/deploys/express-page_sidebar"
37+
app_name: "pypi-shiny-rsconnect"
38+
test_shinyappsio: false
39+
40+
# Released shiny
41+
# Dogfood server and rsconnect
42+
- name: "pypi-shiny-dev-rsconnect-dogfood"
43+
released_connect_server: false
44+
pypi_shiny: true
45+
pypi_rsconnect: false
46+
base_test_dir: "./tests/playwright/deploys/express-page_sidebar"
47+
app_name: "pypi-shiny-dev-rsconnect"
48+
test_shinyappsio: false
49+
50+
# GitHub shiny v1.0.0 - test if github packages can be installed
51+
# Dogfood server and rsconnect
52+
- name: "github-shiny-dev-rsconnect-dogfood"
53+
released_connect_server: false
54+
github_shiny: true
55+
pypi_shiny: false
56+
pypi_rsconnect: false
57+
base_test_dir: "./tests/playwright/deploys/express-page_sidebar"
58+
app_name: "pypi-shiny-dev-rsconnect"
59+
test_shinyappsio: false
60+
61+
# Dev server, shiny, and rsconnect
62+
- name: "dev-shiny-rsconnect-dogfood"
63+
released_connect_server: false
64+
pypi_shiny: false
65+
pypi_rsconnect: false
66+
base_test_dir: "./tests/playwright/deploys"
67+
test_shinyappsio: true
68+
1969
fail-fast: false
2070

2171
steps:
@@ -27,7 +77,24 @@ jobs:
2777
with:
2878
python-version: ${{ matrix.python-version }}
2979

30-
- name: Install rsconnect
80+
- name: Install pypi shiny and htmltools (uninstall GitHub versions)
81+
if: ${{ matrix.config.pypi_shiny }}
82+
run: |
83+
uv pip uninstall shiny htmltools
84+
uv pip install shiny htmltools
85+
86+
- name: Install GitHub shiny@v1.0.0 and htmltools@v0.5.3 (uninstall PyPI versions)
87+
if: ${{ matrix.config.github_shiny }}
88+
run: |
89+
uv pip uninstall shiny htmltools
90+
uv pip install "htmltools @ git+https://github.com/posit-dev/py-htmltools.git@v0.5.3" "shiny @ git+https://github.com/posit-dev/py-shiny.git@v1.0.0"
91+
92+
- name: Install rsconnect (PyPI)
93+
if: ${{ matrix.config.pypi_rsconnect }}
94+
run: |
95+
uv pip install rsconnect
96+
- name: Install rsconnect (GitHub)
97+
if: ${{ ! matrix.config.pypi_rsconnect }}
3198
run: |
3299
make ci-install-rsconnect
33100
@@ -36,25 +103,27 @@ jobs:
36103
env:
37104
DEPLOY_APPS: "false"
38105
run: |
39-
make playwright-deploys SUB_FILE=". -vv"
106+
make playwright-deploys TEST_FILE="${{ matrix.config.base_test_dir }} -vv"
40107
41108
- name: Deploy apps and run tests (on `push` or `deploy**` branches)
42109
env:
43110
DEPLOY_APPS: "true"
44-
DEPLOY_CONNECT_SERVER_URL: "https://rsc.radixu.com/"
45-
DEPLOY_CONNECT_SERVER_API_KEY: "${{ secrets.DEPLOY_CONNECT_SERVER_API_KEY }}"
46-
DEPLOY_SHINYAPPS_NAME: "${{ secrets.DEPLOY_SHINYAPPS_NAME }}"
47-
DEPLOY_SHINYAPPS_TOKEN: "${{ secrets.DEPLOY_SHINYAPPS_TOKEN }}"
48-
DEPLOY_SHINYAPPS_SECRET: "${{ secrets.DEPLOY_SHINYAPPS_SECRET }}"
111+
DEPLOY_CONNECT_SERVER_URL: "${{ (matrix.config.released_connect_server && 'https://connect.posit.it/') || 'https://rsc.radixu.com/' }}"
112+
DEPLOY_CONNECT_SERVER_API_KEY: "${{ (matrix.config.released_connect_server && secrets.DEPLOY_CONNECT_POSIT_SERVER_API_KEY) || secrets.DEPLOY_CONNECT_SERVER_API_KEY }}"
113+
DEPLOY_SHINYAPPS_NAME: "${{ matrix.config.test_shinyappsio && matrix.config.shinyapps_name }}"
114+
DEPLOY_SHINYAPPS_TOKEN: "${{ matrix.config.test_shinyappsio && matrix.config.shinyapps_token }}"
115+
DEPLOY_SHINYAPPS_SECRET: "${{ matrix.config.test_shinyappsio && matrix.config.shinyapps_secret }}"
116+
EXPRESS_PAGE_SIDEBAR_NAME: "${{ matrix.config.app_name }}"
117+
DEPLOY_GITHUB_REQUIREMENTS_TXT: "${{ !matrix.config.pypi_shiny }}"
49118
timeout-minutes: 30
50119
# Given we are waiting for external servers to finish,
51120
# we can have many local processes waiting for deployment to finish
52121
run: |
53-
make playwright-deploys SUB_FILE=". -vv --numprocesses 12"
122+
make playwright-deploys TEST_FILE="${{ matrix.config.base_test_dir }} -vv --numprocesses 12"
54123
55-
- uses: actions/upload-artifact@v4
56-
if: failure()
57-
with:
58-
name: "playright-deploys-${{ matrix.os }}-${{ matrix.python-version }}-results"
59-
path: test-results/
60-
retention-days: 5
124+
# - uses: actions/upload-artifact@v4
125+
# if: failure()
126+
# with:
127+
# name: "playright-deploys-${{ matrix.os }}-${{ matrix.python-version }}-results"
128+
# path: test-results/
129+
# retention-days: 5

.github/workflows/pytest.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,11 @@ jobs:
5858
run: |
5959
make check-format
6060
61+
- name: Verify code can run with mypy (not Windows)
62+
if: steps.install.outcome == 'success' && (success() || failure()) && matrix.os != 'windows-latest'
63+
run: |
64+
make ci-check-mypy-can-run
65+
6166
pypi:
6267
name: "Deploy to PyPI"
6368
runs-on: ubuntu-latest

CHANGELOG.md

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1313

1414
* `shiny create` now supports a succinct format for specifying the GitHub repository via the `--github` flag, e.g. `--github posit-dev/py-shiny-templates`. You can now also use `--github` and `--template` together, in which case `--github` should point to a repository containing a directory matching the name provided in `--template`. (#1623)
1515

16+
* `shiny create` now identifies templates in external repositories using a `_template.json` metadata file. This file should contain at an `"id"` and optionally a `"title"` and `"description"`. When `shiny create` is called with the `--github` flag but without a `--template` flag, it will offer a menu listing all available templates in the repository. (#1631)
17+
1618
### Other changes
1719

20+
* A few changes for `ui.Chat()`, including:
21+
* The `.messages()` method no longer trims messages by default (i.e., the default value of `token_limits` is now `None` instead of the overly generic and conservative value of `(4096, 1000)`). See the new generative AI in production templates (via `shiny create`) for examples of setting `token_limits` based on the model being used. (#1657)
22+
* User input that contains markdown now renders the expected HTML. (#1607)
23+
* Busy indication is now visible/apparent during the entire lifecycle of response generation. (#1607)
24+
1825
### Bug fixes
1926

20-
* A handful of fixes for `ui.Chat()`, including:
27+
* A few fixes for `ui.Chat()`, including:
2128
* A fix for use inside Shiny modules. (#1582)
2229
* `.messages(format="google")` now returns the correct role. (#1622)
30+
* `ui.Chat(messages)` are no longer dropped when dynamically rendered. (#1593)
31+
* `transform_assistant_response` can now return `None` and correctly handles change of content on the last chunk. (#1641)
2332

2433
* An empty `ui.input_date()` value no longer crashes Shiny. (#1528)
2534

@@ -33,6 +42,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
3342

3443
* Some copies of Windows 10 have registry entries mapping .js files to content type "text/plain", which was causing all sorts of problems for browsers. (#1624)
3544

45+
* Added missing support for `express.ui.navset_card_pill(placement:)`. (#1602)
46+
47+
* Added `.expect_sidebar()` and `.expect_title()` methods for `NavsetCardTab`, `NavsetCardPill`, `NavsetCardUnderline`, and `NavsetBar`. (#1602)
48+
49+
* Added `.expect_placement()` method for `NavsetCardPill` and `NavsetCardUnderline`. (#1602)
50+
3651
### Deprecations
3752

3853
## [1.0.0] - 2024-07-18

Makefile

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ clean-build: FORCE
3939
rm -fr dist/
4040
rm -fr .eggs/
4141
find . -name '*.egg-info' -exec rm -fr {} +
42-
find . -name '*.egg' -exec rm -f {} +
42+
find . -name '*.egg' -exec rm -rf {} +
4343

4444
# Remove Python file artifacts
4545
clean-pyc: FORCE
@@ -173,6 +173,8 @@ playwright-shiny: FORCE
173173

174174
# end-to-end tests on deployed apps with playwright; (SUB_FILE="" within tests/playwright/deploys/)
175175
playwright-deploys: FORCE
176+
$(MAKE) playwright PYTEST_BROWSERS="$(PYTEST_DEPLOYS_BROWSERS)" TEST_FILE="$(TEST_FILE)"
177+
playwright-deploys-legacy: FORCE
176178
$(MAKE) playwright TEST_FILE="tests/playwright/deploys/$(SUB_FILE)" PYTEST_BROWSERS="$(PYTEST_DEPLOYS_BROWSERS)"
177179

178180
# end-to-end tests on all py-shiny examples with playwright; (SUB_FILE="" within tests/playwright/examples/)
@@ -225,6 +227,14 @@ ci-install-rsconnect: FORCE
225227
uv pip install "rsconnect-python @ git+https://github.com/rstudio/rsconnect-python.git"
226228

227229

230+
# This is just to check if mypy can run for other users.
231+
# Not added to `make check` or `make check-fix` as all lint errors are supporessed (as we use pyright).
232+
ci-check-mypy-can-run: FORCE
233+
@echo "-------- Checking types with mypy -----------"
234+
uv pip install mypy
235+
mypy shiny
236+
237+
228238
# ## If caching is ever used, we could run:
229239
# install-deps: FORCE ## install latest dependencies
230240
# pip install --editable ".[dev,test]" --upgrade --upgrade-strategy eager

docs/_quartodoc-testing.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,6 @@ quartodoc:
4848
- title: Navigation (tab) panels
4949
desc: Methods for interacting with Shiny app UI content controller.
5050
contents:
51-
- playwright.controller.NavPanel
5251
- playwright.controller.NavsetBar
5352
- playwright.controller.NavsetCardPill
5453
- playwright.controller.NavsetCardTab
@@ -58,6 +57,7 @@ quartodoc:
5857
- playwright.controller.NavsetPillList
5958
- playwright.controller.NavsetTab
6059
- playwright.controller.NavsetUnderline
60+
- playwright.controller.NavPanel
6161
- title: Upload and download
6262
desc: Methods for interacting with Shiny app uploading and downloading controller.
6363
contents:

docs/_renderer.py

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,17 @@
99
from typing import Literal, Optional, TypedDict, Union
1010

1111
import quartodoc.ast as qast
12-
from griffe import dataclasses as dc
13-
from griffe import expressions as exp
14-
from griffe.docstrings import dataclasses as ds
12+
from griffe import (
13+
Alias,
14+
DocstringAttribute,
15+
DocstringParameter,
16+
DocstringSectionParameters,
17+
DocstringSectionText,
18+
Expr,
19+
ExprName,
20+
Function,
21+
Object,
22+
)
1523
from plum import dispatch
1624
from quartodoc import MdRenderer
1725
from quartodoc.pandoc.blocks import DefinitionList
@@ -42,7 +50,7 @@ def render(self, el: qast.DocstringSectionSeeAlso):
4250
return prefix_bare_functions_with_func(el.value)
4351

4452
@dispatch
45-
def render(self, el: Union[dc.Object, dc.Alias]):
53+
def render(self, el: Union[Object, Alias]):
4654
# If `el` is a protocol class that only has a `__call__` method,
4755
# then we want to display information about the method, not the class.
4856
if len(el.members) == 1 and "__call__" in el.members.keys():
@@ -78,7 +86,7 @@ def render(self, el: Union[dc.Object, dc.Alias]):
7886
return converted
7987

8088
@dispatch
81-
def render(self, el: ds.DocstringSectionText):
89+
def render(self, el: DocstringSectionText):
8290
# functions like shiny.ui.tags.b have html in their docstrings, so
8391
# we escape them. Note that we are only escaping text sections, but
8492
# since these cover the top text of the docstring, it should solve
@@ -93,7 +101,7 @@ def render_annotation(self, el: str):
93101
# TODO-future; Can be removed once we use quartodoc 0.3.5
94102
# Related: https://github.com/machow/quartodoc/pull/205
95103
@dispatch
96-
def render(self, el: ds.DocstringAttribute):
104+
def render(self, el: DocstringAttribute):
97105
row = [
98106
sanitize(el.name),
99107
self.render_annotation(el.annotation),
@@ -106,23 +114,23 @@ def render_annotation(self, el: None):
106114
return ""
107115

108116
@dispatch
109-
def render_annotation(self, el: exp.Expr):
110-
# an expression is essentially a list[exp.ExprName | str]
117+
def render_annotation(self, el: Expr):
118+
# an expression is essentially a list[ExprName | str]
111119
# e.g. Optional[TagList]
112120
# -> [Name(source="Optional", ...), "[", Name(...), "]"]
113121

114122
return "".join(map(self.render_annotation, el))
115123

116124
@dispatch
117-
def render_annotation(self, el: exp.ExprName):
125+
def render_annotation(self, el: ExprName):
118126
# e.g. Name(source="Optional", full="typing.Optional")
119127
return f"[{el.name}](`{el.canonical_path}`)"
120128

121129
@dispatch
122130
# Overload of `quartodoc.renderers.md_renderer` to fix bug where the descriptions
123131
# are cut off and never display other places. Fixing by always displaying the
124132
# documentation.
125-
def summarize(self, obj: Union[dc.Object, dc.Alias]) -> str:
133+
def summarize(self, obj: Union[Object, Alias]) -> str:
126134
# get high-level description
127135
doc = obj.docstring
128136
if doc is None:
@@ -131,7 +139,7 @@ def summarize(self, obj: Union[dc.Object, dc.Alias]) -> str:
131139
docstring_parts = doc.parsed
132140

133141
if len(docstring_parts) and isinstance(
134-
docstring_parts[0], ds.DocstringSectionText
142+
docstring_parts[0], DocstringSectionText
135143
):
136144
description = docstring_parts[0].value
137145

@@ -164,7 +172,7 @@ def summarize(self, obj: Union[dc.Object, dc.Alias]) -> str:
164172

165173
# Consolidate the parameter type info into a single column
166174
@dispatch
167-
def render(self, el: ds.DocstringParameter):
175+
def render(self, el: DocstringParameter):
168176
param = f'<span class="parameter-name">{el.name}</span>'
169177
annotation = self.render_annotation(el.annotation)
170178
if annotation:
@@ -178,14 +186,14 @@ def render(self, el: ds.DocstringParameter):
178186
return (param, el.description)
179187

180188
@dispatch
181-
def render(self, el: ds.DocstringSectionParameters):
189+
def render(self, el: DocstringSectionParameters):
182190
rows = list(map(self.render, el.value))
183191
# rows is a list of tuples of (<parameter>, <description>)
184192

185193
return str(DefinitionList(rows))
186194

187195
@dispatch
188-
def signature(self, el: dc.Function, source: Optional[dc.Alias] = None):
196+
def signature(self, el: Function, source: Optional[Alias] = None):
189197
if el.name == "__call__":
190198
# Ex: experimental.ui._card.ImgContainer.__call__(self, *args: Tag) -> Tagifiable
191199
sig = super().signature(el, source)
@@ -302,7 +310,7 @@ def is_no_ex_decorator(x):
302310
# Don't throw for things that can't be decorated
303311
return
304312

305-
if not el.is_explicitely_exported:
313+
if not el.is_exported:
306314
# Don't require examples on "implicitly exported" functions
307315
# In practice, this covers methods of exported classes (class still needs ex)
308316
return

examples/chat/hello-providers/anthropic/app.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ async def _():
3535
messages = chat.messages(format="anthropic")
3636
# Create a response message stream
3737
response = await llm.messages.create(
38-
model="claude-3-opus-20240229",
38+
model="claude-3-5-sonnet-20240620",
3939
messages=messages,
4040
stream=True,
4141
max_tokens=1000,

examples/chat/playground/app.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
"openai": ["gpt-4o", "gpt-3.5-turbo"],
1717
"claude": [
1818
"claude-3-opus-20240229",
19-
"claude-3-sonnet-20240229",
19+
"claude-3-5-sonnet-20240620",
2020
"claude-3-haiku-20240307",
2121
],
2222
"google": ["gemini-1.5-pro-latest"],

js/.nvmrc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
v16
1+
v18

0 commit comments

Comments
 (0)