1def optimize_exception_check(attr_name):
2 def decorator(func):
3 def wrapper(self, exc_type):
4 cache = getattr(self, attr_name)
5 if exc_type in cache:
6 return True
7
8 result = func(self, exc_type) # True or False
9 if result:
10 cache.add(exc_type)
11 return result
12 return wrapper
13 return decorator
14
15
16class ProtectedSection:
17 __counter = 0
18
19 def __init__(self, log=(), suppress=()):
20 if log is not None:
21 for exc in log:
22 if not issubclass(exc, Exception):
23 raise TypeError("Not a valid exception type")
24
25 if suppress is not None:
26 for exc in suppress:
27 if not issubclass(exc, Exception):
28 raise TypeError("Not a valid exception type")
29
30 self._current_exception = None # Saves the specific or last "updated" exception in case of reuse of an already created instance
31 self.log_exceptions = set(log)
32 self.suppress_exceptions = set(suppress)
33 self._checked_exceptions_logs = set() # Optimization to avoid checking one exception n times
34 self._checked_exceptions_suppress = set() # Optimization to avoid checking one exception n times
35 self.exceptions_by_session = {} # Dictionary to store exceptions with their session ID
36
37 @optimize_exception_check("_checked_exceptions_logs")
38 def is_exception_logged(self, exc_type):
39 return exc_type in self.log_exceptions
40
41 @optimize_exception_check("_checked_exceptions_suppress")
42 def is_exception_suppressed(self, exc_type):
43 return exc_type in self.suppress_exceptions
44
45 def __enter__(self):
46 self._current_exception = None
47 return self
48
49 def __exit__(self, exc_type, exc_value, traceback):
50 if exc_type:
51 if self.is_exception_logged(exc_type):
52 self.exceptions_by_session[self.__counter] = exc_value
53 self.__counter += 1
54 self._current_exception = exc_value
55 return True
56
57 if self.is_exception_suppressed(exc_type):
58 self._current_exception = None
59 self.__counter += 1
60 return True
61
62 return False
63
64 @property
65 def exception(self):
66 return self._current_exception
67
68 @property
69 def exceptions(self):
70 return self.exceptions_by_session
71
72 def get_exception_by_session(self, session_id):
73 return self.exceptions_by_session.get(session_id, None)
..
----------------------------------------------------------------------
Ran 2 tests in 0.000s
OK
Георги Кунчев
09.11.2024 17:26Хаха, ок. Определено взе задачата навътре. Давам ти точка за усилията.
Мисля, че е далеч от очакванията, но щом си решил, ще го поощря.
|
Йоан Байчев
09.11.2024 13:40Относно проблема с преизползването на създадена инстанция, тъй като в примера cm1 и cm2 се държат като референции към инстанцията protected_section, създадох променлива "exceptions_by_session", която да пази конкретната грешка за конкретната "референция", като работи с индексация, което вече би било отговорност на потребителя, спрямо желанието му да види съответната грешка на н-тото преизползване. Променливата _current_exception пази грешката на най-актуалната референция, нейната цел е да бъде динамично изпозлвана в блока на with.
|
Георги Кунчев
09.11.2024 10:10Харесва ми, че искаш да оптимизираш, но имам няколко коментара.
* Двата декоратора правят едно и също нещо, просто с различни променливи. Можеш да опиташ да ги обединиш.
* Можеш да приложиш оптимизация като просто инициализираш `self.log_exceptions` и `self.suppress_exceptions` като сетове от кортежите, които влизат. Времето за търсене пак ще е константно. Ако кажеш - да, но губя време да направя сет от кортежа - така е, но така или иначе тази оптимизация ще работи само ако в последователните си блокове използваш една единствена инстанция. Ако за всеки `with` инициализираш наново, новата инстанция няма идея какво се е случило с останалите. С други думи, конвертирането към сет ще се случи само веднъж.
```
protected_section = ProtectedSection(log=(ValueError, ))
with protected_section as cm1:
raise ValueError('Text 1')
print(cm1.exception)
with protected_section as cm2:
raise ValueError('Text 2')
print(cm2.exception)
```
ПП: Държа да спомена, че има риск от използването на една инстанция, защото след презиползването ѝ губиш информация за грешката, която е породена в предишните използвания, тъй като инстанцията може да държи в себе си само една грешка. В края на изпълнението на кода по-горе, `cm1` ще държи същата грешка, която е сетната при изпълнение на втория блок.
|
Йоан Байчев
09.11.2024 01:58Тази оптимизация би била най-полезна в сценарии с множество последователни блокове "with ProtectedSection(...) as err:", изпълнявани често и съдържащи по-големи кортежи за проверка, тъй като елиминира повтарящите се линейни търсения. (вложени блокове)
|
Йоан Байчев
08.11.2024 16:52Целта на ExceptionStore е да осигури начин за запис на изключения, които не са подтиснати или логнати, така че те да могат да бъдат анализирани или обработени в бъдеще.
|
f | 1 | def optimize_exception_check(attr_name): | f | 1 | def optimize_exception_check(attr_name): |
2 | def decorator(func): | 2 | def decorator(func): | ||
3 | def wrapper(self, exc_type): | 3 | def wrapper(self, exc_type): | ||
4 | cache = getattr(self, attr_name) | 4 | cache = getattr(self, attr_name) | ||
5 | if exc_type in cache: | 5 | if exc_type in cache: | ||
6 | return True | 6 | return True | ||
7 | 7 | ||||
8 | result = func(self, exc_type) # True or False | 8 | result = func(self, exc_type) # True or False | ||
9 | if result: | 9 | if result: | ||
10 | cache.add(exc_type) | 10 | cache.add(exc_type) | ||
11 | return result | 11 | return result | ||
12 | return wrapper | 12 | return wrapper | ||
13 | return decorator | 13 | return decorator | ||
14 | 14 | ||||
15 | 15 | ||||
16 | class ProtectedSection: | 16 | class ProtectedSection: | ||
17 | __counter = 0 | 17 | __counter = 0 | ||
18 | 18 | ||||
19 | def __init__(self, log=(), suppress=()): | 19 | def __init__(self, log=(), suppress=()): | ||
20 | if log is not None: | 20 | if log is not None: | ||
21 | for exc in log: | 21 | for exc in log: | ||
22 | if not issubclass(exc, Exception): | 22 | if not issubclass(exc, Exception): | ||
23 | raise TypeError("Not a valid exception type") | 23 | raise TypeError("Not a valid exception type") | ||
24 | 24 | ||||
25 | if suppress is not None: | 25 | if suppress is not None: | ||
26 | for exc in suppress: | 26 | for exc in suppress: | ||
27 | if not issubclass(exc, Exception): | 27 | if not issubclass(exc, Exception): | ||
28 | raise TypeError("Not a valid exception type") | 28 | raise TypeError("Not a valid exception type") | ||
29 | 29 | ||||
30 | self._current_exception = None # Saves the specific or last "updated" exception in case of reuse of an already created instance | 30 | self._current_exception = None # Saves the specific or last "updated" exception in case of reuse of an already created instance | ||
31 | self.log_exceptions = set(log) | 31 | self.log_exceptions = set(log) | ||
32 | self.suppress_exceptions = set(suppress) | 32 | self.suppress_exceptions = set(suppress) | ||
33 | self._checked_exceptions_logs = set() # Optimization to avoid checking one exception n times | 33 | self._checked_exceptions_logs = set() # Optimization to avoid checking one exception n times | ||
34 | self._checked_exceptions_suppress = set() # Optimization to avoid checking one exception n times | 34 | self._checked_exceptions_suppress = set() # Optimization to avoid checking one exception n times | ||
35 | self.exceptions_by_session = {} # Dictionary to store exceptions with their session ID | 35 | self.exceptions_by_session = {} # Dictionary to store exceptions with their session ID | ||
36 | 36 | ||||
37 | @optimize_exception_check("_checked_exceptions_logs") | 37 | @optimize_exception_check("_checked_exceptions_logs") | ||
38 | def is_exception_logged(self, exc_type): | 38 | def is_exception_logged(self, exc_type): | ||
39 | return exc_type in self.log_exceptions | 39 | return exc_type in self.log_exceptions | ||
40 | 40 | ||||
41 | @optimize_exception_check("_checked_exceptions_suppress") | 41 | @optimize_exception_check("_checked_exceptions_suppress") | ||
42 | def is_exception_suppressed(self, exc_type): | 42 | def is_exception_suppressed(self, exc_type): | ||
43 | return exc_type in self.suppress_exceptions | 43 | return exc_type in self.suppress_exceptions | ||
44 | 44 | ||||
45 | def __enter__(self): | 45 | def __enter__(self): | ||
t | t | 46 | self._current_exception = None | ||
46 | return self | 47 | return self | ||
47 | 48 | ||||
48 | def __exit__(self, exc_type, exc_value, traceback): | 49 | def __exit__(self, exc_type, exc_value, traceback): | ||
49 | if exc_type: | 50 | if exc_type: | ||
50 | if self.is_exception_logged(exc_type): | 51 | if self.is_exception_logged(exc_type): | ||
51 | self.exceptions_by_session[self.__counter] = exc_value | 52 | self.exceptions_by_session[self.__counter] = exc_value | ||
52 | self.__counter += 1 | 53 | self.__counter += 1 | ||
53 | self._current_exception = exc_value | 54 | self._current_exception = exc_value | ||
54 | return True | 55 | return True | ||
55 | 56 | ||||
56 | if self.is_exception_suppressed(exc_type): | 57 | if self.is_exception_suppressed(exc_type): | ||
57 | self._current_exception = None | 58 | self._current_exception = None | ||
58 | self.__counter += 1 | 59 | self.__counter += 1 | ||
59 | return True | 60 | return True | ||
60 | 61 | ||||
61 | return False | 62 | return False | ||
62 | 63 | ||||
63 | @property | 64 | @property | ||
64 | def exception(self): | 65 | def exception(self): | ||
65 | return self._current_exception | 66 | return self._current_exception | ||
66 | 67 | ||||
67 | @property | 68 | @property | ||
68 | def exceptions(self): | 69 | def exceptions(self): | ||
69 | return self.exceptions_by_session | 70 | return self.exceptions_by_session | ||
70 | 71 | ||||
71 | def get_exception_by_session(self, session_id): | 72 | def get_exception_by_session(self, session_id): | ||
72 | return self.exceptions_by_session.get(session_id, None) | 73 | return self.exceptions_by_session.get(session_id, None) |
Legends | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
|
f | 1 | def optimize_exception_check(attr_name): | f | 1 | def optimize_exception_check(attr_name): |
2 | def decorator(func): | 2 | def decorator(func): | ||
3 | def wrapper(self, exc_type): | 3 | def wrapper(self, exc_type): | ||
4 | cache = getattr(self, attr_name) | 4 | cache = getattr(self, attr_name) | ||
5 | if exc_type in cache: | 5 | if exc_type in cache: | ||
6 | return True | 6 | return True | ||
7 | 7 | ||||
n | 8 | result = func(self, exc_type) # true or false | n | 8 | result = func(self, exc_type) # True or False |
9 | if result: | 9 | if result: | ||
10 | cache.add(exc_type) | 10 | cache.add(exc_type) | ||
11 | return result | 11 | return result | ||
12 | return wrapper | 12 | return wrapper | ||
13 | return decorator | 13 | return decorator | ||
14 | 14 | ||||
15 | 15 | ||||
16 | class ProtectedSection: | 16 | class ProtectedSection: | ||
n | n | 17 | __counter = 0 | ||
18 | |||||
17 | def __init__(self, log=(), suppress=()): | 19 | def __init__(self, log=(), suppress=()): | ||
18 | if log is not None: | 20 | if log is not None: | ||
19 | for exc in log: | 21 | for exc in log: | ||
20 | if not issubclass(exc, Exception): | 22 | if not issubclass(exc, Exception): | ||
21 | raise TypeError("Not a valid exception type") | 23 | raise TypeError("Not a valid exception type") | ||
22 | 24 | ||||
23 | if suppress is not None: | 25 | if suppress is not None: | ||
24 | for exc in suppress: | 26 | for exc in suppress: | ||
25 | if not issubclass(exc, Exception): | 27 | if not issubclass(exc, Exception): | ||
26 | raise TypeError("Not a valid exception type") | 28 | raise TypeError("Not a valid exception type") | ||
27 | 29 | ||||
n | 28 | self.exception = None | n | 30 | self._current_exception = None # Saves the specific or last "updated" exception in case of reuse of an already created instance |
29 | self.log_exceptions = set(log) | 31 | self.log_exceptions = set(log) | ||
30 | self.suppress_exceptions = set(suppress) | 32 | self.suppress_exceptions = set(suppress) | ||
31 | self._checked_exceptions_logs = set() # Optimization to avoid checking one exception n times | 33 | self._checked_exceptions_logs = set() # Optimization to avoid checking one exception n times | ||
32 | self._checked_exceptions_suppress = set() # Optimization to avoid checking one exception n times | 34 | self._checked_exceptions_suppress = set() # Optimization to avoid checking one exception n times | ||
n | n | 35 | self.exceptions_by_session = {} # Dictionary to store exceptions with their session ID | ||
33 | 36 | ||||
34 | @optimize_exception_check("_checked_exceptions_logs") | 37 | @optimize_exception_check("_checked_exceptions_logs") | ||
35 | def is_exception_logged(self, exc_type): | 38 | def is_exception_logged(self, exc_type): | ||
36 | return exc_type in self.log_exceptions | 39 | return exc_type in self.log_exceptions | ||
37 | 40 | ||||
38 | @optimize_exception_check("_checked_exceptions_suppress") | 41 | @optimize_exception_check("_checked_exceptions_suppress") | ||
39 | def is_exception_suppressed(self, exc_type): | 42 | def is_exception_suppressed(self, exc_type): | ||
40 | return exc_type in self.suppress_exceptions | 43 | return exc_type in self.suppress_exceptions | ||
41 | 44 | ||||
42 | def __enter__(self): | 45 | def __enter__(self): | ||
43 | return self | 46 | return self | ||
44 | 47 | ||||
45 | def __exit__(self, exc_type, exc_value, traceback): | 48 | def __exit__(self, exc_type, exc_value, traceback): | ||
46 | if exc_type: | 49 | if exc_type: | ||
47 | if self.is_exception_logged(exc_type): | 50 | if self.is_exception_logged(exc_type): | ||
n | n | 51 | self.exceptions_by_session[self.__counter] = exc_value | ||
52 | self.__counter += 1 | ||||
48 | self.exception = exc_value | 53 | self._current_exception = exc_value | ||
49 | return True | 54 | return True | ||
50 | 55 | ||||
51 | if self.is_exception_suppressed(exc_type): | 56 | if self.is_exception_suppressed(exc_type): | ||
n | 52 | self.exception = None | n | 57 | self._current_exception = None |
58 | self.__counter += 1 | ||||
53 | return True | 59 | return True | ||
54 | 60 | ||||
55 | return False | 61 | return False | ||
t | t | 62 | |||
63 | @property | ||||
64 | def exception(self): | ||||
65 | return self._current_exception | ||||
66 | |||||
67 | @property | ||||
68 | def exceptions(self): | ||||
69 | return self.exceptions_by_session | ||||
70 | |||||
71 | def get_exception_by_session(self, session_id): | ||||
72 | return self.exceptions_by_session.get(session_id, None) |
Legends | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
|
n | 1 | def optimize_exception_check_for_logs(func): | n | 1 | def optimize_exception_check(attr_name): |
2 | def decorator(func): | ||||
2 | def wrapper(self, exc_type): | 3 | def wrapper(self, exc_type): | ||
3 | if exc_type in self._checked_exceptions_logs: | 4 | cache = getattr(self, attr_name) | ||
4 | return self._checked_exceptions_logs[exc_type] | 5 | if exc_type in cache: | ||
6 | return True | ||||
5 | 7 | ||||
n | 6 | result = func(self, exc_type) # 1 or 0 | n | 8 | result = func(self, exc_type) # true or false |
7 | self._checked_exceptions_logs[exc_type] = result | 9 | if result: | ||
8 | 10 | cache.add(exc_type) | |||
9 | return result | 11 | return result | ||
10 | return wrapper | 12 | return wrapper | ||
11 | 13 | return decorator | |||
12 | def optimize_exception_check_for_suppress(func): | ||||
13 | def wrapper(self, exc_type): | ||||
14 | if exc_type in self._checked_exceptions_suppress: | ||||
15 | return self._checked_exceptions_suppress[exc_type] | ||||
16 | |||||
17 | result = func(self, exc_type) # 1 or 0 | ||||
18 | self._checked_exceptions_suppress[exc_type] = result | ||||
19 | |||||
20 | return result | ||||
21 | return wrapper | ||||
22 | 14 | ||||
23 | 15 | ||||
24 | class ProtectedSection: | 16 | class ProtectedSection: | ||
25 | def __init__(self, log=(), suppress=()): | 17 | def __init__(self, log=(), suppress=()): | ||
26 | if log is not None: | 18 | if log is not None: | ||
27 | for exc in log: | 19 | for exc in log: | ||
28 | if not issubclass(exc, Exception): | 20 | if not issubclass(exc, Exception): | ||
29 | raise TypeError("Not a valid exception type") | 21 | raise TypeError("Not a valid exception type") | ||
30 | 22 | ||||
31 | if suppress is not None: | 23 | if suppress is not None: | ||
32 | for exc in suppress: | 24 | for exc in suppress: | ||
33 | if not issubclass(exc, Exception): | 25 | if not issubclass(exc, Exception): | ||
34 | raise TypeError("Not a valid exception type") | 26 | raise TypeError("Not a valid exception type") | ||
35 | 27 | ||||
n | 36 | self.log_exceptions = log | n | ||
37 | self.suppress_exceptions = suppress | ||||
38 | self.exception = None | 28 | self.exception = None | ||
n | n | 29 | self.log_exceptions = set(log) | ||
30 | self.suppress_exceptions = set(suppress) | ||||
39 | self._checked_exceptions_logs = {} # Optimization to avoid checking one exception n times | 31 | self._checked_exceptions_logs = set() # Optimization to avoid checking one exception n times | ||
40 | self._checked_exceptions_suppress = {} # Optimization to avoid checking one exception n times | 32 | self._checked_exceptions_suppress = set() # Optimization to avoid checking one exception n times | ||
41 | 33 | ||||
n | 42 | @optimize_exception_check_for_logs | n | 34 | @optimize_exception_check("_checked_exceptions_logs") |
43 | def is_exception_logged(self, exc_type): | 35 | def is_exception_logged(self, exc_type): | ||
44 | return exc_type in self.log_exceptions | 36 | return exc_type in self.log_exceptions | ||
45 | 37 | ||||
t | 46 | @optimize_exception_check_for_suppress | t | 38 | @optimize_exception_check("_checked_exceptions_suppress") |
47 | def is_exception_suppressed(self, exc_type): | 39 | def is_exception_suppressed(self, exc_type): | ||
48 | return exc_type in self.suppress_exceptions | 40 | return exc_type in self.suppress_exceptions | ||
49 | 41 | ||||
50 | def __enter__(self): | 42 | def __enter__(self): | ||
51 | return self | 43 | return self | ||
52 | 44 | ||||
53 | def __exit__(self, exc_type, exc_value, traceback): | 45 | def __exit__(self, exc_type, exc_value, traceback): | ||
54 | if exc_type: | 46 | if exc_type: | ||
55 | if self.is_exception_logged(exc_type): | 47 | if self.is_exception_logged(exc_type): | ||
56 | self.exception = exc_value | 48 | self.exception = exc_value | ||
57 | return True | 49 | return True | ||
58 | 50 | ||||
59 | if self.is_exception_suppressed(exc_type): | 51 | if self.is_exception_suppressed(exc_type): | ||
60 | self.exception = None | 52 | self.exception = None | ||
61 | return True | 53 | return True | ||
62 | 54 | ||||
63 | return False | 55 | return False |
Legends | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
|
n | 1 | class ExceptionStore: | n | 1 | def optimize_exception_check_for_logs(func): |
2 | def __init__(self): | 2 | def wrapper(self, exc_type): | ||
3 | self.unhandled_exceptions = [] | 3 | if exc_type in self._checked_exceptions_logs: | ||
4 | self.exception = None | 4 | return self._checked_exceptions_logs[exc_type] | ||
5 | 5 | ||||
n | 6 | def log_exception(self, exc_value, exc_type): | n | 6 | result = func(self, exc_type) # 1 or 0 |
7 | self.unhandled_exceptions.append((exc_value, exc_type)) | 7 | self._checked_exceptions_logs[exc_type] = result | ||
8 | self.exception = exc_value | 8 | |||
9 | return result | ||||
10 | return wrapper | ||||
11 | |||||
12 | def optimize_exception_check_for_suppress(func): | ||||
13 | def wrapper(self, exc_type): | ||||
14 | if exc_type in self._checked_exceptions_suppress: | ||||
15 | return self._checked_exceptions_suppress[exc_type] | ||||
16 | |||||
17 | result = func(self, exc_type) # 1 or 0 | ||||
18 | self._checked_exceptions_suppress[exc_type] = result | ||||
19 | |||||
20 | return result | ||||
21 | return wrapper | ||||
9 | 22 | ||||
10 | 23 | ||||
n | 11 | class ProtectedSection(ExceptionStore): | n | 24 | class ProtectedSection: |
12 | def __init__(self, log=(), suppress=()): | 25 | def __init__(self, log=(), suppress=()): | ||
n | n | 26 | if log is not None: | ||
27 | for exc in log: | ||||
13 | if not all(issubclass(exc, Exception) for exc in log): | 28 | if not issubclass(exc, Exception): | ||
14 | raise TypeError("Must be exception types") | 29 | raise TypeError("Not a valid exception type") | ||
15 | if not all(issubclass(exc, Exception) for exc in suppress): | ||||
16 | raise TypeError("Must be exception types") | ||||
17 | 30 | ||||
n | 18 | super().__init__() | n | 31 | if suppress is not None: |
32 | for exc in suppress: | ||||
33 | if not issubclass(exc, Exception): | ||||
34 | raise TypeError("Not a valid exception type") | ||||
35 | |||||
19 | self.log = log | 36 | self.log_exceptions = log | ||
20 | self.suppress = suppress | 37 | self.suppress_exceptions = suppress | ||
38 | self.exception = None | ||||
39 | self._checked_exceptions_logs = {} # Optimization to avoid checking one exception n times | ||||
40 | self._checked_exceptions_suppress = {} # Optimization to avoid checking one exception n times | ||||
41 | |||||
42 | @optimize_exception_check_for_logs | ||||
43 | def is_exception_logged(self, exc_type): | ||||
44 | return exc_type in self.log_exceptions | ||||
45 | |||||
46 | @optimize_exception_check_for_suppress | ||||
47 | def is_exception_suppressed(self, exc_type): | ||||
48 | return exc_type in self.suppress_exceptions | ||||
21 | 49 | ||||
22 | def __enter__(self): | 50 | def __enter__(self): | ||
23 | return self | 51 | return self | ||
24 | 52 | ||||
25 | def __exit__(self, exc_type, exc_value, traceback): | 53 | def __exit__(self, exc_type, exc_value, traceback): | ||
26 | if exc_type: | 54 | if exc_type: | ||
n | 27 | if exc_type in self.log: | n | 55 | if self.is_exception_logged(exc_type): |
28 | self.exception = exc_value | 56 | self.exception = exc_value | ||
29 | return True | 57 | return True | ||
n | 30 | elif exc_type in self.suppress: | n | 58 | |
59 | if self.is_exception_suppressed(exc_type): | ||||
60 | self.exception = None | ||||
31 | return True | 61 | return True | ||
t | 32 | else: | t | 62 | |
33 | self.log_exception(exc_value, exc_type) | ||||
34 | return False | ||||
35 | return False | 63 | return False |
Legends | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
|
f | 1 | class ExceptionStore: | f | 1 | class ExceptionStore: |
2 | def __init__(self): | 2 | def __init__(self): | ||
3 | self.unhandled_exceptions = [] | 3 | self.unhandled_exceptions = [] | ||
4 | self.exception = None | 4 | self.exception = None | ||
5 | 5 | ||||
6 | def log_exception(self, exc_value, exc_type): | 6 | def log_exception(self, exc_value, exc_type): | ||
7 | self.unhandled_exceptions.append((exc_value, exc_type)) | 7 | self.unhandled_exceptions.append((exc_value, exc_type)) | ||
8 | self.exception = exc_value | 8 | self.exception = exc_value | ||
9 | 9 | ||||
10 | 10 | ||||
11 | class ProtectedSection(ExceptionStore): | 11 | class ProtectedSection(ExceptionStore): | ||
12 | def __init__(self, log=(), suppress=()): | 12 | def __init__(self, log=(), suppress=()): | ||
n | 13 | if not all(isinstance(exc, type) and issubclass(exc, Exception) for exc in log): | n | 13 | if not all(issubclass(exc, Exception) for exc in log): |
14 | raise TypeError("Мust be exception types") | 14 | raise TypeError("Must be exception types") | ||
15 | if not all(isinstance(exc, type) and issubclass(exc, Exception) for exc in suppress): | 15 | if not all(issubclass(exc, Exception) for exc in suppress): | ||
16 | raise TypeError("Мust be exception types") | 16 | raise TypeError("Must be exception types") | ||
17 | 17 | ||||
18 | super().__init__() | 18 | super().__init__() | ||
19 | self.log = log | 19 | self.log = log | ||
20 | self.suppress = suppress | 20 | self.suppress = suppress | ||
21 | 21 | ||||
22 | def __enter__(self): | 22 | def __enter__(self): | ||
23 | return self | 23 | return self | ||
24 | 24 | ||||
25 | def __exit__(self, exc_type, exc_value, traceback): | 25 | def __exit__(self, exc_type, exc_value, traceback): | ||
26 | if exc_type: | 26 | if exc_type: | ||
n | 27 | if any(issubclass(exc_type, log_exc) for log_exc in self.log): | n | 27 | if exc_type in self.log: |
28 | self.exception = exc_value | 28 | self.exception = exc_value | ||
29 | return True | 29 | return True | ||
t | 30 | elif any(issubclass(exc_type, suppress_exc) for suppress_exc in self.suppress): | t | 30 | elif exc_type in self.suppress: |
31 | return True | 31 | return True | ||
32 | else: | 32 | else: | ||
33 | self.log_exception(exc_value, exc_type) | 33 | self.log_exception(exc_value, exc_type) | ||
34 | return False | 34 | return False | ||
35 | return False | 35 | return False |
Legends | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
|