From 243a96b6562201aa6b46592ff8f3b9d726bda042 Mon Sep 17 00:00:00 2001 From: Simon Michael Date: Thu, 2 May 2024 21:18:28 -1000 Subject: [PATCH] dev: clarify how readJournalFiles defers checks, and use a dedicated flag --- hledger-lib/Hledger/Read.hs | 29 +++++++++++++----------- hledger-lib/Hledger/Read/InputOptions.hs | 14 +++++++----- 2 files changed, 24 insertions(+), 19 deletions(-) diff --git a/hledger-lib/Hledger/Read.hs b/hledger-lib/Hledger/Read.hs index 1c0159db9..a202fe5b4 100644 --- a/hledger-lib/Hledger/Read.hs +++ b/hledger-lib/Hledger/Read.hs @@ -219,11 +219,11 @@ type PrefixedFilePath = FilePath -- we use the journal reader (for predictability). -- readJournal :: InputOpts -> Maybe FilePath -> Text -> ExceptT String IO Journal -readJournal iopts@InputOpts{strict_} mpath txt = do +readJournal iopts@InputOpts{strict_, _defer} mpath txt = do let r :: Reader IO = fromMaybe JournalReader.reader $ findReader (mformat_ iopts) mpath dbg6IO "readJournal: trying reader" (rFormat r) j <- rReadFn r iopts (fromMaybe "(string)" mpath) txt - when strict_ $ liftEither $ journalStrictChecks j + when (strict_ && not _defer) $ liftEither $ journalStrictChecks j return j -- | Read a Journal from this file, or from stdin if the file path is -, @@ -241,15 +241,14 @@ readJournal iopts@InputOpts{strict_} mpath txt = do -- generation, a rules file for converting CSV data, etc. -- -- If using --new, and if latest-file writing is enabled in input options, --- and after passing strict checks if enabled, a .latest.FILE file will be created/updated --- (for the main file only, not for included files), --- to remember the latest transaction date (and how many transactions on this date) --- successfully read. +-- and not deferred by readJournalFiles, and after passing strict checks if enabled, +-- a .latest.FILE file will be created/updated (for the main file only, not for included files), +-- to remember the latest transaction date processed. -- readJournalFile :: InputOpts -> PrefixedFilePath -> ExceptT String IO Journal -readJournalFile iopts@InputOpts{new_, new_save_} prefixedfile = do +readJournalFile iopts@InputOpts{new_, new_save_, _defer} prefixedfile = do (j, mlatestdates) <- readJournalFileAndLatestDates iopts prefixedfile - when (new_ && new_save_) $ liftIO $ + when (new_ && new_save_ && not _defer) $ liftIO $ case mlatestdates of Nothing -> return () Just (LatestDatesForFile f ds) -> saveLatestDates ds f @@ -279,9 +278,6 @@ readJournalFileAndLatestDates iopts prefixedfile = do -- | Read a Journal from each specified file path (using @readJournalFile@) -- and combine them into one; or return the first error message. --- Strict checks, if enabled, are deferred till the end. --- Writing .latest files, if enabled, is also deferred till the end, --- and happens only if strict checks pass. -- -- Combining Journals means concatenating them, basically. -- The parse state resets at the start of each file, which means that @@ -289,9 +285,16 @@ readJournalFileAndLatestDates iopts prefixedfile = do -- They do affect included child files though. -- Also the final parse state saved in the Journal does span all files. -- +-- Strict checks, if enabled, are temporarily deferred until all files are read, +-- to ensure they see the whole journal, and/or to avoid redundant work. +-- (Some checks, like assertions and ordereddates, might still be doing redundant work ?) +-- +-- Writing .latest files, if enabled, is also deferred till the end, +-- and is done only if strict checks pass. +-- readJournalFiles :: InputOpts -> [PrefixedFilePath] -> ExceptT String IO Journal -readJournalFiles iopts@InputOpts{strict_,new_,new_save_} prefixedfiles = do - let iopts' = iopts{strict_=False, new_save_=False} +readJournalFiles iopts@InputOpts{strict_, new_, new_save_} prefixedfiles = do + let iopts' = iopts{_defer=True} (j, latestdatesforfiles) <- traceOrLogAt 6 ("readJournalFiles: "++show prefixedfiles) $ readJournalFilesAndLatestDates iopts' prefixedfiles diff --git a/hledger-lib/Hledger/Read/InputOptions.hs b/hledger-lib/Hledger/Read/InputOptions.hs index f5ee2765e..6912feff3 100644 --- a/hledger-lib/Hledger/Read/InputOptions.hs +++ b/hledger-lib/Hledger/Read/InputOptions.hs @@ -29,18 +29,19 @@ data InputOpts = InputOpts { -- by a filename prefix. Nothing means try all. ,mrules_file_ :: Maybe FilePath -- ^ a conversion rules file to use (when reading CSV) ,aliases_ :: [String] -- ^ account name aliases to apply - ,anon_ :: Bool -- ^ do light obfuscation of the data. Now corresponds to --obfuscate, not the old --anon flag. - ,new_ :: Bool -- ^ read only new transactions since this file was last read - ,new_save_ :: Bool -- ^ save latest new transactions state for next time + ,anon_ :: Bool -- ^ do light obfuscation of the data ? Now corresponds to --obfuscate, not the old --anon flag. + ,new_ :: Bool -- ^ read only new transactions since this file was last read ? + ,new_save_ :: Bool -- ^ save latest new transactions state for next time ? ,pivot_ :: String -- ^ use the given field's value as the account name ,forecast_ :: Maybe DateSpan -- ^ span in which to generate forecast transactions ,verbose_tags_ :: Bool -- ^ add user-visible tags when generating/modifying transactions & postings ? ,reportspan_ :: DateSpan -- ^ a dirty hack keeping the query dates in InputOpts. This rightfully lives in ReportSpec, but is duplicated here. - ,auto_ :: Bool -- ^ generate automatic postings when journal is parsed ? + ,auto_ :: Bool -- ^ generate extra postings according to auto posting rules ? ,infer_equity_ :: Bool -- ^ infer equity conversion postings from costs ? ,infer_costs_ :: Bool -- ^ infer costs from equity conversion postings ? distinct from BalancingOpts{infer_balancing_costs_} - ,balancingopts_ :: BalancingOpts -- ^ options for balancing transactions - ,strict_ :: Bool -- ^ do extra error checking (eg, all posted accounts are declared, no prices are inferred) + ,balancingopts_ :: BalancingOpts -- ^ options for transaction balancing + ,strict_ :: Bool -- ^ do extra correctness checks ? + ,_defer :: Bool -- ^ internal flag: postpone checks, because we are processing multiple files ? ,_ioDay :: Day -- ^ today's date, for use with forecast transactions XXX this duplicates _rsDay, and should eventually be removed when it's not needed anymore. } deriving (Show) @@ -61,6 +62,7 @@ definputopts = InputOpts , infer_costs_ = False , balancingopts_ = defbalancingopts , strict_ = False + , _defer = False , _ioDay = nulldate }