]>
crepu.dev Git - config.git/blob - djavu-asus/elpy/rpc-venv/lib/python3.11/site-packages/jedi/inference/analysis.py
2 Module for statical analysis.
4 from parso
.python
import tree
7 from jedi
.inference
.helpers
import is_string
11 'attribute-error': (1, AttributeError, 'Potential AttributeError.'),
12 'name-error': (2, NameError, 'Potential NameError.'),
13 'import-error': (3, ImportError, 'Potential ImportError.'),
14 'type-error-too-many-arguments': (4, TypeError, None),
15 'type-error-too-few-arguments': (5, TypeError, None),
16 'type-error-keyword-argument': (6, TypeError, None),
17 'type-error-multiple-values': (7, TypeError, None),
18 'type-error-star-star': (8, TypeError, None),
19 'type-error-star': (9, TypeError, None),
20 'type-error-operation': (10, TypeError, None),
21 'type-error-not-iterable': (11, TypeError, None),
22 'type-error-isinstance': (12, TypeError, None),
23 'type-error-not-subscriptable': (13, TypeError, None),
24 'value-error-too-many-values': (14, ValueError, None),
25 'value-error-too-few-values': (15, ValueError, None),
30 def __init__(self
, name
, module_path
, start_pos
, message
=None):
31 self
.path
= module_path
32 self
._start
_pos
= start_pos
35 message
= CODES
[self
.name
][2]
36 self
.message
= message
40 return self
._start
_pos
[0]
44 return self
._start
_pos
[1]
48 # The class name start
49 first
= self
.__class
__.__name
__[0]
50 return first
+ str(CODES
[self
.name
][0])
53 return '%s:%s:%s: %s %s' % (self
.path
, self
.line
, self
.column
,
54 self
.code
, self
.message
)
56 def __eq__(self
, other
):
57 return (self
.path
== other
.path
and self
.name
== other
.name
58 and self
._start
_pos
== other
._start
_pos
)
60 def __ne__(self
, other
):
61 return not self
.__eq
__(other
)
64 return hash((self
.path
, self
._start
_pos
, self
.name
))
67 return '<%s %s: %s@%s,%s>' % (self
.__class
__.__name
__,
69 self
._start
_pos
[0], self
._start
_pos
[1])
76 def add(node_context
, error_name
, node
, message
=None, typ
=Error
, payload
=None):
77 exception
= CODES
[error_name
][1]
78 if _check_for_exception_catch(node_context
, node
, exception
, payload
):
81 # TODO this path is probably not right
82 module_context
= node_context
.get_root_context()
83 module_path
= module_context
.py__file__()
84 issue_instance
= typ(error_name
, module_path
, node
.start_pos
, message
)
85 debug
.warning(str(issue_instance
), format
=False)
86 node_context
.inference_state
.analysis
.append(issue_instance
)
90 def _check_for_setattr(instance
):
92 Check if there's any setattr method inside an instance. If so, return True.
94 module
= instance
.get_root_context()
95 node
= module
.tree_node
97 # If it's a compiled module or doesn't have a tree_node
101 stmt_names
= node
.get_used_names()['setattr']
105 return any(node
.start_pos
< n
.start_pos
< node
.end_pos
106 # Check if it's a function called setattr.
107 and not (n
.parent
.type == 'funcdef' and n
.parent
.name
== n
)
111 def add_attribute_error(name_context
, lookup_value
, name
):
112 message
= ('AttributeError: %s has no attribute %s.' % (lookup_value
, name
))
113 # Check for __getattr__/__getattribute__ existance and issue a warning
114 # instead of an error, if that happens.
116 if lookup_value
.is_instance() and not lookup_value
.is_compiled():
117 # TODO maybe make a warning for __getattr__/__getattribute__
119 if _check_for_setattr(lookup_value
):
122 payload
= lookup_value
, name
123 add(name_context
, 'attribute-error', name
, message
, typ
, payload
)
126 def _check_for_exception_catch(node_context
, jedi_name
, exception
, payload
=None):
128 Checks if a jedi object (e.g. `Statement`) sits inside a try/catch and
129 doesn't count as an error (if equal to `exception`).
130 Also checks `hasattr` for AttributeErrors and uses the `payload` to compare
132 Returns True if the exception was catched.
134 def check_match(cls
, exception
):
135 if not cls
.is_class():
138 for python_cls
in exception
.mro():
139 if cls
.py__name__() == python_cls
.__name
__ \
140 and cls
.parent_context
.is_builtins_module():
144 def check_try_for_except(obj
, exception
):
146 iterator
= iter(obj
.children
)
147 for branch_type
in iterator
:
148 next(iterator
) # The colon
149 suite
= next(iterator
)
150 if branch_type
== 'try' \
151 and not (branch_type
.start_pos
< jedi_name
.start_pos
<= suite
.end_pos
):
154 for node
in obj
.get_except_clause_tests():
156 return True # An exception block that catches everything.
158 except_classes
= node_context
.infer_node(node
)
159 for cls
in except_classes
:
160 from jedi
.inference
.value
import iterable
161 if isinstance(cls
, iterable
.Sequence
) and \
162 cls
.array_type
== 'tuple':
163 # multiple exceptions
164 for lazy_value
in cls
.py__iter__():
165 for typ
in lazy_value
.infer():
166 if check_match(typ
, exception
):
169 if check_match(cls
, exception
):
172 def check_hasattr(node
, suite
):
174 assert suite
.start_pos
<= jedi_name
.start_pos
< suite
.end_pos
175 assert node
.type in ('power', 'atom_expr')
176 base
= node
.children
[0]
177 assert base
.type == 'name' and base
.value
== 'hasattr'
178 trailer
= node
.children
[1]
179 assert trailer
.type == 'trailer'
180 arglist
= trailer
.children
[1]
181 assert arglist
.type == 'arglist'
182 from jedi
.inference
.arguments
import TreeArguments
183 args
= TreeArguments(node_context
.inference_state
, node_context
, arglist
)
184 unpacked_args
= list(args
.unpack())
185 # Arguments should be very simple
186 assert len(unpacked_args
) == 2
189 key
, lazy_value
= unpacked_args
[1]
190 names
= list(lazy_value
.infer())
191 assert len(names
) == 1 and is_string(names
[0])
192 assert names
[0].get_safe_value() == payload
[1].value
195 key
, lazy_value
= unpacked_args
[0]
196 objects
= lazy_value
.infer()
197 return payload
[0] in objects
198 except AssertionError:
202 while obj
is not None and not isinstance(obj
, (tree
.Function
, tree
.Class
)):
203 if isinstance(obj
, tree
.Flow
):
204 # try/except catch check
205 if obj
.type == 'try_stmt' and check_try_for_except(obj
, exception
):
208 if exception
== AttributeError and obj
.type in ('if_stmt', 'while_stmt'):
209 if check_hasattr(obj
.children
[1], obj
.children
[3]):