You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
119 lines
3.0 KiB
119 lines
3.0 KiB
from __future__ import annotations |
|
|
|
import asyncio |
|
import inspect |
|
import logging |
|
import os |
|
from contextlib import contextmanager |
|
from enum import Enum |
|
from pathlib import Path |
|
from typing import TYPE_CHECKING, Any, Awaitable, Callable, Dict, Iterator, List, Literal, Optional, Set, Union |
|
|
|
from socketio import AsyncServer |
|
from uvicorn import Server |
|
|
|
from . import background_tasks |
|
|
|
if TYPE_CHECKING: |
|
from .air import Air |
|
from .app import App |
|
from .client import Client |
|
from .language import Language |
|
from .slot import Slot |
|
|
|
|
|
class State(Enum): |
|
STOPPED = 0 |
|
STARTING = 1 |
|
STARTED = 2 |
|
STOPPING = 3 |
|
|
|
|
|
app: App |
|
sio: AsyncServer |
|
server: Server |
|
loop: Optional[asyncio.AbstractEventLoop] = None |
|
log: logging.Logger = logging.getLogger('nicegui') |
|
state: State = State.STOPPED |
|
ui_run_has_been_called: bool = False |
|
optional_features: Set[str] = set() |
|
|
|
reload: bool |
|
title: str |
|
viewport: str |
|
favicon: Optional[Union[str, Path]] |
|
dark: Optional[bool] |
|
language: Language |
|
binding_refresh_interval: float |
|
tailwind: bool |
|
prod_js: bool |
|
endpoint_documentation: Literal['none', 'internal', 'page', 'all'] = 'none' |
|
air: Optional[Air] = None |
|
storage_path: Path = Path(os.environ.get('NICEGUI_STORAGE_PATH', '.nicegui')).resolve() |
|
socket_io_js_query_params: Dict = {} |
|
socket_io_js_extra_headers: Dict = {} |
|
socket_io_js_transports: List[Literal['websocket', 'polling']] = ['websocket', 'polling'] # NOTE: we favor websocket |
|
_socket_id: Optional[str] = None |
|
slot_stacks: Dict[int, List[Slot]] = {} |
|
clients: Dict[str, Client] = {} |
|
index_client: Client |
|
quasar_config: Dict = { |
|
'brand': { |
|
'primary': '#5898d4', |
|
}, |
|
'loadingBar': { |
|
'color': 'primary', |
|
'skipHijack': False, |
|
}, |
|
} |
|
|
|
page_routes: Dict[Callable[..., Any], str] = {} |
|
|
|
startup_handlers: List[Union[Callable[..., Any], Awaitable]] = [] |
|
shutdown_handlers: List[Union[Callable[..., Any], Awaitable]] = [] |
|
connect_handlers: List[Union[Callable[..., Any], Awaitable]] = [] |
|
disconnect_handlers: List[Union[Callable[..., Any], Awaitable]] = [] |
|
exception_handlers: List[Callable[..., Any]] = [log.exception] |
|
|
|
|
|
def get_task_id() -> int: |
|
try: |
|
return id(asyncio.current_task()) |
|
except RuntimeError: |
|
return 0 |
|
|
|
|
|
def get_slot_stack() -> List[Slot]: |
|
task_id = get_task_id() |
|
if task_id not in slot_stacks: |
|
slot_stacks[task_id] = [] |
|
return slot_stacks[task_id] |
|
|
|
|
|
def prune_slot_stack() -> None: |
|
task_id = get_task_id() |
|
if not slot_stacks[task_id]: |
|
del slot_stacks[task_id] |
|
|
|
|
|
def get_slot() -> Slot: |
|
return get_slot_stack()[-1] |
|
|
|
|
|
def get_client() -> Client: |
|
return get_slot().parent.client |
|
|
|
|
|
@contextmanager |
|
def socket_id(id_: str) -> Iterator[None]: |
|
global _socket_id # pylint: disable=global-statement |
|
_socket_id = id_ |
|
yield |
|
_socket_id = None |
|
|
|
|
|
def handle_exception(exception: Exception) -> None: |
|
for handler in exception_handlers: |
|
result = handler() if not inspect.signature(handler).parameters else handler(exception) |
|
if isinstance(result, Awaitable): |
|
background_tasks.create(result)
|
|
|