From 7e5d584910c67851dcfcd074ff307122689b61f5 Mon Sep 17 00:00:00 2001 From: "Christopher J. Markiewicz" Date: Sun, 12 Jan 2025 11:51:49 -0500 Subject: [PATCH 01/11] STY: ruff format [git-blame-ignore-rev] --- nibabel/benchmarks/bench_arrayproxy_slicing.py | 2 +- nibabel/benchmarks/butils.py | 2 +- nibabel/cifti2/cifti2.py | 3 +-- nibabel/cifti2/parse_cifti2.py | 3 +-- nibabel/cmdline/ls.py | 4 ++-- nibabel/cmdline/tests/test_conform.py | 4 ++-- nibabel/cmdline/utils.py | 2 +- nibabel/data.py | 2 +- nibabel/deprecator.py | 2 +- nibabel/gifti/tests/test_parse_gifti_fast.py | 6 +++--- nibabel/nifti1.py | 2 +- nibabel/parrec.py | 8 ++++---- nibabel/rstutils.py | 2 +- nibabel/streamlines/__init__.py | 3 +-- nibabel/streamlines/array_sequence.py | 2 +- nibabel/streamlines/tests/test_array_sequence.py | 2 +- nibabel/streamlines/trk.py | 2 +- nibabel/tests/data/check_parrec_reslice.py | 4 ++-- nibabel/tests/test_funcs.py | 12 ++++++------ nibabel/tests/test_image_types.py | 2 +- nibabel/tests/test_scripts.py | 6 +++--- nibabel/tests/test_spatialimages.py | 6 +++--- nibabel/volumeutils.py | 2 +- 23 files changed, 40 insertions(+), 43 deletions(-) diff --git a/nibabel/benchmarks/bench_arrayproxy_slicing.py b/nibabel/benchmarks/bench_arrayproxy_slicing.py index 3444cb8d8f..808a227395 100644 --- a/nibabel/benchmarks/bench_arrayproxy_slicing.py +++ b/nibabel/benchmarks/bench_arrayproxy_slicing.py @@ -96,7 +96,7 @@ def fmt_sliceobj(sliceobj): slcstr.append(s) else: slcstr.append(str(int(s * SHAPE[i]))) - return f"[{', '.join(slcstr)}]" + return f'[{", ".join(slcstr)}]' with InTemporaryDirectory(): print(f'Generating test data... ({int(round(np.prod(SHAPE) * 4 / 1048576.0))} MB)') diff --git a/nibabel/benchmarks/butils.py b/nibabel/benchmarks/butils.py index 13c255d1c1..6231629030 100644 --- a/nibabel/benchmarks/butils.py +++ b/nibabel/benchmarks/butils.py @@ -5,6 +5,6 @@ def print_git_title(title): """Prints title string with git hash if possible, and underline""" - title = f"{title} for git revision {get_info()['commit_hash']}" + title = f'{title} for git revision {get_info()["commit_hash"]}' print(title) print('-' * len(title)) diff --git a/nibabel/cifti2/cifti2.py b/nibabel/cifti2/cifti2.py index b2b67978b7..7442a91860 100644 --- a/nibabel/cifti2/cifti2.py +++ b/nibabel/cifti2/cifti2.py @@ -294,8 +294,7 @@ def __setitem__(self, key, value): self._labels[key] = Cifti2Label(*([key] + list(value))) except ValueError: raise ValueError( - 'Key should be int, value should be sequence ' - 'of str and 4 floats between 0 and 1' + 'Key should be int, value should be sequence of str and 4 floats between 0 and 1' ) def __delitem__(self, key): diff --git a/nibabel/cifti2/parse_cifti2.py b/nibabel/cifti2/parse_cifti2.py index 764e3ae203..6ed2a29b52 100644 --- a/nibabel/cifti2/parse_cifti2.py +++ b/nibabel/cifti2/parse_cifti2.py @@ -384,8 +384,7 @@ def StartElementHandler(self, name, attrs): model = self.struct_state[-1] if not isinstance(model, Cifti2BrainModel): raise Cifti2HeaderError( - 'VertexIndices element can only be a child ' - 'of the CIFTI-2 BrainModel element' + 'VertexIndices element can only be a child of the CIFTI-2 BrainModel element' ) self.fsm_state.append('VertexIndices') model.vertex_indices = index diff --git a/nibabel/cmdline/ls.py b/nibabel/cmdline/ls.py index 72fb227687..8ddc37869b 100755 --- a/nibabel/cmdline/ls.py +++ b/nibabel/cmdline/ls.py @@ -103,8 +103,8 @@ def proc_file(f, opts): row += [ str(safe_get(h, 'data_dtype')), - f"@l[{ap(safe_get(h, 'data_shape'), '%3g')}]", - f"@l{ap(safe_get(h, 'zooms'), '%.2f', 'x')}", + f'@l[{ap(safe_get(h, "data_shape"), "%3g")}]', + f'@l{ap(safe_get(h, "zooms"), "%.2f", "x")}', ] # Slope if ( diff --git a/nibabel/cmdline/tests/test_conform.py b/nibabel/cmdline/tests/test_conform.py index dbbf96186f..48014e52e4 100644 --- a/nibabel/cmdline/tests/test_conform.py +++ b/nibabel/cmdline/tests/test_conform.py @@ -47,8 +47,8 @@ def test_nondefault(tmpdir): voxel_size = (1, 2, 4) orientation = 'LAS' args = ( - f"{infile} {outfile} --out-shape {' '.join(map(str, out_shape))} " - f"--voxel-size {' '.join(map(str, voxel_size))} --orientation {orientation}" + f'{infile} {outfile} --out-shape {" ".join(map(str, out_shape))} ' + f'--voxel-size {" ".join(map(str, voxel_size))} --orientation {orientation}' ) main(args.split()) assert outfile.isfile() diff --git a/nibabel/cmdline/utils.py b/nibabel/cmdline/utils.py index a085d2e91b..298b6a5ad5 100644 --- a/nibabel/cmdline/utils.py +++ b/nibabel/cmdline/utils.py @@ -55,7 +55,7 @@ def table2string(table, out=None): # eat whole entry while computing width for @w (for wide) markup_strip = re.compile('^@([lrc]|w.*)') col_width = [max(len(markup_strip.sub('', x)) for x in column) for column in zip(*table)] - trans = str.maketrans("lrcw", "<>^^") + trans = str.maketrans('lrcw', '<>^^') lines = [] for row in table: line = [] diff --git a/nibabel/data.py b/nibabel/data.py index 8ea056d8e7..510b4127bc 100644 --- a/nibabel/data.py +++ b/nibabel/data.py @@ -290,7 +290,7 @@ def make_datasource(pkg_def, **kwargs): pkg_hint = pkg_def.get('install hint', DEFAULT_INSTALL_HINT) msg = f'{e}; Is it possible you have not installed a data package?' if 'name' in pkg_def: - msg += f"\n\nYou may need the package \"{pkg_def['name']}\"" + msg += f'\n\nYou may need the package "{pkg_def["name"]}"' if pkg_hint is not None: msg += f'\n\n{pkg_hint}' raise DataError(msg) diff --git a/nibabel/deprecator.py b/nibabel/deprecator.py index 83118dd539..972e5f2a83 100644 --- a/nibabel/deprecator.py +++ b/nibabel/deprecator.py @@ -212,7 +212,7 @@ def __call__( messages.append('* deprecated from version: ' + since) if until: messages.append( - f"* {'Raises' if self.is_bad_version(until) else 'Will raise'} " + f'* {"Raises" if self.is_bad_version(until) else "Will raise"} ' f'{exception} as of version: {until}' ) message = '\n'.join(messages) diff --git a/nibabel/gifti/tests/test_parse_gifti_fast.py b/nibabel/gifti/tests/test_parse_gifti_fast.py index 6ca54df038..cfc8ce4ae2 100644 --- a/nibabel/gifti/tests/test_parse_gifti_fast.py +++ b/nibabel/gifti/tests/test_parse_gifti_fast.py @@ -177,9 +177,9 @@ def assert_default_types(loaded): continue with suppress_warnings(): loadedtype = type(getattr(loaded, attr)) - assert ( - loadedtype == defaulttype - ), f'Type mismatch for attribute: {attr} ({loadedtype} != {defaulttype})' + assert loadedtype == defaulttype, ( + f'Type mismatch for attribute: {attr} ({loadedtype} != {defaulttype})' + ) def test_default_types(): diff --git a/nibabel/nifti1.py b/nibabel/nifti1.py index 0a4d25581b..d012e6b950 100644 --- a/nibabel/nifti1.py +++ b/nibabel/nifti1.py @@ -1804,7 +1804,7 @@ def set_slice_times(self, slice_times): raise HeaderDataError(f'slice ordering of {st_order} fits with no known scheme') if len(matching_labels) > 1: warnings.warn( - f"Multiple slice orders satisfy: {', '.join(matching_labels)}. " + f'Multiple slice orders satisfy: {", ".join(matching_labels)}. ' 'Choosing the first one' ) label = matching_labels[0] diff --git a/nibabel/parrec.py b/nibabel/parrec.py index 0a2005835f..22520a603e 100644 --- a/nibabel/parrec.py +++ b/nibabel/parrec.py @@ -782,10 +782,10 @@ def as_analyze_map(self): # Here we set the parameters we can to simplify PAR/REC # to NIfTI conversion. descr = ( - f"{self.general_info['exam_name']};" - f"{self.general_info['patient_name']};" - f"{self.general_info['exam_date'].replace(' ', '')};" - f"{self.general_info['protocol_name']}" + f'{self.general_info["exam_name"]};' + f'{self.general_info["patient_name"]};' + f'{self.general_info["exam_date"].replace(" ", "")};' + f'{self.general_info["protocol_name"]}' )[:80] is_fmri = self.general_info['max_dynamics'] > 1 # PAR/REC uses msec, but in _calc_zooms we convert to sec diff --git a/nibabel/rstutils.py b/nibabel/rstutils.py index cb40633e54..1ba63f4339 100644 --- a/nibabel/rstutils.py +++ b/nibabel/rstutils.py @@ -52,7 +52,7 @@ def rst_table( cross = format_chars.pop('cross', '+') title_heading = format_chars.pop('title_heading', '*') if len(format_chars) != 0: - raise ValueError(f"Unexpected ``format_char`` keys {', '.join(format_chars)}") + raise ValueError(f'Unexpected ``format_char`` keys {", ".join(format_chars)}') down_joiner = ' ' + down + ' ' down_starter = down + ' ' down_ender = ' ' + down diff --git a/nibabel/streamlines/__init__.py b/nibabel/streamlines/__init__.py index 46b403b424..02e11e4f29 100644 --- a/nibabel/streamlines/__init__.py +++ b/nibabel/streamlines/__init__.py @@ -125,8 +125,7 @@ def save(tractogram, filename, **kwargs): tractogram_file = tractogram if tractogram_file_class is None or not isinstance(tractogram_file, tractogram_file_class): msg = ( - 'The extension you specified is unusual for the provided' - " 'TractogramFile' object." + "The extension you specified is unusual for the provided 'TractogramFile' object." ) warnings.warn(msg, ExtensionWarning) diff --git a/nibabel/streamlines/array_sequence.py b/nibabel/streamlines/array_sequence.py index dd9b3c57d0..63336352bd 100644 --- a/nibabel/streamlines/array_sequence.py +++ b/nibabel/streamlines/array_sequence.py @@ -87,7 +87,7 @@ def fn_binary_op(self, value): '__xor__', ): _wrap(cls, op=op, inplace=False) - _wrap(cls, op=f"__i{op.strip('_')}__", inplace=True) + _wrap(cls, op=f'__i{op.strip("_")}__', inplace=True) for op in ('__eq__', '__ne__', '__lt__', '__le__', '__gt__', '__ge__'): _wrap(cls, op) diff --git a/nibabel/streamlines/tests/test_array_sequence.py b/nibabel/streamlines/tests/test_array_sequence.py index 96e66b44c5..22327b9a31 100644 --- a/nibabel/streamlines/tests/test_array_sequence.py +++ b/nibabel/streamlines/tests/test_array_sequence.py @@ -397,7 +397,7 @@ def _test_binary(op, arrseq, scalars, seqs, inplace=False): if op in CMP_OPS: continue - op = f"__i{op.strip('_')}__" + op = f'__i{op.strip("_")}__' _test_binary(op, seq, SCALARS, ARRSEQS, inplace=True) if op == '__itruediv__': diff --git a/nibabel/streamlines/trk.py b/nibabel/streamlines/trk.py index 0b11f5684e..c434619d63 100644 --- a/nibabel/streamlines/trk.py +++ b/nibabel/streamlines/trk.py @@ -579,7 +579,7 @@ def _read_header(fileobj): header_rec = header_rec.view(header_rec.dtype.newbyteorder()) if header_rec['hdr_size'] != TrkFile.HEADER_SIZE: msg = ( - f"Invalid hdr_size: {header_rec['hdr_size']} " + f'Invalid hdr_size: {header_rec["hdr_size"]} ' f'instead of {TrkFile.HEADER_SIZE}' ) raise HeaderError(msg) diff --git a/nibabel/tests/data/check_parrec_reslice.py b/nibabel/tests/data/check_parrec_reslice.py index 244b4c3a64..b22a869090 100644 --- a/nibabel/tests/data/check_parrec_reslice.py +++ b/nibabel/tests/data/check_parrec_reslice.py @@ -60,7 +60,7 @@ def gmean_norm(data): normal_data = normal_img.get_fdata() normal_normed = gmean_norm(normal_data) - print(f'RMS of standard image {normal_fname:<44}: {np.sqrt(np.sum(normal_normed ** 2))}') + print(f'RMS of standard image {normal_fname:<44}: {np.sqrt(np.sum(normal_normed**2))}') for parfile in glob.glob('*.PAR'): if parfile == normal_fname: @@ -69,4 +69,4 @@ def gmean_norm(data): fixed_img = resample_img2img(normal_img, funny_img) fixed_data = fixed_img.get_fdata() difference_data = normal_normed - gmean_norm(fixed_data) - print(f'RMS resliced {parfile:<52} : {np.sqrt(np.sum(difference_data ** 2))}') + print(f'RMS resliced {parfile:<52} : {np.sqrt(np.sum(difference_data**2))}') diff --git a/nibabel/tests/test_funcs.py b/nibabel/tests/test_funcs.py index 8666406168..b4139f30ef 100644 --- a/nibabel/tests/test_funcs.py +++ b/nibabel/tests/test_funcs.py @@ -101,9 +101,9 @@ def test_concat(): except ValueError as ve: assert expect_error, str(ve) else: - assert ( - not expect_error - ), 'Expected a concatenation error, but got none.' + assert not expect_error, ( + 'Expected a concatenation error, but got none.' + ) assert_array_equal(all_imgs.get_fdata(), all_data) assert_array_equal(all_imgs.affine, affine) @@ -117,9 +117,9 @@ def test_concat(): except ValueError as ve: assert expect_error, str(ve) else: - assert ( - not expect_error - ), 'Expected a concatenation error, but got none.' + assert not expect_error, ( + 'Expected a concatenation error, but got none.' + ) assert_array_equal(all_imgs.get_fdata(), all_data) assert_array_equal(all_imgs.affine, affine) diff --git a/nibabel/tests/test_image_types.py b/nibabel/tests/test_image_types.py index bc50c8417e..a9c41763a7 100644 --- a/nibabel/tests/test_image_types.py +++ b/nibabel/tests/test_image_types.py @@ -68,7 +68,7 @@ def check_img(img_path, img_klass, sniff_mode, sniff, expect_success, msg): # Check that the image type was recognized. new_msg = ( f'{basename(img_path)} ({msg}) image ' - f"is{'' if is_img else ' not'} " + f'is{"" if is_img else " not"} ' f'a {img_klass.__name__} image.' ) assert is_img, new_msg diff --git a/nibabel/tests/test_scripts.py b/nibabel/tests/test_scripts.py index d97c99d051..0ff4ce1984 100644 --- a/nibabel/tests/test_scripts.py +++ b/nibabel/tests/test_scripts.py @@ -166,9 +166,9 @@ def test_nib_ls_multiple(): # they should be indented correctly. Since all files are int type - ln = max(len(f) for f in fnames) i_str = ' i' if sys.byteorder == 'little' else ' Date: Sun, 12 Jan 2025 12:01:05 -0500 Subject: [PATCH 02/11] ENH: Switch from predicate/and/or to if/predicate/else --- nibabel/cmdline/dicomfs.py | 2 +- nibabel/tests/test_nifti1.py | 2 +- nibabel/volumeutils.py | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/nibabel/cmdline/dicomfs.py b/nibabel/cmdline/dicomfs.py index 07aa51e2d3..ae81940a1d 100644 --- a/nibabel/cmdline/dicomfs.py +++ b/nibabel/cmdline/dicomfs.py @@ -231,7 +231,7 @@ def main(args=None): if opts.verbose: logger.addHandler(logging.StreamHandler(sys.stdout)) - logger.setLevel(opts.verbose > 1 and logging.DEBUG or logging.INFO) + logger.setLevel(logging.DEBUG if opts.verbose > 1 else logging.INFO) if len(files) != 2: sys.stderr.write(f'Please provide two arguments:\n{parser.usage}\n') diff --git a/nibabel/tests/test_nifti1.py b/nibabel/tests/test_nifti1.py index 053cad755a..286e6beef5 100644 --- a/nibabel/tests/test_nifti1.py +++ b/nibabel/tests/test_nifti1.py @@ -538,7 +538,7 @@ def test_slice_times(self): hdr.set_slice_duration(0.1) # We need a function to print out the Nones and floating point # values in a predictable way, for the tests below. - _stringer = lambda val: val is not None and f'{val:2.1f}' or None + _stringer = lambda val: f'{val:2.1f}' if val is not None else None _print_me = lambda s: list(map(_stringer, s)) # The following examples are from the nifti1.h documentation. hdr['slice_code'] = slice_order_codes['sequential increasing'] diff --git a/nibabel/volumeutils.py b/nibabel/volumeutils.py index c150e452e3..4dca724f8e 100644 --- a/nibabel/volumeutils.py +++ b/nibabel/volumeutils.py @@ -35,8 +35,8 @@ DT = ty.TypeVar('DT', bound=np.generic) sys_is_le = sys.byteorder == 'little' -native_code = sys_is_le and '<' or '>' -swapped_code = sys_is_le and '>' or '<' +native_code = '<' if sys_is_le else '>' +swapped_code = '>' if sys_is_le else '<' _endian_codes = ( # numpy code, aliases ('<', 'little', 'l', 'le', 'L', 'LE'), From 90a278b33c93a6b006f744a1ec26cd914b8cf596 Mon Sep 17 00:00:00 2001 From: "Christopher J. Markiewicz" Date: Sun, 12 Jan 2025 12:01:25 -0500 Subject: [PATCH 03/11] ENH: Adopt str.removesuffix() --- nibabel/brikhead.py | 2 +- nibabel/filename_parser.py | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/nibabel/brikhead.py b/nibabel/brikhead.py index d187a6b34b..cd791adac1 100644 --- a/nibabel/brikhead.py +++ b/nibabel/brikhead.py @@ -555,7 +555,7 @@ def filespec_to_file_map(klass, filespec): fname = fholder.filename if key == 'header' and not os.path.exists(fname): for ext in klass._compressed_suffixes: - fname = fname[: -len(ext)] if fname.endswith(ext) else fname + fname = fname.removesuffix(ext) elif key == 'image' and not os.path.exists(fname): for ext in klass._compressed_suffixes: if os.path.exists(fname + ext): diff --git a/nibabel/filename_parser.py b/nibabel/filename_parser.py index d2c23ae6e4..a16c13ec22 100644 --- a/nibabel/filename_parser.py +++ b/nibabel/filename_parser.py @@ -111,8 +111,7 @@ def types_filenames( template_fname = _stringify_path(template_fname) if not isinstance(template_fname, str): raise TypesFilenamesError('Need file name as input to set_filenames') - if template_fname.endswith('.'): - template_fname = template_fname[:-1] + template_fname = template_fname.removesuffix('.') filename, found_ext, ignored, guessed_name = parse_filename( template_fname, types_exts, trailing_suffixes, match_case ) From a274579319f23874d4de9698ab7423db535e4532 Mon Sep 17 00:00:00 2001 From: "Christopher J. Markiewicz" Date: Sun, 12 Jan 2025 12:01:38 -0500 Subject: [PATCH 04/11] chore: ruff check --fix --- nibabel/cifti2/cifti2_axes.py | 6 ++++-- nibabel/pointset.py | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/nibabel/cifti2/cifti2_axes.py b/nibabel/cifti2/cifti2_axes.py index 32914be1b6..54dfc79179 100644 --- a/nibabel/cifti2/cifti2_axes.py +++ b/nibabel/cifti2/cifti2_axes.py @@ -634,8 +634,10 @@ def __eq__(self, other): return ( ( self.affine is None - or np.allclose(self.affine, other.affine) - and self.volume_shape == other.volume_shape + or ( + np.allclose(self.affine, other.affine) + and self.volume_shape == other.volume_shape + ) ) and self.nvertices == other.nvertices and np.array_equal(self.name, other.name) diff --git a/nibabel/pointset.py b/nibabel/pointset.py index 889a8c70cd..759a0b15e8 100644 --- a/nibabel/pointset.py +++ b/nibabel/pointset.py @@ -178,7 +178,7 @@ def to_mask(self, shape=None) -> SpatialImage: class GridIndices: """Class for generating indices just-in-time""" - __slots__ = ('gridshape', 'dtype', 'shape') + __slots__ = ('dtype', 'gridshape', 'shape') ndim = 2 def __init__(self, shape, dtype=None): From f321ca3a355a1d664417a8d06719e87411057e26 Mon Sep 17 00:00:00 2001 From: "Christopher J. Markiewicz" Date: Sun, 12 Jan 2025 12:07:42 -0500 Subject: [PATCH 05/11] chore: Update pretty_mapping to use f-strings --- nibabel/volumeutils.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/nibabel/volumeutils.py b/nibabel/volumeutils.py index 4dca724f8e..d8b64fd4bf 100644 --- a/nibabel/volumeutils.py +++ b/nibabel/volumeutils.py @@ -338,12 +338,7 @@ def pretty_mapping( if getterfunc is None: getterfunc = getitem mxlen = max(len(str(name)) for name in mapping) - fmt = '%%-%ds : %%s' % mxlen - out = [] - for name in mapping: - value = getterfunc(mapping, name) - out.append(fmt % (name, value)) - return '\n'.join(out) + return '\n'.join([f'{name:{mxlen}s} : {getterfunc(mapping, name)}' for name in mapping]) def make_dt_codes(codes_seqs: ty.Sequence[ty.Sequence]) -> Recoder: From a08fb3fe1979f8f4d42a8eb4c40ea7a7ee7f561b Mon Sep 17 00:00:00 2001 From: "Christopher J. Markiewicz" Date: Sun, 12 Jan 2025 12:19:07 -0500 Subject: [PATCH 06/11] sty: Use a format template instead of % strings --- nibabel/benchmarks/bench_array_to_file.py | 15 ++++++++------- nibabel/benchmarks/bench_finite_range.py | 9 +++++---- nibabel/benchmarks/bench_load_save.py | 15 ++++++++------- 3 files changed, 21 insertions(+), 18 deletions(-) diff --git a/nibabel/benchmarks/bench_array_to_file.py b/nibabel/benchmarks/bench_array_to_file.py index 2af8b5677f..a77ae6cbc9 100644 --- a/nibabel/benchmarks/bench_array_to_file.py +++ b/nibabel/benchmarks/bench_array_to_file.py @@ -29,24 +29,25 @@ def bench_array_to_file(): sys.stdout.flush() print_git_title('\nArray to file') mtime = measure('array_to_file(arr, BytesIO(), np.float32)', repeat) - print('%30s %6.2f' % ('Save float64 to float32', mtime)) + fmt = '{:30s} {:6.2f}'.format + print(fmt('Save float64 to float32', mtime)) mtime = measure('array_to_file(arr, BytesIO(), np.int16)', repeat) - print('%30s %6.2f' % ('Save float64 to int16', mtime)) + print(fmt('Save float64 to int16', mtime)) # Set a lot of NaNs to check timing arr[:, :, :, 1] = np.nan mtime = measure('array_to_file(arr, BytesIO(), np.float32)', repeat) - print('%30s %6.2f' % ('Save float64 to float32, NaNs', mtime)) + print(fmt('Save float64 to float32, NaNs', mtime)) mtime = measure('array_to_file(arr, BytesIO(), np.int16)', repeat) - print('%30s %6.2f' % ('Save float64 to int16, NaNs', mtime)) + print(fmt('Save float64 to int16, NaNs', mtime)) # Set a lot of infs to check timing arr[:, :, :, 1] = np.inf mtime = measure('array_to_file(arr, BytesIO(), np.float32)', repeat) - print('%30s %6.2f' % ('Save float64 to float32, infs', mtime)) + print(fmt('Save float64 to float32, infs', mtime)) mtime = measure('array_to_file(arr, BytesIO(), np.int16)', repeat) - print('%30s %6.2f' % ('Save float64 to int16, infs', mtime)) + print(fmt('Save float64 to int16, infs', mtime)) # Int16 input, float output arr = np.random.random_integers(low=-1000, high=1000, size=img_shape) arr = arr.astype(np.int16) mtime = measure('array_to_file(arr, BytesIO(), np.float32)', repeat) - print('%30s %6.2f' % ('Save Int16 to float32', mtime)) + print(fmt('Save Int16 to float32', mtime)) sys.stdout.flush() diff --git a/nibabel/benchmarks/bench_finite_range.py b/nibabel/benchmarks/bench_finite_range.py index 957446884c..a4f80f20cb 100644 --- a/nibabel/benchmarks/bench_finite_range.py +++ b/nibabel/benchmarks/bench_finite_range.py @@ -28,16 +28,17 @@ def bench_finite_range(): sys.stdout.flush() print_git_title('\nFinite range') mtime = measure('finite_range(arr)', repeat) - print('%30s %6.2f' % ('float64 all finite', mtime)) + fmt = '{:30s} {:6.2f}'.format + print(fmt('float64 all finite', mtime)) arr[:, :, :, 1] = np.nan mtime = measure('finite_range(arr)', repeat) - print('%30s %6.2f' % ('float64 many NaNs', mtime)) + print(fmt('float64 many NaNs', mtime)) arr[:, :, :, 1] = np.inf mtime = measure('finite_range(arr)', repeat) - print('%30s %6.2f' % ('float64 many infs', mtime)) + print(fmt('float64 many infs', mtime)) # Int16 input, float output arr = np.random.random_integers(low=-1000, high=1000, size=img_shape) arr = arr.astype(np.int16) mtime = measure('finite_range(arr)', repeat) - print('%30s %6.2f' % ('int16', mtime)) + print(fmt('int16', mtime)) sys.stdout.flush() diff --git a/nibabel/benchmarks/bench_load_save.py b/nibabel/benchmarks/bench_load_save.py index 007753ce51..b881c286fb 100644 --- a/nibabel/benchmarks/bench_load_save.py +++ b/nibabel/benchmarks/bench_load_save.py @@ -34,20 +34,21 @@ def bench_load_save(): print_git_title('Image load save') hdr.set_data_dtype(np.float32) mtime = measure('sio.truncate(0); img.to_file_map()', repeat) - print('%30s %6.2f' % ('Save float64 to float32', mtime)) + fmt = '{:30s} {:6.2f}'.format + print(fmt('Save float64 to float32', mtime)) mtime = measure('img.from_file_map(img.file_map)', repeat) - print('%30s %6.2f' % ('Load from float32', mtime)) + print(fmt('Load from float32', mtime)) hdr.set_data_dtype(np.int16) mtime = measure('sio.truncate(0); img.to_file_map()', repeat) - print('%30s %6.2f' % ('Save float64 to int16', mtime)) + print(fmt('Save float64 to int16', mtime)) mtime = measure('img.from_file_map(img.file_map)', repeat) - print('%30s %6.2f' % ('Load from int16', mtime)) + print(fmt('Load from int16', mtime)) # Set a lot of NaNs to check timing arr[:, :, :20] = np.nan mtime = measure('sio.truncate(0); img.to_file_map()', repeat) - print('%30s %6.2f' % ('Save float64 to int16, NaNs', mtime)) + print(fmt('Save float64 to int16, NaNs', mtime)) mtime = measure('img.from_file_map(img.file_map)', repeat) - print('%30s %6.2f' % ('Load from int16, NaNs', mtime)) + print(fmt('Load from int16, NaNs', mtime)) # Int16 input, float output arr = np.random.random_integers(low=-1000, high=1000, size=img_shape) arr = arr.astype(np.int16) @@ -57,5 +58,5 @@ def bench_load_save(): hdr = img.header hdr.set_data_dtype(np.float32) mtime = measure('sio.truncate(0); img.to_file_map()', repeat) - print('%30s %6.2f' % ('Save Int16 to float32', mtime)) + print(fmt('Save Int16 to float32', mtime)) sys.stdout.flush() From 391027533d4dfbfa3fa4e3c60f3ec161c8ca1c5a Mon Sep 17 00:00:00 2001 From: "Christopher J. Markiewicz" Date: Sun, 12 Jan 2025 12:22:00 -0500 Subject: [PATCH 07/11] chore: pre-commit autoupdate --- .pre-commit-config.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 4f49318eb0..8dd5d0547c 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,7 +1,7 @@ exclude: ".*/data/.*" repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.6.0 + rev: v5.0.0 hooks: - id: trailing-whitespace - id: end-of-file-fixer @@ -13,7 +13,7 @@ repos: - id: check-merge-conflict - id: check-vcs-permalinks - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.6.4 + rev: v0.9.1 hooks: - id: ruff args: [ --fix ] @@ -24,7 +24,7 @@ repos: args: [ --select, ISC001, --fix ] exclude: = ["doc", "tools"] - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.11.2 + rev: v1.14.1 hooks: - id: mypy # Sync with project.optional-dependencies.typing From 40e41208a0f04063b3c4e373a65da1a2a6a275b5 Mon Sep 17 00:00:00 2001 From: "Christopher J. Markiewicz" Date: Sun, 12 Jan 2025 12:22:13 -0500 Subject: [PATCH 08/11] sty: ruff format [git-blame-ignore-rev] --- bin/parrec2nii | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/bin/parrec2nii b/bin/parrec2nii index 4a21c6d288..e5ec8bfe38 100755 --- a/bin/parrec2nii +++ b/bin/parrec2nii @@ -1,6 +1,5 @@ #!python -"""PAR/REC to NIfTI converter -""" +"""PAR/REC to NIfTI converter""" from nibabel.cmdline.parrec2nii import main From 77dfa11b47d0525ba526821b2f4084cec3a0fbbd Mon Sep 17 00:00:00 2001 From: "Christopher J. Markiewicz" Date: Sun, 12 Jan 2025 12:23:12 -0500 Subject: [PATCH 09/11] chore: Stop ignoring removed rules --- .git-blame-ignore-revs | 4 ++++ pyproject.toml | 3 --- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index d0546f627f..7769a5f080 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -1,3 +1,7 @@ +# Sun Jan 12 12:22:13 2025 -0500 - markiewicz@stanford.edu - sty: ruff format [git-blame-ignore-rev] +40e41208a0f04063b3c4e373a65da1a2a6a275b5 +# Sun Jan 12 11:51:49 2025 -0500 - markiewicz@stanford.edu - STY: ruff format [git-blame-ignore-rev] +7e5d584910c67851dcfcd074ff307122689b61f5 # Sun Jan 1 12:38:02 2023 -0500 - effigies@gmail.com - STY: Run pre-commit config on all files d14c1cf282a9c3b19189f490f10c35f5739e24d1 # Thu Dec 29 22:53:17 2022 -0500 - effigies@gmail.com - STY: Reduce array().astype() and similar constructs diff --git a/pyproject.toml b/pyproject.toml index 3b2dfc99b1..bf0688142f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -153,8 +153,6 @@ ignore = [ "C416", "PERF203", "PIE790", - "PT004", # deprecated - "PT005", # deprecated "PT007", "PT011", "PT012", @@ -165,7 +163,6 @@ ignore = [ "RUF012", # TODO: enable "RUF015", "RUF017", # TODO: enable - "UP027", # deprecated "UP038", # https://github.com/astral-sh/ruff/issues/7871 # https://docs.astral.sh/ruff/formatter/#conflicting-lint-rules "W191", From 2c31a6e342ddc1d7faf5e3ee921a9b37ad0a7def Mon Sep 17 00:00:00 2001 From: Chris Markiewicz Date: Mon, 13 Jan 2025 11:19:36 -0500 Subject: [PATCH 10/11] Update nibabel/volumeutils.py --- nibabel/volumeutils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nibabel/volumeutils.py b/nibabel/volumeutils.py index d8b64fd4bf..700579a2e3 100644 --- a/nibabel/volumeutils.py +++ b/nibabel/volumeutils.py @@ -338,7 +338,7 @@ def pretty_mapping( if getterfunc is None: getterfunc = getitem mxlen = max(len(str(name)) for name in mapping) - return '\n'.join([f'{name:{mxlen}s} : {getterfunc(mapping, name)}' for name in mapping]) + return '\n'.join(f'{name:{mxlen}s} : {getterfunc(mapping, name)}' for name in mapping) def make_dt_codes(codes_seqs: ty.Sequence[ty.Sequence]) -> Recoder: From eaa72005ded1213ec5a5b8c525eefd65dd7289d5 Mon Sep 17 00:00:00 2001 From: "Christopher J. Markiewicz" Date: Tue, 14 Jan 2025 16:12:40 -0500 Subject: [PATCH 11/11] chore: Enable implicit-string-concatenation rules --- pyproject.toml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index bf0688142f..73f01b66e3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -125,6 +125,7 @@ select = [ "FLY", "FURB", "I", + "ISC", "PERF", "PGH", "PIE", @@ -177,8 +178,6 @@ ignore = [ "Q003", "COM812", "COM819", - "ISC001", - "ISC002", ] [tool.ruff.lint.per-file-ignores]