def __typesystem_type__(self): element_type = self[0][0] ptrs_t = element_type.pointer().pointer().params(name='ptrs') length_t = Type.fromstring('int64 length') size_t = Type.fromstring('int64 size') return Type(ptrs_t, length_t, size_t).params( NumbaPointerType=OmnisciColumnListNumbaType).pointer()
def test(s, caller=False): with heavydb.targets['cpu']: with Type.alias(**heavydb.typesystem_aliases): typ = Type.fromobject(s) if caller: typ = heavydb.caller_signature(typ) return heavydb.format_type(typ)
def test_is_properties(): t = Type() assert t._is_ok and t.is_void t = Type('i') assert t._is_ok and t.is_atomic t = Type('ij') assert t._is_ok and t.is_atomic t = Type_fromstring('ij') assert t._is_ok and t.is_atomic t = Type_fromstring('i,j') assert t._is_ok and t.is_atomic # ! t = Type_fromstring('i *') assert t._is_ok and t.is_pointer t = Type_fromstring('*') assert t._is_ok and t.is_pointer t = Type_fromstring('i* * ') assert t._is_ok and t.is_pointer t = Type_fromstring('i(j)') assert t._is_ok and t.is_function t = Type_fromstring('(j)') assert t._is_ok and t.is_function t = Type_fromstring('()') assert t._is_ok and t.is_function t = Type_fromstring('{i, j}') assert t._is_ok and t.is_struct with pytest.raises(ValueError, match=r'attempt to create an invalid Type object from'): Type('a', 'b')
def test_annotation(target_info): t = Type.fromstring('int foo| a = 1') assert t.annotation() == dict(a='1') assert t[0] == 'int32' def tostr(a): return Type.fromstring(a).tostring() assert tostr('int foo| a = 1') == 'int32 foo | a=1' assert tostr('int foo| a = 1 | b') == 'int32 foo | a=1 | b' assert tostr('int foo| a = 1 | a = 2') == 'int32 foo | a=2' assert tostr('int| a = 1') == 'int32 | a=1' assert tostr('int*| a = 1') == 'int32* | a=1' assert tostr('{int, int}| a = 1') == '{int32, int32} | a=1' assert (tostr('{int|a=1, int|a=2}| a = 3') == '{int32 | a=1, int32 | a=2} | a=3') assert tostr('int foo|') == 'int32 foo' assert tostr('int foo|a') == 'int32 foo | a' assert tostr('int foo|=1') == 'int32 foo | =1' # custom params assert tostr('Column<int> | a') == 'Column<int32> | a' assert tostr('Column<T> | input_id=args<0>') == 'Column<T> | input_id=args<0>' assert tostr('Column<T> | input_id=args<0> | name = foo ') == \ 'Column<T> | input_id=args<0> | name=foo' t = Type.fromstring('int') assert (t | 'a').tostring() == 'int32 | a' assert (t | dict(b=1, c=2)).tostring() == 'int32 | b=1 | c=2'
def check(s): t1 = Type.fromstring(s) m = t1.mangle() try: t2 = Type.demangle(m) except Exception: print('subject: s=`%s`, t1=`%s`, m=`%s`' % (s, t1, m)) raise assert t1 == t2, repr((t1, m, t2))
def cast(typingctx, ptr, typ): """Cast pointer value to any pointer type.""" if isinstance(typ, nb_types.StringLiteral): dtype = Type.fromstring(typ.literal_value) elif isinstance(typ, nb_types.TypeRef): dtype = Type.fromnumba(typ.key) else: return assert dtype.is_pointer sig = dtype.tonumba()(ptr, typ) def codegen(context, builder, signature, args): return builder.bitcast(args[0], dtype.tollvmir()) return sig, codegen
def inner(fname, signature): cmath_fn = getattr(cmath, fname) t = Type.fromstring(signature) retty = str(t[0]) argtypes = tuple(map(str, t[1])) arity = len(argtypes) # define callable if arity == 1: def fn(a): return cmath_fn(a) elif arity == 2: def fn(a, b): return cmath_fn(a, b) else: def fn(a, b, c): return cmath_fn(a, b, c) fn.__name__ = fn_name fn = jit(f"{retty}({', '.join(argtypes)})", devices=["cpu"])(fn) return fn
def inner(fname, signature): cmath_fn = external(signature, name=fname) t = Type.fromstring(signature) retty = str(t[0]) argtypes = tuple(map(str, t[1])) arity = len(argtypes) # define omnisci callable if arity == 1: def fn(a): return cmath_fn(a) elif arity == 2: def fn(a, b): return cmath_fn(a, b) else: def fn(a, b, c): return cmath_fn(a, b, c) fn.__name__ = f"{omnisci.table_name}_{fname}" fn = omnisci(f"{retty}({', '.join(argtypes)})")(fn)
def generic(self, args, kws): # get the correct signature and function name for the current device t = Type.fromstring(f"{retty} {fname}({', '.join(argtys)})") codegen = gen_codegen(fname) lowering_registry.lower(_key, *t.tonumba().args)(codegen) return t.tonumba()
def test_scalar_pointer_access_local(ljit, T): ljit.reset() with Type.alias(T=T): arr = np.array([1, 2, 3, 4], dtype=T) arr2 = np.array([11, 12, 13, 14], dtype=T) ptr = ctypes.c_void_p(arr.__array_interface__['data'][0]) @ljit('T(T* x, int i)') def pitem(x, i): return x[i] @ljit('void(T* x, int i, T)') def sitem(x, i, v): x[i] = v for i in range(len(arr)): v = pitem(ptr, i) assert v == arr[i] for i in range(len(arr)): sitem(ptr, i, arr2[i]) assert (arr == arr2).all()
def generic(self, args, kws): t = Type.fromobject(self.obj._signature).tonumba() name = self.key # lowering def codegen(context, builder, sig, args): fndesc = funcdesc.ExternalFunctionDescriptor( name, sig.return_type, sig.args) func = context.declare_external_function( builder.module, fndesc) return builder.call(func, args) extending.lower_builtin(name, *t.args)(codegen) return t
def test_annotation(target_info): t = Type.fromstring('int foo| a = 1') assert t.annotation() == dict(a='1') assert t[0] == 'int32' def tostr(a): return Type.fromstring(a).tostring() assert tostr('int foo| a = 1') == 'int32 foo | a=1' assert tostr('int foo| a = 1 | b') == 'int32 foo | a=1 | b' assert tostr('int foo| a = 1 | a = 2') == 'int32 foo | a=2' assert tostr('int| a = 1') == 'int32 | a=1' assert tostr('int*| a = 1') == 'int32* | a=1' assert tostr('{int, int}| a = 1') == '{int32, int32} | a=1' assert (tostr('{int|a=1, int|a=2}| a = 3') == '{int32 | a=1, int32 | a=2} | a=3') assert tostr('int foo|') == 'int32 foo' assert tostr('int foo|a') == 'int32 foo | a' assert tostr('int foo|=1') == 'int32 foo | =1' t = Type.fromstring('int') assert (t | 'a').tostring() == 'int32 | a' assert (t | dict(b=1, c=2)).tostring() == 'int32 | b=1 | c=2'
def test_scalar_pointer_access_remote(rjit, memman, T): rjit.reset() calloc_prototype, free_prototype = memory_managers[memman] with Type.alias(T=T): arr = np.array([1, 2, 3, 4], dtype=T) arr2 = np.array([11, 12, 13, 14], dtype=T) calloc = external(calloc_prototype) free = external(free_prototype) @rjit(calloc_prototype) def rcalloc(nmemb, size): return calloc(nmemb, size) @rjit(free_prototype) def rfree(ptr): return free(ptr) @rjit('T(T* x, int i)') def pitem(x, i): return x[i] @rjit('void(T* x, int i, T)') def sitem(x, i, v): x[i] = v ptr = rcalloc(arr.itemsize, len(arr)) assert ptr.value for i in range(len(arr)): sitem(ptr, i, arr[i]) for i in range(len(arr2)): arr2[i] = pitem(ptr, i) rfree(ptr) assert (arr == arr2).all()
def test_fromcallable(target_info): def foo(a: int, b: float) -> int: pass assert Type.fromcallable(foo) == Type.fromstring('i64(i64,d)') def foo(a: 'int32', b): # noqa: F821 pass assert Type.fromcallable(foo) == Type.fromstring('void(i32,<type of b>)') with pytest.raises( ValueError, match=(r'constructing Type instance from' r' a lambda function is not supported')): Type.fromcallable(lambda a: a) with pytest.raises( ValueError, match=r'callable argument kind must be positional'): def foo(*args): pass Type.fromcallable(foo)
def test_dummy(): with pytest.raises( RuntimeError, match=r'Target not specified.'): Type.fromobject('int') with TargetInfo.dummy(): t = Type.fromobject('int') assert str(t) == 'int' t = Type.fromobject('int(int)') assert t.is_function t = Type.fromobject('foo(bar)') assert t.is_function with pytest.raises( RuntimeError, match=r'Target not specified.'): Type.fromobject('foo(bar)')
def external(cls, *args): """ Parameters ---------- signature : object (str, ctypes function, python callable, numba function) Any object convertible to a Numba function via Type.fromobject(...).tonumba() """ ts = defaultdict(list) key = None for signature in args: with TargetInfo.dummy(): t = Type.fromobject(signature) if not t.is_function: raise ValueError("signature must represent a function type") if not t.name: raise ValueError( f"external function name not specified for signature {signature}" ) if key is None: key = t.name if not key: raise ValueError( f"external function name not specified for signature {signature}" ) for device in [ a for a in t.annotation() or [] if a in ["CPU", "GPU"] ] or [ "CPU", "GPU", ]: ts[device].append(signature) obj = cls(key, ts) obj.register() return obj
def fromobject(cls, signature, name: str = None): """ Parameters ---------- signature : object (str, ctypes function, python callable, numba function) Any object convertible to a Numba function via Type.fromobject(...).tonumba() name : str The name of the external function """ # Make inner function for the actual work target_info = TargetInfo.dummy() with target_info: t = Type.fromobject(signature) if not t.is_function: raise ValueError("signature must represent a function type") if name is None: name = t.name if not name: raise ValueError( f"external function name not specified for signature {signature}" ) return cls(name, t)
def test_construction(ljit): assert isinstance(ljit, RemoteJIT) # Case 1 @ljit def add(a: int, b: int) -> int: return a + b assert isinstance(add, Caller) signatures = add.get_signatures() assert len(signatures) == 1 assert signatures[0] == Type.fromstring('i64(i64,i64)') # Case 2 @ljit('double(double, double)') def add(a, b): return a + b assert isinstance(add, Caller) signatures = add.get_signatures() assert len(signatures) == 1 assert signatures[0] == Type.fromstring('f64(f64,f64)') # Case 3 @ljit('double(double, double)') @ljit('int(int, int)') def add(a, b): return a + b assert isinstance(add, Caller) signatures = add.get_signatures() assert len(signatures) == 2 assert signatures[1] == Type.fromstring('i32(i32,i32)') assert signatures[0] == Type.fromstring('f64(f64,f64)') # Case 4 @ljit('double(double, double)', 'int(int, int)') def add(a, b): return a + b assert isinstance(add, Caller) signatures = add.get_signatures() assert len(signatures) == 2 assert signatures[0] == Type.fromstring('f64(f64,f64)') assert signatures[1] == Type.fromstring('i32(i32,i32)') # Case 5 ljit_int = ljit('int(int, int)') ljit_double = ljit('double(double, double)') assert isinstance(ljit_int, Signature) ljit_types = ljit_int(ljit_double) assert isinstance(ljit_types, Signature) @ljit_types def add(a, b): return a + b assert isinstance(add, Caller) signatures = add.get_signatures() assert len(signatures) == 2 assert signatures[0] == Type.fromstring('i32(i32,i32)') assert signatures[1] == Type.fromstring('f64(f64,f64)') # Case 6 @ljit def add(a, b): return a + b assert isinstance(add, Caller) signatures = add.get_signatures() assert len(signatures) == 0 add.signature('i32(i32,i32)') signatures = add.get_signatures() assert len(signatures) == 1 assert signatures[0] == Type.fromstring('i32(i32,i32)')
def test_fromstring(): assert Type_fromstring('void') == Type() assert Type_fromstring('') == Type() assert Type_fromstring('none') == Type() assert Type_fromstring('i') == Type('int32') assert Type_fromstring('i*') == Type(Type('int32'), '*') assert Type_fromstring('*') == Type(Type(), '*') assert Type_fromstring('void*') == Type(Type(), '*') assert Type_fromstring('{i,j}') == Type(Type('int32'), Type('j')) assert Type_fromstring('i(j)') == Type(Type('int32'), (Type('j'), )) assert Type_fromstring('i(j , k)') == Type(Type('int32'), (Type('j'), Type('k'))) assert Type_fromstring(' (j , k) ') == Type(Type(), (Type('j'), Type('k'))) assert Type_fromstring('void(j,k)') == Type(Type(), (Type('j'), Type('k'))) assert Type_fromstring('i a') == Type('int32', name='a') assert Type_fromstring('i* a') == Type(Type('int32'), '*', name='a') assert Type_fromstring('{i,j} a') == Type(Type('int32'), Type('j'), name='a') assert Type_fromstring('i(j) a') == Type(Type('int32'), (Type('j'), ), name='a') assert Type_fromstring('i a*') == Type(Type('int32', name='a'), '*') assert Type_fromstring('{i a,j b} c') == Type(Type('int32', name='a'), Type('j', name='b'), name='c') with pytest.raises(ValueError, match=r'failed to find lparen index in'): Type_fromstring('a)') with pytest.raises(ValueError, match=r'failed to comma-split'): Type_fromstring('a((b)') with pytest.raises(ValueError, match=r'failed to comma-split'): Type_fromstring('a((b)') with pytest.raises(ValueError, match=r'mismatching curly parenthesis in'): Type_fromstring('ab}')
def __typesystem_type__(self): ptr_t = Type.fromstring("int8 ptr") return Type(ptr_t).params(NumbaPointerType=OmnisciTableFunctionManagerNumbaType).pointer()
def test_struct_double_pointer_members(ljit, rjit, location, T): jit = rjit if location == 'remote' else ljit jit.reset() index_t = 'int32' S = '{T** data, index_t length, index_t size}' S1 = '{T* data, index_t size}' with Type.alias(T=T, S=S, S1=S1, index_t=index_t): Sp = S + '*' S1p = S1 + '*' Tp = T + '*' Tpp = T + '**' nb_S = Type.fromstring(S).tonumba() nb_Sp = Type.fromstring(Sp).tonumba() nb_S1 = Type.fromstring(S1).tonumba() nb_S1p = Type.fromstring(S1p).tonumba() nb_T = Type.fromstring(T).tonumba() nb_Tp = Type.fromstring(Tp).tonumba() nb_Tpp = Type.fromstring(Tpp).tonumba() rcalloc, rfree = map(external, memory_managers['cstdlib']) @jit('S* allocate_S(size_t length, size_t size)') def allocate_S(length, size): s = rcalloc(1, sizeof(nb_S)).cast(nb_Sp) s.data = rcalloc(length, sizeof(nb_Tp)).cast(nb_Tpp) s.length = length for i in range(length): s.data[i] = rcalloc(size, sizeof(nb_T)).cast(nb_Tp) s.size = size return s @jit('void deallocate_S(S*)') def deallocate_S(s): if s.length > 0: for i in range(s.length): rfree(s.data[i]) rfree(s.data) rfree(s) @jit('S1* viewitem(S*, index_t)') def viewitem(s, i): s1 = rcalloc(1, sizeof(nb_S1)).cast(nb_S1p) if i >= 0 and i < s.size: s1.size = s.size s1.data = s.data[i] else: s1.size = 0 return s1 @jit('T getitem(S*, index_t, index_t)') def getitem(s, col, row): if col >= 0 and col < s.length: if row >= 0 and row < s.size: return s.data[col][row] return 0 @jit('void free(S1*)') def free(s1): rfree(s1) @jit('void fill1(S1*, T)') def fill1(s1, v): for i in range(s1.size): s1.data[i] = v @jit('void range1(S1*)') def range1(s1): for i in range(s1.size): s1.data[i] = i m, n = 4, 5 s = allocate_S(m, n) # initialize expected = [] for col in range(m): s1 = viewitem(s, col) if col % 2: expected.extend(n * [23+col*10]) fill1(s1, 23+col*10) else: expected.extend(range(n)) range1(s1) free(s1) # check actual = [] for col in range(m): for row in range(n): actual.append(getitem(s, col, row)) deallocate_S(s) assert expected == actual
def test_struct_pointer_members(ljit, rjit, location, T): jit = rjit if location == 'remote' else ljit jit.reset() index_t = 'int32' S = '{T* data, index_t size}' with Type.alias(T=T, S=S, index_t=index_t): Sp = S + '*' nb_S = Type.fromstring(S).tonumba() nb_Sp = Type.fromstring(Sp).tonumba() nb_T = Type.fromstring(T).tonumba() rcalloc, rfree = map(external, memory_managers['cstdlib']) @jit('S* allocate_S(size_t i)') def allocate_S(i): raw = rcalloc(i, sizeof(nb_S)) s = cast(raw, nb_Sp) # cast `void*` to `S*` # s = raw.cast(Sp) # cast `void*` to `S*` s.size = 0 return s @jit('void free(void*)') def free(s): rfree(s) @jit('index_t getsize(S*)') def getsize(s): return s.size @jit('T getitem(S*, index_t)') def getitem(s, i): if i >= 0 and i < s.size: return s.data[i] return 0 # TODO: return some null value or raise exception @jit('void resize_S(S*, index_t)') def resize_S(s, size): if s.size == size: return if s.size != 0: rfree(s.data) s.size = 0 if s.size == 0 and size > 0: raw = rcalloc(size, sizeof(nb_T)) s.data = raw s.size = size s = allocate_S(1) assert getsize(s) == 0 assert getitem(s, 0) == 0 n = 10 resize_S(s, n) assert getsize(s) == n n = 5 resize_S(s, n) assert getsize(s) == n @jit('void fill_S(S*, T)') def fill_S(s, v): for i in range(s.size): s.data[i] = v fill_S(s, 123) assert getitem(s, 0) == 123 @jit('void range_S(S*)') def range_S(s): for i in range(s.size): s.data[i] = i range_S(s) for i in range(getsize(s)): assert getitem(s, i) == i resize_S(s, 0) # deallocate data free(s) # deallocate struct
def __typesystem_type__(self): # Python instance dependent Type return Type.fromstring(S) | type(self).__name__
def Type_fromvalue(s): return Type.fromvalue(s, target_info)
def impl_T_star_to_T_star(context, builder, fromty, toty, value): return builder.bitcast(value, Type.fromnumba(toty).tollvmir())
def test_scalar_pointer_conversion(rjit, T, V): rjit.reset() with Type.alias(T=T, V=V, intp='int64'): # pointer-intp conversion @rjit('T*(intp a)') def i2p(a): return a @rjit('V*(intp a)') def i2r(a): return a @rjit('intp(T* a)') def p2i(a): return a @rjit('intp(V* a)') def r2i(a): return a @rjit('T*(T* a)') def p2p(a): return a @rjit('T*(V* a)') def p2r(a): return a @rjit('V*(T* a)') def r2p(a): return a # pointer artithmetics @rjit('T*(T* a, intp i)') def padd(a, i): return a + i @rjit('T*(T* a)') def pincr(a): return a + 1 if T == V: i = 79 p = i2p(i) assert not isinstance(p, int), (type(p), p) assert ctypes.cast(p, ctypes.c_void_p).value == i i2 = p2i(p) assert i2 == i p2 = p2p(p) assert ctypes.cast(p2, ctypes.c_void_p).value == ctypes.cast(p, ctypes.c_void_p).value assert p2i(padd(p, 2)) == i + 2 assert p2i(pincr(p)) == i + 1 if 'void' in [T, V]: i = 85 r = i2r(i) assert not isinstance(r, int), (type(r), r) assert ctypes.cast(r, ctypes.c_void_p).value == i p2 = r2p(r) assert p2i(p2) == i assert p2i(p2r(i2p(i))) == i # double pointer-intp conversion @rjit('T**(intp a)') def i2pp(a): return a @rjit('V**(intp a)') def i2rr(a): return a @rjit('intp(T** a)') def pp2i(a): return a @rjit('intp(V** a)') def rr2i(a): return a @rjit('T**(T** a)') def pp2pp(a): return a @rjit('T**(T** a, intp i)') def ppadd(a, i): return a + i @rjit('T**(T** a)') def ppincr(a): return a + 1 if T == V: i = 89 pp = i2pp(i) assert ctypes.cast(pp, ctypes.c_void_p).value == i i2 = pp2i(pp) assert i2 == i pp2 = pp2pp(pp) assert ctypes.cast(pp2, ctypes.c_void_p).value == ctypes.cast( pp, ctypes.c_void_p).value assert pp2i(ppadd(pp, 2)) == i + 2 assert pp2i(ppincr(pp)) == i + 1 # double pointer-pointer conversion @rjit('T**(T* a)') def p2pp(a): return a @rjit('T*(T** a)') def pp2p(a): return a # mixed pointer conversion requires void* @rjit('T**(V* a)') def r2pp(a): return a @rjit('V*(T** a)') def pp2r(a): return a if T == V == 'void': i = 99 p = i2p(i) pp = p2pp(p) assert pp2i(pp) == i assert p2i(pp2p(pp)) == i if V == 'void': i = 105 assert r2i(pp2r(i2pp(i))) == i assert pp2i(r2pp(i2r(i))) == i
def impl_intp_to_T_star(context, builder, fromty, toty, value): return builder.inttoptr(value, Type.fromnumba(toty).tollvmir())
def test_struct_input(ljit, rjit, location, T): jit = rjit if location == 'remote' else ljit jit.reset() S = '{T x, T y, T z}' with Type.alias(T=T, S=S): nb_S = Type.fromstring(S).tonumba() nb_T = Type.fromstring(T).tonumba() class MetaMyStructType(type): @property def __typesystem_type__(cls): # Python type dependent type return Type.fromstring(S) | type(cls).__name__ class MyStruct(tuple, metaclass=MetaMyStructType): @property def __typesystem_type__(self): # Python instance dependent Type return Type.fromstring(S) | type(self).__name__ @classmethod def fromobject(cls, obj): return cls([getattr(obj, m.name) for m in cls.__typesystem_type__]) def __getattr__(self, name): typ = self.__typesystem_type__ index = typ.get_field_position(name) return self[index] x, y, z = 123, 2, 3 s = MyStruct((x, y, z)) assert type(s).__typesystem_type__ == s.__typesystem_type__ assert type(s).__typesystem_type__.annotation() != s.__typesystem_type__.annotation() # Get the members of struct given by value and reference @jit('T(S)', 'T(S*)') def get_x(s): return s.x @jit('T(S)', 'T(S*)') def get_y(s): return s.y @jit('T(S)', 'T(S*)') def get_z(s): return s.z assert get_x(s) == x assert get_y(s) == y assert get_z(s) == z # Set the members of struct given by reference # Manage memory of the arrays with struct values rcalloc, rfree = map(external, memory_managers['cstdlib']) @jit('S* allocate_S(size_t i)') def allocate_S(i): return rcalloc(i, sizeof(nb_S)) @jit('void free(void*)') def free(s): rfree(s) @jit('void set_x(S*, T)') def set_x(s, x): s.x = x @jit('void set_y(S*, T)') def set_y(s, y): s.y = y @jit('void set_z(S*, T)') def set_z(s, z): s.z = z p = allocate_S(1) set_x(p, x) assert get_x(p) == x set_y(p, y) assert get_y(p) == y set_z(p, z) assert get_z(p) == z free(p) @jit('size_t sizeof_S(S)', 'size_t sizeof_S(S*)', 'size_t sizeof_T(T)') def sizeof_S(s): return sizeof(s) assert sizeof_S(s) == sizeof_S(nb_T(0)) * 3 assert sizeof_S(p) == 8 # Pointer arithmetics and getitem @jit('void(S*, int64)') def init_S(s, n): s.x = 8 for i in range(n): si = s + i # pointer arithmetics si.x = i si.y = i*10 si.z = i*20 @jit('void(S*, int64)') def init_S2(s, n): s.x = 8 for i in range(n): # `s[i]` is equivalent to `s + i`! That is, the result # of `s[i]` is a pointer value `S*` rather than a # value of `S`. si = s[i] si.x = i*5 si.y = i*15 si.z = i*25 @jit('S*(S*)') def next_S(s): return s + 1 n = 5 p = allocate_S(n) init_S(p, n) r = p for i in range(n): assert (get_x(r), get_y(r), get_z(r)) == (i, i*10, i*20) r = next_S(r) init_S2(p, n) r = p for i in range(n): assert (get_x(r), get_y(r), get_z(r)) == (i*5, i*15, i*25) r = next_S(r) free(p)
def __typesystem_type__(cls): # Python type dependent type return Type.fromstring(S) | type(cls).__name__
def fromnumpy(t): return Type.fromnumpy(t, target_info)