Hello community, here is the log from the commit of package ghc-yaml for openSUSE:Factory checked in at 2019-12-27 13:59:22 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/ghc-yaml (Old) and /work/SRC/openSUSE:Factory/.ghc-yaml.new.6675 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "ghc-yaml" Fri Dec 27 13:59:22 2019 rev:32 rq:759568 version:0.11.2.0 Changes: -------- --- /work/SRC/openSUSE:Factory/ghc-yaml/ghc-yaml.changes 2019-08-29 17:23:38.367306279 +0200 +++ /work/SRC/openSUSE:Factory/.ghc-yaml.new.6675/ghc-yaml.changes 2019-12-27 13:59:22.856832617 +0100 @@ -1,0 +2,20 @@ +Fri Nov 8 16:15:17 UTC 2019 - Peter Simons <psim...@suse.com> + +- Drop obsolete group attributes. + +------------------------------------------------------------------- +Thu Nov 7 06:41:50 UTC 2019 - psim...@suse.com + +- Update yaml to version 0.11.2.0. + ## 0.11.2.0 + + * Reduces some of the code duplication between the `encode` and `encodePretty` functions + * The output of `encodePretty` has been improved: + - Multiline strings now use `Literal` style instead of `SingleQuoted` + - Special keys are now quoted in mappings [#179](https://github.com/snoyberg/yaml/issues/179) + * Support for complex keys in mappings: [#182](https://github.com/snoyberg/yaml/issues/182) + - Adds `complexMapping` function to `Data.Yaml.Builder` + - Decode functions now return a `NonStringKey` error when attempting to decode a mapping with a complex key as it is not possible to decode these to an Aeson `Value` + * Adds missing `ToYaml` instances + +------------------------------------------------------------------- Old: ---- yaml-0.11.1.2.tar.gz New: ---- yaml-0.11.2.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ ghc-yaml.spec ++++++ --- /var/tmp/diff_new_pack.qrGwMV/_old 2019-12-27 13:59:23.316832839 +0100 +++ /var/tmp/diff_new_pack.qrGwMV/_new 2019-12-27 13:59:23.320832841 +0100 @@ -19,11 +19,10 @@ %global pkg_name yaml %bcond_with tests Name: ghc-%{pkg_name} -Version: 0.11.1.2 +Version: 0.11.2.0 Release: 0 Summary: Support for parsing and rendering YAML documents License: BSD-3-Clause -Group: Development/Libraries/Haskell URL: https://hackage.haskell.org/package/%{pkg_name} Source0: https://hackage.haskell.org/package/%{pkg_name}-%{version}/%{pkg_name}-%{version}.tar.gz BuildRequires: ghc-Cabal-devel @@ -59,7 +58,6 @@ %package devel Summary: Haskell %{pkg_name} library development files -Group: Development/Libraries/Haskell Requires: %{name} = %{version}-%{release} Requires: ghc-compiler = %{ghc_version} Requires(post): ghc-compiler = %{ghc_version} ++++++ yaml-0.11.1.2.tar.gz -> yaml-0.11.2.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yaml-0.11.1.2/ChangeLog.md new/yaml-0.11.2.0/ChangeLog.md --- old/yaml-0.11.1.2/ChangeLog.md 2019-08-26 20:14:53.000000000 +0200 +++ new/yaml-0.11.2.0/ChangeLog.md 2019-11-06 07:13:43.000000000 +0100 @@ -1,5 +1,16 @@ # ChangeLog for yaml +## 0.11.2.0 + +* Reduces some of the code duplication between the `encode` and `encodePretty` functions +* The output of `encodePretty` has been improved: + - Multiline strings now use `Literal` style instead of `SingleQuoted` + - Special keys are now quoted in mappings [#179](https://github.com/snoyberg/yaml/issues/179) +* Support for complex keys in mappings: [#182](https://github.com/snoyberg/yaml/issues/182) + - Adds `complexMapping` function to `Data.Yaml.Builder` + - Decode functions now return a `NonStringKey` error when attempting to decode a mapping with a complex key as it is not possible to decode these to an Aeson `Value` +* Adds missing `ToYaml` instances + ## 0.11.1.2 * Compiles with GHC 8.8.1 (`MonadFail` split) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yaml-0.11.1.2/src/Data/Yaml/Builder.hs new/yaml-0.11.2.0/src/Data/Yaml/Builder.hs --- old/yaml-0.11.1.2/src/Data/Yaml/Builder.hs 2019-08-23 05:30:58.000000000 +0200 +++ new/yaml-0.11.2.0/src/Data/Yaml/Builder.hs 2019-11-06 07:13:43.000000000 +0100 @@ -9,6 +9,9 @@ , mapping , namedMapping , maybeNamedMapping + , mappingComplex + , namedMappingComplex + , maybeNamedMappingComplex , array , namedArray , maybeNamedArray @@ -37,7 +40,6 @@ import Prelude hiding (null) -import Control.Arrow (second) #if MIN_VERSION_aeson(1,0,0) import Data.Aeson.Text (encodeToTextBuilder) #else @@ -47,10 +49,9 @@ import Data.ByteString (ByteString) import qualified Data.ByteString.Char8 as S8 import Data.Conduit -import qualified Data.HashSet as HashSet import Data.Scientific (Scientific) import Data.Text (Text, unpack) -import Data.Text.Encoding (encodeUtf8) +import qualified Data.Text as T import qualified Data.Text.Encoding as TE import qualified Data.Text.Lazy as TL import Data.Text.Lazy.Builder (toLazyText) @@ -68,119 +69,148 @@ toYaml :: a -> YamlBuilder instance ToYaml YamlBuilder where toYaml = id -instance ToYaml a => ToYaml [(Text, a)] where - toYaml = mapping . map (second toYaml) +instance (ToYaml a, ToYaml b) => ToYaml [(a, b)] where + toYaml = mappingComplex . map (\(k, v) -> (toYaml k, toYaml v)) instance ToYaml a => ToYaml [a] where toYaml = array . map toYaml instance ToYaml Text where toYaml = string +instance ToYaml String where + toYaml = string . T.pack instance ToYaml Int where - toYaml i = YamlBuilder (EventScalar (S8.pack $ show i) IntTag PlainNoTag Nothing:) + toYaml i = YamlBuilder (EventScalar (S8.pack $ show i) NoTag PlainNoTag Nothing:) +instance ToYaml Double where + toYaml i = YamlBuilder (EventScalar (S8.pack $ show i) NoTag PlainNoTag Nothing:) +instance ToYaml Scientific where + toYaml = scientific +instance ToYaml Bool where + toYaml = bool +instance ToYaml a => ToYaml (Maybe a) where + toYaml = maybe null toYaml -- | --- @since 0.11.0 +-- @since 0.10.3.0 maybeNamedMapping :: Maybe Text -> [(Text, YamlBuilder)] -> YamlBuilder -maybeNamedMapping anchor pairs = YamlBuilder $ \rest -> - EventMappingStart NoTag AnyMapping (unpack <$> anchor) : foldr addPair (EventMappingEnd : rest) pairs +maybeNamedMapping anchor pairs = maybeNamedMappingComplex anchor complexPairs where - addPair (key, YamlBuilder value) after - = EventScalar (encodeUtf8 key) StrTag PlainNoTag Nothing - : value after + complexPairs = map (\(k, v) -> (string k, v)) pairs +-- | +-- @since 0.8.7 mapping :: [(Text, YamlBuilder)] -> YamlBuilder mapping = maybeNamedMapping Nothing -- | --- @since 0.11.0 +-- @since 0.10.3.0 namedMapping :: Text -> [(Text, YamlBuilder)] -> YamlBuilder namedMapping name = maybeNamedMapping $ Just name -- | --- @since 0.11.0 +-- @since 0.11.2.0 +maybeNamedMappingComplex :: Maybe Text -> [(YamlBuilder, YamlBuilder)] -> YamlBuilder +maybeNamedMappingComplex anchor pairs = YamlBuilder $ \rest -> + EventMappingStart NoTag AnyMapping (unpack <$> anchor) : foldr addPair (EventMappingEnd : rest) pairs + where + addPair (YamlBuilder key, YamlBuilder value) after = key $ value after + +-- | +-- @since 0.11.2.0 +mappingComplex :: [(YamlBuilder, YamlBuilder)] -> YamlBuilder +mappingComplex = maybeNamedMappingComplex Nothing + +-- | +-- @since 0.11.2.0 +namedMappingComplex :: Text -> [(YamlBuilder, YamlBuilder)] -> YamlBuilder +namedMappingComplex name = maybeNamedMappingComplex $ Just name + +-- | +-- @since 0.10.3.0 maybeNamedArray :: Maybe Text -> [YamlBuilder] -> YamlBuilder maybeNamedArray anchor bs = YamlBuilder $ (EventSequenceStart NoTag AnySequence (unpack <$> anchor):) . flip (foldr go) bs . (EventSequenceEnd:) where go (YamlBuilder b) = b +-- | +-- @since 0.8.7 array :: [YamlBuilder] -> YamlBuilder array = maybeNamedArray Nothing -- | --- @since 0.11.0 +-- @since 0.10.3.0 namedArray :: Text -> [YamlBuilder] -> YamlBuilder namedArray name = maybeNamedArray $ Just name -- | --- @since 0.11.0 +-- @since 0.10.3.0 maybeNamedString :: Maybe Text -> Text -> YamlBuilder --- Empty strings need special handling to ensure they get quoted. This avoids: --- https://github.com/snoyberg/yaml/issues/24 -maybeNamedString anchor "" = YamlBuilder (EventScalar "" NoTag SingleQuoted (unpack <$> anchor) :) -maybeNamedString anchor s = - YamlBuilder (event :) - where - event - -- Make sure that special strings are encoded as strings properly. - -- See: https://github.com/snoyberg/yaml/issues/31 - | s `HashSet.member` specialStrings || isNumeric s = EventScalar (encodeUtf8 s) NoTag SingleQuoted $ unpack <$> anchor - | otherwise = EventScalar (encodeUtf8 s) StrTag PlainNoTag $ unpack <$> anchor +maybeNamedString anchor s = YamlBuilder (stringScalar defaultStringStyle anchor s :) +-- | +-- @since 0.8.7 string :: Text -> YamlBuilder string = maybeNamedString Nothing -- | --- @since 0.11.0 +-- @since 0.10.3.0 namedString :: Text -> Text -> YamlBuilder namedString name = maybeNamedString $ Just name -- Use aeson's implementation which gets rid of annoying decimal points -- | --- @since 0.11.0 +-- @since 0.10.3.0 maybeNamedScientific :: Maybe Text -> Scientific -> YamlBuilder -maybeNamedScientific anchor n = YamlBuilder (EventScalar (TE.encodeUtf8 $ TL.toStrict $ toLazyText $ encodeToTextBuilder (Number n)) IntTag PlainNoTag (unpack <$> anchor) :) +maybeNamedScientific anchor n = YamlBuilder (EventScalar (TE.encodeUtf8 $ TL.toStrict $ toLazyText $ encodeToTextBuilder (Number n)) NoTag PlainNoTag (unpack <$> anchor) :) +-- | +-- @since 0.8.13 scientific :: Scientific -> YamlBuilder scientific = maybeNamedScientific Nothing -- | --- @since 0.11.0 +-- @since 0.10.3.0 namedScientific :: Text -> Scientific -> YamlBuilder namedScientific name = maybeNamedScientific $ Just name +-- | +-- @since 0.8.13 {-# DEPRECATED number "Use scientific" #-} number :: Scientific -> YamlBuilder number = scientific -- | --- @since 0.11.0 +-- @since 0.10.3.0 maybeNamedBool :: Maybe Text -> Bool -> YamlBuilder -maybeNamedBool anchor True = YamlBuilder (EventScalar "true" BoolTag PlainNoTag (unpack <$> anchor) :) -maybeNamedBool anchor False = YamlBuilder (EventScalar "false" BoolTag PlainNoTag (unpack <$> anchor) :) +maybeNamedBool anchor True = YamlBuilder (EventScalar "true" NoTag PlainNoTag (unpack <$> anchor) :) +maybeNamedBool anchor False = YamlBuilder (EventScalar "false" NoTag PlainNoTag (unpack <$> anchor) :) +-- | +-- @since 0.8.13 bool :: Bool -> YamlBuilder bool = maybeNamedBool Nothing -- | --- @since 0.11.0 +-- @since 0.10.3.0 namedBool :: Text -> Bool -> YamlBuilder namedBool name = maybeNamedBool $ Just name -- | --- @since 0.11.0 +-- @since 0.10.3.0 maybeNamedNull :: Maybe Text -> YamlBuilder -maybeNamedNull anchor = YamlBuilder (EventScalar "null" NullTag PlainNoTag (unpack <$> anchor) :) +maybeNamedNull anchor = YamlBuilder (EventScalar "null" NoTag PlainNoTag (unpack <$> anchor) :) +-- | +-- @since 0.8.13 null :: YamlBuilder null = maybeNamedNull Nothing -- | --- @since 0.11.0 +-- @since 0.10.3.0 namedNull :: Text -> YamlBuilder namedNull name = maybeNamedNull $ Just name -- | --- @since 0.11.0 +-- @since 0.10.3.0 alias :: Text -> YamlBuilder alias anchor = YamlBuilder (EventAlias (unpack anchor) :) @@ -191,6 +221,8 @@ toSource :: (Monad m, ToYaml a) => a -> ConduitM i Event m () toSource = mapM_ yield . toEvents . toYaml +-- | +-- @since 0.8.7 toByteString :: ToYaml a => a -> ByteString toByteString = toByteStringWith defaultFormatOptions diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yaml-0.11.1.2/src/Data/Yaml/Internal.hs new/yaml-0.11.2.0/src/Data/Yaml/Internal.hs --- old/yaml-0.11.1.2/src/Data/Yaml/Internal.hs 2019-08-23 05:30:58.000000000 +0200 +++ new/yaml-0.11.2.0/src/Data/Yaml/Internal.hs 2019-11-06 07:13:43.000000000 +0100 @@ -11,9 +11,14 @@ , parse , decodeHelper , decodeHelper_ + , textToScientific + , stringScalar + , defaultStringStyle + , isSpecialString , specialStrings , isNumeric - , textToScientific + , objToStream + , objToEvents ) where #if !MIN_VERSION_base(4,8,0) @@ -26,11 +31,14 @@ import Control.Monad.State.Strict import Control.Monad.Reader import Data.Aeson -import Data.Aeson.Internal (JSONPath, JSONPathElement(..)) +import Data.Aeson.Internal (JSONPath, JSONPathElement(..), formatError) import Data.Aeson.Types hiding (parse) import qualified Data.Attoparsec.Text as Atto import Data.Bits (shiftL, (.|.)) import Data.ByteString (ByteString) +import qualified Data.ByteString.Builder as BB +import qualified Data.ByteString.Lazy as BL +import Data.ByteString.Builder.Scientific (scientificBuilder) import Data.Char (toUpper, ord) import Data.List import Data.Conduit ((.|), ConduitM, runConduit) @@ -41,10 +49,10 @@ import qualified Data.Map as Map import Data.Set (Set) import qualified Data.Set as Set -import Data.Scientific (Scientific) +import Data.Scientific (Scientific, base10Exponent, coefficient) import Data.Text (Text, pack) import qualified Data.Text as T -import Data.Text.Encoding (decodeUtf8With) +import Data.Text.Encoding (decodeUtf8With, encodeUtf8) import Data.Text.Encoding.Error (lenientDecode) import Data.Typeable import qualified Data.Vector as V @@ -60,6 +68,7 @@ | InvalidYaml (Maybe YamlException) | AesonException String | OtherParseException SomeException + | NonStringKey JSONPath | NonStringKeyAlias Y.AnchorName Value | CyclicIncludes | LoadSettingsException FilePath ParseException @@ -108,6 +117,7 @@ ] AesonException s -> "Aeson exception:\n" ++ s OtherParseException exc -> "Generic parse exception:\n" ++ show exc + NonStringKey path -> formatError path "Non-string keys are not supported" NonStringKeyAlias anchor value -> unlines [ "Non-string key alias:" , " Anchor name: " ++ anchor @@ -250,7 +260,9 @@ Nothing -> liftIO $ throwIO $ UnknownAlias an Just (String t) -> return t Just v -> liftIO $ throwIO $ NonStringKeyAlias an v - _ -> liftIO $ throwIO $ UnexpectedEvent me Nothing + _ -> do + path <- ask + liftIO $ throwIO $ NonStringKey path (mergedKeys', al') <- local (Key s :) $ do o <- parseO @@ -301,10 +313,88 @@ Right ((,) (parseStateWarnings st) <$> parseEither parseJSON y) +type StringStyle = Text -> ( Tag, Style ) + +-- | Encodes a string with the supplied style. This function handles the empty +-- string case properly to avoid https://github.com/snoyberg/yaml/issues/24 +-- +-- @since 0.11.2.0 +stringScalar :: StringStyle -> Maybe Text -> Text -> Event +stringScalar _ anchor "" = EventScalar "" NoTag SingleQuoted (T.unpack <$> anchor) +stringScalar stringStyle anchor s = EventScalar (encodeUtf8 s) tag style (T.unpack <$> anchor) + where + ( tag, style ) = stringStyle s + +-- | +-- @since 0.11.2.0 +defaultStringStyle :: StringStyle +defaultStringStyle = \s -> + case () of + () + | "\n" `T.isInfixOf` s -> ( NoTag, Literal ) + | isSpecialString s -> ( NoTag, SingleQuoted ) + | otherwise -> ( NoTag, PlainNoTag ) + +-- | Determine whether a string must be quoted in YAML and can't appear as plain text. +-- Useful if you want to use 'setStringStyle'. +-- +-- @since 0.10.2.0 +isSpecialString :: Text -> Bool +isSpecialString s = s `HashSet.member` specialStrings || isNumeric s + -- | Strings which must be escaped so as not to be treated as non-string scalars. +-- +-- @since 0.8.32 specialStrings :: HashSet.HashSet Text specialStrings = HashSet.fromList $ T.words "y Y yes Yes YES n N no No NO true True TRUE false False FALSE on On ON off Off OFF null Null NULL ~ *" +-- | +-- @since 0.8.32 isNumeric :: Text -> Bool isNumeric = either (const False) (const True) . textToScientific + +-- | Encode a value as a YAML document stream. +-- +-- @since 0.11.2.0 +objToStream :: ToJSON a => StringStyle -> a -> [Y.Event] +objToStream stringStyle o = + (:) EventStreamStart + . (:) EventDocumentStart + $ objToEvents stringStyle o + [ EventDocumentEnd + , EventStreamEnd + ] + +-- | Encode a value as a list of 'Event's. +-- +-- @since 0.11.2.0 +objToEvents :: ToJSON a => StringStyle -> a -> [Y.Event] -> [Y.Event] +objToEvents stringStyle = objToEvents' . toJSON + where + objToEvents' (Array list) rest = + EventSequenceStart NoTag AnySequence Nothing + : foldr objToEvents' (EventSequenceEnd : rest) (V.toList list) + + objToEvents' (Object o) rest = + EventMappingStart NoTag AnyMapping Nothing + : foldr pairToEvents (EventMappingEnd : rest) (M.toList o) + where + pairToEvents :: Pair -> [Y.Event] -> [Y.Event] + pairToEvents (k, v) = objToEvents' (String k) . objToEvents' v + + objToEvents' (String s) rest = stringScalar stringStyle Nothing s : rest + + objToEvents' Null rest = EventScalar "null" NullTag PlainNoTag Nothing : rest + + objToEvents' (Bool True) rest = EventScalar "true" BoolTag PlainNoTag Nothing : rest + objToEvents' (Bool False) rest = EventScalar "false" BoolTag PlainNoTag Nothing : rest + + objToEvents' (Number s) rest = + let builder + -- Special case the 0 exponent to remove the trailing .0 + | base10Exponent s == 0 = BB.integerDec $ coefficient s + | otherwise = scientificBuilder s + lbs = BB.toLazyByteString builder + bs = BL.toStrict lbs + in EventScalar bs IntTag PlainNoTag Nothing : rest diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yaml-0.11.1.2/src/Data/Yaml/Pretty.hs new/yaml-0.11.2.0/src/Data/Yaml/Pretty.hs --- old/yaml-0.11.1.2/src/Data/Yaml/Pretty.hs 2019-08-23 05:30:58.000000000 +0200 +++ new/yaml-0.11.2.0/src/Data/Yaml/Pretty.hs 2019-11-06 07:13:43.000000000 +0100 @@ -10,6 +10,7 @@ , getConfDropNull , setConfDropNull , defConfig + , pretty ) where import Prelude hiding (null) @@ -34,7 +35,7 @@ -- @since 0.8.13 data Config = Config { confCompare :: Text -> Text -> Ordering -- ^ Function used to sort keys in objects - , confDropNull :: Bool + , confDropNull :: Bool -- ^ Drop null values from objects } -- | The default configuration: do not sort objects or drop keys diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yaml-0.11.1.2/src/Data/Yaml.hs new/yaml-0.11.2.0/src/Data/Yaml.hs --- old/yaml-0.11.1.2/src/Data/Yaml.hs 2019-08-26 19:52:52.000000000 +0200 +++ new/yaml-0.11.2.0/src/Data/Yaml.hs 2019-11-06 07:13:43.000000000 +0100 @@ -72,6 +72,7 @@ , isSpecialString , EncodeOptions , defaultEncodeOptions + , defaultStringStyle , setStringStyle , setFormat , FormatOptions @@ -94,18 +95,10 @@ , Object, Array , withObject, withText, withArray, withScientific, withBool ) -import qualified Data.Scientific as S -import qualified Data.ByteString.Builder.Scientific -import Data.Aeson.Types (Pair, parseMaybe, parseEither, Parser) +import Data.Aeson.Types (parseMaybe, parseEither, Parser) import Data.ByteString (ByteString) -import qualified Data.ByteString.Builder as BB -import qualified Data.ByteString.Lazy as BL import Data.Conduit ((.|), runConduitRes) import qualified Data.Conduit.List as CL -import qualified Data.HashMap.Strict as M -import qualified Data.HashSet as HashSet -import Data.Text.Encoding (encodeUtf8) -import qualified Data.Text as T import qualified Data.Vector as V import System.IO.Unsafe (unsafePerformIO) import Data.Text (Text) @@ -114,13 +107,6 @@ import Text.Libyaml hiding (encode, decode, encodeFile, decodeFile, encodeWith, encodeFileWith) import qualified Text.Libyaml as Y --- | --- @since 0.10.2.0 -data EncodeOptions = EncodeOptions - { encodeOptionsStringStyle :: Text -> ( Tag, Style ) - , encodeOptionsFormat :: FormatOptions - } - -- | Set the string style in the encoded YAML. This is a function that decides -- for each string the type of YAML string to output. -- @@ -145,25 +131,18 @@ setFormat :: FormatOptions -> EncodeOptions -> EncodeOptions setFormat f opts = opts { encodeOptionsFormat = f } --- | Determine whether a string must be quoted in YAML and can't appear as plain text. --- Useful if you want to use 'setStringStyle'. --- +-- | -- @since 0.10.2.0 -isSpecialString :: Text -> Bool -isSpecialString s = s `HashSet.member` specialStrings || isNumeric s +data EncodeOptions = EncodeOptions + { encodeOptionsStringStyle :: Text -> ( Tag, Style ) + , encodeOptionsFormat :: FormatOptions + } -- | -- @since 0.10.2.0 defaultEncodeOptions :: EncodeOptions defaultEncodeOptions = EncodeOptions - { encodeOptionsStringStyle = \s -> - -- Empty strings need special handling to ensure they get quoted. This avoids: - -- https://github.com/snoyberg/yaml/issues/24 - case () of - () - | "\n" `T.isInfixOf` s -> ( NoTag, Literal ) - | isSpecialString s -> ( NoTag, SingleQuoted ) - | otherwise -> ( StrTag, PlainNoTag ) + { encodeOptionsStringStyle = defaultStringStyle , encodeOptionsFormat = defaultFormatOptions } @@ -176,7 +155,7 @@ -- @since 0.10.2.0 encodeWith :: ToJSON a => EncodeOptions -> a -> ByteString encodeWith opts obj = unsafePerformIO $ runConduitRes - $ CL.sourceList (objToEvents opts $ toJSON obj) + $ CL.sourceList (objToStream (encodeOptionsStringStyle opts) $ toJSON obj) .| Y.encodeWith (encodeOptionsFormat opts) -- | Encode a value into its YAML representation and save to the given file. @@ -188,53 +167,9 @@ -- @since 0.10.2.0 encodeFileWith :: ToJSON a => EncodeOptions -> FilePath -> a -> IO () encodeFileWith opts fp obj = runConduitRes - $ CL.sourceList (objToEvents opts $ toJSON obj) + $ CL.sourceList (objToStream (encodeOptionsStringStyle opts) $ toJSON obj) .| Y.encodeFileWith (encodeOptionsFormat opts) fp -objToEvents :: EncodeOptions -> Value -> [Y.Event] -objToEvents opts o = (:) EventStreamStart - . (:) EventDocumentStart - $ objToEvents' o - [ EventDocumentEnd - , EventStreamEnd - ] - where - objToEvents' :: Value -> [Y.Event] -> [Y.Event] - --objToEvents' (Scalar s) rest = scalarToEvent s : rest - objToEvents' (Array list) rest = - EventSequenceStart NoTag AnySequence Nothing - : foldr objToEvents' (EventSequenceEnd : rest) (V.toList list) - objToEvents' (Object pairs) rest = - EventMappingStart NoTag AnyMapping Nothing - : foldr pairToEvents (EventMappingEnd : rest) (M.toList pairs) - - objToEvents' (String "") rest = EventScalar "" NoTag SingleQuoted Nothing : rest - - objToEvents' (String s) rest = EventScalar (encodeUtf8 s) tag style Nothing : rest - where - ( tag, style ) = encodeOptionsStringStyle opts s - objToEvents' Null rest = EventScalar "null" NullTag PlainNoTag Nothing : rest - objToEvents' (Bool True) rest = EventScalar "true" BoolTag PlainNoTag Nothing : rest - objToEvents' (Bool False) rest = EventScalar "false" BoolTag PlainNoTag Nothing : rest - - objToEvents' (Number s) rest = - let builder - -- Special case the 0 exponent to remove the trailing .0 - | S.base10Exponent s == 0 = BB.integerDec $ S.coefficient s - | otherwise = Data.ByteString.Builder.Scientific.scientificBuilder s - lbs = BB.toLazyByteString builder - bs = BL.toStrict lbs - in EventScalar bs IntTag PlainNoTag Nothing : rest - - pairToEvents :: Pair -> [Y.Event] -> [Y.Event] - pairToEvents (k, v) = objToEvents' (String k) . objToEvents' v - -{- FIXME -scalarToEvent :: YamlScalar -> Event -scalarToEvent (YamlScalar v t s) = EventScalar v t s Nothing --} - - decode :: FromJSON a => ByteString -> Maybe a diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yaml-0.11.1.2/test/Data/YamlSpec.hs new/yaml-0.11.2.0/test/Data/YamlSpec.hs --- old/yaml-0.11.1.2/test/Data/YamlSpec.hs 2019-08-23 06:18:43.000000000 +0200 +++ new/yaml-0.11.2.0/test/Data/YamlSpec.hs 2019-11-06 07:13:43.000000000 +0100 @@ -27,6 +27,8 @@ import Test.Mockery.Directory import qualified Data.Yaml as D +import qualified Data.Yaml.Builder as B +import qualified Data.Yaml.Internal as Internal import qualified Data.Yaml.Pretty as Pretty import Data.Yaml (object, array, (.=)) import Data.Maybe @@ -53,17 +55,39 @@ deriveJSON defaultOptions ''TestJSON +testJSON :: TestJSON +testJSON = TestJSON + { string = "str" + , number = 2 + , anArray = V.fromList ["a", "b"] + , hash = HM.fromList [("key1", "value1"), ("key2", "value2")] + , extrastring = "1234-foo" + } + shouldDecode :: (Show a, D.FromJSON a, Eq a) => B8.ByteString -> a -> IO () shouldDecode bs expected = do - actual <- D.decodeThrow bs - actual `shouldBe` expected + actual <- D.decodeThrow bs + actual `shouldBe` expected + +shouldDecodeEvents :: B8.ByteString -> [Y.Event] -> IO () +shouldDecodeEvents bs expected = do + actual <- runConduitRes $ Y.decode bs .| CL.consume + map anyStyle actual `shouldBe` map anyStyle expected + +anyStyle :: Y.Event -> Y.Event +anyStyle (Y.EventScalar bs tag _ anchor) = Y.EventScalar bs tag Y.Any anchor +anyStyle (Y.EventSequenceStart tag _ anchor) = Y.EventSequenceStart tag Y.AnySequence anchor +anyStyle (Y.EventMappingStart tag _ anchor) = Y.EventMappingStart tag Y.AnyMapping anchor +anyStyle event = event testEncodeWith :: Y.FormatOptions -> [Y.Event] -> IO BS.ByteString -testEncodeWith opts es = runConduitRes (CL.sourceList events .| Y.encodeWith opts) - where - events = - [Y.EventStreamStart, Y.EventDocumentStart] ++ es ++ - [Y.EventDocumentEnd, Y.EventStreamEnd] +testEncodeWith opts es = runConduitRes $ CL.sourceList (eventStream es) .| Y.encodeWith opts + +eventStream :: [Y.Event] -> [Y.Event] +eventStream events = + [Y.EventStreamStart, Y.EventDocumentStart] + ++ events + ++ [Y.EventDocumentEnd, Y.EventStreamEnd] main :: IO () main = hspec spec @@ -86,6 +110,7 @@ it "count scalars" caseCountScalars it "largest string" caseLargestString it "encode/decode" caseEncodeDecode + it "encode/decode events" caseEncodeDecodeEvents it "encode/decode file" caseEncodeDecodeFile it "interleaved encode/decode" caseInterleave it "decode invalid document (without segfault)" caseDecodeInvalidDocument @@ -101,6 +126,9 @@ it "encode/decode" caseEncodeDecodeDataPretty it "encode/decode strings" caseEncodeDecodeStringsPretty it "processes datatypes" caseDataTypesPretty + describe "Data.Yaml.Builder" $ do + it "encode/decode" caseEncodeDecodeDataBuilder + it "encode/decode complex mapping" caseEncodeDecodeComplexMappingBuilder describe "Data.Yaml aliases" $ do it "simple scalar alias" caseSimpleScalarAlias it "simple sequence alias" caseSimpleSequenceAlias @@ -159,13 +187,7 @@ describe "decodeFileEither" $ do it "loads YAML through JSON into Haskell data" $ do tj <- either (error . show) id `fmap` D.decodeFileEither "test/json.yaml" - tj `shouldBe` TestJSON - { string = "str" - , number = 2 - , anArray = V.fromList ["a", "b"] - , hash = HM.fromList [("key1", "value1"), ("key2", "value2")] - , extrastring = "1234-foo" - } + tj `shouldBe` testJSON context "when file does not exist" $ do it "returns Left" $ do @@ -188,18 +210,9 @@ it "truncates files" caseTruncatesFiles - it "quoting keys #137" $ do - let keys = T.words "true false NO YES 1.2 1e5 null" - bs = D.encode $ M.fromList $ map (, ()) keys - text = decodeUtf8 bs - forM_ keys $ \key -> do - let quoted = T.concat ["'", key, "'"] - unless (quoted `T.isInfixOf` text) $ error $ concat - [ "Could not find quoted key: " - , T.unpack quoted - , "\n\n" - , T.unpack text - ] :: IO () + it "encode quotes special keys #137" $ caseSpecialKeys D.encode + + it "encodePretty quotes special keys #179" $ caseSpecialKeys (Pretty.encodePretty Pretty.defConfig) describe "non-decimal numbers #135" $ do let go str val = it str $ encodeUtf8 (T.pack str) `shouldDecode` val @@ -479,6 +492,13 @@ yamlString = "foo: bar\nbaz:\n - bin1\n - bin2\n" yamlBS = B8.pack yamlString +caseEncodeDecodeEvents :: Assertion +caseEncodeDecodeEvents = do + let events = Internal.objToEvents D.defaultStringStyle testJSON [] + result <- Internal.decodeHelper_ . CL.sourceList $ eventStream events + let (_, value) = either (error . show) id result + value @?= testJSON + caseEncodeDecodeFile :: Assertion caseEncodeDecodeFile = withFile "" $ \tmpPath -> do eList <- runConduitRes $ Y.decodeFile filePath .| CL.consume @@ -528,6 +548,24 @@ , ("bar3", D.String "") ] , D.String "" + , D.Number 1 + , D.Number 0.1 + , D.Bool True + , D.Null + ] + +sampleBuilder :: B.YamlBuilder +sampleBuilder = B.array + [ B.string "foo" + , B.mapping + [ ("bar1", B.string "bar2") + , ("bar3", B.string "") + ] + , B.string "" + , B.scientific 1 + , B.scientific 0.1 + , B.bool True + , B.null ] caseEncodeDecodeData :: Assertion @@ -537,6 +575,28 @@ caseEncodeDecodeDataPretty = Pretty.encodePretty Pretty.defConfig sample `shouldDecode` sample +caseEncodeDecodeDataBuilder :: Assertion +caseEncodeDecodeDataBuilder = do + let events = B.unYamlBuilder sampleBuilder [] + bs <- testEncodeWith Y.defaultFormatOptions events + bs `shouldDecodeEvents` eventStream events + +caseEncodeDecodeComplexMappingBuilder :: Assertion +caseEncodeDecodeComplexMappingBuilder = do + let events = B.unYamlBuilder builder [] + bs <- testEncodeWith Y.defaultFormatOptions events + bs `shouldDecodeEvents` eventStream events + where + builder :: B.YamlBuilder + builder = B.mappingComplex + [ ( B.mapping + [ ("foo", B.scientific 1) + , ("bar", B.scientific 2) + ] + , B.bool True + ) + ] + caseEncodeDecodeFileData :: Assertion caseEncodeDecodeFileData = withFile "" $ \fp -> do D.encodeFile fp sample @@ -737,6 +797,19 @@ res <- D.decodeFileEither fp either (Left . show) Right res `shouldBe` Right val +caseSpecialKeys :: (HashMap Text () -> B8.ByteString) -> Assertion +caseSpecialKeys encoder = do + let keys = T.words "true false NO YES 1.2 1e5 null" + bs = encoder $ M.fromList $ map (, ()) keys + text = decodeUtf8 bs + forM_ keys $ \key -> do + let quoted = T.concat ["'", key, "'"] + unless (quoted `T.isInfixOf` text) $ error $ concat + [ "Could not find quoted key: " + , T.unpack quoted + , "\n\n" + , T.unpack text + ] :: IO () taggedSequence :: [Y.Event] taggedSequence = diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yaml-0.11.1.2/yaml.cabal new/yaml-0.11.2.0/yaml.cabal --- old/yaml-0.11.1.2/yaml.cabal 2019-08-26 20:14:42.000000000 +0200 +++ new/yaml-0.11.2.0/yaml.cabal 2019-11-06 11:13:39.000000000 +0100 @@ -4,10 +4,10 @@ -- -- see: https://github.com/sol/hpack -- --- hash: fd80752d31072e9d0302c6aab5e524dff535a5e9d72ff7b14a2c1bd0e8cdc86a +-- hash: 1755dcdb4772fa7e743958ba68b120522981238fdcdac9fdc7494a36809ff6ae name: yaml -version: 0.11.1.2 +version: 0.11.2.0 synopsis: Support for parsing and rendering YAML documents. description: README and API documentation are available at <https://www.stackage.org/package/yaml> category: Data