Jelmer Vernooij 2 лет назад
Родитель
Сommit
4fa57f3d0e

+ 14 - 12
dulwich/client.py

@@ -510,8 +510,9 @@ def _read_side_band64k_data(pkt_seq, channel_callbacks):
         pkt = pkt[1:]
         try:
             cb = channel_callbacks[channel]
-        except KeyError:
-            raise AssertionError("Invalid sideband channel %d" % channel)
+        except KeyError as exc:
+            raise AssertionError(
+                "Invalid sideband channel %d" % channel) from exc
         else:
             if cb is not None:
                 cb(pkt)
@@ -1052,8 +1053,8 @@ class TraditionalGitClient(GitClient):
         with proto:
             try:
                 old_refs, server_capabilities = read_pkt_refs(proto.read_pkt_seq())
-            except HangupException:
-                raise _remote_error_from_stderr(stderr)
+            except HangupException as exc:
+                raise _remote_error_from_stderr(stderr) from exc
             (
                 negotiated_capabilities,
                 agent,
@@ -1146,8 +1147,8 @@ class TraditionalGitClient(GitClient):
         with proto:
             try:
                 refs, server_capabilities = read_pkt_refs(proto.read_pkt_seq())
-            except HangupException:
-                raise _remote_error_from_stderr(stderr)
+            except HangupException as exc:
+                raise _remote_error_from_stderr(stderr) from exc
             (
                 negotiated_capabilities,
                 symrefs,
@@ -1195,8 +1196,8 @@ class TraditionalGitClient(GitClient):
         with proto:
             try:
                 refs, _ = read_pkt_refs(proto.read_pkt_seq())
-            except HangupException:
-                raise _remote_error_from_stderr(stderr)
+            except HangupException as exc:
+                raise _remote_error_from_stderr(stderr) from exc
             proto.write_pkt_line(None)
             return refs
 
@@ -1224,8 +1225,8 @@ class TraditionalGitClient(GitClient):
             proto.write_pkt_line(None)
             try:
                 pkt = proto.read_pkt_line()
-            except HangupException:
-                raise _remote_error_from_stderr(stderr)
+            except HangupException as exc:
+                raise _remote_error_from_stderr(stderr) from exc
             if pkt == b"NACK\n" or pkt == b"NACK":
                 return
             elif pkt == b"ACK\n" or pkt == b"ACK":
@@ -1947,8 +1948,9 @@ class AbstractHttpGitClient(GitClient):
                 # The first line should mention the service
                 try:
                     [pkt] = list(proto.read_pkt_seq())
-                except ValueError:
-                    raise GitProtocolError("unexpected number of packets received")
+                except ValueError as exc:
+                    raise GitProtocolError(
+                        "unexpected number of packets received") from exc
                 if pkt.rstrip(b"\n") != (b"# service=" + service):
                     raise GitProtocolError(
                         "unexpected first line %r from smart server" % pkt

+ 4 - 4
dulwich/config.py

@@ -411,15 +411,15 @@ def _parse_string(value: bytes) -> bytes:
             i += 1
             try:
                 v = _ESCAPE_TABLE[value[i]]
-            except IndexError:
+            except IndexError as exc:
                 raise ValueError(
                     "escape character in %r at %d before end of string" % (value, i)
-                )
-            except KeyError:
+                ) from exc
+            except KeyError as exc:
                 raise ValueError(
                     "escape character followed by unknown character "
                     "%s at %d in %r" % (value[i], i, value)
-                )
+                ) from exc
             if whitespace:
                 ret.extend(whitespace)
                 whitespace = bytearray()

+ 3 - 2
dulwich/contrib/swift.py

@@ -170,8 +170,9 @@ def load_conf(path=None, file=None):
     if not path:
         try:
             confpath = os.environ["DULWICH_SWIFT_CFG"]
-        except KeyError:
-            raise Exception("You need to specify a configuration file")
+        except KeyError as exc:
+            raise Exception(
+                "You need to specify a configuration file") from exc
     else:
         confpath = path
     if not os.path.isfile(confpath):

+ 2 - 2
dulwich/file.py

@@ -152,8 +152,8 @@ class _GitFile(object):
                 os.O_RDWR | os.O_CREAT | os.O_EXCL | getattr(os, "O_BINARY", 0),
                 mask,
             )
-        except FileExistsError:
-            raise FileLocked(filename, self._lockfilename)
+        except FileExistsError as exc:
+            raise FileLocked(filename, self._lockfilename) from exc
         self._file = os.fdopen(fd, mode, bufsize)
         self._closed = False
 

+ 1 - 1
dulwich/hooks.py

@@ -200,4 +200,4 @@ class PostReceiveShellHook(ShellHook):
                 raise HookError(err_msg.decode('utf-8', 'backslashreplace'))
             return out_data
         except OSError as err:
-            raise HookError(repr(err))
+            raise HookError(repr(err)) from err

+ 2 - 2
dulwich/lfs.py

@@ -51,8 +51,8 @@ class LFSStore(object):
         """Open an object by sha."""
         try:
             return open(self._sha_path(sha), "rb")
-        except FileNotFoundError:
-            raise KeyError(sha)
+        except FileNotFoundError as exc:
+            raise KeyError(sha) from exc
 
     def write_object(self, chunks):
         """Write an object.

+ 15 - 13
dulwich/objects.py

@@ -111,7 +111,7 @@ def hex_to_sha(hex):
     except TypeError as exc:
         if not isinstance(hex, bytes):
             raise
-        raise ValueError(exc.args[0])
+        raise ValueError(exc.args[0]) from exc
 
 
 def valid_hexsha(hex):
@@ -282,8 +282,9 @@ class ShaFile(object):
         type_name, size = header.split(b" ", 1)
         try:
             int(size)  # sanity check
-        except ValueError as e:
-            raise ObjectFormatException("Object size not an integer: %s" % e)
+        except ValueError as exc:
+            raise ObjectFormatException(
+                "Object size not an integer: %s" % exc) from exc
         obj_class = object_class(type_name)
         if not obj_class:
             raise ObjectFormatException("Not a known type: %s" % type_name)
@@ -427,8 +428,8 @@ class ShaFile(object):
             obj = cls._parse_file(f)
             obj._sha = None
             return obj
-        except (IndexError, ValueError):
-            raise ObjectFormatException("invalid object header")
+        except (IndexError, ValueError) as exc:
+            raise ObjectFormatException("invalid object header") from exc
 
     @staticmethod
     def from_raw_string(type_num, string, sha=None):
@@ -493,8 +494,8 @@ class ShaFile(object):
             self._deserialize(self.as_raw_chunks())
             self._sha = None
             new_sha = self.id
-        except Exception as e:
-            raise ObjectFormatException(e)
+        except Exception as exc:
+            raise ObjectFormatException(exc) from exc
         if old_sha != new_sha:
             raise ChecksumMismatch(new_sha, old_sha)
 
@@ -942,8 +943,9 @@ def parse_tree(text, strict=False):
             raise ObjectFormatException("Invalid mode '%s'" % mode_text)
         try:
             mode = int(mode_text, 8)
-        except ValueError:
-            raise ObjectFormatException("Invalid mode '%s'" % mode_text)
+        except ValueError as exc:
+            raise ObjectFormatException(
+                "Invalid mode '%s'" % mode_text) from exc
         name_end = text.index(b"\0", mode_end)
         name = text[mode_end + 1 : name_end]
         count = name_end + 21
@@ -1114,8 +1116,8 @@ class Tree(ShaFile):
         """Grab the entries in the tree"""
         try:
             parsed_entries = parse_tree(b"".join(chunks))
-        except ValueError as e:
-            raise ObjectFormatException(e)
+        except ValueError as exc:
+            raise ObjectFormatException(exc) from exc
         # TODO: list comprehension is for efficiency in the common (small)
         # case; if memory efficiency in the large case is a concern, use a
         # genexp.
@@ -1255,8 +1257,8 @@ def parse_time_entry(value):
         timetext, timezonetext = rest.rsplit(b" ", 1)
         time = int(timetext)
         timezone, timezone_neg_utc = parse_timezone(timezonetext)
-    except ValueError as e:
-        raise ObjectFormatException(e)
+    except ValueError as exc:
+        raise ObjectFormatException(exc) from exc
     return person, time, (timezone, timezone_neg_utc)
 
 

+ 2 - 2
dulwich/pack.py

@@ -607,10 +607,10 @@ class FilePackIndex(PackIndex):
             sha = hex_to_sha(sha)
         try:
             return self._object_index(sha)
-        except ValueError:
+        except ValueError as exc:
             closed = getattr(self._contents, "closed", None)
             if closed in (None, True):
-                raise PackFileDisappeared(self)
+                raise PackFileDisappeared(self) from exc
             raise
 
     def _object_index(self, sha):

+ 17 - 12
dulwich/porcelain.py

@@ -185,9 +185,8 @@ DEFAULT_ENCODING = "utf-8"
 class Error(Exception):
     """Porcelain-based error. """
 
-    def __init__(self, msg, inner=None):
+    def __init__(self, msg):
         super(Error, self).__init__(msg)
-        self.inner = inner
 
 
 class RemoteExists(Error):
@@ -336,6 +335,10 @@ def path_to_tree_path(repopath, path, tree_encoding=DEFAULT_ENCODING):
 class DivergedBranches(Error):
     """Branches have diverged and fast-forward is not possible."""
 
+    def __init__(self, current_sha, new_sha):
+        self.current_sha = current_sha
+        self.new_sha = new_sha
+
 
 def check_diverged(repo, current_sha, new_sha):
     """Check if updating to a sha can be done with fast forwarding.
@@ -669,8 +672,8 @@ def remove(repo=".", paths=None, cached=False):
             tree_path = path_to_tree_path(r.path, p)
             try:
                 index_sha = index[tree_path].sha
-            except KeyError:
-                raise Error("%s did not match any files" % p)
+            except KeyError as exc:
+                raise Error("%s did not match any files" % p) from exc
 
             if not cached:
                 try:
@@ -1194,8 +1197,10 @@ def push(
                 else:
                     try:
                         localsha = r.refs[lh]
-                    except KeyError:
-                        raise Error("No valid ref %s in local repository" % lh)
+                    except KeyError as exc:
+                        raise Error(
+                            "No valid ref %s in local repository" % lh
+                        ) from exc
                     if not force_ref and rh in refs:
                         check_diverged(r, refs[rh], localsha)
                     new_refs[rh] = localsha
@@ -1211,11 +1216,10 @@ def push(
                 generate_pack_data=r.generate_pack_data,
                 progress=errstream.write,
             )
-        except SendPackError as e:
+        except SendPackError as exc:
             raise Error(
-                "Push to " + remote_location + " failed -> " + e.args[0].decode(),
-                inner=e,
-            )
+                "Push to " + remote_location + " failed -> " + exc.args[0].decode(),
+            ) from exc
         else:
             errstream.write(
                 b"Push to " + remote_location.encode(err_encoding) + b" successful.\n"
@@ -1280,11 +1284,12 @@ def pull(
             if not force_ref and rh in r.refs:
                 try:
                     check_diverged(r, r.refs.follow(rh)[1], fetch_result.refs[lh])
-                except DivergedBranches:
+                except DivergedBranches as exc:
                     if fast_forward:
                         raise
                     else:
-                        raise NotImplementedError("merge is not yet supported")
+                        raise NotImplementedError(
+                            "merge is not yet supported") from exc
             r.refs[rh] = fetch_result.refs[lh]
         if selected_refs:
             r[b"HEAD"] = fetch_result.refs[selected_refs[0][1]]

+ 6 - 6
dulwich/protocol.py

@@ -226,10 +226,10 @@ class Protocol(object):
             if self.report_activity:
                 self.report_activity(size, "read")
             pkt_contents = read(size - 4)
-        except ConnectionResetError:
-            raise HangupException()
-        except socket.error as e:
-            raise GitProtocolError(e)
+        except ConnectionResetError as exc:
+            raise HangupException() from exc
+        except socket.error as exc:
+            raise GitProtocolError(exc) from exc
         else:
             if len(pkt_contents) + 4 != size:
                 raise GitProtocolError(
@@ -291,8 +291,8 @@ class Protocol(object):
             self.write(line)
             if self.report_activity:
                 self.report_activity(len(line), "write")
-        except socket.error as e:
-            raise GitProtocolError(e)
+        except socket.error as exc:
+            raise GitProtocolError(exc) from exc
 
     def write_sideband(self, channel, blob):
         """Write multiplexed data to the sideband.

+ 12 - 10
dulwich/repo.py

@@ -223,8 +223,8 @@ def check_user_identity(identity):
     """
     try:
         fst, snd = identity.split(b" <", 1)
-    except ValueError:
-        raise InvalidUserIdentity(identity)
+    except ValueError as exc:
+        raise InvalidUserIdentity(identity) from exc
     if b">" not in snd:
         raise InvalidUserIdentity(identity)
 
@@ -785,8 +785,8 @@ class BaseRepo(object):
                 pass
         try:
             return self.object_store[self.refs[name]]
-        except RefFormatError:
-            raise KeyError(name)
+        except RefFormatError as exc:
+            raise KeyError(name) from exc
 
     def __contains__(self, name: bytes) -> bool:
         """Check if a specific Git object or ref is present.
@@ -911,8 +911,8 @@ class BaseRepo(object):
         try:
             if not no_verify:
                 self.hooks["pre-commit"].execute()
-        except HookError as e:
-            raise CommitError(e)
+        except HookError as exc:
+            raise CommitError(exc) from exc
         except KeyError:  # no hook defined, silent fallthrough
             pass
 
@@ -969,8 +969,8 @@ class BaseRepo(object):
                 c.message = self.hooks["commit-msg"].execute(message)
                 if c.message is None:
                     c.message = message
-        except HookError as e:
-            raise CommitError(e)
+        except HookError as exc:
+            raise CommitError(exc) from exc
         except KeyError:  # no hook defined, message not modified
             c.message = message
 
@@ -1406,8 +1406,10 @@ class Repo(BaseRepo):
                 try:
                     del index[tree_path]
                     continue
-                except KeyError:
-                    raise KeyError("file '%s' not in index" % (tree_path.decode()))
+                except KeyError as exc:
+                    raise KeyError(
+                        "file '%s' not in index" % (tree_path.decode())
+                    ) from exc
 
             st = None
             try:

+ 2 - 2
dulwich/server.py

@@ -193,10 +193,10 @@ class DictBackend(Backend):
         logger.debug("Opening repository at %s", path)
         try:
             return self.repos[path]
-        except KeyError:
+        except KeyError as exc:
             raise NotGitRepository(
                 "No git repository was found at %(path)s" % dict(path=path)
-            )
+            ) from exc
 
 
 class FileSystemBackend(Backend):

+ 4 - 4
dulwich/tests/test_fastexport.py

@@ -52,8 +52,8 @@ class GitFastExporterTests(TestCase):
         self.stream = BytesIO()
         try:
             from dulwich.fastexport import GitFastExporter
-        except ImportError:
-            raise SkipTest("python-fastimport not available")
+        except ImportError as exc:
+            raise SkipTest("python-fastimport not available") from exc
         self.fastexporter = GitFastExporter(self.stream, self.store)
 
     def test_emit_blob(self):
@@ -100,8 +100,8 @@ class GitImportProcessorTests(TestCase):
         self.repo = MemoryRepo()
         try:
             from dulwich.fastexport import GitImportProcessor
-        except ImportError:
-            raise SkipTest("python-fastimport not available")
+        except ImportError as exc:
+            raise SkipTest("python-fastimport not available") from exc
         self.processor = GitImportProcessor(self.repo)
 
     def test_reset_handler(self):

+ 4 - 2
dulwich/tests/test_refs.py

@@ -641,8 +641,10 @@ class DiskRefsContainerTests(RefsContainerTests, TestCase):
     def test_non_ascii(self):
         try:
             encoded_ref = os.fsencode(u"refs/tags/schön")
-        except UnicodeEncodeError:
-            raise SkipTest("filesystem encoding doesn't support special character")
+        except UnicodeEncodeError as exc:
+            raise SkipTest(
+                "filesystem encoding doesn't support special character"
+            ) from exc
         p = os.path.join(os.fsencode(self._repo.path), encoded_ref)
         with open(p, "w") as f:
             f.write("00" * 20)

+ 3 - 3
dulwich/tests/utils.py

@@ -328,9 +328,9 @@ def build_commit_graph(object_store, commit_spec, trees=None, attrs=None):
         commit_num = commit[0]
         try:
             parent_ids = [nums[pn] for pn in commit[1:]]
-        except KeyError as e:
-            (missing_parent,) = e.args
-            raise ValueError("Unknown parent %i" % missing_parent)
+        except KeyError as exc:
+            (missing_parent,) = exc.args
+            raise ValueError("Unknown parent %i" % missing_parent) from exc
 
         blobs = []
         for entry in trees.get(commit_num, []):

+ 2 - 2
dulwich/walk.py

@@ -148,8 +148,8 @@ class _CommitTimeQueue(object):
     def _push(self, object_id):
         try:
             obj = self._store[object_id]
-        except KeyError:
-            raise MissingCommitError(object_id)
+        except KeyError as exc:
+            raise MissingCommitError(object_id) from exc
         if isinstance(obj, Tag):
             self._push(obj.object[1])
             return