Coverage for src/somesy/mkdocs/writer.py: 100%
54 statements
« prev ^ index » next coverage.py v7.6.0, created at 2024-07-29 07:50 +0000
« prev ^ index » next coverage.py v7.6.0, created at 2024-07-29 07:50 +0000
1"""Project documentation with Markdown (MkDocs) parser and saver."""
3import logging
4from pathlib import Path
5from typing import List, Optional
7from rich.pretty import pretty_repr
8from ruamel.yaml import YAML
10from somesy.core.models import Person, ProjectMetadata
11from somesy.core.writer import FieldKeyMapping, IgnoreKey, ProjectMetadataWriter
12from somesy.mkdocs.models import MkDocsConfig
14logger = logging.getLogger("somesy")
17class MkDocs(ProjectMetadataWriter):
18 """Project documentation with Markdown (MkDocs) parser and saver."""
20 def __init__(self, path: Path, create_if_not_exists: bool = False):
21 """Project documentation with Markdown (MkDocs) parser.
23 See [somesy.core.writer.ProjectMetadataWriter.__init__][].
24 """
25 self._yaml = YAML()
26 self._yaml.preserve_quotes = True
28 mappings: FieldKeyMapping = {
29 "name": ["site_name"],
30 "description": ["site_description"],
31 "homepage": ["site_url"],
32 "repository": ["repo_url"],
33 "authors": ["site_author"],
34 "documentation": IgnoreKey(),
35 "version": IgnoreKey(),
36 "maintainers": IgnoreKey(),
37 "license": IgnoreKey(),
38 "keywords": IgnoreKey(),
39 }
40 super().__init__(
41 path, create_if_not_exists=create_if_not_exists, direct_mappings=mappings
42 )
44 def _load(self):
45 """Load the MkDocs file."""
46 with open(self.path) as f:
47 self._data = self._yaml.load(f)
49 def _validate(self):
50 """Validate the MkDocs file."""
51 config = dict(self._get_property([]))
52 logger.debug(
53 f"Validating config using {MkDocsConfig.__name__}: {pretty_repr(config)}"
54 )
55 MkDocsConfig(**config)
57 def save(self, path: Optional[Path] = None) -> None:
58 """Save the MkDocs object to a file."""
59 path = path or self.path
60 self._yaml.dump(self._data, path)
62 @property
63 def authors(self):
64 """Return the only author from the source file as list."""
65 authors = self._get_property(self._get_key("authors"))
66 if authors is None or self._to_person(authors) is None:
67 return []
68 else:
69 return [authors]
71 @authors.setter
72 def authors(self, authors: List[Person]) -> None:
73 """Set the authors of the project."""
74 authors = self._from_person(authors[0])
75 self._set_property(self._get_key("authors"), authors)
77 @staticmethod
78 def _from_person(person: Person):
79 """MkDocs Person is a string with full name."""
80 return person.to_name_email_string()
82 @staticmethod
83 def _to_person(person: str) -> Optional[Person]:
84 """MkDocs Person is a string with full name."""
85 try:
86 return Person.from_name_email_string(person)
87 except (ValueError, AttributeError):
88 logger.warning(f"Cannot convert {person} to Person object.")
89 return None
91 def sync(self, metadata: ProjectMetadata) -> None:
92 """Sync the MkDocs object with the ProjectMetadata object."""
93 self.name = metadata.name
94 self.description = metadata.description
95 # no author merge since it is a free text field
96 self.authors = metadata.authors()
97 if metadata.homepage:
98 self.homepage = str(metadata.homepage)
99 if metadata.repository:
100 self.repository = str(metadata.repository)
101 self.repo_name = metadata.repository.path