summaryrefslogtreecommitdiff
path: root/tests/functional/u/used/used_before_assignment_typing.py
blob: a685bdabc89362b797c796d3cd35f4597a2c17dd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
"""Tests for used-before-assignment for typing related issues"""
# pylint: disable=missing-function-docstring,ungrouped-imports,invalid-name


from typing import List, Optional, TYPE_CHECKING

if TYPE_CHECKING:
    if True:  # pylint: disable=using-constant-test
        import math
    from urllib.request import urlopen
    import array
    import base64
    import binascii
    import bisect
    import calendar
    import collections
    import copy
    import datetime
    import email
    import heapq
    import json
    import mailbox
    import mimetypes
    import numbers
    import pprint
    import types
    import zoneinfo
elif input():
    import calendar, bisect  # pylint: disable=multiple-imports
    if input() + 1:
        import heapq
    else:
        import heapq
elif input():
    try:
        numbers = None if input() else 1
        import array
    except Exception as e:  # pylint: disable=broad-exception-caught
        import types
    finally:
        copy = None
elif input():
    for i in range(1,2):
        email = None
    else:  # pylint: disable=useless-else-on-loop
        json = None
    while input():
        import mailbox
    else:  # pylint: disable=useless-else-on-loop
        mimetypes = None
elif input():
    with input() as base64:
        pass
    with input() as temp:
        import binascii
else:
    from urllib.request import urlopen
    zoneinfo: str = ''
    def pprint():
        pass
    class collections:  # pylint: disable=too-few-public-methods,missing-class-docstring
        pass

class MyClass:
    """Type annotation or default values for first level methods can't refer to their own class"""

    def incorrect_typing_method(
        self, other: MyClass  # [undefined-variable]
    ) -> bool:
        return self == other

    def incorrect_nested_typing_method(
        self, other: List[MyClass]  # [undefined-variable]
    ) -> bool:
        return self == other[0]

    def incorrect_default_method(
        self, other=MyClass()  # [undefined-variable]
    ) -> bool:
        return self == other

    def correct_string_typing_method(self, other: "MyClass") -> bool:
        return self == other

    def correct_inner_typing_method(self) -> bool:
        def inner_method(self, other: MyClass) -> bool:
            return self == other

        return inner_method(self, MyClass())


class MySecondClass:
    """Class to test self referential variable typing.
    This regressed, reported in: https://github.com/PyCQA/pylint/issues/5342
    """

    def self_referential_optional_within_method(self) -> None:
        variable: Optional[MySecondClass] = self
        print(variable)

    def correct_inner_typing_method(self) -> bool:
        def inner_method(self, other: MySecondClass) -> bool:
            return self == other

        return inner_method(self, MySecondClass())


class MyOtherClass:
    """Class to test self referential variable typing, no regression."""

    def correct_inner_typing_method(self) -> bool:
        def inner_method(self, other: MyOtherClass) -> bool:
            return self == other

        return inner_method(self, MyOtherClass())

    def self_referential_optional_within_method(self) -> None:
        variable: Optional[MyOtherClass] = self
        print(variable)


class MyThirdClass:
    """Class to test self referential variable typing within conditionals.
    This regressed, reported in: https://github.com/PyCQA/pylint/issues/5499
    """

    def function(self, var: int) -> None:
        if var < 0.5:
            _x: MyThirdClass = self

    def other_function(self) -> None:
        _x: MyThirdClass = self


class MyFourthClass:  # pylint: disable=too-few-public-methods
    """Class to test conditional imports guarded by TYPE_CHECKING two levels
    up then used in function annotation. See https://github.com/PyCQA/pylint/issues/7539"""

    def is_close(self, comparator: math.isclose, first, second):  # [used-before-assignment]
        """Conditional imports guarded are only valid for variable annotations."""
        comparator(first, second)


class VariableAnnotationsGuardedByTypeChecking:  # pylint: disable=too-few-public-methods
    """Class to test conditional imports guarded by TYPE_CHECKING then used in
    local (function) variable annotations, which are not evaluated at runtime.

    See: https://github.com/PyCQA/pylint/issues/7609
    and https://github.com/PyCQA/pylint/issues/7882
    """

    still_an_error: datetime.date  # [used-before-assignment]

    def print_date(self, date) -> None:
        date: datetime.date = date
        print(date)

        import datetime  # pylint: disable=import-outside-toplevel


class ConditionalImportGuardedWhenUsed:  # pylint: disable=too-few-public-methods
    """Conditional imports also guarded by TYPE_CHECKING when used."""
    if TYPE_CHECKING:
        print(urlopen)


class TypeCheckingMultiBranch:  # pylint: disable=too-few-public-methods,unused-variable
    """Test for defines in TYPE_CHECKING if/elif/else branching"""
    def defined_in_elif_branch(self) -> calendar.Calendar:
        print(bisect)
        return calendar.Calendar()

    def defined_in_else_branch(self) -> urlopen:
        print(zoneinfo)
        print(pprint())
        print(collections())
        return urlopen

    def defined_in_nested_if_else(self) -> heapq:
        print(heapq)
        return heapq

    def defined_in_try_except(self) -> array:
        print(types)
        print(copy)
        print(numbers)
        return array

    def defined_in_loops(self) -> json:
        print(email)
        print(mailbox)
        print(mimetypes)
        return json

    def defined_in_with(self) -> base64:
        print(binascii)
        return base64