qubasic 0.11.0__tar.gz → 0.11.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. {qubasic-0.11.0 → qubasic-0.11.1}/CHANGELOG.md +5 -0
  2. {qubasic-0.11.0/qubasic.egg-info → qubasic-0.11.1}/PKG-INFO +1 -1
  3. {qubasic-0.11.0 → qubasic-0.11.1}/pyproject.toml +1 -1
  4. {qubasic-0.11.0 → qubasic-0.11.1/qubasic.egg-info}/PKG-INFO +1 -1
  5. {qubasic-0.11.0 → qubasic-0.11.1}/qubasic_core/__init__.py +1 -1
  6. {qubasic-0.11.0 → qubasic-0.11.1}/qubasic_core/executor.py +13 -0
  7. {qubasic-0.11.0 → qubasic-0.11.1}/tests/test_qubasic.py +17 -0
  8. {qubasic-0.11.0 → qubasic-0.11.1}/LICENSE +0 -0
  9. {qubasic-0.11.0 → qubasic-0.11.1}/MANIFEST.in +0 -0
  10. {qubasic-0.11.0 → qubasic-0.11.1}/README.md +0 -0
  11. {qubasic-0.11.0 → qubasic-0.11.1}/examples/bell.qb +0 -0
  12. {qubasic-0.11.0 → qubasic-0.11.1}/examples/grover3.qb +0 -0
  13. {qubasic-0.11.0 → qubasic-0.11.1}/examples/locc_teleport.qb +0 -0
  14. {qubasic-0.11.0 → qubasic-0.11.1}/examples/sweep_rx.qb +0 -0
  15. {qubasic-0.11.0 → qubasic-0.11.1}/qubasic.egg-info/SOURCES.txt +0 -0
  16. {qubasic-0.11.0 → qubasic-0.11.1}/qubasic.egg-info/dependency_links.txt +0 -0
  17. {qubasic-0.11.0 → qubasic-0.11.1}/qubasic.egg-info/entry_points.txt +0 -0
  18. {qubasic-0.11.0 → qubasic-0.11.1}/qubasic.egg-info/requires.txt +0 -0
  19. {qubasic-0.11.0 → qubasic-0.11.1}/qubasic.egg-info/top_level.txt +0 -0
  20. {qubasic-0.11.0 → qubasic-0.11.1}/qubasic_core/__main__.py +0 -0
  21. {qubasic-0.11.0 → qubasic-0.11.1}/qubasic_core/algorithms.py +0 -0
  22. {qubasic-0.11.0 → qubasic-0.11.1}/qubasic_core/algos2.py +0 -0
  23. {qubasic-0.11.0 → qubasic-0.11.1}/qubasic_core/analysis.py +0 -0
  24. {qubasic-0.11.0 → qubasic-0.11.1}/qubasic_core/backend.py +0 -0
  25. {qubasic-0.11.0 → qubasic-0.11.1}/qubasic_core/benchmarking.py +0 -0
  26. {qubasic-0.11.0 → qubasic-0.11.1}/qubasic_core/bosonic.py +0 -0
  27. {qubasic-0.11.0 → qubasic-0.11.1}/qubasic_core/classic.py +0 -0
  28. {qubasic-0.11.0 → qubasic-0.11.1}/qubasic_core/cli.py +0 -0
  29. {qubasic-0.11.0 → qubasic-0.11.1}/qubasic_core/control_flow.py +0 -0
  30. {qubasic-0.11.0 → qubasic-0.11.1}/qubasic_core/debug.py +0 -0
  31. {qubasic-0.11.0 → qubasic-0.11.1}/qubasic_core/demos.py +0 -0
  32. {qubasic-0.11.0 → qubasic-0.11.1}/qubasic_core/display.py +0 -0
  33. {qubasic-0.11.0 → qubasic-0.11.1}/qubasic_core/dynamics.py +0 -0
  34. {qubasic-0.11.0 → qubasic-0.11.1}/qubasic_core/engine.py +0 -0
  35. {qubasic-0.11.0 → qubasic-0.11.1}/qubasic_core/engine_state.py +0 -0
  36. {qubasic-0.11.0 → qubasic-0.11.1}/qubasic_core/errors.py +0 -0
  37. {qubasic-0.11.0 → qubasic-0.11.1}/qubasic_core/exec_context.py +0 -0
  38. {qubasic-0.11.0 → qubasic-0.11.1}/qubasic_core/expression.py +0 -0
  39. {qubasic-0.11.0 → qubasic-0.11.1}/qubasic_core/file_io.py +0 -0
  40. {qubasic-0.11.0 → qubasic-0.11.1}/qubasic_core/gates.py +0 -0
  41. {qubasic-0.11.0 → qubasic-0.11.1}/qubasic_core/help_text.py +0 -0
  42. {qubasic-0.11.0 → qubasic-0.11.1}/qubasic_core/io_protocol.py +0 -0
  43. {qubasic-0.11.0 → qubasic-0.11.1}/qubasic_core/locc.py +0 -0
  44. {qubasic-0.11.0 → qubasic-0.11.1}/qubasic_core/locc_commands.py +0 -0
  45. {qubasic-0.11.0 → qubasic-0.11.1}/qubasic_core/locc_display.py +0 -0
  46. {qubasic-0.11.0 → qubasic-0.11.1}/qubasic_core/locc_engine.py +0 -0
  47. {qubasic-0.11.0 → qubasic-0.11.1}/qubasic_core/locc_execution.py +0 -0
  48. {qubasic-0.11.0 → qubasic-0.11.1}/qubasic_core/memory.py +0 -0
  49. {qubasic-0.11.0 → qubasic-0.11.1}/qubasic_core/mock_backend.py +0 -0
  50. {qubasic-0.11.0 → qubasic-0.11.1}/qubasic_core/noise_mixin.py +0 -0
  51. {qubasic-0.11.0 → qubasic-0.11.1}/qubasic_core/parser.py +0 -0
  52. {qubasic-0.11.0 → qubasic-0.11.1}/qubasic_core/patterns.py +0 -0
  53. {qubasic-0.11.0 → qubasic-0.11.1}/qubasic_core/pauliprop.py +0 -0
  54. {qubasic-0.11.0 → qubasic-0.11.1}/qubasic_core/profiler.py +0 -0
  55. {qubasic-0.11.0 → qubasic-0.11.1}/qubasic_core/program_mgmt.py +0 -0
  56. {qubasic-0.11.0 → qubasic-0.11.1}/qubasic_core/protocol.py +0 -0
  57. {qubasic-0.11.0 → qubasic-0.11.1}/qubasic_core/qec.py +0 -0
  58. {qubasic-0.11.0 → qubasic-0.11.1}/qubasic_core/qol.py +0 -0
  59. {qubasic-0.11.0 → qubasic-0.11.1}/qubasic_core/qudits.py +0 -0
  60. {qubasic-0.11.0 → qubasic-0.11.1}/qubasic_core/resources.py +0 -0
  61. {qubasic-0.11.0 → qubasic-0.11.1}/qubasic_core/scope.py +0 -0
  62. {qubasic-0.11.0 → qubasic-0.11.1}/qubasic_core/screen.py +0 -0
  63. {qubasic-0.11.0 → qubasic-0.11.1}/qubasic_core/state_display.py +0 -0
  64. {qubasic-0.11.0 → qubasic-0.11.1}/qubasic_core/statements.py +0 -0
  65. {qubasic-0.11.0 → qubasic-0.11.1}/qubasic_core/strings.py +0 -0
  66. {qubasic-0.11.0 → qubasic-0.11.1}/qubasic_core/subs.py +0 -0
  67. {qubasic-0.11.0 → qubasic-0.11.1}/qubasic_core/sweep.py +0 -0
  68. {qubasic-0.11.0 → qubasic-0.11.1}/qubasic_core/terminal.py +0 -0
  69. {qubasic-0.11.0 → qubasic-0.11.1}/setup.cfg +0 -0
  70. {qubasic-0.11.0 → qubasic-0.11.1}/tests/test_features.py +0 -0
@@ -1,5 +1,10 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.11.1 (2026-06-19)
4
+
5
+ ### Fixed
6
+ - A configuration/session command (`QUBITS`, `SHOTS`, `METHOD`, `LOCC`, ...) placed on a numbered program line now reports a clear error explaining it must run without a line number (before `RUN`), instead of the misleading `UNKNOWN GATE`. Unnumbered config in a script was, and remains, the correct usage.
7
+
3
8
  ## 0.11.0 (2026-06-19)
4
9
 
5
10
  Convention-conformance and observability pass: make the language behave the way
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: qubasic
3
- Version: 0.11.0
3
+ Version: 0.11.1
4
4
  Summary: Quantum BASIC Interactive Terminal
5
5
  Author-email: "Charles C. Norton" <machineelv@gmail.com>
6
6
  License-Expression: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "qubasic"
7
- version = "0.11.0"
7
+ version = "0.11.1"
8
8
  description = "Quantum BASIC Interactive Terminal"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: qubasic
3
- Version: 0.11.0
3
+ Version: 0.11.1
4
4
  Summary: Quantum BASIC Interactive Terminal
5
5
  Author-email: "Charles C. Norton" <machineelv@gmail.com>
6
6
  License-Expression: MIT
@@ -28,7 +28,7 @@ __all__ = [
28
28
  'GATE_TABLE', 'GATE_ALIASES',
29
29
  ]
30
30
 
31
- __version__ = '0.11.0'
31
+ __version__ = '0.11.1'
32
32
 
33
33
  def __getattr__(name):
34
34
  """Lazy import heavy modules on first access."""
@@ -333,6 +333,19 @@ class ExecutorMixin:
333
333
  return ExecResult.ADVANCE
334
334
  # Fall through to _apply_gate_str for custom gates not in GATE_TABLE
335
335
 
336
+ # A REPL/config command (QUBITS, SHOTS, METHOD, LOCC, ...) used as a
337
+ # numbered program line reaches here only because it is neither a gate
338
+ # nor a statement. Explain it instead of failing with "UNKNOWN GATE".
339
+ # SEND/SHARE are LOCC statements (handled on the LOCC path), so leave
340
+ # them to their own error.
341
+ _first = stmt.split(None, 1)[0].upper() if stmt.split() else ''
342
+ if ((_first in self._CMD_WITH_ARG or _first in self._CMD_NO_ARG)
343
+ and _first not in ('SEND', 'SHARE')):
344
+ raise QBasicBuildError(
345
+ f"{_first} is a configuration/session command, not a program "
346
+ f"statement; run it without a line number (before RUN), e.g. "
347
+ f"QUBITS 3 / SHOTS 1024 / METHOD statevector / LOCC 2 2")
348
+
336
349
  # Slow path: subroutine expansion + gate dispatch
337
350
  expanded = self._expand_statement(stmt)
338
351
  for gate_str in expanded:
@@ -2078,6 +2078,23 @@ class TestConventionAndStateRegressions(unittest.TestCase):
2078
2078
  self.assertIn('rightmost', note)
2079
2079
  self.assertIn('bit_order', t.result())
2080
2080
 
2081
+ def test_config_command_as_program_line_errors_clearly(self):
2082
+ # A config/REPL command used as a numbered program line explains itself
2083
+ # instead of failing with the misleading "UNKNOWN GATE".
2084
+ for cmd in ('QUBITS 3', 'SHOTS 256', 'METHOD stabilizer', 'LOCC 2 2'):
2085
+ t = QBasicTerminal(); t.num_qubits = 2
2086
+ t.program = {10: cmd, 20: 'H 0', 30: 'MEASURE'}
2087
+ _, out = capture(t.cmd_run)
2088
+ self.assertIn('configuration', out.lower())
2089
+ self.assertNotIn('UNKNOWN GATE', out)
2090
+
2091
+ def test_subroutine_call_not_treated_as_config_command(self):
2092
+ t = QBasicTerminal(); t.num_qubits = 2
2093
+ t.process('DEF BELL = H 0 : CX 0,1', track_undo=False)
2094
+ t.program = {10: 'BELL', 20: 'MEASURE'}
2095
+ capture(t.cmd_run)
2096
+ self.assertIsNotNone(t.last_counts) # ran; not blocked as a "command"
2097
+
2081
2098
 
2082
2099
  if __name__ == '__main__':
2083
2100
  if hasattr(sys.stdout, 'reconfigure'):
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes