Coverage for src/debputy/plugin/api/feature_set.py: 73%

36 statements  

« prev     ^ index     » next       coverage.py v7.8.2, created at 2025-10-12 15:06 +0000

1import dataclasses 

2from typing import Dict, List, Tuple, Any, Type 

3from collections.abc import Sequence 

4 

5from debputy.manifest_parser.declarative_parser import ParserGenerator 

6from debputy.plugin.api.impl_types import ( 

7 DebputyPluginMetadata, 

8 PackagerProvidedFileClassSpec, 

9 MetadataOrMaintscriptDetector, 

10 PluginProvidedManifestVariable, 

11 PluginProvidedPackageProcessor, 

12 PluginProvidedDiscardRule, 

13 ServiceManagerDetails, 

14 PluginProvidedKnownPackagingFile, 

15 PluginProvidedTypeMapping, 

16 PluginProvidedBuildSystemAutoDetection, 

17) 

18from debputy.plugin.api.parser_tables import ( 

19 SUPPORTED_DISPATCHABLE_OBJECT_PARSERS, 

20 SUPPORTED_DISPATCHABLE_TABLE_PARSERS, 

21) 

22from debputy.plugins.debputy.to_be_api_types import BuildSystemRule 

23 

24 

25def _initialize_parser_generator() -> ParserGenerator: 

26 pg = ParserGenerator() 

27 

28 for path, ref_doc in SUPPORTED_DISPATCHABLE_OBJECT_PARSERS.items(): 

29 pg.add_object_parser(path, parser_documentation=ref_doc) 

30 

31 for rt, path in SUPPORTED_DISPATCHABLE_TABLE_PARSERS.items(): 

32 pg.add_table_parser(rt, path) 

33 

34 return pg 

35 

36 

37@dataclasses.dataclass(slots=True) 

38class PluginProvidedFeatureSet: 

39 plugin_data: dict[str, DebputyPluginMetadata] = dataclasses.field( 

40 default_factory=dict 

41 ) 

42 packager_provided_files: dict[str, PackagerProvidedFileClassSpec] = ( 

43 dataclasses.field(default_factory=dict) 

44 ) 

45 metadata_maintscript_detectors: dict[str, list[MetadataOrMaintscriptDetector]] = ( 

46 dataclasses.field(default_factory=dict) 

47 ) 

48 manifest_variables: dict[str, PluginProvidedManifestVariable] = dataclasses.field( 

49 default_factory=dict 

50 ) 

51 all_package_processors: dict[tuple[str, str], PluginProvidedPackageProcessor] = ( 

52 dataclasses.field(default_factory=dict) 

53 ) 

54 auto_discard_rules: dict[str, PluginProvidedDiscardRule] = dataclasses.field( 

55 default_factory=dict 

56 ) 

57 service_managers: dict[str, ServiceManagerDetails] = dataclasses.field( 

58 default_factory=dict 

59 ) 

60 known_packaging_files: dict[str, PluginProvidedKnownPackagingFile] = ( 

61 dataclasses.field(default_factory=dict) 

62 ) 

63 mapped_types: dict[Any, PluginProvidedTypeMapping] = dataclasses.field( 

64 default_factory=dict 

65 ) 

66 manifest_parser_generator: ParserGenerator = dataclasses.field( 

67 default_factory=_initialize_parser_generator 

68 ) 

69 auto_detectable_build_systems: dict[ 

70 type[BuildSystemRule], PluginProvidedBuildSystemAutoDetection 

71 ] = dataclasses.field(default_factory=dict) 

72 

73 def package_processors_in_order(self) -> Sequence[PluginProvidedPackageProcessor]: 

74 order = [] 

75 delayed = [] 

76 for plugin_processor in self.all_package_processors.values(): 

77 if not plugin_processor.dependencies: 

78 order.append(plugin_processor) 

79 else: 

80 delayed.append(plugin_processor) 

81 

82 # At the time of writing, insert order will work as a plugin cannot declare 

83 # dependencies out of order in the current version. However, we want to 

84 # ensure dependencies are taken a bit seriously, so we ensure that processors 

85 # without dependencies are run first. This should weed out anything that 

86 # needs dependencies but do not add them. 

87 # 

88 # It is still far from as any dependency issues will be hidden if you just 

89 # add a single dependency. 

90 order.extend(delayed) 

91 return order