File: plugin.py

package info (click to toggle)
hatch-jupyter-builder 0.8.3-3
  • links: PTS, VCS
  • area: main
  • in suites: sid, trixie
  • size: 632 kB
  • sloc: python: 1,506; javascript: 135; makefile: 23
file content (96 lines) | stat: -rw-r--r-- 3,400 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
"""The main plugin for hatch_jupyter_builder."""
import os
import typing as t
import warnings
from dataclasses import dataclass, field, fields

from hatchling.builders.hooks.plugin.interface import BuildHookInterface

from .utils import (
    _get_log,
    ensure_targets,
    get_build_func,
    install_pre_commit_hook,
    normalize_kwargs,
    should_skip,
)


@dataclass
class JupyterBuildConfig:
    """Build config values for Hatch Jupyter Builder."""

    install_pre_commit_hook: str = ""
    build_function: t.Optional[str] = None
    build_kwargs: t.Mapping[str, str] = field(default_factory=dict)
    editable_build_kwargs: t.Mapping[str, str] = field(default_factory=dict)
    ensured_targets: t.List[str] = field(default_factory=list)
    skip_if_exists: t.List[str] = field(default_factory=list)
    optional_editable_build: str = ""


class JupyterBuildHook(BuildHookInterface):
    """The hatch jupyter builder build hook."""

    PLUGIN_NAME = "jupyter-builder"

    def initialize(self, version, build_data):
        """Initialize the plugin."""
        log = _get_log()
        log.info("Running jupyter-builder")
        if self.target_name not in ["wheel", "sdist"]:
            log.info(f"ignoring target name {self.target_name}")
            return False

        if os.getenv("SKIP_JUPYTER_BUILDER"):
            log.info("Skipping the build hook since SKIP_JUPYTER_BUILDER was set")
            return False

        kwargs = normalize_kwargs(self.config)
        available_fields = [f.name for f in fields(JupyterBuildConfig)]
        for key in list(kwargs):
            if key not in available_fields:
                del kwargs[key]
        config = JupyterBuildConfig(**kwargs)

        should_install_hook = config.install_pre_commit_hook.lower() == "true"

        if version == "editable" and should_install_hook:
            install_pre_commit_hook()

        build_kwargs = config.build_kwargs
        if version == "editable":
            build_kwargs = config.editable_build_kwargs or build_kwargs

        should_skip_build = False
        if not config.build_function:
            log.warning("No build function found")
            should_skip_build = True

        elif config.skip_if_exists and version == "standard":
            should_skip_build = should_skip(config.skip_if_exists)
            if should_skip_build:
                log.info("Skip-if-exists file(s) found")

        # Get build function and call it with normalized parameter names.
        if not should_skip_build and config.build_function:
            build_func = get_build_func(config.build_function)
            build_kwargs = normalize_kwargs(build_kwargs)
            log.info(f"Building with {config.build_function}")
            log.info(f"With kwargs: {build_kwargs}")
            try:
                build_func(self.target_name, version, **build_kwargs)
            except Exception as e:
                if version == "editable" and config.optional_editable_build.lower() == "true":
                    warnings.warn(f"Encountered build error:\n{e}")  # noqa B028
                else:
                    raise e
        else:
            log.info("Skipping build")

        # Ensure targets in distributable dists.
        if version == "standard":
            ensure_targets(config.ensured_targets)

        log.info("Finished running jupyter-builder")
        return True