# 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: ...