1import importlib
2import inspect
3
4
5class BridgeKeeper:
6 def __init__(self, module_name):
7 self.module_name = module_name
8 self.module = None
9 self.allowed = {}
10
11 def __enter__(self):
12 self.module = importlib.import_module(self.module_name)
13
14 for name in dir(self.module):
15 obj = getattr(self.module, name)
16
17 if self.is_valid(obj):
18 self.allowed[name] = obj
19
20 return self
21
22 def __exit__(self, exc_type, exc_value, traceback):
23 return False
24
25 def __getattr__(self, name):
26 if name in self.allowed:
27 return self.allowed[name]
28
29 raise AttributeError(name)
30
31 def is_valid(self, obj):
32 return self.has_good_name(obj) and self.has_good_quest(obj) and self.has_good_answer(obj)
33
34 def has_good_name(self, obj):
35 return hasattr(obj, "__name__") and len(obj.__name__) > 0 and obj.__name__[0].isupper()
36
37 def has_good_quest(self, obj):
38 if not callable(obj):
39 return False
40
41 parameters = self.get_parameters(obj)
42
43 try:
44 real_parameters = list(inspect.signature(obj).parameters.keys())
45 except Exception:
46 return False
47
48 doc_names = []
49
50 for name, type_name in parameters:
51 doc_names.append(name)
52
53 if real_parameters != doc_names:
54 return False
55
56 variants = [[]]
57
58 for name, type_name in parameters:
59 values = self.values_for_type(type_name)
60 new_variants = []
61
62 for variant in variants:
63 for value in values:
64 new_variants.append(variant + [value])
65
66 variants = new_variants
67
68 for variant in variants:
69 try:
70 obj(*variant)
71 except Exception:
72 return False
73
74 return True
75
76 def get_parameters(self, obj):
77 doc = getattr(obj, "__doc__", None)
78
79 if not doc:
80 return []
81
82 start = doc.find("Parameters\n----------")
83
84 if start == -1:
85 return []
86
87 block = doc[start + len("Parameters\n----------"):]
88
89 end = block.find("\n\n")
90
91 if end != -1:
92 block = block[:end]
93
94 result = []
95
96 for line in block.split("\n"):
97 line = line.strip()
98
99 if not line:
100 continue
101
102 if ":" in line:
103 name, type_name = line.split(":", 1)
104 result.append((name.strip(), type_name.strip()))
105
106 return result
107
108 def values_for_type(self, type_name):
109 parts = [part.strip() for part in type_name.split("|")]
110 result = []
111
112 for part in parts:
113 result.append(self.value_for_simple_type(part))
114
115 return result
116
117 def value_for_simple_type(self, type_name):
118 if type_name == "int":
119 return 1
120
121 if type_name == "float":
122 return 1.5
123
124 if type_name == "str":
125 return "a"
126
127 if type_name == "bool":
128 return True
129
130 if type_name.startswith("list["):
131 inner = type_name[5:-1]
132 return [self.value_for_simple_type(inner)]
133
134 if type_name.startswith("tuple["):
135 inner = type_name[6:-1]
136 return (self.value_for_simple_type(inner),)
137
138 if type_name.startswith("set["):
139 inner = type_name[4:-1]
140 return {self.value_for_simple_type(inner)}
141
142 if type_name.startswith("dict["):
143 inner = type_name[5:-1]
144 key_type, value_type = inner.split(",", 1)
145
146 key = self.value_for_simple_type(key_type.strip())
147 value = self.value_for_simple_type(value_type.strip())
148
149 return {key: value}
150
151 return None
152
153 def has_good_answer(self, obj):
154 for name in dir(obj):
155 if self.is_good_attribute_name(name):
156 return True
157
158 return False
159
160 def is_good_attribute_name(self, name):
161 if name.startswith("__") and name.endswith("__"):
162 return False
163
164 count = 0
165
166 for ch in name.lower():
167 if ch in "aeiou":
168 count += 1
169
170 if count > 3:
171 return False
172 else:
173 count = 0
174
175 last_letter = ""
176
177 for ch in name:
178 if ch.isalpha() and ch.lower() in "abcdefghijklmnopqrstuvwxyz":
179 last_letter = ch
180
181 return last_letter != "" and last_letter.isupper()
.........................
----------------------------------------------------------------------
Ran 25 tests in 0.021s
OK
Виктор Бечев
27.04.2026 17:41Ех, да бяхме имали лекция за регулярни изрази миналата седмица. 😛
|
27.04.2026 17:09
27.04.2026 17:10
27.04.2026 17:13
27.04.2026 17:15
27.04.2026 17:16
27.04.2026 17:32
27.04.2026 17:37