1import importlib
2import inspect
3import itertools
4import re
5
6class BridgeKeeper:
7 def __init__(self, module: str):
8 self.__module = importlib.import_module(module)
9
10 def __enter__(self):
11 self.__allowed_atributes = []
12 for attr in dir(self.__module):
13 if self.is_allowed(attr):
14 self.__allowed_atributes.append(attr)
15 return self
16
17 def is_allowed(self, attribute: str) -> bool:
18 obj = getattr(self.__module, attribute)
19 return self.what_is_your_name(obj) and self.what_is_your_request(obj) and self.what_is(obj)
20
21
22 def what_is_your_name(self, obj) -> bool:
23 try:
24 return bool(re.search(r"^[A-Z]", obj.__name__))
25 except Exception:
26 return False
27
28 def what_is_your_request(self, obj) -> bool:
29 if not callable(obj):
30 return False
31
32 doc = inspect.getdoc(obj) or ""
33
34 block = re.search(
35 r"(?ms)^Parameters\s*\n[\-]+\s*\n(.*?)(?:\n\s*\n|\Z)",
36 doc,
37 )
38
39 params = [] if not block else re.findall(r"^\s*(\w+)\s*:\s*(.+?)\s*$", block.group(1), re.MULTILINE)
40
41 try:
42 real_names = list(inspect.signature(obj).parameters)
43 doc_names = [name for name, _ in params]
44
45 if real_names != doc_names:
46 return False
47
48 args_options = []
49
50 for _, type_name in params:
51 value = self.value_from_type(type_name)
52
53 if "|" in type_name:
54 args_options.append(value)
55 else:
56 args_options.append([value])
57
58 for args in itertools.product(*args_options):
59 obj(*args)
60
61 return True
62
63 except Exception:
64 return False
65
66 def value_from_type(self, type_name: str):
67 type_name = type_name.strip()
68
69 base_values = {
70 "int": 1,
71 "float": 1.0,
72 "str": "x",
73 "bool": True,
74 "bytes": b"x",
75 "complex": 1 + 0j,
76 }
77
78 collections = {
79 "list": lambda x: [x],
80 "set": lambda x: {x},
81 "tuple": lambda x: (x,),
82 }
83
84 union_parts = re.split(rf"\s*{re.escape("|")}\s*(?![^\[]*\])", type_name)
85
86 if len(union_parts) > 1:
87 return self.value_from_type(union_parts[0])
88
89 if type_name in base_values:
90 return base_values[type_name]
91
92 match = re.match(r"^(list|set|tuple)\[(.+)\]$", type_name)
93 if match:
94 collection_name, inner_type = match.groups()
95 return collections[collection_name](self.value_from_type(inner_type))
96
97 match = re.match(r"^dict\[(.+)\]$", type_name)
98 if match:
99 key_type, value_type = re.split(rf"\s*{re.escape(",")}\s*(?![^\[]*\])", match.group(1))
100 return {self.value_from_type(key_type): self.value_from_type(value_type)}
101
102 return object()
103
104 def what_is(self, obj) -> bool:
105 for attr in dir(obj):
106 if self.is_valid_answer(attr):
107 return True
108 return False
109
110 def is_valid_answer(self, attr: str) -> bool:
111 if attr.startswith("__") and attr.endswith("__") or re.search(r"[aeiouAEIOU]{4,}", attr):
112 return False
113 latin_letters = re.findall(r"[a-zA-Z]", attr)
114 return bool(latin_letters) and latin_letters[-1].isupper()
115
116 def __getattr__(self, name):
117 if name in self.__allowed_atributes:
118 return getattr(self.__module, name)
119 raise AttributeError(name)
120
121 def __exit__(self, exc_type, exc_val, exc_tb):
122 return False
...E...E.................
======================================================================
ERROR: test_allows_multi_argument_union_bonus_case (test.TestBridgeKeeper.test_allows_multi_argument_union_bonus_case)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 95, in test_allows_multi_argument_union_bonus_case
self.assertEqual(filtered.triple_union_pair(3, [1, 2]), 6)
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 119, in __getattr__
raise AttributeError(name)
AttributeError: triple_union_pair
======================================================================
ERROR: test_allows_union_typed_parameter (test.TestBridgeKeeper.test_allows_union_typed_parameter)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 17, in test_allows_union_typed_parameter
self.assertEqual(filtered.sum_group([1, 2, 3]), 6)
^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 119, in __getattr__
raise AttributeError(name)
AttributeError: sum_group
----------------------------------------------------------------------
Ran 25 tests in 0.028s
FAILED (errors=2)
Виктор Бечев
01.05.2026 15:17Супер, добра употреба на регулярните изрази, освен дребните неща, които посочих.
|
01.05.2026 15:14
01.05.2026 15:16