Coverage for glotter/project.py: 100%

40 statements  

« prev     ^ index     » next       coverage.py v7.10.7, created at 2026-03-01 21:54 +0000

1from typing import Annotated, ClassVar, Dict, List, Optional 

2 

3from glotter_core.project import AcronymScheme, CoreProjectMixin 

4from pydantic import BaseModel, Field, ValidationInfo, field_validator 

5 

6from glotter.auto_gen_test import AutoGenTest, AutoGenUseTests 

7from glotter.errors import raise_simple_validation_error, validate_str_dict, validate_str_list 

8 

9 

10class Project(BaseModel, CoreProjectMixin): 

11 VALID_REGEX: ClassVar[str] = "^[0-9a-zA-Z]+$" 

12 

13 words: Annotated[ 

14 List[Annotated[str, Field(min_length=1, pattern=VALID_REGEX, strict=True)]], 

15 Field(min_length=1, strict=True), 

16 ] 

17 requires_parameters: bool = False 

18 strings: Dict[str, str] = {} 

19 acronyms: List[Annotated[str, Field(min_length=1, pattern=VALID_REGEX, strict=True)]] = [] 

20 acronym_scheme: AcronymScheme = AcronymScheme.two_letter_limit 

21 use_tests: Optional[AutoGenUseTests] = None 

22 tests: Dict[str, AutoGenTest] = {} 

23 

24 @field_validator("acronyms", mode="before") 

25 @classmethod 

26 def get_acronym(cls, values): 

27 validate_str_list(cls, values) 

28 return [value.upper() for value in values] 

29 

30 @field_validator("strings", mode="before") 

31 @classmethod 

32 def validate_strings(cls, values): 

33 validate_str_dict(cls, values) 

34 return values 

35 

36 @field_validator("tests", mode="before") 

37 @classmethod 

38 def get_tests(cls, value, info: ValidationInfo): 

39 if not isinstance(value, dict) or not all( 

40 isinstance(test, dict) for test in value.values() 

41 ): 

42 return value 

43 

44 if info.data.get("use_tests"): 

45 raise_simple_validation_error( 

46 cls, '"tests" and "use_tests" items are mutually exclusive', {"use_tests": "..."} 

47 ) 

48 

49 return { 

50 test_name: { 

51 **test, 

52 "requires_parameters": info.data.get("requires_parameters") or False, 

53 "strings": info.data.get("strings") or {}, 

54 "name": test_name, 

55 } 

56 for test_name, test in value.items() 

57 } 

58 

59 def set_tests(self, project: "Project"): 

60 """ 

61 If there is a "use_tests" item, then set the specified tests, renaming them 

62 according to the "use_tests" item. The "use_tests" item is then removed 

63 

64 :params tests: Project with tests to use 

65 """ 

66 

67 if self.use_tests: 

68 self.tests = {} 

69 for test_name_, test in project.tests.items(): 

70 test_name = test_name_.replace(self.use_tests.search, self.use_tests.replace) 

71 self.tests[test_name] = AutoGenTest( 

72 **test.model_dump(exclude={"name"}), name=test_name 

73 ) 

74 

75 self.requires_parameters = project.requires_parameters 

76 self.use_tests = None