@@ -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
5766class 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 )
0 commit comments