1import re
2import ctypes
3"""Взимане на обект от подадено id"""
4def get_object_by_id(object_id):
5 return ctypes.cast(object_id, ctypes.py_object).value
6
7"""Singleton базов клас"""
8class Singleton(type):
9 _instance = None
10
11 def __call__(cls, *args, **kwargs):
12 if cls._instance is None:
13 cls._instance = super(Singleton, cls).__call__(*args, **kwargs)
14 return cls._instance
15
16
17"""Metaclass Kid, който ще всяко дете наследява"""
18class Kid(type):
19 def __new__(cls, name, base, dct):
20 dct["is_naughty"] = False
21 if not hasattr(cls, "__call__"):
22 raise NotImplementedError("Not implemented __call__ method")
23 for method in dct:
24 if hasattr(dct[method], '__call__'):
25 dct[method] = cls.catch_exception(dct[method])
26 return super(). __new__(cls, name, base, dct)
27
28
29 def catch_exception(func):
30 def wrapper(self, *args, **kwargs):
31 try:
32 return func(self, *args, **kwargs)
33 except Exception as e:
34 self.is_naughty = True
35 return None
36 return wrapper
37
38"""Клас Дядо Коледа, наследен от Singleton"""
39class Santa(metaclass = Singleton):
40 _initialized = False
41 _kids_ids = set()
42 _gifts = []
43 def __init__(self):
44 if not self._initialized:
45 self._kids_whishes = {}
46 self._kids_ages = {}
47 self._initialized = True
48
49 """Обработва обажданията до Дядо Коледа"""
50 def __call__(self, kid, letter):
51 kid_id = id(kid)
52 kid_wish = Santa.wish_matcher(letter)
53 if kid_id in self._kids_ids and self._kids_whishes[kid_id] is not None:
54 prev_present = self._kids_whishes[kid_id]
55 self._gifts.remove(prev_present)
56 self._kids_whishes[kid_id] = kid_wish
57 self._gifts.append(kid_wish)
58 if kid_id not in self._kids_ids:
59 self._kids_ids.add(kid_id)
60 self._kids_ages[kid_id] = 0
61
62 """ Обработва писмата до Дядо Коледа; Предефиниране на оператор @ """
63 def __matmul__(self, letter):
64 kid_id = Santa.id_matcher(letter)
65 kid_wish = Santa.wish_matcher(letter)
66 if kid_id in self._kids_ids and self._kids_whishes[kid_id] is not None:
67 prev_present = self._kids_whishes[kid_id]
68 self._gifts.remove(prev_present)
69 self._kids_whishes[kid_id] = kid_wish
70 self._gifts.append(kid_wish)
71 if kid_id not in self._kids_ids:
72 self._kids_ids.add(kid_id)
73 self._kids_ages[kid_id] = 0
74
75 """Раздаване на подаръците за Коледа"""
76 def xmas(self):
77 if self._gifts:
78 most_frequent_gift = Santa.most_frequent_present(self._gifts)
79 for curr_kid_id, curr_gift in self._kids_whishes.items():
80 if self._kids_ages[curr_kid_id] < 5:
81 if curr_gift is None:
82 curr_kid_obj = get_object_by_id(curr_kid_id)
83 curr_kid_obj(most_frequent_gift)
84 elif get_object_by_id(curr_kid_id).is_naughty:
85 curr_kid_obj = get_object_by_id(curr_kid_id)
86 curr_kid_obj('coal')
87 self._kids_whishes[curr_kid_id] = None
88 else:
89 curr_kid_obj = get_object_by_id(curr_kid_id)
90 curr_kid_obj(curr_gift)
91 self._kids_whishes[curr_kid_id] = None
92
93 self._kids_ages[curr_kid_id] +=1
94 self._gifts.clear()
95
96
97 def __iter__(self):
98 return iter(self._gifts)
99
100 """Извличане на най-често срещания елемент в списък """
101 @classmethod
102 def most_frequent_present(cls, my_list):
103 counter = 0
104 present = my_list[0]
105 for curr_present in my_list:
106 curr_frequency = my_list.count(curr_present)
107 if curr_frequency > counter:
108 counter = curr_frequency
109 present = curr_present
110 return present
111
112 """Помощни фунцкии за обработка на id и желание от обаждане или писмо"""
113 @classmethod
114 def id_matcher(cls, letter):
115 id = re.search(r'^\s*(\d+)\s*$', letter, re.MULTILINE)
116 return int(id.group(1))
117
118 @classmethod
119 def wish_matcher(cls, letter):
120 wish = re.search(r'[\'"]([A-Za-z0-9 ]+)[\'"]', letter, re.MULTILINE)
121 return wish.group(1)
122
.F.....F....FF..F.F.
======================================================================
FAIL: test_class_from_kid_without_call_dunder (test.TestKid.test_class_from_kid_without_call_dunder)
Test creating new class from Kid.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 18, in test_class_from_kid_without_call_dunder
with self.assertRaises(NotImplementedError):
AssertionError: NotImplementedError not raised
======================================================================
FAIL: 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 260, in test_santa_gift_order
self.assertEqual(list(self.santa), ["toy2v2", "toy3", "toy1"])
AssertionError: Lists differ: ['toy3', 'toy1', 'toy2v2'] != ['toy2v2', 'toy3', 'toy1']
First differing element 0:
'toy3'
'toy2v2'
- ['toy3', 'toy1', 'toy2v2']
+ ['toy2v2', 'toy3', 'toy1']
======================================================================
FAIL: 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 178, in test_xmass_kid_without_a_wish
self.assertEqual(kid4.SECRET_PRESENT, 'toy1')
AssertionError: None != 'toy1'
======================================================================
FAIL: test_xmass_naughty (test.TestSanta.test_xmass_naughty)
Test a Christmas with naughty kids.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 222, in test_xmass_naughty
with self.assertRaises(ZeroDivisionError):
AssertionError: ZeroDivisionError not raised
======================================================================
FAIL: 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 240, in test_xmass_private_with_error
self.assertEqual(kid1.SECRET_PRESENT, 'sirenie')
AssertionError: 'coal' != 'sirenie'
- coal
+ sirenie
======================================================================
FAIL: 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 213, in test_xmass_years_5_and_over
self.assertEqual(kid1.SECRET_PRESENT, None)
AssertionError: 'toy' != None
----------------------------------------------------------------------
Ran 20 tests in 0.034s
FAILED (failures=6)
19.12.2024 13:31
19.12.2024 13:32
19.12.2024 13:32
19.12.2024 13:34
19.12.2024 13:35
19.12.2024 13:35
19.12.2024 13:37
19.12.2024 13:38
19.12.2024 13:41