Skip to content

Commit

Permalink
Allow add_multi_constructor with None (#358)
Browse files Browse the repository at this point in the history
Loader.add_multi_constructor(None, myconstructor)

Also add test for add_multi_constructor('!', ...) etc.

See issue #317
  • Loading branch information
perlpunk committed Dec 7, 2019
1 parent 5a0cfab commit 03b378d
Show file tree
Hide file tree
Showing 8 changed files with 137 additions and 2 deletions.
2 changes: 1 addition & 1 deletion lib/yaml/constructor.py
Expand Up @@ -74,7 +74,7 @@ def construct_object(self, node, deep=False):
constructor = self.yaml_constructors[node.tag]
else:
for tag_prefix in self.yaml_multi_constructors:
if node.tag.startswith(tag_prefix):
if tag_prefix is not None and node.tag.startswith(tag_prefix):
tag_suffix = node.tag[len(tag_prefix):]
constructor = self.yaml_multi_constructors[tag_prefix]
break
Expand Down
2 changes: 1 addition & 1 deletion lib3/yaml/constructor.py
Expand Up @@ -72,7 +72,7 @@ def construct_object(self, node, deep=False):
constructor = self.yaml_constructors[node.tag]
else:
for tag_prefix in self.yaml_multi_constructors:
if node.tag.startswith(tag_prefix):
if tag_prefix is not None and node.tag.startswith(tag_prefix):
tag_suffix = node.tag[len(tag_prefix):]
constructor = self.yaml_multi_constructors[tag_prefix]
break
Expand Down
4 changes: 4 additions & 0 deletions tests/data/multi-constructor.code
@@ -0,0 +1,4 @@
[
{'Tag1': ['a', 1, 'b', 2]},
{'Tag2': ['a', 1, 'b', 2]},
]
3 changes: 3 additions & 0 deletions tests/data/multi-constructor.multi
@@ -0,0 +1,3 @@
---
- !Tag1 [a, 1, b, 2]
- !!Tag2 [a, 1, b, 2]
63 changes: 63 additions & 0 deletions tests/lib/test_multi_constructor.py
@@ -0,0 +1,63 @@
import yaml
import pprint
import sys

def _load_code(expression):
return eval(expression)

def myconstructor1(constructor, tag, node):
seq = constructor.construct_sequence(node)
return {tag: seq }

def myconstructor2(constructor, tag, node):
seq = constructor.construct_sequence(node)
string = ''
try:
i = tag.index('!') + 1
except:
try:
i = tag.rindex(':') + 1
except:
pass
if i >= 0:
tag = tag[i:]
return { tag: seq }

class Multi1(yaml.FullLoader):
pass
class Multi2(yaml.FullLoader):
pass

def test_multi_constructor(input_filename, code_filename, verbose=False):
input = open(input_filename, 'rb').read().decode('utf-8')
native = _load_code(open(code_filename, 'rb').read())

# default multi constructor for ! and !! tags
Multi1.add_multi_constructor('!', myconstructor1)
Multi1.add_multi_constructor('tag:yaml.org,2002:', myconstructor1)

data = yaml.load(input, Loader=Multi1)
if verbose:
print('Multi1:')
print(data)
print(native)
assert(data == native)


# default multi constructor for all tags
Multi2.add_multi_constructor(None, myconstructor2)

data = yaml.load(input, Loader=Multi2)
if verbose:
print('Multi2:')
print(data)
print(native)
assert(data == native)


test_multi_constructor.unittest = ['.multi', '.code']

if __name__ == '__main__':
import test_appliance
test_appliance.run(globals())

1 change: 1 addition & 0 deletions tests/lib/test_yaml.py
Expand Up @@ -12,6 +12,7 @@
from test_recursive import *
from test_input_output import *
from test_sort_keys import *
from test_multi_constructor import *

if __name__ == '__main__':
import test_appliance
Expand Down
63 changes: 63 additions & 0 deletions tests/lib3/test_multi_constructor.py
@@ -0,0 +1,63 @@
import yaml
import pprint
import sys

def _load_code(expression):
return eval(expression)

def myconstructor1(constructor, tag, node):
seq = constructor.construct_sequence(node)
return {tag: seq }

def myconstructor2(constructor, tag, node):
seq = constructor.construct_sequence(node)
string = ''
try:
i = tag.index('!') + 1
except:
try:
i = tag.rindex(':') + 1
except:
pass
if i >= 0:
tag = tag[i:]
return { tag: seq }

class Multi1(yaml.FullLoader):
pass
class Multi2(yaml.FullLoader):
pass

def test_multi_constructor(input_filename, code_filename, verbose=False):
input = open(input_filename, 'rb').read().decode('utf-8')
native = _load_code(open(code_filename, 'rb').read())

# default multi constructor for ! and !! tags
Multi1.add_multi_constructor('!', myconstructor1)
Multi1.add_multi_constructor('tag:yaml.org,2002:', myconstructor1)

data = yaml.load(input, Loader=Multi1)
if verbose:
print('Multi1:')
print(data)
print(native)
assert(data == native)


# default multi constructor for all tags
Multi2.add_multi_constructor(None, myconstructor2)

data = yaml.load(input, Loader=Multi2)
if verbose:
print('Multi2:')
print(data)
print(native)
assert(data == native)


test_multi_constructor.unittest = ['.multi', '.code']

if __name__ == '__main__':
import test_appliance
test_appliance.run(globals())

1 change: 1 addition & 0 deletions tests/lib3/test_yaml.py
Expand Up @@ -12,6 +12,7 @@
from test_recursive import *
from test_input_output import *
from test_sort_keys import *
from test_multi_constructor import *

if __name__ == '__main__':
import test_appliance
Expand Down

0 comments on commit 03b378d

Please sign in to comment.