Skip to content

chore(uvicorn): Remove uv source of uvicorn PR #1950

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Apr 1, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -134,9 +134,6 @@ doc = [
"griffe>=1.3.2",
]

[tool.uv.sources]
# https://github.com/encode/uvicorn/pull/2602
uvicorn = { git = "https://github.com/schloerke/uvicorn", branch = "reload-exclude-abs-path" }

[project.urls]
Homepage = "https://github.com/posit-dev/py-shiny"
Expand Down
26 changes: 26 additions & 0 deletions shiny/_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,32 @@ def run_app(

reload_args: ReloadArgs = {}
if reload:
if shiny_bookmarks_folder_name in reload_excludes:
# Related: https://github.com/posit-dev/py-shiny/pull/1950
#
# Temp hack to work around uvicorn
# https://github.com/encode/uvicorn/pull/2602 which will incorrectly reload
# an app if any matching files in `RELOAD_INCLUDES_DEFAULT` (e.g. `*.png`)
# are uploaded within `shiny_bookmarks` (an excluded relative directory).
#
# By extending `reload_excludes` to ignore everything under the bookmarks folder, we
# can prevent the unexpected reload from happening for the root session. File
# matches are performed via `pathlib.PurePath.match`, which is a right-match and
# only supports `*` glob.
#
# Ignore up to five modules deep. This should cover most cases.
#
# Note: file uploads are always in the root session, so they are always
# stored in the root bookmark dir of `shiny_bookmarks_folder_name / *`.
reload_excludes = [
*reload_excludes,
str(Path(shiny_bookmarks_folder_name) / "*"),
str(Path(shiny_bookmarks_folder_name) / "*" / "*"),
str(Path(shiny_bookmarks_folder_name) / "*" / "*" / "*"),
str(Path(shiny_bookmarks_folder_name) / "*" / "*" / "*" / "*"),
str(Path(shiny_bookmarks_folder_name) / "*" / "*" / "*" / "*" / "*"),
]

reload_args = {
"reload": reload,
# Adding `reload_includes` param while `reload=False` produces an warning
Expand Down
2 changes: 0 additions & 2 deletions shiny/api-examples/notification_show/app-core.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ def server(input: Inputs, output: Outputs, session: Session):
@reactive.effect
@reactive.event(input.show)
def _():
nonlocal ids
nonlocal n
# Save the ID for removal later
id = ui.notification_show("Message " + str(n), duration=None)
Expand All @@ -24,7 +23,6 @@ def _():
@reactive.effect
@reactive.event(input.remove)
def _():
nonlocal ids
if ids:
ui.notification_remove(ids.pop())

Expand Down
2 changes: 0 additions & 2 deletions shiny/api-examples/notification_show/app-express.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
@reactive.effect
@reactive.event(input.show)
def _():
global ids
global n
# Save the ID for removal later
id = ui.notification_show("Message " + str(n), duration=None)
Expand All @@ -22,6 +21,5 @@ def _():
@reactive.effect
@reactive.event(input.remove)
def _():
global ids
if ids:
ui.notification_remove(ids.pop())
3 changes: 2 additions & 1 deletion shiny/bookmark/_bookmark.py
Original file line number Diff line number Diff line change
Expand Up @@ -610,7 +610,8 @@ async def _scoped_on_bookmark(self, root_state: BookmarkState) -> None:
)

# Make subdir for scope
# TODO: Barret; Is this for uploaded files?!?
#
# Folder only used by author callbacks. File uploads are handled by root session
if root_state.dir is not None:
scope_subpath = self._ns
scoped_state.dir = Path(root_state.dir) / scope_subpath
Expand Down
12 changes: 0 additions & 12 deletions tests/pytest/test_reactives.py
Original file line number Diff line number Diff line change
Expand Up @@ -235,15 +235,13 @@ async def test_async_sequential():
async def react_chain(n: int):
@calc()
async def r():
nonlocal exec_order
exec_order.append(f"r{n}-1")
await asyncio.sleep(0)
exec_order.append(f"r{n}-2")
return x() + 10

@effect()
async def _():
nonlocal exec_order
exec_order.append(f"o{n}-1")
await asyncio.sleep(0)
exec_order.append(f"o{n}-2")
Expand Down Expand Up @@ -402,19 +400,16 @@ async def test_effect_priority():

@effect(priority=1)
def o1():
nonlocal results
v()
results.append(1)

@effect(priority=2)
def o2():
nonlocal results
v()
results.append(2)

@effect(priority=1)
def o3():
nonlocal results
v()
results.append(3)

Expand All @@ -425,7 +420,6 @@ def o3():
# invalidate others by changing v).
@effect(priority=2)
def o4():
nonlocal results
v()
results.append(4)

Expand Down Expand Up @@ -453,19 +447,16 @@ async def test_async_effect_priority():

@effect(priority=1)
async def o1():
nonlocal results
v()
results.append(1)

@effect(priority=2)
async def o2():
nonlocal results
v()
results.append(2)

@effect(priority=1)
async def o3():
nonlocal results
v()
results.append(3)

Expand All @@ -476,7 +467,6 @@ async def o3():
# invalidate others by changing v).
@effect(priority=2)
async def o4():
nonlocal results
v()
results.append(4)

Expand Down Expand Up @@ -506,7 +496,6 @@ async def test_effect_destroy():

@effect()
def o1():
nonlocal results
v()
results.append(1)

Expand All @@ -524,7 +513,6 @@ def o1():

@effect()
def o2():
nonlocal results
v()
results.append(1)

Expand Down
Loading