mirror of
				https://github.com/astral-sh/ruff.git
				synced 2025-11-04 13:39:07 +00:00 
			
		
		
		
	Fix #9080 Example, where `[]` is a 2 byte non-breaking space: ``` def f(): """ Docstring header ^^^^ Real indentation is 4 chars docstring body, over-indented ^^^^^^ Over-indentation is 6 - 4 = 2 chars due to this line [] [] docstring body 2, further indented ^^^^^ We take these 4 chars/5 bytes to match the docstring ... ^^^ ... and these 2 chars/3 bytes to remove the `over_indented_size` ... ^^ ... but preserve this real indent ```
		
			
				
	
	
		
			724 lines
		
	
	
	
		
			17 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			724 lines
		
	
	
	
		
			17 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
# No docstring, so we can test D100
 | 
						||
from functools import wraps
 | 
						||
import os
 | 
						||
from .expected import Expectation
 | 
						||
from typing import overload
 | 
						||
from typing_extensions import override
 | 
						||
 | 
						||
 | 
						||
expectation = Expectation()
 | 
						||
expect = expectation.expect
 | 
						||
 | 
						||
expect('class_', 'D101: Missing docstring in public class')
 | 
						||
 | 
						||
 | 
						||
class class_:
 | 
						||
 | 
						||
    expect('meta', 'D419: Docstring is empty')
 | 
						||
 | 
						||
    class meta:
 | 
						||
        """"""
 | 
						||
 | 
						||
    @expect('D102: Missing docstring in public method')
 | 
						||
    def method(self=None):
 | 
						||
        pass
 | 
						||
 | 
						||
    def _ok_since_private(self=None):
 | 
						||
        pass
 | 
						||
 | 
						||
    @overload
 | 
						||
    def overloaded_method(self, a: int) -> str:
 | 
						||
        ...
 | 
						||
 | 
						||
    @overload
 | 
						||
    def overloaded_method(self, a: str) -> str:
 | 
						||
        """Foo bar documentation."""
 | 
						||
        ...
 | 
						||
 | 
						||
    def overloaded_method(a):
 | 
						||
        """Foo bar documentation."""
 | 
						||
        return str(a)
 | 
						||
 | 
						||
    expect('overloaded_method',
 | 
						||
           "D418: Function/ Method decorated with @overload"
 | 
						||
           " shouldn't contain a docstring")
 | 
						||
 | 
						||
    @override
 | 
						||
    def overridden_method(a):
 | 
						||
        return str(a)
 | 
						||
 | 
						||
    @property
 | 
						||
    def foo(self):
 | 
						||
        """The foo of the thing, which isn't in imperative mood."""
 | 
						||
        return "hello"
 | 
						||
 | 
						||
    @expect('D102: Missing docstring in public method')
 | 
						||
    def __new__(self=None):
 | 
						||
        pass
 | 
						||
 | 
						||
    @expect('D107: Missing docstring in __init__')
 | 
						||
    def __init__(self=None):
 | 
						||
        pass
 | 
						||
 | 
						||
    @expect('D105: Missing docstring in magic method')
 | 
						||
    def __str__(self=None):
 | 
						||
        pass
 | 
						||
 | 
						||
    @expect('D102: Missing docstring in public method')
 | 
						||
    def __call__(self=None, x=None, y=None, z=None):
 | 
						||
        pass
 | 
						||
 | 
						||
 | 
						||
@expect('D419: Docstring is empty')
 | 
						||
def function():
 | 
						||
    """ """
 | 
						||
    def ok_since_nested():
 | 
						||
        pass
 | 
						||
 | 
						||
    @expect('D419: Docstring is empty')
 | 
						||
    def nested():
 | 
						||
        ''
 | 
						||
 | 
						||
 | 
						||
def function_with_nesting():
 | 
						||
    """Foo bar documentation."""
 | 
						||
    @overload
 | 
						||
    def nested_overloaded_func(a: int) -> str:
 | 
						||
        ...
 | 
						||
 | 
						||
    @overload
 | 
						||
    def nested_overloaded_func(a: str) -> str:
 | 
						||
        """Foo bar documentation."""
 | 
						||
        ...
 | 
						||
 | 
						||
    def nested_overloaded_func(a):
 | 
						||
        """Foo bar documentation."""
 | 
						||
        return str(a)
 | 
						||
 | 
						||
 | 
						||
expect('nested_overloaded_func',
 | 
						||
       "D418: Function/ Method decorated with @overload"
 | 
						||
       " shouldn't contain a docstring")
 | 
						||
 | 
						||
 | 
						||
@overload
 | 
						||
def overloaded_func(a: int) -> str:
 | 
						||
    ...
 | 
						||
 | 
						||
 | 
						||
@overload
 | 
						||
def overloaded_func(a: str) -> str:
 | 
						||
    """Foo bar documentation."""
 | 
						||
    ...
 | 
						||
 | 
						||
 | 
						||
def overloaded_func(a):
 | 
						||
    """Foo bar documentation."""
 | 
						||
    return str(a)
 | 
						||
 | 
						||
 | 
						||
expect('overloaded_func',
 | 
						||
       "D418: Function/ Method decorated with @overload"
 | 
						||
       " shouldn't contain a docstring")
 | 
						||
 | 
						||
 | 
						||
@expect('D200: One-line docstring should fit on one line with quotes '
 | 
						||
        '(found 3)')
 | 
						||
@expect('D212: Multi-line docstring summary should start at the first line')
 | 
						||
def asdlkfasd():
 | 
						||
    """
 | 
						||
    Wrong.
 | 
						||
    """
 | 
						||
 | 
						||
 | 
						||
@expect('D201: No blank lines allowed before function docstring (found 1)')
 | 
						||
def leading_space():
 | 
						||
 | 
						||
    """Leading space."""
 | 
						||
 | 
						||
 | 
						||
@expect('D202: No blank lines allowed after function docstring (found 1)')
 | 
						||
def trailing_space():
 | 
						||
    """Leading space."""
 | 
						||
 | 
						||
    pass
 | 
						||
 | 
						||
 | 
						||
@expect('D201: No blank lines allowed before function docstring (found 1)')
 | 
						||
@expect('D202: No blank lines allowed after function docstring (found 1)')
 | 
						||
def trailing_and_leading_space():
 | 
						||
 | 
						||
    """Trailing and leading space."""
 | 
						||
 | 
						||
    pass
 | 
						||
 | 
						||
 | 
						||
expect('LeadingSpaceMissing',
 | 
						||
       'D203: 1 blank line required before class docstring (found 0)')
 | 
						||
 | 
						||
 | 
						||
class LeadingSpaceMissing:
 | 
						||
    """Leading space missing."""
 | 
						||
 | 
						||
 | 
						||
expect('WithLeadingSpace',
 | 
						||
       'D211: No blank lines allowed before class docstring (found 1)')
 | 
						||
 | 
						||
 | 
						||
class WithLeadingSpace:
 | 
						||
 | 
						||
    """With leading space."""
 | 
						||
 | 
						||
 | 
						||
expect('TrailingSpace',
 | 
						||
       'D204: 1 blank line required after class docstring (found 0)')
 | 
						||
expect('TrailingSpace',
 | 
						||
       'D211: No blank lines allowed before class docstring (found 1)')
 | 
						||
 | 
						||
 | 
						||
class TrailingSpace:
 | 
						||
 | 
						||
    """TrailingSpace."""
 | 
						||
    pass
 | 
						||
 | 
						||
 | 
						||
expect('LeadingAndTrailingSpaceMissing',
 | 
						||
       'D203: 1 blank line required before class docstring (found 0)')
 | 
						||
expect('LeadingAndTrailingSpaceMissing',
 | 
						||
       'D204: 1 blank line required after class docstring (found 0)')
 | 
						||
 | 
						||
 | 
						||
class LeadingAndTrailingSpaceMissing:
 | 
						||
    """Leading and trailing space missing."""
 | 
						||
    pass
 | 
						||
 | 
						||
 | 
						||
@expect('D205: 1 blank line required between summary line and description '
 | 
						||
        '(found 0)')
 | 
						||
@expect('D213: Multi-line docstring summary should start at the second line')
 | 
						||
def multi_line_zero_separating_blanks():
 | 
						||
    """Summary.
 | 
						||
    Description.
 | 
						||
 | 
						||
    """
 | 
						||
 | 
						||
 | 
						||
@expect('D205: 1 blank line required between summary line and description '
 | 
						||
        '(found 2)')
 | 
						||
@expect('D213: Multi-line docstring summary should start at the second line')
 | 
						||
def multi_line_two_separating_blanks():
 | 
						||
    """Summary.
 | 
						||
 | 
						||
 | 
						||
    Description.
 | 
						||
 | 
						||
    """
 | 
						||
 | 
						||
 | 
						||
@expect('D213: Multi-line docstring summary should start at the second line')
 | 
						||
def multi_line_one_separating_blanks():
 | 
						||
    """Summary.
 | 
						||
 | 
						||
    Description.
 | 
						||
 | 
						||
    """
 | 
						||
 | 
						||
 | 
						||
@expect('D207: Docstring is under-indented')
 | 
						||
@expect('D213: Multi-line docstring summary should start at the second line')
 | 
						||
def asdfsdf():
 | 
						||
    """Summary.
 | 
						||
 | 
						||
Description.
 | 
						||
 | 
						||
    """
 | 
						||
 | 
						||
 | 
						||
@expect('D207: Docstring is under-indented')
 | 
						||
@expect('D213: Multi-line docstring summary should start at the second line')
 | 
						||
def asdsdfsdffsdf():
 | 
						||
    """Summary.
 | 
						||
 | 
						||
    Description.
 | 
						||
 | 
						||
"""
 | 
						||
 | 
						||
 | 
						||
@expect('D208: Docstring is over-indented')
 | 
						||
@expect('D213: Multi-line docstring summary should start at the second line')
 | 
						||
def asdfsdsdf24():
 | 
						||
    """Summary.
 | 
						||
 | 
						||
       Description.
 | 
						||
 | 
						||
    """
 | 
						||
 | 
						||
 | 
						||
@expect('D208: Docstring is over-indented')
 | 
						||
@expect('D213: Multi-line docstring summary should start at the second line')
 | 
						||
def asdfsdsdfsdf24():
 | 
						||
    """Summary.
 | 
						||
 | 
						||
    Description.
 | 
						||
 | 
						||
        """
 | 
						||
 | 
						||
 | 
						||
@expect('D208: Docstring is over-indented')
 | 
						||
@expect('D213: Multi-line docstring summary should start at the second line')
 | 
						||
def asdfsdfsdsdsdfsdf24():
 | 
						||
    """Summary.
 | 
						||
 | 
						||
        Description.
 | 
						||
 | 
						||
    """
 | 
						||
 | 
						||
 | 
						||
@expect('D209: Multi-line docstring closing quotes should be on a separate '
 | 
						||
        'line')
 | 
						||
@expect('D213: Multi-line docstring summary should start at the second line')
 | 
						||
def asdfljdf24():
 | 
						||
    """Summary.
 | 
						||
 | 
						||
    Description."""
 | 
						||
 | 
						||
 | 
						||
@expect('D210: No whitespaces allowed surrounding docstring text')
 | 
						||
def endswith():
 | 
						||
    """Whitespace at the end. """
 | 
						||
 | 
						||
 | 
						||
@expect('D210: No whitespaces allowed surrounding docstring text')
 | 
						||
def around():
 | 
						||
    """ Whitespace at everywhere. """
 | 
						||
 | 
						||
 | 
						||
@expect('D210: No whitespaces allowed surrounding docstring text')
 | 
						||
@expect('D213: Multi-line docstring summary should start at the second line')
 | 
						||
def multiline():
 | 
						||
    """ Whitespace at the beginning.
 | 
						||
 | 
						||
    This is the end.
 | 
						||
    """
 | 
						||
 | 
						||
 | 
						||
@expect('D300: Use """triple double quotes""" (found \'\'\'-quotes)')
 | 
						||
def triple_single_quotes_raw():
 | 
						||
    r'''Summary.'''
 | 
						||
 | 
						||
 | 
						||
@expect('D300: Use """triple double quotes""" (found \'\'\'-quotes)')
 | 
						||
def triple_single_quotes_raw_uppercase():
 | 
						||
    R'''Summary.'''
 | 
						||
 | 
						||
 | 
						||
@expect('D300: Use """triple double quotes""" (found \'-quotes)')
 | 
						||
def single_quotes_raw():
 | 
						||
    r'Summary.'
 | 
						||
 | 
						||
 | 
						||
@expect('D300: Use """triple double quotes""" (found \'-quotes)')
 | 
						||
def single_quotes_raw_uppercase():
 | 
						||
    R'Summary.'
 | 
						||
 | 
						||
 | 
						||
@expect('D300: Use """triple double quotes""" (found \'-quotes)')
 | 
						||
@expect('D301: Use r""" if any backslashes in a docstring')
 | 
						||
def single_quotes_raw_uppercase_backslash():
 | 
						||
    R'Sum\mary.'
 | 
						||
 | 
						||
 | 
						||
@expect('D301: Use r""" if any backslashes in a docstring')
 | 
						||
def double_quotes_backslash():
 | 
						||
    """Sum\\mary."""
 | 
						||
 | 
						||
 | 
						||
@expect('D301: Use r""" if any backslashes in a docstring')
 | 
						||
def double_quotes_backslash_uppercase():
 | 
						||
    R"""Sum\\mary."""
 | 
						||
 | 
						||
 | 
						||
@expect('D213: Multi-line docstring summary should start at the second line')
 | 
						||
def exceptions_of_D301():
 | 
						||
    """Exclude some backslashes from D301.
 | 
						||
 | 
						||
    In particular, line continuations \
 | 
						||
    and unicode literals \u0394 and \N{GREEK CAPITAL LETTER DELTA}.
 | 
						||
    They are considered to be intentionally unescaped.
 | 
						||
    """
 | 
						||
 | 
						||
 | 
						||
@expect("D400: First line should end with a period (not 'y')")
 | 
						||
@expect("D415: First line should end with a period, question mark, "
 | 
						||
        "or exclamation point (not 'y')")
 | 
						||
def lwnlkjl():
 | 
						||
    """Summary"""
 | 
						||
 | 
						||
 | 
						||
@expect("D401: First line should be in imperative mood "
 | 
						||
        "(perhaps 'Return', not 'Returns')")
 | 
						||
def liouiwnlkjl():
 | 
						||
    """Returns foo."""
 | 
						||
 | 
						||
 | 
						||
@expect("D401: First line should be in imperative mood; try rephrasing "
 | 
						||
        "(found 'Constructor')")
 | 
						||
def sdgfsdg23245():
 | 
						||
    """Constructor for a foo."""
 | 
						||
 | 
						||
 | 
						||
@expect("D401: First line should be in imperative mood; try rephrasing "
 | 
						||
        "(found 'Constructor')")
 | 
						||
def sdgfsdg23245777():
 | 
						||
    """Constructor."""
 | 
						||
 | 
						||
 | 
						||
@expect('D402: First line should not be the function\'s "signature"')
 | 
						||
def foobar():
 | 
						||
    """Signature: foobar()."""
 | 
						||
 | 
						||
 | 
						||
@expect('D213: Multi-line docstring summary should start at the second line')
 | 
						||
def new_209():
 | 
						||
    """First line.
 | 
						||
 | 
						||
    More lines.
 | 
						||
    """
 | 
						||
    pass
 | 
						||
 | 
						||
 | 
						||
@expect('D213: Multi-line docstring summary should start at the second line')
 | 
						||
def old_209():
 | 
						||
    """One liner.
 | 
						||
 | 
						||
    Multi-line comments. OK to have extra blank line
 | 
						||
 | 
						||
    """
 | 
						||
 | 
						||
 | 
						||
@expect("D103: Missing docstring in public function")
 | 
						||
def oneliner_d102(): return
 | 
						||
 | 
						||
 | 
						||
@expect("D400: First line should end with a period (not 'r')")
 | 
						||
@expect("D415: First line should end with a period, question mark,"
 | 
						||
        " or exclamation point (not 'r')")
 | 
						||
def oneliner_withdoc(): """One liner"""
 | 
						||
 | 
						||
 | 
						||
def ignored_decorator(func):   # noqa: D400,D401,D415
 | 
						||
    """Runs something"""
 | 
						||
    func()
 | 
						||
    pass
 | 
						||
 | 
						||
 | 
						||
def decorator_for_test(func):   # noqa: D400,D401,D415
 | 
						||
    """Runs something"""
 | 
						||
    func()
 | 
						||
    pass
 | 
						||
 | 
						||
 | 
						||
@ignored_decorator
 | 
						||
def oneliner_ignored_decorator(): """One liner"""
 | 
						||
 | 
						||
 | 
						||
@decorator_for_test
 | 
						||
@expect("D400: First line should end with a period (not 'r')")
 | 
						||
@expect("D415: First line should end with a period, question mark,"
 | 
						||
        " or exclamation point (not 'r')")
 | 
						||
def oneliner_with_decorator_expecting_errors(): """One liner"""
 | 
						||
 | 
						||
 | 
						||
@decorator_for_test
 | 
						||
def valid_oneliner_with_decorator(): """One liner."""
 | 
						||
 | 
						||
 | 
						||
@expect("D207: Docstring is under-indented")
 | 
						||
@expect('D213: Multi-line docstring summary should start at the second line')
 | 
						||
def docstring_start_in_same_line(): """First Line.
 | 
						||
 | 
						||
    Second Line
 | 
						||
    """
 | 
						||
 | 
						||
 | 
						||
def function_with_lambda_arg(x=lambda y: y):
 | 
						||
    """Wrap the given lambda."""
 | 
						||
 | 
						||
 | 
						||
@expect('D213: Multi-line docstring summary should start at the second line')
 | 
						||
def a_following_valid_function(x=None):
 | 
						||
    """Check for a bug where the previous function caused an assertion.
 | 
						||
 | 
						||
    The assertion was caused in the next function, so this one is necessary.
 | 
						||
 | 
						||
    """
 | 
						||
 | 
						||
 | 
						||
def outer_function():
 | 
						||
    """Do something."""
 | 
						||
    def inner_function():
 | 
						||
        """Do inner something."""
 | 
						||
        return 0
 | 
						||
 | 
						||
 | 
						||
@expect("D400: First line should end with a period (not 'g')")
 | 
						||
@expect("D401: First line should be in imperative mood "
 | 
						||
        "(perhaps 'Run', not 'Runs')")
 | 
						||
@expect("D415: First line should end with a period, question mark, "
 | 
						||
        "or exclamation point (not 'g')")
 | 
						||
def docstring_bad():
 | 
						||
    """Runs something"""
 | 
						||
    pass
 | 
						||
 | 
						||
 | 
						||
def docstring_bad_ignore_all():  # noqa
 | 
						||
    """Runs something"""
 | 
						||
    pass
 | 
						||
 | 
						||
 | 
						||
def docstring_bad_ignore_one():  # noqa: D400,D401,D415
 | 
						||
    """Runs something"""
 | 
						||
    pass
 | 
						||
 | 
						||
 | 
						||
@expect("D401: First line should be in imperative mood "
 | 
						||
        "(perhaps 'Run', not 'Runs')")
 | 
						||
def docstring_ignore_some_violations_but_catch_D401():  # noqa: E501,D400,D415
 | 
						||
    """Runs something"""
 | 
						||
    pass
 | 
						||
 | 
						||
 | 
						||
@expect(
 | 
						||
    "D401: First line should be in imperative mood "
 | 
						||
    "(perhaps 'Initiate', not 'Initiates')"
 | 
						||
)
 | 
						||
def docstring_initiates():
 | 
						||
    """Initiates the process."""
 | 
						||
 | 
						||
 | 
						||
@expect(
 | 
						||
    "D401: First line should be in imperative mood "
 | 
						||
    "(perhaps 'Initialize', not 'Initializes')"
 | 
						||
)
 | 
						||
def docstring_initializes():
 | 
						||
    """Initializes the process."""
 | 
						||
 | 
						||
 | 
						||
@wraps(docstring_bad_ignore_one)
 | 
						||
def bad_decorated_function():
 | 
						||
    """Bad (E501) but decorated"""
 | 
						||
    pass
 | 
						||
 | 
						||
 | 
						||
def valid_google_string():  # noqa: D400
 | 
						||
    """Test a valid something!"""
 | 
						||
 | 
						||
 | 
						||
@expect("D415: First line should end with a period, question mark, "
 | 
						||
        "or exclamation point (not 'g')")
 | 
						||
def bad_google_string():  # noqa: D400
 | 
						||
    """Test a valid something"""
 | 
						||
 | 
						||
 | 
						||
# This is reproducing a bug where AttributeError is raised when parsing class
 | 
						||
# parameters as functions for Google / Numpy conventions.
 | 
						||
class Blah:  # noqa: D203,D213
 | 
						||
    """A Blah.
 | 
						||
 | 
						||
    Parameters
 | 
						||
    ----------
 | 
						||
    x : int
 | 
						||
 | 
						||
    """
 | 
						||
 | 
						||
    def __init__(self, x):
 | 
						||
        pass
 | 
						||
 | 
						||
 | 
						||
expect(os.path.normcase(__file__ if __file__[-1] != 'c' else __file__[:-1]),
 | 
						||
       'D100: Missing docstring in public module')
 | 
						||
 | 
						||
 | 
						||
@expect('D201: No blank lines allowed before function docstring (found 1)')
 | 
						||
@expect('D213: Multi-line docstring summary should start at the second line')
 | 
						||
def multiline_leading_space():
 | 
						||
 | 
						||
    """Leading space.
 | 
						||
 | 
						||
    More content.
 | 
						||
    """
 | 
						||
 | 
						||
 | 
						||
@expect('D202: No blank lines allowed after function docstring (found 1)')
 | 
						||
@expect('D213: Multi-line docstring summary should start at the second line')
 | 
						||
def multiline_trailing_space():
 | 
						||
    """Leading space.
 | 
						||
 | 
						||
    More content.
 | 
						||
    """
 | 
						||
 | 
						||
    pass
 | 
						||
 | 
						||
 | 
						||
@expect('D201: No blank lines allowed before function docstring (found 1)')
 | 
						||
@expect('D202: No blank lines allowed after function docstring (found 1)')
 | 
						||
@expect('D213: Multi-line docstring summary should start at the second line')
 | 
						||
def multiline_trailing_and_leading_space():
 | 
						||
 | 
						||
    """Trailing and leading space.
 | 
						||
 | 
						||
    More content.
 | 
						||
    """
 | 
						||
 | 
						||
    pass
 | 
						||
 | 
						||
 | 
						||
@expect('D210: No whitespaces allowed surrounding docstring text')
 | 
						||
@expect("D400: First line should end with a period (not '\"')")
 | 
						||
@expect("D415: First line should end with a period, question mark, "
 | 
						||
        "or exclamation point (not '\"')")
 | 
						||
def endswith_quote():
 | 
						||
    """Whitespace at the end, but also a quote" """
 | 
						||
 | 
						||
 | 
						||
@expect('D209: Multi-line docstring closing quotes should be on a separate '
 | 
						||
        'line')
 | 
						||
@expect('D213: Multi-line docstring summary should start at the second line')
 | 
						||
def asdfljdjgf24():
 | 
						||
    """Summary.
 | 
						||
 | 
						||
    Description.  """
 | 
						||
 | 
						||
 | 
						||
@expect('D200: One-line docstring should fit on one line with quotes '
 | 
						||
        '(found 3)')
 | 
						||
@expect('D212: Multi-line docstring summary should start at the first line')
 | 
						||
def one_liner():
 | 
						||
    """
 | 
						||
 | 
						||
    Wrong."""
 | 
						||
 | 
						||
 | 
						||
@expect('D200: One-line docstring should fit on one line with quotes '
 | 
						||
        '(found 3)')
 | 
						||
@expect('D212: Multi-line docstring summary should start at the first line')
 | 
						||
def one_liner():
 | 
						||
    r"""Wrong.
 | 
						||
 | 
						||
    """
 | 
						||
 | 
						||
 | 
						||
@expect('D200: One-line docstring should fit on one line with quotes '
 | 
						||
        '(found 3)')
 | 
						||
@expect('D212: Multi-line docstring summary should start at the first line')
 | 
						||
def one_liner():
 | 
						||
    """Wrong."
 | 
						||
 | 
						||
    """
 | 
						||
 | 
						||
 | 
						||
@expect('D200: One-line docstring should fit on one line with quotes '
 | 
						||
        '(found 3)')
 | 
						||
@expect('D212: Multi-line docstring summary should start at the first line')
 | 
						||
def one_liner():
 | 
						||
    """
 | 
						||
 | 
						||
    "Wrong."""
 | 
						||
 | 
						||
 | 
						||
@expect('D404: First word of the docstring should not be "This"')
 | 
						||
def starts_with_this():
 | 
						||
    """This is a docstring."""
 | 
						||
 | 
						||
 | 
						||
@expect('D404: First word of the docstring should not be "This"')
 | 
						||
def starts_with_space_then_this():
 | 
						||
    """ This is a docstring that starts with a space."""  # noqa: D210
 | 
						||
 | 
						||
 | 
						||
class SameLine: """This is a docstring on the same line"""
 | 
						||
 | 
						||
def same_line(): """This is a docstring on the same line"""
 | 
						||
 | 
						||
 | 
						||
def single_line_docstring_with_an_escaped_backslash():
 | 
						||
    "\
 | 
						||
    "
 | 
						||
 | 
						||
class StatementOnSameLineAsDocstring:
 | 
						||
    "After this docstring there's another statement on the same line separated by a semicolon." ; priorities=1
 | 
						||
    def sort_services(self):
 | 
						||
        pass
 | 
						||
 | 
						||
class StatementOnSameLineAsDocstring:
 | 
						||
    "After this docstring there's another statement on the same line separated by a semicolon."; priorities=1
 | 
						||
 | 
						||
 | 
						||
class CommentAfterDocstring:
 | 
						||
    "After this docstring there's a comment."  # priorities=1
 | 
						||
    def sort_services(self):
 | 
						||
        pass
 | 
						||
 | 
						||
 | 
						||
def newline_after_closing_quote(self):
 | 
						||
    "We enforce a newline after the closing quote for a multi-line docstring \
 | 
						||
    but continuations shouldn't be considered multi-line"
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
def retain_extra_whitespace():
 | 
						||
    """Summary.
 | 
						||
 | 
						||
        This is overindented
 | 
						||
            And so is this, but it we should preserve the extra space on this line relative
 | 
						||
            to the one before
 | 
						||
    """
 | 
						||
 | 
						||
 | 
						||
def retain_extra_whitespace_multiple():
 | 
						||
    """Summary.
 | 
						||
 | 
						||
        This is overindented
 | 
						||
            And so is this, but it we should preserve the extra space on this line relative
 | 
						||
            to the one before
 | 
						||
        This is also overindented
 | 
						||
            And so is this, but it we should preserve the extra space on this line relative
 | 
						||
            to the one before
 | 
						||
    """
 | 
						||
 | 
						||
 | 
						||
 | 
						||
def retain_extra_whitespace_deeper():
 | 
						||
    """Summary.
 | 
						||
 | 
						||
        This is overindented
 | 
						||
            And so is this, but it we should preserve the extra space on this line relative
 | 
						||
            to the one before
 | 
						||
                And the relative indent here should be preserved too
 | 
						||
    """
 | 
						||
 | 
						||
def retain_extra_whitespace_followed_by_same_offset():
 | 
						||
    """Summary.
 | 
						||
 | 
						||
        This is overindented
 | 
						||
            And so is this, but it we should preserve the extra space on this line relative
 | 
						||
        This is overindented
 | 
						||
        This is overindented
 | 
						||
    """
 | 
						||
 | 
						||
 | 
						||
def retain_extra_whitespace_not_overindented():
 | 
						||
    """Summary.
 | 
						||
 | 
						||
    This is not overindented
 | 
						||
        This is overindented, but since one line is not overindented this should not raise
 | 
						||
            And so is this, but it we should preserve the extra space on this line relative
 | 
						||
    """
 | 
						||
 | 
						||
 | 
						||
def inconsistent_indent_byte_size():
 | 
						||
    """There's a non-breaking space (2-bytes) after 3 spaces (https://github.com/astral-sh/ruff/issues/9080).
 | 
						||
 | 
						||
       Returns:
 | 
						||
    """
 |