Skip to content

Commit

Permalink
correctly generate the existing test functions
Browse files Browse the repository at this point in the history
  • Loading branch information
thomas-mangin committed Jan 12, 2021
1 parent f70ce47 commit dc61d07
Showing 1 changed file with 99 additions and 98 deletions.
197 changes: 99 additions & 98 deletions yang/generate
Original file line number Diff line number Diff line change
Expand Up @@ -558,6 +558,10 @@ class Code(object):
self.referenced = set()
# the parsed yang as a tree
self.tree = tree
# the main yang namespace/module
self.module = tree[yang.kw['loaded']][0]
# the namespace we are working in
self.ns = self.module

@staticmethod
def _missing(**kargs):
Expand All @@ -573,35 +577,6 @@ class Code(object):
counter[name] = unique
return f'{name}_{unique}'

@staticmethod
def _module(body):
ast = Module(
body=body,
)
return ast

@staticmethod
def _function(name, body):
name = name.split(':')[-1].replace('-', '_')
return [
FunctionDef(
name=name,
args=arguments(
posonlyargs=[],
args=[arg(arg='value', annotation=None, type_comment=None)],
vararg=None,
kwonlyargs=[],
kw_defaults=[],
kwarg=None,
defaults=[],
),
body=body,
decorator_list=[],
returns=None,
type_comment=None,
)
]

@staticmethod
def _return_boolean(value):
return [
Expand All @@ -610,6 +585,13 @@ class Code(object):
)
]

def _python_name(self, name):
if self.ns != self.tree[yang.kw['loaded']][0] and ':' not in name:
# XXX: could this lead to function shadowing?
name = f'{self.ns}:{name}'
# XXX: could this lead to function shadowing?
return name.replace(':', '__').replace('-', '_')

def _if_pattern(self, pattern):
self.imported.add('re')
return [
Expand Down Expand Up @@ -638,12 +620,12 @@ class Code(object):
),
]

def _if_length(self, min, max):
def _if_length(self, minimum, maximum):
self.imported.add('re')
return [
If(
test=Compare(
left=Constant(value=min, kind=None),
left=Constant(value=int(minimum), kind=None),
ops=[
Gt(),
Gt(),
Expand All @@ -654,15 +636,11 @@ class Code(object):
args=[Name(id='value', ctx=Load())],
keywords=[],
),
Constant(value=max, kind=None),
Constant(value=int(maximum), kind=None),
],
),
body=[
Return(
lineno=4,
col_offset=8,
end_lineno=4,
end_col_offset=20,
value=Constant(value=False, kind=None),
),
],
Expand Down Expand Up @@ -782,27 +760,37 @@ class Code(object):
def _if_range(self, minimum, maximum):
return self._if_digit() + self._if_lt(minimum) + self._if_gt(maximum)

def _union(self, names, tests):
funcs = []
def _union(self, node):
values = []

for test in tests:
name = self._unique(names.pop(0))
name = name.replace(':', '__').replace('-', '_')
yield self._function(name, test + self._return_boolean(True))

values += [
UnaryOp(
op=Not(),
operand=Call(
func=Name(id=name, ctx=Load()),
args=[Name(id='value', ctx=Load())],
keywords=[],
generated = []

for union in node:
for what, sub in union.items():
if ':' in what:
if what in generated:
# only generate any imported function once
continue
generated.append(what)
name = what
yield self._type(what, name, sub)
else:
# this is a build_in type (and my have been refined)
# therefore generate one function per type
name = self._unique(what)
yield self._function(name, self._type(what, what, sub))

values += [
UnaryOp(
op=Not(),
operand=Call(
func=Name(id=self._python_name(name), ctx=Load()),
args=[Name(id='value', ctx=Load())],
keywords=[],
),
),
),
]
]

yield funcs + [
yield [
If(
test=BoolOp(
op=And(),
Expand All @@ -817,66 +805,79 @@ class Code(object):
),
]

def _imports(self):
returned = []
def _imported(self):
for imported in self.imported:
returned.append(
Import(
names=[alias(name='re', asname=None)],
)
)
return returned

def _type(self, keyword, node):
if keyword == 'union':
names = []
funcs = []
yield Import(names=[alias(name=imported, asname=None)])

for each in node:
print(each)
for what, sub in each.items():
names.append(what.replace('-', '_'))
funcs.append(self._type(what, sub))
def _type(self, what, name, node):
if what == 'union':
return list(self._union(node))

return list(self._union(names, funcs))

if keyword in ('int8', 'int16', 'int16', 'int32', 'uint8', 'uint16', 'uint16', 'uint32'):
if what in ('int8', 'int16', 'int16', 'int32', 'uint8', 'uint16', 'uint16', 'uint32'):
# not dealing with refine
minimum, maximum = yang.ranges[keyword]
minimum, maximum = yang.ranges[what]
return self._if_range(minimum, maximum)

if keyword == 'string':
if what == 'string':
return list(self._iter_if_string(node))

if ':' in keyword:
ns, name = keyword.split(':', 1)
return list(self._generate(ns, name))
if ':' in what:
ns, name = what.split(':', 1)
backup_ns, self.ns = self.ns, ns
answer = list(self._typedef(ns, name))
self.ns = backup_ns
return answer

self._missing(keyword=keyword, node=node)
self._missing(what=what, name=name, node=node)

def _iter(self, node):
for keyword, content in node.items():
yield self._type(keyword, content)
yield self._type(keyword, keyword, content)

def _generate(self, module, only):
def _function(self, name, body):
# XXX: could this lead to function shadowing?
return [
FunctionDef(
name=self._python_name(name),
args=arguments(
posonlyargs=[],
args=[arg(arg='value', annotation=None, type_comment=None)],
vararg=None,
kwonlyargs=[],
kw_defaults=[],
kwarg=None,
defaults=[],
),
body=body + self._return_boolean(True),
decorator_list=[],
returns=None,
type_comment=None,
)
]

def _typedef(self, module, only):
td = self.tree[module][yang.kw['typedef']]

for name in td:
if only and only != name:
continue
body = list(self._iter(td[name][yang.kw['type']]))
print(name)
print(body)
print('')
yield self._function(name, body + self._return_boolean(True))

def generate(self, module, only=''):
generated = self._imports()
generated += list(self._generate(module, only))
while self.referenced:
module, check = self.referenced.pop(0)
generated += list(self._generate(module, check))
return self._module(generated)
yield self._function(name, body)

def _module(self, module, only=''):
generated = list(self._typedef(module, only))
# while self.referenced:
# module, check = self.referenced.pop(0)
# generated += list(self._typedef(module, check))
return generated

def generate(self, module):
# this must be run first so that the imported module can be generated
body = list(self._module(module))
ast = Module(
body=list(self._imported()) + body,
)
return ast


class Conf(object):
Expand Down Expand Up @@ -910,9 +911,9 @@ class Conf(object):
w.write(self._generate())

def output(self):
for name, data in self.dicts:
pprint.pprint(name)
pprint.pprint(data)
# for name, data in self.dicts:
# pprint.pprint(name)
# pprint.pprint(data)
for section in self.codes:
print(section)

Expand Down

0 comments on commit dc61d07

Please sign in to comment.