|
17 | 17 | import json |
18 | 18 | import logging |
19 | 19 | import textwrap |
| 20 | +from collections.abc import Iterator |
20 | 21 | from itertools import accumulate |
21 | 22 | from pathlib import Path |
22 | 23 | from pprint import pformat |
| 24 | +from types import SimpleNamespace |
23 | 25 | from typing import Any |
24 | 26 |
|
25 | 27 | import datasets |
@@ -502,3 +504,58 @@ def create_lerobot_dataset_card( |
502 | 504 | template_path=str(card_template_path), |
503 | 505 | **kwargs, |
504 | 506 | ) |
| 507 | + |
| 508 | + |
| 509 | +class IterableNamespace(SimpleNamespace): |
| 510 | + """ |
| 511 | + A namespace object that supports both dictionary-like iteration and dot notation access. |
| 512 | + Automatically converts nested dictionaries into IterableNamespaces. |
| 513 | +
|
| 514 | + This class extends SimpleNamespace to provide: |
| 515 | + - Dictionary-style iteration over keys |
| 516 | + - Access to items via both dot notation (obj.key) and brackets (obj["key"]) |
| 517 | + - Dictionary-like methods: items(), keys(), values() |
| 518 | + - Recursive conversion of nested dictionaries |
| 519 | +
|
| 520 | + Args: |
| 521 | + dictionary: Optional dictionary to initialize the namespace |
| 522 | + **kwargs: Additional keyword arguments passed to SimpleNamespace |
| 523 | +
|
| 524 | + Examples: |
| 525 | + >>> data = {"name": "Alice", "details": {"age": 25}} |
| 526 | + >>> ns = IterableNamespace(data) |
| 527 | + >>> ns.name |
| 528 | + 'Alice' |
| 529 | + >>> ns.details.age |
| 530 | + 25 |
| 531 | + >>> list(ns.keys()) |
| 532 | + ['name', 'details'] |
| 533 | + >>> for key, value in ns.items(): |
| 534 | + ... print(f"{key}: {value}") |
| 535 | + name: Alice |
| 536 | + details: IterableNamespace(age=25) |
| 537 | + """ |
| 538 | + |
| 539 | + def __init__(self, dictionary: dict[str, Any] = None, **kwargs): |
| 540 | + super().__init__(**kwargs) |
| 541 | + if dictionary is not None: |
| 542 | + for key, value in dictionary.items(): |
| 543 | + if isinstance(value, dict): |
| 544 | + setattr(self, key, IterableNamespace(value)) |
| 545 | + else: |
| 546 | + setattr(self, key, value) |
| 547 | + |
| 548 | + def __iter__(self) -> Iterator[str]: |
| 549 | + return iter(vars(self)) |
| 550 | + |
| 551 | + def __getitem__(self, key: str) -> Any: |
| 552 | + return vars(self)[key] |
| 553 | + |
| 554 | + def items(self): |
| 555 | + return vars(self).items() |
| 556 | + |
| 557 | + def values(self): |
| 558 | + return vars(self).values() |
| 559 | + |
| 560 | + def keys(self): |
| 561 | + return vars(self).keys() |
0 commit comments