By default, the BaseException object in Python defines an args
attribute which is assigned the tuple of the arguments given to Exception objects at instantiation:
>>> err = ValueError("error msg")
>>> err.args
('error msg', )
It doesn’t seem unreasonable to be able to pattern match against that attribute using a match statement. This currently isn’t an option, as Exceptions (to my knowledge) don’t define a __match_args__
class attribute for the underlying infrastructure to hook into.
I’d like to propose adding a __match_args__ = ("args", )
class attribute to the BaseException object, to allow for structural pattern matching of Exception objects.
There are probably multiple ways to do this, but as a shoddy proof-of-concept I went ahead and cloned the cpython repo and added a getter and a setter to the BaseException_getset table under the name __match_args__
, where the getter returns an ("args", )
tuple and setter returns -1. Then in ceval.c
under the match_class
function, there’s a hook that calls the getter function if the __match_args__
attribute is a getset_descriptor object. That function call replaces the match_args
value with the returned tuple, and everything there on "just works"™.
The result allows you to use structural pattern matching on returned error objects:
# ./script.py
def fn(x):
if x > 10:
return ValueError("x is way too big", 10)
if x > 5:
return ValueError("x is too big", 5)
return x
match fn(11):
case ValueError((msg, 10)):
print(f"error 1: {msg}")
case ValueError((msg, 5)):
print(f"error 2: {msg}")
case _:
print("PASS")
root@7556897c20fe:/code# ./python script.py
error 1: x is way too big
Wondering if there is any interest in adding this type of functionality to the language. Errors as values is a concept well received in other languages such as Rust and Go; it has the potential to benefit static type analysis; and adding __match_args__
functionality to Exceptions would allow developers to elegantly integrate this paradigm into python mechanisms for structural pattern matching.
Repo:
Short description and image: