def _gen_dispatcher(name, name_mangled, doc=None, hasrtn=True): argfill = ", ".join(['self', '*args', '**kwargs']) lines = ['def {0}({1}):'.format(name, argfill)] lines += [] if doc is None else indent('\"\"\"{0}\"\"\"'.format(doc), join=False) types = ["types = set([(i, type(a)) for i, a in enumerate(args)])", "types.update([(k, type(v)) for k, v in kwargs.iteritems()])",] lines += indent(types, join=False) refinenum = lambda x: (sum([int(isrefinement(a[1])) for a in x[0][1:]]), len(x[0]), x[1]) mangitems = sorted(name_mangled.items(), key=refinenum) mtypeslines = [] lines += indent("# vtable-like dispatch for exactly matching types", join=False) for key, mangled_name in mangitems: cargs = key[1:] arang = range(len(cargs)) anames = [ca[0] for ca in cargs] pytypes = [cython_pytype(ca[1]) for ca in cargs] mtypes = ", ".join( ["({0}, {1})".format(i, pyt) for i, pyt in zip(arang, pytypes)] + \ ['("{0}", {1})'.format(n, pyt) for n, pyt in zip(anames, pytypes)]) mtups = '(' + mtypes + ')' if 0 < len(mtypes) else mtypes mtypeslines.append(mangled_name + "_argtypes = frozenset(" + mtups + ")") cond = ["if types <= self.{0}_argtypes:".format(mangled_name),] if hasrtn: rline = "return self.{0}(*args, **kwargs)".format(mangled_name) else: rline = ["self.{0}(*args, **kwargs)".format(mangled_name), "return"] cond += indent(rline, join=False) lines += indent(cond, join=False) lines = sorted(mtypeslines) + [''] + lines lines += indent("# duck-typed dispatch based on whatever works!", join=False) refineopp = lambda x: (-1*sum([int(isrefinement(a[1])) for a in x[0][1:]]), len(x[0]), x[1]) mangitems = sorted(name_mangled.items(), key=refineopp) for key, mangled_name in mangitems: lines += indent('try:', join=False) if hasrtn: rline = "return self.{0}(*args, **kwargs)".format(mangled_name) else: rline = ["self.{0}(*args, **kwargs)".format(mangled_name), "return"] lines += indent(indent(rline, join=False), join=False) lines += indent(["except (RuntimeError, TypeError, NameError):", indent("pass", join=False)[0],], join=False) errmsg = "raise RuntimeError('method {0}() could not be dispatched')".format(name) lines += indent(errmsg, join=False) lines += [''] return lines
def check_cython_pytype(t, exp): obs = ts.cython_pytype(t) assert_equal(obs, exp)