Skip to content

feat: Allow deferred data_source initialization#202

Merged
cpsievert merged 22 commits intomainfrom
deferred-datasource
Jan 23, 2026
Merged

feat: Allow deferred data_source initialization#202
cpsievert merged 22 commits intomainfrom
deferred-datasource

Conversation

@cpsievert
Copy link
Copy Markdown
Contributor

Summary

  • Allow data_source to be None at QueryChat initialization, deferring binding until server() is called
  • Add settable data_source property that rebuilds system prompt when changed
  • Add data_source parameter to Shiny server() method for the deferred pattern
  • Update all framework implementations (Shiny, Streamlit, Gradio, Dash) to support None data_source

Motivation

This enables Shiny Core applications where:

  • UI is defined in "global" scope
  • Database connections need to be created per-user in server scope
  • Credentials may depend on session-specific authentication
# Global scope - UI created before data source
qc = QueryChat(None, "users")

def app_ui(request):
    return ui.page_sidebar(qc.sidebar(), ...)

def server(input, output, session):
    # Data source provided in server scope
    qc_vals = qc.server(data_source=get_connection(session))

Test plan

  • Added unit tests for deferred initialization pattern
  • Added integration tests for full workflow
  • Verified backward compatibility with existing tests
  • All 247 tests pass

🤖 Generated with Claude Code

cpsievert and others added 9 commits January 23, 2026 10:37
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Stores table_name and init parameters for deferred system prompt building.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Normalizes the data source and rebuilds system prompt when set.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Methods that need data_source now raise RuntimeError with helpful message.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Allows deferred data source pattern where UI is created before data source
is available (e.g., in Shiny Core global scope).

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
QueryChatExpress requires data_source at init since it calls mod_server.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
These frameworks require data_source before app()/ui() since there's no
separate server() call like in Shiny.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Comment thread pkg-py/src/querychat/_shiny.py Outdated
Comment thread pkg-py/src/querychat/_shiny.py Outdated
Comment thread pkg-py/src/querychat/_shiny.py Outdated
Comment thread pkg-py/src/querychat/_shiny.py
- Add ibis.Table to server() data_source type hint
- Remove unnecessary comments in server() method
- Make QueryChatExpress data_source required (not optional)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add assert statements after _require_data_source() calls to help pyright
narrow types from DataSource | None to DataSource. Also capture local
variables for nested functions where type narrowing doesn't carry through.

feat(pkg-r): implement deferred data source pattern

Allow data_source to be NULL at initialization, deferring the actual
data source binding until $server() is called. This enables Shiny Core
apps where UI is in global scope but database connections need to be
created per-user in server scope.

Changes:
- data_source parameter accepts NULL in initialize()
- $data_source property is now settable
- $server() accepts optional data_source parameter
- Added _require_data_source checks to methods that need data
- Updated CHANGELOG.md and NEWS.md

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@cpsievert cpsievert changed the title feat(pkg-py): Allow deferred data_source initialization feat: Allow deferred data_source initialization Jan 23, 2026
Comment thread pkg-r/NEWS.md Outdated
Document the deferred data source pattern for per-user database
connections in Shiny Core applications.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Update _data_source type annotation to DataSource | None to match
QueryChatBase. Add assertions to methods that use _data_source.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Assert statements are used for type narrowing after _require_data_source()
which already handles runtime validation.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…pe narrowing

Replace assert statements with `# noqa: S101` by having `_require_data_source()`
return the validated DataSource. This provides cleaner type narrowing without
needing to suppress lint warnings.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add `data_source: None` overload to QueryChatExpress
- Use class variable to cache bookmarking settings between stub and real sessions
- Defer mod_server() call to real session (skip during stub session)
- Add _require_vals() helper for safe accessor access
- Update documentation for Express deferred pattern

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Update mod_server() to accept data_source: DataSource | None
- Handle None data_source during stub session (return placeholder ServerValues)
- Raise clear error if data_source is None during real session
- Simplify QueryChatExpress to always call mod_server() with self._data_source
- Remove _require_vals() helper, use self._vals directly

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

This comment was marked as resolved.

Comment thread pkg-py/docs/build.qmd Outdated
@cpsievert cpsievert merged commit 27c4cc5 into main Jan 23, 2026
18 checks passed
@cpsievert cpsievert deleted the deferred-datasource branch January 23, 2026 23:03
@github-actions github-actions Bot restored the deferred-datasource branch January 23, 2026 23:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants