Skip to content

Commit

Permalink
Merge pull request #3 from blink1073/moar-tests
Browse files Browse the repository at this point in the history
  • Loading branch information
blink1073 committed May 14, 2022
2 parents 57fa834 + 5af70de commit acf4d62
Show file tree
Hide file tree
Showing 13 changed files with 466 additions and 44 deletions.
13 changes: 13 additions & 0 deletions .github/workflows/enforce-label.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
name: Enforce PR label

on:
pull_request:
types: [labeled, unlabeled, opened, edited, synchronize]
jobs:
enforce-label:
runs-on: ubuntu-latest
permissions:
pull-requests: write
steps:
- name: enforce-triage-label
uses: jupyterlab/maintainer-tools/.github/actions/enforce-label@v1
35 changes: 31 additions & 4 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ on:
push:
branches: [main]
pull_request:
branches: [main]
schedule:
# Run weekly
# * is a special character in YAML so you have to quote this string
Expand All @@ -14,17 +13,25 @@ jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: [3.7, 3.8, 3.9, "3.10"]
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
python-version: ["3.7", "3.10"]
include:
- os: windows-latest
python-version: "3.9"
- os: ubuntu-latest
python-version: "pypy-3.8"
- os: macos-latest
python-version: "3.8"

steps:
- uses: actions/checkout@v2
- uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1
- name: Install dependencies
run: pip install -e ".[test]"
- name: Run tests
run: pytest
run: python -m pytest -vv --cov hatch_jupyter_builder --cov-branch --cov-report term-missing:skip-covered --cov-fail-under 90

pre-commit:
name: pre-commit
Expand All @@ -46,6 +53,26 @@ jobs:
echo "or after-the-fact on already committed files with"
echo " pre-commit run --all-files --hook-stage=manual"
test_prereleases:
name: Test Prereleases
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Base Setup
uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1
- name: Install the Python dependencies
run: |
pip install --no-deps -e .
pip install --pre --upgrade "hatch_jupyter_builder[test]"
- name: List installed packages
run: |
pip freeze
pip check
- name: Run the tests
run: pytest -vv

make_sdist:
name: Make SDist
runs-on: ubuntu-latest
Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Changelog

<!-- <START NEW CHANGELOG ENTRY> -->
<!-- <END NEW CHANGELOG ENTRY> -->
58 changes: 45 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
# hatch-jupyter-builder

[![PyPI - Version](https://img.shields.io/pypi/v/hatch-jupyter.svg)](https://pypi.org/project/hatch-jupyter)
[![PyPI - Python Version](https://img.shields.io/pypi/pyversions/hatch-jupyter.svg)](https://pypi.org/project/hatch-jupyter)
[![PyPI - Version](https://img.shields.io/pypi/v/hatch-jupyter-builder.svg)](https://pypi.org/project/hatch-jupyter-builder)
[![PyPI - Python Version](https://img.shields.io/pypi/pyversions/hatch-jupyter-builder.svg)](https://pypi.org/project/hatch-jupyter-builder)

---

This provides a [build hook](https://hatch.pypa.io/latest/config/build/#build-hooks) plugin for [Hatch](https://github.com/pypa/hatch) that adds a build step for use with Jupyter packages.

**Table of Contents**

- [Installation](#installation)
- [License](#license)
- [Configuration](#license)
- [Usage and Configuration](#usage_and_configuration)

## Installation

Expand All @@ -19,16 +21,46 @@ pip install hatch-jupyter-builder

## License

`hatch-jupyter` is distributed under the terms of the [MIT](https://spdx.org/licenses/MIT.html) license.
`hatch-jupyter-builder` is distributed under the terms of the [MIT](https://spdx.org/licenses/MIT.html) license.

## Configuration
## Usage and Configuration

```toml
[tool.hatch.build.targets.wheel.hooks.jupyter]
dependencies = ["hatch-jupyter-builder"]
build_function = "hatch_jupyter_builder.npm_builder"
ensured_targets = ["foo/generated.txt"]
The [build hook plugin](https://hatch.pypa.io/latest/plugins/build-hook/) name is `jupyter-builder`.

[tool.hatch.build.targets.wheel.hooks.jupyter_builder.build_kwargs]
build_cmd = "build:src"
```
- **_pyproject.toml_**

```toml
[tool.hatch.build.targets.wheel.hooks.jupyter-builder]
dependencies = ["hatch-jupyter-builder"]
build-function = "hatch_jupyter_builder.npm_builder"
ensured-targets = ["foo/generated.txt"]

[tool.hatch.build.targets.wheel.hooks.jupyter-builder.build-kwargs]
build_cmd = "build:src"
```

### Options

The only required fields are `dependencies` and `build-function`.
The build function is defined as an importable string with a module and a function name, separated by a period. The function must accept a
`target_name` (either "wheel" or "sdist"), and a `version` (either "standard" or "editable") as its only positional arguments. E.g.

- **_builder.py_**

```python
def build_func(target_name, version):
...
```

Would be defined as `build-function = "builder.build_func"`

The optional `ensured-targets` is a list of expected file paths after building a
"standard" version sdist or wheel.

The optional `build_kwargs` is a set of keyword arguments to pass to the build
function.

### Npm Builder Function

This library provides a convenenice `npm_builder` function which can be
used to build `npm` assets as part of the build.
Empty file removed hatch_jupyter_builder/__about__.py
Empty file.
19 changes: 12 additions & 7 deletions hatch_jupyter_builder/plugin.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,25 @@
from hatchling.builders.hooks.plugin.interface import BuildHookInterface

from .utils import ensure_targets, get_build_func
from .utils import ensure_targets, get_build_func, normalize_kwargs


class JupyterBuildHook(BuildHookInterface):
PLUGIN_NAME = "jupyter_builder"
PLUGIN_NAME = "jupyter-builder"

def initialize(self, version, build_data):
# Get the configuration options.
build_function = self.config.get("build_function")
build_kwargs = self.config.get("build_kwargs", {})
ensured_targets = self.config.get("ensured_targets", [])
build_function = self.config.get("build-function")
build_kwargs = self.config.get("build-kwargs", {})
ensured_targets = self.config.get("ensured-targets", [])

if not build_function:
return

# Get build function, call it, and then ensure targets.
# Get build function and call it with normalized parameter names.
build_func = get_build_func(build_function)
build_kwargs = normalize_kwargs(build_kwargs)
build_func(self.target_name, version, **build_kwargs)
ensure_targets(ensured_targets)

# Ensure targets in distributable dists.
if version == "standard":
ensure_targets(ensured_targets)
42 changes: 25 additions & 17 deletions hatch_jupyter_builder/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import sys
from pathlib import Path
from shutil import which
from typing import Any, Callable, List, Optional, Union
from typing import Any, Callable, Dict, List, Optional, Union

if sys.platform == "win32": # pragma: no cover
from subprocess import list2cmdline
Expand All @@ -19,21 +19,14 @@ def list2cmdline(cmd_list):

log = logging.getLogger(__name__)

if "--skip-npm" in sys.argv or os.environ.get("HATCH_JUPYTER_BUILDER_SKIP_NPM") == "1":
log.info("Skipping npm install as requested.")
skip_npm = True
sys.argv.remove("--skip-npm")
else:
skip_npm = False


def npm_builder(
target_name: str,
version: str,
path: str = ".",
build_dir: Optional[str] = None,
source_dir: Optional[str] = None,
build_cmd: str = "build",
build_cmd: Optional[str] = "build",
force: bool = False,
npm: Optional[Union[str, List]] = None,
editable_build_cmd: Optional[str] = None,
Expand Down Expand Up @@ -62,9 +55,18 @@ def npm_builder(
npm: str or list, optional.
The npm executable name, or a tuple of ['node', executable].
"""

# Check if we are building a wheel from an sdist.
abs_path = Path(path).resolve()

if "--skip-npm" in sys.argv or os.environ.get("HATCH_JUPYTER_BUILDER_SKIP_NPM") == "1":
log.info("Skipping npm install as requested.")
skip_npm = True
if "--skip-npm" in sys.argv:
sys.argv.remove("--skip-npm")
else:
skip_npm = False

is_git_checkout = (abs_path / ".git").exists()
if target_name == "wheel" and not is_git_checkout and not force:
skip_npm = True
Expand Down Expand Up @@ -171,13 +173,10 @@ def get_build_func(build_func_str: str) -> Callable[..., None]:

# If the module fails to import, try importing as a local script.
try:
sys.path.insert(0, str(Path.cwd()))
mod = importlib.import_module(mod_name)
except ImportError:
try:
sys.path.insert(0, str(Path.cwd()))
mod = importlib.import_module(mod_name)
finally:
sys.path.pop(0)
finally:
sys.path.pop(0)

return getattr(mod, func_name)

Expand All @@ -198,15 +197,24 @@ def normalize_cmd(cmd: Union[str, list]) -> List[str]:
return cmd


def normalize_kwargs(kwargs: Dict[str, str]) -> Dict[str, str]:
"""Normalize the key names in a kwargs input dictionary"""
for key in list(kwargs):
if "-" in key:
kwargs[key.replace("-", "_")] = kwargs[key]
del kwargs[key]
return kwargs


def run(cmd: Union[str, list], **kwargs: Any) -> int:
"""Echo a command before running it."""
kwargs.setdefault("shell", os.name == "nt")
normalize_cmd(cmd)
cmd = normalize_cmd(cmd)
log.info(f"> {list2cmdline(cmd)}")
return subprocess.check_call(cmd, **kwargs)


def ensure_targets(ensured_targets: list[str]) -> None:
def ensure_targets(ensured_targets: List[str]) -> None:
"""Ensure that target files are available"""
for target in ensured_targets:
if not Path(target).exists():
Expand Down
14 changes: 11 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ Issues = "https://github.com/blink0173/hatch-jupyter-builder/issues"
Source = "https://github.com/blink0173/hatch-jupyter"

[project.optional-dependencies]
test = ["pytest", "pre-commit"]
test = ["pytest", "pytest-mock", "pre-commit", "hatchling", "pytest-cov"]

[tool.hatch.build.targets.sdist]
[tool.hatch.build.targets.wheel]
Expand Down Expand Up @@ -72,13 +72,21 @@ message_template = "Bump to {new_version}"
tag_template = "v{new_version}"

[[tool.tbump.file]]
src = "hatch_jupyter_builder/_version.py"
version_template = '({major}, {minor}, {patch}, "{channel}", "{release}")'
src = "hatch_jupyter_builder/__init__.py"
version_template = '{major}.{minor}.{patch}{channel}{release}'

[[tool.tbump.file]]
src = "pyproject.toml"
version_template = "{major}.{minor}.{patch}{channel}{release}"

[[tool.tbump.field]]
name = "channel"
default = ""

[[tool.tbump.field]]
name = "release"
default = ""

[tool.mypy]
check_untyped_defs = true
disallow_incomplete_defs = true
Expand Down
3 changes: 3 additions & 0 deletions tests/test_hooks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from hatch_jupyter_builder.hooks import hatch_register_build_hook

hatch_register_build_hook()

0 comments on commit acf4d62

Please sign in to comment.