Schema encode

This commit is contained in:
Tony Garnock-Jones 2021-08-16 11:38:44 -04:00
parent a2ca133983
commit e2b27b619f
1 changed files with 48 additions and 5 deletions

View File

@ -176,11 +176,14 @@ class Enumeration(SchemaEntity):
def _encode(self):
raise TypeError('Cannot encode instance of Enumeration')
def safeattrname(k):
return k + '_' if keyword.iskeyword(k) else k
def safesetattr(o, k, v):
if keyword.iskeyword(k):
setattr(o, k + '_', v)
else:
setattr(o, k, v)
setattr(o, safeattrname(k), v)
def safegetattr(o, k):
return getattr(o, safeattrname(k))
class Definition(SchemaEntity):
EMPTY = False
@ -255,7 +258,13 @@ class Definition(SchemaEntity):
return None
def _encode(self):
raise NotImplementedError('Not yet implemented')
if self.SIMPLE:
if self.EMPTY:
return encode(self.SCHEMA, ())
else:
return encode(self.SCHEMA, self.value)
else:
return encode(self.SCHEMA, self)
def _as_dict(self):
return dict((k, getattr(self, k)) for k in self.FIELD_NAMES)
@ -266,6 +275,35 @@ class Definition(SchemaEntity):
def __setitem__(self, name, value):
return safesetattr(self, name, value)
def encode(p, v):
if p == ANY:
return v
if p.key == NAMED:
return encode(p[1], safegetattr(v, p[0].name))
if p.key == ATOM:
return v
if p.key == EMBEDDED:
return v ## TODO: reconsider representation of embedded values?
if p.key == LIT:
return p[0]
if p.key == SEQOF:
return tuple(encode(p[0], w) for w in v)
if p.key == SETOF:
return set(encode(p[0], w) for w in v)
if p.key == DICTOF:
return dict((encode(p[0], k), encode(p[1], w)) for (k, w) in v.items())
if p.key == REF:
return v._encode()
if p.key == REC:
return Record(encode(p[0], v), encode(p[1], v))
if p.key == TUPLE:
return tuple(encode(pp, v) for pp in p[0])
if p.key == TUPLE_PREFIX:
return tuple(encode(pp, v) for pp in p[0]) + encode(p[1], v)
if p.key == DICT:
return dict((k, encode(pp, v)) for (k, pp) in p[0].items())
raise ValueError('Bad schema')
def module_path_str(mp):
return '.'.join([e.name for e in mp])
@ -392,6 +430,8 @@ if __name__ == '__main__':
with open(__metaschema_filename, 'rb') as f:
x = Decoder(f.read()).next()
print(meta.Schema.decode(x))
print(meta.Schema.decode(x)._encode())
assert meta.Schema.decode(x)._encode() == x
@extend(meta.Schema)
def f(self, x):
@ -407,5 +447,8 @@ if __name__ == '__main__':
x = Decoder(f.read()).next()
print(meta.Schema.decode(x))
print(meta.Schema.decode(x) == meta.Schema.decode(x))
print(meta.Schema.decode(x)._encode())
assert meta.Schema.decode(x)._encode() == x
print()
print(path)