From 20730cf55fdf0a4adf40b26e6f21cd954cf93e0d Mon Sep 17 00:00:00 2001 From: Garrick Aden-Buie Date: Fri, 12 Dec 2025 12:01:43 -0500 Subject: [PATCH 1/2] feat(pkg-py): Bring `cleanup` to Python implementation --- pkg-py/src/querychat/_querychat.py | 24 +++++++++++++++++++++++ pkg-py/src/querychat/_querychat_module.py | 8 ++++++++ 2 files changed, 32 insertions(+) diff --git a/pkg-py/src/querychat/_querychat.py b/pkg-py/src/querychat/_querychat.py index 1ab03f53..010cd748 100644 --- a/pkg-py/src/querychat/_querychat.py +++ b/pkg-py/src/querychat/_querychat.py @@ -36,6 +36,7 @@ def __init__( categorical_threshold: int = 20, extra_instructions: Optional[str | Path] = None, prompt_template: Optional[str | Path] = None, + cleanup: Optional[bool] = None, ): self._data_source = normalize_data_source(data_source, table_name) @@ -57,6 +58,11 @@ def __init__( prompt_template=prompt_template, ) + # By default, only close the connection automatically if we're in a Shiny app session + if cleanup is None: + cleanup = get_current_session() is not None + self._cleanup = cleanup + # Fork and empty chat now so the per-session forks are fast client = as_querychat_client(client) self._client = copy.deepcopy(client) @@ -345,6 +351,10 @@ class QueryChat(QueryChatBase): `data_source.get_schema()` - `{{data_description}}`: The optional data description provided - `{{extra_instructions}}`: Any additional instructions provided + cleanup + Whether or not to automatically run `data_source.cleanup()` when the + Shiny session/app stops. By default, cleanup only occurs if the + `QueryChat` instance is created within a Shiny session. """ @@ -421,6 +431,7 @@ def title(): greeting=self.greeting, client=self._client, enable_bookmarking=enable_bookmarking, + cleanup=self._cleanup, ) @@ -514,6 +525,10 @@ def data_table(): `data_source.get_schema()` - `{{data_description}}`: The optional data description provided - `{{extra_instructions}}`: Any additional instructions provided + cleanup + Whether or not to automatically run `data_source.cleanup()` when the + Shiny session/app stops. By default, cleanup only occurs if the + `QueryChat` instance is created within a Shiny session. """ @@ -530,6 +545,7 @@ def __init__( extra_instructions: Optional[str | Path] = None, prompt_template: Optional[str | Path] = None, enable_bookmarking: Literal["auto", True, False] = "auto", + cleanup: Optional[bool] = None, ): # Sanity check: Express should always have a (stub/real) session session = get_current_session() @@ -563,12 +579,20 @@ def __init__( else: enable = enable_bookmarking + if isinstance(session, ExpressStubSession): + cleanup = False + elif cleanup is None: + cleanup = True + + self._cleanup = cleanup + self._vals = mod_server( self.id, data_source=self._data_source, greeting=self.greeting, client=self._client, enable_bookmarking=enable, + cleanup=cleanup, ) def df(self) -> pd.DataFrame: diff --git a/pkg-py/src/querychat/_querychat_module.py b/pkg-py/src/querychat/_querychat_module.py index 26402584..75c40052 100644 --- a/pkg-py/src/querychat/_querychat_module.py +++ b/pkg-py/src/querychat/_querychat_module.py @@ -93,6 +93,7 @@ def mod_server( greeting: str | None, client: chatlas.Chat, enable_bookmarking: bool, + cleanup: bool = False, ): # Reactive values to store state sql = ReactiveStringOrNone(None) @@ -187,6 +188,13 @@ def _on_restore(x: RestoreState) -> None: if "querychat_has_greeted" in vals: has_greeted.set(vals["querychat_has_greeted"]) + if cleanup: + # Clean up the data source when the session ends + + @session.on_ended + def _cleanup() -> None: + data_source.cleanup() + return ServerValues(df=filtered_df, sql=sql, title=title, client=chat) From 255b49ed327a6d2ce1ecc00606be75ec8a85078c Mon Sep 17 00:00:00 2001 From: Garrick Aden-Buie Date: Fri, 12 Dec 2025 12:03:06 -0500 Subject: [PATCH 2/2] chore: Add changelog item --- pkg-py/CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pkg-py/CHANGELOG.md b/pkg-py/CHANGELOG.md index 901f47ac..ac3b0ee0 100644 --- a/pkg-py/CHANGELOG.md +++ b/pkg-py/CHANGELOG.md @@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [UNRELEASED] +### Improvements + +* If a `QueryChat` instance is created inside a Shiny app context, the data source is automatically cleaned up when the app session ends. This can be configured manually via the `cleanup` parameter of the `QueryChat` constructor. (#164) ## [0.3.0] - 2025-12-10