mirror of
https://github.com/rio-labs/rio.git
synced 2026-05-06 11:29:38 -05:00
add missing docstrings
This commit is contained in:
@@ -15,6 +15,7 @@ from pathlib import Path
|
||||
|
||||
import langcodes
|
||||
import pytz
|
||||
import revel
|
||||
import starlette.datastructures
|
||||
|
||||
import rio
|
||||
@@ -23,6 +24,7 @@ from .. import (
|
||||
assets,
|
||||
data_models,
|
||||
language_info,
|
||||
nice_traceback,
|
||||
routing,
|
||||
session,
|
||||
text_style,
|
||||
@@ -253,9 +255,13 @@ class AbstractAppServer(abc.ABC):
|
||||
) -> t.Iterable[text_style.FontFace]:
|
||||
font_faces = list[text_style.FontFace]()
|
||||
|
||||
async for font_face in font._get_faces():
|
||||
self.weakly_host_asset(font_face.file)
|
||||
font_faces.append(font_face)
|
||||
try:
|
||||
async for font_face in font._get_faces():
|
||||
self.weakly_host_asset(font_face.file)
|
||||
font_faces.append(font_face)
|
||||
except Exception as error:
|
||||
revel.error(f"Failed to load font faces of {font!r}:")
|
||||
nice_traceback.print_exception(error)
|
||||
|
||||
return font_faces
|
||||
|
||||
|
||||
@@ -97,6 +97,20 @@ AccessibilityRole = t.Literal[
|
||||
|
||||
@dataclasses.dataclass
|
||||
class ComponentResizeEvent:
|
||||
"""
|
||||
Holds information regarding a component resize event.
|
||||
|
||||
This is a simple dataclass that stores useful information for when the size
|
||||
of a component changes. You'll typically receive this as argument in
|
||||
`@rio.event.on_resize` events.
|
||||
|
||||
## Attributes
|
||||
|
||||
`width`: The new width of the component.
|
||||
|
||||
`height`: The new height of the component.
|
||||
"""
|
||||
|
||||
width: float
|
||||
height: float
|
||||
|
||||
|
||||
+2
-14
@@ -20,7 +20,6 @@ import introspection
|
||||
import ordered_set
|
||||
import revel
|
||||
import starlette.datastructures
|
||||
import typing_extensions as te
|
||||
import unicall
|
||||
import unicall.json_rpc
|
||||
from identity_containers import IdentityDefaultDict, IdentitySet
|
||||
@@ -48,7 +47,7 @@ from . import (
|
||||
)
|
||||
from .components import dialog_container, fundamental_component, root_components
|
||||
from .data_models import BuildData, UnittestComponentLayout
|
||||
from .observables.dataclass import Dataclass
|
||||
from .observables.dataclass import RioDataclassMeta
|
||||
from .observables.observable_property import AttributeBinding
|
||||
from .observables.session_attachments import SessionAttachments
|
||||
from .observables.session_property import SessionProperty
|
||||
@@ -69,7 +68,7 @@ class WontSerialize(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class Session(unicall.Unicall, Dataclass):
|
||||
class Session(unicall.Unicall, metaclass=RioDataclassMeta):
|
||||
"""
|
||||
Represents a single client connection to the app.
|
||||
|
||||
@@ -467,17 +466,6 @@ class Session(unicall.Unicall, Dataclass):
|
||||
# *after* all the other Session initialization (like loading user
|
||||
# settings) is done.
|
||||
|
||||
# This method is inherited from dataclasses but not meant to be public
|
||||
@te.override
|
||||
def bind(self, *args, **kwargs) -> t.NoReturn:
|
||||
"""
|
||||
## Metadata
|
||||
|
||||
`public`: False
|
||||
"""
|
||||
|
||||
raise AttributeError()
|
||||
|
||||
async def _refresh_whenever_necessary(self) -> None:
|
||||
while True:
|
||||
await self._refresh_required_event.wait()
|
||||
|
||||
+34
-1
@@ -97,7 +97,23 @@ class Font(SelfSerializing):
|
||||
self._css_file: pathlib.Path | rio.URL | str | None = None
|
||||
|
||||
@staticmethod
|
||||
def from_css_file(css_file: pathlib.Path | rio.URL | str) -> Font:
|
||||
def from_css_file(css_file: pathlib.Path | rio.URL | str, /) -> Font:
|
||||
"""
|
||||
Loads a font from a CSS file. Any content other than `@font-face`
|
||||
declarations is ignored.
|
||||
|
||||
The Rio server will download the font files and rehost them. This means
|
||||
clients can use the font even if they don't have an internet connection.
|
||||
|
||||
Note that this method only creates a `Font` object, the CSS is only
|
||||
loaded and parsed once your application uses the font. If an error
|
||||
occurs during this process, it is printed to stderr.
|
||||
|
||||
## Parameters
|
||||
|
||||
`css_file`: The CSS file to load. Can be a path, a URL, or a string
|
||||
containing the CSS text.
|
||||
"""
|
||||
font = Font(b"")
|
||||
font._faces.clear()
|
||||
font._css_file = css_file
|
||||
@@ -105,6 +121,23 @@ class Font(SelfSerializing):
|
||||
|
||||
@staticmethod
|
||||
def from_google_fonts(font_name: str) -> Font:
|
||||
"""
|
||||
Loads a font from Google Fonts.
|
||||
|
||||
The Rio server will download the font files and rehost them. This means
|
||||
clients can use the font even if they don't have an internet connection,
|
||||
since they don't need to access Google Fonts themselves.
|
||||
|
||||
Note that this method only creates a `Font` object; the font files are
|
||||
only downloaded from Google Fonts once your application uses the font.
|
||||
If an error occurs during this process (for example because the font
|
||||
name is misspelled), it is printed to stderr.
|
||||
|
||||
## Parameters
|
||||
|
||||
`font_name`: The name of the font to load. Case-sensitive.
|
||||
"""
|
||||
|
||||
css_url = rio.URL("https://fonts.googleapis.com/css2").with_query(
|
||||
family=font_name
|
||||
)
|
||||
|
||||
+20
-17
@@ -217,25 +217,28 @@ def _create_class_tests(docs: imy.docstrings.ClassDocs) -> type:
|
||||
f"Attribute {attr.name!r} has no details"
|
||||
)
|
||||
|
||||
# Create tests for all members of this class
|
||||
for member in docs.members.values():
|
||||
if isinstance(member, imy.docstrings.FunctionDocs):
|
||||
# Ignore the constructor of Enums
|
||||
if member.name == "__init__" and issubclass(
|
||||
docs.object, enum.Enum
|
||||
):
|
||||
continue
|
||||
# List, Set, and Dict methods don't need to be documented, since they're
|
||||
# just clones of well-known classes.
|
||||
if docs.object not in (rio.List, rio.Set, rio.Dict):
|
||||
# Create tests for all members of this class
|
||||
for member in docs.members.values():
|
||||
if isinstance(member, imy.docstrings.FunctionDocs):
|
||||
# Ignore the constructor of Enums
|
||||
if member.name == "__init__" and issubclass(
|
||||
docs.object, enum.Enum
|
||||
):
|
||||
continue
|
||||
|
||||
test = _create_function_tests(member)
|
||||
elif isinstance(member, imy.docstrings.PropertyDocs):
|
||||
test = _create_property_tests(member)
|
||||
else:
|
||||
raise Exception(
|
||||
f"Don't know how to create tests for a {type(member).__name__} object"
|
||||
)
|
||||
test = _create_function_tests(member)
|
||||
elif isinstance(member, imy.docstrings.PropertyDocs):
|
||||
test = _create_property_tests(member)
|
||||
else:
|
||||
raise Exception(
|
||||
f"Don't know how to create tests for a {type(member).__name__} object"
|
||||
)
|
||||
|
||||
test.__name__ = f"Test<{member.name}>"
|
||||
vars()[test.__name__] = test
|
||||
test.__name__ = f"Test<{member.name}>"
|
||||
locals()[test.__name__] = test
|
||||
|
||||
return ClassTests
|
||||
|
||||
|
||||
+39
-2
@@ -2,7 +2,22 @@ import asyncio
|
||||
import typing as t
|
||||
|
||||
import rio.testing
|
||||
from rio.components import Component
|
||||
from rio.debug.layouter import Layouter
|
||||
|
||||
|
||||
class ResizeEventRecorder(rio.Component):
|
||||
recorded_events: list[rio.ComponentResizeEvent] = []
|
||||
|
||||
@rio.event.on_resize
|
||||
def on_resize(self, resize_event: rio.ComponentResizeEvent) -> None:
|
||||
self.recorded_events.append(resize_event)
|
||||
|
||||
def build(self):
|
||||
return rio.Rectangle(
|
||||
fill=rio.Color.BLUE,
|
||||
min_width=5.0,
|
||||
min_height=10.0,
|
||||
)
|
||||
|
||||
|
||||
class ChildMounter(rio.Component):
|
||||
@@ -40,7 +55,7 @@ class EventCounter(rio.Component):
|
||||
def _on_unmount(self):
|
||||
self.unmount_count += 1
|
||||
|
||||
def build(self) -> Component:
|
||||
def build(self) -> rio.Component:
|
||||
return self.child
|
||||
|
||||
|
||||
@@ -259,3 +274,25 @@ async def test_populate_dead_child():
|
||||
assert not test_client._last_updated_components, (
|
||||
"Unmounted component was sent to the frontend"
|
||||
)
|
||||
|
||||
|
||||
async def test_size_observer_reports_content_dimensions():
|
||||
async with rio.testing.BrowserClient(ResizeEventRecorder) as client:
|
||||
resize_event_recorder = client.get_component(ResizeEventRecorder)
|
||||
rectangle = client.get_component(rio.Rectangle)
|
||||
|
||||
layouter = await Layouter.create(client.session)
|
||||
recorder_layout = layouter.get_layout_is(resize_event_recorder)
|
||||
rectangle_layout = layouter.get_layout_is(rectangle)
|
||||
assert (
|
||||
recorder_layout.allocated_outer_width
|
||||
== rectangle_layout.allocated_outer_width
|
||||
)
|
||||
assert (
|
||||
recorder_layout.allocated_outer_height
|
||||
== rectangle_layout.allocated_outer_height
|
||||
)
|
||||
|
||||
event = resize_event_recorder.recorded_events[-1]
|
||||
assert event.width == recorder_layout.allocated_outer_width
|
||||
assert event.height == recorder_layout.allocated_outer_height
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
import rio.testing
|
||||
from rio.debug.layouter import Layouter
|
||||
|
||||
|
||||
class ResizeEventRecorder(rio.Component):
|
||||
recorded_events: list[rio.ComponentResizeEvent] = []
|
||||
|
||||
@rio.event.on_resize
|
||||
def on_resize(self, resize_event: rio.ComponentResizeEvent) -> None:
|
||||
self.recorded_events.append(resize_event)
|
||||
|
||||
def build(self):
|
||||
return rio.Rectangle(
|
||||
fill=rio.Color.BLUE,
|
||||
min_width=5.0,
|
||||
min_height=10.0,
|
||||
)
|
||||
|
||||
|
||||
async def test_size_observer_reports_content_dimensions():
|
||||
async with rio.testing.BrowserClient(ResizeEventRecorder) as client:
|
||||
resize_event_recorder = client.get_component(ResizeEventRecorder)
|
||||
rectangle = client.get_component(rio.Rectangle)
|
||||
|
||||
layouter = await Layouter.create(client.session)
|
||||
recorder_layout = layouter.get_layout_is(resize_event_recorder)
|
||||
rectangle_layout = layouter.get_layout_is(rectangle)
|
||||
assert (
|
||||
recorder_layout.allocated_outer_width
|
||||
== rectangle_layout.allocated_outer_width
|
||||
)
|
||||
assert (
|
||||
recorder_layout.allocated_outer_height
|
||||
== rectangle_layout.allocated_outer_height
|
||||
)
|
||||
|
||||
event = resize_event_recorder.recorded_events[-1]
|
||||
assert event.width == recorder_layout.allocated_outer_width
|
||||
assert event.height == recorder_layout.allocated_outer_height
|
||||
Reference in New Issue
Block a user