dsi-workflow 1.2.4__tar.gz → 1.2.6__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.
- {dsi_workflow-1.2.4 → dsi_workflow-1.2.6}/PKG-INFO +1 -1
- dsi_workflow-1.2.6/dsi/_version.py +1 -0
- {dsi_workflow-1.2.4 → dsi_workflow-1.2.6}/dsi/backends/duckdb.py +1 -1
- {dsi_workflow-1.2.4 → dsi_workflow-1.2.6}/dsi/backends/ndp.py +1 -1
- {dsi_workflow-1.2.4 → dsi_workflow-1.2.6}/dsi/backends/osti.py +1 -1
- {dsi_workflow-1.2.4 → dsi_workflow-1.2.6}/dsi/backends/rcsbpdb.py +113 -29
- {dsi_workflow-1.2.4 → dsi_workflow-1.2.6}/dsi/backends/tests/test_rcsbpdb.py +71 -12
- dsi_workflow-1.2.6/dsi/backends/tests/test_zenodo.py +1329 -0
- dsi_workflow-1.2.6/dsi/backends/zenodo.py +1683 -0
- {dsi_workflow-1.2.4 → dsi_workflow-1.2.6}/dsi/core.py +15 -3
- {dsi_workflow-1.2.4 → dsi_workflow-1.2.6}/dsi/dsi.py +152 -14
- {dsi_workflow-1.2.4 → dsi_workflow-1.2.6}/dsi/sync.py +3 -3
- {dsi_workflow-1.2.4 → dsi_workflow-1.2.6}/dsi/tests/test_core.py +1 -1
- {dsi_workflow-1.2.4 → dsi_workflow-1.2.6}/dsi/tests/test_dsi.py +60 -1
- dsi_workflow-1.2.6/dsi/utils/version_control/__init__.py +4 -0
- dsi_workflow-1.2.6/dsi/utils/version_control/__main__.py +5 -0
- dsi_workflow-1.2.6/dsi/utils/version_control/cli.py +109 -0
- dsi_workflow-1.2.6/dsi/utils/version_control/dsi_vcs.py +1193 -0
- dsi_workflow-1.2.6/dsi/utils/version_control/plots/plot-add-commit.py +297 -0
- dsi_workflow-1.2.6/dsi/utils/version_control/plots/plot-commit-diff.py +257 -0
- dsi_workflow-1.2.6/dsi/utils/version_control/repolog/__init__.py +32 -0
- dsi_workflow-1.2.6/dsi/utils/version_control/repolog/chunking.py +538 -0
- dsi_workflow-1.2.6/dsi/utils/version_control/repolog/content_chunking/csv_chunking.py +254 -0
- dsi_workflow-1.2.6/dsi/utils/version_control/repolog/content_chunking/db_chunking.py +176 -0
- dsi_workflow-1.2.6/dsi/utils/version_control/repolog/content_chunking/json_chunking.py +585 -0
- dsi_workflow-1.2.6/dsi/utils/version_control/repolog/content_chunking/npy_chunking.py +298 -0
- dsi_workflow-1.2.6/dsi/utils/version_control/repolog/content_chunking/xlsx_chunking.py +288 -0
- dsi_workflow-1.2.6/dsi/utils/version_control/repolog/content_chunking/xml_chunking.py +372 -0
- dsi_workflow-1.2.6/dsi/utils/version_control/repolog/exceptions.py +40 -0
- dsi_workflow-1.2.6/dsi/utils/version_control/repolog/file_store.py +151 -0
- dsi_workflow-1.2.6/dsi/utils/version_control/repolog/frame_codec.py +147 -0
- dsi_workflow-1.2.6/dsi/utils/version_control/repolog/log_record.py +264 -0
- dsi_workflow-1.2.6/dsi/utils/version_control/repolog/merkle.py +171 -0
- dsi_workflow-1.2.6/dsi/utils/version_control/repolog/repository_log.py +400 -0
- dsi_workflow-1.2.6/dsi/utils/version_control/tests/task1_dsivcs_tests.py +223 -0
- dsi_workflow-1.2.6/dsi/utils/version_control/tests/task1_git_tests.py +176 -0
- dsi_workflow-1.2.6/dsi/utils/version_control/tests/task2_dsivcs_tests.py +484 -0
- dsi_workflow-1.2.6/dsi/utils/version_control/tests/task2_git_tests.py +501 -0
- dsi_workflow-1.2.6/dsi/utils/version_control/tests/task3_dsivcs_tests.py +187 -0
- dsi_workflow-1.2.6/dsi/utils/version_control/tests/task3_git_tests.py +183 -0
- dsi_workflow-1.2.6/dsi/utils/version_control/tests/test_vcs.py +144 -0
- dsi_workflow-1.2.6/dsi/utils/version_control/vcs_db.py +93 -0
- dsi_workflow-1.2.6/dsi/utils/version_control/vcs_metadata_helper.py +551 -0
- {dsi_workflow-1.2.4 → dsi_workflow-1.2.6}/dsi_workflow.egg-info/PKG-INFO +1 -1
- {dsi_workflow-1.2.4 → dsi_workflow-1.2.6}/dsi_workflow.egg-info/SOURCES.txt +31 -0
- dsi_workflow-1.2.6/dsi_workflow.egg-info/entry_points.txt +3 -0
- {dsi_workflow-1.2.4 → dsi_workflow-1.2.6}/pyproject.toml +2 -1
- dsi_workflow-1.2.4/dsi/_version.py +0 -1
- dsi_workflow-1.2.4/dsi_workflow.egg-info/entry_points.txt +0 -2
- {dsi_workflow-1.2.4 → dsi_workflow-1.2.6}/README.rst +0 -0
- {dsi_workflow-1.2.4 → dsi_workflow-1.2.6}/dsi/backends/__init__.py +0 -0
- {dsi_workflow-1.2.4 → dsi_workflow-1.2.6}/dsi/backends/backend.py +0 -0
- {dsi_workflow-1.2.4 → dsi_workflow-1.2.6}/dsi/backends/filesystem.py +0 -0
- {dsi_workflow-1.2.4 → dsi_workflow-1.2.6}/dsi/backends/gufi.py +0 -0
- {dsi_workflow-1.2.4 → dsi_workflow-1.2.6}/dsi/backends/hpss.py +0 -0
- {dsi_workflow-1.2.4 → dsi_workflow-1.2.6}/dsi/backends/oceans11.py +0 -0
- {dsi_workflow-1.2.4 → dsi_workflow-1.2.6}/dsi/backends/sqlalchemy.py +0 -0
- {dsi_workflow-1.2.4 → dsi_workflow-1.2.6}/dsi/backends/sqlite.py +0 -0
- {dsi_workflow-1.2.4 → dsi_workflow-1.2.6}/dsi/backends/tests/test_duckdb.py +0 -0
- {dsi_workflow-1.2.4 → dsi_workflow-1.2.6}/dsi/backends/tests/test_gufi.py +0 -0
- {dsi_workflow-1.2.4 → dsi_workflow-1.2.6}/dsi/backends/tests/test_hpss.py +0 -0
- {dsi_workflow-1.2.4 → dsi_workflow-1.2.6}/dsi/backends/tests/test_ndp.py +0 -0
- {dsi_workflow-1.2.4 → dsi_workflow-1.2.6}/dsi/backends/tests/test_oceans11.py +0 -0
- {dsi_workflow-1.2.4 → dsi_workflow-1.2.6}/dsi/backends/tests/test_osti.py +0 -0
- {dsi_workflow-1.2.4 → dsi_workflow-1.2.6}/dsi/backends/tests/test_sqlalchemy.py +0 -0
- {dsi_workflow-1.2.4 → dsi_workflow-1.2.6}/dsi/backends/tests/test_sqlite.py +0 -0
- {dsi_workflow-1.2.4 → dsi_workflow-1.2.6}/dsi/backends/webserver.py +0 -0
- {dsi_workflow-1.2.4 → dsi_workflow-1.2.6}/dsi/cli.py +0 -0
- {dsi_workflow-1.2.4 → dsi_workflow-1.2.6}/dsi/dsifederated.py +0 -0
- {dsi_workflow-1.2.4 → dsi_workflow-1.2.6}/dsi/plugins/collection_reader.py +0 -0
- {dsi_workflow-1.2.4 → dsi_workflow-1.2.6}/dsi/plugins/dashboard.py +0 -0
- {dsi_workflow-1.2.4 → dsi_workflow-1.2.6}/dsi/plugins/env.py +0 -0
- {dsi_workflow-1.2.4 → dsi_workflow-1.2.6}/dsi/plugins/file_reader.py +0 -0
- {dsi_workflow-1.2.4 → dsi_workflow-1.2.6}/dsi/plugins/file_writer.py +0 -0
- {dsi_workflow-1.2.4 → dsi_workflow-1.2.6}/dsi/plugins/metadata.py +0 -0
- {dsi_workflow-1.2.4 → dsi_workflow-1.2.6}/dsi/plugins/ml_emulator.py +0 -0
- {dsi_workflow-1.2.4 → dsi_workflow-1.2.6}/dsi/plugins/plugin.py +0 -0
- {dsi_workflow-1.2.4 → dsi_workflow-1.2.6}/dsi/plugins/plugin_models.py +0 -0
- {dsi_workflow-1.2.4 → dsi_workflow-1.2.6}/dsi/plugins/tests/test_collection_reader.py +0 -0
- {dsi_workflow-1.2.4 → dsi_workflow-1.2.6}/dsi/plugins/tests/test_env.py +0 -0
- {dsi_workflow-1.2.4 → dsi_workflow-1.2.6}/dsi/plugins/tests/test_file_reader.py +0 -0
- {dsi_workflow-1.2.4 → dsi_workflow-1.2.6}/dsi/plugins/tests/test_file_writer.py +0 -0
- {dsi_workflow-1.2.4 → dsi_workflow-1.2.6}/dsi/plugins/vtk_reader.py +0 -0
- {dsi_workflow-1.2.4 → dsi_workflow-1.2.6}/dsi/utils/__init__.py +0 -0
- {dsi_workflow-1.2.4 → dsi_workflow-1.2.6}/dsi/utils/dsi_utils.py +0 -0
- {dsi_workflow-1.2.4 → dsi_workflow-1.2.6}/dsi/utils/federated/__init__.py +0 -0
- {dsi_workflow-1.2.4 → dsi_workflow-1.2.6}/dsi/utils/federated/federate_datasets.py +0 -0
- {dsi_workflow-1.2.4 → dsi_workflow-1.2.6}/dsi/utils/federation_utils.py +0 -0
- {dsi_workflow-1.2.4 → dsi_workflow-1.2.6}/dsi/utils/git_utils.py +0 -0
- {dsi_workflow-1.2.4 → dsi_workflow-1.2.6}/dsi/utils/hpc_kerberos.py +0 -0
- {dsi_workflow-1.2.4 → dsi_workflow-1.2.6}/dsi/utils/rsync_utils.py +0 -0
- {dsi_workflow-1.2.4 → dsi_workflow-1.2.6}/dsi/utils/s3_utils.py +0 -0
- {dsi_workflow-1.2.4 → dsi_workflow-1.2.6}/dsi/utils/web_utils.py +0 -0
- {dsi_workflow-1.2.4 → dsi_workflow-1.2.6}/dsi_workflow.egg-info/dependency_links.txt +0 -0
- {dsi_workflow-1.2.4 → dsi_workflow-1.2.6}/dsi_workflow.egg-info/requires.txt +0 -0
- {dsi_workflow-1.2.4 → dsi_workflow-1.2.6}/dsi_workflow.egg-info/top_level.txt +0 -0
- {dsi_workflow-1.2.4 → dsi_workflow-1.2.6}/requirements.txt +0 -0
- {dsi_workflow-1.2.4 → dsi_workflow-1.2.6}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dsi-workflow
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.6
|
|
4
4
|
Summary: A Data Science Infrastructure Project
|
|
5
5
|
Author-email: Jesus Pulido <pulido@lanl.gov>, James Ahrens <ahrens@lanl.gov>, Divya Banesh <dbanesh@lanl.gov>, Hugh Greenberg <hng@lanl.gov>, Pascal Grosset <pascalgrosset@lanl.gov>, Vedant Iyer <iyer@lanl.gov>, Benjamin Sims <bsims@lanl.gov>, Terece Turton <tlturton@lanl.gov>
|
|
6
6
|
License-Expression: BSD-3-Clause
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "1.2.6"
|
|
@@ -407,7 +407,7 @@ class DuckDB(Filesystem):
|
|
|
407
407
|
"""
|
|
408
408
|
data = None
|
|
409
409
|
command = query.strip().split(None, 1)[0].lower()
|
|
410
|
-
if command in {"select", "pragma"}:
|
|
410
|
+
if command in {"select", "pragma", "with"}:
|
|
411
411
|
try:
|
|
412
412
|
data = self.cur.execute(query).fetch_df()
|
|
413
413
|
if isVerbose:
|
|
@@ -106,7 +106,7 @@ class NDP(Webserver):
|
|
|
106
106
|
if self.api_key:
|
|
107
107
|
self.headers["Authorization"] = self.api_key
|
|
108
108
|
|
|
109
|
-
# skip data retrieval if only checking connection to
|
|
109
|
+
# skip data retrieval if only checking connection to ndp
|
|
110
110
|
if kwargs.get("only_validate", False):
|
|
111
111
|
return
|
|
112
112
|
|
|
@@ -120,7 +120,7 @@ class OSTI(Webserver):
|
|
|
120
120
|
if self.api_key:
|
|
121
121
|
self.headers["Authorization"] = self.api_key
|
|
122
122
|
|
|
123
|
-
# skip data retrieval if only checking connection to
|
|
123
|
+
# skip data retrieval if only checking connection to osti
|
|
124
124
|
if kwargs.get("only_validate", False):
|
|
125
125
|
return
|
|
126
126
|
|
|
@@ -230,7 +230,7 @@ class RCSBPDB(Webserver):
|
|
|
230
230
|
self.params = params or {}
|
|
231
231
|
self.validate_error_msg = None
|
|
232
232
|
|
|
233
|
-
# skip data retrieval if only checking connection to
|
|
233
|
+
# skip data retrieval if only checking connection to rcsbpdb
|
|
234
234
|
if kwargs.get("only_validate", False):
|
|
235
235
|
return
|
|
236
236
|
|
|
@@ -257,7 +257,7 @@ class RCSBPDB(Webserver):
|
|
|
257
257
|
|
|
258
258
|
if self.validate_on_init and not self.validate_connection():
|
|
259
259
|
self._loaded = False
|
|
260
|
-
raise ConnectionError(self.validate_error_msg or "RCSBPDB connection
|
|
260
|
+
raise ConnectionError(self.validate_error_msg or "Validating RCSBPDB connection failed.")
|
|
261
261
|
|
|
262
262
|
if self.auto_load:
|
|
263
263
|
try:
|
|
@@ -1081,13 +1081,19 @@ class RCSBPDB(Webserver):
|
|
|
1081
1081
|
|
|
1082
1082
|
def get_table(self, table_name: str, dict_return=False):
|
|
1083
1083
|
resolved = self._resolve_table_name(table_name)
|
|
1084
|
+
|
|
1085
|
+
if resolved not in self.schemas:
|
|
1086
|
+
raise ValueError(
|
|
1087
|
+
f"Table '{table_name}' not found. Available tables: {list(self.schemas.keys())}"
|
|
1088
|
+
)
|
|
1089
|
+
|
|
1084
1090
|
table = self.tables.get(resolved, OrderedDict())
|
|
1085
1091
|
|
|
1086
1092
|
if dict_return:
|
|
1087
1093
|
return table
|
|
1088
1094
|
|
|
1089
1095
|
if not table:
|
|
1090
|
-
return pd.DataFrame(columns=self.
|
|
1096
|
+
return pd.DataFrame(columns=self.schemas.get(resolved, []))
|
|
1091
1097
|
|
|
1092
1098
|
return pd.DataFrame(table)
|
|
1093
1099
|
|
|
@@ -1202,10 +1208,56 @@ class RCSBPDB(Webserver):
|
|
|
1202
1208
|
return self.tables
|
|
1203
1209
|
|
|
1204
1210
|
def get_schema(self, table_name: str | None = None):
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1211
|
+
"""
|
|
1212
|
+
Return SQL-style CREATE TABLE schema text.
|
|
1213
|
+
|
|
1214
|
+
Parameters
|
|
1215
|
+
----------
|
|
1216
|
+
table_name : str or None
|
|
1217
|
+
If provided, return schema text for one table.
|
|
1218
|
+
If None, return schema text for all loaded/known tables.
|
|
1219
|
+
"""
|
|
1220
|
+
table_names = [self._resolve_table_name(table_name)] if table_name else list(self.schemas.keys())
|
|
1221
|
+
schema_lines = []
|
|
1222
|
+
|
|
1223
|
+
for name in table_names:
|
|
1224
|
+
if name not in self.schemas:
|
|
1225
|
+
raise ValueError(
|
|
1226
|
+
f"Table '{table_name}' not found. Available tables: {list(self.schemas.keys())}"
|
|
1227
|
+
)
|
|
1228
|
+
|
|
1229
|
+
table = self.tables.get(name, OrderedDict())
|
|
1230
|
+
cols = []
|
|
1231
|
+
|
|
1232
|
+
for col_name in self.schemas[name]:
|
|
1233
|
+
dtype = "TEXT"
|
|
1234
|
+
|
|
1235
|
+
values = table.get(col_name, []) if isinstance(table, dict) else []
|
|
1236
|
+
|
|
1237
|
+
for value in values:
|
|
1238
|
+
if value is None:
|
|
1239
|
+
continue
|
|
1240
|
+
|
|
1241
|
+
if isinstance(value, bool):
|
|
1242
|
+
dtype = "BOOLEAN"
|
|
1243
|
+
elif isinstance(value, int):
|
|
1244
|
+
dtype = "INTEGER"
|
|
1245
|
+
elif isinstance(value, float):
|
|
1246
|
+
dtype = "REAL"
|
|
1247
|
+
|
|
1248
|
+
break
|
|
1249
|
+
|
|
1250
|
+
cols.append(f" {col_name} {dtype}")
|
|
1251
|
+
|
|
1252
|
+
create_stmt = (
|
|
1253
|
+
f"CREATE TABLE {name} (\n"
|
|
1254
|
+
+ ",\n".join(cols)
|
|
1255
|
+
+ "\n);"
|
|
1256
|
+
)
|
|
1257
|
+
|
|
1258
|
+
schema_lines.append(create_stmt)
|
|
1259
|
+
|
|
1260
|
+
return "\n\n".join(schema_lines)
|
|
1209
1261
|
|
|
1210
1262
|
def num_tables(self):
|
|
1211
1263
|
table_count = len(self.tables)
|
|
@@ -1353,16 +1405,25 @@ class RCSBPDB(Webserver):
|
|
|
1353
1405
|
|
|
1354
1406
|
return matches
|
|
1355
1407
|
|
|
1356
|
-
def find_cell(self, query_object, **kwargs):
|
|
1408
|
+
def find_cell(self, query_object, row=True, **kwargs):
|
|
1357
1409
|
"""
|
|
1358
1410
|
Finds all cells that match the given query_object.
|
|
1359
1411
|
|
|
1412
|
+
Parameters
|
|
1413
|
+
----------
|
|
1414
|
+
query_object : Any
|
|
1415
|
+
Value to search for.
|
|
1416
|
+
row : bool, optional
|
|
1417
|
+
If True, return full matching rows.
|
|
1418
|
+
If False, return individual matching cells.
|
|
1419
|
+
|
|
1360
1420
|
Matching behavior:
|
|
1361
1421
|
- Exact match for all data types
|
|
1362
1422
|
- Case-insensitive partial match for strings
|
|
1363
1423
|
- String representation match for complex objects
|
|
1364
1424
|
"""
|
|
1365
1425
|
matches = []
|
|
1426
|
+
seen_rows = set()
|
|
1366
1427
|
|
|
1367
1428
|
is_str_query = isinstance(query_object, str)
|
|
1368
1429
|
query_lower = query_object.lower() if is_str_query else None
|
|
@@ -1374,9 +1435,14 @@ class RCSBPDB(Webserver):
|
|
|
1374
1435
|
cols = list(table_data.keys())
|
|
1375
1436
|
df = pd.DataFrame(table_data)
|
|
1376
1437
|
|
|
1377
|
-
|
|
1438
|
+
if df.empty:
|
|
1439
|
+
continue
|
|
1440
|
+
|
|
1441
|
+
for row_idx, row_data in df.iterrows():
|
|
1442
|
+
row_matched = False
|
|
1443
|
+
|
|
1378
1444
|
for col in cols:
|
|
1379
|
-
cell =
|
|
1445
|
+
cell = row_data[col]
|
|
1380
1446
|
match = False
|
|
1381
1447
|
|
|
1382
1448
|
if (
|
|
@@ -1389,21 +1455,42 @@ class RCSBPDB(Webserver):
|
|
|
1389
1455
|
)
|
|
1390
1456
|
):
|
|
1391
1457
|
match = True
|
|
1392
|
-
|
|
1393
1458
|
elif is_str_query and isinstance(cell, (dict, list, tuple)):
|
|
1394
1459
|
cell_str = str(cell).lower()
|
|
1460
|
+
|
|
1395
1461
|
if query_lower in cell_str:
|
|
1396
1462
|
match = True
|
|
1397
1463
|
|
|
1398
|
-
if match:
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1464
|
+
if not match:
|
|
1465
|
+
continue
|
|
1466
|
+
|
|
1467
|
+
if row:
|
|
1468
|
+
row_matched = True
|
|
1469
|
+
break
|
|
1470
|
+
|
|
1471
|
+
val = ValueObject()
|
|
1472
|
+
val.t_name = table_name
|
|
1473
|
+
val.c_name = [col]
|
|
1474
|
+
val.row_num = int(row_idx)
|
|
1475
|
+
val.value = cell
|
|
1476
|
+
val.type = "cell"
|
|
1477
|
+
matches.append(val)
|
|
1405
1478
|
|
|
1406
|
-
|
|
1479
|
+
if row and row_matched:
|
|
1480
|
+
key = (table_name, int(row_idx))
|
|
1481
|
+
|
|
1482
|
+
if key in seen_rows:
|
|
1483
|
+
continue
|
|
1484
|
+
|
|
1485
|
+
seen_rows.add(key)
|
|
1486
|
+
|
|
1487
|
+
val = ValueObject()
|
|
1488
|
+
val.t_name = table_name
|
|
1489
|
+
val.c_name = cols
|
|
1490
|
+
val.row_num = int(row_idx)
|
|
1491
|
+
val.value = row_data.to_dict()
|
|
1492
|
+
val.type = "row"
|
|
1493
|
+
matches.append(val)
|
|
1407
1494
|
|
|
1408
1495
|
return matches
|
|
1409
1496
|
|
|
@@ -1549,25 +1636,19 @@ class RCSBPDB(Webserver):
|
|
|
1549
1636
|
print(f" - num of rows: {df.shape[0]}")
|
|
1550
1637
|
print()
|
|
1551
1638
|
|
|
1552
|
-
def display(self, table_name
|
|
1639
|
+
def display(self, table_name, num_rows=25, display_cols=None, **kwargs):
|
|
1553
1640
|
"""
|
|
1554
|
-
|
|
1641
|
+
Return a preview DataFrame from a table.
|
|
1555
1642
|
|
|
1556
1643
|
Parameters
|
|
1557
1644
|
----------
|
|
1558
1645
|
table_name : str
|
|
1559
1646
|
Name of the table to display.
|
|
1560
1647
|
num_rows : int, optional
|
|
1561
|
-
Number of rows to
|
|
1648
|
+
Number of rows to return.
|
|
1562
1649
|
display_cols : list[str], optional
|
|
1563
1650
|
Specific columns to display.
|
|
1564
1651
|
"""
|
|
1565
|
-
if table_name is None:
|
|
1566
|
-
raise ValueError(
|
|
1567
|
-
"display() requires a table_name. "
|
|
1568
|
-
f"Available tables: {self.list(True)}"
|
|
1569
|
-
)
|
|
1570
|
-
|
|
1571
1652
|
resolved = self._resolve_table_name(table_name)
|
|
1572
1653
|
|
|
1573
1654
|
if resolved not in self.schemas:
|
|
@@ -1592,7 +1673,10 @@ class RCSBPDB(Webserver):
|
|
|
1592
1673
|
|
|
1593
1674
|
df = df[display_cols]
|
|
1594
1675
|
|
|
1595
|
-
|
|
1676
|
+
if num_rows:
|
|
1677
|
+
df = df.head(num_rows)
|
|
1678
|
+
|
|
1679
|
+
return df
|
|
1596
1680
|
|
|
1597
1681
|
|
|
1598
1682
|
def summary(self, table_name=None, *args, **kwargs):
|
|
@@ -257,9 +257,18 @@ def test_rcsbpdb_classify_usability():
|
|
|
257
257
|
def test_rcsbpdb_initialization_no_auto_load(empty_backend):
|
|
258
258
|
assert empty_backend._loaded is True
|
|
259
259
|
assert empty_backend.list(True) == []
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
260
|
+
|
|
261
|
+
datasets_schema = empty_backend.get_schema("datasets")
|
|
262
|
+
resources_schema = empty_backend.get_schema("resources")
|
|
263
|
+
errors_schema = empty_backend.get_schema("errors")
|
|
264
|
+
|
|
265
|
+
assert isinstance(datasets_schema, str)
|
|
266
|
+
assert isinstance(resources_schema, str)
|
|
267
|
+
assert isinstance(errors_schema, str)
|
|
268
|
+
|
|
269
|
+
assert "CREATE TABLE datasets" in datasets_schema
|
|
270
|
+
assert "CREATE TABLE resources" in resources_schema
|
|
271
|
+
assert "CREATE TABLE errors" in errors_schema
|
|
263
272
|
|
|
264
273
|
|
|
265
274
|
def test_rcsbpdb_initialization_with_identifiers(loaded_backend):
|
|
@@ -406,10 +415,26 @@ def test_rcsbpdb_get_schema(empty_backend):
|
|
|
406
415
|
resource_schema = empty_backend.get_schema("resource")
|
|
407
416
|
error_schema = empty_backend.get_schema("error")
|
|
408
417
|
|
|
409
|
-
assert isinstance(full_schema,
|
|
410
|
-
assert dataset_schema
|
|
411
|
-
assert resource_schema
|
|
412
|
-
assert error_schema
|
|
418
|
+
assert isinstance(full_schema, str)
|
|
419
|
+
assert isinstance(dataset_schema, str)
|
|
420
|
+
assert isinstance(resource_schema, str)
|
|
421
|
+
assert isinstance(error_schema, str)
|
|
422
|
+
|
|
423
|
+
assert "CREATE TABLE datasets" in full_schema
|
|
424
|
+
assert "CREATE TABLE resources" in full_schema
|
|
425
|
+
assert "CREATE TABLE errors" in full_schema
|
|
426
|
+
|
|
427
|
+
assert "CREATE TABLE datasets" in dataset_schema
|
|
428
|
+
assert "dataset_id" in dataset_schema
|
|
429
|
+
assert "doi" in dataset_schema
|
|
430
|
+
|
|
431
|
+
assert "CREATE TABLE resources" in resource_schema
|
|
432
|
+
assert "resource_id" in resource_schema
|
|
433
|
+
assert "download_url" in resource_schema
|
|
434
|
+
|
|
435
|
+
assert "CREATE TABLE errors" in error_schema
|
|
436
|
+
assert "identifier" in error_schema
|
|
437
|
+
assert "status" in error_schema
|
|
413
438
|
|
|
414
439
|
|
|
415
440
|
def test_rcsbpdb_table_name_resolution(empty_backend):
|
|
@@ -582,7 +607,7 @@ def test_rcsbpdb_find_searches_table_column_and_cell_values(loaded_backend):
|
|
|
582
607
|
|
|
583
608
|
assert isinstance(matches, list)
|
|
584
609
|
assert len(matches) >= 1
|
|
585
|
-
assert any(match.type == "
|
|
610
|
+
assert any(match.type == "row" for match in matches)
|
|
586
611
|
assert any(match.t_name == "datasets" for match in matches)
|
|
587
612
|
|
|
588
613
|
|
|
@@ -624,7 +649,7 @@ def test_rcsbpdb_find_cell_matches_value(loaded_backend):
|
|
|
624
649
|
|
|
625
650
|
assert isinstance(matches, list)
|
|
626
651
|
assert len(matches) >= 1
|
|
627
|
-
assert all(match.type == "
|
|
652
|
+
assert all(match.type == "row" for match in matches)
|
|
628
653
|
|
|
629
654
|
dataset_matches = [
|
|
630
655
|
match for match in matches
|
|
@@ -632,8 +657,28 @@ def test_rcsbpdb_find_cell_matches_value(loaded_backend):
|
|
|
632
657
|
]
|
|
633
658
|
|
|
634
659
|
assert len(dataset_matches) >= 1
|
|
635
|
-
assert any(
|
|
660
|
+
assert any(
|
|
661
|
+
match.value["dataset_id"] == "1CBS"
|
|
662
|
+
for match in dataset_matches
|
|
663
|
+
)
|
|
664
|
+
|
|
665
|
+
def test_rcsbpdb_find_cell_cell_type_support(loaded_backend):
|
|
666
|
+
matches = loaded_backend.find_cell("1CBS", row=False)
|
|
667
|
+
|
|
668
|
+
assert isinstance(matches, list)
|
|
669
|
+
assert len(matches) >= 1
|
|
670
|
+
assert all(match.type == "cell" for match in matches)
|
|
636
671
|
|
|
672
|
+
dataset_matches = [
|
|
673
|
+
match for match in matches
|
|
674
|
+
if match.t_name == "datasets"
|
|
675
|
+
]
|
|
676
|
+
|
|
677
|
+
assert len(dataset_matches) >= 1
|
|
678
|
+
assert any(
|
|
679
|
+
match.c_name == ["dataset_id"] and match.value == "1CBS"
|
|
680
|
+
for match in dataset_matches
|
|
681
|
+
)
|
|
637
682
|
|
|
638
683
|
def test_rcsbpdb_find_relation_condition_string(loaded_backend):
|
|
639
684
|
matches = loaded_backend.find_relation("dataset_id = 1CBS")
|
|
@@ -842,11 +887,25 @@ def test_rcsbpdb_summary_single_table(loaded_backend):
|
|
|
842
887
|
assert "dataset_id" in set(summary["column"])
|
|
843
888
|
|
|
844
889
|
|
|
845
|
-
def
|
|
890
|
+
def test_rcsbpdb_display_returns_dataframe(loaded_backend):
|
|
846
891
|
result = loaded_backend.display("datasets", num_rows=1)
|
|
847
892
|
|
|
848
|
-
assert result
|
|
893
|
+
assert isinstance(result, pd.DataFrame)
|
|
894
|
+
assert len(result) == 1
|
|
849
895
|
|
|
896
|
+
def test_rcsbpdb_display_cols(loaded_backend):
|
|
897
|
+
result = loaded_backend.display(
|
|
898
|
+
"datasets",
|
|
899
|
+
num_rows=2,
|
|
900
|
+
display_cols=["dataset_id", "title"],
|
|
901
|
+
)
|
|
902
|
+
|
|
903
|
+
assert isinstance(result, pd.DataFrame)
|
|
904
|
+
assert list(result.columns) == ["dataset_id", "title"]
|
|
905
|
+
|
|
906
|
+
def test_rcsbpdb_display_requires_table_name(loaded_backend):
|
|
907
|
+
with pytest.raises(TypeError):
|
|
908
|
+
loaded_backend.display()
|
|
850
909
|
|
|
851
910
|
def test_rcsbpdb_display_missing_table_raises_value_error(empty_backend):
|
|
852
911
|
with pytest.raises(ValueError):
|