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
10 changes: 9 additions & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ project_urls =
packages = find:
install_requires =
packaging
pep517
pep517>=0.9.1
toml
importlib-metadata;python_version < "3.8"
typing;python_version<"3"
Expand All @@ -50,6 +50,9 @@ test =
pytest
pytest-cov
pytest-mock
typing =
mypy==0.790
typing-extensions>=3.7.4.3

[options.packages.find]
where = src
Expand Down Expand Up @@ -78,6 +81,11 @@ omit =
*bin/pyproject-build
*bin\pyproject-build.exe

[coverage:report]
exclude_lines =
\#\s*pragma: no cover
Copy link
Member

Choose a reason for hiding this comment

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

Why?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Here, the core goal is to add raise NotImplementedError to be automatically marked with no coverage needed for them (because the metaclass makes it impossible to hit it). By default, coverage only excludes pragma no cover lines, so we want to extend that. There's no extend the exclude method, though, override of the exclude lines matcher, so we need to set it again.

^\s*raise NotImplementedError\b

[coverage:paths]
source =
src
Expand Down
16 changes: 11 additions & 5 deletions src/build/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,12 @@
import os
import sys
import warnings

from typing import Dict, Iterator, List, Mapping, Optional, Set, Union

import pep517.wrappers
import toml
import toml.decoder


if sys.version_info < (3,):
FileNotFoundError = IOError
PermissionError = OSError
Expand Down Expand Up @@ -118,9 +116,14 @@ def _working_directory(path): # type: (str) -> Iterator[None]


class ProjectBuilder(object):
def __init__(self, srcdir='.', config_settings=None): # type: (str, Optional[ConfigSettings]) -> None
def __init__(self, srcdir='.', config_settings=None, python_executable=sys.executable):
# type: (str, Optional[ConfigSettings], str) -> None
"""
:param srcdir: Source directory
Create a project builder.

:param srcdir: the source directory
: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 {}
Expand Down Expand Up @@ -152,7 +155,10 @@ def __init__(self, srcdir='.', config_settings=None): # type: (str, Optional[Co
self._backend = self._build_system['build-backend']

self.hook = pep517.wrappers.Pep517HookCaller(
self.srcdir, self._backend, backend_path=self._build_system.get('backend-path')
self.srcdir,
self._backend,
backend_path=self._build_system.get('backend-path'),
python_executable=python_executable,
)

@property
Expand Down
10 changes: 5 additions & 5 deletions src/build/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@
from typing import List, Optional, TextIO, Type, Union

from build import BuildBackendException, BuildException, ConfigSettings, ProjectBuilder
from build.env import IsolatedEnvironment

from build.env import IsolatedEnvBuilder

__all__ = ['build', 'main', 'main_parser']

Expand Down Expand Up @@ -40,8 +39,10 @@ def _error(msg, code=1): # type: (str, int) -> None # pragma: no cover
exit(code)


def _build_in_isolated_env(builder, outdir, distributions): # type: (ProjectBuilder, str, List[str]) -> None
with IsolatedEnvironment.for_current() as env:
def _build_in_isolated_env(builder, outdir, distributions):
# type: (ProjectBuilder, str, List[str]) -> None
with IsolatedEnvBuilder() as env:
builder.hook.python_executable = env.executable
env.install(builder.build_dependencies)
for distribution in distributions:
builder.build(distribution, outdir)
Expand Down Expand Up @@ -75,7 +76,6 @@ def build(srcdir, outdir, distributions, config_settings=None, isolation=True, s

try:
builder = ProjectBuilder(srcdir, config_settings)

if isolation:
_build_in_isolated_env(builder, outdir, distributions)
else:
Expand Down
42 changes: 42 additions & 0 deletions src/build/_compat.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import abc
import sys
from typing import Callable, TypeVar

_T = TypeVar('_T')


def add_metaclass(metaclass): # type: (type) -> Callable[[_T], _T]
"""Class decorator for creating a class with a metaclass (borrowed from six code)."""

def wrapper(cls): # type: (_T) -> _T
orig_vars = cls.__dict__.copy()
slots = orig_vars.get('__slots__')
if slots is not None:
if isinstance(slots, str): # pragma: no cover
slots = [slots] # pragma: no cover
for slots_var in slots: # pragma: no cover
orig_vars.pop(slots_var) # pragma: no cover
orig_vars.pop('__dict__', None)
orig_vars.pop('__weakref__', None)
if hasattr(cls, '__qualname__'):
orig_vars['__qualname__'] = cls.__qualname__ # type: ignore
return metaclass(cls.__name__, cls.__bases__, orig_vars) # type: ignore

return wrapper


if sys.version_info[0] == 2:
abstractproperty = abc.abstractproperty
else:
from typing import Any, cast

F = TypeVar('F', bound=Callable[..., Any])

def abstractproperty(func): # type: (F) -> F
return cast(F, property(abc.abstractmethod(func)))


__all__ = (
'abstractproperty',
'add_metaclass',
)
Loading