Sweat The Small Stuff
Details matter.
I’ve been enamored recently with building little Python packages that provide useful capabilities for my colleagues. Things like a client for our internal ticketing system, a convenience wrapper to interact with our LDAP servers, etc. And I talk about them non-stop with anyone who will listen, because I truly believe they are helpful for automating mundane tasks across the organization.
But a pesky thing happens when actual people try to use your code. Bugs pop up. Installation errors occur. Weird behaviors manifest. Whatever can go wrong, will go wrong, and if you’re lucky, you’re going to hear about it from your users. If you’re unlucky, no one will bother to contact you or use your code again.
The gap between a toy script you write for yourself and a full-fledged tool usable by others is vast. Numerous compatibility and usability considerations must be considered: differing hardware, operating systems, language versions, user familiarity, probably even more things I’m not thinking of.
Case in point. A few weeks ago I added @functools.cache
to a couple packages in key places where expensive API calls were being made. It’s a rad little annotation, but was new to Python 3.9. Didn’t take long before someone hit an error message that was anything but clear to them. Quickly I patched the code up by replacing with @functools.lru_cache
which does basically the same thing and has been around for a while longer. But did I bother to test on the older version? No I did not (and shame on me, because tox and pyenv make doing so easy). Once again my user was thwarted, because while Python 3.8 allowed the use of this annotation without a parameter, Python 3.6 and 3.7 do not (and he was running 3.6.9). Once again, I had to quickly patch, but this time I made sure my tox setup tested across versions.
The worst part of the above is that I could have better guarded against an esoteric error message by specifying precise compatibility in setup.py
(in this case with a python_requires='>=3.6'
instead of python_requires='>=3'
). If I’d have done that, my user would have still gotten an error, but it would have happened at install time, and been much clearer as to the cause. Two extra characters in an install script, but hugely improved customer experience.
Like I said, details matter.