LibCST/libcst/_nodes/tests/test_funcdef.py
martin 9542fc3882
remove entry points to pure parser (#1375)
* rm: ci

* rm: entry point

* fix: tests

* fix: remove combine step from ci

* linter fixes

* omit the _parser

* fix newlines

* fix: remove optional

* fix: linter

---------

Co-authored-by: thereversiblewheel <martin.li@uwaterloo.ca>
2025-07-30 16:27:20 +00:00

2267 lines
95 KiB
Python

# Copyright (c) Meta Platforms, Inc. and affiliates.
#
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.
from typing import Any, Callable
import libcst as cst
from libcst import parse_statement
from libcst._nodes.tests.base import CSTNodeTest, DummyIndentedBlock, parse_statement_as
from libcst.metadata import CodeRange
from libcst.testing.utils import data_provider
class FunctionDefCreationTest(CSTNodeTest):
@data_provider(
(
# Simple function definition without any arguments or return
{
"node": cst.FunctionDef(
cst.Name("foo"),
cst.Parameters(),
cst.SimpleStatementSuite((cst.Pass(),)),
),
"code": "def foo(): pass\n",
},
# Functiondef with a return annotation
{
"node": cst.FunctionDef(
cst.Name("foo"),
cst.Parameters(),
cst.SimpleStatementSuite((cst.Pass(),)),
returns=cst.Annotation(cst.Name("str")),
),
"code": "def foo() -> str: pass\n",
"expected_position": CodeRange((1, 0), (1, 22)),
},
# Async function definition.
{
"node": cst.FunctionDef(
cst.Name("foo"),
cst.Parameters(),
cst.SimpleStatementSuite((cst.Pass(),)),
asynchronous=cst.Asynchronous(),
),
"code": "async def foo(): pass\n",
},
# Async function definition with annotation.
{
"node": cst.FunctionDef(
cst.Name("foo"),
cst.Parameters(),
cst.SimpleStatementSuite((cst.Pass(),)),
asynchronous=cst.Asynchronous(),
returns=cst.Annotation(cst.Name("int")),
),
"code": "async def foo() -> int: pass\n",
"expected_position": CodeRange((1, 0), (1, 28)),
},
# Test basic positional params
{
"node": cst.FunctionDef(
cst.Name("foo"),
cst.Parameters(
params=(cst.Param(cst.Name("bar")), cst.Param(cst.Name("baz")))
),
cst.SimpleStatementSuite((cst.Pass(),)),
),
"code": "def foo(bar, baz): pass\n",
},
# Typed positional params
{
"node": cst.FunctionDef(
cst.Name("foo"),
cst.Parameters(
params=(
cst.Param(cst.Name("bar"), cst.Annotation(cst.Name("str"))),
cst.Param(cst.Name("baz"), cst.Annotation(cst.Name("int"))),
)
),
cst.SimpleStatementSuite((cst.Pass(),)),
),
"code": "def foo(bar: str, baz: int): pass\n",
},
# Test basic positional default params
{
"node": cst.FunctionDef(
cst.Name("foo"),
cst.Parameters(
params=(
cst.Param(
cst.Name("bar"), default=cst.SimpleString('"one"')
),
cst.Param(cst.Name("baz"), default=cst.Integer("5")),
)
),
cst.SimpleStatementSuite((cst.Pass(),)),
),
"code": 'def foo(bar = "one", baz = 5): pass\n',
},
# Typed positional default params
{
"node": cst.FunctionDef(
cst.Name("foo"),
cst.Parameters(
params=(
cst.Param(
cst.Name("bar"),
cst.Annotation(cst.Name("str")),
default=cst.SimpleString('"one"'),
),
cst.Param(
cst.Name("baz"),
cst.Annotation(cst.Name("int")),
default=cst.Integer("5"),
),
)
),
cst.SimpleStatementSuite((cst.Pass(),)),
),
"code": 'def foo(bar: str = "one", baz: int = 5): pass\n',
},
# Test basic positional only params
{
"node": cst.FunctionDef(
cst.Name("foo"),
cst.Parameters(
posonly_params=(
cst.Param(cst.Name("bar")),
cst.Param(cst.Name("baz")),
)
),
cst.SimpleStatementSuite((cst.Pass(),)),
),
"code": "def foo(bar, baz, /): pass\n",
},
# Typed positional only params
{
"node": cst.FunctionDef(
cst.Name("foo"),
cst.Parameters(
posonly_params=(
cst.Param(cst.Name("bar"), cst.Annotation(cst.Name("str"))),
cst.Param(cst.Name("baz"), cst.Annotation(cst.Name("int"))),
)
),
cst.SimpleStatementSuite((cst.Pass(),)),
),
"code": "def foo(bar: str, baz: int, /): pass\n",
},
# Test basic positional only default params
{
"node": cst.FunctionDef(
cst.Name("foo"),
cst.Parameters(
posonly_params=(
cst.Param(
cst.Name("bar"), default=cst.SimpleString('"one"')
),
cst.Param(cst.Name("baz"), default=cst.Integer("5")),
)
),
cst.SimpleStatementSuite((cst.Pass(),)),
),
"code": 'def foo(bar = "one", baz = 5, /): pass\n',
},
# Typed positional only default params
{
"node": cst.FunctionDef(
cst.Name("foo"),
cst.Parameters(
posonly_params=(
cst.Param(
cst.Name("bar"),
cst.Annotation(cst.Name("str")),
default=cst.SimpleString('"one"'),
),
cst.Param(
cst.Name("baz"),
cst.Annotation(cst.Name("int")),
default=cst.Integer("5"),
),
)
),
cst.SimpleStatementSuite((cst.Pass(),)),
),
"code": 'def foo(bar: str = "one", baz: int = 5, /): pass\n',
},
# Mixed positional and default params.
{
"node": cst.FunctionDef(
cst.Name("foo"),
cst.Parameters(
params=(
cst.Param(cst.Name("bar"), cst.Annotation(cst.Name("str"))),
cst.Param(
cst.Name("baz"),
cst.Annotation(cst.Name("int")),
default=cst.Integer("5"),
),
)
),
cst.SimpleStatementSuite((cst.Pass(),)),
),
"code": "def foo(bar: str, baz: int = 5): pass\n",
},
# Test kwonly params
{
"node": cst.FunctionDef(
cst.Name("foo"),
cst.Parameters(
kwonly_params=(
cst.Param(
cst.Name("bar"), default=cst.SimpleString('"one"')
),
cst.Param(cst.Name("baz")),
)
),
cst.SimpleStatementSuite((cst.Pass(),)),
),
"code": 'def foo(*, bar = "one", baz): pass\n',
},
# Typed kwonly params
{
"node": cst.FunctionDef(
cst.Name("foo"),
cst.Parameters(
kwonly_params=(
cst.Param(
cst.Name("bar"),
cst.Annotation(cst.Name("str")),
default=cst.SimpleString('"one"'),
),
cst.Param(cst.Name("baz"), cst.Annotation(cst.Name("int"))),
cst.Param(
cst.Name("biz"),
cst.Annotation(cst.Name("str")),
default=cst.SimpleString('"two"'),
),
)
),
cst.SimpleStatementSuite((cst.Pass(),)),
),
"code": 'def foo(*, bar: str = "one", baz: int, biz: str = "two"): pass\n',
},
# Mixed params and kwonly_params
{
"node": cst.FunctionDef(
cst.Name("foo"),
cst.Parameters(
params=(
cst.Param(cst.Name("first")),
cst.Param(cst.Name("second")),
),
kwonly_params=(
cst.Param(
cst.Name("bar"),
cst.Annotation(cst.Name("str")),
default=cst.SimpleString('"one"'),
),
cst.Param(cst.Name("baz"), cst.Annotation(cst.Name("int"))),
cst.Param(
cst.Name("biz"),
cst.Annotation(cst.Name("str")),
default=cst.SimpleString('"two"'),
),
),
),
cst.SimpleStatementSuite((cst.Pass(),)),
),
"code": 'def foo(first, second, *, bar: str = "one", baz: int, biz: str = "two"): pass\n',
},
# Mixed params and kwonly_params
{
"node": cst.FunctionDef(
cst.Name("foo"),
cst.Parameters(
params=(
cst.Param(cst.Name("first"), default=cst.Float("1.0")),
cst.Param(cst.Name("second"), default=cst.Float("1.5")),
),
kwonly_params=(
cst.Param(
cst.Name("bar"),
cst.Annotation(cst.Name("str")),
default=cst.SimpleString('"one"'),
),
cst.Param(cst.Name("baz"), cst.Annotation(cst.Name("int"))),
cst.Param(
cst.Name("biz"),
cst.Annotation(cst.Name("str")),
default=cst.SimpleString('"two"'),
),
),
),
cst.SimpleStatementSuite((cst.Pass(),)),
),
"code": 'def foo(first = 1.0, second = 1.5, *, bar: str = "one", baz: int, biz: str = "two"): pass\n',
},
# Mixed params and kwonly_params
{
"node": cst.FunctionDef(
cst.Name("foo"),
cst.Parameters(
params=(
cst.Param(cst.Name("first")),
cst.Param(cst.Name("second")),
cst.Param(cst.Name("third"), default=cst.Float("1.0")),
cst.Param(cst.Name("fourth"), default=cst.Float("1.5")),
),
kwonly_params=(
cst.Param(
cst.Name("bar"),
cst.Annotation(cst.Name("str")),
default=cst.SimpleString('"one"'),
),
cst.Param(cst.Name("baz"), cst.Annotation(cst.Name("int"))),
cst.Param(
cst.Name("biz"),
cst.Annotation(cst.Name("str")),
default=cst.SimpleString('"two"'),
),
),
),
cst.SimpleStatementSuite((cst.Pass(),)),
),
"code": 'def foo(first, second, third = 1.0, fourth = 1.5, *, bar: str = "one", baz: int, biz: str = "two"): pass\n',
},
# Test star_arg
{
"node": cst.FunctionDef(
cst.Name("foo"),
cst.Parameters(star_arg=cst.Param(cst.Name("params"))),
cst.SimpleStatementSuite((cst.Pass(),)),
),
"code": "def foo(*params): pass\n",
},
# Typed star_arg, include kwonly_params
{
"node": cst.FunctionDef(
cst.Name("foo"),
cst.Parameters(
star_arg=cst.Param(
cst.Name("params"), cst.Annotation(cst.Name("str"))
),
kwonly_params=(
cst.Param(
cst.Name("bar"),
cst.Annotation(cst.Name("str")),
default=cst.SimpleString('"one"'),
),
cst.Param(cst.Name("baz"), cst.Annotation(cst.Name("int"))),
cst.Param(
cst.Name("biz"),
cst.Annotation(cst.Name("str")),
default=cst.SimpleString('"two"'),
),
),
),
cst.SimpleStatementSuite((cst.Pass(),)),
),
"code": 'def foo(*params: str, bar: str = "one", baz: int, biz: str = "two"): pass\n',
},
# Mixed params star_arg and kwonly_params
{
"node": cst.FunctionDef(
cst.Name("foo"),
cst.Parameters(
params=(
cst.Param(cst.Name("first")),
cst.Param(cst.Name("second")),
cst.Param(cst.Name("third"), default=cst.Float("1.0")),
cst.Param(cst.Name("fourth"), default=cst.Float("1.5")),
),
star_arg=cst.Param(
cst.Name("params"), cst.Annotation(cst.Name("str"))
),
kwonly_params=(
cst.Param(
cst.Name("bar"),
cst.Annotation(cst.Name("str")),
default=cst.SimpleString('"one"'),
),
cst.Param(cst.Name("baz"), cst.Annotation(cst.Name("int"))),
cst.Param(
cst.Name("biz"),
cst.Annotation(cst.Name("str")),
default=cst.SimpleString('"two"'),
),
),
),
cst.SimpleStatementSuite((cst.Pass(),)),
),
"code": 'def foo(first, second, third = 1.0, fourth = 1.5, *params: str, bar: str = "one", baz: int, biz: str = "two"): pass\n',
},
# Test star_arg and star_kwarg
{
"node": cst.FunctionDef(
cst.Name("foo"),
cst.Parameters(star_kwarg=cst.Param(cst.Name("kwparams"))),
cst.SimpleStatementSuite((cst.Pass(),)),
),
"code": "def foo(**kwparams): pass\n",
},
# Test star_arg and kwarg
{
"node": cst.FunctionDef(
cst.Name("foo"),
cst.Parameters(
star_arg=cst.Param(cst.Name("params")),
star_kwarg=cst.Param(cst.Name("kwparams")),
),
cst.SimpleStatementSuite((cst.Pass(),)),
),
"code": "def foo(*params, **kwparams): pass\n",
},
# Test typed star_arg and star_kwarg
{
"node": cst.FunctionDef(
cst.Name("foo"),
cst.Parameters(
star_arg=cst.Param(
cst.Name("params"), cst.Annotation(cst.Name("str"))
),
star_kwarg=cst.Param(
cst.Name("kwparams"), cst.Annotation(cst.Name("int"))
),
),
cst.SimpleStatementSuite((cst.Pass(),)),
),
"code": "def foo(*params: str, **kwparams: int): pass\n",
},
# Test positional only params and positional params
{
"node": cst.FunctionDef(
cst.Name("foo"),
cst.Parameters(
posonly_params=(cst.Param(cst.Name("bar")),),
params=(cst.Param(cst.Name("baz")),),
),
cst.SimpleStatementSuite((cst.Pass(),)),
),
"code": "def foo(bar, /, baz): pass\n",
},
# Test positional only params and star args
{
"node": cst.FunctionDef(
cst.Name("foo"),
cst.Parameters(
posonly_params=(cst.Param(cst.Name("bar")),),
star_arg=cst.Param(cst.Name("baz")),
),
cst.SimpleStatementSuite((cst.Pass(),)),
),
"code": "def foo(bar, /, *baz): pass\n",
},
# Test positional only params and kwonly params
{
"node": cst.FunctionDef(
cst.Name("foo"),
cst.Parameters(
posonly_params=(cst.Param(cst.Name("bar")),),
kwonly_params=(cst.Param(cst.Name("baz")),),
),
cst.SimpleStatementSuite((cst.Pass(),)),
),
"code": "def foo(bar, /, *, baz): pass\n",
},
# Test positional only params and star kwargs
{
"node": cst.FunctionDef(
cst.Name("foo"),
cst.Parameters(
posonly_params=(cst.Param(cst.Name("bar")),),
star_kwarg=cst.Param(cst.Name("baz")),
),
cst.SimpleStatementSuite((cst.Pass(),)),
),
"code": "def foo(bar, /, **baz): pass\n",
},
# Test decorators
{
"node": cst.FunctionDef(
cst.Name("foo"),
cst.Parameters(),
cst.SimpleStatementSuite((cst.Pass(),)),
(cst.Decorator(cst.Name("bar")),),
),
"code": "@bar\ndef foo(): pass\n",
},
{
"node": cst.FunctionDef(
cst.Name("foo"),
cst.Parameters(),
cst.SimpleStatementSuite((cst.Pass(),)),
(
cst.Decorator(
cst.Call(
cst.Name("bar"),
(
cst.Arg(cst.Name("baz")),
cst.Arg(cst.SimpleString("'123'")),
),
)
),
),
),
"code": "@bar(baz, '123')\ndef foo(): pass\n",
},
{
"node": cst.FunctionDef(
cst.Name("foo"),
cst.Parameters(),
cst.SimpleStatementSuite((cst.Pass(),)),
(
cst.Decorator(
cst.Call(
cst.Name("bar"), (cst.Arg(cst.SimpleString("'123'")),)
)
),
cst.Decorator(
cst.Call(
cst.Name("baz"), (cst.Arg(cst.SimpleString("'456'")),)
)
),
),
),
"code": "@bar('123')\n@baz('456')\ndef foo(): pass\n",
"expected_position": CodeRange((3, 0), (3, 15)),
},
# Test indentation
{
"node": DummyIndentedBlock(
" ",
cst.FunctionDef(
cst.Name("foo"),
cst.Parameters(),
cst.SimpleStatementSuite((cst.Pass(),)),
(cst.Decorator(cst.Name("bar")),),
),
),
"code": " @bar\n def foo(): pass\n",
},
# With an indented body
{
"node": DummyIndentedBlock(
" ",
cst.FunctionDef(
cst.Name("foo"),
cst.Parameters(),
cst.IndentedBlock((cst.SimpleStatementLine((cst.Pass(),)),)),
(cst.Decorator(cst.Name("bar")),),
),
),
"code": " @bar\n def foo():\n pass\n",
"expected_position": CodeRange((2, 4), (3, 12)),
},
# Leading lines
{
"node": cst.FunctionDef(
cst.Name("foo"),
cst.Parameters(),
cst.SimpleStatementSuite((cst.Pass(),)),
leading_lines=(
cst.EmptyLine(comment=cst.Comment("# leading comment")),
),
),
"code": "# leading comment\ndef foo(): pass\n",
"expected_position": CodeRange((2, 0), (2, 15)),
},
# Inner whitespace
{
"node": cst.FunctionDef(
leading_lines=(
cst.EmptyLine(),
cst.EmptyLine(
comment=cst.Comment("# What an amazing decorator")
),
),
decorators=(
cst.Decorator(
whitespace_after_at=cst.SimpleWhitespace(" "),
decorator=cst.Call(
func=cst.Name("bar"),
whitespace_after_func=cst.SimpleWhitespace(" "),
whitespace_before_args=cst.SimpleWhitespace(" "),
),
),
),
lines_after_decorators=(
cst.EmptyLine(comment=cst.Comment("# What a great function")),
),
asynchronous=cst.Asynchronous(
whitespace_after=cst.SimpleWhitespace(" ")
),
whitespace_after_def=cst.SimpleWhitespace(" "),
name=cst.Name("foo"),
whitespace_after_name=cst.SimpleWhitespace(" "),
whitespace_before_params=cst.SimpleWhitespace(" "),
params=cst.Parameters(),
returns=cst.Annotation(
whitespace_before_indicator=cst.SimpleWhitespace(" "),
whitespace_after_indicator=cst.SimpleWhitespace(" "),
annotation=cst.Name("str"),
),
whitespace_before_colon=cst.SimpleWhitespace(" "),
body=cst.SimpleStatementSuite((cst.Pass(),)),
),
"code": "\n# What an amazing decorator\n@ bar ( )\n# What a great function\nasync def foo ( ) -> str : pass\n",
"expected_position": CodeRange((5, 0), (5, 37)),
},
# Decorators and annotations
{
"node": cst.Decorator(
whitespace_after_at=cst.SimpleWhitespace(" "),
decorator=cst.Call(
func=cst.Name("bar"),
whitespace_after_func=cst.SimpleWhitespace(" "),
whitespace_before_args=cst.SimpleWhitespace(" "),
),
),
"code": "@ bar ( )\n",
"expected_position": CodeRange((1, 0), (1, 10)),
},
# Allow nested calls on decorator
{
"node": cst.FunctionDef(
cst.Name("foo"),
cst.Parameters(),
cst.SimpleStatementSuite((cst.Pass(),)),
(cst.Decorator(cst.Call(func=cst.Call(func=cst.Name("bar")))),),
),
"code": "@bar()()\ndef foo(): pass\n",
},
# Allow any expression in decorator
{
"node": cst.FunctionDef(
cst.Name("foo"),
cst.Parameters(),
cst.SimpleStatementSuite((cst.Pass(),)),
(
cst.Decorator(
cst.BinaryOperation(cst.Name("a"), cst.Add(), cst.Name("b"))
),
),
),
"code": "@a + b\ndef foo(): pass\n",
},
# Allow parentheses around decorator
{
"node": cst.FunctionDef(
cst.Name("foo"),
cst.Parameters(),
cst.SimpleStatementSuite((cst.Pass(),)),
(
cst.Decorator(
cst.Name(
"bar", lpar=(cst.LeftParen(),), rpar=(cst.RightParen(),)
)
),
),
),
"code": "@(bar)\ndef foo(): pass\n",
},
# Parameters
{
"node": cst.Parameters(
params=(
cst.Param(cst.Name("first")),
cst.Param(cst.Name("second")),
cst.Param(cst.Name("third"), default=cst.Float("1.0")),
cst.Param(cst.Name("fourth"), default=cst.Float("1.5")),
),
star_arg=cst.Param(
cst.Name("params"), cst.Annotation(cst.Name("str"))
),
kwonly_params=(
cst.Param(
cst.Name("bar"),
cst.Annotation(cst.Name("str")),
default=cst.SimpleString('"one"'),
),
cst.Param(cst.Name("baz"), cst.Annotation(cst.Name("int"))),
cst.Param(
cst.Name("biz"),
cst.Annotation(cst.Name("str")),
default=cst.SimpleString('"two"'),
),
),
),
"code": 'first, second, third = 1.0, fourth = 1.5, *params: str, bar: str = "one", baz: int, biz: str = "two"',
"expected_position": CodeRange((1, 0), (1, 100)),
},
{
"node": cst.Param(cst.Name("third"), star="", default=cst.Float("1.0")),
"code": "third = 1.0",
"expected_position": CodeRange((1, 0), (1, 5)),
},
{
"node": cst.Param(
cst.Name("third"),
star="*",
whitespace_after_star=cst.SimpleWhitespace(" "),
),
"code": "* third",
"expected_position": CodeRange((1, 0), (1, 7)),
},
{
"node": cst.FunctionDef(
name=cst.Name(
value="foo",
),
params=cst.Parameters(
params=[
cst.Param(
name=cst.Name(
value="param1",
),
),
],
),
body=cst.IndentedBlock(
body=[
cst.SimpleStatementLine(
body=[
cst.Pass(),
],
),
],
),
whitespace_before_params=cst.ParenthesizedWhitespace(
last_line=cst.SimpleWhitespace(
value=" ",
),
),
),
"code": "def foo(\n param1):\n pass\n",
"expected_position": CodeRange((1, 0), (3, 8)),
},
)
)
def test_valid(self, **kwargs: Any) -> None:
if "native_only" in kwargs:
kwargs.pop("native_only")
self.validate_node(**kwargs)
@data_provider(
(
# PEP 646
{
"node": cst.FunctionDef(
name=cst.Name(value="foo"),
params=cst.Parameters(
params=[],
star_arg=cst.Param(
star="*",
name=cst.Name("a"),
annotation=cst.Annotation(
cst.StarredElement(value=cst.Name("b")),
whitespace_before_indicator=cst.SimpleWhitespace(""),
),
),
),
body=cst.SimpleStatementSuite((cst.Pass(),)),
),
"parser": parse_statement,
"code": "def foo(*a: *b): pass\n",
},
{
"node": cst.FunctionDef(
name=cst.Name(value="foo"),
params=cst.Parameters(
params=[],
star_arg=cst.Param(
star="*",
name=cst.Name("a"),
annotation=cst.Annotation(
cst.StarredElement(
value=cst.Subscript(
value=cst.Name("tuple"),
slice=[
cst.SubscriptElement(
cst.Index(cst.Name("int")),
comma=cst.Comma(),
),
cst.SubscriptElement(
cst.Index(
value=cst.Name("Ts"),
star="*",
whitespace_after_star=cst.SimpleWhitespace(
""
),
),
comma=cst.Comma(),
),
cst.SubscriptElement(
cst.Index(cst.Ellipsis())
),
],
)
),
whitespace_before_indicator=cst.SimpleWhitespace(""),
),
),
),
body=cst.SimpleStatementSuite((cst.Pass(),)),
),
"parser": parse_statement,
"code": "def foo(*a: *tuple[int,*Ts,...]): pass\n",
},
# Single type variable
{
"node": cst.FunctionDef(
cst.Name("foo"),
cst.Parameters(),
cst.SimpleStatementSuite((cst.Pass(),)),
type_parameters=cst.TypeParameters(
(cst.TypeParam(cst.TypeVar(cst.Name("T"))),)
),
),
"code": "def foo[T](): pass\n",
"parser": parse_statement,
},
# All the type parameters
{
"node": cst.FunctionDef(
cst.Name("foo"),
cst.Parameters(),
cst.SimpleStatementSuite((cst.Pass(),)),
type_parameters=cst.TypeParameters(
(
cst.TypeParam(
cst.TypeVar(
cst.Name("T"),
bound=cst.Name("int"),
colon=cst.Colon(
whitespace_after=cst.SimpleWhitespace(" ")
),
),
cst.Comma(whitespace_after=cst.SimpleWhitespace(" ")),
),
cst.TypeParam(
cst.TypeVarTuple(cst.Name("Ts")),
cst.Comma(whitespace_after=cst.SimpleWhitespace(" ")),
),
cst.TypeParam(cst.ParamSpec(cst.Name("KW"))),
)
),
),
"code": "def foo[T: int, *Ts, **KW](): pass\n",
"parser": parse_statement,
},
# Type parameters with whitespace
{
"node": cst.FunctionDef(
cst.Name("foo"),
cst.Parameters(),
cst.SimpleStatementSuite((cst.Pass(),)),
type_parameters=cst.TypeParameters(
params=(
cst.TypeParam(
param=cst.TypeVar(
cst.Name("T"),
bound=cst.Name("str"),
colon=cst.Colon(
whitespace_before=cst.SimpleWhitespace(" "),
whitespace_after=cst.ParenthesizedWhitespace(
empty_lines=(cst.EmptyLine(),),
indent=True,
),
),
),
comma=cst.Comma(cst.SimpleWhitespace(" ")),
),
cst.TypeParam(
cst.ParamSpec(
cst.Name("PS"), cst.SimpleWhitespace(" ")
),
cst.Comma(cst.SimpleWhitespace(" ")),
),
)
),
whitespace_after_type_parameters=cst.SimpleWhitespace(" "),
),
"code": "def foo[T :\n\nstr ,** PS ,] (): pass\n",
"parser": parse_statement,
},
)
)
def test_valid_native(self, **kwargs: Any) -> None:
self.validate_node(**kwargs)
@data_provider(
(
(
lambda: cst.FunctionDef(
cst.Name("foo", lpar=(cst.LeftParen(),), rpar=(cst.RightParen(),)),
cst.Parameters(),
cst.SimpleStatementSuite((cst.Pass(),)),
),
"Cannot have parens around Name",
),
(
lambda: cst.FunctionDef(
cst.Name("foo"),
cst.Parameters(),
cst.SimpleStatementSuite((cst.Pass(),)),
asynchronous=cst.Asynchronous(
whitespace_after=cst.SimpleWhitespace("")
),
),
"one space after Asynchronous",
),
(
lambda: cst.FunctionDef(
cst.Name("foo"),
cst.Parameters(),
cst.SimpleStatementSuite((cst.Pass(),)),
whitespace_after_def=cst.SimpleWhitespace(""),
),
"one space between 'def' and name",
),
(
lambda: cst.FunctionDef(
cst.Name("foo"),
cst.Parameters(
star_kwarg=cst.Param(cst.Name("bar"), equal=cst.AssignEqual())
),
cst.SimpleStatementSuite((cst.Pass(),)),
),
"Must have a default when specifying an AssignEqual.",
),
(
lambda: cst.FunctionDef(
cst.Name("foo"),
cst.Parameters(star_kwarg=cst.Param(cst.Name("bar"), star="***")),
cst.SimpleStatementSuite((cst.Pass(),)),
),
r"Must specify either '', '\*' or '\*\*' for star.",
),
(
lambda: cst.FunctionDef(
cst.Name("foo"),
cst.Parameters(
params=(
cst.Param(
cst.Name("bar"), default=cst.SimpleString('"one"')
),
cst.Param(cst.Name("bar")),
)
),
cst.SimpleStatementSuite((cst.Pass(),)),
),
"Cannot have param without defaults following a param with defaults.",
),
(
lambda: cst.FunctionDef(
cst.Name("foo"),
cst.Parameters(
posonly_params=(
cst.Param(
cst.Name("bar"), default=cst.SimpleString('"one"')
),
),
params=(cst.Param(cst.Name("bar")),),
),
cst.SimpleStatementSuite((cst.Pass(),)),
),
"Cannot have param without defaults following a param with defaults.",
),
(
lambda: cst.FunctionDef(
cst.Name("foo"),
cst.Parameters(star_arg=cst.ParamStar()),
cst.SimpleStatementSuite((cst.Pass(),)),
),
"Must have at least one kwonly param if ParamStar is used.",
),
(
lambda: cst.FunctionDef(
cst.Name("foo"),
cst.Parameters(posonly_ind=cst.ParamSlash()),
cst.SimpleStatementSuite((cst.Pass(),)),
),
"Must have at least one posonly param if ParamSlash is used.",
),
(
lambda: cst.FunctionDef(
cst.Name("foo"),
cst.Parameters(params=(cst.Param(cst.Name("bar"), star="*"),)),
cst.SimpleStatementSuite((cst.Pass(),)),
),
"Expecting a star prefix of ''",
),
(
lambda: cst.FunctionDef(
cst.Name("foo"),
cst.Parameters(
params=(
cst.Param(
cst.Name("bar"),
default=cst.SimpleString('"one"'),
star="*",
),
)
),
cst.SimpleStatementSuite((cst.Pass(),)),
),
"Expecting a star prefix of ''",
),
(
lambda: cst.FunctionDef(
cst.Name("foo"),
cst.Parameters(
kwonly_params=(cst.Param(cst.Name("bar"), star="*"),)
),
cst.SimpleStatementSuite((cst.Pass(),)),
),
"Expecting a star prefix of ''",
),
(
lambda: cst.FunctionDef(
cst.Name("foo"),
cst.Parameters(star_arg=cst.Param(cst.Name("bar"), star="**")),
cst.SimpleStatementSuite((cst.Pass(),)),
),
r"Expecting a star prefix of '\*'",
),
(
lambda: cst.FunctionDef(
cst.Name("foo"),
cst.Parameters(star_kwarg=cst.Param(cst.Name("bar"), star="*")),
cst.SimpleStatementSuite((cst.Pass(),)),
),
r"Expecting a star prefix of '\*\*'",
),
)
)
def test_invalid(
self, get_node: Callable[[], cst.CSTNode], expected_re: str
) -> None:
self.assert_invalid(get_node, expected_re)
def _parse_statement_force_38(code: str) -> cst.BaseCompoundStatement:
statement = cst.parse_statement(
code, config=cst.PartialParserConfig(python_version="3.8")
)
if not isinstance(statement, cst.BaseCompoundStatement):
raise ValueError(
"This function is expecting to parse compound statements only!"
)
return statement
class FunctionDefParserTest(CSTNodeTest):
@data_provider(
(
# Simple function definition without any arguments or return
(
cst.FunctionDef(
cst.Name("foo"),
cst.Parameters(),
cst.SimpleStatementSuite((cst.Pass(),)),
),
"def foo(): pass\n",
),
# Functiondef with a return annotation
(
cst.FunctionDef(
cst.Name("foo"),
cst.Parameters(),
cst.SimpleStatementSuite((cst.Pass(),)),
returns=cst.Annotation(
cst.Name("str"),
whitespace_before_indicator=cst.SimpleWhitespace(" "),
),
),
"def foo() -> str: pass\n",
),
# Async function definition.
(
cst.FunctionDef(
cst.Name("foo"),
cst.Parameters(),
cst.SimpleStatementSuite((cst.Pass(),)),
asynchronous=cst.Asynchronous(),
),
"async def foo(): pass\n",
),
# Async function definition with annotation.
(
cst.FunctionDef(
cst.Name("foo"),
cst.Parameters(),
cst.SimpleStatementSuite((cst.Pass(),)),
asynchronous=cst.Asynchronous(),
returns=cst.Annotation(
cst.Name("int"),
whitespace_before_indicator=cst.SimpleWhitespace(" "),
),
),
"async def foo() -> int: pass\n",
),
# Test basic positional params
(
cst.FunctionDef(
cst.Name("foo"),
cst.Parameters(
params=(
cst.Param(
cst.Name("bar"),
star="",
comma=cst.Comma(
whitespace_after=cst.SimpleWhitespace(" ")
),
),
cst.Param(cst.Name("baz"), star=""),
)
),
cst.SimpleStatementSuite((cst.Pass(),)),
),
"def foo(bar, baz): pass\n",
),
# Typed positional params
(
cst.FunctionDef(
cst.Name("foo"),
cst.Parameters(
params=(
cst.Param(
cst.Name("bar"),
cst.Annotation(
cst.Name("str"),
whitespace_before_indicator=cst.SimpleWhitespace(
""
),
),
star="",
comma=cst.Comma(
whitespace_after=cst.SimpleWhitespace(" ")
),
),
cst.Param(
cst.Name("baz"),
cst.Annotation(
cst.Name("int"),
whitespace_before_indicator=cst.SimpleWhitespace(
""
),
),
star="",
),
)
),
cst.SimpleStatementSuite((cst.Pass(),)),
),
"def foo(bar: str, baz: int): pass\n",
),
# Test basic positional default params
(
cst.FunctionDef(
cst.Name("foo"),
cst.Parameters(
params=(
cst.Param(
cst.Name("bar"),
equal=cst.AssignEqual(),
default=cst.SimpleString('"one"'),
star="",
comma=cst.Comma(
whitespace_after=cst.SimpleWhitespace(" ")
),
),
cst.Param(
cst.Name("baz"),
equal=cst.AssignEqual(),
default=cst.Integer("5"),
star="",
),
)
),
cst.SimpleStatementSuite((cst.Pass(),)),
),
'def foo(bar = "one", baz = 5): pass\n',
),
# Typed positional default params
(
cst.FunctionDef(
cst.Name("foo"),
cst.Parameters(
params=(
cst.Param(
cst.Name("bar"),
cst.Annotation(
cst.Name("str"),
whitespace_before_indicator=cst.SimpleWhitespace(
""
),
),
equal=cst.AssignEqual(),
default=cst.SimpleString('"one"'),
star="",
comma=cst.Comma(
whitespace_after=cst.SimpleWhitespace(" ")
),
),
cst.Param(
cst.Name("baz"),
cst.Annotation(
cst.Name("int"),
whitespace_before_indicator=cst.SimpleWhitespace(
""
),
),
equal=cst.AssignEqual(),
default=cst.Integer("5"),
star="",
),
)
),
cst.SimpleStatementSuite((cst.Pass(),)),
),
'def foo(bar: str = "one", baz: int = 5): pass\n',
),
# Mixed positional and default params.
(
cst.FunctionDef(
cst.Name("foo"),
cst.Parameters(
params=(
cst.Param(
cst.Name("bar"),
cst.Annotation(
cst.Name("str"),
whitespace_before_indicator=cst.SimpleWhitespace(
""
),
),
default=None,
star="",
comma=cst.Comma(
whitespace_after=cst.SimpleWhitespace(" ")
),
),
cst.Param(
cst.Name("baz"),
cst.Annotation(
cst.Name("int"),
whitespace_before_indicator=cst.SimpleWhitespace(
""
),
),
equal=cst.AssignEqual(),
default=cst.Integer("5"),
star="",
),
)
),
cst.SimpleStatementSuite((cst.Pass(),)),
),
"def foo(bar: str, baz: int = 5): pass\n",
),
# Test kwonly params
(
cst.FunctionDef(
cst.Name("foo"),
cst.Parameters(
star_arg=cst.ParamStar(),
kwonly_params=(
cst.Param(
cst.Name("bar"),
equal=cst.AssignEqual(),
default=cst.SimpleString('"one"'),
star="",
comma=cst.Comma(
whitespace_after=cst.SimpleWhitespace(" ")
),
),
cst.Param(cst.Name("baz"), default=None, star=""),
),
),
cst.SimpleStatementSuite((cst.Pass(),)),
),
'def foo(*, bar = "one", baz): pass\n',
),
# Typed kwonly params
(
cst.FunctionDef(
cst.Name("foo"),
cst.Parameters(
star_arg=cst.ParamStar(),
kwonly_params=(
cst.Param(
cst.Name("bar"),
cst.Annotation(
cst.Name("str"),
whitespace_before_indicator=cst.SimpleWhitespace(
""
),
),
equal=cst.AssignEqual(),
default=cst.SimpleString('"one"'),
star="",
comma=cst.Comma(
whitespace_after=cst.SimpleWhitespace(" ")
),
),
cst.Param(
cst.Name("baz"),
cst.Annotation(
cst.Name("int"),
whitespace_before_indicator=cst.SimpleWhitespace(
""
),
),
default=None,
star="",
comma=cst.Comma(
whitespace_after=cst.SimpleWhitespace(" ")
),
),
cst.Param(
cst.Name("biz"),
cst.Annotation(
cst.Name("str"),
whitespace_before_indicator=cst.SimpleWhitespace(
""
),
),
equal=cst.AssignEqual(),
default=cst.SimpleString('"two"'),
star="",
),
),
),
cst.SimpleStatementSuite((cst.Pass(),)),
),
'def foo(*, bar: str = "one", baz: int, biz: str = "two"): pass\n',
),
# Mixed params and kwonly_params
(
cst.FunctionDef(
cst.Name("foo"),
cst.Parameters(
params=(
cst.Param(
cst.Name("first"),
annotation=None,
default=None,
star="",
comma=cst.Comma(
whitespace_after=cst.SimpleWhitespace(" ")
),
),
cst.Param(
cst.Name("second"),
annotation=None,
default=None,
star="",
comma=cst.Comma(
whitespace_after=cst.SimpleWhitespace(" ")
),
),
),
star_arg=cst.ParamStar(),
kwonly_params=(
cst.Param(
cst.Name("bar"),
cst.Annotation(
cst.Name("str"),
whitespace_before_indicator=cst.SimpleWhitespace(
""
),
),
equal=cst.AssignEqual(),
default=cst.SimpleString('"one"'),
star="",
comma=cst.Comma(
whitespace_after=cst.SimpleWhitespace(" ")
),
),
cst.Param(
cst.Name("baz"),
cst.Annotation(
cst.Name("int"),
whitespace_before_indicator=cst.SimpleWhitespace(
""
),
),
default=None,
star="",
comma=cst.Comma(
whitespace_after=cst.SimpleWhitespace(" ")
),
),
cst.Param(
cst.Name("biz"),
cst.Annotation(
cst.Name("str"),
whitespace_before_indicator=cst.SimpleWhitespace(
""
),
),
equal=cst.AssignEqual(),
default=cst.SimpleString('"two"'),
star="",
),
),
),
cst.SimpleStatementSuite((cst.Pass(),)),
),
'def foo(first, second, *, bar: str = "one", baz: int, biz: str = "two"): pass\n',
),
# Mixed params and kwonly_params
(
cst.FunctionDef(
cst.Name("foo"),
cst.Parameters(
params=(
cst.Param(
cst.Name("first"),
annotation=None,
equal=cst.AssignEqual(),
default=cst.Float("1.0"),
star="",
comma=cst.Comma(
whitespace_after=cst.SimpleWhitespace(" ")
),
),
cst.Param(
cst.Name("second"),
annotation=None,
equal=cst.AssignEqual(),
default=cst.Float("1.5"),
star="",
comma=cst.Comma(
whitespace_after=cst.SimpleWhitespace(" ")
),
),
),
star_arg=cst.ParamStar(),
kwonly_params=(
cst.Param(
cst.Name("bar"),
cst.Annotation(
cst.Name("str"),
whitespace_before_indicator=cst.SimpleWhitespace(
""
),
),
equal=cst.AssignEqual(),
default=cst.SimpleString('"one"'),
star="",
comma=cst.Comma(
whitespace_after=cst.SimpleWhitespace(" ")
),
),
cst.Param(
cst.Name("baz"),
cst.Annotation(
cst.Name("int"),
whitespace_before_indicator=cst.SimpleWhitespace(
""
),
),
default=None,
star="",
comma=cst.Comma(
whitespace_after=cst.SimpleWhitespace(" ")
),
),
cst.Param(
cst.Name("biz"),
cst.Annotation(
cst.Name("str"),
whitespace_before_indicator=cst.SimpleWhitespace(
""
),
),
equal=cst.AssignEqual(),
default=cst.SimpleString('"two"'),
star="",
),
),
),
cst.SimpleStatementSuite((cst.Pass(),)),
),
'def foo(first = 1.0, second = 1.5, *, bar: str = "one", baz: int, biz: str = "two"): pass\n',
),
# Mixed params, and kwonly_params
(
cst.FunctionDef(
cst.Name("foo"),
cst.Parameters(
params=(
cst.Param(
cst.Name("first"),
annotation=None,
default=None,
star="",
comma=cst.Comma(
whitespace_after=cst.SimpleWhitespace(" ")
),
),
cst.Param(
cst.Name("second"),
annotation=None,
default=None,
star="",
comma=cst.Comma(
whitespace_after=cst.SimpleWhitespace(" ")
),
),
cst.Param(
cst.Name("third"),
annotation=None,
equal=cst.AssignEqual(),
default=cst.Float("1.0"),
star="",
comma=cst.Comma(
whitespace_after=cst.SimpleWhitespace(" ")
),
),
cst.Param(
cst.Name("fourth"),
annotation=None,
equal=cst.AssignEqual(),
default=cst.Float("1.5"),
star="",
comma=cst.Comma(
whitespace_after=cst.SimpleWhitespace(" ")
),
),
),
star_arg=cst.ParamStar(),
kwonly_params=(
cst.Param(
cst.Name("bar"),
cst.Annotation(
cst.Name("str"),
whitespace_before_indicator=cst.SimpleWhitespace(
""
),
),
equal=cst.AssignEqual(),
default=cst.SimpleString('"one"'),
star="",
comma=cst.Comma(
whitespace_after=cst.SimpleWhitespace(" ")
),
),
cst.Param(
cst.Name("baz"),
cst.Annotation(
cst.Name("int"),
whitespace_before_indicator=cst.SimpleWhitespace(
""
),
),
default=None,
star="",
comma=cst.Comma(
whitespace_after=cst.SimpleWhitespace(" ")
),
),
cst.Param(
cst.Name("biz"),
cst.Annotation(
cst.Name("str"),
whitespace_before_indicator=cst.SimpleWhitespace(
""
),
),
equal=cst.AssignEqual(),
default=cst.SimpleString('"two"'),
star="",
),
),
),
cst.SimpleStatementSuite((cst.Pass(),)),
),
'def foo(first, second, third = 1.0, fourth = 1.5, *, bar: str = "one", baz: int, biz: str = "two"): pass\n',
),
# Test star_arg
(
cst.FunctionDef(
cst.Name("foo"),
cst.Parameters(
star_arg=cst.Param(
cst.Name("params"), annotation=None, default=None, star="*"
)
),
cst.SimpleStatementSuite((cst.Pass(),)),
),
"def foo(*params): pass\n",
),
# Typed star_arg, include kwonly_params
(
cst.FunctionDef(
cst.Name("foo"),
cst.Parameters(
star_arg=cst.Param(
cst.Name("params"),
cst.Annotation(
cst.Name("str"),
whitespace_before_indicator=cst.SimpleWhitespace(""),
),
default=None,
star="*",
comma=cst.Comma(whitespace_after=cst.SimpleWhitespace(" ")),
),
kwonly_params=(
cst.Param(
cst.Name("bar"),
cst.Annotation(
cst.Name("str"),
whitespace_before_indicator=cst.SimpleWhitespace(
""
),
),
equal=cst.AssignEqual(),
default=cst.SimpleString('"one"'),
star="",
comma=cst.Comma(
whitespace_after=cst.SimpleWhitespace(" ")
),
),
cst.Param(
cst.Name("baz"),
cst.Annotation(
cst.Name("int"),
whitespace_before_indicator=cst.SimpleWhitespace(
""
),
),
default=None,
star="",
comma=cst.Comma(
whitespace_after=cst.SimpleWhitespace(" ")
),
),
cst.Param(
cst.Name("biz"),
cst.Annotation(
cst.Name("str"),
whitespace_before_indicator=cst.SimpleWhitespace(
""
),
),
equal=cst.AssignEqual(),
default=cst.SimpleString('"two"'),
star="",
),
),
),
cst.SimpleStatementSuite((cst.Pass(),)),
),
'def foo(*params: str, bar: str = "one", baz: int, biz: str = "two"): pass\n',
),
# Mixed params star_arg and kwonly_params
(
cst.FunctionDef(
cst.Name("foo"),
cst.Parameters(
params=(
cst.Param(
cst.Name("first"),
annotation=None,
default=None,
star="",
comma=cst.Comma(
whitespace_after=cst.SimpleWhitespace(" ")
),
),
cst.Param(
cst.Name("second"),
annotation=None,
default=None,
star="",
comma=cst.Comma(
whitespace_after=cst.SimpleWhitespace(" ")
),
),
cst.Param(
cst.Name("third"),
annotation=None,
equal=cst.AssignEqual(),
default=cst.Float("1.0"),
star="",
comma=cst.Comma(
whitespace_after=cst.SimpleWhitespace(" ")
),
),
cst.Param(
cst.Name("fourth"),
annotation=None,
equal=cst.AssignEqual(),
default=cst.Float("1.5"),
star="",
comma=cst.Comma(
whitespace_after=cst.SimpleWhitespace(" ")
),
),
),
star_arg=cst.Param(
cst.Name("params"),
cst.Annotation(
cst.Name("str"),
whitespace_before_indicator=cst.SimpleWhitespace(""),
),
default=None,
star="*",
comma=cst.Comma(whitespace_after=cst.SimpleWhitespace(" ")),
),
kwonly_params=(
cst.Param(
cst.Name("bar"),
cst.Annotation(
cst.Name("str"),
whitespace_before_indicator=cst.SimpleWhitespace(
""
),
),
equal=cst.AssignEqual(),
default=cst.SimpleString('"one"'),
star="",
comma=cst.Comma(
whitespace_after=cst.SimpleWhitespace(" ")
),
),
cst.Param(
cst.Name("baz"),
cst.Annotation(
cst.Name("int"),
whitespace_before_indicator=cst.SimpleWhitespace(
""
),
),
default=None,
star="",
comma=cst.Comma(
whitespace_after=cst.SimpleWhitespace(" ")
),
),
cst.Param(
cst.Name("biz"),
cst.Annotation(
cst.Name("str"),
whitespace_before_indicator=cst.SimpleWhitespace(
""
),
),
equal=cst.AssignEqual(),
default=cst.SimpleString('"two"'),
star="",
),
),
),
cst.SimpleStatementSuite((cst.Pass(),)),
),
'def foo(first, second, third = 1.0, fourth = 1.5, *params: str, bar: str = "one", baz: int, biz: str = "two"): pass\n',
),
# Test star_arg and star_kwarg
(
cst.FunctionDef(
cst.Name("foo"),
cst.Parameters(
star_kwarg=cst.Param(
cst.Name("kwparams"),
annotation=None,
default=None,
star="**",
)
),
cst.SimpleStatementSuite((cst.Pass(),)),
),
"def foo(**kwparams): pass\n",
),
# Test star_arg and kwarg
(
cst.FunctionDef(
cst.Name("foo"),
cst.Parameters(
star_arg=cst.Param(
cst.Name("params"),
annotation=None,
default=None,
star="*",
comma=cst.Comma(whitespace_after=cst.SimpleWhitespace(" ")),
),
star_kwarg=cst.Param(
cst.Name("kwparams"),
annotation=None,
default=None,
star="**",
),
),
cst.SimpleStatementSuite((cst.Pass(),)),
),
"def foo(*params, **kwparams): pass\n",
),
# Test typed star_arg and star_kwarg
(
cst.FunctionDef(
cst.Name("foo"),
cst.Parameters(
star_arg=cst.Param(
cst.Name("params"),
cst.Annotation(
cst.Name("str"),
whitespace_before_indicator=cst.SimpleWhitespace(""),
),
default=None,
star="*",
comma=cst.Comma(whitespace_after=cst.SimpleWhitespace(" ")),
),
star_kwarg=cst.Param(
cst.Name("kwparams"),
cst.Annotation(
cst.Name("int"),
whitespace_before_indicator=cst.SimpleWhitespace(""),
),
default=None,
star="**",
),
),
cst.SimpleStatementSuite((cst.Pass(),)),
),
"def foo(*params: str, **kwparams: int): pass\n",
),
# Test decorators
(
cst.FunctionDef(
cst.Name("foo"),
cst.Parameters(),
cst.SimpleStatementSuite((cst.Pass(),)),
(cst.Decorator(cst.Name("bar")),),
),
"@bar\ndef foo(): pass\n",
),
(
cst.FunctionDef(
cst.Name("foo"),
cst.Parameters(),
cst.SimpleStatementSuite((cst.Pass(),)),
(
cst.Decorator(
cst.Call(
cst.Name("bar"),
(
cst.Arg(
cst.Name("baz"),
keyword=None,
comma=cst.Comma(
whitespace_after=cst.SimpleWhitespace(" ")
),
),
cst.Arg(cst.SimpleString("'123'"), keyword=None),
),
)
),
),
),
"@bar(baz, '123')\ndef foo(): pass\n",
),
(
cst.FunctionDef(
cst.Name("foo"),
cst.Parameters(),
cst.SimpleStatementSuite((cst.Pass(),)),
(
cst.Decorator(
cst.Call(
cst.Name("bar"),
(cst.Arg(cst.SimpleString("'123'"), keyword=None),),
)
),
cst.Decorator(
cst.Call(
cst.Name("baz"),
(cst.Arg(cst.SimpleString("'456'"), keyword=None),),
)
),
),
),
"@bar('123')\n@baz('456')\ndef foo(): pass\n",
),
# Leading lines
(
cst.FunctionDef(
cst.Name("foo"),
cst.Parameters(),
cst.SimpleStatementSuite((cst.Pass(),)),
leading_lines=(
cst.EmptyLine(comment=cst.Comment("# leading comment")),
),
),
"# leading comment\ndef foo(): pass\n",
),
# Inner whitespace
(
cst.FunctionDef(
leading_lines=(
cst.EmptyLine(),
cst.EmptyLine(
comment=cst.Comment("# What an amazing decorator")
),
),
decorators=(
cst.Decorator(
whitespace_after_at=cst.SimpleWhitespace(" "),
decorator=cst.Call(
func=cst.Name("bar"),
whitespace_after_func=cst.SimpleWhitespace(" "),
whitespace_before_args=cst.SimpleWhitespace(" "),
),
),
),
lines_after_decorators=(
cst.EmptyLine(comment=cst.Comment("# What a great function")),
),
asynchronous=cst.Asynchronous(
whitespace_after=cst.SimpleWhitespace(" ")
),
whitespace_after_def=cst.SimpleWhitespace(" "),
name=cst.Name("foo"),
whitespace_after_name=cst.SimpleWhitespace(" "),
whitespace_before_params=cst.SimpleWhitespace(" "),
params=cst.Parameters(),
returns=cst.Annotation(
whitespace_before_indicator=cst.SimpleWhitespace(" "),
whitespace_after_indicator=cst.SimpleWhitespace(" "),
annotation=cst.Name("str"),
),
whitespace_before_colon=cst.SimpleWhitespace(" "),
body=cst.SimpleStatementSuite((cst.Pass(),)),
),
"\n# What an amazing decorator\n@ bar ( )\n# What a great function\nasync def foo ( ) -> str : pass\n",
),
)
)
def test_valid(self, node: cst.CSTNode, code: str) -> None:
self.validate_node(node, code, parse_statement)
@data_provider(
(
# Test basic positional only params
{
"node": cst.FunctionDef(
cst.Name("foo"),
cst.Parameters(
posonly_params=(
cst.Param(
cst.Name("bar"),
star="",
comma=cst.Comma(
whitespace_after=cst.SimpleWhitespace(" ")
),
),
cst.Param(
cst.Name("baz"),
star="",
comma=cst.Comma(
whitespace_after=cst.SimpleWhitespace(" ")
),
),
),
posonly_ind=cst.ParamSlash(),
),
cst.SimpleStatementSuite((cst.Pass(),)),
),
"code": "def foo(bar, baz, /): pass\n",
},
# Positional only params with whitespace after but no comma
{
"node": cst.FunctionDef(
cst.Name("foo"),
cst.Parameters(
posonly_params=(
cst.Param(
cst.Name("bar"),
star="",
comma=cst.Comma(
whitespace_after=cst.SimpleWhitespace(" ")
),
),
cst.Param(
cst.Name("baz"),
star="",
comma=cst.Comma(
whitespace_after=cst.SimpleWhitespace(" ")
),
),
),
posonly_ind=cst.ParamSlash(
whitespace_after=cst.SimpleWhitespace(" ")
),
),
cst.SimpleStatementSuite((cst.Pass(),)),
),
"code": "def foo(bar, baz, / ): pass\n",
"native_only": True,
},
# Typed positional only params
{
"node": cst.FunctionDef(
cst.Name("foo"),
cst.Parameters(
posonly_params=(
cst.Param(
cst.Name("bar"),
cst.Annotation(
cst.Name("str"),
whitespace_before_indicator=cst.SimpleWhitespace(
""
),
),
star="",
comma=cst.Comma(
whitespace_after=cst.SimpleWhitespace(" ")
),
),
cst.Param(
cst.Name("baz"),
cst.Annotation(
cst.Name("int"),
whitespace_before_indicator=cst.SimpleWhitespace(
""
),
),
star="",
comma=cst.Comma(
whitespace_after=cst.SimpleWhitespace(" ")
),
),
),
posonly_ind=cst.ParamSlash(),
),
cst.SimpleStatementSuite((cst.Pass(),)),
),
"code": "def foo(bar: str, baz: int, /): pass\n",
},
# Test basic positional only default params
{
"node": cst.FunctionDef(
cst.Name("foo"),
cst.Parameters(
posonly_params=(
cst.Param(
cst.Name("bar"),
default=cst.SimpleString('"one"'),
equal=cst.AssignEqual(),
star="",
comma=cst.Comma(
whitespace_after=cst.SimpleWhitespace(" ")
),
),
cst.Param(
cst.Name("baz"),
default=cst.Integer("5"),
equal=cst.AssignEqual(),
star="",
comma=cst.Comma(
whitespace_after=cst.SimpleWhitespace(" ")
),
),
),
posonly_ind=cst.ParamSlash(),
),
cst.SimpleStatementSuite((cst.Pass(),)),
),
"code": 'def foo(bar = "one", baz = 5, /): pass\n',
},
# Typed positional only default params
{
"node": cst.FunctionDef(
cst.Name("foo"),
cst.Parameters(
posonly_params=(
cst.Param(
cst.Name("bar"),
cst.Annotation(
cst.Name("str"),
whitespace_before_indicator=cst.SimpleWhitespace(
""
),
),
default=cst.SimpleString('"one"'),
equal=cst.AssignEqual(),
star="",
comma=cst.Comma(
whitespace_after=cst.SimpleWhitespace(" ")
),
),
cst.Param(
cst.Name("baz"),
cst.Annotation(
cst.Name("int"),
whitespace_before_indicator=cst.SimpleWhitespace(
""
),
),
default=cst.Integer("5"),
equal=cst.AssignEqual(),
star="",
comma=cst.Comma(
whitespace_after=cst.SimpleWhitespace(" ")
),
),
),
posonly_ind=cst.ParamSlash(),
),
cst.SimpleStatementSuite((cst.Pass(),)),
),
"code": 'def foo(bar: str = "one", baz: int = 5, /): pass\n',
},
# Test positional only params and positional params
{
"node": cst.FunctionDef(
cst.Name("foo"),
cst.Parameters(
posonly_params=(
cst.Param(
cst.Name("bar"),
star="",
comma=cst.Comma(
whitespace_after=cst.SimpleWhitespace(" ")
),
),
),
posonly_ind=cst.ParamSlash(
comma=cst.Comma(whitespace_after=cst.SimpleWhitespace(" ")),
),
params=(
cst.Param(
cst.Name("baz"),
star="",
),
),
),
cst.SimpleStatementSuite((cst.Pass(),)),
),
"code": "def foo(bar, /, baz): pass\n",
},
# Test positional only params and star args
{
"node": cst.FunctionDef(
cst.Name("foo"),
cst.Parameters(
posonly_params=(
cst.Param(
cst.Name("bar"),
star="",
comma=cst.Comma(
whitespace_after=cst.SimpleWhitespace(" ")
),
),
),
posonly_ind=cst.ParamSlash(
comma=cst.Comma(whitespace_after=cst.SimpleWhitespace(" ")),
),
star_arg=cst.Param(cst.Name("baz"), star="*"),
),
cst.SimpleStatementSuite((cst.Pass(),)),
),
"code": "def foo(bar, /, *baz): pass\n",
},
# Test positional only params and kwonly params
{
"node": cst.FunctionDef(
cst.Name("foo"),
cst.Parameters(
posonly_params=(
cst.Param(
cst.Name("bar"),
star="",
comma=cst.Comma(
whitespace_after=cst.SimpleWhitespace(" ")
),
),
),
posonly_ind=cst.ParamSlash(
comma=cst.Comma(whitespace_after=cst.SimpleWhitespace(" ")),
),
star_arg=cst.ParamStar(
comma=cst.Comma(whitespace_after=cst.SimpleWhitespace(" ")),
),
kwonly_params=(cst.Param(cst.Name("baz"), star=""),),
),
cst.SimpleStatementSuite((cst.Pass(),)),
),
"code": "def foo(bar, /, *, baz): pass\n",
},
# Test positional only params and star kwargs
{
"node": cst.FunctionDef(
cst.Name("foo"),
cst.Parameters(
posonly_params=(
cst.Param(
cst.Name("bar"),
star="",
comma=cst.Comma(
whitespace_after=cst.SimpleWhitespace(" ")
),
),
),
posonly_ind=cst.ParamSlash(
comma=cst.Comma(whitespace_after=cst.SimpleWhitespace(" ")),
),
star_kwarg=cst.Param(cst.Name("baz"), star="**"),
),
cst.SimpleStatementSuite((cst.Pass(),)),
),
"code": "def foo(bar, /, **baz): pass\n",
},
)
)
def test_valid_38(self, node: cst.CSTNode, code: str, **kwargs: Any) -> None:
self.validate_node(node, code, _parse_statement_force_38)
@data_provider(
(
{
"code": "async def foo(): pass",
"parser": parse_statement_as(python_version="3.7"),
"expect_success": True,
},
{
"code": "async def foo(): pass",
"parser": parse_statement_as(python_version="3.6"),
"expect_success": True,
},
{
"code": "async def foo(): pass",
"parser": parse_statement_as(python_version="3.5"),
"expect_success": True,
},
{
"code": "async def foo(): pass",
"parser": parse_statement_as(python_version="3.3"),
"expect_success": False,
},
)
)
def test_versions(self, **kwargs: Any) -> None:
if not kwargs.get("expect_success", True):
self.skipTest("parse errors are disabled for native parser")
self.assert_parses(**kwargs)
@data_provider(
(
{"code": "A[:*b]"},
{"code": "A[*b:]"},
{"code": "A[*b:*b]"},
{"code": "A[*(1:2)]"},
{"code": "A[*:]"},
{"code": "A[:*]"},
{"code": "A[**b]"},
{"code": "def f(x: *b): pass"},
{"code": "def f(**x: *b): pass"},
{"code": "x: *b"},
)
)
def test_parse_error(self, **kwargs: Any) -> None:
self.assert_parses(**kwargs, expect_success=False, parser=parse_statement)