diff --git a/docs/userguide/extension.rst b/docs/userguide/extension.rst index e1e37b5db1..ef5e33f3a8 100644 --- a/docs/userguide/extension.rst +++ b/docs/userguide/extension.rst @@ -122,7 +122,7 @@ a non-``None`` value. Here's an example validation function:: """Verify that value is True, False, 0, or 1""" if bool(value) != value: raise SetupError( - "%r must be a boolean value (got %r)" % (attr,value) + f"{attr!r} must be a boolean value (got {value!r}" ) Your function should accept three arguments: the ``Distribution`` object, diff --git a/pkg_resources/__init__.py b/pkg_resources/__init__.py index 4e9b83d83d..8b88a6e379 100644 --- a/pkg_resources/__init__.py +++ b/pkg_resources/__init__.py @@ -205,7 +205,9 @@ def get_supported_platform(): m = macosVersionString.match(plat) if m is not None and sys.platform == "darwin": try: - plat = 'macosx-%s-%s' % ('.'.join(_macos_vers()[:2]), m.group(3)) + major_minor = '.'.join(_macos_vers()[:2]) + build = m.group(3) + plat = f'macosx-{major_minor}-{build}' except ValueError: # not macOS pass @@ -454,12 +456,8 @@ def get_build_platform(): if sys.platform == "darwin" and not plat.startswith('macosx-'): try: version = _macos_vers() - machine = os.uname()[4].replace(" ", "_") - return "macosx-%d.%d-%s" % ( - int(version[0]), - int(version[1]), - _macos_arch(machine), - ) + machine = _macos_arch(os.uname()[4].replace(" ", "_")) + return f"macosx-{version[0]}.{version[1]}-{machine}" except ValueError: # if someone is running a non-Mac darwin system, this will fall # through to the default implementation @@ -497,7 +495,7 @@ def compatible_platforms(provided: str | None, required: str | None) -> bool: provDarwin = darwinVersionString.match(provided) if provDarwin: dversion = int(provDarwin.group(1)) - macosversion = "%s.%s" % (reqMac.group(1), reqMac.group(2)) + macosversion = f"{reqMac.group(1)}.{reqMac.group(2)}" if ( dversion == 7 and macosversion >= "10.3" @@ -1321,7 +1319,7 @@ def __iadd__(self, other: Distribution | Environment) -> Self: for dist in other[project]: self.add(dist) else: - raise TypeError("Can't add %r to environment" % (other,)) + raise TypeError(f"Can't add {other!r} to environment") return self def __add__(self, other: Distribution | Environment) -> Self: @@ -1704,7 +1702,7 @@ def get_metadata(self, name: str) -> str: except UnicodeDecodeError as exc: # Include the path in the error message to simplify # troubleshooting, and without changing the exception type. - exc.reason += ' in {} file at path: {}'.format(name, path) + exc.reason += f' in {name} file at path: {path}' raise def get_metadata_lines(self, name: str) -> Iterator[str]: @@ -2023,7 +2021,7 @@ def _zipinfo_name(self, fspath): return '' if fspath.startswith(self.zip_pre): return fspath[len(self.zip_pre) :] - raise AssertionError("%s is not a subpath of %s" % (fspath, self.zip_pre)) + raise AssertionError(f"{fspath} is not a subpath of {self.zip_pre}") def _parts(self, zip_path): # Convert a zipfile subpath into an egg-relative path part list. @@ -2031,7 +2029,7 @@ def _parts(self, zip_path): fspath = self.zip_pre + zip_path if fspath.startswith(self.egg_root + os.sep): return fspath[len(self.egg_root) + 1 :].split(os.sep) - raise AssertionError("%s is not a subpath of %s" % (fspath, self.egg_root)) + raise AssertionError(f"{fspath} is not a subpath of {self.egg_root}") @property def zipinfo(self): @@ -2734,15 +2732,16 @@ def __init__( self.dist = dist def __str__(self) -> str: - s = "%s = %s" % (self.name, self.module_name) + s = f"{self.name} = {self.module_name}" if self.attrs: s += ':' + '.'.join(self.attrs) if self.extras: - s += ' [%s]' % ','.join(self.extras) + extras = ','.join(self.extras) + s += f' [{extras}]' return s def __repr__(self) -> str: - return "EntryPoint.parse(%r)" % str(self) + return f"EntryPoint.parse({str(self)!r})" @overload def load( @@ -3054,9 +3053,7 @@ def version(self): version = self._get_version() if version is None: path = self._get_metadata_path_for_display(self.PKG_INFO) - msg = ("Missing 'Version:' header and/or {} file at path: {}").format( - self.PKG_INFO, path - ) + msg = f"Missing 'Version:' header and/or {self.PKG_INFO} file at path: {path}" raise ValueError(msg, self) from e return version @@ -3112,9 +3109,7 @@ def requires(self, extras: Iterable[str] = ()) -> list[Requirement]: try: deps.extend(dm[safe_extra(ext)]) except KeyError as e: - raise UnknownExtra( - "%s has no such extra feature %r" % (self, ext) - ) from e + raise UnknownExtra(f"{self} has no such extra feature {ext!r}") from e return deps def _get_metadata_path_for_display(self, name): @@ -3155,11 +3150,7 @@ def activate(self, path: list[str] | None = None, replace: bool = False) -> None def egg_name(self): """Return what this distribution's standard .egg filename should be""" - filename = "%s-%s-py%s" % ( - to_filename(self.project_name), - to_filename(self.version), - self.py_version or PY_MAJOR, - ) + filename = f"{to_filename(self.project_name)}-{to_filename(self.version)}-py{self.py_version or PY_MAJOR}" if self.platform: filename += '-' + self.platform @@ -3167,7 +3158,7 @@ def egg_name(self): def __repr__(self) -> str: if self.location: - return "%s (%s)" % (self, self.location) + return f"{self} ({self.location})" else: return str(self) @@ -3177,7 +3168,7 @@ def __str__(self) -> str: except ValueError: version = None version = version or "[unknown version]" - return "%s %s" % (self.project_name, version) + return f"{self.project_name} {version}" def __getattr__(self, attr: str): """Delegate all unrecognized public attributes to .metadata provider""" @@ -3205,9 +3196,9 @@ def from_filename( def as_requirement(self): """Return a ``Requirement`` that matches this distribution exactly""" if isinstance(self.parsed_version, packaging.version.Version): - spec = "%s==%s" % (self.project_name, self.parsed_version) + spec = f"{self.project_name}=={self.parsed_version}" else: - spec = "%s===%s" % (self.project_name, self.parsed_version) + spec = f"{self.project_name}==={self.parsed_version}" return Requirement.parse(spec) @@ -3215,7 +3206,7 @@ def load_entry_point(self, group: str, name: str) -> _ResolvedEntryPoint: """Return the `name` entry point of `group` or raise ImportError""" ep = self.get_entry_info(group, name) if ep is None: - raise ImportError("Entry point %r not found" % ((group, name),)) + raise ImportError(f"Entry point {(group, name)!r} not found") return ep.load() @overload @@ -3332,8 +3323,8 @@ def check_version_conflict(self): ): continue issue_warning( - "Module %s was already imported from %s, but %s is being added" - " to sys.path" % (modname, fn, self.location), + f"Module {modname} was already imported from {fn}, " + f"but {self.location} is being added to sys.path", ) def has_version(self): @@ -3517,7 +3508,7 @@ def __hash__(self) -> int: return self.__hash def __repr__(self) -> str: - return "Requirement.parse(%r)" % str(self) + return f"Requirement.parse({str(self)!r})" @staticmethod def parse(s: str | Iterable[str]) -> Requirement: diff --git a/pkg_resources/tests/test_pkg_resources.py b/pkg_resources/tests/test_pkg_resources.py index 18adb3c9d2..d7670cdfba 100644 --- a/pkg_resources/tests/test_pkg_resources.py +++ b/pkg_resources/tests/test_pkg_resources.py @@ -214,8 +214,8 @@ def test_get_metadata__bad_utf8(tmpdir): "codec can't decode byte 0xe9 in position 1: " 'invalid continuation byte in METADATA file at path: ' ) - assert expected in actual, 'actual: {}'.format(actual) - assert actual.endswith(metadata_path), 'actual: {}'.format(actual) + assert expected in actual, f'actual: {actual}' + assert actual.endswith(metadata_path), f'actual: {actual}' def make_distribution_no_version(tmpdir, basename): @@ -252,11 +252,11 @@ def test_distribution_version_missing( """ Test Distribution.version when the "Version" header is missing. """ - basename = 'foo.{}'.format(suffix) + basename = f'foo.{suffix}' dist, dist_dir = make_distribution_no_version(tmpdir, basename) - expected_text = ("Missing 'Version:' header and/or {} file at path: ").format( - expected_filename + expected_text = ( + f"Missing 'Version:' header and/or {expected_filename} file at path: " ) metadata_path = os.path.join(dist_dir, expected_filename) diff --git a/ruff.toml b/ruff.toml index b55b4e8067..7218d7d363 100644 --- a/ruff.toml +++ b/ruff.toml @@ -24,9 +24,7 @@ ignore = [ "TRY003", # raise-vanilla-args, avoid multitude of exception classes "TRY301", # raise-within-try, it's handy "UP015", # redundant-open-modes, explicit is preferred - "UP030", # temporarily disabled - "UP031", # temporarily disabled - "UP032", # temporarily disabled + "UP027", # deprecated https://github.com/astral-sh/ruff/pull/12843 "UP038", # Using `X | Y` in `isinstance` call is slower and more verbose https://github.com/astral-sh/ruff/issues/7871 # Only enforcing return type annotations for public functions "ANN202", # missing-return-type-private-function diff --git a/setuptools/__init__.py b/setuptools/__init__.py index 3a1cc58aa3..fde37b4516 100644 --- a/setuptools/__init__.py +++ b/setuptools/__init__.py @@ -183,9 +183,7 @@ def _ensure_stringlike(self, option, what, default=None): setattr(self, option, default) return default elif not isinstance(val, str): - raise DistutilsOptionError( - "'%s' must be a %s (got `%s`)" % (option, what, val) - ) + raise DistutilsOptionError(f"'{option}' must be a {what} (got `{val}`)") return val def ensure_string_list(self, option): @@ -212,7 +210,7 @@ def ensure_string_list(self, option): ok = False if not ok: raise DistutilsOptionError( - "'%s' must be a list of strings (got %r)" % (option, val) + f"'{option}' must be a list of strings (got {val!r})" ) @overload diff --git a/setuptools/_core_metadata.py b/setuptools/_core_metadata.py index 2e9c48a77b..642b80df31 100644 --- a/setuptools/_core_metadata.py +++ b/setuptools/_core_metadata.py @@ -150,7 +150,7 @@ def write_pkg_file(self, file): # noqa: C901 # is too complex (14) # FIXME version = self.get_metadata_version() def write_field(key, value): - file.write("%s: %s\n" % (key, value)) + file.write(f"{key}: {value}\n") write_field('Metadata-Version', str(version)) write_field('Name', self.get_name()) @@ -178,8 +178,8 @@ def write_field(key, value): if license: write_field('License', rfc822_escape(license)) - for project_url in self.project_urls.items(): - write_field('Project-URL', '%s, %s' % project_url) + for label, url in self.project_urls.items(): + write_field('Project-URL', f'{label}, {url}') keywords = ','.join(self.get_keywords()) if keywords: @@ -209,7 +209,7 @@ def write_field(key, value): long_description = self.get_long_description() if long_description: - file.write("\n%s" % long_description) + file.write(f"\n{long_description}") if not long_description.endswith("\n"): file.write("\n") diff --git a/setuptools/_imp.py b/setuptools/_imp.py index bddbf6a683..f1d9f29218 100644 --- a/setuptools/_imp.py +++ b/setuptools/_imp.py @@ -29,7 +29,7 @@ def find_module(module, paths=None): """Just like 'imp.find_module()', but with package support""" spec = find_spec(module, paths) if spec is None: - raise ImportError("Can't find %s" % module) + raise ImportError(f"Can't find {module}") if not spec.has_location and hasattr(spec, 'submodule_search_locations'): spec = importlib.util.spec_from_loader('__init__.py', spec.loader) @@ -76,12 +76,12 @@ def find_module(module, paths=None): def get_frozen_object(module, paths=None): spec = find_spec(module, paths) if not spec: - raise ImportError("Can't find %s" % module) + raise ImportError(f"Can't find {module}") return spec.loader.get_code(module) def get_module(module, paths, info): spec = find_spec(module, paths) if not spec: - raise ImportError("Can't find %s" % module) + raise ImportError(f"Can't find {module}") return module_from_spec(spec) diff --git a/setuptools/archive_util.py b/setuptools/archive_util.py index e4acd75f9b..a957f324e2 100644 --- a/setuptools/archive_util.py +++ b/setuptools/archive_util.py @@ -60,7 +60,7 @@ def unpack_archive(filename, extract_dir, progress_filter=default_filter, driver else: return else: - raise UnrecognizedFormat("Not a recognized archive type: %s" % filename) + raise UnrecognizedFormat(f"Not a recognized archive type: {filename}") def unpack_directory(filename, extract_dir, progress_filter=default_filter): @@ -69,7 +69,7 @@ def unpack_directory(filename, extract_dir, progress_filter=default_filter): Raises ``UnrecognizedFormat`` if `filename` is not a directory """ if not os.path.isdir(filename): - raise UnrecognizedFormat("%s is not a directory" % filename) + raise UnrecognizedFormat(f"{filename} is not a directory") paths = { filename: ('', extract_dir), @@ -99,7 +99,7 @@ def unpack_zipfile(filename, extract_dir, progress_filter=default_filter): """ if not zipfile.is_zipfile(filename): - raise UnrecognizedFormat("%s is not a zip file" % (filename,)) + raise UnrecognizedFormat(f"{filename} is not a zip file") with zipfile.ZipFile(filename) as z: _unpack_zipfile_obj(z, extract_dir, progress_filter) @@ -196,7 +196,7 @@ def unpack_tarfile(filename, extract_dir, progress_filter=default_filter): tarobj = tarfile.open(filename) except tarfile.TarError as e: raise UnrecognizedFormat( - "%s is not a compressed or uncompressed tar file" % (filename,) + f"{filename} is not a compressed or uncompressed tar file" ) from e for member, final_dst in _iter_open_tar( diff --git a/setuptools/command/alias.py b/setuptools/command/alias.py index 4eed652381..6bd5717e05 100644 --- a/setuptools/command/alias.py +++ b/setuptools/command/alias.py @@ -56,7 +56,7 @@ def run(self): print("setup.py alias", format_alias(alias, aliases)) return else: - print("No alias definition found for %r" % alias) + print(f"No alias definition found for {alias!r}") return else: alias = self.args[0] @@ -74,5 +74,5 @@ def format_alias(name, aliases): elif source == config_file('local'): source = '' else: - source = '--filename=%r' % source + source = f'--filename={source!r}' return source + name + ' ' + command diff --git a/setuptools/command/bdist_egg.py b/setuptools/command/bdist_egg.py index f3b7150208..cc5ed59a75 100644 --- a/setuptools/command/bdist_egg.py +++ b/setuptools/command/bdist_egg.py @@ -60,7 +60,7 @@ def __bootstrap__(): class bdist_egg(Command): - description = "create an \"egg\" distribution" + description = 'create an "egg" distribution' user_options = [ ('bdist-dir=', 'b', "temporary directory for creating the distribution"), @@ -254,7 +254,7 @@ def zap_pyfiles(self): pattern = r'(?P.+)\.(?P[^.]+)\.pyc' m = re.match(pattern, name) path_new = os.path.join(base, os.pardir, m.group('name') + '.pyc') - log.info("Renaming file from [%s] to [%s]" % (path_old, path_new)) + log.info(f"Renaming file from [{path_old}] to [{path_new}]") try: os.remove(path_new) except OSError: diff --git a/setuptools/command/bdist_wheel.py b/setuptools/command/bdist_wheel.py index fa97976fef..b7235c0336 100644 --- a/setuptools/command/bdist_wheel.py +++ b/setuptools/command/bdist_wheel.py @@ -210,9 +210,7 @@ class bdist_wheel(Command): ( "compression=", None, - "zipfile compression (one of: {}) [default: 'deflated']".format( - ", ".join(supported_compressions) - ), + f"zipfile compression (one of: {', '.join(supported_compressions)}) [default: 'deflated']", ), ( "python-tag=", diff --git a/setuptools/command/build_clib.py b/setuptools/command/build_clib.py index d532762ebe..372c8ca3cf 100644 --- a/setuptools/command/build_clib.py +++ b/setuptools/command/build_clib.py @@ -36,9 +36,9 @@ def build_libraries(self, libraries): sources = build_info.get('sources') if sources is None or not isinstance(sources, (list, tuple)): raise DistutilsSetupError( - "in 'libraries' option (library '%s'), " + f"in 'libraries' option (library '{lib_name}'), " "'sources' must be present and must be " - "a list of source filenames" % lib_name + "a list of source filenames" ) sources = sorted(list(sources)) @@ -50,9 +50,9 @@ def build_libraries(self, libraries): obj_deps = build_info.get('obj_deps', dict()) if not isinstance(obj_deps, dict): raise DistutilsSetupError( - "in 'libraries' option (library '%s'), " + f"in 'libraries' option (library '{lib_name}'), " "'obj_deps' must be a dictionary of " - "type 'source: list'" % lib_name + "type 'source: list'" ) dependencies = [] @@ -61,9 +61,9 @@ def build_libraries(self, libraries): global_deps = obj_deps.get('', list()) if not isinstance(global_deps, (list, tuple)): raise DistutilsSetupError( - "in 'libraries' option (library '%s'), " + f"in 'libraries' option (library '{lib_name}'), " "'obj_deps' must be a dictionary of " - "type 'source: list'" % lib_name + "type 'source: list'" ) # Build the list to be used by newer_pairwise_group @@ -74,9 +74,9 @@ def build_libraries(self, libraries): extra_deps = obj_deps.get(source, list()) if not isinstance(extra_deps, (list, tuple)): raise DistutilsSetupError( - "in 'libraries' option (library '%s'), " + f"in 'libraries' option (library '{lib_name}'), " "'obj_deps' must be a dictionary of " - "type 'source: list'" % lib_name + "type 'source: list'" ) src_deps.extend(extra_deps) dependencies.append(src_deps) diff --git a/setuptools/command/build_ext.py b/setuptools/command/build_ext.py index e2a88ce218..1bc82f5ce3 100644 --- a/setuptools/command/build_ext.py +++ b/setuptools/command/build_ext.py @@ -167,7 +167,7 @@ def get_ext_filename(self, fullname: str) -> str: if not isinstance(ext_suffix, str): raise OSError( "Configuration variable EXT_SUFFIX not found for this platform " - + "and environment variable SETUPTOOLS_EXT_SUFFIX is missing" + "and environment variable SETUPTOOLS_EXT_SUFFIX is missing" ) so_ext = ext_suffix @@ -359,7 +359,7 @@ def _write_stub_file(self, stub_file: str, ext: Extension, compile=False): " global __bootstrap__, __file__, __loader__", " import sys, os, pkg_resources, importlib.util" + if_dl(", dl"), " __file__ = pkg_resources.resource_filename" - "(__name__,%r)" % os.path.basename(ext._file_name), + f"(__name__,{os.path.basename(ext._file_name)!r})", " del __bootstrap__", " if '__loader__' in globals():", " del __loader__", diff --git a/setuptools/command/build_py.py b/setuptools/command/build_py.py index 584d2c15ac..eb09ef44cf 100644 --- a/setuptools/command/build_py.py +++ b/setuptools/command/build_py.py @@ -263,10 +263,10 @@ def check_package(self, package, package_dir): contents = f.read() if b'declare_namespace' not in contents: raise distutils.errors.DistutilsError( - "Namespace package problem: %s is a namespace package, but " + f"Namespace package problem: {package} is a namespace package, but " "its\n__init__.py does not call declare_namespace()! Please " 'fix it.\n(See the setuptools manual under ' - '"Namespace Packages" for details.)\n"' % (package,) + '"Namespace Packages" for details.)\n"' ) return init_py diff --git a/setuptools/command/dist_info.py b/setuptools/command/dist_info.py index 1db3fbf6bd..c92836de73 100644 --- a/setuptools/command/dist_info.py +++ b/setuptools/command/dist_info.py @@ -94,7 +94,7 @@ def run(self): egg_info_dir = self.egg_info.egg_info assert os.path.isdir(egg_info_dir), ".egg-info dir should have been created" - log.info("creating '{}'".format(os.path.abspath(self.dist_info_dir))) + log.info(f"creating '{os.path.abspath(self.dist_info_dir)}'") bdist_wheel = self.get_finalized_command('bdist_wheel') # TODO: if bdist_wheel if merged into setuptools, just add "keep_egg_info" there diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py index 25a9eee937..1cdbe1a0ee 100644 --- a/setuptools/command/easy_install.py +++ b/setuptools/command/easy_install.py @@ -133,8 +133,8 @@ class easy_install(Command): ( 'optimize=', 'O', - "also compile with optimization: -O1 for \"python -O\", " - "-O2 for \"python -OO\", and -O0 to disable [default: -O0]", + 'also compile with optimization: -O1 for "python -O", ' + '-O2 for "python -OO", and -O0 to disable [default: -O0]', ), ('record=', None, "filename in which to record list of installed files"), ('always-unzip', 'Z', "don't install as a zipfile, no matter what"), @@ -149,7 +149,7 @@ class easy_install(Command): None, "Don't load find-links defined in packages being installed", ), - ('user', None, "install in user site-package '%s'" % site.USER_SITE), + ('user', None, f"install in user site-package '{site.USER_SITE}'"), ] boolean_options = [ 'zip-ok', @@ -448,7 +448,7 @@ def run(self, show_deprecation=True): self.execute( file_util.write_file, (self.record, outputs), - "writing list of installed files to '%s'" % self.record, + f"writing list of installed files to '{self.record}'", ) self.warn_deprecated_options() finally: @@ -463,7 +463,7 @@ def pseudo_tempname(self): pid = os.getpid() except Exception: pid = random.randint(0, sys.maxsize) - return os.path.join(self.install_dir, "test-easy-install-%s" % pid) + return os.path.join(self.install_dir, f"test-easy-install-{pid}") def warn_deprecated_options(self): pass @@ -651,8 +651,8 @@ def add_output(self, path): def not_editable(self, spec): if self.editable: raise DistutilsArgError( - "Invalid argument %r: you can't use filenames or URLs " - "with --editable (except via the --find-links option)." % (spec,) + f"Invalid argument {spec!r}: you can't use filenames or URLs " + "with --editable (except via the --find-links option)." ) def check_editable(self, spec): @@ -661,8 +661,7 @@ def check_editable(self, spec): if os.path.exists(os.path.join(self.build_directory, spec.key)): raise DistutilsArgError( - "%r already exists in %s; can't do a checkout there" - % (spec.key, self.build_directory) + f"{spec.key!r} already exists in {self.build_directory}; can't do a checkout there" ) @contextlib.contextmanager @@ -700,7 +699,7 @@ def easy_install(self, spec, deps=False): self.local_index, ) if dist is None: - msg = "Could not find suitable distribution for %r" % spec + msg = f"Could not find suitable distribution for {spec!r}" if self.always_copy: msg += " (--always-copy skips system and development eggs)" raise DistutilsError(msg) @@ -917,12 +916,11 @@ def install_eggs(self, spec, dist_filename, tmpdir): setups = glob(os.path.join(setup_base, '*', 'setup.py')) if not setups: raise DistutilsError( - "Couldn't find a setup script in %s" - % os.path.abspath(dist_filename) + f"Couldn't find a setup script in {os.path.abspath(dist_filename)}" ) if len(setups) > 1: raise DistutilsError( - "Multiple setup scripts in %s" % os.path.abspath(dist_filename) + f"Multiple setup scripts in {os.path.abspath(dist_filename)}" ) setup_script = setups[0] @@ -1000,7 +998,7 @@ def install_exe(self, dist_filename, tmpdir): cfg = extract_wininst_cfg(dist_filename) if cfg is None: raise DistutilsError( - "%s is not a valid distutils Windows .exe" % dist_filename + f"{dist_filename} is not a valid distutils Windows .exe" ) # Create a dummy distribution object until we build the real distro dist = Distribution( @@ -1026,7 +1024,8 @@ def install_exe(self, dist_filename, tmpdir): f.write('Metadata-Version: 1.0\n') for k, v in cfg.items('metadata'): if k != 'target_version': - f.write('%s: %s\n' % (k.replace('_', '-').title(), v)) + k = k.replace('_', '-').title() + f.write(f'{k}: {v}\n') script_dir = os.path.join(_egg_info, 'scripts') # delete entry-point scripts to avoid duping self.delete_blockers([ @@ -1114,8 +1113,9 @@ def install_wheel(self, wheel_path, tmpdir): self.execute( wheel.install_as_egg, (destination,), - ("Installing %s to %s") - % (os.path.basename(wheel_path), os.path.dirname(destination)), + ( + f"Installing {os.path.basename(wheel_path)} to {os.path.dirname(destination)}" + ), ) finally: update_dist_caches(destination, fix_zipimporter_caches=False) @@ -1191,7 +1191,7 @@ def run_setup(self, setup_script, setup_base, args): try: run_setup(setup_script, args) except SystemExit as v: - raise DistutilsError("Setup script exited with %s" % (v.args[0],)) from v + raise DistutilsError(f"Setup script exited with {v.args[0]}") from v def build_and_install(self, setup_script, setup_base): args = ['bdist_egg', '--dist-dir'] @@ -1374,7 +1374,7 @@ def create_home_path(self): home = convert_path(os.path.expanduser("~")) for path in only_strs(self.config_vars.values()): if path.startswith(home) and not os.path.isdir(path): - self.debug_print("os.makedirs('%s', 0o700)" % path) + self.debug_print(f"os.makedirs('{path}', 0o700)") os.makedirs(path, 0o700) INSTALL_SCHEMES = dict( @@ -1599,7 +1599,7 @@ def get_exe_prefixes(exe_filename): for pth in yield_lines(contents): pth = pth.strip().replace('\\', '/') if not pth.startswith('import'): - prefixes.append((('%s/%s/' % (parts[0], pth)), '')) + prefixes.append(((f'{parts[0]}/{pth}/'), '')) finally: z.close() prefixes = [(x.lower(), y) for x, y in prefixes] @@ -2324,7 +2324,7 @@ def get_win_launcher(type): Returns the executable as a byte string. """ - launcher_fn = '%s.exe' % type + launcher_fn = f'{type}.exe' if is_64bit(): if get_platform() == "win-arm64": launcher_fn = launcher_fn.replace(".", "-arm64.") diff --git a/setuptools/command/egg_info.py b/setuptools/command/egg_info.py index 280eb5e807..888f0abf5e 100644 --- a/setuptools/command/egg_info.py +++ b/setuptools/command/egg_info.py @@ -48,7 +48,7 @@ def translate_pattern(glob): # noqa: C901 # is too complex (14) # FIXME chunks = glob.split(os.path.sep) sep = re.escape(os.sep) - valid_char = '[^%s]' % (sep,) + valid_char = f'[^{sep}]' for c, chunk in enumerate(chunks): last_chunk = c == len(chunks) - 1 @@ -60,7 +60,7 @@ def translate_pattern(glob): # noqa: C901 # is too complex (14) # FIXME pat += '.*' else: # Match '(name/)*' - pat += '(?:%s+%s)*' % (valid_char, sep) + pat += f'(?:{valid_char}+{sep})*' continue # Break here as the whole path component has been handled # Find any special characters in the remainder @@ -102,7 +102,7 @@ def translate_pattern(glob): # noqa: C901 # is too complex (14) # FIXME inner = inner[1:] char_class += re.escape(inner) - pat += '[%s]' % (char_class,) + pat += f'[{char_class}]' # Skip to the end ] i = inner_i @@ -233,8 +233,7 @@ def finalize_options(self): packaging.requirements.Requirement(spec % (self.egg_name, self.egg_version)) except ValueError as e: raise distutils.errors.DistutilsOptionError( - "Invalid distribution name or version syntax: %s-%s" - % (self.egg_name, self.egg_version) + f"Invalid distribution name or version syntax: {self.egg_name}-{self.egg_version}" ) from e if self.egg_base is None: @@ -498,7 +497,7 @@ def _safe_path(self, path): # To avoid accidental trans-codings errors, first to unicode u_path = unicode_utils.filesys_decode(path) if u_path is None: - log.warn("'%s' in unexpected encoding -- skipping" % path) + log.warn(f"'{path}' in unexpected encoding -- skipping") return False # Must ensure utf-8 encodability @@ -560,7 +559,7 @@ def write_manifest(self): # Now _repairs should encodability, but not unicode files = [self._manifest_normalize(f) for f in self.filelist.files] - msg = "writing manifest file '%s'" % self.manifest + msg = f"writing manifest file '{self.manifest}'" self.execute(write_file, (self.manifest, files), msg) def warn(self, msg): diff --git a/setuptools/command/install_egg_info.py b/setuptools/command/install_egg_info.py index be47254f00..c97ceb34b2 100644 --- a/setuptools/command/install_egg_info.py +++ b/setuptools/command/install_egg_info.py @@ -36,7 +36,7 @@ def run(self): self.execute(os.unlink, (self.target,), "Removing " + self.target) if not self.dry_run: ensure_directory(self.target) - self.execute(self.copytree, (), "Copying %s to %s" % (self.source, self.target)) + self.execute(self.copytree, (), f"Copying {self.source} to {self.target}") self.install_namespaces() def get_outputs(self): diff --git a/setuptools/command/sdist.py b/setuptools/command/sdist.py index fa9a2c4d81..38d7e53cdd 100644 --- a/setuptools/command/sdist.py +++ b/setuptools/command/sdist.py @@ -52,7 +52,7 @@ class sdist(orig.sdist): negative_opt: dict[str, str] = {} README_EXTENSIONS = ['', '.rst', '.txt', '.md'] - READMES = tuple('README{0}'.format(ext) for ext in README_EXTENSIONS) + READMES = tuple(f'README{ext}' for ext in README_EXTENSIONS) def run(self): self.run_command('egg_info') @@ -206,7 +206,7 @@ def read_manifest(self): try: line = line.decode('UTF-8') except UnicodeDecodeError: - log.warn("%r not UTF-8 decodable -- skipping" % line) + log.warn(f"{line!r} not UTF-8 decodable -- skipping") continue # ignore comments and blank lines line = line.strip() diff --git a/setuptools/command/setopt.py b/setuptools/command/setopt.py index e351af22f0..9d4c04dca6 100644 --- a/setuptools/command/setopt.py +++ b/setuptools/command/setopt.py @@ -23,7 +23,7 @@ def config_file(kind="local"): return os.path.join(os.path.dirname(distutils.__file__), 'distutils.cfg') if kind == 'user': dot = os.name == 'posix' and '.' or '' - return os.path.expanduser(convert_path("~/%spydistutils.cfg" % dot)) + return os.path.expanduser(convert_path(f"~/{dot}pydistutils.cfg")) raise ValueError("config_file() type must be 'local', 'global', or 'user'", kind) diff --git a/setuptools/config/expand.py b/setuptools/config/expand.py index e11bcf9b42..0ea0008c8f 100644 --- a/setuptools/config/expand.py +++ b/setuptools/config/expand.py @@ -326,7 +326,7 @@ def version(value: Callable | Iterable[str | int] | str) -> str: return _value if hasattr(_value, '__iter__'): return '.'.join(map(str, _value)) - return '%s' % _value + return f'{_value}' def canonic_package_data(package_data: dict) -> dict: diff --git a/setuptools/config/setupcfg.py b/setuptools/config/setupcfg.py index 54469f74a3..71749364e7 100644 --- a/setuptools/config/setupcfg.py +++ b/setuptools/config/setupcfg.py @@ -277,7 +277,7 @@ def _section_options( def parsers(self): """Metadata item name to parser function mapping.""" raise NotImplementedError( - '%s must provide .parsers property' % self.__class__.__name__ + f'{self.__class__.__name__} must provide .parsers property' ) def __setitem__(self, option_name, value) -> None: @@ -301,7 +301,7 @@ def __setitem__(self, option_name, value) -> None: return simple_setter = functools.partial(target_obj.__setattr__, option_name) - setter = getattr(target_obj, 'set_%s' % option_name, simple_setter) + setter = getattr(target_obj, f'set_{option_name}', simple_setter) setter(parsed) self.set_options.append(option_name) @@ -369,8 +369,8 @@ def parser(value): exclude_directive = 'file:' if value.startswith(exclude_directive): raise ValueError( - 'Only strings are accepted for the {0} field, ' - 'files are not accepted'.format(key) + f'Only strings are accepted for the {key} field, ' + 'files are not accepted' ) return value @@ -488,12 +488,12 @@ def parse(self) -> None: for section_name, section_options in self.sections.items(): method_postfix = '' if section_name: # [section.option] variant - method_postfix = '_%s' % section_name + method_postfix = f'_{section_name}' section_parser_method: Callable | None = getattr( self, # Dots in section names are translated into dunderscores. - ('parse_section%s' % method_postfix).replace('.', '__'), + (f'parse_section{method_postfix}').replace('.', '__'), None, ) diff --git a/setuptools/depends.py b/setuptools/depends.py index 9398b95331..bdf08889f4 100644 --- a/setuptools/depends.py +++ b/setuptools/depends.py @@ -31,7 +31,7 @@ def __init__( def full_name(self): """Return full package/distribution name, w/version""" if self.requested_version is not None: - return '%s-%s' % (self.name, self.requested_version) + return f'{self.name}-{self.requested_version}' return self.name def version_ok(self, version): diff --git a/setuptools/dist.py b/setuptools/dist.py index 68f877decd..606dbd43ec 100644 --- a/setuptools/dist.py +++ b/setuptools/dist.py @@ -47,7 +47,7 @@ def check_importable(dist, attr, value): assert not ep.extras except (TypeError, ValueError, AttributeError, AssertionError) as e: raise DistutilsSetupError( - "%r must be importable 'module:attrs' string (got %r)" % (attr, value) + f"{attr!r} must be importable 'module:attrs' string (got {value!r})" ) from e @@ -61,7 +61,7 @@ def assert_string_list(dist, attr, value): assert ''.join(value) != value except (TypeError, ValueError, AttributeError, AssertionError) as e: raise DistutilsSetupError( - "%r must be a list of strings (got %r)" % (attr, value) + f"{attr!r} must be a list of strings (got {value!r})" ) from e @@ -72,8 +72,7 @@ def check_nsp(dist, attr, value): for nsp in ns_packages: if not dist.has_contents_for(nsp): raise DistutilsSetupError( - "Distribution contains no modules or packages for " - + "namespace package %r" % nsp + f"Distribution contains no modules or packages for namespace package {nsp!r}" ) parent, sep, child = nsp.rpartition('.') if parent and parent not in ns_packages: @@ -126,8 +125,7 @@ def _check_marker(marker): def assert_bool(dist, attr, value): """Verify that value is True, False, 0, or 1""" if bool(value) != value: - tmpl = "{attr!r} must be a boolean value (got {value!r})" - raise DistutilsSetupError(tmpl.format(attr=attr, value=value)) + raise DistutilsSetupError(f"{attr!r} must be a boolean value (got {value!r})") def invalid_unless_false(dist, attr, value): @@ -145,11 +143,10 @@ def check_requirements(dist, attr, value): if isinstance(value, (dict, set)): raise TypeError("Unordered types are not allowed") except (TypeError, ValueError) as error: - tmpl = ( - "{attr!r} must be a string or list of strings " - "containing valid project/version requirement specifiers; {error}" - ) - raise DistutilsSetupError(tmpl.format(attr=attr, error=error)) from error + raise DistutilsSetupError( + f"{attr!r} must be a string or list of strings " + f"containing valid project/version requirement specifiers; {error}" + ) from error def check_specifier(dist, attr, value): @@ -157,8 +154,9 @@ def check_specifier(dist, attr, value): try: SpecifierSet(value) except (InvalidSpecifier, AttributeError) as error: - tmpl = "{attr!r} must be a string containing valid version specifiers; {error}" - raise DistutilsSetupError(tmpl.format(attr=attr, error=error)) from error + raise DistutilsSetupError( + f"{attr!r} must be a string containing valid version specifiers; {error}" + ) from error def check_entry_points(dist, attr, value): @@ -173,15 +171,15 @@ def check_package_data(dist, attr, value): """Verify that value is a dictionary of package names to glob lists""" if not isinstance(value, dict): raise DistutilsSetupError( - "{!r} must be a dictionary mapping package names to lists of " - "string wildcard patterns".format(attr) + f"{attr!r} must be a dictionary mapping package names to lists of " + "string wildcard patterns" ) for k, v in value.items(): if not isinstance(k, str): raise DistutilsSetupError( - "keys of {!r} dict must be strings (got {!r})".format(attr, k) + f"keys of {attr!r} dict must be strings (got {k!r})" ) - assert_string_list(dist, 'values of {!r} dict'.format(attr), v) + assert_string_list(dist, f'values of {attr!r} dict', v) def check_packages(dist, attr, value): @@ -552,10 +550,10 @@ def _set_command_options(self, command_obj, option_dict=None): # noqa: C901 option_dict = self.get_option_dict(command_name) if DEBUG: - self.announce(" setting options for '%s' command:" % command_name) + self.announce(f" setting options for '{command_name}' command:") for option, (source, value) in option_dict.items(): if DEBUG: - self.announce(" %s = %s (from %s)" % (option, value, source)) + self.announce(f" {option} = {value} (from {source})") try: bool_opts = [translate_longopt(o) for o in command_obj.boolean_options] except AttributeError: @@ -575,8 +573,7 @@ def _set_command_options(self, command_obj, option_dict=None): # noqa: C901 setattr(command_obj, option, value) else: raise DistutilsOptionError( - "error in %s: command '%s' has no such option '%s'" - % (source, command_name, option) + f"error in {source}: command '{command_name}' has no such option '{option}'" ) except ValueError as e: raise DistutilsOptionError(e) from e @@ -771,12 +768,12 @@ def _exclude_misc(self, name, value): """Handle 'exclude()' for list/tuple attrs without a special handler""" if not isinstance(value, sequence): raise DistutilsSetupError( - "%s: setting must be a list or tuple (%r)" % (name, value) + f"{name}: setting must be a list or tuple ({value!r})" ) try: old = getattr(self, name) except AttributeError as e: - raise DistutilsSetupError("%s: No such distribution setting" % name) from e + raise DistutilsSetupError(f"{name}: No such distribution setting") from e if old is not None and not isinstance(old, sequence): raise DistutilsSetupError( name + ": this setting cannot be changed via include/exclude" @@ -788,11 +785,11 @@ def _include_misc(self, name, value): """Handle 'include()' for list/tuple attrs without a special handler""" if not isinstance(value, sequence): - raise DistutilsSetupError("%s: setting must be a list (%r)" % (name, value)) + raise DistutilsSetupError(f"{name}: setting must be a list ({value!r})") try: old = getattr(self, name) except AttributeError as e: - raise DistutilsSetupError("%s: No such distribution setting" % name) from e + raise DistutilsSetupError(f"{name}: No such distribution setting") from e if old is None: setattr(self, name, value) elif not isinstance(old, sequence): @@ -829,7 +826,7 @@ def exclude(self, **attrs): def _exclude_packages(self, packages): if not isinstance(packages, sequence): raise DistutilsSetupError( - "packages: setting must be a list or tuple (%r)" % (packages,) + f"packages: setting must be a list or tuple ({packages!r})" ) list(map(self.exclude_package, packages)) diff --git a/setuptools/monkey.py b/setuptools/monkey.py index 3b6eefb4dd..c00fe0fb21 100644 --- a/setuptools/monkey.py +++ b/setuptools/monkey.py @@ -64,7 +64,7 @@ def get_unpatched_class(cls: type[_T]) -> type[_T]: ) base = next(external_bases) if not base.__module__.startswith('distutils'): - msg = "distutils has already been patched by %r" % cls + msg = f"distutils has already been patched by {cls!r}" raise AssertionError(msg) return base diff --git a/setuptools/msvc.py b/setuptools/msvc.py index de4b05f928..5ceca6a09e 100644 --- a/setuptools/msvc.py +++ b/setuptools/msvc.py @@ -105,7 +105,7 @@ def current_dir(self, hidex86=False, x64=False): if (self.current_cpu == 'x86' and hidex86) else r'\x64' if (self.current_cpu == 'amd64' and x64) - else r'\%s' % self.current_cpu + else rf'\{self.current_cpu}' ) def target_dir(self, hidex86=False, x64=False): @@ -129,7 +129,7 @@ def target_dir(self, hidex86=False, x64=False): if (self.target_cpu == 'x86' and hidex86) else r'\x64' if (self.target_cpu == 'amd64' and x64) - else r'\%s' % self.target_cpu + else rf'\{self.target_cpu}' ) def cross_dir(self, forcex86=False): @@ -152,7 +152,7 @@ def cross_dir(self, forcex86=False): return ( '' if self.target_cpu == current - else self.target_dir().replace('\\', '\\%s_' % current) + else self.target_dir().replace('\\', f'\\{current}_') ) @@ -494,11 +494,11 @@ def VSInstallDir(self): """ # Default path default = os.path.join( - self.ProgramFilesx86, 'Microsoft Visual Studio %0.1f' % self.vs_ver + self.ProgramFilesx86, f'Microsoft Visual Studio {self.vs_ver:0.1f}' ) # Try to get path from registry, if fail use default path - return self.ri.lookup(self.ri.vs, '%0.1f' % self.vs_ver) or default + return self.ri.lookup(self.ri.vs, f'{self.vs_ver:0.1f}') or default @property def VCInstallDir(self): @@ -558,16 +558,17 @@ def _guess_vc_legacy(self): path """ default = os.path.join( - self.ProgramFilesx86, r'Microsoft Visual Studio %0.1f\VC' % self.vs_ver + self.ProgramFilesx86, + rf'Microsoft Visual Studio {self.vs_ver:0.1f}\VC', ) # Try to get "VC++ for Python" path from registry as default path - reg_path = os.path.join(self.ri.vc_for_python, '%0.1f' % self.vs_ver) + reg_path = os.path.join(self.ri.vc_for_python, f'{self.vs_ver:0.1f}') python_vc = self.ri.lookup(reg_path, 'installdir') default_vc = os.path.join(python_vc, 'VC') if python_vc else default # Try to get path from registry, if fail use default path - return self.ri.lookup(self.ri.vc, '%0.1f' % self.vs_ver) or default_vc + return self.ri.lookup(self.ri.vc, f'{self.vs_ver:0.1f}') or default_vc @property def WindowsSdkVersion(self): @@ -616,13 +617,13 @@ def WindowsSdkDir(self): # noqa: C901 # is too complex (12) # FIXME sdkdir = '' for ver in self.WindowsSdkVersion: # Try to get it from registry - loc = os.path.join(self.ri.windows_sdk, 'v%s' % ver) + loc = os.path.join(self.ri.windows_sdk, f'v{ver}') sdkdir = self.ri.lookup(loc, 'installationfolder') if sdkdir: break if not sdkdir or not os.path.isdir(sdkdir): # Try to get "VC++ for Python" version from registry - path = os.path.join(self.ri.vc_for_python, '%0.1f' % self.vc_ver) + path = os.path.join(self.ri.vc_for_python, f'{self.vc_ver:0.1f}') install_base = self.ri.lookup(path, 'installdir') if install_base: sdkdir = os.path.join(install_base, 'WinSDK') @@ -630,14 +631,14 @@ def WindowsSdkDir(self): # noqa: C901 # is too complex (12) # FIXME # If fail, use default new path for ver in self.WindowsSdkVersion: intver = ver[: ver.rfind('.')] - path = r'Microsoft SDKs\Windows Kits\%s' % intver + path = rf'Microsoft SDKs\Windows Kits\{intver}' d = os.path.join(self.ProgramFiles, path) if os.path.isdir(d): sdkdir = d if not sdkdir or not os.path.isdir(sdkdir): # If fail, use default old path for ver in self.WindowsSdkVersion: - path = r'Microsoft SDKs\Windows\v%s' % ver + path = rf'Microsoft SDKs\Windows\v{ver}' d = os.path.join(self.ProgramFiles, path) if os.path.isdir(d): sdkdir = d @@ -663,8 +664,8 @@ def WindowsSDKExecutablePath(self): else: netfxver = 40 hidex86 = True if self.vs_ver <= 12.0 else False - arch = self.pi.current_dir(x64=True, hidex86=hidex86) - fx = 'WinSDK-NetFx%dTools%s' % (netfxver, arch.replace('\\', '-')) + arch = self.pi.current_dir(x64=True, hidex86=hidex86).replace('\\', '-') + fx = f'WinSDK-NetFx{netfxver}Tools{arch}' # list all possibles registry paths regpaths = [] @@ -673,7 +674,7 @@ def WindowsSDKExecutablePath(self): regpaths += [os.path.join(self.ri.netfx_sdk, ver, fx)] for ver in self.WindowsSdkVersion: - regpaths += [os.path.join(self.ri.windows_sdk, 'v%sA' % ver, fx)] + regpaths += [os.path.join(self.ri.windows_sdk, f'v{ver}A', fx)] # Return installation folder from the more recent path for path in regpaths: @@ -693,7 +694,7 @@ def FSharpInstallDir(self): str path """ - path = os.path.join(self.ri.visualstudio, r'%0.1f\Setup\F#' % self.vs_ver) + path = os.path.join(self.ri.visualstudio, rf'{self.vs_ver:0.1f}\Setup\F#') return self.ri.lookup(path, 'productdir') or '' @property @@ -711,7 +712,7 @@ def UniversalCRTSdkDir(self): # Find path of the more recent Kit for ver in vers: - sdkdir = self.ri.lookup(self.ri.windows_kits_roots, 'kitsroot%s' % ver) + sdkdir = self.ri.lookup(self.ri.windows_kits_roots, f'kitsroot{ver}') if sdkdir: return sdkdir or '' @@ -835,8 +836,8 @@ def _find_dot_net_versions(self, bits): versions """ # Find actual .NET version in registry - reg_ver = self.ri.lookup(self.ri.vc, 'frameworkver%d' % bits) - dot_net_dir = getattr(self, 'FrameworkDir%d' % bits) + reg_ver = self.ri.lookup(self.ri.vc, f'frameworkver{bits}') + dot_net_dir = getattr(self, f'FrameworkDir{bits}') ver = reg_ver or self._use_last_dir_name(dot_net_dir, 'v') or '' # Set .NET versions for specified MSVC++ version @@ -949,7 +950,7 @@ def VSTools(self): arch_subdir = self.pi.current_dir(hidex86=True, x64=True) paths += [r'Common7\IDE\CommonExtensions\Microsoft\TestWindow'] paths += [r'Team Tools\Performance Tools'] - paths += [r'Team Tools\Performance Tools%s' % arch_subdir] + paths += [rf'Team Tools\Performance Tools{arch_subdir}'] return [os.path.join(self.si.VSInstallDir, path) for path in paths] @@ -982,10 +983,10 @@ def VCLibraries(self): arch_subdir = self.pi.target_dir(x64=True) else: arch_subdir = self.pi.target_dir(hidex86=True) - paths = ['Lib%s' % arch_subdir, r'ATLMFC\Lib%s' % arch_subdir] + paths = [f'Lib{arch_subdir}', rf'ATLMFC\Lib{arch_subdir}'] if self.vs_ver >= 14.0: - paths += [r'Lib\store%s' % arch_subdir] + paths += [rf'Lib\store{arch_subdir}'] return [os.path.join(self.si.VCInstallDir, path) for path in paths] @@ -1019,10 +1020,10 @@ def VCTools(self): forcex86 = True if self.vs_ver <= 10.0 else False arch_subdir = self.pi.cross_dir(forcex86) if arch_subdir: - tools += [os.path.join(si.VCInstallDir, 'Bin%s' % arch_subdir)] + tools += [os.path.join(si.VCInstallDir, f'Bin{arch_subdir}')] if self.vs_ver == 14.0: - path = 'Bin%s' % self.pi.current_dir(hidex86=True) + path = f'Bin{self.pi.current_dir(hidex86=True)}' tools += [os.path.join(si.VCInstallDir, path)] elif self.vs_ver >= 15.0: @@ -1057,13 +1058,13 @@ def OSLibraries(self): """ if self.vs_ver <= 10.0: arch_subdir = self.pi.target_dir(hidex86=True, x64=True) - return [os.path.join(self.si.WindowsSdkDir, 'Lib%s' % arch_subdir)] + return [os.path.join(self.si.WindowsSdkDir, f'Lib{arch_subdir}')] else: arch_subdir = self.pi.target_dir(x64=True) lib = os.path.join(self.si.WindowsSdkDir, 'lib') libver = self._sdk_subdir - return [os.path.join(lib, '%sum%s' % (libver, arch_subdir))] + return [os.path.join(lib, f'{libver}um{arch_subdir}')] @property def OSIncludes(self): @@ -1086,9 +1087,9 @@ def OSIncludes(self): else: sdkver = '' return [ - os.path.join(include, '%sshared' % sdkver), - os.path.join(include, '%sum' % sdkver), - os.path.join(include, '%swinrt' % sdkver), + os.path.join(include, f'{sdkver}shared'), + os.path.join(include, f'{sdkver}um'), + os.path.join(include, f'{sdkver}winrt'), ] @property @@ -1123,7 +1124,7 @@ def OSLibpath(self): self.si.WindowsSdkDir, 'ExtensionSDKs', 'Microsoft.VCLibs', - '%0.1f' % self.vs_ver, + f'{self.vs_ver:0.1f}', 'References', 'CommonConfiguration', 'neutral', @@ -1158,7 +1159,7 @@ def _sdk_tools(self): if not self.pi.current_is_x86(): arch_subdir = self.pi.current_dir(x64=True) - path = 'Bin%s' % arch_subdir + path = f'Bin{arch_subdir}' yield os.path.join(self.si.WindowsSdkDir, path) if self.vs_ver in (10.0, 11.0): @@ -1166,14 +1167,14 @@ def _sdk_tools(self): arch_subdir = '' else: arch_subdir = self.pi.current_dir(hidex86=True, x64=True) - path = r'Bin\NETFX 4.0 Tools%s' % arch_subdir + path = rf'Bin\NETFX 4.0 Tools{arch_subdir}' yield os.path.join(self.si.WindowsSdkDir, path) elif self.vs_ver >= 15.0: path = os.path.join(self.si.WindowsSdkDir, 'Bin') arch_subdir = self.pi.current_dir(x64=True) sdkver = self.si.WindowsSdkLastVersion - yield os.path.join(path, '%s%s' % (sdkver, arch_subdir)) + yield os.path.join(path, f'{sdkver}{arch_subdir}') if self.si.WindowsSDKExecutablePath: yield self.si.WindowsSDKExecutablePath @@ -1189,7 +1190,7 @@ def _sdk_subdir(self): subdir """ ucrtver = self.si.WindowsSdkLastVersion - return ('%s\\' % ucrtver) if ucrtver else '' + return (f'{ucrtver}\\') if ucrtver else '' @property def SdkSetup(self): @@ -1251,7 +1252,7 @@ def NetFxSDKLibraries(self): return [] arch_subdir = self.pi.target_dir(x64=True) - return [os.path.join(self.si.NetFxSdkDir, r'lib\um%s' % arch_subdir)] + return [os.path.join(self.si.NetFxSdkDir, rf'lib\um{arch_subdir}')] @property def NetFxSDKIncludes(self): @@ -1299,7 +1300,7 @@ def MSBuild(self): base_path = self.si.VSInstallDir arch_subdir = '' - path = r'MSBuild\%0.1f\bin%s' % (self.vs_ver, arch_subdir) + path = rf'MSBuild\{self.vs_ver:0.1f}\bin{arch_subdir}' build = [os.path.join(base_path, path)] if self.vs_ver >= 15.0: @@ -1339,7 +1340,7 @@ def UCRTLibraries(self): arch_subdir = self.pi.target_dir(x64=True) lib = os.path.join(self.si.UniversalCRTSdkDir, 'lib') ucrtver = self._ucrt_subdir - return [os.path.join(lib, '%sucrt%s' % (ucrtver, arch_subdir))] + return [os.path.join(lib, f'{ucrtver}ucrt{arch_subdir}')] @property def UCRTIncludes(self): @@ -1355,7 +1356,7 @@ def UCRTIncludes(self): return [] include = os.path.join(self.si.UniversalCRTSdkDir, 'include') - return [os.path.join(include, '%sucrt' % self._ucrt_subdir)] + return [os.path.join(include, f'{self._ucrt_subdir}ucrt')] @property def _ucrt_subdir(self): @@ -1368,7 +1369,7 @@ def _ucrt_subdir(self): subdir """ ucrtver = self.si.UniversalCRTSdkLastVersion - return ('%s\\' % ucrtver) if ucrtver else '' + return (f'{ucrtver}\\') if ucrtver else '' @property def FSharp(self): @@ -1392,7 +1393,7 @@ def VCRuntimeRedist(self) -> str | None: Returns the first suitable path found or None. """ - vcruntime = 'vcruntime%d0.dll' % self.vc_ver + vcruntime = f'vcruntime{self.vc_ver}0.dll' arch_subdir = self.pi.target_dir(x64=True).strip('\\') # Installation prefixes candidates @@ -1408,9 +1409,9 @@ def VCRuntimeRedist(self) -> str | None: # CRT directory crt_dirs = ( - 'Microsoft.VC%d.CRT' % (self.vc_ver * 10), + f'Microsoft.VC{self.vc_ver * 10}.CRT', # Sometime store in directory with VS version instead of VC - 'Microsoft.VC%d.CRT' % (int(self.vs_ver) * 10), + f'Microsoft.VC{int(self.vs_ver) * 10}.CRT', ) # vcruntime path @@ -1509,7 +1510,7 @@ def _build_paths(self, name, spec_path_lists, exists): paths = itertools.chain(spec_paths, env_paths) extant_paths = list(filter(os.path.isdir, paths)) if exists else paths if not extant_paths: - msg = "%s environment variable is empty" % name.upper() + msg = f"{name.upper()} environment variable is empty" raise distutils.errors.DistutilsPlatformError(msg) unique_paths = unique_everseen(extant_paths) return os.pathsep.join(unique_paths) diff --git a/setuptools/package_index.py b/setuptools/package_index.py index 9e01d5e082..f501c6b2d7 100644 --- a/setuptools/package_index.py +++ b/setuptools/package_index.py @@ -75,7 +75,7 @@ def parse_requirement_arg(spec): return Requirement.parse(spec) except ValueError as e: raise DistutilsError( - "Not a URL, existing file, or requirement spec: %r" % (spec,) + f"Not a URL, existing file, or requirement spec: {spec!r}" ) from e @@ -358,7 +358,7 @@ def process_url(self, url, retrieve=False): # noqa: C901 if f is None: return if isinstance(f, urllib.error.HTTPError) and f.code == 401: - self.info("Authentication error: %s" % f.msg) + self.info(f"Authentication error: {f.msg}") self.fetched_urls[f.url] = True if 'html' not in f.headers.get('content-type', '').lower(): f.close() # not html, we can't process it @@ -475,13 +475,13 @@ def process_index(self, url, page): base, frag = egg_info_for_url(new_url) if base.endswith('.py') and not frag: if ver: - new_url += '#egg=%s-%s' % (pkg, ver) + new_url += f'#egg={pkg}-{ver}' else: self.need_version_info(url) self.scan_url(new_url) return PYPI_MD5.sub( - lambda m: '%s' % m.group(1, 3, 2), page + lambda m: '{}'.format(*m.group(1, 3, 2)), page ) def need_version_info(self, url): @@ -526,14 +526,13 @@ def check_hash(self, checker, filename, tfp): """ checker is a ContentChecker """ - checker.report(self.debug, "Validating %%s checksum for %s" % filename) + checker.report(self.debug, f"Validating %s checksum for {filename}") if not checker.is_valid(): tfp.close() os.unlink(filename) raise DistutilsError( - "%s validation failed for %s; " + f"{checker.hash.name} validation failed for {os.path.basename(filename)}; " "possible download problem?" - % (checker.hash.name, os.path.basename(filename)) ) def add_find_links(self, urls): @@ -722,20 +721,15 @@ def gen_setup(self, filename, fragment, tmpdir): with open(os.path.join(tmpdir, 'setup.py'), 'w', encoding="utf-8") as file: file.write( "from setuptools import setup\n" - "setup(name=%r, version=%r, py_modules=[%r])\n" - % ( - dists[0].project_name, - dists[0].version, - os.path.splitext(basename)[0], - ) + f"setup(name={dists[0].project_name!r}, version={dists[0].version!r}, py_modules=[{os.path.splitext(basename)[0]!r}])\n" ) return filename elif match: raise DistutilsError( - "Can't unambiguously interpret project/version identifier %r; " + f"Can't unambiguously interpret project/version identifier {fragment!r}; " "any dashes in the name or version should be escaped using " - "underscores. %r" % (fragment, dists) + f"underscores. {dists!r}" ) else: raise DistutilsError( @@ -753,9 +747,7 @@ def _download_to(self, url, filename): checker = HashChecker.from_url(url) fp = self.open_url(url) if isinstance(fp, urllib.error.HTTPError): - raise DistutilsError( - "Can't download %s: %s %s" % (url, fp.code, fp.msg) - ) + raise DistutilsError(f"Can't download {url}: {fp.code} {fp.msg}") headers = fp.info() blocknum = 0 bs = self.dl_blocksize @@ -795,29 +787,27 @@ def open_url(self, url, warning=None): # noqa: C901 # is too complex (12) if warning: self.warn(warning, msg) else: - raise DistutilsError('%s %s' % (url, msg)) from v + raise DistutilsError(f'{url} {msg}') from v except urllib.error.HTTPError as v: return v except urllib.error.URLError as v: if warning: self.warn(warning, v.reason) else: - raise DistutilsError( - "Download error for %s: %s" % (url, v.reason) - ) from v + raise DistutilsError(f"Download error for {url}: {v.reason}") from v except http.client.BadStatusLine as v: if warning: self.warn(warning, v.line) else: raise DistutilsError( - '%s returned a bad status line. The server might be ' - 'down, %s' % (url, v.line) + f'{url} returned a bad status line. The server might be ' + f'down, {v.line}' ) from v except (http.client.HTTPException, OSError) as v: if warning: self.warn(warning, v) else: - raise DistutilsError("Download error for %s: %s" % (url, v)) from v + raise DistutilsError(f"Download error for {url}: {v}") from v def _download_url(self, url, tmpdir): # Determine download filename @@ -1135,7 +1125,7 @@ def local_open(url): break elif os.path.isdir(filepath): f += '/' - files.append('{name}'.format(name=f)) + files.append(f'{f}') else: tmpl = "{url}{files}" body = tmpl.format(url=url, files='\n'.join(files)) diff --git a/setuptools/tests/config/test_setupcfg.py b/setuptools/tests/config/test_setupcfg.py index 4f0a7349f5..78d8c1ffc2 100644 --- a/setuptools/tests/config/test_setupcfg.py +++ b/setuptools/tests/config/test_setupcfg.py @@ -87,14 +87,14 @@ def test_basic(self, tmpdir): '[options]\n' 'scripts = bin/a.py, bin/b.py\n', ) - config_dict = read_configuration('%s' % config) + config_dict = read_configuration(str(config)) assert config_dict['metadata']['version'] == '10.1.1' assert config_dict['metadata']['keywords'] == ['one', 'two'] assert config_dict['options']['scripts'] == ['bin/a.py', 'bin/b.py'] def test_no_config(self, tmpdir): with pytest.raises(DistutilsFileError): - read_configuration('%s' % tmpdir.join('setup.cfg')) + read_configuration(str(tmpdir.join('setup.cfg'))) def test_ignore_errors(self, tmpdir): _, config = fake_env( @@ -102,9 +102,9 @@ def test_ignore_errors(self, tmpdir): '[metadata]\nversion = attr: none.VERSION\nkeywords = one, two\n', ) with pytest.raises(ImportError): - read_configuration('%s' % config) + read_configuration(str(config)) - config_dict = read_configuration('%s' % config, ignore_option_errors=True) + config_dict = read_configuration(str(config), ignore_option_errors=True) assert config_dict['metadata']['keywords'] == ['one', 'two'] assert 'version' not in config_dict['metadata'] diff --git a/setuptools/tests/server.py b/setuptools/tests/server.py index 15bbc3b1f0..623a49a550 100644 --- a/setuptools/tests/server.py +++ b/setuptools/tests/server.py @@ -44,7 +44,7 @@ def stop(self): def base_url(self): port = self.server_port - return 'http://127.0.0.1:%s/setuptools/tests/indexes/' % port + return f'http://127.0.0.1:{port}/setuptools/tests/indexes/' class RequestRecorder(http.server.BaseHTTPRequestHandler): @@ -70,11 +70,11 @@ def run(self): @property def netloc(self): - return 'localhost:%s' % self.server_port + return f'localhost:{self.server_port}' @property def url(self): - return 'http://%s/' % self.netloc + return f'http://{self.netloc}/' def path_to_url(path, authority=None): diff --git a/setuptools/tests/test_build_ext.py b/setuptools/tests/test_build_ext.py index dab8b41cc9..6398a5b95f 100644 --- a/setuptools/tests/test_build_ext.py +++ b/setuptools/tests/test_build_ext.py @@ -284,8 +284,8 @@ def test_build_ext_config_handling(tmpdir_cwd): ), } path.build(files) - code, output = environment.run_setup_py( + code, (stdout, stderr) = environment.run_setup_py( cmd=['build'], data_stream=(0, 2), ) - assert code == 0, '\nSTDOUT:\n%s\nSTDERR:\n%s' % output + assert code == 0, f'\nSTDOUT:\n{stdout}\nSTDERR:\n{stderr}' diff --git a/setuptools/tests/test_core_metadata.py b/setuptools/tests/test_core_metadata.py index 34828ac750..d8c9a3faaf 100644 --- a/setuptools/tests/test_core_metadata.py +++ b/setuptools/tests/test_core_metadata.py @@ -299,7 +299,7 @@ def test_maintainer_author(name, attrs, tmpdir): for line in pkg_lines: assert not line.startswith(fkey + ':') else: - line = '%s: %s' % (fkey, val) + line = f'{fkey}: {val}' assert line in pkg_lines_set diff --git a/setuptools/tests/test_dist.py b/setuptools/tests/test_dist.py index 597785b519..de9fd82f1e 100644 --- a/setuptools/tests/test_dist.py +++ b/setuptools/tests/test_dist.py @@ -25,7 +25,7 @@ def test_dist_fetch_build_egg(tmpdir): def sdist_with_index(distname, version): dist_dir = index.mkdir(distname) - dist_sdist = '%s-%s.tar.gz' % (distname, version) + dist_sdist = f'{distname}-{version}.tar.gz' make_nspkg_sdist(str(dist_dir.join(dist_sdist)), distname, version) with dist_dir.join('index.html').open('w') as fp: fp.write( diff --git a/setuptools/tests/test_easy_install.py b/setuptools/tests/test_easy_install.py index de257db80c..3309b89553 100644 --- a/setuptools/tests/test_easy_install.py +++ b/setuptools/tests/test_easy_install.py @@ -735,14 +735,14 @@ def make_dependency_sdist(dist_path, distname, version): ( 'setup.py', DALS( - """ + f""" import setuptools setuptools.setup( - name={name!r}, + name={distname!r}, version={version!r}, - py_modules=[{name!r}], + py_modules=[{distname!r}], ) - """.format(name=distname, version=version) + """ ), ), ( @@ -814,7 +814,7 @@ def test_setup_requires_with_pep508_url(self, mock_index, monkeypatch): # Ignored (overridden by setup_attrs) 'python-xlib', '0.19', - setup_attrs=dict(setup_requires='dependency @ %s' % dep_url), + setup_attrs=dict(setup_requires=f'dependency @ {dep_url}'), ) test_setup_py = os.path.join(test_pkg, 'setup.py') run_setup(test_setup_py, ['--version']) @@ -1098,14 +1098,13 @@ def make_trivial_sdist(dist_path, distname, version): ( 'setup.py', DALS( - """\ + f"""\ import setuptools setuptools.setup( - name=%r, - version=%r + name={distname!r}, + version={version!r} ) """ - % (distname, version) ), ), ('setup.cfg', ''), @@ -1126,16 +1125,15 @@ def make_nspkg_sdist(dist_path, distname, version): packages = ['.'.join(parts[:idx]) for idx in range(1, len(parts) + 1)] setup_py = DALS( - """\ + f"""\ import setuptools setuptools.setup( - name=%r, - version=%r, - packages=%r, - namespace_packages=[%r] + name={distname!r}, + version={version!r}, + packages={packages!r}, + namespace_packages=[{nspackage!r}] ) """ - % (distname, version, packages, nspackage) ) init = "__import__('pkg_resources').declare_namespace(__name__)" @@ -1210,7 +1208,7 @@ def create_setup_requires_package( test_setup_attrs = { 'name': 'test_pkg', 'version': '0.0', - 'setup_requires': ['%s==%s' % (distname, version)], + 'setup_requires': [f'{distname}=={version}'], 'dependency_links': [os.path.abspath(path)], } if setup_attrs: @@ -1231,7 +1229,7 @@ def create_setup_requires_package( section = options if isinstance(value, (tuple, list)): value = ';'.join(value) - section.append('%s: %s' % (name, value)) + section.append(f'{name}: {value}') test_setup_cfg_contents = DALS( """ [metadata] @@ -1259,7 +1257,7 @@ def create_setup_requires_package( with open(os.path.join(test_pkg, 'setup.py'), 'w', encoding="utf-8") as f: f.write(setup_py_template % test_setup_attrs) - foobar_path = os.path.join(path, '%s-%s.tar.gz' % (distname, version)) + foobar_path = os.path.join(path, f'{distname}-{version}.tar.gz') make_package(foobar_path, distname, version) return test_pkg @@ -1274,12 +1272,12 @@ class TestScriptHeader: exe_with_spaces = r'C:\Program Files\Python36\python.exe' def test_get_script_header(self): - expected = '#!%s\n' % ei.nt_quote_arg(os.path.normpath(sys.executable)) + expected = f'#!{ei.nt_quote_arg(os.path.normpath(sys.executable))}\n' actual = ei.ScriptWriter.get_header('#!/usr/local/bin/python') assert actual == expected def test_get_script_header_args(self): - expected = '#!%s -x\n' % ei.nt_quote_arg(os.path.normpath(sys.executable)) + expected = f'#!{ei.nt_quote_arg(os.path.normpath(sys.executable))} -x\n' actual = ei.ScriptWriter.get_header('#!/usr/bin/python -x') assert actual == expected @@ -1287,14 +1285,14 @@ def test_get_script_header_non_ascii_exe(self): actual = ei.ScriptWriter.get_header( '#!/usr/bin/python', executable=self.non_ascii_exe ) - expected = '#!%s -x\n' % self.non_ascii_exe + expected = f'#!{self.non_ascii_exe} -x\n' assert actual == expected def test_get_script_header_exe_with_spaces(self): actual = ei.ScriptWriter.get_header( '#!/usr/bin/python', executable='"' + self.exe_with_spaces + '"' ) - expected = '#!"%s"\n' % self.exe_with_spaces + expected = f'#!"{self.exe_with_spaces}"\n' assert actual == expected diff --git a/setuptools/tests/test_egg_info.py b/setuptools/tests/test_egg_info.py index 6e8d0c68c3..16f2bf1850 100644 --- a/setuptools/tests/test_egg_info.py +++ b/setuptools/tests/test_egg_info.py @@ -38,9 +38,8 @@ def env(): '.pydistutils.cfg': DALS( """ [egg_info] - egg-base = %(egg-base)s - """ - % env.paths + egg-base = {egg-base} + """.format(**env.paths) ) } }) @@ -260,13 +259,9 @@ def _setup_script_with_requires(self, requires, use_setup_cfg=False): 'setup.cfg': setup_config, }) - mismatch_marker = "python_version<'{this_ver}'".format( - this_ver=sys.version_info[0], - ) + mismatch_marker = f"python_version<'{sys.version_info[0]}'" # Alternate equivalent syntax. - mismatch_marker_alternate = 'python_version < "{this_ver}"'.format( - this_ver=sys.version_info[0], - ) + mismatch_marker_alternate = f'python_version < "{sys.version_info[0]}"' invalid_marker = "<=>++" class RequiresTestHelper: diff --git a/setuptools/tests/test_install_scripts.py b/setuptools/tests/test_install_scripts.py index 2ae5496525..e62a6b7f31 100644 --- a/setuptools/tests/test_install_scripts.py +++ b/setuptools/tests/test_install_scripts.py @@ -38,7 +38,7 @@ def test_sys_executable_escaping_unix(self, tmpdir, monkeypatch): Ensure that shebang is not quoted on Unix when getting the Python exe from sys.executable. """ - expected = '#!%s\n' % self.unix_exe + expected = f'#!{self.unix_exe}\n' monkeypatch.setattr('sys.executable', self.unix_exe) with tmpdir.as_cwd(): self._run_install_scripts(str(tmpdir)) @@ -52,7 +52,7 @@ def test_sys_executable_escaping_win32(self, tmpdir, monkeypatch): Ensure that shebang is quoted on Windows when getting the Python exe from sys.executable and it contains a space. """ - expected = '#!"%s"\n' % self.win32_exe + expected = f'#!"{self.win32_exe}"\n' monkeypatch.setattr('sys.executable', self.win32_exe) with tmpdir.as_cwd(): self._run_install_scripts(str(tmpdir)) @@ -67,7 +67,7 @@ def test_executable_with_spaces_escaping_unix(self, tmpdir): a value with spaces is specified using --executable. """ - expected = '#!%s\n' % self.unix_spaces_exe + expected = f'#!{self.unix_spaces_exe}\n' with tmpdir.as_cwd(): self._run_install_scripts(str(tmpdir), self.unix_spaces_exe) with open(str(tmpdir.join('foo')), 'r', encoding="utf-8") as f: @@ -81,7 +81,7 @@ def test_executable_arg_escaping_win32(self, tmpdir): getting a path with spaces from --executable, that is itself properly quoted. """ - expected = '#!"%s"\n' % self.win32_exe + expected = f'#!"{self.win32_exe}"\n' with tmpdir.as_cwd(): self._run_install_scripts(str(tmpdir), '"' + self.win32_exe + '"') with open(str(tmpdir.join('foo-script.py')), 'r', encoding="utf-8") as f: diff --git a/setuptools/tests/test_manifest.py b/setuptools/tests/test_manifest.py index ae5572b83c..745c072f20 100644 --- a/setuptools/tests/test_manifest.py +++ b/setuptools/tests/test_manifest.py @@ -34,14 +34,11 @@ def make_local_path(s): 'packages': ['app'], } -SETUP_PY = ( - """\ +SETUP_PY = f"""\ from setuptools import setup -setup(**%r) +setup(**{SETUP_ATTRS!r}) """ - % SETUP_ATTRS -) @contextlib.contextmanager diff --git a/setuptools/tests/test_sandbox.py b/setuptools/tests/test_sandbox.py index 20db6baaa6..a476b7c93d 100644 --- a/setuptools/tests/test_sandbox.py +++ b/setuptools/tests/test_sandbox.py @@ -76,7 +76,7 @@ class CantPickleThis(Exception): "This Exception is unpickleable because it's not in globals" def __repr__(self) -> str: - return 'CantPickleThis%r' % (self.args,) + return f'CantPickleThis{self.args!r}' with setuptools.sandbox.ExceptionSaver() as saved_exc: raise CantPickleThis('detail') diff --git a/setuptools/tests/test_sdist.py b/setuptools/tests/test_sdist.py index 30347190db..3ee0511b1c 100644 --- a/setuptools/tests/test_sdist.py +++ b/setuptools/tests/test_sdist.py @@ -37,14 +37,11 @@ 'data_files': [("data", [os.path.join("d", "e.dat")])], } -SETUP_PY = ( - """\ +SETUP_PY = f"""\ from setuptools import setup -setup(**%r) +setup(**{SETUP_ATTRS!r}) """ - % SETUP_ATTRS -) EXTENSION = Extension( name="sdist_test.f", diff --git a/setuptools/tests/test_wheel.py b/setuptools/tests/test_wheel.py index ac736e2947..4071b1d5b6 100644 --- a/setuptools/tests/test_wheel.py +++ b/setuptools/tests/test_wheel.py @@ -176,7 +176,7 @@ def __init__(self, id, **kwargs): self._fields = kwargs def __repr__(self) -> str: - return '%s(**%r)' % (self._id, self._fields) + return f'{self._id}(**{self._fields!r})' # Using Any to avoid possible type union issues later in test @@ -367,11 +367,10 @@ def __repr__(self) -> str: ), dict( id='requires2', - install_requires=""" + install_requires=f""" bar - foo<=2.0; %r in sys_platform - """ - % sys.platform, + foo<=2.0; {sys.platform!r} in sys_platform + """, requires_txt=DALS( """ bar @@ -381,10 +380,9 @@ def __repr__(self) -> str: ), dict( id='requires3', - install_requires=""" - bar; %r != sys_platform - """ - % sys.platform, + install_requires=f""" + bar; {sys.platform!r} != sys_platform + """, ), dict( id='requires4', @@ -406,7 +404,7 @@ def __repr__(self) -> str: dict( id='requires5', extras_require={ - 'extra': 'foobar; %r != sys_platform' % sys.platform, + 'extra': f'foobar; {sys.platform!r} != sys_platform', }, requires_txt=DALS( """ @@ -599,7 +597,7 @@ def test_wheel_install_pep_503(): def test_wheel_no_dist_dir(): project_name = 'nodistinfo' version = '1.0' - wheel_name = '{0}-{1}-py2.py3-none-any.whl'.format(project_name, version) + wheel_name = f'{project_name}-{version}-py2.py3-none-any.whl' with tempdir() as source_dir: wheel_path = os.path.join(source_dir, wheel_name) # create an empty zip file diff --git a/setuptools/tests/test_windows_wrappers.py b/setuptools/tests/test_windows_wrappers.py index 4a112baf75..cebf6d183f 100644 --- a/setuptools/tests/test_windows_wrappers.py +++ b/setuptools/tests/test_windows_wrappers.py @@ -57,9 +57,9 @@ def win_launcher_exe(prefix): """A simple routine to select launcher script based on platform.""" assert prefix in ('cli', 'gui') if platform.machine() == "ARM64": - return "{}-arm64.exe".format(prefix) + return f"{prefix}-arm64.exe" else: - return "{}-32.exe".format(prefix) + return f"{prefix}-32.exe" class TestCLI(WrapperTester): diff --git a/setuptools/wheel.py b/setuptools/wheel.py index 69a73df244..352d9b50d3 100644 --- a/setuptools/wheel.py +++ b/setuptools/wheel.py @@ -79,7 +79,7 @@ class Wheel: def __init__(self, filename): match = WHEEL_NAME(os.path.basename(filename)) if match is None: - raise ValueError('invalid wheel name: %r' % filename) + raise ValueError(f'invalid wheel name: {filename!r}') self.filename = filename for k, v in match.groupdict().items(): setattr(self, k, v) @@ -122,9 +122,9 @@ def install_as_egg(self, destination_eggdir): self._install_as_egg(destination_eggdir, zf) def _install_as_egg(self, destination_eggdir, zf): - dist_basename = '%s-%s' % (self.project_name, self.version) + dist_basename = f'{self.project_name}-{self.version}' dist_info = self.get_dist_info(zf) - dist_data = '%s.data' % dist_basename + dist_data = f'{dist_basename}.data' egg_info = os.path.join(destination_eggdir, 'EGG-INFO') self._convert_metadata(zf, destination_eggdir, dist_info, egg_info) @@ -145,7 +145,7 @@ def get_metadata(name): wheel_version = parse_version(wheel_metadata.get('Wheel-Version')) wheel_v1 = parse_version('1.0') <= wheel_version < parse_version('2.0dev0') if not wheel_v1: - raise ValueError('unsupported wheel format version: %s' % wheel_version) + raise ValueError(f'unsupported wheel format version: {wheel_version}') # Extract to target directory. _unpack_zipfile_obj(zf, destination_eggdir) # Convert metadata.