blob: 71eb3fbeffcbd6a2b30c5be55346bef53a28c22f [file]
# flags: --preview --pyi
#
# Test cases for blank line handling around overload groups in .pyi files:
# - No blank lines between consecutive same-name decorated functions (overloads)
# - No blank lines between overloads even when a function has a docstring
# - Blank line enforced after an overload group before an unrelated statement
# - Blank line enforced before an overload group after an unrelated statement
# - Blank lines between differently-named decorated functions
# - Async overloaded functions
# - Class-level overload groups with various transitions
# - Transition from undecorated def to decorated overload group
# - Overload group immediately followed by undecorated function (no blank line)
# - Overload groups adjacent to if sys.version_info blocks
# - Overload groups inside if blocks adjacent to undecorated functions
# - Conditional overloads (if/else) with docstrings preceded/followed by undecorated defs
# - Undecorated function around @property-decorated function (with and without gaps)
# - Decorated class with undecorated methods (no spurious blank lines)
import sys
from typing import overload, type_check_only
def decorator(func): ...
@overload
def a(x: int) -> int: ...
@overload
def a(x: str) -> str: ...
def b(x): ...
@decorator
def c() -> None: ...
@overload
def d(x: int) -> int:
"""Int overload."""
@overload
def d(x: str) -> str: ...
def e(x): ...
@overload
async def async_a(x: int) -> int: ...
@overload
async def async_a(x: str) -> str: ...
var: int
class MyClass:
@overload
def method(self, x: int) -> int: ...
@overload
def method(self, x: str) -> str: ...
def after_method(self, x): ...
@overload
def with_docs(self, x: int) -> int:
"""Int."""
@overload
def with_docs(self, x: str) -> str: ...
def after_with_docs(self, x): ...
@overload
def no_gap(self, x: int) -> int: ...
@overload
def no_gap(self, x: str) -> str: ...
@decorator
def different_method(self) -> None: ...
@decorator
def another_dec(self) -> None: ...
@decorator
def yet_another_dec(self) -> None: ...
attr: int
@overload
def after_attr(self, x: int) -> int: ...
@overload
def after_attr(self, x: str) -> str: ...
attr2: str
@property
def prop1(self) -> int: ...
@property
def prop2(self) -> str: ...
@property
def prop3(self) -> bytes: ...
@property
def prop4_with_setter(self) -> int: ...
@prop4_with_setter.setter
def prop4_with_setter(self, value: int) -> None: ...
@property
def prop_5_with_setter(self) -> int: ...
@prop_5_with_setter.setter
def prop_5_with_setter(self, value: int) -> None: ...
@property
def prop6(self) -> int: ...
@property
def prop7(self) -> str: ...
@property
def prop8_with_setter(self) -> int: ...
@prop8_with_setter.setter
def prop8_with_setter(self, value: int) -> None: ...
@property
def prop9(self) -> int: ...
@property
def prop10_with_docstring(self) -> int:
"""Prop with docstring."""
@property
def prop11_with_docstring(self) -> int:
"""Another prop with docstring."""
@property
def prop12(self) -> int: ...
@classmethod
def make_myclass(cls) -> "MyClass": ...
@staticmethod
def static_method() -> None: ...
def plain() -> None: ...
@overload
def different(x: int) -> int: ...
@overload
def different(x: str) -> str: ...
def another_plain() -> None: ...
@decorator
def alpha() -> None: ...
@decorator
def beta() -> None: ...
@overload
def multi(x: int) -> int:
"""Int version."""
@overload
def multi(x: str) -> str:
"""Str version."""
@overload
def multi(x: bytes) -> bytes: ...
def next_func() -> None: ...
@overload
def three_overloads(x: int) -> int: ...
@overload
def three_overloads(x: str) -> str: ...
@overload
def three_overloads(x: bytes) -> bytes: ...
@overload
def four_overloads(x: int) -> int: ...
@overload
def four_overloads(x: str) -> str: ...
@overload
def four_overloads(x: bytes) -> bytes: ...
@overload
def four_overloads(x: float) -> float: ...
@overload
def before_if_no_gap(x: int) -> int: ...
@overload
def before_if_no_gap(x: str) -> str: ...
if sys.version_info >= (3, 10):
def conditional_func() -> None: ...
if sys.version_info >= (3, 10):
def other_conditional() -> None: ...
@overload
def after_if_no_gap(x: int) -> int: ...
@overload
def after_if_no_gap(x: str) -> str: ...
@overload
def before_if_with_gap(x: int) -> int: ...
@overload
def before_if_with_gap(x: str) -> str: ...
if sys.version_info >= (3, 10):
def conditional_func2() -> None: ...
if sys.version_info >= (3, 10):
def other_conditional2() -> None: ...
@overload
def after_if_with_gap(x: int) -> int: ...
@overload
def after_if_with_gap(x: str) -> str: ...
if sys.version_info >= (3, 10):
@overload
def nested_overload_before(x: int) -> int: ...
@overload
def nested_overload_before(x: str) -> str: ...
def undecorated_after() -> None: ...
if sys.version_info >= (3, 10):
def undecorated_before() -> None: ...
@overload
def nested_overload_after(x: int) -> int: ...
@overload
def nested_overload_after(x: str) -> str: ...
if sys.version_info >= (3, 10):
@overload
def nested_overload_before_with_gap(x: int) -> int: ...
@overload
def nested_overload_before_with_gap(x: str) -> str: ...
def undecorated_after_with_gap() -> None: ...
if sys.version_info >= (3, 10):
def undecorated_before_with_gap() -> None: ...
@overload
def nested_overload_after_with_gap(x: int) -> int: ...
@overload
def nested_overload_after_with_gap(x: str) -> str: ...
def before_conditional_overload() -> None: ...
if sys.version_info >= (3, 10):
@overload
def conditional_overload(x: int) -> int:
"""Int."""
else:
@overload
def conditional_overload(x: int) -> int:
"""Int old."""
@overload
def conditional_overload(x: str) -> str: ...
def after_conditional_overload() -> None: ...
def before_conditional_overload_with_gaps() -> None: ...
if sys.version_info >= (3, 10):
@overload
def conditional_overload_with_gaps(x: int) -> int:
"""Int."""
else:
@overload
def conditional_overload_with_gaps(x: int) -> int:
"""Int old."""
@overload
def conditional_overload_with_gaps(x: str) -> str: ...
def after_conditional_overload_with_gaps() -> None: ...
if sys.version_info >= (3, 10):
@overload
def if_else_different_names(x: int) -> int: ...
@overload
def if_else_different_names(x: str) -> str: ...
else:
@overload
def if_else_other_name(x: int) -> int: ...
@overload
def if_else_other_name(x: str) -> str: ...
@overload
def commented(x: int) -> int: ...
# comment in overload group
@overload
def commented(x: str) -> str: ...
def after_commented() -> None: ...
class MyClassWithComments:
@overload
def commented_method(self, x: int) -> int: ...
# comment between class overloads
@overload
def commented_method(self, x: str) -> str: ...
def after_commented_method(self) -> None: ...
@overload
def three_overload_methods(self, x: int) -> int: ...
# comment after first with gap above that is retained
@overload
def three_overload_methods(self, x: str) -> str: ...
# comment after second with gap below that is removed
@overload
def three_overload_methods(self, x: bytes) -> bytes: ...
def after_three_overloads(self) -> None: ...
@overload
def four_overload_methods(self, x: int) -> int: ...
# comment after first with gaps on both lines
@overload
def four_overload_methods(self, x: str) -> str: ...
# comment after second with too many gaps above
@overload
def four_overload_methods(self, x: bytes) -> bytes: ...
# comment after third with large gaps below and above
@overload
def four_overload_methods(self, x: list[bytes]) -> bytes: ...
@overload
def commented_gap_above(x: int) -> int: ...
# comment with gap above that is retained
@overload
def commented_gap_above(x: str) -> str: ...
@overload
def commented_gap_below(x: int) -> int: ...
# comment with gap below that is removed
@overload
def commented_gap_below(x: str) -> str: ...
@overload
def commented_gaps_both(x: int) -> int: ...
# comment with gaps on both sides
@overload
def commented_gaps_both(x: str) -> str: ...
@overload
def multi_comment(x: int) -> int: ...
# first comment
# second comment
@overload
def multi_comment(x: str) -> str: ...
@overload
def large_comment_gaps(x: int) -> int: ...
# comment with large gaps above that are collapsed
@overload
def large_comment_gaps(x: str) -> str: ...
# comment with large gaps above and below that are collapsed
@overload
def large_comment_gaps(x: int) -> int: ...
@overload
def conditional_commented(x: int) -> int: ...
# comment
if sys.version_info >= (3, 10):
# comment
@overload
def conditional_commented(x: str) -> str: ...
else:
# comment
@overload
def conditional_commented(x: str) -> str: ...
def before_comment_group() -> None: ...
# comment before overload group
@overload
def comment_before(x: int) -> int: ...
@overload
def comment_before(x: str) -> str: ...
def after_comment_group() -> None: ...
class ClassWithConditionalOverloads:
def method(self) -> None: ...
if sys.version_info >= (3, 10):
@overload
def conditional(self, x: int) -> int: ...
else:
@overload
def conditional(self, x: str) -> str: ...
@overload
def conditional(self, x: bytes) -> bytes: ...
@overload
def conditional_commented(self, x: int) -> int: ...
# comment
if sys.version_info >= (3, 10):
# comment
@overload
def conditional_commented(self, x: str) -> str: ...
else:
# comment
@overload
def conditional_commented(self, x: str) -> str: ...
class ClassWithOverloadThenConditional:
@overload
def method(self, x: int) -> int: ...
@overload
def method(self, x: str) -> str: ...
if sys.version_info >= (3, 10):
@overload
def method(self, x: bytes) -> bytes: ...
class ClassWithNonOverloadConditional:
def regular(self) -> None: ...
if sys.version_info < (3, 12):
@staticmethod
def legacy_method() -> str:
"""Deprecated."""
@type_check_only
class DecoratedClassWithUndecoratedMethods:
def method_a(self) -> None: ...
def method_b(self) -> None: ...
def method_c(self) -> None: ...
if sys.version_info >= (3, 12):
@overload
def elif_overload(x: int) -> int: ...
elif sys.version_info >= (3, 10):
@overload
def elif_overload(x: float) -> float: ...
else:
@overload
def elif_overload(x: bytes) -> bytes: ...
@overload
def elif_overload(x: str) -> str: ...
@overload
def before_class(x: int) -> int: ...
@overload
def before_class(x: str) -> str: ...
class AfterOverloadGroup: ...
class AfterOverloadGroup2: ...
@overload
def after_class(x: int) -> int: ...
@overload
def after_class(x: str) -> str: ...
@overload
@decorator
def multi_decorated(x: int) -> int: ...
@overload
@decorator
def multi_decorated(x: str) -> str: ...
def after_multi_decorated() -> None: ...
class Outer:
class Inner:
@overload
def method(self, x: int) -> int: ...
@overload
def method(self, x: str) -> str: ...
@overload
def method(self, x: int) -> int: ...
@overload
def method(self, x: str) -> str: ...
# output
#
# Test cases for blank line handling around overload groups in .pyi files:
# - No blank lines between consecutive same-name decorated functions (overloads)
# - No blank lines between overloads even when a function has a docstring
# - Blank line enforced after an overload group before an unrelated statement
# - Blank line enforced before an overload group after an unrelated statement
# - Blank lines between differently-named decorated functions
# - Async overloaded functions
# - Class-level overload groups with various transitions
# - Transition from undecorated def to decorated overload group
# - Overload group immediately followed by undecorated function (no blank line)
# - Overload groups adjacent to if sys.version_info blocks
# - Overload groups inside if blocks adjacent to undecorated functions
# - Conditional overloads (if/else) with docstrings preceded/followed by undecorated defs
# - Undecorated function around @property-decorated function (with and without gaps)
# - Decorated class with undecorated methods (no spurious blank lines)
import sys
from typing import overload, type_check_only
def decorator(func): ...
@overload
def a(x: int) -> int: ...
@overload
def a(x: str) -> str: ...
def b(x): ...
@decorator
def c() -> None: ...
@overload
def d(x: int) -> int:
"""Int overload."""
@overload
def d(x: str) -> str: ...
def e(x): ...
@overload
async def async_a(x: int) -> int: ...
@overload
async def async_a(x: str) -> str: ...
var: int
class MyClass:
@overload
def method(self, x: int) -> int: ...
@overload
def method(self, x: str) -> str: ...
def after_method(self, x): ...
@overload
def with_docs(self, x: int) -> int:
"""Int."""
@overload
def with_docs(self, x: str) -> str: ...
def after_with_docs(self, x): ...
@overload
def no_gap(self, x: int) -> int: ...
@overload
def no_gap(self, x: str) -> str: ...
@decorator
def different_method(self) -> None: ...
@decorator
def another_dec(self) -> None: ...
@decorator
def yet_another_dec(self) -> None: ...
attr: int
@overload
def after_attr(self, x: int) -> int: ...
@overload
def after_attr(self, x: str) -> str: ...
attr2: str
@property
def prop1(self) -> int: ...
@property
def prop2(self) -> str: ...
@property
def prop3(self) -> bytes: ...
@property
def prop4_with_setter(self) -> int: ...
@prop4_with_setter.setter
def prop4_with_setter(self, value: int) -> None: ...
@property
def prop_5_with_setter(self) -> int: ...
@prop_5_with_setter.setter
def prop_5_with_setter(self, value: int) -> None: ...
@property
def prop6(self) -> int: ...
@property
def prop7(self) -> str: ...
@property
def prop8_with_setter(self) -> int: ...
@prop8_with_setter.setter
def prop8_with_setter(self, value: int) -> None: ...
@property
def prop9(self) -> int: ...
@property
def prop10_with_docstring(self) -> int:
"""Prop with docstring."""
@property
def prop11_with_docstring(self) -> int:
"""Another prop with docstring."""
@property
def prop12(self) -> int: ...
@classmethod
def make_myclass(cls) -> "MyClass": ...
@staticmethod
def static_method() -> None: ...
def plain() -> None: ...
@overload
def different(x: int) -> int: ...
@overload
def different(x: str) -> str: ...
def another_plain() -> None: ...
@decorator
def alpha() -> None: ...
@decorator
def beta() -> None: ...
@overload
def multi(x: int) -> int:
"""Int version."""
@overload
def multi(x: str) -> str:
"""Str version."""
@overload
def multi(x: bytes) -> bytes: ...
def next_func() -> None: ...
@overload
def three_overloads(x: int) -> int: ...
@overload
def three_overloads(x: str) -> str: ...
@overload
def three_overloads(x: bytes) -> bytes: ...
@overload
def four_overloads(x: int) -> int: ...
@overload
def four_overloads(x: str) -> str: ...
@overload
def four_overloads(x: bytes) -> bytes: ...
@overload
def four_overloads(x: float) -> float: ...
@overload
def before_if_no_gap(x: int) -> int: ...
@overload
def before_if_no_gap(x: str) -> str: ...
if sys.version_info >= (3, 10):
def conditional_func() -> None: ...
if sys.version_info >= (3, 10):
def other_conditional() -> None: ...
@overload
def after_if_no_gap(x: int) -> int: ...
@overload
def after_if_no_gap(x: str) -> str: ...
@overload
def before_if_with_gap(x: int) -> int: ...
@overload
def before_if_with_gap(x: str) -> str: ...
if sys.version_info >= (3, 10):
def conditional_func2() -> None: ...
if sys.version_info >= (3, 10):
def other_conditional2() -> None: ...
@overload
def after_if_with_gap(x: int) -> int: ...
@overload
def after_if_with_gap(x: str) -> str: ...
if sys.version_info >= (3, 10):
@overload
def nested_overload_before(x: int) -> int: ...
@overload
def nested_overload_before(x: str) -> str: ...
def undecorated_after() -> None: ...
if sys.version_info >= (3, 10):
def undecorated_before() -> None: ...
@overload
def nested_overload_after(x: int) -> int: ...
@overload
def nested_overload_after(x: str) -> str: ...
if sys.version_info >= (3, 10):
@overload
def nested_overload_before_with_gap(x: int) -> int: ...
@overload
def nested_overload_before_with_gap(x: str) -> str: ...
def undecorated_after_with_gap() -> None: ...
if sys.version_info >= (3, 10):
def undecorated_before_with_gap() -> None: ...
@overload
def nested_overload_after_with_gap(x: int) -> int: ...
@overload
def nested_overload_after_with_gap(x: str) -> str: ...
def before_conditional_overload() -> None: ...
if sys.version_info >= (3, 10):
@overload
def conditional_overload(x: int) -> int:
"""Int."""
else:
@overload
def conditional_overload(x: int) -> int:
"""Int old."""
@overload
def conditional_overload(x: str) -> str: ...
def after_conditional_overload() -> None: ...
def before_conditional_overload_with_gaps() -> None: ...
if sys.version_info >= (3, 10):
@overload
def conditional_overload_with_gaps(x: int) -> int:
"""Int."""
else:
@overload
def conditional_overload_with_gaps(x: int) -> int:
"""Int old."""
@overload
def conditional_overload_with_gaps(x: str) -> str: ...
def after_conditional_overload_with_gaps() -> None: ...
if sys.version_info >= (3, 10):
@overload
def if_else_different_names(x: int) -> int: ...
@overload
def if_else_different_names(x: str) -> str: ...
else:
@overload
def if_else_other_name(x: int) -> int: ...
@overload
def if_else_other_name(x: str) -> str: ...
@overload
def commented(x: int) -> int: ...
# comment in overload group
@overload
def commented(x: str) -> str: ...
def after_commented() -> None: ...
class MyClassWithComments:
@overload
def commented_method(self, x: int) -> int: ...
# comment between class overloads
@overload
def commented_method(self, x: str) -> str: ...
def after_commented_method(self) -> None: ...
@overload
def three_overload_methods(self, x: int) -> int: ...
# comment after first with gap above that is retained
@overload
def three_overload_methods(self, x: str) -> str: ...
# comment after second with gap below that is removed
@overload
def three_overload_methods(self, x: bytes) -> bytes: ...
def after_three_overloads(self) -> None: ...
@overload
def four_overload_methods(self, x: int) -> int: ...
# comment after first with gaps on both lines
@overload
def four_overload_methods(self, x: str) -> str: ...
# comment after second with too many gaps above
@overload
def four_overload_methods(self, x: bytes) -> bytes: ...
# comment after third with large gaps below and above
@overload
def four_overload_methods(self, x: list[bytes]) -> bytes: ...
@overload
def commented_gap_above(x: int) -> int: ...
# comment with gap above that is retained
@overload
def commented_gap_above(x: str) -> str: ...
@overload
def commented_gap_below(x: int) -> int: ...
# comment with gap below that is removed
@overload
def commented_gap_below(x: str) -> str: ...
@overload
def commented_gaps_both(x: int) -> int: ...
# comment with gaps on both sides
@overload
def commented_gaps_both(x: str) -> str: ...
@overload
def multi_comment(x: int) -> int: ...
# first comment
# second comment
@overload
def multi_comment(x: str) -> str: ...
@overload
def large_comment_gaps(x: int) -> int: ...
# comment with large gaps above that are collapsed
@overload
def large_comment_gaps(x: str) -> str: ...
# comment with large gaps above and below that are collapsed
@overload
def large_comment_gaps(x: int) -> int: ...
@overload
def conditional_commented(x: int) -> int: ...
# comment
if sys.version_info >= (3, 10):
# comment
@overload
def conditional_commented(x: str) -> str: ...
else:
# comment
@overload
def conditional_commented(x: str) -> str: ...
def before_comment_group() -> None: ...
# comment before overload group
@overload
def comment_before(x: int) -> int: ...
@overload
def comment_before(x: str) -> str: ...
def after_comment_group() -> None: ...
class ClassWithConditionalOverloads:
def method(self) -> None: ...
if sys.version_info >= (3, 10):
@overload
def conditional(self, x: int) -> int: ...
else:
@overload
def conditional(self, x: str) -> str: ...
@overload
def conditional(self, x: bytes) -> bytes: ...
@overload
def conditional_commented(self, x: int) -> int: ...
# comment
if sys.version_info >= (3, 10):
# comment
@overload
def conditional_commented(self, x: str) -> str: ...
else:
# comment
@overload
def conditional_commented(self, x: str) -> str: ...
class ClassWithOverloadThenConditional:
@overload
def method(self, x: int) -> int: ...
@overload
def method(self, x: str) -> str: ...
if sys.version_info >= (3, 10):
@overload
def method(self, x: bytes) -> bytes: ...
class ClassWithNonOverloadConditional:
def regular(self) -> None: ...
if sys.version_info < (3, 12):
@staticmethod
def legacy_method() -> str:
"""Deprecated."""
@type_check_only
class DecoratedClassWithUndecoratedMethods:
def method_a(self) -> None: ...
def method_b(self) -> None: ...
def method_c(self) -> None: ...
if sys.version_info >= (3, 12):
@overload
def elif_overload(x: int) -> int: ...
elif sys.version_info >= (3, 10):
@overload
def elif_overload(x: float) -> float: ...
else:
@overload
def elif_overload(x: bytes) -> bytes: ...
@overload
def elif_overload(x: str) -> str: ...
@overload
def before_class(x: int) -> int: ...
@overload
def before_class(x: str) -> str: ...
class AfterOverloadGroup: ...
class AfterOverloadGroup2: ...
@overload
def after_class(x: int) -> int: ...
@overload
def after_class(x: str) -> str: ...
@overload
@decorator
def multi_decorated(x: int) -> int: ...
@overload
@decorator
def multi_decorated(x: str) -> str: ...
def after_multi_decorated() -> None: ...
class Outer:
class Inner:
@overload
def method(self, x: int) -> int: ...
@overload
def method(self, x: str) -> str: ...
@overload
def method(self, x: int) -> int: ...
@overload
def method(self, x: str) -> str: ...