forked from beancount/fava
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy path_build_backend.py
More file actions
125 lines (102 loc) · 3.68 KB
/
_build_backend.py
File metadata and controls
125 lines (102 loc) · 3.68 KB
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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
"""Build backend that also compiles translations and frontend."""
from __future__ import annotations
import shutil
import subprocess
from itertools import chain
from os import walk
from pathlib import Path
from typing import TYPE_CHECKING
from setuptools import build_meta
from setuptools.build_meta import get_requires_for_build_editable
from setuptools.build_meta import get_requires_for_build_sdist
from setuptools.build_meta import get_requires_for_build_wheel
from setuptools.build_meta import prepare_metadata_for_build_editable
from setuptools.build_meta import prepare_metadata_for_build_wheel
if TYPE_CHECKING: # pragma: no cover
from collections.abc import Iterable
__all__ = [
"build_editable",
"build_sdist",
"build_wheel",
"get_requires_for_build_editable",
"get_requires_for_build_sdist",
"get_requires_for_build_wheel",
"prepare_metadata_for_build_editable",
"prepare_metadata_for_build_wheel",
]
def _frontend_sources() -> Iterable[Path]:
"""List all frontend sources that should trigger a rebuild if changed.
Yields:
The files relevant for the frontend build.
"""
yield Path("frontend/bun.lock")
yield Path("frontend/build.ts")
for directory, _dirnames, files in chain(
walk(Path("frontend/css")),
walk(Path("frontend/src")),
):
dirpath = Path(directory)
for file in files:
yield dirpath / file
def _compile_frontend() -> None:
"""Compile the frontend (if changed or missing)."""
source_mtime = max(p.stat().st_mtime_ns for p in _frontend_sources())
app_js = Path("src/rustfava/static/app.js")
if app_js.exists() and source_mtime < app_js.stat().st_mtime_ns:
return
bun = shutil.which("bun")
if bun is None:
msg = "bun is missing"
raise RuntimeError(msg)
subprocess.run((bun, "install"), cwd="frontend", check=True)
Path("frontend/node_modules").touch()
subprocess.run((bun, "run", "build"), cwd="frontend", check=True)
def _compile_translations() -> None:
"""Compile the translations from .po to .mo (if changed or missing)."""
# Lazy import to avoid requiring Babel for metadata preparation
from babel.messages.mofile import write_mo
from babel.messages.pofile import read_po
for source in Path().glob("src/rustfava/translations/**/messages.po"):
target = source.parent / "messages.mo"
if (
not target.exists()
or target.stat().st_mtime_ns < source.stat().st_mtime_ns
):
locale = source.parts[-3]
catalog = read_po(source.open("rb"), locale)
write_mo(target.open("wb"), catalog)
def _build_rustfava() -> None:
"""Run the build steps for rustfava."""
_compile_frontend()
_compile_translations()
def build_wheel(
wheel_directory: str,
config_settings: dict[str, str | list[str] | None] | None = None,
metadata_directory: str | None = None,
) -> str:
_build_rustfava()
return build_meta.build_wheel(
wheel_directory,
config_settings=config_settings,
metadata_directory=metadata_directory,
)
def build_editable(
wheel_directory: str,
config_settings: dict[str, str | list[str] | None] | None = None,
metadata_directory: str | None = None,
) -> str:
_build_rustfava()
return build_meta.build_editable(
wheel_directory,
config_settings=config_settings,
metadata_directory=metadata_directory,
)
def build_sdist(
sdist_directory: str,
config_settings: dict[str, str | list[str] | None] | None = None,
) -> str:
_build_rustfava()
return build_meta.build_sdist(
sdist_directory,
config_settings=config_settings,
)