diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-14 20:19:53 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-14 20:19:53 +0000 |
commit | e7ee850d46d54789979bf0c5244bae1825fb7149 (patch) | |
tree | 6e94ed55df9ec749682a3c792ce752d07892b968 /_test | |
parent | Initial commit. (diff) | |
download | python-ruyaml-upstream.tar.xz python-ruyaml-upstream.zip |
Adding upstream version 0.91.0.upstream/0.91.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '_test')
616 files changed, 13986 insertions, 0 deletions
diff --git a/_test/__init__.py b/_test/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/_test/__init__.py diff --git a/_test/data/a-nasty-libyaml-bug.loader-error b/_test/data/a-nasty-libyaml-bug.loader-error new file mode 100644 index 0000000..f97d49f --- /dev/null +++ b/_test/data/a-nasty-libyaml-bug.loader-error @@ -0,0 +1 @@ +[ [
\ No newline at end of file diff --git a/_test/data/aliases-cdumper-bug.code b/_test/data/aliases-cdumper-bug.code new file mode 100644 index 0000000..0168441 --- /dev/null +++ b/_test/data/aliases-cdumper-bug.code @@ -0,0 +1 @@ +[ today, today ] diff --git a/_test/data/aliases.events b/_test/data/aliases.events new file mode 100644 index 0000000..9139b51 --- /dev/null +++ b/_test/data/aliases.events @@ -0,0 +1,8 @@ +- !StreamStart +- !DocumentStart +- !SequenceStart +- !Scalar { anchor: 'myanchor', tag: '!mytag', value: 'data' } +- !Alias { anchor: 'myanchor' } +- !SequenceEnd +- !DocumentEnd +- !StreamEnd diff --git a/_test/data/bool.data b/_test/data/bool.data new file mode 100644 index 0000000..ff99e77 --- /dev/null +++ b/_test/data/bool.data @@ -0,0 +1,18 @@ +- yes +- Yes +- YES +- no +- No +- NO +- true +- True +- TRUE +- false +- False +- FALSE +- on +- On +- ON +- off +- Off +- OFF diff --git a/_test/data/bool.detect b/_test/data/bool.detect new file mode 100644 index 0000000..947ebbb --- /dev/null +++ b/_test/data/bool.detect @@ -0,0 +1 @@ +tag:yaml.org,2002:bool diff --git a/_test/data/colon-in-flow-context.loader-error b/_test/data/colon-in-flow-context.loader-error new file mode 100644 index 0000000..13d5087 --- /dev/null +++ b/_test/data/colon-in-flow-context.loader-error @@ -0,0 +1 @@ +{ foo:bar } diff --git a/_test/data/comment_no_eol.data b/_test/data/comment_no_eol.data new file mode 100644 index 0000000..f7b15f6 --- /dev/null +++ b/_test/data/comment_no_eol.data @@ -0,0 +1 @@ +european: 10 # abc
\ No newline at end of file diff --git a/_test/data/composite_key.code b/_test/data/composite_key.code new file mode 100644 index 0000000..627b049 --- /dev/null +++ b/_test/data/composite_key.code @@ -0,0 +1 @@ +{('foo', 'bar'): 'baz'} diff --git a/_test/data/composite_key.data b/_test/data/composite_key.data new file mode 100644 index 0000000..d748e37 --- /dev/null +++ b/_test/data/composite_key.data @@ -0,0 +1,4 @@ +--- +? - foo + - bar +: baz diff --git a/_test/data/construct-binary-py3.code b/_test/data/construct-binary-py3.code new file mode 100644 index 0000000..30bfc3f --- /dev/null +++ b/_test/data/construct-binary-py3.code @@ -0,0 +1,7 @@ +{ + "canonical": + b"GIF89a\x0c\x00\x0c\x00\x84\x00\x00\xff\xff\xf7\xf5\xf5\xee\xe9\xe9\xe5fff\x00\x00\x00\xe7\xe7\xe7^^^\xf3\xf3\xed\x8e\x8e\x8e\xe0\xe0\xe0\x9f\x9f\x9f\x93\x93\x93\xa7\xa7\xa7\x9e\x9e\x9eiiiccc\xa3\xa3\xa3\x84\x84\x84\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9!\xfe\x0eMade with GIMP\x00,\x00\x00\x00\x00\x0c\x00\x0c\x00\x00\x05, \x8e\x810\x9e\xe3@\x14\xe8i\x10\xc4\xd1\x8a\x08\x1c\xcf\x80M$z\xef\xff0\x85p\xb8\xb01f\r\x1b\xce\x01\xc3\x01\x1e\x10' \x82\n\x01\x00;", + "generic": + b"GIF89a\x0c\x00\x0c\x00\x84\x00\x00\xff\xff\xf7\xf5\xf5\xee\xe9\xe9\xe5fff\x00\x00\x00\xe7\xe7\xe7^^^\xf3\xf3\xed\x8e\x8e\x8e\xe0\xe0\xe0\x9f\x9f\x9f\x93\x93\x93\xa7\xa7\xa7\x9e\x9e\x9eiiiccc\xa3\xa3\xa3\x84\x84\x84\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9!\xfe\x0eMade with GIMP\x00,\x00\x00\x00\x00\x0c\x00\x0c\x00\x00\x05, \x8e\x810\x9e\xe3@\x14\xe8i\x10\xc4\xd1\x8a\x08\x1c\xcf\x80M$z\xef\xff0\x85p\xb8\xb01f\r\x1b\xce\x01\xc3\x01\x1e\x10' \x82\n\x01\x00;", + "description": "The binary value above is a tiny arrow encoded as a gif image.", +} diff --git a/_test/data/construct-binary-py3.data b/_test/data/construct-binary-py3.data new file mode 100644 index 0000000..dcdb16f --- /dev/null +++ b/_test/data/construct-binary-py3.data @@ -0,0 +1,12 @@ +canonical: !!binary "\ + R0lGODlhDAAMAIQAAP//9/X17unp5WZmZgAAAOfn515eXvPz7Y6OjuDg4J+fn5\ + OTk6enp56enmlpaWNjY6Ojo4SEhP/++f/++f/++f/++f/++f/++f/++f/++f/+\ + +f/++f/++f/++f/++f/++SH+Dk1hZGUgd2l0aCBHSU1QACwAAAAADAAMAAAFLC\ + AgjoEwnuNAFOhpEMTRiggcz4BNJHrv/zCFcLiwMWYNG84BwwEeECcgggoBADs=" +generic: !!binary | + R0lGODlhDAAMAIQAAP//9/X17unp5WZmZgAAAOfn515eXvPz7Y6OjuDg4J+fn5 + OTk6enp56enmlpaWNjY6Ojo4SEhP/++f/++f/++f/++f/++f/++f/++f/++f/+ + +f/++f/++f/++f/++f/++SH+Dk1hZGUgd2l0aCBHSU1QACwAAAAADAAMAAAFLC + AgjoEwnuNAFOhpEMTRiggcz4BNJHrv/zCFcLiwMWYNG84BwwEeECcgggoBADs= +description: + The binary value above is a tiny arrow encoded as a gif image. diff --git a/_test/data/construct-bool.code b/_test/data/construct-bool.code new file mode 100644 index 0000000..3d02580 --- /dev/null +++ b/_test/data/construct-bool.code @@ -0,0 +1,7 @@ +{ + "canonical": True, + "answer": False, + "logical": True, + "option": True, + "but": { "y": "is a string", "n": "is a string" }, +} diff --git a/_test/data/construct-bool.data b/_test/data/construct-bool.data new file mode 100644 index 0000000..36d6519 --- /dev/null +++ b/_test/data/construct-bool.data @@ -0,0 +1,9 @@ +canonical: yes +answer: NO +logical: True +option: on + + +but: + y: is a string + n: is a string diff --git a/_test/data/construct-custom.code b/_test/data/construct-custom.code new file mode 100644 index 0000000..2d5f063 --- /dev/null +++ b/_test/data/construct-custom.code @@ -0,0 +1,10 @@ +[ + MyTestClass1(x=1), + MyTestClass1(x=1, y=2, z=3), + MyTestClass2(x=10), + MyTestClass2(x=10, y=20, z=30), + MyTestClass3(x=1), + MyTestClass3(x=1, y=2, z=3), + MyTestClass3(x=1, y=2, z=3), + YAMLObject1(my_parameter='foo', my_another_parameter=[1,2,3]) +] diff --git a/_test/data/construct-custom.data b/_test/data/construct-custom.data new file mode 100644 index 0000000..9db0f64 --- /dev/null +++ b/_test/data/construct-custom.data @@ -0,0 +1,26 @@ +--- +- !tag1 + x: 1 +- !tag1 + x: 1 + 'y': 2 + z: 3 +- !tag2 + 10 +- !tag2 + =: 10 + 'y': 20 + z: 30 +- !tag3 + x: 1 +- !tag3 + x: 1 + 'y': 2 + z: 3 +- !tag3 + =: 1 + 'y': 2 + z: 3 +- !foo + my-parameter: foo + my-another-parameter: [1,2,3] diff --git a/_test/data/construct-float.code b/_test/data/construct-float.code new file mode 100644 index 0000000..8493bf2 --- /dev/null +++ b/_test/data/construct-float.code @@ -0,0 +1,8 @@ +{ + "canonical": 685230.15, + "exponential": 685230.15, + "fixed": 685230.15, + "sexagesimal": 685230.15, + "negative infinity": -1e300000, + "not a number": 1e300000/1e300000, +} diff --git a/_test/data/construct-float.data b/_test/data/construct-float.data new file mode 100644 index 0000000..b662c62 --- /dev/null +++ b/_test/data/construct-float.data @@ -0,0 +1,6 @@ +canonical: 6.8523015e+5 +exponential: 685.230_15e+03 +fixed: 685_230.15 +sexagesimal: 190:20:30.15 +negative infinity: -.inf +not a number: .NaN diff --git a/_test/data/construct-int.code b/_test/data/construct-int.code new file mode 100644 index 0000000..1058f7b --- /dev/null +++ b/_test/data/construct-int.code @@ -0,0 +1,8 @@ +{ + "canonical": 685230, + "decimal": 685230, + "octal": 685230, + "hexadecimal": 685230, + "binary": 685230, + "sexagesimal": 685230, +} diff --git a/_test/data/construct-int.data b/_test/data/construct-int.data new file mode 100644 index 0000000..852c314 --- /dev/null +++ b/_test/data/construct-int.data @@ -0,0 +1,6 @@ +canonical: 685230 +decimal: +685_230 +octal: 02472256 +hexadecimal: 0x_0A_74_AE +binary: 0b1010_0111_0100_1010_1110 +sexagesimal: 190:20:30 diff --git a/_test/data/construct-map.code b/_test/data/construct-map.code new file mode 100644 index 0000000..736ba48 --- /dev/null +++ b/_test/data/construct-map.code @@ -0,0 +1,6 @@ +{ + "Block style": + { "Clark" : "Evans", "Brian" : "Ingerson", "Oren" : "Ben-Kiki" }, + "Flow style": + { "Clark" : "Evans", "Brian" : "Ingerson", "Oren" : "Ben-Kiki" }, +} diff --git a/_test/data/construct-map.data b/_test/data/construct-map.data new file mode 100644 index 0000000..022446d --- /dev/null +++ b/_test/data/construct-map.data @@ -0,0 +1,6 @@ +# Unordered set of key: value pairs. +Block style: !!map + Clark : Evans + Brian : Ingerson + Oren : Ben-Kiki +Flow style: !!map { Clark: Evans, Brian: Ingerson, Oren: Ben-Kiki } diff --git a/_test/data/construct-merge.code b/_test/data/construct-merge.code new file mode 100644 index 0000000..6cd419d --- /dev/null +++ b/_test/data/construct-merge.code @@ -0,0 +1,10 @@ +[ + { "x": 1, "y": 2 }, + { "x": 0, "y": 2 }, + { "r": 10 }, + { "r": 1 }, + { "x": 1, "y": 2, "r": 10, "label": "center/big" }, + { "x": 1, "y": 2, "r": 10, "label": "center/big" }, + { "x": 1, "y": 2, "r": 10, "label": "center/big" }, + { "x": 1, "y": 2, "r": 10, "label": "center/big" }, +] diff --git a/_test/data/construct-merge.data b/_test/data/construct-merge.data new file mode 100644 index 0000000..3fdb2e2 --- /dev/null +++ b/_test/data/construct-merge.data @@ -0,0 +1,27 @@ +--- +- &CENTER { x: 1, 'y': 2 } +- &LEFT { x: 0, 'y': 2 } +- &BIG { r: 10 } +- &SMALL { r: 1 } + +# All the following maps are equal: + +- # Explicit keys + x: 1 + 'y': 2 + r: 10 + label: center/big + +- # Merge one map + << : *CENTER + r: 10 + label: center/big + +- # Merge multiple maps + << : [ *CENTER, *BIG ] + label: center/big + +- # Override + << : [ *BIG, *LEFT, *SMALL ] + x: 1 + label: center/big diff --git a/_test/data/construct-null.code b/_test/data/construct-null.code new file mode 100644 index 0000000..a895eaa --- /dev/null +++ b/_test/data/construct-null.code @@ -0,0 +1,13 @@ +[ + None, + { "empty": None, "canonical": None, "english": None, None: "null key" }, + { + "sparse": [ + None, + "2nd entry", + None, + "4th entry", + None, + ], + }, +] diff --git a/_test/data/construct-null.data b/_test/data/construct-null.data new file mode 100644 index 0000000..9ad0344 --- /dev/null +++ b/_test/data/construct-null.data @@ -0,0 +1,18 @@ +# A document may be null. +--- +--- +# This mapping has four keys, +# one has a value. +empty: +canonical: ~ +english: null +~: null key +--- +# This sequence has five +# entries, two have values. +sparse: + - ~ + - 2nd entry + - + - 4th entry + - Null diff --git a/_test/data/construct-omap.code b/_test/data/construct-omap.code new file mode 100644 index 0000000..33a1574 --- /dev/null +++ b/_test/data/construct-omap.code @@ -0,0 +1,8 @@ +{ + "Bestiary": ordereddict([ + ("aardvark", "African pig-like ant eater. Ugly."), + ("anteater", "South-American ant eater. Two species."), + ("anaconda", "South-American constrictor snake. Scaly."), + ]), + "Numbers": ordereddict([ ("one", 4), ("one", 1), ("two", 2), ("three", 3) ]), +} diff --git a/_test/data/construct-omap.data b/_test/data/construct-omap.data new file mode 100644 index 0000000..4fa0f45 --- /dev/null +++ b/_test/data/construct-omap.data @@ -0,0 +1,8 @@ +# Explicitly typed ordered map (dictionary). +Bestiary: !!omap + - aardvark: African pig-like ant eater. Ugly. + - anteater: South-American ant eater. Two species. + - anaconda: South-American constrictor snake. Scaly. + # Etc. +# Flow style +Numbers: !!omap [ one: 1, two: 2, three : 3 ] diff --git a/_test/data/construct-pairs.code b/_test/data/construct-pairs.code new file mode 100644 index 0000000..64f86ee --- /dev/null +++ b/_test/data/construct-pairs.code @@ -0,0 +1,9 @@ +{ + "Block tasks": [ + ("meeting", "with team."), + ("meeting", "with boss."), + ("break", "lunch."), + ("meeting", "with client."), + ], + "Flow tasks": [ ("meeting", "with team"), ("meeting", "with boss") ], +} diff --git a/_test/data/construct-pairs.data b/_test/data/construct-pairs.data new file mode 100644 index 0000000..05f55b9 --- /dev/null +++ b/_test/data/construct-pairs.data @@ -0,0 +1,7 @@ +# Explicitly typed pairs. +Block tasks: !!pairs + - meeting: with team. + - meeting: with boss. + - break: lunch. + - meeting: with client. +Flow tasks: !!pairs [ meeting: with team, meeting: with boss ] diff --git a/_test/data/construct-python-bool.code b/_test/data/construct-python-bool.code new file mode 100644 index 0000000..170da01 --- /dev/null +++ b/_test/data/construct-python-bool.code @@ -0,0 +1 @@ +[ True, False ] diff --git a/_test/data/construct-python-bool.data b/_test/data/construct-python-bool.data new file mode 100644 index 0000000..0068869 --- /dev/null +++ b/_test/data/construct-python-bool.data @@ -0,0 +1 @@ +[ !!python/bool True, !!python/bool False ] diff --git a/_test/data/construct-python-bytes-py3.code b/_test/data/construct-python-bytes-py3.code new file mode 100644 index 0000000..b9051d8 --- /dev/null +++ b/_test/data/construct-python-bytes-py3.code @@ -0,0 +1 @@ +b'some binary data' diff --git a/_test/data/construct-python-bytes-py3.data b/_test/data/construct-python-bytes-py3.data new file mode 100644 index 0000000..9528725 --- /dev/null +++ b/_test/data/construct-python-bytes-py3.data @@ -0,0 +1 @@ +--- !!python/bytes 'c29tZSBiaW5hcnkgZGF0YQ==' diff --git a/_test/data/construct-python-complex.code b/_test/data/construct-python-complex.code new file mode 100644 index 0000000..e582dff --- /dev/null +++ b/_test/data/construct-python-complex.code @@ -0,0 +1 @@ +[0.5+0j, 0.5+0.5j, 0.5j, -0.5+0.5j, -0.5+0j, -0.5-0.5j, -0.5j, 0.5-0.5j] diff --git a/_test/data/construct-python-complex.data b/_test/data/construct-python-complex.data new file mode 100644 index 0000000..17ebad4 --- /dev/null +++ b/_test/data/construct-python-complex.data @@ -0,0 +1,8 @@ +- !!python/complex 0.5+0j +- !!python/complex 0.5+0.5j +- !!python/complex 0.5j +- !!python/complex -0.5+0.5j +- !!python/complex -0.5+0j +- !!python/complex -0.5-0.5j +- !!python/complex -0.5j +- !!python/complex 0.5-0.5j diff --git a/_test/data/construct-python-float.code b/_test/data/construct-python-float.code new file mode 100644 index 0000000..d5910a0 --- /dev/null +++ b/_test/data/construct-python-float.code @@ -0,0 +1 @@ +123.456 diff --git a/_test/data/construct-python-float.data b/_test/data/construct-python-float.data new file mode 100644 index 0000000..b460eb8 --- /dev/null +++ b/_test/data/construct-python-float.data @@ -0,0 +1 @@ +!!python/float 123.456 diff --git a/_test/data/construct-python-int.code b/_test/data/construct-python-int.code new file mode 100644 index 0000000..190a180 --- /dev/null +++ b/_test/data/construct-python-int.code @@ -0,0 +1 @@ +123 diff --git a/_test/data/construct-python-int.data b/_test/data/construct-python-int.data new file mode 100644 index 0000000..741d669 --- /dev/null +++ b/_test/data/construct-python-int.data @@ -0,0 +1 @@ +!!python/int 123 diff --git a/_test/data/construct-python-long-short-py3.code b/_test/data/construct-python-long-short-py3.code new file mode 100644 index 0000000..190a180 --- /dev/null +++ b/_test/data/construct-python-long-short-py3.code @@ -0,0 +1 @@ +123 diff --git a/_test/data/construct-python-long-short-py3.data b/_test/data/construct-python-long-short-py3.data new file mode 100644 index 0000000..4bd5dc2 --- /dev/null +++ b/_test/data/construct-python-long-short-py3.data @@ -0,0 +1 @@ +!!python/long 123 diff --git a/_test/data/construct-python-name-module.code b/_test/data/construct-python-name-module.code new file mode 100644 index 0000000..6f39148 --- /dev/null +++ b/_test/data/construct-python-name-module.code @@ -0,0 +1 @@ +[str, yaml.Loader, yaml.dump, abs, yaml.tokens] diff --git a/_test/data/construct-python-name-module.data b/_test/data/construct-python-name-module.data new file mode 100644 index 0000000..f0c9712 --- /dev/null +++ b/_test/data/construct-python-name-module.data @@ -0,0 +1,5 @@ +- !!python/name:str +- !!python/name:yaml.Loader +- !!python/name:yaml.dump +- !!python/name:abs +- !!python/module:yaml.tokens diff --git a/_test/data/construct-python-none.code b/_test/data/construct-python-none.code new file mode 100644 index 0000000..b0047fa --- /dev/null +++ b/_test/data/construct-python-none.code @@ -0,0 +1 @@ +None diff --git a/_test/data/construct-python-none.data b/_test/data/construct-python-none.data new file mode 100644 index 0000000..7907ec3 --- /dev/null +++ b/_test/data/construct-python-none.data @@ -0,0 +1 @@ +!!python/none diff --git a/_test/data/construct-python-object.code b/_test/data/construct-python-object.code new file mode 100644 index 0000000..7f1edf1 --- /dev/null +++ b/_test/data/construct-python-object.code @@ -0,0 +1,23 @@ +[ +AnObject(1, 'two', [3,3,3]), +AnInstance(1, 'two', [3,3,3]), + +AnObject(1, 'two', [3,3,3]), +AnInstance(1, 'two', [3,3,3]), + +AState(1, 'two', [3,3,3]), +ACustomState(1, 'two', [3,3,3]), + +InitArgs(1, 'two', [3,3,3]), +InitArgsWithState(1, 'two', [3,3,3]), + +NewArgs(1, 'two', [3,3,3]), +NewArgsWithState(1, 'two', [3,3,3]), + +Reduce(1, 'two', [3,3,3]), +ReduceWithState(1, 'two', [3,3,3]), + +MyInt(3), +MyList(3), +MyDict(3), +] diff --git a/_test/data/construct-python-object.data b/_test/data/construct-python-object.data new file mode 100644 index 0000000..bce8b2e --- /dev/null +++ b/_test/data/construct-python-object.data @@ -0,0 +1,21 @@ +- !!python/object:test_constructor.AnObject { foo: 1, bar: two, baz: [3,3,3] } +- !!python/object:test_constructor.AnInstance { foo: 1, bar: two, baz: [3,3,3] } + +- !!python/object/new:test_constructor.AnObject { args: [1, two], kwds: {baz: [3,3,3]} } +- !!python/object/apply:test_constructor.AnInstance { args: [1, two], kwds: {baz: [3,3,3]} } + +- !!python/object:test_constructor.AState { _foo: 1, _bar: two, _baz: [3,3,3] } +- !!python/object/new:test_constructor.ACustomState { state: !!python/tuple [1, two, [3,3,3]] } + +- !!python/object/new:test_constructor.InitArgs [1, two, [3,3,3]] +- !!python/object/new:test_constructor.InitArgsWithState { args: [1, two], state: [3,3,3] } + +- !!python/object/new:test_constructor.NewArgs [1, two, [3,3,3]] +- !!python/object/new:test_constructor.NewArgsWithState { args: [1, two], state: [3,3,3] } + +- !!python/object/apply:test_constructor.Reduce [1, two, [3,3,3]] +- !!python/object/apply:test_constructor.ReduceWithState { args: [1, two], state: [3,3,3] } + +- !!python/object/new:test_constructor.MyInt [3] +- !!python/object/new:test_constructor.MyList { listitems: [~, ~, ~] } +- !!python/object/new:test_constructor.MyDict { dictitems: {0, 1, 2} } diff --git a/_test/data/construct-python-str-ascii.code b/_test/data/construct-python-str-ascii.code new file mode 100644 index 0000000..d9d62f6 --- /dev/null +++ b/_test/data/construct-python-str-ascii.code @@ -0,0 +1 @@ +"ascii string" diff --git a/_test/data/construct-python-str-ascii.data b/_test/data/construct-python-str-ascii.data new file mode 100644 index 0000000..a83349e --- /dev/null +++ b/_test/data/construct-python-str-ascii.data @@ -0,0 +1 @@ +--- !!python/str "ascii string" diff --git a/_test/data/construct-python-str-utf8-py2.code b/_test/data/construct-python-str-utf8-py2.code new file mode 100644 index 0000000..6ca7d8f --- /dev/null +++ b/_test/data/construct-python-str-utf8-py2.code @@ -0,0 +1 @@ +'\u042d\u0442\u043e \u0443\u043d\u0438\u043a\u043e\u0434\u043d\u0430\u044f \u0441\u0442\u0440\u043e\u043a\u0430'.encode('utf-8') diff --git a/_test/data/construct-python-str-utf8-py3.code b/_test/data/construct-python-str-utf8-py3.code new file mode 100644 index 0000000..9f66032 --- /dev/null +++ b/_test/data/construct-python-str-utf8-py3.code @@ -0,0 +1 @@ +'\u042d\u0442\u043e \u0443\u043d\u0438\u043a\u043e\u0434\u043d\u0430\u044f \u0441\u0442\u0440\u043e\u043a\u0430' diff --git a/_test/data/construct-python-str-utf8-py3.data b/_test/data/construct-python-str-utf8-py3.data new file mode 100644 index 0000000..9ef2c72 --- /dev/null +++ b/_test/data/construct-python-str-utf8-py3.data @@ -0,0 +1 @@ +--- !!python/str "Ðто ÑƒÐ½Ð¸ÐºÐ¾Ð´Ð½Ð°Ñ Ñтрока" diff --git a/_test/data/construct-python-tuple-list-dict.code b/_test/data/construct-python-tuple-list-dict.code new file mode 100644 index 0000000..20ced98 --- /dev/null +++ b/_test/data/construct-python-tuple-list-dict.code @@ -0,0 +1,6 @@ +[ + [1, 2, 3, 4], + (1, 2, 3, 4), + {1: 2, 3: 4}, + {(0,0): 0, (0,1): 1, (1,0): 1, (1,1): 0}, +] diff --git a/_test/data/construct-python-tuple-list-dict.data b/_test/data/construct-python-tuple-list-dict.data new file mode 100644 index 0000000..c56159b --- /dev/null +++ b/_test/data/construct-python-tuple-list-dict.data @@ -0,0 +1,8 @@ +- !!python/list [1, 2, 3, 4] +- !!python/tuple [1, 2, 3, 4] +- !!python/dict {1: 2, 3: 4} +- !!python/dict + !!python/tuple [0,0]: 0 + !!python/tuple [0,1]: 1 + !!python/tuple [1,0]: 1 + !!python/tuple [1,1]: 0 diff --git a/_test/data/construct-python-unicode-ascii-py3.code b/_test/data/construct-python-unicode-ascii-py3.code new file mode 100644 index 0000000..d9d62f6 --- /dev/null +++ b/_test/data/construct-python-unicode-ascii-py3.code @@ -0,0 +1 @@ +"ascii string" diff --git a/_test/data/construct-python-unicode-ascii-py3.data b/_test/data/construct-python-unicode-ascii-py3.data new file mode 100644 index 0000000..3a0647b --- /dev/null +++ b/_test/data/construct-python-unicode-ascii-py3.data @@ -0,0 +1 @@ +--- !!python/unicode "ascii string" diff --git a/_test/data/construct-python-unicode-utf8-py2.code b/_test/data/construct-python-unicode-utf8-py2.code new file mode 100644 index 0000000..9f66032 --- /dev/null +++ b/_test/data/construct-python-unicode-utf8-py2.code @@ -0,0 +1 @@ +'\u042d\u0442\u043e \u0443\u043d\u0438\u043a\u043e\u0434\u043d\u0430\u044f \u0441\u0442\u0440\u043e\u043a\u0430' diff --git a/_test/data/construct-python-unicode-utf8-py3.code b/_test/data/construct-python-unicode-utf8-py3.code new file mode 100644 index 0000000..9f66032 --- /dev/null +++ b/_test/data/construct-python-unicode-utf8-py3.code @@ -0,0 +1 @@ +'\u042d\u0442\u043e \u0443\u043d\u0438\u043a\u043e\u0434\u043d\u0430\u044f \u0441\u0442\u0440\u043e\u043a\u0430' diff --git a/_test/data/construct-python-unicode-utf8-py3.data b/_test/data/construct-python-unicode-utf8-py3.data new file mode 100644 index 0000000..5a980ea --- /dev/null +++ b/_test/data/construct-python-unicode-utf8-py3.data @@ -0,0 +1 @@ +--- !!python/unicode "Ðто ÑƒÐ½Ð¸ÐºÐ¾Ð´Ð½Ð°Ñ Ñтрока" diff --git a/_test/data/construct-seq.code b/_test/data/construct-seq.code new file mode 100644 index 0000000..0c90c05 --- /dev/null +++ b/_test/data/construct-seq.code @@ -0,0 +1,4 @@ +{ + "Block style": ["Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune", "Pluto"], + "Flow style": ["Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune", "Pluto"], +} diff --git a/_test/data/construct-seq.data b/_test/data/construct-seq.data new file mode 100644 index 0000000..bb92fd1 --- /dev/null +++ b/_test/data/construct-seq.data @@ -0,0 +1,15 @@ +# Ordered sequence of nodes +Block style: !!seq +- Mercury # Rotates - no light/dark sides. +- Venus # Deadliest. Aptly named. +- Earth # Mostly dirt. +- Mars # Seems empty. +- Jupiter # The king. +- Saturn # Pretty. +- Uranus # Where the sun hardly shines. +- Neptune # Boring. No rings. +- Pluto # You call this a planet? +Flow style: !!seq [ Mercury, Venus, Earth, Mars, # Rocks + Jupiter, Saturn, Uranus, Neptune, # Gas + Pluto ] # Overrated + diff --git a/_test/data/construct-set.code b/_test/data/construct-set.code new file mode 100644 index 0000000..aa090e8 --- /dev/null +++ b/_test/data/construct-set.code @@ -0,0 +1,4 @@ +{ + "baseball players": set(["Mark McGwire", "Sammy Sosa", "Ken Griffey"]), + "baseball teams": set(["Boston Red Sox", "Detroit Tigers", "New York Yankees"]), +} diff --git a/_test/data/construct-set.data b/_test/data/construct-set.data new file mode 100644 index 0000000..e05dc88 --- /dev/null +++ b/_test/data/construct-set.data @@ -0,0 +1,7 @@ +# Explicitly typed set. +baseball players: !!set + ? Mark McGwire + ? Sammy Sosa + ? Ken Griffey +# Flow style +baseball teams: !!set { Boston Red Sox, Detroit Tigers, New York Yankees } diff --git a/_test/data/construct-str-ascii.code b/_test/data/construct-str-ascii.code new file mode 100644 index 0000000..d9d62f6 --- /dev/null +++ b/_test/data/construct-str-ascii.code @@ -0,0 +1 @@ +"ascii string" diff --git a/_test/data/construct-str-ascii.data b/_test/data/construct-str-ascii.data new file mode 100644 index 0000000..0d93013 --- /dev/null +++ b/_test/data/construct-str-ascii.data @@ -0,0 +1 @@ +--- !!str "ascii string" diff --git a/_test/data/construct-str-utf8-py2.code b/_test/data/construct-str-utf8-py2.code new file mode 100644 index 0000000..9f66032 --- /dev/null +++ b/_test/data/construct-str-utf8-py2.code @@ -0,0 +1 @@ +'\u042d\u0442\u043e \u0443\u043d\u0438\u043a\u043e\u0434\u043d\u0430\u044f \u0441\u0442\u0440\u043e\u043a\u0430' diff --git a/_test/data/construct-str-utf8-py3.code b/_test/data/construct-str-utf8-py3.code new file mode 100644 index 0000000..9f66032 --- /dev/null +++ b/_test/data/construct-str-utf8-py3.code @@ -0,0 +1 @@ +'\u042d\u0442\u043e \u0443\u043d\u0438\u043a\u043e\u0434\u043d\u0430\u044f \u0441\u0442\u0440\u043e\u043a\u0430' diff --git a/_test/data/construct-str-utf8-py3.data b/_test/data/construct-str-utf8-py3.data new file mode 100644 index 0000000..e355f18 --- /dev/null +++ b/_test/data/construct-str-utf8-py3.data @@ -0,0 +1 @@ +--- !!str "Ðто ÑƒÐ½Ð¸ÐºÐ¾Ð´Ð½Ð°Ñ Ñтрока" diff --git a/_test/data/construct-str.code b/_test/data/construct-str.code new file mode 100644 index 0000000..8d57214 --- /dev/null +++ b/_test/data/construct-str.code @@ -0,0 +1 @@ +{ "string": "abcd" } diff --git a/_test/data/construct-str.data b/_test/data/construct-str.data new file mode 100644 index 0000000..606ac6b --- /dev/null +++ b/_test/data/construct-str.data @@ -0,0 +1 @@ +string: abcd diff --git a/_test/data/construct-timestamp.code b/_test/data/construct-timestamp.code new file mode 100644 index 0000000..ffc3b2f --- /dev/null +++ b/_test/data/construct-timestamp.code @@ -0,0 +1,7 @@ +{ + "canonical": datetime.datetime(2001, 12, 15, 2, 59, 43, 100000), + "valid iso8601": datetime.datetime(2001, 12, 15, 2, 59, 43, 100000), + "space separated": datetime.datetime(2001, 12, 15, 2, 59, 43, 100000), + "no time zone (Z)": datetime.datetime(2001, 12, 15, 2, 59, 43, 100000), + "date (00:00:00Z)": datetime.date(2002, 12, 14), +} diff --git a/_test/data/construct-timestamp.data b/_test/data/construct-timestamp.data new file mode 100644 index 0000000..c5f3840 --- /dev/null +++ b/_test/data/construct-timestamp.data @@ -0,0 +1,5 @@ +canonical: 2001-12-15T02:59:43.1Z +valid iso8601: 2001-12-14t21:59:43.10-05:00 +space separated: 2001-12-14 21:59:43.10 -5 +no time zone (Z): 2001-12-15 2:59:43.10 +date (00:00:00Z): 2002-12-14 diff --git a/_test/data/construct-value.code b/_test/data/construct-value.code new file mode 100644 index 0000000..f1f015e --- /dev/null +++ b/_test/data/construct-value.code @@ -0,0 +1,9 @@ +[ + { "link with": [ "library1.dll", "library2.dll" ] }, + { + "link with": [ + { "=": "library1.dll", "version": 1.2 }, + { "=": "library2.dll", "version": 2.3 }, + ], + }, +] diff --git a/_test/data/construct-value.data b/_test/data/construct-value.data new file mode 100644 index 0000000..3eb7919 --- /dev/null +++ b/_test/data/construct-value.data @@ -0,0 +1,10 @@ +--- # Old schema +link with: + - library1.dll + - library2.dll +--- # New schema +link with: + - = : library1.dll + version: 1.2 + - = : library2.dll + version: 2.3 diff --git a/_test/data/document-separator-in-quoted-scalar.loader-error b/_test/data/document-separator-in-quoted-scalar.loader-error new file mode 100644 index 0000000..9eeb0d6 --- /dev/null +++ b/_test/data/document-separator-in-quoted-scalar.loader-error @@ -0,0 +1,11 @@ +--- +"this --- is correct" +--- +"this +...is also +correct" +--- +"a quoted scalar +cannot contain +--- +document separators" diff --git a/_test/data/documents.events b/_test/data/documents.events new file mode 100644 index 0000000..775a51a --- /dev/null +++ b/_test/data/documents.events @@ -0,0 +1,11 @@ +- !StreamStart +- !DocumentStart { explicit: false } +- !Scalar { implicit: [true,false], value: 'data' } +- !DocumentEnd +- !DocumentStart +- !Scalar { implicit: [true,false] } +- !DocumentEnd +- !DocumentStart { version: [1,1], tags: { '!': '!foo', '!yaml!': 'tag:yaml.org,2002:', '!ugly!': '!!!!!!!' } } +- !Scalar { implicit: [true,false] } +- !DocumentEnd +- !StreamEnd diff --git a/_test/data/duplicate-anchor-1.loader-warning b/_test/data/duplicate-anchor-1.loader-warning new file mode 100644 index 0000000..906cf29 --- /dev/null +++ b/_test/data/duplicate-anchor-1.loader-warning @@ -0,0 +1,3 @@ +- &foo bar +- &bar bar +- &foo bar diff --git a/_test/data/duplicate-anchor-2.loader-warning b/_test/data/duplicate-anchor-2.loader-warning new file mode 100644 index 0000000..62b4389 --- /dev/null +++ b/_test/data/duplicate-anchor-2.loader-warning @@ -0,0 +1 @@ +&foo [1, 2, 3, &foo 4] diff --git a/_test/data/duplicate-merge-key.former-loader-error.code b/_test/data/duplicate-merge-key.former-loader-error.code new file mode 100644 index 0000000..6a757f3 --- /dev/null +++ b/_test/data/duplicate-merge-key.former-loader-error.code @@ -0,0 +1 @@ +{ 'x': 1, 'y': 2, 'foo': 'bar', 'z': 3, 't': 4 } diff --git a/_test/data/duplicate-tag-directive.loader-error b/_test/data/duplicate-tag-directive.loader-error new file mode 100644 index 0000000..50c81a0 --- /dev/null +++ b/_test/data/duplicate-tag-directive.loader-error @@ -0,0 +1,3 @@ +%TAG !foo! bar +%TAG !foo! baz +--- foo diff --git a/_test/data/duplicate-yaml-directive.loader-error b/_test/data/duplicate-yaml-directive.loader-error new file mode 100644 index 0000000..9b72390 --- /dev/null +++ b/_test/data/duplicate-yaml-directive.loader-error @@ -0,0 +1,3 @@ +%YAML 1.1 +%YAML 1.1 +--- foo diff --git a/_test/data/emit-block-scalar-in-simple-key-context-bug.canonical b/_test/data/emit-block-scalar-in-simple-key-context-bug.canonical new file mode 100644 index 0000000..473bed5 --- /dev/null +++ b/_test/data/emit-block-scalar-in-simple-key-context-bug.canonical @@ -0,0 +1,6 @@ +%YAML 1.1 +--- !!map +{ + ? !!str "foo" + : !!str "bar" +} diff --git a/_test/data/emit-block-scalar-in-simple-key-context-bug.data b/_test/data/emit-block-scalar-in-simple-key-context-bug.data new file mode 100644 index 0000000..b6b42ba --- /dev/null +++ b/_test/data/emit-block-scalar-in-simple-key-context-bug.data @@ -0,0 +1,4 @@ +? |- + foo +: |- + bar diff --git a/_test/data/emitting-unacceptable-unicode-character-bug-py3.code b/_test/data/emitting-unacceptable-unicode-character-bug-py3.code new file mode 100644 index 0000000..2a5df00 --- /dev/null +++ b/_test/data/emitting-unacceptable-unicode-character-bug-py3.code @@ -0,0 +1 @@ +"\udd00" diff --git a/_test/data/emitting-unacceptable-unicode-character-bug-py3.data b/_test/data/emitting-unacceptable-unicode-character-bug-py3.data new file mode 100644 index 0000000..2a5df00 --- /dev/null +++ b/_test/data/emitting-unacceptable-unicode-character-bug-py3.data @@ -0,0 +1 @@ +"\udd00" diff --git a/_test/data/emitting-unacceptable-unicode-character-bug-py3.skip-ext b/_test/data/emitting-unacceptable-unicode-character-bug-py3.skip-ext new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/_test/data/emitting-unacceptable-unicode-character-bug-py3.skip-ext diff --git a/_test/data/empty-anchor.emitter-error b/_test/data/empty-anchor.emitter-error new file mode 100644 index 0000000..ce663b6 --- /dev/null +++ b/_test/data/empty-anchor.emitter-error @@ -0,0 +1,5 @@ +- !StreamStart +- !DocumentStart +- !Scalar { anchor: '', value: 'foo' } +- !DocumentEnd +- !StreamEnd diff --git a/_test/data/empty-document-bug.canonical b/_test/data/empty-document-bug.canonical new file mode 100644 index 0000000..28a6cf1 --- /dev/null +++ b/_test/data/empty-document-bug.canonical @@ -0,0 +1 @@ +# This YAML stream contains no YAML documents. diff --git a/_test/data/empty-document-bug.data b/_test/data/empty-document-bug.data new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/_test/data/empty-document-bug.data diff --git a/_test/data/empty-document-bug.empty b/_test/data/empty-document-bug.empty new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/_test/data/empty-document-bug.empty diff --git a/_test/data/empty-documents.single-loader-error b/_test/data/empty-documents.single-loader-error new file mode 100644 index 0000000..f8dba8d --- /dev/null +++ b/_test/data/empty-documents.single-loader-error @@ -0,0 +1,2 @@ +--- # first document +--- # second document diff --git a/_test/data/empty-python-module.loader-error b/_test/data/empty-python-module.loader-error new file mode 100644 index 0000000..83d3232 --- /dev/null +++ b/_test/data/empty-python-module.loader-error @@ -0,0 +1 @@ +--- !!python:module: diff --git a/_test/data/empty-python-name.loader-error b/_test/data/empty-python-name.loader-error new file mode 100644 index 0000000..6162957 --- /dev/null +++ b/_test/data/empty-python-name.loader-error @@ -0,0 +1 @@ +--- !!python/name: empty diff --git a/_test/data/empty-tag-handle.emitter-error b/_test/data/empty-tag-handle.emitter-error new file mode 100644 index 0000000..235c899 --- /dev/null +++ b/_test/data/empty-tag-handle.emitter-error @@ -0,0 +1,5 @@ +- !StreamStart +- !DocumentStart { tags: { '': 'bar' } } +- !Scalar { value: 'foo' } +- !DocumentEnd +- !StreamEnd diff --git a/_test/data/empty-tag-prefix.emitter-error b/_test/data/empty-tag-prefix.emitter-error new file mode 100644 index 0000000..c6c0e95 --- /dev/null +++ b/_test/data/empty-tag-prefix.emitter-error @@ -0,0 +1,5 @@ +- !StreamStart +- !DocumentStart { tags: { '!': '' } } +- !Scalar { value: 'foo' } +- !DocumentEnd +- !StreamEnd diff --git a/_test/data/empty-tag.emitter-error b/_test/data/empty-tag.emitter-error new file mode 100644 index 0000000..b7ca593 --- /dev/null +++ b/_test/data/empty-tag.emitter-error @@ -0,0 +1,5 @@ +- !StreamStart +- !DocumentStart +- !Scalar { tag: '', value: 'key', implicit: [false,false] } +- !DocumentEnd +- !StreamEnd diff --git a/_test/data/expected-document-end.emitter-error b/_test/data/expected-document-end.emitter-error new file mode 100644 index 0000000..0cbab89 --- /dev/null +++ b/_test/data/expected-document-end.emitter-error @@ -0,0 +1,6 @@ +- !StreamStart +- !DocumentStart +- !Scalar { value: 'data 1' } +- !Scalar { value: 'data 2' } +- !DocumentEnd +- !StreamEnd diff --git a/_test/data/expected-document-start.emitter-error b/_test/data/expected-document-start.emitter-error new file mode 100644 index 0000000..8ce575e --- /dev/null +++ b/_test/data/expected-document-start.emitter-error @@ -0,0 +1,4 @@ +- !StreamStart +- !MappingStart +- !MappingEnd +- !StreamEnd diff --git a/_test/data/expected-mapping.loader-error b/_test/data/expected-mapping.loader-error new file mode 100644 index 0000000..82aed98 --- /dev/null +++ b/_test/data/expected-mapping.loader-error @@ -0,0 +1 @@ +--- !!map [not, a, map] diff --git a/_test/data/expected-node-1.emitter-error b/_test/data/expected-node-1.emitter-error new file mode 100644 index 0000000..36ceca3 --- /dev/null +++ b/_test/data/expected-node-1.emitter-error @@ -0,0 +1,4 @@ +- !StreamStart +- !DocumentStart +- !DocumentEnd +- !StreamEnd diff --git a/_test/data/expected-node-2.emitter-error b/_test/data/expected-node-2.emitter-error new file mode 100644 index 0000000..891ee37 --- /dev/null +++ b/_test/data/expected-node-2.emitter-error @@ -0,0 +1,7 @@ +- !StreamStart +- !DocumentStart +- !MappingStart +- !Scalar { value: 'key' } +- !MappingEnd +- !DocumentEnd +- !StreamEnd diff --git a/_test/data/expected-nothing.emitter-error b/_test/data/expected-nothing.emitter-error new file mode 100644 index 0000000..62c54d3 --- /dev/null +++ b/_test/data/expected-nothing.emitter-error @@ -0,0 +1,4 @@ +- !StreamStart +- !StreamEnd +- !StreamStart +- !StreamEnd diff --git a/_test/data/expected-scalar.loader-error b/_test/data/expected-scalar.loader-error new file mode 100644 index 0000000..7b3171e --- /dev/null +++ b/_test/data/expected-scalar.loader-error @@ -0,0 +1 @@ +--- !!str [not a scalar] diff --git a/_test/data/expected-sequence.loader-error b/_test/data/expected-sequence.loader-error new file mode 100644 index 0000000..08074ea --- /dev/null +++ b/_test/data/expected-sequence.loader-error @@ -0,0 +1 @@ +--- !!seq {foo, bar, baz} diff --git a/_test/data/expected-stream-start.emitter-error b/_test/data/expected-stream-start.emitter-error new file mode 100644 index 0000000..480dc2e --- /dev/null +++ b/_test/data/expected-stream-start.emitter-error @@ -0,0 +1,2 @@ +- !DocumentStart +- !DocumentEnd diff --git a/_test/data/explicit-document.single-loader-error b/_test/data/explicit-document.single-loader-error new file mode 100644 index 0000000..46c6f8b --- /dev/null +++ b/_test/data/explicit-document.single-loader-error @@ -0,0 +1,4 @@ +--- +foo: bar +--- +foo: bar diff --git a/_test/data/fetch-complex-value-bug.loader-error b/_test/data/fetch-complex-value-bug.loader-error new file mode 100644 index 0000000..25fac24 --- /dev/null +++ b/_test/data/fetch-complex-value-bug.loader-error @@ -0,0 +1,2 @@ +? "foo" + : "bar" diff --git a/_test/data/float-representer-2.3-bug.code b/_test/data/float-representer-2.3-bug.code new file mode 100644 index 0000000..d8db834 --- /dev/null +++ b/_test/data/float-representer-2.3-bug.code @@ -0,0 +1,7 @@ +{ +# 0.0: 0, + 1.0: 1, + 1e300000: +10, + -1e300000: -10, + 1e300000/1e300000: 100, +} diff --git a/_test/data/float-representer-2.3-bug.data b/_test/data/float-representer-2.3-bug.data new file mode 100644 index 0000000..efd1716 --- /dev/null +++ b/_test/data/float-representer-2.3-bug.data @@ -0,0 +1,5 @@ +#0.0: # hash(0) == hash(nan) and 0 == nan in Python 2.3 +1.0: 1 ++.inf: 10 +-.inf: -10 +.nan: 100 diff --git a/_test/data/float.data b/_test/data/float.data new file mode 100644 index 0000000..524d5db --- /dev/null +++ b/_test/data/float.data @@ -0,0 +1,6 @@ +- 6.8523015e+5 +- 685.230_15e+03 +- 685_230.15 +- 190:20:30.15 +- -.inf +- .NaN diff --git a/_test/data/float.detect b/_test/data/float.detect new file mode 100644 index 0000000..1e12343 --- /dev/null +++ b/_test/data/float.detect @@ -0,0 +1 @@ +tag:yaml.org,2002:float diff --git a/_test/data/forbidden-entry.loader-error b/_test/data/forbidden-entry.loader-error new file mode 100644 index 0000000..f2e3079 --- /dev/null +++ b/_test/data/forbidden-entry.loader-error @@ -0,0 +1,2 @@ +test: - foo + - bar diff --git a/_test/data/forbidden-key.loader-error b/_test/data/forbidden-key.loader-error new file mode 100644 index 0000000..da9b471 --- /dev/null +++ b/_test/data/forbidden-key.loader-error @@ -0,0 +1,2 @@ +test: ? foo + : bar diff --git a/_test/data/forbidden-value.loader-error b/_test/data/forbidden-value.loader-error new file mode 100644 index 0000000..efd7ce5 --- /dev/null +++ b/_test/data/forbidden-value.loader-error @@ -0,0 +1 @@ +test: key: value diff --git a/_test/data/implicit-document.single-loader-error b/_test/data/implicit-document.single-loader-error new file mode 100644 index 0000000..f8c9a5c --- /dev/null +++ b/_test/data/implicit-document.single-loader-error @@ -0,0 +1,3 @@ +foo: bar +--- +foo: bar diff --git a/_test/data/int.data b/_test/data/int.data new file mode 100644 index 0000000..f71d814 --- /dev/null +++ b/_test/data/int.data @@ -0,0 +1,7 @@ +- 685230 +- +685_230 +- 02472256 +- 0o2472256 +- 0x_0A_74_AE +- 0b1010_0111_0100_1010_1110 +- 190:20:30 diff --git a/_test/data/int.detect b/_test/data/int.detect new file mode 100644 index 0000000..575c9eb --- /dev/null +++ b/_test/data/int.detect @@ -0,0 +1 @@ +tag:yaml.org,2002:int diff --git a/_test/data/invalid-anchor-1.loader-error b/_test/data/invalid-anchor-1.loader-error new file mode 100644 index 0000000..fcf7d0f --- /dev/null +++ b/_test/data/invalid-anchor-1.loader-error @@ -0,0 +1 @@ +--- &? foo # we allow only ascii and numeric characters in anchor names. diff --git a/_test/data/invalid-anchor-2.loader-error b/_test/data/invalid-anchor-2.loader-error new file mode 100644 index 0000000..bfc4ff0 --- /dev/null +++ b/_test/data/invalid-anchor-2.loader-error @@ -0,0 +1,8 @@ +--- +- [ + &correct foo, + *correct, + *correct] # still correct +- *correct: still correct +- &correct-or-not[foo, bar] + diff --git a/_test/data/invalid-anchor.emitter-error b/_test/data/invalid-anchor.emitter-error new file mode 100644 index 0000000..3d2a814 --- /dev/null +++ b/_test/data/invalid-anchor.emitter-error @@ -0,0 +1,5 @@ +- !StreamStart +- !DocumentStart +- !Scalar { anchor: '5*5=25', value: 'foo' } +- !DocumentEnd +- !StreamEnd diff --git a/_test/data/invalid-base64-data-2.loader-error b/_test/data/invalid-base64-data-2.loader-error new file mode 100644 index 0000000..2553a4f --- /dev/null +++ b/_test/data/invalid-base64-data-2.loader-error @@ -0,0 +1,2 @@ +--- !!binary + двоичные данные в base64 diff --git a/_test/data/invalid-base64-data.loader-error b/_test/data/invalid-base64-data.loader-error new file mode 100644 index 0000000..798abba --- /dev/null +++ b/_test/data/invalid-base64-data.loader-error @@ -0,0 +1,2 @@ +--- !!binary + binary data encoded in base64 should be here. diff --git a/_test/data/invalid-block-scalar-indicator.loader-error b/_test/data/invalid-block-scalar-indicator.loader-error new file mode 100644 index 0000000..16a6db1 --- /dev/null +++ b/_test/data/invalid-block-scalar-indicator.loader-error @@ -0,0 +1,2 @@ +--- > what is this? # a comment +data diff --git a/_test/data/invalid-character.loader-error b/_test/data/invalid-character.loader-error Binary files differnew file mode 100644 index 0000000..03687b0 --- /dev/null +++ b/_test/data/invalid-character.loader-error diff --git a/_test/data/invalid-character.stream-error b/_test/data/invalid-character.stream-error Binary files differnew file mode 100644 index 0000000..171face --- /dev/null +++ b/_test/data/invalid-character.stream-error diff --git a/_test/data/invalid-directive-line.loader-error b/_test/data/invalid-directive-line.loader-error new file mode 100644 index 0000000..0892eb6 --- /dev/null +++ b/_test/data/invalid-directive-line.loader-error @@ -0,0 +1,2 @@ +%YAML 1.1 ? # extra symbol +--- diff --git a/_test/data/invalid-directive-name-1.loader-error b/_test/data/invalid-directive-name-1.loader-error new file mode 100644 index 0000000..153fd88 --- /dev/null +++ b/_test/data/invalid-directive-name-1.loader-error @@ -0,0 +1,2 @@ +% # no name at all +--- diff --git a/_test/data/invalid-directive-name-2.loader-error b/_test/data/invalid-directive-name-2.loader-error new file mode 100644 index 0000000..3732a06 --- /dev/null +++ b/_test/data/invalid-directive-name-2.loader-error @@ -0,0 +1,2 @@ +%invalid-characters:in-directive name +--- diff --git a/_test/data/invalid-escape-character.loader-error b/_test/data/invalid-escape-character.loader-error new file mode 100644 index 0000000..a95ab76 --- /dev/null +++ b/_test/data/invalid-escape-character.loader-error @@ -0,0 +1 @@ +"some escape characters are \ncorrect, but this one \?\nis not\n" diff --git a/_test/data/invalid-escape-numbers.loader-error b/_test/data/invalid-escape-numbers.loader-error new file mode 100644 index 0000000..614ec9f --- /dev/null +++ b/_test/data/invalid-escape-numbers.loader-error @@ -0,0 +1 @@ +"hm.... \u123?" diff --git a/_test/data/invalid-indentation-indicator-1.loader-error b/_test/data/invalid-indentation-indicator-1.loader-error new file mode 100644 index 0000000..a3cd12f --- /dev/null +++ b/_test/data/invalid-indentation-indicator-1.loader-error @@ -0,0 +1,2 @@ +--- >0 # not valid +data diff --git a/_test/data/invalid-indentation-indicator-2.loader-error b/_test/data/invalid-indentation-indicator-2.loader-error new file mode 100644 index 0000000..eefb6ec --- /dev/null +++ b/_test/data/invalid-indentation-indicator-2.loader-error @@ -0,0 +1,2 @@ +--- >-0 +data diff --git a/_test/data/invalid-item-without-trailing-break.loader-error b/_test/data/invalid-item-without-trailing-break.loader-error new file mode 100644 index 0000000..fdcf6c6 --- /dev/null +++ b/_test/data/invalid-item-without-trailing-break.loader-error @@ -0,0 +1,2 @@ +- +-0
\ No newline at end of file diff --git a/_test/data/invalid-merge-1.loader-error b/_test/data/invalid-merge-1.loader-error new file mode 100644 index 0000000..fc3c284 --- /dev/null +++ b/_test/data/invalid-merge-1.loader-error @@ -0,0 +1,2 @@ +foo: bar +<<: baz diff --git a/_test/data/invalid-merge-2.loader-error b/_test/data/invalid-merge-2.loader-error new file mode 100644 index 0000000..8e88615 --- /dev/null +++ b/_test/data/invalid-merge-2.loader-error @@ -0,0 +1,2 @@ +foo: bar +<<: [x: 1, y: 2, z, t: 4] diff --git a/_test/data/invalid-omap-1.loader-error b/_test/data/invalid-omap-1.loader-error new file mode 100644 index 0000000..2863392 --- /dev/null +++ b/_test/data/invalid-omap-1.loader-error @@ -0,0 +1,3 @@ +--- !!omap +foo: bar +baz: bat diff --git a/_test/data/invalid-omap-2.loader-error b/_test/data/invalid-omap-2.loader-error new file mode 100644 index 0000000..c377dfb --- /dev/null +++ b/_test/data/invalid-omap-2.loader-error @@ -0,0 +1,3 @@ +--- !!omap +- foo: bar +- baz diff --git a/_test/data/invalid-omap-3.loader-error b/_test/data/invalid-omap-3.loader-error new file mode 100644 index 0000000..2a4f50d --- /dev/null +++ b/_test/data/invalid-omap-3.loader-error @@ -0,0 +1,4 @@ +--- !!omap +- foo: bar +- baz: bar + bar: bar diff --git a/_test/data/invalid-pairs-1.loader-error b/_test/data/invalid-pairs-1.loader-error new file mode 100644 index 0000000..42d19ae --- /dev/null +++ b/_test/data/invalid-pairs-1.loader-error @@ -0,0 +1,3 @@ +--- !!pairs +foo: bar +baz: bat diff --git a/_test/data/invalid-pairs-2.loader-error b/_test/data/invalid-pairs-2.loader-error new file mode 100644 index 0000000..31389ea --- /dev/null +++ b/_test/data/invalid-pairs-2.loader-error @@ -0,0 +1,3 @@ +--- !!pairs +- foo: bar +- baz diff --git a/_test/data/invalid-pairs-3.loader-error b/_test/data/invalid-pairs-3.loader-error new file mode 100644 index 0000000..f8d7704 --- /dev/null +++ b/_test/data/invalid-pairs-3.loader-error @@ -0,0 +1,4 @@ +--- !!pairs +- foo: bar +- baz: bar + bar: bar diff --git a/_test/data/invalid-python-bytes-2-py3.loader-error b/_test/data/invalid-python-bytes-2-py3.loader-error new file mode 100644 index 0000000..f43af59 --- /dev/null +++ b/_test/data/invalid-python-bytes-2-py3.loader-error @@ -0,0 +1,2 @@ +--- !!python/bytes + двоичные данные в base64 diff --git a/_test/data/invalid-python-bytes-py3.loader-error b/_test/data/invalid-python-bytes-py3.loader-error new file mode 100644 index 0000000..a19dfd0 --- /dev/null +++ b/_test/data/invalid-python-bytes-py3.loader-error @@ -0,0 +1,2 @@ +--- !!python/bytes + binary data encoded in base64 should be here. diff --git a/_test/data/invalid-python-module-kind.loader-error b/_test/data/invalid-python-module-kind.loader-error new file mode 100644 index 0000000..4f71cb5 --- /dev/null +++ b/_test/data/invalid-python-module-kind.loader-error @@ -0,0 +1 @@ +--- !!python/module:sys { must, be, scalar } diff --git a/_test/data/invalid-python-module-value.loader-error b/_test/data/invalid-python-module-value.loader-error new file mode 100644 index 0000000..f6797fc --- /dev/null +++ b/_test/data/invalid-python-module-value.loader-error @@ -0,0 +1 @@ +--- !!python/module:sys "non-empty value" diff --git a/_test/data/invalid-python-module.loader-error b/_test/data/invalid-python-module.loader-error new file mode 100644 index 0000000..4e24072 --- /dev/null +++ b/_test/data/invalid-python-module.loader-error @@ -0,0 +1 @@ +--- !!python/module:no.such.module diff --git a/_test/data/invalid-python-name-kind.loader-error b/_test/data/invalid-python-name-kind.loader-error new file mode 100644 index 0000000..6ff8eb6 --- /dev/null +++ b/_test/data/invalid-python-name-kind.loader-error @@ -0,0 +1 @@ +--- !!python/name:sys.modules {} diff --git a/_test/data/invalid-python-name-module-2.loader-error b/_test/data/invalid-python-name-module-2.loader-error new file mode 100644 index 0000000..debc313 --- /dev/null +++ b/_test/data/invalid-python-name-module-2.loader-error @@ -0,0 +1 @@ +--- !!python/name:xml.parsers diff --git a/_test/data/invalid-python-name-module.loader-error b/_test/data/invalid-python-name-module.loader-error new file mode 100644 index 0000000..1966f6a --- /dev/null +++ b/_test/data/invalid-python-name-module.loader-error @@ -0,0 +1 @@ +--- !!python/name:sys.modules.keys diff --git a/_test/data/invalid-python-name-object.loader-error b/_test/data/invalid-python-name-object.loader-error new file mode 100644 index 0000000..50f386f --- /dev/null +++ b/_test/data/invalid-python-name-object.loader-error @@ -0,0 +1 @@ +--- !!python/name:os.path.rm_rf diff --git a/_test/data/invalid-python-name-value.loader-error b/_test/data/invalid-python-name-value.loader-error new file mode 100644 index 0000000..7be1401 --- /dev/null +++ b/_test/data/invalid-python-name-value.loader-error @@ -0,0 +1 @@ +--- !!python/name:sys.modules 5 diff --git a/_test/data/invalid-simple-key.loader-error b/_test/data/invalid-simple-key.loader-error new file mode 100644 index 0000000..a58deec --- /dev/null +++ b/_test/data/invalid-simple-key.loader-error @@ -0,0 +1,3 @@ +key: value +invalid simple key +next key: next value diff --git a/_test/data/invalid-single-quote-bug.code b/_test/data/invalid-single-quote-bug.code new file mode 100644 index 0000000..5558945 --- /dev/null +++ b/_test/data/invalid-single-quote-bug.code @@ -0,0 +1 @@ +["foo 'bar'", "foo\n'bar'"] diff --git a/_test/data/invalid-single-quote-bug.data b/_test/data/invalid-single-quote-bug.data new file mode 100644 index 0000000..76ef7ae --- /dev/null +++ b/_test/data/invalid-single-quote-bug.data @@ -0,0 +1,2 @@ +- "foo 'bar'" +- "foo\n'bar'" diff --git a/_test/data/invalid-starting-character.loader-error b/_test/data/invalid-starting-character.loader-error new file mode 100644 index 0000000..bb81c60 --- /dev/null +++ b/_test/data/invalid-starting-character.loader-error @@ -0,0 +1 @@ +@@@@@@@@@@@@@@@@@@@ diff --git a/_test/data/invalid-tag-1.loader-error b/_test/data/invalid-tag-1.loader-error new file mode 100644 index 0000000..a68cd38 --- /dev/null +++ b/_test/data/invalid-tag-1.loader-error @@ -0,0 +1 @@ +- !<foo#bar> baz diff --git a/_test/data/invalid-tag-2.loader-error b/_test/data/invalid-tag-2.loader-error new file mode 100644 index 0000000..3a36700 --- /dev/null +++ b/_test/data/invalid-tag-2.loader-error @@ -0,0 +1 @@ +- !prefix!foo#bar baz diff --git a/_test/data/invalid-tag-directive-handle.loader-error b/_test/data/invalid-tag-directive-handle.loader-error new file mode 100644 index 0000000..42b5d7e --- /dev/null +++ b/_test/data/invalid-tag-directive-handle.loader-error @@ -0,0 +1,2 @@ +%TAG !!! !!! +--- diff --git a/_test/data/invalid-tag-directive-prefix.loader-error b/_test/data/invalid-tag-directive-prefix.loader-error new file mode 100644 index 0000000..0cb482c --- /dev/null +++ b/_test/data/invalid-tag-directive-prefix.loader-error @@ -0,0 +1,2 @@ +%TAG ! tag:zz.com/foo#bar # '#' is not allowed in URLs +--- diff --git a/_test/data/invalid-tag-handle-1.emitter-error b/_test/data/invalid-tag-handle-1.emitter-error new file mode 100644 index 0000000..d5df9a2 --- /dev/null +++ b/_test/data/invalid-tag-handle-1.emitter-error @@ -0,0 +1,5 @@ +- !StreamStart +- !DocumentStart { tags: { '!foo': 'bar' } } +- !Scalar { value: 'foo' } +- !DocumentEnd +- !StreamEnd diff --git a/_test/data/invalid-tag-handle-1.loader-error b/_test/data/invalid-tag-handle-1.loader-error new file mode 100644 index 0000000..ef0d143 --- /dev/null +++ b/_test/data/invalid-tag-handle-1.loader-error @@ -0,0 +1,2 @@ +%TAG foo bar +--- diff --git a/_test/data/invalid-tag-handle-2.emitter-error b/_test/data/invalid-tag-handle-2.emitter-error new file mode 100644 index 0000000..d1831d5 --- /dev/null +++ b/_test/data/invalid-tag-handle-2.emitter-error @@ -0,0 +1,5 @@ +- !StreamStart +- !DocumentStart { tags: { '!!!': 'bar' } } +- !Scalar { value: 'foo' } +- !DocumentEnd +- !StreamEnd diff --git a/_test/data/invalid-tag-handle-2.loader-error b/_test/data/invalid-tag-handle-2.loader-error new file mode 100644 index 0000000..06c7f0e --- /dev/null +++ b/_test/data/invalid-tag-handle-2.loader-error @@ -0,0 +1,2 @@ +%TAG !foo bar +--- diff --git a/_test/data/invalid-uri-escapes-1.loader-error b/_test/data/invalid-uri-escapes-1.loader-error new file mode 100644 index 0000000..a6ecb36 --- /dev/null +++ b/_test/data/invalid-uri-escapes-1.loader-error @@ -0,0 +1 @@ +--- !<tag:%x?y> foo diff --git a/_test/data/invalid-uri-escapes-2.loader-error b/_test/data/invalid-uri-escapes-2.loader-error new file mode 100644 index 0000000..b89e8f6 --- /dev/null +++ b/_test/data/invalid-uri-escapes-2.loader-error @@ -0,0 +1 @@ +--- !<%FF> foo diff --git a/_test/data/invalid-uri-escapes-3.loader-error b/_test/data/invalid-uri-escapes-3.loader-error new file mode 100644 index 0000000..f2e4cb8 --- /dev/null +++ b/_test/data/invalid-uri-escapes-3.loader-error @@ -0,0 +1 @@ +--- !<foo%d0%af%d0%af%d0bar> baz diff --git a/_test/data/invalid-uri.loader-error b/_test/data/invalid-uri.loader-error new file mode 100644 index 0000000..06307e0 --- /dev/null +++ b/_test/data/invalid-uri.loader-error @@ -0,0 +1 @@ +--- !foo! bar diff --git a/_test/data/invalid-utf8-byte.loader-error b/_test/data/invalid-utf8-byte.loader-error new file mode 100644 index 0000000..0a58c70 --- /dev/null +++ b/_test/data/invalid-utf8-byte.loader-error @@ -0,0 +1,66 @@ +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +Invalid byte ('\xFF'): ÿ <-- +############################################################### diff --git a/_test/data/invalid-utf8-byte.stream-error b/_test/data/invalid-utf8-byte.stream-error new file mode 100644 index 0000000..0a58c70 --- /dev/null +++ b/_test/data/invalid-utf8-byte.stream-error @@ -0,0 +1,66 @@ +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +############################################################### +Invalid byte ('\xFF'): ÿ <-- +############################################################### diff --git a/_test/data/invalid-yaml-directive-version-1.loader-error b/_test/data/invalid-yaml-directive-version-1.loader-error new file mode 100644 index 0000000..e9b4e3a --- /dev/null +++ b/_test/data/invalid-yaml-directive-version-1.loader-error @@ -0,0 +1,3 @@ +# No version at all. +%YAML +--- diff --git a/_test/data/invalid-yaml-directive-version-2.loader-error b/_test/data/invalid-yaml-directive-version-2.loader-error new file mode 100644 index 0000000..6aa7740 --- /dev/null +++ b/_test/data/invalid-yaml-directive-version-2.loader-error @@ -0,0 +1,2 @@ +%YAML 1e-5 +--- diff --git a/_test/data/invalid-yaml-directive-version-3.loader-error b/_test/data/invalid-yaml-directive-version-3.loader-error new file mode 100644 index 0000000..345e784 --- /dev/null +++ b/_test/data/invalid-yaml-directive-version-3.loader-error @@ -0,0 +1,2 @@ +%YAML 1. +--- diff --git a/_test/data/invalid-yaml-directive-version-4.loader-error b/_test/data/invalid-yaml-directive-version-4.loader-error new file mode 100644 index 0000000..b35ca82 --- /dev/null +++ b/_test/data/invalid-yaml-directive-version-4.loader-error @@ -0,0 +1,2 @@ +%YAML 1.132.435 +--- diff --git a/_test/data/invalid-yaml-directive-version-5.loader-error b/_test/data/invalid-yaml-directive-version-5.loader-error new file mode 100644 index 0000000..7c2b49f --- /dev/null +++ b/_test/data/invalid-yaml-directive-version-5.loader-error @@ -0,0 +1,2 @@ +%YAML A.0 +--- diff --git a/_test/data/invalid-yaml-directive-version-6.loader-error b/_test/data/invalid-yaml-directive-version-6.loader-error new file mode 100644 index 0000000..bae714f --- /dev/null +++ b/_test/data/invalid-yaml-directive-version-6.loader-error @@ -0,0 +1,2 @@ +%YAML 123.C +--- diff --git a/_test/data/invalid-yaml-version.loader-error b/_test/data/invalid-yaml-version.loader-error new file mode 100644 index 0000000..dd01948 --- /dev/null +++ b/_test/data/invalid-yaml-version.loader-error @@ -0,0 +1,2 @@ +%YAML 2.0 +--- foo diff --git a/_test/data/latin.unicode b/_test/data/latin.unicode new file mode 100644 index 0000000..4fb799c --- /dev/null +++ b/_test/data/latin.unicode @@ -0,0 +1,384 @@ +ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzªµºÀÃÂÃÄÅÆÇÈÉÊ +ËÌÃÃŽÃÃÑÒÓÔÕÖØÙÚÛÜÃÞßà áâãäåæçèéêëìÃîïðñòóôõöøùúûüýþÿĀÄĂ㥹ĆćĈĉĊċČÄÄŽ +ÄÄđĒēĔĕĖėĘęĚěĜÄÄžÄŸÄ Ä¡Ä¢Ä£Ä¤Ä¥Ä¦Ä§Ä¨Ä©ÄªÄ«Ä¬ÄĮįİıIJijĴĵĶķĸĹĺĻļĽľĿŀÅłŃńŅņŇňʼnŊŋŌÅÅŽÅÅ +őŒœŔŕŖŗŘřŚśŜÅŞşŠšŢţŤťŦŧŨũŪūŬÅŮůŰűŲųŴŵŶŷŸŹźŻżŽžſƀÆƂƃƄƅƆƇƈƉƊƋƌÆÆŽÆÆÆ‘Æ’ +ƓƔƕƖƗƘƙƚƛƜÆÆžÆŸÆ Æ¡Æ¢Æ£Æ¤Æ¥Æ¦Æ§Æ¨Æ©ÆªÆ«Æ¬ÆƮƯưƱƲƳƴƵƶƷƸƹƺƼƽƾƿDŽdžLJljNJnjÇÇŽÇÇǑǒǓǔǕǖǗǘǙǚǛǜ +ÇÇžÇŸÇ Ç¡Ç¢Ç£Ç¤Ç¥Ç¦Ç§Ç¨Ç©ÇªÇ«Ç¬ÇǮǯǰDZdzǴǵǶǷǸǹǺǻǼǽǾǿȀÈȂȃȄȅȆȇȈȉȊȋȌÈÈŽÈÈȑȒȓȔȕȖȗȘșȚțȜÈȞȟ +È È¡È¢È£È¤È¥È¦È§È¨È©ÈªÈ«È¬ÈȮȯȰȱȲȳȴȵȶȷȸȹȺȻȼȽȾȿɀÉÉɑɒɓɔɕɖɗɘəɚɛɜÉÉžÉŸÉ É¡É¢É£É¤É¥É¦É§É¨É©ÉªÉ«É¬Éɮɯ +ɰɱɲɳɴɵɶɷɸɹɺɻɼɽɾɿʀÊʂʃʄʅʆʇʈʉʊʋʌÊÊŽÊÊʑʒʓʔʕʖʗʘʙʚʛʜÊÊžÊŸÊ Ê¡Ê¢Ê£Ê¤Ê¥Ê¦Ê§Ê¨Ê©ÊªÊ«Ê¬ÊʮʯΆΈ +ΉΊΌΎÎÎΑΒΓΔΕΖΗΘΙΚΛΜÎΞΟΠΡΣΤΥΦΧΨΩΪΫάÎήίΰαβγδεζηθικλμνξοπÏÏ‚ÏƒÏ„Ï…Ï†Ï‡ÏˆÏ‰ÏŠÏ‹ÏŒÏ +ÏŽÏϑϒϓϔϕϖϗϘϙϚϛϜÏÏžÏŸÏ Ï¡Ï¢Ï£Ï¤Ï¥Ï¦Ï§Ï¨Ï©ÏªÏ«Ï¬ÏϮϯϰϱϲϳϴϵϷϸϹϺϻϼϽϾϿЀÐЂЃЄЅІЇЈЉЊЋЌÐÐŽÐÐБ +ВГДЕЖЗИЙКЛМÐОПРСТУФХЦЧШЩЪЫЬÐЮЯабвгдежзийклмнопрÑтуфхцчшщъыьÑÑŽÑÑÑ‘Ñ’Ñ“ +єѕіїјљњћќÑÑžÑŸÑ Ñ¡Ñ¢Ñ£Ñ¤Ñ¥Ñ¦Ñ§Ñ¨Ñ©ÑªÑ«Ñ¬ÑѮѯѰѱѲѳѴѵѶѷѸѹѺѻѼѽѾѿҀÒÒŠÒ‹ÒŒÒÒŽÒÒÒ‘Ò’Ò“Ò”Ò•Ò–Ò—Ò˜Ò™ÒšÒ›ÒœÒ +ÒžÒŸÒ Ò¡Ò¢Ò£Ò¤Ò¥Ò¦Ò§Ò¨Ò©ÒªÒ«Ò¬ÒÒ®Ò¯Ò°Ò±Ò²Ò³Ò´ÒµÒ¶Ò·Ò¸Ò¹ÒºÒ»Ò¼Ò½Ò¾Ò¿Ó€ÓÓ‚ÓƒÓ„Ó…Ó†Ó‡ÓˆÓ‰ÓŠÓ‹ÓŒÓÓŽÓÓ‘Ó’Ó“Ó”Ó•Ó–Ó—Ó˜Ó™ÓšÓ›ÓœÓÓžÓŸÓ +Ó¡Ó¢Ó£Ó¤Ó¥Ó¦Ó§Ó¨Ó©ÓªÓ«Ó¬ÓÓ®Ó¯Ó°Ó±Ó²Ó³Ó´ÓµÓ¶Ó·Ó¸Ó¹Ô€ÔÔ‚ÔƒÔ„Ô…Ô†Ô‡ÔˆÔ‰ÔŠÔ‹ÔŒÔÔŽÔÔ±Ô²Ô³Ô´ÔµÔ¶Ô·Ô¸Ô¹ÔºÔ»Ô¼Ô½Ô¾Ô¿Õ€ÕÕ‚ÕƒÕ„Õ…Õ†Õ‡ÕˆÕ‰ +ÕŠÕ‹ÕŒÕÕŽÕÕÕ‘Õ’Õ“Õ”Õ•Õ–Õ¡Õ¢Õ£Õ¤Õ¥Õ¦Õ§Õ¨Õ©ÕªÕ«Õ¬ÕÕ®Õ¯Õ°Õ±Õ²Õ³Õ´ÕµÕ¶Õ·Õ¸Õ¹ÕºÕ»Õ¼Õ½Õ¾Õ¿Ö€ÖւփքօֆևႠႡႢႣႤႥႦႧႨႩႪႫႬႠ+ႮႯႰႱႲႳႴႵႶႷႸႹႺႻႼႽႾႿჀáƒáƒ‚ჃჄჅᴀá´á´‚ᴃᴄᴅᴆᴇᴈᴉᴊᴋᴌá´á´Žá´á´á´‘ᴒᴓᴔᴕᴖᴗᴘᴙᴚᴛᴜá´á´žá´Ÿá´ ᴡᴢᴣᴤᴥᴦᴧᴨᴩ +ᴪᴫᵢᵣᵤᵥᵦᵧᵨᵩᵪᵫᵬáµáµ®áµ¯áµ°áµ±áµ²áµ³áµ´áµµáµ¶áµ·áµ¹áµºáµ»áµ¼áµ½áµ¾áµ¿á¶€á¶á¶‚ᶃᶄᶅᶆᶇᶈᶉᶊᶋᶌá¶á¶Žá¶á¶á¶‘ᶒᶓᶔᶕᶖᶗᶘᶙᶚḀá¸á¸‚ḃḄḅḆḇ +ḈḉḊḋḌá¸á¸Žá¸á¸á¸‘ḒḓḔḕḖḗḘḙḚḛḜá¸á¸žá¸Ÿá¸ ḡḢḣḤḥḦḧḨḩḪḫḬá¸á¸®á¸¯á¸°á¸±á¸²á¸³á¸´á¸µá¸¶á¸·á¸¸á¸¹á¸ºá¸»á¸¼á¸½á¸¾á¸¿á¹€á¹á¹‚ṃṄṅṆṇṈṉ +ṊṋṌá¹á¹Žá¹á¹á¹‘ṒṓṔṕṖṗṘṙṚṛṜá¹á¹žá¹Ÿá¹ ṡṢṣṤṥṦṧṨṩṪṫṬá¹á¹®á¹¯á¹°á¹±á¹²á¹³á¹´á¹µá¹¶á¹·á¹¸á¹¹á¹ºá¹»á¹¼á¹½á¹¾á¹¿áº€áºáº‚ẃẄẅẆẇẈẉẊẋ +ẌáºáºŽáºáºáº‘ẒẓẔẕẖẗẘẙẚẛẠạẢảẤấẦầẨẩẪẫẬáºáº®áº¯áº°áº±áº²áº³áº´áºµáº¶áº·áº¸áº¹áººáº»áº¼áº½áº¾áº¿á»€á»á»‚ểỄễỆệỈỉỊịỌá»á»Žá»á»á»‘ +ỒồỔổỖỗỘộỚớỜá»á»žá»Ÿá» ỡỢợỤụỦủỨứỪừỬá»á»®á»¯á»°á»±á»²á»³á»´á»µá»¶á»·á»¸á»¹á¼€á¼á¼‚ἃἄἅἆἇἈἉἊἋἌá¼á¼Žá¼á¼á¼‘ἒἓἔἕἘἙἚἛ +Ἔá¼á¼ ἡἢἣἤἥἦἧἨἩἪἫἬá¼á¼®á¼¯á¼°á¼±á¼²á¼³á¼´á¼µá¼¶á¼·á¼¸á¼¹á¼ºá¼»á¼¼á¼½á¼¾á¼¿á½€á½á½‚ὃὄὅὈὉὊὋὌá½á½á½‘ὒὓὔὕὖὗὙὛá½á½Ÿá½ ὡὢὣὤὥὦὧ +ὨὩὪὫὬá½á½®á½¯á½°á½±á½²á½³á½´á½µá½¶á½·á½¸á½¹á½ºá½»á½¼á½½á¾€á¾á¾‚ᾃᾄᾅᾆᾇá¾á¾‘ᾒᾓᾔᾕᾖᾗᾠᾡᾢᾣᾤᾥᾦᾧᾰᾱᾲᾳᾴᾶᾷᾸᾹᾺΆιῂῃῄῆῇῈΈῊ +á¿‹á¿á¿‘ῒΐῖῗῘῙῚΊῠῡῢΰῤῥῦῧῨῩῪΎῬῲῳῴῶῷῸΌῺΏâ±â¿â„‚ℇℊℋℌâ„â„Žâ„â„ℑℒℓℕℙℚℛℜâ„ℤΩℨKÅℬâ„ℯℰℱℳℴℹ +ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzªµºÀÃÂÃÄÅÆÇÈÉÊ +ËÌÃÃŽÃÃÑÒÓÔÕÖØÙÚÛÜÃÞßà áâãäåæçèéêëìÃîïðñòóôõöøùúûüýþÿĀÄĂ㥹ĆćĈĉĊċČÄÄŽ +ÄÄđĒēĔĕĖėĘęĚěĜÄÄžÄŸÄ Ä¡Ä¢Ä£Ä¤Ä¥Ä¦Ä§Ä¨Ä©ÄªÄ«Ä¬ÄĮįİıIJijĴĵĶķĸĹĺĻļĽľĿŀÅłŃńŅņŇňʼnŊŋŌÅÅŽÅÅ +őŒœŔŕŖŗŘřŚśŜÅŞşŠšŢţŤťŦŧŨũŪūŬÅŮůŰűŲųŴŵŶŷŸŹźŻżŽžſƀÆƂƃƄƅƆƇƈƉƊƋƌÆÆŽÆÆÆ‘Æ’ +ƓƔƕƖƗƘƙƚƛƜÆÆžÆŸÆ Æ¡Æ¢Æ£Æ¤Æ¥Æ¦Æ§Æ¨Æ©ÆªÆ«Æ¬ÆƮƯưƱƲƳƴƵƶƷƸƹƺƼƽƾƿDŽdžLJljNJnjÇÇŽÇÇǑǒǓǔǕǖǗǘǙǚǛǜ +ÇÇžÇŸÇ Ç¡Ç¢Ç£Ç¤Ç¥Ç¦Ç§Ç¨Ç©ÇªÇ«Ç¬ÇǮǯǰDZdzǴǵǶǷǸǹǺǻǼǽǾǿȀÈȂȃȄȅȆȇȈȉȊȋȌÈÈŽÈÈȑȒȓȔȕȖȗȘșȚțȜÈȞȟ +È È¡È¢È£È¤È¥È¦È§È¨È©ÈªÈ«È¬ÈȮȯȰȱȲȳȴȵȶȷȸȹȺȻȼȽȾȿɀÉÉɑɒɓɔɕɖɗɘəɚɛɜÉÉžÉŸÉ É¡É¢É£É¤É¥É¦É§É¨É©ÉªÉ«É¬Éɮɯ +ɰɱɲɳɴɵɶɷɸɹɺɻɼɽɾɿʀÊʂʃʄʅʆʇʈʉʊʋʌÊÊŽÊÊʑʒʓʔʕʖʗʘʙʚʛʜÊÊžÊŸÊ Ê¡Ê¢Ê£Ê¤Ê¥Ê¦Ê§Ê¨Ê©ÊªÊ«Ê¬ÊʮʯΆΈ +ΉΊΌΎÎÎΑΒΓΔΕΖΗΘΙΚΛΜÎΞΟΠΡΣΤΥΦΧΨΩΪΫάÎήίΰαβγδεζηθικλμνξοπÏÏ‚ÏƒÏ„Ï…Ï†Ï‡ÏˆÏ‰ÏŠÏ‹ÏŒÏ +ÏŽÏϑϒϓϔϕϖϗϘϙϚϛϜÏÏžÏŸÏ Ï¡Ï¢Ï£Ï¤Ï¥Ï¦Ï§Ï¨Ï©ÏªÏ«Ï¬ÏϮϯϰϱϲϳϴϵϷϸϹϺϻϼϽϾϿЀÐЂЃЄЅІЇЈЉЊЋЌÐÐŽÐÐБ +ВГДЕЖЗИЙКЛМÐОПРСТУФХЦЧШЩЪЫЬÐЮЯабвгдежзийклмнопрÑтуфхцчшщъыьÑÑŽÑÑÑ‘Ñ’Ñ“ +єѕіїјљњћќÑÑžÑŸÑ Ñ¡Ñ¢Ñ£Ñ¤Ñ¥Ñ¦Ñ§Ñ¨Ñ©ÑªÑ«Ñ¬ÑѮѯѰѱѲѳѴѵѶѷѸѹѺѻѼѽѾѿҀÒÒŠÒ‹ÒŒÒÒŽÒÒÒ‘Ò’Ò“Ò”Ò•Ò–Ò—Ò˜Ò™ÒšÒ›ÒœÒ +ÒžÒŸÒ Ò¡Ò¢Ò£Ò¤Ò¥Ò¦Ò§Ò¨Ò©ÒªÒ«Ò¬ÒÒ®Ò¯Ò°Ò±Ò²Ò³Ò´ÒµÒ¶Ò·Ò¸Ò¹ÒºÒ»Ò¼Ò½Ò¾Ò¿Ó€ÓÓ‚ÓƒÓ„Ó…Ó†Ó‡ÓˆÓ‰ÓŠÓ‹ÓŒÓÓŽÓÓ‘Ó’Ó“Ó”Ó•Ó–Ó—Ó˜Ó™ÓšÓ›ÓœÓÓžÓŸÓ +Ó¡Ó¢Ó£Ó¤Ó¥Ó¦Ó§Ó¨Ó©ÓªÓ«Ó¬ÓÓ®Ó¯Ó°Ó±Ó²Ó³Ó´ÓµÓ¶Ó·Ó¸Ó¹Ô€ÔÔ‚ÔƒÔ„Ô…Ô†Ô‡ÔˆÔ‰ÔŠÔ‹ÔŒÔÔŽÔÔ±Ô²Ô³Ô´ÔµÔ¶Ô·Ô¸Ô¹ÔºÔ»Ô¼Ô½Ô¾Ô¿Õ€ÕÕ‚ÕƒÕ„Õ…Õ†Õ‡ÕˆÕ‰ +ÕŠÕ‹ÕŒÕÕŽÕÕÕ‘Õ’Õ“Õ”Õ•Õ–Õ¡Õ¢Õ£Õ¤Õ¥Õ¦Õ§Õ¨Õ©ÕªÕ«Õ¬ÕÕ®Õ¯Õ°Õ±Õ²Õ³Õ´ÕµÕ¶Õ·Õ¸Õ¹ÕºÕ»Õ¼Õ½Õ¾Õ¿Ö€ÖւփքօֆևႠႡႢႣႤႥႦႧႨႩႪႫႬႠ+ႮႯႰႱႲႳႴႵႶႷႸႹႺႻႼႽႾႿჀáƒáƒ‚ჃჄჅᴀá´á´‚ᴃᴄᴅᴆᴇᴈᴉᴊᴋᴌá´á´Žá´á´á´‘ᴒᴓᴔᴕᴖᴗᴘᴙᴚᴛᴜá´á´žá´Ÿá´ ᴡᴢᴣᴤᴥᴦᴧᴨᴩ +ᴪᴫᵢᵣᵤᵥᵦᵧᵨᵩᵪᵫᵬáµáµ®áµ¯áµ°áµ±áµ²áµ³áµ´áµµáµ¶áµ·áµ¹áµºáµ»áµ¼áµ½áµ¾áµ¿á¶€á¶á¶‚ᶃᶄᶅᶆᶇᶈᶉᶊᶋᶌá¶á¶Žá¶á¶á¶‘ᶒᶓᶔᶕᶖᶗᶘᶙᶚḀá¸á¸‚ḃḄḅḆḇ +ḈḉḊḋḌá¸á¸Žá¸á¸á¸‘ḒḓḔḕḖḗḘḙḚḛḜá¸á¸žá¸Ÿá¸ ḡḢḣḤḥḦḧḨḩḪḫḬá¸á¸®á¸¯á¸°á¸±á¸²á¸³á¸´á¸µá¸¶á¸·á¸¸á¸¹á¸ºá¸»á¸¼á¸½á¸¾á¸¿á¹€á¹á¹‚ṃṄṅṆṇṈṉ +ṊṋṌá¹á¹Žá¹á¹á¹‘ṒṓṔṕṖṗṘṙṚṛṜá¹á¹žá¹Ÿá¹ ṡṢṣṤṥṦṧṨṩṪṫṬá¹á¹®á¹¯á¹°á¹±á¹²á¹³á¹´á¹µá¹¶á¹·á¹¸á¹¹á¹ºá¹»á¹¼á¹½á¹¾á¹¿áº€áºáº‚ẃẄẅẆẇẈẉẊẋ +ẌáºáºŽáºáºáº‘ẒẓẔẕẖẗẘẙẚẛẠạẢảẤấẦầẨẩẪẫẬáºáº®áº¯áº°áº±áº²áº³áº´áºµáº¶áº·áº¸áº¹áººáº»áº¼áº½áº¾áº¿á»€á»á»‚ểỄễỆệỈỉỊịỌá»á»Žá»á»á»‘ +ỒồỔổỖỗỘộỚớỜá»á»žá»Ÿá» ỡỢợỤụỦủỨứỪừỬá»á»®á»¯á»°á»±á»²á»³á»´á»µá»¶á»·á»¸á»¹á¼€á¼á¼‚ἃἄἅἆἇἈἉἊἋἌá¼á¼Žá¼á¼á¼‘ἒἓἔἕἘἙἚἛ +Ἔá¼á¼ ἡἢἣἤἥἦἧἨἩἪἫἬá¼á¼®á¼¯á¼°á¼±á¼²á¼³á¼´á¼µá¼¶á¼·á¼¸á¼¹á¼ºá¼»á¼¼á¼½á¼¾á¼¿á½€á½á½‚ὃὄὅὈὉὊὋὌá½á½á½‘ὒὓὔὕὖὗὙὛá½á½Ÿá½ ὡὢὣὤὥὦὧ +ὨὩὪὫὬá½á½®á½¯á½°á½±á½²á½³á½´á½µá½¶á½·á½¸á½¹á½ºá½»á½¼á½½á¾€á¾á¾‚ᾃᾄᾅᾆᾇá¾á¾‘ᾒᾓᾔᾕᾖᾗᾠᾡᾢᾣᾤᾥᾦᾧᾰᾱᾲᾳᾴᾶᾷᾸᾹᾺΆιῂῃῄῆῇῈΈῊ +á¿‹á¿á¿‘ῒΐῖῗῘῙῚΊῠῡῢΰῤῥῦῧῨῩῪΎῬῲῳῴῶῷῸΌῺΏâ±â¿â„‚ℇℊℋℌâ„â„Žâ„â„ℑℒℓℕℙℚℛℜâ„ℤΩℨKÅℬâ„ℯℰℱℳℴℹ +ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzªµºÀÃÂÃÄÅÆÇÈÉÊ +ËÌÃÃŽÃÃÑÒÓÔÕÖØÙÚÛÜÃÞßà áâãäåæçèéêëìÃîïðñòóôõöøùúûüýþÿĀÄĂ㥹ĆćĈĉĊċČÄÄŽ +ÄÄđĒēĔĕĖėĘęĚěĜÄÄžÄŸÄ Ä¡Ä¢Ä£Ä¤Ä¥Ä¦Ä§Ä¨Ä©ÄªÄ«Ä¬ÄĮįİıIJijĴĵĶķĸĹĺĻļĽľĿŀÅłŃńŅņŇňʼnŊŋŌÅÅŽÅÅ +őŒœŔŕŖŗŘřŚśŜÅŞşŠšŢţŤťŦŧŨũŪūŬÅŮůŰűŲųŴŵŶŷŸŹźŻżŽžſƀÆƂƃƄƅƆƇƈƉƊƋƌÆÆŽÆÆÆ‘Æ’ +ƓƔƕƖƗƘƙƚƛƜÆÆžÆŸÆ Æ¡Æ¢Æ£Æ¤Æ¥Æ¦Æ§Æ¨Æ©ÆªÆ«Æ¬ÆƮƯưƱƲƳƴƵƶƷƸƹƺƼƽƾƿDŽdžLJljNJnjÇÇŽÇÇǑǒǓǔǕǖǗǘǙǚǛǜ +ÇÇžÇŸÇ Ç¡Ç¢Ç£Ç¤Ç¥Ç¦Ç§Ç¨Ç©ÇªÇ«Ç¬ÇǮǯǰDZdzǴǵǶǷǸǹǺǻǼǽǾǿȀÈȂȃȄȅȆȇȈȉȊȋȌÈÈŽÈÈȑȒȓȔȕȖȗȘșȚțȜÈȞȟ +È È¡È¢È£È¤È¥È¦È§È¨È©ÈªÈ«È¬ÈȮȯȰȱȲȳȴȵȶȷȸȹȺȻȼȽȾȿɀÉÉɑɒɓɔɕɖɗɘəɚɛɜÉÉžÉŸÉ É¡É¢É£É¤É¥É¦É§É¨É©ÉªÉ«É¬Éɮɯ +ɰɱɲɳɴɵɶɷɸɹɺɻɼɽɾɿʀÊʂʃʄʅʆʇʈʉʊʋʌÊÊŽÊÊʑʒʓʔʕʖʗʘʙʚʛʜÊÊžÊŸÊ Ê¡Ê¢Ê£Ê¤Ê¥Ê¦Ê§Ê¨Ê©ÊªÊ«Ê¬ÊʮʯΆΈ +ΉΊΌΎÎÎΑΒΓΔΕΖΗΘΙΚΛΜÎΞΟΠΡΣΤΥΦΧΨΩΪΫάÎήίΰαβγδεζηθικλμνξοπÏÏ‚ÏƒÏ„Ï…Ï†Ï‡ÏˆÏ‰ÏŠÏ‹ÏŒÏ +ÏŽÏϑϒϓϔϕϖϗϘϙϚϛϜÏÏžÏŸÏ Ï¡Ï¢Ï£Ï¤Ï¥Ï¦Ï§Ï¨Ï©ÏªÏ«Ï¬ÏϮϯϰϱϲϳϴϵϷϸϹϺϻϼϽϾϿЀÐЂЃЄЅІЇЈЉЊЋЌÐÐŽÐÐБ +ВГДЕЖЗИЙКЛМÐОПРСТУФХЦЧШЩЪЫЬÐЮЯабвгдежзийклмнопрÑтуфхцчшщъыьÑÑŽÑÑÑ‘Ñ’Ñ“ +єѕіїјљњћќÑÑžÑŸÑ Ñ¡Ñ¢Ñ£Ñ¤Ñ¥Ñ¦Ñ§Ñ¨Ñ©ÑªÑ«Ñ¬ÑѮѯѰѱѲѳѴѵѶѷѸѹѺѻѼѽѾѿҀÒÒŠÒ‹ÒŒÒÒŽÒÒÒ‘Ò’Ò“Ò”Ò•Ò–Ò—Ò˜Ò™ÒšÒ›ÒœÒ +ÒžÒŸÒ Ò¡Ò¢Ò£Ò¤Ò¥Ò¦Ò§Ò¨Ò©ÒªÒ«Ò¬ÒÒ®Ò¯Ò°Ò±Ò²Ò³Ò´ÒµÒ¶Ò·Ò¸Ò¹ÒºÒ»Ò¼Ò½Ò¾Ò¿Ó€ÓÓ‚ÓƒÓ„Ó…Ó†Ó‡ÓˆÓ‰ÓŠÓ‹ÓŒÓÓŽÓÓ‘Ó’Ó“Ó”Ó•Ó–Ó—Ó˜Ó™ÓšÓ›ÓœÓÓžÓŸÓ +Ó¡Ó¢Ó£Ó¤Ó¥Ó¦Ó§Ó¨Ó©ÓªÓ«Ó¬ÓÓ®Ó¯Ó°Ó±Ó²Ó³Ó´ÓµÓ¶Ó·Ó¸Ó¹Ô€ÔÔ‚ÔƒÔ„Ô…Ô†Ô‡ÔˆÔ‰ÔŠÔ‹ÔŒÔÔŽÔÔ±Ô²Ô³Ô´ÔµÔ¶Ô·Ô¸Ô¹ÔºÔ»Ô¼Ô½Ô¾Ô¿Õ€ÕÕ‚ÕƒÕ„Õ…Õ†Õ‡ÕˆÕ‰ +ÕŠÕ‹ÕŒÕÕŽÕÕÕ‘Õ’Õ“Õ”Õ•Õ–Õ¡Õ¢Õ£Õ¤Õ¥Õ¦Õ§Õ¨Õ©ÕªÕ«Õ¬ÕÕ®Õ¯Õ°Õ±Õ²Õ³Õ´ÕµÕ¶Õ·Õ¸Õ¹ÕºÕ»Õ¼Õ½Õ¾Õ¿Ö€ÖւփքօֆևႠႡႢႣႤႥႦႧႨႩႪႫႬႠ+ႮႯႰႱႲႳႴႵႶႷႸႹႺႻႼႽႾႿჀáƒáƒ‚ჃჄჅᴀá´á´‚ᴃᴄᴅᴆᴇᴈᴉᴊᴋᴌá´á´Žá´á´á´‘ᴒᴓᴔᴕᴖᴗᴘᴙᴚᴛᴜá´á´žá´Ÿá´ ᴡᴢᴣᴤᴥᴦᴧᴨᴩ +ᴪᴫᵢᵣᵤᵥᵦᵧᵨᵩᵪᵫᵬáµáµ®áµ¯áµ°áµ±áµ²áµ³áµ´áµµáµ¶áµ·áµ¹áµºáµ»áµ¼áµ½áµ¾áµ¿á¶€á¶á¶‚ᶃᶄᶅᶆᶇᶈᶉᶊᶋᶌá¶á¶Žá¶á¶á¶‘ᶒᶓᶔᶕᶖᶗᶘᶙᶚḀá¸á¸‚ḃḄḅḆḇ +ḈḉḊḋḌá¸á¸Žá¸á¸á¸‘ḒḓḔḕḖḗḘḙḚḛḜá¸á¸žá¸Ÿá¸ ḡḢḣḤḥḦḧḨḩḪḫḬá¸á¸®á¸¯á¸°á¸±á¸²á¸³á¸´á¸µá¸¶á¸·á¸¸á¸¹á¸ºá¸»á¸¼á¸½á¸¾á¸¿á¹€á¹á¹‚ṃṄṅṆṇṈṉ +ṊṋṌá¹á¹Žá¹á¹á¹‘ṒṓṔṕṖṗṘṙṚṛṜá¹á¹žá¹Ÿá¹ ṡṢṣṤṥṦṧṨṩṪṫṬá¹á¹®á¹¯á¹°á¹±á¹²á¹³á¹´á¹µá¹¶á¹·á¹¸á¹¹á¹ºá¹»á¹¼á¹½á¹¾á¹¿áº€áºáº‚ẃẄẅẆẇẈẉẊẋ +ẌáºáºŽáºáºáº‘ẒẓẔẕẖẗẘẙẚẛẠạẢảẤấẦầẨẩẪẫẬáºáº®áº¯áº°áº±áº²áº³áº´áºµáº¶áº·áº¸áº¹áººáº»áº¼áº½áº¾áº¿á»€á»á»‚ểỄễỆệỈỉỊịỌá»á»Žá»á»á»‘ +ỒồỔổỖỗỘộỚớỜá»á»žá»Ÿá» ỡỢợỤụỦủỨứỪừỬá»á»®á»¯á»°á»±á»²á»³á»´á»µá»¶á»·á»¸á»¹á¼€á¼á¼‚ἃἄἅἆἇἈἉἊἋἌá¼á¼Žá¼á¼á¼‘ἒἓἔἕἘἙἚἛ +Ἔá¼á¼ ἡἢἣἤἥἦἧἨἩἪἫἬá¼á¼®á¼¯á¼°á¼±á¼²á¼³á¼´á¼µá¼¶á¼·á¼¸á¼¹á¼ºá¼»á¼¼á¼½á¼¾á¼¿á½€á½á½‚ὃὄὅὈὉὊὋὌá½á½á½‘ὒὓὔὕὖὗὙὛá½á½Ÿá½ ὡὢὣὤὥὦὧ +ὨὩὪὫὬá½á½®á½¯á½°á½±á½²á½³á½´á½µá½¶á½·á½¸á½¹á½ºá½»á½¼á½½á¾€á¾á¾‚ᾃᾄᾅᾆᾇá¾á¾‘ᾒᾓᾔᾕᾖᾗᾠᾡᾢᾣᾤᾥᾦᾧᾰᾱᾲᾳᾴᾶᾷᾸᾹᾺΆιῂῃῄῆῇῈΈῊ +á¿‹á¿á¿‘ῒΐῖῗῘῙῚΊῠῡῢΰῤῥῦῧῨῩῪΎῬῲῳῴῶῷῸΌῺΏâ±â¿â„‚ℇℊℋℌâ„â„Žâ„â„ℑℒℓℕℙℚℛℜâ„ℤΩℨKÅℬâ„ℯℰℱℳℴℹ +ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzªµºÀÃÂÃÄÅÆÇÈÉÊ +ËÌÃÃŽÃÃÑÒÓÔÕÖØÙÚÛÜÃÞßà áâãäåæçèéêëìÃîïðñòóôõöøùúûüýþÿĀÄĂ㥹ĆćĈĉĊċČÄÄŽ +ÄÄđĒēĔĕĖėĘęĚěĜÄÄžÄŸÄ Ä¡Ä¢Ä£Ä¤Ä¥Ä¦Ä§Ä¨Ä©ÄªÄ«Ä¬ÄĮįİıIJijĴĵĶķĸĹĺĻļĽľĿŀÅłŃńŅņŇňʼnŊŋŌÅÅŽÅÅ +őŒœŔŕŖŗŘřŚśŜÅŞşŠšŢţŤťŦŧŨũŪūŬÅŮůŰűŲųŴŵŶŷŸŹźŻżŽžſƀÆƂƃƄƅƆƇƈƉƊƋƌÆÆŽÆÆÆ‘Æ’ +ƓƔƕƖƗƘƙƚƛƜÆÆžÆŸÆ Æ¡Æ¢Æ£Æ¤Æ¥Æ¦Æ§Æ¨Æ©ÆªÆ«Æ¬ÆƮƯưƱƲƳƴƵƶƷƸƹƺƼƽƾƿDŽdžLJljNJnjÇÇŽÇÇǑǒǓǔǕǖǗǘǙǚǛǜ +ÇÇžÇŸÇ Ç¡Ç¢Ç£Ç¤Ç¥Ç¦Ç§Ç¨Ç©ÇªÇ«Ç¬ÇǮǯǰDZdzǴǵǶǷǸǹǺǻǼǽǾǿȀÈȂȃȄȅȆȇȈȉȊȋȌÈÈŽÈÈȑȒȓȔȕȖȗȘșȚțȜÈȞȟ +È È¡È¢È£È¤È¥È¦È§È¨È©ÈªÈ«È¬ÈȮȯȰȱȲȳȴȵȶȷȸȹȺȻȼȽȾȿɀÉÉɑɒɓɔɕɖɗɘəɚɛɜÉÉžÉŸÉ É¡É¢É£É¤É¥É¦É§É¨É©ÉªÉ«É¬Éɮɯ +ɰɱɲɳɴɵɶɷɸɹɺɻɼɽɾɿʀÊʂʃʄʅʆʇʈʉʊʋʌÊÊŽÊÊʑʒʓʔʕʖʗʘʙʚʛʜÊÊžÊŸÊ Ê¡Ê¢Ê£Ê¤Ê¥Ê¦Ê§Ê¨Ê©ÊªÊ«Ê¬ÊʮʯΆΈ +ΉΊΌΎÎÎΑΒΓΔΕΖΗΘΙΚΛΜÎΞΟΠΡΣΤΥΦΧΨΩΪΫάÎήίΰαβγδεζηθικλμνξοπÏÏ‚ÏƒÏ„Ï…Ï†Ï‡ÏˆÏ‰ÏŠÏ‹ÏŒÏ +ÏŽÏϑϒϓϔϕϖϗϘϙϚϛϜÏÏžÏŸÏ Ï¡Ï¢Ï£Ï¤Ï¥Ï¦Ï§Ï¨Ï©ÏªÏ«Ï¬ÏϮϯϰϱϲϳϴϵϷϸϹϺϻϼϽϾϿЀÐЂЃЄЅІЇЈЉЊЋЌÐÐŽÐÐБ +ВГДЕЖЗИЙКЛМÐОПРСТУФХЦЧШЩЪЫЬÐЮЯабвгдежзийклмнопрÑтуфхцчшщъыьÑÑŽÑÑÑ‘Ñ’Ñ“ +єѕіїјљњћќÑÑžÑŸÑ Ñ¡Ñ¢Ñ£Ñ¤Ñ¥Ñ¦Ñ§Ñ¨Ñ©ÑªÑ«Ñ¬ÑѮѯѰѱѲѳѴѵѶѷѸѹѺѻѼѽѾѿҀÒÒŠÒ‹ÒŒÒÒŽÒÒÒ‘Ò’Ò“Ò”Ò•Ò–Ò—Ò˜Ò™ÒšÒ›ÒœÒ +ÒžÒŸÒ Ò¡Ò¢Ò£Ò¤Ò¥Ò¦Ò§Ò¨Ò©ÒªÒ«Ò¬ÒÒ®Ò¯Ò°Ò±Ò²Ò³Ò´ÒµÒ¶Ò·Ò¸Ò¹ÒºÒ»Ò¼Ò½Ò¾Ò¿Ó€ÓÓ‚ÓƒÓ„Ó…Ó†Ó‡ÓˆÓ‰ÓŠÓ‹ÓŒÓÓŽÓÓ‘Ó’Ó“Ó”Ó•Ó–Ó—Ó˜Ó™ÓšÓ›ÓœÓÓžÓŸÓ +Ó¡Ó¢Ó£Ó¤Ó¥Ó¦Ó§Ó¨Ó©ÓªÓ«Ó¬ÓÓ®Ó¯Ó°Ó±Ó²Ó³Ó´ÓµÓ¶Ó·Ó¸Ó¹Ô€ÔÔ‚ÔƒÔ„Ô…Ô†Ô‡ÔˆÔ‰ÔŠÔ‹ÔŒÔÔŽÔÔ±Ô²Ô³Ô´ÔµÔ¶Ô·Ô¸Ô¹ÔºÔ»Ô¼Ô½Ô¾Ô¿Õ€ÕÕ‚ÕƒÕ„Õ…Õ†Õ‡ÕˆÕ‰ +ÕŠÕ‹ÕŒÕÕŽÕÕÕ‘Õ’Õ“Õ”Õ•Õ–Õ¡Õ¢Õ£Õ¤Õ¥Õ¦Õ§Õ¨Õ©ÕªÕ«Õ¬ÕÕ®Õ¯Õ°Õ±Õ²Õ³Õ´ÕµÕ¶Õ·Õ¸Õ¹ÕºÕ»Õ¼Õ½Õ¾Õ¿Ö€ÖւփքօֆևႠႡႢႣႤႥႦႧႨႩႪႫႬႠ+ႮႯႰႱႲႳႴႵႶႷႸႹႺႻႼႽႾႿჀáƒáƒ‚ჃჄჅᴀá´á´‚ᴃᴄᴅᴆᴇᴈᴉᴊᴋᴌá´á´Žá´á´á´‘ᴒᴓᴔᴕᴖᴗᴘᴙᴚᴛᴜá´á´žá´Ÿá´ ᴡᴢᴣᴤᴥᴦᴧᴨᴩ +ᴪᴫᵢᵣᵤᵥᵦᵧᵨᵩᵪᵫᵬáµáµ®áµ¯áµ°áµ±áµ²áµ³áµ´áµµáµ¶áµ·áµ¹áµºáµ»áµ¼áµ½áµ¾áµ¿á¶€á¶á¶‚ᶃᶄᶅᶆᶇᶈᶉᶊᶋᶌá¶á¶Žá¶á¶á¶‘ᶒᶓᶔᶕᶖᶗᶘᶙᶚḀá¸á¸‚ḃḄḅḆḇ +ḈḉḊḋḌá¸á¸Žá¸á¸á¸‘ḒḓḔḕḖḗḘḙḚḛḜá¸á¸žá¸Ÿá¸ ḡḢḣḤḥḦḧḨḩḪḫḬá¸á¸®á¸¯á¸°á¸±á¸²á¸³á¸´á¸µá¸¶á¸·á¸¸á¸¹á¸ºá¸»á¸¼á¸½á¸¾á¸¿á¹€á¹á¹‚ṃṄṅṆṇṈṉ +ṊṋṌá¹á¹Žá¹á¹á¹‘ṒṓṔṕṖṗṘṙṚṛṜá¹á¹žá¹Ÿá¹ ṡṢṣṤṥṦṧṨṩṪṫṬá¹á¹®á¹¯á¹°á¹±á¹²á¹³á¹´á¹µá¹¶á¹·á¹¸á¹¹á¹ºá¹»á¹¼á¹½á¹¾á¹¿áº€áºáº‚ẃẄẅẆẇẈẉẊẋ +ẌáºáºŽáºáºáº‘ẒẓẔẕẖẗẘẙẚẛẠạẢảẤấẦầẨẩẪẫẬáºáº®áº¯áº°áº±áº²áº³áº´áºµáº¶áº·áº¸áº¹áººáº»áº¼áº½áº¾áº¿á»€á»á»‚ểỄễỆệỈỉỊịỌá»á»Žá»á»á»‘ +ỒồỔổỖỗỘộỚớỜá»á»žá»Ÿá» ỡỢợỤụỦủỨứỪừỬá»á»®á»¯á»°á»±á»²á»³á»´á»µá»¶á»·á»¸á»¹á¼€á¼á¼‚ἃἄἅἆἇἈἉἊἋἌá¼á¼Žá¼á¼á¼‘ἒἓἔἕἘἙἚἛ +Ἔá¼á¼ ἡἢἣἤἥἦἧἨἩἪἫἬá¼á¼®á¼¯á¼°á¼±á¼²á¼³á¼´á¼µá¼¶á¼·á¼¸á¼¹á¼ºá¼»á¼¼á¼½á¼¾á¼¿á½€á½á½‚ὃὄὅὈὉὊὋὌá½á½á½‘ὒὓὔὕὖὗὙὛá½á½Ÿá½ ὡὢὣὤὥὦὧ +ὨὩὪὫὬá½á½®á½¯á½°á½±á½²á½³á½´á½µá½¶á½·á½¸á½¹á½ºá½»á½¼á½½á¾€á¾á¾‚ᾃᾄᾅᾆᾇá¾á¾‘ᾒᾓᾔᾕᾖᾗᾠᾡᾢᾣᾤᾥᾦᾧᾰᾱᾲᾳᾴᾶᾷᾸᾹᾺΆιῂῃῄῆῇῈΈῊ +á¿‹á¿á¿‘ῒΐῖῗῘῙῚΊῠῡῢΰῤῥῦῧῨῩῪΎῬῲῳῴῶῷῸΌῺΏâ±â¿â„‚ℇℊℋℌâ„â„Žâ„â„ℑℒℓℕℙℚℛℜâ„ℤΩℨKÅℬâ„ℯℰℱℳℴℹ +ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzªµºÀÃÂÃÄÅÆÇÈÉÊ +ËÌÃÃŽÃÃÑÒÓÔÕÖØÙÚÛÜÃÞßà áâãäåæçèéêëìÃîïðñòóôõöøùúûüýþÿĀÄĂ㥹ĆćĈĉĊċČÄÄŽ +ÄÄđĒēĔĕĖėĘęĚěĜÄÄžÄŸÄ Ä¡Ä¢Ä£Ä¤Ä¥Ä¦Ä§Ä¨Ä©ÄªÄ«Ä¬ÄĮįİıIJijĴĵĶķĸĹĺĻļĽľĿŀÅłŃńŅņŇňʼnŊŋŌÅÅŽÅÅ +őŒœŔŕŖŗŘřŚśŜÅŞşŠšŢţŤťŦŧŨũŪūŬÅŮůŰűŲųŴŵŶŷŸŹźŻżŽžſƀÆƂƃƄƅƆƇƈƉƊƋƌÆÆŽÆÆÆ‘Æ’ +ƓƔƕƖƗƘƙƚƛƜÆÆžÆŸÆ Æ¡Æ¢Æ£Æ¤Æ¥Æ¦Æ§Æ¨Æ©ÆªÆ«Æ¬ÆƮƯưƱƲƳƴƵƶƷƸƹƺƼƽƾƿDŽdžLJljNJnjÇÇŽÇÇǑǒǓǔǕǖǗǘǙǚǛǜ +ÇÇžÇŸÇ Ç¡Ç¢Ç£Ç¤Ç¥Ç¦Ç§Ç¨Ç©ÇªÇ«Ç¬ÇǮǯǰDZdzǴǵǶǷǸǹǺǻǼǽǾǿȀÈȂȃȄȅȆȇȈȉȊȋȌÈÈŽÈÈȑȒȓȔȕȖȗȘșȚțȜÈȞȟ +È È¡È¢È£È¤È¥È¦È§È¨È©ÈªÈ«È¬ÈȮȯȰȱȲȳȴȵȶȷȸȹȺȻȼȽȾȿɀÉÉɑɒɓɔɕɖɗɘəɚɛɜÉÉžÉŸÉ É¡É¢É£É¤É¥É¦É§É¨É©ÉªÉ«É¬Éɮɯ +ɰɱɲɳɴɵɶɷɸɹɺɻɼɽɾɿʀÊʂʃʄʅʆʇʈʉʊʋʌÊÊŽÊÊʑʒʓʔʕʖʗʘʙʚʛʜÊÊžÊŸÊ Ê¡Ê¢Ê£Ê¤Ê¥Ê¦Ê§Ê¨Ê©ÊªÊ«Ê¬ÊʮʯΆΈ +ΉΊΌΎÎÎΑΒΓΔΕΖΗΘΙΚΛΜÎΞΟΠΡΣΤΥΦΧΨΩΪΫάÎήίΰαβγδεζηθικλμνξοπÏÏ‚ÏƒÏ„Ï…Ï†Ï‡ÏˆÏ‰ÏŠÏ‹ÏŒÏ +ÏŽÏϑϒϓϔϕϖϗϘϙϚϛϜÏÏžÏŸÏ Ï¡Ï¢Ï£Ï¤Ï¥Ï¦Ï§Ï¨Ï©ÏªÏ«Ï¬ÏϮϯϰϱϲϳϴϵϷϸϹϺϻϼϽϾϿЀÐЂЃЄЅІЇЈЉЊЋЌÐÐŽÐÐБ +ВГДЕЖЗИЙКЛМÐОПРСТУФХЦЧШЩЪЫЬÐЮЯабвгдежзийклмнопрÑтуфхцчшщъыьÑÑŽÑÑÑ‘Ñ’Ñ“ +єѕіїјљњћќÑÑžÑŸÑ Ñ¡Ñ¢Ñ£Ñ¤Ñ¥Ñ¦Ñ§Ñ¨Ñ©ÑªÑ«Ñ¬ÑѮѯѰѱѲѳѴѵѶѷѸѹѺѻѼѽѾѿҀÒÒŠÒ‹ÒŒÒÒŽÒÒÒ‘Ò’Ò“Ò”Ò•Ò–Ò—Ò˜Ò™ÒšÒ›ÒœÒ +ÒžÒŸÒ Ò¡Ò¢Ò£Ò¤Ò¥Ò¦Ò§Ò¨Ò©ÒªÒ«Ò¬ÒÒ®Ò¯Ò°Ò±Ò²Ò³Ò´ÒµÒ¶Ò·Ò¸Ò¹ÒºÒ»Ò¼Ò½Ò¾Ò¿Ó€ÓÓ‚ÓƒÓ„Ó…Ó†Ó‡ÓˆÓ‰ÓŠÓ‹ÓŒÓÓŽÓÓ‘Ó’Ó“Ó”Ó•Ó–Ó—Ó˜Ó™ÓšÓ›ÓœÓÓžÓŸÓ +Ó¡Ó¢Ó£Ó¤Ó¥Ó¦Ó§Ó¨Ó©ÓªÓ«Ó¬ÓÓ®Ó¯Ó°Ó±Ó²Ó³Ó´ÓµÓ¶Ó·Ó¸Ó¹Ô€ÔÔ‚ÔƒÔ„Ô…Ô†Ô‡ÔˆÔ‰ÔŠÔ‹ÔŒÔÔŽÔÔ±Ô²Ô³Ô´ÔµÔ¶Ô·Ô¸Ô¹ÔºÔ»Ô¼Ô½Ô¾Ô¿Õ€ÕÕ‚ÕƒÕ„Õ…Õ†Õ‡ÕˆÕ‰ +ÕŠÕ‹ÕŒÕÕŽÕÕÕ‘Õ’Õ“Õ”Õ•Õ–Õ¡Õ¢Õ£Õ¤Õ¥Õ¦Õ§Õ¨Õ©ÕªÕ«Õ¬ÕÕ®Õ¯Õ°Õ±Õ²Õ³Õ´ÕµÕ¶Õ·Õ¸Õ¹ÕºÕ»Õ¼Õ½Õ¾Õ¿Ö€ÖւփքօֆևႠႡႢႣႤႥႦႧႨႩႪႫႬႠ+ႮႯႰႱႲႳႴႵႶႷႸႹႺႻႼႽႾႿჀáƒáƒ‚ჃჄჅᴀá´á´‚ᴃᴄᴅᴆᴇᴈᴉᴊᴋᴌá´á´Žá´á´á´‘ᴒᴓᴔᴕᴖᴗᴘᴙᴚᴛᴜá´á´žá´Ÿá´ ᴡᴢᴣᴤᴥᴦᴧᴨᴩ +ᴪᴫᵢᵣᵤᵥᵦᵧᵨᵩᵪᵫᵬáµáµ®áµ¯áµ°áµ±áµ²áµ³áµ´áµµáµ¶áµ·áµ¹áµºáµ»áµ¼áµ½áµ¾áµ¿á¶€á¶á¶‚ᶃᶄᶅᶆᶇᶈᶉᶊᶋᶌá¶á¶Žá¶á¶á¶‘ᶒᶓᶔᶕᶖᶗᶘᶙᶚḀá¸á¸‚ḃḄḅḆḇ +ḈḉḊḋḌá¸á¸Žá¸á¸á¸‘ḒḓḔḕḖḗḘḙḚḛḜá¸á¸žá¸Ÿá¸ ḡḢḣḤḥḦḧḨḩḪḫḬá¸á¸®á¸¯á¸°á¸±á¸²á¸³á¸´á¸µá¸¶á¸·á¸¸á¸¹á¸ºá¸»á¸¼á¸½á¸¾á¸¿á¹€á¹á¹‚ṃṄṅṆṇṈṉ +ṊṋṌá¹á¹Žá¹á¹á¹‘ṒṓṔṕṖṗṘṙṚṛṜá¹á¹žá¹Ÿá¹ ṡṢṣṤṥṦṧṨṩṪṫṬá¹á¹®á¹¯á¹°á¹±á¹²á¹³á¹´á¹µá¹¶á¹·á¹¸á¹¹á¹ºá¹»á¹¼á¹½á¹¾á¹¿áº€áºáº‚ẃẄẅẆẇẈẉẊẋ +ẌáºáºŽáºáºáº‘ẒẓẔẕẖẗẘẙẚẛẠạẢảẤấẦầẨẩẪẫẬáºáº®áº¯áº°áº±áº²áº³áº´áºµáº¶áº·áº¸áº¹áººáº»áº¼áº½áº¾áº¿á»€á»á»‚ểỄễỆệỈỉỊịỌá»á»Žá»á»á»‘ +ỒồỔổỖỗỘộỚớỜá»á»žá»Ÿá» ỡỢợỤụỦủỨứỪừỬá»á»®á»¯á»°á»±á»²á»³á»´á»µá»¶á»·á»¸á»¹á¼€á¼á¼‚ἃἄἅἆἇἈἉἊἋἌá¼á¼Žá¼á¼á¼‘ἒἓἔἕἘἙἚἛ +Ἔá¼á¼ ἡἢἣἤἥἦἧἨἩἪἫἬá¼á¼®á¼¯á¼°á¼±á¼²á¼³á¼´á¼µá¼¶á¼·á¼¸á¼¹á¼ºá¼»á¼¼á¼½á¼¾á¼¿á½€á½á½‚ὃὄὅὈὉὊὋὌá½á½á½‘ὒὓὔὕὖὗὙὛá½á½Ÿá½ ὡὢὣὤὥὦὧ +ὨὩὪὫὬá½á½®á½¯á½°á½±á½²á½³á½´á½µá½¶á½·á½¸á½¹á½ºá½»á½¼á½½á¾€á¾á¾‚ᾃᾄᾅᾆᾇá¾á¾‘ᾒᾓᾔᾕᾖᾗᾠᾡᾢᾣᾤᾥᾦᾧᾰᾱᾲᾳᾴᾶᾷᾸᾹᾺΆιῂῃῄῆῇῈΈῊ +á¿‹á¿á¿‘ῒΐῖῗῘῙῚΊῠῡῢΰῤῥῦῧῨῩῪΎῬῲῳῴῶῷῸΌῺΏâ±â¿â„‚ℇℊℋℌâ„â„Žâ„â„ℑℒℓℕℙℚℛℜâ„ℤΩℨKÅℬâ„ℯℰℱℳℴℹ +ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzªµºÀÃÂÃÄÅÆÇÈÉÊ +ËÌÃÃŽÃÃÑÒÓÔÕÖØÙÚÛÜÃÞßà áâãäåæçèéêëìÃîïðñòóôõöøùúûüýþÿĀÄĂ㥹ĆćĈĉĊċČÄÄŽ +ÄÄđĒēĔĕĖėĘęĚěĜÄÄžÄŸÄ Ä¡Ä¢Ä£Ä¤Ä¥Ä¦Ä§Ä¨Ä©ÄªÄ«Ä¬ÄĮįİıIJijĴĵĶķĸĹĺĻļĽľĿŀÅłŃńŅņŇňʼnŊŋŌÅÅŽÅÅ +őŒœŔŕŖŗŘřŚśŜÅŞşŠšŢţŤťŦŧŨũŪūŬÅŮůŰűŲųŴŵŶŷŸŹźŻżŽžſƀÆƂƃƄƅƆƇƈƉƊƋƌÆÆŽÆÆÆ‘Æ’ +ƓƔƕƖƗƘƙƚƛƜÆÆžÆŸÆ Æ¡Æ¢Æ£Æ¤Æ¥Æ¦Æ§Æ¨Æ©ÆªÆ«Æ¬ÆƮƯưƱƲƳƴƵƶƷƸƹƺƼƽƾƿDŽdžLJljNJnjÇÇŽÇÇǑǒǓǔǕǖǗǘǙǚǛǜ +ÇÇžÇŸÇ Ç¡Ç¢Ç£Ç¤Ç¥Ç¦Ç§Ç¨Ç©ÇªÇ«Ç¬ÇǮǯǰDZdzǴǵǶǷǸǹǺǻǼǽǾǿȀÈȂȃȄȅȆȇȈȉȊȋȌÈÈŽÈÈȑȒȓȔȕȖȗȘșȚțȜÈȞȟ +È È¡È¢È£È¤È¥È¦È§È¨È©ÈªÈ«È¬ÈȮȯȰȱȲȳȴȵȶȷȸȹȺȻȼȽȾȿɀÉÉɑɒɓɔɕɖɗɘəɚɛɜÉÉžÉŸÉ É¡É¢É£É¤É¥É¦É§É¨É©ÉªÉ«É¬Éɮɯ +ɰɱɲɳɴɵɶɷɸɹɺɻɼɽɾɿʀÊʂʃʄʅʆʇʈʉʊʋʌÊÊŽÊÊʑʒʓʔʕʖʗʘʙʚʛʜÊÊžÊŸÊ Ê¡Ê¢Ê£Ê¤Ê¥Ê¦Ê§Ê¨Ê©ÊªÊ«Ê¬ÊʮʯΆΈ +ΉΊΌΎÎÎΑΒΓΔΕΖΗΘΙΚΛΜÎΞΟΠΡΣΤΥΦΧΨΩΪΫάÎήίΰαβγδεζηθικλμνξοπÏÏ‚ÏƒÏ„Ï…Ï†Ï‡ÏˆÏ‰ÏŠÏ‹ÏŒÏ +ÏŽÏϑϒϓϔϕϖϗϘϙϚϛϜÏÏžÏŸÏ Ï¡Ï¢Ï£Ï¤Ï¥Ï¦Ï§Ï¨Ï©ÏªÏ«Ï¬ÏϮϯϰϱϲϳϴϵϷϸϹϺϻϼϽϾϿЀÐЂЃЄЅІЇЈЉЊЋЌÐÐŽÐÐБ +ВГДЕЖЗИЙКЛМÐОПРСТУФХЦЧШЩЪЫЬÐЮЯабвгдежзийклмнопрÑтуфхцчшщъыьÑÑŽÑÑÑ‘Ñ’Ñ“ +єѕіїјљњћќÑÑžÑŸÑ Ñ¡Ñ¢Ñ£Ñ¤Ñ¥Ñ¦Ñ§Ñ¨Ñ©ÑªÑ«Ñ¬ÑѮѯѰѱѲѳѴѵѶѷѸѹѺѻѼѽѾѿҀÒÒŠÒ‹ÒŒÒÒŽÒÒÒ‘Ò’Ò“Ò”Ò•Ò–Ò—Ò˜Ò™ÒšÒ›ÒœÒ +ÒžÒŸÒ Ò¡Ò¢Ò£Ò¤Ò¥Ò¦Ò§Ò¨Ò©ÒªÒ«Ò¬ÒÒ®Ò¯Ò°Ò±Ò²Ò³Ò´ÒµÒ¶Ò·Ò¸Ò¹ÒºÒ»Ò¼Ò½Ò¾Ò¿Ó€ÓÓ‚ÓƒÓ„Ó…Ó†Ó‡ÓˆÓ‰ÓŠÓ‹ÓŒÓÓŽÓÓ‘Ó’Ó“Ó”Ó•Ó–Ó—Ó˜Ó™ÓšÓ›ÓœÓÓžÓŸÓ +Ó¡Ó¢Ó£Ó¤Ó¥Ó¦Ó§Ó¨Ó©ÓªÓ«Ó¬ÓÓ®Ó¯Ó°Ó±Ó²Ó³Ó´ÓµÓ¶Ó·Ó¸Ó¹Ô€ÔÔ‚ÔƒÔ„Ô…Ô†Ô‡ÔˆÔ‰ÔŠÔ‹ÔŒÔÔŽÔÔ±Ô²Ô³Ô´ÔµÔ¶Ô·Ô¸Ô¹ÔºÔ»Ô¼Ô½Ô¾Ô¿Õ€ÕÕ‚ÕƒÕ„Õ…Õ†Õ‡ÕˆÕ‰ +ÕŠÕ‹ÕŒÕÕŽÕÕÕ‘Õ’Õ“Õ”Õ•Õ–Õ¡Õ¢Õ£Õ¤Õ¥Õ¦Õ§Õ¨Õ©ÕªÕ«Õ¬ÕÕ®Õ¯Õ°Õ±Õ²Õ³Õ´ÕµÕ¶Õ·Õ¸Õ¹ÕºÕ»Õ¼Õ½Õ¾Õ¿Ö€ÖւփքօֆևႠႡႢႣႤႥႦႧႨႩႪႫႬႠ+ႮႯႰႱႲႳႴႵႶႷႸႹႺႻႼႽႾႿჀáƒáƒ‚ჃჄჅᴀá´á´‚ᴃᴄᴅᴆᴇᴈᴉᴊᴋᴌá´á´Žá´á´á´‘ᴒᴓᴔᴕᴖᴗᴘᴙᴚᴛᴜá´á´žá´Ÿá´ ᴡᴢᴣᴤᴥᴦᴧᴨᴩ +ᴪᴫᵢᵣᵤᵥᵦᵧᵨᵩᵪᵫᵬáµáµ®áµ¯áµ°áµ±áµ²áµ³áµ´áµµáµ¶áµ·áµ¹áµºáµ»áµ¼áµ½áµ¾áµ¿á¶€á¶á¶‚ᶃᶄᶅᶆᶇᶈᶉᶊᶋᶌá¶á¶Žá¶á¶á¶‘ᶒᶓᶔᶕᶖᶗᶘᶙᶚḀá¸á¸‚ḃḄḅḆḇ +ḈḉḊḋḌá¸á¸Žá¸á¸á¸‘ḒḓḔḕḖḗḘḙḚḛḜá¸á¸žá¸Ÿá¸ ḡḢḣḤḥḦḧḨḩḪḫḬá¸á¸®á¸¯á¸°á¸±á¸²á¸³á¸´á¸µá¸¶á¸·á¸¸á¸¹á¸ºá¸»á¸¼á¸½á¸¾á¸¿á¹€á¹á¹‚ṃṄṅṆṇṈṉ +ṊṋṌá¹á¹Žá¹á¹á¹‘ṒṓṔṕṖṗṘṙṚṛṜá¹á¹žá¹Ÿá¹ ṡṢṣṤṥṦṧṨṩṪṫṬá¹á¹®á¹¯á¹°á¹±á¹²á¹³á¹´á¹µá¹¶á¹·á¹¸á¹¹á¹ºá¹»á¹¼á¹½á¹¾á¹¿áº€áºáº‚ẃẄẅẆẇẈẉẊẋ +ẌáºáºŽáºáºáº‘ẒẓẔẕẖẗẘẙẚẛẠạẢảẤấẦầẨẩẪẫẬáºáº®áº¯áº°áº±áº²áº³áº´áºµáº¶áº·áº¸áº¹áººáº»áº¼áº½áº¾áº¿á»€á»á»‚ểỄễỆệỈỉỊịỌá»á»Žá»á»á»‘ +ỒồỔổỖỗỘộỚớỜá»á»žá»Ÿá» ỡỢợỤụỦủỨứỪừỬá»á»®á»¯á»°á»±á»²á»³á»´á»µá»¶á»·á»¸á»¹á¼€á¼á¼‚ἃἄἅἆἇἈἉἊἋἌá¼á¼Žá¼á¼á¼‘ἒἓἔἕἘἙἚἛ +Ἔá¼á¼ ἡἢἣἤἥἦἧἨἩἪἫἬá¼á¼®á¼¯á¼°á¼±á¼²á¼³á¼´á¼µá¼¶á¼·á¼¸á¼¹á¼ºá¼»á¼¼á¼½á¼¾á¼¿á½€á½á½‚ὃὄὅὈὉὊὋὌá½á½á½‘ὒὓὔὕὖὗὙὛá½á½Ÿá½ ὡὢὣὤὥὦὧ +ὨὩὪὫὬá½á½®á½¯á½°á½±á½²á½³á½´á½µá½¶á½·á½¸á½¹á½ºá½»á½¼á½½á¾€á¾á¾‚ᾃᾄᾅᾆᾇá¾á¾‘ᾒᾓᾔᾕᾖᾗᾠᾡᾢᾣᾤᾥᾦᾧᾰᾱᾲᾳᾴᾶᾷᾸᾹᾺΆιῂῃῄῆῇῈΈῊ +á¿‹á¿á¿‘ῒΐῖῗῘῙῚΊῠῡῢΰῤῥῦῧῨῩῪΎῬῲῳῴῶῷῸΌῺΏâ±â¿â„‚ℇℊℋℌâ„â„Žâ„â„ℑℒℓℕℙℚℛℜâ„ℤΩℨKÅℬâ„ℯℰℱℳℴℹ +ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzªµºÀÃÂÃÄÅÆÇÈÉÊ +ËÌÃÃŽÃÃÑÒÓÔÕÖØÙÚÛÜÃÞßà áâãäåæçèéêëìÃîïðñòóôõöøùúûüýþÿĀÄĂ㥹ĆćĈĉĊċČÄÄŽ +ÄÄđĒēĔĕĖėĘęĚěĜÄÄžÄŸÄ Ä¡Ä¢Ä£Ä¤Ä¥Ä¦Ä§Ä¨Ä©ÄªÄ«Ä¬ÄĮįİıIJijĴĵĶķĸĹĺĻļĽľĿŀÅłŃńŅņŇňʼnŊŋŌÅÅŽÅÅ +őŒœŔŕŖŗŘřŚśŜÅŞşŠšŢţŤťŦŧŨũŪūŬÅŮůŰűŲųŴŵŶŷŸŹźŻżŽžſƀÆƂƃƄƅƆƇƈƉƊƋƌÆÆŽÆÆÆ‘Æ’ +ƓƔƕƖƗƘƙƚƛƜÆÆžÆŸÆ Æ¡Æ¢Æ£Æ¤Æ¥Æ¦Æ§Æ¨Æ©ÆªÆ«Æ¬ÆƮƯưƱƲƳƴƵƶƷƸƹƺƼƽƾƿDŽdžLJljNJnjÇÇŽÇÇǑǒǓǔǕǖǗǘǙǚǛǜ +ÇÇžÇŸÇ Ç¡Ç¢Ç£Ç¤Ç¥Ç¦Ç§Ç¨Ç©ÇªÇ«Ç¬ÇǮǯǰDZdzǴǵǶǷǸǹǺǻǼǽǾǿȀÈȂȃȄȅȆȇȈȉȊȋȌÈÈŽÈÈȑȒȓȔȕȖȗȘșȚțȜÈȞȟ +È È¡È¢È£È¤È¥È¦È§È¨È©ÈªÈ«È¬ÈȮȯȰȱȲȳȴȵȶȷȸȹȺȻȼȽȾȿɀÉÉɑɒɓɔɕɖɗɘəɚɛɜÉÉžÉŸÉ É¡É¢É£É¤É¥É¦É§É¨É©ÉªÉ«É¬Éɮɯ +ɰɱɲɳɴɵɶɷɸɹɺɻɼɽɾɿʀÊʂʃʄʅʆʇʈʉʊʋʌÊÊŽÊÊʑʒʓʔʕʖʗʘʙʚʛʜÊÊžÊŸÊ Ê¡Ê¢Ê£Ê¤Ê¥Ê¦Ê§Ê¨Ê©ÊªÊ«Ê¬ÊʮʯΆΈ +ΉΊΌΎÎÎΑΒΓΔΕΖΗΘΙΚΛΜÎΞΟΠΡΣΤΥΦΧΨΩΪΫάÎήίΰαβγδεζηθικλμνξοπÏÏ‚ÏƒÏ„Ï…Ï†Ï‡ÏˆÏ‰ÏŠÏ‹ÏŒÏ +ÏŽÏϑϒϓϔϕϖϗϘϙϚϛϜÏÏžÏŸÏ Ï¡Ï¢Ï£Ï¤Ï¥Ï¦Ï§Ï¨Ï©ÏªÏ«Ï¬ÏϮϯϰϱϲϳϴϵϷϸϹϺϻϼϽϾϿЀÐЂЃЄЅІЇЈЉЊЋЌÐÐŽÐÐБ +ВГДЕЖЗИЙКЛМÐОПРСТУФХЦЧШЩЪЫЬÐЮЯабвгдежзийклмнопрÑтуфхцчшщъыьÑÑŽÑÑÑ‘Ñ’Ñ“ +єѕіїјљњћќÑÑžÑŸÑ Ñ¡Ñ¢Ñ£Ñ¤Ñ¥Ñ¦Ñ§Ñ¨Ñ©ÑªÑ«Ñ¬ÑѮѯѰѱѲѳѴѵѶѷѸѹѺѻѼѽѾѿҀÒÒŠÒ‹ÒŒÒÒŽÒÒÒ‘Ò’Ò“Ò”Ò•Ò–Ò—Ò˜Ò™ÒšÒ›ÒœÒ +ÒžÒŸÒ Ò¡Ò¢Ò£Ò¤Ò¥Ò¦Ò§Ò¨Ò©ÒªÒ«Ò¬ÒÒ®Ò¯Ò°Ò±Ò²Ò³Ò´ÒµÒ¶Ò·Ò¸Ò¹ÒºÒ»Ò¼Ò½Ò¾Ò¿Ó€ÓÓ‚ÓƒÓ„Ó…Ó†Ó‡ÓˆÓ‰ÓŠÓ‹ÓŒÓÓŽÓÓ‘Ó’Ó“Ó”Ó•Ó–Ó—Ó˜Ó™ÓšÓ›ÓœÓÓžÓŸÓ +Ó¡Ó¢Ó£Ó¤Ó¥Ó¦Ó§Ó¨Ó©ÓªÓ«Ó¬ÓÓ®Ó¯Ó°Ó±Ó²Ó³Ó´ÓµÓ¶Ó·Ó¸Ó¹Ô€ÔÔ‚ÔƒÔ„Ô…Ô†Ô‡ÔˆÔ‰ÔŠÔ‹ÔŒÔÔŽÔÔ±Ô²Ô³Ô´ÔµÔ¶Ô·Ô¸Ô¹ÔºÔ»Ô¼Ô½Ô¾Ô¿Õ€ÕÕ‚ÕƒÕ„Õ…Õ†Õ‡ÕˆÕ‰ +ÕŠÕ‹ÕŒÕÕŽÕÕÕ‘Õ’Õ“Õ”Õ•Õ–Õ¡Õ¢Õ£Õ¤Õ¥Õ¦Õ§Õ¨Õ©ÕªÕ«Õ¬ÕÕ®Õ¯Õ°Õ±Õ²Õ³Õ´ÕµÕ¶Õ·Õ¸Õ¹ÕºÕ»Õ¼Õ½Õ¾Õ¿Ö€ÖւփքօֆևႠႡႢႣႤႥႦႧႨႩႪႫႬႠ+ႮႯႰႱႲႳႴႵႶႷႸႹႺႻႼႽႾႿჀáƒáƒ‚ჃჄჅᴀá´á´‚ᴃᴄᴅᴆᴇᴈᴉᴊᴋᴌá´á´Žá´á´á´‘ᴒᴓᴔᴕᴖᴗᴘᴙᴚᴛᴜá´á´žá´Ÿá´ ᴡᴢᴣᴤᴥᴦᴧᴨᴩ +ᴪᴫᵢᵣᵤᵥᵦᵧᵨᵩᵪᵫᵬáµáµ®áµ¯áµ°áµ±áµ²áµ³áµ´áµµáµ¶áµ·áµ¹áµºáµ»áµ¼áµ½áµ¾áµ¿á¶€á¶á¶‚ᶃᶄᶅᶆᶇᶈᶉᶊᶋᶌá¶á¶Žá¶á¶á¶‘ᶒᶓᶔᶕᶖᶗᶘᶙᶚḀá¸á¸‚ḃḄḅḆḇ +ḈḉḊḋḌá¸á¸Žá¸á¸á¸‘ḒḓḔḕḖḗḘḙḚḛḜá¸á¸žá¸Ÿá¸ ḡḢḣḤḥḦḧḨḩḪḫḬá¸á¸®á¸¯á¸°á¸±á¸²á¸³á¸´á¸µá¸¶á¸·á¸¸á¸¹á¸ºá¸»á¸¼á¸½á¸¾á¸¿á¹€á¹á¹‚ṃṄṅṆṇṈṉ +ṊṋṌá¹á¹Žá¹á¹á¹‘ṒṓṔṕṖṗṘṙṚṛṜá¹á¹žá¹Ÿá¹ ṡṢṣṤṥṦṧṨṩṪṫṬá¹á¹®á¹¯á¹°á¹±á¹²á¹³á¹´á¹µá¹¶á¹·á¹¸á¹¹á¹ºá¹»á¹¼á¹½á¹¾á¹¿áº€áºáº‚ẃẄẅẆẇẈẉẊẋ +ẌáºáºŽáºáºáº‘ẒẓẔẕẖẗẘẙẚẛẠạẢảẤấẦầẨẩẪẫẬáºáº®áº¯áº°áº±áº²áº³áº´áºµáº¶áº·áº¸áº¹áººáº»áº¼áº½áº¾áº¿á»€á»á»‚ểỄễỆệỈỉỊịỌá»á»Žá»á»á»‘ +ỒồỔổỖỗỘộỚớỜá»á»žá»Ÿá» ỡỢợỤụỦủỨứỪừỬá»á»®á»¯á»°á»±á»²á»³á»´á»µá»¶á»·á»¸á»¹á¼€á¼á¼‚ἃἄἅἆἇἈἉἊἋἌá¼á¼Žá¼á¼á¼‘ἒἓἔἕἘἙἚἛ +Ἔá¼á¼ ἡἢἣἤἥἦἧἨἩἪἫἬá¼á¼®á¼¯á¼°á¼±á¼²á¼³á¼´á¼µá¼¶á¼·á¼¸á¼¹á¼ºá¼»á¼¼á¼½á¼¾á¼¿á½€á½á½‚ὃὄὅὈὉὊὋὌá½á½á½‘ὒὓὔὕὖὗὙὛá½á½Ÿá½ ὡὢὣὤὥὦὧ +ὨὩὪὫὬá½á½®á½¯á½°á½±á½²á½³á½´á½µá½¶á½·á½¸á½¹á½ºá½»á½¼á½½á¾€á¾á¾‚ᾃᾄᾅᾆᾇá¾á¾‘ᾒᾓᾔᾕᾖᾗᾠᾡᾢᾣᾤᾥᾦᾧᾰᾱᾲᾳᾴᾶᾷᾸᾹᾺΆιῂῃῄῆῇῈΈῊ +á¿‹á¿á¿‘ῒΐῖῗῘῙῚΊῠῡῢΰῤῥῦῧῨῩῪΎῬῲῳῴῶῷῸΌῺΏâ±â¿â„‚ℇℊℋℌâ„â„Žâ„â„ℑℒℓℕℙℚℛℜâ„ℤΩℨKÅℬâ„ℯℰℱℳℴℹ +ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzªµºÀÃÂÃÄÅÆÇÈÉÊ +ËÌÃÃŽÃÃÑÒÓÔÕÖØÙÚÛÜÃÞßà áâãäåæçèéêëìÃîïðñòóôõöøùúûüýþÿĀÄĂ㥹ĆćĈĉĊċČÄÄŽ +ÄÄđĒēĔĕĖėĘęĚěĜÄÄžÄŸÄ Ä¡Ä¢Ä£Ä¤Ä¥Ä¦Ä§Ä¨Ä©ÄªÄ«Ä¬ÄĮįİıIJijĴĵĶķĸĹĺĻļĽľĿŀÅłŃńŅņŇňʼnŊŋŌÅÅŽÅÅ +őŒœŔŕŖŗŘřŚśŜÅŞşŠšŢţŤťŦŧŨũŪūŬÅŮůŰűŲųŴŵŶŷŸŹźŻżŽžſƀÆƂƃƄƅƆƇƈƉƊƋƌÆÆŽÆÆÆ‘Æ’ +ƓƔƕƖƗƘƙƚƛƜÆÆžÆŸÆ Æ¡Æ¢Æ£Æ¤Æ¥Æ¦Æ§Æ¨Æ©ÆªÆ«Æ¬ÆƮƯưƱƲƳƴƵƶƷƸƹƺƼƽƾƿDŽdžLJljNJnjÇÇŽÇÇǑǒǓǔǕǖǗǘǙǚǛǜ +ÇÇžÇŸÇ Ç¡Ç¢Ç£Ç¤Ç¥Ç¦Ç§Ç¨Ç©ÇªÇ«Ç¬ÇǮǯǰDZdzǴǵǶǷǸǹǺǻǼǽǾǿȀÈȂȃȄȅȆȇȈȉȊȋȌÈÈŽÈÈȑȒȓȔȕȖȗȘșȚțȜÈȞȟ +È È¡È¢È£È¤È¥È¦È§È¨È©ÈªÈ«È¬ÈȮȯȰȱȲȳȴȵȶȷȸȹȺȻȼȽȾȿɀÉÉɑɒɓɔɕɖɗɘəɚɛɜÉÉžÉŸÉ É¡É¢É£É¤É¥É¦É§É¨É©ÉªÉ«É¬Éɮɯ +ɰɱɲɳɴɵɶɷɸɹɺɻɼɽɾɿʀÊʂʃʄʅʆʇʈʉʊʋʌÊÊŽÊÊʑʒʓʔʕʖʗʘʙʚʛʜÊÊžÊŸÊ Ê¡Ê¢Ê£Ê¤Ê¥Ê¦Ê§Ê¨Ê©ÊªÊ«Ê¬ÊʮʯΆΈ +ΉΊΌΎÎÎΑΒΓΔΕΖΗΘΙΚΛΜÎΞΟΠΡΣΤΥΦΧΨΩΪΫάÎήίΰαβγδεζηθικλμνξοπÏÏ‚ÏƒÏ„Ï…Ï†Ï‡ÏˆÏ‰ÏŠÏ‹ÏŒÏ +ÏŽÏϑϒϓϔϕϖϗϘϙϚϛϜÏÏžÏŸÏ Ï¡Ï¢Ï£Ï¤Ï¥Ï¦Ï§Ï¨Ï©ÏªÏ«Ï¬ÏϮϯϰϱϲϳϴϵϷϸϹϺϻϼϽϾϿЀÐЂЃЄЅІЇЈЉЊЋЌÐÐŽÐÐБ +ВГДЕЖЗИЙКЛМÐОПРСТУФХЦЧШЩЪЫЬÐЮЯабвгдежзийклмнопрÑтуфхцчшщъыьÑÑŽÑÑÑ‘Ñ’Ñ“ +єѕіїјљњћќÑÑžÑŸÑ Ñ¡Ñ¢Ñ£Ñ¤Ñ¥Ñ¦Ñ§Ñ¨Ñ©ÑªÑ«Ñ¬ÑѮѯѰѱѲѳѴѵѶѷѸѹѺѻѼѽѾѿҀÒÒŠÒ‹ÒŒÒÒŽÒÒÒ‘Ò’Ò“Ò”Ò•Ò–Ò—Ò˜Ò™ÒšÒ›ÒœÒ +ÒžÒŸÒ Ò¡Ò¢Ò£Ò¤Ò¥Ò¦Ò§Ò¨Ò©ÒªÒ«Ò¬ÒÒ®Ò¯Ò°Ò±Ò²Ò³Ò´ÒµÒ¶Ò·Ò¸Ò¹ÒºÒ»Ò¼Ò½Ò¾Ò¿Ó€ÓÓ‚ÓƒÓ„Ó…Ó†Ó‡ÓˆÓ‰ÓŠÓ‹ÓŒÓÓŽÓÓ‘Ó’Ó“Ó”Ó•Ó–Ó—Ó˜Ó™ÓšÓ›ÓœÓÓžÓŸÓ +Ó¡Ó¢Ó£Ó¤Ó¥Ó¦Ó§Ó¨Ó©ÓªÓ«Ó¬ÓÓ®Ó¯Ó°Ó±Ó²Ó³Ó´ÓµÓ¶Ó·Ó¸Ó¹Ô€ÔÔ‚ÔƒÔ„Ô…Ô†Ô‡ÔˆÔ‰ÔŠÔ‹ÔŒÔÔŽÔÔ±Ô²Ô³Ô´ÔµÔ¶Ô·Ô¸Ô¹ÔºÔ»Ô¼Ô½Ô¾Ô¿Õ€ÕÕ‚ÕƒÕ„Õ…Õ†Õ‡ÕˆÕ‰ +ÕŠÕ‹ÕŒÕÕŽÕÕÕ‘Õ’Õ“Õ”Õ•Õ–Õ¡Õ¢Õ£Õ¤Õ¥Õ¦Õ§Õ¨Õ©ÕªÕ«Õ¬ÕÕ®Õ¯Õ°Õ±Õ²Õ³Õ´ÕµÕ¶Õ·Õ¸Õ¹ÕºÕ»Õ¼Õ½Õ¾Õ¿Ö€ÖւփքօֆևႠႡႢႣႤႥႦႧႨႩႪႫႬႠ+ႮႯႰႱႲႳႴႵႶႷႸႹႺႻႼႽႾႿჀáƒáƒ‚ჃჄჅᴀá´á´‚ᴃᴄᴅᴆᴇᴈᴉᴊᴋᴌá´á´Žá´á´á´‘ᴒᴓᴔᴕᴖᴗᴘᴙᴚᴛᴜá´á´žá´Ÿá´ ᴡᴢᴣᴤᴥᴦᴧᴨᴩ +ᴪᴫᵢᵣᵤᵥᵦᵧᵨᵩᵪᵫᵬáµáµ®áµ¯áµ°áµ±áµ²áµ³áµ´áµµáµ¶áµ·áµ¹áµºáµ»áµ¼áµ½áµ¾áµ¿á¶€á¶á¶‚ᶃᶄᶅᶆᶇᶈᶉᶊᶋᶌá¶á¶Žá¶á¶á¶‘ᶒᶓᶔᶕᶖᶗᶘᶙᶚḀá¸á¸‚ḃḄḅḆḇ +ḈḉḊḋḌá¸á¸Žá¸á¸á¸‘ḒḓḔḕḖḗḘḙḚḛḜá¸á¸žá¸Ÿá¸ ḡḢḣḤḥḦḧḨḩḪḫḬá¸á¸®á¸¯á¸°á¸±á¸²á¸³á¸´á¸µá¸¶á¸·á¸¸á¸¹á¸ºá¸»á¸¼á¸½á¸¾á¸¿á¹€á¹á¹‚ṃṄṅṆṇṈṉ +ṊṋṌá¹á¹Žá¹á¹á¹‘ṒṓṔṕṖṗṘṙṚṛṜá¹á¹žá¹Ÿá¹ ṡṢṣṤṥṦṧṨṩṪṫṬá¹á¹®á¹¯á¹°á¹±á¹²á¹³á¹´á¹µá¹¶á¹·á¹¸á¹¹á¹ºá¹»á¹¼á¹½á¹¾á¹¿áº€áºáº‚ẃẄẅẆẇẈẉẊẋ +ẌáºáºŽáºáºáº‘ẒẓẔẕẖẗẘẙẚẛẠạẢảẤấẦầẨẩẪẫẬáºáº®áº¯áº°áº±áº²áº³áº´áºµáº¶áº·áº¸áº¹áººáº»áº¼áº½áº¾áº¿á»€á»á»‚ểỄễỆệỈỉỊịỌá»á»Žá»á»á»‘ +ỒồỔổỖỗỘộỚớỜá»á»žá»Ÿá» ỡỢợỤụỦủỨứỪừỬá»á»®á»¯á»°á»±á»²á»³á»´á»µá»¶á»·á»¸á»¹á¼€á¼á¼‚ἃἄἅἆἇἈἉἊἋἌá¼á¼Žá¼á¼á¼‘ἒἓἔἕἘἙἚἛ +Ἔá¼á¼ ἡἢἣἤἥἦἧἨἩἪἫἬá¼á¼®á¼¯á¼°á¼±á¼²á¼³á¼´á¼µá¼¶á¼·á¼¸á¼¹á¼ºá¼»á¼¼á¼½á¼¾á¼¿á½€á½á½‚ὃὄὅὈὉὊὋὌá½á½á½‘ὒὓὔὕὖὗὙὛá½á½Ÿá½ ὡὢὣὤὥὦὧ +ὨὩὪὫὬá½á½®á½¯á½°á½±á½²á½³á½´á½µá½¶á½·á½¸á½¹á½ºá½»á½¼á½½á¾€á¾á¾‚ᾃᾄᾅᾆᾇá¾á¾‘ᾒᾓᾔᾕᾖᾗᾠᾡᾢᾣᾤᾥᾦᾧᾰᾱᾲᾳᾴᾶᾷᾸᾹᾺΆιῂῃῄῆῇῈΈῊ +á¿‹á¿á¿‘ῒΐῖῗῘῙῚΊῠῡῢΰῤῥῦῧῨῩῪΎῬῲῳῴῶῷῸΌῺΏâ±â¿â„‚ℇℊℋℌâ„â„Žâ„â„ℑℒℓℕℙℚℛℜâ„ℤΩℨKÅℬâ„ℯℰℱℳℴℹ +ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzªµºÀÃÂÃÄÅÆÇÈÉÊ +ËÌÃÃŽÃÃÑÒÓÔÕÖØÙÚÛÜÃÞßà áâãäåæçèéêëìÃîïðñòóôõöøùúûüýþÿĀÄĂ㥹ĆćĈĉĊċČÄÄŽ +ÄÄđĒēĔĕĖėĘęĚěĜÄÄžÄŸÄ Ä¡Ä¢Ä£Ä¤Ä¥Ä¦Ä§Ä¨Ä©ÄªÄ«Ä¬ÄĮįİıIJijĴĵĶķĸĹĺĻļĽľĿŀÅłŃńŅņŇňʼnŊŋŌÅÅŽÅÅ +őŒœŔŕŖŗŘřŚśŜÅŞşŠšŢţŤťŦŧŨũŪūŬÅŮůŰűŲųŴŵŶŷŸŹźŻżŽžſƀÆƂƃƄƅƆƇƈƉƊƋƌÆÆŽÆÆÆ‘Æ’ +ƓƔƕƖƗƘƙƚƛƜÆÆžÆŸÆ Æ¡Æ¢Æ£Æ¤Æ¥Æ¦Æ§Æ¨Æ©ÆªÆ«Æ¬ÆƮƯưƱƲƳƴƵƶƷƸƹƺƼƽƾƿDŽdžLJljNJnjÇÇŽÇÇǑǒǓǔǕǖǗǘǙǚǛǜ +ÇÇžÇŸÇ Ç¡Ç¢Ç£Ç¤Ç¥Ç¦Ç§Ç¨Ç©ÇªÇ«Ç¬ÇǮǯǰDZdzǴǵǶǷǸǹǺǻǼǽǾǿȀÈȂȃȄȅȆȇȈȉȊȋȌÈÈŽÈÈȑȒȓȔȕȖȗȘșȚțȜÈȞȟ +È È¡È¢È£È¤È¥È¦È§È¨È©ÈªÈ«È¬ÈȮȯȰȱȲȳȴȵȶȷȸȹȺȻȼȽȾȿɀÉÉɑɒɓɔɕɖɗɘəɚɛɜÉÉžÉŸÉ É¡É¢É£É¤É¥É¦É§É¨É©ÉªÉ«É¬Éɮɯ +ɰɱɲɳɴɵɶɷɸɹɺɻɼɽɾɿʀÊʂʃʄʅʆʇʈʉʊʋʌÊÊŽÊÊʑʒʓʔʕʖʗʘʙʚʛʜÊÊžÊŸÊ Ê¡Ê¢Ê£Ê¤Ê¥Ê¦Ê§Ê¨Ê©ÊªÊ«Ê¬ÊʮʯΆΈ +ΉΊΌΎÎÎΑΒΓΔΕΖΗΘΙΚΛΜÎΞΟΠΡΣΤΥΦΧΨΩΪΫάÎήίΰαβγδεζηθικλμνξοπÏÏ‚ÏƒÏ„Ï…Ï†Ï‡ÏˆÏ‰ÏŠÏ‹ÏŒÏ +ÏŽÏϑϒϓϔϕϖϗϘϙϚϛϜÏÏžÏŸÏ Ï¡Ï¢Ï£Ï¤Ï¥Ï¦Ï§Ï¨Ï©ÏªÏ«Ï¬ÏϮϯϰϱϲϳϴϵϷϸϹϺϻϼϽϾϿЀÐЂЃЄЅІЇЈЉЊЋЌÐÐŽÐÐБ +ВГДЕЖЗИЙКЛМÐОПРСТУФХЦЧШЩЪЫЬÐЮЯабвгдежзийклмнопрÑтуфхцчшщъыьÑÑŽÑÑÑ‘Ñ’Ñ“ +єѕіїјљњћќÑÑžÑŸÑ Ñ¡Ñ¢Ñ£Ñ¤Ñ¥Ñ¦Ñ§Ñ¨Ñ©ÑªÑ«Ñ¬ÑѮѯѰѱѲѳѴѵѶѷѸѹѺѻѼѽѾѿҀÒÒŠÒ‹ÒŒÒÒŽÒÒÒ‘Ò’Ò“Ò”Ò•Ò–Ò—Ò˜Ò™ÒšÒ›ÒœÒ +ÒžÒŸÒ Ò¡Ò¢Ò£Ò¤Ò¥Ò¦Ò§Ò¨Ò©ÒªÒ«Ò¬ÒÒ®Ò¯Ò°Ò±Ò²Ò³Ò´ÒµÒ¶Ò·Ò¸Ò¹ÒºÒ»Ò¼Ò½Ò¾Ò¿Ó€ÓÓ‚ÓƒÓ„Ó…Ó†Ó‡ÓˆÓ‰ÓŠÓ‹ÓŒÓÓŽÓÓ‘Ó’Ó“Ó”Ó•Ó–Ó—Ó˜Ó™ÓšÓ›ÓœÓÓžÓŸÓ +Ó¡Ó¢Ó£Ó¤Ó¥Ó¦Ó§Ó¨Ó©ÓªÓ«Ó¬ÓÓ®Ó¯Ó°Ó±Ó²Ó³Ó´ÓµÓ¶Ó·Ó¸Ó¹Ô€ÔÔ‚ÔƒÔ„Ô…Ô†Ô‡ÔˆÔ‰ÔŠÔ‹ÔŒÔÔŽÔÔ±Ô²Ô³Ô´ÔµÔ¶Ô·Ô¸Ô¹ÔºÔ»Ô¼Ô½Ô¾Ô¿Õ€ÕÕ‚ÕƒÕ„Õ…Õ†Õ‡ÕˆÕ‰ +ÕŠÕ‹ÕŒÕÕŽÕÕÕ‘Õ’Õ“Õ”Õ•Õ–Õ¡Õ¢Õ£Õ¤Õ¥Õ¦Õ§Õ¨Õ©ÕªÕ«Õ¬ÕÕ®Õ¯Õ°Õ±Õ²Õ³Õ´ÕµÕ¶Õ·Õ¸Õ¹ÕºÕ»Õ¼Õ½Õ¾Õ¿Ö€ÖւփքօֆևႠႡႢႣႤႥႦႧႨႩႪႫႬႠ+ႮႯႰႱႲႳႴႵႶႷႸႹႺႻႼႽႾႿჀáƒáƒ‚ჃჄჅᴀá´á´‚ᴃᴄᴅᴆᴇᴈᴉᴊᴋᴌá´á´Žá´á´á´‘ᴒᴓᴔᴕᴖᴗᴘᴙᴚᴛᴜá´á´žá´Ÿá´ ᴡᴢᴣᴤᴥᴦᴧᴨᴩ +ᴪᴫᵢᵣᵤᵥᵦᵧᵨᵩᵪᵫᵬáµáµ®áµ¯áµ°áµ±áµ²áµ³áµ´áµµáµ¶áµ·áµ¹áµºáµ»áµ¼áµ½áµ¾áµ¿á¶€á¶á¶‚ᶃᶄᶅᶆᶇᶈᶉᶊᶋᶌá¶á¶Žá¶á¶á¶‘ᶒᶓᶔᶕᶖᶗᶘᶙᶚḀá¸á¸‚ḃḄḅḆḇ +ḈḉḊḋḌá¸á¸Žá¸á¸á¸‘ḒḓḔḕḖḗḘḙḚḛḜá¸á¸žá¸Ÿá¸ ḡḢḣḤḥḦḧḨḩḪḫḬá¸á¸®á¸¯á¸°á¸±á¸²á¸³á¸´á¸µá¸¶á¸·á¸¸á¸¹á¸ºá¸»á¸¼á¸½á¸¾á¸¿á¹€á¹á¹‚ṃṄṅṆṇṈṉ +ṊṋṌá¹á¹Žá¹á¹á¹‘ṒṓṔṕṖṗṘṙṚṛṜá¹á¹žá¹Ÿá¹ ṡṢṣṤṥṦṧṨṩṪṫṬá¹á¹®á¹¯á¹°á¹±á¹²á¹³á¹´á¹µá¹¶á¹·á¹¸á¹¹á¹ºá¹»á¹¼á¹½á¹¾á¹¿áº€áºáº‚ẃẄẅẆẇẈẉẊẋ +ẌáºáºŽáºáºáº‘ẒẓẔẕẖẗẘẙẚẛẠạẢảẤấẦầẨẩẪẫẬáºáº®áº¯áº°áº±áº²áº³áº´áºµáº¶áº·áº¸áº¹áººáº»áº¼áº½áº¾áº¿á»€á»á»‚ểỄễỆệỈỉỊịỌá»á»Žá»á»á»‘ +ỒồỔổỖỗỘộỚớỜá»á»žá»Ÿá» ỡỢợỤụỦủỨứỪừỬá»á»®á»¯á»°á»±á»²á»³á»´á»µá»¶á»·á»¸á»¹á¼€á¼á¼‚ἃἄἅἆἇἈἉἊἋἌá¼á¼Žá¼á¼á¼‘ἒἓἔἕἘἙἚἛ +Ἔá¼á¼ ἡἢἣἤἥἦἧἨἩἪἫἬá¼á¼®á¼¯á¼°á¼±á¼²á¼³á¼´á¼µá¼¶á¼·á¼¸á¼¹á¼ºá¼»á¼¼á¼½á¼¾á¼¿á½€á½á½‚ὃὄὅὈὉὊὋὌá½á½á½‘ὒὓὔὕὖὗὙὛá½á½Ÿá½ ὡὢὣὤὥὦὧ +ὨὩὪὫὬá½á½®á½¯á½°á½±á½²á½³á½´á½µá½¶á½·á½¸á½¹á½ºá½»á½¼á½½á¾€á¾á¾‚ᾃᾄᾅᾆᾇá¾á¾‘ᾒᾓᾔᾕᾖᾗᾠᾡᾢᾣᾤᾥᾦᾧᾰᾱᾲᾳᾴᾶᾷᾸᾹᾺΆιῂῃῄῆῇῈΈῊ +á¿‹á¿á¿‘ῒΐῖῗῘῙῚΊῠῡῢΰῤῥῦῧῨῩῪΎῬῲῳῴῶῷῸΌῺΏâ±â¿â„‚ℇℊℋℌâ„â„Žâ„â„ℑℒℓℕℙℚℛℜâ„ℤΩℨKÅℬâ„ℯℰℱℳℴℹ +ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzªµºÀÃÂÃÄÅÆÇÈÉÊ +ËÌÃÃŽÃÃÑÒÓÔÕÖØÙÚÛÜÃÞßà áâãäåæçèéêëìÃîïðñòóôõöøùúûüýþÿĀÄĂ㥹ĆćĈĉĊċČÄÄŽ +ÄÄđĒēĔĕĖėĘęĚěĜÄÄžÄŸÄ Ä¡Ä¢Ä£Ä¤Ä¥Ä¦Ä§Ä¨Ä©ÄªÄ«Ä¬ÄĮįİıIJijĴĵĶķĸĹĺĻļĽľĿŀÅłŃńŅņŇňʼnŊŋŌÅÅŽÅÅ +őŒœŔŕŖŗŘřŚśŜÅŞşŠšŢţŤťŦŧŨũŪūŬÅŮůŰűŲųŴŵŶŷŸŹźŻżŽžſƀÆƂƃƄƅƆƇƈƉƊƋƌÆÆŽÆÆÆ‘Æ’ +ƓƔƕƖƗƘƙƚƛƜÆÆžÆŸÆ Æ¡Æ¢Æ£Æ¤Æ¥Æ¦Æ§Æ¨Æ©ÆªÆ«Æ¬ÆƮƯưƱƲƳƴƵƶƷƸƹƺƼƽƾƿDŽdžLJljNJnjÇÇŽÇÇǑǒǓǔǕǖǗǘǙǚǛǜ +ÇÇžÇŸÇ Ç¡Ç¢Ç£Ç¤Ç¥Ç¦Ç§Ç¨Ç©ÇªÇ«Ç¬ÇǮǯǰDZdzǴǵǶǷǸǹǺǻǼǽǾǿȀÈȂȃȄȅȆȇȈȉȊȋȌÈÈŽÈÈȑȒȓȔȕȖȗȘșȚțȜÈȞȟ +È È¡È¢È£È¤È¥È¦È§È¨È©ÈªÈ«È¬ÈȮȯȰȱȲȳȴȵȶȷȸȹȺȻȼȽȾȿɀÉÉɑɒɓɔɕɖɗɘəɚɛɜÉÉžÉŸÉ É¡É¢É£É¤É¥É¦É§É¨É©ÉªÉ«É¬Éɮɯ +ɰɱɲɳɴɵɶɷɸɹɺɻɼɽɾɿʀÊʂʃʄʅʆʇʈʉʊʋʌÊÊŽÊÊʑʒʓʔʕʖʗʘʙʚʛʜÊÊžÊŸÊ Ê¡Ê¢Ê£Ê¤Ê¥Ê¦Ê§Ê¨Ê©ÊªÊ«Ê¬ÊʮʯΆΈ +ΉΊΌΎÎÎΑΒΓΔΕΖΗΘΙΚΛΜÎΞΟΠΡΣΤΥΦΧΨΩΪΫάÎήίΰαβγδεζηθικλμνξοπÏÏ‚ÏƒÏ„Ï…Ï†Ï‡ÏˆÏ‰ÏŠÏ‹ÏŒÏ +ÏŽÏϑϒϓϔϕϖϗϘϙϚϛϜÏÏžÏŸÏ Ï¡Ï¢Ï£Ï¤Ï¥Ï¦Ï§Ï¨Ï©ÏªÏ«Ï¬ÏϮϯϰϱϲϳϴϵϷϸϹϺϻϼϽϾϿЀÐЂЃЄЅІЇЈЉЊЋЌÐÐŽÐÐБ +ВГДЕЖЗИЙКЛМÐОПРСТУФХЦЧШЩЪЫЬÐЮЯабвгдежзийклмнопрÑтуфхцчшщъыьÑÑŽÑÑÑ‘Ñ’Ñ“ +єѕіїјљњћќÑÑžÑŸÑ Ñ¡Ñ¢Ñ£Ñ¤Ñ¥Ñ¦Ñ§Ñ¨Ñ©ÑªÑ«Ñ¬ÑѮѯѰѱѲѳѴѵѶѷѸѹѺѻѼѽѾѿҀÒÒŠÒ‹ÒŒÒÒŽÒÒÒ‘Ò’Ò“Ò”Ò•Ò–Ò—Ò˜Ò™ÒšÒ›ÒœÒ +ÒžÒŸÒ Ò¡Ò¢Ò£Ò¤Ò¥Ò¦Ò§Ò¨Ò©ÒªÒ«Ò¬ÒÒ®Ò¯Ò°Ò±Ò²Ò³Ò´ÒµÒ¶Ò·Ò¸Ò¹ÒºÒ»Ò¼Ò½Ò¾Ò¿Ó€ÓÓ‚ÓƒÓ„Ó…Ó†Ó‡ÓˆÓ‰ÓŠÓ‹ÓŒÓÓŽÓÓ‘Ó’Ó“Ó”Ó•Ó–Ó—Ó˜Ó™ÓšÓ›ÓœÓÓžÓŸÓ +Ó¡Ó¢Ó£Ó¤Ó¥Ó¦Ó§Ó¨Ó©ÓªÓ«Ó¬ÓÓ®Ó¯Ó°Ó±Ó²Ó³Ó´ÓµÓ¶Ó·Ó¸Ó¹Ô€ÔÔ‚ÔƒÔ„Ô…Ô†Ô‡ÔˆÔ‰ÔŠÔ‹ÔŒÔÔŽÔÔ±Ô²Ô³Ô´ÔµÔ¶Ô·Ô¸Ô¹ÔºÔ»Ô¼Ô½Ô¾Ô¿Õ€ÕÕ‚ÕƒÕ„Õ…Õ†Õ‡ÕˆÕ‰ +ÕŠÕ‹ÕŒÕÕŽÕÕÕ‘Õ’Õ“Õ”Õ•Õ–Õ¡Õ¢Õ£Õ¤Õ¥Õ¦Õ§Õ¨Õ©ÕªÕ«Õ¬ÕÕ®Õ¯Õ°Õ±Õ²Õ³Õ´ÕµÕ¶Õ·Õ¸Õ¹ÕºÕ»Õ¼Õ½Õ¾Õ¿Ö€ÖւփքօֆևႠႡႢႣႤႥႦႧႨႩႪႫႬႠ+ႮႯႰႱႲႳႴႵႶႷႸႹႺႻႼႽႾႿჀáƒáƒ‚ჃჄჅᴀá´á´‚ᴃᴄᴅᴆᴇᴈᴉᴊᴋᴌá´á´Žá´á´á´‘ᴒᴓᴔᴕᴖᴗᴘᴙᴚᴛᴜá´á´žá´Ÿá´ ᴡᴢᴣᴤᴥᴦᴧᴨᴩ +ᴪᴫᵢᵣᵤᵥᵦᵧᵨᵩᵪᵫᵬáµáµ®áµ¯áµ°áµ±áµ²áµ³áµ´áµµáµ¶áµ·áµ¹áµºáµ»áµ¼áµ½áµ¾áµ¿á¶€á¶á¶‚ᶃᶄᶅᶆᶇᶈᶉᶊᶋᶌá¶á¶Žá¶á¶á¶‘ᶒᶓᶔᶕᶖᶗᶘᶙᶚḀá¸á¸‚ḃḄḅḆḇ +ḈḉḊḋḌá¸á¸Žá¸á¸á¸‘ḒḓḔḕḖḗḘḙḚḛḜá¸á¸žá¸Ÿá¸ ḡḢḣḤḥḦḧḨḩḪḫḬá¸á¸®á¸¯á¸°á¸±á¸²á¸³á¸´á¸µá¸¶á¸·á¸¸á¸¹á¸ºá¸»á¸¼á¸½á¸¾á¸¿á¹€á¹á¹‚ṃṄṅṆṇṈṉ +ṊṋṌá¹á¹Žá¹á¹á¹‘ṒṓṔṕṖṗṘṙṚṛṜá¹á¹žá¹Ÿá¹ ṡṢṣṤṥṦṧṨṩṪṫṬá¹á¹®á¹¯á¹°á¹±á¹²á¹³á¹´á¹µá¹¶á¹·á¹¸á¹¹á¹ºá¹»á¹¼á¹½á¹¾á¹¿áº€áºáº‚ẃẄẅẆẇẈẉẊẋ +ẌáºáºŽáºáºáº‘ẒẓẔẕẖẗẘẙẚẛẠạẢảẤấẦầẨẩẪẫẬáºáº®áº¯áº°áº±áº²áº³áº´áºµáº¶áº·áº¸áº¹áººáº»áº¼áº½áº¾áº¿á»€á»á»‚ểỄễỆệỈỉỊịỌá»á»Žá»á»á»‘ +ỒồỔổỖỗỘộỚớỜá»á»žá»Ÿá» ỡỢợỤụỦủỨứỪừỬá»á»®á»¯á»°á»±á»²á»³á»´á»µá»¶á»·á»¸á»¹á¼€á¼á¼‚ἃἄἅἆἇἈἉἊἋἌá¼á¼Žá¼á¼á¼‘ἒἓἔἕἘἙἚἛ +Ἔá¼á¼ ἡἢἣἤἥἦἧἨἩἪἫἬá¼á¼®á¼¯á¼°á¼±á¼²á¼³á¼´á¼µá¼¶á¼·á¼¸á¼¹á¼ºá¼»á¼¼á¼½á¼¾á¼¿á½€á½á½‚ὃὄὅὈὉὊὋὌá½á½á½‘ὒὓὔὕὖὗὙὛá½á½Ÿá½ ὡὢὣὤὥὦὧ +ὨὩὪὫὬá½á½®á½¯á½°á½±á½²á½³á½´á½µá½¶á½·á½¸á½¹á½ºá½»á½¼á½½á¾€á¾á¾‚ᾃᾄᾅᾆᾇá¾á¾‘ᾒᾓᾔᾕᾖᾗᾠᾡᾢᾣᾤᾥᾦᾧᾰᾱᾲᾳᾴᾶᾷᾸᾹᾺΆιῂῃῄῆῇῈΈῊ +á¿‹á¿á¿‘ῒΐῖῗῘῙῚΊῠῡῢΰῤῥῦῧῨῩῪΎῬῲῳῴῶῷῸΌῺΏâ±â¿â„‚ℇℊℋℌâ„â„Žâ„â„ℑℒℓℕℙℚℛℜâ„ℤΩℨKÅℬâ„ℯℰℱℳℴℹ +ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzªµºÀÃÂÃÄÅÆÇÈÉÊ +ËÌÃÃŽÃÃÑÒÓÔÕÖØÙÚÛÜÃÞßà áâãäåæçèéêëìÃîïðñòóôõöøùúûüýþÿĀÄĂ㥹ĆćĈĉĊċČÄÄŽ +ÄÄđĒēĔĕĖėĘęĚěĜÄÄžÄŸÄ Ä¡Ä¢Ä£Ä¤Ä¥Ä¦Ä§Ä¨Ä©ÄªÄ«Ä¬ÄĮįİıIJijĴĵĶķĸĹĺĻļĽľĿŀÅłŃńŅņŇňʼnŊŋŌÅÅŽÅÅ +őŒœŔŕŖŗŘřŚśŜÅŞşŠšŢţŤťŦŧŨũŪūŬÅŮůŰűŲųŴŵŶŷŸŹźŻżŽžſƀÆƂƃƄƅƆƇƈƉƊƋƌÆÆŽÆÆÆ‘Æ’ +ƓƔƕƖƗƘƙƚƛƜÆÆžÆŸÆ Æ¡Æ¢Æ£Æ¤Æ¥Æ¦Æ§Æ¨Æ©ÆªÆ«Æ¬ÆƮƯưƱƲƳƴƵƶƷƸƹƺƼƽƾƿDŽdžLJljNJnjÇÇŽÇÇǑǒǓǔǕǖǗǘǙǚǛǜ +ÇÇžÇŸÇ Ç¡Ç¢Ç£Ç¤Ç¥Ç¦Ç§Ç¨Ç©ÇªÇ«Ç¬ÇǮǯǰDZdzǴǵǶǷǸǹǺǻǼǽǾǿȀÈȂȃȄȅȆȇȈȉȊȋȌÈÈŽÈÈȑȒȓȔȕȖȗȘșȚțȜÈȞȟ +È È¡È¢È£È¤È¥È¦È§È¨È©ÈªÈ«È¬ÈȮȯȰȱȲȳȴȵȶȷȸȹȺȻȼȽȾȿɀÉÉɑɒɓɔɕɖɗɘəɚɛɜÉÉžÉŸÉ É¡É¢É£É¤É¥É¦É§É¨É©ÉªÉ«É¬Éɮɯ +ɰɱɲɳɴɵɶɷɸɹɺɻɼɽɾɿʀÊʂʃʄʅʆʇʈʉʊʋʌÊÊŽÊÊʑʒʓʔʕʖʗʘʙʚʛʜÊÊžÊŸÊ Ê¡Ê¢Ê£Ê¤Ê¥Ê¦Ê§Ê¨Ê©ÊªÊ«Ê¬ÊʮʯΆΈ +ΉΊΌΎÎÎΑΒΓΔΕΖΗΘΙΚΛΜÎΞΟΠΡΣΤΥΦΧΨΩΪΫάÎήίΰαβγδεζηθικλμνξοπÏÏ‚ÏƒÏ„Ï…Ï†Ï‡ÏˆÏ‰ÏŠÏ‹ÏŒÏ +ÏŽÏϑϒϓϔϕϖϗϘϙϚϛϜÏÏžÏŸÏ Ï¡Ï¢Ï£Ï¤Ï¥Ï¦Ï§Ï¨Ï©ÏªÏ«Ï¬ÏϮϯϰϱϲϳϴϵϷϸϹϺϻϼϽϾϿЀÐЂЃЄЅІЇЈЉЊЋЌÐÐŽÐÐБ +ВГДЕЖЗИЙКЛМÐОПРСТУФХЦЧШЩЪЫЬÐЮЯабвгдежзийклмнопрÑтуфхцчшщъыьÑÑŽÑÑÑ‘Ñ’Ñ“ +єѕіїјљњћќÑÑžÑŸÑ Ñ¡Ñ¢Ñ£Ñ¤Ñ¥Ñ¦Ñ§Ñ¨Ñ©ÑªÑ«Ñ¬ÑѮѯѰѱѲѳѴѵѶѷѸѹѺѻѼѽѾѿҀÒÒŠÒ‹ÒŒÒÒŽÒÒÒ‘Ò’Ò“Ò”Ò•Ò–Ò—Ò˜Ò™ÒšÒ›ÒœÒ +ÒžÒŸÒ Ò¡Ò¢Ò£Ò¤Ò¥Ò¦Ò§Ò¨Ò©ÒªÒ«Ò¬ÒÒ®Ò¯Ò°Ò±Ò²Ò³Ò´ÒµÒ¶Ò·Ò¸Ò¹ÒºÒ»Ò¼Ò½Ò¾Ò¿Ó€ÓÓ‚ÓƒÓ„Ó…Ó†Ó‡ÓˆÓ‰ÓŠÓ‹ÓŒÓÓŽÓÓ‘Ó’Ó“Ó”Ó•Ó–Ó—Ó˜Ó™ÓšÓ›ÓœÓÓžÓŸÓ +Ó¡Ó¢Ó£Ó¤Ó¥Ó¦Ó§Ó¨Ó©ÓªÓ«Ó¬ÓÓ®Ó¯Ó°Ó±Ó²Ó³Ó´ÓµÓ¶Ó·Ó¸Ó¹Ô€ÔÔ‚ÔƒÔ„Ô…Ô†Ô‡ÔˆÔ‰ÔŠÔ‹ÔŒÔÔŽÔÔ±Ô²Ô³Ô´ÔµÔ¶Ô·Ô¸Ô¹ÔºÔ»Ô¼Ô½Ô¾Ô¿Õ€ÕÕ‚ÕƒÕ„Õ…Õ†Õ‡ÕˆÕ‰ +ÕŠÕ‹ÕŒÕÕŽÕÕÕ‘Õ’Õ“Õ”Õ•Õ–Õ¡Õ¢Õ£Õ¤Õ¥Õ¦Õ§Õ¨Õ©ÕªÕ«Õ¬ÕÕ®Õ¯Õ°Õ±Õ²Õ³Õ´ÕµÕ¶Õ·Õ¸Õ¹ÕºÕ»Õ¼Õ½Õ¾Õ¿Ö€ÖւփքօֆևႠႡႢႣႤႥႦႧႨႩႪႫႬႠ+ႮႯႰႱႲႳႴႵႶႷႸႹႺႻႼႽႾႿჀáƒáƒ‚ჃჄჅᴀá´á´‚ᴃᴄᴅᴆᴇᴈᴉᴊᴋᴌá´á´Žá´á´á´‘ᴒᴓᴔᴕᴖᴗᴘᴙᴚᴛᴜá´á´žá´Ÿá´ ᴡᴢᴣᴤᴥᴦᴧᴨᴩ +ᴪᴫᵢᵣᵤᵥᵦᵧᵨᵩᵪᵫᵬáµáµ®áµ¯áµ°áµ±áµ²áµ³áµ´áµµáµ¶áµ·áµ¹áµºáµ»áµ¼áµ½áµ¾áµ¿á¶€á¶á¶‚ᶃᶄᶅᶆᶇᶈᶉᶊᶋᶌá¶á¶Žá¶á¶á¶‘ᶒᶓᶔᶕᶖᶗᶘᶙᶚḀá¸á¸‚ḃḄḅḆḇ +ḈḉḊḋḌá¸á¸Žá¸á¸á¸‘ḒḓḔḕḖḗḘḙḚḛḜá¸á¸žá¸Ÿá¸ ḡḢḣḤḥḦḧḨḩḪḫḬá¸á¸®á¸¯á¸°á¸±á¸²á¸³á¸´á¸µá¸¶á¸·á¸¸á¸¹á¸ºá¸»á¸¼á¸½á¸¾á¸¿á¹€á¹á¹‚ṃṄṅṆṇṈṉ +ṊṋṌá¹á¹Žá¹á¹á¹‘ṒṓṔṕṖṗṘṙṚṛṜá¹á¹žá¹Ÿá¹ ṡṢṣṤṥṦṧṨṩṪṫṬá¹á¹®á¹¯á¹°á¹±á¹²á¹³á¹´á¹µá¹¶á¹·á¹¸á¹¹á¹ºá¹»á¹¼á¹½á¹¾á¹¿áº€áºáº‚ẃẄẅẆẇẈẉẊẋ +ẌáºáºŽáºáºáº‘ẒẓẔẕẖẗẘẙẚẛẠạẢảẤấẦầẨẩẪẫẬáºáº®áº¯áº°áº±áº²áº³áº´áºµáº¶áº·áº¸áº¹áººáº»áº¼áº½áº¾áº¿á»€á»á»‚ểỄễỆệỈỉỊịỌá»á»Žá»á»á»‘ +ỒồỔổỖỗỘộỚớỜá»á»žá»Ÿá» ỡỢợỤụỦủỨứỪừỬá»á»®á»¯á»°á»±á»²á»³á»´á»µá»¶á»·á»¸á»¹á¼€á¼á¼‚ἃἄἅἆἇἈἉἊἋἌá¼á¼Žá¼á¼á¼‘ἒἓἔἕἘἙἚἛ +Ἔá¼á¼ ἡἢἣἤἥἦἧἨἩἪἫἬá¼á¼®á¼¯á¼°á¼±á¼²á¼³á¼´á¼µá¼¶á¼·á¼¸á¼¹á¼ºá¼»á¼¼á¼½á¼¾á¼¿á½€á½á½‚ὃὄὅὈὉὊὋὌá½á½á½‘ὒὓὔὕὖὗὙὛá½á½Ÿá½ ὡὢὣὤὥὦὧ +ὨὩὪὫὬá½á½®á½¯á½°á½±á½²á½³á½´á½µá½¶á½·á½¸á½¹á½ºá½»á½¼á½½á¾€á¾á¾‚ᾃᾄᾅᾆᾇá¾á¾‘ᾒᾓᾔᾕᾖᾗᾠᾡᾢᾣᾤᾥᾦᾧᾰᾱᾲᾳᾴᾶᾷᾸᾹᾺΆιῂῃῄῆῇῈΈῊ +á¿‹á¿á¿‘ῒΐῖῗῘῙῚΊῠῡῢΰῤῥῦῧῨῩῪΎῬῲῳῴῶῷῸΌῺΏâ±â¿â„‚ℇℊℋℌâ„â„Žâ„â„ℑℒℓℕℙℚℛℜâ„ℤΩℨKÅℬâ„ℯℰℱℳℴℹ +ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzªµºÀÃÂÃÄÅÆÇÈÉÊ +ËÌÃÃŽÃÃÑÒÓÔÕÖØÙÚÛÜÃÞßà áâãäåæçèéêëìÃîïðñòóôõöøùúûüýþÿĀÄĂ㥹ĆćĈĉĊċČÄÄŽ +ÄÄđĒēĔĕĖėĘęĚěĜÄÄžÄŸÄ Ä¡Ä¢Ä£Ä¤Ä¥Ä¦Ä§Ä¨Ä©ÄªÄ«Ä¬ÄĮįİıIJijĴĵĶķĸĹĺĻļĽľĿŀÅłŃńŅņŇňʼnŊŋŌÅÅŽÅÅ +őŒœŔŕŖŗŘřŚśŜÅŞşŠšŢţŤťŦŧŨũŪūŬÅŮůŰűŲųŴŵŶŷŸŹźŻżŽžſƀÆƂƃƄƅƆƇƈƉƊƋƌÆÆŽÆÆÆ‘Æ’ +ƓƔƕƖƗƘƙƚƛƜÆÆžÆŸÆ Æ¡Æ¢Æ£Æ¤Æ¥Æ¦Æ§Æ¨Æ©ÆªÆ«Æ¬ÆƮƯưƱƲƳƴƵƶƷƸƹƺƼƽƾƿDŽdžLJljNJnjÇÇŽÇÇǑǒǓǔǕǖǗǘǙǚǛǜ +ÇÇžÇŸÇ Ç¡Ç¢Ç£Ç¤Ç¥Ç¦Ç§Ç¨Ç©ÇªÇ«Ç¬ÇǮǯǰDZdzǴǵǶǷǸǹǺǻǼǽǾǿȀÈȂȃȄȅȆȇȈȉȊȋȌÈÈŽÈÈȑȒȓȔȕȖȗȘșȚțȜÈȞȟ +È È¡È¢È£È¤È¥È¦È§È¨È©ÈªÈ«È¬ÈȮȯȰȱȲȳȴȵȶȷȸȹȺȻȼȽȾȿɀÉÉɑɒɓɔɕɖɗɘəɚɛɜÉÉžÉŸÉ É¡É¢É£É¤É¥É¦É§É¨É©ÉªÉ«É¬Éɮɯ +ɰɱɲɳɴɵɶɷɸɹɺɻɼɽɾɿʀÊʂʃʄʅʆʇʈʉʊʋʌÊÊŽÊÊʑʒʓʔʕʖʗʘʙʚʛʜÊÊžÊŸÊ Ê¡Ê¢Ê£Ê¤Ê¥Ê¦Ê§Ê¨Ê©ÊªÊ«Ê¬ÊʮʯΆΈ +ΉΊΌΎÎÎΑΒΓΔΕΖΗΘΙΚΛΜÎΞΟΠΡΣΤΥΦΧΨΩΪΫάÎήίΰαβγδεζηθικλμνξοπÏÏ‚ÏƒÏ„Ï…Ï†Ï‡ÏˆÏ‰ÏŠÏ‹ÏŒÏ +ÏŽÏϑϒϓϔϕϖϗϘϙϚϛϜÏÏžÏŸÏ Ï¡Ï¢Ï£Ï¤Ï¥Ï¦Ï§Ï¨Ï©ÏªÏ«Ï¬ÏϮϯϰϱϲϳϴϵϷϸϹϺϻϼϽϾϿЀÐЂЃЄЅІЇЈЉЊЋЌÐÐŽÐÐБ +ВГДЕЖЗИЙКЛМÐОПРСТУФХЦЧШЩЪЫЬÐЮЯабвгдежзийклмнопрÑтуфхцчшщъыьÑÑŽÑÑÑ‘Ñ’Ñ“ +єѕіїјљњћќÑÑžÑŸÑ Ñ¡Ñ¢Ñ£Ñ¤Ñ¥Ñ¦Ñ§Ñ¨Ñ©ÑªÑ«Ñ¬ÑѮѯѰѱѲѳѴѵѶѷѸѹѺѻѼѽѾѿҀÒÒŠÒ‹ÒŒÒÒŽÒÒÒ‘Ò’Ò“Ò”Ò•Ò–Ò—Ò˜Ò™ÒšÒ›ÒœÒ +ÒžÒŸÒ Ò¡Ò¢Ò£Ò¤Ò¥Ò¦Ò§Ò¨Ò©ÒªÒ«Ò¬ÒÒ®Ò¯Ò°Ò±Ò²Ò³Ò´ÒµÒ¶Ò·Ò¸Ò¹ÒºÒ»Ò¼Ò½Ò¾Ò¿Ó€ÓÓ‚ÓƒÓ„Ó…Ó†Ó‡ÓˆÓ‰ÓŠÓ‹ÓŒÓÓŽÓÓ‘Ó’Ó“Ó”Ó•Ó–Ó—Ó˜Ó™ÓšÓ›ÓœÓÓžÓŸÓ +Ó¡Ó¢Ó£Ó¤Ó¥Ó¦Ó§Ó¨Ó©ÓªÓ«Ó¬ÓÓ®Ó¯Ó°Ó±Ó²Ó³Ó´ÓµÓ¶Ó·Ó¸Ó¹Ô€ÔÔ‚ÔƒÔ„Ô…Ô†Ô‡ÔˆÔ‰ÔŠÔ‹ÔŒÔÔŽÔÔ±Ô²Ô³Ô´ÔµÔ¶Ô·Ô¸Ô¹ÔºÔ»Ô¼Ô½Ô¾Ô¿Õ€ÕÕ‚ÕƒÕ„Õ…Õ†Õ‡ÕˆÕ‰ +ÕŠÕ‹ÕŒÕÕŽÕÕÕ‘Õ’Õ“Õ”Õ•Õ–Õ¡Õ¢Õ£Õ¤Õ¥Õ¦Õ§Õ¨Õ©ÕªÕ«Õ¬ÕÕ®Õ¯Õ°Õ±Õ²Õ³Õ´ÕµÕ¶Õ·Õ¸Õ¹ÕºÕ»Õ¼Õ½Õ¾Õ¿Ö€ÖւփքօֆևႠႡႢႣႤႥႦႧႨႩႪႫႬႠ+ႮႯႰႱႲႳႴႵႶႷႸႹႺႻႼႽႾႿჀáƒáƒ‚ჃჄჅᴀá´á´‚ᴃᴄᴅᴆᴇᴈᴉᴊᴋᴌá´á´Žá´á´á´‘ᴒᴓᴔᴕᴖᴗᴘᴙᴚᴛᴜá´á´žá´Ÿá´ ᴡᴢᴣᴤᴥᴦᴧᴨᴩ +ᴪᴫᵢᵣᵤᵥᵦᵧᵨᵩᵪᵫᵬáµáµ®áµ¯áµ°áµ±áµ²áµ³áµ´áµµáµ¶áµ·áµ¹áµºáµ»áµ¼áµ½áµ¾áµ¿á¶€á¶á¶‚ᶃᶄᶅᶆᶇᶈᶉᶊᶋᶌá¶á¶Žá¶á¶á¶‘ᶒᶓᶔᶕᶖᶗᶘᶙᶚḀá¸á¸‚ḃḄḅḆḇ +ḈḉḊḋḌá¸á¸Žá¸á¸á¸‘ḒḓḔḕḖḗḘḙḚḛḜá¸á¸žá¸Ÿá¸ ḡḢḣḤḥḦḧḨḩḪḫḬá¸á¸®á¸¯á¸°á¸±á¸²á¸³á¸´á¸µá¸¶á¸·á¸¸á¸¹á¸ºá¸»á¸¼á¸½á¸¾á¸¿á¹€á¹á¹‚ṃṄṅṆṇṈṉ +ṊṋṌá¹á¹Žá¹á¹á¹‘ṒṓṔṕṖṗṘṙṚṛṜá¹á¹žá¹Ÿá¹ ṡṢṣṤṥṦṧṨṩṪṫṬá¹á¹®á¹¯á¹°á¹±á¹²á¹³á¹´á¹µá¹¶á¹·á¹¸á¹¹á¹ºá¹»á¹¼á¹½á¹¾á¹¿áº€áºáº‚ẃẄẅẆẇẈẉẊẋ +ẌáºáºŽáºáºáº‘ẒẓẔẕẖẗẘẙẚẛẠạẢảẤấẦầẨẩẪẫẬáºáº®áº¯áº°áº±áº²áº³áº´áºµáº¶áº·áº¸áº¹áººáº»áº¼áº½áº¾áº¿á»€á»á»‚ểỄễỆệỈỉỊịỌá»á»Žá»á»á»‘ +ỒồỔổỖỗỘộỚớỜá»á»žá»Ÿá» ỡỢợỤụỦủỨứỪừỬá»á»®á»¯á»°á»±á»²á»³á»´á»µá»¶á»·á»¸á»¹á¼€á¼á¼‚ἃἄἅἆἇἈἉἊἋἌá¼á¼Žá¼á¼á¼‘ἒἓἔἕἘἙἚἛ +Ἔá¼á¼ ἡἢἣἤἥἦἧἨἩἪἫἬá¼á¼®á¼¯á¼°á¼±á¼²á¼³á¼´á¼µá¼¶á¼·á¼¸á¼¹á¼ºá¼»á¼¼á¼½á¼¾á¼¿á½€á½á½‚ὃὄὅὈὉὊὋὌá½á½á½‘ὒὓὔὕὖὗὙὛá½á½Ÿá½ ὡὢὣὤὥὦὧ +ὨὩὪὫὬá½á½®á½¯á½°á½±á½²á½³á½´á½µá½¶á½·á½¸á½¹á½ºá½»á½¼á½½á¾€á¾á¾‚ᾃᾄᾅᾆᾇá¾á¾‘ᾒᾓᾔᾕᾖᾗᾠᾡᾢᾣᾤᾥᾦᾧᾰᾱᾲᾳᾴᾶᾷᾸᾹᾺΆιῂῃῄῆῇῈΈῊ +á¿‹á¿á¿‘ῒΐῖῗῘῙῚΊῠῡῢΰῤῥῦῧῨῩῪΎῬῲῳῴῶῷῸΌῺΏâ±â¿â„‚ℇℊℋℌâ„â„Žâ„â„ℑℒℓℕℙℚℛℜâ„ℤΩℨKÅℬâ„ℯℰℱℳℴℹ +ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzªµºÀÃÂÃÄÅÆÇÈÉÊ +ËÌÃÃŽÃÃÑÒÓÔÕÖØÙÚÛÜÃÞßà áâãäåæçèéêëìÃîïðñòóôõöøùúûüýþÿĀÄĂ㥹ĆćĈĉĊċČÄÄŽ +ÄÄđĒēĔĕĖėĘęĚěĜÄÄžÄŸÄ Ä¡Ä¢Ä£Ä¤Ä¥Ä¦Ä§Ä¨Ä©ÄªÄ«Ä¬ÄĮįİıIJijĴĵĶķĸĹĺĻļĽľĿŀÅłŃńŅņŇňʼnŊŋŌÅÅŽÅÅ +őŒœŔŕŖŗŘřŚśŜÅŞşŠšŢţŤťŦŧŨũŪūŬÅŮůŰűŲųŴŵŶŷŸŹźŻżŽžſƀÆƂƃƄƅƆƇƈƉƊƋƌÆÆŽÆÆÆ‘Æ’ +ƓƔƕƖƗƘƙƚƛƜÆÆžÆŸÆ Æ¡Æ¢Æ£Æ¤Æ¥Æ¦Æ§Æ¨Æ©ÆªÆ«Æ¬ÆƮƯưƱƲƳƴƵƶƷƸƹƺƼƽƾƿDŽdžLJljNJnjÇÇŽÇÇǑǒǓǔǕǖǗǘǙǚǛǜ +ÇÇžÇŸÇ Ç¡Ç¢Ç£Ç¤Ç¥Ç¦Ç§Ç¨Ç©ÇªÇ«Ç¬ÇǮǯǰDZdzǴǵǶǷǸǹǺǻǼǽǾǿȀÈȂȃȄȅȆȇȈȉȊȋȌÈÈŽÈÈȑȒȓȔȕȖȗȘșȚțȜÈȞȟ +È È¡È¢È£È¤È¥È¦È§È¨È©ÈªÈ«È¬ÈȮȯȰȱȲȳȴȵȶȷȸȹȺȻȼȽȾȿɀÉÉɑɒɓɔɕɖɗɘəɚɛɜÉÉžÉŸÉ É¡É¢É£É¤É¥É¦É§É¨É©ÉªÉ«É¬Éɮɯ +ɰɱɲɳɴɵɶɷɸɹɺɻɼɽɾɿʀÊʂʃʄʅʆʇʈʉʊʋʌÊÊŽÊÊʑʒʓʔʕʖʗʘʙʚʛʜÊÊžÊŸÊ Ê¡Ê¢Ê£Ê¤Ê¥Ê¦Ê§Ê¨Ê©ÊªÊ«Ê¬ÊʮʯΆΈ +ΉΊΌΎÎÎΑΒΓΔΕΖΗΘΙΚΛΜÎΞΟΠΡΣΤΥΦΧΨΩΪΫάÎήίΰαβγδεζηθικλμνξοπÏÏ‚ÏƒÏ„Ï…Ï†Ï‡ÏˆÏ‰ÏŠÏ‹ÏŒÏ +ÏŽÏϑϒϓϔϕϖϗϘϙϚϛϜÏÏžÏŸÏ Ï¡Ï¢Ï£Ï¤Ï¥Ï¦Ï§Ï¨Ï©ÏªÏ«Ï¬ÏϮϯϰϱϲϳϴϵϷϸϹϺϻϼϽϾϿЀÐЂЃЄЅІЇЈЉЊЋЌÐÐŽÐÐБ +ВГДЕЖЗИЙКЛМÐОПРСТУФХЦЧШЩЪЫЬÐЮЯабвгдежзийклмнопрÑтуфхцчшщъыьÑÑŽÑÑÑ‘Ñ’Ñ“ +єѕіїјљњћќÑÑžÑŸÑ Ñ¡Ñ¢Ñ£Ñ¤Ñ¥Ñ¦Ñ§Ñ¨Ñ©ÑªÑ«Ñ¬ÑѮѯѰѱѲѳѴѵѶѷѸѹѺѻѼѽѾѿҀÒÒŠÒ‹ÒŒÒÒŽÒÒÒ‘Ò’Ò“Ò”Ò•Ò–Ò—Ò˜Ò™ÒšÒ›ÒœÒ +ÒžÒŸÒ Ò¡Ò¢Ò£Ò¤Ò¥Ò¦Ò§Ò¨Ò©ÒªÒ«Ò¬ÒÒ®Ò¯Ò°Ò±Ò²Ò³Ò´ÒµÒ¶Ò·Ò¸Ò¹ÒºÒ»Ò¼Ò½Ò¾Ò¿Ó€ÓÓ‚ÓƒÓ„Ó…Ó†Ó‡ÓˆÓ‰ÓŠÓ‹ÓŒÓÓŽÓÓ‘Ó’Ó“Ó”Ó•Ó–Ó—Ó˜Ó™ÓšÓ›ÓœÓÓžÓŸÓ +Ó¡Ó¢Ó£Ó¤Ó¥Ó¦Ó§Ó¨Ó©ÓªÓ«Ó¬ÓÓ®Ó¯Ó°Ó±Ó²Ó³Ó´ÓµÓ¶Ó·Ó¸Ó¹Ô€ÔÔ‚ÔƒÔ„Ô…Ô†Ô‡ÔˆÔ‰ÔŠÔ‹ÔŒÔÔŽÔÔ±Ô²Ô³Ô´ÔµÔ¶Ô·Ô¸Ô¹ÔºÔ»Ô¼Ô½Ô¾Ô¿Õ€ÕÕ‚ÕƒÕ„Õ…Õ†Õ‡ÕˆÕ‰ +ÕŠÕ‹ÕŒÕÕŽÕÕÕ‘Õ’Õ“Õ”Õ•Õ–Õ¡Õ¢Õ£Õ¤Õ¥Õ¦Õ§Õ¨Õ©ÕªÕ«Õ¬ÕÕ®Õ¯Õ°Õ±Õ²Õ³Õ´ÕµÕ¶Õ·Õ¸Õ¹ÕºÕ»Õ¼Õ½Õ¾Õ¿Ö€ÖւփքօֆևႠႡႢႣႤႥႦႧႨႩႪႫႬႠ+ႮႯႰႱႲႳႴႵႶႷႸႹႺႻႼႽႾႿჀáƒáƒ‚ჃჄჅᴀá´á´‚ᴃᴄᴅᴆᴇᴈᴉᴊᴋᴌá´á´Žá´á´á´‘ᴒᴓᴔᴕᴖᴗᴘᴙᴚᴛᴜá´á´žá´Ÿá´ ᴡᴢᴣᴤᴥᴦᴧᴨᴩ +ᴪᴫᵢᵣᵤᵥᵦᵧᵨᵩᵪᵫᵬáµáµ®áµ¯áµ°áµ±áµ²áµ³áµ´áµµáµ¶áµ·áµ¹áµºáµ»áµ¼áµ½áµ¾áµ¿á¶€á¶á¶‚ᶃᶄᶅᶆᶇᶈᶉᶊᶋᶌá¶á¶Žá¶á¶á¶‘ᶒᶓᶔᶕᶖᶗᶘᶙᶚḀá¸á¸‚ḃḄḅḆḇ +ḈḉḊḋḌá¸á¸Žá¸á¸á¸‘ḒḓḔḕḖḗḘḙḚḛḜá¸á¸žá¸Ÿá¸ ḡḢḣḤḥḦḧḨḩḪḫḬá¸á¸®á¸¯á¸°á¸±á¸²á¸³á¸´á¸µá¸¶á¸·á¸¸á¸¹á¸ºá¸»á¸¼á¸½á¸¾á¸¿á¹€á¹á¹‚ṃṄṅṆṇṈṉ +ṊṋṌá¹á¹Žá¹á¹á¹‘ṒṓṔṕṖṗṘṙṚṛṜá¹á¹žá¹Ÿá¹ ṡṢṣṤṥṦṧṨṩṪṫṬá¹á¹®á¹¯á¹°á¹±á¹²á¹³á¹´á¹µá¹¶á¹·á¹¸á¹¹á¹ºá¹»á¹¼á¹½á¹¾á¹¿áº€áºáº‚ẃẄẅẆẇẈẉẊẋ +ẌáºáºŽáºáºáº‘ẒẓẔẕẖẗẘẙẚẛẠạẢảẤấẦầẨẩẪẫẬáºáº®áº¯áº°áº±áº²áº³áº´áºµáº¶áº·áº¸áº¹áººáº»áº¼áº½áº¾áº¿á»€á»á»‚ểỄễỆệỈỉỊịỌá»á»Žá»á»á»‘ +ỒồỔổỖỗỘộỚớỜá»á»žá»Ÿá» ỡỢợỤụỦủỨứỪừỬá»á»®á»¯á»°á»±á»²á»³á»´á»µá»¶á»·á»¸á»¹á¼€á¼á¼‚ἃἄἅἆἇἈἉἊἋἌá¼á¼Žá¼á¼á¼‘ἒἓἔἕἘἙἚἛ +Ἔá¼á¼ ἡἢἣἤἥἦἧἨἩἪἫἬá¼á¼®á¼¯á¼°á¼±á¼²á¼³á¼´á¼µá¼¶á¼·á¼¸á¼¹á¼ºá¼»á¼¼á¼½á¼¾á¼¿á½€á½á½‚ὃὄὅὈὉὊὋὌá½á½á½‘ὒὓὔὕὖὗὙὛá½á½Ÿá½ ὡὢὣὤὥὦὧ +ὨὩὪὫὬá½á½®á½¯á½°á½±á½²á½³á½´á½µá½¶á½·á½¸á½¹á½ºá½»á½¼á½½á¾€á¾á¾‚ᾃᾄᾅᾆᾇá¾á¾‘ᾒᾓᾔᾕᾖᾗᾠᾡᾢᾣᾤᾥᾦᾧᾰᾱᾲᾳᾴᾶᾷᾸᾹᾺΆιῂῃῄῆῇῈΈῊ +á¿‹á¿á¿‘ῒΐῖῗῘῙῚΊῠῡῢΰῤῥῦῧῨῩῪΎῬῲῳῴῶῷῸΌῺΏâ±â¿â„‚ℇℊℋℌâ„â„Žâ„â„ℑℒℓℕℙℚℛℜâ„ℤΩℨKÅℬâ„ℯℰℱℳℴℹ +ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzªµºÀÃÂÃÄÅÆÇÈÉÊ +ËÌÃÃŽÃÃÑÒÓÔÕÖØÙÚÛÜÃÞßà áâãäåæçèéêëìÃîïðñòóôõöøùúûüýþÿĀÄĂ㥹ĆćĈĉĊċČÄÄŽ +ÄÄđĒēĔĕĖėĘęĚěĜÄÄžÄŸÄ Ä¡Ä¢Ä£Ä¤Ä¥Ä¦Ä§Ä¨Ä©ÄªÄ«Ä¬ÄĮįİıIJijĴĵĶķĸĹĺĻļĽľĿŀÅłŃńŅņŇňʼnŊŋŌÅÅŽÅÅ +őŒœŔŕŖŗŘřŚśŜÅŞşŠšŢţŤťŦŧŨũŪūŬÅŮůŰűŲųŴŵŶŷŸŹźŻżŽžſƀÆƂƃƄƅƆƇƈƉƊƋƌÆÆŽÆÆÆ‘Æ’ +ƓƔƕƖƗƘƙƚƛƜÆÆžÆŸÆ Æ¡Æ¢Æ£Æ¤Æ¥Æ¦Æ§Æ¨Æ©ÆªÆ«Æ¬ÆƮƯưƱƲƳƴƵƶƷƸƹƺƼƽƾƿDŽdžLJljNJnjÇÇŽÇÇǑǒǓǔǕǖǗǘǙǚǛǜ +ÇÇžÇŸÇ Ç¡Ç¢Ç£Ç¤Ç¥Ç¦Ç§Ç¨Ç©ÇªÇ«Ç¬ÇǮǯǰDZdzǴǵǶǷǸǹǺǻǼǽǾǿȀÈȂȃȄȅȆȇȈȉȊȋȌÈÈŽÈÈȑȒȓȔȕȖȗȘșȚțȜÈȞȟ +È È¡È¢È£È¤È¥È¦È§È¨È©ÈªÈ«È¬ÈȮȯȰȱȲȳȴȵȶȷȸȹȺȻȼȽȾȿɀÉÉɑɒɓɔɕɖɗɘəɚɛɜÉÉžÉŸÉ É¡É¢É£É¤É¥É¦É§É¨É©ÉªÉ«É¬Éɮɯ +ɰɱɲɳɴɵɶɷɸɹɺɻɼɽɾɿʀÊʂʃʄʅʆʇʈʉʊʋʌÊÊŽÊÊʑʒʓʔʕʖʗʘʙʚʛʜÊÊžÊŸÊ Ê¡Ê¢Ê£Ê¤Ê¥Ê¦Ê§Ê¨Ê©ÊªÊ«Ê¬ÊʮʯΆΈ +ΉΊΌΎÎÎΑΒΓΔΕΖΗΘΙΚΛΜÎΞΟΠΡΣΤΥΦΧΨΩΪΫάÎήίΰαβγδεζηθικλμνξοπÏÏ‚ÏƒÏ„Ï…Ï†Ï‡ÏˆÏ‰ÏŠÏ‹ÏŒÏ +ÏŽÏϑϒϓϔϕϖϗϘϙϚϛϜÏÏžÏŸÏ Ï¡Ï¢Ï£Ï¤Ï¥Ï¦Ï§Ï¨Ï©ÏªÏ«Ï¬ÏϮϯϰϱϲϳϴϵϷϸϹϺϻϼϽϾϿЀÐЂЃЄЅІЇЈЉЊЋЌÐÐŽÐÐБ +ВГДЕЖЗИЙКЛМÐОПРСТУФХЦЧШЩЪЫЬÐЮЯабвгдежзийклмнопрÑтуфхцчшщъыьÑÑŽÑÑÑ‘Ñ’Ñ“ +єѕіїјљњћќÑÑžÑŸÑ Ñ¡Ñ¢Ñ£Ñ¤Ñ¥Ñ¦Ñ§Ñ¨Ñ©ÑªÑ«Ñ¬ÑѮѯѰѱѲѳѴѵѶѷѸѹѺѻѼѽѾѿҀÒÒŠÒ‹ÒŒÒÒŽÒÒÒ‘Ò’Ò“Ò”Ò•Ò–Ò—Ò˜Ò™ÒšÒ›ÒœÒ +ÒžÒŸÒ Ò¡Ò¢Ò£Ò¤Ò¥Ò¦Ò§Ò¨Ò©ÒªÒ«Ò¬ÒÒ®Ò¯Ò°Ò±Ò²Ò³Ò´ÒµÒ¶Ò·Ò¸Ò¹ÒºÒ»Ò¼Ò½Ò¾Ò¿Ó€ÓÓ‚ÓƒÓ„Ó…Ó†Ó‡ÓˆÓ‰ÓŠÓ‹ÓŒÓÓŽÓÓ‘Ó’Ó“Ó”Ó•Ó–Ó—Ó˜Ó™ÓšÓ›ÓœÓÓžÓŸÓ +Ó¡Ó¢Ó£Ó¤Ó¥Ó¦Ó§Ó¨Ó©ÓªÓ«Ó¬ÓÓ®Ó¯Ó°Ó±Ó²Ó³Ó´ÓµÓ¶Ó·Ó¸Ó¹Ô€ÔÔ‚ÔƒÔ„Ô…Ô†Ô‡ÔˆÔ‰ÔŠÔ‹ÔŒÔÔŽÔÔ±Ô²Ô³Ô´ÔµÔ¶Ô·Ô¸Ô¹ÔºÔ»Ô¼Ô½Ô¾Ô¿Õ€ÕÕ‚ÕƒÕ„Õ…Õ†Õ‡ÕˆÕ‰ +ÕŠÕ‹ÕŒÕÕŽÕÕÕ‘Õ’Õ“Õ”Õ•Õ–Õ¡Õ¢Õ£Õ¤Õ¥Õ¦Õ§Õ¨Õ©ÕªÕ«Õ¬ÕÕ®Õ¯Õ°Õ±Õ²Õ³Õ´ÕµÕ¶Õ·Õ¸Õ¹ÕºÕ»Õ¼Õ½Õ¾Õ¿Ö€ÖւփքօֆևႠႡႢႣႤႥႦႧႨႩႪႫႬႠ+ႮႯႰႱႲႳႴႵႶႷႸႹႺႻႼႽႾႿჀáƒáƒ‚ჃჄჅᴀá´á´‚ᴃᴄᴅᴆᴇᴈᴉᴊᴋᴌá´á´Žá´á´á´‘ᴒᴓᴔᴕᴖᴗᴘᴙᴚᴛᴜá´á´žá´Ÿá´ ᴡᴢᴣᴤᴥᴦᴧᴨᴩ +ᴪᴫᵢᵣᵤᵥᵦᵧᵨᵩᵪᵫᵬáµáµ®áµ¯áµ°áµ±áµ²áµ³áµ´áµµáµ¶áµ·áµ¹áµºáµ»áµ¼áµ½áµ¾áµ¿á¶€á¶á¶‚ᶃᶄᶅᶆᶇᶈᶉᶊᶋᶌá¶á¶Žá¶á¶á¶‘ᶒᶓᶔᶕᶖᶗᶘᶙᶚḀá¸á¸‚ḃḄḅḆḇ +ḈḉḊḋḌá¸á¸Žá¸á¸á¸‘ḒḓḔḕḖḗḘḙḚḛḜá¸á¸žá¸Ÿá¸ ḡḢḣḤḥḦḧḨḩḪḫḬá¸á¸®á¸¯á¸°á¸±á¸²á¸³á¸´á¸µá¸¶á¸·á¸¸á¸¹á¸ºá¸»á¸¼á¸½á¸¾á¸¿á¹€á¹á¹‚ṃṄṅṆṇṈṉ +ṊṋṌá¹á¹Žá¹á¹á¹‘ṒṓṔṕṖṗṘṙṚṛṜá¹á¹žá¹Ÿá¹ ṡṢṣṤṥṦṧṨṩṪṫṬá¹á¹®á¹¯á¹°á¹±á¹²á¹³á¹´á¹µá¹¶á¹·á¹¸á¹¹á¹ºá¹»á¹¼á¹½á¹¾á¹¿áº€áºáº‚ẃẄẅẆẇẈẉẊẋ +ẌáºáºŽáºáºáº‘ẒẓẔẕẖẗẘẙẚẛẠạẢảẤấẦầẨẩẪẫẬáºáº®áº¯áº°áº±áº²áº³áº´áºµáº¶áº·áº¸áº¹áººáº»áº¼áº½áº¾áº¿á»€á»á»‚ểỄễỆệỈỉỊịỌá»á»Žá»á»á»‘ +ỒồỔổỖỗỘộỚớỜá»á»žá»Ÿá» ỡỢợỤụỦủỨứỪừỬá»á»®á»¯á»°á»±á»²á»³á»´á»µá»¶á»·á»¸á»¹á¼€á¼á¼‚ἃἄἅἆἇἈἉἊἋἌá¼á¼Žá¼á¼á¼‘ἒἓἔἕἘἙἚἛ +Ἔá¼á¼ ἡἢἣἤἥἦἧἨἩἪἫἬá¼á¼®á¼¯á¼°á¼±á¼²á¼³á¼´á¼µá¼¶á¼·á¼¸á¼¹á¼ºá¼»á¼¼á¼½á¼¾á¼¿á½€á½á½‚ὃὄὅὈὉὊὋὌá½á½á½‘ὒὓὔὕὖὗὙὛá½á½Ÿá½ ὡὢὣὤὥὦὧ +ὨὩὪὫὬá½á½®á½¯á½°á½±á½²á½³á½´á½µá½¶á½·á½¸á½¹á½ºá½»á½¼á½½á¾€á¾á¾‚ᾃᾄᾅᾆᾇá¾á¾‘ᾒᾓᾔᾕᾖᾗᾠᾡᾢᾣᾤᾥᾦᾧᾰᾱᾲᾳᾴᾶᾷᾸᾹᾺΆιῂῃῄῆῇῈΈῊ +á¿‹á¿á¿‘ῒΐῖῗῘῙῚΊῠῡῢΰῤῥῦῧῨῩῪΎῬῲῳῴῶῷῸΌῺΏâ±â¿â„‚ℇℊℋℌâ„â„Žâ„â„ℑℒℓℕℙℚℛℜâ„ℤΩℨKÅℬâ„ℯℰℱℳℴℹ +ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzªµºÀÃÂÃÄÅÆÇÈÉÊ +ËÌÃÃŽÃÃÑÒÓÔÕÖØÙÚÛÜÃÞßà áâãäåæçèéêëìÃîïðñòóôõöøùúûüýþÿĀÄĂ㥹ĆćĈĉĊċČÄÄŽ +ÄÄđĒēĔĕĖėĘęĚěĜÄÄžÄŸÄ Ä¡Ä¢Ä£Ä¤Ä¥Ä¦Ä§Ä¨Ä©ÄªÄ«Ä¬ÄĮįİıIJijĴĵĶķĸĹĺĻļĽľĿŀÅłŃńŅņŇňʼnŊŋŌÅÅŽÅÅ +őŒœŔŕŖŗŘřŚśŜÅŞşŠšŢţŤťŦŧŨũŪūŬÅŮůŰűŲųŴŵŶŷŸŹźŻżŽžſƀÆƂƃƄƅƆƇƈƉƊƋƌÆÆŽÆÆÆ‘Æ’ +ƓƔƕƖƗƘƙƚƛƜÆÆžÆŸÆ Æ¡Æ¢Æ£Æ¤Æ¥Æ¦Æ§Æ¨Æ©ÆªÆ«Æ¬ÆƮƯưƱƲƳƴƵƶƷƸƹƺƼƽƾƿDŽdžLJljNJnjÇÇŽÇÇǑǒǓǔǕǖǗǘǙǚǛǜ +ÇÇžÇŸÇ Ç¡Ç¢Ç£Ç¤Ç¥Ç¦Ç§Ç¨Ç©ÇªÇ«Ç¬ÇǮǯǰDZdzǴǵǶǷǸǹǺǻǼǽǾǿȀÈȂȃȄȅȆȇȈȉȊȋȌÈÈŽÈÈȑȒȓȔȕȖȗȘșȚțȜÈȞȟ +È È¡È¢È£È¤È¥È¦È§È¨È©ÈªÈ«È¬ÈȮȯȰȱȲȳȴȵȶȷȸȹȺȻȼȽȾȿɀÉÉɑɒɓɔɕɖɗɘəɚɛɜÉÉžÉŸÉ É¡É¢É£É¤É¥É¦É§É¨É©ÉªÉ«É¬Éɮɯ +ɰɱɲɳɴɵɶɷɸɹɺɻɼɽɾɿʀÊʂʃʄʅʆʇʈʉʊʋʌÊÊŽÊÊʑʒʓʔʕʖʗʘʙʚʛʜÊÊžÊŸÊ Ê¡Ê¢Ê£Ê¤Ê¥Ê¦Ê§Ê¨Ê©ÊªÊ«Ê¬ÊʮʯΆΈ +ΉΊΌΎÎÎΑΒΓΔΕΖΗΘΙΚΛΜÎΞΟΠΡΣΤΥΦΧΨΩΪΫάÎήίΰαβγδεζηθικλμνξοπÏÏ‚ÏƒÏ„Ï…Ï†Ï‡ÏˆÏ‰ÏŠÏ‹ÏŒÏ +ÏŽÏϑϒϓϔϕϖϗϘϙϚϛϜÏÏžÏŸÏ Ï¡Ï¢Ï£Ï¤Ï¥Ï¦Ï§Ï¨Ï©ÏªÏ«Ï¬ÏϮϯϰϱϲϳϴϵϷϸϹϺϻϼϽϾϿЀÐЂЃЄЅІЇЈЉЊЋЌÐÐŽÐÐБ +ВГДЕЖЗИЙКЛМÐОПРСТУФХЦЧШЩЪЫЬÐЮЯабвгдежзийклмнопрÑтуфхцчшщъыьÑÑŽÑÑÑ‘Ñ’Ñ“ +єѕіїјљњћќÑÑžÑŸÑ Ñ¡Ñ¢Ñ£Ñ¤Ñ¥Ñ¦Ñ§Ñ¨Ñ©ÑªÑ«Ñ¬ÑѮѯѰѱѲѳѴѵѶѷѸѹѺѻѼѽѾѿҀÒÒŠÒ‹ÒŒÒÒŽÒÒÒ‘Ò’Ò“Ò”Ò•Ò–Ò—Ò˜Ò™ÒšÒ›ÒœÒ +ÒžÒŸÒ Ò¡Ò¢Ò£Ò¤Ò¥Ò¦Ò§Ò¨Ò©ÒªÒ«Ò¬ÒÒ®Ò¯Ò°Ò±Ò²Ò³Ò´ÒµÒ¶Ò·Ò¸Ò¹ÒºÒ»Ò¼Ò½Ò¾Ò¿Ó€ÓÓ‚ÓƒÓ„Ó…Ó†Ó‡ÓˆÓ‰ÓŠÓ‹ÓŒÓÓŽÓÓ‘Ó’Ó“Ó”Ó•Ó–Ó—Ó˜Ó™ÓšÓ›ÓœÓÓžÓŸÓ +Ó¡Ó¢Ó£Ó¤Ó¥Ó¦Ó§Ó¨Ó©ÓªÓ«Ó¬ÓÓ®Ó¯Ó°Ó±Ó²Ó³Ó´ÓµÓ¶Ó·Ó¸Ó¹Ô€ÔÔ‚ÔƒÔ„Ô…Ô†Ô‡ÔˆÔ‰ÔŠÔ‹ÔŒÔÔŽÔÔ±Ô²Ô³Ô´ÔµÔ¶Ô·Ô¸Ô¹ÔºÔ»Ô¼Ô½Ô¾Ô¿Õ€ÕÕ‚ÕƒÕ„Õ…Õ†Õ‡ÕˆÕ‰ +ÕŠÕ‹ÕŒÕÕŽÕÕÕ‘Õ’Õ“Õ”Õ•Õ–Õ¡Õ¢Õ£Õ¤Õ¥Õ¦Õ§Õ¨Õ©ÕªÕ«Õ¬ÕÕ®Õ¯Õ°Õ±Õ²Õ³Õ´ÕµÕ¶Õ·Õ¸Õ¹ÕºÕ»Õ¼Õ½Õ¾Õ¿Ö€ÖւփքօֆևႠႡႢႣႤႥႦႧႨႩႪႫႬႠ+ႮႯႰႱႲႳႴႵႶႷႸႹႺႻႼႽႾႿჀáƒáƒ‚ჃჄჅᴀá´á´‚ᴃᴄᴅᴆᴇᴈᴉᴊᴋᴌá´á´Žá´á´á´‘ᴒᴓᴔᴕᴖᴗᴘᴙᴚᴛᴜá´á´žá´Ÿá´ ᴡᴢᴣᴤᴥᴦᴧᴨᴩ +ᴪᴫᵢᵣᵤᵥᵦᵧᵨᵩᵪᵫᵬáµáµ®áµ¯áµ°áµ±áµ²áµ³áµ´áµµáµ¶áµ·áµ¹áµºáµ»áµ¼áµ½áµ¾áµ¿á¶€á¶á¶‚ᶃᶄᶅᶆᶇᶈᶉᶊᶋᶌá¶á¶Žá¶á¶á¶‘ᶒᶓᶔᶕᶖᶗᶘᶙᶚḀá¸á¸‚ḃḄḅḆḇ +ḈḉḊḋḌá¸á¸Žá¸á¸á¸‘ḒḓḔḕḖḗḘḙḚḛḜá¸á¸žá¸Ÿá¸ ḡḢḣḤḥḦḧḨḩḪḫḬá¸á¸®á¸¯á¸°á¸±á¸²á¸³á¸´á¸µá¸¶á¸·á¸¸á¸¹á¸ºá¸»á¸¼á¸½á¸¾á¸¿á¹€á¹á¹‚ṃṄṅṆṇṈṉ +ṊṋṌá¹á¹Žá¹á¹á¹‘ṒṓṔṕṖṗṘṙṚṛṜá¹á¹žá¹Ÿá¹ ṡṢṣṤṥṦṧṨṩṪṫṬá¹á¹®á¹¯á¹°á¹±á¹²á¹³á¹´á¹µá¹¶á¹·á¹¸á¹¹á¹ºá¹»á¹¼á¹½á¹¾á¹¿áº€áºáº‚ẃẄẅẆẇẈẉẊẋ +ẌáºáºŽáºáºáº‘ẒẓẔẕẖẗẘẙẚẛẠạẢảẤấẦầẨẩẪẫẬáºáº®áº¯áº°áº±áº²áº³áº´áºµáº¶áº·áº¸áº¹áººáº»áº¼áº½áº¾áº¿á»€á»á»‚ểỄễỆệỈỉỊịỌá»á»Žá»á»á»‘ +ỒồỔổỖỗỘộỚớỜá»á»žá»Ÿá» ỡỢợỤụỦủỨứỪừỬá»á»®á»¯á»°á»±á»²á»³á»´á»µá»¶á»·á»¸á»¹á¼€á¼á¼‚ἃἄἅἆἇἈἉἊἋἌá¼á¼Žá¼á¼á¼‘ἒἓἔἕἘἙἚἛ +Ἔá¼á¼ ἡἢἣἤἥἦἧἨἩἪἫἬá¼á¼®á¼¯á¼°á¼±á¼²á¼³á¼´á¼µá¼¶á¼·á¼¸á¼¹á¼ºá¼»á¼¼á¼½á¼¾á¼¿á½€á½á½‚ὃὄὅὈὉὊὋὌá½á½á½‘ὒὓὔὕὖὗὙὛá½á½Ÿá½ ὡὢὣὤὥὦὧ +ὨὩὪὫὬá½á½®á½¯á½°á½±á½²á½³á½´á½µá½¶á½·á½¸á½¹á½ºá½»á½¼á½½á¾€á¾á¾‚ᾃᾄᾅᾆᾇá¾á¾‘ᾒᾓᾔᾕᾖᾗᾠᾡᾢᾣᾤᾥᾦᾧᾰᾱᾲᾳᾴᾶᾷᾸᾹᾺΆιῂῃῄῆῇῈΈῊ +á¿‹á¿á¿‘ῒΐῖῗῘῙῚΊῠῡῢΰῤῥῦῧῨῩῪΎῬῲῳῴῶῷῸΌῺΏâ±â¿â„‚ℇℊℋℌâ„â„Žâ„â„ℑℒℓℕℙℚℛℜâ„ℤΩℨKÅℬâ„ℯℰℱℳℴℹ +ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzªµºÀÃÂÃÄÅÆÇÈÉÊ +ËÌÃÃŽÃÃÑÒÓÔÕÖØÙÚÛÜÃÞßà áâãäåæçèéêëìÃîïðñòóôõöøùúûüýþÿĀÄĂ㥹ĆćĈĉĊċČÄÄŽ +ÄÄđĒēĔĕĖėĘęĚěĜÄÄžÄŸÄ Ä¡Ä¢Ä£Ä¤Ä¥Ä¦Ä§Ä¨Ä©ÄªÄ«Ä¬ÄĮįİıIJijĴĵĶķĸĹĺĻļĽľĿŀÅłŃńŅņŇňʼnŊŋŌÅÅŽÅÅ +őŒœŔŕŖŗŘřŚśŜÅŞşŠšŢţŤťŦŧŨũŪūŬÅŮůŰűŲųŴŵŶŷŸŹźŻżŽžſƀÆƂƃƄƅƆƇƈƉƊƋƌÆÆŽÆÆÆ‘Æ’ +ƓƔƕƖƗƘƙƚƛƜÆÆžÆŸÆ Æ¡Æ¢Æ£Æ¤Æ¥Æ¦Æ§Æ¨Æ©ÆªÆ«Æ¬ÆƮƯưƱƲƳƴƵƶƷƸƹƺƼƽƾƿDŽdžLJljNJnjÇÇŽÇÇǑǒǓǔǕǖǗǘǙǚǛǜ +ÇÇžÇŸÇ Ç¡Ç¢Ç£Ç¤Ç¥Ç¦Ç§Ç¨Ç©ÇªÇ«Ç¬ÇǮǯǰDZdzǴǵǶǷǸǹǺǻǼǽǾǿȀÈȂȃȄȅȆȇȈȉȊȋȌÈÈŽÈÈȑȒȓȔȕȖȗȘșȚțȜÈȞȟ +È È¡È¢È£È¤È¥È¦È§È¨È©ÈªÈ«È¬ÈȮȯȰȱȲȳȴȵȶȷȸȹȺȻȼȽȾȿɀÉÉɑɒɓɔɕɖɗɘəɚɛɜÉÉžÉŸÉ É¡É¢É£É¤É¥É¦É§É¨É©ÉªÉ«É¬Éɮɯ +ɰɱɲɳɴɵɶɷɸɹɺɻɼɽɾɿʀÊʂʃʄʅʆʇʈʉʊʋʌÊÊŽÊÊʑʒʓʔʕʖʗʘʙʚʛʜÊÊžÊŸÊ Ê¡Ê¢Ê£Ê¤Ê¥Ê¦Ê§Ê¨Ê©ÊªÊ«Ê¬ÊʮʯΆΈ +ΉΊΌΎÎÎΑΒΓΔΕΖΗΘΙΚΛΜÎΞΟΠΡΣΤΥΦΧΨΩΪΫάÎήίΰαβγδεζηθικλμνξοπÏÏ‚ÏƒÏ„Ï…Ï†Ï‡ÏˆÏ‰ÏŠÏ‹ÏŒÏ +ÏŽÏϑϒϓϔϕϖϗϘϙϚϛϜÏÏžÏŸÏ Ï¡Ï¢Ï£Ï¤Ï¥Ï¦Ï§Ï¨Ï©ÏªÏ«Ï¬ÏϮϯϰϱϲϳϴϵϷϸϹϺϻϼϽϾϿЀÐЂЃЄЅІЇЈЉЊЋЌÐÐŽÐÐБ +ВГДЕЖЗИЙКЛМÐОПРСТУФХЦЧШЩЪЫЬÐЮЯабвгдежзийклмнопрÑтуфхцчшщъыьÑÑŽÑÑÑ‘Ñ’Ñ“ +єѕіїјљњћќÑÑžÑŸÑ Ñ¡Ñ¢Ñ£Ñ¤Ñ¥Ñ¦Ñ§Ñ¨Ñ©ÑªÑ«Ñ¬ÑѮѯѰѱѲѳѴѵѶѷѸѹѺѻѼѽѾѿҀÒÒŠÒ‹ÒŒÒÒŽÒÒÒ‘Ò’Ò“Ò”Ò•Ò–Ò—Ò˜Ò™ÒšÒ›ÒœÒ +ÒžÒŸÒ Ò¡Ò¢Ò£Ò¤Ò¥Ò¦Ò§Ò¨Ò©ÒªÒ«Ò¬ÒÒ®Ò¯Ò°Ò±Ò²Ò³Ò´ÒµÒ¶Ò·Ò¸Ò¹ÒºÒ»Ò¼Ò½Ò¾Ò¿Ó€ÓÓ‚ÓƒÓ„Ó…Ó†Ó‡ÓˆÓ‰ÓŠÓ‹ÓŒÓÓŽÓÓ‘Ó’Ó“Ó”Ó•Ó–Ó—Ó˜Ó™ÓšÓ›ÓœÓÓžÓŸÓ +Ó¡Ó¢Ó£Ó¤Ó¥Ó¦Ó§Ó¨Ó©ÓªÓ«Ó¬ÓÓ®Ó¯Ó°Ó±Ó²Ó³Ó´ÓµÓ¶Ó·Ó¸Ó¹Ô€ÔÔ‚ÔƒÔ„Ô…Ô†Ô‡ÔˆÔ‰ÔŠÔ‹ÔŒÔÔŽÔÔ±Ô²Ô³Ô´ÔµÔ¶Ô·Ô¸Ô¹ÔºÔ»Ô¼Ô½Ô¾Ô¿Õ€ÕÕ‚ÕƒÕ„Õ…Õ†Õ‡ÕˆÕ‰ +ÕŠÕ‹ÕŒÕÕŽÕÕÕ‘Õ’Õ“Õ”Õ•Õ–Õ¡Õ¢Õ£Õ¤Õ¥Õ¦Õ§Õ¨Õ©ÕªÕ«Õ¬ÕÕ®Õ¯Õ°Õ±Õ²Õ³Õ´ÕµÕ¶Õ·Õ¸Õ¹ÕºÕ»Õ¼Õ½Õ¾Õ¿Ö€ÖւփքօֆևႠႡႢႣႤႥႦႧႨႩႪႫႬႠ+ႮႯႰႱႲႳႴႵႶႷႸႹႺႻႼႽႾႿჀáƒáƒ‚ჃჄჅᴀá´á´‚ᴃᴄᴅᴆᴇᴈᴉᴊᴋᴌá´á´Žá´á´á´‘ᴒᴓᴔᴕᴖᴗᴘᴙᴚᴛᴜá´á´žá´Ÿá´ ᴡᴢᴣᴤᴥᴦᴧᴨᴩ +ᴪᴫᵢᵣᵤᵥᵦᵧᵨᵩᵪᵫᵬáµáµ®áµ¯áµ°áµ±áµ²áµ³áµ´áµµáµ¶áµ·áµ¹áµºáµ»áµ¼áµ½áµ¾áµ¿á¶€á¶á¶‚ᶃᶄᶅᶆᶇᶈᶉᶊᶋᶌá¶á¶Žá¶á¶á¶‘ᶒᶓᶔᶕᶖᶗᶘᶙᶚḀá¸á¸‚ḃḄḅḆḇ +ḈḉḊḋḌá¸á¸Žá¸á¸á¸‘ḒḓḔḕḖḗḘḙḚḛḜá¸á¸žá¸Ÿá¸ ḡḢḣḤḥḦḧḨḩḪḫḬá¸á¸®á¸¯á¸°á¸±á¸²á¸³á¸´á¸µá¸¶á¸·á¸¸á¸¹á¸ºá¸»á¸¼á¸½á¸¾á¸¿á¹€á¹á¹‚ṃṄṅṆṇṈṉ +ṊṋṌá¹á¹Žá¹á¹á¹‘ṒṓṔṕṖṗṘṙṚṛṜá¹á¹žá¹Ÿá¹ ṡṢṣṤṥṦṧṨṩṪṫṬá¹á¹®á¹¯á¹°á¹±á¹²á¹³á¹´á¹µá¹¶á¹·á¹¸á¹¹á¹ºá¹»á¹¼á¹½á¹¾á¹¿áº€áºáº‚ẃẄẅẆẇẈẉẊẋ +ẌáºáºŽáºáºáº‘ẒẓẔẕẖẗẘẙẚẛẠạẢảẤấẦầẨẩẪẫẬáºáº®áº¯áº°áº±áº²áº³áº´áºµáº¶áº·áº¸áº¹áººáº»áº¼áº½áº¾áº¿á»€á»á»‚ểỄễỆệỈỉỊịỌá»á»Žá»á»á»‘ +ỒồỔổỖỗỘộỚớỜá»á»žá»Ÿá» ỡỢợỤụỦủỨứỪừỬá»á»®á»¯á»°á»±á»²á»³á»´á»µá»¶á»·á»¸á»¹á¼€á¼á¼‚ἃἄἅἆἇἈἉἊἋἌá¼á¼Žá¼á¼á¼‘ἒἓἔἕἘἙἚἛ +Ἔá¼á¼ ἡἢἣἤἥἦἧἨἩἪἫἬá¼á¼®á¼¯á¼°á¼±á¼²á¼³á¼´á¼µá¼¶á¼·á¼¸á¼¹á¼ºá¼»á¼¼á¼½á¼¾á¼¿á½€á½á½‚ὃὄὅὈὉὊὋὌá½á½á½‘ὒὓὔὕὖὗὙὛá½á½Ÿá½ ὡὢὣὤὥὦὧ +ὨὩὪὫὬá½á½®á½¯á½°á½±á½²á½³á½´á½µá½¶á½·á½¸á½¹á½ºá½»á½¼á½½á¾€á¾á¾‚ᾃᾄᾅᾆᾇá¾á¾‘ᾒᾓᾔᾕᾖᾗᾠᾡᾢᾣᾤᾥᾦᾧᾰᾱᾲᾳᾴᾶᾷᾸᾹᾺΆιῂῃῄῆῇῈΈῊ +á¿‹á¿á¿‘ῒΐῖῗῘῙῚΊῠῡῢΰῤῥῦῧῨῩῪΎῬῲῳῴῶῷῸΌῺΏâ±â¿â„‚ℇℊℋℌâ„â„Žâ„â„ℑℒℓℕℙℚℛℜâ„ℤΩℨKÅℬâ„ℯℰℱℳℴℹ diff --git a/_test/data/mappings.events b/_test/data/mappings.events new file mode 100644 index 0000000..3cb5579 --- /dev/null +++ b/_test/data/mappings.events @@ -0,0 +1,44 @@ +- !StreamStart + +- !DocumentStart +- !MappingStart +- !Scalar { implicit: [true,true], value: 'key' } +- !Scalar { implicit: [true,true], value: 'value' } +- !Scalar { implicit: [true,true], value: 'empty mapping' } +- !MappingStart +- !MappingEnd +- !Scalar { implicit: [true,true], value: 'empty mapping with tag' } +- !MappingStart { tag: '!mytag', implicit: false } +- !MappingEnd +- !Scalar { implicit: [true,true], value: 'block mapping' } +- !MappingStart +- !MappingStart +- !Scalar { implicit: [true,true], value: 'complex' } +- !Scalar { implicit: [true,true], value: 'key' } +- !Scalar { implicit: [true,true], value: 'complex' } +- !Scalar { implicit: [true,true], value: 'key' } +- !MappingEnd +- !MappingStart +- !Scalar { implicit: [true,true], value: 'complex' } +- !Scalar { implicit: [true,true], value: 'key' } +- !MappingEnd +- !MappingEnd +- !Scalar { implicit: [true,true], value: 'flow mapping' } +- !MappingStart { flow_style: true } +- !Scalar { implicit: [true,true], value: 'key' } +- !Scalar { implicit: [true,true], value: 'value' } +- !MappingStart +- !Scalar { implicit: [true,true], value: 'complex' } +- !Scalar { implicit: [true,true], value: 'key' } +- !Scalar { implicit: [true,true], value: 'complex' } +- !Scalar { implicit: [true,true], value: 'key' } +- !MappingEnd +- !MappingStart +- !Scalar { implicit: [true,true], value: 'complex' } +- !Scalar { implicit: [true,true], value: 'key' } +- !MappingEnd +- !MappingEnd +- !MappingEnd +- !DocumentEnd + +- !StreamEnd diff --git a/_test/data/merge.data b/_test/data/merge.data new file mode 100644 index 0000000..e455bbc --- /dev/null +++ b/_test/data/merge.data @@ -0,0 +1 @@ +- << diff --git a/_test/data/merge.detect b/_test/data/merge.detect new file mode 100644 index 0000000..1672d0d --- /dev/null +++ b/_test/data/merge.detect @@ -0,0 +1 @@ +tag:yaml.org,2002:merge diff --git a/_test/data/more-floats.code b/_test/data/more-floats.code new file mode 100644 index 0000000..e3e444e --- /dev/null +++ b/_test/data/more-floats.code @@ -0,0 +1 @@ +[0.0, +1.0, -1.0, +1e300000, -1e300000, 1e300000/1e300000, -(1e300000/1e300000)] # last two items are ind and qnan respectively. diff --git a/_test/data/more-floats.data b/_test/data/more-floats.data new file mode 100644 index 0000000..399eb17 --- /dev/null +++ b/_test/data/more-floats.data @@ -0,0 +1 @@ +[0.0, +1.0, -1.0, +.inf, -.inf, .nan, .nan] diff --git a/_test/data/negative-float-bug.code b/_test/data/negative-float-bug.code new file mode 100644 index 0000000..18e16e3 --- /dev/null +++ b/_test/data/negative-float-bug.code @@ -0,0 +1 @@ +-1.0 diff --git a/_test/data/negative-float-bug.data b/_test/data/negative-float-bug.data new file mode 100644 index 0000000..18e16e3 --- /dev/null +++ b/_test/data/negative-float-bug.data @@ -0,0 +1 @@ +-1.0 diff --git a/_test/data/no-alias-anchor.emitter-error b/_test/data/no-alias-anchor.emitter-error new file mode 100644 index 0000000..5ff065c --- /dev/null +++ b/_test/data/no-alias-anchor.emitter-error @@ -0,0 +1,8 @@ +- !StreamStart +- !DocumentStart +- !SequenceStart +- !Scalar { anchor: A, value: data } +- !Alias { } +- !SequenceEnd +- !DocumentEnd +- !StreamEnd diff --git a/_test/data/no-alias-anchor.skip-ext b/_test/data/no-alias-anchor.skip-ext new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/_test/data/no-alias-anchor.skip-ext diff --git a/_test/data/no-block-collection-end.loader-error b/_test/data/no-block-collection-end.loader-error new file mode 100644 index 0000000..02d4d37 --- /dev/null +++ b/_test/data/no-block-collection-end.loader-error @@ -0,0 +1,3 @@ +- foo +- bar +baz: bar diff --git a/_test/data/no-block-mapping-end-2.loader-error b/_test/data/no-block-mapping-end-2.loader-error new file mode 100644 index 0000000..be63571 --- /dev/null +++ b/_test/data/no-block-mapping-end-2.loader-error @@ -0,0 +1,3 @@ +? foo +: bar +: baz diff --git a/_test/data/no-block-mapping-end.loader-error b/_test/data/no-block-mapping-end.loader-error new file mode 100644 index 0000000..1ea921c --- /dev/null +++ b/_test/data/no-block-mapping-end.loader-error @@ -0,0 +1 @@ +foo: "bar" "baz" diff --git a/_test/data/no-document-start.loader-error b/_test/data/no-document-start.loader-error new file mode 100644 index 0000000..c725ec8 --- /dev/null +++ b/_test/data/no-document-start.loader-error @@ -0,0 +1,3 @@ +%YAML 1.1 +# no --- +foo: bar diff --git a/_test/data/no-flow-mapping-end.loader-error b/_test/data/no-flow-mapping-end.loader-error new file mode 100644 index 0000000..8bd1403 --- /dev/null +++ b/_test/data/no-flow-mapping-end.loader-error @@ -0,0 +1 @@ +{ foo: bar ] diff --git a/_test/data/no-flow-sequence-end.loader-error b/_test/data/no-flow-sequence-end.loader-error new file mode 100644 index 0000000..750d973 --- /dev/null +++ b/_test/data/no-flow-sequence-end.loader-error @@ -0,0 +1 @@ +[foo, bar} diff --git a/_test/data/no-node-1.loader-error b/_test/data/no-node-1.loader-error new file mode 100644 index 0000000..07b1500 --- /dev/null +++ b/_test/data/no-node-1.loader-error @@ -0,0 +1 @@ +- !foo ] diff --git a/_test/data/no-node-2.loader-error b/_test/data/no-node-2.loader-error new file mode 100644 index 0000000..563e3b3 --- /dev/null +++ b/_test/data/no-node-2.loader-error @@ -0,0 +1 @@ +- [ !foo } ] diff --git a/_test/data/no-tag.emitter-error b/_test/data/no-tag.emitter-error new file mode 100644 index 0000000..384c62f --- /dev/null +++ b/_test/data/no-tag.emitter-error @@ -0,0 +1,5 @@ +- !StreamStart +- !DocumentStart +- !Scalar { value: 'foo', implicit: [false,false] } +- !DocumentEnd +- !StreamEnd diff --git a/_test/data/null.data b/_test/data/null.data new file mode 100644 index 0000000..ad12528 --- /dev/null +++ b/_test/data/null.data @@ -0,0 +1,3 @@ +- +- ~ +- null diff --git a/_test/data/null.detect b/_test/data/null.detect new file mode 100644 index 0000000..19110c7 --- /dev/null +++ b/_test/data/null.detect @@ -0,0 +1 @@ +tag:yaml.org,2002:null diff --git a/_test/data/odd-utf16.stream-error b/_test/data/odd-utf16.stream-error Binary files differnew file mode 100644 index 0000000..b59e434 --- /dev/null +++ b/_test/data/odd-utf16.stream-error diff --git a/_test/data/omap.data b/_test/data/omap.data new file mode 100644 index 0000000..b366fbc --- /dev/null +++ b/_test/data/omap.data @@ -0,0 +1,8 @@ +Bestiary: !!omap +- aardvark: African pig-like ant eater. Ugly. +- anteater: South-American ant eater. Two species. +- anaconda: South-American constrictor snake. Scaly. +Numbers: !!omap +- one: 1 +- two: 2 +- three: 3 diff --git a/_test/data/omap.roundtrip b/_test/data/omap.roundtrip new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/_test/data/omap.roundtrip diff --git a/_test/data/recursive-anchor.former-loader-error b/_test/data/recursive-anchor.former-loader-error new file mode 100644 index 0000000..661166c --- /dev/null +++ b/_test/data/recursive-anchor.former-loader-error @@ -0,0 +1,4 @@ +- &foo [1 + 2, + 3, + *foo] diff --git a/_test/data/recursive-dict.recursive b/_test/data/recursive-dict.recursive new file mode 100644 index 0000000..8f326f5 --- /dev/null +++ b/_test/data/recursive-dict.recursive @@ -0,0 +1,3 @@ +value = {} +instance = AnInstance(value, value) +value[instance] = instance diff --git a/_test/data/recursive-list.recursive b/_test/data/recursive-list.recursive new file mode 100644 index 0000000..27a4ae5 --- /dev/null +++ b/_test/data/recursive-list.recursive @@ -0,0 +1,2 @@ +value = [] +value.append(value) diff --git a/_test/data/recursive-set.recursive b/_test/data/recursive-set.recursive new file mode 100644 index 0000000..457c50d --- /dev/null +++ b/_test/data/recursive-set.recursive @@ -0,0 +1,7 @@ +try: + set +except NameError: + from sets import Set as set +value = set() +value.add(AnInstance(foo=value, bar=value)) +value.add(AnInstance(foo=value, bar=value)) diff --git a/_test/data/recursive-state.recursive b/_test/data/recursive-state.recursive new file mode 100644 index 0000000..bffe61e --- /dev/null +++ b/_test/data/recursive-state.recursive @@ -0,0 +1,2 @@ +value = [] +value.append(AnInstanceWithState(value, value)) diff --git a/_test/data/recursive-tuple.recursive b/_test/data/recursive-tuple.recursive new file mode 100644 index 0000000..dc08d02 --- /dev/null +++ b/_test/data/recursive-tuple.recursive @@ -0,0 +1,3 @@ +value = ([], []) +value[0].append(value) +value[1].append(value[0]) diff --git a/_test/data/recursive.former-dumper-error b/_test/data/recursive.former-dumper-error new file mode 100644 index 0000000..3c7cc2f --- /dev/null +++ b/_test/data/recursive.former-dumper-error @@ -0,0 +1,3 @@ +data = [] +data.append(data) +dump(data) diff --git a/_test/data/remove-possible-simple-key-bug.loader-error b/_test/data/remove-possible-simple-key-bug.loader-error new file mode 100644 index 0000000..fe1bc6c --- /dev/null +++ b/_test/data/remove-possible-simple-key-bug.loader-error @@ -0,0 +1,3 @@ +foo: &A bar +*A ] # The ']' indicator triggers remove_possible_simple_key, + # which should raise an error. diff --git a/_test/data/resolver.data b/_test/data/resolver.data new file mode 100644 index 0000000..a296404 --- /dev/null +++ b/_test/data/resolver.data @@ -0,0 +1,30 @@ +--- +"this scalar should be selected" +--- +key11: !foo + key12: + is: [selected] + key22: + key13: [not, selected] + key23: [not, selected] + key32: + key31: [not, selected] + key32: [not, selected] + key33: {not: selected} +key21: !bar + - not selected + - selected + - not selected +key31: !baz + key12: + key13: + key14: {selected} + key23: + key14: [not, selected] + key33: + key14: {selected} + key24: {not: selected} + key22: + - key14: {selected} + key24: {not: selected} + - key14: {selected} diff --git a/_test/data/resolver.path b/_test/data/resolver.path new file mode 100644 index 0000000..ec677d2 --- /dev/null +++ b/_test/data/resolver.path @@ -0,0 +1,30 @@ +--- !root/scalar +"this scalar should be selected" +--- !root +key11: !foo + key12: !root/key11/key12/* + is: [selected] + key22: + key13: [not, selected] + key23: [not, selected] + key32: + key31: [not, selected] + key32: [not, selected] + key33: {not: selected} +key21: !bar + - not selected + - !root/key21/1/* selected + - not selected +key31: !baz + key12: + key13: + key14: !root/key31/*/*/key14/map {selected} + key23: + key14: [not, selected] + key33: + key14: !root/key31/*/*/key14/map {selected} + key24: {not: selected} + key22: + - key14: !root/key31/*/*/key14/map {selected} + key24: {not: selected} + - key14: !root/key31/*/*/key14/map {selected} diff --git a/_test/data/run-parser-crash-bug.data b/_test/data/run-parser-crash-bug.data new file mode 100644 index 0000000..fe01734 --- /dev/null +++ b/_test/data/run-parser-crash-bug.data @@ -0,0 +1,8 @@ +--- +- Harry Potter and the Prisoner of Azkaban +- Harry Potter and the Goblet of Fire +- Harry Potter and the Order of the Phoenix +--- +- Memoirs Found in a Bathtub +- Snow Crash +- Ghost World diff --git a/_test/data/scalars.events b/_test/data/scalars.events new file mode 100644 index 0000000..32c40f4 --- /dev/null +++ b/_test/data/scalars.events @@ -0,0 +1,28 @@ +- !StreamStart + +- !DocumentStart +- !MappingStart +- !Scalar { implicit: [true,true], value: 'empty scalar' } +- !Scalar { implicit: [true,false], value: '' } +- !Scalar { implicit: [true,true], value: 'implicit scalar' } +- !Scalar { implicit: [true,true], value: 'data' } +- !Scalar { implicit: [true,true], value: 'quoted scalar' } +- !Scalar { value: 'data', style: '"' } +- !Scalar { implicit: [true,true], value: 'block scalar' } +- !Scalar { value: 'data', style: '|' } +- !Scalar { implicit: [true,true], value: 'empty scalar with tag' } +- !Scalar { implicit: [false,false], tag: '!mytag', value: '' } +- !Scalar { implicit: [true,true], value: 'implicit scalar with tag' } +- !Scalar { implicit: [false,false], tag: '!mytag', value: 'data' } +- !Scalar { implicit: [true,true], value: 'quoted scalar with tag' } +- !Scalar { value: 'data', style: '"', tag: '!mytag', implicit: [false,false] } +- !Scalar { implicit: [true,true], value: 'block scalar with tag' } +- !Scalar { value: 'data', style: '|', tag: '!mytag', implicit: [false,false] } +- !Scalar { implicit: [true,true], value: 'single character' } +- !Scalar { value: 'a', implicit: [true,true] } +- !Scalar { implicit: [true,true], value: 'single digit' } +- !Scalar { value: '1', implicit: [true,false] } +- !MappingEnd +- !DocumentEnd + +- !StreamEnd diff --git a/_test/data/scan-document-end-bug.canonical b/_test/data/scan-document-end-bug.canonical new file mode 100644 index 0000000..4a0e8a8 --- /dev/null +++ b/_test/data/scan-document-end-bug.canonical @@ -0,0 +1,3 @@ +%YAML 1.1 +--- +!!null "" diff --git a/_test/data/scan-document-end-bug.data b/_test/data/scan-document-end-bug.data new file mode 100644 index 0000000..3c70543 --- /dev/null +++ b/_test/data/scan-document-end-bug.data @@ -0,0 +1,3 @@ +# Ticket #4 +--- +...
\ No newline at end of file diff --git a/_test/data/scan-line-break-bug.canonical b/_test/data/scan-line-break-bug.canonical new file mode 100644 index 0000000..79f08b7 --- /dev/null +++ b/_test/data/scan-line-break-bug.canonical @@ -0,0 +1,3 @@ +%YAML 1.1 +--- +!!map { ? !!str "foo" : !!str "bar baz" } diff --git a/_test/data/scan-line-break-bug.data b/_test/data/scan-line-break-bug.data new file mode 100644 index 0000000..c974fab --- /dev/null +++ b/_test/data/scan-line-break-bug.data @@ -0,0 +1,3 @@ +foo:
+ bar
+ baz
diff --git a/_test/data/sequences.events b/_test/data/sequences.events new file mode 100644 index 0000000..692a329 --- /dev/null +++ b/_test/data/sequences.events @@ -0,0 +1,81 @@ +- !StreamStart + +- !DocumentStart +- !SequenceStart +- !SequenceEnd +- !DocumentEnd + +- !DocumentStart +- !SequenceStart { tag: '!mytag', implicit: false } +- !SequenceEnd +- !DocumentEnd + +- !DocumentStart +- !SequenceStart +- !SequenceStart +- !SequenceEnd +- !SequenceStart { tag: '!mytag', implicit: false } +- !SequenceEnd +- !SequenceStart +- !Scalar +- !Scalar { value: 'data' } +- !Scalar { tag: '!mytag', implicit: [false,false], value: 'data' } +- !SequenceEnd +- !SequenceStart +- !SequenceStart +- !SequenceStart +- !Scalar +- !SequenceEnd +- !SequenceEnd +- !SequenceEnd +- !SequenceStart +- !SequenceStart { tag: '!mytag', implicit: false } +- !SequenceStart +- !Scalar { value: 'data' } +- !SequenceEnd +- !SequenceEnd +- !SequenceEnd +- !SequenceEnd +- !DocumentEnd + +- !DocumentStart +- !SequenceStart +- !MappingStart +- !Scalar { value: 'key1' } +- !SequenceStart +- !Scalar { value: 'data1' } +- !Scalar { value: 'data2' } +- !SequenceEnd +- !Scalar { value: 'key2' } +- !SequenceStart { tag: '!mytag1', implicit: false } +- !Scalar { value: 'data3' } +- !SequenceStart +- !Scalar { value: 'data4' } +- !Scalar { value: 'data5' } +- !SequenceEnd +- !SequenceStart { tag: '!mytag2', implicit: false } +- !Scalar { value: 'data6' } +- !Scalar { value: 'data7' } +- !SequenceEnd +- !SequenceEnd +- !MappingEnd +- !SequenceEnd +- !DocumentEnd + +- !DocumentStart +- !SequenceStart +- !SequenceStart { flow_style: true } +- !SequenceStart +- !SequenceEnd +- !Scalar +- !Scalar { value: 'data' } +- !Scalar { tag: '!mytag', implicit: [false,false], value: 'data' } +- !SequenceStart { tag: '!mytag', implicit: false } +- !Scalar { value: 'data' } +- !Scalar { value: 'data' } +- !SequenceEnd +- !SequenceEnd +- !SequenceEnd +- !DocumentEnd + +- !StreamEnd diff --git a/_test/data/serializer-is-already-opened.dumper-error b/_test/data/serializer-is-already-opened.dumper-error new file mode 100644 index 0000000..9a23525 --- /dev/null +++ b/_test/data/serializer-is-already-opened.dumper-error @@ -0,0 +1,3 @@ +dumper = yaml.Dumper(StringIO()) +dumper.open() +dumper.open() diff --git a/_test/data/serializer-is-closed-1.dumper-error b/_test/data/serializer-is-closed-1.dumper-error new file mode 100644 index 0000000..8e7e600 --- /dev/null +++ b/_test/data/serializer-is-closed-1.dumper-error @@ -0,0 +1,4 @@ +dumper = yaml.Dumper(StringIO()) +dumper.open() +dumper.close() +dumper.open() diff --git a/_test/data/serializer-is-closed-2.dumper-error b/_test/data/serializer-is-closed-2.dumper-error new file mode 100644 index 0000000..89aef7e --- /dev/null +++ b/_test/data/serializer-is-closed-2.dumper-error @@ -0,0 +1,4 @@ +dumper = yaml.Dumper(StringIO()) +dumper.open() +dumper.close() +dumper.serialize(yaml.ScalarNode(tag='!foo', value='bar')) diff --git a/_test/data/serializer-is-not-opened-1.dumper-error b/_test/data/serializer-is-not-opened-1.dumper-error new file mode 100644 index 0000000..8f22e73 --- /dev/null +++ b/_test/data/serializer-is-not-opened-1.dumper-error @@ -0,0 +1,2 @@ +dumper = yaml.Dumper(StringIO()) +dumper.close() diff --git a/_test/data/serializer-is-not-opened-2.dumper-error b/_test/data/serializer-is-not-opened-2.dumper-error new file mode 100644 index 0000000..ebd9df1 --- /dev/null +++ b/_test/data/serializer-is-not-opened-2.dumper-error @@ -0,0 +1,2 @@ +dumper = yaml.Dumper(StringIO()) +dumper.serialize(yaml.ScalarNode(tag='!foo', value='bar')) diff --git a/_test/data/single-dot-is-not-float-bug.code b/_test/data/single-dot-is-not-float-bug.code new file mode 100644 index 0000000..dcd0c2f --- /dev/null +++ b/_test/data/single-dot-is-not-float-bug.code @@ -0,0 +1 @@ +'.' diff --git a/_test/data/single-dot-is-not-float-bug.data b/_test/data/single-dot-is-not-float-bug.data new file mode 100644 index 0000000..9c558e3 --- /dev/null +++ b/_test/data/single-dot-is-not-float-bug.data @@ -0,0 +1 @@ +. diff --git a/_test/data/sloppy-indentation.canonical b/_test/data/sloppy-indentation.canonical new file mode 100644 index 0000000..438bc04 --- /dev/null +++ b/_test/data/sloppy-indentation.canonical @@ -0,0 +1,18 @@ +%YAML 1.1 +--- +!!map { + ? !!str "in the block context" + : !!map { + ? !!str "indentation should be kept" + : !!map { + ? !!str "but in the flow context" + : !!seq [ !!str "it may be violated" ] + } + } +} +--- !!str +"the parser does not require scalars to be indented with at least one space" +--- !!str +"the parser does not require scalars to be indented with at least one space" +--- !!map +{ ? !!str "foo": { ? !!str "bar" : !!str "quoted scalars may not adhere indentation" } } diff --git a/_test/data/sloppy-indentation.data b/_test/data/sloppy-indentation.data new file mode 100644 index 0000000..2eb4f5a --- /dev/null +++ b/_test/data/sloppy-indentation.data @@ -0,0 +1,17 @@ +--- +in the block context: + indentation should be kept: { + but in the flow context: [ +it may be violated] +} +--- +the parser does not require scalars +to be indented with at least one space +... +--- +"the parser does not require scalars +to be indented with at least one space" +--- +foo: + bar: 'quoted scalars +may not adhere indentation' diff --git a/_test/data/spec-02-01.code b/_test/data/spec-02-01.code new file mode 100644 index 0000000..0e927a3 --- /dev/null +++ b/_test/data/spec-02-01.code @@ -0,0 +1 @@ +['Mark McGwire', 'Sammy Sosa', 'Ken Griffey'] diff --git a/_test/data/spec-02-01.data b/_test/data/spec-02-01.data new file mode 100644 index 0000000..d12e671 --- /dev/null +++ b/_test/data/spec-02-01.data @@ -0,0 +1,3 @@ +- Mark McGwire +- Sammy Sosa +- Ken Griffey diff --git a/_test/data/spec-02-01.structure b/_test/data/spec-02-01.structure new file mode 100644 index 0000000..f532f4a --- /dev/null +++ b/_test/data/spec-02-01.structure @@ -0,0 +1 @@ +[True, True, True] diff --git a/_test/data/spec-02-01.tokens b/_test/data/spec-02-01.tokens new file mode 100644 index 0000000..ce44cac --- /dev/null +++ b/_test/data/spec-02-01.tokens @@ -0,0 +1 @@ +[[ , _ , _ , _ ]} diff --git a/_test/data/spec-02-02.data b/_test/data/spec-02-02.data new file mode 100644 index 0000000..7b7ec94 --- /dev/null +++ b/_test/data/spec-02-02.data @@ -0,0 +1,3 @@ +hr: 65 # Home runs +avg: 0.278 # Batting average +rbi: 147 # Runs Batted In diff --git a/_test/data/spec-02-02.structure b/_test/data/spec-02-02.structure new file mode 100644 index 0000000..aba1ced --- /dev/null +++ b/_test/data/spec-02-02.structure @@ -0,0 +1 @@ +[(True, True), (True, True), (True, True)] diff --git a/_test/data/spec-02-02.tokens b/_test/data/spec-02-02.tokens new file mode 100644 index 0000000..e4e381b --- /dev/null +++ b/_test/data/spec-02-02.tokens @@ -0,0 +1,5 @@ +{{ +? _ : _ +? _ : _ +? _ : _ +]} diff --git a/_test/data/spec-02-03.data b/_test/data/spec-02-03.data new file mode 100644 index 0000000..656d628 --- /dev/null +++ b/_test/data/spec-02-03.data @@ -0,0 +1,8 @@ +american: + - Boston Red Sox + - Detroit Tigers + - New York Yankees +national: + - New York Mets + - Chicago Cubs + - Atlanta Braves diff --git a/_test/data/spec-02-03.structure b/_test/data/spec-02-03.structure new file mode 100644 index 0000000..25de5d2 --- /dev/null +++ b/_test/data/spec-02-03.structure @@ -0,0 +1 @@ +[(True, [True, True, True]), (True, [True, True, True])] diff --git a/_test/data/spec-02-03.tokens b/_test/data/spec-02-03.tokens new file mode 100644 index 0000000..89815f2 --- /dev/null +++ b/_test/data/spec-02-03.tokens @@ -0,0 +1,4 @@ +{{ +? _ : [[ , _ , _ , _ ]} +? _ : [[ , _ , _ , _ ]} +]} diff --git a/_test/data/spec-02-04.data b/_test/data/spec-02-04.data new file mode 100644 index 0000000..430f6b3 --- /dev/null +++ b/_test/data/spec-02-04.data @@ -0,0 +1,8 @@ +- + name: Mark McGwire + hr: 65 + avg: 0.278 +- + name: Sammy Sosa + hr: 63 + avg: 0.288 diff --git a/_test/data/spec-02-04.structure b/_test/data/spec-02-04.structure new file mode 100644 index 0000000..e7b526c --- /dev/null +++ b/_test/data/spec-02-04.structure @@ -0,0 +1,4 @@ +[ + [(True, True), (True, True), (True, True)], + [(True, True), (True, True), (True, True)], +] diff --git a/_test/data/spec-02-04.tokens b/_test/data/spec-02-04.tokens new file mode 100644 index 0000000..9cb9815 --- /dev/null +++ b/_test/data/spec-02-04.tokens @@ -0,0 +1,4 @@ +[[ +, {{ ? _ : _ ? _ : _ ? _ : _ ]} +, {{ ? _ : _ ? _ : _ ? _ : _ ]} +]} diff --git a/_test/data/spec-02-05.data b/_test/data/spec-02-05.data new file mode 100644 index 0000000..cdd7770 --- /dev/null +++ b/_test/data/spec-02-05.data @@ -0,0 +1,3 @@ +- [name , hr, avg ] +- [Mark McGwire, 65, 0.278] +- [Sammy Sosa , 63, 0.288] diff --git a/_test/data/spec-02-05.structure b/_test/data/spec-02-05.structure new file mode 100644 index 0000000..e06b75a --- /dev/null +++ b/_test/data/spec-02-05.structure @@ -0,0 +1,5 @@ +[ + [True, True, True], + [True, True, True], + [True, True, True], +] diff --git a/_test/data/spec-02-05.tokens b/_test/data/spec-02-05.tokens new file mode 100644 index 0000000..3f6f1ab --- /dev/null +++ b/_test/data/spec-02-05.tokens @@ -0,0 +1,5 @@ +[[ +, [ _ , _ , _ ] +, [ _ , _ , _ ] +, [ _ , _ , _ ] +]} diff --git a/_test/data/spec-02-06.data b/_test/data/spec-02-06.data new file mode 100644 index 0000000..7a957b2 --- /dev/null +++ b/_test/data/spec-02-06.data @@ -0,0 +1,5 @@ +Mark McGwire: {hr: 65, avg: 0.278} +Sammy Sosa: { + hr: 63, + avg: 0.288 + } diff --git a/_test/data/spec-02-06.structure b/_test/data/spec-02-06.structure new file mode 100644 index 0000000..3ef0f4b --- /dev/null +++ b/_test/data/spec-02-06.structure @@ -0,0 +1,4 @@ +[ + (True, [(True, True), (True, True)]), + (True, [(True, True), (True, True)]), +] diff --git a/_test/data/spec-02-06.tokens b/_test/data/spec-02-06.tokens new file mode 100644 index 0000000..a1a5eef --- /dev/null +++ b/_test/data/spec-02-06.tokens @@ -0,0 +1,4 @@ +{{ +? _ : { ? _ : _ , ? _ : _ } +? _ : { ? _ : _ , ? _ : _ } +]} diff --git a/_test/data/spec-02-07.data b/_test/data/spec-02-07.data new file mode 100644 index 0000000..bc711d5 --- /dev/null +++ b/_test/data/spec-02-07.data @@ -0,0 +1,10 @@ +# Ranking of 1998 home runs +--- +- Mark McGwire +- Sammy Sosa +- Ken Griffey + +# Team ranking +--- +- Chicago Cubs +- St Louis Cardinals diff --git a/_test/data/spec-02-07.structure b/_test/data/spec-02-07.structure new file mode 100644 index 0000000..c5d72a3 --- /dev/null +++ b/_test/data/spec-02-07.structure @@ -0,0 +1,4 @@ +[ +[True, True, True], +[True, True], +] diff --git a/_test/data/spec-02-07.tokens b/_test/data/spec-02-07.tokens new file mode 100644 index 0000000..ed48883 --- /dev/null +++ b/_test/data/spec-02-07.tokens @@ -0,0 +1,12 @@ +--- +[[ +, _ +, _ +, _ +]} + +--- +[[ +, _ +, _ +]} diff --git a/_test/data/spec-02-08.data b/_test/data/spec-02-08.data new file mode 100644 index 0000000..05e102d --- /dev/null +++ b/_test/data/spec-02-08.data @@ -0,0 +1,10 @@ +--- +time: 20:03:20 +player: Sammy Sosa +action: strike (miss) +... +--- +time: 20:03:47 +player: Sammy Sosa +action: grand slam +... diff --git a/_test/data/spec-02-08.structure b/_test/data/spec-02-08.structure new file mode 100644 index 0000000..24cff73 --- /dev/null +++ b/_test/data/spec-02-08.structure @@ -0,0 +1,4 @@ +[ +[(True, True), (True, True), (True, True)], +[(True, True), (True, True), (True, True)], +] diff --git a/_test/data/spec-02-08.tokens b/_test/data/spec-02-08.tokens new file mode 100644 index 0000000..7d2c03d --- /dev/null +++ b/_test/data/spec-02-08.tokens @@ -0,0 +1,15 @@ +--- +{{ +? _ : _ +? _ : _ +? _ : _ +]} +... + +--- +{{ +? _ : _ +? _ : _ +? _ : _ +]} +... diff --git a/_test/data/spec-02-09.data b/_test/data/spec-02-09.data new file mode 100644 index 0000000..e264180 --- /dev/null +++ b/_test/data/spec-02-09.data @@ -0,0 +1,8 @@ +--- +hr: # 1998 hr ranking + - Mark McGwire + - Sammy Sosa +rbi: + # 1998 rbi ranking + - Sammy Sosa + - Ken Griffey diff --git a/_test/data/spec-02-09.structure b/_test/data/spec-02-09.structure new file mode 100644 index 0000000..b4c9914 --- /dev/null +++ b/_test/data/spec-02-09.structure @@ -0,0 +1 @@ +[(True, [True, True]), (True, [True, True])] diff --git a/_test/data/spec-02-09.tokens b/_test/data/spec-02-09.tokens new file mode 100644 index 0000000..b2ec10e --- /dev/null +++ b/_test/data/spec-02-09.tokens @@ -0,0 +1,5 @@ +--- +{{ +? _ : [[ , _ , _ ]} +? _ : [[ , _ , _ ]} +]} diff --git a/_test/data/spec-02-10.data b/_test/data/spec-02-10.data new file mode 100644 index 0000000..61808f6 --- /dev/null +++ b/_test/data/spec-02-10.data @@ -0,0 +1,8 @@ +--- +hr: + - Mark McGwire + # Following node labeled SS + - &SS Sammy Sosa +rbi: + - *SS # Subsequent occurrence + - Ken Griffey diff --git a/_test/data/spec-02-10.structure b/_test/data/spec-02-10.structure new file mode 100644 index 0000000..ff8f4c3 --- /dev/null +++ b/_test/data/spec-02-10.structure @@ -0,0 +1 @@ +[(True, [True, True]), (True, ['*', True])] diff --git a/_test/data/spec-02-10.tokens b/_test/data/spec-02-10.tokens new file mode 100644 index 0000000..26caa2b --- /dev/null +++ b/_test/data/spec-02-10.tokens @@ -0,0 +1,5 @@ +--- +{{ +? _ : [[ , _ , & _ ]} +? _ : [[ , * , _ ]} +]} diff --git a/_test/data/spec-02-11.code b/_test/data/spec-02-11.code new file mode 100644 index 0000000..6e02325 --- /dev/null +++ b/_test/data/spec-02-11.code @@ -0,0 +1,10 @@ +{ +('Detroit Tigers', 'Chicago cubs'): [datetime.date(2001, 7, 23)], + +('New York Yankees', 'Atlanta Braves'): + [datetime.date(2001, 7, 2), + datetime.date(2001, 8, 12), + datetime.date(2001, 8, 14)] +} + + diff --git a/_test/data/spec-02-11.data b/_test/data/spec-02-11.data new file mode 100644 index 0000000..9123ce2 --- /dev/null +++ b/_test/data/spec-02-11.data @@ -0,0 +1,9 @@ +? - Detroit Tigers + - Chicago cubs +: + - 2001-07-23 + +? [ New York Yankees, + Atlanta Braves ] +: [ 2001-07-02, 2001-08-12, + 2001-08-14 ] diff --git a/_test/data/spec-02-11.structure b/_test/data/spec-02-11.structure new file mode 100644 index 0000000..3d8f1ff --- /dev/null +++ b/_test/data/spec-02-11.structure @@ -0,0 +1,4 @@ +[ +([True, True], [True]), +([True, True], [True, True, True]), +] diff --git a/_test/data/spec-02-11.tokens b/_test/data/spec-02-11.tokens new file mode 100644 index 0000000..fe24203 --- /dev/null +++ b/_test/data/spec-02-11.tokens @@ -0,0 +1,6 @@ +{{ +? [[ , _ , _ ]} +: [[ , _ ]} +? [ _ , _ ] +: [ _ , _ , _ ] +]} diff --git a/_test/data/spec-02-12.data b/_test/data/spec-02-12.data new file mode 100644 index 0000000..1fc33f9 --- /dev/null +++ b/_test/data/spec-02-12.data @@ -0,0 +1,8 @@ +--- +# products purchased +- item : Super Hoop + quantity: 1 +- item : Basketball + quantity: 4 +- item : Big Shoes + quantity: 1 diff --git a/_test/data/spec-02-12.structure b/_test/data/spec-02-12.structure new file mode 100644 index 0000000..e9c5359 --- /dev/null +++ b/_test/data/spec-02-12.structure @@ -0,0 +1,5 @@ +[ +[(True, True), (True, True)], +[(True, True), (True, True)], +[(True, True), (True, True)], +] diff --git a/_test/data/spec-02-12.tokens b/_test/data/spec-02-12.tokens new file mode 100644 index 0000000..ea21e50 --- /dev/null +++ b/_test/data/spec-02-12.tokens @@ -0,0 +1,6 @@ +--- +[[ +, {{ ? _ : _ ? _ : _ ]} +, {{ ? _ : _ ? _ : _ ]} +, {{ ? _ : _ ? _ : _ ]} +]} diff --git a/_test/data/spec-02-13.data b/_test/data/spec-02-13.data new file mode 100644 index 0000000..13fb656 --- /dev/null +++ b/_test/data/spec-02-13.data @@ -0,0 +1,4 @@ +# ASCII Art +--- | + \//||\/|| + // || ||__ diff --git a/_test/data/spec-02-13.structure b/_test/data/spec-02-13.structure new file mode 100644 index 0000000..0ca9514 --- /dev/null +++ b/_test/data/spec-02-13.structure @@ -0,0 +1 @@ +True diff --git a/_test/data/spec-02-13.tokens b/_test/data/spec-02-13.tokens new file mode 100644 index 0000000..7456c05 --- /dev/null +++ b/_test/data/spec-02-13.tokens @@ -0,0 +1 @@ +--- _ diff --git a/_test/data/spec-02-14.data b/_test/data/spec-02-14.data new file mode 100644 index 0000000..59943de --- /dev/null +++ b/_test/data/spec-02-14.data @@ -0,0 +1,4 @@ +--- + Mark McGwire's + year was crippled + by a knee injury. diff --git a/_test/data/spec-02-14.structure b/_test/data/spec-02-14.structure new file mode 100644 index 0000000..0ca9514 --- /dev/null +++ b/_test/data/spec-02-14.structure @@ -0,0 +1 @@ +True diff --git a/_test/data/spec-02-14.tokens b/_test/data/spec-02-14.tokens new file mode 100644 index 0000000..7456c05 --- /dev/null +++ b/_test/data/spec-02-14.tokens @@ -0,0 +1 @@ +--- _ diff --git a/_test/data/spec-02-15.data b/_test/data/spec-02-15.data new file mode 100644 index 0000000..80b89a6 --- /dev/null +++ b/_test/data/spec-02-15.data @@ -0,0 +1,8 @@ +> + Sammy Sosa completed another + fine season with great stats. + + 63 Home Runs + 0.288 Batting Average + + What a year! diff --git a/_test/data/spec-02-15.structure b/_test/data/spec-02-15.structure new file mode 100644 index 0000000..0ca9514 --- /dev/null +++ b/_test/data/spec-02-15.structure @@ -0,0 +1 @@ +True diff --git a/_test/data/spec-02-15.tokens b/_test/data/spec-02-15.tokens new file mode 100644 index 0000000..31354ec --- /dev/null +++ b/_test/data/spec-02-15.tokens @@ -0,0 +1 @@ +_ diff --git a/_test/data/spec-02-16.data b/_test/data/spec-02-16.data new file mode 100644 index 0000000..9f66d88 --- /dev/null +++ b/_test/data/spec-02-16.data @@ -0,0 +1,7 @@ +name: Mark McGwire +accomplishment: > + Mark set a major league + home run record in 1998. +stats: | + 65 Home Runs + 0.278 Batting Average diff --git a/_test/data/spec-02-16.structure b/_test/data/spec-02-16.structure new file mode 100644 index 0000000..aba1ced --- /dev/null +++ b/_test/data/spec-02-16.structure @@ -0,0 +1 @@ +[(True, True), (True, True), (True, True)] diff --git a/_test/data/spec-02-16.tokens b/_test/data/spec-02-16.tokens new file mode 100644 index 0000000..e4e381b --- /dev/null +++ b/_test/data/spec-02-16.tokens @@ -0,0 +1,5 @@ +{{ +? _ : _ +? _ : _ +? _ : _ +]} diff --git a/_test/data/spec-02-17.data b/_test/data/spec-02-17.data new file mode 100644 index 0000000..b2870c5 --- /dev/null +++ b/_test/data/spec-02-17.data @@ -0,0 +1,7 @@ +unicode: "Sosa did fine.\u263A" +control: "\b1998\t1999\t2000\n" +hexesc: "\x13\x10 is \r\n" + +single: '"Howdy!" he cried.' +quoted: ' # not a ''comment''.' +tie-fighter: '|\-*-/|' diff --git a/_test/data/spec-02-17.structure b/_test/data/spec-02-17.structure new file mode 100644 index 0000000..933646d --- /dev/null +++ b/_test/data/spec-02-17.structure @@ -0,0 +1 @@ +[(True, True), (True, True), (True, True), (True, True), (True, True), (True, True)] diff --git a/_test/data/spec-02-17.tokens b/_test/data/spec-02-17.tokens new file mode 100644 index 0000000..db65540 --- /dev/null +++ b/_test/data/spec-02-17.tokens @@ -0,0 +1,8 @@ +{{ +? _ : _ +? _ : _ +? _ : _ +? _ : _ +? _ : _ +? _ : _ +]} diff --git a/_test/data/spec-02-18.data b/_test/data/spec-02-18.data new file mode 100644 index 0000000..e0a8bfa --- /dev/null +++ b/_test/data/spec-02-18.data @@ -0,0 +1,6 @@ +plain: + This unquoted scalar + spans many lines. + +quoted: "So does this + quoted scalar.\n" diff --git a/_test/data/spec-02-18.structure b/_test/data/spec-02-18.structure new file mode 100644 index 0000000..0ca4991 --- /dev/null +++ b/_test/data/spec-02-18.structure @@ -0,0 +1 @@ +[(True, True), (True, True)] diff --git a/_test/data/spec-02-18.tokens b/_test/data/spec-02-18.tokens new file mode 100644 index 0000000..83b31dc --- /dev/null +++ b/_test/data/spec-02-18.tokens @@ -0,0 +1,4 @@ +{{ +? _ : _ +? _ : _ +]} diff --git a/_test/data/spec-02-19.data b/_test/data/spec-02-19.data new file mode 100644 index 0000000..bf69de6 --- /dev/null +++ b/_test/data/spec-02-19.data @@ -0,0 +1,5 @@ +canonical: 12345 +decimal: +12,345 +sexagesimal: 3:25:45 +octal: 014 +hexadecimal: 0xC diff --git a/_test/data/spec-02-19.structure b/_test/data/spec-02-19.structure new file mode 100644 index 0000000..48ca99d --- /dev/null +++ b/_test/data/spec-02-19.structure @@ -0,0 +1 @@ +[(True, True), (True, True), (True, True), (True, True), (True, True)] diff --git a/_test/data/spec-02-19.tokens b/_test/data/spec-02-19.tokens new file mode 100644 index 0000000..5bda68f --- /dev/null +++ b/_test/data/spec-02-19.tokens @@ -0,0 +1,7 @@ +{{ +? _ : _ +? _ : _ +? _ : _ +? _ : _ +? _ : _ +]} diff --git a/_test/data/spec-02-20.data b/_test/data/spec-02-20.data new file mode 100644 index 0000000..1d4897f --- /dev/null +++ b/_test/data/spec-02-20.data @@ -0,0 +1,6 @@ +canonical: 1.23015e+3 +exponential: 12.3015e+02 +sexagesimal: 20:30.15 +fixed: 1,230.15 +negative infinity: -.inf +not a number: .NaN diff --git a/_test/data/spec-02-20.structure b/_test/data/spec-02-20.structure new file mode 100644 index 0000000..933646d --- /dev/null +++ b/_test/data/spec-02-20.structure @@ -0,0 +1 @@ +[(True, True), (True, True), (True, True), (True, True), (True, True), (True, True)] diff --git a/_test/data/spec-02-20.tokens b/_test/data/spec-02-20.tokens new file mode 100644 index 0000000..db65540 --- /dev/null +++ b/_test/data/spec-02-20.tokens @@ -0,0 +1,8 @@ +{{ +? _ : _ +? _ : _ +? _ : _ +? _ : _ +? _ : _ +? _ : _ +]} diff --git a/_test/data/spec-02-21.data b/_test/data/spec-02-21.data new file mode 100644 index 0000000..dec6a56 --- /dev/null +++ b/_test/data/spec-02-21.data @@ -0,0 +1,4 @@ +null: ~ +true: y +false: n +string: '12345' diff --git a/_test/data/spec-02-21.structure b/_test/data/spec-02-21.structure new file mode 100644 index 0000000..021635f --- /dev/null +++ b/_test/data/spec-02-21.structure @@ -0,0 +1 @@ +[(True, True), (True, True), (True, True), (True, True)] diff --git a/_test/data/spec-02-21.tokens b/_test/data/spec-02-21.tokens new file mode 100644 index 0000000..aeccbaf --- /dev/null +++ b/_test/data/spec-02-21.tokens @@ -0,0 +1,6 @@ +{{ +? _ : _ +? _ : _ +? _ : _ +? _ : _ +]} diff --git a/_test/data/spec-02-22.data b/_test/data/spec-02-22.data new file mode 100644 index 0000000..aaac185 --- /dev/null +++ b/_test/data/spec-02-22.data @@ -0,0 +1,4 @@ +canonical: 2001-12-15T02:59:43.1Z +iso8601: 2001-12-14t21:59:43.10-05:00 +spaced: 2001-12-14 21:59:43.10 -5 +date: 2002-12-14 diff --git a/_test/data/spec-02-22.structure b/_test/data/spec-02-22.structure new file mode 100644 index 0000000..021635f --- /dev/null +++ b/_test/data/spec-02-22.structure @@ -0,0 +1 @@ +[(True, True), (True, True), (True, True), (True, True)] diff --git a/_test/data/spec-02-22.tokens b/_test/data/spec-02-22.tokens new file mode 100644 index 0000000..aeccbaf --- /dev/null +++ b/_test/data/spec-02-22.tokens @@ -0,0 +1,6 @@ +{{ +? _ : _ +? _ : _ +? _ : _ +? _ : _ +]} diff --git a/_test/data/spec-02-23.data b/_test/data/spec-02-23.data new file mode 100644 index 0000000..5dbd992 --- /dev/null +++ b/_test/data/spec-02-23.data @@ -0,0 +1,13 @@ +--- +not-date: !!str 2002-04-28 + +picture: !!binary | + R0lGODlhDAAMAIQAAP//9/X + 17unp5WZmZgAAAOfn515eXv + Pz7Y6OjuDg4J+fn5OTk6enp + 56enmleECcgggoBADs= + +application specific tag: !something | + The semantics of the tag + above may be different for + different documents. diff --git a/_test/data/spec-02-23.structure b/_test/data/spec-02-23.structure new file mode 100644 index 0000000..aba1ced --- /dev/null +++ b/_test/data/spec-02-23.structure @@ -0,0 +1 @@ +[(True, True), (True, True), (True, True)] diff --git a/_test/data/spec-02-23.tokens b/_test/data/spec-02-23.tokens new file mode 100644 index 0000000..9ac54aa --- /dev/null +++ b/_test/data/spec-02-23.tokens @@ -0,0 +1,6 @@ +--- +{{ +? _ : ! _ +? _ : ! _ +? _ : ! _ +]} diff --git a/_test/data/spec-02-24.data b/_test/data/spec-02-24.data new file mode 100644 index 0000000..1180757 --- /dev/null +++ b/_test/data/spec-02-24.data @@ -0,0 +1,14 @@ +%TAG ! tag:clarkevans.com,2002: +--- !shape + # Use the ! handle for presenting + # tag:clarkevans.com,2002:circle +- !circle + center: &ORIGIN {x: 73, y: 129} + radius: 7 +- !line + start: *ORIGIN + finish: { x: 89, y: 102 } +- !label + start: *ORIGIN + color: 0xFFEEBB + text: Pretty vector drawing. diff --git a/_test/data/spec-02-24.structure b/_test/data/spec-02-24.structure new file mode 100644 index 0000000..a800729 --- /dev/null +++ b/_test/data/spec-02-24.structure @@ -0,0 +1,5 @@ +[ +[(True, [(True, True), (True, True)]), (True, True)], +[(True, '*'), (True, [(True, True), (True, True)])], +[(True, '*'), (True, True), (True, True)], +] diff --git a/_test/data/spec-02-24.tokens b/_test/data/spec-02-24.tokens new file mode 100644 index 0000000..039c385 --- /dev/null +++ b/_test/data/spec-02-24.tokens @@ -0,0 +1,20 @@ +% +--- ! +[[ +, ! + {{ + ? _ : & { ? _ : _ , ? _ : _ } + ? _ : _ + ]} +, ! + {{ + ? _ : * + ? _ : { ? _ : _ , ? _ : _ } + ]} +, ! + {{ + ? _ : * + ? _ : _ + ? _ : _ + ]} +]} diff --git a/_test/data/spec-02-25.data b/_test/data/spec-02-25.data new file mode 100644 index 0000000..769ac31 --- /dev/null +++ b/_test/data/spec-02-25.data @@ -0,0 +1,7 @@ +# sets are represented as a +# mapping where each key is +# associated with the empty string +--- !!set +? Mark McGwire +? Sammy Sosa +? Ken Griff diff --git a/_test/data/spec-02-25.structure b/_test/data/spec-02-25.structure new file mode 100644 index 0000000..0b40e61 --- /dev/null +++ b/_test/data/spec-02-25.structure @@ -0,0 +1 @@ +[(True, None), (True, None), (True, None)] diff --git a/_test/data/spec-02-25.tokens b/_test/data/spec-02-25.tokens new file mode 100644 index 0000000..b700236 --- /dev/null +++ b/_test/data/spec-02-25.tokens @@ -0,0 +1,6 @@ +--- ! +{{ +? _ +? _ +? _ +]} diff --git a/_test/data/spec-02-26.data b/_test/data/spec-02-26.data new file mode 100644 index 0000000..3143763 --- /dev/null +++ b/_test/data/spec-02-26.data @@ -0,0 +1,7 @@ +# ordered maps are represented as +# a sequence of mappings, with +# each mapping having one key +--- !!omap +- Mark McGwire: 65 +- Sammy Sosa: 63 +- Ken Griffy: 58 diff --git a/_test/data/spec-02-26.structure b/_test/data/spec-02-26.structure new file mode 100644 index 0000000..cf429b9 --- /dev/null +++ b/_test/data/spec-02-26.structure @@ -0,0 +1,5 @@ +[ +[(True, True)], +[(True, True)], +[(True, True)], +] diff --git a/_test/data/spec-02-26.tokens b/_test/data/spec-02-26.tokens new file mode 100644 index 0000000..7bee492 --- /dev/null +++ b/_test/data/spec-02-26.tokens @@ -0,0 +1,6 @@ +--- ! +[[ +, {{ ? _ : _ ]} +, {{ ? _ : _ ]} +, {{ ? _ : _ ]} +]} diff --git a/_test/data/spec-02-27.data b/_test/data/spec-02-27.data new file mode 100644 index 0000000..4625739 --- /dev/null +++ b/_test/data/spec-02-27.data @@ -0,0 +1,29 @@ +--- !<tag:clarkevans.com,2002:invoice> +invoice: 34843 +date : 2001-01-23 +bill-to: &id001 + given : Chris + family : Dumars + address: + lines: | + 458 Walkman Dr. + Suite #292 + city : Royal Oak + state : MI + postal : 48046 +ship-to: *id001 +product: + - sku : BL394D + quantity : 4 + description : Basketball + price : 450.00 + - sku : BL4438H + quantity : 1 + description : Super Hoop + price : 2392.00 +tax : 251.42 +total: 4443.52 +comments: + Late afternoon is best. + Backup contact is Nancy + Billsmer @ 338-4338. diff --git a/_test/data/spec-02-27.structure b/_test/data/spec-02-27.structure new file mode 100644 index 0000000..a2113b9 --- /dev/null +++ b/_test/data/spec-02-27.structure @@ -0,0 +1,17 @@ +[ +(True, True), +(True, True), +(True, [ + (True, True), + (True, True), + (True, [(True, True), (True, True), (True, True), (True, True)]), + ]), +(True, '*'), +(True, [ + [(True, True), (True, True), (True, True), (True, True)], + [(True, True), (True, True), (True, True), (True, True)], + ]), +(True, True), +(True, True), +(True, True), +] diff --git a/_test/data/spec-02-27.tokens b/_test/data/spec-02-27.tokens new file mode 100644 index 0000000..2dc1c25 --- /dev/null +++ b/_test/data/spec-02-27.tokens @@ -0,0 +1,20 @@ +--- ! +{{ +? _ : _ +? _ : _ +? _ : & + {{ + ? _ : _ + ? _ : _ + ? _ : {{ ? _ : _ ? _ : _ ? _ : _ ? _ : _ ]} + ]} +? _ : * +? _ : + [[ + , {{ ? _ : _ ? _ : _ ? _ : _ ? _ : _ ]} + , {{ ? _ : _ ? _ : _ ? _ : _ ? _ : _ ]} + ]} +? _ : _ +? _ : _ +? _ : _ +]} diff --git a/_test/data/spec-02-28.data b/_test/data/spec-02-28.data new file mode 100644 index 0000000..a5c8dc8 --- /dev/null +++ b/_test/data/spec-02-28.data @@ -0,0 +1,26 @@ +--- +Time: 2001-11-23 15:01:42 -5 +User: ed +Warning: + This is an error message + for the log file +--- +Time: 2001-11-23 15:02:31 -5 +User: ed +Warning: + A slightly different error + message. +--- +Date: 2001-11-23 15:03:17 -5 +User: ed +Fatal: + Unknown variable "bar" +Stack: + - file: TopClass.py + line: 23 + code: | + x = MoreObject("345\n") + - file: MoreClass.py + line: 58 + code: |- + foo = bar diff --git a/_test/data/spec-02-28.structure b/_test/data/spec-02-28.structure new file mode 100644 index 0000000..8ec0b56 --- /dev/null +++ b/_test/data/spec-02-28.structure @@ -0,0 +1,10 @@ +[ +[(True, True), (True, True), (True, True)], +[(True, True), (True, True), (True, True)], +[(True, True), (True, True), (True, True), +(True, [ + [(True, True), (True, True), (True, True)], + [(True, True), (True, True), (True, True)], + ]), +] +] diff --git a/_test/data/spec-02-28.tokens b/_test/data/spec-02-28.tokens new file mode 100644 index 0000000..8d5e1bc --- /dev/null +++ b/_test/data/spec-02-28.tokens @@ -0,0 +1,23 @@ +--- +{{ +? _ : _ +? _ : _ +? _ : _ +]} +--- +{{ +? _ : _ +? _ : _ +? _ : _ +]} +--- +{{ +? _ : _ +? _ : _ +? _ : _ +? _ : + [[ + , {{ ? _ : _ ? _ : _ ? _ : _ ]} + , {{ ? _ : _ ? _ : _ ? _ : _ ]} + ]} +]} diff --git a/_test/data/spec-05-01-utf16be.data b/_test/data/spec-05-01-utf16be.data Binary files differnew file mode 100644 index 0000000..3525062 --- /dev/null +++ b/_test/data/spec-05-01-utf16be.data diff --git a/_test/data/spec-05-01-utf16be.empty b/_test/data/spec-05-01-utf16be.empty new file mode 100644 index 0000000..bfffa8b --- /dev/null +++ b/_test/data/spec-05-01-utf16be.empty @@ -0,0 +1,2 @@ +# This stream contains no +# documents, only comments. diff --git a/_test/data/spec-05-01-utf16le.data b/_test/data/spec-05-01-utf16le.data Binary files differnew file mode 100644 index 0000000..0823f74 --- /dev/null +++ b/_test/data/spec-05-01-utf16le.data diff --git a/_test/data/spec-05-01-utf16le.empty b/_test/data/spec-05-01-utf16le.empty new file mode 100644 index 0000000..bfffa8b --- /dev/null +++ b/_test/data/spec-05-01-utf16le.empty @@ -0,0 +1,2 @@ +# This stream contains no +# documents, only comments. diff --git a/_test/data/spec-05-01-utf8.data b/_test/data/spec-05-01-utf8.data new file mode 100644 index 0000000..780d25b --- /dev/null +++ b/_test/data/spec-05-01-utf8.data @@ -0,0 +1 @@ +# Comment only. diff --git a/_test/data/spec-05-01-utf8.empty b/_test/data/spec-05-01-utf8.empty new file mode 100644 index 0000000..bfffa8b --- /dev/null +++ b/_test/data/spec-05-01-utf8.empty @@ -0,0 +1,2 @@ +# This stream contains no +# documents, only comments. diff --git a/_test/data/spec-05-02-utf16be.data b/_test/data/spec-05-02-utf16be.data Binary files differnew file mode 100644 index 0000000..5ebbb04 --- /dev/null +++ b/_test/data/spec-05-02-utf16be.data diff --git a/_test/data/spec-05-02-utf16be.error b/_test/data/spec-05-02-utf16be.error new file mode 100644 index 0000000..1df3616 --- /dev/null +++ b/_test/data/spec-05-02-utf16be.error @@ -0,0 +1,3 @@ +ERROR: + A BOM must not appear + inside a document. diff --git a/_test/data/spec-05-02-utf16le.data b/_test/data/spec-05-02-utf16le.data Binary files differnew file mode 100644 index 0000000..0cd90a2 --- /dev/null +++ b/_test/data/spec-05-02-utf16le.data diff --git a/_test/data/spec-05-02-utf16le.error b/_test/data/spec-05-02-utf16le.error new file mode 100644 index 0000000..1df3616 --- /dev/null +++ b/_test/data/spec-05-02-utf16le.error @@ -0,0 +1,3 @@ +ERROR: + A BOM must not appear + inside a document. diff --git a/_test/data/spec-05-02-utf8.data b/_test/data/spec-05-02-utf8.data new file mode 100644 index 0000000..fb74866 --- /dev/null +++ b/_test/data/spec-05-02-utf8.data @@ -0,0 +1,3 @@ +# Invalid use of BOM +# inside a +# document. diff --git a/_test/data/spec-05-02-utf8.error b/_test/data/spec-05-02-utf8.error new file mode 100644 index 0000000..1df3616 --- /dev/null +++ b/_test/data/spec-05-02-utf8.error @@ -0,0 +1,3 @@ +ERROR: + A BOM must not appear + inside a document. diff --git a/_test/data/spec-05-03.canonical b/_test/data/spec-05-03.canonical new file mode 100644 index 0000000..a143a73 --- /dev/null +++ b/_test/data/spec-05-03.canonical @@ -0,0 +1,14 @@ +%YAML 1.1 +--- +!!map { + ? !!str "sequence" + : !!seq [ + !!str "one", !!str "two" + ], + ? !!str "mapping" + : !!map { + ? !!str "sky" : !!str "blue", +# ? !!str "sea" : !!str "green", + ? !!map { ? !!str "sea" : !!str "green" } : !!null "", + } +} diff --git a/_test/data/spec-05-03.data b/_test/data/spec-05-03.data new file mode 100644 index 0000000..4661f33 --- /dev/null +++ b/_test/data/spec-05-03.data @@ -0,0 +1,7 @@ +sequence: +- one +- two +mapping: + ? sky + : blue + ? sea : green diff --git a/_test/data/spec-05-04.canonical b/_test/data/spec-05-04.canonical new file mode 100644 index 0000000..00c9723 --- /dev/null +++ b/_test/data/spec-05-04.canonical @@ -0,0 +1,13 @@ +%YAML 1.1 +--- +!!map { + ? !!str "sequence" + : !!seq [ + !!str "one", !!str "two" + ], + ? !!str "mapping" + : !!map { + ? !!str "sky" : !!str "blue", + ? !!str "sea" : !!str "green", + } +} diff --git a/_test/data/spec-05-04.data b/_test/data/spec-05-04.data new file mode 100644 index 0000000..df33847 --- /dev/null +++ b/_test/data/spec-05-04.data @@ -0,0 +1,2 @@ +sequence: [ one, two, ] +mapping: { sky: blue, sea: green } diff --git a/_test/data/spec-05-05.data b/_test/data/spec-05-05.data new file mode 100644 index 0000000..62524c0 --- /dev/null +++ b/_test/data/spec-05-05.data @@ -0,0 +1 @@ +# Comment only. diff --git a/_test/data/spec-05-05.empty b/_test/data/spec-05-05.empty new file mode 100644 index 0000000..bfffa8b --- /dev/null +++ b/_test/data/spec-05-05.empty @@ -0,0 +1,2 @@ +# This stream contains no +# documents, only comments. diff --git a/_test/data/spec-05-06.canonical b/_test/data/spec-05-06.canonical new file mode 100644 index 0000000..4f30c11 --- /dev/null +++ b/_test/data/spec-05-06.canonical @@ -0,0 +1,8 @@ +%YAML 1.1 +--- +!!map { + ? !!str "anchored" + : &A1 !local "value", + ? !!str "alias" + : *A1, +} diff --git a/_test/data/spec-05-06.data b/_test/data/spec-05-06.data new file mode 100644 index 0000000..7a1f9b3 --- /dev/null +++ b/_test/data/spec-05-06.data @@ -0,0 +1,2 @@ +anchored: !local &anchor value +alias: *anchor diff --git a/_test/data/spec-05-07.canonical b/_test/data/spec-05-07.canonical new file mode 100644 index 0000000..dc3732a --- /dev/null +++ b/_test/data/spec-05-07.canonical @@ -0,0 +1,8 @@ +%YAML 1.1 +--- +!!map { + ? !!str "literal" + : !!str "text\n", + ? !!str "folded" + : !!str "text\n", +} diff --git a/_test/data/spec-05-07.data b/_test/data/spec-05-07.data new file mode 100644 index 0000000..97eb3a3 --- /dev/null +++ b/_test/data/spec-05-07.data @@ -0,0 +1,4 @@ +literal: | + text +folded: > + text diff --git a/_test/data/spec-05-08.canonical b/_test/data/spec-05-08.canonical new file mode 100644 index 0000000..610bd68 --- /dev/null +++ b/_test/data/spec-05-08.canonical @@ -0,0 +1,8 @@ +%YAML 1.1 +--- +!!map { + ? !!str "single" + : !!str "text", + ? !!str "double" + : !!str "text", +} diff --git a/_test/data/spec-05-08.data b/_test/data/spec-05-08.data new file mode 100644 index 0000000..04ebf69 --- /dev/null +++ b/_test/data/spec-05-08.data @@ -0,0 +1,2 @@ +single: 'text' +double: "text" diff --git a/_test/data/spec-05-09.canonical b/_test/data/spec-05-09.canonical new file mode 100644 index 0000000..597e3de --- /dev/null +++ b/_test/data/spec-05-09.canonical @@ -0,0 +1,3 @@ +%YAML 1.1 +--- +!!str "text" diff --git a/_test/data/spec-05-09.data b/_test/data/spec-05-09.data new file mode 100644 index 0000000..a43431b --- /dev/null +++ b/_test/data/spec-05-09.data @@ -0,0 +1,2 @@ +%YAML 1.1 +--- text diff --git a/_test/data/spec-05-10.data b/_test/data/spec-05-10.data new file mode 100644 index 0000000..a4caf91 --- /dev/null +++ b/_test/data/spec-05-10.data @@ -0,0 +1,2 @@ +commercial-at: @text +grave-accent: `text diff --git a/_test/data/spec-05-10.error b/_test/data/spec-05-10.error new file mode 100644 index 0000000..46f776e --- /dev/null +++ b/_test/data/spec-05-10.error @@ -0,0 +1,3 @@ +ERROR: + Reserved indicators can't + start a plain scalar. diff --git a/_test/data/spec-05-11.canonical b/_test/data/spec-05-11.canonical new file mode 100644 index 0000000..fc25bef --- /dev/null +++ b/_test/data/spec-05-11.canonical @@ -0,0 +1,6 @@ +%YAML 1.1 +--- !!str +"Generic line break (no glyph)\n\ + Generic line break (glyphed)\n\ + Line separator\u2028\ + Paragraph separator\u2029" diff --git a/_test/data/spec-05-11.data b/_test/data/spec-05-11.data new file mode 100644 index 0000000..b448b75 --- /dev/null +++ b/_test/data/spec-05-11.data @@ -0,0 +1,3 @@ +| + Generic line break (no glyph) + Generic line break (glyphed)… Line separator
 Paragraph separator

\ No newline at end of file diff --git a/_test/data/spec-05-12.data b/_test/data/spec-05-12.data new file mode 100644 index 0000000..7c3ad7f --- /dev/null +++ b/_test/data/spec-05-12.data @@ -0,0 +1,9 @@ +# Tabs do's and don'ts: +# comment: +quoted: "Quoted " +block: | + void main() { + printf("Hello, world!\n"); + } +elsewhere: # separation + indentation, in plain scalar diff --git a/_test/data/spec-05-12.error b/_test/data/spec-05-12.error new file mode 100644 index 0000000..8aad4c8 --- /dev/null +++ b/_test/data/spec-05-12.error @@ -0,0 +1,8 @@ +ERROR: + Tabs may appear inside + comments and quoted or + block scalar content. + Tabs must not appear + elsewhere, such as + in indentation and + separation spaces. diff --git a/_test/data/spec-05-13.canonical b/_test/data/spec-05-13.canonical new file mode 100644 index 0000000..90c1c5c --- /dev/null +++ b/_test/data/spec-05-13.canonical @@ -0,0 +1,5 @@ +%YAML 1.1 +--- !!str +"Text containing \ + both space and \ + tab characters" diff --git a/_test/data/spec-05-13.data b/_test/data/spec-05-13.data new file mode 100644 index 0000000..fce7951 --- /dev/null +++ b/_test/data/spec-05-13.data @@ -0,0 +1,3 @@ + "Text containing + both space and + tab characters" diff --git a/_test/data/spec-05-14.canonical b/_test/data/spec-05-14.canonical new file mode 100644 index 0000000..4bff01c --- /dev/null +++ b/_test/data/spec-05-14.canonical @@ -0,0 +1,7 @@ +%YAML 1.1 +--- +"Fun with \x5C + \x22 \x07 \x08 \x1B \x0C + \x0A \x0D \x09 \x0B \x00 + \x20 \xA0 \x85 \u2028 \u2029 + A A A" diff --git a/_test/data/spec-05-14.data b/_test/data/spec-05-14.data new file mode 100644 index 0000000..d6e8ce4 --- /dev/null +++ b/_test/data/spec-05-14.data @@ -0,0 +1,2 @@ +"Fun with \\ + \" \a \b \e \f \Â… \n \r \t \v \0 \
 \ \_ \N \L \P \
 \x41 \u0041 \U00000041" diff --git a/_test/data/spec-05-15.data b/_test/data/spec-05-15.data new file mode 100644 index 0000000..7bf12b6 --- /dev/null +++ b/_test/data/spec-05-15.data @@ -0,0 +1,3 @@ +Bad escapes: + "\c + \xq-" diff --git a/_test/data/spec-05-15.error b/_test/data/spec-05-15.error new file mode 100644 index 0000000..71ffbd9 --- /dev/null +++ b/_test/data/spec-05-15.error @@ -0,0 +1,3 @@ +ERROR: +- c is an invalid escaped character. +- q and - are invalid hex digits. diff --git a/_test/data/spec-06-01.canonical b/_test/data/spec-06-01.canonical new file mode 100644 index 0000000..f17ec92 --- /dev/null +++ b/_test/data/spec-06-01.canonical @@ -0,0 +1,15 @@ +%YAML 1.1 +--- +!!map { + ? !!str "Not indented" + : !!map { + ? !!str "By one space" + : !!str "By four\n spaces\n", + ? !!str "Flow style" + : !!seq [ + !!str "By two", + !!str "Also by two", + !!str "Still by two", + ] + } +} diff --git a/_test/data/spec-06-01.data b/_test/data/spec-06-01.data new file mode 100644 index 0000000..6134ba1 --- /dev/null +++ b/_test/data/spec-06-01.data @@ -0,0 +1,14 @@ + # Leading comment line spaces are + # neither content nor indentation. + +Not indented: + By one space: | + By four + spaces + Flow style: [ # Leading spaces + By two, # in flow style + Also by two, # are neither +# Tabs are not allowed: +# Still by two # content nor + Still by two # content nor + ] # indentation. diff --git a/_test/data/spec-06-02.data b/_test/data/spec-06-02.data new file mode 100644 index 0000000..ff741e5 --- /dev/null +++ b/_test/data/spec-06-02.data @@ -0,0 +1,3 @@ + # Comment + + diff --git a/_test/data/spec-06-02.empty b/_test/data/spec-06-02.empty new file mode 100644 index 0000000..bfffa8b --- /dev/null +++ b/_test/data/spec-06-02.empty @@ -0,0 +1,2 @@ +# This stream contains no +# documents, only comments. diff --git a/_test/data/spec-06-03.canonical b/_test/data/spec-06-03.canonical new file mode 100644 index 0000000..ec26902 --- /dev/null +++ b/_test/data/spec-06-03.canonical @@ -0,0 +1,6 @@ +%YAML 1.1 +--- +!!map { + ? !!str "key" + : !!str "value" +} diff --git a/_test/data/spec-06-03.data b/_test/data/spec-06-03.data new file mode 100644 index 0000000..9db0912 --- /dev/null +++ b/_test/data/spec-06-03.data @@ -0,0 +1,2 @@ +key: # Comment + value diff --git a/_test/data/spec-06-04.canonical b/_test/data/spec-06-04.canonical new file mode 100644 index 0000000..ec26902 --- /dev/null +++ b/_test/data/spec-06-04.canonical @@ -0,0 +1,6 @@ +%YAML 1.1 +--- +!!map { + ? !!str "key" + : !!str "value" +} diff --git a/_test/data/spec-06-04.data b/_test/data/spec-06-04.data new file mode 100644 index 0000000..86308dd --- /dev/null +++ b/_test/data/spec-06-04.data @@ -0,0 +1,4 @@ +key: # Comment + # lines + value + diff --git a/_test/data/spec-06-05.canonical b/_test/data/spec-06-05.canonical new file mode 100644 index 0000000..8da431d --- /dev/null +++ b/_test/data/spec-06-05.canonical @@ -0,0 +1,16 @@ +%YAML 1.1 +--- +!!map { + ? !!map { + ? !!str "first" + : !!str "Sammy", + ? !!str "last" + : !!str "Sosa" + } + : !!map { + ? !!str "hr" + : !!int "65", + ? !!str "avg" + : !!float "0.278" + } +} diff --git a/_test/data/spec-06-05.data b/_test/data/spec-06-05.data new file mode 100644 index 0000000..37613f5 --- /dev/null +++ b/_test/data/spec-06-05.data @@ -0,0 +1,6 @@ +{ first: Sammy, last: Sosa }: +# Statistics: + hr: # Home runs + 65 + avg: # Average + 0.278 diff --git a/_test/data/spec-06-06.canonical b/_test/data/spec-06-06.canonical new file mode 100644 index 0000000..513d07a --- /dev/null +++ b/_test/data/spec-06-06.canonical @@ -0,0 +1,10 @@ +%YAML 1.1 +--- +!!map { + ? !!str "plain" + : !!str "text lines", + ? !!str "quoted" + : !!str "text lines", + ? !!str "block" + : !!str "text\n lines\n" +} diff --git a/_test/data/spec-06-06.data b/_test/data/spec-06-06.data new file mode 100644 index 0000000..2f62d08 --- /dev/null +++ b/_test/data/spec-06-06.data @@ -0,0 +1,7 @@ +plain: text + lines +quoted: "text + lines" +block: | + text + lines diff --git a/_test/data/spec-06-07.canonical b/_test/data/spec-06-07.canonical new file mode 100644 index 0000000..11357e4 --- /dev/null +++ b/_test/data/spec-06-07.canonical @@ -0,0 +1,6 @@ +%YAML 1.1 +--- +!!seq [ + !!str "foo\nbar", + !!str "foo\n\nbar" +] diff --git a/_test/data/spec-06-07.data b/_test/data/spec-06-07.data new file mode 100644 index 0000000..130cfa7 --- /dev/null +++ b/_test/data/spec-06-07.data @@ -0,0 +1,8 @@ +- foo + + bar +- |- + foo + + bar + diff --git a/_test/data/spec-06-08.canonical b/_test/data/spec-06-08.canonical new file mode 100644 index 0000000..cc72bc8 --- /dev/null +++ b/_test/data/spec-06-08.canonical @@ -0,0 +1,5 @@ +%YAML 1.1 +--- !!str +"specific\L\ + trimmed\n\n\n\ + as space" diff --git a/_test/data/spec-06-08.data b/_test/data/spec-06-08.data new file mode 100644 index 0000000..f2896ed --- /dev/null +++ b/_test/data/spec-06-08.data @@ -0,0 +1,2 @@ +>- + specific
 trimmedÂ… Â… Â…Â… asÂ… space diff --git a/_test/data/spec-07-01.canonical b/_test/data/spec-07-01.canonical new file mode 100644 index 0000000..8c8c48d --- /dev/null +++ b/_test/data/spec-07-01.canonical @@ -0,0 +1,3 @@ +%YAML 1.1 +--- !!str +"foo" diff --git a/_test/data/spec-07-01.data b/_test/data/spec-07-01.data new file mode 100644 index 0000000..2113eb6 --- /dev/null +++ b/_test/data/spec-07-01.data @@ -0,0 +1,3 @@ +%FOO bar baz # Should be ignored + # with a warning. +--- "foo" diff --git a/_test/data/spec-07-01.skip-ext b/_test/data/spec-07-01.skip-ext new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/_test/data/spec-07-01.skip-ext diff --git a/_test/data/spec-07-02.canonical b/_test/data/spec-07-02.canonical new file mode 100644 index 0000000..cb7dd1c --- /dev/null +++ b/_test/data/spec-07-02.canonical @@ -0,0 +1,3 @@ +%YAML 1.1 +--- +!!str "foo" diff --git a/_test/data/spec-07-02.data b/_test/data/spec-07-02.data new file mode 100644 index 0000000..c8b7322 --- /dev/null +++ b/_test/data/spec-07-02.data @@ -0,0 +1,4 @@ +%YAML 1.2 # Attempt parsing + # with a warning +--- +"foo" diff --git a/_test/data/spec-07-02.skip-ext b/_test/data/spec-07-02.skip-ext new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/_test/data/spec-07-02.skip-ext diff --git a/_test/data/spec-07-03.data b/_test/data/spec-07-03.data new file mode 100644 index 0000000..4bfa07a --- /dev/null +++ b/_test/data/spec-07-03.data @@ -0,0 +1,3 @@ +%YAML 1.1 +%YAML 1.1 +foo diff --git a/_test/data/spec-07-03.error b/_test/data/spec-07-03.error new file mode 100644 index 0000000..b0ac446 --- /dev/null +++ b/_test/data/spec-07-03.error @@ -0,0 +1,3 @@ +ERROR: +The YAML directive must only be +given at most once per document. diff --git a/_test/data/spec-07-04.canonical b/_test/data/spec-07-04.canonical new file mode 100644 index 0000000..cb7dd1c --- /dev/null +++ b/_test/data/spec-07-04.canonical @@ -0,0 +1,3 @@ +%YAML 1.1 +--- +!!str "foo" diff --git a/_test/data/spec-07-04.data b/_test/data/spec-07-04.data new file mode 100644 index 0000000..50f5ab9 --- /dev/null +++ b/_test/data/spec-07-04.data @@ -0,0 +1,3 @@ +%TAG !yaml! tag:yaml.org,2002: +--- +!yaml!str "foo" diff --git a/_test/data/spec-07-05.data b/_test/data/spec-07-05.data new file mode 100644 index 0000000..7276eae --- /dev/null +++ b/_test/data/spec-07-05.data @@ -0,0 +1,3 @@ +%TAG ! !foo +%TAG ! !foo +bar diff --git a/_test/data/spec-07-05.error b/_test/data/spec-07-05.error new file mode 100644 index 0000000..5601b19 --- /dev/null +++ b/_test/data/spec-07-05.error @@ -0,0 +1,4 @@ +ERROR: +The TAG directive must only +be given at most once per +handle in the same document. diff --git a/_test/data/spec-07-06.canonical b/_test/data/spec-07-06.canonical new file mode 100644 index 0000000..bddf616 --- /dev/null +++ b/_test/data/spec-07-06.canonical @@ -0,0 +1,6 @@ +%YAML 1.1 +--- +!!seq [ + !<!foobar> "baz", + !<tag:yaml.org,2002:str> "string" +] diff --git a/_test/data/spec-07-06.data b/_test/data/spec-07-06.data new file mode 100644 index 0000000..d9854cb --- /dev/null +++ b/_test/data/spec-07-06.data @@ -0,0 +1,5 @@ +%TAG ! !foo +%TAG !yaml! tag:yaml.org,2002: +--- +- !bar "baz" +- !yaml!str "string" diff --git a/_test/data/spec-07-07a.canonical b/_test/data/spec-07-07a.canonical new file mode 100644 index 0000000..fa086df --- /dev/null +++ b/_test/data/spec-07-07a.canonical @@ -0,0 +1,3 @@ +%YAML 1.1 +--- +!<!foo> "bar" diff --git a/_test/data/spec-07-07a.data b/_test/data/spec-07-07a.data new file mode 100644 index 0000000..9d42ec3 --- /dev/null +++ b/_test/data/spec-07-07a.data @@ -0,0 +1,2 @@ +# Private application: +!foo "bar" diff --git a/_test/data/spec-07-07b.canonical b/_test/data/spec-07-07b.canonical new file mode 100644 index 0000000..fe917d8 --- /dev/null +++ b/_test/data/spec-07-07b.canonical @@ -0,0 +1,3 @@ +%YAML 1.1 +--- +!<tag:ben-kiki.org,2000:app/foo> "bar" diff --git a/_test/data/spec-07-07b.data b/_test/data/spec-07-07b.data new file mode 100644 index 0000000..2d36d0e --- /dev/null +++ b/_test/data/spec-07-07b.data @@ -0,0 +1,4 @@ +# Migrated to global: +%TAG ! tag:ben-kiki.org,2000:app/ +--- +!foo "bar" diff --git a/_test/data/spec-07-08.canonical b/_test/data/spec-07-08.canonical new file mode 100644 index 0000000..703aa7b --- /dev/null +++ b/_test/data/spec-07-08.canonical @@ -0,0 +1,7 @@ +%YAML 1.1 +--- +!!seq [ + !<!foo> "bar", + !<tag:yaml.org,2002:str> "string", + !<tag:ben-kiki.org,2000:type> "baz" +] diff --git a/_test/data/spec-07-08.data b/_test/data/spec-07-08.data new file mode 100644 index 0000000..e2c6d9e --- /dev/null +++ b/_test/data/spec-07-08.data @@ -0,0 +1,9 @@ +# Explicitly specify default settings: +%TAG ! ! +%TAG !! tag:yaml.org,2002: +# Named handles have no default: +%TAG !o! tag:ben-kiki.org,2000: +--- +- !foo "bar" +- !!str "string" +- !o!type "baz" diff --git a/_test/data/spec-07-09.canonical b/_test/data/spec-07-09.canonical new file mode 100644 index 0000000..32d9e94 --- /dev/null +++ b/_test/data/spec-07-09.canonical @@ -0,0 +1,9 @@ +%YAML 1.1 +--- +!!str "foo" +%YAML 1.1 +--- +!!str "bar" +%YAML 1.1 +--- +!!str "baz" diff --git a/_test/data/spec-07-09.data b/_test/data/spec-07-09.data new file mode 100644 index 0000000..1209d47 --- /dev/null +++ b/_test/data/spec-07-09.data @@ -0,0 +1,11 @@ +--- +foo +... +# Repeated end marker. +... +--- +bar +# No end marker. +--- +baz +... diff --git a/_test/data/spec-07-10.canonical b/_test/data/spec-07-10.canonical new file mode 100644 index 0000000..1db650a --- /dev/null +++ b/_test/data/spec-07-10.canonical @@ -0,0 +1,15 @@ +%YAML 1.1 +--- +!!str "Root flow scalar" +%YAML 1.1 +--- +!!str "Root block scalar\n" +%YAML 1.1 +--- +!!map { + ? !!str "foo" + : !!str "bar" +} +--- +#!!str "" +!!null "" diff --git a/_test/data/spec-07-10.data b/_test/data/spec-07-10.data new file mode 100644 index 0000000..6939b39 --- /dev/null +++ b/_test/data/spec-07-10.data @@ -0,0 +1,11 @@ +"Root flow + scalar" +--- !!str > + Root block + scalar +--- +# Root collection: +foo : bar +... # Is optional. +--- +# Explicit document may be empty. diff --git a/_test/data/spec-07-11.data b/_test/data/spec-07-11.data new file mode 100644 index 0000000..d11302d --- /dev/null +++ b/_test/data/spec-07-11.data @@ -0,0 +1,2 @@ +# A stream may contain +# no documents. diff --git a/_test/data/spec-07-11.empty b/_test/data/spec-07-11.empty new file mode 100644 index 0000000..bfffa8b --- /dev/null +++ b/_test/data/spec-07-11.empty @@ -0,0 +1,2 @@ +# This stream contains no +# documents, only comments. diff --git a/_test/data/spec-07-12a.canonical b/_test/data/spec-07-12a.canonical new file mode 100644 index 0000000..efc116f --- /dev/null +++ b/_test/data/spec-07-12a.canonical @@ -0,0 +1,6 @@ +%YAML 1.1 +--- +!!map { + ? !!str "foo" + : !!str "bar" +} diff --git a/_test/data/spec-07-12a.data b/_test/data/spec-07-12a.data new file mode 100644 index 0000000..3807d57 --- /dev/null +++ b/_test/data/spec-07-12a.data @@ -0,0 +1,3 @@ +# Implicit document. Root +# collection (mapping) node. +foo : bar diff --git a/_test/data/spec-07-12b.canonical b/_test/data/spec-07-12b.canonical new file mode 100644 index 0000000..04bcffc --- /dev/null +++ b/_test/data/spec-07-12b.canonical @@ -0,0 +1,3 @@ +%YAML 1.1 +--- +!!str "Text content\n" diff --git a/_test/data/spec-07-12b.data b/_test/data/spec-07-12b.data new file mode 100644 index 0000000..43250db --- /dev/null +++ b/_test/data/spec-07-12b.data @@ -0,0 +1,4 @@ +# Explicit document. Root +# scalar (literal) node. +--- | + Text content diff --git a/_test/data/spec-07-13.canonical b/_test/data/spec-07-13.canonical new file mode 100644 index 0000000..5af71e9 --- /dev/null +++ b/_test/data/spec-07-13.canonical @@ -0,0 +1,9 @@ +%YAML 1.1 +--- +!!str "First document" +--- +!<!foo> "No directives" +--- +!<!foobar> "With directives" +--- +!<!baz> "Reset settings" diff --git a/_test/data/spec-07-13.data b/_test/data/spec-07-13.data new file mode 100644 index 0000000..ba7ec63 --- /dev/null +++ b/_test/data/spec-07-13.data @@ -0,0 +1,9 @@ +! "First document" +--- +!foo "No directives" +%TAG ! !foo +--- +!bar "With directives" +%YAML 1.1 +--- +!baz "Reset settings" diff --git a/_test/data/spec-08-01.canonical b/_test/data/spec-08-01.canonical new file mode 100644 index 0000000..69e4161 --- /dev/null +++ b/_test/data/spec-08-01.canonical @@ -0,0 +1,8 @@ +%YAML 1.1 +--- +!!map { + ? &A1 !!str "foo" + : !!str "bar", + ? &A2 !!str "baz" + : *A1 +} diff --git a/_test/data/spec-08-01.data b/_test/data/spec-08-01.data new file mode 100644 index 0000000..48986ec --- /dev/null +++ b/_test/data/spec-08-01.data @@ -0,0 +1,2 @@ +!!str &a1 "foo" : !!str bar +&a2 baz : *a1 diff --git a/_test/data/spec-08-02.canonical b/_test/data/spec-08-02.canonical new file mode 100644 index 0000000..dd6f76e --- /dev/null +++ b/_test/data/spec-08-02.canonical @@ -0,0 +1,8 @@ +%YAML 1.1 +--- +!!map { + ? !!str "First occurrence" + : &A !!str "Value", + ? !!str "Second occurrence" + : *A +} diff --git a/_test/data/spec-08-02.data b/_test/data/spec-08-02.data new file mode 100644 index 0000000..600d179 --- /dev/null +++ b/_test/data/spec-08-02.data @@ -0,0 +1,2 @@ +First occurrence: &anchor Value +Second occurrence: *anchor diff --git a/_test/data/spec-08-03.canonical b/_test/data/spec-08-03.canonical new file mode 100644 index 0000000..be7ea8f --- /dev/null +++ b/_test/data/spec-08-03.canonical @@ -0,0 +1,6 @@ +%YAML 1.1 +--- +!!map { + ? !<tag:yaml.org,2002:str> "foo" + : !<!bar> "baz" +} diff --git a/_test/data/spec-08-03.data b/_test/data/spec-08-03.data new file mode 100644 index 0000000..8e51f52 --- /dev/null +++ b/_test/data/spec-08-03.data @@ -0,0 +1,2 @@ +!<tag:yaml.org,2002:str> foo : + !<!bar> baz diff --git a/_test/data/spec-08-04.data b/_test/data/spec-08-04.data new file mode 100644 index 0000000..f7d1b01 --- /dev/null +++ b/_test/data/spec-08-04.data @@ -0,0 +1,2 @@ +- !<!> foo +- !<$:?> bar diff --git a/_test/data/spec-08-04.error b/_test/data/spec-08-04.error new file mode 100644 index 0000000..6066375 --- /dev/null +++ b/_test/data/spec-08-04.error @@ -0,0 +1,6 @@ +ERROR: +- Verbatim tags aren't resolved, + so ! is invalid. +- The $:? tag is neither a global + URI tag nor a local tag starting + with “!â€. diff --git a/_test/data/spec-08-05.canonical b/_test/data/spec-08-05.canonical new file mode 100644 index 0000000..a5c710a --- /dev/null +++ b/_test/data/spec-08-05.canonical @@ -0,0 +1,7 @@ +%YAML 1.1 +--- +!!seq [ + !<!local> "foo", + !<tag:yaml.org,2002:str> "bar", + !<tag:ben-kiki.org,2000:type> "baz", +] diff --git a/_test/data/spec-08-05.data b/_test/data/spec-08-05.data new file mode 100644 index 0000000..93576ed --- /dev/null +++ b/_test/data/spec-08-05.data @@ -0,0 +1,5 @@ +%TAG !o! tag:ben-kiki.org,2000: +--- +- !local foo +- !!str bar +- !o!type baz diff --git a/_test/data/spec-08-06.data b/_test/data/spec-08-06.data new file mode 100644 index 0000000..8580010 --- /dev/null +++ b/_test/data/spec-08-06.data @@ -0,0 +1,5 @@ +%TAG !o! tag:ben-kiki.org,2000: +--- +- !$a!b foo +- !o! bar +- !h!type baz diff --git a/_test/data/spec-08-06.error b/_test/data/spec-08-06.error new file mode 100644 index 0000000..fb76f42 --- /dev/null +++ b/_test/data/spec-08-06.error @@ -0,0 +1,4 @@ +ERROR: +- The !$a! looks like a handle. +- The !o! handle has no suffix. +- The !h! handle wasn't declared. diff --git a/_test/data/spec-08-07.canonical b/_test/data/spec-08-07.canonical new file mode 100644 index 0000000..e2f43d9 --- /dev/null +++ b/_test/data/spec-08-07.canonical @@ -0,0 +1,8 @@ +%YAML 1.1 +--- +!!seq [ + !<tag:yaml.org,2002:str> "12", + !<tag:yaml.org,2002:int> "12", +# !<tag:yaml.org,2002:str> "12", + !<tag:yaml.org,2002:int> "12", +] diff --git a/_test/data/spec-08-07.data b/_test/data/spec-08-07.data new file mode 100644 index 0000000..98aa565 --- /dev/null +++ b/_test/data/spec-08-07.data @@ -0,0 +1,4 @@ +# Assuming conventional resolution: +- "12" +- 12 +- ! 12 diff --git a/_test/data/spec-08-08.canonical b/_test/data/spec-08-08.canonical new file mode 100644 index 0000000..d3f8b1a --- /dev/null +++ b/_test/data/spec-08-08.canonical @@ -0,0 +1,15 @@ +%YAML 1.1 +--- +!!map { + ? !!str "foo" + : !!str "bar baz" +} +%YAML 1.1 +--- +!!str "foo bar" +%YAML 1.1 +--- +!!str "foo bar" +%YAML 1.1 +--- +!!str "foo\n" diff --git a/_test/data/spec-08-08.data b/_test/data/spec-08-08.data new file mode 100644 index 0000000..757a93d --- /dev/null +++ b/_test/data/spec-08-08.data @@ -0,0 +1,13 @@ +--- +foo: + "bar + baz" +--- +"foo + bar" +--- +foo + bar +--- | + foo +... diff --git a/_test/data/spec-08-09.canonical b/_test/data/spec-08-09.canonical new file mode 100644 index 0000000..3805daf --- /dev/null +++ b/_test/data/spec-08-09.canonical @@ -0,0 +1,21 @@ +%YAML 1.1 +--- !!map { + ? !!str "scalars" : !!map { + ? !!str "plain" + : !!str "some text", + ? !!str "quoted" + : !!map { + ? !!str "single" + : !!str "some text", + ? !!str "double" + : !!str "some text" + } }, + ? !!str "collections" : !!map { + ? !!str "sequence" : !!seq [ + !!str "entry", + !!map { + ? !!str "key" : !!str "value" + } ], + ? !!str "mapping" : !!map { + ? !!str "key" : !!str "value" +} } } diff --git a/_test/data/spec-08-09.data b/_test/data/spec-08-09.data new file mode 100644 index 0000000..69da042 --- /dev/null +++ b/_test/data/spec-08-09.data @@ -0,0 +1,11 @@ +--- +scalars: + plain: !!str some text + quoted: + single: 'some text' + double: "some text" +collections: + sequence: !!seq [ !!str entry, + # Mapping entry: + key: value ] + mapping: { key: value } diff --git a/_test/data/spec-08-10.canonical b/_test/data/spec-08-10.canonical new file mode 100644 index 0000000..8281c5e --- /dev/null +++ b/_test/data/spec-08-10.canonical @@ -0,0 +1,23 @@ +%YAML 1.1 +--- +!!map { + ? !!str "block styles" : !!map { + ? !!str "scalars" : !!map { + ? !!str "literal" + : !!str "#!/usr/bin/perl\n\ + print \"Hello, + world!\\n\";\n", + ? !!str "folded" + : !!str "This sentence + is false.\n" + }, + ? !!str "collections" : !!map { + ? !!str "sequence" : !!seq [ + !!str "entry", + !!map { + ? !!str "key" : !!str "value" + } + ], + ? !!str "mapping" : !!map { + ? !!str "key" : !!str "value" +} } } } diff --git a/_test/data/spec-08-10.data b/_test/data/spec-08-10.data new file mode 100644 index 0000000..72acc56 --- /dev/null +++ b/_test/data/spec-08-10.data @@ -0,0 +1,15 @@ +block styles: + scalars: + literal: !!str | + #!/usr/bin/perl + print "Hello, world!\n"; + folded: > + This sentence + is false. + collections: !!map + sequence: !!seq # Entry: + - entry # Plain + # Mapping entry: + - key: value + mapping: + key: value diff --git a/_test/data/spec-08-11.canonical b/_test/data/spec-08-11.canonical new file mode 100644 index 0000000..dd6f76e --- /dev/null +++ b/_test/data/spec-08-11.canonical @@ -0,0 +1,8 @@ +%YAML 1.1 +--- +!!map { + ? !!str "First occurrence" + : &A !!str "Value", + ? !!str "Second occurrence" + : *A +} diff --git a/_test/data/spec-08-11.data b/_test/data/spec-08-11.data new file mode 100644 index 0000000..600d179 --- /dev/null +++ b/_test/data/spec-08-11.data @@ -0,0 +1,2 @@ +First occurrence: &anchor Value +Second occurrence: *anchor diff --git a/_test/data/spec-08-12.canonical b/_test/data/spec-08-12.canonical new file mode 100644 index 0000000..93899f4 --- /dev/null +++ b/_test/data/spec-08-12.canonical @@ -0,0 +1,10 @@ +%YAML 1.1 +--- +!!seq [ + !!str "Without properties", + &A !!str "Anchored", + !!str "Tagged", + *A, + !!str "", + !!str "", +] diff --git a/_test/data/spec-08-12.data b/_test/data/spec-08-12.data new file mode 100644 index 0000000..3d4c6b7 --- /dev/null +++ b/_test/data/spec-08-12.data @@ -0,0 +1,8 @@ +[ + Without properties, + &anchor "Anchored", + !!str 'Tagged', + *anchor, # Alias node + !!str , # Empty plain scalar + '', # Empty plain scalar +] diff --git a/_test/data/spec-08-13.canonical b/_test/data/spec-08-13.canonical new file mode 100644 index 0000000..618bb7b --- /dev/null +++ b/_test/data/spec-08-13.canonical @@ -0,0 +1,10 @@ +%YAML 1.1 +--- +!!map { + ? !!str "foo" +# : !!str "", +# ? !!str "" + : !!null "", + ? !!null "" + : !!str "bar", +} diff --git a/_test/data/spec-08-13.data b/_test/data/spec-08-13.data new file mode 100644 index 0000000..ebe663a --- /dev/null +++ b/_test/data/spec-08-13.data @@ -0,0 +1,4 @@ +{ + ? foo :, + ? : bar, +} diff --git a/_test/data/spec-08-13.skip-ext b/_test/data/spec-08-13.skip-ext new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/_test/data/spec-08-13.skip-ext diff --git a/_test/data/spec-08-14.canonical b/_test/data/spec-08-14.canonical new file mode 100644 index 0000000..11db439 --- /dev/null +++ b/_test/data/spec-08-14.canonical @@ -0,0 +1,10 @@ +%YAML 1.1 +--- +!!seq [ + !!str "flow in block", + !!str "Block scalar\n", + !!map { + ? !!str "foo" + : !!str "bar" + } +] diff --git a/_test/data/spec-08-14.data b/_test/data/spec-08-14.data new file mode 100644 index 0000000..2fbb1f7 --- /dev/null +++ b/_test/data/spec-08-14.data @@ -0,0 +1,5 @@ +- "flow in block" +- > + Block scalar +- !!map # Block collection + foo : bar diff --git a/_test/data/spec-08-15.canonical b/_test/data/spec-08-15.canonical new file mode 100644 index 0000000..76f028e --- /dev/null +++ b/_test/data/spec-08-15.canonical @@ -0,0 +1,11 @@ +%YAML 1.1 +--- +!!seq [ + !!null "", + !!map { + ? !!str "foo" + : !!null "", + ? !!null "" + : !!str "bar", + } +] diff --git a/_test/data/spec-08-15.data b/_test/data/spec-08-15.data new file mode 100644 index 0000000..7c86bcf --- /dev/null +++ b/_test/data/spec-08-15.data @@ -0,0 +1,5 @@ +- # Empty plain scalar +- ? foo + : + ? + : bar diff --git a/_test/data/spec-09-01.canonical b/_test/data/spec-09-01.canonical new file mode 100644 index 0000000..e71a548 --- /dev/null +++ b/_test/data/spec-09-01.canonical @@ -0,0 +1,11 @@ +%YAML 1.1 +--- +!!map { + ? !!str "simple key" + : !!map { + ? !!str "also simple" + : !!str "value", + ? !!str "not a simple key" + : !!str "any value" + } +} diff --git a/_test/data/spec-09-01.data b/_test/data/spec-09-01.data new file mode 100644 index 0000000..9e83eaf --- /dev/null +++ b/_test/data/spec-09-01.data @@ -0,0 +1,6 @@ +"simple key" : { + "also simple" : value, + ? "not a + simple key" : "any + value" +} diff --git a/_test/data/spec-09-02.canonical b/_test/data/spec-09-02.canonical new file mode 100644 index 0000000..6f8f41a --- /dev/null +++ b/_test/data/spec-09-02.canonical @@ -0,0 +1,7 @@ +%YAML 1.1 +--- +!!str "as space \ + trimmed\n\ + specific\L\n\ + escaped\t\n\ + none" diff --git a/_test/data/spec-09-02.data b/_test/data/spec-09-02.data new file mode 100644 index 0000000..d84883d --- /dev/null +++ b/_test/data/spec-09-02.data @@ -0,0 +1,6 @@ + "as space + trimmed + + specific
 + escaped \
 + none" diff --git a/_test/data/spec-09-03.canonical b/_test/data/spec-09-03.canonical new file mode 100644 index 0000000..658c6df --- /dev/null +++ b/_test/data/spec-09-03.canonical @@ -0,0 +1,7 @@ +%YAML 1.1 +--- +!!seq [ + !!str " last", + !!str " last", + !!str " \tfirst last", +] diff --git a/_test/data/spec-09-03.data b/_test/data/spec-09-03.data new file mode 100644 index 0000000..e0b914d --- /dev/null +++ b/_test/data/spec-09-03.data @@ -0,0 +1,6 @@ +- " + last" +- " + last" +- " first + last" diff --git a/_test/data/spec-09-04.canonical b/_test/data/spec-09-04.canonical new file mode 100644 index 0000000..fa46632 --- /dev/null +++ b/_test/data/spec-09-04.canonical @@ -0,0 +1,6 @@ +%YAML 1.1 +--- +!!str "first \ + inner 1 \ + inner 2 \ + last" diff --git a/_test/data/spec-09-04.data b/_test/data/spec-09-04.data new file mode 100644 index 0000000..313a91b --- /dev/null +++ b/_test/data/spec-09-04.data @@ -0,0 +1,4 @@ + "first + inner 1 + \ inner 2 \ + last" diff --git a/_test/data/spec-09-05.canonical b/_test/data/spec-09-05.canonical new file mode 100644 index 0000000..24d1052 --- /dev/null +++ b/_test/data/spec-09-05.canonical @@ -0,0 +1,7 @@ +%YAML 1.1 +--- +!!seq [ + !!str "first ", + !!str "first\nlast", + !!str "first inner \tlast", +] diff --git a/_test/data/spec-09-05.data b/_test/data/spec-09-05.data new file mode 100644 index 0000000..624c30e --- /dev/null +++ b/_test/data/spec-09-05.data @@ -0,0 +1,8 @@ +- "first + " +- "first + + last" +- "first + inner + \ last" diff --git a/_test/data/spec-09-06.canonical b/_test/data/spec-09-06.canonical new file mode 100644 index 0000000..5028772 --- /dev/null +++ b/_test/data/spec-09-06.canonical @@ -0,0 +1,3 @@ +%YAML 1.1 +--- +!!str "here's to \"quotes\"" diff --git a/_test/data/spec-09-06.data b/_test/data/spec-09-06.data new file mode 100644 index 0000000..b038078 --- /dev/null +++ b/_test/data/spec-09-06.data @@ -0,0 +1 @@ + 'here''s to "quotes"' diff --git a/_test/data/spec-09-07.canonical b/_test/data/spec-09-07.canonical new file mode 100644 index 0000000..e71a548 --- /dev/null +++ b/_test/data/spec-09-07.canonical @@ -0,0 +1,11 @@ +%YAML 1.1 +--- +!!map { + ? !!str "simple key" + : !!map { + ? !!str "also simple" + : !!str "value", + ? !!str "not a simple key" + : !!str "any value" + } +} diff --git a/_test/data/spec-09-07.data b/_test/data/spec-09-07.data new file mode 100644 index 0000000..755b54a --- /dev/null +++ b/_test/data/spec-09-07.data @@ -0,0 +1,6 @@ +'simple key' : { + 'also simple' : value, + ? 'not a + simple key' : 'any + value' +} diff --git a/_test/data/spec-09-08.canonical b/_test/data/spec-09-08.canonical new file mode 100644 index 0000000..06abdb5 --- /dev/null +++ b/_test/data/spec-09-08.canonical @@ -0,0 +1,6 @@ +%YAML 1.1 +--- +!!str "as space \ + trimmed\n\ + specific\L\n\ + none" diff --git a/_test/data/spec-09-08.data b/_test/data/spec-09-08.data new file mode 100644 index 0000000..aa4d458 --- /dev/null +++ b/_test/data/spec-09-08.data @@ -0,0 +1 @@ + 'as space Â… trimmed Â…Â… specific
… none' diff --git a/_test/data/spec-09-09.canonical b/_test/data/spec-09-09.canonical new file mode 100644 index 0000000..658c6df --- /dev/null +++ b/_test/data/spec-09-09.canonical @@ -0,0 +1,7 @@ +%YAML 1.1 +--- +!!seq [ + !!str " last", + !!str " last", + !!str " \tfirst last", +] diff --git a/_test/data/spec-09-09.data b/_test/data/spec-09-09.data new file mode 100644 index 0000000..52171df --- /dev/null +++ b/_test/data/spec-09-09.data @@ -0,0 +1,6 @@ +- ' + last' +- ' + last' +- ' first + last' diff --git a/_test/data/spec-09-10.canonical b/_test/data/spec-09-10.canonical new file mode 100644 index 0000000..2028d04 --- /dev/null +++ b/_test/data/spec-09-10.canonical @@ -0,0 +1,5 @@ +%YAML 1.1 +--- +!!str "first \ + inner \ + last" diff --git a/_test/data/spec-09-10.data b/_test/data/spec-09-10.data new file mode 100644 index 0000000..0e41449 --- /dev/null +++ b/_test/data/spec-09-10.data @@ -0,0 +1,3 @@ + 'first + inner + last' diff --git a/_test/data/spec-09-11.canonical b/_test/data/spec-09-11.canonical new file mode 100644 index 0000000..4eb222c --- /dev/null +++ b/_test/data/spec-09-11.canonical @@ -0,0 +1,6 @@ +%YAML 1.1 +--- +!!seq [ + !!str "first ", + !!str "first\nlast", +] diff --git a/_test/data/spec-09-11.data b/_test/data/spec-09-11.data new file mode 100644 index 0000000..5efa873 --- /dev/null +++ b/_test/data/spec-09-11.data @@ -0,0 +1,5 @@ +- 'first + ' +- 'first + + last' diff --git a/_test/data/spec-09-12.canonical b/_test/data/spec-09-12.canonical new file mode 100644 index 0000000..d8e6dce --- /dev/null +++ b/_test/data/spec-09-12.canonical @@ -0,0 +1,12 @@ +%YAML 1.1 +--- +!!seq [ + !!str "::std::vector", + !!str "Up, up, and away!", + !!int "-123", + !!seq [ + !!str "::std::vector", + !!str "Up, up, and away!", + !!int "-123", + ] +] diff --git a/_test/data/spec-09-12.data b/_test/data/spec-09-12.data new file mode 100644 index 0000000..b9a3ac5 --- /dev/null +++ b/_test/data/spec-09-12.data @@ -0,0 +1,8 @@ +# Outside flow collection: +- ::std::vector +- Up, up, and away! +- -123 +# Inside flow collection: +- [ '::std::vector', + "Up, up, and away!", + -123 ] diff --git a/_test/data/spec-09-13.canonical b/_test/data/spec-09-13.canonical new file mode 100644 index 0000000..e71a548 --- /dev/null +++ b/_test/data/spec-09-13.canonical @@ -0,0 +1,11 @@ +%YAML 1.1 +--- +!!map { + ? !!str "simple key" + : !!map { + ? !!str "also simple" + : !!str "value", + ? !!str "not a simple key" + : !!str "any value" + } +} diff --git a/_test/data/spec-09-13.data b/_test/data/spec-09-13.data new file mode 100644 index 0000000..b156386 --- /dev/null +++ b/_test/data/spec-09-13.data @@ -0,0 +1,6 @@ +simple key : { + also simple : value, + ? not a + simple key : any + value +} diff --git a/_test/data/spec-09-14.data b/_test/data/spec-09-14.data new file mode 100644 index 0000000..97f2316 --- /dev/null +++ b/_test/data/spec-09-14.data @@ -0,0 +1,14 @@ +--- +--- ||| : foo +... >>>: bar +--- +[ +--- +, +... , +{ +--- : +... # Nested +} +] +... diff --git a/_test/data/spec-09-14.error b/_test/data/spec-09-14.error new file mode 100644 index 0000000..9f3db7b --- /dev/null +++ b/_test/data/spec-09-14.error @@ -0,0 +1,6 @@ +ERROR: + The --- and ... document + start and end markers must + not be specified as the + first content line of a + non-indented plain scalar. diff --git a/_test/data/spec-09-15.canonical b/_test/data/spec-09-15.canonical new file mode 100644 index 0000000..df02040 --- /dev/null +++ b/_test/data/spec-09-15.canonical @@ -0,0 +1,18 @@ +%YAML 1.1 +--- +!!map { + ? !!str "---" + : !!str "foo", + ? !!str "..." + : !!str "bar" +} +%YAML 1.1 +--- +!!seq [ + !!str "---", + !!str "...", + !!map { + ? !!str "---" + : !!str "..." + } +] diff --git a/_test/data/spec-09-15.data b/_test/data/spec-09-15.data new file mode 100644 index 0000000..e6863b0 --- /dev/null +++ b/_test/data/spec-09-15.data @@ -0,0 +1,13 @@ +--- +"---" : foo +...: bar +--- +[ +---, +..., +{ +? --- +: ... +} +] +... diff --git a/_test/data/spec-09-16.canonical b/_test/data/spec-09-16.canonical new file mode 100644 index 0000000..06abdb5 --- /dev/null +++ b/_test/data/spec-09-16.canonical @@ -0,0 +1,6 @@ +%YAML 1.1 +--- +!!str "as space \ + trimmed\n\ + specific\L\n\ + none" diff --git a/_test/data/spec-09-16.data b/_test/data/spec-09-16.data new file mode 100644 index 0000000..473beb9 --- /dev/null +++ b/_test/data/spec-09-16.data @@ -0,0 +1,3 @@ +# Tabs are confusing: +# as space/trimmed/specific/none + as space Â… trimmed Â…Â… specific
… none diff --git a/_test/data/spec-09-17.canonical b/_test/data/spec-09-17.canonical new file mode 100644 index 0000000..68cb70d --- /dev/null +++ b/_test/data/spec-09-17.canonical @@ -0,0 +1,4 @@ +%YAML 1.1 +--- +!!str "first line\n\ + more line" diff --git a/_test/data/spec-09-17.data b/_test/data/spec-09-17.data new file mode 100644 index 0000000..97bc46c --- /dev/null +++ b/_test/data/spec-09-17.data @@ -0,0 +1,3 @@ + first line + + more line diff --git a/_test/data/spec-09-18.canonical b/_test/data/spec-09-18.canonical new file mode 100644 index 0000000..f21428f --- /dev/null +++ b/_test/data/spec-09-18.canonical @@ -0,0 +1,8 @@ +%YAML 1.1 +--- +!!seq [ + !!str "literal\n", + !!str " folded\n", + !!str "keep\n\n", + !!str " strip", +] diff --git a/_test/data/spec-09-18.data b/_test/data/spec-09-18.data new file mode 100644 index 0000000..68c5d7c --- /dev/null +++ b/_test/data/spec-09-18.data @@ -0,0 +1,9 @@ +- | # Just the style + literal +- >1 # Indentation indicator + folded +- |+ # Chomping indicator + keep + +- >-1 # Both indicators + strip diff --git a/_test/data/spec-09-19.canonical b/_test/data/spec-09-19.canonical new file mode 100644 index 0000000..3e828d7 --- /dev/null +++ b/_test/data/spec-09-19.canonical @@ -0,0 +1,6 @@ +%YAML 1.1 +--- +!!seq [ + !!str "literal\n", + !!str "folded\n", +] diff --git a/_test/data/spec-09-19.data b/_test/data/spec-09-19.data new file mode 100644 index 0000000..f0e589d --- /dev/null +++ b/_test/data/spec-09-19.data @@ -0,0 +1,4 @@ +- | + literal +- > + folded diff --git a/_test/data/spec-09-20.canonical b/_test/data/spec-09-20.canonical new file mode 100644 index 0000000..d03bef5 --- /dev/null +++ b/_test/data/spec-09-20.canonical @@ -0,0 +1,8 @@ +%YAML 1.1 +--- +!!seq [ + !!str "detected\n", + !!str "\n\n# detected\n", + !!str " explicit\n", + !!str "\t\ndetected\n", +] diff --git a/_test/data/spec-09-20.data b/_test/data/spec-09-20.data new file mode 100644 index 0000000..39bee04 --- /dev/null +++ b/_test/data/spec-09-20.data @@ -0,0 +1,11 @@ +- | + detected +- > + + + # detected +- |1 + explicit +- > + + detected diff --git a/_test/data/spec-09-20.skip-ext b/_test/data/spec-09-20.skip-ext new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/_test/data/spec-09-20.skip-ext diff --git a/_test/data/spec-09-21.data b/_test/data/spec-09-21.data new file mode 100644 index 0000000..0fdd14f --- /dev/null +++ b/_test/data/spec-09-21.data @@ -0,0 +1,8 @@ +- | + + text +- > + text + text +- |1 + text diff --git a/_test/data/spec-09-21.error b/_test/data/spec-09-21.error new file mode 100644 index 0000000..1379ca5 --- /dev/null +++ b/_test/data/spec-09-21.error @@ -0,0 +1,7 @@ +ERROR: +- A leading all-space line must + not have too many spaces. +- A following text line must + not be less indented. +- The text is less indented + than the indicated level. diff --git a/_test/data/spec-09-22.canonical b/_test/data/spec-09-22.canonical new file mode 100644 index 0000000..c1bbcd2 --- /dev/null +++ b/_test/data/spec-09-22.canonical @@ -0,0 +1,10 @@ +%YAML 1.1 +--- +!!map { + ? !!str "strip" + : !!str "text", + ? !!str "clip" + : !!str "text\n", + ? !!str "keep" + : !!str "text\L", +} diff --git a/_test/data/spec-09-22.data b/_test/data/spec-09-22.data new file mode 100644 index 0000000..0dd51eb --- /dev/null +++ b/_test/data/spec-09-22.data @@ -0,0 +1,4 @@ +strip: |- + text
clip: | + textÂ…keep: |+ + text

\ No newline at end of file diff --git a/_test/data/spec-09-23.canonical b/_test/data/spec-09-23.canonical new file mode 100644 index 0000000..c4444ca --- /dev/null +++ b/_test/data/spec-09-23.canonical @@ -0,0 +1,10 @@ +%YAML 1.1 +--- +!!map { + ? !!str "strip" + : !!str "# text", + ? !!str "clip" + : !!str "# text\n", + ? !!str "keep" + : !!str "# text\L\n", +} diff --git a/_test/data/spec-09-23.data b/_test/data/spec-09-23.data new file mode 100644 index 0000000..8972d2b --- /dev/null +++ b/_test/data/spec-09-23.data @@ -0,0 +1,11 @@ + # Strip + # Comments: +strip: |- + # text
 
 # Clip + # comments: +Â…clip: | + # textÂ… 
 # Keep + # comments: +Â…keep: |+ + # text
… # Trail + # comments. diff --git a/_test/data/spec-09-24.canonical b/_test/data/spec-09-24.canonical new file mode 100644 index 0000000..45a99b0 --- /dev/null +++ b/_test/data/spec-09-24.canonical @@ -0,0 +1,10 @@ +%YAML 1.1 +--- +!!map { + ? !!str "strip" + : !!str "", + ? !!str "clip" + : !!str "", + ? !!str "keep" + : !!str "\n", +} diff --git a/_test/data/spec-09-24.data b/_test/data/spec-09-24.data new file mode 100644 index 0000000..de0b64b --- /dev/null +++ b/_test/data/spec-09-24.data @@ -0,0 +1,6 @@ +strip: >- + +clip: > + +keep: |+ + diff --git a/_test/data/spec-09-25.canonical b/_test/data/spec-09-25.canonical new file mode 100644 index 0000000..9d2327b --- /dev/null +++ b/_test/data/spec-09-25.canonical @@ -0,0 +1,4 @@ +%YAML 1.1 +--- +!!str "literal\n\ + \ttext\n" diff --git a/_test/data/spec-09-25.data b/_test/data/spec-09-25.data new file mode 100644 index 0000000..f6303a1 --- /dev/null +++ b/_test/data/spec-09-25.data @@ -0,0 +1,3 @@ +| # Simple block scalar + literal + text diff --git a/_test/data/spec-09-26.canonical b/_test/data/spec-09-26.canonical new file mode 100644 index 0000000..3029a11 --- /dev/null +++ b/_test/data/spec-09-26.canonical @@ -0,0 +1,3 @@ +%YAML 1.1 +--- +!!str "\n\nliteral\n\ntext\n" diff --git a/_test/data/spec-09-26.data b/_test/data/spec-09-26.data new file mode 100644 index 0000000..f28555a --- /dev/null +++ b/_test/data/spec-09-26.data @@ -0,0 +1,8 @@ +| + + + literal + + text + + # Comment diff --git a/_test/data/spec-09-27.canonical b/_test/data/spec-09-27.canonical new file mode 100644 index 0000000..3029a11 --- /dev/null +++ b/_test/data/spec-09-27.canonical @@ -0,0 +1,3 @@ +%YAML 1.1 +--- +!!str "\n\nliteral\n\ntext\n" diff --git a/_test/data/spec-09-27.data b/_test/data/spec-09-27.data new file mode 100644 index 0000000..f28555a --- /dev/null +++ b/_test/data/spec-09-27.data @@ -0,0 +1,8 @@ +| + + + literal + + text + + # Comment diff --git a/_test/data/spec-09-28.canonical b/_test/data/spec-09-28.canonical new file mode 100644 index 0000000..3029a11 --- /dev/null +++ b/_test/data/spec-09-28.canonical @@ -0,0 +1,3 @@ +%YAML 1.1 +--- +!!str "\n\nliteral\n\ntext\n" diff --git a/_test/data/spec-09-28.data b/_test/data/spec-09-28.data new file mode 100644 index 0000000..f28555a --- /dev/null +++ b/_test/data/spec-09-28.data @@ -0,0 +1,8 @@ +| + + + literal + + text + + # Comment diff --git a/_test/data/spec-09-29.canonical b/_test/data/spec-09-29.canonical new file mode 100644 index 0000000..0980789 --- /dev/null +++ b/_test/data/spec-09-29.canonical @@ -0,0 +1,4 @@ +%YAML 1.1 +--- +!!str "folded text\n\ + \tlines\n" diff --git a/_test/data/spec-09-29.data b/_test/data/spec-09-29.data new file mode 100644 index 0000000..82e611f --- /dev/null +++ b/_test/data/spec-09-29.data @@ -0,0 +1,4 @@ +> # Simple folded scalar + folded + text + lines diff --git a/_test/data/spec-09-30.canonical b/_test/data/spec-09-30.canonical new file mode 100644 index 0000000..fc37db1 --- /dev/null +++ b/_test/data/spec-09-30.canonical @@ -0,0 +1,7 @@ +%YAML 1.1 +--- +!!str "folded line\n\ + next line\n\n\ + \ * bullet\n\ + \ * list\n\n\ + last line\n" diff --git a/_test/data/spec-09-30.data b/_test/data/spec-09-30.data new file mode 100644 index 0000000..a4d8c36 --- /dev/null +++ b/_test/data/spec-09-30.data @@ -0,0 +1,14 @@ +> + folded + line + + next + line + + * bullet + * list + + last + line + +# Comment diff --git a/_test/data/spec-09-31.canonical b/_test/data/spec-09-31.canonical new file mode 100644 index 0000000..fc37db1 --- /dev/null +++ b/_test/data/spec-09-31.canonical @@ -0,0 +1,7 @@ +%YAML 1.1 +--- +!!str "folded line\n\ + next line\n\n\ + \ * bullet\n\ + \ * list\n\n\ + last line\n" diff --git a/_test/data/spec-09-31.data b/_test/data/spec-09-31.data new file mode 100644 index 0000000..a4d8c36 --- /dev/null +++ b/_test/data/spec-09-31.data @@ -0,0 +1,14 @@ +> + folded + line + + next + line + + * bullet + * list + + last + line + +# Comment diff --git a/_test/data/spec-09-32.canonical b/_test/data/spec-09-32.canonical new file mode 100644 index 0000000..fc37db1 --- /dev/null +++ b/_test/data/spec-09-32.canonical @@ -0,0 +1,7 @@ +%YAML 1.1 +--- +!!str "folded line\n\ + next line\n\n\ + \ * bullet\n\ + \ * list\n\n\ + last line\n" diff --git a/_test/data/spec-09-32.data b/_test/data/spec-09-32.data new file mode 100644 index 0000000..a4d8c36 --- /dev/null +++ b/_test/data/spec-09-32.data @@ -0,0 +1,14 @@ +> + folded + line + + next + line + + * bullet + * list + + last + line + +# Comment diff --git a/_test/data/spec-09-33.canonical b/_test/data/spec-09-33.canonical new file mode 100644 index 0000000..fc37db1 --- /dev/null +++ b/_test/data/spec-09-33.canonical @@ -0,0 +1,7 @@ +%YAML 1.1 +--- +!!str "folded line\n\ + next line\n\n\ + \ * bullet\n\ + \ * list\n\n\ + last line\n" diff --git a/_test/data/spec-09-33.data b/_test/data/spec-09-33.data new file mode 100644 index 0000000..a4d8c36 --- /dev/null +++ b/_test/data/spec-09-33.data @@ -0,0 +1,14 @@ +> + folded + line + + next + line + + * bullet + * list + + last + line + +# Comment diff --git a/_test/data/spec-10-01.canonical b/_test/data/spec-10-01.canonical new file mode 100644 index 0000000..d08cdd4 --- /dev/null +++ b/_test/data/spec-10-01.canonical @@ -0,0 +1,12 @@ +%YAML 1.1 +--- +!!seq [ + !!seq [ + !!str "inner", + !!str "inner", + ], + !!seq [ + !!str "inner", + !!str "last", + ], +] diff --git a/_test/data/spec-10-01.data b/_test/data/spec-10-01.data new file mode 100644 index 0000000..e668d38 --- /dev/null +++ b/_test/data/spec-10-01.data @@ -0,0 +1,2 @@ +- [ inner, inner, ] +- [inner,last] diff --git a/_test/data/spec-10-02.canonical b/_test/data/spec-10-02.canonical new file mode 100644 index 0000000..82fe0d9 --- /dev/null +++ b/_test/data/spec-10-02.canonical @@ -0,0 +1,14 @@ +%YAML 1.1 +--- +!!seq [ + !!str "double quoted", + !!str "single quoted", + !!str "plain text", + !!seq [ + !!str "nested", + ], + !!map { + ? !!str "single" + : !!str "pair" + } +] diff --git a/_test/data/spec-10-02.data b/_test/data/spec-10-02.data new file mode 100644 index 0000000..3b23351 --- /dev/null +++ b/_test/data/spec-10-02.data @@ -0,0 +1,8 @@ +[ +"double + quoted", 'single + quoted', +plain + text, [ nested ], +single: pair , +] diff --git a/_test/data/spec-10-03.canonical b/_test/data/spec-10-03.canonical new file mode 100644 index 0000000..1443395 --- /dev/null +++ b/_test/data/spec-10-03.canonical @@ -0,0 +1,12 @@ +%YAML 1.1 +--- +!!map { + ? !!str "block" + : !!seq [ + !!str "one", + !!map { + ? !!str "two" + : !!str "three" + } + ] +} diff --git a/_test/data/spec-10-03.data b/_test/data/spec-10-03.data new file mode 100644 index 0000000..9e15f83 --- /dev/null +++ b/_test/data/spec-10-03.data @@ -0,0 +1,4 @@ +block: # Block + # sequence +- one +- two : three diff --git a/_test/data/spec-10-04.canonical b/_test/data/spec-10-04.canonical new file mode 100644 index 0000000..ae486a3 --- /dev/null +++ b/_test/data/spec-10-04.canonical @@ -0,0 +1,11 @@ +%YAML 1.1 +--- +!!map { + ? !!str "block" + : !!seq [ + !!str "one", + !!seq [ + !!str "two" + ] + ] +} diff --git a/_test/data/spec-10-04.data b/_test/data/spec-10-04.data new file mode 100644 index 0000000..2905b0d --- /dev/null +++ b/_test/data/spec-10-04.data @@ -0,0 +1,4 @@ +block: +- one +- + - two diff --git a/_test/data/spec-10-05.canonical b/_test/data/spec-10-05.canonical new file mode 100644 index 0000000..07cc0c9 --- /dev/null +++ b/_test/data/spec-10-05.canonical @@ -0,0 +1,14 @@ +%YAML 1.1 +--- +!!seq [ + !!null "", + !!str "block node\n", + !!seq [ + !!str "one", + !!str "two", + ], + !!map { + ? !!str "one" + : !!str "two", + } +] diff --git a/_test/data/spec-10-05.data b/_test/data/spec-10-05.data new file mode 100644 index 0000000..f19a99e --- /dev/null +++ b/_test/data/spec-10-05.data @@ -0,0 +1,7 @@ +- # Empty +- | + block node +- - one # in-line + - two # sequence +- one: two # in-line + # mapping diff --git a/_test/data/spec-10-06.canonical b/_test/data/spec-10-06.canonical new file mode 100644 index 0000000..d9986c2 --- /dev/null +++ b/_test/data/spec-10-06.canonical @@ -0,0 +1,16 @@ +%YAML 1.1 +--- +!!seq [ + !!map { + ? !!str "inner" + : !!str "entry", + ? !!str "also" + : !!str "inner" + }, + !!map { + ? !!str "inner" + : !!str "entry", + ? !!str "last" + : !!str "entry" + } +] diff --git a/_test/data/spec-10-06.data b/_test/data/spec-10-06.data new file mode 100644 index 0000000..860ba25 --- /dev/null +++ b/_test/data/spec-10-06.data @@ -0,0 +1,2 @@ +- { inner : entry , also: inner , } +- {inner: entry,last : entry} diff --git a/_test/data/spec-10-07.canonical b/_test/data/spec-10-07.canonical new file mode 100644 index 0000000..ec74230 --- /dev/null +++ b/_test/data/spec-10-07.canonical @@ -0,0 +1,16 @@ +%YAML 1.1 +--- +!!map { + ? !!null "" + : !!str "value", + ? !!str "explicit key" + : !!str "value", + ? !!str "simple key" + : !!str "value", + ? !!seq [ + !!str "collection", + !!str "simple", + !!str "key" + ] + : !!str "value" +} diff --git a/_test/data/spec-10-07.data b/_test/data/spec-10-07.data new file mode 100644 index 0000000..ff943fb --- /dev/null +++ b/_test/data/spec-10-07.data @@ -0,0 +1,7 @@ +{ +? : value, # Empty key +? explicit + key: value, +simple key : value, +[ collection, simple, key ]: value +} diff --git a/_test/data/spec-10-08.data b/_test/data/spec-10-08.data new file mode 100644 index 0000000..55bd788 --- /dev/null +++ b/_test/data/spec-10-08.data @@ -0,0 +1,5 @@ +{ +multi-line + simple key : value, +very long ...................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................(>1KB)................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................... key: value +} diff --git a/_test/data/spec-10-08.error b/_test/data/spec-10-08.error new file mode 100644 index 0000000..3979e1f --- /dev/null +++ b/_test/data/spec-10-08.error @@ -0,0 +1,5 @@ +ERROR: +- A simple key is restricted + to only one line. +- A simple key must not be + longer than 1024 characters. diff --git a/_test/data/spec-10-09.canonical b/_test/data/spec-10-09.canonical new file mode 100644 index 0000000..4d9827b --- /dev/null +++ b/_test/data/spec-10-09.canonical @@ -0,0 +1,8 @@ +%YAML 1.1 +--- +!!map { + ? !!str "key" + : !!str "value", + ? !!str "empty" + : !!null "", +} diff --git a/_test/data/spec-10-09.data b/_test/data/spec-10-09.data new file mode 100644 index 0000000..4d55e21 --- /dev/null +++ b/_test/data/spec-10-09.data @@ -0,0 +1,4 @@ +{ +key : value, +empty: # empty value↓ +} diff --git a/_test/data/spec-10-10.canonical b/_test/data/spec-10-10.canonical new file mode 100644 index 0000000..016fb64 --- /dev/null +++ b/_test/data/spec-10-10.canonical @@ -0,0 +1,16 @@ +%YAML 1.1 +--- +!!map { + ? !!str "explicit key1" + : !!str "explicit value", + ? !!str "explicit key2" + : !!null "", + ? !!str "explicit key3" + : !!null "", + ? !!str "simple key1" + : !!str "explicit value", + ? !!str "simple key2" + : !!null "", + ? !!str "simple key3" + : !!null "", +} diff --git a/_test/data/spec-10-10.data b/_test/data/spec-10-10.data new file mode 100644 index 0000000..0888b05 --- /dev/null +++ b/_test/data/spec-10-10.data @@ -0,0 +1,8 @@ +{ +? explicit key1 : explicit value, +? explicit key2 : , # Explicit empty +? explicit key3, # Empty value +simple key1 : explicit value, +simple key2 : , # Explicit empty +simple key3, # Empty value +} diff --git a/_test/data/spec-10-11.canonical b/_test/data/spec-10-11.canonical new file mode 100644 index 0000000..7309544 --- /dev/null +++ b/_test/data/spec-10-11.canonical @@ -0,0 +1,24 @@ +%YAML 1.1 +--- +!!seq [ + !!map { + ? !!str "explicit key1" + : !!str "explicit value", + }, + !!map { + ? !!str "explicit key2" + : !!null "", + }, + !!map { + ? !!str "explicit key3" + : !!null "", + }, + !!map { + ? !!str "simple key1" + : !!str "explicit value", + }, + !!map { + ? !!str "simple key2" + : !!null "", + }, +] diff --git a/_test/data/spec-10-11.data b/_test/data/spec-10-11.data new file mode 100644 index 0000000..9f05568 --- /dev/null +++ b/_test/data/spec-10-11.data @@ -0,0 +1,7 @@ +[ +? explicit key1 : explicit value, +? explicit key2 : , # Explicit empty +? explicit key3, # Implicit empty +simple key1 : explicit value, +simple key2 : , # Explicit empty +] diff --git a/_test/data/spec-10-12.canonical b/_test/data/spec-10-12.canonical new file mode 100644 index 0000000..a95dd40 --- /dev/null +++ b/_test/data/spec-10-12.canonical @@ -0,0 +1,9 @@ +%YAML 1.1 +--- +!!map { + ? !!str "block" + : !!map { + ? !!str "key" + : !!str "value" + } +} diff --git a/_test/data/spec-10-12.data b/_test/data/spec-10-12.data new file mode 100644 index 0000000..5521443 --- /dev/null +++ b/_test/data/spec-10-12.data @@ -0,0 +1,3 @@ +block: # Block + # mapping + key: value diff --git a/_test/data/spec-10-13.canonical b/_test/data/spec-10-13.canonical new file mode 100644 index 0000000..e183c50 --- /dev/null +++ b/_test/data/spec-10-13.canonical @@ -0,0 +1,11 @@ +%YAML 1.1 +--- +!!map { + ? !!str "explicit key" + : !!null "", + ? !!str "block key\n" + : !!seq [ + !!str "one", + !!str "two", + ] +} diff --git a/_test/data/spec-10-13.data b/_test/data/spec-10-13.data new file mode 100644 index 0000000..b5b97db --- /dev/null +++ b/_test/data/spec-10-13.data @@ -0,0 +1,5 @@ +? explicit key # implicit value +? | + block key +: - one # explicit in-line + - two # block value diff --git a/_test/data/spec-10-14.canonical b/_test/data/spec-10-14.canonical new file mode 100644 index 0000000..e87c880 --- /dev/null +++ b/_test/data/spec-10-14.canonical @@ -0,0 +1,11 @@ +%YAML 1.1 +--- +!!map { + ? !!str "plain key" + : !!null "", + ? !!str "quoted key" + : !!seq [ + !!str "one", + !!str "two", + ] +} diff --git a/_test/data/spec-10-14.data b/_test/data/spec-10-14.data new file mode 100644 index 0000000..7f5995c --- /dev/null +++ b/_test/data/spec-10-14.data @@ -0,0 +1,4 @@ +plain key: # empty value +"quoted key": +- one # explicit next-line +- two # block value diff --git a/_test/data/spec-10-15.canonical b/_test/data/spec-10-15.canonical new file mode 100644 index 0000000..85fbbd0 --- /dev/null +++ b/_test/data/spec-10-15.canonical @@ -0,0 +1,18 @@ +%YAML 1.1 +--- +!!seq [ + !!map { + ? !!str "sun" + : !!str "yellow" + }, + !!map { + ? !!map { + ? !!str "earth" + : !!str "blue" + } + : !!map { + ? !!str "moon" + : !!str "white" + } + } +] diff --git a/_test/data/spec-10-15.data b/_test/data/spec-10-15.data new file mode 100644 index 0000000..d675cfd --- /dev/null +++ b/_test/data/spec-10-15.data @@ -0,0 +1,3 @@ +- sun: yellow +- ? earth: blue + : moon: white diff --git a/_test/data/str.data b/_test/data/str.data new file mode 100644 index 0000000..7cbdb7c --- /dev/null +++ b/_test/data/str.data @@ -0,0 +1 @@ +- abcd diff --git a/_test/data/str.detect b/_test/data/str.detect new file mode 100644 index 0000000..7d5026f --- /dev/null +++ b/_test/data/str.detect @@ -0,0 +1 @@ +tag:yaml.org,2002:str diff --git a/_test/data/tags.events b/_test/data/tags.events new file mode 100644 index 0000000..bb93dce --- /dev/null +++ b/_test/data/tags.events @@ -0,0 +1,12 @@ +- !StreamStart +- !DocumentStart +- !SequenceStart +- !Scalar { value: 'data' } +#- !Scalar { tag: '!', value: 'data' } +- !Scalar { tag: 'tag:yaml.org,2002:str', value: 'data' } +- !Scalar { tag: '!myfunnytag', value: 'data' } +- !Scalar { tag: '!my!ugly!tag', value: 'data' } +- !Scalar { tag: 'tag:my.domain.org,2002:data!? #', value: 'data' } +- !SequenceEnd +- !DocumentEnd +- !StreamEnd diff --git a/_test/data/test_mark.marks b/_test/data/test_mark.marks new file mode 100644 index 0000000..7b08ee4 --- /dev/null +++ b/_test/data/test_mark.marks @@ -0,0 +1,38 @@ +--- +*The first line. +The last line. +--- +The first*line. +The last line. +--- +The first line.* +The last line. +--- +The first line. +*The last line. +--- +The first line. +The last*line. +--- +The first line. +The last line.* +--- +The first line. +*The selected line. +The last line. +--- +The first line. +The selected*line. +The last line. +--- +The first line. +The selected line.* +The last line. +--- +*The only line. +--- +The only*line. +--- +The only line.* +--- +Loooooooooooooooooooooooooooooooooooooooooooooong*Liiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiine diff --git a/_test/data/timestamp-bugs.code b/_test/data/timestamp-bugs.code new file mode 100644 index 0000000..b1d6e9c --- /dev/null +++ b/_test/data/timestamp-bugs.code @@ -0,0 +1,8 @@ +[ + datetime.datetime(2001, 12, 15, 3, 29, 43, 100000), + datetime.datetime(2001, 12, 14, 16, 29, 43, 100000), + datetime.datetime(2001, 12, 14, 21, 59, 43, 1010), + datetime.datetime(2001, 12, 14, 21, 59, 43, 0, FixedOffset(60, "+1")), + datetime.datetime(2001, 12, 14, 21, 59, 43, 0, FixedOffset(-90, "-1:30")), + datetime.datetime(2005, 7, 8, 17, 35, 4, 517600), +] diff --git a/_test/data/timestamp-bugs.data b/_test/data/timestamp-bugs.data new file mode 100644 index 0000000..721d290 --- /dev/null +++ b/_test/data/timestamp-bugs.data @@ -0,0 +1,6 @@ +- 2001-12-14 21:59:43.10 -5:30 +- 2001-12-14 21:59:43.10 +5:30 +- 2001-12-14 21:59:43.00101 +- 2001-12-14 21:59:43+1 +- 2001-12-14 21:59:43-1:30 +- 2005-07-08 17:35:04.517600 diff --git a/_test/data/timestamp.data b/_test/data/timestamp.data new file mode 100644 index 0000000..7d214ce --- /dev/null +++ b/_test/data/timestamp.data @@ -0,0 +1,5 @@ +- 2001-12-15T02:59:43.1Z +- 2001-12-14t21:59:43.10-05:00 +- 2001-12-14 21:59:43.10 -5 +- 2001-12-15 2:59:43.10 +- 2002-12-14 diff --git a/_test/data/timestamp.detect b/_test/data/timestamp.detect new file mode 100644 index 0000000..2013936 --- /dev/null +++ b/_test/data/timestamp.detect @@ -0,0 +1 @@ +tag:yaml.org,2002:timestamp diff --git a/_test/data/unclosed-bracket.loader-error b/_test/data/unclosed-bracket.loader-error new file mode 100644 index 0000000..8c82077 --- /dev/null +++ b/_test/data/unclosed-bracket.loader-error @@ -0,0 +1,6 @@ +test: + - [ foo: bar +# comment the rest of the stream to let the scanner detect the problem. +# - baz +#"we could have detected the unclosed bracket on the above line, but this would forbid such syntax as": { +#} diff --git a/_test/data/unclosed-quoted-scalar.loader-error b/_test/data/unclosed-quoted-scalar.loader-error new file mode 100644 index 0000000..8537429 --- /dev/null +++ b/_test/data/unclosed-quoted-scalar.loader-error @@ -0,0 +1,2 @@ +'foo + bar diff --git a/_test/data/undefined-anchor.loader-error b/_test/data/undefined-anchor.loader-error new file mode 100644 index 0000000..9469103 --- /dev/null +++ b/_test/data/undefined-anchor.loader-error @@ -0,0 +1,3 @@ +- foo +- &bar baz +- *bat diff --git a/_test/data/undefined-constructor.loader-error b/_test/data/undefined-constructor.loader-error new file mode 100644 index 0000000..9a37ccc --- /dev/null +++ b/_test/data/undefined-constructor.loader-error @@ -0,0 +1 @@ +--- !foo bar diff --git a/_test/data/undefined-tag-handle.loader-error b/_test/data/undefined-tag-handle.loader-error new file mode 100644 index 0000000..82ba335 --- /dev/null +++ b/_test/data/undefined-tag-handle.loader-error @@ -0,0 +1 @@ +--- !foo!bar baz diff --git a/_test/data/unknown.dumper-error b/_test/data/unknown.dumper-error new file mode 100644 index 0000000..83204d2 --- /dev/null +++ b/_test/data/unknown.dumper-error @@ -0,0 +1 @@ +yaml.safe_dump(object) diff --git a/_test/data/unsupported-version.emitter-error b/_test/data/unsupported-version.emitter-error new file mode 100644 index 0000000..f9c6197 --- /dev/null +++ b/_test/data/unsupported-version.emitter-error @@ -0,0 +1,5 @@ +- !StreamStart +- !DocumentStart { version: [5,6] } +- !Scalar { value: foo } +- !DocumentEnd +- !StreamEnd diff --git a/_test/data/utf16be.code b/_test/data/utf16be.code new file mode 100644 index 0000000..c45b371 --- /dev/null +++ b/_test/data/utf16be.code @@ -0,0 +1 @@ +"UTF-16-BE" diff --git a/_test/data/utf16be.data b/_test/data/utf16be.data Binary files differnew file mode 100644 index 0000000..50dcfae --- /dev/null +++ b/_test/data/utf16be.data diff --git a/_test/data/utf16le.code b/_test/data/utf16le.code new file mode 100644 index 0000000..400530a --- /dev/null +++ b/_test/data/utf16le.code @@ -0,0 +1 @@ +"UTF-16-LE" diff --git a/_test/data/utf16le.data b/_test/data/utf16le.data Binary files differnew file mode 100644 index 0000000..76f5e73 --- /dev/null +++ b/_test/data/utf16le.data diff --git a/_test/data/utf8-implicit.code b/_test/data/utf8-implicit.code new file mode 100644 index 0000000..29326db --- /dev/null +++ b/_test/data/utf8-implicit.code @@ -0,0 +1 @@ +"implicit UTF-8" diff --git a/_test/data/utf8-implicit.data b/_test/data/utf8-implicit.data new file mode 100644 index 0000000..9d8081e --- /dev/null +++ b/_test/data/utf8-implicit.data @@ -0,0 +1 @@ +--- implicit UTF-8 diff --git a/_test/data/utf8.code b/_test/data/utf8.code new file mode 100644 index 0000000..dcf11cc --- /dev/null +++ b/_test/data/utf8.code @@ -0,0 +1 @@ +"UTF-8" diff --git a/_test/data/utf8.data b/_test/data/utf8.data new file mode 100644 index 0000000..686f48a --- /dev/null +++ b/_test/data/utf8.data @@ -0,0 +1 @@ +--- UTF-8 diff --git a/_test/data/util/00_ok.yaml b/_test/data/util/00_ok.yaml new file mode 100644 index 0000000..adc4adf --- /dev/null +++ b/_test/data/util/00_ok.yaml @@ -0,0 +1,3 @@ +- abc +- ghi # some comment +- klm diff --git a/_test/data/util/01_second_rt_ok.yaml b/_test/data/util/01_second_rt_ok.yaml new file mode 100644 index 0000000..de19513 --- /dev/null +++ b/_test/data/util/01_second_rt_ok.yaml @@ -0,0 +1,3 @@ +- abc +- ghi # some comment +- klm diff --git a/_test/data/util/02_not_ok.yaml b/_test/data/util/02_not_ok.yaml new file mode 100644 index 0000000..945e5ec --- /dev/null +++ b/_test/data/util/02_not_ok.yaml @@ -0,0 +1,2 @@ +123 # single scalar cannot have comment +... diff --git a/_test/data/util/03_no_comment_ok.yaml b/_test/data/util/03_no_comment_ok.yaml new file mode 100644 index 0000000..081284a --- /dev/null +++ b/_test/data/util/03_no_comment_ok.yaml @@ -0,0 +1,2 @@ +123 +... diff --git a/_test/data/valid_escape_characters.code b/_test/data/valid_escape_characters.code new file mode 100644 index 0000000..0434f0c --- /dev/null +++ b/_test/data/valid_escape_characters.code @@ -0,0 +1 @@ +"\" \\ / \b \f \n \r \t" diff --git a/_test/data/valid_escape_characters.data b/_test/data/valid_escape_characters.data new file mode 100644 index 0000000..a28e216 --- /dev/null +++ b/_test/data/valid_escape_characters.data @@ -0,0 +1 @@ +"\" \\ \/ \b \f \n \r \t" diff --git a/_test/data/valid_escape_characters.skip-ext b/_test/data/valid_escape_characters.skip-ext new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/_test/data/valid_escape_characters.skip-ext diff --git a/_test/data/value.data b/_test/data/value.data new file mode 100644 index 0000000..c5b7680 --- /dev/null +++ b/_test/data/value.data @@ -0,0 +1 @@ +- = diff --git a/_test/data/value.detect b/_test/data/value.detect new file mode 100644 index 0000000..7c37d02 --- /dev/null +++ b/_test/data/value.detect @@ -0,0 +1 @@ +tag:yaml.org,2002:value diff --git a/_test/data/yaml.data b/_test/data/yaml.data new file mode 100644 index 0000000..a4bb3f8 --- /dev/null +++ b/_test/data/yaml.data @@ -0,0 +1,3 @@ +- !!yaml '!' +- !!yaml '&' +- !!yaml '*' diff --git a/_test/data/yaml.detect b/_test/data/yaml.detect new file mode 100644 index 0000000..e2cf189 --- /dev/null +++ b/_test/data/yaml.detect @@ -0,0 +1 @@ +tag:yaml.org,2002:yaml diff --git a/_test/lib/canonical.py b/_test/lib/canonical.py new file mode 100644 index 0000000..56fa297 --- /dev/null +++ b/_test/lib/canonical.py @@ -0,0 +1,387 @@ +import ruyaml +from ruyaml.composer import Composer +from ruyaml.constructor import Constructor +from ruyaml.resolver import Resolver + + +class CanonicalError(ruyaml.YAMLError): + pass + + +class CanonicalScanner: + def __init__(self, data): + try: + if isinstance(data, bytes): + data = data.decode('utf-8') + except UnicodeDecodeError: + raise CanonicalError('utf-8 stream is expected') + self.data = data + '\0' + self.index = 0 + self.tokens = [] + self.scanned = False + + def check_token(self, *choices): + if not self.scanned: + self.scan() + if self.tokens: + if not choices: + return True + for choice in choices: + if isinstance(self.tokens[0], choice): + return True + return False + + def peek_token(self): + if not self.scanned: + self.scan() + if self.tokens: + return self.tokens[0] + + def get_token(self, choice=None): + if not self.scanned: + self.scan() + token = self.tokens.pop(0) + if choice and not isinstance(token, choice): + raise CanonicalError('unexpected token ' + repr(token)) + return token + + def get_token_value(self): + token = self.get_token() + return token.value + + def scan(self): + self.tokens.append(ruyaml.StreamStartToken(None, None)) + while True: + self.find_token() + ch = self.data[self.index] + if ch == '\0': + self.tokens.append(ruyaml.StreamEndToken(None, None)) + break + elif ch == '%': + self.tokens.append(self.scan_directive()) + elif ch == '-' and self.data[self.index : self.index + 3] == '---': + self.index += 3 + self.tokens.append(ruyaml.DocumentStartToken(None, None)) + elif ch == '[': + self.index += 1 + self.tokens.append(ruyaml.FlowSequenceStartToken(None, None)) + elif ch == '{': + self.index += 1 + self.tokens.append(ruyaml.FlowMappingStartToken(None, None)) + elif ch == ']': + self.index += 1 + self.tokens.append(ruyaml.FlowSequenceEndToken(None, None)) + elif ch == '}': + self.index += 1 + self.tokens.append(ruyaml.FlowMappingEndToken(None, None)) + elif ch == '?': + self.index += 1 + self.tokens.append(ruyaml.KeyToken(None, None)) + elif ch == ':': + self.index += 1 + self.tokens.append(ruyaml.ValueToken(None, None)) + elif ch == ',': + self.index += 1 + self.tokens.append(ruyaml.FlowEntryToken(None, None)) + elif ch == '*' or ch == '&': + self.tokens.append(self.scan_alias()) + elif ch == '!': + self.tokens.append(self.scan_tag()) + elif ch == '"': + self.tokens.append(self.scan_scalar()) + else: + raise CanonicalError('invalid token') + self.scanned = True + + DIRECTIVE = '%YAML 1.1' + + def scan_directive(self): + if ( + self.data[self.index : self.index + len(self.DIRECTIVE)] == self.DIRECTIVE + and self.data[self.index + len(self.DIRECTIVE)] in ' \n\0' + ): + self.index += len(self.DIRECTIVE) + return ruyaml.DirectiveToken('YAML', (1, 1), None, None) + else: + raise CanonicalError('invalid directive') + + def scan_alias(self): + if self.data[self.index] == '*': + TokenClass = ruyaml.AliasToken + else: + TokenClass = ruyaml.AnchorToken + self.index += 1 + start = self.index + while self.data[self.index] not in ', \n\0': + self.index += 1 + value = self.data[start : self.index] + return TokenClass(value, None, None) + + def scan_tag(self): + self.index += 1 + start = self.index + while self.data[self.index] not in ' \n\0': + self.index += 1 + value = self.data[start : self.index] + if not value: + value = '!' + elif value[0] == '!': + value = 'tag:yaml.org,2002:' + value[1:] + elif value[0] == '<' and value[-1] == '>': + value = value[1:-1] + else: + value = '!' + value + return ruyaml.TagToken(value, None, None) + + QUOTE_CODES = {'x': 2, 'u': 4, 'U': 8} + + QUOTE_REPLACES = { + '\\': '\\', + '"': '"', + ' ': ' ', + 'a': '\x07', + 'b': '\x08', + 'e': '\x1B', + 'f': '\x0C', + 'n': '\x0A', + 'r': '\x0D', + 't': '\x09', + 'v': '\x0B', + 'N': '\u0085', + 'L': '\u2028', + 'P': '\u2029', + '_': '_', + '0': '\x00', + } + + def scan_scalar(self): + self.index += 1 + chunks = [] + start = self.index + ignore_spaces = False + while self.data[self.index] != '"': + if self.data[self.index] == '\\': + ignore_spaces = False + chunks.append(self.data[start : self.index]) + self.index += 1 + ch = self.data[self.index] + self.index += 1 + if ch == '\n': + ignore_spaces = True + elif ch in self.QUOTE_CODES: + length = self.QUOTE_CODES[ch] + code = int(self.data[self.index : self.index + length], 16) + chunks.append(chr(code)) + self.index += length + else: + if ch not in self.QUOTE_REPLACES: + raise CanonicalError('invalid escape code') + chunks.append(self.QUOTE_REPLACES[ch]) + start = self.index + elif self.data[self.index] == '\n': + chunks.append(self.data[start : self.index]) + chunks.append(' ') + self.index += 1 + start = self.index + ignore_spaces = True + elif ignore_spaces and self.data[self.index] == ' ': + self.index += 1 + start = self.index + else: + ignore_spaces = False + self.index += 1 + chunks.append(self.data[start : self.index]) + self.index += 1 + return ruyaml.ScalarToken("".join(chunks), False, None, None) + + def find_token(self): + found = False + while not found: + while self.data[self.index] in ' \t': + self.index += 1 + if self.data[self.index] == '#': + while self.data[self.index] != '\n': + self.index += 1 + if self.data[self.index] == '\n': + self.index += 1 + else: + found = True + + +class CanonicalParser: + def __init__(self): + self.events = [] + self.parsed = False + + def dispose(self): + pass + + # stream: STREAM-START document* STREAM-END + def parse_stream(self): + self.get_token(ruyaml.StreamStartToken) + self.events.append(ruyaml.StreamStartEvent(None, None)) + while not self.check_token(ruyaml.StreamEndToken): + if self.check_token(ruyaml.DirectiveToken, ruyaml.DocumentStartToken): + self.parse_document() + else: + raise CanonicalError( + 'document is expected, got ' + repr(self.tokens[0]) + ) + self.get_token(ruyaml.StreamEndToken) + self.events.append(ruyaml.StreamEndEvent(None, None)) + + # document: DIRECTIVE? DOCUMENT-START node + def parse_document(self): + # node = None + if self.check_token(ruyaml.DirectiveToken): + self.get_token(ruyaml.DirectiveToken) + self.get_token(ruyaml.DocumentStartToken) + self.events.append(ruyaml.DocumentStartEvent(None, None)) + self.parse_node() + self.events.append(ruyaml.DocumentEndEvent(None, None)) + + # node: ALIAS | ANCHOR? TAG? (SCALAR|sequence|mapping) + def parse_node(self): + if self.check_token(ruyaml.AliasToken): + self.events.append(ruyaml.AliasEvent(self.get_token_value(), None, None)) + else: + anchor = None + if self.check_token(ruyaml.AnchorToken): + anchor = self.get_token_value() + tag = None + if self.check_token(ruyaml.TagToken): + tag = self.get_token_value() + if self.check_token(ruyaml.ScalarToken): + self.events.append( + ruyaml.ScalarEvent( + anchor, tag, (False, False), self.get_token_value(), None, None + ) + ) + elif self.check_token(ruyaml.FlowSequenceStartToken): + self.events.append(ruyaml.SequenceStartEvent(anchor, tag, None, None)) + self.parse_sequence() + elif self.check_token(ruyaml.FlowMappingStartToken): + self.events.append(ruyaml.MappingStartEvent(anchor, tag, None, None)) + self.parse_mapping() + else: + raise CanonicalError( + "SCALAR, '[', or '{' is expected, got " + repr(self.tokens[0]) + ) + + # sequence: SEQUENCE-START (node (ENTRY node)*)? ENTRY? SEQUENCE-END + def parse_sequence(self): + self.get_token(ruyaml.FlowSequenceStartToken) + if not self.check_token(ruyaml.FlowSequenceEndToken): + self.parse_node() + while not self.check_token(ruyaml.FlowSequenceEndToken): + self.get_token(ruyaml.FlowEntryToken) + if not self.check_token(ruyaml.FlowSequenceEndToken): + self.parse_node() + self.get_token(ruyaml.FlowSequenceEndToken) + self.events.append(ruyaml.SequenceEndEvent(None, None)) + + # mapping: MAPPING-START (map_entry (ENTRY map_entry)*)? ENTRY? MAPPING-END + def parse_mapping(self): + self.get_token(ruyaml.FlowMappingStartToken) + if not self.check_token(ruyaml.FlowMappingEndToken): + self.parse_map_entry() + while not self.check_token(ruyaml.FlowMappingEndToken): + self.get_token(ruyaml.FlowEntryToken) + if not self.check_token(ruyaml.FlowMappingEndToken): + self.parse_map_entry() + self.get_token(ruyaml.FlowMappingEndToken) + self.events.append(ruyaml.MappingEndEvent(None, None)) + + # map_entry: KEY node VALUE node + def parse_map_entry(self): + self.get_token(ruyaml.KeyToken) + self.parse_node() + self.get_token(ruyaml.ValueToken) + self.parse_node() + + def parse(self): + self.parse_stream() + self.parsed = True + + def get_event(self): + if not self.parsed: + self.parse() + return self.events.pop(0) + + def check_event(self, *choices): + if not self.parsed: + self.parse() + if self.events: + if not choices: + return True + for choice in choices: + if isinstance(self.events[0], choice): + return True + return False + + def peek_event(self): + if not self.parsed: + self.parse() + return self.events[0] + + +class CanonicalLoader( + CanonicalScanner, CanonicalParser, Composer, Constructor, Resolver +): + def __init__(self, stream): + if hasattr(stream, 'read'): + stream = stream.read() + CanonicalScanner.__init__(self, stream) + CanonicalParser.__init__(self) + Composer.__init__(self) + Constructor.__init__(self) + Resolver.__init__(self) + + +ruyaml.CanonicalLoader = CanonicalLoader + + +def canonical_scan(stream): + yaml = ruyaml.YAML() + yaml.scanner = CanonicalScanner + return yaml.scan(stream) + + +ruyaml.canonical_scan = canonical_scan + + +def canonical_parse(stream): + return ruyaml.parse(stream, Loader=CanonicalLoader) + + +ruyaml.canonical_parse = canonical_parse + + +def canonical_compose(stream): + return ruyaml.compose(stream, Loader=CanonicalLoader) + + +ruyaml.canonical_compose = canonical_compose + + +def canonical_compose_all(stream): + return ruyaml.compose_all(stream, Loader=CanonicalLoader) + + +ruyaml.canonical_compose_all = canonical_compose_all + + +def canonical_load(stream): + return ruyaml.load(stream, Loader=CanonicalLoader) + + +ruyaml.canonical_load = canonical_load + + +def canonical_load_all(stream): + yaml = ruyaml.YAML(typ='safe', pure=True) + yaml.Loader = CanonicalLoader + return yaml.load_all(stream) + + +ruyaml.canonical_load_all = canonical_load_all diff --git a/_test/lib/test_all.py b/_test/lib/test_all.py new file mode 100644 index 0000000..5c2fa95 --- /dev/null +++ b/_test/lib/test_all.py @@ -0,0 +1,21 @@ +import sys # NOQA + +import test_appliance + +import ruyaml + + +def main(args=None): + collections = [] + import test_yaml + + collections.append(test_yaml) + if ruyaml.__with_libyaml__: + import test_yaml_ext + + collections.append(test_yaml_ext) + test_appliance.run(collections, args) + + +if __name__ == '__main__': + main() diff --git a/_test/lib/test_appliance.py b/_test/lib/test_appliance.py new file mode 100644 index 0000000..a95de5e --- /dev/null +++ b/_test/lib/test_appliance.py @@ -0,0 +1,205 @@ +import argparse +import os +import pprint +import sys +import traceback +import types + +# DATA = 'tests/data' +# determine the position of data dynamically relative to program +# this allows running test while the current path is not the top of the +# repository, e.g. from the tests/data directory: python ../test_yaml.py +DATA = __file__.rsplit(os.sep, 2)[0] + '/data' + + +def find_test_functions(collections): + if not isinstance(collections, list): + collections = [collections] + functions = [] + for collection in collections: + if not isinstance(collection, dict): + collection = vars(collection) + for key in sorted(collection): + value = collection[key] + if isinstance(value, types.FunctionType) and hasattr(value, 'unittest'): + functions.append(value) + return functions + + +def find_test_filenames(directory): + filenames = {} + for filename in os.listdir(directory): + if os.path.isfile(os.path.join(directory, filename)): + base, ext = os.path.splitext(filename) + filenames.setdefault(base, []).append(ext) + filenames = sorted(filenames.items()) + return filenames + + +def parse_arguments(args): + """""" + parser = argparse.ArgumentParser( + usage=""" run the yaml tests. By default + all functions on all appropriate test_files are run. Functions have + unittest attributes that determine the required extensions to filenames + that need to be available in order to run that test. E.g.\n\n + python test_yaml.py test_constructor_types\n + python test_yaml.py --verbose test_tokens spec-02-05\n\n + The presence of an extension in the .skip attribute of a function + disables the test for that function.""" + ) + # ToDo: make into int and test > 0 in functions + parser.add_argument( + '--verbose', + '-v', + action='store_true', + default='YAML_TEST_VERBOSE' in os.environ, + help='set verbosity output', + ) + parser.add_argument( + '--list-functions', + action='store_true', + help="""list all functions with required file extensions for test files + """, + ) + parser.add_argument('function', nargs='?', help="""restrict function to run""") + parser.add_argument( + 'filenames', + nargs='*', + help="""basename of filename set, extensions (.code, .data) have to + be a superset of those in the unittest attribute of the selected + function""", + ) + args = parser.parse_args(args) + # print('args', args) + verbose = args.verbose + include_functions = [args.function] if args.function else [] + include_filenames = args.filenames + # if args is None: + # args = sys.argv[1:] + # verbose = False + # if '-v' in args: + # verbose = True + # args.remove('-v') + # if '--verbose' in args: + # verbose = True + # args.remove('--verbose') # never worked without this + # if 'YAML_TEST_VERBOSE' in os.environ: + # verbose = True + # include_functions = [] + # if args: + # include_functions.append(args.pop(0)) + if 'YAML_TEST_FUNCTIONS' in os.environ: + include_functions.extend(os.environ['YAML_TEST_FUNCTIONS'].split()) + # include_filenames = [] + # include_filenames.extend(args) + if 'YAML_TEST_FILENAMES' in os.environ: + include_filenames.extend(os.environ['YAML_TEST_FILENAMES'].split()) + return include_functions, include_filenames, verbose, args + + +def execute(function, filenames, verbose): + name = function.__name__ + if verbose: + sys.stdout.write('=' * 75 + '\n') + sys.stdout.write('%s(%s)...\n' % (name, ', '.join(filenames))) + try: + function(verbose=verbose, *filenames) + except Exception as exc: + info = sys.exc_info() + if isinstance(exc, AssertionError): + kind = 'FAILURE' + else: + kind = 'ERROR' + if verbose: + traceback.print_exc(limit=1, file=sys.stdout) + else: + sys.stdout.write(kind[0]) + sys.stdout.flush() + else: + kind = 'SUCCESS' + info = None + if not verbose: + sys.stdout.write('.') + sys.stdout.flush() + return (name, filenames, kind, info) + + +def display(results, verbose): + if results and not verbose: + sys.stdout.write('\n') + total = len(results) + failures = 0 + errors = 0 + for name, filenames, kind, info in results: + if kind == 'SUCCESS': + continue + if kind == 'FAILURE': + failures += 1 + if kind == 'ERROR': + errors += 1 + sys.stdout.write('=' * 75 + '\n') + sys.stdout.write('%s(%s): %s\n' % (name, ', '.join(filenames), kind)) + if kind == 'ERROR': + traceback.print_exception(file=sys.stdout, *info) + else: + sys.stdout.write('Traceback (most recent call last):\n') + traceback.print_tb(info[2], file=sys.stdout) + sys.stdout.write('%s: see below\n' % info[0].__name__) + sys.stdout.write('~' * 75 + '\n') + for arg in info[1].args: + pprint.pprint(arg, stream=sys.stdout) + for filename in filenames: + sys.stdout.write('-' * 75 + '\n') + sys.stdout.write('%s:\n' % filename) + with open(filename, 'r', errors='replace') as fp: + data = fp.read() + sys.stdout.write(data) + if data and data[-1] != '\n': + sys.stdout.write('\n') + sys.stdout.write('=' * 75 + '\n') + sys.stdout.write('TESTS: %s\n' % total) + ret_val = 0 + if failures: + sys.stdout.write('FAILURES: %s\n' % failures) + ret_val = 1 + if errors: + sys.stdout.write('ERRORS: %s\n' % errors) + ret_val = 2 + return ret_val + + +def run(collections, args=None): + test_functions = find_test_functions(collections) + test_filenames = find_test_filenames(DATA) + include_functions, include_filenames, verbose, a = parse_arguments(args) + if a.list_functions: + print('test functions:') + for f in test_functions: + print(' {:30s} {}'.format(f.__name__, f.unittest)) + return + results = [] + for function in test_functions: + if include_functions and function.__name__ not in include_functions: + continue + if function.unittest: + for base, exts in test_filenames: + if include_filenames and base not in include_filenames: + continue + filenames = [] + for ext in function.unittest: + if ext not in exts: + break + filenames.append(os.path.join(DATA, base + ext)) + else: + skip_exts = getattr(function, 'skip', []) + for skip_ext in skip_exts: + if skip_ext in exts: + break + else: + result = execute(function, filenames, verbose) + results.append(result) + else: + result = execute(function, [], verbose) + results.append(result) + return display(results, verbose=verbose) diff --git a/_test/lib/test_build.py b/_test/lib/test_build.py new file mode 100644 index 0000000..9fbab43 --- /dev/null +++ b/_test/lib/test_build.py @@ -0,0 +1,15 @@ +if __name__ == '__main__': + import distutils.util + import os + import sys + + build_lib = 'build/lib' + build_lib_ext = os.path.join( + 'build', 'lib.%s-%s' % (distutils.util.get_platform(), sys.version[0:3]) + ) + sys.path.insert(0, build_lib) + sys.path.insert(0, build_lib_ext) + import test_appliance + import test_yaml + + test_appliance.run(test_yaml) diff --git a/_test/lib/test_build_ext.py b/_test/lib/test_build_ext.py new file mode 100644 index 0000000..3a2bc0f --- /dev/null +++ b/_test/lib/test_build_ext.py @@ -0,0 +1,15 @@ +if __name__ == '__main__': + import distutils.util + import os + import sys + + build_lib = 'build/lib' + build_lib_ext = os.path.join( + 'build', 'lib.%s-%s' % (distutils.util.get_platform(), sys.version[0:3]) + ) + sys.path.insert(0, build_lib) + sys.path.insert(0, build_lib_ext) + import test_appliance + import test_yaml_ext + + test_appliance.run(test_yaml_ext) diff --git a/_test/lib/test_canonical.py b/_test/lib/test_canonical.py new file mode 100644 index 0000000..fe27ec6 --- /dev/null +++ b/_test/lib/test_canonical.py @@ -0,0 +1,55 @@ +# Skipped because we have no idea where this "canonical" module +# comes from, nor where all those fixtures originate +import pytest + +pytestmark = pytest.mark.skip +# import canonical # NOQA + +import ruyaml + + +def test_canonical_scanner(canonical_filename, verbose=False): + with open(canonical_filename, 'rb') as fp0: + data = fp0.read() + tokens = list(ruyaml.canonical_scan(data)) + assert tokens, tokens + if verbose: + for token in tokens: + print(token) + + +test_canonical_scanner.unittest = ['.canonical'] + + +def test_canonical_parser(canonical_filename, verbose=False): + with open(canonical_filename, 'rb') as fp0: + data = fp0.read() + events = list(ruyaml.canonical_parse(data)) + assert events, events + if verbose: + for event in events: + print(event) + + +test_canonical_parser.unittest = ['.canonical'] + + +def test_canonical_error(data_filename, canonical_filename, verbose=False): + with open(data_filename, 'rb') as fp0: + data = fp0.read() + try: + output = list(ruyaml.canonical_load_all(data)) # NOQA + except ruyaml.YAMLError as exc: + if verbose: + print(exc) + else: + raise AssertionError('expected an exception') + + +test_canonical_error.unittest = ['.data', '.canonical'] +test_canonical_error.skip = ['.empty'] + +if __name__ == '__main__': + import test_appliance + + test_appliance.run(globals()) diff --git a/_test/lib/test_constructor.py b/_test/lib/test_constructor.py new file mode 100644 index 0000000..681b34d --- /dev/null +++ b/_test/lib/test_constructor.py @@ -0,0 +1,393 @@ +# Skipped because we have no idea where all those fixtures originate +import pytest + +pytestmark = pytest.mark.skip + +import ruyaml as yaml + +YAML = yaml.YAML + +import datetime +import pprint + +import ruyaml + +try: + set +except NameError: + from sets import Set as set # NOQA + +import ruyaml.tokens + + +def cmp(a, b): + return (a > b) - (a < b) + + +def execute(code): + global value + exec(code) + return value + + +def _make_objects(): + global MyLoader, MyDumper, MyTestClass1, MyTestClass2, MyTestClass3 + global YAMLobject1, YAMLobject2, AnObject, AnInstance, AState, ACustomState + global InitArgs, InitArgsWithState + global NewArgs, NewArgsWithState, Reduce, ReduceWithState, MyInt, MyList, MyDict + global FixedOffset, today, execute + + class MyLoader(ruyaml.Loader): + pass + + class MyDumper(ruyaml.Dumper): + pass + + class MyTestClass1: + def __init__(self, x, y=0, z=0): + self.x = x + self.y = y + self.z = z + + def __eq__(self, other): + if isinstance(other, MyTestClass1): + return self.__class__, self.__dict__ == other.__class__, other.__dict__ + else: + return False + + def construct1(constructor, node): + mapping = constructor.construct_mapping(node) + return MyTestClass1(**mapping) + + def represent1(representer, native): + return representer.represent_mapping('!tag1', native.__dict__) + + ruyaml.add_constructor('!tag1', construct1, Loader=MyLoader) + ruyaml.add_representer(MyTestClass1, represent1, Dumper=MyDumper) + + class MyTestClass2(MyTestClass1, ruyaml.YAMLObject): + ruyaml.loader = MyLoader + ruyaml.dumper = MyDumper + ruyaml.tag = '!tag2' + + def from_yaml(cls, constructor, node): + x = constructor.construct_yaml_int(node) + return cls(x=x) + + from_yaml = classmethod(from_yaml) + + def to_yaml(cls, representer, native): + return representer.represent_scalar(cls.yaml_tag, str(native.x)) + + to_yaml = classmethod(to_yaml) + + class MyTestClass3(MyTestClass2): + ruyaml.tag = '!tag3' + + def from_yaml(cls, constructor, node): + mapping = constructor.construct_mapping(node) + if '=' in mapping: + x = mapping['='] + del mapping['='] + mapping['x'] = x + return cls(**mapping) + + from_yaml = classmethod(from_yaml) + + def to_yaml(cls, representer, native): + return representer.represent_mapping(cls.yaml_tag, native.__dict__) + + to_yaml = classmethod(to_yaml) + + class YAMLobject1(ruyaml.YAMLObject): + ruyaml.loader = MyLoader + ruyaml.dumper = MyDumper + ruyaml.tag = '!foo' + + def __init__(self, my_parameter=None, my_another_parameter=None): + self.my_parameter = my_parameter + self.my_another_parameter = my_another_parameter + + def __eq__(self, other): + if isinstance(other, YAMLobject1): + return self.__class__, self.__dict__ == other.__class__, other.__dict__ + else: + return False + + class YAMLobject2(ruyaml.YAMLObject): + ruyaml.loader = MyLoader + ruyaml.dumper = MyDumper + ruyaml.tag = '!bar' + + def __init__(self, foo=1, bar=2, baz=3): + self.foo = foo + self.bar = bar + self.baz = baz + + def __getstate__(self): + return {1: self.foo, 2: self.bar, 3: self.baz} + + def __setstate__(self, state): + self.foo = state[1] + self.bar = state[2] + self.baz = state[3] + + def __eq__(self, other): + if isinstance(other, YAMLobject2): + return self.__class__, self.__dict__ == other.__class__, other.__dict__ + else: + return False + + class AnObject: + def __new__(cls, foo=None, bar=None, baz=None): + self = object.__new__(cls) + self.foo = foo + self.bar = bar + self.baz = baz + return self + + def __cmp__(self, other): + return cmp( + (type(self), self.foo, self.bar, self.baz), # NOQA + (type(other), other.foo, other.bar, other.baz), + ) + + def __eq__(self, other): + return type(self) is type(other) and (self.foo, self.bar, self.baz) == ( + other.foo, + other.bar, + other.baz, + ) + + class AnInstance: + def __init__(self, foo=None, bar=None, baz=None): + self.foo = foo + self.bar = bar + self.baz = baz + + def __cmp__(self, other): + return cmp( + (type(self), self.foo, self.bar, self.baz), # NOQA + (type(other), other.foo, other.bar, other.baz), + ) + + def __eq__(self, other): + return type(self) is type(other) and (self.foo, self.bar, self.baz) == ( + other.foo, + other.bar, + other.baz, + ) + + class AState(AnInstance): + def __getstate__(self): + return {'_foo': self.foo, '_bar': self.bar, '_baz': self.baz} + + def __setstate__(self, state): + self.foo = state['_foo'] + self.bar = state['_bar'] + self.baz = state['_baz'] + + class ACustomState(AnInstance): + def __getstate__(self): + return (self.foo, self.bar, self.baz) + + def __setstate__(self, state): + self.foo, self.bar, self.baz = state + + # class InitArgs(AnInstance): + # def __getinitargs__(self): + # return (self.foo, self.bar, self.baz) + # def __getstate__(self): + # return {} + + # class InitArgsWithState(AnInstance): + # def __getinitargs__(self): + # return (self.foo, self.bar) + # def __getstate__(self): + # return self.baz + # def __setstate__(self, state): + # self.baz = state + + class NewArgs(AnObject): + def __getnewargs__(self): + return (self.foo, self.bar, self.baz) + + def __getstate__(self): + return {} + + class NewArgsWithState(AnObject): + def __getnewargs__(self): + return (self.foo, self.bar) + + def __getstate__(self): + return self.baz + + def __setstate__(self, state): + self.baz = state + + InitArgs = NewArgs + + InitArgsWithState = NewArgsWithState + + class Reduce(AnObject): + def __reduce__(self): + return self.__class__, (self.foo, self.bar, self.baz) + + class ReduceWithState(AnObject): + def __reduce__(self): + return self.__class__, (self.foo, self.bar), self.baz + + def __setstate__(self, state): + self.baz = state + + class MyInt(int): + def __eq__(self, other): + return type(self) is type(other) and int(self) == int(other) + + class MyList(list): + def __init__(self, n=1): + self.extend([None] * n) + + def __eq__(self, other): + return type(self) is type(other) and list(self) == list(other) + + class MyDict(dict): + def __init__(self, n=1): + for k in range(n): + self[k] = None + + def __eq__(self, other): + return type(self) is type(other) and dict(self) == dict(other) + + class FixedOffset(datetime.tzinfo): + def __init__(self, offset, name): + self.__offset = datetime.timedelta(minutes=offset) + self.__name = name + + def utcoffset(self, dt): + return self.__offset + + def tzname(self, dt): + return self.__name + + def dst(self, dt): + return datetime.timedelta(0) + + today = datetime.date.today() + + +try: + from ruamel.ordereddict import ordereddict +except ImportError: + from collections import OrderedDict + + # to get the right name import ... as ordereddict doesn't do that + + class ordereddict(OrderedDict): + pass + + +def _load_code(expression): + return eval(expression, globals()) + + +def _serialize_value(data): + if isinstance(data, list): + return '[%s]' % ', '.join(map(_serialize_value, data)) + elif isinstance(data, dict): + items = [] + for key, value in data.items(): + key = _serialize_value(key) + value = _serialize_value(value) + items.append('%s: %s' % (key, value)) + items.sort() + return '{%s}' % ', '.join(items) + elif isinstance(data, datetime.datetime): + return repr(data.utctimetuple()) + elif isinstance(data, float) and data != data: + return '?' + else: + return str(data) + + +def test_constructor_types(data_filename, code_filename, verbose=False): + _make_objects() + native1 = None + native2 = None + yaml = ruyaml.YAML(typ='safe', pure=True) + yaml.loader = MyLoader + try: + with open(data_filename, 'rb') as fp0: + native1 = list(ruyaml.load_all(fp0)) + if len(native1) == 1: + native1 = native1[0] + with open(code_filename, 'rb') as fp0: + native2 = _load_code(fp0.read()) + try: + if native1 == native2: + return + except TypeError: + pass + # print('native1', native1) + if verbose: + print('SERIALIZED NATIVE1:') + print(_serialize_value(native1)) + print('SERIALIZED NATIVE2:') + print(_serialize_value(native2)) + assert _serialize_value(native1) == _serialize_value(native2), ( + native1, + native2, + ) + finally: + if verbose: + print('NATIVE1:') + pprint.pprint(native1) + print('NATIVE2:') + pprint.pprint(native2) + + +test_constructor_types.unittest = ['.data', '.code'] + + +def test_roundtrip_data(code_filename, roundtrip_filename, verbose=False): + _make_objects() + with open(code_filename, 'rb') as fp0: + value1 = fp0.read() + yaml = YAML(typ='safe', pure=True) + yaml.Loader = MyLoader + native2 = list(yaml.load_all(value1)) + if len(native2) == 1: + native2 = native2[0] + try: + value2 = ruyaml.dump( + native2, + Dumper=MyDumper, + default_flow_style=False, + allow_unicode=True, + encoding='utf-8', + ) + # value2 += x + if verbose: + print('SERIALIZED NATIVE1:') + print(value1) + print('SERIALIZED NATIVE2:') + print(value2) + assert value1 == value2, (value1, value2) + finally: + if verbose: + print('NATIVE2:') + pprint.pprint(native2) + + +test_roundtrip_data.unittest = ['.data', '.roundtrip'] + + +if __name__ == '__main__': + import sys + + import test_constructor # NOQA + + sys.modules['test_constructor'] = sys.modules['__main__'] + import test_appliance + + test_appliance.run(globals()) diff --git a/_test/lib/test_emitter.py b/_test/lib/test_emitter.py new file mode 100644 index 0000000..0327c1b --- /dev/null +++ b/_test/lib/test_emitter.py @@ -0,0 +1,145 @@ +from __future__ import absolute_import, print_function + +# Skipped because we have no idea where all those fixtures originate +import pytest + +import ruyaml as yaml + +pytestmark = pytest.mark.skip + + +def _compare_events(events1, events2): + assert len(events1) == len(events2), (events1, events2) + for event1, event2 in zip(events1, events2): + assert event1.__class__ == event2.__class__, (event1, event2) + if isinstance(event1, yaml.NodeEvent): + assert event1.anchor == event2.anchor, (event1, event2) + if isinstance(event1, yaml.CollectionStartEvent): + assert event1.tag == event2.tag, (event1, event2) + if isinstance(event1, yaml.ScalarEvent): + if True not in event1.implicit + event2.implicit: + assert event1.tag == event2.tag, (event1, event2) + assert event1.value == event2.value, (event1, event2) + + +def test_emitter_on_data(data_filename, canonical_filename, verbose=False): + with open(data_filename, 'rb') as fp0: + events = list(yaml.parse(fp0)) + output = yaml.emit(events) + if verbose: + print('OUTPUT:') + print(output) + new_events = list(yaml.parse(output)) + _compare_events(events, new_events) + + +test_emitter_on_data.unittest = ['.data', '.canonical'] + + +def test_emitter_on_canonical(canonical_filename, verbose=False): + with open(canonical_filename, 'rb') as fp0: + events = list(yaml.parse(fp0)) + for canonical in [False, True]: + output = yaml.emit(events, canonical=canonical) + if verbose: + print('OUTPUT (canonical=%s):' % canonical) + print(output) + new_events = list(yaml.parse(output)) + _compare_events(events, new_events) + + +test_emitter_on_canonical.unittest = ['.canonical'] + + +def test_emitter_styles(data_filename, canonical_filename, verbose=False): + for filename in [data_filename, canonical_filename]: + with open(filename, 'rb') as fp0: + events = list(yaml.parse(fp0)) + for flow_style in [False, True]: + for style in ['|', '>', '"', "'", ""]: + styled_events = [] + for event in events: + if isinstance(event, yaml.ScalarEvent): + event = yaml.ScalarEvent( + event.anchor, + event.tag, + event.implicit, + event.value, + style=style, + ) + elif isinstance(event, yaml.SequenceStartEvent): + event = yaml.SequenceStartEvent( + event.anchor, + event.tag, + event.implicit, + flow_style=flow_style, + ) + elif isinstance(event, yaml.MappingStartEvent): + event = yaml.MappingStartEvent( + event.anchor, + event.tag, + event.implicit, + flow_style=flow_style, + ) + styled_events.append(event) + output = yaml.emit(styled_events) + if verbose: + print( + 'OUTPUT (filename=%r, flow_style=%r, style=%r)' + % (filename, flow_style, style) + ) + print(output) + new_events = list(yaml.parse(output)) + _compare_events(events, new_events) + + +test_emitter_styles.unittest = ['.data', '.canonical'] + + +class EventsLoader(yaml.Loader): + def construct_event(self, node): + if isinstance(node, yaml.ScalarNode): + mapping = {} + else: + mapping = self.construct_mapping(node) + class_name = str(node.tag[1:]) + 'Event' + if class_name in [ + 'AliasEvent', + 'ScalarEvent', + 'SequenceStartEvent', + 'MappingStartEvent', + ]: + mapping.setdefault('anchor', None) + if class_name in ['ScalarEvent', 'SequenceStartEvent', 'MappingStartEvent']: + mapping.setdefault('tag', None) + if class_name in ['SequenceStartEvent', 'MappingStartEvent']: + mapping.setdefault('implicit', True) + if class_name == 'ScalarEvent': + mapping.setdefault('implicit', (False, True)) + mapping.setdefault('value', "") + value = getattr(yaml, class_name)(**mapping) + return value + + +# if Loader is not a composite, add this function +# EventsLoader.add_constructor = yaml.constructor.Constructor.add_constructor + + +EventsLoader.add_constructor(None, EventsLoader.construct_event) + + +def test_emitter_events(events_filename, verbose=False): + with open(events_filename, 'rb') as fp0: + events = list(yaml.load(fp0, Loader=EventsLoader)) + output = yaml.emit(events) + if verbose: + print('OUTPUT:') + print(output) + new_events = list(yaml.parse(output)) + _compare_events(events, new_events) + + +if __name__ == '__main__': + import test_appliance + + test_appliance.run(globals()) diff --git a/_test/lib/test_errors.py b/_test/lib/test_errors.py new file mode 100644 index 0000000..3fb3e1d --- /dev/null +++ b/_test/lib/test_errors.py @@ -0,0 +1,100 @@ +import ruyaml as yaml + +YAML = yaml.YAML + +import warnings + +# Skipped because we have no idea where the "error_filename" +# fixture is supposed to come from +import pytest +import test_emitter + +import ruyaml as yaml + +pytestmark = pytest.mark.skip + +warnings.simplefilter('ignore', yaml.error.UnsafeLoaderWarning) + + +def test_loader_error(error_filename, verbose=False): + yaml = YAML(typ='safe', pure=True) + try: + with open(error_filename, 'rb') as fp0: + list(yaml.load_all(fp0)) + except yaml.YAMLError as exc: + if verbose: + print('%s:' % exc.__class__.__name__, exc) + else: + raise AssertionError('expected an exception') + + +test_loader_error.unittest = ['.loader-error'] + + +def test_loader_error_string(error_filename, verbose=False): + yaml = YAML(typ='safe', pure=True) + try: + with open(error_filename, 'rb') as fp0: + list(yaml.load_all(fp0.read())) + except yaml.YAMLError as exc: + if verbose: + print('%s:' % exc.__class__.__name__, exc) + else: + raise AssertionError('expected an exception') + + +test_loader_error_string.unittest = ['.loader-error'] + + +def test_loader_error_single(error_filename, verbose=False): + yaml = YAML(typ='safe', pure=True) + try: + with open(error_filename, 'rb') as fp0: + yaml.load(fp0.read()) + except yaml.YAMLError as exc: + if verbose: + print('%s:' % exc.__class__.__name__, exc) + else: + raise AssertionError('expected an exception') + + +test_loader_error_single.unittest = ['.single-loader-error'] + + +def test_emitter_error(error_filename, verbose=False): + yaml = YAML(typ='safe', pure=True) + with open(error_filename, 'rb') as fp0: + events = list(yaml.load(fp0, Loader=test_emitter.EventsLoader)) + try: + yaml.emit(events) + except yaml.YAMLError as exc: + if verbose: + print('%s:' % exc.__class__.__name__, exc) + else: + raise AssertionError('expected an exception') + + +test_emitter_error.unittest = ['.emitter-error'] + + +def test_dumper_error(error_filename, verbose=False): + yaml = YAML(typ='safe', pure=True) + with open(error_filename, 'rb') as fp0: + code = fp0.read() + try: + import yaml + + exec(code) + except yaml.YAMLError as exc: + if verbose: + print('%s:' % exc.__class__.__name__, exc) + else: + raise AssertionError('expected an exception') + + +test_dumper_error.unittest = ['.dumper-error'] + +if __name__ == '__main__': + import test_appliance + + test_appliance.run(globals()) diff --git a/_test/lib/test_input_output.py b/_test/lib/test_input_output.py new file mode 100644 index 0000000..8d0c2cb --- /dev/null +++ b/_test/lib/test_input_output.py @@ -0,0 +1,190 @@ +import ruyaml as yaml + +YAML = yaml.YAML +import codecs +import os +import os.path +import tempfile +from io import BytesIO, StringIO + +# Skipped because we have no idea where the "unicode_filename" +# fixture is supposed to come from +import pytest + +import ruyaml as yaml + +pytestmark = pytest.mark.skip + + +def test_unicode_input(unicode_filename, verbose=False): + yaml = YAML(typ='safe', pure=True) + with open(unicode_filename, 'rb') as fp: + data = fp.read().decode('utf-8') + value = ' '.join(data.split()) + output = yaml.load(data) + assert output == value, (output, value) + output = yaml.load(StringIO(data)) + assert output == value, (output, value) + for input in [ + data.encode('utf-8'), + codecs.BOM_UTF8 + data.encode('utf-8'), + codecs.BOM_UTF16_BE + data.encode('utf-16-be'), + codecs.BOM_UTF16_LE + data.encode('utf-16-le'), + ]: + if verbose: + print('INPUT:', repr(input[:10]), '...') + output = yaml.load(input) + assert output == value, (output, value) + output = yaml.load(BytesIO(input)) + assert output == value, (output, value) + + +test_unicode_input.unittest = ['.unicode'] + + +def test_unicode_input_errors(unicode_filename, verbose=False): + yaml = YAML(typ='safe', pure=True) + with open(unicode_filename, 'rb') as fp: + data = fp.read().decode('utf-8') + for input in [ + data.encode('latin1', 'ignore'), + data.encode('utf-16-be'), + data.encode('utf-16-le'), + codecs.BOM_UTF8 + data.encode('utf-16-be'), + codecs.BOM_UTF16_BE + data.encode('utf-16-le'), + codecs.BOM_UTF16_LE + data.encode('utf-8') + b'!', + ]: + try: + yaml.load(input) + except yaml.YAMLError as exc: + if verbose: + print(exc) + else: + raise AssertionError('expected an exception') + try: + yaml.load(BytesIO(input)) + except yaml.YAMLError as exc: + if verbose: + print(exc) + else: + raise AssertionError('expected an exception') + + +test_unicode_input_errors.unittest = ['.unicode'] + + +def test_unicode_output(unicode_filename, verbose=False): + yaml = YAML(typ='safe', pure=True) + with open(unicode_filename, 'rb') as fp: + data = fp.read().decode('utf-8') + value = ' '.join(data.split()) + for allow_unicode in [False, True]: + data1 = yaml.dump(value, allow_unicode=allow_unicode) + for encoding in [None, 'utf-8', 'utf-16-be', 'utf-16-le']: + stream = StringIO() + yaml.dump(value, stream, encoding=encoding, allow_unicode=allow_unicode) + data2 = stream.getvalue() + data3 = yaml.dump(value, encoding=encoding, allow_unicode=allow_unicode) + if encoding is not None: + assert isinstance(data3, bytes) + data3 = data3.decode(encoding) + stream = BytesIO() + if encoding is None: + try: + yaml.dump( + value, stream, encoding=encoding, allow_unicode=allow_unicode + ) + except TypeError as exc: + if verbose: + print(exc) + data4 = None + else: + raise AssertionError('expected an exception') + else: + yaml.dump(value, stream, encoding=encoding, allow_unicode=allow_unicode) + data4 = stream.getvalue() + if verbose: + print('BYTES:', data4[:50]) + data4 = data4.decode(encoding) + for copy in [data1, data2, data3, data4]: + if copy is None: + continue + assert isinstance(copy, str) + if allow_unicode: + try: + copy[4:].encode('ascii') + except UnicodeEncodeError as exc: + if verbose: + print(exc) + else: + raise AssertionError('expected an exception') + else: + copy[4:].encode('ascii') + assert isinstance(data1, str), (type(data1), encoding) + assert isinstance(data2, str), (type(data2), encoding) + + +test_unicode_output.unittest = ['.unicode'] + + +def test_file_output(unicode_filename, verbose=False): + yaml = YAML(typ='safe', pure=True) + with open(unicode_filename, 'rb') as fp: + data = fp.read().decode('utf-8') + handle, filename = tempfile.mkstemp() + os.close(handle) + try: + stream = StringIO() + yaml.dump(data, stream, allow_unicode=True) + data1 = stream.getvalue() + stream = BytesIO() + yaml.dump(data, stream, encoding='utf-16-le', allow_unicode=True) + data2 = stream.getvalue().decode('utf-16-le')[1:] + with open(filename, 'w', encoding='utf-16-le') as stream: + yaml.dump(data, stream, allow_unicode=True) + with open(filename, 'r', encoding='utf-16-le') as fp0: + data3 = fp0.read() + with open(filename, 'wb') as stream: + yaml.dump(data, stream, encoding='utf-8', allow_unicode=True) + with open(filename, 'r', encoding='utf-8') as fp0: + data4 = fp0.read() + assert data1 == data2, (data1, data2) + assert data1 == data3, (data1, data3) + assert data1 == data4, (data1, data4) + finally: + if os.path.exists(filename): + os.unlink(filename) + + +test_file_output.unittest = ['.unicode'] + + +def test_unicode_transfer(unicode_filename, verbose=False): + yaml = YAML(typ='safe', pure=True) + with open(unicode_filename, 'rb') as fp: + data = fp.read().decode('utf-8') + for encoding in [None, 'utf-8', 'utf-16-be', 'utf-16-le']: + input = data + if encoding is not None: + input = ('\ufeff' + input).encode(encoding) + output1 = yaml.emit(yaml.parse(input), allow_unicode=True) + if encoding is None: + stream = StringIO() + else: + stream = BytesIO() + yaml.emit(yaml.parse(input), stream, allow_unicode=True) + output2 = stream.getvalue() + assert isinstance(output1, str), (type(output1), encoding) + if encoding is None: + assert isinstance(output2, str), (type(output1), encoding) + else: + assert isinstance(output2, bytes), (type(output1), encoding) + output2.decode(encoding) + + +test_unicode_transfer.unittest = ['.unicode'] + +if __name__ == '__main__': + import test_appliance + + test_appliance.run(globals()) diff --git a/_test/lib/test_mark.py b/_test/lib/test_mark.py new file mode 100644 index 0000000..af592a5 --- /dev/null +++ b/_test/lib/test_mark.py @@ -0,0 +1,40 @@ +# Skipped because we have no idea where the "marks_filename" +# fixture is supposed to come from +import pytest + +import ruyaml as yaml + +pytestmark = pytest.mark.skip + + +def test_marks(marks_filename, verbose=False): + with open(marks_filename, 'r') as fp0: + inputs = fp0.read().split('---\n')[1:] + for input in inputs: + index = 0 + line = 0 + column = 0 + while input[index] != '*': + if input[index] == '\n': + line += 1 + column = 0 + else: + column += 1 + index += 1 + mark = yaml.Mark(marks_filename, index, line, column, str(input), index) + snippet = mark.get_snippet(indent=2, max_length=79) + if verbose: + print(snippet) + assert isinstance(snippet, str), type(snippet) + assert snippet.count('\n') == 1, snippet.count('\n') + data, pointer = snippet.split('\n') + assert len(data) < 82, len(data) + assert data[len(pointer) - 1] == '*', data[len(pointer) - 1] + + +test_marks.unittest = ['.marks'] + +if __name__ == '__main__': + import test_appliance + + test_appliance.run(globals()) diff --git a/_test/lib/test_reader.py b/_test/lib/test_reader.py new file mode 100644 index 0000000..56ad671 --- /dev/null +++ b/_test/lib/test_reader.py @@ -0,0 +1,49 @@ +import codecs # NOQA +import io + +# Skipped because we have no idea where the "error_filename" +# fixture is supposed to come from +import pytest + +import ruyaml.reader + +pytestmark = pytest.mark.skip + + +def _run_reader(data, verbose): + try: + stream = ruyaml.py.reader.Reader(data) + while stream.peek() != '\0': + stream.forward() + except ruyaml.py.reader.ReaderError as exc: + if verbose: + print(exc) + else: + raise AssertionError('expected an exception') + + +def test_stream_error(error_filename, verbose=False): + with open(error_filename, 'rb') as fp0: + _run_reader(fp0, verbose) + with open(error_filename, 'rb') as fp0: + _run_reader(fp0.read(), verbose) + for encoding in ['utf-8', 'utf-16-le', 'utf-16-be']: + try: + with open(error_filename, 'rb') as fp0: + data = fp0.read().decode(encoding) + break + except UnicodeDecodeError: + pass + else: + return + _run_reader(data, verbose) + with io.open(error_filename, encoding=encoding) as fp: + _run_reader(fp, verbose) + + +test_stream_error.unittest = ['.stream-error'] + +if __name__ == '__main__': + import test_appliance + + test_appliance.run(globals()) diff --git a/_test/lib/test_recursive.py b/_test/lib/test_recursive.py new file mode 100644 index 0000000..e9d9565 --- /dev/null +++ b/_test/lib/test_recursive.py @@ -0,0 +1,63 @@ +# Skipped because we have no idea where the "recursive_filename" +# fixture is supposed to come from +import pytest + +import ruyaml + +pytestmark = pytest.mark.skip + + +class AnInstance: + def __init__(self, foo, bar): + self.foo = foo + self.bar = bar + + def __repr__(self): + try: + return '%s(foo=%r, bar=%r)' % (self.__class__.__name__, self.foo, self.bar) + except RuntimeError: + return '%s(foo=..., bar=...)' % self.__class__.__name__ + + +class AnInstanceWithState(AnInstance): + def __getstate__(self): + return {'attributes': [self.foo, self.bar]} + + def __setstate__(self, state): + self.foo, self.bar = state['attributes'] + + +def test_recursive(recursive_filename, verbose=False): + yaml = ruyaml.YAML(typ='safe', pure=True) + context = globals().copy() + with open(recursive_filename, 'rb') as fp0: + exec(fp0.read(), context) + value1 = context['value'] + output1 = None + value2 = None + output2 = None + try: + buf = ruyaml.compat.StringIO() + output1 = yaml.dump(value1, buf) + yaml.load(output1) + value2 = buf.getvalue() + buf = ruyaml.compat.StringIO() + yaml.dump(value2, buf) + output2 = buf.getvalue() + assert output1 == output2, (output1, output2) + finally: + if verbose: + print('VALUE1:', value1) + print('VALUE2:', value2) + print('OUTPUT1:') + print(output1) + print('OUTPUT2:') + print(output2) + + +test_recursive.unittest = ['.recursive'] + +if __name__ == '__main__': + import test_appliance + + test_appliance.run(globals()) diff --git a/_test/lib/test_representer.py b/_test/lib/test_representer.py new file mode 100644 index 0000000..9eb290c --- /dev/null +++ b/_test/lib/test_representer.py @@ -0,0 +1,59 @@ +import ruyaml as yaml + +YAML = yaml.YAML + +import pprint + +# Skipped because we have no idea where the "code_filename" +# fixture is supposed to come from +import pytest +import test_constructor + +pytestmark = pytest.mark.skip + + +def test_representer_types(code_filename, verbose=False): + yaml = YAML(typ='safe', pure=True) + test_constructor._make_objects() + for allow_unicode in [False, True]: + for encoding in ['utf-8', 'utf-16-be', 'utf-16-le']: + with open(code_filename, 'rb') as fp0: + native1 = test_constructor._load_code(fp0.read()) + native2 = None + try: + output = yaml.dump( + native1, + Dumper=test_constructor.MyDumper, + allow_unicode=allow_unicode, + encoding=encoding, + ) + native2 = yaml.load(output, Loader=test_constructor.MyLoader) + try: + if native1 == native2: + continue + except TypeError: + pass + value1 = test_constructor._serialize_value(native1) + value2 = test_constructor._serialize_value(native2) + if verbose: + print('SERIALIZED NATIVE1:') + print(value1) + print('SERIALIZED NATIVE2:') + print(value2) + assert value1 == value2, (native1, native2) + finally: + if verbose: + print('NATIVE1:') + pprint.pprint(native1) + print('NATIVE2:') + pprint.pprint(native2) + print('OUTPUT:') + print(output) + + +test_representer_types.unittest = ['.code'] + +if __name__ == '__main__': + import test_appliance + + test_appliance.run(globals()) diff --git a/_test/lib/test_resolver.py b/_test/lib/test_resolver.py new file mode 100644 index 0000000..41c0364 --- /dev/null +++ b/_test/lib/test_resolver.py @@ -0,0 +1,117 @@ +import pprint + +# Skipped because we have no idea where all those fixtures originate +import pytest + +import ruyaml as yaml + +pytestmark = pytest.mark.skip + + +def test_implicit_resolver(data_filename, detect_filename, verbose=False): + correct_tag = None + node = None + try: + with open(detect_filename, 'r') as fp0: + correct_tag = fp0.read().strip() + with open(data_filename, 'rb') as fp0: + node = yaml.compose(fp0) + assert isinstance(node, yaml.SequenceNode), node + for scalar in node.value: + assert isinstance(scalar, yaml.ScalarNode), scalar + assert scalar.tag == correct_tag, (scalar.tag, correct_tag) + finally: + if verbose: + print('CORRECT TAG:', correct_tag) + if hasattr(node, 'value'): + print('CHILDREN:') + pprint.pprint(node.value) + + +test_implicit_resolver.unittest = ['.data', '.detect'] + + +def _make_path_loader_and_dumper(): + global MyLoader, MyDumper + + class MyLoader(yaml.Loader): + pass + + class MyDumper(yaml.Dumper): + pass + + yaml.add_path_resolver('!root', [], Loader=MyLoader, Dumper=MyDumper) + yaml.add_path_resolver('!root/scalar', [], str, Loader=MyLoader, Dumper=MyDumper) + yaml.add_path_resolver( + '!root/key11/key12/*', ['key11', 'key12'], Loader=MyLoader, Dumper=MyDumper + ) + yaml.add_path_resolver( + '!root/key21/1/*', ['key21', 1], Loader=MyLoader, Dumper=MyDumper + ) + yaml.add_path_resolver( + '!root/key31/*/*/key14/map', + ['key31', None, None, 'key14'], + dict, + Loader=MyLoader, + Dumper=MyDumper, + ) + + return MyLoader, MyDumper + + +def _convert_node(node): + if isinstance(node, yaml.ScalarNode): + return (node.tag, node.value) + elif isinstance(node, yaml.SequenceNode): + value = [] + for item in node.value: + value.append(_convert_node(item)) + return (node.tag, value) + elif isinstance(node, yaml.MappingNode): + value = [] + for key, item in node.value: + value.append((_convert_node(key), _convert_node(item))) + return (node.tag, value) + + +def test_path_resolver_loader(data_filename, path_filename, verbose=False): + _make_path_loader_and_dumper() + with open(data_filename, 'rb') as fp0: + nodes1 = list(yaml.compose_all(fp0.read(), Loader=MyLoader)) + with open(path_filename, 'rb') as fp0: + nodes2 = list(yaml.compose_all(fp0.read())) + try: + for node1, node2 in zip(nodes1, nodes2): + data1 = _convert_node(node1) + data2 = _convert_node(node2) + assert data1 == data2, (data1, data2) + finally: + if verbose: + print(yaml.serialize_all(nodes1)) + + +test_path_resolver_loader.unittest = ['.data', '.path'] + + +def test_path_resolver_dumper(data_filename, path_filename, verbose=False): + _make_path_loader_and_dumper() + for filename in [data_filename, path_filename]: + with open(filename, 'rb') as fp0: + output = yaml.serialize_all(yaml.compose_all(fp0), Dumper=MyDumper) + if verbose: + print(output) + nodes1 = yaml.compose_all(output) + with open(data_filename, 'rb') as fp0: + nodes2 = yaml.compose_all(fp0) + for node1, node2 in zip(nodes1, nodes2): + data1 = _convert_node(node1) + data2 = _convert_node(node2) + assert data1 == data2, (data1, data2) + + +test_path_resolver_dumper.unittest = ['.data', '.path'] + +if __name__ == '__main__': + import test_appliance + + test_appliance.run(globals()) diff --git a/_test/lib/test_structure.py b/_test/lib/test_structure.py new file mode 100644 index 0000000..0a3bc39 --- /dev/null +++ b/_test/lib/test_structure.py @@ -0,0 +1,234 @@ +import pprint + +import canonical # NOQA + +# Skipped because we have no idea where this "canonical" module +# comes from, nor where all those fixtures originate +import pytest + +import ruyaml + +pytestmark = pytest.mark.skip +# import canonical # NOQA + + +def _convert_structure(loader): + if loader.check_event(ruyaml.ScalarEvent): + event = loader.get_event() + if event.tag or event.anchor or event.value: + return True + else: + return None + elif loader.check_event(ruyaml.SequenceStartEvent): + loader.get_event() + sequence = [] + while not loader.check_event(ruyaml.SequenceEndEvent): + sequence.append(_convert_structure(loader)) + loader.get_event() + return sequence + elif loader.check_event(ruyaml.MappingStartEvent): + loader.get_event() + mapping = [] + while not loader.check_event(ruyaml.MappingEndEvent): + key = _convert_structure(loader) + value = _convert_structure(loader) + mapping.append((key, value)) + loader.get_event() + return mapping + elif loader.check_event(ruyaml.AliasEvent): + loader.get_event() + return '*' + else: + loader.get_event() + return '?' + + +def test_structure(data_filename, structure_filename, verbose=False): + nodes1 = [] + with open(structure_filename, 'r') as fp: + nodes2 = eval(fp.read()) + try: + with open(data_filename, 'rb') as fp: + loader = ruyaml.Loader(fp) + while loader.check_event(): + if loader.check_event( + ruyaml.StreamStartEvent, + ruyaml.StreamEndEvent, + ruyaml.DocumentStartEvent, + ruyaml.DocumentEndEvent, + ): + loader.get_event() + continue + nodes1.append(_convert_structure(loader)) + if len(nodes1) == 1: + nodes1 = nodes1[0] + assert nodes1 == nodes2, (nodes1, nodes2) + finally: + if verbose: + print('NODES1:') + pprint.pprint(nodes1) + print('NODES2:') + pprint.pprint(nodes2) + + +test_structure.unittest = ['.data', '.structure'] + + +def _compare_events(events1, events2, full=False): + assert len(events1) == len(events2), (len(events1), len(events2)) + for event1, event2 in zip(events1, events2): + assert event1.__class__ == event2.__class__, (event1, event2) + if isinstance(event1, ruyaml.AliasEvent) and full: + assert event1.anchor == event2.anchor, (event1, event2) + if isinstance(event1, (ruyaml.ScalarEvent, ruyaml.CollectionStartEvent)): + if ( + event1.tag not in [None, '!'] and event2.tag not in [None, '!'] + ) or full: + assert event1.tag == event2.tag, (event1, event2) + if isinstance(event1, ruyaml.ScalarEvent): + assert event1.value == event2.value, (event1, event2) + + +def test_parser(data_filename, canonical_filename, verbose=False): + events1 = None + events2 = None + try: + with open(data_filename, 'rb') as fp0: + events1 = list(ruyaml.parse(fp0)) + with open(canonical_filename, 'rb') as fp0: + events2 = list(ruyaml.canonical_parse(fp0)) + _compare_events(events1, events2) + finally: + if verbose: + print('EVENTS1:') + pprint.pprint(events1) + print('EVENTS2:') + pprint.pprint(events2) + + +test_parser.unittest = ['.data', '.canonical'] + + +def test_parser_on_canonical(canonical_filename, verbose=False): + events1 = None + events2 = None + try: + with open(canonical_filename, 'rb') as fp0: + events1 = list(ruyaml.parse(fp0)) + with open(canonical_filename, 'rb') as fp0: + events2 = list(ruyaml.canonical_parse(fp0)) + _compare_events(events1, events2, full=True) + finally: + if verbose: + print('EVENTS1:') + pprint.pprint(events1) + print('EVENTS2:') + pprint.pprint(events2) + + +test_parser_on_canonical.unittest = ['.canonical'] + + +def _compare_nodes(node1, node2): + assert node1.__class__ == node2.__class__, (node1, node2) + assert node1.tag == node2.tag, (node1, node2) + if isinstance(node1, ruyaml.ScalarNode): + assert node1.value == node2.value, (node1, node2) + else: + assert len(node1.value) == len(node2.value), (node1, node2) + for item1, item2 in zip(node1.value, node2.value): + if not isinstance(item1, tuple): + item1 = (item1,) + item2 = (item2,) + for subnode1, subnode2 in zip(item1, item2): + _compare_nodes(subnode1, subnode2) + + +def test_composer(data_filename, canonical_filename, verbose=False): + nodes1 = None + nodes2 = None + try: + with open(data_filename, 'rb') as fp0: + nodes1 = list(ruyaml.compose_all(fp0)) + with open(canonical_filename, 'rb') as fp0: + nodes2 = list(ruyaml.canonical_compose_all(fp0)) + assert len(nodes1) == len(nodes2), (len(nodes1), len(nodes2)) + for node1, node2 in zip(nodes1, nodes2): + _compare_nodes(node1, node2) + finally: + if verbose: + print('NODES1:') + pprint.pprint(nodes1) + print('NODES2:') + pprint.pprint(nodes2) + + +test_composer.unittest = ['.data', '.canonical'] + + +def _make_loader(): + global MyLoader + + class MyLoader(ruyaml.Loader): + def construct_sequence(self, node): + return tuple(ruyaml.Loader.construct_sequence(self, node)) + + def construct_mapping(self, node): + pairs = self.construct_pairs(node) + pairs.sort(key=(lambda i: str(i))) + return pairs + + def construct_undefined(self, node): + return self.construct_scalar(node) + + MyLoader.add_constructor('tag:yaml.org,2002:map', MyLoader.construct_mapping) + MyLoader.add_constructor(None, MyLoader.construct_undefined) + + +def _make_canonical_loader(): + global MyCanonicalLoader + + class MyCanonicalLoader(ruyaml.CanonicalLoader): + def construct_sequence(self, node): + return tuple(ruyaml.CanonicalLoader.construct_sequence(self, node)) + + def construct_mapping(self, node): + pairs = self.construct_pairs(node) + pairs.sort(key=(lambda i: str(i))) + return pairs + + def construct_undefined(self, node): + return self.construct_scalar(node) + + MyCanonicalLoader.add_constructor( + 'tag:yaml.org,2002:map', MyCanonicalLoader.construct_mapping + ) + MyCanonicalLoader.add_constructor(None, MyCanonicalLoader.construct_undefined) + + +def test_constructor(data_filename, canonical_filename, verbose=False): + _make_loader() + _make_canonical_loader() + native1 = None + native2 = None + yaml = ruyaml.YAML(typ='safe') + try: + with open(data_filename, 'rb') as fp0: + native1 = list(yaml.load(fp0, Loader=MyLoader)) + with open(canonical_filename, 'rb') as fp0: + native2 = list(yaml.load(fp0, Loader=MyCanonicalLoader)) + assert native1 == native2, (native1, native2) + finally: + if verbose: + print('NATIVE1:') + pprint.pprint(native1) + print('NATIVE2:') + pprint.pprint(native2) + + +test_constructor.unittest = ['.data', '.canonical'] + +if __name__ == '__main__': + import test_appliance + + test_appliance.run(globals()) diff --git a/_test/lib/test_tokens.py b/_test/lib/test_tokens.py new file mode 100644 index 0000000..8c213fd --- /dev/null +++ b/_test/lib/test_tokens.py @@ -0,0 +1,93 @@ +# Skipped because we have no idea where all those fixtures originate +import pytest + +pytestmark = pytest.mark.skip + +import pprint + +import ruyaml + +# Tokens mnemonic: +# directive: % +# document_start: --- +# document_end: ... +# alias: * +# anchor: & +# tag: ! +# scalar _ +# block_sequence_start: [[ +# block_mapping_start: {{ +# block_end: ]} +# flow_sequence_start: [ +# flow_sequence_end: ] +# flow_mapping_start: { +# flow_mapping_end: } +# entry: , +# key: ? +# value: : + +_replaces = { + ruyaml.DirectiveToken: '%', + ruyaml.DocumentStartToken: '---', + ruyaml.DocumentEndToken: '...', + ruyaml.AliasToken: '*', + ruyaml.AnchorToken: '&', + ruyaml.TagToken: '!', + ruyaml.ScalarToken: '_', + ruyaml.BlockSequenceStartToken: '[[', + ruyaml.BlockMappingStartToken: '{{', + ruyaml.BlockEndToken: ']}', + ruyaml.FlowSequenceStartToken: '[', + ruyaml.FlowSequenceEndToken: ']', + ruyaml.FlowMappingStartToken: '{', + ruyaml.FlowMappingEndToken: '}', + ruyaml.BlockEntryToken: ',', + ruyaml.FlowEntryToken: ',', + ruyaml.KeyToken: '?', + ruyaml.ValueToken: ':', +} + + +def test_tokens(data_filename, tokens_filename, verbose=False): + tokens1 = [] + with open(tokens_filename, 'r') as fp: + tokens2 = fp.read().split() + try: + yaml = ruyaml.YAML(typ='unsafe', pure=True) + with open(data_filename, 'rb') as fp1: + for token in yaml.scan(fp1): + if not isinstance( + token, (ruyaml.StreamStartToken, ruyaml.StreamEndToken) + ): + tokens1.append(_replaces[token.__class__]) + finally: + if verbose: + print('TOKENS1:', ' '.join(tokens1)) + print('TOKENS2:', ' '.join(tokens2)) + assert len(tokens1) == len(tokens2), (tokens1, tokens2) + for token1, token2 in zip(tokens1, tokens2): + assert token1 == token2, (token1, token2) + + +test_tokens.unittest = ['.data', '.tokens'] + + +def test_scanner(data_filename, canonical_filename, verbose=False): + for filename in [data_filename, canonical_filename]: + tokens = [] + try: + yaml = ruyaml.YAML(typ='unsafe', pure=False) + with open(filename, 'rb') as fp: + for token in yaml.scan(fp): + tokens.append(token.__class__.__name__) + finally: + if verbose: + pprint.pprint(tokens) + + +test_scanner.unittest = ['.data', '.canonical'] + +if __name__ == '__main__': + import test_appliance + + test_appliance.run(globals()) diff --git a/_test/lib/test_yaml.py b/_test/lib/test_yaml.py new file mode 100644 index 0000000..8df5d1f --- /dev/null +++ b/_test/lib/test_yaml.py @@ -0,0 +1,21 @@ +# coding: utf-8 + +from test_canonical import * # NOQA +from test_constructor import * # NOQA +from test_emitter import * # NOQA +from test_errors import * # NOQA +from test_input_output import * # NOQA +from test_mark import * # NOQA +from test_reader import * # NOQA +from test_recursive import * # NOQA +from test_representer import * # NOQA +from test_resolver import * # NOQA +from test_structure import * # NOQA +from test_tokens import * # NOQA + +if __name__ == '__main__': + import sys + + import test_appliance + + sys.exit(test_appliance.run(globals())) diff --git a/_test/lib/test_yaml_ext.py b/_test/lib/test_yaml_ext.py new file mode 100644 index 0000000..15af5a7 --- /dev/null +++ b/_test/lib/test_yaml_ext.py @@ -0,0 +1,418 @@ +# coding: utf-8 + +import pprint +import types + +import ruyaml + +try: + import _ruyaml +except ImportError: + import pytest + + pytestmark = pytest.mark.skip + + class DummyLoader(type): + pass + + ruyaml.CLoader = DummyLoader + ruyaml.CDumper = DummyLoader + +ruyaml.PyBaseLoader = ruyaml.BaseLoader +ruyaml.PySafeLoader = ruyaml.SafeLoader +ruyaml.PyLoader = ruyaml.Loader +ruyaml.PyBaseDumper = ruyaml.BaseDumper +ruyaml.PySafeDumper = ruyaml.SafeDumper +ruyaml.PyDumper = ruyaml.Dumper + +old_scan = ruyaml.scan + + +def new_scan(stream, Loader=ruyaml.CLoader): + return old_scan(stream, Loader) + + +old_parse = ruyaml.parse + + +def new_parse(stream, Loader=ruyaml.CLoader): + return old_parse(stream, Loader) + + +old_compose = ruyaml.compose + + +def new_compose(stream, Loader=ruyaml.CLoader): + return old_compose(stream, Loader) + + +old_compose_all = ruyaml.compose_all + + +def new_compose_all(stream, Loader=ruyaml.CLoader): + return old_compose_all(stream, Loader) + + +old_load = ruyaml.load + + +def new_load(stream, Loader=ruyaml.CLoader): + return old_load(stream, Loader) + + +old_load_all = ruyaml.load_all + + +def new_load_all(stream, Loader=ruyaml.CLoader): + return old_load_all(stream, Loader) + + +old_safe_load = ruyaml.safe_load + + +def new_safe_load(stream): + return old_load(stream, ruyaml.CSafeLoader) + + +old_safe_load_all = ruyaml.safe_load_all + + +def new_safe_load_all(stream): + return old_load_all(stream, ruyaml.CSafeLoader) + + +old_emit = ruyaml.emit + + +def new_emit(events, stream=None, Dumper=ruyaml.CDumper, **kwds): + return old_emit(events, stream, Dumper, **kwds) + + +old_serialize = ruyaml.serialize + + +def new_serialize(node, stream, Dumper=ruyaml.CDumper, **kwds): + return old_serialize(node, stream, Dumper, **kwds) + + +old_serialize_all = ruyaml.serialize_all + + +def new_serialize_all(nodes, stream=None, Dumper=ruyaml.CDumper, **kwds): + return old_serialize_all(nodes, stream, Dumper, **kwds) + + +old_dump = ruyaml.dump + + +def new_dump(data, stream=None, Dumper=ruyaml.CDumper, **kwds): + return old_dump(data, stream, Dumper, **kwds) + + +old_dump_all = ruyaml.dump_all + + +def new_dump_all(documents, stream=None, Dumper=ruyaml.CDumper, **kwds): + return old_dump_all(documents, stream, Dumper, **kwds) + + +old_safe_dump = ruyaml.safe_dump + + +def new_safe_dump(data, stream=None, **kwds): + return old_dump(data, stream, ruyaml.CSafeDumper, **kwds) + + +old_safe_dump_all = ruyaml.safe_dump_all + + +def new_safe_dump_all(documents, stream=None, **kwds): + return old_dump_all(documents, stream, ruyaml.CSafeDumper, **kwds) + + +def _set_up(): + ruyaml.BaseLoader = ruyaml.CBaseLoader + ruyaml.SafeLoader = ruyaml.CSafeLoader + ruyaml.Loader = ruyaml.CLoader + ruyaml.BaseDumper = ruyaml.CBaseDumper + ruyaml.SafeDumper = ruyaml.CSafeDumper + ruyaml.Dumper = ruyaml.CDumper + ruyaml.scan = new_scan + ruyaml.parse = new_parse + ruyaml.compose = new_compose + ruyaml.compose_all = new_compose_all + ruyaml.load = new_load + ruyaml.load_all = new_load_all + ruyaml.safe_load = new_safe_load + ruyaml.safe_load_all = new_safe_load_all + ruyaml.emit = new_emit + ruyaml.serialize = new_serialize + ruyaml.serialize_all = new_serialize_all + ruyaml.dump = new_dump + ruyaml.dump_all = new_dump_all + ruyaml.safe_dump = new_safe_dump + ruyaml.safe_dump_all = new_safe_dump_all + + +def _tear_down(): + ruyaml.BaseLoader = ruyaml.PyBaseLoader + ruyaml.SafeLoader = ruyaml.PySafeLoader + ruyaml.Loader = ruyaml.PyLoader + ruyaml.BaseDumper = ruyaml.PyBaseDumper + ruyaml.SafeDumper = ruyaml.PySafeDumper + ruyaml.Dumper = ruyaml.PyDumper + ruyaml.scan = old_scan + ruyaml.parse = old_parse + ruyaml.compose = old_compose + ruyaml.compose_all = old_compose_all + ruyaml.load = old_load + ruyaml.load_all = old_load_all + ruyaml.safe_load = old_safe_load + ruyaml.safe_load_all = old_safe_load_all + ruyaml.emit = old_emit + ruyaml.serialize = old_serialize + ruyaml.serialize_all = old_serialize_all + ruyaml.dump = old_dump + ruyaml.dump_all = old_dump_all + ruyaml.safe_dump = old_safe_dump + ruyaml.safe_dump_all = old_safe_dump_all + + +def test_c_version(verbose=False): + if verbose: + print(_ruyaml.get_version()) + print(_ruyaml.get_version_string()) + assert ('%s.%s.%s' % _ruyaml.get_version()) == _ruyaml.get_version_string(), ( + _ruyaml.get_version(), + _ruyaml.get_version_string(), + ) + + +def _compare_scanners(py_data, c_data, verbose): + yaml = ruyaml.YAML(typ='unsafe', pure=True) + py_tokens = list(yaml.scan(py_data, Loader=ruyaml.PyLoader)) + c_tokens = [] + try: + yaml = ruyaml.YAML(typ='unsafe', pure=False) + for token in yaml.scan(c_data, Loader=ruyaml.CLoader): + c_tokens.append(token) + assert len(py_tokens) == len(c_tokens), (len(py_tokens), len(c_tokens)) + for py_token, c_token in zip(py_tokens, c_tokens): + assert py_token.__class__ == c_token.__class__, (py_token, c_token) + if hasattr(py_token, 'value'): + assert py_token.value == c_token.value, (py_token, c_token) + if isinstance(py_token, ruyaml.StreamEndToken): + continue + py_start = ( + py_token.start_mark.index, + py_token.start_mark.line, + py_token.start_mark.column, + ) + py_end = ( + py_token.end_mark.index, + py_token.end_mark.line, + py_token.end_mark.column, + ) + c_start = ( + c_token.start_mark.index, + c_token.start_mark.line, + c_token.start_mark.column, + ) + c_end = ( + c_token.end_mark.index, + c_token.end_mark.line, + c_token.end_mark.column, + ) + assert py_start == c_start, (py_start, c_start) + assert py_end == c_end, (py_end, c_end) + finally: + if verbose: + print('PY_TOKENS:') + pprint.pprint(py_tokens) + print('C_TOKENS:') + pprint.pprint(c_tokens) + + +def test_c_scanner(data_filename, canonical_filename, verbose=False): + with open(data_filename, 'rb') as fp0: + with open(data_filename, 'rb') as fp1: + _compare_scanners(fp0, fp1, verbose) + with open(data_filename, 'rb') as fp0: + with open(data_filename, 'rb') as fp1: + _compare_scanners(fp0.read(), fp1.read(), verbose) + with open(canonical_filename, 'rb') as fp0: + with open(canonical_filename, 'rb') as fp1: + _compare_scanners(fp0, fp1, verbose) + with open(canonical_filename, 'rb') as fp0: + with open(canonical_filename, 'rb') as fp1: + _compare_scanners(fp0.read(), fp1.read(), verbose) + + +test_c_scanner.unittest = ['.data', '.canonical'] +test_c_scanner.skip = ['.skip-ext'] + + +def _compare_parsers(py_data, c_data, verbose): + py_events = list(ruyaml.parse(py_data, Loader=ruyaml.PyLoader)) + c_events = [] + try: + for event in ruyaml.parse(c_data, Loader=ruyaml.CLoader): + c_events.append(event) + assert len(py_events) == len(c_events), (len(py_events), len(c_events)) + for py_event, c_event in zip(py_events, c_events): + for attribute in [ + '__class__', + 'anchor', + 'tag', + 'implicit', + 'value', + 'explicit', + 'version', + 'tags', + ]: + py_value = getattr(py_event, attribute, None) + c_value = getattr(c_event, attribute, None) + assert py_value == c_value, (py_event, c_event, attribute) + finally: + if verbose: + print('PY_EVENTS:') + pprint.pprint(py_events) + print('C_EVENTS:') + pprint.pprint(c_events) + + +def test_c_parser(data_filename, canonical_filename, verbose=False): + with open(data_filename, 'rb') as fp0: + with open(data_filename, 'rb') as fp1: + _compare_parsers(fp0, fp1, verbose) + with open(data_filename, 'rb') as fp0: + with open(data_filename, 'rb') as fp1: + _compare_parsers(fp0.read(), fp1.read(), verbose) + with open(canonical_filename, 'rb') as fp0: + with open(canonical_filename, 'rb') as fp1: + _compare_parsers(fp0, fp1, verbose) + with open(canonical_filename, 'rb') as fp0: + with open(canonical_filename, 'rb') as fp1: + _compare_parsers(fp0.read(), fp1.read(), verbose) + + +test_c_parser.unittest = ['.data', '.canonical'] +test_c_parser.skip = ['.skip-ext'] + + +def _compare_emitters(data, verbose): + events = list(ruyaml.parse(data, Loader=ruyaml.PyLoader)) + c_data = ruyaml.emit(events, Dumper=ruyaml.CDumper) + if verbose: + print(c_data) + py_events = list(ruyaml.parse(c_data, Loader=ruyaml.PyLoader)) + c_events = list(ruyaml.parse(c_data, Loader=ruyaml.CLoader)) + try: + assert len(events) == len(py_events), (len(events), len(py_events)) + assert len(events) == len(c_events), (len(events), len(c_events)) + for event, py_event, c_event in zip(events, py_events, c_events): + for attribute in [ + '__class__', + 'anchor', + 'tag', + 'implicit', + 'value', + 'explicit', + 'version', + 'tags', + ]: + value = getattr(event, attribute, None) + py_value = getattr(py_event, attribute, None) + c_value = getattr(c_event, attribute, None) + if ( + attribute == 'tag' + and value in [None, '!'] + and py_value in [None, '!'] + and c_value in [None, '!'] + ): + continue + if attribute == 'explicit' and (py_value or c_value): + continue + assert value == py_value, (event, py_event, attribute) + assert value == c_value, (event, c_event, attribute) + finally: + if verbose: + print('EVENTS:') + pprint.pprint(events) + print('PY_EVENTS:') + pprint.pprint(py_events) + print('C_EVENTS:') + pprint.pprint(c_events) + + +def test_c_emitter(data_filename, canonical_filename, verbose=False): + with open(data_filename, 'rb') as fp0: + _compare_emitters(fp0.read(), verbose) + with open(canonical_filename, 'rb') as fp0: + _compare_emitters(fp0.read(), verbose) + + +test_c_emitter.unittest = ['.data', '.canonical'] +test_c_emitter.skip = ['.skip-ext'] + + +def wrap_ext_function(function): + def wrapper(*args, **kwds): + _set_up() + try: + function(*args, **kwds) + finally: + _tear_down() + + wrapper.__name__ = '%s_ext' % function.__name__ + wrapper.unittest = function.unittest + wrapper.skip = getattr(function, 'skip', []) + ['.skip-ext'] + return wrapper + + +def wrap_ext(collections): + functions = [] + if not isinstance(collections, list): + collections = [collections] + for collection in collections: + if not isinstance(collection, dict): + collection = vars(collection) + for key in sorted(collection): + value = collection[key] + if isinstance(value, types.FunctionType) and hasattr(value, 'unittest'): + functions.append(wrap_ext_function(value)) + for function in functions: + assert function.__name__ not in globals() + globals()[function.__name__] = function + + +import test_constructor # NOQA +import test_emitter # NOQA +import test_errors # NOQA +import test_input_output # NOQA +import test_recursive # NOQA +import test_representer # NOQA +import test_resolver # NOQA +import test_structure # NOQA +import test_tokens # NOQA + +wrap_ext( + [ + test_tokens, + test_structure, + test_errors, + test_resolver, + test_constructor, + test_emitter, + test_representer, + test_recursive, + test_input_output, + ] +) + +if __name__ == '__main__': + import sys + + import test_appliance + + sys.exit(test_appliance.run(globals())) diff --git a/_test/roundtrip.py b/_test/roundtrip.py new file mode 100644 index 0000000..9313f42 --- /dev/null +++ b/_test/roundtrip.py @@ -0,0 +1,346 @@ +# coding: utf-8 + +""" +helper routines for testing round trip of commented YAML data +""" +import io +import sys +import textwrap +from pathlib import Path + +import ruyaml + +unset = object() + + +def dedent(data): + try: + position_of_first_newline = data.index('\n') + for idx in range(position_of_first_newline): + if not data[idx].isspace(): + raise ValueError + except ValueError: + pass + else: + data = data[position_of_first_newline + 1 :] + return textwrap.dedent(data) + + +def round_trip_load(inp, preserve_quotes=None, version=None): + import ruyaml # NOQA + + dinp = dedent(inp) + yaml = ruyaml.YAML() + yaml.preserve_quotes = preserve_quotes + yaml.version = version + return yaml.load(dinp) + + +def round_trip_load_all(inp, preserve_quotes=None, version=None): + import ruyaml # NOQA + + dinp = dedent(inp) + yaml = ruyaml.YAML() + yaml.preserve_quotes = preserve_quotes + yaml.version = version + return yaml.load_all(dinp) + + +def round_trip_dump( + data, + stream=None, # *, + indent=None, + block_seq_indent=None, + default_flow_style=unset, + top_level_colon_align=None, + prefix_colon=None, + explicit_start=None, + explicit_end=None, + version=None, + allow_unicode=True, +): + import ruyaml # NOQA + + yaml = ruyaml.YAML() + yaml.indent(mapping=indent, sequence=indent, offset=block_seq_indent) + if default_flow_style is not unset: + yaml.default_flow_style = default_flow_style + yaml.top_level_colon_align = top_level_colon_align + yaml.prefix_colon = prefix_colon + yaml.explicit_start = explicit_start + yaml.explicit_end = explicit_end + yaml.version = version + yaml.allow_unicode = allow_unicode + if stream is not None: + yaml.dump(data, stream=stream) + return + buf = io.StringIO() + yaml.dump(data, stream=buf) + return buf.getvalue() + + +def round_trip_dump_all( + data, + stream=None, # *, + indent=None, + block_seq_indent=None, + default_flow_style=unset, + top_level_colon_align=None, + prefix_colon=None, + explicit_start=None, + explicit_end=None, + version=None, + allow_unicode=None, +): + yaml = ruyaml.YAML() + yaml.indent(mapping=indent, sequence=indent, offset=block_seq_indent) + if default_flow_style is not unset: + yaml.default_flow_style = default_flow_style + yaml.top_level_colon_align = top_level_colon_align + yaml.prefix_colon = prefix_colon + yaml.explicit_start = explicit_start + yaml.explicit_end = explicit_end + yaml.version = version + yaml.allow_unicode = allow_unicode + if stream is not None: + yaml.dump(data, stream=stream) + return + buf = io.StringIO() + yaml.dump_all(data, stream=buf) + return buf.getvalue() + + +def diff(inp, outp, file_name='stdin'): + import difflib + + inl = inp.splitlines(True) # True for keepends + outl = outp.splitlines(True) + diff = difflib.unified_diff(inl, outl, file_name, 'round trip YAML') + for line in diff: + sys.stdout.write(line) + + +def round_trip( + inp, + outp=None, + extra=None, + intermediate=None, + indent=None, + block_seq_indent=None, + top_level_colon_align=None, + prefix_colon=None, + preserve_quotes=None, + explicit_start=None, + explicit_end=None, + version=None, + dump_data=None, +): + """ + inp: input string to parse + outp: expected output (equals input if not specified) + """ + if outp is None: + outp = inp + doutp = dedent(outp) + if extra is not None: + doutp += extra + data = round_trip_load(inp, preserve_quotes=preserve_quotes) + if dump_data: + print('data', data) + if intermediate is not None: + if isinstance(intermediate, dict): + for k, v in intermediate.items(): + if data[k] != v: + print('{0!r} <> {1!r}'.format(data[k], v)) + raise ValueError + res = round_trip_dump( + data, + indent=indent, + block_seq_indent=block_seq_indent, + top_level_colon_align=top_level_colon_align, + prefix_colon=prefix_colon, + explicit_start=explicit_start, + explicit_end=explicit_end, + version=version, + ) + if res != doutp: + diff(doutp, res, 'input string') + print('\nroundtrip data:\n', res, sep="") + assert res == doutp + res = round_trip_dump( + data, + indent=indent, + block_seq_indent=block_seq_indent, + top_level_colon_align=top_level_colon_align, + prefix_colon=prefix_colon, + explicit_start=explicit_start, + explicit_end=explicit_end, + version=version, + ) + print('roundtrip second round data:\n', res, sep="") + assert res == doutp + return data + + +def na_round_trip( + inp, + outp=None, + extra=None, + intermediate=None, + indent=None, + top_level_colon_align=None, + prefix_colon=None, + preserve_quotes=None, + explicit_start=None, + explicit_end=None, + version=None, + dump_data=None, +): + """ + inp: input string to parse + outp: expected output (equals input if not specified) + """ + inp = dedent(inp) + if outp is None: + outp = inp + if version is not None: + version = version + doutp = dedent(outp) + if extra is not None: + doutp += extra + yaml = YAML() + yaml.preserve_quotes = preserve_quotes + yaml.scalar_after_indicator = False # newline after every directives end + data = yaml.load(inp) + if dump_data: + print('data', data) + if intermediate is not None: + if isinstance(intermediate, dict): + for k, v in intermediate.items(): + if data[k] != v: + print('{0!r} <> {1!r}'.format(data[k], v)) + raise ValueError + yaml.indent = indent + yaml.top_level_colon_align = top_level_colon_align + yaml.prefix_colon = prefix_colon + yaml.explicit_start = explicit_start + yaml.explicit_end = explicit_end + res = yaml.dump(data, compare=doutp) + return res + + +def YAML(**kw): + import ruyaml # NOQA + + class MyYAML(ruyaml.YAML): + """auto dedent string parameters on load""" + + def load(self, stream): + if isinstance(stream, str): + if stream and stream[0] == '\n': + stream = stream[1:] + stream = textwrap.dedent(stream) + return ruyaml.YAML.load(self, stream) + + def load_all(self, stream): + if isinstance(stream, str): + if stream and stream[0] == '\n': + stream = stream[1:] + stream = textwrap.dedent(stream) + for d in ruyaml.YAML.load_all(self, stream): + yield d + + def dump(self, data, **kw): + from io import BytesIO, StringIO # NOQA + + assert ('stream' in kw) ^ ('compare' in kw) + if 'stream' in kw: + return ruyaml.YAML.dump(data, **kw) + lkw = kw.copy() + expected = textwrap.dedent(lkw.pop('compare')) + unordered_lines = lkw.pop('unordered_lines', False) + if expected and expected[0] == '\n': + expected = expected[1:] + lkw['stream'] = st = StringIO() + ruyaml.YAML.dump(self, data, **lkw) + res = st.getvalue() + print(res) + if unordered_lines: + res = sorted(res.splitlines()) + expected = sorted(expected.splitlines()) + assert res == expected + + def round_trip(self, stream, **kw): + from io import BytesIO, StringIO # NOQA + + assert isinstance(stream, str) + lkw = kw.copy() + if stream and stream[0] == '\n': + stream = stream[1:] + stream = textwrap.dedent(stream) + data = ruyaml.YAML.load(self, stream) + outp = lkw.pop('outp', stream) + lkw['stream'] = st = StringIO() + ruyaml.YAML.dump(self, data, **lkw) + res = st.getvalue() + if res != outp: + diff(outp, res, 'input string') + assert res == outp + + def round_trip_all(self, stream, **kw): + from io import BytesIO, StringIO # NOQA + + assert isinstance(stream, str) + lkw = kw.copy() + if stream and stream[0] == '\n': + stream = stream[1:] + stream = textwrap.dedent(stream) + data = list(ruyaml.YAML.load_all(self, stream)) + outp = lkw.pop('outp', stream) + lkw['stream'] = st = StringIO() + ruyaml.YAML.dump_all(self, data, **lkw) + res = st.getvalue() + if res != outp: + diff(outp, res, 'input string') + assert res == outp + + return MyYAML(**kw) + + +def save_and_run(program, base_dir=None, output=None, file_name=None, optimized=False): + """ + safe and run a python program, thereby circumventing any restrictions on module level + imports + """ + from subprocess import STDOUT, CalledProcessError, check_output + + if not hasattr(base_dir, 'hash'): + base_dir = Path(str(base_dir)) + if file_name is None: + file_name = 'safe_and_run_tmp.py' + file_name = base_dir / file_name + file_name.write_text(dedent(program)) + + try: + cmd = [sys.executable, '-Wd'] + if optimized: + cmd.append('-O') + cmd.append(str(file_name)) + print('running:', *cmd) + # 3.5 needs strings + res = check_output( + cmd, stderr=STDOUT, universal_newlines=True, cwd=str(base_dir) + ) + if output is not None: + if '__pypy__' in sys.builtin_module_names: + res = res.splitlines(True) + res = [line for line in res if 'no version info' not in line] + res = ''.join(res) + print('result: ', res, end='') + print('expected:', output, end='') + assert res == output + except CalledProcessError as exception: + print("##### Running '{} {}' FAILED #####".format(sys.executable, file_name)) + print(exception.output) + return exception.returncode + return 0 diff --git a/_test/test_a_dedent.py b/_test/test_a_dedent.py new file mode 100644 index 0000000..23729f0 --- /dev/null +++ b/_test/test_a_dedent.py @@ -0,0 +1,57 @@ +# coding: utf-8 + +from .roundtrip import dedent + + +class TestDedent: + def test_start_newline(self): + # fmt: off + x = dedent(""" + 123 + 456 + """) + # fmt: on + assert x == '123\n 456\n' + + def test_start_space_newline(self): + # special construct to prevent stripping of following whitespace + # fmt: off + x = dedent(" " """ + 123 + """) + # fmt: on + assert x == '123\n' + + def test_start_no_newline(self): + # special construct to prevent stripping of following whitespac + x = dedent( + """\ + 123 + 456 + """ + ) + assert x == '123\n 456\n' + + def test_preserve_no_newline_at_end(self): + x = dedent( + """ + 123""" + ) + assert x == '123' + + def test_preserve_no_newline_at_all(self): + x = dedent( + """\ + 123""" + ) + assert x == '123' + + def test_multiple_dedent(self): + x = dedent( + dedent( + """ + 123 + """ + ) + ) + assert x == '123\n' diff --git a/_test/test_add_xxx.py b/_test/test_add_xxx.py new file mode 100644 index 0000000..ee42bf1 --- /dev/null +++ b/_test/test_add_xxx.py @@ -0,0 +1,184 @@ +# coding: utf-8 + +import re + +import pytest # NOQA + +from .roundtrip import dedent, round_trip_dump # NOQA + + +# from PyYAML docs +class Dice(tuple): + def __new__(cls, a, b): + return tuple.__new__(cls, [a, b]) + + def __repr__(self): + return 'Dice(%s,%s)' % self + + +def dice_constructor(loader, node): + value = loader.construct_scalar(node) + a, b = map(int, value.split('d')) + return Dice(a, b) + + +def dice_representer(dumper, data): + return dumper.represent_scalar('!dice', '{}d{}'.format(*data)) + + +def test_dice_constructor(): + import ruyaml # NOQA + + yaml = ruyaml.YAML(typ='unsafe', pure=True) + ruyaml.add_constructor('!dice', dice_constructor) + data = yaml.load('initial hit points: !dice 8d4') + assert str(data) == "{'initial hit points': Dice(8,4)}" + + +def test_dice_constructor_with_loader(): + import ruyaml # NOQA + + yaml = ruyaml.YAML(typ='unsafe', pure=True) + ruyaml.add_constructor('!dice', dice_constructor, Loader=ruyaml.Loader) + data = yaml.load('initial hit points: !dice 8d4') + assert str(data) == "{'initial hit points': Dice(8,4)}" + + +def test_dice_representer(): + import ruyaml # NOQA + + yaml = ruyaml.YAML(typ='unsafe', pure=True) + yaml.default_flow_style = False + ruyaml.add_representer(Dice, dice_representer) + # ruyaml 0.15.8+ no longer forces quotes tagged scalars + buf = ruyaml.compat.StringIO() + yaml.dump(dict(gold=Dice(10, 6)), buf) + assert buf.getvalue() == 'gold: !dice 10d6\n' + + +def test_dice_implicit_resolver(): + import ruyaml # NOQA + + yaml = ruyaml.YAML(typ='unsafe', pure=True) + yaml.default_flow_style = False + pattern = re.compile(r'^\d+d\d+$') + ruyaml.add_implicit_resolver('!dice', pattern) + buf = ruyaml.compat.StringIO() + yaml.dump(dict(treasure=Dice(10, 20)), buf) + assert buf.getvalue() == 'treasure: 10d20\n' + assert yaml.load('damage: 5d10') == dict(damage=Dice(5, 10)) + + +class Obj1(dict): + def __init__(self, suffix): + self._suffix = suffix + self._node = None + + def add_node(self, n): + self._node = n + + def __repr__(self): + return 'Obj1(%s->%s)' % (self._suffix, self.items()) + + def dump(self): + return repr(self._node) + + +class YAMLObj1(object): + yaml_tag = '!obj:' + + @classmethod + def from_yaml(cls, loader, suffix, node): + import ruyaml # NOQA + + obj1 = Obj1(suffix) + if isinstance(node, ruyaml.MappingNode): + obj1.add_node(loader.construct_mapping(node)) + else: + raise NotImplementedError + return obj1 + + @classmethod + def to_yaml(cls, dumper, data): + return dumper.represent_scalar(cls.yaml_tag + data._suffix, data.dump()) + + +def test_yaml_obj(): + import ruyaml # NOQA + + yaml = ruyaml.YAML(typ='unsafe', pure=True) + ruyaml.add_representer(Obj1, YAMLObj1.to_yaml) + ruyaml.add_multi_constructor(YAMLObj1.yaml_tag, YAMLObj1.from_yaml) + x = yaml.load('!obj:x.2\na: 1') + print(x) + buf = ruyaml.compat.StringIO() + yaml.dump(x, buf) + assert buf.getvalue() == """!obj:x.2 "{'a': 1}"\n""" + + +def test_yaml_obj_with_loader_and_dumper(): + import ruyaml # NOQA + + yaml = ruyaml.YAML(typ='unsafe', pure=True) + ruyaml.add_representer(Obj1, YAMLObj1.to_yaml, Dumper=ruyaml.Dumper) + ruyaml.add_multi_constructor( + YAMLObj1.yaml_tag, YAMLObj1.from_yaml, Loader=ruyaml.Loader + ) + x = yaml.load('!obj:x.2\na: 1') + # x = ruyaml.load('!obj:x.2\na: 1') + print(x) + buf = ruyaml.compat.StringIO() + yaml.dump(x, buf) + assert buf.getvalue() == """!obj:x.2 "{'a': 1}"\n""" + + +# ToDo use nullege to search add_multi_representer and add_path_resolver +# and add some test code + +# Issue 127 reported by Tommy Wang + + +def test_issue_127(): + import ruyaml # NOQA + + class Ref(ruyaml.YAMLObject): + yaml_constructor = ruyaml.RoundTripConstructor + yaml_representer = ruyaml.RoundTripRepresenter + yaml_tag = '!Ref' + + def __init__(self, logical_id): + self.logical_id = logical_id + + @classmethod + def from_yaml(cls, loader, node): + return cls(loader.construct_scalar(node)) + + @classmethod + def to_yaml(cls, dumper, data): + if isinstance(data.logical_id, ruyaml.scalarstring.ScalarString): + style = data.logical_id.style # ruyaml>0.15.8 + else: + style = None + return dumper.represent_scalar(cls.yaml_tag, data.logical_id, style=style) + + document = dedent( + """\ + AList: + - !Ref One + - !Ref 'Two' + - !Ref + Two and a half + BList: [!Ref Three, !Ref "Four"] + CList: + - Five Six + - 'Seven Eight' + """ + ) + yaml = ruyaml.YAML() + yaml.preserve_quotes = True + yaml.default_flow_style = None + yaml.indent(sequence=4, offset=2) + data = yaml.load(document) + buf = ruyaml.compat.StringIO() + yaml.dump(data, buf) + assert buf.getvalue() == document.replace('\n Two and', ' Two and') diff --git a/_test/test_anchor.py b/_test/test_anchor.py new file mode 100644 index 0000000..5003428 --- /dev/null +++ b/_test/test_anchor.py @@ -0,0 +1,608 @@ +# coding: utf-8 + +""" +testing of anchors and the aliases referring to them +""" + +import platform +from textwrap import dedent + +import pytest + +from .roundtrip import ( # NOQA + YAML, + dedent, + round_trip, + round_trip_dump, + round_trip_load, +) + + +def load(s): + return round_trip_load(dedent(s)) + + +def compare(d, s): + assert round_trip_dump(d) == dedent(s) + + +class TestAnchorsAliases: + def test_anchor_id_renumber(self): + from ruyaml.serializer import Serializer + + assert Serializer.ANCHOR_TEMPLATE == 'id%03d' + data = load( + """ + a: &id002 + b: 1 + c: 2 + d: *id002 + """ + ) + compare( + data, + """ + a: &id001 + b: 1 + c: 2 + d: *id001 + """, + ) + + def test_template_matcher(self): + """test if id matches the anchor template""" + from ruyaml.serializer import templated_id + + assert templated_id('id001') + assert templated_id('id999') + assert templated_id('id1000') + assert templated_id('id0001') + assert templated_id('id0000') + assert not templated_id('id02') + assert not templated_id('id000') + assert not templated_id('x000') + + # def test_re_matcher(self): + # import re + # assert re.compile('id(?!000)\\d{3,}').match('id001') + # assert not re.compile('id(?!000\\d*)\\d{3,}').match('id000') + # assert re.compile('id(?!000$)\\d{3,}').match('id0001') + + def test_anchor_assigned(self): + from ruyaml.comments import CommentedMap + + data = load( + """ + a: &id002 + b: 1 + c: 2 + d: *id002 + e: &etemplate + b: 1 + c: 2 + f: *etemplate + """ + ) + d = data['d'] + assert isinstance(d, CommentedMap) + assert d.yaml_anchor() is None # got dropped as it matches pattern + e = data['e'] + assert isinstance(e, CommentedMap) + assert e.yaml_anchor().value == 'etemplate' + assert e.yaml_anchor().always_dump is False + + def test_anchor_id_retained(self): + data = load( + """ + a: &id002 + b: 1 + c: 2 + d: *id002 + e: &etemplate + b: 1 + c: 2 + f: *etemplate + """ + ) + compare( + data, + """ + a: &id001 + b: 1 + c: 2 + d: *id001 + e: &etemplate + b: 1 + c: 2 + f: *etemplate + """, + ) + + @pytest.mark.skipif( + platform.python_implementation() == 'Jython', + reason='Jython throws RepresenterError', + ) + def test_alias_before_anchor(self): + from ruyaml.composer import ComposerError + + with pytest.raises(ComposerError): + data = load( + """ + d: *id002 + a: &id002 + b: 1 + c: 2 + """ + ) + data = data + + def test_anchor_on_sequence(self): + # as reported by Bjorn Stabell + # https://bitbucket.org/ruyaml/issue/7/anchor-names-not-preserved + from ruyaml.comments import CommentedSeq + + data = load( + """ + nut1: &alice + - 1 + - 2 + nut2: &blake + - some data + - *alice + nut3: + - *blake + - *alice + """ + ) + r = data['nut1'] + assert isinstance(r, CommentedSeq) + assert r.yaml_anchor() is not None + assert r.yaml_anchor().value == 'alice' + + merge_yaml = dedent( + """ + - &CENTER {x: 1, y: 2} + - &LEFT {x: 0, y: 2} + - &BIG {r: 10} + - &SMALL {r: 1} + # All the following maps are equal: + # Explicit keys + - x: 1 + y: 2 + r: 10 + label: center/small + # Merge one map + - <<: *CENTER + r: 10 + label: center/medium + # Merge multiple maps + - <<: [*CENTER, *BIG] + label: center/big + # Override + - <<: [*BIG, *LEFT, *SMALL] + x: 1 + label: center/huge + """ + ) + + def test_merge_00(self): + data = load(self.merge_yaml) + d = data[4] + ok = True + for k in d: + for o in [5, 6, 7]: + x = d.get(k) + y = data[o].get(k) + if not isinstance(x, int): + x = x.split('/')[0] + y = y.split('/')[0] + if x != y: + ok = False + print('key', k, d.get(k), data[o].get(k)) + assert ok + + def test_merge_accessible(self): + from ruyaml.comments import CommentedMap, merge_attrib + + data = load( + """ + k: &level_2 { a: 1, b2 } + l: &level_1 { a: 10, c: 3 } + m: + <<: *level_1 + c: 30 + d: 40 + """ + ) + d = data['m'] + assert isinstance(d, CommentedMap) + assert hasattr(d, merge_attrib) + + def test_merge_01(self): + data = load(self.merge_yaml) + compare(data, self.merge_yaml) + + def test_merge_nested(self): + yaml = """ + a: + <<: &content + 1: plugh + 2: plover + 0: xyzzy + b: + <<: *content + """ + data = round_trip(yaml) # NOQA + + def test_merge_nested_with_sequence(self): + yaml = """ + a: + <<: &content + <<: &y2 + 1: plugh + 2: plover + 0: xyzzy + b: + <<: [*content, *y2] + """ + data = round_trip(yaml) # NOQA + + def test_add_anchor(self): + from ruyaml.comments import CommentedMap + + data = CommentedMap() + data_a = CommentedMap() + data['a'] = data_a + data_a['c'] = 3 + data['b'] = 2 + data.yaml_set_anchor('klm', always_dump=True) + data['a'].yaml_set_anchor('xyz', always_dump=True) + compare( + data, + """ + &klm + a: &xyz + c: 3 + b: 2 + """, + ) + + # this is an error in PyYAML + def test_reused_anchor(self): + from ruyaml.error import ReusedAnchorWarning + + yaml = """ + - &a + x: 1 + - <<: *a + - &a + x: 2 + - <<: *a + """ + with pytest.warns(ReusedAnchorWarning): + data = round_trip(yaml) # NOQA + + def test_issue_130(self): + # issue 130 reported by Devid Fee + import ruyaml + + ys = dedent( + """\ + components: + server: &server_component + type: spark.server:ServerComponent + host: 0.0.0.0 + port: 8000 + shell: &shell_component + type: spark.shell:ShellComponent + + services: + server: &server_service + <<: *server_component + shell: &shell_service + <<: *shell_component + components: + server: {<<: *server_service} + """ + ) + yaml = ruyaml.YAML(typ='safe', pure=True) + data = yaml.load(ys) + assert data['services']['shell']['components']['server']['port'] == 8000 + + def test_issue_130a(self): + # issue 130 reported by Devid Fee + import ruyaml + + ys = dedent( + """\ + components: + server: &server_component + type: spark.server:ServerComponent + host: 0.0.0.0 + port: 8000 + shell: &shell_component + type: spark.shell:ShellComponent + + services: + server: &server_service + <<: *server_component + port: 4000 + shell: &shell_service + <<: *shell_component + components: + server: {<<: *server_service} + """ + ) + yaml = ruyaml.YAML(typ='safe', pure=True) + data = yaml.load(ys) + assert data['services']['shell']['components']['server']['port'] == 4000 + + +class TestMergeKeysValues: + + yaml_str = dedent( + """\ + - &mx + a: x1 + b: x2 + c: x3 + - &my + a: y1 + b: y2 # masked by the one in &mx + d: y4 + - + a: 1 + <<: [*mx, *my] + m: 6 + """ + ) + + # in the following d always has "expanded" the merges + + def test_merge_for(self): + from ruyaml import YAML + + d = YAML(typ='safe', pure=True).load(self.yaml_str) + data = round_trip_load(self.yaml_str) + count = 0 + for x in data[2]: + count += 1 + print(count, x) + assert count == len(d[2]) + + def test_merge_keys(self): + from ruyaml import YAML + + d = YAML(typ='safe', pure=True).load(self.yaml_str) + data = round_trip_load(self.yaml_str) + count = 0 + for x in data[2].keys(): + count += 1 + print(count, x) + assert count == len(d[2]) + + def test_merge_values(self): + from ruyaml import YAML + + d = YAML(typ='safe', pure=True).load(self.yaml_str) + data = round_trip_load(self.yaml_str) + count = 0 + for x in data[2].values(): + count += 1 + print(count, x) + assert count == len(d[2]) + + def test_merge_items(self): + from ruyaml import YAML + + d = YAML(typ='safe', pure=True).load(self.yaml_str) + data = round_trip_load(self.yaml_str) + count = 0 + for x in data[2].items(): + count += 1 + print(count, x) + assert count == len(d[2]) + + def test_len_items_delete(self): + from ruyaml import YAML + + d = YAML(typ='safe', pure=True).load(self.yaml_str) + data = round_trip_load(self.yaml_str) + x = data[2].items() + print('d2 items', d[2].items(), len(d[2].items()), x, len(x)) + ref = len(d[2].items()) + print('ref', ref) + assert len(x) == ref + del data[2]['m'] + ref -= 1 + assert len(x) == ref + del data[2]['d'] + ref -= 1 + assert len(x) == ref + del data[2]['a'] + ref -= 1 + assert len(x) == ref + + def test_issue_196_cast_of_dict(self, capsys): + from ruyaml import YAML + + yaml = YAML() + mapping = yaml.load( + """\ + anchored: &anchor + a : 1 + + mapping: + <<: *anchor + b: 2 + """ + )['mapping'] + + for k in mapping: + print('k', k) + for k in mapping.copy(): + print('kc', k) + + print('v', list(mapping.keys())) + print('v', list(mapping.values())) + print('v', list(mapping.items())) + print(len(mapping)) + print('-----') + + # print({**mapping}) + # print(type({**mapping})) + # assert 'a' in {**mapping} + assert 'a' in mapping + x = {} + for k in mapping: + x[k] = mapping[k] + assert 'a' in x + assert 'a' in mapping.keys() + assert mapping['a'] == 1 + assert mapping.__getitem__('a') == 1 + assert 'a' in dict(mapping) + assert 'a' in dict(mapping.items()) + + def test_values_of_merged(self): + from ruyaml import YAML + + yaml = YAML() + data = yaml.load(dedent(self.yaml_str)) + assert list(data[2].values()) == [1, 6, 'x2', 'x3', 'y4'] + + def test_issue_213_copy_of_merge(self): + from ruyaml import YAML + + yaml = YAML() + d = yaml.load( + """\ + foo: &foo + a: a + foo2: + <<: *foo + b: b + """ + )['foo2'] + assert d['a'] == 'a' + d2 = d.copy() + assert d2['a'] == 'a' + print('d', d) + del d['a'] + assert 'a' not in d + assert 'a' in d2 + + def test_dup_merge(self): + from ruyaml import YAML + + yaml = YAML() + yaml.allow_duplicate_keys = True + d = yaml.load( + """\ + foo: &f + a: a + foo2: &g + b: b + all: + <<: *f + <<: *g + """ + )['all'] + assert d == {'a': 'a', 'b': 'b'} + + def test_dup_merge_fail(self): + from ruyaml import YAML + from ruyaml.constructor import DuplicateKeyError + + yaml = YAML() + yaml.allow_duplicate_keys = False + with pytest.raises(DuplicateKeyError): + yaml.load( + """\ + foo: &f + a: a + foo2: &g + b: b + all: + <<: *f + <<: *g + """ + ) + + +class TestDuplicateKeyThroughAnchor: + def test_duplicate_key_00(self): + from ruyaml import YAML, version_info + from ruyaml.constructor import DuplicateKeyError, DuplicateKeyFutureWarning + + s = dedent( + """\ + &anchor foo: + foo: bar + *anchor : duplicate key + baz: bat + *anchor : duplicate key + """ + ) + if version_info < (0, 15, 1): + pass + elif version_info < (0, 16, 0): + with pytest.warns(DuplicateKeyFutureWarning): + YAML(typ='safe', pure=True).load(s) + with pytest.warns(DuplicateKeyFutureWarning): + YAML(typ='rt').load(s) + else: + with pytest.raises(DuplicateKeyError): + YAML(typ='safe', pure=True).load(s) + with pytest.raises(DuplicateKeyError): + YAML(typ='rt').load(s) + + def test_duplicate_key_01(self): + # so issue https://stackoverflow.com/a/52852106/1307905 + from ruyaml.constructor import DuplicateKeyError + + s = dedent( + """\ + - &name-name + a: 1 + - &help-name + b: 2 + - <<: *name-name + <<: *help-name + """ + ) + with pytest.raises(DuplicateKeyError): + yaml = YAML(typ='safe') + yaml.load(s) + with pytest.raises(DuplicateKeyError): + yaml = YAML() + yaml.load(s) + + +class TestFullCharSetAnchors: + def test_master_of_orion(self): + # https://bitbucket.org/ruyaml/issues/72/not-allowed-in-anchor-names + # submitted by Shalon Wood + yaml_str = """ + - collection: &Backend.Civilizations.RacialPerk + items: + - key: perk_population_growth_modifier + - *Backend.Civilizations.RacialPerk + """ + data = load(yaml_str) # NOQA + + def test_roundtrip_00(self): + yaml_str = """ + - &dotted.words.here + a: 1 + b: 2 + - *dotted.words.here + """ + data = round_trip(yaml_str) # NOQA + + def test_roundtrip_01(self): + yaml_str = """ + - &dotted.words.here[a, b] + - *dotted.words.here + """ + data = load(yaml_str) # NOQA + compare(data, yaml_str.replace('[', ' [')) # an extra space is inserted diff --git a/_test/test_api_change.py b/_test/test_api_change.py new file mode 100644 index 0000000..dd25fd9 --- /dev/null +++ b/_test/test_api_change.py @@ -0,0 +1,230 @@ +# coding: utf-8 + +""" +testing of anchors and the aliases referring to them +""" + +import sys +import textwrap +from pathlib import Path + +import pytest + + +class TestNewAPI: + def test_duplicate_keys_00(self): + from ruyaml import YAML + from ruyaml.constructor import DuplicateKeyError + + yaml = YAML() + with pytest.raises(DuplicateKeyError): + yaml.load('{a: 1, a: 2}') + + def test_duplicate_keys_01(self): + from ruyaml import YAML + from ruyaml.constructor import DuplicateKeyError + + yaml = YAML(typ='safe', pure=True) + with pytest.raises(DuplicateKeyError): + yaml.load('{a: 1, a: 2}') + + def test_duplicate_keys_02(self): + from ruyaml import YAML + from ruyaml.constructor import DuplicateKeyError + + yaml = YAML(typ='safe') + with pytest.raises(DuplicateKeyError): + yaml.load('{a: 1, a: 2}') + + def test_issue_135(self): + # reported by Andrzej Ostrowski + from ruyaml import YAML + + data = {'a': 1, 'b': 2} + yaml = YAML(typ='safe') + # originally on 2.7: with pytest.raises(TypeError): + yaml.dump(data, sys.stdout) + + def test_issue_135_temporary_workaround(self): + # never raised error + from ruyaml import YAML + + data = {'a': 1, 'b': 2} + yaml = YAML(typ='safe', pure=True) + yaml.dump(data, sys.stdout) + + +class TestWrite: + def test_dump_path(self, tmpdir): + from ruyaml import YAML + + fn = Path(str(tmpdir)) / 'test.yaml' + yaml = YAML() + data = yaml.map() + data['a'] = 1 + data['b'] = 2 + yaml.dump(data, fn) + assert fn.read_text() == 'a: 1\nb: 2\n' + + def test_dump_file(self, tmpdir): + from ruyaml import YAML + + fn = Path(str(tmpdir)) / 'test.yaml' + yaml = YAML() + data = yaml.map() + data['a'] = 1 + data['b'] = 2 + with open(str(fn), 'w') as fp: + yaml.dump(data, fp) + assert fn.read_text() == 'a: 1\nb: 2\n' + + def test_dump_missing_stream(self): + from ruyaml import YAML + + yaml = YAML() + data = yaml.map() + data['a'] = 1 + data['b'] = 2 + with pytest.raises(TypeError): + yaml.dump(data) + + def test_dump_too_many_args(self, tmpdir): + from ruyaml import YAML + + fn = Path(str(tmpdir)) / 'test.yaml' + yaml = YAML() + data = yaml.map() + data['a'] = 1 + data['b'] = 2 + with pytest.raises(TypeError): + yaml.dump(data, fn, True) + + def test_transform(self, tmpdir): + from ruyaml import YAML + + def tr(s): + return s.replace(' ', ' ') + + fn = Path(str(tmpdir)) / 'test.yaml' + yaml = YAML() + data = yaml.map() + data['a'] = 1 + data['b'] = 2 + yaml.dump(data, fn, transform=tr) + assert fn.read_text() == 'a: 1\nb: 2\n' + + def test_print(self, capsys): + from ruyaml import YAML + + yaml = YAML() + data = yaml.map() + data['a'] = 1 + data['b'] = 2 + yaml.dump(data, sys.stdout) + out, err = capsys.readouterr() + assert out == 'a: 1\nb: 2\n' + + +class TestRead: + def test_multi_load(self): + # make sure reader, scanner, parser get reset + from ruyaml import YAML + + yaml = YAML() + yaml.load('a: 1') + yaml.load('a: 1') # did not work in 0.15.4 + + def test_parse(self): + # ensure `parse` method is functional and can parse "unsafe" yaml + from ruyaml import YAML + from ruyaml.constructor import ConstructorError + + yaml = YAML(typ='safe') + s = '- !User0 {age: 18, name: Anthon}' + # should fail to load + with pytest.raises(ConstructorError): + yaml.load(s) + # should parse fine + yaml = YAML(typ='safe') + for _ in yaml.parse(s): + pass + + +class TestLoadAll: + def test_multi_document_load(self, tmpdir): + """this went wrong on 3.7 because of StopIteration, PR 37 and Issue 211""" + from ruyaml import YAML + + fn = Path(str(tmpdir)) / 'test.yaml' + fn.write_text( + textwrap.dedent( + """\ + --- + - a + --- + - b + ... + """ + ) + ) + yaml = YAML() + assert list(yaml.load_all(fn)) == [['a'], ['b']] + + +class TestDuplSet: + def test_dupl_set_00(self): + # round-trip-loader should except + from ruyaml import YAML + from ruyaml.constructor import DuplicateKeyError + + yaml = YAML() + with pytest.raises(DuplicateKeyError): + yaml.load( + textwrap.dedent( + """\ + !!set + ? a + ? b + ? c + ? a + """ + ) + ) + + +class TestDumpLoadUnicode: + # test triggered by SamH on stackoverflow (https://stackoverflow.com/q/45281596/1307905) + # and answer by randomir (https://stackoverflow.com/a/45281922/1307905) + def test_write_unicode(self, tmpdir): + from ruyaml import YAML + + yaml = YAML() + text_dict = {'text': 'HELLO_WORLD©'} + file_name = str(tmpdir) + '/tstFile.yaml' + yaml.dump(text_dict, open(file_name, 'w')) + assert open(file_name, 'rb').read().decode('utf-8') == 'text: HELLO_WORLD©\n' + + def test_read_unicode(self, tmpdir): + from ruyaml import YAML + + yaml = YAML() + file_name = str(tmpdir) + '/tstFile.yaml' + with open(file_name, 'wb') as fp: + fp.write('text: HELLO_WORLD©\n'.encode('utf-8')) + text_dict = yaml.load(open(file_name, 'r')) + assert text_dict['text'] == 'HELLO_WORLD©' + + +class TestFlowStyle: + def test_flow_style(self, capsys): + # https://stackoverflow.com/questions/45791712/ + from ruyaml import YAML + + yaml = YAML() + yaml.default_flow_style = None + data = yaml.map() + data['b'] = 1 + data['a'] = [[1, 2], [3, 4]] + yaml.dump(data, sys.stdout) + out, err = capsys.readouterr() + assert out == 'b: 1\na:\n- [1, 2]\n- [3, 4]\n' diff --git a/_test/test_class_register.py b/_test/test_class_register.py new file mode 100644 index 0000000..54c2191 --- /dev/null +++ b/_test/test_class_register.py @@ -0,0 +1,141 @@ +# coding: utf-8 + +""" +testing of YAML.register_class and @yaml_object +""" + +from .roundtrip import YAML + + +class User0: + def __init__(self, name, age): + self.name = name + self.age = age + + +class User1(object): + yaml_tag = '!user' + + def __init__(self, name, age): + self.name = name + self.age = age + + @classmethod + def to_yaml(cls, representer, node): + return representer.represent_scalar( + cls.yaml_tag, '{.name}-{.age}'.format(node, node) + ) + + @classmethod + def from_yaml(cls, constructor, node): + return cls(*node.value.split('-')) + + +class TestRegisterClass: + def test_register_0_rt(self): + yaml = YAML() + yaml.register_class(User0) + ys = """ + - !User0 + name: Anthon + age: 18 + """ + d = yaml.load(ys) + yaml.dump(d, compare=ys, unordered_lines=True) + + def test_register_0_safe(self): + # default_flow_style = None + yaml = YAML(typ='safe') + yaml.register_class(User0) + ys = """ + - !User0 {age: 18, name: Anthon} + """ + d = yaml.load(ys) + yaml.dump(d, compare=ys) + + def test_register_0_unsafe(self): + # default_flow_style = None + yaml = YAML(typ='unsafe') + yaml.register_class(User0) + ys = """ + - !User0 {age: 18, name: Anthon} + """ + d = yaml.load(ys) + yaml.dump(d, compare=ys) + + def test_register_1_rt(self): + yaml = YAML() + yaml.register_class(User1) + ys = """ + - !user Anthon-18 + """ + d = yaml.load(ys) + yaml.dump(d, compare=ys) + + def test_register_1_safe(self): + yaml = YAML(typ='safe') + yaml.register_class(User1) + ys = """ + [!user Anthon-18] + """ + d = yaml.load(ys) + yaml.dump(d, compare=ys) + + def test_register_1_unsafe(self): + yaml = YAML(typ='unsafe') + yaml.register_class(User1) + ys = """ + [!user Anthon-18] + """ + d = yaml.load(ys) + yaml.dump(d, compare=ys) + + +class TestDecorator: + def test_decorator_implicit(self): + from ruyaml import yaml_object + + yml = YAML() + + @yaml_object(yml) + class User2: + def __init__(self, name, age): + self.name = name + self.age = age + + ys = """ + - !User2 + name: Anthon + age: 18 + """ + d = yml.load(ys) + yml.dump(d, compare=ys, unordered_lines=True) + + def test_decorator_explicit(self): + from ruyaml import yaml_object + + yml = YAML() + + @yaml_object(yml) + class User3(object): + yaml_tag = '!USER' + + def __init__(self, name, age): + self.name = name + self.age = age + + @classmethod + def to_yaml(cls, representer, node): + return representer.represent_scalar( + cls.yaml_tag, '{.name}-{.age}'.format(node, node) + ) + + @classmethod + def from_yaml(cls, constructor, node): + return cls(*node.value.split('-')) + + ys = """ + - !USER Anthon-18 + """ + d = yml.load(ys) + yml.dump(d, compare=ys) diff --git a/_test/test_collections.py b/_test/test_collections.py new file mode 100644 index 0000000..579e30f --- /dev/null +++ b/_test/test_collections.py @@ -0,0 +1,19 @@ +# coding: utf-8 + +""" +collections.OrderedDict is a new class not supported by PyYAML (issue 83 by Frazer McLean) + +This is now so integrated in Python that it can be mapped to !!omap + +""" + +import pytest # NOQA + +from .roundtrip import dedent, round_trip, round_trip_dump, round_trip_load # NOQA + + +class TestOrderedDict: + def test_ordereddict(self): + from collections import OrderedDict + + assert round_trip_dump(OrderedDict()) == '!!omap []\n' diff --git a/_test/test_comment_manipulation.py b/_test/test_comment_manipulation.py new file mode 100644 index 0000000..39fde99 --- /dev/null +++ b/_test/test_comment_manipulation.py @@ -0,0 +1,721 @@ +# coding: utf-8 + +import pytest # NOQA + +from .roundtrip import dedent, round_trip, round_trip_dump, round_trip_load # NOQA + + +def load(s): + return round_trip_load(dedent(s)) + + +def compare(data, s, **kw): + assert round_trip_dump(data, **kw) == dedent(s) + + +def compare_eol(data, s): + assert 'EOL' in s + ds = dedent(s).replace('EOL', '').replace('\n', '|\n') + assert round_trip_dump(data).replace('\n', '|\n') == ds + + +class TestCommentsManipulation: + + # list + def test_seq_set_comment_on_existing_explicit_column(self): + data = load( + """ + - a # comment 1 + - b + - c + """ + ) + data.yaml_add_eol_comment('comment 2', key=1, column=6) + exp = """ + - a # comment 1 + - b # comment 2 + - c + """ + compare(data, exp) + + def test_seq_overwrite_comment_on_existing_explicit_column(self): + data = load( + """ + - a # comment 1 + - b + - c + """ + ) + data.yaml_add_eol_comment('comment 2', key=0, column=6) + exp = """ + - a # comment 2 + - b + - c + """ + compare(data, exp) + + def test_seq_first_comment_explicit_column(self): + data = load( + """ + - a + - b + - c + """ + ) + data.yaml_add_eol_comment('comment 1', key=1, column=6) + exp = """ + - a + - b # comment 1 + - c + """ + compare(data, exp) + + def test_seq_set_comment_on_existing_column_prev(self): + data = load( + """ + - a # comment 1 + - b + - c + - d # comment 3 + """ + ) + data.yaml_add_eol_comment('comment 2', key=1) + exp = """ + - a # comment 1 + - b # comment 2 + - c + - d # comment 3 + """ + compare(data, exp) + + def test_seq_set_comment_on_existing_column_next(self): + data = load( + """ + - a # comment 1 + - b + - c + - d # comment 3 + """ + ) + print(data._yaml_comment) + # print(type(data._yaml_comment._items[0][0].start_mark)) + # ruyaml.error.Mark + # print(type(data._yaml_comment._items[0][0].start_mark)) + data.yaml_add_eol_comment('comment 2', key=2) + exp = """ + - a # comment 1 + - b + - c # comment 2 + - d # comment 3 + """ + compare(data, exp) + + def test_seq_set_comment_on_existing_column_further_away(self): + """ + no comment line before or after, take the latest before + the new position + """ + data = load( + """ + - a # comment 1 + - b + - c + - d + - e + - f # comment 3 + """ + ) + print(data._yaml_comment) + # print(type(data._yaml_comment._items[0][0].start_mark)) + # ruyaml.error.Mark + # print(type(data._yaml_comment._items[0][0].start_mark)) + data.yaml_add_eol_comment('comment 2', key=3) + exp = """ + - a # comment 1 + - b + - c + - d # comment 2 + - e + - f # comment 3 + """ + compare(data, exp) + + def test_seq_set_comment_on_existing_explicit_column_with_hash(self): + data = load( + """ + - a # comment 1 + - b + - c + """ + ) + data.yaml_add_eol_comment('# comment 2', key=1, column=6) + exp = """ + - a # comment 1 + - b # comment 2 + - c + """ + compare(data, exp) + + # dict + + def test_dict_set_comment_on_existing_explicit_column(self): + data = load( + """ + a: 1 # comment 1 + b: 2 + c: 3 + d: 4 + e: 5 + """ + ) + data.yaml_add_eol_comment('comment 2', key='c', column=7) + exp = """ + a: 1 # comment 1 + b: 2 + c: 3 # comment 2 + d: 4 + e: 5 + """ + compare(data, exp) + + def test_dict_overwrite_comment_on_existing_explicit_column(self): + data = load( + """ + a: 1 # comment 1 + b: 2 + c: 3 + d: 4 + e: 5 + """ + ) + data.yaml_add_eol_comment('comment 2', key='a', column=7) + exp = """ + a: 1 # comment 2 + b: 2 + c: 3 + d: 4 + e: 5 + """ + compare(data, exp) + + def test_map_set_comment_on_existing_column_prev(self): + data = load( + """ + a: 1 # comment 1 + b: 2 + c: 3 + d: 4 + e: 5 # comment 3 + """ + ) + data.yaml_add_eol_comment('comment 2', key='b') + exp = """ + a: 1 # comment 1 + b: 2 # comment 2 + c: 3 + d: 4 + e: 5 # comment 3 + """ + compare(data, exp) + + def test_map_set_comment_on_existing_column_next(self): + data = load( + """ + a: 1 # comment 1 + b: 2 + c: 3 + d: 4 + e: 5 # comment 3 + """ + ) + data.yaml_add_eol_comment('comment 2', key='d') + exp = """ + a: 1 # comment 1 + b: 2 + c: 3 + d: 4 # comment 2 + e: 5 # comment 3 + """ + compare(data, exp) + + def test_map_set_comment_on_existing_column_further_away(self): + """ + no comment line before or after, take the latest before + the new position + """ + data = load( + """ + a: 1 # comment 1 + b: 2 + c: 3 + d: 4 + e: 5 # comment 3 + """ + ) + data.yaml_add_eol_comment('comment 2', key='c') + print(round_trip_dump(data)) + exp = """ + a: 1 # comment 1 + b: 2 + c: 3 # comment 2 + d: 4 + e: 5 # comment 3 + """ + compare(data, exp) + + def test_before_top_map_rt(self): + data = load( + """ + a: 1 + b: 2 + """ + ) + data.yaml_set_start_comment('Hello\nWorld\n') + exp = """ + # Hello + # World + a: 1 + b: 2 + """ + compare(data, exp.format(comment='#')) + + def test_before_top_map_replace(self): + data = load( + """ + # abc + # def + a: 1 # 1 + b: 2 + """ + ) + data.yaml_set_start_comment('Hello\nWorld\n') + exp = """ + # Hello + # World + a: 1 # 1 + b: 2 + """ + compare(data, exp.format(comment='#')) + + def test_before_top_map_from_scratch(self): + from ruyaml.comments import CommentedMap + + data = CommentedMap() + data['a'] = 1 + data['b'] = 2 + data.yaml_set_start_comment('Hello\nWorld\n') + # print(data.ca) + # print(data.ca._items) + exp = """ + # Hello + # World + a: 1 + b: 2 + """ + compare(data, exp.format(comment='#')) + + def test_before_top_seq_rt(self): + data = load( + """ + - a + - b + """ + ) + data.yaml_set_start_comment('Hello\nWorld\n') + print(round_trip_dump(data)) + exp = """ + # Hello + # World + - a + - b + """ + compare(data, exp) + + def test_before_top_seq_rt_replace(self): + s = """ + # this + # that + - a + - b + """ + data = load(s.format(comment='#')) + data.yaml_set_start_comment('Hello\nWorld\n') + print(round_trip_dump(data)) + exp = """ + # Hello + # World + - a + - b + """ + compare(data, exp.format(comment='#')) + + def test_before_top_seq_from_scratch(self): + from ruyaml.comments import CommentedSeq + + data = CommentedSeq() + data.append('a') + data.append('b') + data.yaml_set_start_comment('Hello\nWorld\n') + print(round_trip_dump(data)) + exp = """ + # Hello + # World + - a + - b + """ + compare(data, exp.format(comment='#')) + + # nested variants + def test_before_nested_map_rt(self): + data = load( + """ + a: 1 + b: + c: 2 + d: 3 + """ + ) + data['b'].yaml_set_start_comment('Hello\nWorld\n') + exp = """ + a: 1 + b: + # Hello + # World + c: 2 + d: 3 + """ + compare(data, exp.format(comment='#')) + + def test_before_nested_map_rt_indent(self): + data = load( + """ + a: 1 + b: + c: 2 + d: 3 + """ + ) + data['b'].yaml_set_start_comment('Hello\nWorld\n', indent=2) + exp = """ + a: 1 + b: + # Hello + # World + c: 2 + d: 3 + """ + compare(data, exp.format(comment='#')) + print(data['b'].ca) + + def test_before_nested_map_from_scratch(self): + from ruyaml.comments import CommentedMap + + data = CommentedMap() + datab = CommentedMap() + data['a'] = 1 + data['b'] = datab + datab['c'] = 2 + datab['d'] = 3 + data['b'].yaml_set_start_comment('Hello\nWorld\n') + exp = """ + a: 1 + b: + # Hello + # World + c: 2 + d: 3 + """ + compare(data, exp.format(comment='#')) + + def test_before_nested_seq_from_scratch(self): + from ruyaml.comments import CommentedMap, CommentedSeq + + data = CommentedMap() + datab = CommentedSeq() + data['a'] = 1 + data['b'] = datab + datab.append('c') + datab.append('d') + data['b'].yaml_set_start_comment('Hello\nWorld\n', indent=2) + exp = """ + a: 1 + b: + # Hello + # World + - c + - d + """ + compare(data, exp.format(comment='#')) + + def test_before_nested_seq_from_scratch_block_seq_indent(self): + from ruyaml.comments import CommentedMap, CommentedSeq + + data = CommentedMap() + datab = CommentedSeq() + data['a'] = 1 + data['b'] = datab + datab.append('c') + datab.append('d') + data['b'].yaml_set_start_comment('Hello\nWorld\n', indent=2) + exp = """ + a: 1 + b: + # Hello + # World + - c + - d + """ + compare(data, exp.format(comment='#'), indent=4, block_seq_indent=2) + + def test_map_set_comment_before_and_after_non_first_key_00(self): + # http://stackoverflow.com/a/40705671/1307905 + data = load( + """ + xyz: + a: 1 # comment 1 + b: 2 + + test1: + test2: + test3: 3 + """ + ) + data.yaml_set_comment_before_after_key( + 'test1', 'before test1 (top level)', after='before test2' + ) + data['test1']['test2'].yaml_set_start_comment('after test2', indent=4) + exp = """ + xyz: + a: 1 # comment 1 + b: 2 + + # before test1 (top level) + test1: + # before test2 + test2: + # after test2 + test3: 3 + """ + compare(data, exp) + + def Xtest_map_set_comment_before_and_after_non_first_key_01(self): + data = load( + """ + xyz: + a: 1 # comment 1 + b: 2 + + test1: + test2: + test3: 3 + """ + ) + data.yaml_set_comment_before_after_key( + 'test1', 'before test1 (top level)', after='before test2\n\n' + ) + data['test1']['test2'].yaml_set_start_comment('after test2', indent=4) + # EOL is needed here as dedenting gets rid of spaces (as well as does Emacs + exp = """ + xyz: + a: 1 # comment 1 + b: 2 + + # before test1 (top level) + test1: + # before test2 + EOL + test2: + # after test2 + test3: 3 + """ + compare_eol(data, exp) + + # EOL is no longer necessary + # fixed together with issue # 216 + def test_map_set_comment_before_and_after_non_first_key_01(self): + data = load( + """ + xyz: + a: 1 # comment 1 + b: 2 + + test1: + test2: + test3: 3 + """ + ) + data.yaml_set_comment_before_after_key( + 'test1', 'before test1 (top level)', after='before test2\n\n' + ) + data['test1']['test2'].yaml_set_start_comment('after test2', indent=4) + exp = """ + xyz: + a: 1 # comment 1 + b: 2 + + # before test1 (top level) + test1: + # before test2 + + test2: + # after test2 + test3: 3 + """ + compare(data, exp) + + def Xtest_map_set_comment_before_and_after_non_first_key_02(self): + data = load( + """ + xyz: + a: 1 # comment 1 + b: 2 + + test1: + test2: + test3: 3 + """ + ) + data.yaml_set_comment_before_after_key( + 'test1', + 'xyz\n\nbefore test1 (top level)', + after='\nbefore test2', + after_indent=4, + ) + data['test1']['test2'].yaml_set_start_comment('after test2', indent=4) + # EOL is needed here as dedenting gets rid of spaces (as well as does Emacs + exp = """ + xyz: + a: 1 # comment 1 + b: 2 + + # xyz + + # before test1 (top level) + test1: + EOL + # before test2 + test2: + # after test2 + test3: 3 + """ + compare_eol(data, exp) + + def test_map_set_comment_before_and_after_non_first_key_02(self): + data = load( + """ + xyz: + a: 1 # comment 1 + b: 2 + + test1: + test2: + test3: 3 + """ + ) + data.yaml_set_comment_before_after_key( + 'test1', + 'xyz\n\nbefore test1 (top level)', + after='\nbefore test2', + after_indent=4, + ) + data['test1']['test2'].yaml_set_start_comment('after test2', indent=4) + exp = """ + xyz: + a: 1 # comment 1 + b: 2 + + # xyz + + # before test1 (top level) + test1: + + # before test2 + test2: + # after test2 + test3: 3 + """ + compare(data, exp) + + # issue 32 + def test_yaml_add_eol_comment_issue_32(self): + data = load( + """ + items: + - one: 1 + uno: '1' + - # item 2 + two: 2 + duo: '2' + - three: 3 + """ + ) + + data['items'].yaml_add_eol_comment('second pass', key=1) + + exp = """ + items: + - one: 1 + uno: '1' + - # second pass + two: 2 + duo: '2' + - three: 3 + """ + + compare(data, exp) + + def test_yaml_add_eol_comment_issue_32_ok(self): + data = load( + """ + items: + - one + - two # item 2 + - three + """ + ) + + data['items'].yaml_add_eol_comment('second pass', key=1) + + exp = """ + items: + - one + - two # second pass + - three + """ + + compare(data, exp) + + # issue 33 + @pytest.mark.xfail(reason="open issue", raises=AttributeError) + def test_yaml_set_start_comment_issue_33(self): + data = load( + """ + items: + # item 1 + - one: 1 + uno: '1' + # item 2 + - two: 2 + duo: '2' + # item 3 + - three: 3 + """ + ) + + data['items'][0].yaml_set_start_comment('uno') + data['items'][1].yaml_set_start_comment('duo') + data['items'][2].yaml_set_start_comment('tre') + + exp = """ + items: + # uno + - one: 1 + uno: '1' + # duo + - two: 2 + duo: '2' + # tre + - three: 3 + """ + + compare(data, exp) diff --git a/_test/test_comments.py b/_test/test_comments.py new file mode 100644 index 0000000..7973349 --- /dev/null +++ b/_test/test_comments.py @@ -0,0 +1,964 @@ +# coding: utf-8 + +""" +comment testing is all about roundtrips +these can be done in the "old" way by creating a file.data and file.roundtrip +but there is little flexibility in doing that + +but some things are not easily tested, eog. how a +roundtrip changes + +""" + +import pytest + +from .roundtrip import dedent, round_trip, round_trip_dump, round_trip_load + + +class TestComments: + def test_no_end_of_file_eol(self): + """not excluding comments caused some problems if at the end of + the file without a newline. First error, then included \0""" + x = """\ + - europe: 10 # abc""" + round_trip(x, extra='\n') + with pytest.raises(AssertionError): + round_trip(x, extra='a\n') + + def test_no_comments(self): + round_trip( + """ + - europe: 10 + - usa: + - ohio: 2 + - california: 9 + """ + ) + + def test_round_trip_ordering(self): + round_trip( + """ + a: 1 + b: 2 + c: 3 + b1: 2 + b2: 2 + d: 4 + e: 5 + f: 6 + """ + ) + + def test_complex(self): + round_trip( + """ + - europe: 10 # top + - usa: + - ohio: 2 + - california: 9 # o + """ + ) + + def test_dropped(self): + s = """\ + # comment + scalar + ... + """ + round_trip(s, 'scalar\n...\n') + + def test_main_mapping_begin_end(self): + round_trip( + """ + # C start a + # C start b + abc: 1 + ghi: 2 + klm: 3 + # C end a + # C end b + """ + ) + + def test_reindent(self): + x = """\ + a: + b: # comment 1 + c: 1 # comment 2 + """ + d = round_trip_load(x) + y = round_trip_dump(d, indent=4) + assert y == dedent( + """\ + a: + b: # comment 1 + c: 1 # comment 2 + """ + ) + + def test_main_mapping_begin_end_items_post(self): + round_trip( + """ + # C start a + # C start b + abc: 1 # abc comment + ghi: 2 + klm: 3 # klm comment + # C end a + # C end b + """ + ) + + def test_main_sequence_begin_end(self): + round_trip( + """ + # C start a + # C start b + - abc + - ghi + - klm + # C end a + # C end b + """ + ) + + def test_main_sequence_begin_end_items_post(self): + round_trip( + """ + # C start a + # C start b + - abc # abc comment + - ghi + - klm # klm comment + # C end a + # C end b + """ + ) + + def test_main_mapping_begin_end_complex(self): + round_trip( + """ + # C start a + # C start b + abc: 1 + ghi: 2 + klm: + 3a: alpha + 3b: beta # it is all greek to me + # C end a + # C end b + """ + ) + + def test_09(self): # 2.9 from the examples in the spec + s = """\ + hr: # 1998 hr ranking + - Mark McGwire + - Sammy Sosa + rbi: + # 1998 rbi ranking + - Sammy Sosa + - Ken Griffey + """ + round_trip(s, indent=4, block_seq_indent=2) + + def test_09a(self): + round_trip( + """ + hr: # 1998 hr ranking + - Mark McGwire + - Sammy Sosa + rbi: + # 1998 rbi ranking + - Sammy Sosa + - Ken Griffey + """ + ) + + def test_simple_map_middle_comment(self): + round_trip( + """ + abc: 1 + # C 3a + # C 3b + ghi: 2 + """ + ) + + def test_map_in_map_0(self): + round_trip( + """ + map1: # comment 1 + # comment 2 + map2: + key1: val1 + """ + ) + + def test_map_in_map_1(self): + # comment is moved from value to key + round_trip( + """ + map1: + # comment 1 + map2: + key1: val1 + """ + ) + + def test_application_arguments(self): + # application configur + round_trip( + """ + args: + username: anthon + passwd: secret + fullname: Anthon van der Neut + tmux: + session-name: test + loop: + wait: 10 + """ + ) + + def test_substitute(self): + x = """ + args: + username: anthon # name + passwd: secret # password + fullname: Anthon van der Neut + tmux: + session-name: test + loop: + wait: 10 + """ + data = round_trip_load(x) + data['args']['passwd'] = 'deleted password' + # note the requirement to add spaces for alignment of comment + x = x.replace(': secret ', ': deleted password') + assert round_trip_dump(data) == dedent(x) + + def test_set_comment(self): + round_trip( + """ + !!set + # the beginning + ? a + # next one is B (lowercase) + ? b # You see? Promised you. + ? c + # this is the end + """ + ) + + def test_omap_comment_roundtrip(self): + round_trip( + """ + !!omap + - a: 1 + - b: 2 # two + - c: 3 # three + - d: 4 + """ + ) + + def test_omap_comment_roundtrip_pre_comment(self): + round_trip( + """ + !!omap + - a: 1 + - b: 2 # two + - c: 3 # three + # last one + - d: 4 + """ + ) + + def test_non_ascii(self): + round_trip( + """ + verbosity: 1 # 0 is minimal output, -1 none + base_url: http://gopher.net + special_indices: [1, 5, 8] + also_special: + - a + - 19 + - 32 + asia and europe: &asia_europe + Turkey: Ankara + Russia: Moscow + countries: + Asia: + <<: *asia_europe + Japan: Tokyo # æ±äº¬ + Europe: + <<: *asia_europe + Spain: Madrid + Italy: Rome + """ + ) + + def test_dump_utf8(self): + import ruyaml # NOQA + + x = dedent( + """\ + ab: + - x # comment + - y # more comment + """ + ) + data = round_trip_load(x) + for utf in [True, False]: + y = round_trip_dump(data, default_flow_style=False, allow_unicode=utf) + assert y == x + + def test_dump_unicode_utf8(self): + import ruyaml # NOQA + + x = dedent( + """\ + ab: + - x # comment + - y # more comment + """ + ) + data = round_trip_load(x) + for utf in [True, False]: + y = round_trip_dump(data, default_flow_style=False, allow_unicode=utf) + assert y == x + + def test_mlget_00(self): + x = """\ + a: + - b: + c: 42 + - d: + f: 196 + e: + g: 3.14 + """ + d = round_trip_load(x) + assert d.mlget(['a', 1, 'd', 'f'], list_ok=True) == 196 + # with pytest.raises(AssertionError): + # d.mlget(['a', 1, 'd', 'f']) == 196 + + +class TestInsertPopList: + """list insertion is more complex than dict insertion, as you + need to move the values to subsequent keys on insert""" + + @property + def ins(self): + return """\ + ab: + - a # a + - b # b + - c + - d # d + + de: + - 1 + - 2 + """ + + def test_insert_0(self): + d = round_trip_load(self.ins) + d['ab'].insert(0, 'xyz') + y = round_trip_dump(d, indent=2) + assert y == dedent( + """\ + ab: + - xyz + - a # a + - b # b + - c + - d # d + + de: + - 1 + - 2 + """ + ) + + def test_insert_1(self): + d = round_trip_load(self.ins) + d['ab'].insert(4, 'xyz') + y = round_trip_dump(d, indent=2) + assert y == dedent( + """\ + ab: + - a # a + - b # b + - c + - d # d + + - xyz + de: + - 1 + - 2 + """ + ) + + def test_insert_2(self): + d = round_trip_load(self.ins) + d['ab'].insert(1, 'xyz') + y = round_trip_dump(d, indent=2) + assert y == dedent( + """\ + ab: + - a # a + - xyz + - b # b + - c + - d # d + + de: + - 1 + - 2 + """ + ) + + def test_pop_0(self): + d = round_trip_load(self.ins) + d['ab'].pop(0) + y = round_trip_dump(d, indent=2) + print(y) + assert y == dedent( + """\ + ab: + - b # b + - c + - d # d + + de: + - 1 + - 2 + """ + ) + + def test_pop_1(self): + d = round_trip_load(self.ins) + d['ab'].pop(1) + y = round_trip_dump(d, indent=2) + print(y) + assert y == dedent( + """\ + ab: + - a # a + - c + - d # d + + de: + - 1 + - 2 + """ + ) + + def test_pop_2(self): + d = round_trip_load(self.ins) + d['ab'].pop(2) + y = round_trip_dump(d, indent=2) + print(y) + assert y == dedent( + """\ + ab: + - a # a + - b # b + - d # d + + de: + - 1 + - 2 + """ + ) + + def test_pop_3(self): + d = round_trip_load(self.ins) + d['ab'].pop(3) + y = round_trip_dump(d, indent=2) + print(y) + assert y == dedent( + """\ + ab: + - a # a + - b # b + - c + de: + - 1 + - 2 + """ + ) + + +# inspired by demux' question on stackoverflow +# http://stackoverflow.com/a/36970608/1307905 +class TestInsertInMapping: + @property + def ins(self): + return """\ + first_name: Art + occupation: Architect # This is an occupation comment + about: Art Vandelay is a fictional character that George invents... + """ + + def test_insert_at_pos_1(self): + d = round_trip_load(self.ins) + d.insert(1, 'last name', 'Vandelay', comment='new key') + y = round_trip_dump(d) + print(y) + assert y == dedent( + """\ + first_name: Art + last name: Vandelay # new key + occupation: Architect # This is an occupation comment + about: Art Vandelay is a fictional character that George invents... + """ + ) + + def test_insert_at_pos_0(self): + d = round_trip_load(self.ins) + d.insert(0, 'last name', 'Vandelay', comment='new key') + y = round_trip_dump(d) + print(y) + assert y == dedent( + """\ + last name: Vandelay # new key + first_name: Art + occupation: Architect # This is an occupation comment + about: Art Vandelay is a fictional character that George invents... + """ + ) + + def test_insert_at_pos_3(self): + # much more simple if done with appending. + d = round_trip_load(self.ins) + d.insert(3, 'last name', 'Vandelay', comment='new key') + y = round_trip_dump(d) + print(y) + assert y == dedent( + """\ + first_name: Art + occupation: Architect # This is an occupation comment + about: Art Vandelay is a fictional character that George invents... + last name: Vandelay # new key + """ + ) + + +class TestCommentedMapMerge: + def test_in_operator(self): + data = round_trip_load( + """ + x: &base + a: 1 + b: 2 + c: 3 + y: + <<: *base + k: 4 + l: 5 + """ + ) + assert data['x']['a'] == 1 + assert 'a' in data['x'] + assert data['y']['a'] == 1 + assert 'a' in data['y'] + + def test_issue_60(self): + data = round_trip_load( + """ + x: &base + a: 1 + y: + <<: *base + """ + ) + assert data['x']['a'] == 1 + assert data['y']['a'] == 1 + assert str(data['y']) == """ordereddict([('a', 1)])""" + + def test_issue_60_1(self): + data = round_trip_load( + """ + x: &base + a: 1 + y: + <<: *base + b: 2 + """ + ) + assert data['x']['a'] == 1 + assert data['y']['a'] == 1 + assert str(data['y']) == """ordereddict([('b', 2), ('a', 1)])""" + + +class TestEmptyLines: + # prompted by issue 46 from Alex Harvey + def test_issue_46(self): + yaml_str = dedent( + """\ + --- + # Please add key/value pairs in alphabetical order + + aws_s3_bucket: 'mys3bucket' + + jenkins_ad_credentials: + bind_name: 'CN=svc-AAA-BBB-T,OU=Example,DC=COM,DC=EXAMPLE,DC=Local' + bind_pass: 'xxxxyyyy{' + """ + ) + d = round_trip_load(yaml_str, preserve_quotes=True) + y = round_trip_dump(d, explicit_start=True) + assert yaml_str == y + + def test_multispace_map(self): + round_trip( + """ + a: 1x + + b: 2x + + + c: 3x + + + + d: 4x + + """ + ) + + @pytest.mark.xfail(strict=True) + def test_multispace_map_initial(self): + round_trip( + """ + + a: 1x + + b: 2x + + + c: 3x + + + + d: 4x + + """ + ) + + def test_embedded_map(self): + round_trip( + """ + - a: 1y + b: 2y + + c: 3y + """ + ) + + def test_toplevel_seq(self): + round_trip( + """\ + - 1 + + - 2 + + - 3 + """ + ) + + def test_embedded_seq(self): + round_trip( + """ + a: + b: + - 1 + + - 2 + + + - 3 + """ + ) + + def test_line_with_only_spaces(self): + # issue 54 + yaml_str = "---\n\na: 'x'\n \nb: y\n" + d = round_trip_load(yaml_str, preserve_quotes=True) + y = round_trip_dump(d, explicit_start=True) + stripped = "" + for line in yaml_str.splitlines(): + stripped += line.rstrip() + '\n' + print(line + '$') + assert stripped == y + + def test_some_eol_spaces(self): + # spaces after tokens and on empty lines + yaml_str = '--- \n \na: "x" \n \nb: y \n' + d = round_trip_load(yaml_str, preserve_quotes=True) + y = round_trip_dump(d, explicit_start=True) + stripped = "" + for line in yaml_str.splitlines(): + stripped += line.rstrip() + '\n' + print(line + '$') + assert stripped == y + + def test_issue_54_not_ok(self): + yaml_str = dedent( + """\ + toplevel: + + # some comment + sublevel: 300 + """ + ) + d = round_trip_load(yaml_str) + print(d.ca) + y = round_trip_dump(d, indent=4) + print(y.replace('\n', '$\n')) + assert yaml_str == y + + def test_issue_54_ok(self): + yaml_str = dedent( + """\ + toplevel: + # some comment + sublevel: 300 + """ + ) + d = round_trip_load(yaml_str) + y = round_trip_dump(d, indent=4) + assert yaml_str == y + + def test_issue_93(self): + round_trip( + """\ + a: + b: + - c1: cat # a1 + # my comment on catfish + - c2: catfish # a2 + """ + ) + + def test_issue_93_00(self): + round_trip( + """\ + a: + - - c1: cat # a1 + # my comment on catfish + - c2: catfish # a2 + """ + ) + + def test_issue_93_01(self): + round_trip( + """\ + - - c1: cat # a1 + # my comment on catfish + - c2: catfish # a2 + """ + ) + + def test_issue_93_02(self): + # never failed as there is no indent + round_trip( + """\ + - c1: cat + # my comment on catfish + - c2: catfish + """ + ) + + def test_issue_96(self): + # inserted extra line on trailing spaces + round_trip( + """\ + a: + b: + c: c_val + d: + + e: + g: g_val + """ + ) + + +class TestUnicodeComments: + def test_issue_55(self): # reported by Haraguroicha Hsu + round_trip( + """\ + name: TEST + description: test using + author: Harguroicha + sql: + command: |- + select name from testtbl where no = :no + + ci-test: + - :no: 04043709 # å°èŠ± + - :no: 05161690 # 茶 + - :no: 05293147 # ã€‡ð¤‹¥å· + - :no: 05338777 # 〇〇啓 + - :no: 05273867 # 〇 + - :no: 05205786 # 〇𤦌 + """ + ) + + +class TestEmptyValueBeforeComments: + def test_issue_25a(self): + round_trip( + """\ + - a: b + c: d + d: # foo + - e: f + """ + ) + + def test_issue_25a1(self): + round_trip( + """\ + - a: b + c: d + d: # foo + e: f + """ + ) + + def test_issue_25b(self): + round_trip( + """\ + var1: #empty + var2: something #notempty + """ + ) + + def test_issue_25c(self): + round_trip( + """\ + params: + a: 1 # comment a + b: # comment b + c: 3 # comment c + """ + ) + + def test_issue_25c1(self): + round_trip( + """\ + params: + a: 1 # comment a + b: # comment b + # extra + c: 3 # comment c + """ + ) + + def test_issue_25_00(self): + round_trip( + """\ + params: + a: 1 # comment a + b: # comment b + """ + ) + + def test_issue_25_01(self): + round_trip( + """\ + a: # comment 1 + # comment 2 + - b: # comment 3 + c: 1 # comment 4 + """ + ) + + def test_issue_25_02(self): + round_trip( + """\ + a: # comment 1 + # comment 2 + - b: 2 # comment 3 + """ + ) + + def test_issue_25_03(self): + s = """\ + a: # comment 1 + # comment 2 + - b: 2 # comment 3 + """ + round_trip(s, indent=4, block_seq_indent=2) + + def test_issue_25_04(self): + round_trip( + """\ + a: # comment 1 + # comment 2 + b: 1 # comment 3 + """ + ) + + def test_flow_seq_within_seq(self): + round_trip( + """\ + # comment 1 + - a + - b + # comment 2 + - c + - d + # comment 3 + - [e] + - f + # comment 4 + - [] + """ + ) + + def test_comment_after_block_scalar_indicator(self): + round_trip( + """\ + a: | # abc + test 1 + test 2 + # all done + """ + ) + + +test_block_scalar_commented_line_template = """\ +y: p +# Some comment + +a: | + x +{}b: y +""" + + +class TestBlockScalarWithComments: + # issue 99 reported by Colm O'Connor + def test_scalar_with_comments(self): + import ruyaml # NOQA + + for x in [ + "", + '\n', + '\n# Another comment\n', + '\n\n', + '\n\n# abc\n#xyz\n', + '\n\n# abc\n#xyz\n', + '# abc\n\n#xyz\n', + '\n\n # abc\n #xyz\n', + ]: + + commented_line = test_block_scalar_commented_line_template.format(x) + data = round_trip_load(commented_line) + + assert round_trip_dump(data) == commented_line diff --git a/_test/test_contextmanager.py b/_test/test_contextmanager.py new file mode 100644 index 0000000..4539614 --- /dev/null +++ b/_test/test_contextmanager.py @@ -0,0 +1,116 @@ +# coding: utf-8 + +""" +testing of anchors and the aliases referring to them +""" + +import sys + +import pytest + +single_doc = """\ +- a: 1 +- b: + - 2 + - 3 +""" + +single_data = [dict(a=1), dict(b=[2, 3])] + +multi_doc = """\ +--- +- abc +- xyz +--- +- a: 1 +- b: + - 2 + - 3 +""" + +multi_doc_data = [['abc', 'xyz'], single_data] + + +def get_yaml(): + from ruyaml import YAML + + return YAML() + + +class TestOldStyle: + def test_single_load(self): + d = get_yaml().load(single_doc) + print(d) + print(type(d[0])) + assert d == single_data + + def test_single_load_no_arg(self): + with pytest.raises(TypeError): + assert get_yaml().load() == single_data + + def test_multi_load(self): + data = list(get_yaml().load_all(multi_doc)) + assert data == multi_doc_data + + def test_single_dump(self, capsys): + get_yaml().dump(single_data, sys.stdout) + out, err = capsys.readouterr() + assert out == single_doc + + def test_multi_dump(self, capsys): + yaml = get_yaml() + yaml.explicit_start = True + yaml.dump_all(multi_doc_data, sys.stdout) + out, err = capsys.readouterr() + assert out == multi_doc + + +class TestContextManager: + def test_single_dump(self, capsys): + from ruyaml import YAML + + with YAML(output=sys.stdout) as yaml: + yaml.dump(single_data) + out, err = capsys.readouterr() + print(err) + assert out == single_doc + + def test_multi_dump(self, capsys): + from ruyaml import YAML + + with YAML(output=sys.stdout) as yaml: + yaml.explicit_start = True + yaml.dump(multi_doc_data[0]) + yaml.dump(multi_doc_data[1]) + + out, err = capsys.readouterr() + print(err) + assert out == multi_doc + + # input is not as simple with a context manager + # you need to indicate what you expect hence load and load_all + + # @pytest.mark.xfail(strict=True) + # def test_single_load(self): + # from ruyaml import YAML + # with YAML(input=single_doc) as yaml: + # assert yaml.load() == single_data + # + # @pytest.mark.xfail(strict=True) + # def test_multi_load(self): + # from ruyaml import YAML + # with YAML(input=multi_doc) as yaml: + # for idx, data in enumerate(yaml.load()): + # assert data == multi_doc_data[0] + + def test_roundtrip(self, capsys): + from ruyaml import YAML + + with YAML(output=sys.stdout) as yaml: + yaml.explicit_start = True + for data in yaml.load_all(multi_doc): + yaml.dump(data) + + out, err = capsys.readouterr() + print(err) + assert out == multi_doc diff --git a/_test/test_copy.py b/_test/test_copy.py new file mode 100644 index 0000000..7ebd4c1 --- /dev/null +++ b/_test/test_copy.py @@ -0,0 +1,135 @@ +# coding: utf-8 + +""" +Testing copy and deepcopy, instigated by Issue 84 (Peter Amstutz) +""" + +import copy + +import pytest # NOQA + +from .roundtrip import dedent, round_trip_dump, round_trip_load + + +class TestDeepCopy: + def test_preserve_flow_style_simple(self): + x = dedent( + """\ + {foo: bar, baz: quux} + """ + ) + data = round_trip_load(x) + data_copy = copy.deepcopy(data) + y = round_trip_dump(data_copy) + print('x [{}]'.format(x)) + print('y [{}]'.format(y)) + assert y == x + assert data.fa.flow_style() == data_copy.fa.flow_style() + + def test_deepcopy_flow_style_nested_dict(self): + x = dedent( + """\ + a: {foo: bar, baz: quux} + """ + ) + data = round_trip_load(x) + assert data['a'].fa.flow_style() is True + data_copy = copy.deepcopy(data) + assert data_copy['a'].fa.flow_style() is True + data_copy['a'].fa.set_block_style() + assert data['a'].fa.flow_style() != data_copy['a'].fa.flow_style() + assert data['a'].fa._flow_style is True + assert data_copy['a'].fa._flow_style is False + y = round_trip_dump(data_copy) + + print('x [{}]'.format(x)) + print('y [{}]'.format(y)) + assert y == dedent( + """\ + a: + foo: bar + baz: quux + """ + ) + + def test_deepcopy_flow_style_nested_list(self): + x = dedent( + """\ + a: [1, 2, 3] + """ + ) + data = round_trip_load(x) + assert data['a'].fa.flow_style() is True + data_copy = copy.deepcopy(data) + assert data_copy['a'].fa.flow_style() is True + data_copy['a'].fa.set_block_style() + assert data['a'].fa.flow_style() != data_copy['a'].fa.flow_style() + assert data['a'].fa._flow_style is True + assert data_copy['a'].fa._flow_style is False + y = round_trip_dump(data_copy) + + print('x [{}]'.format(x)) + print('y [{}]'.format(y)) + assert y == dedent( + """\ + a: + - 1 + - 2 + - 3 + """ + ) + + +class TestCopy: + def test_copy_flow_style_nested_dict(self): + x = dedent( + """\ + a: {foo: bar, baz: quux} + """ + ) + data = round_trip_load(x) + assert data['a'].fa.flow_style() is True + data_copy = copy.copy(data) + assert data_copy['a'].fa.flow_style() is True + data_copy['a'].fa.set_block_style() + assert data['a'].fa.flow_style() == data_copy['a'].fa.flow_style() + assert data['a'].fa._flow_style is False + assert data_copy['a'].fa._flow_style is False + y = round_trip_dump(data_copy) + z = round_trip_dump(data) + assert y == z + + assert y == dedent( + """\ + a: + foo: bar + baz: quux + """ + ) + + def test_copy_flow_style_nested_list(self): + x = dedent( + """\ + a: [1, 2, 3] + """ + ) + data = round_trip_load(x) + assert data['a'].fa.flow_style() is True + data_copy = copy.copy(data) + assert data_copy['a'].fa.flow_style() is True + data_copy['a'].fa.set_block_style() + assert data['a'].fa.flow_style() == data_copy['a'].fa.flow_style() + assert data['a'].fa._flow_style is False + assert data_copy['a'].fa._flow_style is False + y = round_trip_dump(data_copy) + + print('x [{}]'.format(x)) + print('y [{}]'.format(y)) + assert y == dedent( + """\ + a: + - 1 + - 2 + - 3 + """ + ) diff --git a/_test/test_cyaml.py b/_test/test_cyaml.py new file mode 100644 index 0000000..b16c7ab --- /dev/null +++ b/_test/test_cyaml.py @@ -0,0 +1,97 @@ +# coding: utf-8 + +import platform +import sys +from textwrap import dedent + +import pytest + +NO_CLIB_VER = (3, 10) + + +@pytest.mark.skipif( + platform.python_implementation() in ['Jython', 'PyPy'], + reason='Jython throws RepresenterError', +) +@pytest.mark.xfail(reason="cyaml not ported yet") +def test_load_cyaml(): + print("???????????????????????", platform.python_implementation()) + import ruyaml + + if sys.version_info >= NO_CLIB_VER: + return + yaml = ruyaml.YAML(typ='safe', pure=False) + assert ruyaml.__with_libyaml__ + + yaml.load('abc: 1') + + +@pytest.mark.skipif( + sys.version_info >= NO_CLIB_VER + or platform.python_implementation() in ['Jython', 'PyPy'], + reason='no _PyGC_FINALIZED', +) +def test_dump_cyaml(): + import ruyaml + + if sys.version_info >= NO_CLIB_VER: + return + data = {'a': 1, 'b': 2} + yaml = ruyaml.YAML(typ='safe', pure=False) + yaml.default_flow_style = False + yaml.allow_unicode = True + buf = ruyaml.compat.StringIO() + yaml.dump(data, buf) + assert buf.getvalue() == 'a: 1\nb: 2\n' + + +@pytest.mark.skipif( + platform.python_implementation() in ['Jython', 'PyPy'], reason='not avialable' +) +@pytest.mark.xfail(reason="cyaml not ported yet") +def test_load_cyaml_1_2(): + # issue 155 + import ruyaml + + if sys.version_info >= NO_CLIB_VER: + return + assert ruyaml.__with_libyaml__ + inp = dedent( + """\ + %YAML 1.2 + --- + num_epochs: 70000 + """ + ) + yaml = ruyaml.YAML(typ='safe') + yaml.load(inp) + + +@pytest.mark.skipif( + platform.python_implementation() in ['Jython', 'PyPy'], reason='not available' +) +@pytest.mark.xfail(reason="cyaml not ported yet") +def test_dump_cyaml_1_2(): + # issue 155 + from io import StringIO + + import ruyaml + + if sys.version_info >= NO_CLIB_VER: + return + assert ruyaml.__with_libyaml__ + yaml = ruyaml.YAML(typ='safe') + yaml.version = (1, 2) + yaml.default_flow_style = False + data = {'a': 1, 'b': 2} + exp = dedent( + """\ + %YAML 1.2 + --- + a: 1 + b: 2 + """ + ) + buf = StringIO() + yaml.dump(data, buf) + assert buf.getvalue() == exp diff --git a/_test/test_datetime.py b/_test/test_datetime.py new file mode 100644 index 0000000..9997ba0 --- /dev/null +++ b/_test/test_datetime.py @@ -0,0 +1,158 @@ +# coding: utf-8 + +""" +http://yaml.org/type/timestamp.html specifies the regexp to use +for datetime.date and datetime.datetime construction. Date is simple +but datetime can have 'T' or 't' as well as 'Z' or a timezone offset (in +hours and minutes). This information was originally used to create +a UTC datetime and then discarded + +examples from the above: + +canonical: 2001-12-15T02:59:43.1Z +valid iso8601: 2001-12-14t21:59:43.10-05:00 +space separated: 2001-12-14 21:59:43.10 -5 +no time zone (Z): 2001-12-15 2:59:43.10 +date (00:00:00Z): 2002-12-14 + +Please note that a fraction can only be included if not equal to 0 + +""" + +import copy + +import pytest # NOQA + +from .roundtrip import dedent, round_trip, round_trip_dump, round_trip_load # NOQA + + +class TestDateTime: + def test_date_only(self): + inp = """ + - 2011-10-02 + """ + exp = """ + - 2011-10-02 + """ + round_trip(inp, exp) + + def test_zero_fraction(self): + inp = """ + - 2011-10-02 16:45:00.0 + """ + exp = """ + - 2011-10-02 16:45:00 + """ + round_trip(inp, exp) + + def test_long_fraction(self): + inp = """ + - 2011-10-02 16:45:00.1234 # expand with zeros + - 2011-10-02 16:45:00.123456 + - 2011-10-02 16:45:00.12345612 # round to microseconds + - 2011-10-02 16:45:00.1234565 # round up + - 2011-10-02 16:45:00.12345678 # round up + """ + exp = """ + - 2011-10-02 16:45:00.123400 # expand with zeros + - 2011-10-02 16:45:00.123456 + - 2011-10-02 16:45:00.123456 # round to microseconds + - 2011-10-02 16:45:00.123457 # round up + - 2011-10-02 16:45:00.123457 # round up + """ + round_trip(inp, exp) + + def test_canonical(self): + inp = """ + - 2011-10-02T16:45:00.1Z + """ + exp = """ + - 2011-10-02T16:45:00.100000Z + """ + round_trip(inp, exp) + + def test_spaced_timezone(self): + inp = """ + - 2011-10-02T11:45:00 -5 + """ + exp = """ + - 2011-10-02T11:45:00-5 + """ + round_trip(inp, exp) + + def test_normal_timezone(self): + round_trip( + """ + - 2011-10-02T11:45:00-5 + - 2011-10-02 11:45:00-5 + - 2011-10-02T11:45:00-05:00 + - 2011-10-02 11:45:00-05:00 + """ + ) + + def test_no_timezone(self): + inp = """ + - 2011-10-02 6:45:00 + """ + exp = """ + - 2011-10-02 06:45:00 + """ + round_trip(inp, exp) + + def test_explicit_T(self): + inp = """ + - 2011-10-02T16:45:00 + """ + exp = """ + - 2011-10-02T16:45:00 + """ + round_trip(inp, exp) + + def test_explicit_t(self): # to upper + inp = """ + - 2011-10-02t16:45:00 + """ + exp = """ + - 2011-10-02T16:45:00 + """ + round_trip(inp, exp) + + def test_no_T_multi_space(self): + inp = """ + - 2011-10-02 16:45:00 + """ + exp = """ + - 2011-10-02 16:45:00 + """ + round_trip(inp, exp) + + def test_iso(self): + round_trip( + """ + - 2011-10-02T15:45:00+01:00 + """ + ) + + def test_zero_tz(self): + round_trip( + """ + - 2011-10-02T15:45:00+0 + """ + ) + + def test_issue_45(self): + round_trip( + """ + dt: 2016-08-19T22:45:47Z + """ + ) + + def test_deepcopy_datestring(self): + # reported by Quuxplusone, http://stackoverflow.com/a/41577841/1307905 + x = dedent( + """\ + foo: 2016-10-12T12:34:56 + """ + ) + data = copy.deepcopy(round_trip_load(x)) + assert round_trip_dump(data) == x diff --git a/_test/test_deprecation.py b/_test/test_deprecation.py new file mode 100644 index 0000000..c6ed62e --- /dev/null +++ b/_test/test_deprecation.py @@ -0,0 +1,14 @@ +# coding: utf-8 + +import sys + +import pytest # NOQA + + +@pytest.mark.skipif( + sys.version_info < (3, 7) or sys.version_info >= (3, 9), + reason='collections not available?', +) +def test_collections_deprecation(): + with pytest.warns(DeprecationWarning): + from collections import Hashable # NOQA diff --git a/_test/test_documents.py b/_test/test_documents.py new file mode 100644 index 0000000..b750d5f --- /dev/null +++ b/_test/test_documents.py @@ -0,0 +1,75 @@ +# coding: utf-8 + +import pytest # NOQA + +from .roundtrip import round_trip, round_trip_dump_all, round_trip_load_all + + +class TestDocument: + def test_single_doc_begin_end(self): + inp = """\ + --- + - a + - b + ... + """ + round_trip(inp, explicit_start=True, explicit_end=True) + + def test_multi_doc_begin_end(self): + inp = """\ + --- + - a + ... + --- + - b + ... + """ + docs = list(round_trip_load_all(inp)) + assert docs == [['a'], ['b']] + out = round_trip_dump_all(docs, explicit_start=True, explicit_end=True) + assert out == '---\n- a\n...\n---\n- b\n...\n' + + def test_multi_doc_no_start(self): + inp = """\ + - a + ... + --- + - b + ... + """ + docs = list(round_trip_load_all(inp)) + assert docs == [['a'], ['b']] + + def test_multi_doc_no_end(self): + inp = """\ + - a + --- + - b + """ + docs = list(round_trip_load_all(inp)) + assert docs == [['a'], ['b']] + + def test_multi_doc_ends_only(self): + # this is ok in 1.2 + inp = """\ + - a + ... + - b + ... + """ + docs = list(round_trip_load_all(inp, version=(1, 2))) + assert docs == [['a'], ['b']] + + def test_multi_doc_ends_only_1_1(self): + import ruyaml + + # this is not ok in 1.1 + with pytest.raises(ruyaml.parser.ParserError): + inp = """\ + - a + ... + - b + ... + """ + docs = list(round_trip_load_all(inp, version=(1, 1))) + assert docs == [['a'], ['b']] # not True, but not reached diff --git a/_test/test_fail.py b/_test/test_fail.py new file mode 100644 index 0000000..4970c5e --- /dev/null +++ b/_test/test_fail.py @@ -0,0 +1,255 @@ +# coding: utf-8 + +# there is some work to do +# provide a failing test xyz and a non-failing xyz_no_fail ( to see +# what the current failing output is. +# on fix of ruyaml, move the marked test to the appropriate test (without mark) +# and remove remove the xyz_no_fail + +import pytest + +from .roundtrip import dedent, round_trip, round_trip_dump, round_trip_load + + +class TestCommentFailures: + @pytest.mark.xfail(strict=True) + def test_set_comment_before_tag(self): + # no comments before tags + round_trip( + """ + # the beginning + !!set + # or this one? + ? a + # next one is B (lowercase) + ? b # You see? Promised you. + ? c + # this is the end + """ + ) + + def test_set_comment_before_tag_no_fail(self): + # no comments before tags + inp = """ + # the beginning + !!set + # or this one? + ? a + # next one is B (lowercase) + ? b # You see? Promised you. + ? c + # this is the end + """ + assert round_trip_dump(round_trip_load(inp)) == dedent( + """ + !!set + # or this one? + ? a + # next one is B (lowercase) + ? b # You see? Promised you. + ? c + # this is the end + """ + ) + + @pytest.mark.xfail(strict=True) + def test_comment_dash_line(self): + round_trip( + """ + - # abc + a: 1 + b: 2 + """ + ) + + def test_comment_dash_line_fail(self): + x = """ + - # abc + a: 1 + b: 2 + """ + data = round_trip_load(x) + # this is not nice + assert round_trip_dump(data) == dedent( + """ + # abc + - a: 1 + b: 2 + """ + ) + + +class TestIndentFailures: + @pytest.mark.xfail(strict=True) + def test_indent_not_retained(self): + round_trip( + """ + verbosity: 1 # 0 is minimal output, -1 none + base_url: http://gopher.net + special_indices: [1, 5, 8] + also_special: + - a + - 19 + - 32 + asia and europe: &asia_europe + Turkey: Ankara + Russia: Moscow + countries: + Asia: + <<: *asia_europe + Japan: Tokyo # æ±äº¬ + Europe: + <<: *asia_europe + Spain: Madrid + Italy: Rome + Antarctica: + - too cold + """ + ) + + def test_indent_not_retained_no_fail(self): + inp = """ + verbosity: 1 # 0 is minimal output, -1 none + base_url: http://gopher.net + special_indices: [1, 5, 8] + also_special: + - a + - 19 + - 32 + asia and europe: &asia_europe + Turkey: Ankara + Russia: Moscow + countries: + Asia: + <<: *asia_europe + Japan: Tokyo # æ±äº¬ + Europe: + <<: *asia_europe + Spain: Madrid + Italy: Rome + Antarctica: + - too cold + """ + assert round_trip_dump(round_trip_load(inp), indent=4) == dedent( + """ + verbosity: 1 # 0 is minimal output, -1 none + base_url: http://gopher.net + special_indices: [1, 5, 8] + also_special: + - a + - 19 + - 32 + asia and europe: &asia_europe + Turkey: Ankara + Russia: Moscow + countries: + Asia: + <<: *asia_europe + Japan: Tokyo # æ±äº¬ + Europe: + <<: *asia_europe + Spain: Madrid + Italy: Rome + Antarctica: + - too cold + """ + ) + + def Xtest_indent_top_level_no_fail(self): + inp = """ + - a: + - b + """ + round_trip(inp, indent=4) + + +class TestTagFailures: + @pytest.mark.xfail(strict=True) + def test_standard_short_tag(self): + round_trip( + """\ + !!map + name: Anthon + location: Germany + language: python + """ + ) + + def test_standard_short_tag_no_fail(self): + inp = """ + !!map + name: Anthon + location: Germany + language: python + """ + exp = """ + name: Anthon + location: Germany + language: python + """ + assert round_trip_dump(round_trip_load(inp)) == dedent(exp) + + +class TestFlowValues: + def test_flow_value_with_colon(self): + inp = """\ + {a: bcd:efg} + """ + round_trip(inp) + + def test_flow_value_with_colon_quoted(self): + inp = """\ + {a: 'bcd:efg'} + """ + round_trip(inp, preserve_quotes=True) + + +class TestMappingKey: + def test_simple_mapping_key(self): + inp = """\ + {a: 1, b: 2}: hello world + """ + round_trip(inp, preserve_quotes=True, dump_data=False) + + def test_set_simple_mapping_key(self): + from ruyaml.comments import CommentedKeyMap + + d = {CommentedKeyMap([('a', 1), ('b', 2)]): 'hello world'} + exp = dedent( + """\ + {a: 1, b: 2}: hello world + """ + ) + assert round_trip_dump(d) == exp + + def test_change_key_simple_mapping_key(self): + from ruyaml.comments import CommentedKeyMap + + inp = """\ + {a: 1, b: 2}: hello world + """ + d = round_trip_load(inp, preserve_quotes=True) + d[CommentedKeyMap([('b', 1), ('a', 2)])] = d.pop( + CommentedKeyMap([('a', 1), ('b', 2)]) + ) + exp = dedent( + """\ + {b: 1, a: 2}: hello world + """ + ) + assert round_trip_dump(d) == exp + + def test_change_value_simple_mapping_key(self): + from ruyaml.comments import CommentedKeyMap + + inp = """\ + {a: 1, b: 2}: hello world + """ + d = round_trip_load(inp, preserve_quotes=True) + d = {CommentedKeyMap([('a', 1), ('b', 2)]): 'goodbye'} + exp = dedent( + """\ + {a: 1, b: 2}: goodbye + """ + ) + assert round_trip_dump(d) == exp diff --git a/_test/test_float.py b/_test/test_float.py new file mode 100644 index 0000000..4be2e48 --- /dev/null +++ b/_test/test_float.py @@ -0,0 +1,90 @@ +# coding: utf-8 + +import pytest # NOQA + +from .roundtrip import dedent, round_trip, round_trip_dump, round_trip_load # NOQA + +# http://yaml.org/type/int.html is where underscores in integers are defined + + +class TestFloat: + def test_round_trip_non_exp(self): + data = round_trip( + """\ + - 1.0 + - 1.00 + - 23.100 + - -1.0 + - -1.00 + - -23.100 + - 42. + - -42. + - +42. + - .5 + - +.5 + - -.5 + """ + ) + print(data) + assert 0.999 < data[0] < 1.001 + assert 0.999 < data[1] < 1.001 + assert 23.099 < data[2] < 23.101 + assert 0.999 < -data[3] < 1.001 + assert 0.999 < -data[4] < 1.001 + assert 23.099 < -data[5] < 23.101 + assert 41.999 < data[6] < 42.001 + assert 41.999 < -data[7] < 42.001 + assert 41.999 < data[8] < 42.001 + assert 0.49 < data[9] < 0.51 + assert 0.49 < data[10] < 0.51 + assert -0.51 < data[11] < -0.49 + + def test_round_trip_zeros_0(self): + data = round_trip( + """\ + - 0. + - +0. + - -0. + - 0.0 + - +0.0 + - -0.0 + - 0.00 + - +0.00 + - -0.00 + """ + ) + print(data) + for d in data: + assert -0.00001 < d < 0.00001 + + def Xtest_round_trip_non_exp_trailing_dot(self): + data = round_trip( + """\ + """ + ) + print(data) + + def test_yaml_1_1_no_dot(self): + from ruyaml.error import MantissaNoDotYAML1_1Warning + + with pytest.warns(MantissaNoDotYAML1_1Warning): + round_trip_load( + """\ + %YAML 1.1 + --- + - 1e6 + """ + ) + + +class TestCalculations: + def test_mul_00(self): + # issue 149 reported by jan.brezina@tul.cz + d = round_trip_load( + """\ + - 0.1 + """ + ) + d[0] *= -1 + x = round_trip_dump(d) + assert x == '- -0.1\n' diff --git a/_test/test_flowsequencekey.py b/_test/test_flowsequencekey.py new file mode 100644 index 0000000..8362bec --- /dev/null +++ b/_test/test_flowsequencekey.py @@ -0,0 +1,25 @@ +# coding: utf-8 + +""" +test flow style sequences as keys roundtrip + +""" + +# import pytest + +from .roundtrip import round_trip # , dedent, round_trip_load, round_trip_dump + + +class TestFlowStyleSequenceKey: + def test_so_39595807(self): + inp = """\ + %YAML 1.2 + --- + [2, 3, 4]: + a: + - 1 + - 2 + b: Hello World! + c: 'Voilà !' + """ + round_trip(inp, preserve_quotes=True, explicit_start=True, version=(1, 2)) diff --git a/_test/test_indentation.py b/_test/test_indentation.py new file mode 100644 index 0000000..a68f69b --- /dev/null +++ b/_test/test_indentation.py @@ -0,0 +1,352 @@ +# coding: utf-8 + +import pytest # NOQA + +from .roundtrip import YAML, dedent, round_trip, round_trip_dump, round_trip_load + + +def rt(s): + + res = round_trip_dump(round_trip_load(s)) + return res.strip() + '\n' + + +class TestIndent: + def test_roundtrip_inline_list(self): + s = 'a: [a, b, c]\n' + output = rt(s) + assert s == output + + def test_roundtrip_mapping_of_inline_lists(self): + s = dedent( + """\ + a: [a, b, c] + j: [k, l, m] + """ + ) + output = rt(s) + assert s == output + + def test_roundtrip_mapping_of_inline_lists_comments(self): + s = dedent( + """\ + # comment A + a: [a, b, c] + # comment B + j: [k, l, m] + """ + ) + output = rt(s) + assert s == output + + def test_roundtrip_mapping_of_inline_sequence_eol_comments(self): + s = dedent( + """\ + # comment A + a: [a, b, c] # comment B + j: [k, l, m] # comment C + """ + ) + output = rt(s) + assert s == output + + # first test by explicitly setting flow style + def test_added_inline_list(self): + s1 = dedent( + """ + a: + - b + - c + - d + """ + ) + s = 'a: [b, c, d]\n' + data = round_trip_load(s1) + val = data['a'] + val.fa.set_flow_style() + # print(type(val), '_yaml_format' in dir(val)) + output = round_trip_dump(data) + assert s == output + + # ############ flow mappings + + def test_roundtrip_flow_mapping(self): + s = dedent( + """\ + - {a: 1, b: hallo} + - {j: fka, k: 42} + """ + ) + data = round_trip_load(s) + output = round_trip_dump(data) + assert s == output + + def test_roundtrip_sequence_of_inline_mappings_eol_comments(self): + s = dedent( + """\ + # comment A + - {a: 1, b: hallo} # comment B + - {j: fka, k: 42} # comment C + """ + ) + output = rt(s) + assert s == output + + def test_indent_top_level(self): + inp = """ + - a: + - b + """ + round_trip(inp, indent=4) + + def test_set_indent_5_block_list_indent_1(self): + inp = """ + a: + - b: c + - 1 + - d: + - 2 + """ + round_trip(inp, indent=5, block_seq_indent=1) + + def test_set_indent_4_block_list_indent_2(self): + inp = """ + a: + - b: c + - 1 + - d: + - 2 + """ + round_trip(inp, indent=4, block_seq_indent=2) + + def test_set_indent_3_block_list_indent_0(self): + inp = """ + a: + - b: c + - 1 + - d: + - 2 + """ + round_trip(inp, indent=3, block_seq_indent=0) + + def Xtest_set_indent_3_block_list_indent_2(self): + inp = """ + a: + - + b: c + - + 1 + - + d: + - + 2 + """ + round_trip(inp, indent=3, block_seq_indent=2) + + def test_set_indent_3_block_list_indent_2(self): + inp = """ + a: + - b: c + - 1 + - d: + - 2 + """ + round_trip(inp, indent=3, block_seq_indent=2) + + def Xtest_set_indent_2_block_list_indent_2(self): + inp = """ + a: + - + b: c + - + 1 + - + d: + - + 2 + """ + round_trip(inp, indent=2, block_seq_indent=2) + + # this is how it should be: block_seq_indent stretches the indent + def test_set_indent_2_block_list_indent_2(self): + inp = """ + a: + - b: c + - 1 + - d: + - 2 + """ + round_trip(inp, indent=2, block_seq_indent=2) + + # have to set indent! + def test_roundtrip_four_space_indents(self): + # fmt: off + s = ( + 'a:\n' + '- foo\n' + '- bar\n' + ) + # fmt: on + round_trip(s, indent=4) + + def test_roundtrip_four_space_indents_no_fail(self): + inp = """ + a: + - foo + - bar + """ + exp = """ + a: + - foo + - bar + """ + assert round_trip_dump(round_trip_load(inp)) == dedent(exp) + + +class TestYpkgIndent: + def test_00(self): + inp = """ + name : nano + version : 2.3.2 + release : 1 + homepage : http://www.nano-editor.org + source : + - http://www.nano-editor.org/dist/v2.3/nano-2.3.2.tar.gz : ff30924807ea289f5b60106be8 + license : GPL-2.0 + summary : GNU nano is an easy-to-use text editor + builddeps : + - ncurses-devel + description: | + GNU nano is an easy-to-use text editor originally designed + as a replacement for Pico, the ncurses-based editor from the non-free mailer + package Pine (itself now available under the Apache License as Alpine). + """ + round_trip( + inp, + indent=4, + block_seq_indent=2, + top_level_colon_align=True, + prefix_colon=' ', + ) + + +def guess(s): + from ruyaml.util import load_yaml_guess_indent + + x, y, z = load_yaml_guess_indent(dedent(s)) + return y, z + + +class TestGuessIndent: + def test_guess_20(self): + inp = """\ + a: + - 1 + """ + assert guess(inp) == (2, 0) + + def test_guess_42(self): + inp = """\ + a: + - 1 + """ + assert guess(inp) == (4, 2) + + def test_guess_42a(self): + # block seq indent prevails over nested key indent level + inp = """\ + b: + a: + - 1 + """ + assert guess(inp) == (4, 2) + + def test_guess_3None(self): + inp = """\ + b: + a: 1 + """ + assert guess(inp) == (3, None) + + +class TestSeparateMapSeqIndents: + # using uncommon 6 indent with 3 push in as 2 push in automatically + # gets you 4 indent even if not set + def test_00(self): + # old style + yaml = YAML() + yaml.indent = 6 + yaml.block_seq_indent = 3 + inp = """ + a: + - 1 + - [1, 2] + """ + yaml.round_trip(inp) + + def test_01(self): + yaml = YAML() + yaml.indent(sequence=6) + yaml.indent(offset=3) + inp = """ + a: + - 1 + - {b: 3} + """ + yaml.round_trip(inp) + + def test_02(self): + yaml = YAML() + yaml.indent(mapping=5, sequence=6, offset=3) + inp = """ + a: + b: + - 1 + - [1, 2] + """ + yaml.round_trip(inp) + + def test_03(self): + inp = """ + a: + b: + c: + - 1 + - [1, 2] + """ + round_trip(inp, indent=4) + + def test_04(self): + yaml = YAML() + yaml.indent(mapping=5, sequence=6) + inp = """ + a: + b: + - 1 + - [1, 2] + - {d: 3.14} + """ + yaml.round_trip(inp) + + def test_issue_51(self): + yaml = YAML() + # yaml.map_indent = 2 # the default + yaml.indent(sequence=4, offset=2) + yaml.preserve_quotes = True + yaml.round_trip( + """ + role::startup::author::rsyslog_inputs: + imfile: + - ruleset: 'AEM-slinglog' + File: '/opt/aem/author/crx-quickstart/logs/error.log' + startmsg.regex: '^[-+T.:[:digit:]]*' + tag: 'error' + - ruleset: 'AEM-slinglog' + File: '/opt/aem/author/crx-quickstart/logs/stdout.log' + startmsg.regex: '^[-+T.:[:digit:]]*' + tag: 'stdout' + """ + ) + + +# ############ indentation diff --git a/_test/test_int.py b/_test/test_int.py new file mode 100644 index 0000000..d409746 --- /dev/null +++ b/_test/test_int.py @@ -0,0 +1,34 @@ +# coding: utf-8 + +import pytest # NOQA + +from .roundtrip import dedent, round_trip_dump, round_trip_load + +# http://yaml.org/type/int.html is where underscores in integers are defined + + +class TestBinHexOct: + def test_calculate(self): + # make sure type, leading zero(s) and underscore are preserved + s = dedent( + """\ + - 42 + - 0b101010 + - 0x_2a + - 0x2A + - 0o00_52 + """ + ) + d = round_trip_load(s) + for idx, elem in enumerate(d): + elem -= 21 + d[idx] = elem + for idx, elem in enumerate(d): + elem *= 2 + d[idx] = elem + for idx, elem in enumerate(d): + t = elem + elem **= 2 + elem //= t + d[idx] = elem + assert round_trip_dump(d) == s diff --git a/_test/test_issues.py b/_test/test_issues.py new file mode 100644 index 0000000..65efa95 --- /dev/null +++ b/_test/test_issues.py @@ -0,0 +1,957 @@ +# coding: utf-8 + +import pytest # NOQA + +from .roundtrip import ( # NOQA + YAML, + dedent, + na_round_trip, + round_trip, + round_trip_dump, + round_trip_load, + save_and_run, +) + + +class TestIssues: + def test_issue_61(self): + s = dedent( + """ + def1: &ANCHOR1 + key1: value1 + def: &ANCHOR + <<: *ANCHOR1 + key: value + comb: + <<: *ANCHOR + """ + ) + data = round_trip_load(s) + assert str(data['comb']) == str(data['def']) + assert ( + str(data['comb']) == "ordereddict([('key', 'value'), ('key1', 'value1')])" + ) + + def test_issue_82(self, tmpdir): + program_src = r''' + import ruyaml as yaml + import re + + class SINumber(yaml.YAMLObject): + PREFIXES = {'k': 1e3, 'M': 1e6, 'G': 1e9} + yaml_loader = yaml.Loader + yaml_dumper = yaml.Dumper + yaml_tag = '!si' + yaml_implicit_pattern = re.compile( + r'^(?P<value>[0-9]+(?:\.[0-9]+)?)(?P<prefix>[kMG])$') + + @classmethod + def from_yaml(cls, loader, node): + return cls(node.value) + + @classmethod + def to_yaml(cls, dumper, data): + return dumper.represent_scalar(cls.yaml_tag, str(data)) + + def __init__(self, *args): + m = self.yaml_implicit_pattern.match(args[0]) + self.value = float(m.groupdict()['value']) + self.prefix = m.groupdict()['prefix'] + + def __str__(self): + return str(self.value)+self.prefix + + def __int__(self): + return int(self.value*self.PREFIXES[self.prefix]) + + # This fails: + yaml.add_implicit_resolver(SINumber.yaml_tag, SINumber.yaml_implicit_pattern) + + ret = yaml.load(""" + [1,2,3, !si 10k, 100G] + """, Loader=yaml.Loader) + for idx, l in enumerate([1, 2, 3, 10000, 100000000000]): + assert int(ret[idx]) == l + ''' + assert save_and_run(dedent(program_src), tmpdir) == 0 + + def test_issue_82rt(self, tmpdir): + yaml_str = '[1, 2, 3, !si 10k, 100G]\n' + x = round_trip(yaml_str, preserve_quotes=True) # NOQA + + def test_issue_102(self): + yaml_str = dedent( + """ + var1: #empty + var2: something #notempty + var3: {} #empty object + var4: {a: 1} #filled object + var5: [] #empty array + """ + ) + x = round_trip(yaml_str, preserve_quotes=True) # NOQA + + def test_issue_150(self): + from ruyaml import YAML + + inp = """\ + base: &base_key + first: 123 + second: 234 + + child: + <<: *base_key + third: 345 + """ + yaml = YAML() + data = yaml.load(inp) + child = data['child'] + assert 'second' in dict(**child) + + def test_issue_160(self): + from io import StringIO + + s = dedent( + """\ + root: + # a comment + - {some_key: "value"} + + foo: 32 + bar: 32 + """ + ) + a = round_trip_load(s) + del a['root'][0]['some_key'] + buf = StringIO() + round_trip_dump(a, buf, block_seq_indent=4) + exp = dedent( + """\ + root: + # a comment + - {} + + foo: 32 + bar: 32 + """ + ) + assert buf.getvalue() == exp + + def test_issue_161(self): + yaml_str = dedent( + """\ + mapping-A: + key-A:{} + mapping-B: + """ + ) + for comment in ['', ' # no-newline', ' # some comment\n', '\n']: + s = yaml_str.format(comment) + res = round_trip(s) # NOQA + + def test_issue_161a(self): + yaml_str = dedent( + """\ + mapping-A: + key-A:{} + mapping-B: + """ + ) + for comment in ['\n# between']: + s = yaml_str.format(comment) + res = round_trip(s) # NOQA + + def test_issue_163(self): + s = dedent( + """\ + some-list: + # List comment + - {} + """ + ) + x = round_trip(s, preserve_quotes=True) # NOQA + + json_str = ( + r'{"sshKeys":[{"name":"AETROS\/google-k80-1","uses":0,"getLastUse":0,' + '"fingerprint":"MD5:19:dd:41:93:a1:a3:f5:91:4a:8e:9b:d0:ae:ce:66:4c",' + '"created":1509497961}]}' + ) + + json_str2 = '{"abc":[{"a":"1", "uses":0}]}' + + def test_issue_172(self): + x = round_trip_load(TestIssues.json_str2) # NOQA + x = round_trip_load(TestIssues.json_str) # NOQA + + def test_issue_176(self): + # basic request by Stuart Berg + from ruyaml import YAML + + yaml = YAML() + seq = yaml.load('[1,2,3]') + seq[:] = [1, 2, 3, 4] + + def test_issue_176_preserve_comments_on_extended_slice_assignment(self): + yaml_str = dedent( + """\ + - a + - b # comment + - c # commment c + # comment c+ + - d + + - e # comment + """ + ) + seq = round_trip_load(yaml_str) + seq[1::2] = ['B', 'D'] + res = round_trip_dump(seq) + assert res == yaml_str.replace(' b ', ' B ').replace(' d\n', ' D\n') + + def test_issue_176_test_slicing(self): + mss = round_trip_load('[0, 1, 2, 3, 4]') + assert len(mss) == 5 + assert mss[2:2] == [] + assert mss[2:4] == [2, 3] + assert mss[1::2] == [1, 3] + + # slice assignment + m = mss[:] + m[2:2] = [42] + assert m == [0, 1, 42, 2, 3, 4] + + m = mss[:] + m[:3] = [42, 43, 44] + assert m == [42, 43, 44, 3, 4] + m = mss[:] + m[2:] = [42, 43, 44] + assert m == [0, 1, 42, 43, 44] + m = mss[:] + m[:] = [42, 43, 44] + assert m == [42, 43, 44] + + # extend slice assignment + m = mss[:] + m[2:4] = [42, 43, 44] + assert m == [0, 1, 42, 43, 44, 4] + m = mss[:] + m[1::2] = [42, 43] + assert m == [0, 42, 2, 43, 4] + m = mss[:] + with pytest.raises(TypeError, match='too many'): + m[1::2] = [42, 43, 44] + with pytest.raises(TypeError, match='not enough'): + m[1::2] = [42] + m = mss[:] + m += [5] + m[1::2] = [42, 43, 44] + assert m == [0, 42, 2, 43, 4, 44] + + # deleting + m = mss[:] + del m[1:3] + assert m == [0, 3, 4] + m = mss[:] + del m[::2] + assert m == [1, 3] + m = mss[:] + del m[:] + assert m == [] + + def test_issue_184(self): + yaml_str = dedent( + """\ + test::test: + # test + foo: + bar: baz + """ + ) + d = round_trip_load(yaml_str) + d['bar'] = 'foo' + d.yaml_add_eol_comment('test1', 'bar') + assert round_trip_dump(d) == yaml_str + 'bar: foo # test1\n' + + def test_issue_219(self): + yaml_str = dedent( + """\ + [StackName: AWS::StackName] + """ + ) + d = round_trip_load(yaml_str) # NOQA + + def test_issue_219a(self): + yaml_str = dedent( + """\ + [StackName: + AWS::StackName] + """ + ) + d = round_trip_load(yaml_str) # NOQA + + def test_issue_220(self, tmpdir): + program_src = r''' + from ruyaml import YAML + + yaml_str = """\ + --- + foo: ["bar"] + """ + + yaml = YAML(typ='safe', pure=True) + d = yaml.load(yaml_str) + print(d) + ''' + assert save_and_run(dedent(program_src), tmpdir, optimized=True) == 0 + + def test_issue_221_add(self): + from ruyaml.comments import CommentedSeq + + a = CommentedSeq([1, 2, 3]) + a + [4, 5] + + def test_issue_221_sort(self): + from io import StringIO + + from ruyaml import YAML + + yaml = YAML() + inp = dedent( + """\ + - d + - a # 1 + - c # 3 + - e # 5 + - b # 2 + """ + ) + a = yaml.load(dedent(inp)) + a.sort() + buf = StringIO() + yaml.dump(a, buf) + exp = dedent( + """\ + - a # 1 + - b # 2 + - c # 3 + - d + - e # 5 + """ + ) + assert buf.getvalue() == exp + + def test_issue_221_sort_reverse(self): + from io import StringIO + + from ruyaml import YAML + + yaml = YAML() + inp = dedent( + """\ + - d + - a # 1 + - c # 3 + - e # 5 + - b # 2 + """ + ) + a = yaml.load(dedent(inp)) + a.sort(reverse=True) + buf = StringIO() + yaml.dump(a, buf) + exp = dedent( + """\ + - e # 5 + - d + - c # 3 + - b # 2 + - a # 1 + """ + ) + assert buf.getvalue() == exp + + def test_issue_221_sort_key(self): + from io import StringIO + + from ruyaml import YAML + + yaml = YAML() + inp = dedent( + """\ + - four + - One # 1 + - Three # 3 + - five # 5 + - two # 2 + """ + ) + a = yaml.load(dedent(inp)) + a.sort(key=str.lower) + buf = StringIO() + yaml.dump(a, buf) + exp = dedent( + """\ + - five # 5 + - four + - One # 1 + - Three # 3 + - two # 2 + """ + ) + assert buf.getvalue() == exp + + def test_issue_221_sort_key_reverse(self): + from io import StringIO + + from ruyaml import YAML + + yaml = YAML() + inp = dedent( + """\ + - four + - One # 1 + - Three # 3 + - five # 5 + - two # 2 + """ + ) + a = yaml.load(dedent(inp)) + a.sort(key=str.lower, reverse=True) + buf = StringIO() + yaml.dump(a, buf) + exp = dedent( + """\ + - two # 2 + - Three # 3 + - One # 1 + - four + - five # 5 + """ + ) + assert buf.getvalue() == exp + + def test_issue_222(self): + from io import StringIO + + import ruyaml + + yaml = ruyaml.YAML(typ='safe') + buf = StringIO() + yaml.dump(['012923'], buf) + assert buf.getvalue() == "['012923']\n" + + def test_issue_223(self): + import ruyaml + + yaml = ruyaml.YAML(typ='safe') + yaml.load('phone: 0123456789') + + def test_issue_232(self): + import ruyaml + + yaml = ruyaml.YAML(typ='safe', pure=True) + + with pytest.raises(ruyaml.parser.ParserError): + yaml.load(']') + with pytest.raises(ruyaml.parser.ParserError): + yaml.load('{]') + + def test_issue_233(self): + import json + + from ruyaml import YAML + + yaml = YAML() + data = yaml.load('{}') + json_str = json.dumps(data) # NOQA + + def test_issue_233a(self): + import json + + from ruyaml import YAML + + yaml = YAML() + data = yaml.load('[]') + json_str = json.dumps(data) # NOQA + + def test_issue_234(self): + from ruyaml import YAML + + inp = dedent( + """\ + - key: key1 + ctx: [one, two] + help: one + cmd: > + foo bar + foo bar + """ + ) + yaml = YAML(typ='safe', pure=True) + data = yaml.load(inp) + fold = data[0]['cmd'] + print(repr(fold)) + assert '\a' not in fold + + def test_issue_236(self): + inp = """ + conf: + xx: {a: "b", c: []} + asd: "nn" + """ + d = round_trip(inp, preserve_quotes=True) # NOQA + + def test_issue_238(self, tmpdir): + program_src = r""" + import ruyaml + from io import StringIO + + yaml = ruyaml.YAML(typ='unsafe') + + + class A: + def __setstate__(self, d): + self.__dict__ = d + + + class B: + pass + + + a = A() + b = B() + + a.x = b + b.y = [b] + assert a.x.y[0] == a.x + + buf = StringIO() + yaml.dump(a, buf) + + data = yaml.load(buf.getvalue()) + assert data.x.y[0] == data.x + """ + assert save_and_run(dedent(program_src), tmpdir) == 0 + + def test_issue_239(self): + inp = """ + first_name: Art + occupation: Architect + # I'm safe + about: Art Vandelay is a fictional character that George invents... + # we are not :( + # help me! + --- + # what?! + hello: world + # someone call the Batman + foo: bar # or quz + # Lost again + --- + I: knew + # final words + """ + d = YAML().round_trip_all(inp) # NOQA + + def test_issue_242(self): + from ruyaml.comments import CommentedMap + + d0 = CommentedMap([('a', 'b')]) + assert d0['a'] == 'b' + + def test_issue_245(self): + from ruyaml import YAML + + inp = """ + d: yes + """ + for typ in ['safepure', 'rt', 'safe']: + if typ.endswith('pure'): + pure = True + typ = typ[:-4] + else: + pure = None + + yaml = YAML(typ=typ, pure=pure) + yaml.version = (1, 1) + d = yaml.load(inp) + print(typ, yaml.parser, yaml.resolver) + assert d['d'] is True + + def test_issue_249(self): + yaml = YAML() + inp = dedent( + """\ + # comment + - + - 1 + - 2 + - 3 + """ + ) + exp = dedent( + """\ + # comment + - - 1 + - 2 + - 3 + """ + ) + yaml.round_trip(inp, outp=exp) # NOQA + + def test_issue_250(self): + inp = """ + # 1. + - - 1 + # 2. + - map: 2 + # 3. + - 4 + """ + d = round_trip(inp) # NOQA + + # @pytest.mark.xfail(strict=True, reason='bla bla', raises=AssertionError) + def test_issue_279(self): + from io import StringIO + + from ruyaml import YAML + + yaml = YAML() + yaml.indent(sequence=4, offset=2) + inp = dedent( + """\ + experiments: + - datasets: + # ATLAS EWK + - {dataset: ATLASWZRAP36PB, frac: 1.0} + - {dataset: ATLASZHIGHMASS49FB, frac: 1.0} + """ + ) + a = yaml.load(inp) + buf = StringIO() + yaml.dump(a, buf) + print(buf.getvalue()) + assert buf.getvalue() == inp + + def test_issue_280(self): + from collections import namedtuple + from sys import stdout + + from ruyaml import YAML + from ruyaml.representer import RepresenterError + + T = namedtuple('T', ('a', 'b')) + t = T(1, 2) + yaml = YAML() + with pytest.raises(RepresenterError, match='cannot represent'): + yaml.dump({'t': t}, stdout) + + def test_issue_282(self): + # update from list of tuples caused AttributeError + import ruyaml + + yaml_data = ruyaml.comments.CommentedMap([('a', 'apple'), ('b', 'banana')]) + yaml_data.update([('c', 'cantaloupe')]) + yaml_data.update({'d': 'date', 'k': 'kiwi'}) + assert 'c' in yaml_data.keys() + assert 'c' in yaml_data._ok + + def test_issue_284(self): + import ruyaml + + inp = dedent( + """\ + plain key: in-line value + : # Both empty + "quoted key": + - entry + """ + ) + yaml = ruyaml.YAML(typ='rt') + yaml.version = (1, 2) + d = yaml.load(inp) + assert d[None] is None + + yaml = ruyaml.YAML(typ='rt') + yaml.version = (1, 1) + with pytest.raises(ruyaml.parser.ParserError, match='expected <block end>'): + d = yaml.load(inp) + + def test_issue_285(self): + from ruyaml import YAML + + yaml = YAML() + inp = dedent( + """\ + %YAML 1.1 + --- + - y + - n + - Y + - N + """ + ) + a = yaml.load(inp) + assert a[0] + assert a[2] + assert not a[1] + assert not a[3] + + def test_issue_286(self): + from io import StringIO + + from ruyaml import YAML + + yaml = YAML() + inp = dedent( + """\ + parent_key: + - sub_key: sub_value + + # xxx""" + ) + a = yaml.load(inp) + a['new_key'] = 'new_value' + buf = StringIO() + yaml.dump(a, buf) + assert buf.getvalue().endswith('xxx\nnew_key: new_value\n') + + def test_issue_288(self): + import sys + from io import StringIO + + from ruyaml import YAML + + yamldoc = dedent( + """\ + --- + # Reusable values + aliases: + # First-element comment + - &firstEntry First entry + # Second-element comment + - &secondEntry Second entry + + # Third-element comment is + # a multi-line value + - &thirdEntry Third entry + + # EOF Comment + """ + ) + + yaml = YAML() + yaml.indent(mapping=2, sequence=4, offset=2) + yaml.explicit_start = True + yaml.preserve_quotes = True + yaml.width = sys.maxsize + data = yaml.load(yamldoc) + buf = StringIO() + yaml.dump(data, buf) + assert buf.getvalue() == yamldoc + + def test_issue_288a(self): + import sys + from io import StringIO + + from ruyaml import YAML + + yamldoc = dedent( + """\ + --- + # Reusable values + aliases: + # First-element comment + - &firstEntry First entry + # Second-element comment + - &secondEntry Second entry + + # Third-element comment is + # a multi-line value + - &thirdEntry Third entry + + # EOF Comment + """ + ) + + yaml = YAML() + yaml.indent(mapping=2, sequence=4, offset=2) + yaml.explicit_start = True + yaml.preserve_quotes = True + yaml.width = sys.maxsize + data = yaml.load(yamldoc) + buf = StringIO() + yaml.dump(data, buf) + assert buf.getvalue() == yamldoc + + def test_issue_290(self): + import sys + from io import StringIO + + from ruyaml import YAML + + yamldoc = dedent( + """\ + --- + aliases: + # Folded-element comment + # for a multi-line value + - &FoldedEntry > + THIS IS A + FOLDED, MULTI-LINE + VALUE + + # Literal-element comment + # for a multi-line value + - &literalEntry | + THIS IS A + LITERAL, MULTI-LINE + VALUE + + # Plain-element comment + - &plainEntry Plain entry + """ + ) + + yaml = YAML() + yaml.indent(mapping=2, sequence=4, offset=2) + yaml.explicit_start = True + yaml.preserve_quotes = True + yaml.width = sys.maxsize + data = yaml.load(yamldoc) + buf = StringIO() + yaml.dump(data, buf) + assert buf.getvalue() == yamldoc + + def test_issue_290a(self): + import sys + from io import StringIO + + from ruyaml import YAML + + yamldoc = dedent( + """\ + --- + aliases: + # Folded-element comment + # for a multi-line value + - &FoldedEntry > + THIS IS A + FOLDED, MULTI-LINE + VALUE + + # Literal-element comment + # for a multi-line value + - &literalEntry | + THIS IS A + LITERAL, MULTI-LINE + VALUE + + # Plain-element comment + - &plainEntry Plain entry + """ + ) + + yaml = YAML() + yaml.indent(mapping=2, sequence=4, offset=2) + yaml.explicit_start = True + yaml.preserve_quotes = True + yaml.width = sys.maxsize + data = yaml.load(yamldoc) + buf = StringIO() + yaml.dump(data, buf) + assert buf.getvalue() == yamldoc + + # @pytest.mark.xfail(strict=True, reason='should fail pre 0.15.100', raises=AssertionError) + def test_issue_295(self): + # deepcopy also makes a copy of the start and end mark, and these did not + # have any comparison beyond their ID, which of course changed, breaking + # some old merge_comment code + import copy + + inp = dedent( + """ + A: + b: + # comment + - l1 + - l2 + + C: + d: e + f: + # comment2 + - - l31 + - l32 + - l33: '5' + """ + ) + data = round_trip_load(inp) # NOQA + dc = copy.deepcopy(data) + assert round_trip_dump(dc) == inp + + def test_issue_300(self): + from ruyaml import YAML + + inp = dedent( + """ + %YAML 1.2 + %TAG ! tag:example.com,2019/path#fragment + --- + null + """ + ) + YAML().load(inp) + + def test_issue_300a(self): + import ruyaml + + inp = dedent( + """ + %YAML 1.1 + %TAG ! tag:example.com,2019/path#fragment + --- + null + """ + ) + yaml = YAML() + with pytest.raises( + ruyaml.scanner.ScannerError, match='while scanning a directive' + ): + yaml.load(inp) + + def test_issue_304(self): + inp = """ + %YAML 1.2 + %TAG ! tag:example.com,2019: + --- + !foo null + ... + """ + d = na_round_trip(inp) # NOQA + + def test_issue_305(self): + inp = """ + %YAML 1.2 + --- + !<tag:example.com,2019/path#foo> null + ... + """ + d = na_round_trip(inp) # NOQA + + def test_issue_307(self): + inp = """ + %YAML 1.2 + %TAG ! tag:example.com,2019/path# + --- + null + ... + """ + d = na_round_trip(inp) # NOQA + + +# @pytest.mark.xfail(strict=True, reason='bla bla', raises=AssertionError) +# def test_issue_ xxx(self): +# inp = """ +# """ +# d = round_trip(inp) # NOQA diff --git a/_test/test_json_numbers.py b/_test/test_json_numbers.py new file mode 100644 index 0000000..1bfd5ba --- /dev/null +++ b/_test/test_json_numbers.py @@ -0,0 +1,56 @@ +# coding: utf-8 + +import json + +import pytest # NOQA + + +def load(s, typ=float): + import ruyaml + + yaml = ruyaml.YAML() + x = '{"low": %s }' % (s) + print('input: [%s]' % (s), repr(x)) + # just to check it is loadable json + res = json.loads(x) + assert isinstance(res['low'], typ) + ret_val = yaml.load(x) + print(ret_val) + return ret_val['low'] + + +class TestJSONNumbers: + # based on http://stackoverflow.com/a/30462009/1307905 + # yaml number regex: http://yaml.org/spec/1.2/spec.html#id2804092 + # + # -? [1-9] ( \. [0-9]* [1-9] )? ( e [-+] [1-9] [0-9]* )? + # + # which is not a superset of the JSON numbers + def test_json_number_float(self): + for x in ( + y.split('#')[0].strip() + for y in """ + 1.0 # should fail on YAML spec on 1-9 allowed as single digit + -1.0 + 1e-06 + 3.1e-5 + 3.1e+5 + 3.1e5 # should fail on YAML spec: no +- after e + """.splitlines() + ): + if not x: + continue + res = load(x) + assert isinstance(res, float) + + def test_json_number_int(self): + for x in ( + y.split('#')[0].strip() + for y in """ + 42 + """.splitlines() + ): + if not x: + continue + res = load(x, int) + assert isinstance(res, int) diff --git a/_test/test_line_col.py b/_test/test_line_col.py new file mode 100644 index 0000000..6bc5a82 --- /dev/null +++ b/_test/test_line_col.py @@ -0,0 +1,104 @@ +# coding: utf-8 + +import pytest # NOQA + +from .roundtrip import dedent, round_trip, round_trip_dump, round_trip_load # NOQA + + +def load(s): + return round_trip_load(dedent(s)) + + +class TestLineCol: + def test_item_00(self): + data = load( + """ + - a + - e + - [b, d] + - c + """ + ) + assert data[2].lc.line == 2 + assert data[2].lc.col == 2 + + def test_item_01(self): + data = load( + """ + - a + - e + - {x: 3} + - c + """ + ) + assert data[2].lc.line == 2 + assert data[2].lc.col == 2 + + def test_item_02(self): + data = load( + """ + - a + - e + - !!set {x, y} + - c + """ + ) + assert data[2].lc.line == 2 + assert data[2].lc.col == 2 + + def test_item_03(self): + data = load( + """ + - a + - e + - !!omap + - x: 1 + - y: 3 + - c + """ + ) + assert data[2].lc.line == 2 + assert data[2].lc.col == 2 + + def test_item_04(self): + data = load( + """ + # testing line and column based on SO + # http://stackoverflow.com/questions/13319067/ + - key1: item 1 + key2: item 2 + - key3: another item 1 + key4: another item 2 + """ + ) + assert data[0].lc.line == 2 + assert data[0].lc.col == 2 + assert data[1].lc.line == 4 + assert data[1].lc.col == 2 + + def test_pos_mapping(self): + data = load( + """ + a: 1 + b: 2 + c: 3 + # comment + klm: 42 + d: 4 + """ + ) + assert data.lc.key('klm') == (4, 0) + assert data.lc.value('klm') == (4, 5) + + def test_pos_sequence(self): + data = load( + """ + - a + - b + - c + # next one! + - klm + - d + """ + ) + assert data.lc.item(3) == (4, 2) diff --git a/_test/test_literal.py b/_test/test_literal.py new file mode 100644 index 0000000..dbd2e2b --- /dev/null +++ b/_test/test_literal.py @@ -0,0 +1,335 @@ +# coding: utf-8 + +import pytest # NOQA + +from .roundtrip import YAML # does an automatic dedent on load + +""" +YAML 1.0 allowed root level literal style without indentation: + "Usually top level nodes are not indented" (example 4.21 in 4.6.3) +YAML 1.1 is a bit vague but says: + "Regardless of style, scalar content must always be indented by at least one space" + (4.4.3) + "In general, the document’s node is indented as if it has a parent indented at -1 spaces." + (4.3.3) +YAML 1.2 is again clear about root literal level scalar after directive in example 9.5: + +%YAML 1.2 +--- | +%!PS-Adobe-2.0 +... +%YAML1.2 +--- +# Empty +... +""" + + +class TestNoIndent: + def test_root_literal_scalar_indent_example_9_5(self): + yaml = YAML() + s = '%!PS-Adobe-2.0' + inp = """ + --- | + {} + """ + d = yaml.load(inp.format(s)) + print(d) + assert d == s + '\n' + + def test_root_literal_scalar_no_indent(self): + yaml = YAML() + s = 'testing123' + inp = """ + --- | + {} + """ + d = yaml.load(inp.format(s)) + print(d) + assert d == s + '\n' + + def test_root_literal_scalar_no_indent_1_1(self): + yaml = YAML() + s = 'testing123' + inp = """ + %YAML 1.1 + --- | + {} + """ + d = yaml.load(inp.format(s)) + print(d) + assert d == s + '\n' + + def test_root_literal_scalar_no_indent_1_1_old_style(self): + from textwrap import dedent + + from ruyaml import YAML + + yaml = YAML(typ='safe', pure=True) + s = 'testing123' + inp = """ + %YAML 1.1 + --- | + {} + """ + d = yaml.load(dedent(inp.format(s))) + print(d) + assert d == s + '\n' + + def test_root_literal_scalar_no_indent_1_1_no_raise(self): + # from ruyaml.parser import ParserError + + yaml = YAML() + yaml.root_level_block_style_scalar_no_indent_error_1_1 = True + s = 'testing123' + # with pytest.raises(ParserError): + if True: + inp = """ + %YAML 1.1 + --- | + {} + """ + yaml.load(inp.format(s)) + + def test_root_literal_scalar_indent_offset_one(self): + yaml = YAML() + s = 'testing123' + inp = """ + --- |1 + {} + """ + d = yaml.load(inp.format(s)) + print(d) + assert d == s + '\n' + + def test_root_literal_scalar_indent_offset_four(self): + yaml = YAML() + s = 'testing123' + inp = """ + --- |4 + {} + """ + d = yaml.load(inp.format(s)) + print(d) + assert d == s + '\n' + + def test_root_literal_scalar_indent_offset_two_leading_space(self): + yaml = YAML() + s = ' testing123' + inp = """ + --- |4 + {s} + {s} + """ + d = yaml.load(inp.format(s=s)) + print(d) + assert d == (s + '\n') * 2 + + def test_root_literal_scalar_no_indent_special(self): + yaml = YAML() + s = '%!PS-Adobe-2.0' + inp = """ + --- | + {} + """ + d = yaml.load(inp.format(s)) + print(d) + assert d == s + '\n' + + def test_root_folding_scalar_indent(self): + yaml = YAML() + s = '%!PS-Adobe-2.0' + inp = """ + --- > + {} + """ + d = yaml.load(inp.format(s)) + print(d) + assert d == s + '\n' + + def test_root_folding_scalar_no_indent(self): + yaml = YAML() + s = 'testing123' + inp = """ + --- > + {} + """ + d = yaml.load(inp.format(s)) + print(d) + assert d == s + '\n' + + def test_root_folding_scalar_no_indent_special(self): + yaml = YAML() + s = '%!PS-Adobe-2.0' + inp = """ + --- > + {} + """ + d = yaml.load(inp.format(s)) + print(d) + assert d == s + '\n' + + def test_root_literal_multi_doc(self): + yaml = YAML(typ='safe', pure=True) + s1 = 'abc' + s2 = 'klm' + inp = """ + --- |- + {} + --- | + {} + """ + for idx, d1 in enumerate(yaml.load_all(inp.format(s1, s2))): + print('d1:', d1) + assert ['abc', 'klm\n'][idx] == d1 + + def test_root_literal_doc_indent_directives_end(self): + yaml = YAML() + yaml.explicit_start = True + inp = """ + --- |- + %YAML 1.3 + --- + this: is a test + """ + yaml.round_trip(inp) + + def test_root_literal_doc_indent_document_end(self): + yaml = YAML() + yaml.explicit_start = True + inp = """ + --- |- + some more + ... + text + """ + yaml.round_trip(inp) + + def test_root_literal_doc_indent_marker(self): + yaml = YAML() + yaml.explicit_start = True + inp = """ + --- |2 + some more + text + """ + d = yaml.load(inp) + print(type(d), repr(d)) + yaml.round_trip(inp) + + def test_nested_literal_doc_indent_marker(self): + yaml = YAML() + yaml.explicit_start = True + inp = """ + --- + a: |2 + some more + text + """ + d = yaml.load(inp) + print(type(d), repr(d)) + yaml.round_trip(inp) + + +class Test_RoundTripLiteral: + def test_rt_root_literal_scalar_no_indent(self): + yaml = YAML() + yaml.explicit_start = True + s = 'testing123' + ys = """ + --- | + {} + """ + ys = ys.format(s) + d = yaml.load(ys) + yaml.dump(d, compare=ys) + + def test_rt_root_literal_scalar_indent(self): + yaml = YAML() + yaml.explicit_start = True + yaml.indent = 4 + s = 'testing123' + ys = """ + --- | + {} + """ + ys = ys.format(s) + d = yaml.load(ys) + yaml.dump(d, compare=ys) + + def test_rt_root_plain_scalar_no_indent(self): + yaml = YAML() + yaml.explicit_start = True + yaml.indent = 0 + s = 'testing123' + ys = """ + --- + {} + """ + ys = ys.format(s) + d = yaml.load(ys) + yaml.dump(d, compare=ys) + + def test_rt_root_plain_scalar_expl_indent(self): + yaml = YAML() + yaml.explicit_start = True + yaml.indent = 4 + s = 'testing123' + ys = """ + --- + {} + """ + ys = ys.format(s) + d = yaml.load(ys) + yaml.dump(d, compare=ys) + + def test_rt_root_sq_scalar_expl_indent(self): + yaml = YAML() + yaml.explicit_start = True + yaml.indent = 4 + s = "'testing: 123'" + ys = """ + --- + {} + """ + ys = ys.format(s) + d = yaml.load(ys) + yaml.dump(d, compare=ys) + + def test_rt_root_dq_scalar_expl_indent(self): + # if yaml.indent is the default (None) + # then write after the directive indicator + yaml = YAML() + yaml.explicit_start = True + yaml.indent = 0 + s = '"\'testing123"' + ys = """ + --- + {} + """ + ys = ys.format(s) + d = yaml.load(ys) + yaml.dump(d, compare=ys) + + def test_rt_root_literal_scalar_no_indent_no_eol(self): + yaml = YAML() + yaml.explicit_start = True + s = 'testing123' + ys = """ + --- |- + {} + """ + ys = ys.format(s) + d = yaml.load(ys) + yaml.dump(d, compare=ys) + + def test_rt_non_root_literal_scalar(self): + yaml = YAML() + s = 'testing123' + ys = """ + - | + {} + """ + ys = ys.format(s) + d = yaml.load(ys) + yaml.dump(d, compare=ys) diff --git a/_test/test_none.py b/_test/test_none.py new file mode 100644 index 0000000..fa81c10 --- /dev/null +++ b/_test/test_none.py @@ -0,0 +1,42 @@ +# coding: utf-8 + +import pytest # NOQA + +from .roundtrip import round_trip_dump, round_trip_load + + +class TestNone: + def test_dump00(self): + data = None + s = round_trip_dump(data) + assert s == 'null\n...\n' + d = round_trip_load(s) + assert d == data + + def test_dump01(self): + data = None + s = round_trip_dump(data, explicit_end=True) + assert s == 'null\n...\n' + d = round_trip_load(s) + assert d == data + + def test_dump02(self): + data = None + s = round_trip_dump(data, explicit_end=False) + assert s == 'null\n...\n' + d = round_trip_load(s) + assert d == data + + def test_dump03(self): + data = None + s = round_trip_dump(data, explicit_start=True) + assert s == '---\n...\n' + d = round_trip_load(s) + assert d == data + + def test_dump04(self): + data = None + s = round_trip_dump(data, explicit_start=True, explicit_end=False) + assert s == '---\n...\n' + d = round_trip_load(s) + assert d == data diff --git a/_test/test_numpy.py b/_test/test_numpy.py new file mode 100644 index 0000000..4590625 --- /dev/null +++ b/_test/test_numpy.py @@ -0,0 +1,22 @@ +# coding: utf-8 + +try: + import numpy +except: # NOQA + numpy = None + + +def Xtest_numpy(): + import ruyaml + + if numpy is None: + return + data = numpy.arange(10) + print('data', type(data), data) + + yaml_str = ruyaml.dump(data) + datb = ruyaml.load(yaml_str) + print('datb', type(datb), datb) + + print('\nYAML', yaml_str) + assert data == datb diff --git a/_test/test_program_config.py b/_test/test_program_config.py new file mode 100644 index 0000000..d633f72 --- /dev/null +++ b/_test/test_program_config.py @@ -0,0 +1,65 @@ +# coding: utf-8 + +import pytest # NOQA + +# import ruyaml +from .roundtrip import round_trip + + +class TestProgramConfig: + def test_application_arguments(self): + # application configur + round_trip( + """ + args: + username: anthon + passwd: secret + fullname: Anthon van der Neut + tmux: + session-name: test + loop: + wait: 10 + """ + ) + + def test_single(self): + # application configuration + round_trip( + """ + # default arguments for the program + args: # needed to prevent comment wrapping + # this should be your username + username: anthon + passwd: secret # this is plaintext don't reuse \ +# important/system passwords + fullname: Anthon van der Neut + tmux: + session-name: test # make sure this doesn't clash with + # other sessions + loop: # looping related defaults + # experiment with the following + wait: 10 + # no more argument info to pass + """ + ) + + def test_multi(self): + # application configuration + round_trip( + """ + # default arguments for the program + args: # needed to prevent comment wrapping + # this should be your username + username: anthon + passwd: secret # this is plaintext don't reuse + # important/system passwords + fullname: Anthon van der Neut + tmux: + session-name: test # make sure this doesn't clash with + # other sessions + loop: # looping related defaults + # experiment with the following + wait: 10 + # no more argument info to pass + """ + ) diff --git a/_test/test_spec_examples.py b/_test/test_spec_examples.py new file mode 100644 index 0000000..3a1725c --- /dev/null +++ b/_test/test_spec_examples.py @@ -0,0 +1,337 @@ +# coding: utf-8 + +import pytest # NOQA + +from .roundtrip import YAML + + +def test_example_2_1(): + yaml = YAML() + yaml.round_trip( + """ + - Mark McGwire + - Sammy Sosa + - Ken Griffey + """ + ) + + +@pytest.mark.xfail(strict=True) +def test_example_2_2(): + yaml = YAML() + yaml.mapping_value_align = True + yaml.round_trip( + """ + hr: 65 # Home runs + avg: 0.278 # Batting average + rbi: 147 # Runs Batted In + """ + ) + + +def test_example_2_3(): + yaml = YAML() + yaml.indent(sequence=4, offset=2) + yaml.round_trip( + """ + american: + - Boston Red Sox + - Detroit Tigers + - New York Yankees + national: + - New York Mets + - Chicago Cubs + - Atlanta Braves + """ + ) + + +@pytest.mark.xfail(strict=True) +def test_example_2_4(): + yaml = YAML() + yaml.mapping_value_align = True + yaml.round_trip( + """ + - + name: Mark McGwire + hr: 65 + avg: 0.278 + - + name: Sammy Sosa + hr: 63 + avg: 0.288 + """ + ) + + +@pytest.mark.xfail(strict=True) +def test_example_2_5(): + yaml = YAML() + yaml.flow_sequence_element_align = True + yaml.round_trip( + """ + - [name , hr, avg ] + - [Mark McGwire, 65, 0.278] + - [Sammy Sosa , 63, 0.288] + """ + ) + + +@pytest.mark.xfail(strict=True) +def test_example_2_6(): + yaml = YAML() + # yaml.flow_mapping_final_comma = False + yaml.flow_mapping_one_element_per_line = True + yaml.round_trip( + """ + Mark McGwire: {hr: 65, avg: 0.278} + Sammy Sosa: { + hr: 63, + avg: 0.288 + } + """ + ) + + +@pytest.mark.xfail(strict=True) +def test_example_2_7(): + yaml = YAML() + yaml.round_trip_all( + """ + # Ranking of 1998 home runs + --- + - Mark McGwire + - Sammy Sosa + - Ken Griffey + + # Team ranking + --- + - Chicago Cubs + - St Louis Cardinals + """ + ) + + +def test_example_2_8(): + yaml = YAML() + yaml.explicit_start = True + yaml.explicit_end = True + yaml.round_trip_all( + """ + --- + time: 20:03:20 + player: Sammy Sosa + action: strike (miss) + ... + --- + time: 20:03:47 + player: Sammy Sosa + action: grand slam + ... + """ + ) + + +def test_example_2_9(): + yaml = YAML() + yaml.explicit_start = True + yaml.indent(sequence=4, offset=2) + yaml.round_trip( + """ + --- + hr: # 1998 hr ranking + - Mark McGwire + - Sammy Sosa + rbi: + # 1998 rbi ranking + - Sammy Sosa + - Ken Griffey + """ + ) + + +@pytest.mark.xfail(strict=True) +def test_example_2_10(): + yaml = YAML() + yaml.explicit_start = True + yaml.indent(sequence=4, offset=2) + yaml.round_trip( + """ + --- + hr: + - Mark McGwire + # Following node labeled SS + - &SS Sammy Sosa + rbi: + - *SS # Subsequent occurrence + - Ken Griffey + """ + ) + + +@pytest.mark.xfail(strict=True) +def test_example_2_11(): + yaml = YAML() + yaml.round_trip( + """ + ? - Detroit Tigers + - Chicago cubs + : + - 2001-07-23 + + ? [ New York Yankees, + Atlanta Braves ] + : [ 2001-07-02, 2001-08-12, + 2001-08-14 ] + """ + ) + + +@pytest.mark.xfail(strict=True) +def test_example_2_12(): + yaml = YAML() + yaml.explicit_start = True + yaml.round_trip( + """ + --- + # Products purchased + - item : Super Hoop + quantity: 1 + - item : Basketball + quantity: 4 + - item : Big Shoes + quantity: 1 + """ + ) + + +@pytest.mark.xfail(strict=True) +def test_example_2_13(): + yaml = YAML() + yaml.round_trip( + r""" + # ASCII Art + --- | + \//||\/|| + // || ||__ + """ + ) + + +@pytest.mark.xfail(strict=True) +def test_example_2_14(): + yaml = YAML() + yaml.explicit_start = True + yaml.indent(root_scalar=2) # needs to be added + yaml.round_trip( + """ + --- > + Mark McGwire's + year was crippled + by a knee injury. + """ + ) + + +@pytest.mark.xfail(strict=True) +def test_example_2_15(): + yaml = YAML() + yaml.round_trip( + """ + > + Sammy Sosa completed another + fine season with great stats. + + 63 Home Runs + 0.288 Batting Average + + What a year! + """ + ) + + +def test_example_2_16(): + yaml = YAML() + yaml.round_trip( + """ + name: Mark McGwire + accomplishment: > + Mark set a major league + home run record in 1998. + stats: | + 65 Home Runs + 0.278 Batting Average + """ + ) + + +@pytest.mark.xfail( + strict=True, reason='cannot YAML dump escape sequences (\n) as hex and normal' +) +def test_example_2_17(): + yaml = YAML() + yaml.allow_unicode = False + yaml.preserve_quotes = True + yaml.round_trip( + r""" + unicode: "Sosa did fine.\u263A" + control: "\b1998\t1999\t2000\n" + hex esc: "\x0d\x0a is \r\n" + + single: '"Howdy!" he cried.' + quoted: ' # Not a ''comment''.' + tie-fighter: '|\-*-/|' + """ + ) + + +@pytest.mark.xfail( + strict=True, reason='non-literal/folding multiline scalars not supported' +) +def test_example_2_18(): + yaml = YAML() + yaml.round_trip( + """ + plain: + This unquoted scalar + spans many lines. + + quoted: "So does this + quoted scalar.\n" + """ + ) + + +@pytest.mark.xfail(strict=True, reason='leading + on decimal dropped') +def test_example_2_19(): + yaml = YAML() + yaml.round_trip( + """ + canonical: 12345 + decimal: +12345 + octal: 0o14 + hexadecimal: 0xC + """ + ) + + +@pytest.mark.xfail(strict=True, reason='case of NaN not preserved') +def test_example_2_20(): + yaml = YAML() + yaml.round_trip( + """ + canonical: 1.23015e+3 + exponential: 12.3015e+02 + fixed: 1230.15 + negative infinity: -.inf + not a number: .NaN + """ + ) + + +def Xtest_example_2_X(): + yaml = YAML() + yaml.round_trip( + """ + """ + ) diff --git a/_test/test_string.py b/_test/test_string.py new file mode 100644 index 0000000..1527e54 --- /dev/null +++ b/_test/test_string.py @@ -0,0 +1,228 @@ +# coding: utf-8 + +""" +various test cases for string scalars in YAML files +'|' for preserved newlines +'>' for folded (newlines become spaces) + +and the chomping modifiers: +'-' for stripping: final line break and any trailing empty lines are excluded +'+' for keeping: final line break and empty lines are preserved +'' for clipping: final line break preserved, empty lines at end not + included in content (no modifier) + +""" + +import platform + +import pytest + +# from ruyaml.compat import ordereddict +from .roundtrip import dedent, round_trip, round_trip_dump, round_trip_load # NOQA + + +class TestLiteralScalarString: + def test_basic_string(self): + round_trip( + """ + a: abcdefg + """ + ) + + def test_quoted_integer_string(self): + round_trip( + """ + a: '12345' + """ + ) + + @pytest.mark.skipif( + platform.python_implementation() == 'Jython', + reason='Jython throws RepresenterError', + ) + def test_preserve_string(self): + inp = """ + a: | + abc + def + """ + round_trip(inp, intermediate=dict(a='abc\ndef\n')) + + @pytest.mark.skipif( + platform.python_implementation() == 'Jython', + reason='Jython throws RepresenterError', + ) + def test_preserve_string_strip(self): + s = """ + a: |- + abc + def + + """ + round_trip(s, intermediate=dict(a='abc\ndef')) + + @pytest.mark.skipif( + platform.python_implementation() == 'Jython', + reason='Jython throws RepresenterError', + ) + def test_preserve_string_keep(self): + # with pytest.raises(AssertionError) as excinfo: + inp = """ + a: |+ + ghi + jkl + + + b: x + """ + round_trip(inp, intermediate=dict(a='ghi\njkl\n\n\n', b='x')) + + @pytest.mark.skipif( + platform.python_implementation() == 'Jython', + reason='Jython throws RepresenterError', + ) + def test_preserve_string_keep_at_end(self): + # at EOF you have to specify the ... to get proper "closure" + # of the multiline scalar + inp = """ + a: |+ + ghi + jkl + + ... + """ + round_trip(inp, intermediate=dict(a='ghi\njkl\n\n')) + + def test_fold_string(self): + inp = """ + a: > + abc + def + + """ + round_trip(inp) + + def test_fold_string_strip(self): + inp = """ + a: >- + abc + def + + """ + round_trip(inp) + + def test_fold_string_keep(self): + with pytest.raises(AssertionError) as excinfo: # NOQA + inp = """ + a: >+ + abc + def + + """ + round_trip(inp, intermediate=dict(a='abc def\n\n')) + + +class TestQuotedScalarString: + def test_single_quoted_string(self): + inp = """ + a: 'abc' + """ + round_trip(inp, preserve_quotes=True) + + def test_double_quoted_string(self): + inp = """ + a: "abc" + """ + round_trip(inp, preserve_quotes=True) + + def test_non_preserved_double_quoted_string(self): + inp = """ + a: "abc" + """ + exp = """ + a: abc + """ + round_trip(inp, outp=exp) + + +class TestReplace: + """inspired by issue 110 from sandres23""" + + def test_replace_preserved_scalar_string(self): + import ruyaml + + s = dedent( + """\ + foo: | + foo + foo + bar + foo + """ + ) + data = round_trip_load(s, preserve_quotes=True) + so = data['foo'].replace('foo', 'bar', 2) + assert isinstance(so, ruyaml.scalarstring.LiteralScalarString) + assert so == dedent( + """ + bar + bar + bar + foo + """ + ) + + def test_replace_double_quoted_scalar_string(self): + import ruyaml + + s = dedent( + """\ + foo: "foo foo bar foo" + """ + ) + data = round_trip_load(s, preserve_quotes=True) + so = data['foo'].replace('foo', 'bar', 2) + assert isinstance(so, ruyaml.scalarstring.DoubleQuotedScalarString) + assert so == 'bar bar bar foo' + + +class TestWalkTree: + def test_basic(self): + from ruyaml.comments import CommentedMap + from ruyaml.scalarstring import walk_tree + + data = CommentedMap() + data[1] = 'a' + data[2] = 'with\nnewline\n' + walk_tree(data) + exp = """\ + 1: a + 2: | + with + newline + """ + assert round_trip_dump(data) == dedent(exp) + + def test_map(self): + from ruyaml.comments import CommentedMap + from ruyaml.compat import ordereddict + from ruyaml.scalarstring import DoubleQuotedScalarString as dq + from ruyaml.scalarstring import SingleQuotedScalarString as sq + from ruyaml.scalarstring import preserve_literal, walk_tree + + data = CommentedMap() + data[1] = 'a' + data[2] = 'with\nnew : line\n' + data[3] = '${abc}' + data[4] = 'almost:mapping' + m = ordereddict([('\n', preserve_literal), ('${', sq), (':', dq)]) + walk_tree(data, map=m) + exp = """\ + 1: a + 2: | + with + new : line + 3: '${abc}' + 4: "almost:mapping" + """ + assert round_trip_dump(data) == dedent(exp) diff --git a/_test/test_tag.py b/_test/test_tag.py new file mode 100644 index 0000000..8168493 --- /dev/null +++ b/_test/test_tag.py @@ -0,0 +1,171 @@ +# coding: utf-8 + +import pytest # NOQA + +from .roundtrip import YAML, round_trip, round_trip_load + + +def register_xxx(**kw): + import ruyaml as yaml + + class XXX(yaml.comments.CommentedMap): + @staticmethod + def yaml_dump(dumper, data): + return dumper.represent_mapping('!xxx', data) + + @classmethod + def yaml_load(cls, constructor, node): + data = cls() + yield data + constructor.construct_mapping(node, data) + + yaml.add_constructor('!xxx', XXX.yaml_load, constructor=yaml.RoundTripConstructor) + yaml.add_representer(XXX, XXX.yaml_dump, representer=yaml.RoundTripRepresenter) + + +class TestIndentFailures: + def test_tag(self): + round_trip( + """\ + !!python/object:__main__.Developer + name: Anthon + location: Germany + language: python + """ + ) + + def test_full_tag(self): + round_trip( + """\ + !!tag:yaml.org,2002:python/object:__main__.Developer + name: Anthon + location: Germany + language: python + """ + ) + + def test_standard_tag(self): + round_trip( + """\ + !!tag:yaml.org,2002:python/object:map + name: Anthon + location: Germany + language: python + """ + ) + + def test_Y1(self): + round_trip( + """\ + !yyy + name: Anthon + location: Germany + language: python + """ + ) + + def test_Y2(self): + round_trip( + """\ + !!yyy + name: Anthon + location: Germany + language: python + """ + ) + + +class TestRoundTripCustom: + def test_X1(self): + register_xxx() + round_trip( + """\ + !xxx + name: Anthon + location: Germany + language: python + """ + ) + + @pytest.mark.xfail(strict=True) + def test_X_pre_tag_comment(self): + register_xxx() + round_trip( + """\ + - + # hello + !xxx + name: Anthon + location: Germany + language: python + """ + ) + + @pytest.mark.xfail(strict=True) + def test_X_post_tag_comment(self): + register_xxx() + round_trip( + """\ + - !xxx + # hello + name: Anthon + location: Germany + language: python + """ + ) + + def test_scalar_00(self): + # https://stackoverflow.com/a/45967047/1307905 + round_trip( + """\ + Outputs: + Vpc: + Value: !Ref: vpc # first tag + Export: + Name: !Sub "${AWS::StackName}-Vpc" # second tag + """ + ) + + +class TestIssue201: + def test_encoded_unicode_tag(self): + round_trip_load( + """ + s: !!python/%75nicode 'abc' + """ + ) + + +class TestImplicitTaggedNodes: + def test_scalar(self): + round_trip( + """\ + - !Scalar abcdefg + """ + ) + + def test_mapping(self): + round_trip( + """\ + - !Mapping {a: 1, b: 2} + """ + ) + + def test_sequence(self): + yaml = YAML() + yaml.brace_single_entry_mapping_in_flow_sequence = True + yaml.mapping_value_align = True + yaml.round_trip( + """ + - !Sequence [a, {b: 1}, {c: {d: 3}}] + """ + ) + + def test_sequence2(self): + yaml = YAML() + yaml.mapping_value_align = True + yaml.round_trip( + """ + - !Sequence [a, b: 1, c: {d: 3}] + """ + ) diff --git a/_test/test_version.py b/_test/test_version.py new file mode 100644 index 0000000..963fa66 --- /dev/null +++ b/_test/test_version.py @@ -0,0 +1,177 @@ +# coding: utf-8 + +import pytest # NOQA + +from .roundtrip import dedent, round_trip, round_trip_load + + +def load(s, version=None): + import ruyaml # NOQA + + yaml = ruyaml.YAML() + yaml.version = version + return yaml.load(dedent(s)) + + +class TestVersions: + def test_explicit_1_2(self): + r = load( + """\ + %YAML 1.2 + --- + - 12:34:56 + - 012 + - 012345678 + - 0o12 + - on + - off + - yes + - no + - true + """ + ) + assert r[0] == '12:34:56' + assert r[1] == 12 + assert r[2] == 12345678 + assert r[3] == 10 + assert r[4] == 'on' + assert r[5] == 'off' + assert r[6] == 'yes' + assert r[7] == 'no' + assert r[8] is True + + def test_explicit_1_1(self): + r = load( + """\ + %YAML 1.1 + --- + - 12:34:56 + - 012 + - 012345678 + - 0o12 + - on + - off + - yes + - no + - true + """ + ) + assert r[0] == 45296 + assert r[1] == 10 + assert r[2] == '012345678' + assert r[3] == '0o12' + assert r[4] is True + assert r[5] is False + assert r[6] is True + assert r[7] is False + assert r[8] is True + + def test_implicit_1_2(self): + r = load( + """\ + - 12:34:56 + - 12:34:56.78 + - 012 + - 012345678 + - 0o12 + - on + - off + - yes + - no + - true + """ + ) + assert r[0] == '12:34:56' + assert r[1] == '12:34:56.78' + assert r[2] == 12 + assert r[3] == 12345678 + assert r[4] == 10 + assert r[5] == 'on' + assert r[6] == 'off' + assert r[7] == 'yes' + assert r[8] == 'no' + assert r[9] is True + + def test_load_version_1_1(self): + inp = """\ + - 12:34:56 + - 12:34:56.78 + - 012 + - 012345678 + - 0o12 + - on + - off + - yes + - no + - true + """ + r = load(inp, version='1.1') + assert r[0] == 45296 + assert r[1] == 45296.78 + assert r[2] == 10 + assert r[3] == '012345678' + assert r[4] == '0o12' + assert r[5] is True + assert r[6] is False + assert r[7] is True + assert r[8] is False + assert r[9] is True + + +class TestIssue62: + # bitbucket issue 62, issue_62 + def test_00(self): + import ruyaml # NOQA + + s = dedent( + """\ + {}# Outside flow collection: + - ::vector + - ": - ()" + - Up, up, and away! + - -123 + - http://example.com/foo#bar + # Inside flow collection: + - [::vector, ": - ()", "Down, down and away!", -456, http://example.com/foo#bar] + """ + ) + with pytest.raises(ruyaml.parser.ParserError): + round_trip(s.format('%YAML 1.1\n---\n'), preserve_quotes=True) + round_trip(s.format(""), preserve_quotes=True) + + def test_00_single_comment(self): + import ruyaml # NOQA + + s = dedent( + """\ + {}# Outside flow collection: + - ::vector + - ": - ()" + - Up, up, and away! + - -123 + - http://example.com/foo#bar + - [::vector, ": - ()", "Down, down and away!", -456, http://example.com/foo#bar] + """ + ) + with pytest.raises(ruyaml.parser.ParserError): + round_trip(s.format('%YAML 1.1\n---\n'), preserve_quotes=True) + round_trip(s.format(""), preserve_quotes=True) + # round_trip(s.format('%YAML 1.2\n---\n'), preserve_quotes=True, version=(1, 2)) + + def test_01(self): + import ruyaml # NOQA + + s = dedent( + """\ + {}[random plain value that contains a ? character] + """ + ) + with pytest.raises(ruyaml.parser.ParserError): + round_trip(s.format('%YAML 1.1\n---\n'), preserve_quotes=True) + round_trip(s.format(""), preserve_quotes=True) + # note the flow seq on the --- line! + round_trip(s.format('%YAML 1.2\n--- '), preserve_quotes=True, version='1.2') + + def test_so_45681626(self): + # was not properly parsing + round_trip_load('{"in":{},"out":{}}') diff --git a/_test/test_yamlfile.py b/_test/test_yamlfile.py new file mode 100644 index 0000000..149478a --- /dev/null +++ b/_test/test_yamlfile.py @@ -0,0 +1,229 @@ +# coding: utf-8 + +""" +various test cases for YAML files +""" + +import io +import platform + +import pytest # NOQA + +from .roundtrip import dedent, round_trip, round_trip_dump, round_trip_load # NOQA + + +class TestYAML: + def test_backslash(self): + round_trip( + """ + handlers: + static_files: applications/\\1/static/\\2 + """ + ) + + def test_omap_out(self): + # ordereddict mapped to !!omap + import ruyaml # NOQA + from ruyaml.compat import ordereddict + + x = ordereddict([('a', 1), ('b', 2)]) + res = round_trip_dump(x, default_flow_style=False) + assert res == dedent( + """ + !!omap + - a: 1 + - b: 2 + """ + ) + + def test_omap_roundtrip(self): + round_trip( + """ + !!omap + - a: 1 + - b: 2 + - c: 3 + - d: 4 + """ + ) + + def test_dump_collections_ordereddict(self): + from collections import OrderedDict + + import ruyaml # NOQA + + # OrderedDict mapped to !!omap + x = OrderedDict([('a', 1), ('b', 2)]) + res = round_trip_dump(x, default_flow_style=False) + assert res == dedent( + """ + !!omap + - a: 1 + - b: 2 + """ + ) + + def test_CommentedSet(self): + from ruyaml.constructor import CommentedSet + + s = CommentedSet(['a', 'b', 'c']) + s.remove('b') + s.add('d') + assert s == CommentedSet(['a', 'c', 'd']) + s.add('e') + s.add('f') + s.remove('e') + assert s == CommentedSet(['a', 'c', 'd', 'f']) + + def test_set_out(self): + # preferable would be the shorter format without the ': null' + import ruyaml # NOQA + + x = set(['a', 'b', 'c']) + # cannot use round_trip_dump, it doesn't show null in block style + buf = io.StringIO() + yaml = ruyaml.YAML(typ='unsafe', pure=True) + yaml.default_flow_style = False + yaml.dump(x, buf) + assert buf.getvalue() == dedent( + """ + !!set + a: null + b: null + c: null + """ + ) + + # ordering is not preserved in a set + def test_set_compact(self): + # this format is read and also should be written by default + round_trip( + """ + !!set + ? a + ? b + ? c + """ + ) + + def test_blank_line_after_comment(self): + round_trip( + """ + # Comment with spaces after it. + + + a: 1 + """ + ) + + def test_blank_line_between_seq_items(self): + round_trip( + """ + # Seq with empty lines in between items. + b: + - bar + + + - baz + """ + ) + + @pytest.mark.skipif( + platform.python_implementation() == 'Jython', + reason='Jython throws RepresenterError', + ) + def test_blank_line_after_literal_chip(self): + s = """ + c: + - | + This item + has a blank line + following it. + + - | + To visually separate it from this item. + + This item contains a blank line. + + + """ + d = round_trip_load(dedent(s)) + print(d) + round_trip(s) + assert d['c'][0].split('it.')[1] == '\n' + assert d['c'][1].split('line.')[1] == '\n' + + @pytest.mark.skipif( + platform.python_implementation() == 'Jython', + reason='Jython throws RepresenterError', + ) + def test_blank_line_after_literal_keep(self): + """have to insert an eof marker in YAML to test this""" + s = """ + c: + - |+ + This item + has a blank line + following it. + + - |+ + To visually separate it from this item. + + This item contains a blank line. + + + ... + """ + d = round_trip_load(dedent(s)) + print(d) + round_trip(s) + assert d['c'][0].split('it.')[1] == '\n\n' + assert d['c'][1].split('line.')[1] == '\n\n\n' + + @pytest.mark.skipif( + platform.python_implementation() == 'Jython', + reason='Jython throws RepresenterError', + ) + def test_blank_line_after_literal_strip(self): + s = """ + c: + - |- + This item + has a blank line + following it. + + - |- + To visually separate it from this item. + + This item contains a blank line. + + + """ + d = round_trip_load(dedent(s)) + print(d) + round_trip(s) + assert d['c'][0].split('it.')[1] == "" + assert d['c'][1].split('line.')[1] == "" + + def test_load_all_perserve_quotes(self): + import ruyaml # NOQA + + yaml = ruyaml.YAML() + yaml.preserve_quotes = True + s = dedent( + """\ + a: 'hello' + --- + b: "goodbye" + """ + ) + data = [] + for x in yaml.load_all(s): + data.append(x) + buf = ruyaml.compat.StringIO() + yaml.dump_all(data, buf) + out = buf.getvalue() + print(type(data[0]['a']), data[0]['a']) + # out = ruyaml.round_trip_dump_all(data) + print(out) + assert out == s diff --git a/_test/test_yamlobject.py b/_test/test_yamlobject.py new file mode 100644 index 0000000..0f9c48c --- /dev/null +++ b/_test/test_yamlobject.py @@ -0,0 +1,82 @@ +# coding: utf-8 + +import pytest # NOQA + +from .roundtrip import save_and_run # NOQA + + +def test_monster(tmpdir): + program_src = '''\ + import ruyaml + from textwrap import dedent + + class Monster(ruyaml.YAMLObject): + yaml_tag = '!Monster' + + def __init__(self, name, hp, ac, attacks): + self.name = name + self.hp = hp + self.ac = ac + self.attacks = attacks + + def __repr__(self): + return "%s(name=%r, hp=%r, ac=%r, attacks=%r)" % ( + self.__class__.__name__, self.name, self.hp, self.ac, self.attacks) + + data = ruyaml.load(dedent("""\\ + --- !Monster + name: Cave spider + hp: [2,6] # 2d6 + ac: 16 + attacks: [BITE, HURT] + """), Loader=ruyaml.Loader) + # normal dump, keys will be sorted + assert ruyaml.dump(data) == dedent("""\\ + !Monster + ac: 16 + attacks: [BITE, HURT] + hp: [2, 6] + name: Cave spider + """) + ''' + assert save_and_run(program_src, tmpdir) == 0 + + +def test_qualified_name00(tmpdir): + """issue 214""" + program_src = """\ + import ruyaml + from io import StringIO + + class A: + def f(self): + pass + + yaml = ruyaml.YAML(typ='unsafe', pure=True) + yaml.explicit_end = True + buf = StringIO() + yaml.dump(A.f, buf) + res = buf.getvalue() + print('res', repr(res)) + assert res == "!!python/name:__main__.A.f ''\\n...\\n" + x = ruyaml.load(res) + assert x == A.f + """ + assert save_and_run(program_src, tmpdir) == 0 + + +def test_qualified_name01(tmpdir): + """issue 214""" + from io import StringIO + + import ruyaml.comments + from ruyaml import YAML + + yaml = YAML(typ='unsafe', pure=True) + yaml.explicit_end = True + buf = StringIO() + yaml.dump(ruyaml.comments.CommentedBase.yaml_anchor, buf) + res = buf.getvalue() + assert res == "!!python/name:ruyaml.comments.CommentedBase.yaml_anchor ''\n...\n" + x = yaml.load(res) + assert x == ruyaml.comments.CommentedBase.yaml_anchor diff --git a/_test/test_z_check_debug_leftovers.py b/_test/test_z_check_debug_leftovers.py new file mode 100644 index 0000000..a446dae --- /dev/null +++ b/_test/test_z_check_debug_leftovers.py @@ -0,0 +1,40 @@ +# coding: utf-8 + +import sys + +import pytest # NOQA + +from .roundtrip import dedent, round_trip_dump, round_trip_load + + +class TestLeftOverDebug: + # idea here is to capture round_trip_output via pytest stdout capture + # if there is are any leftover debug statements they should show up + def test_00(self, capsys): + s = dedent( + """ + a: 1 + b: [] + c: [a, 1] + d: {f: 3.14, g: 42} + """ + ) + d = round_trip_load(s) + round_trip_dump(d, sys.stdout) + out, err = capsys.readouterr() + assert out == s + + def test_01(self, capsys): + s = dedent( + """ + - 1 + - [] + - [a, 1] + - {f: 3.14, g: 42} + - - 123 + """ + ) + d = round_trip_load(s) + round_trip_dump(d, sys.stdout) + out, err = capsys.readouterr() + assert out == s diff --git a/_test/test_z_data.py b/_test/test_z_data.py new file mode 100644 index 0000000..273eddf --- /dev/null +++ b/_test/test_z_data.py @@ -0,0 +1,272 @@ +# coding: utf-8 + +import os +import sys +import warnings # NOQA +from pathlib import Path + +import pytest # NOQA + +from ruyaml.compat import _F + +base_path = Path('data') # that is ruamel.yaml.data + + +class YAMLData: + yaml_tag = '!YAML' + + def __init__(self, s): + self._s = s + + # Conversion tables for input. E.g. "<TAB>" is replaced by "\t" + # fmt: off + special = { + 'SPC': ' ', + 'TAB': '\t', + '---': '---', + '...': '...', + } + # fmt: on + + @property + def value(self): + if hasattr(self, '_p'): + return self._p + assert ' \n' not in self._s + assert '\t\n' not in self._s + self._p = self._s + for k, v in YAMLData.special.items(): + k = '<' + k + '>' + self._p = self._p.replace(k, v) + return self._p + + def test_rewrite(self, s): + assert ' \n' not in s + assert '\t\n' not in s + for k, v in YAMLData.special.items(): + k = '<' + k + '>' + s = s.replace(k, v) + return s + + @classmethod + def from_yaml(cls, constructor, node): + from ruyaml.nodes import MappingNode + + if isinstance(node, MappingNode): + return cls(constructor.construct_mapping(node)) + return cls(node.value) + + +class Python(YAMLData): + yaml_tag = '!Python' + + +class Output(YAMLData): + yaml_tag = '!Output' + + +class Assert(YAMLData): + yaml_tag = '!Assert' + + @property + def value(self): + from collections.abc import Mapping + + if hasattr(self, '_pa'): + return self._pa + if isinstance(self._s, Mapping): + self._s['lines'] = self.test_rewrite(self._s['lines']) + self._pa = self._s + return self._pa + + +def pytest_generate_tests(metafunc): + test_yaml = [] + paths = sorted(base_path.glob('**/*.yaml')) + idlist = [] + for path in paths: + # while developing tests put them in data/debug and run: + # auto -c "pytest _test/test_z_data.py" data/debug/*.yaml *.py _test/*.py + if os.environ.get('RUAMELAUTOTEST') == '1': + if path.parent.stem != 'debug': + continue + elif path.parent.stem == 'debug': + # don't test debug entries for production + continue + stem = path.stem + if stem.startswith('.#'): # skip emacs temporary file + continue + idlist.append(stem) + test_yaml.append([path]) + metafunc.parametrize(['yaml'], test_yaml, ids=idlist, scope='class') + + +class TestYAMLData: + def yaml(self, yaml_version=None): + from ruyaml import YAML + + y = YAML() + y.preserve_quotes = True + if yaml_version: + y.version = yaml_version + return y + + def docs(self, path): + from ruyaml import YAML + + tyaml = YAML(typ='safe', pure=True) + tyaml.register_class(YAMLData) + tyaml.register_class(Python) + tyaml.register_class(Output) + tyaml.register_class(Assert) + return list(tyaml.load_all(path)) + + def yaml_load(self, value, yaml_version=None): + yaml = self.yaml(yaml_version=yaml_version) + data = yaml.load(value) + return yaml, data + + def round_trip(self, input, output=None, yaml_version=None): + from io import StringIO + + yaml, data = self.yaml_load(input.value, yaml_version=yaml_version) + buf = StringIO() + yaml.dump(data, buf) + expected = input.value if output is None else output.value + value = buf.getvalue() + assert value == expected + + def load_assert(self, input, confirm, yaml_version=None): + from collections.abc import Mapping + + d = self.yaml_load(input.value, yaml_version=yaml_version)[1] # NOQA + print('confirm.value', confirm.value, type(confirm.value)) + if isinstance(confirm.value, Mapping): + r = range(confirm.value['range']) + lines = confirm.value['lines'].splitlines() + for idx in r: # NOQA + for line in lines: + line = 'assert ' + line + print(line) + exec(line) + else: + for line in confirm.value.splitlines(): + line = 'assert ' + line + print(line) + exec(line) + + def run_python(self, python, data, tmpdir, input=None): + from roundtrip import save_and_run + + if input is not None: + (tmpdir / 'input.yaml').write_text(input.value, encoding='utf-8') + assert save_and_run(python.value, base_dir=tmpdir, output=data.value) == 0 + + def insert_comments(self, data, actions): + """this is to automatically insert based on: + path (a.1.b), + position (before, after, between), and + offset (absolute/relative) + """ + raise NotImplementedError + expected = [] + for line in data.value.splitlines(True): + idx = line.index['?'] + if idx < 0: + expected.append(line) + continue + assert line.lstrip()[0] == '#' # it has to be comment line + print(data) + assert ''.join(expected) == data.value + + # this is executed by pytest the methods with names not starting with + # test_ are helper methods + def test_yaml_data(self, yaml, tmpdir): + from collections.abc import Mapping + + idx = 0 + typ = None + yaml_version = None + + docs = self.docs(yaml) + if isinstance(docs[0], Mapping): + d = docs[0] + typ = d.get('type') + yaml_version = d.get('yaml_version') + if 'python' in d: + if not check_python_version(d['python']): + pytest.skip('unsupported version') + idx += 1 + data = output = confirm = python = None + for doc in docs[idx:]: + if isinstance(doc, Output): + output = doc + elif isinstance(doc, Assert): + confirm = doc + elif isinstance(doc, Python): + python = doc + if typ is None: + typ = 'python_run' + elif isinstance(doc, YAMLData): + data = doc + else: + print('no handler for type:', type(doc), repr(doc)) + raise AssertionError() + if typ is None: + if data is not None and output is not None: + typ = 'rt' + elif data is not None and confirm is not None: + typ = 'load_assert' + else: + assert data is not None + typ = 'rt' + print('type:', typ) + if data is not None: + print('data:', data.value, end='') + print('output:', output.value if output is not None else output) + if typ == 'rt': + self.round_trip(data, output, yaml_version=yaml_version) + elif typ == 'python_run': + inp = None if output is None or data is None else data + self.run_python( + python, output if output is not None else data, tmpdir, input=inp + ) + elif typ == 'load_assert': + self.load_assert(data, confirm, yaml_version=yaml_version) + elif typ == 'comment': + actions = [] + self.insert_comments(data, actions) + else: + _F('\n>>>>>> run type unknown: "{typ}" <<<<<<\n') + raise AssertionError() + + +def check_python_version(match, current=None): + """ + version indication, return True if version matches. + match should be something like 3.6+, or [2.7, 3.3] etc. Floats + are converted to strings. Single values are made into lists. + """ + if current is None: + current = list(sys.version_info[:3]) + if not isinstance(match, list): + match = [match] + for m in match: + minimal = False + if isinstance(m, float): + m = str(m) + if m.endswith('+'): + minimal = True + m = m[:-1] + # assert m[0].isdigit() + # assert m[-1].isdigit() + m = [int(x) for x in m.split('.')] + current_len = current[: len(m)] + # print(m, current, current_len) + if minimal: + if current_len >= m: + return True + else: + if current_len == m: + return True + return False diff --git a/_test/test_z_olddata.py b/_test/test_z_olddata.py new file mode 100644 index 0000000..f260aad --- /dev/null +++ b/_test/test_z_olddata.py @@ -0,0 +1,42 @@ +# coding: utf-8 + +import os +import sys + +import pytest # NOQA + +sys.path.insert(0, os.path.dirname(__file__) + '/lib') + +import warnings # NOQA + +args = [] + + +def test_data(): + import test_appliance # NOQA + + warnings.simplefilter('ignore', PendingDeprecationWarning) + collections = [] + import test_yaml + + collections.append(test_yaml) + test_appliance.run(collections, args) + + +# @pytest.mark.skipif(not ruyaml.__with_libyaml__, +# reason="no libyaml") + + +def test_data_ext(): + collections = [] + import test_appliance # NOQA + + import ruyaml + + warnings.simplefilter('ignore', ruyaml.error.UnsafeLoaderWarning) + warnings.simplefilter('ignore', PendingDeprecationWarning) + if ruyaml.__with_libyaml__: + import test_yaml_ext + + collections.append(test_yaml_ext) + test_appliance.run(collections, args) |