Merge branch 'master' of github.com:flyx/NimYAML

This commit is contained in:
Felix Krause 2016-01-24 21:41:16 +01:00
commit daafa8b8e8
10 changed files with 331 additions and 205 deletions

View File

@ -26,7 +26,7 @@ a list:
""" """
var var
parser = newParser(coreTagLibrary()) parser = newYamlParser(initCoreTagLibrary())
events = parser.parse(newStringStream(input)) events = parser.parse(newStringStream(input))
for event in events(): for event in events():
@ -60,13 +60,13 @@ import yaml, streams
proc example(): YamlStream = proc example(): YamlStream =
result = iterator(): YamlStreamEvent = result = iterator(): YamlStreamEvent =
yield startDocEvent() yield startDocEvent()
yield startMapEvent(mayHaveKeyObjects = false) yield startMapEvent()
yield scalarEvent("an integer") yield scalarEvent("an integer")
yield scalarEvent("42", tag = yTagInteger) yield scalarEvent("42", tag = yTagInteger)
yield scalarEvent("a list") yield scalarEvent("a list")
yield startSeqEvent(tag = yTagSequence) yield startSeqEvent(tag = yTagSequence)
yield scalarEvent("item", tag = yTagString) yield scalarEvent("item", tag = yTagString)
yield scalarEvent("no", tag = yTagBoolean, typeHint = yTypeBoolFalse) yield scalarEvent("no", tag = yTagBoolean)
yield scalarEvent("") yield scalarEvent("")
yield endSeqEvent() yield endSeqEvent()
yield scalarEvent("a float") yield scalarEvent("a float")
@ -74,11 +74,11 @@ proc example(): YamlStream =
yield endMapEvent() yield endMapEvent()
yield endDocEvent() yield endDocEvent()
present(example(), newFileStream(stdout), coreTagLibrary(), yDumpBlockOnly) present(example(), newFileStream(stdout), initCoreTagLibrary(), psBlockOnly)
echo "\n\n" echo "\n\n"
present(example(), newFileStream(stdout), coreTagLibrary(), yDumpCanonical) present(example(), newFileStream(stdout), initCoreTagLibrary(), psCanonical)
echo "\n\n" echo "\n\n"
present(example(), newFileStream(stdout), coreTagLibrary(), yDumpJson) present(example(), newFileStream(stdout), initCoreTagLibrary(), psJson)
``` ```
Output: Output:
@ -129,7 +129,7 @@ a float: !!float 3.14159
import yaml.serialization import yaml.serialization
import tables import tables
make_serializable: serializable:
type type
Person = object Person = object
firstname, surname: string firstname, surname: string
@ -162,7 +162,7 @@ assert persons[1].additionalAttributes["location"] == "Celle"
# dumping # dumping
dump(persons, newFileStream(stdout), ypsCanonical) dump(persons, newFileStream(stdout), psCanonical)
``` ```
Output: Output:
@ -177,9 +177,9 @@ Output:
? !!str "surname" ? !!str "surname"
: !!str "Pan", : !!str "Pan",
? !!str "age" ? !!str "age"
: !!int "12", : !nim:int "12",
? !!str "additionalAttributes" ? !!str "additionalAttributes"
: { : !nim:Table(tag:yaml.org,2002:str,tag:yaml.org,2002:str) {
? !!str "canFly" ? !!str "canFly"
: !!str "yes", : !!str "yes",
? !!str "location" ? !!str "location"
@ -192,9 +192,9 @@ Output:
? !!str "surname" ? !!str "surname"
: !!str "Koch", : !!str "Koch",
? !!str "age" ? !!str "age"
: !!int "23", : !nim:int "23",
? !!str "additionalAttributes" ? !!str "additionalAttributes"
: { : !nim:Table(tag:yaml.org,2002:str,tag:yaml.org,2002:str) {
? !!str "occupation" ? !!str "occupation"
: !!str "Hacker", : !!str "Hacker",
? !!str "location" ? !!str "location"
@ -208,7 +208,7 @@ Output:
* Documentation: * Documentation:
- Document yaml.serialization - Document yaml.serialization
* Lexer: * Misc:
- Add type hints for more scalar types - Add type hints for more scalar types
* Serialization: * Serialization:
- Support for more standard library types - Support for more standard library types
@ -225,10 +225,6 @@ Output:
- Possibly use `genSym` for predefined and generated `yamlTag` procs because - Possibly use `genSym` for predefined and generated `yamlTag` procs because
they are an implementation detail and should not be visible to the caller. they are an implementation detail and should not be visible to the caller.
same goes for `lazyLoadTag` and `safeLoadUri`. same goes for `lazyLoadTag` and `safeLoadUri`.
* General:
- Proper error handling (do not use `ValueError` for everything)
- Proper error handling, seriously
- Document exceptions with `raises` pragmas in code
## License ## License

View File

@ -8,11 +8,6 @@ task tests, "Run all tests":
--verbosity:0 --verbosity:0
setCommand "c", "test/tests" setCommand "c", "test/tests"
task lexerTests, "Run lexer tests":
--r
--verbosity:0
setCommand "c", "test/lexing"
task parserTests, "Run parser tests": task parserTests, "Run parser tests":
--r --r
--verbosity:0 --verbosity:0
@ -25,8 +20,8 @@ task serializationTests, "Run serialization tests":
task documentation, "Generate documentation": task documentation, "Generate documentation":
exec "mkdir -p docout" exec "mkdir -p docout"
exec r"nim doc2 -o:docout/yaml.html yaml" exec r"nim doc2 -o:docout/yaml.html --docSeeSrcUrl:https://github.com/flyx/NimYAML/blob/`git log -n 1 --format=%H` yaml"
exec r"nim doc2 -o:docout/serialization.html yaml/serialization.nim" exec r"nim doc2 -o:docout/serialization.html --docSeeSrcUrl:https://github.com/flyx/NimYAML/blob/`git log -n 1 --format=%H` yaml/serialization.nim"
exec r"nim rst2html -o:docout/index.html doc/index.txt" exec r"nim rst2html -o:docout/index.html doc/index.txt"
exec "cp doc/docutils.css doc/style.css doc/testing.html docout" exec "cp doc/docutils.css doc/style.css doc/testing.html docout"
setCommand "nop" setCommand "nop"

View File

@ -66,6 +66,15 @@ html {
background-color: rgba(252, 248, 244, 0.75); background-color: rgba(252, 248, 244, 0.75);
} }
/* necessary for links to scroll to the right position */
dt:before {
margin-top: -50px;
height: 50px;
content: ' ';
display: block;
visibility: hidden;
}
#testingground textarea { #testingground textarea {
width: 100%; width: 100%;
height: 100%; height: 100%;

View File

@ -136,7 +136,7 @@ template handleObjectStart(k: YamlStreamEventKind) {.dirty.} =
debug("started sequence at " & (if level.indentation == -1: $indentation else: debug("started sequence at " & (if level.indentation == -1: $indentation else:
$level.indentation)) $level.indentation))
level.kind = fplSequence level.kind = fplSequence
tag = yTagQuestionmark tag = yTagQuestionMark
anchor = yAnchorNone anchor = yAnchorNone
if level.indentation == -1: if level.indentation == -1:
level.indentation = indentation level.indentation = indentation
@ -183,7 +183,7 @@ template handleMapKeyIndicator() {.dirty.} =
of fplMapValue: of fplMapValue:
if level.indentation != indentation: if level.indentation != indentation:
parserError("Invalid indentation of map key indicator") parserError("Invalid indentation of map key indicator")
yield scalarEvent("", yTagQuestionmark, yAnchorNone) yield scalarEvent("", yTagQuestionMark, yAnchorNone)
level.kind = fplMapKey level.kind = fplMapKey
ancestry.add(level) ancestry.add(level)
level = FastParseLevel(kind: fplUnknown, indentation: -1) level = FastParseLevel(kind: fplUnknown, indentation: -1)
@ -205,16 +205,16 @@ template handleMapValueIndicator() {.dirty.} =
of fplUnknown: of fplUnknown:
if level.indentation == -1: if level.indentation == -1:
handleObjectStart(yamlStartMap) handleObjectStart(yamlStartMap)
yield scalarEvent("", yTagQuestionmark, yAnchorNone) yield scalarEvent("", yTagQuestionMark, yAnchorNone)
else: else:
yield scalarEvent("", tag, anchor) yield scalarEvent("", tag, anchor)
tag = yTagQuestionmark tag = yTagQuestionMark
anchor = yAnchorNone anchor = yAnchorNone
ancestry[ancestry.high].kind = fplMapValue ancestry[ancestry.high].kind = fplMapValue
of fplMapKey: of fplMapKey:
if level.indentation != indentation: if level.indentation != indentation:
parserError("Invalid indentation of map key indicator") parserError("Invalid indentation of map key indicator")
yield scalarEvent("", yTagQuestionmark, yAnchorNone) yield scalarEvent("", yTagQuestionMark, yAnchorNone)
level.kind = fplMapValue level.kind = fplMapValue
ancestry.add(level) ancestry.add(level)
level = FastParseLevel(kind: fplUnknown, indentation: -1) level = FastParseLevel(kind: fplUnknown, indentation: -1)
@ -238,14 +238,14 @@ template initDocValues() {.dirty.} =
shorthands["!!"] = "tag:yaml.org,2002:" shorthands["!!"] = "tag:yaml.org,2002:"
nextAnchorId = 0.AnchorId nextAnchorId = 0.AnchorId
level = FastParseLevel(kind: fplUnknown, indentation: -1) level = FastParseLevel(kind: fplUnknown, indentation: -1)
tag = yTagQuestionmark tag = yTagQuestionMark
anchor = yAnchorNone anchor = yAnchorNone
template handleTagHandle() {.dirty.} = template handleTagHandle() {.dirty.} =
startToken() startToken()
if level.kind != fplUnknown: if level.kind != fplUnknown:
parserError("Unexpected tag handle") parserError("Unexpected tag handle")
if tag != yTagQuestionmark: if tag != yTagQuestionMark:
parserError("Only one tag handle is allowed per node") parserError("Only one tag handle is allowed per node")
content = "" content = ""
var var
@ -281,7 +281,7 @@ template handleAlias() {.dirty.} =
startToken() startToken()
if level.kind != fplUnknown: if level.kind != fplUnknown:
parserError("Unexpected token") parserError("Unexpected token")
if anchor != yAnchorNone or tag != yTagQuestionmark: if anchor != yAnchorNone or tag != yTagQuestionMark:
parserError("Alias may not have anchor or tag") parserError("Alias may not have anchor or tag")
content = "" content = ""
p.lexer.anchorName(content) p.lexer.anchorName(content)
@ -338,7 +338,7 @@ template handleBlockItemStart() {.dirty.} =
level = FastParseLevel(kind: fplUnknown, indentation: indentation) level = FastParseLevel(kind: fplUnknown, indentation: indentation)
of fplMapValue: of fplMapValue:
yield scalarEvent("", tag, anchor) yield scalarEvent("", tag, anchor)
tag = yTagQuestionmark tag = yTagQuestionMark
anchor = yAnchorNone anchor = yAnchorNone
level.kind = fplMapKey level.kind = fplMapKey
ancestry.add(level) ancestry.add(level)
@ -1313,8 +1313,8 @@ proc parse*(p: YamlParser, s: Stream): YamlStream =
var stateAfter: FastParseState var stateAfter: FastParseState
content = "" content = ""
p.lexer.blockScalar(content, stateAfter) p.lexer.blockScalar(content, stateAfter)
if tag == yTagQuestionmark: if tag == yTagQuestionMark:
tag = yTagExclamationmark tag = yTagExclamationMark
yield scalarEvent(content, tag, anchor) yield scalarEvent(content, tag, anchor)
handleObjectEnd(stateAfter) handleObjectEnd(stateAfter)
of '-': of '-':
@ -1424,14 +1424,14 @@ proc parse*(p: YamlParser, s: Stream): YamlStream =
case level.kind case level.kind
of fplMapValue: of fplMapValue:
yield scalarEvent("", tag, anchor) yield scalarEvent("", tag, anchor)
tag = yTagQuestionmark tag = yTagQuestionMark
anchor = yAnchorNone anchor = yAnchorNone
level.kind = fplMapKey level.kind = fplMapKey
of fplMapKey: of fplMapKey:
if tag != yTagQuestionmark or anchor != yAnchorNone or if tag != yTagQuestionMark or anchor != yAnchorNone or
explicitFlowKey: explicitFlowKey:
yield scalarEvent("", tag, anchor) yield scalarEvent("", tag, anchor)
tag = yTagQuestionmark tag = yTagQuestionMark
anchor = yAnchorNone anchor = yAnchorNone
yield scalarEvent("", tag, anchor) yield scalarEvent("", tag, anchor)
of fplSequence: of fplSequence:
@ -1446,9 +1446,9 @@ proc parse*(p: YamlParser, s: Stream): YamlStream =
level = ancestry.pop() level = ancestry.pop()
case level.kind case level.kind
of fplSequence: of fplSequence:
if tag != yTagQuestionmark or anchor != yAnchorNone: if tag != yTagQuestionMark or anchor != yAnchorNone:
yield scalarEvent("", tag, anchor) yield scalarEvent("", tag, anchor)
tag = yTagQuestionmark tag = yTagQuestionMark
anchor = yAnchorNone anchor = yAnchorNone
of fplMapKey, fplMapValue: of fplMapKey, fplMapValue:
startToken() startToken()
@ -1463,17 +1463,17 @@ proc parse*(p: YamlParser, s: Stream): YamlStream =
case level.kind case level.kind
of fplSequence: of fplSequence:
yield scalarEvent("", tag, anchor) yield scalarEvent("", tag, anchor)
tag = yTagQuestionmark tag = yTagQuestionMark
anchor = yAnchorNone anchor = yAnchorNone
of fplMapValue: of fplMapValue:
yield scalarEvent("", tag, anchor) yield scalarEvent("", tag, anchor)
tag = yTagQuestionmark tag = yTagQuestionMark
anchor = yAnchorNone anchor = yAnchorNone
level.kind = fplMapKey level.kind = fplMapKey
explicitFlowKey = false explicitFlowKey = false
of fplMapKey: of fplMapKey:
yield scalarEvent("", tag, anchor) yield scalarEvent("", tag, anchor)
tag = yTagQuestionmark tag = yTagQuestionMark
anchor = yAnchorNone anchor = yAnchorNone
yield scalarEvent("", tag, anchor) yield scalarEvent("", tag, anchor)
explicitFlowKey = false explicitFlowKey = false
@ -1492,7 +1492,7 @@ proc parse*(p: YamlParser, s: Stream): YamlStream =
parserError("Unexpected token (expected ',')") parserError("Unexpected token (expected ',')")
of fplMapKey: of fplMapKey:
yield scalarEvent("", tag, anchor) yield scalarEvent("", tag, anchor)
tag = yTagQuestionmark tag = yTagQuestionMark
anchor = yAnchorNone anchor = yAnchorNone
level.kind = fplMapValue level.kind = fplMapValue
of fplUnknown, fplScalar: of fplUnknown, fplScalar:
@ -1514,8 +1514,8 @@ proc parse*(p: YamlParser, s: Stream): YamlStream =
content = "" content = ""
startToken() startToken()
p.lexer.doubleQuotedScalar(content) p.lexer.doubleQuotedScalar(content)
if tag == yTagQuestionmark: if tag == yTagQuestionMark:
tag = yTagExclamationmark tag = yTagExclamationMark
yield scalarEvent(content, tag, anchor) yield scalarEvent(content, tag, anchor)
handleObjectEnd(fpFlowAfterObject) handleObjectEnd(fpFlowAfterObject)
of '!': of '!':
@ -1567,7 +1567,7 @@ proc parse*(p: YamlParser, s: Stream): YamlStream =
of fplSequence: of fplSequence:
discard discard
of fplMapValue: of fplMapValue:
yield scalarEvent("", yTagQuestionmark, yAnchorNone) yield scalarEvent("", yTagQuestionMark, yAnchorNone)
level.kind = fplMapKey level.kind = fplMapKey
explicitFlowKey = false explicitFlowKey = false
of fplMapKey: of fplMapKey:

View File

@ -206,9 +206,9 @@ proc loadToJson*(s: Stream): seq[JsonNode] =
raise e raise e
except YamlConstructionStreamError: except YamlConstructionStreamError:
let e = getCurrentException() let e = getCurrentException()
if e.parent is IOError: if e.parent of IOError:
raise cast[ref IOError](e.parent) raise cast[ref IOError](e.parent)
elif e.parent is YamlParserError: elif e.parent of YamlParserError:
raise cast[ref YamlParserError](e.parent) raise cast[ref YamlParserError](e.parent)
else: else:
# can never happen # can never happen

View File

@ -4,6 +4,8 @@
# See the file "copying.txt", included in this # See the file "copying.txt", included in this
# distribution, for details about the copyright. # distribution, for details about the copyright.
import typetraits
type type
DumperState = enum DumperState = enum
dBlockExplicitMapKey, dBlockImplicitMapKey, dBlockMapValue, dBlockExplicitMapKey, dBlockImplicitMapKey, dBlockMapValue,
@ -12,7 +14,7 @@ type
dFlowSequenceStart dFlowSequenceStart
proc needsEscaping(scalar: string): bool {.raises: [].} = proc needsEscaping(scalar: string): bool {.raises: [].} =
scalar.len == 0 or scalar.len == 0 or scalar[0] in ['@', '`'] or
scalar.find({'{', '}', '[', ']', ',', '#', '-', ':', '?', '%', '"', scalar.find({'{', '}', '[', ']', ',', '#', '-', ':', '?', '%', '"',
'\'', '\x0A', '\c'}) != -1 '\'', '\x0A', '\c'}) != -1
@ -164,7 +166,7 @@ proc present*(s: YamlStream, target: Stream, tagLib: TagLibrary,
if finished(s): if finished(s):
break break
cached.enqueue(item) cached.enqueue(item)
except: except Exception:
var e = newException(YamlPresenterStreamError, "") var e = newException(YamlPresenterStreamError, "")
e.parent = getCurrentException() e.parent = getCurrentException()
raise e raise e
@ -208,10 +210,16 @@ proc present*(s: YamlStream, target: Stream, tagLib: TagLibrary,
elif item.scalarTag in [yTagQuestionMark, yTagNull] and elif item.scalarTag in [yTagQuestionMark, yTagNull] and
hint == yTypeNull: hint == yTypeNull:
safeWrite("null") safeWrite("null")
elif item.scalarTag in [yTagQuestionMark, yTagInteger] and
hint == yTypeInteger:
safeWrite(item.scalarContent)
elif item.scalarTag in [yTagQuestionMark, yTagFloat] and elif item.scalarTag in [yTagQuestionMark, yTagFloat] and
hint in [yTypeFloatInf, yTypeFloatNaN]: hint in [yTypeFloatInf, yTypeFloatNaN]:
raise newException(YamlPresenterJsonError, raise newException(YamlPresenterJsonError,
"Infinity and not-a-number values cannot be presented as JSON!") "Infinity and not-a-number values cannot be presented as JSON!")
elif item.scalarTag in [yTagQuestionMark, yTagFloat] and
hint == yTypeFloat:
safeWrite(item.scalarContent)
else: else:
writeDoubleQuoted(item.scalarContent, target) writeDoubleQuoted(item.scalarContent, target)
elif style == psCanonical or item.scalarContent.needsEscaping: elif style == psCanonical or item.scalarContent.needsEscaping:
@ -251,7 +259,7 @@ proc present*(s: YamlStream, target: Stream, tagLib: TagLibrary,
else: else:
length = high(int) length = high(int)
break break
except: except Exception:
var e = newException(YamlPresenterStreamError, "") var e = newException(YamlPresenterStreamError, "")
e.parent = getCurrentException() e.parent = getCurrentException()
raise e raise e
@ -316,7 +324,7 @@ proc present*(s: YamlStream, target: Stream, tagLib: TagLibrary,
break break
else: else:
mps = mpNeedBlock mps = mpNeedBlock
except: except Exception:
var e = newException(YamlPresenterStreamError, "") var e = newException(YamlPresenterStreamError, "")
e.parent = getCurrentException() e.parent = getCurrentException()
raise e raise e
@ -442,7 +450,7 @@ proc present*(s: YamlStream, target: Stream, tagLib: TagLibrary,
if finished(s): if finished(s):
break break
cached.enqueue(next) cached.enqueue(next)
except: except Exception:
var e = newException(YamlPresenterStreamError, "") var e = newException(YamlPresenterStreamError, "")
e.parent = getCurrentException() e.parent = getCurrentException()
raise e raise e
@ -493,9 +501,9 @@ proc transform*(input: Stream, output: Stream, style: PresentationStyle,
present(events, output, tagLib, style, indentationStep) present(events, output, tagLib, style, indentationStep)
except YamlPresenterStreamError: except YamlPresenterStreamError:
let e = getCurrentException() let e = getCurrentException()
if e.parent is IOError: if e.parent of IOError:
raise cast[ref IOError](e.parent) raise cast[ref IOError](e.parent)
elif e.parent is YamlParserError: elif e.parent of YamlParserError:
raise cast[ref YamlParserError](e.parent) raise cast[ref YamlParserError](e.parent)
else: else:
# never happens # never happens

46
test/constructingJson.nim Normal file
View File

@ -0,0 +1,46 @@
import "../yaml"
import unittest, json
proc wc(line, column: int, lineContent: string, message: string) =
echo "Warning (", line, ",", column, "): ", message, "\n", lineContent
proc ensureEqual(yamlIn, jsonIn: string) =
var
parser = newYamlParser(initCoreTagLibrary(), wc)
yamlResult = constructJson(parser.parse(newStringStream(yamlIn)))
jsonResult = parseJson(jsonIn)
assert yamlResult.len == 1
assert(jsonResult == yamlResult[0])
suite "Constructing JSON":
test "Constructing JSON: Simple Sequence":
ensureEqual("- 1\n- 2\n- 3", "[1, 2, 3]")
test "Constructing JSON: Simple Map":
ensureEqual("a: b\nc: d", """{"a": "b", "c": "d"}""")
test "Constructing JSON: Complex Structure":
ensureEqual("""
%YAML 1.2
---
Foo:
- - a
- b
- c
- bla: blubb
Numbers, bools, special values:
- 1
- true
- ~
- 42.23
- no
""", """{
"Foo": [
[ "a", "b", "c"],
{ "bla": "blubb"}
],
"Numbers, bools, special values": [
1, true, null, 42.23, false
]
}""")

View File

@ -1,7 +1,7 @@
import "../yaml/serialization" import "../yaml/serialization"
import unittest import unittest
make_serializable: serializable:
type type
Person = object Person = object
firstname, surname: string firstname, surname: string

View File

@ -27,7 +27,7 @@ type
TypeHint* = enum TypeHint* = enum
## A type hint can be computed from scalar content and tells you what ## A type hint can be computed from scalar content and tells you what
## NimYAML thinks the scalar's type is. It is generated by ## NimYAML thinks the scalar's type is. It is generated by
## `guessType <#guessType,string,TypeHint>`_ The first matching RegEx ## `guessType <#guessType,string>`_ The first matching RegEx
## in the following table will be the type hint of a scalar string. ## in the following table will be the type hint of a scalar string.
## ##
## You can use it to determine the type of YAML scalars that have a '?' ## You can use it to determine the type of YAML scalars that have a '?'
@ -118,14 +118,9 @@ type
TagLibrary* = ref object TagLibrary* = ref object
## A ``TagLibrary`` maps tag URIs to ``TagId`` s. ## A ``TagLibrary`` maps tag URIs to ``TagId`` s.
## ##
## Three tag libraries are provided with this module:
## `failsafeTagLibrary <#failsafeTagLibrary>`_,
## `coreTagLibrary <#coreTagLibrary>`_, and
## `extendedTagLibrary <#extendedTagLibrary>`_.
##
## When `YamlParser <#YamlParser>`_ encounters tags not existing in the ## When `YamlParser <#YamlParser>`_ encounters tags not existing in the
## tag library, it will use ## tag library, it will use
## `registerTagUri <#registerTagUri,TagLibrary,string,TagId>`_ to add ## `registerTagUri <#registerTagUri,TagLibrary,string>`_ to add
## the tag to the library. ## the tag to the library.
## ##
## You can base your tag library on common tag libraries by initializing ## You can base your tag library on common tag libraries by initializing
@ -148,7 +143,7 @@ type
YamlParser* = ref object YamlParser* = ref object
## A parser object. Retains its ``TagLibrary`` across calls to ## A parser object. Retains its ``TagLibrary`` across calls to
## `parse <#parse,YamlParser,Stream,YamlStream>`_. Can be used ## `parse <#parse,YamlParser,Stream>`_. Can be used
## to access anchor names while parsing a YAML character stream, but ## to access anchor names while parsing a YAML character stream, but
## only until the document goes out of scope (i.e. until ## only until the document goes out of scope (i.e. until
## ``yamlEndDocument`` is yielded). ## ``yamlEndDocument`` is yielded).

View File

@ -6,18 +6,27 @@ type
TagStyle* = enum TagStyle* = enum
tsNone, tsRootOnly, tsAll tsNone, tsRootOnly, tsAll
proc initSerializationTagLibrary(): TagLibrary = const
yTagNimInt* = 100.TagId
yTagNimInt64* = 101.TagId
yTagNimFloat* = 102.TagId
yTagNimFloat64* = 103.TagId
proc initSerializationTagLibrary(): TagLibrary {.raises: [].} =
result = initTagLibrary() result = initTagLibrary()
result.tags["!"] = yTagExclamationMark result.tags["!"] = yTagExclamationMark
result.tags["?"] = yTagQuestionMark result.tags["?"] = yTagQuestionMark
result.tags["tag:yaml.org,2002:str"] = yTagString result.tags["tag:yaml.org,2002:str"] = yTagString
result.tags["tag:yaml.org,2002:null"] = yTagNull result.tags["tag:yaml.org,2002:null"] = yTagNull
result.tags["tag:yaml.org,2002:bool"] = yTagBoolean result.tags["tag:yaml.org,2002:bool"] = yTagBoolean
result.tags["tag:yaml.org,2002:int"] = yTagInteger
result.tags["tag:yaml.org,2002:float"] = yTagFloat result.tags["tag:yaml.org,2002:float"] = yTagFloat
result.tags["tag:yaml.org,2002:timestamp"] = yTagTimestamp result.tags["tag:yaml.org,2002:timestamp"] = yTagTimestamp
result.tags["tag:yaml.org,2002:value"] = yTagValue result.tags["tag:yaml.org,2002:value"] = yTagValue
result.tags["tag:yaml.org,2002:binary"] = yTagBinary result.tags["tag:yaml.org,2002:binary"] = yTagBinary
result.tags["!nim:int"] = yTagNimInt
result.tags["!nim:int64"] = yTagNimInt64
result.tags["!nim:float"] = yTagNimFloat
result.tags["!nim:float64"] = yTagNimFloat64
var var
serializationTagLibrary* = initSerializationTagLibrary() ## \ serializationTagLibrary* = initSerializationTagLibrary() ## \
@ -26,11 +35,12 @@ var
## as those are not suited for Nim's static type system. ## as those are not suited for Nim's static type system.
## ##
## Should not be modified manually. Will be extended by ## Should not be modified manually. Will be extended by
## `make_serializable <#make_serializable,stmt,stmt`_. ## `serializable <#serializable,stmt,stmt>`_.
static: static:
iterator objectFields(n: NimNode): tuple[name: NimNode, t: NimNode] = iterator objectFields(n: NimNode): tuple[name: NimNode, t: NimNode]
{.raises: [].} =
assert n.kind in [nnkRecList, nnkTupleTy] 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
@ -42,13 +52,13 @@ static:
template presentTag(t: typedesc, tagStyle: TagStyle): TagId = template presentTag(t: typedesc, tagStyle: TagStyle): TagId =
if tagStyle == tsNone: yTagQuestionMark else: yamlTag(t) if tagStyle == tsNone: yTagQuestionMark else: yamlTag(t)
proc lazyLoadTag*(uri: string): TagId {.inline.} = proc lazyLoadTag*(uri: string): TagId {.inline, raises: [].} =
try: try:
result = serializationTagLibrary.tags[uri] result = serializationTagLibrary.tags[uri]
except KeyError: except KeyError:
result = serializationTagLibrary.registerUri(uri) result = serializationTagLibrary.registerUri(uri)
macro make_serializable*(types: stmt): stmt = macro serializable*(types: stmt): stmt =
assert types.kind == nnkTypeSection assert types.kind == nnkTypeSection
result = newStmtList(types) result = newStmtList(types)
for typedef in types.children: for typedef in types.children:
@ -116,32 +126,36 @@ macro make_serializable*(types: stmt): stmt =
newIdentDefs(newIdentNode("s"), newIdentNode("YamlStream")), newIdentDefs(newIdentNode("s"), newIdentNode("YamlStream")),
newIdentDefs(newIdentNode("result"), newIdentDefs(newIdentNode("result"),
newNimNode(nnkVarTy).add(tIdent))]) newNimNode(nnkVarTy).add(tIdent))])
constructProc[4] = newNimNode(nnkPragma).add(
newNimNode(nnkExprColonExpr).add(newIdentNode("raises"),
newNimNode(nnkBracket).add(
newIdentNode("YamlConstructionError"),
newIdentNode("YamlConstructionStreamError"))))
impl = quote do: impl = quote do:
var event = s() var event = s()
if finished(s) or event.kind != yamlStartMap: if finished(s) or event.kind != yamlStartMap:
raise newException(ValueError, "Construction error!") raise newException(YamlConstructionError, "Expected map start")
if event.mapTag != yTagQuestionMark and if event.mapTag != yTagQuestionMark and
event.mapTag != yamlTag(type(`tIdent`)): event.mapTag != yamlTag(type(`tIdent`)):
raise newException(ValueError, "Wrong tag for " & `tName`) raise newException(YamlConstructionError,
"Wrong tag for " & `tName`)
event = s() event = s()
if finished(s): assert(not finished(s))
raise newException(ValueError, "Construction error!")
while event.kind != yamlEndMap: while event.kind != yamlEndMap:
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 event.scalarContent
else: else:
raise newException(ValueError, "Unknown key for " & raise newException(YamlConstructionError,
`tName` & ": " & event.scalarContent) "Unknown key for " & `tName` & ": " &
event.scalarContent)
event = s() event = s()
if finished(s): assert(not finished(s))
raise newException(ValueError, "Construction error!")
var keyCase = impl[5][1][2] var keyCase = impl[5][1][2]
assert keyCase.kind == nnkCaseStmt assert keyCase.kind == nnkCaseStmt
for field in objectFields(recList): for field in objectFields(recList):
let nameHash = hash($field.name.ident)
keyCase.insert(1, newNimNode(nnkOfBranch).add( keyCase.insert(1, newNimNode(nnkOfBranch).add(
newIntLitNode(nameHash)).add(newStmtList( newStrLitNode($field.name.ident)).add(newStmtList(
newCall("construct", [newIdentNode("s"), newDotExpr( newCall("construct", [newIdentNode("s"), newDotExpr(
newIdentNode("result"), field.name)]) newIdentNode("result"), field.name)])
)) ))
@ -158,6 +172,9 @@ macro make_serializable*(types: stmt): stmt =
newIdentDefs(newIdentNode("tagStyle"), newIdentDefs(newIdentNode("tagStyle"),
newIdentNode("TagStyle"), newIdentNode("TagStyle"),
newIdentNode("tsNone"))]) newIdentNode("tsNone"))])
serializeProc[4] = newNimNode(nnkPragma).add(
newNimNode(nnkExprColonExpr).add(newIdentNode("raises"),
newNimNode(nnkBracket)))
var iterBody = newStmtList( var iterBody = newStmtList(
newLetStmt(newIdentNode("childTagStyle"), newNimNode(nnkIfExpr).add( newLetStmt(newIdentNode("childTagStyle"), newNimNode(nnkIfExpr).add(
newNimNode(nnkElifExpr).add( newNimNode(nnkElifExpr).add(
@ -213,77 +230,98 @@ macro make_serializable*(types: stmt): stmt =
serializeProc[6] = impl serializeProc[6] = impl
result.add(serializeProc) result.add(serializeProc)
proc prepend*(event: YamlStreamEvent, s: YamlStream): YamlStream = proc prepend(event: YamlStreamEvent, s: YamlStream): YamlStream {.raises: [].} =
result = iterator(): YamlStreamEvent = result = iterator(): YamlStreamEvent =
yield event yield event
for e in s(): for e in s():
yield e yield e
proc yamlTag*(T: typedesc[string]): TagId {.inline.} = yTagString proc safeTagUri*(id: TagId): string {.raises: [].} =
try:
proc safeTagUri*(id: TagId): string =
let uri = serializationTagLibrary.uri(id) let uri = serializationTagLibrary.uri(id)
if uri.len > 0 and uri[0] == '!': if uri.len > 0 and uri[0] == '!':
return uri[1..uri.len - 1] return uri[1..uri.len - 1]
else: else:
return uri return uri
except KeyError:
# cannot happen (theoretically, you known)
assert(false)
proc construct*(s: YamlStream, result: var string) = template constructScalarItem(item: YamlStreamEvent, name: string, t: TagId,
let item = s() content: stmt) =
try:
item = s()
except Exception:
var e = newException(YamlConstructionStreamError, "")
e.parent = getCurrentException()
raise e
if finished(s) or item.kind != yamlScalar: if finished(s) or item.kind != yamlScalar:
raise newException(ValueError, "Construction error!") raise newException(YamlConstructionError, "Expected scalar")
if item.scalarTag notin [yTagQuestionMark, yTagExclamationMark, yTagString]: if item.scalarTag notin [yTagQuestionMark, yTagExclamationMark, t]:
raise newException(ValueError, "Wrong tag for string.") raise newException(YamlConstructionError, "Wrong tag for " & name)
try:
content
except YamlConstructionError:
raise
except Exception:
var e = newException(YamlConstructionError,
"Cannot construct to " & name & ": " & item.scalarContent)
e.parent = getCurrentException()
raise e
template safeNextEvent(e: YamlStreamEvent, s: YamlStream) =
try:
e = s()
except Exception:
var ex = newException(YamlConstructionStreamError, "")
ex.parent = getCurrentException()
raise ex
proc yamlTag*(T: typedesc[string]): TagId {.inline, raises: [].} = yTagString
proc construct*(s: YamlStream, result: var string)
{.raises: [YamlConstructionError, YamlConstructionStreamError].} =
var item: YamlStreamEvent
constructScalarItem(item, "string", yTagString):
result = item.scalarContent result = item.scalarContent
proc serialize*(value: string, proc serialize*(value: string,
tagStyle: TagStyle = tsNone): YamlStream = tagStyle: TagStyle = tsNone): YamlStream {.raises: [].} =
result = iterator(): YamlStreamEvent = result = iterator(): YamlStreamEvent =
yield scalarEvent(value, presentTag(string, tagStyle), yAnchorNone) yield scalarEvent(value, presentTag(string, tagStyle), yAnchorNone)
proc yamlTag*(T: typedesc[int]): TagId {.inline.} = yTagInteger proc yamlTag*(T: typedesc[int]): TagId {.inline.} = yTagNimInt
proc construct*(s: YamlStream, result: var int) = proc construct*(s: YamlStream, result: var int)
let item = s() {.raises: [YamlConstructionError, YamlConstructionStreamError].} =
if finished(s) or item.kind != yamlScalar: var item: YamlStreamEvent
raise newException(ValueError, "Construction error!") constructScalarItem(item, "int", yTagNimInt):
if item.scalarTag != yTagInteger and not (
item.scalarTag == yTagQuestionMark and
guessType(item.scalarContent) == yTypeInteger):
raise newException(ValueError, "Wrong scalar type for int.")
result = parseInt(item.scalarContent) result = parseInt(item.scalarContent)
proc serialize*(value: int, tagStyle: TagStyle = tsNone): YamlStream = proc serialize*(value: int, tagStyle: TagStyle = tsNone): YamlStream =
result = iterator(): YamlStreamEvent = result = iterator(): YamlStreamEvent {.raises: [].} =
yield scalarEvent($value, presentTag(int, tagStyle), yAnchorNone) yield scalarEvent($value, presentTag(int, tagStyle), yAnchorNone)
proc yamlTag*(T: typedesc[int64]): TagId {.inline.} = yTagInteger proc yamlTag*(T: typedesc[int64]): TagId {.inline, raises: [].} = yTagNimInt64
proc contruct*(s: YamlStream, result: var int64) = proc contruct*(s: YamlStream, result: var int64)
let item = s() {.raises: [YamlConstructionError, YamlConstructionStreamError].} =
if finished(s) or item.kind != yamlScalar: var item: YamlStreamEvent
raise newException(ValueError, "Construction error!") constructScalarItem(item, "int64", yTagNimInt64):
if item.scalarTag != yTagInteger and not (
item.scalarTag == yTagQuestionMark and
guessType(item.scalarContent) == yTypeInteger):
raise newException(ValueError, "Wrong scalar type for int64.")
result = parseBiggestInt(item.scalarContent) result = parseBiggestInt(item.scalarContent)
proc serialize*(value: int64, tagStyle: TagStyle = tsNone): YamlStream = proc serialize*(value: int64, tagStyle: TagStyle = tsNone): YamlStream
{.raises: [].}=
result = iterator(): YamlStreamEvent = result = iterator(): YamlStreamEvent =
yield scalarEvent($value, presentTag(int64, tagStyle), yAnchorNone) yield scalarEvent($value, presentTag(int64, tagStyle), yAnchorNone)
proc yamlTag*(T: typedesc[float]): TagId {.inline.} = yTagFloat proc yamlTag*(T: typedesc[float]): TagId {.inline, raises: [].} = yTagNimFloat
proc construct*(s: YamlStream, result: var float) = proc construct*(s: YamlStream, result: var float)
let item = s() {.raises: [YamlConstructionError, YamlConstructionStreamError].} =
if finished(s) or item.kind != yamlScalar: var item: YamlStreamEvent
raise newException(ValueError, "Construction error!") constructScalarItem(item, "float", yTagNimFloat):
let hint = guessType(item.scalarContent) let hint = guessType(item.scalarContent)
if item.scalarTag != yTagFloat and not (
item.scalarTag == yTagQuestionMark and
hint in [yTypeFloat, yTypeFloatInf, yTypeFloatNaN]):
raise newException(ValueError, "Wrong scalar type for float.")
case hint case hint
of yTypeFloat: of yTypeFloat:
result = parseFloat(item.scalarContent) result = parseFloat(item.scalarContent)
@ -295,9 +333,11 @@ proc construct*(s: YamlStream, result: var float) =
of yTypeFloatNaN: of yTypeFloatNaN:
result = NaN result = NaN
else: else:
raise newException(ValueError, "Wrong scalar type for float.") raise newException(YamlConstructionError,
"Cannot construct to float: " & item.scalarContent)
proc serialize*(value: float, tagStyle: TagStyle = tsNone): YamlStream = proc serialize*(value: float, tagStyle: TagStyle = tsNone): YamlStream
{.raises: [].}=
result = iterator(): YamlStreamEvent = result = iterator(): YamlStreamEvent =
var var
asString: string asString: string
@ -312,57 +352,57 @@ proc serialize*(value: float, tagStyle: TagStyle = tsNone): YamlStream =
asString = $value asString = $value
yield scalarEvent(asString, presentTag(float, tagStyle), yAnchorNone) yield scalarEvent(asString, presentTag(float, tagStyle), yAnchorNone)
proc yamlTag*(T: typedesc[bool]): TagId {.inline.} = yTagBoolean proc yamlTag*(T: typedesc[bool]): TagId {.inline, raises: [].} = yTagBoolean
proc construct*(s: YamlStream, result: var bool) = proc construct*(s: YamlStream, result: var bool)
let item = s() {.raises: [YamlConstructionError, YamlConstructionStreamError].} =
if finished(s) or item.kind != yamlScalar: var item: YamlStreamEvent
raise newException(ValueError, "Construction error!") constructScalarItem(item, "bool", yTagBoolean):
let hint = guessType(item.scalarContent) case guessType(item.scalarContent)
case item.scalarTag
of yTagQuestionMark, yTagBoolean:
case hint
of yTypeBoolTrue: of yTypeBoolTrue:
result = true result = true
of yTypeBoolFalse: of yTypeBoolFalse:
result = false result = false
else: else:
raise newException(ValueError, raise newException(YamlConstructionError,
"Not a boolean: " & item.scalarContent) "Cannot construct to bool: " & item.scalarContent)
else:
raise newException(ValueError, "Wrong scalar type for bool")
proc serialize*(value: bool, tagStyle: TagStyle = tsNone): YamlStream = proc serialize*(value: bool, tagStyle: TagStyle = tsNone): YamlStream
{.raises: [].}=
result = iterator(): YamlStreamEvent = result = iterator(): YamlStreamEvent =
yield scalarEvent(if value: "y" else: "n", presentTag(bool, tagStyle), yield scalarEvent(if value: "y" else: "n", presentTag(bool, tagStyle),
yAnchorNone) yAnchorNone)
proc yamlTag*[I](T: typedesc[seq[I]]): TagId {.inline.} = proc yamlTag*[I](T: typedesc[seq[I]]): TagId {.inline, raises: [].} =
let uri = "!nim:seq(" & safeTagUri(yamlTag(I)) & ")" let uri = "!nim:seq(" & safeTagUri(yamlTag(I)) & ")"
result = lazyLoadTag(uri) result = lazyLoadTag(uri)
proc construct*[T](s: YamlStream, result: var seq[T]) = proc construct*[T](s: YamlStream, result: var seq[T])
var event = s() {.raises: [YamlConstructionError, YamlConstructionStreamError].} =
var event: YamlStreamEvent
safeNextEvent(event, s)
if finished(s) or event.kind != yamlStartSequence: if finished(s) or event.kind != yamlStartSequence:
raise newException(ValueError, "Construction error!1") raise newException(YamlConstructionError, "Expected sequence start")
if event.seqTag != yTagQuestionMark and if event.seqTag notin [yTagQuestionMark, yamlTag(seq[T])]:
event.seqTag != yamlTag(seq[T]): raise newException(YamlConstructionError, "Wrong tag for seq[T]")
raise newException(ValueError, "Wrong sequence type for seq[T]")
result = newSeq[T]() result = newSeq[T]()
event = s() safeNextEvent(event, s)
if finished(s): assert(not finished(s))
raise newException(ValueError, "Construction error!2")
while event.kind != yamlEndSequence: while event.kind != yamlEndSequence:
var var
item: T item: T
events = prepend(event, s) events = prepend(event, s)
try:
construct(events, item) construct(events, item)
except:
# compiler bug: https://github.com/nim-lang/Nim/issues/3772
assert(false)
result.add(item) result.add(item)
event = s() safeNextEvent(event, s)
if finished(s): assert(not finished(s))
raise newException(ValueError, "Construction error!3")
proc serialize*[T](value: seq[T], tagStyle: TagStyle = tsNone): YamlStream = proc serialize*[T](value: seq[T], tagStyle: TagStyle = tsNone): YamlStream
{.raises: [].} =
result = iterator(): YamlStreamEvent = result = iterator(): YamlStreamEvent =
let childTagStyle = if tagStyle == tsRootOnly: tsNone else: tagStyle let childTagStyle = if tagStyle == tsRootOnly: tsNone else: tagStyle
yield YamlStreamEvent(kind: yamlStartSequence, yield YamlStreamEvent(kind: yamlStartSequence,
@ -374,41 +414,49 @@ proc serialize*[T](value: seq[T], tagStyle: TagStyle = tsNone): YamlStream =
yield event yield event
yield YamlStreamEvent(kind: yamlEndSequence) yield YamlStreamEvent(kind: yamlEndSequence)
proc yamlTag*[K, V](T: typedesc[Table[K, V]]): TagId {.inline.} = proc yamlTag*[K, V](T: typedesc[Table[K, V]]): TagId {.inline, raises: [].} =
try:
let let
keyUri = serializationTagLibrary.uri(yamlTag(K)) keyUri = serializationTagLibrary.uri(yamlTag(K))
valueUri = serializationTagLibrary.uri(yamlTag(V)) valueUri = serializationTagLibrary.uri(yamlTag(V))
keyIdent = if keyUri[0] == '!': keyUri[1..keyUri.len - 1] else: keyUri keyIdent = if keyUri[0] == '!': keyUri[1..keyUri.len - 1] else:
keyUri
valueIdent = if valueUri[0] == '!': valueIdent = if valueUri[0] == '!':
valueUri[1..valueUri.len - 1] else: valueUri valueUri[1..valueUri.len - 1] else: valueUri
uri = "!nim:Table(" & keyUri & "," & valueUri & ")" uri = "!nim:Table(" & keyUri & "," & valueUri & ")"
result = lazyLoadTag(uri) result = lazyLoadTag(uri)
except KeyError:
# cannot happen (theoretically, you known)
assert(false)
proc construct*[K, V](s: YamlStream, result: var Table[K, V]) = proc construct*[K, V](s: YamlStream, result: var Table[K, V])
var event = s() {.raises: [YamlConstructionError, YamlConstructionStreamError].} =
var event: YamlStreamEvent
safeNextEvent(event, s)
if finished(s) or event.kind != yamlStartMap: if finished(s) or event.kind != yamlStartMap:
raise newException(ValueError, "Construction error!") raise newException(YamlConstructionError, "Expected map start")
if event.mapTag != yTagQuestionMark and if event.mapTag notin [yTagQuestionMark, yamlTag(Table[K, V])]:
event.mapTag != yamlTag(Table[K, V]): raise newException(YamlConstructionError, "Wrong tag for Table[K, V]")
raise newException(ValueError, "Wrong map type for Table[K, V]")
result = initTable[K, V]() result = initTable[K, V]()
event = s() safeNextEvent(event, s)
if finished(s): assert(not finished(s))
raise newException(ValueError, "Construction error!")
while event.kind != yamlEndMap: while event.kind != yamlEndMap:
var var
key: K key: K
value: V value: V
events = prepend(event, s) events = prepend(event, s)
try:
construct(events, key) construct(events, key)
construct(s, value) construct(s, value)
except Exception:
# compiler bug: https://github.com/nim-lang/Nim/issues/3772
assert(false)
result[key] = value result[key] = value
event = s() safeNextEvent(event, s)
if finished(s): assert(not finished(s))
raise newException(ValueError, "Construction error!")
proc serialize*[K, V](value: Table[K, V], proc serialize*[K, V](value: Table[K, V],
tagStyle: TagStyle = tsNone): YamlStream = tagStyle: TagStyle = tsNone): YamlStream {.raises: [].} =
result = iterator(): YamlStreamEvent = result = iterator(): YamlStreamEvent =
let childTagStyle = if tagStyle == tsRootOnly: tsNone else: tagStyle let childTagStyle = if tagStyle == tsRootOnly: tsNone else: tagStyle
yield YamlStreamEvent(kind: yamlStartMap, yield YamlStreamEvent(kind: yamlStartMap,
@ -423,21 +471,50 @@ proc serialize*[K, V](value: Table[K, V],
yield event yield event
yield YamlStreamEvent(kind: yamlEndMap) yield YamlStreamEvent(kind: yamlEndMap)
proc load*[K](input: Stream, target: var K) = proc load*[K](input: Stream, target: var K)
{.raises: [YamlConstructionError, IOError, YamlParserError].} =
try:
var var
tagLib = serializationTagLibrary parser = newYamlParser(serializationTagLibrary)
events = parse(tagLib, input) events = parser.parse(input)
assert events().kind == yamlStartDocument assert events().kind == yamlStartDocument
construct(events, target) construct(events, target)
assert events().kind == yamlEndDocument assert events().kind == yamlEndDocument
except YamlConstructionError, IOError, YamlParserError:
raise
except YamlConstructionStreamError:
let e = cast[ref YamlConstructionError](getCurrentException())
if e.parent of IOError:
raise cast[ref IOError](e.parent)
elif e.parent of YamlParserError:
raise cast[ref YamlParserError](e.parent)
else:
assert(false)
except Exception:
# compiler bug: https://github.com/nim-lang/Nim/issues/3772
assert(false)
proc dump*[K](value: K, target: Stream, style: PresentationStyle = psDefault, proc dump*[K](value: K, target: Stream, style: PresentationStyle = psDefault,
tagStyle: TagStyle = tsRootOnly, indentationStep: int = 2) = tagStyle: TagStyle = tsRootOnly, indentationStep: int = 2)
{.raises: [YamlConstructionError, YamlConstructionStreamError,
YamlPresenterJsonError, YamlPresenterOutputError].} =
var serialized = serialize(value, var serialized = serialize(value,
if style == psCanonical: tsAll else: tagStyle) if style == psCanonical: tsAll else: tagStyle)
var events = iterator(): YamlStreamEvent = var events = iterator(): YamlStreamEvent =
yield YamlStreamEvent(kind: yamlStartDocument) yield YamlStreamEvent(kind: yamlStartDocument)
for event in serialized(): while true:
var event: YamlStreamEvent
try:
event = serialized()
if finished(serialized): break
except Exception:
# serializing object does not raise any errors, so we can
# ignore this
assert(false)
yield event yield event
yield YamlStreamEvent(kind: yamlEndDocument) yield YamlStreamEvent(kind: yamlEndDocument)
try:
present(events, target, serializationTagLibrary, style, indentationStep) present(events, target, serializationTagLibrary, style, indentationStep)
except YamlPresenterStreamError:
# serializing object does not raise any errors, so we can ignore this
assert(false)