wemake-python-styleguide icon indicating copy to clipboard operation
wemake-python-styleguide copied to clipboard

Forbid "fat" finally

Open efimov-mikhail opened this issue 6 months ago • 2 comments

Rule request

Allow finally block to have simple content only. It can contain few lines of code, but it shouldn't contain untrivial logic, which can not be understand very quickly at code reading.

Thesis

Correct finally block:

  1. One-two statements.
  2. One if with elif and else w/o sub-blocks.

Wrong finally block: One bloated with business logic and hard to read.

It's arguable when exactly the watershed should be located. I propose something like this for correct finally:

  1. Up to 10 statements.
  2. Up to 2 levels of indentation (i.e. sub-blocks)
  3. Maybe up to 10 basic tokens in each statement.

Reasoning

IMO, finally block best suites for code snippets like this:


try:
    x = open_something()
    y = x.read_value()
    ...
except SomeError as e:
   ...
finally:
    close_something(x)

It's easy to read and understand what finally block stands for. But code with big and difficult finally block smells.

My arguments are here:

  1. Code in finally block should basically do nothing other than some "cleaning" or "finishing" after try and provide only necessary things. If some code can be located after try-except-finally, it should be located there, and not in finally itself.
  2. There is an accepted PEP 765 (https://peps.python.org/pep-0765/) which disallow return/break/continue in finally block for 3.14+. Thus finally is already block with very special rules, we just want to make those rules to be more strict.
  3. Generated bytecode has two copies of finally block content on latest CPython versions. As a result, big finally block provide larger code objects.

efimov-mikhail avatar Jun 13 '25 22:06 efimov-mikhail

I would put it like this: we need a rule that counts max lines in finally, by default it should be 2. Configuration should be also available.

sobolevn avatar Jun 13 '25 22:06 sobolevn

I can work. I want to take up this issue.

alexeev-prog avatar Jun 16 '25 10:06 alexeev-prog

How to deal with a function call with multiple arguments? Black will split it into multiple lines, which is ok for me. And there is no way to avoid that. Except using partial, but it's ugly. Even a function with one argument and a long name will use 3 lines of code. I suggest allowing one function call without a line number restriction. The number of arguments in a function already has its own rule.

NikitaSemenovAiforia avatar Jul 10 '25 13:07 NikitaSemenovAiforia

It should not be reported. We should only count top-level statements. Not inner ones. Please, send a fix if this is the case.

sobolevn avatar Jul 10 '25 15:07 sobolevn

It should not be reported. We should only count top-level statements. Not inner ones. Please, send a fix if this is the case.

Will be very complicated to fix. The code itself validates only number of lines. Error message, tests and error description focus only on this aspect. It should be removed and rewriten completly, as far as I inderstood. I suggest to use the same rules as in try..except block. It counts statements correctly and strict enogh.

NikitaSemenovAiforia avatar Jul 10 '25 15:07 NikitaSemenovAiforia

Yes, please :)

sobolevn avatar Jul 10 '25 16:07 sobolevn