Домашни > The Old Man from Scene #24 > Решения > Решението на Никол Николова

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

4 точки общо

23 успешни теста
2 неуспешни теста
Код

 1import importlib
 2import re
 3
 4class BridgeKeeper:
 5    def __init__(self, module_name):
 6        self.module_name = module_name
 7        self.module = None
 8        
 9    def __enter__(self):
10        self.module = importlib.import_module(self.module_name)
11        return self
12    
13    def __exit__(self, exc_type, exc_val, exc_tb):
14        return False
15    
16    def __getattr__(self, name):
17        if not hasattr(self.module, name):
18            raise AttributeError(f"Module '{self.module_name}' has no attribute '{name}'")
19        obj = getattr(self.module, name)
20        if not self._check_name(obj):
21            raise AttributeError(f"Object '{name}' does not pass the name check")
22        if not self._check_quest(obj):
23            raise AttributeError(f"Object '{name}' does not pass the quest check")
24        if not self._check_random_question(obj):
25            raise AttributeError(f"Object '{name}' does not pass the random question check")
26        return obj
27    
28    def _check_name(self, obj):
29        if not hasattr(obj, '__name__'):
30            return False
31        return len(obj.__name__) > 0 and obj.__name__[0].isupper()
32    
33    def _check_quest(self, obj):
34        if not callable(obj):
35            return False
36        doc = getattr(obj, '__doc__', '') or ''
37        match = re.search(r'Parameters\n----------\n(.*?)(\n\n|$)', doc, re.DOTALL)
38        if match:
39            lines = match.group(1).splitlines()
40            types = [line.split(":", 1)[1].strip() for line in lines if ":" in line and not line.strip().startswith(":")]
41        else:
42            types = []
43        try:
44            args = [self._create_value(t) for t in types]
45            obj(*args)
46            return True
47        except Exception:
48            return False
49        
50    def _create_value(self, t):
51        t = t.strip()
52        if "|" in t:
53            return self._create_value(t.split("|")[0])
54        if t.startswith("list["):
55            inner = t[5:-1]
56            return [self._create_value(inner)]
57        if t.startswith("tuple["):
58            inner = t[6:-1]
59            return (self._create_value(inner),)
60        if t.startswith("set["):
61            inner = t[4:-1]
62            return {self._create_value(inner)}
63        if t.startswith("dict["):
64            inner = t[5:-1]
65            k, v = inner.split(",")
66            return {self._create_value(k.strip()): self._create_value(v.strip())}
67        return {"int": 1, "float": 1.0, "str": "a", "bool": True}.get(t, None)
68    
69    def _check_random_question(self, obj):
70        for attr_name in dir(obj):
71            if attr_name.startswith('__') and attr_name.endswith('__'):
72                continue
73            if self._has_more_than_3_consecutive_vowels(attr_name):
74                continue
75            if not self._last_letter_is_uppercase(attr_name):
76                continue
77            return True       
78        return False
79    
80    def _has_more_than_3_consecutive_vowels(self, s):
81        return bool(re.search(r'[aeiouAEIOU]{4,}', s))
82    
83    def _last_letter_is_uppercase(self, s):
84        letters = [symbol for symbol in s if symbol.isalpha()]
85        return letters and letters[-1].isupper()

............F...........F
======================================================================
FAIL: test_rejects_callable_when_parameter_names_do_not_match (test.TestBridgeKeeper.test_rejects_callable_when_parameter_names_do_not_match)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 59, in test_rejects_callable_when_parameter_names_do_not_match
with self.assertRaises(AttributeError):
~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^
AssertionError: AttributeError not raised

======================================================================
FAIL: test_rejects_union_when_callable_does_not_support_all_union_branches (test.TestBridgeKeeper.test_rejects_union_when_callable_does_not_support_all_union_branches)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 72, in test_rejects_union_when_callable_does_not_support_all_union_branches
with self.assertRaises(AttributeError):
~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^
AssertionError: AttributeError not raised

----------------------------------------------------------------------
Ran 25 tests in 0.002s

FAILED (failures=2)

Дискусия
История
Това решение има само една версия.