Coverage for src/debputy/build_support/buildsystem_detection.py: 12%

52 statements  

« prev     ^ index     » next       coverage.py v7.6.0, created at 2025-01-27 13:59 +0000

1from typing import ( 

2 Optional, 

3 TYPE_CHECKING, 

4) 

5 

6from debputy.filesystem_scan import FSROOverlay 

7from debputy.manifest_parser.base_types import BuildEnvironmentDefinition 

8from debputy.manifest_parser.util import AttributePath 

9from debputy.plugin.debputy.to_be_api_types import ( 

10 BuildSystemRule, 

11) 

12from debputy.plugin.plugin_state import run_in_context_of_plugin_wrap_errors 

13from debputy.util import ( 

14 _error, 

15 _debug_log, 

16) 

17 

18if TYPE_CHECKING: 

19 from debputy.highlevel_manifest import HighLevelManifest 

20 

21 

22def default_build_environment_only( 

23 manifest: "HighLevelManifest", 

24) -> BuildEnvironmentDefinition: 

25 build_envs = manifest.build_environments 

26 if build_envs.environments: 

27 _error( 

28 'When automatic build system detection is used, the manifest cannot use "build-environments"' 

29 ) 

30 build_env = build_envs.default_environment 

31 assert build_env is not None 

32 return build_env 

33 

34 

35def auto_detect_buildsystem( 

36 manifest: "HighLevelManifest", 

37) -> Optional[BuildSystemRule]: 

38 auto_detectable_build_systems = ( 

39 manifest.plugin_provided_feature_set.auto_detectable_build_systems 

40 ) 

41 excludes = set() 

42 options = [] 

43 _debug_log("Auto-detecting build systems.") 

44 source_root = FSROOverlay.create_root_dir("", ".") 

45 for ppadbs in auto_detectable_build_systems.values(): 

46 detected = ppadbs.detector(source_root) 

47 if not isinstance(detected, bool): 

48 _error( 

49 f'The auto-detector for the build system {ppadbs.manifest_keyword} returned a "non-bool"' 

50 f" ({detected!r}), which could be a bug in the plugin or the plugin relying on a newer" 

51 " version of `debputy` that changed the auto-detection protocol." 

52 ) 

53 if not detected: 

54 _debug_log( 

55 f"Skipping build system {ppadbs.manifest_keyword}: Detector returned False!" 

56 ) 

57 continue 

58 _debug_log( 

59 f"Considering build system {ppadbs.manifest_keyword} as its Detector returned True!" 

60 ) 

61 if ppadbs.auto_detection_shadow_build_systems: 

62 names = ", ".join( 

63 sorted(x for x in ppadbs.auto_detection_shadow_build_systems) 

64 ) 

65 _debug_log(f"Build system {ppadbs.manifest_keyword} excludes: {names}!") 

66 excludes.update(ppadbs.auto_detection_shadow_build_systems) 

67 options.append(ppadbs) 

68 

69 if not options: 

70 _debug_log("Zero candidates; continuing without a build system") 

71 return None 

72 

73 if excludes: 

74 names = ", ".join(sorted(x for x in excludes)) 

75 _debug_log(f"The following build systems have been excluded: {names}!") 

76 remaining_options = [o for o in options if o.manifest_keyword not in excludes] 

77 else: 

78 remaining_options = options 

79 

80 if len(remaining_options) > 1: 

81 names = ", ".join(o.manifest_keyword for o in remaining_options) 

82 # TODO: This means adding an auto-detectable build system to an existing plugin causes FTBFS 

83 # We need a better way of handling this. Probably the build systems should include 

84 # a grace timer based on d/changelog. Anything before the changelog date is in 

85 # "grace mode" and will not conflict with a build system that is. If all choices 

86 # are in "grace mode", "oldest one" wins. 

87 _error( 

88 f"Multiple build systems match, please pick one explicitly (under `builds:`): {names}" 

89 ) 

90 

91 if not remaining_options: 

92 names = ", ".join(o.build_system_rule_type.__name__ for o in options) 

93 # TODO: Detect at registration time 

94 _error( 

95 f"Multiple build systems matched but they all shadowed each other: {names}." 

96 f" There is a bug in at least one of them!" 

97 ) 

98 

99 chosen_build_system = remaining_options[0] 

100 environment = default_build_environment_only(manifest) 

101 bs = run_in_context_of_plugin_wrap_errors( 

102 chosen_build_system.plugin_metadata.plugin_name, 

103 chosen_build_system.constructor, 

104 { 

105 "environment": environment, 

106 }, 

107 AttributePath.builtin_path(), 

108 manifest, 

109 ) 

110 bs.auto_generated_stem = "" 

111 return bs