Skip to content

Add Python Plugin#20

Merged
flowerthrower merged 72 commits into
mainfrom
add-python-plugin
Jan 9, 2026
Merged

Add Python Plugin#20
flowerthrower merged 72 commits into
mainfrom
add-python-plugin

Conversation

@flowerthrower
Copy link
Copy Markdown
Collaborator

@flowerthrower flowerthrower commented Dec 10, 2025

Description

This PR includes all of the necessary files to provide a fully fledged Python package:

  • added Python helper functions for plugin setup
  • added end-to-end (round-trip) Python tests

Checklist:

  • The pull request only contains commits that are focused and relevant to this change.
  • I have added appropriate tests that cover the new/changed functionality.
  • I have updated the documentation to reflect these changes.
  • I have added entries to the changelog for any noteworthy additions, changes, fixes, or removals.
  • I have added migration instructions to the upgrade guide (if needed).
  • The changes follow the project's style guidelines and introduce no new warnings.
  • The changes are fully tested and pass the CI checks.
  • I have reviewed my own code changes.

Comment thread test/python/test_plugin.py Fixed
Comment thread .github/workflows/cd.yml Outdated
Signed-off-by: burgholzer <burgholzer@me.com>
Signed-off-by: burgholzer <burgholzer@me.com>
Signed-off-by: burgholzer <burgholzer@me.com>
Signed-off-by: burgholzer <burgholzer@me.com>
Signed-off-by: burgholzer <burgholzer@me.com>
Signed-off-by: burgholzer <burgholzer@me.com>
Signed-off-by: burgholzer <burgholzer@me.com>
Signed-off-by: burgholzer <burgholzer@me.com>
@burgholzer burgholzer added feature New feature or request python Python related changes labels Jan 9, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In @python/mqt/core/plugins/catalyst/plugin.py:
- Around line 22-56: The get_catalyst_plugin_abs_path function currently
searches package resources and site.getsitepackages() but misses user site
installs; update it to also iterate site.getusersitepackages() (or
site.USER_SITE) similarly to how site.getsitepackages() is handled, constructing
the catalyst path (using variables like plugin_lib and package_path) and
checking files in each user site-packages directory, returning the found Path or
falling back to the existing FileNotFoundError message; ensure the new loop
mirrors the existing site_pkg_dir logic to cover pip install --user scenarios.
📜 Review details

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 370efbe and be501b5.

⛔ Files ignored due to path filters (1)
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (14)
  • .github/workflows/cd.yml
  • .github/workflows/ci.yml
  • .pre-commit-config.yaml
  • .readthedocs.yaml
  • CMakeLists.txt
  • cmake/ExternalDependencies.cmake
  • docs/conf.py
  • pyproject.toml
  • python/mqt/core/plugins/catalyst/__init__.py
  • python/mqt/core/plugins/catalyst/device.py
  • python/mqt/core/plugins/catalyst/plugin.py
  • sitecustomize.py
  • test/test_plugin.py
  • test/test_plugin_setup.py
💤 Files with no reviewable changes (1)
  • CMakeLists.txt
🧰 Additional context used
🧠 Learnings (21)
📓 Common learnings
Learnt from: flowerthrower
Repo: munich-quantum-toolkit/core-plugins-catalyst PR: 1
File: CHANGELOG.md:18-18
Timestamp: 2025-12-01T11:00:40.342Z
Learning: In the munich-quantum-toolkit/core-plugins-catalyst repository, the CHANGELOG.md intentionally references the parent MQT Core repository's release notes (https://github.com/munich-quantum-toolkit/core/releases) because the plugin repository is based on work performed in the parent repository.
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core-plugins-catalyst PR: 23
File: .readthedocs.yaml:13-18
Timestamp: 2025-12-14T16:51:52.504Z
Learning: In the munich-quantum-toolkit/core-plugins-catalyst repository, LLVM and MLIR toolchains are required for the documentation build because `uv run` includes a full build of the package, which compiles C++/MLIR extensions using scikit-build-core.
📚 Learning: 2025-12-01T11:00:40.342Z
Learnt from: flowerthrower
Repo: munich-quantum-toolkit/core-plugins-catalyst PR: 1
File: CHANGELOG.md:18-18
Timestamp: 2025-12-01T11:00:40.342Z
Learning: In the munich-quantum-toolkit/core-plugins-catalyst repository, the CHANGELOG.md intentionally references the parent MQT Core repository's release notes (https://github.com/munich-quantum-toolkit/core/releases) because the plugin repository is based on work performed in the parent repository.

Applied to files:

  • python/mqt/core/plugins/catalyst/plugin.py
  • python/mqt/core/plugins/catalyst/device.py
  • cmake/ExternalDependencies.cmake
  • test/test_plugin.py
  • test/test_plugin_setup.py
  • pyproject.toml
  • python/mqt/core/plugins/catalyst/__init__.py
📚 Learning: 2025-12-14T15:23:49.063Z
Learnt from: flowerthrower
Repo: munich-quantum-toolkit/core-plugins-catalyst PR: 23
File: docs/conf.py:110-130
Timestamp: 2025-12-14T15:23:49.063Z
Learning: In the munich-quantum-toolkit/core-plugins-catalyst repo, Ruff is configured to enable ALL rules with only specific ones disabled. PLR6301 (no-self-use) is active, so you must add a // noqa: PLR6301 directive for any instance of a class method that does not use self, even if Ruff flags RUF100 as unused. Apply this pattern across Python files (not just docs/conf.py) to comply with the repository-wide Ruff configuration.

Applied to files:

  • python/mqt/core/plugins/catalyst/plugin.py
  • python/mqt/core/plugins/catalyst/device.py
  • test/test_plugin.py
  • docs/conf.py
  • sitecustomize.py
  • test/test_plugin_setup.py
  • python/mqt/core/plugins/catalyst/__init__.py
📚 Learning: 2026-01-08T10:07:23.393Z
Learnt from: flowerthrower
Repo: munich-quantum-toolkit/core-plugins-catalyst PR: 20
File: python/mqt/core/plugins/catalyst/device.py:69-69
Timestamp: 2026-01-08T10:07:23.393Z
Learning: In python/mqt/core/plugins/catalyst/, Ruff is configured with select = ["ALL"] and SLF001 enabled. When accessing private attributes (e.g., device._to_matrix_ops) in this repository, add a # noqa: SLF001 directive to suppress the private-member access warning. This applies even if Ruff would emit RUF100 about unused directives. Ensure any access to private attributes in this module is accompanied by a corresponding noqa: SLF001 comment on that line.

Applied to files:

  • python/mqt/core/plugins/catalyst/plugin.py
  • python/mqt/core/plugins/catalyst/device.py
  • python/mqt/core/plugins/catalyst/__init__.py
📚 Learning: 2025-12-25T13:28:10.402Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/predictor PR: 526
File: tests/compilation/test_predictor_rl.py:225-225
Timestamp: 2025-12-25T13:28:10.402Z
Learning: In the munich-quantum-toolkit/predictor repository, Ruff is configured with the "SLF" (flake8-self) rule category enabled in extend-select. SLF001 (private member access) is active, so `# noqa: SLF001` directives are necessary when accessing private methods/attributes (e.g., `_ensure_device_averages_cached()`), even if Ruff reports RUF100 warnings suggesting the directive is unused.

Applied to files:

  • python/mqt/core/plugins/catalyst/device.py
  • pyproject.toml
📚 Learning: 2025-12-25T13:28:25.619Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/predictor PR: 526
File: src/mqt/predictor/rl/predictorenv.py:271-271
Timestamp: 2025-12-25T13:28:25.619Z
Learning: In the munich-quantum-toolkit/predictor repository, Ruff is configured with an extensive set of rules including SLF (flake8-self) in the extend-select list. The `# noqa: SLF001` directive for private member access (e.g., `self.state._layout = self.layout` in src/mqt/predictor/rl/predictorenv.py) is necessary and appropriate, even if Ruff reports RUF100 warnings suggesting the directive is unused.

Applied to files:

  • python/mqt/core/plugins/catalyst/device.py
  • pyproject.toml
📚 Learning: 2025-11-27T21:26:39.677Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/qmap PR: 846
File: python/mqt/qmap/plugins/qiskit/sc/load_calibration.py:34-34
Timestamp: 2025-11-27T21:26:39.677Z
Learning: In the qmap project, the Ruff linter has the "PL" (pylint) rule category enabled, which includes PLC0415 (import-outside-top-level). Therefore, `# noqa: PLC0415` directives on lazy imports are appropriate and necessary, not unused.

Applied to files:

  • python/mqt/core/plugins/catalyst/device.py
  • pyproject.toml
📚 Learning: 2025-11-24T10:19:41.147Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1326
File: python/mqt/core/__init__.py:22-22
Timestamp: 2025-11-24T10:19:41.147Z
Learning: In the munich-quantum-toolkit/core repository, Ruff is configured with 'ALL' rules enabled by default, and only specific rules are selectively disabled. When reviewing changes that enable previously-disabled rules (like PLC0415), noqa directives for those rules become necessary and should be retained.

Applied to files:

  • python/mqt/core/plugins/catalyst/device.py
  • pyproject.toml
📚 Learning: 2025-11-27T21:22:11.330Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/qmap PR: 846
File: pyproject.toml:213-214
Timestamp: 2025-11-27T21:22:11.330Z
Learning: In the qmap project (pyproject.toml), the maintainers intentionally enable `unsafe-fixes = true` in the ruff configuration. This is an established practice that has worked well for the project, with the expectation that PR authors review any automated fixes.

Applied to files:

  • python/mqt/core/plugins/catalyst/device.py
  • pyproject.toml
📚 Learning: 2025-10-11T13:21:15.212Z
Learnt from: denialhaag
Repo: munich-quantum-toolkit/ddsim PR: 674
File: .github/workflows/cd.yml:56-56
Timestamp: 2025-10-11T13:21:15.212Z
Learning: In the ddsim repository, modifying .github/workflows/cd.yml intentionally triggers CD workflow testing in CI through a change-detection mechanism in ci.yml. The change-detection job outputs a run-cd flag that controls whether build-sdist and build-wheel jobs execute in CI, allowing testing of the CD workflow (including wheel building and testing) before actual releases.

Applied to files:

  • .github/workflows/ci.yml
  • .github/workflows/cd.yml
📚 Learning: 2025-12-02T10:08:36.022Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core-plugins-catalyst PR: 1
File: .github/workflows/cd.yml:40-48
Timestamp: 2025-12-02T10:08:36.022Z
Learning: In munich-quantum-toolkit workflows, the reusable-python-packaging-sdist.yml workflow uploads the sdist artifact with the name `cibw-sdist` (or `dev-cibw-sdist` for pull requests), which means it is covered by the `cibw-*` glob pattern when downloading artifacts for deployment.

Applied to files:

  • .github/workflows/ci.yml
  • .github/workflows/cd.yml
📚 Learning: 2025-12-14T15:23:54.712Z
Learnt from: flowerthrower
Repo: munich-quantum-toolkit/core-plugins-catalyst PR: 23
File: docs/conf.py:110-130
Timestamp: 2025-12-14T15:23:54.712Z
Learning: In the munich-quantum-toolkit/core-plugins-catalyst repository, the Ruff configuration has 'ALL' rules enabled with only specific rules disabled. PLR6301 (no-self-use) is active, so `# noqa: PLR6301` directives are necessary for methods that don't use self, even if Ruff reports RUF100 warnings suggesting the directive is unused.

Applied to files:

  • .github/workflows/ci.yml
  • pyproject.toml
📚 Learning: 2025-12-23T23:19:56.478Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core-plugins-catalyst PR: 3
File: .github/workflows/reusable-mlir-tests.yml:38-39
Timestamp: 2025-12-23T23:19:56.478Z
Learning: In workflow YAMLs that use the rui314/setup-mold action (v1), rely on its built-in OS detection (runner.os == 'linux') to skip non-Linux runners. Do not add an extra if: runner.os condition in the workflow for those steps. This guidance applies broadly to all workflows using that action across the repository; if cross-platform behavior is needed, consider separate jobs or alternative actions.

Applied to files:

  • .github/workflows/ci.yml
  • .github/workflows/cd.yml
📚 Learning: 2025-12-05T17:45:37.602Z
Learnt from: denialhaag
Repo: munich-quantum-toolkit/core PR: 1360
File: .github/workflows/reusable-mlir-tests.yml:40-43
Timestamp: 2025-12-05T17:45:37.602Z
Learning: In the munich-quantum-toolkit/core repository, patch releases of LLVM dependencies don't require documentation updates, changelog entries, or additional tests beyond what's validated by passing CI checks.

Applied to files:

  • cmake/ExternalDependencies.cmake
📚 Learning: 2025-10-09T13:14:10.178Z
Learnt from: DRovara
Repo: munich-quantum-toolkit/core PR: 1108
File: mlir/lib/Dialect/MQTOpt/Transforms/ReplaceBasisStateControlsWithIfPattern.cpp:219-221
Timestamp: 2025-10-09T13:14:10.178Z
Learning: The MQT Core project (munich-quantum-toolkit/core repository) uses the C++20 standard, not C++17. C++20 features such as abbreviated function templates (e.g., `const auto&` parameters) are supported and valid in this codebase.

Applied to files:

  • cmake/ExternalDependencies.cmake
📚 Learning: 2025-11-03T23:09:26.881Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1287
File: test/qdmi/dd/CMakeLists.txt:9-21
Timestamp: 2025-11-03T23:09:26.881Z
Learning: The CMake functions `generate_device_defs_executable` and `generate_prefixed_qdmi_headers` used in QDMI device test CMakeLists.txt files are provided by the external QDMI library (fetched via FetchContent from https://github.com/Munich-Quantum-Software-Stack/qdmi.git), specifically in the cmake/PrefixHandling.cmake module of the QDMI repository.

Applied to files:

  • cmake/ExternalDependencies.cmake
📚 Learning: 2025-12-13T20:08:45.549Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/qmap PR: 862
File: pyproject.toml:65-66
Timestamp: 2025-12-13T20:08:45.549Z
Learning: In the qmap project (pyproject.toml), maintain broad compatibility with dependencies across supported Python versions. Avoid artificially raising minimum version requirements unless there's a specific need (e.g., to guarantee binary wheel availability for certain Python versions, or to access required features). The goal is to keep the software as broadly compatible as possible with the rest of the ecosystem.

Applied to files:

  • pyproject.toml
📚 Learning: 2025-10-10T08:09:54.528Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1246
File: bindings/CMakeLists.txt:0-0
Timestamp: 2025-10-10T08:09:54.528Z
Learning: In the Munich Quantum Toolkit (MQT) Core project, scikit-build-core is configured with `wheel.install-dir = "mqt/core"` in pyproject.toml, which automatically prefixes all CMake `DESTINATION` paths with `mqt/core/` during wheel installation. Therefore, CMake install destinations are relative to the `mqt/core` package namespace, not `site-packages`.

Applied to files:

  • pyproject.toml
📚 Learning: 2025-12-05T15:54:56.385Z
Learnt from: flowerthrower
Repo: munich-quantum-toolkit/core-plugins-catalyst PR: 3
File: lib/Conversion/CatalystQuantumToMQTOpt/CMakeLists.txt:19-20
Timestamp: 2025-12-05T15:54:56.385Z
Learning: The munich-quantum-toolkit/core-plugins-catalyst project does not support Windows builds, so MSVC-specific compiler options or cross-platform compatibility with MSVC is not required.

Applied to files:

  • pyproject.toml
📚 Learning: 2026-01-08T10:07:23.393Z
Learnt from: flowerthrower
Repo: munich-quantum-toolkit/core-plugins-catalyst PR: 20
File: python/mqt/core/plugins/catalyst/device.py:69-69
Timestamp: 2026-01-08T10:07:23.393Z
Learning: In the munich-quantum-toolkit/core-plugins-catalyst repository, Ruff is configured with select = ["ALL"] and only specific rules are disabled. SLF001 (flake8-self - private member access) is enabled, so `# noqa: SLF001` directives are necessary when accessing private attributes like `device._to_matrix_ops` in python/mqt/core/plugins/catalyst/device.py, even if Ruff reports RUF100 warnings suggesting the directive is unused.

Applied to files:

  • pyproject.toml
📚 Learning: 2025-12-28T17:13:36.900Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1403
File: pyproject.toml:98-102
Timestamp: 2025-12-28T17:13:36.900Z
Learning: In the munich-quantum-toolkit/core project, scikit-build-core is intelligent enough to skip build targets listed in pyproject.toml that don't exist for a given platform, so platform-specific targets (like `-dyn` targets conditioned on `NOT WIN32`) can be unconditionally listed in `build.targets` without causing Windows build failures.

Applied to files:

  • pyproject.toml
🧬 Code graph analysis (2)
test/test_plugin.py (1)
python/mqt/core/plugins/catalyst/device.py (1)
  • get_device (81-104)
python/mqt/core/plugins/catalyst/__init__.py (2)
python/mqt/core/plugins/catalyst/device.py (2)
  • configure_device_for_mqt (29-78)
  • get_device (81-104)
python/mqt/core/plugins/catalyst/plugin.py (2)
  • get_catalyst_plugin_abs_path (22-56)
  • name2pass (59-68)
🪛 Ruff (0.14.10)
python/mqt/core/plugins/catalyst/device.py

72-72: Unused noqa directive (non-enabled: SLF001)

Remove unused noqa directive

(RUF100)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (8)
  • GitHub Check: 🐍 Test (ubuntu-24.04-arm) / 🐍 ubuntu-24.04-arm
  • GitHub Check: 🚀 CD (wheel) (ubuntu-24.04) / 🎡 ubuntu-24.04
  • GitHub Check: 🚀 CD (wheel) (ubuntu-24.04-arm) / 🎡 ubuntu-24.04-arm
  • GitHub Check: 🐍 Test (ubuntu-24.04) / 🐍 ubuntu-24.04
  • GitHub Check: 🇨‌ Lint / 🚨 Lint
  • GitHub Check: 🐍 Packaging (ubuntu-24.04-arm) / 🎡 ubuntu-24.04-arm
  • GitHub Check: 🐍 Packaging (ubuntu-24.04) / 🎡 ubuntu-24.04
  • GitHub Check: 🐍 Packaging (macos-14) / 🎡 macos-14
🔇 Additional comments (30)
docs/conf.py (1)

46-46: LGTM!

The blank line improves readability by visually separating the version assignment from the filtering comment.

.readthedocs.yaml (2)

14-14: LGTM!

The addition of graphviz aligns with documentation build requirements for generating diagrams. The removal of previously listed packages (jq, zstd) suggests they were unnecessary for the current doc build pipeline.


21-21: LGTM!

Adding lib/ to the diff check ensures documentation builds are triggered when library source files change, which is appropriate for maintaining up-to-date API documentation.

sitecustomize.py (1)

1-23: LGTM!

The implementation correctly handles optional multiprocess coverage collection. The try-except pattern with a silent pass for ImportError is appropriate since coverage is an optional testing dependency and the file should not fail when coverage is unavailable.

.pre-commit-config.yaml (1)

80-80: LGTM!

Broadening the mypy file pattern from test/python to test aligns with the expanded test scope and ensures type checking coverage across all Python test files in the repository.

cmake/ExternalDependencies.cmake (1)

14-18: MQT Core version bump verified.

The version bump to 3.4.0 is correct:

  • The commit hash 6bcc01e7d135058c6439c64fdd5f14b65ab88816 exactly matches the v3.4.0 release tag
  • The release was published on 2026-01-08 and follows proper release procedures with all checklist items completed
  • v3.4.0 is the latest stable release from the v3.x branch, created with cherry-picked changes from main

The change is approved.

python/mqt/core/plugins/catalyst/plugin.py (2)

1-19: LGTM!

License header, imports, and module-level exports are correctly structured. The __dir__ function properly returns __all__ for IDE support.


59-68: LGTM!

Simple and clean wrapper function that correctly delegates to get_catalyst_plugin_abs_path() and returns the expected tuple format.

python/mqt/core/plugins/catalyst/device.py (3)

1-27: LGTM!

Module structure, imports, and exports are well-organized. The docstring clearly explains the purpose of preventing Catalyst from decomposing gates into matrix operations.


29-78: The # noqa: SLF001 directive is correct and should be retained.

The static analysis hint (RUF100) suggesting the directive is unused is a false positive. Based on learnings, Ruff is configured with select = ["ALL"] and SLF001 is enabled in this repository, making the directive necessary for private member access on device._to_matrix_ops.

The function logic is sound—it properly loads capabilities from TOML, removes QubitUnitary to prevent matrix decomposition, clears _to_matrix_ops, and injects modified capabilities via qjit_capabilities.


81-103: LGTM!

Clean convenience wrapper that creates and configures a device in one call. The ANN401 suppression for **kwargs: Any is appropriate for pass-through kwargs.

pyproject.toml (3)

128-136: LGTM!

The filterwarnings configuration properly:

  1. Treats warnings as errors by default
  2. Ignores known deprecation warnings from jaxlib and pyct_anno
  3. Sets appropriate test paths

273-278: LGTM!

The cache-keys configuration for uv properly includes pyproject.toml, git metadata, and source directories (lib/**/*, include/**/*) to ensure cache invalidation when native code changes.


56-58: Entry point and module export configuration is correct.

The entry point "mqt.passes" = "mqt.core.plugins.catalyst" properly references the plugin module, which exports the name2pass function with the correct signature expected by Catalyst's pass resolution mechanism.

.github/workflows/cd.yml (1)

6-13: LGTM!

Adding the pull_request trigger with a path filter for .github/workflows/cd.yml enables testing CD workflow changes before actual releases. The permissions are correctly scoped for build attestation and PyPI publishing.

python/mqt/core/plugins/catalyst/__init__.py (1)

1-21: LGTM!

Clean public API surface that properly re-exports all utilities from submodules. The __all__ list is correctly alphabetized and matches the imports.

Consider adding a __dir__ function for consistency with the submodules, though this is optional since the __all__ already controls from mqt.core.plugins.catalyst import * behavior.

test/test_plugin.py (5)

68-110: LGTM!

The FileCheck discovery logic is thorough, checking multiple environment variables (FILECHECK_PATH, LLVM_INSTALL_PREFIX, LLVM_ROOT, LLVM_DIR, MLIR_DIR) and falling back to PATH. The lru_cache ensures the lookup happens only once.


113-168: LGTM!

The _run_filecheck helper is well-implemented:

  • Proper error handling with informative messages
  • Uses temporary file for check patterns (cleaned up in finally)
  • 30-second timeout prevents hangs
  • Truncates MLIR output in error messages for readability

The # noqa: S603 is appropriate since the FileCheck binary path is validated to exist.


171-246: Well-structured roundtrip test.

The test_paulix_roundtrip test follows a clear pattern:

  1. Define circuit with various gate variants (non-controlled, controlled, named controlled)
  2. Apply conversion passes via decorators
  3. Run qjit with custom pipeline and keep_intermediate=2
  4. Read intermediate MLIR files and verify with FileCheck patterns

This pattern is consistently applied across all gate tests.


908-964: LGTM!

The Toffoli gate test properly covers multi-control scenarios and verifies the conversion maintains the expected gate structure through the roundtrip.


40-66: Configuration correctly prevents race conditions—no action needed.

The pytest configuration with --dist=loadfile ensures tests within the same file run sequentially, which protects against concurrent MLIR artifact cleanup. Since only test_plugin.py generates MLIR artifacts (verified via codebase search), and test_plugin_setup.py does not, there is no interference between parallel test processes. The cleanup fixture operates safely within this configuration.

.github/workflows/ci.yml (2)

22-68: LGTM on the new Python CI jobs.

The job structure is well-organized:

  • python-tests: Core test matrix on primary platforms
  • python-coverage: Aggregates coverage after tests pass
  • python-tests-extensive: Extended matrix triggered by label for broader compatibility testing
  • python-linter: Runs Ruff and ty with MLIR setup

All jobs correctly depend on change-detection and use consistent LLVM versioning.


108-145: LGTM!

The required-checks-pass job correctly:

  1. Lists all new Python jobs in needs
  2. Updates allowed-skips to conditionally skip Python jobs when run-python-tests is false
  3. Handles the extensive-python-ci label condition for python-tests-extensive
  4. Removes the deleted mlir-tests job from dependencies
test/test_plugin_setup.py (7)

1-13: LGTM!

The copyright header and module docstring are clear and appropriate. The docstring correctly sets expectations that these are smoke tests verifying plugin installation, not pass execution.


15-28: LGTM!

The imports are well-organized and follow best practices. The TYPE_CHECKING block is used correctly to avoid runtime import of StateMP, which is only needed for type annotations.


50-67: LGTM!

This test correctly validates that the plugin can be used via apply_pass_plugin without explicit preregistration in the qjit decorator. The test logic is sound and appropriate for smoke testing.


69-97: LGTM!

Both tests correctly validate alternative plugin registration mechanisms:

  • test_mqt_entry_point: Uses entry-point syntax with the "mqt." prefix
  • test_mqt_dictionary: Uses the Catalyst pipeline dictionary approach

The test coverage across different usage patterns is comprehensive for smoke testing.


99-114: LGTM!

The error handling test is well-structured. The mock setup correctly simulates a missing library scenario, and the pytest.raises assertion properly validates the expected error message.


116-132: LGTM!

Both error handling tests correctly validate the behavior when config_filepath is not set:

  • test_configure_device_for_mqt_no_config: Tests direct device configuration
  • test_get_device_no_config: Tests device creation path

The mock setup and error assertions are appropriate and comprehensive.


31-48: Consider adding explicit return type annotation.

The test logic is correct and appropriately validates that the MQT pass appears in the generated MLIR. For consistency with the codebase's type annotation practices, consider adding an explicit -> None return type annotation to the test function.

📝 Proposed refinement
-def test_mqt_plugin() -> None:
+def test_mqt_plugin() -> None:

Note: Apply this pattern to all test functions in the file (lines 31, 50, 69, 84, 99, 116, 124).

Likely an incorrect or invalid review comment.

Comment thread python/mqt/core/plugins/catalyst/plugin.py
Signed-off-by: burgholzer <burgholzer@me.com>
Signed-off-by: burgholzer <burgholzer@me.com>
Signed-off-by: burgholzer <burgholzer@me.com>
Signed-off-by: burgholzer <burgholzer@me.com>
Signed-off-by: burgholzer <burgholzer@me.com>
Signed-off-by: burgholzer <burgholzer@me.com>
Signed-off-by: burgholzer <burgholzer@me.com>
Copy link
Copy Markdown
Member

@burgholzer burgholzer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alright. I simplified quite a few things here as quite some of the changes felt like LLM bloat.
Also merged in the latest main branch with some dependency updates.
This is looking good to go now. 🚀

There is a lot of duplication in the test code that would be great to address in a follow up. I don't want to block this PR with that.
I am also not too sure if all of the code in device.py is really necessary and it seems fairly hacky.

@flowerthrower might be worth for you to look through the changes here and merge if you consider them reasonable.

@burgholzer
Copy link
Copy Markdown
Member

Ah. Something that I missed: this definitely deserves a changelog entry.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature New feature or request python Python related changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants