Skip to content

Commit 1dbeedc

Browse files
authored
Adds code for IPC files (#77)
1 parent ce23143 commit 1dbeedc

File tree

4 files changed

+83
-0
lines changed

4 files changed

+83
-0
lines changed

RATapi/controls.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
import contextlib
2+
import os
3+
import tempfile
14
import warnings
25

36
import prettytable
@@ -70,6 +73,8 @@ class Controls(BaseModel, validate_assignment=True, extra="forbid"):
7073
pUnitGamma: float = Field(0.2, gt=0.0, lt=1.0)
7174
boundHandling: BoundHandling = BoundHandling.Reflect
7275
adaptPCR: bool = True
76+
# Private field for IPC file
77+
_IPCFilePath: str = ""
7378

7479
@model_validator(mode="wrap")
7580
def warn_setting_incorrect_properties(self, handler: ValidatorFunctionWrapHandler) -> "Controls":
@@ -131,3 +136,31 @@ def __str__(self) -> str:
131136
table.field_names = ["Property", "Value"]
132137
table.add_rows([[k, v] for k, v in self.model_dump().items()])
133138
return table.get_string()
139+
140+
def initialise_IPC(self):
141+
"""Setup the inter-process communication file."""
142+
IPC_obj, self._IPCFilePath = tempfile.mkstemp()
143+
os.write(IPC_obj, b"0")
144+
os.close(IPC_obj)
145+
return None
146+
147+
def sendStopEvent(self):
148+
"""Sends the stop event via the inter-process communication file.
149+
150+
Warnings
151+
--------
152+
UserWarning
153+
Raised if we try to delete an IPC file that was not initialised.
154+
"""
155+
if os.path.isfile(self._IPCFilePath):
156+
with open(self._IPCFilePath, "wb") as f:
157+
f.write(b"1")
158+
else:
159+
warnings.warn("An IPC file was not initialised.", UserWarning, stacklevel=2)
160+
return None
161+
162+
def delete_IPC(self):
163+
"""Delete the inter-process communication file."""
164+
with contextlib.suppress(FileNotFoundError):
165+
os.remove(self._IPCFilePath)
166+
return None

RATapi/inputs.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -470,4 +470,6 @@ def make_controls(input_controls: RATapi.Controls, checks: Checks) -> Control:
470470
# IPC
471471
controls.IPCFilePath = ""
472472

473+
controls.IPCFilePath = input_controls._IPCFilePath
474+
473475
return controls

RATapi/run.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,8 @@ def run(project, controls):
130130
for index, value in enumerate(getattr(problem_definition, parameter_field[class_list])):
131131
getattr(project, class_list)[index].value = value
132132

133+
controls.delete_IPC()
134+
133135
if display_on:
134136
print("Finished RAT " + horizontal_line)
135137

tests/test_controls.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
"""Test the controls module."""
22

3+
import contextlib
4+
import os
5+
import tempfile
36
from typing import Any, Union
47

58
import pydantic
@@ -9,6 +12,17 @@
912
from RATapi.utils.enums import BoundHandling, Display, Parallel, Procedures, Strategies
1013

1114

15+
@pytest.fixture
16+
def IPC_controls():
17+
"""A controls object with a temporary file set as the IPC file."""
18+
IPC_controls = Controls()
19+
IPC_obj, IPC_controls._IPCFilePath = tempfile.mkstemp()
20+
os.close(IPC_obj)
21+
yield IPC_controls
22+
with contextlib.suppress(FileNotFoundError):
23+
os.remove(IPC_controls._IPCFilePath)
24+
25+
1226
def test_initialise_procedure_error() -> None:
1327
"""Tests for a ValidationError if the procedure property of the Controls class is initialised with an invalid
1428
value.
@@ -851,3 +865,35 @@ def test_dream_nChains_error(self, value: int) -> None:
851865
def test_control_class_dream_str(self, table_str) -> None:
852866
"""Tests the Dream model __str__."""
853867
assert self.dream.__str__() == table_str
868+
869+
870+
def test_initialise_IPC() -> None:
871+
"""Tests that an Inter-Process Communication File can be set up."""
872+
test_controls = Controls()
873+
test_controls.initialise_IPC()
874+
assert test_controls._IPCFilePath != ""
875+
with open(test_controls._IPCFilePath, "rb") as f:
876+
file_content = f.read()
877+
assert file_content == b"0"
878+
os.remove(test_controls._IPCFilePath)
879+
880+
881+
def test_sendStopEvent(IPC_controls) -> None:
882+
"""Tests that an Inter-Process Communication File can be modified."""
883+
IPC_controls.sendStopEvent()
884+
with open(IPC_controls._IPCFilePath, "rb") as f:
885+
file_content = f.read()
886+
assert file_content == b"1"
887+
888+
889+
def test_sendStopEvent_empty_file() -> None:
890+
"""Tests that we do not write to a non-existent Inter-Process Communication File."""
891+
test_controls = Controls()
892+
with pytest.warns(UserWarning, match="An IPC file was not initialised."):
893+
test_controls.sendStopEvent()
894+
895+
896+
def test_delete_IPC(IPC_controls) -> None:
897+
"""Tests that an Inter-Process Communication File can be safely removed."""
898+
IPC_controls.delete_IPC()
899+
assert not os.path.isfile(IPC_controls._IPCFilePath)

0 commit comments

Comments
 (0)