diff --git a/lib3/yaml/constructor.py b/lib3/yaml/constructor.py index 619acd30..f45484e5 100644 --- a/lib3/yaml/constructor.py +++ b/lib3/yaml/constructor.py @@ -2,10 +2,12 @@ __all__ = [ 'BaseConstructor', 'SafeConstructor', + 'CoreConstructor', 'FullConstructor', 'UnsafeConstructor', 'Constructor', - 'ConstructorError' + 'ConstructorError', + 'JSONConstructor', ] from .error import * @@ -18,6 +20,12 @@ class ConstructorError(MarkedYAMLError): class BaseConstructor: + inf_value = 1e300 + while inf_value != inf_value*inf_value: + inf_value *= inf_value + nan_value = -inf_value/inf_value # Trying to make a quiet NaN (like C99). + + yaml_constructors = {} yaml_multi_constructors = {} @@ -168,55 +176,6 @@ def add_multi_constructor(cls, tag_prefix, multi_constructor): cls.yaml_multi_constructors = cls.yaml_multi_constructors.copy() cls.yaml_multi_constructors[tag_prefix] = multi_constructor -class SafeConstructor(BaseConstructor): - - def construct_scalar(self, node): - if isinstance(node, MappingNode): - for key_node, value_node in node.value: - if key_node.tag == 'tag:yaml.org,2002:value': - return self.construct_scalar(value_node) - return super().construct_scalar(node) - - def flatten_mapping(self, node): - merge = [] - index = 0 - while index < len(node.value): - key_node, value_node = node.value[index] - if key_node.tag == 'tag:yaml.org,2002:merge': - del node.value[index] - if isinstance(value_node, MappingNode): - self.flatten_mapping(value_node) - merge.extend(value_node.value) - elif isinstance(value_node, SequenceNode): - submerge = [] - for subnode in value_node.value: - if not isinstance(subnode, MappingNode): - raise ConstructorError("while constructing a mapping", - node.start_mark, - "expected a mapping for merging, but found %s" - % subnode.id, subnode.start_mark) - self.flatten_mapping(subnode) - submerge.append(subnode.value) - submerge.reverse() - for value in submerge: - merge.extend(value) - else: - raise ConstructorError("while constructing a mapping", node.start_mark, - "expected a mapping or list of mappings for merging, but found %s" - % value_node.id, value_node.start_mark) - elif key_node.tag == 'tag:yaml.org,2002:value': - key_node.tag = 'tag:yaml.org,2002:str' - index += 1 - else: - index += 1 - if merge: - node.value = merge + node.value - - def construct_mapping(self, node, deep=False): - if isinstance(node, MappingNode): - self.flatten_mapping(node) - return super().construct_mapping(node, deep=deep) - def construct_yaml_null(self, node): self.construct_scalar(node) return None @@ -234,62 +193,40 @@ def construct_yaml_bool(self, node): value = self.construct_scalar(node) return self.bool_values[value.lower()] - def construct_yaml_int(self, node): - value = self.construct_scalar(node) - value = value.replace('_', '') - sign = +1 - if value[0] == '-': - sign = -1 - if value[0] in '+-': - value = value[1:] - if value == '0': - return 0 - elif value.startswith('0b'): - return sign*int(value[2:], 2) - elif value.startswith('0x'): - return sign*int(value[2:], 16) - elif value[0] == '0': - return sign*int(value, 8) - elif ':' in value: - digits = [int(part) for part in value.split(':')] - digits.reverse() - base = 1 - value = 0 - for digit in digits: - value += digit*base - base *= 60 - return sign*value - else: - return sign*int(value) + def construct_yaml_str(self, node): + return self.construct_scalar(node) - inf_value = 1e300 - while inf_value != inf_value*inf_value: - inf_value *= inf_value - nan_value = -inf_value/inf_value # Trying to make a quiet NaN (like C99). + def construct_yaml_seq(self, node): + data = [] + yield data + data.extend(self.construct_sequence(node)) + + def construct_yaml_map(self, node): + data = {} + yield data + value = self.construct_mapping(node) + data.update(value) + + def construct_undefined(self, node): + raise ConstructorError(None, None, + "could not determine a constructor for the tag %r" % node.tag, + node.start_mark) + + @classmethod + def init_constructors(cls, keys): + for i in keys: + if i not in _constructors: + continue + for key in _constructors[i]: + callback = _constructors[i][key] + if (key is None): + cls.add_constructor(key, callback) + else: + cls.add_constructor('tag:yaml.org,2002:' + key, callback) - def construct_yaml_float(self, node): - value = self.construct_scalar(node) - value = value.replace('_', '').lower() - sign = +1 - if value[0] == '-': - sign = -1 - if value[0] in '+-': - value = value[1:] - if value == '.inf': - return sign*self.inf_value - elif value == '.nan': - return self.nan_value - elif ':' in value: - digits = [float(part) for part in value.split(':')] - digits.reverse() - base = 1 - value = 0.0 - for digit in digits: - value += digit*base - base *= 60 - return sign*value - else: - return sign*float(value) + +# SafeConstructor implements YAML 1.1 +class SafeConstructor(BaseConstructor): def construct_yaml_binary(self, node): try: @@ -399,19 +336,104 @@ def construct_yaml_set(self, node): value = self.construct_mapping(node) data.update(value) - def construct_yaml_str(self, node): - return self.construct_scalar(node) + def construct_scalar(self, node): + if isinstance(node, MappingNode): + for key_node, value_node in node.value: + if key_node.tag == 'tag:yaml.org,2002:value': + return self.construct_scalar(value_node) + return super().construct_scalar(node) - def construct_yaml_seq(self, node): - data = [] - yield data - data.extend(self.construct_sequence(node)) + def flatten_mapping(self, node): + merge = [] + index = 0 + while index < len(node.value): + key_node, value_node = node.value[index] + if key_node.tag == 'tag:yaml.org,2002:merge': + del node.value[index] + if isinstance(value_node, MappingNode): + self.flatten_mapping(value_node) + merge.extend(value_node.value) + elif isinstance(value_node, SequenceNode): + submerge = [] + for subnode in value_node.value: + if not isinstance(subnode, MappingNode): + raise ConstructorError("while constructing a mapping", + node.start_mark, + "expected a mapping for merging, but found %s" + % subnode.id, subnode.start_mark) + self.flatten_mapping(subnode) + submerge.append(subnode.value) + submerge.reverse() + for value in submerge: + merge.extend(value) + else: + raise ConstructorError("while constructing a mapping", node.start_mark, + "expected a mapping or list of mappings for merging, but found %s" + % value_node.id, value_node.start_mark) + elif key_node.tag == 'tag:yaml.org,2002:value': + key_node.tag = 'tag:yaml.org,2002:str' + index += 1 + else: + index += 1 + if merge: + node.value = merge + node.value - def construct_yaml_map(self, node): - data = {} - yield data - value = self.construct_mapping(node) - data.update(value) + def construct_yaml_int(self, node): + value = self.construct_scalar(node) + value = value.replace('_', '') + sign = +1 + if value[0] == '-': + sign = -1 + if value[0] in '+-': + value = value[1:] + if value == '0': + return 0 + elif value.startswith('0b'): + return sign*int(value[2:], 2) + elif value.startswith('0x'): + return sign*int(value[2:], 16) + elif value[0] == '0': + return sign*int(value, 8) + elif ':' in value: + digits = [int(part) for part in value.split(':')] + digits.reverse() + base = 1 + value = 0 + for digit in digits: + value += digit*base + base *= 60 + return sign*value + else: + return sign*int(value) + + def construct_yaml_float(self, node): + value = self.construct_scalar(node) + value = value.replace('_', '').lower() + sign = +1 + if value[0] == '-': + sign = -1 + if value[0] in '+-': + value = value[1:] + if value == '.inf': + return sign*self.inf_value + elif value == '.nan': + return self.nan_value + elif ':' in value: + digits = [float(part) for part in value.split(':')] + digits.reverse() + base = 1 + value = 0.0 + for digit in digits: + value += digit*base + base *= 60 + return sign*value + else: + return sign*float(value) + + def construct_mapping(self, node, deep=False): + if isinstance(node, MappingNode): + self.flatten_mapping(node) + return super().construct_mapping(node, deep=deep) def construct_yaml_object(self, node, cls): data = cls.__new__(cls) @@ -423,61 +445,108 @@ def construct_yaml_object(self, node, cls): state = self.construct_mapping(node) data.__dict__.update(state) - def construct_undefined(self, node): - raise ConstructorError(None, None, - "could not determine a constructor for the tag %r" % node.tag, - node.start_mark) - -SafeConstructor.add_constructor( - 'tag:yaml.org,2002:null', - SafeConstructor.construct_yaml_null) - -SafeConstructor.add_constructor( - 'tag:yaml.org,2002:bool', - SafeConstructor.construct_yaml_bool) - -SafeConstructor.add_constructor( - 'tag:yaml.org,2002:int', - SafeConstructor.construct_yaml_int) - -SafeConstructor.add_constructor( - 'tag:yaml.org,2002:float', - SafeConstructor.construct_yaml_float) - -SafeConstructor.add_constructor( - 'tag:yaml.org,2002:binary', - SafeConstructor.construct_yaml_binary) - -SafeConstructor.add_constructor( - 'tag:yaml.org,2002:timestamp', - SafeConstructor.construct_yaml_timestamp) - -SafeConstructor.add_constructor( - 'tag:yaml.org,2002:omap', - SafeConstructor.construct_yaml_omap) +# CoreConstructor implements YAML 1.2 Core Schema +class CoreConstructor(BaseConstructor): + def construct_yaml_int(self, node): + value = self.construct_scalar(node) + sign = +1 + if value[0] == '-': + sign = -1 + if value[0] in '+-': + value = value[1:] -SafeConstructor.add_constructor( - 'tag:yaml.org,2002:pairs', - SafeConstructor.construct_yaml_pairs) + if value == '0': + return 0 + elif value.startswith('0o'): + return sign*int(value[2:], 8) + elif value.startswith('0x'): + return sign*int(value[2:], 16) + else: + return sign*int(value) -SafeConstructor.add_constructor( - 'tag:yaml.org,2002:set', - SafeConstructor.construct_yaml_set) + def construct_yaml_float(self, node): + value = self.construct_scalar(node) + value = value.lower() + sign = +1 + if value[0] == '-': + sign = -1 + if value[0] in '+-': + value = value[1:] + if value == '.inf': + return sign*self.inf_value + elif value == '.nan': + return self.nan_value + else: + return sign*float(value) -SafeConstructor.add_constructor( - 'tag:yaml.org,2002:str', - SafeConstructor.construct_yaml_str) +# JSONConstructor implements YAML 1.2 JSON Schema +class JSONConstructor(BaseConstructor): -SafeConstructor.add_constructor( - 'tag:yaml.org,2002:seq', - SafeConstructor.construct_yaml_seq) + def construct_yaml_int(self, node): + value = self.construct_scalar(node) + sign = +1 + if value[0] == '-': + sign = -1 + if value[0] in '+-': + value = value[1:] -SafeConstructor.add_constructor( - 'tag:yaml.org,2002:map', - SafeConstructor.construct_yaml_map) + if value == '0': + return 0 + else: + return sign*int(value) -SafeConstructor.add_constructor(None, - SafeConstructor.construct_undefined) + def construct_yaml_float(self, node): + value = self.construct_scalar(node) + value = value.lower() + sign = +1 + if value[0] == '-': + sign = -1 + if value[0] in '+-': + value = value[1:] + return sign*float(value) + + +_constructors = { + 'yaml11': { + 'str': BaseConstructor.construct_yaml_str, + 'seq': BaseConstructor.construct_yaml_seq, + 'map': BaseConstructor.construct_yaml_map, + None: BaseConstructor.construct_undefined, + 'int': SafeConstructor.construct_yaml_int, + 'float': SafeConstructor.construct_yaml_float, + 'null': BaseConstructor.construct_yaml_null, + 'bool': BaseConstructor.construct_yaml_bool, + 'binary': SafeConstructor.construct_yaml_binary, + 'timestamp': SafeConstructor.construct_yaml_timestamp, + 'omap': SafeConstructor.construct_yaml_omap, + 'pairs': SafeConstructor.construct_yaml_pairs, + 'set': SafeConstructor.construct_yaml_set, + }, + 'core': { + 'str': BaseConstructor.construct_yaml_str, + 'seq': BaseConstructor.construct_yaml_seq, + 'map': BaseConstructor.construct_yaml_map, + None: BaseConstructor.construct_undefined, + 'int': CoreConstructor.construct_yaml_int, + 'float': CoreConstructor.construct_yaml_float, + 'null': BaseConstructor.construct_yaml_null, + 'bool': BaseConstructor.construct_yaml_bool, + }, + 'json': { + 'str': BaseConstructor.construct_yaml_str, + 'seq': BaseConstructor.construct_yaml_seq, + 'map': BaseConstructor.construct_yaml_map, + None: BaseConstructor.construct_undefined, + 'int': JSONConstructor.construct_yaml_int, + 'float': JSONConstructor.construct_yaml_float, + 'null': BaseConstructor.construct_yaml_null, + 'bool': BaseConstructor.construct_yaml_bool, + }, +} + +SafeConstructor.init_constructors(['yaml11']) +CoreConstructor.init_constructors(['core']) +JSONConstructor.init_constructors(['json']) class FullConstructor(SafeConstructor): # 'extend' is blacklisted because it is used by diff --git a/lib3/yaml/dumper.py b/lib3/yaml/dumper.py index 6aadba55..0d3d7d1e 100644 --- a/lib3/yaml/dumper.py +++ b/lib3/yaml/dumper.py @@ -1,5 +1,5 @@ -__all__ = ['BaseDumper', 'SafeDumper', 'Dumper'] +__all__ = ['BaseDumper', 'SafeDumper', 'Dumper', 'CoreDumper', 'JSONDumper'] from .emitter import * from .serializer import * @@ -42,6 +42,42 @@ def __init__(self, stream, default_flow_style=default_flow_style, sort_keys=sort_keys) Resolver.__init__(self) +class CoreDumper(Emitter, Serializer, CoreRepresenter, CoreResolver): + + def __init__(self, stream, + default_style=None, default_flow_style=False, + canonical=None, indent=None, width=None, + allow_unicode=None, line_break=None, + encoding=None, explicit_start=None, explicit_end=None, + version=None, tags=None, sort_keys=True): + Emitter.__init__(self, stream, canonical=canonical, + indent=indent, width=width, + allow_unicode=allow_unicode, line_break=line_break) + Serializer.__init__(self, encoding=encoding, + explicit_start=explicit_start, explicit_end=explicit_end, + version=version, tags=tags) + CoreRepresenter.__init__(self, default_style=default_style, + default_flow_style=default_flow_style, sort_keys=sort_keys) + CoreResolver.__init__(self) + +class JSONDumper(Emitter, Serializer, JSONRepresenter, JSONResolver): + + def __init__(self, stream, + default_style=None, default_flow_style=False, + canonical=None, indent=None, width=None, + allow_unicode=None, line_break=None, + encoding=None, explicit_start=None, explicit_end=None, + version=None, tags=None, sort_keys=True): + Emitter.__init__(self, stream, canonical=canonical, + indent=indent, width=width, + allow_unicode=allow_unicode, line_break=line_break) + Serializer.__init__(self, encoding=encoding, + explicit_start=explicit_start, explicit_end=explicit_end, + version=version, tags=tags) + JSONRepresenter.__init__(self, default_style=default_style, + default_flow_style=default_flow_style, sort_keys=sort_keys) + JSONResolver.__init__(self) + class Dumper(Emitter, Serializer, Representer, Resolver): def __init__(self, stream, diff --git a/lib3/yaml/loader.py b/lib3/yaml/loader.py index e90c1122..c1b62abf 100644 --- a/lib3/yaml/loader.py +++ b/lib3/yaml/loader.py @@ -1,5 +1,6 @@ -__all__ = ['BaseLoader', 'FullLoader', 'SafeLoader', 'Loader', 'UnsafeLoader'] +__all__ = ['BaseLoader', 'FullLoader', 'SafeLoader', 'Loader', 'UnsafeLoader', + 'CoreLoader', 'JSONLoader'] from .reader import * from .scanner import * @@ -38,6 +39,26 @@ def __init__(self, stream): SafeConstructor.__init__(self) Resolver.__init__(self) +class CoreLoader(Reader, Scanner, Parser, Composer, CoreConstructor, CoreResolver): + + def __init__(self, stream): + Reader.__init__(self, stream) + Scanner.__init__(self) + Parser.__init__(self) + Composer.__init__(self) + CoreConstructor.__init__(self) + CoreResolver.__init__(self) + +class JSONLoader(Reader, Scanner, Parser, Composer, JSONConstructor, JSONResolver): + + def __init__(self, stream): + Reader.__init__(self, stream) + Scanner.__init__(self) + Parser.__init__(self) + Composer.__init__(self) + JSONConstructor.__init__(self) + JSONResolver.__init__(self) + class Loader(Reader, Scanner, Parser, Composer, Constructor, Resolver): def __init__(self, stream): diff --git a/lib3/yaml/representer.py b/lib3/yaml/representer.py index 3b0b192e..bfb68b4c 100644 --- a/lib3/yaml/representer.py +++ b/lib3/yaml/representer.py @@ -1,6 +1,6 @@ __all__ = ['BaseRepresenter', 'SafeRepresenter', 'Representer', - 'RepresenterError'] + 'RepresenterError', 'CoreRepresenter', 'JSONRepresenter'] from .error import * from .nodes import * @@ -131,29 +131,30 @@ def represent_mapping(self, tag, mapping, flow_style=None): def ignore_aliases(self, data): return False -class SafeRepresenter(BaseRepresenter): + def represent_str(self, data): + return self.represent_scalar('tag:yaml.org,2002:str', data) - def ignore_aliases(self, data): - if data is None: - return True - if isinstance(data, tuple) and data == (): - return True - if isinstance(data, (str, bytes, bool, int, float)): - return True + def represent_list(self, data): + #pairs = (len(data) > 0 and isinstance(data, list)) + #if pairs: + # for item in data: + # if not isinstance(item, tuple) or len(item) != 2: + # pairs = False + # break + #if not pairs: + return self.represent_sequence('tag:yaml.org,2002:seq', data) + #value = [] + #for item_key, item_value in data: + # value.append(self.represent_mapping(u'tag:yaml.org,2002:map', + # [(item_key, item_value)])) + #return SequenceNode(u'tag:yaml.org,2002:pairs', value) + + def represent_dict(self, data): + return self.represent_mapping('tag:yaml.org,2002:map', data) def represent_none(self, data): return self.represent_scalar('tag:yaml.org,2002:null', 'null') - def represent_str(self, data): - return self.represent_scalar('tag:yaml.org,2002:str', data) - - def represent_binary(self, data): - if hasattr(base64, 'encodebytes'): - data = base64.encodebytes(data).decode('ascii') - else: - data = base64.encodestring(data).decode('ascii') - return self.represent_scalar('tag:yaml.org,2002:binary', data, style='|') - def represent_bool(self, data): if data: value = 'true' @@ -184,27 +185,17 @@ def represent_float(self, data): # Unfortunately, this is not a valid float representation according # to the definition of the `!!float` tag. We fix this by adding # '.0' before the 'e' symbol. + # TODO (In YAML 1.2 Core, 1e17 would be a valid float though) if '.' not in value and 'e' in value: value = value.replace('e', '.0e', 1) return self.represent_scalar('tag:yaml.org,2002:float', value) - def represent_list(self, data): - #pairs = (len(data) > 0 and isinstance(data, list)) - #if pairs: - # for item in data: - # if not isinstance(item, tuple) or len(item) != 2: - # pairs = False - # break - #if not pairs: - return self.represent_sequence('tag:yaml.org,2002:seq', data) - #value = [] - #for item_key, item_value in data: - # value.append(self.represent_mapping(u'tag:yaml.org,2002:map', - # [(item_key, item_value)])) - #return SequenceNode(u'tag:yaml.org,2002:pairs', value) - - def represent_dict(self, data): - return self.represent_mapping('tag:yaml.org,2002:map', data) + def represent_binary(self, data): + if hasattr(base64, 'encodebytes'): + data = base64.encodebytes(data).decode('ascii') + else: + data = base64.encodestring(data).decode('ascii') + return self.represent_scalar('tag:yaml.org,2002:binary', data, style='|') def represent_set(self, data): value = {} @@ -220,54 +211,111 @@ def represent_datetime(self, data): value = data.isoformat(' ') return self.represent_scalar('tag:yaml.org,2002:timestamp', value) - def represent_yaml_object(self, tag, data, cls, flow_style=None): - if hasattr(data, '__getstate__'): - state = data.__getstate__() - else: - state = data.__dict__.copy() - return self.represent_mapping(tag, state, flow_style=flow_style) - def represent_undefined(self, data): raise RepresenterError("cannot represent an object", data) -SafeRepresenter.add_representer(type(None), - SafeRepresenter.represent_none) - -SafeRepresenter.add_representer(str, - SafeRepresenter.represent_str) + @classmethod + def init_representers(cls, name): + for key in _representers[name]: + callback = _representers[name][key] + cls.add_representer(key, callback) -SafeRepresenter.add_representer(bytes, - SafeRepresenter.represent_binary) -SafeRepresenter.add_representer(bool, - SafeRepresenter.represent_bool) +class SafeRepresenter(BaseRepresenter): -SafeRepresenter.add_representer(int, - SafeRepresenter.represent_int) + def ignore_aliases(self, data): + if data is None: + return True + if isinstance(data, tuple) and data == (): + return True + if isinstance(data, (str, bytes, bool, int, float)): + return True -SafeRepresenter.add_representer(float, - SafeRepresenter.represent_float) + def represent_yaml_object(self, tag, data, cls, flow_style=None): + if hasattr(data, '__getstate__'): + state = data.__getstate__() + else: + state = data.__dict__.copy() + return self.represent_mapping(tag, state, flow_style=flow_style) -SafeRepresenter.add_representer(list, - SafeRepresenter.represent_list) +class CoreRepresenter(BaseRepresenter): -SafeRepresenter.add_representer(tuple, - SafeRepresenter.represent_list) + def ignore_aliases(self, data): + if data is None: + return True + if isinstance(data, tuple) and data == (): + return True + if isinstance(data, (str, bytes, bool, int, float)): + return True -SafeRepresenter.add_representer(dict, - SafeRepresenter.represent_dict) + def represent_yaml_object(self, tag, data, cls, flow_style=None): + if hasattr(data, '__getstate__'): + state = data.__getstate__() + else: + state = data.__dict__.copy() + return self.represent_mapping(tag, state, flow_style=flow_style) -SafeRepresenter.add_representer(set, - SafeRepresenter.represent_set) +class JSONRepresenter(BaseRepresenter): -SafeRepresenter.add_representer(datetime.date, - SafeRepresenter.represent_date) + def ignore_aliases(self, data): + if data is None: + return True + if isinstance(data, tuple) and data == (): + return True + if isinstance(data, (str, bytes, bool, int, float)): + return True -SafeRepresenter.add_representer(datetime.datetime, - SafeRepresenter.represent_datetime) + def represent_yaml_object(self, tag, data, cls, flow_style=None): + if hasattr(data, '__getstate__'): + state = data.__getstate__() + else: + state = data.__dict__.copy() + return self.represent_mapping(tag, state, flow_style=flow_style) -SafeRepresenter.add_representer(None, - SafeRepresenter.represent_undefined) +_representers = { + 'yaml11': { + bool: BaseRepresenter.represent_bool, + dict: BaseRepresenter.represent_dict, + list: BaseRepresenter.represent_list, + tuple: BaseRepresenter.represent_list, + str: BaseRepresenter.represent_str, + float: BaseRepresenter.represent_float, + int: BaseRepresenter.represent_int, + type(None): BaseRepresenter.represent_none, + bytes: BaseRepresenter.represent_binary, + set: BaseRepresenter.represent_set, + datetime.date: BaseRepresenter.represent_date, + datetime.datetime: BaseRepresenter.represent_datetime, + None: BaseRepresenter.represent_undefined, + }, + 'core': { + bool: BaseRepresenter.represent_bool, + dict: BaseRepresenter.represent_dict, + list: BaseRepresenter.represent_list, + tuple: BaseRepresenter.represent_list, + str: BaseRepresenter.represent_str, + float: BaseRepresenter.represent_float, + int: BaseRepresenter.represent_int, + type(None): BaseRepresenter.represent_none, + None: BaseRepresenter.represent_undefined, + }, + 'json': { + bool: BaseRepresenter.represent_bool, + dict: BaseRepresenter.represent_dict, + list: BaseRepresenter.represent_list, + tuple: BaseRepresenter.represent_list, + str: BaseRepresenter.represent_str, + float: BaseRepresenter.represent_float, + int: BaseRepresenter.represent_int, + type(None): BaseRepresenter.represent_none, + None: BaseRepresenter.represent_undefined, + }, +} + + +SafeRepresenter.init_representers('yaml11') +CoreRepresenter.init_representers('core') +JSONRepresenter.init_representers('json') class Representer(SafeRepresenter): diff --git a/lib3/yaml/resolver.py b/lib3/yaml/resolver.py index 013896d2..8e7b992e 100644 --- a/lib3/yaml/resolver.py +++ b/lib3/yaml/resolver.py @@ -1,5 +1,5 @@ -__all__ = ['BaseResolver', 'Resolver'] +__all__ = ['BaseResolver', 'Resolver', 'CoreResolver', 'JSONResolver'] from .error import * from .nodes import * @@ -164,64 +164,102 @@ def resolve(self, kind, value, implicit): elif kind is MappingNode: return self.DEFAULT_MAPPING_TAG -class Resolver(BaseResolver): - pass + @classmethod + def init_resolvers(cls, key): + for args in _resolvers[key]: + cls.add_implicit_resolver( + 'tag:yaml.org,2002:' + args[0], + args[1], args[2] + ) -Resolver.add_implicit_resolver( - 'tag:yaml.org,2002:bool', - re.compile(r'''^(?:yes|Yes|YES|no|No|NO +_resolvers = { + 'yaml11': [ + ['bool', + re.compile(r'''^(?:yes|Yes|YES|no|No|NO |true|True|TRUE|false|False|FALSE |on|On|ON|off|Off|OFF)$''', re.X), - list('yYnNtTfFoO')) - -Resolver.add_implicit_resolver( - 'tag:yaml.org,2002:float', - re.compile(r'''^(?:[-+]?(?:[0-9][0-9_]*)\.[0-9_]*(?:[eE][-+][0-9]+)? + list('yYnNtTfFoO')], + ['float', + re.compile(r'''^(?:[-+]?(?:[0-9][0-9_]*)\.[0-9_]*(?:[eE][-+][0-9]+)? |\.[0-9_]+(?:[eE][-+][0-9]+)? |[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\.[0-9_]* |[-+]?\.(?:inf|Inf|INF) |\.(?:nan|NaN|NAN))$''', re.X), - list('-+0123456789.')) - -Resolver.add_implicit_resolver( - 'tag:yaml.org,2002:int', - re.compile(r'''^(?:[-+]?0b[0-1_]+ + list('-+0123456789.')], + ['int', + re.compile(r'''^(?:[-+]?0b[0-1_]+ |[-+]?0[0-7_]+ |[-+]?(?:0|[1-9][0-9_]*) |[-+]?0x[0-9a-fA-F_]+ |[-+]?[1-9][0-9_]*(?::[0-5]?[0-9])+)$''', re.X), - list('-+0123456789')) - -Resolver.add_implicit_resolver( - 'tag:yaml.org,2002:merge', - re.compile(r'^(?:<<)$'), - ['<']) - -Resolver.add_implicit_resolver( - 'tag:yaml.org,2002:null', - re.compile(r'''^(?: ~ + list('-+0123456789')], + ['merge', + re.compile(r'^(?:<<)$'), + ['<']], + ['null', + re.compile(r'''^(?: ~ |null|Null|NULL | )$''', re.X), - ['~', 'n', 'N', '']) - -Resolver.add_implicit_resolver( - 'tag:yaml.org,2002:timestamp', - re.compile(r'''^(?:[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] + ['~', 'n', 'N', '']], + ['timestamp', + re.compile(r'''^(?:[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] |[0-9][0-9][0-9][0-9] -[0-9][0-9]? -[0-9][0-9]? (?:[Tt]|[ \t]+)[0-9][0-9]? :[0-9][0-9] :[0-9][0-9] (?:\.[0-9]*)? (?:[ \t]*(?:Z|[-+][0-9][0-9]?(?::[0-9][0-9])?))?)$''', re.X), - list('0123456789')) - -Resolver.add_implicit_resolver( - 'tag:yaml.org,2002:value', - re.compile(r'^(?:=)$'), - ['=']) - + list('0123456789')], + ['value', + re.compile(r'^(?:=)$'), + ['=']], # The following resolver is only for documentation purposes. It cannot work # because plain scalars cannot start with '!', '&', or '*'. -Resolver.add_implicit_resolver( - 'tag:yaml.org,2002:yaml', - re.compile(r'^(?:!|&|\*)$'), - list('!&*')) + ['yaml', + re.compile(r'^(?:!|&|\*)$'), + list('!&*')], + ], + 'core': [ + ['bool', + re.compile(r'''^(?:|true|True|TRUE|false|False|FALSE)$''', re.X), + list('tTfF')], + ['int', + re.compile(r'''^(?: + |0o[0-7]+ + |[-+]?(?:[0-9]+) + |0x[0-9a-fA-F]+ + )$''', re.X), + list('-+0123456789')], + ['float', + re.compile(r'''^(?:[-+]?(?:\.[0-9]+|[0-9]+(\.[0-9]*)?)(?:[eE][-+]?[0-9]+)? + |[-+]?\.(?:inf|Inf|INF) + |\.(?:nan|NaN|NAN))$''', re.X), + list('-+0123456789.')], + ['null', + re.compile(r'''^(?:~||null|Null|NULL)$''', re.X), + ['~', 'n', 'N', '']], + ], + 'json': [ + ['bool', + re.compile(r'''^(?:true|false)$''', re.X), + list('tf')], + ['int', + re.compile(r'''^-?(?:0|[1-9][0-9]*)$''', re.X), + list('-0123456789')], + ['float', + re.compile(r'''^-?(?:0|[1-9][0-9]*)(\.[0-9]*)?(?:[eE][-+]?[0-9]+)?$''', re.X), + list('-0123456789.')], + ['null', + re.compile(r'''^null$''', re.X), + ['n']], + ], +} + +class Resolver(BaseResolver): pass + +class CoreResolver(BaseResolver): pass + +class JSONResolver(BaseResolver): pass + +Resolver.init_resolvers('yaml11') +CoreResolver.init_resolvers('core') +JSONResolver.init_resolvers('json') diff --git a/tests/data/core.schema b/tests/data/core.schema new file mode 100644 index 00000000..2529700d --- /dev/null +++ b/tests/data/core.schema @@ -0,0 +1,234 @@ +--- +'!!bool FALSE': ['bool', 'false()', 'false'] +'!!bool False': ['bool', 'false()', 'false'] +'!!bool TRUE': ['bool', 'true()', 'true'] +'!!bool True': ['bool', 'true()', 'true'] +'!!bool false': ['bool', 'false()', 'false'] +'!!bool true': ['bool', 'true()', 'true'] +'!!float +.INF': ['inf', 'inf()', '.inf'] +'!!float +.Inf': ['inf', 'inf()', '.inf'] +'!!float +.inf': ['inf', 'inf()', '.inf'] +'!!float +0.3e+3': ['float', '300.0', '300.0'] +'!!float +0.3e3': ['float', '300.0', '300.0'] +'!!float -.INF': ['inf', 'inf-neg()', '-.inf'] +'!!float -.Inf': ['inf', 'inf-neg()', '-.inf'] +'!!float -.inf': ['inf', 'inf-neg()', '-.inf'] +'!!float -3.14': ['float', '-3.14', '-3.14'] +'!!float .0': ['float', '0.0', '0.0'] +'!!float .14': ['float', '0.14', '0.14'] +'!!float .3E-1': ['float', '0.03', '0.03'] +'!!float .3e+3': ['float', '300.0', '300.0'] +'!!float .3e3': ['float', '300.0', '300.0'] +'!!float .INF': ['inf', 'inf()', '.inf'] +'!!float .Inf': ['inf', 'inf()', '.inf'] +'!!float .NAN': ['nan', 'nan()', '.nan'] +'!!float .NaN': ['nan', 'nan()', '.nan'] +'!!float .inf': ['inf', 'inf()', '.inf'] +'!!float .nan': ['nan', 'nan()', '.nan'] +'!!float 0.0': ['float', '0.0', '0.0'] +'!!float 0.3e3': ['float', '300.0', '300.0'] +'!!float 001.23': ['float', '1.23', '1.23'] +'!!float 3.': ['float', '3.0', '3.0'] +'!!float 3.14': ['float', '3.14', '3.14'] +'!!float 3.3e+3': ['float', '3300.0', '3300.0'] +'!!int +0': ['int', '0', '0'] +'!!int +23': ['int', '23', '23'] +'!!int -0': ['int', '0', '0'] +'!!int -23': ['int', '-23', '-23'] +'!!int 0': ['int', '0', '0'] +'!!int 0011': ['int', '11', '11'] +'!!int 07': ['int', '7', '7'] +'!!int 0o0': ['int', '0', '0'] +'!!int 0o10': ['int', '8', '8'] +'!!int 0o7': ['int', '7', '7'] +'!!int 0x0': ['int', '0', '0'] +'!!int 0x10': ['int', '16', '16'] +'!!int 0x42': ['int', '66', '66'] +'!!int 0xa': ['int', '10', '10'] +'!!int 23': ['int', '23', '23'] +'!!null #empty': ['null', 'null()', "null"] +'!!null NULL': ['null', 'null()', "null"] +'!!null Null': ['null', 'null()', "null"] +'!!null null': ['null', 'null()', 'null'] +'!!null ~': ['null', 'null()', 'null'] +'!!str #empty': ['str', '', "''"] +'!!str +.INF': ['str', '+.INF', "'+.INF'"] +'!!str +.Inf': ['str', '+.Inf', "'+.Inf'"] +'!!str +.inf': ['str', '+.inf', "'+.inf'"] +'!!str +0': ['str', '+0', "'+0'"] +'!!str +0.3e+3': ['str', '+0.3e+3', "'+0.3e+3'"] +'!!str +0.3e3': ['str', '+0.3e3', "'+0.3e3'"] +'!!str +0100_200': ['str', '+0100_200', "+0100_200"] +'!!str +0b100': ['str', '+0b100', "+0b100"] +'!!str +190:20:30': ['str', '+190:20:30', "+190:20:30"] +'!!str +23': ['str', '+23', "'+23'"] +'!!str -.INF': ['str', '-.INF', "'-.INF'"] +'!!str -.Inf': ['str', '-.Inf', "'-.Inf'"] +'!!str -.inf': ['str', '-.inf', "'-.inf'"] +'!!str -0': ['str', '-0', "'-0'"] +'!!str -0100_200': ['str', '-0100_200', "-0100_200"] +'!!str -0b101': ['str', '-0b101', "-0b101"] +'!!str -0x30': ['str', '-0x30', "-0x30"] +'!!str -190:20:30': ['str', '-190:20:30', "-190:20:30"] +'!!str -23': ['str', '-23', "'-23'"] +'!!str -3.14': ['str', '-3.14', "'-3.14'"] +'!!str .': ['str', '.', '.'] +'!!str .0': ['str', '.0', "'.0'"] +'!!str .14': ['str', '.14', "'.14'"] +'!!str .1_4': ['str', '.1_4', '.1_4'] +'!!str .3E-1': ['str', '.3E-1', "'.3E-1'"] +'!!str .3e+3': ['str', '.3e+3', "'.3e+3'"] +'!!str .3e3': ['str', '.3e3', "'.3e3'"] +'!!str .INF': ['str', '.INF', "'.INF'"] +'!!str .Inf': ['str', '.Inf', "'.Inf'"] +'!!str .NAN': ['str', '.NAN', "'.NAN'"] +'!!str .NaN': ['str', '.NaN', "'.NaN'"] +'!!str ._': ['str', '._', '._'] +'!!str ._14': ['str', '._14', '._14'] +'!!str .inf': ['str', '.inf', "'.inf'"] +'!!str .nan': ['str', '.nan', "'.nan'"] +'!!str 0': ['str', '0', "'0'"] +'!!str 0.0': ['str', '0.0', "'0.0'"] +'!!str 0.3e3': ['str', '0.3e3', "'0.3e3'"] +'!!str 00': ['str', '00', "'00'"] +'!!str 001.23': ['str', '001.23', "'001.23'"] +'!!str 0011': ['str', '0011', "'0011'"] +'!!str 010': ['str', '010', "'010'"] +'!!str 02_0': ['str', '02_0', "02_0"] +'!!str 07': ['str', '07', "'07'"] +'!!str 0b0': ['str', '0b0', "0b0"] +'!!str 0b100_101': ['str', '0b100_101', "0b100_101"] +'!!str 0o0': ['str', '0o0', "'0o0'"] +'!!str 0o10': ['str', '0o10', "'0o10'"] +'!!str 0o7': ['str', '0o7', "'0o7'"] +'!!str 0x0': ['str', '0x0', "'0x0'"] +'!!str 0x2_0': ['str', '0x2_0', "0x2_0"] +'!!str 0xa': ['str', '0xa', "'0xa'"] +'!!str 100_000': ['str', '100_000', "100_000"] +'!!str 190:20:30': ['str', '190:20:30', "190:20:30"] +'!!str 190:20:30.15': ['str', '190:20:30.15', "190:20:30.15"] +'!!str 23': ['str', '23', "'23'"] +'!!str 3.': ['str', '3.', "'3.'"] +'!!str 3.14': ['str', '3.14', "'3.14'"] +'!!str 3.3e+3': ['str', '3.3e+3', "'3.3e+3'"] +'!!str 85.230_15e+03': ['str', '85.230_15e+03', "85.230_15e+03"] +'!!str 85_230.15': ['str', '85_230.15', "85_230.15"] +'!!str FALSE': ['str', 'FALSE', "'FALSE'"] +'!!str False': ['str', 'False', "'False'"] +'!!str N': ['str', 'N', "N"] +'!!str NO': ['str', 'NO', "NO"] +'!!str NULL': ['str', 'NULL', "'NULL'"] +'!!str Null': ['str', 'Null', "'Null'"] +'!!str OFF': ['str', 'OFF', "OFF"] +'!!str ON': ['str', 'ON', "ON"] +'!!str Off': ['str', 'Off', "Off"] +'!!str On': ['str', 'On', "On"] +'!!str TRUE': ['str', 'TRUE', "'TRUE'"] +'!!str True': ['str', 'True', "'True'"] +'!!str Y': ['str', 'Y', "Y"] +'!!str YES': ['str', 'YES', "YES"] +'!!str Yes': ['str', 'Yes', "Yes"] +'!!str _._': ['str', '_._', '_._'] +'!!str false': ['str', 'false', "'false'"] +'!!str n': ['str', 'n', "n"] +'!!str no': ['str', 'no', "no"] +'!!str null': ['str', 'null', "'null'"] +'!!str off': ['str', 'off', "off"] +'!!str on': ['str', 'on', "on"] +'!!str true': ['str', 'true', "'true'"] +'!!str y': ['str', 'y', "y"] +'!!str yes': ['str', 'yes', "yes"] +'!!str ~': ['str', '~', "'~'"] +'#empty': ['null', 'null()', "null"] +'+.INF': ['inf', 'inf()', '.inf'] +'+.Inf': ['inf', 'inf()', '.inf'] +'+.inf': ['inf', 'inf()', '.inf'] +'+0': ['int', '0', '0'] +'+0.3e+3': ['float', '300.0', '300.0'] +'+0.3e3': ['float', '300.0', '300.0'] +'+0100_200': ['str', '+0100_200', '+0100_200'] +'+0b100': ['str', '+0b100', '+0b100'] +'+190:20:30': ['str', '+190:20:30', '+190:20:30'] +'+23': ['int', '23', '23'] +'+3.14': ['float', '3.14', '3.14'] +'-.INF': ['inf', 'inf-neg()', '-.inf'] +'-.Inf': ['inf', 'inf-neg()', '-.inf'] +'-.inf': ['inf', 'inf-neg()', '-.inf'] +'-0': ['int', '0', '0'] +'-0100_200': ['str', '-0100_200', '-0100_200'] +'-0b101': ['str', '-0b101', '-0b101'] +'-0x30': ['str', '-0x30', '-0x30'] +'-190:20:30': ['str', '-190:20:30', '-190:20:30'] +'-23': ['int', '-23', '-23'] +'-3.14': ['float', '-3.14', '-3.14'] +'.': ['str', '.', '.'] +'.0': ['float', '0.0', '0.0'] +'.14': ['float', '0.14', '0.14'] +'.1_4': ['str', '.1_4', '.1_4'] +'.3E-1': ['float', '0.03', '0.03'] +'.3e+3': ['float', '300.0', '300.0'] +'.3e3': ['float', '300.0', '300.0'] +'.INF': ['inf', 'inf()', '.inf'] +'.Inf': ['inf', 'inf()', '.inf'] +'.NAN': ['nan', 'nan()', '.nan'] +'.NaN': ['nan', 'nan()', '.nan'] +'._': ['str', '._', '._'] +'._14': ['str', '._14', '._14'] +'.inf': ['inf', 'inf()', '.inf'] +'.nan': ['nan', 'nan()', '.nan'] +'0': ['int', '0', '0'] +'0.0': ['float', '0.0', '0.0'] +'0.3e3': ['float', '300.0', '300.0'] +'00': ['int', '0', '0'] +'001.23': ['float', '1.23', '1.23'] +'0011': ['int', '11', '11'] +'010': ['int', '10', '10'] +'02_0': ['str', '02_0', '02_0'] +'07': ['int', '7', '7'] +'08': ['int', '8', '8'] +'0b0': ['str', '0b0', '0b0'] +'0b100_101': ['str', '0b100_101', '0b100_101'] +'0o0': ['int', '0', '0'] +'0o10': ['int', '8', '8'] +'0o7': ['int', '7', '7'] +'0x0': ['int', '0', '0'] +'0x10': ['int', '16', '16'] +'0x2_0': ['str', '0x2_0', '0x2_0'] +'0x42': ['int', '66', '66'] +'0xa': ['int', '10', '10'] +'100_000': ['str', '100_000', '100_000'] +'190:20:30': ['str', '190:20:30', '190:20:30'] +'190:20:30.15': ['str', '190:20:30.15', '190:20:30.15'] +'23': ['int', '23', '23'] +'3.': ['float', '3.0', '3.0'] +'3.14': ['float', '3.14', '3.14'] +'3.3e+3': ['float', '3300', '3300.0'] +'3e3': ['float', '3000', '3000.0'] +'85.230_15e+03': ['str', '85.230_15e+03', '85.230_15e+03'] +'85_230.15': ['str', '85_230.15', '85_230.15'] +'FALSE': ['bool', 'false()', 'false'] +'False': ['bool', 'false()', 'false'] +'N': ['str', 'N', "N"] +'NO': ['str', 'NO', "NO"] +'NULL': ['null', 'null()', "null"] +'Null': ['null', 'null()', "null"] +'OFF': ['str', 'OFF', "OFF"] +'ON': ['str', 'ON', "ON"] +'Off': ['str', 'Off', "Off"] +'On': ['str', 'On', "On"] +'TRUE': ['bool', 'true()', 'true'] +'True': ['bool', 'true()', 'true'] +'Y': ['str', 'Y', "Y"] +'YES': ['str', 'YES', "YES"] +'Yes': ['str', 'Yes', "Yes"] +'_._': ['str', '_._', '_._'] +'false': ['bool', 'false()', 'false'] +'n': ['str', 'n', "n"] +'no': ['str', 'no', "no"] +'null': ['null', 'null()', "null"] +'off': ['str', 'off', "off"] +'on': ['str', 'on', "on"] +'true': ['bool', 'true()', 'true'] +'y': ['str', 'y', "y"] +'yes': ['str', 'yes', "yes"] +'~': ['null', 'null()', "null"] diff --git a/tests/data/core.schema-skip b/tests/data/core.schema-skip new file mode 100644 index 00000000..d412d083 --- /dev/null +++ b/tests/data/core.schema-skip @@ -0,0 +1,4 @@ +load: { + } +dump: { + } diff --git a/tests/data/json.schema b/tests/data/json.schema new file mode 100644 index 00000000..08594080 --- /dev/null +++ b/tests/data/json.schema @@ -0,0 +1,194 @@ +--- +'!!bool false': ['bool', 'false()', 'false'] +'!!bool true': ['bool', 'true()', 'true'] +'!!float -3.14': ['float', '-3.14', '-3.14'] +'!!float 0.0': ['float', '0.0', '0.0'] +'!!float 0.3e3': ['float', '300.0', '300.0'] +'!!float 3.': ['float', '3.0', '3.0'] +'!!float 3.14': ['float', '3.14', '3.14'] +'!!int -0': ['int', '0', '0'] +'!!int -23': ['int', '-23', '-23'] +'!!int 0': ['int', '0', '0'] +'!!int 23': ['int', '23', '23'] +'!!null null': ['null', 'null()', 'null'] +'!!str #empty': ['str', '', "''"] +'!!str +.INF': ['str', '+.INF', "+.INF"] +'!!str +.Inf': ['str', '+.Inf', "+.Inf"] +'!!str +.inf': ['str', '+.inf', "+.inf"] +'!!str +0': ['str', '+0', "+0"] +'!!str +0.3e+3': ['str', '+0.3e+3', "+0.3e+3"] +'!!str +0.3e3': ['str', '+0.3e3', "+0.3e3"] +'!!str +0100_200': ['str', '+0100_200', "+0100_200"] +'!!str +0b100': ['str', '+0b100', "+0b100"] +'!!str +190:20:30': ['str', '+190:20:30', "+190:20:30"] +'!!str +23': ['str', '+23', "+23"] +'!!str -.INF': ['str', '-.INF', "-.INF"] +'!!str -.Inf': ['str', '-.Inf', "-.Inf"] +'!!str -.inf': ['str', '-.inf', "-.inf"] +'!!str -0': ['str', '-0', "'-0'"] +'!!str -0100_200': ['str', '-0100_200', "-0100_200"] +'!!str -0b101': ['str', '-0b101', "-0b101"] +'!!str -0x30': ['str', '-0x30', "-0x30"] +'!!str -190:20:30': ['str', '-190:20:30', "-190:20:30"] +'!!str -23': ['str', '-23', "'-23'"] +'!!str -3.14': ['str', '-3.14', "'-3.14'"] +'!!str .': ['str', '.', '.'] +'!!str .0': ['str', '.0', ".0"] +'!!str .14': ['str', '.14', '.14'] +'!!str .1_4': ['str', '.1_4', '.1_4'] +'!!str .3E-1': ['str', '.3E-1', ".3E-1"] +'!!str .3e+3': ['str', '.3e+3', ".3e+3"] +'!!str .3e3': ['str', '.3e3', ".3e3"] +'!!str .INF': ['str', '.INF', ".INF"] +'!!str .Inf': ['str', '.Inf', ".Inf"] +'!!str .NAN': ['str', '.NAN', ".NAN"] +'!!str .NaN': ['str', '.NaN', ".NaN"] +'!!str ._': ['str', '._', '._'] +'!!str ._14': ['str', '._14', '._14'] +'!!str .inf': ['str', '.inf', ".inf"] +'!!str .nan': ['str', '.nan', ".nan"] +'!!str 0': ['str', '0', "'0'"] +'!!str 0.0': ['str', '0.0', "'0.0'"] +'!!str 0.3e3': ['str', '0.3e3', "'0.3e3'"] +'!!str 00': ['str', '00', "00"] +'!!str 001.23': ['str', '001.23', "001.23"] +'!!str 0011': ['str', '0011', "0011"] +'!!str 010': ['str', '010', "010"] +'!!str 02_0': ['str', '02_0', "02_0"] +'!!str 07': ['str', '07', "07"] +'!!str 0b0': ['str', '0b0', "0b0"] +'!!str 0b100_101': ['str', '0b100_101', "0b100_101"] +'!!str 0o0': ['str', '0o0', "0o0"] +'!!str 0o10': ['str', '0o10', "0o10"] +'!!str 0o7': ['str', '0o7', "0o7"] +'!!str 0x0': ['str', '0x0', "0x0"] +'!!str 0x2_0': ['str', '0x2_0', "0x2_0"] +'!!str 0xa': ['str', '0xa', "0xa"] +'!!str 100_000': ['str', '100_000', "100_000"] +'!!str 190:20:30': ['str', '190:20:30', "190:20:30"] +'!!str 190:20:30.15': ['str', '190:20:30.15', "190:20:30.15"] +'!!str 23': ['str', '23', "'23'"] +'!!str 3.': ['str', '3.', "'3.'"] +'!!str 3.14': ['str', '3.14', "'3.14'"] +'!!str 3.3e+3': ['str', '3.3e+3', "'3.3e+3'"] +'!!str 85.230_15e+03': ['str', '85.230_15e+03', "85.230_15e+03"] +'!!str 85_230.15': ['str', '85_230.15', "85_230.15"] +'!!str FALSE': ['str', 'FALSE', "FALSE"] +'!!str False': ['str', 'False', "False"] +'!!str N': ['str', 'N', "N"] +'!!str NO': ['str', 'NO', "NO"] +'!!str NULL': ['str', 'NULL', "NULL"] +'!!str Null': ['str', 'Null', "Null"] +'!!str OFF': ['str', 'OFF', "OFF"] +'!!str ON': ['str', 'ON', "ON"] +'!!str Off': ['str', 'Off', "Off"] +'!!str On': ['str', 'On', "On"] +'!!str TRUE': ['str', 'TRUE', 'TRUE'] +'!!str True': ['str', 'True', 'True'] +'!!str Y': ['str', 'Y', "Y"] +'!!str YES': ['str', 'YES', "YES"] +'!!str Yes': ['str', 'Yes', "Yes"] +'!!str _._': ['str', '_._', '_._'] +'!!str false': ['str', 'false', "'false'"] +'!!str n': ['str', 'n', "n"] +'!!str no': ['str', 'no', "no"] +'!!str null': ['str', 'null', "'null'"] +'!!str off': ['str', 'off', "off"] +'!!str on': ['str', 'on', "on"] +'!!str true': ['str', 'true', "'true'"] +'!!str y': ['str', 'y', "y"] +'!!str yes': ['str', 'yes', "yes"] +'!!str ~': ['str', '~', '~'] +'#empty': ['str', '', "''"] +'+.INF': ['str', '+.INF', '+.INF'] +'+.Inf': ['str', '+.Inf', '+.Inf'] +'+.inf': ['str', '+.inf', '+.inf'] +'+0': ['str', '+0', '+0'] +'+0.3e+3': ['str', '+0.3e+3', '+0.3e+3'] +'+0.3e3': ['str', '+0.3e3', '+0.3e3'] +'+0100_200': ['str', '+0100_200', '+0100_200'] +'+0b100': ['str', '+0b100', '+0b100'] +'+190:20:30': ['str', '+190:20:30', '+190:20:30'] +'+23': ['str', '+23', '+23'] +'+3.14': ['str', '+3.14', '+3.14'] +'-.INF': ['str', '-.INF', '-.INF'] +'-.Inf': ['str', '-.Inf', '-.Inf'] +'-.inf': ['str', '-.inf', '-.inf'] +'-0': ['int', '0', '0'] +'-0100_200': ['str', '-0100_200', '-0100_200'] +'-0b101': ['str', '-0b101', '-0b101'] +'-0x30': ['str', '-0x30', '-0x30'] +'-190:20:30': ['str', '-190:20:30', '-190:20:30'] +'-23': ['int', '-23', '-23'] +'-3.14': ['float', '-3.14', '-3.14'] +'.': ['str', '.', '.'] +'.0': ['str', '.0', '.0'] +'.14': ['str', '.14', '.14'] +'.1_4': ['str', '.1_4', '.1_4'] +'.3E-1': ['str', '.3E-1', '.3E-1'] +'.3e+3': ['str', '.3e+3', '.3e+3'] +'.3e3': ['str', '.3e3', '.3e3'] +'.INF': ['str', '.INF', '.INF'] +'.Inf': ['str', '.Inf', '.Inf'] +'.NAN': ['str', '.NAN', '.NAN'] +'.NaN': ['str', '.NaN', '.NaN'] +'._': ['str', '._', '._'] +'._14': ['str', '._14', '._14'] +'.inf': ['str', '.inf', '.inf'] +'.nan': ['str', '.nan', '.nan'] +'0': ['int', '0', '0'] +'0.0': ['float', '0.0', '0.0'] +'0.3e3': ['float', '300.0', '300.0'] +'00': ['str', '00', '00'] +'001.23': ['str', '001.23', '001.23'] +'0011': ['str', '0011', '0011'] +'010': ['str', '010', '010'] +'02_0': ['str', '02_0', '02_0'] +'07': ['str', '07', '07'] +'08': ['str', '08', '08'] +'0b0': ['str', '0b0', '0b0'] +'0b100_101': ['str', '0b100_101', '0b100_101'] +'0o0': ['str', '0o0', '0o0'] +'0o10': ['str', '0o10', '0o10'] +'0o7': ['str', '0o7', '0o7'] +'0x0': ['str', '0x0', '0x0'] +'0x10': ['str', '0x10', '0x10'] +'0x2_0': ['str', '0x2_0', '0x2_0'] +'0x42': ['str', '0x42', '0x42'] +'0xa': ['str', '0xa', '0xa'] +'100_000': ['str', '100_000', '100_000'] +'190:20:30': ['str', '190:20:30', '190:20:30'] +'190:20:30.15': ['str', '190:20:30.15', '190:20:30.15'] +'23': ['int', '23', '23'] +'3.': ['float', '3.0', '3.0'] +'3.14': ['float', '3.14', '3.14'] +'3.3e+3': ['float', '3300', '3300.0'] +'3e3': ['float', '3000', '3000.0'] +'85.230_15e+03': ['str', '85.230_15e+03', '85.230_15e+03'] +'85_230.15': ['str', '85_230.15', '85_230.15'] +'FALSE': ['str', 'FALSE', 'FALSE'] +'False': ['str', 'False', 'False'] +'N': ['str', 'N', "N"] +'NO': ['str', 'NO', "NO"] +'NULL': ['str', 'NULL', 'NULL'] +'Null': ['str', 'Null', 'Null'] +'OFF': ['str', 'OFF', "OFF"] +'ON': ['str', 'ON', "ON"] +'Off': ['str', 'Off', "Off"] +'On': ['str', 'On', "On"] +'TRUE': ['str', 'TRUE', 'TRUE'] +'True': ['str', 'True', 'True'] +'Y': ['str', 'Y', "Y"] +'YES': ['str', 'YES', "YES"] +'Yes': ['str', 'Yes', "Yes"] +'_._': ['str', '_._', '_._'] +'false': ['bool', 'false()', 'false'] +'n': ['str', 'n', "n"] +'no': ['str', 'no', "no"] +'null': ['null', 'null()', "null"] +'off': ['str', 'off', "off"] +'on': ['str', 'on', "on"] +'true': ['bool', 'true()', 'true'] +'y': ['str', 'y', "y"] +'yes': ['str', 'yes', "yes"] +'~': ['str', '~', '~'] diff --git a/tests/data/json.schema-skip b/tests/data/json.schema-skip new file mode 100644 index 00000000..d2fe12e4 --- /dev/null +++ b/tests/data/json.schema-skip @@ -0,0 +1,6 @@ +load: { + } +dump: { + '#empty': 1, + '!!str #empty': 1, + } diff --git a/tests/data/yaml11.schema b/tests/data/yaml11.schema new file mode 100644 index 00000000..26e43efb --- /dev/null +++ b/tests/data/yaml11.schema @@ -0,0 +1,263 @@ +--- +'!!bool FALSE': ['bool', 'false()', 'false'] +'!!bool False': ['bool', 'false()', 'false'] +'!!bool N': ['bool', 'false()', "false"] +'!!bool NO': ['bool', 'false()', "false"] +'!!bool No': ['bool', 'false()', "false"] +'!!bool OFF': ['bool', 'false()', "false"] +'!!bool ON': ['bool', 'true()', "true"] +'!!bool Off': ['bool', 'false()', "false"] +'!!bool On': ['bool', 'true()', "true"] +'!!bool TRUE': ['bool', 'true()', 'true'] +'!!bool True': ['bool', 'true()', 'true'] +'!!bool Y': ['bool', 'true()', "true"] +'!!bool YES': ['bool', 'true()', "true"] +'!!bool Yes': ['bool', 'true()', "true"] +'!!bool false': ['bool', 'false()', 'false'] +'!!bool n': ['bool', 'false()', "false"] +'!!bool no': ['bool', 'false()', "false"] +'!!bool off': ['bool', 'false()', "false"] +'!!bool on': ['bool', 'true()', "true"] +'!!bool true': ['bool', 'true()', 'true'] +'!!bool y': ['bool', 'true()', "true"] +'!!bool yes': ['bool', 'true()', "true"] +'!!float +.INF': ['inf', 'inf()', '.inf'] +'!!float +.Inf': ['inf', 'inf()', '.inf'] +'!!float +.inf': ['inf', 'inf()', '.inf'] +'!!float +0.3e+3': ['float', '300.0', '300.0'] +'!!float -.INF': ['inf', 'inf-neg()', '-.inf'] +'!!float -.Inf': ['inf', 'inf-neg()', '-.inf'] +'!!float -.inf': ['inf', 'inf-neg()', '-.inf'] +'!!float -3.14': ['float', '-3.14', '-3.14'] +'!!float .0': ['float', '0.0', '0.0'] +'!!float .14': ['float', '0.14', '0.14'] +'!!float .1_4': ['float', '0.14', '0.14'] +'!!float .3E-1': ['float', '0.03', '0.03'] +'!!float .3e+3': ['float', '300.0', '300.0'] +'!!float .INF': ['inf', 'inf()', '.inf'] +'!!float .Inf': ['inf', 'inf()', '.inf'] +'!!float .NAN': ['nan', 'nan()', '.nan'] +'!!float .NaN': ['nan', 'nan()', '.nan'] +'!!float .inf': ['inf', 'inf()', '.inf'] +'!!float .nan': ['nan', 'nan()', '.nan'] +'!!float 0.0': ['float', '0.0', '0.0'] +'!!float 001.23': ['float', '1.23', '1.23'] +'!!float 190:20:30.15': ['float', '685230.15', '685230.15'] +'!!float 3.': ['float', '3.0', '3.0'] +'!!float 3.14': ['float', '3.14', '3.14'] +'!!float 3.3e+3': ['float', '3300.0', '3300.0'] +'!!float 85.230_15e+03': ['float', '85230.15', '85230.15'] +'!!float 85_230.15': ['float', '85230.15', '85230.15'] +'!!int +0': ['int', '0', '0'] +'!!int +0100_200': ['int', '32896', '32896'] +'!!int +0b100': ['int', '4', '4'] +'!!int +190:20:30': ['int', '685230', '685230'] +'!!int +23': ['int', '23', '23'] +'!!int -0': ['int', '0', '0'] +'!!int -0100_200': ['int', '-32896', '-32896'] +'!!int -0b101': ['int', '-5', '-5'] +'!!int -0x30': ['int', '-48', '-48'] +'!!int -190:20:30': ['int', '-685230', '-685230'] +'!!int -23': ['int', '-23', '-23'] +'!!int 0': ['int', '0', '0'] +'!!int 00': ['int', '0', '0'] +'!!int 0011': ['int', '9', '9'] +'!!int 010': ['int', '8', '8'] +'!!int 02_0': ['int', '16', '16'] +'!!int 07': ['int', '7', '7'] +'!!int 0b0': ['int', '0', '0'] +'!!int 0b100_101': ['int', '37', '37'] +'!!int 0x0': ['int', '0', '0'] +'!!int 0x10': ['int', '16', '16'] +'!!int 0x2_0': ['int', '32', '32'] +'!!int 0x42': ['int', '66', '66'] +'!!int 0xa': ['int', '10', '10'] +'!!int 100_000': ['int', '100000', '100000'] +'!!int 190:20:30': ['int', '685230', '685230'] +'!!int 23': ['int', '23', '23'] +'!!null #empty': ['null', 'null()', "null"] +'!!null NULL': ['null', 'null()', "null"] +'!!null Null': ['null', 'null()', "null"] +'!!null null': ['null', 'null()', 'null'] +'!!null ~': ['null', 'null()', 'null'] +'!!str #empty': ['str', '', "''"] +'!!str +.INF': ['str', '+.INF', "'+.INF'"] +'!!str +.Inf': ['str', '+.Inf', "'+.Inf'"] +'!!str +.inf': ['str', '+.inf', "'+.inf'"] +'!!str +0': ['str', '+0', "'+0'"] +'!!str +0.3e+3': ['str', '+0.3e+3', "'+0.3e+3'"] +'!!str +0.3e3': ['str', '+0.3e3', "+0.3e3"] +'!!str +0100_200': ['str', '+0100_200', "'+0100_200'"] +'!!str +0b100': ['str', '+0b100', "'+0b100'"] +'!!str +190:20:30': ['str', '+190:20:30', "'+190:20:30'"] +'!!str +23': ['str', '+23', "'+23'"] +'!!str -.INF': ['str', '-.INF', "'-.INF'"] +'!!str -.Inf': ['str', '-.Inf', "'-.Inf'"] +'!!str -.inf': ['str', '-.inf', "'-.inf'"] +'!!str -0': ['str', '-0', "'-0'"] +'!!str -0100_200': ['str', '-0100_200', "'-0100_200'"] +'!!str -0b101': ['str', '-0b101', "'-0b101'"] +'!!str -0x30': ['str', '-0x30', "'-0x30'"] +'!!str -190:20:30': ['str', '-190:20:30', "'-190:20:30'"] +'!!str -23': ['str', '-23', "'-23'"] +'!!str -3.14': ['str', '-3.14', "'-3.14'"] +'!!str .': ['str', '.', '.'] +'!!str .0': ['str', '.0', "'.0'"] +'!!str .14': ['str', '.14', "'.14'"] +'!!str .1_4': ['str', '.1_4', "'.1_4'"] +'!!str .3E-1': ['str', '.3E-1', "'.3E-1'"] +'!!str .3e+3': ['str', '.3e+3', "'.3e+3'"] +'!!str .3e3': ['str', '.3e3', ".3e3"] +'!!str .INF': ['str', '.INF', "'.INF'"] +'!!str .Inf': ['str', '.Inf', "'.Inf'"] +'!!str .NAN': ['str', '.NAN', "'.NAN'"] +'!!str .NaN': ['str', '.NaN', "'.NaN'"] +'!!str ._': ['str', '._', '._'] +'!!str ._14': ['str', '._14', '._14'] +'!!str .inf': ['str', '.inf', "'.inf'"] +'!!str .nan': ['str', '.nan', "'.nan'"] +'!!str 0': ['str', '0', "'0'"] +'!!str 0.0': ['str', '0.0', "'0.0'"] +'!!str 0.3e3': ['str', '0.3e3', "0.3e3"] +'!!str 00': ['str', '00', "'00'"] +'!!str 001.23': ['str', '001.23', "'001.23'"] +'!!str 0011': ['str', '0011', "'0011'"] +'!!str 010': ['str', '010', "'010'"] +'!!str 02_0': ['str', '02_0', "'02_0'"] +'!!str 07': ['str', '07', "'07'"] +'!!str 0b0': ['str', '0b0', "'0b0'"] +'!!str 0b100_101': ['str', '0b100_101', "'0b100_101'"] +'!!str 0o0': ['str', '0o0', "0o0"] +'!!str 0o10': ['str', '0o10', "0o10"] +'!!str 0o7': ['str', '0o7', "0o7"] +'!!str 0x0': ['str', '0x0', "'0x0'"] +'!!str 0x2_0': ['str', '0x2_0', "'0x2_0'"] +'!!str 0xa': ['str', '0xa', "'0xa'"] +'!!str 100_000': ['str', '100_000', "'100_000'"] +'!!str 190:20:30': ['str', '190:20:30', "'190:20:30'"] +'!!str 190:20:30.15': ['str', '190:20:30.15', "'190:20:30.15'"] +'!!str 23': ['str', '23', "'23'"] +'!!str 3.': ['str', '3.', "'3.'"] +'!!str 3.14': ['str', '3.14', "'3.14'"] +'!!str 3.3e+3': ['str', '3.3e+3', "'3.3e+3'"] +'!!str 85.230_15e+03': ['str', '85.230_15e+03', "'85.230_15e+03'"] +'!!str 85_230.15': ['str', '85_230.15', "'85_230.15'"] +'!!str FALSE': ['str', 'FALSE', "'FALSE'"] +'!!str False': ['str', 'False', "'False'"] +'!!str N': ['str', 'N', "'N'"] +'!!str NO': ['str', 'NO', "'NO'"] +'!!str NULL': ['str', 'NULL', "'NULL'"] +'!!str Null': ['str', 'Null', "'Null'"] +'!!str OFF': ['str', 'OFF', "'OFF'"] +'!!str ON': ['str', 'ON', "'ON'"] +'!!str Off': ['str', 'Off', "'Off'"] +'!!str On': ['str', 'On', "'On'"] +'!!str TRUE': ['str', 'TRUE', "'TRUE'"] +'!!str True': ['str', 'True', "'True'"] +'!!str Y': ['str', 'Y', "'Y'"] +'!!str YES': ['str', 'YES', "'YES'"] +'!!str Yes': ['str', 'Yes', "'Yes'"] +'!!str _._': ['str', '_._', '_._'] +'!!str false': ['str', 'false', "'false'"] +'!!str n': ['str', 'n', "'n'"] +'!!str no': ['str', 'no', "'no'"] +'!!str null': ['str', 'null', "'null'"] +'!!str off': ['str', 'off', "'off'"] +'!!str on': ['str', 'on', "'on'"] +'!!str true': ['str', 'true', "'true'"] +'!!str y': ['str', 'y', "'y'"] +'!!str yes': ['str', 'yes', "'yes'"] +'!!str ~': ['str', '~', "'~'"] +'#empty': ['null', 'null()', "null"] +'+.INF': ['inf', 'inf()', '.inf'] +'+.Inf': ['inf', 'inf()', '.inf'] +'+.inf': ['inf', 'inf()', '.inf'] +'+0': ['int', '0', '0'] +'+0.3e+3': ['float', '300.0', '300.0'] +'+0.3e3': ['str', '+0.3e3', '+0.3e3'] +'+0100_200': ['int', '32896', '32896'] +'+0b100': ['int', '4', '4'] +'+190:20:30': ['int', '685230', '685230'] +'+23': ['int', '23', '23'] +'+3.14': ['float', '3.14', '3.14'] +'-.INF': ['inf', 'inf-neg()', '-.inf'] +'-.Inf': ['inf', 'inf-neg()', '-.inf'] +'-.inf': ['inf', 'inf-neg()', '-.inf'] +'-0': ['int', '0', '0'] +'-0100_200': ['int', '-32896', '-32896'] +'-0b101': ['int', '-5', '-5'] +'-0x30': ['int', '-48', '-48'] +'-190:20:30': ['int', '-685230', '-685230'] +'-23': ['int', '-23', '-23'] +'-3.14': ['float', '-3.14', '-3.14'] +'.': ['str', '.', '.'] +'.0': ['float', '0.0', '0.0'] +'.14': ['float', '0.14', '0.14'] +'.1_4': ['float', '0.14', '0.14'] +'.3E-1': ['float', '0.03', '0.03'] +'.3e+3': ['float', '300.0', '300.0'] +'.3e3': ['str', '.3e3', '.3e3'] +'.INF': ['inf', 'inf()', '.inf'] +'.Inf': ['inf', 'inf()', '.inf'] +'.NAN': ['nan', 'nan()', '.nan'] +'.NaN': ['nan', 'nan()', '.nan'] +'._': ['str', '._', '._'] +'._14': ['str', '._14', '._14'] +'.inf': ['inf', 'inf()', '.inf'] +'.nan': ['nan', 'nan()', '.nan'] +'0': ['int', '0', '0'] +'0.0': ['float', '0.0', '0.0'] +'0.3e3': ['str', '0.3e3', '0.3e3'] +'00': ['int', '0', '0'] +'001.23': ['float', '1.23', '1.23'] +'0011': ['int', '9', '9'] +'010': ['int', '8', '8'] +'02_0': ['int', '16', '16'] +'07': ['int', '7', '7'] +'08': ['str', '08', '08'] +'0b0': ['int', '0', '0'] +'0b100_101': ['int', '37', '37'] +'0o0': ['str', '0o0', '0o0'] +'0o10': ['str', '0o10', '0o10'] +'0o7': ['str', '0o7', '0o7'] +'0x0': ['int', '0', '0'] +'0x10': ['int', '16', '16'] +'0x2_0': ['int', '32', '32'] +'0x42': ['int', '66', '66'] +'0xa': ['int', '10', '10'] +'100_000': ['int', '100000', '100000'] +'190:20:30': ['int', '685230', '685230'] +'190:20:30.15': ['float', '685230.15', '685230.15'] +'23': ['int', '23', '23'] +'3.': ['float', '3.0', '3.0'] +'3.14': ['float', '3.14', '3.14'] +'3.3e+3': ['float', '3300', '3300.0'] +'3e3': ['str', '3e3', '3e3'] +'85.230_15e+03': ['float', '85230.15', '85230.15'] +'85_230.15': ['float', '85230.15', '85230.15'] +'FALSE': ['bool', 'false()', 'false'] +'False': ['bool', 'false()', 'false'] +'N': ['bool', 'false()', "false"] +'NO': ['bool', 'false()', "false"] +'NULL': ['null', 'null()', "null"] +'Null': ['null', 'null()', "null"] +'OFF': ['bool', 'false()', "false"] +'ON': ['bool', 'true()', "true"] +'Off': ['bool', 'false()', "false"] +'On': ['bool', 'true()', "true"] +'TRUE': ['bool', 'true()', 'true'] +'True': ['bool', 'true()', 'true'] +'Y': ['bool', 'true()', "true"] +'YES': ['bool', 'true()', "true"] +'Yes': ['bool', 'true()', "true"] +'_._': ['str', '_._', '_._'] +'false': ['bool', 'false()', 'false'] +'n': ['bool', 'false()', "false"] +'no': ['bool', 'false()', "false"] +'null': ['null', 'null()', "null"] +'off': ['bool', 'false()', "false"] +'on': ['bool', 'true()', "true"] +'true': ['bool', 'true()', 'true'] +'y': ['bool', 'true()', "true"] +'yes': ['bool', 'true()', "true"] +'~': ['null', 'null()', "null"] diff --git a/tests/data/yaml11.schema-skip b/tests/data/yaml11.schema-skip new file mode 100644 index 00000000..4fe0f0bf --- /dev/null +++ b/tests/data/yaml11.schema-skip @@ -0,0 +1,9 @@ +load: { + 'Y': 1, 'y': 1, 'N': 1, 'n': 1, + '!!bool Y': 1, '!!bool N': 1, '!!bool n': 1, '!!bool y': 1, + '._', '!!str ._', + '._14', '!!str ._14' + } +dump: { + '!!str N': 1, '!!str Y': 1, '!!str n': 1, '!!str y': 1, + } diff --git a/tests/lib3/test_schema.py b/tests/lib3/test_schema.py new file mode 100644 index 00000000..3113c5fc --- /dev/null +++ b/tests/lib3/test_schema.py @@ -0,0 +1,177 @@ +import yaml +import os +import sys +import pprint + +def check_bool(value, expected): + if expected == 'false()' and value is False: + return 1 + if expected == 'true()' and value is True: + return 1 + print(value) + print(expected) + return 0 + +def check_int(value, expected): + if (int(expected) == value): + return 1 + print(value) + print(expected) + return 0 + +def check_float(value, expected): + if expected == 'inf()': + if value == float("inf"): + return 1 + elif expected == 'inf-neg()': + if value == float("-inf"): + return 1 + elif expected == 'nan()': + if value != value or (value == 0.0 and value == 1.0): + return 1 + elif (float(expected) == value): + return 1 + else: + print(value) + print(expected) + return 0 + +def check_str(value, expected): + if value == expected: + return 1 + print(value) + print(expected) + return 0 + + +def _fail(input, test): + print("Input: >>" + input + "<<"); + print(test); + +# The tests/data/yaml11.schema file is copied from +# https://github.com/perlpunk/yaml-test-schema/blob/dev/data/schema-yaml11.yaml +def test_implicit_resolver(data_filename, skip_filename, verbose=False): + types = { + 'str': [str, check_str], + 'int': [int, check_int], + 'float': [float, check_float], + 'inf': [float, check_float], + 'nan': [float, check_float], + 'bool': [bool, check_bool], + } + loaders = { + 'yaml11': yaml.SafeLoader, + 'core': yaml.CoreLoader, + 'json': yaml.JSONLoader, + } + dumpers = { + 'yaml11': yaml.SafeDumper, + 'core': yaml.CoreDumper, + 'json': yaml.JSONDumper, + } + loadername = os.path.splitext(os.path.basename(data_filename))[0] + print('==================') + print(loadername) +# loadername = 'yaml11' + skipdata = yaml.load(open(skip_filename, 'rb'), Loader=yaml.SafeLoader) + skip_load = skipdata['load']; + skip_dump = skipdata['dump']; + if verbose: + print(skip_load) + tests = yaml.load(open(data_filename, 'rb'), Loader=yaml.SafeLoader) + + i = 0; + fail = 0; + for input, test in sorted(tests.items()): + if verbose: + print('-------------------- ' + str(i)) + test = tests[input] + i += 1 + + # Skip known loader bugs + if input in skip_load: + continue + + exp_type = test[0]; + data = test[1]; + exp_dump = test[2]; + + # Test loading + try: + doc_input = """---\n""" + input + loaded = yaml.load(doc_input, Loader=loaders[loadername]) + except: + print("Error:", sys.exc_info()[0], '(', sys.exc_info()[1], ')') + fail+=1 + _fail(input, test) + continue + + if verbose: + print(input) + print(test) + print(loaded) + print(type(loaded)) + + if exp_type == 'null': + if loaded is None: + pass + else: + fail+=1 + _fail(input, test) + else: + t = types[exp_type][0] + code = types[exp_type][1] + + if isinstance(loaded, t): + if code(loaded, data): + pass + else: + fail+=1 + print("Expected data: >>" + str(data) + "<< Got: >>" + str(loaded) + "<<"); + _fail(input, test) + else: + fail+=1 + print("Expected type: >>" + exp_type + "<< Got: >>" + str(loaded) + "<<"); + _fail(input, test) + + # Skip known dumper bugs + if input in skip_dump: + continue + + dump = yaml.dump(loaded, explicit_end=False, Dumper=dumpers[loadername]) + # strip trailing newlines and footers + if (dump == '...\n'): + dump = '' + if dump.endswith('\n...\n'): + dump = dump[:-5] + if dump.endswith('\n'): + dump = dump[:-1] + if dump == exp_dump: + pass + else: + print("Compare: >>" + dump + "<< >>" + exp_dump + "<<"); + print(skip_dump) + print(input) + print(test) + print(loaded) + print(type(loaded)) + fail+=1 + _fail(input, test) + +# if i >= 80: +# break + + if fail > 0: + print("Failed " + str(fail) + " / " + str(i) + " tests"); + assert(False) + else: + print("Passed " + str(i) + " tests"); + print("Skipped " + str(len(skip_load)) + " load tests"); + print("Skipped " + str(len(skip_dump)) + " dump tests"); + +test_implicit_resolver.unittest = ['.schema', '.schema-skip'] + +if __name__ == '__main__': + import test_appliance + test_appliance.run(globals()) + diff --git a/tests/lib3/test_yaml.py b/tests/lib3/test_yaml.py index 352cd8d1..7b3d8f9d 100644 --- a/tests/lib3/test_yaml.py +++ b/tests/lib3/test_yaml.py @@ -14,6 +14,8 @@ from test_sort_keys import * from test_multi_constructor import * +from test_schema import * + if __name__ == '__main__': import test_appliance test_appliance.run(globals())