From 93e475b14eecddbaedd8e01da16bede229599091 Mon Sep 17 00:00:00 2001 From: Micah Jerome Ellison Date: Mon, 6 Mar 2023 10:54:04 -0800 Subject: [PATCH] Completely remake get_files in FolderJournal: - move get_files into FolderJournal class and add underscore prefix - create iterables to get for year/month folders and day files - make year/month/day file reading strict: only exact expected months and days out of all possible months and days --- jrnl/journals/FolderJournal.py | 75 +++++++++++++++++++--------------- 1 file changed, 41 insertions(+), 34 deletions(-) diff --git a/jrnl/journals/FolderJournal.py b/jrnl/journals/FolderJournal.py index 8be527b4..a06e1ce9 100644 --- a/jrnl/journals/FolderJournal.py +++ b/jrnl/journals/FolderJournal.py @@ -2,8 +2,8 @@ # License: https://www.gnu.org/licenses/gpl-3.0.html import codecs -import fnmatch import os +import pathlib from typing import TYPE_CHECKING from jrnl import time @@ -14,36 +14,14 @@ if TYPE_CHECKING: from jrnl.journals import Entry -def get_files(journal_path: str) -> list[str]: - """Searches through sub directories starting with journal_path and find all text files that look like entries""" - filenames = [] - for dirpath, dirnames, f in os.walk(journal_path): - for filename in fnmatch.filter(f, "*.txt"): - if _should_file_be_opened(journal_path, dirpath, filename): - filenames.append(os.path.join(dirpath, filename)) - return filenames - - -def _should_file_be_opened(journal_path: str, dirpath: str, filename: str) -> bool: - """Checks whether a file should be opened based on its name and location in the folder journal structure""" - if journal_path[-1] in ["\\", "/"]: - journal_path = journal_path[:-1] # no trailing slash - - filename_without_extension = os.path.splitext(filename)[0] - - return ( - dirpath != journal_path # don't read any files in top level - and os.path.dirname(dirpath) != journal_path # no files in year - and os.path.basename(dirpath).isdigit() # month dir is numbers - and len(os.path.basename(dirpath)) <= 2 # month dir is 1-2 digits - and filename_without_extension.isdigit() # day of the month - and len(filename_without_extension) <= 2 # day of the month - ) - class Folder(Journal): """A Journal handling multiple files in a folder""" + # 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)] + def __init__(self, name: str = "default", **kwargs): self.entries = [] self._diff_entry_dates = [] @@ -53,12 +31,14 @@ class Folder(Journal): def open(self) -> "Folder": filenames = [] self.entries = [] - filenames = get_files(self.config["journal"]) - for filename in filenames: - with codecs.open(filename, "r", "utf-8") as f: - journal = f.read() - self.entries.extend(self._parse(journal)) - self.sort() + + if os.path.exists(self.config["journal"]): + filenames = Folder._get_files(self.config["journal"]) + for filename in filenames: + with codecs.open(filename, "r", "utf-8") as f: + journal = f.read() + self.entries.extend(self._parse(journal)) + return self def write(self) -> None: @@ -99,7 +79,7 @@ class Folder(Journal): journal_file.write(journal) # look for and delete empty files filenames = [] - filenames = get_files(self.config["journal"]) + filenames = Folder._get_files(self.config["journal"]) for filename in filenames: if os.stat(filename).st_size <= 0: os.remove(filename) @@ -133,3 +113,30 @@ class Folder(Journal): for entry in mod_entries: entry.modified = not any(entry == old_entry for old_entry in self.entries) self.entries = mod_entries + + def _get_files(journal_path: str) -> list[str]: + """Searches through sub directories starting with journal_path and find all text files that look like entries""" + for year_folder in Folder._get_year_folders(pathlib.Path(journal_path)): + for month_folder in Folder._get_month_folders(year_folder): + yield from Folder._get_day_files(month_folder) + + def _get_year_folders(path: pathlib.Path) -> list[pathlib.Path]: + for child in path.iterdir(): + if child.name.isdigit() and len(child.name) == 4 and child.is_dir(): + yield child + return + + def _get_month_folders(path: pathlib.Path) -> list[pathlib.Path]: + for child in path.iterdir(): + if child.name in Folder.MONTH_FOLDERS and path.is_dir(): + yield child + return + + def _get_day_files(path: pathlib.Path) -> list[str]: + for child in path.iterdir(): + if ( + child.stem in Folder.DAY_FILE_STEMS + and child.suffix.lower() == ".txt" + and child.is_file() + ): + yield str(child)