Cope 2.5.0
My personal "standard library" of all the generally useful code I've written for various projects over the years
Loading...
Searching...
No Matches
decorators.py
1"""
2Miscellaneous decorators that can be useful
3"""
4
5from .debugging import get_metadata, called_as_decorator, print_debug_count, get_context, print_context
6from .misc import interpret_percentage
7from warnings import warn
8# from .colors import coloredOutput, darken
9# from ._config import config
10_todoCalls = set()
11hide_todo = False
12
13
14class EpistemologicalWarning(UserWarning):
15 """ This is a joke/pet peeve of mine for people who say they're 100% confident in something """
16 pass
17
18def todo(feature:str=None, enabled:bool=True, blocking:bool=False, limit:bool=True):
19 # Can be manually turned on or off with hideAllTodos(bool).
20 """ Leave reminders for yourself to finish parts of your code.
21 Can also be used as a decorator (for functions or classes) to print a reminder and optionally
22 throw a NotImplemented error on being called/constructed.
23 Parameters:
24 enabled: enable or disable printed warnings
25 blocking: raise an error, instead of just warning you
26 limit: if called multiple times, and this is true, only print once
27 """
28
29 if not __debug__:
30 return
31
32 metadata = get_metadata(2)
33 situation = called_as_decorator('todo', metadata)
34 # First off, if we're limiting calls, check if we've already been called
35 uniqueID = (metadata.lineno, metadata.filename)
36 if limit and uniqueID in _todoCalls:
37 return
38 else:
39 _todoCalls.add(uniqueID)
40
41 def printTodo(disableFunc):
42 if not hide_todo and enabled:
43 print_debug_count()
44 print(get_context(metadata, path=True, func=False if disableFunc else None), end='', style=color)
45 # This is coincidental, but it works
46 print(f'TODO: {feature.__name__ if disableFunc else feature}')
47 if blocking:
48 raise NotImplementedError(feature)
49
50 # Being used as a function decorator, or we're not sure
51 if situation in (1, 3):
52 def wrap(func):
53 def innerWrap(*funcArgs, **funcKwArgs):
54 printTodo(True)
55 if blocking:
56 raise NotImplementedError(feature)
57 return feature(*funcArgs, **funcKwArgs)
58 return innerWrap
59 return wrap
60
61 elif situation == 2:
62 def wrap(clas):
63 def raiseErr(*_, **kw_):
64 raise NotImplementedError(feature)
65 printTodo(True)
66 if blocking:
67 feature.__init__ = raiseErr
68 return feature
69 else:
70 printTodo(False)
71
72def confidence(level:float):
73 if not __debug__:
74 return
75
76 level = interpret_percentage(level) * 100
77
78 def wrap(func):
79 def innerWrap(*funcArgs, **funcKwArgs):
80
81 # This is a pet-peeve
82 if level > 100:
83 raise TypeError(f"You can't be {level}% confident, that's not how it works.")
84 elif level == 100:
85 raise EpistemologicalWarning(f'Are you *sure* you\'re 100% confident? (not 99.99%?)')
86 # Definite Failure
87 elif level < 10:
88 raise UserWarning(f"{func.__name__} will almost certainly going to fail. ({level}% confidence)")
89 # Likely Failure
90 elif level <= 50:
91 print_context(3, func=False, color='warn')
92 print(f"Warning: {func.__name__} will probably fail. ({level}% confidence)", style='warn')
93 # Possible Failure
94 elif level < 80:
95 # print_context(3, func=False, color='confidence_warning')
96 print(f"Warning: {func.__name__} might not work. ({level}% confidence)", style='confidence_warning')
97
98 return func(*funcArgs, **funcKwArgs)
99 return innerWrap
100 return wrap
101
102def depricated(why=''):
103 if not __debug__:
104 return
105
106 def wrap(func):
107 def innerWrap(*funcArgs, **funcKwArgs):
108
109 print_context(2, color='warn')
110 warn(f"{func.__name__} is Depricated{': ' if len(why) else '.'}{why}")
111
112 return func(*funcArgs, **funcKwArgs)
113 return innerWrap
114 return wrap
115
116def reprise(obj: type, *args, **kwargs) -> type:
117 """
118 A class decorator that sets the __repr__ member to the __str__ member.
119 Not super useful, but nice for quick custom classes.
120 """
121 obj.__repr__ = obj.__str__
122 return obj
123
124
125confident = confidence
126untested = confidence(51)
127tested = confidence(95)
This is a joke/pet peeve of mine for people who say they're 100% confident in something.
Definition: decorators.py:14
type reprise(type obj, *args, **kwargs)
A class decorator that sets the repr member to the str member.
Definition: decorators.py:116
def todo(str feature=None, bool enabled=True, bool blocking=False, bool limit=True)
Leave reminders for yourself to finish parts of your code.
Definition: decorators.py:18