Skip to content

Commit 6472f5a

Browse files
committed
ENH: Add type annotations to pacify mypy
1 parent 9ef7aab commit 6472f5a

21 files changed

+82
-72
lines changed

nibabel/analyze.py

+8-5
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,9 @@
8181
can be loaded with and without a default flip, so the saved zoom will not
8282
constrain the affine.
8383
"""
84+
from __future__ import annotations
85+
86+
from typing import Type
8487

8588
import numpy as np
8689

@@ -131,7 +134,7 @@
131134
('glmax', 'i4'),
132135
('glmin', 'i4'),
133136
]
134-
data_history_dtd = [
137+
data_history_dtd: list[tuple[str, str] | tuple[str, str, tuple[int, ...]]] = [
135138
('descrip', 'S80'),
136139
('aux_file', 'S24'),
137140
('orient', 'S1'),
@@ -892,11 +895,11 @@ def may_contain_header(klass, binaryblock):
892895
class AnalyzeImage(SpatialImage):
893896
"""Class for basic Analyze format image"""
894897

895-
header_class = AnalyzeHeader
898+
header_class: Type[AnalyzeHeader] = AnalyzeHeader
896899
_meta_sniff_len = header_class.sizeof_hdr
897-
files_types = (('image', '.img'), ('header', '.hdr'))
898-
valid_exts = ('.img', '.hdr')
899-
_compressed_suffixes = ('.gz', '.bz2', '.zst')
900+
files_types: tuple[tuple[str, str], ...] = (('image', '.img'), ('header', '.hdr'))
901+
valid_exts: tuple[str, ...] = ('.img', '.hdr')
902+
_compressed_suffixes: tuple[str, ...] = ('.gz', '.bz2', '.zst')
900903

901904
makeable = True
902905
rw = True

nibabel/benchmarks/bench_arrayproxy_slicing.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626

2727
# if memory_profiler is installed, we get memory usage results
2828
try:
29-
from memory_profiler import memory_usage
29+
from memory_profiler import memory_usage # type: ignore
3030
except ImportError:
3131
memory_usage = None
3232

nibabel/brikhead.py

+4-3
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
am aware) always be >= 1. This permits sub-brick indexing common in AFNI
2828
programs (e.g., example4d+orig'[0]').
2929
"""
30+
from __future__ import annotations
3031

3132
import os
3233
import re
@@ -476,9 +477,9 @@ class AFNIImage(SpatialImage):
476477
True
477478
"""
478479

479-
header_class = AFNIHeader
480-
valid_exts = ('.brik', '.head')
481-
files_types = (('image', '.brik'), ('header', '.head'))
480+
header_class: type = AFNIHeader
481+
valid_exts: tuple[str, ...] = ('.brik', '.head')
482+
files_types: tuple[tuple[str, str], ...] = (('image', '.brik'), ('header', '.head'))
482483
_compressed_suffixes = ('.gz', '.bz2', '.Z', '.zst')
483484
makeable = False
484485
rw = False

nibabel/casting.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
Most routines work round some numpy oddities in floating point precision and
44
casting. Others work round numpy casting to and from python ints
55
"""
6+
from __future__ import annotations
67

78
import warnings
89
from numbers import Integral
@@ -110,7 +111,7 @@ def float_to_int(arr, int_type, nan2zero=True, infmax=False):
110111

111112

112113
# Cache range values
113-
_SHARED_RANGES = {}
114+
_SHARED_RANGES: dict[tuple[type, type], tuple[np.number, np.number]] = {}
114115

115116

116117
def shared_range(flt_type, int_type):

nibabel/cmdline/dicomfs.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ class dummy_fuse:
2525

2626

2727
try:
28-
import fuse
28+
import fuse # type: ignore
2929

3030
uid = os.getuid()
3131
gid = os.getgid()

nibabel/externals/netcdf.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -871,6 +871,7 @@ def __setattr__(self, attr, value):
871871
pass
872872
self.__dict__[attr] = value
873873

874+
@property
874875
def isrec(self):
875876
"""Returns whether the variable has a record dimension or not.
876877
@@ -881,16 +882,15 @@ def isrec(self):
881882
882883
"""
883884
return bool(self.data.shape) and not self._shape[0]
884-
isrec = property(isrec)
885885

886+
@property
886887
def shape(self):
887888
"""Returns the shape tuple of the data variable.
888889
889890
This is a read-only attribute and can not be modified in the
890891
same manner of other numpy arrays.
891892
"""
892893
return self.data.shape
893-
shape = property(shape)
894894

895895
def getValue(self):
896896
"""

nibabel/filebasedimages.py

+8-7
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#
88
### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ##
99
"""Common interface for any image format--volume or surface, binary or xml."""
10+
from __future__ import annotations
1011

1112
import io
1213
from copy import deepcopy
@@ -144,14 +145,14 @@ class FileBasedImage:
144145
work.
145146
"""
146147

147-
header_class = FileBasedHeader
148-
_meta_sniff_len = 0
149-
files_types = (('image', None),)
150-
valid_exts = ()
151-
_compressed_suffixes = ()
148+
header_class: type = FileBasedHeader
149+
_meta_sniff_len: int = 0
150+
files_types: tuple[tuple[str, str | None], ...] = (('image', None),)
151+
valid_exts: tuple[str, ...] = ()
152+
_compressed_suffixes: tuple[str, ...] = ()
152153

153-
makeable = True # Used in test code
154-
rw = True # Used in test code
154+
makeable: bool = True # Used in test code
155+
rw: bool = True # Used in test code
155156

156157
def __init__(self, header=None, extra=None, file_map=None):
157158
"""Initialize image

nibabel/gifti/gifti.py

+8-5
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,12 @@
1111
The Gifti specification was (at time of writing) available as a PDF download
1212
from http://www.nitrc.org/projects/gifti/
1313
"""
14+
from __future__ import annotations
1415

1516
import base64
1617
import sys
1718
import warnings
19+
from typing import Type
1820

1921
import numpy as np
2022

@@ -577,7 +579,7 @@ class GiftiImage(xml.XmlSerializable, SerializableImage):
577579
# The parser will in due course be a GiftiImageParser, but we can't set
578580
# that now, because it would result in a circular import. We set it after
579581
# the class has been defined, at the end of the class definition.
580-
parser = None
582+
parser: Type[xml.XmlParser]
581583

582584
def __init__(
583585
self,
@@ -832,17 +834,18 @@ def _to_xml_element(self):
832834
GIFTI.append(dar._to_xml_element())
833835
return GIFTI
834836

835-
def to_xml(self, enc='utf-8'):
837+
def to_xml(self, enc='utf-8') -> bytes:
836838
"""Return XML corresponding to image content"""
837839
header = b"""<?xml version="1.0" encoding="UTF-8"?>
838840
<!DOCTYPE GIFTI SYSTEM "http://www.nitrc.org/frs/download.php/115/gifti.dtd">
839841
"""
840842
return header + super().to_xml(enc)
841843

842844
# Avoid the indirection of going through to_file_map
843-
to_bytes = to_xml
845+
def to_bytes(self, enc='utf-8'):
846+
return self.to_xml(enc=enc)
844847

845-
def to_file_map(self, file_map=None):
848+
def to_file_map(self, file_map=None, enc='utf-8'):
846849
"""Save the current image to the specified file_map
847850
848851
Parameters
@@ -858,7 +861,7 @@ def to_file_map(self, file_map=None):
858861
if file_map is None:
859862
file_map = self.file_map
860863
with file_map['image'].get_prepare_fileobj('wb') as f:
861-
f.write(self.to_xml())
864+
f.write(self.to_xml(enc=enc))
862865

863866
@classmethod
864867
def from_file_map(klass, file_map, buffer_size=35000000, mmap=True):

nibabel/minc1.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#
88
### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ##
99
"""Read MINC1 format images"""
10+
from __future__ import annotations
1011

1112
from numbers import Integral
1213

@@ -305,11 +306,11 @@ class Minc1Image(SpatialImage):
305306
load.
306307
"""
307308

308-
header_class = Minc1Header
309+
header_class: type = Minc1Header
309310
_meta_sniff_len = 4
310311
valid_exts = ('.mnc',)
311312
files_types = (('image', '.mnc'),)
312-
_compressed_suffixes = ('.gz', '.bz2', '.zst')
313+
_compressed_suffixes: tuple[str, ...] = ('.gz', '.bz2', '.zst')
313314

314315
makeable = True
315316
rw = False

nibabel/minc2.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
2626
mincstats my_funny.mnc
2727
"""
28+
from __future__ import annotations
29+
2830
import numpy as np
2931

3032
from .minc1 import Minc1File, Minc1Image, MincError, MincHeader
@@ -148,14 +150,14 @@ class Minc2Image(Minc1Image):
148150
"""
149151

150152
# MINC2 does not do compressed whole files
151-
_compressed_suffixes = ()
153+
_compressed_suffixes: tuple[str, ...] = ()
152154
header_class = Minc2Header
153155

154156
@classmethod
155157
def from_file_map(klass, file_map, *, mmap=True, keep_file_open=None):
156158
# Import of h5py might take awhile for MPI-enabled builds
157159
# So we are importing it here "on demand"
158-
import h5py
160+
import h5py # type: ignore
159161

160162
holder = file_map['image']
161163
if holder.filename is None:

nibabel/nicom/dicomwrappers.py

-2
Original file line numberDiff line numberDiff line change
@@ -127,8 +127,6 @@ class Wrapper:
127127
is_multiframe = False
128128
b_matrix = None
129129
q_vector = None
130-
b_value = None
131-
b_vector = None
132130

133131
def __init__(self, dcm_data):
134132
"""Initialize wrapper

nibabel/nifti1.py

+7-7
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,11 @@
1010
1111
NIfTI1 format defined at http://nifti.nimh.nih.gov/nifti-1/
1212
"""
13+
from __future__ import annotations
14+
1315
import warnings
1416
from io import BytesIO
17+
from typing import Type
1518

1619
import numpy as np
1720
import numpy.linalg as npl
@@ -86,8 +89,8 @@
8689
# datatypes not in analyze format, with codes
8790
if have_binary128():
8891
# Only enable 128 bit floats if we really have IEEE binary 128 longdoubles
89-
_float128t = np.longdouble
90-
_complex256t = np.longcomplex
92+
_float128t: Type[np.generic] = np.longdouble
93+
_complex256t: Type[np.generic] = np.longcomplex
9194
else:
9295
_float128t = np.void
9396
_complex256t = np.void
@@ -1813,7 +1816,7 @@ class Nifti1PairHeader(Nifti1Header):
18131816
class Nifti1Pair(analyze.AnalyzeImage):
18141817
"""Class for NIfTI1 format image, header pair"""
18151818

1816-
header_class = Nifti1PairHeader
1819+
header_class: Type[Nifti1Header] = Nifti1PairHeader
18171820
_meta_sniff_len = header_class.sizeof_hdr
18181821
rw = True
18191822

@@ -1844,9 +1847,7 @@ def __init__(self, dataobj, affine, header=None, extra=None, file_map=None, dtyp
18441847
self._affine2header()
18451848

18461849
# Copy docstring
1847-
__init__.__doc__ = (
1848-
analyze.AnalyzeImage.__init__.__doc__
1849-
+ """
1850+
__init__.__doc__ = f"""{analyze.AnalyzeImage.__init__.__doc__}
18501851
Notes
18511852
-----
18521853
@@ -1859,7 +1860,6 @@ def __init__(self, dataobj, affine, header=None, extra=None, file_map=None, dtyp
18591860
:meth:`set_qform` methods can be used to update the codes after an image
18601861
has been created - see those methods, and the :ref:`manual
18611862
<default-sform-qform-codes>` for more details. """
1862-
)
18631863

18641864
def update_header(self):
18651865
"""Harmonize header with image data and affine

nibabel/openers.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020

2121
# is indexed_gzip present and modern?
2222
try:
23-
import indexed_gzip as igzip
23+
import indexed_gzip as igzip # type: ignore
2424

2525
version = igzip.__version__
2626

nibabel/parrec.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -1338,7 +1338,7 @@ def from_filename(
13381338
strict_sort=strict_sort,
13391339
)
13401340

1341-
load = from_filename
1341+
load = from_filename # type: ignore
13421342

13431343

1344-
load = PARRECImage.load
1344+
load = PARRECImage.from_filename

nibabel/pydicom_compat.py

+15-11
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
without error, and always defines:
88
99
* have_dicom : True if we can import pydicom or dicom;
10-
* pydicom : pydicom module or dicom module or None of not importable;
10+
* pydicom : pydicom module or dicom module or None if not importable;
1111
* read_file : ``read_file`` function if pydicom or dicom module is importable
1212
else None;
1313
* tag_for_keyword : ``tag_for_keyword`` function if pydicom or dicom module
@@ -19,26 +19,30 @@
1919
2020
A deprecated copy is available here for backward compatibility.
2121
"""
22+
from __future__ import annotations
23+
24+
from types import ModuleType
25+
from typing import Callable
26+
27+
from .deprecated import deprecate_with_version
28+
from .optpkg import optional_package
2229

2330
# Module has (apparently) unused imports; stop flake8 complaining
2431
# flake8: noqa
2532

26-
from .deprecated import deprecate_with_version
2733

28-
have_dicom = True
29-
pydicom = read_file = tag_for_keyword = Sequence = None
34+
pydicom, have_dicom, _ = optional_package('pydicom')
3035

31-
try:
32-
import pydicom
33-
except ImportError:
34-
have_dicom = False
35-
else: # pydicom module available
36+
read_file: Callable | None = None
37+
tag_for_keyword: Callable | None = None
38+
Sequence: type | None = None
39+
40+
if have_dicom:
3641
# Values not imported by default
37-
import pydicom.values
42+
import pydicom.values # type: ignore
3843
from pydicom.dicomio import read_file
3944
from pydicom.sequence import Sequence
4045

41-
if have_dicom:
4246
tag_for_keyword = pydicom.datadict.tag_for_keyword
4347

4448

nibabel/spatialimages.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@
129129
>>> np.all(img3.get_fdata(dtype=np.float32) == data)
130130
True
131131
"""
132+
from __future__ import annotations
132133

133134
import numpy as np
134135

@@ -400,7 +401,7 @@ def slice_affine(self, slicer):
400401
class SpatialImage(DataobjImage):
401402
"""Template class for volumetric (3D/4D) images"""
402403

403-
header_class = SpatialHeader
404+
header_class: type = SpatialHeader
404405
ImageSlicer = SpatialFirstSlicer
405406

406407
def __init__(self, dataobj, affine, header=None, extra=None, file_map=None):

0 commit comments

Comments
 (0)