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
This commit is contained in:
Micah Jerome Ellison 2023-03-06 10:54:04 -08:00
parent c5236fee7c
commit 93e475b14e

View file

@ -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"])
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))
self.sort()
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)