Skip to content

Commit c610ce1

Browse files
committed
add mkdocs module
1 parent 6cf00b4 commit c610ce1

3 files changed

Lines changed: 130 additions & 0 deletions

File tree

src/somesy/mkdocs/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
"""MkDocs module."""
2+
from .writer import MkDocs
3+
4+
__all__ = ["MkDocs"]

src/somesy/mkdocs/models.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
"""Pyproject models."""
2+
from typing import Optional
3+
4+
from pydantic import (
5+
BaseModel,
6+
Field,
7+
)
8+
from typing_extensions import Annotated
9+
10+
from somesy.core.types import HttpUrlStr
11+
12+
13+
class MkDocsConfig(BaseModel):
14+
"""MkDocs configuration model."""
15+
16+
model_config = dict(use_enum_values=True)
17+
18+
site_name: Annotated[
19+
str,
20+
Field(pattern=r"^[A-Za-z0-9]+([_-][A-Za-z0-9]+)*$", description="Site name"),
21+
]
22+
site_description: Annotated[str, Field(description="Site description")] = None
23+
site_author: Annotated[str, Field(description="Site authors")] = None
24+
site_url: Annotated[Optional[HttpUrlStr], Field(description="Site homepage")] = None
25+
repo_url: Annotated[
26+
Optional[HttpUrlStr], Field(description="Package repository")
27+
] = None
28+
repo_name: Annotated[str, Field(description="Repository name")] = None

src/somesy/mkdocs/writer.py

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
"""Project documentation with Markdown (MkDocs) parser and saver."""
2+
import logging
3+
from pathlib import Path
4+
from typing import List, Optional
5+
6+
from rich.pretty import pretty_repr
7+
from ruamel.yaml import YAML
8+
9+
from somesy.core.models import Person, ProjectMetadata
10+
from somesy.core.writer import FieldKeyMapping, IgnoreKey, ProjectMetadataWriter
11+
from somesy.mkdocs.models import MkDocsConfig
12+
13+
logger = logging.getLogger("somesy")
14+
15+
16+
class 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

0 commit comments

Comments
 (0)