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 | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
|