globals.py 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. import asyncio
  2. import inspect
  3. import logging
  4. from contextlib import contextmanager
  5. from enum import Enum
  6. from pathlib import Path
  7. from typing import TYPE_CHECKING, Any, Awaitable, Callable, Dict, Iterator, List, Optional, Union
  8. from socketio import AsyncServer
  9. from uvicorn import Server
  10. from . import background_tasks
  11. from .app import App
  12. from .language import Language
  13. if TYPE_CHECKING:
  14. from .client import Client
  15. from .slot import Slot
  16. class State(Enum):
  17. STOPPED = 0
  18. STARTING = 1
  19. STARTED = 2
  20. STOPPING = 3
  21. app: App
  22. sio: AsyncServer
  23. server: Server
  24. loop: Optional[asyncio.AbstractEventLoop] = None
  25. log: logging.Logger = logging.getLogger('nicegui')
  26. state: State = State.STOPPED
  27. ui_run_has_been_called: bool = False
  28. reload: bool
  29. title: str
  30. viewport: str
  31. favicon: Optional[Union[str, Path]]
  32. dark: Optional[bool]
  33. language: Language
  34. binding_refresh_interval: float
  35. excludes: List[str]
  36. tailwind: bool
  37. socket_io_js_extra_headers: Dict = {}
  38. _socket_id: Optional[str] = None
  39. slot_stacks: Dict[int, List['Slot']] = {}
  40. clients: Dict[str, 'Client'] = {}
  41. index_client: 'Client'
  42. page_routes: Dict[Callable[..., Any], str] = {}
  43. startup_handlers: List[Union[Callable[..., Any], Awaitable]] = []
  44. shutdown_handlers: List[Union[Callable[..., Any], Awaitable]] = []
  45. connect_handlers: List[Union[Callable[..., Any], Awaitable]] = []
  46. disconnect_handlers: List[Union[Callable[..., Any], Awaitable]] = []
  47. exception_handlers: List[Callable[..., Any]] = [log.exception]
  48. def get_task_id() -> int:
  49. try:
  50. return id(asyncio.current_task())
  51. except RuntimeError:
  52. return 0
  53. def get_slot_stack() -> List['Slot']:
  54. task_id = get_task_id()
  55. if task_id not in slot_stacks:
  56. slot_stacks[task_id] = []
  57. return slot_stacks[task_id]
  58. def prune_slot_stack() -> None:
  59. task_id = get_task_id()
  60. if not slot_stacks[task_id]:
  61. del slot_stacks[task_id]
  62. def get_slot() -> 'Slot':
  63. return get_slot_stack()[-1]
  64. def get_client() -> 'Client':
  65. return get_slot().parent.client
  66. @contextmanager
  67. def socket_id(id: str) -> Iterator[None]:
  68. global _socket_id
  69. _socket_id = id
  70. yield
  71. _socket_id = None
  72. def handle_exception(exception: Exception) -> None:
  73. for handler in exception_handlers:
  74. result = handler() if not inspect.signature(handler).parameters else handler(exception)
  75. if isinstance(result, Awaitable):
  76. background_tasks.create(result)