Skip to content

Commit e08dde6

Browse files
authored
Add convenience options runtests (#496)
* Add subcommands to the individual codeformat test One often wants to run the very fast codeformatting tests without running any of the unit tests. Add a commands to allow this behavior with "./runtests.sh [--black|--pytype|--mypy|--flake8]". One often wants the `black` formatting tool to automatically fix formatting violations without requiring explicit manual call. Use "./runtests.sh --black-fix" Add mypy static checking tool to monai Run the complete mypy static checking tool during evaluations of code format style checks. Related to #476 subtask for enable mypy Expand the documentation for runtest.sh script. Provide more expressive documentation for `-h` The dryrun request to print the commands used for static and format checking without actually running the commands. * Temporarily add branch needed to trigger CI of this codebase. * Suppress mypy warnings about incompatible superclass signature Related to #495 * Suppress mypy error: Cannot assign to a method Related to #494 * Mypy potential type mismatch resolved with assertion. * Mypy type ambiguity resolved.
1 parent 15c8d5e commit e08dde6

File tree

11 files changed

+200
-62
lines changed

11 files changed

+200
-62
lines changed

.github/workflows/pythonapp.yml

+12-8
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ on:
55
push:
66
branches:
77
- master
8-
- enable-pytype
8+
# TODO: Remove ci trigger branch used for testing
9+
- add-convenience-options-runtests
910
pull_request:
1011

1112
jobs:
@@ -21,16 +22,19 @@ jobs:
2122
run: |
2223
python -m pip install --upgrade pip wheel
2324
pip install -r requirements-dev.txt
24-
- name: Lint with flake8
25+
- name: Lint with black formater
2526
run: |
26-
flake8 --version
27-
python -c 'import monai; monai.config.print_config()'
28-
MYPYPATH=$(pwd)/monai flake8 $(pwd) --count --statistics
29-
- name: Type check with Pytype
27+
$(pwd)/runtests.sh --nounittests --black
28+
- name: Lint with flake8 code checker
29+
run: |
30+
$(pwd)/runtests.sh --nounittests --flake8
31+
- name: Type check with mypy static analysis
32+
run: |
33+
$(pwd)/runtests.sh --nounittests --mypy
34+
- name: Type check with Pytype static analysis
3035
run: |
31-
pytype --version
3236
# Git hub actions have 2 cores, so parallize pytype
33-
pytype -j 2 --python-version=$(python -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')")
37+
$(pwd)/runtests.sh --nounittests --pytype -j 2
3438
3539
quick-py3:
3640
runs-on: ${{ matrix.os }}

monai/handlers/segmentation_saver.py

+1
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ def __init__(
6565
name (str): identifier of logging.logger to use, defaulting to `engine.logger`.
6666
6767
"""
68+
self.saver: Union[NiftiSaver, PNGSaver]
6869
if output_ext in (".nii.gz", ".nii"):
6970
self.saver = NiftiSaver(output_dir, output_postfix, output_ext, resample, interp_order, mode, cval, dtype)
7071
elif output_ext == ".png":

monai/losses/dice.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,9 @@ class MaskedDiceLoss(DiceLoss):
141141
Same as DiceLoss, but accepts a binary mask ([0,1]) indicating a region over which to compute the dice.
142142
"""
143143

144-
def forward(self, input: torch.Tensor, target: torch.Tensor, mask: torch.Tensor = None, smooth: float = 1e-5):
144+
def forward( # type: ignore # see issue #495
145+
self, input: torch.Tensor, target: torch.Tensor, mask: torch.Tensor = None, smooth: float = 1e-5
146+
):
145147
"""
146148
Args:
147149
input (tensor): the shape should be BNH[WD].

monai/transforms/croppad/array.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ def _determine_data_pad_width(self, data_shape):
5353
else:
5454
return [(0, max(self.spatial_size[i] - data_shape[i], 0)) for i in range(len(self.spatial_size))]
5555

56-
def __call__(self, img, mode: Optional[str] = None):
56+
def __call__(self, img, mode: Optional[str] = None): # type: ignore # see issue #495
5757
data_pad_width = self._determine_data_pad_width(img.shape[1:])
5858
all_pad_width = [(0, 0)] + data_pad_width
5959
img = np.pad(img, all_pad_width, mode=mode or self.mode)

monai/transforms/post/array.py

+6-4
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ def __init__(self, to_onehot: bool = False, num_classes: Optional[int] = None):
3838
self.to_onehot = to_onehot
3939
self.num_classes = num_classes
4040

41-
def __call__(self, img, to_onehot: Optional[bool] = None, num_classes: Optional[int] = None):
41+
def __call__(self, img, to_onehot: Optional[bool] = None, num_classes: Optional[int] = None): # type: ignore # see issue #495
4242
if to_onehot or self.to_onehot:
4343
if num_classes is None:
4444
num_classes = self.num_classes
@@ -69,7 +69,7 @@ def __init__(self, sigmoid: bool = False, softmax: bool = False, other: Optional
6969
self.softmax = softmax
7070
self.other = other
7171

72-
def __call__(
72+
def __call__( # type: ignore # see issue #495
7373
self, img, sigmoid: Optional[bool] = None, softmax: Optional[bool] = None, other: Optional[Callable] = None
7474
):
7575
if sigmoid is True and softmax is True:
@@ -118,7 +118,7 @@ def __init__(
118118
self.threshold_values = threshold_values
119119
self.logit_thresh = logit_thresh
120120

121-
def __call__(
121+
def __call__( # type: ignore # see issue #495
122122
self,
123123
img,
124124
argmax: Optional[bool] = None,
@@ -131,7 +131,9 @@ def __call__(
131131
img = torch.argmax(img, dim=1, keepdim=True)
132132

133133
if to_onehot or self.to_onehot:
134-
img = one_hot(img, self.n_classes if n_classes is None else n_classes)
134+
_nclasses = self.n_classes if n_classes is None else n_classes
135+
assert isinstance(_nclasses, int), "One of self.n_classes or n_classes must be an integer"
136+
img = one_hot(img, _nclasses)
135137

136138
if threshold_values or self.threshold_values:
137139
img = img >= (self.logit_thresh if logit_thresh is None else logit_thresh)

monai/transforms/spatial/array.py

+11-11
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ def __init__(
7979
self.cval = cval
8080
self.dtype = dtype
8181

82-
def __call__(
82+
def __call__( # type: ignore # see issue #495
8383
self,
8484
data_array: np.ndarray,
8585
affine=None,
@@ -162,7 +162,7 @@ def __init__(self, axcodes=None, as_closest_canonical: bool = False, labels=tupl
162162
self.as_closest_canonical = as_closest_canonical
163163
self.labels = labels
164164

165-
def __call__(self, data_array: np.ndarray, affine=None):
165+
def __call__(self, data_array: np.ndarray, affine=None): # type: ignore # see issue #495
166166
"""
167167
original orientation of `data_array` is defined by `affine`.
168168
@@ -261,7 +261,7 @@ def __init__(
261261
self.preserve_range = preserve_range
262262
self.anti_aliasing = anti_aliasing
263263

264-
def __call__(
264+
def __call__( # type: ignore # see issue #495
265265
self,
266266
img,
267267
order=None,
@@ -329,7 +329,7 @@ def __init__(
329329
self.cval = cval
330330
self.prefilter = prefilter
331331

332-
def __call__(
332+
def __call__( # type: ignore # see issue #495
333333
self,
334334
img,
335335
order=None,
@@ -471,7 +471,7 @@ def __init__(self, k: int = 1, spatial_axes=(0, 1)):
471471
self.k = k
472472
self.spatial_axes = spatial_axes
473473

474-
def __call__(self, img: np.ndarray):
474+
def __call__(self, img: np.ndarray): # type: ignore # see issue #495
475475
"""
476476
Args:
477477
img (ndarray): channel first array, must have shape: (num_channels, H[, W, ..., ]),
@@ -567,7 +567,7 @@ def randomize(self):
567567
self._do_transform = self.R.random_sample() < self.prob
568568
self.angle = self.R.uniform(low=self.degrees[0], high=self.degrees[1])
569569

570-
def __call__(
570+
def __call__( # type: ignore # see issue #495
571571
self,
572572
img,
573573
order=None,
@@ -671,7 +671,7 @@ def randomize(self):
671671
else:
672672
self._zoom = self.R.uniform(self.min_zoom, self.max_zoom)
673673

674-
def __call__(
674+
def __call__( # type: ignore # see issue #495
675675
self,
676676
img,
677677
order=None,
@@ -887,7 +887,7 @@ def __init__(
887887
self.as_tensor_output = as_tensor_output
888888
self.device = device
889889

890-
def __call__(
890+
def __call__( # type: ignore # see issue #495
891891
self,
892892
img: Union[np.ndarray, torch.Tensor],
893893
grid: Union[np.ndarray, torch.Tensor],
@@ -977,7 +977,7 @@ def __init__(
977977
self.padding_mode = padding_mode
978978
self.mode = mode
979979

980-
def __call__(
980+
def __call__( # type: ignore # see issue #495
981981
self,
982982
img: Union[np.ndarray, torch.Tensor],
983983
spatial_size=None,
@@ -1061,7 +1061,7 @@ def randomize(self):
10611061
self.do_transform = self.R.rand() < self.prob
10621062
self.rand_affine_grid.randomize()
10631063

1064-
def __call__(
1064+
def __call__( # type: ignore # see issue #495
10651065
self,
10661066
img: Union[np.ndarray, torch.Tensor],
10671067
spatial_size=None,
@@ -1158,7 +1158,7 @@ def randomize(self, spatial_size):
11581158
self.deform_grid.randomize(spatial_size)
11591159
self.rand_affine_grid.randomize()
11601160

1161-
def __call__(
1161+
def __call__( # type: ignore # see issue #495
11621162
self,
11631163
img: Union[np.ndarray, torch.Tensor],
11641164
spatial_size=None,

monai/transforms/utility/array.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ def __init__(self, dtype: np.dtype = np.float32):
118118
"""
119119
self.dtype = dtype
120120

121-
def __call__(self, img: np.ndarray):
121+
def __call__(self, img: np.ndarray): # type: ignore # see issue #495
122122
assert isinstance(img, np.ndarray), "image must be numpy array."
123123
return img.astype(self.dtype)
124124

@@ -161,7 +161,7 @@ def __init__(self, dim: Optional[int] = None):
161161
assert isinstance(dim, int) and dim >= -1, "invalid channel dimension."
162162
self.dim = dim
163163

164-
def __call__(self, img: np.ndarray):
164+
def __call__(self, img: np.ndarray): # type: ignore # see issue #495
165165
"""
166166
Args:
167167
img (ndarray): numpy arrays with required dimension `dim` removed
@@ -209,7 +209,7 @@ def __init__(
209209
if logger_handler is not None:
210210
self._logger.addHandler(logger_handler)
211211

212-
def __call__(
212+
def __call__( # type: ignore # see issue #495
213213
self,
214214
img,
215215
prefix: Optional[str] = None,

requirements-dev.txt

+1
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,4 @@ coverage
1414
parameterized
1515
black
1616
pytype>=2020.6.1
17+
mypy

0 commit comments

Comments
 (0)