Repository: pypa/build
Pull request #159 (2020-10-23 14:45:21)

main: add --version/-V
Signed-off-by: Filipe Laíns <lains@archlinux.org>


Patch:
diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml
index 5eb3704..c841def 100644
--- a/.github/workflows/check.yml
+++ b/.github/workflows/check.yml
@@ -25,7 +25,7 @@ jobs:
   pytest:
     runs-on: ${{ matrix.os }}-latest
     env:
-      PYTEST_ADDOPTS: "--showlocals -vv --durations=10"
+      PYTEST_ADDOPTS: "--run-integration --showlocals -vv --durations=10"
     strategy:
       fail-fast: false
       matrix:
@@ -78,13 +78,13 @@ jobs:
         run: tox -e ${{env.BASE}} --skip-pkg-install
 
       - name: Run test suite via path
-        run: tox -e ${{env.BASE}}-path --skip-pkg-install -- --run-integration
+        run: tox -e ${{env.BASE}}-path --skip-pkg-install
 
       - name: Run test suite via sdist
-        run: tox -e ${{env.BASE}}-sdist --skip-pkg-install -- --run-integration
+        run: tox -e ${{env.BASE}}-sdist --skip-pkg-install
 
       - name: Run test suite via wheel
-        run: tox -e ${{env.BASE}}-wheel --skip-pkg-install -- --run-integration
+        run: tox -e ${{env.BASE}}-wheel --skip-pkg-install
 
       - name: Rename coverage report file
         run: |
@@ -108,7 +108,7 @@ jobs:
       fail-fast: false
       matrix:
         os:
-          - Ubuntu
+          - ubuntu
         tox_env:
           - type
           - docs
diff --git a/setup.cfg b/setup.cfg
index 3a8de65..d013a22 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -1,6 +1,7 @@
 [metadata]
 name = build
 version = 0.0.4
+description = A simple, correct PEP517 package builder
 long_description = file: README.md
 long_description_content_type = text/markdown
 author = Filipe Laíns
@@ -55,6 +56,10 @@ typing =
     mypy==0.790
     typing-extensions>=3.7.4.3
 
+[options.package_data]
+build =
+    py.typed
+
 [options.packages.find]
 where = src
 
diff --git a/src/build/__init__.py b/src/build/__init__.py
index f441341..ce5375c 100644
--- a/src/build/__init__.py
+++ b/src/build/__init__.py
@@ -11,7 +11,7 @@ import os
 import sys
 import warnings
 
-from typing import Dict, Iterator, List, Mapping, Optional, Set, Union, Text
+from typing import Iterator, Mapping, Optional, Sequence, Set, Text, Union
 
 import pep517.wrappers
 import toml
@@ -22,7 +22,7 @@ if sys.version_info < (3,):
     PermissionError = OSError
 
 
-ConfigSettings = Dict[str, Union[str, List[str]]]
+ConfigSettings = Mapping[str, Union[str, Sequence[str]]]
 
 
 _DEFAULT_BACKEND = {
@@ -84,7 +84,7 @@ def check_version(requirement_string, extra=''):  # type: (str, str) -> bool
             return False
         warnings.warn(
             "Verified that the '{}[{}]' extra is present but did not verify that it is active "
-            "(it's dependencies are met)".format(req.name, extra),
+            '(its dependencies are met)'.format(req.name, extra),
             IncompleteCheckWarning,
         )
 
@@ -126,8 +126,8 @@ class ProjectBuilder(object):
         :param config_settings: config settings for the build backend
         :param python_executable: the python executable where the backend lives
         """
-        self.srcdir = os.path.abspath(srcdir)
-        self.config_settings = config_settings if config_settings else {}
+        self.srcdir = os.path.abspath(srcdir)  # type: str
+        self.config_settings = config_settings if config_settings else {}  # type: ConfigSettings
 
         spec_file = os.path.join(srcdir, 'pyproject.toml')
 
@@ -155,7 +155,7 @@ class ProjectBuilder(object):
 
         self._backend = self._build_system['build-backend']
 
-        self.hook = pep517.wrappers.Pep517HookCaller(
+        self._hook = pep517.wrappers.Pep517HookCaller(
             self.srcdir,
             self._backend,
             backend_path=self._build_system.get('backend-path'),
@@ -165,12 +165,12 @@ class ProjectBuilder(object):
     @property
     def python_executable(self):  # type: () -> Union[bytes, Text]
         # make mypy happy
-        exe = self.hook.python_executable  # type: Union[bytes, Text]
+        exe = self._hook.python_executable  # type: Union[bytes, Text]
         return exe
 
     @python_executable.setter
     def python_executable(self, value):  # type: (Union[bytes, Text]) -> None
-        self.hook.python_executable = value
+        self._hook.python_executable = value
 
     @property
     def build_dependencies(self):  # type: () -> Set[str]
@@ -180,7 +180,7 @@ class ProjectBuilder(object):
         """
         Returns a set of dependencies
         """
-        get_requires = getattr(self.hook, 'get_requires_for_build_{}'.format(distribution))
+        get_requires = getattr(self._hook, 'get_requires_for_build_{}'.format(distribution))
 
         try:
             with _working_directory(self.srcdir):
@@ -208,7 +208,7 @@ class ProjectBuilder(object):
         :param distribution: Distribution to build (sdist or wheel)
         :param outdir: Output directory
         """
-        build = getattr(self.hook, 'build_{}'.format(distribution))
+        build = getattr(self._hook, 'build_{}'.format(distribution))
         outdir = os.path.abspath(outdir)
 
         if os.path.exists(outdir):
diff --git a/src/build/__main__.py b/src/build/__main__.py
index 24fe371..3ee1257 100644
--- a/src/build/__main__.py
+++ b/src/build/__main__.py
@@ -6,8 +6,9 @@ import sys
 import traceback
 import warnings
 
-from typing import List, Optional, TextIO, Type, Union
+from typing import List, Optional, TextIO, Type, Union, Iterable
 
+import build
 from build import BuildBackendException, BuildException, ConfigSettings, ProjectBuilder
 from build.env import IsolatedEnvBuilder
 
@@ -59,7 +60,7 @@ def _build_in_current_env(builder, outdir, distributions, skip_dependencies=Fals
         builder.build(dist, outdir)
 
 
-def build(srcdir, outdir, distributions, config_settings=None, isolation=True, skip_dependencies=False):
+def build_package(srcdir, outdir, distributions, config_settings=None, isolation=True, skip_dependencies=False):
     # type: (str, str, List[str], Optional[ConfigSettings], bool, bool) -> None
     """
     Runs the build process
@@ -96,6 +97,9 @@ def main_parser():  # type: () -> argparse.ArgumentParser
     """
     cwd = os.getcwd()
     out = os.path.join(cwd, 'dist')
+    # mypy does not recognize module.__path__
+    # https://github.com/python/mypy/issues/1422
+    paths = build.__path__  # type: Iterable[Optional[str]]  # type: ignore
     parser = argparse.ArgumentParser()
     parser.add_argument(
         'srcdir',
@@ -105,6 +109,12 @@ def main_parser():  # type: () -> argparse.ArgumentParser
         default=cwd,
         help='source directory (defaults to current directory)',
     )
+    parser.add_argument(
+        '--version',
+        '-V',
+        action='version',
+        version='build {} ({})'.format(build.__version__, ', '.join(path for path in paths if path)),
+    )
     parser.add_argument(
         '--sdist',
         '-s',
@@ -183,7 +193,7 @@ def main(cli_args, prog=None):  # type: (List[str], Optional[str]) -> None
     if not distributions:
         distributions = ['sdist', 'wheel']
 
-    build(args.srcdir, args.outdir, distributions, config_settings, not args.no_isolation, args.skip_dependencies)
+    build_package(args.srcdir, args.outdir, distributions, config_settings, not args.no_isolation, args.skip_dependencies)
 
 
 def entrypoint():  # type: () -> None


Test patch:
diff --git a/src/build/py.typed b/src/build/py.typed
new file mode 100644
index 0000000..e69de29
diff --git a/tests/test_main.py b/tests/test_main.py
index bca03a1..3a00fc8 100644
--- a/tests/test_main.py
+++ b/tests/test_main.py
@@ -66,10 +66,10 @@ out = os.path.join(cwd, 'dist')
     ],
 )
 def test_parse_args(mocker, cli_args, build_args):
-    mocker.patch('build.__main__.build')
+    mocker.patch('build.__main__.build_package')
 
     build.__main__.main(cli_args)
-    build.__main__.build.assert_called_with(*build_args)
+    build.__main__.build_package.assert_called_with(*build_args)
 
 
 def test_prog():
@@ -86,13 +86,21 @@ def test_prog():
             build.__main__.main(['--help'], prog='something')
 
 
+def test_version(capsys):
+    with pytest.raises(SystemExit):
+        build.__main__.main(['--version'])
+    out, err = capsys.readouterr()
+    target = out if sys.version_info[0] == 3 else err
+    assert target.startswith('build {}'.format(build.__version__))
+
+
 @pytest.mark.isolated
 def test_build_isolated(mocker, test_flit_path):
     build_cmd = mocker.patch('build.ProjectBuilder.build')
     mocker.patch('build.__main__._error')
     install = mocker.patch('build.env._IsolatedEnvVenvPip.install')
 
-    build.__main__.build(test_flit_path, '.', ['sdist'])
+    build.__main__.build_package(test_flit_path, '.', ['sdist'])
 
     build_cmd.assert_called_with('sdist', '.')
     install.assert_called_with({'flit_core >=2,<3'})
@@ -103,7 +111,7 @@ def test_build_no_isolation_check_deps_empty(mocker, test_flit_path):
     build_cmd = mocker.patch('build.ProjectBuilder.build')
     mocker.patch('build.ProjectBuilder.check_dependencies', return_value=[])
 
-    build.__main__.build(test_flit_path, '.', ['sdist'], isolation=False)
+    build.__main__.build_package(test_flit_path, '.', ['sdist'], isolation=False)
 
     build_cmd.assert_called_with('sdist', '.')
 
@@ -114,7 +122,7 @@ def test_build_no_isolation_with_check_deps(mocker, test_flit_path):
     build_cmd = mocker.patch('build.ProjectBuilder.build')
     mocker.patch('build.ProjectBuilder.check_dependencies', return_value=['something'])
 
-    build.__main__.build(test_flit_path, '.', ['sdist'], isolation=False)
+    build.__main__.build_package(test_flit_path, '.', ['sdist'], isolation=False)
 
     build_cmd.assert_called_with('sdist', '.')
     error.assert_called_with('Missing dependencies:\n\tsomething')
@@ -126,7 +134,7 @@ def test_build_raises_build_exception(mocker, test_flit_path):
     mocker.patch('build.ProjectBuilder.build', side_effect=build.BuildException)
     mocker.patch('build.env._IsolatedEnvVenvPip.install')
 
-    build.__main__.build(test_flit_path, '.', ['sdist'])
+    build.__main__.build_package(test_flit_path, '.', ['sdist'])
 
     error.assert_called_with('')
 
@@ -137,6 +145,6 @@ def test_build_raises_build_backend_exception(mocker, test_flit_path):
     mocker.patch('build.ProjectBuilder.build', side_effect=build.BuildBackendException)
     mocker.patch('build.env._IsolatedEnvVenvPip.install')
 
-    build.__main__.build(test_flit_path, '.', ['sdist'])
+    build.__main__.build_package(test_flit_path, '.', ['sdist'])
 
     error.assert_called_with('')
diff --git a/tests/test_projectbuilder.py b/tests/test_projectbuilder.py
index 3304e06..1d38efa 100644
--- a/tests/test_projectbuilder.py
+++ b/tests/test_projectbuilder.py
@@ -136,7 +136,7 @@ def test_python_executable(test_flit_path, value):
 
     builder.python_executable = value
     assert builder.python_executable == value
-    assert builder.hook.python_executable == value
+    assert builder._hook.python_executable == value
 
 
 @pytest.mark.parametrize('distribution', ['wheel', 'sdist'])
@@ -172,8 +172,8 @@ def test_check_dependencies(mocker, test_flit_path):
     ]
 
     build.check_version.return_value = False
-    builder.hook.get_requires_for_build_sdist.side_effect = copy.copy(side_effects)
-    builder.hook.get_requires_for_build_wheel.side_effect = copy.copy(side_effects)
+    builder._hook.get_requires_for_build_sdist.side_effect = copy.copy(side_effects)
+    builder._hook.get_requires_for_build_wheel.side_effect = copy.copy(side_effects)
 
     # requires = []
     assert builder.check_dependencies('sdist') == {'flit_core >=2,<3'}
@@ -203,15 +203,15 @@ def test_build(mocker, test_flit_path, tmp_dir):
 
     builder = build.ProjectBuilder(test_flit_path)
 
-    builder.hook.build_sdist.side_effect = [None, Exception]
-    builder.hook.build_wheel.side_effect = [None, Exception]
+    builder._hook.build_sdist.side_effect = [None, Exception]
+    builder._hook.build_wheel.side_effect = [None, Exception]
 
     builder.build('sdist', tmp_dir)
-    builder.hook.build_sdist.assert_called_with(tmp_dir, {})
+    builder._hook.build_sdist.assert_called_with(tmp_dir, {})
     build._working_directory.assert_called_with(test_flit_path)
 
     builder.build('wheel', tmp_dir)
-    builder.hook.build_wheel.assert_called_with(tmp_dir, {})
+    builder._hook.build_wheel.assert_called_with(tmp_dir, {})
     build._working_directory.assert_called_with(test_flit_path)
 
     with pytest.raises(build.BuildBackendException):
@@ -277,7 +277,7 @@ def test_relative_outdir(mocker, tmp_dir, test_flit_path):
 
     builder.build('sdist', '.')
 
-    builder.hook.build_sdist.assert_called_with(os.path.abspath('.'), {})
+    builder._hook.build_sdist.assert_called_with(os.path.abspath('.'), {})
 
 
 def test_not_dir_outdir(mocker, tmp_dir, test_flit_path):