Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ Types of changes:
### Removed

### Fixed
- Fixed `loads("")` / whitespace-only input raising `AttributeError` instead of `ValidationError`. Empty and whitespace programs now raise `ValidationError` like other parse failures. ([#451](https://github.com/qBraid/pyqasm/pull/451), [#437](https://github.com/qBraid/pyqasm/issues/437))

### Dependencies

Expand Down
3 changes: 2 additions & 1 deletion src/pyqasm/entrypoint.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,8 @@ def loads(program: openqasm3.ast.Program | str, **kwargs) -> QasmModule:
program, opaque_gates = rewrite_opaque_declarations(program)
try:
program = openqasm3.parse(program)
except openqasm3.parser.QASM3ParsingError as err:
except (openqasm3.parser.QASM3ParsingError, AttributeError) as err:
# openqasm3 can raise AttributeError on empty/whitespace-only input
raise ValidationError(f"Failed to parse OpenQASM string: {err}") from err
elif not isinstance(program, openqasm3.ast.Program):
raise TypeError("Input quantum program must be of type 'str' or 'openqasm3.ast.Program'.")
Expand Down
14 changes: 14 additions & 0 deletions tests/qasm3/test_entrypoint.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,3 +74,17 @@ def test_incorrect_module_unroll_raises_error():
with pytest.raises(ValidationError):
module = loads("OPENQASM 3.0;\n qubit q; h q[2]")
module.unroll()


def test_loads_empty_string_raises_validation_error():
"""Empty / whitespace-only input must raise ValidationError, not AttributeError."""
for program in ("", " ", "\n\t"):
with pytest.raises(ValidationError, match="Failed to parse OpenQASM string"):
loads(program)


def test_loads_header_only_module_ok():
"""A header-only OpenQASM 3 program (no statements) remains valid."""
module = loads("OPENQASM 3.0;\n")
assert module.num_qubits == 0
assert module.num_clbits == 0
Loading