Skip to content

feat: initial support for data-platform#430

Open
sg-s wants to merge 1 commit intomainfrom
data-platform-api
Open

feat: initial support for data-platform#430
sg-s wants to merge 1 commit intomainfrom
data-platform-api

Conversation

@sg-s
Copy link
Collaborator

@sg-s sg-s commented Feb 3, 2026

changes

  • basic support for data-platform
  • ability to list projects
  • ability to create a project
  • ability to check if a project exists
  • ability to register a Ligand
  • ability to register a protein
  • ability to search for a Ligand
  • ability to search for a protein
  • ability to construct a Ligand from ID
  • ability to construct a Protein from ID

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds initial support for the data-platform API, enabling users to search and query various entities (ligands, proteins, etc.) through the DeepOriginClient.

Changes:

  • Added a new Data API wrapper class with methods for health checks, model listing, and entity searching
  • Integrated the Data wrapper into DeepOriginClient
  • Added comprehensive test coverage and mock server endpoints for the new functionality

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
src/platform/data.py New Data API wrapper class with methods for searching entities, ligands, and proteins, plus health and model listing endpoints
src/platform/client.py Integration of Data wrapper into DeepOriginClient initialization
tests/test_data.py Comprehensive test suite for data platform functionality including health checks, search operations, and error handling
tests/mock_server/server.py Mock endpoints for data platform API including health, search, and model listing
docs/platform/ref/data.md User-facing documentation for the Data API with usage examples
mkdocs.yaml Added data reference to documentation navigation

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +70 to +90
def test_search_proteins_lv1():
"""Test searching proteins using convenience method."""
client = DeepOriginClient()
response = client.data.search_proteins()

assert isinstance(response, dict), "Expected a dictionary response"
assert "data" in response, "Expected 'data' key in response"
assert isinstance(response["data"], list), "Expected 'data' to be a list"


def test_search_proteins_molecular_weight():
"""Test searching proteins with molecular weight filters."""
client = DeepOriginClient()
response = client.data.search_proteins(
min_molecular_weight=250, max_molecular_weight=550
)

assert isinstance(response, dict), "Expected a dictionary response"
assert "data" in response, "Expected 'data' key in response"
assert isinstance(response["data"], list), "Expected 'data' to be a list"

Copy link

Copilot AI Feb 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no test coverage for the pdb_id parameter in search_proteins. Consider adding a test that verifies the pdb_id filter works correctly.

Copilot uses AI. Check for mistakes.
entity: str,
*,
cursor: str | None = None,
filter_dict: dict[str, Any] | None = None,
Copy link

Copilot AI Feb 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The parameter name is inconsistent between search_ligands_with_results which uses 'filter' (line 48, 157) and the internal search method which uses 'filter_dict' (line 95). This inconsistency makes the API confusing. Consider renaming 'filter_dict' to 'filter' in the search method signature to maintain consistency across the API, or rename 'filter' to 'filter_dict' in search_ligands_with_results and search_ligands for consistency.

Copilot uses AI. Check for mistakes.
Comment on lines +223 to +235
def search_proteins(
self,
*,
cursor: str | None = None,
pdb_id: str | None = None,
min_molecular_weight: float | int | None = None,
max_molecular_weight: float | int | None = None,
sequence: str | None = None,
limit: int | None = None,
offset: int | None = None,
select: list[str] | None = None,
sort: dict[str, str] | None = None,
) -> dict:
Copy link

Copilot AI Feb 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The search_proteins method does not accept a filter parameter like search_ligands does (line 157). Users cannot pass custom filters to search_proteins, which limits flexibility. Consider adding a filter parameter to maintain consistency with search_ligands and allow users to specify custom filter criteria beyond the convenience parameters (pdb_id, molecular_weight, sequence).

Copilot uses AI. Check for mistakes.
"""
# Build filter dict, starting with provided filter or empty dict
filter_dict = filter.copy() if filter is not None else {}
filter_dict.setdefault("deleted", False)
Copy link

Copilot AI Feb 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The search_ligands method uses filter_dict.setdefault("deleted", False) which will not override an existing "deleted" key if the user passes one in the filter. In contrast, search_proteins and the search method unconditionally set filter_dict["deleted"] = False, which overrides any user-provided value. This inconsistency in handling the "deleted" field could lead to unexpected behavior. Consider using a consistent approach across all methods - either always override or always preserve user values.

Suggested change
filter_dict.setdefault("deleted", False)
# Ensure deleted records are excluded consistently with other search methods
filter_dict["deleted"] = False

Copilot uses AI. Check for mistakes.
Comment on lines +48 to +56
def test_search_ligands_lv1():
"""Test searching ligands using convenience method."""
client = DeepOriginClient()
response = client.data.search_ligands()

assert isinstance(response, dict), "Expected a dictionary response"
assert "data" in response, "Expected 'data' key in response"
assert isinstance(response["data"], list), "Expected 'data' to be a list"

Copy link

Copilot AI Feb 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no test coverage for the filter parameter in search_ligands. The test_search_ligands_lv1 function only tests the basic case without filters, and test_search_ligands_molecular_weight only tests the molecular weight convenience parameters. Consider adding a test that verifies the filter parameter works correctly, similar to how the search method is tested in test_search_entity_lv1.

Copilot uses AI. Check for mistakes.
org_key: str, request: Request
) -> dict[str, Any]:
"""Search ligands joined with tool results."""
body = await request.json()
Copy link

Copilot AI Feb 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Variable body is not used.

Copilot uses AI. Check for mistakes.
org_key: str, entity: str, request: Request
) -> dict[str, Any]:
"""Search an entity."""
body = await request.json()
Copy link

Copilot AI Feb 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Variable body is not used.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant