Переглянути джерело

support import and ui.run() in interactive python shell

Falko Schindler 3 роки тому
батько
коміт
5308dea05c
3 змінених файлів з 30 додано та 21 видалено
  1. 1 0
      README.md
  2. 24 19
      nicegui/config.py
  3. 5 2
      nicegui/run.py

+ 1 - 0
README.md

@@ -61,6 +61,7 @@ You can call `ui.run()` with optional arguments for some high-level configuratio
 - `favicon` (default: `'favicon.ico'`)
 - `favicon` (default: `'favicon.ico'`)
 - `reload`: automatically reload the ui on file changes (default: `True`)
 - `reload`: automatically reload the ui on file changes (default: `True`)
 - `show`: automatically open the ui in a browser tab (default: `True`)
 - `show`: automatically open the ui in a browser tab (default: `True`)
+- `interactive`: used internally when run in interactive Python shell (default: `False`)
 
 
 ## Docker
 ## Docker
 
 

+ 24 - 19
nicegui/config.py

@@ -12,6 +12,7 @@ class Config(BaseModel):
     favicon: str = 'favicon.ico'
     favicon: str = 'favicon.ico'
     reload: bool = True
     reload: bool = True
     show: bool = True
     show: bool = True
+    interactive: bool = False
 
 
 
 
 excluded_endings = (
 excluded_endings = (
@@ -28,26 +29,30 @@ for f in reversed(inspect.stack()):
 else:
 else:
     raise Exception("Could not find main script in stacktrace")
     raise Exception("Could not find main script in stacktrace")
 
 
-with open(filepath) as f:
-    source = f.read()
-
-for node in ast.parse(source).body:
-    try:
-        func = node.value.func
-        if func.value.id == 'ui' and func.attr == 'run':
-            args = {
-                keyword.arg:
-                    keyword.value.n if isinstance(keyword.value, ast.Num) else
-                    keyword.value.s if isinstance(keyword.value, ast.Str) else
-                    keyword.value.value
-                for keyword in node.value.keywords
-            }
-            config = Config(**args)
-            break
-    except AttributeError:
-        continue
+try:
+    with open(filepath) as f:
+        source = f.read()
+except FileNotFoundError:
+    print('Could not main script. Starting with interactive mode.', flush=True)
+    config = Config(interactive=True)
 else:
 else:
-    raise Exception('Could not find ui.run() command')
+    for node in ast.parse(source).body:
+        try:
+            func = node.value.func
+            if func.value.id == 'ui' and func.attr == 'run':
+                args = {
+                    keyword.arg:
+                        keyword.value.n if isinstance(keyword.value, ast.Num) else
+                        keyword.value.s if isinstance(keyword.value, ast.Str) else
+                        keyword.value.value
+                    for keyword in node.value.keywords
+                }
+                config = Config(**args)
+                break
+        except AttributeError:
+            continue
+    else:
+        raise Exception('Could not find ui.run() command')
 
 
 os.environ['HOST'] = config.host
 os.environ['HOST'] = config.host
 os.environ['PORT'] = str(config.port)
 os.environ['PORT'] = str(config.port)

+ 5 - 2
nicegui/run.py

@@ -2,10 +2,11 @@ import inspect
 import sys
 import sys
 import webbrowser
 import webbrowser
 import uvicorn
 import uvicorn
+from .elements.element import Element
 from .config import config  # NOTE: before justpy
 from .config import config  # NOTE: before justpy
 import justpy as jp
 import justpy as jp
 
 
-if config.reload and not inspect.stack()[-2].filename.endswith('spawn.py'):
+if not config.interactive and config.reload and not inspect.stack()[-2].filename.endswith('spawn.py'):
 
 
     if config.show:
     if config.show:
         webbrowser.open(f'http://{config.host}:{config.port}/')
         webbrowser.open(f'http://{config.host}:{config.port}/')
@@ -14,7 +15,9 @@ if config.reload and not inspect.stack()[-2].filename.endswith('spawn.py'):
 
 
 def run(self, *, host='0.0.0.0', port=80, title='NiceGUI', favicon='favicon.ico', reload=True, show=True):
 def run(self, *, host='0.0.0.0', port=80, title='NiceGUI', favicon='favicon.ico', reload=True, show=True):
 
 
-    if reload == False:  # NOTE: in case reload == True we already started uvicorn above
+    if config.interactive or reload == False:  # NOTE: if reload == True we already started uvicorn above
         if show:
         if show:
             webbrowser.open(f'http://{host if host != "0.0.0.0" else "127.0.0.1"}:{port}/')
             webbrowser.open(f'http://{host if host != "0.0.0.0" else "127.0.0.1"}:{port}/')
+        Element.wp.title = title
+        Element.wp.favicon = favicon
         uvicorn.run(jp.app, host=host, port=port, lifespan='on')
         uvicorn.run(jp.app, host=host, port=port, lifespan='on')