gifn-apply: allow Ruff to insist on trailing commas

Change-Id: I0bec61de010daede21bfaab9dd5bec62ed892575
diff --git a/tools/git-if-needed/python/config/ruff-base/pyproject.toml b/tools/git-if-needed/python/config/ruff-base/pyproject.toml
index b46b792..a57fa70 100644
--- a/tools/git-if-needed/python/config/ruff-base/pyproject.toml
+++ b/tools/git-if-needed/python/config/ruff-base/pyproject.toml
@@ -10,9 +10,6 @@
   # We know what "self" is, we hope
   "ANN101",
 
-  # We leave most of the formatting to the 'black' tool
-  "COM812",
-
   # This is our style
   "D203",
   "D213",
diff --git a/tools/git-if-needed/python/gifn_apply/__main__.py b/tools/git-if-needed/python/gifn_apply/__main__.py
index eae4c87..bcac2f3 100644
--- a/tools/git-if-needed/python/gifn_apply/__main__.py
+++ b/tools/git-if-needed/python/gifn_apply/__main__.py
@@ -129,10 +129,16 @@
         help="the name of the series file in the patches directory (default: 'series')",
     )
     parser.add_argument(
-        "-v", "--verbose", action="store_true", help="verbose operation; display diagnostic output"
+        "-v",
+        "--verbose",
+        action="store_true",
+        help="verbose operation; display diagnostic output",
     )
     parser.add_argument(
-        "-V", "--version", action="store_true", help="display program version information and exit"
+        "-V",
+        "--version",
+        action="store_true",
+        help="display program version information and exit",
     )
 
     args: Final = parser.parse_args()
@@ -173,7 +179,7 @@
             patches=patches,
             series=patches / series_file,
             repo_urls=repo_urls_ok,
-        )
+        ),
     )
 
 
@@ -204,7 +210,9 @@
         )
 
         def list_change_ids(
-            cfg: defs.Config, repo: defs.Repo, repo_dir: pathlib.Path
+            cfg: defs.Config,
+            repo: defs.Repo,
+            repo_dir: pathlib.Path,
         ) -> RepoChanges:
             """List the changes in the cloned or manipulated repository."""
             changes: Final = git.list_change_ids(cfg, repo_dir)
@@ -233,7 +241,7 @@
             if rchanges.repo != repo:
                 sys.exit(
                     f"Internal error: {repo=!r} not the same as {rchanges.repo=!r} for "
-                    f"{rchanges.repo_dir=!r} {len(rchanges.changes)} changes"
+                    f"{rchanges.repo_dir=!r} {len(rchanges.changes)} changes",
                 )
 
             res: Final = list_change_ids(cfg, repo, rchanges.repo_dir)
@@ -242,18 +250,18 @@
             if len_after < len_before:
                 sys.exit(
                     f"gifn weirdness: {len_after=!r} < {len_before=!r} for "
-                    f"{rchanges.repo=!r} at {rchanges.repo_dir=!r}"
+                    f"{rchanges.repo=!r} at {rchanges.repo_dir=!r}",
                 )
             if res.changes[:len_before] != rchanges.changes:
                 sys.exit(
                     f"gifn weirdness: the first {len_before} changes are not the same for "
-                    f"{rchanges.repo=!r} at {rchanges.repo_dir=!r}"
+                    f"{rchanges.repo=!r} at {rchanges.repo_dir=!r}",
                 )
             if not rchanges.changes_set.issubset(res.changes_set):
                 sys.exit(
                     f"gifn weirdness: the {len_before=!r} changes are not "
                     f"contained within the {len_after=!r} ones for "
-                    f"{rchanges.repo=!r} at {rchanges.repo_dir=!r}"
+                    f"{rchanges.repo=!r} at {rchanges.repo_dir=!r}",
                 )
 
             return res
diff --git a/tools/git-if-needed/python/gifn_apply/git.py b/tools/git-if-needed/python/gifn_apply/git.py
index 931e930..f33c1a1 100644
--- a/tools/git-if-needed/python/gifn_apply/git.py
+++ b/tools/git-if-needed/python/gifn_apply/git.py
@@ -31,7 +31,7 @@
     )
 
     repo_url: Final = loc.url._replace(
-        path=loc.url.path + ("" if loc.url.path.endswith("/") else "/") + repo.repo
+        path=loc.url.path + ("" if loc.url.path.endswith("/") else "/") + repo.repo,
     )
     repo_dir: Final = tempd / repo.origin / repo.repo
     if repo_dir.exists() or repo_dir.is_symlink():
@@ -50,7 +50,7 @@
         )
     except (OSError, subprocess.CalledProcessError) as err:
         raise GitError(
-            f"Could not run `git clone {repo_url.geturl()} {repo.repo}` in {tempd}: {err}"
+            f"Could not run `git clone {repo_url.geturl()} {repo.repo}` in {tempd}: {err}",
         ) from err
     if not repo_dir.is_dir():
         raise GitError(f"`git clone` did not create {repo_dir}")
@@ -76,7 +76,7 @@
         raise GitError(f"Could not run `git log` for change IDs in {repo_dir}: {err}") from err
     except ValueError as err:
         raise GitError(
-            f"Could not decode the output of `git log` in {repo_dir} into UTF-8 change IDs: {err}"
+            f"Could not decode the output of `git log` in {repo_dir} into UTF-8 change IDs: {err}",
         ) from err
 
     def parse_line(line: str) -> str:
diff --git a/tools/git-if-needed/python/gifn_apply/quilt.py b/tools/git-if-needed/python/gifn_apply/quilt.py
index 3de9049..b7bb8e7 100644
--- a/tools/git-if-needed/python/gifn_apply/quilt.py
+++ b/tools/git-if-needed/python/gifn_apply/quilt.py
@@ -78,7 +78,11 @@
 
         change_id = _extract_change_id(patchfile)
         return Patch(
-            change_id=change_id, filename=filename, path=patchfile, relpath=relpath, repo=repo
+            change_id=change_id,
+            filename=filename,
+            path=patchfile,
+            relpath=relpath,
+            repo=repo,
         )
 
     if not cfg.series.is_file():
diff --git a/tools/git-if-needed/python/gifn_apply/repo_url.py b/tools/git-if-needed/python/gifn_apply/repo_url.py
index 3204811..af077e7 100644
--- a/tools/git-if-needed/python/gifn_apply/repo_url.py
+++ b/tools/git-if-needed/python/gifn_apply/repo_url.py
@@ -68,7 +68,9 @@
     """Make sure a http(s):// URL has a host, slash-terminate the path."""
     if not url.netloc:
         return RepoURLError(
-            name, value, ValueError("Expected a hostname for 'http' or 'https' URLs")
+            name,
+            value,
+            ValueError("Expected a hostname for 'http' or 'https' URLs"),
         )
 
     url = _slash_extend(url)
@@ -95,7 +97,9 @@
     validator = _SCHEME_VALIDATORS.get(url.scheme)
     if validator is None:
         return RepoURLError(
-            name, value, ValueError("Expected 'http', 'https', or 'file' as the URL scheme")
+            name,
+            value,
+            ValueError("Expected 'http', 'https', or 'file' as the URL scheme"),
         )
     return validator(name, value, url)
 
@@ -106,7 +110,7 @@
         environ = dict(os.environ)
 
     res: dict[str, RepoURLResult] = {
-        "OPENSTACK": RepoURLOK(defs.RepoURL(uparse.urlparse("https://github.com/openstack")))
+        "OPENSTACK": RepoURLOK(defs.RepoURL(uparse.urlparse("https://github.com/openstack"))),
     }
     for name, value in environ.items():
         base = util.str_removeprefix(name, "REPO_URL_")