pragyalint 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.
- pragyalint-0.1.0/.github/workflows/bins.yml +107 -0
- pragyalint-0.1.0/.github/workflows/pages.yml +36 -0
- pragyalint-0.1.0/.github/workflows/publish.yml +93 -0
- pragyalint-0.1.0/.github/workflows/tests.yml +28 -0
- pragyalint-0.1.0/.gitignore +52 -0
- pragyalint-0.1.0/CHANGELOG.md +37 -0
- pragyalint-0.1.0/LICENSE +662 -0
- pragyalint-0.1.0/PKG-INFO +221 -0
- pragyalint-0.1.0/README.md +199 -0
- pragyalint-0.1.0/config.md +59 -0
- pragyalint-0.1.0/extensions/vscode-pragyalint/.gitignore +5 -0
- pragyalint-0.1.0/extensions/vscode-pragyalint/README.md +49 -0
- pragyalint-0.1.0/extensions/vscode-pragyalint/package.json +80 -0
- pragyalint-0.1.0/extensions/vscode-pragyalint/src/extension.ts +152 -0
- pragyalint-0.1.0/extensions/vscode-pragyalint/tsconfig.json +15 -0
- pragyalint-0.1.0/pragyalint/__init__.py +3 -0
- pragyalint-0.1.0/pragyalint/__main__.py +6 -0
- pragyalint-0.1.0/pragyalint/analyzer.py +98 -0
- pragyalint-0.1.0/pragyalint/cli.py +258 -0
- pragyalint-0.1.0/pragyalint/config.py +80 -0
- pragyalint-0.1.0/pragyalint/finders/__init__.py +38 -0
- pragyalint-0.1.0/pragyalint/finders/cycles.py +27 -0
- pragyalint-0.1.0/pragyalint/finders/unused_exports.py +93 -0
- pragyalint-0.1.0/pragyalint/finders/unused_files.py +52 -0
- pragyalint-0.1.0/pragyalint/finders/unused_imports.py +104 -0
- pragyalint-0.1.0/pragyalint/finders/unused_local.py +114 -0
- pragyalint-0.1.0/pragyalint/fixer.py +391 -0
- pragyalint-0.1.0/pragyalint/graph.py +414 -0
- pragyalint-0.1.0/pragyalint/models.py +161 -0
- pragyalint-0.1.0/pragyalint/reporters/__init__.py +7 -0
- pragyalint-0.1.0/pragyalint/reporters/json.py +22 -0
- pragyalint-0.1.0/pragyalint/reporters/sarif.py +83 -0
- pragyalint-0.1.0/pragyalint/reporters/terminal.py +73 -0
- pragyalint-0.1.0/pyproject.toml +48 -0
- pragyalint-0.1.0/site/_redirects +1 -0
- pragyalint-0.1.0/site/css/style.css +817 -0
- pragyalint-0.1.0/site/docs/config.html +126 -0
- pragyalint-0.1.0/site/docs/faq.html +103 -0
- pragyalint-0.1.0/site/docs/fixes.html +130 -0
- pragyalint-0.1.0/site/docs/index.html +139 -0
- pragyalint-0.1.0/site/docs/install.html +63 -0
- pragyalint-0.1.0/site/favicon.svg +15 -0
- pragyalint-0.1.0/site/index.html +171 -0
- pragyalint-0.1.0/site/js/docs.js +35 -0
- pragyalint-0.1.0/site/js/layout.js +73 -0
- pragyalint-0.1.0/site/js/main.js +315 -0
- pragyalint-0.1.0/site/logo.html +167 -0
- pragyalint-0.1.0/site/wrangler.toml +3 -0
- pragyalint-0.1.0/tests/__init__.py +0 -0
- pragyalint-0.1.0/tests/conftest.py +1 -0
- pragyalint-0.1.0/tests/helpers.py +41 -0
- pragyalint-0.1.0/tests/test_cli.py +62 -0
- pragyalint-0.1.0/tests/test_config_reporters.py +70 -0
- pragyalint-0.1.0/tests/test_exports.py +63 -0
- pragyalint-0.1.0/tests/test_fixer.py +109 -0
- pragyalint-0.1.0/tests/test_graph.py +77 -0
- pragyalint-0.1.0/tests/test_imports.py +55 -0
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
name: binaries
|
|
2
|
+
|
|
3
|
+
# Builds standalone executables for Windows (EXE), Linux, and macOS using
|
|
4
|
+
# PyInstaller and attaches them to the GitHub Release created by the
|
|
5
|
+
# `release:` trigger (see publish.yml).
|
|
6
|
+
#
|
|
7
|
+
# The build matrix runs in parallel on native runners (Windows, Ubuntu, macOS).
|
|
8
|
+
# macOS binaries are built with an unsigned quirk: the `codesign` step is kept
|
|
9
|
+
# off unless a signing identity is provided via the secret `MACOS_CERT`.
|
|
10
|
+
|
|
11
|
+
on:
|
|
12
|
+
push:
|
|
13
|
+
branches: [main]
|
|
14
|
+
release:
|
|
15
|
+
types: [published]
|
|
16
|
+
# Manual trigger: run to build binaries off the current code.
|
|
17
|
+
workflow_dispatch:
|
|
18
|
+
|
|
19
|
+
permissions:
|
|
20
|
+
contents: write
|
|
21
|
+
|
|
22
|
+
jobs:
|
|
23
|
+
build-binaries:
|
|
24
|
+
name: build (${{ matrix.os }})
|
|
25
|
+
runs-on: ${{ matrix.os }}
|
|
26
|
+
strategy:
|
|
27
|
+
fail-fast: false
|
|
28
|
+
matrix:
|
|
29
|
+
include:
|
|
30
|
+
- os: windows-latest
|
|
31
|
+
artifact: pragyalint-windows-x64.exe
|
|
32
|
+
ext: .exe
|
|
33
|
+
args: --onefile --name pragyalint
|
|
34
|
+
- os: ubuntu-latest
|
|
35
|
+
artifact: pragyalint-linux-x64
|
|
36
|
+
ext: ""
|
|
37
|
+
args: --onefile --name pragyalint
|
|
38
|
+
- os: macos-latest
|
|
39
|
+
artifact: pragyalint-macos-x64
|
|
40
|
+
ext: ""
|
|
41
|
+
args: --onefile --name pragyalint
|
|
42
|
+
|
|
43
|
+
steps:
|
|
44
|
+
- uses: actions/checkout@v4
|
|
45
|
+
|
|
46
|
+
- name: Set up Python
|
|
47
|
+
uses: actions/setup-python@v5
|
|
48
|
+
with:
|
|
49
|
+
python-version: "3.12"
|
|
50
|
+
|
|
51
|
+
- name: Install PyInstaller
|
|
52
|
+
run: pip install pyinstaller
|
|
53
|
+
|
|
54
|
+
- name: Build with PyInstaller
|
|
55
|
+
run: pyinstaller --clean --noconfirm ${{ matrix.args }} pragyalint/cli.py
|
|
56
|
+
|
|
57
|
+
- name: Locate binary
|
|
58
|
+
id: loc
|
|
59
|
+
shell: bash
|
|
60
|
+
run: |
|
|
61
|
+
if [ "${{ matrix.ext }}" = ".exe" ]; then
|
|
62
|
+
echo "bin=dist/pragyalint${{ matrix.ext }}" >> "$GITHUB_OUTPUT"
|
|
63
|
+
else
|
|
64
|
+
echo "bin=dist/pragyalint" >> "$GITHUB_OUTPUT"
|
|
65
|
+
fi
|
|
66
|
+
|
|
67
|
+
- name: Rename artifact
|
|
68
|
+
shell: bash
|
|
69
|
+
run: |
|
|
70
|
+
cp "${{ steps.loc.outputs.bin }}" \
|
|
71
|
+
"${{ runner.temp }}/${{ matrix.artifact }}"
|
|
72
|
+
|
|
73
|
+
- name: Make executable (unix)
|
|
74
|
+
if: matrix.os != 'windows-latest'
|
|
75
|
+
run: chmod +x "${{ runner.temp }}/${{ matrix.artifact }}"
|
|
76
|
+
|
|
77
|
+
- name: Smoke-test the binary
|
|
78
|
+
shell: bash
|
|
79
|
+
run: |
|
|
80
|
+
BIN="${{ runner.temp }}/${{ matrix.artifact }}"
|
|
81
|
+
"$BIN" --version
|
|
82
|
+
"$BIN" --help | head -5
|
|
83
|
+
|
|
84
|
+
- name: Upload artifact
|
|
85
|
+
uses: actions/upload-artifact@v4
|
|
86
|
+
with:
|
|
87
|
+
name: ${{ matrix.artifact }}
|
|
88
|
+
path: ${{ runner.temp }}/${{ matrix.artifact }}
|
|
89
|
+
if-no-files-found: error
|
|
90
|
+
|
|
91
|
+
# Runs only when the build is part of (or triggered by) a published release,
|
|
92
|
+
# attaching every platform binary to that release.
|
|
93
|
+
attach:
|
|
94
|
+
name: attach to release
|
|
95
|
+
runs-on: ubuntu-latest
|
|
96
|
+
needs: build-binaries
|
|
97
|
+
if: github.event_name == 'release' && github.event.action == 'published'
|
|
98
|
+
steps:
|
|
99
|
+
- uses: actions/download-artifact@v4
|
|
100
|
+
with:
|
|
101
|
+
path: binaries
|
|
102
|
+
merge-multiple: true
|
|
103
|
+
- name: Attach binaries to release
|
|
104
|
+
uses: softprops/action-gh-release@v2
|
|
105
|
+
with:
|
|
106
|
+
tag_name: ${{ github.event.release.tag_name }}
|
|
107
|
+
files: binaries/*
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
name: deploy-pages
|
|
2
|
+
|
|
3
|
+
# Deploys the static site in site/ to GitHub Pages on every push to main.
|
|
4
|
+
# Uses the official Pages deploy action (no static-site generator needed).
|
|
5
|
+
|
|
6
|
+
on:
|
|
7
|
+
push:
|
|
8
|
+
branches: [main]
|
|
9
|
+
workflow_dispatch:
|
|
10
|
+
|
|
11
|
+
permissions:
|
|
12
|
+
contents: read
|
|
13
|
+
pages: write
|
|
14
|
+
id-token: write
|
|
15
|
+
|
|
16
|
+
concurrency:
|
|
17
|
+
group: pages
|
|
18
|
+
cancel-in-progress: true
|
|
19
|
+
|
|
20
|
+
jobs:
|
|
21
|
+
deploy:
|
|
22
|
+
runs-on: ubuntu-latest
|
|
23
|
+
environment:
|
|
24
|
+
name: github-pages
|
|
25
|
+
url: ${{ steps.deployment.outputs.page_url }}
|
|
26
|
+
steps:
|
|
27
|
+
- uses: actions/checkout@v4
|
|
28
|
+
|
|
29
|
+
- name: Upload site artifact
|
|
30
|
+
uses: actions/upload-pages-artifact@v3
|
|
31
|
+
with:
|
|
32
|
+
path: site
|
|
33
|
+
|
|
34
|
+
- name: Deploy to GitHub Pages
|
|
35
|
+
id: deployment
|
|
36
|
+
uses: actions/deploy-pages@v4
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
name: release
|
|
2
|
+
|
|
3
|
+
# Builds and publishes PragyaLint to PyPI and creates a GitHub Release
|
|
4
|
+
# when a commit message contains the trigger word `release:`
|
|
5
|
+
# (e.g. "release: v0.1.0").
|
|
6
|
+
#
|
|
7
|
+
# The test job always runs on push. The publish job only runs when the
|
|
8
|
+
# head commit message contains `release:`.
|
|
9
|
+
#
|
|
10
|
+
# Secrets needed:
|
|
11
|
+
# - PyPI Trusted Publishing (recommended): no secret; just configure the
|
|
12
|
+
# PyPI "Trusted Publishing" publisher for this repo.
|
|
13
|
+
# - Or a classic API token in a secret named `PYPI_TOKEN`.
|
|
14
|
+
|
|
15
|
+
on:
|
|
16
|
+
push:
|
|
17
|
+
branches: [main]
|
|
18
|
+
# Manual trigger: check "Publish to PyPI even without release: commit".
|
|
19
|
+
workflow_dispatch:
|
|
20
|
+
inputs:
|
|
21
|
+
force-release:
|
|
22
|
+
description: "Publish to PyPI even without release: commit"
|
|
23
|
+
type: boolean
|
|
24
|
+
required: false
|
|
25
|
+
default: false
|
|
26
|
+
|
|
27
|
+
permissions:
|
|
28
|
+
contents: write # for GitHub Release creation
|
|
29
|
+
id-token: write # for PyPI trusted publishing
|
|
30
|
+
|
|
31
|
+
jobs:
|
|
32
|
+
test:
|
|
33
|
+
uses: ./.github/workflows/tests.yml
|
|
34
|
+
|
|
35
|
+
build:
|
|
36
|
+
needs: [test]
|
|
37
|
+
runs-on: ubuntu-latest
|
|
38
|
+
outputs:
|
|
39
|
+
version: ${{ steps.version.outputs.version }}
|
|
40
|
+
steps:
|
|
41
|
+
- uses: actions/checkout@v4
|
|
42
|
+
- name: Set up Python
|
|
43
|
+
uses: actions/setup-python@v5
|
|
44
|
+
with:
|
|
45
|
+
python-version: "3.12"
|
|
46
|
+
- name: Install build tooling
|
|
47
|
+
run: pip install --upgrade build
|
|
48
|
+
- name: Build wheel + sdist
|
|
49
|
+
run: python -m build
|
|
50
|
+
- name: Capture version
|
|
51
|
+
id: version
|
|
52
|
+
run: echo "version=$(python -c 'import tomllib;print(tomllib.load(open(\"pyproject.toml\",\"rb\"))[\"project\"][\"version\"])')" >> "$GITHUB_OUTPUT"
|
|
53
|
+
- name: Upload artifacts
|
|
54
|
+
uses: actions/upload-artifact@v4
|
|
55
|
+
with:
|
|
56
|
+
name: dist
|
|
57
|
+
path: dist/
|
|
58
|
+
|
|
59
|
+
publish:
|
|
60
|
+
needs: [build]
|
|
61
|
+
runs-on: ubuntu-latest
|
|
62
|
+
if: |
|
|
63
|
+
contains(github.event.head_commit.message, 'release:') ||
|
|
64
|
+
(github.event_name == 'workflow_dispatch' && github.event.inputs.force-release == 'true')
|
|
65
|
+
steps:
|
|
66
|
+
- uses: actions/download-artifact@v4
|
|
67
|
+
with:
|
|
68
|
+
name: dist
|
|
69
|
+
path: dist/
|
|
70
|
+
- name: Publish to PyPI
|
|
71
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
72
|
+
# Trusted Publishing needs no password. Passing a token (optional)
|
|
73
|
+
# covers the classic-token path; gh-action skips publishing if empty.
|
|
74
|
+
with:
|
|
75
|
+
password: ${{ secrets.PYPI_TOKEN }}
|
|
76
|
+
|
|
77
|
+
github_release:
|
|
78
|
+
needs: [publish]
|
|
79
|
+
runs-on: ubuntu-latest
|
|
80
|
+
if: needs.publish.result == 'success'
|
|
81
|
+
steps:
|
|
82
|
+
- uses: actions/download-artifact@v4
|
|
83
|
+
with:
|
|
84
|
+
name: dist
|
|
85
|
+
path: dist/
|
|
86
|
+
- name: Create GitHub Release and attach Python artifacts
|
|
87
|
+
uses: softprops/action-gh-release@v2
|
|
88
|
+
with:
|
|
89
|
+
name: PragyaLint v${{ needs.build.outputs.version }}
|
|
90
|
+
tag_name: v${{ needs.build.outputs.version }}
|
|
91
|
+
draft: false
|
|
92
|
+
generate_release_notes: true
|
|
93
|
+
files: dist/*
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
name: tests
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
workflow_call:
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
test:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
strategy:
|
|
13
|
+
matrix:
|
|
14
|
+
python-version: ["3.11", "3.12", "3.13"]
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v4
|
|
17
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
18
|
+
uses: actions/setup-python@v5
|
|
19
|
+
with:
|
|
20
|
+
python-version: ${{ matrix.python-version }}
|
|
21
|
+
- name: Install
|
|
22
|
+
run: |
|
|
23
|
+
pip install -e ".[dev]"
|
|
24
|
+
- name: Run tests
|
|
25
|
+
run: pytest -q
|
|
26
|
+
- name: Self-analysis gate
|
|
27
|
+
run: |
|
|
28
|
+
pragyalint --fail-on high --include pragyalint
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
*.egg-info/
|
|
6
|
+
.eggs/
|
|
7
|
+
build/
|
|
8
|
+
dist/
|
|
9
|
+
wheels/
|
|
10
|
+
.venv/
|
|
11
|
+
venv/
|
|
12
|
+
env/
|
|
13
|
+
.venvs/
|
|
14
|
+
pip-wheel-metadata/
|
|
15
|
+
share/python-wheels/
|
|
16
|
+
|
|
17
|
+
# Test / coverage
|
|
18
|
+
.pytest_cache/
|
|
19
|
+
.coverage
|
|
20
|
+
.coverage.*
|
|
21
|
+
htmlcov/
|
|
22
|
+
.nox/
|
|
23
|
+
.tox/
|
|
24
|
+
.cache/
|
|
25
|
+
coverage.xml
|
|
26
|
+
*.cover
|
|
27
|
+
|
|
28
|
+
# Lint / typing
|
|
29
|
+
.mypy_cache/
|
|
30
|
+
.ruff_cache/
|
|
31
|
+
.dmypy.json
|
|
32
|
+
dmypy.json
|
|
33
|
+
pyrightconfig.json
|
|
34
|
+
.pytype/
|
|
35
|
+
|
|
36
|
+
# Packaging / publishing
|
|
37
|
+
*.whl
|
|
38
|
+
*.tar.gz
|
|
39
|
+
requirements.txt.bak
|
|
40
|
+
|
|
41
|
+
# Editors / OS
|
|
42
|
+
.DS_Store
|
|
43
|
+
*.swp
|
|
44
|
+
*.swo
|
|
45
|
+
.idea/
|
|
46
|
+
.vscode/
|
|
47
|
+
*.log
|
|
48
|
+
|
|
49
|
+
# Environments
|
|
50
|
+
.env
|
|
51
|
+
.env.*
|
|
52
|
+
!.env.example
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to PragyaLint are documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/).
|
|
7
|
+
|
|
8
|
+
## [0.1.0] - 2026-08-29
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- **Fix engine** (`--fix`) — opt-in removal of dead code, confidence-gated with
|
|
13
|
+
dry-run support:
|
|
14
|
+
- `files`: delete unreachable modules (never entries or `__init__.py`).
|
|
15
|
+
- `imports`: remove unused imports; trims unused names from multi-name imports.
|
|
16
|
+
- `exports`: remove unused function/class/variable definitions (respects `__all__`).
|
|
17
|
+
- `--confidence high|medium+|low+|all`, `--dry-run`, and `--force` flags.
|
|
18
|
+
- Module graph builder using the standard-library `ast` module.
|
|
19
|
+
- Entry discovery (conventional entries: `main.py`, `app.py`, `__main__.py`,
|
|
20
|
+
`setup.py`) and explicit `--entry` support.
|
|
21
|
+
- Package/`__init__.py` handling and relative import resolution.
|
|
22
|
+
- Dynamic import detection (`importlib.import_module`, `__import__`).
|
|
23
|
+
- Qualified member-access tracking (`helper.used()` counts as a usage).
|
|
24
|
+
- Reachability analysis and strongly-connected-component cycle detection.
|
|
25
|
+
- Dead-code finders:
|
|
26
|
+
- `unused_file` (high): unreachable modules.
|
|
27
|
+
- `unused_import` (high): unused imports, honoring `__all__` re-exports.
|
|
28
|
+
- `unused_export` (medium): defined public names never imported.
|
|
29
|
+
- `unused_local` (medium/low): unused functions, classes, and assignments.
|
|
30
|
+
- `cycle` (low): circular import cycles.
|
|
31
|
+
- Confidence levels on every finding (`high` / `medium` / `low`).
|
|
32
|
+
- Terminal, JSON, and SARIF reporters.
|
|
33
|
+
- `--fail-on <confidence>` CI gating.
|
|
34
|
+
- Configuration via `pragyalint.toml`, `pragyalint.json`, or
|
|
35
|
+
`[tool.pragyalint]` in `pyproject.toml`.
|
|
36
|
+
- Zero runtime dependencies; requires Python 3.9+.
|
|
37
|
+
- Test suite (pytest) and GitHub Actions CI with a self-analysis gate.
|