Skip to content

Commit a31393a

Browse files
authored
Add option to enable/disable git use. (#187)
Add option `use_git`, defaults to True. If not, the plugin does not try use the git log nor does not check if this is a valid git repository and use only informations from page meta (YAML frontmatter). Closes #160
2 parents c3444ee + 5e017b6 commit a31393a

6 files changed

Lines changed: 266 additions & 32 deletions

File tree

.github/workflows/lint-and-tests.yml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ jobs:
4040
python -m pip install --upgrade pip setuptools wheel
4141
python -m pip install --upgrade -r requirements.txt
4242
python -m pip install --upgrade -r requirements/development.txt
43-
python -m pip install --upgrade -r requirements/documentation.txt
4443
4544
- name: Lint with flake8
4645
run: |
@@ -53,7 +52,7 @@ jobs:
5352
run: python -m pip install -e .
5453

5554
- name: Run Unit tests
56-
run: pytest
55+
run: python -m pytest
5756

5857
- name: Upload coverage to Codecov
5958
uses: codecov/codecov-action@v3.1.4

mkdocs_rss_plugin/plugin.py

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -58,12 +58,11 @@ class GitRssPlugin(BasePlugin):
5858
("match_path", config_options.Type(str, default=".*")),
5959
("pretty_print", config_options.Type(bool, default=False)),
6060
("url_parameters", config_options.Type(dict, default=None)),
61+
("use_git", config_options.Type(bool, default=True)),
6162
)
6263

6364
def __init__(self):
6465
"""Instanciation."""
65-
# tooling
66-
self.util = Util()
6766
# dates source
6867
self.src_date_created = self.src_date_updated = "git"
6968
self.meta_datetime_format = None
@@ -94,6 +93,9 @@ def on_config(self, config: config_options.Config) -> dict:
9493
if not self.config.get("enabled"):
9594
return config
9695

96+
# instanciate plugin tooling
97+
self.util = Util(use_git=self.config.get("use_git", True))
98+
9799
# check template dirs
98100
if not Path(DEFAULT_TEMPLATE_FILENAME).is_file():
99101
raise FileExistsError(DEFAULT_TEMPLATE_FILENAME)
@@ -152,10 +154,17 @@ def on_config(self, config: config_options.Config) -> dict:
152154
f"format %H:%M. Trace: {err}"
153155
)
154156

155-
logger.debug(
156-
"[rss-plugin] Dates will be retrieved from page meta (yaml "
157-
"frontmatter). The git log will be used as fallback."
158-
)
157+
if self.config.get("use_git", True):
158+
logger.debug(
159+
"[rss-plugin] Dates will be retrieved FIRSTLY from page meta (yaml "
160+
"frontmatter). The git log will be used as fallback."
161+
)
162+
else:
163+
logger.debug(
164+
"[rss-plugin] Dates will be retrieved ONLY from page meta (yaml "
165+
"frontmatter). The build date will be used as fallback, without any "
166+
"call to Git."
167+
)
159168
else:
160169
logger.debug("[rss-plugin] Dates will be retrieved from git log.")
161170

mkdocs_rss_plugin/util.py

Lines changed: 85 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -52,26 +52,53 @@
5252

5353

5454
class Util:
55-
def __init__(self, path: str = "."):
55+
"""Plugin logic."""
56+
57+
git_is_valid: bool = False
58+
59+
def __init__(self, path: str = ".", use_git: bool = True):
5660
"""Class hosting the plugin logic.
5761
5862
:param str path: path tot the git repository to use. Defaults to: "." - optional
63+
:param bool use_git: flag to use git under the hood or not, defaults to True
5964
"""
60-
try:
61-
git_repo = Repo(path, search_parent_directories=True)
62-
self.repo = git_repo.git
63-
self.git_is_valid = 1
64-
except InvalidGitRepositoryError as err:
65-
logging.warning(
66-
f"[rss-plugin] Path '{path}' is not a valid git directory. Trace: {err}"
65+
if use_git:
66+
logger.debug("[rss-plugin] Git use is disabled.")
67+
try:
68+
git_repo = Repo(path, search_parent_directories=True)
69+
self.repo = git_repo.git
70+
self.git_is_valid = True
71+
except InvalidGitRepositoryError as err:
72+
logger.warning(
73+
f"[rss-plugin] Path '{path}' is not a valid git directory. "
74+
"Only page.meta (YAML frontmatter will be used). "
75+
"To disable this warning, set 'use_git: false' in plugin options. "
76+
f"Trace: {err}"
77+
)
78+
self.git_is_valid = False
79+
use_git = False
80+
except Exception as err:
81+
logger.warning(
82+
f"[rss-plugin] Unrecognized git issue. "
83+
"Only page.meta (YAML frontmatter will be used). "
84+
"To disable this warning, set 'use_git: false' in plugin options. "
85+
f"Trace: {err}"
86+
)
87+
self.git_is_valid = False
88+
use_git = False
89+
90+
# Checks if user is running builds on CI and raise appropriate warnings
91+
if self.git_is_valid:
92+
CiHandler(git_repo.git).raise_ci_warnings()
93+
else:
94+
self.git_is_valid = False
95+
logger.debug(
96+
"[rss-plugin] Git use is disabled. "
97+
"Only page.meta (YAML frontmatter will be used). "
6798
)
68-
self.git_is_valid = 0
69-
except Exception as err:
70-
logging.warning(f"[rss-plugin] Git issue: {err}")
71-
self.git_is_valid = 0
7299

73-
# Checks if user is running builds on CI and raise appropriate warnings
74-
CiHandler(git_repo.git).raise_ci_warnings()
100+
# save git enable/disable status
101+
self.use_git = use_git
75102

76103
def build_url(self, base_url: str, path: str, args_dict: dict = None) -> str:
77104
"""Build URL using base URL, cumulating existing and passed path, \
@@ -135,27 +162,48 @@ def get_file_dates(
135162
dt_created = dt_updated = None
136163

137164
# if enabled, try to retrieve dates from page metadata
138-
if source_date_creation != "git" and in_page.meta.get(source_date_creation):
165+
if not self.use_git or (
166+
source_date_creation != "git" and in_page.meta.get(source_date_creation)
167+
):
139168
dt_created = self.get_date_from_meta(
140169
date_metatag_value=in_page.meta.get(source_date_creation),
141170
meta_datetime_format=meta_datetime_format,
142171
meta_datetime_timezone=meta_default_timezone,
143172
meta_default_time=meta_default_time,
144173
)
145174
if isinstance(dt_created, str):
146-
logger.error(f"Creation date is a string: {dt_created}")
147-
dt_created = None
175+
logger.info(
176+
f"[rss-plugin] Creation date of {in_page.file.abs_src_path} is an "
177+
f"a character string: {dt_created} ({type(dt_created)})"
178+
)
179+
180+
elif dt_created is None:
181+
logger.info(
182+
f"[rss-plugin] Creation date of {in_page.file.abs_src_path} has not "
183+
"been recognized."
184+
)
148185

149-
if source_date_update != "git" and in_page.meta.get(source_date_update):
186+
if not self.use_git or (
187+
source_date_update != "git" and in_page.meta.get(source_date_update)
188+
):
150189
dt_updated = self.get_date_from_meta(
151190
date_metatag_value=in_page.meta.get(source_date_update),
152191
meta_datetime_format=meta_datetime_format,
153192
meta_datetime_timezone=meta_default_timezone,
154193
meta_default_time=meta_default_time,
155194
)
195+
156196
if isinstance(dt_updated, str):
157-
logger.error(f"Update date is a string: {dt_updated}")
158-
dt_updated = None
197+
logger.info(
198+
f"[rss-plugin] Update date of {in_page.file.abs_src_path} is an "
199+
f"a character string: {dt_updated} ({type(dt_updated)})"
200+
)
201+
202+
elif dt_updated is None:
203+
logger.info(
204+
f"[rss-plugin] Update date of {in_page.file.abs_src_path} is an "
205+
f"unrecognized type: {dt_updated} ({type(dt_updated)})"
206+
)
159207

160208
# explore git log
161209
if self.git_is_valid:
@@ -180,12 +228,14 @@ def get_file_dates(
180228
logging.warning(
181229
f"[rss-plugin] Unable to read git logs of '{in_page.file.abs_src_path}'. "
182230
"Is git log readable? Falling back to build date. "
231+
"To disable this warning, set 'use_git: false' in plugin options. "
183232
f"Trace: {err}"
184233
)
185234
except GitCommandNotFound as err:
186235
logging.error(
187236
"[rss-plugin] Unable to perform command 'git log'. Is git installed? "
188-
" Falling back to build date. "
237+
"Falling back to build date. "
238+
"To disable this warning, set 'use_git: false' in plugin options. "
189239
f"Trace: {err}"
190240
)
191241
self.git_is_valid = 0
@@ -334,11 +384,22 @@ def get_date_from_meta(
334384
time_to_add = datetime.min.time()
335385
out_date = datetime.combine(date_metatag_value, time_to_add)
336386
else:
337-
return "[rss-plugin] Incompatible date type."
387+
logger.debug(
388+
f"[rss-plugin] Incompatible date type: {type(date_metatag_value)}"
389+
)
390+
return out_date
338391
except ValueError as err:
339-
return f"[rss-plugin] Incompatible date found. Trace: {err}"
392+
logger.error(
393+
f"[rss-plugin] Incompatible date found: {date_metatag_value=} "
394+
f"{type(date_metatag_value)}. Trace: {err}"
395+
)
396+
return out_date
340397
except Exception as err:
341-
return f"[rss-plugin] Unable to retrieve creation date. Trace: {err}"
398+
logger.error(
399+
f"[rss-plugin] Unable to retrieve creation date: {date_metatag_value=} "
400+
f"{type(date_metatag_value)}. Trace: {err}"
401+
)
402+
return out_date
342403

343404
if not out_date.tzinfo:
344405
out_date = set_datetime_zoneinfo(out_date, meta_datetime_timezone)
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# Project information
2+
site_name: MkDocs RSS Plugin - TEST
3+
site_description: Basic setup to test against MkDocs RSS plugin
4+
site_author: Julien Moura (Guts)
5+
site_url: https://guts.github.io/mkdocs-rss-plugin
6+
copyright: "Guts - In Geo Veritas"
7+
8+
# Repository
9+
repo_name: "guts/mkdocs-rss-plugin"
10+
repo_url: "https://github.com/guts/mkdocs-rss-plugin"
11+
12+
use_directory_urls: true
13+
14+
plugins:
15+
- rss:
16+
abstract_chars_count: 160 # -1 for full content
17+
categories:
18+
- tags
19+
comments_path: "#__comments"
20+
date_from_meta:
21+
as_creation: "date"
22+
as_update: false
23+
datetime_format: "%Y-%m-%d %H:%M"
24+
default_timezone: Europe/Paris
25+
default_time: "09:30"
26+
enabled: true
27+
feed_ttl: 1440
28+
image: https://upload.wikimedia.org/wikipedia/commons/thumb/4/43/Feed-icon.svg/128px-Feed-icon.svg.png
29+
length: 20
30+
pretty_print: false
31+
match_path: ".*"
32+
url_parameters:
33+
utm_source: "documentation"
34+
utm_medium: "RSS"
35+
utm_campaign: "feed-syndication"
36+
use_git: false
37+
theme:
38+
name: readthedocs
39+
locale: fr
40+
41+
# Extensions to enhance markdown
42+
markdown_extensions:
43+
- meta

tests/test_build_no_git.py

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
#! python3 # noqa E265
2+
3+
"""Usage from the repo root folder:
4+
5+
.. code-block:: python
6+
7+
# for whole test
8+
python -m unittest tests.test_build_no_git
9+
# for specific test
10+
python -m unittest tests.test_build_no_git.TestBuildRssNoGit.test_not_git_repo_without_option
11+
"""
12+
13+
# #############################################################################
14+
# ########## Libraries #############
15+
# ##################################
16+
17+
# Standard library
18+
import tempfile
19+
import unittest
20+
21+
# logging
22+
from logging import DEBUG, getLogger
23+
from pathlib import Path
24+
from traceback import format_exception
25+
26+
# test suite
27+
from tests.base import BaseTest
28+
29+
logger = getLogger(__name__)
30+
logger.setLevel(DEBUG)
31+
32+
# #############################################################################
33+
# ########## Classes ###############
34+
# ##################################
35+
36+
37+
class TestBuildRssNoGit(BaseTest):
38+
"""Test MkDocs build with RSS plugin but without git."""
39+
40+
# -- Standard methods --------------------------------------------------------
41+
@classmethod
42+
def setUpClass(cls):
43+
"""Executed when module is loaded before any test."""
44+
pass
45+
46+
def setUp(self):
47+
"""Executed before each test."""
48+
pass
49+
50+
def tearDown(self):
51+
"""Executed after each test."""
52+
pass
53+
54+
@classmethod
55+
def tearDownClass(cls):
56+
"""Executed after the last test."""
57+
# # In case of some tests failure, ensure that everything is cleaned up
58+
# temp_page = Path("tests/fixtures/docs/temp_page_not_in_git_log.md")
59+
# # if temp_page.exists():
60+
# # temp_page.unlink()
61+
62+
git_dir = Path("_git")
63+
if git_dir.exists():
64+
git_dir.replace(git_dir.with_name(".git"))
65+
66+
# -- TESTS ---------------------------------------------------------
67+
def test_not_git_repo(self):
68+
# temporarily rename the git folder to fake a non-git repo
69+
git_dir = Path(".git")
70+
git_dir_tmp = git_dir.with_name("_git")
71+
git_dir.replace(git_dir_tmp)
72+
73+
with tempfile.TemporaryDirectory() as tmpdirname:
74+
cli_result = self.build_docs_setup(
75+
testproject_path="docs",
76+
mkdocs_yml_filepath=Path("tests/fixtures/mkdocs_complete_no_git.yml"),
77+
output_path=tmpdirname,
78+
strict=True,
79+
)
80+
81+
self.assertIsNone(cli_result.exception)
82+
self.assertEqual(cli_result.exit_code, 0, cli_result)
83+
84+
# restore name
85+
git_dir_tmp.replace(git_dir)
86+
87+
def test_not_git_repo_without_option(self):
88+
# temporarily rename the git folder to fake a non-git repo
89+
git_dir = Path(".git")
90+
git_dir_tmp = git_dir.with_name("_git")
91+
git_dir.replace(git_dir_tmp)
92+
93+
with tempfile.TemporaryDirectory() as tmpdirname:
94+
cli_result = self.build_docs_setup(
95+
testproject_path="docs",
96+
mkdocs_yml_filepath=Path("tests/fixtures/mkdocs_complete.yml"),
97+
output_path=tmpdirname,
98+
strict=True,
99+
)
100+
101+
self.assertIsNotNone(cli_result.exception)
102+
self.assertEqual(
103+
cli_result.exit_code,
104+
1,
105+
format_exception(
106+
type(cli_result.exception),
107+
cli_result.exception,
108+
cli_result.exception.__traceback__,
109+
),
110+
)
111+
112+
# restore name
113+
git_dir_tmp.replace(git_dir)
114+
115+
116+
# ##############################################################################
117+
# ##### Stand alone program ########
118+
# ##################################
119+
if __name__ == "__main__":
120+
unittest.main()

0 commit comments

Comments
 (0)