Checks Reference
pycmdcheck includes 66 built-in checks organized into 10 groups. Each check has a unique ID, name, severity level, and documentation.
Check Groups
Structure
Checks for essential package structure files:
| ID | Name | Severity | Description |
|---|---|---|---|
| ST001 | HasReadme | ERROR | Check that README file exists |
| ST002 | HasLicense | ERROR | Check that LICENSE file exists |
| ST003 | HasPyprojectToml | ERROR | Check that pyproject.toml exists |
| ST004 | NoSetupPy | WARNING | Check that setup.py is not present |
| ST005 | HasSrcLayout | NOTE | Check for src/ directory layout |
| ST006 | HasPyTyped | NOTE | Check for py.typed marker (PEP 561) |
| ST007 | HasGitignore | NOTE | Check that .gitignore exists |
| ST008 | ExportConsistencyCheck | WARNING | Check all exports are consistent |
| ST009 | HasContributing | WARNING | Check for CONTRIBUTING file |
| ST010 | HasCodeOfConduct | WARNING | Check for CODE_OF_CONDUCT file |
| ST011 | HasPreCommitConfig | NOTE | Check for pre-commit configuration |
| ST012 | HasCIConfig | WARNING | Check for CI configuration |
Metadata
Checks for pyproject.toml metadata fields:
| ID | Name | Severity | Description |
|---|---|---|---|
| MT001 | HasProjectName | ERROR | Check that project name is defined |
| MT002 | HasProjectVersion | ERROR | Check that project version is defined |
| MT003 | HasProjectDescription | ERROR | Check that project description is defined |
| MT004 | HasRequiresPython | ERROR | Check that requires-python is defined |
| MT005 | HasKeywords | NOTE | Check that keywords are defined |
| MT006 | HasClassifiers | WARNING | Check that classifiers are defined |
| MT007 | HasHomepage | WARNING | Check that homepage URL is defined |
| MT008 | HasReadmeField | WARNING | Check that readme field is defined |
| MT009 | ValidLicenseIdentifier | NOTE | Check that license is a valid SPDX identifier |
| MT010 | LicenseCompatibilityCheck | WARNING | Check license compatibility |
| MT011 | OSIApprovedLicense | WARNING | Check license is OSI-approved |
| MT012 | AuthorEmail | NOTE | Check that author/maintainer email is defined |
Tests
Checks for test infrastructure:
| ID | Name | Severity | Description |
|---|---|---|---|
| TS001 | HasTestsDirectory | WARNING | Check that tests directory exists |
| TS002 | TestsRun | ERROR | Check that tests run and pass |
| TS003 | TestCoverage | WARNING | Check that test coverage meets threshold |
| TS004 | TestNamingConvention | NOTE | Check test files follow naming conventions |
| TS005 | TestDiscoverability | NOTE | Check all test files are discoverable by pytest |
Documentation
Checks for documentation presence:
| ID | Name | Severity | Description |
|---|---|---|---|
| DC001 | HasDocstrings | WARNING | Check that package has module docstring |
| DC002 | HasDocsDirectory | NOTE | Check that docs directory exists |
| DC003 | HasExamples | NOTE | Check for examples directory or code |
| DC004 | HasAPIReference | NOTE | Check for API documentation setup |
| DC005 | BrokenLinksCheck | WARNING | Check for broken URLs in documentation |
| DC006 | ReadmeStructure | WARNING | Check README has install/usage sections |
| DC007 | ReadmeBadges | NOTE | Check README has status badges |
Code Quality
Checks for code quality and standards:
| ID | Name | Severity | Description |
|---|---|---|---|
| CQ001 | RuffCheck | WARNING | Check that code passes ruff linting |
| CQ002 | HasTypeHints | NOTE | Check for py.typed marker (PEP 561) |
| CQ003 | NoTODOsInCode | NOTE | Check for TODO/FIXME comments |
| CQ004 | MypyCheck | WARNING | Check that code passes mypy type checking |
| CQ005 | ComplexityCheck | WARNING | Check code cyclomatic complexity |
| CQ006 | DeadCodeCheck | NOTE | Check for unused code with vulture |
| CQ007 | DoctestCheck | WARNING | Check that doctests pass |
| CQ008 | DocstringCoverage | NOTE | Check docstring coverage percentage |
| CQ009 | TypeHintCoverage | NOTE | Check type hint coverage percentage |
Dependencies
Checks for dependency management:
| ID | Name | Severity | Description |
|---|---|---|---|
| DP001 | NoPinnedDependencies | WARNING | Check that deps aren’t overly pinned |
| DP002 | HasLockfile | NOTE | Check that a lockfile exists |
| DP003 | DependencyFreshnessCheck | NOTE | Check for outdated dependencies |
| DP004 | CircularImportCheck | ERROR | Check for circular imports |
| DP005 | UnusedDependencyCheck | WARNING | Check for unused declared dependencies |
Security
Checks for security issues:
| ID | Name | Severity | Description |
|---|---|---|---|
| SC001 | NoHardcodedSecrets | ERROR | Check for hardcoded API keys, passwords, and secrets |
| SC002 | NoInsecureFunctions | WARNING | Check for eval(), exec(), pickle, subprocess shell=True |
| SC003 | NoDependencyVulnerabilities | WARNING | Check for known vulnerabilities in dependencies |
| SC004 | DependencyAudit | WARNING | Audit dependencies for security issues |
| SC005 | NoHardcodedSecretsV2 | NOTE | Enhanced check for hardcoded secrets |
| SC006 | DeprecatedAPIs | WARNING | Check for deprecated Python stdlib usage |
Build
Checks for build and distribution:
| ID | Name | Severity | Description |
|---|---|---|---|
| BD001 | BuildSucceeds | ERROR | Check that package builds successfully |
| BD002 | WheelBuilds | ERROR | Check that wheel can be built |
| BD003 | InstallSucceeds | ERROR | Check that package installs correctly |
| BD004 | ImportSucceeds | ERROR | Check that package imports without errors |
Release
Checks for release readiness:
| ID | Name | Severity | Description |
|---|---|---|---|
| RL001 | HasChangelog | WARNING | Check that changelog exists |
| RL002 | ValidVersion | ERROR | Check that version follows semver |
| RL003 | ChangelogFormatCheck | WARNING | Check that changelog follows standard format |
| RL004 | HasCitation | NOTE | Check for CITATION.cff file |
| RL005 | PyPIPublished | NOTE | Check package is on PyPI |
Governance
Checks for license and governance compliance:
| ID | Name | Severity | Description |
|---|---|---|---|
| GV001 | LicenseCompatibility | WARNING | Check license compatibility with dependencies |
Severity Levels
| Severity | Exit Code | Description |
|---|---|---|
| ERROR | 1 | Critical issue that should block release |
| WARNING | 2 | Important issue that should be addressed |
| NOTE | 0 | Informational, non-blocking issue |
Filtering Checks
Skip specific checks
pycmdcheck --skip ST001 --skip MT003Skip entire groups
pycmdcheck --skip-group metadata --skip-group documentationOnly run specific checks
pycmdcheck --only ST001 --only ST002Only run specific groups
pycmdcheck --only-group structure --only-group releaseCreating Custom Checks
You can create custom checks by implementing the check protocol and registering via entry points.
Check Protocol
from typing import ClassVar
from pycmdcheck import CheckResult, CheckStatus, Severity
class MyCustomCheck:
id: ClassVar[str] = "CU001"
group: ClassVar[str] = "custom"
name: ClassVar[str] = "MyCustomCheck"
description: ClassVar[str] = "Description of what this check does"
severity: ClassVar[Severity] = Severity.WARNING
requires: ClassVar[set[str]] = {"root", "pyproject"}
doc_url: ClassVar[str] = "https://example.com/checks/CU001.html"
@classmethod
def check(cls, root, pyproject) -> CheckResult:
# Perform check logic
if some_condition:
return CheckResult.passed(
check_id=cls.id,
check_name=cls.name,
message="Check passed",
url=cls.doc_url,
)
return CheckResult.failed(
check_id=cls.id,
check_name=cls.name,
severity=cls.severity,
message="Check failed",
hint="How to fix this issue",
url=cls.doc_url,
)Register via Entry Points
In your package’s pyproject.toml:
[project.entry-points."pycmdcheck.checks"]
my_checks = "my_package.checks:register"The register function:
def register(registry):
registry.add(MyCustomCheck)