kosh 3.4__tar.gz → 3.5__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {kosh-3.4/kosh.egg-info → kosh-3.5}/PKG-INFO +1 -1
- kosh-3.5/kosh/current_version.py +1 -0
- {kosh-3.4 → kosh-3.5}/kosh/dataset.py +44 -1
- {kosh-3.4 → kosh-3.5}/kosh/ensemble.py +44 -1
- {kosh-3.4 → kosh-3.5}/kosh/store.py +44 -1
- {kosh-3.4 → kosh-3.5/kosh.egg-info}/PKG-INFO +1 -1
- {kosh-3.4 → kosh-3.5}/kosh.egg-info/SOURCES.txt +12 -0
- {kosh-3.4 → kosh-3.5}/kosh.egg-info/top_level.txt +1 -4
- kosh-3.5/kosh_aml_files/dead/cassandra/__init__.py +1 -0
- kosh-3.5/kosh_aml_files/dead/cassandra/core.py +329 -0
- kosh-3.5/kosh_aml_files/dead/cassandra/init_casandra.py +70 -0
- kosh-3.5/kosh_aml_files/dead/cassandra/models.py +32 -0
- kosh-3.5/kosh_aml_files/dead/tests/cassandra/test_kosh_00.py +2 -0
- kosh-3.5/kosh_aml_files/dead/tests/cassandra/test_kosh_01.py +26 -0
- kosh-3.5/kosh_aml_files/dead/tests/cassandra/test_kosh_02.py +23 -0
- kosh-3.5/kosh_aml_files/dead/tests/cassandra/test_kosh_03.py +8 -0
- kosh-3.5/kosh_aml_files/dead/tests/sina/test_kosh_00.py +5 -0
- kosh-3.5/kosh_aml_files/dead/tests/sina/test_kosh_01.py +22 -0
- kosh-3.5/kosh_aml_files/dead/tests/sina/test_kosh_02.py +27 -0
- kosh-3.5/kosh_aml_files/dead/tests/sina/test_kosh_03.py +15 -0
- kosh-3.4/kosh/current_version.py +0 -1
- {kosh-3.4 → kosh-3.5}/LICENSE +0 -0
- {kosh-3.4 → kosh-3.5}/NOTICE +0 -0
- {kosh-3.4 → kosh-3.5}/README.md +0 -0
- {kosh-3.4 → kosh-3.5}/docs/gen_api_docs.py +0 -0
- {kosh-3.4 → kosh-3.5}/docs/source/conf.py +0 -0
- {kosh-3.4 → kosh-3.5}/examples/cluster.py +0 -0
- {kosh-3.4 → kosh-3.5}/examples/some_user_io_functions.py +0 -0
- {kosh-3.4 → kosh-3.5}/kosh/__init__.py +0 -0
- {kosh-3.4 → kosh-3.5}/kosh/_version.py +0 -0
- {kosh-3.4 → kosh-3.5}/kosh/cli.py +0 -0
- {kosh-3.4 → kosh-3.5}/kosh/core_sina.py +0 -0
- {kosh-3.4 → kosh-3.5}/kosh/exec_graphs/__init__.py +0 -0
- {kosh-3.4 → kosh-3.5}/kosh/exec_graphs/core.py +0 -0
- {kosh-3.4 → kosh-3.5}/kosh/kosh_command.py +0 -0
- {kosh-3.4 → kosh-3.5}/kosh/loaders/UltraLoader.py +0 -0
- {kosh-3.4 → kosh-3.5}/kosh/loaders/__init__.py +0 -0
- {kosh-3.4 → kosh-3.5}/kosh/loaders/core.py +0 -0
- {kosh-3.4 → kosh-3.5}/kosh/loaders/hdf5.py +0 -0
- {kosh-3.4 → kosh-3.5}/kosh/loaders/jsons.py +0 -0
- {kosh-3.4 → kosh-3.5}/kosh/loaders/npy.py +0 -0
- {kosh-3.4 → kosh-3.5}/kosh/loaders/pandas_loader.py +0 -0
- {kosh-3.4 → kosh-3.5}/kosh/loaders/pgm.py +0 -0
- {kosh-3.4 → kosh-3.5}/kosh/loaders/pil.py +0 -0
- {kosh-3.4 → kosh-3.5}/kosh/loaders/sidre.py +0 -0
- {kosh-3.4 → kosh-3.5}/kosh/lock_strategies.py +0 -0
- {kosh-3.4 → kosh-3.5}/kosh/operators/__init__.py +0 -0
- {kosh-3.4 → kosh-3.5}/kosh/operators/core.py +0 -0
- {kosh-3.4 → kosh-3.5}/kosh/operators/koshClustering.py +0 -0
- {kosh-3.4 → kosh-3.5}/kosh/operators/koshMaths.py +0 -0
- {kosh-3.4 → kosh-3.5}/kosh/parameter_store.py +0 -0
- {kosh-3.4 → kosh-3.5}/kosh/sampling_methods/__init__.py +0 -0
- {kosh-3.4 → kosh-3.5}/kosh/sampling_methods/cluster_sampling/Clustering.py +0 -0
- {kosh-3.4 → kosh-3.5}/kosh/sampling_methods/cluster_sampling/__init__.py +0 -0
- {kosh-3.4 → kosh-3.5}/kosh/schema.py +0 -0
- {kosh-3.4 → kosh-3.5}/kosh/skills/kosh/SKILL.md +0 -0
- {kosh-3.4 → kosh-3.5}/kosh/skills/kosh/agents/openai.yaml +0 -0
- {kosh-3.4 → kosh-3.5}/kosh/threadsafe.py +0 -0
- {kosh-3.4 → kosh-3.5}/kosh/threadsafe_decorators.py +0 -0
- {kosh-3.4 → kosh-3.5}/kosh/transformers/__init__.py +0 -0
- {kosh-3.4 → kosh-3.5}/kosh/transformers/core.py +0 -0
- {kosh-3.4 → kosh-3.5}/kosh/transformers/npy.py +0 -0
- {kosh-3.4 → kosh-3.5}/kosh/transformers/sidre.py +0 -0
- {kosh-3.4 → kosh-3.5}/kosh/transformers/skl.py +0 -0
- {kosh-3.4 → kosh-3.5}/kosh/transformers/utils.py +0 -0
- {kosh-3.4 → kosh-3.5}/kosh/utils.py +0 -0
- {kosh-3.4 → kosh-3.5}/kosh/workflow.py +0 -0
- {kosh-3.4 → kosh-3.5}/kosh/wrapper.py +0 -0
- {kosh-3.4 → kosh-3.5}/kosh.egg-info/dependency_links.txt +0 -0
- {kosh-3.4 → kosh-3.5}/kosh.egg-info/entry_points.txt +0 -0
- {kosh-3.4 → kosh-3.5}/kosh.egg-info/requires.txt +0 -0
- {kosh-3.4 → kosh-3.5}/pyproject.toml +0 -0
- {kosh-3.4 → kosh-3.5}/scripts/render_logos.py +0 -0
- {kosh-3.4 → kosh-3.5}/scripts/sbang +0 -0
- {kosh-3.4 → kosh-3.5}/setup.cfg +0 -0
- {kosh-3.4 → kosh-3.5}/setup.py +0 -0
- {kosh-3.4 → kosh-3.5}/tests/baselines/npy/gen.py +0 -0
- {kosh-3.4 → kosh-3.5}/tests/baselines/scripts/dummy.py +0 -0
- {kosh-3.4 → kosh-3.5}/tests/conftest.py +0 -0
- {kosh-3.4 → kosh-3.5}/tests/kosh_scaling.py +0 -0
- {kosh-3.4 → kosh-3.5}/tests/koshbase.py +0 -0
- {kosh-3.4 → kosh-3.5}/tests/non_parallel/test_kosh_cp.py +0 -0
- {kosh-3.4 → kosh-3.5}/tests/parallel/kosh_scaling.py +0 -0
- {kosh-3.4 → kosh-3.5}/tests/parallel/kosh_scaling_pgen.py +0 -0
- {kosh-3.4 → kosh-3.5}/tests/parallel/test_kosh_clustering.py +0 -0
- {kosh-3.4 → kosh-3.5}/tests/parallel/test_kosh_clustering_raw.py +0 -0
- {kosh-3.4 → kosh-3.5}/tests/parallel/test_kosh_mariadb_mpi.py +0 -0
- {kosh-3.4 → kosh-3.5}/tests/parallel/test_kosh_scaling_parallel.py +0 -0
- {kosh-3.4 → kosh-3.5}/tests/test_kosh_aliases.py +0 -0
- {kosh-3.4 → kosh-3.5}/tests/test_kosh_broken_loader.py +0 -0
- {kosh-3.4 → kosh-3.5}/tests/test_kosh_command_line.py +0 -0
- {kosh-3.4 → kosh-3.5}/tests/test_kosh_context_manager.py +0 -0
- {kosh-3.4 → kosh-3.5}/tests/test_kosh_curves.py +0 -0
- {kosh-3.4 → kosh-3.5}/tests/test_kosh_datasets.py +0 -0
- {kosh-3.4 → kosh-3.5}/tests/test_kosh_describe_feature.py +0 -0
- {kosh-3.4 → kosh-3.5}/tests/test_kosh_ensembles.py +0 -0
- {kosh-3.4 → kosh-3.5}/tests/test_kosh_ensembles_cp.py +0 -0
- {kosh-3.4 → kosh-3.5}/tests/test_kosh_fast_load.py +0 -0
- {kosh-3.4 → kosh-3.5}/tests/test_kosh_fix_fastsha.py +0 -0
- {kosh-3.4 → kosh-3.5}/tests/test_kosh_flake8.py +0 -0
- {kosh-3.4 → kosh-3.5}/tests/test_kosh_getitem_back_propagate.py +0 -0
- {kosh-3.4 → kosh-3.5}/tests/test_kosh_import_export_datasets.py +0 -0
- {kosh-3.4 → kosh-3.5}/tests/test_kosh_list_features.py +0 -0
- {kosh-3.4 → kosh-3.5}/tests/test_kosh_load_sina.py +0 -0
- {kosh-3.4 → kosh-3.5}/tests/test_kosh_loaders.py +0 -0
- {kosh-3.4 → kosh-3.5}/tests/test_kosh_loaders_multiple_features_name.py +0 -0
- {kosh-3.4 → kosh-3.5}/tests/test_kosh_lot_big_curves.py +0 -0
- {kosh-3.4 → kosh-3.5}/tests/test_kosh_mv.py +0 -0
- {kosh-3.4 → kosh-3.5}/tests/test_kosh_operators.py +0 -0
- {kosh-3.4 → kosh-3.5}/tests/test_kosh_operators_chain_preprocess.py +0 -0
- {kosh-3.4 → kosh-3.5}/tests/test_kosh_operators_decorators.py +0 -0
- {kosh-3.4 → kosh-3.5}/tests/test_kosh_parameter_store.py +0 -0
- {kosh-3.4 → kosh-3.5}/tests/test_kosh_protected_attributes.py +0 -0
- {kosh-3.4 → kosh-3.5}/tests/test_kosh_reassociate.py +0 -0
- {kosh-3.4 → kosh-3.5}/tests/test_kosh_rm.py +0 -0
- {kosh-3.4 → kosh-3.5}/tests/test_kosh_scaling.py +0 -0
- {kosh-3.4 → kosh-3.5}/tests/test_kosh_schema.py +0 -0
- {kosh-3.4 → kosh-3.5}/tests/test_kosh_script_wrapper.py +0 -0
- {kosh-3.4 → kosh-3.5}/tests/test_kosh_search.py +0 -0
- {kosh-3.4 → kosh-3.5}/tests/test_kosh_search_speed.py +0 -0
- {kosh-3.4 → kosh-3.5}/tests/test_kosh_sina_curves_as_associated.py +0 -0
- {kosh-3.4 → kosh-3.5}/tests/test_kosh_sina_files_section_as_associated.py +0 -0
- {kosh-3.4 → kosh-3.5}/tests/test_kosh_sina_section_for_kosh.py +0 -0
- {kosh-3.4 → kosh-3.5}/tests/test_kosh_skill.py +0 -0
- {kosh-3.4 → kosh-3.5}/tests/test_kosh_skill_codex_smoke.py +0 -0
- {kosh-3.4 → kosh-3.5}/tests/test_kosh_special_sina_types.py +0 -0
- {kosh-3.4 → kosh-3.5}/tests/test_kosh_store.py +0 -0
- {kosh-3.4 → kosh-3.5}/tests/test_kosh_store_custom_loaders.py +0 -0
- {kosh-3.4 → kosh-3.5}/tests/test_kosh_store_mv_cp_tar.py +0 -0
- {kosh-3.4 → kosh-3.5}/tests/test_kosh_sync.py +0 -0
- {kosh-3.4 → kosh-3.5}/tests/test_kosh_transformers.py +0 -0
- {kosh-3.4 → kosh-3.5}/tests/test_kosh_transformers_decorators.py +0 -0
- {kosh-3.4 → kosh-3.5}/tests/test_kosh_transformers_parent.py +0 -0
- {kosh-3.4 → kosh-3.5}/tests/test_kosh_users_and_groups.py +0 -0
- {kosh-3.4 → kosh-3.5}/tests/test_kosh_verbose_list_features.py +0 -0
- {kosh-3.4 → kosh-3.5}/tests/test_kosh_workflow_cli.py +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
current_version = "3.5"
|
|
@@ -1463,7 +1463,7 @@ class KoshDataset(KoshSinaObject):
|
|
|
1463
1463
|
return attributes
|
|
1464
1464
|
|
|
1465
1465
|
@lock_strategies.lock_method
|
|
1466
|
-
def to_dataframe(self, data_columns=[], *atts, **keys):
|
|
1466
|
+
def to_dataframe(self, data_columns=[], typed_columns=None, *atts, **keys):
|
|
1467
1467
|
"""Return the find object as a Pandas DataFrame.
|
|
1468
1468
|
|
|
1469
1469
|
Pass in the same arguments and keyword arguments as the find method.
|
|
@@ -1482,6 +1482,39 @@ class KoshDataset(KoshSinaObject):
|
|
|
1482
1482
|
:param data_columns: Columns to extract. By default this will include ['id', 'mime_type', 'uri', 'associated'].
|
|
1483
1483
|
If nothing is passed, will return all data.
|
|
1484
1484
|
:type data_columns: Union(str, list), optional
|
|
1485
|
+
:param typed_columns: Dictionary of column types and replacement values.
|
|
1486
|
+
If omitted, MySQL defaults are returned.
|
|
1487
|
+
|
|
1488
|
+
Supported types:
|
|
1489
|
+
[
|
|
1490
|
+
"Int8", "Int16", "Int32", "Int64",
|
|
1491
|
+
"UInt8", "UInt16", "UInt32", "UInt64",
|
|
1492
|
+
"float16", "float32", "float64",
|
|
1493
|
+
"Float32", "Float64",
|
|
1494
|
+
"bool", "boolean", "string", "object",
|
|
1495
|
+
"category", "datetime64[ns]", "timedelta64[ns]",
|
|
1496
|
+
]
|
|
1497
|
+
|
|
1498
|
+
Example:
|
|
1499
|
+
{
|
|
1500
|
+
"my_int": {
|
|
1501
|
+
"type": "Int64",
|
|
1502
|
+
"replace": {None: 42},
|
|
1503
|
+
},
|
|
1504
|
+
"my_float": {
|
|
1505
|
+
"type": "float64",
|
|
1506
|
+
"replace": {None: np.nan, 999: -1},
|
|
1507
|
+
},
|
|
1508
|
+
"my_boolean": {
|
|
1509
|
+
"type": "boolean",
|
|
1510
|
+
"replace": {None: False},
|
|
1511
|
+
},
|
|
1512
|
+
"my_string": {
|
|
1513
|
+
"type": "string",
|
|
1514
|
+
"replace": {"This is empty": "Nothing Here"},
|
|
1515
|
+
},
|
|
1516
|
+
}
|
|
1517
|
+
:type typed_columns: dict, optional
|
|
1485
1518
|
:return: Pandas DataFrame
|
|
1486
1519
|
:rtype: Pandas DataFrame
|
|
1487
1520
|
"""
|
|
@@ -1522,4 +1555,14 @@ class KoshDataset(KoshSinaObject):
|
|
|
1522
1555
|
attr_dict[column][i] = source['data'].get(column, {}).get('value', pd.NA)
|
|
1523
1556
|
|
|
1524
1557
|
df = pd.DataFrame(attr_dict)
|
|
1558
|
+
|
|
1559
|
+
if isinstance(typed_columns, dict):
|
|
1560
|
+
for key, config in typed_columns.items():
|
|
1561
|
+
series = df[key]
|
|
1562
|
+
|
|
1563
|
+
if "replace" in config:
|
|
1564
|
+
series = series.replace(config["replace"]).infer_objects(copy=False)
|
|
1565
|
+
|
|
1566
|
+
df[key] = series.astype(config["type"])
|
|
1567
|
+
|
|
1525
1568
|
return df
|
|
@@ -337,7 +337,7 @@ These datasets will inherit attributes and associated sources from the ensemble.
|
|
|
337
337
|
|
|
338
338
|
@lock_strategies.lock_method
|
|
339
339
|
def to_dataframe(self, data_columns=[], include_ensemble_attributes=True, include_ensemble_tags=True,
|
|
340
|
-
*atts, **keys):
|
|
340
|
+
typed_columns=None, *atts, **keys):
|
|
341
341
|
"""Return the find_datasets object as a Pandas DataFrame.
|
|
342
342
|
|
|
343
343
|
Pass in the same arguments and keyword arguments as the find method.
|
|
@@ -362,6 +362,39 @@ These datasets will inherit attributes and associated sources from the ensemble.
|
|
|
362
362
|
:type include_ensemble_attributes: bool, optional
|
|
363
363
|
:param include_ensemble_tags: Include ensemble tags in DataFrame.
|
|
364
364
|
:type include_ensemble_tags: bool, optional
|
|
365
|
+
:param typed_columns: Dictionary of column types and replacement values.
|
|
366
|
+
If omitted, MySQL defaults are returned.
|
|
367
|
+
|
|
368
|
+
Supported types:
|
|
369
|
+
[
|
|
370
|
+
"Int8", "Int16", "Int32", "Int64",
|
|
371
|
+
"UInt8", "UInt16", "UInt32", "UInt64",
|
|
372
|
+
"float16", "float32", "float64",
|
|
373
|
+
"Float32", "Float64",
|
|
374
|
+
"bool", "boolean", "string", "object",
|
|
375
|
+
"category", "datetime64[ns]", "timedelta64[ns]",
|
|
376
|
+
]
|
|
377
|
+
|
|
378
|
+
Example:
|
|
379
|
+
{
|
|
380
|
+
"my_int": {
|
|
381
|
+
"type": "Int64",
|
|
382
|
+
"replace": {None: 42},
|
|
383
|
+
},
|
|
384
|
+
"my_float": {
|
|
385
|
+
"type": "float64",
|
|
386
|
+
"replace": {None: np.nan, 999: -1},
|
|
387
|
+
},
|
|
388
|
+
"my_boolean": {
|
|
389
|
+
"type": "boolean",
|
|
390
|
+
"replace": {None: False},
|
|
391
|
+
},
|
|
392
|
+
"my_string": {
|
|
393
|
+
"type": "string",
|
|
394
|
+
"replace": {"This is empty": "Nothing Here"},
|
|
395
|
+
},
|
|
396
|
+
}
|
|
397
|
+
:type typed_columns: dict, optional
|
|
365
398
|
:return: Pandas DataFrame
|
|
366
399
|
:rtype: Pandas DataFrame
|
|
367
400
|
"""
|
|
@@ -425,4 +458,14 @@ These datasets will inherit attributes and associated sources from the ensemble.
|
|
|
425
458
|
attr_dict[f"{self.id}_ENSEMBLE_ATTRIBUTE_{key}"] = [val] * total_datasets
|
|
426
459
|
|
|
427
460
|
df = pd.DataFrame(attr_dict)
|
|
461
|
+
|
|
462
|
+
if isinstance(typed_columns, dict):
|
|
463
|
+
for key, config in typed_columns.items():
|
|
464
|
+
series = df[key]
|
|
465
|
+
|
|
466
|
+
if "replace" in config:
|
|
467
|
+
series = series.replace(config["replace"]).infer_objects(copy=False)
|
|
468
|
+
|
|
469
|
+
df[key] = series.astype(config["type"])
|
|
470
|
+
|
|
428
471
|
return df
|
|
@@ -2307,7 +2307,7 @@ class KoshStore(object):
|
|
|
2307
2307
|
KoshCmd._tar(self, tar_type, store_args=cmmd, opts=opts)
|
|
2308
2308
|
|
|
2309
2309
|
@lock_strategies.lock_method
|
|
2310
|
-
def to_dataframe(self, data_columns=[], *atts, **keys):
|
|
2310
|
+
def to_dataframe(self, data_columns=[], typed_columns=None, *atts, **keys):
|
|
2311
2311
|
"""Return the find object as a Pandas DataFrame.
|
|
2312
2312
|
|
|
2313
2313
|
Pass in the same arguments and keyword arguments as the find method.
|
|
@@ -2328,6 +2328,39 @@ class KoshStore(object):
|
|
|
2328
2328
|
'creation_date', 'last_modified_date'].
|
|
2329
2329
|
If nothing is passed, will return all data.
|
|
2330
2330
|
:type data_columns: Union(str, list), optional
|
|
2331
|
+
:param typed_columns: Dictionary of column types and replacement values.
|
|
2332
|
+
If omitted, MySQL defaults are returned.
|
|
2333
|
+
|
|
2334
|
+
Supported types:
|
|
2335
|
+
[
|
|
2336
|
+
"Int8", "Int16", "Int32", "Int64",
|
|
2337
|
+
"UInt8", "UInt16", "UInt32", "UInt64",
|
|
2338
|
+
"float16", "float32", "float64",
|
|
2339
|
+
"Float32", "Float64",
|
|
2340
|
+
"bool", "boolean", "string", "object",
|
|
2341
|
+
"category", "datetime64[ns]", "timedelta64[ns]",
|
|
2342
|
+
]
|
|
2343
|
+
|
|
2344
|
+
Example:
|
|
2345
|
+
{
|
|
2346
|
+
"my_int": {
|
|
2347
|
+
"type": "Int64",
|
|
2348
|
+
"replace": {None: 42},
|
|
2349
|
+
},
|
|
2350
|
+
"my_float": {
|
|
2351
|
+
"type": "float64",
|
|
2352
|
+
"replace": {None: np.nan, 999: -1},
|
|
2353
|
+
},
|
|
2354
|
+
"my_boolean": {
|
|
2355
|
+
"type": "boolean",
|
|
2356
|
+
"replace": {None: False},
|
|
2357
|
+
},
|
|
2358
|
+
"my_string": {
|
|
2359
|
+
"type": "string",
|
|
2360
|
+
"replace": {"This is empty": "Nothing Here"},
|
|
2361
|
+
},
|
|
2362
|
+
}
|
|
2363
|
+
:type typed_columns: dict, optional
|
|
2331
2364
|
:return: Pandas DataFrame
|
|
2332
2365
|
:rtype: Pandas DataFrame
|
|
2333
2366
|
"""
|
|
@@ -2365,4 +2398,14 @@ class KoshStore(object):
|
|
|
2365
2398
|
attr_dict[column][i] = dataset['data'].get(column, {}).get('value', pd.NA)
|
|
2366
2399
|
|
|
2367
2400
|
df = pd.DataFrame(attr_dict)
|
|
2401
|
+
|
|
2402
|
+
if isinstance(typed_columns, dict):
|
|
2403
|
+
for key, config in typed_columns.items():
|
|
2404
|
+
series = df[key]
|
|
2405
|
+
|
|
2406
|
+
if "replace" in config:
|
|
2407
|
+
series = series.replace(config["replace"]).infer_objects(copy=False)
|
|
2408
|
+
|
|
2409
|
+
df[key] = series.astype(config["type"])
|
|
2410
|
+
|
|
2368
2411
|
return df
|
|
@@ -57,6 +57,18 @@ kosh/transformers/npy.py
|
|
|
57
57
|
kosh/transformers/sidre.py
|
|
58
58
|
kosh/transformers/skl.py
|
|
59
59
|
kosh/transformers/utils.py
|
|
60
|
+
kosh_aml_files/dead/cassandra/__init__.py
|
|
61
|
+
kosh_aml_files/dead/cassandra/core.py
|
|
62
|
+
kosh_aml_files/dead/cassandra/init_casandra.py
|
|
63
|
+
kosh_aml_files/dead/cassandra/models.py
|
|
64
|
+
kosh_aml_files/dead/tests/cassandra/test_kosh_00.py
|
|
65
|
+
kosh_aml_files/dead/tests/cassandra/test_kosh_01.py
|
|
66
|
+
kosh_aml_files/dead/tests/cassandra/test_kosh_02.py
|
|
67
|
+
kosh_aml_files/dead/tests/cassandra/test_kosh_03.py
|
|
68
|
+
kosh_aml_files/dead/tests/sina/test_kosh_00.py
|
|
69
|
+
kosh_aml_files/dead/tests/sina/test_kosh_01.py
|
|
70
|
+
kosh_aml_files/dead/tests/sina/test_kosh_02.py
|
|
71
|
+
kosh_aml_files/dead/tests/sina/test_kosh_03.py
|
|
60
72
|
scripts/render_logos.py
|
|
61
73
|
scripts/sbang
|
|
62
74
|
tests/conftest.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from .core import KoshStoreCassandra, KoshArrayCassandra, KoshConnect
|
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
# Cassandra implementation
|
|
2
|
+
from kosh.core import KoshStoreClass, KoshDataset, KoshArray
|
|
3
|
+
import cassandra
|
|
4
|
+
from cassandra.cluster import Cluster, Session
|
|
5
|
+
from cassandra.auth import PlainTextAuthProvider
|
|
6
|
+
from cassandra.cqlengine.models import Model
|
|
7
|
+
from cassandra.cqlengine import connection, columns
|
|
8
|
+
from cassandra.cqlengine.management import sync_table
|
|
9
|
+
from cassandra.util import uuid_from_time
|
|
10
|
+
from cassandra.query import BatchStatement, ConsistencyLevel
|
|
11
|
+
from .models import DataSetModel, UsersModel, MetadataModel, types_mapping
|
|
12
|
+
from collections import OrderedDict
|
|
13
|
+
import warnings
|
|
14
|
+
import time
|
|
15
|
+
import uuid
|
|
16
|
+
import numpy
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
types = {"dataset": 0, "array": 1, "image": 2}
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class KoshCassandraObject(object):
|
|
23
|
+
def __init__(self, Id, koshType, protected=[]):
|
|
24
|
+
self.__dict__["__protected__"] = [
|
|
25
|
+
"__id__", "__type__", "__protected__"] + protected
|
|
26
|
+
self.__dict__["__id__"] = Id
|
|
27
|
+
self.__dict__["__type__"] = koshType
|
|
28
|
+
|
|
29
|
+
def __setattr__(self, name, value):
|
|
30
|
+
if name in self.__protected__:
|
|
31
|
+
self.__dict__[name] = value
|
|
32
|
+
return
|
|
33
|
+
exists = MetadataModel.objects(
|
|
34
|
+
id=self.__id__, id_type=self.__type__, name=name)
|
|
35
|
+
if exists.count() != 0:
|
|
36
|
+
# we need to drop it first, replacing
|
|
37
|
+
for e in exists:
|
|
38
|
+
e.delete()
|
|
39
|
+
MetadataModel.create(
|
|
40
|
+
id=self.__id__, id_type=self.__type__, name=name, value=repr(value))
|
|
41
|
+
|
|
42
|
+
def __getattr__(self, name):
|
|
43
|
+
if name in self.__dict__["__protected__"]:
|
|
44
|
+
return self.__dict__.get(name)
|
|
45
|
+
if name == "__attributes__":
|
|
46
|
+
return self.__getattributes__()
|
|
47
|
+
|
|
48
|
+
exists = MetadataModel.objects(
|
|
49
|
+
id=self.__id__, id_type=self.__type__, name=name)
|
|
50
|
+
if exists.count() == 0:
|
|
51
|
+
raise RuntimeError(
|
|
52
|
+
"Object {} does not have {} attribute".format(self.__id__, name))
|
|
53
|
+
return eval(exists[0].value)
|
|
54
|
+
|
|
55
|
+
def __delattr__(self, name):
|
|
56
|
+
if name in self.__protected__:
|
|
57
|
+
return
|
|
58
|
+
exists = MetadataModel.objects(
|
|
59
|
+
id=self.__id__, id_type=self.__type__, name=name)
|
|
60
|
+
if exists.count() == 0:
|
|
61
|
+
raise RuntimeError(
|
|
62
|
+
"Object {} does not have {} attribute".format(self.__id__, name))
|
|
63
|
+
exists[0].delete()
|
|
64
|
+
|
|
65
|
+
def listattributes(self):
|
|
66
|
+
exists = MetadataModel.objects(id=self.__id__, id_type=self.__type__)
|
|
67
|
+
attributes = []
|
|
68
|
+
for e in exists:
|
|
69
|
+
attributes.append(e.name)
|
|
70
|
+
return attributes
|
|
71
|
+
|
|
72
|
+
def __getattributes__(self):
|
|
73
|
+
exists = MetadataModel.objects(id=self.__id__, id_type=self.__type__)
|
|
74
|
+
attributes = {}
|
|
75
|
+
for e in exists:
|
|
76
|
+
attributes[e.name] = eval(e.value)
|
|
77
|
+
return attributes
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
class KoshConnect(object):
|
|
81
|
+
def __init__(self, username, token, keyspace=None, cluster=[
|
|
82
|
+
"sonar8", ], auth_provider=None, cassandraRoot="kosh"):
|
|
83
|
+
# This allows me to have test tables, etc...
|
|
84
|
+
self.__cassandraRoot__ = cassandraRoot
|
|
85
|
+
print("Connecting")
|
|
86
|
+
self.connect(username, token, keyspace, cluster, auth_provider)
|
|
87
|
+
|
|
88
|
+
def connect(self, username, token, keyspace=None,
|
|
89
|
+
cluster_names=["sonar8", ], auth_provider=None):
|
|
90
|
+
""" Connect to a cassandra database """
|
|
91
|
+
from cassandra.cluster import Cluster, Session
|
|
92
|
+
if auth_provider is None:
|
|
93
|
+
print("CREATING AUTH", username, token)
|
|
94
|
+
from cassandra.auth import PlainTextAuthProvider
|
|
95
|
+
auth_provider = PlainTextAuthProvider(
|
|
96
|
+
username=username, password=token)
|
|
97
|
+
|
|
98
|
+
if not isinstance(cluster_names, list):
|
|
99
|
+
cluster_names = [cluster_names, ]
|
|
100
|
+
# print("CLUSTER TO:", cluster_names)
|
|
101
|
+
cluster = Cluster(cluster_names, auth_provider=auth_provider)
|
|
102
|
+
if keyspace is None:
|
|
103
|
+
keyspace = username + "_k"
|
|
104
|
+
# print("KSPACE:", keyspace)
|
|
105
|
+
self.__session__ = cluster.connect(keyspace)
|
|
106
|
+
# print("CONNECTED TO:", self.__session__, auth_provider.username, auth_provider.password)
|
|
107
|
+
self.__username__ = username
|
|
108
|
+
connection.setup(cluster_names, default_keyspace=keyspace,
|
|
109
|
+
auth_provider=auth_provider)
|
|
110
|
+
for obj in [DataSetModel, UsersModel, MetadataModel]:
|
|
111
|
+
obj.__keyspace__ = self.__session__.keyspace
|
|
112
|
+
obj.__table_name__ = "{}_{}".format(
|
|
113
|
+
self.__cassandraRoot__, obj.__table_suffix__)
|
|
114
|
+
sync_table(obj)
|
|
115
|
+
self.__user_id__ = UsersModel.objects(name=self.__username__)[0].id
|
|
116
|
+
# self.prepared = {}
|
|
117
|
+
# self.prepared["datasetids"] = self.session.prepare("SELECT id from {}_datasets".format(self.cassandraRoot))
|
|
118
|
+
# self.prepared["metadata"] = self.session.prepare("SELECT * from {}_metadata where id=? and id_type=?".format(self.cassandraRoot))
|
|
119
|
+
|
|
120
|
+
def __del__(self):
|
|
121
|
+
# when destroying let's shutdown Cassandra cluster
|
|
122
|
+
# print("Shutting down Cassandra Cluster")
|
|
123
|
+
self.__session__.cluster.shutdown()
|
|
124
|
+
del(self.__session__)
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
class KoshArrayCassandra(KoshConnect, KoshCassandraObject, KoshArray):
|
|
128
|
+
def __init__(self, Id, dimensions, username, token, keyspace=None, cluster=[
|
|
129
|
+
"sonar8", ], auth_provider=None, cassandraRoot="kosh"):
|
|
130
|
+
""" Create a Casandra-based array, needs a connection to a cassandra database for metadata
|
|
131
|
+
|
|
132
|
+
Id: can be set to None to indicate new/inexisting array, otherwise point to array to read/extend
|
|
133
|
+
dimensions: ignored if array already exists, otherwise dictionary with dimension names as keys and metadata as dictinoary value
|
|
134
|
+
"""
|
|
135
|
+
if Id is None: # New array?
|
|
136
|
+
Id = uuid.uuid1().hex
|
|
137
|
+
|
|
138
|
+
KoshCassandraObject.__init__(self, Id, types["array"], protected=[
|
|
139
|
+
"__name__", "__creator__", "__type__", "__dims__",
|
|
140
|
+
"__session__", "__username__", "__cassandraRoot__",
|
|
141
|
+
"__table_id__", "__user_id__",
|
|
142
|
+
"__readers__", "__exporters__"])
|
|
143
|
+
|
|
144
|
+
KoshConnect.__init__(
|
|
145
|
+
self,
|
|
146
|
+
username,
|
|
147
|
+
token,
|
|
148
|
+
keyspace,
|
|
149
|
+
cluster,
|
|
150
|
+
auth_provider,
|
|
151
|
+
cassandraRoot)
|
|
152
|
+
|
|
153
|
+
self.__type__ = types["array"]
|
|
154
|
+
# Ok now create associted table, based on dimensions
|
|
155
|
+
self.__table_id__ = "{}_array_{}".format(self.__cassandraRoot__, Id)
|
|
156
|
+
|
|
157
|
+
dims = []
|
|
158
|
+
primary = []
|
|
159
|
+
if isinstance(dimensions, (list, tuple)):
|
|
160
|
+
tmp = OrderedDict()
|
|
161
|
+
for d in dimensions:
|
|
162
|
+
tmp[d] = {}
|
|
163
|
+
dimensions = tmp
|
|
164
|
+
if not isinstance(dimensions, OrderedDict):
|
|
165
|
+
raise RuntimeError("'dimensions' must be list or ordered dict")
|
|
166
|
+
self.__dims__ = dimensions
|
|
167
|
+
for dim in dimensions:
|
|
168
|
+
dim_dict = dimensions[dim]
|
|
169
|
+
dim_type = dim_dict.get("type", "float")
|
|
170
|
+
if dim_dict.get("primary", False):
|
|
171
|
+
primary.append(dim)
|
|
172
|
+
dims += [dim + " " + dim_type]
|
|
173
|
+
if primary == []:
|
|
174
|
+
primary = dimensions.keys()
|
|
175
|
+
tables = self.__session__.cluster.metadata.keyspaces[self.__session__.keyspace].tables
|
|
176
|
+
dims.append("value float")
|
|
177
|
+
if not self.__table_id__ in tables:
|
|
178
|
+
self.__session__.execute("create table {}({}, primary key({}))".format(
|
|
179
|
+
self.__table_id__, ",".join(dims), ",".join(primary)))
|
|
180
|
+
# self.__ArrayModel__ = ArrayModel
|
|
181
|
+
|
|
182
|
+
def load_from_numpy(self, data, offsets=None):
|
|
183
|
+
dims = list(self.__dims__.keys()) + ["value", ]
|
|
184
|
+
print("DIMS:", dims)
|
|
185
|
+
vals = ["?", ] * len(dims)
|
|
186
|
+
ps = self.__session__.prepare(
|
|
187
|
+
"INSERT INTO {} ( {} ) VALUES ( {} )".format(
|
|
188
|
+
self.__table_id__, ",".join(dims), ",".join(vals)))
|
|
189
|
+
# Ok did user send us dimensions values?
|
|
190
|
+
for i, d in enumerate(self.__dims__):
|
|
191
|
+
if self.__dims__[d].get("values", None) is None:
|
|
192
|
+
self.__dims__[d]["values"] = list(range(data.shape[i]))
|
|
193
|
+
|
|
194
|
+
batch = BatchStatement(consistency_level=ConsistencyLevel.QUORUM)
|
|
195
|
+
for i in range(data.size):
|
|
196
|
+
values = list(numpy.unravel_index(i, data.shape))
|
|
197
|
+
values += [float(data.flat[i]), ]
|
|
198
|
+
if data.size < 65535:
|
|
199
|
+
batch.add(ps, values)
|
|
200
|
+
else:
|
|
201
|
+
self.__session__.execute_async(ps, values)
|
|
202
|
+
if data.size < 65535:
|
|
203
|
+
self.__session__.execute_async(batch)
|
|
204
|
+
|
|
205
|
+
def __getitem__(self, *args):
|
|
206
|
+
args = args[0]
|
|
207
|
+
dims = list(self.__dims__.keys())
|
|
208
|
+
values = []
|
|
209
|
+
for i in range(len(args)):
|
|
210
|
+
a = self.__dims__[dims[i]]["values"][args[i]]
|
|
211
|
+
vals = ", ".join([str(_) for _ in a])
|
|
212
|
+
cmd = dims[i] + " IN ( {} )".format(vals)
|
|
213
|
+
values.append(cmd)
|
|
214
|
+
stmnt = "SELECT value FROM " + self.__table_id__ + \
|
|
215
|
+
" WHERE " + " AND ".join(values) + ";"
|
|
216
|
+
return self.__session__.execute(stmnt)
|
|
217
|
+
|
|
218
|
+
def __str__(self):
|
|
219
|
+
st = ""
|
|
220
|
+
st += "KOSH Array\n"
|
|
221
|
+
st += "\tid: {}\n".format(self.__id__)
|
|
222
|
+
st += "\tdimensions:{}\n".format(self.__dims__)
|
|
223
|
+
atts = self.__attributes__
|
|
224
|
+
if len(atts) > 0:
|
|
225
|
+
st += "\n--- Attributes ---\n"
|
|
226
|
+
for a in atts:
|
|
227
|
+
st += "\t{}: {}\n".format(a, atts[a])
|
|
228
|
+
st += "DONE!"
|
|
229
|
+
return st
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
class KoshDatasetCassandra(KoshDataset, KoshCassandraObject):
|
|
233
|
+
def __init__(self, Id):
|
|
234
|
+
KoshCassandraObject.__init__(self, Id, types["dataset"], protected=[
|
|
235
|
+
"__name__", "__creator__"])
|
|
236
|
+
ds = DataSetModel.objects(id=Id)[0] # unique by design
|
|
237
|
+
self.__creator__ = ds.creator
|
|
238
|
+
self.__name__ = ds.name
|
|
239
|
+
|
|
240
|
+
def __str__(self):
|
|
241
|
+
st = ""
|
|
242
|
+
st += "KOSH DATASET\n"
|
|
243
|
+
st += "\tid: {}\n".format(self.__id__)
|
|
244
|
+
st += "\tname:{}\n".format(self.__name__)
|
|
245
|
+
st += "\tcreator: {}\n".format(self.__creator__)
|
|
246
|
+
atts = self.__attributes__
|
|
247
|
+
if len(atts) > 0:
|
|
248
|
+
st += "\n--- Attributes ---\n"
|
|
249
|
+
for a in atts:
|
|
250
|
+
st += "\t{}: {}\n".format(a, atts[a])
|
|
251
|
+
return st
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
class KoshStoreCassandra(KoshConnect, KoshStoreClass):
|
|
255
|
+
def __name_value_search(self, name, value):
|
|
256
|
+
if isinstance(value, str):
|
|
257
|
+
value = "''{}''".format(value)
|
|
258
|
+
values = "(name, id_type, value) = ('{}', {}, '{}' )".format(
|
|
259
|
+
name, types["dataset"], value)
|
|
260
|
+
stmnt = "select id from {}_metadata where {} allow filtering".format(
|
|
261
|
+
self.__cassandraRoot__, values)
|
|
262
|
+
print("STE:", stmnt)
|
|
263
|
+
rows = self.__session__.execute(stmnt)
|
|
264
|
+
return rows
|
|
265
|
+
|
|
266
|
+
def search(self, *atts, **keys):
|
|
267
|
+
""" Search cassandra for datasets matching some metadata
|
|
268
|
+
arguments are the metadata name we are looking for e.g search("attr1", "attr2")
|
|
269
|
+
you can further restrict by specifying exact value for a metadata via key=value
|
|
270
|
+
"""
|
|
271
|
+
no_values = "name in ({}) and id_type={}".format(
|
|
272
|
+
",".join(["'{}'".format(a) for a in atts]), types["dataset"])
|
|
273
|
+
|
|
274
|
+
if len(atts) == 0 and len(keys) == 0:
|
|
275
|
+
raise RuntimeError("You need to pass some search")
|
|
276
|
+
|
|
277
|
+
rows = self.__session__.execute(
|
|
278
|
+
"select id from {}_metadata where {} allow filtering".format(
|
|
279
|
+
self.__cassandraRoot__, no_values))
|
|
280
|
+
ids = set()
|
|
281
|
+
for row in rows:
|
|
282
|
+
ids.add(row.id)
|
|
283
|
+
# Need to "escape quotes"
|
|
284
|
+
for k in keys:
|
|
285
|
+
value = keys[k]
|
|
286
|
+
if not isinstance(value, (list, tuple)):
|
|
287
|
+
value = [value, ]
|
|
288
|
+
rows = []
|
|
289
|
+
for val in value:
|
|
290
|
+
rows += self.__name_value_search(k, val)
|
|
291
|
+
limited = set()
|
|
292
|
+
for row in rows:
|
|
293
|
+
if row.id in ids:
|
|
294
|
+
limited.add(row.id)
|
|
295
|
+
for an_id in list(ids):
|
|
296
|
+
if not an_id in limited:
|
|
297
|
+
ids.remove(an_id)
|
|
298
|
+
|
|
299
|
+
# Return the datasets
|
|
300
|
+
ds = []
|
|
301
|
+
for ds_id in ids:
|
|
302
|
+
ds.append(self.open(ds_id))
|
|
303
|
+
return ds
|
|
304
|
+
|
|
305
|
+
def open(self, id):
|
|
306
|
+
"""Returns a dataset from Cassandra, based on its id"""
|
|
307
|
+
return KoshDatasetCassandra(id)
|
|
308
|
+
|
|
309
|
+
def create(self, name=None, id=None, metadata={}):
|
|
310
|
+
"""create a new (possibly named) dataset"""
|
|
311
|
+
# existingDatasets = self.session.execute_async(self.prepared["datasetids"])
|
|
312
|
+
if id is None:
|
|
313
|
+
if name is None:
|
|
314
|
+
name = "Unnamed Dataset"
|
|
315
|
+
ds = DataSetModel.create(
|
|
316
|
+
id=uuid_from_time(
|
|
317
|
+
time.time()),
|
|
318
|
+
name=name,
|
|
319
|
+
creator=self.__user_id__)
|
|
320
|
+
else:
|
|
321
|
+
ds = DataSetModel.objects(id=id)
|
|
322
|
+
if ds.count() == 0:
|
|
323
|
+
ds = DataSetModel.create(
|
|
324
|
+
id=id, name=name, creator=self.__user_id__)
|
|
325
|
+
else:
|
|
326
|
+
raise RuntimeError(
|
|
327
|
+
"Dataset Id {}, already exists, cannot create duplicate dataset".format(id))
|
|
328
|
+
ds = KoshDatasetCassandra(str(ds.id))
|
|
329
|
+
return ds
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
from cassandra.cluster import Cluster, Session
|
|
5
|
+
from cassandra.auth import PlainTextAuthProvider
|
|
6
|
+
import os
|
|
7
|
+
|
|
8
|
+
parser = argparse.ArgumentParser()
|
|
9
|
+
parser.add_argument("--user", default="cdoutrix", help="username to connect to cassandra")
|
|
10
|
+
parser.add_argument("--token", default=None, help="token to log, will try to read from ${HOME}/.cassandra/cqlshrc")
|
|
11
|
+
parser.add_argument("--keyspace", default=None, help="keyspace, will try to read from ${HOME}/.cassandra/cqlshrc")
|
|
12
|
+
parser.add_argument("--cluster", default="sonar8", help="Cluster")
|
|
13
|
+
parser.add_argument("--tables_root", default="kosh", help="root for tables names")
|
|
14
|
+
args = parser.parse_args()
|
|
15
|
+
|
|
16
|
+
token = args.token
|
|
17
|
+
keyspace = args.keyspace
|
|
18
|
+
with open(os.path.expanduser("~/.cassandra/cqlshrc")) as f:
|
|
19
|
+
lines = f.readlines()
|
|
20
|
+
if token is None:
|
|
21
|
+
token = lines[2].split("=", 0)[-1].strip()
|
|
22
|
+
if keyspace is None:
|
|
23
|
+
keyspace = lines[3].split("=")[1].strip()
|
|
24
|
+
auth_provider = PlainTextAuthProvider(username=args.user, password=token)
|
|
25
|
+
cluster = Cluster(args.cluster.split(),auth_provider=auth_provider, protocol_version=2)
|
|
26
|
+
session = cluster.connect(keyspace)
|
|
27
|
+
|
|
28
|
+
drop_commands = """
|
|
29
|
+
drop table {root}_metadata
|
|
30
|
+
drop table {root}_datasets
|
|
31
|
+
drop table {root}_permissions
|
|
32
|
+
drop table {root}_users
|
|
33
|
+
drop table {root}_targets
|
|
34
|
+
""".format(root=args.tables_root)
|
|
35
|
+
|
|
36
|
+
create_commands = """
|
|
37
|
+
create table {root}_metadata (id timeuuid , id_type int , name text, value text, primary key ((id), name, id_type, value))
|
|
38
|
+
create index on {root}_metadata (name)
|
|
39
|
+
create index on {root}_metadata (value)
|
|
40
|
+
create index on {root}_metadata (id_type)
|
|
41
|
+
create table {root}_datasets (id timeuuid, creator int, name text, primary key (id, creator))
|
|
42
|
+
create table {root}_users(id int, name text, primary key (name, id))
|
|
43
|
+
create table {root}_permissions(user_id int, resource_id text, resource_type int, permission int, primary key (user_id, resource_id, resource_type))
|
|
44
|
+
create table {root}_targets(id timeuuid primary key, source_type int, source_parameters map<text, text>, target_url text)
|
|
45
|
+
insert into {root}_users (id, name) values (0, '{user}')
|
|
46
|
+
""".format(root=args.tables_root, user=args.user)
|
|
47
|
+
for command in drop_commands.split("\n"):
|
|
48
|
+
if len(command)>0:
|
|
49
|
+
print("Executing:", command)
|
|
50
|
+
try:
|
|
51
|
+
session.execute(command)
|
|
52
|
+
except Exception:
|
|
53
|
+
pass
|
|
54
|
+
|
|
55
|
+
# Now drop array tables
|
|
56
|
+
tables = list(cluster.metadata.keyspaces[keyspace].tables.keys())
|
|
57
|
+
for table in tables:
|
|
58
|
+
if table.startswith("{}_array".format(args.tables_root)):
|
|
59
|
+
try:
|
|
60
|
+
session.execute("drop table {}".format(table))
|
|
61
|
+
except Exception as err:
|
|
62
|
+
print("EEROR: ", err)
|
|
63
|
+
pass
|
|
64
|
+
|
|
65
|
+
# Create tables
|
|
66
|
+
for command in create_commands.split("\n"):
|
|
67
|
+
if len(command)>0:
|
|
68
|
+
print("Executing:", command)
|
|
69
|
+
session.execute(command)
|
|
70
|
+
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
from cassandra.cqlengine.models import Model
|
|
2
|
+
from cassandra.cqlengine import columns
|
|
3
|
+
import time
|
|
4
|
+
|
|
5
|
+
types_mapping = {
|
|
6
|
+
"int": columns.Integer,
|
|
7
|
+
"text": columns.Text,
|
|
8
|
+
"uuid": columns.TimeUUID,
|
|
9
|
+
"float": columns.Float,
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class DataSetModel(Model):
|
|
14
|
+
__table_suffix__ = "datasets"
|
|
15
|
+
id = columns.TimeUUID(primary_key=True)
|
|
16
|
+
creator = columns.Integer(required=True, primary_key=True)
|
|
17
|
+
name = columns.Text()
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class UsersModel(Model):
|
|
21
|
+
__table_suffix__ = "users"
|
|
22
|
+
name = columns.Text(primary_key=True, required=True)
|
|
23
|
+
id = columns.Integer(primary_key=True)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class MetadataModel(Model):
|
|
27
|
+
__table_suffix__ = "metadata"
|
|
28
|
+
id = columns.TimeUUID(primary_key=True)
|
|
29
|
+
|
|
30
|
+
name = columns.Text(primary_key=True, required=True)
|
|
31
|
+
id_type = columns.Integer(primary_key=True)
|
|
32
|
+
value = columns.Text(primary_key=True)
|