-
Notifications
You must be signed in to change notification settings - Fork 1
Design
There is a lot of metaprogramming magic in the module chris.link
which enables the code everywhere else to be declarative.
The modules chris.client
and chris.models
are mostly type definitions, using the decorators of chris.link.http
to "code itself."
Everything in CUBE has links: on the base URL there are collection_links
, things like plugin instances have a link to their feed, etc. Linked
is the superclass of most classes in aiochris
.
Subclasses of Linked
can make HTTP requests to their links easily by defining methods decorated by parameterized decorators defined in the chris.link.http
module. For example:
import serde
import dataclasses
from typing import Optional
from chris.link import http
from chris.link.linked import LinkedModel
@serde.deserialize
@dataclasses.dataclass(frozen=True)
class PluginInstance(LinkedModel):
url: str # URL link of this plugin instance
feed: str # URL link to plugin instance's feed
id: int # plugin instance ID number
title: str
previous_id: Optional[int]
@http.get("feed")
async def get_feed(self) -> "Feed":
...
@http.put("url")
async def set(
self, title: Optional[str] = None, status: Optional[str] = None
) -> "PluginInstance":
...
@http.delete("url")
def delete(self) -> None:
...
The example above differs from the real chris.models.logged_in.PluginInstance
in how its fields are defined in a superclass chris.models.data.PluginInstanceData
.
The parameter to the @http.*
decorator is the name of a link in the class. These values are validated by the metaclass chris.link.linked.LinkedMeta
at the time of class definition, so that typos are caught early.
┌──────┐ │Linked│ └──┬───┘ │ ┌──────────────────┴─────────────────────┐ │ │ ┌───────────▼───────────┐ ┌────▼──────┐ │CollectionJsonApiClient│ │LinkedModel│ └──┬───────────────┬────┘ └────┬──────┘ │ │ │ │ │ │ ┌────────▼──────┐ ┌───▼───────────┐ ┌────────────────┴───┬───────────────┬──────────┐ │BaseChrisClient│ │_AdminApiClient│ │ │ │ │ └──┬──────────┬─┘ └───────────────┘ │ │ │ │ │ │ ┌───▼────────┐ ┌────────▼─────────┐ ┌───▼────┐ ┌─▼─┐ │ │ │PublicPlugin│ │PluginInstanceData│ │FeedData│ │...│ ┌───────────▼───┐ ┌───▼───────────────┐ └─────┬──────┘ └────────┬─────────┘ └───┬────┘ └─┬─┘ │AnonChrisClient│ │AuthenticatedClient│ │ │ │ │ └───────────────┘ └───┬───────────┬───┘ │ │ │ │ │ │ ┌──▼───┐ ┌──────▼───────┐ ┌─▼──┐ ┌─▼─┐ │ │ │Plugin│ │PluginInstance│ │Feed│ │...│ ┌─────▼─────┐ ┌───▼────────────┐ └──────┘ └──────────────┘ └────┘ └───┘ │ChrisClient│ │ChrisAdminClient│ └───────────┘ └────────────────┘