1import re
2import inspect
3from itertools import product
4
5
6SAMPLE_VALUES_BY_TYPE = {
7 "int": 1,
8 "float": 1.0,
9 "str": "а",
10 "bool": True,
11 "bytes": b"a",
12}
13
14class BridgeKeeper:
15 def __init__(self, module_name):
16 self.module_name = module_name
17
18 def __enter__(self):
19 module = __import__(self.module_name)
20 return FilteredModule(module)
21
22 def __exit__(self, exc_type, exc_val, exc_tb):
23 return False
24
25
26class FilteredModule:
27 def __init__(self, module):
28 self._module = module
29
30 def __getattr__(self, name):
31 attr = getattr(self._module, name)
32
33 if (self._has_name(attr)
34 and self._can_answer_quest(attr)
35 and self._has_third_attribute(attr)):
36 return attr
37
38 raise AttributeError(name)
39
40 @staticmethod
41 def _has_name(attr):
42 try:
43 attr_name = attr.__name__
44 except AttributeError:
45 return False
46
47 return isinstance(attr_name, str) and bool(re.match(r"^[A-Z]", attr_name))
48
49 @staticmethod
50 def _can_answer_quest(attr):
51 if not callable(attr):
52 return False
53
54 parameters_block = FilteredModule._get_parameters_block(attr.__doc__)
55 if parameters_block is None:
56 try:
57 attr()
58 return True
59 except Exception:
60 return False
61
62 parameters = FilteredModule._get_docstring_parameters(parameters_block)
63
64 if not FilteredModule._parameter_names_match(attr, parameters):
65 return False
66
67 possible_args = [
68 FilteredModule._generate_values(type_str)
69 for _, type_str in parameters
70 ]
71
72 if any(not values for values in possible_args):
73 return False
74
75 for args in product(*possible_args):
76 try:
77 attr(*args)
78 except Exception:
79 return False
80
81 return True
82
83 @staticmethod
84 def _has_third_attribute(attr):
85 for attr_name in dir(attr):
86 if attr_name.startswith("__") and attr_name.endswith("__"):
87 continue
88
89 if re.search(r"[aeiouAEIOU]{4,}", attr_name):
90 continue
91
92 latin_letters = re.findall(r"[a-zA-Z]", attr_name)
93 if not latin_letters or not latin_letters[-1].isupper():
94 continue
95
96 return True
97
98 return False
99
100 @staticmethod
101 def _parameter_names_match(attr, parameters):
102 try:
103 signature = inspect.signature(attr)
104 except (TypeError, ValueError):
105 return False
106
107 actual_names = list(signature.parameters)
108 expected_names = [name for name, _ in parameters]
109
110 return actual_names == expected_names
111
112 @staticmethod
113 def _get_parameters_block(docstring):
114 match = re.search(
115 r"^\s*Parameters\s*\n\s*-{10,}\s*\n(?P<body>.*?)(?:\n\s*\n|\Z)",
116 docstring or "",
117 re.DOTALL | re.MULTILINE
118 )
119 return match.group('body') if match else None
120
121 @staticmethod
122 def _get_docstring_parameters(parameters_block):
123 parameters = []
124
125 for line in parameters_block.splitlines():
126 if not line.strip():
127 continue
128
129 match = re.match(
130 r"^\s*(?P<name>\w+)\s*:\s*(?P<type>.+?)\s*$",
131 line
132 )
133
134 if match:
135 parameters.append(
136 (match.group("name"), match.group("type"))
137 )
138
139 return parameters
140
141 @staticmethod
142 def _generate_values(type_str):
143 type_str = type_str.strip()
144
145 if "|" in type_str:
146 values = []
147
148 for option in type_str.split("|"):
149 values.extend(FilteredModule._generate_values(option))
150
151 return values
152
153 match = re.match(r"^(\w+)\[(.+)\]$", type_str)
154 if match:
155 outer, inner = match.group(1), match.group(2)
156
157 if outer == "dict":
158 key_type, value_type = [part.strip() for part in inner.split(",", 1)]
159
160 key_samples = FilteredModule._generate_values(key_type)
161 value_samples = FilteredModule._generate_values(value_type)
162
163 if not key_samples or not value_samples:
164 return []
165
166 return [{key_samples[0]: value_samples[0]}]
167
168 inner_values = FilteredModule._generate_values(inner)
169 if not inner_values:
170 return []
171
172 match outer:
173 case "list":
174 return [[inner_values[0]]]
175 case "tuple":
176 return [(inner_values[0],)]
177 case "set":
178 return [{inner_values[0]}]
179
180 return [SAMPLE_VALUES_BY_TYPE[type_str]] if type_str in SAMPLE_VALUES_BY_TYPE else []
.........................
----------------------------------------------------------------------
Ran 25 tests in 0.002s
OK
Виктор Бечев
03.05.2026 23:25Отвъд дребните забележки по-горе - изглежда добре. А и основната грешка е в кода, който е написал LLM-ът, а не в твоето лично творчество.
|
03.05.2026 23:16
03.05.2026 23:18
03.05.2026 23:18