Skip to content

Commit 5fc5bba

Browse files
authored
Merge pull request #40 from PyNumLab/tools
add tool adoptions
1 parent dfa0ced commit 5fc5bba

145 files changed

Lines changed: 161732 additions & 280230 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.github/workflows/fuzz.yml‎

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
name: Fuzz
2+
3+
on:
4+
schedule:
5+
- cron: "17 3 * * 1"
6+
workflow_dispatch:
7+
8+
jobs:
9+
fuzz:
10+
runs-on: ubuntu-latest
11+
timeout-minutes: 15
12+
permissions:
13+
contents: read
14+
steps:
15+
- name: Checkout repository
16+
uses: actions/checkout@v4
17+
- name: Set up Python
18+
uses: actions/setup-python@v5
19+
with:
20+
python-version: "3.12"
21+
- name: Install QA dependencies
22+
run: |
23+
python -m pip install --upgrade pip
24+
python -m pip install -e ".[qa]"
25+
- name: Run bounded parser fuzz tests
26+
env:
27+
PYTHONPATH: .
28+
HYPOTHESIS_PROFILE: fuzz
29+
run: python -m pytest -q tests/property -m fuzz --hypothesis-show-statistics

‎.github/workflows/parser-reference-guard.yml‎

Lines changed: 82 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,15 @@ jobs:
1111
(github.event.action == 'opened' ||
1212
github.event.action == 'synchronize' ||
1313
github.event.action == 'reopened' ||
14-
github.event.label.name == 'ignore-parser-reference-guard')
14+
github.event.label.name == 'ignore-parser-reference-guard' ||
15+
github.event.label.name == 'require-parser-reference-update')
1516
runs-on: ubuntu-latest
1617
steps:
1718
- name: Checkout repository
1819
uses: actions/checkout@v4
1920
with:
2021
fetch-depth: 0
21-
- name: Verify parser implementation reference was updated when needed
22+
- name: Verify parser references were updated when needed
2223
env:
2324
BASE_SHA: ${{ github.event.pull_request.base.sha }}
2425
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
@@ -45,28 +46,93 @@ jobs:
4546
exit 0
4647
fi
4748
48-
DOC_CHANGED=false
49-
if echo "$CHANGED_FILES" | grep -Fxq "docs/fortran/parser_implementation_reference.md"; then
50-
DOC_CHANGED=true
49+
C_DOC="docs/c_parser.md"
50+
FORTRAN_DOC="docs/fortran_parser.md"
51+
52+
C_DOC_CHANGED=false
53+
FORTRAN_DOC_CHANGED=false
54+
C_PARSER_CHANGED=false
55+
FORTRAN_PARSER_CHANGED=false
56+
SHARED_PARSER_CHANGED=false
57+
58+
if printf '%s\n' "$CHANGED_FILES" | grep -Fxq "$C_DOC"; then
59+
C_DOC_CHANGED=true
5160
fi
61+
if printf '%s\n' "$CHANGED_FILES" | grep -Fxq "$FORTRAN_DOC"; then
62+
FORTRAN_DOC_CHANGED=true
63+
fi
64+
65+
while IFS= read -r changed_file; do
66+
case "$changed_file" in
67+
c_parser/*|tests/parser/c/*|tests/data/c/*|tests/parser/test_c_standard_type_probe.py)
68+
C_PARSER_CHANGED=true
69+
;;
70+
fortran_parser/*|tests/parser/fortran/*|tests/data/fortran/*)
71+
FORTRAN_PARSER_CHANGED=true
72+
;;
73+
tests/parser/test_declaration_and_interface_edges.py|\
74+
tests/parser/test_error_handling.py|\
75+
tests/parser/test_fortran_fixture_suite.py|\
76+
tests/parser/test_fortran_json_sanity.py|\
77+
tests/parser/test_fortran_parser_regression_contracts.py|\
78+
tests/parser/test_fortran_type_probe.py|\
79+
tests/parser/test_function_header_parsing.py|\
80+
tests/parser/test_parser_developer_tutorial.py|\
81+
tests/parser/test_parser_public_entrypoints.py|\
82+
tests/parser/test_procedure_and_type_parsing.py|\
83+
tests/parser/test_project_scope_models.py|\
84+
tests/parser/test_scope_handling.py)
85+
FORTRAN_PARSER_CHANGED=true
86+
;;
87+
tests/parser/conftest.py|\
88+
tests/parser/test_cli.py|\
89+
tests/parser/test_preprocessing_cli.py|\
90+
x2py/preprocessing.py)
91+
SHARED_PARSER_CHANGED=true
92+
;;
93+
esac
94+
done <<< "$CHANGED_FILES"
5295
5396
if echo ",${PR_LABELS}," | grep -Fq ",${FORCE_LABEL},"; then
54-
if [ "$DOC_CHANGED" = true ]; then
55-
echo "${FORCE_LABEL} label present and doc updated."
56-
exit 0
97+
if [ "$C_DOC_CHANGED" = true ] || [ "$FORTRAN_DOC_CHANGED" = true ]; then
98+
echo "${FORCE_LABEL} label present and at least one parser reference changed."
99+
else
100+
echo "${FORCE_LABEL} label present, but no parser reference changed."
101+
echo "Update ${C_DOC} or ${FORTRAN_DOC}, or remove ${FORCE_LABEL}."
102+
exit 1
57103
fi
58-
echo "${FORCE_LABEL} label present, but doc not updated."
59-
exit 1
60104
fi
61105
62-
if [ "$DOC_CHANGED" = true ]; then
63-
echo "docs/fortran/parser_implementation_reference.md changed."
64-
exit 0
106+
FAILED=false
107+
108+
if [ "$C_PARSER_CHANGED" = true ] && [ "$C_DOC_CHANGED" != true ]; then
109+
echo "C parser-related files changed without updating ${C_DOC}."
110+
FAILED=true
65111
fi
66112
67-
if echo "$CHANGED_FILES" | grep -Eq "^(fortran_parser/|tests/parser/|tests/data/fortran/)"; then
68-
echo "Parser-related files changed without updating docs/fortran/parser_implementation_reference.md."
113+
if [ "$FORTRAN_PARSER_CHANGED" = true ] && [ "$FORTRAN_DOC_CHANGED" != true ]; then
114+
echo "Fortran parser-related files changed without updating ${FORTRAN_DOC}."
115+
FAILED=true
116+
fi
117+
118+
if [ "$SHARED_PARSER_CHANGED" = true ] && \
119+
[ "$C_DOC_CHANGED" != true ] && \
120+
[ "$FORTRAN_DOC_CHANGED" != true ]; then
121+
echo "Shared parser workflow files changed without updating a parser reference."
122+
echo "Update ${C_DOC} or ${FORTRAN_DOC}, whichever behavior changed."
123+
FAILED=true
124+
fi
125+
126+
if [ "$FAILED" = true ]; then
127+
echo "Use ${IGNORE_LABEL} only when the parser reference is already accurate."
69128
exit 1
70129
fi
71130
72-
echo "No parser-related files changed; update not required."
131+
if [ "$C_DOC_CHANGED" = true ]; then
132+
echo "${C_DOC} changed."
133+
fi
134+
if [ "$FORTRAN_DOC_CHANGED" = true ]; then
135+
echo "${FORTRAN_DOC} changed."
136+
fi
137+
138+
echo "Parser reference guard passed."

‎.github/workflows/quality.yml‎

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
name: Quality
2+
3+
on:
4+
pull_request:
5+
types: [opened, synchronize, reopened]
6+
push:
7+
branches:
8+
- main
9+
- release/*
10+
11+
jobs:
12+
static-analysis:
13+
runs-on: ubuntu-latest
14+
permissions:
15+
contents: read
16+
steps:
17+
- name: Checkout repository
18+
uses: actions/checkout@v4
19+
with:
20+
fetch-depth: 0
21+
- name: Set up Python
22+
uses: actions/setup-python@v5
23+
with:
24+
python-version: "3.12"
25+
- name: Install QA dependencies
26+
run: |
27+
python -m pip install --upgrade pip
28+
python -m pip install -e ".[qa]"
29+
- name: Ruff lint
30+
run: python -m ruff check .
31+
- name: Ruff format
32+
run: python -m ruff format --check .
33+
- name: Bandit security scan
34+
run: bandit -c pyproject.toml -r c_parser fortran_parser semantics x2py --severity-level medium --confidence-level medium
35+
- name: pip-audit dependency scan
36+
run: pip-audit . --cache-dir /tmp/pip-audit-cache
37+
- name: Vulture dead-code scan
38+
run: vulture
39+
- name: Radon complexity policy
40+
env:
41+
PR_BASE_SHA: ${{ github.event.pull_request.base.sha }}
42+
PUSH_BEFORE_SHA: ${{ github.event.before }}
43+
run: python tools/check_radon_policy.py --base-ref auto
44+
- name: Radon complexity report
45+
continue-on-error: true
46+
run: radon cc c_parser fortran_parser semantics x2py -n C -s --total-average
47+
- name: Radon maintainability report
48+
continue-on-error: true
49+
run: radon mi c_parser fortran_parser semantics x2py -s
50+
51+
# Benchmark workflow is intentionally parked for later activation.
52+
# benchmark:
53+
# if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'
54+
# runs-on: ubuntu-latest
55+
# timeout-minutes: 15
56+
# permissions:
57+
# contents: read
58+
# steps:
59+
# - name: Checkout repository
60+
# uses: actions/checkout@v4
61+
# - name: Set up Python
62+
# uses: actions/setup-python@v5
63+
# with:
64+
# python-version: "3.12"
65+
# - name: Install QA dependencies
66+
# run: |
67+
# python -m pip install --upgrade pip
68+
# python -m pip install -e ".[qa]"
69+
# - name: Run parser benchmarks
70+
# env:
71+
# PYTHONPATH: .
72+
# run: python -m pytest -q tests/benchmarks -m benchmark --benchmark-only --benchmark-json=benchmark.json
73+
# - name: Upload benchmark report
74+
# uses: actions/upload-artifact@v4
75+
# with:
76+
# name: parser-benchmark-${{ github.run_id }}
77+
# path: benchmark.json
78+
# retention-days: 90

‎.github/workflows/tests.yml‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,13 @@ jobs:
3030
- name: Install test dependencies
3131
run: |
3232
python -m pip install --upgrade pip
33-
python -m pip install -e . pytest coverage
33+
python -m pip install -e ".[qa]"
3434
- name: Run tests
3535
env:
3636
PYTHONPATH: .
3737
COVERAGE_PROCESS_START: ${{ github.workspace }}/pyproject.toml
38-
run: python -m coverage run -m pytest -q
38+
HYPOTHESIS_PROFILE: ci
39+
run: python -m coverage run -m pytest -q --randomly-seed=1
3940
- name: Combine coverage data
4041
run: python -m coverage combine
4142
- name: Report coverage

‎.gitignore‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,15 @@
11
__pycache__
22
__pyccel__
33
.pymon
4+
.coverage
5+
.coverage.*
6+
.hypothesis/
7+
.mutmut-cache/
8+
mutants/
9+
.pytest_cache/
10+
.ruff_cache/
11+
.benchmarks/
12+
htmlcov/
413

514
*.pyc
615
*.pyo

‎CONTRIBUTING.md‎

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,25 @@
44

55
- **CI must be green before merging**: do not merge a PR unless all checks pass (including `test` and `parser-reference-guard`).
66
- **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.
7+
- **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.
78

89
### Parser reference guard
910

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

12-
- **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.
14+
- **C parser changes**: if you change `c_parser/`, `tests/parser/c/`, or
15+
`tests/data/c/`, update `docs/c_parser.md` when the change affects the
16+
documented feature inventory, public API, diagnostics, fixtures, semantic
17+
handoff, or maintenance workflow. The guard also treats
18+
`tests/parser/test_c_standard_type_probe.py` as C parser related.
19+
- **Fortran parser changes**: if you change `fortran_parser/`,
20+
`tests/parser/fortran/`, or `tests/data/fortran/`, update
21+
`docs/fortran_parser.md` when the change affects the documented feature
22+
inventory, public API, diagnostics, fixtures, semantic handoff, or
23+
maintenance workflow. The guard also tracks focused Fortran parser tests
24+
directly under `tests/parser/`.
25+
- **Shared parser workflow changes**: if you change shared parser CLI or
26+
preprocessing behavior, update `docs/c_parser.md` or
27+
`docs/fortran_parser.md`, whichever parser behavior changed.
1328
- **Bypass (use sparingly)**: add the PR label `ignore-parser-reference-guard` to skip that guard for changes that do not meaningfully affect the reference.

0 commit comments

Comments
 (0)