Skip to content
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
29 changes: 29 additions & 0 deletions .github/workflows/fuzz.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
name: Fuzz

on:
schedule:
- cron: "17 3 * * 1"
workflow_dispatch:

jobs:
fuzz:
runs-on: ubuntu-latest
timeout-minutes: 15
permissions:
contents: read
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Install QA dependencies
run: |
python -m pip install --upgrade pip
python -m pip install -e ".[qa]"
- name: Run bounded parser fuzz tests
env:
PYTHONPATH: .
HYPOTHESIS_PROFILE: fuzz
run: python -m pytest -q tests/property -m fuzz --hypothesis-show-statistics
98 changes: 82 additions & 16 deletions .github/workflows/parser-reference-guard.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,15 @@ jobs:
(github.event.action == 'opened' ||
github.event.action == 'synchronize' ||
github.event.action == 'reopened' ||
github.event.label.name == 'ignore-parser-reference-guard')
github.event.label.name == 'ignore-parser-reference-guard' ||
github.event.label.name == 'require-parser-reference-update')
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Verify parser implementation reference was updated when needed
- name: Verify parser references were updated when needed
env:
BASE_SHA: ${{ github.event.pull_request.base.sha }}
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
Expand All @@ -45,28 +46,93 @@ jobs:
exit 0
fi

DOC_CHANGED=false
if echo "$CHANGED_FILES" | grep -Fxq "docs/fortran/parser_implementation_reference.md"; then
DOC_CHANGED=true
C_DOC="docs/c_parser.md"
FORTRAN_DOC="docs/fortran_parser.md"

C_DOC_CHANGED=false
FORTRAN_DOC_CHANGED=false
C_PARSER_CHANGED=false
FORTRAN_PARSER_CHANGED=false
SHARED_PARSER_CHANGED=false

if printf '%s\n' "$CHANGED_FILES" | grep -Fxq "$C_DOC"; then
C_DOC_CHANGED=true
fi
if printf '%s\n' "$CHANGED_FILES" | grep -Fxq "$FORTRAN_DOC"; then
FORTRAN_DOC_CHANGED=true
fi

while IFS= read -r changed_file; do
case "$changed_file" in
c_parser/*|tests/parser/c/*|tests/data/c/*|tests/parser/test_c_standard_type_probe.py)
C_PARSER_CHANGED=true
;;
fortran_parser/*|tests/parser/fortran/*|tests/data/fortran/*)
FORTRAN_PARSER_CHANGED=true
;;
tests/parser/test_declaration_and_interface_edges.py|\
tests/parser/test_error_handling.py|\
tests/parser/test_fortran_fixture_suite.py|\
tests/parser/test_fortran_json_sanity.py|\
tests/parser/test_fortran_parser_regression_contracts.py|\
tests/parser/test_fortran_type_probe.py|\
tests/parser/test_function_header_parsing.py|\
tests/parser/test_parser_developer_tutorial.py|\
tests/parser/test_parser_public_entrypoints.py|\
tests/parser/test_procedure_and_type_parsing.py|\
tests/parser/test_project_scope_models.py|\
tests/parser/test_scope_handling.py)
FORTRAN_PARSER_CHANGED=true
;;
tests/parser/conftest.py|\
tests/parser/test_cli.py|\
tests/parser/test_preprocessing_cli.py|\
x2py/preprocessing.py)
SHARED_PARSER_CHANGED=true
;;
esac
done <<< "$CHANGED_FILES"

if echo ",${PR_LABELS}," | grep -Fq ",${FORCE_LABEL},"; then
if [ "$DOC_CHANGED" = true ]; then
echo "${FORCE_LABEL} label present and doc updated."
exit 0
if [ "$C_DOC_CHANGED" = true ] || [ "$FORTRAN_DOC_CHANGED" = true ]; then
echo "${FORCE_LABEL} label present and at least one parser reference changed."
else
echo "${FORCE_LABEL} label present, but no parser reference changed."
echo "Update ${C_DOC} or ${FORTRAN_DOC}, or remove ${FORCE_LABEL}."
exit 1
fi
echo "${FORCE_LABEL} label present, but doc not updated."
exit 1
fi

if [ "$DOC_CHANGED" = true ]; then
echo "docs/fortran/parser_implementation_reference.md changed."
exit 0
FAILED=false

if [ "$C_PARSER_CHANGED" = true ] && [ "$C_DOC_CHANGED" != true ]; then
echo "C parser-related files changed without updating ${C_DOC}."
FAILED=true
fi

if echo "$CHANGED_FILES" | grep -Eq "^(fortran_parser/|tests/parser/|tests/data/fortran/)"; then
echo "Parser-related files changed without updating docs/fortran/parser_implementation_reference.md."
if [ "$FORTRAN_PARSER_CHANGED" = true ] && [ "$FORTRAN_DOC_CHANGED" != true ]; then
echo "Fortran parser-related files changed without updating ${FORTRAN_DOC}."
FAILED=true
fi

if [ "$SHARED_PARSER_CHANGED" = true ] && \
[ "$C_DOC_CHANGED" != true ] && \
[ "$FORTRAN_DOC_CHANGED" != true ]; then
echo "Shared parser workflow files changed without updating a parser reference."
echo "Update ${C_DOC} or ${FORTRAN_DOC}, whichever behavior changed."
FAILED=true
fi

if [ "$FAILED" = true ]; then
echo "Use ${IGNORE_LABEL} only when the parser reference is already accurate."
exit 1
fi

echo "No parser-related files changed; update not required."
if [ "$C_DOC_CHANGED" = true ]; then
echo "${C_DOC} changed."
fi
if [ "$FORTRAN_DOC_CHANGED" = true ]; then
echo "${FORTRAN_DOC} changed."
fi

echo "Parser reference guard passed."
78 changes: 78 additions & 0 deletions .github/workflows/quality.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
name: Quality

on:
pull_request:
types: [opened, synchronize, reopened]
push:
branches:
- main
- release/*

jobs:
static-analysis:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Install QA dependencies
run: |
python -m pip install --upgrade pip
python -m pip install -e ".[qa]"
- name: Ruff lint
run: python -m ruff check .
- name: Ruff format
run: python -m ruff format --check .
- name: Bandit security scan
run: bandit -c pyproject.toml -r c_parser fortran_parser semantics x2py --severity-level medium --confidence-level medium
- name: pip-audit dependency scan
run: pip-audit . --cache-dir /tmp/pip-audit-cache
- name: Vulture dead-code scan
run: vulture
- name: Radon complexity policy
env:
PR_BASE_SHA: ${{ github.event.pull_request.base.sha }}
PUSH_BEFORE_SHA: ${{ github.event.before }}
run: python tools/check_radon_policy.py --base-ref auto
- name: Radon complexity report
continue-on-error: true
run: radon cc c_parser fortran_parser semantics x2py -n C -s --total-average
- name: Radon maintainability report
continue-on-error: true
run: radon mi c_parser fortran_parser semantics x2py -s

# Benchmark workflow is intentionally parked for later activation.
# benchmark:
# if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'
# runs-on: ubuntu-latest
# timeout-minutes: 15
# permissions:
# contents: read
# steps:
# - name: Checkout repository
# uses: actions/checkout@v4
# - name: Set up Python
# uses: actions/setup-python@v5
# with:
# python-version: "3.12"
# - name: Install QA dependencies
# run: |
# python -m pip install --upgrade pip
# python -m pip install -e ".[qa]"
# - name: Run parser benchmarks
# env:
# PYTHONPATH: .
# run: python -m pytest -q tests/benchmarks -m benchmark --benchmark-only --benchmark-json=benchmark.json
# - name: Upload benchmark report
# uses: actions/upload-artifact@v4
# with:
# name: parser-benchmark-${{ github.run_id }}
# path: benchmark.json
# retention-days: 90
5 changes: 3 additions & 2 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,13 @@ jobs:
- name: Install test dependencies
run: |
python -m pip install --upgrade pip
python -m pip install -e . pytest coverage
python -m pip install -e ".[qa]"
- name: Run tests
env:
PYTHONPATH: .
COVERAGE_PROCESS_START: ${{ github.workspace }}/pyproject.toml
run: python -m coverage run -m pytest -q
HYPOTHESIS_PROFILE: ci
run: python -m coverage run -m pytest -q --randomly-seed=1
- name: Combine coverage data
run: python -m coverage combine
- name: Report coverage
Expand Down
9 changes: 9 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
__pycache__
__pyccel__
.pymon
.coverage
.coverage.*
.hypothesis/
.mutmut-cache/
mutants/
.pytest_cache/
.ruff_cache/
.benchmarks/
htmlcov/

*.pyc
*.pyo
Expand Down
19 changes: 17 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,25 @@

- **CI must be green before merging**: do not merge a PR unless all checks pass (including `test` and `parser-reference-guard`).
- **Explain fixture/golden updates**: if you update any JSON under `tests/data/fortran/` or `tests/parser/fortran/fixtures/`, include a short note in the PR describing why the expected output changed.
- **Run the QA stack for parser/compiler changes**: install `python -m pip install -e ".[qa]"`, use the workflows in `docs/quality.md`, and update that file when a staged adoption task or scheduled triage item changes.

### Parser reference guard

This repo includes a CI guard that may require updating `docs/fortran/parser_implementation_reference.md` when parser-related files change.
This repo includes a CI guard that may require updating parser reference docs
when parser-related files change.

- **Default behavior**: if you change `fortran_parser/` or `tests/data/fortran/`, update `docs/fortran/parser_implementation_reference.md` when the change affects the documented feature inventory or behavior.
- **C parser changes**: if you change `c_parser/`, `tests/parser/c/`, or
`tests/data/c/`, update `docs/c_parser.md` when the change affects the
documented feature inventory, public API, diagnostics, fixtures, semantic
handoff, or maintenance workflow. The guard also treats
`tests/parser/test_c_standard_type_probe.py` as C parser related.
- **Fortran parser changes**: if you change `fortran_parser/`,
`tests/parser/fortran/`, or `tests/data/fortran/`, update
`docs/fortran_parser.md` when the change affects the documented feature
inventory, public API, diagnostics, fixtures, semantic handoff, or
maintenance workflow. The guard also tracks focused Fortran parser tests
directly under `tests/parser/`.
- **Shared parser workflow changes**: if you change shared parser CLI or
preprocessing behavior, update `docs/c_parser.md` or
`docs/fortran_parser.md`, whichever parser behavior changed.
- **Bypass (use sparingly)**: add the PR label `ignore-parser-reference-guard` to skip that guard for changes that do not meaningfully affect the reference.
Loading
Loading