Skip to content

Commit 74bc3c2

Browse files
authored
Fix issue 410 where the latest typeguard version 3.x is incompatible (#411)
* Set typeguard version to be about 2.12.1 to avoid incompatible v3 Signed-off-by: M Q <mingmelvinq@nvidia.com> * Set typeguard ver close to 2.12.1 to avoid incompatible v3 Signed-off-by: M Q <mingmelvinq@nvidia.com> * Fixed complaints by black (new version) Signed-off-by: M Q <mingmelvinq@nvidia.com> * Excluded two files to avoid black complaint but it never stated what's wrong Signed-off-by: M Q <mingmelvinq@nvidia.com> * Exclude files with relative path due to unknown black complaints Signed-off-by: M Q <mingmelvinq@nvidia.com> * Another small fix to get the exclude list work Signed-off-by: M Q <mingmelvinq@nvidia.com> * Fixed local file permission issue causing black to fail Signed-off-by: M Q <mingmelvinq@nvidia.com> * Changes to fix flake8 complaints Signed-off-by: M Q <mingmelvinq@nvidia.com> * More falke8 complaint fix Signed-off-by: M Q <mingmelvinq@nvidia.com> * Flake8 fix Signed-off-by: M Q <mingmelvinq@nvidia.com> * Input folder required by the new versio of pytype Signed-off-by: M Q <mingmelvinq@nvidia.com> * Used pyproject.toml for pytype config as the existing config is out of date Also, need to update the code to quiet the complaints from pytype. A couple errors in the source code need to be investigated but for now ignored Signed-off-by: M Q <mingmelvinq@nvidia.com> * isort: Imports are incorrectly sorted and/or formatted. Signed-off-by: M Q <mingmelvinq@nvidia.com> * Gtihub run of pytype complains about import-error though local run does not! Signed-off-by: M Q <mingmelvinq@nvidia.com> * mypy complains about the fix required by flake8; the latter is wrong and quieted Signed-off-by: M Q <mingmelvinq@nvidia.com> --------- Signed-off-by: M Q <mingmelvinq@nvidia.com>
1 parent 42bec18 commit 74bc3c2

24 files changed

+95
-65
lines changed

examples/apps/ai_livertumor_seg_app/livertumor_seg_operator.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,14 +52,12 @@ class LiverTumorSegOperator(Operator):
5252
"""
5353

5454
def __init__(self):
55-
5655
self.logger = logging.getLogger("{}.{}".format(__name__, type(self).__name__))
5756
super().__init__()
5857
self._input_dataset_key = "image"
5958
self._pred_dataset_key = "pred"
6059

6160
def compute(self, op_input: InputContext, op_output: OutputContext, context: ExecutionContext):
62-
6361
input_image = op_input.get("image")
6462
if not input_image:
6563
raise ValueError("Input image is not found.")

examples/apps/ai_unetr_seg_app/unetr_seg_operator.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,14 +46,12 @@ class UnetrSegOperator(Operator):
4646
"""
4747

4848
def __init__(self):
49-
5049
self.logger = logging.getLogger("{}.{}".format(__name__, type(self).__name__))
5150
super().__init__()
5251
self._input_dataset_key = "image"
5352
self._pred_dataset_key = "pred"
5453

5554
def compute(self, op_input: InputContext, op_output: OutputContext, context: ExecutionContext):
56-
5755
input_image = op_input.get("image")
5856
if not input_image:
5957
raise ValueError("Input image is not found.")

monai/deploy/core/application.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ def __init__(
8282
self.description = get_docstring(self.__class__)
8383
if not self.version:
8484
try:
85-
from _version import get_versions
85+
from monai.deploy._version import get_versions
8686

8787
self.version = get_versions()["version"]
8888
except ImportError:

monai/deploy/core/executors/single_process_executor.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ def run(self):
141141
)
142142

143143
next_op_exec_context = ExecutionContext(exec_context, next_op)
144-
for (out_label, in_labels) in io_map.items():
144+
for out_label, in_labels in io_map.items():
145145
output = op_exec_context.output_context.get(out_label)
146146
for in_label in in_labels:
147147
next_op_exec_context.input_context.set(output, in_label)

monai/deploy/core/graphs/nx_digraph.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,5 +52,5 @@ def gen_worklist(self) -> Generator[Optional[Operator], None, None]:
5252
return worklist
5353

5454
def gen_next_operators(self, op: Operator) -> Generator[Optional[Operator], None, None]:
55-
for (_, v) in self._graph.out_edges(op):
55+
for _, v in self._graph.out_edges(op):
5656
yield v

monai/deploy/operators/dicom_data_loader_operator.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,6 @@ def _load_data(self, files: List[str]):
118118
logging.warning(f"Ignored {file}, reason being: {ex}")
119119

120120
for sop_instance in sop_instances:
121-
122121
study_instance_uid = sop_instance[0x0020, 0x000D].value.name # name is the UID as str
123122

124123
if study_instance_uid not in study_dict:

monai/deploy/operators/dicom_encapsulated_pdf_writer_operator.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@
4242
@md.output("dicom_instance", DataPath, IOType.DISK)
4343
@md.env(pip_packages=["pydicom >= 1.4.2", "PyPDF2 >= 2.11.1", "monai"])
4444
class DICOMEncapsulatedPDFWriterOperator(Operator):
45-
4645
DCM_EXTENSION = ".dcm"
4746

4847
def __init__(

monai/deploy/operators/dicom_seg_writer_operator.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
import datetime
1313
import logging
14+
import os
1415
from pathlib import Path
1516
from random import randint
1617
from typing import TYPE_CHECKING, Dict, List, Optional, Sequence, Union

monai/deploy/operators/dicom_series_to_volume_operator.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -389,7 +389,6 @@ def _get_instance_properties(obj: object, not_none: bool = True) -> Dict:
389389

390390

391391
def test():
392-
393392
from pathlib import Path
394393

395394
from monai.deploy.operators.dicom_data_loader_operator import DICOMDataLoaderOperator

monai/deploy/operators/dicom_text_sr_writer_operator.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@
3939
@md.output("dicom_instance", DataPath, IOType.DISK)
4040
@md.env(pip_packages=["pydicom >= 1.4.2", "monai"])
4141
class DICOMTextSRWriterOperator(Operator):
42-
4342
# File extension for the generated DICOM Part 10 file.
4443
DCM_EXTENSION = ".dcm"
4544

monai/deploy/operators/dicom_utils.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,6 @@ class ModelInfo(object):
6060
"""
6161

6262
def __init__(self, creator: str = "", name: str = "", version: str = "", uid: str = ""):
63-
6463
self.creator = creator if isinstance(creator, str) else ""
6564
self.name = name if isinstance(name, str) else ""
6665
self.version = version if isinstance(version, str) else ""
@@ -77,7 +76,6 @@ def __init__(
7776
series_number: str = "0000",
7877
software_version_number: str = "",
7978
):
80-
8179
self.manufacturer = manufacturer if isinstance(manufacturer, str) else ""
8280
self.manufacturer_model = manufacturer_model if isinstance(manufacturer_model, str) else ""
8381
self.series_number = series_number if isinstance(series_number, str) else ""

monai/deploy/operators/monai_bundle_inference_operator.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,8 @@ def _read_from_archive(archive, root_name: str, config_name: str, do_search=True
7878

7979
# Try directly read with constructed and expected path into the archive
8080
for suffix in bundle_suffixes:
81+
path = Path(root_name, config_folder, config_name).with_suffix(suffix)
8182
try:
82-
path = Path(root_name, config_folder, config_name).with_suffix(suffix)
8383
logging.debug(f"Trying to read config '{config_name}' content from {path}.")
8484
content_text = archive.read(str(path))
8585
break
@@ -268,6 +268,7 @@ def _ensure_str_list(config_names):
268268

269269
DEFAULT_BundleConfigNames = BundleConfigNames()
270270

271+
271272
# The operator env decorator defines the required pip packages commonly used in the Bundles.
272273
# The MONAI Deploy App SDK packager currently relies on the App to consolidate all required packages in order to
273274
# install them in the MAP Docker image.
@@ -768,7 +769,6 @@ def _convert_from_image(self, img: Image) -> Tuple[np.ndarray, Dict]:
768769
or ("spacing" in img_meta_dict and "original_affine" in img_meta_dict)
769770
or "row_pixel_spacing" not in img_meta_dict
770771
):
771-
772772
return img.asnumpy(), img_meta_dict
773773
else:
774774
return self._convert_from_image_dicom_source(img)

monai/deploy/utils/importutil.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ def exact_version(the_module, version_str: str = "") -> bool:
155155
Returns True if the module's __version__ matches version_str
156156
"""
157157
if not hasattr(the_module, "__version__"):
158-
warnings.warn(f"{the_module} has no attribute __version__ in exact_version check.")
158+
warnings.warn(f"{the_module} has no attribute __version__ in exact_version check.", stacklevel=2)
159159
return False
160160
return bool(the_module.__version__ == version_str)
161161

notebooks/tutorials/02_mednist_app-prebuilt.ipynb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@
8484
"Collecting networkx>=2.4\n",
8585
" Downloading networkx-2.5.1-py3-none-any.whl (1.6 MB)\n",
8686
"\u001b[K |████████████████████████████████| 1.6 MB 12.8 MB/s eta 0:00:01\n",
87-
"\u001b[?25hCollecting typeguard>=2.12.1\n",
87+
"\u001b[?25hCollecting typeguard~=2.12.1\n",
8888
" Downloading typeguard-2.12.1-py3-none-any.whl (17 kB)\n",
8989
"Collecting numpy>=1.17\n",
9090
" Downloading numpy-1.19.5-cp36-cp36m-manylinux2010_x86_64.whl (14.8 MB)\n",

notebooks/tutorials/03_segmentation_app.ipynb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@
104104
"!python -c \"import pydicom\" || pip install -q \"pydicom>=1.4.2\"\n",
105105
"!python -c \"import highdicom\" || pip install -q \"highdicom>=0.18.2\"\n",
106106
"!python -c \"import SimpleITK\" || pip install -q \"SimpleITK>=2.0.0\"\n",
107-
"!python -c \"import typeguard\" || pip install -q \"typeguard>=2.12.1\"\n",
107+
"!python -c \"import typeguard\" || pip install -q \"typeguard~=2.12.1\"\n",
108108
"\n",
109109
"# Install MONAI Deploy App SDK package\n",
110110
"!python -c \"import monai.deploy\" || pip install --upgrade -q \"monai-deploy-app-sdk\""

notebooks/tutorials/03_segmentation_viz_app.ipynb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@
113113
"!python -c \"import pydicom\" || pip install -q \"pydicom>=1.4.2\"\n",
114114
"!python -c \"import highdicom\" || pip install -q \"highdicom>=0.18.2\"\n",
115115
"!python -c \"import SimpleITK\" || pip install -q \"SimpleITK>=2.0.0\"\n",
116-
"!python -c \"import typeguard\" || pip install -q \"typeguard>=2.12.1\"\n",
116+
"!python -c \"import typeguard\" || pip install -q \"typeguard~=2.12.1\"\n",
117117
"\n",
118118
"# Install MONAI Deploy App SDK package\n",
119119
"!python -c \"import monai.deploy\" || pip install --upgrade -q \"monai-deploy-app-sdk\"\n",

notebooks/tutorials/06_monai_bundle_app.ipynb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@
106106
"!python -c \"import pydicom\" || pip install -q \"pydicom>=1.4.2\"\n",
107107
"!python -c \"import highdicom\" || pip install -q \"highdicom>=0.18.2\"\n",
108108
"!python -c \"import SimpleITK\" || pip install -q \"SimpleITK>=2.0.0\"\n",
109-
"!python -c \"import typeguard\" || pip install -q \"typeguard>=2.12.1\"\n",
109+
"!python -c \"import typeguard\" || pip install -q \"typeguard~=2.12.1\"\n",
110110
"\n",
111111
"# Install MONAI Deploy App SDK package\n",
112112
"!python -c \"import monai.deploy\" || pip install --upgrade -q \"monai-deploy-app-sdk\""

notebooks/tutorials/07_multi_model_app.ipynb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@
144144
"!python -c \"import pydicom\" || pip install -q \"pydicom>=1.4.2\"\n",
145145
"!python -c \"import highdicom\" || pip install -q \"highdicom>=0.18.2\"\n",
146146
"!python -c \"import SimpleITK\" || pip install -q \"SimpleITK>=2.0.0\"\n",
147-
"!python -c \"import typeguard\" || pip install -q \"typeguard>=2.12.1\"\n",
147+
"!python -c \"import typeguard\" || pip install -q \"typeguard~=2.12.1\"\n",
148148
"\n",
149149
"# Install MONAI Deploy App SDK package\n",
150150
"!python -c \"import monai.deploy\" || pip install --upgrade -q \"monai-deploy-app-sdk\""

platforms/nuance_pin/app/inference.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,6 @@ def detection_list(self):
8282
@md.env(pip_packages=["monai>=0.8.1", "torch>=1.5", "numpy>=1.21", "nibabel"])
8383
class LungNoduleInferenceOperator(Operator):
8484
def __init__(self, model_path: str = "model/model.ts"):
85-
8685
self.logger = logging.getLogger("{}.{}".format(__name__, type(self).__name__))
8786
super().__init__()
8887
self._input_dataset_key = "image"
@@ -125,7 +124,6 @@ def __init__(self, model_path: str = "model/model.ts"):
125124
self.detector.eval()
126125

127126
def compute(self, op_input: InputContext, op_output: OutputContext, context: ExecutionContext):
128-
129127
input_image = op_input.get("image")
130128
if not input_image:
131129
raise ValueError("Input image not found.")

platforms/nuance_pin/app/post_inference_ops.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ def __init__(self, pin_processor: Optional[AiJobProcessor], *args, **kwargs):
3636
self.pin_processor = pin_processor
3737

3838
def compute(self, op_input: InputContext, op_output: OutputContext, context: ExecutionContext):
39-
4039
selected_study = op_input.get("original_dicom")[0] # assuming a single study
4140
selected_series = selected_study.selected_series[0] # assuming a single series
4241
detection_result: DetectionResult = op_input.get("detection_predictions").detection_list[0]
@@ -60,7 +59,6 @@ def compute(self, op_input: InputContext, op_output: OutputContext, context: Exe
6059
accession = all_ref_images[0].AccessionNumber
6160

6261
for inst_num, (box_data, box_score) in enumerate(zip(detection_result.box_data, detection_result.score_data)):
63-
6462
tracking_id = f"{accession}_nodule_{inst_num}" # site-specific ID
6563
tracking_uid = hd.UID()
6664

@@ -160,7 +158,6 @@ def __init__(self, pin_processor: Optional[AiJobProcessor], *args, **kwargs):
160158
self.pin_processor = pin_processor
161159

162160
def compute(self, op_input: InputContext, op_output: OutputContext, context: ExecutionContext):
163-
164161
selected_study = op_input.get("original_dicom")[0] # assuming a single study
165162
selected_series = selected_study.selected_series[0] # assuming a single series
166163
detection_result: DetectionResult = op_input.get("detection_predictions").detection_list[0]
@@ -190,7 +187,6 @@ def compute(self, op_input: InputContext, op_output: OutputContext, context: Exe
190187
slice_coords = list(range(len(selected_series.series.get_sop_instances())))
191188

192189
for box_data, box_score in zip(detection_result.box_data, detection_result.score_data):
193-
194190
affected_slice_idx = [
195191
idx
196192
for idx, slice_coord in enumerate(slice_coords)

platforms/nuance_pin/app_wrapper.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,6 @@
5050

5151

5252
class MONAIAppWrapper(AiJobProcessor):
53-
5453
partner_name = os.environ["AI_PARTNER_NAME"]
5554
service_name = os.environ["AI_SVC_NAME"]
5655
service_version = os.environ["AI_SVC_VERSION"]

pyproject.toml

Lines changed: 74 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,5 +36,78 @@ exclude = '''
3636
'''
3737

3838
# https://github.com/microsoft/pyright/blob/main/docs/configuration.md
39+
# NOTE: All relative paths are relative to the location of this file.
3940
[tool.pyright]
40-
ignore = ["versioneer.py", "_version.py"]
41+
ignore = ["versioneer.py", "_version.py"]
42+
43+
# https://google.github.io/pytype/
44+
[tool.pytype]
45+
# Space-separated list of files or directories to exclude.
46+
exclude = [
47+
'versioneer.py',
48+
'_version.py',
49+
'**/_version.py',
50+
]
51+
# Space-separated list of files or directories to process.
52+
inputs = [
53+
'monai',
54+
]
55+
# Keep going past errors to analyze as many files as possible.
56+
keep_going = true
57+
# Run N jobs in parallel. When 'auto' is used, this will be equivalent to the
58+
# number of CPUs on the host system.
59+
jobs = 8
60+
# All pytype output goes here.
61+
output = '.pytype'
62+
# Platform (e.g., "linux", "win32") that the target code runs on.
63+
platform = 'linux'
64+
# Paths to source code directories, separated by ':'.
65+
pythonpath = '.'
66+
67+
# Always use function return type annotations. This flag is temporary and will
68+
# be removed once this behavior is enabled by default.
69+
always_use_return_annotations = false
70+
71+
# Enable parameter count checks for overriding methods. This flag is temporary
72+
# and will be removed once this behavior is enabled by default.
73+
overriding_parameter_count_checks = false
74+
75+
# Enable return type checks for overriding methods. This flag is temporary and
76+
# will be removed once this behavior is enabled by default.
77+
overriding_return_type_checks = true
78+
79+
# Use the enum overlay for more precise enum checking. This flag is temporary
80+
# and will be removed once this behavior is enabled by default.
81+
use_enum_overlay = false
82+
83+
# Opt-in: Do not allow Any as a return type.
84+
no_return_any = false
85+
86+
# Experimental: Support pyglib's @cached.property.
87+
enable_cached_property = false
88+
89+
# Experimental: Infer precise return types even for invalid function calls.
90+
precise_return = false
91+
92+
# Experimental: Solve unknown types to label with structural types.
93+
protocols = false
94+
95+
# Experimental: Only load submodules that are explicitly imported.
96+
strict_import = false
97+
98+
# Experimental: Enable exhaustive checking of function parameter types.
99+
strict_parameter_checks = false
100+
101+
# Experimental: Emit errors for comparisons between incompatible primitive
102+
# types.
103+
strict_primitive_comparisons = false
104+
105+
# Space-separated list of error names to ignore.
106+
disable = [
107+
'pyi-error',
108+
'container-type-mismatch',
109+
'attribute-error',
110+
]
111+
112+
# Don't report errors.
113+
report_errors = true

requirements.txt

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

setup.cfg

Lines changed: 8 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ install_requires =
2626
numpy>=1.21.6
2727
networkx>=2.4
2828
colorama>=0.4.1
29-
typeguard>=2.12.1
29+
typeguard~=2.12.1
3030

3131
[options.extras_require]
3232
all =
@@ -43,8 +43,13 @@ ignore =
4343
E203,E305,E402,E501,E721,E741,F821,F841,F999,W503,W504,C408,E302,W291,E303,
4444
# N812 lowercase 'torch.nn.functional' imported as non lowercase 'F'
4545
N812,
46-
B024, #abstract base class, but it has no abstract methods
47-
B027 #method in base class with no implementation
46+
#B024, abstract base class, but it has no abstract methods
47+
B024,
48+
# B027, #method in base class with no implementation
49+
B027,
50+
# B905 `zip()` without an explicit `strict=` parameter, but conflicting with pytype
51+
B905
52+
4853
per_file_ignores =
4954
__init__.py: F401
5055
# Allow using camel case for variable/argument names for the sake of readability.
@@ -105,38 +110,6 @@ ignore_errors = True
105110
# Ignores all non-fatal errors.
106111
ignore_errors = True
107112

108-
[pytype]
109-
# Space-separated list of files or directories to exclude.
110-
exclude = versioneer.py _version.py
111-
# Space-separated list of files or directories to process.
112-
inputs = monai
113-
# Keep going past errors to analyze as many files as possible.
114-
keep_going = True
115-
# Run N jobs in parallel.
116-
jobs = 8
117-
# All pytype output goes here.
118-
output = .pytype
119-
# Paths to source code directories, separated by ':'.
120-
pythonpath = .
121-
# Check attribute values against their annotations.
122-
check_attribute_types = True
123-
# Check container mutations against their annotations.
124-
check_container_types = True
125-
# Check parameter defaults and assignments against their annotations.
126-
check_parameter_types = True
127-
# Check variable values against their annotations.
128-
check_variable_types = True
129-
# Comma or space separated list of error names to ignore.
130-
disable = pyi-error
131-
# Report errors.
132-
report_errors = True
133-
# Experimental: Infer precise return types even for invalid function calls.
134-
precise_return = True
135-
# Experimental: solve unknown types to label with structural types.
136-
protocols = True
137-
# Experimental: Only load submodules that are explicitly imported.
138-
strict_import = False
139-
140113
[tool:pytest]
141114
# If a pytest section is found in one of the possible config files
142115
# (pytest.ini, tox.ini or setup.cfg), then pytest will not look for any others,

0 commit comments

Comments
 (0)