Skip to content

Commit d0aea57

Browse files
authored
Merge pull request #114 from Project-MONAI/verify_io_types
Verify operator IO data types with typeguard
2 parents 8a2aa60 + c7d4868 commit d0aea57

File tree

4 files changed

+19
-3
lines changed

4 files changed

+19
-3
lines changed

monai/deploy/core/io_context.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
from abc import ABC
1313
from typing import TYPE_CHECKING, Any, Set
1414

15+
from typeguard import check_type
16+
1517
# To avoid "Cannot resolve forward reference" error
1618
# : https://github.com/agronholm/sphinx-autodoc-typehints#dealing-with-circular-imports
1719
from . import execution_context
@@ -101,6 +103,19 @@ def set(self, value: Any, label: str = ""):
101103
# This is to keep the actual path of the data in the storage across different Operator execution contexts.
102104
if isinstance(value, DataPath):
103105
value.to_absolute()
106+
107+
# Verify the type of the value is matching the type of the input/output of the operator.
108+
# Use 'typeguard' package because Python's built-in isinstance() does not support parameterized generic type
109+
# checking: https://www.python.org/dev/peps/pep-0585/#id15
110+
data_type = self._op_info.get_data_type(self._io_kind, label)
111+
try:
112+
check_type("value", value, data_type)
113+
except TypeError:
114+
raise IOMappingError(
115+
f"The data type of '{label}' in the {self._io_kind} of '{self._op}' is {data_type}, but the value"
116+
f" to set is the data type of {type(value)}."
117+
)
118+
104119
storage.put(key, value)
105120

106121

monai/deploy/operators/dicom_data_loader_operator.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434

3535

3636
@input("dicom_files", DataPath, IOType.DISK)
37-
@output("dicom_study_list", DICOMStudy, IOType.IN_MEMORY)
37+
@output("dicom_study_list", List[DICOMStudy], IOType.IN_MEMORY)
3838
@env(pip_packages=["pydicom >= 1.4.2"])
3939
class DICOMDataLoaderOperator(Operator):
4040
"""

monai/deploy/operators/dicom_series_selector_operator.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
# See the License for the specific language governing permissions and
1010
# limitations under the License.
1111

12-
from typing import Dict
12+
from typing import Dict, List
1313

1414
from monai.deploy.core import ExecutionContext, InputContext, IOType, Operator, OutputContext, input, output
1515
from monai.deploy.core.domain.dicom_series import DICOMSeries
@@ -18,7 +18,7 @@
1818
from monai.deploy.operators.dicom_data_loader_operator import DICOMDataLoaderOperator
1919

2020

21-
@input("dicom_study_list", DICOMStudy, IOType.IN_MEMORY)
21+
@input("dicom_study_list", List[DICOMStudy], IOType.IN_MEMORY)
2222
@input("selection_rules", Dict, IOType.IN_MEMORY)
2323
@output("dicom_series", DICOMSeries, IOType.IN_MEMORY)
2424
class DICOMSeriesSelectorOperator(Operator):

requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
numpy>=1.17
22
networkx>=2.4
33
colorama>=0.4.1
4+
typeguard>=2.12.1

0 commit comments

Comments
 (0)