Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP Support for the YAML 1.2 Core and JSON schemas #512

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
397 changes: 233 additions & 164 deletions lib3/yaml/constructor.py

Large diffs are not rendered by default.

38 changes: 37 additions & 1 deletion lib3/yaml/dumper.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

__all__ = ['BaseDumper', 'SafeDumper', 'Dumper']
__all__ = ['BaseDumper', 'SafeDumper', 'Dumper', 'CoreDumper', 'JSONDumper']

from .emitter import *
from .serializer import *
Expand Down Expand Up @@ -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,
Expand Down
23 changes: 22 additions & 1 deletion lib3/yaml/loader.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@

__all__ = ['BaseLoader', 'FullLoader', 'SafeLoader', 'Loader', 'UnsafeLoader']
__all__ = ['BaseLoader', 'FullLoader', 'SafeLoader', 'Loader', 'UnsafeLoader',
'CoreLoader', 'JSONLoader']

from .reader import *
from .scanner import *
Expand Down Expand Up @@ -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):
Expand Down
188 changes: 118 additions & 70 deletions lib3/yaml/representer.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@

__all__ = ['BaseRepresenter', 'SafeRepresenter', 'Representer',
'RepresenterError']
'RepresenterError', 'CoreRepresenter', 'JSONRepresenter']

from .error import *
from .nodes import *
Expand Down Expand Up @@ -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'
Expand Down Expand Up @@ -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 = {}
Expand All @@ -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):

Expand Down
Loading