Skip to main content

typed command line argument parser

Project description

typed-cap

pypi style

Cap is a python Command-line Argument Parser that provides typing support. Using Cap requires less code to generate a more robust parser.

As you know python is a weakly typed programming language, and even if there is a typing module, its functionality is very weak compared to other languages like Typescript or Rust. We know it's ridiculous and pointless to compare python to any of these languages at the typing level, but properly handling these types in your code can really improve readability and reduce typing errors. And that gave us the motivation to write this package.

Usage

⚠️ typed_cap required python>=3.8

pip install typed_cap

Quick Example

# python>=3.9 only
from typed_cap import Cap, helpers, annotation_extra as anno
from typing import Annotated, List, Optional, TypedDict


class T(TypedDict):
    verbose: Annotated[bool, anno("v", "verbose output")]
    message: Annotated[List[str], anno("m", about="your messages")]
    size: Annotated[Optional[float], anno(alias="n", about="optional number")]


cap = Cap(T)
from typed_cap import Cap, helpers
from typing import List, Optional, TypedDict


class T(TypedDict):
    verbose: bool
    message: List[str]
    size: Optional[float]


cap = Cap(T)
cap.default(
    {
        "verbose": False,
    }
)
cap.helper(
    {
        "verbose": {
            "alias": "v",
            "about": "verbose output",
        },
        "message": {"alias": "m", "about": "your messages"},
        "size": {
            "alias": "n",
            "about": "optional number",
        },
    }
)
helpers["arg_help"](cap, "help", None)
helpers["arg_version"](cap, "version", "V")
args = cap.parse()

print(args.args)
print(args.val)
python demo.py
# DEMO: option 'message':list[str] is required but it is missing

python demo.py -vv -m="msg1" --message "msg2" -m "msg3" -n=0.1 -n=10 ~/.config
# ['/home/local/.config']
# {'verbose': True, 'message': ['msg1', 'msg2', 'msg3'], 'size': 10.0}

Features

Flags

flags are bool fields defined in input type

class T(TypedDict):
    silent: bool
    yes: Optional[bool]
...
args = cap.parse()
yes = args.val['yes']
  • alias for flags and options adds short-version for convenient
    cap.helper(
        { "ipv4": "4" }
    )
    
    -4 equals to --ipv4
  • supports combining alias -zxvf equals to -z -x -v -f
  • supports multiple occurrences -v -v or -vv how to get occurrences of the argument
    class T(TypedDict):
        ...
        verbose: bool
    ...
    args.count('verbose') # -> int
    

Option Argument

named options which are take values

class T(TypedDict):
    integer: int
    floating: float
    strings: List[str]
  • supports adding alias
    cap.helper(
        {
            {"integer": {"alias": "i"}},
            {"floating": {"alias": "f"}},
            {"strings": {"alias": "s"}},
        }
    )
    
    -i 1 -i=1 --integer 1 --integer=1
  • supports multiple values -m="msg1" --message "msg2" -m "msg3" will get
    { 'message': ['msg1', 'msg2', 'msg3'] }
    

Typing

Cap accepts an arbitrary TypedDict instance T to get the values that satisfy the predefined parameters and their types via the built-in validator. After parser execution you will get a dict that strictly satisfies type T. The nice thing about this is that you can leverage features such as auto-completion and type checking from modern editors.

The preset validator currently supports:

  • bool
  • int
  • float
  • str
  • NoneType
  • Union including Optional (e.g. Optional[int] equals Union[int, None])
  • queue list and tuple
  • Literal

Check the supported types in the preset validator from here.

Custom validator

TODO: build your validator with ValidVal

from typed_cap.typing import ValidVal
...

Helpers

Cap proviedes some useful argument helpers

  • help generate help documents that automatically adapt to the terminal width usage:

    helpers["arg_help"](
        cap: Cap,
        name: str,
        alias: Optional[VALID_ALIAS_CANDIDATES],
    ) -> None
    

    example:

    from typed_cap import Cap, helpers
    ... # code from quick example
    cap.about("some descriptions") # optional
    helpers["arg_help"](cap, "help", None)
    args = cap.parse()
    
    python demo.py --help
    # some descriptions
    #
    # OPTIONS:
    #     -v,--verbose    verbose output
    #     -m,--message    your messages
    #     -n,--size       optional number
    #        --help       display the help text
    
  • version usage:

    helpers["arg_help"](
        cap: Cap,
        name: str,
        alias: Optional[VALID_ALIAS_CANDIDATES],
    ) -> None
    

    example:

    from typed_cap import Cap, helpers
    ... # code from quick example
    cap.name("your-demo") # optional
    cap.version("0.1.0")
    helpers["arg_version"](cap, "version", "V")
    args = cap.parse()
    
    python demo.py -V # or
    python demo.py --version
    # your-demo 0.1.0
    

Others

using Cap.raw_exception to expose exceptions

Examples

Basic Example

from typed_cap import Cap
from typing import Optional, TypedDict


class T(TypedDict):
    all: Optional[bool]
    total: Optional[bool]
    max_depth: Optional[int]
    human_readable: Optional[bool]


cap = Cap(T)
args = cap.parse()

print(args.args)
print(args.val)
python demo.py --all --total /opt
# ['/opt']
# {'all': True, 'total': True, 'max_depth': None, 'human_readable': None}

Advance Example

from typed_cap import Cap, helpers
from typing import Optional, TypedDict


class T(TypedDict):
    all: bool
    total: bool
    max_depth: int
    human_readable: Optional[bool]


cap = Cap(T)
cap.default(
    {
        "all": False,
        "total": False,
        "max_depth": -1,
    }
)
cap.helper(
    {
        "all": {
            "alias": "a",
            "about": "write counts for all files, not just directories",
        },
        "total": {"alias": "c", "about": "produce a grand total"},
        "max_depth": {
            "alias": "d",
            "about": "print the total for a directory (or file, with --all) only if it is N or fewer levels below the command line argument;",
        },
        "human_readable": {
            "alias": "h",
            "about": "print sizes in human readable format (e.g., 1K 234M 2G)",
        },
    }
)
helpers["arg_help"](cap, 'help')
args = cap.parse()

print(args.args)
print(args.val)
python demo.py -ah --max-depth=1 /tmp
# ['/tmp']
# {'all': True, 'human_readable': True, 'max_depth': 1, 'total': False}

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_cap-0.2.3.tar.gz (527.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

typed_cap-0.2.3-py3-none-any.whl (24.6 kB view details)

Uploaded Python 3

File details

Details for the file typed_cap-0.2.3.tar.gz.

File metadata

  • Download URL: typed_cap-0.2.3.tar.gz
  • Upload date:
  • Size: 527.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.4.2 importlib_metadata/4.8.1 pkginfo/1.7.1 requests/2.26.0 requests-toolbelt/0.9.1 tqdm/4.62.3 CPython/3.9.7

File hashes

Hashes for typed_cap-0.2.3.tar.gz
Algorithm Hash digest
SHA256 9c622fcd42f5ec461e2f00ef8d7041dd1921f7ea7cdb657ac30fd414bfc5bb8f
MD5 b4fd5796e55d111fe30daba081588998
BLAKE2b-256 fd3098b3b3b81ad20a9f609b4fd715f49ab4ca7d81597343282792dbe551c18a

See more details on using hashes here.

File details

Details for the file typed_cap-0.2.3-py3-none-any.whl.

File metadata

  • Download URL: typed_cap-0.2.3-py3-none-any.whl
  • Upload date:
  • Size: 24.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.4.2 importlib_metadata/4.8.1 pkginfo/1.7.1 requests/2.26.0 requests-toolbelt/0.9.1 tqdm/4.62.3 CPython/3.9.7

File hashes

Hashes for typed_cap-0.2.3-py3-none-any.whl
Algorithm Hash digest
SHA256 af68c659e9ef5a271a9f63a78faa68cc20449eb916c67496dbcd2d3b36d42f90
MD5 c5894392fabe24ed849e49868a981054
BLAKE2b-256 bc41a3f29eb68cd61bb64bc011905beddd1d187e53089985ff528b29bf194d59

See more details on using hashes here.

Supported by

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