greskell-core 0.1.3.7 → 1.0.0.0
raw patch · 8 files changed
+69/−43 lines, 8 filesdep ~aesondep ~doctestdep ~hashablePVP ok
version bump matches the API change (PVP)
Dependency ranges changed: aeson, doctest, hashable, semigroups
API changes (from Hackage documentation)
- Data.Greskell.GraphSON: instance Data.Greskell.GraphSON.FromGraphSON a => Data.Greskell.GraphSON.FromGraphSON (Data.Semigroup.Option a)
+ Data.Greskell.GraphSON: instance Data.Greskell.GraphSON.FromGraphSON Data.Aeson.Key.Key
+ Data.Greskell.GraphSON: instance Data.Greskell.GraphSON.FromGraphSON v => Data.Greskell.GraphSON.FromGraphSON (Data.Aeson.KeyMap.KeyMap v)
- Data.Greskell.GMap: parseToGMap :: (IsList (c k v), Item (c k v) ~ (k, v)) => (s -> Parser k) -> (s -> Parser v) -> (HashMap Text s -> Parser (c k v)) -> Either (HashMap Text s) (Vector s) -> Parser (GMap c k v)
+ Data.Greskell.GMap: parseToGMap :: (IsList (c k v), Item (c k v) ~ (k, v)) => (s -> Parser k) -> (s -> Parser v) -> (KeyMap s -> Parser (c k v)) -> Either (KeyMap s) (Vector s) -> Parser (GMap c k v)
- Data.Greskell.GMap: parseToGMapEntry :: FromJSONKey k => (s -> Parser k) -> (s -> Parser v) -> Either (HashMap Text s) (Vector s) -> Parser (GMapEntry k v)
+ Data.Greskell.GMap: parseToGMapEntry :: FromJSONKey k => (s -> Parser k) -> (s -> Parser v) -> Either (KeyMap s) (Vector s) -> Parser (GMapEntry k v)
- Data.Greskell.GraphSON: (.:) :: FromGraphSON a => HashMap Text GValue -> Text -> Parser a
+ Data.Greskell.GraphSON: (.:) :: FromGraphSON a => KeyMap GValue -> Key -> Parser a
- Data.Greskell.GraphSON: GObject :: !HashMap Text GValue -> GValueBody
+ Data.Greskell.GraphSON: GObject :: !KeyMap GValue -> GValueBody
- Data.Greskell.GraphSON.GValue: GObject :: !HashMap Text GValue -> GValueBody
+ Data.Greskell.GraphSON.GValue: GObject :: !KeyMap GValue -> GValueBody
Files
- ChangeLog.md +13/−0
- greskell-core.cabal +5/−5
- src/Data/Greskell/GMap.hs +13/−16
- src/Data/Greskell/GraphSON.hs +21/−9
- src/Data/Greskell/GraphSON/GValue.hs +3/−2
- src/Data/Greskell/Greskell.hs +5/−4
- test/Data/Greskell/GMapSpec.hs +3/−2
- test/Data/Greskell/GraphSONSpec.hs +6/−5
ChangeLog.md view
@@ -1,5 +1,18 @@ # Revision history for greskell-core +## 1.0.0.0 -- 2021-12-28++* **BREAKING CHANGE**: `GObject` variant of `GValueBody` is now based on `KeyMap` from `aeson-2.0`.+ Before, it was based on `HashMap Text`.+ As a result, signature of the following functions has been changed.+ * `parseToGMap`+ * `parseToGMapEntry`+ * `(.:)`+* **BREAKING CHANGE**: Remove `FromGraphSON` instance for `Data.Semigroup.Option`, which is deprecated.+* Add `FromGraphSON` instance to `KeyMap` and `Key` from `aeson-2.0`.+* Confirm test with `aeson-2.0.2.0`, `semigroups-0.20` and `hashable-1.4.0.1`, `doctest-0.19.0`, `doctest-0.20.0`.++ ## 0.1.3.7 -- 2021-11-08 * Confirm test with `base-4.15.0.0`
greskell-core.cabal view
@@ -1,5 +1,5 @@ name: greskell-core-version: 0.1.3.7+version: 1.0.0.0 author: Toshio Ito <debug.ito@gmail.com> maintainer: Toshio Ito <debug.ito@gmail.com> license: BSD3@@ -31,12 +31,12 @@ other-modules: Data.Greskell.GraphSON.GraphSONTyped, Data.Greskell.GraphSON.Core build-depends: base >=4.9.0.0 && <4.16,- aeson >=1.0.2.1 && <1.6,+ aeson >=2.0.2.0 && <2.1, unordered-containers >=0.2.7.1 && <0.3,- hashable >=1.2.6.1 && <1.4,+ hashable >=1.2.6.1 && <1.5, scientific >=0.3.4.9 && <0.4, text >=1.2.2.1 && <1.3,- semigroups >=0.18.2 && <0.20,+ semigroups >=0.18.2 && <0.21, vector >=0.12.0.1 && <0.13, containers >=0.5.7.1 && <0.7, uuid >=1.3.13 && <1.4@@ -68,7 +68,7 @@ main-is: DocTest.hs build-tool-depends: doctest-discover:doctest-discover build-depends: base,- doctest >=0.11 && <0.19,+ doctest >=0.11 && <0.21, doctest-discover >=0.1.0.7 && <0.3
src/Data/Greskell/GMap.hs view
@@ -31,10 +31,11 @@ FromJSONKey, fromJSONKey, FromJSONKeyFunction(..), ToJSONKey ) import Data.Aeson.Types (Parser)+import Data.Aeson.KeyMap (KeyMap)+import qualified Data.Aeson.KeyMap as KM+import qualified Data.Aeson.Key as Key import Data.Foldable (length, Foldable) import Data.Hashable (Hashable)-import Data.HashMap.Strict (HashMap)-import qualified Data.HashMap.Strict as HM import qualified Data.Map as M import Data.Text (Text, intercalate, unpack) import Data.Traversable (Traversable, traverse)@@ -153,8 +154,8 @@ parseToGMap :: (IsList (c k v), Item (c k v) ~ (k,v)) => (s -> Parser k) -- ^ key parser -> (s -> Parser v) -- ^ value parser- -> (HashMap Text s -> Parser (c k v)) -- ^ object parser- -> Either (HashMap Text s) (Vector s) -- ^ input object or flattened key-values.+ -> (KeyMap s -> Parser (c k v)) -- ^ object parser+ -> Either (KeyMap s) (Vector s) -- ^ input object or flattened key-values. -> Parser (GMap c k v) parseToGMap _ _ op (Left o) = fmap (GMap False) $ op o parseToGMap kp vp _ (Right v) = fmap (GMap True . unFlattenedMap) $ parseToFlattenedMap kp vp v@@ -213,14 +214,14 @@ parseKeyValueToEntry :: (s -> Parser k) -> (s -> Parser v)- -> HashMap Text s+ -> KeyMap s -> Parser (Maybe (GMapEntry k v)) parseKeyValueToEntry kp vp o = if length o /= 2 then return Nothing else do- mk <- parseIfPresent kp $ HM.lookup "key" o- mv <- parseIfPresent vp $ HM.lookup "value" o+ mk <- parseIfPresent kp $ KM.lookup "key" o+ mv <- parseIfPresent vp $ KM.lookup "value" o return $ GMapEntry False <$> mk <*> mv where parseIfPresent :: (a -> Parser v) -> Maybe a -> Parser (Maybe v)@@ -228,12 +229,12 @@ parseSingleEntryObjectToEntry :: FromJSONKey k => (s -> Parser v)- -> HashMap Text s+ -> KeyMap s -> Parser (Maybe (GMapEntry k v)) parseSingleEntryObjectToEntry vp o =- case HM.toList o of+ case KM.toList o of [(raw_key, raw_val)] -> do- key <- parseKey raw_key+ key <- parseKey $ Key.toText raw_key val <- vp raw_val return $ Just $ GMapEntry False key val _ -> return Nothing@@ -248,11 +249,7 @@ ++ " It expects that the entry key is parsed from the text key in JSON Object," ++ " but the key type does not support it." )-#if MIN_VERSION_aeson(1,5,0) FromJSONKeyCoerce -> return $ fmap return coerce-#else- FromJSONKeyCoerce _ -> return $ fmap return unsafeCoerce-#endif orElseM :: Monad m => m (Maybe a) -> m (Maybe a) -> m (Maybe a) orElseM act_a act_b = do@@ -265,7 +262,7 @@ parseToGMapEntry :: FromJSONKey k => (s -> Parser k) -- ^ key parser -> (s -> Parser v) -- ^ value parser- -> Either (HashMap Text s) (Vector s) -- ^ input object or flattened key-values+ -> Either (KeyMap s) (Vector s) -- ^ input object or flattened key-values -> Parser (GMapEntry k v) parseToGMapEntry kp vp (Right vec) = do avec <- parseToAVec kp vp vec@@ -276,7 +273,7 @@ m_ret <- parseKeyValueToEntry kp vp o `orElseM` parseSingleEntryObjectToEntry vp o case m_ret of Just ret -> return ret- Nothing -> fail ("Unexpected structure of Object: got keys: " ++ (unpack $ intercalate ", " $ HM.keys o))+ Nothing -> fail ("Unexpected structure of Object: got keys: " ++ (unpack $ intercalate ", " $ map Key.toText $ KM.keys o)) -- | Map to \"g:Map\". instance GraphSONTyped (GMapEntry k v) where
src/Data/Greskell/GraphSON.hs view
@@ -41,10 +41,13 @@ import qualified Data.Aeson as Aeson import Data.Aeson.Types (Parser) import qualified Data.Aeson.Types as Aeson (parseEither)+import Data.Aeson.KeyMap (KeyMap)+import qualified Data.Aeson.KeyMap as KM+import Data.Aeson.Key (Key)+import qualified Data.Aeson.Key as Key import Data.Foldable (Foldable(foldr)) import Data.Functor.Identity (Identity(..)) import Data.HashMap.Strict (HashMap)-import qualified Data.HashMap.Strict as HM import qualified Data.HashMap.Lazy as L (HashMap) import Data.HashSet (HashSet) import Data.Hashable (Hashable(..))@@ -153,11 +156,11 @@ -- | Like Aeson's 'Aeson..:', but for 'FromGraphSON'. ----- @since 0.1.2.0-(.:) :: FromGraphSON a => HashMap Text GValue -> Text -> Parser a-go .: label = maybe failure parseGraphSON $ HM.lookup label go+-- @since 1.0.0.0+(.:) :: FromGraphSON a => KeyMap GValue -> Key -> Parser a+go .: label = maybe failure parseGraphSON $ KM.lookup label go where- failure = fail ("Cannot find field " ++ unpack label)+ failure = fail ("Cannot find field " ++ Key.toString label) -- | Implementation of 'parseJSON' based on 'parseGraphSON'. The input -- 'Value' is first converted to 'GValue', and it's parsed to the@@ -212,6 +215,12 @@ instance FromGraphSON IntSet where parseGraphSON = parseUnwrapAll +-- | First convert to 'Text', and convert to 'Key'.+--+-- @since 1.0.0.0+instance FromGraphSON Key where+ parseGraphSON = fmap Key.fromText . parseGraphSON+ ---- List instances instance FromGraphSON a => FromGraphSON [a] where@@ -283,7 +292,7 @@ b -> fail ("Expects GArray, but got " ++ show b) parseGObjectToTraversal :: (Traversable t, FromJSON (t GValue), FromGraphSON v)- => HashMap Text GValue+ => KeyMap GValue -> Parser (t v) parseGObjectToTraversal o = traverse parseGraphSON =<< (parseJSON $ Object $ fmap toJSON o) @@ -322,6 +331,12 @@ mapToIntMap :: L.Map Int v -> L.IntMap v mapToIntMap = LMap.foldrWithKey LIntMap.insert mempty +-- | First convert to 'L.Map' with 'Text' key, and convert to 'KeyMap'.+--+-- @since 1.0.0.0+instance FromGraphSON v => FromGraphSON (KeyMap v) where+ parseGraphSON = fmap KM.fromMap . parseGraphSON+ ---- Maybe and Either -- | Parse 'GNull' into 'Nothing'.@@ -335,9 +350,6 @@ ---- Trivial wrapper for Maybe --- | @since 0.1.3.0-instance FromGraphSON a => FromGraphSON (S.Option a) where- parseGraphSON = fmap S.Option . parseGraphSON -- | @since 0.1.3.0 instance FromGraphSON a => FromGraphSON (M.First a) where parseGraphSON = fmap M.First . parseGraphSON
src/Data/Greskell/GraphSON/GValue.hs view
@@ -28,6 +28,7 @@ import Data.Aeson ( ToJSON(toJSON), FromJSON(parseJSON), Value(..) )+import Data.Aeson.KeyMap (KeyMap) import Data.Aeson.Types (Parser) import Data.Foldable (foldl') import Data.Hashable (Hashable(..))@@ -56,9 +57,9 @@ -- | 'GValue' without the top-level 'GraphSON' wrapper. ----- @since 0.1.2.0+-- @since 1.0.0.0 data GValueBody =- GObject !(HashMap Text GValue)+ GObject !(KeyMap GValue) | GArray !(Vector GValue) | GString !Text | GNumber !Scientific
src/Data/Greskell/Greskell.hs view
@@ -35,9 +35,10 @@ import Data.Aeson (Value) import qualified Data.Aeson as Aeson+import qualified Data.Aeson.KeyMap as KM+import qualified Data.Aeson.Key as Key import Data.Bifunctor (bimap) import Data.Foldable (toList)-import qualified Data.HashMap.Lazy as HM import Data.Monoid (Monoid(..)) import Data.Ratio (numerator, denominator, Rational) import Data.Scientific (Scientific, coefficient, base10Exponent)@@ -222,11 +223,11 @@ value (Aeson.String s) = unsafeToValue $ string s value (Aeson.Array v) = unsafeToValue $ list $ map value $ toList v value (Aeson.Object obj)- | HM.null obj = unsafeGreskellLazy "[:]"- | otherwise = unsafeGreskellLazy $ toGroovyMap $ HM.toList obj+ | KM.null obj = unsafeGreskellLazy "[:]"+ | otherwise = unsafeGreskellLazy $ toGroovyMap $ KM.toList obj where toGroovyMap pairs = "[" <> TL.intercalate "," (map toPairText pairs) <> "]"- toPairText (key, val) = (toGremlinLazy $ string key) <> ":" <> (toGremlinLazy $ value val)+ toPairText (key, val) = (toGremlinLazy $ string $ Key.toText key) <> ":" <> (toGremlinLazy $ value val) -- | Integer literal as 'Value' type. --
test/Data/Greskell/GMapSpec.hs view
@@ -2,6 +2,7 @@ module Data.Greskell.GMapSpec (main,spec) where import Data.Aeson (eitherDecode, object, (.=), toJSON, Value(..))+import qualified Data.Aeson.KeyMap as KM import Data.HashMap.Strict (HashMap) import qualified Data.HashMap.Strict as HM import Data.List (isInfixOf)@@ -51,8 +52,8 @@ String "a", Number 1 ] (Object got) = toJSON val- HM.lookup "@type" got `shouldBe` (Just $ String "g:Map")- let (Just (Array got_flat)) = HM.lookup "@value" got+ KM.lookup "@type" got `shouldBe` (Just $ String "g:Map")+ let (Just (Array got_flat)) = KM.lookup "@value" got pairList got_flat `shouldMatchList` pairList exp_flat specify "FromJSON empty" $ do let val_empty :: GraphSON (GMap HashMap String Int)
test/Data/Greskell/GraphSONSpec.hs view
@@ -3,6 +3,7 @@ import Data.Aeson (object, (.=), ToJSON(..), FromJSON(..), Value(..)) import qualified Data.Aeson as Aeson+import qualified Data.Aeson.KeyMap as KM import Data.Aeson.Types (parseEither, Value(..), Parser) import qualified Data.ByteString.Lazy as BSL import Data.Either (isLeft)@@ -189,9 +190,9 @@ fromToJSON "wrapped array" (gson "g:List" "[null, \"foo\", 100]") (wrapped "g:List" $ GArray $ fmap bare $ V.fromList [GNull, GString "foo", GNumber 100]) fromToJSON "bare object" "{\"foo\": \"bar\", \"hoge\": 99, \"quux\": null}"- (bare $ GObject $ fmap bare $ HM.fromList [("foo", GString "bar"), ("hoge", GNumber 99), ("quux", GNull)])+ (bare $ GObject $ fmap bare $ KM.fromList [("foo", GString "bar"), ("hoge", GNumber 99), ("quux", GNull)]) fromToJSON "wrapped object" (gson "g:Map" "{\"foo\": \"bar\", \"hoge\": 99, \"quux\": null}")- (wrapped "g:Map" $ GObject $ fmap bare $ HM.fromList [("foo", GString "bar"), ("hoge", GNumber 99), ("quux", GNull)])+ (wrapped "g:Map" $ GObject $ fmap bare $ KM.fromList [("foo", GString "bar"), ("hoge", GNumber 99), ("quux", GNull)]) nested_spec double_wrap_spec decode_error_spec@@ -208,7 +209,7 @@ nested_spec = fromToJSON "mixed nested" nestedSample expected where expected = wrapped "g:List" $ GArray $ V.fromList [ bare $ GNumber 100, exp_a, exp_b ]- exp_a = wrapped "g:Map" $ GObject $ HM.fromList+ exp_a = wrapped "g:Map" $ GObject $ KM.fromList [ ("foo", bare $ GNumber 100), ("bar", wrapped "g:Int" $ GNumber 200) ]@@ -218,7 +219,7 @@ exp_c, wrapped "g:Boolean" $ GBool False ]- exp_c = bare $ GObject $ HM.fromList+ exp_c = bare $ GObject $ KM.fromList [ ("xxx", wrapped "g:Int" $ GNumber 200), ("yyy", bare $ GBool True) ]@@ -230,7 +231,7 @@ double_wrap_spec = fromToJSON "double wrapped" input expected where input = gson "g:Object" $ gson "g:Int" "100"- expected = wrapped "g:Object" $ GObject $ HM.fromList+ expected = wrapped "g:Object" $ GObject $ KM.fromList [ ("@type", bare $ GString "g:Int"), ("@value", bare $ GNumber 100) ]