Skip to content

Commit

Permalink
Merge pull request #2251 from pallets/except-chain
Browse files Browse the repository at this point in the history
use exception chaining
  • Loading branch information
davidism committed Oct 5, 2021
2 parents 366b2d9 + 08a0ea5 commit ff5cd45
Show file tree
Hide file tree
Showing 7 changed files with 40 additions and 25 deletions.
2 changes: 1 addition & 1 deletion examples/cupoftee/pages.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ def process(self, id):
try:
self.server = self.cup.server_browser.servers[id]
except KeyError:
raise NotFound()
raise NotFound() from None


class Search(Page):
Expand Down
22 changes: 15 additions & 7 deletions src/werkzeug/datastructures.py
Original file line number Diff line number Diff line change
Expand Up @@ -578,19 +578,20 @@ def pop(self, key, default=_missing):
except KeyError:
if default is not _missing:
return default
raise exceptions.BadRequestKeyError(key)

raise exceptions.BadRequestKeyError(key) from None

def popitem(self):
"""Pop an item from the dict."""
try:
item = dict.popitem(self)

if len(item[1]) == 0:
raise exceptions.BadRequestKeyError(item)
raise exceptions.BadRequestKeyError(item[0])

return (item[0], item[1][0])
except KeyError as e:
raise exceptions.BadRequestKeyError(e.args[0])
raise exceptions.BadRequestKeyError(e.args[0]) from None

def poplist(self, key):
"""Pop the list for a key from the dict. If the key is not in the dict
Expand All @@ -607,7 +608,7 @@ def popitemlist(self):
try:
return dict.popitem(self)
except KeyError as e:
raise exceptions.BadRequestKeyError(e.args[0])
raise exceptions.BadRequestKeyError(e.args[0]) from None

def __copy__(self):
return self.copy()
Expand Down Expand Up @@ -801,27 +802,34 @@ def pop(self, key, default=_missing):
except KeyError:
if default is not _missing:
return default
raise exceptions.BadRequestKeyError(key)

raise exceptions.BadRequestKeyError(key) from None

for bucket in buckets:
bucket.unlink(self)

return buckets[0].value

def popitem(self):
try:
key, buckets = dict.popitem(self)
except KeyError as e:
raise exceptions.BadRequestKeyError(e.args[0])
raise exceptions.BadRequestKeyError(e.args[0]) from None

for bucket in buckets:
bucket.unlink(self)

return key, buckets[0].value

def popitemlist(self):
try:
key, buckets = dict.popitem(self)
except KeyError as e:
raise exceptions.BadRequestKeyError(e.args[0])
raise exceptions.BadRequestKeyError(e.args[0]) from None

for bucket in buckets:
bucket.unlink(self)

return key, [x.value for x in buckets]


Expand Down
9 changes: 5 additions & 4 deletions src/werkzeug/local.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ class _CannotUseContextVar(Exception):
from gevent.monkey import is_object_patched
except ImportError:
# Gevent isn't used, but Greenlet is and hasn't patched
raise _CannotUseContextVar()
raise _CannotUseContextVar() from None
else:
if is_object_patched("threading", "local") and not is_object_patched(
"contextvars", "ContextVar"
Expand Down Expand Up @@ -162,7 +162,7 @@ def __getattr__(self, name: str) -> t.Any:
try:
return values[name]
except KeyError:
raise AttributeError(name)
raise AttributeError(name) from None

def __setattr__(self, name: str, value: t.Any) -> None:
values = self._storage.get({}).copy()
Expand All @@ -175,7 +175,7 @@ def __delattr__(self, name: str) -> None:
del values[name]
self._storage.set(values)
except KeyError:
raise AttributeError(name)
raise AttributeError(name) from None


class LocalStack:
Expand Down Expand Up @@ -556,7 +556,8 @@ def _get_current_object(self) -> t.Any:
try:
return getattr(self.__local, self.__name) # type: ignore
except AttributeError:
raise RuntimeError(f"no object bound to {self.__name}") # type: ignore
name = self.__name # type: ignore
raise RuntimeError(f"no object bound to {name}") from None

__doc__ = _ProxyLookup( # type: ignore
class_value=__doc__, fallback=lambda self: type(self).__doc__
Expand Down
10 changes: 6 additions & 4 deletions src/werkzeug/routing.py
Original file line number Diff line number Diff line change
Expand Up @@ -1591,10 +1591,12 @@ def bind(
script_name = "/"
if path_info is None:
path_info = "/"

try:
server_name = _encode_idna(server_name) # type: ignore
except UnicodeError:
raise BadHost()
except UnicodeError as e:
raise BadHost() from e

return MapAdapter(
self,
server_name,
Expand Down Expand Up @@ -1973,13 +1975,13 @@ def match(
url_quote(e.path_info, self.map.charset, safe="/:|+"),
query_args,
)
)
) from None
except RequestAliasRedirect as e:
raise RequestRedirect(
self.make_alias_redirect_url(
path, rule.endpoint, e.matched_values, method, query_args
)
)
) from None
if rv is None:
continue
if rule.methods is not None and method not in rule.methods:
Expand Down
10 changes: 6 additions & 4 deletions src/werkzeug/serving.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@

class _SslDummy:
def __getattr__(self, name: str) -> t.Any:
raise RuntimeError("SSL support unavailable")
raise RuntimeError("SSL support unavailable") # noqa: B904

ssl = _SslDummy() # type: ignore

Expand Down Expand Up @@ -98,8 +98,8 @@ def read_chunk_len(self) -> int:
try:
line = self._rfile.readline().decode("latin1")
_len = int(line.strip(), 16)
except ValueError:
raise OSError("Invalid chunk header")
except ValueError as e:
raise OSError("Invalid chunk header") from e
if _len < 0:
raise OSError("Negative chunk length not allowed")
return _len
Expand Down Expand Up @@ -467,7 +467,9 @@ def generate_adhoc_ssl_pair(
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import rsa
except ImportError:
raise TypeError("Using ad-hoc certificates requires the cryptography library.")
raise TypeError(
"Using ad-hoc certificates requires the cryptography library."
) from None

backend = default_backend()
pkey = rsa.generate_private_key(
Expand Down
8 changes: 5 additions & 3 deletions src/werkzeug/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -847,7 +847,7 @@ def send_from_directory(
raise NotFound()
except ValueError:
# path contains null byte on Python < 3.8
raise NotFound()
raise NotFound() from None

return send_file(path, environ, **kwargs)

Expand Down Expand Up @@ -880,11 +880,13 @@ def import_string(import_name: str, silent: bool = False) -> t.Any:
try:
return getattr(module, obj_name)
except AttributeError as e:
raise ImportError(e)
raise ImportError(e) from None

except ImportError as e:
if not silent:
raise ImportStringError(import_name, e).with_traceback(sys.exc_info()[2])
raise ImportStringError(import_name, e).with_traceback(
sys.exc_info()[2]
) from None

return None

Expand Down
4 changes: 2 additions & 2 deletions tests/test_debug.py
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ def do_something():
try:
do_something()
except ValueError:
raise KeyError("outer")
raise KeyError("outer") # noqa: B904

debugged = DebuggedApplication(app)
client = Client(debugged)
Expand Down Expand Up @@ -331,7 +331,7 @@ def test_chained_exception_cycle():
try:
raise ValueError()
except ValueError:
raise TypeError()
raise TypeError() # noqa: B904
except TypeError as e:
# create a cycle and make it available outside the except block
e.__context__.__context__ = error = e
Expand Down

0 comments on commit ff5cd45

Please sign in to comment.