When using python -m build, the following are automatically included:
- Python files: All
.pyfiles in packages found by setuptools - Package metadata:
README.md,LICENSE(as specified inpyproject.toml) - Package data: Only if explicitly configured (see below)
Not included by default:
- Tests directory (good!)
- Documentation files
- Configuration files (
.env, etc.) - Data files in packages
To include non-Python files (templates, configs, data) in your package:
[tool.setuptools.package-data]
# Include specific file patterns in your package
my_package = [
"*.txt", # All .txt files in my_package/
"data/*.json", # JSON files in my_package/data/
"templates/*.html", # HTML templates
"static/**/*", # Everything in static/ (recursive)
]
# For multiple packages
[tool.setuptools.package-data]
my_package = ["*.txt", "data/*.json"]
my_package.submodule = ["*.yaml"]For data files that should be installed outside your package directory:
[tool.setuptools.data-files]
# Format: destination = [source_files]
"share/my_package" = ["data/*.conf", "data/*.ini"]
"etc/my_package" = ["config/default.cfg"]Note: This approach is less common. Usually better to keep data inside your package.
With src layout, you rarely need to exclude files. But if needed:
[tool.setuptools]
# Exclude specific patterns from all packages
exclude-package-data = {
"*" = ["*.c", "*.h", "*.so"], # Exclude C source/compiled files
}Always check what ended up in your distribution:
# Build the wheel
python -m build
# List contents of wheel
unzip -l dist/my_package-1.0.0-py3-none-any.whl
# Or extract and inspect
unzip dist/my_package-1.0.0-py3-none-any.whl -d /tmp/inspect
tree /tmp/inspect[tool.setuptools.package-data]
my_package = ["data.json"]Access in code:
from importlib.resources import files
data_file = files('my_package') / 'data.json'
text = data_file.read_text()[tool.setuptools.package-data]
my_package = ["templates/**/*"] # Everything in templates/ recursively[tool.setuptools.package-data]
my_package = [
"*.txt",
"*.md",
"*.json",
"*.yaml",
"*.yml",
]With pyproject.toml, you rarely need MANIFEST.in. It’s only needed for:
- Including files in source distribution (
.tar.gz) but not in wheel - Legacy compatibility with old build systems
Modern approach: Configure everything in pyproject.toml