martes, 26 de abril de 2022

Parsing args with python (alt version)

Parsing cli arguments is a solved problem. Every language has a library to get the flags from your command line. Maybe not in the stdlib, but for sure there blessed libs for it.

In Python, argparse is the official way. It's very complete and everything, but I've found it's api quite hard to follow, and I've read code that feels like written in a copypaste style, and instead of giving you more intuition on the program as a developer, it hides the knowledge of which flags go where, and which defaults they have, and which options make sense to each subcommand.

I recently rewrote a tool that had exactly that problem. Unused flags that no one removed from the argparse parsing code, hidden defaults...

When I rewrote that code, I started with this yosefk post in mind (and some reminiscence of picolisp's cli handling). I'll just do the simplest thing. Even against the standard official way (so kids, don't do it at home, or yes, do it only at home. Or not).

Here's the first version


What's already something super good is that there's 0 overhead for getting your parameters.  Of course, the parameters are not processed at all, so you'll have to cover for defaults or wrong number of args. But the language already is going to help on some of those. It will just complain if you try to call testing without an argument.

Another nice thing is that you can predict what's going to happen without checking any docs or anything. For someone that doesn't create cli apps every day, this is a nice pro IMHO.

Second version:


What can we say about this? This one takes --flag=value, and you can pass them in the order you want because the nice splat operator will take care of it. It's very rewarding to use the language features to work alongside your goal.  **kwargs, does also a great job, providing for optional parameters, that every function will make sure to validate (It should be their job anyway, not the argparser's IMHO).


Of course, in the end, the overengineering takes over:


And we end up feeling envy from --help. In this case we also can use reflection to fill in the parameters and docs from the signatures and docstrings.

That was a nice exercise!

(In the end, I just went with the first solution, because KISS and YAGNI and Suckless.)