def test_block_namespace(self): code = Code() with code.block('if {name}:', name='x') as ns: ns.w('return {name}') # src = code.build() assert src == ("if x:\n" " return x")
def test_args_default(self): code = Code() varnames = ['x', ('y', 3)] assert code.args(varnames) == 'x, y=3' assert code.args(varnames, '*args') == 'x, y=3, *args' assert code.args(varnames, '*args', '**kwargs') == 'x, y=3, *args, **kwargs'
def test_params_simple(self): code = Code() varnames = ['x', 'y'] assert code.params(varnames) == 'x, y' assert code.params(varnames, '*args') == 'x, y, *args' assert code.params(varnames, '*args', '**kwargs') == 'x, y, *args, **kwargs'
def test_formatting(): code = Code() code.w('{hello}') assert code.build() == '{hello}' # code = Code() code.w('{hello}', hello='world') assert code.build() == 'world'
def test_ww(): code = Code() code.ww(""" if {name}: return {name} """, name="x") src = code.build() assert src == ("if x:\n" " return x")
def __init__(self, request, convert_case, pyx, standalone): self.code = Code(pyx=pyx) self.request = request self.convert_case = convert_case self.pyx = pyx self.standalone = standalone self.allnodes = {} # id -> node self.children = defaultdict(list) # nodeId -> nested nodes self.importnames = {} # filename -> import name self.extra_annotations = defaultdict(list) # obj -> [ann]
def __init__(self, request, pyx, standalone, default_options): self.request = request self.pyx = pyx self.standalone = standalone self.default_options = default_options self.version_check = default_options.version_check self.code = Code(pyx=self.pyx) self.allnodes = {} # id -> node self.children = defaultdict(list) # nodeId -> nested nodes self._node_options = {} # node -> Options self.importnames = {} # filename -> import name self.extra_annotations = defaultdict(list) # obj -> [ann] self.field_override = {} # obj -> obj
def test_new_global(): code = Code() name = code.new_global('x', 42) assert name == 'x' assert code['x'] == 42 # name = code.new_global('x', 42) assert name == 'x' assert code['x'] == 42 # name = code.new_global('x', 43) assert name == 'x__1' assert code['x'] == 42 assert code['x__1'] == 43
def test_def_(): code = Code() with code.def_('foo', ['x', 'y']): code.w('return x+y') # code.compile() foo = code['foo'] assert foo(1, 2) == 3
def test_block_autopass(): code = Code() with code.block('if True:'): pass src = code.build() assert src == ("if True:\n" " pass") # code = Code() with code.block('if True:', autopass=False): pass src = code.build() assert src == "if True:"
def test_def__default_args(): code = Code() with code.def_('foo', ['x', ('y', 3)]): code.w('return x+y') # code.compile() foo = code['foo'] assert foo(1) == 4 assert foo(1, 10) == 11
def test_build(): code = Code() with code.block('if True:'): code.w('x = 42') # src = code.build() assert src == ("if True:\n" " x = 42")
def test_pyx_types(self): code = Code(pyx=True) varnames = ['x', 'y'] assert code.args(varnames) == 'x, y' assert code.args(varnames, '*args') == 'x, y, *args' assert code.params(varnames) == 'object x, object y' assert code.params(varnames, '*args') == 'object x, object y, *args'
def test_simple(self, schema, benchmark): code = Code() code.global_scope.N = self.N code.ww(""" def new_and_sum(Point): res = 0 for i in range({N}): obj = Point(x=1, y=2, z=3) res += obj.z return res """) code.compile() new_and_sum = code['new_and_sum'] res = benchmark(new_and_sum, schema.Point) assert res == self.N * 3
def test_list_of_ints(self, schema, benchmark): code = Code() code.global_scope.N = self.N code.ww(""" def new_and_sum(MyInt64List, items): res = 0 for i in range({N}): obj = MyInt64List(items) res += 1 return res """) code.compile() new_and_sum = code['new_and_sum'] items = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] res = benchmark(new_and_sum, schema.MyInt64List, items) assert res == self.N
def test_list(self, schema, benchmark): code = Code() code.global_scope.N = self.N code.ww(""" def new_and_sum(MyStructContainer, items): res = 0 for i in range({N}): obj = MyStructContainer(items) res += 1 return res """) code.compile() new_and_sum = code['new_and_sum'] items = [get_obj(schema)] * 10 res = benchmark(new_and_sum, schema.MyStructContainer, items) assert res == self.N
def test_text(self, schema, benchmark): code = Code() code.global_scope.N = self.N code.ww(""" def new_and_sum(StrPoint): res = 0 for i in range({N}): obj = StrPoint(x='hello', y='this is a longer string', z='bar') res += len(obj.z) return res """) code.compile() new_and_sum = code['new_and_sum'] res = benchmark(new_and_sum, schema.StrPoint) assert res == self.N * 3
def test_struct(self, schema, benchmark): code = Code() code.global_scope.N = self.N code.ww(""" def new_and_sum(Rectangle, a, b): res = 0 for i in range({N}): obj = Rectangle(a=a, b=b) res += 1 return res """) code.compile() new_and_sum = code['new_and_sum'] a = schema.Point(1, 2, 3) b = schema.Point(4, 5, 6) res = benchmark(new_and_sum, schema.Rectangle, a, b) assert res == self.N
def make_wrappers(): from pypytools.codegen import Code code = Code() names = [ 'all', 'any', 'argmax', 'argmin', 'argsort', 'choose', 'clip', 'copy', 'cumprod', 'cumsum', 'diagonal', 'max', 'min', 'nonzero', 'prod', 'ptp', 'put', 'ravel', 'repeat', 'reshape', 'round', 'squeeze', 'sum', 'swapaxes', 'transpose' ] # for name in names: ns = code.new_scope(name=name) with code.def_(name, ['myarray'], '*args', '**kwargs'): ns.w('return myarray.{name}(*args, **kwargs)') # code.compile() gbl = globals() for name in names: gbl[name] = code[name]
def test_numeric(self, schema, numeric_type, benchmark, obj=None): # the extra_info is used to generate the charts benchmark.extra_info['attribute_type'] = numeric_type code = Code() code.global_scope.N = self.N code.global_scope.numeric_type = numeric_type code.ww(""" def sum_attr(obj): myobjs = (obj, obj) res = 0 for i in range({N}): obj = myobjs[i%2] res += obj.{numeric_type} return res """) code.compile() sum_attr = code['sum_attr'] obj = get_obj(schema) res = benchmark(sum_attr, obj) assert res == 100 * self.N
class ModuleGenerator(object): def __init__(self, request, convert_case, pyx, version_check, standalone): self.code = Code(pyx=pyx) self.request = request self.convert_case = convert_case self.pyx = pyx self.version_check = version_check self.standalone = standalone self.allnodes = {} # id -> node self.children = defaultdict(list) # nodeId -> nested nodes self.importnames = {} # filename -> import name self.extra_annotations = defaultdict(list) # obj -> [ann] self.field_override = {} # obj -> obj def register_extra_annotation(self, obj, ann): self.extra_annotations[obj].append(ann.annotation) def register_field_override(self, origin, target): self.field_override[origin] = target def has_annotation(self, obj, anncls): annotations = self.extra_annotations.get(obj, []) if obj.annotations is not None: annotations += obj.annotations for ann in annotations: if ann.id == anncls.__id__: # XXX: probably "annotation" should be taken by the # constructor res = anncls() res.annotation = ann res.target = obj return res return None def w(self, *args, **kwargs): self.code.w(*args, **kwargs) def block(self, *args, **kwargs): return self.code.block(*args, **kwargs) def register_import(self, fname): name = py.path.local(fname).purebasename name = name.replace('+', 'PLUS') name = '_%s_capnp' % name if name in self.importnames.values(): # avoid name clashes name = '%s_%s' % (name, len(self.filenames)) self.importnames[fname] = name return name def generate(self): self.request.emit(self) return self.code.build() def _dump_node(self, node): def visit(node, deep=0): print('%s%s: %s' % (' ' * deep, node.which(), node.displayName)) for child in self.children[node.id]: visit(child, deep + 2) visit(node) def _convert_name(self, name): name = ensure_unicode(name) if PY3 else name if self.convert_case: return from_camel_case(name) else: return name def _field_name(self, field): name = self._convert_name(field.name) name = self._mangle_name(name) return name def _mangle_name(self, name): if name in keyword.kwlist: return name + '_' return name def declare_enum(self, compile_name, name, items): # this method cannot go on Node__Enum because it's also called by # Node__Struct (for __tag__) items = list(map(repr, items)) ns = self.code.new_scope() ns.name = compile_name ns.members = "(%s,)" % (', '.join(items)) ns.prebuilt = [ ns.format('{name}({i})', i=i) for i in range(len(items)) ] ns.prebuilt = ', '.join(ns.prebuilt) ns.prebuilt = ns.format('({prebuilt},)') with ns.block("{cdef class} {name}(_BaseEnum):"): ns.w("__members__ = {members}") # # define the _new staticmethod, to create new instances. if self.pyx: # on CPython, make a tuple of prebuilt instances for the # statically known values ns.w("@staticmethod") with ns.block( 'cdef _new(long x, __prebuilt={prebuilt}):') as ns: ns.ww(""" try: return __prebuilt[x] except IndexError: return {name}(x) """) else: # on PyPy, always create a new object, so that the JIT will be # able to make it virtual ns.w("@staticmethod") with ns.block('def _new(x):') as ns: ns.w('return {name}(x)') ns.w("_fill_enum({name})") def def_property(self, ns, name, src): if self.pyx: with ns.block('property {name}:', name=name): with ns.block('def __get__(self):'): ns.ww(src) else: ns.w('@property') with ns.block('def {name}(self):', name=name): ns.ww(src) ns.w()
def test_global_kwargs(): code = Code() code.global_scope.x = 42 code.w('return {x}') assert code.build() == 'return 42'
def test_cdef_var(): code = Code() with code.def_('foo', ['x', 'y']): code.cdef_var('long', 'foo') code.cdef_var('int', 'bar', 42) code.w('return') src = code.build() assert src == ("def foo(x, y):\n" " return") # code = Code(pyx=True) with code.def_('foo', ['x', 'y']): code.cdef_var('long', 'foo') code.cdef_var('int', 'bar', 42) code.w('return') src = code.build() assert src == ("def foo(object x, object y):\n" " cdef long foo\n" " cdef int bar = 42\n" " return")
def test_global_kwargs_override(): code = Code() code.global_scope.x = 42 code.w('return {x}', x=52) assert code.build() == 'return 52'
class ModuleGenerator(object): def __init__(self, request, convert_case, pyx, standalone): self.code = Code(pyx=pyx) self.request = request self.convert_case = convert_case self.pyx = pyx self.standalone = standalone self.allnodes = {} # id -> node self.children = defaultdict(list) # nodeId -> nested nodes self.importnames = {} # filename -> import name self.extra_annotations = defaultdict(list) # obj -> [ann] def register_extra_annotation(self, obj, ann): self.extra_annotations[obj].append(ann.annotation) def has_annotation(self, obj, anncls): annotations = self.extra_annotations.get(obj, []) if obj.annotations is not None: annotations += obj.annotations for ann in annotations: if ann.id == anncls.__id__: # XXX: probably "annotation" should be taken by the # constructor res = anncls() res.annotation = ann res.target = obj return res return None def w(self, *args, **kwargs): self.code.w(*args, **kwargs) def block(self, *args, **kwargs): return self.code.block(*args, **kwargs) def register_import(self, fname): name = py.path.local(fname).purebasename name = name.replace('+', 'PLUS') name = '_%s_capnp' % name if name in self.importnames.values(): # avoid name clashes name = '%s_%s' % (name, len(self.filenames)) self.importnames[fname] = name return name def generate(self): self.request.emit(self) return self.code.build() def _dump_node(self, node): def visit(node, deep=0): print '%s%s: %s' % (' ' * deep, node.which(), node.displayName) for child in self.children[node.id]: visit(child, deep+2) visit(node) def _convert_name(self, name): if self.convert_case: return from_camel_case(name) else: return name def _field_name(self, field): name = self._convert_name(field.name) name = self._mangle_name(name) return name def _mangle_name(self, name): if name in keyword.kwlist: return name + '_' return name def declare_enum(self, var_name, enum_name, items): # this method cannot go on Node__Enum because it's also called by # Node__Struct (for __tag__) items = map(repr, items) decl = "%s = _enum(%r, [%s])" % (var_name, enum_name, ', '.join(items)) self.w(decl) def def_property(self, ns, name, src): if self.pyx: with ns.block('property {name}:', name=name): with ns.block('def __get__(self):'): ns.ww(src) else: ns.w('@property') with ns.block('def {name}(self):', name=name): ns.ww(src) ns.w()
def test_call(self): for pyx in (False, True): code = Code(pyx=pyx) assert code.call('foo', ['x', 'y']) == 'foo(x, y)'
def test_pyx_default(self): code = Code(pyx=True) varnames = ['x', ('y', 3)] assert code.params(varnames) == 'object x, object y=3' assert code.params(varnames, '*args') == 'object x, object y=3, *args'
def test_set_get_globals(): code = Code() code['x'] = 42 assert code['x'] == 42
def test_new_scope(self): code = Code() code.global_scope.x = 42 code.global_scope.y = 52 ns = code.new_scope(y=53, z=63) assert ns.__dict__ == dict(x=42, y=53, z=63)
def test_scope_formatting(self): code = Code() ns = code.new_scope(y=52) ns.x = 42 ns.w('x == {x}, y == {y}') assert code.build() == 'x == 42, y == 52'