In setuptools, MANIFEST.in controls which files are selected for a source distribution (sdist); it does not, by itself, guarantee those files will be in a wheel. Use package_data or include_package_data to select runtime files for a wheel, make sure the intended Python packages are discovered, then inspect both built artifacts.
First decide which artifact needs the file
An sdist is a source archive used for building and development; it can include documentation, tests, generated sources, and other build inputs. A wheel is intended for installation. The Python Packaging User Guide describes the distinction in Package Formats and explains conceptually that “A wheel contains exactly the files that need to be copied when installing the package.” That describes the format, not whether a particular project has configured its wheel correctly.
- Build input or source-only file: ensure it is selected for the sdist.
- Runtime file inside an importable package: select it for the wheel using a package-data mechanism.
- Needed both to build from source and at runtime: configure both outcomes and verify the sdist and wheel separately.
Presence in an sdist does not establish presence in the wheel.
What each setuptools setting controls
| Mechanism | Main selection role | Artifact implications |
|---|---|---|
MANIFEST.in |
Ordered commands select and remove paths in the sdist file list. | It can contribute package-directory files to a wheel when include_package_data is enabled, but it is not a wheel guarantee by itself. |
package_data |
Explicit patterns select data files within packages. | Can select package data for a wheel and an sdist without relying on a manifest or VCS plugin. |
include_package_data |
Uses package data selected through MANIFEST.in or discovered by an appropriate revision-control plugin. |
When enabled, relevant selected files within package directories can be included in a wheel. |
exclude_package_data |
Excludes matching package files. | Exclusions remove matching files even if another inclusion route would otherwise select them. |
| Package discovery | Determines which Python packages setuptools includes. | It is a separate gate; discovering a package does not automatically include every non-Python file in it. |
These behaviors are documented in the setuptools data files guide. In brief, a wheel file must not be excluded and must be selected by package_data, or through MANIFEST.in together with include_package_data = true. For an sdist, the documented selection rule is a file selected by MANIFEST.in or package_data, unless excluded.
#1 Best Overall
Use MANIFEST.in to shape the sdist
Setuptools looks for MANIFEST.in at the project root. The supported name includes the .in extension; MANIFEST without it is not the documented manifest file. Commands are processed in order, and their paths are relative to the project root.
Choose commands by the paths you need
includeandexcludeselect or remove paths.recursive-includeandrecursive-excludeselect or remove matching files under a directory.global-includeandglobal-excludeapply patterns throughout the tree.graftandpruneadd or remove directory trees.
Command order affects the result
For example, graft tests followed by global-exclude *.py[cod] adds the tests tree and then removes matching bytecode files from the selected list. Reversing the commands can change the result: a later graft may add files again. Start with a broad selection such as a graft when appropriate, then refine it rather than making the manifest unnecessarily intricate.
Rank #2
Setuptools already includes common project files and configured package/data files in an sdist. Add a manifest when defaults miss required files or when you need finer control, such as excluding CI files or including generated sources. A configured VCS plugin such as setuptools-scm can use tracked files to populate the sdist; that is an alternative mechanism, not a universal setuptools guarantee.
Select package files for installation
Use package_data for explicit patterns
package_data is the direct choice when you know which non-code files inside a package belong in distributions. Its patterns do not require MANIFEST.in or a VCS plugin for that selection.
The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Use include_package_data to carry selected files through
include_package_data allows relevant package data selected by the manifest or discovered by an appropriate VCS plugin to reach the wheel. A manifest may select files for the sdist more broadly, but the wheel rule still depends on the setting and package-file scope.
Use exclude_package_data to remove matches
When a file should not ship, exclude_package_data can remove matching package files, including files another inclusion rule selected. Review exclusions alongside both explicit patterns and manifest-based selection.
Account for configuration format and setuptools version
The documented default for include-package-data is true in setuptools pyproject.toml configuration, a behavior introduced in setuptools 61.0.0. In setup.cfg and setup.py, the default remains false for backwards compatibility. Set the value explicitly when you want the configuration to be clear across formats.
Setuptools documents default inclusion of in-package .pyi and py.typed files as introduced in setuptools 69.0.0 and describes it as experimental. Check the behavior against the setuptools version declared in the project’s build requirements; the published setuptools documentation reviewed here identifies version 84.0.0.
Best Value
Make package discovery a separate check
Setuptools automatic package discovery is enabled only when neither packages nor py_modules is explicitly configured. Its discovery guide covers flat and src layouts as well as customization for nested packages and reserved top-level names.
For pyproject.toml, use [tool.setuptools.packages.find] settings such as where, include, exclude, and namespace controls to shape discovery. Implicit namespace scanning is enabled by default in this configuration. See the setuptools package discovery guide.
If a package is not discovered, selecting its data will not solve the packaging problem. Conversely, finding the package does not ensure its non-Python files appear in the wheel; configure data selection independently.
Build and inspect both distributions
- Identify the target: decide whether each missing path belongs in the sdist, installed wheel, or both.
- Confirm package discovery: check the configured layout and any explicit package inclusion or exclusion rules.
- Choose the data mechanism: use manifest commands for sdist selection, package-data settings for package files, and exclusions where needed.
- Build the artifacts: build an sdist and wheel using the project’s configured build backend and requirements.
- Inspect their contents separately: verify the source archive and wheel contain the intended files and omit unwanted ones.
The Packaging User Guide notes that a wheel’s RECORD lists its files, so it is useful for confirming wheel contents. Current standardized sdist layout requirements include a top-level project directory containing pyproject.toml and PKG-INFO; for metadata version 2.4 or later, declared License-File paths must also be present. The source distribution format specification and pyproject.toml specification describe these requirements, including that files matched by configured license-files patterns be included in all distribution archives and listed in Core Metadata.
These are setuptools-specific rules. They should not be assumed to describe similarly named settings or manifest behavior in Hatchling, Flit, Poetry, or another build backend.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




