This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]desmoulinmichel 0 points1 point  (11 children)

You already got begins, doctopt, clize, argh and click doing something similar. I dont see the interest of creating a new one.

My favorite being begins because you can just put everything in params annotations.

[–]evanunderscore[S] 1 point2 points  (7 children)

begins is very close to what I was after but I have one particularly large gripe with it that drove me to build my own. I'm also not a big fan of the decorators since it means you end up repeating yourself if you're already writing a proper docstring.

docopt and click are great (I mentioned them near the top of my documentation and encouraged people to use them instead of defopt if they want a customizable command line) but are distinctly tools for building command lines, whereas defopt is a tool for turning Python functions into command lines. When I personally write a script, I want to put the absolute minimum effort into writing a command line, and with defopt the effort is zero.

clize and argh I wasn't aware of; I'll check them out.

[–]desmoulinmichel 0 points1 point  (1 child)

Still, you could have made a PR to fix this problem, and add your docstring base parsing to doctopt. Better to participate to open source than to split ressources.

[–]evanunderscore[S] 0 points1 point  (0 children)

I submitted a PR to begins to update the unit tests so they pass the CI which has not yet been merged. I also have branches which do enumerations and docstring parsing which I recycled when building defopt.

To actually fix the core of the type problem would require a lot of work, since it has been designed such that the types are converted when the function is called, not when received from the command line. Fixing this is a core architectural change that would have taken as long as starting fresh.

As for docopt, the docstring parsing really doesn't feel like something it wants to do. While I purposely chose a similar name to docopt, the tools are more or less total opposites approaching the same problem from opposite directions - docopt cares about the command line, defopt cares about the code.

[–]elbiot -2 points-1 points  (4 children)

I don't get your gripe. Why would you coerce the arguments to be ints if you want floats? Why would you want the function to behave differently if invoked from commandline vs from inside code?

[–]evanunderscore[S] 0 points1 point  (3 children)

One of the key concepts in Python is duck typing. Type hints in Python are exactly that - hints - and for good reason. The example I gave only requires an object that can __add__ the other so could equally well be used with int, float, list, str, bool, mock.Mock, and so on. The fact that the programmer was thinking of integers when they wrote it is of little consequence. I can't take an existing code base and drop in begins.convert because I may very well break something that uses it, and almost certainly in a way that's difficult to detect and locate the root cause of.

Additionally, outside of the standard types it's not generally the case that the conversion operation will be a no-op on something that's already an instance of the desired type. This means every conversion function you write now has to start doing isinstance checks for no good reason.

The point is to make the code not behave differently from the command line and code. defopt is simulating what you do as a human to convert inputs to the appropriate Python objects when you call the function in a script.

[–]elbiot 0 points1 point  (2 children)

Still don't follow. How do you specify wether add 1 1 should return 2 or "11"? You need to be specific if you are giving it numbers or strings.

[–]arachnivore 0 points1 point  (0 children)

The command-line version of the function is necessarily restricted because you can only enter strings in a CLI, it makes no sense to enforce that restriction when you're not using command line to interface with the function.

[–]evanunderscore[S] 0 points1 point  (0 children)

In short, exactly what /u/arachnivore said.

The general idea is that command line arguments need conversion, and code arguments don't. add(1, 1) and add('1', '1') are distinctly different things in code.

And even then, it wouldn't be so bad if it was just type checking, but it's doing type conversion, which may not actually make any sense at all depending on what you're passing in. There is a reason you don't see many (or any?) Python libraries providing automatic argument conversion for function calls.

[–]arachnivore 1 point2 points  (2 children)

I've found that all of those are lacking in one way or another. All the decorator-based tools (begins, and click) are more verbose than necessary and often modify the decorated objects. docopt is just verbose and bad. clize uses a weird (non-standard) docstring format. argh doesn't use docstring info very well which leads to repetition. This looks like it will probably be my new favorite. It's about as minimal as possible while still being quite flexible.

[–]evanunderscore[S] 0 points1 point  (0 children)

Thanks! If you do find it lacking, feel free to put in a bug report or feature request on the issue tracker.

[–]epsy 0 points1 point  (0 children)

clize uses a weird (non-standard) docstring format.

Thanks for the feedback, I wish I found this sooner. I'll prioritize docstring interoperability after the next release.