Skip to content

Formatter: Attribute and call chains "fluent interface" #5343

@konstin

Description

@konstin

Black supports attribute access and call chaining to provide good formatting for fluent interface style programming with extensive method chaining which is common e.g. with django (https://black.readthedocs.io/en/stable/the_black_code_style/current_style.html#call-chains):

def example(session):
    result = (
        session.query(models.Customer.id)
        .filter(
            models.Customer.account_id == account_id,
            models.Customer.email == email_address,
        )
        .order_by(models.Customer.id.asc())
        .all()
    )

#5340 implements a part of this badly to fix a bug and #5341 adds basic function call formatting.

We need to implement a formatting where the outermost call adds the optional parentheses and formats all inner accesses and calls to not have them add parentheses. A complication is that unlike for if-statements the tree is left recursive, meaning that for a.b().c.d.e the outermost call see an access of e on a.b().c.d, while we must format first a, then .b(), .d and finally .e. We can implement by either collecting into a stack (needs allocation) or using recursing (we most not overrun the recursion and stack limits).

Metadata

Metadata

Labels

formatterRelated to the formatter

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions