CompilationResult.native_quil_metadata is readable, but nothing on the object it returns is:
>>> from qcs_sdk.compiler.quilc import NativeQuilMetadata
>>> m = NativeQuilMetadata([9, 0, 1, 2], 3, 4, 1, 0.5, 0.99, 2, 1.5)
>>> [a for a in dir(m) if not a.startswith("_")]
[]
>>> m.final_rewiring
AttributeError: 'qcs_sdk.compiler.quilc.NativeQuilMetadata' object has no attribute 'final_rewiring'
Verified on qcs-sdk-python 0.26.3 (latest) and 0.26.1, and still the case on main: quilc.pyi declares only __eq__, __getnewargs__, __new__ and __repr__ for the class.
It looks like an omission
In crates/lib/src/compiler/quilc.rs#L302, NativeQuilMetadata is the only pyclass in the module that has pub fields and does not pass get_all:
| pyclass |
get_all |
field visibility |
CompilationResult, PauliTerm, and 5 others |
yes |
pub |
CompilerOpts |
no |
pub(crate) |
TargetDevice |
no |
private |
NativeQuilMetadata |
no |
pub |
So the two classes that legitimately hide their fields do so by keeping them non-public, while this one declares all eight fields pub and then exposes none of them.
Why it's worth fixing
final_rewiring is the only record of how quilc relabelled logical qubits onto physical ones. Anything expressed in physical qubits has to be interpreted against it — Quil-T especially, since DELAY 0 0.0005 and frame references address physical qubits, and reasoning about a compiled program without the mapping silently targets the wrong qubit rather than failing.
The only route today is __getnewargs__()[0]. It does return a typed list[int], so this isn't blocking, but it's the pickle protocol rather than an accessor: positional, undocumented, free to change, and it yields None instead of [] for an empty rewiring. __repr__ is the alternative, which means parsing Rust Debug output.
Suggested fix
#[cfg_attr(
feature = "python",
- pyo3::pyclass(module = "qcs_sdk.compiler.quilc", eq)
+ pyo3::pyclass(module = "qcs_sdk.compiler.quilc", eq, get_all)
)]
pub struct NativeQuilMetadata {
Sibling classes also pass frozen; I've left it out here since it's a semantic change beyond adding getters, but it would match the module if you want it.
Happy to open a PR.
CompilationResult.native_quil_metadatais readable, but nothing on the object it returns is:Verified on
qcs-sdk-python0.26.3 (latest) and 0.26.1, and still the case onmain:quilc.pyideclares only__eq__,__getnewargs__,__new__and__repr__for the class.It looks like an omission
In
crates/lib/src/compiler/quilc.rs#L302,NativeQuilMetadatais the onlypyclassin the module that haspubfields and does not passget_all:get_allCompilationResult,PauliTerm, and 5 otherspubCompilerOptspub(crate)TargetDeviceNativeQuilMetadatapubSo the two classes that legitimately hide their fields do so by keeping them non-public, while this one declares all eight fields
puband then exposes none of them.Why it's worth fixing
final_rewiringis the only record of how quilc relabelled logical qubits onto physical ones. Anything expressed in physical qubits has to be interpreted against it — Quil-T especially, sinceDELAY 0 0.0005and frame references address physical qubits, and reasoning about a compiled program without the mapping silently targets the wrong qubit rather than failing.The only route today is
__getnewargs__()[0]. It does return a typedlist[int], so this isn't blocking, but it's the pickle protocol rather than an accessor: positional, undocumented, free to change, and it yieldsNoneinstead of[]for an empty rewiring.__repr__is the alternative, which means parsing RustDebugoutput.Suggested fix
#[cfg_attr( feature = "python", - pyo3::pyclass(module = "qcs_sdk.compiler.quilc", eq) + pyo3::pyclass(module = "qcs_sdk.compiler.quilc", eq, get_all) )] pub struct NativeQuilMetadata {Sibling classes also pass
frozen; I've left it out here since it's a semantic change beyond adding getters, but it would match the module if you want it.Happy to open a PR.