Repository: pypa/pip

Issue:
Update %-format call to use str.format
**What's the problem this feature will solve?**

Currently in [`src/pip/_internal/operations/prepare.py`](https://github.com/pypa/pip/blob/bffca72d4a29df4e27264e43b7bc4ee44e617c55/src/pip/_internal/operations/prepare.py#L110-L112), we use `%`-style string formatting.

**Describe the solution you'd like**

We should use the `.format` method for consistency with the rest of the code base.

We should also consider doing the same for the rest of the code base. Whoever takes care of this specific issue should make a general issue for that!

_Posted in its original form by @pradyunsg in [#6968 (comment)](https://github.com/pypa/pip/pull/6968#discussion_r320562155)_

----

This issue is a good starting point for anyone who wants to help out with pip's development -- it's simple and the process of fixing this should be a good introduction to pip's development workflow.


Discussion:
I like simple.

As long as you are not expecting this yesterday, I'll be happy to take this.
👋 submitting PR now
is there a general issue? happy to do that too
All yours then @dyspop
FYI, to catch `%`-style string formatting in the code consider [flake8-printf-formatting]( https://github.com/atugushev/flake8-printf-formatting) plugin for flake8.

Usage:
```bash
$ pip install flake8 flake8-printf-formatting
$ flake8 src/pip/_internal/operations/prepare.py --select=MOD
src/pip/_internal/operations/prepare.py:111:13: MOD001 do not use printf-style string formatting
src/pip/_internal/operations/prepare.py:147:21: MOD001 do not use printf-style string formatting
src/pip/_internal/operations/prepare.py:217:21: MOD001 do not use printf-style string formatting
src/pip/_internal/operations/prepare.py:249:21: MOD001 do not use printf-style string formatting
src/pip/_internal/operations/prepare.py:277:13: MOD001 do not use printf-style string formatting
```

---
following the https://github.com/pypa/pip/pull/6763#discussion_r321961775
/cc @pradyunsg 
One clarification / caveat: we probably want to exclude logging calls from this change. I can provide reasons if desired.
@cjerdonek I agree -- https://github.com/pypa/pip/pull/6968#discussion_r320098782.

I do wonder if there's some way to make the format strings for logging calls to use the new-style formatting. Let's discuss in a new issue.
> I do wonder if there's some way to make the format strings for logging calls to use the new-style formatting

The style parameter documented [here](https://docs.python.org/3/library/logging.html#logging.Formatter) allows this. But it's Python 3 only. Can we stop supporting Python 2 now, please? 🙂 
@pfmoore I wish. :(

I guess we could write a Formatter that would do this handling for us. It shouldn't be too difficult. Anyway, I opened #7009 for discussing this further.


Resolving patch:
diff --git a/src/pip/_internal/operations/prepare.py b/src/pip/_internal/operations/prepare.py
--- a/src/pip/_internal/operations/prepare.py
+++ b/src/pip/_internal/operations/prepare.py
@@ -105,8 +105,8 @@ def _download_should_save(self):
 
         logger.critical('Could not find download directory')
         raise InstallationError(
-            "Could not find or access download directory '%s'"
-            % display_path(self.download_dir))
+            "Could not find or access download directory '{}'"
+            .format(self.download_dir))
 
     def prepare_linked_requirement(
         self,
@@ -141,12 +141,12 @@ def prepare_linked_requirement(
             # package unpacked in `req.source_dir`
             if os.path.exists(os.path.join(req.source_dir, 'setup.py')):
                 raise PreviousBuildDirError(
-                    "pip can't proceed with requirements '%s' due to a"
-                    " pre-existing build directory (%s). This is "
+                    "pip can't proceed with requirements '{}' due to a"
+                    " pre-existing build directory ({}). This is "
                     "likely due to a previous installation that failed"
                     ". pip is being responsible and not assuming it "
                     "can delete this. Please delete it and try again."
-                    % (req, req.source_dir)
+                    .format(req, req.source_dir)
                 )
 
             # Now that we have the real link, we can tell what kind of
@@ -200,9 +200,8 @@ def prepare_linked_requirement(
                     exc,
                 )
                 raise InstallationError(
-                    'Could not install requirement %s because of HTTP '
-                    'error %s for URL %s' %
-                    (req, exc, link)
+                    'Could not install requirement {} because of HTTP '
+                    'error {} for URL {}'.format(req, exc, link)
                 )
 
             if link.is_wheel:
@@ -247,9 +246,9 @@ def prepare_editable_requirement(
         with indent_log():
             if require_hashes:
                 raise InstallationError(
-                    'The editable requirement %s cannot be installed when '
+                    'The editable requirement {} cannot be installed when '
                     'requiring hashes, because there is no single file to '
-                    'hash.' % req
+                    'hash.'.format(req)
                 )
             req.ensure_has_source_dir(self.src_dir)
             req.update_editable(not self._download_should_save)
@@ -276,7 +275,7 @@ def prepare_installed_requirement(
         assert req.satisfied_by, "req should have been satisfied but isn't"
         assert skip_reason is not None, (
             "did not get skip reason skipped but req.satisfied_by "
-            "is set to %r" % (req.satisfied_by,)
+            "is set to {}".format(req.satisfied_by)
         )
         logger.info(
             'Requirement %s: %s (%s)',


Test patch: