I agree. But those are not our only choices.
The ironic thing about Python is that it actually does have an open-brace. It's the colon. The compiler can tell that this:
def foo():
baz()
is syntactically incorrect. And if you tab the second line, auto-indent can do the Right Thing. The screw case is this:
def foo():
if baz:
bar()
bing()
boff()
If you auto-indent the last line, it will quietly change the semantics of your program. That's bad.
I always end my blocks with a PASS statement (or a return), i.e.:
def foo():
if baz:
bar()
bing()
pass
boff()
return
If you do this, then auto-indent will always do the Right Thing. This is particularly beneficial if you want to take a big block of code and wrap in an an outer block. I can add two lines to the above code:
def foo():
while snoz: <--
if baz:
bar()
bing()
pass
boff()
pass <--
return
Then I can just auto-indent the whole thing and be confident that the result will be correct.
Contrast this with the traditional method where you have to manually re-indent your code. If you accidentally select the wrong region to re-indent you can change the semantics of the code in a way that loses the information about what the semantics should have been. The only way to recover from this is to manually reconstruct the correct semantics. It may not happen very often, but when it does it's a colossal PITA. (Entering those examples was a colossal PITA too.)