packages feed

hgrib 0.3.0.0 → 0.3.1.0

raw patch · 4 files changed

+94/−16 lines, 4 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

- Data.Grib.Exception: [Grib7777NotFound] :: ErrorCode
- Data.Grib.Exception: [GribArrayTooSmall] :: ErrorCode
- Data.Grib.Exception: [GribBufferTooSmall] :: ErrorCode
- Data.Grib.Exception: [GribCodeNotFoundInTable] :: ErrorCode
- Data.Grib.Exception: [GribConceptNoMatch] :: ErrorCode
- Data.Grib.Exception: [GribConstantField] :: ErrorCode
- Data.Grib.Exception: [GribCorruptedIndex] :: ErrorCode
- Data.Grib.Exception: [GribDecodingError] :: ErrorCode
- Data.Grib.Exception: [GribDifferentEdition] :: ErrorCode
- Data.Grib.Exception: [GribEncodingError] :: ErrorCode
- Data.Grib.Exception: [GribEndOfFile] :: ErrorCode
- Data.Grib.Exception: [GribEndOfIndex] :: ErrorCode
- Data.Grib.Exception: [GribEnd] :: ErrorCode
- Data.Grib.Exception: [GribException] :: ErrorCode -> GribException
- Data.Grib.Exception: [GribFileNotFound] :: ErrorCode
- Data.Grib.Exception: [GribGeocalculusProblem] :: ErrorCode
- Data.Grib.Exception: [GribInternalArrayTooSmall] :: ErrorCode
- Data.Grib.Exception: [GribInternalError] :: ErrorCode
- Data.Grib.Exception: [GribInvalidArgument] :: ErrorCode
- Data.Grib.Exception: [GribInvalidBpv] :: ErrorCode
- Data.Grib.Exception: [GribInvalidFile] :: ErrorCode
- Data.Grib.Exception: [GribInvalidGrib] :: ErrorCode
- Data.Grib.Exception: [GribInvalidIndex] :: ErrorCode
- Data.Grib.Exception: [GribInvalidIterator] :: ErrorCode
- Data.Grib.Exception: [GribInvalidKeyValue] :: ErrorCode
- Data.Grib.Exception: [GribInvalidKeysIterator] :: ErrorCode
- Data.Grib.Exception: [GribInvalidMessage] :: ErrorCode
- Data.Grib.Exception: [GribInvalidNearest] :: ErrorCode
- Data.Grib.Exception: [GribInvalidOrderby] :: ErrorCode
- Data.Grib.Exception: [GribInvalidSectionNumber] :: ErrorCode
- Data.Grib.Exception: [GribInvalidType] :: ErrorCode
- Data.Grib.Exception: [GribIoProblem] :: ErrorCode
- Data.Grib.Exception: [GribMessageMalformed] :: ErrorCode
- Data.Grib.Exception: [GribMessageTooLarge] :: ErrorCode
- Data.Grib.Exception: [GribMissingKey] :: ErrorCode
- Data.Grib.Exception: [GribNoDefinitions] :: ErrorCode
- Data.Grib.Exception: [GribNoMoreInSet] :: ErrorCode
- Data.Grib.Exception: [GribNoValues] :: ErrorCode
- Data.Grib.Exception: [GribNotFound] :: ErrorCode
- Data.Grib.Exception: [GribNotImplemented] :: ErrorCode
- Data.Grib.Exception: [GribNullHandle] :: ErrorCode
- Data.Grib.Exception: [GribNullIndex] :: ErrorCode
- Data.Grib.Exception: [GribOutOfArea] :: ErrorCode
- Data.Grib.Exception: [GribOutOfMemory] :: ErrorCode
- Data.Grib.Exception: [GribPrematureEndOfFile] :: ErrorCode
- Data.Grib.Exception: [GribReadOnly] :: ErrorCode
- Data.Grib.Exception: [GribSuccess] :: ErrorCode
- Data.Grib.Exception: [GribSwitchNoMatch] :: ErrorCode
- Data.Grib.Exception: [GribUnderflow] :: ErrorCode
- Data.Grib.Exception: [GribValueCannotBeMissing] :: ErrorCode
- Data.Grib.Exception: [GribValueDifferent] :: ErrorCode
- Data.Grib.Exception: [GribWrongArraySize] :: ErrorCode
- Data.Grib.Exception: [GribWrongGrid] :: ErrorCode
- Data.Grib.Exception: [GribWrongLength] :: ErrorCode
- Data.Grib.Exception: [GribWrongStepUnit] :: ErrorCode
- Data.Grib.Exception: [GribWrongStep] :: ErrorCode
- Data.Grib.Exception: [GribWrongType] :: ErrorCode
- Data.Grib.Exception: [NullPtrReturned] :: GribException
- Data.Grib.Exception: instance Exception GribException
- Data.Grib.Exception: instance Show GribException
- Data.Grib.Raw.CFile: [AppendMode] :: IOMode
- Data.Grib.Raw.CFile: [ReadMode] :: IOMode
- Data.Grib.Raw.CFile: [ReadWriteMode] :: IOMode
- Data.Grib.Raw.CFile: [WriteMode] :: IOMode
- Data.Grib.Raw.Context: [GribContext] :: (Ptr (GribContext)) -> GribContext
- Data.Grib.Raw.Context: instance Eq GribContext
- Data.Grib.Raw.Context: instance Show GribContext
- Data.Grib.Raw.Handle: [GribHandle] :: (ForeignPtr (GribHandle)) -> GribHandle
- Data.Grib.Raw.Handle: [GribMultiHandle] :: (ForeignPtr (GribMultiHandle)) -> GribMultiHandle
- Data.Grib.Raw.Handle: instance Eq GribHandle
- Data.Grib.Raw.Handle: instance Eq GribMultiHandle
- Data.Grib.Raw.Handle: instance Show GribHandle
- Data.Grib.Raw.Handle: instance Show GribMultiHandle
- Data.Grib.Raw.Index: [GribIndex] :: (ForeignPtr (GribIndex)) -> GribIndex
- Data.Grib.Raw.Iterator: [GribIterator] :: (Ptr (GribIterator)) -> GribIterator
- Data.Grib.Raw.Iterator: instance Eq GribIterator
- Data.Grib.Raw.Iterator: instance Show GribIterator
- Data.Grib.Raw.KeysIterator: [GribKeysIteratorAllKeys] :: GribKeysIteratorFlag
- Data.Grib.Raw.KeysIterator: [GribKeysIteratorSkipCoded] :: GribKeysIteratorFlag
- Data.Grib.Raw.KeysIterator: [GribKeysIteratorSkipComputed] :: GribKeysIteratorFlag
- Data.Grib.Raw.KeysIterator: [GribKeysIteratorSkipDuplicates] :: GribKeysIteratorFlag
- Data.Grib.Raw.KeysIterator: [GribKeysIteratorSkipEditionSpecific] :: GribKeysIteratorFlag
- Data.Grib.Raw.KeysIterator: [GribKeysIteratorSkipFunction] :: GribKeysIteratorFlag
- Data.Grib.Raw.KeysIterator: [GribKeysIteratorSkipOptional] :: GribKeysIteratorFlag
- Data.Grib.Raw.KeysIterator: [GribKeysIteratorSkipReadOnly] :: GribKeysIteratorFlag
- Data.Grib.Raw.KeysIterator: [GribKeysIterator] :: (Ptr (GribKeysIterator)) -> GribKeysIterator
- Data.Grib.Raw.KeysIterator: instance Enum GribKeysIteratorFlag
- Data.Grib.Raw.KeysIterator: instance Eq GribKeysIterator
- Data.Grib.Raw.KeysIterator: instance Eq GribKeysIteratorFlag
- Data.Grib.Raw.KeysIterator: instance Show GribKeysIterator
- Data.Grib.Raw.KeysIterator: instance Show GribKeysIteratorFlag
- Data.Grib.Raw.Nearest: [GribNearestSameData] :: GribNearestFlag
- Data.Grib.Raw.Nearest: [GribNearestSameGrid] :: GribNearestFlag
- Data.Grib.Raw.Nearest: [GribNearestSamePoint] :: GribNearestFlag
- Data.Grib.Raw.Nearest: [GribNearest] :: (Ptr (GribNearest)) -> GribNearest
- Data.Grib.Raw.Nearest: instance Enum GribNearestFlag
- Data.Grib.Raw.Nearest: instance Eq GribNearest
- Data.Grib.Raw.Nearest: instance Eq GribNearestFlag
- Data.Grib.Raw.Nearest: instance Show GribNearest
- Data.Grib.Raw.Nearest: instance Show GribNearestFlag
+ Data.Grib: data SkipMessage
+ Data.Grib: instance GHC.Exception.Exception Data.Grib.SkipMessage
+ Data.Grib: instance GHC.Show.Show Data.Grib.SkipMessage
+ Data.Grib: skipMessage :: GribIO a
+ Data.Grib: skipMessageIf :: (a -> Bool) -> GribIO a -> GribIO a
+ Data.Grib: skipMessageIf_ :: (a -> Bool) -> GribIO a -> GribIO ()
+ Data.Grib.Exception: Grib7777NotFound :: ErrorCode
+ Data.Grib.Exception: GribArrayTooSmall :: ErrorCode
+ Data.Grib.Exception: GribBufferTooSmall :: ErrorCode
+ Data.Grib.Exception: GribCodeNotFoundInTable :: ErrorCode
+ Data.Grib.Exception: GribConceptNoMatch :: ErrorCode
+ Data.Grib.Exception: GribConstantField :: ErrorCode
+ Data.Grib.Exception: GribCorruptedIndex :: ErrorCode
+ Data.Grib.Exception: GribDecodingError :: ErrorCode
+ Data.Grib.Exception: GribDifferentEdition :: ErrorCode
+ Data.Grib.Exception: GribEncodingError :: ErrorCode
+ Data.Grib.Exception: GribEnd :: ErrorCode
+ Data.Grib.Exception: GribEndOfFile :: ErrorCode
+ Data.Grib.Exception: GribEndOfIndex :: ErrorCode
+ Data.Grib.Exception: GribException :: ErrorCode -> GribException
+ Data.Grib.Exception: GribFileNotFound :: ErrorCode
+ Data.Grib.Exception: GribGeocalculusProblem :: ErrorCode
+ Data.Grib.Exception: GribInternalArrayTooSmall :: ErrorCode
+ Data.Grib.Exception: GribInternalError :: ErrorCode
+ Data.Grib.Exception: GribInvalidArgument :: ErrorCode
+ Data.Grib.Exception: GribInvalidBpv :: ErrorCode
+ Data.Grib.Exception: GribInvalidFile :: ErrorCode
+ Data.Grib.Exception: GribInvalidGrib :: ErrorCode
+ Data.Grib.Exception: GribInvalidIndex :: ErrorCode
+ Data.Grib.Exception: GribInvalidIterator :: ErrorCode
+ Data.Grib.Exception: GribInvalidKeyValue :: ErrorCode
+ Data.Grib.Exception: GribInvalidKeysIterator :: ErrorCode
+ Data.Grib.Exception: GribInvalidMessage :: ErrorCode
+ Data.Grib.Exception: GribInvalidNearest :: ErrorCode
+ Data.Grib.Exception: GribInvalidOrderby :: ErrorCode
+ Data.Grib.Exception: GribInvalidSectionNumber :: ErrorCode
+ Data.Grib.Exception: GribInvalidType :: ErrorCode
+ Data.Grib.Exception: GribIoProblem :: ErrorCode
+ Data.Grib.Exception: GribMessageMalformed :: ErrorCode
+ Data.Grib.Exception: GribMessageTooLarge :: ErrorCode
+ Data.Grib.Exception: GribMissingKey :: ErrorCode
+ Data.Grib.Exception: GribNoDefinitions :: ErrorCode
+ Data.Grib.Exception: GribNoMoreInSet :: ErrorCode
+ Data.Grib.Exception: GribNoValues :: ErrorCode
+ Data.Grib.Exception: GribNotFound :: ErrorCode
+ Data.Grib.Exception: GribNotImplemented :: ErrorCode
+ Data.Grib.Exception: GribNullHandle :: ErrorCode
+ Data.Grib.Exception: GribNullIndex :: ErrorCode
+ Data.Grib.Exception: GribOutOfArea :: ErrorCode
+ Data.Grib.Exception: GribOutOfMemory :: ErrorCode
+ Data.Grib.Exception: GribPrematureEndOfFile :: ErrorCode
+ Data.Grib.Exception: GribReadOnly :: ErrorCode
+ Data.Grib.Exception: GribSuccess :: ErrorCode
+ Data.Grib.Exception: GribSwitchNoMatch :: ErrorCode
+ Data.Grib.Exception: GribUnderflow :: ErrorCode
+ Data.Grib.Exception: GribValueCannotBeMissing :: ErrorCode
+ Data.Grib.Exception: GribValueDifferent :: ErrorCode
+ Data.Grib.Exception: GribWrongArraySize :: ErrorCode
+ Data.Grib.Exception: GribWrongGrid :: ErrorCode
+ Data.Grib.Exception: GribWrongLength :: ErrorCode
+ Data.Grib.Exception: GribWrongStep :: ErrorCode
+ Data.Grib.Exception: GribWrongStepUnit :: ErrorCode
+ Data.Grib.Exception: GribWrongType :: ErrorCode
+ Data.Grib.Exception: NullPtrReturned :: GribException
+ Data.Grib.Exception: instance GHC.Exception.Exception Data.Grib.Exception.GribException
+ Data.Grib.Exception: instance GHC.Show.Show Data.Grib.Exception.GribException
+ Data.Grib.Raw.CFile: AppendMode :: IOMode
+ Data.Grib.Raw.CFile: ReadMode :: IOMode
+ Data.Grib.Raw.CFile: ReadWriteMode :: IOMode
+ Data.Grib.Raw.CFile: WriteMode :: IOMode
+ Data.Grib.Raw.Context: GribContext :: (Ptr (GribContext)) -> GribContext
+ Data.Grib.Raw.Context: instance GHC.Classes.Eq Data.Grib.Raw.Context.GribContext
+ Data.Grib.Raw.Context: instance GHC.Show.Show Data.Grib.Raw.Context.GribContext
+ Data.Grib.Raw.Handle: GribHandle :: (ForeignPtr (GribHandle)) -> GribHandle
+ Data.Grib.Raw.Handle: GribMultiHandle :: (ForeignPtr (GribMultiHandle)) -> GribMultiHandle
+ Data.Grib.Raw.Handle: instance GHC.Classes.Eq Data.Grib.Raw.Handle.GribHandle
+ Data.Grib.Raw.Handle: instance GHC.Classes.Eq Data.Grib.Raw.Handle.GribMultiHandle
+ Data.Grib.Raw.Handle: instance GHC.Show.Show Data.Grib.Raw.Handle.GribHandle
+ Data.Grib.Raw.Handle: instance GHC.Show.Show Data.Grib.Raw.Handle.GribMultiHandle
+ Data.Grib.Raw.Index: GribIndex :: (ForeignPtr (GribIndex)) -> GribIndex
+ Data.Grib.Raw.Iterator: GribIterator :: (Ptr (GribIterator)) -> GribIterator
+ Data.Grib.Raw.Iterator: instance GHC.Classes.Eq Data.Grib.Raw.Iterator.GribIterator
+ Data.Grib.Raw.Iterator: instance GHC.Show.Show Data.Grib.Raw.Iterator.GribIterator
+ Data.Grib.Raw.KeysIterator: GribKeysIterator :: (Ptr (GribKeysIterator)) -> GribKeysIterator
+ Data.Grib.Raw.KeysIterator: GribKeysIteratorAllKeys :: GribKeysIteratorFlag
+ Data.Grib.Raw.KeysIterator: GribKeysIteratorSkipCoded :: GribKeysIteratorFlag
+ Data.Grib.Raw.KeysIterator: GribKeysIteratorSkipComputed :: GribKeysIteratorFlag
+ Data.Grib.Raw.KeysIterator: GribKeysIteratorSkipDuplicates :: GribKeysIteratorFlag
+ Data.Grib.Raw.KeysIterator: GribKeysIteratorSkipEditionSpecific :: GribKeysIteratorFlag
+ Data.Grib.Raw.KeysIterator: GribKeysIteratorSkipFunction :: GribKeysIteratorFlag
+ Data.Grib.Raw.KeysIterator: GribKeysIteratorSkipOptional :: GribKeysIteratorFlag
+ Data.Grib.Raw.KeysIterator: GribKeysIteratorSkipReadOnly :: GribKeysIteratorFlag
+ Data.Grib.Raw.KeysIterator: instance GHC.Classes.Eq Data.Grib.Raw.KeysIterator.GribKeysIterator
+ Data.Grib.Raw.KeysIterator: instance GHC.Classes.Eq Data.Grib.Raw.KeysIterator.GribKeysIteratorFlag
+ Data.Grib.Raw.KeysIterator: instance GHC.Enum.Enum Data.Grib.Raw.KeysIterator.GribKeysIteratorFlag
+ Data.Grib.Raw.KeysIterator: instance GHC.Show.Show Data.Grib.Raw.KeysIterator.GribKeysIterator
+ Data.Grib.Raw.KeysIterator: instance GHC.Show.Show Data.Grib.Raw.KeysIterator.GribKeysIteratorFlag
+ Data.Grib.Raw.Nearest: GribNearest :: (Ptr (GribNearest)) -> GribNearest
+ Data.Grib.Raw.Nearest: GribNearestSameData :: GribNearestFlag
+ Data.Grib.Raw.Nearest: GribNearestSameGrid :: GribNearestFlag
+ Data.Grib.Raw.Nearest: GribNearestSamePoint :: GribNearestFlag
+ Data.Grib.Raw.Nearest: instance GHC.Classes.Eq Data.Grib.Raw.Nearest.GribNearest
+ Data.Grib.Raw.Nearest: instance GHC.Classes.Eq Data.Grib.Raw.Nearest.GribNearestFlag
+ Data.Grib.Raw.Nearest: instance GHC.Enum.Enum Data.Grib.Raw.Nearest.GribNearestFlag
+ Data.Grib.Raw.Nearest: instance GHC.Show.Show Data.Grib.Raw.Nearest.GribNearest
+ Data.Grib.Raw.Nearest: instance GHC.Show.Show Data.Grib.Raw.Nearest.GribNearestFlag

Files

CHANGELOG.md view
@@ -1,5 +1,12 @@ # HGrib Change Log +## 0.3.1.0++* Added `skipMessage`, `skipMessageIf`, and `skipMessageIf_` to+  `Data.Grib`, three functions to easily skip unwanted GRIB messages+  in a file.++ ## 0.3.0.0  * Added a `GribIO` monad in `Data.Grib`, which is a higher-level
hgrib.cabal view
@@ -1,7 +1,7 @@ -- Package description for HGrib.  name:                hgrib-version:             0.3.0.0+version:             0.3.1.0 synopsis:            Unofficial bindings for GRIB API description:     Unofficial bindings to ECMWF's GRIB API library for reading WMO@@ -33,7 +33,7 @@ source-repository this   type:      git   location:  https://github.com/mjakob/hgrib.git-  tag:       0.3.0.0+  tag:       0.3.1.0  library   default-language:  Haskell2010
src/Data/Grib.hs view
@@ -9,11 +9,15 @@ Portability : portable -} +{-# LANGUAGE DeriveDataTypeable #-}+ module Data.Grib ( -- *The GRIB Monad                    GribIO                  , runGribIO                  , runGribIO_-                 , GribEnv+                 , skipMessage+                 , skipMessageIf+                 , skipMessageIf_                     -- **Get values                    --@@ -45,11 +49,17 @@                  , getIndex                  , getHandle                  , liftIO++                   -- **Auxiliary types+                 , GribEnv+                 , SkipMessage                  ) where -import Control.Monad              ( void )+import Control.Exception          ( Exception, throwIO, try )+import Control.Monad              ( void, when ) import Control.Monad.IO.Class     ( liftIO ) import Control.Monad.Trans.Reader ( ReaderT, ask, runReaderT )+import Data.Typeable              ( Typeable ) import Foreign                    ( allocaArray, allocaBytes )  -- Hack to have Applicative in base < 4.8 but avoid warning in base >= 4.8:@@ -77,6 +87,43 @@ envs :: FilePath -> IO [GribEnv] envs path = fmap (zipWith3 GribEnv (repeat path) [0..]) (handles path) +-- |If this exception is raised in 'GribIO', the message will be+-- discarded.  Normally, you simply call 'skipMessage' instead of+-- throwing this exception manually.+data SkipMessage = SkipMessage deriving (Show, Typeable)+instance Exception SkipMessage++-- |Skip the current GRIB message.  No result will be put in the+-- output list of 'runGribIO' for this message.+skipMessage :: GribIO a+skipMessage = liftIO . throwIO $ SkipMessage++-- |Skip the current GRIB message if the predicate is true.  No result+-- will be put in the output list of 'runGribIO' in this case.+skipMessageIf :: (a -> Bool)  -- ^a predicate that will be given the+                              -- result of the action+              -> GribIO a     -- ^an action to perform+              -> GribIO a+skipMessageIf p m = do { x <- m; when (p x) skipMessage; return x }++-- |Like 'skipMessageIf', but discard the result of the action.+--+-- ==== __Examples__+--+-- Sum all grid points of the first vertical level in a GRIB message:+--+-- > runGribIO "test/stage/test_uuid.grib2" $ do+-- >   skipMessageIf_ (/= 1) $ getLong "topLevel"+-- >   fmap sum getValues+skipMessageIf_ :: (a -> Bool)+               -> GribIO a+               -> GribIO ()+skipMessageIf_ p m = do { x <- m; when (p x) skipMessage }++-- A try that catches the SkipMessage exception.+trySkipMessage :: IO a -> IO (Either SkipMessage a)+trySkipMessage = try+ -- |The 'GribIO' monad is a 'ReaderT' monad transformer over the -- 'IO' monad with a 'GribEnv' environment. type GribIO = ReaderT GribEnv IO@@ -95,7 +142,9 @@ runGribIO :: FilePath  -- ^a path to a GRIB file           -> GribIO a  -- ^an action to take on each GRIB message in the file           -> IO [a]    -- ^the results of the actions-runGribIO path m = envs path >>= mapM (runReaderT m)+runGribIO path m = envs path >>= foldr k (return [])+  where k env res = trySkipMessage (runReaderT m env) >>=+                    either (const res) (\x -> fmap (x :) res)  -- |Like 'runGribIO', but discard the results. runGribIO_ :: FilePath -> GribIO a -> IO ()
test/Data/GribSpec.hs view
@@ -38,7 +38,7 @@      it "should fail with any exception raised by the action" $       runGribIO testUuidPath (liftIO $ throwIO NullPtrReturned)-        `shouldThrow` isNullPtrReturned+      `shouldThrow` isNullPtrReturned    describe "runGribIO_" $ do     it "should return unit" $@@ -52,49 +52,71 @@      it "should fail with any exception raised by the action" $       runGribIO_ testUuidPath (liftIO $ throwIO NullPtrReturned)-        `shouldThrow` isNullPtrReturned+      `shouldThrow` isNullPtrReturned +  describe "skipMessage" $+    it "should make runGribIO not return the result" $ do+      r <- runGribIO testUuidPath $ do+        l <- getLong "topLevel"+        if l == 1 then skipMessage else return l+      r `shouldBe` [2]++  describe "skipMessageIf" $+    it "should make runGribIO not return the result if the predicate is true" $+      runGribIO testUuidPath (skipMessageIf (== 1) $ getLong "topLevel")+      `shouldReturn` [2]++  describe "skipMessageIf_" $ do+    it "should make runGribIO not return () if the predicate is true" $+      runGribIO testUuidPath (skipMessageIf_ (== 1) $ getLong "topLevel")+      `shouldReturn` [()]+    it "should behave like in the documented example" $ do+      runGribIO testUuidPath $ do+        skipMessageIf_ (/= 1) $ getLong "topLevel"+        fmap sum getValues+      `shouldReturn` [31595.198486328125]+   describe "getDouble" $     it "should fail with GribNotFound if the key does not exist" $       runGribIO_ testUuidPath (getDouble "missingKey")-        `shouldThrow` isGribException GribNotFound+      `shouldThrow` isGribException GribNotFound    describe "getLong" $     it "should fail with GribNotFound if the key does not exist" $       runGribIO_ testUuidPath (getLong "missingKey")-        `shouldThrow` isGribException GribNotFound+      `shouldThrow` isGribException GribNotFound    describe "getString" $     it "should fail with GribNotFound if the key does not exist" $       runGribIO_ testUuidPath (getString "missingKey")-        `shouldThrow` isGribException GribNotFound+      `shouldThrow` isGribException GribNotFound    describe "setDouble" $ do     it "should fail with GribNotFound if the key does not exist" $       runGribIO_ testUuidPath (setDouble "missingKey" 0)-        `shouldThrow` isGribException GribNotFound+      `shouldThrow` isGribException GribNotFound      it "should fail with GribReadOnly if the key is read-only" $       runGribIO_ testUuidPath (setDouble "referenceValue" 0)-        `shouldThrow` isGribException GribReadOnly+      `shouldThrow` isGribException GribReadOnly    describe "setLong" $ do     it "should fail with GribNotFound if the key does not exist" $       runGribIO_ testUuidPath (setLong "missingKey" 0)-        `shouldThrow` isGribException GribNotFound+      `shouldThrow` isGribException GribNotFound      it "should fail with GribReadOnly if the key is read-only" $       runGribIO_ testUuidPath (setLong "getNumberOfValues" 0)-        `shouldThrow` isGribException GribReadOnly+      `shouldThrow` isGribException GribReadOnly    describe "setString" $ do     it "should fail with GribNotFound if the key does not exist" $       runGribIO_ testUuidPath (setString "missingKey" "value")-        `shouldThrow` isGribException GribNotFound+      `shouldThrow` isGribException GribNotFound      it "should fail with GribReadOnly if the key is read-only" $       runGribIO_ testUuidPath (setString "referenceValue" "value")-        `shouldThrow` isGribException GribReadOnly+      `shouldThrow` isGribException GribReadOnly    describe "getFilename" $     it "should return the name of the file being read" $