diff --git a/shiny/express/_run.py b/shiny/express/_run.py index cc52d72e4..ac5f20ea7 100644 --- a/shiny/express/_run.py +++ b/shiny/express/_run.py @@ -90,6 +90,7 @@ def set_result(x: object): var_context: dict[str, object] = { "__file__": file_path, display_decorator_func_name: _display_decorator_function_def, + "input": InputNotImportedShim(), } # Execute each top-level node in the AST @@ -150,3 +151,16 @@ def reset_top_level_recall_context_manager() -> None: def get_top_level_recall_context_manager() -> RecallContextManager[Tag]: return _top_level_recall_context_manager + + +class InputNotImportedShim: + # This is a dummy class that is used to provide a helpful error message when the + # user tries to access `input.x` but forgot to import `input`. If they do that, then + # it would get the builtin `input` function, and print an unhelpful error message: + # RuntimeError: 'builtin_function_or_method' object has no attribute 'x' + # This class provides an error message that is more helpful. + def __getattr__(self, name: str): + raise AttributeError( + "Tried to access `input`, but it was not imported. " + "Perhaps you need `from shiny.express import input`?" + )