From 26bf57e2398a9b61d4c7bbf09fb387123055ffc5 Mon Sep 17 00:00:00 2001 From: Austin Noto-Moniz Date: Fri, 14 Feb 2025 10:46:48 -0500 Subject: [PATCH] [PNE-6610] Expose more candidate attributes. Expose the pinned metadata, hidden attribubte, and name of each candidate as read-only properties. --- src/citrine/__version__.py | 2 +- src/citrine/informatics/design_candidate.py | 8 ++++++ tests/conftest.py | 4 ++- tests/resources/test_design_executions.py | 27 +++++++++++++++++++++ 4 files changed, 39 insertions(+), 2 deletions(-) diff --git a/src/citrine/__version__.py b/src/citrine/__version__.py index 00e46670a..331093ae1 100644 --- a/src/citrine/__version__.py +++ b/src/citrine/__version__.py @@ -1 +1 @@ -__version__ = "3.15.1" +__version__ = "3.16.0" diff --git a/src/citrine/informatics/design_candidate.py b/src/citrine/informatics/design_candidate.py index 336576fe1..5e392b400 100644 --- a/src/citrine/informatics/design_candidate.py +++ b/src/citrine/informatics/design_candidate.py @@ -177,6 +177,14 @@ class DesignCandidate(Serializable["DesignCandidate"]): and constraints (higher is better)""" material = properties.Object(DesignMaterial, 'material') """:DesignMaterial: the material returned by the design workflow""" + name = properties.String('name') + """:str: the name of the candidate""" + hidden = properties.Boolean('hidden') + """:str: whether the candidate is marked hidden""" + pinned_by = properties.Optional(properties.UUID, 'pinned.user') + """:Optional[UUID]: id of the user who pinned the candidate, if it's been pinned""" + pinned_time = properties.Optional(properties.Datetime, 'pinned.time') + """:Optional[datetime]: date and time at which the candidate was pinned, if it's been pinned""" class HierarchicalDesignCandidate(Serializable["HierarchicalDesignCandidate"]): diff --git a/tests/conftest.py b/tests/conftest.py index 4548a208e..55ca200ea 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -849,7 +849,9 @@ def example_candidates(example_design_material): "material_id": str(uuid.uuid4()), "identifiers": [], "primary_score": 0, - "material": example_design_material + "material": example_design_material, + "name": "Example candidate", + "hidden": True }] } diff --git a/tests/resources/test_design_executions.py b/tests/resources/test_design_executions.py index 87a54a440..48cf3c4c2 100644 --- a/tests/resources/test_design_executions.py +++ b/tests/resources/test_design_executions.py @@ -1,5 +1,7 @@ import pytest import uuid +from copy import deepcopy +from datetime import datetime from citrine.informatics.executions.design_execution import DesignExecution from citrine.resources.design_execution import DesignExecutionCollection @@ -99,6 +101,31 @@ def test_workflow_execution_results(workflow_execution: DesignExecution, session assert session.last_call == FakeCall(method='GET', path=expected_path, params={"per_page": 4, 'page': 1}) +def test_workflow_execution_results_pinned(workflow_execution: DesignExecution, session, example_candidates): + # Given + pinned_by = uuid.uuid4() + pinned_time = datetime.now() + example_candidates_pinned = deepcopy(example_candidates) + example_candidates_pinned["response"][0]["pinned"] = { + "user": pinned_by, + "time": pinned_time + } + session.set_response(example_candidates_pinned) + + # When + candidates = list(workflow_execution.candidates(per_page=4)) + + # Then + expected_path = '/projects/{}/design-workflows/{}/executions/{}/candidates'.format( + workflow_execution.project_id, + workflow_execution.workflow_id, + workflow_execution.uid, + ) + assert session.last_call == FakeCall(method='GET', path=expected_path, params={"per_page": 4, 'page': 1}) + assert candidates[0].pinned_by == pinned_by + assert candidates[0].pinned_time == pinned_time + + def test_list(collection: DesignExecutionCollection, session): session.set_response({"per_page": 4, "next": "", "response": []}) lst = list(collection.list(per_page=4))