Skip to content
This repository was archived by the owner on Sep 15, 2025. It is now read-only.

Commit a2533ec

Browse files
committed
Ensure type correctness of props in component invocations.
1 parent 1d1ca0b commit a2533ec

File tree

2 files changed

+17
-17
lines changed

2 files changed

+17
-17
lines changed

html_tstring/processor.py

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ def _substitute_style_attr(value: object) -> t.Iterable[tuple[str, str | None]]:
187187

188188
def _substitute_spread_attrs(
189189
value: object,
190-
) -> t.Iterable[tuple[str, str | t.Callable | None]]:
190+
) -> t.Iterable[tuple[str, object | None]]:
191191
"""
192192
Substitute a spread attribute based on the interpolated value.
193193
@@ -214,7 +214,7 @@ def _substitute_spread_attrs(
214214
def _substitute_attr(
215215
key: str,
216216
value: object,
217-
) -> t.Iterable[tuple[str, str | t.Callable | None]]:
217+
) -> t.Iterable[tuple[str, object | None]]:
218218
"""
219219
Substitute a single attribute based on its key and the interpolated value.
220220
@@ -230,23 +230,19 @@ def _substitute_attr(
230230

231231
# General handling for all other attributes:
232232
match value:
233-
case str():
234-
yield (key, value)
235233
case True:
236234
yield (key, None)
237235
case False | None:
238236
pass
239-
case _ if callable(value):
240-
yield (key, value)
241237
case _:
242-
yield (key, str(value))
238+
yield (key, value)
243239

244240

245241
def _substitute_attrs(
246242
attrs: dict[str, str | None], interpolations: tuple[Interpolation, ...]
247-
) -> dict[str, str | t.Callable | None]:
243+
) -> dict[str, object | None]:
248244
"""Substitute placeholders in attributes based on the corresponding interpolations."""
249-
new_attrs: dict[str, str | ComponentCallable | None] = {}
245+
new_attrs: dict[str, object | None] = {}
250246
for key, value in attrs.items():
251247
if value and value.startswith(_PLACEHOLDER_PREFIX):
252248
index = _placholder_index(value)
@@ -314,7 +310,7 @@ def _node_from_value(value: object) -> Node:
314310

315311
def _invoke_component(
316312
tag: str,
317-
new_attrs: dict[str, str | t.Callable | None],
313+
new_attrs: dict[str, object | None],
318314
new_children: list[Node],
319315
interpolations: tuple[Interpolation, ...],
320316
) -> Node:
@@ -345,6 +341,11 @@ def _invoke_component(
345341
)
346342

347343

344+
def _stringify_attrs(attrs: dict[str, object | None]) -> dict[str, str | None]:
345+
"""Convert all attribute values to strings, preserving None values."""
346+
return {k: str(v) if v is not None else None for k, v in attrs.items()}
347+
348+
348349
def _substitute_node(p_node: Node, interpolations: tuple[Interpolation, ...]) -> Node:
349350
"""Substitute placeholders in a node based on the corresponding interpolations."""
350351
match p_node:
@@ -359,10 +360,8 @@ def _substitute_node(p_node: Node, interpolations: tuple[Interpolation, ...]) ->
359360
if tag.startswith(_PLACEHOLDER_PREFIX):
360361
return _invoke_component(tag, new_attrs, new_children, interpolations)
361362
else:
362-
final_attrs = {
363-
k: str(v) if v is not None else None for k, v in new_attrs.items()
364-
}
365-
return Element(tag=tag, attrs=final_attrs, children=new_children)
363+
new_attrs = _stringify_attrs(new_attrs)
364+
return Element(tag=tag, attrs=new_attrs, children=new_children)
366365
case Fragment(children=children):
367366
new_children = _substitute_and_flatten_children(children, interpolations)
368367
return Fragment(children=new_children)

html_tstring/processor_test.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -475,12 +475,13 @@ def test_interpolated_style_attribute():
475475
# --------------------------------------------------------------------------
476476

477477

478-
# TODO: I need to get precise about the typing story here. *IS* `second`
479-
# really an `int`? After all, the processor has already substituted the
480-
# attributes, so it may be a `str` at this point.
481478
def TemplateComponent(
482479
*children: Node, first: str, second: int, third: str, **attrs: t.Any
483480
) -> Template:
481+
# Ensure type correctness of props at runtime for testing purposes
482+
assert isinstance(first, str)
483+
assert isinstance(second, int)
484+
assert isinstance(third, str)
484485
new_attrs = {
485486
"id": third,
486487
"data": {"first": first, "second": second},

0 commit comments

Comments
 (0)