Coverage for src/debputy/build_support/build_context.py: 48%
46 statements
« prev ^ index » next coverage.py v7.8.2, created at 2025-10-12 15:06 +0000
« prev ^ index » next coverage.py v7.8.2, created at 2025-10-12 15:06 +0000
1from typing import Optional, TYPE_CHECKING
2from collections.abc import Mapping
4from debputy.architecture_support import DpkgArchitectureBuildProcessValuesTable
5from debputy.manifest_conditions import _run_build_time_tests
7if TYPE_CHECKING:
8 from debputy.commands.debputy_cmd.context import CommandContext
11class BuildContext:
12 @staticmethod
13 def from_command_context(
14 cmd_context: "CommandContext",
15 ) -> "BuildContext":
16 return BuildContextImpl(cmd_context)
18 @property
19 def deb_build_options(self) -> Mapping[str, str | None]:
20 raise NotImplementedError
22 def parallelization_limit(self, *, support_zero_as_unlimited: bool = False) -> int:
23 """Parallelization limit of the build
25 This is accessor that reads the `parallel` option from `DEB_BUILD_OPTIONS` with relevant
26 fallback behavior.
28 :param support_zero_as_unlimited: The debhelper framework allowed `0` to mean unlimited
29 in some build systems. If the build system supports this, it should set this option
30 to True, which will allow `0` as a possible return value. WHen this option is False
31 (which is the default), `0` will be remapped to a high number to preserve the effect
32 in spirit (said fallback number is also from `debhelper`).
33 """
34 limit = self.deb_build_options.get("parallel")
35 if limit is None:
36 return 1
37 try:
38 v = int(limit)
39 except ValueError:
40 return 1
41 if v == 0 and not support_zero_as_unlimited:
42 # debhelper allowed "0" to be used as unlimited in some cases. Preserve that feature
43 # for callers that are prepared for it. For everyone else, remap 0 to an obscene number
44 # that de facto has the same behavior
45 #
46 # The number is taken out of `cmake.pm` from `debhelper` to be "Bug compatible" with
47 # debhelper on the fallback as well.
48 return 999
49 return v
51 @property
52 def is_terse_build(self) -> bool:
53 """Whether the build is terse
55 This is a shorthand for testing for `terse` in DEB_BUILD_OPTIONS
56 """
57 return "terse" in self.deb_build_options
59 @property
60 def is_cross_compiling(self) -> bool:
61 """Whether the build is considered a cross build
63 Note: Do **not** use this as indicator for whether tests should run. Use `should_run_tests` instead.
64 To the naive eye, they seem like they overlap in functionality, but they do not. There are cross
65 builds where tests can be run. Additionally, there are non-cross-builds where tests should be
66 skipped.
67 """
68 return self.dpkg_architecture_variables.is_cross_compiling
70 def cross_tool(self, command: str) -> str:
71 if not self.is_cross_compiling:
72 return command
73 cross_prefix = self.dpkg_architecture_variables["DEB_HOST_GNU_TYPE"]
74 return f"{cross_prefix}-{command}"
76 @property
77 def dpkg_architecture_variables(self) -> DpkgArchitectureBuildProcessValuesTable:
78 raise NotImplementedError
80 @property
81 def should_run_tests(self) -> bool:
82 return _run_build_time_tests(self.deb_build_options)
85class BuildContextImpl(BuildContext):
86 def __init__(
87 self,
88 cmd_context: "CommandContext",
89 ) -> None:
90 self._cmd_context = cmd_context
92 @property
93 def deb_build_options(self) -> Mapping[str, str | None]:
94 return self._cmd_context.deb_build_options
96 @property
97 def dpkg_architecture_variables(self) -> DpkgArchitectureBuildProcessValuesTable:
98 return self._cmd_context.dpkg_architecture_variables()