From 6ce554099c64f5d2c1b13a04f4a8de3e7801c7ed Mon Sep 17 00:00:00 2001 From: Kleis Auke Wolthuizen Date: Sat, 21 Sep 2024 17:54:56 +0200 Subject: [PATCH] Replace all %-substitution and .format() calls with f-strings (#506) Eliminate all old-style string replacement (`%` substitutions) and explicit `.format()` calls, in favor of equivalent f-strings. --- doc/intro.rst | 10 +++++----- examples/pil-numpy-pyvips.py | 2 +- examples/progress.py | 2 +- examples/soak-test.py | 2 +- examples/try5.py | 2 +- pyvips/__init__.py | 11 +++++------ pyvips/error.py | 2 +- pyvips/gobject.py | 4 ++-- pyvips/gvalue.py | 2 +- pyvips/pyvips_build.py | 5 +++-- pyvips/vdecls.py | 2 +- pyvips/vimage.py | 22 ++++++++++------------ pyvips/vinterpolate.py | 2 +- pyvips/voperation.py | 35 ++++++++++++++++------------------- pyvips/vsource.py | 6 ++---- pyvips/vtarget.py | 7 +++---- setup.py | 2 +- tests/helpers/helpers.py | 4 ++-- 18 files changed, 57 insertions(+), 65 deletions(-) diff --git a/doc/intro.rst b/doc/intro.rst index 6786288..fe8effc 100644 --- a/doc/intro.rst +++ b/doc/intro.rst @@ -333,11 +333,11 @@ Handlers are given a `progress` object containing a number of useful fields. For example:: def eval_handler(image, progress): - print('run time so far (secs) = {}'.format(progress.run)) - print('estimated time of arrival (secs) = {}'.format(progress.eta)) - print('total number of pels to process = {}'.format(progress.tpels)) - print('number of pels processed so far = {}'.format(progress.npels)) - print('percent complete = {}'.format(progress.percent)) + print(f' run = {progress.run} (seconds of run time)') + print(f' eta = {progress.eta} (estimated seconds left)') + print(f' tpels = {progress.tpels} (total number of pels)') + print(f' npels = {progress.npels} (number of pels computed so far)') + print(f' percent = {progress.percent} (percent complete)') Use :meth:`.Image.set_kill` on the image to stop computation early. diff --git a/examples/pil-numpy-pyvips.py b/examples/pil-numpy-pyvips.py index 1bd1b39..b040697 100755 --- a/examples/pil-numpy-pyvips.py +++ b/examples/pil-numpy-pyvips.py @@ -8,7 +8,7 @@ import numpy as np if len(sys.argv) != 3: - print('usage: {0} input-filename output-filename'.format(sys.argv[0])) + print(f'usage: {sys.argv[0]} input-filename output-filename') sys.exit(-1) diff --git a/examples/progress.py b/examples/progress.py index 414d709..8307bb1 100755 --- a/examples/progress.py +++ b/examples/progress.py @@ -4,7 +4,7 @@ def progress_print(name, progress): - print(f'signal {name}:'.format(name)) + print(f'signal {name}:') print(f' run = {progress.run} (seconds of run time)') print(f' eta = {progress.eta} (estimated seconds left)') print(f' tpels = {progress.tpels} (total number of pels)') diff --git a/examples/soak-test.py b/examples/soak-test.py index 79ff23d..8a7ccf9 100755 --- a/examples/soak-test.py +++ b/examples/soak-test.py @@ -7,7 +7,7 @@ pyvips.cache_set_max(0) for i in range(1000): - print("loop {0} ...".format(i)) + print(f"loop {i} ...") im = pyvips.Image.new_from_file(sys.argv[1]) im = im.embed(100, 100, 3000, 3000, extend="mirror") im.write_to_file("x.v") diff --git a/examples/try5.py b/examples/try5.py index 9aade16..ebc307f 100755 --- a/examples/try5.py +++ b/examples/try5.py @@ -11,7 +11,7 @@ def should_equal(test, a, b): if abs(a - b) > 0.01: - print('%s: seen %g and %g' % (test, a, b)) + print(f'{test}: seen {a:g} and {b:g}') sys.exit(1) diff --git a/pyvips/__init__.py b/pyvips/__init__.py index 323992b..82fe1cf 100644 --- a/pyvips/__init__.py +++ b/pyvips/__init__.py @@ -32,9 +32,8 @@ lib_minor = vips_lib.vips_version(1) wrap_major = vips_lib.VIPS_MAJOR_VERSION wrap_minor = vips_lib.VIPS_MINOR_VERSION - logger.debug('Module generated for libvips %s.%s' % - (wrap_major, wrap_minor)) - logger.debug('Linked to libvips %s.%s' % (lib_major, lib_minor)) + logger.debug(f'Module generated for libvips {wrap_major}.{wrap_minor}') + logger.debug(f'Linked to libvips {lib_major}.{lib_minor}') if wrap_major != lib_major or wrap_minor != lib_minor: raise Exception('bad wrapper version') @@ -42,7 +41,7 @@ API_mode = True except Exception as e: - logger.debug('Binary module load failed: %s' % e) + logger.debug(f'Binary module load failed: {e}') logger.debug('Falling back to ABI mode') from cffi import FFI @@ -141,14 +140,14 @@ class GLogLevelFlags(object): @ffi.def_extern() def _log_handler_callback(domain, level, message, user_data): logger.log(GLogLevelFlags.LEVEL_TO_LOGGER[level], - '{0}: {1}'.format(_to_string(domain), _to_string(message))) + f'{_to_string(domain)}: {_to_string(message)}') # keep a ref to the cb to stop it being GCd _log_handler_cb = glib_lib._log_handler_callback else: def _log_handler_callback(domain, level, message, user_data): logger.log(GLogLevelFlags.LEVEL_TO_LOGGER[level], - '{0}: {1}'.format(_to_string(domain), _to_string(message))) + f'{_to_string(domain)}: {_to_string(message)}') # keep a ref to the cb to stop it being GCd _log_handler_cb = ffi.callback('GLogFunc', _log_handler_callback) diff --git a/pyvips/error.py b/pyvips/error.py index 962a1f6..8e78b78 100644 --- a/pyvips/error.py +++ b/pyvips/error.py @@ -68,7 +68,7 @@ def __init__(self, message, detail=None): logger.debug('Error %s %s', self.message, self.detail) def __str__(self): - return '{0}\n {1}'.format(self.message, self.detail) + return f'{self.message}\n {self.detail}' __all__ = [ diff --git a/pyvips/gobject.py b/pyvips/gobject.py index 706424c..93c6564 100644 --- a/pyvips/gobject.py +++ b/pyvips/gobject.py @@ -159,7 +159,7 @@ def new_pointer_from_gtype(gtype): pointer = gobject_lib.g_object_new(gtype, ffi.NULL) if pointer == ffi.NULL: - raise Error("can't create {0}".format(type_name(gtype))) + raise Error(f"can't create {type_name(gtype)}") return pointer @@ -176,7 +176,7 @@ def signal_connect(self, name, callback): """ if name not in _marshalers: - raise Error('unsupported signal "{0}"'.format(name)) + raise Error(f'unsupported signal "{name}"') go = ffi.cast('GObject *', self.pointer) handle = ffi.new_handle(callback) diff --git a/pyvips/gvalue.py b/pyvips/gvalue.py index 88f2360..04069e8 100644 --- a/pyvips/gvalue.py +++ b/pyvips/gvalue.py @@ -84,7 +84,7 @@ def gtype_to_python(gtype): name = type_name(gtype) if name.startswith('Vips'): name = name[4:] - return "Union[str, %s]" % name + return f"Union[str, {name}]" if gtype in GValue._gtype_to_python: return GValue._gtype_to_python[gtype] if fundamental in GValue._gtype_to_python: diff --git a/pyvips/pyvips_build.py b/pyvips/pyvips_build.py index 788b479..e76c13b 100644 --- a/pyvips/pyvips_build.py +++ b/pyvips/pyvips_build.py @@ -32,9 +32,10 @@ ''' if major == 8 and minor < 6 else '' ffibuilder.set_source("_libvips", - r""" + f""" #include - """ + compat, + {compat} + """, **pkgconfig.parse('vips')) features = { diff --git a/pyvips/vdecls.py b/pyvips/vdecls.py index d142268..3a68a37 100644 --- a/pyvips/vdecls.py +++ b/pyvips/vdecls.py @@ -472,7 +472,7 @@ def cdefs(features): # add contents of features as a comment ... handy for debugging for key, value in features.items(): - code += '//%s = %s\n' % (key, value) + code += f'//{key} = {value}\n' return code diff --git a/pyvips/vimage.py b/pyvips/vimage.py index 46f1ee1..a4ab8cd 100644 --- a/pyvips/vimage.py +++ b/pyvips/vimage.py @@ -181,7 +181,7 @@ def _guess_interpretation(bands, format): """ if format not in FORMAT_TO_TYPESTR: - raise ValueError('Unknown format: {}'.format(format)) + raise ValueError(f'Unknown format: {format}') if not isinstance(bands, int) or bands < 1: raise ValueError('Number of bands must be a positive integer.') @@ -323,7 +323,7 @@ def new_from_file(vips_filename, **kwargs): pointer = vips_lib.vips_foreign_find_load(vips_filename) if pointer == ffi.NULL: - raise Error('unable to load from file {0}'.format(vips_filename)) + raise Error(f'unable to load from file {vips_filename}') name = _to_string(pointer) return pyvips.Operation.call(name, filename, @@ -493,8 +493,7 @@ def new_from_array(cls, obj, scale=1.0, offset=0.0, interpretation=None): if ndim > 3: raise ValueError('array has more than 3 dimensions') if typestr not in TYPESTR_TO_FORMAT: - raise ValueError('conversion from {0} not supported' - .format(typestr)) + raise ValueError(f'conversion from {typestr} not supported') if ndim == 0: width = 1 @@ -776,7 +775,7 @@ def write_to_file(self, vips_filename, **kwargs): pointer = vips_lib.vips_foreign_find_save(vips_filename) if pointer == ffi.NULL: - raise Error('unable to write to file {0}'.format(vips_filename)) + raise Error(f'unable to write to file {vips_filename}') name = _to_string(pointer) return pyvips.Operation.call(name, self, filename, @@ -1038,7 +1037,7 @@ def get(self, name): result = vips_lib.vips_image_get(self.pointer, _to_bytes(name), gv.pointer) if result != 0: - raise Error('unable to get {0}'.format(name)) + raise Error(f'unable to get {name}') return gv.get() @@ -1107,8 +1106,8 @@ def set(self, name, value): """ gtype = self.get_typeof(name) if gtype == 0: - raise Error('metadata item {0} does not exist - ' - 'use set_type() to create and set'.format(name)) + raise Error(f'metadata item {name} does not exist -' + ' use set_type() to create and set') self.set_type(gtype, name, value) def remove(self, name): @@ -1143,7 +1142,7 @@ def tolist(self): row_els = self.width if not is_complex else 2 * self.width - rowfmt = '{0}{1}'.format(row_els, FORMAT_TO_PYFORMAT[self.format]) + rowfmt = f'{row_els}{FORMAT_TO_PYFORMAT[self.format]}' buf = self.write_to_memory() lst = [list(row) for row in struct.iter_unpack(rowfmt, buf)] @@ -1261,9 +1260,8 @@ def __repr__(self): array = self.tolist() return repr(array) else: - return (''. - format(self.width, self.height, self.format, self.bands, - self.interpretation)) + return (f'') def __getattr__(self, name): """Divert unknown names to libvips. diff --git a/pyvips/vinterpolate.py b/pyvips/vinterpolate.py index 5b0f2c7..f111469 100644 --- a/pyvips/vinterpolate.py +++ b/pyvips/vinterpolate.py @@ -35,7 +35,7 @@ def new(name): vi = vips_lib.vips_interpolate_new(_to_bytes(name)) if vi == ffi.NULL: - raise Error('no such interpolator {0}'.format(name)) + raise Error(f'no such interpolator {name}') return Interpolate(vi) diff --git a/pyvips/voperation.py b/pyvips/voperation.py index db66b15..849fcb8 100644 --- a/pyvips/voperation.py +++ b/pyvips/voperation.py @@ -188,7 +188,7 @@ def __init__(self, pointer): def new_from_name(operation_name): vop = vips_lib.vips_operation_new(_to_bytes(operation_name)) if vop == ffi.NULL: - raise Error('no such operation {0}'.format(operation_name)) + raise Error(f'no such operation {operation_name}') return Operation(vop) def set(self, name, flags, match_image, value): @@ -232,10 +232,8 @@ def call(operation_name, *args, **kwargs): intro = Introspect.get(operation_name) if len(intro.required_input) != len(args): - raise Error('{0} needs {1} arguments, but {2} given' - .format(operation_name, - len(intro.required_input), - len(args))) + raise Error(f'{operation_name} needs {len(intro.required_input)} ' + f'arguments, but {len(args)} given') op = Operation.new_from_name(operation_name) @@ -243,7 +241,7 @@ def call(operation_name, *args, **kwargs): # overridden string_options = kwargs.pop('string_options', '') if not op.set_string(string_options): - raise Error('unable to call {0}'.format(operation_name)) + raise Error(f'unable to call {operation_name}') # the first image argument is the thing we expand constants to # match ... look inside tables for images, since we may be passing @@ -283,8 +281,8 @@ def add_reference(x): for name in kwargs: if (name not in intro.optional_input and name not in intro.optional_output): - raise Error('{0} does not support optional argument {1}' - .format(operation_name, name)) + raise Error(f'{operation_name} does not support optional ' + f'argument {name}') value = kwargs[name] details = intro.details[name] @@ -300,7 +298,7 @@ def add_reference(x): vop = vips_lib.vips_cache_operation_build(op.pointer) if vop == ffi.NULL: vips_lib.vips_object_unref_outputs(op.vobject) - raise Error('unable to call {0}'.format(operation_name)) + raise Error(f'unable to call {operation_name}') op = Operation(vop) # attach all input refs to output x @@ -353,7 +351,7 @@ def generate_docstring(operation_name): intro = Introspect.get(operation_name) if (intro.flags & _OPERATION_DEPRECATED) != 0: raise Error('No such operator.', - 'operator "{0}" is deprecated'.format(operation_name)) + f'operator "{operation_name}" is deprecated') result = intro.description[0].upper() + intro.description[1:] + '.\n\n' result += 'Example:\n' @@ -417,7 +415,7 @@ def generate_sphinx(operation_name): intro = Introspect.get(operation_name) if (intro.flags & _OPERATION_DEPRECATED) != 0: raise Error('No such operator.', - 'operator "{0}" is deprecated'.format(operation_name)) + f'operator "{operation_name}" is deprecated') if intro.member_x is not None: result = '.. method:: ' @@ -451,14 +449,13 @@ def generate_sphinx(operation_name): for name in intro.method_args + intro.doc_optional_input: details = intro.details[name] - result += (':param {0}: {1}\n'. - format(name, details['blurb'])) - result += (':type {0}: {1}\n'. - format(name, GValue.gtype_to_python(details['type']))) + result += f':param {name}: {details["blurb"]}\n' + result += (f':type {name}: ' + f'{GValue.gtype_to_python(details["type"])}\n') for name in intro.doc_optional_output: - result += (':param {0}: enable output: {1}\n'. - format(name, intro.details[name]['blurb'])) - result += (':type {0}: bool\n'.format(name)) + result += (f':param {name}: ' + f'enable output: {intro.details[name]["blurb"]}\n') + result += f':type {name}: bool\n' output_types = [GValue.gtype_to_python(intro.details[name]['type']) for name in intro.required_output] @@ -532,7 +529,7 @@ def add_name(gtype, a, b): print(' .. autosummary::') print(' :nosignatures:\n') for name in all_names: - print(' ~{0}'.format(name)) + print(f' ~{name}') print() # Output docs diff --git a/pyvips/vsource.py b/pyvips/vsource.py index a1b7d50..d4f2386 100644 --- a/pyvips/vsource.py +++ b/pyvips/vsource.py @@ -35,8 +35,7 @@ def new_from_descriptor(descriptor): # sources are mutable, so we can't use the cache pointer = vips_lib.vips_source_new_from_descriptor(descriptor) if pointer == ffi.NULL: - raise Error("can't create source from descriptor {0}" - .format(descriptor)) + raise Error(f"can't create source from descriptor {descriptor}") return Source(pointer) @@ -57,8 +56,7 @@ def new_from_file(filename): pointer = vips_lib.vips_source_new_from_file(_to_bytes(filename)) if pointer == ffi.NULL: - raise Error("can't create source from filename {0}" - .format(filename)) + raise Error(f"can't create source from filename {filename}") return Source(pointer) diff --git a/pyvips/vtarget.py b/pyvips/vtarget.py index 9eecfdf..10de359 100644 --- a/pyvips/vtarget.py +++ b/pyvips/vtarget.py @@ -36,8 +36,8 @@ def new_to_descriptor(descriptor): # targets are mutable, so we can't use the cache pointer = vips_lib.vips_target_new_to_descriptor(descriptor) if pointer == ffi.NULL: - raise Error("can't create output target from descriptor {0}" - .format(descriptor)) + raise Error(f"can't create output target from descriptor " + f'{descriptor}') return Target(pointer) @@ -57,8 +57,7 @@ def new_to_file(filename): pointer = vips_lib.vips_target_new_to_file(_to_bytes(filename)) if pointer == ffi.NULL: - raise Error("can't create output target from filename {0}" - .format(filename)) + raise Error(f"can't create output target from filename {filename}") return Target(pointer) diff --git a/setup.py b/setup.py index 2bebdae..331453c 100644 --- a/setup.py +++ b/setup.py @@ -18,5 +18,5 @@ try: setup(cffi_modules=['pyvips/pyvips_build.py:ffibuilder']) except Exception as e: - print('Falling back to ABI mode. Details: {0}'.format(e)) + print(f'Falling back to ABI mode. Details: {e}') setup() diff --git a/tests/helpers/helpers.py b/tests/helpers/helpers.py index d7f14fd..be35059 100644 --- a/tests/helpers/helpers.py +++ b/tests/helpers/helpers.py @@ -74,14 +74,14 @@ def run_fn2(fn, x, y): # test a pair of things which can be lists for approx. equality def assert_almost_equal_objects(a, b, threshold=0.0001, msg=''): - # print 'assertAlmostEqualObjects %s = %s' % (a, b) + # print(f'assertAlmostEqualObjects {a} = {b}') assert all([pytest.approx(x, abs=threshold) == y for x, y in zip_expand(a, b)]), msg # test a pair of things which can be lists for equality def assert_equal_objects(a, b, msg=''): - # print 'assertEqualObjects %s = %s' % (a, b) + # print(f'assertEqualObjects {a} = {b}') assert all([x == y for x, y in zip_expand(a, b)]), msg