Browse Source

Upgrade to python 3.7.

Jelmer Vernooij 2 years ago
parent
commit
f6faf9e187
81 changed files with 469 additions and 505 deletions
  1. 3 4
      docs/conf.py
  2. 2 3
      dulwich/archive.py
  3. 1 1
      dulwich/bundle.py
  4. 7 7
      dulwich/cli.py
  5. 26 26
      dulwich/client.py
  6. 3 3
      dulwich/cloud/gcs.py
  7. 4 4
      dulwich/config.py
  8. 2 3
      dulwich/contrib/diffstat.py
  9. 2 2
      dulwich/contrib/paramiko_vendor.py
  10. 2 2
      dulwich/contrib/release_robot.py
  11. 1 1
      dulwich/contrib/requests_vendor.py
  12. 7 7
      dulwich/contrib/swift.py
  13. 2 2
      dulwich/contrib/test_paramiko_vendor.py
  14. 7 7
      dulwich/contrib/test_swift.py
  15. 3 4
      dulwich/diff_tree.py
  16. 7 7
      dulwich/errors.py
  17. 1 1
      dulwich/fastexport.py
  18. 15 18
      dulwich/file.py
  19. 0 1
      dulwich/graph.py
  20. 3 4
      dulwich/greenthreads.py
  21. 1 1
      dulwich/hooks.py
  22. 9 9
      dulwich/ignore.py
  23. 6 7
      dulwich/index.py
  24. 1 1
      dulwich/lfs.py
  25. 1 1
      dulwich/line_ending.py
  26. 1 1
      dulwich/lru_cache.py
  27. 1 1
      dulwich/mailmap.py
  28. 15 19
      dulwich/object_store.py
  29. 15 15
      dulwich/objects.py
  30. 20 20
      dulwich/pack.py
  31. 5 5
      dulwich/patch.py
  32. 5 5
      dulwich/porcelain.py
  33. 6 7
      dulwich/protocol.py
  34. 7 7
      dulwich/refs.py
  35. 5 5
      dulwich/repo.py
  36. 14 14
      dulwich/server.py
  37. 1 2
      dulwich/stash.py
  38. 1 1
      dulwich/tests/__init__.py
  39. 4 4
      dulwich/tests/compat/server_utils.py
  40. 8 10
      dulwich/tests/compat/test_client.py
  41. 1 1
      dulwich/tests/compat/test_pack.py
  42. 1 1
      dulwich/tests/compat/test_patch.py
  43. 3 3
      dulwich/tests/compat/test_porcelain.py
  44. 4 4
      dulwich/tests/compat/test_repository.py
  45. 1 1
      dulwich/tests/compat/test_server.py
  46. 2 2
      dulwich/tests/compat/test_utils.py
  47. 2 2
      dulwich/tests/compat/test_web.py
  48. 4 4
      dulwich/tests/compat/utils.py
  49. 1 1
      dulwich/tests/test_archive.py
  50. 2 2
      dulwich/tests/test_blackbox.py
  51. 24 28
      dulwich/tests/test_client.py
  52. 3 3
      dulwich/tests/test_diff_tree.py
  53. 2 2
      dulwich/tests/test_fastexport.py
  54. 6 6
      dulwich/tests/test_file.py
  55. 4 4
      dulwich/tests/test_grafts.py
  56. 7 8
      dulwich/tests/test_graph.py
  57. 2 2
      dulwich/tests/test_greenthreads.py
  58. 1 1
      dulwich/tests/test_hooks.py
  59. 2 2
      dulwich/tests/test_ignore.py
  60. 12 13
      dulwich/tests/test_index.py
  61. 1 1
      dulwich/tests/test_lfs.py
  62. 0 1
      dulwich/tests/test_line_ending.py
  63. 6 6
      dulwich/tests/test_missing_obj_finder.py
  64. 7 7
      dulwich/tests/test_object_store.py
  65. 5 5
      dulwich/tests/test_objects.py
  66. 29 31
      dulwich/tests/test_pack.py
  67. 31 33
      dulwich/tests/test_porcelain.py
  68. 1 1
      dulwich/tests/test_protocol.py
  69. 0 1
      dulwich/tests/test_reflog.py
  70. 2 3
      dulwich/tests/test_refs.py
  71. 11 12
      dulwich/tests/test_repository.py
  72. 23 23
      dulwich/tests/test_server.py
  73. 1 1
      dulwich/tests/test_utils.py
  74. 4 4
      dulwich/tests/test_walk.py
  75. 22 24
      dulwich/tests/test_web.py
  76. 4 4
      dulwich/walk.py
  77. 10 11
      dulwich/web.py
  78. 1 1
      examples/clone.py
  79. 2 2
      examples/latest_change.py
  80. 1 1
      examples/rename-branch.py
  81. 0 1
      setup.py

+ 3 - 4
docs/conf.py

@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
 #
 #
 # dulwich documentation build configuration file, created by
 # dulwich documentation build configuration file, created by
 # sphinx-quickstart on Thu Feb 18 23:18:28 2010.
 # sphinx-quickstart on Thu Feb 18 23:18:28 2010.
@@ -48,8 +47,8 @@ source_suffix = '.txt'
 master_doc = 'index'
 master_doc = 'index'
 
 
 # General information about the project.
 # General information about the project.
-project = u'dulwich'
-copyright = u'2011-2019 Jelmer Vernooij'
+project = 'dulwich'
+copyright = '2011-2023 Jelmer Vernooij'
 
 
 # The version info for the project you're documenting, acts as replacement for
 # The version info for the project you're documenting, acts as replacement for
 # |version| and |release|, also used in various other places throughout the
 # |version| and |release|, also used in various other places throughout the
@@ -186,7 +185,7 @@ htmlhelp_basename = 'dulwichdoc'
 # (source start file, target name, title, author, documentclass
 # (source start file, target name, title, author, documentclass
 # [howto/manual]).
 # [howto/manual]).
 latex_documents = [
 latex_documents = [
-    ('index', 'dulwich.tex', u'dulwich Documentation',
+    ('index', 'dulwich.tex', 'dulwich Documentation',
      'Jelmer Vernooij', 'manual'),
      'Jelmer Vernooij', 'manual'),
 ]
 ]
 
 

+ 2 - 3
dulwich/archive.py

@@ -32,7 +32,7 @@ from io import BytesIO
 from contextlib import closing
 from contextlib import closing
 
 
 
 
-class ChunkedBytesIO(object):
+class ChunkedBytesIO:
     """Turn a list of bytestrings into a file-like object.
     """Turn a list of bytestrings into a file-like object.
 
 
     This is similar to creating a `BytesIO` from a concatenation of the
     This is similar to creating a `BytesIO` from a concatenation of the
@@ -129,7 +129,6 @@ def _walk_tree(store, tree, root=b""):
     for entry in tree.iteritems():
     for entry in tree.iteritems():
         entry_abspath = posixpath.join(root, entry.path)
         entry_abspath = posixpath.join(root, entry.path)
         if stat.S_ISDIR(entry.mode):
         if stat.S_ISDIR(entry.mode):
-            for _ in _walk_tree(store, store[entry.sha], entry_abspath):
-                yield _
+            yield from _walk_tree(store, store[entry.sha], entry_abspath)
         else:
         else:
             yield (entry_abspath, entry)
             yield (entry_abspath, entry)

+ 1 - 1
dulwich/bundle.py

@@ -25,7 +25,7 @@ from typing import Dict, List, Tuple, Optional, Union, Sequence
 from .pack import PackData, write_pack_data
 from .pack import PackData, write_pack_data
 
 
 
 
-class Bundle(object):
+class Bundle:
 
 
     version: Optional[int] = None
     version: Optional[int] = None
 
 

+ 7 - 7
dulwich/cli.py

@@ -55,7 +55,7 @@ def signal_quit(signal, frame):
     pdb.set_trace()
     pdb.set_trace()
 
 
 
 
-class Command(object):
+class Command:
     """A Dulwich subcommand."""
     """A Dulwich subcommand."""
 
 
     def run(self, args):
     def run(self, args):
@@ -139,7 +139,7 @@ class cmd_fsck(Command):
         opts, args = getopt(args, "", [])
         opts, args = getopt(args, "", [])
         opts = dict(opts)
         opts = dict(opts)
         for (obj, msg) in porcelain.fsck("."):
         for (obj, msg) in porcelain.fsck("."):
-            print("%s: %s" % (obj, msg))
+            print("{}: {}".format(obj, msg))
 
 
 
 
 class cmd_log(Command):
 class cmd_log(Command):
@@ -202,9 +202,9 @@ class cmd_dump_pack(Command):
             try:
             try:
                 print("\t%s" % x[name])
                 print("\t%s" % x[name])
             except KeyError as k:
             except KeyError as k:
-                print("\t%s: Unable to resolve base %s" % (name, k))
+                print("\t{}: Unable to resolve base {}".format(name, k))
             except ApplyDeltaError as e:
             except ApplyDeltaError as e:
-                print("\t%s: Unable to apply delta: %r" % (name, e))
+                print("\t{}: Unable to apply delta: {!r}".format(name, e))
 
 
 
 
 class cmd_dump_index(Command):
 class cmd_dump_index(Command):
@@ -483,7 +483,7 @@ class cmd_status(Command):
             for kind, names in status.staged.items():
             for kind, names in status.staged.items():
                 for name in names:
                 for name in names:
                     sys.stdout.write(
                     sys.stdout.write(
-                        "\t%s: %s\n" % (kind, name.decode(sys.getfilesystemencoding()))
+                        "\t{}: {}\n".format(kind, name.decode(sys.getfilesystemencoding()))
                     )
                     )
             sys.stdout.write("\n")
             sys.stdout.write("\n")
         if status.unstaged:
         if status.unstaged:
@@ -506,7 +506,7 @@ class cmd_ls_remote(Command):
             sys.exit(1)
             sys.exit(1)
         refs = porcelain.ls_remote(args[0])
         refs = porcelain.ls_remote(args[0])
         for ref in sorted(refs):
         for ref in sorted(refs):
-            sys.stdout.write("%s\t%s\n" % (ref, refs[ref]))
+            sys.stdout.write("{}\t{}\n".format(ref, refs[ref]))
 
 
 
 
 class cmd_ls_tree(Command):
 class cmd_ls_tree(Command):
@@ -630,7 +630,7 @@ class cmd_submodule_list(Command):
         parser = argparse.ArgumentParser()
         parser = argparse.ArgumentParser()
         parser.parse_args(argv)
         parser.parse_args(argv)
         for path, sha in porcelain.submodule_list("."):
         for path, sha in porcelain.submodule_list("."):
-            sys.stdout.write(' %s %s\n' % (sha, path))
+            sys.stdout.write(' {} {}\n'.format(sha, path))
 
 
 
 
 class cmd_submodule_init(Command):
 class cmd_submodule_init(Command):

+ 26 - 26
dulwich/client.py

@@ -194,7 +194,7 @@ RECEIVE_CAPABILITIES = [
 ] + COMMON_CAPABILITIES
 ] + COMMON_CAPABILITIES
 
 
 
 
-class ReportStatusParser(object):
+class ReportStatusParser:
     """Handle status as reported by servers with 'report-status' capability."""
     """Handle status as reported by servers with 'report-status' capability."""
 
 
     def __init__(self):
     def __init__(self):
@@ -258,13 +258,13 @@ def read_pkt_refs(pkt_seq):
         refs[ref] = sha
         refs[ref] = sha
 
 
     if len(refs) == 0:
     if len(refs) == 0:
-        return {}, set([])
+        return {}, set()
     if refs == {CAPABILITIES_REF: ZERO_SHA}:
     if refs == {CAPABILITIES_REF: ZERO_SHA}:
         refs = {}
         refs = {}
     return refs, set(server_capabilities)
     return refs, set(server_capabilities)
 
 
 
 
-class FetchPackResult(object):
+class FetchPackResult:
     """Result of a fetch-pack operation.
     """Result of a fetch-pack operation.
 
 
     Attributes:
     Attributes:
@@ -336,10 +336,10 @@ class FetchPackResult(object):
         if name in type(self)._FORWARDED_ATTRS:
         if name in type(self)._FORWARDED_ATTRS:
             self._warn_deprecated()
             self._warn_deprecated()
             return getattr(self.refs, name)
             return getattr(self.refs, name)
-        return super(FetchPackResult, self).__getattribute__(name)
+        return super().__getattribute__(name)
 
 
     def __repr__(self):
     def __repr__(self):
-        return "%s(%r, %r, %r)" % (
+        return "{}({!r}, {!r}, {!r})".format(
             self.__class__.__name__,
             self.__class__.__name__,
             self.refs,
             self.refs,
             self.symrefs,
             self.symrefs,
@@ -347,7 +347,7 @@ class FetchPackResult(object):
         )
         )
 
 
 
 
-class SendPackResult(object):
+class SendPackResult:
     """Result of a upload-pack operation.
     """Result of a upload-pack operation.
 
 
     Attributes:
     Attributes:
@@ -414,10 +414,10 @@ class SendPackResult(object):
         if name in type(self)._FORWARDED_ATTRS:
         if name in type(self)._FORWARDED_ATTRS:
             self._warn_deprecated()
             self._warn_deprecated()
             return getattr(self.refs, name)
             return getattr(self.refs, name)
-        return super(SendPackResult, self).__getattribute__(name)
+        return super().__getattribute__(name)
 
 
     def __repr__(self):
     def __repr__(self):
-        return "%s(%r, %r)" % (self.__class__.__name__, self.refs, self.agent)
+        return "{}({!r}, {!r})".format(self.__class__.__name__, self.refs, self.agent)
 
 
 
 
 def _read_shallow_updates(pkt_seq):
 def _read_shallow_updates(pkt_seq):
@@ -434,7 +434,7 @@ def _read_shallow_updates(pkt_seq):
     return (new_shallow, new_unshallow)
     return (new_shallow, new_unshallow)
 
 
 
 
-class _v1ReceivePackHeader(object):
+class _v1ReceivePackHeader:
 
 
     def __init__(self, capabilities, old_refs, new_refs):
     def __init__(self, capabilities, old_refs, new_refs):
         self.want = []
         self.want = []
@@ -464,12 +464,12 @@ class _v1ReceivePackHeader(object):
             old_sha1 = old_refs.get(refname, ZERO_SHA)
             old_sha1 = old_refs.get(refname, ZERO_SHA)
             if not isinstance(old_sha1, bytes):
             if not isinstance(old_sha1, bytes):
                 raise TypeError(
                 raise TypeError(
-                    "old sha1 for %s is not a bytestring: %r" % (refname, old_sha1)
+                    "old sha1 for {!r} is not a bytestring: {!r}".format(refname, old_sha1)
                 )
                 )
             new_sha1 = new_refs.get(refname, ZERO_SHA)
             new_sha1 = new_refs.get(refname, ZERO_SHA)
             if not isinstance(new_sha1, bytes):
             if not isinstance(new_sha1, bytes):
                 raise TypeError(
                 raise TypeError(
-                    "old sha1 for %s is not a bytestring %r" % (refname, new_sha1)
+                    "old sha1 for {!r} is not a bytestring {!r}".format(refname, new_sha1)
                 )
                 )
 
 
             if old_sha1 != new_sha1:
             if old_sha1 != new_sha1:
@@ -643,7 +643,7 @@ def _handle_upload_pack_tail(
 # TODO(durin42): this doesn't correctly degrade if the server doesn't
 # TODO(durin42): this doesn't correctly degrade if the server doesn't
 # support some capabilities. This should work properly with servers
 # support some capabilities. This should work properly with servers
 # that don't support multi_ack.
 # that don't support multi_ack.
-class GitClient(object):
+class GitClient:
     """Git smart server client."""
     """Git smart server client."""
 
 
     def __init__(
     def __init__(
@@ -1012,7 +1012,7 @@ class TraditionalGitClient(GitClient):
 
 
     def __init__(self, path_encoding=DEFAULT_ENCODING, **kwargs):
     def __init__(self, path_encoding=DEFAULT_ENCODING, **kwargs):
         self._remote_path_encoding = path_encoding
         self._remote_path_encoding = path_encoding
-        super(TraditionalGitClient, self).__init__(**kwargs)
+        super().__init__(**kwargs)
 
 
     async def _connect(self, cmd, path):
     async def _connect(self, cmd, path):
         """Create a connection to the server.
         """Create a connection to the server.
@@ -1255,7 +1255,7 @@ class TCPGitClient(TraditionalGitClient):
             port = TCP_GIT_PORT
             port = TCP_GIT_PORT
         self._host = host
         self._host = host
         self._port = port
         self._port = port
-        super(TCPGitClient, self).__init__(**kwargs)
+        super().__init__(**kwargs)
 
 
     @classmethod
     @classmethod
     def from_parsedurl(cls, parsedurl, **kwargs):
     def from_parsedurl(cls, parsedurl, **kwargs):
@@ -1283,7 +1283,7 @@ class TCPGitClient(TraditionalGitClient):
             try:
             try:
                 s.connect(sockaddr)
                 s.connect(sockaddr)
                 break
                 break
-            except socket.error as e:
+            except OSError as e:
                 err = e
                 err = e
                 if s is not None:
                 if s is not None:
                     s.close()
                     s.close()
@@ -1313,7 +1313,7 @@ class TCPGitClient(TraditionalGitClient):
         return proto, lambda: _fileno_can_read(s), None
         return proto, lambda: _fileno_can_read(s), None
 
 
 
 
-class SubprocessWrapper(object):
+class SubprocessWrapper:
     """A socket-like object that talks to a subprocess via pipes."""
     """A socket-like object that talks to a subprocess via pipes."""
 
 
     def __init__(self, proc):
     def __init__(self, proc):
@@ -1472,7 +1472,7 @@ class LocalGitClient(GitClient):
                 old_sha1 = old_refs.get(refname, ZERO_SHA)
                 old_sha1 = old_refs.get(refname, ZERO_SHA)
                 if new_sha1 != ZERO_SHA:
                 if new_sha1 != ZERO_SHA:
                     if not target.refs.set_if_equals(refname, old_sha1, new_sha1):
                     if not target.refs.set_if_equals(refname, old_sha1, new_sha1):
-                        msg = "unable to set %s to %s" % (refname, new_sha1)
+                        msg = "unable to set {} to {}".format(refname, new_sha1)
                         progress(msg)
                         progress(msg)
                         ref_status[refname] = msg
                         ref_status[refname] = msg
                 else:
                 else:
@@ -1557,7 +1557,7 @@ class LocalGitClient(GitClient):
 default_local_git_client_cls = LocalGitClient
 default_local_git_client_cls = LocalGitClient
 
 
 
 
-class SSHVendor(object):
+class SSHVendor:
     """A client side SSH implementation."""
     """A client side SSH implementation."""
 
 
     def run_command(
     def run_command(
@@ -1594,7 +1594,7 @@ class StrangeHostname(Exception):
     """Refusing to connect to strange SSH hostname."""
     """Refusing to connect to strange SSH hostname."""
 
 
     def __init__(self, hostname):
     def __init__(self, hostname):
-        super(StrangeHostname, self).__init__(hostname)
+        super().__init__(hostname)
 
 
 
 
 class SubprocessSSHVendor(SSHVendor):
 class SubprocessSSHVendor(SSHVendor):
@@ -1630,7 +1630,7 @@ class SubprocessSSHVendor(SSHVendor):
             args.extend(["-i", str(key_filename)])
             args.extend(["-i", str(key_filename)])
 
 
         if username:
         if username:
-            host = "%s@%s" % (username, host)
+            host = "{}@{}".format(username, host)
         if host.startswith("-"):
         if host.startswith("-"):
             raise StrangeHostname(hostname=host)
             raise StrangeHostname(hostname=host)
         args.append(host)
         args.append(host)
@@ -1684,7 +1684,7 @@ class PLinkSSHVendor(SSHVendor):
             args.extend(["-i", str(key_filename)])
             args.extend(["-i", str(key_filename)])
 
 
         if username:
         if username:
-            host = "%s@%s" % (username, host)
+            host = "{}@{}".format(username, host)
         if host.startswith("-"):
         if host.startswith("-"):
             raise StrangeHostname(hostname=host)
             raise StrangeHostname(hostname=host)
         args.append(host)
         args.append(host)
@@ -1736,7 +1736,7 @@ class SSHGitClient(TraditionalGitClient):
         self.ssh_command = ssh_command or os.environ.get(
         self.ssh_command = ssh_command or os.environ.get(
             "GIT_SSH_COMMAND", os.environ.get("GIT_SSH")
             "GIT_SSH_COMMAND", os.environ.get("GIT_SSH")
         )
         )
-        super(SSHGitClient, self).__init__(**kwargs)
+        super().__init__(**kwargs)
         self.alternative_paths = {}
         self.alternative_paths = {}
         if vendor is not None:
         if vendor is not None:
             self.ssh_vendor = vendor
             self.ssh_vendor = vendor
@@ -2195,14 +2195,14 @@ class AbstractHttpGitClient(GitClient):
             kwargs["username"] = urlunquote(username)
             kwargs["username"] = urlunquote(username)
         netloc = parsedurl.hostname
         netloc = parsedurl.hostname
         if parsedurl.port:
         if parsedurl.port:
-            netloc = "%s:%s" % (netloc, parsedurl.port)
+            netloc = "{}:{}".format(netloc, parsedurl.port)
         if parsedurl.username:
         if parsedurl.username:
-            netloc = "%s@%s" % (parsedurl.username, netloc)
+            netloc = "{}@{}".format(parsedurl.username, netloc)
         parsedurl = parsedurl._replace(netloc=netloc)
         parsedurl = parsedurl._replace(netloc=netloc)
         return cls(urlunparse(parsedurl), **kwargs)
         return cls(urlunparse(parsedurl), **kwargs)
 
 
     def __repr__(self):
     def __repr__(self):
-        return "%s(%r, dumb=%r)" % (
+        return "{}({!r}, dumb={!r})".format(
             type(self).__name__,
             type(self).__name__,
             self._base_url,
             self._base_url,
             self.dumb,
             self.dumb,
@@ -2239,7 +2239,7 @@ class Urllib3HttpGitClient(AbstractHttpGitClient):
 
 
         self.config = config
         self.config = config
 
 
-        super(Urllib3HttpGitClient, self).__init__(
+        super().__init__(
             base_url=base_url, dumb=dumb, **kwargs)
             base_url=base_url, dumb=dumb, **kwargs)
 
 
     def _get_url(self, path):
     def _get_url(self, path):

+ 3 - 3
dulwich/cloud/gcs.py

@@ -34,12 +34,12 @@ from ..pack import PackData, Pack, load_pack_index_file
 class GcsObjectStore(BucketBasedObjectStore):
 class GcsObjectStore(BucketBasedObjectStore):
 
 
     def __init__(self, bucket, subpath=''):
     def __init__(self, bucket, subpath=''):
-        super(GcsObjectStore, self).__init__()
+        super().__init__()
         self.bucket = bucket
         self.bucket = bucket
         self.subpath = subpath
         self.subpath = subpath
 
 
     def __repr__(self):
     def __repr__(self):
-        return "%s(%r, subpath=%r)" % (
+        return "{}({!r}, subpath={!r})".format(
             type(self).__name__, self.bucket, self.subpath)
             type(self).__name__, self.bucket, self.subpath)
 
 
     def _remove_pack(self, name):
     def _remove_pack(self, name):
@@ -53,7 +53,7 @@ class GcsObjectStore(BucketBasedObjectStore):
             name, ext = posixpath.splitext(posixpath.basename(blob.name))
             name, ext = posixpath.splitext(posixpath.basename(blob.name))
             packs.setdefault(name, set()).add(ext)
             packs.setdefault(name, set()).add(ext)
         for name, exts in packs.items():
         for name, exts in packs.items():
-            if exts == set(['.pack', '.idx']):
+            if exts == {'.pack', '.idx'}:
                 yield name
                 yield name
 
 
     def _load_pack_data(self, name):
     def _load_pack_data(self, name):

+ 4 - 4
dulwich/config.py

@@ -145,7 +145,7 @@ Value = bytes
 ValueLike = Union[bytes, str]
 ValueLike = Union[bytes, str]
 
 
 
 
-class Config(object):
+class Config:
     """A Git configuration."""
     """A Git configuration."""
 
 
     def get(self, section: SectionLike, name: NameLike) -> Value:
     def get(self, section: SectionLike, name: NameLike) -> Value:
@@ -265,7 +265,7 @@ class ConfigDict(Config, MutableMapping[Section, MutableMapping[Name, Value]]):
         self._values = CaseInsensitiveOrderedMultiDict.make(values)
         self._values = CaseInsensitiveOrderedMultiDict.make(values)
 
 
     def __repr__(self) -> str:
     def __repr__(self) -> str:
-        return "%s(%r)" % (self.__class__.__name__, self._values)
+        return "{}({!r})".format(self.__class__.__name__, self._values)
 
 
     def __eq__(self, other: object) -> bool:
     def __eq__(self, other: object) -> bool:
         return isinstance(other, self.__class__) and other._values == self._values
         return isinstance(other, self.__class__) and other._values == self._values
@@ -534,7 +534,7 @@ class ConfigFile(ConfigDict):
         ] = None,
         ] = None,
         encoding: Union[str, None] = None
         encoding: Union[str, None] = None
     ) -> None:
     ) -> None:
-        super(ConfigFile, self).__init__(values=values, encoding=encoding)
+        super().__init__(values=values, encoding=encoding)
         self.path: Optional[str] = None
         self.path: Optional[str] = None
 
 
     @classmethod  # noqa: C901
     @classmethod  # noqa: C901
@@ -687,7 +687,7 @@ class StackedConfig(Config):
         self.writable = writable
         self.writable = writable
 
 
     def __repr__(self) -> str:
     def __repr__(self) -> str:
-        return "<%s for %r>" % (self.__class__.__name__, self.backends)
+        return "<{} for {!r}>".format(self.__class__.__name__, self.backends)
 
 
     @classmethod
     @classmethod
     def default(cls) -> "StackedConfig":
     def default(cls) -> "StackedConfig":

+ 2 - 3
dulwich/contrib/diffstat.py

@@ -1,5 +1,4 @@
 #!/usr/bin/env python
 #!/usr/bin/env python
-# -*- coding: utf-8 -*-
 # vim:ts=4:sw=4:softtabstop=4:smarttab:expandtab
 # vim:ts=4:sw=4:softtabstop=4:smarttab:expandtab
 
 
 # Copyright (c) 2020 Kevin B. Hendricks, Stratford Ontario Canada
 # Copyright (c) 2020 Kevin B. Hendricks, Stratford Ontario Canada
@@ -35,7 +34,7 @@
 
 
 import sys
 import sys
 import re
 import re
-from typing import Optional
+from typing import Optional, Tuple, List
 
 
 # only needs to detect git style diffs as this is for
 # only needs to detect git style diffs as this is for
 # use with dulwich
 # use with dulwich
@@ -56,7 +55,7 @@ _GIT_UNCHANGED_START = b" "
 # properly interface with diffstat routine
 # properly interface with diffstat routine
 
 
 
 
-def _parse_patch(lines):
+def _parse_patch(lines: List[bytes]) -> Tuple[List[bytes], List[bool], List[Tuple[int, int]]]:
     """Parse a git style diff or patch to generate diff stats.
     """Parse a git style diff or patch to generate diff stats.
 
 
     Args:
     Args:

+ 2 - 2
dulwich/contrib/paramiko_vendor.py

@@ -34,7 +34,7 @@ import paramiko
 import paramiko.client
 import paramiko.client
 
 
 
 
-class _ParamikoWrapper(object):
+class _ParamikoWrapper:
     def __init__(self, client, channel):
     def __init__(self, client, channel):
         self.client = client
         self.client = client
         self.channel = channel
         self.channel = channel
@@ -70,7 +70,7 @@ class _ParamikoWrapper(object):
         self.channel.close()
         self.channel.close()
 
 
 
 
-class ParamikoSSHVendor(object):
+class ParamikoSSHVendor:
     # http://docs.paramiko.org/en/2.4/api/client.html
     # http://docs.paramiko.org/en/2.4/api/client.html
 
 
     def __init__(self, **kwargs):
     def __init__(self, **kwargs):

+ 2 - 2
dulwich/contrib/release_robot.py

@@ -78,11 +78,11 @@ def get_recent_tags(projdir=PROJDIR):
             obj = project.get_object(value)  # dulwich object from SHA-1
             obj = project.get_object(value)  # dulwich object from SHA-1
             # don't just check if object is "tag" b/c it could be a "commit"
             # don't just check if object is "tag" b/c it could be a "commit"
             # instead check if "tags" is in the ref-name
             # instead check if "tags" is in the ref-name
-            if u"tags" not in key:
+            if "tags" not in key:
                 # skip ref if not a tag
                 # skip ref if not a tag
                 continue
                 continue
             # strip the leading text from refs to get "tag name"
             # strip the leading text from refs to get "tag name"
-            _, tag = key.rsplit(u"/", 1)
+            _, tag = key.rsplit("/", 1)
             # check if tag object is "commit" or "tag" pointing to a "commit"
             # check if tag object is "commit" or "tag" pointing to a "commit"
             try:
             try:
                 commit = obj.object  # a tuple (commit class, commit id)
                 commit = obj.object  # a tuple (commit class, commit id)

+ 1 - 1
dulwich/contrib/requests_vendor.py

@@ -55,7 +55,7 @@ class RequestsHttpGitClient(AbstractHttpGitClient):
         if username is not None:
         if username is not None:
             self.session.auth = (username, password)
             self.session.auth = (username, password)
 
 
-        super(RequestsHttpGitClient, self).__init__(
+        super().__init__(
             base_url=base_url, dumb=dumb, **kwargs)
             base_url=base_url, dumb=dumb, **kwargs)
 
 
     def _http_request(self, url, headers=None, data=None, allow_compression=False):
     def _http_request(self, url, headers=None, data=None, allow_compression=False):

+ 7 - 7
dulwich/contrib/swift.py

@@ -234,7 +234,7 @@ class SwiftException(Exception):
     pass
     pass
 
 
 
 
-class SwiftConnector(object):
+class SwiftConnector:
     """A Connector to swift that manage authentication and errors catching"""
     """A Connector to swift that manage authentication and errors catching"""
 
 
     def __init__(self, root, conf):
     def __init__(self, root, conf):
@@ -501,7 +501,7 @@ class SwiftConnector(object):
             )
             )
 
 
 
 
-class SwiftPackReader(object):
+class SwiftPackReader:
     """A SwiftPackReader that mimic read and sync method
     """A SwiftPackReader that mimic read and sync method
 
 
     The reader allows to read a specified amount of bytes from
     The reader allows to read a specified amount of bytes from
@@ -532,7 +532,7 @@ class SwiftPackReader(object):
             self.buff_length = self.buff_length * 2
             self.buff_length = self.buff_length * 2
         offset = self.base_offset
         offset = self.base_offset
         r = min(self.base_offset + self.buff_length, self.pack_length)
         r = min(self.base_offset + self.buff_length, self.pack_length)
-        ret = self.scon.get_object(self.filename, range="%s-%s" % (offset, r))
+        ret = self.scon.get_object(self.filename, range="{}-{}".format(offset, r))
         self.buff = ret
         self.buff = ret
 
 
     def read(self, length):
     def read(self, length):
@@ -629,7 +629,7 @@ class SwiftPack(Pack):
     def __init__(self, *args, **kwargs):
     def __init__(self, *args, **kwargs):
         self.scon = kwargs["scon"]
         self.scon = kwargs["scon"]
         del kwargs["scon"]
         del kwargs["scon"]
-        super(SwiftPack, self).__init__(*args, **kwargs)
+        super().__init__(*args, **kwargs)
         self._pack_info_path = self._basename + ".info"
         self._pack_info_path = self._basename + ".info"
         self._pack_info = None
         self._pack_info = None
         self._pack_info_load = lambda: load_pack_info(self._pack_info_path, self.scon)
         self._pack_info_load = lambda: load_pack_info(self._pack_info_path, self.scon)
@@ -657,7 +657,7 @@ class SwiftObjectStore(PackBasedObjectStore):
         Args:
         Args:
           scon: A `SwiftConnector` instance
           scon: A `SwiftConnector` instance
         """
         """
-        super(SwiftObjectStore, self).__init__()
+        super().__init__()
         self.scon = scon
         self.scon = scon
         self.root = self.scon.root
         self.root = self.scon.root
         self.pack_dir = posixpath.join(OBJECTDIR, PACKDIR)
         self.pack_dir = posixpath.join(OBJECTDIR, PACKDIR)
@@ -860,7 +860,7 @@ class SwiftInfoRefsContainer(InfoRefsContainer):
         f = self.scon.get_object(self.filename)
         f = self.scon.get_object(self.filename)
         if not f:
         if not f:
             f = BytesIO(b"")
             f = BytesIO(b"")
-        super(SwiftInfoRefsContainer, self).__init__(f)
+        super().__init__(f)
 
 
     def _load_check_ref(self, name, old_ref):
     def _load_check_ref(self, name, old_ref):
         self._check_refname(name)
         self._check_refname(name)
@@ -1066,7 +1066,7 @@ def main(argv=sys.argv):
     }
     }
 
 
     if len(sys.argv) < 2:
     if len(sys.argv) < 2:
-        print("Usage: %s <%s> [OPTIONS...]" % (sys.argv[0], "|".join(commands.keys())))
+        print("Usage: {} <{}> [OPTIONS...]".format(sys.argv[0], "|".join(commands.keys())))
         sys.exit(1)
         sys.exit(1)
 
 
     cmd = sys.argv[1]
     cmd = sys.argv[1]

+ 2 - 2
dulwich/contrib/test_paramiko_vendor.py

@@ -38,7 +38,7 @@ else:
     class Server(paramiko.ServerInterface):
     class Server(paramiko.ServerInterface):
         """http://docs.paramiko.org/en/2.4/api/server.html"""
         """http://docs.paramiko.org/en/2.4/api/server.html"""
         def __init__(self, commands, *args, **kwargs):
         def __init__(self, commands, *args, **kwargs):
-            super(Server, self).__init__(*args, **kwargs)
+            super().__init__(*args, **kwargs)
             self.commands = commands
             self.commands = commands
 
 
         def check_channel_exec_request(self, channel, command):
         def check_channel_exec_request(self, channel, command):
@@ -152,7 +152,7 @@ class ParamikoSSHVendorTests(TestCase):
     def _run(self):
     def _run(self):
         try:
         try:
             conn, addr = self.socket.accept()
             conn, addr = self.socket.accept()
-        except socket.error:
+        except OSError:
             return False
             return False
         self.transport = paramiko.Transport(conn)
         self.transport = paramiko.Transport(conn)
         self.addCleanup(self.transport.close)
         self.addCleanup(self.transport.close)

+ 7 - 7
dulwich/contrib/test_swift.py

@@ -99,7 +99,7 @@ def create_swift_connector(store={}):
     return lambda root, conf: FakeSwiftConnector(root, conf=conf, store=store)
     return lambda root, conf: FakeSwiftConnector(root, conf=conf, store=store)
 
 
 
 
-class Response(object):
+class Response:
     def __init__(self, headers={}, status=200, content=None):
     def __init__(self, headers={}, status=200, content=None):
         self.headers = headers
         self.headers = headers
         self.status_code = status
         self.status_code = status
@@ -183,14 +183,14 @@ def create_commit(data, marker=b"Default", blob=None):
 def create_commits(length=1, marker=b"Default"):
 def create_commits(length=1, marker=b"Default"):
     data = []
     data = []
     for i in range(0, length):
     for i in range(0, length):
-        _marker = ("%s_%s" % (marker, i)).encode()
+        _marker = ("{}_{}".format(marker, i)).encode()
         blob, tree, tag, cmt = create_commit(data, _marker)
         blob, tree, tag, cmt = create_commit(data, _marker)
         data.extend([blob, tree, tag, cmt])
         data.extend([blob, tree, tag, cmt])
     return data
     return data
 
 
 
 
 @skipIf(missing_libs, skipmsg)
 @skipIf(missing_libs, skipmsg)
-class FakeSwiftConnector(object):
+class FakeSwiftConnector:
     def __init__(self, root, conf, store=None):
     def __init__(self, root, conf, store=None):
         if store:
         if store:
             self.store = store
             self.store = store
@@ -246,7 +246,7 @@ class FakeSwiftConnector(object):
 @skipIf(missing_libs, skipmsg)
 @skipIf(missing_libs, skipmsg)
 class TestSwiftRepo(TestCase):
 class TestSwiftRepo(TestCase):
     def setUp(self):
     def setUp(self):
-        super(TestSwiftRepo, self).setUp()
+        super().setUp()
         self.conf = swift.load_conf(file=StringIO(config_file % def_config_file))
         self.conf = swift.load_conf(file=StringIO(config_file % def_config_file))
 
 
     def test_init(self):
     def test_init(self):
@@ -302,7 +302,7 @@ class TestSwiftRepo(TestCase):
 @skipIf(missing_libs, skipmsg)
 @skipIf(missing_libs, skipmsg)
 class TestSwiftInfoRefsContainer(TestCase):
 class TestSwiftInfoRefsContainer(TestCase):
     def setUp(self):
     def setUp(self):
-        super(TestSwiftInfoRefsContainer, self).setUp()
+        super().setUp()
         content = (
         content = (
             b"22effb216e3a82f97da599b8885a6cadb488b4c5\trefs/heads/master\n"
             b"22effb216e3a82f97da599b8885a6cadb488b4c5\trefs/heads/master\n"
             b"cca703b0e1399008b53a1a236d6b4584737649e4\trefs/heads/dev"
             b"cca703b0e1399008b53a1a236d6b4584737649e4\trefs/heads/dev"
@@ -343,7 +343,7 @@ class TestSwiftInfoRefsContainer(TestCase):
 @skipIf(missing_libs, skipmsg)
 @skipIf(missing_libs, skipmsg)
 class TestSwiftConnector(TestCase):
 class TestSwiftConnector(TestCase):
     def setUp(self):
     def setUp(self):
-        super(TestSwiftConnector, self).setUp()
+        super().setUp()
         self.conf = swift.load_conf(file=StringIO(config_file % def_config_file))
         self.conf = swift.load_conf(file=StringIO(config_file % def_config_file))
         with patch("geventhttpclient.HTTPClient.request", fake_auth_request_v1):
         with patch("geventhttpclient.HTTPClient.request", fake_auth_request_v1):
             self.conn = swift.SwiftConnector("fakerepo", conf=self.conf)
             self.conn = swift.SwiftConnector("fakerepo", conf=self.conf)
@@ -409,7 +409,7 @@ class TestSwiftConnector(TestCase):
         with patch(
         with patch(
             "geventhttpclient.HTTPClient.request",
             "geventhttpclient.HTTPClient.request",
             lambda *args: Response(
             lambda *args: Response(
-                content=json.dumps((({"name": "a"}, {"name": "b"})))
+                content=json.dumps(({"name": "a"}, {"name": "b"}))
             ),
             ),
         ):
         ):
             self.assertEqual(len(self.conn.get_container_objects()), 2)
             self.assertEqual(len(self.conn.get_container_objects()), 2)

+ 3 - 4
dulwich/diff_tree.py

@@ -191,13 +191,12 @@ def tree_changes(
         source and target tree.
         source and target tree.
     """
     """
     if rename_detector is not None and tree1_id is not None and tree2_id is not None:
     if rename_detector is not None and tree1_id is not None and tree2_id is not None:
-        for change in rename_detector.changes_with_renames(
+        yield from rename_detector.changes_with_renames(
             tree1_id,
             tree1_id,
             tree2_id,
             tree2_id,
             want_unchanged=want_unchanged,
             want_unchanged=want_unchanged,
             include_trees=include_trees,
             include_trees=include_trees,
-        ):
-            yield change
+        )
         return
         return
 
 
     entries = walk_trees(
     entries = walk_trees(
@@ -402,7 +401,7 @@ def _tree_change_key(entry):
     return (path1, path2)
     return (path1, path2)
 
 
 
 
-class RenameDetector(object):
+class RenameDetector:
     """Object for handling rename detection between two trees."""
     """Object for handling rename detection between two trees."""
 
 
     def __init__(
     def __init__(

+ 7 - 7
dulwich/errors.py

@@ -43,12 +43,12 @@ class ChecksumMismatch(Exception):
         if self.extra is None:
         if self.extra is None:
             Exception.__init__(
             Exception.__init__(
                 self,
                 self,
-                "Checksum mismatch: Expected %s, got %s" % (expected, got),
+                "Checksum mismatch: Expected {}, got {}".format(expected, got),
             )
             )
         else:
         else:
             Exception.__init__(
             Exception.__init__(
                 self,
                 self,
-                "Checksum mismatch: Expected %s, got %s; %s" % (expected, got, extra),
+                "Checksum mismatch: Expected {}, got {}; {}".format(expected, got, extra),
             )
             )
 
 
 
 
@@ -64,7 +64,7 @@ class WrongObjectException(Exception):
     type_name: str
     type_name: str
 
 
     def __init__(self, sha, *args, **kwargs):
     def __init__(self, sha, *args, **kwargs):
-        Exception.__init__(self, "%s is not a %s" % (sha, self.type_name))
+        Exception.__init__(self, "{} is not a {}".format(sha, self.type_name))
 
 
 
 
 class NotCommitError(WrongObjectException):
 class NotCommitError(WrongObjectException):
@@ -142,7 +142,7 @@ class UpdateRefsError(GitProtocolError):
 
 
     def __init__(self, *args, **kwargs):
     def __init__(self, *args, **kwargs):
         self.ref_status = kwargs.pop("ref_status")
         self.ref_status = kwargs.pop("ref_status")
-        super(UpdateRefsError, self).__init__(*args, **kwargs)
+        super().__init__(*args, **kwargs)
 
 
 
 
 class HangupException(GitProtocolError):
 class HangupException(GitProtocolError):
@@ -150,13 +150,13 @@ class HangupException(GitProtocolError):
 
 
     def __init__(self, stderr_lines=None):
     def __init__(self, stderr_lines=None):
         if stderr_lines:
         if stderr_lines:
-            super(HangupException, self).__init__(
+            super().__init__(
                 "\n".join(
                 "\n".join(
                     [line.decode("utf-8", "surrogateescape") for line in stderr_lines]
                     [line.decode("utf-8", "surrogateescape") for line in stderr_lines]
                 )
                 )
             )
             )
         else:
         else:
-            super(HangupException, self).__init__(
+            super().__init__(
                 "The remote server unexpectedly closed the connection."
                 "The remote server unexpectedly closed the connection."
             )
             )
         self.stderr_lines = stderr_lines
         self.stderr_lines = stderr_lines
@@ -173,7 +173,7 @@ class UnexpectedCommandError(GitProtocolError):
             command = "flush-pkt"
             command = "flush-pkt"
         else:
         else:
             command = "command %s" % command
             command = "command %s" % command
-        super(UnexpectedCommandError, self).__init__(
+        super().__init__(
             "Protocol got unexpected %s" % command
             "Protocol got unexpected %s" % command
         )
         )
 
 

+ 1 - 1
dulwich/fastexport.py

@@ -45,7 +45,7 @@ def split_email(text):
     return (name, email.rstrip(b">"))
     return (name, email.rstrip(b">"))
 
 
 
 
-class GitFastExporter(object):
+class GitFastExporter:
     """Generate a fast-export output stream for Git objects."""
     """Generate a fast-export output stream for Git objects."""
 
 
     def __init__(self, outf, store):
     def __init__(self, outf, store):

+ 15 - 18
dulwich/file.py

@@ -20,7 +20,6 @@
 
 
 """Safe access to git files."""
 """Safe access to git files."""
 
 
-import io
 import os
 import os
 import sys
 import sys
 
 
@@ -83,15 +82,15 @@ def GitFile(filename, mode="rb", bufsize=-1, mask=0o644):
 
 
     """
     """
     if "a" in mode:
     if "a" in mode:
-        raise IOError("append mode not supported for Git files")
+        raise OSError("append mode not supported for Git files")
     if "+" in mode:
     if "+" in mode:
-        raise IOError("read/write mode not supported for Git files")
+        raise OSError("read/write mode not supported for Git files")
     if "b" not in mode:
     if "b" not in mode:
-        raise IOError("text mode not supported for Git files")
+        raise OSError("text mode not supported for Git files")
     if "w" in mode:
     if "w" in mode:
         return _GitFile(filename, mode, bufsize, mask)
         return _GitFile(filename, mode, bufsize, mask)
     else:
     else:
-        return io.open(filename, mode, bufsize)
+        return open(filename, mode, bufsize)
 
 
 
 
 class FileLocked(Exception):
 class FileLocked(Exception):
@@ -100,10 +99,10 @@ class FileLocked(Exception):
     def __init__(self, filename, lockfilename):
     def __init__(self, filename, lockfilename):
         self.filename = filename
         self.filename = filename
         self.lockfilename = lockfilename
         self.lockfilename = lockfilename
-        super(FileLocked, self).__init__(filename, lockfilename)
+        super().__init__(filename, lockfilename)
 
 
 
 
-class _GitFile(object):
+class _GitFile:
     """File that follows the git locking protocol for writes.
     """File that follows the git locking protocol for writes.
 
 
     All writes to a file foo will be written into foo.lock in the same
     All writes to a file foo will be written into foo.lock in the same
@@ -114,17 +113,15 @@ class _GitFile(object):
         released. Typically this will happen in a finally block.
         released. Typically this will happen in a finally block.
     """
     """
 
 
-    PROXY_PROPERTIES = set(
-        [
-            "closed",
-            "encoding",
-            "errors",
-            "mode",
-            "name",
-            "newlines",
-            "softspace",
-        ]
-    )
+    PROXY_PROPERTIES = {
+        "closed",
+        "encoding",
+        "errors",
+        "mode",
+        "name",
+        "newlines",
+        "softspace",
+    }
     PROXY_METHODS = (
     PROXY_METHODS = (
         "__iter__",
         "__iter__",
         "flush",
         "flush",

+ 0 - 1
dulwich/graph.py

@@ -1,5 +1,4 @@
 #!/usr/bin/env python
 #!/usr/bin/env python
-# -*- coding: utf-8 -*-
 # vim:ts=4:sw=4:softtabstop=4:smarttab:expandtab
 # vim:ts=4:sw=4:softtabstop=4:smarttab:expandtab
 # Copyright (c) 2020 Kevin B. Hendricks, Stratford Ontario Canada
 # Copyright (c) 2020 Kevin B. Hendricks, Stratford Ontario Canada
 #
 #

+ 3 - 4
dulwich/greenthreads.py

@@ -104,7 +104,7 @@ class GreenThreadsMissingObjectFinder(MissingObjectFinder):
             self.sha_done.add(t)
             self.sha_done.add(t)
         missing_tags = want_tags.difference(have_tags)
         missing_tags = want_tags.difference(have_tags)
         wants = missing_commits.union(missing_tags)
         wants = missing_commits.union(missing_tags)
-        self.objects_to_send = set([(w, None, False) for w in wants])
+        self.objects_to_send = {(w, None, False) for w in wants}
         if progress is None:
         if progress is None:
             self.progress = lambda x: None
             self.progress = lambda x: None
         else:
         else:
@@ -122,15 +122,14 @@ class GreenThreadsObjectStoreIterator(ObjectStoreIterator):
     def __init__(self, store, shas, finder, concurrency=1):
     def __init__(self, store, shas, finder, concurrency=1):
         self.finder = finder
         self.finder = finder
         self.p = pool.Pool(size=concurrency)
         self.p = pool.Pool(size=concurrency)
-        super(GreenThreadsObjectStoreIterator, self).__init__(store, shas)
+        super().__init__(store, shas)
 
 
     def retrieve(self, args):
     def retrieve(self, args):
         sha, path = args
         sha, path = args
         return self.store[sha], path
         return self.store[sha], path
 
 
     def __iter__(self):
     def __iter__(self):
-        for sha, path in self.p.imap_unordered(self.retrieve, self.itershas()):
-            yield sha, path
+        yield from self.p.imap_unordered(self.retrieve, self.itershas())
 
 
     def __len__(self):
     def __len__(self):
         if len(self._shas) > 0:
         if len(self._shas) > 0:

+ 1 - 1
dulwich/hooks.py

@@ -28,7 +28,7 @@ from dulwich.errors import (
 )
 )
 
 
 
 
-class Hook(object):
+class Hook:
     """Generic hook object."""
     """Generic hook object."""
 
 
     def execute(self, *args):
     def execute(self, *args):

+ 9 - 9
dulwich/ignore.py

@@ -154,7 +154,7 @@ def match_pattern(path: bytes, pattern: bytes, ignorecase: bool = False) -> bool
     return Pattern(pattern, ignorecase).match(path)
     return Pattern(pattern, ignorecase).match(path)
 
 
 
 
-class Pattern(object):
+class Pattern:
     """A single ignore pattern."""
     """A single ignore pattern."""
 
 
     def __init__(self, pattern: bytes, ignorecase: bool = False):
     def __init__(self, pattern: bytes, ignorecase: bool = False):
@@ -186,7 +186,7 @@ class Pattern(object):
         )
         )
 
 
     def __repr__(self) -> str:
     def __repr__(self) -> str:
-        return "%s(%r, %r)" % (
+        return "{}({!r}, {!r})".format(
             type(self).__name__,
             type(self).__name__,
             self.pattern,
             self.pattern,
             self.ignorecase,
             self.ignorecase,
@@ -202,7 +202,7 @@ class Pattern(object):
         return bool(self._re.match(path))
         return bool(self._re.match(path))
 
 
 
 
-class IgnoreFilter(object):
+class IgnoreFilter:
     def __init__(self, patterns: Iterable[bytes], ignorecase: bool = False, path=None):
     def __init__(self, patterns: Iterable[bytes], ignorecase: bool = False, path=None):
         self._patterns: List[Pattern] = []
         self._patterns: List[Pattern] = []
         self._ignorecase = ignorecase
         self._ignorecase = ignorecase
@@ -249,12 +249,12 @@ class IgnoreFilter(object):
     def __repr__(self) -> str:
     def __repr__(self) -> str:
         path = getattr(self, "_path", None)
         path = getattr(self, "_path", None)
         if path is not None:
         if path is not None:
-            return "%s.from_path(%r)" % (type(self).__name__, path)
+            return "{}.from_path({!r})".format(type(self).__name__, path)
         else:
         else:
             return "<%s>" % (type(self).__name__)
             return "<%s>" % (type(self).__name__)
 
 
 
 
-class IgnoreFilterStack(object):
+class IgnoreFilterStack:
     """Check for ignore status in multiple filters."""
     """Check for ignore status in multiple filters."""
 
 
     def __init__(self, filters):
     def __init__(self, filters):
@@ -295,7 +295,7 @@ def default_user_ignore_filter_path(config: Config) -> str:
     return get_xdg_config_home_path("git", "ignore")
     return get_xdg_config_home_path("git", "ignore")
 
 
 
 
-class IgnoreFilterManager(object):
+class IgnoreFilterManager:
     """Ignore file manager."""
     """Ignore file manager."""
 
 
     def __init__(
     def __init__(
@@ -310,7 +310,7 @@ class IgnoreFilterManager(object):
         self._ignorecase = ignorecase
         self._ignorecase = ignorecase
 
 
     def __repr__(self) -> str:
     def __repr__(self) -> str:
-        return "%s(%s, %r, %r)" % (
+        return "{}({}, {!r}, {!r})".format(
             type(self).__name__,
             type(self).__name__,
             self._top_path,
             self._top_path,
             self._global_filters,
             self._global_filters,
@@ -326,7 +326,7 @@ class IgnoreFilterManager(object):
         p = os.path.join(self._top_path, path, ".gitignore")
         p = os.path.join(self._top_path, path, ".gitignore")
         try:
         try:
             self._path_filters[path] = IgnoreFilter.from_path(p, self._ignorecase)
             self._path_filters[path] = IgnoreFilter.from_path(p, self._ignorecase)
-        except IOError:
+        except OSError:
             self._path_filters[path] = None
             self._path_filters[path] = None
         return self._path_filters[path]
         return self._path_filters[path]
 
 
@@ -389,7 +389,7 @@ class IgnoreFilterManager(object):
         ]:
         ]:
             try:
             try:
                 global_filters.append(IgnoreFilter.from_path(os.path.expanduser(p)))
                 global_filters.append(IgnoreFilter.from_path(os.path.expanduser(p)))
-            except IOError:
+            except OSError:
                 pass
                 pass
         config = repo.get_config_stack()
         config = repo.get_config_stack()
         ignorecase = config.get_boolean((b"core"), (b"ignorecase"), False)
         ignorecase = config.get_boolean((b"core"), (b"ignorecase"), False)

+ 6 - 7
dulwich/index.py

@@ -174,7 +174,7 @@ def read_cache_entry(f, version: int) -> Tuple[str, IndexEntry]:
         (extended_flags, ) = struct.unpack(">H", f.read(2))
         (extended_flags, ) = struct.unpack(">H", f.read(2))
     else:
     else:
         extended_flags = 0
         extended_flags = 0
-    name = f.read((flags & 0x0FFF))
+    name = f.read(flags & 0x0FFF)
     # Padding:
     # Padding:
     if version < 4:
     if version < 4:
         real_size = (f.tell() - beginoffset + 8) & ~7
         real_size = (f.tell() - beginoffset + 8) & ~7
@@ -313,7 +313,7 @@ def cleanup_mode(mode: int) -> int:
     return ret
     return ret
 
 
 
 
-class Index(object):
+class Index:
     """A Git Index file."""
     """A Git Index file."""
 
 
     def __init__(self, filename: Union[bytes, str], read=True):
     def __init__(self, filename: Union[bytes, str], read=True):
@@ -335,7 +335,7 @@ class Index(object):
         return self._filename
         return self._filename
 
 
     def __repr__(self):
     def __repr__(self):
-        return "%s(%r)" % (self.__class__.__name__, self._filename)
+        return "{}({!r})".format(self.__class__.__name__, self._filename)
 
 
     def write(self) -> None:
     def write(self) -> None:
         """Write current contents of index to disk."""
         """Write current contents of index to disk."""
@@ -431,14 +431,13 @@ class Index(object):
             entry = self[path]
             entry = self[path]
             return entry.sha, cleanup_mode(entry.mode)
             return entry.sha, cleanup_mode(entry.mode)
 
 
-        for (name, mode, sha) in changes_from_tree(
+        yield from changes_from_tree(
             self._byname.keys(),
             self._byname.keys(),
             lookup_entry,
             lookup_entry,
             object_store,
             object_store,
             tree,
             tree,
             want_unchanged=want_unchanged,
             want_unchanged=want_unchanged,
-        ):
-            yield (name, mode, sha)
+        )
 
 
     def commit(self, object_store):
     def commit(self, object_store):
         """Create a new tree from an index.
         """Create a new tree from an index.
@@ -1014,7 +1013,7 @@ def refresh_index(index: Index, root_path: bytes):
             index[path] = entry
             index[path] = entry
 
 
 
 
-class locked_index(object):
+class locked_index:
     """Lock the index while making modifications.
     """Lock the index while making modifications.
 
 
     Works as a context manager.
     Works as a context manager.

+ 1 - 1
dulwich/lfs.py

@@ -23,7 +23,7 @@ import os
 import tempfile
 import tempfile
 
 
 
 
-class LFSStore(object):
+class LFSStore:
     """Stores objects on disk, indexed by SHA256."""
     """Stores objects on disk, indexed by SHA256."""
 
 
     def __init__(self, path):
     def __init__(self, path):

+ 1 - 1
dulwich/line_ending.py

@@ -214,7 +214,7 @@ def get_checkin_filter_autocrlf(core_autocrlf):
     return None
     return None
 
 
 
 
-class BlobNormalizer(object):
+class BlobNormalizer:
     """An object to store computation result of which filter to apply based
     """An object to store computation result of which filter to apply based
     on configuration, gitattributes, path and operation (checkin or checkout)
     on configuration, gitattributes, path and operation (checkin or checkout)
     """
     """

+ 1 - 1
dulwich/lru_cache.py

@@ -56,7 +56,7 @@ class _LRUNode(Generic[K, V]):
             prev_key = None
             prev_key = None
         else:
         else:
             prev_key = self.prev.key
             prev_key = self.prev.key
-        return "%s(%r n:%r p:%r)" % (
+        return "{}({!r} n:{!r} p:{!r})".format(
             self.__class__.__name__,
             self.__class__.__name__,
             self.key,
             self.key,
             self.next_key,
             self.next_key,

+ 1 - 1
dulwich/mailmap.py

@@ -58,7 +58,7 @@ def read_mailmap(f):
         yield parsed_canonical_identity, parsed_from_identity
         yield parsed_canonical_identity, parsed_from_identity
 
 
 
 
-class Mailmap(object):
+class Mailmap:
     """Class for accessing a mailmap file."""
     """Class for accessing a mailmap file."""
 
 
     def __init__(self, map=None):
     def __init__(self, map=None):

+ 15 - 19
dulwich/object_store.py

@@ -79,7 +79,7 @@ PACKDIR = "pack"
 PACK_MODE = 0o444 if sys.platform != "win32" else 0o644
 PACK_MODE = 0o444 if sys.platform != "win32" else 0o644
 
 
 
 
-class BaseObjectStore(object):
+class BaseObjectStore:
     """Object store interface."""
     """Object store interface."""
 
 
     def determine_wants_all(
     def determine_wants_all(
@@ -477,8 +477,7 @@ class PackBasedObjectStore(BaseObjectStore):
     def _iter_alternate_objects(self):
     def _iter_alternate_objects(self):
         """Iterate over the SHAs of all the objects in alternate stores."""
         """Iterate over the SHAs of all the objects in alternate stores."""
         for alternate in self.alternates:
         for alternate in self.alternates:
-            for alternate_object in alternate:
-                yield alternate_object
+            yield from alternate
 
 
     def _iter_loose_objects(self):
     def _iter_loose_objects(self):
         """Iterate over the SHAs of all loose objects."""
         """Iterate over the SHAs of all loose objects."""
@@ -539,14 +538,11 @@ class PackBasedObjectStore(BaseObjectStore):
         self._update_pack_cache()
         self._update_pack_cache()
         for pack in self._iter_cached_packs():
         for pack in self._iter_cached_packs():
             try:
             try:
-                for sha in pack:
-                    yield sha
+                yield from pack
             except PackFileDisappeared:
             except PackFileDisappeared:
                 pass
                 pass
-        for sha in self._iter_loose_objects():
-            yield sha
-        for sha in self._iter_alternate_objects():
-            yield sha
+        yield from self._iter_loose_objects()
+        yield from self._iter_alternate_objects()
 
 
     def contains_loose(self, sha):
     def contains_loose(self, sha):
         """Check if a particular object is present by SHA1 and is loose.
         """Check if a particular object is present by SHA1 and is loose.
@@ -571,7 +567,7 @@ class PackBasedObjectStore(BaseObjectStore):
             sha = name
             sha = name
             hexsha = None
             hexsha = None
         else:
         else:
-            raise AssertionError("Invalid object name %r" % (name,))
+            raise AssertionError("Invalid object name {!r}".format(name))
         for pack in self._iter_cached_packs():
         for pack in self._iter_cached_packs():
             try:
             try:
                 return pack.get_raw(sha)
                 return pack.get_raw(sha)
@@ -618,7 +614,7 @@ class DiskObjectStore(PackBasedObjectStore):
           loose_compression_level: zlib compression level for loose objects
           loose_compression_level: zlib compression level for loose objects
           pack_compression_level: zlib compression level for pack objects
           pack_compression_level: zlib compression level for pack objects
         """
         """
-        super(DiskObjectStore, self).__init__(
+        super().__init__(
             pack_compression_level=pack_compression_level
             pack_compression_level=pack_compression_level
         )
         )
         self.path = path
         self.path = path
@@ -628,7 +624,7 @@ class DiskObjectStore(PackBasedObjectStore):
         self.pack_compression_level = pack_compression_level
         self.pack_compression_level = pack_compression_level
 
 
     def __repr__(self):
     def __repr__(self):
-        return "<%s(%r)>" % (self.__class__.__name__, self.path)
+        return "<{}({!r})>".format(self.__class__.__name__, self.path)
 
 
     @classmethod
     @classmethod
     def from_config(cls, path, config):
     def from_config(cls, path, config):
@@ -956,7 +952,7 @@ class MemoryObjectStore(BaseObjectStore):
     """Object store that keeps all objects in memory."""
     """Object store that keeps all objects in memory."""
 
 
     def __init__(self):
     def __init__(self):
-        super(MemoryObjectStore, self).__init__()
+        super().__init__()
         self._data = {}
         self._data = {}
         self.pack_compression_level = -1
         self.pack_compression_level = -1
 
 
@@ -966,7 +962,7 @@ class MemoryObjectStore(BaseObjectStore):
         elif len(sha) == 20:
         elif len(sha) == 20:
             return sha_to_hex(sha)
             return sha_to_hex(sha)
         else:
         else:
-            raise ValueError("Invalid sha %r" % (sha,))
+            raise ValueError("Invalid sha {!r}".format(sha))
 
 
     def contains_loose(self, sha):
     def contains_loose(self, sha):
         """Check if a particular object is present by SHA1 and is loose."""
         """Check if a particular object is present by SHA1 and is loose."""
@@ -1087,7 +1083,7 @@ class MemoryObjectStore(BaseObjectStore):
             commit()
             commit()
 
 
 
 
-class ObjectIterator(object):
+class ObjectIterator:
     """Interface for iterating over objects."""
     """Interface for iterating over objects."""
 
 
     def iterobjects(self):
     def iterobjects(self):
@@ -1239,7 +1235,7 @@ def _split_commits_and_tags(obj_store, lst, ignore_unknown=False):
     return (commits, tags, others)
     return (commits, tags, others)
 
 
 
 
-class MissingObjectFinder(object):
+class MissingObjectFinder:
     """Find the objects missing from another object store.
     """Find the objects missing from another object store.
 
 
     Args:
     Args:
@@ -1313,7 +1309,7 @@ class MissingObjectFinder(object):
         wants = missing_commits.union(missing_tags)
         wants = missing_commits.union(missing_tags)
         wants = wants.union(missing_others)
         wants = wants.union(missing_others)
 
 
-        self.objects_to_send = set([(w, None, False) for w in wants])
+        self.objects_to_send = {(w, None, False) for w in wants}
 
 
         if progress is None:
         if progress is None:
             self.progress = lambda x: None
             self.progress = lambda x: None
@@ -1354,7 +1350,7 @@ class MissingObjectFinder(object):
     __next__ = next
     __next__ = next
 
 
 
 
-class ObjectStoreGraphWalker(object):
+class ObjectStoreGraphWalker:
     """Graph walker that finds what commits are missing from an object store.
     """Graph walker that finds what commits are missing from an object store.
 
 
     Attributes:
     Attributes:
@@ -1380,7 +1376,7 @@ class ObjectStoreGraphWalker(object):
         """Ack that a revision and its ancestors are present in the source."""
         """Ack that a revision and its ancestors are present in the source."""
         if len(sha) != 40:
         if len(sha) != 40:
             raise ValueError("unexpected sha %r received" % sha)
             raise ValueError("unexpected sha %r received" % sha)
-        ancestors = set([sha])
+        ancestors = {sha}
 
 
         # stop if we run out of heads to remove
         # stop if we run out of heads to remove
         while self.heads:
         while self.heads:

+ 15 - 15
dulwich/objects.py

@@ -199,7 +199,7 @@ def check_hexsha(hex, error_msg):
       ObjectFormatException: Raised when the string is not valid
       ObjectFormatException: Raised when the string is not valid
     """
     """
     if not valid_hexsha(hex):
     if not valid_hexsha(hex):
-        raise ObjectFormatException("%s %s" % (error_msg, hex))
+        raise ObjectFormatException("{} {}".format(error_msg, hex))
 
 
 
 
 def check_identity(identity: bytes, error_msg: str) -> None:
 def check_identity(identity: bytes, error_msg: str) -> None:
@@ -243,7 +243,7 @@ def git_line(*items):
     return b" ".join(items) + b"\n"
     return b" ".join(items) + b"\n"
 
 
 
 
-class FixedSha(object):
+class FixedSha:
     """SHA object that behaves like hashlib's but is given a fixed value."""
     """SHA object that behaves like hashlib's but is given a fixed value."""
 
 
     __slots__ = ("_hexsha", "_sha")
     __slots__ = ("_hexsha", "_sha")
@@ -265,7 +265,7 @@ class FixedSha(object):
         return self._hexsha.decode("ascii")
         return self._hexsha.decode("ascii")
 
 
 
 
-class ShaFile(object):
+class ShaFile:
     """A git SHA file."""
     """A git SHA file."""
 
 
     __slots__ = ("_chunked_text", "_sha", "_needs_serialization")
     __slots__ = ("_chunked_text", "_sha", "_needs_serialization")
@@ -557,7 +557,7 @@ class ShaFile(object):
         return self.sha().hexdigest().encode("ascii")
         return self.sha().hexdigest().encode("ascii")
 
 
     def __repr__(self):
     def __repr__(self):
-        return "<%s %s>" % (self.__class__.__name__, self.id)
+        return "<{} {}>".format(self.__class__.__name__, self.id)
 
 
     def __ne__(self, other):
     def __ne__(self, other):
         """Check whether this object does not match the other."""
         """Check whether this object does not match the other."""
@@ -591,7 +591,7 @@ class Blob(ShaFile):
     _chunked_text: List[bytes]
     _chunked_text: List[bytes]
 
 
     def __init__(self):
     def __init__(self):
-        super(Blob, self).__init__()
+        super().__init__()
         self._chunked_text = []
         self._chunked_text = []
         self._needs_serialization = False
         self._needs_serialization = False
 
 
@@ -636,7 +636,7 @@ class Blob(ShaFile):
         Raises:
         Raises:
           ObjectFormatException: if the object is malformed in some way
           ObjectFormatException: if the object is malformed in some way
         """
         """
-        super(Blob, self).check()
+        super().check()
 
 
     def splitlines(self) -> List[bytes]:
     def splitlines(self) -> List[bytes]:
         """Return list of lines in this blob.
         """Return list of lines in this blob.
@@ -741,7 +741,7 @@ class Tag(ShaFile):
     _tagger: Optional[bytes]
     _tagger: Optional[bytes]
 
 
     def __init__(self):
     def __init__(self):
-        super(Tag, self).__init__()
+        super().__init__()
         self._tagger = None
         self._tagger = None
         self._tag_time = None
         self._tag_time = None
         self._tag_timezone = None
         self._tag_timezone = None
@@ -761,7 +761,7 @@ class Tag(ShaFile):
         Raises:
         Raises:
           ObjectFormatException: if the object is malformed in some way
           ObjectFormatException: if the object is malformed in some way
         """
         """
-        super(Tag, self).check()
+        super().check()
         assert self._chunked_text is not None
         assert self._chunked_text is not None
         self._check_has_member("_object_sha", "missing object sha")
         self._check_has_member("_object_sha", "missing object sha")
         self._check_has_member("_object_class", "missing object type")
         self._check_has_member("_object_class", "missing object type")
@@ -1042,7 +1042,7 @@ def pretty_format_tree_entry(name, mode, hexsha, encoding="utf-8"):
         kind = "tree"
         kind = "tree"
     else:
     else:
         kind = "blob"
         kind = "blob"
-    return "%04o %s %s\t%s\n" % (
+    return "{:04o} {} {}\t{}\n".format(
         mode,
         mode,
         kind,
         kind,
         hexsha.decode("ascii"),
         hexsha.decode("ascii"),
@@ -1067,7 +1067,7 @@ class Tree(ShaFile):
     __slots__ = "_entries"
     __slots__ = "_entries"
 
 
     def __init__(self):
     def __init__(self):
-        super(Tree, self).__init__()
+        super().__init__()
         self._entries = {}
         self._entries = {}
 
 
     @classmethod
     @classmethod
@@ -1144,7 +1144,7 @@ class Tree(ShaFile):
         # TODO: list comprehension is for efficiency in the common (small)
         # TODO: list comprehension is for efficiency in the common (small)
         # case; if memory efficiency in the large case is a concern, use a
         # case; if memory efficiency in the large case is a concern, use a
         # genexp.
         # genexp.
-        self._entries = dict([(n, (m, s)) for n, m, s in parsed_entries])
+        self._entries = {n: (m, s) for n, m, s in parsed_entries}
 
 
     def check(self):
     def check(self):
         """Check this object for internal consistency.
         """Check this object for internal consistency.
@@ -1152,7 +1152,7 @@ class Tree(ShaFile):
         Raises:
         Raises:
           ObjectFormatException: if the object is malformed in some way
           ObjectFormatException: if the object is malformed in some way
         """
         """
-        super(Tree, self).check()
+        super().check()
         assert self._chunked_text is not None
         assert self._chunked_text is not None
         last = None
         last = None
         allowed_modes = (
         allowed_modes = (
@@ -1362,7 +1362,7 @@ class Commit(ShaFile):
     )
     )
 
 
     def __init__(self):
     def __init__(self):
-        super(Commit, self).__init__()
+        super().__init__()
         self._parents = []
         self._parents = []
         self._encoding = None
         self._encoding = None
         self._mergetag = []
         self._mergetag = []
@@ -1407,7 +1407,7 @@ class Commit(ShaFile):
         Raises:
         Raises:
           ObjectFormatException: if the object is malformed in some way
           ObjectFormatException: if the object is malformed in some way
         """
         """
-        super(Commit, self).check()
+        super().check()
         assert self._chunked_text is not None
         assert self._chunked_text is not None
         self._check_has_member("_tree", "missing tree")
         self._check_has_member("_tree", "missing tree")
         self._check_has_member("_author", "missing author")
         self._check_has_member("_author", "missing author")
@@ -1540,7 +1540,7 @@ class Commit(ShaFile):
                 chunks[-1] = chunks[-1][:-2]
                 chunks[-1] = chunks[-1][:-2]
         for k, v in self.extra:
         for k, v in self.extra:
             if b"\n" in k or b"\n" in v:
             if b"\n" in k or b"\n" in v:
-                raise AssertionError("newline in extra data: %r -> %r" % (k, v))
+                raise AssertionError("newline in extra data: {!r} -> {!r}".format(k, v))
             chunks.append(git_line(k, v))
             chunks.append(git_line(k, v))
         if self.gpgsig:
         if self.gpgsig:
             sig_chunks = self.gpgsig.split(b"\n")
             sig_chunks = self.gpgsig.split(b"\n")

+ 20 - 20
dulwich/pack.py

@@ -116,7 +116,7 @@ class PackFileDisappeared(Exception):
         self.obj = obj
         self.obj = obj
 
 
 
 
-class UnpackedObject(object):
+class UnpackedObject:
     """Class encapsulating an object unpacked from a pack file.
     """Class encapsulating an object unpacked from a pack file.
 
 
     These objects should only be created from within unpack_object. Most
     These objects should only be created from within unpack_object. Most
@@ -195,8 +195,8 @@ class UnpackedObject(object):
         return not (self == other)
         return not (self == other)
 
 
     def __repr__(self):
     def __repr__(self):
-        data = ["%s=%r" % (s, getattr(self, s)) for s in self.__slots__]
-        return "%s(%s)" % (self.__class__.__name__, ", ".join(data))
+        data = ["{}={!r}".format(s, getattr(self, s)) for s in self.__slots__]
+        return "{}({})".format(self.__class__.__name__, ", ".join(data))
 
 
 
 
 _ZLIB_BUFSIZE = 4096
 _ZLIB_BUFSIZE = 4096
@@ -356,7 +356,7 @@ def bisect_find_sha(start, end, sha, unpack_name):
     return None
     return None
 
 
 
 
-class PackIndex(object):
+class PackIndex:
     """An index in to a packfile.
     """An index in to a packfile.
 
 
     Given a sha id of an object a pack index can tell you the location in the
     Given a sha id of an object a pack index can tell you the location in the
@@ -524,7 +524,7 @@ class FilePackIndex(PackIndex):
         ):
         ):
             return False
             return False
 
 
-        return super(FilePackIndex, self).__eq__(other)
+        return super().__eq__(other)
 
 
     def close(self):
     def close(self):
         self._file.close()
         self._file.close()
@@ -645,7 +645,7 @@ class PackIndex1(FilePackIndex):
     """Version 1 Pack Index file."""
     """Version 1 Pack Index file."""
 
 
     def __init__(self, filename, file=None, contents=None, size=None):
     def __init__(self, filename, file=None, contents=None, size=None):
-        super(PackIndex1, self).__init__(filename, file, contents, size)
+        super().__init__(filename, file, contents, size)
         self.version = 1
         self.version = 1
         self._fan_out_table = self._read_fan_out_table(0)
         self._fan_out_table = self._read_fan_out_table(0)
 
 
@@ -670,7 +670,7 @@ class PackIndex2(FilePackIndex):
     """Version 2 Pack Index file."""
     """Version 2 Pack Index file."""
 
 
     def __init__(self, filename, file=None, contents=None, size=None):
     def __init__(self, filename, file=None, contents=None, size=None):
-        super(PackIndex2, self).__init__(filename, file, contents, size)
+        super().__init__(filename, file, contents, size)
         if self._contents[:4] != b"\377tOc":
         if self._contents[:4] != b"\377tOc":
             raise AssertionError("Not a v2 pack index file")
             raise AssertionError("Not a v2 pack index file")
         (self.version,) = unpack_from(b">L", self._contents, 4)
         (self.version,) = unpack_from(b">L", self._contents, 4)
@@ -817,14 +817,14 @@ def _compute_object_size(value):
     return chunks_length(obj)
     return chunks_length(obj)
 
 
 
 
-class PackStreamReader(object):
+class PackStreamReader:
     """Class to read a pack stream.
     """Class to read a pack stream.
 
 
     The pack is read from a ReceivableProtocol using read() or recv() as
     The pack is read from a ReceivableProtocol using read() or recv() as
     appropriate.
     appropriate.
     """
     """
 
 
-    def __init__(self, read_all, read_some=None, zlib_bufsize=_ZLIB_BUFSIZE):
+    def __init__(self, read_all, read_some=None, zlib_bufsize=_ZLIB_BUFSIZE) -> None:
         self.read_all = read_all
         self.read_all = read_all
         if read_some is None:
         if read_some is None:
             self.read_some = read_all
             self.read_some = read_all
@@ -977,13 +977,13 @@ class PackStreamCopier(PackStreamReader):
           delta_iter: Optional DeltaChainIterator to record deltas as we
           delta_iter: Optional DeltaChainIterator to record deltas as we
             read them.
             read them.
         """
         """
-        super(PackStreamCopier, self).__init__(read_all, read_some=read_some)
+        super().__init__(read_all, read_some=read_some)
         self.outfile = outfile
         self.outfile = outfile
         self._delta_iter = delta_iter
         self._delta_iter = delta_iter
 
 
     def _read(self, read, size):
     def _read(self, read, size):
         """Read data from the read callback and write it to the file."""
         """Read data from the read callback and write it to the file."""
-        data = super(PackStreamCopier, self)._read(read, size)
+        data = super()._read(read, size)
         self.outfile.write(data)
         self.outfile.write(data)
         return data
         return data
 
 
@@ -1041,7 +1041,7 @@ def compute_file_sha(f, start_ofs=0, end_ofs=0, buffer_size=1 << 16):
     return sha
     return sha
 
 
 
 
-class PackData(object):
+class PackData:
     """The data contained in a packfile.
     """The data contained in a packfile.
 
 
     Pack files can be accessed both sequentially for exploding a pack, and
     Pack files can be accessed both sequentially for exploding a pack, and
@@ -1314,7 +1314,7 @@ class PackData(object):
         return (unpacked.pack_type_num, unpacked._obj())
         return (unpacked.pack_type_num, unpacked._obj())
 
 
 
 
-class DeltaChainIterator(object):
+class DeltaChainIterator:
     """Abstract iterator over pack data based on delta chains.
     """Abstract iterator over pack data based on delta chains.
 
 
     Each object in the pack is guaranteed to be inflated exactly once,
     Each object in the pack is guaranteed to be inflated exactly once,
@@ -1461,7 +1461,7 @@ class PackInflater(DeltaChainIterator):
         return unpacked.sha_file()
         return unpacked.sha_file()
 
 
 
 
-class SHA1Reader(object):
+class SHA1Reader:
     """Wrapper for file-like object that remembers the SHA1 of its data."""
     """Wrapper for file-like object that remembers the SHA1 of its data."""
 
 
     def __init__(self, f):
     def __init__(self, f):
@@ -1485,7 +1485,7 @@ class SHA1Reader(object):
         return self.f.tell()
         return self.f.tell()
 
 
 
 
-class SHA1Writer(object):
+class SHA1Writer:
     """Wrapper for file-like object that remembers the SHA1 of its data."""
     """Wrapper for file-like object that remembers the SHA1 of its data."""
 
 
     def __init__(self, f):
     def __init__(self, f):
@@ -1643,7 +1643,7 @@ def write_pack_header(write, num_objects):
         write(chunk)
         write(chunk)
 
 
 
 
-def deltify_pack_objects(objects, window_size=None, reuse_pack=None):
+def deltify_pack_objects(objects, window_size: Optional[int] = None, reuse_pack=None):
     """Generate deltas for pack objects.
     """Generate deltas for pack objects.
 
 
     Args:
     Args:
@@ -1770,7 +1770,7 @@ def write_pack_objects(
     )
     )
 
 
 
 
-class PackChunkGenerator(object):
+class PackChunkGenerator:
 
 
     def __init__(self, num_records=None, records=None, progress=None, compression_level=-1):
     def __init__(self, num_records=None, records=None, progress=None, compression_level=-1):
         self.cs = sha1(b"")
         self.cs = sha1(b"")
@@ -2073,7 +2073,7 @@ def write_pack_index_v2(f, entries, pack_checksum):
 write_pack_index = write_pack_index_v2
 write_pack_index = write_pack_index_v2
 
 
 
 
-class _PackTupleIterable(object):
+class _PackTupleIterable:
     """Helper for Pack.pack_tuples."""
     """Helper for Pack.pack_tuples."""
 
 
     def __init__(self, iterobjects, length):
     def __init__(self, iterobjects, length):
@@ -2087,7 +2087,7 @@ class _PackTupleIterable(object):
         return ((o, None) for o in self._iterobjects())
         return ((o, None) for o in self._iterobjects())
 
 
 
 
-class Pack(object):
+class Pack:
     """A Git pack object."""
     """A Git pack object."""
 
 
     _data_load: Optional[Callable[[], PackData]]
     _data_load: Optional[Callable[[], PackData]]
@@ -2171,7 +2171,7 @@ class Pack(object):
         return len(self.index)
         return len(self.index)
 
 
     def __repr__(self):
     def __repr__(self):
-        return "%s(%r)" % (self.__class__.__name__, self._basename)
+        return "{}({!r})".format(self.__class__.__name__, self._basename)
 
 
     def __iter__(self):
     def __iter__(self):
         """Iterate over all the sha1s of the objects in this pack."""
         """Iterate over all the sha1s of the objects in this pack."""

+ 5 - 5
dulwich/patch.py

@@ -109,10 +109,10 @@ def _format_range_unified(start, stop):
     beginning = start + 1  # lines start numbering with one
     beginning = start + 1  # lines start numbering with one
     length = stop - start
     length = stop - start
     if length == 1:
     if length == 1:
-        return "{}".format(beginning)
+        return f"{beginning}"
     if not length:
     if not length:
         beginning -= 1  # empty ranges begin at line just before the range
         beginning -= 1  # empty ranges begin at line just before the range
-    return "{},{}".format(beginning, length)
+    return f"{beginning},{length}"
 
 
 
 
 def unified_diff(
 def unified_diff(
@@ -136,8 +136,8 @@ def unified_diff(
     for group in SequenceMatcher(None, a, b).get_grouped_opcodes(n):
     for group in SequenceMatcher(None, a, b).get_grouped_opcodes(n):
         if not started:
         if not started:
             started = True
             started = True
-            fromdate = "\t{}".format(fromfiledate) if fromfiledate else ""
-            todate = "\t{}".format(tofiledate) if tofiledate else ""
+            fromdate = f"\t{fromfiledate}" if fromfiledate else ""
+            todate = f"\t{tofiledate}" if tofiledate else ""
             yield "--- {}{}{}".format(
             yield "--- {}{}{}".format(
                 fromfile.decode(tree_encoding), fromdate, lineterm
                 fromfile.decode(tree_encoding), fromdate, lineterm
             ).encode(output_encoding)
             ).encode(output_encoding)
@@ -148,7 +148,7 @@ def unified_diff(
         first, last = group[0], group[-1]
         first, last = group[0], group[-1]
         file1_range = _format_range_unified(first[1], last[2])
         file1_range = _format_range_unified(first[1], last[2])
         file2_range = _format_range_unified(first[3], last[4])
         file2_range = _format_range_unified(first[3], last[4])
-        yield "@@ -{} +{} @@{}".format(file1_range, file2_range, lineterm).encode(
+        yield f"@@ -{file1_range} +{file2_range} @@{lineterm}".encode(
             output_encoding
             output_encoding
         )
         )
 
 

+ 5 - 5
dulwich/porcelain.py

@@ -187,7 +187,7 @@ class Error(Exception):
     """Porcelain-based error. """
     """Porcelain-based error. """
 
 
     def __init__(self, msg):
     def __init__(self, msg):
-        super(Error, self).__init__(msg)
+        super().__init__(msg)
 
 
 
 
 class RemoteExists(Error):
 class RemoteExists(Error):
@@ -699,7 +699,7 @@ def remove(repo=".", paths=None, cached=False):
                 else:
                 else:
                     try:
                     try:
                         blob = blob_from_path_and_stat(full_path, st)
                         blob = blob_from_path_and_stat(full_path, st)
-                    except IOError:
+                    except OSError:
                         pass
                         pass
                     else:
                     else:
                         try:
                         try:
@@ -2036,10 +2036,10 @@ def describe(repo, abbrev=7):
         for key, value in refs.items():
         for key, value in refs.items():
             key = key.decode()
             key = key.decode()
             obj = r.get_object(value)
             obj = r.get_object(value)
-            if u"tags" not in key:
+            if "tags" not in key:
                 continue
                 continue
 
 
-            _, tag = key.rsplit(u"/", 1)
+            _, tag = key.rsplit("/", 1)
 
 
             try:
             try:
                 commit = obj.object
                 commit = obj.object
@@ -2056,7 +2056,7 @@ def describe(repo, abbrev=7):
 
 
         # If there are no tags, return the current commit
         # If there are no tags, return the current commit
         if len(sorted_tags) == 0:
         if len(sorted_tags) == 0:
-            return "g{}".format(find_unique_abbrev(r.object_store, r[r.head()].id))
+            return f"g{find_unique_abbrev(r.object_store, r[r.head()].id)}"
 
 
         # We're now 0 commits from the top
         # We're now 0 commits from the top
         commit_count = 0
         commit_count = 0

+ 6 - 7
dulwich/protocol.py

@@ -25,7 +25,6 @@ from io import BytesIO
 from os import (
 from os import (
     SEEK_END,
     SEEK_END,
 )
 )
-import socket
 
 
 import dulwich
 import dulwich
 from dulwich.errors import (
 from dulwich.errors import (
@@ -171,7 +170,7 @@ def pkt_line(data):
     return ("%04x" % (len(data) + 4)).encode("ascii") + data
     return ("%04x" % (len(data) + 4)).encode("ascii") + data
 
 
 
 
-class Protocol(object):
+class Protocol:
     """Class for interacting with a remote git process over the wire.
     """Class for interacting with a remote git process over the wire.
 
 
     Parts of the git wire protocol use 'pkt-lines' to communicate. A pkt-line
     Parts of the git wire protocol use 'pkt-lines' to communicate. A pkt-line
@@ -228,7 +227,7 @@ class Protocol(object):
             pkt_contents = read(size - 4)
             pkt_contents = read(size - 4)
         except ConnectionResetError as exc:
         except ConnectionResetError as exc:
             raise HangupException() from exc
             raise HangupException() from exc
-        except socket.error as exc:
+        except OSError as exc:
             raise GitProtocolError(exc) from exc
             raise GitProtocolError(exc) from exc
         else:
         else:
             if len(pkt_contents) + 4 != size:
             if len(pkt_contents) + 4 != size:
@@ -291,7 +290,7 @@ class Protocol(object):
             self.write(line)
             self.write(line)
             if self.report_activity:
             if self.report_activity:
                 self.report_activity(len(line), "write")
                 self.report_activity(len(line), "write")
-        except socket.error as exc:
+        except OSError as exc:
             raise GitProtocolError(exc) from exc
             raise GitProtocolError(exc) from exc
 
 
     def write_sideband(self, channel, blob):
     def write_sideband(self, channel, blob):
@@ -348,7 +347,7 @@ class ReceivableProtocol(Protocol):
     def __init__(
     def __init__(
         self, recv, write, close=None, report_activity=None, rbufsize=_RBUFSIZE
         self, recv, write, close=None, report_activity=None, rbufsize=_RBUFSIZE
     ):
     ):
-        super(ReceivableProtocol, self).__init__(
+        super().__init__(
             self.read, write, close=close, report_activity=report_activity
             self.read, write, close=close, report_activity=report_activity
         )
         )
         self._recv = recv
         self._recv = recv
@@ -480,7 +479,7 @@ def ack_type(capabilities):
     return SINGLE_ACK
     return SINGLE_ACK
 
 
 
 
-class BufferedPktLineWriter(object):
+class BufferedPktLineWriter:
     """Writer that wraps its data in pkt-lines and has an independent buffer.
     """Writer that wraps its data in pkt-lines and has an independent buffer.
 
 
     Consecutive calls to write() wrap the data in a pkt-line and then buffers
     Consecutive calls to write() wrap the data in a pkt-line and then buffers
@@ -524,7 +523,7 @@ class BufferedPktLineWriter(object):
         self._wbuf = BytesIO()
         self._wbuf = BytesIO()
 
 
 
 
-class PktLineParser(object):
+class PktLineParser:
     """Packet line parser that hands completed packets off to a callback."""
     """Packet line parser that hands completed packets off to a callback."""
 
 
     def __init__(self, handle_pkt):
     def __init__(self, handle_pkt):

+ 7 - 7
dulwich/refs.py

@@ -106,7 +106,7 @@ def check_ref_format(refname: Ref):
     return True
     return True
 
 
 
 
-class RefsContainer(object):
+class RefsContainer:
     """A container for refs."""
     """A container for refs."""
 
 
     def __init__(self, logger=None):
     def __init__(self, logger=None):
@@ -447,7 +447,7 @@ class DictRefsContainer(RefsContainer):
     """
     """
 
 
     def __init__(self, refs, logger=None):
     def __init__(self, refs, logger=None):
-        super(DictRefsContainer, self).__init__(logger=logger)
+        super().__init__(logger=logger)
         self._refs = refs
         self._refs = refs
         self._peeled = {}
         self._peeled = {}
         self._watchers = set()
         self._watchers = set()
@@ -622,7 +622,7 @@ class DiskRefsContainer(RefsContainer):
     """Refs container that reads refs from disk."""
     """Refs container that reads refs from disk."""
 
 
     def __init__(self, path, worktree_path=None, logger=None):
     def __init__(self, path, worktree_path=None, logger=None):
-        super(DiskRefsContainer, self).__init__(logger=logger)
+        super().__init__(logger=logger)
         if getattr(path, "encode", None) is not None:
         if getattr(path, "encode", None) is not None:
             path = os.fsencode(path)
             path = os.fsencode(path)
         self.path = path
         self.path = path
@@ -635,7 +635,7 @@ class DiskRefsContainer(RefsContainer):
         self._peeled_refs = None
         self._peeled_refs = None
 
 
     def __repr__(self):
     def __repr__(self):
-        return "%s(%r)" % (self.__class__.__name__, self.path)
+        return "{}({!r})".format(self.__class__.__name__, self.path)
 
 
     def subkeys(self, base):
     def subkeys(self, base):
         subkeys = set()
         subkeys = set()
@@ -911,12 +911,12 @@ class DiskRefsContainer(RefsContainer):
                     if orig_ref != old_ref:
                     if orig_ref != old_ref:
                         f.abort()
                         f.abort()
                         return False
                         return False
-                except (OSError, IOError):
+                except OSError:
                     f.abort()
                     f.abort()
                     raise
                     raise
             try:
             try:
                 f.write(new_ref + b"\n")
                 f.write(new_ref + b"\n")
-            except (OSError, IOError):
+            except OSError:
                 f.abort()
                 f.abort()
                 raise
                 raise
             self._log(
             self._log(
@@ -966,7 +966,7 @@ class DiskRefsContainer(RefsContainer):
                 return False
                 return False
             try:
             try:
                 f.write(ref + b"\n")
                 f.write(ref + b"\n")
-            except (OSError, IOError):
+            except OSError:
                 f.abort()
                 f.abort()
                 raise
                 raise
             else:
             else:

+ 5 - 5
dulwich/repo.py

@@ -180,7 +180,7 @@ def _get_default_identity() -> Tuple[str, str]:
         fullname = username
         fullname = username
     email = os.environ.get("EMAIL")
     email = os.environ.get("EMAIL")
     if email is None:
     if email is None:
-        email = "{}@{}".format(username, socket.gethostname())
+        email = f"{username}@{socket.gethostname()}"
     return (fullname, email)  # type: ignore
     return (fullname, email)  # type: ignore
 
 
 
 
@@ -329,7 +329,7 @@ def _set_filesystem_hidden(path):
     # Could implement other platform specific filesystem hiding here
     # Could implement other platform specific filesystem hiding here
 
 
 
 
-class ParentsProvider(object):
+class ParentsProvider:
     def __init__(self, store, grafts={}, shallows=[]):
     def __init__(self, store, grafts={}, shallows=[]):
         self.store = store
         self.store = store
         self.grafts = grafts
         self.grafts = grafts
@@ -347,7 +347,7 @@ class ParentsProvider(object):
         return commit.parents
         return commit.parents
 
 
 
 
-class BaseRepo(object):
+class BaseRepo:
     """Base class for a git repository.
     """Base class for a git repository.
 
 
     This base class is meant to be used for Repository implementations that e.g.
     This base class is meant to be used for Repository implementations that e.g.
@@ -642,7 +642,7 @@ class BaseRepo(object):
                 raise NotTagError(ret)
                 raise NotTagError(ret)
             else:
             else:
                 raise Exception(
                 raise Exception(
-                    "Type invalid: %r != %r" % (ret.type_name, cls.type_name)
+                    "Type invalid: {!r} != {!r}".format(ret.type_name, cls.type_name)
                 )
                 )
         return ret
         return ret
 
 
@@ -1133,7 +1133,7 @@ class Repo(BaseRepo):
         self.bare = bare
         self.bare = bare
         if bare is False:
         if bare is False:
             if os.path.isfile(hidden_path):
             if os.path.isfile(hidden_path):
-                with open(hidden_path, "r") as f:
+                with open(hidden_path) as f:
                     path = read_gitfile(f)
                     path = read_gitfile(f)
                 self._controldir = os.path.join(root, path)
                 self._controldir = os.path.join(root, path)
             else:
             else:

+ 14 - 14
dulwich/server.py

@@ -126,7 +126,7 @@ from dulwich.repo import (
 logger = log_utils.getLogger(__name__)
 logger = log_utils.getLogger(__name__)
 
 
 
 
-class Backend(object):
+class Backend:
     """A backend for the Git smart server implementation."""
     """A backend for the Git smart server implementation."""
 
 
     def open_repository(self, path):
     def open_repository(self, path):
@@ -141,7 +141,7 @@ class Backend(object):
         raise NotImplementedError(self.open_repository)
         raise NotImplementedError(self.open_repository)
 
 
 
 
-class BackendRepo(object):
+class BackendRepo:
     """Repository abstraction used by the Git server.
     """Repository abstraction used by the Git server.
 
 
     The methods required here are a subset of those provided by
     The methods required here are a subset of those provided by
@@ -203,7 +203,7 @@ class FileSystemBackend(Backend):
     """Simple backend looking up Git repositories in the local file system."""
     """Simple backend looking up Git repositories in the local file system."""
 
 
     def __init__(self, root=os.sep):
     def __init__(self, root=os.sep):
-        super(FileSystemBackend, self).__init__()
+        super().__init__()
         self.root = (os.path.abspath(root) + os.sep).replace(os.sep * 2, os.sep)
         self.root = (os.path.abspath(root) + os.sep).replace(os.sep * 2, os.sep)
 
 
     def open_repository(self, path):
     def open_repository(self, path):
@@ -212,11 +212,11 @@ class FileSystemBackend(Backend):
         normcase_abspath = os.path.normcase(abspath)
         normcase_abspath = os.path.normcase(abspath)
         normcase_root = os.path.normcase(self.root)
         normcase_root = os.path.normcase(self.root)
         if not normcase_abspath.startswith(normcase_root):
         if not normcase_abspath.startswith(normcase_root):
-            raise NotGitRepository("Path %r not inside root %r" % (path, self.root))
+            raise NotGitRepository("Path {!r} not inside root {!r}".format(path, self.root))
         return Repo(abspath)
         return Repo(abspath)
 
 
 
 
-class Handler(object):
+class Handler:
     """Smart protocol command handler base class."""
     """Smart protocol command handler base class."""
 
 
     def __init__(self, backend, proto, stateless_rpc=False):
     def __init__(self, backend, proto, stateless_rpc=False):
@@ -232,7 +232,7 @@ class PackHandler(Handler):
     """Protocol handler for packs."""
     """Protocol handler for packs."""
 
 
     def __init__(self, backend, proto, stateless_rpc=False):
     def __init__(self, backend, proto, stateless_rpc=False):
-        super(PackHandler, self).__init__(backend, proto, stateless_rpc)
+        super().__init__(backend, proto, stateless_rpc)
         self._client_capabilities = None
         self._client_capabilities = None
         # Flags needed for the no-done capability
         # Flags needed for the no-done capability
         self._done_received = False
         self._done_received = False
@@ -289,7 +289,7 @@ class UploadPackHandler(PackHandler):
     """Protocol handler for uploading a pack to the client."""
     """Protocol handler for uploading a pack to the client."""
 
 
     def __init__(self, backend, args, proto, stateless_rpc=False, advertise_refs=False):
     def __init__(self, backend, args, proto, stateless_rpc=False, advertise_refs=False):
-        super(UploadPackHandler, self).__init__(
+        super().__init__(
             backend, proto, stateless_rpc=stateless_rpc
             backend, proto, stateless_rpc=stateless_rpc
         )
         )
         self.repo = backend.open_repository(args[0])
         self.repo = backend.open_repository(args[0])
@@ -500,7 +500,7 @@ def _find_shallow(store, heads, depth):
 def _want_satisfied(store, haves, want, earliest):
 def _want_satisfied(store, haves, want, earliest):
     o = store[want]
     o = store[want]
     pending = collections.deque([o])
     pending = collections.deque([o])
-    known = set([want])
+    known = {want}
     while pending:
     while pending:
         commit = pending.popleft()
         commit = pending.popleft()
         if commit.id in haves:
         if commit.id in haves:
@@ -541,7 +541,7 @@ def _all_wants_satisfied(store, haves, wants):
     return True
     return True
 
 
 
 
-class _ProtocolGraphWalker(object):
+class _ProtocolGraphWalker:
     """A graph walker that knows the git protocol.
     """A graph walker that knows the git protocol.
 
 
     As a graph walker, this class implements ack(), next(), and reset(). It
     As a graph walker, this class implements ack(), next(), and reset(). It
@@ -752,7 +752,7 @@ class _ProtocolGraphWalker(object):
 _GRAPH_WALKER_COMMANDS = (COMMAND_HAVE, COMMAND_DONE, None)
 _GRAPH_WALKER_COMMANDS = (COMMAND_HAVE, COMMAND_DONE, None)
 
 
 
 
-class SingleAckGraphWalkerImpl(object):
+class SingleAckGraphWalkerImpl:
     """Graph walker implementation that speaks the single-ack protocol."""
     """Graph walker implementation that speaks the single-ack protocol."""
 
 
     def __init__(self, walker):
     def __init__(self, walker):
@@ -796,7 +796,7 @@ class SingleAckGraphWalkerImpl(object):
         return True
         return True
 
 
 
 
-class MultiAckGraphWalkerImpl(object):
+class MultiAckGraphWalkerImpl:
     """Graph walker implementation that speaks the multi-ack protocol."""
     """Graph walker implementation that speaks the multi-ack protocol."""
 
 
     def __init__(self, walker):
     def __init__(self, walker):
@@ -855,7 +855,7 @@ class MultiAckGraphWalkerImpl(object):
         return True
         return True
 
 
 
 
-class MultiAckDetailedGraphWalkerImpl(object):
+class MultiAckDetailedGraphWalkerImpl:
     """Graph walker implementation speaking the multi-ack-detailed protocol."""
     """Graph walker implementation speaking the multi-ack-detailed protocol."""
 
 
     def __init__(self, walker):
     def __init__(self, walker):
@@ -924,7 +924,7 @@ class ReceivePackHandler(PackHandler):
     """Protocol handler for downloading a pack from the client."""
     """Protocol handler for downloading a pack from the client."""
 
 
     def __init__(self, backend, args, proto, stateless_rpc=False, advertise_refs=False):
     def __init__(self, backend, args, proto, stateless_rpc=False, advertise_refs=False):
-        super(ReceivePackHandler, self).__init__(
+        super().__init__(
             backend, proto, stateless_rpc=stateless_rpc
             backend, proto, stateless_rpc=stateless_rpc
         )
         )
         self.repo = backend.open_repository(args[0])
         self.repo = backend.open_repository(args[0])
@@ -1088,7 +1088,7 @@ class ReceivePackHandler(PackHandler):
 
 
 class UploadArchiveHandler(Handler):
 class UploadArchiveHandler(Handler):
     def __init__(self, backend, args, proto, stateless_rpc=False):
     def __init__(self, backend, args, proto, stateless_rpc=False):
-        super(UploadArchiveHandler, self).__init__(backend, proto, stateless_rpc)
+        super().__init__(backend, proto, stateless_rpc)
         self.repo = backend.open_repository(args[0])
         self.repo = backend.open_repository(args[0])
 
 
     def handle(self):
     def handle(self):

+ 1 - 2
dulwich/stash.py

@@ -20,7 +20,6 @@
 
 
 """Stash handling."""
 """Stash handling."""
 
 
-from __future__ import absolute_import
 
 
 import os
 import os
 
 
@@ -35,7 +34,7 @@ from dulwich.reflog import drop_reflog_entry, read_reflog
 DEFAULT_STASH_REF = b"refs/stash"
 DEFAULT_STASH_REF = b"refs/stash"
 
 
 
 
-class Stash(object):
+class Stash:
     """A Git stash.
     """A Git stash.
 
 
     Note that this doesn't currently update the working tree.
     Note that this doesn't currently update the working tree.

+ 1 - 1
dulwich/tests/__init__.py

@@ -48,7 +48,7 @@ from unittest import (  # noqa: F401
 
 
 class TestCase(_TestCase):
 class TestCase(_TestCase):
     def setUp(self):
     def setUp(self):
-        super(TestCase, self).setUp()
+        super().setUp()
         self.overrideEnv("HOME", "/nonexistent")
         self.overrideEnv("HOME", "/nonexistent")
         self.overrideEnv("GIT_CONFIG_NOSYSTEM", "1")
         self.overrideEnv("GIT_CONFIG_NOSYSTEM", "1")
 
 

+ 4 - 4
dulwich/tests/compat/server_utils.py

@@ -43,7 +43,7 @@ from dulwich.tests.compat.utils import (
 from dulwich.tests.compat.utils import require_git_version
 from dulwich.tests.compat.utils import require_git_version
 
 
 
 
-class _StubRepo(object):
+class _StubRepo:
     """A stub repo that just contains a path to tear down."""
     """A stub repo that just contains a path to tear down."""
 
 
     def __init__(self, name):
     def __init__(self, name):
@@ -70,7 +70,7 @@ def _get_shallow(repo):
     return shallows
     return shallows
 
 
 
 
-class ServerTests(object):
+class ServerTests:
     """Base tests for testing servers.
     """Base tests for testing servers.
 
 
     Does not inherit from TestCase so tests are not automatically run.
     Does not inherit from TestCase so tests are not automatically run.
@@ -87,12 +87,12 @@ class ServerTests(object):
         self._new_repo = self.import_repo("server_new.export")
         self._new_repo = self.import_repo("server_new.export")
 
 
     def url(self, port):
     def url(self, port):
-        return "%s://localhost:%s/" % (self.protocol, port)
+        return "{}://localhost:{}/".format(self.protocol, port)
 
 
     def branch_args(self, branches=None):
     def branch_args(self, branches=None):
         if branches is None:
         if branches is None:
             branches = ["master", "branch"]
             branches = ["master", "branch"]
-        return ["%s:%s" % (b, b) for b in branches]
+        return ["{}:{}".format(b, b) for b in branches]
 
 
     def test_push_to_dulwich(self):
     def test_push_to_dulwich(self):
         self.import_repos()
         self.import_repos()

+ 8 - 10
dulwich/tests/compat/test_client.py

@@ -62,7 +62,7 @@ if sys.platform == "win32":
     import ctypes
     import ctypes
 
 
 
 
-class DulwichClientTestBase(object):
+class DulwichClientTestBase:
     """Tests for client/server compatibility."""
     """Tests for client/server compatibility."""
 
 
     def setUp(self):
     def setUp(self):
@@ -248,12 +248,10 @@ class DulwichClientTestBase(object):
                 dest.refs.set_if_equals(r[0], None, r[1])
                 dest.refs.set_if_equals(r[0], None, r[1])
             self.assertEqual(
             self.assertEqual(
                 dest.get_shallow(),
                 dest.get_shallow(),
-                set(
-                    [
-                        b"35e0b59e187dd72a0af294aedffc213eaa4d03ff",
-                        b"514dc6d3fbfe77361bcaef320c4d21b72bc10be9",
-                    ]
-                ),
+                {
+                    b"35e0b59e187dd72a0af294aedffc213eaa4d03ff",
+                    b"514dc6d3fbfe77361bcaef320c4d21b72bc10be9",
+                },
             )
             )
 
 
     def test_repeat(self):
     def test_repeat(self):
@@ -409,7 +407,7 @@ class DulwichTCPClientTest(CompatTestCase, DulwichClientTestBase):
             try:
             try:
                 os.kill(pid, signal.SIGKILL)
                 os.kill(pid, signal.SIGKILL)
                 os.unlink(self.pidfile)
                 os.unlink(self.pidfile)
-            except (OSError, IOError):
+            except OSError:
                 pass
                 pass
         self.process.wait()
         self.process.wait()
         self.process.stdout.close()
         self.process.stdout.close()
@@ -435,7 +433,7 @@ class DulwichTCPClientTest(CompatTestCase, DulwichClientTestBase):
         self.skipTest('skip flaky test; see #1015')
         self.skipTest('skip flaky test; see #1015')
 
 
 
 
-class TestSSHVendor(object):
+class TestSSHVendor:
     @staticmethod
     @staticmethod
     def run_command(
     def run_command(
         host,
         host,
@@ -648,7 +646,7 @@ class HTTPGitServer(http.server.HTTPServer):
         self.server_name = "localhost"
         self.server_name = "localhost"
 
 
     def get_url(self):
     def get_url(self):
-        return "http://%s:%s/" % (self.server_name, self.server_port)
+        return "http://{}:{}/".format(self.server_name, self.server_port)
 
 
 
 
 class DulwichHttpClientTest(CompatTestCase, DulwichClientTestBase):
 class DulwichHttpClientTest(CompatTestCase, DulwichClientTestBase):

+ 1 - 1
dulwich/tests/compat/test_pack.py

@@ -66,7 +66,7 @@ class TestPack(PackTests):
 
 
     def setUp(self):
     def setUp(self):
         require_git_version((1, 5, 0))
         require_git_version((1, 5, 0))
-        super(TestPack, self).setUp()
+        super().setUp()
         self._tempdir = tempfile.mkdtemp()
         self._tempdir = tempfile.mkdtemp()
         self.addCleanup(shutil.rmtree, self._tempdir)
         self.addCleanup(shutil.rmtree, self._tempdir)
 
 

+ 1 - 1
dulwich/tests/compat/test_patch.py

@@ -36,7 +36,7 @@ from dulwich.tests.compat.utils import (
 
 
 class CompatPatchTestCase(CompatTestCase):
 class CompatPatchTestCase(CompatTestCase):
     def setUp(self):
     def setUp(self):
-        super(CompatPatchTestCase, self).setUp()
+        super().setUp()
         self.test_dir = tempfile.mkdtemp()
         self.test_dir = tempfile.mkdtemp()
         self.addCleanup(shutil.rmtree, self.test_dir)
         self.addCleanup(shutil.rmtree, self.test_dir)
         self.repo_path = os.path.join(self.test_dir, "repo")
         self.repo_path = os.path.join(self.test_dir, "repo")

+ 3 - 3
dulwich/tests/compat/test_porcelain.py

@@ -41,7 +41,7 @@ from dulwich.tests.test_porcelain import (
 @skipIf(platform.python_implementation() == "PyPy" or sys.platform == "win32", "gpgme not easily available or supported on Windows and PyPy")
 @skipIf(platform.python_implementation() == "PyPy" or sys.platform == "win32", "gpgme not easily available or supported on Windows and PyPy")
 class TagCreateSignTestCase(PorcelainGpgTestCase, CompatTestCase):
 class TagCreateSignTestCase(PorcelainGpgTestCase, CompatTestCase):
     def setUp(self):
     def setUp(self):
-        super(TagCreateSignTestCase, self).setUp()
+        super().setUp()
 
 
     def test_sign(self):
     def test_sign(self):
         # Test that dulwich signatures can be verified by CGit
         # Test that dulwich signatures can be verified by CGit
@@ -64,7 +64,7 @@ class TagCreateSignTestCase(PorcelainGpgTestCase, CompatTestCase):
 
 
         run_git_or_fail(
         run_git_or_fail(
             [
             [
-                "--git-dir={}".format(self.repo.controldir()),
+                f"--git-dir={self.repo.controldir()}",
                 "tag",
                 "tag",
                 "-v",
                 "-v",
                 "tryme"
                 "tryme"
@@ -82,7 +82,7 @@ class TagCreateSignTestCase(PorcelainGpgTestCase, CompatTestCase):
 
 
         run_git_or_fail(
         run_git_or_fail(
             [
             [
-                "--git-dir={}".format(self.repo.controldir()),
+                f"--git-dir={self.repo.controldir()}",
                 "tag",
                 "tag",
                 "-u",
                 "-u",
                 PorcelainGpgTestCase.DEFAULT_KEY_ID,
                 PorcelainGpgTestCase.DEFAULT_KEY_ID,

+ 4 - 4
dulwich/tests/compat/test_repository.py

@@ -45,7 +45,7 @@ class ObjectStoreTestCase(CompatTestCase):
     """Tests for git repository compatibility."""
     """Tests for git repository compatibility."""
 
 
     def setUp(self):
     def setUp(self):
-        super(ObjectStoreTestCase, self).setUp()
+        super().setUp()
         self._repo = self.import_repo("server_new.export")
         self._repo = self.import_repo("server_new.export")
 
 
     def _run_git(self, args):
     def _run_git(self, args):
@@ -147,7 +147,7 @@ class WorkingTreeTestCase(ObjectStoreTestCase):
         return temp_dir
         return temp_dir
 
 
     def setUp(self):
     def setUp(self):
-        super(WorkingTreeTestCase, self).setUp()
+        super().setUp()
         self._worktree_path = self.create_new_worktree(self._repo.path, "branch")
         self._worktree_path = self.create_new_worktree(self._repo.path, "branch")
         self._worktree_repo = Repo(self._worktree_path)
         self._worktree_repo = Repo(self._worktree_path)
         self.addCleanup(self._worktree_repo.close)
         self.addCleanup(self._worktree_repo.close)
@@ -156,7 +156,7 @@ class WorkingTreeTestCase(ObjectStoreTestCase):
         self._repo = self._worktree_repo
         self._repo = self._worktree_repo
 
 
     def test_refs(self):
     def test_refs(self):
-        super(WorkingTreeTestCase, self).test_refs()
+        super().test_refs()
         self.assertEqual(
         self.assertEqual(
             self._mainworktree_repo.refs.allkeys(), self._repo.refs.allkeys()
             self._mainworktree_repo.refs.allkeys(), self._repo.refs.allkeys()
         )
         )
@@ -225,7 +225,7 @@ class InitNewWorkingDirectoryTestCase(WorkingTreeTestCase):
     min_git_version = (2, 5, 0)
     min_git_version = (2, 5, 0)
 
 
     def setUp(self):
     def setUp(self):
-        super(InitNewWorkingDirectoryTestCase, self).setUp()
+        super().setUp()
         self._other_worktree = self._repo
         self._other_worktree = self._repo
         worktree_repo_path = tempfile.mkdtemp()
         worktree_repo_path = tempfile.mkdtemp()
         self.addCleanup(rmtree_ro, worktree_repo_path)
         self.addCleanup(rmtree_ro, worktree_repo_path)

+ 1 - 1
dulwich/tests/compat/test_server.py

@@ -81,7 +81,7 @@ class GitServerSideBand64kTestCase(GitServerTestCase):
     min_git_version = (1, 7, 0, 2)
     min_git_version = (1, 7, 0, 2)
 
 
     def setUp(self):
     def setUp(self):
-        super(GitServerSideBand64kTestCase, self).setUp()
+        super().setUp()
         # side-band-64k is broken in the windows client.
         # side-band-64k is broken in the windows client.
         # https://github.com/msysgit/git/issues/101
         # https://github.com/msysgit/git/issues/101
         # Fix has landed for the 1.9.3 release.
         # Fix has landed for the 1.9.3 release.

+ 2 - 2
dulwich/tests/compat/test_utils.py

@@ -29,7 +29,7 @@ from dulwich.tests.compat import utils
 
 
 class GitVersionTests(TestCase):
 class GitVersionTests(TestCase):
     def setUp(self):
     def setUp(self):
-        super(GitVersionTests, self).setUp()
+        super().setUp()
         self._orig_run_git = utils.run_git
         self._orig_run_git = utils.run_git
         self._version_str = None  # tests can override to set stub version
         self._version_str = None  # tests can override to set stub version
 
 
@@ -40,7 +40,7 @@ class GitVersionTests(TestCase):
         utils.run_git = run_git
         utils.run_git = run_git
 
 
     def tearDown(self):
     def tearDown(self):
-        super(GitVersionTests, self).tearDown()
+        super().tearDown()
         utils.run_git = self._orig_run_git
         utils.run_git = self._orig_run_git
 
 
     def test_git_version_none(self):
     def test_git_version_none(self):

+ 2 - 2
dulwich/tests/compat/test_web.py

@@ -135,10 +135,10 @@ class SmartWebSideBand64kTestCase(SmartWebTestCase):
     def setUp(self):
     def setUp(self):
         self.o_uph_cap = patch_capabilities(UploadPackHandler, (b"no-done",))
         self.o_uph_cap = patch_capabilities(UploadPackHandler, (b"no-done",))
         self.o_rph_cap = patch_capabilities(ReceivePackHandler, (b"no-done",))
         self.o_rph_cap = patch_capabilities(ReceivePackHandler, (b"no-done",))
-        super(SmartWebSideBand64kTestCase, self).setUp()
+        super().setUp()
 
 
     def tearDown(self):
     def tearDown(self):
-        super(SmartWebSideBand64kTestCase, self).tearDown()
+        super().tearDown()
         UploadPackHandler.capabilities = self.o_uph_cap
         UploadPackHandler.capabilities = self.o_uph_cap
         ReceivePackHandler.capabilities = self.o_rph_cap
         ReceivePackHandler.capabilities = self.o_rph_cap
 
 

+ 4 - 4
dulwich/tests/compat/utils.py

@@ -94,7 +94,7 @@ def require_git_version(required_version, git_path=_DEFAULT_GIT):
     found_version = git_version(git_path=git_path)
     found_version = git_version(git_path=git_path)
     if found_version is None:
     if found_version is None:
         raise SkipTest(
         raise SkipTest(
-            "Test requires git >= %s, but c git not found" % (required_version,)
+            "Test requires git >= {}, but c git not found".format(required_version)
         )
         )
 
 
     if len(required_version) > _VERSION_LEN:
     if len(required_version) > _VERSION_LEN:
@@ -112,7 +112,7 @@ def require_git_version(required_version, git_path=_DEFAULT_GIT):
         required_version = ".".join(map(str, required_version))
         required_version = ".".join(map(str, required_version))
         found_version = ".".join(map(str, found_version))
         found_version = ".".join(map(str, found_version))
         raise SkipTest(
         raise SkipTest(
-            "Test requires git >= %s, found %s" % (required_version, found_version)
+            "Test requires git >= {}, found {}".format(required_version, found_version)
         )
         )
 
 
 
 
@@ -216,7 +216,7 @@ def check_for_daemon(limit=10, delay=0.1, timeout=0.1, port=TCP_GIT_PORT):
             return True
             return True
         except socket.timeout:
         except socket.timeout:
             pass
             pass
-        except socket.error as e:
+        except OSError as e:
             if getattr(e, "errno", False) and e.errno != errno.ECONNREFUSED:
             if getattr(e, "errno", False) and e.errno != errno.ECONNREFUSED:
                 raise
                 raise
             elif e.args[0] != errno.ECONNREFUSED:
             elif e.args[0] != errno.ECONNREFUSED:
@@ -236,7 +236,7 @@ class CompatTestCase(TestCase):
     min_git_version: Tuple[int, ...] = (1, 5, 0)
     min_git_version: Tuple[int, ...] = (1, 5, 0)
 
 
     def setUp(self):
     def setUp(self):
-        super(CompatTestCase, self).setUp()
+        super().setUp()
         require_git_version(self.min_git_version)
         require_git_version(self.min_git_version)
 
 
     def assertObjectStoreEqual(self, store1, store2):
     def assertObjectStoreEqual(self, store1, store2):

+ 1 - 1
dulwich/tests/test_archive.py

@@ -78,7 +78,7 @@ class ArchiveTests(TestCase):
         b1 = Blob.from_string(b"somedata")
         b1 = Blob.from_string(b"somedata")
         store.add_object(b1)
         store.add_object(b1)
         t1 = Tree()
         t1 = Tree()
-        t1.add("ő".encode('utf-8'), 0o100644, b1.id)
+        t1.add("ő".encode(), 0o100644, b1.id)
         store.add_object(t1)
         store.add_object(t1)
         stream = b"".join(tar_stream(store, t1, mtime=0))
         stream = b"".join(tar_stream(store, t1, mtime=0))
         tf = tarfile.TarFile(fileobj=BytesIO(stream))
         tf = tarfile.TarFile(fileobj=BytesIO(stream))

+ 2 - 2
dulwich/tests/test_blackbox.py

@@ -35,7 +35,7 @@ class GitReceivePackTests(BlackboxTestCase):
     """Blackbox tests for dul-receive-pack."""
     """Blackbox tests for dul-receive-pack."""
 
 
     def setUp(self):
     def setUp(self):
-        super(GitReceivePackTests, self).setUp()
+        super().setUp()
         self.path = tempfile.mkdtemp()
         self.path = tempfile.mkdtemp()
         self.addCleanup(shutil.rmtree, self.path)
         self.addCleanup(shutil.rmtree, self.path)
         self.repo = Repo.init(self.path)
         self.repo = Repo.init(self.path)
@@ -60,7 +60,7 @@ class GitUploadPackTests(BlackboxTestCase):
     """Blackbox tests for dul-upload-pack."""
     """Blackbox tests for dul-upload-pack."""
 
 
     def setUp(self):
     def setUp(self):
-        super(GitUploadPackTests, self).setUp()
+        super().setUp()
         self.path = tempfile.mkdtemp()
         self.path = tempfile.mkdtemp()
         self.addCleanup(shutil.rmtree, self.path)
         self.addCleanup(shutil.rmtree, self.path)
         self.repo = Repo.init(self.path)
         self.repo = Repo.init(self.path)

+ 24 - 28
dulwich/tests/test_client.py

@@ -118,7 +118,7 @@ class DummyPopen:
 # TODO(durin42): add unit-level tests of GitClient
 # TODO(durin42): add unit-level tests of GitClient
 class GitClientTests(TestCase):
 class GitClientTests(TestCase):
     def setUp(self):
     def setUp(self):
-        super(GitClientTests, self).setUp()
+        super().setUp()
         self.rout = BytesIO()
         self.rout = BytesIO()
         self.rin = BytesIO()
         self.rin = BytesIO()
         self.client = DummyClient(lambda x: True, self.rin.read, self.rout.write)
         self.client = DummyClient(lambda x: True, self.rin.read, self.rout.write)
@@ -126,29 +126,25 @@ class GitClientTests(TestCase):
     def test_caps(self):
     def test_caps(self):
         agent_cap = ("agent=dulwich/%d.%d.%d" % dulwich.__version__).encode("ascii")
         agent_cap = ("agent=dulwich/%d.%d.%d" % dulwich.__version__).encode("ascii")
         self.assertEqual(
         self.assertEqual(
-            set(
-                [
-                    b"multi_ack",
-                    b"side-band-64k",
-                    b"ofs-delta",
-                    b"thin-pack",
-                    b"multi_ack_detailed",
-                    b"shallow",
-                    agent_cap,
-                ]
-            ),
+            {
+                b"multi_ack",
+                b"side-band-64k",
+                b"ofs-delta",
+                b"thin-pack",
+                b"multi_ack_detailed",
+                b"shallow",
+                agent_cap,
+            },
             set(self.client._fetch_capabilities),
             set(self.client._fetch_capabilities),
         )
         )
         self.assertEqual(
         self.assertEqual(
-            set(
-                [
-                    b"delete-refs",
-                    b"ofs-delta",
-                    b"report-status",
-                    b"side-band-64k",
-                    agent_cap,
-                ]
-            ),
+            {
+                b"delete-refs",
+                b"ofs-delta",
+                b"report-status",
+                b"side-band-64k",
+                agent_cap,
+            },
             set(self.client._send_capabilities),
             set(self.client._send_capabilities),
         )
         )
 
 
@@ -720,7 +716,7 @@ class TestGetTransportAndPathFromUrl(TestCase):
                     c, path = get_transport_and_path(remote_url)
                     c, path = get_transport_and_path(remote_url)
 
 
 
 
-class TestSSHVendor(object):
+class TestSSHVendor:
     def __init__(self):
     def __init__(self):
         self.host = None
         self.host = None
         self.command = ""
         self.command = ""
@@ -759,7 +755,7 @@ class TestSSHVendor(object):
 
 
 class SSHGitClientTests(TestCase):
 class SSHGitClientTests(TestCase):
     def setUp(self):
     def setUp(self):
-        super(SSHGitClientTests, self).setUp()
+        super().setUp()
 
 
         self.server = TestSSHVendor()
         self.server = TestSSHVendor()
         self.real_vendor = client.get_ssh_vendor
         self.real_vendor = client.get_ssh_vendor
@@ -768,7 +764,7 @@ class SSHGitClientTests(TestCase):
         self.client = SSHGitClient("git.samba.org")
         self.client = SSHGitClient("git.samba.org")
 
 
     def tearDown(self):
     def tearDown(self):
-        super(SSHGitClientTests, self).tearDown()
+        super().tearDown()
         client.get_ssh_vendor = self.real_vendor
         client.get_ssh_vendor = self.real_vendor
 
 
     def test_get_url(self):
     def test_get_url(self):
@@ -1013,7 +1009,7 @@ class HttpGitClientTests(TestCase):
         self.assertEqual("passwd", c._password)
         self.assertEqual("passwd", c._password)
 
 
         basic_auth = c.pool_manager.headers["authorization"]
         basic_auth = c.pool_manager.headers["authorization"]
-        auth_string = "%s:%s" % ("user", "passwd")
+        auth_string = "{}:{}".format("user", "passwd")
         b64_credentials = base64.b64encode(auth_string.encode("latin1"))
         b64_credentials = base64.b64encode(auth_string.encode("latin1"))
         expected_basic_auth = "Basic %s" % b64_credentials.decode("latin1")
         expected_basic_auth = "Basic %s" % b64_credentials.decode("latin1")
         self.assertEqual(basic_auth, expected_basic_auth)
         self.assertEqual(basic_auth, expected_basic_auth)
@@ -1069,7 +1065,7 @@ class HttpGitClientTests(TestCase):
         self.assertEqual(original_password, c._password)
         self.assertEqual(original_password, c._password)
 
 
         basic_auth = c.pool_manager.headers["authorization"]
         basic_auth = c.pool_manager.headers["authorization"]
-        auth_string = "%s:%s" % (original_username, original_password)
+        auth_string = "{}:{}".format(original_username, original_password)
         b64_credentials = base64.b64encode(auth_string.encode("latin1"))
         b64_credentials = base64.b64encode(auth_string.encode("latin1"))
         expected_basic_auth = "Basic %s" % b64_credentials.decode("latin1")
         expected_basic_auth = "Basic %s" % b64_credentials.decode("latin1")
         self.assertEqual(basic_auth, expected_basic_auth)
         self.assertEqual(basic_auth, expected_basic_auth)
@@ -1527,7 +1523,7 @@ class PLinkSSHVendorTests(TestCase):
                 break
                 break
         else:
         else:
             raise AssertionError(
             raise AssertionError(
-                "Expected warning %r not in %r" % (expected_warning, warnings_list)
+                "Expected warning {!r} not in {!r}".format(expected_warning, warnings_list)
             )
             )
 
 
         args = command.proc.args
         args = command.proc.args
@@ -1572,7 +1568,7 @@ class PLinkSSHVendorTests(TestCase):
                 break
                 break
         else:
         else:
             raise AssertionError(
             raise AssertionError(
-                "Expected warning %r not in %r" % (expected_warning, warnings_list)
+                "Expected warning {!r} not in {!r}".format(expected_warning, warnings_list)
             )
             )
 
 
         args = command.proc.args
         args = command.proc.args

+ 3 - 3
dulwich/tests/test_diff_tree.py

@@ -64,7 +64,7 @@ from dulwich.tests.utils import (
 
 
 class DiffTestCase(TestCase):
 class DiffTestCase(TestCase):
     def setUp(self):
     def setUp(self):
-        super(DiffTestCase, self).setUp()
+        super().setUp()
         self.store = MemoryObjectStore()
         self.store = MemoryObjectStore()
         self.empty_tree = self.commit_tree([])
         self.empty_tree = self.commit_tree([])
 
 
@@ -87,7 +87,7 @@ class DiffTestCase(TestCase):
 
 
 class TreeChangesTest(DiffTestCase):
 class TreeChangesTest(DiffTestCase):
     def setUp(self):
     def setUp(self):
-        super(TreeChangesTest, self).setUp()
+        super().setUp()
         self.detector = RenameDetector(self.store)
         self.detector = RenameDetector(self.store)
 
 
     def assertMergeFails(self, merge_entries, name, mode, sha):
     def assertMergeFails(self, merge_entries, name, mode, sha):
@@ -699,7 +699,7 @@ class RenameDetectionTest(DiffTestCase):
 
 
         block_cache = {}
         block_cache = {}
         self.assertEqual(50, _similarity_score(blob1, blob2, block_cache=block_cache))
         self.assertEqual(50, _similarity_score(blob1, blob2, block_cache=block_cache))
-        self.assertEqual(set([blob1.id, blob2.id]), set(block_cache))
+        self.assertEqual({blob1.id, blob2.id}, set(block_cache))
 
 
         def fail_chunks():
         def fail_chunks():
             self.fail("Unexpected call to as_raw_chunks()")
             self.fail("Unexpected call to as_raw_chunks()")

+ 2 - 2
dulwich/tests/test_fastexport.py

@@ -47,7 +47,7 @@ class GitFastExporterTests(TestCase):
     """Tests for the GitFastExporter tests."""
     """Tests for the GitFastExporter tests."""
 
 
     def setUp(self):
     def setUp(self):
-        super(GitFastExporterTests, self).setUp()
+        super().setUp()
         self.store = MemoryObjectStore()
         self.store = MemoryObjectStore()
         self.stream = BytesIO()
         self.stream = BytesIO()
         try:
         try:
@@ -96,7 +96,7 @@ class GitImportProcessorTests(TestCase):
     """Tests for the GitImportProcessor tests."""
     """Tests for the GitImportProcessor tests."""
 
 
     def setUp(self):
     def setUp(self):
-        super(GitImportProcessorTests, self).setUp()
+        super().setUp()
         self.repo = MemoryRepo()
         self.repo = MemoryRepo()
         try:
         try:
             from dulwich.fastexport import GitImportProcessor
             from dulwich.fastexport import GitImportProcessor

+ 6 - 6
dulwich/tests/test_file.py

@@ -33,7 +33,7 @@ from dulwich.tests import (
 
 
 class FancyRenameTests(TestCase):
 class FancyRenameTests(TestCase):
     def setUp(self):
     def setUp(self):
-        super(FancyRenameTests, self).setUp()
+        super().setUp()
         self._tempdir = tempfile.mkdtemp()
         self._tempdir = tempfile.mkdtemp()
         self.foo = self.path("foo")
         self.foo = self.path("foo")
         self.bar = self.path("bar")
         self.bar = self.path("bar")
@@ -41,7 +41,7 @@ class FancyRenameTests(TestCase):
 
 
     def tearDown(self):
     def tearDown(self):
         shutil.rmtree(self._tempdir)
         shutil.rmtree(self._tempdir)
-        super(FancyRenameTests, self).tearDown()
+        super().tearDown()
 
 
     def path(self, filename):
     def path(self, filename):
         return os.path.join(self._tempdir, filename)
         return os.path.join(self._tempdir, filename)
@@ -89,7 +89,7 @@ class FancyRenameTests(TestCase):
 
 
 class GitFileTests(TestCase):
 class GitFileTests(TestCase):
     def setUp(self):
     def setUp(self):
-        super(GitFileTests, self).setUp()
+        super().setUp()
         self._tempdir = tempfile.mkdtemp()
         self._tempdir = tempfile.mkdtemp()
         f = open(self.path("foo"), "wb")
         f = open(self.path("foo"), "wb")
         f.write(b"foo contents")
         f.write(b"foo contents")
@@ -97,7 +97,7 @@ class GitFileTests(TestCase):
 
 
     def tearDown(self):
     def tearDown(self):
         shutil.rmtree(self._tempdir)
         shutil.rmtree(self._tempdir)
-        super(GitFileTests, self).tearDown()
+        super().tearDown()
 
 
     def path(self, filename):
     def path(self, filename):
         return os.path.join(self._tempdir, filename)
         return os.path.join(self._tempdir, filename)
@@ -191,14 +191,14 @@ class GitFileTests(TestCase):
         f.abort()
         f.abort()
         try:
         try:
             f.close()
             f.close()
-        except (IOError, OSError):
+        except OSError:
             self.fail()
             self.fail()
 
 
         f = GitFile(foo, "wb")
         f = GitFile(foo, "wb")
         f.close()
         f.close()
         try:
         try:
             f.abort()
             f.abort()
-        except (IOError, OSError):
+        except OSError:
             self.fail()
             self.fail()
 
 
     def test_abort_close_removed(self):
     def test_abort_close_removed(self):

+ 4 - 4
dulwich/tests/test_grafts.py

@@ -104,9 +104,9 @@ class GraftSerializerTests(TestCase):
         )
         )
 
 
 
 
-class GraftsInRepositoryBase(object):
+class GraftsInRepositoryBase:
     def tearDown(self):
     def tearDown(self):
-        super(GraftsInRepositoryBase, self).tearDown()
+        super().tearDown()
 
 
     def get_repo_with_grafts(self, grafts):
     def get_repo_with_grafts(self, grafts):
         r = self._repo
         r = self._repo
@@ -148,7 +148,7 @@ class GraftsInRepositoryBase(object):
 
 
 class GraftsInRepoTests(GraftsInRepositoryBase, TestCase):
 class GraftsInRepoTests(GraftsInRepositoryBase, TestCase):
     def setUp(self):
     def setUp(self):
-        super(GraftsInRepoTests, self).setUp()
+        super().setUp()
         self._repo_dir = os.path.join(tempfile.mkdtemp())
         self._repo_dir = os.path.join(tempfile.mkdtemp())
         r = self._repo = Repo.init(self._repo_dir)
         r = self._repo = Repo.init(self._repo_dir)
         self.addCleanup(shutil.rmtree, self._repo_dir)
         self.addCleanup(shutil.rmtree, self._repo_dir)
@@ -188,7 +188,7 @@ class GraftsInRepoTests(GraftsInRepositoryBase, TestCase):
 
 
 class GraftsInMemoryRepoTests(GraftsInRepositoryBase, TestCase):
 class GraftsInMemoryRepoTests(GraftsInRepositoryBase, TestCase):
     def setUp(self):
     def setUp(self):
-        super(GraftsInMemoryRepoTests, self).setUp()
+        super().setUp()
         r = self._repo = MemoryRepo()
         r = self._repo = MemoryRepo()
 
 
         self._shas = []
         self._shas = []

+ 7 - 8
dulwich/tests/test_graph.py

@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
 # test_index.py -- Tests for merge
 # test_index.py -- Tests for merge
 # encoding: utf-8
 # encoding: utf-8
 # Copyright (c) 2020 Kevin B. Hendricks, Stratford Ontario Canada
 # Copyright (c) 2020 Kevin B. Hendricks, Stratford Ontario Canada
@@ -48,7 +47,7 @@ class FindMergeBaseTests(TestCase):
             "1": [],
             "1": [],
             "0": [],
             "0": [],
         }
         }
-        self.assertEqual(self.run_test(graph, ["4", "5"]), set(["1", "2"]))
+        self.assertEqual(self.run_test(graph, ["4", "5"]), {"1", "2"})
 
 
     def test_no_common_ancestor(self):
     def test_no_common_ancestor(self):
         # no common ancestor
         # no common ancestor
@@ -59,7 +58,7 @@ class FindMergeBaseTests(TestCase):
             "1": ["0"],
             "1": ["0"],
             "0": [],
             "0": [],
         }
         }
-        self.assertEqual(self.run_test(graph, ["4", "3"]), set([]))
+        self.assertEqual(self.run_test(graph, ["4", "3"]), set())
 
 
     def test_ancestor(self):
     def test_ancestor(self):
         # ancestor
         # ancestor
@@ -72,7 +71,7 @@ class FindMergeBaseTests(TestCase):
             "B": ["A"],
             "B": ["A"],
             "A": [],
             "A": [],
         }
         }
-        self.assertEqual(self.run_test(graph, ["D", "C"]), set(["C"]))
+        self.assertEqual(self.run_test(graph, ["D", "C"]), {"C"})
 
 
     def test_direct_parent(self):
     def test_direct_parent(self):
         # parent
         # parent
@@ -85,7 +84,7 @@ class FindMergeBaseTests(TestCase):
             "B": ["A"],
             "B": ["A"],
             "A": [],
             "A": [],
         }
         }
-        self.assertEqual(self.run_test(graph, ["G", "D"]), set(["D"]))
+        self.assertEqual(self.run_test(graph, ["G", "D"]), {"D"})
 
 
     def test_another_crossover(self):
     def test_another_crossover(self):
         # Another cross over
         # Another cross over
@@ -98,7 +97,7 @@ class FindMergeBaseTests(TestCase):
             "B": ["A"],
             "B": ["A"],
             "A": [],
             "A": [],
         }
         }
-        self.assertEqual(self.run_test(graph, ["D", "F"]), set(["E", "C"]))
+        self.assertEqual(self.run_test(graph, ["D", "F"]), {"E", "C"})
 
 
     def test_three_way_merge_lca(self):
     def test_three_way_merge_lca(self):
         # three way merge commit straight from git docs
         # three way merge commit straight from git docs
@@ -121,7 +120,7 @@ class FindMergeBaseTests(TestCase):
         }
         }
         # assumes a theoretical merge M exists that merges B and C first
         # assumes a theoretical merge M exists that merges B and C first
         # which actually means find the first LCA from either of B OR C with A
         # which actually means find the first LCA from either of B OR C with A
-        self.assertEqual(self.run_test(graph, ["A", "B", "C"]), set(["1"]))
+        self.assertEqual(self.run_test(graph, ["A", "B", "C"]), {"1"})
 
 
     def test_octopus(self):
     def test_octopus(self):
         # octopus algorithm test
         # octopus algorithm test
@@ -156,7 +155,7 @@ class FindMergeBaseTests(TestCase):
                 res = _find_lcas(lookup_parents, cmt, [ca])
                 res = _find_lcas(lookup_parents, cmt, [ca])
                 next_lcas.extend(res)
                 next_lcas.extend(res)
             lcas = next_lcas[:]
             lcas = next_lcas[:]
-        self.assertEqual(set(lcas), set(["2"]))
+        self.assertEqual(set(lcas), {"2"})
 
 
 
 
 class CanFastForwardTests(TestCase):
 class CanFastForwardTests(TestCase):

+ 2 - 2
dulwich/tests/test_greenthreads.py

@@ -80,7 +80,7 @@ def init_store(store, count=1):
 @skipIf(not gevent_support, skipmsg)
 @skipIf(not gevent_support, skipmsg)
 class TestGreenThreadsObjectStoreIterator(TestCase):
 class TestGreenThreadsObjectStoreIterator(TestCase):
     def setUp(self):
     def setUp(self):
-        super(TestGreenThreadsObjectStoreIterator, self).setUp()
+        super().setUp()
         self.store = MemoryObjectStore()
         self.store = MemoryObjectStore()
         self.cmt_amount = 10
         self.cmt_amount = 10
         self.objs = init_store(self.store, self.cmt_amount)
         self.objs = init_store(self.store, self.cmt_amount)
@@ -116,7 +116,7 @@ class TestGreenThreadsObjectStoreIterator(TestCase):
 @skipIf(not gevent_support, skipmsg)
 @skipIf(not gevent_support, skipmsg)
 class TestGreenThreadsMissingObjectFinder(TestCase):
 class TestGreenThreadsMissingObjectFinder(TestCase):
     def setUp(self):
     def setUp(self):
-        super(TestGreenThreadsMissingObjectFinder, self).setUp()
+        super().setUp()
         self.store = MemoryObjectStore()
         self.store = MemoryObjectStore()
         self.cmt_amount = 10
         self.cmt_amount = 10
         self.objs = init_store(self.store, self.cmt_amount)
         self.objs = init_store(self.store, self.cmt_amount)

+ 1 - 1
dulwich/tests/test_hooks.py

@@ -38,7 +38,7 @@ from dulwich.tests import TestCase
 
 
 class ShellHookTests(TestCase):
 class ShellHookTests(TestCase):
     def setUp(self):
     def setUp(self):
-        super(ShellHookTests, self).setUp()
+        super().setUp()
         if os.name != "posix":
         if os.name != "posix":
             self.skipTest("shell hook tests requires POSIX shell")
             self.skipTest("shell hook tests requires POSIX shell")
         self.assertTrue(os.path.exists("/bin/sh"))
         self.assertTrue(os.path.exists("/bin/sh"))

+ 2 - 2
dulwich/tests/test_ignore.py

@@ -133,14 +133,14 @@ class MatchPatternTests(TestCase):
         for (path, pattern) in POSITIVE_MATCH_TESTS:
         for (path, pattern) in POSITIVE_MATCH_TESTS:
             self.assertTrue(
             self.assertTrue(
                 match_pattern(path, pattern),
                 match_pattern(path, pattern),
-                "path: %r, pattern: %r" % (path, pattern),
+                "path: {!r}, pattern: {!r}".format(path, pattern),
             )
             )
 
 
     def test_no_matches(self):
     def test_no_matches(self):
         for (path, pattern) in NEGATIVE_MATCH_TESTS:
         for (path, pattern) in NEGATIVE_MATCH_TESTS:
             self.assertFalse(
             self.assertFalse(
                 match_pattern(path, pattern),
                 match_pattern(path, pattern),
-                "path: %r, pattern: %r" % (path, pattern),
+                "path: {!r}, pattern: {!r}".format(path, pattern),
             )
             )
 
 
 
 

+ 12 - 13
dulwich/tests/test_index.py

@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
 # test_index.py -- Tests for the git index
 # test_index.py -- Tests for the git index
 # encoding: utf-8
 # encoding: utf-8
 # Copyright (C) 2008-2009 Jelmer Vernooij <jelmer@jelmer.uk>
 # Copyright (C) 2008-2009 Jelmer Vernooij <jelmer@jelmer.uk>
@@ -203,7 +202,7 @@ class ReadIndexDictTests(IndexTestCase):
 
 
 class CommitTreeTests(TestCase):
 class CommitTreeTests(TestCase):
     def setUp(self):
     def setUp(self):
-        super(CommitTreeTests, self).setUp()
+        super().setUp()
         self.store = MemoryObjectStore()
         self.store = MemoryObjectStore()
 
 
     def test_single_blob(self):
     def test_single_blob(self):
@@ -214,7 +213,7 @@ class CommitTreeTests(TestCase):
         rootid = commit_tree(self.store, blobs)
         rootid = commit_tree(self.store, blobs)
         self.assertEqual(rootid, b"1a1e80437220f9312e855c37ac4398b68e5c1d50")
         self.assertEqual(rootid, b"1a1e80437220f9312e855c37ac4398b68e5c1d50")
         self.assertEqual((stat.S_IFREG, blob.id), self.store[rootid][b"bla"])
         self.assertEqual((stat.S_IFREG, blob.id), self.store[rootid][b"bla"])
-        self.assertEqual(set([rootid, blob.id]), set(self.store._data.keys()))
+        self.assertEqual({rootid, blob.id}, set(self.store._data.keys()))
 
 
     def test_nested(self):
     def test_nested(self):
         blob = Blob()
         blob = Blob()
@@ -227,12 +226,12 @@ class CommitTreeTests(TestCase):
         self.assertEqual(dirid, b"c1a1deb9788150829579a8b4efa6311e7b638650")
         self.assertEqual(dirid, b"c1a1deb9788150829579a8b4efa6311e7b638650")
         self.assertEqual((stat.S_IFDIR, dirid), self.store[rootid][b"bla"])
         self.assertEqual((stat.S_IFDIR, dirid), self.store[rootid][b"bla"])
         self.assertEqual((stat.S_IFREG, blob.id), self.store[dirid][b"bar"])
         self.assertEqual((stat.S_IFREG, blob.id), self.store[dirid][b"bar"])
-        self.assertEqual(set([rootid, dirid, blob.id]), set(self.store._data.keys()))
+        self.assertEqual({rootid, dirid, blob.id}, set(self.store._data.keys()))
 
 
 
 
 class CleanupModeTests(TestCase):
 class CleanupModeTests(TestCase):
     def assertModeEqual(self, expected, got):
     def assertModeEqual(self, expected, got):
-        self.assertEqual(expected, got, "%o != %o" % (expected, got))
+        self.assertEqual(expected, got, "{:o} != {:o}".format(expected, got))
 
 
     def test_file(self):
     def test_file(self):
         self.assertModeEqual(0o100644, cleanup_mode(0o100000))
         self.assertModeEqual(0o100644, cleanup_mode(0o100000))
@@ -547,9 +546,9 @@ class BuildIndexTests(TestCase):
             file = Blob.from_string(b"foo")
             file = Blob.from_string(b"foo")
 
 
             tree = Tree()
             tree = Tree()
-            latin1_name = u"À".encode("latin1")
+            latin1_name = "À".encode("latin1")
             latin1_path = os.path.join(repo_dir_bytes, latin1_name)
             latin1_path = os.path.join(repo_dir_bytes, latin1_name)
-            utf8_name = u"À".encode("utf8")
+            utf8_name = "À".encode()
             utf8_path = os.path.join(repo_dir_bytes, utf8_name)
             utf8_path = os.path.join(repo_dir_bytes, utf8_name)
             tree[latin1_name] = (stat.S_IFREG | 0o644, file.id)
             tree[latin1_name] = (stat.S_IFREG | 0o644, file.id)
             tree[utf8_name] = (stat.S_IFREG | 0o644, file.id)
             tree[utf8_name] = (stat.S_IFREG | 0o644, file.id)
@@ -795,19 +794,19 @@ class TestValidatePathElement(TestCase):
 
 
 class TestTreeFSPathConversion(TestCase):
 class TestTreeFSPathConversion(TestCase):
     def test_tree_to_fs_path(self):
     def test_tree_to_fs_path(self):
-        tree_path = u"délwíçh/foo".encode("utf8")
+        tree_path = "délwíçh/foo".encode()
         fs_path = _tree_to_fs_path(b"/prefix/path", tree_path)
         fs_path = _tree_to_fs_path(b"/prefix/path", tree_path)
         self.assertEqual(
         self.assertEqual(
             fs_path,
             fs_path,
-            os.fsencode(os.path.join(u"/prefix/path", u"délwíçh", u"foo")),
+            os.fsencode(os.path.join("/prefix/path", "délwíçh", "foo")),
         )
         )
 
 
     def test_fs_to_tree_path_str(self):
     def test_fs_to_tree_path_str(self):
-        fs_path = os.path.join(os.path.join(u"délwíçh", u"foo"))
+        fs_path = os.path.join(os.path.join("délwíçh", "foo"))
         tree_path = _fs_to_tree_path(fs_path)
         tree_path = _fs_to_tree_path(fs_path)
-        self.assertEqual(tree_path, u"délwíçh/foo".encode("utf-8"))
+        self.assertEqual(tree_path, "délwíçh/foo".encode())
 
 
     def test_fs_to_tree_path_bytes(self):
     def test_fs_to_tree_path_bytes(self):
-        fs_path = os.path.join(os.fsencode(os.path.join(u"délwíçh", u"foo")))
+        fs_path = os.path.join(os.fsencode(os.path.join("délwíçh", "foo")))
         tree_path = _fs_to_tree_path(fs_path)
         tree_path = _fs_to_tree_path(fs_path)
-        self.assertEqual(tree_path, u"délwíçh/foo".encode("utf-8"))
+        self.assertEqual(tree_path, "délwíçh/foo".encode())

+ 1 - 1
dulwich/tests/test_lfs.py

@@ -28,7 +28,7 @@ import tempfile
 
 
 class LFSTests(TestCase):
 class LFSTests(TestCase):
     def setUp(self):
     def setUp(self):
-        super(LFSTests, self).setUp()
+        super().setUp()
         self.test_dir = tempfile.mkdtemp()
         self.test_dir = tempfile.mkdtemp()
         self.addCleanup(shutil.rmtree, self.test_dir)
         self.addCleanup(shutil.rmtree, self.test_dir)
         self.lfs = LFSStore.create(self.test_dir)
         self.lfs = LFSStore.create(self.test_dir)

+ 0 - 1
dulwich/tests/test_line_ending.py

@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
 # test_line_ending.py -- Tests for the line ending functions
 # test_line_ending.py -- Tests for the line ending functions
 # encoding: utf-8
 # encoding: utf-8
 # Copyright (C) 2018-2019 Boris Feld <boris.feld@comet.ml>
 # Copyright (C) 2018-2019 Boris Feld <boris.feld@comet.ml>

+ 6 - 6
dulwich/tests/test_missing_obj_finder.py

@@ -34,7 +34,7 @@ from dulwich.tests.utils import (
 
 
 class MissingObjectFinderTest(TestCase):
 class MissingObjectFinderTest(TestCase):
     def setUp(self):
     def setUp(self):
-        super(MissingObjectFinderTest, self).setUp()
+        super().setUp()
         self.store = MemoryObjectStore()
         self.store = MemoryObjectStore()
         self.commits = []
         self.commits = []
 
 
@@ -46,20 +46,20 @@ class MissingObjectFinderTest(TestCase):
             self.assertIn(
             self.assertIn(
                 sha,
                 sha,
                 expected,
                 expected,
-                "(%s,%s) erroneously reported as missing" % (sha, path)
+                "({},{}) erroneously reported as missing".format(sha, path)
             )
             )
             expected.remove(sha)
             expected.remove(sha)
 
 
         self.assertEqual(
         self.assertEqual(
             len(expected),
             len(expected),
             0,
             0,
-            "some objects are not reported as missing: %s" % (expected,),
+            "some objects are not reported as missing: {}".format(expected),
         )
         )
 
 
 
 
 class MOFLinearRepoTest(MissingObjectFinderTest):
 class MOFLinearRepoTest(MissingObjectFinderTest):
     def setUp(self):
     def setUp(self):
-        super(MOFLinearRepoTest, self).setUp()
+        super().setUp()
         # present in 1, removed in 3
         # present in 1, removed in 3
         f1_1 = make_object(Blob, data=b"f1")
         f1_1 = make_object(Blob, data=b"f1")
         # present in all revisions, changed in 2 and 3
         # present in all revisions, changed in 2 and 3
@@ -130,7 +130,7 @@ class MOFMergeForkRepoTest(MissingObjectFinderTest):
     #             5
     #             5
 
 
     def setUp(self):
     def setUp(self):
-        super(MOFMergeForkRepoTest, self).setUp()
+        super().setUp()
         f1_1 = make_object(Blob, data=b"f1")
         f1_1 = make_object(Blob, data=b"f1")
         f1_2 = make_object(Blob, data=b"f1-2")
         f1_2 = make_object(Blob, data=b"f1-2")
         f1_4 = make_object(Blob, data=b"f1-4")
         f1_4 = make_object(Blob, data=b"f1-4")
@@ -256,7 +256,7 @@ class MOFMergeForkRepoTest(MissingObjectFinderTest):
 
 
 class MOFTagsTest(MissingObjectFinderTest):
 class MOFTagsTest(MissingObjectFinderTest):
     def setUp(self):
     def setUp(self):
-        super(MOFTagsTest, self).setUp()
+        super().setUp()
         f1_1 = make_object(Blob, data=b"f1")
         f1_1 = make_object(Blob, data=b"f1")
         commit_spec = [[1]]
         commit_spec = [[1]]
         trees = {1: [(b"f1", f1_1)]}
         trees = {1: [(b"f1", f1_1)]}

+ 7 - 7
dulwich/tests/test_object_store.py

@@ -77,7 +77,7 @@ except ImportError:
 testobject = make_object(Blob, data=b"yummy data")
 testobject = make_object(Blob, data=b"yummy data")
 
 
 
 
-class ObjectStoreTests(object):
+class ObjectStoreTests:
     def test_determine_wants_all(self):
     def test_determine_wants_all(self):
         self.assertEqual(
         self.assertEqual(
             [b"1" * 40],
             [b"1" * 40],
@@ -164,7 +164,7 @@ class ObjectStoreTests(object):
 
 
     def test_add_object(self):
     def test_add_object(self):
         self.store.add_object(testobject)
         self.store.add_object(testobject)
-        self.assertEqual(set([testobject.id]), set(self.store))
+        self.assertEqual({testobject.id}, set(self.store))
         self.assertIn(testobject.id, self.store)
         self.assertIn(testobject.id, self.store)
         r = self.store[testobject.id]
         r = self.store[testobject.id]
         self.assertEqual(r, testobject)
         self.assertEqual(r, testobject)
@@ -172,7 +172,7 @@ class ObjectStoreTests(object):
     def test_add_objects(self):
     def test_add_objects(self):
         data = [(testobject, "mypath")]
         data = [(testobject, "mypath")]
         self.store.add_objects(data)
         self.store.add_objects(data)
-        self.assertEqual(set([testobject.id]), set(self.store))
+        self.assertEqual({testobject.id}, set(self.store))
         self.assertIn(testobject.id, self.store)
         self.assertIn(testobject.id, self.store)
         r = self.store[testobject.id]
         r = self.store[testobject.id]
         self.assertEqual(r, testobject)
         self.assertEqual(r, testobject)
@@ -626,9 +626,9 @@ class TreeLookupPathTests(TestCase):
 
 
 class ObjectStoreGraphWalkerTests(TestCase):
 class ObjectStoreGraphWalkerTests(TestCase):
     def get_walker(self, heads, parent_map):
     def get_walker(self, heads, parent_map):
-        new_parent_map = dict(
-            [(k * 40, [(p * 40) for p in ps]) for (k, ps) in parent_map.items()]
-        )
+        new_parent_map = {
+            k * 40: [(p * 40) for p in ps] for (k, ps) in parent_map.items()
+        }
         return ObjectStoreGraphWalker(
         return ObjectStoreGraphWalker(
             [x * 40 for x in heads], new_parent_map.__getitem__
             [x * 40 for x in heads], new_parent_map.__getitem__
         )
         )
@@ -707,7 +707,7 @@ class ObjectStoreGraphWalkerTests(TestCase):
 
 
 class CommitTreeChangesTests(TestCase):
 class CommitTreeChangesTests(TestCase):
     def setUp(self):
     def setUp(self):
-        super(CommitTreeChangesTests, self).setUp()
+        super().setUp()
         self.store = MemoryObjectStore()
         self.store = MemoryObjectStore()
         self.blob_a = make_object(Blob, data=b"a")
         self.blob_a = make_object(Blob, data=b"a")
         self.blob_b = make_object(Blob, data=b"b")
         self.blob_b = make_object(Blob, data=b"b")

+ 5 - 5
dulwich/tests/test_objects.py

@@ -980,7 +980,7 @@ class TreeTests(ShaFileCheckTests):
     def test_iter(self):
     def test_iter(self):
         t = Tree()
         t = Tree()
         t[b"foo"] = (0o100644, a_sha)
         t[b"foo"] = (0o100644, a_sha)
-        self.assertEqual(set([b"foo"]), set(t))
+        self.assertEqual({b"foo"}, set(t))
 
 
 
 
 class TagSerializeTests(TestCase):
 class TagSerializeTests(TestCase):
@@ -1143,7 +1143,7 @@ class TagParseTests(ShaFileCheckTests):
 
 
     def test_check_tag_with_overflow_time(self):
     def test_check_tag_with_overflow_time(self):
         """Date with overflow should raise an ObjectFormatException when checked"""
         """Date with overflow should raise an ObjectFormatException when checked"""
-        author = "Some Dude <some@dude.org> %s +0000" % (MAX_TIME + 1,)
+        author = "Some Dude <some@dude.org> {} +0000".format(MAX_TIME + 1)
         tag = Tag.from_string(self.make_tag_text(tagger=(author.encode())))
         tag = Tag.from_string(self.make_tag_text(tagger=(author.encode())))
         with self.assertRaises(ObjectFormatException):
         with self.assertRaises(ObjectFormatException):
             tag.check()
             tag.check()
@@ -1301,14 +1301,14 @@ class TimezoneTests(TestCase):
         self.assertEqual(b"-0440", format_timezone(int(((-4 * 60) - 40) * 60)))
         self.assertEqual(b"-0440", format_timezone(int(((-4 * 60) - 40) * 60)))
 
 
     def test_format_timezone_double_negative(self):
     def test_format_timezone_double_negative(self):
-        self.assertEqual(b"--700", format_timezone(int(((7 * 60)) * 60), True))
+        self.assertEqual(b"--700", format_timezone(int((7 * 60) * 60), True))
 
 
     def test_parse_timezone_pdt_half(self):
     def test_parse_timezone_pdt_half(self):
         self.assertEqual((((-4 * 60) - 40) * 60, False), parse_timezone(b"-0440"))
         self.assertEqual((((-4 * 60) - 40) * 60, False), parse_timezone(b"-0440"))
 
 
     def test_parse_timezone_double_negative(self):
     def test_parse_timezone_double_negative(self):
-        self.assertEqual((int(((7 * 60)) * 60), False), parse_timezone(b"+700"))
-        self.assertEqual((int(((7 * 60)) * 60), True), parse_timezone(b"--700"))
+        self.assertEqual((int((7 * 60) * 60), False), parse_timezone(b"+700"))
+        self.assertEqual((int((7 * 60) * 60), True), parse_timezone(b"--700"))
 
 
 
 
 class ShaFileCopyTests(TestCase):
 class ShaFileCopyTests(TestCase):

+ 29 - 31
dulwich/tests/test_pack.py

@@ -91,7 +91,7 @@ class PackTests(TestCase):
     """Base class for testing packs"""
     """Base class for testing packs"""
 
 
     def setUp(self):
     def setUp(self):
-        super(PackTests, self).setUp()
+        super().setUp()
         self.tempdir = tempfile.mkdtemp()
         self.tempdir = tempfile.mkdtemp()
         self.addCleanup(shutil.rmtree, self.tempdir)
         self.addCleanup(shutil.rmtree, self.tempdir)
 
 
@@ -171,7 +171,7 @@ class PackIndexTests(PackTests):
 
 
     def test_iter(self):
     def test_iter(self):
         p = self.get_pack_index(pack1_sha)
         p = self.get_pack_index(pack1_sha)
-        self.assertEqual(set([tree_sha, commit_sha, a_sha]), set(p))
+        self.assertEqual({tree_sha, commit_sha, a_sha}, set(p))
 
 
 
 
 class TestPackDeltas(TestCase):
 class TestPackDeltas(TestCase):
@@ -313,25 +313,23 @@ class TestPackData(PackTests):
         with self.get_pack_data(pack1_sha) as p:
         with self.get_pack_data(pack1_sha) as p:
             entries = {(sha_to_hex(s), o, c) for s, o, c in p.iterentries()}
             entries = {(sha_to_hex(s), o, c) for s, o, c in p.iterentries()}
             self.assertEqual(
             self.assertEqual(
-                set(
-                    [
-                        (
-                            b"6f670c0fb53f9463760b7295fbb814e965fb20c8",
-                            178,
-                            1373561701,
-                        ),
-                        (
-                            b"b2a2766a2879c209ab1176e7e778b81ae422eeaa",
-                            138,
-                            912998690,
-                        ),
-                        (
-                            b"f18faa16531ac570a3fdc8c7ca16682548dafd12",
-                            12,
-                            3775879613,
-                        ),
-                    ]
-                ),
+                {
+                    (
+                        b"6f670c0fb53f9463760b7295fbb814e965fb20c8",
+                        178,
+                        1373561701,
+                    ),
+                    (
+                        b"b2a2766a2879c209ab1176e7e778b81ae422eeaa",
+                        138,
+                        912998690,
+                    ),
+                    (
+                        b"f18faa16531ac570a3fdc8c7ca16682548dafd12",
+                        12,
+                        3775879613,
+                    ),
+                },
                 entries,
                 entries,
             )
             )
 
 
@@ -399,17 +397,17 @@ class TestPack(PackTests):
 
 
     def test_iter(self):
     def test_iter(self):
         with self.get_pack(pack1_sha) as p:
         with self.get_pack(pack1_sha) as p:
-            self.assertEqual(set([tree_sha, commit_sha, a_sha]), set(p))
+            self.assertEqual({tree_sha, commit_sha, a_sha}, set(p))
 
 
     def test_iterobjects(self):
     def test_iterobjects(self):
         with self.get_pack(pack1_sha) as p:
         with self.get_pack(pack1_sha) as p:
-            expected = set([p[s] for s in [commit_sha, tree_sha, a_sha]])
+            expected = {p[s] for s in [commit_sha, tree_sha, a_sha]}
             self.assertEqual(expected, set(list(p.iterobjects())))
             self.assertEqual(expected, set(list(p.iterobjects())))
 
 
     def test_pack_tuples(self):
     def test_pack_tuples(self):
         with self.get_pack(pack1_sha) as p:
         with self.get_pack(pack1_sha) as p:
             tuples = p.pack_tuples()
             tuples = p.pack_tuples()
-            expected = set([(p[s], None) for s in [commit_sha, tree_sha, a_sha]])
+            expected = {(p[s], None) for s in [commit_sha, tree_sha, a_sha]}
             self.assertEqual(expected, set(list(tuples)))
             self.assertEqual(expected, set(list(tuples)))
             self.assertEqual(expected, set(list(tuples)))
             self.assertEqual(expected, set(list(tuples)))
             self.assertEqual(3, len(tuples))
             self.assertEqual(3, len(tuples))
@@ -468,7 +466,7 @@ class TestPack(PackTests):
         # file should exist
         # file should exist
         self.assertTrue(os.path.exists(keepfile_name))
         self.assertTrue(os.path.exists(keepfile_name))
 
 
-        with open(keepfile_name, "r") as f:
+        with open(keepfile_name) as f:
             buf = f.read()
             buf = f.read()
             self.assertEqual("", buf)
             self.assertEqual("", buf)
 
 
@@ -535,7 +533,7 @@ class TestPack(PackTests):
 
 
 class TestThinPack(PackTests):
 class TestThinPack(PackTests):
     def setUp(self):
     def setUp(self):
-        super(TestThinPack, self).setUp()
+        super().setUp()
         self.store = MemoryObjectStore()
         self.store = MemoryObjectStore()
         self.blobs = {}
         self.blobs = {}
         for blob in (b"foo", b"bar", b"foo1234", b"bar2468"):
         for blob in (b"foo", b"bar", b"foo1234", b"bar2468"):
@@ -664,7 +662,7 @@ class WritePackTests(TestCase):
 pack_checksum = hex_to_sha("721980e866af9a5f93ad674144e1459b8ba3e7b7")
 pack_checksum = hex_to_sha("721980e866af9a5f93ad674144e1459b8ba3e7b7")
 
 
 
 
-class BaseTestPackIndexWriting(object):
+class BaseTestPackIndexWriting:
     def assertSucceeds(self, func, *args, **kwargs):
     def assertSucceeds(self, func, *args, **kwargs):
         try:
         try:
             func(*args, **kwargs)
             func(*args, **kwargs)
@@ -801,7 +799,7 @@ class ReadZlibTests(TestCase):
     extra = b"nextobject"
     extra = b"nextobject"
 
 
     def setUp(self):
     def setUp(self):
-        super(ReadZlibTests, self).setUp()
+        super().setUp()
         self.read = BytesIO(self.comp + self.extra).read
         self.read = BytesIO(self.comp + self.extra).read
         self.unpacked = UnpackedObject(Tree.type_num, None, len(self.decomp), 0)
         self.unpacked = UnpackedObject(Tree.type_num, None, len(self.decomp), 0)
 
 
@@ -953,7 +951,7 @@ class TestPackIterator(DeltaChainIterator):
     _compute_crc32 = True
     _compute_crc32 = True
 
 
     def __init__(self, *args, **kwargs):
     def __init__(self, *args, **kwargs):
-        super(TestPackIterator, self).__init__(*args, **kwargs)
+        super().__init__(*args, **kwargs)
         self._unpacked_offsets = set()
         self._unpacked_offsets = set()
 
 
     def _result(self, unpacked):
     def _result(self, unpacked):
@@ -971,14 +969,14 @@ class TestPackIterator(DeltaChainIterator):
             "Attempted to re-inflate offset %i" % offset
             "Attempted to re-inflate offset %i" % offset
         )
         )
         self._unpacked_offsets.add(offset)
         self._unpacked_offsets.add(offset)
-        return super(TestPackIterator, self)._resolve_object(
+        return super()._resolve_object(
             offset, pack_type_num, base_chunks
             offset, pack_type_num, base_chunks
         )
         )
 
 
 
 
 class DeltaChainIteratorTests(TestCase):
 class DeltaChainIteratorTests(TestCase):
     def setUp(self):
     def setUp(self):
-        super(DeltaChainIteratorTests, self).setUp()
+        super().setUp()
         self.store = MemoryObjectStore()
         self.store = MemoryObjectStore()
         self.fetched = set()
         self.fetched = set()
 
 

+ 31 - 33
dulwich/tests/test_porcelain.py

@@ -86,7 +86,7 @@ def flat_walk_dir(dir_to_walk):
 
 
 class PorcelainTestCase(TestCase):
 class PorcelainTestCase(TestCase):
     def setUp(self):
     def setUp(self):
-        super(PorcelainTestCase, self).setUp()
+        super().setUp()
         self.test_dir = tempfile.mkdtemp()
         self.test_dir = tempfile.mkdtemp()
         self.addCleanup(shutil.rmtree, self.test_dir)
         self.addCleanup(shutil.rmtree, self.test_dir)
         self.repo_path = os.path.join(self.test_dir, "repo")
         self.repo_path = os.path.join(self.test_dir, "repo")
@@ -274,7 +274,7 @@ ya6JVZCRbMXfdCy8lVPgtNQ6VlHaj8Wvnn2FLbWWO2n2r3s=
     NON_DEFAULT_KEY_ID = "6A93393F50C5E6ACD3D6FB45B936212EDB4E14C0"
     NON_DEFAULT_KEY_ID = "6A93393F50C5E6ACD3D6FB45B936212EDB4E14C0"
 
 
     def setUp(self):
     def setUp(self):
-        super(PorcelainGpgTestCase, self).setUp()
+        super().setUp()
         self.gpg_dir = os.path.join(self.test_dir, "gpg")
         self.gpg_dir = os.path.join(self.test_dir, "gpg")
         os.mkdir(self.gpg_dir, mode=0o700)
         os.mkdir(self.gpg_dir, mode=0o700)
         # Ignore errors when deleting GNUPGHOME, because of race conditions
         # Ignore errors when deleting GNUPGHOME, because of race conditions
@@ -289,7 +289,7 @@ ya6JVZCRbMXfdCy8lVPgtNQ6VlHaj8Wvnn2FLbWWO2n2r3s=
             stdout=subprocess.DEVNULL,
             stdout=subprocess.DEVNULL,
             stderr=subprocess.DEVNULL,
             stderr=subprocess.DEVNULL,
             input=PorcelainGpgTestCase.DEFAULT_KEY,
             input=PorcelainGpgTestCase.DEFAULT_KEY,
-            universal_newlines=True,
+            text=True,
         )
         )
 
 
     def import_non_default_key(self):
     def import_non_default_key(self):
@@ -298,7 +298,7 @@ ya6JVZCRbMXfdCy8lVPgtNQ6VlHaj8Wvnn2FLbWWO2n2r3s=
             stdout=subprocess.DEVNULL,
             stdout=subprocess.DEVNULL,
             stderr=subprocess.DEVNULL,
             stderr=subprocess.DEVNULL,
             input=PorcelainGpgTestCase.NON_DEFAULT_KEY,
             input=PorcelainGpgTestCase.NON_DEFAULT_KEY,
-            universal_newlines=True,
+            text=True,
         )
         )
 
 
 
 
@@ -906,7 +906,7 @@ class AddTests(PorcelainTestCase):
         cwd = os.getcwd()
         cwd = os.getcwd()
         try:
         try:
             os.chdir(self.repo.path)
             os.chdir(self.repo.path)
-            self.assertEqual(set(["foo", "blah", "adir", ".git"]), set(os.listdir(".")))
+            self.assertEqual({"foo", "blah", "adir", ".git"}, set(os.listdir(".")))
             self.assertEqual(
             self.assertEqual(
                 (["foo", os.path.join("adir", "afile")], set()),
                 (["foo", os.path.join("adir", "afile")], set()),
                 porcelain.add(self.repo.path),
                 porcelain.add(self.repo.path),
@@ -967,8 +967,8 @@ class AddTests(PorcelainTestCase):
             ],
             ],
         )
         )
         self.assertIn(b"bar", self.repo.open_index())
         self.assertIn(b"bar", self.repo.open_index())
-        self.assertEqual(set(["bar"]), set(added))
-        self.assertEqual(set(["foo", os.path.join("subdir", "")]), ignored)
+        self.assertEqual({"bar"}, set(added))
+        self.assertEqual({"foo", os.path.join("subdir", "")}, ignored)
 
 
     def test_add_file_absolute_path(self):
     def test_add_file_absolute_path(self):
         # Absolute paths are (not yet) supported
         # Absolute paths are (not yet) supported
@@ -1554,7 +1554,7 @@ class ResetFileTests(PorcelainTestCase):
             f.write('something new')
             f.write('something new')
         porcelain.reset_file(self.repo, file, target=sha)
         porcelain.reset_file(self.repo, file, target=sha)
 
 
-        with open(full_path, 'r') as f:
+        with open(full_path) as f:
             self.assertEqual('hello', f.read())
             self.assertEqual('hello', f.read())
 
 
     def test_reset_remove_file_to_commit(self):
     def test_reset_remove_file_to_commit(self):
@@ -1573,7 +1573,7 @@ class ResetFileTests(PorcelainTestCase):
         os.remove(full_path)
         os.remove(full_path)
         porcelain.reset_file(self.repo, file, target=sha)
         porcelain.reset_file(self.repo, file, target=sha)
 
 
-        with open(full_path, 'r') as f:
+        with open(full_path) as f:
             self.assertEqual('hello', f.read())
             self.assertEqual('hello', f.read())
 
 
     def test_resetfile_with_dir(self):
     def test_resetfile_with_dir(self):
@@ -1598,7 +1598,7 @@ class ResetFileTests(PorcelainTestCase):
             author=b"John <john@example.com>",
             author=b"John <john@example.com>",
         )
         )
         porcelain.reset_file(self.repo, os.path.join('new_dir', 'foo'), target=sha)
         porcelain.reset_file(self.repo, os.path.join('new_dir', 'foo'), target=sha)
-        with open(full_path, 'r') as f:
+        with open(full_path) as f:
             self.assertEqual('hello', f.read())
             self.assertEqual('hello', f.read())
 
 
 
 
@@ -1616,7 +1616,7 @@ class SubmoduleTests(PorcelainTestCase):
 
 
     def test_add(self):
     def test_add(self):
         porcelain.submodule_add(self.repo, "../bar.git", "bar")
         porcelain.submodule_add(self.repo, "../bar.git", "bar")
-        with open('%s/.gitmodules' % self.repo.path, 'r') as f:
+        with open('%s/.gitmodules' % self.repo.path) as f:
             self.assertEqual("""\
             self.assertEqual("""\
 [submodule "bar"]
 [submodule "bar"]
 \turl = ../bar.git
 \turl = ../bar.git
@@ -1901,7 +1901,7 @@ class PushTests(PorcelainTestCase):
 
 
 class PullTests(PorcelainTestCase):
 class PullTests(PorcelainTestCase):
     def setUp(self):
     def setUp(self):
-        super(PullTests, self).setUp()
+        super().setUp()
         # create a file for initial commit
         # create a file for initial commit
         handle, fullpath = tempfile.mkstemp(dir=self.repo.path)
         handle, fullpath = tempfile.mkstemp(dir=self.repo.path)
         os.close(handle)
         os.close(handle)
@@ -2301,7 +2301,7 @@ class StatusTests(PorcelainTestCase):
             os.path.join(self.repo.path, "link"),
             os.path.join(self.repo.path, "link"),
         )
         )
         self.assertEqual(
         self.assertEqual(
-            set(["ignored", "notignored", ".gitignore", "link"]),
+            {"ignored", "notignored", ".gitignore", "link"},
             set(
             set(
                 porcelain.get_untracked_paths(
                 porcelain.get_untracked_paths(
                     self.repo.path, self.repo.path, self.repo.open_index()
                     self.repo.path, self.repo.path, self.repo.open_index()
@@ -2309,11 +2309,11 @@ class StatusTests(PorcelainTestCase):
             ),
             ),
         )
         )
         self.assertEqual(
         self.assertEqual(
-            set([".gitignore", "notignored", "link"]),
+            {".gitignore", "notignored", "link"},
             set(porcelain.status(self.repo).untracked),
             set(porcelain.status(self.repo).untracked),
         )
         )
         self.assertEqual(
         self.assertEqual(
-            set([".gitignore", "notignored", "ignored", "link"]),
+            {".gitignore", "notignored", "ignored", "link"},
             set(porcelain.status(self.repo, ignored=True).untracked),
             set(porcelain.status(self.repo, ignored=True).untracked),
         )
         )
 
 
@@ -2332,7 +2332,7 @@ class StatusTests(PorcelainTestCase):
             f.write("blop\n")
             f.write("blop\n")
 
 
         self.assertEqual(
         self.assertEqual(
-            set([".gitignore", "notignored", os.path.join("nested", "")]),
+            {".gitignore", "notignored", os.path.join("nested", "")},
             set(
             set(
                 porcelain.get_untracked_paths(
                 porcelain.get_untracked_paths(
                     self.repo.path, self.repo.path, self.repo.open_index()
                     self.repo.path, self.repo.path, self.repo.open_index()
@@ -2340,7 +2340,7 @@ class StatusTests(PorcelainTestCase):
             ),
             ),
         )
         )
         self.assertEqual(
         self.assertEqual(
-            set([".gitignore", "notignored"]),
+            {".gitignore", "notignored"},
             set(
             set(
                 porcelain.get_untracked_paths(
                 porcelain.get_untracked_paths(
                     self.repo.path,
                     self.repo.path,
@@ -2351,7 +2351,7 @@ class StatusTests(PorcelainTestCase):
             ),
             ),
         )
         )
         self.assertEqual(
         self.assertEqual(
-            set(["ignored", "with", "manager"]),
+            {"ignored", "with", "manager"},
             set(
             set(
                 porcelain.get_untracked_paths(
                 porcelain.get_untracked_paths(
                     subrepo.path, subrepo.path, subrepo.open_index()
                     subrepo.path, subrepo.path, subrepo.open_index()
@@ -2369,9 +2369,9 @@ class StatusTests(PorcelainTestCase):
             ),
             ),
         )
         )
         self.assertEqual(
         self.assertEqual(
-            set([os.path.join('nested', 'ignored'),
+            {os.path.join('nested', 'ignored'),
                 os.path.join('nested', 'with'),
                 os.path.join('nested', 'with'),
-                os.path.join('nested', 'manager')]),
+                os.path.join('nested', 'manager')},
             set(
             set(
                 porcelain.get_untracked_paths(
                 porcelain.get_untracked_paths(
                     self.repo.path,
                     self.repo.path,
@@ -2393,14 +2393,12 @@ class StatusTests(PorcelainTestCase):
             f.write("foo")
             f.write("foo")
 
 
         self.assertEqual(
         self.assertEqual(
-            set(
-                [
-                    ".gitignore",
-                    "notignored",
-                    "ignored",
-                    os.path.join("subdir", ""),
-                ]
-            ),
+            {
+                ".gitignore",
+                "notignored",
+                "ignored",
+                os.path.join("subdir", ""),
+            },
             set(
             set(
                 porcelain.get_untracked_paths(
                 porcelain.get_untracked_paths(
                     self.repo.path,
                     self.repo.path,
@@ -2410,7 +2408,7 @@ class StatusTests(PorcelainTestCase):
             )
             )
         )
         )
         self.assertEqual(
         self.assertEqual(
-            set([".gitignore", "notignored"]),
+            {".gitignore", "notignored"},
             set(
             set(
                 porcelain.get_untracked_paths(
                 porcelain.get_untracked_paths(
                     self.repo.path,
                     self.repo.path,
@@ -2488,14 +2486,14 @@ class ReceivePackTests(PorcelainTestCase):
 
 
 class BranchListTests(PorcelainTestCase):
 class BranchListTests(PorcelainTestCase):
     def test_standard(self):
     def test_standard(self):
-        self.assertEqual(set([]), set(porcelain.branch_list(self.repo)))
+        self.assertEqual(set(), set(porcelain.branch_list(self.repo)))
 
 
     def test_new_branch(self):
     def test_new_branch(self):
         [c1] = build_commit_graph(self.repo.object_store, [[1]])
         [c1] = build_commit_graph(self.repo.object_store, [[1]])
         self.repo[b"HEAD"] = c1.id
         self.repo[b"HEAD"] = c1.id
         porcelain.branch_create(self.repo, b"foo")
         porcelain.branch_create(self.repo, b"foo")
         self.assertEqual(
         self.assertEqual(
-            set([b"master", b"foo"]), set(porcelain.branch_list(self.repo))
+            {b"master", b"foo"}, set(porcelain.branch_list(self.repo))
         )
         )
 
 
 
 
@@ -2512,7 +2510,7 @@ class BranchCreateTests(PorcelainTestCase):
         self.repo[b"HEAD"] = c1.id
         self.repo[b"HEAD"] = c1.id
         porcelain.branch_create(self.repo, b"foo")
         porcelain.branch_create(self.repo, b"foo")
         self.assertEqual(
         self.assertEqual(
-            set([b"master", b"foo"]), set(porcelain.branch_list(self.repo))
+            {b"master", b"foo"}, set(porcelain.branch_list(self.repo))
         )
         )
 
 
 
 
@@ -3023,7 +3021,7 @@ class DescribeTests(PorcelainTestCase):
 
 
 class PathToTreeTests(PorcelainTestCase):
 class PathToTreeTests(PorcelainTestCase):
     def setUp(self):
     def setUp(self):
-        super(PathToTreeTests, self).setUp()
+        super().setUp()
         self.fp = os.path.join(self.test_dir, "bar")
         self.fp = os.path.join(self.test_dir, "bar")
         with open(self.fp, "w") as f:
         with open(self.fp, "w") as f:
             f.write("something")
             f.write("something")

+ 1 - 1
dulwich/tests/test_protocol.py

@@ -42,7 +42,7 @@ from dulwich.protocol import (
 from dulwich.tests import TestCase
 from dulwich.tests import TestCase
 
 
 
 
-class BaseProtocolTests(object):
+class BaseProtocolTests:
     def test_write_pkt_line_none(self):
     def test_write_pkt_line_none(self):
         self.proto.write_pkt_line(None)
         self.proto.write_pkt_line(None)
         self.assertEqual(self.rout.getvalue(), b"0000")
         self.assertEqual(self.rout.getvalue(), b"0000")

+ 0 - 1
dulwich/tests/test_reflog.py

@@ -1,5 +1,4 @@
 # test_reflog.py -- tests for reflog.py
 # test_reflog.py -- tests for reflog.py
-# encoding: utf-8
 # Copyright (C) 2015 Jelmer Vernooij <jelmer@jelmer.uk>
 # Copyright (C) 2015 Jelmer Vernooij <jelmer@jelmer.uk>
 #
 #
 # Dulwich is dual-licensed under the Apache License, Version 2.0 and the GNU
 # Dulwich is dual-licensed under the Apache License, Version 2.0 and the GNU

+ 2 - 3
dulwich/tests/test_refs.py

@@ -1,5 +1,4 @@
 # test_refs.py -- tests for refs.py
 # test_refs.py -- tests for refs.py
-# encoding: utf-8
 # Copyright (C) 2013 Jelmer Vernooij <jelmer@jelmer.uk>
 # Copyright (C) 2013 Jelmer Vernooij <jelmer@jelmer.uk>
 #
 #
 # Dulwich is dual-licensed under the Apache License, Version 2.0 and the GNU
 # Dulwich is dual-licensed under the Apache License, Version 2.0 and the GNU
@@ -172,7 +171,7 @@ _TEST_REFS = {
 }
 }
 
 
 
 
-class RefsContainerTests(object):
+class RefsContainerTests:
     def test_keys(self):
     def test_keys(self):
         actual_keys = set(self._refs.keys())
         actual_keys = set(self._refs.keys())
         self.assertEqual(set(self._refs.allkeys()), actual_keys)
         self.assertEqual(set(self._refs.allkeys()), actual_keys)
@@ -700,7 +699,7 @@ class DiskRefsContainerTests(RefsContainerTests, TestCase):
 
 
     def test_non_ascii(self):
     def test_non_ascii(self):
         try:
         try:
-            encoded_ref = os.fsencode(u"refs/tags/schön")
+            encoded_ref = os.fsencode("refs/tags/schön")
         except UnicodeEncodeError as exc:
         except UnicodeEncodeError as exc:
             raise SkipTest(
             raise SkipTest(
                 "filesystem encoding doesn't support special character"
                 "filesystem encoding doesn't support special character"

+ 11 - 12
dulwich/tests/test_repository.py

@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
 # test_repository.py -- tests for repository.py
 # test_repository.py -- tests for repository.py
 # Copyright (C) 2007 James Westby <jw+debian@jameswestby.net>
 # Copyright (C) 2007 James Westby <jw+debian@jameswestby.net>
 #
 #
@@ -332,7 +331,7 @@ class RepositoryRootTests(TestCase):
         self.assertFilesystemHidden(os.path.join(repo_dir, ".git"))
         self.assertFilesystemHidden(os.path.join(repo_dir, ".git"))
 
 
     def test_init_mkdir_unicode(self):
     def test_init_mkdir_unicode(self):
-        repo_name = u"\xa7"
+        repo_name = "\xa7"
         try:
         try:
             os.fsencode(repo_name)
             os.fsencode(repo_name)
         except UnicodeEncodeError:
         except UnicodeEncodeError:
@@ -543,7 +542,7 @@ class RepositoryRootTests(TestCase):
         ``Repo.fetch_objects()``).
         ``Repo.fetch_objects()``).
         """
         """
 
 
-        expected_shas = set([b"60dacdc733de308bb77bb76ce0fb0f9b44c9769e"])
+        expected_shas = {b"60dacdc733de308bb77bb76ce0fb0f9b44c9769e"}
 
 
         # Source for objects.
         # Source for objects.
         r_base = self.open_repo("simple_merge.git")
         r_base = self.open_repo("simple_merge.git")
@@ -690,9 +689,9 @@ exit 0
         if os.name != "posix":
         if os.name != "posix":
             self.skipTest("shell hook tests requires POSIX shell")
             self.skipTest("shell hook tests requires POSIX shell")
 
 
-        pre_commit_contents = """#!%(executable)s
+        pre_commit_contents = """#!{executable}
 import sys
 import sys
-sys.path.extend(%(path)r)
+sys.path.extend({path!r})
 from dulwich.repo import Repo
 from dulwich.repo import Repo
 
 
 with open('foo', 'w') as f:
 with open('foo', 'w') as f:
@@ -700,9 +699,9 @@ with open('foo', 'w') as f:
 
 
 r = Repo('.')
 r = Repo('.')
 r.stage(['foo'])
 r.stage(['foo'])
-""" % {
-            'executable': sys.executable,
-            'path': [os.path.join(os.path.dirname(__file__), '..', '..')] + sys.path}
+""".format(
+            executable=sys.executable,
+            path=[os.path.join(os.path.dirname(__file__), '..', '..')] + sys.path)
 
 
         repo_dir = os.path.join(self.mkdtemp())
         repo_dir = os.path.join(self.mkdtemp())
         self.addCleanup(shutil.rmtree, repo_dir)
         self.addCleanup(shutil.rmtree, repo_dir)
@@ -732,7 +731,7 @@ r.stage(['foo'])
         self.assertEqual([], r[commit_sha].parents)
         self.assertEqual([], r[commit_sha].parents)
 
 
         tree = r[r[commit_sha].tree]
         tree = r[r[commit_sha].tree]
-        self.assertEqual(set([b'blah', b'foo']), set(tree))
+        self.assertEqual({b'blah', b'foo'}, set(tree))
 
 
     def test_shell_hook_post_commit(self):
     def test_shell_hook_post_commit(self):
         if os.name != "posix":
         if os.name != "posix":
@@ -814,7 +813,7 @@ exit 1
                 break
                 break
         else:
         else:
             raise AssertionError(
             raise AssertionError(
-                "Expected warning %r not in %r" % (expected_warning, warnings_list)
+                "Expected warning {!r} not in {!r}".format(expected_warning, warnings_list)
             )
             )
         self.assertEqual([commit_sha], r[commit_sha2].parents)
         self.assertEqual([commit_sha], r[commit_sha2].parents)
 
 
@@ -887,7 +886,7 @@ class BuildRepoRootTests(TestCase):
         return os.path.join(tempfile.mkdtemp(), "test")
         return os.path.join(tempfile.mkdtemp(), "test")
 
 
     def setUp(self):
     def setUp(self):
-        super(BuildRepoRootTests, self).setUp()
+        super().setUp()
         self._repo_dir = self.get_repo_dir()
         self._repo_dir = self.get_repo_dir()
         os.makedirs(self._repo_dir)
         os.makedirs(self._repo_dir)
         r = self._repo = Repo.init(self._repo_dir)
         r = self._repo = Repo.init(self._repo_dir)
@@ -1434,7 +1433,7 @@ class BuildRepoRootTests(TestCase):
         r = self._repo
         r = self._repo
         repo_path_bytes = os.fsencode(r.path)
         repo_path_bytes = os.fsencode(r.path)
         encodings = ("utf8", "latin1")
         encodings = ("utf8", "latin1")
-        names = [u"À".encode(encoding) for encoding in encodings]
+        names = ["À".encode(encoding) for encoding in encodings]
         for name, encoding in zip(names, encodings):
         for name, encoding in zip(names, encodings):
             full_path = os.path.join(repo_path_bytes, name)
             full_path = os.path.join(repo_path_bytes, name)
             with open(full_path, "wb") as f:
             with open(full_path, "wb") as f:

+ 23 - 23
dulwich/tests/test_server.py

@@ -75,7 +75,7 @@ FIVE = b"5" * 40
 SIX = b"6" * 40
 SIX = b"6" * 40
 
 
 
 
-class TestProto(object):
+class TestProto:
     def __init__(self):
     def __init__(self):
         self._output = []
         self._output = []
         self._received = {0: [], 1: [], 2: [], 3: []}
         self._received = {0: [], 1: [], 2: [], 3: []}
@@ -120,7 +120,7 @@ class TestGenericPackHandler(PackHandler):
 
 
 class HandlerTestCase(TestCase):
 class HandlerTestCase(TestCase):
     def setUp(self):
     def setUp(self):
-        super(HandlerTestCase, self).setUp()
+        super().setUp()
         self._handler = TestGenericPackHandler()
         self._handler = TestGenericPackHandler()
 
 
     def assertSucceeds(self, func, *args, **kwargs):
     def assertSucceeds(self, func, *args, **kwargs):
@@ -164,7 +164,7 @@ class HandlerTestCase(TestCase):
 
 
 class UploadPackHandlerTestCase(TestCase):
 class UploadPackHandlerTestCase(TestCase):
     def setUp(self):
     def setUp(self):
-        super(UploadPackHandlerTestCase, self).setUp()
+        super().setUp()
         self._repo = MemoryRepo.init_bare([], {})
         self._repo = MemoryRepo.init_bare([], {})
         backend = DictBackend({b"/": self._repo})
         backend = DictBackend({b"/": self._repo})
         self._handler = UploadPackHandler(
         self._handler = UploadPackHandler(
@@ -251,7 +251,7 @@ class UploadPackHandlerTestCase(TestCase):
 
 
 class FindShallowTests(TestCase):
 class FindShallowTests(TestCase):
     def setUp(self):
     def setUp(self):
-        super(FindShallowTests, self).setUp()
+        super().setUp()
         self._store = MemoryObjectStore()
         self._store = MemoryObjectStore()
 
 
     def make_commit(self, **attrs):
     def make_commit(self, **attrs):
@@ -274,18 +274,18 @@ class FindShallowTests(TestCase):
         c1, c2, c3 = self.make_linear_commits(3)
         c1, c2, c3 = self.make_linear_commits(3)
 
 
         self.assertEqual(
         self.assertEqual(
-            (set([c3.id]), set([])), _find_shallow(self._store, [c3.id], 1)
+            ({c3.id}, set()), _find_shallow(self._store, [c3.id], 1)
         )
         )
         self.assertEqual(
         self.assertEqual(
-            (set([c2.id]), set([c3.id])),
+            ({c2.id}, {c3.id}),
             _find_shallow(self._store, [c3.id], 2),
             _find_shallow(self._store, [c3.id], 2),
         )
         )
         self.assertEqual(
         self.assertEqual(
-            (set([c1.id]), set([c2.id, c3.id])),
+            ({c1.id}, {c2.id, c3.id}),
             _find_shallow(self._store, [c3.id], 3),
             _find_shallow(self._store, [c3.id], 3),
         )
         )
         self.assertEqual(
         self.assertEqual(
-            (set([]), set([c1.id, c2.id, c3.id])),
+            (set(), {c1.id, c2.id, c3.id}),
             _find_shallow(self._store, [c3.id], 4),
             _find_shallow(self._store, [c3.id], 4),
         )
         )
 
 
@@ -296,7 +296,7 @@ class FindShallowTests(TestCase):
         heads = [a[1].id, b[1].id, c[1].id]
         heads = [a[1].id, b[1].id, c[1].id]
 
 
         self.assertEqual(
         self.assertEqual(
-            (set([a[0].id, b[0].id, c[0].id]), set(heads)),
+            ({a[0].id, b[0].id, c[0].id}, set(heads)),
             _find_shallow(self._store, heads, 2),
             _find_shallow(self._store, heads, 2),
         )
         )
 
 
@@ -311,7 +311,7 @@ class FindShallowTests(TestCase):
 
 
         # 1 is shallow along the path from 4, but not along the path from 2.
         # 1 is shallow along the path from 4, but not along the path from 2.
         self.assertEqual(
         self.assertEqual(
-            (set([c1.id]), set([c1.id, c2.id, c3.id, c4.id])),
+            ({c1.id}, {c1.id, c2.id, c3.id, c4.id}),
             _find_shallow(self._store, [c2.id, c4.id], 3),
             _find_shallow(self._store, [c2.id, c4.id], 3),
         )
         )
 
 
@@ -321,7 +321,7 @@ class FindShallowTests(TestCase):
         c3 = self.make_commit(parents=[c1.id, c2.id])
         c3 = self.make_commit(parents=[c1.id, c2.id])
 
 
         self.assertEqual(
         self.assertEqual(
-            (set([c1.id, c2.id]), set([c3.id])),
+            ({c1.id, c2.id}, {c3.id}),
             _find_shallow(self._store, [c3.id], 2),
             _find_shallow(self._store, [c3.id], 2),
         )
         )
 
 
@@ -331,7 +331,7 @@ class FindShallowTests(TestCase):
         self._store.add_object(tag)
         self._store.add_object(tag)
 
 
         self.assertEqual(
         self.assertEqual(
-            (set([c1.id]), set([c2.id])),
+            ({c1.id}, {c2.id}),
             _find_shallow(self._store, [tag.id], 2),
             _find_shallow(self._store, [tag.id], 2),
         )
         )
 
 
@@ -344,7 +344,7 @@ class TestUploadPackHandler(UploadPackHandler):
 
 
 class ReceivePackHandlerTestCase(TestCase):
 class ReceivePackHandlerTestCase(TestCase):
     def setUp(self):
     def setUp(self):
-        super(ReceivePackHandlerTestCase, self).setUp()
+        super().setUp()
         self._repo = MemoryRepo.init_bare([], {})
         self._repo = MemoryRepo.init_bare([], {})
         backend = DictBackend({b"/": self._repo})
         backend = DictBackend({b"/": self._repo})
         self._handler = ReceivePackHandler(
         self._handler = ReceivePackHandler(
@@ -367,7 +367,7 @@ class ReceivePackHandlerTestCase(TestCase):
 
 
 class ProtocolGraphWalkerEmptyTestCase(TestCase):
 class ProtocolGraphWalkerEmptyTestCase(TestCase):
     def setUp(self):
     def setUp(self):
-        super(ProtocolGraphWalkerEmptyTestCase, self).setUp()
+        super().setUp()
         self._repo = MemoryRepo.init_bare([], {})
         self._repo = MemoryRepo.init_bare([], {})
         backend = DictBackend({b"/": self._repo})
         backend = DictBackend({b"/": self._repo})
         self._walker = _ProtocolGraphWalker(
         self._walker = _ProtocolGraphWalker(
@@ -390,7 +390,7 @@ class ProtocolGraphWalkerEmptyTestCase(TestCase):
 
 
 class ProtocolGraphWalkerTestCase(TestCase):
 class ProtocolGraphWalkerTestCase(TestCase):
     def setUp(self):
     def setUp(self):
-        super(ProtocolGraphWalkerTestCase, self).setUp()
+        super().setUp()
         # Create the following commit tree:
         # Create the following commit tree:
         #   3---5
         #   3---5
         #  /
         #  /
@@ -555,7 +555,7 @@ class ProtocolGraphWalkerTestCase(TestCase):
 
 
     def test_handle_shallow_request_no_client_shallows(self):
     def test_handle_shallow_request_no_client_shallows(self):
         self._handle_shallow_request([b"deepen 2\n"], [FOUR, FIVE])
         self._handle_shallow_request([b"deepen 2\n"], [FOUR, FIVE])
-        self.assertEqual(set([TWO, THREE]), self._walker.shallow)
+        self.assertEqual({TWO, THREE}, self._walker.shallow)
         self.assertReceived(
         self.assertReceived(
             [
             [
                 b"shallow " + TWO,
                 b"shallow " + TWO,
@@ -570,7 +570,7 @@ class ProtocolGraphWalkerTestCase(TestCase):
             b"deepen 2\n",
             b"deepen 2\n",
         ]
         ]
         self._handle_shallow_request(lines, [FOUR, FIVE])
         self._handle_shallow_request(lines, [FOUR, FIVE])
-        self.assertEqual(set([TWO, THREE]), self._walker.shallow)
+        self.assertEqual({TWO, THREE}, self._walker.shallow)
         self.assertReceived([])
         self.assertReceived([])
 
 
     def test_handle_shallow_request_unshallows(self):
     def test_handle_shallow_request_unshallows(self):
@@ -579,7 +579,7 @@ class ProtocolGraphWalkerTestCase(TestCase):
             b"deepen 3\n",
             b"deepen 3\n",
         ]
         ]
         self._handle_shallow_request(lines, [FOUR, FIVE])
         self._handle_shallow_request(lines, [FOUR, FIVE])
-        self.assertEqual(set([ONE]), self._walker.shallow)
+        self.assertEqual({ONE}, self._walker.shallow)
         self.assertReceived(
         self.assertReceived(
             [
             [
                 b"shallow " + ONE,
                 b"shallow " + ONE,
@@ -589,7 +589,7 @@ class ProtocolGraphWalkerTestCase(TestCase):
         )
         )
 
 
 
 
-class TestProtocolGraphWalker(object):
+class TestProtocolGraphWalker:
     def __init__(self):
     def __init__(self):
         self.acks = []
         self.acks = []
         self.lines = []
         self.lines = []
@@ -639,7 +639,7 @@ class AckGraphWalkerImplTestCase(TestCase):
     """Base setup and asserts for AckGraphWalker tests."""
     """Base setup and asserts for AckGraphWalker tests."""
 
 
     def setUp(self):
     def setUp(self):
-        super(AckGraphWalkerImplTestCase, self).setUp()
+        super().setUp()
         self._walker = TestProtocolGraphWalker()
         self._walker = TestProtocolGraphWalker()
         self._walker.lines = [
         self._walker.lines = [
             (b"have", TWO),
             (b"have", TWO),
@@ -1064,7 +1064,7 @@ class FileSystemBackendTests(TestCase):
     """Tests for FileSystemBackend."""
     """Tests for FileSystemBackend."""
 
 
     def setUp(self):
     def setUp(self):
-        super(FileSystemBackendTests, self).setUp()
+        super().setUp()
         self.path = tempfile.mkdtemp()
         self.path = tempfile.mkdtemp()
         self.addCleanup(shutil.rmtree, self.path)
         self.addCleanup(shutil.rmtree, self.path)
         self.repo = Repo.init(self.path)
         self.repo = Repo.init(self.path)
@@ -1124,7 +1124,7 @@ class ServeCommandTests(TestCase):
     """Tests for serve_command."""
     """Tests for serve_command."""
 
 
     def setUp(self):
     def setUp(self):
-        super(ServeCommandTests, self).setUp()
+        super().setUp()
         self.backend = DictBackend({})
         self.backend = DictBackend({})
 
 
     def serve_command(self, handler_cls, args, inf, outf):
     def serve_command(self, handler_cls, args, inf, outf):
@@ -1159,7 +1159,7 @@ class UpdateServerInfoTests(TestCase):
     """Tests for update_server_info."""
     """Tests for update_server_info."""
 
 
     def setUp(self):
     def setUp(self):
-        super(UpdateServerInfoTests, self).setUp()
+        super().setUp()
         self.path = tempfile.mkdtemp()
         self.path = tempfile.mkdtemp()
         self.addCleanup(shutil.rmtree, self.path)
         self.addCleanup(shutil.rmtree, self.path)
         self.repo = Repo.init(self.path)
         self.repo = Repo.init(self.path)

+ 1 - 1
dulwich/tests/test_utils.py

@@ -37,7 +37,7 @@ from dulwich.tests.utils import (
 
 
 class BuildCommitGraphTest(TestCase):
 class BuildCommitGraphTest(TestCase):
     def setUp(self):
     def setUp(self):
-        super(BuildCommitGraphTest, self).setUp()
+        super().setUp()
         self.store = MemoryObjectStore()
         self.store = MemoryObjectStore()
 
 
     def test_linear(self):
     def test_linear(self):

+ 4 - 4
dulwich/tests/test_walk.py

@@ -51,13 +51,13 @@ from dulwich.tests.utils import (
 )
 )
 
 
 
 
-class TestWalkEntry(object):
+class TestWalkEntry:
     def __init__(self, commit, changes):
     def __init__(self, commit, changes):
         self.commit = commit
         self.commit = commit
         self.changes = changes
         self.changes = changes
 
 
     def __repr__(self):
     def __repr__(self):
-        return "<TestWalkEntry commit=%s, changes=%r>" % (
+        return "<TestWalkEntry commit={}, changes={!r}>".format(
             self.commit.id,
             self.commit.id,
             self.changes,
             self.changes,
         )
         )
@@ -72,7 +72,7 @@ class TestWalkEntry(object):
 
 
 class WalkerTest(TestCase):
 class WalkerTest(TestCase):
     def setUp(self):
     def setUp(self):
-        super(WalkerTest, self).setUp()
+        super().setUp()
         self.store = MemoryObjectStore()
         self.store = MemoryObjectStore()
 
 
     def make_commits(self, commit_spec, **kwargs):
     def make_commits(self, commit_spec, **kwargs):
@@ -500,7 +500,7 @@ class WalkerTest(TestCase):
 
 
 class WalkEntryTest(TestCase):
 class WalkEntryTest(TestCase):
     def setUp(self):
     def setUp(self):
-        super(WalkEntryTest, self).setUp()
+        super().setUp()
         self.store = MemoryObjectStore()
         self.store = MemoryObjectStore()
 
 
     def make_commits(self, commit_spec, **kwargs):
     def make_commits(self, commit_spec, **kwargs):

+ 22 - 24
dulwich/tests/test_web.py

@@ -67,7 +67,7 @@ from dulwich.tests.utils import (
 )
 )
 
 
 
 
-class MinimalistWSGIInputStream(object):
+class MinimalistWSGIInputStream:
     """WSGI input stream with no 'seek()' and 'tell()' methods."""
     """WSGI input stream with no 'seek()' and 'tell()' methods."""
 
 
     def __init__(self, data):
     def __init__(self, data):
@@ -113,7 +113,7 @@ class WebTestCase(TestCase):
     _req_class: Type[HTTPGitRequest] = TestHTTPGitRequest
     _req_class: Type[HTTPGitRequest] = TestHTTPGitRequest
 
 
     def setUp(self):
     def setUp(self):
-        super(WebTestCase, self).setUp()
+        super().setUp()
         self._environ = {}
         self._environ = {}
         self._req = self._req_class(
         self._req = self._req_class(
             self._environ, self._start_response, handlers=self._handlers()
             self._environ, self._start_response, handlers=self._handlers()
@@ -168,7 +168,7 @@ class DumbHandlersTestCase(WebTestCase):
         self.assertTrue(f.closed)
         self.assertTrue(f.closed)
 
 
     def test_send_file_error(self):
     def test_send_file_error(self):
-        class TestFile(object):
+        class TestFile:
             def __init__(self, exc_class):
             def __init__(self, exc_class):
                 self.closed = False
                 self.closed = False
                 self._exc_class = exc_class
                 self._exc_class = exc_class
@@ -221,7 +221,7 @@ class DumbHandlersTestCase(WebTestCase):
         mat = re.search("^(..)(.{38})$", blob.id.decode("ascii"))
         mat = re.search("^(..)(.{38})$", blob.id.decode("ascii"))
 
 
         def as_legacy_object_error(self):
         def as_legacy_object_error(self):
-            raise IOError
+            raise OSError
 
 
         self.addCleanup(setattr, Blob, "as_legacy_object", Blob.as_legacy_object)
         self.addCleanup(setattr, Blob, "as_legacy_object", Blob.as_legacy_object)
         Blob.as_legacy_object = as_legacy_object_error
         Blob.as_legacy_object = as_legacy_object_error
@@ -296,11 +296,11 @@ class DumbHandlersTestCase(WebTestCase):
         self.assertContentTypeEquals("text/plain")
         self.assertContentTypeEquals("text/plain")
 
 
     def test_get_info_packs(self):
     def test_get_info_packs(self):
-        class TestPackData(object):
+        class TestPackData:
             def __init__(self, sha):
             def __init__(self, sha):
                 self.filename = "pack-%s.pack" % sha
                 self.filename = "pack-%s.pack" % sha
 
 
-        class TestPack(object):
+        class TestPack:
             def __init__(self, sha):
             def __init__(self, sha):
                 self.data = TestPackData(sha)
                 self.data = TestPackData(sha)
 
 
@@ -327,7 +327,7 @@ class DumbHandlersTestCase(WebTestCase):
 
 
 
 
 class SmartHandlersTestCase(WebTestCase):
 class SmartHandlersTestCase(WebTestCase):
-    class _TestUploadPackHandler(object):
+    class _TestUploadPackHandler:
         def __init__(
         def __init__(
             self,
             self,
             backend,
             backend,
@@ -364,7 +364,7 @@ class SmartHandlersTestCase(WebTestCase):
             self._environ["CONTENT_LENGTH"] = content_length
             self._environ["CONTENT_LENGTH"] = content_length
         mat = re.search(".*", "/git-upload-pack")
         mat = re.search(".*", "/git-upload-pack")
 
 
-        class Backend(object):
+        class Backend:
             def open_repository(self, path):
             def open_repository(self, path):
                 return None
                 return None
 
 
@@ -390,7 +390,7 @@ class SmartHandlersTestCase(WebTestCase):
     def test_get_info_refs_unknown(self):
     def test_get_info_refs_unknown(self):
         self._environ["QUERY_STRING"] = "service=git-evil-handler"
         self._environ["QUERY_STRING"] = "service=git-evil-handler"
 
 
-        class Backend(object):
+        class Backend:
             def open_repository(self, url):
             def open_repository(self, url):
                 return None
                 return None
 
 
@@ -404,7 +404,7 @@ class SmartHandlersTestCase(WebTestCase):
         self._environ["wsgi.input"] = BytesIO(b"foo")
         self._environ["wsgi.input"] = BytesIO(b"foo")
         self._environ["QUERY_STRING"] = "service=git-upload-pack"
         self._environ["QUERY_STRING"] = "service=git-upload-pack"
 
 
-        class Backend(object):
+        class Backend:
             def open_repository(self, url):
             def open_repository(self, url):
                 return None
                 return None
 
 
@@ -454,14 +454,14 @@ class HTTPGitRequestTestCase(WebTestCase):
         message = "Something not found"
         message = "Something not found"
         self.assertEqual(message.encode("ascii"), self._req.not_found(message))
         self.assertEqual(message.encode("ascii"), self._req.not_found(message))
         self.assertEqual(HTTP_NOT_FOUND, self._status)
         self.assertEqual(HTTP_NOT_FOUND, self._status)
-        self.assertEqual(set([("Content-Type", "text/plain")]), set(self._headers))
+        self.assertEqual({("Content-Type", "text/plain")}, set(self._headers))
 
 
     def test_forbidden(self):
     def test_forbidden(self):
         self._req.cache_forever()  # cache headers should be discarded
         self._req.cache_forever()  # cache headers should be discarded
         message = "Something not found"
         message = "Something not found"
         self.assertEqual(message.encode("ascii"), self._req.forbidden(message))
         self.assertEqual(message.encode("ascii"), self._req.forbidden(message))
         self.assertEqual(HTTP_FORBIDDEN, self._status)
         self.assertEqual(HTTP_FORBIDDEN, self._status)
-        self.assertEqual(set([("Content-Type", "text/plain")]), set(self._headers))
+        self.assertEqual({("Content-Type", "text/plain")}, set(self._headers))
 
 
     def test_respond_ok(self):
     def test_respond_ok(self):
         self._req.respond()
         self._req.respond()
@@ -476,16 +476,14 @@ class HTTPGitRequestTestCase(WebTestCase):
             headers=[("X-Foo", "foo"), ("X-Bar", "bar")],
             headers=[("X-Foo", "foo"), ("X-Bar", "bar")],
         )
         )
         self.assertEqual(
         self.assertEqual(
-            set(
-                [
-                    ("X-Foo", "foo"),
-                    ("X-Bar", "bar"),
-                    ("Content-Type", "some/type"),
-                    ("Expires", "Fri, 01 Jan 1980 00:00:00 GMT"),
-                    ("Pragma", "no-cache"),
-                    ("Cache-Control", "no-cache, max-age=0, must-revalidate"),
-                ]
-            ),
+            {
+                ("X-Foo", "foo"),
+                ("X-Bar", "bar"),
+                ("Content-Type", "some/type"),
+                ("Expires", "Fri, 01 Jan 1980 00:00:00 GMT"),
+                ("Pragma", "no-cache"),
+                ("Cache-Control", "no-cache, max-age=0, must-revalidate"),
+            },
             set(self._headers),
             set(self._headers),
         )
         )
         self.assertEqual(402, self._status)
         self.assertEqual(402, self._status)
@@ -493,7 +491,7 @@ class HTTPGitRequestTestCase(WebTestCase):
 
 
 class HTTPGitApplicationTestCase(TestCase):
 class HTTPGitApplicationTestCase(TestCase):
     def setUp(self):
     def setUp(self):
-        super(HTTPGitApplicationTestCase, self).setUp()
+        super().setUp()
         self._app = HTTPGitApplication("backend")
         self._app = HTTPGitApplication("backend")
 
 
         self._environ = {
         self._environ = {
@@ -533,7 +531,7 @@ class GunzipTestCase(HTTPGitApplicationTestCase):
     example_text = __doc__.encode("ascii")
     example_text = __doc__.encode("ascii")
 
 
     def setUp(self):
     def setUp(self):
-        super(GunzipTestCase, self).setUp()
+        super().setUp()
         self._app = GunzipFilter(self._app)
         self._app = GunzipFilter(self._app)
         self._environ["HTTP_CONTENT_ENCODING"] = "gzip"
         self._environ["HTTP_CONTENT_ENCODING"] = "gzip"
         self._environ["REQUEST_METHOD"] = "POST"
         self._environ["REQUEST_METHOD"] = "POST"

+ 4 - 4
dulwich/walk.py

@@ -50,7 +50,7 @@ ALL_ORDERS = (ORDER_DATE, ORDER_TOPO)
 _MAX_EXTRA_COMMITS = 5
 _MAX_EXTRA_COMMITS = 5
 
 
 
 
-class WalkEntry(object):
+class WalkEntry:
     """Object encapsulating a single result from a walk."""
     """Object encapsulating a single result from a walk."""
 
 
     def __init__(self, walker, commit):
     def __init__(self, walker, commit):
@@ -122,13 +122,13 @@ class WalkEntry(object):
         return self._changes[path_prefix]
         return self._changes[path_prefix]
 
 
     def __repr__(self):
     def __repr__(self):
-        return "<WalkEntry commit=%s, changes=%r>" % (
+        return "<WalkEntry commit={}, changes={!r}>".format(
             self.commit.id,
             self.commit.id,
             self.changes(),
             self.changes(),
         )
         )
 
 
 
 
-class _CommitTimeQueue(object):
+class _CommitTimeQueue:
     """Priority queue of WalkEntry objects by commit time."""
     """Priority queue of WalkEntry objects by commit time."""
 
 
     def __init__(self, walker: "Walker"):
     def __init__(self, walker: "Walker"):
@@ -232,7 +232,7 @@ class _CommitTimeQueue(object):
     __next__ = next
     __next__ = next
 
 
 
 
-class Walker(object):
+class Walker:
     """Object for performing a walk of commits in a store.
     """Object for performing a walk of commits in a store.
 
 
     Walker objects are initialized with a store and other options and can then
     Walker objects are initialized with a store and other options and can then

+ 10 - 11
dulwich/web.py

@@ -157,7 +157,7 @@ def send_file(req, f, content_type):
             if not data:
             if not data:
                 break
                 break
             yield data
             yield data
-    except IOError:
+    except OSError:
         yield req.error("Error reading file")
         yield req.error("Error reading file")
     finally:
     finally:
         f.close()
         f.close()
@@ -183,7 +183,7 @@ def get_loose_object(req, backend, mat):
         return
         return
     try:
     try:
         data = object_store[sha].as_legacy_object()
         data = object_store[sha].as_legacy_object()
-    except IOError:
+    except OSError:
         yield req.error("Error reading object")
         yield req.error("Error reading object")
         return
         return
     req.cache_forever()
     req.cache_forever()
@@ -245,8 +245,7 @@ def get_info_refs(req, backend, mat):
         req.nocache()
         req.nocache()
         req.respond(HTTP_OK, "text/plain")
         req.respond(HTTP_OK, "text/plain")
         logger.info("Emulating dumb info/refs")
         logger.info("Emulating dumb info/refs")
-        for text in generate_info_refs(repo):
-            yield text
+        yield from generate_info_refs(repo)
 
 
 
 
 def get_info_packs(req, backend, mat):
 def get_info_packs(req, backend, mat):
@@ -266,7 +265,7 @@ def _chunk_iter(f):
         yield chunk[:-2]
         yield chunk[:-2]
 
 
 
 
-class ChunkReader(object):
+class ChunkReader:
 
 
     def __init__(self, f):
     def __init__(self, f):
         self._iter = _chunk_iter(f)
         self._iter = _chunk_iter(f)
@@ -284,7 +283,7 @@ class ChunkReader(object):
         return ret
         return ret
 
 
 
 
-class _LengthLimitedFile(object):
+class _LengthLimitedFile:
     """Wrapper class to limit the length of reads from a file-like object.
     """Wrapper class to limit the length of reads from a file-like object.
 
 
     This is used to ensure EOF is read from the wsgi.input object once
     This is used to ensure EOF is read from the wsgi.input object once
@@ -332,7 +331,7 @@ def handle_service_request(req, backend, mat):
     handler.handle()
     handler.handle()
 
 
 
 
-class HTTPGitRequest(object):
+class HTTPGitRequest:
     """Class encapsulating the state of a single git HTTP request.
     """Class encapsulating the state of a single git HTTP request.
 
 
     Attributes:
     Attributes:
@@ -396,7 +395,7 @@ class HTTPGitRequest(object):
         self._cache_headers = cache_forever_headers()
         self._cache_headers = cache_forever_headers()
 
 
 
 
-class HTTPGitApplication(object):
+class HTTPGitApplication:
     """Class encapsulating the state of a git WSGI application.
     """Class encapsulating the state of a git WSGI application.
 
 
     Attributes:
     Attributes:
@@ -458,7 +457,7 @@ class HTTPGitApplication(object):
         return handler(req, self.backend, mat)
         return handler(req, self.backend, mat)
 
 
 
 
-class GunzipFilter(object):
+class GunzipFilter:
     """WSGI middleware that unzips gzip-encoded requests before
     """WSGI middleware that unzips gzip-encoded requests before
     passing on to the underlying application.
     passing on to the underlying application.
     """
     """
@@ -471,7 +470,7 @@ class GunzipFilter(object):
             try:
             try:
                 environ["wsgi.input"].tell()
                 environ["wsgi.input"].tell()
                 wsgi_input = environ["wsgi.input"]
                 wsgi_input = environ["wsgi.input"]
-            except (AttributeError, IOError, NotImplementedError):
+            except (AttributeError, OSError, NotImplementedError):
                 # The gzip implementation in the standard library of Python 2.x
                 # The gzip implementation in the standard library of Python 2.x
                 # requires working '.seek()' and '.tell()' methods on the input
                 # requires working '.seek()' and '.tell()' methods on the input
                 # stream.  Read the data into a temporary file to work around
                 # stream.  Read the data into a temporary file to work around
@@ -490,7 +489,7 @@ class GunzipFilter(object):
         return self.app(environ, start_response)
         return self.app(environ, start_response)
 
 
 
 
-class LimitedInputFilter(object):
+class LimitedInputFilter:
     """WSGI middleware that limits the input length of a request to that
     """WSGI middleware that limits the input length of a request to that
     specified in Content-Length.
     specified in Content-Length.
     """
     """

+ 1 - 1
examples/clone.py

@@ -22,7 +22,7 @@ _, args = getopt(sys.argv, "", [])
 
 
 
 
 if len(args) < 2:
 if len(args) < 2:
-    print("usage: %s host:path path" % (args[0], ))
+    print("usage: {} host:path path".format(args[0]))
     sys.exit(1)
     sys.exit(1)
 
 
 elif len(args) < 3:
 elif len(args) < 3:

+ 2 - 2
examples/latest_change.py

@@ -6,7 +6,7 @@ import time
 from dulwich.repo import Repo
 from dulwich.repo import Repo
 
 
 if len(sys.argv) < 2:
 if len(sys.argv) < 2:
-    print("usage: %s filename" % (sys.argv[0], ))
+    print("usage: {} filename".format(sys.argv[0]))
     sys.exit(1)
     sys.exit(1)
 
 
 r = Repo(".")
 r = Repo(".")
@@ -19,5 +19,5 @@ try:
 except StopIteration:
 except StopIteration:
     print("No file %s anywhere in history." % sys.argv[1])
     print("No file %s anywhere in history." % sys.argv[1])
 else:
 else:
-    print("%s was last changed by %s at %s (commit %s)" % (
+    print("{} was last changed by {} at {} (commit {})".format(
         sys.argv[1], c.author, time.ctime(c.author_time), c.id))
         sys.argv[1], c.author, time.ctime(c.author_time), c.id))

+ 1 - 1
examples/rename-branch.py

@@ -26,4 +26,4 @@ def update_refs(refs):
 
 
 
 
 client.send_pack(path, update_refs, generate_pack_data)
 client.send_pack(path, update_refs, generate_pack_data)
-print("Renamed %s to %s" % (args.old_ref, args.new_ref))
+print("Renamed {} to {}".format(args.old_ref, args.new_ref))

+ 0 - 1
setup.py

@@ -1,5 +1,4 @@
 #!/usr/bin/python3
 #!/usr/bin/python3
-# encoding: utf-8
 # Setup file for dulwich
 # Setup file for dulwich
 # Copyright (C) 2008-2022 Jelmer Vernooij <jelmer@jelmer.uk>
 # Copyright (C) 2008-2022 Jelmer Vernooij <jelmer@jelmer.uk>