Skip to main content

💡 type-safe args for argparse without much refactoring.

Project description

typed_argparse

💡 type-safe args for argparse without much refactoring.

PyPI version Build Status codecov Code style: black mypy license




Motivation

Want to add type annotations to a code base that makes use of argparse without refactoring all you CLIs? typed_argparse allows to do that with minimal changes:

  1. Add a type MyArgs(TypedArgs) that inherits from TypedArgs and fill it with type annotations.
  2. Wrap the result of e.g. your parse_args function with MyArgs.
  3. That's it, enjoy IDE auto-completion and strong type safety 😀.

Features

  • Implicit runtime validation to ensure type annotations are correct
  • Very lightweight
  • No dependencies
  • Fully typed, no stubs required

Install

$ pip install typed-argparse

The only requirement is a modern Python (3.6+).

Usage

import argparse
import sys
from typing import List, Optional
from typed_argparse import TypedArgs


# Step 1: Add an argument type.
class MyArgs(TypedArgs):
    foo: str
    num: Optional[int]
    files: List[str]


def parse_args(args: List[str] = sys.argv[1:]) -> MyArgs:
    parser = argparse.ArgumentParser()
    parser.add_argument("--foo", type=str, required=True)
    parser.add_argument("--num", type=int)
    parser.add_argument("--files", type=str, nargs="*")
    # Step 2: Wrap the plain argparser result with your type.
    return MyArgs(parser.parse_args(args))


def main() -> None:
    args = parse_args(["--foo", "foo", "--num", "42", "--files", "a", "b", "c"])
    # Step 3: Done, enjoy IDE auto-completion and strong type safety
    assert args.foo == "foo"
    assert args.num == 42
    assert args.files == ["a", "b", "c"]


if __name__ == "__main__":
    main()

Notes:

  • typed_argparse validates that no attributes from the type definition are missing, and that no unexpected extra types are present in the argparse.Namespace object. It also validates the types at runtime. Therefore, if the MyArgs(args) doesn't throw a TypeError you can be sure that your type annotation is correct.
  • If you have usages that require access to the raw argparse.Namespace object, you can do so by using args.get_raw_args(). Note that internal argparse.Namespace object isn't synced with the args data itself, i.e., mutating either of them doesn't mutate the other.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

typed_argparse-0.1.6.tar.gz (10.0 kB view hashes)

Uploaded Source

Built Distribution

typed_argparse-0.1.6-py3-none-any.whl (9.8 kB view hashes)

Uploaded Python 3

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page