Moving, part 3

I'm creating a theme basically from scratch. I have hated web design with a burning passion for over a decade. Bootstrap makes it easier but it is still easily the single most miserable programming I've had to suffer through in years.

At least pagination works. Mostly. With problems. With hard-coded URL's. So it doesn't work for category views.

I HATE web design.

Moving, part 2

It appears Pelican has made a stand against supporting multiple categories. There are two bug reports that I've found where somebody requested support for multiple categories and was told no. This is something I applaud and encourage. Happily, Pelican is open source so I can modify it to support multiple categories.

Also, it appears Pelican has limited feed and archive settings. I can customize the URL structure for articles, pages, translations, tags, categories, drafts, authors...but not feeds or archives. I consider this an exposure in my URL design so I'll modify this as well.

Moving, part 1

This past week I set up a web server and started customizing Pelican, the blog software I expect I'll use to generate the site. I am making some changes to the theme, but after it's functional enough I will begin working to import over 10 years of content.

The state of feedparser

feedparser is near and dear to my heart but I haven't touched it in quite a while. There are a number of personal and professional reasons for this which I won't bore you with here, but those same forces are now allowing and compelling me back. Personally, I'm needing to do some coding that isn't work-related. Professionally, I've been writing software in utter isolation for two years but am now expecting that I will begin to see contributions from others...meaning that I need to finally have a better understanding of git. So let's see what's going on now and where I'd like to direct the project this year!

As of right now, the Python Project Index has almost 48,000 downloads on record in the last month. Google has only 84,000 downloads listed for the last two years since I released version 5.1.3. In 2013 Google Code announced that it was discontinuing file hosting so starting with the next release, feedparser downloads will be exclusively available through PyPI.

Both due to my company's ISO 9001 policies and in expectation that others will soon be contributing to my software, I've completely switched all of my professional git repos over to the Vincent Driessen's git branching model. I've been shocked how easy it's been to release new updates with this model so in 2015 I'll migrate feedparser's git repo over to this model.

feedparser has been a monolithic blob of code since its inception. As a project, it's refused to let go of ancient Python compatibility; when I first started contributing half a decade ago my first big patch was also the first compatibility loss the project had ever seen (no on cries for you, Python 2.3). I've been reevaluating Python interpreter support and see that it's time to let go of Python 2.4 at least, and possibly Python 2.5 and 2.6, too. I also think it's time to separate feedparser into function-specific files, in part to encourage a model for adding additional namespace support.

These are all achievable near-term goals. They open the door for better merging, faster releases, and more maintainable code. I'm excited for 2015!

In the beginning

My first programming language was some variant of BASIC on a VTech Precomputer 2000. Then one day I discovered that a copy of QBasic was included with DOS and began using it to program. I wrote software to add and subtract arbitrarily long strings of integers (I don't think I added support for floating point), software that would perform long division of polynomials, and software that would graph my math homework. One day while a friend and I were goofing around with some code, his dad happened to look over our shoulders and said "You know, you should put that block of code in a subroutine." We didn't know what that was but after a few minutes saw its utility as our code became more modular.

When we were 16, that same friend and I decided to create software with a brand: Freesoft. Our slogan was "Freesoft for the common man". My friend used a font editor to identify the horizontal lines for the letter 'f' in a fancy font and programmed that as a rasterized image that would display at the start of our software...even playing a tune he created! My software usually involved algorithms and math while his software was usually games, including a multiplayer version of Nibbles (or Snake, as it's usually called) and a simple two-player Scorched Earth-style ballistics/physics game. We also created a website to host our software using Xoom web hosting and created multiple email pseudonyms for ourselves using the free Juno email service. We thought we were pretty cool.

Now, 14 years later, my mom was gearing up for a garage sale and I found an old 3.5" floppy disk. It's labeled in my finest handwriting with the following list:

  • Fontmaker
  • Iconmaker
  • Freesoft programs
  • FirstBASIC

QBASIC ruined my brain for several years, creating patterns of thinking that were difficult to change when I tried to learn other programming languages. Thank goodness I did or I would still be spinning my wheels trying to use Envelop Basic, XBasic, and RapidQ.

Even so, I'm going to try recovering that old software. I want to see what my code looked like back then.

Caller ID blocking options

I've been considering asking my company to drop my work cell phone plan and pay for my personal cell phone plan. Some people might cringe to be more accessible to their company but work already calls my personal phone all the time. Therefore, the biggest concern I have about doing this is that I sometimes have to interface with outside people who don't need my personal cell phone number.

I can give out my desk number and have that forward to my personal cell phone but if I return a call I need my personal number hidden and there just don't seem to be options for doing this systematically. Sure, you can find apps in the Google Play store but they all appear to be designed with the assumption that you're blocking or changing your caller ID number because you want to be a douchebag to people. What I've yet to see is a setting or an app that simply dials *67 on outgoing phone calls if certain rules are met. I imagine it would work with a blacklist/whitelist option:

  • Blacklist version: Only dial *67 if the contact is in a specific category in your address book, like "Work".
  • Whitelist version: Always dial *67 unless the contact is in your address book and is not in a specific category in your address book.

I've seen articles suggesting that more and more businesses are supporting a bring-your-own-device model, but I'm not finding apps or settings that would support my use case. Does anyone have app or search keyword suggestions? Searching "spoof caller id" simply turns up apps advertising that you can "Find out if your ex is ignoring you! Confuse your friends! Get through to someone really important!" which is not my goal here.

Update: I finally found the right search term: "android auto dial prefix". This led me to Prefixer, which appears to be exactly what I want. The free version allows you to configure a single rule but I think that'll be sufficient.

The Debris Cathedral

For a very long time I've been writing code at my job that automates some very tedious tasks. It's not Python code, though! It's a macro language that has saved the company a lot of time and energy but suffers from severe limitations:

  • No scoping -- everything is in a global namespace.
  • No functions -- the entire language is based on keywords.
  • Incomplete support for lists -- the list can be defined but its length cannot later be checked.
  • Incomplete support for including code from other source files -- the included file will run from top to bottom and exit.
  • Inconsistent ordinal and cardinal numbering -- list indices start with '0', but string indices start with '1'.
  • Insufficient variable quantity and size limits -- one maximum quantity, for instance, is '9'.
  • GOTO.

A couple of years back I inherited some code and ran with it, but now I'm bumping up against these limits on a regular basis so I've had to get creative. Did you ever see Apollo 13? You know the scene where they gather scientists and engineers in a room, dump out a bunch of junk on the table, and tell the team "Make an oxygen filter"? I did that with this language.

I picked up INCLUDE in one hand and GOTO in the other and stared at the global namespace and decided "I'm going to emulate functions in a namespace." Now I'm able to call code in other files using this syntax:

callsub = 'namespace:function'
INCLUDE 'subroutine'

The integer size limits were truncating calculations so (really heavy sigh) I wrote code that adds two hexadecimal strings of arbitrary length, thus avoiding integers entirely. That's something I did for fun in QBasic when I was 16, and the concept was revisited when I was wiring an adder on a breadboard in college, but it is staggering to have to do that to get real work done.

This is tested production code, so that's not going to get thrown away anytime soon. However, each time I bolt on another feature I feel like I'm building a cathedral out of rubble and debris. Relief is on its way, though: I've been building a foundation in Python that I believe I can shift this macro code over to. Then Python can handle the business logic and final validation while leveraging tested code to perform the required steps.

A change of scenery

I am absolutely lost on this computer of mine.

When my old PC finally died and I built my new one, I tried several different Linux distributions and was dissatisfied with each for some reason or another. I ended up defaulting to Ubuntu because it had the fewest hardware problems out-of-the-box and because it was what I'd been using on the old PC. However, that has proven to be a frustrating and debilitating decision: I don't use my PC but once every several weeks. I hate the GUI. Seriously, I absolutely and completely hate the GUI. It frustrates the fire out of me. It's time for something new.

So, I'm going to try Arch Linux. I want to use LVM and have snapshots of my hard drive. I want to use stock Gnome 3, customized to look like Gnome 2, the only Linux GUI I've ever been comfortable with. And I want to WANT to sit down in front of my computer and work on feedparser. I haven't touched it in forever, and I know one of the big reasons is that I hate -- HATE -- using my computer, ever. I basically only use my PC once each month because I have to pay bills.

I usually dislike announcing an intent to do something but this is more for me than it is my readership. I want a stake in the ground to spur me on to actually fix this awful situation.

Raspberry Pi benchmarks

I had a bit of time today and decided to start using the Raspberry Pi I bought last year. I'm very interested in wringing performance out of it, so to the best of my ability I'm going to measure performance.

I had previously downloaded Arch Linux, so I put that on an SD card. Then I saw a blog post suggesting that a USB drive could increase the performance. So! I adapted the instructions and captured some benchmarks. Quick summary: the USB drive has a slower write speed but a faster read speed...but I have to acknowledge that the results might be better with a different USB drive.

The SD card (a 32GB Sandisk Ultra class 10 32GB card)

[root@alarmpi sdcard]# hdparm -tT /dev/mmcblk0

 Timing cached reads:   312 MB in  2.00 seconds = 155.98 MB/sec
 Timing buffered disk reads:  54 MB in  3.06 seconds =  17.65 MB/sec
[root@alarmpi sdcard]# sync;time bash -c "(dd if=/dev/zero of=bf bs=8k count=50000; sync)"
50000+0 records in
50000+0 records out
409600000 bytes (410 MB) copied, 39.6374 s, 10.3 MB/s

real    0m41.003s
user    0m0.240s
sys     0m10.230s
[root@alarmpi sdcard]# dd if=bf of=/dev/null
800000+0 records in
800000+0 records out
409600000 bytes (410 MB) copied, 22.3598 s, 18.3 MB/s

The USB drive (a Lexar 8GB Jumpdrive)

[root@alarmpi ~]# hdparm -tT /dev/sda

 Timing cached reads:   308 MB in  2.00 seconds = 153.90 MB/sec
 Timing buffered disk reads:  58 MB in  3.04 seconds =  19.09 MB/sec
[root@alarmpi ~]# sync;time bash -c "(dd if=/dev/zero of=bf bs=8k count=50000; sync)"
50000+0 records in
50000+0 records out
409600000 bytes (410 MB) copied, 41.1666 s, 9.9 MB/s

real    0m45.185s
user    0m0.250s
sys     0m8.210s
[root@alarmpi ~]# dd if=bf of=/dev/null
800000+0 records in
800000+0 records out
409600000 bytes (410 MB) copied, 20.5428 s, 19.9 MB/s


While eating dinner with one of my brothers.

Me: I love you, Stephan.
Stephan: Thanks, Kurt.
Me: Really appreciate spending time with you, and especially when you sometimes aren't talking.
Stephan: Wha...
Me: See what I did there? That's called a 'neg'.
Stephan: Wow, you know that's really clever, Kyle! Whoops, I mean 'Kurt'. You see what I did there? Sometimes I purposefully get people's names wrong so they know I don't care about them at all. It lets them know I just don't give a