Squeezing the sponge: How to implement a buffering SMTP Handler in Python

…when he needs what you have gleaned, it is but squeezing you,
and, sponge, you shall be dry again.
– Hamlet

One of the first things I implement in most Python projects is some quick stream logging so as not to dot too many print statements across the code. At some point file logging usually  follows as a feature so it can run by itself and I can check up on it from time to time.

Recently I got ambitious and added email logging to poca, my podcast client project. Which isn’t difficult as the logging module has an SMTPHandler built-in that you just stick on your logger and now your logs are airborne. It’s almost xkcd-like. The way it works though is that an email is sent off instantly every time something is logged, just like stream logging only over port 25. This was not what I wanted. To be specific I was looking for something that

  • Would gather up log entries as my script runs it course
  • At the end of the script it would evaluate if there was anything worthwhile sending
  • If so, send it; if not, save, don’t send

The way to do, as suggested by the logging module author himself, is to subclass the BufferingHandler which does a fine job of soaking up the entries and keeping them until its time to release them. He has written an example of how to do this himself and put it on Github.

I had, however, a further requirement. When a podcast feed fails, it’s not necessarily cause for alarm or notifying the user. Maybe the server’s in maintenance mode for a few minutes, maybe builders unplugged the cable for an hour, maybe you did. You only really need email logging to tell you when a podcast feed consistently fails because then it’s probably either a software failure or the feed is offline, either of which requires user intervention. Vinay Sajip’s script doesn’t allow for that. Also, using unicode is easier if we keep a clear distinction between body and headers which Sajip’s approach seems to fudge a bit.

My requirements meant that I would have to not just buffer entries in memory but save them over time and only release them when there was a sufficient number (and of sufficient severity) to worry about.

(more…)

Alphanumericalize: Filename munging music file names in ABCDE

Ripping CD feels a lot more 2005 than 2015. And it was probably already starting to feel old back then. However, I never got round to do a systematic, lossless rip of my entire CD collection. So before it’s too late I have bought a DVD-RW drive that will never get to write a single disc and armed myself with a 1Tb USB drive to hold all the data.

My weapon of choice is ABCDE, A Better CD Encoder, a Bash based CLI tool for ripping that has been in continuous development since before 2002 (!). ABCDE has many advantages over GUI CD rippers, the most obvious being that you don’t need to fiddle with the mouse, you just hit enter. This is important if you’ve got a case of hundreds of CDs to get through.

Another advantage is that the settings file allows you to string a piped line of stream editors together when forming the file name. What this means is that once you have determined how the file names should be formed, e.g. “Artist/Album/Track no. – Track title”, you can further manipulate it e.g. by making it entirely lower-/uppercase, removing slashes and other control characters etc. The genius of ABCDE is that rather than implement these features itself, it simply allows you to use tested and true unix utilities, like sed and tr and whatever else you care to throw at it to accomplish this.

Here I’m going to detail generally how this ‘filename munging’ works and specifically I’m going to show how to get file names that are universally OS-, URL- and command line friendly by only using numerical digits, the letters a-z, underscores (_) and hyphens (-).

(more…)