|
| 1 | +"""Setuptools build hook for generating Java stubs. |
| 2 | +
|
| 3 | +To use this hook, add the following to your `pyproject.toml`: |
| 4 | +
|
| 5 | +```toml |
| 6 | +[build-system] |
| 7 | +requires = ["setuptools>=69", "wheel", "scyjava"] |
| 8 | +build-backend = "setuptools.build_meta" |
| 9 | +
|
| 10 | +[tool.setuptools.cmdclass] |
| 11 | +build_py = "scyjava_stubgen.build:build_py" |
| 12 | +# optional project-specific defaults |
| 13 | +maven_coordinates = ["org.scijava:parsington:3.1.0"] |
| 14 | +prefixes = ["org.scijava"] |
| 15 | +``` |
| 16 | +
|
| 17 | +This will generate stubs for the given maven coordinates and prefixes. The generated |
| 18 | +stubs will be placed in `src/scyjava/types` and will be included in the wheel package. |
| 19 | +This hook is only run when building a wheel package. |
| 20 | +""" |
| 21 | + |
| 22 | +from __future__ import annotations |
| 23 | + |
| 24 | +import logging |
| 25 | +from pathlib import Path |
| 26 | +from typing import List |
| 27 | + |
| 28 | +from setuptools.command.build_py import build_py as _build_py |
| 29 | +from scyjava._stubs._genstubs import generate_stubs |
| 30 | + |
| 31 | +log = logging.getLogger("scyjava") |
| 32 | + |
| 33 | + |
| 34 | +class build_py(_build_py): # type: ignore[misc] |
| 35 | + """ |
| 36 | + A drop-in replacement for setuptools' build_py that |
| 37 | + generates Java type stubs before Python sources are copied |
| 38 | + into *build_lib*. |
| 39 | + """ |
| 40 | + |
| 41 | + # expose two optional CLI/pyproject options so users can override defaults |
| 42 | + user_options: List[tuple[str, str | None, str]] = _build_py.user_options + [ |
| 43 | + ("maven-coordinates=", None, "List of Maven coordinates to stub"), |
| 44 | + ("prefixes=", None, "Java package prefixes to include"), |
| 45 | + ] |
| 46 | + |
| 47 | + def initialize_options(self) -> None: # noqa: D401 |
| 48 | + super().initialize_options() |
| 49 | + self.maven_coordinates: list[str] | None = None |
| 50 | + self.prefixes: list[str] | None = None |
| 51 | + |
| 52 | + def finalize_options(self) -> None: # noqa: D401 |
| 53 | + """Fill in options that may come from pyproject metadata.""" |
| 54 | + super().finalize_options() |
| 55 | + dist = self.distribution # alias |
| 56 | + if self.maven_coordinates is None: |
| 57 | + self.maven_coordinates = getattr(dist, "maven_coordinates", []) |
| 58 | + if self.prefixes is None: |
| 59 | + self.prefixes = getattr(dist, "prefixes", []) |
| 60 | + |
| 61 | + def run(self) -> None: # noqa: D401 |
| 62 | + """Generate stubs, then let the normal build_py proceed.""" |
| 63 | + if self.maven_coordinates: |
| 64 | + dest = Path(self.build_lib, "scyjava", "types") |
| 65 | + dest.parent.mkdir(parents=True, exist_ok=True) |
| 66 | + (dest.parent / "py.typed").touch() |
| 67 | + |
| 68 | + generate_stubs( |
| 69 | + endpoints=self.maven_coordinates, |
| 70 | + prefixes=self.prefixes, |
| 71 | + output_dir=dest, |
| 72 | + remove_namespace_only_stubs=True, |
| 73 | + ) |
| 74 | + log.info("Generated stubs for %s", ", ".join(self.maven_coordinates)) |
| 75 | + |
| 76 | + # make sure the wheel knows about them |
| 77 | + self.package_data.setdefault("scyjava", []).append("types/**/*.pyi") |
| 78 | + |
| 79 | + super().run() |
0 commit comments