Skip to content

Commit 0f9806a

Browse files
authored
Merge branch 'main' into main
2 parents 7d891e5 + 60459f9 commit 0f9806a

File tree

10 files changed

+155
-15
lines changed

10 files changed

+155
-15
lines changed

CHANGELOG.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,24 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1616
### Removed
1717
1818
-->
19+
20+
## 1.14.0 - 2024-06-25
21+
22+
### Bugs fixes 🐛
23+
24+
* Update docs for `as_update` (boolean not supported anymore) by @brapoprod in <https://github.com/Guts/mkdocs-rss-plugin/pull/306>
25+
* improve(remote_images): handle connection error by @Guts in <https://github.com/Guts/mkdocs-rss-plugin/pull/307>
26+
* act depending on the used Mkdocs command and disable remote images length fetching to avoid HTTP errors by @Guts in <https://github.com/Guts/mkdocs-rss-plugin/pull/311>
27+
28+
### Features and enhancements 🎉
29+
30+
* Feature: add http caching mechanism by @Guts in <https://github.com/Guts/mkdocs-rss-plugin/pull/309>
31+
* improve(http): disable warnings for unverified requests by @Guts in <https://github.com/Guts/mkdocs-rss-plugin/pull/308>
32+
33+
## New Contributors
34+
35+
* @brapoprod made their first contribution in <https://github.com/Guts/mkdocs-rss-plugin/pull/306>
36+
1937
## 1.13.4 - 2024-06-24
2038

2139
### Bugs fixes 🐛

docs/configuration.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,28 @@ Default: `<!-- more -->`
196196

197197
----
198198

199+
### :material-recycle: `cache_dir`: folder where to store plugin's cached files { #cache_dir }
200+
201+
The plugin implements a caching mechanism, ensuring that a remote media is only get once during its life-cycle on remote HTTP server (using [Cache Control](https://pypi.org/project/CacheControl/) under the hood). It is normally not necessary to specify this setting, except for when you want to change the path within your root directory where HTTP body and metadata files are cached.
202+
203+
If you want to change it, use:
204+
205+
``` yaml
206+
plugins:
207+
- rss:
208+
cache_dir: my/custom/dir
209+
```
210+
211+
It's strongly recommended to add the path to your `.gitignore` file in the root of your project:
212+
213+
``` title=".gitignore"
214+
.cache
215+
```
216+
217+
Default: `.cache/plugins/rss`.
218+
219+
----
220+
199221
### :material-tag-multiple: `categories`: item categories { #categories }
200222

201223
`categories`: list of page metadata values to use as [RSS item categories](https://www.w3schools.com/xml/rss_tag_category_item.asp).

mkdocs_rss_plugin/__about__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
__title_clean__ = "".join(e for e in __title__ if e.isalnum())
4141
__uri__ = "https://github.com/Guts/mkdocs-rss-plugin/"
4242

43-
__version__ = "1.13.4"
43+
__version__ = "1.14.0"
4444
__version_info__ = tuple(
4545
[
4646
int(num) if num.isdigit() else num

mkdocs_rss_plugin/config.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88
from mkdocs.config import config_options
99
from mkdocs.config.base import Config
1010

11+
# package
12+
from mkdocs_rss_plugin.constants import DEFAULT_CACHE_FOLDER
13+
1114
# ############################################################################
1215
# ########## Classes ###############
1316
# ##################################
@@ -16,7 +19,6 @@
1619
class _DateFromMeta(Config):
1720
"""Sub configuration object for related date options."""
1821

19-
# TODO: remove deprecated code in future version. Only str values will be accepted
2022
# for as_creation and as_update
2123
as_creation = config_options.Type(str, default="git")
2224
as_update = config_options.Type(str, default="git")
@@ -42,6 +44,7 @@ class RssPluginConfig(Config):
4244
categories = config_options.Optional(
4345
config_options.ListOfItems(config_options.Type(str))
4446
)
47+
cache_dir = config_options.Type(str, default=f"{DEFAULT_CACHE_FOLDER.resolve()}")
4548
comments_path = config_options.Optional(config_options.Type(str))
4649
date_from_meta = config_options.SubConfig(_DateFromMeta)
4750
enabled = config_options.Type(bool, default=True)

mkdocs_rss_plugin/constants.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
# ########## Globals #############
1515
# ################################
1616

17+
DEFAULT_CACHE_FOLDER = Path(".cache/plugins/rss")
1718
DEFAULT_TEMPLATE_FOLDER = Path(__file__).parent / "templates"
1819
DEFAULT_TEMPLATE_FILENAME = DEFAULT_TEMPLATE_FOLDER / "rss.xml.jinja2"
1920
MKDOCS_LOGGER_NAME = "[RSS-plugin]"

mkdocs_rss_plugin/plugin.py

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
from email.utils import formatdate
1212
from pathlib import Path
1313
from re import compile as re_compile
14-
from typing import List, Optional
14+
from typing import List, Literal, Optional
1515

1616
# 3rd party
1717
from jinja2 import Environment, FileSystemLoader, select_autoescape
@@ -55,9 +55,30 @@ class GitRssPlugin(BasePlugin[RssPluginConfig]):
5555
# allow to set the plugin multiple times in the same mkdocs config
5656
supports_multiple_instances = True
5757

58-
def __init__(self):
58+
def __init__(self, *args, **kwargs):
5959
"""Instantiation."""
6060
# pages storage
61+
super().__init__(*args, **kwargs)
62+
63+
self.cmd_is_serve: bool = False
64+
65+
def on_startup(
66+
self, *, command: Literal["build", "gh-deploy", "serve"], dirty: bool
67+
) -> None:
68+
"""The `startup` event runs once at the very beginning of an `mkdocs` invocation.
69+
Note that for initializing variables, the __init__ method is still preferred.
70+
For initializing per-build variables (and whenever in doubt), use the
71+
on_config event.
72+
73+
See: https://www.mkdocs.org/user-guide/plugins/#on_startup
74+
75+
Args:
76+
command: the command that MkDocs was invoked with, e.g. "serve" for `mkdocs serve`.
77+
dirty: whether `--dirty` flag was passed.
78+
"""
79+
# flag used command to disable some actions if serve is used
80+
self.cmd_is_serve = command == "serve"
81+
6182
self.pages_to_filter: List[PageInformation] = []
6283
# prepare output feeds
6384
self.feed_created: dict = {}
@@ -92,6 +113,11 @@ def on_config(self, config: MkDocsConfig) -> MkDocsConfig:
92113
self.config.enabled = False
93114
return config
94115

116+
# cache dir
117+
self.cache_dir = Path(self.config.cache_dir)
118+
self.cache_dir.mkdir(parents=True, exist_ok=True)
119+
logger.debug(f"Caching HTTP requests to: {self.cache_dir.resolve()}")
120+
95121
# integrations - check if theme is Material and if social cards are enabled
96122
self.integration_material_social_cards = IntegrationMaterialSocialCards(
97123
mkdocs_config=config,
@@ -100,8 +126,10 @@ def on_config(self, config: MkDocsConfig) -> MkDocsConfig:
100126

101127
# instantiate plugin tooling
102128
self.util = Util(
129+
cache_dir=self.cache_dir,
103130
use_git=self.config.use_git,
104131
integration_material_social_cards=self.integration_material_social_cards,
132+
mkdocs_command_is_on_serve=self.cmd_is_serve,
105133
)
106134

107135
# check template dirs
@@ -169,10 +197,6 @@ def on_config(self, config: MkDocsConfig) -> MkDocsConfig:
169197
self.config.date_from_meta.default_time = datetime.strptime(
170198
self.config.date_from_meta.default_time, "%H:%M"
171199
)
172-
print(
173-
self.config.date_from_meta.default_time,
174-
type(self.config.date_from_meta.default_time),
175-
)
176200
except (TypeError, ValueError) as err:
177201
logger.warning(
178202
"Config error: `date_from_meta.default_time` value "

mkdocs_rss_plugin/util.py

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
# 3rd party
2020
import markdown
2121
import urllib3
22+
from cachecontrol import CacheControl
23+
from cachecontrol.caches.file_cache import SeparateBodyFileCache
2224
from git import (
2325
GitCommandError,
2426
GitCommandNotFound,
@@ -34,7 +36,11 @@
3436
from requests.exceptions import ConnectionError, HTTPError
3537

3638
# package
37-
from mkdocs_rss_plugin.constants import MKDOCS_LOGGER_NAME, REMOTE_REQUEST_HEADERS
39+
from mkdocs_rss_plugin.constants import (
40+
DEFAULT_CACHE_FOLDER,
41+
MKDOCS_LOGGER_NAME,
42+
REMOTE_REQUEST_HEADERS,
43+
)
3844
from mkdocs_rss_plugin.git_manager.ci import CiHandler
3945
from mkdocs_rss_plugin.integrations.theme_material_social_plugin import (
4046
IntegrationMaterialSocialCards,
@@ -66,11 +72,13 @@ class Util:
6672

6773
def __init__(
6874
self,
69-
path: str = ".",
70-
use_git: bool = True,
75+
cache_dir: Path = DEFAULT_CACHE_FOLDER,
7176
integration_material_social_cards: Optional[
7277
IntegrationMaterialSocialCards
7378
] = None,
79+
mkdocs_command_is_on_serve: bool = False,
80+
path: str = ".",
81+
use_git: bool = True,
7482
):
7583
"""Class hosting the plugin logic.
7684
@@ -80,6 +88,13 @@ def __init__(
8088
integration_material_social_cards (bool, optional): option to enable
8189
integration with Social Cards plugin from Material theme. Defaults to True.
8290
"""
91+
self.mkdocs_command_is_on_serve = mkdocs_command_is_on_serve
92+
if self.mkdocs_command_is_on_serve:
93+
logger.debug(
94+
"Mkdocs serve - Fetching remote images length is disabled to avoid "
95+
"HTTP errors."
96+
)
97+
8398
if use_git:
8499
logger.debug("Git use is enabled.")
85100
try:
@@ -122,8 +137,13 @@ def __init__(
122137
self.social_cards = integration_material_social_cards
123138

124139
# http/s session
125-
self.req_session = Session()
126-
self.req_session.headers.update(REMOTE_REQUEST_HEADERS)
140+
session = Session()
141+
session.headers.update(REMOTE_REQUEST_HEADERS)
142+
self.req_session = CacheControl(
143+
sess=session,
144+
cache=SeparateBodyFileCache(directory=cache_dir),
145+
cacheable_methods=("GET", "HEAD"),
146+
)
127147

128148
def build_url(
129149
self, base_url: str, path: str, args_dict: Optional[dict] = None
@@ -645,6 +665,9 @@ def get_remote_image_length(
645665
Returns:
646666
int | None: image length as int or None
647667
"""
668+
if self.mkdocs_command_is_on_serve:
669+
return None
670+
648671
# first, try HEAD request to avoid downloading the image
649672
try:
650673
attempt += 1

requirements/base.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Common requirements
22
# -----------------------
33

4-
4+
cachecontrol[filecache] >=0.14,<1
55
GitPython>=3.1,<3.2
66
mkdocs>=1.5,<2
77
requests>=2.31,<3

tests/dev/dev_cached_http.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import http.client
2+
import logging
3+
from pathlib import Path
4+
5+
import requests
6+
from cachecontrol import CacheControl
7+
from cachecontrol.caches.file_cache import FileCache
8+
9+
http.client.HTTPConnection.debuglevel = 1
10+
logging.basicConfig()
11+
logging.getLogger().setLevel(logging.DEBUG)
12+
req_log = logging.getLogger("requests.packages.urllib3")
13+
req_log.setLevel(logging.DEBUG)
14+
req_log.propagate = True
15+
16+
17+
sess = CacheControl(
18+
requests.Session(), cache=FileCache(".web_cache"), cacheable_methods=("HEAD", "GET")
19+
)
20+
21+
22+
# get requests
23+
resp = sess.get("https://geotribu.fr")
24+
resp_img = sess.get(
25+
"https://cdn.geotribu.fr/img/articles-blog-rdp/capture-ecran/kevish_Air-Traffic.png"
26+
)
27+
28+
# try again, cache hit expected
29+
resp = sess.get("https://geotribu.fr")
30+
resp_img = sess.get(
31+
"https://cdn.geotribu.fr/img/articles-blog-rdp/capture-ecran/kevish_Air-Traffic.png"
32+
)
33+
34+
# head requests
35+
resp_img = sess.head(
36+
"https://cdn.geotribu.fr/img/articles-blog-rdp/capture-ecran/kevish_Air-Traffic.png"
37+
)
38+
39+
40+
# try again, cache hit expected
41+
resp_img = sess.head(
42+
"https://cdn.geotribu.fr/img/articles-blog-rdp/capture-ecran/kevish_Air-Traffic.png"
43+
)
44+
45+
print(list(Path(".web_cache").iterdir()))

tests/test_config.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,10 @@
2121
# 3rd party
2222
from mkdocs.config.base import Config
2323

24-
# plugin target
2524
from mkdocs_rss_plugin.config import RssPluginConfig
25+
26+
# plugin target
27+
from mkdocs_rss_plugin.constants import DEFAULT_CACHE_FOLDER
2628
from mkdocs_rss_plugin.plugin import GitRssPlugin
2729

2830
# test suite
@@ -62,6 +64,7 @@ def test_plugin_config_defaults(self):
6264
"abstract_chars_count": 160,
6365
"abstract_delimiter": "<!-- more -->",
6466
"categories": None,
67+
"cache_dir": f"{DEFAULT_CACHE_FOLDER.resolve()}",
6568
"comments_path": None,
6669
"date_from_meta": {
6770
"as_creation": "git",
@@ -105,6 +108,7 @@ def test_plugin_config_image(self):
105108
expected = {
106109
"abstract_chars_count": 160,
107110
"abstract_delimiter": "<!-- more -->",
111+
"cache_dir": f"{DEFAULT_CACHE_FOLDER.resolve()}",
108112
"categories": None,
109113
"comments_path": None,
110114
"date_from_meta": {

0 commit comments

Comments
 (0)