Skip to content

Commit

Permalink
Replace all %-substitution and .format() calls with f-strings (#506)
Browse files Browse the repository at this point in the history
Eliminate all old-style string replacement (`%` substitutions) and
explicit `.format()` calls, in favor of equivalent f-strings.
  • Loading branch information
kleisauke authored Sep 21, 2024
1 parent 2c67877 commit 6ce5540
Show file tree
Hide file tree
Showing 18 changed files with 57 additions and 65 deletions.
10 changes: 5 additions & 5 deletions doc/intro.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down
2 changes: 1 addition & 1 deletion examples/pil-numpy-pyvips.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)


Expand Down
2 changes: 1 addition & 1 deletion examples/progress.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)')
Expand Down
2 changes: 1 addition & 1 deletion examples/soak-test.py
Original file line number Diff line number Diff line change
Expand Up @@ -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")
2 changes: 1 addition & 1 deletion examples/try5.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)


Expand Down
11 changes: 5 additions & 6 deletions pyvips/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,17 +32,16 @@
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')

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
Expand Down Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion pyvips/error.py
Original file line number Diff line number Diff line change
Expand Up @@ -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__ = [
Expand Down
4 changes: 2 additions & 2 deletions pyvips/gobject.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion pyvips/gvalue.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
5 changes: 3 additions & 2 deletions pyvips/pyvips_build.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,10 @@
''' if major == 8 and minor < 6 else ''

ffibuilder.set_source("_libvips",
r"""
f"""
#include <vips/vips.h>
""" + compat,
{compat}
""",
**pkgconfig.parse('vips'))

features = {
Expand Down
2 changes: 1 addition & 1 deletion pyvips/vdecls.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
22 changes: 10 additions & 12 deletions pyvips/vimage.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.')

Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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()

Expand Down Expand Up @@ -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):
Expand Down Expand Up @@ -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)]
Expand Down Expand Up @@ -1261,9 +1260,8 @@ def __repr__(self):
array = self.tolist()
return repr(array)
else:
return ('<pyvips.Image {0}x{1} {2}, {3} bands, {4}>'.
format(self.width, self.height, self.format, self.bands,
self.interpretation))
return (f'<pyvips.Image {self.width}x{self.height} {self.format}, '
f'{self.bands} bands, {self.interpretation}>')

def __getattr__(self, name):
"""Divert unknown names to libvips.
Expand Down
2 changes: 1 addition & 1 deletion pyvips/vinterpolate.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
35 changes: 16 additions & 19 deletions pyvips/voperation.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down Expand Up @@ -232,18 +232,16 @@ 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)

# set any string options before any args so they can't be
# 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
Expand Down Expand Up @@ -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]
Expand All @@ -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
Expand Down Expand Up @@ -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'
Expand Down Expand Up @@ -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:: '
Expand Down Expand Up @@ -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]
Expand Down Expand Up @@ -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
Expand Down
6 changes: 2 additions & 4 deletions pyvips/vsource.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand All @@ -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)

Expand Down
7 changes: 3 additions & 4 deletions pyvips/vtarget.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand All @@ -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)

Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()
4 changes: 2 additions & 2 deletions tests/helpers/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -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


Expand Down

0 comments on commit 6ce5540

Please sign in to comment.