[HN Gopher] Docopt
       ___________________________________________________________________
        
       Docopt
        
       Author : tosh
       Score  : 58 points
       Date   : 2021-12-31 14:14 UTC (8 hours ago)
        
 (HTM) web link (docopt.org)
 (TXT) w3m dump (docopt.org)
        
       | kortex wrote:
       | I've tried just about every python cli parser out there:
       | argparse, click, Cleo, docopt, fire, hydra, typer, a few others.
       | Nothing has been a slam dunk for me the way Clap for rust or
       | cobra for go have been. But I've found a good enough system.
       | 
       | My criteria are: well supported, composable, sub commands,
       | reusable options, sane stack traces.
       | 
       | My current pattern: Cleo plus pydantic. I can create a module of
       | commonly used flags and options that I can share among commands.
       | Commands are first class objects. I can use them as entry points.
       | I can readily parse the options into a static structure with
       | defaults read from env or a file using pydantic. This is feed to
       | runner/API functions, with minimal logic in the command class
       | itself. The one thing that is lacking is I wish I could define
       | pydantic models that double as commands. That is a pretty
       | specific nit to pick.
       | 
       | Overall I love it. Poetry runs on it so I think it's got a long
       | support life. It's beautiful. Easy to use. Just the right amount
       | of opinionated for me. Supports auto complete. Built in commonly
       | used flags like version, quiet, and verbose levels.
       | 
       | I find click and any of the decorator based systems super obtuse
       | and difficult to compose. They add tons of noise to stack traces.
       | 
       | Docopt is way too string based. I like static types.
       | 
       | Argparse is... surprisingly not bad. The main drawback is reuse
       | is not very easy and it's hard to write composable structures.
        
       | epage wrote:
       | It seems like docopt was trendy for a while which always
       | surprised me. The idea of specifying your CLI in an incompletely
       | defined DSL embedded in a string always confused me both because
       | of the brittleness and because there is stuff you just can't
       | express (like types).
       | 
       | In Python, I was always skeptical of click which later took the
       | attention though I think using StructOpt [0] in Rust has cured me
       | of that to a degree though I much prefer field attributes over
       | stacking function attributes per parameter (or Typer's form of
       | parameter attributes). I'd probably still stick with argparse
       | anyways because most of my Python scripts are built without
       | dependencies (weird build systems or being one step above bash
       | scripts).
       | 
       | [0] https://docs.rs/structopt/latest/structopt/
        
         | smitty1e wrote:
         | Speaking of Click:
         | 
         | "Docopt, and many tools like it, are cool in how they work, but
         | very few of these tools deal with nesting of commands and
         | composability in a way like Click. To the best of the
         | developer's knowledge, Click is the first Python library that
         | aims to create a level of composability of applications that
         | goes beyond what the system itself supports.
         | 
         | Docopt, for instance, acts by parsing your help pages and then
         | parsing according to those rules. The side effect of this is
         | that docopt is quite rigid in how it handles the command line
         | interface. The upside of docopt is that it gives you strong
         | control over your help page; the downside is that due to this
         | it cannot rewrap your output for the current terminal width,
         | and it makes translations hard. On top of that, docopt is
         | restricted to basic parsing. It does not handle argument
         | dispatching and callback invocation or types. This means there
         | is a lot of code that needs to be written in addition to the
         | basic help page to handle the parsing results.
         | 
         | Most of all, however, it makes composability hard. While docopt
         | does support dispatching to subcommands, it, for instance, does
         | not directly support any kind of automatic subcommand
         | enumeration based on what's available or it does not enforce
         | subcommands to work in a consistent way."
         | 
         | https://click.palletsprojects.com/en/8.0.x/why/#why-not-doco...
        
           | cb321 wrote:
           | I think plac and argh in the Python space pre-dated Click by
           | a long time and had many similar features. I'm not sure if
           | they had everything the Click author exactly wanted, but they
           | do seem like strong prior related work.
        
           | michaelcampbell wrote:
           | > Most of all, however, it makes composability hard.
           | 
           | I see this argument a lot as if it's self evident. Using X
           | makes Y hard. Ok, what if you don't need Y?
        
             | dragonwriter wrote:
             | > Using X makes Y hard. Ok, what if you don't need Y?
             | 
             | Then knock yourself out using X. It's an argument about the
             | purpose of the alternative and what it is intended to be
             | useful for. Assuming that it is valid, it tells you both
             | for what purposes you might want to use the alternative and
             | for what purposes you might not want to bother.
             | 
             | Z improves on X for Y is fairly explicitly not an argument
             | that Z is superior to X for all purposes.
        
       | cb321 wrote:
       | If the PL you are using already has named parameters with
       | defaults then you can roll a CLI on top of it with a better
       | spcified "spec" language (the PL itself) and with less work.
       | There are a few Python packages for this and
       | https://github.com/c-blake/cligen (which lets you add a CLI to an
       | existing API with just one line of code).
       | 
       | This is theoretically even possible for C++ with some kind of
       | compile-time reflection API, but the way the C preprocessor works
       | probably makes it hard to preserve structured comments for
       | automatic documentation extraction. It was quite easy to do in
       | Nim.
        
       | ris wrote:
       | Please Just Say No.
       | 
       | Docopt is the sort of thing that seems like it would work
       | wonderfully but you'd be surprised how quickly you end up running
       | into a situation that is ambiguous or just impossible to
       | represent using docopt. On the other hand, I never really found
       | that argparse-specified interfaces were significantly more
       | verbose to set up.
        
         | michaelcampbell wrote:
         | I've used it, and it's... fine, I guess. I ended up using
         | something else but it was kind of nifty.
        
         | pythux wrote:
         | I used it a lot and it usually works great. Of course there are
         | corner cases but if you don't need to handle them in most cases
         | I don't think it means you should never use the library in the
         | first place.
        
       | shrimpx wrote:
       | I've used docopt a ton for core CLI tooling at my last company.
       | IMO its shortcomings outweigh the benefits by a long margin,
       | compared to tools like argparse which make it super hard to
       | understand what the full UI of a tool is. That said, my company
       | did start transitioning to Click because of its
       | nesting/subcommand abilities. I would probably choose Click for a
       | new project, but I do think docopt is still the best for speed of
       | understanding the total interface of a tool. You just read the
       | `__doc__` straight up.
        
       | junon wrote:
       | Used this before for a few languages and assuming you can
       | incorporate it into your build system it's actually quite
       | pleasant to use.
       | 
       | The problem is, shoe-horning it into your project can be a huge
       | burden. It's why I left it in my toolbox as more of a toy.
        
       | hprotagonist wrote:
       | These days i use typer (https://typer.tiangolo.com/), but docopt
       | remains a fan favorite of mine for being just so darn cute.
       | 
       | it's a shame that the last i checked, there wasn't really a
       | formal grammar for it and so doing a lot of the modern
       | conveniences i like[0] is either hard or impossible, but the
       | idea's still charming.
       | 
       | [0]: i want things like "ensure this is a path and it's a file
       | and it exists and it's nonzero size and give it back to me as a
       | `pathlib.Path` please" or "this argument must be an integer
       | between 10 and 5002", etc.
        
       | formerly_proven wrote:
       | rST somehow ended up with a (strict) parser for more or less
       | this:
       | https://docutils.sourceforge.io/docs/ref/rst/restructuredtex...
        
       | dbrgn wrote:
       | I like Docopt for quick scripts, used it both in Python and Rust
       | projects. It is quite unflexible though.
       | 
       | The Rust Docopt implementation1 was deprecated this year, which
       | is probably good because clap v32 is so awesome. In a project of
       | mine (tealdeer), I noticed that docopt.rs was responsible for the
       | _huge_ majority of CPU instructions when running the binary:
       | https://github.com/dbrgn/tealdeer/issues/106#issuecomment-59... I
       | then switched3 to clap and shaved off almost a megabyte from the
       | release binary4. Performance improved as well, time required for
       | rendering a tldr page went down from ~15.9 ms to ~12.4 ms5. With
       | the migration, we also managed to reduce a lot of custom
       | validation logic and move this logic into the derive macro
       | attributes.
       | 
       | 1 https://github.com/docopt/docopt.rs
       | 
       | 2 https://github.com/clap-rs/clap
       | 
       | 3 https://github.com/dbrgn/tealdeer/pull/108
       | 
       | 4 https://github.com/dbrgn/tealdeer/pull/108#issuecomment-9448...
       | 
       | 5 https://github.com/dbrgn/tealdeer/pull/108#issuecomment-9448...
        
         | guitarbill wrote:
         | I agree that clap v3 (with it's derive capabilities basically
         | incorporating structopt) is awesome. But it's still pretty
         | heavyweight, although you can make it a bit more lightweight by
         | turning off some features. In some cases, I actually put the
         | CLI args in a separate crate, so that changing the program
         | doesn't involve rebuilding the CLI arg structures. As a bonus,
         | it makes changes to the CLI much more obvious in code review.
        
           | epage wrote:
           | Now that we have clap 3.0 released, trimming the fat is going
           | to be a focus.
        
           | dbrgn wrote:
           | Hmm, putting them in a subcrate / separate compilation unit
           | is pretty smart. I can imagine that quite a chunk of the
           | compilation time goes into the proc macros :)
        
       ___________________________________________________________________
       (page generated 2021-12-31 23:01 UTC)