%PDF- %PDF-
Direktori : /opt/alt/python37/lib64/python3.7/site-packages/guppy/gsl/ |
Current File : //opt/alt/python37/lib64/python3.7/site-packages/guppy/gsl/Tester.py |
class Doc2Tester: def __init__(self, mod, doc, node): self.mod = mod self.doc = doc self.node = node self.exdefs = [] self.set_out([]) self.test_names = {} self.condition_exprs = {} self.condition_methods = {} self.document_metas = [] self.document_lang = None self.document_title = None self.example_exprs = {} self.ex_id = 1 def _visit_children(self, node): E = self.mod.ReportedError for ch in node.children: try: ch.accept(self) except E: pass def ap(self, *args): self.extend(args) def error(self, msg, *args, **kwds): msg = 'Doc2Tester: ' + msg self.doc.env.error(msg, *args, **kwds) def get_condition_method(self, cond): idn = cond.get_id_name() name = self.condition_methods.get(idn) if name is None: name = 'cond_%d' % len(self.condition_methods) self.condition_methods[idn] = name ap = self.ap myself = '_self' arg_names = cond.get_arg_names() while myself in arg_names: myself = '_' + myself argstring = ', '.join([myself]+arg_names) ap('def %s(%s):' % (name, argstring), '<NL>', '<INDENT>') ap('# Condition: %s' % idn, '<NL>') pcs = cond.find_aspects('python_code') if not pcs: self.error('No python code specified for testing condition: %r.' % idn, cond.src.node, exception=None) for pc in pcs: for ic in pc.find_aspects('in_context'): ctx = ic.src.node.arg.strip() for line in ctx.split('\n'): ap(line, '<NL>') if pc is pcs[-1]: ap('return (%s)' % pc.src.node.arg.strip(), '<NL>') else: ap('if not (%s):' % pc.src.node.arg.strip(), '<NL>', '<INDENT>') ap('return False', '<NL>', '<DEDENT>') ap('<DEDENT>') return name def gen_comment(self, s): for line in s.split('\n'): self.ap('# '+line, '<NL>') def get_children(self, node): if not node.arg.strip(): return node.children return (self.doc.node_of_taci('name', node.arg.strip()),)+tuple(node.children) def get_condition_expr(self, po, args, attr, src, tgt): cond = po.get_definition() if cond is None: return None name = self.get_condition_method(cond) callargs = [] self_name = attr.get_self_name() for an in po.arg_names: v = None if an == self_name: v = src elif an == '<returned value>': v = tgt else: v = args.get_arg_value(an) if v is None: self.error('Invalid condition argument: %r.' % an, po.src.node, exception=None) continue v = args.mapname(v) callargs.append(v) return '%sself.%s(%s)' % ( ('', 'not ')[po.is_not], name, ', '.join(callargs)) def get_example_expr(self, eg): ex = self.example_exprs.get(eg) if ex is not None: return ex ex = eg.get_ex_text() ctx = eg.get_ctx_text() if ctx: ex_name = 'get_ex_%d' % self.ex_id self.ex_id += 1 self.ap('def %s(self):' % ex_name, '<NL>', '<INDENT>') for line in ctx.split('\n'): self.ap(line, '<NL>') self.ap('return %s' % ex, '<NL>', '<DEDENT>') ex = 'self.%s()' % ex_name self.example_exprs[eg] = ex return ex def get_test_name(self, kind): tn = kind.srclastname if tn in self.test_names: i = self.test_names[tn] self.test_names[tn] += 1 tn = '%s_%d' % (tn, i) else: self.test_names[tn] = 1 return tn def get_tester(self): ap = self.ap ap('# Tests generated by: %s' % __name__, '<NL>') # ap('# Main source file: %s' % # self.doc.env.get_package().get_filename(), '<NL>') ap('# Date: %s' % self.mod.time.asctime( self.mod.time.localtime()), '<NL>') ap('class Tester:', '<NL>', '<INDENT>') ap('tests = {}', '<NL>') self._visit_children(self.node) lines = [] indent = 0 line = [] for tok in self.out: if tok == '<INDENT>': indent += 4 elif tok == '<DEDENT>': indent -= 4 elif tok == '<NL>': lines.append(''.join(line)) line = [] else: if not line: line.append(indent * ' ') line.append(tok) return '\n'.join(lines)+'\n' def set_out(self, out): self.out = out self.extend = out.extend def visit_arglist(self, node): self.ap('(') comma = 0 for ch in self.get_children(node): if comma: self.ap(', ') else: comma = 1 ch.accept(self) self.ap(')') def visit_assign(self, node): children = self.get_children(node) while children: children[0].accept(self) self.ap(' = ') children[1].accept(self) self.ap('<NL>') children = children[2:] def visit_block(self, node): self.ap('<INDENT>') self._visit_children(node) self.ap('<DEDENT>') def visit_call(self, node): children = self.get_children(node) children[0].accept(self) self.ap('(') comma = 0 for ch in children[1:]: if comma: self.ap(', ') else: comma = 1 ch.accept(self) self.ap(')') def visit_comment(self, node): pass def visit_def(self, node): self.ap('def ') children = self.get_children(node) children[0].accept(self) children[1].accept(self) self.ap(':', '<NL>') for ch in children[2:]: ch.accept(self) def visit_default(self, node): self.error('I don\'t know what to generate for the tag %r.' % node.tag, node) def visit_document(self, node): self._visit_children(node) def visit_document_lang(self, node): if self.document_lang is not None: self.error('Duplicate document lang directive.', node) self.document_lang = node def visit_document_title(self, node): if self.document_title is not None: self.error('Duplicate document title directive.', node) self.document_title = node def visit_exdefs(self, node): self.exdefs.append(node) def visit_fcall(self, node): self.visit_call(node) def visit_index(self, node): children = self.get_children(node) children[0].accept(self) self.ap('[') comma = 0 for ch in children[1:]: if comma: self.ap(', ') else: comma = 1 ch.accept(self) self.ap(']') def visit_meta(self, node): self.document_metas.append(node) def visit_name(self, node): self.ap(node.arg.strip()) def visit_pcall(self, node): self.visit_call(node) self.ap('<NL>') def visit_string(self, node): self.ap('%r' % node.arg.strip()) def visit_subject(self, node): self.ap('SUBJECT') def visit_test_of(self, node): TestOf(self, node) def visit_test_program_segment(self, node): self.gen_comment('Test for: %s' % node.arg.strip()) self._visit_children(node) def visit_to_document_only(self, node): pass def visit_to_tester_only(self, node): self._visit_children(node) class DiffKind: def __init__(self, a, b): self.a = a self.b = b self.d_tag = 'diffkind' def get_atom_kinds(self): return [self] def get_id_name(self): return self.a.get_id_name() + '+' + self.b.get_id_name() + "'" class EitherTest: def __init__(self, ): pass class TestOf(Doc2Tester): def __init__(self, parent, node): self.__dict__.update(parent.__dict__) self.parent = parent self.node = node kind, args = node.arg, node.children mod = self.mod = parent.mod self.Kan = mod.KanExtension self.Cat = mod.Cat self.args = args self.kind = kind self.coverage = None for node in args: t = node.tag if t == 'coverage': if self.coverage is not None: self.error('Duplicate coverage specifications', node, exception=None) else: try: coverage = int(node.arg.strip()) except ValueError: coverage = node.arg.strip() self.coverage = coverage else: self.error('Invalid element in %r.' % self.node.tag, node, exception=None) if self.coverage is None: self.coverage = 1 self.make_cat() def getattr_code(self, obj, attr): if self.mod.is_identifier(attr): return '%s.%s' % (obj, attr) else: return 'getattr(%s, %r)' % (obj, attr) def warn(self, message, node=None): self.error(message, node, exception=None, harmless=1) def make_cat(self): objects = [] arrows = {} relations = [] fa = {} fo = {} arg_counter = 1 ac = [1] eithertests = [] kinds = [] kindofname = {} ex_setup = [] ex_map = {} pc_checks = {} def add_kind(kind): name = kind.get_id_name() if name not in objects: objects.append(name) kinds.append(kind) kindofname[name] = kind return name def get_example_expr(a): if a in ex_map: return ex_map[a] x = self.parent.get_example_expr(a) usage = a.get_use_text(x) ex_map[a] = usage return usage def gen_atom_beam(asp): asptgt = asp.tgt tag = asptgt.d_tag if tag == 'attribute': attr = asptgt otherkinds = [] atkak = attr.get_atom_beams() for ab in atkak: a = ab.tgt if a.d_tag == 'mapping': op = asp + ab ret_kind = a.get_return_test_kind() tgt_name = add_kind(ret_kind) examples = a.get_args_examples(get_example_expr, kind) for args in examples: arrow_name = 'CALLATTR%d' % ac[0] ac[0] += 1 arrows[arrow_name] = (src_name, tgt_name) fa[arrow_name] = ('callattr', op, args) else: otherkinds.append(a) if otherkinds or not atkak: if len(otherkinds) != len(atkak): # make new atk somehow oth = [(x.get_id_name(), x) for x in otherkinds] oth.sort() otherkinds = [y for (x, y) in oth] atk = self.mod.Main.Kind() atk.d_tag = 'kind' atk.aspects = otherkinds atk.tgtfullname = '(%s)' % ( '&'.join([x.tgtfullname for x in otherkinds])) else: atk = attr.get_test_kind() arrow_name = '%s:%d' % (attr.get_id_name(), ac[0]) ac[0] += 1 tgt_name = add_kind(atk) assert arrow_name not in arrows arrows[arrow_name] = (src_name, tgt_name) fa[arrow_name] = ('getattr', attr.get_attr_name()) elif tag in ('operator', 'function_operator', 'inplace_operator', 'reverse_operator', 'mapping', 'setitem', 'delitem', 'getitem'): ret_kind = asp.get_return_test_kind() tgt_name = add_kind(ret_kind) examples = asp.get_args_examples(get_example_expr) for args in examples: arrow_name = 'OPERATOR%d' % ac[0] ac[0] += 1 arrows[arrow_name] = (src_name, tgt_name) fa[arrow_name] = (tag, asp, args) elif tag == 'either': asp_name = add_kind(asptgt) if asptgt is not kind: arrow_name = '(%s:%s:%d)' % (src_name, asp_name, ac[0]) ac[0] += 1 arrows[arrow_name] = (src_name, asp_name) fa[arrow_name] = ('subkind', asp_name) for i, ak in enumerate(asptgt.get_alt_kinds()): tgt_name = add_kind(ak) arrow_name = "(%s'%s)" % (asp_name, tgt_name) arrows[arrow_name] = (asp_name, tgt_name) fa[arrow_name] = ('superkind', i) else: assert 0 add_kind(self.kind) while kinds: kind = kinds.pop() src_name = kind.get_id_name() for asp in kind.get_atom_beams(): try: gen_atom_beam(asp) except self.mod.ReportedError: pass cat = self.Cat.oarcat(objects, arrows, relations) tester = self.Kan.category_tester( self.Cat.Functor(fo, fa, cat), coverage=self.coverage) def get_arrow_name(a): return ','.join(a) tester.get_arrow_name = get_arrow_name object_tester = tester.get_object_tester(self.kind.get_id_name()) icode = object_tester.get_intermediate_test_code() e_names = {} e_name_no = [0] def e_name_of(a): if not a: return 'arg' # return 'e[%r]'%a if a not in e_names: e_names[a] = 't%d' % e_name_no[0] e_name_no[0] += 1 return e_names[a] def call_fo(a, b): return 'fo[%r](%s)' % (a, e_name_of(b)) def assign_fa(append, tgt, func, src): tag = func[0] if tag == 'getattr': name = func[1] append('%s = %s' % (tgt, self.getattr_code(src, name))) elif tag in ('callattr', 'operator', 'inplace_operator', 'function_operator', 'reverse_operator', 'mapping', 'setitem', 'delitem', 'getitem'): op = func[1] opname = op.get_op_name() args = func[2] sus = args.get_setups_for_preconditions() if sus is not None: for su in sus: append('%s.%s(%s)' % (src, su.get_name(), su.get_args())) else: self.error('Could not find postcondition to satisfy precondition for %r.' % ( op.get_op_id_name()), exception=None) eqs = [] for eq in op.find_equations(): pres = eq.find_aspects('precondition') posts = eq.find_aspects('postcondition') # xxx late checking but will do for now I may relax it anyway if len(pres) != 1: if pres: node = pres[0].src.node else: node = eq.src.node self.error('Exactly one precondition currently allowed in equation.', node, exception=None) if len(posts) < 1: self.error('At least one postcondition currently required in equation.', eq.src.node, exception=None) if pres: pre = pres[0] ce = self.parent.get_condition_expr( pre, args, op, src, None) if ce is None: # This 'cant happen' anymore, checked here 'just in case'... raise SyntaxError('Undefined condition: %r' % pre) prename = 'pre_%d' % len(eqs) eqs.append((prename, posts)) append('%s = %s' % (prename, ce)) if tag == 'callattr': append('%s = %s(%s)' % (tgt, self.getattr_code(src, opname), args)) elif tag == 'operator': append('%s = %s %s %s' % (tgt, src, opname, args)) elif tag == 'inplace_operator': append('%s = %s' % (tgt, src)) append('%s %s %s' % (tgt, opname, args)) elif tag == 'reverse_operator': append('%s = %s %s %s' % (tgt, args, opname, src)) elif tag == 'function_operator': argstr = str(args) if argstr: argstr = ', ' + argstr append('%s = %s(%s%s)' % (tgt, opname, src, argstr)) elif tag == 'mapping': append('%s = %s(%s)' % (tgt, src, args)) elif tag == 'getitem': # Number of args >=1, has been checked. append('%s = %s[%s]' % (tgt, src, args)) elif tag == 'delitem': # Number of args >=1, has been checked. append('del %s[%s]' % (src, args)) elif tag == 'setitem': # Number of args >=2, has been checked. append('%s[%s] = %s' % (src, ', '.join(args.negs[:-1]), args.negs[-1])) else: assert 0 posts = args.get_postconditions() for po in posts: ce = self.parent.get_condition_expr(po, args, op, src, tgt) if ce is None: continue append('assert %s, %r' % ( ce, 'Failed postcondition: %r' % po.cond_expr, )) for (prename, posts) in eqs: for post in posts: ce = self.parent.get_condition_expr( post, args, op, src, tgt) if ce is None: # This 'cant happen' anymore, checked here 'just in case'... raise SyntaxError('Undefined condition: %r' % post) message = 'Failed postcondition equality: %r' % post append('assert %s == %s, %r' % ( prename, ce, message)) else: assert 0 pylines = [] class ArrowTree: def __init__(self, pre): self.pre = pre self.children = [] def __str__(self): if self.children: chdrn = ', chdrn = %s' % self.children else: chdrn = '' return 'AT(pre = %s%s)' % (self.pre, chdrn) __repr__ = __str__ ats = {} def at_of_pre(pre): at = ats.get(pre) if at is None: at = ArrowTree(pre) ats[pre] = at if pre: at_of_pre(pre[:-1]).children.append(at) return at def trav(t): subs = [] src = t.pre src_name = e_name_of(src) for ch in t.children: try: ar = ch.pre[-1] func = fa[ar] tgt = ch.pre tag = func[0] if tag == 'subkind': e_names[ch.pre] = src_name trav(ch) elif tag == 'superkind': subs.append((func, ch)) else: assign_fa(pylines.append, e_name_of( tgt), func, src_name) trav(ch) except self.mod.ReportedError: pass if subs: subs.sort() indents = 0 for func, ch in subs: e_names[ch.pre] = src_name pos = len(pylines) pylines.append('try:') pylines.append('<INDENT>') trav(ch) if pos+2 == len(pylines): pylines.pop() pylines.pop() else: indents += 1 pylines.append('<DEDENT>') pylines.append('except:') pylines.append('<INDENT>') if indents: pylines.append('raise') pylines.extend(['<DEDENT>']*indents) alla = object_tester.get_all_arrows() init = at_of_pre(()) for a in alla: for i in range(1, len(a)+1): at_of_pre(a[:i]) trav(init) if not pylines: self.warn('No tests generated for %r.' % self.kind.tgtfullname) pylines = ['pass'] ap = self.parent.ap name = self.parent.get_test_name(self.kind) test_name = 'test_%s' % name ap('def %s(self, arg):' % test_name, '<NL>', '<INDENT>') for line in ex_setup + pylines: ap(line) if line not in ('<INDENT>', '<DEDENT>'): ap('<NL>') ap('<DEDENT>') ap('tests[%r] = %s' % (self.kind.tgtfullname, test_name), '<NL>') class _GLUECLAMP_: _imports_ = ( '_parent:SpecNodes', '_parent.SpecNodes:node_of_taci', '_parent:Main', '_parent.Main:ReportedError', '_root.io:StringIO', '_root.sys:stdout', '_root:sys', '_root.traceback:format_exception', '_root.guppy.etc:KanExtension', '_root.guppy.etc:Cat', '_root:re', '_root:time', ) # Reserved words found in Grammar of Python 2.3.3 # Is there a list somewhere in some std lib? reserved_words = ( 'and', 'assert', 'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except', 'exec', 'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 'not', 'or', 'pass', 'print', 'raise', 'return', 'try', 'while', 'yield', ) def _get_is_identifier(self): m = self.re.compile('[_a-zA-Z][_a-zA-Z0-9]*').match rwd = dict([(rw, 1) for rw in self.reserved_words]) return lambda x: m(x) and x not in rwd def doc2text(self, doc, node): d2h = Doc2Tester(self, doc, node) return d2h.get_tester() def doc2filer(self, doc, node, name, dir, opts, IO): text = self.doc2text(doc, node) path = IO.path.join(dir, '%s.py' % name) node = self.node_of_taci('write_file', path, [ self.node_of_taci('text', text)]) return node