Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New api: updatePartsListProperties() #235

Merged
merged 6 commits into from
Mar 6, 2024
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
17 changes: 17 additions & 0 deletions src/ansys/sherlock/core/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -984,3 +984,20 @@ def __init__(self, message):
def __str__(self):
"""Format error message."""
return f"Import zipped project archive error: {self.message}"


class SherlockUpdatePartsListPropertiesError(Exception):
"""Contains the errors raised when a parts list properties cannot be updated."""

def __init__(self, message=None, error_array=None):
"""Initialize error message."""
self.message = message
self.error_array = error_array

def str_itr(self):
"""Format error message."""
if self.message is None:
return [f"Update parts list properties error: {error}" for error in self.error_array]

assert self.error_array is None
return [f"Update parts list properties error: {self.message}"]
125 changes: 125 additions & 0 deletions src/ansys/sherlock/core/parts.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
SherlockImportPartsListError,
SherlockUpdatePartsFromAVLError,
SherlockUpdatePartsListError,
SherlockUpdatePartsListPropertiesError,
SherlockUpdatePartsLocationsByFileError,
SherlockUpdatePartsLocationsError,
)
Expand Down Expand Up @@ -804,3 +805,127 @@ def update_parts_from_AVL(
except SherlockUpdatePartsFromAVLError as e:
LOG.error(str(e))
raise e

def update_parts_list_properties(self, project, cca_name, part_properties):
"""
Update one or more properties of one or more parts in a parts list.

Parameters
----------
project : str
Name of the Sherlock project.
cca_name : str
Name of the CCA.
part_properties : list
List of part properties consisting of these properties:

- reference_designators : List of str, optional
List of the reference designator for each part to be updated. If not included,
update properties for all parts in the CCA.
- properties : list
List of properties consisting of these properties:

- name : str
Name of property to be updated.
- value : str
Value to be applied to the chosen part property.

Returns
-------
int
Status code of the response. 0 for success.

Examples
--------
>>> from ansys.sherlock.core.launcher import launch_sherlock
>>> sherlock = launch_sherlock()
>>> sherlock.parts.update_parts_list_properties(
"Test",
"Card",
[
{
"reference_designators": ["C1"],
"properties": [
{"name": "partType", "value": "RESISTOR"}
]
},
{
"reference_designators": ["C2"],
"properties": [
{"name": "locX", "value": "1"}
]
}
]
)
"""
try:
if project == "":
raise SherlockUpdatePartsListPropertiesError(message="Project name is invalid.")
if cca_name == "":
raise SherlockUpdatePartsListPropertiesError(message="CCA name is invalid.")
if len(part_properties) == 0:
raise SherlockUpdatePartsListPropertiesError(message="Part properties are missing.")

for i, part_property in enumerate(part_properties):
if len(part_property) < 1 or len(part_property) > 2:
raise SherlockUpdatePartsListPropertiesError(
f"Number of elements ({len(part_property)}) "
f"is wrong for part list property {i}."
)
elif not isinstance(part_property["reference_designators"], list):
raise SherlockUpdatePartsListPropertiesError(
f"reference_designators is not a list " f"for parts list property {i}."
)

properties = part_property["properties"]
for j, property in enumerate(properties):
if len(property) < 1 or len(property) > 2:
raise SherlockUpdatePartsListPropertiesError(
f"Number of elements ({len(property)}) " f"is wrong for property {j}."
)
elif not isinstance(property["name"], str) or property["name"] == "":
raise SherlockUpdatePartsListPropertiesError(
f"Name is required " f"for property {j}."
)
elif not isinstance(property["value"], str):
raise SherlockUpdatePartsListPropertiesError(message="Value is invalid.")

if not self._is_connection_up():
LOG.error("There is no connection to a gRPC service.")
return

request = SherlockPartsService_pb2.UpdatePartsListPropertiesRequest(
project=project, ccaName=cca_name
)

# Add part properties to the request
for part_prop in part_properties:
prop = request.partProperties.add()
reference_designators = part_prop["reference_designators"]
if reference_designators is not None:
for ref_des in reference_designators:
prop.refDes.append(ref_des)

props = part_prop["properties"]
if props is not None:
for prop_dict in props:
property_obj = prop.properties.add()
property_obj.name = prop_dict["name"]
property_obj.value = prop_dict["value"]

response = self.stub.updatePartsListProperties(request)

return_code = response.returnCode

if return_code.value == -1:
if return_code.message == "":
raise SherlockUpdatePartsListPropertiesError(error_array=response.errors)

raise SherlockUpdatePartsListPropertiesError(message=return_code.message)

return return_code.value

except SherlockUpdatePartsListPropertiesError as e:
for error in e.str_itr():
LOG.error(error)
raise e
158 changes: 158 additions & 0 deletions tests/test_parts.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
SherlockImportPartsListError,
SherlockUpdatePartsFromAVLError,
SherlockUpdatePartsListError,
SherlockUpdatePartsListPropertiesError,
SherlockUpdatePartsLocationsByFileError,
SherlockUpdatePartsLocationsError,
)
Expand All @@ -34,6 +35,8 @@ def test_all():

helper_test_update_parts_list(parts)
time.sleep(1)
helper_test_update_parts_list_properties(parts)
time.sleep(1)
ansnfernand marked this conversation as resolved.
Show resolved Hide resolved
helper_test_update_parts_from_AVL(parts)
helper_test_update_parts_locations(parts)
helper_test_update_parts_locations_by_file(parts)
Expand Down Expand Up @@ -672,5 +675,160 @@ def helper_test_get_part_location(parts):
assert str(e) == "Get part location error: Location unit is invalid."


def helper_test_update_parts_list_properties(parts):
"""Test update_parts_list_properties API"""
try:
parts.update_parts_list_properties(
"",
"CCA_Name",
[
{
"reference_designators": ["C1"],
"properties": [{"name": "partType", "value": "RESISTOR"}],
}
],
)
pytest.fail("No exception raised when using an invalid parameter")
except SherlockUpdatePartsListPropertiesError as e:
assert str(e.str_itr()) == (
"['Update parts list properties error: Project name is invalid.']"
)

try:
parts.update_parts_list_properties(
"Test",
"",
[
{
"reference_designators": ["C1"],
"properties": [{"name": "partType", "value": "RESISTOR"}],
}
],
)
pytest.fail("No exception raised when using an invalid parameter")
except SherlockUpdatePartsListPropertiesError as e:
assert str(e.str_itr()) == "['Update parts list properties error: CCA name is invalid.']"

try:
parts.update_parts_list_properties("Test", "CCA_Name", [])
pytest.fail("No exception raised when using an invalid parameter")
except SherlockUpdatePartsListPropertiesError as e:
assert str(e.str_itr()) == (
"['Update parts list properties error: Part properties are missing.']"
)

try:
parts.update_parts_list_properties(
"Test",
"CCA_name",
[
{
"reference_designators": ["C1"],
"properties": [{"name": "partType", "value": "RESISTOR"}],
"test": "test",
}
],
)
pytest.fail("No exception raised when using an invalid parameter")
except SherlockUpdatePartsListPropertiesError as e:
assert str(e.str_itr()) == (
"['Update parts list properties error: Number of elements (3) "
"is wrong for part list property 0.']"
)

try:
parts.update_parts_list_properties(
"Test",
"CCA_name",
[
{
"reference_designators": "C1",
"properties": [{"name": "partType", "value": "RESISTOR"}],
}
],
)
pytest.fail("No exception raised when using an invalid parameter")
except SherlockUpdatePartsListPropertiesError as e:
assert str(e.str_itr()) == (
"['Update parts list properties error: reference_designators is not a list "
"for parts list property 0.']"
)

try:
parts.update_parts_list_properties(
"Test",
"CCA_name",
[
{
"reference_designators": ["C1"],
"properties": [{"name": "partType", "value": "RESISTOR", "test": "test"}],
}
],
)
pytest.fail("No exception raised when using an invalid parameter")
except SherlockUpdatePartsListPropertiesError as e:
assert str(e.str_itr()) == (
"['Update parts list properties error: Number of elements (3) "
"is wrong for property 0.']"
)

try:
parts.update_parts_list_properties(
"Test",
"CCA_name",
[{"reference_designators": ["C1"], "properties": [{"name": "", "value": "RESISTOR"}]}],
)
pytest.fail("No exception raised when using an invalid parameter")
except SherlockUpdatePartsListPropertiesError as e:
assert str(e.str_itr()) == (
"['Update parts list properties error: Name is required for property 0.']"
)

try:
parts.update_parts_list_properties(
"Test",
"CCA_name",
[{"reference_designators": ["C1"], "properties": [{"name": "partType", "value": 0}]}],
)
pytest.fail("No exception raised when using an invalid parameter")
except SherlockUpdatePartsListPropertiesError as e:
assert str(e.str_itr()) == ("['Update parts list properties error: Value is invalid.']")

if not parts._is_connection_up():
return

try:
parts.update_parts_list_properties(
"Invalid project",
"CCA_name",
[
{
"reference_designators": ["C1"],
"properties": [{"name": "partType", "value": "RESISTOR"}],
}
],
)
pytest.fail("No exception raised when using an invalid parameter")
except Exception as e:
assert type(e) == SherlockUpdatePartsListPropertiesError

try:
result = parts.update_parts_list_properties(
"Tutorial Project",
"Main Board",
[
{
"reference_designators": ["C1"],
"properties": [{"name": "partType", "value": "RESISTOR"}],
}
],
)

assert result == 0

except Exception as e:
pytest.fail(e.message)


if __name__ == "__main__":
test_all()
Loading