Tabs are *MISUNDERSTOOD*, *EVIL* AND *STUPID*, end of discussion. (Re: Tabs versus Spaces in Source Code)

Duncan Booth duncan.booth at invalid.invalid
Thu May 18 04:30:03 EDT 2006


PoD wrote:
> How many levels of indentation does 12 spaces indicate?
> It could be 1,2,3,4,6 or 12.  If you say it's 3 then you are
> _implying_ that each level is represented by 4 spaces.

By reading the code I can see how many levels of indentation it
represents. 

> How many levels of indentation is 3 tabs?  3 levels in any code that
> you will find in the wild.

No. That is precisely the problem: there is code in the wild which
contains mixed space and tab indentation, and any time that happens 3
tabs could mean any number of indentations. 

Now, I just know someone is going to challenge me over my assertion that
there really could be code with mixed spaces and tabs out there, so here
are a few examples found by grepping a Plone Products folder. All the 
projects below use spaces almost everywhere for indentation, but it looks
like a few tabs slipped through.

http://svn.plone.org/view/archetypes/Archetypes/trunk/BaseUnit.py?rev=5111&view=auto 

contains tabs at the start of two lines. Fortunately these are
continuation lines so it doesn't really matter how you display them. I
think they are intended to be displayed with tab-size=8.

http://svn.plone.org/view/archetypes/Archetypes/trunk/Storage/__init__.py?rev=4970&view=auto

One tab used for indentation. The block is only one line long so the code
doesn't break whatever tabsize you use, but visually it would appear the 
intended tabsize is 0.

http://svn.plone.org/view/plone/CMFPlone/trunk/skins/plone_scripts/computeRelatedItems.py?rev=9836&view=auto

A tab is used for two levels of indentation. Anything other than tabsize=8 
would cause a syntax error.

http://svn.plone.org/view/plone/CMFPlone/trunk/skins/plone_scripts/computeRoleMap.py?rev=9836&view=auto

Lots of tabs, most but not all on continuation lines. The two which aren't 
are on single line blocks with a single tab representing two indents.

CMFPlone\tests\testInterfaces.py
CMFPlone\tests\testTranslationServiceTool.py
ExternalEditor (various files)
kupu (spellcheck.py)

and finally, at the end of my Plone Products directory I found this beauty 
where I've replaced the tab characters with <tab> to make them visible:

svn://svn.zope.org/repos/main/Zelenium/trunk/scripts/tinyWebServer.py

if __name__ == '__main__':
<tab>port = PORT
<tab>if len(sys.argv) > 1:
<tab>    port = int(sys.argv[1])
<tab>
        server_address = ('', port)
    <tab>httpd = BaseHTTPServer.HTTPServer(server_address, HTTPHandler)
    
    <tab>print "serving at port", port
    <tab>print "To run the entire JsUnit test suite, open"
    <tab>print "  http://localhost:8000/jsunit/testRunner.html?testPage=http://localhost:8000/tests/JsUnitSuite.html&autoRun=true"
    <tab>print "To run the acceptance test suite, open"
    <tab>print "  http://localhost:8000/TestRunner.html"
    
    <tab>while not HTTPHandler.quitRequestReceived :
        <tab>httpd.handle_request()<tab>
<tab>

This is a genuine example of code in the wild which will look like 
syntactically valid Python at either tab-size=4 or tab-size=8, but 
if you view it at tab-size=4 you will see different block indentation 
than the Python interpreter uses at tab-size=8.

At tab-size=4 it reads:

if __name__ == '__main__':
    port = PORT
    if len(sys.argv) > 1:
        port = int(sys.argv[1])
    
        server_address = ('', port)
        httpd = BaseHTTPServer.HTTPServer(server_address, HTTPHandler)
    
        print "serving at port", port
        print "To run the entire JsUnit test suite, open"
        print "  http://localhost:8000/jsunit/testRunner.html?testPage=http://localhost:8000/tests/JsUnitSuite.html&autoRun=true"
        print "To run the acceptance test suite, open"
        print "  http://localhost:8000/TestRunner.html"
    
        while not HTTPHandler.quitRequestReceived :
            httpd.handle_request()  
    
but at tab-size=8 it reads:

if __name__ == '__main__':
        port = PORT
        if len(sys.argv) > 1:
            port = int(sys.argv[1])
        
        server_address = ('', port)
        httpd = BaseHTTPServer.HTTPServer(server_address, HTTPHandler)
    
        print "serving at port", port
        print "To run the entire JsUnit test suite, open"
        print "  http://localhost:8000/jsunit/testRunner.html?testPage=http://localhost:8000/tests/JsUnitSuite.html&autoRun=true"
        print "To run the acceptance test suite, open"
        print "  http://localhost:8000/TestRunner.html"
    
        while not HTTPHandler.quitRequestReceived :
                httpd.handle_request()  
        
I wouldn't have a problem with tabs if Python rejected mixed indentation by 
default, because then none of the code above would execute. But it doesn't.
 :(

Anyone got a subversion checkin hook to reject mixed indentation? I think that big
repositories like Zope and Plone could benefit from it.

I just ran the same grep on the Python source tree. Not a tab in sight. :)



More information about the Python-list mailing list