Skip to content

Commit

Permalink
Merge f6ab1a0 into 4695989
Browse files Browse the repository at this point in the history
  • Loading branch information
mgedmin committed Oct 29, 2019
2 parents 4695989 + f6ab1a0 commit 15bc359
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 23 deletions.
5 changes: 4 additions & 1 deletion CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ Changelog
0.41 (unreleased)
-----------------

- Nothing changed yet.
- Support `PEP 517`_, i.e. packages using pyproject.toml instead of a setup.py
(`#105 <https://github.com/mgedmin/check-manifest/issue/105>`_).

.. _PEP 517: https://www.python.org/dev/peps/pep-0517/


0.40 (2019-10-15)
Expand Down
52 changes: 34 additions & 18 deletions check_manifest.py
Original file line number Diff line number Diff line change
Expand Up @@ -827,9 +827,12 @@ def is_package(source_tree='.'):
"""Is the directory the root of a Python package?
Note: the term "package" here refers to a collection of files
with a setup.py, not to a directory with an __init__.py.
with a setup.py/pyproject.toml, not to a directory with an __init__.py.
"""
return os.path.exists(os.path.join(source_tree, 'setup.py'))
return (
os.path.exists(os.path.join(source_tree, 'setup.py'))
or os.path.exists(os.path.join(source_tree, 'pyproject.toml'))
)


def extract_version_from_filename(filename):
Expand All @@ -840,6 +843,23 @@ def extract_version_from_filename(filename):
return filename.partition('-')[2]


def build_sdist(tempdir, python=sys.executable):
"""Build a source distribution in a temporary directory.
Should be run with the current working directory inside the Python package
you want to build.
"""
if os.path.exists('pyproject.toml'):
# I could do this in-process with
# import pep517.envbuild
# pep517.envbuild.build_sdist('.', tempdir)
# but then it would print a bunch of things to stdout and I'd have to
# worry about exceptions
run([python, '-m', 'pep517.build', '--source', '-o', tempdir, '.'])
else:
run([python, 'setup.py', 'sdist', '-d', tempdir])


def check_manifest(source_tree='.', create=False, update=False,
python=sys.executable):
"""Compare a generated source distribution with list of files in a VCS.
Expand All @@ -851,7 +871,8 @@ def check_manifest(source_tree='.', create=False, update=False,
python = os.path.abspath(python)
with cd(source_tree):
if not is_package():
raise Failure('This is not a Python project (no setup.py).')
raise Failure(
'This is not a Python project (no setup.py/pyproject.toml).')
read_config()
read_manifest()
info_begin("listing source files under version control")
Expand All @@ -862,7 +883,7 @@ def check_manifest(source_tree='.', create=False, update=False,
raise Failure('There are no files added to version control!')
info_begin("building an sdist")
with mkdtemp('-sdist') as tempdir:
run([python, 'setup.py', 'sdist', '-d', tempdir])
build_sdist(tempdir, python=python)
sdist_filename = get_one_file_in(tempdir)
info_continue(": %s" % os.path.basename(sdist_filename))
sdist_files = sorted(normalize_names(strip_sdist_extras(
Expand All @@ -877,24 +898,19 @@ def check_manifest(source_tree='.', create=False, update=False,
info_begin("copying source files to a temporary directory")
with mkdtemp('-sources') as tempsourcedir:
copy_files(existing_source_files, tempsourcedir)
if os.path.exists('MANIFEST.in') and 'MANIFEST.in' not in source_files:
# See https://github.com/mgedmin/check-manifest/issues/7
# if do this, we will emit a warning about MANIFEST.in not
# being in source control, if we don't do this, the user
# gets confused about their new manifest rules being
# ignored.
copy_files(['MANIFEST.in'], tempsourcedir)
if 'setup.py' not in source_files:
# See https://github.com/mgedmin/check-manifest/issues/46
# if do this, we will emit a warning about setup.py not
# being in source control, if we don't do this, the user
# gets a scary error
copy_files(['setup.py'], tempsourcedir)
for filename in 'MANIFEST.in', 'setup.py', 'pyproject.toml':
if filename not in source_files and os.path.exists(filename):
# See https://github.com/mgedmin/check-manifest/issues/7
# and https://github.com/mgedmin/check-manifest/issues/46:
# if we do this, the user gets a warning about files
# missing from source control; if we don't do this,
# things get very confusing for the user!
copy_files([filename], tempsourcedir)
info_begin("building a clean sdist")
with cd(tempsourcedir):
with mkdtemp('-sdist') as tempdir:
os.environ['SETUPTOOLS_SCM_PRETEND_VERSION'] = version
run([python, 'setup.py', 'sdist', '-d', tempdir])
build_sdist(tempdir, python=python)
sdist_filename = get_one_file_in(tempdir)
info_continue(": %s" % os.path.basename(sdist_filename))
clean_sdist_files = sorted(normalize_names(strip_sdist_extras(
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@
zip_safe=False,
test_suite='tests.test_suite',
python_requires=">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*",
install_requires=['toml'],
install_requires=['toml', 'pep517'],
extras_require={
'test': ['mock'],
},
Expand Down
27 changes: 24 additions & 3 deletions tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -452,9 +452,11 @@ def test_find_suggestions_ignores_directories(self):
def test_is_package(self):
from check_manifest import is_package
j = os.path.join
with mock.patch('os.path.exists', lambda fn: fn == j('a', 'setup.py')):
exists = {j('a', 'setup.py'), j('c', 'pyproject.toml')}
with mock.patch('os.path.exists', lambda fn: fn in exists):
self.assertTrue(is_package('a'))
self.assertFalse(is_package('b'))
self.assertTrue(is_package('c'))

def test_extract_version_from_filename(self):
from check_manifest import extract_version_from_filename as e
Expand Down Expand Up @@ -593,6 +595,24 @@ def test_get_ignore_from_manifest_warnings(self):
"%s, line 2: continuation line immediately precedes end-of-file" % filename,
])

def test_build_sdist(self):
from check_manifest import build_sdist, cd, get_one_file_in
src_dir = self.make_temp_dir()
filename = os.path.join(src_dir, 'pyproject.toml')
self.create_file(filename, textwrap.dedent('''
[build-system]
requires = [
"setuptools >= 40.6.0",
"wheel",
]
build-backend = "setuptools.build_meta"
'''))
out_dir = self.make_temp_dir()
python = os.path.abspath(sys.executable)
with cd(src_dir):
build_sdist(out_dir, python=python)
self.assertTrue(get_one_file_in(out_dir))


class TestConfiguration(unittest.TestCase):

Expand Down Expand Up @@ -1386,8 +1406,9 @@ def test_not_python_project(self):
from check_manifest import check_manifest, Failure
with self.assertRaises(Failure) as cm:
check_manifest()
self.assertEqual(str(cm.exception),
"This is not a Python project (no setup.py).")
self.assertEqual(
str(cm.exception),
"This is not a Python project (no setup.py/pyproject.toml).")

def test_forgot_to_git_add_anything(self):
from check_manifest import check_manifest, Failure
Expand Down

0 comments on commit 15bc359

Please sign in to comment.