Coverage for lobster/tools/trlc/lobster_trlc_config.py: 100%

32 statements  

« prev     ^ index     » next       coverage.py v7.10.7, created at 2026-09-22 04:43 +0000

1# LOBSTER - Lightweight Open BMW Software Traceability Evidence Report 

2# Copyright (C) 2025-2026 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) 

3# 

4# This program is free software: you can redistribute it and/or modify 

5# it under the terms of the GNU Affero General Public License as 

6# published by the Free Software Foundation, either version 3 of the 

7# License, or (at your option) any later version. 

8# 

9# This program is distributed in the hope that it will be useful, but 

10# WITHOUT ANY WARRANTY; without even the implied warranty of 

11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 

12# Affero General Public License for more details. 

13# 

14# You should have received a copy of the GNU Affero General Public 

15# License along with this program. If not, see 

16# <https://www.gnu.org/licenses/>. 

17 

18from dataclasses import dataclass 

19from pathlib import Path 

20from typing import List 

21 

22import yamale 

23import yaml 

24 

25from lobster.common.items import Requirement 

26from lobster.common.multi_file_input_config import Config 

27from lobster.tools.trlc.conversion_rule import ConversionRule 

28from lobster.tools.trlc.to_string_rules import ToStringRules 

29 

30 

31@dataclass 

32class LobsterTrlcConfig(Config): 

33 conversion_rules: List[ConversionRule] 

34 to_string_rules: List[ToStringRules] 

35 

36 @classmethod 

37 def from_dict(cls, data: dict) -> "LobsterTrlcConfig": 

38 conversion_rules = [] 

39 for conversion_rule_dict in data.get("conversion-rules", []): 

40 # The YAML schema uses hyphens, but those are not valid Python identifiers. 

41 # Replace hyphens with underscores to create valid attribute names. 

42 conversion_rule_dict_updated = { 

43 key.replace("-", "_"): value 

44 for key, value in conversion_rule_dict.items() 

45 } 

46 conversion_rules.append(ConversionRule(**conversion_rule_dict_updated)) 

47 

48 return LobsterTrlcConfig( 

49 conversion_rules=conversion_rules, 

50 to_string_rules=[ToStringRules.from_dict(rules) 

51 for rules in data.get("to-string-rules", [])], 

52 inputs=data.get("inputs", ""), 

53 inputs_from_file=data.get("inputs-from-file", ""), 

54 extensions=(".rsl", ".trlc", ".trlc.md"), 

55 exclude_patterns=data.get("exclude-patterns", []), 

56 schema=Requirement, 

57 ) 

58 

59 @staticmethod 

60 def _validate_config(filename: str): 

61 schema_file = Path(__file__).parent / "schema.yamale" 

62 schema = yamale.make_schema(schema_file) 

63 # Note: using 'resolve()' only for the purpose that yamale prints the full path 

64 # in its exception in case of validation errors. 

65 data = yamale.make_data(Path(filename).resolve()) 

66 yamale.validate(schema, data) 

67 

68 @classmethod 

69 def from_file(cls, filename: str) -> "LobsterTrlcConfig": 

70 cls._validate_config(filename) 

71 

72 with open(filename, "r", encoding="UTF-8") as f: 

73 config_data = yaml.safe_load(f) 

74 

75 return cls.from_dict(config_data)