Also add reuse_anchors to libyaml backend

This commit is contained in:
Tina Müller 2021-09-23 19:56:28 +02:00
parent bd96e4000c
commit 737ad62df0
10 changed files with 58 additions and 26 deletions

View file

@ -48,7 +48,7 @@ def parse(stream, Loader=Loader, reuse_anchors=False):
finally: finally:
loader.dispose() loader.dispose()
def compose(stream, Loader=Loader): def compose(stream, Loader=Loader, reuse_anchors=False):
""" """
Parse the first YAML document in a stream Parse the first YAML document in a stream
and produce the corresponding representation tree. and produce the corresponding representation tree.

View file

@ -15,36 +15,36 @@ from .resolver import *
class CBaseLoader(CParser, BaseConstructor, BaseResolver): class CBaseLoader(CParser, BaseConstructor, BaseResolver):
def __init__(self, stream): def __init__(self, stream, reuse_anchors=False):
CParser.__init__(self, stream) CParser.__init__(self, stream, reuse_anchors=reuse_anchors)
BaseConstructor.__init__(self) BaseConstructor.__init__(self)
BaseResolver.__init__(self) BaseResolver.__init__(self)
class CSafeLoader(CParser, SafeConstructor, Resolver): class CSafeLoader(CParser, SafeConstructor, Resolver):
def __init__(self, stream): def __init__(self, stream, reuse_anchors=False):
CParser.__init__(self, stream) CParser.__init__(self, stream, reuse_anchors=reuse_anchors)
SafeConstructor.__init__(self) SafeConstructor.__init__(self)
Resolver.__init__(self) Resolver.__init__(self)
class CFullLoader(CParser, FullConstructor, Resolver): class CFullLoader(CParser, FullConstructor, Resolver):
def __init__(self, stream): def __init__(self, stream, reuse_anchors=False):
CParser.__init__(self, stream) CParser.__init__(self, stream, reuse_anchors=reuse_anchors)
FullConstructor.__init__(self) FullConstructor.__init__(self)
Resolver.__init__(self) Resolver.__init__(self)
class CUnsafeLoader(CParser, UnsafeConstructor, Resolver): class CUnsafeLoader(CParser, UnsafeConstructor, Resolver):
def __init__(self, stream): def __init__(self, stream, reuse_anchors=False):
CParser.__init__(self, stream) CParser.__init__(self, stream, reuse_anchors=reuse_anchors)
UnsafeConstructor.__init__(self) UnsafeConstructor.__init__(self)
Resolver.__init__(self) Resolver.__init__(self)
class CLoader(CParser, Constructor, Resolver): class CLoader(CParser, Constructor, Resolver):
def __init__(self, stream): def __init__(self, stream, reuse_anchors=False):
CParser.__init__(self, stream) CParser.__init__(self, stream, reuse_anchors=reuse_anchors)
Constructor.__init__(self) Constructor.__init__(self)
Resolver.__init__(self) Resolver.__init__(self)

View file

@ -0,0 +1,3 @@
- &foo bar
- &bar bar
- &foo bar

View file

@ -258,7 +258,7 @@ def test_constructor_types(data_filename, code_filename, verbose=False):
native2 = None native2 = None
try: try:
with open(data_filename, 'rb') as file: with open(data_filename, 'rb') as file:
native1 = list(yaml.load_all(file, Loader=MyLoader, reuse_anchors=True)) native1 = list(yaml.load_all(file, Loader=MyLoader))
if len(native1) == 1: if len(native1) == 1:
native1 = native1[0] native1 = native1[0]
with open(code_filename, 'rb') as file: with open(code_filename, 'rb') as file:
@ -296,6 +296,34 @@ def test_subclass_blacklist_types(data_filename, verbose=False):
test_subclass_blacklist_types.unittest = ['.subclass_blacklist'] test_subclass_blacklist_types.unittest = ['.subclass_blacklist']
def test_reuse_anchors(data_filename, code_filename, verbose=False):
try:
with open(data_filename, 'rb') as file:
native1 = list(yaml.load_all(file, Loader=yaml.SafeLoader, reuse_anchors=True))
if len(native1) == 1:
native1 = native1[0]
with open(code_filename, 'rb') as file:
native2 = _load_code(file.read())
try:
if native1 == native2:
return
except TypeError:
pass
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_reuse_anchors.unittest = ['.reuse-anchors-data', '.reuse-anchors-code']
if __name__ == '__main__': if __name__ == '__main__':
import sys, test_constructor import sys, test_constructor
sys.modules['test_constructor'] = sys.modules['__main__'] sys.modules['test_constructor'] = sys.modules['__main__']

View file

@ -18,28 +18,28 @@ def new_parse(stream, Loader=yaml.CLoader):
return old_parse(stream, Loader) return old_parse(stream, Loader)
old_compose = yaml.compose old_compose = yaml.compose
def new_compose(stream, Loader=yaml.CLoader): def new_compose(stream, Loader=yaml.CLoader, reuse_anchors=False):
return old_compose(stream, Loader) return old_compose(stream, Loader, reuse_anchors=reuse_anchors)
old_compose_all = yaml.compose_all old_compose_all = yaml.compose_all
def new_compose_all(stream, Loader=yaml.CLoader): def new_compose_all(stream, Loader=yaml.CLoader, reuse_anchors=False):
return old_compose_all(stream, Loader) return old_compose_all(stream, Loader, reuse_anchors=reuse_anchors)
old_load = yaml.load old_load = yaml.load
def new_load(stream, Loader=yaml.CLoader): def new_load(stream, Loader=yaml.CLoader, reuse_anchors=False):
return old_load(stream, Loader) return old_load(stream, Loader, reuse_anchors=reuse_anchors)
old_load_all = yaml.load_all old_load_all = yaml.load_all
def new_load_all(stream, Loader=yaml.CLoader): def new_load_all(stream, Loader=yaml.CLoader, reuse_anchors=False):
return old_load_all(stream, Loader) return old_load_all(stream, Loader, reuse_anchors=reuse_anchors)
old_safe_load = yaml.safe_load old_safe_load = yaml.safe_load
def new_safe_load(stream): def new_safe_load(stream, reuse_anchors=False):
return old_load(stream, yaml.CSafeLoader) return old_load(stream, yaml.CSafeLoader, reuse_anchors=reuse_anchors)
old_safe_load_all = yaml.safe_load_all old_safe_load_all = yaml.safe_load_all
def new_safe_load_all(stream): def new_safe_load_all(stream, reuse_anchors=False):
return old_load_all(stream, yaml.CSafeLoader) return old_load_all(stream, yaml.CSafeLoader, reuse_anchors=reuse_anchors)
old_emit = yaml.emit old_emit = yaml.emit
def new_emit(events, stream=None, Dumper=yaml.CDumper, **kwds): def new_emit(events, stream=None, Dumper=yaml.CDumper, **kwds):

View file

@ -256,7 +256,8 @@ cdef class CParser:
cdef int stream_cache_pos cdef int stream_cache_pos
cdef int unicode_source cdef int unicode_source
def __init__(self, stream): def __init__(self, stream, reuse_anchors=False):
self.reuse_anchors=reuse_anchors
cdef is_readable cdef is_readable
if yaml_parser_initialize(&self.parser) == 0: if yaml_parser_initialize(&self.parser) == 0:
raise MemoryError raise MemoryError
@ -714,7 +715,7 @@ cdef class CParser:
and self.parsed_event.data.mapping_start.anchor != NULL: and self.parsed_event.data.mapping_start.anchor != NULL:
anchor = PyUnicode_FromYamlString(self.parsed_event.data.mapping_start.anchor) anchor = PyUnicode_FromYamlString(self.parsed_event.data.mapping_start.anchor)
if anchor is not None: if anchor is not None:
if anchor in self.anchors: if anchor in self.anchors and not self.reuse_anchors:
mark = Mark(self.stream_name, mark = Mark(self.stream_name,
self.parsed_event.start_mark.index, self.parsed_event.start_mark.index,
self.parsed_event.start_mark.line, self.parsed_event.start_mark.line,