Coverage for src/somesy/mkdocs/writer.py: 100%

53 statements  

« prev     ^ index     » next       coverage.py v7.3.2, created at 2024-04-30 09:42 +0000

1"""Project documentation with Markdown (MkDocs) parser and saver.""" 

2import logging 

3from pathlib import Path 

4from typing import List, Optional 

5 

6from rich.pretty import pretty_repr 

7from ruamel.yaml import YAML 

8 

9from somesy.core.models import Person, ProjectMetadata 

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

11from somesy.mkdocs.models import MkDocsConfig 

12 

13logger = logging.getLogger("somesy") 

14 

15 

16class MkDocs(ProjectMetadataWriter): 

17 """Project documentation with Markdown (MkDocs) parser and saver.""" 

18 

19 def __init__(self, path: Path, create_if_not_exists: bool = False): 

20 """Project documentation with Markdown (MkDocs) parser. 

21 

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

23 """ 

24 self._yaml = YAML() 

25 self._yaml.preserve_quotes = True 

26 

27 mappings: FieldKeyMapping = { 

28 "name": ["site_name"], 

29 "description": ["site_description"], 

30 "homepage": ["site_url"], 

31 "repository": ["repo_url"], 

32 "authors": ["site_author"], 

33 "documentation": IgnoreKey(), 

34 "version": IgnoreKey(), 

35 "maintainers": IgnoreKey(), 

36 "license": IgnoreKey(), 

37 "keywords": IgnoreKey(), 

38 } 

39 super().__init__( 

40 path, create_if_not_exists=create_if_not_exists, direct_mappings=mappings 

41 ) 

42 

43 def _load(self): 

44 """Load the MkDocs file.""" 

45 with open(self.path) as f: 

46 self._data = self._yaml.load(f) 

47 

48 def _validate(self): 

49 """Validate the MkDocs file.""" 

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

51 logger.debug( 

52 f"Validating config using {MkDocsConfig.__name__}: {pretty_repr(config)}" 

53 ) 

54 MkDocsConfig(**config) 

55 

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

57 """Save the MkDocs object to a file.""" 

58 path = path or self.path 

59 self._yaml.dump(self._data, path) 

60 

61 @property 

62 def authors(self): 

63 """Return the only author from the source file as list.""" 

64 authors = [] 

65 try: 

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

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

68 except AttributeError: 

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

70 return authors 

71 

72 @authors.setter 

73 def authors(self, authors: List[Person]) -> None: 

74 """Set the authors of the project.""" 

75 authors = self._from_person(authors[0]) 

76 self._set_property(self._get_key("authors"), authors) 

77 

78 @staticmethod 

79 def _from_person(person: Person): 

80 """MkDocs Person is a string with full name.""" 

81 return person.to_name_email_string() 

82 

83 @staticmethod 

84 def _to_person(person: str): 

85 """MkDocs Person is a string with full name.""" 

86 return Person.from_name_email_string(person) 

87 

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

89 """Sync the MkDocs object with the ProjectMetadata object.""" 

90 self.name = metadata.name 

91 self.description = metadata.description 

92 # no author merge since it is a free text field 

93 self.authors = metadata.authors() 

94 if metadata.homepage: 

95 self.homepage = str(metadata.homepage) 

96 if metadata.repository: 

97 self.repository = str(metadata.repository) 

98 self.repo_name = metadata.repository.path