Coverage for src/somesy/fortran/writer.py: 81%

75 statements  

« prev     ^ index     » next       coverage.py v7.6.0, created at 2025-03-10 14:56 +0000

1"""Fortran writer.""" 

2 

3import logging 

4from pathlib import Path 

5from typing import List, Optional, Union 

6 

7import tomlkit 

8from rich.pretty import pretty_repr 

9 

10from somesy.core.models import Entity, Person, ProjectMetadata 

11from somesy.core.writer import FieldKeyMapping, IgnoreKey, ProjectMetadataWriter 

12 

13from .models import FortranConfig 

14 

15logger = logging.getLogger("somesy") 

16 

17 

18class Fortran(ProjectMetadataWriter): 

19 """Fortran config file handler parsed from fpm.toml.""" 

20 

21 def __init__( 

22 self, 

23 path: Path, 

24 pass_validation: Optional[bool] = False, 

25 ): 

26 """Fortran config file handler parsed from fpm.toml. 

27 

28 See [somesy.core.writer.ProjectMetadataWriter.__init__][]. 

29 """ 

30 mappings: FieldKeyMapping = { 

31 "authors": ["author"], 

32 "maintainers": ["maintainer"], 

33 "documentation": IgnoreKey(), 

34 } 

35 super().__init__( 

36 path, 

37 create_if_not_exists=False, 

38 direct_mappings=mappings, 

39 pass_validation=pass_validation, 

40 ) 

41 

42 @property 

43 def authors(self): 

44 """Return the only author of the fpm.toml file as list.""" 

45 authors = [] 

46 try: 

47 self._to_person(self._get_property(self._get_key("authors"))) 

48 authors = [self._get_property(self._get_key("authors"))] 

49 except ValueError: 

50 logger.warning("Cannot convert authors to Person object.") 

51 return authors 

52 

53 @authors.setter 

54 def authors(self, authors: List[Union[Person, Entity]]) -> None: 

55 """Set the authors of the project.""" 

56 self._set_property(self._get_key("authors"), self._from_person(authors[0])) 

57 

58 @property 

59 def maintainers(self): 

60 """Return the only author of the fpm.toml file as list.""" 

61 maintainers = self._get_property(self._get_key("maintainers")) 

62 if maintainers: 

63 return [self._get_property(self._get_key("maintainers"))] 

64 return [] 

65 

66 @maintainers.setter 

67 def maintainers(self, maintainers: List[Union[Person, Entity]]) -> None: 

68 """Set the maintainers of the project.""" 

69 maintainers = self._from_person(maintainers[0]) 

70 self._set_property(self._get_key("maintainers"), maintainers) 

71 

72 def _load(self) -> None: 

73 """Load fpm.toml file.""" 

74 with open(self.path) as f: 

75 self._data = tomlkit.load(f) 

76 

77 def _validate(self) -> None: 

78 """Validate poetry config using pydantic class. 

79 

80 In order to preserve toml comments and structure, tomlkit library is used. 

81 Pydantic class only used for validation. 

82 """ 

83 if self.pass_validation: 

84 return 

85 config = dict(self._get_property([])) 

86 logger.debug( 

87 f"Validating config using {FortranConfig.__name__}: {pretty_repr(config)}" 

88 ) 

89 FortranConfig(**config) 

90 

91 def save(self, path: Optional[Path] = None) -> None: 

92 """Save the fpm file.""" 

93 path = path or self.path 

94 with open(path, "w") as f: 

95 tomlkit.dump(self._data, f) 

96 

97 @staticmethod 

98 def _from_person(person: Union[Person, Entity]): 

99 """Convert project metadata person/entity object to poetry string for person format "full name <email>.""" 

100 return person.to_name_email_string() 

101 

102 @staticmethod 

103 def _to_person(person: str) -> Optional[Union[Person, Entity]]: 

104 """Convert from free string to person or entity object.""" 

105 try: 

106 return Person.from_name_email_string(person) 

107 except (ValueError, AttributeError): 

108 logger.info(f"Cannot convert {person} to Person object, trying Entity.") 

109 

110 try: 

111 return Entity.from_name_email_string(person) 

112 except (ValueError, AttributeError): 

113 logger.warning(f"Cannot convert {person} to Entity.") 

114 return None 

115 

116 def sync(self, metadata: ProjectMetadata) -> None: 

117 """Sync output file with other metadata files.""" 

118 self.name = metadata.name 

119 self.description = metadata.description 

120 

121 if metadata.version: 

122 self.version = metadata.version 

123 

124 if metadata.keywords: 

125 self.keywords = metadata.keywords 

126 

127 self.authors = metadata.authors() 

128 maintainers = metadata.maintainers() 

129 

130 # set if not empty 

131 if maintainers: 

132 # only one maintainer is allowed 

133 self.maintainers = maintainers 

134 

135 self.license = metadata.license.value 

136 

137 self.homepage = str(metadata.homepage) if metadata.homepage else None