Skip to content

Commit 61fba85

Browse files
committed
Strip potentially heavy ignored keys out of item save from app and API
- Add metadata field for blocks
1 parent 7c08882 commit 61fba85

File tree

8 files changed

+82
-8
lines changed

8 files changed

+82
-8
lines changed

pydatalab/schemas/cell.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,10 @@
242242
"processed_data": {
243243
"title": "Processed Data",
244244
"type": "object"
245+
},
246+
"metadata": {
247+
"title": "Metadata",
248+
"type": "object"
245249
}
246250
},
247251
"required": [

pydatalab/schemas/equipment.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,10 @@
206206
"processed_data": {
207207
"title": "Processed Data",
208208
"type": "object"
209+
},
210+
"metadata": {
211+
"title": "Metadata",
212+
"type": "object"
209213
}
210214
},
211215
"required": [

pydatalab/schemas/sample.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,10 @@
295295
"processed_data": {
296296
"title": "Processed Data",
297297
"type": "object"
298+
},
299+
"metadata": {
300+
"title": "Metadata",
301+
"type": "object"
298302
}
299303
},
300304
"required": [

pydatalab/schemas/startingmaterial.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,10 @@
348348
"processed_data": {
349349
"title": "Processed Data",
350350
"type": "object"
351+
},
352+
"metadata": {
353+
"title": "Metadata",
354+
"type": "object"
351355
}
352356
},
353357
"required": [

pydatalab/src/pydatalab/blocks/base.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,8 @@ def from_web(cls, data: dict):
315315

316316
def update_from_web(self, data: dict):
317317
"""Update the block with validated data received from a web request.
318+
Will strip any fields that are "computed" or otherwise not controllable
319+
by the user.
318320
319321
Parameters:
320322
data: A dictionary of data to update the block with.
@@ -326,7 +328,8 @@ def update_from_web(self, data: dict):
326328
)
327329
self.data.update(
328330
self.block_db_model(**data).dict(
329-
exclude={"bokeh_plot_data", "b64_encoded_image"}, exclude_unset=True
331+
exclude={"processed_data", "metadata", "bokeh_plot_data", "b64_encoded_image"},
332+
exclude_unset=True,
330333
)
331334
)
332335

pydatalab/src/pydatalab/models/blocks.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@ class DataBlockResponse(BaseModel):
4747
processed_data: dict | None = None
4848
"""Any processed data associated with the block, small enough to store."""
4949

50+
metadata: dict | None = None
51+
"""Any metadata associated with the block."""
52+
5053
class Config:
5154
allow_population_by_field_name = True
5255
json_encoders = JSON_ENCODERS

pydatalab/tests/server/test_blocks.py

Lines changed: 49 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,7 @@ def test_xrd_block_lifecycle(admin_client, default_sample_dict):
250250
item_data = response.json["item_data"]
251251
block_data = item_data["blocks_obj"][block_id]
252252
block_data["file_id"] = file_id
253+
block_data["wavelength"] = 2.0
253254

254255
response = admin_client.post(
255256
"/update-block/", json={"block_data": block_data, "save_to_db": True}
@@ -258,16 +259,30 @@ def test_xrd_block_lifecycle(admin_client, default_sample_dict):
258259
web_block = response.json["new_block_data"]
259260
assert "bokeh_plot_data" in web_block
260261
assert "processed_data" in web_block
262+
assert web_block["wavelength"] == 2.0
261263
assert "peak_data" in web_block["processed_data"]
262264
assert "file_id" in web_block
263265
assert web_block["file_id"] == file_id
264266
assert web_block.get("errors") is None
265267

266268
block = XRDBlock.from_web(web_block)
267269
db = block.to_db()
270+
# 'computed' keys should be dropped when loading from web
268271
assert "bokeh_plot_data" not in db
269-
assert "processed_data" in db
270-
assert "peak_data" in db["processed_data"]
272+
assert "processed_data" not in db
273+
assert db["wavelength"] == 2.0
274+
275+
# But they should still be in the database
276+
response = admin_client.get(f"/get-item-data/{sample_id}")
277+
assert response.status_code == 200
278+
279+
item_data = response.json["item_data"]
280+
assert response.json["status"] == "success"
281+
assert "blocks_obj" in item_data
282+
block = item_data["blocks_obj"][block_id]
283+
assert "processed_data" in block
284+
assert "peak_data" in block["processed_data"]
285+
assert block["wavelength"] == 2.0
271286

272287

273288
def test_comment_block_manipulation(admin_client, default_sample_dict, database):
@@ -313,6 +328,7 @@ def test_comment_block_manipulation(admin_client, default_sample_dict, database)
313328
# Check that this result was actually stored
314329
response = admin_client.get(f"/get-item-data/{sample_id}")
315330
assert response.status_code == 200
331+
item_data = response.json["item_data"]
316332
assert response.json["status"] == "success"
317333
assert (
318334
response.json["item_data"]["blocks_obj"][block_id]["freeform_comment"]
@@ -323,20 +339,46 @@ def test_comment_block_manipulation(admin_client, default_sample_dict, database)
323339
# Try to add some bad data
324340
block_data["bokeh_plot_data"] = {"bokeh": "json"}
325341
block_data["random_new_key"] = "test new key"
342+
block_data["freeform_comment"] = "This is a test comment block with extra data."
326343
response = admin_client.post("/update-block/", json={"block_data": block_data})
327344
assert response.status_code == 200
328345
assert response.json["status"] == "success"
329346
assert response.json["new_block_data"]["blocktype"] == block_type
330-
assert response.json["new_block_data"]["freeform_comment"] == "This is a test comment block."
347+
assert (
348+
response.json["new_block_data"]["freeform_comment"]
349+
== "This is a test comment block with extra data."
350+
)
331351
assert response.json["new_block_data"]["title"] == "Test Comment Block"
332352
assert "bokeh_plot_data" not in response.json["new_block_data"]
333-
assert "random_new_key" not in response.json["new_block_data"]
353+
354+
# Extra random keys will be in the response (in case they are parameters for the block that are not yet handled,
355+
# but they will not be stored in the database)
356+
assert "random_new_key" in response.json["new_block_data"]
334357

335358
raw_item = database.items.find_one({"item_id": sample_id})
336359
assert raw_item
337-
assert "bokeh_plot_data" not in raw_item
338-
assert "random_new_key" not in raw_item
339-
assert "errors" not in raw_item
360+
raw_block = raw_item["blocks_obj"][block_id]
361+
assert "bokeh_plot_data" not in raw_block
362+
# assert "random_new_key" not in raw_block
363+
assert "errors" not in raw_block
364+
365+
# Finally, try to update using the save-item endpoint, and make sure any bad data gets stripped out
366+
item_data["blocks_obj"][block_id]["bokeh_plot_data"] = {"bokeh": "json"}
367+
item_data["blocks_obj"][block_id]["random_new_key"] = "test new key again"
368+
item_data["blocks_obj"][block_id]["freeform_comment"] = "This is the latest test comment."
369+
370+
admin_client.post("/save-item/", json={"item_id": sample_id, "data": item_data})
371+
assert response.status_code == 200
372+
373+
response = admin_client.get(f"/get-item-data/{sample_id}")
374+
assert response.status_code == 200
375+
assert response.json["status"] == "success"
376+
item_data = response.json["item_data"]
377+
block = item_data["blocks_obj"][block_id]
378+
379+
assert block["freeform_comment"] == "This is the latest test comment."
380+
assert block.get("bokeh_plot_data") is None
381+
assert block["random_new_key"] == "test new key again"
340382

341383

342384
@pytest.mark.parametrize(

webapp/src/server_fetch_utils.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -576,6 +576,16 @@ export function saveItem(item_id) {
576576
var item_data = store.state.all_item_data[item_id];
577577
console.log("Item data before saving:", item_data);
578578

579+
// Strip large data from blocks before saving
580+
if (item_data.blocks_obj) {
581+
for (const block_id in item_data.blocks_obj) {
582+
const block = item_data.blocks_obj[block_id];
583+
block.bokeh_plot_data = null;
584+
block.processed_data = null;
585+
block.metadata = null;
586+
}
587+
}
588+
579589
store.commit("setItemSaved", { item_id: item_id, isSaved: false });
580590
fetch_post(`${API_URL}/save-item/`, {
581591
item_id: item_id,

0 commit comments

Comments
 (0)