# `zerodds-idl-python`
IDL4 → **Python codegen** for ZeroDDS. Emits `@idl_struct(...)` +
`@dataclass` classes usable directly with `zerodds.IdlTopic(MyClass)`
— the encoder/decoder comes from the `zerodds-py`
runtime, this codegen only delivers the annotated classes.
Part of the [**ZeroDDS**](../../README.md) project. Safety class
**STANDARD** — `forbid(unsafe_code)`, deterministic codegen.
> **Status RC phase**: phase-2 coverage complete — struct (with
> inheritance), enum, bitmask, bitset, union, typedef, exception,
> module nesting, primitives, string, sequence. Not supported
> remain: `valuetype`, `interface`, `fixed`, `map`, `any` — these return
> a clean `IdlPythonError::Unsupported`.
---
## Quick Start
```rust
use zerodds_idl::config::ParserConfig;
use zerodds_idl_python::{PythonGenOptions, generate_python_module};
let ast = zerodds_idl::parse(
"struct Greeting { long id; string<128> text; };",
&ParserConfig::default(),
)?;
let py_src =
generate_python_module(&ast, &PythonGenOptions::default())?;
assert!(py_src.contains("@idl_struct(typename=\"Greeting\")"));
assert!(py_src.contains("@dataclass"));
assert!(py_src.contains("class Greeting:"));
# Ok::<(), Box<dyn std::error::Error>>(())
```
In the CLI, `zerodds-idlc --python -o <dir> <file.idl>` handles the
codegen. Output lands as `<basename>.py` and imports the brands
from `zerodds.idl`.
## Generated code
Input:
```idl
module sensors {
enum Quality { GOOD, DEGRADED, FAILED };
struct Reading {
long sensor_id;
double value;
Quality quality;
sequence<double> history;
};
};
```
Output (abbreviated):
```python
# SPDX-License-Identifier: Apache-2.0
# Auto-generated by `zerodds-idl-python`. Do not edit by hand.
from dataclasses import dataclass
from enum import IntEnum
from typing import List
from zerodds.idl import idl_struct, Float64, Int32
class sensors_Quality(IntEnum):
GOOD = 0
DEGRADED = 1
FAILED = 2
@idl_struct(typename="sensors::Reading")
@dataclass
class sensors_Reading:
sensor_id: Int32
value: Float64
quality: sensors_Quality
history: List[Float64]
```
Application usage:
```python
from zerodds import DomainParticipant, IdlTopic
from gen.sensors import sensors_Reading, sensors_Quality
p = DomainParticipant(domain_id=0)
topic = IdlTopic(p, sensors_Reading, "sensors")
writer = topic.create_writer()
writer.write(sensors_Reading(
sensor_id=1,
value=42.5,
quality=sensors_Quality.GOOD,
history=[40.0, 41.2, 42.5],
))
```
## Construct mapping
| `struct` | `@idl_struct(typename=...)` + `@dataclass class` |
| `struct Foo : Base` | `class Foo(Base):` (dataclass inheritance) |
| `enum` | `class X(IntEnum)` |
| `bitmask` | `class X(IntFlag)` with `member = 1 << position` |
| `bitset` | `X: TypeAlias = Int64` + `class X_Bits:` with `_SHIFT`/`_WIDTH`/`_MASK` constants per bitfield |
| `union` | `X = idl_union(typename=..., discriminator=..., cases={...}, default=...)` |
| `typedef T name` | `name: TypeAlias = T` |
| `exception` | `@idl_struct(typename=...)` + `@dataclass class X(Exception):` |
| `module M { ... }` | flat class name `M_Inner` (Python PSM, Annex B) |
| `boolean` | `bool` |
| `octet` | `Octet` (zerodds.idl brand) |
| `short`/`long`/`long long` | `Int16` / `Int32` / `Int64` |
| `unsigned short`/`unsigned long`/`unsigned long long` | `UInt16` / `UInt32` / `UInt64` |
| `int8` / `uint8` | `Int8` / `UInt8` |
| `float` / `double` / `long double` | `Float32` / `Float64` / `LongDouble` |
| `char` / `wchar` | `Char` / `WChar` |
| `string` / `wstring` (bounded or unbounded) | `String` / `WString` |
| `sequence<T>` | `List[T]` |
| `T[N]` (array) | `List[T]` (multi-dim nested) |
| Python reserved word as field name | escaped with a `_` suffix (`class` → `class_`) |
## Phase 3 (today `IdlPythonError::Unsupported`)
- `valuetype`, `interface`
- `fixed`, `map`, `any`
- union cases with `case ENUM_MEMBER:` (scoped const expression — follow-up iteration)
- union cases with binary const expressions (`case A | B:` etc.)
## Spec mapping
| OMG IDL 4.2 (ISO/IEC 19516) | §7 — construct mapping |
| OMG XTypes 1.3 Annex B (Python PSM) | class naming convention, discriminator layout |
| ZeroDDS `zerodds-py-1.0` (vendor spec) | `@idl_struct` decorator API, type-brand names |
## Features
* `default = []` — std-only.
## Stability
`1.0.0-rc.2`. The CLI and library API are stable; emitted code may still
change in details before 1.0.0-final (brand imports could be consolidated
after a code review).
## Tests
```bash
cargo test -p zerodds-idl-python
```
26 smoke tests (phase 1 + phase 2: typedef, exception, bitmask,
bitset, union, struct inheritance, module nesting for phase-2
constructs) + 1 doc-test.
## See also
- [`zerodds-idl`](../idl/README.md) — parser + AST.
- [`zerodds-py`](../py/README.md) — Python runtime with `@idl_struct` + `IdlTopic`.
- [`zerodds-idlc`](../../tools/idlc/README.md) — CLI with the `--python` flag.
- [`packaging/docker/py-runtime/`](../../packaging/docker/py-runtime/) — sandbox image.