typed-argument-parser
typed-argument-parser copied to clipboard
Design Proposal: Separate parser from argument data
Currently, parser class and the namespace object are the same type and object.
from tap import Tap
class SimpleArgumentParser(Tap):
name: str
language: str = 'Python'
args: SimpleArgumentParser = SimpleArgumentParser().parse_args()
There're disadvantages doing this:
- Types are less intuitive.
SimpleArgumentParser().name
will pass mypy
checks, but will definitely throw error since argument is not there yet.
Meanwhile, in args = SimpleArgumentParser().parse_args()
, args
will still have irrelevant types information about the parser.
- When trying to nest the subparser inside the main parser (#69), it make less sense for an unused subparser to be an accessible data. It will be harder to manipulate when methods mixed with data in the future.
Instead, we can have something like:
import tap
@dataclass
class SimpleArgument:
name: str
language: str = 'Python'
args = tap.parse_args(SimpleArgument)
This is an improvement because:
-
SimpleArgument
is just a built-indataclass
which can be instantiated normally, getting free hash and equal, free structural pattern matching, and can be tested like normal data. - Cleaner types interface.
- Nested data types are natural.
An example of subparser:
import tap
from tap import Parser
@dataclass
class Foo:
foo: str
@dataclass
class Bar:
bar: str
@dataclass
class SimpleArgument:
name: str
language: str = 'Python'
command: Parser[Foo | Bar]
args = tap.parse_args(SimpleArgument)
Hi @kavinvin,
Since making Tap, we've been hoping to find a way to separate the Namespace
and ArgumentParser
without making typing extremely unpleasant. We couldn't figure out a way to do it. This seems like a totally sensible proposal. We have to think more about this one, but we'll add it to our options in the design doc and update you with our thoughts.
Thanks again, Kyle and Jesse