Passed
Push — master ( 16e282...dc8133 )
by Ramon
56s queued 11s
created

test_resources.hintable.C.__init__()   A

Complexity

Conditions 1

Size

Total Lines 2
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nop 2
dl 0
loc 2
rs 10
c 0
b 0
f 0
1
from typing import Type
2
from unittest import TestCase
3
4
from typish import T, hintable
5
6
7
class C:
8
    def __init__(self, subject):
9
        self.subject = subject
10
11
12
@hintable
13
def cast(subject, hint: Type[T]) -> T:
14
    return hint(subject)
15
16
17
@hintable
18
def some_func(hint: Type[T]) -> Type[T]:
19
    """Some docstring"""
20
    return hint
21
22
23
@hintable(param='cls')
24
def some_func_with_custom_param_name(cls):
25
    return cls
26
27
28
class SomeClass:
29
    @hintable
30
    def some_method(self, hint):
31
        return hint
32
33
    @staticmethod
34
    @hintable
35
    def some_static_method(hint):
36
        return hint
37
38
    @classmethod
39
    @hintable
40
    def some_class_method(cls, hint):
41
        return hint
42
43
44
class TestHintable(TestCase):
45
    def test_hintable(self):
46
        # Test that a function can be decorated and receives a hint.
47
48
        x: int = cast('42')
49
        y: str = cast(42)
50
        z: '  str  ' = cast(42)  # Even a sloppy hint should work.
51
52
        self.assertEqual(42, x)
53
        self.assertEqual('42', y)
54
        self.assertEqual('42', z)
55
56
    def test_hintable_with_parentheses(self):
57
        # Test that hintable can be used with parentheses as well.
58
59
        @hintable()  # Note the parentheses.
60
        def some_function(hint):
61
            return hint
62
63
        x: int = some_function()
64
65
        self.assertEqual(int, x)
66
67
    def test_hintable_with_custom_param_name(self):
68
        # Test that functions can customize the parameter name that receives
69
        # the type hint.
70
71
        x: int = some_func_with_custom_param_name()
72
73
        self.assertEqual(int, x)
74
75
    def test_hintable_method(self):
76
        # Test that methods can be hintable as well.
77
78
        sc = SomeClass()
79
        x: int = sc.some_method()
80
        y: float = SomeClass.some_static_method()
81
        z: str = SomeClass.some_class_method()
82
83
        self.assertEqual(int, x)
84
        self.assertEqual(float, y)
85
        self.assertEqual(str, z)
86
87
    def test_hintable_with_custom_type(self):
88
        # Test that a custom type can be used as hint without a problem.
89
90
        x: C = cast(42)
91
        y: 'C' = cast(42)
92
93
        self.assertTrue(isinstance(x, C))
94
        self.assertTrue(isinstance(y, C))
95
96
    def test_hintable_with_textual_hint(self):
97
        # Test that textual hints are received as strings.
98
99
        x: 'some rubbish' = some_func()
100
        y: "'some even greater rubbish'" = some_func()
101
102
        self.assertEqual('some rubbish', x)
103
        self.assertEqual('\'some even greater rubbish\'', y)
104
105
    def test_hintable_with_comment_hint(self):
106
        # Test that hints in MyPy style work as well.
107
108
        x = some_func()  # type: int
109
        y = some_func()  # type: rubbish_again
110
        # The type hint should take precedence of MyPy-styled-hints:
111
        z: int = some_func()  # type: str
112
113
        self.assertEqual(int, x)
114
        self.assertEqual('rubbish_again', y)
115
        self.assertEqual(int, z)
116
117
    def test_override_with_custom_hint(self):
118
        # Test that you can still override the hint.
119
120
        x = some_func(hint=int)
121
        y: int = some_func(hint=str)  # It's allowed, but is it a good idea?
122
123
        self.assertEqual(int, x)
124
        self.assertEqual(str, y)
125
126
    def test_as_parameter_in_a_function(self):
127
        # Test that a hintable function should also work as default argument.
128
129
        def func_with_default(arg1: int = some_func(), arg2: float = some_func(), arg3: str = some_func()):
130
            return arg1, arg2, arg3
131
132
        x, y, z = func_with_default()
133
        x2, y2, z2 = func_with_default()
134
        x3, y3, z3 = func_with_default()
135
136
        self.assertEqual(int, x)
137
        self.assertEqual(float, y)
138
        self.assertEqual(str, z)
139
        self.assertEqual(int, x2)
140
        self.assertEqual(float, y2)
141
        self.assertEqual(str, z2)
142
        self.assertEqual(int, x3)
143
        self.assertEqual(float, y3)
144
        self.assertEqual(str, z3)
145
146
    def test_multiple_on_a_line(self):
147
        # Test that multiple hintable calls on a line work.
148
149
        # Yes, this IS valid Python. No it is NOT recommended!
150
        x: int = some_func(); y: str = some_func()
151
152
        self.assertEqual(int, x)
153
        self.assertEqual(str, y)
154
155
    def test_multiline_wont_break(self):
156
        # Test that multiline code at least doesnt break
157
158
        # This is just too crazy. If you write code like this, you're on your
159
        # own.
160
        x: \
161
            int \
162
            = \
163
            some_func()
164
165
        self.assertEqual(None, x)
166