Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
#: Sequence of :class:`Dot` nodes indicating relative import level.
relative: Sequence[Dot] = ()
#: Optional open parenthesis for multi-line import continuation.
lpar: Optional[LeftParen] = None
#: Optional close parenthesis for multi-line import continuation.
rpar: Optional[RightParen] = None
#: Optional semicolon when this is used in a statement line. This semicolon
#: owns the whitespace on both sides of it when it is used.
semicolon: Union[Semicolon, MaybeSentinel] = MaybeSentinel.DEFAULT
#: The whitespace that appears after the ``from`` keyword but before
#: the module and any relative import dots.
whitespace_after_from: SimpleWhitespace = SimpleWhitespace.field(" ")
#: The whitespace that appears after the module but before the
#: ``import`` keyword.
whitespace_before_import: SimpleWhitespace = SimpleWhitespace.field(" ")
#: The whitespace that appears after the ``import`` keyword but
#: before the first import name or optional left paren.
whitespace_after_import: SimpleWhitespace = SimpleWhitespace.field(" ")
def _validate_module(self) -> None:
if self.module is None and len(self.relative) == 0:
raise CSTValidationError(
"Must have a module specified if there is no relative import."
)
def _validate_names(self) -> None:
...
@add_slots
@dataclass(frozen=True)
class Del(BaseSmallStatement):
"""
Represents a ``del`` statement. ``del`` is always followed by a target.
"""
#: The target expression will be deleted. This can be a name, a tuple,
#: an item of a list, an item of a dictionary, or an attribute.
target: BaseDelTargetExpression
#: The whitespace after the ``del`` keyword.
whitespace_after_del: SimpleWhitespace = SimpleWhitespace.field(" ")
#: Optional semicolon when this is used in a statement line. This semicolon
#: owns the whitespace on both sides of it when it is used.
semicolon: Union[Semicolon, MaybeSentinel] = MaybeSentinel.DEFAULT
def _validate(self) -> None:
if (
self.whitespace_after_del.empty
and not self.target._safe_to_use_with_word_operator(
ExpressionPosition.RIGHT
)
):
raise CSTValidationError("Must have at least one space after 'del'.")
def _visit_and_replace_children(self, visitor: CSTVisitorT) -> "Del":
return Del(
:class:`TrailingWhitespace`. If you have whitespace that does not contain
comments or newlines, use :class:`SimpleWhitespace` instead.
"""
#: The whitespace that comes after the previous node, up to and including
#: the end-of-line comment and newline.
first_line: TrailingWhitespace = TrailingWhitespace.field()
#: Any lines after the first that contain only indentation and/or comments.
empty_lines: Sequence[EmptyLine] = ()
#: Whether or not the final simple whitespace is indented regularly.
indent: bool = False
#: Extra whitespace after the indent, but before the next node.
last_line: SimpleWhitespace = SimpleWhitespace.field("")
def _visit_and_replace_children(
self, visitor: CSTVisitorT
) -> "ParenthesizedWhitespace":
return ParenthesizedWhitespace(
first_line=visit_required(self, "first_line", self.first_line, visitor),
empty_lines=visit_sequence(self, "empty_lines", self.empty_lines, visitor),
indent=self.indent,
last_line=visit_required(self, "last_line", self.last_line, visitor),
)
def _codegen_impl(self, state: CodegenState) -> None:
self.first_line._codegen(state)
for line in self.empty_lines:
line._codegen(state)
if self.indent:
#: Optional async modifier, if this is an async function.
asynchronous: Optional[Asynchronous] = None
#: Leading empty lines and comments before the first decorator. We
#: assume any comments before the first decorator are owned by the
#: function definition itself. If there are no decorators, this will
#: still contain all of the empty lines and comments before the
#: function definition.
leading_lines: Sequence[EmptyLine] = ()
#: Empty lines and comments between the final decorator and the
#: :class:`FunctionDef` node. In the case of no decorators, this will be empty.
lines_after_decorators: Sequence[EmptyLine] = ()
#: Whitespace after the ``def`` keyword and before the function name.
whitespace_after_def: SimpleWhitespace = SimpleWhitespace.field(" ")
#: Whitespace after the function name and before the opening parenthesis for
#: the parameters.
whitespace_after_name: SimpleWhitespace = SimpleWhitespace.field("")
#: Whitespace after the opening parenthesis for the parameters but before
#: the first param itself.
whitespace_before_params: SimpleWhitespace = SimpleWhitespace.field("")
#: Whitespace after the closing parenthesis or return annotation and before
#: the colon.
whitespace_before_colon: SimpleWhitespace = SimpleWhitespace.field("")
def _validate(self) -> None:
if len(self.name.lpar) > 0 or len(self.name.rpar) > 0:
raise CSTValidationError("Cannot have parens around Name in a FunctionDef.")
#: The arguments to pass to the resulting callable. These may be a mix of
#: positional arguments, keyword arguments, or "starred" arguments.
args: Sequence[Arg] = ()
lpar: Sequence[LeftParen] = ()
#: Sequence of parenthesis for precedence dictation. These are not the parenthesis
#: before and after the list of ``args``, but rather arguments around the entire
#: call expression, such as ``(( do_math(1, 2) ))``.
rpar: Sequence[RightParen] = ()
#: Whitespace after the ``func`` name, but before the opening parenthesis.
whitespace_after_func: BaseParenthesizableWhitespace = SimpleWhitespace.field("")
#: Whitespace after the opening parenthesis but before the first argument (if there
#: are any). Whitespace after the last argument but before the closing parenthesis
#: is owned by the last :class:`Arg` if it exists.
whitespace_before_args: BaseParenthesizableWhitespace = SimpleWhitespace.field("")
def _safe_to_use_with_word_operator(self, position: ExpressionPosition) -> bool:
"""
Calls have a close paren on the right side regardless of whether they're
parenthesized as a whole. As a result, they are safe to use directly against
an adjacent node to the right.
"""
if position == ExpressionPosition.LEFT:
return True
if super(Call, self)._safe_to_use_with_word_operator(position):
return True
if position == ExpressionPosition.RIGHT:
return self.func._safe_to_use_with_word_operator(ExpressionPosition.RIGHT)
return False
def _visit_and_replace_children(self, visitor: CSTVisitorT) -> "Call":
def _codegen_impl(self, state: CodegenState) -> None:
self.whitespace_before._codegen(state)
state.add_token("}")
@add_slots
@dataclass(frozen=True)
class LeftParen(CSTNode):
"""
Used by various nodes to denote a parenthesized section. This doesn't own
the whitespace to the left of it since this is owned by the parent node.
"""
#: Any space that appears directly after this left parenthesis.
whitespace_after: BaseParenthesizableWhitespace = SimpleWhitespace.field("")
def _visit_and_replace_children(self, visitor: CSTVisitorT) -> "LeftParen":
return LeftParen(
whitespace_after=visit_required(
self, "whitespace_after", self.whitespace_after, visitor
)
)
def _codegen_impl(self, state: CodegenState) -> None:
state.add_token("(")
self.whitespace_after._codegen(state)
@add_slots
@dataclass(frozen=True)
class RightParen(CSTNode):
"""
#: A sequence of one or more items that evaluate to context managers.
items: Sequence[WithItem]
#: The suite that is wrapped with this statement.
body: BaseSuite
#: Optional async modifier if this is an ``async with`` statement.
asynchronous: Optional[Asynchronous] = None
#: Sequence of empty lines appearing before this with statement.
leading_lines: Sequence[EmptyLine] = ()
#: Whitespace after the ``with`` keyword and before the first item.
whitespace_after_with: SimpleWhitespace = SimpleWhitespace.field(" ")
#: Whitespace after the last item and before the colon.
whitespace_before_colon: SimpleWhitespace = SimpleWhitespace.field("")
def _validate(self) -> None:
if len(self.items) == 0:
raise CSTValidationError(
"A With statement must have at least one WithItem."
)
if self.items[-1].comma != MaybeSentinel.DEFAULT:
raise CSTValidationError(
"The last WithItem in a With cannot have a trailing comma."
)
if self.whitespace_after_with.empty and not self.items[
0
].item._safe_to_use_with_word_operator(ExpressionPosition.RIGHT):
class CompIf(CSTNode):
"""
A conditional clause in a :class:`CompFor`, used as part of a generator or
comprehension expression.
If the ``test`` fails, the current element in the :class:`CompFor` will be skipped.
"""
#: An expression to evaluate. When interpreted, Python will coerce it to a boolean.
test: BaseExpression
#: Whitespace before the ``if`` keyword.
whitespace_before: BaseParenthesizableWhitespace = SimpleWhitespace.field(" ")
#: Whitespace after the ``if`` keyword, but before the ``test`` expression.
whitespace_before_test: BaseParenthesizableWhitespace = SimpleWhitespace.field(" ")
def _validate(self) -> None:
if (
self.whitespace_before_test.empty
and not self.test._safe_to_use_with_word_operator(ExpressionPosition.RIGHT)
):
raise CSTValidationError("Must have at least one space after 'if' keyword.")
def _visit_and_replace_children(self, visitor: CSTVisitorT) -> "CompIf":
return CompIf(
whitespace_before=visit_required(
self, "whitespace_before", self.whitespace_before, visitor
),
whitespace_before_test=visit_required(
self, "whitespace_before_test", self.whitespace_before_test, visitor
),
default: Optional[BaseExpression] = None
#: A trailing comma. If one is not provided, :class:`MaybeSentinel` will be
#: replaced with a comma only if a comma is required.
comma: Union[Comma, MaybeSentinel] = MaybeSentinel.DEFAULT
#: Zero, one, or two asterisks appearing before name for :class:`Param`'s
#: ``star_arg`` and ``star_kwarg``.
star: Union[str, MaybeSentinel] = MaybeSentinel.DEFAULT
#: The whitespace before ``name``. It will appear after ``star`` when a star
#: exists.
whitespace_after_star: BaseParenthesizableWhitespace = SimpleWhitespace.field("")
#: The whitespace after this entire node.
whitespace_after_param: BaseParenthesizableWhitespace = SimpleWhitespace.field("")
def _validate(self) -> None:
if self.default is None and isinstance(self.equal, AssignEqual):
raise CSTValidationError(
"Must have a default when specifying an AssignEqual."
)
if isinstance(self.star, str) and self.star not in ("", "*", "**"):
raise CSTValidationError("Must specify either '', '*' or '**' for star.")
def _visit_and_replace_children(self, visitor: CSTVisitorT) -> "Param":
return Param(
star=self.star,
whitespace_after_star=visit_required(
self, "whitespace_after_star", self.whitespace_after_star, visitor
),
name=visit_required(self, "name", self.name, visitor),
def _codegen_impl(self, state: CodegenState) -> None:
self.whitespace_before._codegen(state)
state.add_token(")")
@add_slots
@dataclass(frozen=True)
class Asynchronous(CSTNode):
"""
Used by asynchronous function definitions, as well as ``async for`` and
``async with``.
"""
#: Any space that appears directly after this async keyword.
whitespace_after: SimpleWhitespace = SimpleWhitespace.field(" ")
def _validate(self) -> None:
if len(self.whitespace_after.value) < 1:
raise CSTValidationError("Must have at least one space after Asynchronous.")
def _visit_and_replace_children(self, visitor: CSTVisitorT) -> "Asynchronous":
return Asynchronous(
whitespace_after=visit_required(
self, "whitespace_after", self.whitespace_after, visitor
)
)
def _codegen_impl(self, state: CodegenState) -> None:
with state.record_syntactic_position(self):
state.add_token("async")
self.whitespace_after._codegen(state)