%PDF- %PDF-
Direktori : /opt/alt/python37/lib64/python3.7/site-packages/guppy/heapy/ |
Current File : //opt/alt/python37/lib64/python3.7/site-packages/guppy/heapy/Spec.py |
""" Contains some experimental set constructions. In the current state, not to be used by the faint-hearted. It is likely due for some major refactoring and has probably many bugs, it was a long time since I run the tests. You don't get any other documentation than this right now. """ DEBUG = 1 def briefstr(x): try: return getattr(x, 'brief') except AttributeError: if isinstance(x, tuple): return '(%s)' % (','.join([briefstr(xi) for xi in x])) return str(x) class SpecFamily: def __init__(self, unisetmod, specmod): self.specmod = specmod self.defrefining(unisetmod.Anything) self.disjoints -= [self] def __call__(self, arg): return self.Set(self, arg) def c_and(self, a, b): if isinstance(b, SpecFamily): return self.mod.fam_And._cons((a, b)) else: return b.fam._and_ATOM(b, a) def _and_ID(self, a, b): env = self.specmod._static_test_env res = self.mod.mutnodeset() for bi in b.nodes: try: env.test_contains(a, bi, 'select contains') except Exception: # TestError pass else: res.add(bi) return self.mod.fam_Identity._cons(self.mod.immnodeset(res)) def c_contains(self, a, b): env = self.specmod._static_test_env try: return env.test_contains(a, b, 'Spec contains') except TestError: return False def c_getlimstr(self, a, max_len): x = a.brief if len(x) > max_len: x = x[:max_len-3]+'...' return x def c_get_brief(self, a): return '<%s(%s)>' % (self.__class__.__name__, briefstr(a.arg)) class ArgNamesFamily(SpecFamily): def __call__(self, *args): return self.Set(self, args) def getargnames(self, code): inspect = self.specmod._root.inspect (args, varargs, varkw) = inspect.getargs(code) if varargs is not None: args.append('*%s' % varargs) if varkw is not None: args.append('**%s' % varkw) return tuple(args) def func_argnames(self, f, args): try: code = f.__code__ return self.getargnames(code) == args except AttributeError: return False def meth_argnames(self, m, args): try: f = m.__func__ code = f.__code__ return self.getargnames(code)[1:] == args except AttributeError: return False def c_contains(self, a, x): def func_argnames(f): return self.func_argnames(f, a.arg) def meth_argnames(m): return self.meth_argnames(m, a.arg) types = self.mod._root.types return (func_argnames(x) or meth_argnames(x) or (isinstance(x, type) and (hasattr(x, '__init__') and meth_argnames(x.__init__))) or (isinstance(x, type) and (hasattr(x, '__init__') and meth_argnames(x.__init__))) or (hasattr(x, '__call__') and meth_argnames(x.__call__)) ) class AttributeFamily(SpecFamily): def __call__(self, name, type=None): if type is None: type = self.specmod.any else: if not isinstance(type, self.mod.UniSet): type = self.c_from(type) return self.specotup((name, type)) def c_test_contains(self, a, b, env): name, type = a.arg x = env.gengetattr(b, name) return type.test_contains(x, env) def c_get_brieflimstr(self, a): x = '<AttributeFamily(%r%%s>' % (a.arg[0],) if a.arg[1] is not None: x = x % (','+a.arg[1].brief) else: x = x % '' return x class AdaptupleFamily(SpecFamily): def __init__(self, *a, **k): SpecFamily.__init__(self, *a, **k) self.add_export('new', lambda x: x.arg[0]) def __call__(self, func, type): func, doc = self.specmod._exodoc(func) type = self.specmod.setcast(type) return self.specoargtup((func, type), (doc, type)) def c_test_contains(self, a, b, env): func, type = a.arg if isinstance(b, tuple): try: x = func(*b) except Exception: return env.failed_exc_info('calling func failed') else: x = b return type.test_contains(x, env) class CartesianProductFamily(SpecFamily): def __call__(self, *types): return self.Set(self, types) def c_domain(self, a): types = a.arg if len(types) == 2: return types[0] raise TypeError('Domain is defined on binary relations only') def c_get_examples(self, a, env): # We have to check length before calling iterpermute - # to give a reasonable error message examples are missing from some set. exs = [] for i, ai in enumerate(a.arg): ex = list(env.get_examples(ai)) if not ex: # ??? if not env.failed_coverage('cartesian product', ai, None, 'the argument #%d' % i): return [] exs.append(ex) return self.mod._root.guppy.etc.iterpermute(*exs) def c_len(self, a): l = 1 for ai in a.arg: l = l * len(ai.arg) return l def c_test_contains(self, a, b, env): types = a.arg bs = tuple(b) if len(types) != len(bs): env.failed('cprod of length %d: argument has length %d' % (len(types), len(bs))) else: for t, b in zip(types, bs): if not t.test_contains(b, env): return False return True class SequenceFamily(SpecFamily): def __call__(self, type): return self.specoarg(type) def c_test_contains(self, a, b, env): for x in b: if not a.arg.test_contains(x, env): return False return True def c_get_examples(self, a, env): for i in range(env.max_sequence_examples_length): for x in env.get_examples(self.specmod.cprod(*[a.arg]*i)): yield x class MappingFamily(SpecFamily): def __init__(self, *a, **k): SpecFamily.__init__(self, *a, **k) self.add_export('arrow', lambda x: lambda f: self.c_arrow(x, f)) def c_arrow(self, a, f): tf, ts, ret = a.arg return Arrow(ts, ret, f) def __call__(self, *args): ts = [] as_ = [] ret = None i = 0 setcast = self.specmod.setcast while i < len(args): ai = args[i] if isinstance(ai, str): if ai == '->': i += 1 if not i == len(args)-1: raise SyntaxError( "The '->' specifier must be next to last in the argument list") ret = setcast(args[i]) elif ai.endswith('='): i += 1 t = setcast(args[i]) as_.append('%s=%args[%d]' % (ai[:-1], len(ts))) ts.append(t) elif ai == '*': i += 1 t = setcast(args[i]) as_.append('*args[%d]' % len(ts)) ts.append(self.specmod.sequence(t)) else: raise SyntaxError("Invalid argument specifier: %r" % ai) else: as_.append('args[%d]' % len(ts)) ts.append(setcast(ai)) i += 1 fn = 'lambda f: lambda *args: f('+','.join(as_)+')' f = eval(fn) ts = self.specmod.cprod(*ts) if ret is None: ret = self.specmod.Anything return self.Set(self, (f, ts, ret)) def c_test_contains(self, a, func, env): f, ts, ret = a.arg f = f(func) def g(env, args): try: r = f(*args) except Exception: # TypeError, ValueError, AttributeError ... - what not raise #env.failed('Call exception') else: if ret is not None: return env.test_contains(ret, r, "Mapping Return Type") else: return True return env.forall(ts, g) def c_get_examples(self, a, env): f, ts, ret = a.arg return [lambda *args, **kwds: x for x in env.get_examples(ret)] class PredicateFamily(SpecFamily): def __call__(self, arg, doc): return self.Set(self, (arg, doc)) def c_test_contains(self, a, b, env): pred, doc = a.arg if not pred(env, b): return env.failed('pred: doc = %r; failed for element == %s' % (doc, env.name(b))) return True class PowersetFamily(SpecFamily): def __init__(self, *args): SpecFamily.__init__(self, *args) self.add_export('union', lambda x: x.arg) def __call__(self, set): return self.specoarg(set) def c_get_examples(self, a, env): x = [self.specmod.Nothing, a.arg] try: y = env.get_examples(a.arg) except Exception: # xxx complain? We can always generate 2 examples.. return x # xxx should we make all permutations?.. return x def c_test_contains(self, a, b, env): if not b in self.specmod.set: env.failed('powerset.test_contains: not a set: %s' % self.specmod.iso(b)) set = a.arg return env.forall(b, lambda env, x: env.test_contains(set, x, 'powerset'), 'powerset') class DocFamily(SpecFamily): def __call__(self, doc, type=None): if type is None: type = self.specmod.UniSet.NotNothing else: if not type in self.specmod.set: type = self.specmod.UniSet.convert(type) return self.Set(self, (doc, type)) def c_test_contains(self, a, b, env): doc, type = a.arg return type.test_contains(b, env) class RelOpFamily(SpecFamily): def __init__(self, *a, **k): SpecFamily.__init__(self, *a, **k) self.add_export('domain', lambda x: x.arg[0]) self.add_export('range', lambda x: x.arg[2]) # The memo dict keeps relops with the same domain, op, and range. # Primarily introduced to make equality work with default mechanism, # since different compiled func's compared differently even with # the same source. self.memo = {} def __call__(self, domain, op, range=None): domain = self.specmod.setcast(domain) if range is None: range = domain else: range = self.specmod.setcast(range) x = self.memo.get((domain, op, range)) if x is None: if op in ('<', '<=', '==', '!=', '>', '>=', 'in', 'not in', 'is', 'is not'): func = eval('lambda x,y: x %s y' % op) func.name = op else: func = op func.name = func.__name__ x = self.Set(self, (domain, func, range)) self.memo[(domain, op, range)] = x return x def c_get_examples(self, a, env): # We have to check length before calling iterpermute - # to give a reasonable error message examples are missing from some set. dom = list(env.get_examples(a.domain)) if not dom: failed_coverage('relation', a.domain, None, 'domain') return [] ran = list(env.get_examples(a.range)) if not ran: failed_coverage('relation', a.range, None, 'range') return [] exs = [] for ex in self.specmod._root.guppy.etc.iterpermute(dom, ran): if env.contains(a, ex): exs.append(ex) return exs def c_test_contains(self, a, b, env): d, op, r = a.arg if not op(*b): return env.failed() return True class EqualsFamily(SpecFamily): def __call__(self, *args): if not args: return self.specmod.Nothing return self.specotup(args) def c_test_contains(self, a, b, env): if b in a.arg: return True return env.failed('equals') def c_get_examples(self, a, env): return a.arg class ExampleFamily(SpecFamily): def __call__(self, set, *examples): return self.Set(self, (set, examples)) def c_test_contains(self, a, b, env): set, examples = a.arg return set.test_contains(b, env) def c_get_examples(self, a, env): set, examples = a.arg # for e in examples: env.test_contains(set, e, 'ExampleFamily.c_get_examples') return examples class SynonymsFamily(SpecFamily): def __call__(self, *names): return self.Set(self, names) def c_test_contains(self, a, b, env): names = a.arg ms = self.specmod.UniSet.mutnodeset() for name in names: x = env.getattr(b, name) ms.add(x) if not len(ms): env.failed('Synonyms: no such names: %r' % names) if len(ms) > 1: env.failed('Synonyms: %d different nodes for names: %r' % (len(ms), names)) return True class InstanceFamily(SpecFamily): def c_test_contains(self, a, b, env): if not isinstance(b, a.arg): env.failed('InstanceFamily: %s is not an instance of %s' % ( self.specmod.iso(b), a.arg)) return True def c_get_examples(self, a, env): return env.get_examples(self.specmod.setcast(a.arg)) def _and_ID(self, a, b): return self.mod.fam_Identity(*[bi for bi in b.nodes if isinstance(bi, a.arg)]) class ExpressionPredicateFamily(SpecFamily): def __call__(self, names, expression): func = None return self.Set(self, (names, expression, func)) def c_test_contains(self, a, b, env): names, expression, func = a.arg func = eval('lambda %s:%s' % (','.join(names), expression)) d = {} for name in names: x = env.getattr(b, name) d[name] = x x = func(**d) if not x: env.failed('False expression: %s' % expression) return True class ExpressionSetFamily(SpecFamily): def __call__(self, expression, *names): func = None return self.Set(self, (names, expression, func)) def c_test_contains(self, a, b, env): names, expression, func = a.arg func = self.specmod.eval('lambda %s:(%s)' % ( ','.join(('LE',)+tuple(names)), expression)) d = {'LE': env.LE} for name in names: x = env.getattr(b, name) d[name] = x x = func(**d) return env.test_contains(x, b, 'expset(%s, %s)' % (expression, ','.join(names))) class MatchesFamily(SpecFamily): def __init__(self, *a, **k): SpecFamily.__init__(self, *a, **k) self.sre = self.specmod._root.sre def __call__(self, regexp): return self.specoargtup(self.sre.compile(regexp), (regexp,)) def c_test_contains(self, a, b, env): regexpobj = a.arg m = self.sre.match(regexpobj, b) if m is None: return env.failed('Did not match') return True class RecurSelfFamily(SpecFamily): def __init__(self, *a, **k): SpecFamily.__init__(self, *a, **k) class RecurSpec(self.Set): __slots__ = 'func', 'recursion_level', 'recursion_limit' self.RecurSpec = RecurSpec def __call__(self, expr, recursion_limit=10): s = self.RecurSpec(self, expr) s.recursion_limit = recursion_limit s.recursion_level = 0 return s def c_test_contains(self, a, b, env): try: func = a.func except AttributeError: expr = a.arg func = a.func = env.eval('lambda self:%s' % expr) s = func(self.specmod.Nothing) try: tf = env.test_contains(s, b, 'recur with Nothing, ok to fail') if not tf: raise TestError except Exception: # TestError: eg for match, we got a TypeError.. s = func(a) rl = a.recursion_level try: if rl >= a.recursion_limit: return env.failed('recurself: recursion_level = %s' % a.recursion_limit) else: a.recursion_level = rl + 1 tf = env.test_contains(s, b, 'recur') finally: a.recursion_level = rl return tf class Dummy: pass class TupleformFamily(SpecFamily): def __call__(self, form, set): return self.specotup((form, set)) def c_test_contains(self, a, b, env): form, set = a.arg bt = tuple(b) if len(bt) != len(form): return env.failed('tupleform: wrong length: got %d expected %d' % (len(bt), len(form))) ob = Dummy() for name, val in zip(form, bt): setattr(ob, name, val) return env.test_contains(set, ob, 'tupleform') class Arrow: def __init__(self, category, source, target): self.category = category self.source = source self.target = target def of(self, other): # compose self <-- other # (Standard composition order) other = self.category.validate(other) return self.category.compose(self, other) def to(self, other): # compose self --> other # (Nonstandard composition order; sometimes seems more natural) other = self.category.validate(other) return self.category.compose(other, self) class IdentityArrow(Arrow): def __init__(self, category, object): Arrow.__init__(self, category, object, object) def __call__(self, x): return x class FunctionArrow(Arrow): def __init__(self, category, source, target, function): Arrow.__init__(self, category, source, target) self.__call__ = function class RepresentationCategory: _derive_origin_ = None _origin_ = None def __init__(self, mod, spec): fam = mod.family(RepresentationObjectFamily) fam.init2(self, spec) self._fam = fam def __eq__(self, other): return self is other def __hash__(self): return hash(id(self)) def __getattr__(self, name): r = self._fam.getobject(name) self.__dict__[name] = r return r class RepresentationObjectFamily(SpecFamily): def init2(self, cat, spec): self.cat = cat self.objects = {} self.specs = {} self.arrows = {} self.add_export('fromuniversal', self.fromuniversal) Set = self.Set class RepresentationObject(Set): __slots__ = 'to', 'from' self.Set = RepresentationObject class RepresentationCategorySpec(spec): def __init__(self, fam): self._fam = fam self._cat = fam.cat def __getattr__(self, name): if hasattr(self.__class__, '_get_%s' % name): r = getattr(self, '_get_%s' % name)(self._fam.specmod) self.__dict__[name] = r return r raise AttributeError(name) self.spec = RepresentationCategorySpec(self) def getarrow(self, dom, cod): dc = (dom, cod) if dc in self.arrows: return self.arrows[dc] raise SpecError def getobject(self, name): if name in self.objects: return self.objects[name] normname = self.normoname(name) if normname in self.objects: self.objects[name] = self.objects[normname] return self.objects[normname] o = self(normname) self.objects[normname] = self.objects[name] = o return o raise SpecError('No such object: %r' % name) def getspec(self, obj): name = obj.arg if name in self.specs: return self.specs[name] gs = getattr(self.spec, '_get_spec_%s' % name, None) if gs is not None: sp = gs(self.specmod) self.specs[name] = sp return sp raise SpecError('getspec: No spec of %r' % name) def fromuniversal(self, target): # Find a most general arrow into 'target' # 1. Find all predefined arrows to target # 2. Make a category sum of the set of sources S of all such arrows # 3. Make a specification-set P for this sum, which is that: # a. The element should be isomorphic to a tuple (O, A) where # b. O, the tag, should be an object in S # c. A, the value, should be an element in O # Return an arrow taking this object to target. # # Arrows thus created are memoized. name = target.arg arrowname = '%s.fromuniversal' % name if arrowname in self.arrows: return self.arrows[arrowname] S = {} S[name] = IdentityArrow(self.cat, target) for an in dir(self.spec): if not (an.startswith('map_') and '_to_' in an): continue s, t = an.split('_to_') s = s[4:] if t == name: f = getattr(self.spec, an) S[s] = FunctionArrow(self.cat, getattr(self.cat, s), target, lambda x: f(self.specmod, x)) def p(env, e): try: O, A = e except Exception: return env.failed('Not a sequence with length 2') fam = getattr(O, 'fam', None) if fam is not self: return env.failed('Tag is not an object of this family') name_ = getattr(O, 'arg', None) if name_ not in S: return env.failed('Object is not a source of this target') return env.test_contains(O, A, 'Value is not an element of this object') uniname = '%s.universal' % name P = self.specmod.predicate(p, 'Specification-set for %r' % uniname) self.specs[uniname] = P source = self(uniname) class AlphaSum(Arrow): def __init__(self, category, source, target, S): Arrow.__init__(self, category, source, target) self._S = S def __getitem__(self, x): # Don't know what to call this unique arrow return self._S[self.source.fam.normoname(x)] def __call__(self, xxx_todo_changeme): (O, E) = xxx_todo_changeme return self[O.arg](E) arrow = AlphaSum(self.cat, source, target, S) self.arrows[arrowname] = arrow return arrow def normoname(self, on): isos = getattr(self.spec, '_isos_', None) if isos is not None: for l in self.spec._isos_: nn = None for n in l: if n.isdigit(): nn = n if n == on: if nn is not None: return nn raise SpecError( 'No numeric object name corresponding to %r' % on) return on def __call__(self, name): r = self.specoarg(name) class To: __slots__ = 'source', def __init__(self, source): self.source = source def __call__(self, target): return self.source.fam.getarrow(self.source, target) def __getattr__(self, name): source = self.source fam = source.fam target = fam.getobject(name) return fam.getarrow(source, target) r.to = To(r) return r def c_test_contains(self, a, b, env): set = self.getspec(a) return env.test_contains(set, b, 'RepresentationObjectFamily: not in object specification') def c_get_examples(self, a, env): set = self.getspec(a) return env.get_examples(set) class AbstractSetFamily(SpecFamily): def __init__(self, *a, **k): SpecFamily.__init__(self, *a, **k) class AbstractSet(self.Set): __slots__ = '_memo', def __init__(self, fam, arg): self.fam = fam self.arg = arg self._origin_ = None self._memo = {} self.Set = AbstractSet def __call__(self, arrow, set): r = self.specotup((arrow, set)) r._memo = {} return r def c_and(self, a, b): if b.fam is self: aa, sa = a.arg ab, sb = b.arg if aa is ab: return self(aa, sa & sb) return b.fam._rand_ATOM(b, a) def c_getattr2(self, a, b): if b in a._memo: return a._memo[b] arrow, set = a.arg pararrow = arrow[b] srcset = pararrow.source def p(env, x): t = env.test_contains( srcset, x, 'AbstractSet: not in arrow.source') if t: e = pararrow(x) t = env.test_contains( set, e, 'AbstractSet: not in argument set') return t return env.contains(set, y) s = self.specmod.predicate(p, 'Abstract set attribute: %r' % b) # ... a._memo[b] = s return s def c_test_contains(self, a, b, env): arrow, set = a.arg t = env.test_contains( arrow.source, b, 'AbstractSet: not in arrow.source') if t: e = arrow(b) t = env.test_contains(set, e, 'AbstractSet: not in argument set') return t class ElemFamily(SpecFamily): def __call__(self, func): return self.specoarg(func) def c_test_contains(self, a, b, env): func = a.arg s = func(b) return env.test_contains(s, b, 'ElemFamily') class IntersectionFamily(SpecFamily): def __call__(self, domain, function): return self.specotup((domain, function)) def c_test_contains(self, a, b, env): domain, function = a.arg return env.forall(domain, lambda env, x: env.test_contains(function(x), b, 'Intersection')) class SpecError(Exception): pass class TestError(Exception): pass class CoverageError(Exception): pass class LocalEnv: _derive_origin_ = 'ADD' def __init__(self, mod, spec, nodoc=1): self._mod = mod self._spec = spec self._origin_ = None self.nodoc = nodoc def __getattr__(self, attribute_name): mod = self._mod f = getattr(self._spec, attribute_name) d = self._mod._load_names( mod._root.guppy.etc.Code.co_findloadednames(f.__code__)) nf = mod._root.types.FunctionType( f.__code__, d, f.__name__, f.__defaults__, f.__closure__) r = nf(()) self.__dict__[attribute_name] = r return r class TestEnv: _derive_origin_ = 'ADD' iscomplete = False issilent = False # ie. (), cprod(x) cprod(x, y) are yielded by default max_sequence_examples_length = 2 TestError = TestError def __init__(self, mod, Spec): self.mod = mod self.messages = [] self.examples = {} if Spec is not None: self.spec = spec = Spec() try: lex = spec.LocalEnvExpr except AttributeError: lex = '' LE = LocalEnv(mod, lex) LE._OBJ_ = mod self.LE = LE self.topspec = self.eval(spec.GlueTypeExpr) def eval(self, expr): mod = self.mod types = mod._root.types if isinstance(expr, (str,)): func = self.mod.eval('lambda LE:(\n%s\n)' % expr) return func(self.LE) ls = [] selfset = None names = list(expr.__dict__.keys()) names.sort() for name in names: f = getattr(expr, name) try: co = f.__code__ except AttributeError: continue if co.co_varnames[:co.co_argcount] == ('IN',): d = mod._load_names( mod._root.guppy.etc.Code.co_findloadednames(co)) #d = mod._load_names() nf = mod._root.types.FunctionType( f.__code__, d, f.__name__, f.__defaults__, f.__closure__) s = nf(()) if name == '_SELF_': selfset = s else: ls.append(mod.attr(name, s)) else: raise SpecError('TestEnv.eval: invalid argument mode') # Constructing an AND in one sweep = faster # We assume they are not disjoint - which # would be determined by testing that we are going to do # (We know they are all attr's of different names here) # Except that selfset may perhaps be disjoint; but why care here # if selfset is not None: ls.append(selfset) # Alternatively: r = r & selfset afterwards, # but could be unnecessarily slow r = mod.UniSet.fam_And._cons(ls) return r def get_examples(self, collection): try: it = iter(collection) except TypeError: try: ex = self.examples[collection] except KeyError: if isinstance(collection, self.mod.UniSet.UniSet): ex = collection.get_examples(self) else: ex = list(collection) it = iter(ex) return it def getattr(self, obj, name): if '.' in name: x = obj for subname in name.split('.'): try: x = getattr(x, subname) except Exception: return self.failed('getattr: %s has no attribute %r' % (self.name(obj), name) + ',\nbecause %s has no attribute %r' % (self.name(x), subname)) else: try: x = getattr(obj, name) except Exception: if DEBUG: raise return self.failed('attr: %s has no attribute %r' % (self.name(obj), name)) return x def gengetattr(self, obj, name_or_tuple): if isinstance(name_or_tuple, str): return self.getattr(obj, name_or_tuple) elif isinstance(name_or_tuple, tuple): if len(name_or_tuple) == 2 and name_or_tuple[0] is self.mod.quote: return name_or_tuple[1] else: return tuple([self.gengetattr(obj, nt) for nt in name_or_tuple]) else: raise TypeError('gengetattr: I am picky, required string or tuple') def log(self, message): self.messages.append(message) def name(self, obj): if isinstance(obj, self.mod.UniSet.UniSet): return str(obj) else: return '%s' % self.mod.iso(obj) def name_coll(self, collection): return '%s' % collection def test(self, obj): self.get_obj_examples(obj) try: self.test_contains(self.topspec, obj, 'Top spec') except Exception: tvt = self.mod._root.sys.exc_info() self.dump_failure(tvt) def get_obj_examples(self, obj): ex = self.spec.GetExamples(self, obj) for e in ex: vs = e[1:] e = e[0] s = self.examples.setdefault(e, []) for v in vs: s.append(v) self.test_contains(e, v, 'testing example of set') def dump_failure(self, xxx_todo_changeme3, noraise=0): (type, value, traceback) = xxx_todo_changeme3 list = [] tb = traceback while tb is not None: f = tb.tb_frame if f.f_code is self.test_contains.__func__.__code__: list.append(f) tb = tb.tb_next for f in list: lo = f.f_locals print('a = %r' % (lo['a'],)) print('b = %r' % (lo['b'],)) print('message = ', lo['message']) print('-----') if noraise: self.mod._root.traceback.print_exception(type, value, traceback) else: raise def contains(self, a, b): try: x = self.test_contains(a, b, 'contains') except CoverageError: raise except Exception: return False return x def test_contains(self, a, b, message): return a.test_contains(b, self) def test_contains_not(self, a, b, message): try: a.test_contains(b, self) except CoverageError: raise except Exception: # TestError: # well we axcept anything.. ok? return True else: return self.failed('test_contains_not, from: %s' % message) def failed(self, message=''): if not self.issilent: self.log('Failed:' + message) raise TestError(message) return False def failed_coverage(self, forwhat, collection, func, message): if collection is self.mod.Nothing: return True raise CoverageError('%s: no examples for collection = %s, message: %s' % ( forwhat, collection, message)) def failed_exc_info(self, message): exc_info = self.mod._root.sys.exc_info() type, value, traceback = exc_info if not self.issilent: self.log('Failed:' + message) raise type(value) return False def forall(self, collection, func, message=''): ex = self.get_examples(collection) n = 0 for e in ex: if not func(self, e): return self.failed('forall: e = %s, from: %s' % (self.name(e), message)) n += 1 if not n: try: a = len(collection) if a > 0: raise CoverageError # Otherwise ok, it was really an Nothing collection. except Exception: self.failed_coverage('forall', collection, func, message) return True def forall_pairs(self, collection, func, message=''): as_ = self.get_examples(collection) n = 0 for a in as_: for b in self.get_examples(collection): if not func(self, a, b): self.failed('forall_pairs: a = %s, b = %s, from: %s' % ( self.name(a), self.name(b), message)) n += 1 if not n: self.failed_coverage('forall_pairs', collection, func, message) return True def forall_triples(self, collection, func, message=''): as_ = self.get_examples(collection) n = 0 for a in as_: for b in self.get_examples(collection): for c in self.get_examples(collection): if not func(self, a, b, c): self.failed('forall_triples: a = %s, b = %s, c=%s, from: %s' % ( self.name(a), self.name(b), self.name(c), message)) n += 1 if not n: self.failed_coverage('forall_triples', collection, func, message) return True def forsome(self, collection, func, message=''): failures = [] for i, x in enumerate(collection): try: b = func(x) except Exception: # TestError: failures.append((i, self.mod._root.sys.exc_info())) continue if b: return True for (i, tvt) in failures: print('forsome: exception at collection[%d]:' % i) self.dump_failure(tvt, noraise=1) self.failed(message) class _GLUECLAMP_: _chgable_ = '_loaded', _nowrap_ = ('_origin_', 'Doc', 'family', 'eval', 'setcast', 'compile', 'wrap_source_string', '_load_names', 'iso') _preload_ = '_hiding_tag_', # 'imports' _imports_ = ( '_parent:Use', '_parent.Use:iso', '_parent.Use:Nothing', ) def _get_UniSet(self): return self._parent.UniSet def _get_Doc(self): return self._parent.Doc def _get_View(self): return self._parent.View # def _get__origin_(self): return self.Doc.attribute(self.Doc.root, 'guppy.heapy.Spec') def _wrapattr_(self, obj, name): Doc = self.Doc if name == 'setof': pass try: obj = Doc.wrap(obj, Doc.attribute(self._origin_, name)) except Doc.DocError: __import__('traceback').print_exc() print('no wrap:', name) return obj def _get_abstractset(self): return self.family(AbstractSetFamily) def _get_adaptuple(self): return self.family(AdaptupleFamily) def _get_any(self): return ~self.Nothing def _get_argnames(self): return self.family(ArgNamesFamily) def _get_attr(self): return self.family(AttributeFamily) def attrs(self, names, type=None): x = self.any for n in names: x &= self.attr(n, type) return x def _get_boolean(self): def p(env, x): try: if x: pass except Exception: env.failed("boolean: 'if x' raised an exception") return True return self.predicate(p, 'boolean') def _get_callable(self): return self.predicate(lambda env, x: callable(x), 'callable') def _get_compile(self): token = self._root.token parser = self._root.parser symbol = self._root.symbol def mapchildren_id(node, f): return node def mapchildren_default(node, f): return [node[0]] + [f(n) for n in node[1:]] mapchildren_dispatch = dict( [(value, mapchildren_id) for value in range(token.N_TOKENS)]) mapchildren_dispatch.update(dict([(value, mapchildren_default) for value, name in list(symbol.sym_name.items())])) def mapchildren(node, f): return mapchildren_dispatch[node[0]](node, f) def visitor(C): d = mapchildren_dispatch.copy() for value, name in list(symbol.sym_name.items()): if hasattr(C, name): d[value] = getattr(C, name).__func__ def _visit(node): return d[node[0]](node, _visit) return _visit def recover_source_node(node, l): for n in node[1:]: recover_source_dispatch[n[0]](n, l) def recover_source_token(node, l): if l and l[-1] != '(': l.append(' ') l.append(node[1]) def recover_source_name(node, l): if l and l[-1] not in ('.', '('): l.append(' ') l.append(node[1]) def recover_source_tight_left(node, l): l.append(node[1]) def recover_source_lpar(node, l): if l and not (l[-1][-1:].isalnum() or l[-1] == '('): l.append(' ') l.append(node[1]) recover_source_dispatch = dict([(value, recover_source_node) for value, name in list(symbol.sym_name.items())]) recover_source_dispatch.update( dict([(value, recover_source_token) for value in range(token.N_TOKENS)])) recover_source_dispatch[token.NAME] = recover_source_name for tok in ('RPAR', 'LSQB', 'RSQB', 'COLON', 'COMMA', 'SEMI', 'DOT', 'LBRACE', 'RBRACE'): recover_source_dispatch[getattr( token, tok)] = recover_source_tight_left recover_source_dispatch[token.LPAR] = recover_source_lpar def recover_source(node): l = [] recover_source_dispatch[node[0]](node, l) return ''.join(l) class wrap_lambdef: def test(node, f): # and_test ('or' and_test)* | lambdef if len(node) == 2 and node[1][0] == symbol.lambdef: lsource = recover_source(node[1]) lnode = mapchildren(node[1], f) return ( 292, (293, (294, (295, (297, (298, (299, (300, (301, (302, (303, (304, (305, (1, 'wrap_source_string')), (308, (7, '('), (317, (318, (292, lnode)), (12, ','), (318, (292, (293, (294, (295, (297, (298, (299, (300, (301, (302, (303, (304, (305, (3, '%r' % lsource )))))))))))))))), (8, ')')))))))))))))) return mapchildren(node, f) wrap_lambdef = visitor(wrap_lambdef) def compile_(source, filename, mode, *args): if mode != 'spec': return compile(source, filename, mode, *args) ast = parser.expr(source) node = parser.ast2tuple(ast, line_info=1) node = mapchildren(node, wrap_lambdef) ast = parser.tuple2ast(node) co = parser.compileast(ast) return co return compile_ def _get_cprod(self): return self.family(CartesianProductFamily) def dictof(self, set=None): return self.UniSet.byclodo.dictof(set) def _get_doc(self): return self.family(DocFamily) def docof(self, set): doc = (set.doc % self._origin_).shortest() do = str(doc) print(do) return do def eval(self, expr, init=None, nodoc=0): if nodoc: mode = 'eval' else: mode = 'spec' co = self.compile(expr, '', mode) d = self._load_names(self._root.guppy.etc.Code.co_findloadednames(co)) if init is not None: d = d.copy() exec(init, d) return eval(co, d) def _get_all_names(self): names = {'_root': 1} for x in _GLUECLAMP_.__dict__: if x.startswith('_get_'): x = x[5:] names[x] = 1 return names def _load_names(self, names=None): if names is None: if '_loaded' not in self.__dict__: for x in self.all_names: getattr(self, x) self._loaded = 1 else: all = self.all_names for name in names: if name in all: getattr(self, name) d = self.__dict__ d['__builtins__'] = self._load_names.__globals__['__builtins__'] return d def _get_eg(self): return self.family(ExampleFamily) def _get_elem(self): return self.family(ElemFamily) def _exodoc(self, expr): if expr in self.LE.string: r = self.eval(expr) return r, self.Doc.anon(expr) elif (expr in self.Type.Function and expr.__code__.co_name == '<lambda>' and expr.__code__.co_filename.startswith('<!SPECEVAL!>')): fn = expr.__code__.co_filename lines = fn.split('\n') lnum = expr.__code__.co_firstlineno inspect = self._root.inspect print(lines[lnum:]) block = inspect.getblock(lines[lnum:]) source = '\n'.join(block) return expr, self.Doc.getdoc(source) else: return expr, self.Doc.getdoc(expr) def _get_expred(self): return self.family(ExpressionPredicateFamily) def _get_expression(self): def p(env, x): try: eval('lambda : %s' % x) except SyntaxError: env.failed('Not a valid expression: %r' % x) return True return self.predicate(p, 'expression') def _get_expset(self): return self.family(ExpressionSetFamily) def _get_equals(self): return self.family(EqualsFamily) def family(self, fam, *args, **kwds): return self.UniSet.fam_mixin_argatom(fam, self, *args, **kwds) def _get__hiding_tag_(self): return self.UniSet._hiding_tag_ def _get_instance(self): return self.family(InstanceFamily) def _get_intersection(self): return self.family(IntersectionFamily) def _get_LE(self): return LocalEnv(self, self._Specification_.LocalEnvExpr) def _get_SPLE(self): return self.LE def _get_mapping(self): return self.family(MappingFamily) def _get_matches(self): return self.family(MatchesFamily) def mkTestEnv(self, Spec): return TestEnv(self, Spec) def newtype(self, name): return self.predicate(lambda e, x: 1, name) # xxx new family? def _get_nothing(self): return self.Use.Nothing def partition(self, set): return self.doc('partition', self.union_equals(set) & self.LE.nonempty & self.set_of_disjoint_sets ) def _get_predicate(self): return self.family(PredicateFamily) def _get_powerset(self): return self.family(PowersetFamily) def _get_Anything(self): return self.UniSet.Anything def _get_quote(self): return [] def _get_recurself(self): return self.family(RecurSelfFamily) def _get_relation(self): # relation is a representation category # We have the following representation objects: # 1. set of pairs with attribute dom, cod # 2. set of pairs with dom is cod # 3. fuop = func | op, string in ('==',..) # 4. (A, fuop), where A is a set # 5. (A, fuop, B), where A and B are sets # # A final object is 1. class RelationSpec: _isos_ = [ ('1', 'paxb'), ('2', 'paxa'), ('3', 'defiop', 'fuop', ), ('4', 'defipair'), ('5', 'defitriple'), ] def _get_spec_1(self, e): return e.setof(e.cprod(e.Anything, e.Anything)) def _get_spec_2(self, e): return (e.setof(e.cprod(e.Anything, e.Anything))) def _get_spec_3(self, e): return (e.boolean << (e.Anything, e.Anything) | e.equals('<', '<=', '==', '!=', '>', '>=', 'in', 'not in', 'is', 'is not')) def _get_spec_4(self, e): return e.cprod(e.set, self._cat.fuop) def _get_spec_5(self, e): return e.cprod(e.set, self._cat.fuop, e.set) def _get__relop(self, e): return e.family(RelOpFamily) map_2_to_1 = id def map_3_to_4(self, e, fuop): return (e.Anything, fuop) def map_3_to_2(self, e, fuop): return self._relop(e.Anything, fuop) # redundant def map_4_to_2(self, e, args): return self._relop(*args) def map_5_to_1(self, e, args): return self._relop(*args) return self.repcat(RelationSpec) def _get_relop(self): return self.relation.defiop.to.paxa def repcat(self, spec): return RepresentationCategory(self, spec) def _get_sequence(self): return self.family(SequenceFamily) def _get_set(self): return self.instance(self.UniSet.UniSet) def _get_set_of_disjoint_sets(self): def p(env, x): return env.forall_pairs(x, lambda env, a, b: a == b or a.disjoint(b), 'a == b or a.disjoint(b)') return self.predicate(p, 'set of disjoint sets') def setcast(self, arg): if not isinstance(arg, self.UniSet.UniSet): arg = self.UniSet.convert(arg) arg = self.Doc.wrap(arg, self.Doc.callfunc( self.Doc.attribute(self._origin_, 'setcast'), arg)) return arg def _get_setof(self): return self.powerset def _get__static_test_env(self): return self.mkTestEnv(None) def _get_synonyms(self): return self.family(SynonymsFamily) def _get_tupleform(self): return self.family(TupleformFamily) def _get_Type(self): return self.Use.Type def union_equals(self, set): return self.eg(self.attr('union', self.equals(set)), self.powerset(set)) def wrap_source_string(self, func, str): func._origin_ = self.Doc.source(str) return func