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

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

4 точки общо

19 успешни теста
6 неуспешни теста
Код

 1import re
 2import inspect
 3import builtins
 4
 5_SAFE_BUILTINS = {name: obj for name, obj in vars(builtins).items() if isinstance(obj, type)}
 6
 7
 8def _default_for(type_str):
 9    type_str = type_str.strip()
10
11    if '|' in type_str:
12        return _default_for(type_str.split('|')[0])
13
14    match = re.match(r'^(\w+)\[', type_str)
15    type_name = match.group(1) if match else type_str
16
17    if type_name == 'None':
18        return None
19
20    try:  # Code Injection - Try me bitch
21        return eval(type_name, {"__builtins__": _SAFE_BUILTINS})()
22    except Exception as e:
23        raise AttributeError(f"'{type_name}' is not a valid built-in type") from e
24
25
26def _parse_params(docstring):
27    if not docstring:
28        return []
29
30    docstring = inspect.cleandoc(docstring)
31    match = re.search(r'Parameters\n-{10}\n(.*?)(\n\n|$)', docstring, re.DOTALL)
32
33    if not match:
34        return []
35
36    variable_block = match.group(1)
37    # Returns list of the types of all variables
38    return re.findall(r'^\w+\s*:\s*(.+)$', variable_block, re.MULTILINE)
39
40
41class FilteredModule:
42    def __init__(self, module):
43        self.__module = module
44
45    def __getattr__(self, name):
46        if not hasattr(self.__module, name):
47            raise AttributeError(f"Module has no attribute '{name}'")
48
49        obj = getattr(self.__module, name)
50
51        self.__check_name(obj)
52        self.__check_callable(obj)
53        self.__check_attribute(obj)
54
55        return obj
56
57    @staticmethod
58    def __check_name(obj):
59        if not hasattr(obj, '__name__') or not obj.__name__[0].isupper():
60            raise AttributeError(
61                f"'{getattr(obj, '__name__', repr(obj))}' failed question 1: __name__ must start with uppercase")
62
63    @staticmethod
64    def __check_callable(obj):
65        params = _parse_params(obj.__doc__)
66        args = [_default_for(type_str) for type_str in params]
67
68        try:
69            obj(*args)
70        except Exception as e:
71            raise AttributeError(f"'{obj.__name__}' failed question 2: call failed or not callable") from e
72
73    @staticmethod
74    def __check_attribute(obj):
75        for attr in vars(obj).keys():
76            # Skip if dunder OR contains 4+ consecutive vowels OR last letter isn't uppercase
77            if (re.search(r'^__.*__$', attr) or re.search(r'[aeiouAEIOU]{4,}', attr) or
78                    not re.search(r'[A-Z][^a-zA-Z]*$', attr)):
79                continue
80            return
81
82        raise AttributeError(f"'{obj.__name__}' failed question 3: no valid attribute found")
83
84
85class BridgeKeeper:
86    def __init__(self, module_name):
87        self.module_name = module_name
88
89    def __enter__(self):
90        self.module = __import__(self.module_name)
91        return FilteredModule(self.module)
92
93    def __exit__(self, exc_type, exc_val, exc_tb):
94        return False

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

======================================================================
FAIL: test_rejects_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 90, in test_rejects_dict_when_callable_does_not_work_with_documented_key_and_value_types
with self.assertRaises(AttributeError):
~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^
AssertionError: AttributeError not raised

======================================================================
FAIL: 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 102, in test_rejects_list_when_callable_does_not_work_with_documented_element_type
with self.assertRaises(AttributeError):
~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^
AssertionError: AttributeError not raised

======================================================================
FAIL: 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 112, in test_rejects_set_when_callable_does_not_work_with_documented_element_type
with self.assertRaises(AttributeError):
~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^
AssertionError: AttributeError not raised

======================================================================
FAIL: 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 107, in test_rejects_tuple_when_callable_does_not_work_with_documented_element_type
with self.assertRaises(AttributeError):
~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^
AssertionError: AttributeError not raised

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

----------------------------------------------------------------------
Ran 25 tests in 0.003s

FAILED (failures=6)

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

f1import ref1import re
2import inspect2import inspect
3import builtins3import builtins
44
5_SAFE_BUILTINS = {name: obj for name, obj in vars(builtins).items() if isinstance(obj, type)}5_SAFE_BUILTINS = {name: obj for name, obj in vars(builtins).items() if isinstance(obj, type)}
66
77
8def _default_for(type_str):8def _default_for(type_str):
9    type_str = type_str.strip()9    type_str = type_str.strip()
1010
11    if '|' in type_str:11    if '|' in type_str:
12        return _default_for(type_str.split('|')[0])12        return _default_for(type_str.split('|')[0])
1313
14    match = re.match(r'^(\w+)\[', type_str)14    match = re.match(r'^(\w+)\[', type_str)
15    type_name = match.group(1) if match else type_str15    type_name = match.group(1) if match else type_str
1616
17    if type_name == 'None':17    if type_name == 'None':
18        return None18        return None
1919
20    try:  # Code Injection - Try me bitch20    try:  # Code Injection - Try me bitch
21        return eval(type_name, {"__builtins__": _SAFE_BUILTINS})()21        return eval(type_name, {"__builtins__": _SAFE_BUILTINS})()
22    except Exception as e:22    except Exception as e:
23        raise AttributeError(f"'{type_name}' is not a valid built-in type") from e23        raise AttributeError(f"'{type_name}' is not a valid built-in type") from e
2424
2525
26def _parse_params(docstring):26def _parse_params(docstring):
27    if not docstring:27    if not docstring:
28        return []28        return []
2929
30    docstring = inspect.cleandoc(docstring)30    docstring = inspect.cleandoc(docstring)
t31    match = re.search(r'Parameters\n----------\n(.*?)(\n\n|$)', docstring, re.DOTALL)t31    match = re.search(r'Parameters\n-{10}\n(.*?)(\n\n|$)', docstring, re.DOTALL)
3232
33    if not match:33    if not match:
34        return []34        return []
3535
36    variable_block = match.group(1)36    variable_block = match.group(1)
37    # Returns list of the types of all variables37    # Returns list of the types of all variables
38    return re.findall(r'^\w+\s*:\s*(.+)$', variable_block, re.MULTILINE)38    return re.findall(r'^\w+\s*:\s*(.+)$', variable_block, re.MULTILINE)
3939
4040
41class FilteredModule:41class FilteredModule:
42    def __init__(self, module):42    def __init__(self, module):
43        self.__module = module43        self.__module = module
4444
45    def __getattr__(self, name):45    def __getattr__(self, name):
46        if not hasattr(self.__module, name):46        if not hasattr(self.__module, name):
47            raise AttributeError(f"Module has no attribute '{name}'")47            raise AttributeError(f"Module has no attribute '{name}'")
4848
49        obj = getattr(self.__module, name)49        obj = getattr(self.__module, name)
5050
51        self.__check_name(obj)51        self.__check_name(obj)
52        self.__check_callable(obj)52        self.__check_callable(obj)
53        self.__check_attribute(obj)53        self.__check_attribute(obj)
5454
55        return obj55        return obj
5656
57    @staticmethod57    @staticmethod
58    def __check_name(obj):58    def __check_name(obj):
59        if not hasattr(obj, '__name__') or not obj.__name__[0].isupper():59        if not hasattr(obj, '__name__') or not obj.__name__[0].isupper():
60            raise AttributeError(60            raise AttributeError(
61                f"'{getattr(obj, '__name__', repr(obj))}' failed question 1: __name__ must start with uppercase")61                f"'{getattr(obj, '__name__', repr(obj))}' failed question 1: __name__ must start with uppercase")
6262
63    @staticmethod63    @staticmethod
64    def __check_callable(obj):64    def __check_callable(obj):
65        params = _parse_params(obj.__doc__)65        params = _parse_params(obj.__doc__)
66        args = [_default_for(type_str) for type_str in params]66        args = [_default_for(type_str) for type_str in params]
6767
68        try:68        try:
69            obj(*args)69            obj(*args)
70        except Exception as e:70        except Exception as e:
71            raise AttributeError(f"'{obj.__name__}' failed question 2: call failed or not callable") from e71            raise AttributeError(f"'{obj.__name__}' failed question 2: call failed or not callable") from e
7272
73    @staticmethod73    @staticmethod
74    def __check_attribute(obj):74    def __check_attribute(obj):
75        for attr in vars(obj).keys():75        for attr in vars(obj).keys():
76            # Skip if dunder OR contains 4+ consecutive vowels OR last letter isn't uppercase76            # Skip if dunder OR contains 4+ consecutive vowels OR last letter isn't uppercase
77            if (re.search(r'^__.*__$', attr) or re.search(r'[aeiouAEIOU]{4,}', attr) or77            if (re.search(r'^__.*__$', attr) or re.search(r'[aeiouAEIOU]{4,}', attr) or
78                    not re.search(r'[A-Z][^a-zA-Z]*$', attr)):78                    not re.search(r'[A-Z][^a-zA-Z]*$', attr)):
79                continue79                continue
80            return80            return
8181
82        raise AttributeError(f"'{obj.__name__}' failed question 3: no valid attribute found")82        raise AttributeError(f"'{obj.__name__}' failed question 3: no valid attribute found")
8383
8484
85class BridgeKeeper:85class BridgeKeeper:
86    def __init__(self, module_name):86    def __init__(self, module_name):
87        self.module_name = module_name87        self.module_name = module_name
8888
89    def __enter__(self):89    def __enter__(self):
90        self.module = __import__(self.module_name)90        self.module = __import__(self.module_name)
91        return FilteredModule(self.module)91        return FilteredModule(self.module)
9292
93    def __exit__(self, exc_type, exc_val, exc_tb):93    def __exit__(self, exc_type, exc_val, exc_tb):
94        return False94        return False
Legends
Colors
 Added 
Changed
Deleted
Links
(f)irst change
(n)ext change
(t)op

f1import ref1import re
2import inspect2import inspect
3import builtins3import builtins
44
t5_SAFE_BUILTINS = {t5_SAFE_BUILTINS = {name: obj for name, obj in vars(builtins).items() if isinstance(obj, type)}
6    name: obj
7    for name, obj in vars(builtins).items()
8    if isinstance(obj, type)
9}
106
117
12def _default_for(type_str):8def _default_for(type_str):
13    type_str = type_str.strip()9    type_str = type_str.strip()
1410
15    if '|' in type_str:11    if '|' in type_str:
16        return _default_for(type_str.split('|')[0])12        return _default_for(type_str.split('|')[0])
1713
18    match = re.match(r'^(\w+)\[', type_str)14    match = re.match(r'^(\w+)\[', type_str)
19    type_name = match.group(1) if match else type_str15    type_name = match.group(1) if match else type_str
2016
21    if type_name == 'None':17    if type_name == 'None':
22        return None18        return None
2319
24    try:  # Code Injection - Try me bitch20    try:  # Code Injection - Try me bitch
25        return eval(type_name, {"__builtins__": _SAFE_BUILTINS})()21        return eval(type_name, {"__builtins__": _SAFE_BUILTINS})()
26    except Exception as e:22    except Exception as e:
27        raise AttributeError(f"'{type_name}' is not a valid built-in type") from e23        raise AttributeError(f"'{type_name}' is not a valid built-in type") from e
2824
2925
30def _parse_params(docstring):26def _parse_params(docstring):
31    if not docstring:27    if not docstring:
32        return []28        return []
3329
34    docstring = inspect.cleandoc(docstring)30    docstring = inspect.cleandoc(docstring)
35    match = re.search(r'Parameters\n----------\n(.*?)(\n\n|$)', docstring, re.DOTALL)31    match = re.search(r'Parameters\n----------\n(.*?)(\n\n|$)', docstring, re.DOTALL)
3632
37    if not match:33    if not match:
38        return []34        return []
3935
40    variable_block = match.group(1)36    variable_block = match.group(1)
41    # Returns list of the types of all variables37    # Returns list of the types of all variables
42    return re.findall(r'^\w+\s*:\s*(.+)$', variable_block, re.MULTILINE)38    return re.findall(r'^\w+\s*:\s*(.+)$', variable_block, re.MULTILINE)
4339
4440
45class FilteredModule:41class FilteredModule:
46    def __init__(self, module):42    def __init__(self, module):
47        self.__module = module43        self.__module = module
4844
49    def __getattr__(self, name):45    def __getattr__(self, name):
50        if not hasattr(self.__module, name):46        if not hasattr(self.__module, name):
51            raise AttributeError(f"Module has no attribute '{name}'")47            raise AttributeError(f"Module has no attribute '{name}'")
5248
53        obj = getattr(self.__module, name)49        obj = getattr(self.__module, name)
5450
55        self.__check_name(obj)51        self.__check_name(obj)
56        self.__check_callable(obj)52        self.__check_callable(obj)
57        self.__check_attribute(obj)53        self.__check_attribute(obj)
5854
59        return obj55        return obj
6056
61    @staticmethod57    @staticmethod
62    def __check_name(obj):58    def __check_name(obj):
63        if not hasattr(obj, '__name__') or not obj.__name__[0].isupper():59        if not hasattr(obj, '__name__') or not obj.__name__[0].isupper():
64            raise AttributeError(60            raise AttributeError(
65                f"'{getattr(obj, '__name__', repr(obj))}' failed question 1: __name__ must start with uppercase")61                f"'{getattr(obj, '__name__', repr(obj))}' failed question 1: __name__ must start with uppercase")
6662
67    @staticmethod63    @staticmethod
68    def __check_callable(obj):64    def __check_callable(obj):
69        params = _parse_params(obj.__doc__)65        params = _parse_params(obj.__doc__)
70        args = [_default_for(type_str) for type_str in params]66        args = [_default_for(type_str) for type_str in params]
7167
72        try:68        try:
73            obj(*args)69            obj(*args)
74        except Exception as e:70        except Exception as e:
75            raise AttributeError(f"'{obj.__name__}' failed question 2: call failed or not callable") from e71            raise AttributeError(f"'{obj.__name__}' failed question 2: call failed or not callable") from e
7672
77    @staticmethod73    @staticmethod
78    def __check_attribute(obj):74    def __check_attribute(obj):
79        for attr in vars(obj).keys():75        for attr in vars(obj).keys():
80            # Skip if dunder OR contains 4+ consecutive vowels OR last letter isn't uppercase76            # Skip if dunder OR contains 4+ consecutive vowels OR last letter isn't uppercase
81            if (re.search(r'^__.*__$', attr) or re.search(r'[aeiouAEIOU]{4,}', attr) or77            if (re.search(r'^__.*__$', attr) or re.search(r'[aeiouAEIOU]{4,}', attr) or
82                    not re.search(r'[A-Z][^a-zA-Z]*$', attr)):78                    not re.search(r'[A-Z][^a-zA-Z]*$', attr)):
83                continue79                continue
84            return80            return
8581
86        raise AttributeError(f"'{obj.__name__}' failed question 3: no valid attribute found")82        raise AttributeError(f"'{obj.__name__}' failed question 3: no valid attribute found")
8783
8884
89class BridgeKeeper:85class BridgeKeeper:
90    def __init__(self, module_name):86    def __init__(self, module_name):
91        self.module_name = module_name87        self.module_name = module_name
9288
93    def __enter__(self):89    def __enter__(self):
94        self.module = __import__(self.module_name)90        self.module = __import__(self.module_name)
95        return FilteredModule(self.module)91        return FilteredModule(self.module)
9692
97    def __exit__(self, exc_type, exc_val, exc_tb):93    def __exit__(self, exc_type, exc_val, exc_tb):
98        return False94        return False
Legends
Colors
 Added 
Changed
Deleted
Links
(f)irst change
(n)ext change
(t)op