A Visual Studio Code extension with support for Python manifest
templates, e.g. MANIFEST.in.
The Python manifest template has always been tricky to deal with. First you
have to get the right configuration between all of the involved bits, such as
setup.py, setup.cfg, and MANIFEST.in. Then you then need to play
whack-a-mole testing your distribution or — actually probably and —
take a very deep dive into distutils and setuptools code to figure out
the nuance of the six template commands for including and excluding files.
Hopefully between the syntax, snippets, and documentation (below) your pain will lessen.
That is a good question! More and more the answer is, “Possibly not.” There
are various setuptools extensions like setuptools_scm that can
leverage your version control for tracking files to include and exclude.
There are also complete build system replacements, such as flit.
However, you may still need a MANIFEST.in.
- You may be unable or unwilling to use a build system other than 
setuptools. - Your project may be so simple that you don’t want to bother with another dependency for version control integration.
 - Your project may be so complex that version control integration does not fully meet your needs. You may be generating untracked files that need to be included, or need to exclude tracked files.
 
If you do need a MANIFEST.in we are going to try to make it hurt less. They
can be tough because first you have to get the right configuration between
all of the involved bits, such as setup.py, setup.cfg, and MANIFEST.in.
Then you then need to play whack-a-mole testing your distribution or —
actually probably and — take a very deep dive into distutils and
setuptools code to figure out the nuance of the six template commands for
including and excluding files.
Look at the included example directory to see an documented example of a
Python package with a MANIFEST.in.
There are eight commands that take one, two, or more shell-style patterns.
| Add | Remove | Arguments | Anchored | 
|---|---|---|---|
include | 
exclude | 
file-pattern1 [file-patternN] | ✔ | 
global-include | 
global-exclude | 
file-pattern1 [file-patternN] | ✘ | 
recursive-include | 
recursive-exclude | 
dir-pattern file-pattern1 [file-patternN] | ✔ dir pattern  ✘ file patterns  | 
graft | 
prune | 
dir-pattern | ✔ | 
The order of the commands in your template file matters. I recommend doing includes first, then excludes, going from most specific to most general.
includesglobal-includesrecursive-includesgraftsexcludesglobal-excludesrecursive-excludesprunes
Remember: You only need to exclude files get added to the list by default or
*with your include commands -- *you do not need to fully mirror your
*.gitignore with exclude commands.
If a pattern is anchored that means it must match the root of the project precisely. For example, given these files:
.
├── LICENSE.txt
└── things
    └── LICENSE.txt
- The command 
include LICENSE.txtwould addLICENSE.txtbut missthings/LICENSE.txt. - The command 
global-include LICENSE.txtwould add anyLICENSE.txtfound in the tree. 
Thus you want to be certain to use a global-exclude to keep out unwanted
files that get strewn about everywhere:
global-exclude *.py[cod]
global-exclude .DS_Store
| Glob | Becomes regex | Matches | Example | 
|---|---|---|---|
* | 
[^/]* | 
Match 0 or more anything but a path seperator, e.g. / | 
*.txt | 
? | 
[^/] | 
Match 1 of anything but a path seperator, e.g. / | 
|
** | 
.* | 
Match anything, including path seperators. | src/**/templates | 
[seq] | 
[seq] | 
Match any character within; ranges are valid. | step-[0-9].png | 
[!seq] | 
[^seq] | 
Match anything except a character within; ranges are valid. | [!0-9] | 
Note: Older versions of Python did not support the globstar (
**). While it is a wonderful addition in newer version of Python andsetuptools, it can still take some playing with to get the result you want, particularly withgraftandprune.
- Leading and trailing whitespace are irrelevant.
 - Comments are an 
#not escaped with a\, i.e.,\#would not start a comment. - Lines can be continued using a 
\. 
An example of some syntax is useful:
include LICENSE.txt
# If you need a literal special glob character, put it in a sequence.
include myfile[?].txt
# To match a literal hash, escape it.
include my\#file.txt
graft docs
global-exclude \
  *.py[cod] \  # Comments after line continuations are valid.
  # And between line continuations as well!
  .DS_Store \  # Last item can have a line continuation as well, as long as the next line is blank.
prune docs/build
For a real-world example, have a look at the included example/MANIFEST.in.
