Repository: zauberzeug/nicegui
Pull request #3589 (2024-08-25 06:01:15)

Disable FastAPI docs by default
This PR is inspired by #3570. While seeking a simple solution, it dawned on me that it is probably not a good idea to make the docs available by default. A normal website or UI does not need it and it might lead to unexpected outcomes (https://nicegui.io/docs for example).
So I propose to use 2.0 to introduce a breaking change and make docs only available if `fastapi_docs=True` is passed to `ui.run`.


Patch:
diff --git a/nicegui/app/app.py b/nicegui/app/app.py
index 535d706a..4cd7e29e 100644
--- a/nicegui/app/app.py
+++ b/nicegui/app/app.py
@@ -32,7 +32,7 @@ class State(Enum):
 class App(FastAPI):
 
     def __init__(self, **kwargs) -> None:
-        super().__init__(**kwargs)
+        super().__init__(**kwargs, docs_url=None, redoc_url=None, openapi_url=None)
         self.native = NativeConfig()
         self.storage = Storage()
         self.urls = ObservableSet()
diff --git a/nicegui/element.py b/nicegui/element.py
index 6d476dcc..e0699e24 100644
--- a/nicegui/element.py
+++ b/nicegui/element.py
@@ -122,14 +122,14 @@ class Element(Visibility):
             return sorted(path.parent.glob(path.name), key=lambda p: p.stem)
 
         if libraries:
-            helpers.warn_once('The `libraries` parameter is deprecated. Use `dependencies` instead.',
-                              stack_info=True)
+            helpers.warn_once(f'The `libraries` parameter for subclassing "{cls.__name__}" is deprecated. '
+                              'Use `dependencies` instead.')
         if exposed_libraries:
-            helpers.warn_once('The `exposed_libraries` parameter is deprecated. Use `dependencies` instead.',
-                              stack_info=True)
+            helpers.warn_once(f'The `exposed_libraries` parameter for subclassing "{cls.__name__}" is deprecated. '
+                              'Use `dependencies` instead.')
         if extra_libraries:
-            helpers.warn_once('The `extra_libraries` parameter is deprecated. Use `dependencies` instead.',
-                              stack_info=True)
+            helpers.warn_once(f'The `extra_libraries` parameter for subclassing "{cls.__name__}" is deprecated. '
+                              'Use `dependencies` instead.')
 
         cls.component = copy(cls.component)
         cls.libraries = copy(cls.libraries)
diff --git a/nicegui/ui_run.py b/nicegui/ui_run.py
index 58a175a2..78be41d2 100644
--- a/nicegui/ui_run.py
+++ b/nicegui/ui_run.py
@@ -31,6 +31,7 @@ def run(*,
         language: Language = 'en-US',
         binding_refresh_interval: float = 0.1,
         reconnect_timeout: float = 3.0,
+        fastapi_docs: bool = False,
         show: bool = True,
         on_air: Optional[Union[str, Literal[True]]] = None,
         native: bool = False,
@@ -63,6 +64,7 @@ def run(*,
     :param language: language for Quasar elements (default: `'en-US'`)
     :param binding_refresh_interval: time between binding updates (default: `0.1` seconds, bigger is more CPU friendly)
     :param reconnect_timeout: maximum time the server waits for the browser to reconnect (default: 3.0 seconds)
+    :param fastapi_docs: whether to enable FastAPI's automatic documentation with Swagger UI, ReDoc, and OpenAPI JSON (default: `False`)
     :param show: automatically open the UI in a browser tab (default: `True`)
     :param on_air: tech preview: `allows temporary remote access <https://nicegui.io/documentation/section_configuration_deployment#nicegui_on_air>`_ if set to `True` (default: disabled)
     :param native: open the UI in a native window of size 800x600 (default: `False`, deactivates `show`, automatically finds an open port)
@@ -104,6 +106,15 @@ def run(*,
         if route.path == '/' or route.path in Client.page_routes.values():
             route.include_in_schema = endpoint_documentation in {'page', 'all'}
 
+    if fastapi_docs:
+        if not core.app.docs_url:
+            core.app.docs_url = '/docs'
+        if not core.app.redoc_url:
+            core.app.redoc_url = '/redoc'
+        if not core.app.openapi_url:
+            core.app.openapi_url = '/openapi.json'
+        core.app.setup()
+
     if on_air:
         core.air = Air('' if on_air is True else on_air)
 


Test patch:
diff --git a/tests/test_endpoint_docs.py b/tests/test_endpoint_docs.py
index 3a092d86..2921f7ed 100644
--- a/tests/test_endpoint_docs.py
+++ b/tests/test_endpoint_docs.py
@@ -1,11 +1,17 @@
 from typing import Set
 
+import pytest
 import requests
 
 from nicegui import __version__
 from nicegui.testing import Screen
 
 
+@pytest.fixture(autouse=True)
+def activate_fastapi_docs(screen: Screen):
+    screen.ui_run_kwargs['fastapi_docs'] = True
+
+
 def get_openapi_paths() -> Set[str]:
     return set(requests.get(f'http://localhost:{Screen.PORT}/openapi.json', timeout=5).json()['paths'])