1import re
2
3
4class Elf:
5 """A proxy to a kid, helping Santa with various tasks."""
6
7 MAX_YEARS = 5
8 COAL = 'coal'
9
10 def __init__(self, kid):
11 """Initiate based on a Kid instance."""
12 self._kid = kid
13 self._counter = 0
14 self._naughty = False
15 self._decorate_naughty_monitor()
16
17 def _decorate_naughty_monitor(self):
18 """Decorate all public methods with naughty monitors."""
19 for key in dir(self._kid):
20 val = getattr(self._kid, key)
21 if not key.startswith('_') and callable(val):
22 setattr(self._kid, key, self._monitor_naughty(val))
23
24 def _monitor_naughty(self, fun):
25 """Decorate a kid public method to monitor for Exceptions."""
26 def decorated(*args, **kwargs):
27 """Decorated version of the public method."""
28 try:
29 result = fun(*args, **kwargs)
30 except Exception:
31 self._naughty = True
32 raise
33 return result
34 return decorated
35
36 def __call__(self, present):
37 """Send a present to the kid."""
38 if present is not None: # Otherwise there is no xmas so no coals
39 present = self.COAL if self._naughty else present
40 self._counter += 1
41 self._naughty = False
42 if present is not None and self._counter <= self.MAX_YEARS:
43 self._kid(present)
44
45
46class Santa:
47 """Santa Claus."""
48
49 PRESENT_REGEX = re.compile(r'["\'](?P<present>[a-zA-Z0-9 ]+)["\']')
50 SIGATURE_REGEX = re.compile(r'^\s*(?P<signature>\d+)\s*$', re.MULTILINE)
51 _wishes = {}
52 _elves = {}
53
54 @classmethod
55 def _present_from_text(cls, message):
56 """Extract the wish from a message."""
57 return cls.PRESENT_REGEX.search(message)['present']
58
59 @classmethod
60 def _signature_from_text(cls, message):
61 """Extract the signature from a message."""
62 return cls.SIGATURE_REGEX.search(message)['signature']
63
64 def __new__(cls):
65 """Create as singleton."""
66 if not hasattr(cls, '_instance'):
67 cls._instance = super().__new__(cls)
68 return cls._instance
69
70 def __call__(self, kid, message):
71 """Receive a wish via calling."""
72 elf = self._elves[id(kid)]
73 self._wishes[elf] = self._present_from_text(message)
74
75 def __matmul__(self, message):
76 """Receive a wish via email."""
77 kid_id = int(self._signature_from_text(message))
78 elf = self._elves[kid_id]
79 self._wishes[elf] = self._present_from_text(message)
80
81 def __iter__(self):
82 """Make the class iterable."""
83 return iter(self._wishes.values())
84
85 @property
86 def _most_wanted(self):
87 """Get most wanted present."""
88 if not self._wishes:
89 return None
90 presents = list(self._wishes.values())
91 return max(presents, key=presents.count)
92
93 def register_kid(self, kid):
94 """Register a new kid."""
95 self._elves[id(kid)] = Elf(kid)
96
97 def xmas(self):
98 """Celebrate Christmas and give presents away."""
99 for elf in self._elves.values():
100 present = self._wishes.get(elf, self._most_wanted)
101 elf(present)
102 self._wishes = {}
103
104
105class Kid(type):
106
107 def __new__(cls, name, bases, dct):
108 """Creating a new class."""
109 if '__call__' not in dct:
110 raise NotImplementedError('А как ще получиш подарък?')
111 return super().__new__(cls, name, bases, dct)
112
113 def __call__(cls, *args, **kwargs):
114 """Creating new instance of a class."""
115 instance = super().__call__(*args, **kwargs)
116 Santa().register_kid(instance)
117 return instance
....................
----------------------------------------------------------------------
Ran 20 tests in 0.046s
OK
| f | 1 | import re | f | 1 | import re |
| 2 | 2 | ||||
| 3 | 3 | ||||
| 4 | class Elf: | 4 | class Elf: | ||
| 5 | """A proxy to a kid, helping Santa with various tasks.""" | 5 | """A proxy to a kid, helping Santa with various tasks.""" | ||
| 6 | 6 | ||||
| 7 | MAX_YEARS = 5 | 7 | MAX_YEARS = 5 | ||
| 8 | COAL = 'coal' | 8 | COAL = 'coal' | ||
| 9 | 9 | ||||
| 10 | def __init__(self, kid): | 10 | def __init__(self, kid): | ||
| 11 | """Initiate based on a Kid instance.""" | 11 | """Initiate based on a Kid instance.""" | ||
| 12 | self._kid = kid | 12 | self._kid = kid | ||
| 13 | self._counter = 0 | 13 | self._counter = 0 | ||
| 14 | self._naughty = False | 14 | self._naughty = False | ||
| 15 | self._decorate_naughty_monitor() | 15 | self._decorate_naughty_monitor() | ||
| 16 | 16 | ||||
| 17 | def _decorate_naughty_monitor(self): | 17 | def _decorate_naughty_monitor(self): | ||
| 18 | """Decorate all public methods with naughty monitors.""" | 18 | """Decorate all public methods with naughty monitors.""" | ||
| 19 | for key in dir(self._kid): | 19 | for key in dir(self._kid): | ||
| 20 | val = getattr(self._kid, key) | 20 | val = getattr(self._kid, key) | ||
| 21 | if not key.startswith('_') and callable(val): | 21 | if not key.startswith('_') and callable(val): | ||
| 22 | setattr(self._kid, key, self._monitor_naughty(val)) | 22 | setattr(self._kid, key, self._monitor_naughty(val)) | ||
| 23 | 23 | ||||
| 24 | def _monitor_naughty(self, fun): | 24 | def _monitor_naughty(self, fun): | ||
| 25 | """Decorate a kid public method to monitor for Exceptions.""" | 25 | """Decorate a kid public method to monitor for Exceptions.""" | ||
| 26 | def decorated(*args, **kwargs): | 26 | def decorated(*args, **kwargs): | ||
| 27 | """Decorated version of the public method.""" | 27 | """Decorated version of the public method.""" | ||
| 28 | try: | 28 | try: | ||
| 29 | result = fun(*args, **kwargs) | 29 | result = fun(*args, **kwargs) | ||
| 30 | except Exception: | 30 | except Exception: | ||
| 31 | self._naughty = True | 31 | self._naughty = True | ||
| 32 | raise | 32 | raise | ||
| 33 | return result | 33 | return result | ||
| 34 | return decorated | 34 | return decorated | ||
| 35 | 35 | ||||
| 36 | def __call__(self, present): | 36 | def __call__(self, present): | ||
| 37 | """Send a present to the kid.""" | 37 | """Send a present to the kid.""" | ||
| t | t | 38 | if present is not None: # Otherwise there is no xmas so no coals | ||
| 38 | present = self.COAL if self._naughty else present | 39 | present = self.COAL if self._naughty else present | ||
| 39 | self._counter += 1 | 40 | self._counter += 1 | ||
| 40 | self._naughty = False | 41 | self._naughty = False | ||
| 41 | if present is not None and self._counter <= self.MAX_YEARS: | 42 | if present is not None and self._counter <= self.MAX_YEARS: | ||
| 42 | self._kid(present) | 43 | self._kid(present) | ||
| 43 | 44 | ||||
| 44 | 45 | ||||
| 45 | class Santa: | 46 | class Santa: | ||
| 46 | """Santa Claus.""" | 47 | """Santa Claus.""" | ||
| 47 | 48 | ||||
| 48 | PRESENT_REGEX = re.compile(r'["\'](?P<present>[a-zA-Z0-9 ]+)["\']') | 49 | PRESENT_REGEX = re.compile(r'["\'](?P<present>[a-zA-Z0-9 ]+)["\']') | ||
| 49 | SIGATURE_REGEX = re.compile(r'^\s*(?P<signature>\d+)\s*$', re.MULTILINE) | 50 | SIGATURE_REGEX = re.compile(r'^\s*(?P<signature>\d+)\s*$', re.MULTILINE) | ||
| 50 | _wishes = {} | 51 | _wishes = {} | ||
| 51 | _elves = {} | 52 | _elves = {} | ||
| 52 | 53 | ||||
| 53 | @classmethod | 54 | @classmethod | ||
| 54 | def _present_from_text(cls, message): | 55 | def _present_from_text(cls, message): | ||
| 55 | """Extract the wish from a message.""" | 56 | """Extract the wish from a message.""" | ||
| 56 | return cls.PRESENT_REGEX.search(message)['present'] | 57 | return cls.PRESENT_REGEX.search(message)['present'] | ||
| 57 | 58 | ||||
| 58 | @classmethod | 59 | @classmethod | ||
| 59 | def _signature_from_text(cls, message): | 60 | def _signature_from_text(cls, message): | ||
| 60 | """Extract the signature from a message.""" | 61 | """Extract the signature from a message.""" | ||
| 61 | return cls.SIGATURE_REGEX.search(message)['signature'] | 62 | return cls.SIGATURE_REGEX.search(message)['signature'] | ||
| 62 | 63 | ||||
| 63 | def __new__(cls): | 64 | def __new__(cls): | ||
| 64 | """Create as singleton.""" | 65 | """Create as singleton.""" | ||
| 65 | if not hasattr(cls, '_instance'): | 66 | if not hasattr(cls, '_instance'): | ||
| 66 | cls._instance = super().__new__(cls) | 67 | cls._instance = super().__new__(cls) | ||
| 67 | return cls._instance | 68 | return cls._instance | ||
| 68 | 69 | ||||
| 69 | def __call__(self, kid, message): | 70 | def __call__(self, kid, message): | ||
| 70 | """Receive a wish via calling.""" | 71 | """Receive a wish via calling.""" | ||
| 71 | elf = self._elves[id(kid)] | 72 | elf = self._elves[id(kid)] | ||
| 72 | self._wishes[elf] = self._present_from_text(message) | 73 | self._wishes[elf] = self._present_from_text(message) | ||
| 73 | 74 | ||||
| 74 | def __matmul__(self, message): | 75 | def __matmul__(self, message): | ||
| 75 | """Receive a wish via email.""" | 76 | """Receive a wish via email.""" | ||
| 76 | kid_id = int(self._signature_from_text(message)) | 77 | kid_id = int(self._signature_from_text(message)) | ||
| 77 | elf = self._elves[kid_id] | 78 | elf = self._elves[kid_id] | ||
| 78 | self._wishes[elf] = self._present_from_text(message) | 79 | self._wishes[elf] = self._present_from_text(message) | ||
| 79 | 80 | ||||
| 80 | def __iter__(self): | 81 | def __iter__(self): | ||
| 81 | """Make the class iterable.""" | 82 | """Make the class iterable.""" | ||
| 82 | return iter(self._wishes.values()) | 83 | return iter(self._wishes.values()) | ||
| 83 | 84 | ||||
| 84 | @property | 85 | @property | ||
| 85 | def _most_wanted(self): | 86 | def _most_wanted(self): | ||
| 86 | """Get most wanted present.""" | 87 | """Get most wanted present.""" | ||
| 87 | if not self._wishes: | 88 | if not self._wishes: | ||
| 88 | return None | 89 | return None | ||
| 89 | presents = list(self._wishes.values()) | 90 | presents = list(self._wishes.values()) | ||
| 90 | return max(presents, key=presents.count) | 91 | return max(presents, key=presents.count) | ||
| 91 | 92 | ||||
| 92 | def register_kid(self, kid): | 93 | def register_kid(self, kid): | ||
| 93 | """Register a new kid.""" | 94 | """Register a new kid.""" | ||
| 94 | self._elves[id(kid)] = Elf(kid) | 95 | self._elves[id(kid)] = Elf(kid) | ||
| 95 | 96 | ||||
| 96 | def xmas(self): | 97 | def xmas(self): | ||
| 97 | """Celebrate Christmas and give presents away.""" | 98 | """Celebrate Christmas and give presents away.""" | ||
| 98 | for elf in self._elves.values(): | 99 | for elf in self._elves.values(): | ||
| 99 | present = self._wishes.get(elf, self._most_wanted) | 100 | present = self._wishes.get(elf, self._most_wanted) | ||
| 100 | elf(present) | 101 | elf(present) | ||
| 101 | self._wishes = {} | 102 | self._wishes = {} | ||
| 102 | 103 | ||||
| 103 | 104 | ||||
| 104 | class Kid(type): | 105 | class Kid(type): | ||
| 105 | 106 | ||||
| 106 | def __new__(cls, name, bases, dct): | 107 | def __new__(cls, name, bases, dct): | ||
| 107 | """Creating a new class.""" | 108 | """Creating a new class.""" | ||
| 108 | if '__call__' not in dct: | 109 | if '__call__' not in dct: | ||
| 109 | raise NotImplementedError('А как ще получиш подарък?') | 110 | raise NotImplementedError('А как ще получиш подарък?') | ||
| 110 | return super().__new__(cls, name, bases, dct) | 111 | return super().__new__(cls, name, bases, dct) | ||
| 111 | 112 | ||||
| 112 | def __call__(cls, *args, **kwargs): | 113 | def __call__(cls, *args, **kwargs): | ||
| 113 | """Creating new instance of a class.""" | 114 | """Creating new instance of a class.""" | ||
| 114 | instance = super().__call__(*args, **kwargs) | 115 | instance = super().__call__(*args, **kwargs) | ||
| 115 | Santa().register_kid(instance) | 116 | Santa().register_kid(instance) | ||
| 116 | return instance | 117 | return instance |
| Legends | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
| |||||||||
| f | 1 | import re | f | 1 | import re |
| n | 2 | n | |||
| 3 | |||||
| 4 | class Singleton(type): | ||||
| 5 | """Metaclass for singleton classes.""" | ||||
| 6 | |||||
| 7 | _instances = {} | ||||
| 8 | |||||
| 9 | def __call__(cls, *args, **kwargs): | ||||
| 10 | """Creating new instance of a class.""" | ||||
| 11 | if cls not in cls._instances: | ||||
| 12 | cls._instances[cls] = super().__call__(*args, **kwargs) | ||||
| 13 | return cls._instances[cls] | ||||
| 14 | 2 | ||||
| 15 | 3 | ||||
| 16 | class Elf: | 4 | class Elf: | ||
| 17 | """A proxy to a kid, helping Santa with various tasks.""" | 5 | """A proxy to a kid, helping Santa with various tasks.""" | ||
| 18 | 6 | ||||
| 19 | MAX_YEARS = 5 | 7 | MAX_YEARS = 5 | ||
| 20 | COAL = 'coal' | 8 | COAL = 'coal' | ||
| 21 | 9 | ||||
| 22 | def __init__(self, kid): | 10 | def __init__(self, kid): | ||
| 23 | """Initiate based on a Kid instance.""" | 11 | """Initiate based on a Kid instance.""" | ||
| 24 | self._kid = kid | 12 | self._kid = kid | ||
| 25 | self._counter = 0 | 13 | self._counter = 0 | ||
| 26 | self._naughty = False | 14 | self._naughty = False | ||
| 27 | self._decorate_naughty_monitor() | 15 | self._decorate_naughty_monitor() | ||
| 28 | 16 | ||||
| 29 | def _decorate_naughty_monitor(self): | 17 | def _decorate_naughty_monitor(self): | ||
| 30 | """Decorate all public methods with naughty monitors.""" | 18 | """Decorate all public methods with naughty monitors.""" | ||
| 31 | for key in dir(self._kid): | 19 | for key in dir(self._kid): | ||
| 32 | val = getattr(self._kid, key) | 20 | val = getattr(self._kid, key) | ||
| 33 | if not key.startswith('_') and callable(val): | 21 | if not key.startswith('_') and callable(val): | ||
| 34 | setattr(self._kid, key, self._monitor_naughty(val)) | 22 | setattr(self._kid, key, self._monitor_naughty(val)) | ||
| 35 | 23 | ||||
| 36 | def _monitor_naughty(self, fun): | 24 | def _monitor_naughty(self, fun): | ||
| 37 | """Decorate a kid public method to monitor for Exceptions.""" | 25 | """Decorate a kid public method to monitor for Exceptions.""" | ||
| 38 | def decorated(*args, **kwargs): | 26 | def decorated(*args, **kwargs): | ||
| 39 | """Decorated version of the public method.""" | 27 | """Decorated version of the public method.""" | ||
| 40 | try: | 28 | try: | ||
| n | 41 | result = fun(self._kid, *args, **kwargs) | n | 29 | result = fun(*args, **kwargs) |
| 42 | except Exception: | 30 | except Exception: | ||
| 43 | self._naughty = True | 31 | self._naughty = True | ||
| 44 | raise | 32 | raise | ||
| 45 | return result | 33 | return result | ||
| 46 | return decorated | 34 | return decorated | ||
| 47 | 35 | ||||
| 48 | def __call__(self, present): | 36 | def __call__(self, present): | ||
| 49 | """Send a present to the kid.""" | 37 | """Send a present to the kid.""" | ||
| 50 | present = self.COAL if self._naughty else present | 38 | present = self.COAL if self._naughty else present | ||
| 51 | self._counter += 1 | 39 | self._counter += 1 | ||
| 52 | self._naughty = False | 40 | self._naughty = False | ||
| 53 | if present is not None and self._counter <= self.MAX_YEARS: | 41 | if present is not None and self._counter <= self.MAX_YEARS: | ||
| 54 | self._kid(present) | 42 | self._kid(present) | ||
| 55 | 43 | ||||
| 56 | 44 | ||||
| n | 57 | class Santa(metaclass=Singleton): | n | 45 | class Santa: |
| 58 | """Santa.""" | 46 | """Santa Claus.""" | ||
| 59 | 47 | ||||
| 60 | PRESENT_REGEX = re.compile(r'["\'](?P<present>[a-zA-Z0-9 ]+)["\']') | 48 | PRESENT_REGEX = re.compile(r'["\'](?P<present>[a-zA-Z0-9 ]+)["\']') | ||
| 61 | SIGATURE_REGEX = re.compile(r'^\s*(?P<signature>\d+)\s*$', re.MULTILINE) | 49 | SIGATURE_REGEX = re.compile(r'^\s*(?P<signature>\d+)\s*$', re.MULTILINE) | ||
| 62 | _wishes = {} | 50 | _wishes = {} | ||
| 63 | _elves = {} | 51 | _elves = {} | ||
| 64 | 52 | ||||
| 65 | @classmethod | 53 | @classmethod | ||
| 66 | def _present_from_text(cls, message): | 54 | def _present_from_text(cls, message): | ||
| 67 | """Extract the wish from a message.""" | 55 | """Extract the wish from a message.""" | ||
| 68 | return cls.PRESENT_REGEX.search(message)['present'] | 56 | return cls.PRESENT_REGEX.search(message)['present'] | ||
| 69 | 57 | ||||
| 70 | @classmethod | 58 | @classmethod | ||
| 71 | def _signature_from_text(cls, message): | 59 | def _signature_from_text(cls, message): | ||
| 72 | """Extract the signature from a message.""" | 60 | """Extract the signature from a message.""" | ||
| 73 | return cls.SIGATURE_REGEX.search(message)['signature'] | 61 | return cls.SIGATURE_REGEX.search(message)['signature'] | ||
| t | t | 62 | |||
| 63 | def __new__(cls): | ||||
| 64 | """Create as singleton.""" | ||||
| 65 | if not hasattr(cls, '_instance'): | ||||
| 66 | cls._instance = super().__new__(cls) | ||||
| 67 | return cls._instance | ||||
| 74 | 68 | ||||
| 75 | def __call__(self, kid, message): | 69 | def __call__(self, kid, message): | ||
| 76 | """Receive a wish via calling.""" | 70 | """Receive a wish via calling.""" | ||
| 77 | elf = self._elves[id(kid)] | 71 | elf = self._elves[id(kid)] | ||
| 78 | self._wishes[elf] = self._present_from_text(message) | 72 | self._wishes[elf] = self._present_from_text(message) | ||
| 79 | 73 | ||||
| 80 | def __matmul__(self, message): | 74 | def __matmul__(self, message): | ||
| 81 | """Receive a wish via email.""" | 75 | """Receive a wish via email.""" | ||
| 82 | kid_id = int(self._signature_from_text(message)) | 76 | kid_id = int(self._signature_from_text(message)) | ||
| 83 | elf = self._elves[kid_id] | 77 | elf = self._elves[kid_id] | ||
| 84 | self._wishes[elf] = self._present_from_text(message) | 78 | self._wishes[elf] = self._present_from_text(message) | ||
| 85 | 79 | ||||
| 86 | def __iter__(self): | 80 | def __iter__(self): | ||
| 87 | """Make the class iterable.""" | 81 | """Make the class iterable.""" | ||
| 88 | return iter(self._wishes.values()) | 82 | return iter(self._wishes.values()) | ||
| 89 | 83 | ||||
| 90 | @property | 84 | @property | ||
| 91 | def _most_wanted(self): | 85 | def _most_wanted(self): | ||
| 92 | """Get most wanted present.""" | 86 | """Get most wanted present.""" | ||
| 93 | if not self._wishes: | 87 | if not self._wishes: | ||
| 94 | return None | 88 | return None | ||
| 95 | presents = list(self._wishes.values()) | 89 | presents = list(self._wishes.values()) | ||
| 96 | return max(presents, key=presents.count) | 90 | return max(presents, key=presents.count) | ||
| 97 | 91 | ||||
| 98 | def register_kid(self, kid): | 92 | def register_kid(self, kid): | ||
| 99 | """Register a new kid.""" | 93 | """Register a new kid.""" | ||
| 100 | self._elves[id(kid)] = Elf(kid) | 94 | self._elves[id(kid)] = Elf(kid) | ||
| 101 | 95 | ||||
| 102 | def xmas(self): | 96 | def xmas(self): | ||
| 103 | """Celebrate Christmas and give presents away.""" | 97 | """Celebrate Christmas and give presents away.""" | ||
| 104 | for elf in self._elves.values(): | 98 | for elf in self._elves.values(): | ||
| 105 | present = self._wishes.get(elf, self._most_wanted) | 99 | present = self._wishes.get(elf, self._most_wanted) | ||
| 106 | elf(present) | 100 | elf(present) | ||
| 107 | self._wishes = {} | 101 | self._wishes = {} | ||
| 108 | 102 | ||||
| 109 | 103 | ||||
| 110 | class Kid(type): | 104 | class Kid(type): | ||
| 111 | 105 | ||||
| 112 | def __new__(cls, name, bases, dct): | 106 | def __new__(cls, name, bases, dct): | ||
| 113 | """Creating a new class.""" | 107 | """Creating a new class.""" | ||
| 114 | if '__call__' not in dct: | 108 | if '__call__' not in dct: | ||
| 115 | raise NotImplementedError('А как ще получиш подарък?') | 109 | raise NotImplementedError('А как ще получиш подарък?') | ||
| 116 | return super().__new__(cls, name, bases, dct) | 110 | return super().__new__(cls, name, bases, dct) | ||
| 117 | 111 | ||||
| 118 | def __call__(cls, *args, **kwargs): | 112 | def __call__(cls, *args, **kwargs): | ||
| 119 | """Creating new instance of a class.""" | 113 | """Creating new instance of a class.""" | ||
| 120 | instance = super().__call__(*args, **kwargs) | 114 | instance = super().__call__(*args, **kwargs) | ||
| 121 | Santa().register_kid(instance) | 115 | Santa().register_kid(instance) | ||
| 122 | return instance | 116 | return instance |
| Legends | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
| |||||||||
| f | 1 | import re | f | 1 | import re |
| 2 | 2 | ||||
| 3 | 3 | ||||
| 4 | class Singleton(type): | 4 | class Singleton(type): | ||
| 5 | """Metaclass for singleton classes.""" | 5 | """Metaclass for singleton classes.""" | ||
| 6 | 6 | ||||
| 7 | _instances = {} | 7 | _instances = {} | ||
| 8 | 8 | ||||
| 9 | def __call__(cls, *args, **kwargs): | 9 | def __call__(cls, *args, **kwargs): | ||
| 10 | """Creating new instance of a class.""" | 10 | """Creating new instance of a class.""" | ||
| 11 | if cls not in cls._instances: | 11 | if cls not in cls._instances: | ||
| 12 | cls._instances[cls] = super().__call__(*args, **kwargs) | 12 | cls._instances[cls] = super().__call__(*args, **kwargs) | ||
| 13 | return cls._instances[cls] | 13 | return cls._instances[cls] | ||
| 14 | 14 | ||||
| 15 | 15 | ||||
| 16 | class Elf: | 16 | class Elf: | ||
| 17 | """A proxy to a kid, helping Santa with various tasks.""" | 17 | """A proxy to a kid, helping Santa with various tasks.""" | ||
| 18 | 18 | ||||
| 19 | MAX_YEARS = 5 | 19 | MAX_YEARS = 5 | ||
| 20 | COAL = 'coal' | 20 | COAL = 'coal' | ||
| 21 | 21 | ||||
| 22 | def __init__(self, kid): | 22 | def __init__(self, kid): | ||
| 23 | """Initiate based on a Kid instance.""" | 23 | """Initiate based on a Kid instance.""" | ||
| 24 | self._kid = kid | 24 | self._kid = kid | ||
| 25 | self._counter = 0 | 25 | self._counter = 0 | ||
| 26 | self._naughty = False | 26 | self._naughty = False | ||
| 27 | self._decorate_naughty_monitor() | 27 | self._decorate_naughty_monitor() | ||
| 28 | 28 | ||||
| 29 | def _decorate_naughty_monitor(self): | 29 | def _decorate_naughty_monitor(self): | ||
| t | t | 30 | """Decorate all public methods with naughty monitors.""" | ||
| 30 | for key in dir(self._kid): | 31 | for key in dir(self._kid): | ||
| 31 | val = getattr(self._kid, key) | 32 | val = getattr(self._kid, key) | ||
| 32 | if not key.startswith('_') and callable(val): | 33 | if not key.startswith('_') and callable(val): | ||
| 33 | setattr(self._kid, key, self._monitor_naughty(val)) | 34 | setattr(self._kid, key, self._monitor_naughty(val)) | ||
| 34 | 35 | ||||
| 35 | def _monitor_naughty(self, fun): | 36 | def _monitor_naughty(self, fun): | ||
| 36 | """Decorate a kid public method to monitor for Exceptions.""" | 37 | """Decorate a kid public method to monitor for Exceptions.""" | ||
| 37 | def decorated(*args, **kwargs): | 38 | def decorated(*args, **kwargs): | ||
| 38 | """Decorated version of the public method.""" | 39 | """Decorated version of the public method.""" | ||
| 39 | try: | 40 | try: | ||
| 40 | result = fun(self._kid, *args, **kwargs) | 41 | result = fun(self._kid, *args, **kwargs) | ||
| 41 | except Exception: | 42 | except Exception: | ||
| 42 | self._naughty = True | 43 | self._naughty = True | ||
| 43 | raise | 44 | raise | ||
| 44 | return result | 45 | return result | ||
| 45 | return decorated | 46 | return decorated | ||
| 46 | 47 | ||||
| 47 | def __call__(self, present): | 48 | def __call__(self, present): | ||
| 48 | """Send a present to the kid.""" | 49 | """Send a present to the kid.""" | ||
| 49 | present = self.COAL if self._naughty else present | 50 | present = self.COAL if self._naughty else present | ||
| 50 | self._counter += 1 | 51 | self._counter += 1 | ||
| 51 | self._naughty = False | 52 | self._naughty = False | ||
| 52 | if present is not None and self._counter <= self.MAX_YEARS: | 53 | if present is not None and self._counter <= self.MAX_YEARS: | ||
| 53 | self._kid(present) | 54 | self._kid(present) | ||
| 54 | 55 | ||||
| 55 | 56 | ||||
| 56 | class Santa(metaclass=Singleton): | 57 | class Santa(metaclass=Singleton): | ||
| 57 | """Santa.""" | 58 | """Santa.""" | ||
| 58 | 59 | ||||
| 59 | PRESENT_REGEX = re.compile(r'["\'](?P<present>[a-zA-Z0-9 ]+)["\']') | 60 | PRESENT_REGEX = re.compile(r'["\'](?P<present>[a-zA-Z0-9 ]+)["\']') | ||
| 60 | SIGATURE_REGEX = re.compile(r'^\s*(?P<signature>\d+)\s*$', re.MULTILINE) | 61 | SIGATURE_REGEX = re.compile(r'^\s*(?P<signature>\d+)\s*$', re.MULTILINE) | ||
| 61 | _wishes = {} | 62 | _wishes = {} | ||
| 62 | _elves = {} | 63 | _elves = {} | ||
| 63 | 64 | ||||
| 64 | @classmethod | 65 | @classmethod | ||
| 65 | def _present_from_text(cls, message): | 66 | def _present_from_text(cls, message): | ||
| 66 | """Extract the wish from a message.""" | 67 | """Extract the wish from a message.""" | ||
| 67 | return cls.PRESENT_REGEX.search(message)['present'] | 68 | return cls.PRESENT_REGEX.search(message)['present'] | ||
| 68 | 69 | ||||
| 69 | @classmethod | 70 | @classmethod | ||
| 70 | def _signature_from_text(cls, message): | 71 | def _signature_from_text(cls, message): | ||
| 71 | """Extract the signature from a message.""" | 72 | """Extract the signature from a message.""" | ||
| 72 | return cls.SIGATURE_REGEX.search(message)['signature'] | 73 | return cls.SIGATURE_REGEX.search(message)['signature'] | ||
| 73 | 74 | ||||
| 74 | def __call__(self, kid, message): | 75 | def __call__(self, kid, message): | ||
| 75 | """Receive a wish via calling.""" | 76 | """Receive a wish via calling.""" | ||
| 76 | elf = self._elves[id(kid)] | 77 | elf = self._elves[id(kid)] | ||
| 77 | self._wishes[elf] = self._present_from_text(message) | 78 | self._wishes[elf] = self._present_from_text(message) | ||
| 78 | 79 | ||||
| 79 | def __matmul__(self, message): | 80 | def __matmul__(self, message): | ||
| 80 | """Receive a wish via email.""" | 81 | """Receive a wish via email.""" | ||
| 81 | kid_id = int(self._signature_from_text(message)) | 82 | kid_id = int(self._signature_from_text(message)) | ||
| 82 | elf = self._elves[kid_id] | 83 | elf = self._elves[kid_id] | ||
| 83 | self._wishes[elf] = self._present_from_text(message) | 84 | self._wishes[elf] = self._present_from_text(message) | ||
| 84 | 85 | ||||
| 85 | def __iter__(self): | 86 | def __iter__(self): | ||
| 86 | """Make the class iterable.""" | 87 | """Make the class iterable.""" | ||
| 87 | return iter(self._wishes.values()) | 88 | return iter(self._wishes.values()) | ||
| 88 | 89 | ||||
| 89 | @property | 90 | @property | ||
| 90 | def _most_wanted(self): | 91 | def _most_wanted(self): | ||
| 91 | """Get most wanted present.""" | 92 | """Get most wanted present.""" | ||
| 92 | if not self._wishes: | 93 | if not self._wishes: | ||
| 93 | return None | 94 | return None | ||
| 94 | presents = list(self._wishes.values()) | 95 | presents = list(self._wishes.values()) | ||
| 95 | return max(presents, key=presents.count) | 96 | return max(presents, key=presents.count) | ||
| 96 | 97 | ||||
| 97 | def register_kid(self, kid): | 98 | def register_kid(self, kid): | ||
| 98 | """Register a new kid.""" | 99 | """Register a new kid.""" | ||
| 99 | self._elves[id(kid)] = Elf(kid) | 100 | self._elves[id(kid)] = Elf(kid) | ||
| 100 | 101 | ||||
| 101 | def xmas(self): | 102 | def xmas(self): | ||
| 102 | """Celebrate Christmas and give presents away.""" | 103 | """Celebrate Christmas and give presents away.""" | ||
| 103 | for elf in self._elves.values(): | 104 | for elf in self._elves.values(): | ||
| 104 | present = self._wishes.get(elf, self._most_wanted) | 105 | present = self._wishes.get(elf, self._most_wanted) | ||
| 105 | elf(present) | 106 | elf(present) | ||
| 106 | self._wishes = {} | 107 | self._wishes = {} | ||
| 107 | 108 | ||||
| 108 | 109 | ||||
| 109 | class Kid(type): | 110 | class Kid(type): | ||
| 110 | 111 | ||||
| 111 | def __new__(cls, name, bases, dct): | 112 | def __new__(cls, name, bases, dct): | ||
| 112 | """Creating a new class.""" | 113 | """Creating a new class.""" | ||
| 113 | if '__call__' not in dct: | 114 | if '__call__' not in dct: | ||
| 114 | raise NotImplementedError('А как ще получиш подарък?') | 115 | raise NotImplementedError('А как ще получиш подарък?') | ||
| 115 | return super().__new__(cls, name, bases, dct) | 116 | return super().__new__(cls, name, bases, dct) | ||
| 116 | 117 | ||||
| 117 | def __call__(cls, *args, **kwargs): | 118 | def __call__(cls, *args, **kwargs): | ||
| 118 | """Creating new instance of a class.""" | 119 | """Creating new instance of a class.""" | ||
| 119 | instance = super().__call__(*args, **kwargs) | 120 | instance = super().__call__(*args, **kwargs) | ||
| 120 | Santa().register_kid(instance) | 121 | Santa().register_kid(instance) | ||
| 121 | return instance | 122 | return instance |
| Legends | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
| |||||||||