Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 9 additions & 6 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
global-exclude .DS_Store

global-include *.rst
global-include *.py
# Neither global-include reaches Markdown, which the examples' READMEs are (#719).
# The global-include does not reach Markdown, which the examples' READMEs are (#719).
recursive-include examples *.md

prune .eggs
Expand Down Expand Up @@ -53,7 +52,7 @@ include README.md
include LICENSE

# Load-bearing, and missed for the same reason as ``CHANGELOG.md`` below:
# neither ``global-include`` at the top of this file can reach a ``.cff``, so
# the ``global-include`` at the top of this file cannot reach a ``.cff``, so
# without this line ``CITATION.cff`` sits in the repository and in no source
# distribution at all -- measured by building one each way, not assumed. Nor is
# there a default to fall back on: setuptools ships ``LICENSE`` from its
Expand All @@ -71,7 +70,7 @@ include CITATION.cff

# The changelog needs two lines of its own, and neither is redundant.
#
# ``global-include *.rst`` above matches only ``*.rst``, so the root
# ``global-include *.py`` above matches only ``*.py``, so the root
# ``CHANGELOG.md`` is picked up by nothing and would be absent from every source
# distribution without this line -- measured, not assumed.
include CHANGELOG.md
Expand All @@ -85,5 +84,9 @@ include CHANGELOG.md
# shipped, because it is a ``toctree`` that only Sphinx can read.
recursive-include docs/source/changelog *.rst

include pcapkit/_extern
exclude pcapkit/protocols/*/NotImplemented
# Nothing here names ``pcapkit/_extern``. ``conda/pypcapkit/build.sh`` and
# ``bld.bat`` create it and then run ``pip install .``, which builds the wheel
# straight from the tree, so the conda recipe builds no sdist; its modules
# reach that wheel through package discovery. A line naming it would warn in
# every other build, and ``include`` of a directory matched nothing even in the
# conda one (#1794).
4 changes: 2 additions & 2 deletions docs/source/contributing/conventions/documentation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -298,8 +298,8 @@ Format and Mechanics
ruled this on :issue:`719`, correcting a blanket *always* ``.rst`` that had been in
circulation: the Sphinx documentation is reST, and the other documents --
the READMEs included -- are Markdown where that applies. ``CONTRIBUTING.md``'s own
*Documentation* section records the same split. Neither ``global-include`` in
:file:`MANIFEST.in` reaches Markdown, so the two READMEs under :file:`examples/`
*Documentation* section records the same split. The ``global-include`` in
:file:`MANIFEST.in` does not reach Markdown, so the READMEs under :file:`examples/`
ship through ``recursive-include examples *.md``, and any other Markdown file
ships only if setuptools or an ``include`` line adds it.
* **Prose names the real defining module, not a re-export.** One strand of the
Expand Down
54 changes: 53 additions & 1 deletion tests/project/test_build_leftovers_1773.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
a real wheel of a stub package with :file:`setup.py`'s own ``cmdclass``.
* Each backport's failure message names the feature that tool back-ports.
* ``make profile`` reaches a Makefile that exists, and every ``prune`` in
:file:`MANIFEST.in` names a directory the repository tracks or ignores.
:file:`MANIFEST.in` names a directory the repository tracks or ignores. Every
other line there changes what the template selects (#1794).
* No reStructuredText is tracked outside ``docs/`` (the #719 ruling), the
examples' Markdown READMEs still ship in the sdist, and nothing points at a
README path that no longer exists.
Expand Down Expand Up @@ -213,6 +214,57 @@ def test_every_prune_names_a_tracked_or_ignored_directory(self) -> None:
self.assertEqual(ignored.returncode, 0,
f'prune {directory} names a directory git neither tracks nor ignores')

def test_every_other_directive_changes_the_selection(self) -> None:
"""Dropping any non-``prune`` line changes which tracked files the template selects.

An exclusion may instead guard a path git ignores, as ``prune`` may above.
The template runs without setuptools' defaults, so ``include README.md``
counts as effective here although a real build ships the README anyway
(#1794).
"""
files = tracked()
directives = [line.strip() for line in
(ROOT / 'MANIFEST.in').read_text(encoding='utf-8').splitlines()
if line.strip() and not line.lstrip().startswith('#')]
driver = textwrap.dedent('''
import json, os, sys
from setuptools.command.egg_info import FileList
data = json.loads(sys.stdin.read())
tracked = set(data['files'])

def select(lines):
listing = FileList()
listing.allfiles = list(data['files'])
for line in lines:
listing.process_template_line(line)
return sorted({name.replace(os.sep, '/') for name in listing.files} & tracked)

lines = data['lines']
print(json.dumps([select(lines)] + [select(lines[:index] + lines[index + 1:])
for index in range(len(lines))]))
''')
result = subprocess.run([sys.executable, '-c', driver], cwd=ROOT, # nosec
input=json.dumps({'files': files, 'lines': directives}),
capture_output=True, text=True, check=True, timeout=120)
selected, *without = json.loads(result.stdout)
for line, rest in zip(directives, without):
action, *words = line.split()
if action == 'prune':
continue
with self.subTest(line=line):
if rest != selected:
continue
if action.endswith('exclude'):
if action.startswith('recursive-'):
targets = [f'{words[0]}/{pattern}' for pattern in words[1:]]
else:
targets = words
if all(subprocess.run(['git', 'check-ignore', '-q', '--no-index', # nosec
target], cwd=ROOT, check=False).returncode == 0
for target in targets):
continue
self.fail(f'{line!r} changes nothing the template selects from the tracked files')

def test_no_restructuredtext_outside_docs(self) -> None:
stray = [name for name in tracked()
if name.endswith('.rst') and not name.startswith('docs/')]
Expand Down
Loading