| 416 | |
| 417 | |
| 418 | def validate_layout(layout, layout_value): |
| 419 | if layout is None: |
| 420 | raise exceptions.NoLayoutException( |
| 421 | """ |
| 422 | The layout was `None` at the time that `run` was called. |
| 423 | Make sure to set the `layout` attribute of your application |
| 424 | before running the server. |
| 425 | """ |
| 426 | ) |
| 427 | |
| 428 | component_ids = set() |
| 429 | |
| 430 | def _validate(value): |
| 431 | def _validate_id(comp): |
| 432 | component_id = stringify_id(getattr(comp, "id", None)) |
| 433 | if component_id and component_id in component_ids: |
| 434 | raise exceptions.DuplicateIdError( |
| 435 | f""" |
| 436 | Duplicate component id found in the initial layout: `{component_id}` |
| 437 | """ |
| 438 | ) |
| 439 | component_ids.add(component_id) |
| 440 | |
| 441 | _validate_id(value) |
| 442 | |
| 443 | for component in value._traverse(): # pylint: disable=protected-access |
| 444 | _validate_id(component) |
| 445 | |
| 446 | if isinstance(layout_value, (list, tuple)): |
| 447 | for component in layout_value: |
| 448 | if isinstance(component, (str,)): |
| 449 | continue |
| 450 | if isinstance(component, (Component,)): |
| 451 | _validate(component) |
| 452 | else: |
| 453 | raise exceptions.NoLayoutException( |
| 454 | "Only strings and components are allowed in a list layout." |
| 455 | ) |
| 456 | else: |
| 457 | _validate(layout_value) |
| 458 | |
| 459 | |
| 460 | def validate_template(template): |