From 100da1fbedf537312d0928ee6c22c3ed626be898 Mon Sep 17 00:00:00 2001
From: PE39806 <185931318+PE39806@users.noreply.github.com>
Date: Tue, 10 Dec 2024 15:40:55 +0000
Subject: [PATCH 1/4] BAI-1545 remove unused team and teams endpoints
---
backend/docs/README.md | 5 +-
.../docs/notebooks/access_requests_demo.ipynb | 2 +-
backend/docs/notebooks/datacards_demo.ipynb | 4 +-
.../notebooks/experiment_tracking_demo.ipynb | 2 +-
.../models_and_releases_demo_pytorch.ipynb | 6 +-
lib/python/README.md | 22 +++--
lib/python/src/bailo/core/client.py | 81 -------------------
lib/python/src/bailo/helper/__init__.py | 1 -
lib/python/src/bailo/helper/datacard.py | 3 -
lib/python/src/bailo/helper/model.py | 6 --
lib/python/src/bailo/helper/release.py | 1 -
lib/python/tests/conftest.py | 1 -
lib/python/tests/test_client.py | 55 -------------
lib/python/tests/test_datacard.py | 11 +--
lib/python/tests/test_model.py | 17 +---
15 files changed, 32 insertions(+), 185 deletions(-)
diff --git a/backend/docs/README.md b/backend/docs/README.md
index 0f5235bf1..ae3ac5d4d 100644
--- a/backend/docs/README.md
+++ b/backend/docs/README.md
@@ -51,8 +51,7 @@ client = Client("http://localhost:8080")
yolo = Model.create(
client=client,
name="YoloV4",
- description="You only look once!",
- team_id="Uncategorised"
+ description="You only look once!"
)
yolo.card_from_schema("minimal-general-v10-beta")
@@ -68,7 +67,7 @@ with open("yolo.onnx") as f:
## Documentation
-Documenation is rendered with Sphinx and served [here](https://gchq.github.io/Bailo/docs/python/index.html).
+Documentation is rendered with Sphinx and served [here](https://gchq.github.io/Bailo/docs/python/index.html).
### Building locally
diff --git a/backend/docs/notebooks/access_requests_demo.ipynb b/backend/docs/notebooks/access_requests_demo.ipynb
index 8ba5b485f..ea46d9e01 100644
--- a/backend/docs/notebooks/access_requests_demo.ipynb
+++ b/backend/docs/notebooks/access_requests_demo.ipynb
@@ -87,7 +87,7 @@
"metadata": {},
"outputs": [],
"source": [
- "model = Model.create(client=client, name=\"YOLOv5\", description=\"YOLOv5 model for object detection.\", team_id=\"uncategorised\")\n",
+ "model = Model.create(client=client, name=\"YOLOv5\", description=\"YOLOv5 model for object detection.\")\n",
"model_id = model.model_id\n",
"\n",
"metadata = {\"overview\": {\"entities\": [\"user\"], \"name\": \"test\", \"endDate\": \"1970-01-01\"}}\n",
diff --git a/backend/docs/notebooks/datacards_demo.ipynb b/backend/docs/notebooks/datacards_demo.ipynb
index a16a4c089..178b8267c 100644
--- a/backend/docs/notebooks/datacards_demo.ipynb
+++ b/backend/docs/notebooks/datacards_demo.ipynb
@@ -74,7 +74,7 @@
"\n",
"### Creating and updating the base datacard\n",
"\n",
- "In this section, we'll create a new datacard using the `Datacard.create()` classmethod. On the Bailo service, a datacard must consist of at least 4 parameters upon creation. These are **name**, **description**, **visibility** and **team_id**. Below, we use the `Client()` object created before when instantiating the new `Datacard()` object. \n",
+ "In this section, we'll create a new datacard using the `Datacard.create()` classmethod. On the Bailo service, a datacard must consist of at least 4 parameters upon creation. These are **name**, **description** and **visibility**. Below, we use the `Client()` object created before when instantiating the new `Datacard()` object. \n",
"\n",
"NOTE: This creates the datacard on your Bailo service too! The `datacard_id` is assigned by the backend, and we will use this later to retrieve the datacard. *Like with models on Bailo, the actual datacard has not been populated at this stage.*"
]
@@ -85,7 +85,7 @@
"metadata": {},
"outputs": [],
"source": [
- "datacard = Datacard.create(client=client, name=\"ImageNet\", description=\"ImageNet dataset consisting of images.\", team_id=\"uncategorised\")\n",
+ "datacard = Datacard.create(client=client, name=\"ImageNet\", description=\"ImageNet dataset consisting of images.\")\n",
"\n",
"datacard_id = datacard.datacard_id"
]
diff --git a/backend/docs/notebooks/experiment_tracking_demo.ipynb b/backend/docs/notebooks/experiment_tracking_demo.ipynb
index 4d6028355..7b4c2da80 100644
--- a/backend/docs/notebooks/experiment_tracking_demo.ipynb
+++ b/backend/docs/notebooks/experiment_tracking_demo.ipynb
@@ -69,7 +69,7 @@
"\n",
"# Creating a demo model\n",
"\n",
- "model = Model.create(client=client, name=\"YOLOv5\", description=\"YOLOv5 model for object detection.\", team_id=\"uncategorised\")"
+ "model = Model.create(client=client, name=\"YOLOv5\", description=\"YOLOv5 model for object detection.\")"
]
},
{
diff --git a/backend/docs/notebooks/models_and_releases_demo_pytorch.ipynb b/backend/docs/notebooks/models_and_releases_demo_pytorch.ipynb
index 03827e9d2..da94e4819 100644
--- a/backend/docs/notebooks/models_and_releases_demo_pytorch.ipynb
+++ b/backend/docs/notebooks/models_and_releases_demo_pytorch.ipynb
@@ -91,7 +91,7 @@
"\n",
"### Creating and updating the base model\n",
"\n",
- "In this section, we'll create a new model representing ResNet-50 using the `Model.create()` classmethod. On the Bailo service, a model must consist of at least 4 parameters upon creation. These are **name**, **description**, **visibility** and **team_id**. Other attributes like model cards, files, or releases are added later on. Below, we use the `Client()` object created before when instantiating the new `Model()` object. \n",
+ "In this section, we'll create a new model representing ResNet-50 using the `Model.create()` classmethod. On the Bailo service, a model must consist of at least 4 parameters upon creation. These are **name**, **description** and **visibility**. Other attributes like model cards, files, or releases are added later on. Below, we use the `Client()` object created before when instantiating the new `Model()` object. \n",
"\n",
"NOTE: This creates the model on your Bailo service too! The `model_id` is assigned by the backend, and we will use this later to retrieve the model."
]
@@ -102,7 +102,7 @@
"metadata": {},
"outputs": [],
"source": [
- "model = Model.create(client=client, name=\"ResNet-50\", description=\"ResNet-50 model for image classification.\", team_id=\"uncategorised\")\n",
+ "model = Model.create(client=client, name=\"ResNet-50\", description=\"ResNet-50 model for image classification.\")\n",
"\n",
"model_id = model.model_id"
]
@@ -163,7 +163,7 @@
"outputs": [],
"source": [
"model2 = Model.create(\n",
- " client=client, name=\"ResNet-50\", description=\"ResNet-50 model for image classification.\", team_id=\"uncategorised\"\n",
+ " client=client, name=\"ResNet-50\", description=\"ResNet-50 model for image classification.\"\n",
")\n",
"\n",
"model2_id = model2.model_id\n",
diff --git a/lib/python/README.md b/lib/python/README.md
index d08e411d3..69bb5b164 100644
--- a/lib/python/README.md
+++ b/lib/python/README.md
@@ -17,10 +17,22 @@ A simple Python API Wrapper for Bailo
Getting Started
+
+ Documentation
+
+
Development
@@ -35,7 +47,8 @@ A simple Python API Wrapper for Bailo
## Installing
-**Python 3.8.1 or higher is required**
+> [!IMPORTANT]
+> Python 3.8.1 or higher is required
```bash
pip install bailo
@@ -51,8 +64,7 @@ client = Client("http://localhost:8080")
yolo = Model.create(
client=client,
name="YoloV4",
- description="You only look once!",
- team_id="Uncategorised"
+ description="You only look once!"
)
yolo.card_from_schema("minimal-general-v10")
@@ -68,7 +80,7 @@ with open("yolo.onnx") as f:
## Documentation
-Documenation is rendered with Sphinx and served [here](https://gchq.github.io/Bailo/docs/python/index.html).
+Documentation is rendered with Sphinx and served [here](https://gchq.github.io/Bailo/docs/python/index.html).
### Building locally
diff --git a/lib/python/src/bailo/core/client.py b/lib/python/src/bailo/core/client.py
index b3056935d..1b442b09f 100644
--- a/lib/python/src/bailo/core/client.py
+++ b/lib/python/src/bailo/core/client.py
@@ -24,7 +24,6 @@ def post_model(
name: str,
kind: EntryKind,
description: str,
- team_id: str,
visibility: ModelVisibility | None = None,
):
"""Create a model.
@@ -536,86 +535,6 @@ def get_model_user_roles(
f"{self.url}/v2/model/{model_id}/roles/mine",
).json()
- def post_team(
- self,
- team_id: str,
- name: str,
- description: str,
- ):
- """
- Create new team.
-
- :param team_id: Unique team ID
- :param name: Team name
- :param description: Team description
- :return: JSON response object
- """
- return self.agent.post(
- f"{self.url}/v2/teams",
- json={
- "id": team_id,
- "name": name,
- "description": description,
- },
- ).json()
-
- def get_all_teams(
- self,
- ):
- """
- Get all teams.
-
- :return: JSON response object
- """
- return self.agent.get(
- f"{self.url}/v2/teams",
- ).json()
-
- def get_user_teams(
- self,
- ):
- """
- Get user teams.
-
- :return: JSON response object
- """
- return self.agent.get(
- f"{self.url}/v2/teams/mine",
- ).json()
-
- def get_team(
- self,
- team_id: str,
- ):
- """Retrieve a specific team given its unique ID.
-
- :param team_id: Unique team ID
- :return: JSON response object
- """
- return self.agent.get(
- f"{self.url}/v2/team/{team_id}",
- ).json()
-
- def patch_team(
- self,
- team_id: str,
- name: str | None = None,
- description: str | None = None,
- ):
- """Update a team given its unique ID.
-
- :param team_id: Unique team ID
- :param name: Name of team, defaults to None
- :param description: Description of team, defaults to None
- :return: JSON response object
- """
- filtered_json = filter_none({"name": name, "description": description})
-
- return self.agent.patch(
- f"{self.url}/v2/team/{team_id}",
- json=filtered_json,
- ).json()
-
def get_access_request(self, model_id: str, access_request_id: str):
"""Retrieve a specific access request given its unique ID.
diff --git a/lib/python/src/bailo/helper/__init__.py b/lib/python/src/bailo/helper/__init__.py
index bc75f96ec..438de8d5f 100644
--- a/lib/python/src/bailo/helper/__init__.py
+++ b/lib/python/src/bailo/helper/__init__.py
@@ -17,6 +17,5 @@
client=client,
name="YoloV4",
description="You only look once!",
- team_id="Uncategorised"
)
"""
diff --git a/lib/python/src/bailo/helper/datacard.py b/lib/python/src/bailo/helper/datacard.py
index 723eaa482..1c3dd0f36 100644
--- a/lib/python/src/bailo/helper/datacard.py
+++ b/lib/python/src/bailo/helper/datacard.py
@@ -46,7 +46,6 @@ def create(
client: Client,
name: str,
description: str,
- team_id: str,
visibility: ModelVisibility | None = None,
) -> Datacard:
"""Build a datacard from Bailo and upload it.
@@ -54,7 +53,6 @@ def create(
:param client: A client object used to interact with Bailo
:param name: Name of datacard
:param description: Description of datacard
- :param team_id: A unique team ID
:param visibility: Visibility of datacard, using ModelVisibility enum (e.g Public or Private), defaults to None
:return: Datacard object
"""
@@ -62,7 +60,6 @@ def create(
name=name,
kind=EntryKind.DATACARD,
description=description,
- team_id=team_id,
visibility=visibility,
)
datacard_id = res["model"]["id"]
diff --git a/lib/python/src/bailo/helper/model.py b/lib/python/src/bailo/helper/model.py
index 9d1b9dfd6..d36db37d5 100644
--- a/lib/python/src/bailo/helper/model.py
+++ b/lib/python/src/bailo/helper/model.py
@@ -60,7 +60,6 @@ def create(
client: Client,
name: str,
description: str,
- team_id: str,
visibility: ModelVisibility | None = None,
) -> Model:
"""Build a model from Bailo and upload it.
@@ -68,7 +67,6 @@ def create(
:param client: A client object used to interact with Bailo
:param name: Name of model
:param description: Description of model
- :param team_id: A unique team ID
:param visibility: Visibility of model, using ModelVisibility enum (e.g Public or Private), defaults to None
:return: Model object
"""
@@ -76,7 +74,6 @@ def create(
name=name,
kind=EntryKind.MODEL,
description=description,
- team_id=team_id,
visibility=visibility,
)
model_id = res["model"]["id"]
@@ -160,7 +157,6 @@ def from_mlflow(
cls,
client: Client,
mlflow_uri: str,
- team_id: str,
name: str,
schema_id: str = MinimalSchema.MODEL,
version: str | None = None,
@@ -171,7 +167,6 @@ def from_mlflow(
:param client: A client object used to interact with Bailo
:param mlflow_uri: MLFlow server URI
- :param team_id: A unique team ID
:param name: Name of model (on MLFlow). Same name will be used on Bailo
:param schema_id: A unique schema ID, only required when files is True, defaults to minimal-general-v10
:param version: Specific MLFlow model version to import, defaults to None
@@ -207,7 +202,6 @@ def from_mlflow(
name=name,
kind=EntryKind.MODEL,
description=description,
- team_id=team_id,
visibility=visibility,
)
model_id = bailo_res["model"]["id"]
diff --git a/lib/python/src/bailo/helper/release.py b/lib/python/src/bailo/helper/release.py
index fc5af4d3c..652cf36b9 100644
--- a/lib/python/src/bailo/helper/release.py
+++ b/lib/python/src/bailo/helper/release.py
@@ -62,7 +62,6 @@ def __init__(
self.files = files
self.images = images
self.draft = draft
- self.files = files
@classmethod
def create(
diff --git a/lib/python/tests/conftest.py b/lib/python/tests/conftest.py
index 8b71d6ed5..85dfeefae 100644
--- a/lib/python/tests/conftest.py
+++ b/lib/python/tests/conftest.py
@@ -37,7 +37,6 @@ def example_model(integration_client, metrics_schema):
client=integration_client,
name="Yolo-v4",
description="You only look once!",
- team_id="team_id",
visibility=ModelVisibility.PUBLIC,
)
model.card_from_schema(metrics_schema.schema_id)
diff --git a/lib/python/tests/test_client.py b/lib/python/tests/test_client.py
index 52a822e58..0067a84b2 100644
--- a/lib/python/tests/test_client.py
+++ b/lib/python/tests/test_client.py
@@ -17,7 +17,6 @@ def test_post_model(requests_mock):
kind=EntryKind.MODEL,
description="test",
visibility=ModelVisibility.PUBLIC,
- team_id="uncategorised",
)
assert result == {"success": True}
@@ -244,60 +243,6 @@ def test_get_model_user_roles(requests_mock):
assert result == {"success": True}
-def test_post_team(requests_mock):
- requests_mock.post("https://example.com/api/v2/teams", json={"success": True})
-
- client = Client("https://example.com")
- result = client.post_team(
- team_id="test_id",
- name="test",
- description="test",
- )
-
- assert result == {"success": True}
-
-
-def test_get_all_teams(requests_mock):
- requests_mock.get("https://example.com/api/v2/teams", json={"success": True})
-
- client = Client("https://example.com")
- result = client.get_all_teams()
-
- assert result == {"success": True}
-
-
-def test_get_user_teams(requests_mock):
- requests_mock.get("https://example.com/api/v2/teams/mine", json={"success": True})
-
- client = Client("https://example.com")
- result = client.get_user_teams()
-
- assert result == {"success": True}
-
-
-def test_get_team(requests_mock):
- requests_mock.get("https://example.com/api/v2/team/test_id", json={"success": True})
-
- client = Client("https://example.com")
- result = client.get_team(
- team_id="test_id",
- )
-
- assert result == {"success": True}
-
-
-def test_patch_team(requests_mock):
- requests_mock.patch("https://example.com/api/v2/team/test_id", json={"success": True})
-
- client = Client("https://example.com")
- result = client.patch_team(
- team_id="test_id",
- name="name",
- )
-
- assert result == {"success": True}
-
-
def test_get_access_request(requests_mock):
requests_mock.get(
"https://example.com/api/v2/model/test_id/access-request/test_id",
diff --git a/lib/python/tests/test_datacard.py b/lib/python/tests/test_datacard.py
index 4505dc60f..cf978b2ab 100644
--- a/lib/python/tests/test_datacard.py
+++ b/lib/python/tests/test_datacard.py
@@ -11,16 +11,15 @@ def test_datacard(local_datacard):
@pytest.mark.integration
@pytest.mark.parametrize(
- ("name", "description", "team_id", "visibility"),
+ ("name", "description", "visibility"),
[
- ("test-datacard", "test", "Uncategorised", ModelVisibility.PUBLIC),
- ("test-datacard", "test", "Uncategorised", None),
+ ("test-datacard", "test", ModelVisibility.PUBLIC),
+ ("test-datacard", "test", None),
],
)
def test_create_get_from_id_and_update(
name: str,
description: str,
- team_id: str,
visibility: ModelVisibility | None,
integration_client: Client,
):
@@ -29,7 +28,6 @@ def test_create_get_from_id_and_update(
client=integration_client,
name=name,
description=description,
- team_id=team_id,
visibility=visibility,
)
datacard.card_from_schema("minimal-data-card-v10")
@@ -52,7 +50,6 @@ def test_get_and_update_latest_data_card(integration_client):
client=integration_client,
name="test-datacard",
description="test",
- team_id="Uncategorised",
visibility=ModelVisibility.PUBLIC,
)
@@ -69,7 +66,6 @@ def get_data_card_without_creation(integration_client):
client=integration_client,
name="test-datacard",
description="test",
- team_id="Uncategorised",
visibility=ModelVisibility.PUBLIC,
)
datacard.card_from_schema("minimal-data-card-v10")
@@ -84,7 +80,6 @@ def test_get_model_as_datacard(integration_client):
client=integration_client,
name="test-model",
description="test",
- team_id="Uncategorised",
visibility=ModelVisibility.PUBLIC,
)
diff --git a/lib/python/tests/test_model.py b/lib/python/tests/test_model.py
index 3c001810f..b6e3d22f9 100644
--- a/lib/python/tests/test_model.py
+++ b/lib/python/tests/test_model.py
@@ -18,16 +18,15 @@ def test_create_experiment_from_model(local_model):
@pytest.mark.integration
@pytest.mark.parametrize(
- ("name", "description", "team_id", "visibility"),
+ ("name", "description", "visibility"),
[
- ("test-model", "test", "Uncategorised", ModelVisibility.PUBLIC),
- ("test-model", "test", "Uncategorised", None),
+ ("test-model", "test", ModelVisibility.PUBLIC),
+ ("test-model", "test", None),
],
)
def test_create_get_from_id_and_update(
name: str,
description: str,
- team_id: str,
visibility: ModelVisibility | None,
integration_client: Client,
):
@@ -36,7 +35,6 @@ def test_create_get_from_id_and_update(
client=integration_client,
name=name,
description=description,
- team_id=team_id,
visibility=visibility,
)
model.card_from_schema("minimal-general-v10")
@@ -73,7 +71,6 @@ def test_get_and_update_latest_model_card(integration_client):
client=integration_client,
name="test-model",
description="test",
- team_id="Uncategorised",
visibility=ModelVisibility.PUBLIC,
)
@@ -90,7 +87,6 @@ def get_model_card_without_creation(integration_client):
client=integration_client,
name="test-model",
description="test",
- team_id="Uncategorised",
visibility=ModelVisibility.PUBLIC,
)
model.card_from_schema("minimal-general-v10")
@@ -105,7 +101,6 @@ def test_get_releases(integration_client):
client=integration_client,
name="test-model",
description="test",
- team_id="Uncategorised",
visibility=ModelVisibility.PUBLIC,
)
model.card_from_schema("minimal-general-v10")
@@ -128,7 +123,6 @@ def test_create_release_without_model_card(integration_client):
client=integration_client,
name="test-model",
description="test",
- team_id="Uncategorised",
visibility=ModelVisibility.PUBLIC,
)
@@ -142,7 +136,6 @@ def test_get_datacard_as_model(integration_client):
client=integration_client,
name="test-datacard",
description="test",
- team_id="Uncategorised",
visibility=ModelVisibility.PUBLIC,
)
@@ -190,7 +183,6 @@ def test_import_model_from_mlflow(integration_client, mlflow_model, request):
model = Model.from_mlflow(
client=integration_client,
mlflow_uri=request.config.mlflow_uri,
- team_id="Uncategorised",
schema_id="minimal-general-v10",
name=mlflow_model,
)
@@ -205,7 +197,6 @@ def test_import_nonexistent_model_from_mlflow(integration_client, request):
model = Model.from_mlflow(
client=integration_client,
mlflow_uri=request.config.mlflow_uri,
- team_id="Uncategorised",
schema_id="minimal-general-v10",
name="fake-model-name",
)
@@ -217,7 +208,6 @@ def test_import_model_files_no_run(integration_client, mlflow_model_no_run, requ
model = Model.from_mlflow(
client=integration_client,
mlflow_uri=request.config.mlflow_uri,
- team_id="Uncategorised",
schema_id="minimal-general-v10",
name=mlflow_model_no_run,
)
@@ -229,7 +219,6 @@ def test_import_model_no_schema(integration_client, mlflow_model, request):
model = Model.from_mlflow(
client=integration_client,
mlflow_uri=request.config.mlflow_uri,
- team_id="Uncategorised",
name=mlflow_model,
)
From 7a7af17d420d395efcf03a09e3d3663493dd0b3a Mon Sep 17 00:00:00 2001
From: PE39806 <185931318+PE39806@users.noreply.github.com>
Date: Tue, 10 Dec 2024 16:06:38 +0000
Subject: [PATCH 2/4] BAI-1545 improve READMEs and spelling
---
backend/docs/README.md | 100 ++++--------------
.../notebooks/experiment_tracking_demo.ipynb | 2 +-
.../models_and_releases_demo_pytorch.ipynb | 4 +-
lib/python/README.md | 21 +---
lib/python/src/bailo/core/client.py | 2 +-
lib/python/src/bailo/helper/entry.py | 12 ++-
lib/python/src/bailo/helper/model.py | 12 +--
lib/python/src/bailo/helper/release.py | 10 +-
8 files changed, 47 insertions(+), 116 deletions(-)
diff --git a/backend/docs/README.md b/backend/docs/README.md
index ae3ac5d4d..d85ca54b9 100644
--- a/backend/docs/README.md
+++ b/backend/docs/README.md
@@ -1,6 +1,6 @@
-# Bailo Python Client
+# Bailo Python Client Documentation
-A simple Python API Wrapper for Bailo
+The documentation for [a simple Python API Wrapper for Bailo](lib/python/README.md)
@@ -9,19 +9,15 @@ A simple Python API Wrapper for Bailo
Table of Contents
-
- Key Features
-
- -
- Installing
-
- -
- Getting Started
-
- -
- Development
+ Documentation
@@ -29,81 +25,27 @@ A simple Python API Wrapper for Bailo
-## Key Features
-
-- Uploading and downloading model binaries
-
-## Installing
-
-**Python 3.8.1 or higher is required**
-
-```bash
-pip install bailo
-```
-
-## Getting Started
-
-```python
-from bailo import Client, Model
-client = Client("http://localhost:8080")
-
-# Create a model
-yolo = Model.create(
- client=client,
- name="YoloV4",
- description="You only look once!"
-)
-
-yolo.card_from_schema("minimal-general-v10-beta")
-
-# Create a new release
-my_release = yolo.create_release(version="0.1.0",
- notes="Beta")
-
-# Upload a file to the release
-with open("yolo.onnx") as f:
- my_release.upload("yolo", f)
-```
-
## Documentation
Documentation is rendered with Sphinx and served [here](https://gchq.github.io/Bailo/docs/python/index.html).
### Building locally
-From the docs directory run either `make html` or `make.bat` on Windows. This will build it in the backend directory by
-default.
-
-## Development
-
-### Install and add precommit
-
-If already working on Bailo you may be prompted to overwrite Husky. Follow the instructions given by Git CLI.
-
-```bash
-pip install pre-commit
-pre-commit install
-```
-
-### Install the package locally
-
-```bash
-pip install -e .
-```
-
-### Testing
+
+> [!IMPORTANT]
+> Python 3.8.1 or higher is required
+
-The package uses Pytest to test packages. Tests can be ran accordingly from within this directory. Tests are split into
-categories sections for automation purposes.
+#### Prerequisites
-In order to run integration tests make sure Bailo is running on `https://localhost:8080`:
+From within the `backend/docs` directory:
```bash
-pytest -m integration
+pip install bailo -r requirements.txt
+apt install -y pandoc
```
-Run all other tests:
+#### Building
-```bash
-pytest
-```
+From the docs directory run either `make html` (Linux & Mac) or `make.bat` (Windows). This will build it in the backend
+directory by default.
diff --git a/backend/docs/notebooks/experiment_tracking_demo.ipynb b/backend/docs/notebooks/experiment_tracking_demo.ipynb
index 7b4c2da80..92858ea8b 100644
--- a/backend/docs/notebooks/experiment_tracking_demo.ipynb
+++ b/backend/docs/notebooks/experiment_tracking_demo.ipynb
@@ -218,7 +218,7 @@
"source": [
"## Importing existing experiments from MLFlow into Bailo\n",
"\n",
- "As previously mentioned, you can import existing experiments into the `Experiment()` class by using the `Experiment.from_mlflow()` method. You must provide the **MLFlow tracking URI** and the experiment ID. To get the experiement ID, go to the link provided in the cell \"Creating a dummy MLFlow experiment run\". In the details section you will see \"Experiment ID\", copy this ID and add it to the argument **experiment_id**. ![image.png](img/experiment_id.png)"
+ "As previously mentioned, you can import existing experiments into the `Experiment()` class by using the `Experiment.from_mlflow()` method. You must provide the **MLFlow tracking URI** and the experiment ID. To get the experiment ID, go to the link provided in the cell \"Creating a dummy MLFlow experiment run\". In the details section you will see \"Experiment ID\", copy this ID and add it to the argument **experiment_id**. ![image.png](img/experiment_id.png)"
]
},
{
diff --git a/backend/docs/notebooks/models_and_releases_demo_pytorch.ipynb b/backend/docs/notebooks/models_and_releases_demo_pytorch.ipynb
index da94e4819..6dbedc9a2 100644
--- a/backend/docs/notebooks/models_and_releases_demo_pytorch.ipynb
+++ b/backend/docs/notebooks/models_and_releases_demo_pytorch.ipynb
@@ -151,7 +151,7 @@
"\n",
"### Creating and populated a new model card with a template\n",
"\n",
- "When creating a model card from a template, we need to use a preexisting model card as our template. First we create a new model, to create the new model card we use the `card_from_template` method and pass our chosen template model's ID. \n",
+ "When creating a model card from a template, we need to use a pre-existing model card as our template. First we create a new model, to create the new model card we use the `card_from_template` method and pass our chosen template model's ID. \n",
"\n",
"\n"
]
@@ -378,7 +378,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "If the message \"**All keys matched successfully**\" is displayed, we have successfully initated our model."
+ "If the message \"**All keys matched successfully**\" is displayed, we have successfully initiated our model."
]
},
{
diff --git a/lib/python/README.md b/lib/python/README.md
index 69bb5b164..a2bb0adc6 100644
--- a/lib/python/README.md
+++ b/lib/python/README.md
@@ -20,12 +20,7 @@ A simple Python API Wrapper for Bailo
Documentation
@@ -47,8 +42,10 @@ A simple Python API Wrapper for Bailo
## Installing
+
> [!IMPORTANT]
> Python 3.8.1 or higher is required
+
```bash
pip install bailo
@@ -84,17 +81,7 @@ Documentation is rendered with Sphinx and served [here](https://gchq.github.io/B
### Building locally
-#### prerequisites
-
-From within the `backend/docs` directory:
-
-```bash
-pip install bailo -r requirements.txt
-apt install -y pandoc
-```
-
-From the docs directory run either `make html` or `make.bat` on Windows. This will build it in the backend directory by
-default.
+Refer to [backend/docs/README.md](backend/docs/README.md) for local build steps.
## Development
diff --git a/lib/python/src/bailo/core/client.py b/lib/python/src/bailo/core/client.py
index 1b442b09f..120c2aa29 100644
--- a/lib/python/src/bailo/core/client.py
+++ b/lib/python/src/bailo/core/client.py
@@ -179,7 +179,7 @@ def model_card_from_schema(
def model_card_from_template(self, model_id: str, template_id: str | None):
"""Create a model card using a given template ID (previously created models, model ID)
:param model_id: Unique model ID
- :param tempate_id Previous model's unique ID to be used as template for new model card
+ :param template_id Previous model's unique ID to be used as template for new model card
:return: JSON response object
"""
return self.agent.post(
diff --git a/lib/python/src/bailo/helper/entry.py b/lib/python/src/bailo/helper/entry.py
index 93f468d4a..185b247d3 100644
--- a/lib/python/src/bailo/helper/entry.py
+++ b/lib/python/src/bailo/helper/entry.py
@@ -1,11 +1,11 @@
from __future__ import annotations
-from typing import Any
import logging
import warnings
+from typing import Any
from bailo.core.client import Client
-from bailo.core.enums import EntryKind, ModelVisibility, MinimalSchema
+from bailo.core.enums import EntryKind, MinimalSchema, ModelVisibility
logger = logging.getLogger(__name__)
@@ -17,7 +17,7 @@ class Entry:
:param id: A unique ID for the entry
:param name: Name of the entry
:param description: Description of the entry
- :param visibility: Visibility of model, using ModelVisiblility enum (i.e. Public or Private), defaults to None
+ :param visibility: Visibility of model, using ModelVisibility enum (i.e. Public or Private), defaults to None
:param kind: Represents whether entry type (i.e. Model or Datacard)
"""
@@ -55,7 +55,7 @@ def update(self) -> None:
logger.info(f"ID %s updated locally and on server.", self.id)
- def card_from_schema(self, schema_id: str) -> None:
+ def card_from_schema(self, schema_id: str | None = None) -> None:
"""Create a card using a schema on Bailo.
:param schema_id: A unique schema ID, defaults to None. If None, either minimal-general-v10 or minimal-data-card-v10 is used
@@ -63,8 +63,10 @@ def card_from_schema(self, schema_id: str) -> None:
if schema_id is None:
if self.kind == EntryKind.MODEL:
schema_id = MinimalSchema.MODEL
- if self.kind == EntryKind.DATACARD:
+ elif self.kind == EntryKind.DATACARD:
schema_id = MinimalSchema.DATACARD
+ else:
+ raise NotImplementedError(f"No default schema set for {self.kind=}")
res = self.client.model_card_from_schema(model_id=self.id, schema_id=schema_id)
self.__unpack_card(res["card"])
diff --git a/lib/python/src/bailo/helper/model.py b/lib/python/src/bailo/helper/model.py
index d36db37d5..305b8a466 100644
--- a/lib/python/src/bailo/helper/model.py
+++ b/lib/python/src/bailo/helper/model.py
@@ -1,14 +1,14 @@
from __future__ import annotations
+import logging
import os
import shutil
import tempfile
-from typing import Any
-import logging
import warnings
+from typing import Any
from bailo.core.client import Client
-from bailo.core.enums import EntryKind, ModelVisibility, MinimalSchema
+from bailo.core.enums import EntryKind, MinimalSchema, ModelVisibility
from bailo.core.exceptions import BailoException
from bailo.core.utils import NestedDict
from bailo.helper.entry import Entry
@@ -222,13 +222,13 @@ def from_mlflow(
run_id = sel_model.run_id
if run_id is None:
raise BailoException(
- "MLFlow model does not have an assosciated run_id, therefore artifacts cannot be transfered."
+ "MLFlow model does not have an associated run_id, therefore artifacts cannot be transferred."
)
mlflow_run = mlflow_client.get_run(run_id)
artifact_uri: str = str(mlflow_run.info.artifact_uri)
if artifact_uri is None:
- raise BailoException("Artifact URI could not be found, therefore artifacts cannot be transfered.")
+ raise BailoException("Artifact URI could not be found, therefore artifacts cannot be transferred.")
if mlflow.artifacts.list_artifacts(artifact_uri=artifact_uri) is not None:
temp_dir = os.path.join(tempfile.gettempdir(), "mlflow_model")
@@ -336,7 +336,7 @@ def get_images(self):
"""
res = self.client.get_all_images(model_id=self.model_id)
- logger.info(f"Images for %s retreived successfully.", self.model_id)
+ logger.info(f"Images for %s retrieved successfully.", self.model_id)
return res["images"]
diff --git a/lib/python/src/bailo/helper/release.py b/lib/python/src/bailo/helper/release.py
index 652cf36b9..21af74b60 100644
--- a/lib/python/src/bailo/helper/release.py
+++ b/lib/python/src/bailo/helper/release.py
@@ -1,18 +1,18 @@
from __future__ import annotations
-import os
import fnmatch
+import logging
+import os
import shutil
from io import BytesIO
from typing import Any
-import logging
-from tqdm import tqdm
-from tqdm.utils import CallbackIOWrapper
from bailo.core.client import Client
from bailo.core.exceptions import BailoException
from bailo.core.utils import NO_COLOR
from semantic_version import Version
+from tqdm import tqdm
+from tqdm.utils import CallbackIOWrapper
BLOCK_SIZE = 1024
logger = logging.getLogger(__name__)
@@ -266,7 +266,7 @@ def upload(self, path: str, data: BytesIO | None = None) -> str: # type: ignore
# If no datastream object provided
name = os.path.split(path)[-1]
if data is None:
- # If we havent passed in a file object, we must create one from the path.
+ # If we haven't passed in a file object, we must create one from the path.
# Check if file exists, if it does the zip required
zip_required = not os.path.isfile(path)
From 05228ad1bad0c70a186069df4305525ced8699e5 Mon Sep 17 00:00:00 2001
From: PE39806 <185931318+PE39806@users.noreply.github.com>
Date: Tue, 10 Dec 2024 16:10:20 +0000
Subject: [PATCH 3/4] BAI-1545 correct README links
---
backend/docs/README.md | 2 +-
lib/python/README.md | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/backend/docs/README.md b/backend/docs/README.md
index d85ca54b9..13d56c845 100644
--- a/backend/docs/README.md
+++ b/backend/docs/README.md
@@ -1,6 +1,6 @@
# Bailo Python Client Documentation
-The documentation for [a simple Python API Wrapper for Bailo](lib/python/README.md)
+The documentation for [a simple Python API Wrapper for Bailo](../../lib/python/README.md)
diff --git a/lib/python/README.md b/lib/python/README.md
index a2bb0adc6..33207a877 100644
--- a/lib/python/README.md
+++ b/lib/python/README.md
@@ -81,7 +81,7 @@ Documentation is rendered with Sphinx and served [here](https://gchq.github.io/B
### Building locally
-Refer to [backend/docs/README.md](backend/docs/README.md) for local build steps.
+Refer to [backend/docs/README.md](../../backend/docs/README.md) for local build steps.
## Development
From b38b663f2907ecac059b82e5a187d2b53878fd0c Mon Sep 17 00:00:00 2001
From: PE39806 <185931318+PE39806@users.noreply.github.com>
Date: Wed, 11 Dec 2024 16:25:36 +0000
Subject: [PATCH 4/4] BAI-1545 improve grammar
---
.../docs/notebooks/access_requests_demo.ipynb | 4 +-
backend/docs/notebooks/datacards_demo.ipynb | 6 +-
.../notebooks/experiment_tracking_demo.ipynb | 8 +-
.../models_and_releases_demo_pytorch.ipynb | 10 +-
backend/docs/notebooks/schemas_demo.ipynb | 390 +++++++++---------
5 files changed, 209 insertions(+), 209 deletions(-)
diff --git a/backend/docs/notebooks/access_requests_demo.ipynb b/backend/docs/notebooks/access_requests_demo.ipynb
index ea46d9e01..9574736a1 100644
--- a/backend/docs/notebooks/access_requests_demo.ipynb
+++ b/backend/docs/notebooks/access_requests_demo.ipynb
@@ -78,7 +78,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "In this section, we'll create a new access request using the `AccessRequest.create()` classmethod. On the Bailo service, an access request must consist of at least 3 parameters upon creation. These are **model_id**, **schema_id** and **metadata**. Below, we use the `Client()` object created before when instantiating the new `AccessRequest()` object. We'll also need to create a new model on the service, which our access request will be for."
+ "In this section, we will create a new access request using the `AccessRequest.create()` classmethod. On the Bailo service, an access request must consist of at least 3 parameters upon creation. These are **model_id**, **schema_id** and **metadata**. Below, we use the `Client()` object created before when instantiating the new `AccessRequest()` object. We will also need to create a new model on the service, which our access request will be for."
]
},
{
@@ -117,7 +117,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "In this section, we'll retrieve our previous access request using the `AccessRequest.from_id()` classmethod. This will create your `AccessRequest()` object as before, but using existing information retrieved from the service."
+ "In this section, we will retrieve our previous access request using the `AccessRequest.from_id()` classmethod. This will create your `AccessRequest()` object as before, but using existing information retrieved from the service."
]
},
{
diff --git a/backend/docs/notebooks/datacards_demo.ipynb b/backend/docs/notebooks/datacards_demo.ipynb
index 178b8267c..7ae0ad8d2 100644
--- a/backend/docs/notebooks/datacards_demo.ipynb
+++ b/backend/docs/notebooks/datacards_demo.ipynb
@@ -74,7 +74,7 @@
"\n",
"### Creating and updating the base datacard\n",
"\n",
- "In this section, we'll create a new datacard using the `Datacard.create()` classmethod. On the Bailo service, a datacard must consist of at least 4 parameters upon creation. These are **name**, **description** and **visibility**. Below, we use the `Client()` object created before when instantiating the new `Datacard()` object. \n",
+ "In this section, we will create a new datacard using the `Datacard.create()` classmethod. On the Bailo service, a datacard must consist of at least 4 parameters upon creation. These are **name**, **description** and **visibility**. Below, we use the `Client()` object created before when instantiating the new `Datacard()` object. \n",
"\n",
"NOTE: This creates the datacard on your Bailo service too! The `datacard_id` is assigned by the backend, and we will use this later to retrieve the datacard. *Like with models on Bailo, the actual datacard has not been populated at this stage.*"
]
@@ -131,7 +131,7 @@
"source": [
"If successful, the above will have created a new datacard, and the `data_card_version` attribute should be set to 1.\n",
"\n",
- "Next, we can populate the data using the `update_data_card()` method. This can be used any time you want to make changes, and the backend will create a new datacard version each time. We'll learn how to retrieve datacards later (either the latest, or a specific release).\n",
+ "Next, we can populate the data using the `update_data_card()` method. This can be used any time you want to make changes, and the backend will create a new datacard version each time. We will learn how to retrieve datacards later (either the latest, or a specific release).\n",
"\n",
"NOTE: Your datacard must match the schema, otherwise an error will be thrown."
]
@@ -170,7 +170,7 @@
"\n",
"### Using the .from_id() method\n",
"\n",
- "In this section, we'll retrieve our previous datacard using the `Datacard.from_id()` classmethod. This will create your `Datacard()` object as before, but using existing information retrieved from the service."
+ "In this section, we will retrieve our previous datacard using the `Datacard.from_id()` classmethod. This will create your `Datacard()` object as before, but using existing information retrieved from the service."
]
},
{
diff --git a/backend/docs/notebooks/experiment_tracking_demo.ipynb b/backend/docs/notebooks/experiment_tracking_demo.ipynb
index 92858ea8b..0ac109e77 100644
--- a/backend/docs/notebooks/experiment_tracking_demo.ipynb
+++ b/backend/docs/notebooks/experiment_tracking_demo.ipynb
@@ -38,7 +38,7 @@
"\n",
"### Connecting with Bailo\n",
"\n",
- "In order to create an `Experiment()` object, you'll first need to have a Bailo `Model()` object, and thus a defined `Client()` too. We learned how to do this in a previous notebook, but this time we'll create a new model with a custom schema which supports model metrics. *More on that later...*"
+ "In order to create an `Experiment()` object, you'll first need to have a Bailo `Model()` object, and thus a defined `Client()` too. We learned how to do this in a previous notebook, but this time we will create a new model with a custom schema which supports model metrics. *More on that later...*"
]
},
{
@@ -79,7 +79,7 @@
"source": [
"### Setting up MLFlow Tracking\n",
"\n",
- "In order to complete the integration element of this tutorial, we'll need to set up a local instance of MLFlow Tracking, and create a sample experiment run. *This will not contain any actual model training and is only to demonstrate the functionality of Bailo.*\n",
+ "In order to complete the integration element of this tutorial, we will need to set up a local instance of MLFlow Tracking, and create a sample experiment run. *This will not contain any actual model training and is only to demonstrate the functionality of Bailo.*\n",
"\n",
"Run `mlflow ui` on the command line. Typically this will run on **localhost:5000** and the UI can be accessed on a browser"
]
@@ -156,7 +156,7 @@
"\n",
"You can run experiments directly using the Bailo python client as follows.\n",
"\n",
- "**NOTE**: This will only work for sequential experiment runs, so if you're running experiments in parallel then it would be better to use **MLFlow Tracking**. We'll learn how to import completed experiments from MLFlow in the next section."
+ "**NOTE**: This will only work for sequential experiment runs, so if you're running experiments in parallel then it would be better to use **MLFlow Tracking**. We will learn how to import completed experiments from MLFlow in the next section."
]
},
{
@@ -218,7 +218,7 @@
"source": [
"## Importing existing experiments from MLFlow into Bailo\n",
"\n",
- "As previously mentioned, you can import existing experiments into the `Experiment()` class by using the `Experiment.from_mlflow()` method. You must provide the **MLFlow tracking URI** and the experiment ID. To get the experiment ID, go to the link provided in the cell \"Creating a dummy MLFlow experiment run\". In the details section you will see \"Experiment ID\", copy this ID and add it to the argument **experiment_id**. ![image.png](img/experiment_id.png)"
+ "You can import existing experiments into the `Experiment()` class by using the `Experiment.from_mlflow()` method. You must provide the **MLFlow tracking URI** and the experiment ID. To get the experiment ID, go to the link provided in the cell \"Creating a dummy MLFlow experiment run\". In the details section you will see \"Experiment ID\", copy this ID and add it to the argument **experiment_id**. ![image.png](img/experiment_id.png)"
]
},
{
diff --git a/backend/docs/notebooks/models_and_releases_demo_pytorch.ipynb b/backend/docs/notebooks/models_and_releases_demo_pytorch.ipynb
index 6dbedc9a2..988efe5ab 100644
--- a/backend/docs/notebooks/models_and_releases_demo_pytorch.ipynb
+++ b/backend/docs/notebooks/models_and_releases_demo_pytorch.ipynb
@@ -91,7 +91,7 @@
"\n",
"### Creating and updating the base model\n",
"\n",
- "In this section, we'll create a new model representing ResNet-50 using the `Model.create()` classmethod. On the Bailo service, a model must consist of at least 4 parameters upon creation. These are **name**, **description** and **visibility**. Other attributes like model cards, files, or releases are added later on. Below, we use the `Client()` object created before when instantiating the new `Model()` object. \n",
+ "In this section, we will create a new model representing ResNet-50 using the `Model.create()` classmethod. On the Bailo service, a model must consist of at least 4 parameters upon creation. These are **name**, **description** and **visibility**. Other attributes like model cards, files, or releases are added later on. Below, we use the `Client()` object created before when instantiating the new `Model()` object. \n",
"\n",
"NOTE: This creates the model on your Bailo service too! The `model_id` is assigned by the backend, and we will use this later to retrieve the model."
]
@@ -180,7 +180,7 @@
"source": [
"If successful, the above will have created a new model card, and the `model_card_version` attribute should be set to 1.\n",
"\n",
- "Next, we can populate the model card using the `update_model_card()` method. This can be used any time you want to make changes, and the backend will create a new model card version each time. We'll learn how to retrieve model cards later (either the latest, or a specific release).\n",
+ "Next, we can populate the model card using the `update_model_card()` method. This can be used any time you want to make changes, and the backend will create a new model card version each time. We will learn how to retrieve model cards later (either the latest, or a specific release).\n",
"\n",
"NOTE: Your model card must match the schema, otherwise an error will be thrown."
]
@@ -220,7 +220,7 @@
"\n",
"### Using the .from_id() method\n",
"\n",
- "In this section, we'll retrieve our previous model using the `Model.from_id()` classmethod. This will create your `Model()` object as before, but using existing information retrieved from the service."
+ "In this section, we will retrieve our previous model using the `Model.from_id()` classmethod. This will create your `Model()` object as before, but using existing information retrieved from the service."
]
},
{
@@ -337,7 +337,7 @@
"source": [
"### Downloading weights from the release\n",
"\n",
- "Similarly you can also download specific files from release using the `download()` method. In this case, we'll write them to a new file: **bailo_resnet50_weights.pth**. **NOTE**: `filename` refers to the filename on Bailo, and `path` is the local destination for your download.\n",
+ "You can also download specific files from release using the `download()` method. In this case, we will write them to a new file: **bailo_resnet50_weights.pth**. **NOTE**: `filename` refers to the filename on Bailo, and `path` is the local destination for your download.\n",
"\n",
"In addition to this, you can also use the `download_all()` method by providing a local directory path as `path`. By default, this will download all files, but you can provide `include` and `exclude` lists, e.g. `include=[\"*.txt\", \"*.json\"]` to only include TXT or JSON files. "
]
@@ -400,7 +400,7 @@
"* Libraries used for the model (e.g. PyTorch).\n",
"* Model card search (string to be found in model cards).\n",
"\n",
- "In the below example, we'll just search for all models with no filters."
+ "In the below example, we will just search for all models with no filters."
]
},
{
diff --git a/backend/docs/notebooks/schemas_demo.ipynb b/backend/docs/notebooks/schemas_demo.ipynb
index 881da6ad0..e4eee22fc 100644
--- a/backend/docs/notebooks/schemas_demo.ipynb
+++ b/backend/docs/notebooks/schemas_demo.ipynb
@@ -1,198 +1,198 @@
{
- "cells": [
- {
- "attachments": {},
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# Managing Schemas"
- ]
+ "cells": [
+ {
+ "attachments": {},
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Managing Schemas"
+ ]
+ },
+ {
+ "attachments": {},
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "The Bailo python client enables intuitive interaction with the Bailo service, from within a python environment. This example notebook will run through the following concepts:\n",
+ "\n",
+ "* Creating a new schema on Bailo.\n",
+ "* Retrieving schemas from the service.\n",
+ "\n",
+ "Prerequisites:\n",
+ "\n",
+ "* Python 3.8.1 or higher (including a notebook environment for this demo).\n",
+ "* A local or remote Bailo service (see https://github.com/gchq/Bailo)."
+ ]
+ },
+ {
+ "attachments": {},
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Introduction"
+ ]
+ },
+ {
+ "attachments": {},
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "The Bailo python client is split into two sub-packages: **core** and **helper**.\n",
+ "\n",
+ "* **Core:** For direct interactions with the service endpoints.\n",
+ "* **Helper:** For more intuitive interactions with the service, using classes (e.g. Model) to handle operations.\n",
+ "\n",
+ "In order to create helper classes, you will first need to instantiate a `Client()` object from the core. By default, this object will not support any authentication. However, Bailo also supports PKI authentication, which you can use from Python by passing a `PkiAgent()` object into the `Client()` object when you instantiate it."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Necessary import statements\n",
+ "\n",
+ "from bailo import Client, Schema, SchemaKind\n",
+ "import random\n",
+ "import string\n",
+ "\n",
+ "# Instantiating the PkiAgent(), if using.\n",
+ "# agent = PkiAgent(cert='', key='', auth='')\n",
+ "\n",
+ "# Instantiating the Bailo client\n",
+ "\n",
+ "client = Client(\"http://127.0.0.1:8080\") # <- INSERT BAILO URL (if not hosting locally)"
+ ]
+ },
+ {
+ "attachments": {},
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Creating a new schema"
+ ]
+ },
+ {
+ "attachments": {},
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "In this section, we will create a new schema using the `Schema.create()` classmethod. On the Bailo service, a schema must consist of 5 parameters upon creation. These are **schema_id**, **name**, **description**, **kind** and **json_schema**. Below, we use the `Client()` object created before when instantiating the new `Schema()` object. In this instance, **schema_id** is generated using a random generator function, however any unique identifier would suffice.\n",
+ "\n",
+ "NOTE: This creates the schema on your Bailo service too! This operation is typically reserved for administrators."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def random_generator(N=10):\n",
+ " return \"\".join(random.choices(string.ascii_uppercase + string.digits, k=N))\n",
+ "\n",
+ "json_schema = {\n",
+ " \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n",
+ " \"type\": \"object\",\n",
+ " \"properties\": {\n",
+ " \"overview\": {\n",
+ " \"title\": \"Overview\",\n",
+ " \"description\": \"Summary of the model functionality.\",\n",
+ " \"type\": \"object\",\n",
+ " \"properties\": {\n",
+ " \"modelOverview\": {\n",
+ " \"title\": \"What does the model do?\",\n",
+ " \"description\": \"A description of what the model does.\",\n",
+ " \"type\": \"string\",\n",
+ " \"minLength\": 1,\n",
+ " \"maxLength\": 5000,\n",
+ " },\n",
+ " \"tags\": {\n",
+ " \"title\": \"Descriptive tags for the model.\",\n",
+ " \"description\": \"These tags will be searchable and will help others find this model.\",\n",
+ " \"type\": \"array\",\n",
+ " \"widget\": \"tagSelectorBeta\",\n",
+ " \"items\": {\"type\": \"string\"},\n",
+ " \"uniqueItems\": True,\n",
+ " },\n",
+ " },\n",
+ " \"required\": [],\n",
+ " \"additionalProperties\": False,\n",
+ " },\n",
+ " },\n",
+ " \"required\": [],\n",
+ " \"additionalProperties\": False,\n",
+ "}\n",
+ "\n",
+ "schema = Schema.create(\n",
+ " client=client,\n",
+ " schema_id=random_generator(),\n",
+ " name=\"Test\",\n",
+ " description=\"Example Description\",\n",
+ " kind=SchemaKind.MODEL,\n",
+ " json_schema=json_schema\n",
+ ")\n",
+ "\n",
+ "schema_id = schema.schema_id "
+ ]
+ },
+ {
+ "attachments": {},
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Retrieving an existing schema"
+ ]
+ },
+ {
+ "attachments": {},
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Using the .from_id() method"
+ ]
+ },
+ {
+ "attachments": {},
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "In this section, we will retrieve our previous schema using the `Schema.from_id()` classmethod. This will create your `Schema()` object as before, but using existing information retrieved from the service."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "schema = Schema.from_id(client=client, schema_id=schema_id)\n",
+ "\n",
+ "schema.description"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.10.12"
+ },
+ "orig_nbformat": 4
},
- {
- "attachments": {},
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "The Bailo python client enables intuitive interaction with the Bailo service, from within a python environment. This example notebook will run through the following concepts:\n",
- "\n",
- "* Creating a new schema on Bailo.\n",
- "* Retrieving schemas from the service.\n",
- "\n",
- "Prerequisites:\n",
- "\n",
- "* Python 3.8.1 or higher (including a notebook environment for this demo).\n",
- "* A local or remote Bailo service (see https://github.com/gchq/Bailo)."
- ]
- },
- {
- "attachments": {},
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Introduction"
- ]
- },
- {
- "attachments": {},
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "The Bailo python client is split into two sub-packages: **core** and **helper**.\n",
- "\n",
- "* **Core:** For direct interactions with the service endpoints.\n",
- "* **Helper:** For more intuitive interactions with the service, using classes (e.g. Model) to handle operations.\n",
- "\n",
- "In order to create helper classes, you will first need to instantiate a `Client()` object from the core. By default, this object will not support any authentication. However, Bailo also supports PKI authentication, which you can use from Python by passing a `PkiAgent()` object into the `Client()` object when you instantiate it."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Necessary import statements\n",
- "\n",
- "from bailo import Client, Schema, SchemaKind\n",
- "import random\n",
- "import string\n",
- "\n",
- "# Instantiating the PkiAgent(), if using.\n",
- "# agent = PkiAgent(cert='', key='', auth='')\n",
- "\n",
- "# Instantiating the Bailo client\n",
- "\n",
- "client = Client(\"http://127.0.0.1:8080\") # <- INSERT BAILO URL (if not hosting locally)"
- ]
- },
- {
- "attachments": {},
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Creating a new schema"
- ]
- },
- {
- "attachments": {},
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "In this section, we'll create a new schema using the `Schema.create()` classmethod. On the Bailo service, a schema must consist of 5 parameters upon creation. These are **schema_id**, **name**, **description**, **kind** and **json_schema**. Below, we use the `Client()` object created before when instantiating the new `Schema()` object. In this instance, **schema_id** is generated using a random generator function, however any unique identifier would suffice.\n",
- "\n",
- "NOTE: This creates the schema on your Bailo service too! This operation is typically reserved for administrators."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "def random_generator(N=10):\n",
- " return \"\".join(random.choices(string.ascii_uppercase + string.digits, k=N))\n",
- "\n",
- "json_schema = {\n",
- " \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n",
- " \"type\": \"object\",\n",
- " \"properties\": {\n",
- " \"overview\": {\n",
- " \"title\": \"Overview\",\n",
- " \"description\": \"Summary of the model functionality.\",\n",
- " \"type\": \"object\",\n",
- " \"properties\": {\n",
- " \"modelOverview\": {\n",
- " \"title\": \"What does the model do?\",\n",
- " \"description\": \"A description of what the model does.\",\n",
- " \"type\": \"string\",\n",
- " \"minLength\": 1,\n",
- " \"maxLength\": 5000,\n",
- " },\n",
- " \"tags\": {\n",
- " \"title\": \"Descriptive tags for the model.\",\n",
- " \"description\": \"These tags will be searchable and will help others find this model.\",\n",
- " \"type\": \"array\",\n",
- " \"widget\": \"tagSelectorBeta\",\n",
- " \"items\": {\"type\": \"string\"},\n",
- " \"uniqueItems\": True,\n",
- " },\n",
- " },\n",
- " \"required\": [],\n",
- " \"additionalProperties\": False,\n",
- " },\n",
- " },\n",
- " \"required\": [],\n",
- " \"additionalProperties\": False,\n",
- "}\n",
- "\n",
- "schema = Schema.create(\n",
- " client=client,\n",
- " schema_id=random_generator(),\n",
- " name=\"Test\",\n",
- " description=\"Example Description\",\n",
- " kind=SchemaKind.MODEL,\n",
- " json_schema=json_schema\n",
- ")\n",
- "\n",
- "schema_id = schema.schema_id "
- ]
- },
- {
- "attachments": {},
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Retrieving an existing schema"
- ]
- },
- {
- "attachments": {},
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Using the .from_id() method"
- ]
- },
- {
- "attachments": {},
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "In this section, we'll retrieve our previous schema using the `Schema.from_id()` classmethod. This will create your `Schema()` object as before, but using existing information retrieved from the service."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "schema = Schema.from_id(client=client, schema_id=schema_id)\n",
- "\n",
- "schema.description"
- ]
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Python 3",
- "language": "python",
- "name": "python"
- },
- "language_info": {
- "codemirror_mode": {
- "name": "ipython",
- "version": 3
- },
- "file_extension": ".py",
- "mimetype": "text/x-python",
- "name": "python",
- "nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.10.12"
- },
- "orig_nbformat": 4
- },
- "nbformat": 4,
- "nbformat_minor": 2
+ "nbformat": 4,
+ "nbformat_minor": 2
}