Домашни > Подаръци ще има за всички от сърце > Решения > Решението на Илиан Запрянов

Резултати
2 точки от тестове
0 точки от учител

2 точки общо

3 успешни теста
17 неуспешни теста
Код
Скрий всички коментари

  1import re
  2from collections import OrderedDict
  3import random
  4from unittest.mock import patch, call
  5
  6class SingletonMeta(type):
  7    """A metaclass for realizing the Singleton design pattern."""
  8   
  9   #attribute to save the unique instance in
 10    _instance = None
 11
 12    def __call__(cls, *args, **kwargs):
 13        """Control the creation of an instance of a class."""
 14        if not cls._instance:
 15            cls._instance = super().__call__(*args, **kwargs)
 16        return cls._instance
 17
 18class Santa(metaclass=SingletonMeta):
 19    """A class representing Santa."""
 20
 21    _kids = {}
 22    _wishes = OrderedDict()
 23    
 24    def __call__(self, kid, phone_call):
 25        """Handle a wish request made by a kid made by a phone call."""
 26        wish = self.get_wish_of(phone_call)
 27        self._wishes[id(kid)] = wish
 28            
 29    def __matmul__(self, letter):
 30        """Handle a wish request made by a Kid sent as a letter."""    
 31        wish = self.get_wish_of(letter)
 32        signature = int(re.search(r'(\b\d+\b)', letter).group(0))
 33        self._wishes[signature] = wish
 34
 35    def get_wish_of(self, source):
 36        """Match the wish in source."""    
 37        wish_match = re.search(r"(['\"])([\w ]+)\1", source, re.MULTILINE | re.DOTALL)
 38        return wish_match.group(1)
 39        
 40    @classmethod
 41    def add_new_kid(cls, kid):
 42        """Save kids in order to be able to call them."""    
 43        cls._kids[id(kid)] = kid
 44    
 45    def __iter__(self):
 46        """Return an iterator for Santa's presents."""
 47        self._all_presents = list(self._wishes.values())
 48        self._index = 0
 49        return self
 50
 51    def __next__(self):
 52        """Return the next present in the list."""
 53        if self._index < len(self._all_presents):
 54            result = self._all_presents[self._index]
 55            self._index += 1
 56            return result
 57        raise StopIteration
 58
 59    def _get_most_common_gift(self):
 60        """Find the most common gift."""
 61        gifts = list(self._wishes.values())
 62        gift_counts = {gift: gifts.count(gift) for gift in set(gifts)}
 63        
 64        max_count = max(gift_counts.values())
 65        most_frequent_gifts = [gift for gift, count in gift_counts.items() if count == max_count]
 66        
 67        return random.choice(most_frequent_gifts)
 68        
 69    def to_next_christmas(self):
 70        """Age up all kids and clear gifts for next Christmas."""
 71        self._wishes = OrderedDict()
 72        for kid in self._kids.values():
 73            kid.age_up()
 74            kid.set_is_good()
 75        
 76    def _handle_kid(self, id, instance):
 77        """Handle the present for a kid."""
 78        if instance.age >= 5:
 79            return
 80
 81        if not instance.is_good:
 82            instance('coal')
 83        elif id in self._wishes:
 84            instance(self._wishes[id])
 85        else:
 86            instance(self._get_most_common_gift())
 87        
 88    def xmas(self):
 89        """Distribute presents according to the rules."""
 90        if not self._wishes:
 91            self.to_next_christmas()    
 92            return
 93    
 94        for id, instance  in self._kids.items():
 95            self._handle_kid(id, instance)
 96
 97        self.to_next_christmas()   
 98              
 99class Kid(type):
100    """Metaclass that ensures every new kid is registered in Santa and has required methods."""
101
102    def __new__(cls, name, bases, attributes):
103        if '__call__' not in attributes:
104            raise NotImplementedError("О, неразумни юроде!")
105
106        new_class = super().__new__(cls, name, bases, attributes)
107
108        interface = cls.create_kid_methods()
109        new_class.__init__ = interface[0]
110        new_class.age_up = interface[1]        
111        new_class.set_is_good = interface[2]
112        return new_class
113    
114    def __init__(cls, name, bases, attributes):
115        """Wrap class methods to flag the kid is naughty if exception is thrown."""
116        for method_name, method in cls.__dict__.items():
117            if callable(method) and not method_name.startswith('_'):
118                setattr(cls, method_name, cls.wrapped_method(method))
119                
120    @staticmethod
121    def create_kid_methods():
122        """Generate __init__, age_up, set_is_good."""
123        def __init__(self, *args, **kwargs):
124            self.age = 0 
125            self.is_good = True  
126            super().__init__(*args, **kwargs)
127        
128        def age_up(self):
129            self.age += 1
130
131        def set_is_good(self, is_good=True):
132            self.is_good = is_good
133
134        return __init__, age_up, set_is_good
135
136    @staticmethod
137    def wrapped_method(method):
138        """Search for raised exception in public methods."""
139        def decoratored_method(self, *args, **kwargs):
140            try:
141                return method(self, *args, **kwargs)
142            except Exception as err:
143                self.set_is_good(False)
144                raise err
145        return decoratored_method
146    
147    def __call__(cls, *args, **kwargs):
148        """Add kid in the wishlist when a kid is called."""
149        instance = super().__call__(*args, **kwargs)
150        Santa.add_new_kid(instance)
151        return instance

..EEEEEEE.EEEEEEEEEE
======================================================================
ERROR: test_call (test.TestSanta.test_call)
Test sending message via calling.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 52, in test_call
kid1 = self.KidClass1()
^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 149, in __call__
instance = super().__call__(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 126, in __init__
super().__init__(*args, **kwargs)
^^^^^^^^^^^^^^^^
TypeError: super(type, obj): obj must be an instance or subtype of type

======================================================================
ERROR: test_call_and_mail_same_kid (test.TestSanta.test_call_and_mail_same_kid)
Test that calls and mails work for the same kid.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 68, in test_call_and_mail_same_kid
kid1 = self.KidClass1()
^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 149, in __call__
instance = super().__call__(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 126, in __init__
super().__init__(*args, **kwargs)
^^^^^^^^^^^^^^^^
TypeError: super(type, obj): obj must be an instance or subtype of type

======================================================================
ERROR: test_iterable (test.TestSanta.test_iterable)
Ensure Santa can be iterated multiple times including overwriting presents.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 124, in test_iterable
kid1 = self.KidClass1()
^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 149, in __call__
instance = super().__call__(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 126, in __init__
super().__init__(*args, **kwargs)
^^^^^^^^^^^^^^^^
TypeError: super(type, obj): obj must be an instance or subtype of type

======================================================================
ERROR: test_mail (test.TestSanta.test_mail)
Test sending message via email.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 60, in test_mail
kid1 = self.KidClass1()
^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 149, in __call__
instance = super().__call__(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 126, in __init__
super().__init__(*args, **kwargs)
^^^^^^^^^^^^^^^^
TypeError: super(type, obj): obj must be an instance or subtype of type

======================================================================
ERROR: test_present_matching (test.TestSanta.test_present_matching)
Test matching signature in the letter.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 75, in test_present_matching
kid1 = self.KidClass1()
^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 149, in __call__
instance = super().__call__(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 126, in __init__
super().__init__(*args, **kwargs)
^^^^^^^^^^^^^^^^
TypeError: super(type, obj): obj must be an instance or subtype of type

======================================================================
ERROR: test_santa_gift_order (test.TestSanta.test_santa_gift_order)
Test ordering of the Santa iterator.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 252, in test_santa_gift_order
kid1 = self.KidClass1()
^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 149, in __call__
instance = super().__call__(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 126, in __init__
super().__init__(*args, **kwargs)
^^^^^^^^^^^^^^^^
TypeError: super(type, obj): obj must be an instance or subtype of type

======================================================================
ERROR: test_signature_matching (test.TestSanta.test_signature_matching)
Test matching present in the letter / call.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 96, in test_signature_matching
kid1 = self.KidClass1()
^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 149, in __call__
instance = super().__call__(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 126, in __init__
super().__init__(*args, **kwargs)
^^^^^^^^^^^^^^^^
TypeError: super(type, obj): obj must be an instance or subtype of type

======================================================================
ERROR: test_xmass (test.TestSanta.test_xmass)
Test a simple Christmas case.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 134, in test_xmass
kid1 = self.KidClass1()
^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 149, in __call__
instance = super().__call__(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 126, in __init__
super().__init__(*args, **kwargs)
^^^^^^^^^^^^^^^^
TypeError: super(type, obj): obj must be an instance or subtype of type

======================================================================
ERROR: test_xmass_kid_with_multiple_wishes (test.TestSanta.test_xmass_kid_with_multiple_wishes)
Test a Christmas with a kid who sends multiple wishes.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 182, in test_xmass_kid_with_multiple_wishes
kid1 = self.KidClass1()
^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 149, in __call__
instance = super().__call__(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 126, in __init__
super().__init__(*args, **kwargs)
^^^^^^^^^^^^^^^^
TypeError: super(type, obj): obj must be an instance or subtype of type

======================================================================
ERROR: test_xmass_kid_without_a_wish (test.TestSanta.test_xmass_kid_without_a_wish)
Test a Christmas with a kids that hasn't sent a wish.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 167, in test_xmass_kid_without_a_wish
kid1 = self.KidClass1()
^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 149, in __call__
instance = super().__call__(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 126, in __init__
super().__init__(*args, **kwargs)
^^^^^^^^^^^^^^^^
TypeError: super(type, obj): obj must be an instance or subtype of type

======================================================================
ERROR: test_xmass_naughty (test.TestSanta.test_xmass_naughty)
Test a Christmas with naughty kids.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 217, in test_xmass_naughty
kid1 = self.KidClass1()
^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 149, in __call__
instance = super().__call__(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 126, in __init__
super().__init__(*args, **kwargs)
^^^^^^^^^^^^^^^^
TypeError: super(type, obj): obj must be an instance or subtype of type

======================================================================
ERROR: test_xmass_no_wishes (test.TestSanta.test_xmass_no_wishes)
Test a Christmas with no wishes.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 147, in test_xmass_no_wishes
kid1 = self.KidClass1()
^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 149, in __call__
instance = super().__call__(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 126, in __init__
super().__init__(*args, **kwargs)
^^^^^^^^^^^^^^^^
TypeError: super(type, obj): obj must be an instance or subtype of type

======================================================================
ERROR: test_xmass_no_wishes_but_naughty_kids (test.TestSanta.test_xmass_no_wishes_but_naughty_kids)
Test a Christmas with no wishes, but naughty kids present.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 157, in test_xmass_no_wishes_but_naughty_kids
kid1 = self.KidClass1()
^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 149, in __call__
instance = super().__call__(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 126, in __init__
super().__init__(*args, **kwargs)
^^^^^^^^^^^^^^^^
TypeError: super(type, obj): obj must be an instance or subtype of type

======================================================================
ERROR: test_xmass_private_with_error (test.TestSanta.test_xmass_private_with_error)
Test a Christmas with not-so-naughty kids.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 233, in test_xmass_private_with_error
kid1 = self.KidClass1()
^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 149, in __call__
instance = super().__call__(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 126, in __init__
super().__init__(*args, **kwargs)
^^^^^^^^^^^^^^^^
TypeError: super(type, obj): obj must be an instance or subtype of type

======================================================================
ERROR: test_xmass_public_with_no_error (test.TestSanta.test_xmass_public_with_no_error)
Test a Christmas with not-so-naughty kids.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 244, in test_xmass_public_with_no_error
kid1 = self.KidClass1()
^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 149, in __call__
instance = super().__call__(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 126, in __init__
super().__init__(*args, **kwargs)
^^^^^^^^^^^^^^^^
TypeError: super(type, obj): obj must be an instance or subtype of type

======================================================================
ERROR: test_xmass_years_5_and_over (test.TestSanta.test_xmass_years_5_and_over)
Test with passing years with kid aged 5 and over.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 205, in test_xmass_years_5_and_over
kid1 = self.KidClass1()
^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 149, in __call__
instance = super().__call__(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 126, in __init__
super().__init__(*args, **kwargs)
^^^^^^^^^^^^^^^^
TypeError: super(type, obj): obj must be an instance or subtype of type

======================================================================
ERROR: test_xmass_years_under_5 (test.TestSanta.test_xmass_years_under_5)
Test with passing years with a kid under 5 years old.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 191, in test_xmass_years_under_5
kid1 = self.KidClass1()
^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 149, in __call__
instance = super().__call__(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 126, in __init__
super().__init__(*args, **kwargs)
^^^^^^^^^^^^^^^^
TypeError: super(type, obj): obj must be an instance or subtype of type

----------------------------------------------------------------------
Ran 20 tests in 0.041s

FAILED (errors=17)

Дискусия
Илиан Запрянов
19.12.2024 18:52

💀
Виктор Бечев
19.12.2024 13:59

Аз искам да те питам нещо, без да ми е съвестно, че съм помогнал прекалено. Просто не обичам да виждам труд, който да отиде "на вятъра" заради нещо глупаво... Пусна ли примерния код?
История

f1import ref1import re
2from collections import OrderedDict2from collections import OrderedDict
3import random3import random
4from unittest.mock import patch, call4from unittest.mock import patch, call
55
6class SingletonMeta(type):6class SingletonMeta(type):
7    """A metaclass for realizing the Singleton design pattern."""7    """A metaclass for realizing the Singleton design pattern."""
8   8   
9   #attribute to save the unique instance in9   #attribute to save the unique instance in
10    _instance = None10    _instance = None
1111
12    def __call__(cls, *args, **kwargs):12    def __call__(cls, *args, **kwargs):
13        """Control the creation of an instance of a class."""13        """Control the creation of an instance of a class."""
14        if not cls._instance:14        if not cls._instance:
15            cls._instance = super().__call__(*args, **kwargs)15            cls._instance = super().__call__(*args, **kwargs)
16        return cls._instance16        return cls._instance
1717
18class Santa(metaclass=SingletonMeta):18class Santa(metaclass=SingletonMeta):
19    """A class representing Santa."""19    """A class representing Santa."""
2020
21    _kids = {}21    _kids = {}
22    _wishes = OrderedDict()22    _wishes = OrderedDict()
23    23    
24    def __call__(self, kid, phone_call):24    def __call__(self, kid, phone_call):
25        """Handle a wish request made by a kid made by a phone call."""25        """Handle a wish request made by a kid made by a phone call."""
26        wish = self.get_wish_of(phone_call)26        wish = self.get_wish_of(phone_call)
27        self._wishes[id(kid)] = wish27        self._wishes[id(kid)] = wish
28            28            
29    def __matmul__(self, letter):29    def __matmul__(self, letter):
30        """Handle a wish request made by a Kid sent as a letter."""    30        """Handle a wish request made by a Kid sent as a letter."""    
31        wish = self.get_wish_of(letter)31        wish = self.get_wish_of(letter)
32        signature = int(re.search(r'(\b\d+\b)', letter).group(0))32        signature = int(re.search(r'(\b\d+\b)', letter).group(0))
33        self._wishes[signature] = wish33        self._wishes[signature] = wish
3434
35    def get_wish_of(self, source):35    def get_wish_of(self, source):
36        """Match the wish in source."""    36        """Match the wish in source."""    
37        wish_match = re.search(r"(['\"])([\w ]+)\1", source, re.MULTILINE | re.DOTALL)37        wish_match = re.search(r"(['\"])([\w ]+)\1", source, re.MULTILINE | re.DOTALL)
38        return wish_match.group(1)38        return wish_match.group(1)
39        39        
40    @classmethod40    @classmethod
41    def add_new_kid(cls, kid):41    def add_new_kid(cls, kid):
42        """Save kids in order to be able to call them."""    42        """Save kids in order to be able to call them."""    
43        cls._kids[id(kid)] = kid43        cls._kids[id(kid)] = kid
44    44    
45    def __iter__(self):45    def __iter__(self):
46        """Return an iterator for Santa's presents."""46        """Return an iterator for Santa's presents."""
47        self._all_presents = list(self._wishes.values())47        self._all_presents = list(self._wishes.values())
48        self._index = 048        self._index = 0
49        return self49        return self
5050
51    def __next__(self):51    def __next__(self):
52        """Return the next present in the list."""52        """Return the next present in the list."""
53        if self._index < len(self._all_presents):53        if self._index < len(self._all_presents):
54            result = self._all_presents[self._index]54            result = self._all_presents[self._index]
55            self._index += 155            self._index += 1
56            return result56            return result
57        raise StopIteration57        raise StopIteration
5858
59    def _get_most_common_gift(self):59    def _get_most_common_gift(self):
60        """Find the most common gift."""60        """Find the most common gift."""
61        gifts = list(self._wishes.values())61        gifts = list(self._wishes.values())
62        gift_counts = {gift: gifts.count(gift) for gift in set(gifts)}62        gift_counts = {gift: gifts.count(gift) for gift in set(gifts)}
63        63        
64        max_count = max(gift_counts.values())64        max_count = max(gift_counts.values())
65        most_frequent_gifts = [gift for gift, count in gift_counts.items() if count == max_count]65        most_frequent_gifts = [gift for gift, count in gift_counts.items() if count == max_count]
66        66        
67        return random.choice(most_frequent_gifts)67        return random.choice(most_frequent_gifts)
68        68        
69    def to_next_christmas(self):69    def to_next_christmas(self):
70        """Age up all kids and clear gifts for next Christmas."""70        """Age up all kids and clear gifts for next Christmas."""
71        self._wishes = OrderedDict()71        self._wishes = OrderedDict()
72        for kid in self._kids.values():72        for kid in self._kids.values():
73            kid.age_up()73            kid.age_up()
74            kid.set_is_good()74            kid.set_is_good()
75        75        
76    def _handle_kid(self, id, instance):76    def _handle_kid(self, id, instance):
77        """Handle the present for a kid."""77        """Handle the present for a kid."""
78        if instance.age >= 5:78        if instance.age >= 5:
79            return79            return
8080
81        if not instance.is_good:81        if not instance.is_good:
82            instance('coal')82            instance('coal')
83        elif id in self._wishes:83        elif id in self._wishes:
84            instance(self._wishes[id])84            instance(self._wishes[id])
85        else:85        else:
86            instance(self._get_most_common_gift())86            instance(self._get_most_common_gift())
87        87        
88    def xmas(self):88    def xmas(self):
89        """Distribute presents according to the rules."""89        """Distribute presents according to the rules."""
90        if not self._wishes:90        if not self._wishes:
91            self.to_next_christmas()    91            self.to_next_christmas()    
92            return92            return
93    93    
94        for id, instance  in self._kids.items():94        for id, instance  in self._kids.items():
95            self._handle_kid(id, instance)95            self._handle_kid(id, instance)
9696
97        self.to_next_christmas()   97        self.to_next_christmas()   
98              98              
99class Kid(type):99class Kid(type):
100    """Metaclass that ensures every new kid is registered in Santa and has required methods."""100    """Metaclass that ensures every new kid is registered in Santa and has required methods."""
101101
102    def __new__(cls, name, bases, attributes):102    def __new__(cls, name, bases, attributes):
103        if '__call__' not in attributes:103        if '__call__' not in attributes:
104            raise NotImplementedError("О, неразумни юроде!")104            raise NotImplementedError("О, неразумни юроде!")
105105
106        new_class = super().__new__(cls, name, bases, attributes)106        new_class = super().__new__(cls, name, bases, attributes)
107107
108        interface = cls.create_kid_methods()108        interface = cls.create_kid_methods()
109        new_class.__init__ = interface[0]109        new_class.__init__ = interface[0]
110        new_class.age_up = interface[1]        110        new_class.age_up = interface[1]        
111        new_class.set_is_good = interface[2]111        new_class.set_is_good = interface[2]
112        return new_class112        return new_class
113    113    
114    def __init__(cls, name, bases, attributes):114    def __init__(cls, name, bases, attributes):
t115        """Validate is kid good when initialized."""t115        """Wrap class methods to flag the kid is naughty if exception is thrown."""
116        for method_name, method in cls.__dict__.items():116        for method_name, method in cls.__dict__.items():
117            if callable(method) and not method_name.startswith('_'):117            if callable(method) and not method_name.startswith('_'):
118                setattr(cls, method_name, cls.wrapped_method(method))118                setattr(cls, method_name, cls.wrapped_method(method))
119                119                
120    @staticmethod120    @staticmethod
121    def create_kid_methods():121    def create_kid_methods():
122        """Generate __init__, age_up, set_is_good."""122        """Generate __init__, age_up, set_is_good."""
123        def __init__(self, *args, **kwargs):123        def __init__(self, *args, **kwargs):
124            self.age = 0 124            self.age = 0 
125            self.is_good = True  125            self.is_good = True  
126            super().__init__(*args, **kwargs)126            super().__init__(*args, **kwargs)
127        127        
128        def age_up(self):128        def age_up(self):
129            self.age += 1129            self.age += 1
130130
131        def set_is_good(self, is_good=True):131        def set_is_good(self, is_good=True):
132            self.is_good = is_good132            self.is_good = is_good
133133
134        return __init__, age_up, set_is_good134        return __init__, age_up, set_is_good
135135
136    @staticmethod136    @staticmethod
137    def wrapped_method(method):137    def wrapped_method(method):
138        """Search for raised exception in public methods."""138        """Search for raised exception in public methods."""
139        def decoratored_method(self, *args, **kwargs):139        def decoratored_method(self, *args, **kwargs):
140            try:140            try:
141                return method(self, *args, **kwargs)141                return method(self, *args, **kwargs)
142            except Exception as err:142            except Exception as err:
143                self.set_is_good(False)143                self.set_is_good(False)
144                raise err144                raise err
145        return decoratored_method145        return decoratored_method
146    146    
147    def __call__(cls, *args, **kwargs):147    def __call__(cls, *args, **kwargs):
148        """Add kid in the wishlist when a kid is called."""148        """Add kid in the wishlist when a kid is called."""
149        instance = super().__call__(*args, **kwargs)149        instance = super().__call__(*args, **kwargs)
150        Santa.add_new_kid(instance)150        Santa.add_new_kid(instance)
151        return instance151        return instance
Legends
Colors
 Added 
Changed
Deleted
Links
(f)irst change
(n)ext change
(t)op

t1import ret1import re
2from collections import OrderedDict2from collections import OrderedDict
3import random3import random
4from unittest.mock import patch, call4from unittest.mock import patch, call
55
6class SingletonMeta(type):6class SingletonMeta(type):
7    """A metaclass for realizing the Singleton design pattern."""7    """A metaclass for realizing the Singleton design pattern."""
8   8   
9   #attribute to save the unique instance in9   #attribute to save the unique instance in
10    _instance = None10    _instance = None
1111
12    def __call__(cls, *args, **kwargs):12    def __call__(cls, *args, **kwargs):
13        """Control the creation of an instance of a class."""13        """Control the creation of an instance of a class."""
14        if not cls._instance:14        if not cls._instance:
15            cls._instance = super().__call__(*args, **kwargs)15            cls._instance = super().__call__(*args, **kwargs)
16        return cls._instance16        return cls._instance
1717
18class Santa(metaclass=SingletonMeta):18class Santa(metaclass=SingletonMeta):
19    """A class representing Santa."""19    """A class representing Santa."""
2020
21    _kids = {}21    _kids = {}
22    _wishes = OrderedDict()22    _wishes = OrderedDict()
23    23    
24    def __call__(self, kid, phone_call):24    def __call__(self, kid, phone_call):
25        """Handle a wish request made by a kid made by a phone call."""25        """Handle a wish request made by a kid made by a phone call."""
26        wish = self.get_wish_of(phone_call)26        wish = self.get_wish_of(phone_call)
27        self._wishes[id(kid)] = wish27        self._wishes[id(kid)] = wish
28            28            
29    def __matmul__(self, letter):29    def __matmul__(self, letter):
30        """Handle a wish request made by a Kid sent as a letter."""    30        """Handle a wish request made by a Kid sent as a letter."""    
31        wish = self.get_wish_of(letter)31        wish = self.get_wish_of(letter)
32        signature = int(re.search(r'(\b\d+\b)', letter).group(0))32        signature = int(re.search(r'(\b\d+\b)', letter).group(0))
33        self._wishes[signature] = wish33        self._wishes[signature] = wish
3434
35    def get_wish_of(self, source):35    def get_wish_of(self, source):
36        """Match the wish in source."""    36        """Match the wish in source."""    
37        wish_match = re.search(r"(['\"])([\w ]+)\1", source, re.MULTILINE | re.DOTALL)37        wish_match = re.search(r"(['\"])([\w ]+)\1", source, re.MULTILINE | re.DOTALL)
38        return wish_match.group(1)38        return wish_match.group(1)
39        39        
40    @classmethod40    @classmethod
41    def add_new_kid(cls, kid):41    def add_new_kid(cls, kid):
42        """Save kids in order to be able to call them."""    42        """Save kids in order to be able to call them."""    
43        cls._kids[id(kid)] = kid43        cls._kids[id(kid)] = kid
44    44    
45    def __iter__(self):45    def __iter__(self):
46        """Return an iterator for Santa's presents."""46        """Return an iterator for Santa's presents."""
47        self._all_presents = list(self._wishes.values())47        self._all_presents = list(self._wishes.values())
48        self._index = 048        self._index = 0
49        return self49        return self
5050
51    def __next__(self):51    def __next__(self):
52        """Return the next present in the list."""52        """Return the next present in the list."""
53        if self._index < len(self._all_presents):53        if self._index < len(self._all_presents):
54            result = self._all_presents[self._index]54            result = self._all_presents[self._index]
55            self._index += 155            self._index += 1
56            return result56            return result
57        raise StopIteration57        raise StopIteration
5858
59    def _get_most_common_gift(self):59    def _get_most_common_gift(self):
60        """Find the most common gift."""60        """Find the most common gift."""
61        gifts = list(self._wishes.values())61        gifts = list(self._wishes.values())
62        gift_counts = {gift: gifts.count(gift) for gift in set(gifts)}62        gift_counts = {gift: gifts.count(gift) for gift in set(gifts)}
63        63        
64        max_count = max(gift_counts.values())64        max_count = max(gift_counts.values())
65        most_frequent_gifts = [gift for gift, count in gift_counts.items() if count == max_count]65        most_frequent_gifts = [gift for gift, count in gift_counts.items() if count == max_count]
66        66        
67        return random.choice(most_frequent_gifts)67        return random.choice(most_frequent_gifts)
68        68        
69    def to_next_christmas(self):69    def to_next_christmas(self):
70        """Age up all kids and clear gifts for next Christmas."""70        """Age up all kids and clear gifts for next Christmas."""
71        self._wishes = OrderedDict()71        self._wishes = OrderedDict()
72        for kid in self._kids.values():72        for kid in self._kids.values():
73            kid.age_up()73            kid.age_up()
74            kid.set_is_good()74            kid.set_is_good()
75        75        
76    def _handle_kid(self, id, instance):76    def _handle_kid(self, id, instance):
77        """Handle the present for a kid."""77        """Handle the present for a kid."""
78        if instance.age >= 5:78        if instance.age >= 5:
79            return79            return
8080
81        if not instance.is_good:81        if not instance.is_good:
82            instance('coal')82            instance('coal')
83        elif id in self._wishes:83        elif id in self._wishes:
84            instance(self._wishes[id])84            instance(self._wishes[id])
85        else:85        else:
86            instance(self._get_most_common_gift())86            instance(self._get_most_common_gift())
87        87        
88    def xmas(self):88    def xmas(self):
89        """Distribute presents according to the rules."""89        """Distribute presents according to the rules."""
90        if not self._wishes:90        if not self._wishes:
91            self.to_next_christmas()    91            self.to_next_christmas()    
92            return92            return
93    93    
94        for id, instance  in self._kids.items():94        for id, instance  in self._kids.items():
95            self._handle_kid(id, instance)95            self._handle_kid(id, instance)
9696
97        self.to_next_christmas()   97        self.to_next_christmas()   
98              98              
99class Kid(type):99class Kid(type):
100    """Metaclass that ensures every new kid is registered in Santa and has required methods."""100    """Metaclass that ensures every new kid is registered in Santa and has required methods."""
101101
102    def __new__(cls, name, bases, attributes):102    def __new__(cls, name, bases, attributes):
103        if '__call__' not in attributes:103        if '__call__' not in attributes:
104            raise NotImplementedError("О, неразумни юроде!")104            raise NotImplementedError("О, неразумни юроде!")
105105
106        new_class = super().__new__(cls, name, bases, attributes)106        new_class = super().__new__(cls, name, bases, attributes)
107107
108        interface = cls.create_kid_methods()108        interface = cls.create_kid_methods()
109        new_class.__init__ = interface[0]109        new_class.__init__ = interface[0]
110        new_class.age_up = interface[1]        110        new_class.age_up = interface[1]        
111        new_class.set_is_good = interface[2]111        new_class.set_is_good = interface[2]
112        return new_class112        return new_class
113    113    
114    def __init__(cls, name, bases, attributes):114    def __init__(cls, name, bases, attributes):
115        """Validate is kid good when initialized."""115        """Validate is kid good when initialized."""
116        for method_name, method in cls.__dict__.items():116        for method_name, method in cls.__dict__.items():
117            if callable(method) and not method_name.startswith('_'):117            if callable(method) and not method_name.startswith('_'):
118                setattr(cls, method_name, cls.wrapped_method(method))118                setattr(cls, method_name, cls.wrapped_method(method))
119                119                
120    @staticmethod120    @staticmethod
121    def create_kid_methods():121    def create_kid_methods():
122        """Generate __init__, age_up, set_is_good."""122        """Generate __init__, age_up, set_is_good."""
123        def __init__(self, *args, **kwargs):123        def __init__(self, *args, **kwargs):
124            self.age = 0 124            self.age = 0 
125            self.is_good = True  125            self.is_good = True  
126            super().__init__(*args, **kwargs)126            super().__init__(*args, **kwargs)
127        127        
128        def age_up(self):128        def age_up(self):
129            self.age += 1129            self.age += 1
130130
131        def set_is_good(self, is_good=True):131        def set_is_good(self, is_good=True):
132            self.is_good = is_good132            self.is_good = is_good
133133
134        return __init__, age_up, set_is_good134        return __init__, age_up, set_is_good
135135
136    @staticmethod136    @staticmethod
137    def wrapped_method(method):137    def wrapped_method(method):
138        """Search for raised exception in public methods."""138        """Search for raised exception in public methods."""
139        def decoratored_method(self, *args, **kwargs):139        def decoratored_method(self, *args, **kwargs):
140            try:140            try:
141                return method(self, *args, **kwargs)141                return method(self, *args, **kwargs)
142            except Exception as err:142            except Exception as err:
143                self.set_is_good(False)143                self.set_is_good(False)
144                raise err144                raise err
145        return decoratored_method145        return decoratored_method
146    146    
147    def __call__(cls, *args, **kwargs):147    def __call__(cls, *args, **kwargs):
148        """Add kid in the wishlist when a kid is called."""148        """Add kid in the wishlist when a kid is called."""
149        instance = super().__call__(*args, **kwargs)149        instance = super().__call__(*args, **kwargs)
150        Santa.add_new_kid(instance)150        Santa.add_new_kid(instance)
151        return instance151        return instance
Legends
Colors
 Added 
Changed
Deleted
Links
(f)irst change
(n)ext change
(t)op

f1import ref1import re
2from collections import OrderedDict2from collections import OrderedDict
3import random3import random
4from unittest.mock import patch, call4from unittest.mock import patch, call
55
6class SingletonMeta(type):6class SingletonMeta(type):
7    """A metaclass for realizing the Singleton design pattern."""7    """A metaclass for realizing the Singleton design pattern."""
8   8   
9   #attribute to save the unique instance in9   #attribute to save the unique instance in
10    _instance = None10    _instance = None
1111
12    def __call__(cls, *args, **kwargs):12    def __call__(cls, *args, **kwargs):
13        """Control the creation of an instance of a class."""13        """Control the creation of an instance of a class."""
14        if not cls._instance:14        if not cls._instance:
15            cls._instance = super().__call__(*args, **kwargs)15            cls._instance = super().__call__(*args, **kwargs)
16        return cls._instance16        return cls._instance
1717
18class Santa(metaclass=SingletonMeta):18class Santa(metaclass=SingletonMeta):
19    """A class representing Santa."""19    """A class representing Santa."""
2020
21    _kids = {}21    _kids = {}
22    _wishes = OrderedDict()22    _wishes = OrderedDict()
23    23    
24    def __call__(self, kid, phone_call):24    def __call__(self, kid, phone_call):
25        """Handle a wish request made by a kid made by a phone call."""25        """Handle a wish request made by a kid made by a phone call."""
26        wish = self.get_wish_of(phone_call)26        wish = self.get_wish_of(phone_call)
27        self._wishes[id(kid)] = wish27        self._wishes[id(kid)] = wish
28            28            
29    def __matmul__(self, letter):29    def __matmul__(self, letter):
30        """Handle a wish request made by a Kid sent as a letter."""    30        """Handle a wish request made by a Kid sent as a letter."""    
31        wish = self.get_wish_of(letter)31        wish = self.get_wish_of(letter)
32        signature = int(re.search(r'(\b\d+\b)', letter).group(0))32        signature = int(re.search(r'(\b\d+\b)', letter).group(0))
33        self._wishes[signature] = wish33        self._wishes[signature] = wish
3434
35    def get_wish_of(self, source):35    def get_wish_of(self, source):
36        """Match the wish in source."""    36        """Match the wish in source."""    
n37        wish_match = re.search(r"['\"]([A-Za-z0-9 ]+)['\"]", source, re.MULTILINE | re.DOTALL)n37        wish_match = re.search(r"(['\"])([\w ]+)\1", source, re.MULTILINE | re.DOTALL)
38        return wish_match.group(1)38        return wish_match.group(1)
39        39        
40    @classmethod40    @classmethod
41    def add_new_kid(cls, kid):41    def add_new_kid(cls, kid):
42        """Save kids in order to be able to call them."""    42        """Save kids in order to be able to call them."""    
43        cls._kids[id(kid)] = kid43        cls._kids[id(kid)] = kid
44    44    
45    def __iter__(self):45    def __iter__(self):
46        """Return an iterator for Santa's presents."""46        """Return an iterator for Santa's presents."""
47        self._all_presents = list(self._wishes.values())47        self._all_presents = list(self._wishes.values())
48        self._index = 048        self._index = 0
49        return self49        return self
5050
51    def __next__(self):51    def __next__(self):
52        """Return the next present in the list."""52        """Return the next present in the list."""
53        if self._index < len(self._all_presents):53        if self._index < len(self._all_presents):
54            result = self._all_presents[self._index]54            result = self._all_presents[self._index]
55            self._index += 155            self._index += 1
56            return result56            return result
57        raise StopIteration57        raise StopIteration
5858
59    def _get_most_common_gift(self):59    def _get_most_common_gift(self):
60        """Find the most common gift."""60        """Find the most common gift."""
61        gifts = list(self._wishes.values())61        gifts = list(self._wishes.values())
62        gift_counts = {gift: gifts.count(gift) for gift in set(gifts)}62        gift_counts = {gift: gifts.count(gift) for gift in set(gifts)}
63        63        
64        max_count = max(gift_counts.values())64        max_count = max(gift_counts.values())
65        most_frequent_gifts = [gift for gift, count in gift_counts.items() if count == max_count]65        most_frequent_gifts = [gift for gift, count in gift_counts.items() if count == max_count]
66        66        
67        return random.choice(most_frequent_gifts)67        return random.choice(most_frequent_gifts)
68        68        
69    def to_next_christmas(self):69    def to_next_christmas(self):
70        """Age up all kids and clear gifts for next Christmas."""70        """Age up all kids and clear gifts for next Christmas."""
71        self._wishes = OrderedDict()71        self._wishes = OrderedDict()
72        for kid in self._kids.values():72        for kid in self._kids.values():
73            kid.age_up()73            kid.age_up()
74            kid.set_is_good()74            kid.set_is_good()
75        75        
76    def _handle_kid(self, id, instance):76    def _handle_kid(self, id, instance):
77        """Handle the present for a kid."""77        """Handle the present for a kid."""
78        if instance.age >= 5:78        if instance.age >= 5:
79            return79            return
8080
81        if not instance.is_good:81        if not instance.is_good:
82            instance('coal')82            instance('coal')
83        elif id in self._wishes:83        elif id in self._wishes:
84            instance(self._wishes[id])84            instance(self._wishes[id])
85        else:85        else:
86            instance(self._get_most_common_gift())86            instance(self._get_most_common_gift())
87        87        
88    def xmas(self):88    def xmas(self):
89        """Distribute presents according to the rules."""89        """Distribute presents according to the rules."""
90        if not self._wishes:90        if not self._wishes:
91            self.to_next_christmas()    91            self.to_next_christmas()    
92            return92            return
93    93    
94        for id, instance  in self._kids.items():94        for id, instance  in self._kids.items():
95            self._handle_kid(id, instance)95            self._handle_kid(id, instance)
9696
97        self.to_next_christmas()   97        self.to_next_christmas()   
98              98              
99class Kid(type):99class Kid(type):
100    """Metaclass that ensures every new kid is registered in Santa and has required methods."""100    """Metaclass that ensures every new kid is registered in Santa and has required methods."""
101101
102    def __new__(cls, name, bases, attributes):102    def __new__(cls, name, bases, attributes):
103        if '__call__' not in attributes:103        if '__call__' not in attributes:
104            raise NotImplementedError("О, неразумни юроде!")104            raise NotImplementedError("О, неразумни юроде!")
105105
106        new_class = super().__new__(cls, name, bases, attributes)106        new_class = super().__new__(cls, name, bases, attributes)
107107
108        interface = cls.create_kid_methods()108        interface = cls.create_kid_methods()
109        new_class.__init__ = interface[0]109        new_class.__init__ = interface[0]
110        new_class.age_up = interface[1]        110        new_class.age_up = interface[1]        
111        new_class.set_is_good = interface[2]111        new_class.set_is_good = interface[2]
112        return new_class112        return new_class
113    113    
114    def __init__(cls, name, bases, attributes):114    def __init__(cls, name, bases, attributes):
115        """Validate is kid good when initialized."""115        """Validate is kid good when initialized."""
116        for method_name, method in cls.__dict__.items():116        for method_name, method in cls.__dict__.items():
117            if callable(method) and not method_name.startswith('_'):117            if callable(method) and not method_name.startswith('_'):
118                setattr(cls, method_name, cls.wrapped_method(method))118                setattr(cls, method_name, cls.wrapped_method(method))
119                119                
120    @staticmethod120    @staticmethod
121    def create_kid_methods():121    def create_kid_methods():
122        """Generate __init__, age_up, set_is_good."""122        """Generate __init__, age_up, set_is_good."""
123        def __init__(self, *args, **kwargs):123        def __init__(self, *args, **kwargs):
124            self.age = 0 124            self.age = 0 
125            self.is_good = True  125            self.is_good = True  
t126            super(self.__class__, self).__init__(*args, **kwargs)t126            super().__init__(*args, **kwargs)
127        127        
128        def age_up(self):128        def age_up(self):
129            self.age += 1129            self.age += 1
130130
131        def set_is_good(self, is_good=True):131        def set_is_good(self, is_good=True):
132            self.is_good = is_good132            self.is_good = is_good
133133
134        return __init__, age_up, set_is_good134        return __init__, age_up, set_is_good
135135
136    @staticmethod136    @staticmethod
137    def wrapped_method(method):137    def wrapped_method(method):
138        """Search for raised exception in public methods."""138        """Search for raised exception in public methods."""
139        def decoratored_method(self, *args, **kwargs):139        def decoratored_method(self, *args, **kwargs):
140            try:140            try:
141                return method(self, *args, **kwargs)141                return method(self, *args, **kwargs)
142            except Exception as err:142            except Exception as err:
143                self.set_is_good(False)143                self.set_is_good(False)
144                raise err144                raise err
145        return decoratored_method145        return decoratored_method
146    146    
147    def __call__(cls, *args, **kwargs):147    def __call__(cls, *args, **kwargs):
148        """Add kid in the wishlist when a kid is called."""148        """Add kid in the wishlist when a kid is called."""
149        instance = super().__call__(*args, **kwargs)149        instance = super().__call__(*args, **kwargs)
150        Santa.add_new_kid(instance)150        Santa.add_new_kid(instance)
151        return instance151        return instance
Legends
Colors
 Added 
Changed
Deleted
Links
(f)irst change
(n)ext change
(t)op