Домашни > The Old Man from Scene #24 > Решения > Решението на Цветинка Хаджиева

Резултати
4 точки от тестове
0 точки от учител

4 точки общо

25 успешни теста
0 неуспешни теста
Код
Скрий всички коментари

  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

Ех, да бяхме имали лекция за регулярни изрази миналата седмица. 😛
История
Това решение има само една версия.