Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
config: ParserConfig,
children: typing.Sequence[typing.Any],
single_child_is_sequence: bool,
sequence_type: typing.Union[
typing.Type[Tuple], typing.Type[List], typing.Type[Set]
],
) -> typing.Any:
if not single_child_is_sequence and len(children) == 1:
return children[0]
# N.B. The parent node (e.g. atom) is responsible for computing and attaching
# whitespace information on any parenthesis, square brackets, or curly braces
elements = []
for wrapped_expr_or_starred_element, comma_token in grouper(children, 2):
expr_or_starred_element = wrapped_expr_or_starred_element.value
if comma_token is None:
comma = MaybeSentinel.DEFAULT
else:
comma = Comma(
whitespace_before=parse_parenthesizable_whitespace(
config, comma_token.whitespace_before
),
# Only compute whitespace_after if we're not a trailing comma.
# If we're a trailing comma, that whitespace should be consumed by the
# TrailingWhitespace, parenthesis, etc.
whitespace_after=(
parse_parenthesizable_whitespace(
config, comma_token.whitespace_after
)
if comma_token is not children[-1]
else SimpleWhitespace("")
),
)
This supports named keyword arguments in the form of ``keyword=value`` and variable
argument expansion using ``*args`` or ``**kwargs`` syntax.
"""
#: The argument expression itself, not including a preceding keyword, or any of
#: the surrounding the value, like a comma or asterisks.
value: BaseExpression
#: Optional keyword for the argument.
keyword: Optional[Name] = None
#: The equals sign used to denote assignment if there is a keyword.
equal: Union[AssignEqual, MaybeSentinel] = MaybeSentinel.DEFAULT
#: Any trailing comma.
comma: Union[Comma, MaybeSentinel] = MaybeSentinel.DEFAULT
#: A string with zero, one, or two asterisks appearing before the name. These are
#: expanded into variable number of positional or keyword arguments.
star: Literal["", "*", "**"] = ""
#: Whitespace after the ``star`` (if it exists), but before the ``keyword`` or
#: ``value`` (if no keyword is provided).
whitespace_after_star: BaseParenthesizableWhitespace = SimpleWhitespace.field("")
#: Whitespace after this entire node. The :class:`Comma` node (if it exists) may
#: also store some trailing whitespace.
whitespace_after_arg: BaseParenthesizableWhitespace = SimpleWhitespace.field("")
def _validate(self) -> None:
if self.keyword is None and isinstance(self.equal, AssignEqual):
raise CSTValidationError(
"Must have a keyword when specifying an AssignEqual."
"""
#: The lower bound in the slice, if present
lower: Optional[BaseExpression]
#: The upper bound in the slice, if present
upper: Optional[BaseExpression]
#: The step in the slice, if present
step: Optional[BaseExpression] = None
#: The first slice operator
first_colon: Colon = Colon.field()
#: The second slice operator, usually omitted
second_colon: Union[Colon, MaybeSentinel] = MaybeSentinel.DEFAULT
def _visit_and_replace_children(self, visitor: CSTVisitorT) -> "Slice":
return Slice(
lower=visit_optional(self, "lower", self.lower, visitor),
first_colon=visit_required(self, "first_colon", self.first_colon, visitor),
upper=visit_optional(self, "upper", self.upper, visitor),
second_colon=visit_sentinel(
self, "second_colon", self.second_colon, visitor
),
step=visit_optional(self, "step", self.step, visitor),
)
def _codegen_impl(self, state: CodegenState) -> None:
lower = self.lower
if lower is not None:
lower._codegen(state)
@add_slots
@dataclass(frozen=True)
class From(CSTNode):
"""
A ``from x`` stanza in a :class:`Yield` or :class:`Raise`.
"""
#: The expression that we are yielding/raising from.
item: BaseExpression
#: The whitespace at the very start of this node.
whitespace_before_from: Union[
BaseParenthesizableWhitespace, MaybeSentinel
] = MaybeSentinel.DEFAULT
#: The whitespace after the ``from`` keyword, but before the ``item``.
whitespace_after_from: BaseParenthesizableWhitespace = SimpleWhitespace.field(" ")
def _validate(self) -> None:
if (
isinstance(self.whitespace_after_from, BaseParenthesizableWhitespace)
and self.whitespace_after_from.empty
and not self.item._safe_to_use_with_word_operator(ExpressionPosition.RIGHT)
):
raise CSTValidationError(
"Must have at least one space after 'from' keyword."
)
def _visit_and_replace_children(self, visitor: CSTVisitorT) -> "From":
return From(
"""
A single argument to a :class:`Call`.
This supports named keyword arguments in the form of ``keyword=value`` and variable
argument expansion using ``*args`` or ``**kwargs`` syntax.
"""
#: The argument expression itself, not including a preceding keyword, or any of
#: the surrounding the value, like a comma or asterisks.
value: BaseExpression
#: Optional keyword for the argument.
keyword: Optional[Name] = None
#: The equals sign used to denote assignment if there is a keyword.
equal: Union[AssignEqual, MaybeSentinel] = MaybeSentinel.DEFAULT
#: Any trailing comma.
comma: Union[Comma, MaybeSentinel] = MaybeSentinel.DEFAULT
#: A string with zero, one, or two asterisks appearing before the name. These are
#: expanded into variable number of positional or keyword arguments.
star: Literal["", "*", "**"] = ""
#: Whitespace after the ``star`` (if it exists), but before the ``keyword`` or
#: ``value`` (if no keyword is provided).
whitespace_after_star: BaseParenthesizableWhitespace = SimpleWhitespace.field("")
#: Whitespace after this entire node. The :class:`Comma` node (if it exists) may
#: also store some trailing whitespace.
whitespace_after_arg: BaseParenthesizableWhitespace = SimpleWhitespace.field("")
def _validate(self) -> None:
def convert_decorator(config: ParserConfig, children: Sequence[Any]) -> Any:
atsign, name, *arglist, newline = children
if not arglist:
# This is either a name or an attribute node, so just extract it.
decoratornode = name
else:
# This needs to be converted into a call node, and we have the
# arglist partial.
lpar, *args, rpar = arglist
args = args[0].args if args else []
# If the trailing argument doesn't have a comma, then it owns the
# trailing whitespace before the rpar. Otherwise, the comma owns
# it.
if len(args) > 0 and args[-1].comma == MaybeSentinel.DEFAULT:
args[-1] = args[-1].with_changes(
whitespace_after_arg=parse_parenthesizable_whitespace(
config, rpar.whitespace_before
)
)
decoratornode = Call(
func=name,
whitespace_after_func=parse_simple_whitespace(
config, lpar.whitespace_before
),
whitespace_before_args=parse_parenthesizable_whitespace(
config, lpar.whitespace_after
),
args=tuple(args),
)
def _validate(self) -> None:
if len(self.names) == 0:
raise CSTValidationError(
"A Nonlocal statement must have at least one NameItem."
)
if self.names[-1].comma != MaybeSentinel.DEFAULT:
raise CSTValidationError(
"The last NameItem in a Nonlocal cannot have a trailing comma."
)
if self.whitespace_after_nonlocal.empty:
raise CSTValidationError(
"Must have at least one space after 'nonlocal' keyword."
)
def convert_argslist(config: ParserConfig, children: Sequence[Any]) -> Any:
params: List[Param] = []
seen_default: bool = False
star_arg: Union[Param, ParamStar, MaybeSentinel] = MaybeSentinel.DEFAULT
kwonly_params: List[Param] = []
star_kwarg: Optional[Param] = None
def add_param(
current_param: Optional[List[Param]], param: Union[Param, ParamStar]
) -> Optional[List[Param]]:
nonlocal star_arg
nonlocal star_kwarg
nonlocal seen_default
if isinstance(param, ParamStar):
# Only can add this if we don't already have a "*" or a "*param".
if current_param is params:
star_arg = param
current_param = kwonly_params
else:
name: Name
#: The class body.
body: BaseSuite
#: Sequence of base classes this class inherits from.
bases: Sequence[Arg] = ()
#: Sequence of keywords, such as "metaclass".
keywords: Sequence[Arg] = ()
#: Sequence of decorators applied to this class.
decorators: Sequence[Decorator] = ()
#: Optional open parenthesis used when there are bases or keywords.
lpar: Union[LeftParen, MaybeSentinel] = MaybeSentinel.DEFAULT
#: Optional close parenthesis used when there are bases or keywords.
rpar: Union[RightParen, MaybeSentinel] = MaybeSentinel.DEFAULT
#: Leading empty lines and comments before the first decorator. We
#: assume any comments before the first decorator are owned by the
#: class definition itself. If there are no decorators, this will
#: still contain all of the empty lines and comments before the
#: class definition.
leading_lines: Sequence[EmptyLine] = ()
#: Empty lines and comments between the final decorator and the
#: :class:`ClassDef` node. In the case of no decorators, this will be empty.
lines_after_decorators: Sequence[EmptyLine] = ()
#: Whitespace after the ``class`` keyword and before the class name.