Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add a python package #885

Merged
merged 10 commits into from
Mar 19, 2024
Merged
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
26 changes: 26 additions & 0 deletions .github/pre-commit
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,30 @@ then
exit 1
fi

# Run `ruff` python formatting
if ! poetry run ruff format --check
then
echo ""
echo "There are some python code style issues."
echo "Run `poetry run ruff format` first."
exit 1
fi

# Run `mypy` for python type checking
if ! poetry run mypy .
then
echo ""
echo "There are some python code style issues."
echo "Fix the warnings returned by `poetry run mypy .` first."
exit 1
fi

# Run `ruff` python linting
if ! poetry run ruff check
then
echo ""
echo "There are some python linting issues."
exit 1
fi

exit 0
124 changes: 124 additions & 0 deletions .github/workflows/ci-py.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
name: Continuous integration 🐍

on:
push:
branches:
- main
pull_request:
branches:
- main
merge_group:
types: [checks_requested]
workflow_dispatch: {}

env:
SCCACHE_GHA_ENABLED: "true"

jobs:
# Check if changes were made to the relevant files.
# Always returns true if running on the default branch, to ensure all changes are throughly checked.
changes:
name: Check for changes in Python files
runs-on: ubuntu-latest
# Required permissions
permissions:
pull-requests: read
# Set job outputs to values from filter step
outputs:
python: ${{ github.ref_name == github.event.repository.default_branch || steps.filter.outputs.python }}
steps:
# For pull requests it's not necessary to checkout the code
- uses: dorny/paths-filter@v3
id: filter
with:
filters: |
python:
- 'quantinuum-hugr-py/**'
- 'pyproject.toml'
check:
needs: changes
if: ${{ needs.changes.outputs.python == 'true' }}

name: check python
runs-on: ubuntu-latest

strategy:
matrix:
python-version: ['3.10']

steps:
- uses: actions/checkout@v3
- name: Run sccache-cache
uses: mozilla-actions/sccache-action@v0.0.3
- name: Install poetry
run: pipx install poetry
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v3
with:
python-version: ${{ matrix.python-version }}
cache: "poetry"

- name: Install the project libraries
run: poetry install

- name: Type check with mypy
run: poetry run mypy .

- name: Check formatting with ruff
run: poetry run ruff format --check

- name: Lint with ruff
run: poetry run ruff check

- name: Run tests
run: poetry run pytest

# This is a meta job to mark successful completion of the required checks,
# even if they are skipped due to no changes in the relevant files.
required-checks:
name: Required checks 🐍
needs: [check]
if: always()
runs-on: ubuntu-latest
steps:
- name: Fail if required checks failed
if: (failure() || cancelled())
run: |
echo "Required checks failed"
echo "Please check the logs for more information"
exit 1
- name: Pass if required checks passed
run: |
echo "All required checks passed"
coverage:
needs: [changes, check]
# Run only if there are changes in the relevant files and the check job passed or was skipped
if: always() && !failure() && !cancelled() && needs.changes.outputs.python == 'true' && github.event_name != 'merge_group'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run sccache-cache
uses: mozilla-actions/sccache-action@v0.0.3
- name: Install poetry
run: pipx install poetry
- name: Set up Python 3.10
uses: actions/setup-python@v3
with:
python-version: '3.10'
cache: "poetry"

- name: Install the project libraries
run: poetry install

- name: Run python tests with coverage instrumentation
run: poetry run pytest --cov=./ --cov-report=xml

- name: Upload python coverage to codecov.io
uses: codecov/codecov-action@v3
with:
files: coverage.xml
name: python
flags: python
token: ${{ secrets.CODECOV_TOKEN }}
101 changes: 81 additions & 20 deletions .github/workflows/ci.yml → .github/workflows/ci-rs.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Continuous integration
name: Continuous integration 🦀

on:
push:
Expand All @@ -21,7 +21,31 @@ env:
RUSTC_WRAPPER: "sccache"

jobs:
# Check if changes were made to the relevant files.
# Always returns true if running on the default branch, to ensure all changes are throughly checked.
changes:
name: Check for changes in Rust files
runs-on: ubuntu-latest
# Required permissions
permissions:
pull-requests: read
# Set job outputs to values from filter step
outputs:
rust: ${{ github.ref_name == github.event.repository.default_branch || steps.filter.outputs.rust }}
steps:
# For pull requests it's not necessary to checkout the code
- uses: dorny/paths-filter@v3
id: filter
with:
filters: |
rust:
- 'quantinuum-hugr/**'
- 'Cargo.toml'
- 'specification/schema/**'
check:
needs: changes
if: ${{ needs.changes.outputs.rust == 'true' }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
Expand All @@ -40,7 +64,8 @@ jobs:
RUSTDOCFLAGS: "-Dwarnings"

benches:
if: github.event_name != 'merge_group'
needs: changes
if: ${{ needs.changes.outputs.rust == 'true' }} && github.event_name != 'merge_group'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
Expand All @@ -52,22 +77,39 @@ jobs:
- name: Build benchmarks with all features
run: cargo bench --verbose --no-run --workspace --all-features

tests:
# Run tests on Rust stable
tests-stable:
needs: changes
if: ${{ needs.changes.outputs.rust == 'true' }}
runs-on: ubuntu-latest
cqc-alec marked this conversation as resolved.
Show resolved Hide resolved
name: tests (Rust stable)
steps:
- uses: actions/checkout@v4
- uses: mozilla-actions/sccache-action@v0.0.4
- id: toolchain
uses: dtolnay/rust-toolchain@master
with:
toolchain: 'stable'
- name: Configure default rust toolchain
run: rustup override set ${{steps.toolchain.outputs.name}}
- name: Build with no features
run: cargo test --verbose --workspace --no-default-features --no-run
- name: Tests with no features
run: cargo test --verbose --workspace --no-default-features
- name: Build with all features
run: cargo test --verbose --workspace --all-features --no-run
- name: Tests with all features
run: cargo test --verbose --workspace --all-features

# Run tests on other toolchains
tests-other:
needs: changes
if: ${{ needs.changes.outputs.rust == 'true' && github.event_name != 'merge_group' }}
runs-on: ubuntu-latest
strategy:
fail-fast: true
matrix:
rust: ['1.75', stable, beta, nightly]
# workaround to ignore non-stable tests when running the merge queue checks
# see: https://gh.neting.ccmunity/t/how-to-conditionally-include-exclude-items-in-matrix-eg-based-on-branch/16853/6
isMerge:
- ${{ github.event_name == 'merge_group' }}
exclude:
- rust: '1.75'
isMerge: true
- rust: beta
isMerge: true
- rust: nightly
isMerge: true
rust: ['1.75', beta, nightly]
name: tests (Rust ${{ matrix.rust }})
steps:
- uses: actions/checkout@v4
Expand All @@ -87,9 +129,28 @@ jobs:
- name: Tests with all features
run: cargo test --verbose --workspace --all-features

# This is a meta job to mark successful completion of the required checks,
# even if they are skipped due to no changes in the relevant files.
required-checks:
name: Required checks 🦀
needs: [check, tests-stable]
if: always()
runs-on: ubuntu-latest
steps:
- name: Fail if required checks failed
if: (failure() || cancelled())
run: |
echo "Required checks failed"
echo "Please check the logs for more information"
exit 1
- name: Pass if required checks passed
run: |
echo "All required checks passed"
coverage:
if: github.event_name != 'merge_group'
needs: [tests, check]
needs: [changes, tests-stable, tests-other, check]
# Run only if there are changes in the relevant files and the check job passed or was skipped
if: always() && !failure() && !cancelled() && needs.changes.outputs.rust == 'true' && github.event_name != 'merge_group'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
Expand All @@ -110,6 +171,6 @@ jobs:
uses: codecov/codecov-action@v4
with:
files: coverage.json
name: ubuntu
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
name: rust
flags: rust
token: ${{ secrets.CODECOV_TOKEN }}
23 changes: 22 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,25 @@ devenv.local.nix
.pre-commit-config.yaml

# Coverage report
lcov.info
lcov.info

# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# Unit test / coverage reports
htmlcov/
.coverage

# Jupyter Notebook
.ipynb_checkpoints

# Environments
.env
.venv
env/
venv/

# ruff
.ruff_cache
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ See [DEVELOPMENT.md](https://github.com/CQCL/hugr/blob/main/DEVELOPMENT.md) for
This project is licensed under Apache License, Version 2.0 ([LICENSE][] or http://www.apache.org/licenses/LICENSE-2.0).

[API documentation here]: https://docs.rs/quantinuum-hugr/
[build_status]: https://github.com/CQCL/hugr/workflows/Continuous%20integration/badge.svg?branch=main
[build_status]: https://github.com/CQCL/hugr/actions/workflows/ci-rs.yml/badge.svg?branch=main
[msrv]: https://img.shields.io/badge/rust-1.75.0%2B-blue.svg
[crates]: https://img.shields.io/crates/v/quantinuum-hugr
[codecov]: https://img.shields.io/codecov/c/gh/CQCL/hugr?logo=codecov
Expand Down
25 changes: 25 additions & 0 deletions codecov.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Codecov coverage report configuration

# Coverage report
# Do not fail if the coverage is not met
coverage:
status:
patch:
default:
informational: false
only_pulls: true
project:
default:
informational: true

# Ignore tests and binaries
ignore:
- "quantinuum-hugr-py/tests"

# Coverage groups config
flag_management:
default_rules: # the rules that will be followed for any flag added, generally
# Use previous coverage if one is not available for the current commit.
#
# (E.g. if the PR doesn't modify a subproject, we don't submit a coverage report for it.)
carryforward: true
14 changes: 14 additions & 0 deletions justfile
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ test:
# Auto-fix all clippy warnings
fix:
cargo clippy --all-targets --all-features --workspace --fix --allow-staged
poetry run ruff check --fix

# Run the pre-commit checks
check:
Expand All @@ -17,7 +18,20 @@ check:
# Format the code
format:
cargo fmt
poetry run ruff format

# Generate a test coverage report
coverage:
cargo llvm-cov --lcov > lcov.info

# Load a poetry shell with the dependencies installed
pyshell:
poetry shell

# Run the python tests
pytest:
poetry run pytest

# Generate a python test coverage report
pycoverage:
poetry run pytest --cov=./ --cov-report=html
Loading
Loading