Explicitly check for valid dates in FolderJournal and add unit test

This commit is contained in:
Micah Jerome Ellison 2023-04-29 15:05:22 -07:00
parent 128cd16744
commit 542781d62c
3 changed files with 83 additions and 11 deletions

View file

@ -13,20 +13,16 @@ from .Journal import Journal
if TYPE_CHECKING:
from jrnl.journals import Entry
# Search patterns
# glob search patterns
DIGIT_PATTERN = "[0123456789]"
YEAR_PATTERN = DIGIT_PATTERN * 4
MONTH_PATTERN = DIGIT_PATTERN * 2
DAY_PATTERN = (DIGIT_PATTERN * 2) + ".txt"
MONTH_PATTERN = "[01]" + DIGIT_PATTERN
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):
"""A Journal handling multiple files in a folder"""
def __init__(self, name: str = "default", **kwargs):
self.entries = []
self._diff_entry_dates = []
@ -134,14 +130,14 @@ class Folder(Journal):
@staticmethod
def _get_year_folders(path: pathlib.Path) -> list[pathlib.Path]:
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
return
@staticmethod
def _get_month_folders(path: pathlib.Path) -> list[pathlib.Path]:
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
return
@ -149,8 +145,13 @@ class Folder(Journal):
def _get_day_files(path: pathlib.Path) -> list[str]:
for child in path.glob(DAY_PATTERN):
if (
child.stem in DAY_FILE_STEMS
and child.match("*.txt")
int(child.stem) > 0
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()
):
yield str(child)

View file

@ -89,3 +89,14 @@ def parse(
if dt.days < -28 and not year_present:
date = date.replace(date.year - 1)
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

View 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