mirror of
https://github.com/jrnl-org/jrnl.git
synced 2025-05-10 16:48:31 +02:00
Explicitly check for valid dates in FolderJournal and add unit test
This commit is contained in:
parent
128cd16744
commit
542781d62c
3 changed files with 83 additions and 11 deletions
|
@ -13,20 +13,16 @@ from .Journal import Journal
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from jrnl.journals import Entry
|
from jrnl.journals import Entry
|
||||||
|
|
||||||
# Search patterns
|
# glob search patterns
|
||||||
DIGIT_PATTERN = "[0123456789]"
|
DIGIT_PATTERN = "[0123456789]"
|
||||||
YEAR_PATTERN = DIGIT_PATTERN * 4
|
YEAR_PATTERN = DIGIT_PATTERN * 4
|
||||||
MONTH_PATTERN = DIGIT_PATTERN * 2
|
MONTH_PATTERN = "[01]" + DIGIT_PATTERN
|
||||||
DAY_PATTERN = (DIGIT_PATTERN * 2) + ".txt"
|
DAY_PATTERN = "[0123]" + DIGIT_PATTERN + ".txt"
|
||||||
|
|
||||||
# Entire range of possible folder/file names for months and days
|
|
||||||
MONTH_FOLDERS = [str(m).zfill(2) for m in range(1, 13)]
|
|
||||||
DAY_FILE_STEMS = [str(d).zfill(2) for d in range(1, 32)]
|
|
||||||
|
|
||||||
class Folder(Journal):
|
class Folder(Journal):
|
||||||
"""A Journal handling multiple files in a folder"""
|
"""A Journal handling multiple files in a folder"""
|
||||||
|
|
||||||
|
|
||||||
def __init__(self, name: str = "default", **kwargs):
|
def __init__(self, name: str = "default", **kwargs):
|
||||||
self.entries = []
|
self.entries = []
|
||||||
self._diff_entry_dates = []
|
self._diff_entry_dates = []
|
||||||
|
@ -134,14 +130,14 @@ class Folder(Journal):
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _get_year_folders(path: pathlib.Path) -> list[pathlib.Path]:
|
def _get_year_folders(path: pathlib.Path) -> list[pathlib.Path]:
|
||||||
for child in path.glob(YEAR_PATTERN):
|
for child in path.glob(YEAR_PATTERN):
|
||||||
if child.name.isdigit() and len(child.name) == 4 and child.is_dir():
|
if child.is_dir():
|
||||||
yield child
|
yield child
|
||||||
return
|
return
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _get_month_folders(path: pathlib.Path) -> list[pathlib.Path]:
|
def _get_month_folders(path: pathlib.Path) -> list[pathlib.Path]:
|
||||||
for child in path.glob(MONTH_PATTERN):
|
for child in path.glob(MONTH_PATTERN):
|
||||||
if child.name in MONTH_FOLDERS and path.is_dir():
|
if int(child.name) > 0 and int(child.name) <= 12 and path.is_dir():
|
||||||
yield child
|
yield child
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -149,8 +145,13 @@ class Folder(Journal):
|
||||||
def _get_day_files(path: pathlib.Path) -> list[str]:
|
def _get_day_files(path: pathlib.Path) -> list[str]:
|
||||||
for child in path.glob(DAY_PATTERN):
|
for child in path.glob(DAY_PATTERN):
|
||||||
if (
|
if (
|
||||||
child.stem in DAY_FILE_STEMS
|
int(child.stem) > 0
|
||||||
and child.match("*.txt")
|
and int(child.stem) <= 31
|
||||||
|
and time.is_valid_date(
|
||||||
|
year=int(path.parent.name),
|
||||||
|
month=int(path.name),
|
||||||
|
day=int(child.stem),
|
||||||
|
)
|
||||||
and child.is_file()
|
and child.is_file()
|
||||||
):
|
):
|
||||||
yield str(child)
|
yield str(child)
|
||||||
|
|
11
jrnl/time.py
11
jrnl/time.py
|
@ -89,3 +89,14 @@ def parse(
|
||||||
if dt.days < -28 and not year_present:
|
if dt.days < -28 and not year_present:
|
||||||
date = date.replace(date.year - 1)
|
date = date.replace(date.year - 1)
|
||||||
return date
|
return date
|
||||||
|
|
||||||
|
|
||||||
|
def is_valid_date(year, month, day):
|
||||||
|
"""
|
||||||
|
Checks if a string can be parsed as a date
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
datetime.datetime(year, month, day)
|
||||||
|
return True
|
||||||
|
except ValueError:
|
||||||
|
return False
|
||||||
|
|
60
tests/unit/test_journals_folder_journal.py
Normal file
60
tests/unit/test_journals_folder_journal.py
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
# Copyright © 2012-2023 jrnl contributors
|
||||||
|
# License: https://www.gnu.org/licenses/gpl-3.0.html
|
||||||
|
|
||||||
|
import pathlib
|
||||||
|
from unittest import mock
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
import jrnl
|
||||||
|
from jrnl.journals.FolderJournal import Folder
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"inputs_and_outputs",
|
||||||
|
[
|
||||||
|
[
|
||||||
|
"/2020/01",
|
||||||
|
["02.txt", "03.txt", "31.txt"],
|
||||||
|
["/2020/01/02.txt", "/2020/01/03.txt", "/2020/01/31.txt"],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"/2020/02", # leap year
|
||||||
|
["02.txt", "03.txt", "28.txt", "29.txt", "31.txt", "39.txt"],
|
||||||
|
[
|
||||||
|
"/2020/02/02.txt",
|
||||||
|
"/2020/02/03.txt",
|
||||||
|
"/2020/02/28.txt",
|
||||||
|
"/2020/02/29.txt",
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"/2100/02", # not a leap year
|
||||||
|
["01.txt", "28.txt", "29.txt", "39.txt"],
|
||||||
|
["/2100/02/01.txt", "/2100/02/28.txt"],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"/2023/04",
|
||||||
|
["29.txt", "30.txt", "31.txt", "39.txt"],
|
||||||
|
["/2023/04/29.txt", "/2023/04/30.txt"],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
)
|
||||||
|
def test_get_day_files_expected_filtering(inputs_and_outputs):
|
||||||
|
year_month_path, glob_filenames, expected_output = inputs_and_outputs
|
||||||
|
|
||||||
|
year_month_path = pathlib.Path(year_month_path)
|
||||||
|
|
||||||
|
glob_files = map(lambda x: year_month_path / x, glob_filenames)
|
||||||
|
expected_output = list(map(lambda x: str(pathlib.PurePath(x)), expected_output))
|
||||||
|
|
||||||
|
with (
|
||||||
|
mock.patch("pathlib.Path.glob", return_value=glob_files),
|
||||||
|
mock.patch.object(pathlib.Path, "is_file", return_value=True),
|
||||||
|
):
|
||||||
|
actual_output = list(Folder._get_day_files(year_month_path))
|
||||||
|
actual_output.sort()
|
||||||
|
|
||||||
|
expected_output.sort()
|
||||||
|
|
||||||
|
assert actual_output == expected_output
|
Loading…
Add table
Reference in a new issue