Skip to main content

Extends the native Python3 `argparse.ArgumentParser` to supports using maps as a `choices` argument type.

Project description

Wintersdeep Argument Parser

This is a small extension to the native Python3 argparse.ArgumentParser. It adds some functionality I find I always end up requiring.

Installation

pip install wintersdeep.argparse

Log level support

Often you want the user to be able to configure log levels, thats a pain in itself. Then when you select debug and get overwhelmed you realise you only want it on one or more loggers, and not all of them. Often this is done by tweaking the code to acheive what you need in the moment. This helps fix that by making adjusting log levels at the command line simple - take a look:

from wintersdeep.argparse import ArgumentParser

argument_parser = ArgumentParser()
argument_parser.add_log_level_arguments() # there are options here, but the defaults will work fine.
arguments = argument_parser.parse_args()
if log_levels := arguments.log_level:
    log_levels.apply()

A user can now type -l[log-level] to set the global/default log level, or -l[logger]=[log-level] to set a specific log level, or any mix of the two.

python3 -m path.to.app -lwarning -lpath.to.app.problematic=debug -lpath.to.app.suspect=info

Mapping choices support.

It alters the behaviour of the choices argument on the add_argument method such that it supports the use of Mapping objects such as dict.

When using a Mapping object as a choices constraint the user will be able to choose only from the keys of the Mapping object specified. The arguments value in the resulting Namespace will be that which is associated with the key in the provided Mapping - e.g. if the user specified the key "abc" the value in the resulting namespace would be taken from choices_mapping["abc"].

As a simple example, the below code accepts any number of integer arguments and prints them to stdout using the CLI specified formatting. The formatter argument -f is constrained using choices which is provided as the formatters dict object. Users will only be able to choose one of its keys (bin, hex or oct) and the value in the resulting namespace is the assoicated lambda expression.

from wintersdeep.argparse import ArgumentParser

formatters = {
    "bin": lambda n: f"{n:b}",
    "oct": lambda n: f"{n:o}",
    "hex": lambda n: f"{n:x}"
}

argument_parser = ArgumentParser()
argument_parser.add_argument("N", nargs="+", type=int)
argument_parser.add_argument("-f", choices=formatters, default_key='hex')

arguments = argument_parser.parse_args()

for n in arguments.N:
    print( arguments.formatter(n) )

Features

  • Allows usage of Mapping type objects as a choices constraint on ArgumentParser::add_argument. Accepted input will be constrained to key values in the given map and the value in the resulting Namespace will be that keys associated value.
  • Added a default_key keyword argument; you can specify either default or default_key but not both. When using default_key the default value will be the value associated with the specified default_key in the choices map. default_key allows you to ensure documentation and behaviour remain syncronised and readable. default can still be used as normal if preferred and is required when the default option should not be user selectable.

Behaviour Notes

  • The action process wasn't applied to the default value (specified or derived from default_key).

    This is by intention and is consistent with the native ArgumentParser behaviour - the default value is provided "as-is" when the option is not specifed.

  • The Action returned by add_argument is not the type specified by add_arguments action parameter

    The libraries behaviours are implemented by shimming add_argument, and inserting a custom action when choices are a Mapping type.

    If you have set your own action then add_argument will preserve this and invoke it after the value has been translated, so you should still get the expected behaviour. However this does mean the Action class return by add_argument will not be of the type you originally specified. Your original action can be found in the [action].next_action property.

    For example, the below script extends the original sample to use an AddPrefix action to prefix a string to the user specified formatter. This works identically to the native behaviour, except the values argument will be the value from the choices mapping.

    from argparse import Action
    from wintersdeep.argparse import ArgumentParser
    
    # A custom action to add a prefix to all formatters.
    class AddPrefix(Action):
        def __call__(self, parser, namespace, values, option_string=None):
            # by the time this action receives `values` it has been converted into its Mapping associated value (in context a lambda function from `formatters`.
            prefix_fn = lambda x: f"Your number is {values(x)}"
            setattr(namespace, self.dest, prefix_fn)
    
    formatters = {
        "bin": lambda n: f"{n:b}",
        "oct": lambda n: f"{n:o}",
        "hex": lambda n: f"{n:x}"
    }
    
    argument_parser = ArgumentParser()
    argument_parser.add_argument("N", nargs="+", type=int)
    argument_parser.add_argument("-f", action=AddPrefix, choices=formatters, required=True)
    
    arguments = argument_parser.parse_args()
    
    for n in arguments.N:
        print( arguments.formatter(n) )
    
    print(action.__class__.__name__)    # "MappingChoicesAction"
    print(action.next_action.__class__) # <class '__main__.AddPrefix'>
    

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

wintersdeep_argparse-1.1.4.tar.gz (12.9 kB view details)

Uploaded Source

Built Distribution

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

wintersdeep.argparse-1.1.4-py3-none-any.whl (11.4 kB view details)

Uploaded Python 3

File details

Details for the file wintersdeep_argparse-1.1.4.tar.gz.

File metadata

  • Download URL: wintersdeep_argparse-1.1.4.tar.gz
  • Upload date:
  • Size: 12.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/5.1.0 CPython/3.11.6

File hashes

Hashes for wintersdeep_argparse-1.1.4.tar.gz
Algorithm Hash digest
SHA256 846cd88487032fa782b865b0d4092f25a2c43a3cf2aa5d7106d1c1ea23c1ed5b
MD5 22d901062a969548e02568aeb3a46ff1
BLAKE2b-256 3125a5fa26eb164f4c0846e2caa807179fce6209196790e8e93408b19ee201e0

See more details on using hashes here.

File details

Details for the file wintersdeep.argparse-1.1.4-py3-none-any.whl.

File metadata

File hashes

Hashes for wintersdeep.argparse-1.1.4-py3-none-any.whl
Algorithm Hash digest
SHA256 f6ef7d643e9d35dccb609eeffc5c18af303800b5f1c22aa9752fc41a3ee55e4e
MD5 316e1e9471f2c836debc5274744e3c53
BLAKE2b-256 b993320b251f26217df20ee2be318d885ee6de76ea95d3c8bbabf25009857683

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