diff --git a/tests/test_client.py b/tests/test_client.py index 49f12e8..60ea159 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -220,6 +220,64 @@ def _object_contents(idx): self.assertEqual(_object_contents(response_idx), response.body.decode('utf-8')) +class TestSchema(Test): + + def setUp(self): + super(TestSchema, self).setUp() + + self._schema_dir = '/v3io-py-test-schema' + self._schema_path = os.path.join(self._schema_dir, '.%23schema') + + # clean up + self._delete_dir(self._schema_dir) + + def test_create_schema(self): + # write schema + self._client.create_schema(container=self._container, + path=self._schema_dir, + key='key_field', + fields=[ + { + 'name': 'key_field', + 'type': 'string', + 'nullable': False + }, + { + 'name': 'data_field_0', + 'type': 'long', + 'nullable': True + }, + { + 'name': 'data_field_1', + 'type': 'double', + 'nullable': True + }, + ]) + + # write to test the values in the UI (requires breaking afterwards) + items = { + 'a': {'data_field_0': 30, 'data_field_1': 100}, + 'b': {'data_field_0': 300, 'data_field_1': 1000}, + 'c': {'data_field_0': 3000, 'data_field_1': 10000}, + } + + for item_key, item_attributes in future.utils.viewitems(items): + self._client.put_item(container=self._container, + path=v3io.common.helpers.url_join(self._schema_dir, item_key), + attributes=item_attributes) + + # verify the scehma + response = self._client.get_object(container=self._container, + path=self._schema_path, + raise_for_status=v3io.dataplane.RaiseForStatus.never) + + self.assertEqual( + '{"hashingBucketNum":0,"key":"key_field","fields":[{"name":"key_field","type":"string","nullable":false},' + '{"name":"data_field_0","type":"long","nullable":true},{"name":"data_field_1","type":"double"' + ',"nullable":true}]}', + response.body.decode('utf-8')) + + class TestEmd(Test): def setUp(self): diff --git a/v3io/dataplane/client.py b/v3io/dataplane/client.py index 4c2483e..e2d1cea 100644 --- a/v3io/dataplane/client.py +++ b/v3io/dataplane/client.py @@ -1,4 +1,5 @@ import os +import ujson import future.utils @@ -307,7 +308,7 @@ def put_item(self, locals()) def put_items(self, container, path, items, access_key=None, raise_for_status=None, condition=None): - """A helper to put several items, calling put_item for each. + """[OBSOLETED] A helper to put several items, calling put_item for each. Parameters ---------- @@ -786,9 +787,78 @@ def get_records(self, locals(), v3io.dataplane.output.GetRecordsOutput) + # + # Helpers + # + + def create_schema(self, + container, + path, + access_key=None, + raise_for_status=None, + transport_actions=None, + key=None, + fields=None): + """Creates a KV schema file + + Parameters + ---------- + container (Required) : str + The container on which to operate. + path (Required) : str + The path of the object + access_key (Optional) : str + The access key with which to authenticate. Defaults to the V3IO_ACCESS_KEY env. + key (Required) : str + The key field name + fields (Required) : list of dicts + A dictionary of fields, where each item has: + - name (string) + - type (string - one of string, double, long) + - nullable (boolean) + + Example: [ + { + 'name': 'my_field', + 'type': 'string', + 'nullable': False + }, + { + 'name': 'who', + 'type': 'string', + "nullable": True + } + ] + + Return Value + ---------- + A `Response` object + """ + put_object_args = locals() + put_object_args['path'] = os.path.join(put_object_args['path'], '.%23schema') + put_object_args['offset'] = 0 + put_object_args['body'] = self._get_schema_contents(key, fields) + del(put_object_args['key']) + del (put_object_args['fields']) + + return self._transport.request(container, + access_key or self._access_key, + raise_for_status, + transport_actions, + v3io.dataplane.request.encode_put_object, + put_object_args) + @staticmethod def _normalize_stream_path(path): if not path.endswith('/'): return path + '/' return path + + @staticmethod + def _get_schema_contents(key, fields): + return ujson.dumps({ + 'hashingBucketNum': 0, + 'key': key, + 'fields': fields + })