Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
# Dev

# 1.3.0

- Adds GHC 9.2.8 support
- Fix build errors with GHC 9.2.8
- Remove version bounds on dependency packages in Cabal file
- Adds new "cabal.project" file to project
- Handle Aeson V2.x `KeyMap` <-> `HashMap` data-type changes
- Handle Aeson V2.x `Key` <-> `Text` key-type changes
- Fix broken test-suite after project GHC upgrade
- Test with GHC 9.2.8
- Update `stack.yaml` to use LTS 20.26 (ghc 9.2.8 package-set)

# 1.2.0

- Widen QuickCheck bounds.
Expand Down
2 changes: 2 additions & 0 deletions cabal.project
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
packages: .

54 changes: 27 additions & 27 deletions medea.cabal
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
cabal-version: 2.2
name: medea
version: 1.2.0
version: 1.3.0
synopsis: A schema language for JSON.
description:
A reference implementation of a schema language, together with a conformance
Expand All @@ -18,7 +18,7 @@ maintainer: koz.ross@retro-freedom.nz
copyright: Juspay Technologies Pvt Ltd (C) 2020
category: Data
build-type: Simple
tested-with: GHC ==8.6.5 || ==8.8.4 || ==8.10.1
tested-with: GHC ==8.6.5 || ==8.8.4 || ==8.10.1 || ==9.2.8
extra-source-files:
.hspec
CHANGELOG.md
Expand Down Expand Up @@ -46,9 +46,9 @@ common test-common
import: lang-common
other-modules: TestM
build-depends:
, directory ^>=1.3.3.0
, filepath ^>=1.4.2.1
, hspec >=2.7.1 && <2.9.0
, directory
, filepath
, hspec
, medea
, mtl

Expand All @@ -75,24 +75,24 @@ library
Data.Medea.ValidJSON

build-depends:
, aeson >=1.4.6.0 && <2.0.0.0
, algebraic-graphs ^>=0.5
, bytestring ^>=0.10.8.2
, containers ^>=0.6.0.1
, deepseq ^>=1.4.4.0
, free ^>=5.1.3
, hashable >=1.2.7.0 && <1.4.0.0
, megaparsec >=8.0.0 && <10.0.0
, microlens-ghc ^>=0.4.12
, mtl ^>=2.2.2
, nonempty-containers ^>=0.3.3.0
, parser-combinators >=1.1.0 && <2.0.0
, scientific ^>=0.3.6.2
, smash ^>=0.1.1.0
, text ^>=1.2.3.1
, unordered-containers ^>=0.2.10.0
, vector ^>=0.12.0.3
, vector-instances ^>=3.4
, aeson
, algebraic-graphs
, bytestring
, containers
, deepseq
, free
, hashable
, megaparsec
, microlens-ghc
, mtl
, nonempty-containers
, parser-combinators
, scientific
, smash
, text
, unordered-containers
, vector
, vector-instances

hs-source-dirs: src

Expand All @@ -116,11 +116,11 @@ test-suite quickcheck-validator
build-depends:
, aeson
, bytestring
, hspec-core >=2.7.1 && <2.9.0
, QuickCheck >=2.13.2 && <2.15.0
, quickcheck-instances ^>=0.3.22
, hspec-core
, QuickCheck
, quickcheck-instances
, text
, unordered-containers ^>=0.2.10.0
, unordered-containers
, vector

hs-source-dirs: test/validator-quickcheck
7 changes: 4 additions & 3 deletions src/Data/Medea.hs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ import Control.Monad.RWS.Strict (RWST (..), evalRWST)
import Control.Monad.Reader (MonadReader, asks)
import Control.Monad.State.Strict (MonadState (..), gets)
import Data.Aeson (Array, Object, Value (..), decodeStrict)
import qualified Data.Aeson.KeyMap as AKM
import qualified Data.ByteString as BS
import Data.ByteString (ByteString)
import Data.Can (Can (..))
Expand Down Expand Up @@ -163,7 +164,7 @@ toValue (ValidatedJSON (_ :< f)) = case f of
NumberF n -> Number n
StringF s -> String s
ArrayF v -> Array . fmap (toValue . coerce) $ v
ObjectF hm -> Object . fmap (toValue . coerce) $ hm
ObjectF hm -> Object . fmap (toValue . coerce) $ AKM.fromHashMapText hm

-- | What schema did this validate against?
validAgainst :: ValidatedJSON -> SchemaInformation
Expand Down Expand Up @@ -332,7 +333,7 @@ checkPrim v = do
Object obj -> case par of
-- Fast path (no object spec)
Nothing ->
put (anySet, Nothing) >> (ObjectSchema :<) . ObjectF <$> traverse checkTypes obj
put (anySet, Nothing) >> (ObjectSchema :<) . ObjectF <$> traverse checkTypes (AKM.toHashMapText obj)
Just parIdent -> checkObject obj parIdent

-- check if the array satisfies the corresponding specification.
Expand Down Expand Up @@ -361,7 +362,7 @@ checkArray arr parIdent = do
-- check if object properties satisfy the corresponding specification.
checkObject :: Object -> Identifier -> ValidationM (Cofree ValidJSONF SchemaInformation)
checkObject obj parIdent = do
valsAndTypes <- pairPropertySchemaAndVal obj parIdent
valsAndTypes <- pairPropertySchemaAndVal (AKM.toHashMapText obj) parIdent
checkedObj <- traverse go valsAndTypes
pure (ObjectSchema :< ObjectF checkedObj)
where
Expand Down
2 changes: 1 addition & 1 deletion src/Data/Medea/ValidJSON.hs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ data ValidJSONF a
| StringF {-# UNPACK #-} !Text
| ArrayF {-# UNPACK #-} !(Vector a)
| ObjectF !(HashMap Text a)
deriving stock (Functor, Typeable, Data)
deriving stock (Functor, Typeable, Data, Eq)

instance Foldable ValidJSONF where
{-# INLINE foldMap #-}
Expand Down
10 changes: 2 additions & 8 deletions stack.yaml
Original file line number Diff line number Diff line change
@@ -1,12 +1,6 @@
---
resolver: lts-15.15
resolver: lts-20.26
packages:
- .
extra-deps:
- megaparsec-8.0.0@sha256:362f85e243ecbcb550e1de6e5c74ba5a50c09edaa1208c99bc5b9fd242227fc6,3808
- microlens-ghc-0.4.12@sha256:77337e3222c900011df2bd3dd55d90367ee90c6c8904f4f2826d6dd874945f35,2505
- microlens-0.4.11.2@sha256:765ec5cdd12a459e65161f0e3cdbce84652bf634d62af3911ba24e4bf8d4d944,4455
- algebraic-graphs-0.5@sha256:6eeec5ed1687ff7aa916e7bf9f02f51aaabde6f314dc0b7b1a84156974d7da73,8071
- nonempty-containers-0.3.3.0@sha256:f306bdbb271fb43057e0205293915bbfafc92f9960d89c0ea457625aad752eca,2717
- nonempty-vector-0.2.0.1@sha256:332f8d48b5de02c1ab4e52c99973d4ca42dcbce21a073ffd1b5b2da1221e113f,1753
- smash-0.1.1.0@sha256:593381bad038ff93898a8a1422c6e81fc4a2a6fb23b64afa2f758f56607b83dc,1583
- smash-0.1.3@sha256:e812275cad1fac9d6f8a479f08c1622ae5e694506883c75e26f4c93895bebca8,1351
3 changes: 2 additions & 1 deletion test/Data/Aeson/Arbitrary.hs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import Control.Monad (filterM, replicateM)
import Control.Monad.Reader (ReaderT, asks, local, runReaderT)
import Control.Monad.Trans (lift)
import Data.Aeson (Array, Object, Value (..))
import qualified Data.Aeson.KeyMap as AKM
import qualified Data.HashMap.Strict as HM
import Data.Text (Text)
import qualified Data.Vector as V
Expand Down Expand Up @@ -93,7 +94,7 @@ makeRandomObject (ObjGenOpts props optionalProps minAdditional maxAdditional) =
someOptionalProps <- filterM (\_ -> lift arbitrary) optionalProps
let keys = genKeys ++ props ++ someOptionalProps
keyVals <- mapM (\x -> (x,) <$> local dec makeRandomValue) keys
pure . HM.fromList $ keyVals
pure . AKM.fromHashMapText . HM.fromList $ keyVals

dec :: Word -> Word
dec = subtract 1
11 changes: 6 additions & 5 deletions test/validator-quickcheck/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@ import Data.Aeson.Arbitrary
isObject,
isString,
)
import qualified Data.Aeson.Key as AesonKey
import qualified Data.Aeson.KeyMap as AKM
import Data.ByteString.Lazy (toStrict)
import Data.Either (isLeft, isRight)
import Data.HashMap.Strict (filterWithKey, lookup)
import Data.Medea (Schema, loadSchemaFromFile, validate)
import Data.Text (Text)
import qualified Data.Vector as V
Expand Down Expand Up @@ -293,16 +294,16 @@ validationFail gen p scm = property $ forAll gen prop
-- Returns true iff the value is an object with the given property and the
-- property-value satisfies the predicate.
hasProperty :: Text -> (Value -> Bool) -> Object -> Bool
hasProperty propName p obj = maybe False p $ lookup propName obj
hasProperty propName p obj = maybe False p $ AKM.lookup (AesonKey.fromText propName) obj

-- Like hasProperty but is also true when the given property is absent.
hasOptionalProperty :: Text -> (Value -> Bool) -> Object -> Bool
hasOptionalProperty propName p obj = maybe True p $ lookup propName obj
hasOptionalProperty propName p obj = maybe True p $ AKM.lookup (AesonKey.fromText propName) obj

makeMapPred :: ObjGenOpts -> (Value -> Bool) -> Object -> Bool
makeMapPred (ObjGenOpts props optProps _ _) p = all p . filterWithKey (\k _ -> k `notElem` specifiedProps)
makeMapPred (ObjGenOpts props optProps _ _) p = all p . AKM.filterWithKey (\k _ -> k `notElem` specifiedProps)
where
specifiedProps = props ++ optProps
specifiedProps = fmap (AesonKey.fromText) $ props ++ optProps

testStringVals :: FilePath -> [String] -> Spec
testStringVals fp validStrings = do
Expand Down