Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Accept os.PathLike in addition to str for paths in public API #392

Merged
merged 14 commits into from Oct 27, 2021
6 changes: 6 additions & 0 deletions CHANGELOG.rst
Expand Up @@ -6,6 +6,12 @@ Changelog
Unreleased
==========

- Accept `os.PathLike[str]` in addition to str for paths in public API
and rename `output_directory` to `outdir` (`PR #392`_, Fixes `#372`_)

.. _PR #392: https://github.com/pypa/build/pull/TODO
.. _#372: https://github.com/pypa/build/issues/372
Copy link
Member

Choose a reason for hiding this comment

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

Put this below, see the other release sections for an example.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

updated in bf3faf7


- Add schema validation for ``build-system`` table to check conformity
with PEP 517 and PEP 518 (`PR #365`_, Fixes `#364`_)

Expand Down
31 changes: 16 additions & 15 deletions src/build/__init__.py
Expand Up @@ -50,6 +50,7 @@

RunnerType = Callable[[Sequence[str], Optional[str], Optional[Mapping[str, str]]], None]
ConfigSettingsType = Mapping[str, Union[str, Sequence[str]]]
PathType = Union[str, 'os.PathLike[str]']
Copy link
Member

Choose a reason for hiding this comment

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

Do from __future__ import annotations instead.

Copy link
Contributor

Choose a reason for hiding this comment

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

Python 3.6 hasn't hit EoL.

Besides, they are talking about deprecating that in 3.11 and removing it in 3.13. 😠

Copy link
Member

Choose a reason for hiding this comment

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

Ah 😕

Yeah, it will likely be replaced by co_annotations, but I haven't been following the progress closely.

Copy link
Member

Choose a reason for hiding this comment

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

We might have to do a version check here actually.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think it's safe to do a string inside this, it'll be a ForwardRef. Also, from __future__ import annotations wouldn't work here, this is not an annotation.

https://discuss.python.org/t/type-annotations-pep-649-and-pep-563/11363 for the annotation discussion.

_ExcInfoType = Union[Tuple[Type[BaseException], BaseException, types.TracebackType], Tuple[None, None, None]]


Expand Down Expand Up @@ -121,7 +122,7 @@ def _working_directory(path: str) -> Iterator[None]:
os.chdir(current)


def _validate_source_directory(srcdir: str) -> None:
def _validate_source_directory(srcdir: PathType) -> None:
if not os.path.isdir(srcdir):
raise BuildException(f'Source {srcdir} is not a directory')
pyproject_toml = os.path.join(srcdir, 'pyproject.toml')
Expand Down Expand Up @@ -228,7 +229,7 @@ class ProjectBuilder:

def __init__(
self,
srcdir: str,
srcdir: PathType,
python_executable: str = sys.executable,
scripts_dir: Optional[str] = None,
runner: RunnerType = pep517.wrappers.default_subprocess_runner,
Expand Down Expand Up @@ -356,21 +357,21 @@ def check_dependencies(
return {u for d in dependencies for u in check_dependency(d)}

def prepare(
self, distribution: str, output_directory: str, config_settings: Optional[ConfigSettingsType] = None
self, distribution: str, outdir: PathType, config_settings: Optional[ConfigSettingsType] = None
FFY00 marked this conversation as resolved.
Show resolved Hide resolved
) -> Optional[str]:
"""
Prepare metadata for a distribution.

:param distribution: Distribution to build (must be ``wheel``)
:param output_directory: Directory to put the prepared metadata in
:param outdir: Directory to put the prepared metadata in
:param config_settings: Config settings for the build backend
:returns: The full path to the prepared metadata directory
"""
self.log(f'Getting metadata for {distribution}...')
try:
return self._call_backend(
f'prepare_metadata_for_build_{distribution}',
output_directory,
outdir,
config_settings,
_allow_fallback=False,
)
Expand All @@ -382,54 +383,54 @@ def prepare(
def build(
self,
distribution: str,
output_directory: str,
outdir: PathType,
config_settings: Optional[ConfigSettingsType] = None,
metadata_directory: Optional[str] = None,
) -> str:
"""
Build a distribution.

:param distribution: Distribution to build (``sdist`` or ``wheel``)
:param output_directory: Directory to put the built distribution in
:param outdir: Directory to put the built distribution in
:param config_settings: Config settings for the build backend
:param metadata_directory: If provided, should be the return value of a
previous ``prepare`` call on the same ``distribution`` kind
:returns: The full path to the built distribution
"""
self.log(f'Building {distribution}...')
kwargs = {} if metadata_directory is None else {'metadata_directory': metadata_directory}
return self._call_backend(f'build_{distribution}', output_directory, config_settings, **kwargs)
return self._call_backend(f'build_{distribution}', outdir, config_settings, **kwargs)

def metadata_path(self, output_directory: str) -> str:
def metadata_path(self, outdir: PathType) -> str:
"""
Generates the metadata directory of a distribution and returns its path.

If the backend does not support the ``prepare_metadata_for_build_wheel``
hook, a wheel will be built and the metadata extracted.

:param output_directory: Directory to put the metadata distribution in
:param outdir: Directory to put the metadata distribution in
"""
# prepare_metadata hook
metadata = self.prepare('wheel', output_directory)
metadata = self.prepare('wheel', outdir)
if metadata is not None:
return metadata

# fallback to build_wheel hook
wheel = self.build('wheel', output_directory)
wheel = self.build('wheel', outdir)
match = _WHEEL_NAME_REGEX.match(os.path.basename(wheel))
if not match:
raise ValueError('Invalid wheel')
distinfo = f"{match['distribution']}-{match['version']}.dist-info"
member_prefix = f'{distinfo}/'
with zipfile.ZipFile(wheel) as w:
w.extractall(
output_directory,
outdir,
(member for member in w.namelist() if member.startswith(member_prefix)),
)
return os.path.join(output_directory, distinfo)
return os.path.join(outdir, distinfo)

def _call_backend(
self, hook_name: str, outdir: str, config_settings: Optional[ConfigSettingsType] = None, **kwargs: Any
self, hook_name: str, outdir: PathType, config_settings: Optional[ConfigSettingsType] = None, **kwargs: Any
) -> str:
outdir = os.path.abspath(outdir)

Expand Down
16 changes: 8 additions & 8 deletions src/build/__main__.py
Expand Up @@ -17,7 +17,7 @@

import build

from build import BuildBackendException, BuildException, ConfigSettingsType, ProjectBuilder
from build import BuildBackendException, BuildException, ConfigSettingsType, PathType, ProjectBuilder
from build.env import IsolatedEnvBuilder


Expand Down Expand Up @@ -99,7 +99,7 @@ def _format_dep_chain(dep_chain: Sequence[str]) -> str:


def _build_in_isolated_env(
builder: ProjectBuilder, outdir: str, distribution: str, config_settings: Optional[ConfigSettingsType]
builder: ProjectBuilder, outdir: PathType, distribution: str, config_settings: Optional[ConfigSettingsType]
) -> str:
with _IsolatedEnvBuilder() as env:
builder.python_executable = env.executable
Expand All @@ -113,7 +113,7 @@ def _build_in_isolated_env(

def _build_in_current_env(
builder: ProjectBuilder,
outdir: str,
outdir: PathType,
distribution: str,
config_settings: Optional[ConfigSettingsType],
skip_dependency_check: bool = False,
Expand All @@ -131,7 +131,7 @@ def _build_in_current_env(
def _build(
isolation: bool,
builder: ProjectBuilder,
outdir: str,
outdir: PathType,
distribution: str,
config_settings: Optional[ConfigSettingsType],
skip_dependency_check: bool,
Expand Down Expand Up @@ -179,8 +179,8 @@ def _natural_language_list(elements: Sequence[str]) -> str:


def build_package(
srcdir: str,
outdir: str,
srcdir: PathType,
outdir: PathType,
distributions: Sequence[str],
config_settings: Optional[ConfigSettingsType] = None,
isolation: bool = True,
Expand All @@ -205,8 +205,8 @@ def build_package(


def build_package_via_sdist(
srcdir: str,
outdir: str,
srcdir: PathType,
outdir: PathType,
distributions: Sequence[str],
config_settings: Optional[ConfigSettingsType] = None,
isolation: bool = True,
Expand Down
4 changes: 1 addition & 3 deletions src/build/util.py
Expand Up @@ -5,8 +5,6 @@
import sys
import tempfile

from typing import Union

import pep517

import build
Expand All @@ -27,7 +25,7 @@ def _project_wheel_metadata(builder: build.ProjectBuilder) -> 'importlib_metadat


def project_wheel_metadata(
srcdir: Union[str, 'os.PathLike[str]'],
srcdir: build.PathType,
isolated: bool = True,
) -> 'importlib_metadata.PackageMetadata':
"""
Expand Down