update import convention for dataclasses & abc

This commit is contained in:
Jakob Pinterits
2025-01-19 13:36:37 +01:00
parent 1ed819ae6d
commit d022586b0e
74 changed files with 319 additions and 278 deletions
+74 -46
View File
@@ -7,10 +7,10 @@ Rio even better. Ready to jump in? We recommend checking out the
how things work. All our code lives on GitHub, so you can easily see what's
happening and get involved.
**Quick tip:** Chatting on discord with a maintainer before diving into a big
pull request can save you time. That way, you can make sure your idea aligns
with Rio's goals! Every contribution goes through the same fair review process,
no matter who submits it.
**Quick tip:** [A quick chat on discord](https://discord.gg/7ejXaPwhyH) with a
maintainer before diving into a big pull request can save you time. That way,
you can make sure your idea aligns with Rio's goals! We're very active on
discord - you can expect to get an answer in minutes when we aren't asleep.
## Feature Requests
@@ -18,20 +18,12 @@ Feature Requests by the community are highly encouraged. Feel free to submit a
new one or upvote an existing feature request on [Github
Discussions](https://github.com/rio-labs/rio/discussions/categories/feature-requests).
## Code of Conduct
This project, and everyone participating in it, are governed by Rio's Code of
Conduct. By participating, you are expected to uphold it. Make sure to read the
full text to understand which type of actions may or may not be tolerated.
## Bugs
Rio is using [GitHub issues](https://github.com/rio-labs/rio/issues) to manage
bugs. We keep a close eye on them. Before filing a new issue, try to ensure your
problem does not already exist.
<hr style="border:2px solid gray">
## Before Submitting a Pull Request
The Rio core team will review your pull request and either merge it, request
@@ -39,17 +31,17 @@ changes, or close it.
### Prerequisites
- You have [Python](https://www.python.org/) at `version 3.10 or higher`
installed.
- You have [Rye](https://rye.astral.sh/) at `version 0.33.0 or higher`
installed.
- You have [Node.js](https://nodejs.org/) at `version 20.0 or higher` installed.
- You are familiar with [Git](https://git-scm.com/).
- You have [Python](https://www.python.org/) version 3.10 or higher
installed
- You have [Rye](https://rye.astral.sh/) version 0.33.0 or higher
installed
- You have [Node.js](https://nodejs.org/) version 20.0 or higher installed
- You are familiar with [Git](https://git-scm.com/)
### Project structure
- `frontend/` - TypeScript code for the Rio frontend
- `raw-icons` - In addition to the official material icons, Rio ships with some
- `raw-icons/` - In addition to the official material icons, Rio ships with some
of its own. This directory contains any and all custom icons.
- `rio/` - Python code for the Rio backend
- `scripts/` - Contains scripts which are tangentially related to Rio, but not
@@ -59,10 +51,6 @@ changes, or close it.
### Development Setup
While Rio allows users to write apps in 100% Python, Rio itself has both a
Python and a TypeScript component. In order to get started using Rio from the
repository, you'll have to build the typescript Component as well.
### 1. Fork the repository
[Go to the repository](https://github.com/rio-labs/rio) and fork it using your
@@ -99,20 +87,24 @@ before creating commits:
python -m pre_commit install
```
While Rio allows users to write apps in 100% Python, Rio itself has both a
Python and a TypeScript component. In order to get started using Rio from the
repository, you'll have to build the typescript Component first
Install dev dependencies using `npm`:
```bash
npm install
```
Some developers have reported that they must explicitly import `sass`. If you
run into issues, try running:
The previous command doesn't reliably install `sass` for some reason. To be
on the safe side, install it manually:
```bash
npm install sass
```
Build the frontend:
Now build the frontend:
```bash
rye run dev-build
@@ -130,18 +122,18 @@ To avoid this, we've decided on a few conventions used throughout Rio:
etc., NOT past tense (`on_changed`, `on_moved`).
- Whenever a value has physical units attached, prefer to use SI base units. For
example, measure time in seconds, not milliseconds.
example, durations are measured in seconds, not milliseconds.
Occasionally it can make sense to break this rule. For example, when
configuring how long a cache lasts, users will have a hard time understanding
a duration of days, when expressed in seconds. If you do decide to use a
different unit, always make that clear, by including the unit in the name
(e.g. `cache_duration_days`).
configuring how long a cache lasts, users will have a hard time
understanding a duration on the order of days expressed in seconds. If you
do decide to use a different unit, always make that clear, by including the
unit in the name (e.g. `cache_duration_in_days`).
Sometimes the library/language you're in already has a well established class
for this. For example, in Python the built-in `timedelta` class would be
preferable to all of the above. This way times can be expressed in any unit
the user prefers.
Sometimes the library/language you're in already has a well established
class for this. For example, in Python the built-in `timedelta` class would
be preferable to all of the above. This way times can be expressed in any
unit the user prefers.
- Avoid negatives. For example, use `is_visible` instead of `is_hidden`. Nobody
likes to think around corners. Here's some more examples
@@ -150,8 +142,8 @@ To avoid this, we've decided on a few conventions used throughout Rio:
- `is_sensitive` instead of `is_insensitive`
- `is_active` instead of `is_disabled`
Along the same lines, **absolutely avoid double negatives**. Never, ever, ever
use names like `is_not_hidden` or `dont_hide_something`.
Along the same lines, **absolutely avoid double negatives**. Never, ever,
ever use names like `is_not_hidden` or `dont_hide_something`.
- Python code follows Python naming conventions, such as all_lower_case for
variables and functions, and CamelCase for classes.
@@ -170,14 +162,50 @@ To avoid this, we've decided on a few conventions used throughout Rio:
that don't stick to this convention. Feel free to report and/or change them if
you spot any.
## Reporting Issues
- _In general,_ avoid importing values from modules. Import the modules
themselves, then include the module name when accessing values. Also avoid
renaming modules when imported.
Before submitting an issue, please check the existing issues to see if your
issue has already been reported. If it has, please add a comment to the existing
issue instead of creating a new one.
```python
# Do this
import traceback
traceback.print_exc()
- You are experiencing a technical issue with Rio.
- Your issue title is concise, on-topic, and polite.
- You provide steps to reproduce the issue.
- Make sure the issue template is respected.
- Make sure your issue body is readable and [well formatted](https://docs.github.com/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax).
# Not this
from traceback import print_exc
print_exc()
# Or this
import traceback as tb
tb.print_exc()
```
A little bit of verbosity beats having to constantly think about whether a
value is available as `foo` or `foo.bar` in each file.
This has limits however. Some modules, types & functions are so common that
the rules above can lead to unreadable code. Here are some conventions that
have been established over time:
```python
# These are fine, and encouraged
from __future__ import annotations
from datetime import datetime, timezone, timedelta
from pathlib import Path
import typing as t
import typing_extensions as te
import numpy as np
import pandas as pd
import polars as pl
# In Rio projects specifically
import components as comps
```
- **Use type hints!** They don't take long to type, but help out **you**, anyone
else reading your code, and most importantly, your type checker. They really
pay off in the long run. Not to mention that they force you to think about
your data models a bit more critically, leading to better code.
+2 -2
View File
@@ -7,11 +7,11 @@ exceptions and rescheduling the job for the future.
from __future__ import annotations
import asyncio
import dataclasses
import inspect
import logging
import time
import typing as t
from dataclasses import dataclass
from datetime import datetime, timedelta, timezone
import rio
@@ -80,7 +80,7 @@ async def _call_sync_or_async_function(
return result # type: ignore
@dataclass
@dataclasses.dataclass
class ScheduledJob:
"""
A job that has been scheduled.
+9 -9
View File
@@ -3,19 +3,19 @@ Pretty-strings a traceback. The result looks very similar to Python's default,
but is colored and just tweaked in general.
"""
import dataclasses
import html
import io
import linecache
import sys
import traceback
import typing as t
from dataclasses import dataclass
from pathlib import Path
import revel
@dataclass
@dataclasses.dataclass
class FormatStyle:
bold: str
nobold: str
@@ -121,20 +121,20 @@ def _format_single_exception_raw(
frame is tb_list[-1]
and hasattr(frame, "colno")
and hasattr(frame, "end_colno")
and frame.colno is not None
and frame.end_colno is not None
and frame.colno is not None # type: ignore
and frame.end_colno is not None # type: ignore
):
if (
hasattr(frame, "end_lineno")
and frame.end_lineno is not None
and frame.end_lineno > frame.lineno
and frame.end_lineno is not None # type: ignore
and frame.end_lineno > frame.lineno # type: ignore
):
end_col = len(source_line) - 1 # -1 to exclude the \n
else:
end_col = frame.end_colno
end_col = frame.end_colno # type: ignore
before = style.escape(source_line[: frame.colno].lstrip())
error = style.escape(source_line[frame.colno : end_col])
before = style.escape(source_line[: frame.colno].lstrip()) # type: ignore
error = style.escape(source_line[frame.colno : end_col]) # type: ignore
after = style.escape(source_line[end_col:].rstrip())
formatted_line = (
f"{before}{style.red}{error}{style.nored}{after}"
+3 -3
View File
@@ -1,4 +1,4 @@
from dataclasses import dataclass
import dataclasses
from pathlib import Path
@@ -6,7 +6,7 @@ class Event:
pass
@dataclass
@dataclasses.dataclass
class FileChanged(Event):
"""
A file in the project has changed, necessitating a reload.
@@ -18,7 +18,7 @@ class FileChanged(Event):
path_to_file: Path
@dataclass
@dataclasses.dataclass
class StopRequested(Event):
"""
Request a shutdown of the running project.
+2 -2
View File
@@ -1,12 +1,12 @@
from __future__ import annotations
import asyncio
import dataclasses
import sys
import typing as t
import warnings
import weakref
from collections import defaultdict
from dataclasses import field
import introspection
import typing_extensions as te
@@ -29,7 +29,7 @@ C = t.TypeVar("C", bound="rio.Component")
# `@te.dataclass_transform`, so we'll annotate it again...
@te.dataclass_transform(
eq_default=False,
field_specifiers=(internal_field, field),
field_specifiers=(internal_field, dataclasses.field),
)
class ComponentMeta(RioDataclassMeta):
# Cache for the set of all `StateProperty` instances in this class
+2 -2
View File
@@ -1,7 +1,7 @@
from __future__ import annotations
import dataclasses
import typing as t
from dataclasses import KW_ONLY
import rio
@@ -115,7 +115,7 @@ class Sidebar(component.Component):
class AppRoot(component.Component):
_: KW_ONLY
_: dataclasses.KW_ONLY
fallback_build: t.Callable[[], rio.Component] | None = None
_sidebar_is_open: bool = False
+3 -4
View File
@@ -3,7 +3,6 @@ from __future__ import annotations
import dataclasses
import enum
import typing as t
from dataclasses import KW_ONLY, dataclass, is_dataclass
import rio
@@ -17,7 +16,7 @@ def prettify_name(name: str) -> str:
return " ".join(p.title() for p in parts)
@dataclass
@dataclasses.dataclass
class AutoFormChangeEvent:
field_name: str
value: t.Any
@@ -33,12 +32,12 @@ class AutoForm(component.Component):
"""
value: t.Any
_: KW_ONLY
_: dataclasses.KW_ONLY
on_change: rio.EventHandler[[AutoFormChangeEvent]] = None
def __post_init__(self) -> None:
# Make sure the passed value is a dataclass
if not is_dataclass(self.value):
if not dataclasses.is_dataclass(self.value):
raise TypeError(
f"The value to `AutoForm` must be a dataclass, not `{type(self.value)}`"
)
+2 -2
View File
@@ -1,7 +1,7 @@
from __future__ import annotations
import dataclasses
import typing as t
from dataclasses import KW_ONLY
import rio
@@ -88,7 +88,7 @@ class Banner(component.Component):
text: str | None
style: t.Literal["info", "success", "warning", "danger"]
_: KW_ONLY
_: dataclasses.KW_ONLY
markdown: bool = False
icon: str | None = None
+3 -3
View File
@@ -1,7 +1,7 @@
from __future__ import annotations
import dataclasses
import typing as t
from dataclasses import KW_ONLY
from uniserde import JsonDoc
@@ -110,7 +110,7 @@ class Button(Component):
"""
content: str | rio.Component = ""
_: KW_ONLY
_: dataclasses.KW_ONLY
icon: str | None = None
shape: t.Literal["pill", "rounded", "rectangle"] = "pill"
style: t.Literal[
@@ -204,7 +204,7 @@ class Button(Component):
class _ButtonInternal(FundamentalComponent):
_: KW_ONLY
_: dataclasses.KW_ONLY
on_press: rio.EventHandler[[]]
content: rio.Component
shape: t.Literal["pill", "rounded", "rectangle", "circle"]
+3 -3
View File
@@ -1,7 +1,7 @@
from __future__ import annotations
import dataclasses
import typing as t
from dataclasses import KW_ONLY, dataclass
from datetime import date
import imy.docstrings
@@ -19,7 +19,7 @@ __all__ = [
@t.final
@imy.docstrings.mark_constructor_as_private
@dataclass
@dataclasses.dataclass
class DateChangeEvent:
"""
Holds information regarding a date change event.
@@ -104,7 +104,7 @@ class Calendar(FundamentalComponent):
value: date
_: KW_ONLY
_: dataclasses.KW_ONLY
on_change: rio.EventHandler[DateChangeEvent] = None
+2 -2
View File
@@ -1,7 +1,7 @@
from __future__ import annotations
import dataclasses
import typing as t
from dataclasses import KW_ONLY
from uniserde import JsonDoc
@@ -103,7 +103,7 @@ class Card(FundamentalComponent):
"""
content: rio.Component
_: KW_ONLY
_: dataclasses.KW_ONLY
corner_radius: float | tuple[float, float, float, float] | None = None
on_press: rio.EventHandler[[]] = None
ripple: bool | None = None
+3 -3
View File
@@ -1,7 +1,7 @@
from __future__ import annotations
import dataclasses
import typing as t
from dataclasses import KW_ONLY, dataclass
import imy.docstrings
from uniserde import JsonDoc
@@ -18,7 +18,7 @@ __all__ = [
@t.final
@imy.docstrings.mark_constructor_as_private
@dataclass
@dataclasses.dataclass
class CheckboxChangeEvent:
"""
Holds information regarding a checkbox change event.
@@ -102,7 +102,7 @@ class Checkbox(FundamentalComponent):
"""
is_on: bool = False
_: KW_ONLY
_: dataclasses.KW_ONLY
is_sensitive: bool = True
on_change: rio.EventHandler[CheckboxChangeEvent] = None
+2 -2
View File
@@ -1,5 +1,5 @@
import dataclasses
import typing as t
from dataclasses import KW_ONLY
from .. import deprecations
from .fundamental_component import FundamentalComponent
@@ -48,7 +48,7 @@ class CodeBlock(FundamentalComponent):
code: str
_: KW_ONLY
_: dataclasses.KW_ONLY
language: str | None = None
show_controls: bool = True
+3 -3
View File
@@ -1,7 +1,7 @@
from __future__ import annotations
import dataclasses
import typing as t
from dataclasses import KW_ONLY, dataclass
import imy.docstrings
from uniserde import JsonDoc
@@ -18,7 +18,7 @@ __all__ = [
@t.final
@imy.docstrings.mark_constructor_as_private
@dataclass
@dataclasses.dataclass
class ColorChangeEvent:
"""
Holds information regarding a color change event.
@@ -98,7 +98,7 @@ class ColorPicker(FundamentalComponent):
"""
color: rio.Color
_: KW_ONLY
_: dataclasses.KW_ONLY
pick_opacity: bool = False
on_change: rio.EventHandler[ColorChangeEvent] = None
+2 -2
View File
@@ -1,9 +1,9 @@
from __future__ import annotations
import abc
import dataclasses
import io
import typing as t
from dataclasses import KW_ONLY
from pathlib import Path
import typing_extensions as te
@@ -206,7 +206,7 @@ class Component(abc.ABC, metaclass=ComponentMeta):
bottom-aligned.
"""
_: KW_ONLY
_: dataclasses.KW_ONLY
key: str | int | None = internal_field(default=None, init=True)
min_width: float = 0
+3 -3
View File
@@ -1,8 +1,8 @@
from __future__ import annotations
import dataclasses
import random
import typing as t
from dataclasses import KW_ONLY, dataclass
from datetime import date, datetime
import imy.docstrings
@@ -20,7 +20,7 @@ __all__ = [
@t.final
@imy.docstrings.mark_constructor_as_private
@dataclass
@dataclasses.dataclass
class DateConfirmEvent:
"""
Holds information regarding a date confirm event.
@@ -129,7 +129,7 @@ class DateInput(Component):
value: date
_: KW_ONLY
_: dataclasses.KW_ONLY
label: str = ""
accessibility_label: str = ""
+4 -2
View File
@@ -1,10 +1,10 @@
from __future__ import annotations
import concurrent.futures
import dataclasses
import subprocess
import tempfile
import typing as t
from dataclasses import field
from pathlib import Path
import rio
@@ -30,7 +30,9 @@ class DevelComponent(FundamentalComponent):
`public`: False
"""
children: t.Sequence[rio.Component] = field(default_factory=list)
children: t.Sequence[rio.Component] = dataclasses.field(
default_factory=list
)
def __init__(
self,
+3 -3
View File
@@ -1,7 +1,7 @@
from __future__ import annotations
import dataclasses
import typing as t
from dataclasses import KW_ONLY, dataclass
import imy.docstrings
from uniserde import JsonDoc
@@ -18,7 +18,7 @@ __all__ = [
@t.final
@imy.docstrings.mark_constructor_as_private
@dataclass
@dataclasses.dataclass
class DrawerOpenOrCloseEvent:
"""
Holds information regarding a drawer open or close event.
@@ -113,7 +113,7 @@ class Drawer(FundamentalComponent):
anchor: rio.Component
content: rio.Component
_: KW_ONLY
_: dataclasses.KW_ONLY
on_open_or_close: rio.EventHandler[DrawerOpenOrCloseEvent] = None
side: t.Literal["left", "right", "top", "bottom"] = "left"
is_modal: bool = True
+3 -3
View File
@@ -1,7 +1,7 @@
from __future__ import annotations
import dataclasses
import typing as t
from dataclasses import KW_ONLY, dataclass
import imy.docstrings
from uniserde import JsonDoc
@@ -21,7 +21,7 @@ T = t.TypeVar("T")
@t.final
@imy.docstrings.mark_constructor_as_private
@dataclass
@dataclasses.dataclass
class DropdownChangeEvent(t.Generic[T]):
"""
Holds information regarding a dropdown change event.
@@ -126,7 +126,7 @@ class Dropdown(FundamentalComponent, t.Generic[T]):
"""
options: t.Mapping[str, T]
_: KW_ONLY
_: dataclasses.KW_ONLY
label: str
style: t.Literal["underlined", "rounded", "pill"]
selected_value: T | utils.NotGiven = utils.NOT_GIVEN
+6 -4
View File
@@ -1,8 +1,8 @@
from __future__ import annotations
import dataclasses
import logging
import typing as t
from dataclasses import dataclass, field
import imy.docstrings
from uniserde import JsonDoc
@@ -20,7 +20,7 @@ __all__ = [
@t.final
@imy.docstrings.mark_constructor_as_private
@dataclass
@dataclasses.dataclass
class FilePickEvent:
"""
Holds information regarding a file upload event.
@@ -99,8 +99,10 @@ class FilePickerArea(FundamentalComponent):
if not t.TYPE_CHECKING:
# At most one of these is set, the other `None`. If both are `None`, the
# component will display a default message.
child_text: str | None = field(default=None, init=False)
child_component: rio.Component | None = field(default=None, init=False)
child_text: str | None = dataclasses.field(default=None, init=False)
child_component: rio.Component | None = dataclasses.field(
default=None, init=False
)
# The serializer can't handle Union types. Override the constructor, so it
# splits the content into two values
+2 -2
View File
@@ -1,7 +1,7 @@
from __future__ import annotations
import dataclasses
import typing as t
from dataclasses import KW_ONLY
import typing_extensions as te
from uniserde import JsonDoc
@@ -53,7 +53,7 @@ class FlowContainer(FundamentalComponent):
"""
children: list[rio.Component]
_: KW_ONLY
_: dataclasses.KW_ONLY
spacing: float | None
row_spacing: float | None
column_spacing: float | None
+3 -3
View File
@@ -1,8 +1,8 @@
from __future__ import annotations
import dataclasses
import math
import typing as t
from dataclasses import KW_ONLY, dataclass
import typing_extensions as te
from uniserde import JsonDoc
@@ -15,7 +15,7 @@ __all__ = ["Grid"]
@t.final
@dataclass
@dataclasses.dataclass
class GridChildPosition:
row: int
column: int
@@ -89,7 +89,7 @@ class Grid(FundamentalComponent):
```
"""
_: KW_ONLY
_: dataclasses.KW_ONLY
row_spacing: float
column_spacing: float
+2 -2
View File
@@ -1,7 +1,7 @@
from __future__ import annotations
import dataclasses
import typing as t
from dataclasses import KW_ONLY
from pathlib import Path
from uniserde import JsonDoc
@@ -83,7 +83,7 @@ class Icon(FundamentalComponent):
"""
icon: str
_: KW_ONLY
_: dataclasses.KW_ONLY
fill: _IconFill
@staticmethod
+2 -2
View File
@@ -1,7 +1,7 @@
from __future__ import annotations
import dataclasses
import typing as t
from dataclasses import KW_ONLY
from uniserde import JsonDoc
@@ -108,7 +108,7 @@ class IconButton(Component):
"""
icon: str
_: KW_ONLY
_: dataclasses.KW_ONLY
style: t.Literal["major", "minor", "colored-text", "plain-text", "plain"]
color: rio.ColorSet
is_sensitive: bool
+2 -2
View File
@@ -1,7 +1,7 @@
from __future__ import annotations
import dataclasses
import typing as t
from dataclasses import KW_ONLY
from uniserde import Jsonable, JsonDoc
@@ -112,7 +112,7 @@ class Image(FundamentalComponent):
"""
image: ImageLike
_: KW_ONLY
_: dataclasses.KW_ONLY
fill_mode: t.Literal["fit", "stretch", "zoom"] = "fit"
on_error: EventHandler[[]] = None
corner_radius: float | tuple[float, float, float, float] = 0
+3 -3
View File
@@ -1,7 +1,7 @@
from __future__ import annotations
import dataclasses
import typing as t
from dataclasses import KW_ONLY, dataclass
import imy.docstrings
from uniserde import Jsonable
@@ -568,7 +568,7 @@ ModifierKey = t.Literal["alt", "control", "meta", "shift"]
_MODIFIERS = ("control", "shift", "alt", "meta")
@dataclass(frozen=True)
@dataclasses.dataclass(frozen=True)
class _KeyUpDownEvent:
"""
Holds information about a key event.
@@ -662,7 +662,7 @@ class KeyEventListener(KeyboardFocusableFundamentalComponent):
"""
content: rio.Component
_: KW_ONLY
_: dataclasses.KW_ONLY
on_key_down: rio.EventHandler[KeyDownEvent] = None
on_key_up: rio.EventHandler[KeyUpEvent] = None
on_key_press: rio.EventHandler[KeyPressEvent] = None
+2 -2
View File
@@ -1,7 +1,7 @@
from __future__ import annotations
import dataclasses
import typing as t
from dataclasses import field
import typing_extensions as te
@@ -42,7 +42,7 @@ class LabeledColumn(Component):
`public`: False
"""
_child_list: list[Component] = field(init=False)
_child_list: list[Component] = dataclasses.field(init=False)
def __init__(
self,
+2 -2
View File
@@ -1,5 +1,5 @@
import dataclasses
import typing as t
from dataclasses import KW_ONLY
from uniserde import JsonDoc
@@ -66,7 +66,7 @@ class Markdown(FundamentalComponent):
'''
text: str
_: KW_ONLY
_: dataclasses.KW_ONLY
default_language: str | None = None
selectable: bool = True
justify: t.Literal["left", "right", "center", "justify"] = "left"
+8 -8
View File
@@ -1,8 +1,8 @@
from __future__ import annotations
import dataclasses
import enum
import typing as t
from dataclasses import KW_ONLY, dataclass
import imy.docstrings
from uniserde import JsonDoc
@@ -34,12 +34,12 @@ class MouseButton(enum.Enum):
RIGHT = "right"
@dataclass
@dataclasses.dataclass
class _ButtonEvent:
button: MouseButton
@dataclass
@dataclasses.dataclass
class _PositionedEvent:
"""
## Attributes
@@ -57,7 +57,7 @@ class _PositionedEvent:
@t.final
@imy.docstrings.mark_constructor_as_private
@dataclass
@dataclasses.dataclass
class PressEvent(_ButtonEvent, _PositionedEvent):
"""
Holds information regarding a mouse press event.
@@ -74,7 +74,7 @@ class PressEvent(_ButtonEvent, _PositionedEvent):
@t.final
@imy.docstrings.mark_constructor_as_private
@dataclass
@dataclasses.dataclass
class MouseDownEvent(_ButtonEvent, _PositionedEvent):
"""
Holds information regarding a mouse down event.
@@ -91,7 +91,7 @@ class MouseDownEvent(_ButtonEvent, _PositionedEvent):
@t.final
@imy.docstrings.mark_constructor_as_private
@dataclass
@dataclasses.dataclass
class MouseUpEvent(_ButtonEvent, _PositionedEvent):
"""
Holds information regarding a mouse up event.
@@ -142,7 +142,7 @@ class MouseLeaveEvent(_PositionedEvent):
"""
@dataclass
@dataclasses.dataclass
class _DragEvent(_ButtonEvent, _PositionedEvent):
"""
Holds information regarding a drag event.
@@ -244,7 +244,7 @@ class MouseEventListener(FundamentalComponent):
"""
content: rio.Component
_: KW_ONLY
_: dataclasses.KW_ONLY
on_press: rio.EventHandler[PressEvent] = None
on_mouse_down: rio.EventHandler[MouseDownEvent] = None
on_mouse_up: rio.EventHandler[MouseUpEvent] = None
+4 -4
View File
@@ -1,7 +1,7 @@
from __future__ import annotations
import dataclasses
import typing as t
from dataclasses import KW_ONLY, dataclass
import imy.docstrings
from uniserde import JsonDoc
@@ -19,7 +19,7 @@ __all__ = [
@t.final
@imy.docstrings.mark_constructor_as_private
@dataclass
@dataclasses.dataclass
class MultiLineTextInputChangeEvent:
"""
Holds information regarding a text input change event.
@@ -38,7 +38,7 @@ class MultiLineTextInputChangeEvent:
@t.final
@imy.docstrings.mark_constructor_as_private
@dataclass
@dataclasses.dataclass
class MultiLineTextInputConfirmEvent:
"""
Holds information regarding a text input confirm event.
@@ -137,7 +137,7 @@ class MultiLineTextInput(KeyboardFocusableFundamentalComponent):
"""
text: str = ""
_: KW_ONLY
_: dataclasses.KW_ONLY
label: str = ""
accessibility_label: str = ""
is_sensitive: bool = True
+5 -5
View File
@@ -1,7 +1,7 @@
from __future__ import annotations
import dataclasses
import typing as t
from dataclasses import KW_ONLY, dataclass
import imy.docstrings
@@ -27,7 +27,7 @@ _multiplier_suffixes: t.Mapping[str, int] = {
@t.final
@imy.docstrings.mark_constructor_as_private
@dataclass
@dataclasses.dataclass
class NumberInputChangeEvent:
"""
Holds information regarding a number change event.
@@ -46,7 +46,7 @@ class NumberInputChangeEvent:
@t.final
@imy.docstrings.mark_constructor_as_private
@dataclass
@dataclasses.dataclass
class NumberInputConfirmEvent:
"""
Holds information regarding a number confirm event.
@@ -65,7 +65,7 @@ class NumberInputConfirmEvent:
@t.final
@imy.docstrings.mark_constructor_as_private
@dataclass
@dataclasses.dataclass
class NumberInputFocusEvent:
"""
Holds information regarding a number input focus event.
@@ -190,7 +190,7 @@ class NumberInput(Component):
"""
value: float = 0
_: KW_ONLY
_: dataclasses.KW_ONLY
label: str = ""
accessibility_label: str = ""
style: t.Literal["underlined", "rounded", "pill"] = "underlined"
+3 -3
View File
@@ -1,7 +1,7 @@
from __future__ import annotations
import dataclasses
import typing as t
from dataclasses import KW_ONLY, field
import rio
@@ -110,7 +110,7 @@ class PageView(Component):
# TODO: Link to the routing/multipage how-to page
_: KW_ONLY
_: dataclasses.KW_ONLY
fallback_build: t.Callable[[], rio.Component] | None = None
@@ -118,7 +118,7 @@ class PageView(Component):
# for top-level PageViews, 1 for the next level, and so on.
#
# Initialized in `__post_init__`.
_level: int = field(init=False)
_level: int = dataclasses.field(init=False)
def __post_init__(self) -> None:
self.session._page_views.add(self)
+4 -4
View File
@@ -1,7 +1,7 @@
from __future__ import annotations
import dataclasses
import typing as t
from dataclasses import KW_ONLY, dataclass
import imy.docstrings
from uniserde import JsonDoc
@@ -18,7 +18,7 @@ __all__ = [
@imy.docstrings.mark_constructor_as_private
@dataclass
@dataclasses.dataclass
class PointerEvent:
"""
Holds information regarding a pointer event.
@@ -78,7 +78,7 @@ class PointerEvent:
@t.final
@imy.docstrings.mark_constructor_as_private
@dataclass
@dataclasses.dataclass
class PointerMoveEvent(PointerEvent):
"""
Holds information regarding a pointer move event.
@@ -158,7 +158,7 @@ class PointerEventListener(FundamentalComponent):
"""
content: rio.Component
_: KW_ONLY
_: dataclasses.KW_ONLY
on_press: rio.EventHandler[PointerEvent] = None
on_pointer_down: rio.EventHandler[PointerEvent] = None
on_pointer_up: rio.EventHandler[PointerEvent] = None
+2 -2
View File
@@ -1,7 +1,7 @@
from __future__ import annotations
import dataclasses
import typing as t
from dataclasses import KW_ONLY
from uniserde import JsonDoc
@@ -128,7 +128,7 @@ class Popup(FundamentalComponent):
anchor: rio.Component
content: rio.Component
_: KW_ONLY
_: dataclasses.KW_ONLY
is_open: bool = False
modal: bool = False
user_closable: bool = False
+2 -2
View File
@@ -1,7 +1,7 @@
from __future__ import annotations
import dataclasses
import typing as t
from dataclasses import KW_ONLY
from uniserde import JsonDoc
@@ -125,7 +125,7 @@ class Rectangle(FundamentalComponent):
you just want a simple rectangle.
"""
_: KW_ONLY
_: dataclasses.KW_ONLY
content: rio.Component | None = None
transition_time: float = 1.0
cursor: rio.CursorStyle = cursor_style.CursorStyle.DEFAULT
+3 -3
View File
@@ -1,7 +1,7 @@
from __future__ import annotations
import dataclasses
import typing as t
from dataclasses import KW_ONLY, dataclass
import imy.docstrings
from uniserde import JsonDoc
@@ -20,7 +20,7 @@ T = t.TypeVar("T")
@t.final
@imy.docstrings.mark_constructor_as_private
@dataclass
@dataclasses.dataclass
class RevealerChangeEvent:
"""
Holds information regarding a revealer change event.
@@ -97,7 +97,7 @@ class Revealer(FundamentalComponent):
header: str | None
content: rio.Component
_: KW_ONLY
_: dataclasses.KW_ONLY
header_style: (
t.Literal["heading1", "heading2", "heading3", "text"] | rio.TextStyle
) = "text"
+2 -2
View File
@@ -1,7 +1,7 @@
from __future__ import annotations
import dataclasses
import typing as t
from dataclasses import KW_ONLY
import rio
@@ -55,7 +55,7 @@ class ScrollContainer(FundamentalComponent):
"""
content: rio.Component
_: KW_ONLY
_: dataclasses.KW_ONLY
scroll_x: t.Literal["never", "auto", "always"] = "auto"
scroll_y: t.Literal["never", "auto", "always"] = "auto"
initial_x: float = 0
+2 -2
View File
@@ -1,7 +1,7 @@
from __future__ import annotations
import dataclasses
import typing as t
from dataclasses import KW_ONLY
from uniserde import JsonDoc
@@ -61,7 +61,7 @@ class ScrollTarget(FundamentalComponent):
id: str
content: rio.Component | None = None
_: KW_ONLY
_: dataclasses.KW_ONLY
copy_button_content: str | rio.Component | None = ""
copy_button_spacing: float = 0.5
+2 -2
View File
@@ -1,7 +1,7 @@
from __future__ import annotations
import dataclasses
import typing as t
from dataclasses import KW_ONLY
import rio
@@ -46,7 +46,7 @@ class Separator(FundamentalComponent):
```
"""
_: KW_ONLY
_: dataclasses.KW_ONLY
color: rio.Color | None = None
+2 -2
View File
@@ -1,8 +1,8 @@
from __future__ import annotations
import dataclasses
import math
import typing as t
from dataclasses import dataclass
import imy.docstrings
from uniserde import JsonDoc
@@ -19,7 +19,7 @@ __all__ = [
@t.final
@imy.docstrings.mark_constructor_as_private
@dataclass
@dataclasses.dataclass
class SliderChangeEvent:
"""
Holds information regarding a slider change event.
+2 -2
View File
@@ -1,7 +1,7 @@
from __future__ import annotations
import dataclasses
import typing as t
from dataclasses import KW_ONLY
from datetime import timedelta
from uniserde import JsonDoc
@@ -65,7 +65,7 @@ class Slideshow(FundamentalComponent):
"""
children: list[rio.Component]
_: KW_ONLY
_: dataclasses.KW_ONLY
linger_time: float
corner_radius: None | float | tuple[float, float, float, float]
+3 -3
View File
@@ -1,7 +1,7 @@
from __future__ import annotations
import dataclasses
import typing as t
from dataclasses import KW_ONLY, dataclass
import imy.docstrings
from uniserde import JsonDoc
@@ -18,7 +18,7 @@ __all__ = [
@t.final
@imy.docstrings.mark_constructor_as_private
@dataclass
@dataclasses.dataclass
class SwitchChangeEvent:
"""
Holds information regarding a switch change event.
@@ -102,7 +102,7 @@ class Switch(FundamentalComponent):
"""
is_on: bool = False
_: KW_ONLY
_: dataclasses.KW_ONLY
is_sensitive: bool = True
on_change: rio.EventHandler[SwitchChangeEvent] = None
+2 -2
View File
@@ -1,7 +1,7 @@
from __future__ import annotations
import dataclasses
import typing as t
from dataclasses import KW_ONLY
import rio
@@ -81,7 +81,7 @@ class Switcher(FundamentalComponent):
content: rio.Component | None
_: KW_ONLY
_: dataclasses.KW_ONLY
transition_time: float = 0.35
+2 -2
View File
@@ -1,7 +1,7 @@
from __future__ import annotations
import dataclasses
import typing as t
from dataclasses import dataclass
import imy.docstrings
from uniserde import JsonDoc
@@ -21,7 +21,7 @@ T = t.TypeVar("T")
@t.final
@imy.docstrings.mark_constructor_as_private
@dataclass
@dataclasses.dataclass
class SwitcherBarChangeEvent(t.Generic[T]):
"""
Holds information regarding a switcher bar change event.
+14 -8
View File
@@ -1,7 +1,7 @@
from __future__ import annotations
import dataclasses
import typing as t
from dataclasses import KW_ONLY, dataclass, field
import narwhals as nw
import typing_extensions as te
@@ -25,7 +25,7 @@ TableValue = int | float | str
@t.final
@dataclass
@dataclasses.dataclass
class TableSelection:
_table: Table
@@ -378,26 +378,32 @@ class Table(FundamentalComponent): # TODO: add more content to docstring
| numpy.ndarray
)
_: KW_ONLY
_: dataclasses.KW_ONLY
show_row_numbers: bool = True
# All headers, if present
_headers: list[str] | None = field(default=None, init=False)
_headers: list[str] | None = dataclasses.field(default=None, init=False)
# The data, as a list of columns ("column major"). This is set in
# `__post_init__`.
_columns: list[list[TableValue]] = field(default_factory=list, init=False)
_columns: list[list[TableValue]] = dataclasses.field(
default_factory=list, init=False
)
# All styles applied to the table, in the same order they were added
_styling: list[TableSelection] = field(default_factory=list, init=False)
_styling: list[TableSelection] = dataclasses.field(
default_factory=list, init=False
)
# These must be annotated, otherwise rio won't understand that tables have
# child components and won't copy over the new values when two Tables are
# reconciled.
_children: list[rio.Component] = field(default_factory=list, init=False)
_children: list[rio.Component] = dataclasses.field(
default_factory=list, init=False
)
_child_positions: list[tuple[int, int]] = field(
_child_positions: list[tuple[int, int]] = dataclasses.field(
default_factory=list, init=False
)
+3 -3
View File
@@ -1,7 +1,7 @@
from __future__ import annotations
import dataclasses
import typing as t
from dataclasses import KW_ONLY
from uniserde import JsonDoc
@@ -72,7 +72,7 @@ class Text(FundamentalComponent):
"""
text: str
_: KW_ONLY
_: dataclasses.KW_ONLY
selectable: bool = True
style: (
t.Literal["heading1", "heading2", "heading3", "text", "dim"]
@@ -97,7 +97,7 @@ class Text(FundamentalComponent):
since="0.10",
old_name="wrap",
new_name="overflow",
owner="rio.Text",
function="rio.Text",
)
if self.wrap is True:
+5 -5
View File
@@ -1,7 +1,7 @@
from __future__ import annotations
import dataclasses
import typing as t
from dataclasses import KW_ONLY, dataclass
import imy.docstrings
@@ -19,7 +19,7 @@ __all__ = [
@t.final
@imy.docstrings.mark_constructor_as_private
@dataclass
@dataclasses.dataclass
class TextInputChangeEvent:
"""
Holds information regarding a text input change event.
@@ -38,7 +38,7 @@ class TextInputChangeEvent:
@t.final
@imy.docstrings.mark_constructor_as_private
@dataclass
@dataclasses.dataclass
class TextInputConfirmEvent:
"""
Holds information regarding a text input confirm event.
@@ -57,7 +57,7 @@ class TextInputConfirmEvent:
@t.final
@imy.docstrings.mark_constructor_as_private
@dataclass
@dataclasses.dataclass
class TextInputFocusEvent:
"""
Holds information regarding a text input focus event.
@@ -161,7 +161,7 @@ class TextInput(KeyboardFocusableFundamentalComponent):
"""
text: str = ""
_: KW_ONLY
_: dataclasses.KW_ONLY
label: str = ""
accessibility_label: str = ""
style: t.Literal["underlined", "rounded", "pill"] = "underlined"
+6 -6
View File
@@ -1,7 +1,7 @@
from __future__ import annotations
import dataclasses
import typing as t
from dataclasses import dataclass
# Never import * from typing_extensions! It breaks `Any` on 3.10, preventing
# users from connecting. Ask me how I know.
@@ -13,7 +13,7 @@ import rio
__all__ = ["BuildData", "ComponentLayout", "InitialClientMessage"]
@dataclass
@dataclasses.dataclass
class BuildData:
build_result: rio.Component
@@ -25,7 +25,7 @@ class BuildData:
build_generation: int
@dataclass
@dataclasses.dataclass
class InitialClientMessage(uniserde.Serde):
# The URL the client used to connect to the website. This can be quite
# different from the URLs we see in FastAPI requests, because proxies like
@@ -150,7 +150,7 @@ class InitialClientMessage(uniserde.Serde):
# open_browser_on_startup: bool = True
@dataclass
@dataclasses.dataclass
class ComponentLayout(uniserde.Serde):
# The minimum amount of size needed by the component. The width is
# calculated first, meaning the height can depend on the width. (i.e. a
@@ -192,13 +192,13 @@ class ComponentLayout(uniserde.Serde):
parent_id: int | None
@dataclass
@dataclasses.dataclass
class UnittestComponentLayout(ComponentLayout):
# Additional, component-specific information
aux: dict[str, t.Any]
@dataclass
@dataclasses.dataclass
class UnittestClientLayoutInfo:
window_width: float
window_height: float
+2 -2
View File
@@ -1,7 +1,7 @@
from __future__ import annotations
import dataclasses
import typing as t
from dataclasses import KW_ONLY
from pathlib import Path
import rio
@@ -18,7 +18,7 @@ except Exception:
class ComponentAttributes(rio.Component):
component_id: int
_: KW_ONLY
_: dataclasses.KW_ONLY
on_switch_to_layout_view: rio.EventHandler[[]] = None
+2 -2
View File
@@ -1,6 +1,6 @@
from __future__ import annotations
from dataclasses import KW_ONLY
import dataclasses
from uniserde import JsonDoc
@@ -24,7 +24,7 @@ class ComponentTree(FundamentalComponent):
component_id: int # This can be invalid. The component must deal with it.
_: KW_ONLY
_: dataclasses.KW_ONLY
# Triggered whenever the user selects a component in the tree. The passed
# value is the component's ID.
+1 -2
View File
@@ -2,7 +2,6 @@ import dataclasses
import functools
import re
import typing as t
from dataclasses import KW_ONLY
import fuzzywuzzy.fuzz
@@ -121,7 +120,7 @@ def get_available_icons() -> list[tuple[str, str, tuple[str | None, ...]]]:
class IconsPage(rio.Component):
_: KW_ONLY
_: dataclasses.KW_ONLY
search_text: str = ""
matches: list[tuple[str, str, tuple[str | None, ...]]] = dataclasses.field(
default_factory=list
+2 -2
View File
@@ -1,7 +1,7 @@
from __future__ import annotations
import dataclasses
import typing as t
from dataclasses import KW_ONLY
from uniserde import JsonDoc
@@ -18,7 +18,7 @@ __all__ = [
class LayoutDisplay(FundamentalComponent):
component_id: int # This can be invalid. The component must deal with it.
_: KW_ONLY
_: dataclasses.KW_ONLY
max_requested_height: float = 1
on_component_change: rio.EventHandler[int] = None
+4 -4
View File
@@ -1,7 +1,7 @@
from __future__ import annotations
import dataclasses
import typing as t
from dataclasses import KW_ONLY
import rio
import rio.components.fundamental_component
@@ -15,7 +15,7 @@ class SizeControls(rio.Component):
grow: bool
min_value: float
_: KW_ONLY
_: dataclasses.KW_ONLY
on_grow_change: rio.EventHandler[bool] = None
on_min_change: rio.EventHandler[float] = None
@@ -58,7 +58,7 @@ class AlignmentControls(rio.Component):
label: str
value: float | None
_: KW_ONLY
_: dataclasses.KW_ONLY
on_change: rio.EventHandler[float | None] = None
@@ -187,7 +187,7 @@ class ActionAnchor(rio.Component):
class LayoutSubpage(rio.Component):
component_id: int
_: KW_ONLY
_: dataclasses.KW_ONLY
_layout_explainer: layout_explainer.LayoutExplainer | None = None
_explanation_is_expanded: bool = True
+2 -2
View File
@@ -1,12 +1,12 @@
import dataclasses
import types
from dataclasses import dataclass
import introspection.typing
__all__ = ["ScopedAnnotation"]
@dataclass
@dataclasses.dataclass
class ScopedAnnotation:
annotation: introspection.types.TypeAnnotation
module: types.ModuleType
+2 -2
View File
@@ -2,10 +2,10 @@ from __future__ import annotations
import collections
import copy
import dataclasses
import json
import re
import typing as t
from dataclasses import dataclass
from pathlib import Path
from uniserde import Jsonable, JsonDoc
@@ -21,7 +21,7 @@ __all__ = [
]
@dataclass
@dataclasses.dataclass
class ClientComponent:
id: int
type: str
+5 -3
View File
@@ -185,7 +185,7 @@ def on_populate(
```python
import httpx
from dataclasses import field
import dataclasses
class PypiVersionFetcher(rio.Component):
@@ -193,7 +193,7 @@ def on_populate(
# The `version` attribute is initialized to an empty
# string, which will will act as a placeholder until
# the HTTP request finishes
version: str = field(init=False, default="")
version: str = dataclasses.field(init=False, default="")
@rio.event.on_populate
async def on_populate(self):
@@ -218,7 +218,9 @@ def on_populate(
return handler
def on_unmount(handler: MethodWithNoParametersVar,) -> MethodWithNoParametersVar:
def on_unmount(
handler: MethodWithNoParametersVar,
) -> MethodWithNoParametersVar:
"""
Triggered when the component is removed from the component tree.
+7 -7
View File
@@ -1,8 +1,8 @@
from __future__ import annotations
import dataclasses
import enum
import typing as t
from dataclasses import dataclass
import fastapi
import imy.docstrings
@@ -101,7 +101,7 @@ class ExtensionEventTag(enum.Enum):
@t.final
@imy.docstrings.mark_constructor_as_private
@dataclass
@dataclasses.dataclass
class ExtensionAsFastapiEvent:
"""
Holds information regarding an extension as_fastapi event.
@@ -127,7 +127,7 @@ class ExtensionAsFastapiEvent:
@t.final
@imy.docstrings.mark_constructor_as_private
@dataclass
@dataclasses.dataclass
class ExtensionAppStartEvent:
"""
Holds information regarding an extension app start event.
@@ -150,7 +150,7 @@ class ExtensionAppStartEvent:
@t.final
@imy.docstrings.mark_constructor_as_private
@dataclass
@dataclasses.dataclass
class ExtensionAppCloseEvent:
"""
Holds information regarding an extension app close event.
@@ -173,7 +173,7 @@ class ExtensionAppCloseEvent:
@t.final
@imy.docstrings.mark_constructor_as_private
@dataclass
@dataclasses.dataclass
class ExtensionSessionStartEvent:
"""
Holds information regarding a session start event.
@@ -196,7 +196,7 @@ class ExtensionSessionStartEvent:
@t.final
@imy.docstrings.mark_constructor_as_private
@dataclass
@dataclasses.dataclass
class ExtensionSessionCloseEvent:
"""
Holds information regarding a session close event.
@@ -219,7 +219,7 @@ class ExtensionSessionCloseEvent:
@t.final
@imy.docstrings.mark_constructor_as_private
@dataclass
@dataclasses.dataclass
class ExtensionPageChangeEvent:
"""
Holds information regarding a page change event.
+6 -6
View File
@@ -1,8 +1,8 @@
from __future__ import annotations
import abc
import dataclasses
import typing as t
from abc import ABC
from dataclasses import dataclass
import typing_extensions as te
from uniserde import Jsonable
@@ -27,7 +27,7 @@ __all__ = [
since="0.8.5",
description="The `Fill` base class will be removed.",
)
class Fill(SelfSerializing, ABC):
class Fill(SelfSerializing, abc.ABC):
"""
Base class for how shapes are filled.
@@ -44,7 +44,7 @@ class Fill(SelfSerializing, ABC):
"""
@dataclass(frozen=True, eq=True)
@dataclasses.dataclass(frozen=True, eq=True)
class SolidFill(Fill):
"""
Fills a shape with a single color.
@@ -66,7 +66,7 @@ class SolidFill(Fill):
}
@dataclass(frozen=True, eq=True)
@dataclasses.dataclass(frozen=True, eq=True)
class LinearGradientFill(Fill):
"""
Fills a shape with a linear gradient.
@@ -219,7 +219,7 @@ class ImageFill(Fill):
)
@dataclass(frozen=True, eq=True)
@dataclasses.dataclass(frozen=True, eq=True)
class FrostedGlassFill(Fill):
"""
Fills a shape with a frosted glass effect.
+14 -12
View File
@@ -1,10 +1,10 @@
from __future__ import annotations
import dataclasses
import functools
import logging
import typing as t
import warnings
from dataclasses import KW_ONLY, dataclass, field
from pathlib import Path
import imy.docstrings
@@ -59,7 +59,7 @@ def _verify_url_and_parse_into_pattern(
@t.final
@dataclass(frozen=True)
@dataclasses.dataclass(frozen=True)
class Redirect:
"""
Redirects the user to a different page.
@@ -106,7 +106,7 @@ class Redirect:
# A pre-parsed URL pattern object, used to verify whether a URL matches
# this page, as well as extracting path parameters
_url_pattern: url_pattern.UrlPattern = field(init=False)
_url_pattern: url_pattern.UrlPattern = dataclasses.field(init=False)
def __post_init__(self) -> None:
vars(self).update(
@@ -121,7 +121,7 @@ class Redirect:
old_name="page_url",
new_name="url_segment",
)
@dataclass(frozen=True)
@dataclasses.dataclass(frozen=True)
class ComponentPage:
"""
A routable page in a Rio app.
@@ -211,23 +211,25 @@ class ComponentPage:
name: str
url_segment: str
build: t.Callable[..., rio.Component]
_: KW_ONLY
_: dataclasses.KW_ONLY
icon: str = DEFAULT_ICON
children: t.Sequence[ComponentPage | Redirect] = field(default_factory=list)
children: t.Sequence[ComponentPage | Redirect] = dataclasses.field(
default_factory=list
)
guard: t.Callable[[rio.GuardEvent], None | rio.URL | str] | None = None
meta_tags: dict[str, str] = field(default_factory=dict)
meta_tags: dict[str, str] = dataclasses.field(default_factory=dict)
# This is used to allow users to order pages when using the `rio.page`
# decorator. It's not public, but simply a convenient place to store this.
_page_order_: int | None = field(default=None, init=False)
_page_order_: int | None = dataclasses.field(default=None, init=False)
# A pre-parsed URL pattern object, used to verify whether a URL matches
# this page, as well as extracting path parameters
_url_pattern: url_pattern.UrlPattern = field(init=False)
_url_pattern: url_pattern.UrlPattern = dataclasses.field(init=False)
# The names of the query parameters that are passed to the `build` function
_url_parameter_parsers: t.Mapping[str, UrlParameterParser] = field(
init=False
_url_parameter_parsers: t.Mapping[str, UrlParameterParser] = (
dataclasses.field(init=False)
)
def __post_init__(self) -> None:
@@ -497,7 +499,7 @@ def _get_active_page_instances(
@t.final
@imy.docstrings.mark_constructor_as_private
@dataclass(frozen=True)
@dataclasses.dataclass(frozen=True)
class GuardEvent:
"""
Holds information regarding a guard event.
+3 -3
View File
@@ -1,9 +1,9 @@
from __future__ import annotations
import copy
import dataclasses
import json
import typing as t
from dataclasses import dataclass
import typing_extensions as te
import uniserde
@@ -47,7 +47,7 @@ AvailableTemplatesLiteral: te.TypeAlias = t.Literal[
]
@dataclass
@dataclasses.dataclass
class _TemplateConfig(uniserde.Serde):
"""
Model for parsing the JSON file which comes along with each project
@@ -79,7 +79,7 @@ class _TemplateConfig(uniserde.Serde):
theme: str | None
@dataclass
@dataclasses.dataclass
class ProjectTemplate:
"""
Project templates are stored as snippets. This class represents all
@@ -1,11 +1,11 @@
import dataclasses
import typing as t
from dataclasses import dataclass, field
from datetime import datetime, timezone
import openai # type: ignore (hidden from user)
@dataclass
@dataclasses.dataclass
class ChatMessage:
"""
A simple storage class containing all the information needed for a single
@@ -17,7 +17,7 @@ class ChatMessage:
text: str
@dataclass
@dataclasses.dataclass
class Conversation:
"""
The start of the show. This class contains a list of messages and can
@@ -25,7 +25,7 @@ class Conversation:
"""
# The entire message history
messages: list[ChatMessage] = field(default_factory=list)
messages: list[ChatMessage] = dataclasses.field(default_factory=list)
async def respond(self, client: openai.AsyncOpenAI) -> ChatMessage:
"""
@@ -1,6 +1,6 @@
from __future__ import annotations
from dataclasses import field
import dataclasses
# <additional-imports>
from datetime import datetime, timezone
@@ -32,7 +32,7 @@ class ChatPage(rio.Component):
# Since Python's dataclasses don't allow for mutable default values, we need
# to use a factory function to create a new instance of the conversation
# class.
conversation: conversation.Conversation = field(
conversation: conversation.Conversation = dataclasses.field(
default_factory=conversation.Conversation
)
@@ -1,16 +1,16 @@
from __future__ import annotations
import dataclasses
import hashlib
import os
import secrets
import uuid
from dataclasses import dataclass
from datetime import datetime, timezone
import rio
@dataclass
@dataclasses.dataclass
class UserSettings(rio.UserSettings):
"""
Model for data stored client-side for each user.
@@ -25,7 +25,7 @@ class UserSettings(rio.UserSettings):
auth_token: str
@dataclass
@dataclasses.dataclass
class UserSession:
# This ID uniquely identifies the session. It also serves as the
# authentication token for the user.
@@ -41,7 +41,7 @@ class UserSession:
valid_until: datetime
@dataclass
@dataclasses.dataclass
class AppUser:
"""
Model for a user of the application.
@@ -1,4 +1,4 @@
from dataclasses import field
import dataclasses
# <additional-imports>
from pathlib import Path
@@ -39,7 +39,7 @@ class DashboardPage(rio.Component):
"""
fetch_data_from_api: bool = False
coin_data: pd.DataFrame = field(
coin_data: pd.DataFrame = dataclasses.field(
default=pd.DataFrame(
{
"date": np.zeros(5),
@@ -1,8 +1,8 @@
import dataclasses
import typing as t
from dataclasses import dataclass
@dataclass(frozen=True)
@dataclasses.dataclass(frozen=True)
class PageLayout:
"""
Represents the layout configuration for a page.
@@ -16,7 +16,7 @@ class PageLayout:
device: t.Literal["desktop", "mobile"]
@dataclass()
@dataclasses.dataclass
class Testimonial:
"""
Class to represent a testimonial on the website.
@@ -36,7 +36,7 @@ class Testimonial:
image: str
@dataclass()
@dataclasses.dataclass
class BlogPost:
"""
Class to represent a blog post on the website.
@@ -1,10 +1,10 @@
from __future__ import annotations
import copy
from dataclasses import dataclass
import dataclasses
@dataclass
@dataclasses.dataclass
class MenuItem:
"""
MenuItem data model.
@@ -1,8 +1,9 @@
from __future__ import annotations
import dataclasses
# <additional-imports>
import datetime
from dataclasses import field
import rio
@@ -25,7 +26,7 @@ class NewTodoItemInput(rio.Component):
# This is a private field that we need for an attribute binding. We don't
# want to create a constructor parameter for this field, so we set
# `init=False`.
_title: str = field(init=False, default="")
_title: str = dataclasses.field(init=False, default="")
async def _on_confirm(
self, _: rio.TextInputConfirmEvent | None = None
@@ -1,10 +1,10 @@
import dataclasses
import datetime
from dataclasses import dataclass
import rio
@dataclass
@dataclasses.dataclass
class TodoItem:
title: str
creation_time: datetime.datetime
+2 -2
View File
@@ -1,8 +1,8 @@
from __future__ import annotations
import dataclasses
import re
import typing as t
from dataclasses import dataclass
from pathlib import Path
__all__ = [
@@ -14,7 +14,7 @@ __all__ = [
SECTION_PATTERN = re.compile(r" *#\s*<(\/?[\w-]+)>")
@dataclass
@dataclasses.dataclass
class Snippet:
# The group the snippet is in
group: str
+4 -4
View File
@@ -1,8 +1,8 @@
from __future__ import annotations
import dataclasses
import pathlib
import typing as t
from dataclasses import KW_ONLY, dataclass
from uniserde import JsonDoc
@@ -22,7 +22,7 @@ __all__ = [
_TextFill = SolidFill | LinearGradientFill | ImageFill | Color
@dataclass(frozen=True)
@dataclasses.dataclass(frozen=True)
class Font(SelfSerializing):
"""
A custom font face.
@@ -79,7 +79,7 @@ Font.ROBOTO_MONO = Font(
)
@dataclass(frozen=True)
@dataclasses.dataclass(frozen=True)
class TextStyle(SelfSerializing):
"""
A collection of styling properties for text.
@@ -107,7 +107,7 @@ class TextStyle(SelfSerializing):
`all_caps`: Whether the text is transformed to ALL CAPS or not.
"""
_: KW_ONLY
_: dataclasses.KW_ONLY
font: Font | None = None
fill: _TextFill | None = None
font_size: float = 1.0
+4 -4
View File
@@ -1,7 +1,7 @@
from __future__ import annotations
import dataclasses
import typing as t
from dataclasses import KW_ONLY, dataclass
from uniserde import Jsonable
@@ -105,7 +105,7 @@ def _make_semantic_palette(color: rio.Color) -> Palette:
@t.final
@dataclass()
@dataclasses.dataclass()
class Palette:
background: rio.Color
background_variant: rio.Color
@@ -147,7 +147,7 @@ class Palette:
@t.final
@dataclass()
@dataclasses.dataclass()
class Theme:
"""
Defines the visual style of the application.
@@ -162,7 +162,7 @@ class Theme:
stable interface.
"""
_: KW_ONLY
_: dataclasses.KW_ONLY
primary_palette: Palette
secondary_palette: Palette
+3 -3
View File
@@ -1,8 +1,8 @@
from __future__ import annotations
import copy
import dataclasses
import typing as t
from dataclasses import field
import imy.docstrings
import typing_extensions as te
@@ -85,12 +85,12 @@ class UserSettings(metaclass=RioDataclassMeta):
# set outside of any sections.
section_name: t.ClassVar[str] = ""
_rio_session_: session.Session | None = field(
_rio_session_: session.Session | None = dataclasses.field(
default=None, init=False, repr=False, compare=False
)
# Set of field names that have been modified and need to be saved
_rio_dirty_attribute_names_: set[str] = field(
_rio_dirty_attribute_names_: set[str] = dataclasses.field(
default_factory=set, init=False, repr=False, compare=False
)
+3 -3
View File
@@ -1,5 +1,6 @@
from __future__ import annotations
import dataclasses
import hashlib
import io
import mimetypes
@@ -8,7 +9,6 @@ import re
import secrets
import socket
import typing as t
from dataclasses import dataclass, field
from io import BytesIO, StringIO
from pathlib import Path
@@ -140,7 +140,7 @@ def secure_string_hash(*values: str, hash_length: int = 32) -> str:
return hasher.hexdigest()
@dataclass(frozen=True)
@dataclasses.dataclass(frozen=True)
class FileInfo:
"""
Contains information about a file.
@@ -166,7 +166,7 @@ class FileInfo:
name: str
size_in_bytes: int
media_type: str
_contents: bytes | t.IO[bytes] = field(repr=False)
_contents: bytes | t.IO[bytes] = dataclasses.field(repr=False)
def __init__(
self,
+2 -2
View File
@@ -1,10 +1,10 @@
import dataclasses
import typing as t
from dataclasses import dataclass
import typing_extensions as te
@dataclass(frozen=True)
@dataclasses.dataclass(frozen=True)
class Version:
major: int
minor: int = 0