Skip to content

Commit 74eeb99

Browse files
feat: Added APIs delete_event() and delete_phase() (#648)
Co-authored-by: pyansys-ci-bot <[email protected]>
1 parent 2c53f13 commit 74eeb99

File tree

5 files changed

+283
-0
lines changed

5 files changed

+283
-0
lines changed

doc/changelog.d/648.added.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Feat: Added APIs delete_event() and delete_phase()

src/ansys/sherlock/core/errors.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1304,3 +1304,15 @@ def __init__(self, message):
13041304
def __str__(self):
13051305
"""Format error message."""
13061306
return f"Save profile error: {self.message}"
1307+
1308+
1309+
class SherlockDeleteError(Exception):
1310+
"""Contains the errors raised when an event or a phase cannot be deleted."""
1311+
1312+
def __init__(self, message):
1313+
"""Initialize error message."""
1314+
self.message = message
1315+
1316+
def __str__(self):
1317+
"""Format error message."""
1318+
return f"Delete error: {self.message}"

src/ansys/sherlock/core/lifecycle.py

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
SherlockAddThermalEventError,
2424
SherlockAddThermalProfilesError,
2525
SherlockCreateLifePhaseError,
26+
SherlockDeleteError,
2627
SherlockInvalidHarmonicProfileEntriesError,
2728
SherlockInvalidLoadDirectionError,
2829
SherlockInvalidOrientationError,
@@ -39,6 +40,8 @@
3940
)
4041
from ansys.sherlock.core.grpc_stub import GrpcStub
4142
from ansys.sherlock.core.types.lifecycle_types import (
43+
DeleteEventRequest,
44+
DeletePhaseRequest,
4245
ImportThermalSignalRequest,
4346
SaveHarmonicProfileRequest,
4447
SaveRandomVibeProfileRequest,
@@ -2353,3 +2356,86 @@ def save_thermal_profile(
23532356
# Raise error if save failed
23542357
if response.value != 0:
23552358
raise SherlockSaveProfileError(response.message)
2359+
2360+
@require_version(261)
2361+
def delete_event(self, request: DeleteEventRequest) -> SherlockCommonService_pb2.ReturnCode:
2362+
"""Delete a life cycle event from a given phase in a project.
2363+
2364+
Available Since: 2026R1
2365+
2366+
Parameters
2367+
----------
2368+
request : DeleteEventRequest
2369+
Request object containing project, phase name, and event name.
2370+
2371+
Returns
2372+
-------
2373+
SherlockCommonService_pb2.ReturnCode
2374+
Status code of the response. 0 for success.
2375+
2376+
Examples
2377+
--------
2378+
>>> from ansys.sherlock.core.types.lifecycle_types import DeleteEventRequest
2379+
>>> from ansys.sherlock.core.launcher import launch_sherlock
2380+
>>> sherlock = launch_sherlock()
2381+
>>> response = sherlock.lifecycle.delete_event(
2382+
>>> DeleteEventRequest(
2383+
>>> project="MyProject",
2384+
>>> phase_name="ThermalPhase",
2385+
>>> event_name="ThermalCycle_A",
2386+
>>> )
2387+
>>> )
2388+
>>> assert response.value == 0
2389+
"""
2390+
grpc_request = request._convert_to_grpc()
2391+
2392+
if not self._is_connection_up():
2393+
raise SherlockNoGrpcConnectionException()
2394+
2395+
response = self.stub.deleteEvent(grpc_request)
2396+
2397+
if response.value != 0:
2398+
raise SherlockDeleteError(response.message)
2399+
2400+
return response
2401+
2402+
@require_version(261)
2403+
def delete_phase(self, request: DeletePhaseRequest) -> SherlockCommonService_pb2.ReturnCode:
2404+
"""Delete a life cycle phase from a project.
2405+
2406+
Available Since: 2026R1
2407+
2408+
Parameters
2409+
----------
2410+
request : DeletePhaseRequest
2411+
Request object containing project and phase name.
2412+
2413+
Returns
2414+
-------
2415+
SherlockCommonService_pb2.ReturnCode
2416+
Status code of the response. 0 for success.
2417+
2418+
Examples
2419+
--------
2420+
>>> from ansys.sherlock.core.types.lifecycle_types import DeletePhaseRequest
2421+
>>> from ansys.sherlock.core.launcher import launch_sherlock
2422+
>>> sherlock = launch_sherlock()
2423+
>>> response = sherlock.lifecycle.delete_phase(
2424+
>>> DeletePhaseRequest(
2425+
>>> project="MyProject",
2426+
>>> phase_name="ThermalPhase",
2427+
>>> )
2428+
>>> )
2429+
>>> assert response.value == 0
2430+
"""
2431+
grpc_request = request._convert_to_grpc()
2432+
2433+
if not self._is_connection_up():
2434+
raise SherlockNoGrpcConnectionException()
2435+
2436+
response = self.stub.deletePhase(grpc_request)
2437+
2438+
if response.value != 0:
2439+
raise SherlockDeleteError(response.message)
2440+
2441+
return response

src/ansys/sherlock/core/types/lifecycle_types.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,3 +252,53 @@ def _convert_to_grpc(self) -> SherlockLifeCycleService_pb2.SaveThermalProfileReq
252252
eventName=self.event_name,
253253
filePath=self.file_path,
254254
)
255+
256+
257+
class DeleteEventRequest(BaseModel):
258+
"""Request to delete a life cycle event from a project phase."""
259+
260+
project: str
261+
"""Sherlock project name."""
262+
263+
phase_name: str
264+
"""The name of the life cycle phase from which to delete this event."""
265+
266+
event_name: str
267+
"""Name of the event to be deleted."""
268+
269+
@field_validator("project", "phase_name", "event_name")
270+
@classmethod
271+
def str_validation(cls, value: str, info: ValidationInfo):
272+
"""Validate string fields listed."""
273+
return basic_str_validator(value, info.field_name)
274+
275+
def _convert_to_grpc(self) -> SherlockLifeCycleService_pb2.DeleteEventRequest:
276+
"""Convert to gRPC DeleteEventRequest."""
277+
return SherlockLifeCycleService_pb2.DeleteEventRequest(
278+
project=self.project,
279+
phaseName=self.phase_name,
280+
eventName=self.event_name,
281+
)
282+
283+
284+
class DeletePhaseRequest(BaseModel):
285+
"""Request to delete a life cycle phase from a project."""
286+
287+
project: str
288+
"""Sherlock project name."""
289+
290+
phase_name: str
291+
"""Name of the life cycle phase to be deleted."""
292+
293+
@field_validator("project", "phase_name")
294+
@classmethod
295+
def str_validation(cls, value: str, info: ValidationInfo):
296+
"""Validate string fields listed."""
297+
return basic_str_validator(value, info.field_name)
298+
299+
def _convert_to_grpc(self) -> SherlockLifeCycleService_pb2.DeletePhaseRequest:
300+
"""Convert to gRPC DeletePhaseRequest."""
301+
return SherlockLifeCycleService_pb2.DeletePhaseRequest(
302+
project=self.project,
303+
phaseName=self.phase_name,
304+
)

tests/test_lifecycle.py

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
SherlockAddThermalEventError,
1717
SherlockAddThermalProfilesError,
1818
SherlockCreateLifePhaseError,
19+
SherlockDeleteError,
1920
SherlockLoadHarmonicProfileError,
2021
SherlockLoadRandomVibeProfileError,
2122
SherlockLoadShockProfileDatasetError,
@@ -25,6 +26,8 @@
2526
)
2627
from ansys.sherlock.core.lifecycle import Lifecycle
2728
from ansys.sherlock.core.types.lifecycle_types import (
29+
DeleteEventRequest,
30+
DeletePhaseRequest,
2831
ImportThermalSignalRequest,
2932
SaveHarmonicProfileRequest,
3033
SaveRandomVibeProfileRequest,
@@ -62,6 +65,9 @@ def test_all():
6265
helper_test_save_shock_pulse_profile(lifecycle)
6366
helper_test_save_thermal_profile(lifecycle)
6467

68+
helper_test_delete_event(lifecycle, shock_event_name, phase_name)
69+
helper_test_delete_phase(lifecycle, phase_name)
70+
6571

6672
def helper_test_create_life_phase(lifecycle: Lifecycle):
6773
"""Test create_life_phase API"""
@@ -2618,5 +2624,133 @@ def helper_test_save_thermal_profile(lifecycle: Lifecycle):
26182624
assert type(e) == SherlockSaveProfileError
26192625

26202626

2627+
def helper_test_delete_event(lifecycle: Lifecycle, event_name: str, phase_name: str):
2628+
# project missing
2629+
try:
2630+
lifecycle.delete_event(
2631+
DeleteEventRequest(
2632+
project="",
2633+
phase_name="On The Road",
2634+
event_name="ThermalCycle_A",
2635+
)
2636+
)
2637+
pytest.fail("No exception raised when using a missing project parameter")
2638+
except Exception as e:
2639+
assert isinstance(e, pydantic.ValidationError)
2640+
assert str(e.errors()[0]["msg"]) == (
2641+
"Value error, project is invalid because it is None or empty."
2642+
)
2643+
2644+
# phase_name missing
2645+
try:
2646+
lifecycle.delete_event(
2647+
DeleteEventRequest(
2648+
project="Tutorial Project",
2649+
phase_name="",
2650+
event_name="ThermalCycle_A",
2651+
)
2652+
)
2653+
pytest.fail("No exception raised when using a missing phase_name parameter")
2654+
except Exception as e:
2655+
assert isinstance(e, pydantic.ValidationError)
2656+
assert str(e.errors()[0]["msg"]) == (
2657+
"Value error, phase_name is invalid because it is None or empty."
2658+
)
2659+
2660+
# event_name missing
2661+
try:
2662+
lifecycle.delete_event(
2663+
DeleteEventRequest(
2664+
project="Tutorial Project",
2665+
phase_name="On The Road",
2666+
event_name="",
2667+
)
2668+
)
2669+
pytest.fail("No exception raised when using a missing event_name parameter")
2670+
except Exception as e:
2671+
assert isinstance(e, pydantic.ValidationError)
2672+
assert str(e.errors()[0]["msg"]) == (
2673+
"Value error, event_name is invalid because it is None or empty."
2674+
)
2675+
2676+
if lifecycle._is_connection_up():
2677+
# valid request but false event_name
2678+
try:
2679+
lifecycle.delete_event(
2680+
DeleteEventRequest(
2681+
project="Tutorial Project",
2682+
phase_name="On The Road",
2683+
event_name="NonExistingEvent",
2684+
)
2685+
)
2686+
pytest.fail("No exception raised for server error response")
2687+
except Exception as e:
2688+
assert isinstance(e, SherlockDeleteError)
2689+
2690+
# valid request with actual event
2691+
response = lifecycle.delete_event(
2692+
DeleteEventRequest(
2693+
project="Tutorial Project",
2694+
phase_name=phase_name,
2695+
event_name=event_name,
2696+
)
2697+
)
2698+
assert response.value == 0
2699+
2700+
2701+
def helper_test_delete_phase(lifecycle: Lifecycle, phase_name: str):
2702+
# project missing
2703+
try:
2704+
lifecycle.delete_phase(
2705+
DeletePhaseRequest(
2706+
project="",
2707+
phase_name="SomePhase",
2708+
)
2709+
)
2710+
pytest.fail("No exception raised when using a missing project parameter")
2711+
except Exception as e:
2712+
assert isinstance(e, pydantic.ValidationError)
2713+
assert str(e.errors()[0]["msg"]) == (
2714+
"Value error, project is invalid because it is None or empty."
2715+
)
2716+
2717+
# phase_name missing
2718+
try:
2719+
lifecycle.delete_phase(
2720+
DeletePhaseRequest(
2721+
project="Tutorial Project",
2722+
phase_name="",
2723+
)
2724+
)
2725+
pytest.fail("No exception raised when using a missing phase_name parameter")
2726+
except Exception as e:
2727+
assert isinstance(e, pydantic.ValidationError)
2728+
assert str(e.errors()[0]["msg"]) == (
2729+
"Value error, phase_name is invalid because it is None or empty."
2730+
)
2731+
2732+
if lifecycle._is_connection_up():
2733+
# valid request but false phase_name
2734+
try:
2735+
lifecycle.delete_phase(
2736+
DeletePhaseRequest(
2737+
project="Tutorial Project",
2738+
phase_name="NonExistingPhase",
2739+
)
2740+
)
2741+
pytest.fail("No exception raised for server error response")
2742+
except Exception as e:
2743+
assert isinstance(e, SherlockDeleteError)
2744+
2745+
# valid request with actual phase
2746+
response = lifecycle.delete_phase(
2747+
DeletePhaseRequest(
2748+
project="Tutorial Project",
2749+
phase_name=phase_name,
2750+
)
2751+
)
2752+
assert response.value == 0
2753+
2754+
26212755
if __name__ == "__main__":
26222756
test_all()

0 commit comments

Comments
 (0)