Skip to content

Commit 1a9ef48

Browse files
committed
Update dependencies and enhance CI workflows
- Added `antlr4-python3-runtime` to runtime and development dependencies in `pyproject.toml` and `requirements.txt`. - Expanded `hiddenimports` in `Blinter.spec` to include additional ANTLR components. - Updated CI workflows to include new smoke tests for the executable and improved static analysis checks with `autopep8`. - Revised README.md to reflect changes in CI processes and testing scripts.
1 parent af9ae1b commit 1a9ef48

8 files changed

Lines changed: 126 additions & 9 deletions

File tree

.github/workflows/Build-Release-PYPI.yml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ jobs:
127127
python -m pip install --upgrade wheel
128128
python -m pip install --upgrade pyinstaller
129129
python -m pip install --upgrade -r requirements.txt
130+
python -m pip install -e .
130131
shell: pwsh
131132

132133
- name: Generate version info file
@@ -148,6 +149,16 @@ jobs:
148149
}
149150
shell: pwsh
150151

152+
- name: Run cmd.exe corpus oracle
153+
run: |
154+
.\venv\Scripts\Activate.ps1
155+
python scripts/spec/cmd_oracle.py
156+
shell: pwsh
157+
158+
- name: Smoke test executable
159+
run: .\scripts\test_exe_smoke.ps1 -ExePath .\dist\Blinter.exe
160+
shell: pwsh
161+
151162
- name: Rename executable
152163
run: |
153164
Rename-Item -Path dist/Blinter.exe -NewName "Blinter-v${{ steps.version.outputs.version }}.exe"

.github/workflows/test.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ jobs:
2727
exit 1
2828
}
2929
30+
- name: Fetch batch-spec tags
31+
run: git -C vendor/batch-spec fetch --tags origin
32+
3033
- name: Set up Python
3134
uses: actions/setup-python@v6
3235
with:
@@ -41,6 +44,7 @@ jobs:
4144
run: |
4245
python -m black --check src tests scripts
4346
python -m isort --check-only src tests scripts
47+
python -m autopep8 --select=W291,W293 --diff -r src tests scripts
4448
python scripts/spec/validate_spec.py
4549
python scripts/spec/validate_corpus.py
4650
python scripts/spec/generate_rules.py --check
@@ -53,6 +57,7 @@ jobs:
5357
python -m mypy src/blinter tests scripts/verify.py
5458
python -m pylint src/blinter
5559
python -m bandit -r src/blinter -c pyproject.toml -ll -q
60+
python -m pip-audit -r requirements.txt -r requirements-dev.txt
5661
5762
test-python:
5863
name: pytest (Python ${{ matrix.python-version }})

Blinter.spec

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,15 @@ a = Analysis(
2121
('src/blinter/py.typed', 'blinter'),
2222
('pyproject.toml', '.'),
2323
],
24-
hiddenimports=['blinter', 'charset_normalizer'],
24+
hiddenimports=[
25+
'blinter',
26+
'charset_normalizer',
27+
'antlr4',
28+
'antlr4.error.ErrorListener',
29+
'antlr4.error.ErrorStrategy',
30+
'antlr4.error.Errors',
31+
'antlr4.tree.Tree',
32+
],
2533
hookspath=[],
2634
hooksconfig={},
2735
runtime_hooks=[],

README.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -493,12 +493,13 @@ Optional manual steps (same checks as `verify.py`):
493493

494494
```bash
495495
py -m pytest
496-
py -m mypy src/blinter tests
496+
py -m mypy src/blinter tests scripts/verify.py
497497
py -m pylint src/blinter --output-format=text > pylint-output.txt
498498
py -m bandit -r src/blinter
499499
py -m pip-audit -r requirements.txt -r requirements-dev.txt
500-
py -m black --check src tests
501-
py -m isort --check-only src tests
500+
py -m autopep8 --select=W291,W293 --diff -r src tests scripts
501+
py -m black --check src tests scripts
502+
py -m isort --check-only src tests scripts
502503
```
503504

504505
### SSOT corpus tests
@@ -522,7 +523,7 @@ py scripts/spec/generate_docs.py
522523

523524
See [`spec/README.md`](spec/README.md) for the full SSOT layout.
524525

525-
The test suite enforces 90% branch coverage (`pytest.ini`, `.coveragerc`). CI runs pytest on Python 3.11–3.14, static analysis (black, isort, mypy, pylint, bandit), and Windows executable smoke tests on every push and pull request to `main`. Releases run automatically when `version` in `pyproject.toml` is bumped on `main`.
526+
The test suite enforces 90% branch coverage (`pytest.ini`, `.coveragerc`). CI runs pytest on Python 3.11–3.14, static analysis (autopep8, black, isort, mypy, pylint, bandit, pip-audit), SSOT drift checks, and Windows executable smoke tests on every push and pull request to `main`. Releases run automatically when `version` in `pyproject.toml` is bumped on `main`.
526527

527528
See [docs/Architecture.md](docs/Architecture.md) for module layout and extension points.
528529

pyproject.toml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,10 @@ classifiers = [
3232
"Environment :: Console",
3333
]
3434
requires-python = ">=3.11"
35-
dependencies = ["charset_normalizer"]
35+
dependencies = [
36+
"charset_normalizer",
37+
"antlr4-python3-runtime",
38+
]
3639

3740
[project.optional-dependencies]
3841
dev = [
@@ -54,7 +57,6 @@ dev = [
5457
"types-PyYAML",
5558
"jsonschema",
5659
"antlr4-tools",
57-
"antlr4-python3-runtime",
5860
# Code Formatting
5961
"black",
6062
"isort",

requirements-dev.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ pyyaml
1919
types-PyYAML
2020
jsonschema
2121
antlr4-tools
22-
antlr4-python3-runtime
2322

2423
# Security Analysis
2524
pip-audit

requirements.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
1-
# Required runtime dependency for encoding detection
1+
# Required runtime dependencies
22
charset_normalizer
3+
antlr4-python3-runtime

tests/test_runtime_dependencies.py

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
"""Tests that production runtime dependencies are declared and importable."""
2+
3+
from __future__ import annotations
4+
5+
from pathlib import Path
6+
import subprocess
7+
import sys
8+
import tomllib
9+
from typing import Final
10+
11+
import pytest
12+
13+
_REPO_ROOT = Path(__file__).resolve().parent.parent
14+
_PYPROJECT = _REPO_ROOT / "pyproject.toml"
15+
_REQUIREMENTS = _REPO_ROOT / "requirements.txt"
16+
17+
# Import-time runtime dependencies required for lint_batch_file to work.
18+
_REQUIRED_RUNTIME_PACKAGES: Final[tuple[str, ...]] = (
19+
"charset_normalizer",
20+
"antlr4-python3-runtime",
21+
)
22+
23+
24+
def _read_pyproject_dependencies() -> list[str]:
25+
data = tomllib.loads(_PYPROJECT.read_text(encoding="utf-8"))
26+
deps = data["project"]["dependencies"]
27+
assert isinstance(deps, list)
28+
return [str(dep) for dep in deps]
29+
30+
31+
def _read_requirements_packages() -> set[str]:
32+
packages: set[str] = set()
33+
for line in _REQUIREMENTS.read_text(encoding="utf-8").splitlines():
34+
stripped = line.strip()
35+
if not stripped or stripped.startswith("#"):
36+
continue
37+
packages.add(stripped.split()[0])
38+
return packages
39+
40+
41+
class TestRuntimeDependencies:
42+
"""Ensure production installs include every import-time dependency."""
43+
44+
def test_pyproject_declares_required_runtime_packages(self) -> None:
45+
"""pyproject.toml must list all packages needed at import/lint time."""
46+
declared = {dep.split("[")[0] for dep in _read_pyproject_dependencies()}
47+
for package in _REQUIRED_RUNTIME_PACKAGES:
48+
assert (
49+
package in declared
50+
), f"{package} missing from pyproject.toml [project].dependencies"
51+
52+
def test_requirements_txt_matches_pyproject_runtime_deps(self) -> None:
53+
"""requirements.txt must mirror pyproject.toml runtime dependencies."""
54+
pyproject_deps = {dep.split("[")[0] for dep in _read_pyproject_dependencies()}
55+
requirements_deps = _read_requirements_packages()
56+
assert pyproject_deps == requirements_deps
57+
58+
@pytest.mark.slow
59+
def test_minimal_editable_install_imports_lint_api(self, tmp_path: Path) -> None:
60+
"""pip install -e . without [dev] must expose lint_batch_file."""
61+
venv_dir = tmp_path / "minimal-venv"
62+
subprocess.run(
63+
[sys.executable, "-m", "venv", str(venv_dir)],
64+
check=True,
65+
timeout=120,
66+
)
67+
if sys.platform == "win32":
68+
python = venv_dir / "Scripts" / "python.exe"
69+
pip = venv_dir / "Scripts" / "pip.exe"
70+
else:
71+
python = venv_dir / "bin" / "python"
72+
pip = venv_dir / "bin" / "pip"
73+
74+
subprocess.run(
75+
[str(pip), "install", "-q", "-e", str(_REPO_ROOT)],
76+
check=True,
77+
timeout=300,
78+
)
79+
result = subprocess.run(
80+
[
81+
str(python),
82+
"-c",
83+
"from blinter import lint_batch_file; print('ok')",
84+
],
85+
check=False,
86+
capture_output=True,
87+
text=True,
88+
timeout=60,
89+
)
90+
assert result.returncode == 0, result.stderr or result.stdout

0 commit comments

Comments
 (0)