avro 0.4.4.2 → 0.4.4.3
raw patch · 11 files changed
+227/−50 lines, 11 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
Files
- avro.cabal +4/−3
- src/Data/Avro/Schema.hs +2/−2
- test/Avro/Deconflict/A/Reader.hs +23/−4
- test/Avro/Deconflict/A/Writer.hs +22/−4
- test/Avro/Deconflict/C/Reader.hs +51/−0
- test/Avro/Deconflict/C/Writer.hs +54/−0
- test/Avro/DeconflictSpec.hs +37/−4
- test/Avro/NamespaceSpec.hs +17/−0
- test/data/deconflict/reader.avsc +0/−17
- test/data/deconflict/writer.avsc +0/−16
- test/data/null-namespace.json +17/−0
avro.cabal view
@@ -1,7 +1,7 @@ cabal-version: 1.12 name: avro-version: 0.4.4.2+version: 0.4.4.3 synopsis: Avro serialization support for Haskell description: Avro serialization and deserialization support for Haskell category: Data@@ -27,10 +27,9 @@ test/data/unions.avsc test/data/enums-object.json test/data/namespace-inference.json+ test/data/null-namespace.json test/data/unions-object-a.json test/data/unions-object-b.json- test/data/deconflict/reader.avsc- test/data/deconflict/writer.avsc test/data/overlay/composite.avsc test/data/overlay/expectation.avsc test/data/overlay/primitives.avsc@@ -135,6 +134,8 @@ Avro.Deconflict.A.Writer Avro.Deconflict.B.Reader Avro.Deconflict.B.Writer+ Avro.Deconflict.C.Reader+ Avro.Deconflict.C.Writer Avro.DeconflictSpec Avro.DefaultsSpec Avro.EncodeRawSpec
src/Data/Avro/Schema.hs view
@@ -222,7 +222,7 @@ -- @ renderFullname :: TypeName -> T.Text renderFullname TN { baseName, namespace } =- T.intercalate "." namespace <> "." <> baseName+ T.intercalate "." $ namespace ++ [baseName] -- | Parses a fullname into a 'TypeName', assuming the string -- representation is valid.@@ -268,7 +268,7 @@ mkTypeName context name ns | isFullName name = parseFullname name | otherwise = case ns of- Just ns -> TN name $ T.splitOn "." ns+ Just ns -> TN name $ filter (/= "") (T.splitOn "." ns) Nothing -> TN name $ fromMaybe [] $ namespace <$> context where isFullName = isJust . T.find (== '.')
test/Avro/Deconflict/A/Reader.hs view
@@ -1,13 +1,32 @@ {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE QuasiQuotes #-} {-# LANGUAGE TemplateHaskell #-}-module Avro.Deconflict.A.Reader-where -import Data.Avro.Deconflict+module Avro.Deconflict.A.Reader where+ import Data.Avro.Deriving+import Text.RawString.QQ -deriveAvro "test/data/deconflict/reader.avsc"+deriveAvroFromByteString [r|+{+ "type": "record",+ "name": "Outer",+ "fields": [+ { "name": "name", "type": "string" },+ { "name": "inner", "type": {+ "type": "record",+ "name": "Inner",+ "fields": [+ { "name": "id", "type": "int" },+ { "name": "smell", "type": ["null", "string"], "default": null }+ ]+ }+ },+ { "name": "other", "type": "Inner" }+ ]+}+|] sampleValue :: Outer sampleValue = Outer "Peone" (Inner 3 Nothing) (Inner 5 Nothing)
test/Avro/Deconflict/A/Writer.hs view
@@ -1,13 +1,31 @@ {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE QuasiQuotes #-} {-# LANGUAGE TemplateHaskell #-}-module Avro.Deconflict.A.Writer-where -import Data.Avro.Deconflict+module Avro.Deconflict.A.Writer where+ import Data.Avro.Deriving+import Text.RawString.QQ -deriveAvro "test/data/deconflict/writer.avsc"+deriveAvroFromByteString [r|+{+ "type": "record",+ "name": "Outer",+ "fields": [+ { "name": "name", "type": "string" },+ { "name": "inner", "type": {+ "type": "record",+ "name": "Inner",+ "fields": [+ { "name": "id", "type": "int" }+ ]+ }+ },+ { "name": "other", "type": "Inner" }+ ]+}+|] sampleValue :: Outer sampleValue = Outer "Peone" (Inner 3) (Inner 5)
+ test/Avro/Deconflict/C/Reader.hs view
@@ -0,0 +1,51 @@+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE QuasiQuotes #-}+{-# LANGUAGE TemplateHaskell #-}++module Avro.Deconflict.C.Reader where++import Data.Avro.Deriving+import Text.RawString.QQ++deriveAvroFromByteString [r|+[+{+ "type": "record",+ "name": "Foo",+ "namespace": "avro.test",+ "fields": [+ { "name": "fieldA",+ "type": ["null", {+ "type": "record",+ "name": "Goo",+ "fields": [+ { "name": "fieldB1",+ "type": {+ "type": "record",+ "name": "Moo",+ "fields": [+ { "name": "name", "type": "string" }+ ]+ }+ },+ { "name": "fieldB2", "type": "Moo" }+ ]+ }]+ }+ ]+}+]+|]++sampleValue :: Foo+sampleValue = Foo+ { fooFieldA = Just Goo+ { gooFieldB1 = Moo+ { mooName = "X"+ }+ , gooFieldB2 = Moo+ { mooName = "X"+ }+ }+ }
+ test/Avro/Deconflict/C/Writer.hs view
@@ -0,0 +1,54 @@+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE QuasiQuotes #-}+{-# LANGUAGE TemplateHaskell #-}++module Avro.Deconflict.C.Writer where++import Data.Avro.Deriving+import Text.RawString.QQ++deriveAvroFromByteString [r|+[+{+ "type": "record",+ "name": "Foo",+ "namespace": "avro.test",+ "fields": [+ { "name": "fieldA",+ "type": ["null", {+ "type": "record",+ "name": "Goo",+ "fields": [+ { "name": "fieldB1",+ "type": {+ "type": "record",+ "name": "Moo",+ "fields": [+ { "name": "name", "type": "string" },+ { "name": "fullName", "type": ["null", "string"], "default": null }+ ]+ }+ },+ { "name": "fieldB2", "type": "Moo" }+ ]+ }]+ }+ ]+}+]+|]++sampleValue :: Foo+sampleValue = Foo+ { fooFieldA = Just Goo+ { gooFieldB1 = Moo+ { mooName = "X"+ , mooFullName = Nothing+ }+ , gooFieldB2 = Moo+ { mooName = "X"+ , mooFullName = Nothing+ }+ }+ }
test/Avro/DeconflictSpec.hs view
@@ -14,6 +14,8 @@ import qualified Avro.Deconflict.A.Writer as AW import qualified Avro.Deconflict.B.Reader as BR import qualified Avro.Deconflict.B.Writer as BW+import qualified Avro.Deconflict.C.Reader as CR+import qualified Avro.Deconflict.C.Writer as CW import qualified Data.Avro.Decode as A (decodeAvro) import qualified Data.Avro.Decode.Lazy as AL import qualified Data.Avro.Decode.Lazy.Deconflict as AL@@ -76,11 +78,11 @@ AL.decodeContainer w `shouldBe` [ Right BR.sampleValue ] it "should deconflict lazy value" $ do- let payload = A.encode AW.sampleValue- let decodedAvro = AL.decodeAvro AW.schema'Outer payload- let deconflicted = AL.deconflict AW.schema'Outer AR.schema'Outer decodedAvro+ let payload = A.encode BW.sampleValue+ let decodedAvro = AL.decodeAvro BW.schema'Foo payload+ let deconflicted = AL.deconflict BW.schema'Foo BR.schema'Foo decodedAvro - AL.fromLazyAvro deconflicted `shouldBe` Success AR.sampleValue+ AL.fromLazyAvro deconflicted `shouldBe` Success BR.sampleValue it "should deconflict strict container" $ do w <- A.encodeContainer [[BW.sampleValue]]@@ -92,3 +94,34 @@ let Right deconflicted = A.deconflict BW.schema'Foo BR.schema'Foo decodedAvro A.fromAvro deconflicted `shouldBe` Success BR.sampleValue++ describe "Type C" $ do+ it "should deconflict complex type" $ do+ let payload = A.encode CW.sampleValue+ let decodedAvro = AL.decodeAvro CW.schema'Foo payload+ let res = AL.deconflict CW.schema'Foo CR.schema'Foo decodedAvro++ AL.fromLazyAvro res `shouldBe` Success CR.sampleValue++ it "should deconflict lazy container" $ do+ w <- liftIO $ A.encodeContainer [[ CW.sampleValue ]]+ AL.decodeContainer w `shouldBe` [ Right CR.sampleValue ]++ it "should deconflict lazy value" $ do+ let payload = A.encode CW.sampleValue+ let decodedAvro = AL.decodeAvro CW.schema'Foo payload+ let deconflicted = AL.deconflict CW.schema'Foo CR.schema'Foo decodedAvro++ AL.fromLazyAvro deconflicted `shouldBe` Success CR.sampleValue++ it "should deconflict strict container" $ do+ w <- A.encodeContainer [[CW.sampleValue]]+ A.decodeContainer w `shouldBe` [[CR.sampleValue]]++ it "should deconflict strict value" $ do+ let payload = A.encode CW.sampleValue+ let Right decodedAvro = A.decodeAvro CW.schema'Foo payload+ let Right deconflicted = A.deconflict CW.schema'Foo CR.schema'Foo decodedAvro++ A.fromAvro deconflicted `shouldBe` Success CR.sampleValue+
test/Avro/NamespaceSpec.hs view
@@ -28,6 +28,11 @@ let expectedJSONSchema :: Aeson.Value Just expectedJSONSchema = head <$> Aeson.decode schemas Aeson.toJSON expected `shouldBe` expectedJSONSchema+ it "should render names in the null namespace with no leading '.'" $+ renderFullname (TN "FooType" []) `shouldBe` "FooType"+ nullNamespaceSchema <- runIO $ getFileName "test/data/null-namespace.json" >>= LBS.readFile+ it "should generate JSON with null namespaces rendered correctly" $+ Aeson.decode nullNamespaceSchema `shouldBe` Just expectedNullNamespace expected :: Schema expected = Record@@ -58,6 +63,18 @@ , field "bazzy" $ NamedType "com.example.Bazzy" ] }+++expectedNullNamespace :: Schema+expectedNullNamespace = Record+ { name = "Foo"+ , aliases = []+ , doc = Just "An example schema to test null namespace handling."+ , order = Just Ascending+ , fields = [field "bar" $ NamedType "Bar", field "baz" $ NamedType "com.example.Baz"]+ }+ where field name schema = Field name [] Nothing (Just Ascending) schema Nothing+ getFileName :: FilePath -> IO FilePath getFileName p = do
− test/data/deconflict/reader.avsc
@@ -1,17 +0,0 @@-{- "type": "record",- "name": "Outer",- "fields": [- { "name": "name", "type": "string" },- { "name": "inner", "type": {- "type": "record",- "name": "Inner",- "fields": [- { "name": "id", "type": "int" },- { "name": "smell", "type": ["null", "string"], "default": null }- ]- }- },- { "name": "other", "type": "Inner" }- ]-}
− test/data/deconflict/writer.avsc
@@ -1,16 +0,0 @@-{- "type": "record",- "name": "Outer",- "fields": [- { "name": "name", "type": "string" },- { "name": "inner", "type": {- "type": "record",- "name": "Inner",- "fields": [- { "name": "id", "type": "int" }- ]- }- },- { "name": "other", "type": "Inner" }- ]-}
+ test/data/null-namespace.json view
@@ -0,0 +1,17 @@+{+ "type" : "record",+ "name" : "Foo",+ "namespace" : "",+ "aliases" : [],+ "doc": "An example schema to test null namespace handling.",+ "fields" : [+ {+ "name" : "bar",+ "type" : "Bar"+ },+ {+ "name" : "baz",+ "type" : "com.example.Baz"+ }+ ]+}