packages feed

ofx 0.2.0.0 → 0.4.0.0

raw patch · 2 files changed

+65/−78 lines, 2 filesdep −explicit-exception

Dependencies removed: explicit-exception

Files

Data/OFX.hs view
@@ -55,8 +55,11 @@ --  module Data.OFX-  ( -- * The OFX data tree-    HeaderTag+  ( -- * Error handling+    Err+  +    -- * The OFX data tree+  , HeaderTag   , HeaderValue   , OFXHeader(..)   , TagName@@ -124,17 +127,20 @@   , pExceptional   ) where +--+-- # Imports+--+ import Control.Applicative   ( (<$), (<|>), (*>), many, optional,     (<$>), (<*), (<*>), pure ) import Control.Monad (replicateM)-import qualified Control.Monad.Exception.Synchronous as Ex import qualified Data.Time as T    import Text.Parsec.String (Parser) import Text.Parsec   ( lookAhead, char, manyTill, anyChar, (<?>), eof,-    try, digit, many1, spaces )+    try, digit, many1, spaces, string, choice ) import qualified Text.Parsec as P import Data.Maybe (listToMaybe) import qualified Data.Monoid as M@@ -145,9 +151,17 @@   ----- Data types+-- # Error handling -- +-- | Error handling. Errors are indicated with a Left String;+-- successes with a Right.+type Err = Either String++--+-- # Data types+--+ -- | Headers consists of simple @tag:value@ pairs; this represents the -- tag. type HeaderTag = String@@ -185,7 +199,7 @@   } deriving (Eq, Show)  ----- Parsers+-- # Parsers --  -- | Parses either a UNIX or an MS-DOS newline. According to 1.2.2,@@ -199,19 +213,29 @@ -- | Parses a character, possibly with an escape sequence. The -- greater-than sign, less-than sign, and ampersand must be entered -- with escape sequences.+--+-- According to OFX spec section 2.3.2.1, ampersands, less-than signs,+-- and greater-than signs must appear as entities.  However some banks+-- deliver broken OFX files that do not use entities for ampersands+-- (and possibly for less-than or greater-than signs too, although I+-- have not yet observed such behavior.) There is now an error message+-- that reflects this problem.  Client code can filter the OFX data+-- for known offenders before passing it to this library. escChar :: Parser Char escChar =   do     c <- anyChar     case c of       '&' -> do-        cs <- manyTill anyChar (char ';')-        case cs of-          "lt" -> return '<'-          "gt" -> return '>'-          "amp" -> return '&'-          _ -> fail $ "unrecognized esacpe sequence: \"&"-                      ++ cs ++ ";\""+        let mkParser (ch, str) = try (ch <$ string str)+        ent <- choice (map mkParser+                [('<', "lt"), ('>', "gt"), ('&', "amp")])+                <?> ( "entity (\"lt\", \"gt\", or \"amp\")\n"+                      ++ "some banks create broken OFX files. Try\n"+                      ++ "removing the ampersands from the file and\n"+                      ++ "trying again.")+        _ <- char ';'+        return ent       _ -> return c   <?> "character" @@ -286,9 +310,9 @@   <?> "OFX file"  -- | Parses an OFX date; provides an error message if the parse fails.-parseDate :: String -> Ex.Exceptional String T.ZonedTime+parseDate :: String -> Err T.ZonedTime parseDate s = case P.parse date "" s of-  Left e -> Ex.throw $ "could not parse date: " ++ s ++ ": "+  Left e -> Left $ "could not parse date: " ++ s ++ ": "             ++ show e   Right g -> return g @@ -370,7 +394,7 @@         Just _ -> return negate  ----- Manipulating trees of tags+-- # Manipulating trees of tags --  -- | Finds child tags with the given name. When a tag is found, that@@ -446,14 +470,14 @@ -- | Finds the first tag (either this tag or any children) that has -- the given name and that is a data tag. Gives an error message if -- the tag is not found.-required :: TagName -> Tag -> Ex.Exceptional String TagData+required :: TagName -> Tag -> Err TagData required n t = case findData n t of-  Nothing -> Ex.throw $ "required tag missing: " ++ n+  Nothing -> Left $ "required tag missing: " ++ n   Just r -> return r   ----- OFX data+-- # OFX data --   -- | OFX transaction types. These are used in STMTTRN aggregates, see@@ -664,13 +688,13 @@   | ACREDITLINE   deriving (Eq, Show, Ord) -acctType :: String -> Ex.Exceptional String AcctType+acctType :: String -> Err AcctType acctType s   | s == "CHECKING" = return ACHECKING   | s == "SAVINGS" = return ASAVINGS   | s == "MONEYMRKT" = return AMONEYMRKT   | s == "CREDITLINE" = return ACREDITLINE-  | otherwise = Ex.throw $ "unrecognized account type: " ++ s+  | otherwise = Left $ "unrecognized account type: " ++ s  -- | Holds all data both for CURRENCY and for ORIGCURRENCY. data CurrencyData = CurrencyData@@ -689,7 +713,7 @@   deriving (Eq, Show)  ----- Helpers to build aggregates+-- # Helpers to build aggregates -- trnType :: TagData -> Maybe TrnType trnType d = case d of@@ -712,13 +736,15 @@   "OTHER" -> Just TOTHER   _ -> Nothing + -- | Gets a single Transaction from a tag. The tag should be the one -- named STMTTRN. Fails with an error message if any required field -- was not present.-transaction :: Tag -> Ex.Exceptional String Transaction+transaction :: Tag -> Err Transaction transaction t = do+  let fromMaybe e = maybe (Left e) Right   trntyStr <- required "TRNTYPE" t-  trnTy <- Ex.fromMaybe ("could not parse transaction type: " ++ trntyStr)+  trnTy <- fromMaybe ("could not parse transaction type: " ++ trntyStr)            $ trnType trntyStr    dtpStr <- required "DTPOSTED" t@@ -738,7 +764,7 @@       Nothing -> return Nothing       Just d ->          maybe (return Nothing)-          (Ex.fromMaybe ("could not parse correct action: " ++ d))+          (fromMaybe ("could not parse correct action: " ++ d))         . safeRead         $ d   let srvrtid = findData "SRVRTID" t@@ -785,10 +811,10 @@   -- ^ The tag which contains the PAYEE tag, if there is one. This   -- would typically be a STMTTRN tag. -  -> Maybe (Ex.Exceptional String Payee)+  -> Maybe (Err Payee)   -- ^ Nothing if there is no PAYEE tag. Just if a PAYEE tag is found,-  -- with an Exception if the tag is lacking a required element, or a-  -- Success if the tag is successfully parsed.+  -- with a Left if the tag is lacking a required element, or a+  -- Right if the tag is successfully parsed.   --   -- If there is more than one PAYEE tag, only the first one is   -- considered.@@ -806,14 +832,14 @@       <*> required "PHONE" t    -currency :: Tag -> Maybe (Ex.Exceptional String Currency)+currency :: Tag -> Maybe (Err Currency) currency   = fmap (fmap Currency)   . fmap currencyData   . listToMaybe   . find "CURRENCY" -origCurrency :: Tag -> Maybe (Ex.Exceptional String OrigCurrency)+origCurrency :: Tag -> Maybe (Err OrigCurrency) origCurrency   = fmap (fmap OrigCurrency)   . fmap currencyData@@ -826,12 +852,12 @@   :: Tag   -- ^ The tag that contains the data, e.g. CURRENCY or ORIGCURRENCY. -  -> Ex.Exceptional String CurrencyData+  -> Err CurrencyData currencyData t = CurrencyData   <$> required "CURRATE" t   <*> required "CURSYM" t -bankAcctTo :: Tag -> Maybe (Ex.Exceptional String BankAcctTo)+bankAcctTo :: Tag -> Maybe (Err BankAcctTo) bankAcctTo = fmap getTo . listToMaybe . find "BANKACCTTO"   where     getTo t = BankAcctTo@@ -841,7 +867,7 @@       <*> (required "ACCTTYPE" t >>= acctType)       <*> pure (findData "ACCTKEY" t) -ccAcctTo :: Tag -> Maybe (Ex.Exceptional String CCAcctTo)+ccAcctTo :: Tag -> Maybe (Err CCAcctTo) ccAcctTo = fmap getTo . listToMaybe . find "CCACCTTO"   where     getTo t = CCAcctTo@@ -859,11 +885,11 @@ -- library.) In case of the former, you can manually parse the -- transaction information yourself using functions like -- 'pathData'. In case of the latter, please send bugreports :-)-transactions :: OFXFile -> Ex.Exceptional String [Transaction]+transactions :: OFXFile -> Err [Transaction] transactions = mapM transaction . find "STMTTRN" . fTag  ----- Pretty printers+-- # Pretty printers -- pPayee :: Payee -> Doc pPayee p = hang "Payee:" 2 ls@@ -945,8 +971,8 @@ pExceptional   :: (e -> Doc)   -> (a -> Doc)-  -> Ex.Exceptional e a+  -> Either e a   -> Doc pExceptional fe fa =-  Ex.switch (\e -> hang "Exception:" 2 $ parens (fe e))-            (\g -> hang "Success:" 2 $ parens (fa g))+  either (\e -> hang "Exception:" 2 $ parens (fe e))+         (\g -> hang "Success:" 2 $ parens (fa g))
ofx.cabal view
@@ -1,21 +1,6 @@--- Initial ofx.cabal generated by cabal init.  For further documentation, --- see http://haskell.org/cabal/users-guide/---- The name of the package. name:                ofx---- The package version.  See the Haskell package versioning policy (PVP) --- for standards guiding when and how versions should be incremented.--- http://www.haskell.org/haskellwiki/Package_versioning_policy--- PVP summary:      +-+------- breaking API changes---                   | | +----- non-breaking API additions---                   | | | +--- code changes with no API change-version:             0.2.0.0---- A short (one-line) description of the package.+version:             0.4.0.0 synopsis:            Parser for OFX data---- A longer description of the package. description:    A parser for Open Financial Exchange (OFX) financial data. This@@ -43,51 +28,27 @@    The OFX spec is available at <http://www.ofx.net> --- URL for the project homepage or repository. homepage:            http://www.github.com/massysett/ofx---- The license under which the package is released. license:             BSD3---- The file containing the license text. license-file:        LICENSE---- The package author(s). author:              Omari Norman---- An email address to which users can send suggestions, bug reports, and --- patches. maintainer:          omari@smileystation.com---- A copyright notice.--- copyright:           - category:            Finance- build-type:          Simple---- Constraint on the version of Cabal needed to build this package. cabal-version:       >=1.8 - source-repository head   type: git   location: git://github.com/massysett/ofx.git  library-  -- Modules exported by the library.   ghc-options: -Wall    exposed-modules:       Data.OFX   -  -- Modules included in this library but not exported.-  -- other-modules:       -  -  -- Other library packages from which modules are imported.   build-depends:       base ==4.6.*-    , explicit-exception ==0.1.*     , parsec ==3.1.*     , pretty ==1.1.*     , time ==1.4.*