Skip to content

Commit

Permalink
feat: rename the is_enabled hook to pdm_build_hook_enabled
Browse files Browse the repository at this point in the history
  • Loading branch information
frostming committed Nov 30, 2022
1 parent 67db615 commit 4729bd1
Show file tree
Hide file tree
Showing 8 changed files with 59 additions and 37 deletions.
6 changes: 3 additions & 3 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ repos:
hooks:
- id: black
- repo: https://github.com/PyCQA/flake8
rev: 5.0.4
rev: 6.0.0
hooks:
- id: flake8
additional_dependencies:
Expand All @@ -21,13 +21,13 @@ repos:
exclude: ^.*/?setup\.py$

- repo: https://github.com/pre-commit/mirrors-mypy
rev: v0.982
rev: v0.991
hooks:
- id: mypy
exclude: ^(src/pdm/backend/_vendor|tests|scripts)

- repo: https://github.com/asottile/pyupgrade
rev: v3.2.0
rev: v3.2.3
hooks:
- id: pyupgrade
args:
Expand Down
2 changes: 1 addition & 1 deletion docs/build_config.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ Some build frontends such as [build] and [pdm] supports passing options from com
- `--python-tag=<tag>` Override the python implementation compatibility tag(e.g. `cp37`, `py3`, `pp3`)
- `--py-limited-api=<abi>` Python tag (`cp32`|`cp33`|`cpNN`) for abi3 wheel tag
- `--plat-name=<plat>` Override the platform name(e.g. `win_amd64`, `manylinux2010_x86_64`)
- `no-clean` Don't clean the build directory before the build starts
- `no-clean-build` Don't clean the build directory before the build starts, this can also work by setting env var `PDM_BUILD_NO_CLEAN` to `1`.

For example, you can supply these options with [build]:

Expand Down
25 changes: 20 additions & 5 deletions docs/hooks.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,18 +70,33 @@ Or, you can generate it anywhere and include the path explicitly.

## Enable the hook for a specific build target

Sometimes you only want to activate the hook for a specific hook, you can define the `is_enabled()` hook:
Sometimes you only want to activate the hook for a specific hook, you can define the `pdm_build_hook_enabled()` hook:

=== "pdm_build.py"

```python
def is_enabled(context):
def pdm_build_hook_enabled(context):
# Only enable for sdist builds
return context.target == "sdist"
```

You can also look at the `context` object inside a specific hook to determine it should be called.


## Build hooks flow

The hooks are called in the following order:

```mermaid
flowchart TD
A{{pdm_build_hook_enabled?}}-->pdm_build_initialize
pdm_build_initialize-.run-setuptools.-> pdm_build_update_setup_kwargs
pdm_build_update_setup_kwargs-.->pdm_build_update_files
pdm_build_update_files --> pdm_build_finalize
```

Read the [API references](./api.md) for more details.

## Distribute the hook as a plugin

If you want to share your hook with others, you can change the hook script file into a Python package and upload it to PyPI.
Expand Down Expand Up @@ -119,12 +134,12 @@ pdm-build-mypyc

```python
class MypycBuildHook:
def pdm_build_hook_enabled(self, context):
return context.target == "wheel"

def pdm_build_initialize(self, context):
context.ensure_build_dir()
mypyc_build(context.build_dir)

def is_enabled(self, context):
return context.target == "wheel"
```


Expand Down
2 changes: 1 addition & 1 deletion src/pdm/backend/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from pathlib import Path
from typing import Any, Mapping

__version__ = "2.0.0a2"
__version__ = "2.0.0a3"


def get_requires_for_build_wheel(
Expand Down
9 changes: 6 additions & 3 deletions src/pdm/backend/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,8 +126,8 @@ def call_hook(
) -> None:
"""Call the hook on all registered hooks and skip if not implemented."""
for hook in self._hooks:
if hasattr(hook, "is_enabled"):
if not hook.is_enabled(context):
if hasattr(hook, "pdm_build_hook_enabled"):
if not hook.pdm_build_hook_enabled(context):
continue
if hasattr(hook, hook_name):
getattr(hook, hook_name)(context, *args, **kwargs)
Expand Down Expand Up @@ -182,7 +182,10 @@ def finalize(self, context: Context, artifact: Path) -> None:
def build(self, build_dir: str, **kwargs: Any) -> Path:
"""Build the package and return the path to the artifact."""
context = self.build_context(Path(build_dir), **kwargs)
if not self.config_settings.get("no-clean"):
if (
not self.config_settings.get("no-clean-build")
or os.getenv("PDM_BUILD_NO_CLEAN", "false").lower() != "false"
):
self.clean(context)
self.initialize(context)
files = self.get_files(context)
Expand Down
5 changes: 3 additions & 2 deletions src/pdm/backend/hooks/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ class BuildHookInterface(Protocol):
Custom hooks can implement part of the methods to provide corresponding abilities.
"""

def is_enabled(self, context: Context) -> bool:
def pdm_build_hook_enabled(self, context: Context) -> bool:
"""Return True if the hook is enabled for the current build and context
Parameters:
Expand Down Expand Up @@ -107,6 +107,7 @@ def pdm_build_update_setup_kwargs(
kwargs: The arguments to be passed to the setup() function
Note:
This hook will be called in the subprocess of running setup.py
This hook will be called in the subprocess of running setup.py.
Any changes made to the context won't be written back.
"""
...
2 changes: 1 addition & 1 deletion src/pdm/backend/hooks/setuptools.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ def _format_dict_list(data: dict[str, list[str]], indent: int = 4) -> str:
class SetuptoolsBuildHook:
"""A build hook to run setuptools build command."""

def is_enabled(self, context: Context) -> bool:
def pdm_build_hook_enabled(self, context: Context) -> bool:
return context.target != "sdist" and context.config.build_config.run_setuptools

def pdm_build_update_files(self, context: Context, files: dict[str, Path]) -> None:
Expand Down
45 changes: 24 additions & 21 deletions src/pdm/backend/wheel.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
import zipfile
from base64 import urlsafe_b64encode
from pathlib import Path
from typing import IO, Any, Iterable, Mapping, NamedTuple
from typing import IO, Any, Iterable, Mapping, NamedTuple, cast

from pdm.backend import __version__
from pdm.backend._vendor.packaging import tags
Expand Down Expand Up @@ -39,7 +39,7 @@
% __version__
)

PY_LIMITED_API_PATTERN = r"cp3\d"
PY_LIMITED_API_PATTERN = r"cp3\d{1,2}"
# Fix the date time for reproducible builds
ZIPINFO_DEFAULT_DATE_TIME = (2016, 1, 1, 0, 0, 0)

Expand All @@ -60,29 +60,28 @@ class WheelBuilder(Builder):
hooks = Builder.hooks + [SetuptoolsBuildHook()]

def __init__(
self,
location: str | Path,
config_settings: Mapping[str, Any] | None = None,
self, location: str | Path, config_settings: Mapping[str, Any] | None = None
) -> None:
super().__init__(location, config_settings)
self._parse_config_settings()
self.__tag: str | None = None

def _parse_config_settings(self) -> None:
self.python_tag = None
self.py_limited_api = None
self.plat_name = None
def _get_platform_tags(self) -> tuple[str | None, str | None, str | None]:
python_tag: str | None = None
py_limited_api: str | None = None
plat_name: str | None = None
if not self.config_settings:
return
return python_tag, py_limited_api, plat_name
if "--python-tag" in self.config_settings:
self.python_tag = self.config_settings["--python-tag"]
python_tag = self.config_settings["--python-tag"]
if "--py-limited-api" in self.config_settings:
self.py_limited_api = self.config_settings["--py-limited-api"]
if not re.match(PY_LIMITED_API_PATTERN, self.py_limited_api):
py_limited_api = cast(str, self.config_settings["--py-limited-api"])
if not re.match(PY_LIMITED_API_PATTERN, py_limited_api):
raise ValueError(
"py-limited-api must match '%s'" % PY_LIMITED_API_PATTERN
)
if "--plat-name" in self.config_settings:
self.plat_name = self.config_settings["--plat-name"]
plat_name = self.config_settings["--plat-name"]
return python_tag, py_limited_api, plat_name

def prepare_metadata(self, metadata_directory: str) -> Path:
"""Write the dist-info files under the given directory"""
Expand Down Expand Up @@ -154,16 +153,20 @@ def dist_info_name(self) -> str:

@property
def tag(self) -> str:
platform = self.plat_name
impl = self.python_tag
if self.__tag is None:
self.__tag = self._get_tag()
return self.__tag

def _get_tag(self) -> str:
impl, abi, platform = self._get_platform_tags()
is_purelib = self.config.build_config.is_purelib
if not is_purelib:
if not platform:
platform = get_platform(self.location / "build")
if not impl:
impl = tags.interpreter_name() + tags.interpreter_version()
if self.py_limited_api and impl.startswith("cp3"):
impl = self.py_limited_api
if abi and impl.startswith("cp3"): # type: ignore[union-attr]
impl = abi
abi_tag = "abi3"
else:
abi_tag = str(get_abi_tag()).lower()
Expand All @@ -178,14 +181,14 @@ def tag(self) -> str:
else:
impl = "py3"

platform = platform.lower().replace("-", "_").replace(".", "_")
platform = platform.lower().replace("-", "_").replace(".", "_") # type: ignore
tag = (impl, abi_tag, platform)
if not is_purelib:
supported_tags = [(t.interpreter, t.abi, platform) for t in tags.sys_tags()]
assert (
tag in supported_tags
), f"would build wheel with unsupported tag {tag}"
return "-".join(tag)
return "-".join(tag) # type: ignore[arg-type]

def _write_dist_info(self, parent: Path) -> Path:
"""write the dist-info directory and return the path to it"""
Expand Down

0 comments on commit 4729bd1

Please sign in to comment.