mirror of
https://github.com/status-im/NimYAML.git
synced 2025-01-27 11:34:56 +00:00
Support serializing tuples. Multiple bugfixes.
* Parser: Properly support explicit keys in flow style. * Parser: Properly support object tags in flow style. * Serializer: Basic support for tuples. * Serializer: Properly parse int and bool types when given as string with explicit tag.
This commit is contained in:
parent
aa98c5863e
commit
d64184c025
15
README.md
15
README.md
@ -213,18 +213,25 @@ Output:
|
|||||||
- Add type hints for more scalar types
|
- Add type hints for more scalar types
|
||||||
* Parser:
|
* Parser:
|
||||||
- Properly handle leading spaces in block scalars
|
- Properly handle leading spaces in block scalars
|
||||||
|
- Raise exceptions instead of yielding yamlError tokens, which are a pain to
|
||||||
|
handle for the caller.
|
||||||
|
- Add an optional warning callback instead of yielding yamlWarning tokens,
|
||||||
|
which are a pain to handle for the caller.
|
||||||
|
- Oh and did I mention `yamlError` and `yamlWarning` are evil and need to
|
||||||
|
die.
|
||||||
* Serialization:
|
* Serialization:
|
||||||
- Generate local tags and use them
|
|
||||||
- Support for tuples
|
|
||||||
- Support for more standard library types
|
- Support for more standard library types
|
||||||
- Support for ref and ptr types
|
- Support for ref and ptr types
|
||||||
- Support for anchors and aliases
|
- Support for anchors and aliases (requires ref and ptr types)
|
||||||
- Support polymorphism
|
- Support polymorphism (requires ref and ptr types)
|
||||||
- Support variant objects
|
- Support variant objects
|
||||||
|
- Support transient fields (i.e. fields that will not be (de-)serialized on
|
||||||
|
objects and tuples)
|
||||||
- Make it possible for user to define a tag URI for custom types
|
- Make it possible for user to define a tag URI for custom types
|
||||||
- Use `concept` type class `Serializable` or something
|
- Use `concept` type class `Serializable` or something
|
||||||
* General:
|
* General:
|
||||||
- Proper error handling (do not use `ValueError` for everything)
|
- Proper error handling (do not use `ValueError` for everything)
|
||||||
|
- Proper error handling, seriously
|
||||||
- Document exceptions with `raises` pragmas in code
|
- Document exceptions with `raises` pragmas in code
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
@ -25,7 +25,7 @@ type
|
|||||||
# from here on tokens only in content
|
# from here on tokens only in content
|
||||||
tLineStart,
|
tLineStart,
|
||||||
# control characters
|
# control characters
|
||||||
tColon, tDash, tQuestionmark, tComma, tOpeningBrace,
|
tColon, tDash, tQuestionMark, tComma, tOpeningBrace,
|
||||||
tOpeningBracket, tClosingBrace, tClosingBracket, tPipe, tGreater,
|
tOpeningBracket, tClosingBrace, tClosingBracket, tPipe, tGreater,
|
||||||
# block scalar header
|
# block scalar header
|
||||||
tBlockIndentationIndicator, tPlus,
|
tBlockIndentationIndicator, tPlus,
|
||||||
@ -887,6 +887,7 @@ iterator tokens(my: var YamlLexer): YamlLexerToken {.closure.} =
|
|||||||
my.content = "!"
|
my.content = "!"
|
||||||
yield(tTagHandle)
|
yield(tTagHandle)
|
||||||
my.content = suffix
|
my.content = suffix
|
||||||
|
my.content.add(c)
|
||||||
state = ylTagSuffix
|
state = ylTagSuffix
|
||||||
of ' ', '\t', EndOfFile, '\r', '\x0A':
|
of ' ', '\t', EndOfFile, '\r', '\x0A':
|
||||||
let suffix = my.content[1..^1]
|
let suffix = my.content[1..^1]
|
||||||
|
@ -11,7 +11,8 @@ type
|
|||||||
ypBlockAfterAlias, ypBlockAfterColon, ypBlockMultilineScalar,
|
ypBlockAfterAlias, ypBlockAfterColon, ypBlockMultilineScalar,
|
||||||
ypBlockLineEnd, ypBlockScalarHeader, ypBlockScalar, ypFlow,
|
ypBlockLineEnd, ypBlockScalarHeader, ypBlockScalar, ypFlow,
|
||||||
ypFlowAfterObject, ypFlowAfterTag, ypFlowAfterAnchor,
|
ypFlowAfterObject, ypFlowAfterTag, ypFlowAfterAnchor,
|
||||||
ypFlowAfterAnchorAndTag, ypExpectingDocumentEnd, ypAfterDirectivesEnd
|
ypFlowAfterQuestionMark, ypFlowAfterAnchorAndTag,
|
||||||
|
ypExpectingDocumentEnd, ypAfterDirectivesEnd
|
||||||
|
|
||||||
DocumentLevelMode = enum
|
DocumentLevelMode = enum
|
||||||
mBlockSequenceItem, mFlowSequenceItem, mExplicitBlockMapKey,
|
mBlockSequenceItem, mFlowSequenceItem, mExplicitBlockMapKey,
|
||||||
@ -112,7 +113,8 @@ template yieldScalar(content: string, typeHint: YamlTypeHint,
|
|||||||
"scalar[\"", content, "\", type=", typeHint, "]"
|
"scalar[\"", content, "\", type=", typeHint, "]"
|
||||||
if objectTag.len > 0:
|
if objectTag.len > 0:
|
||||||
if tag.len > 0:
|
if tag.len > 0:
|
||||||
yieldError("Duplicate tag for scalar")
|
yieldError("Duplicate tag for scalar (tag=" & tag & ", objectTag=" &
|
||||||
|
objectTag)
|
||||||
tag = objectTag
|
tag = objectTag
|
||||||
objectTag = ""
|
objectTag = ""
|
||||||
yield YamlStreamEvent(kind: yamlScalar,
|
yield YamlStreamEvent(kind: yamlScalar,
|
||||||
@ -809,6 +811,8 @@ proc parse*(parser: YamlSequentialParser, s: Stream): YamlStream =
|
|||||||
indentationColumn: -1)
|
indentationColumn: -1)
|
||||||
else:
|
else:
|
||||||
yieldUnexpectedToken("scalar, comma or map end")
|
yieldUnexpectedToken("scalar, comma or map end")
|
||||||
|
of tQuestionMark:
|
||||||
|
state = ypFlowAfterQuestionMark
|
||||||
of tComma:
|
of tComma:
|
||||||
yieldScalar("", yTypeUnknown)
|
yieldScalar("", yTypeUnknown)
|
||||||
level = ancestry.pop()
|
level = ancestry.pop()
|
||||||
@ -826,6 +830,10 @@ proc parse*(parser: YamlSequentialParser, s: Stream): YamlStream =
|
|||||||
if level.mode != mUnknown:
|
if level.mode != mUnknown:
|
||||||
yieldUnexpectedToken()
|
yieldUnexpectedToken()
|
||||||
level.mode = mFlowMapKey
|
level.mode = mFlowMapKey
|
||||||
|
if objectTag.len > 0:
|
||||||
|
assert tag.len == 0
|
||||||
|
tag = objectTag
|
||||||
|
objectTag = ""
|
||||||
yieldStart(yamlStartMap)
|
yieldStart(yamlStartMap)
|
||||||
ancestry.add(level)
|
ancestry.add(level)
|
||||||
level = DocumentLevel(mode: mUnknown, indicatorColumn: -1,
|
level = DocumentLevel(mode: mUnknown, indicatorColumn: -1,
|
||||||
@ -834,6 +842,10 @@ proc parse*(parser: YamlSequentialParser, s: Stream): YamlStream =
|
|||||||
if level.mode != mUnknown:
|
if level.mode != mUnknown:
|
||||||
yieldUnexpectedToken()
|
yieldUnexpectedToken()
|
||||||
level.mode = mFlowSequenceItem
|
level.mode = mFlowSequenceItem
|
||||||
|
if objectTag.len > 0:
|
||||||
|
assert tag.len == 0
|
||||||
|
tag = objectTag
|
||||||
|
objectTag = ""
|
||||||
yieldStart(yamlStartSequence)
|
yieldStart(yamlStartSequence)
|
||||||
ancestry.add(level)
|
ancestry.add(level)
|
||||||
level = DocumentLevel(mode: mUnknown, indicatorColumn: -1,
|
level = DocumentLevel(mode: mUnknown, indicatorColumn: -1,
|
||||||
@ -884,6 +896,15 @@ proc parse*(parser: YamlSequentialParser, s: Stream): YamlStream =
|
|||||||
level = ancestry.pop()
|
level = ancestry.pop()
|
||||||
else:
|
else:
|
||||||
yieldUnexpectedToken()
|
yieldUnexpectedToken()
|
||||||
|
of ypFlowAfterQuestionMark:
|
||||||
|
case token
|
||||||
|
of tScalar, tScalarPart, tColon, tComma, tOpeningBrace,
|
||||||
|
tOpeningBracket, tClosingBrace, tClosingBracket, tTagHandle,
|
||||||
|
tAnchor, tAlias:
|
||||||
|
state = ypFlow
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
yieldUnexpectedToken()
|
||||||
of ypFlowAfterTag:
|
of ypFlowAfterTag:
|
||||||
case token
|
case token
|
||||||
of tTagHandle:
|
of tTagHandle:
|
||||||
|
@ -13,6 +13,7 @@ proc registerUri*(tagLib: var YamlTagLibrary, uri: string): TagId =
|
|||||||
tagLib.tags[uri] = tagLib.nextCustomTagId
|
tagLib.tags[uri] = tagLib.nextCustomTagId
|
||||||
result = tagLib.nextCustomTagId
|
result = tagLib.nextCustomTagId
|
||||||
tagLib.nextCustomTagId = cast[TagId](cast[int](tagLib.nextCustomTagId) + 1)
|
tagLib.nextCustomTagId = cast[TagId](cast[int](tagLib.nextCustomTagId) + 1)
|
||||||
|
echo "registered ", uri, " as: ", result
|
||||||
|
|
||||||
proc uri*(tagLib: YamlTagLibrary, id: TagId): string =
|
proc uri*(tagLib: YamlTagLibrary, id: TagId): string =
|
||||||
for iUri, iId in tagLib.tags.pairs:
|
for iUri, iId in tagLib.tags.pairs:
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import "../yaml"
|
import "../yaml"
|
||||||
import macros, strutils, streams, tables, json, hashes
|
import macros, strutils, streams, tables, json, hashes, re
|
||||||
export yaml, streams, tables, json
|
export yaml, streams, tables, json
|
||||||
|
|
||||||
type
|
type
|
||||||
@ -33,11 +33,13 @@ var
|
|||||||
|
|
||||||
static:
|
static:
|
||||||
iterator objectFields(n: NimNode): tuple[name: NimNode, t: NimNode] =
|
iterator objectFields(n: NimNode): tuple[name: NimNode, t: NimNode] =
|
||||||
assert n.kind == nnkRecList
|
assert n.kind in [nnkRecList, nnkTupleTy]
|
||||||
for identDefs in n.children:
|
for identDefs in n.children:
|
||||||
let numFields = identDefs.len - 2
|
let numFields = identDefs.len - 2
|
||||||
for i in 0..numFields - 1:
|
for i in 0..numFields - 1:
|
||||||
yield (name: identDefs[i], t: identDefs[^2])
|
yield (name: identDefs[i], t: identDefs[^2])
|
||||||
|
|
||||||
|
var existingTuples = newSeq[NimNode]()
|
||||||
|
|
||||||
template presentTag(t: typedesc, tagStyle: YamlTagStyle): TagId =
|
template presentTag(t: typedesc, tagStyle: YamlTagStyle): TagId =
|
||||||
if tagStyle == ytsNone: yTagQuestionMark else: yamlTag(t)
|
if tagStyle == ytsNone: yTagQuestionMark else: yamlTag(t)
|
||||||
@ -56,22 +58,56 @@ macro make_serializable*(types: stmt): stmt =
|
|||||||
let
|
let
|
||||||
tName = $typedef[0].symbol
|
tName = $typedef[0].symbol
|
||||||
tIdent = newIdentNode(tName)
|
tIdent = newIdentNode(tName)
|
||||||
tUri = "!nim:" & tName
|
var
|
||||||
|
tUri: NimNode
|
||||||
|
recList: NimNode
|
||||||
assert typedef[1].kind == nnkEmpty
|
assert typedef[1].kind == nnkEmpty
|
||||||
let objectTy = typedef[2]
|
let objectTy = typedef[2]
|
||||||
assert objectTy.kind == nnkObjectTy
|
case objectTy.kind
|
||||||
assert objectTy[0].kind == nnkEmpty
|
of nnkObjectTy:
|
||||||
assert objectTy[1].kind == nnkEmpty
|
assert objectTy[0].kind == nnkEmpty
|
||||||
let recList = objectTy[2]
|
assert objectTy[1].kind == nnkEmpty
|
||||||
assert recList.kind == nnkRecList
|
tUri = newStrLitNode("!nim:" & tName)
|
||||||
|
recList = objectTy[2]
|
||||||
|
of nnkTupleTy:
|
||||||
|
if objectTy in existingTuples:
|
||||||
|
continue
|
||||||
|
existingTuples.add(objectTy)
|
||||||
|
|
||||||
|
recList = objectTy
|
||||||
|
tUri = newStmtList()
|
||||||
|
var
|
||||||
|
first = true
|
||||||
|
curStrLit = "!nim:tuple("
|
||||||
|
curInfix = tUri
|
||||||
|
for field in objectFields(recList):
|
||||||
|
if first:
|
||||||
|
first = false
|
||||||
|
else:
|
||||||
|
curStrLit &= ","
|
||||||
|
curStrLit &= $field.name & "="
|
||||||
|
var tmp = newNimNode(nnkInfix).add(newIdentNode("&"),
|
||||||
|
newStrLitNode(curStrLit))
|
||||||
|
curInfix.add(tmp)
|
||||||
|
curInfix = tmp
|
||||||
|
tmp = newNimNode(nnkInfix).add(newIdentNode("&"),
|
||||||
|
newCall("safeTagUri", newCall("yamlTag",
|
||||||
|
newCall("type", field.t))))
|
||||||
|
curInfix.add(tmp)
|
||||||
|
curInfix = tmp
|
||||||
|
curStrLit = ""
|
||||||
|
curInfix.add(newStrLitNode(curStrLit & ")"))
|
||||||
|
tUri = tUri[0]
|
||||||
|
else:
|
||||||
|
assert false
|
||||||
|
|
||||||
# yamlTag()
|
# yamlTag()
|
||||||
|
|
||||||
var yamlTagProc = newProc(newIdentNode("yamlTag"), [
|
var yamlTagProc = newProc(newIdentNode("yamlTag"), [
|
||||||
newIdentNode("TagId"),
|
newIdentNode("TagId"),
|
||||||
newIdentDefs(newIdentNode("T"), newNimNode(nnkBracketExpr).add(
|
newIdentDefs(newIdentNode("T"), newNimNode(nnkBracketExpr).add(
|
||||||
newIdentNode("typedesc"), tIdent))])
|
newIdentNode("typedesc"), tIdent))])
|
||||||
var impl = newStmtList(newCall("lazyLoadTag", newStrLitNode(tUri)))
|
var impl = newStmtList(newCall("lazyLoadTag", tUri))
|
||||||
yamlTagProc[6] = impl
|
yamlTagProc[6] = impl
|
||||||
result.add(yamlTagProc)
|
result.add(yamlTagProc)
|
||||||
|
|
||||||
@ -93,6 +129,7 @@ macro make_serializable*(types: stmt): stmt =
|
|||||||
if finished(s):
|
if finished(s):
|
||||||
raise newException(ValueError, "Construction error!")
|
raise newException(ValueError, "Construction error!")
|
||||||
while event.kind != yamlEndMap:
|
while event.kind != yamlEndMap:
|
||||||
|
if event.kind == yamlError: echo event.description
|
||||||
assert event.kind == yamlScalar
|
assert event.kind == yamlScalar
|
||||||
assert event.scalarTag in [yTagQuestionMark, yTagString]
|
assert event.scalarTag in [yTagQuestionMark, yTagString]
|
||||||
case hash(event.scalarContent)
|
case hash(event.scalarContent)
|
||||||
@ -102,7 +139,7 @@ macro make_serializable*(types: stmt): stmt =
|
|||||||
event = s()
|
event = s()
|
||||||
if finished(s):
|
if finished(s):
|
||||||
raise newException(ValueError, "Construction error!")
|
raise newException(ValueError, "Construction error!")
|
||||||
var keyCase = impl[5][1][2]
|
var keyCase = impl[5][1][3]
|
||||||
assert keyCase.kind == nnkCaseStmt
|
assert keyCase.kind == nnkCaseStmt
|
||||||
for field in objectFields(recList):
|
for field in objectFields(recList):
|
||||||
let nameHash = hash($field.name.ident)
|
let nameHash = hash($field.name.ident)
|
||||||
@ -178,6 +215,7 @@ macro make_serializable*(types: stmt): stmt =
|
|||||||
nnkIteratorDef)))
|
nnkIteratorDef)))
|
||||||
serializeProc[6] = impl
|
serializeProc[6] = impl
|
||||||
result.add(serializeProc)
|
result.add(serializeProc)
|
||||||
|
echo result.repr
|
||||||
|
|
||||||
proc prepend*(event: YamlStreamEvent, s: YamlStream): YamlStream =
|
proc prepend*(event: YamlStreamEvent, s: YamlStream): YamlStream =
|
||||||
result = iterator(): YamlStreamEvent =
|
result = iterator(): YamlStreamEvent =
|
||||||
@ -187,6 +225,13 @@ proc prepend*(event: YamlStreamEvent, s: YamlStream): YamlStream =
|
|||||||
|
|
||||||
proc yamlTag*(T: typedesc[string]): TagId {.inline.} = yTagString
|
proc yamlTag*(T: typedesc[string]): TagId {.inline.} = yTagString
|
||||||
|
|
||||||
|
proc safeTagUri*(id: TagId): string =
|
||||||
|
let uri = serializationTagLibrary.uri(id)
|
||||||
|
if uri.len > 0 and uri[0] == '!':
|
||||||
|
return uri[1..uri.len - 1]
|
||||||
|
else:
|
||||||
|
return uri
|
||||||
|
|
||||||
proc construct*(s: YamlStream, result: var string) =
|
proc construct*(s: YamlStream, result: var string) =
|
||||||
let item = s()
|
let item = s()
|
||||||
if finished(s) or item.kind != yamlScalar:
|
if finished(s) or item.kind != yamlScalar:
|
||||||
@ -208,8 +253,8 @@ proc construct*(s: YamlStream, result: var int) =
|
|||||||
let item = s()
|
let item = s()
|
||||||
if finished(s) or item.kind != yamlScalar:
|
if finished(s) or item.kind != yamlScalar:
|
||||||
raise newException(ValueError, "Construction error!")
|
raise newException(ValueError, "Construction error!")
|
||||||
if item.scalarTag notin [yTagQuestionMark, yTagInteger] or
|
if item.scalarTag != yTagInteger and not (
|
||||||
item.scalarType != yTypeInteger:
|
item.scalarTag == yTagQuestionMark and item.scalarType == yTypeInteger):
|
||||||
raise newException(ValueError, "Wrong scalar type for int.")
|
raise newException(ValueError, "Wrong scalar type for int.")
|
||||||
result = parseInt(item.scalarContent)
|
result = parseInt(item.scalarContent)
|
||||||
|
|
||||||
@ -226,8 +271,8 @@ proc contruct*(s: YamlStream, result: var int64) =
|
|||||||
let item = s()
|
let item = s()
|
||||||
if finished(s) or item.kind != yamlScalar:
|
if finished(s) or item.kind != yamlScalar:
|
||||||
raise newException(ValueError, "Construction error!")
|
raise newException(ValueError, "Construction error!")
|
||||||
if item.scalarTag notin [yTagQuestionMark, yTagInteger] or
|
if item.scalarTag != yTagInteger and not (
|
||||||
item.scalarType != yTypeInteger:
|
item.scalarTag == yTagQuestionMark and item.scalarType == yTypeInteger):
|
||||||
raise newException(ValueError, "Wrong scalar type for int64.")
|
raise newException(ValueError, "Wrong scalar type for int64.")
|
||||||
result = parseBiggestInt(item.scalarContent)
|
result = parseBiggestInt(item.scalarContent)
|
||||||
|
|
||||||
@ -244,7 +289,8 @@ proc construct*(s: YamlStream, result: var float) =
|
|||||||
let item = s()
|
let item = s()
|
||||||
if finished(s) or item.kind != yamlScalar:
|
if finished(s) or item.kind != yamlScalar:
|
||||||
raise newException(ValueError, "Construction error!")
|
raise newException(ValueError, "Construction error!")
|
||||||
if item.scalarTag notin [yTagQuestionMark, yTagFloat]:
|
if item.scalarTag != yTagFloat and not (
|
||||||
|
item.scalarTag == yTagQuestionMark and item.scalarType == yTypeFloat):
|
||||||
raise newException(ValueError, "Wrong scalar type for float.")
|
raise newException(ValueError, "Wrong scalar type for float.")
|
||||||
case item.scalarType
|
case item.scalarType
|
||||||
of yTypeFloat:
|
of yTypeFloat:
|
||||||
@ -278,16 +324,27 @@ proc construct*(s: YamlStream, result: var bool) =
|
|||||||
let item = s()
|
let item = s()
|
||||||
if finished(s) or item.kind != yamlScalar:
|
if finished(s) or item.kind != yamlScalar:
|
||||||
raise newException(ValueError, "Construction error!")
|
raise newException(ValueError, "Construction error!")
|
||||||
if item.scalarTag notin [yTagQuestionMark, yTagBoolean]:
|
case item.scalarTag
|
||||||
raise newException(ValueError, "Wrong scalar type for bool.")
|
of yTagQuestionMark:
|
||||||
case item.scalarType
|
case item.scalarType
|
||||||
of yTypeBoolTrue:
|
of yTypeBoolTrue:
|
||||||
result = true
|
result = true
|
||||||
of yTypeBoolFalse:
|
of yTypeBoolFalse:
|
||||||
result = false
|
result = false
|
||||||
|
else:
|
||||||
|
raise newException(ValueError, "Wrong scalar type for bool.")
|
||||||
|
of yTagBoolean:
|
||||||
|
if item.scalarContent.match(
|
||||||
|
re"y|Y|yes|Yes|YES|true|True|TRUE|on|On|ON"):
|
||||||
|
result = true
|
||||||
|
elif item.scalarContent.match(
|
||||||
|
re"n|N|no|No|NO|false|False|FALSE|off|Off|OFF"):
|
||||||
|
result = false
|
||||||
|
else:
|
||||||
|
raise newException(ValueError, "Wrong content for bool.")
|
||||||
else:
|
else:
|
||||||
raise newException(ValueError, "Wrong scalar type for bool.")
|
raise newException(ValueError, "Wrong scalar type for bool")
|
||||||
|
|
||||||
proc serialize*(value: bool,
|
proc serialize*(value: bool,
|
||||||
tagStyle: YamlTagStyle = ytsNone): YamlStream =
|
tagStyle: YamlTagStyle = ytsNone): YamlStream =
|
||||||
result = iterator(): YamlStreamEvent =
|
result = iterator(): YamlStreamEvent =
|
||||||
@ -297,11 +354,7 @@ proc serialize*(value: bool,
|
|||||||
if value: "y" else: "n")
|
if value: "y" else: "n")
|
||||||
|
|
||||||
proc yamlTag*[I](T: typedesc[seq[I]]): TagId {.inline.} =
|
proc yamlTag*[I](T: typedesc[seq[I]]): TagId {.inline.} =
|
||||||
let
|
let uri = "!nim:seq(" & safeTagUri(yamlTag(I)) & ")"
|
||||||
childUri = serializationTagLibrary.uri(yamlTag(I))
|
|
||||||
childId = if childUri[0] == '!':
|
|
||||||
childUri[1..childUri.len-1] else: childUri
|
|
||||||
uri = "!nim:seq(" & childId & ")"
|
|
||||||
result = lazyLoadTag(uri)
|
result = lazyLoadTag(uri)
|
||||||
|
|
||||||
proc construct*[T](s: YamlStream, result: var seq[T]) =
|
proc construct*[T](s: YamlStream, result: var seq[T]) =
|
||||||
@ -389,7 +442,7 @@ proc serialize*[K, V](value: Table[K, V],
|
|||||||
|
|
||||||
proc load*[K](input: Stream, target: var K) =
|
proc load*[K](input: Stream, target: var K) =
|
||||||
var
|
var
|
||||||
parser = newParser(coreTagLibrary())
|
parser = newParser(serializationTagLibrary)
|
||||||
events = parser.parse(input)
|
events = parser.parse(input)
|
||||||
assert events().kind == yamlStartDocument
|
assert events().kind == yamlStartDocument
|
||||||
construct(events, target)
|
construct(events, target)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user