Skip to content

Commit

Permalink
Use AliasGenerator for camelCase serialization aliases (#296)
Browse files Browse the repository at this point in the history
  • Loading branch information
sydney-runkle committed May 2, 2024
1 parent d00bc2f commit 3f90dfb
Show file tree
Hide file tree
Showing 6 changed files with 77 additions and 72 deletions.
7 changes: 7 additions & 0 deletions src/python-fastui/fastui/base.py
@@ -0,0 +1,7 @@
from pydantic import AliasGenerator, ConfigDict
from pydantic import BaseModel as _BaseModel
from pydantic.alias_generators import to_camel


class BaseModel(_BaseModel):
model_config = ConfigDict(alias_generator=AliasGenerator(serialization_alias=to_camel))
87 changes: 43 additions & 44 deletions src/python-fastui/fastui/components/__init__.py
Expand Up @@ -12,6 +12,7 @@
from .. import class_name as _class_name
from .. import events
from .. import types as _types
from ..base import BaseModel
from .display import Details, Display
from .forms import (
Form,
Expand Down Expand Up @@ -69,7 +70,7 @@
)


class Text(_p.BaseModel, extra='forbid'):
class Text(BaseModel, extra='forbid'):
"""Text component that displays a string."""

text: str
Expand All @@ -79,7 +80,7 @@ class Text(_p.BaseModel, extra='forbid'):
"""The type of the component. Always 'Text'."""


class Paragraph(_p.BaseModel, extra='forbid'):
class Paragraph(BaseModel, extra='forbid'):
"""Paragraph component that displays a string as a paragraph."""

text: str
Expand All @@ -92,7 +93,7 @@ class Paragraph(_p.BaseModel, extra='forbid'):
"""The type of the component. Always 'Paragraph'."""


class PageTitle(_p.BaseModel, extra='forbid'):
class PageTitle(BaseModel, extra='forbid'):
"""Sets the title of the HTML page via the `document.title` property."""

text: str
Expand All @@ -102,7 +103,7 @@ class PageTitle(_p.BaseModel, extra='forbid'):
"""The type of the component. Always 'PageTitle'."""


class Div(_p.BaseModel, extra='forbid'):
class Div(BaseModel, extra='forbid'):
"""A generic container component."""

components: '_t.List[AnyComponent]'
Expand All @@ -115,7 +116,7 @@ class Div(_p.BaseModel, extra='forbid'):
"""The type of the component. Always 'Div'."""


class Page(_p.BaseModel, extra='forbid'):
class Page(BaseModel, extra='forbid'):
"""Similar to `container` in many UI frameworks, this acts as a root component for most pages."""

components: '_t.List[AnyComponent]'
Expand All @@ -128,7 +129,7 @@ class Page(_p.BaseModel, extra='forbid'):
"""The type of the component. Always 'Page'."""


class Heading(_p.BaseModel, extra='forbid'):
class Heading(BaseModel, extra='forbid'):
"""Heading component."""

text: str
Expand All @@ -137,7 +138,7 @@ class Heading(_p.BaseModel, extra='forbid'):
level: _t.Literal[1, 2, 3, 4, 5, 6] = 1
"""The level of the heading. 1 is the largest, 6 is the smallest."""

html_id: _t.Union[str, None] = _p.Field(default=None, serialization_alias='htmlId')
html_id: _t.Union[str, None] = None
"""Optional HTML ID to apply to the heading's HTML component."""

class_name: _class_name.ClassNameField = None
Expand Down Expand Up @@ -169,7 +170,7 @@ def __get_pydantic_json_schema__(
"""


class Markdown(_p.BaseModel, extra='forbid'):
class Markdown(BaseModel, extra='forbid'):
"""Markdown component that renders markdown text."""

text: str
Expand All @@ -185,7 +186,7 @@ class Markdown(_p.BaseModel, extra='forbid'):
"""The type of the component. Always 'Markdown'."""


class Code(_p.BaseModel, extra='forbid'):
class Code(BaseModel, extra='forbid'):
"""Code component that renders code with syntax highlighting."""

text: str
Expand All @@ -204,7 +205,7 @@ class Code(_p.BaseModel, extra='forbid'):
"""The type of the component. Always 'Code'."""


class Json(_p.BaseModel, extra='forbid'):
class Json(BaseModel, extra='forbid'):
"""JSON component that renders JSON data."""

value: _types.JsonData
Expand All @@ -217,18 +218,16 @@ class Json(_p.BaseModel, extra='forbid'):
"""The type of the component. Always 'JSON'."""


class Button(_p.BaseModel, extra='forbid'):
class Button(BaseModel, extra='forbid'):
"""Button component."""

text: str
"""The text to display on the button."""

on_click: _t.Union[events.AnyEvent, None] = _p.Field(default=None, serialization_alias='onClick')
on_click: _t.Union[events.AnyEvent, None] = None
"""Optional event to trigger when the button is clicked."""

html_type: _t.Union[_t.Literal['button', 'reset', 'submit'], None] = _p.Field(
default=None, serialization_alias='htmlType'
)
html_type: _t.Union[_t.Literal['button', 'reset', 'submit'], None] = None
"""Optional HTML type of the button. If None, defaults to 'button'."""

named_style: _class_name.NamedStyleField = None
Expand All @@ -241,13 +240,13 @@ class Button(_p.BaseModel, extra='forbid'):
"""The type of the component. Always 'Button'."""


class Link(_p.BaseModel, extra='forbid'):
class Link(BaseModel, extra='forbid'):
"""Link component."""

components: '_t.List[AnyComponent]'
"""List of components to render attached to the link."""

on_click: _t.Union[events.AnyEvent, None] = _p.Field(default=None, serialization_alias='onClick')
on_click: _t.Union[events.AnyEvent, None] = None
"""Optional event to trigger when the link is clicked."""

mode: _t.Union[_t.Literal['navbar', 'footer', 'tabs', 'vertical', 'pagination'], None] = None
Expand All @@ -266,7 +265,7 @@ class Link(_p.BaseModel, extra='forbid'):
"""The type of the component. Always 'Link'."""


class LinkList(_p.BaseModel, extra='forbid'):
class LinkList(BaseModel, extra='forbid'):
"""List of Link components."""

links: _t.List[Link]
Expand All @@ -282,19 +281,19 @@ class LinkList(_p.BaseModel, extra='forbid'):
"""The type of the component. Always 'LinkList'."""


class Navbar(_p.BaseModel, extra='forbid'):
class Navbar(BaseModel, extra='forbid'):
"""Navbar component used for moving between pages."""

title: _t.Union[str, None] = None
"""Optional title to display in the navbar."""

title_event: _t.Union[events.AnyEvent, None] = _p.Field(default=None, serialization_alias='titleEvent')
title_event: _t.Union[events.AnyEvent, None] = None
"""Optional event to trigger when the title is clicked. Often used to navigate to the home page."""

start_links: _t.List[Link] = _p.Field(default=[], serialization_alias='startLinks')
start_links: _t.List[Link] = []
"""List of links to render at the start of the navbar."""

end_links: _t.List[Link] = _p.Field(default=[], serialization_alias='endLinks')
end_links: _t.List[Link] = []
"""List of links to render at the end of the navbar."""

class_name: _class_name.ClassNameField = None
Expand All @@ -313,13 +312,13 @@ def __get_pydantic_json_schema__(
return json_schema


class Footer(_p.BaseModel, extra='forbid'):
class Footer(BaseModel, extra='forbid'):
"""Footer component."""

links: _t.List[Link]
"""List of links to render in the footer."""

extra_text: _t.Union[str, None] = _p.Field(default=None, serialization_alias='extraText')
extra_text: _t.Union[str, None] = None
"""Optional extra text to display in the footer."""

class_name: _class_name.ClassNameField = None
Expand All @@ -329,7 +328,7 @@ class Footer(_p.BaseModel, extra='forbid'):
"""The type of the component. Always 'Footer'."""


class Modal(_p.BaseModel, extra='forbid'):
class Modal(BaseModel, extra='forbid'):
"""Modal component that displays a modal dialog."""

title: str
Expand All @@ -341,10 +340,10 @@ class Modal(_p.BaseModel, extra='forbid'):
footer: '_t.Union[_t.List[AnyComponent], None]' = None
"""Optional list of components to render in the modal footer."""

open_trigger: _t.Union[events.PageEvent, None] = _p.Field(default=None, serialization_alias='openTrigger')
open_trigger: _t.Union[events.PageEvent, None] = None
"""Optional event to trigger when the modal is opened."""

open_context: _t.Union[events.ContextType, None] = _p.Field(default=None, serialization_alias='openContext')
open_context: _t.Union[events.ContextType, None] = None
"""Optional context to pass to the open trigger event."""

class_name: _class_name.ClassNameField = None
Expand All @@ -354,13 +353,13 @@ class Modal(_p.BaseModel, extra='forbid'):
"""The type of the component. Always 'Modal'."""


class ServerLoad(_p.BaseModel, extra='forbid'):
class ServerLoad(BaseModel, extra='forbid'):
"""A component that will be replaced by the server with the component returned by the given URL."""

path: str
"""The URL to load the component from."""

load_trigger: _t.Union[events.PageEvent, None] = _p.Field(default=None, serialization_alias='loadTrigger')
load_trigger: _t.Union[events.PageEvent, None] = None
"""Optional event to trigger when the component is loaded."""

components: '_t.Union[_t.List[AnyComponent], None]' = None
Expand All @@ -369,7 +368,7 @@ class ServerLoad(_p.BaseModel, extra='forbid'):
sse: _t.Union[bool, None] = None
"""Optional flag to enable server-sent events (SSE) for the server load."""

sse_retry: _t.Union[int, None] = _p.Field(default=None, serialization_alias='sseRetry')
sse_retry: _t.Union[int, None] = None
"""Optional time in milliseconds to retry the SSE connection."""

method: _t.Union[_t.Literal['GET', 'POST', 'PATCH', 'PUT', 'DELETE'], None] = None
Expand All @@ -379,7 +378,7 @@ class ServerLoad(_p.BaseModel, extra='forbid'):
"""The type of the component. Always 'ServerLoad'."""


class Image(_p.BaseModel, extra='forbid'):
class Image(BaseModel, extra='forbid'):
"""Image container component."""

src: str
Expand All @@ -406,15 +405,15 @@ class Image(_p.BaseModel, extra='forbid'):
'unsafe-url',
],
None,
] = _p.Field(None, serialization_alias='referrerPolicy')
] = None
"""Optional referrer policy for the image. Specifies what information to send when fetching the image.
For more info, see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy."""

loading: _t.Union[_t.Literal['eager', 'lazy'], None] = None
"""Optional loading strategy for the image."""

on_click: _t.Union[events.AnyEvent, None] = _p.Field(default=None, serialization_alias='onClick')
on_click: _t.Union[events.AnyEvent, None] = None
"""Optional event to trigger when the image is clicked."""

class_name: _class_name.ClassNameField = None
Expand All @@ -424,7 +423,7 @@ class Image(_p.BaseModel, extra='forbid'):
"""The type of the component. Always 'Image'."""


class Iframe(_p.BaseModel, extra='forbid'):
class Iframe(BaseModel, extra='forbid'):
"""Iframe component that displays content from a URL."""

src: _p.HttpUrl
Expand Down Expand Up @@ -452,7 +451,7 @@ class Iframe(_p.BaseModel, extra='forbid'):
"""The type of the component. Always 'Iframe'."""


class Video(_p.BaseModel, extra='forbid'):
class Video(BaseModel, extra='forbid'):
"""Video component that displays a video or multiple videos."""

sources: _t.List[_p.AnyUrl]
Expand Down Expand Up @@ -486,7 +485,7 @@ class Video(_p.BaseModel, extra='forbid'):
"""The type of the component. Always 'Video'."""


class FireEvent(_p.BaseModel, extra='forbid'):
class FireEvent(BaseModel, extra='forbid'):
"""Fire an event."""

event: events.AnyEvent
Expand All @@ -499,7 +498,7 @@ class FireEvent(_p.BaseModel, extra='forbid'):
"""The type of the component. Always 'FireEvent'."""


class Error(_p.BaseModel, extra='forbid'):
class Error(BaseModel, extra='forbid'):
"""Utility component used to display an error."""

title: str
Expand All @@ -508,7 +507,7 @@ class Error(_p.BaseModel, extra='forbid'):
description: str
"""The description of the error."""

status_code: _t.Union[int, None] = _p.Field(None, serialization_alias='statusCode')
status_code: _t.Union[int, None] = None
"""Optional status code of the error."""

class_name: _class_name.ClassNameField = None
Expand All @@ -527,7 +526,7 @@ def __get_pydantic_json_schema__(
return json_schema


class Spinner(_p.BaseModel, extra='forbid'):
class Spinner(BaseModel, extra='forbid'):
"""Spinner component that displays a loading spinner."""

text: _t.Union[str, None] = None
Expand All @@ -540,7 +539,7 @@ class Spinner(_p.BaseModel, extra='forbid'):
"""The type of the component. Always 'Spinner'."""


class Toast(_p.BaseModel, extra='forbid'):
class Toast(BaseModel, extra='forbid'):
"""Toast component that displays a toast message (small temporary message)."""

title: str
Expand All @@ -566,10 +565,10 @@ class Toast(_p.BaseModel, extra='forbid'):
] = None
"""Optional position of the toast."""

open_trigger: _t.Union[events.PageEvent, None] = _p.Field(default=None, serialization_alias='openTrigger')
open_trigger: _t.Union[events.PageEvent, None] = None
"""Optional event to trigger when the toast is opened."""

open_context: _t.Union[events.ContextType, None] = _p.Field(default=None, serialization_alias='openContext')
open_context: _t.Union[events.ContextType, None] = None
"""Optional context to pass to the open trigger event."""

class_name: _class_name.ClassNameField = None
Expand All @@ -579,13 +578,13 @@ class Toast(_p.BaseModel, extra='forbid'):
"""The type of the component. Always 'Toast'."""


class Custom(_p.BaseModel, extra='forbid'):
class Custom(BaseModel, extra='forbid'):
"""Custom component that allows for special data to be rendered."""

data: _types.JsonData
"""The data to render in the custom component."""

sub_type: str = _p.Field(serialization_alias='subType')
sub_type: str
"""The sub-type of the custom component."""

library: _t.Union[str, None] = None
Expand Down

0 comments on commit 3f90dfb

Please sign in to comment.