Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/parso/python/tree.py: 68%
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1"""
2This is the syntax tree for Python 3 syntaxes. The classes represent
3syntax elements like functions and imports.
5All of the nodes can be traced back to the `Python grammar file
6<https://docs.python.org/3/reference/grammar.html>`_. If you want to know how
7a tree is structured, just analyse that file (for each Python version it's a
8bit different).
10There's a lot of logic here that makes it easier for Jedi (and other libraries)
11to deal with a Python syntax tree.
13By using :py:meth:`parso.tree.NodeOrLeaf.get_code` on a module, you can get
14back the 1-to-1 representation of the input given to the parser. This is
15important if you want to refactor a parser tree.
17>>> from parso import parse
18>>> parser = parse('import os')
19>>> module = parser.get_root_node()
20>>> module
21<Module: @1-1>
23Any subclasses of :class:`Scope`, including :class:`Module` has an attribute
24:attr:`iter_imports <Scope.iter_imports>`:
26>>> list(module.iter_imports())
27[<ImportName: import os@1,0>]
29Changes to the Python Grammar
30-----------------------------
32A few things have changed when looking at Python grammar files:
34- :class:`Param` does not exist in Python grammar files. It is essentially a
35 part of a ``parameters`` node. |parso| splits it up to make it easier to
36 analyse parameters. However this just makes it easier to deal with the syntax
37 tree, it doesn't actually change the valid syntax.
38- A few nodes like `lambdef` and `lambdef_nocond` have been merged in the
39 syntax tree to make it easier to do deal with them.
41Parser Tree Classes
42-------------------
43"""
45import re
46from collections.abc import Mapping
47from typing import Tuple, Any
49from parso.tree import Node, BaseNode, Leaf, ErrorNode, ErrorLeaf, search_ancestor # noqa
50from parso.python.prefix import split_prefix
51from parso.utils import split_lines
53_FLOW_CONTAINERS = set(['if_stmt', 'while_stmt', 'for_stmt', 'try_stmt',
54 'with_stmt', 'async_stmt', 'suite'])
55_RETURN_STMT_CONTAINERS = set(['suite', 'simple_stmt']) | _FLOW_CONTAINERS
57_FUNC_CONTAINERS = set(
58 ['suite', 'simple_stmt', 'decorated', 'async_funcdef']
59) | _FLOW_CONTAINERS
61_GET_DEFINITION_TYPES = set([
62 'expr_stmt', 'sync_comp_for', 'with_stmt', 'for_stmt', 'import_name',
63 'import_from', 'param', 'del_stmt', 'namedexpr_test',
64])
65_IMPORTS = set(['import_name', 'import_from'])
68class DocstringMixin:
69 __slots__ = ()
70 type: str
71 children: "list[Any]"
72 parent: Any
74 def get_doc_node(self):
75 """
76 Returns the string leaf of a docstring. e.g. ``r'''foo'''``.
77 """
78 if self.type == 'file_input':
79 node = self.children[0]
80 elif self.type in ('funcdef', 'classdef'):
81 node = self.children[self.children.index(':') + 1]
82 if node.type == 'suite': # Normally a suite
83 node = node.children[1] # -> NEWLINE stmt
84 else: # ExprStmt
85 simple_stmt = self.parent
86 c = simple_stmt.parent.children
87 index = c.index(simple_stmt)
88 if not index:
89 return None
90 node = c[index - 1]
92 if node.type == 'simple_stmt':
93 node = node.children[0]
94 if node.type == 'string':
95 return node
96 return None
99class PythonMixin:
100 """
101 Some Python specific utilities.
102 """
103 __slots__ = ()
104 children: "list[Any]"
106 def get_name_of_position(self, position):
107 """
108 Given a (line, column) tuple, returns a :py:class:`Name` or ``None`` if
109 there is no name at that position.
110 """
111 for c in self.children:
112 if isinstance(c, Leaf):
113 if c.type == 'name' and c.start_pos <= position <= c.end_pos:
114 return c
115 else:
116 result = c.get_name_of_position(position)
117 if result is not None:
118 return result
119 return None
122class PythonLeaf(PythonMixin, Leaf):
123 __slots__ = ()
125 def _split_prefix(self):
126 return split_prefix(self, self.get_start_pos_of_prefix())
128 def get_start_pos_of_prefix(self):
129 """
130 Basically calls :py:meth:`parso.tree.NodeOrLeaf.get_start_pos_of_prefix`.
131 """
132 # TODO it is really ugly that we have to override it. Maybe change
133 # indent error leafs somehow? No idea how, though.
134 previous_leaf = self.get_previous_leaf()
135 if previous_leaf is not None and previous_leaf.type == 'error_leaf' \
136 and previous_leaf.token_type in ('INDENT', 'DEDENT', 'ERROR_DEDENT'):
137 previous_leaf = previous_leaf.get_previous_leaf()
139 if previous_leaf is None: # It's the first leaf.
140 lines = split_lines(self.prefix)
141 # + 1 is needed because split_lines always returns at least [''].
142 return self.line - len(lines) + 1, 0 # It's the first leaf.
143 return previous_leaf.end_pos
146class _LeafWithoutNewlines(PythonLeaf):
147 """
148 Simply here to optimize performance.
149 """
150 __slots__ = ()
152 @property
153 def end_pos(self) -> Tuple[int, int]:
154 return self.line, self.column + len(self.value)
157# Python base classes
158class PythonBaseNode(PythonMixin, BaseNode):
159 __slots__ = ()
162class PythonNode(PythonMixin, Node):
163 __slots__ = ()
166class PythonErrorNode(PythonMixin, ErrorNode):
167 __slots__ = ()
170class PythonErrorLeaf(ErrorLeaf, PythonLeaf):
171 __slots__ = ()
174class EndMarker(_LeafWithoutNewlines):
175 __slots__ = ()
176 type = 'endmarker'
178 def __repr__(self):
179 return "<%s: prefix=%s end_pos=%s>" % (
180 type(self).__name__, repr(self.prefix), self.end_pos
181 )
184class Newline(PythonLeaf):
185 """Contains NEWLINE and ENDMARKER tokens."""
186 __slots__ = ()
187 type = 'newline'
189 def __repr__(self):
190 return "<%s: %s>" % (type(self).__name__, repr(self.value))
193class Name(_LeafWithoutNewlines):
194 """
195 A string. Sometimes it is important to know if the string belongs to a name
196 or not.
197 """
198 type = 'name'
199 __slots__ = ()
201 def __repr__(self):
202 return "<%s: %s@%s,%s>" % (type(self).__name__, self.value,
203 self.line, self.column)
205 def is_definition(self, include_setitem=False):
206 """
207 Returns True if the name is being defined.
208 """
209 return self.get_definition(include_setitem=include_setitem) is not None
211 def get_definition(self, import_name_always=False, include_setitem=False):
212 """
213 Returns None if there's no definition for a name.
215 :param import_name_always: Specifies if an import name is always a
216 definition. Normally foo in `from foo import bar` is not a
217 definition.
218 """
219 node = self.parent
220 type_ = node.type
222 if type_ in ('funcdef', 'classdef'):
223 if self == node.name: # type: ignore[union-attr]
224 return node
225 return None
227 if type_ == 'except_clause':
228 if self.get_previous_sibling() == 'as':
229 return node.parent # The try_stmt.
230 return None
232 while node is not None:
233 if node.type == 'suite':
234 return None
235 if node.type in _GET_DEFINITION_TYPES:
236 if self in node.get_defined_names(include_setitem): # type: ignore[attr-defined]
237 return node
238 if import_name_always and node.type in _IMPORTS:
239 return node
240 return None
241 node = node.parent
242 return None
245class Literal(PythonLeaf):
246 __slots__ = ()
249class Number(Literal):
250 type = 'number'
251 __slots__ = ()
254class String(Literal):
255 type = 'string'
256 __slots__ = ()
258 @property
259 def string_prefix(self):
260 return re.match(r'\w*(?=[\'"])', self.value).group(0)
262 def _get_payload(self):
263 match = re.search(
264 r'''('{3}|"{3}|'|")(.*)$''',
265 self.value,
266 flags=re.DOTALL
267 )
268 return match.group(2)[:-len(match.group(1))]
271class FStringString(PythonLeaf):
272 """
273 f-strings contain f-string expressions and normal python strings. These are
274 the string parts of f-strings.
275 """
276 type = 'fstring_string'
277 __slots__ = ()
280class FStringStart(PythonLeaf):
281 """
282 f-strings contain f-string expressions and normal python strings. These are
283 the string parts of f-strings.
284 """
285 type = 'fstring_start'
286 __slots__ = ()
289class FStringEnd(PythonLeaf):
290 """
291 f-strings contain f-string expressions and normal python strings. These are
292 the string parts of f-strings.
293 """
294 type = 'fstring_end'
295 __slots__ = ()
298class _StringComparisonMixin:
299 __slots__ = ()
300 value: Any
302 def __eq__(self, other):
303 """
304 Make comparisons with strings easy.
305 Improves the readability of the parser.
306 """
307 if isinstance(other, str):
308 return self.value == other
310 return self is other
312 def __hash__(self):
313 return hash(self.value)
316class Operator(_LeafWithoutNewlines, _StringComparisonMixin):
317 type = 'operator'
318 __slots__ = ()
321class Keyword(_LeafWithoutNewlines, _StringComparisonMixin):
322 type = 'keyword'
323 __slots__ = ()
326class Scope(PythonBaseNode, DocstringMixin):
327 """
328 Super class for the parser tree, which represents the state of a python
329 text file.
330 A Scope is either a function, class or lambda.
331 """
332 __slots__ = ()
334 def __init__(self, children):
335 super().__init__(children)
337 def iter_funcdefs(self):
338 """
339 Returns a generator of `funcdef` nodes.
340 """
341 return self._search_in_scope('funcdef')
343 def iter_classdefs(self):
344 """
345 Returns a generator of `classdef` nodes.
346 """
347 return self._search_in_scope('classdef')
349 def iter_imports(self):
350 """
351 Returns a generator of `import_name` and `import_from` nodes.
352 """
353 return self._search_in_scope('import_name', 'import_from')
355 def _search_in_scope(self, *names):
356 def scan(children):
357 for element in children:
358 if element.type in names:
359 yield element
360 if element.type in _FUNC_CONTAINERS:
361 yield from scan(element.children)
363 return scan(self.children)
365 def get_suite(self):
366 """
367 Returns the part that is executed by the function.
368 """
369 return self.children[-1]
371 def __repr__(self):
372 try:
373 name = self.name.value # type: ignore[attr-defined]
374 except AttributeError:
375 name = ''
377 return "<%s: %s@%s-%s>" % (type(self).__name__, name,
378 self.start_pos[0], self.end_pos[0])
381class Module(Scope):
382 """
383 The top scope, which is always a module.
384 Depending on the underlying parser this may be a full module or just a part
385 of a module.
386 """
387 __slots__ = ('_used_names',)
388 type = 'file_input'
390 def __init__(self, children):
391 super().__init__(children)
392 self._used_names = None
394 def _iter_future_import_names(self):
395 """
396 :return: A list of future import names.
397 :rtype: list of str
398 """
399 # In Python it's not allowed to use future imports after the first
400 # actual (non-future) statement. However this is not a linter here,
401 # just return all future imports. If people want to scan for issues
402 # they should use the API.
403 for imp in self.iter_imports():
404 if imp.type == 'import_from' and imp.level == 0:
405 for path in imp.get_paths():
406 names = [name.value for name in path]
407 if len(names) == 2 and names[0] == '__future__':
408 yield names[1]
410 def get_used_names(self):
411 """
412 Returns all the :class:`Name` leafs that exist in this module. This
413 includes both definitions and references of names.
414 """
415 if self._used_names is None:
416 # Don't directly use self._used_names to eliminate a lookup.
417 dct = {}
419 def recurse(node):
420 try:
421 children = node.children
422 except AttributeError:
423 if node.type == 'name':
424 arr = dct.setdefault(node.value, [])
425 arr.append(node)
426 else:
427 for child in children:
428 recurse(child)
430 recurse(self)
431 self._used_names = UsedNamesMapping(dct)
432 return self._used_names
435class Decorator(PythonBaseNode):
436 type = 'decorator'
437 __slots__ = ()
440class ClassOrFunc(Scope):
441 __slots__ = ()
443 @property
444 def name(self):
445 """
446 Returns the `Name` leaf that defines the function or class name.
447 """
448 return self.children[1]
450 def get_decorators(self):
451 """
452 :rtype: list of :class:`Decorator`
453 """
454 decorated = self.parent
455 if decorated.type == 'async_funcdef':
456 decorated = decorated.parent
458 if decorated.type == 'decorated':
459 if decorated.children[0].type == 'decorators':
460 return decorated.children[0].children
461 else:
462 return decorated.children[:1]
463 else:
464 return []
467class Class(ClassOrFunc):
468 """
469 Used to store the parsed contents of a python class.
470 """
471 type = 'classdef'
472 __slots__ = ()
474 def __init__(self, children):
475 super().__init__(children)
477 def get_super_arglist(self):
478 """
479 Returns the `arglist` node that defines the super classes. It returns
480 None if there are no arguments.
481 """
482 for i, child in enumerate(self.children):
483 if child == '(':
484 next_child = self.children[i + 1]
485 if next_child == ')':
486 return None
487 return next_child
488 return None
491def _create_params(parent, argslist_list):
492 """
493 `argslist_list` is a list that can contain an argslist as a first item, but
494 most not. It's basically the items between the parameter brackets (which is
495 at most one item).
496 This function modifies the parser structure. It generates `Param` objects
497 from the normal ast. Those param objects do not exist in a normal ast, but
498 make the evaluation of the ast tree so much easier.
499 You could also say that this function replaces the argslist node with a
500 list of Param objects.
501 """
502 try:
503 first = argslist_list[0]
504 except IndexError:
505 return []
507 if first.type in ('name', 'fpdef'):
508 return [Param([first], parent)]
509 elif first == '*':
510 return [first]
511 else: # argslist is a `typedargslist` or a `varargslist`.
512 if first.type == 'tfpdef':
513 children = [first]
514 else:
515 children = first.children
516 new_children = []
517 start = 0
518 # Start with offset 1, because the end is higher.
519 for end, child in enumerate(children + [None], 1):
520 if child is None or child == ',':
521 param_children = children[start:end]
522 if param_children: # Could as well be comma and then end.
523 if param_children[0] == '*' \
524 and (len(param_children) == 1
525 or param_children[1] == ',') \
526 or param_children[0] == '/':
527 for p in param_children:
528 p.parent = parent
529 new_children += param_children
530 else:
531 new_children.append(Param(param_children, parent))
532 start = end
533 return new_children
536class Function(ClassOrFunc):
537 """
538 Used to store the parsed contents of a python function.
540 Children::
542 0. <Keyword: def>
543 1. <Name>
544 2. parameter list (including open-paren and close-paren <Operator>s)
545 3. or 5. <Operator: :>
546 4. or 6. Node() representing function body
547 3. -> (if annotation is also present)
548 4. annotation (if present)
549 """
550 type = 'funcdef'
551 __slots__ = ()
553 def __init__(self, children):
554 super().__init__(children)
555 parameters = self._find_parameters()
556 parameters_children = parameters.children[1:-1]
557 if not any(isinstance(child, Param) for child in parameters_children):
558 parameters.children[1:-1] = _create_params(
559 parameters, parameters_children
560 )
562 def _find_parameters(self):
563 for child in self.children:
564 if child.type == 'parameters':
565 return child
566 raise Exception("A function should always have parameters")
568 def _get_param_nodes(self):
569 return self._find_parameters().children
571 def get_params(self):
572 """
573 Returns a list of `Param()`.
574 """
575 return [p for p in self._get_param_nodes() if p.type == 'param']
577 @property
578 def name(self):
579 return self.children[1] # First token after `def`
581 def iter_yield_exprs(self):
582 """
583 Returns a generator of `yield_expr`.
584 """
585 def scan(children):
586 for element in children:
587 if element.type in ('classdef', 'funcdef', 'lambdef'):
588 continue
590 try:
591 nested_children = element.children
592 except AttributeError:
593 if element.value == 'yield':
594 if element.parent.type == 'yield_expr':
595 yield element.parent
596 else:
597 yield element
598 else:
599 yield from scan(nested_children)
601 return scan(self.children)
603 def iter_return_stmts(self):
604 """
605 Returns a generator of `return_stmt`.
606 """
607 def scan(children):
608 for element in children:
609 if element.type == 'return_stmt' \
610 or element.type == 'keyword' and element.value == 'return':
611 yield element
612 if element.type in _RETURN_STMT_CONTAINERS:
613 yield from scan(element.children)
615 return scan(self.children)
617 def iter_raise_stmts(self):
618 """
619 Returns a generator of `raise_stmt`. Includes raise statements inside try-except blocks
620 """
621 def scan(children):
622 for element in children:
623 if element.type == 'raise_stmt' \
624 or element.type == 'keyword' and element.value == 'raise':
625 yield element
626 if element.type in _RETURN_STMT_CONTAINERS:
627 yield from scan(element.children)
629 return scan(self.children)
631 def is_generator(self):
632 """
633 :return bool: Checks if a function is a generator or not.
634 """
635 return next(self.iter_yield_exprs(), None) is not None
637 @property
638 def annotation(self):
639 """
640 Returns the test node after `->` or `None` if there is no annotation.
641 """
642 for i, child in enumerate(self.children):
643 if child == '->':
644 return self.children[i + 1]
645 return None
648class Lambda(Function):
649 """
650 Lambdas are basically trimmed functions, so give it the same interface.
652 Children::
654 0. <Keyword: lambda>
655 *. <Param x> for each argument x
656 -2. <Operator: :>
657 -1. Node() representing body
658 """
659 type = 'lambdef'
660 __slots__ = ()
662 def __init__(self, children):
663 # We don't want to call the Function constructor, call its parent.
664 super(Function, self).__init__(children)
665 # Everything between `lambda` and the `:` operator is a parameter.
666 parameters_children = self.children[1:-2]
667 # If input children list already has Param objects, keep it as is;
668 # otherwise, convert it to a list of Param objects.
669 if not any(isinstance(child, Param) for child in parameters_children):
670 self.children[1:-2] = _create_params(self, parameters_children)
672 @property
673 def name(self):
674 """
675 Raises an AttributeError. Lambdas don't have a defined name.
676 """
677 raise AttributeError("lambda is not named.")
679 def _get_param_nodes(self):
680 return self.children[1:-2]
682 @property
683 def annotation(self):
684 """
685 Returns `None`, lambdas don't have annotations.
686 """
687 return None
689 def __repr__(self):
690 return "<%s@%s>" % (self.__class__.__name__, self.start_pos)
693class Flow(PythonBaseNode):
694 __slots__ = ()
697class IfStmt(Flow):
698 type = 'if_stmt'
699 __slots__ = ()
701 def get_test_nodes(self):
702 """
703 E.g. returns all the `test` nodes that are named as x, below:
705 if x:
706 pass
707 elif x:
708 pass
709 """
710 for i, c in enumerate(self.children):
711 if c in ('elif', 'if'):
712 yield self.children[i + 1]
714 def get_corresponding_test_node(self, node):
715 """
716 Searches for the branch in which the node is and returns the
717 corresponding test node (see function above). However if the node is in
718 the test node itself and not in the suite return None.
719 """
720 start_pos = node.start_pos
721 for check_node in reversed(list(self.get_test_nodes())):
722 if check_node.start_pos < start_pos:
723 if start_pos < check_node.end_pos:
724 return None
725 # In this case the node is within the check_node itself,
726 # not in the suite
727 else:
728 return check_node
730 def is_node_after_else(self, node):
731 """
732 Checks if a node is defined after `else`.
733 """
734 for c in self.children:
735 if c == 'else':
736 if node.start_pos > c.start_pos:
737 return True
738 else:
739 return False
742class WhileStmt(Flow):
743 type = 'while_stmt'
744 __slots__ = ()
747class ForStmt(Flow):
748 type = 'for_stmt'
749 __slots__ = ()
751 def get_testlist(self):
752 """
753 Returns the input node ``y`` from: ``for x in y:``.
754 """
755 return self.children[3]
757 def get_defined_names(self, include_setitem=False):
758 return _defined_names(self.children[1], include_setitem)
761class TryStmt(Flow):
762 type = 'try_stmt'
763 __slots__ = ()
765 def get_except_clause_tests(self):
766 """
767 Returns the ``test`` nodes found in ``except_clause`` nodes.
768 Returns ``[None]`` for except clauses without an exception given.
769 """
770 for node in self.children:
771 if node.type == 'except_clause':
772 yield node.children[1]
773 elif node == 'except':
774 yield None
777class WithStmt(Flow):
778 type = 'with_stmt'
779 __slots__ = ()
781 def get_defined_names(self, include_setitem=False):
782 """
783 Returns the a list of `Name` that the with statement defines. The
784 defined names are set after `as`.
785 """
786 names = []
787 for with_item in self.children[1:-2:2]:
788 # Check with items for 'as' names.
789 if with_item.type == 'with_item':
790 names += _defined_names(with_item.children[2], include_setitem)
791 return names
793 def get_test_node_from_name(self, name):
794 node = name.search_ancestor("with_item")
795 if node is None:
796 raise ValueError('The name is not actually part of a with statement.')
797 return node.children[0]
800class Import(PythonBaseNode):
801 __slots__ = ()
802 get_paths: Any
803 _aliases: Any
805 def get_path_for_name(self, name):
806 """
807 The path is the list of names that leads to the searched name.
809 :return list of Name:
810 """
811 try:
812 # The name may be an alias. If it is, just map it back to the name.
813 name = self._aliases()[name]
814 except KeyError:
815 pass
817 for path in self.get_paths():
818 if name in path:
819 return path[:path.index(name) + 1]
820 raise ValueError('Name should be defined in the import itself')
822 def is_nested(self):
823 return False # By default, sub classes may overwrite this behavior
825 def is_star_import(self):
826 return self.children[-1] == '*'
828 def get_defined_names(self):
829 raise NotImplementedError("Use ImportFrom or ImportName")
832class ImportFrom(Import):
833 type = 'import_from'
834 __slots__ = ()
836 def get_defined_names(self, include_setitem=False):
837 """
838 Returns the a list of `Name` that the import defines. The
839 defined names are set after `import` or in case an alias - `as` - is
840 present that name is returned.
841 """
842 return [alias or name for name, alias in self._as_name_tuples()]
844 def _aliases(self):
845 """Mapping from alias to its corresponding name."""
846 return dict((alias, name) for name, alias in self._as_name_tuples()
847 if alias is not None)
849 def get_from_names(self):
850 for n in self.children[1:]:
851 if n not in ('.', '...'):
852 break
853 if n.type == 'dotted_name': # from x.y import
854 return n.children[::2]
855 elif n == 'import': # from . import
856 return []
857 else: # from x import
858 return [n]
860 @property
861 def level(self):
862 """The level parameter of ``__import__``."""
863 level = 0
864 for n in self.children[1:]:
865 if n in ('.', '...'):
866 level += len(n.value)
867 else:
868 break
869 return level
871 def _as_name_tuples(self):
872 last = self.children[-1]
873 if last == ')':
874 last = self.children[-2]
875 elif last == '*':
876 return # No names defined directly.
878 if last.type == 'import_as_names':
879 as_names = last.children[::2]
880 else:
881 as_names = [last]
882 for as_name in as_names:
883 if as_name.type == 'name':
884 yield as_name, None
885 else:
886 yield as_name.children[::2] # yields x, y -> ``x as y``
888 def get_paths(self):
889 """
890 The import paths defined in an import statement. Typically an array
891 like this: ``[<Name: datetime>, <Name: date>]``.
893 :return list of list of Name:
894 """
895 dotted = self.get_from_names()
897 if self.children[-1] == '*':
898 return [dotted]
899 return [dotted + [name] for name, alias in self._as_name_tuples()]
902class ImportName(Import):
903 """For ``import_name`` nodes. Covers normal imports without ``from``."""
904 type = 'import_name'
905 __slots__ = ()
907 def get_defined_names(self, include_setitem=False):
908 """
909 Returns the a list of `Name` that the import defines. The defined names
910 is always the first name after `import` or in case an alias - `as` - is
911 present that name is returned.
912 """
913 return [alias or path[0] for path, alias in self._dotted_as_names()]
915 @property
916 def level(self):
917 """The level parameter of ``__import__``."""
918 return 0 # Obviously 0 for imports without from.
920 def get_paths(self):
921 return [path for path, alias in self._dotted_as_names()]
923 def _dotted_as_names(self):
924 """Generator of (list(path), alias) where alias may be None."""
925 dotted_as_names = self.children[1]
926 if dotted_as_names.type == 'dotted_as_names':
927 as_names = dotted_as_names.children[::2]
928 else:
929 as_names = [dotted_as_names]
931 for as_name in as_names:
932 if as_name.type == 'dotted_as_name':
933 alias = as_name.children[2]
934 as_name = as_name.children[0]
935 else:
936 alias = None
937 if as_name.type == 'name':
938 yield [as_name], alias
939 else:
940 # dotted_names
941 yield as_name.children[::2], alias
943 def is_nested(self):
944 """
945 This checks for the special case of nested imports, without aliases and
946 from statement::
948 import foo.bar
949 """
950 return bool([1 for path, alias in self._dotted_as_names()
951 if alias is None and len(path) > 1])
953 def _aliases(self):
954 """
955 :return list of Name: Returns all the alias
956 """
957 return dict((alias, path[-1]) for path, alias in self._dotted_as_names()
958 if alias is not None)
961class KeywordStatement(PythonBaseNode):
962 """
963 For the following statements: `assert`, `del`, `global`, `nonlocal`,
964 `raise`, `return`, `yield`.
966 `pass`, `continue` and `break` are not in there, because they are just
967 simple keywords and the parser reduces it to a keyword.
968 """
969 __slots__ = ()
971 @property
972 def type(self):
973 """
974 Keyword statements start with the keyword and end with `_stmt`. You can
975 crosscheck this with the Python grammar.
976 """
977 return '%s_stmt' % self.keyword
979 @property
980 def keyword(self):
981 return self.children[0].value
983 def get_defined_names(self, include_setitem=False):
984 keyword = self.keyword
985 if keyword == 'del':
986 return _defined_names(self.children[1], include_setitem)
987 if keyword in ('global', 'nonlocal'):
988 return self.children[1::2]
989 return []
992class AssertStmt(KeywordStatement):
993 __slots__ = ()
995 @property
996 def assertion(self):
997 return self.children[1]
1000class GlobalStmt(KeywordStatement):
1001 __slots__ = ()
1003 def get_global_names(self):
1004 return self.children[1::2]
1007class ReturnStmt(KeywordStatement):
1008 __slots__ = ()
1011class YieldExpr(PythonBaseNode):
1012 type = 'yield_expr'
1013 __slots__ = ()
1016def _defined_names(current, include_setitem):
1017 """
1018 A helper function to find the defined names in statements, for loops and
1019 list comprehensions.
1020 """
1021 names = []
1022 if current.type in ('testlist_star_expr', 'testlist_comp', 'exprlist', 'testlist'):
1023 for child in current.children[::2]:
1024 names += _defined_names(child, include_setitem)
1025 elif current.type in ('atom', 'star_expr'):
1026 names += _defined_names(current.children[1], include_setitem)
1027 elif current.type in ('power', 'atom_expr'):
1028 if current.children[-2] != '**': # Just if there's no operation
1029 trailer = current.children[-1]
1030 if trailer.children[0] == '.':
1031 names.append(trailer.children[1])
1032 elif trailer.children[0] == '[' and include_setitem:
1033 for node in current.children[-2::-1]:
1034 if node.type == 'trailer':
1035 names.append(node.children[1])
1036 break
1037 if node.type == 'name':
1038 names.append(node)
1039 break
1040 else:
1041 names.append(current)
1042 return names
1045class ExprStmt(PythonBaseNode, DocstringMixin):
1046 type = 'expr_stmt'
1047 __slots__ = ()
1049 def get_defined_names(self, include_setitem=False):
1050 """
1051 Returns a list of `Name` defined before the `=` sign.
1052 """
1053 names = []
1054 if self.children[1].type == 'annassign':
1055 names = _defined_names(self.children[0], include_setitem)
1056 return [
1057 name
1058 for i in range(0, len(self.children) - 2, 2)
1059 if '=' in self.children[i + 1].value
1060 for name in _defined_names(self.children[i], include_setitem)
1061 ] + names
1063 def get_rhs(self):
1064 """Returns the right-hand-side of the equals."""
1065 node = self.children[-1]
1066 if node.type == 'annassign':
1067 if len(node.children) == 4:
1068 node = node.children[3]
1069 else:
1070 node = node.children[1]
1071 return node
1073 def yield_operators(self):
1074 """
1075 Returns a generator of `+=`, `=`, etc. or None if there is no operation.
1076 """
1077 first = self.children[1]
1078 if first.type == 'annassign':
1079 if len(first.children) <= 2:
1080 return # No operator is available, it's just PEP 484.
1082 first = first.children[2]
1083 yield first
1085 yield from self.children[3::2]
1088class NamedExpr(PythonBaseNode):
1089 type = 'namedexpr_test'
1091 def get_defined_names(self, include_setitem=False):
1092 return _defined_names(self.children[0], include_setitem)
1095class Param(PythonBaseNode):
1096 """
1097 It's a helper class that makes business logic with params much easier. The
1098 Python grammar defines no ``param`` node. It defines it in a different way
1099 that is not really suited to working with parameters.
1100 """
1101 type = 'param'
1103 def __init__(self, children, parent=None):
1104 super().__init__(children)
1105 self.parent = parent
1107 @property
1108 def star_count(self):
1109 """
1110 Is `0` in case of `foo`, `1` in case of `*foo` or `2` in case of
1111 `**foo`.
1112 """
1113 first = self.children[0]
1114 if first in ('*', '**'):
1115 return len(first.value)
1116 return 0
1118 @property
1119 def default(self):
1120 """
1121 The default is the test node that appears after the `=`. Is `None` in
1122 case no default is present.
1123 """
1124 has_comma = self.children[-1] == ','
1125 try:
1126 if self.children[-2 - int(has_comma)] == '=':
1127 return self.children[-1 - int(has_comma)]
1128 except IndexError:
1129 return None
1131 @property
1132 def annotation(self):
1133 """
1134 The default is the test node that appears after `:`. Is `None` in case
1135 no annotation is present.
1136 """
1137 tfpdef = self._tfpdef()
1138 if tfpdef.type == 'tfpdef':
1139 assert tfpdef.children[1] == ":"
1140 assert len(tfpdef.children) == 3
1141 annotation = tfpdef.children[2]
1142 return annotation
1143 else:
1144 return None
1146 def _tfpdef(self):
1147 """
1148 tfpdef: see e.g. grammar36.txt.
1149 """
1150 offset = int(self.children[0] in ('*', '**'))
1151 return self.children[offset]
1153 @property
1154 def name(self):
1155 """
1156 The `Name` leaf of the param.
1157 """
1158 if self._tfpdef().type == 'tfpdef':
1159 return self._tfpdef().children[0]
1160 else:
1161 return self._tfpdef()
1163 def get_defined_names(self, include_setitem=False):
1164 return [self.name]
1166 @property
1167 def position_index(self):
1168 """
1169 Property for the positional index of a paramter.
1170 """
1171 index = self.parent.children.index(self)
1172 try:
1173 keyword_only_index = self.parent.children.index('*')
1174 if index > keyword_only_index:
1175 # Skip the ` *, `
1176 index -= 2
1177 except ValueError:
1178 pass
1179 try:
1180 keyword_only_index = self.parent.children.index('/')
1181 if index > keyword_only_index:
1182 # Skip the ` /, `
1183 index -= 2
1184 except ValueError:
1185 pass
1186 return index - 1
1188 def get_parent_function(self):
1189 """
1190 Returns the function/lambda of a parameter.
1191 """
1192 return self.search_ancestor('funcdef', 'lambdef')
1194 def get_code(self, include_prefix=True, include_comma=True):
1195 """
1196 Like all the other get_code functions, but includes the param
1197 `include_comma`.
1199 :param include_comma bool: If enabled includes the comma in the string output.
1200 """
1201 if include_comma:
1202 return super().get_code(include_prefix)
1204 children = self.children
1205 if children[-1] == ',':
1206 children = children[:-1]
1207 return self._get_code_for_children(
1208 children,
1209 include_prefix=include_prefix
1210 )
1212 def __repr__(self):
1213 default = '' if self.default is None else '=%s' % self.default.get_code()
1214 return '<%s: %s>' % (type(self).__name__, str(self._tfpdef()) + default)
1217class SyncCompFor(PythonBaseNode):
1218 type = 'sync_comp_for'
1219 __slots__ = ()
1221 def get_defined_names(self, include_setitem=False):
1222 """
1223 Returns the a list of `Name` that the comprehension defines.
1224 """
1225 # allow async for
1226 return _defined_names(self.children[1], include_setitem)
1229# This is simply here so an older Jedi version can work with this new parso
1230# version. Can be deleted in the next release.
1231CompFor = SyncCompFor
1234class UsedNamesMapping(Mapping):
1235 """
1236 This class exists for the sole purpose of creating an immutable dict.
1237 """
1238 def __init__(self, dct):
1239 self._dict = dct
1241 def __getitem__(self, key):
1242 return self._dict[key]
1244 def __len__(self):
1245 return len(self._dict)
1247 def __iter__(self):
1248 return iter(self._dict)
1250 def __hash__(self):
1251 return id(self)
1253 def __eq__(self, other):
1254 # Comparing these dicts does not make sense.
1255 return self is other