Skip to content

Commit 2e644a6

Browse files
committed
Use magic comment
1 parent 552c5a8 commit 2e644a6

File tree

4 files changed

+13
-41
lines changed

4 files changed

+13
-41
lines changed

shiny/express/__init__.py

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -37,16 +37,6 @@
3737
session: _Session
3838

3939

40-
allow_express_in_core = False
41-
"""
42-
Control whether Shiny Express imports are allowed in Shiny Core apps.
43-
44-
Normally Shiny Express imports are not allowed in Shiny Core apps because the mixing of
45-
the two could lead to confusion. However, there are special cases where we do allow
46-
this, like when using Shiny Express syntax in a Quarto Dashboard.
47-
"""
48-
49-
5040
# Note that users should use `from shiny.express import input` instead of `from shiny
5141
# import express` and acces via `express.input`. The former provides a static value for
5242
# `input`, but the latter is dynamic -- every time `express.input` is accessed, it

shiny/express/_is_express.py

Lines changed: 10 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -44,24 +44,29 @@ def is_express_app(app: str, app_dir: str | None) -> bool:
4444
# Read the file, parse it, and look for any imports of shiny.express.
4545
with open(app_path) as f:
4646
content = f.read()
47+
48+
# Check for magic comment in the first 1000 characters
49+
for line in content[:1000].splitlines():
50+
line = line.rstrip()
51+
if line == "# shiny_mode: express":
52+
return True
53+
elif line == "# shiny_mode: core":
54+
return False
55+
4756
tree = ast.parse(content, app_path)
4857
detector = DetectShinyExpressVisitor()
4958
detector.visit(tree)
5059

5160
except Exception:
5261
return False
5362

54-
return detector.is_express_app()
63+
return detector.found_shiny_express_import
5564

5665

5766
class DetectShinyExpressVisitor(ast.NodeVisitor):
5867
def __init__(self):
5968
super().__init__()
6069
self.found_shiny_express_import = False
61-
self.found_shiny_express_in_core = False
62-
63-
def is_express_app(self) -> bool:
64-
return self.found_shiny_express_import and not self.found_shiny_express_in_core
6570

6671
def visit_Import(self, node: ast.Import) -> None:
6772
if any(alias.name == "shiny.express" for alias in node.names):
@@ -75,20 +80,6 @@ def visit_ImportFrom(self, node: ast.ImportFrom) -> None:
7580
):
7681
self.found_shiny_express_import = True
7782

78-
def visit_Assign(self, node: ast.Assign) -> None:
79-
for target in node.targets:
80-
# Look for the statement `shiny.express.allow_express_in_core = True` at the
81-
# top level.
82-
if (
83-
isinstance(target, ast.Attribute)
84-
and isinstance(target.value, ast.Attribute)
85-
and target.value.attr == "express"
86-
and isinstance(target.value.value, ast.Name)
87-
and target.value.value.id == "shiny"
88-
and target.attr == "allow_express_in_core"
89-
):
90-
self.found_shiny_express_in_core = True
91-
9283
# Visit top-level nodes.
9384
def visit_Module(self, node: ast.Module) -> None:
9485
super().generic_visit(node)

shiny/express/_run.py

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -144,15 +144,8 @@ def set_result(x: object):
144144
get_top_level_recall_context_manager().__exit__(None, None, None)
145145

146146
# If we're running as an Express app but there's also a top-level item named app
147-
# which is a shiny.App object, the user probably made a mistake. The exception
148-
# is if allow_express_in_core is True, which happens with Quarto Dashboards.
149-
from . import allow_express_in_core
150-
151-
if (
152-
not allow_express_in_core
153-
and "app" in var_context
154-
and isinstance(var_context["app"], App)
155-
):
147+
# which is a shiny.App object, the user probably made a mistake.
148+
if "app" in var_context and isinstance(var_context["app"], App):
156149
raise RuntimeError(
157150
"This looks like a Shiny Express app because it imports shiny.express, "
158151
"but it also looks like a Shiny Core app because it has a variable named "

shiny/quarto.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,14 +68,12 @@ def convert_code_cells_to_app_py(json_file: str | Path, app_file: str | Path) ->
6868
)
6969

7070
app_content = f"""# This file generated by Quarto; do not edit by hand.
71+
# shiny_mode: core
7172
7273
from __future__ import annotations
7374
7475
from pathlib import Path
7576
from shiny import App, Inputs, Outputs, Session, ui
76-
import shiny.express
77-
78-
shiny.express.allow_express_in_core = True
7977
8078
{"".join(global_code_cell_texts)}
8179

0 commit comments

Comments
 (0)