How to Solve Annoying IndentationErrors and TabErrors in Python on Replit (or Anywhere Really)

So there I was.

Alternating between coding and listening to old Led Zeppelin tracks I totally haven't already jammed to a million times, considering that maybe I should've picked something more responsible and reliable for a career than software development.

You know, something to really impress mama... Something like being a rockstar like Jimmy Page 🎸🀘. He's got a pretty stable lifestyle, right? I could probably be him.

When all of a sudden, an evil error pulled me perniciously down from the cloudy apogee of my daydreams, reminding me of my other, more mundane, yet still flagging dream of being a code superstar like Taylor Otwell.

It was that nightmarish and nefarious error, the defeat of which has become a proper rite of passage for all up-and-coming pythonistas, and who has for decades deviously drawn the ire and dread of Python devotees the world over.

It was totally a TabError

I've recently been coding in Python on Replit.

The two are a charming duo, to be sure. But I'd be willing to bet that just about anyone, on or off Replit, that uses Python (or Ruby probably) has run into a situation I like to call "tab hell."

Even if you don't use tabs, I'm gonna call it that because it sounds catchier than "indentation hell" or "space hell"β€” although tbh that last one sounds vaguely cyberpunk/horror πŸ€”

This applies whether or not you're using tabs or spaces, and whether or not Replit is your main editor. I'm pretty sure it started to happen when I started getting cocky and trying to use code to generate code file boilerplate for my mini MVC framework.

I also stupidly altered the Replit tab settings halfway through the project, being the Neanderthal that I am. So to be clear, it was not due to a wart that Replit or Hacker's Keyboard has.

It was, as grandma used to quip with a smirk, "the operator."

Not to fear! Polydorkic is here 🦸 Or maybe I should dub myself Polydorkus πŸ˜‚

I promise we will get to the bottom of this. All examples will intentionally be easily accessible if you code on mobile like I sometimes do; otherwise, if you're on desktop then this will be even easier for you. In any case, this solution is probably a handy tool to add to your toolbox.

But What About tabnanny?

True, Python does come preloaded with that tabnanny thing. My first experience with it was... neat. But not the πŸ’― % solution I was looking for.

Here is a screenshot of an error similar to the original one I generated:

SmartSelect_20210317-125349_Firefox.jpg

Okay, let's give tabnanny a shot. Here's an example of how to use tabnanny on Replit:

Alright, so let's try it on that original problem. Here's the output:

SmartSelect_20210317-134812_Firefox.jpg

Hmm.

Not very helpful in my opinion. I'm not personally sure that tabnanny adds an immense amount of value on top of the default errors that Python already spits out. Adds a lot of cuteness though 😚

The problem in my view is that I don't just want to know what line the IndentationError is on. To solve the problem I have to contrast the problematic tab or space location with the rest of the file. How do we do that? Because the whole point of using such a debugging tool is ostensibly that it's commonly difficult to accurately evaluate such problems with a glance of the naked eye.

I knew better (just barely) than to whip out a quick find-and-replace off the top of my head and risk mangling half my codebase. My first solution was to write a small utility that reads the contents of a specified .py file and prints it to the console. That ended up being the solution, but with an additional step required.

Tabby_Poppins is supercalifragilisticexpialidocious

Before I explain it, here's the REPL (feel free to use this in your own projects):

So the Tabby_Poppins tool basically prints out the contents of the whole file to the console (unlike tabnanny which just prints out the offending line without context). Additionally, like the tabnanny tool, instead of rendering the tab and newline characters it explicitly declares their locations with \t and \n. So you can easily contrast where an actual tab character was inserted on one line and, say, spaces on another line.

Let's see what it the Tabby_Poppins strategy has to say about my original error:

SmartSelect_20210317-184205_Firefox.jpg

AHA.

So the problem is actually that an explicit tab character was used on one line before table, and spaces were used on the next line before relations. How that happened is my code boilerplate generator tool that I wrote generated the original file with an explicit \t character, but my Replit editor settings (shown below) were set so that the tab key results in spaces, NOT a literal tab character. In python, there of course needs to be consistent indentation practices within a file so that when it is parsed the parser knows how to tokenize it properly.

SmartSelect_20210317-184301_Firefox.jpg

Contrast the original Tabby_Poppins output with the output now that I was able to pinpoint and fix the issue:

SmartSelect_20210317-184631_Firefox.jpg

It pays to note that with my setup, using Replit in the Firefox Mobile web browser on Android with the Hacker's Keyboard, it turns out there is a difference between hitting the return key so the editor auto-indents the next line and simply hitting tab with the cursor at the beginning of a line. That detail isn't that important; the really important thing is that I was able to identify that inconsistency with this debugging approach and adjust it accordingly.

Because really, python doesn't care as long as your indentation is consistent in a file.

I hope you found this helpful. If it was, please like and share below! If you have any comments or constructive criticisms (or complaints about my lame sense of humor lol), I'd love to hear from you in the comments.

Β