Last active
January 19, 2022 12:02
-
-
Save matteoferla/24d9a319d05773ae219dd678a3aa11be to your computer and use it in GitHub Desktop.
Yet another decorator wrapping error catching
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from typing import Any | |
from collections import defaultdict | |
class Safeguard: | |
""" | |
A decorator class (not a decorator factory class) | |
that will catch errors. | |
.. code-block:: python | |
@Safeguard | |
def foo(): | |
pass | |
foo.default_value = {} # set the value to return on error (default: nan) | |
foo.turn_off() # disable | |
foo.turn_on() # enable | |
foo.errors # Dict[List[Exceptions]] of caught errors | |
foo.error_to_catch # Exceptions to catch | |
""" | |
default_value = float('nan') | |
errors = defaultdict(list) | |
error_to_catch = Exception | |
def __init__(self, func): | |
import functools | |
functools.update_wrapper(self, func) | |
self.func = func | |
def __call__(self, *args, **kwargs): | |
""" | |
This wraps the function call, | |
not return a function that wraps the function call | |
""" | |
try: | |
return self.func(*args, **kwargs) | |
except self.error_to_catch as error: | |
self.errors[error.__class__.__name__].append(error) | |
return self.default_value | |
def turn_off(self): | |
self.error_to_catch = () | |
def turn_on(self, error_to_catch = Exception): | |
self.error_to_catch = error_to_catch | |
def reset(self): | |
self.errors = defaultdict(list) | |
@classmethod | |
def with_default_value(cls, default_value: Any) -> type: # i.e. the class not an instanace (=self) | |
""" | |
Rather hackish as it changes it globally! | |
""" | |
cls.default_value = default_value | |
return cls |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hacky loading the latest on a Jupyter notebook by not copypasting a larger code block:
Breaking that down...
API. A Gist url has a username and a hash id in it. Then each revision has a hash id in turn as seen in the url when you press
raw
. The API does not care for the username and wants only the hash.exec The
exec(response.text)
would work fine without thefaux_globals
if theexec
were run in the main namespace, but within a function the imported modules within the excecuted codeblock before the class are not visible to the class as they weren't the global namespace. Theimportlib.import_module('typing')
returns typing, but does not add it to the namespace.