gawain 0.1.0__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 (86) hide show
  1. gawain-0.1.0/.github/workflows/ci.yml +88 -0
  2. gawain-0.1.0/.github/workflows/release.yml +152 -0
  3. gawain-0.1.0/.gitignore +12 -0
  4. gawain-0.1.0/.pre-commit-hooks.yaml +6 -0
  5. gawain-0.1.0/Cargo.lock +1030 -0
  6. gawain-0.1.0/Cargo.toml +26 -0
  7. gawain-0.1.0/LICENSE +21 -0
  8. gawain-0.1.0/PKG-INFO +198 -0
  9. gawain-0.1.0/README.md +175 -0
  10. gawain-0.1.0/docs/assets/gawain-dark.svg +14 -0
  11. gawain-0.1.0/docs/assets/gawain-wordmark-dark.svg +15 -0
  12. gawain-0.1.0/docs/assets/gawain-wordmark.svg +15 -0
  13. gawain-0.1.0/docs/assets/gawain.svg +14 -0
  14. gawain-0.1.0/docs/benchmarks.md +54 -0
  15. gawain-0.1.0/docs/configuration.md +79 -0
  16. gawain-0.1.0/docs/rules.md +123 -0
  17. gawain-0.1.0/pyproject.toml +35 -0
  18. gawain-0.1.0/scripts/compare.py +2045 -0
  19. gawain-0.1.0/src/config.rs +90 -0
  20. gawain-0.1.0/src/diagnostics.rs +93 -0
  21. gawain-0.1.0/src/discovery.rs +209 -0
  22. gawain-0.1.0/src/lib.rs +10 -0
  23. gawain-0.1.0/src/main.rs +228 -0
  24. gawain-0.1.0/src/modules.rs +525 -0
  25. gawain-0.1.0/src/presence/annotations.rs +66 -0
  26. gawain-0.1.0/src/presence/any_check.rs +307 -0
  27. gawain-0.1.0/src/presence/class_index.rs +428 -0
  28. gawain-0.1.0/src/presence/mod.rs +355 -0
  29. gawain-0.1.0/src/presence/obvious.rs +188 -0
  30. gawain-0.1.0/src/presence/scopes.rs +296 -0
  31. gawain-0.1.0/src/presence/visitor.rs +755 -0
  32. gawain-0.1.0/src/report.rs +201 -0
  33. gawain-0.1.0/src/suppression.rs +268 -0
  34. gawain-0.1.0/src/types_phase.rs +281 -0
  35. gawain-0.1.0/tests/cli.rs +2036 -0
  36. gawain-0.1.0/tests/fixtures/any_ban.py +77 -0
  37. gawain-0.1.0/tests/fixtures/any_nested_shadow.py +10 -0
  38. gawain-0.1.0/tests/fixtures/any_shadow.py +15 -0
  39. gawain-0.1.0/tests/fixtures/any_star.py +5 -0
  40. gawain-0.1.0/tests/fixtures/any_star_shadow.py +6 -0
  41. gawain-0.1.0/tests/fixtures/any_star_te.py +5 -0
  42. gawain-0.1.0/tests/fixtures/classes.py +197 -0
  43. gawain-0.1.0/tests/fixtures/constants.py +55 -0
  44. gawain-0.1.0/tests/fixtures/duplicate_class.py +11 -0
  45. gawain-0.1.0/tests/fixtures/duplicate_class_bodies.py +9 -0
  46. gawain-0.1.0/tests/fixtures/fully_annotated.py +11 -0
  47. gawain-0.1.0/tests/fixtures/functions.py +240 -0
  48. gawain-0.1.0/tests/fixtures/pkg_inherit/app/__init__.py +1 -0
  49. gawain-0.1.0/tests/fixtures/pkg_inherit/app/derived.py +7 -0
  50. gawain-0.1.0/tests/fixtures/pkg_inherit/app/ext.py +8 -0
  51. gawain-0.1.0/tests/fixtures/pkg_inherit/app/loop_a.py +6 -0
  52. gawain-0.1.0/tests/fixtures/pkg_inherit/app/loop_b.py +1 -0
  53. gawain-0.1.0/tests/fixtures/pkg_inherit/app/models.py +2 -0
  54. gawain-0.1.0/tests/fixtures/pkg_inherit/app/pkgref.py +19 -0
  55. gawain-0.1.0/tests/fixtures/pkg_inherit/app/reexport.py +1 -0
  56. gawain-0.1.0/tests/fixtures/pkg_inherit/app/users.py +14 -0
  57. gawain-0.1.0/tests/fixtures/rebound_class_name.py +24 -0
  58. gawain-0.1.0/tests/fixtures/suppression.py +56 -0
  59. gawain-0.1.0/tests/fixtures/variables.py +259 -0
  60. gawain-0.1.0/tests/fixtures.rs +265 -0
  61. gawain-0.1.0/tests/fixtures_obvious/classes.py +97 -0
  62. gawain-0.1.0/tests/fixtures_obvious/constants.py +28 -0
  63. gawain-0.1.0/tests/fixtures_obvious/constructors.py +100 -0
  64. gawain-0.1.0/tests/fixtures_obvious/containers.py +32 -0
  65. gawain-0.1.0/tests/fixtures_obvious/generics/box.py +7 -0
  66. gawain-0.1.0/tests/fixtures_obvious/generics/use.py +29 -0
  67. gawain-0.1.0/tests/fixtures_obvious/inherit/base.py +8 -0
  68. gawain-0.1.0/tests/fixtures_obvious/inherit/child.py +8 -0
  69. gawain-0.1.0/tests/fixtures_obvious/inherit_rebound/kid.py +6 -0
  70. gawain-0.1.0/tests/fixtures_obvious/inherit_rebound/parent.py +7 -0
  71. gawain-0.1.0/tests/fixtures_obvious/literals.py +27 -0
  72. gawain-0.1.0/tests/fixtures_obvious/reassignment.py +159 -0
  73. gawain-0.1.0/tests/fixtures_obvious/star/box.py +11 -0
  74. gawain-0.1.0/tests/fixtures_obvious/star/external.py +4 -0
  75. gawain-0.1.0/tests/fixtures_obvious/star/use.py +7 -0
  76. gawain-0.1.0/tests/fixtures_obvious/typevar_import/tv.py +7 -0
  77. gawain-0.1.0/tests/fixtures_obvious/typevar_import/use.py +23 -0
  78. gawain-0.1.0/tests/python/conftest.py +13 -0
  79. gawain-0.1.0/tests/python/data/fixtures_report.txt +318 -0
  80. gawain-0.1.0/tests/python/data/inherit/package/__init__.py +0 -0
  81. gawain-0.1.0/tests/python/data/inherit/package/base.py +2 -0
  82. gawain-0.1.0/tests/python/data/inherit/package/box.py +6 -0
  83. gawain-0.1.0/tests/python/data/report/agree.py +1 -0
  84. gawain-0.1.0/tests/python/data/report/finals.py +4 -0
  85. gawain-0.1.0/tests/python/data/unexplained/unit.py +1 -0
  86. gawain-0.1.0/tests/python/test_compare.py +1300 -0
@@ -0,0 +1,88 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ workflow_dispatch:
8
+ workflow_call:
9
+
10
+ permissions:
11
+ contents: read
12
+
13
+ concurrency:
14
+ group: ci-${{ github.workflow }}-${{ github.ref }}
15
+ cancel-in-progress: true
16
+
17
+ env:
18
+ CARGO_TERM_COLOR: always
19
+
20
+ jobs:
21
+ rust:
22
+ name: Rust tests (${{ matrix.os }})
23
+ runs-on: ${{ matrix.os }}
24
+ strategy:
25
+ fail-fast: false
26
+ matrix:
27
+ os: [ubuntu-latest, macos-latest]
28
+ steps:
29
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
30
+ - uses: dtolnay/rust-toolchain@b725eda525362e7cf34af9a7243cac1e3f01a7ec # stable
31
+ with:
32
+ toolchain: stable
33
+ components: clippy, rustfmt
34
+ - uses: Swatinem/rust-cache@d1527c8f67ef9af357290475d4af4b0fab8f12e0 # v2.9.3
35
+ - uses: astral-sh/setup-uv@68559e99cc807c1eb7e9238fd43a15bba460eec2 # v10.3.3
36
+ - name: Install ty into .venv
37
+ run: |
38
+ uv venv --python 3.14 .venv
39
+ uv pip install --python .venv ty==0.0.100
40
+ - run: cargo fmt --check
41
+ - run: cargo clippy --all-targets -- -D warnings
42
+ - run: cargo test --no-fail-fast
43
+
44
+ python:
45
+ name: Differential tests and self-check
46
+ runs-on: ubuntu-latest
47
+ steps:
48
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
49
+ - uses: dtolnay/rust-toolchain@b725eda525362e7cf34af9a7243cac1e3f01a7ec # stable
50
+ with:
51
+ toolchain: stable
52
+ - uses: Swatinem/rust-cache@d1527c8f67ef9af357290475d4af4b0fab8f12e0 # v2.9.3
53
+ - uses: astral-sh/setup-uv@68559e99cc807c1eb7e9238fd43a15bba460eec2 # v10.3.3
54
+ - run: cargo build
55
+ - name: Differential tests against must-annotate
56
+ run: uv run --no-project --python 3.14 --with pytest --with must-annotate==0.1.2 python -m pytest tests/python
57
+ - name: gawain checks its own Python code
58
+ run: |
59
+ uv venv --python 3.14 .venv
60
+ uv pip install --python .venv ty==0.0.100 pytest
61
+ PATH="$PWD/.venv/bin:$PATH" target/debug/gawain check scripts tests/python
62
+
63
+ windows:
64
+ name: Windows smoke test
65
+ runs-on: windows-latest
66
+ defaults:
67
+ run:
68
+ shell: bash
69
+ steps:
70
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
71
+ - uses: dtolnay/rust-toolchain@b725eda525362e7cf34af9a7243cac1e3f01a7ec # stable
72
+ with:
73
+ toolchain: stable
74
+ - uses: Swatinem/rust-cache@d1527c8f67ef9af357290475d4af4b0fab8f12e0 # v2.9.3
75
+ - uses: astral-sh/setup-uv@68559e99cc807c1eb7e9238fd43a15bba460eec2 # v10.3.3
76
+ - run: cargo build --release
77
+ - name: Run gawain on a clean file and on a file with a missing annotation
78
+ run: |
79
+ uv venv --python 3.14 .venv
80
+ uv pip install --python .venv ty==0.0.100
81
+ export PATH="$PWD/.venv/Scripts:$PATH"
82
+ mkdir -p smoke/clean smoke/dirty
83
+ printf 'def add(a: int, b: int) -> int:\n return a + b\n' > smoke/clean/ok.py
84
+ printf 'total = sum([1, 2])\n' > smoke/dirty/bad.py
85
+ target/release/gawain.exe check smoke/clean
86
+ status=0
87
+ target/release/gawain.exe check smoke/dirty || status=$?
88
+ test "$status" -eq 1
@@ -0,0 +1,152 @@
1
+ name: Release
2
+
3
+ # A tag push (v0.1.0, ...) builds every wheel and the sdist, tests the wheels and publishes to PyPI.
4
+ # A manual run builds and tests the same files without publishing them.
5
+
6
+ on:
7
+ push:
8
+ tags: ["v*"]
9
+ workflow_dispatch:
10
+
11
+ permissions:
12
+ contents: read
13
+
14
+ jobs:
15
+ ci:
16
+ name: CI
17
+ uses: ./.github/workflows/ci.yml
18
+
19
+ version:
20
+ name: Tag matches the package version
21
+ if: github.event_name == 'push'
22
+ runs-on: ubuntu-latest
23
+ steps:
24
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
25
+ - name: Compare the tag with pyproject.toml and Cargo.toml
26
+ run: |
27
+ tag="${GITHUB_REF_NAME#v}"
28
+ py=$(python3 -c 'import tomllib; print(tomllib.load(open("pyproject.toml", "rb"))["project"]["version"])')
29
+ rs=$(python3 -c 'import tomllib; print(tomllib.load(open("Cargo.toml", "rb"))["package"]["version"])')
30
+ echo "tag=$tag pyproject=$py Cargo=$rs"
31
+ test "$tag" = "$py" && test "$tag" = "$rs"
32
+
33
+ wheels:
34
+ name: Wheel ${{ matrix.name }}
35
+ runs-on: ${{ matrix.runner }}
36
+ strategy:
37
+ fail-fast: false
38
+ matrix:
39
+ include:
40
+ - { name: linux-x86_64, runner: ubuntu-latest, target: x86_64, manylinux: auto }
41
+ - { name: linux-aarch64, runner: ubuntu-latest, target: aarch64, manylinux: auto }
42
+ - { name: musllinux-x86_64, runner: ubuntu-latest, target: x86_64, manylinux: musllinux_1_2 }
43
+ - { name: musllinux-aarch64, runner: ubuntu-latest, target: aarch64, manylinux: musllinux_1_2 }
44
+ - { name: macos-x86_64, runner: macos-15-intel, target: x86_64 }
45
+ - { name: macos-aarch64, runner: macos-latest, target: aarch64 }
46
+ - { name: windows-x64, runner: windows-latest, target: x64 }
47
+ steps:
48
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
49
+ - uses: PyO3/maturin-action@e83996d129638aa358a18fbd1dfb82f0b0fb5d3b # v1.51.0
50
+ with:
51
+ target: ${{ matrix.target }}
52
+ manylinux: ${{ matrix.manylinux }}
53
+ args: --release --locked --out dist
54
+ - uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
55
+ with:
56
+ name: dist-${{ matrix.name }}
57
+ path: dist
58
+
59
+ sdist:
60
+ name: Source distribution
61
+ runs-on: ubuntu-latest
62
+ steps:
63
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
64
+ - uses: PyO3/maturin-action@e83996d129638aa358a18fbd1dfb82f0b0fb5d3b # v1.51.0
65
+ with:
66
+ command: sdist
67
+ args: --out dist
68
+ - uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
69
+ with:
70
+ name: dist-sdist
71
+ path: dist
72
+
73
+ test-wheels:
74
+ name: Install and run (${{ matrix.os }})
75
+ needs: wheels
76
+ runs-on: ${{ matrix.os }}
77
+ strategy:
78
+ fail-fast: false
79
+ matrix:
80
+ os: [ubuntu-latest, ubuntu-24.04-arm, macos-latest, macos-15-intel, windows-latest]
81
+ defaults:
82
+ run:
83
+ shell: bash
84
+ steps:
85
+ - uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
86
+ with:
87
+ pattern: dist-*
88
+ merge-multiple: true
89
+ path: dist
90
+ - uses: astral-sh/setup-uv@68559e99cc807c1eb7e9238fd43a15bba460eec2 # v10.3.3
91
+ - name: Install the built wheel and run it on a clean file and on a file with a missing annotation
92
+ run: |
93
+ uv venv --python 3.14 .venv
94
+ uv pip install --python .venv ty==0.0.100
95
+ uv pip install --python .venv --no-index --find-links dist gawain
96
+ if [ -d .venv/Scripts ]; then bin=.venv/Scripts; else bin=.venv/bin; fi
97
+ export PATH="$PWD/$bin:$PATH"
98
+ mkdir -p smoke/clean smoke/dirty
99
+ printf 'def add(a: int, b: int) -> int:\n return a + b\n' > smoke/clean/ok.py
100
+ printf 'total = sum([1, 2])\n' > smoke/dirty/bad.py
101
+ gawain check smoke/clean
102
+ status=0
103
+ gawain check smoke/dirty || status=$?
104
+ test "$status" -eq 1
105
+
106
+ test-musl:
107
+ name: Install and run (musl, ${{ matrix.runner }})
108
+ needs: wheels
109
+ runs-on: ${{ matrix.runner }}
110
+ strategy:
111
+ fail-fast: false
112
+ matrix:
113
+ runner: [ubuntu-latest, ubuntu-24.04-arm]
114
+ steps:
115
+ - uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
116
+ with:
117
+ pattern: dist-musllinux-*
118
+ merge-multiple: true
119
+ path: dist
120
+ - name: Install the built wheel in Alpine and run it on a clean file and on a file with a missing annotation
121
+ run: |
122
+ docker run --rm -v "$PWD/dist:/dist:ro" python:3.14-alpine sh -euc '
123
+ python -m venv /venv
124
+ /venv/bin/pip install --quiet ty==0.0.100
125
+ /venv/bin/pip install --quiet --no-index --find-links /dist gawain
126
+ export PATH="/venv/bin:$PATH"
127
+ mkdir -p /smoke/clean /smoke/dirty
128
+ printf "def add(a: int, b: int) -> int:\n return a + b\n" > /smoke/clean/ok.py
129
+ printf "total = sum([1, 2])\n" > /smoke/dirty/bad.py
130
+ gawain check /smoke/clean
131
+ status=0
132
+ gawain check /smoke/dirty || status=$?
133
+ test "$status" -eq 1
134
+ '
135
+
136
+ publish-pypi:
137
+ name: Publish to PyPI
138
+ if: github.event_name == 'push'
139
+ needs: [ci, version, wheels, sdist, test-wheels, test-musl]
140
+ runs-on: ubuntu-latest
141
+ environment:
142
+ name: pypi
143
+ url: https://pypi.org/p/gawain
144
+ permissions:
145
+ id-token: write
146
+ steps:
147
+ - uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
148
+ with:
149
+ pattern: dist-*
150
+ merge-multiple: true
151
+ path: dist
152
+ - uses: pypa/gh-action-pypi-publish@7245906fb61fa33a13554f9d5fb856fe61758086 # v1.14.3
@@ -0,0 +1,12 @@
1
+ target/
2
+ .metrics/
3
+ .venv/
4
+ *.whl
5
+ __pycache__/
6
+ .coverage
7
+ uv.lock
8
+
9
+ # Internal development notes
10
+ docs/crap-exceptions.md
11
+ docs/differential.md
12
+ docs/glossary.md
@@ -0,0 +1,6 @@
1
+ - id: gawain
2
+ name: gawain
3
+ entry: gawain check
4
+ language: python
5
+ types: [python]
6
+ require_serial: true