Python SDK: Allow objects with the __html__ protocol to be used for merge_fragments (#837)
* Allow objects with the __html__ protocol to be used for merge_fragments * Clarify what HasHtml is for with a docstring
This commit is contained in:
parent
b758fb3e06
commit
3c5974c2e1
|
@ -1,16 +1,2 @@
|
||||||
from typing import override
|
from .sse import ServerSentEventGenerator
|
||||||
|
from .starlette import DatastarStreamingResponse
|
||||||
from fastcore.xml import to_xml
|
|
||||||
|
|
||||||
from .sse import SSE_HEADERS, ServerSentEventGenerator
|
|
||||||
from .starlette import DatastarStreamingResponse as _DatastarStreamingResponse
|
|
||||||
|
|
||||||
|
|
||||||
class DatastarStreamingResponse(_DatastarStreamingResponse):
|
|
||||||
@classmethod
|
|
||||||
@override
|
|
||||||
def merge_fragments(cls, fragments, *args, **kwargs):
|
|
||||||
if not isinstance(fragments, str):
|
|
||||||
fragments = to_xml(fragments)
|
|
||||||
# From here, business as usual
|
|
||||||
return super().merge_fragments(fragments, *args, **kwargs)
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import json
|
import json
|
||||||
from itertools import chain
|
from itertools import chain
|
||||||
from typing import Optional
|
from typing import Optional, Protocol, Union, runtime_checkable
|
||||||
|
|
||||||
import datastar_py.consts as consts
|
import datastar_py.consts as consts
|
||||||
|
|
||||||
|
@ -11,6 +11,17 @@ SSE_HEADERS = {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@runtime_checkable
|
||||||
|
class _HtmlProvider(Protocol):
|
||||||
|
"""A type that produces text ready to be placed in an HTML document.
|
||||||
|
|
||||||
|
This is a convention used by html producing/consuming libraries. This lets
|
||||||
|
e.g. fasthtml fasttags, or htpy elements, be passed straight in to
|
||||||
|
merge_fragments."""
|
||||||
|
|
||||||
|
def __html__(self) -> str: ...
|
||||||
|
|
||||||
|
|
||||||
class ServerSentEventGenerator:
|
class ServerSentEventGenerator:
|
||||||
__slots__ = ()
|
__slots__ = ()
|
||||||
|
|
||||||
|
@ -38,13 +49,15 @@ class ServerSentEventGenerator:
|
||||||
@classmethod
|
@classmethod
|
||||||
def merge_fragments(
|
def merge_fragments(
|
||||||
cls,
|
cls,
|
||||||
fragments: str,
|
fragments: Union[str, _HtmlProvider],
|
||||||
selector: Optional[str] = None,
|
selector: Optional[str] = None,
|
||||||
merge_mode: Optional[consts.FragmentMergeMode] = None,
|
merge_mode: Optional[consts.FragmentMergeMode] = None,
|
||||||
use_view_transition: bool = consts.DEFAULT_FRAGMENTS_USE_VIEW_TRANSITIONS,
|
use_view_transition: bool = consts.DEFAULT_FRAGMENTS_USE_VIEW_TRANSITIONS,
|
||||||
event_id: Optional[int] = None,
|
event_id: Optional[int] = None,
|
||||||
retry_duration: int = consts.DEFAULT_SSE_RETRY_DURATION,
|
retry_duration: int = consts.DEFAULT_SSE_RETRY_DURATION,
|
||||||
):
|
):
|
||||||
|
if isinstance(fragments, _HtmlProvider):
|
||||||
|
fragments = fragments.__html__()
|
||||||
data_lines = []
|
data_lines = []
|
||||||
if merge_mode:
|
if merge_mode:
|
||||||
data_lines.append(f"data: {consts.MERGE_MODE_DATALINE_LITERAL} {merge_mode}")
|
data_lines.append(f"data: {consts.MERGE_MODE_DATALINE_LITERAL} {merge_mode}")
|
||||||
|
|
Loading…
Reference in New Issue