Hello community,

here is the log from the commit of package python-pep517 for openSUSE:Factory 
checked in at 2019-08-30 14:39:44
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-pep517 (Old)
 and      /work/SRC/openSUSE:Factory/.python-pep517.new.7948 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-pep517"

Fri Aug 30 14:39:44 2019 rev:2 rq:726606 version:0.6.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-pep517/python-pep517.changes      
2019-03-22 15:00:40.913815072 +0100
+++ /work/SRC/openSUSE:Factory/.python-pep517.new.7948/python-pep517.changes    
2019-08-30 14:39:45.333436446 +0200
@@ -1,0 +2,11 @@
+Tue Aug 27 14:19:08 UTC 2019 - Marketa Calabkova <[email protected]>
+
+- update to version 0.6.0
+  * Rely on __legacy__ for fallback behavior.
+  * Add a runner argument to Pep517HookCaller.
+  * Rename 'build_meta' to simply 'meta'
+  * Use the classic syntax for __main__ detection
+  * Move 'build' support to build module
+  * backend-path fixes
+
+-------------------------------------------------------------------

Old:
----
  pep517-0.5.0.tar.gz

New:
----
  pep517-0.6.0.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-pep517.spec ++++++
--- /var/tmp/diff_new_pack.KOKTsf/_old  2019-08-30 14:39:46.333436265 +0200
+++ /var/tmp/diff_new_pack.KOKTsf/_new  2019-08-30 14:39:46.333436265 +0200
@@ -18,7 +18,7 @@
 
 %{?!python_module:%define python_module() python-%{**} python3-%{**}}
 Name:           python-pep517
-Version:        0.5.0
+Version:        0.6.0
 Release:        0
 Summary:        Wrappers to build Python packages using PEP 517 hooks
 License:        MIT
@@ -30,10 +30,10 @@
 BuildRequires:  python-rpm-macros
 BuildArch:      noarch
 Requires:       python-pytoml
+BuildRequires:  %{python_module mock}
+BuildRequires:  %{python_module pytest}
 BuildRequires:  %{python_module pytoml}
 BuildRequires:  %{python_module testpath}
-BuildRequires:  %{python_module pytest}
-BuildRequires:  %{python_module mock}
 %python_subpackages
 
 %description
@@ -51,7 +51,8 @@
 %python_expand %fdupes %{buildroot}%{$python_sitelib}
 
 %check
-%python_exec -m pytest
+#test_meta.py: xFx (F like "failed to download package via pip")
+%pytest --ignore tests/test_meta.py
 
 %files %{python_files}
 %doc README.rst

++++++ pep517-0.5.0.tar.gz -> pep517-0.6.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pep517-0.5.0/PKG-INFO new/pep517-0.6.0/PKG-INFO
--- old/pep517-0.5.0/PKG-INFO   1970-01-01 01:00:00.000000000 +0100
+++ new/pep517-0.6.0/PKG-INFO   1970-01-01 01:00:00.000000000 +0100
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: pep517
-Version: 0.5.0
+Version: 0.6.0
 Summary: Wrappers to build Python packages using PEP 517 hooks
 Home-page: https://github.com/takluyver/pep517
 Author: Thomas Kluyver
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pep517-0.5.0/README.rst new/pep517-0.6.0/README.rst
--- old/pep517-0.5.0/README.rst 2018-12-17 18:23:15.552506700 +0100
+++ new/pep517-0.6.0/README.rst 2019-02-01 13:28:28.911631300 +0100
@@ -34,11 +34,16 @@
 .. code-block:: python
 
     import os
+    import pytoml
     from pep517.wrappers import Pep517HookCaller
 
     src = 'path/to/source'  # Folder containing 'pyproject.toml'
-    hooks = Pep517HookCaller(src)
-    print(hooks.build_sys_requires)  # List of static requirements
+    with open(os.path.join(src, 'pyproject.toml')) as f:
+        build_sys = pytoml.load(f)['build-system']
+
+    print(build_sys['requires'])  # List of static requirements
+
+    hooks = Pep517HookCaller(src, build_backend=build_sys['build_backend'])
 
     config_options = {}   # Optional parameters for backend
     # List of dynamic requirements:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pep517-0.5.0/dev-requirements.txt 
new/pep517-0.6.0/dev-requirements.txt
--- old/pep517-0.5.0/dev-requirements.txt       2018-12-17 18:23:15.552506700 
+0100
+++ new/pep517-0.6.0/dev-requirements.txt       2019-08-06 12:38:22.919091000 
+0200
@@ -4,3 +4,5 @@
 testpath
 pytoml
 setuptools>=30
+importlib_metadata
+zipp
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pep517-0.5.0/pep517/__init__.py 
new/pep517-0.6.0/pep517/__init__.py
--- old/pep517-0.5.0/pep517/__init__.py 2018-12-17 18:23:15.552506700 +0100
+++ new/pep517-0.6.0/pep517/__init__.py 2019-08-06 12:40:43.178316800 +0200
@@ -1,4 +1,4 @@
 """Wrappers to build Python packages using PEP 517 hooks
 """
 
-__version__ = '0.5.0'
+__version__ = '0.6.0'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pep517-0.5.0/pep517/_in_process.py 
new/pep517-0.6.0/pep517/_in_process.py
--- old/pep517-0.5.0/pep517/_in_process.py      2018-12-17 18:23:15.552506700 
+0100
+++ new/pep517-0.6.0/pep517/_in_process.py      2019-05-19 11:07:04.276072700 
+0200
@@ -2,7 +2,9 @@
 
 It expects:
 - Command line args: hook_name, control_dir
-- Environment variable: PEP517_BUILD_BACKEND=entry.point:spec
+- Environment variables:
+      PEP517_BUILD_BACKEND=entry.point:spec
+      PEP517_BACKEND_PATH=paths (separated with os.pathsep)
 - control_dir/input.json:
   - {"kwargs": {...}}
 
@@ -13,10 +15,12 @@
 from glob import glob
 from importlib import import_module
 import os
+import os.path
 from os.path import join as pjoin
 import re
 import shutil
 import sys
+import traceback
 
 # This is run as a script, not a module, so it can't do a relative import
 import compat
@@ -24,16 +28,45 @@
 
 class BackendUnavailable(Exception):
     """Raised if we cannot import the backend"""
+    def __init__(self, traceback):
+        self.traceback = traceback
+
+
+class BackendInvalid(Exception):
+    """Raised if the backend is invalid"""
+    def __init__(self, message):
+        self.message = message
+
+
+def contained_in(filename, directory):
+    """Test if a file is located within the given directory."""
+    filename = os.path.normcase(os.path.abspath(filename))
+    directory = os.path.normcase(os.path.abspath(directory))
+    return os.path.commonprefix([filename, directory]) == directory
 
 
 def _build_backend():
     """Find and load the build backend"""
+    # Add in-tree backend directories to the front of sys.path.
+    backend_path = os.environ.get('PEP517_BACKEND_PATH')
+    if backend_path:
+        extra_pathitems = backend_path.split(os.pathsep)
+        sys.path[:0] = extra_pathitems
+
     ep = os.environ['PEP517_BUILD_BACKEND']
     mod_path, _, obj_path = ep.partition(':')
     try:
         obj = import_module(mod_path)
     except ImportError:
-        raise BackendUnavailable
+        raise BackendUnavailable(traceback.format_exc())
+
+    if backend_path:
+        if not any(
+            contained_in(obj.__file__, path)
+            for path in extra_pathitems
+        ):
+            raise BackendInvalid("Backend was not loaded from backend-path")
+
     if obj_path:
         for path_part in obj_path.split('.'):
             obj = getattr(obj, path_part)
@@ -161,6 +194,8 @@
 
 class GotUnsupportedOperation(Exception):
     """For internal use when backend raises UnsupportedOperation"""
+    def __init__(self, traceback):
+        self.traceback = traceback
 
 
 def build_sdist(sdist_directory, config_settings):
@@ -169,7 +204,7 @@
     try:
         return backend.build_sdist(sdist_directory, config_settings)
     except getattr(backend, 'UnsupportedOperation', _DummyException):
-        raise GotUnsupportedOperation
+        raise GotUnsupportedOperation(traceback.format_exc())
 
 
 HOOK_NAMES = {
@@ -195,10 +230,15 @@
     json_out = {'unsupported': False, 'return_val': None}
     try:
         json_out['return_val'] = hook(**hook_input['kwargs'])
-    except BackendUnavailable:
+    except BackendUnavailable as e:
         json_out['no_backend'] = True
-    except GotUnsupportedOperation:
+        json_out['traceback'] = e.traceback
+    except BackendInvalid as e:
+        json_out['backend_invalid'] = True
+        json_out['backend_error'] = e.message
+    except GotUnsupportedOperation as e:
         json_out['unsupported'] = True
+        json_out['traceback'] = e.traceback
 
     compat.write_json(json_out, pjoin(control_dir, 'output.json'), indent=2)
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pep517-0.5.0/pep517/build.py 
new/pep517-0.6.0/pep517/build.py
--- old/pep517-0.5.0/pep517/build.py    2018-12-17 18:23:15.564506800 +0100
+++ new/pep517-0.6.0/pep517/build.py    2019-08-06 12:38:22.919091000 +0200
@@ -3,25 +3,56 @@
 import argparse
 import logging
 import os
-import contextlib
 import pytoml
 import shutil
-import errno
-import tempfile
 
 from .envbuild import BuildEnvironment
 from .wrappers import Pep517HookCaller
+from .dirtools import tempdir, mkdir_p
+from .compat import FileNotFoundError
 
 log = logging.getLogger(__name__)
 
 
[email protected]
-def tempdir():
-    td = tempfile.mkdtemp()
+def validate_system(system):
+    """
+    Ensure build system has the requisite fields.
+    """
+    required = {'requires', 'build-backend'}
+    if not (required <= set(system)):
+        message = "Missing required fields: {missing}".format(
+            missing=required-set(system),
+        )
+        raise ValueError(message)
+
+
+def load_system(source_dir):
+    """
+    Load the build system from a source dir (pyproject.toml).
+    """
+    pyproject = os.path.join(source_dir, 'pyproject.toml')
+    with open(pyproject) as f:
+        pyproject_data = pytoml.load(f)
+    return pyproject_data['build-system']
+
+
+def compat_system(source_dir):
+    """
+    Given a source dir, attempt to get a build system backend
+    and requirements from pyproject.toml. Fallback to
+    setuptools but only if the file was not found or a build
+    system was not indicated.
+    """
     try:
-        yield td
-    finally:
-        shutil.rmtree(td)
+        system = load_system(source_dir)
+    except (FileNotFoundError, KeyError):
+        system = {}
+    system.setdefault(
+        'build-backend',
+        'setuptools.build_meta:__legacy__',
+    )
+    system.setdefault('requires', ['setuptools', 'wheel'])
+    return system
 
 
 def _do_build(hooks, env, dist, dest):
@@ -42,33 +73,16 @@
         shutil.move(source, os.path.join(dest, os.path.basename(filename)))
 
 
-def mkdir_p(*args, **kwargs):
-    """Like `mkdir`, but does not raise an exception if the
-    directory already exists.
-    """
-    try:
-        return os.mkdir(*args, **kwargs)
-    except OSError as exc:
-        if exc.errno != errno.EEXIST:
-            raise
-
-
-def build(source_dir, dist, dest=None):
-    pyproject = os.path.join(source_dir, 'pyproject.toml')
+def build(source_dir, dist, dest=None, system=None):
+    system = system or load_system(source_dir)
     dest = os.path.join(source_dir, dest or 'dist')
     mkdir_p(dest)
 
-    with open(pyproject) as f:
-        pyproject_data = pytoml.load(f)
-    # Ensure the mandatory data can be loaded
-    buildsys = pyproject_data['build-system']
-    requires = buildsys['requires']
-    backend = buildsys['build-backend']
-
-    hooks = Pep517HookCaller(source_dir, backend)
+    validate_system(system)
+    hooks = Pep517HookCaller(source_dir, system['build-backend'])
 
     with BuildEnvironment() as env:
-        env.pip_install(requires)
+        env.pip_install(system['requires'])
         _do_build(hooks, env, dist, dest)
 
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pep517-0.5.0/pep517/compat.py 
new/pep517-0.6.0/pep517/compat.py
--- old/pep517-0.5.0/pep517/compat.py   2018-12-17 18:23:15.564506800 +0100
+++ new/pep517-0.6.0/pep517/compat.py   2019-08-06 12:38:22.920091000 +0200
@@ -1,7 +1,10 @@
-"""Handle reading and writing JSON in UTF-8, on Python 3 and 2."""
+"""Python 2/3 compatibility"""
 import json
 import sys
 
+
+# Handle reading and writing JSON in UTF-8, on Python 3 and 2.
+
 if sys.version_info[0] >= 3:
     # Python 3
     def write_json(obj, path, **kwargs):
@@ -21,3 +24,11 @@
     def read_json(path):
         with open(path, 'rb') as f:
             return json.load(f)
+
+
+# FileNotFoundError
+
+try:
+    FileNotFoundError = FileNotFoundError
+except NameError:
+    FileNotFoundError = IOError
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pep517-0.5.0/pep517/dirtools.py 
new/pep517-0.6.0/pep517/dirtools.py
--- old/pep517-0.5.0/pep517/dirtools.py 1970-01-01 01:00:00.000000000 +0100
+++ new/pep517-0.6.0/pep517/dirtools.py 2019-08-06 12:38:22.920091000 +0200
@@ -0,0 +1,44 @@
+import os
+import io
+import contextlib
+import tempfile
+import shutil
+import errno
+import zipfile
+
+
[email protected]
+def tempdir():
+    """Create a temporary directory in a context manager."""
+    td = tempfile.mkdtemp()
+    try:
+        yield td
+    finally:
+        shutil.rmtree(td)
+
+
+def mkdir_p(*args, **kwargs):
+    """Like `mkdir`, but does not raise an exception if the
+    directory already exists.
+    """
+    try:
+        return os.mkdir(*args, **kwargs)
+    except OSError as exc:
+        if exc.errno != errno.EEXIST:
+            raise
+
+
+def dir_to_zipfile(root):
+    """Construct an in-memory zip file for a directory."""
+    buffer = io.BytesIO()
+    zip_file = zipfile.ZipFile(buffer, 'w')
+    for root, dirs, files in os.walk(root):
+        for path in dirs:
+            fs_path = os.path.join(root, path)
+            rel_path = os.path.relpath(fs_path, root)
+            zip_file.writestr(rel_path + '/', '')
+        for path in files:
+            fs_path = os.path.join(root, path)
+            rel_path = os.path.relpath(fs_path, root)
+            zip_file.write(fs_path, rel_path)
+    return zip_file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pep517-0.5.0/pep517/envbuild.py 
new/pep517-0.6.0/pep517/envbuild.py
--- old/pep517-0.5.0/pep517/envbuild.py 2018-12-17 18:23:15.564506800 +0100
+++ new/pep517-0.6.0/pep517/envbuild.py 2019-08-06 12:38:22.920091000 +0200
@@ -10,7 +10,7 @@
 from sysconfig import get_paths
 from tempfile import mkdtemp
 
-from .wrappers import Pep517HookCaller
+from .wrappers import Pep517HookCaller, LoggerWrapper
 
 log = logging.getLogger(__name__)
 
@@ -90,9 +90,14 @@
         if not reqs:
             return
         log.info('Calling pip to install %s', reqs)
-        check_call([
+        cmd = [
             sys.executable, '-m', 'pip', 'install', '--ignore-installed',
-            '--prefix', self.path] + list(reqs))
+            '--prefix', self.path] + list(reqs)
+        check_call(
+            cmd,
+            stdout=LoggerWrapper(log, logging.INFO),
+            stderr=LoggerWrapper(log, logging.ERROR),
+        )
 
     def __exit__(self, exc_type, exc_val, exc_tb):
         needs_cleanup = (
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pep517-0.5.0/pep517/meta.py 
new/pep517-0.6.0/pep517/meta.py
--- old/pep517-0.5.0/pep517/meta.py     1970-01-01 01:00:00.000000000 +0100
+++ new/pep517-0.6.0/pep517/meta.py     2019-08-06 12:38:22.920091000 +0200
@@ -0,0 +1,90 @@
+"""Build metadata for a project using PEP 517 hooks.
+"""
+import argparse
+import logging
+import os
+import shutil
+import functools
+
+try:
+    import importlib.metadata as imp_meta
+except ImportError:
+    import importlib_metadata as imp_meta
+
+try:
+    from zipfile import Path
+except ImportError:
+    from zipp import Path
+
+from .envbuild import BuildEnvironment
+from .wrappers import Pep517HookCaller, quiet_subprocess_runner
+from .dirtools import tempdir, mkdir_p, dir_to_zipfile
+from .build import validate_system, load_system, compat_system
+
+log = logging.getLogger(__name__)
+
+
+def _prep_meta(hooks, env, dest):
+    reqs = hooks.get_requires_for_build_wheel({})
+    log.info('Got build requires: %s', reqs)
+
+    env.pip_install(reqs)
+    log.info('Installed dynamic build dependencies')
+
+    with tempdir() as td:
+        log.info('Trying to build metadata in %s', td)
+        filename = hooks.prepare_metadata_for_build_wheel(td, {})
+        source = os.path.join(td, filename)
+        shutil.move(source, os.path.join(dest, os.path.basename(filename)))
+
+
+def build(source_dir='.', dest=None, system=None):
+    system = system or load_system(source_dir)
+    dest = os.path.join(source_dir, dest or 'dist')
+    mkdir_p(dest)
+    validate_system(system)
+    hooks = Pep517HookCaller(source_dir, system['build-backend'])
+
+    with hooks.subprocess_runner(quiet_subprocess_runner):
+        with BuildEnvironment() as env:
+            env.pip_install(system['requires'])
+            _prep_meta(hooks, env, dest)
+
+
+def build_as_zip(builder=build):
+    with tempdir() as out_dir:
+        builder(dest=out_dir)
+        return dir_to_zipfile(out_dir)
+
+
+def load(root):
+    """
+    Given a source directory (root) of a package,
+    return an importlib.metadata.Distribution object
+    with metadata build from that package.
+    """
+    root = os.path.expanduser(root)
+    system = compat_system(root)
+    builder = functools.partial(build, source_dir=root, system=system)
+    path = Path(build_as_zip(builder))
+    return imp_meta.PathDistribution(path)
+
+
+parser = argparse.ArgumentParser()
+parser.add_argument(
+    'source_dir',
+    help="A directory containing pyproject.toml",
+)
+parser.add_argument(
+    '--out-dir', '-o',
+    help="Destination in which to save the builds relative to source dir",
+)
+
+
+def main():
+    args = parser.parse_args()
+    build(args.source_dir, args.out_dir)
+
+
+if __name__ == '__main__':
+    main()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pep517-0.5.0/pep517/wrappers.py 
new/pep517-0.6.0/pep517/wrappers.py
--- old/pep517-0.5.0/pep517/wrappers.py 2018-12-17 18:23:15.564506800 +0100
+++ new/pep517-0.6.0/pep517/wrappers.py 2019-08-06 12:38:22.921090800 +0200
@@ -1,8 +1,9 @@
+import threading
 from contextlib import contextmanager
 import os
 from os.path import dirname, abspath, join as pjoin
 import shutil
-from subprocess import check_call
+from subprocess import check_call, check_output, STDOUT
 import sys
 from tempfile import mkdtemp
 
@@ -22,10 +23,22 @@
 
 class BackendUnavailable(Exception):
     """Will be raised if the backend cannot be imported in the hook process."""
+    def __init__(self, traceback):
+        self.traceback = traceback
+
+
+class BackendInvalid(Exception):
+    """Will be raised if the backend is invalid."""
+    def __init__(self, backend_name, backend_path, message):
+        self.backend_name = backend_name
+        self.backend_path = backend_path
+        self.message = message
 
 
 class UnsupportedOperation(Exception):
     """May be raised by build_sdist if the backend indicates that it can't."""
+    def __init__(self, traceback):
+        self.traceback = traceback
 
 
 def default_subprocess_runner(cmd, cwd=None, extra_environ=None):
@@ -37,16 +50,65 @@
     check_call(cmd, cwd=cwd, env=env)
 
 
+def quiet_subprocess_runner(cmd, cwd=None, extra_environ=None):
+    """A method of calling the wrapper subprocess while suppressing output."""
+    env = os.environ.copy()
+    if extra_environ:
+        env.update(extra_environ)
+
+    check_output(cmd, cwd=cwd, env=env, stderr=STDOUT)
+
+
+def norm_and_check(source_tree, requested):
+    """Normalise and check a backend path.
+
+    Ensure that the requested backend path is specified as a relative path,
+    and resolves to a location under the given source tree.
+
+    Return an absolute version of the requested path.
+    """
+    if os.path.isabs(requested):
+        raise ValueError("paths must be relative")
+
+    abs_source = os.path.abspath(source_tree)
+    abs_requested = os.path.normpath(os.path.join(abs_source, requested))
+    # We have to use commonprefix for Python 2.7 compatibility. So we
+    # normalise case to avoid problems because commonprefix is a character
+    # based comparison :-(
+    norm_source = os.path.normcase(abs_source)
+    norm_requested = os.path.normcase(abs_requested)
+    if os.path.commonprefix([norm_source, norm_requested]) != norm_source:
+        raise ValueError("paths must be inside source tree")
+
+    return abs_requested
+
+
 class Pep517HookCaller(object):
     """A wrapper around a source directory to be built with a PEP 517 backend.
 
     source_dir : The path to the source directory, containing pyproject.toml.
     backend : The build backend spec, as per PEP 517, from pyproject.toml.
+    backend_path : The backend path, as per PEP 517, from pyproject.toml.
+    runner : A callable that invokes the wrapper subprocess.
     """
-    def __init__(self, source_dir, build_backend):
+    def __init__(
+            self,
+            source_dir,
+            build_backend,
+            backend_path=None,
+            runner=None,
+    ):
+        if runner is None:
+            runner = default_subprocess_runner
+
         self.source_dir = abspath(source_dir)
         self.build_backend = build_backend
-        self._subprocess_runner = default_subprocess_runner
+        if backend_path:
+            backend_path = [
+                norm_and_check(self.source_dir, p) for p in backend_path
+            ]
+        self.backend_path = backend_path
+        self._subprocess_runner = runner
 
     # TODO: Is this over-engineered? Maybe frontends only need to
     #       set this when creating the wrapper, not on every call.
@@ -139,25 +201,74 @@
         # letters, digits and _, . and : characters, and will be used as a
         # Python identifier, so non-ASCII content is wrong on Python 2 in
         # any case).
+        # For backend_path, we use sys.getfilesystemencoding.
         if sys.version_info[0] == 2:
             build_backend = self.build_backend.encode('ASCII')
         else:
             build_backend = self.build_backend
+        extra_environ = {'PEP517_BUILD_BACKEND': build_backend}
+
+        if self.backend_path:
+            backend_path = os.pathsep.join(self.backend_path)
+            if sys.version_info[0] == 2:
+                backend_path = backend_path.encode(sys.getfilesystemencoding())
+            extra_environ['PEP517_BACKEND_PATH'] = backend_path
 
         with tempdir() as td:
-            compat.write_json({'kwargs': kwargs}, pjoin(td, 'input.json'),
+            hook_input = {'kwargs': kwargs}
+            compat.write_json(hook_input, pjoin(td, 'input.json'),
                               indent=2)
 
             # Run the hook in a subprocess
             self._subprocess_runner(
                 [sys.executable, _in_proc_script, hook_name, td],
                 cwd=self.source_dir,
-                extra_environ={'PEP517_BUILD_BACKEND': build_backend}
+                extra_environ=extra_environ
             )
 
             data = compat.read_json(pjoin(td, 'output.json'))
             if data.get('unsupported'):
-                raise UnsupportedOperation
+                raise UnsupportedOperation(data.get('traceback', ''))
             if data.get('no_backend'):
-                raise BackendUnavailable
+                raise BackendUnavailable(data.get('traceback', ''))
+            if data.get('backend_invalid'):
+                raise BackendInvalid(
+                    backend_name=self.build_backend,
+                    backend_path=self.backend_path,
+                    message=data.get('backend_error', '')
+                )
             return data['return_val']
+
+
+class LoggerWrapper(threading.Thread):
+    """
+    Read messages from a pipe and redirect them
+    to a logger (see python's logging module).
+    """
+
+    def __init__(self, logger, level):
+        threading.Thread.__init__(self)
+        self.daemon = True
+
+        self.logger = logger
+        self.level = level
+
+        # create the pipe and reader
+        self.fd_read, self.fd_write = os.pipe()
+        self.reader = os.fdopen(self.fd_read)
+
+        self.start()
+
+    def fileno(self):
+        return self.fd_write
+
+    @staticmethod
+    def remove_newline(msg):
+        return msg[:-1] if msg.endswith(os.linesep) else msg
+
+    def run(self):
+        for line in self.reader:
+            self._write(self.remove_newline(line))
+
+    def _write(self, message):
+        self.logger.log(self.level, message)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pep517-0.5.0/pyproject.toml 
new/pep517-0.6.0/pyproject.toml
--- old/pep517-0.5.0/pyproject.toml     2018-12-17 18:23:15.564506800 +0100
+++ new/pep517-0.6.0/pyproject.toml     2019-08-06 12:38:22.921090800 +0200
@@ -10,6 +10,8 @@
 description-file = "README.rst"
 requires = [
     "pytoml",
+    "importlib_metadata",
+    "zipp",
 ]
 classifiers = ["License :: OSI Approved :: MIT License"]
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pep517-0.5.0/setup.py new/pep517-0.6.0/setup.py
--- old/pep517-0.5.0/setup.py   1970-01-01 01:00:00.000000000 +0100
+++ new/pep517-0.6.0/setup.py   1970-01-01 01:00:00.000000000 +0100
@@ -10,10 +10,10 @@
 {'': ['*']}
 
 install_requires = \
-['pytoml']
+['pytoml', 'importlib_metadata', 'zipp']
 
 setup(name='pep517',
-      version='0.5.0',
+      version='0.6.0',
       description='Wrappers to build Python packages using PEP 517 hooks',
       author='Thomas Kluyver',
       author_email='[email protected]',
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/pep517-0.5.0/tests/samples/pkg_intree/backend/intree_backend.py 
new/pep517-0.6.0/tests/samples/pkg_intree/backend/intree_backend.py
--- old/pep517-0.5.0/tests/samples/pkg_intree/backend/intree_backend.py 
1970-01-01 01:00:00.000000000 +0100
+++ new/pep517-0.6.0/tests/samples/pkg_intree/backend/intree_backend.py 
2019-05-19 11:07:04.276072700 +0200
@@ -0,0 +1,2 @@
+def get_requires_for_build_sdist(config_settings):
+    return ["intree_backend_called"]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pep517-0.5.0/tests/samples/pkg_intree/pyproject.toml 
new/pep517-0.6.0/tests/samples/pkg_intree/pyproject.toml
--- old/pep517-0.5.0/tests/samples/pkg_intree/pyproject.toml    1970-01-01 
01:00:00.000000000 +0100
+++ new/pep517-0.6.0/tests/samples/pkg_intree/pyproject.toml    2019-05-19 
11:07:04.277072700 +0200
@@ -0,0 +1,3 @@
+[build-system]
+build-backend = 'intree_backend'
+backend-path = ['backend']
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pep517-0.5.0/tests/test_build.py 
new/pep517-0.6.0/tests/test_build.py
--- old/pep517-0.5.0/tests/test_build.py        1970-01-01 01:00:00.000000000 
+0100
+++ new/pep517-0.6.0/tests/test_build.py        2019-08-06 12:38:22.921090800 
+0200
@@ -0,0 +1,27 @@
+import pytest
+
+from pep517 import build
+
+
+def system(*args):
+    return dict.fromkeys(args)
+
+
+class TestValidateSystem:
+    def test_missing(self):
+        with pytest.raises(ValueError):
+            build.validate_system(system())
+        with pytest.raises(ValueError):
+            build.validate_system(system('requires'))
+        with pytest.raises(ValueError):
+            build.validate_system(system('build-backend'))
+        with pytest.raises(ValueError):
+            build.validate_system(system('other'))
+
+    def test_missing_and_extra(self):
+        with pytest.raises(ValueError):
+            build.validate_system(system('build-backend', 'other'))
+
+    def test_satisfied(self):
+        build.validate_system(system('build-backend', 'requires'))
+        build.validate_system(system('build-backend', 'requires', 'other'))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pep517-0.5.0/tests/test_inplace_hooks.py 
new/pep517-0.6.0/tests/test_inplace_hooks.py
--- old/pep517-0.5.0/tests/test_inplace_hooks.py        1970-01-01 
01:00:00.000000000 +0100
+++ new/pep517-0.6.0/tests/test_inplace_hooks.py        2019-05-19 
11:07:04.277072700 +0200
@@ -0,0 +1,49 @@
+from os.path import dirname, abspath, join as pjoin
+import pytoml
+from testpath import modified_env
+import pytest
+
+from pep517.wrappers import Pep517HookCaller, BackendInvalid
+
+SAMPLES_DIR = pjoin(dirname(abspath(__file__)), 'samples')
+BUILDSYS_PKGS = pjoin(SAMPLES_DIR, 'buildsys_pkgs')
+
+
+def get_hooks(pkg, backend=None, path=None):
+    source_dir = pjoin(SAMPLES_DIR, pkg)
+    with open(pjoin(source_dir, 'pyproject.toml')) as f:
+        data = pytoml.load(f)
+    if backend is None:
+        backend = data['build-system']['build-backend']
+    if path is None:
+        path = data['build-system']['backend-path']
+    return Pep517HookCaller(source_dir, backend, path)
+
+
+def test_backend_path_within_tree():
+    source_dir = pjoin(SAMPLES_DIR, 'pkg1')
+    assert Pep517HookCaller(source_dir, 'dummy', ['.', 'subdir'])
+    assert Pep517HookCaller(source_dir, 'dummy', ['../pkg1', 'subdir/..'])
+    # TODO: Do we want to insist on ValueError, or invent another exception?
+    with pytest.raises(Exception):
+        assert Pep517HookCaller(source_dir, 'dummy', [source_dir])
+    with pytest.raises(Exception):
+        Pep517HookCaller(source_dir, 'dummy', ['.', '..'])
+    with pytest.raises(Exception):
+        Pep517HookCaller(source_dir, 'dummy', ['subdir/../..'])
+    with pytest.raises(Exception):
+        Pep517HookCaller(source_dir, 'dummy', ['/'])
+
+
+def test_intree_backend():
+    hooks = get_hooks('pkg_intree')
+    with modified_env({'PYTHONPATH': BUILDSYS_PKGS}):
+        res = hooks.get_requires_for_build_sdist({})
+    assert res == ["intree_backend_called"]
+
+
+def test_intree_backend_not_in_path():
+    hooks = get_hooks('pkg_intree', backend='buildsys')
+    with modified_env({'PYTHONPATH': BUILDSYS_PKGS}):
+        with pytest.raises(BackendInvalid):
+            hooks.get_requires_for_build_sdist({})
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pep517-0.5.0/tests/test_meta.py 
new/pep517-0.6.0/tests/test_meta.py
--- old/pep517-0.5.0/tests/test_meta.py 1970-01-01 01:00:00.000000000 +0100
+++ new/pep517-0.6.0/tests/test_meta.py 2019-08-06 12:38:22.922091000 +0200
@@ -0,0 +1,38 @@
+from __future__ import unicode_literals, absolute_import, division
+
+import re
+
+import pytest
+
+from pep517 import meta
+
+
+pep517_needs_python_3 = pytest.mark.xfail(
+    'sys.version_info < (3,)',
+    reason="pep517 cannot be built on Python 2",
+)
+
+
+@pep517_needs_python_3
+def test_meta_for_this_package():
+    dist = meta.load('.')
+    assert re.match(r'[\d.]+', dist.version)
+    assert dist.metadata['Name'] == 'pep517'
+
+
+def test_classic_package(tmpdir):
+    (tmpdir / 'setup.py').write_text(
+        'from distutils.core import setup; setup(name="foo", version="1.0")',
+        encoding='utf-8',
+    )
+    dist = meta.load(str(tmpdir))
+    assert dist.version == '1.0'
+    assert dist.metadata['Name'] == 'foo'
+
+
+@pep517_needs_python_3
+def test_meta_output(capfd):
+    """load shouldn't emit any output"""
+    meta.load('.')
+    captured = capfd.readouterr()
+    assert captured.out == captured.err == ''


Reply via email to