Skip to content

Commit

Permalink
Resolve conflicts
Browse files Browse the repository at this point in the history
  • Loading branch information
BenjaminCharmes committed Sep 13, 2024
2 parents 9e3c180 + 94e1f46 commit fd81b56
Show file tree
Hide file tree
Showing 45 changed files with 7,710 additions and 570 deletions.
1 change: 1 addition & 0 deletions .docker/app_dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ ARG VUE_APP_LOGO_URL=magic-logo-url
ARG VUE_APP_HOMEPAGE_URL=magic-homepage-url
ARG VUE_APP_EDITABLE_INVENTORY=magic-setting
ARG VUE_APP_WEBSITE_TITLE=magic-title
ARG VUE_APP_QR_CODE_RESOLVER_URL=magic-qr-code-resolver-url

COPY webapp ./
RUN /node_modules/.bin/vue-cli-service build
Expand Down
2 changes: 2 additions & 0 deletions .docker/app_entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ echo " LOGO_URL: ${VUE_APP_LOGO_URL}"
echo " HOMEPAGE_URL: ${VUE_APP_HOMPAGE_URL}"
echo " EDITABLE_INVENTORY: ${VUE_APP_EDITABLE_INVENTORY}"
echo " WEBSITE_TITLE: ${VUE_APP_WEBSITE_TITLE}"
echo " QR_CODE_RESOLVER_URL: ${VUE_APP_QR_CODE_RESOLVER_URL}"
echo ""
echo "Patching..."

Expand All @@ -36,6 +37,7 @@ for file in $ROOT_DIR/js/app.*.js* $ROOT_DIR/*html; do
sed -i "s|magic-homepage-url|${VUE_APP_HOMEPAGE_URL}|g" $file
sed -i "s|magic-setting|${VUE_APP_EDITABLE_INVENTORY}|g" $file
sed -i "s|magic-title|${VUE_APP_WEBSITE_TITLE}|g" $file
sed -i "s|magic-qr-code-resolver-url|${VUE_APP_QR_CODE_RESOLVER_URL}|g" $file
done

echo "Done!"
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ webapp/cypress/videos
#starting material files
greyGroup_chemInventory*

pydatalab/Pipfile


*.sublime-workspace
*.sublime-project
Expand Down
2 changes: 1 addition & 1 deletion INSTALL.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ To make use of this file:
- Detailed instructions for installing `pipenv`, `pip` and Python itself can be found on the [`pipenv` website](https://pipenv.pypa.io/en/latest/install/#installing-pipenv).
- We recommend you install `pipenv` from PyPI (with `pip install pipenv` or `pip install --user pipenv`) for the Python distribution of your choice (in a virtual environment or otherwise). `pipenv` will be used to create its own virtual environment for installation of the `pydatalab` package.
1. Install the `pydatalab` package.
- Navigate to the `pydatalab` folder and run `pipenv install --dev`.
- Navigate to the `pydatalab` folder and run `pipenv sync --dev`.
- The default Python executable on your machine must be 3.10+, otherwise this must be specified explicitly at this point).
- This will create a `pipenv` environment for `pydatalab` and all of its dependencies that is registered within *this folder* only.
- You can remove this environment to start fresh at any time by running `pipenv --rm` from within this directory.
Expand Down
4 changes: 2 additions & 2 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ services:
- VUE_APP_LOGO_URL
- VUE_APP_HOMEPAGE_URL
- VUE_APP_EDITABLE_INVENTORY
- VUE_APP_WEBSITE_TITLE
- VUE_APP_QR_CODE_RESOLVER_URL
ports:
- "8081:8081"

Expand Down Expand Up @@ -94,8 +96,6 @@ services:
restart: unless-stopped
networks:
- backend
ports:
- "27017:27017"

networks:
backend:
Expand Down
13 changes: 0 additions & 13 deletions pydatalab/Pipfile

This file was deleted.

2,913 changes: 2,620 additions & 293 deletions pydatalab/Pipfile.lock

Large diffs are not rendered by default.

21 changes: 11 additions & 10 deletions pydatalab/pydatalab/apps/chat/blocks.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,11 +79,11 @@ class ChatBlock(DataBlock):
"input_cost_usd_per_MTok": 5.00,
"output_cost_usd_per_MTok": 15.00,
},
"gpt-3.5-turbo": {
"name": "gpt-3.5-turbo",
"context_window": 16385,
"input_cost_usd_per_MTok": 1.50,
"output_cost_usd_per_MTok": 2.00,
"gpt-4o-mini": {
"name": "gpt-4o-mini",
"context_window": 128_000,
"input_cost_usd_per_MTok": 0.15,
"output_cost_usd_per_MTok": 0.60,
},
"gpt-4": {
"name": "gpt-4",
Expand Down Expand Up @@ -155,10 +155,11 @@ def render(self):
return

if self.data.get("model") not in self.data.get("available_models", {}):
bad_model = self.data.get("model")
self.data["error_message"] = (
f"Chatblock received an unknown model: {self.data.get('model')}"
f"Chatblock received an unknown or deprecated model: {bad_model}. Reverting to default model {self.defaults['model']}."
)
return
self.data["model"] = self.defaults["model"]

try:
model_name = self.data["model"]
Expand Down Expand Up @@ -237,10 +238,10 @@ def _prepare_item_json_for_chat(self, item_id: str):
item_filenames = {
str(file["immutable_id"]): file["name"] for file in item_info.get("files", [])
}
for block in item_info.get("blocks_obj", {}).values():
block.pop("bokeh_plot_data", None)

block_fields_to_remove = ["item_id", "block_id"]
big_data_keys = ["bokeh_plot_data", "b64_encoded_image"]
for block in item_info.get("blocks_obj", {}).values():
block_fields_to_remove = ["item_id", "block_id", "collection_id"] + big_data_keys
[block.pop(field, None) for field in block_fields_to_remove]

# nmr block fields to remove (need a more general way to do this)
Expand Down
8 changes: 7 additions & 1 deletion pydatalab/pydatalab/routes/v0_1/items.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from typing import Dict, List, Optional, Set, Union

from bson import ObjectId
from flask import Blueprint, jsonify, request
from flask import Blueprint, jsonify, redirect, request
from flask_login import current_user
from pydantic import ValidationError
from pymongo.command_cursor import CommandCursor
Expand Down Expand Up @@ -644,6 +644,9 @@ def get_item_data(
call its render function).
"""
redirect_to_ui = bool(request.args.get("redirect-to-ui", default=False, type=json.loads))
if refcode and redirect_to_ui and CONFIG.APP_URL:
return redirect(f"{CONFIG.APP_URL}/items/{refcode}", code=307)

if item_id:
match = {"item_id": item_id}
Expand Down Expand Up @@ -767,6 +770,9 @@ def get_item_data(
# Must be exported to JSON first to apply the custom pydantic JSON encoders
return_dict = json.loads(doc.json(exclude_unset=True))

if item_id is None:
item_id = return_dict["item_id"]

# create the files_data dictionary keyed by file ObjectId
files_data: Dict[ObjectId, Dict] = {
f["immutable_id"]: f for f in return_dict.get("files") or []
Expand Down
4 changes: 2 additions & 2 deletions pydatalab/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ classifiers = [
"Topic :: Scientific/Engineering",
]

requires-python = ">=3.10"
requires-python = ">= 3.10, < 3.12"

dependencies = [
# Slightly confusing, but git dependencies cannot be included as extra by uv at the moment
Expand Down Expand Up @@ -60,7 +60,7 @@ server = [
"bokeh ~= 2.4, < 3.0",
"Flask ~= 3.0",
"Flask-Login ~= 0.6",
"Flask-Cors ~= 4.0",
"Flask-Cors ~= 5.0",
"Flask-Dance ~= 7.1",
"Flask-PyMongo ~= 2.3",
"Flask-Mail ~= 0.10",
Expand Down
4 changes: 2 additions & 2 deletions pydatalab/requirements/requirements-all-dev.txt
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ contourpy==1.2.1
# via matplotlib
coverage==7.6.1
# via pytest-cov
cryptography==43.0.0
cryptography==43.0.1
# via paramiko
cycler==0.12.1
# via matplotlib
Expand Down Expand Up @@ -106,7 +106,7 @@ flask==3.0.3
# flask-pymongo
flask-compress==1.15
# via datalab-server (pyproject.toml)
flask-cors==4.0.1
flask-cors==5.0.0
# via datalab-server (pyproject.toml)
flask-dance==7.1.0
# via datalab-server (pyproject.toml)
Expand Down
4 changes: 2 additions & 2 deletions pydatalab/requirements/requirements-all.txt
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ cloudpickle==3.0.0
# via dask
contourpy==1.2.1
# via matplotlib
cryptography==43.0.0
cryptography==43.0.1
# via paramiko
cycler==0.12.1
# via matplotlib
Expand Down Expand Up @@ -89,7 +89,7 @@ flask==3.0.3
# flask-pymongo
flask-compress==1.15
# via datalab-server (pyproject.toml)
flask-cors==4.0.1
flask-cors==5.0.0
# via datalab-server (pyproject.toml)
flask-dance==7.1.0
# via datalab-server (pyproject.toml)
Expand Down
13 changes: 13 additions & 0 deletions pydatalab/scripts/pipenv-resync.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/bin/bash

# This script is a hack to keep a pipenv lock synced with our pip-compile files
# It injects dynamic optional dependencies into our pyproject.toml (currently incompatible
# with any non-dynamic dependencies in setuptools 74) and generates the lock file
#

TOP_DIR=$(git rev-parse --show-toplevel)
# Strip comments
sed -i '/^\s&*#/d' $TOP_DIR/pydatalab/requirements/*.txt
cd $TOP_DIR/pydatalab && pipenv install -r requirements/requirements-all.txt && pipenv install -r requirements/requirements-all-dev.txt --dev
# Reset Pipfile, which will now have all deps inlined
cd $TOP_DIR/pydatalab && git checkout requirements
67 changes: 58 additions & 9 deletions pydatalab/tests/server/test_graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,21 @@ def test_simple_graph(admin_client):

child_2 = Sample(
item_id="child_2",
refcode="test:TEST02",
synthesis_constituents=[
Constituent(item={"type": "samples", "item_id": "parent"}, quantity=None),
],
)

child_3 = Sample(
item_id="child_3",
synthesis_constituents=[
Constituent(item={"type": "samples", "item_id": "parent"}, quantity=None),
],
)

child_4 = Sample(
item_id="child_4",
synthesis_constituents=[
Constituent(item={"type": "samples", "item_id": "parent"}, quantity=None),
],
Expand All @@ -45,25 +60,30 @@ def test_simple_graph(admin_client):
cell_format="swagelok",
)

new_samples = [json.loads(d.json()) for d in [parent, child_1, child_2, missing_child, cell]]
new_samples = [
json.loads(d.json())
for d in [parent, child_1, child_2, child_3, child_4, missing_child, cell]
]

response = admin_client.post(
sample_list = admin_client.post(
"/new-samples/",
json={"new_sample_datas": new_samples},
)

assert response.status_code == 207
assert all(d == 201 for d in response.json["http_codes"])
assert sample_list.status_code == 207
assert all(d == 201 for d in sample_list.json["http_codes"])

graph = admin_client.get("/item-graph").json
assert {n["data"]["id"] for n in graph["nodes"]} == {
"parent",
"child_1",
"child_2",
"child_3",
"child_4",
"missing_child",
"abcd-1-2-3",
}
assert len(graph["edges"]) == 4
assert len(graph["edges"]) == 6

response = admin_client.post("/delete-sample/", json={"item_id": "missing_child"})
assert response
Expand All @@ -73,18 +93,20 @@ def test_simple_graph(admin_client):
"parent",
"child_1",
"child_2",
"child_3",
"child_4",
"abcd-1-2-3",
}

assert len(graph["edges"]) == 3
assert len(graph["edges"]) == 5

graph = admin_client.get("/item-graph/child_1").json
assert len(graph["nodes"]) == 2
assert len(graph["edges"]) == 1

graph = admin_client.get("/item-graph/parent").json
assert len(graph["nodes"]) == 4
assert len(graph["edges"]) == 3
assert len(graph["nodes"]) == 6
assert len(graph["edges"]) == 5

collection_id = "testcoll"
collection_json = {
Expand All @@ -107,5 +129,32 @@ def test_simple_graph(admin_client):
assert len(graph["edges"]) == 2

graph = admin_client.get("/item-graph/parent").json
assert len(graph["nodes"]) == 7
assert len(graph["edges"]) == 10

samples = sample_list.json["responses"]

refcode_child_3 = None
refcode_child_4 = None

for item in samples:
if item["item_id"] == "child_3":
refcode_child_3 = item["sample_list_entry"].get("refcode")
elif item["item_id"] == "child_4":
refcode_child_4 = item["sample_list_entry"].get("refcode")

response = admin_client.post(
f"/collections/{collection_id}",
json={"data": {"refcodes": [refcode_child_3, refcode_child_4]}},
)

assert response.status_code == 200
assert response.json["status"] == "success"

graph = admin_client.get(f"/item-graph?collection_id={collection_id}").json
assert len(graph["nodes"]) == 5
assert len(graph["edges"]) == 8
assert len(graph["edges"]) == 4

graph = admin_client.get("/item-graph/parent").json
assert len(graph["nodes"]) == 7
assert len(graph["edges"]) == 14
6 changes: 6 additions & 0 deletions pydatalab/tests/server/test_items.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,19 @@ def test_single_item_endpoints(client, inserted_default_items):
for item in inserted_default_items:
response = client.get(f"/items/{item.refcode}")
assert response.status_code == 200, response.json
assert response.json["item_id"] == item.item_id
assert response.json["item_data"]["item_id"] == item.item_id
assert response.json["status"] == "success"

test_ref = item.refcode.split(":")[1]
response = client.get(f"/items/{test_ref}")
assert response.status_code == 200, response.json
assert response.json["item_id"] == item.item_id
assert response.json["item_data"]["item_id"] == item.item_id
assert response.json["status"] == "success"

response = client.get(f"/get-item-data/{item.item_id}")
assert response.status_code == 200, response.json
assert response.json["status"] == "success"
assert response.json["item_id"] == item.item_id
assert response.json["item_data"]["item_id"] == item.item_id
Loading

0 comments on commit fd81b56

Please sign in to comment.