pycmdcheck 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.
- pycmdcheck-0.1.0/.devcontainer/Dockerfile +17 -0
- pycmdcheck-0.1.0/.devcontainer/devcontainer.json +61 -0
- pycmdcheck-0.1.0/.devcontainer/requirements-dev.txt +5 -0
- pycmdcheck-0.1.0/.github/workflows/ci.yml +54 -0
- pycmdcheck-0.1.0/.github/workflows/release.yml +52 -0
- pycmdcheck-0.1.0/.gitignore +22 -0
- pycmdcheck-0.1.0/CHANGELOG.md +78 -0
- pycmdcheck-0.1.0/LICENSE +21 -0
- pycmdcheck-0.1.0/PKG-INFO +346 -0
- pycmdcheck-0.1.0/README.md +304 -0
- pycmdcheck-0.1.0/docs/.gitignore +2 -0
- pycmdcheck-0.1.0/docs/_extensions/machow/interlinks/.gitignore +3 -0
- pycmdcheck-0.1.0/docs/_extensions/machow/interlinks/_extension.yml +7 -0
- pycmdcheck-0.1.0/docs/_extensions/machow/interlinks/interlinks.lua +411 -0
- pycmdcheck-0.1.0/docs/_extensions/machow/interlinks/objects.txt +7 -0
- pycmdcheck-0.1.0/docs/_extensions/machow/interlinks/test.qmd +22 -0
- pycmdcheck-0.1.0/docs/_inv/python_objects.json +1 -0
- pycmdcheck-0.1.0/docs/_quarto.yml +85 -0
- pycmdcheck-0.1.0/docs/_site/changelog.html +618 -0
- pycmdcheck-0.1.0/docs/_site/cli.html +788 -0
- pycmdcheck-0.1.0/docs/_site/configuration.html +900 -0
- pycmdcheck-0.1.0/docs/_site/custom-checks.html +882 -0
- pycmdcheck-0.1.0/docs/_site/getting-started.html +784 -0
- pycmdcheck-0.1.0/docs/_site/index.html +680 -0
- pycmdcheck-0.1.0/docs/_site/reference/CheckResult.html +693 -0
- pycmdcheck-0.1.0/docs/_site/reference/CheckStatus.html +638 -0
- pycmdcheck-0.1.0/docs/_site/reference/Report.html +797 -0
- pycmdcheck-0.1.0/docs/_site/reference/check.html +657 -0
- pycmdcheck-0.1.0/docs/_site/reference/checks.base.BaseCheck.html +727 -0
- pycmdcheck-0.1.0/docs/_site/reference/checks.base.Check.html +684 -0
- pycmdcheck-0.1.0/docs/_site/reference/checks.docs.DocsCheck.html +707 -0
- pycmdcheck-0.1.0/docs/_site/reference/checks.imports.ImportsCheck.html +707 -0
- pycmdcheck-0.1.0/docs/_site/reference/checks.license.LicenseCheck.html +698 -0
- pycmdcheck-0.1.0/docs/_site/reference/checks.linting.LintingCheck.html +713 -0
- pycmdcheck-0.1.0/docs/_site/reference/checks.metadata.MetadataCheck.html +709 -0
- pycmdcheck-0.1.0/docs/_site/reference/checks.structure.StructureCheck.html +701 -0
- pycmdcheck-0.1.0/docs/_site/reference/checks.tests.TestsCheck.html +709 -0
- pycmdcheck-0.1.0/docs/_site/reference/checks.typing.TypingCheck.html +707 -0
- pycmdcheck-0.1.0/docs/_site/reference/config.get_check_config.html +645 -0
- pycmdcheck-0.1.0/docs/_site/reference/config.is_check_enabled.html +636 -0
- pycmdcheck-0.1.0/docs/_site/reference/config.load_config.html +643 -0
- pycmdcheck-0.1.0/docs/_site/reference/discovery.discover_checks.html +636 -0
- pycmdcheck-0.1.0/docs/_site/reference/discovery.list_available_checks.html +652 -0
- pycmdcheck-0.1.0/docs/_site/reference/index.html +688 -0
- pycmdcheck-0.1.0/docs/_site/reference/runner.run_checks.html +661 -0
- pycmdcheck-0.1.0/docs/_site/search.json +856 -0
- pycmdcheck-0.1.0/docs/_site/site_libs/bootstrap/bootstrap-5b4ad623e5705c0698d39aec6f10cf02.min.css +12 -0
- pycmdcheck-0.1.0/docs/_site/site_libs/bootstrap/bootstrap-icons.css +2106 -0
- pycmdcheck-0.1.0/docs/_site/site_libs/bootstrap/bootstrap-icons.woff +0 -0
- pycmdcheck-0.1.0/docs/_site/site_libs/bootstrap/bootstrap.min.js +7 -0
- pycmdcheck-0.1.0/docs/_site/site_libs/clipboard/clipboard.min.js +7 -0
- pycmdcheck-0.1.0/docs/_site/site_libs/quarto-html/anchor.min.js +9 -0
- pycmdcheck-0.1.0/docs/_site/site_libs/quarto-html/axe/axe-check.js +145 -0
- pycmdcheck-0.1.0/docs/_site/site_libs/quarto-html/popper.min.js +6 -0
- pycmdcheck-0.1.0/docs/_site/site_libs/quarto-html/quarto-syntax-highlighting-587c61ba64f3a5504c4d52d930310e48.css +236 -0
- pycmdcheck-0.1.0/docs/_site/site_libs/quarto-html/quarto.js +847 -0
- pycmdcheck-0.1.0/docs/_site/site_libs/quarto-html/tabsets/tabsets.js +95 -0
- pycmdcheck-0.1.0/docs/_site/site_libs/quarto-html/tippy.css +1 -0
- pycmdcheck-0.1.0/docs/_site/site_libs/quarto-html/tippy.umd.min.js +2 -0
- pycmdcheck-0.1.0/docs/_site/site_libs/quarto-nav/headroom.min.js +7 -0
- pycmdcheck-0.1.0/docs/_site/site_libs/quarto-nav/quarto-nav.js +325 -0
- pycmdcheck-0.1.0/docs/_site/site_libs/quarto-search/autocomplete.umd.js +3 -0
- pycmdcheck-0.1.0/docs/_site/site_libs/quarto-search/fuse.min.js +9 -0
- pycmdcheck-0.1.0/docs/_site/site_libs/quarto-search/quarto-search.js +1290 -0
- pycmdcheck-0.1.0/docs/changelog.qmd +5 -0
- pycmdcheck-0.1.0/docs/cli.qmd +249 -0
- pycmdcheck-0.1.0/docs/configuration.qmd +299 -0
- pycmdcheck-0.1.0/docs/custom-checks.qmd +264 -0
- pycmdcheck-0.1.0/docs/getting-started.qmd +146 -0
- pycmdcheck-0.1.0/docs/index.qmd +76 -0
- pycmdcheck-0.1.0/docs/objects.json +1 -0
- pycmdcheck-0.1.0/docs/reference/CheckResult.qmd +91 -0
- pycmdcheck-0.1.0/docs/reference/CheckStatus.qmd +44 -0
- pycmdcheck-0.1.0/docs/reference/Report.qmd +178 -0
- pycmdcheck-0.1.0/docs/reference/_sidebar.yml +36 -0
- pycmdcheck-0.1.0/docs/reference/check.qmd +73 -0
- pycmdcheck-0.1.0/docs/reference/checks.base.BaseCheck.qmd +116 -0
- pycmdcheck-0.1.0/docs/reference/checks.base.Check.qmd +72 -0
- pycmdcheck-0.1.0/docs/reference/checks.docs.DocsCheck.qmd +101 -0
- pycmdcheck-0.1.0/docs/reference/checks.imports.ImportsCheck.qmd +96 -0
- pycmdcheck-0.1.0/docs/reference/checks.license.LicenseCheck.qmd +89 -0
- pycmdcheck-0.1.0/docs/reference/checks.linting.LintingCheck.qmd +105 -0
- pycmdcheck-0.1.0/docs/reference/checks.metadata.MetadataCheck.qmd +98 -0
- pycmdcheck-0.1.0/docs/reference/checks.structure.StructureCheck.qmd +92 -0
- pycmdcheck-0.1.0/docs/reference/checks.tests.TestsCheck.qmd +102 -0
- pycmdcheck-0.1.0/docs/reference/checks.typing.TypingCheck.qmd +102 -0
- pycmdcheck-0.1.0/docs/reference/config.get_check_config.qmd +57 -0
- pycmdcheck-0.1.0/docs/reference/config.is_check_enabled.qmd +38 -0
- pycmdcheck-0.1.0/docs/reference/config.load_config.qmd +42 -0
- pycmdcheck-0.1.0/docs/reference/discovery.discover_checks.qmd +51 -0
- pycmdcheck-0.1.0/docs/reference/discovery.list_available_checks.qmd +60 -0
- pycmdcheck-0.1.0/docs/reference/index.qmd +56 -0
- pycmdcheck-0.1.0/docs/reference/runner.run_checks.qmd +73 -0
- pycmdcheck-0.1.0/pyproject.toml +111 -0
- pycmdcheck-0.1.0/src/pycmdcheck/__init__.py +104 -0
- pycmdcheck-0.1.0/src/pycmdcheck/__main__.py +6 -0
- pycmdcheck-0.1.0/src/pycmdcheck/ast_cache.py +45 -0
- pycmdcheck-0.1.0/src/pycmdcheck/checks/__init__.py +1 -0
- pycmdcheck-0.1.0/src/pycmdcheck/checks/base.py +143 -0
- pycmdcheck-0.1.0/src/pycmdcheck/checks/build.py +101 -0
- pycmdcheck-0.1.0/src/pycmdcheck/checks/changelog.py +101 -0
- pycmdcheck-0.1.0/src/pycmdcheck/checks/ci.py +87 -0
- pycmdcheck-0.1.0/src/pycmdcheck/checks/citation.py +102 -0
- pycmdcheck-0.1.0/src/pycmdcheck/checks/community.py +108 -0
- pycmdcheck-0.1.0/src/pycmdcheck/checks/dependencies.py +309 -0
- pycmdcheck-0.1.0/src/pycmdcheck/checks/docs.py +305 -0
- pycmdcheck-0.1.0/src/pycmdcheck/checks/doctests.py +129 -0
- pycmdcheck-0.1.0/src/pycmdcheck/checks/formatting.py +200 -0
- pycmdcheck-0.1.0/src/pycmdcheck/checks/imports.py +239 -0
- pycmdcheck-0.1.0/src/pycmdcheck/checks/license.py +304 -0
- pycmdcheck-0.1.0/src/pycmdcheck/checks/linting.py +304 -0
- pycmdcheck-0.1.0/src/pycmdcheck/checks/metadata.py +233 -0
- pycmdcheck-0.1.0/src/pycmdcheck/checks/py_typed.py +207 -0
- pycmdcheck-0.1.0/src/pycmdcheck/checks/python_versions.py +188 -0
- pycmdcheck-0.1.0/src/pycmdcheck/checks/structure.py +282 -0
- pycmdcheck-0.1.0/src/pycmdcheck/checks/tests.py +230 -0
- pycmdcheck-0.1.0/src/pycmdcheck/checks/typing.py +257 -0
- pycmdcheck-0.1.0/src/pycmdcheck/checks/urls.py +124 -0
- pycmdcheck-0.1.0/src/pycmdcheck/checks/version.py +184 -0
- pycmdcheck-0.1.0/src/pycmdcheck/cli.py +296 -0
- pycmdcheck-0.1.0/src/pycmdcheck/config.py +194 -0
- pycmdcheck-0.1.0/src/pycmdcheck/constants.py +29 -0
- pycmdcheck-0.1.0/src/pycmdcheck/discovery.py +127 -0
- pycmdcheck-0.1.0/src/pycmdcheck/package_layout.py +234 -0
- pycmdcheck-0.1.0/src/pycmdcheck/profiles.py +158 -0
- pycmdcheck-0.1.0/src/pycmdcheck/py.typed +0 -0
- pycmdcheck-0.1.0/src/pycmdcheck/pyproject_reader.py +226 -0
- pycmdcheck-0.1.0/src/pycmdcheck/results.py +320 -0
- pycmdcheck-0.1.0/src/pycmdcheck/runner.py +236 -0
- pycmdcheck-0.1.0/src/pycmdcheck/subprocess_runner.py +166 -0
- pycmdcheck-0.1.0/tests/__init__.py +1 -0
- pycmdcheck-0.1.0/tests/conftest.py +375 -0
- pycmdcheck-0.1.0/tests/test_ast_cache.py +37 -0
- pycmdcheck-0.1.0/tests/test_check_build.py +130 -0
- pycmdcheck-0.1.0/tests/test_check_changelog.py +49 -0
- pycmdcheck-0.1.0/tests/test_check_ci.py +63 -0
- pycmdcheck-0.1.0/tests/test_check_citation.py +56 -0
- pycmdcheck-0.1.0/tests/test_check_community.py +74 -0
- pycmdcheck-0.1.0/tests/test_check_dependencies.py +143 -0
- pycmdcheck-0.1.0/tests/test_check_deps_enhanced.py +53 -0
- pycmdcheck-0.1.0/tests/test_check_docs.py +120 -0
- pycmdcheck-0.1.0/tests/test_check_doctests.py +110 -0
- pycmdcheck-0.1.0/tests/test_check_formatting.py +202 -0
- pycmdcheck-0.1.0/tests/test_check_license.py +102 -0
- pycmdcheck-0.1.0/tests/test_check_metadata.py +131 -0
- pycmdcheck-0.1.0/tests/test_check_py_typed.py +40 -0
- pycmdcheck-0.1.0/tests/test_check_python_versions.py +90 -0
- pycmdcheck-0.1.0/tests/test_check_urls.py +61 -0
- pycmdcheck-0.1.0/tests/test_check_version.py +140 -0
- pycmdcheck-0.1.0/tests/test_checks.py +592 -0
- pycmdcheck-0.1.0/tests/test_cli.py +204 -0
- pycmdcheck-0.1.0/tests/test_config.py +86 -0
- pycmdcheck-0.1.0/tests/test_config_validation.py +40 -0
- pycmdcheck-0.1.0/tests/test_integration.py +45 -0
- pycmdcheck-0.1.0/tests/test_package_layout.py +97 -0
- pycmdcheck-0.1.0/tests/test_profiles.py +111 -0
- pycmdcheck-0.1.0/tests/test_pyproject_reader.py +154 -0
- pycmdcheck-0.1.0/tests/test_results.py +173 -0
- pycmdcheck-0.1.0/tests/test_runner.py +247 -0
- pycmdcheck-0.1.0/tests/test_subprocess_runner.py +762 -0
- pycmdcheck-0.1.0/tests/test_tool_checks_mocked.py +204 -0
- pycmdcheck-0.1.0/uv.lock +1264 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Python version: 3, 3.10, 3.11, 3.12, ...
|
|
2
|
+
# https://hub.docker.com/_/microsoft-devcontainers-python
|
|
3
|
+
ARG VARIANT="3.12"
|
|
4
|
+
FROM mcr.microsoft.com/devcontainers/python:${VARIANT}
|
|
5
|
+
|
|
6
|
+
# Setup devcontainer user
|
|
7
|
+
ARG USERNAME=vscode
|
|
8
|
+
ARG USER_UID=1000
|
|
9
|
+
ARG USER_GID=$USER_UID
|
|
10
|
+
|
|
11
|
+
# Update pip
|
|
12
|
+
RUN pip install --upgrade pip
|
|
13
|
+
|
|
14
|
+
# Install pkg dev dependencies
|
|
15
|
+
COPY requirements-dev.txt /tmp/requirements-dev.txt
|
|
16
|
+
RUN pip install -r /tmp/requirements-dev.txt && \
|
|
17
|
+
rm /tmp/requirements-dev.txt
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
// For format details, see https://aka.ms/devcontainer.json.
|
|
2
|
+
{
|
|
3
|
+
"name": "Python 3",
|
|
4
|
+
"build": {
|
|
5
|
+
// More info: https://containers.dev/guide/dockerfile
|
|
6
|
+
"dockerfile": "Dockerfile",
|
|
7
|
+
// Change VARIANT to pick different Python version: 3, 3.10, 3.11, 3.12, ...
|
|
8
|
+
"args": {
|
|
9
|
+
"VARIANT": "3.12"
|
|
10
|
+
}
|
|
11
|
+
},
|
|
12
|
+
"customizations": {
|
|
13
|
+
"vscode": {
|
|
14
|
+
"extensions": [
|
|
15
|
+
// Python
|
|
16
|
+
"ms-python.python",
|
|
17
|
+
"ms-python.black-formatter",
|
|
18
|
+
"ms-toolsai.jupyter",
|
|
19
|
+
"ms-toolsai.jupyter-renderers",
|
|
20
|
+
"ms-python.vscode-pylance",
|
|
21
|
+
// Docker
|
|
22
|
+
"ms-azuretools.vscode-docker",
|
|
23
|
+
// Documentation
|
|
24
|
+
"njpwerner.autodocstring",
|
|
25
|
+
// Format
|
|
26
|
+
"stkb.rewrap",
|
|
27
|
+
// Lint
|
|
28
|
+
"charliermarsh.ruff",
|
|
29
|
+
// Gen AI
|
|
30
|
+
"GitHub.copilot"
|
|
31
|
+
],
|
|
32
|
+
"settings": {
|
|
33
|
+
// Editor
|
|
34
|
+
"editor.formatOnSave": true,
|
|
35
|
+
// Files
|
|
36
|
+
"files.insertFinalNewline": true,
|
|
37
|
+
"files.trimTrailingWhitespace": true,
|
|
38
|
+
// Testing
|
|
39
|
+
"python.testing.pytestArgs": [
|
|
40
|
+
"."
|
|
41
|
+
],
|
|
42
|
+
"python.testing.unittestEnabled": false,
|
|
43
|
+
"python.testing.pytestEnabled": true,
|
|
44
|
+
"python.testing.autoTestDiscoverOnSaveEnabled": true,
|
|
45
|
+
// Formatting
|
|
46
|
+
"python.formatting.provider": "black",
|
|
47
|
+
"python.formatting.blackArgs": [
|
|
48
|
+
"--no-color"
|
|
49
|
+
],
|
|
50
|
+
// Linting
|
|
51
|
+
"python.linting.mypyEnabled": true,
|
|
52
|
+
"python.linting.enabled": true
|
|
53
|
+
},
|
|
54
|
+
"git.branchProtection": [
|
|
55
|
+
"main",
|
|
56
|
+
"master"
|
|
57
|
+
]
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
"remoteUser": "vscode"
|
|
61
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: read
|
|
10
|
+
|
|
11
|
+
concurrency:
|
|
12
|
+
group: ci-${{ github.ref }}
|
|
13
|
+
cancel-in-progress: true
|
|
14
|
+
|
|
15
|
+
jobs:
|
|
16
|
+
lint:
|
|
17
|
+
name: Lint & type-check
|
|
18
|
+
runs-on: ubuntu-latest
|
|
19
|
+
steps:
|
|
20
|
+
- uses: actions/checkout@v4
|
|
21
|
+
- name: Install uv
|
|
22
|
+
uses: astral-sh/setup-uv@v6
|
|
23
|
+
with:
|
|
24
|
+
# 3.10 matches [tool.mypy] python_version and installs tomli
|
|
25
|
+
# (a conditional dependency) so mypy can resolve the tomllib fallback.
|
|
26
|
+
python-version: "3.10"
|
|
27
|
+
enable-cache: true
|
|
28
|
+
- name: Install dependencies
|
|
29
|
+
run: uv sync --extra dev --extra linting --extra typing-mypy
|
|
30
|
+
- name: Ruff (lint)
|
|
31
|
+
run: uv run ruff check src/ tests/
|
|
32
|
+
- name: Ruff (format)
|
|
33
|
+
run: uv run ruff format --check src/ tests/
|
|
34
|
+
- name: Mypy
|
|
35
|
+
run: uv run mypy src/pycmdcheck
|
|
36
|
+
|
|
37
|
+
test:
|
|
38
|
+
name: Test (py${{ matrix.python-version }})
|
|
39
|
+
runs-on: ubuntu-latest
|
|
40
|
+
strategy:
|
|
41
|
+
fail-fast: false
|
|
42
|
+
matrix:
|
|
43
|
+
python-version: ["3.10", "3.11", "3.12", "3.13"]
|
|
44
|
+
steps:
|
|
45
|
+
- uses: actions/checkout@v4
|
|
46
|
+
- name: Install uv
|
|
47
|
+
uses: astral-sh/setup-uv@v6
|
|
48
|
+
with:
|
|
49
|
+
python-version: ${{ matrix.python-version }}
|
|
50
|
+
enable-cache: true
|
|
51
|
+
- name: Install dependencies
|
|
52
|
+
run: uv sync --extra dev
|
|
53
|
+
- name: Run tests
|
|
54
|
+
run: uv run pytest -q
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- "v*"
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: read
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
build:
|
|
13
|
+
name: Test & build distributions
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v4
|
|
17
|
+
- name: Install uv
|
|
18
|
+
uses: astral-sh/setup-uv@v6
|
|
19
|
+
with:
|
|
20
|
+
python-version: "3.12"
|
|
21
|
+
enable-cache: true
|
|
22
|
+
- name: Install dependencies
|
|
23
|
+
run: uv sync --extra dev
|
|
24
|
+
- name: Run tests (gate the release on green)
|
|
25
|
+
run: uv run pytest -q
|
|
26
|
+
- name: Build sdist and wheel
|
|
27
|
+
run: uv build
|
|
28
|
+
- name: Upload distributions
|
|
29
|
+
uses: actions/upload-artifact@v4
|
|
30
|
+
with:
|
|
31
|
+
name: dist
|
|
32
|
+
path: dist/
|
|
33
|
+
|
|
34
|
+
publish:
|
|
35
|
+
name: Publish to PyPI
|
|
36
|
+
needs: build
|
|
37
|
+
runs-on: ubuntu-latest
|
|
38
|
+
# The environment can be configured on GitHub to require manual approval
|
|
39
|
+
# before a release is published.
|
|
40
|
+
environment:
|
|
41
|
+
name: pypi
|
|
42
|
+
url: https://pypi.org/p/pycmdcheck
|
|
43
|
+
permissions:
|
|
44
|
+
id-token: write # OIDC: required for PyPI Trusted Publishing (no token)
|
|
45
|
+
steps:
|
|
46
|
+
- name: Download distributions
|
|
47
|
+
uses: actions/download-artifact@v4
|
|
48
|
+
with:
|
|
49
|
+
name: dist
|
|
50
|
+
path: dist/
|
|
51
|
+
- name: Publish to PyPI
|
|
52
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*.egg-info/
|
|
5
|
+
dist/
|
|
6
|
+
build/
|
|
7
|
+
*.egg
|
|
8
|
+
|
|
9
|
+
# Virtual environments
|
|
10
|
+
.venv/
|
|
11
|
+
venv/
|
|
12
|
+
|
|
13
|
+
# OS
|
|
14
|
+
.DS_Store
|
|
15
|
+
|
|
16
|
+
# IDE
|
|
17
|
+
.idea/
|
|
18
|
+
.vscode/
|
|
19
|
+
*.swp
|
|
20
|
+
|
|
21
|
+
# Plans (keep locally, don't track)
|
|
22
|
+
docs/plans/
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to pycmdcheck will be 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/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- 7 additional built-in checks (bringing the total to **20**):
|
|
13
|
+
- `community` - Checks for CONTRIBUTING and CODE_OF_CONDUCT files
|
|
14
|
+
- `ci` - Checks for CI configuration
|
|
15
|
+
- `changelog` - Checks for a CHANGELOG/NEWS/HISTORY file
|
|
16
|
+
- `citation` - Checks for a CITATION file
|
|
17
|
+
- `python_versions` - Checks `requires-python` excludes EOL Python versions
|
|
18
|
+
- `urls` - Validates project URLs are reachable
|
|
19
|
+
- `doctests` - Runs doctests via `pytest --doctest-modules`
|
|
20
|
+
- Profile system with built-in profiles `minimal`, `triage`, `default`,
|
|
21
|
+
`pyopensci`, and `strict`, plus `--profile` and `--list-profiles` CLI options.
|
|
22
|
+
The new `triage` profile runs only the static, no-install/no-network checks —
|
|
23
|
+
intended for CI triage of arbitrary (un-installed) repositories.
|
|
24
|
+
- Support for legacy Poetry projects (`[tool.poetry]` with no PEP 621
|
|
25
|
+
`[project]` table) across the metadata, version, python_versions, and
|
|
26
|
+
dependencies checks.
|
|
27
|
+
- `structure` now recognizes PEP 420 implicit namespace packages, single-file
|
|
28
|
+
modules, and native-extension build backends (maturin/scikit-build/setuptools-rust).
|
|
29
|
+
- GitHub Actions workflows: CI (lint + type-check + pytest matrix on 3.10–3.13)
|
|
30
|
+
and a tag-triggered PyPI release using Trusted Publishing (OIDC).
|
|
31
|
+
- `packaging` added as a runtime dependency (accurate PEP 440 version handling).
|
|
32
|
+
|
|
33
|
+
### Changed
|
|
34
|
+
|
|
35
|
+
- The `formatting` check now defaults to `tool = "auto"`: it detects ruff vs
|
|
36
|
+
black from `[tool.ruff]`/`ruff.toml`/`[tool.black]` and is **skipped** when no
|
|
37
|
+
formatter is configured (previously hard-coded to ruff).
|
|
38
|
+
- Many checks were made more lenient to eliminate false positives on legitimate
|
|
39
|
+
real-world packages: PEP 621 `dynamic` metadata fields, dual-license/suffixed
|
|
40
|
+
license filenames, RST/plain-text README section detection, community files in
|
|
41
|
+
`.github/`/`docs/`, single-module/re-exported `__version__`, dependency extras,
|
|
42
|
+
`pytest` "no tests collected" (exit 5) in doctests, and ruff/mypy
|
|
43
|
+
tool/config-error handling.
|
|
44
|
+
|
|
45
|
+
### Fixed
|
|
46
|
+
|
|
47
|
+
- `metadata` no longer reports a false ERROR for packages whose version is
|
|
48
|
+
supplied dynamically (PEP 621 `dynamic = ["version"]`, e.g. setuptools_scm /
|
|
49
|
+
hatch-vcs / uv-dynamic-versioning) or declared under legacy `[tool.poetry]`.
|
|
50
|
+
|
|
51
|
+
## [0.1.0] - 2024-12-31
|
|
52
|
+
|
|
53
|
+
### Added
|
|
54
|
+
|
|
55
|
+
- Initial release of pycmdcheck
|
|
56
|
+
- Core `check()` function for programmatic package checking
|
|
57
|
+
- CLI with `pycmdcheck` command
|
|
58
|
+
- 13 built-in checks:
|
|
59
|
+
- `build` - Verifies package builds (wheel/sdist)
|
|
60
|
+
- `dependencies` - Audits declared vs. actual imports
|
|
61
|
+
- `docs` - Checks for README and docstrings
|
|
62
|
+
- `formatting` - Checks code formatting (ruff format/black)
|
|
63
|
+
- `imports` - Validates imports
|
|
64
|
+
- `license` - Checks for LICENSE file
|
|
65
|
+
- `linting` - Runs ruff/flake8/pylint
|
|
66
|
+
- `metadata` - Validates pyproject.toml
|
|
67
|
+
- `py_typed` - Checks for PEP 561 py.typed marker
|
|
68
|
+
- `structure` - Validates package structure
|
|
69
|
+
- `tests` - Runs pytest/unittest
|
|
70
|
+
- `typing` - Runs mypy/pyright
|
|
71
|
+
- `version` - Verifies version consistency
|
|
72
|
+
- Configuration via `[tool.pycmdcheck]` in pyproject.toml
|
|
73
|
+
- Plugin system via entry points for custom checks
|
|
74
|
+
- Parallel check execution
|
|
75
|
+
- Rich terminal output with colors and tables
|
|
76
|
+
- JSON output format for CI integration
|
|
77
|
+
- `CheckResult`, `CheckStatus`, and `Report` classes
|
|
78
|
+
- `BaseCheck` abstract class for custom check development
|
pycmdcheck-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 pycmdcheck contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pycmdcheck
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Python package quality checker inspired by R CMD check
|
|
5
|
+
Project-URL: Homepage, https://github.com/pycmdcheck/pycmdcheck
|
|
6
|
+
Project-URL: Repository, https://github.com/pycmdcheck/pycmdcheck
|
|
7
|
+
Project-URL: Issues, https://github.com/pycmdcheck/pycmdcheck/issues
|
|
8
|
+
Author: pycmdcheck contributors
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: check,lint,package,quality,test
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Topic :: Software Development :: Quality Assurance
|
|
20
|
+
Classifier: Topic :: Software Development :: Testing
|
|
21
|
+
Requires-Python: >=3.10
|
|
22
|
+
Requires-Dist: click>=8.0
|
|
23
|
+
Requires-Dist: packaging>=21.0
|
|
24
|
+
Requires-Dist: rich>=13.0
|
|
25
|
+
Requires-Dist: tomli>=2.0; python_version < '3.11'
|
|
26
|
+
Provides-Extra: all
|
|
27
|
+
Requires-Dist: mypy>=1.0; extra == 'all'
|
|
28
|
+
Requires-Dist: pyright>=1.1; extra == 'all'
|
|
29
|
+
Requires-Dist: ruff>=0.1; extra == 'all'
|
|
30
|
+
Provides-Extra: dev
|
|
31
|
+
Requires-Dist: pytest-cov>=4.0; extra == 'dev'
|
|
32
|
+
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
33
|
+
Provides-Extra: docs
|
|
34
|
+
Requires-Dist: quartodoc>=0.7; extra == 'docs'
|
|
35
|
+
Provides-Extra: linting
|
|
36
|
+
Requires-Dist: ruff>=0.1; extra == 'linting'
|
|
37
|
+
Provides-Extra: typing-mypy
|
|
38
|
+
Requires-Dist: mypy>=1.0; extra == 'typing-mypy'
|
|
39
|
+
Provides-Extra: typing-pyright
|
|
40
|
+
Requires-Dist: pyright>=1.1; extra == 'typing-pyright'
|
|
41
|
+
Description-Content-Type: text/markdown
|
|
42
|
+
|
|
43
|
+
# pycmdcheck
|
|
44
|
+
|
|
45
|
+
A Python package quality checker inspired by R's `R CMD check`.
|
|
46
|
+
|
|
47
|
+
## Installation
|
|
48
|
+
|
|
49
|
+
> **Note:** pycmdcheck is not yet published to PyPI. Install it directly from
|
|
50
|
+
> GitHub for now. Once it is released, `pip install pycmdcheck` will work too.
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
pip install git+https://github.com/coatless-py-pkg/pycmdcheck
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Or with uv:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
uv pip install git+https://github.com/coatless-py-pkg/pycmdcheck
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
To pin a specific branch, tag, or commit, append `@<ref>` to the URL — for
|
|
63
|
+
example `git+https://github.com/coatless-py-pkg/pycmdcheck@main`.
|
|
64
|
+
|
|
65
|
+
### Optional dependencies
|
|
66
|
+
|
|
67
|
+
pycmdcheck can use external tools for linting and type checking. Request the
|
|
68
|
+
matching extra in the install command. For a GitHub install, the extra goes in
|
|
69
|
+
the PEP 508 `pycmdcheck[extra] @ <url>` form:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
# For mypy type checking
|
|
73
|
+
pip install "pycmdcheck[typing-mypy] @ git+https://github.com/coatless-py-pkg/pycmdcheck"
|
|
74
|
+
|
|
75
|
+
# For pyright type checking
|
|
76
|
+
pip install "pycmdcheck[typing-pyright] @ git+https://github.com/coatless-py-pkg/pycmdcheck"
|
|
77
|
+
|
|
78
|
+
# For ruff linting
|
|
79
|
+
pip install "pycmdcheck[linting] @ git+https://github.com/coatless-py-pkg/pycmdcheck"
|
|
80
|
+
|
|
81
|
+
# All optional dependencies
|
|
82
|
+
pip install "pycmdcheck[all] @ git+https://github.com/coatless-py-pkg/pycmdcheck"
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Usage
|
|
86
|
+
|
|
87
|
+
### Command Line
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
# Check current directory
|
|
91
|
+
pycmdcheck
|
|
92
|
+
|
|
93
|
+
# Check a specific directory
|
|
94
|
+
pycmdcheck /path/to/package
|
|
95
|
+
|
|
96
|
+
# Run only specific checks
|
|
97
|
+
pycmdcheck -c metadata -c tests
|
|
98
|
+
|
|
99
|
+
# Skip specific checks
|
|
100
|
+
pycmdcheck -s typing -s linting
|
|
101
|
+
|
|
102
|
+
# Fail on warnings too
|
|
103
|
+
pycmdcheck --fail-on error --fail-on warning
|
|
104
|
+
|
|
105
|
+
# List available checks
|
|
106
|
+
pycmdcheck --list
|
|
107
|
+
|
|
108
|
+
# JSON output
|
|
109
|
+
pycmdcheck --json
|
|
110
|
+
|
|
111
|
+
# Stop after first error (fail fast)
|
|
112
|
+
pycmdcheck -x
|
|
113
|
+
pycmdcheck --fail-fast
|
|
114
|
+
|
|
115
|
+
# Verbose output with details
|
|
116
|
+
pycmdcheck -v
|
|
117
|
+
|
|
118
|
+
# Use a check profile
|
|
119
|
+
pycmdcheck --profile pyopensci
|
|
120
|
+
pycmdcheck --profile minimal
|
|
121
|
+
pycmdcheck --profile strict
|
|
122
|
+
|
|
123
|
+
# List available profiles
|
|
124
|
+
pycmdcheck --list-profiles
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### With uv
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
uv run pycmdcheck
|
|
131
|
+
uv run pycmdcheck -c tests -c linting
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### Python API
|
|
135
|
+
|
|
136
|
+
```python
|
|
137
|
+
from pycmdcheck import check, CheckStatus
|
|
138
|
+
|
|
139
|
+
# Check current directory
|
|
140
|
+
report = check(".")
|
|
141
|
+
|
|
142
|
+
# Check specific directory
|
|
143
|
+
report = check("/path/to/package")
|
|
144
|
+
|
|
145
|
+
# Run only specific checks
|
|
146
|
+
report = check(".", checks=["metadata", "tests"])
|
|
147
|
+
|
|
148
|
+
# Skip specific checks
|
|
149
|
+
report = check(".", skip=["linting", "typing"])
|
|
150
|
+
|
|
151
|
+
# Check results
|
|
152
|
+
if report.passed:
|
|
153
|
+
print("All checks passed!")
|
|
154
|
+
else:
|
|
155
|
+
for result in report.results:
|
|
156
|
+
print(f"{result.status}: {result.name} - {result.message}")
|
|
157
|
+
|
|
158
|
+
# Get counts by status
|
|
159
|
+
counts = report.count_by_status()
|
|
160
|
+
print(f"OK: {counts[CheckStatus.OK]}, Errors: {counts[CheckStatus.ERROR]}")
|
|
161
|
+
|
|
162
|
+
# JSON output
|
|
163
|
+
import json
|
|
164
|
+
print(json.dumps(report.to_dict(), indent=2))
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
## Built-in Checks
|
|
168
|
+
|
|
169
|
+
### Core checks
|
|
170
|
+
|
|
171
|
+
| Check | Description |
|
|
172
|
+
|-------|-------------|
|
|
173
|
+
| `build` | Verifies the package builds successfully (wheel/sdist) |
|
|
174
|
+
| `dependencies` | Audits declared vs. actual imports, warns on unbounded versions |
|
|
175
|
+
| `docs` | Checks for README (content sections, word count) and docstrings |
|
|
176
|
+
| `formatting` | Checks code formatting (ruff format/black) |
|
|
177
|
+
| `imports` | Validates all imports can be resolved |
|
|
178
|
+
| `license` | Checks for LICENSE file and OSI-approved license validation |
|
|
179
|
+
| `linting` | Runs ruff, flake8, or pylint |
|
|
180
|
+
| `metadata` | Validates pyproject.toml fields (required, recommended, extended) |
|
|
181
|
+
| `py_typed` | Checks for PEP 561 py.typed marker |
|
|
182
|
+
| `structure` | Checks package directory structure (src or flat layout) |
|
|
183
|
+
| `tests` | Runs pytest or unittest and reports results |
|
|
184
|
+
| `typing` | Runs mypy or pyright type checker |
|
|
185
|
+
| `version` | Verifies version consistency between pyproject.toml and code |
|
|
186
|
+
|
|
187
|
+
### pyOpenSci / community checks
|
|
188
|
+
|
|
189
|
+
| Check | Description |
|
|
190
|
+
|-------|-------------|
|
|
191
|
+
| `changelog` | Checks for CHANGELOG, NEWS, or HISTORY file |
|
|
192
|
+
| `ci` | Checks for CI configuration (GitHub Actions, CircleCI, etc.) |
|
|
193
|
+
| `citation` | Checks for CITATION.cff or CITATION.bib file |
|
|
194
|
+
| `community` | Checks for CONTRIBUTING.md and CODE_OF_CONDUCT.md |
|
|
195
|
+
| `doctests` | Runs doctests via pytest --doctest-modules |
|
|
196
|
+
| `python_versions` | Checks requires-python excludes EOL Python versions |
|
|
197
|
+
| `urls` | Validates project URLs in metadata are reachable |
|
|
198
|
+
|
|
199
|
+
## Profiles
|
|
200
|
+
|
|
201
|
+
Profiles bundle checks for common use cases:
|
|
202
|
+
|
|
203
|
+
| Profile | Description | Checks |
|
|
204
|
+
|---------|-------------|--------|
|
|
205
|
+
| `minimal` | Quick sanity checks | metadata, structure, license |
|
|
206
|
+
| `triage` | Static checks only — no install, external tools, or network (for CI triage of arbitrary repos) | All static checks (excludes tests, imports, dependencies, build, linting, typing, formatting, doctests, urls) |
|
|
207
|
+
| `default` | Standard quality checks | All 13 core checks |
|
|
208
|
+
| `pyopensci` | pyOpenSci onboarding | All 20 checks with stricter docs settings |
|
|
209
|
+
| `strict` | Maximum strictness | All 20 checks with strict typing |
|
|
210
|
+
|
|
211
|
+
```bash
|
|
212
|
+
# Run pyOpenSci onboarding checks
|
|
213
|
+
pycmdcheck --profile pyopensci
|
|
214
|
+
|
|
215
|
+
# Static-only triage (safe to run on an un-installed repo in CI)
|
|
216
|
+
pycmdcheck --profile triage
|
|
217
|
+
|
|
218
|
+
# Quick check before committing
|
|
219
|
+
pycmdcheck --profile minimal
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
Profiles can be combined with `--skip` to exclude specific checks:
|
|
223
|
+
|
|
224
|
+
```bash
|
|
225
|
+
pycmdcheck --profile pyopensci -s urls -s doctests
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
## Configuration
|
|
229
|
+
|
|
230
|
+
Configure pycmdcheck in your `pyproject.toml`:
|
|
231
|
+
|
|
232
|
+
```toml
|
|
233
|
+
[tool.pycmdcheck]
|
|
234
|
+
# Fail on these statuses (default: ["error"])
|
|
235
|
+
fail_on = ["error", "warning"]
|
|
236
|
+
|
|
237
|
+
[tool.pycmdcheck.checks]
|
|
238
|
+
# Enable/disable checks with boolean
|
|
239
|
+
metadata = true
|
|
240
|
+
structure = true
|
|
241
|
+
imports = true
|
|
242
|
+
license = true
|
|
243
|
+
|
|
244
|
+
# Configure checks with options
|
|
245
|
+
tests = { enabled = true, runner = "pytest" }
|
|
246
|
+
linting = { enabled = true, tool = "ruff" }
|
|
247
|
+
typing = { enabled = true, tool = "mypy", strict = false }
|
|
248
|
+
# formatting "tool" defaults to "auto": detects ruff vs black from
|
|
249
|
+
# [tool.ruff]/ruff.toml or [tool.black]; skips if neither is configured.
|
|
250
|
+
formatting = { enabled = true, tool = "auto" }
|
|
251
|
+
docs = { enabled = true, require_readme = true, check_docstrings = false, check_readme_sections = false }
|
|
252
|
+
|
|
253
|
+
# New checks (disabled by default in "default" profile)
|
|
254
|
+
community = true
|
|
255
|
+
ci = true
|
|
256
|
+
changelog = true
|
|
257
|
+
citation = true
|
|
258
|
+
python_versions = true
|
|
259
|
+
urls = { enabled = true, timeout = 10 }
|
|
260
|
+
doctests = true
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
### Linting tools
|
|
264
|
+
|
|
265
|
+
Supported linting tools:
|
|
266
|
+
- `ruff` (default, recommended)
|
|
267
|
+
- `flake8`
|
|
268
|
+
- `pylint`
|
|
269
|
+
|
|
270
|
+
```toml
|
|
271
|
+
[tool.pycmdcheck.checks.linting]
|
|
272
|
+
tool = "ruff"
|
|
273
|
+
args = ["--select=E,F,W"]
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
### Build options
|
|
277
|
+
|
|
278
|
+
```toml
|
|
279
|
+
[tool.pycmdcheck.checks.build]
|
|
280
|
+
timeout = 300 # seconds (default: 120)
|
|
281
|
+
args = ["--wheel"]
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
### Type checking tools
|
|
285
|
+
|
|
286
|
+
Supported type checkers:
|
|
287
|
+
- `mypy` (default)
|
|
288
|
+
- `pyright`
|
|
289
|
+
|
|
290
|
+
```toml
|
|
291
|
+
[tool.pycmdcheck.checks.typing]
|
|
292
|
+
tool = "pyright"
|
|
293
|
+
strict = true
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
## Custom Checks
|
|
297
|
+
|
|
298
|
+
Create custom checks by implementing the `Check` protocol:
|
|
299
|
+
|
|
300
|
+
```python
|
|
301
|
+
from pathlib import Path
|
|
302
|
+
from typing import Any
|
|
303
|
+
from pycmdcheck.checks.base import BaseCheck
|
|
304
|
+
from pycmdcheck.results import CheckResult, CheckStatus
|
|
305
|
+
|
|
306
|
+
class MyCustomCheck(BaseCheck):
|
|
307
|
+
name = "my_custom_check"
|
|
308
|
+
description = "My custom quality check"
|
|
309
|
+
|
|
310
|
+
def run(self, package_path: Path, config: dict[str, Any]) -> CheckResult:
|
|
311
|
+
# Your check logic here
|
|
312
|
+
issues = [] # ... populate with any issues found
|
|
313
|
+
if not issues:
|
|
314
|
+
return CheckResult(
|
|
315
|
+
name=self.name,
|
|
316
|
+
status=CheckStatus.OK,
|
|
317
|
+
message="All good!",
|
|
318
|
+
)
|
|
319
|
+
return CheckResult(
|
|
320
|
+
name=self.name,
|
|
321
|
+
status=CheckStatus.ERROR,
|
|
322
|
+
message="Something is wrong",
|
|
323
|
+
details=issues,
|
|
324
|
+
)
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
Register your check via entry points in `pyproject.toml`:
|
|
328
|
+
|
|
329
|
+
```toml
|
|
330
|
+
[project.entry-points."pycmdcheck.checks"]
|
|
331
|
+
my_custom_check = "my_package.checks:MyCustomCheck"
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
## Check Statuses
|
|
335
|
+
|
|
336
|
+
| Status | Symbol | Description |
|
|
337
|
+
|--------|--------|-------------|
|
|
338
|
+
| OK | ✓ | Check passed |
|
|
339
|
+
| NOTE | ℹ | Minor observation, not a problem |
|
|
340
|
+
| WARNING | ⚠ | Potential issue, should be reviewed |
|
|
341
|
+
| ERROR | ✗ | Check failed |
|
|
342
|
+
| SKIPPED | ○ | Check was skipped (e.g., tool not installed) |
|
|
343
|
+
|
|
344
|
+
## License
|
|
345
|
+
|
|
346
|
+
MIT
|