diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index d507680f64..08cf87f28b 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -18,7 +18,7 @@ ci:
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
- rev: v4.5.0
+ rev: v4.6.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
@@ -36,7 +36,7 @@ repos:
additional_dependencies: [black==24.3.0]
- repo: https://github.com/astral-sh/ruff-pre-commit
- rev: v0.4.0
+ rev: v0.4.3
hooks:
- id: ruff-format
types_or: [ python, pyi, jupyter ]
@@ -50,7 +50,7 @@ repos:
- id: rst-backticks
- repo: https://github.com/MarcoGorelli/cython-lint
- rev: v0.16.0
+ rev: v0.16.2
hooks:
- id: cython-lint
args: [--no-pycodestyle]
diff --git a/yt/_maintenance/backports.py b/yt/_maintenance/backports.py
index f3ee778243..78577af3e4 100644
--- a/yt/_maintenance/backports.py
+++ b/yt/_maintenance/backports.py
@@ -52,7 +52,7 @@ def __new__(cls, *values):
if len(values) == 3:
# check that errors argument is a string
if not isinstance(values[2], str):
- raise TypeError("errors must be a string, not %r" % (values[2]))
+ raise TypeError("errors must be a string, not %r" % (values[2])) # noqa: UP031
value = str(*values)
member = str.__new__(cls, value)
member._value_ = value
diff --git a/yt/data_objects/analyzer_objects.py b/yt/data_objects/analyzer_objects.py
index b6824b6249..97610f8273 100644
--- a/yt/data_objects/analyzer_objects.py
+++ b/yt/data_objects/analyzer_objects.py
@@ -67,7 +67,7 @@ class QuantityProxy(AnalysisTask):
def __repr__(self):
# Stolen from YTDataContainer.__repr__
s = f"{self.__class__.__name__}: "
- s += ", ".join(["%s" % list(self.args)])
+ s += ", ".join([str(list(self.args))])
s += ", ".join(f"{k}={v}" for k, v in self.kwargs.items())
return s
diff --git a/yt/data_objects/construction_data_containers.py b/yt/data_objects/construction_data_containers.py
index adcf01532c..03c10f92c1 100644
--- a/yt/data_objects/construction_data_containers.py
+++ b/yt/data_objects/construction_data_containers.py
@@ -880,10 +880,11 @@ def get_data(self, fields=None):
fill, gen, part, alias = self._split_fields(fields_to_get)
except NeedsGridType as e:
if self._num_ghost_zones == 0:
+ num_ghost_zones = self._num_ghost_zones
raise RuntimeError(
"Attempting to access a field that needs ghost zones, but "
- "num_ghost_zones = %s. You should create the covering grid "
- "with nonzero num_ghost_zones." % self._num_ghost_zones
+ f"{num_ghost_zones = }. You should create the covering grid "
+ "with nonzero num_ghost_zones."
) from e
else:
raise
diff --git a/yt/data_objects/level_sets/clump_info_items.py b/yt/data_objects/level_sets/clump_info_items.py
index 798aecc30b..d0c727f310 100644
--- a/yt/data_objects/level_sets/clump_info_items.py
+++ b/yt/data_objects/level_sets/clump_info_items.py
@@ -109,7 +109,7 @@ def _distance_to_main_clump(clump, units="pc"):
distance = np.sqrt(((master_com - my_com) ** 2).sum())
distance.convert_to_units("pc")
return (
- "Distance from master center of mass: %%.6e %s." % units,
+ f"Distance from master center of mass: %.6e {units}.",
distance.in_units(units),
)
diff --git a/yt/data_objects/static_output.py b/yt/data_objects/static_output.py
index 5c546a1849..57f6507dcd 100644
--- a/yt/data_objects/static_output.py
+++ b/yt/data_objects/static_output.py
@@ -1395,7 +1395,7 @@ def set_units(self):
new_unit,
my_u.base_value / (1 + self.current_redshift),
dimensions.length,
- "\\rm{%s}/(1+z)" % my_unit,
+ f"\\rm{{{my_unit}}}/(1+z)",
prefixable=True,
)
self.unit_registry.modify("a", 1 / (1 + self.current_redshift))
diff --git a/yt/fields/derived_field.py b/yt/fields/derived_field.py
index 42b6ff6636..7e90277b2d 100644
--- a/yt/fields/derived_field.py
+++ b/yt/fields/derived_field.py
@@ -303,7 +303,7 @@ def get_label(self, projected=False):
name = self.display_name
# Start with the field name
- data_label = r"$\rm{%s}" % name
+ data_label = rf"$\rm{{{name}}}"
# Grab the correct units
if projected:
diff --git a/yt/fields/particle_fields.py b/yt/fields/particle_fields.py
index c52bd2a0b4..7db9bfabea 100644
--- a/yt/fields/particle_fields.py
+++ b/yt/fields/particle_fields.py
@@ -110,7 +110,7 @@ def particle_count(field, data):
function=particle_count,
validators=[ValidateSpatial()],
units="",
- display_name=r"\mathrm{%s Count}" % ptype_dn,
+ display_name=rf"\mathrm{{{ptype_dn} Count}}",
)
def particle_mass(field, data):
@@ -125,7 +125,7 @@ def particle_mass(field, data):
sampling_type="cell",
function=particle_mass,
validators=[ValidateSpatial()],
- display_name=r"\mathrm{%s Mass}" % ptype_dn,
+ display_name=rf"\mathrm{{{ptype_dn} Mass}}",
units=unit_system["mass"],
)
@@ -144,7 +144,7 @@ def particle_density(field, data):
sampling_type="cell",
function=particle_density,
validators=[ValidateSpatial()],
- display_name=r"\mathrm{%s Density}" % ptype_dn,
+ display_name=rf"\mathrm{{{ptype_dn} Density}}",
units=unit_system["density"],
)
@@ -160,7 +160,7 @@ def particle_cic(field, data):
sampling_type="cell",
function=particle_cic,
validators=[ValidateSpatial()],
- display_name=r"\mathrm{%s CIC Density}" % ptype_dn,
+ display_name=rf"\mathrm{{{ptype_dn} CIC Density}}",
units=unit_system["density"],
)
diff --git a/yt/fields/vector_operations.py b/yt/fields/vector_operations.py
index 0c3cbe0a2f..99e0544539 100644
--- a/yt/fields/vector_operations.py
+++ b/yt/fields/vector_operations.py
@@ -133,7 +133,7 @@ def _los_field(field, data):
function=_los_field,
units=field_units,
validators=validators,
- display_name=r"\mathrm{Line of Sight %s}" % basename.capitalize(),
+ display_name=rf"\mathrm{{Line of Sight {basename.capitalize()}}}",
)
diff --git a/yt/frontends/adaptahop/data_structures.py b/yt/frontends/adaptahop/data_structures.py
index d36bcff4a2..e8cb853568 100644
--- a/yt/frontends/adaptahop/data_structures.py
+++ b/yt/frontends/adaptahop/data_structures.py
@@ -107,7 +107,7 @@ def _guess_headers_from_file(self, filename) -> None:
pass
if not ok:
- raise OSError("Could not read headers from file %s" % filename)
+ raise OSError(f"Could not read headers from file {filename}")
istart = fpu.tell()
fpu.seek(0, 2)
@@ -130,7 +130,7 @@ def _guess_headers_from_file(self, filename) -> None:
continue
if not ok:
- raise OSError("Could not guess fields from file %s" % filename)
+ raise OSError(f"Could not guess fields from file {filename}")
self._header_attributes = header_attributes
self._halo_attributes = attributes
diff --git a/yt/frontends/boxlib/fields.py b/yt/frontends/boxlib/fields.py
index 5e32ad83e7..8ce65068a7 100644
--- a/yt/frontends/boxlib/fields.py
+++ b/yt/frontends/boxlib/fields.py
@@ -488,7 +488,7 @@ def setup_fluid_fields(self):
sampling_type="cell",
function=func,
units=unit_system["density"],
- display_name=r"\rho %s" % tex_label,
+ display_name=rf"\rho {tex_label}",
)
# Most of the time our species will be of the form
@@ -507,7 +507,7 @@ def setup_fluid_fields(self):
elif field.startswith("omegadot("):
nice_name, tex_label = _nice_species_name(field)
- display_name = r"\dot{\omega}\left[%s\right]" % tex_label
+ display_name = rf"\dot{{\omega}}\left[{tex_label}\right]"
# Overwrite field to use nicer tex_label'ed display_name
self.add_output_field(
("boxlib", field),
diff --git a/yt/frontends/enzo/simulation_handling.py b/yt/frontends/enzo/simulation_handling.py
index 8733e40f84..5fb432650a 100644
--- a/yt/frontends/enzo/simulation_handling.py
+++ b/yt/frontends/enzo/simulation_handling.py
@@ -88,7 +88,7 @@ def _set_units(self):
new_unit,
self.unit_registry.lut[my_unit][0],
dimensions.length,
- "\\rm{%s}/(1+z)" % my_unit,
+ f"\\rm{{{my_unit}}}/(1+z)",
prefixable=True,
)
self.length_unit = self.quan(
diff --git a/yt/frontends/fits/misc.py b/yt/frontends/fits/misc.py
index 2da062b203..8362c6fa81 100644
--- a/yt/frontends/fits/misc.py
+++ b/yt/frontends/fits/misc.py
@@ -287,6 +287,6 @@ def _repr_html_(self):
img = base64.b64encode(f.read()).decode()
ret += (
r'
' % img
+ rf'src="data:image/png;base64,{img}">
'
)
return ret
diff --git a/yt/frontends/flash/data_structures.py b/yt/frontends/flash/data_structures.py
index 7d617f07a1..abc8d0d654 100644
--- a/yt/frontends/flash/data_structures.py
+++ b/yt/frontends/flash/data_structures.py
@@ -246,7 +246,7 @@ def _set_code_unit_attributes(self):
else:
raise RuntimeError(
"Runtime parameter unitsystem with "
- "value %s is unrecognized" % self["unitsystem"]
+ f"value {self['unitsystem']} is unrecognized"
)
else:
b_factor = 1.0
diff --git a/yt/frontends/gadget/simulation_handling.py b/yt/frontends/gadget/simulation_handling.py
index 505382aeca..b53c08ec89 100644
--- a/yt/frontends/gadget/simulation_handling.py
+++ b/yt/frontends/gadget/simulation_handling.py
@@ -81,7 +81,7 @@ def _set_units(self):
new_unit,
self.unit_registry.lut[my_unit][0],
dimensions.length,
- "\\rm{%s}/(1+z)" % my_unit,
+ f"\\rm{{{my_unit}}}/(1+z)",
prefixable=True,
)
self.length_unit = self.quan(
diff --git a/yt/frontends/ramses/data_structures.py b/yt/frontends/ramses/data_structures.py
index 97cc7c5af2..851cf29b88 100644
--- a/yt/frontends/ramses/data_structures.py
+++ b/yt/frontends/ramses/data_structures.py
@@ -417,7 +417,7 @@ def __init__(
elif num_ghost_zones < 0:
raise RuntimeError(
"Cannot initialize a domain subset with a negative number "
- "of ghost zones, was called with num_ghost_zones=%s" % num_ghost_zones
+ f"of ghost zones, was called with {num_ghost_zones=}"
)
@property
@@ -1038,8 +1038,8 @@ def caster(val):
if rheader["ordering type"] != "hilbert" and self._bbox is not None:
raise NotImplementedError(
- "The ordering %s is not compatible with the `bbox` argument."
- % rheader["ordering type"]
+ f"The ordering {rheader['ordering type']} "
+ "is not compatible with the `bbox` argument."
)
self.parameters.update(rheader)
self.domain_left_edge = np.zeros(3, dtype="float64")
diff --git a/yt/frontends/sph/data_structures.py b/yt/frontends/sph/data_structures.py
index 7d0e9c696d..3c65b7171d 100644
--- a/yt/frontends/sph/data_structures.py
+++ b/yt/frontends/sph/data_structures.py
@@ -59,8 +59,8 @@ def sph_smoothing_style(self):
def sph_smoothing_style(self, value):
if value not in self._sph_smoothing_styles:
raise ValueError(
- "Smoothing style not implemented: %s, please "
- "select one of the following: " % value,
+ f"Smoothing style not implemented: {value}, "
+ "please select one of the following: ",
self._sph_smoothing_styles,
)
diff --git a/yt/frontends/tipsy/data_structures.py b/yt/frontends/tipsy/data_structures.py
index 70d3e1cb77..d27c7f38d5 100644
--- a/yt/frontends/tipsy/data_structures.py
+++ b/yt/frontends/tipsy/data_structures.py
@@ -118,7 +118,7 @@ def _parse_parameter_file(self):
# the snapshot time and particle counts.
f = open(self.parameter_filename, "rb")
- hh = self.endian + "".join("%s" % (b) for a, b in self._header_spec)
+ hh = self.endian + "".join(str(b) for a, b in self._header_spec)
hvals = {
a: c
for (a, b), c in zip(
diff --git a/yt/funcs.py b/yt/funcs.py
index 94547af091..2c44d521f8 100644
--- a/yt/funcs.py
+++ b/yt/funcs.py
@@ -1086,12 +1086,20 @@ def array_like_field(data, x, field):
return data.ds.quan(x, units)
+def _full_type_name(obj: object = None, /, *, cls: Optional[type] = None) -> str:
+ if cls is not None and obj is not None:
+ raise TypeError("_full_type_name takes an object or a class, but not both")
+ if cls is None:
+ cls = obj.__class__
+ prefix = f"{cls.__module__}." if cls.__module__ != "builtins" else ""
+ return f"{prefix}{cls.__name__}"
+
+
def validate_3d_array(obj):
if not is_sequence(obj) or len(obj) != 3:
raise TypeError(
- "Expected an array of size (3,), received '{}' of length {}".format(
- str(type(obj)).split("'")[1], len(obj)
- )
+ f"Expected an array of size (3,), "
+ f"received {_full_type_name(obj)!r} of length {len(obj)}"
)
@@ -1135,23 +1143,21 @@ def validate_float(obj):
):
raise TypeError(
"Expected a numeric value (or tuple of format "
- "(float, String)), received an inconsistent tuple "
- "'%s'." % str(obj)
+ f"(float, String)), received an inconsistent tuple {str(obj)!r}."
)
else:
return
if is_sequence(obj) and (len(obj) != 1 or not isinstance(obj[0], numeric_type)):
raise TypeError(
"Expected a numeric value (or size-1 array), "
- "received '{}' of length {}".format(str(type(obj)).split("'")[1], len(obj))
+ f"received {_full_type_name(obj)!r} of length {len(obj)}"
)
def validate_sequence(obj):
if obj is not None and not is_sequence(obj):
raise TypeError(
- "Expected an iterable object, "
- "received '%s'" % str(type(obj)).split("'")[1]
+ "Expected an iterable object, " f"received {_full_type_name(obj)!r}"
)
@@ -1181,9 +1187,8 @@ def is_valid_field_key(key):
def validate_object(obj, data_type):
if obj is not None and not isinstance(obj, data_type):
raise TypeError(
- "Expected an object of '{}' type, received '{}'".format(
- str(data_type).split("'")[1], str(type(obj)).split("'")[1]
- )
+ f"Expected an object of {_full_type_name(cls=data_type)!r} type, "
+ f"received {_full_type_name(obj)!r}"
)
@@ -1209,13 +1214,13 @@ def validate_center(center):
raise TypeError(
"Expected 'center' to be in ['c', 'center', "
"'m', 'max', 'min'] or the prefix to be "
- "'max_'/'min_', received '%s'." % center
+ f"'max_'/'min_', received {center!r}."
)
elif not isinstance(center, (numeric_type, YTQuantity)) and not is_sequence(center):
raise TypeError(
"Expected 'center' to be a numeric object of type "
"list/tuple/np.ndarray/YTArray/YTQuantity, "
- "received '%s'." % str(type(center)).split("'")[1]
+ f"received {_full_type_name(center)}."
)
diff --git a/yt/geometry/coordinates/cartesian_coordinates.py b/yt/geometry/coordinates/cartesian_coordinates.py
index 95812c4d91..775de8c6a5 100644
--- a/yt/geometry/coordinates/cartesian_coordinates.py
+++ b/yt/geometry/coordinates/cartesian_coordinates.py
@@ -593,8 +593,8 @@ def _ortho_pixelize(
mask = mask.transpose()
else:
raise NotImplementedError(
- "A pixelization routine has not been implemented for %s "
- "data objects" % str(type(data_source))
+ "A pixelization routine has not been implemented for "
+ f"{type(data_source)} data objects"
)
buff = buff.transpose()
mask = mask.transpose()
diff --git a/yt/utilities/cosmology.py b/yt/utilities/cosmology.py
index cb415bc766..691d86e1c4 100644
--- a/yt/utilities/cosmology.py
+++ b/yt/utilities/cosmology.py
@@ -95,7 +95,7 @@ def __init__(
new_unit,
my_u.base_value,
dimensions.length,
- "\\rm{%s}/(1+z)" % my_unit,
+ f"\\rm{{{my_unit}}}/(1+z)",
prefixable=True,
)
self.unit_registry = unit_registry
diff --git a/yt/utilities/on_demand_imports.py b/yt/utilities/on_demand_imports.py
index e77a482e34..839617f4a5 100644
--- a/yt/utilities/on_demand_imports.py
+++ b/yt/utilities/on_demand_imports.py
@@ -180,8 +180,8 @@ def __init__(self, pkg_name, exc: Optional[BaseException] = None):
# relatively short. Discussion related to this is in
# yt-project/yt#1966
self.error = ImportError(
- "This functionality requires the %s "
- "package to be installed." % self.pkg_name
+ f"This functionality requires the {self.pkg_name} "
+ "package to be installed."
)
else:
self.error = ImportError(
diff --git a/yt/utilities/particle_generator.py b/yt/utilities/particle_generator.py
index c41bd68a95..a0957e9b38 100644
--- a/yt/utilities/particle_generator.py
+++ b/yt/utilities/particle_generator.py
@@ -36,7 +36,7 @@ def __init__(self, ds, num_particles, field_list, ptype="io"):
except Exception as e:
raise KeyError(
"You must specify position fields: "
- + " ".join("particle_position_%s" % ax for ax in "xyz")
+ + " ".join(f"particle_position_{ax}" for ax in "xyz")
) from e
self.index_index = self.field_list.index((ptype, "particle_index"))
diff --git a/yt/visualization/_commons.py b/yt/visualization/_commons.py
index 49fdc33c15..99d4b919a2 100644
--- a/yt/visualization/_commons.py
+++ b/yt/visualization/_commons.py
@@ -258,8 +258,8 @@ def get_default_from_config(data_source, *, field, keys, defaults):
def _get_units_label(units: str) -> str:
if r"\frac" in units:
- return r"$\ \ \left(%s\right)$" % units
+ return rf"$\ \ \left({units}\right)$"
elif units:
- return r"$\ \ (%s)$" % units
+ return rf"$\ \ ({units})$"
else:
return ""
diff --git a/yt/visualization/fixed_resolution.py b/yt/visualization/fixed_resolution.py
index 05fdae3db8..d2da6a29e1 100644
--- a/yt/visualization/fixed_resolution.py
+++ b/yt/visualization/fixed_resolution.py
@@ -825,7 +825,7 @@ def _generate_image_and_mask(self, item) -> None:
norm = self.ds.quan(dpx * dpy, "code_length**2").in_base()
buff /= norm.v
units = data.units / norm.units
- info["label"] = "%s $\\rm{Density}$" % info["label"]
+ info["label"] += " $\\rm{Density}$"
else:
units = data.units
diff --git a/yt/visualization/image_writer.py b/yt/visualization/image_writer.py
index e9326d23cc..87bd9189e9 100644
--- a/yt/visualization/image_writer.py
+++ b/yt/visualization/image_writer.py
@@ -137,7 +137,7 @@ def write_bitmap(bitmap_array, filename, max_val=None, transpose=False):
if len(bitmap_array.shape) != 3 or bitmap_array.shape[-1] not in (3, 4):
raise RuntimeError(
"Expecting image array of shape (N,M,3) or "
- "(N,M,4), received %s" % str(bitmap_array.shape)
+ f"(N,M,4), received {str(bitmap_array.shape)}"
)
if bitmap_array.dtype != np.uint8:
diff --git a/yt/visualization/plot_modifications.py b/yt/visualization/plot_modifications.py
index fd90ca03cc..ca69ff6549 100644
--- a/yt/visualization/plot_modifications.py
+++ b/yt/visualization/plot_modifications.py
@@ -1244,9 +1244,9 @@ def __call__(self, plot):
y[i] = right_edge_y[n] - (12 * (yy1 - yy0) / ypix)
else:
raise RuntimeError(
- "Unrecognized id_loc value ('%s'). "
+ f"Unrecognized id_loc value ({self.id_loc!r}). "
"Allowed values are 'lower left', lower right', "
- "'upper left', and 'upper right'." % self.id_loc
+ "'upper left', and 'upper right'."
)
xi, yi = self._sanitize_xy_order(plot, x[i], y[i])
plot._axes.text(xi, yi, "%d" % block_ids[n], clip_on=True)
diff --git a/yt/visualization/plot_window.py b/yt/visualization/plot_window.py
index bb6cae9c9d..4534d7325c 100644
--- a/yt/visualization/plot_window.py
+++ b/yt/visualization/plot_window.py
@@ -1195,9 +1195,9 @@ def _setup_plots(self):
if colorbar_label is None:
colorbar_label = image.info["label"]
if getattr(self, "moment", 1) == 2:
- colorbar_label = "%s \\rm{Standard Deviation}" % colorbar_label
+ colorbar_label = f"{colorbar_label} \\rm{{Standard Deviation}}"
if hasattr(self, "projected"):
- colorbar_label = "$\\rm{Projected }$ %s" % colorbar_label
+ colorbar_label = f"$\\rm{{Projected }}$ {colorbar_label}"
if units is not None and units != "":
colorbar_label += _get_units_label(units)
diff --git a/yt/visualization/tests/test_save.py b/yt/visualization/tests/test_save.py
index 31ec9e230a..2612e8054d 100644
--- a/yt/visualization/tests/test_save.py
+++ b/yt/visualization/tests/test_save.py
@@ -76,8 +76,8 @@ def test_suffix_clashing(ext, simple_sliceplot, tmp_path):
target = (tmp_path / "myfile").with_suffix(ext)
expected_warning = re.compile(
- r"Received two valid image formats '%s' \(from filename\) "
- r"and 'png' \(from suffix\)\. The former is ignored\." % ext[1:]
+ rf"Received two valid image formats {ext.removeprefix('.')!r} "
+ r"\(from filename\) and 'png' \(from suffix\)\. The former is ignored\."
)
with pytest.warns(UserWarning, match=expected_warning):
diff --git a/yt/visualization/volume_rendering/lens.py b/yt/visualization/volume_rendering/lens.py
index 0e19b7e0a1..7335cebe34 100644
--- a/yt/visualization/volume_rendering/lens.py
+++ b/yt/visualization/volume_rendering/lens.py
@@ -137,10 +137,11 @@ def project_to_plane(self, camera, pos, res=None):
return px, py, dz
def __repr__(self):
- disp = ":\n\tlens_type:plane-parallel\n\tviewpoint:%s" % (
- self.viewpoint
+ return (
+ ":\n"
+ "\tlens_type:plane-parallel\n"
+ f"\tviewpoint:{self.viewpoint}"
)
- return disp
class PerspectiveLens(Lens):
diff --git a/yt/visualization/volume_rendering/render_source.py b/yt/visualization/volume_rendering/render_source.py
index 6943d04ed7..aff769543f 100644
--- a/yt/visualization/volume_rendering/render_source.py
+++ b/yt/visualization/volume_rendering/render_source.py
@@ -290,7 +290,7 @@ def transfer_function(self, value):
if not isinstance(value, valid_types):
raise RuntimeError(
"transfer_function not a valid type, "
- "received object of type %s" % type(value)
+ f"received object of type {type(value)}"
)
if isinstance(value, ProjectionTransferFunction):
self.sampler_type = "projection"
diff --git a/yt/visualization/volume_rendering/scene.py b/yt/visualization/volume_rendering/scene.py
index e45033cb14..ca8207cfbe 100644
--- a/yt/visualization/volume_rendering/scene.py
+++ b/yt/visualization/volume_rendering/scene.py
@@ -141,8 +141,8 @@ def add_source(self, render_source, keyname=None):
lens_str = str(self.camera.lens)
if "fisheye" in lens_str or "spherical" in lens_str:
raise NotImplementedError(
- "Line annotation sources are not supported for %s."
- % (type(self.camera.lens).__name__),
+ "Line annotation sources are not supported "
+ f"for {type(self.camera.lens).__name__}."
)
if isinstance(render_source, (LineSource, PointSource)):
diff --git a/yt/visualization/volume_rendering/utils.py b/yt/visualization/volume_rendering/utils.py
index d275f37b41..60340aca2a 100644
--- a/yt/visualization/volume_rendering/utils.py
+++ b/yt/visualization/volume_rendering/utils.py
@@ -26,7 +26,7 @@ def data_source_or_all(data_source):
raise RuntimeError(
"The data_source is not a valid 3D data container.\n"
"Expected an object of type YTSelectionContainer3D but received "
- "an object of type %s." % type(data_source)
+ f"an object of type {type(data_source)}."
)
return data_source