Skip to content

Commit 9e94f49

Browse files
authored
Fix error getting content from cache (#171)
* Add more tests * Fix error in cache * Fix detection of invalid heading-offset argument values * Don't omit plugin file from coverage
1 parent a661b8f commit 9e94f49

File tree

11 files changed

+150
-64
lines changed

11 files changed

+150
-64
lines changed

examples/http-cache/docs/README.md

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,20 @@
11
# Header
22

3-
You need to install `platformdirs` to run this example.
3+
:warning: You need to install `platformdirs` to run this example.
44

55
{%
66
include-markdown "https://raw.githubusercontent.com/mondeja/mkdocs-include-markdown-plugin/master/examples/basic/docs/included.md"
77
%}
88

9+
## mkdocs.yml
10+
11+
```
912
{%
10-
include-markdown "https://raw.githubusercontent.com/mondeja/mkdocs-include-markdown-plugin/master/examples/basic/mkdocs.yml"
13+
include "https://raw.githubusercontent.com/mondeja/mkdocs-include-markdown-plugin/master/examples/basic/mkdocs.yml"
1114
%}
15+
```
16+
17+
## From cache
1218

1319
{%
1420
include-markdown "https://raw.githubusercontent.com/mondeja/mkdocs-include-markdown-plugin/master/examples/basic/docs/included.md"

pyproject.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,6 @@ style = [
111111

112112
[tool.coverage.run]
113113
source = ["src"]
114-
omit = ["src/mkdocs_include_markdown_plugin/plugin.py"]
115114
plugins = ["covdefaults"]
116115
parallel = true
117116
data_file = ".coverage/.coverage"

src/mkdocs_include_markdown_plugin/cache.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ def get_(self, url: str) -> str | None: # noqa: D102
4444
fpath = os.path.join(self.cache_dir, key)
4545
if os.path.isfile(fpath):
4646
creation_time = self.get_creation_time_from_fpath(fpath)
47-
if time.time() > creation_time + self.expiration_seconds:
47+
if time.time() < creation_time + self.expiration_seconds:
4848
return self.read_file(fpath)
4949
else:
5050
os.remove(fpath)

src/mkdocs_include_markdown_plugin/directive.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,9 @@ class DirectiveBoolArgument(TypedDict): # noqa: D101
6060
}
6161

6262

63-
def bool_arg(arg: str) -> re.Pattern[str]:
63+
def arg(arg: str) -> re.Pattern[str]:
6464
"""Return a compiled regexp to match a boolean argument."""
65-
return re.compile(rf'{arg}=(\w+)')
65+
return re.compile(rf'{arg}=([-\w]*)')
6666

6767

6868
def str_arg(arg: str) -> re.Pattern[str]:
@@ -80,14 +80,14 @@ def str_arg(arg: str) -> re.Pattern[str]:
8080
'encoding': str_arg('encoding'),
8181

8282
# bool
83-
'comments': bool_arg('comments'),
84-
'preserve-includer-indent': bool_arg('preserve-includer-indent'),
85-
'dedent': bool_arg('dedent'),
86-
'trailing-newlines': bool_arg('trailing-newlines'),
87-
'rewrite-relative-urls': bool_arg('rewrite-relative-urls'),
83+
'comments': arg('comments'),
84+
'preserve-includer-indent': arg('preserve-includer-indent'),
85+
'dedent': arg('dedent'),
86+
'trailing-newlines': arg('trailing-newlines'),
87+
'rewrite-relative-urls': arg('rewrite-relative-urls'),
8888

8989
# int
90-
'heading-offset': re.compile(r'heading-offset=(-?\d+)'),
90+
'heading-offset': arg('heading-offset'),
9191
}
9292

9393

src/mkdocs_include_markdown_plugin/event.py

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -89,9 +89,9 @@ def found_include_tag(match: re.Match[str]) -> str:
8989

9090
exclude_match = ARGUMENT_REGEXES['exclude'].search(arguments_string)
9191
if exclude_match is None:
92-
if defaults['exclude'] is None:
92+
if defaults['exclude'] is None: # pragma: no branch
9393
ignore_paths: list[str] = []
94-
else:
94+
else: # pragma: no cover
9595
ignore_paths = glob.glob(defaults['exclude'])
9696
else:
9797
exclude_string = parse_string_argument(exclude_match)
@@ -121,7 +121,7 @@ def found_include_tag(match: re.Match[str]) -> str:
121121
else:
122122
file_paths_to_include = process.filter_paths(
123123
glob.iglob(file_path_glob, recursive=True),
124-
ignore_paths=ignore_paths,
124+
ignore_paths,
125125
)
126126

127127
if not file_paths_to_include:
@@ -209,7 +209,7 @@ def found_include_tag(match: re.Match[str]) -> str:
209209
else:
210210
new_text_to_include = process.read_file(file_path, encoding)
211211

212-
if start is not None or end is not None:
212+
if start or end:
213213
new_text_to_include, *expected_not_found = (
214214
process.filter_inclusions(
215215
start,
@@ -307,9 +307,9 @@ def found_include_markdown_tag(match: re.Match[str]) -> str:
307307

308308
exclude_match = ARGUMENT_REGEXES['exclude'].search(arguments_string)
309309
if exclude_match is None:
310-
if defaults['exclude'] is None:
310+
if defaults['exclude'] is None: # pragma: no branch
311311
ignore_paths: list[str] = []
312-
else:
312+
else: # pragma: no cover
313313
ignore_paths = glob.glob(defaults['exclude'])
314314
else:
315315
exclude_string = parse_string_argument(exclude_match)
@@ -340,7 +340,7 @@ def found_include_markdown_tag(match: re.Match[str]) -> str:
340340
else:
341341
file_paths_to_include = process.filter_paths(
342342
glob.iglob(file_path_glob, recursive=True),
343-
ignore_paths=ignore_paths,
343+
ignore_paths,
344344
)
345345

346346
if not file_paths_to_include:
@@ -432,16 +432,27 @@ def found_include_markdown_tag(match: re.Match[str]) -> str:
432432
arguments_string,
433433
)
434434
if offset_match:
435+
offset = offset_match.group(1)
436+
if offset == '':
437+
lineno = lineno_from_content_start(
438+
markdown,
439+
directive_match_start,
440+
)
441+
raise BuildError(
442+
"Invalid empty 'heading-offset' argument in"
443+
" 'include-markdown' directive at"
444+
f' {os.path.relpath(page_src_path, docs_dir)}:{lineno}',
445+
)
435446
try:
436-
offset = int(offset_match.group(1))
447+
offset = int(offset)
437448
except ValueError:
438449
lineno = lineno_from_content_start(
439450
markdown,
440451
directive_match_start,
441452
)
442453
raise BuildError(
443-
"Invalid 'heading-offset' argument in 'include-markdown'"
444-
' directive at '
454+
f"Invalid 'heading-offset' argument \"{offset}\" in"
455+
" 'include-markdown' directive at "
445456
f'{os.path.relpath(page_src_path, docs_dir)}:{lineno}',
446457
)
447458
else:
@@ -468,7 +479,7 @@ def found_include_markdown_tag(match: re.Match[str]) -> str:
468479
else:
469480
new_text_to_include = process.read_file(file_path, encoding)
470481

471-
if start is not None or end is not None:
482+
if start or end:
472483
new_text_to_include, *expected_not_found = (
473484
process.filter_inclusions(
474485
start,

src/mkdocs_include_markdown_plugin/plugin.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ def on_config(self, config: MkDocsConfig, **kwargs: Any) -> MkDocsConfig:
5858

5959
return config
6060

61-
def _watch_included_files(self) -> None:
61+
def _watch_included_files(self) -> None: # pragma: no cover
6262
global FILES_WATCHER, SERVER
6363
SERVER = cast(LiveReloadServer, SERVER)
6464
FILES_WATCHER = cast(FilesWatcher, FILES_WATCHER)
@@ -83,7 +83,7 @@ def on_page_content(
8383
config: MkDocsConfig,
8484
files: Files,
8585
) -> str:
86-
if SERVER is not None:
86+
if SERVER is not None: # pragma: no cover
8787
self._watch_included_files()
8888
return html
8989

@@ -94,7 +94,7 @@ def on_serve(
9494
builder: Callable[[Any], Any],
9595
) -> None:
9696
global SERVER
97-
if SERVER is None:
97+
if SERVER is None: # pragma: no cover
9898
SERVER = server
9999
self._watch_included_files()
100100

src/mkdocs_include_markdown_plugin/process.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,7 @@ def filter_inclusions(
324324
expected_start_not_found = True
325325
text_to_include = new_text_to_include
326326

327-
elif new_end is not None:
327+
elif new_end is not None: # pragma: no branch
328328
end = interpret_escapes(new_end)
329329
if end in text_to_include:
330330
text_to_include = text_to_include.split(
@@ -381,7 +381,7 @@ def rstrip_trailing_newlines(content: str) -> str:
381381

382382
def filter_paths(
383383
filepaths: Iterator[str],
384-
ignore_paths: list[str] | None = None,
384+
ignore_paths: list[str],
385385
) -> list[str]:
386386
"""Filters a list of paths removing those defined in other list of paths.
387387
@@ -400,9 +400,6 @@ def filter_paths(
400400
Returns:
401401
list: Non filtered paths ordered alphabetically.
402402
"""
403-
if ignore_paths is None:
404-
ignore_paths = []
405-
406403
response = []
407404
for filepath in filepaths:
408405
# ignore by filepath

tests/test_unit/test_arguments.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,50 @@ def test_empty_encoding_argument(directive, page, tmp_path, caplog):
201201
)
202202

203203

204+
@pytest.mark.parametrize(
205+
('argument_value', 'exception_message'),
206+
(
207+
pytest.param(
208+
'invalidoption', (
209+
"Invalid 'heading-offset' argument \"invalidoption\" in"
210+
" 'include-markdown' directive at includer.md:1"
211+
),
212+
id='invalidoption',
213+
),
214+
pytest.param(
215+
'', (
216+
"Invalid empty 'heading-offset' argument in"
217+
" 'include-markdown' directive at includer.md:1"
218+
),
219+
id='empty',
220+
),
221+
),
222+
)
223+
def test_invalid_heading_offset_arguments(
224+
argument_value,
225+
exception_message,
226+
page,
227+
tmp_path,
228+
caplog,
229+
):
230+
page_to_include_filepath = tmp_path / 'included.md'
231+
page_to_include_filepath.write_text('# Content to include')
232+
233+
with pytest.raises(BuildError) as exc:
234+
on_page_markdown(
235+
f'''{{%
236+
include-markdown "{page_to_include_filepath}"
237+
comments=false
238+
heading-offset={argument_value}
239+
%}}''',
240+
page(tmp_path / 'includer.md'),
241+
tmp_path,
242+
)
243+
244+
assert len(caplog.records) == 0
245+
assert str(exc.value) == exception_message
246+
247+
204248
class TestFilename:
205249
double_quoted_filenames = [
206250
'inc"luded.md', 'inc"lude"d.md', 'included.md"', '"included.md',

tests/test_unit/test_cache.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,12 @@ def test_cache_read_file(tmp_path):
1616
)
1717

1818

19+
def test_cache_expiration_on_get(tmp_path):
20+
cache = Cache(tmp_path)
21+
cache.set_('foo', f'{time.time() - 600*10}\nbar')
22+
assert cache.get_('foo') is None
23+
24+
1925
def test_cache_clean(tmp_path):
2026
now_ts = int(time.time())
2127

tests/test_unit/test_include_markdown.py

Lines changed: 5 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -400,7 +400,7 @@
400400
id='dedent=true,preserve-includer-indent=true',
401401
),
402402
403-
# Markdown heading offset 1
403+
# Markdown heading offsets
404404
pytest.param(
405405
'''# Header
406406
@@ -423,7 +423,6 @@
423423
[],
424424
id='heading-offset=1',
425425
),
426-
# Markdown heading offset 2
427426
pytest.param(
428427
'''# Header
429428
@@ -494,30 +493,6 @@
494493
id='heading-offset=0',
495494
),
496495
497-
# Markdown heading offset string
498-
pytest.param(
499-
'''# Header
500-
501-
{%
502-
include-markdown "{filepath}"
503-
heading-offset=true
504-
%}
505-
''',
506-
'''# This should be a first level heading.
507-
508-
Example data''',
509-
'''# Header
510-
511-
<!-- BEGIN INCLUDE {filepath} -->
512-
# This should be a first level heading.
513-
514-
Example data
515-
<!-- END INCLUDE -->
516-
''',
517-
[],
518-
id='heading-offset=<str>',
519-
),
520-
521496
# Markdown heading negative offset
522497
pytest.param(
523498
'''# Header
@@ -622,10 +597,7 @@
622597
pytest.param(
623598
'''# Header
624599
625-
{%
626-
include-markdown "{filepath}"
627-
heading-offset=true
628-
%}
600+
{% include-markdown "{filepath}" %}
629601
''',
630602
'''Тест інклуде
631603
азъ
@@ -664,7 +636,7 @@
664636
id='russian-characters',
665637
),
666638
667-
# right strip unix trailing newlines
639+
# Right strip unix trailing newlines
668640
pytest.param(
669641
'''1. List item number 1
670642
1. {% include-markdown "{filepath}" comments=false trailing-newlines=false %}
@@ -679,7 +651,7 @@
679651
id='rstrip-unix-trailing-newlines',
680652
),
681653
682-
# right strip windows trailing nwlines
654+
# Right strip windows trailing newlines
683655
pytest.param(
684656
'''1. List item number 1
685657
1. {%
@@ -698,7 +670,7 @@
698670
id='rstrip-windows-trailing-newlines',
699671
),
700672
701-
# right strip trailing newlines keeping comments
673+
# Right strip trailing newlines keeping comments
702674
pytest.param(
703675
'''1. List item number 1
704676
1. {% include-markdown "{filepath}" trailing-newlines=false %}

0 commit comments

Comments
 (0)