1import importlib
2import re
3
4class BridgeKeeper:
5 """Context manager class (to do)"""
6 TYPE_REGEX = r"(dict\[\w+,\s*\w+\]|\w+\[\w+\]|\w+)"
7 NAME_REGEX = rf"^\w+ : {TYPE_REGEX}( \| {TYPE_REGEX})?$"
8
9 def __init__(self, module_name : str):
10 self._module_name = module_name
11 self._module = importlib.import_module(module_name)
12
13 def __enter__(self):
14 return self
15
16 def __exit__(self, exc_type, exc_val, exc_tb):
17 "Tова не виждам къде мога да го ползвам"
18 pass
19
20 def __getattr__(self, obj_name : str):
21 obj = getattr(self._module, obj_name)
22 if self._check_name(obj) and self._check_quest(obj) and self._check_extra_requirements(obj):
23 return obj
24 raise AttributeError
25
26 def _check_name(self, obj):
27 return hasattr(obj, "__name__") and str(obj.__name__[0]).isupper()
28
29 def _check_quest(self, obj):
30 if not callable(obj):
31 return False
32
33 doc_str = obj.__doc__
34 args = []
35
36 if doc_str and "Parameters" in doc_str:
37 params_match = re.search(r"Parameters\n----------\n(.*?)(\n\n|$)", doc_str, re.DOTALL)
38 if params_match:
39 for row in params_match.group(1).splitlines():
40 if re.match(self.NAME_REGEX, row):
41 type_str = re.match(self.NAME_REGEX, row).group(2)
42 args.append(self._generate_arg(type_str))
43
44 try:
45 obj(*args)
46 return True
47 except Exception:
48 return False
49
50 def _check_extra_requirements(self, obj):
51 for attr_name in dir(obj):
52 if attr_name.startswith('__') and attr_name.endswith('__'):
53 continue
54 letters = re.findall(r'[a-zA-Z]', attr_name)
55 if not letters:
56 continue
57 if letters[-1].isupper() and not re.search(r'[aeiouAEIOU]{4,}', attr_name):
58 return True
59 return False
60
61 def _generate_arg(self, type_str : str):
62 if type_str.startswith("dict"):
63 return {}
64 elif "[" in type_str:
65 return []
66 elif type_str == "int":
67 return 1
68 elif type_str == "float":
69 return 1.0
70 elif type_str == "str":
71 return "a"
72 elif type_str == "bool":
73 return True
74 return None
75
EEEEEEE.E..E............F
======================================================================
ERROR: test_allows_attribute_whose_last_letter_is_uppercase_but_name_continues (test.TestBridgeKeeper.test_allows_attribute_whose_last_letter_is_uppercase_but_name_continues)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 55, in test_allows_attribute_whose_last_letter_is_uppercase_but_name_continues
self.assertEqual(filtered.trailing_marker(7), 70)
^^^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 22, in __getattr__
if self._check_name(obj) and self._check_quest(obj) and self._check_extra_requirements(obj):
~~~~~~~~~~~~~~~~~^^^^^
File "/tmp/solution.py", line 42, in _check_quest
args.append(self._generate_arg(type_str))
~~~~~~~~~~~~~~~~~~^^^^^^^^^^
File "/tmp/solution.py", line 62, in _generate_arg
if type_str.startswith("dict"):
^^^^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'startswith'
======================================================================
ERROR: test_allows_callable_instance (test.TestBridgeKeeper.test_allows_callable_instance)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 86, in test_allows_callable_instance
self.assertEqual(filtered.callable_box([1, 2, 3]), 6)
^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 22, in __getattr__
if self._check_name(obj) and self._check_quest(obj) and self._check_extra_requirements(obj):
~~~~~~~~~~~~~~~~~^^^^^
File "/tmp/solution.py", line 42, in _check_quest
args.append(self._generate_arg(type_str))
~~~~~~~~~~~~~~~~~~^^^^^^^^^^
File "/tmp/solution.py", line 62, in _generate_arg
if type_str.startswith("dict"):
^^^^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'startswith'
======================================================================
ERROR: test_allows_dict_typed_parameter (test.TestBridgeKeeper.test_allows_dict_typed_parameter)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 68, in test_allows_dict_typed_parameter
self.assertEqual(filtered.score_map({"alice": 3, "bob": 7}), 10)
^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 22, in __getattr__
if self._check_name(obj) and self._check_quest(obj) and self._check_extra_requirements(obj):
~~~~~~~~~~~~~~~~~^^^^^
File "/tmp/solution.py", line 42, in _check_quest
args.append(self._generate_arg(type_str))
~~~~~~~~~~~~~~~~~~^^^^^^^^^^
File "/tmp/solution.py", line 62, in _generate_arg
if type_str.startswith("dict"):
^^^^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'startswith'
======================================================================
ERROR: test_allows_multi_argument_union_bonus_case (test.TestBridgeKeeper.test_allows_multi_argument_union_bonus_case)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 95, in test_allows_multi_argument_union_bonus_case
self.assertEqual(filtered.triple_union_pair(3, [1, 2]), 6)
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 24, in __getattr__
raise AttributeError
AttributeError
======================================================================
ERROR: test_allows_set_typed_parameter (test.TestBridgeKeeper.test_allows_set_typed_parameter)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 77, in test_allows_set_typed_parameter
self.assertEqual(filtered.gather_tags({"bridge", "keeper"}), "bridge,keeper")
^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 22, in __getattr__
if self._check_name(obj) and self._check_quest(obj) and self._check_extra_requirements(obj):
~~~~~~~~~~~~~~~~~^^^^^
File "/tmp/solution.py", line 42, in _check_quest
args.append(self._generate_arg(type_str))
~~~~~~~~~~~~~~~~~~^^^^^^^^^^
File "/tmp/solution.py", line 62, in _generate_arg
if type_str.startswith("dict"):
^^^^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'startswith'
======================================================================
ERROR: test_allows_third_answer_name_with_trailing_double_underscores_if_not_dunder (test.TestBridgeKeeper.test_allows_third_answer_name_with_trailing_double_underscores_if_not_dunder)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 64, in test_allows_third_answer_name_with_trailing_double_underscores_if_not_dunder
self.assertEqual(filtered.trailing_underscores(4), 5)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 22, in __getattr__
if self._check_name(obj) and self._check_quest(obj) and self._check_extra_requirements(obj):
~~~~~~~~~~~~~~~~~^^^^^
File "/tmp/solution.py", line 42, in _check_quest
args.append(self._generate_arg(type_str))
~~~~~~~~~~~~~~~~~~^^^^^^^^^^
File "/tmp/solution.py", line 62, in _generate_arg
if type_str.startswith("dict"):
^^^^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'startswith'
======================================================================
ERROR: test_allows_third_answer_with_single_uppercase_letter_name (test.TestBridgeKeeper.test_allows_third_answer_with_single_uppercase_letter_name)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 117, in test_allows_third_answer_with_single_uppercase_letter_name
self.assertEqual(filtered.single_letter_answer(5), 15)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 22, in __getattr__
if self._check_name(obj) and self._check_quest(obj) and self._check_extra_requirements(obj):
~~~~~~~~~~~~~~~~~^^^^^
File "/tmp/solution.py", line 42, in _check_quest
args.append(self._generate_arg(type_str))
~~~~~~~~~~~~~~~~~~^^^^^^^^^^
File "/tmp/solution.py", line 62, in _generate_arg
if type_str.startswith("dict"):
^^^^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'startswith'
======================================================================
ERROR: test_allows_valid_function (test.TestBridgeKeeper.test_allows_valid_function)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 9, in test_allows_valid_function
self.assertEqual(filtered.multiply_text(3, "na"), "nanana")
^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 22, in __getattr__
if self._check_name(obj) and self._check_quest(obj) and self._check_extra_requirements(obj):
~~~~~~~~~~~~~~~~~^^^^^
File "/tmp/solution.py", line 42, in _check_quest
args.append(self._generate_arg(type_str))
~~~~~~~~~~~~~~~~~~^^^^^^^^^^
File "/tmp/solution.py", line 62, in _generate_arg
if type_str.startswith("dict"):
^^^^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'startswith'
======================================================================
ERROR: test_ignores_parameter_like_lines_outside_parameters_block (test.TestBridgeKeeper.test_ignores_parameter_like_lines_outside_parameters_block)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 37, in test_ignores_parameter_like_lines_outside_parameters_block
self.assertEqual(filtered.tricky_doc(2, "xo"), "xoxo")
^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 22, in __getattr__
if self._check_name(obj) and self._check_quest(obj) and self._check_extra_requirements(obj):
~~~~~~~~~~~~~~~~~^^^^^
File "/tmp/solution.py", line 42, in _check_quest
args.append(self._generate_arg(type_str))
~~~~~~~~~~~~~~~~~~^^^^^^^^^^
File "/tmp/solution.py", line 62, in _generate_arg
if type_str.startswith("dict"):
^^^^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'startswith'
======================================================================
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.008s
FAILED (failures=1, errors=9)