Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Read the existing MANIFEST.in file for files to ignore. #19

Merged
merged 16 commits into from
Oct 10, 2013

Conversation

mauritsvanrees
Copy link
Contributor

The existing MANIFEST.in can have been setup to ignore some files or complete directories. check-manifest should not complain that those are in version control but not in the sdist.

If MANIFEST.in exists, we read it and add relevant entries to the IGNORE definition. To properly support the exclude directive I needed to add an IGNORE_REGEXPS definition.

Tests pass on the two supported pythons that I have: 2.7 and 3.3.

@coveralls
Copy link

Coverage Status

Coverage increased (+2.2%) when pulling 76e42db on mauritsvanrees:maurits-read-manifest into c8e785a on mgedmin:master.

@mauritsvanrees
Copy link
Contributor Author

Strange: the above comment by coveralls says the coverage increased, but I got a mail from coveralls and that said:

"Coverage remained the same when pulling 76e42db on mauritsvanrees:maurits-read-manifest into c8e785a on mgedmin:master."

The percentage is 78 in both cases. I had this difference with a previous pull request too. Oh well.

# XXX modifies global state, which is kind of evil
if not os.path.isfile('MANIFEST.in'):
return
contents = open('MANIFEST.in').read()
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use the with statement to avoid ResourceWarnings on Python 3.x and leaking file descriptors on PyPy.

@mgedmin
Copy link
Owner

mgedmin commented Oct 6, 2013

Thank you for the pull request.

I'd like to see some examples of projects that have files contained in the version control system that must be excluded from source distributions. Can you satisfy my curiosity?

This avoids ResourceWarnings on Python 3.x and leaking file descriptors on PyPy.
'split' already ignores leading and trailing whitespace.
Remove leading whitespace programmatically with textwrap.dedent.
@coveralls
Copy link

Coverage Status

Coverage increased (+2.33%) when pulling 3a5afc6 on mauritsvanrees:maurits-read-manifest into c8e785a on mgedmin:master.

@mauritsvanrees
Copy link
Contributor Author

Thanks for your detailed feedback on the code. I have pushed the improvements.

The example that caused me to have a look at this, is plone.app.contenttypes. When I run check-manifest in a clone, I get this output:

$ check-manifest 
listing source files under version control: 169 files and directories
copying source files to a temporary directory
building an sdist: plone.app.contenttypes-1.0dev.tar.gz: 155 files and directories
files in version control do not match the sdist!
missing from sdist:
  .travis.yml
  bootstrap.py
  buildout.cfg
  dev.cfg
  headers.sh
  jenkins.cfg
  sphinx.cfg
  templates
  templates/code-analysis.sh
  test-plone-4.1.x.cfg
  test-plone-4.2.x.cfg
  test-plone-4.3.x-ecosystem.cfg
  test-plone-4.3.x.cfg
  travis.cfg
suggested MANIFEST.in rules:
  include *.py
  include *.sh
  include .travis.yml
  include buildout.cfg
  include dev.cfg
  include jenkins.cfg
  include sphinx.cfg
  include test-plone-4.1.x.cfg
  include test-plone-4.2.x.cfg
  include test-plone-4.3.x-ecosystem.cfg
  include test-plone-4.3.x.cfg
  include travis.cfg
  recursive-include templates *.sh

There is a MANIFEST.in already. It has no relevant excludes yet, but with the code in this pull request I could add these lines to the manifest and then check-manifest no longer complains:

exclude bootstrap.py *.cfg *.yml *.sh
prune templates

An argument against this would be that these are files that are not normally included by Python, so it may be better to tell check-manifest to ignore these by adding a few lines to setup.cfg. But someone may have installed the setuptools-git package and then these files would be included.

Perhaps a better example is that some packages prune the tests directory, for example Products.TinyMCE. Without the code from this pull request, check-manifest complains:

missing from sdist:
  Products/TinyMCE/tests
  Products/TinyMCE/tests/__init__.py
  Products/TinyMCE/tests/base.py
  ...

# Regular expressions for filename to ignore. This is useful for
# filename patterns where the '*' part must not search in
# directories.
]
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The closing ] should be unindented.

I believe pep8 warns about this, but even if it doesn't, let's keep it consistent with the rest of the file.

@mgedmin
Copy link
Owner

mgedmin commented Oct 7, 2013

As for your project examples, I think all those are source files that should be included in source distributions. Tests are part of the source code! Build configuration is something you need if you want to work on a package. Even .travis.yml, while functionally useless in a tarball, can act as documentation for people telling them how to run the tests.

@coveralls
Copy link

Coverage Status

Coverage increased (+3.15%) when pulling 77fe8dc on mauritsvanrees:maurits-read-manifest into c8e785a on mgedmin:master.

@mauritsvanrees
Copy link
Contributor Author

I am done with the fixes.

I actually never exclude the tests in my packages, but I can imagine that in some projects people think they bloat the package too much. And lots of source code packages have the same bootstrap.py and it does help much to distribute that. Also, it will not actually be available once you have installed it as an egg: it ends up in the source distribution but not in the egg.

Anyway, the pull request does not advocate excluding or pruning stuff, but only helps in not letting check-manifest complain about missing those files, but I think you got that point.

elif cmd == 'global-exclude':
ignore.extend(rest.split())
elif cmd == 'recursive-exclude':
dirname, patterns = rest.split(None, 1)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this can raise ValueError if you've got a malformed MANIFEST.in with recursive-exclude dir but no patterns.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True. I was thinking: if this is wrong then python itself will complain when trying to use the manifest.

Well, python prints a warning but happily continues:

warning: manifest_maker: MANIFEST.in, line 6: 'recursive-exclude' expects <dir> <pattern1> <pattern2> ...

I have changed to code to print the same warning (without line number) when we get a ValueError.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I have added a test for this. This means that running the tests will print a warning. Not sure if that is a thing to avoid.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer tests to pass without warnings or in fact any extra output to stdout/stderr. This should be easy to arrange by adding a

with warnings.catch_warnings():
   self.assertEqual(function_that_causes_the_warning(...), ...)

We could even test the spelling of the warning with

with warnings.catch_warnings(record=True) as w:
   self.assertEqual(function_that_causes_the_warning(...), ...)
   self.assertEqual(w, ['...'])

but I'm not convinced it's worth the effort.

@coveralls
Copy link

Coverage Status

Coverage increased (+3.48%) when pulling b62f61a on mauritsvanrees:maurits-read-manifest into c8e785a on mgedmin:master.

@mauritsvanrees
Copy link
Contributor Author

Thanks for your continuing constructive feedback. I have pushed the commits based on your remarks. I am now running tox with all four supported pythons and the tests all pass.

Should you finally decide not to accept this pull request, I have at least learned a lot about MANIFEST.in. ;-)

@mgedmin
Copy link
Owner

mgedmin commented Oct 9, 2013

Incidentally I came up with a really good use-case for the 'exclude' feature: buildout. It has two packages in one source tree (zc.buildout and zc.recipe.egg), with separate setup.py files and everything.

Ironically, its MANIFEST.in does not use the exclude feature.

@mgedmin
Copy link
Owner

mgedmin commented Oct 9, 2013

I keep wondering about one thing: if one has a setuptools version control system plugin that tells it to include some file, but the MANIFEST in tells it to exclude the same file, what will setuptools do?

I hope it'll exclude that file, in which case I have no further reservations for merging this PR. Well, except those two small fixes I asked about: shutting up warnings and handling recursive-exclude dir prefix*. And I worry a bit that all those string.rstrip(os.path.sep) will make Windows compatibility a pain. And I worry about blindly using a glob pattern as a regexp, after escaping just two of the special characters (. and *), but ignoring the rest (e.g. ? is special in glob but has a completely different meaning in regexps; I don't expect + or | or (/) to show up in filename patterns...).

Eh, we can deal with those issues when the bugs get filed. I'll wait for updates for warnings and prefix*, then merge this. Or if you're tired of complying with my unreasonable demands, I can merge and do the fixes myself.

@coveralls
Copy link

Coverage Status

Coverage increased (+4.25%) when pulling f83b42d on mauritsvanrees:maurits-read-manifest into c8e785a on mgedmin:master.

@mauritsvanrees
Copy link
Contributor Author

I notice one nasty thing that seems really unexpected in MANIFEST.in. If for example in plone.app.contenttypes I add this line I expect that the sdist will exclude upgrades.py and browser/utils.py and a few more like that:

recursive-exclude plone/app/contenttypes u*

That is correct, but a file like subscribers.py is also excluded, simply because there is a u followed by some more characters. That there is an s in front is disregarded. This has got nothing to do with check-manifest, this is just what happens when I check the result of python2.7 setup.py sdist.

With the current status of this pull request, check-manifest complains that subscribers.py and some more files are not in the sdist. This means that check-manifest does not parse the MANIFEST.in correctly, but I am inclined to say that it is good to warn here, because for most people this will be unexpected.

@mgedmin
Copy link
Owner

mgedmin commented Oct 10, 2013

headdesk distutils

Ignore warnings in one known spot in the tests.
This keeps the test output clean.
@coveralls
Copy link

Coverage Status

Coverage increased (+4.31%) when pulling 7538143 on mauritsvanrees:maurits-read-manifest into c8e785a on mgedmin:master.

@mauritsvanrees
Copy link
Contributor Author

Quoting you: "I keep wondering about one thing: if one has a setuptools version control system plugin that tells it to include some file, but the MANIFEST in tells it to exclude the same file, what will setuptools do?"

It excludes them. If I use a clean python without setuptools plugins and use it to create an sdist of a plone package without MANIFEST.in, it will not contain for example the zcml files. If I install setuptools-git and recreate the sdist, the zcml files are included. If I add a line in MANIFEST.in to exclude zcml files, they are again excluded.

The warnings are ignored now in the tests, which means I had to change the existing warning function, because it simply printed to stderr. Note that the warnings module by default prints to stderr too.

I'm not tired of unreasonable or reasonable demands yet. ;-)

@mgedmin
Copy link
Owner

mgedmin commented Oct 10, 2013

Gah! Sorry, I completely forgot that there was an existing warning() function, and assumed you used the warnings module.

mgedmin added a commit that referenced this pull request Oct 10, 2013
Read the existing MANIFEST.in file for files to ignore.
@mgedmin mgedmin merged commit 58b0aaa into mgedmin:master Oct 10, 2013
@mauritsvanrees
Copy link
Contributor Author

0.17 is released I see. Thanks!

@mauritsvanrees mauritsvanrees deleted the maurits-read-manifest branch October 10, 2013 15:05
@myint
Copy link
Contributor

myint commented Oct 11, 2013

I guess this accomplishes what I originally wanted in #10. Thanks!

@myint
Copy link
Contributor

myint commented Oct 11, 2013

By the way, if you ever want to get rid of the --ignore option I added, that would be fine with me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants