Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/parso/python/tree.py: 39%
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 if self.children[2] != '(': # Has no parentheses
483 return None
484 else:
485 if self.children[3] == ')': # Empty parentheses
486 return None
487 else:
488 return self.children[3]
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.children[2] # After `def foo`
556 parameters_children = parameters.children[1:-1]
557 # If input parameters list already has Param objects, keep it as is;
558 # otherwise, convert it to a list of Param objects.
559 if not any(isinstance(child, Param) for child in parameters_children):
560 parameters.children[1:-1] = _create_params(parameters, parameters_children)
562 def _get_param_nodes(self):
563 return self.children[2].children
565 def get_params(self):
566 """
567 Returns a list of `Param()`.
568 """
569 return [p for p in self._get_param_nodes() if p.type == 'param']
571 @property
572 def name(self):
573 return self.children[1] # First token after `def`
575 def iter_yield_exprs(self):
576 """
577 Returns a generator of `yield_expr`.
578 """
579 def scan(children):
580 for element in children:
581 if element.type in ('classdef', 'funcdef', 'lambdef'):
582 continue
584 try:
585 nested_children = element.children
586 except AttributeError:
587 if element.value == 'yield':
588 if element.parent.type == 'yield_expr':
589 yield element.parent
590 else:
591 yield element
592 else:
593 yield from scan(nested_children)
595 return scan(self.children)
597 def iter_return_stmts(self):
598 """
599 Returns a generator of `return_stmt`.
600 """
601 def scan(children):
602 for element in children:
603 if element.type == 'return_stmt' \
604 or element.type == 'keyword' and element.value == 'return':
605 yield element
606 if element.type in _RETURN_STMT_CONTAINERS:
607 yield from scan(element.children)
609 return scan(self.children)
611 def iter_raise_stmts(self):
612 """
613 Returns a generator of `raise_stmt`. Includes raise statements inside try-except blocks
614 """
615 def scan(children):
616 for element in children:
617 if element.type == 'raise_stmt' \
618 or element.type == 'keyword' and element.value == 'raise':
619 yield element
620 if element.type in _RETURN_STMT_CONTAINERS:
621 yield from scan(element.children)
623 return scan(self.children)
625 def is_generator(self):
626 """
627 :return bool: Checks if a function is a generator or not.
628 """
629 return next(self.iter_yield_exprs(), None) is not None
631 @property
632 def annotation(self):
633 """
634 Returns the test node after `->` or `None` if there is no annotation.
635 """
636 try:
637 if self.children[3] == "->":
638 return self.children[4]
639 assert self.children[3] == ":"
640 return None
641 except IndexError:
642 return None
645class Lambda(Function):
646 """
647 Lambdas are basically trimmed functions, so give it the same interface.
649 Children::
651 0. <Keyword: lambda>
652 *. <Param x> for each argument x
653 -2. <Operator: :>
654 -1. Node() representing body
655 """
656 type = 'lambdef'
657 __slots__ = ()
659 def __init__(self, children):
660 # We don't want to call the Function constructor, call its parent.
661 super(Function, self).__init__(children)
662 # Everything between `lambda` and the `:` operator is a parameter.
663 parameters_children = self.children[1:-2]
664 # If input children list already has Param objects, keep it as is;
665 # otherwise, convert it to a list of Param objects.
666 if not any(isinstance(child, Param) for child in parameters_children):
667 self.children[1:-2] = _create_params(self, parameters_children)
669 @property
670 def name(self):
671 """
672 Raises an AttributeError. Lambdas don't have a defined name.
673 """
674 raise AttributeError("lambda is not named.")
676 def _get_param_nodes(self):
677 return self.children[1:-2]
679 @property
680 def annotation(self):
681 """
682 Returns `None`, lambdas don't have annotations.
683 """
684 return None
686 def __repr__(self):
687 return "<%s@%s>" % (self.__class__.__name__, self.start_pos)
690class Flow(PythonBaseNode):
691 __slots__ = ()
694class IfStmt(Flow):
695 type = 'if_stmt'
696 __slots__ = ()
698 def get_test_nodes(self):
699 """
700 E.g. returns all the `test` nodes that are named as x, below:
702 if x:
703 pass
704 elif x:
705 pass
706 """
707 for i, c in enumerate(self.children):
708 if c in ('elif', 'if'):
709 yield self.children[i + 1]
711 def get_corresponding_test_node(self, node):
712 """
713 Searches for the branch in which the node is and returns the
714 corresponding test node (see function above). However if the node is in
715 the test node itself and not in the suite return None.
716 """
717 start_pos = node.start_pos
718 for check_node in reversed(list(self.get_test_nodes())):
719 if check_node.start_pos < start_pos:
720 if start_pos < check_node.end_pos:
721 return None
722 # In this case the node is within the check_node itself,
723 # not in the suite
724 else:
725 return check_node
727 def is_node_after_else(self, node):
728 """
729 Checks if a node is defined after `else`.
730 """
731 for c in self.children:
732 if c == 'else':
733 if node.start_pos > c.start_pos:
734 return True
735 else:
736 return False
739class WhileStmt(Flow):
740 type = 'while_stmt'
741 __slots__ = ()
744class ForStmt(Flow):
745 type = 'for_stmt'
746 __slots__ = ()
748 def get_testlist(self):
749 """
750 Returns the input node ``y`` from: ``for x in y:``.
751 """
752 return self.children[3]
754 def get_defined_names(self, include_setitem=False):
755 return _defined_names(self.children[1], include_setitem)
758class TryStmt(Flow):
759 type = 'try_stmt'
760 __slots__ = ()
762 def get_except_clause_tests(self):
763 """
764 Returns the ``test`` nodes found in ``except_clause`` nodes.
765 Returns ``[None]`` for except clauses without an exception given.
766 """
767 for node in self.children:
768 if node.type == 'except_clause':
769 yield node.children[1]
770 elif node == 'except':
771 yield None
774class WithStmt(Flow):
775 type = 'with_stmt'
776 __slots__ = ()
778 def get_defined_names(self, include_setitem=False):
779 """
780 Returns the a list of `Name` that the with statement defines. The
781 defined names are set after `as`.
782 """
783 names = []
784 for with_item in self.children[1:-2:2]:
785 # Check with items for 'as' names.
786 if with_item.type == 'with_item':
787 names += _defined_names(with_item.children[2], include_setitem)
788 return names
790 def get_test_node_from_name(self, name):
791 node = name.search_ancestor("with_item")
792 if node is None:
793 raise ValueError('The name is not actually part of a with statement.')
794 return node.children[0]
797class Import(PythonBaseNode):
798 __slots__ = ()
799 get_paths: Any
800 _aliases: Any
802 def get_path_for_name(self, name):
803 """
804 The path is the list of names that leads to the searched name.
806 :return list of Name:
807 """
808 try:
809 # The name may be an alias. If it is, just map it back to the name.
810 name = self._aliases()[name]
811 except KeyError:
812 pass
814 for path in self.get_paths():
815 if name in path:
816 return path[:path.index(name) + 1]
817 raise ValueError('Name should be defined in the import itself')
819 def is_nested(self):
820 return False # By default, sub classes may overwrite this behavior
822 def is_star_import(self):
823 return self.children[-1] == '*'
825 def get_defined_names(self):
826 raise NotImplementedError("Use ImportFrom or ImportName")
829class ImportFrom(Import):
830 type = 'import_from'
831 __slots__ = ()
833 def get_defined_names(self, include_setitem=False):
834 """
835 Returns the a list of `Name` that the import defines. The
836 defined names are set after `import` or in case an alias - `as` - is
837 present that name is returned.
838 """
839 return [alias or name for name, alias in self._as_name_tuples()]
841 def _aliases(self):
842 """Mapping from alias to its corresponding name."""
843 return dict((alias, name) for name, alias in self._as_name_tuples()
844 if alias is not None)
846 def get_from_names(self):
847 for n in self.children[1:]:
848 if n not in ('.', '...'):
849 break
850 if n.type == 'dotted_name': # from x.y import
851 return n.children[::2]
852 elif n == 'import': # from . import
853 return []
854 else: # from x import
855 return [n]
857 @property
858 def level(self):
859 """The level parameter of ``__import__``."""
860 level = 0
861 for n in self.children[1:]:
862 if n in ('.', '...'):
863 level += len(n.value)
864 else:
865 break
866 return level
868 def _as_name_tuples(self):
869 last = self.children[-1]
870 if last == ')':
871 last = self.children[-2]
872 elif last == '*':
873 return # No names defined directly.
875 if last.type == 'import_as_names':
876 as_names = last.children[::2]
877 else:
878 as_names = [last]
879 for as_name in as_names:
880 if as_name.type == 'name':
881 yield as_name, None
882 else:
883 yield as_name.children[::2] # yields x, y -> ``x as y``
885 def get_paths(self):
886 """
887 The import paths defined in an import statement. Typically an array
888 like this: ``[<Name: datetime>, <Name: date>]``.
890 :return list of list of Name:
891 """
892 dotted = self.get_from_names()
894 if self.children[-1] == '*':
895 return [dotted]
896 return [dotted + [name] for name, alias in self._as_name_tuples()]
899class ImportName(Import):
900 """For ``import_name`` nodes. Covers normal imports without ``from``."""
901 type = 'import_name'
902 __slots__ = ()
904 def get_defined_names(self, include_setitem=False):
905 """
906 Returns the a list of `Name` that the import defines. The defined names
907 is always the first name after `import` or in case an alias - `as` - is
908 present that name is returned.
909 """
910 return [alias or path[0] for path, alias in self._dotted_as_names()]
912 @property
913 def level(self):
914 """The level parameter of ``__import__``."""
915 return 0 # Obviously 0 for imports without from.
917 def get_paths(self):
918 return [path for path, alias in self._dotted_as_names()]
920 def _dotted_as_names(self):
921 """Generator of (list(path), alias) where alias may be None."""
922 dotted_as_names = self.children[1]
923 if dotted_as_names.type == 'dotted_as_names':
924 as_names = dotted_as_names.children[::2]
925 else:
926 as_names = [dotted_as_names]
928 for as_name in as_names:
929 if as_name.type == 'dotted_as_name':
930 alias = as_name.children[2]
931 as_name = as_name.children[0]
932 else:
933 alias = None
934 if as_name.type == 'name':
935 yield [as_name], alias
936 else:
937 # dotted_names
938 yield as_name.children[::2], alias
940 def is_nested(self):
941 """
942 This checks for the special case of nested imports, without aliases and
943 from statement::
945 import foo.bar
946 """
947 return bool([1 for path, alias in self._dotted_as_names()
948 if alias is None and len(path) > 1])
950 def _aliases(self):
951 """
952 :return list of Name: Returns all the alias
953 """
954 return dict((alias, path[-1]) for path, alias in self._dotted_as_names()
955 if alias is not None)
958class KeywordStatement(PythonBaseNode):
959 """
960 For the following statements: `assert`, `del`, `global`, `nonlocal`,
961 `raise`, `return`, `yield`.
963 `pass`, `continue` and `break` are not in there, because they are just
964 simple keywords and the parser reduces it to a keyword.
965 """
966 __slots__ = ()
968 @property
969 def type(self):
970 """
971 Keyword statements start with the keyword and end with `_stmt`. You can
972 crosscheck this with the Python grammar.
973 """
974 return '%s_stmt' % self.keyword
976 @property
977 def keyword(self):
978 return self.children[0].value
980 def get_defined_names(self, include_setitem=False):
981 keyword = self.keyword
982 if keyword == 'del':
983 return _defined_names(self.children[1], include_setitem)
984 if keyword in ('global', 'nonlocal'):
985 return self.children[1::2]
986 return []
989class AssertStmt(KeywordStatement):
990 __slots__ = ()
992 @property
993 def assertion(self):
994 return self.children[1]
997class GlobalStmt(KeywordStatement):
998 __slots__ = ()
1000 def get_global_names(self):
1001 return self.children[1::2]
1004class ReturnStmt(KeywordStatement):
1005 __slots__ = ()
1008class YieldExpr(PythonBaseNode):
1009 type = 'yield_expr'
1010 __slots__ = ()
1013def _defined_names(current, include_setitem):
1014 """
1015 A helper function to find the defined names in statements, for loops and
1016 list comprehensions.
1017 """
1018 names = []
1019 if current.type in ('testlist_star_expr', 'testlist_comp', 'exprlist', 'testlist'):
1020 for child in current.children[::2]:
1021 names += _defined_names(child, include_setitem)
1022 elif current.type in ('atom', 'star_expr'):
1023 names += _defined_names(current.children[1], include_setitem)
1024 elif current.type in ('power', 'atom_expr'):
1025 if current.children[-2] != '**': # Just if there's no operation
1026 trailer = current.children[-1]
1027 if trailer.children[0] == '.':
1028 names.append(trailer.children[1])
1029 elif trailer.children[0] == '[' and include_setitem:
1030 for node in current.children[-2::-1]:
1031 if node.type == 'trailer':
1032 names.append(node.children[1])
1033 break
1034 if node.type == 'name':
1035 names.append(node)
1036 break
1037 else:
1038 names.append(current)
1039 return names
1042class ExprStmt(PythonBaseNode, DocstringMixin):
1043 type = 'expr_stmt'
1044 __slots__ = ()
1046 def get_defined_names(self, include_setitem=False):
1047 """
1048 Returns a list of `Name` defined before the `=` sign.
1049 """
1050 names = []
1051 if self.children[1].type == 'annassign':
1052 names = _defined_names(self.children[0], include_setitem)
1053 return [
1054 name
1055 for i in range(0, len(self.children) - 2, 2)
1056 if '=' in self.children[i + 1].value
1057 for name in _defined_names(self.children[i], include_setitem)
1058 ] + names
1060 def get_rhs(self):
1061 """Returns the right-hand-side of the equals."""
1062 node = self.children[-1]
1063 if node.type == 'annassign':
1064 if len(node.children) == 4:
1065 node = node.children[3]
1066 else:
1067 node = node.children[1]
1068 return node
1070 def yield_operators(self):
1071 """
1072 Returns a generator of `+=`, `=`, etc. or None if there is no operation.
1073 """
1074 first = self.children[1]
1075 if first.type == 'annassign':
1076 if len(first.children) <= 2:
1077 return # No operator is available, it's just PEP 484.
1079 first = first.children[2]
1080 yield first
1082 yield from self.children[3::2]
1085class NamedExpr(PythonBaseNode):
1086 type = 'namedexpr_test'
1088 def get_defined_names(self, include_setitem=False):
1089 return _defined_names(self.children[0], include_setitem)
1092class Param(PythonBaseNode):
1093 """
1094 It's a helper class that makes business logic with params much easier. The
1095 Python grammar defines no ``param`` node. It defines it in a different way
1096 that is not really suited to working with parameters.
1097 """
1098 type = 'param'
1100 def __init__(self, children, parent=None):
1101 super().__init__(children)
1102 self.parent = parent
1104 @property
1105 def star_count(self):
1106 """
1107 Is `0` in case of `foo`, `1` in case of `*foo` or `2` in case of
1108 `**foo`.
1109 """
1110 first = self.children[0]
1111 if first in ('*', '**'):
1112 return len(first.value)
1113 return 0
1115 @property
1116 def default(self):
1117 """
1118 The default is the test node that appears after the `=`. Is `None` in
1119 case no default is present.
1120 """
1121 has_comma = self.children[-1] == ','
1122 try:
1123 if self.children[-2 - int(has_comma)] == '=':
1124 return self.children[-1 - int(has_comma)]
1125 except IndexError:
1126 return None
1128 @property
1129 def annotation(self):
1130 """
1131 The default is the test node that appears after `:`. Is `None` in case
1132 no annotation is present.
1133 """
1134 tfpdef = self._tfpdef()
1135 if tfpdef.type == 'tfpdef':
1136 assert tfpdef.children[1] == ":"
1137 assert len(tfpdef.children) == 3
1138 annotation = tfpdef.children[2]
1139 return annotation
1140 else:
1141 return None
1143 def _tfpdef(self):
1144 """
1145 tfpdef: see e.g. grammar36.txt.
1146 """
1147 offset = int(self.children[0] in ('*', '**'))
1148 return self.children[offset]
1150 @property
1151 def name(self):
1152 """
1153 The `Name` leaf of the param.
1154 """
1155 if self._tfpdef().type == 'tfpdef':
1156 return self._tfpdef().children[0]
1157 else:
1158 return self._tfpdef()
1160 def get_defined_names(self, include_setitem=False):
1161 return [self.name]
1163 @property
1164 def position_index(self):
1165 """
1166 Property for the positional index of a paramter.
1167 """
1168 index = self.parent.children.index(self)
1169 try:
1170 keyword_only_index = self.parent.children.index('*')
1171 if index > keyword_only_index:
1172 # Skip the ` *, `
1173 index -= 2
1174 except ValueError:
1175 pass
1176 try:
1177 keyword_only_index = self.parent.children.index('/')
1178 if index > keyword_only_index:
1179 # Skip the ` /, `
1180 index -= 2
1181 except ValueError:
1182 pass
1183 return index - 1
1185 def get_parent_function(self):
1186 """
1187 Returns the function/lambda of a parameter.
1188 """
1189 return self.search_ancestor('funcdef', 'lambdef')
1191 def get_code(self, include_prefix=True, include_comma=True):
1192 """
1193 Like all the other get_code functions, but includes the param
1194 `include_comma`.
1196 :param include_comma bool: If enabled includes the comma in the string output.
1197 """
1198 if include_comma:
1199 return super().get_code(include_prefix)
1201 children = self.children
1202 if children[-1] == ',':
1203 children = children[:-1]
1204 return self._get_code_for_children(
1205 children,
1206 include_prefix=include_prefix
1207 )
1209 def __repr__(self):
1210 default = '' if self.default is None else '=%s' % self.default.get_code()
1211 return '<%s: %s>' % (type(self).__name__, str(self._tfpdef()) + default)
1214class SyncCompFor(PythonBaseNode):
1215 type = 'sync_comp_for'
1216 __slots__ = ()
1218 def get_defined_names(self, include_setitem=False):
1219 """
1220 Returns the a list of `Name` that the comprehension defines.
1221 """
1222 # allow async for
1223 return _defined_names(self.children[1], include_setitem)
1226# This is simply here so an older Jedi version can work with this new parso
1227# version. Can be deleted in the next release.
1228CompFor = SyncCompFor
1231class UsedNamesMapping(Mapping):
1232 """
1233 This class exists for the sole purpose of creating an immutable dict.
1234 """
1235 def __init__(self, dct):
1236 self._dict = dct
1238 def __getitem__(self, key):
1239 return self._dict[key]
1241 def __len__(self):
1242 return len(self._dict)
1244 def __iter__(self):
1245 return iter(self._dict)
1247 def __hash__(self):
1248 return id(self)
1250 def __eq__(self, other):
1251 # Comparing these dicts does not make sense.
1252 return self is other