Represents a CDDL type definition.
| 414 | |
| 415 | @dataclass |
| 416 | class CddlTypeDefinition: |
| 417 | """Represents a CDDL type definition.""" |
| 418 | |
| 419 | module: str |
| 420 | name: str |
| 421 | fields: dict[str, str] = field(default_factory=dict) |
| 422 | description: str = "" |
| 423 | |
| 424 | def to_python_dataclass(self, enhancements: dict[str, Any] | None = None) -> str: |
| 425 | """Generate Python dataclass code for this type. |
| 426 | |
| 427 | Args: |
| 428 | enhancements: Dictionary containing dataclass_methods and method_docstrings |
| 429 | """ |
| 430 | enhancements = enhancements or {} |
| 431 | dataclass_methods = enhancements.get("dataclass_methods", {}) |
| 432 | method_docstrings = enhancements.get("method_docstrings", {}) |
| 433 | |
| 434 | # Generate class name from type name (keep it as-is, don't split on underscores) |
| 435 | class_name = self.name |
| 436 | code = "@dataclass\n" |
| 437 | code += f"class {class_name}:\n" |
| 438 | class_docstrings = enhancements.get("class_docstrings", {}) |
| 439 | class_doc = _docstring_text(class_docstrings.get(class_name), class_name, self.description) |
| 440 | code += _emit_docstring(class_doc, 4) |
| 441 | code += "\n" |
| 442 | |
| 443 | if not self.fields: |
| 444 | code += " pass\n" |
| 445 | else: |
| 446 | for field_name, field_type in self.fields.items(): |
| 447 | # Convert CDDL type to Python type |
| 448 | python_type = self._get_python_type(field_type) |
| 449 | snake_name = CddlCommand._camel_to_snake(field_name) |
| 450 | |
| 451 | # Check if the CDDL field type is a quoted string literal (e.g., type: "key") |
| 452 | # These are discriminant fields: auto-populate and exclude from __init__ |
| 453 | # so callers don't need to pass them as positional or keyword arguments. |
| 454 | literal_match = re.match(r'^"([^"]+)"$', field_type.strip()) |
| 455 | if literal_match: |
| 456 | literal_value = literal_match.group(1) |
| 457 | code += f' {snake_name}: str = field(default="{literal_value}", init=False)\n' |
| 458 | # Check if this field is a list type (using lowercase 'list[' from Python 3.10+ syntax) |
| 459 | elif python_type.startswith("list["): |
| 460 | # Remove the trailing ' | None' from list types since default_factory=list ensures non-None |
| 461 | type_annotation = python_type.replace(" | None", "") |
| 462 | code += f" {snake_name}: {type_annotation} = field(default_factory=list)\n" |
| 463 | # Check if this field is a dict type (using lowercase 'dict[' from Python 3.10+ syntax) |
| 464 | elif python_type.startswith("dict["): |
| 465 | # Remove the trailing ' | None' from dict types since default_factory=dict ensures non-None |
| 466 | type_annotation = python_type.replace(" | None", "") |
| 467 | code += f" {snake_name}: {type_annotation} = field(default_factory=dict)\n" |
| 468 | else: |
| 469 | code += f" {snake_name}: {python_type} = None\n" |
| 470 | |
| 471 | # Add custom methods if defined for this class |
| 472 | if class_name in dataclass_methods: |
| 473 | code += "\n" |