Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions doc/changelog.d/587.added.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Feat: added api gettestpointproperties
1 change: 1 addition & 0 deletions doc/source/api/layer_types.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ Classes used for the Layer API.

CopyPottingRegionRequest
DeletePottingRegionRequest
GetTestPointPropertiesRequest
PolygonalShape
RectangularShape
SlotShape
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "flit_core.buildapi"

[project]
name = "ansys-sherlock-core"
version = "0.9.dev0"
version = "0.10.dev0"
description = "A python wrapper for Ansys Sherlock"
readme = "README.rst"
requires-python = ">=3.10,<4"
Expand Down
40 changes: 40 additions & 0 deletions src/ansys/sherlock/core/layer.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
CircularShape,
CopyPottingRegionRequest,
DeletePottingRegionRequest,
GetTestPointPropertiesRequest,
PCBShape,
PolygonalShape,
RectangularShape,
Expand Down Expand Up @@ -2057,3 +2058,42 @@
except SherlockExportLayerImageError as e:
LOG.error(str(e))
raise e

@require_version(261)
def get_test_point_props(
self, request: GetTestPointPropertiesRequest
) -> list[SherlockLayerService_pb2.GetTestPointPropertiesResponse]:
"""Return the properties for each test point given a comma-separated list of test point IDs.

Available Since: 2026R1

Parameters
----------
request: GetTestPointPropertiesRequest
Contains all the information needed to return the properties for one or more test
points.

Returns
-------
list[SherlockCommonService_pb2.GetTestPointPropertiesResponse]
Properties for each test point that correspond to the reference designators.

Examples
--------
>>> from ansys.sherlock.core.launcher import launch_sherlock
>>> from ansys.sherlock.core.types.layer_types import GetTestPointPropertiesRequest
>>> sherlock = launch_sherlock()
>>> request = layer_types.GetTestPointPropertiesRequest(
>>> project = "Test Point Test Project"
>>> cca_name = "Main Board"
>>> test_point_ids = "TP1,TP2"
>>> )
>>> responses = layer.get_test_point_props(request)
"""
get_test_point_props_request = request._convert_to_grpc()
responses = []
for get_test_point_props_response in self.stub.getTestPointProperties(

Check warning on line 2095 in src/ansys/sherlock/core/layer.py

View check run for this annotation

Codecov / codecov/patch

src/ansys/sherlock/core/layer.py#L2093-L2095

Added lines #L2093 - L2095 were not covered by tests
get_test_point_props_request
):
responses.append(get_test_point_props_response)
return responses

Check warning on line 2099 in src/ansys/sherlock/core/layer.py

View check run for this annotation

Codecov / codecov/patch

src/ansys/sherlock/core/layer.py#L2098-L2099

Added lines #L2098 - L2099 were not covered by tests
38 changes: 36 additions & 2 deletions src/ansys/sherlock/core/types/layer_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@
"""Module containing types for the Layer Service."""


from typing import Union
from typing import Optional, Union

from ansys.api.sherlock.v0 import SherlockLayerService_pb2
from pydantic import BaseModel, ValidationInfo, field_validator, model_validator
from typing_extensions import Self

from ansys.sherlock.core.types.common_types import basic_str_validator
from ansys.sherlock.core.types.common_types import basic_str_validator, optional_str_validator


class PolygonalShape(BaseModel):
Expand Down Expand Up @@ -334,3 +334,37 @@
for delete_data in self.potting_region_delete_data:
request.pottingRegionDeleteData.append(delete_data._convert_to_grpc())
return request


class GetTestPointPropertiesRequest(BaseModel):
"""Return the properties for each test point given a comma-separated list of test point ids."""

project: str
"""Name of the project."""
cca_name: str
"""Name of the CCA containing the test point properties to return."""
test_point_ids: Optional[str] = None
"""Optional Param: Comma-separated list of test point ids representing one or more test points.
If this parameter is not included, then the entire list of test points for a given CCA will
have their properties returned.
"""

@field_validator("project", "cca_name", "test_point_ids")
@classmethod
def str_validation(cls, value: str, info: ValidationInfo):
"""Validate string fields listed."""
return basic_str_validator(value, info.field_name)

@field_validator("test_point_ids")
@classmethod
def optional_str_validation(cls, value: Optional[str], info):
"""Allow the test_point_ids to not be set, i.e., None."""
return optional_str_validator(value, info.field_name)

def _convert_to_grpc(self) -> SherlockLayerService_pb2.GetTestPointPropertiesRequest:
request = SherlockLayerService_pb2.GetTestPointPropertiesRequest()
request.project = self.project
request.ccaName = self.cca_name
if self.test_point_ids is not None:
request.testPointIDs = self.test_point_ids
return request

Check warning on line 370 in src/ansys/sherlock/core/types/layer_types.py

View check run for this annotation

Codecov / codecov/patch

src/ansys/sherlock/core/types/layer_types.py#L365-L370

Added lines #L365 - L370 were not covered by tests
173 changes: 173 additions & 0 deletions tests/test_layer.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
CircularShape,
CopyPottingRegionRequest,
DeletePottingRegionRequest,
GetTestPointPropertiesRequest,
PCBShape,
PolygonalShape,
PottingRegion,
Expand Down Expand Up @@ -69,6 +70,7 @@ def test_all():
helper_test_copy_modeling_region(layer, region_id)
helper_test_delete_modeling_region(layer, region_id)
helper_test_list_layers(layer)
helper_test_get_test_point_props(layer)
helper_test_export_layer_image(layer)


Expand Down Expand Up @@ -1509,6 +1511,177 @@ def helper_test_list_layers(layer):
pytest.fail(e.message())


def helper_test_get_test_point_props(layer):
"""Test get_test_point_props API."""

project = "Test Point Test Project"
cca_name = "Main Board"
test_point_ids = "TP1,TP2"

good_bad_test_point_ids = "TP1,Bad1,Bad2,TP2"

# Missing project name
try:
GetTestPointPropertiesRequest(
project="",
cca_name=cca_name,
test_point_ids=test_point_ids,
)
pytest.fail("No exception raised when using an invalid project parameter")
except Exception as e:
assert isinstance(e, pydantic.ValidationError)

# Missing CCA name
try:
GetTestPointPropertiesRequest(
project=project,
cca_name="",
test_point_ids=test_point_ids,
)
pytest.fail("No exception raised when using an invalid cca_name parameter")
except Exception as e:
assert isinstance(e, pydantic.ValidationError)

# test_point_ids is the empty string
try:
GetTestPointPropertiesRequest(
project=project,
cca_name=cca_name,
test_point_ids="",
)
pytest.fail("No exception raised when using an invalid test_point_ids parameter")
except Exception as e:
assert isinstance(e, pydantic.ValidationError)

if layer._is_connection_up():

# Bad project name
badProjectRequest = GetTestPointPropertiesRequest(
project="Invalid Project Name",
cca_name=cca_name,
test_point_ids=test_point_ids,
)

badProjectResponses = layer.get_test_point_props(badProjectRequest)
assert len(badProjectResponses) == 1
assert badProjectResponses[0].returnCode.value == -1
assert (
badProjectResponses[0].returnCode.message == "Cannot find project: Invalid Project Name"
)

# Test request with valid test point ids.
request = GetTestPointPropertiesRequest(
project=project,
cca_name=cca_name,
test_point_ids=test_point_ids,
)

responses = layer.get_test_point_props(request)
assert len(responses) == 2
assert responses[0].testPointProperties.ID == "TP1"
assert responses[0].testPointProperties.side == "TOP"
assert responses[0].testPointProperties.units == "mm"
assert responses[0].testPointProperties.centerX == 53.09614010443865
assert responses[0].testPointProperties.centerY == 10.578305680323764
assert responses[0].testPointProperties.radius == 1
assert responses[0].testPointProperties.loadType == 0
assert responses[0].testPointProperties.loadValue == 0.36
assert responses[0].testPointProperties.loadUnits == "N"

assert responses[1].testPointProperties.ID == "TP2"
assert responses[1].testPointProperties.side == "TOP"
assert responses[1].testPointProperties.units == "mm"
assert responses[1].testPointProperties.centerX == 71.21625140992168
assert responses[1].testPointProperties.centerY == 10.718771659436035
assert responses[1].testPointProperties.radius == 1
assert responses[1].testPointProperties.loadType == 0
assert responses[1].testPointProperties.loadValue == 0.36
assert responses[1].testPointProperties.loadUnits == "N"

# Test a mix of valid test points and invalid ones.
mixedRequest = GetTestPointPropertiesRequest(
project=project,
cca_name=cca_name,
test_point_ids=good_bad_test_point_ids,
)

mixedResponses = layer.get_test_point_props(mixedRequest)
# 2 good test points, 2 bad test points
assert len(mixedResponses) == 4

assert mixedResponses[0].returnCode.value == -1

assert mixedResponses[1].returnCode.value == -1

assert mixedResponses[2].testPointProperties.ID == "TP1"
assert mixedResponses[2].testPointProperties.side == "TOP"
assert mixedResponses[2].testPointProperties.units == "mm"
assert mixedResponses[2].testPointProperties.centerX == 53.09614010443865
assert mixedResponses[2].testPointProperties.centerY == 10.578305680323764
assert mixedResponses[2].testPointProperties.radius == 1
assert mixedResponses[2].testPointProperties.loadType == 0
assert mixedResponses[2].testPointProperties.loadValue == 0.36
assert mixedResponses[2].testPointProperties.loadUnits == "N"

assert mixedResponses[3].testPointProperties.ID == "TP2"
assert mixedResponses[3].testPointProperties.side == "TOP"
assert mixedResponses[3].testPointProperties.units == "mm"
assert mixedResponses[3].testPointProperties.centerX == 71.21625140992168
assert mixedResponses[3].testPointProperties.centerY == 10.718771659436035
assert mixedResponses[3].testPointProperties.radius == 1
assert mixedResponses[3].testPointProperties.loadType == 0
assert mixedResponses[3].testPointProperties.loadValue == 0.36
assert mixedResponses[3].testPointProperties.loadUnits == "N"

# Test that no test_point_ids param will return all of the test points in the project.
allPointsRequest = GetTestPointPropertiesRequest(
project=project,
cca_name=cca_name,
)

allPointsResponses = layer.get_test_point_props(allPointsRequest)
assert len(allPointsResponses) == 4

assert allPointsResponses[0].testPointProperties.ID == "TP1"
assert allPointsResponses[0].testPointProperties.side == "TOP"
assert allPointsResponses[0].testPointProperties.units == "mm"
assert allPointsResponses[0].testPointProperties.centerX == 53.09614010443865
assert allPointsResponses[0].testPointProperties.centerY == 10.578305680323764
assert allPointsResponses[0].testPointProperties.radius == 1
assert allPointsResponses[0].testPointProperties.loadType == 0
assert allPointsResponses[0].testPointProperties.loadValue == 0.36
assert allPointsResponses[0].testPointProperties.loadUnits == "N"

assert allPointsResponses[1].testPointProperties.side == "TOP"
assert allPointsResponses[1].testPointProperties.units == "mm"
assert allPointsResponses[1].testPointProperties.centerX == 71.21625140992168
assert allPointsResponses[1].testPointProperties.centerY == 10.718771659436035
assert allPointsResponses[1].testPointProperties.radius == 1
assert allPointsResponses[1].testPointProperties.loadType == 0
assert allPointsResponses[1].testPointProperties.loadValue == 0.36
assert allPointsResponses[1].testPointProperties.loadUnits == "N"

assert allPointsResponses[2].testPointProperties.ID == "TP3"
assert allPointsResponses[2].testPointProperties.side == "TOP"
assert allPointsResponses[2].testPointProperties.units == "mm"
assert allPointsResponses[2].testPointProperties.centerX == 71.21625140992168
assert allPointsResponses[2].testPointProperties.centerY == -10.632057165629243
assert allPointsResponses[2].testPointProperties.radius == 1
assert allPointsResponses[2].testPointProperties.loadType == 0
assert allPointsResponses[2].testPointProperties.loadValue == 0.36
assert allPointsResponses[2].testPointProperties.loadUnits == "N"

assert allPointsResponses[3].testPointProperties.ID == "TP4"
assert allPointsResponses[3].testPointProperties.side == "TOP"
assert allPointsResponses[3].testPointProperties.units == "mm"
assert allPointsResponses[3].testPointProperties.centerX == 53.09614010443865
assert allPointsResponses[3].testPointProperties.centerY == -10.632057165629243
assert allPointsResponses[3].testPointProperties.radius == 1
assert allPointsResponses[3].testPointProperties.loadType == 0
assert allPointsResponses[3].testPointProperties.loadValue == 0.36
assert allPointsResponses[3].testPointProperties.loadUnits == "N"


def helper_test_export_layer_image(layer):
"""Test export_layer_image API"""

Expand Down
Loading