Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Type conversions #58

Closed
flying-sheep opened this issue Oct 4, 2012 · 3 comments
Closed

Type conversions #58

flying-sheep opened this issue Oct 4, 2012 · 3 comments

Comments

@flying-sheep
Copy link

I thought about what docopt does right and where that approach has its drawbacks.

I came to the conclusion that it’s a little too fast for its own good when it comes to the speed at which you get something (the dictionary) out of it: docopt is designed to be used in 1 function call on 1 docstring you wrote, but since that one also needs to be human readable, it has its shortcomings.


My problem is type conversions: Though roundabout, after using argparse you have an object containing ints, files, and everything you can instantiate by feeding it strings.

Compare argparse’s options.x with docopt’s int(options["<x>"]). docopt is beautiful and easy until you have the dict, but ugly afterwards.

The other problem is “break early and often”: if you convert stuff whenever it is needed, it is there where your program will break if fed invalid options. If you decide to do this as early as possible (e.g. by converting your dictionary into a set of variables), you have to do if-else branches again and handle missing arguments (e.g. if an optional path to a file is not given, you have to do f = file(options['--path']) if options['--path'] else None)


so what do i want?

  • a way to easily typeconvert and validate while directly after docopting.

what is “easy”?

  • not doing it manually, but letting docopt do it. either by another function, or by another keyword argument. This should of course handle lists by just mapping the conversion onto them.

    (e.g. docopt(__doc__, conversions={'<x>': int, '<y>': int})

  • letting docopt handle missing optional arguments: if something isn’t given, it will yield None in the dict, which docopt shouldn’t typeconvert, as mist constructors do silly stuff or break when given None. (for lists, that’s easy. map(int, []) ist still [])

@keleshev
Copy link
Member

keleshev commented Oct 5, 2012

int(options["<x>"]) is what I have in some of my throw-away scripts, and I'm not totally happy with this.

However there is little overhead in using schema. Compare:

  • your API:
args = docopt(__doc__, conversions={'<x>': int, '<y>': int})
  • docopt with schema:
Int = Or(None, Use(int))
args = Schema({'<x>': Int, '<y>': Int}).validate(docopt(__doc__))

And the more complex your CLI is—the smaller is the relative overhead.

Also, I have never seen a program that takes arbitrary integers—except for calculators—it is always a range or a set, which you can express easily with schema:

schema = Schema({'<x>': And(Use(int), lambda n: n in [2**n for n in range(10)]))

@flying-sheep
Copy link
Author

As said on Reddit: I'm almost convinced, yet I still think it's not DRY that way: you have to tell schema which arguments are optional, while docopt already knows about that.

@keleshev
Copy link
Member

keleshev commented Oct 8, 2012

As I said somewhere before—I prefer to err on the side of simplicity. Anyway, thanks for suggestion—more of that is always welcome.

@keleshev keleshev closed this as completed Oct 8, 2012
mitkof6 pushed a commit to mitkof6/docopt that referenced this issue Oct 3, 2020
Fix install directory of CMake package in multiarch environments.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants