diff --git a/CHANGELOG.md b/CHANGELOG.md index 19fb40517..d12eb15c2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -60,7 +60,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * `shiny create` now uses the template `id` rather than the directory name as the default directory. (#1666) -* `ui.Theme()` now works correctly on Windows when the theme requires Sass compilation. (thanks @yuuuxt, #1684) +* `ui.Theme()` now works correctly on Windows when the theme requires Sass compilation. (Thanks, @yuuuxt!) (#1684) * Fixed multiple input controllers (`InputSlider`, `InputDate`, `InputDateRange`, `InputCheckbox`, and `InputCheckboxGroup`) in `shiny.playwright.controller` to check the `width` property within the `style` attribute. (#1691, #1696, #1702) @@ -76,6 +76,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * Fixed output controller `OutputDataFrame` in `shiny.playwright.controller` to correctly assert the number of rows in `.expect_nrow()` as the total number of virtual rows, not the number of currently displaying rows. (#1719) +* Fixed issue where `@render.download` did not respect the module namespacing. (Thanks, @nsiicm0) (#1732) ## [1.1.0] - 2024-09-03 diff --git a/shiny/render/_render.py b/shiny/render/_render.py index 0486524a2..feda9b03f 100644 --- a/shiny/render/_render.py +++ b/shiny/render/_render.py @@ -688,7 +688,8 @@ def url() -> str: from urllib.parse import quote session = require_active_session(None) - return f"session/{quote(session.id)}/download/{quote(self.output_id)}?w=" + # All download urls must be fully namespaced + return f"session/{quote(session.id)}/download/{quote(session.ns(self.output_id))}?w=" # Unlike most value functions, this one's name is `url`. But we want to get the # name from the user-supplied function. @@ -705,7 +706,9 @@ def url() -> str: # have been started. session = get_current_session() if session is not None and not session.is_stub_session(): - session._downloads[self.output_id] = DownloadInfo( + # All download objects are stored in the root session. + # They must be fully namespaced + session._downloads[session.ns(self.output_id)] = DownloadInfo( filename=self.filename, content_type=self.media_type, handler=fn,