|
5 | 5 |
|
6 | 6 | from __future__ import annotations |
7 | 7 |
|
8 | | -from typing import Any, Dict, Iterable, List, Mapping, Optional, Sequence, Tuple, Union |
| 8 | +from typing import Any, Iterable, List, Mapping, Optional, Sequence, Tuple, Union |
9 | 9 |
|
10 | 10 | from fastjsonschema import compile as compile_json_schema |
11 | 11 | from mypy_extensions import TypedDict |
@@ -119,10 +119,9 @@ def vdom( |
119 | 119 | tag: |
120 | 120 | The type of element (e.g. 'div', 'h1', 'img') |
121 | 121 | attributes_and_children: |
122 | | - Attribute mappings followed by iterables of children for the element. The |
123 | | - attributes **must** precede the children, though you may pass multiple sets |
124 | | - of attributes, or children which will be merged into their respective parts |
125 | | - of the model. |
| 122 | + An optional attribute mapping followed by any number of children or |
| 123 | + iterables of children. The attribute mapping **must** precede the children, |
| 124 | + or children which will be merged into their respective parts of the model. |
126 | 125 | key: |
127 | 126 | A string idicating the identity of a particular element. This is significant |
128 | 127 | to preserve event handlers across updates - without a key, a re-render would |
@@ -201,26 +200,22 @@ def constructor( |
201 | 200 |
|
202 | 201 |
|
203 | 202 | def coalesce_attributes_and_children( |
204 | | - attributes_and_children: _AttributesAndChildrenArg, |
205 | | -) -> Tuple[Dict[str, Any], List[Any]]: |
206 | | - attributes: Dict[str, Any] = {} |
207 | | - children: List[Any] = [] |
| 203 | + values: Sequence[Any], |
| 204 | +) -> Tuple[Mapping[str, Any], List[Any]]: |
| 205 | + if not values: |
| 206 | + return {}, [] |
| 207 | + |
| 208 | + children_or_iterables: Sequence[Any] |
| 209 | + attributes, *children_or_iterables = values |
| 210 | + if not isinstance(attributes, Mapping) or "tagName" in attributes: |
| 211 | + attributes = {} |
| 212 | + children_or_iterables = values |
208 | 213 |
|
209 | | - began_children = False |
210 | | - for argument in attributes_and_children: |
211 | | - if isinstance(argument, Mapping): |
212 | | - if "tagName" not in argument: |
213 | | - if began_children: |
214 | | - raise ValueError("Attribute dictionaries should precede children.") |
215 | | - attributes.update(argument) |
216 | | - else: |
217 | | - children.append(argument) |
218 | | - began_children = True |
219 | | - elif not isinstance(argument, str) and isinstance(argument, Iterable): |
220 | | - children.extend(argument) |
221 | | - began_children = True |
| 214 | + children: List[Any] = [] |
| 215 | + for child in children_or_iterables: |
| 216 | + if isinstance(child, (str, Mapping)) or not hasattr(child, "__iter__"): |
| 217 | + children.append(child) |
222 | 218 | else: |
223 | | - children.append(argument) |
224 | | - began_children = True |
| 219 | + children.extend(child) |
225 | 220 |
|
226 | 221 | return attributes, children |
0 commit comments