bacommon.docui.routes package

Type-safe routes and local-actions layered over doc-ui v2.

The doc-ui wire format is string based (request paths, arg dicts, local-action names). The classes here let first-party code work purely in dataclasses instead; the modules alongside define the routes for individual doc-ui domains and are shared by whichever ends (client and/or server) author or handle that domain’s pages.

class bacommon.docui.routes.DocUILocalActionBase[source]

Bases: object

A local-action in a doc-ui domain, with args as dataclass fields.

The local-action analogue of DocUIRoute: each named action a domain’s client-side controller exposes is an @ioprepped dataclass inheriting from that domain’s family class (a direct child of this class).

attach(response: bacommon.docui.v2.Response) → None[source]

Have a response run this local-action when first received.

classmethod from_name_and_args(name: str, args: dict) → Self[source]

Return the local-action in this family matching a name + args.

Should be called on a family class. Raises DocUIRouteError if there is no match.

classmethod get_action_types() → tuple[type[DocUILocalActionBase], ...][source]

Return all concrete local-actions in this family.

Must be overridden by each family class; see get_route_types().

classmethod get_name() → str[source]

Return the wire name for this local-action.

classmethod get_press_sound() → PressSound[source]

What a button plays when pressed to run this local-action.

Actions that stay on the page click (the default); override to return SWISH for ones that go somewhere (open a window or popup). A press whose action has default_sound off plays nothing either way.

local(*, close_window: bool = False, default_sound: bool = True, sets: Sequence[DocUIStateAssign[DocUIState]] | None = None) → bacommon.docui.v2.Local[source]

Return an action running this local-action immediately.

Any sets are applied to the pressing page’s state first.

classmethod press_sound_for_name(name: str) → PressSound[source]

The press sound for the local-action in this family named so.

Should be called on a family class. Unknown names click.

class bacommon.docui.routes.DocUIRoute[source]

Bases: object

A page in a doc-ui domain, with its args as dataclass fields.

Doc-ui (v2) requests are a path string plus a dict of args on the wire. A route is a type-safe stand-in for one: each page a domain offers is an @ioprepped dataclass inheriting from that domain’s family class (itself a direct child of this class). The dataclass’ fields are the page’s args; its path and request-method are given as keywords on its class line (class Foo(FooFamily, path='/foo', method=POST)).

Page code never touches the path or args dict directly: authoring goes through the browse() and replace() verbs and handling goes through from_request() (generally called on one’s behalf by a controller or request-handler base class).

Paths within a family are a closed set; anything variable belongs in args (no /item/<id> style paths). Routes are keyed on path and method, so a page and the POST that submits it can share a path.

browse(*, default_sound: bool = True, sets: Sequence[DocUIStateAssign[DocUIState]] | None = None, state: DocUIState | None = None, layout: bacommon.docui.v2.WindowLayout | None = None, scroll_edge_style: bacommon.docui.v2.ScrollEdgeStyle | None = None, background_color: tuple[float, float, float] | None = None, cancel_button_color: tuple[float, float, float] | None = None, add_to_history: bool = True) → bacommon.docui.v2.Browse[source]

Return an action browsing to this route in a new window.

The pressing page’s state goes along with the request, with any sets applied to it. Pass state to send some other state entirely; generally what a different page expects. The window opens at layout, or at get_window_layout() if not given, with scroll_edge_style (or its layout’s default if not given) and the frame colors given (see bacommon.docui.v2.Browse.background_color). (Its viewer pane, if any, is up to each page; see viewer.) With add_to_history off, the new window takes the current one’s place in the back history instead of adding to it (see bacommon.docui.v2.Browse.add_to_history).

classmethod close_to(*assigns: DocUIStateAssign[DocUIState], default_sound: bool = True) → bacommon.docui.v2.Local[source]

Return an action closing back to an earlier page of ours.

Closes the current window and every window above the nearest earlier one showing this route’s page, which then refreshes; for leaving a flow several pages deep in one step (say a purchase confirmation returning to the listing the purchase started from). Any assigns (all for one state type) are handed back into that page’s state, as with assign_on_return().

The page should be one the user is sure to have come through. If it isn’t in the window’s history the client warns and just closes the one window, which is a bug to fix rather than a fallback to rely on. Matching is by path, so any earlier window showing this route’s page counts, whatever its args.

classmethod from_request(request: bacommon.docui.v2.Request) → Self[source]

Return the route in this family that a request maps to.

Should be called on a family class. Raises DocUIRouteError if the request does not map to a route in the family.

classmethod get_method() → bacommon.docui.v2.RequestMethod[source]

Return the request method for this route.

classmethod get_path() → str[source]

Return the request path for this route.

classmethod get_route_types() → tuple[type[DocUIRoute], ...][source]

Return all concrete routes in this family.

Must be overridden by each family class. A family generally defines a union alias of its routes (which also gives handlers assert_never exhaustiveness) and returns family_members() of it here.

get_source_request() → bacommon.docui.v2.Request | None[source]

Return the request we were built from, if we were.

Unlike request(), which only ever describes the route itself, this carries whatever else rode along with the request (page state, trigger). Something forwarding an incoming route elsewhere as-is wants those to go along too.

get_state(state_type: type[S]) → S | None[source]

Return page state that arrived with the request for us.

Only routes built from requests have any, and only when the page the request was fired from had state of this type; anything else gives None. State is always optional input, so callers need a story for that.

get_trigger() → str | None[source]

State key of the input whose change fired our request, if any.

classmethod get_window_layout() → bacommon.docui.v2.WindowLayout[source]

The layout windows browsing to this route open with.

browse() uses this unless told otherwise, so a route whose page is best shown at some layout declares it once rather than at every link.

Defaults to WIDE_TALL, a middling shape that suits most pages, short or tall, without ever being a big mostly-empty window. Pages that suit another shape ask for it: WIDE for short one-off pages (a confirmation, a dialog) and LARGE, which grows to fill more of the screen at medium/large ui-scale, for pages built to use that room (store listings and the like).

replace(*, default_sound: bool = True, sets: Sequence[DocUIStateAssign[DocUIState]] | None = None, state: DocUIState | None = None) → bacommon.docui.v2.Replace[source]

Return an action replacing the current page with this route.

See browse() for sets and state.

request() → bacommon.docui.v2.Request[source]

Return the wire request for this route.

exception bacommon.docui.routes.DocUIRouteError[source]

Bases: Exception

A request or local-action could not be mapped to a typed form.

class bacommon.docui.routes.DocUIState[source]

Bases: object

Values belonging to a doc-ui page, as dataclass fields.

Where route args say which page something is, state is what the user is in the middle of on it: the values its input rows show and edit plus anything else it wants handed back (a draft being composed, say). A page declares its state once and the client sends the current values along with every request fired from that page, so individual links need only say what they change.

Subclasses are @ioprepped dataclasses declaring a globally unique id on their class line (class Foo(DocUIState, state_id='mydomain.foo')). The id rides along with the values so that state arriving at a page expecting some other type reads as no state at all instead of being mis-decoded. Field storage names must not start with an underscore.

State is always optional input; a page must be able to make do without any (see DocUIRoute.get_state).

classmethod assign(field: Callable[[Self], V], value: V) → DocUIStateAssign[Self][source]
classmethod assign(field: Callable[[Self], V | None], value: V) → DocUIStateAssign[Self]

Return an assignment of a value to one of our fields.

For passing as sets when creating actions: route.replace(sets=[MyState.assign(lambda s: s.color, c)]). The value is type-checked against the field. (The second overload is what lets a plain E be assigned to an E | None field: mypy settles the type variable from the value before it looks at the lambda.)

classmethod assign_locally(*assigns: DocUIStateAssign[Self], default_sound: bool = True) → bacommon.docui.v2.Local[source]

Return an action assigning values with no request involved.

The values simply go out with whatever the page sends next.

classmethod assign_on_return(*assigns: DocUIStateAssign[Self], default_sound: bool = True) → bacommon.docui.v2.Local[source]

Return an action closing the window, handing values back.

For a picker opened in a window of its own: the window closes and the values are assigned into the state of the page returned to (which must hold our state type; the client checks), which then refreshes with them.

classmethod checkbox_row(field: Callable[[Self], bool], *, label: LangStrSpec | None = None, title: LangStrSpec | None = None, subtitle: LangStrSpec | None = None, title_align: bacommon.docui.v2.HAlign | None = None, footnote: LangStrSpec | None = None, on_change: bacommon.docui.v2.Action | None = None, disabled: bool = False, debug: bool = False) → bacommon.docui.v2.CheckboxRow[source]

Return a checkbox row editing one of our (bool) fields.

disabled shows it dimmed and not toggleable (still selectable).

classmethod choice_row(field: Callable[[Self], E], *, choice_label: Callable[[E], LangStrSpec], choices: Sequence[E] | None = None, disabled_choices: Collection[E] = (), label: LangStrSpec | None = None, title: LangStrSpec | None = None, subtitle: LangStrSpec | None = None, title_align: bacommon.docui.v2.HAlign | None = None, footnote: LangStrSpec | None = None, on_change: bacommon.docui.v2.Action | None = None, disabled: bool = False, debug: bool = False) → bacommon.docui.v2.ChoiceRow[source]
classmethod choice_row(field: Callable[[Self], E | None], *, choice_label: Callable[[E], LangStrSpec], none_label: LangStrSpec, choices: Sequence[E] | None = None, disabled_choices: Collection[E] = (), label: LangStrSpec | None = None, title: LangStrSpec | None = None, subtitle: LangStrSpec | None = None, title_align: bacommon.docui.v2.HAlign | None = None, footnote: LangStrSpec | None = None, on_change: bacommon.docui.v2.Action | None = None, disabled: bool = False, debug: bool = False) → bacommon.docui.v2.ChoiceRow
classmethod choice_row(field: Callable[[Self], str], *, choices: Sequence[tuple[str, LangStrSpec]], disabled_choices: Collection[str] = (), label: LangStrSpec | None = None, title: LangStrSpec | None = None, subtitle: LangStrSpec | None = None, title_align: bacommon.docui.v2.HAlign | None = None, footnote: LangStrSpec | None = None, on_change: bacommon.docui.v2.Action | None = None, disabled: bool = False, debug: bool = False) → bacommon.docui.v2.ChoiceRow
classmethod choice_row(field: Callable[[Self], str | None], *, choices: Sequence[tuple[str, LangStrSpec]], none_label: LangStrSpec, disabled_choices: Collection[str] = (), label: LangStrSpec | None = None, title: LangStrSpec | None = None, subtitle: LangStrSpec | None = None, title_align: bacommon.docui.v2.HAlign | None = None, footnote: LangStrSpec | None = None, on_change: bacommon.docui.v2.Action | None = None, disabled: bool = False, debug: bool = False) → bacommon.docui.v2.ChoiceRow

Return a choice row editing one of our enum or str fields.

For an enum field, choice_label gives each option’s display text; write it as a match ending in assert_never so a new enum member can’t go unlabeled. choices narrows/reorders the options shown (default: every member, in definition order).

For a str field there is no closed set to be exhaustive over, so choices instead defines the options as (value, label) pairs, in display order; choice_label does not apply. The state’s current value should be among them (a value that isn’t shows as the first option).

disabled_choices lists options to show greyed out and unpickable (enum members, or str values, matching how choices are given) – each must be one of the options. disabled instead disables the whole row: shown dimmed with its menu unopenable (still selectable).

A field typed E | None / str | None gets a ‘nothing’ option too, listed first, whose display text is none_label – required for such fields and not allowed for others. The type checker enforces the required halves of all this via the overloads; what it can’t express (a stray none_label or choice_label) is checked here at runtime along with the rest.

classmethod color_row(field: Callable[[Self], tuple[float, float, float]], *, label: LangStrSpec | None = None, title: LangStrSpec | None = None, subtitle: LangStrSpec | None = None, title_align: bacommon.docui.v2.HAlign | None = None, footnote: LangStrSpec | None = None, on_change: bacommon.docui.v2.Action | None = None, disabled: bool = False, debug: bool = False) → bacommon.docui.v2.ColorRow[source]

Return a color row editing one of our rgb fields.

The field must be typed tuple[float, float, float] (0-1 components). on_change fires when the picker closes with a changed color, not per intermediate change. disabled shows it dimmed with its picker unopenable (still selectable).

classmethod decode(data: dict | None) → Self | None[source]

Return state of this type from its wire form, if that it be.

Returns None for no data, data for some other state type, or data that fails to decode. State comes from clients and is always optional, so none of those are errors.

encode() → dict[source]

Return the wire form of this state (for Page.state etc.).

classmethod get_keys() → set[str][source]

Return the wire keys of all of our fields.

classmethod get_state_id() → str[source]

Return the wire id for this state type.

classmethod key(field: Callable[[Self], Any]) → str[source]

Return the wire key for a field, given a lambda fetching it.

MyState.key(lambda s: s.some_field)

classmethod number_row(field: Callable[[Self], float], *, min_value: float, max_value: float, increment: float, as_percent: bool = False, decimals: int = 0, label: LangStrSpec | None = None, title: LangStrSpec | None = None, subtitle: LangStrSpec | None = None, title_align: bacommon.docui.v2.HAlign | None = None, footnote: LangStrSpec | None = None, on_change: bacommon.docui.v2.Action | None = None, disabled: bool = False, debug: bool = False) → bacommon.docui.v2.NumberRow[source]

Return a ‘-‘/’+’ number row editing one of our float fields.

on_change fires on each press that changes the value. disabled shows it dimmed and not adjustable (still selectable). See bacommon.docui.v2.NumberRow.

classmethod slider_row(field: Callable[[Self], float], *, min_value: float, max_value: float, increment: float, as_percent: bool = False, decimals: int = 2, label: LangStrSpec | None = None, title: LangStrSpec | None = None, subtitle: LangStrSpec | None = None, title_align: bacommon.docui.v2.HAlign | None = None, footnote: LangStrSpec | None = None, on_change: bacommon.docui.v2.Action | None = None, on_drag: bacommon.docui.v2.Local | None = None, drag_interval: float = 0.25, drag_delay: float = 0.0, disabled: bool = False, debug: bool = False) → bacommon.docui.v2.SliderRow[source]

Return a slider row editing one of our float fields.

on_change fires for a settled value (release, or a run of key/controller steps going quiet); on_drag – a local action, built via MyAction().local() – fires during a drag (key/controller steps included) at the throttled cadence drag_interval / drag_delay describe, reading the live value from the page’s state. disabled shows it dimmed and not adjustable (still selectable). See bacommon.docui.v2.SliderRow.

classmethod text_input_row(field: Callable[[Self], str], *, label: LangStrSpec | None = None, title: LangStrSpec | None = None, subtitle: LangStrSpec | None = None, title_align: bacommon.docui.v2.HAlign | None = None, footnote: LangStrSpec | None = None, description: LangStrSpec | None = None, max_chars: int = 64, on_change: bacommon.docui.v2.Action | None = None, on_submit: bacommon.docui.v2.Action | None = None, disabled: bool = False, debug: bool = False) → bacommon.docui.v2.TextInputRow[source]

Return a text-input row editing one of our (str) fields.

disabled shows it dimmed and not editable (still selectable).

class bacommon.docui.routes.DocUIStateAssign(state_type: type[S], key: str, value: Any)[source]

Bases: Generic

A value to be assigned into a page’s state of type S.

Create these via DocUIState.assign(). (Frozen, which makes the type covariant: an assign for FooState is also a DocUIStateAssign[DocUIState], the form taken by things that accept assigns for any state type.)

key: str
state_type: type[S]
value: Any
class bacommon.docui.routes.NoLocalActions[source]

Bases: DocUILocalActionBase

Stock local-action family for domains that have none.

Pair with typing.Never as the local-action type arg.

classmethod get_action_types() → tuple[type[DocUILocalActionBase], ...][source]

Return all concrete local-actions in this family.

Must be overridden by each family class; see get_route_types().

class bacommon.docui.routes.PopupParent(state_type: type[S])[source]

Bases: Generic

Builds a popup’s actions that act on the page it is over.

Get one from PopupRoute.parent(). Every action here closes the popup; the parent then does what the action says, as though pressed there. A link that would read Foo().replace() on the parent page reads parent.replace(Foo()) in the popup.

browse(route: DocUIRoute, *, sets: Sequence[DocUIStateAssign[S]] | None = None, state: DocUIState | None = None, layout: bacommon.docui.v2.WindowLayout | None = None, default_sound: bool = True) → bacommon.docui.v2.Local[source]

Close the popup; the parent browses to a route.

As for browse(), with sets applying to the parent’s state.

close(*, default_sound: bool = True) → bacommon.docui.v2.Local[source]

Close the popup and the parent’s window too.

close_to(route_type: type[DocUIRoute], *assigns: DocUIStateAssign[DocUIState], default_sound: bool = True) → bacommon.docui.v2.Local[source]

Close the popup, then close the parent back to a route.

As close_to() would if pressed on the parent (assigns go to the page closed back to, so may be of any one state type).

dismiss(*, default_sound: bool = True) → bacommon.docui.v2.Local[source]

Close the popup, leaving the parent alone.

refresh(*assigns: DocUIStateAssign[S], default_sound: bool = True) → bacommon.docui.v2.Local[source]

Close the popup and refresh the parent.

Any assigns are applied to the parent’s state first.

replace(route: DocUIRoute, *, sets: Sequence[DocUIStateAssign[S]] | None = None, state: DocUIState | None = None, default_sound: bool = True) → bacommon.docui.v2.Local[source]

Close the popup; the parent replaces its page with a route.

sets and state are as for replace(), with sets applying to the parent’s state.

run(action: bacommon.docui.v2.Action, *, default_sound: bool = True) → bacommon.docui.v2.Local[source]

Close the popup; the parent runs an arbitrary action.

The escape hatch for anything the other methods don’t cover (a local-action’s local(), say). The action must be a browse, replace or local (not one acting on a parent itself); its sets apply to the parent’s state.

state_type: type[S]

State type of the parent page.

class bacommon.docui.routes.PopupRoute[source]

Bases: DocUIRoute, Generic

A route whose page is shown in a popup over a parent page.

Mixed in next to a domain’s family class, naming the state type of the page(s) the popup opens over: class SortMenu(StoreRoute, PopupRoute[ListingState], path=...). That type is what the popup may act on: its parent() builds actions applying to the parent (setting keys of S), and get_parent_state() reads the parent’s current state. Pages opening the popup must hold state of type S; that and the rules for what a popup page may contain are checked when pages are validated (see validate_route_page()).

Open one with popup().

get_parent_state() → S | None[source]

Return the parent page’s state as it arrived with our request.

As with get_state(), this is always optional input: None when absent, of another type, or undecodable.

classmethod get_parent_state_type() → type[S][source]

Return the state type of the page this popup opens over.

classmethod get_popup_size() → tuple[float, float][source]

Content-area size (width, height) our popups open at.

In window units (see bacommon.docui.v2.Popup.size), at least POPUP_MIN_SIZE; clients shrink whatever doesn’t fit their screen. Override to suit the page; popup() can also be told otherwise per link.

classmethod parent() → PopupParent[S][source]

Return a handle for building actions acting on our parent.

popup(*, default_sound: bool = True, sets: Sequence[DocUIStateAssign[S]] | None = None, size: tuple[float, float] | None = None, show_title: bool = False, show_close_button: bool = False, dim_background: bool = True, scroll_edge_style: bacommon.docui.v2.ScrollEdgeStyle = ScrollEdgeStyle.FADE, background_color: tuple[float, float, float] | None = None, cancel_button_color: tuple[float, float, float] | None = None) → bacommon.docui.v2.Popup[source]

Return an action opening this route’s page in a popup.

The pressing page (whose state must be of our parent state type) is the popup’s parent; any sets are applied to its state first, and that state goes along with the request (and every later one fired from the popup). The popup’s content area is size, or get_popup_size() if not given; the rest is as for bacommon.docui.v2.Popup.

Only clients from bacommon.docui.v2.POPUP_BUILD on can show popups; gate links to them on bacommon.docui.v2.supports_popups().

class bacommon.docui.routes.PressSound(*values)[source]

Bases: Enum

What a button plays when pressed to run a local-action.

See get_press_sound().

CLICK = 'click'

The standard click, for actions that stay on the page.

NONE = 'none'

Nothing (the action handles any sound itself).

SWISH = 'swish'

The standard ui swish, for actions that go somewhere – open a window or a popup, say – like a browse does.

bacommon.docui.routes.family_members(alias: Any) → tuple[Any, ...][source]

Return the classes making up a family’s union alias.

Handles the degenerate single-member case, where the ‘union’ is simply the one class.

bacommon.docui.routes.validate_page_state(page: bacommon.docui.v2.Page, *, in_popup: bool = False) → None[source]

Make sure a page’s use of its state hangs together.

Checks that everything referring to the page’s state by key (input rows, sets on actions) names a real field of the state type the page declares. Those are all produced by type-checked calls, but nothing static ties them to the same state type as the page’s, so that part gets checked here. Pages whose state is of no type known to us (third party ones, say) are left alone.

With in_popup (a page shown in a popup window), actions opening another popup are left out: their sets go to the popup’s parent (see validate_popup_page()).

bacommon.docui.routes.validate_popup_page(page: bacommon.docui.v2.Page, parent_state_type: type[DocUIState]) → None[source]

Make sure a page shown in a popup keeps to the popup rules.

No Browse (the parent browses instead), parent actions of the allowed kinds only, and everything aimed at the parent (sets of its actions, values handed back) belonging to the parent’s state type.

bacommon.docui.routes.validate_route_page(route: DocUIRoute, page: bacommon.docui.v2.Page) → None[source]

Run every validation that applies to a route’s page.

validate_page_state(), plus validate_popup_page() for a popup route. Typed controllers and request handlers call this on every page they produce, so a misbuilt page fails on its first render rather than in the field.

Submodules

bacommon.docui.routes.classicaccount module

Routes for the classic account doc-ui domain (classicaccount).

Pages about an account, served by the master server: the place to link to whenever an account is shown (a party member’s verified account, a stats row, and so on). Other domains open them through local-actions of their own (see TypedDocUIController.browse_from() on the client).

class bacommon.docui.routes.classicaccount.Account(account_id: str)[source]

Bases: ClassicAccountRoute

About one account.

account_id: str

The account (a-XXX).

bacommon.docui.routes.classicaccount.AnyClassicAccountLocalAction

alias of Placeholder

bacommon.docui.routes.classicaccount.AnyClassicAccountRoute

alias of Account

class bacommon.docui.routes.classicaccount.ClassicAccountLocalAction[source]

Bases: DocUILocalActionBase

Family class for classic account local-actions.

classmethod get_action_types() → tuple[type[DocUILocalActionBase], ...][source]

Return all concrete local-actions in this family.

Must be overridden by each family class; see get_route_types().

class bacommon.docui.routes.classicaccount.ClassicAccountRoute[source]

Bases: DocUIRoute

Family class for classic account routes.

classmethod get_route_types() → tuple[type[DocUIRoute], ...][source]

Return all concrete routes in this family.

Must be overridden by each family class. A family generally defines a union alias of its routes (which also gives handlers assert_never exhaustiveness) and returns family_members() of it here.

classmethod get_window_layout() → WindowLayout[source]

The layout windows browsing to this route open with.

browse() uses this unless told otherwise, so a route whose page is best shown at some layout declares it once rather than at every link.

Defaults to WIDE_TALL, a middling shape that suits most pages, short or tall, without ever being a big mostly-empty window. Pages that suit another shape ask for it: WIDE for short one-off pages (a confirmation, a dialog) and LARGE, which grows to fill more of the screen at medium/large ui-scale, for pages built to use that room (store listings and the like).

class bacommon.docui.routes.classicaccount.Placeholder[source]

Bases: ClassicAccountLocalAction

Does nothing; holds the family’s place until it has real ones.

(A family needs a member.)

bacommon.docui.routes.classiccharacterpreview module

Routes for the classic character-preview doc-ui domain.

A character being tried out in a game (sent there from its builder page; see the game’s character-preview session): the profile editor for it, as a player who picks the character will see it. Saving changes nothing stored anywhere; it answers with the character as edited for the preview session to carry on with.

bacommon.docui.routes.classiccharacterpreview.AnyCharacterPreviewLocalAction

alias of Saved

class bacommon.docui.routes.classiccharacterpreview.CharacterPreviewLocalAction[source]

Bases: DocUILocalActionBase

Family class for classic character-preview local-actions.

classmethod get_action_types() → tuple[type[DocUILocalActionBase], ...][source]

Return all concrete local-actions in this family.

Must be overridden by each family class; see get_route_types().

class bacommon.docui.routes.classiccharacterpreview.CharacterPreviewRoute[source]

Bases: DocUIRoute

Family class for classic character-preview routes.

classmethod get_route_types() → tuple[type[DocUIRoute], ...][source]

Return all concrete routes in this family.

Must be overridden by each family class. A family generally defines a union alias of its routes (which also gives handlers assert_never exhaustiveness) and returns family_members() of it here.

classmethod get_window_layout() → WindowLayout[source]

The layout windows browsing to this route open with.

browse() uses this unless told otherwise, so a route whose page is best shown at some layout declares it once rather than at every link.

Defaults to WIDE_TALL, a middling shape that suits most pages, short or tall, without ever being a big mostly-empty window. Pages that suit another shape ask for it: WIDE for short one-off pages (a confirmation, a dialog) and LARGE, which grows to fill more of the screen at medium/large ui-scale, for pages built to use that room (store listings and the like).

class bacommon.docui.routes.classiccharacterpreview.Edit(preview_id: str)[source]

Bases: CharacterPreviewRoute

The profile editor for a previewed character.

The draft being composed rides along as page state (the profile editor’s own: ProfileDraft).

preview_id: str

The preview’s id, as the game was given it with the character.

class bacommon.docui.routes.classiccharacterpreview.Save(preview_id: str)[source]

Bases: CharacterPreviewRoute

Save the editor’s draft; answered with Saved.

preview_id: str
class bacommon.docui.routes.classiccharacterpreview.Saved(preview_id: str, character: str)[source]

Bases: CharacterPreviewLocalAction

The previewed character was edited; here it is as it now stands.

character: str

The character, in the form the game was first given it.

preview_id: str

bacommon.docui.routes.classicchest module

Routes for the classic chest doc-ui domain.

One chest slot: what’s in it, its prize odds and its unlock wait, with buttons to open it (now, for tokens, or once unlocked) or to watch an ad to cut the wait. Opening answers with the chest’s contents and the open animation as client-effects.

class bacommon.docui.routes.classicchest.AdWatched(slot: int)[source]

Bases: ChestRoute

The player watched an ad to reduce a chest’s wait.

Answered like Open if that unlocked it; otherwise with the slot as it now stands.

slot: int
class bacommon.docui.routes.classicchest.ChestLocalAction[source]

Bases: DocUILocalActionBase

Family class for classic chest local-actions.

classmethod get_action_types() → tuple[type[DocUILocalActionBase], ...][source]

Return all concrete local-actions in this family.

Must be overridden by each family class; see get_route_types().

class bacommon.docui.routes.classicchest.ChestRoute[source]

Bases: DocUIRoute

Family class for classic chest routes.

classmethod get_route_types() → tuple[type[DocUIRoute], ...][source]

Return all concrete routes in this family.

Must be overridden by each family class. A family generally defines a union alias of its routes (which also gives handlers assert_never exhaustiveness) and returns family_members() of it here.

classmethod get_window_layout() → WindowLayout[source]

The layout windows browsing to this route open with.

browse() uses this unless told otherwise, so a route whose page is best shown at some layout declares it once rather than at every link.

Defaults to WIDE_TALL, a middling shape that suits most pages, short or tall, without ever being a big mostly-empty window. Pages that suit another shape ask for it: WIDE for short one-off pages (a confirmation, a dialog) and LARGE, which grows to fill more of the screen at medium/large ui-scale, for pages built to use that room (store listings and the like).

class bacommon.docui.routes.classicchest.GetTokens[source]

Bases: ChestLocalAction

Offer to get more tokens (not enough to open a chest now).

classmethod get_press_sound() → PressSound[source]

What a button plays when pressed to run this local-action.

Actions that stay on the page click (the default); override to return SWISH for ones that go somewhere (open a window or popup). A press whose action has default_sound off plays nothing either way.

class bacommon.docui.routes.classicchest.Open(slot: int, token_payment: int)[source]

Bases: ChestRoute

Open a chest, paying any tokens its wait currently costs.

Answered with its contents and the open animation.

slot: int
token_payment: int

Tokens the player agreed to pay (0 for an unlocked chest). The open fails if the cost has since changed.

class bacommon.docui.routes.classicchest.Root(slot: int, ad_ready: bool = False, open_me: bool = False)[source]

Bases: ChestRoute

A chest slot: its chest (if any) and what can be done with it.

The two flags are things only the client knows, so it states them when asking.

ad_ready: bool = False

Whether an ad is ready to show right now (so a ‘watch an ad to reduce the wait’ button can work).

open_me: bool = False

Whether to remind about opening early with tokens (the player can switch the reminder off).

slot: int

Which slot (0-based).

class bacommon.docui.routes.classicchest.StopReminding(slot: int)[source]

Bases: ChestLocalAction

Stop reminding about opening chests early; re-show the slot.

slot: int
class bacommon.docui.routes.classicchest.WatchAd(slot: int)[source]

Bases: ChestLocalAction

Show an ad; once watched, ask for AdWatched.

slot: int

bacommon.docui.routes.classichost module

Routes for the classic host doc-ui domain.

Pages a game host serves its connected clients over the game connection (see bacommon.hostui): the defaults classic hosts ship with. Hosts may serve other routes of their own alongside these.

bacommon.docui.routes.classichost.AnyClassicHostLocalAction

alias of ShowAccount

class bacommon.docui.routes.classichost.ClassicHostLocalAction[source]

Bases: DocUILocalActionBase

Family class for local-actions host pages may use.

Hosts are untrusted, so these are the only things a host page can make a client do locally: each is safe whatever a host passes it (its fields arrive from the host as-is). Clients ignore anything else.

classmethod get_action_types() → tuple[type[DocUILocalActionBase], ...][source]

Return all concrete local-actions in this family.

Must be overridden by each family class; see get_route_types().

class bacommon.docui.routes.classichost.ClassicHostRoute[source]

Bases: DocUIRoute

Family class for classic host routes.

classmethod get_route_types() → tuple[type[DocUIRoute], ...][source]

Return all concrete routes in this family.

Must be overridden by each family class. A family generally defines a union alias of its routes (which also gives handlers assert_never exhaustiveness) and returns family_members() of it here.

class bacommon.docui.routes.classichost.Client(client_id: int)[source]

Bases: ClassicHostRoute

One party member (a connected client, or -1 for the host).

Their account, connection and players, and kicking them. Party windows open this when a member’s name is pressed.

client_id: int
classmethod get_window_layout() → WindowLayout[source]

The layout windows browsing to this route open with.

browse() uses this unless told otherwise, so a route whose page is best shown at some layout declares it once rather than at every link.

Defaults to WIDE_TALL, a middling shape that suits most pages, short or tall, without ever being a big mostly-empty window. Pages that suit another shape ask for it: WIDE for short one-off pages (a confirmation, a dialog) and LARGE, which grows to fill more of the screen at medium/large ui-scale, for pages built to use that room (store listings and the like).

class bacommon.docui.routes.classichost.KickVote(client_id: int | None = None, player_id: int | None = None)[source]

Bases: ClassicHostRoute

Start or follow a vote to kick someone.

Clients open this with client_id set to whoever they chose to kick (and player_id to the player they chose them by, if any); without one it shows any vote in progress.

client_id: int | None = None
classmethod get_window_layout() → WindowLayout[source]

The layout windows browsing to this route open with.

browse() uses this unless told otherwise, so a route whose page is best shown at some layout declares it once rather than at every link.

Defaults to WIDE_TALL, a middling shape that suits most pages, short or tall, without ever being a big mostly-empty window. Pages that suit another shape ask for it: WIDE for short one-off pages (a confirmation, a dialog) and LARGE, which grows to fill more of the screen at medium/large ui-scale, for pages built to use that room (store listings and the like).

player_id: int | None = None
class bacommon.docui.routes.classichost.KickVoteCast(yes: bool)[source]

Bases: ClassicHostRoute

Vote in the kick vote in progress.

yes: bool
class bacommon.docui.routes.classichost.KickVoteStart(client_id: int, player_id: int | None = None)[source]

Bases: ClassicHostRoute

Start a vote to kick a client.

client_id: int
player_id: int | None = None
class bacommon.docui.routes.classichost.Player(player_id: int)[source]

Bases: ClassicHostRoute

One player in the game, by their session player id.

How they’re doing, who they’re playing as, and kicking them.

classmethod get_window_layout() → WindowLayout[source]

The layout windows browsing to this route open with.

browse() uses this unless told otherwise, so a route whose page is best shown at some layout declares it once rather than at every link.

Defaults to WIDE_TALL, a middling shape that suits most pages, short or tall, without ever being a big mostly-empty window. Pages that suit another shape ask for it: WIDE for short one-off pages (a confirmation, a dialog) and LARGE, which grows to fill more of the screen at medium/large ui-scale, for pages built to use that room (store listings and the like).

player_id: int
bacommon.docui.routes.classichost.SHOW_ACCOUNT_BUILD = 23075

First engine build that runs ShowAccount from host pages (older ones ignore host local-actions; the button then does nothing).

class bacommon.docui.routes.classichost.ShowAccount(account_id: str)[source]

Bases: ClassicHostLocalAction

Open an account’s page from the master server, over this one.

(See bacommon.docui.routes.classicaccount.Account; backing out of it returns to the host page.) Only presses can do it. Builds before SHOW_ACCOUNT_BUILD ignore it.

account_id: str

The account (a-XXX).

class bacommon.docui.routes.classichost.Stats[source]

Bases: ClassicHostRoute

Who is in the party and how their connections are doing.

bacommon.docui.routes.classicinbox module

Routes for the classic inbox doc-ui domain.

The inbox lists an account’s messages (rewards, notices, tournament results) as cards; responding to one – claiming a reward, accepting or declining – posts back and gets the updated list in return.

class bacommon.docui.routes.classicinbox.InboxLocalAction[source]

Bases: DocUILocalActionBase

Family class for classic inbox local-actions.

classmethod get_action_types() → tuple[type[DocUILocalActionBase], ...][source]

Return all concrete local-actions in this family.

Must be overridden by each family class; see get_route_types().

class bacommon.docui.routes.classicinbox.InboxRoute[source]

Bases: DocUIRoute

Family class for classic inbox routes.

classmethod get_route_types() → tuple[type[DocUIRoute], ...][source]

Return all concrete routes in this family.

Must be overridden by each family class. A family generally defines a union alias of its routes (which also gives handlers assert_never exhaustiveness) and returns family_members() of it here.

classmethod get_window_layout() → WindowLayout[source]

The layout windows browsing to this route open with.

browse() uses this unless told otherwise, so a route whose page is best shown at some layout declares it once rather than at every link.

Defaults to WIDE_TALL, a middling shape that suits most pages, short or tall, without ever being a big mostly-empty window. Pages that suit another shape ask for it: WIDE for short one-off pages (a confirmation, a dialog) and LARGE, which grows to fill more of the screen at medium/large ui-scale, for pages built to use that room (store listings and the like).

class bacommon.docui.routes.classicinbox.OpenUrl(url: str)[source]

Bases: InboxLocalAction

Open a url in the platform’s browser.

url: str
class bacommon.docui.routes.classicinbox.Respond(entry_id: str, positive: bool = True)[source]

Bases: InboxRoute

Respond to one message (claim it, accept or decline it, etc.).

Answered with the updated inbox, with any effects of the response (reward animations, sounds) attached. Shares the inbox’s own path so the client treats the answer as the same page updated (holding its scroll position) rather than a new one.

entry_id: str

The message.

positive: bool = True

Whether this is the message’s positive response (claim, accept, ok) as opposed to its negative one (decline).

class bacommon.docui.routes.classicinbox.Root(debug: bool = False)[source]

Bases: InboxRoute

The inbox: every message, newest first.

debug: bool = False

Draw bounds and other debug bits.

class bacommon.docui.routes.classicinbox.TourneyScores(tournament_id: str)[source]

Bases: InboxLocalAction

Show a tournament’s final standings.

classmethod get_press_sound() → PressSound[source]

What a button plays when pressed to run this local-action.

Actions that stay on the page click (the default); override to return SWISH for ones that go somewhere (open a window or popup). A press whose action has default_sound off plays nothing either way.

tournament_id: str

bacommon.docui.routes.classicleaguepresidency module

Routes for the classic league-presidency doc-ui domain.

bacommon.docui.routes.classicleaguepresidency.AnyLeaguePresidencyLocalAction

alias of GetTokens

class bacommon.docui.routes.classicleaguepresidency.BidState(bid: int = 0)[source]

Bases: DocUIState

The presidency page’s state: the bid being composed.

Clients that speak page state carry this; older ones carry the same value as the bid arg on the routes.

bid: int = 0
class bacommon.docui.routes.classicleaguepresidency.GetTokens[source]

Bases: LeaguePresidencyLocalAction

Show the get-tokens window.

class bacommon.docui.routes.classicleaguepresidency.LeaguePresidencyLocalAction[source]

Bases: DocUILocalActionBase

Family class for classic league-presidency local-actions.

classmethod get_action_types() → tuple[type[DocUILocalActionBase], ...][source]

Return all concrete local-actions in this family.

Must be overridden by each family class; see get_route_types().

class bacommon.docui.routes.classicleaguepresidency.LeaguePresidencyRoute[source]

Bases: DocUIRoute

Family class for classic league-presidency routes.

classmethod get_route_types() → tuple[type[DocUIRoute], ...][source]

Return all concrete routes in this family.

Must be overridden by each family class. A family generally defines a union alias of its routes (which also gives handlers assert_never exhaustiveness) and returns family_members() of it here.

classmethod get_window_layout() → WindowLayout[source]

The layout windows browsing to this route open with.

browse() uses this unless told otherwise, so a route whose page is best shown at some layout declares it once rather than at every link.

Defaults to WIDE_TALL, a middling shape that suits most pages, short or tall, without ever being a big mostly-empty window. Pages that suit another shape ask for it: WIDE for short one-off pages (a confirmation, a dialog) and LARGE, which grows to fill more of the screen at medium/large ui-scale, for pages built to use that room (store listings and the like).

class bacommon.docui.routes.classicleaguepresidency.Root(bid: int = 0, debug: bool = False, season: str | None = None)[source]

Bases: LeaguePresidencyRoute

The presidency page for the account’s current league.

bid: int = 0

The bid being composed (the page’s +/- buttons adjust this). Only meaningful for clients without page state; others carry it in BidState.

debug: bool = False

Draw bounds and other debug bits.

season: str | None = None

Season the client was looking at when it opened us. Not currently used (the page always shows the current season).

class bacommon.docui.routes.classicleaguepresidency.SubmitBid(bid: int = 0, debug: bool = False)[source]

Bases: LeaguePresidencyRoute

Submit a bid.

bid: int = 0

See Root.bid.

debug: bool = False

bacommon.docui.routes.classicstore module

Routes for the classic store and inventory doc-ui domains.

The store and inventory are two domains served by a single set of pages (the inventory is essentially the store filtered to owned things plus player-profiles), so they share one route family. Each has its own local-actions.

class bacommon.docui.routes.classicstore.EditProfile(profile: str)[source]

Bases: InventoryLocalAction

Open the (legacy) profile editor on an existing profile.

classmethod get_press_sound() → PressSound[source]

What a button plays when pressed to run this local-action.

Actions that stay on the page click (the default); override to return SWISH for ones that go somewhere (open a window or popup). A press whose action has default_sound off plays nothing either way.

profile: str
class bacommon.docui.routes.classicstore.GetTokens[source]

Bases: StoreLocalAction

Show the get-tokens window.

class bacommon.docui.routes.classicstore.InventoryLocalAction[source]

Bases: DocUILocalActionBase

Family class for classic inventory local-actions.

classmethod get_action_types() → tuple[type[DocUILocalActionBase], ...][source]

Return all concrete local-actions in this family.

Must be overridden by each family class; see get_route_types().

class bacommon.docui.routes.classicstore.NewProfile[source]

Bases: InventoryLocalAction

Open the (legacy) profile editor on a new profile.

classmethod get_press_sound() → PressSound[source]

What a button plays when pressed to run this local-action.

Actions that stay on the page click (the default); override to return SWISH for ones that go somewhere (open a window or popup). A press whose action has default_sound off plays nothing either way.

class bacommon.docui.routes.classicstore.ProfileCharacter[source]

Bases: StoreRoute

(Inventory) pick the profile editor’s character.

Opened from the editor, whose ProfileDraft comes along as page state; picking one hands it back to the editor (see assign_on_return()).

classmethod get_window_layout() → WindowLayout[source]

The layout windows browsing to this route open with.

browse() uses this unless told otherwise, so a route whose page is best shown at some layout declares it once rather than at every link.

Defaults to WIDE_TALL, a middling shape that suits most pages, short or tall, without ever being a big mostly-empty window. Pages that suit another shape ask for it: WIDE for short one-off pages (a confirmation, a dialog) and LARGE, which grows to fill more of the screen at medium/large ui-scale, for pages built to use that room (store listings and the like).

class bacommon.docui.routes.classicstore.ProfileDelete(profile_name: str)[source]

Bases: StoreRoute

(Inventory) delete a stored profile.

profile_name: str
class bacommon.docui.routes.classicstore.ProfileDeleteConfirm(profile_name: str)[source]

Bases: StoreRoute

(Inventory) confirm deleting a stored profile.

Replaces the editor’s page in its window; its draft rides along as page state, so cancelling goes back to the editor with it intact.

classmethod get_window_layout() → WindowLayout[source]

The layout windows browsing to this route open with.

browse() uses this unless told otherwise, so a route whose page is best shown at some layout declares it once rather than at every link.

Defaults to WIDE_TALL, a middling shape that suits most pages, short or tall, without ever being a big mostly-empty window. Pages that suit another shape ask for it: WIDE for short one-off pages (a confirmation, a dialog) and LARGE, which grows to fill more of the screen at medium/large ui-scale, for pages built to use that room (store listings and the like).

profile_name: str
class bacommon.docui.routes.classicstore.ProfileDraft(color: tuple[float, float, float], highlight: tuple[float, float, float], name: str = '', character: str = '', icon: str = '')[source]

Bases: DocUIState

The profile editor’s working profile.

Page state for the editor and its save: what the user has composed so far. A request with no draft at all (the first visit) gets one built from the stored profile, or fresh defaults when creating; an empty name, character or icon means the same for that field.

character: str = ''
color: tuple[float, float, float]
highlight: tuple[float, float, float]
icon: str = ''
name: str = ''
class bacommon.docui.routes.classicstore.ProfileEdit(profile_name: str | None = None)[source]

Bases: StoreRoute

(Inventory) the cloud player-profile editor.

The draft being composed rides along as ProfileDraft page state; the route itself only says which stored profile (if any) is being edited.

classmethod get_window_layout() → WindowLayout[source]

The layout windows browsing to this route open with.

browse() uses this unless told otherwise, so a route whose page is best shown at some layout declares it once rather than at every link.

Defaults to WIDE_TALL, a middling shape that suits most pages, short or tall, without ever being a big mostly-empty window. Pages that suit another shape ask for it: WIDE for short one-off pages (a confirmation, a dialog) and LARGE, which grows to fill more of the screen at medium/large ui-scale, for pages built to use that room (store listings and the like).

profile_name: str | None = None

Stored profile being edited, or None when creating one.

class bacommon.docui.routes.classicstore.ProfileGlobalUpgrade(profile_name: str)[source]

Bases: StoreRoute

(Inventory) offer to upgrade a cloud profile to a global one.

Says whether the name can be had and what it costs. Like ProfileDeleteConfirm, it replaces the editor’s page in its window with the editor’s draft riding along as page state.

classmethod get_window_layout() → WindowLayout[source]

The layout windows browsing to this route open with.

browse() uses this unless told otherwise, so a route whose page is best shown at some layout declares it once rather than at every link.

Defaults to WIDE_TALL, a middling shape that suits most pages, short or tall, without ever being a big mostly-empty window. Pages that suit another shape ask for it: WIDE for short one-off pages (a confirmation, a dialog) and LARGE, which grows to fill more of the screen at medium/large ui-scale, for pages built to use that room (store listings and the like).

profile_name: str
class bacommon.docui.routes.classicstore.ProfileGlobalUpgradeBuy(profile_name: str, ticket_cost: int)[source]

Bases: StoreRoute

(Inventory) upgrade a cloud profile to a global one.

profile_name: str
ticket_cost: int

The price the offer page showed; a changed price is refused rather than silently charged.

class bacommon.docui.routes.classicstore.ProfileIcon[source]

Bases: StoreRoute

(Inventory) pick the profile editor’s icon.

Works as ProfileCharacter does: the editor’s ProfileDraft comes along as page state and the pick is handed back to it.

classmethod get_window_layout() → WindowLayout[source]

The layout windows browsing to this route open with.

browse() uses this unless told otherwise, so a route whose page is best shown at some layout declares it once rather than at every link.

Defaults to WIDE_TALL, a middling shape that suits most pages, short or tall, without ever being a big mostly-empty window. Pages that suit another shape ask for it: WIDE for short one-off pages (a confirmation, a dialog) and LARGE, which grows to fill more of the screen at medium/large ui-scale, for pages built to use that room (store listings and the like).

class bacommon.docui.routes.classicstore.ProfileMigrate(profiles_only: bool = False, debug: bool = False)[source]

Bases: StoreRoute

(Inventory) copy the account’s legacy profiles into cloud ones.

Requested by the ‘Converting profiles…’ page the root shows while a migration is due; redirects back to the root afterward (carrying the root’s view arguments along).

debug: bool = False

See Root.debug.

profiles_only: bool = False

See Root.profiles_only.

class bacommon.docui.routes.classicstore.ProfileSave(profile_name: str | None = None)[source]

Bases: StoreRoute

(Inventory) save the editor’s draft (its ProfileDraft).

profile_name: str | None = None

See ProfileEdit.profile_name.

class bacommon.docui.routes.classicstore.Purchase(purchase_id: str, debug: bool = False)[source]

Bases: StoreRoute

Purchase options for a single item.

debug: bool = False
classmethod get_window_layout() → WindowLayout[source]

The layout windows browsing to this route open with.

browse() uses this unless told otherwise, so a route whose page is best shown at some layout declares it once rather than at every link.

Defaults to WIDE_TALL, a middling shape that suits most pages, short or tall, without ever being a big mostly-empty window. Pages that suit another shape ask for it: WIDE for short one-off pages (a confirmation, a dialog) and LARGE, which grows to fill more of the screen at medium/large ui-scale, for pages built to use that room (store listings and the like).

purchase_id: str
class bacommon.docui.routes.classicstore.PurchaseConfirm(purchase_id: str, purchase_method: PurchaseMethod, debug: bool = False)[source]

Bases: StoreRoute

Actually purchase an item.

debug: bool = False
purchase_id: str
purchase_method: PurchaseMethod
class bacommon.docui.routes.classicstore.PurchaseMethod(*values)[source]

Bases: Enum

How to purchase something.

GOLD_PASS = 'g'
PURPLE_TICKETS = 'p'
TICKETS = 'k'
TOKENS = 't'
class bacommon.docui.routes.classicstore.RestorePurchases[source]

Bases: StoreLocalAction

Kick off a platform purchase-restore.

class bacommon.docui.routes.classicstore.Root(debug: bool = False, is_refresh: bool = False, legacy_profiles: bool = False, profiles_only: bool = False, unlockreqs: list[str] | None = None)[source]

Bases: StoreRoute

The main store/inventory listing.

debug: bool = False

Draw bounds and other debug bits.

classmethod get_window_layout() → WindowLayout[source]

The layout windows browsing to this route open with.

browse() uses this unless told otherwise, so a route whose page is best shown at some layout declares it once rather than at every link.

Defaults to WIDE_TALL, a middling shape that suits most pages, short or tall, without ever being a big mostly-empty window. Pages that suit another shape ask for it: WIDE for short one-off pages (a confirmation, a dialog) and LARGE, which grows to fill more of the screen at medium/large ui-scale, for pages built to use that room (store listings and the like).

is_refresh: bool = False

Set on the page’s own refresh button. One-time-use; the server does not carry it into further links.

legacy_profiles: bool = False

(Inventory) the client is showing its locally-spliced legacy profiles; omit cloud profile rows.

profiles_only: bool = False

(Inventory) render only the profiles section (the in-game profile browser).

unlockreqs: list[str] | None = None

Legacy purchase ids required to unlock something; when provided, only items providing those are shown.

bacommon.docui.routes.classicstore.SHOW_STORE_BUILD = 23074

The first build that knows ShowStore; older ones show an error for it, so don’t send it to them.

class bacommon.docui.routes.classicstore.ShowCloudProfiles[source]

Bases: InventoryLocalAction

Switch the inventory to cloud profiles.

class bacommon.docui.routes.classicstore.ShowLegacyProfiles[source]

Bases: InventoryLocalAction

Switch the inventory to the client’s legacy profiles.

class bacommon.docui.routes.classicstore.ShowStore[source]

Bases: InventoryLocalAction

Open the store at its top level, on top of the current window.

The store is a different doc-ui domain than the inventory, so inventory pages can’t simply browse to it; backing out of the store returns to the page it was opened from. Builds older than SHOW_STORE_BUILD don’t know this action.

classmethod get_press_sound() → PressSound[source]

What a button plays when pressed to run this local-action.

Actions that stay on the page click (the default); override to return SWISH for ones that go somewhere (open a window or popup). A press whose action has default_sound off plays nothing either way.

class bacommon.docui.routes.classicstore.SpawnBot(name: str)[source]

Bases: InventoryLocalAction

Spawn a character in the main-menu background.

name: str

Internal appearance name of the character.

class bacommon.docui.routes.classicstore.StoreLocalAction[source]

Bases: DocUILocalActionBase

Family class for classic store local-actions.

classmethod get_action_types() → tuple[type[DocUILocalActionBase], ...][source]

Return all concrete local-actions in this family.

Must be overridden by each family class; see get_route_types().

class bacommon.docui.routes.classicstore.StoreRoute[source]

Bases: DocUIRoute

Family class for classic store/inventory routes.

classmethod get_route_types() → tuple[type[DocUIRoute], ...][source]

Return all concrete routes in this family.

Must be overridden by each family class. A family generally defines a union alias of its routes (which also gives handlers assert_never exhaustiveness) and returns family_members() of it here.

bacommon.docui.routes.docuitest module

Routes for the doc-ui test domain.

class bacommon.docui.routes.docuitest.Animation[source]

Bases: TestRoute

Decorations animated by keyframe client-effects.

class bacommon.docui.routes.docuitest.BoundsTests[source]

Bases: TestRoute

Button-style bounds tests.

class bacommon.docui.routes.docuitest.ButtonGrids(debug: bool = False, viewer_side: ViewerSide | None = None, theme: ThemeVariant = ThemeVariant.DEFAULT)[source]

Bases: TestRoute

Grid button rows: columns, cells, alignment and navigation.

Browse to it at several layouts; grids reflow to fit each width.

debug: bool = False
theme: ThemeVariant = 'default'

See WindowLayouts.theme.

viewer_side: ViewerSide | None = None

See WindowLayouts.viewer_side.

class bacommon.docui.routes.docuitest.CloudMsgTestGet[source]

Bases: TestRoute

A page fetched through our cloud connection via GET.

class bacommon.docui.routes.docuitest.CloudMsgTestPost[source]

Bases: TestRoute

A page fetched through our cloud connection via POST.

class bacommon.docui.routes.docuitest.ControlRowKind(*values)[source]

Bases: Enum

Kinds of control row (for NavTest).

BUTTON = 'button'
CHECKBOX = 'checkbox'
CHOICE = 'choice'
COLOR = 'color'
NUMBER = 'number'
SLIDER = 'slider'
TEXT_INPUT = 'text'
class bacommon.docui.routes.docuitest.Depictions(debug: bool = False)[source]

Bases: TestRoute

Depiction tests.

debug: bool = False
class bacommon.docui.routes.docuitest.DisplayItems(debug: bool = False)[source]

Bases: TestRoute

Display-item tests.

debug: bool = False
class bacommon.docui.routes.docuitest.Drill[source]

Bases: TestRoute

The top of a drill-down; shows what was found at the bottom.

Exploring opens levels in windows of their own, several deep; picking something at the bottom closes all of them at once and hands the pick back here (see close_to()).

class bacommon.docui.routes.docuitest.DrillLevel(depth: int = 1, trail: str = '')[source]

Bases: TestRoute

One level of the drill-down, each in a window of its own.

depth: int = 1

How deep this is (1 is the first level below the top).

trail: str = ''

Doors taken to get here, in order.

class bacommon.docui.routes.docuitest.DrillState(found: str = '')[source]

Bases: DocUIState

State for the drill-down’s top page.

found: str = ''

What was picked at the bottom, handed back up (empty for nothing yet).

class bacommon.docui.routes.docuitest.EmptyPage[source]

Bases: TestRoute

A page with nothing on it.

class bacommon.docui.routes.docuitest.Flavor(*values)[source]

Bases: Enum

Something to pick from on the widgets test page.

CHOCOLATE = 'c'
MINT = 'm'
STRAWBERRY = 's'
VANILLA = 'v'
class bacommon.docui.routes.docuitest.Glyphs[source]

Bases: TestRoute

Custom glyphs against their measured bounds and anchor points.

class bacommon.docui.routes.docuitest.GlyphsState(crosshairs: bool = True, bounds: bool = True)[source]

Bases: DocUIState

What the glyphs test page draws over its glyphs.

bounds: bool = True
crosshairs: bool = True
class bacommon.docui.routes.docuitest.LayoutFit(over: bool = False, wide_over: bool = False, layout: WindowLayout = WindowLayout.WIDE_TALL, theme: ThemeVariant = ThemeVariant.DEFAULT)[source]

Bases: TestRoute

A row exactly as big as a layout promises (browse at that layout).

layout says which layout it’s being shown in. The row fills the content rect the layout promises (see bacommon.docui.v2.SMALL_CONTENT_WIDTH and friends), less the page’s insets, and should never scroll; with over / wide_over set it’s a hair taller / wider, which should scroll where the promise is exact (and may not where it’s only a minimum). Viewer layouts show a blank viewer pane, as their promises are for a page beside one.

layout: WindowLayout = 'wt'
over: bool = False
theme: ThemeVariant = 'default'

See WindowLayouts.theme. (The page keeps its own vertical inset, which its row’s size is figured from.)

wide_over: bool = False
class bacommon.docui.routes.docuitest.LiveTimes[source]

Bases: TestRoute

Time-varying text (countdowns, elapsed times) that ticks itself.

class bacommon.docui.routes.docuitest.Names(debug: bool = False)[source]

Bases: TestRoute

Name depiction tests (basic and capsule forms).

debug: bool = False
class bacommon.docui.routes.docuitest.NavTest(kind: ControlRowKind = ControlRowKind.CHECKBOX)[source]

Bases: TestRoute

A button row, then one control row of some kind as the last row.

For checking directional navigation on control rows: down from the last row should reach the toolbars, left should reach the back button, and right from a row’s rightmost control should do nothing.

kind: ControlRowKind = 'checkbox'
class bacommon.docui.routes.docuitest.NinePatch(debug: bool = False)[source]

Bases: TestRoute

9-patch image tests (stretched and tile-fit, tinted).

debug: bool = False
class bacommon.docui.routes.docuitest.Popups[source]

Bases: TestRoute

Popup windows: opening them and what they can do to this page.

class bacommon.docui.routes.docuitest.PopupsMain[source]

Bases: TestRoute, PopupRoute[PopupsState]

The main test popup: acts on its parent every way there is.

classmethod get_popup_size() → tuple[float, float][source]

Content-area size (width, height) our popups open at.

In window units (see bacommon.docui.v2.Popup.size), at least POPUP_MIN_SIZE; clients shrink whatever doesn’t fit their screen. Override to suit the page; popup() can also be told otherwise per link.

class bacommon.docui.routes.docuitest.PopupsMainState(bumps: int = 0)[source]

Bases: DocUIState

The main test popup’s own state (apart from its parent’s).

bumps: int = 0

Bumped by the popup replacing its own page.

class bacommon.docui.routes.docuitest.PopupsOther[source]

Bases: TestRoute, PopupRoute[PopupsState]

A second popup, swapped in for the first (and back).

class bacommon.docui.routes.docuitest.PopupsState(color: str = '', count: int = 0, opened_with: str = '', edge_style: ScrollEdgeStyle = ScrollEdgeStyle.FADE)[source]

Bases: DocUIState

State for the popups test page, which its popups act on.

color: str = ''

A color picked in a popup (empty for none yet).

count: int = 0

Bumped by popups replacing the page.

edge_style: ScrollEdgeStyle = 'f'

Scroll edge style for the popups this page opens.

opened_with: str = ''

Set by the button opening a popup (handed along to it).

class bacommon.docui.routes.docuitest.Root(debug: bool = False, test_effects: bool = False, test_action: bool = False)[source]

Bases: TestRoute

The root test page.

debug: bool = False

Draw bounds and other debug bits.

test_action: bool = False

Have the response include a local-action.

test_effects: bool = False

Have the response include some client-effects.

class bacommon.docui.routes.docuitest.RootState(layout: WindowLayout = WindowLayout.WIDE_TALL, viewer_side: ViewerSide | None = None, theme: ThemeVariant = ThemeVariant.DEFAULT)[source]

Bases: DocUIState

State for the root test page.

layout: WindowLayout = 'wt'

The window layout picked in its ‘Layout Test Options’ (for rows below to open their pages at), and at viewer layouts which side the viewer pane sits on (None for no pane).

theme: ThemeVariant = 'default'

The theme picked in its ‘Layout Test Options’ (for rows below to show their pages in).

viewer_side: ViewerSide | None = None
class bacommon.docui.routes.docuitest.Sections(debug: bool = False, viewer_side: ViewerSide | None = None, theme: ThemeVariant = ThemeVariant.DEFAULT)[source]

Bases: TestRoute

Sections: headings, notes, backings and spacing between them.

debug: bool = False
classmethod get_window_layout() → WindowLayout[source]

The layout windows browsing to this route open with.

browse() uses this unless told otherwise, so a route whose page is best shown at some layout declares it once rather than at every link.

Defaults to WIDE_TALL, a middling shape that suits most pages, short or tall, without ever being a big mostly-empty window. Pages that suit another shape ask for it: WIDE for short one-off pages (a confirmation, a dialog) and LARGE, which grows to fill more of the screen at medium/large ui-scale, for pages built to use that room (store listings and the like).

theme: ThemeVariant = 'default'

See WindowLayouts.theme.

viewer_side: ViewerSide | None = None

See WindowLayouts.viewer_side.

class bacommon.docui.routes.docuitest.ShowVolume[source]

Bases: TestLocalAction

Show the volume slider’s live value (fired while dragging).

class bacommon.docui.routes.docuitest.Size(*values)[source]

Bases: Enum

Something else to pick from on the widgets test page.

L = 'l'
M = 'm'
S = 's'
XL = 'x'
class bacommon.docui.routes.docuitest.Slow[source]

Bases: TestRoute

A page that takes a while to load.

class bacommon.docui.routes.docuitest.Test2[source]

Bases: TestRoute

A second simple page.

class bacommon.docui.routes.docuitest.TestAction(testparam: int)[source]

Bases: TestLocalAction

Show a message proving we got here.

testparam: int
class bacommon.docui.routes.docuitest.TestLocalAction[source]

Bases: DocUILocalActionBase

Family class for doc-ui test local-actions.

classmethod get_action_types() → tuple[type[DocUILocalActionBase], ...][source]

Return all concrete local-actions in this family.

Must be overridden by each family class; see get_route_types().

class bacommon.docui.routes.docuitest.TestRoute[source]

Bases: DocUIRoute

Family class for doc-ui test routes.

classmethod get_route_types() → tuple[type[DocUIRoute], ...][source]

Return all concrete routes in this family.

Must be overridden by each family class. A family generally defines a union alias of its routes (which also gives handlers assert_never exhaustiveness) and returns family_members() of it here.

classmethod get_window_layout() → WindowLayout[source]

The layout windows browsing to this route open with.

browse() uses this unless told otherwise, so a route whose page is best shown at some layout declares it once rather than at every link.

Defaults to WIDE_TALL, a middling shape that suits most pages, short or tall, without ever being a big mostly-empty window. Pages that suit another shape ask for it: WIDE for short one-off pages (a confirmation, a dialog) and LARGE, which grows to fill more of the screen at medium/large ui-scale, for pages built to use that room (store listings and the like).

class bacommon.docui.routes.docuitest.TextImages(debug: bool = False)[source]

Bases: TestRoute

Text-with-images tests.

debug: bool = False
class bacommon.docui.routes.docuitest.TextWrapping(debug: bool = False)[source]

Bases: TestRoute

Titles, subtitles and footnotes word-wrapped to their columns.

debug: bool = False
class bacommon.docui.routes.docuitest.ThemeVariant(*values)[source]

Bases: Enum

A look test pages can show their content in.

The page-themes test pages show each; the root page’s ‘Layout Test Options’ pick one for its ‘Layout Tests’ pages.

BUTTON_COLOR = 'button_color'
DARK = 'dark'
DEFAULT = 'default'
POPUP_LOOK = 'popup_look'
ROLE_COLORS = 'role_colors'
ROOMY = 'roomy'
TEXT_STYLES = 'text_styles'
TIGHT = 'tight'
class bacommon.docui.routes.docuitest.Themes(variant: ThemeVariant = ThemeVariant.DEFAULT)[source]

Bases: TestRoute

Page themes: the same content shown with various look values.

classmethod get_window_layout() → WindowLayout[source]

The layout windows browsing to this route open with.

browse() uses this unless told otherwise, so a route whose page is best shown at some layout declares it once rather than at every link.

Defaults to WIDE_TALL, a middling shape that suits most pages, short or tall, without ever being a big mostly-empty window. Pages that suit another shape ask for it: WIDE for short one-off pages (a confirmation, a dialog) and LARGE, which grows to fill more of the screen at medium/large ui-scale, for pages built to use that room (store listings and the like).

variant: ThemeVariant = 'default'
class bacommon.docui.routes.docuitest.ThemesPopup(variant: ThemeVariant = ThemeVariant.DEFAULT)[source]

Bases: TestRoute, PopupRoute[ThemesState]

The page-themes sample content in a popup.

classmethod get_popup_size() → tuple[float, float][source]

Content-area size (width, height) our popups open at.

In window units (see bacommon.docui.v2.Popup.size), at least POPUP_MIN_SIZE; clients shrink whatever doesn’t fit their screen. Override to suit the page; popup() can also be told otherwise per link.

variant: ThemeVariant = 'default'
class bacommon.docui.routes.docuitest.ThemesState(checked: bool = False)[source]

Bases: DocUIState

State for the page-themes test pages (and their popups).

checked: bool = False

Backs the sample checkbox.

class bacommon.docui.routes.docuitest.TimedActions(val: int = 5)[source]

Bases: TestRoute

A page that counts down via timed-actions and then closes.

val: int = 5
class bacommon.docui.routes.docuitest.Viewers(case: str = '')[source]

Bases: TestRoute

Live viewer tests: good cases and bad data, one shown at a time.

The page’s own controls switch cases, and the pane’s style and side (page state), in place.

case: str = ''

Which case the viewer pane shows (a test-page case name; unknown names show the first).

classmethod get_window_layout() → WindowLayout[source]

The layout windows browsing to this route open with.

browse() uses this unless told otherwise, so a route whose page is best shown at some layout declares it once rather than at every link.

Defaults to WIDE_TALL, a middling shape that suits most pages, short or tall, without ever being a big mostly-empty window. Pages that suit another shape ask for it: WIDE for short one-off pages (a confirmation, a dialog) and LARGE, which grows to fill more of the screen at medium/large ui-scale, for pages built to use that room (store listings and the like).

class bacommon.docui.routes.docuitest.WebTestGet[source]

Bases: TestRoute

A page fetched from a web server via GET.

class bacommon.docui.routes.docuitest.WebTestPost[source]

Bases: TestRoute

A page fetched from a web server via POST.

class bacommon.docui.routes.docuitest.WidgetTestState(plain: bool = False, live: bool = False, checked_disabled: bool = True, unchecked_disabled: bool = False, presses: int = 0, text_short: str = '', text_medium: str = 'Some text', text_long: str = '', text_live: str = '', text_disabled: str = 'Not editable', flavor: Flavor = Flavor.VANILLA, flavor_live: Flavor = Flavor.VANILLA, size: Size = Size.M, size_long: Size = Size.M, topping: Flavor | None = None, difficulty: str = 'normal', region: str | None = None, flavor_disabled: Flavor = Flavor.CHOCOLATE, topping_disabled: Flavor | None = None, difficulty_disabled: str = 'hard', region_disabled: str | None = 'eu', volume: float = 0.5, volume_disabled: float = 0.3, series_length: float = 7.0, series_length_disabled: float = 5.0, tint: tuple[float, float, float] = (0.5, 0.25, 1.0), tint_disabled: tuple[float, float, float] = (1.0, 0.6, 0.1), spacing_top_demo: bool = False, spacing_bottom_demo: bool = False, bands_demo: bool = False)[source]

Bases: DocUIState

State for the widgets test page.

bands_demo: bool = False
checked_disabled: bool = True

Disabled checkboxes (selectable; not toggleable), one checked and one not.

difficulty: str = 'normal'

Choices over an arbitrary string set (the page defines the options, not an enum); plain and optional.

difficulty_disabled: str = 'hard'
flavor: Flavor = 'v'

Choices, plain and live.

flavor_disabled: Flavor = 'c'

Disabled choice rows (selectable; menus won’t open), one of each form: enum, optional enum, str, optional str.

flavor_live: Flavor = 'v'
live: bool = False

A checkbox that re-requests the page when changed.

plain: bool = False

A checkbox with no on-change action.

presses: int = 0

Nothing shows or edits this directly; it simply rides along (and gets bumped by a button).

region: str | None = None
region_disabled: str | None = 'eu'
series_length: float = 7.0

A number-row value shaped like a series length – 1-21 by 2.

series_length_disabled: float = 5.0

A disabled number row (selectable; not adjustable).

size: Size = 'm'

Short choice labels (a compact button) and an absurdly long one.

size_long: Size = 'm'
spacing_bottom_demo: bool = False
spacing_top_demo: bool = False

Checkboxes on rows demonstrating control-row spacing and header / footer bands (they drive nothing).

text_disabled: str = 'Not editable'

A disabled text input (selectable; not editable).

text_live: str = ''

A text input that re-requests the page when an edit is committed.

text_long: str = ''
text_medium: str = 'Some text'
text_short: str = ''

Text inputs with labels of assorted lengths.

tint: tuple[float, float, float] = (0.5, 0.25, 1.0)

An rgb color, edited via the color-picker popup.

tint_disabled: tuple[float, float, float] = (1.0, 0.6, 0.1)

A disabled color row (selectable; picker won’t open).

topping: Flavor | None = None

An optional choice – a ‘nothing’ option ahead of the flavors.

topping_disabled: Flavor | None = None
unchecked_disabled: bool = False
volume: float = 0.5

A slider value shaped like the sound-settings ones – 0-1 by 0.05.

volume_disabled: float = 0.3

A disabled slider (selectable; not adjustable).

class bacommon.docui.routes.docuitest.Widgets(debug: bool = False, viewer_side: ViewerSide | None = None, theme: ThemeVariant = ThemeVariant.DEFAULT)[source]

Bases: TestRoute

Control rows and page state.

debug: bool = False
theme: ThemeVariant = 'default'

See WindowLayouts.theme.

viewer_side: ViewerSide | None = None

See WindowLayouts.viewer_side.

class bacommon.docui.routes.docuitest.WindowLayouts(debug: bool = False, layout: WindowLayout | None = None, viewer_side: ViewerSide | None = None, theme: ThemeVariant = ThemeVariant.DEFAULT)[source]

Bases: TestRoute

Assorted rows for judging window layouts (browse to it at each).

Control rows, titles and button rows at every alignment, and long rows, which in a narrow column scroll within it.

debug: bool = False
layout: WindowLayout | None = None

The layout we’re being browsed to at, for the page to name (the browse sets the actual layout; this is just for show).

theme: ThemeVariant = 'default'

The theme to show the page in (its frame colors come with the link that opens it).

viewer_side: ViewerSide | None = None

Which side the page’s viewer pane (a turning punch powerup box) sits on at viewer layouts, or None for a page with no viewer (its rows then span the window). Ignored at other layouts.