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

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

0 точки общо

0 успешни теста
25 неуспешни теста
Код (Последно. Обещавам. :D)

 1import ast
 2import inspect
 3import re
 4import sys
 5from types import ModuleType
 6from typing import Any
 7
 8
 9class BridgeKeeper:
10    def __init__(self, module_name) -> None:
11        self.module_name = module_name
12
13    @staticmethod
14    def _check_for_attributes(obj: Any) -> bool:
15        return bool([arg for arg in dir(obj) if (not re.match(r"[aeiou]{4,}", arg) and
16                                                 not re.match(r"^__.+__$", arg) and
17                                                 not list(filter(lambda x: x.isalpha(), list(arg)))[-1].islower())])
18
19    @staticmethod
20    def _check_for_name(obj: Any) -> bool:
21        return "__name__" in dir(obj) and obj.__name__[0].isupper()
22
23    @staticmethod
24    def _check_for_quest(obj: Any) -> bool:
25
26        def convert_doctype(doctype: str) -> object:
27            base_types = {
28                "int": 1,
29                "float": 1.2,
30                "str": "'string'",
31                "bool": True,
32            }
33
34            if not doctype.startswith('dict'):
35                doctype = doctype.replace("[", "((")
36                doctype = doctype.replace("]", ",))")
37            else:
38                doctype = doctype.replace("[", "([(")
39                doctype = doctype.replace("]", ")])")
40            for key, value in base_types.items():
41                doctype = doctype.replace(key, str(value))
42
43            return ast.literal_eval(doctype)
44
45        func_params = inspect.signature(obj).parameters.keys()
46        doc_string = obj.__doc__
47        doc_params = re.search(r"(?s).+(?<=Parameters\n).+(?<=-{10}\n)(.+?)(?=\n\n|\n$|$)",
48                               "\n".join([x.strip() for x in doc_string.split("\n")]))
49        test_args = [[]]
50        if doc_params:
51            for name, types in [x.split(" : ") for x in doc_params.group(1).split("\n") if " : " in x]:
52                if name not in func_params:
53                    return False
54                test_args = [args + [convert_doctype(_type)] for _type in types.split(" | ") for args in test_args]
55
56        try:
57            for args in test_args:
58                obj(*args)
59            return True
60        except Exception:
61            return False
62
63    def __enter__(self) -> ModuleType:
64        module = __import__(self.module_name)
65        copy_module = ModuleType("copy_module")
66        for obj_name, obj in [(obj_name, getattr(module, obj_name)) for obj_name in dir(module) if
67                              callable(getattr(module, obj_name))]:
68            if (self._check_for_name(obj) and
69                    self._check_for_attributes(obj) and
70                    self._check_for_quest(obj)):
71                setattr(copy_module, obj_name, obj)
72        return copy_module
73
74    def __exit__(self, exc_type, exc, tb):
75        del sys.modules[self.module_name]
76
77
78if __name__ == "__main__":
79    with BridgeKeeper("tests") as filtered_module:
80        # print.pprint(sys.modules)
81        # print(filtered_module.baba(5, 'banichka'))
82        # print(filtered_module.dyado())  # Хвърля се AttributeError, защото dyado не отговаря на въпроси 1 и 3
83        filtered_module.strinka  # Хвърля се AttributeError, защото strinka не може
84        # да бъде извикана успешно с аргументите, описани в docstring-а
85        pass

EEEEEEEEEEEEEEEEEEEEEEEEE
======================================================================
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 54, in test_allows_attribute_whose_last_letter_is_uppercase_but_name_continues
with BridgeKeeper("bridgekeeper_cases") as filtered:
~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 70, in __enter__
self._check_for_quest(obj)):
~~~~~~~~~~~~~~~~~~~~~^^^^^
File "/tmp/solution.py", line 54, in _check_for_quest
test_args = [args + [convert_doctype(_type)] for _type in types.split(" | ") for args in test_args]
~~~~~~~~~~~~~~~^^^^^^^
File "/tmp/solution.py", line 43, in convert_doctype
return ast.literal_eval(doctype)
~~~~~~~~~~~~~~~~^^^^^^^^^
File "/usr/lib/python3.14/ast.py", line 106, in literal_eval
return _convert(node_or_string)
File "/usr/lib/python3.14/ast.py", line 105, in _convert
return _convert_signed_num(node)
File "/usr/lib/python3.14/ast.py", line 79, in _convert_signed_num
return _convert_num(node)
File "/usr/lib/python3.14/ast.py", line 70, in _convert_num
_raise_malformed_node(node)
~~~~~~~~~~~~~~~~~~~~~^^^^^^
File "/usr/lib/python3.14/ast.py", line 67, in _raise_malformed_node
raise ValueError(msg + f': {node!r}')
ValueError: malformed node or string on line 1: Call(func=Name(id='list', ctx=Load()), args=[Tuple(elts=[Constant(value=1, kind=None)], ctx=Load())], keywords=[])

======================================================================
ERROR: test_allows_callable_instance (test.TestBridgeKeeper.test_allows_callable_instance)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 85, in test_allows_callable_instance
with BridgeKeeper("bridgekeeper_cases") as filtered:
~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 70, in __enter__
self._check_for_quest(obj)):
~~~~~~~~~~~~~~~~~~~~~^^^^^
File "/tmp/solution.py", line 54, in _check_for_quest
test_args = [args + [convert_doctype(_type)] for _type in types.split(" | ") for args in test_args]
~~~~~~~~~~~~~~~^^^^^^^
File "/tmp/solution.py", line 43, in convert_doctype
return ast.literal_eval(doctype)
~~~~~~~~~~~~~~~~^^^^^^^^^
File "/usr/lib/python3.14/ast.py", line 106, in literal_eval
return _convert(node_or_string)
File "/usr/lib/python3.14/ast.py", line 105, in _convert
return _convert_signed_num(node)
File "/usr/lib/python3.14/ast.py", line 79, in _convert_signed_num
return _convert_num(node)
File "/usr/lib/python3.14/ast.py", line 70, in _convert_num
_raise_malformed_node(node)
~~~~~~~~~~~~~~~~~~~~~^^^^^^
File "/usr/lib/python3.14/ast.py", line 67, in _raise_malformed_node
raise ValueError(msg + f': {node!r}')
ValueError: malformed node or string on line 1: Call(func=Name(id='list', ctx=Load()), args=[Tuple(elts=[Constant(value=1, kind=None)], ctx=Load())], keywords=[])

======================================================================
ERROR: test_allows_dict_typed_parameter (test.TestBridgeKeeper.test_allows_dict_typed_parameter)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 67, in test_allows_dict_typed_parameter
with BridgeKeeper("bridgekeeper_cases") as filtered:
~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 70, in __enter__
self._check_for_quest(obj)):
~~~~~~~~~~~~~~~~~~~~~^^^^^
File "/tmp/solution.py", line 54, in _check_for_quest
test_args = [args + [convert_doctype(_type)] for _type in types.split(" | ") for args in test_args]
~~~~~~~~~~~~~~~^^^^^^^
File "/tmp/solution.py", line 43, in convert_doctype
return ast.literal_eval(doctype)
~~~~~~~~~~~~~~~~^^^^^^^^^
File "/usr/lib/python3.14/ast.py", line 106, in literal_eval
return _convert(node_or_string)
File "/usr/lib/python3.14/ast.py", line 105, in _convert
return _convert_signed_num(node)
File "/usr/lib/python3.14/ast.py", line 79, in _convert_signed_num
return _convert_num(node)
File "/usr/lib/python3.14/ast.py", line 70, in _convert_num
_raise_malformed_node(node)
~~~~~~~~~~~~~~~~~~~~~^^^^^^
File "/usr/lib/python3.14/ast.py", line 67, in _raise_malformed_node
raise ValueError(msg + f': {node!r}')
ValueError: malformed node or string on line 1: Call(func=Name(id='list', ctx=Load()), args=[Tuple(elts=[Constant(value=1, kind=None)], ctx=Load())], keywords=[])

======================================================================
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 94, in test_allows_multi_argument_union_bonus_case
with BridgeKeeper("bridgekeeper_cases") as filtered:
~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 70, in __enter__
self._check_for_quest(obj)):
~~~~~~~~~~~~~~~~~~~~~^^^^^
File "/tmp/solution.py", line 54, in _check_for_quest
test_args = [args + [convert_doctype(_type)] for _type in types.split(" | ") for args in test_args]
~~~~~~~~~~~~~~~^^^^^^^
File "/tmp/solution.py", line 43, in convert_doctype
return ast.literal_eval(doctype)
~~~~~~~~~~~~~~~~^^^^^^^^^
File "/usr/lib/python3.14/ast.py", line 106, in literal_eval
return _convert(node_or_string)
File "/usr/lib/python3.14/ast.py", line 105, in _convert
return _convert_signed_num(node)
File "/usr/lib/python3.14/ast.py", line 79, in _convert_signed_num
return _convert_num(node)
File "/usr/lib/python3.14/ast.py", line 70, in _convert_num
_raise_malformed_node(node)
~~~~~~~~~~~~~~~~~~~~~^^^^^^
File "/usr/lib/python3.14/ast.py", line 67, in _raise_malformed_node
raise ValueError(msg + f': {node!r}')
ValueError: malformed node or string on line 1: Call(func=Name(id='list', ctx=Load()), args=[Tuple(elts=[Constant(value=1, kind=None)], ctx=Load())], keywords=[])

======================================================================
ERROR: test_allows_set_typed_parameter (test.TestBridgeKeeper.test_allows_set_typed_parameter)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 76, in test_allows_set_typed_parameter
with BridgeKeeper("bridgekeeper_cases") as filtered:
~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 70, in __enter__
self._check_for_quest(obj)):
~~~~~~~~~~~~~~~~~~~~~^^^^^
File "/tmp/solution.py", line 54, in _check_for_quest
test_args = [args + [convert_doctype(_type)] for _type in types.split(" | ") for args in test_args]
~~~~~~~~~~~~~~~^^^^^^^
File "/tmp/solution.py", line 43, in convert_doctype
return ast.literal_eval(doctype)
~~~~~~~~~~~~~~~~^^^^^^^^^
File "/usr/lib/python3.14/ast.py", line 106, in literal_eval
return _convert(node_or_string)
File "/usr/lib/python3.14/ast.py", line 105, in _convert
return _convert_signed_num(node)
File "/usr/lib/python3.14/ast.py", line 79, in _convert_signed_num
return _convert_num(node)
File "/usr/lib/python3.14/ast.py", line 70, in _convert_num
_raise_malformed_node(node)
~~~~~~~~~~~~~~~~~~~~~^^^^^^
File "/usr/lib/python3.14/ast.py", line 67, in _raise_malformed_node
raise ValueError(msg + f': {node!r}')
ValueError: malformed node or string on line 1: Call(func=Name(id='list', ctx=Load()), args=[Tuple(elts=[Constant(value=1, kind=None)], ctx=Load())], keywords=[])

======================================================================
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 63, in test_allows_third_answer_name_with_trailing_double_underscores_if_not_dunder
with BridgeKeeper("bridgekeeper_cases") as filtered:
~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 70, in __enter__
self._check_for_quest(obj)):
~~~~~~~~~~~~~~~~~~~~~^^^^^
File "/tmp/solution.py", line 54, in _check_for_quest
test_args = [args + [convert_doctype(_type)] for _type in types.split(" | ") for args in test_args]
~~~~~~~~~~~~~~~^^^^^^^
File "/tmp/solution.py", line 43, in convert_doctype
return ast.literal_eval(doctype)
~~~~~~~~~~~~~~~~^^^^^^^^^
File "/usr/lib/python3.14/ast.py", line 106, in literal_eval
return _convert(node_or_string)
File "/usr/lib/python3.14/ast.py", line 105, in _convert
return _convert_signed_num(node)
File "/usr/lib/python3.14/ast.py", line 79, in _convert_signed_num
return _convert_num(node)
File "/usr/lib/python3.14/ast.py", line 70, in _convert_num
_raise_malformed_node(node)
~~~~~~~~~~~~~~~~~~~~~^^^^^^
File "/usr/lib/python3.14/ast.py", line 67, in _raise_malformed_node
raise ValueError(msg + f': {node!r}')
ValueError: malformed node or string on line 1: Call(func=Name(id='list', ctx=Load()), args=[Tuple(elts=[Constant(value=1, kind=None)], ctx=Load())], keywords=[])

======================================================================
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 116, in test_allows_third_answer_with_single_uppercase_letter_name
with BridgeKeeper("bridgekeeper_cases") as filtered:
~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 70, in __enter__
self._check_for_quest(obj)):
~~~~~~~~~~~~~~~~~~~~~^^^^^
File "/tmp/solution.py", line 54, in _check_for_quest
test_args = [args + [convert_doctype(_type)] for _type in types.split(" | ") for args in test_args]
~~~~~~~~~~~~~~~^^^^^^^
File "/tmp/solution.py", line 43, in convert_doctype
return ast.literal_eval(doctype)
~~~~~~~~~~~~~~~~^^^^^^^^^
File "/usr/lib/python3.14/ast.py", line 106, in literal_eval
return _convert(node_or_string)
File "/usr/lib/python3.14/ast.py", line 105, in _convert
return _convert_signed_num(node)
File "/usr/lib/python3.14/ast.py", line 79, in _convert_signed_num
return _convert_num(node)
File "/usr/lib/python3.14/ast.py", line 70, in _convert_num
_raise_malformed_node(node)
~~~~~~~~~~~~~~~~~~~~~^^^^^^
File "/usr/lib/python3.14/ast.py", line 67, in _raise_malformed_node
raise ValueError(msg + f': {node!r}')
ValueError: malformed node or string on line 1: Call(func=Name(id='list', ctx=Load()), args=[Tuple(elts=[Constant(value=1, kind=None)], ctx=Load())], keywords=[])

======================================================================
ERROR: test_allows_union_typed_parameter (test.TestBridgeKeeper.test_allows_union_typed_parameter)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 16, in test_allows_union_typed_parameter
with BridgeKeeper("bridgekeeper_cases") as filtered:
~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 70, in __enter__
self._check_for_quest(obj)):
~~~~~~~~~~~~~~~~~~~~~^^^^^
File "/tmp/solution.py", line 54, in _check_for_quest
test_args = [args + [convert_doctype(_type)] for _type in types.split(" | ") for args in test_args]
~~~~~~~~~~~~~~~^^^^^^^
File "/tmp/solution.py", line 43, in convert_doctype
return ast.literal_eval(doctype)
~~~~~~~~~~~~~~~~^^^^^^^^^
File "/usr/lib/python3.14/ast.py", line 106, in literal_eval
return _convert(node_or_string)
File "/usr/lib/python3.14/ast.py", line 105, in _convert
return _convert_signed_num(node)
File "/usr/lib/python3.14/ast.py", line 79, in _convert_signed_num
return _convert_num(node)
File "/usr/lib/python3.14/ast.py", line 70, in _convert_num
_raise_malformed_node(node)
~~~~~~~~~~~~~~~~~~~~~^^^^^^
File "/usr/lib/python3.14/ast.py", line 67, in _raise_malformed_node
raise ValueError(msg + f': {node!r}')
ValueError: malformed node or string on line 1: Call(func=Name(id='list', ctx=Load()), args=[Tuple(elts=[Constant(value=1, kind=None)], ctx=Load())], keywords=[])

======================================================================
ERROR: test_allows_valid_function (test.TestBridgeKeeper.test_allows_valid_function)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 8, in test_allows_valid_function
with BridgeKeeper("bridgekeeper_cases") as filtered:
~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 70, in __enter__
self._check_for_quest(obj)):
~~~~~~~~~~~~~~~~~~~~~^^^^^
File "/tmp/solution.py", line 54, in _check_for_quest
test_args = [args + [convert_doctype(_type)] for _type in types.split(" | ") for args in test_args]
~~~~~~~~~~~~~~~^^^^^^^
File "/tmp/solution.py", line 43, in convert_doctype
return ast.literal_eval(doctype)
~~~~~~~~~~~~~~~~^^^^^^^^^
File "/usr/lib/python3.14/ast.py", line 106, in literal_eval
return _convert(node_or_string)
File "/usr/lib/python3.14/ast.py", line 105, in _convert
return _convert_signed_num(node)
File "/usr/lib/python3.14/ast.py", line 79, in _convert_signed_num
return _convert_num(node)
File "/usr/lib/python3.14/ast.py", line 70, in _convert_num
_raise_malformed_node(node)
~~~~~~~~~~~~~~~~~~~~~^^^^^^
File "/usr/lib/python3.14/ast.py", line 67, in _raise_malformed_node
raise ValueError(msg + f': {node!r}')
ValueError: malformed node or string on line 1: Call(func=Name(id='list', ctx=Load()), args=[Tuple(elts=[Constant(value=1, kind=None)], ctx=Load())], keywords=[])

======================================================================
ERROR: test_allows_zero_arg_callable_when_parameters_block_is_missing (test.TestBridgeKeeper.test_allows_zero_arg_callable_when_parameters_block_is_missing)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 12, in test_allows_zero_arg_callable_when_parameters_block_is_missing
with BridgeKeeper("bridgekeeper_cases") as filtered:
~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 70, in __enter__
self._check_for_quest(obj)):
~~~~~~~~~~~~~~~~~~~~~^^^^^
File "/tmp/solution.py", line 54, in _check_for_quest
test_args = [args + [convert_doctype(_type)] for _type in types.split(" | ") for args in test_args]
~~~~~~~~~~~~~~~^^^^^^^
File "/tmp/solution.py", line 43, in convert_doctype
return ast.literal_eval(doctype)
~~~~~~~~~~~~~~~~^^^^^^^^^
File "/usr/lib/python3.14/ast.py", line 106, in literal_eval
return _convert(node_or_string)
File "/usr/lib/python3.14/ast.py", line 105, in _convert
return _convert_signed_num(node)
File "/usr/lib/python3.14/ast.py", line 79, in _convert_signed_num
return _convert_num(node)
File "/usr/lib/python3.14/ast.py", line 70, in _convert_num
_raise_malformed_node(node)
~~~~~~~~~~~~~~~~~~~~~^^^^^^
File "/usr/lib/python3.14/ast.py", line 67, in _raise_malformed_node
raise ValueError(msg + f': {node!r}')
ValueError: malformed node or string on line 1: Call(func=Name(id='list', ctx=Load()), args=[Tuple(elts=[Constant(value=1, kind=None)], ctx=Load())], keywords=[])

======================================================================
ERROR: test_allows_zero_arg_callable_with_missing_docstring (test.TestBridgeKeeper.test_allows_zero_arg_callable_with_missing_docstring)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 50, in test_allows_zero_arg_callable_with_missing_docstring
with BridgeKeeper("bridgekeeper_cases") as filtered:
~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 70, in __enter__
self._check_for_quest(obj)):
~~~~~~~~~~~~~~~~~~~~~^^^^^
File "/tmp/solution.py", line 54, in _check_for_quest
test_args = [args + [convert_doctype(_type)] for _type in types.split(" | ") for args in test_args]
~~~~~~~~~~~~~~~^^^^^^^
File "/tmp/solution.py", line 43, in convert_doctype
return ast.literal_eval(doctype)
~~~~~~~~~~~~~~~~^^^^^^^^^
File "/usr/lib/python3.14/ast.py", line 106, in literal_eval
return _convert(node_or_string)
File "/usr/lib/python3.14/ast.py", line 105, in _convert
return _convert_signed_num(node)
File "/usr/lib/python3.14/ast.py", line 79, in _convert_signed_num
return _convert_num(node)
File "/usr/lib/python3.14/ast.py", line 70, in _convert_num
_raise_malformed_node(node)
~~~~~~~~~~~~~~~~~~~~~^^^^^^
File "/usr/lib/python3.14/ast.py", line 67, in _raise_malformed_node
raise ValueError(msg + f': {node!r}')
ValueError: malformed node or string on line 1: Call(func=Name(id='list', ctx=Load()), args=[Tuple(elts=[Constant(value=1, kind=None)], ctx=Load())], keywords=[])

======================================================================
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 36, in test_ignores_parameter_like_lines_outside_parameters_block
with BridgeKeeper("bridgekeeper_cases") as filtered:
~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 70, in __enter__
self._check_for_quest(obj)):
~~~~~~~~~~~~~~~~~~~~~^^^^^
File "/tmp/solution.py", line 54, in _check_for_quest
test_args = [args + [convert_doctype(_type)] for _type in types.split(" | ") for args in test_args]
~~~~~~~~~~~~~~~^^^^^^^
File "/tmp/solution.py", line 43, in convert_doctype
return ast.literal_eval(doctype)
~~~~~~~~~~~~~~~~^^^^^^^^^
File "/usr/lib/python3.14/ast.py", line 106, in literal_eval
return _convert(node_or_string)
File "/usr/lib/python3.14/ast.py", line 105, in _convert
return _convert_signed_num(node)
File "/usr/lib/python3.14/ast.py", line 79, in _convert_signed_num
return _convert_num(node)
File "/usr/lib/python3.14/ast.py", line 70, in _convert_num
_raise_malformed_node(node)
~~~~~~~~~~~~~~~~~~~~~^^^^^^
File "/usr/lib/python3.14/ast.py", line 67, in _raise_malformed_node
raise ValueError(msg + f': {node!r}')
ValueError: malformed node or string on line 1: Call(func=Name(id='list', ctx=Load()), args=[Tuple(elts=[Constant(value=1, kind=None)], ctx=Load())], keywords=[])

======================================================================
ERROR: 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 58, in test_rejects_callable_when_parameter_names_do_not_match
with BridgeKeeper("bridgekeeper_cases") as filtered:
~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 70, in __enter__
self._check_for_quest(obj)):
~~~~~~~~~~~~~~~~~~~~~^^^^^
File "/tmp/solution.py", line 54, in _check_for_quest
test_args = [args + [convert_doctype(_type)] for _type in types.split(" | ") for args in test_args]
~~~~~~~~~~~~~~~^^^^^^^
File "/tmp/solution.py", line 43, in convert_doctype
return ast.literal_eval(doctype)
~~~~~~~~~~~~~~~~^^^^^^^^^
File "/usr/lib/python3.14/ast.py", line 106, in literal_eval
return _convert(node_or_string)
File "/usr/lib/python3.14/ast.py", line 105, in _convert
return _convert_signed_num(node)
File "/usr/lib/python3.14/ast.py", line 79, in _convert_signed_num
return _convert_num(node)
File "/usr/lib/python3.14/ast.py", line 70, in _convert_num
_raise_malformed_node(node)
~~~~~~~~~~~~~~~~~~~~~^^^^^^
File "/usr/lib/python3.14/ast.py", line 67, in _raise_malformed_node
raise ValueError(msg + f': {node!r}')
ValueError: malformed node or string on line 1: Call(func=Name(id='list', ctx=Load()), args=[Tuple(elts=[Constant(value=1, kind=None)], ctx=Load())], keywords=[])

======================================================================
ERROR: test_rejects_callable_without_valid_third_answer (test.TestBridgeKeeper.test_rejects_callable_without_valid_third_answer)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 31, in test_rejects_callable_without_valid_third_answer
with BridgeKeeper("bridgekeeper_cases") as filtered:
~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 70, in __enter__
self._check_for_quest(obj)):
~~~~~~~~~~~~~~~~~~~~~^^^^^
File "/tmp/solution.py", line 54, in _check_for_quest
test_args = [args + [convert_doctype(_type)] for _type in types.split(" | ") for args in test_args]
~~~~~~~~~~~~~~~^^^^^^^
File "/tmp/solution.py", line 43, in convert_doctype
return ast.literal_eval(doctype)
~~~~~~~~~~~~~~~~^^^^^^^^^
File "/usr/lib/python3.14/ast.py", line 106, in literal_eval
return _convert(node_or_string)
File "/usr/lib/python3.14/ast.py", line 105, in _convert
return _convert_signed_num(node)
File "/usr/lib/python3.14/ast.py", line 79, in _convert_signed_num
return _convert_num(node)
File "/usr/lib/python3.14/ast.py", line 70, in _convert_num
_raise_malformed_node(node)
~~~~~~~~~~~~~~~~~~~~~^^^^^^
File "/usr/lib/python3.14/ast.py", line 67, in _raise_malformed_node
raise ValueError(msg + f': {node!r}')
ValueError: malformed node or string on line 1: Call(func=Name(id='list', ctx=Load()), args=[Tuple(elts=[Constant(value=1, kind=None)], ctx=Load())], keywords=[])

======================================================================
ERROR: test_rejects_dict_when_callable_does_not_work_with_documented_key_and_value_types (test.TestBridgeKeeper.test_rejects_dict_when_callable_does_not_work_with_documented_key_and_value_types)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 89, in test_rejects_dict_when_callable_does_not_work_with_documented_key_and_value_types
with BridgeKeeper("bridgekeeper_cases") as filtered:
~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 70, in __enter__
self._check_for_quest(obj)):
~~~~~~~~~~~~~~~~~~~~~^^^^^
File "/tmp/solution.py", line 54, in _check_for_quest
test_args = [args + [convert_doctype(_type)] for _type in types.split(" | ") for args in test_args]
~~~~~~~~~~~~~~~^^^^^^^
File "/tmp/solution.py", line 43, in convert_doctype
return ast.literal_eval(doctype)
~~~~~~~~~~~~~~~~^^^^^^^^^
File "/usr/lib/python3.14/ast.py", line 106, in literal_eval
return _convert(node_or_string)
File "/usr/lib/python3.14/ast.py", line 105, in _convert
return _convert_signed_num(node)
File "/usr/lib/python3.14/ast.py", line 79, in _convert_signed_num
return _convert_num(node)
File "/usr/lib/python3.14/ast.py", line 70, in _convert_num
_raise_malformed_node(node)
~~~~~~~~~~~~~~~~~~~~~^^^^^^
File "/usr/lib/python3.14/ast.py", line 67, in _raise_malformed_node
raise ValueError(msg + f': {node!r}')
ValueError: malformed node or string on line 1: Call(func=Name(id='list', ctx=Load()), args=[Tuple(elts=[Constant(value=1, kind=None)], ctx=Load())], keywords=[])

======================================================================
ERROR: test_rejects_docstring_with_arity_mismatch (test.TestBridgeKeeper.test_rejects_docstring_with_arity_mismatch)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 45, in test_rejects_docstring_with_arity_mismatch
with BridgeKeeper("bridgekeeper_cases") as filtered:
~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 70, in __enter__
self._check_for_quest(obj)):
~~~~~~~~~~~~~~~~~~~~~^^^^^
File "/tmp/solution.py", line 54, in _check_for_quest
test_args = [args + [convert_doctype(_type)] for _type in types.split(" | ") for args in test_args]
~~~~~~~~~~~~~~~^^^^^^^
File "/tmp/solution.py", line 43, in convert_doctype
return ast.literal_eval(doctype)
~~~~~~~~~~~~~~~~^^^^^^^^^
File "/usr/lib/python3.14/ast.py", line 106, in literal_eval
return _convert(node_or_string)
File "/usr/lib/python3.14/ast.py", line 105, in _convert
return _convert_signed_num(node)
File "/usr/lib/python3.14/ast.py", line 79, in _convert_signed_num
return _convert_num(node)
File "/usr/lib/python3.14/ast.py", line 70, in _convert_num
_raise_malformed_node(node)
~~~~~~~~~~~~~~~~~~~~~^^^^^^
File "/usr/lib/python3.14/ast.py", line 67, in _raise_malformed_node
raise ValueError(msg + f': {node!r}')
ValueError: malformed node or string on line 1: Call(func=Name(id='list', ctx=Load()), args=[Tuple(elts=[Constant(value=1, kind=None)], ctx=Load())], keywords=[])

======================================================================
ERROR: test_rejects_docstring_with_parameter_order_mismatch (test.TestBridgeKeeper.test_rejects_docstring_with_parameter_order_mismatch)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 40, in test_rejects_docstring_with_parameter_order_mismatch
with BridgeKeeper("bridgekeeper_cases") as filtered:
~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 70, in __enter__
self._check_for_quest(obj)):
~~~~~~~~~~~~~~~~~~~~~^^^^^
File "/tmp/solution.py", line 54, in _check_for_quest
test_args = [args + [convert_doctype(_type)] for _type in types.split(" | ") for args in test_args]
~~~~~~~~~~~~~~~^^^^^^^
File "/tmp/solution.py", line 43, in convert_doctype
return ast.literal_eval(doctype)
~~~~~~~~~~~~~~~~^^^^^^^^^
File "/usr/lib/python3.14/ast.py", line 106, in literal_eval
return _convert(node_or_string)
File "/usr/lib/python3.14/ast.py", line 105, in _convert
return _convert_signed_num(node)
File "/usr/lib/python3.14/ast.py", line 79, in _convert_signed_num
return _convert_num(node)
File "/usr/lib/python3.14/ast.py", line 70, in _convert_num
_raise_malformed_node(node)
~~~~~~~~~~~~~~~~~~~~~^^^^^^
File "/usr/lib/python3.14/ast.py", line 67, in _raise_malformed_node
raise ValueError(msg + f': {node!r}')
ValueError: malformed node or string on line 1: Call(func=Name(id='list', ctx=Load()), args=[Tuple(elts=[Constant(value=1, kind=None)], ctx=Load())], keywords=[])

======================================================================
ERROR: test_rejects_list_when_callable_does_not_work_with_documented_element_type (test.TestBridgeKeeper.test_rejects_list_when_callable_does_not_work_with_documented_element_type)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 101, in test_rejects_list_when_callable_does_not_work_with_documented_element_type
with BridgeKeeper("bridgekeeper_cases") as filtered:
~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 70, in __enter__
self._check_for_quest(obj)):
~~~~~~~~~~~~~~~~~~~~~^^^^^
File "/tmp/solution.py", line 54, in _check_for_quest
test_args = [args + [convert_doctype(_type)] for _type in types.split(" | ") for args in test_args]
~~~~~~~~~~~~~~~^^^^^^^
File "/tmp/solution.py", line 43, in convert_doctype
return ast.literal_eval(doctype)
~~~~~~~~~~~~~~~~^^^^^^^^^
File "/usr/lib/python3.14/ast.py", line 106, in literal_eval
return _convert(node_or_string)
File "/usr/lib/python3.14/ast.py", line 105, in _convert
return _convert_signed_num(node)
File "/usr/lib/python3.14/ast.py", line 79, in _convert_signed_num
return _convert_num(node)
File "/usr/lib/python3.14/ast.py", line 70, in _convert_num
_raise_malformed_node(node)
~~~~~~~~~~~~~~~~~~~~~^^^^^^
File "/usr/lib/python3.14/ast.py", line 67, in _raise_malformed_node
raise ValueError(msg + f': {node!r}')
ValueError: malformed node or string on line 1: Call(func=Name(id='list', ctx=Load()), args=[Tuple(elts=[Constant(value=1, kind=None)], ctx=Load())], keywords=[])

======================================================================
ERROR: test_rejects_missing_parameters_block_when_callable_requires_arguments (test.TestBridgeKeeper.test_rejects_missing_parameters_block_when_callable_requires_arguments)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 80, in test_rejects_missing_parameters_block_when_callable_requires_arguments
with BridgeKeeper("bridgekeeper_cases") as filtered:
~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 70, in __enter__
self._check_for_quest(obj)):
~~~~~~~~~~~~~~~~~~~~~^^^^^
File "/tmp/solution.py", line 54, in _check_for_quest
test_args = [args + [convert_doctype(_type)] for _type in types.split(" | ") for args in test_args]
~~~~~~~~~~~~~~~^^^^^^^
File "/tmp/solution.py", line 43, in convert_doctype
return ast.literal_eval(doctype)
~~~~~~~~~~~~~~~~^^^^^^^^^
File "/usr/lib/python3.14/ast.py", line 106, in literal_eval
return _convert(node_or_string)
File "/usr/lib/python3.14/ast.py", line 105, in _convert
return _convert_signed_num(node)
File "/usr/lib/python3.14/ast.py", line 79, in _convert_signed_num
return _convert_num(node)
File "/usr/lib/python3.14/ast.py", line 70, in _convert_num
_raise_malformed_node(node)
~~~~~~~~~~~~~~~~~~~~~^^^^^^
File "/usr/lib/python3.14/ast.py", line 67, in _raise_malformed_node
raise ValueError(msg + f': {node!r}')
ValueError: malformed node or string on line 1: Call(func=Name(id='list', ctx=Load()), args=[Tuple(elts=[Constant(value=1, kind=None)], ctx=Load())], keywords=[])

======================================================================
ERROR: test_rejects_non_callable_object (test.TestBridgeKeeper.test_rejects_non_callable_object)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 26, in test_rejects_non_callable_object
with BridgeKeeper("bridgekeeper_cases") as filtered:
~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 70, in __enter__
self._check_for_quest(obj)):
~~~~~~~~~~~~~~~~~~~~~^^^^^
File "/tmp/solution.py", line 54, in _check_for_quest
test_args = [args + [convert_doctype(_type)] for _type in types.split(" | ") for args in test_args]
~~~~~~~~~~~~~~~^^^^^^^
File "/tmp/solution.py", line 43, in convert_doctype
return ast.literal_eval(doctype)
~~~~~~~~~~~~~~~~^^^^^^^^^
File "/usr/lib/python3.14/ast.py", line 106, in literal_eval
return _convert(node_or_string)
File "/usr/lib/python3.14/ast.py", line 105, in _convert
return _convert_signed_num(node)
File "/usr/lib/python3.14/ast.py", line 79, in _convert_signed_num
return _convert_num(node)
File "/usr/lib/python3.14/ast.py", line 70, in _convert_num
_raise_malformed_node(node)
~~~~~~~~~~~~~~~~~~~~~^^^^^^
File "/usr/lib/python3.14/ast.py", line 67, in _raise_malformed_node
raise ValueError(msg + f': {node!r}')
ValueError: malformed node or string on line 1: Call(func=Name(id='list', ctx=Load()), args=[Tuple(elts=[Constant(value=1, kind=None)], ctx=Load())], keywords=[])

======================================================================
ERROR: test_rejects_object_with_lowercase_name (test.TestBridgeKeeper.test_rejects_object_with_lowercase_name)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 21, in test_rejects_object_with_lowercase_name
with BridgeKeeper("bridgekeeper_cases") as filtered:
~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 70, in __enter__
self._check_for_quest(obj)):
~~~~~~~~~~~~~~~~~~~~~^^^^^
File "/tmp/solution.py", line 54, in _check_for_quest
test_args = [args + [convert_doctype(_type)] for _type in types.split(" | ") for args in test_args]
~~~~~~~~~~~~~~~^^^^^^^
File "/tmp/solution.py", line 43, in convert_doctype
return ast.literal_eval(doctype)
~~~~~~~~~~~~~~~~^^^^^^^^^
File "/usr/lib/python3.14/ast.py", line 106, in literal_eval
return _convert(node_or_string)
File "/usr/lib/python3.14/ast.py", line 105, in _convert
return _convert_signed_num(node)
File "/usr/lib/python3.14/ast.py", line 79, in _convert_signed_num
return _convert_num(node)
File "/usr/lib/python3.14/ast.py", line 70, in _convert_num
_raise_malformed_node(node)
~~~~~~~~~~~~~~~~~~~~~^^^^^^
File "/usr/lib/python3.14/ast.py", line 67, in _raise_malformed_node
raise ValueError(msg + f': {node!r}')
ValueError: malformed node or string on line 1: Call(func=Name(id='list', ctx=Load()), args=[Tuple(elts=[Constant(value=1, kind=None)], ctx=Load())], keywords=[])

======================================================================
ERROR: test_rejects_set_when_callable_does_not_work_with_documented_element_type (test.TestBridgeKeeper.test_rejects_set_when_callable_does_not_work_with_documented_element_type)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 111, in test_rejects_set_when_callable_does_not_work_with_documented_element_type
with BridgeKeeper("bridgekeeper_cases") as filtered:
~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 70, in __enter__
self._check_for_quest(obj)):
~~~~~~~~~~~~~~~~~~~~~^^^^^
File "/tmp/solution.py", line 54, in _check_for_quest
test_args = [args + [convert_doctype(_type)] for _type in types.split(" | ") for args in test_args]
~~~~~~~~~~~~~~~^^^^^^^
File "/tmp/solution.py", line 43, in convert_doctype
return ast.literal_eval(doctype)
~~~~~~~~~~~~~~~~^^^^^^^^^
File "/usr/lib/python3.14/ast.py", line 106, in literal_eval
return _convert(node_or_string)
File "/usr/lib/python3.14/ast.py", line 105, in _convert
return _convert_signed_num(node)
File "/usr/lib/python3.14/ast.py", line 79, in _convert_signed_num
return _convert_num(node)
File "/usr/lib/python3.14/ast.py", line 70, in _convert_num
_raise_malformed_node(node)
~~~~~~~~~~~~~~~~~~~~~^^^^^^
File "/usr/lib/python3.14/ast.py", line 67, in _raise_malformed_node
raise ValueError(msg + f': {node!r}')
ValueError: malformed node or string on line 1: Call(func=Name(id='list', ctx=Load()), args=[Tuple(elts=[Constant(value=1, kind=None)], ctx=Load())], keywords=[])

======================================================================
ERROR: test_rejects_third_answer_with_four_consecutive_uppercase_vowels (test.TestBridgeKeeper.test_rejects_third_answer_with_four_consecutive_uppercase_vowels)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 120, in test_rejects_third_answer_with_four_consecutive_uppercase_vowels
with BridgeKeeper("bridgekeeper_cases") as filtered:
~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 70, in __enter__
self._check_for_quest(obj)):
~~~~~~~~~~~~~~~~~~~~~^^^^^
File "/tmp/solution.py", line 54, in _check_for_quest
test_args = [args + [convert_doctype(_type)] for _type in types.split(" | ") for args in test_args]
~~~~~~~~~~~~~~~^^^^^^^
File "/tmp/solution.py", line 43, in convert_doctype
return ast.literal_eval(doctype)
~~~~~~~~~~~~~~~~^^^^^^^^^
File "/usr/lib/python3.14/ast.py", line 106, in literal_eval
return _convert(node_or_string)
File "/usr/lib/python3.14/ast.py", line 105, in _convert
return _convert_signed_num(node)
File "/usr/lib/python3.14/ast.py", line 79, in _convert_signed_num
return _convert_num(node)
File "/usr/lib/python3.14/ast.py", line 70, in _convert_num
_raise_malformed_node(node)
~~~~~~~~~~~~~~~~~~~~~^^^^^^
File "/usr/lib/python3.14/ast.py", line 67, in _raise_malformed_node
raise ValueError(msg + f': {node!r}')
ValueError: malformed node or string on line 1: Call(func=Name(id='list', ctx=Load()), args=[Tuple(elts=[Constant(value=1, kind=None)], ctx=Load())], keywords=[])

======================================================================
ERROR: test_rejects_tuple_when_callable_does_not_work_with_documented_element_type (test.TestBridgeKeeper.test_rejects_tuple_when_callable_does_not_work_with_documented_element_type)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 106, in test_rejects_tuple_when_callable_does_not_work_with_documented_element_type
with BridgeKeeper("bridgekeeper_cases") as filtered:
~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 70, in __enter__
self._check_for_quest(obj)):
~~~~~~~~~~~~~~~~~~~~~^^^^^
File "/tmp/solution.py", line 54, in _check_for_quest
test_args = [args + [convert_doctype(_type)] for _type in types.split(" | ") for args in test_args]
~~~~~~~~~~~~~~~^^^^^^^
File "/tmp/solution.py", line 43, in convert_doctype
return ast.literal_eval(doctype)
~~~~~~~~~~~~~~~~^^^^^^^^^
File "/usr/lib/python3.14/ast.py", line 106, in literal_eval
return _convert(node_or_string)
File "/usr/lib/python3.14/ast.py", line 105, in _convert
return _convert_signed_num(node)
File "/usr/lib/python3.14/ast.py", line 79, in _convert_signed_num
return _convert_num(node)
File "/usr/lib/python3.14/ast.py", line 70, in _convert_num
_raise_malformed_node(node)
~~~~~~~~~~~~~~~~~~~~~^^^^^^
File "/usr/lib/python3.14/ast.py", line 67, in _raise_malformed_node
raise ValueError(msg + f': {node!r}')
ValueError: malformed node or string on line 1: Call(func=Name(id='list', ctx=Load()), args=[Tuple(elts=[Constant(value=1, kind=None)], ctx=Load())], keywords=[])

======================================================================
ERROR: 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 71, in test_rejects_union_when_callable_does_not_support_all_union_branches
with BridgeKeeper("bridgekeeper_cases") as filtered:
~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 70, in __enter__
self._check_for_quest(obj)):
~~~~~~~~~~~~~~~~~~~~~^^^^^
File "/tmp/solution.py", line 54, in _check_for_quest
test_args = [args + [convert_doctype(_type)] for _type in types.split(" | ") for args in test_args]
~~~~~~~~~~~~~~~^^^^^^^
File "/tmp/solution.py", line 43, in convert_doctype
return ast.literal_eval(doctype)
~~~~~~~~~~~~~~~~^^^^^^^^^
File "/usr/lib/python3.14/ast.py", line 106, in literal_eval
return _convert(node_or_string)
File "/usr/lib/python3.14/ast.py", line 105, in _convert
return _convert_signed_num(node)
File "/usr/lib/python3.14/ast.py", line 79, in _convert_signed_num
return _convert_num(node)
File "/usr/lib/python3.14/ast.py", line 70, in _convert_num
_raise_malformed_node(node)
~~~~~~~~~~~~~~~~~~~~~^^^^^^
File "/usr/lib/python3.14/ast.py", line 67, in _raise_malformed_node
raise ValueError(msg + f': {node!r}')
ValueError: malformed node or string on line 1: Call(func=Name(id='list', ctx=Load()), args=[Tuple(elts=[Constant(value=1, kind=None)], ctx=Load())], keywords=[])

----------------------------------------------------------------------
Ran 25 tests in 0.026s

FAILED (errors=25)

Дискусия
История

f1import astf1import ast
2import inspect2import inspect
3import re3import re
nn4import sys
4from types import ModuleType5from types import ModuleType
nn6from typing import Any
57
68
7class BridgeKeeper:9class BridgeKeeper:
8    def __init__(self, module_name) -> None:10    def __init__(self, module_name) -> None:
9        self.module_name = module_name11        self.module_name = module_name
1012
11    @staticmethod13    @staticmethod
n12    def _check_for_attributes(obj) -> bool:n14    def _check_for_attributes(obj: Any) -> bool:
13        for arg in obj.__dir__():15        return bool([arg for arg in dir(obj) if (not re.match(r"[aeiou]{4,}", arg) and
14            if (not re.match(r"[aeiou]{4,}", arg) and
15                    not re.match(r"^__.+__$", arg) and16                                                 not re.match(r"^__.+__$", arg) and
16                    not list(filter(lambda x: x.isalpha(), list(arg)))[-1].islower()):17                                                 not list(filter(lambda x: x.isalpha(), list(arg)))[-1].islower())])
17                return True
18        return False
1918
20    @staticmethod19    @staticmethod
n21    def _check_for_name(obj) -> bool:n20    def _check_for_name(obj: Any) -> bool:
22        return "__name__" in obj.__dir__() and obj.__name__[0].isupper()21        return "__name__" in dir(obj) and obj.__name__[0].isupper()
2322
24    @staticmethod23    @staticmethod
n25    def _check_for_quest(obj) -> bool:n24    def _check_for_quest(obj: Any) -> bool:
2625
27        def convert_doctype(doctype: str) -> object:26        def convert_doctype(doctype: str) -> object:
n28            help_values = {n27            base_types = {
29                "int": 1,28                "int": 1,
30                "float": 1.2,29                "float": 1.2,
31                "str": "'string'",30                "str": "'string'",
32                "bool": True,31                "bool": True,
33            }32            }
3433
35            if not doctype.startswith('dict'):34            if not doctype.startswith('dict'):
36                doctype = doctype.replace("[", "((")35                doctype = doctype.replace("[", "((")
37                doctype = doctype.replace("]", ",))")36                doctype = doctype.replace("]", ",))")
38            else:37            else:
39                doctype = doctype.replace("[", "([(")38                doctype = doctype.replace("[", "([(")
40                doctype = doctype.replace("]", ")])")39                doctype = doctype.replace("]", ")])")
n41            for key, value in help_values.items():n40            for key, value in base_types.items():
42                doctype = doctype.replace(key, str(value))41                doctype = doctype.replace(key, str(value))
4342
44            return ast.literal_eval(doctype)43            return ast.literal_eval(doctype)
4544
n46        if "__call__" in dir(obj):n45        func_params = inspect.signature(obj).parameters.keys()
47            doc_string = obj.__doc__46        doc_string = obj.__doc__
48            if inspect.isfunction(obj):
49                func_args = obj.__code__.co_varnames
50            else:
51                func_args = obj.__init__.__code__.co_varnames
52        else:
53            return False
54 
55        doc_args = re.search(r"(?s)(?<=Parameters\n----------\n).+(?=\n\n|\n$|$)",47        doc_params = re.search(r"(?s).+(?<=Parameters\n).+(?<=-{10}\n)(.+?)(?=\n\n|\n$|$)",
56                             "\n".join(list(map(lambda x: x.strip(), doc_string.split("\n")))))48                               "\n".join([x.strip() for x in doc_string.split("\n")]))
57        test_params = [[]]49        test_args = [[]]
58        if doc_args:50        if doc_params:
59            for arg in filter(lambda x: " : " in x, doc_args.group().split("\n")):51            for name, types in [x.split(" : ") for x in doc_params.group(1).split("\n") if " : " in x]:
60                kvp = arg.split(" : ")
61                name, types = kvp
62                if name not in func_args:52                if name not in func_params:
63                    return False53                    return False
n64                types = types.split(" | ")n
65                test_param= [test + [convert_doctype(_type)] for _type in types for test in test_params]54                test_args = [args + [convert_doctype(_type)] for _type in types.split(" | ") for args in test_args]
6655
67        try:56        try:
n68            for params in test_params:n57            for args in test_args:
69                obj(*params)58                obj(*args)
70        except (ValueError, TypeError):59            return True
60        except Exception:
71            return False61            return False
n72 n
73        return True
7462
75    def __enter__(self) -> ModuleType:63    def __enter__(self) -> ModuleType:
76        module = __import__(self.module_name)64        module = __import__(self.module_name)
n77        for obj_name in module.__dir__():n65        copy_module = ModuleType("copy_module")
78            obj = getattr(module, obj_name)66        for obj_name, obj in [(obj_name, getattr(module, obj_name)) for obj_name in dir(module) if
79            if "__call__" in obj.__dir__() and (not self._check_for_name(obj) or67                              callable(getattr(module, obj_name))]:
80                                                not self._check_for_attributes(obj) or68            if (self._check_for_name(obj) and
69                    self._check_for_attributes(obj) and
81                                                not self._check_for_quest(obj)):70                    self._check_for_quest(obj)):
82                delattr(module, obj_name)71                setattr(copy_module, obj_name, obj)
83        return module72        return copy_module
8473
85    def __exit__(self, exc_type, exc, tb):74    def __exit__(self, exc_type, exc, tb):
n86        passn75        del sys.modules[self.module_name]
8776
8877
89if __name__ == "__main__":78if __name__ == "__main__":
90    with BridgeKeeper("tests") as filtered_module:79    with BridgeKeeper("tests") as filtered_module:
tt80        # print.pprint(sys.modules)
91        print(filtered_module.baba(5, 'banichka'))81        # print(filtered_module.baba(5, 'banichka'))
92        filtered_module.dyado  # Хвърля се AttributeError, защото dyado не отговаря на въпроси 1 и 382        # print(filtered_module.dyado())  # Хвърля се AttributeError, защото dyado не отговаря на въпроси 1 и 3
93        filtered_module.strinka  # Хвърля се AttributeError, защото strinka не може да бъде извикана успешно с аргументите, описани в docstring-а83        filtered_module.strinka  # Хвърля се AttributeError, защото strinka не може
84        # да бъде извикана успешно с аргументите, описани в docstring-а
94        pass85        pass
Legends
Colors
 Added 
Changed
Deleted
Links
(f)irst change
(n)ext change
(t)op

nn1import ast
2import inspect
1import re3import re
n2import inspectn4from types import ModuleType
3from itertools import permutations5 
46
5class BridgeKeeper:7class BridgeKeeper:
6    def __init__(self, module_name) -> None:8    def __init__(self, module_name) -> None:
7        self.module_name = module_name9        self.module_name = module_name
810
9    @staticmethod11    @staticmethod
n10    def __check_for_attributes(obj) -> bool:n12    def _check_for_attributes(obj) -> bool:
11        for arg in obj.__dir__():13        for arg in obj.__dir__():
n12            if (not re.match(r"[aeiou]{4,}", arg) and n14            if (not re.match(r"[aeiou]{4,}", arg) and
13                not re.match(r"^__.+__$", arg) and 15                    not re.match(r"^__.+__$", arg) and
14                not list(filter(lambda x: x.isalpha(), list(arg)))[-1].islower()): 16                    not list(filter(lambda x: x.isalpha(), list(arg)))[-1].islower()):
15                return True17                return True
16        return False18        return False
1719
18    @staticmethod20    @staticmethod
n19    def __check_for_name(obj) -> bool:n21    def _check_for_name(obj) -> bool:
20        return "__name__" in obj.__dir__() and obj.__name__[0].isupper()22        return "__name__" in obj.__dir__() and obj.__name__[0].isupper()
n21    n23 
22    @staticmethod24    @staticmethod
n23    def __check_for_quest(obj) -> bool:n25    def _check_for_quest(obj) -> bool:
2426
25        def convert_doctype(doctype: str) -> object:27        def convert_doctype(doctype: str) -> object:
26            help_values = {28            help_values = {
n27            "int": 1,n29                "int": 1,
28            "float": 1.2,30                "float": 1.2,
29            "str": "'string'",31                "str": "'string'",
30            "bool": True,32                "bool": True,
31            }33            }
3234
33            if not doctype.startswith('dict'):35            if not doctype.startswith('dict'):
34                doctype = doctype.replace("[", "((")36                doctype = doctype.replace("[", "((")
35                doctype = doctype.replace("]", ",))")37                doctype = doctype.replace("]", ",))")
36            else:38            else:
37                doctype = doctype.replace("[", "([(")39                doctype = doctype.replace("[", "([(")
38                doctype = doctype.replace("]", ")])")40                doctype = doctype.replace("]", ")])")
n39            for type, value in help_values.items():n41            for key, value in help_values.items():
40                doctype = doctype.replace(type, str(value))42                doctype = doctype.replace(key, str(value))
41            43 
42            return eval(doctype)44            return ast.literal_eval(doctype)
43    45 
44        if "__call__" in dir(obj):46        if "__call__" in dir(obj):
45            doc_string = obj.__doc__47            doc_string = obj.__doc__
46            if inspect.isfunction(obj):48            if inspect.isfunction(obj):
47                func_args = obj.__code__.co_varnames49                func_args = obj.__code__.co_varnames
48            else:50            else:
49                func_args = obj.__init__.__code__.co_varnames51                func_args = obj.__init__.__code__.co_varnames
50        else:52        else:
51            return False53            return False
n52        n54 
53        doc_args = re.search(r"(?<=Parameters\n----------\n).+(?=\n\n|\n$|$)", doc_string, re.S)55        doc_args = re.search(r"(?s)(?<=Parameters\n----------\n).+(?=\n\n|\n$|$)",
56                             "\n".join(list(map(lambda x: x.strip(), doc_string.split("\n")))))
54        test_params = [[]]57        test_params = [[]]
55        if doc_args:58        if doc_args:
56            for arg in filter(lambda x: " : " in x, doc_args.group().split("\n")):59            for arg in filter(lambda x: " : " in x, doc_args.group().split("\n")):
57                kvp = arg.split(" : ")60                kvp = arg.split(" : ")
58                name, types = kvp61                name, types = kvp
59                if name not in func_args:62                if name not in func_args:
60                    return False63                    return False
61                types = types.split(" | ")64                types = types.split(" | ")
n62                test_params = [test + [convert_doctype(type)] for type in types for test in test_params]n65                test_params = [test + [convert_doctype(_type)] for _type in types for test in test_params]
63        66 
64        try: 67        try:
65            for params in test_params:  68            for params in test_params:
66                obj(*params)69                obj(*params)
n67        except:n70        except (ValueError, TypeError):
68            return False  71            return False
69        72 
70        return True73        return True
n71    n74 
72    def __enter__(self):75    def __enter__(self) -> ModuleType:
73        module = __import__(self.module_name)76        module = __import__(self.module_name)
74        for obj_name in module.__dir__():77        for obj_name in module.__dir__():
75            obj = getattr(module, obj_name)78            obj = getattr(module, obj_name)
n76            if (not self.__check_for_name(obj) or n79            if "__call__" in obj.__dir__() and (not self._check_for_name(obj) or
77                not self.__check_for_attributes(obj) or 80                                                not self._check_for_attributes(obj) or
78                not self.__check_for_quest(obj)):81                                                not self._check_for_quest(obj)):
79                delattr(module, obj_name)82                delattr(module, obj_name)
80        return module83        return module
8184
82    def __exit__(self, exc_type, exc, tb):85    def __exit__(self, exc_type, exc, tb):
83        pass86        pass
8487
8588
86if __name__ == "__main__":89if __name__ == "__main__":
87    with BridgeKeeper("tests") as filtered_module:90    with BridgeKeeper("tests") as filtered_module:
t88        filtered_module.baba(5, 'banichka')t91        print(filtered_module.baba(5, 'banichka'))
89        # filtered_module.dyado    # Хвърля се AttributeError, защото dyado не отговаря на въпроси 1 и 392        filtered_module.dyado  # Хвърля се AttributeError, защото dyado не отговаря на въпроси 1 и 3
90        filtered_module.strinka  # Хвърля се AttributeError, защото strinka не може да бъде извикана успешно с аргументите, описани в docstring-а93        filtered_module.strinka  # Хвърля се AttributeError, защото strinka не може да бъде извикана успешно с аргументите, описани в docstring-а
91        pass94        pass
Legends
Colors
 Added 
Changed
Deleted
Links
(f)irst change
(n)ext change
(t)op

f1import ref1import re
2import inspect2import inspect
nn3from itertools import permutations
34
4class BridgeKeeper:5class BridgeKeeper:
5    def __init__(self, module_name) -> None:6    def __init__(self, module_name) -> None:
6        self.module_name = module_name7        self.module_name = module_name
78
8    @staticmethod9    @staticmethod
9    def __check_for_attributes(obj) -> bool:10    def __check_for_attributes(obj) -> bool:
10        for arg in obj.__dir__():11        for arg in obj.__dir__():
11            if (not re.match(r"[aeiou]{4,}", arg) and 12            if (not re.match(r"[aeiou]{4,}", arg) and 
12                not re.match(r"^__.+__$", arg) and 13                not re.match(r"^__.+__$", arg) and 
13                not list(filter(lambda x: x.isalpha(), list(arg)))[-1].islower()): 14                not list(filter(lambda x: x.isalpha(), list(arg)))[-1].islower()): 
14                return True15                return True
15        return False16        return False
1617
17    @staticmethod18    @staticmethod
18    def __check_for_name(obj) -> bool:19    def __check_for_name(obj) -> bool:
19        return "__name__" in obj.__dir__() and obj.__name__[0].isupper()20        return "__name__" in obj.__dir__() and obj.__name__[0].isupper()
20    21    
21    @staticmethod22    @staticmethod
22    def __check_for_quest(obj) -> bool:23    def __check_for_quest(obj) -> bool:
2324
n24        def convert_doctype_to_type(doctype: str) -> object:n25        def convert_doctype(doctype: str) -> object:
25            help_values = {26            help_values = {
26            "int": 1,27            "int": 1,
27            "float": 1.2,28            "float": 1.2,
28            "str": "'string'",29            "str": "'string'",
29            "bool": True,30            "bool": True,
30            }31            }
3132
32            if not doctype.startswith('dict'):33            if not doctype.startswith('dict'):
33                doctype = doctype.replace("[", "((")34                doctype = doctype.replace("[", "((")
34                doctype = doctype.replace("]", ",))")35                doctype = doctype.replace("]", ",))")
35            else:36            else:
36                doctype = doctype.replace("[", "([(")37                doctype = doctype.replace("[", "([(")
37                doctype = doctype.replace("]", ")])")38                doctype = doctype.replace("]", ")])")
38            for type, value in help_values.items():39            for type, value in help_values.items():
39                doctype = doctype.replace(type, str(value))40                doctype = doctype.replace(type, str(value))
40            41            
41            return eval(doctype)42            return eval(doctype)
42    43    
43        if "__call__" in dir(obj):44        if "__call__" in dir(obj):
44            doc_string = obj.__doc__45            doc_string = obj.__doc__
45            if inspect.isfunction(obj):46            if inspect.isfunction(obj):
46                func_args = obj.__code__.co_varnames47                func_args = obj.__code__.co_varnames
47            else:48            else:
48                func_args = obj.__init__.__code__.co_varnames49                func_args = obj.__init__.__code__.co_varnames
49        else:50        else:
50            return False51            return False
51        52        
52        doc_args = re.search(r"(?<=Parameters\n----------\n).+(?=\n\n|\n$|$)", doc_string, re.S)53        doc_args = re.search(r"(?<=Parameters\n----------\n).+(?=\n\n|\n$|$)", doc_string, re.S)
53        test_params = [[]]54        test_params = [[]]
54        if doc_args:55        if doc_args:
55            for arg in filter(lambda x: " : " in x, doc_args.group().split("\n")):56            for arg in filter(lambda x: " : " in x, doc_args.group().split("\n")):
56                kvp = arg.split(" : ")57                kvp = arg.split(" : ")
57                name, types = kvp58                name, types = kvp
58                if name not in func_args:59                if name not in func_args:
59                    return False60                    return False
60                types = types.split(" | ")61                types = types.split(" | ")
t61                test_params *= len(types)t62                test_params = [test + [convert_doctype(type)] for type in types for test in test_params]
62                for i, type in enumerate(types):
63                    test_params[i].append(convert_doctype_to_type(type))
64        63        
65        try: 64        try: 
66            for params in test_params:  65            for params in test_params:  
67                obj(*params)66                obj(*params)
68        except:67        except:
69            return False  68            return False  
70        69        
71        return True70        return True
72    71    
73    def __enter__(self):72    def __enter__(self):
74        module = __import__(self.module_name)73        module = __import__(self.module_name)
75        for obj_name in module.__dir__():74        for obj_name in module.__dir__():
76            obj = getattr(module, obj_name)75            obj = getattr(module, obj_name)
77            if (not self.__check_for_name(obj) or 76            if (not self.__check_for_name(obj) or 
78                not self.__check_for_attributes(obj) or 77                not self.__check_for_attributes(obj) or 
79                not self.__check_for_quest(obj)):78                not self.__check_for_quest(obj)):
80                delattr(module, obj_name)79                delattr(module, obj_name)
81        return module80        return module
8281
83    def __exit__(self, exc_type, exc, tb):82    def __exit__(self, exc_type, exc, tb):
84        pass83        pass
8584
8685
87if __name__ == "__main__":86if __name__ == "__main__":
88    with BridgeKeeper("tests") as filtered_module:87    with BridgeKeeper("tests") as filtered_module:
89        filtered_module.baba(5, 'banichka')88        filtered_module.baba(5, 'banichka')
90        # filtered_module.dyado    # Хвърля се AttributeError, защото dyado не отговаря на въпроси 1 и 389        # filtered_module.dyado    # Хвърля се AttributeError, защото dyado не отговаря на въпроси 1 и 3
91        filtered_module.strinka  # Хвърля се AttributeError, защото strinka не може да бъде извикана успешно с аргументите, описани в docstring-а90        filtered_module.strinka  # Хвърля се AttributeError, защото strinka не може да бъде извикана успешно с аргументите, описани в docstring-а
92        pass91        pass
Legends
Colors
 Added 
Changed
Deleted
Links
(f)irst change
(n)ext change
(t)op

f1import ref1import re
2import inspect2import inspect
33
4class BridgeKeeper:4class BridgeKeeper:
5    def __init__(self, module_name) -> None:5    def __init__(self, module_name) -> None:
6        self.module_name = module_name6        self.module_name = module_name
77
8    @staticmethod8    @staticmethod
9    def __check_for_attributes(obj) -> bool:9    def __check_for_attributes(obj) -> bool:
10        for arg in obj.__dir__():10        for arg in obj.__dir__():
11            if (not re.match(r"[aeiou]{4,}", arg) and 11            if (not re.match(r"[aeiou]{4,}", arg) and 
12                not re.match(r"^__.+__$", arg) and 12                not re.match(r"^__.+__$", arg) and 
n13                list(filter(lambda x: x.isalpha(), list(arg)))[-1].isupper()): n13                not list(filter(lambda x: x.isalpha(), list(arg)))[-1].islower()): 
14                return True14                return True
15        return False15        return False
1616
17    @staticmethod17    @staticmethod
18    def __check_for_name(obj) -> bool:18    def __check_for_name(obj) -> bool:
19        return "__name__" in obj.__dir__() and obj.__name__[0].isupper()19        return "__name__" in obj.__dir__() and obj.__name__[0].isupper()
20    20    
21    @staticmethod21    @staticmethod
22    def __check_for_quest(obj) -> bool:22    def __check_for_quest(obj) -> bool:
2323
24        def convert_doctype_to_type(doctype: str) -> object:24        def convert_doctype_to_type(doctype: str) -> object:
25            help_values = {25            help_values = {
26            "int": 1,26            "int": 1,
27            "float": 1.2,27            "float": 1.2,
28            "str": "'string'",28            "str": "'string'",
29            "bool": True,29            "bool": True,
30            }30            }
3131
32            if not doctype.startswith('dict'):32            if not doctype.startswith('dict'):
33                doctype = doctype.replace("[", "((")33                doctype = doctype.replace("[", "((")
34                doctype = doctype.replace("]", ",))")34                doctype = doctype.replace("]", ",))")
35            else:35            else:
36                doctype = doctype.replace("[", "([(")36                doctype = doctype.replace("[", "([(")
37                doctype = doctype.replace("]", ")])")37                doctype = doctype.replace("]", ")])")
38            for type, value in help_values.items():38            for type, value in help_values.items():
39                doctype = doctype.replace(type, str(value))39                doctype = doctype.replace(type, str(value))
40            40            
41            return eval(doctype)41            return eval(doctype)
42    42    
43        if "__call__" in dir(obj):43        if "__call__" in dir(obj):
44            doc_string = obj.__doc__44            doc_string = obj.__doc__
45            if inspect.isfunction(obj):45            if inspect.isfunction(obj):
46                func_args = obj.__code__.co_varnames46                func_args = obj.__code__.co_varnames
47            else:47            else:
48                func_args = obj.__init__.__code__.co_varnames48                func_args = obj.__init__.__code__.co_varnames
49        else:49        else:
50            return False50            return False
51        51        
52        doc_args = re.search(r"(?<=Parameters\n----------\n).+(?=\n\n|\n$|$)", doc_string, re.S)52        doc_args = re.search(r"(?<=Parameters\n----------\n).+(?=\n\n|\n$|$)", doc_string, re.S)
53        test_params = [[]]53        test_params = [[]]
54        if doc_args:54        if doc_args:
55            for arg in filter(lambda x: " : " in x, doc_args.group().split("\n")):55            for arg in filter(lambda x: " : " in x, doc_args.group().split("\n")):
56                kvp = arg.split(" : ")56                kvp = arg.split(" : ")
57                name, types = kvp57                name, types = kvp
58                if name not in func_args:58                if name not in func_args:
59                    return False59                    return False
60                types = types.split(" | ")60                types = types.split(" | ")
61                test_params *= len(types)61                test_params *= len(types)
62                for i, type in enumerate(types):62                for i, type in enumerate(types):
63                    test_params[i].append(convert_doctype_to_type(type))63                    test_params[i].append(convert_doctype_to_type(type))
t64        elif not func_args:t
65            return True
66        64        
67        try: 65        try: 
68            for params in test_params:  66            for params in test_params:  
69                obj(*params)67                obj(*params)
70        except:68        except:
71            return False  69            return False  
72        70        
73        return True71        return True
74    72    
75    def __enter__(self):73    def __enter__(self):
76        module = __import__(self.module_name)74        module = __import__(self.module_name)
77        for obj_name in module.__dir__():75        for obj_name in module.__dir__():
78            obj = getattr(module, obj_name)76            obj = getattr(module, obj_name)
79            if (not self.__check_for_name(obj) or 77            if (not self.__check_for_name(obj) or 
80                not self.__check_for_attributes(obj) or 78                not self.__check_for_attributes(obj) or 
81                not self.__check_for_quest(obj)):79                not self.__check_for_quest(obj)):
82                delattr(module, obj_name)80                delattr(module, obj_name)
83        return module81        return module
8482
85    def __exit__(self, exc_type, exc, tb):83    def __exit__(self, exc_type, exc, tb):
86        pass84        pass
8785
8886
89if __name__ == "__main__":87if __name__ == "__main__":
90    with BridgeKeeper("tests") as filtered_module:88    with BridgeKeeper("tests") as filtered_module:
91        filtered_module.baba(5, 'banichka')89        filtered_module.baba(5, 'banichka')
92        # filtered_module.dyado    # Хвърля се AttributeError, защото dyado не отговаря на въпроси 1 и 390        # filtered_module.dyado    # Хвърля се AttributeError, защото dyado не отговаря на въпроси 1 и 3
93        filtered_module.strinka  # Хвърля се AttributeError, защото strinka не може да бъде извикана успешно с аргументите, описани в docstring-а91        filtered_module.strinka  # Хвърля се AttributeError, защото strinka не може да бъде извикана успешно с аргументите, описани в docstring-а
94        pass92        pass
Legends
Colors
 Added 
Changed
Deleted
Links
(f)irst change
(n)ext change
(t)op

f1import ref1import re
2import inspect2import inspect
33
4class BridgeKeeper:4class BridgeKeeper:
5    def __init__(self, module_name) -> None:5    def __init__(self, module_name) -> None:
6        self.module_name = module_name6        self.module_name = module_name
77
8    @staticmethod8    @staticmethod
9    def __check_for_attributes(obj) -> bool:9    def __check_for_attributes(obj) -> bool:
10        for arg in obj.__dir__():10        for arg in obj.__dir__():
11            if (not re.match(r"[aeiou]{4,}", arg) and 11            if (not re.match(r"[aeiou]{4,}", arg) and 
12                not re.match(r"^__.+__$", arg) and 12                not re.match(r"^__.+__$", arg) and 
13                list(filter(lambda x: x.isalpha(), list(arg)))[-1].isupper()): 13                list(filter(lambda x: x.isalpha(), list(arg)))[-1].isupper()): 
14                return True14                return True
15        return False15        return False
1616
17    @staticmethod17    @staticmethod
18    def __check_for_name(obj) -> bool:18    def __check_for_name(obj) -> bool:
19        return "__name__" in obj.__dir__() and obj.__name__[0].isupper()19        return "__name__" in obj.__dir__() and obj.__name__[0].isupper()
20    20    
21    @staticmethod21    @staticmethod
22    def __check_for_quest(obj) -> bool:22    def __check_for_quest(obj) -> bool:
2323
24        def convert_doctype_to_type(doctype: str) -> object:24        def convert_doctype_to_type(doctype: str) -> object:
25            help_values = {25            help_values = {
26            "int": 1,26            "int": 1,
27            "float": 1.2,27            "float": 1.2,
28            "str": "'string'",28            "str": "'string'",
29            "bool": True,29            "bool": True,
30            }30            }
3131
32            if not doctype.startswith('dict'):32            if not doctype.startswith('dict'):
33                doctype = doctype.replace("[", "((")33                doctype = doctype.replace("[", "((")
34                doctype = doctype.replace("]", ",))")34                doctype = doctype.replace("]", ",))")
35            else:35            else:
36                doctype = doctype.replace("[", "([(")36                doctype = doctype.replace("[", "([(")
37                doctype = doctype.replace("]", ")])")37                doctype = doctype.replace("]", ")])")
38            for type, value in help_values.items():38            for type, value in help_values.items():
39                doctype = doctype.replace(type, str(value))39                doctype = doctype.replace(type, str(value))
40            40            
41            return eval(doctype)41            return eval(doctype)
42    42    
43        if "__call__" in dir(obj):43        if "__call__" in dir(obj):
44            doc_string = obj.__doc__44            doc_string = obj.__doc__
45            if inspect.isfunction(obj):45            if inspect.isfunction(obj):
46                func_args = obj.__code__.co_varnames46                func_args = obj.__code__.co_varnames
47            else:47            else:
48                func_args = obj.__init__.__code__.co_varnames48                func_args = obj.__init__.__code__.co_varnames
49        else:49        else:
50            return False50            return False
51        51        
52        doc_args = re.search(r"(?<=Parameters\n----------\n).+(?=\n\n|\n$|$)", doc_string, re.S)52        doc_args = re.search(r"(?<=Parameters\n----------\n).+(?=\n\n|\n$|$)", doc_string, re.S)
53        test_params = [[]]53        test_params = [[]]
54        if doc_args:54        if doc_args:
55            for arg in filter(lambda x: " : " in x, doc_args.group().split("\n")):55            for arg in filter(lambda x: " : " in x, doc_args.group().split("\n")):
56                kvp = arg.split(" : ")56                kvp = arg.split(" : ")
57                name, types = kvp57                name, types = kvp
58                if name not in func_args:58                if name not in func_args:
59                    return False59                    return False
60                types = types.split(" | ")60                types = types.split(" | ")
61                test_params *= len(types)61                test_params *= len(types)
62                for i, type in enumerate(types):62                for i, type in enumerate(types):
63                    test_params[i].append(convert_doctype_to_type(type))63                    test_params[i].append(convert_doctype_to_type(type))
64        elif not func_args:64        elif not func_args:
65            return True65            return True
66        66        
67        try: 67        try: 
n68            for param in test_params:  n68            for params in test_params:  
69                obj(*param)69                obj(*params)
70        except TypeError:70        except:
71            return False  71            return False  
72        72        
73        return True73        return True
74    74    
75    def __enter__(self):75    def __enter__(self):
76        module = __import__(self.module_name)76        module = __import__(self.module_name)
77        for obj_name in module.__dir__():77        for obj_name in module.__dir__():
78            obj = getattr(module, obj_name)78            obj = getattr(module, obj_name)
t79            if not self.__check_for_name(obj) or not self.__check_for_attributes(obj) or not self.__check_for_quest(obj):t79            if (not self.__check_for_name(obj) or 
80                not self.__check_for_attributes(obj) or 
81                not self.__check_for_quest(obj)):
80                delattr(module, obj_name)82                delattr(module, obj_name)
81        return module83        return module
8284
83    def __exit__(self, exc_type, exc, tb):85    def __exit__(self, exc_type, exc, tb):
84        pass86        pass
8587
8688
87if __name__ == "__main__":89if __name__ == "__main__":
88    with BridgeKeeper("tests") as filtered_module:90    with BridgeKeeper("tests") as filtered_module:
89        filtered_module.baba(5, 'banichka')91        filtered_module.baba(5, 'banichka')
90        # filtered_module.dyado    # Хвърля се AttributeError, защото dyado не отговаря на въпроси 1 и 392        # filtered_module.dyado    # Хвърля се AttributeError, защото dyado не отговаря на въпроси 1 и 3
91        filtered_module.strinka  # Хвърля се AttributeError, защото strinka не може да бъде извикана успешно с аргументите, описани в docstring-а93        filtered_module.strinka  # Хвърля се AttributeError, защото strinka не може да бъде извикана успешно с аргументите, описани в docstring-а
92        pass94        pass
Legends
Colors
 Added 
Changed
Deleted
Links
(f)irst change
(n)ext change
(t)op

f1import ref1import re
2import inspect2import inspect
33
4class BridgeKeeper:4class BridgeKeeper:
5    def __init__(self, module_name) -> None:5    def __init__(self, module_name) -> None:
6        self.module_name = module_name6        self.module_name = module_name
77
8    @staticmethod8    @staticmethod
9    def __check_for_attributes(obj) -> bool:9    def __check_for_attributes(obj) -> bool:
10        for arg in obj.__dir__():10        for arg in obj.__dir__():
n11            if not re.match(r"[aeiou]{4,}", arg) and not re.match(r"^__.+__$", arg) and list(filter(lambda x: x.isalpha(), list(arg)))[-1].isupper(): n11            if (not re.match(r"[aeiou]{4,}", arg) and 
12                not re.match(r"^__.+__$", arg) and 
13                list(filter(lambda x: x.isalpha(), list(arg)))[-1].isupper()): 
12                return True14                return True
13        return False15        return False
1416
15    @staticmethod17    @staticmethod
16    def __check_for_name(obj) -> bool:18    def __check_for_name(obj) -> bool:
17        return "__name__" in obj.__dir__() and obj.__name__[0].isupper()19        return "__name__" in obj.__dir__() and obj.__name__[0].isupper()
18    20    
19    @staticmethod21    @staticmethod
20    def __check_for_quest(obj) -> bool:22    def __check_for_quest(obj) -> bool:
2123
22        def convert_doctype_to_type(doctype: str) -> object:24        def convert_doctype_to_type(doctype: str) -> object:
23            help_values = {25            help_values = {
24            "int": 1,26            "int": 1,
25            "float": 1.2,27            "float": 1.2,
26            "str": "'string'",28            "str": "'string'",
27            "bool": True,29            "bool": True,
28            }30            }
2931
30            if not doctype.startswith('dict'):32            if not doctype.startswith('dict'):
31                doctype = doctype.replace("[", "((")33                doctype = doctype.replace("[", "((")
32                doctype = doctype.replace("]", ",))")34                doctype = doctype.replace("]", ",))")
33            else:35            else:
34                doctype = doctype.replace("[", "([(")36                doctype = doctype.replace("[", "([(")
35                doctype = doctype.replace("]", ")])")37                doctype = doctype.replace("]", ")])")
36            for type, value in help_values.items():38            for type, value in help_values.items():
37                doctype = doctype.replace(type, str(value))39                doctype = doctype.replace(type, str(value))
38            40            
39            return eval(doctype)41            return eval(doctype)
40    42    
41        if "__call__" in dir(obj):43        if "__call__" in dir(obj):
42            doc_string = obj.__doc__44            doc_string = obj.__doc__
43            if inspect.isfunction(obj):45            if inspect.isfunction(obj):
44                func_args = obj.__code__.co_varnames46                func_args = obj.__code__.co_varnames
45            else:47            else:
46                func_args = obj.__init__.__code__.co_varnames48                func_args = obj.__init__.__code__.co_varnames
47        else:49        else:
48            return False50            return False
49        51        
n50        doc_args = re.search(r"(?<=Parameters\n----------\n).+(?=\n\n|$)", doc_string, re.S)n52        doc_args = re.search(r"(?<=Parameters\n----------\n).+(?=\n\n|\n$|$)", doc_string, re.S)
51        test_params = [[]]53        test_params = [[]]
52        if doc_args:54        if doc_args:
53            for arg in filter(lambda x: " : " in x, doc_args.group().split("\n")):55            for arg in filter(lambda x: " : " in x, doc_args.group().split("\n")):
54                kvp = arg.split(" : ")56                kvp = arg.split(" : ")
55                name, types = kvp57                name, types = kvp
56                if name not in func_args:58                if name not in func_args:
57                    return False59                    return False
58                types = types.split(" | ")60                types = types.split(" | ")
59                test_params *= len(types)61                test_params *= len(types)
60                for i, type in enumerate(types):62                for i, type in enumerate(types):
61                    test_params[i].append(convert_doctype_to_type(type))63                    test_params[i].append(convert_doctype_to_type(type))
62        elif not func_args:64        elif not func_args:
63            return True65            return True
64        66        
65        try: 67        try: 
66            for param in test_params:  68            for param in test_params:  
67                obj(*param)69                obj(*param)
t68        except :t70        except TypeError:
69            return False  71            return False  
70        72        
71        return True73        return True
72    74    
73    def __enter__(self):75    def __enter__(self):
74        module = __import__(self.module_name)76        module = __import__(self.module_name)
75        for obj_name in module.__dir__():77        for obj_name in module.__dir__():
76            obj = getattr(module, obj_name)78            obj = getattr(module, obj_name)
77            if not self.__check_for_name(obj) or not self.__check_for_attributes(obj) or not self.__check_for_quest(obj):79            if not self.__check_for_name(obj) or not self.__check_for_attributes(obj) or not self.__check_for_quest(obj):
78                delattr(module, obj_name)80                delattr(module, obj_name)
79        return module81        return module
8082
81    def __exit__(self, exc_type, exc, tb):83    def __exit__(self, exc_type, exc, tb):
82        pass84        pass
8385
8486
85if __name__ == "__main__":87if __name__ == "__main__":
86    with BridgeKeeper("tests") as filtered_module:88    with BridgeKeeper("tests") as filtered_module:
87        filtered_module.baba(5, 'banichka')89        filtered_module.baba(5, 'banichka')
88        # filtered_module.dyado    # Хвърля се AttributeError, защото dyado не отговаря на въпроси 1 и 390        # filtered_module.dyado    # Хвърля се AttributeError, защото dyado не отговаря на въпроси 1 и 3
89        filtered_module.strinka  # Хвърля се AttributeError, защото strinka не може да бъде извикана успешно с аргументите, описани в docstring-а91        filtered_module.strinka  # Хвърля се AttributeError, защото strinka не може да бъде извикана успешно с аргументите, описани в docstring-а
90        pass92        pass
Legends
Colors
 Added 
Changed
Deleted
Links
(f)irst change
(n)ext change
(t)op