ST005: HasSrcLayout
Overview
| Property | Value |
|---|---|
| ID | ST005 |
| Name | HasSrcLayout |
| Group | structure |
| Severity | NOTE |
Description
Checks that the package uses the src/ layout structure.
The src layout places your package code inside a src/ directory, which provides better isolation and prevents common import issues during development.
What it checks
The check verifies:
- A
src/directory exists in the package root - The
src/directory contains at least one package (a directory with__init__.py)
Why it matters
The src layout prevents a common pitfall in Python development:
- Import isolation - Without src layout, Python may accidentally import your local development code instead of the installed package
- Realistic testing - Tests run against the installed package, not the development source
- Build verification - Ensures your package installs correctly before release
Flat layout problems
With a flat layout (my_package/ at root), this can happen:
# You think you're testing the installed package...
import my_package
# But Python imports from the local directory instead!
# Bugs might not be caught until after release.Src layout solution
With src layout (src/my_package/):
# This always imports the installed package
import my_package
# Your tests verify the real installation behaviorHow to fix
Step 1: Create the src directory
mkdir srcStep 2: Move your package
mv my_package src/Step 3: Update pyproject.toml
Most modern build backends auto-detect src layout. If needed, configure explicitly:
For Hatchling:
[tool.hatch.build.targets.wheel]
packages = ["src/my_package"]For Setuptools:
[tool.setuptools.packages.find]
where = ["src"]For Flit:
[tool.flit.module]
name = "my_package"Step 4: Verify
pip install -e .
python -c "import my_package; print(my_package.__file__)"The output should show the installed location, not src/my_package.
Directory structure example
Before (flat layout):
my-project/
my_package/
__init__.py
module.py
tests/
pyproject.toml
After (src layout):
my-project/
src/
my_package/
__init__.py
module.py
tests/
pyproject.toml
Configuration
Skip this check
[tool.pycmdcheck]
skip = ["ST005"]CLI
pycmdcheck --skip ST005