1import re
2import inspect
3
4class BridgeKeeper:
5 def __init__(self, module_name):
6 self.module_name = module_name
7
8 def __enter__(self):
9 module = __import__(self.module_name)
10 return Filter(module)
11
12 def __exit__(self, exc_type, exc_value, traceback):
13 return False
14
15
16class Filter:
17 BASE_VALUES = {
18 "int": 1,
19 "float": 1.0,
20 "str": "a",
21 "bool": True,
22 "complex": 1 + 0j,
23 "bytes": b"a",
24 }
25
26 def __init__(self, module):
27 self.module = module
28
29 def whats_your_name(self, attribute):
30 if hasattr(attribute, "__name__"):
31 value = getattr(attribute, "__name__", "")
32 return isinstance(value, str) and re.fullmatch(r"[A-Z]+.*", value)
33
34 return False
35
36
37 def cartesian_product(self, sets):
38 if not sets:
39 yield ()
40 return
41
42 for item in sets[0]:
43 for rest in self.cartesian_product(sets[1:]):
44 yield (item,) + rest
45
46 def value_from_type(self, type_name):
47 type_name = type_name.strip()
48
49 if type_name in self.BASE_VALUES:
50 return self.BASE_VALUES[type_name]
51
52 match = re.fullmatch(r"(list|tuple|set)\[(.+)\]", type_name)
53
54 if match:
55 collection_type = match.group(1)
56 inner_type = match.group(2).strip()
57
58 inner_value = self.value_from_type(inner_type)
59
60 if collection_type == "list":
61 return [inner_value]
62
63 if collection_type == "tuple":
64 return (inner_value,)
65
66 if collection_type == "set":
67 return {inner_value}
68
69 match = re.fullmatch(r"dict\[(.+),\s*(.+)\]", type_name)
70
71 if match:
72 key_type = match.group(1).strip()
73 value_type = match.group(2).strip()
74
75 key = self.value_from_type(key_type)
76 value = self.value_from_type(value_type)
77
78 return {key: value}
79
80 raise ValueError(f"Unknown type: {type_name}")
81
82
83 def values_from_current_types(self, curr):
84 values = []
85
86 for type_name in curr:
87 values.append(self.value_from_type(type_name))
88
89 return values
90
91 def whats_your_quest(self, attribute):
92 if not callable(attribute):
93 return False
94
95 match = ""
96 if attribute.__doc__:
97 match = re.search(r"Parameters\s*\n-+\s*\n([\s\S]*?)(?:\n\s*\n|$)", attribute.__doc__)
98
99 if match:
100 match = match.group(1)
101 else:
102 match = ""
103
104 parameters = []
105 for line in match.splitlines():
106 line = line.strip()
107
108 if line:
109 name, types_of_name = line.split(":", 1)
110 name = name.strip()
111 types_of_name = types_of_name.strip()
112 parameters.append((name, types_of_name))
113
114 signature = inspect.signature(attribute)
115
116 names = list(signature.parameters.keys())
117 doc_names = [name for name, type_of_name in parameters]
118
119 if names != doc_names:
120 return False
121
122 types_by_parameter = []
123
124 for name, types_of_name in parameters:
125 types = [t.strip() for t in types_of_name.split("|")]
126 types_by_parameter.append(types)
127
128 for curr in self.cartesian_product(types_by_parameter):
129 vals = self.values_from_current_types(curr)
130
131 try:
132 attribute(*vals)
133 except:
134 return False
135
136 return True
137
138 def not_dunder(self, attribute):
139 return not (attribute.startswith("__") and attribute.endswith("__"))
140
141 def no_4_consecutive_vowels(self, attribute):
142 return re.search(r"[aeiouAEIOU]{4,}", attribute) is None
143
144 def upper_last_letter(self, attribute):
145 return re.fullmatch(r".*[A-Z][^a-z]*", attribute)
146
147 def what_is(self, attribute):
148 r_correct_attr = "[^_]"
149 for attr in dir(attribute):
150 if self.not_dunder(attr) and self.no_4_consecutive_vowels(attr) and self.upper_last_letter(attr):
151 return True
152 return False
153
154 def isValid(self, attribute):
155 return self.whats_your_name(attribute) and self.whats_your_quest(attribute) and self.what_is(attribute)
156
157 def __getattr__(self, name):
158 attribute = getattr(self.module, name)
159
160 if self.isValid(attribute):
161 return attribute
162
163 raise AttributeError
.........................
----------------------------------------------------------------------
Ran 25 tests in 0.002s
OK