Skip to content

Commit

Permalink
Refacto: modernize config date from meta (#285)
Browse files Browse the repository at this point in the history
  • Loading branch information
Guts committed Jun 10, 2024
2 parents 3b8337e + a5db57f commit 3fceb45
Show file tree
Hide file tree
Showing 7 changed files with 107 additions and 78 deletions.
4 changes: 2 additions & 2 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ markdown_extensions:
pygments_lang_class: true
- pymdownx.inlinehilite
- pymdownx.snippets:
base_path: "."
base_path:
- "."
check_paths: true
- pymdownx.superfences
- pymdownx.tabbed:
Expand Down Expand Up @@ -105,7 +106,6 @@ plugins:
abstract_delimiter: <!-- more -->
date_from_meta:
as_creation: "date"
as_update: false
datetime_format: "%Y-%m-%d %H:%M"
default_timezone: "Europe/Paris"
default_time: "22:00"
Expand Down
15 changes: 14 additions & 1 deletion mkdocs_rss_plugin/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
# ########## Libraries #############
# ##################################

# standard
from datetime import datetime
from typing import Union

# 3rd party
from mkdocs.config import config_options
Expand All @@ -14,6 +17,16 @@
# ##################################


class _DateFromMeta(Config):
# TODO: remove deprecated code in future version. Only str values will be accepted
# for as_creation and as_update
as_creation = config_options.Type(Union[bool, str], default="git")
as_update = config_options.Type(Union[bool, str], default="git")
datetime_format = config_options.Type(str, default="%Y-%m-%d %H:%M")
default_time = config_options.Type(str, default=datetime.min.strftime("%H:%M"))
default_timezone = config_options.Type(str, default="UTC")


class _FeedsFilenamesConfig(Config):
json_created = config_options.Type(str, default="feed_json_created.json")
json_updated = config_options.Type(str, default="feed_json_updated.json")
Expand All @@ -30,7 +43,7 @@ class RssPluginConfig(Config):
config_options.ListOfItems(config_options.Type(str))
)
comments_path = config_options.Optional(config_options.Type(str))
date_from_meta = config_options.Optional(config_options.Type(dict))
date_from_meta = config_options.SubConfig(_DateFromMeta)
enabled = config_options.Type(bool, default=True)
feed_ttl = config_options.Type(int, default=1440)
feeds_filenames = config_options.SubConfig(_FeedsFilenamesConfig)
Expand Down
146 changes: 76 additions & 70 deletions mkdocs_rss_plugin/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,15 @@
from datetime import datetime
from email.utils import formatdate
from pathlib import Path
from re import compile
from re import compile as re_compile

# 3rd party
from jinja2 import Environment, FileSystemLoader, select_autoescape
from mkdocs.config import config_options
from mkdocs.config.defaults import MkDocsConfig
from mkdocs.exceptions import PluginError
from mkdocs.plugins import BasePlugin, event_priority, get_plugin_logger
from mkdocs.structure.files import Files
from mkdocs.structure.pages import Page
from mkdocs.utils import get_build_timestamp

Expand Down Expand Up @@ -55,30 +57,28 @@ class GitRssPlugin(BasePlugin[RssPluginConfig]):

def __init__(self):
"""Instanciation."""
# dates source
self.src_date_created = self.src_date_updated = "git"
self.meta_datetime_format: str | None = None
self.meta_default_timezone: str = "UTC"
self.meta_default_time: datetime.time | None = None
# pages storage
self.pages_to_filter: list = []
# prepare output feeds
self.feed_created: dict = {}
self.feed_updated: dict = {}

def on_config(self, config: config_options.Config) -> dict:
def on_config(self, config: MkDocsConfig) -> MkDocsConfig:
"""The config event is the first event called on build and
is run immediately after the user configuration is loaded and validated.
Any alterations to the config should be made here.
https://www.mkdocs.org/user-guide/plugins/#on_config
:param config: global configuration object
:type config: config_options.Config
See: https://www.mkdocs.org/user-guide/plugins/#on_config
:raises FileExistsError: if the template for the RSS feed is not found
Args:
config (config_options.Config): global configuration object
:return: plugin configuration object
:rtype: dict
Raises:
FileExistsError: if the template for the RSS feed is not found
PluginError: if the 'date_from_meta.default_time' format does not comply
Returns:
MkDocsConfig: global configuration object
"""
# Skip if disabled
if not self.config.enabled:
Expand Down Expand Up @@ -131,48 +131,56 @@ def on_config(self, config: config_options.Config) -> dict:
base_feed["logo_url"] = self.config.image

# pattern to match pages included in output
self.match_path_pattern = compile(self.config.match_path)
self.match_path_pattern = re_compile(self.config.match_path)

# date handling
if self.config.date_from_meta is not None:
self.src_date_created = self.config.date_from_meta.get("as_creation", False)
self.src_date_updated = self.config.date_from_meta.get("as_update", False)
self.meta_datetime_format = self.config.date_from_meta.get(
"datetime_format", "%Y-%m-%d %H:%M"
if (
self.config.date_from_meta.as_creation == "git"
and self.config.date_from_meta.as_update == "git"
):
logger.debug("Dates will be retrieved from git log.")
elif any(
[
isinstance(self.config.date_from_meta.as_creation, bool),
isinstance(self.config.date_from_meta.as_update, bool),
]
):
deprecation_msg = (
"Since version 1.13, using a boolean for "
"'date_from_meta.as_creation' and 'date_from_meta.as_update' is "
"deprecated. Please update your "
"`rss` plugin settings in your Mkdocs configuration "
f"({config.config_file_path}) by using a str or removing the value if "
"you were using `False`., "
)
self.meta_default_timezone = self.config.date_from_meta.get(
"default_timezone", "UTC"
logger.warning(DeprecationWarning(deprecation_msg))
self.config.date_from_meta.as_creation = (
self.config.date_from_meta.as_update
) = "git"

# check if default time complies with expected format
try:
self.config.date_from_meta.default_time = datetime.strptime(
self.config.date_from_meta.default_time, "%H:%M"
)
self.meta_default_time = self.config.date_from_meta.get(
"default_time", None
except ValueError as err:
raise PluginError(
"Config error: `date_from_meta.default_time` value "
f"'{self.config.date_from_meta.default_time}' format doesn't match the "
f"expected format %H:%M. Trace: {err}"
)
if self.meta_default_time:
try:
self.meta_default_time = datetime.strptime(
self.meta_default_time, "%H:%M"
)
except ValueError as err:
raise PluginError(
"Config error: `date_from_meta.default_time` value "
f"'{self.meta_default_time}' format doesn't match the expected "
f"format %H:%M. Trace: {err}"
)
else:
self.meta_default_time = datetime.min

if self.config.use_git:
logger.debug(
"Dates will be retrieved FIRSTLY from page meta (yaml "
"frontmatter). The git log will be used as fallback."
)
else:
logger.debug(
"Dates will be retrieved ONLY from page meta (yaml "
"frontmatter). The build date will be used as fallback, without any "
"call to Git."
)
if self.config.use_git:
logger.debug(
"Dates will be retrieved FIRSTLY from page meta (yaml "
"frontmatter). The git log will be used as fallback."
)
else:
logger.debug("Dates will be retrieved from git log.")
logger.debug(
"Dates will be retrieved ONLY from page meta (yaml "
"frontmatter). The build date will be used as fallback, without any "
"call to Git."
)

# create 2 final dicts
self.feed_created = deepcopy(base_feed)
Expand All @@ -199,34 +207,32 @@ def on_config(self, config: config_options.Config) -> dict:
"configuration file whereas a URL is mandatory to publish. "
"See: https://validator.w3.org/feed/docs/rss2.html#requiredChannelElements"
)
self.feed_created["rss_url"] = self.feed_updated["rss_url"] = None
self.feed_created["rss_url"] = self.feed_updated["json_url"] = (
self.feed_updated["rss_url"]
) = self.feed_updated["json_url"] = None

# ending event
return config

@event_priority(priority=-75)
def on_page_content(
self, html: str, page: Page, config: config_options.Config, files
self, html: str, page: Page, config: MkDocsConfig, files: Files
) -> str | None:
"""The page_content event is called after the Markdown text is rendered
to HTML (but before being passed to a template) and can be used to alter
the HTML body of the page.
"""The page_content event is called after the Markdown text is rendered to HTML
(but before being passed to a template) and can be used to alter the HTML
body of the page.
https://www.mkdocs.org/user-guide/plugins/#on_page_content
See: https://www.mkdocs.org/user-guide/plugins/#on_page_content
:param html: HTML rendered from Markdown source as string
:type html: str
:param page: mkdocs.nav.Page instance
:type page: Page
:param config: global configuration object
:type config: config_options.Config
:param files: global navigation object
:type files: [type]
Args:
html (str): HTML rendered from Markdown source as string
page (Page): `mkdocs.structure.pages.Page` instance
config (MkDocsConfig): global configuration object
files (Files): global files collection
:return: HTML rendered from Markdown source as string
:rtype: str
Returns:
Optional[str]: HTML rendered from Markdown source as string
"""

# Skip if disabled
if not self.config.enabled:
return
Expand All @@ -243,11 +249,11 @@ def on_page_content(
# retrieve dates from git log
page_dates = self.util.get_file_dates(
in_page=page,
source_date_creation=self.src_date_created,
source_date_update=self.src_date_updated,
meta_datetime_format=self.meta_datetime_format,
meta_default_timezone=self.meta_default_timezone,
meta_default_time=self.meta_default_time,
source_date_creation=self.config.date_from_meta.as_creation,
source_date_update=self.config.date_from_meta.as_update,
meta_datetime_format=self.config.date_from_meta.datetime_format,
meta_default_timezone=self.config.date_from_meta.default_timezone,
meta_default_time=self.config.date_from_meta.default_time,
)

# handle custom URL parameters
Expand Down
1 change: 0 additions & 1 deletion tests/fixtures/mkdocs_complete.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ plugins:
comments_path: "#__comments"
date_from_meta:
as_creation: "date"
as_update: false
datetime_format: "%Y-%m-%d %H:%M"
default_timezone: Europe/Paris
default_time: "09:30"
Expand Down
1 change: 0 additions & 1 deletion tests/fixtures/mkdocs_complete_no_git.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ plugins:
comments_path: "#__comments"
date_from_meta:
as_creation: "date"
as_update: false
datetime_format: "%Y-%m-%d %H:%M"
default_timezone: Europe/Paris
default_time: "09:30"
Expand Down
1 change: 0 additions & 1 deletion tests/fixtures/mkdocs_simple.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ plugins:
- rss:
date_from_meta:
as_creation: "date"
as_update: false
datetime_format: "%Y-%m-%d %H:%M"
default_timezone: "Europe/Paris"
default_time: "22:00"
Expand Down
17 changes: 15 additions & 2 deletions tests/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

# Standard library
import unittest
from datetime import datetime
from pathlib import Path

# 3rd party
Expand Down Expand Up @@ -62,7 +63,13 @@ def test_plugin_config_defaults(self):
"abstract_delimiter": "<!-- more -->",
"categories": None,
"comments_path": None,
"date_from_meta": None,
"date_from_meta": {
"as_creation": "git",
"as_update": "git",
"datetime_format": "%Y-%m-%d %H:%M",
"default_time": datetime.min.strftime("%H:%M"),
"default_timezone": "UTC",
},
"enabled": True,
"feed_ttl": 1440,
"image": None,
Expand Down Expand Up @@ -98,7 +105,13 @@ def test_plugin_config_image(self):
"abstract_delimiter": "<!-- more -->",
"categories": None,
"comments_path": None,
"date_from_meta": None,
"date_from_meta": {
"as_creation": "git",
"as_update": "git",
"datetime_format": "%Y-%m-%d %H:%M",
"default_time": datetime.min.strftime("%H:%M"),
"default_timezone": "UTC",
},
"enabled": True,
"feed_ttl": 1440,
"image": self.feed_image,
Expand Down

0 comments on commit 3fceb45

Please sign in to comment.