def expect_dense(dtype, shape, flat): return { str(tc.URI(tc.tensor.Dense)): [ [list(shape), str(tc.URI(dtype))], list(flat), ] }
def testCNN(self): inputs = np.ones([BATCH_SIZE, 3, 5, 5]) self.host.post( tc.URI(NeuralNetTester).append("test_cnn_layer"), {"inputs": load_dense(inputs)}) self.host.post( tc.URI(NeuralNetTester).append("test_cnn"), {"inputs": load_dense(inputs)})
def expect_sparse(dtype, shape, values): if isinstance(values, np.ndarray): values = nparray_to_sparse(values, dtype) return { str(tc.URI(tc.tensor.Sparse)): [ [list(shape), str(tc.URI(dtype))], list(values), ] }
def expect_dense(ndarray): shape = list(ndarray.shape) dtype = np_to_tc_dtype(ndarray.dtype) return { str(tc.URI(tc.tensor.Dense)): [ [shape, str(tc.URI(dtype))], ndarray.flatten().tolist(), ] }
def testDNN(self): inputs = np.random.random(2 * BATCH_SIZE).reshape([BATCH_SIZE, 2]) self.host.post( tc.URI(NeuralNetTester).append("test_linear"), {"inputs": load_dense(inputs)}) start = time.time() self.host.post( tc.URI(NeuralNetTester).append("test_dnn"), {"inputs": load_dense(inputs)}) elapsed = time.time() - start print(f"trained a deep neural net in {elapsed:.2}s")
def testCast(self): cxt = tc.Context() cxt.x = tc.tensor.Dense.random_normal([3, 3]) cxt.y1 = cxt.x / tc.Float(3.) cxt.y2 = cxt.x / tc.Int(3).cast(tc.Float) cxt.y3 = cxt.x.cast(tc.F32) / 3 cxt.result = (cxt.y1.dtype, cxt.y2.dtype, cxt.y3.dtype) actual = self.host.post(ENDPOINT, cxt) self.assertEqual(actual, [{ tc.URI(tc.Class): { tc.URI(tc.F64): {} } }] * 3)
def testMulWithBroadcast(self): tau = np.array([[4.188]]) v = np.array([[1], [0.618]]) cxt = tc.Context() cxt.tau = load_dense(tau) cxt.v = load_dense(v) cxt.result = cxt.tau * tc.tensor.einsum("ij,kj->ik", [cxt.v, cxt.v]) actual = self.host.post(ENDPOINT, cxt) expected = tau * (v @ v.T) self.assertEqual(expected.shape, tuple(actual[tc.URI(tc.tensor.Dense)][0][0])) self.assertTrue( np.allclose(expected.flatten(), actual[tc.URI(tc.tensor.Dense)][1]))
def expect_sparse(ndarray): shape = list(ndarray.shape) dtype = np_to_tc_dtype(ndarray.dtype) coords = itertools.product(*[range(dim) for dim in shape]) elements = [[list(coord), n] for (coord, n) in zip(coords, (n for n in ndarray.flatten().tolist())) if n != 0] return { str(tc.URI(tc.tensor.Sparse)): [ [shape, str(tc.URI(dtype))], elements, ] }
def start_docker(name, app_or_library=[], overwrite=True, host_uri=None, wait_time=1., **flags): if not os.path.exists(DOCKERFILE): raise RuntimeError( f"Dockerfile at {DOCKERFILE} not found--use the TC_DOCKER environment variable to set a different path" ) port = DEFAULT_PORT if host_uri is not None and host_uri.port(): port = host_uri.port() config_dir = os.getcwd() config_dir += f"/{CONFIG}/{name}/{port}" _maybe_create_dir(config_dir, overwrite) app_configs = [] deps = tc.app.dependencies(app_or_library) if isinstance( app_or_library, tc.app.Library) else app_or_library for lib in deps: lib_path = tc.URI(lib).path() tc.app.write_config(lib, f"{config_dir}{lib_path}", overwrite) app_configs.append(lib_path) process = Docker(config_dir, app_configs, http_port=port, **flags) process.start(wait_time) return tc.host.Local(process, f"http://{process.ADDRESS}:{port}")
def testCreateUser(self): details = { "first_name": "First", "last_name": "Last", "email": "*****@*****.**" } self.host.post(tc.URI(TestApp).append("create_user"), details)
def start_local_host(name, app_or_library=[], overwrite=True, host_uri=None, wait_time=1, **flags): if not os.path.isfile(TC_PATH): hint = "use the TC_PATH environment variable to set the path to the TinyChain host binary" raise RuntimeError(f"invalid executable path: {TC_PATH} ({hint})") deps = tc.app.dependencies(app_or_library) if isinstance( app_or_library, tc.app.Library) else app_or_library port = DEFAULT_PORT if host_uri is not None and host_uri.port(): port = host_uri.port() elif deps and tc.URI(deps[0]).port(): port = tc.URI(deps[0]).port() config_dir = os.getcwd() config_dir += f"/{CONFIG}/{name}/{port}" _maybe_create_dir(config_dir, overwrite) app_configs = [] for dep in deps: app_path = tc.URI(dep).path() app_path = f"{config_dir}{app_path}" tc.app.write_config(dep, app_path, overwrite) app_configs.append(app_path) data_dir = f"/tmp/tc/tmp/{port}/{name}" if overwrite and os.path.exists(data_dir): shutil.rmtree(data_dir) if "log_level" not in flags: flags["log_level"] = "debug" process = Local(TC_PATH, workspace=f"/tmp/tc/tmp/{port}/{name}", libs=app_configs, force_create=True, data_dir=data_dir, http_port=port, **flags) process.start(wait_time) return tc.host.Local(process, f"http://{process.ADDRESS}:{port}")
class ClientService(tc.Cluster): __uri__ = tc.URI("http://127.0.0.1:8702/app/clientservice") @tc.get_method def room_area(self, txn, dimensions: tc.Tuple) -> Meters: area_service = tc.use(AreaService) txn.length = area_service.Meters(dimensions[0]) txn.width = area_service.Meters(dimensions[1]) return area_service.area(length=txn.length, width=txn.width)
class Feet(Distance): __uri__ = tc.URI(LINK) + "/Feet" @tc.get_method def to_feet(self) -> Feet: return self @tc.get_method def to_meters(self) -> Meters: return self / 3.28
class Meters(Distance): __uri__ = tc.URI(LINK) + "/Meters" @tc.get_method def to_feet(self) -> Feet: return self * 3.28 @tc.get_method def to_meters(self) -> Meters: return self
class Persistent(tc.app.App): __uri__ = tc.URI(f"http://127.0.0.1:{DEFAULT_PORT}/test/table") def __init__(self): self.table = chain_type(tc.table.Table(SCHEMA)) tc.app.App.__init__(self) @tc.delete def truncate(self): return self.table.delete()
class Distance(tc.Number): __uri__ = tc.URI(LINK) + "/Distance" @tc.get_method def to_feet(self) -> Feet: return tc.error.NotImplemented("abstract") @tc.get_method def to_meters(self) -> Meters: return tc.error.NotImplemented("abstract")
class Wholesaler(tc.Cluster): __uri__ = tc.URI("/app/wholesaler") @tc.post_method def buy(self, txn, quantity: tc.Number): producer = tc.use(Producer) return self.grant( SCOPE, {"/state/scalar/op/post": [("buy_result", producer.buy(quantity=quantity))]}, {"quantity": quantity}, )
class AreaService(tc.Cluster): __uri__ = tc.URI(LINK) def _configure(self): self.Distance = Distance self.Feet = Feet self.Meters = Meters @tc.post_method def area(self, txn, length: Distance, width: Distance) -> tc.Number: txn.length_m = length.to_meters() txn.width_m = width.to_meters() return txn.length_m * txn.width_m
async def post(self, path, params={}): endpoint = str(tc.URI(self) + path) async with aiohttp.ClientSession(timeout=TIMEOUT) as session: response = await session.post(endpoint, json=tc.to_json(params)) backoff = BACKOFF while response.status in self.RETRYABLE: await asyncio.sleep(backoff) response = await session.post(endpoint, json=params) backoff *= 2 return response
def testMatmul(self): l = np.random.random([2, 3, 4]) r = np.random.random([2, 4, 5]) cxt = tc.Context() cxt.l = tc.tensor.Dense.load(l.shape, l.flatten().tolist(), tc.F32) cxt.r = tc.tensor.Dense.load(r.shape, r.flatten().tolist(), tc.F32) cxt.result = cxt.l @ cxt.r expected = np.matmul(l, r) actual = self.host.post(ENDPOINT, cxt) actual = actual[tc.URI(tc.tensor.Dense)][1] self.assertTrue(np.allclose(expected.flatten(), actual))
async def delete(self, path, key=None): endpoint = str(tc.URI(self) + path) async with aiohttp.ClientSession(timeout=TIMEOUT) as session: response = await session.delete( endpoint, params={"key": json.dumps(tc.to_json(key))}) backoff = BACKOFF while response.status in self.RETRYABLE: await asyncio.sleep(backoff) response = await session.get(endpoint, params={"key": json.dumps(key)}) backoff *= 2 return response
def _execute(self, chain_type): name = self.NAME app = self.app(chain_type) hosts = [] for i in range(self.NUM_HOSTS): port = DEFAULT_PORT + i host_uri = f"http://127.0.0.1:{port}" + tc.URI(app).path() host = start_host(f"test_{name}_{i}", [app], host_uri=host_uri, cache_size=self.CACHE_SIZE) hosts.append(host) time.sleep(1) self.execute(hosts) for host in hosts: host.stop()
def testSelect(self): count = 5 values = [[v] for v in range(count)] keys = [[num2words(i)] for i in range(count)] cxt = tc.Context() cxt.table = tc.table.Table(SCHEMA) cxt.inserts = [cxt.table.insert(k, v) for k, v in zip(keys, values)] cxt.result = tc.After(cxt.inserts, cxt.table.select(["name"])) expected = { str(tc.URI(tc.table.Table)): [ tc.to_json(tc.table.Schema([tc.Column("name", tc.String, 512)])), list(sorted(keys)) ] } actual = self.host.post(ENDPOINT, cxt) self.assertEqual(actual, expected)
class Producer(tc.Cluster): __uri__ = tc.URI("/app/producer") def _configure(self): self.in_stock = tc.Chain.Sync(IN_STOCK) @tc.post_method def buy(self, txn, quantity: tc.Number): txn.inventory = self.inventory() txn.new_inventory = txn.inventory - quantity txn.sale = tc.If( quantity > txn.inventory, tc.error.BadRequest("requested quantity is unavailable"), self.in_stock.set(txn.new_inventory)) return tc.After(self.authorize(SCOPE), txn.sale) @tc.get_method def inventory(self) -> tc.Number: return self.in_stock.subject()
class Persistent(tc.app.App): __uri__ = tc.URI(f"http://127.0.0.1:{DEFAULT_PORT}/test/tensor") def __init__(self): schema = ([2, 3], tc.I32) self.dense = chain_type(tc.tensor.Dense(schema)) self.sparse = chain_type(tc.tensor.Sparse(schema)) tc.app.App.__init__(self) @tc.put def overwrite(self, txn): txn.new = tc.tensor.Dense.constant([3], 2) return [ self.dense.write(txn.new), self.sparse[0].write(txn.new) ] @tc.get def eq(self): return self.sparse == self.dense
import tinychain as tc import unittest from ..process import start_host URI = tc.URI("/test/app") class User(tc.app.Model): __uri__ = URI.append("Foo") first_name = tc.Column(tc.String, 100) last_name = tc.Column(tc.String, 100) email = tc.Column(tc.EmailAddress, 100) def __init__(self, first_name, last_name, email): self.first_name = first_name self.last_name = last_name self.email = email class TestApp(tc.app.App): __uri__ = URI @tc.post def create_user(self, new_user: User): """TODO""" class UserTests(unittest.TestCase): @classmethod
"""Representation of a models directory. Used only for testing purposes.""" import tinychain as tc URI = tc.URI("/test/tctest/unit/models") class Product(tc.app.Model): __uri__ = URI.append("Product") price = tc.Column("price", tc.I32) name = tc.Column("name", tc.String, 100) def __init__(self, product, name, price): self.product = product self.price = price self.name = name class User(tc.app.Model): __uri__ = URI.append("User") first_name = tc.Column("first_name", tc.String, 100) last_name = tc.Column("last_name", tc.String, 100) def __init__(self, user_id, first_name, last_name): self.user_id = user_id self.first_name = first_name self.last_name = last_name class Order(tc.app.Model):
def __init__(self, host): self.__uri__ = tc.URI(host) self._host = host # keep a reference here so it doesn't get dropped
import typing import unittest import tinychain as tc from ..process import start_host URI = tc.URI("/test/lib") class Foo(tc.app.Model): __uri__ = URI.append("Foo") name = tc.String def __init__(self, name): self.name = name @tc.get def greet(self): return tc.String("my name is {{name}}").render(name=self.name) class Bar(Foo): __uri__ = URI.append("Bar") @tc.get def greet(self): return tc.String("their name is {{name}}").render(name=self.name) class Baz(Bar, tc.app.Dynamic):
class Balance(tc.Cluster): __uri__ = tc.URI("/app/balance") def _configure(self): self.weight = tc.Chain.Sync(10)