Skip to content

Commit 7c41058

Browse files
authored
New api: updatePartsListProperties() (#235)
1 parent 6ce4e96 commit 7c41058

File tree

3 files changed

+300
-0
lines changed

3 files changed

+300
-0
lines changed

src/ansys/sherlock/core/errors.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -984,3 +984,20 @@ def __init__(self, message):
984984
def __str__(self):
985985
"""Format error message."""
986986
return f"Import zipped project archive error: {self.message}"
987+
988+
989+
class SherlockUpdatePartsListPropertiesError(Exception):
990+
"""Contains the errors raised when a parts list properties cannot be updated."""
991+
992+
def __init__(self, message=None, error_array=None):
993+
"""Initialize error message."""
994+
self.message = message
995+
self.error_array = error_array
996+
997+
def str_itr(self):
998+
"""Format error message."""
999+
if self.message is None:
1000+
return [f"Update parts list properties error: {error}" for error in self.error_array]
1001+
1002+
assert self.error_array is None
1003+
return [f"Update parts list properties error: {self.message}"]

src/ansys/sherlock/core/parts.py

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
SherlockImportPartsListError,
1818
SherlockUpdatePartsFromAVLError,
1919
SherlockUpdatePartsListError,
20+
SherlockUpdatePartsListPropertiesError,
2021
SherlockUpdatePartsLocationsByFileError,
2122
SherlockUpdatePartsLocationsError,
2223
)
@@ -804,3 +805,127 @@ def update_parts_from_AVL(
804805
except SherlockUpdatePartsFromAVLError as e:
805806
LOG.error(str(e))
806807
raise e
808+
809+
def update_parts_list_properties(self, project, cca_name, part_properties):
810+
"""
811+
Update one or more properties of one or more parts in a parts list.
812+
813+
Parameters
814+
----------
815+
project : str
816+
Name of the Sherlock project.
817+
cca_name : str
818+
Name of the CCA.
819+
part_properties : list
820+
List of part properties consisting of these properties:
821+
822+
- reference_designators : List of str, optional
823+
List of the reference designator for each part to be updated. If not included,
824+
update properties for all parts in the CCA.
825+
- properties : list
826+
List of properties consisting of these properties:
827+
828+
- name : str
829+
Name of property to be updated.
830+
- value : str
831+
Value to be applied to the chosen part property.
832+
833+
Returns
834+
-------
835+
int
836+
Status code of the response. 0 for success.
837+
838+
Examples
839+
--------
840+
>>> from ansys.sherlock.core.launcher import launch_sherlock
841+
>>> sherlock = launch_sherlock()
842+
>>> sherlock.parts.update_parts_list_properties(
843+
"Test",
844+
"Card",
845+
[
846+
{
847+
"reference_designators": ["C1"],
848+
"properties": [
849+
{"name": "partType", "value": "RESISTOR"}
850+
]
851+
},
852+
{
853+
"reference_designators": ["C2"],
854+
"properties": [
855+
{"name": "locX", "value": "1"}
856+
]
857+
}
858+
]
859+
)
860+
"""
861+
try:
862+
if project == "":
863+
raise SherlockUpdatePartsListPropertiesError(message="Project name is invalid.")
864+
if cca_name == "":
865+
raise SherlockUpdatePartsListPropertiesError(message="CCA name is invalid.")
866+
if len(part_properties) == 0:
867+
raise SherlockUpdatePartsListPropertiesError(message="Part properties are missing.")
868+
869+
for i, part_property in enumerate(part_properties):
870+
if len(part_property) < 1 or len(part_property) > 2:
871+
raise SherlockUpdatePartsListPropertiesError(
872+
f"Number of elements ({len(part_property)}) "
873+
f"is wrong for part list property {i}."
874+
)
875+
elif not isinstance(part_property["reference_designators"], list):
876+
raise SherlockUpdatePartsListPropertiesError(
877+
f"reference_designators is not a list " f"for parts list property {i}."
878+
)
879+
880+
properties = part_property["properties"]
881+
for j, property in enumerate(properties):
882+
if len(property) < 1 or len(property) > 2:
883+
raise SherlockUpdatePartsListPropertiesError(
884+
f"Number of elements ({len(property)}) " f"is wrong for property {j}."
885+
)
886+
elif not isinstance(property["name"], str) or property["name"] == "":
887+
raise SherlockUpdatePartsListPropertiesError(
888+
f"Name is required " f"for property {j}."
889+
)
890+
elif not isinstance(property["value"], str):
891+
raise SherlockUpdatePartsListPropertiesError(message="Value is invalid.")
892+
893+
if not self._is_connection_up():
894+
LOG.error("There is no connection to a gRPC service.")
895+
return
896+
897+
request = SherlockPartsService_pb2.UpdatePartsListPropertiesRequest(
898+
project=project, ccaName=cca_name
899+
)
900+
901+
# Add part properties to the request
902+
for part_prop in part_properties:
903+
prop = request.partProperties.add()
904+
reference_designators = part_prop["reference_designators"]
905+
if reference_designators is not None:
906+
for ref_des in reference_designators:
907+
prop.refDes.append(ref_des)
908+
909+
props = part_prop["properties"]
910+
if props is not None:
911+
for prop_dict in props:
912+
property_obj = prop.properties.add()
913+
property_obj.name = prop_dict["name"]
914+
property_obj.value = prop_dict["value"]
915+
916+
response = self.stub.updatePartsListProperties(request)
917+
918+
return_code = response.returnCode
919+
920+
if return_code.value == -1:
921+
if return_code.message == "":
922+
raise SherlockUpdatePartsListPropertiesError(error_array=response.errors)
923+
924+
raise SherlockUpdatePartsListPropertiesError(message=return_code.message)
925+
926+
return return_code.value
927+
928+
except SherlockUpdatePartsListPropertiesError as e:
929+
for error in e.str_itr():
930+
LOG.error(error)
931+
raise e

tests/test_parts.py

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
SherlockImportPartsListError,
1515
SherlockUpdatePartsFromAVLError,
1616
SherlockUpdatePartsListError,
17+
SherlockUpdatePartsListPropertiesError,
1718
SherlockUpdatePartsLocationsByFileError,
1819
SherlockUpdatePartsLocationsError,
1920
)
@@ -34,6 +35,8 @@ def test_all():
3435

3536
helper_test_update_parts_list(parts)
3637
time.sleep(1)
38+
helper_test_update_parts_list_properties(parts)
39+
time.sleep(1)
3740
helper_test_update_parts_from_AVL(parts)
3841
helper_test_update_parts_locations(parts)
3942
helper_test_update_parts_locations_by_file(parts)
@@ -672,5 +675,160 @@ def helper_test_get_part_location(parts):
672675
assert str(e) == "Get part location error: Location unit is invalid."
673676

674677

678+
def helper_test_update_parts_list_properties(parts):
679+
"""Test update_parts_list_properties API"""
680+
try:
681+
parts.update_parts_list_properties(
682+
"",
683+
"CCA_Name",
684+
[
685+
{
686+
"reference_designators": ["C1"],
687+
"properties": [{"name": "partType", "value": "RESISTOR"}],
688+
}
689+
],
690+
)
691+
pytest.fail("No exception raised when using an invalid parameter")
692+
except SherlockUpdatePartsListPropertiesError as e:
693+
assert str(e.str_itr()) == (
694+
"['Update parts list properties error: Project name is invalid.']"
695+
)
696+
697+
try:
698+
parts.update_parts_list_properties(
699+
"Test",
700+
"",
701+
[
702+
{
703+
"reference_designators": ["C1"],
704+
"properties": [{"name": "partType", "value": "RESISTOR"}],
705+
}
706+
],
707+
)
708+
pytest.fail("No exception raised when using an invalid parameter")
709+
except SherlockUpdatePartsListPropertiesError as e:
710+
assert str(e.str_itr()) == "['Update parts list properties error: CCA name is invalid.']"
711+
712+
try:
713+
parts.update_parts_list_properties("Test", "CCA_Name", [])
714+
pytest.fail("No exception raised when using an invalid parameter")
715+
except SherlockUpdatePartsListPropertiesError as e:
716+
assert str(e.str_itr()) == (
717+
"['Update parts list properties error: Part properties are missing.']"
718+
)
719+
720+
try:
721+
parts.update_parts_list_properties(
722+
"Test",
723+
"CCA_name",
724+
[
725+
{
726+
"reference_designators": ["C1"],
727+
"properties": [{"name": "partType", "value": "RESISTOR"}],
728+
"test": "test",
729+
}
730+
],
731+
)
732+
pytest.fail("No exception raised when using an invalid parameter")
733+
except SherlockUpdatePartsListPropertiesError as e:
734+
assert str(e.str_itr()) == (
735+
"['Update parts list properties error: Number of elements (3) "
736+
"is wrong for part list property 0.']"
737+
)
738+
739+
try:
740+
parts.update_parts_list_properties(
741+
"Test",
742+
"CCA_name",
743+
[
744+
{
745+
"reference_designators": "C1",
746+
"properties": [{"name": "partType", "value": "RESISTOR"}],
747+
}
748+
],
749+
)
750+
pytest.fail("No exception raised when using an invalid parameter")
751+
except SherlockUpdatePartsListPropertiesError as e:
752+
assert str(e.str_itr()) == (
753+
"['Update parts list properties error: reference_designators is not a list "
754+
"for parts list property 0.']"
755+
)
756+
757+
try:
758+
parts.update_parts_list_properties(
759+
"Test",
760+
"CCA_name",
761+
[
762+
{
763+
"reference_designators": ["C1"],
764+
"properties": [{"name": "partType", "value": "RESISTOR", "test": "test"}],
765+
}
766+
],
767+
)
768+
pytest.fail("No exception raised when using an invalid parameter")
769+
except SherlockUpdatePartsListPropertiesError as e:
770+
assert str(e.str_itr()) == (
771+
"['Update parts list properties error: Number of elements (3) "
772+
"is wrong for property 0.']"
773+
)
774+
775+
try:
776+
parts.update_parts_list_properties(
777+
"Test",
778+
"CCA_name",
779+
[{"reference_designators": ["C1"], "properties": [{"name": "", "value": "RESISTOR"}]}],
780+
)
781+
pytest.fail("No exception raised when using an invalid parameter")
782+
except SherlockUpdatePartsListPropertiesError as e:
783+
assert str(e.str_itr()) == (
784+
"['Update parts list properties error: Name is required for property 0.']"
785+
)
786+
787+
try:
788+
parts.update_parts_list_properties(
789+
"Test",
790+
"CCA_name",
791+
[{"reference_designators": ["C1"], "properties": [{"name": "partType", "value": 0}]}],
792+
)
793+
pytest.fail("No exception raised when using an invalid parameter")
794+
except SherlockUpdatePartsListPropertiesError as e:
795+
assert str(e.str_itr()) == ("['Update parts list properties error: Value is invalid.']")
796+
797+
if not parts._is_connection_up():
798+
return
799+
800+
try:
801+
parts.update_parts_list_properties(
802+
"Invalid project",
803+
"CCA_name",
804+
[
805+
{
806+
"reference_designators": ["C1"],
807+
"properties": [{"name": "partType", "value": "RESISTOR"}],
808+
}
809+
],
810+
)
811+
pytest.fail("No exception raised when using an invalid parameter")
812+
except Exception as e:
813+
assert type(e) == SherlockUpdatePartsListPropertiesError
814+
815+
try:
816+
result = parts.update_parts_list_properties(
817+
"Tutorial Project",
818+
"Main Board",
819+
[
820+
{
821+
"reference_designators": ["C1"],
822+
"properties": [{"name": "partType", "value": "RESISTOR"}],
823+
}
824+
],
825+
)
826+
827+
assert result == 0
828+
829+
except Exception as e:
830+
pytest.fail(e.message)
831+
832+
675833
if __name__ == "__main__":
676834
test_all()

0 commit comments

Comments
 (0)