Предизвикателства > Abomination decorator > Решения > Решението на Надежда Донева

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

1 точки общо

1 успешни теста
3 неуспешни теста
Код

 1def check_types(value, expected_types, error_message):
 2    """Check the type and print error message."""
 3    if not isinstance(value, expected_types):
 4        types_str = ", ".join(str(t) for t in expected_types)
 5        print(error_message.format(types_str))
 6        return False 
 7    return True  
 8
 9def check_input_types(args, kwargs, expected_types):
10    """Check the types of args and kwargs."""
11    valid = True
12    for arg in args:
13        if not check_types(arg, expected_types, "Invalid input arguments, expected {}!"):
14            valid = False
15    
16    for key, value in kwargs.items():
17        if not check_types(value, expected_types, f"Invalid input argument '{key}', expected {{}}!"):
18            valid = False
19    
20    return valid
21
22def type_check(mode):
23    def decorator(*expected_types):
24        def wrapper(func):
25            def inner(*args, **kwargs):
26                if mode == "in":
27                    if not check_input_types(args, kwargs, expected_types):
28                        return None
29                result = func(*args, **kwargs)
30                
31                if mode == "out":
32                    if not check_types(result, expected_types, "Invalid output value, expected {}!"):
33                        return result 
34                
35                return result
36            return inner
37        return wrapper
38    return decorator
39
40
41@type_check("in")(int, float)
42@type_check("out")(int, float)
43def power(num, power):
44    return num ** power
45
46print(power(6j, 2)) 
47@type_check("in")(str)
48def concatenate(*strings, separator=' beep boop '):
49    return separator.join(strings)
50
51print(concatenate(5, '6'))

Invalid input arguments, expected <class 'int'>, <class 'float'>!
None
Invalid input arguments, expected <class 'str'>!
None
FFF.
======================================================================
FAIL: test_check_both (test.TestTypeCheck.test_check_both)
The decorator should report invalid "in" and "out" together.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/usr/lib/python3.12/unittest/mock.py", line 1390, in patched
return func(*newargs, **newkeywargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/test.py", line 98, in test_check_both
mock_print.assert_has_calls(
File "/usr/lib/python3.12/unittest/mock.py", line 981, in assert_has_calls
raise AssertionError(
AssertionError: Calls not found.
Expected: [call("Invalid input arguments, expected <class 'float'>!"),
call("Invalid output value, expected <class 'int'>!")]
Actual: [call("Invalid input arguments, expected <class 'float'>!"),
call("Invalid input arguments, expected <class 'float'>!"),
call("Invalid input argument 'pirates', expected <class 'float'>!"),
call("Invalid output value, expected <class 'int'>!")]

======================================================================
FAIL: test_check_decorated_exception (test.TestTypeCheck.test_check_decorated_exception)
The decorator should not supress any exceptions raised.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/usr/lib/python3.12/unittest/mock.py", line 1390, in patched
return func(*newargs, **newkeywargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/test.py", line 110, in test_check_decorated_exception
with self.assertRaises(ZeroDivisionError):
AssertionError: ZeroDivisionError not raised

======================================================================
FAIL: test_check_in (test.TestTypeCheck.test_check_in)
The decorator should report invalid "in" arguments.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/usr/lib/python3.12/unittest/mock.py", line 1390, in patched
return func(*newargs, **newkeywargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/test.py", line 43, in test_check_in
self.assertEqual(mock_print.call_count, 1)
AssertionError: 2 != 1

----------------------------------------------------------------------
Ran 4 tests in 0.003s

FAILED (failures=3)

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