Source code for bacommon.cloudui.v1
# Released under the MIT License. See LICENSE for details.
#
"""Full UIs defined in the cloud - similar to a basic form of html"""
from __future__ import annotations
from enum import Enum
from dataclasses import dataclass, field
from typing import Annotated, override, assert_never
from efro.dataclassio import ioprepped, IOAttrs, IOMultiType
from bacommon.cloudui._cloudui import CloudUI, CloudUITypeID
[docs]
class DecorationTypeID(Enum):
"""Type ID for each of our subclasses."""
UNKNOWN = 'u'
TEXT = 't'
[docs]
class Decoration(IOMultiType[DecorationTypeID]):
"""Top level class for our multitype."""
[docs]
@override
@classmethod
def get_type_id(cls) -> DecorationTypeID:
# Require child classes to supply this themselves. If we did a
# full type registry/lookup here it would require us to import
# everything and would prevent lazy loading.
raise NotImplementedError()
[docs]
@override
@classmethod
def get_type(cls, type_id: DecorationTypeID) -> type[Decoration]:
"""Return the subclass for each of our type-ids."""
# pylint: disable=cyclic-import
t = DecorationTypeID
if type_id is t.UNKNOWN:
return UnknownDecoration
if type_id is t.TEXT:
return Text
# Important to make sure we provide all types.
assert_never(type_id)
[docs]
@override
@classmethod
def get_unknown_type_fallback(cls) -> Decoration:
# If we encounter some future type we don't know anything about,
# drop in a placeholder.
return UnknownDecoration()
[docs]
@ioprepped
@dataclass
class UnknownDecoration(Decoration):
"""An unknown decoration.
In practice these should never show up since the master-server
generates these on the fly for the client and so should not send
clients one they can't digest.
"""
[docs]
@override
@classmethod
def get_type_id(cls) -> DecorationTypeID:
return DecorationTypeID.UNKNOWN
[docs]
@ioprepped
@dataclass
class Text(Decoration):
"""Text decoration."""
text: str
[docs]
@override
@classmethod
def get_type_id(cls) -> DecorationTypeID:
return DecorationTypeID.TEXT
[docs]
@ioprepped
@dataclass
class Row:
"""A row in our cloud ui."""
buttons: list[Button]
title: str | None = None
subtitle: str | None = None
button_spacing: float = 5.0
padding_left: float = 10.0
padding_right: float = 10.0
padding_top: float = 10.0
padding_bottom: float = 10.0
center: bool = False
[docs]
@ioprepped
@dataclass
class UI(CloudUI):
"""Version 1 of our cloud-defined UI type."""
title: str
rows: list[Row]
[docs]
@override
@classmethod
def get_type_id(cls) -> CloudUITypeID:
return CloudUITypeID.V1
# Docs-generation hack; import some stuff that we likely only forward-declared
# in our actual source code so that docs tools can find it.
from typing import (Coroutine, Any, Literal, Callable,
Generator, Awaitable, Sequence, Self)
import asyncio
from concurrent.futures import Future
from pathlib import Path
from enum import Enum