Skip to content

Option dataclass

A model for a custom option to add to the Botstrap-provided CLI.

This is a simple dataclass whose attributes (also referred to as fields) define the type and behavior of a command-line option, thus allowing for extensive customization of a bot's CLI.

To add a custom option, create an instance of this class and pass it into the parse_args() method of your Botstrap integration. You may add as many options as you want, as long as their names are unique. Their values will be returned as an instance of Option.Results.

Diagram - Defining an Option

Although it's possible to instantiate this class without specifying any custom field values, it's almost always ideal to tailor them to better fit your bot's requirements. However, some fields are mutually exclusive. ⚔

This diagram helps to illustrate which fields should (and shouldn't) be set when defining an option. Start at the top, and click on each field name that you encounter on the way down for more details about how to customize its value.

flowchart TB
    A("What is the value type of the option?")
    A -- bool --> B{{" flag   "}}
    A -- str --> C{{" default  "}}
    A -- int --> C
    A -- float --> C
    B --> F{{" help "}}
    C --> D("Is there a restricted set of values?")
    D -- Yes --> E{{" choices "}}
    D -- No --> F
    E --> F
    F --> G(("Done!"))

    click B "#botstrap.options.Option.flag"
    click C "#botstrap.options.Option.default"
    click E "#botstrap.options.Option.choices"
    click F "#botstrap.options.Option.help"

    class B,C,E,F field;
    classDef field font-family: Roboto Mono, font-size: 14px, font-weight: bold
    classDef field fill: #7c4dff66, stroke: #7c4dffff, stroke-width: 2px

    class A,D textBox;
    classDef textBox fill: #00b0ff11, stroke: #00b0ff33, stroke-width: 2px

    class G lastNode;
    classDef lastNode fill: #00c85366, stroke: #00c853cc
    classDef lastNode font-weight: bold, stroke-width: 2px

    linkStyle 1,2,3,6 opacity: 0.9, stroke-dasharray: 8 4
    linkStyle 0,7 opacity: 0.9, stroke-dasharray: 5 6
    linkStyle 4,5,8,9 opacity: 0.9, stroke-width: 2px

A model for a custom option to add to the Botstrap-provided CLI.

This is a simple dataclass whose attributes (also referred to as fields) define the type and behavior of a command-line option, thus allowing for extensive customization of a bot's CLI.

To add a custom option, create an instance of this class and pass it into the parse_args() method of your Botstrap integration. You may add as many options as you want, as long as their names are unique. Their values will be returned as an instance of Option.Results.

Attributes

flag: bool = False class-attribute

Whether this option represents a boolean flag (i.e. an on/off switch).

A flag is the most basic type of option. It doesn't require another command-line argument to tell it what its value should be - it'll simply be True if its name (or abbreviation) was specified on the command line, or False if not.

FAQ - How does this field affect the others?
  • If this field is set to True, you should ignore the default and choices fields when instantiating this class. Effectively, default will behave as if it were set to False, and choices will be unused because this option does not parse a separate command-line argument to determine its value.

  • If this field is set to False (or omitted, because that's the default setting), you should set the default and choices fields when instantiating this class - unless you intend to use their default values, of course.

  • This field has no effect on help, which should always be provided for a user-friendly experience! ✨

Note - The default value of a flag

It's important to avoid confusing the value of this field with the value of the resulting command-line option:

  • To create an option with a bool value type, this field should always be set to True.
  • The default value of the resulting command-line option will always be False.

Consequently, if you'd like to create a custom option corresponding to a bool value that normally defaults to True (such as auto_sync_commands), it must be semantically negated. For example:

from botstrap import Botstrap, Option

botstrap = Botstrap()
args = botstrap.parse_args(
    disable_auto_sync=Option(
        flag=True, # (1)!
        help="Disable automatic syncing of the bot's slash commands.",
    )
)
botstrap.run_bot(auto_sync_commands=(not args.disable_auto_sync))
  1. This creates a flag named --disable-auto-sync (or -d for short) with a default value of False.

default: str | int | float = '' class-attribute

The value that should be used if this option is not specified.

In addition to providing a standard value, this field determines the type of the parsed value for this option. If omitted, this option's type will be str and its default value will be the empty string.

Note that the value of this field must be a str, an int, or a float. To create an option with a bool value type, use the flag field instead.

Example - Creating options of different types
example.py
from botstrap import Botstrap, Option

Botstrap().parse_args(
    a=Option(help="An option with type 'str'."),
    b=Option(default=0, help="An option with type 'int'."),
    c=Option(default=0.0, help="An option with type 'float'."),
    d=Option(flag=True, help="A boolean flag."),
)
Console Session
$ python example.py -h
usage: example.py [-a <str>] [-b <int>] [-c <float>] [-d] [-t] [--help]

  Run "python example.py" with no parameters to start the bot.

options:
  -a <>         An option with type 'str'.
  -b <>         An option with type 'int'.
  -c <>         An option with type 'float'.
  -d            A boolean flag.
  -t, --tokens  View/manage your saved Discord bot tokens.
  -h, --help    Display this help message.

choices: Iterable[str | int | float] = () class-attribute

A group of values representing the acceptable choices for this option.

When command-line arguments are parsed and this option is specified, the given value will be checked against the values in this field. If the given value is not one of these "acceptable" values, an error message will be displayed.

If this field is omitted or otherwise empty, the given value for this option will not be checked. This means that any value with the same type as the default value will be considered acceptable.

Example - Defining valid values for an option
example.py
from botstrap import Botstrap, Option

Botstrap().parse_args(
    pizza_topping=Option(
        default="cheese", # (1)!
        choices=("mushrooms", "olives", "pepperoni", "sausage"),
    ),
)
  1. If the specified default value is not included in choices, Botstrap will automatically prepend it to ensure consistent and predictable behavior.
Console Session
$ python example.py -p pineapple
usage: example.py [-p <str>] [-t] [--help]
example.py: error: argument -p/--pizza-topping: invalid choice: 'pineapple'
(choose from 'cheese', 'mushrooms', 'olives', 'pepperoni', 'sausage')

help: str | None = None class-attribute

A string containing a brief description of this option.

This text will be displayed alongside the entry for this option when --help (or -h) is specified on the command line. If omitted, the entry for this option will appear without any help text. To prevent this option from being listed in the help menu, set this field to Option.HIDE_HELP.

Example - Configuring visibility in the help menu
example.py
from botstrap import Botstrap, Option

args = Botstrap().parse_args(
    x=Option(help="A user-friendly option with help text!"),
    y=Option(),
    z=Option(help=Option.HIDE_HELP),
)
print(args)
Console Session
$ python example.py -h
usage: example.py [-x <str>] [-y <str>] [-t] [--help]

  Run "python example.py" with no parameters to start the bot.

options:
  -x <>         A user-friendly option with help text!
  -y <>
  -t, --tokens  View/manage your saved Discord bot tokens.
  -h, --help    Display this help message.

$ python example.py -y "a mysterious option" -z "a super secret option"
Results(z='', y='a mysterious option', z='a super secret option')

Notice that -y appears without a description because it didn't specify a value for its help field, while -z does not appear in the help menu at all because it specified Option.HIDE_HELP. However, both options are equally usable.

Constants

HIDE_HELP: ClassVar[str] = argparse.SUPPRESS class-attribute

Hides an option's -h menu entry when used as the value for the help field.

Nested Classes

Results

A basic class to hold the final parsed values of custom command-line options.

This class (like its superclass, Namespace) is essentially just an object with a readable string representation. The names of its attributes will match the names you specify for your Option objects when passing them as keyword arguments to parse_args().

If you prefer to work with a dict representation of your parsed option values, simply pass your instance of this class to the built-in Python function vars().

Example - Viewing and using parsed option values
example.py
from botstrap import Botstrap, Option

args = Botstrap().parse_args(
    message=Option(),
    reply_chance=Option(default=0.01),
    ping_on_reply=Option(flag=True),
    daily_limit=Option(default=10, choices=range(-1, 101)),
)
print(f"args as 'Results':\n  {args}") # (1)!
print(f"args as a 'dict':\n  {(args_dict := vars(args))}\n")

if args.message and args.daily_limit and (chance := max(0, min(args.reply_chance, 1))):
    print("> Random replies are enabled.")
    print(f"  - {int(chance * 100)}% chance of replying with '{args.message}'.")
    print(f"  - Will{'' if args.ping_on_reply else ' not'} ping the original sender.")
    if args.daily_limit > 0:
        print(f"  - This will occur a maximum of {args.daily_limit} times per day.")
else:
    print("> Random replies are disabled.")
  1. Note: args is an instance of Option.Results. The following line creates args_dict, which is a dict[str, bool | str | int | float].

For reference, here's how the if condition on line 12 (highlighted above) can be equivalently written using a dict:

if (
    args_dict["message"]
    and args_dict["daily_limit"]
    and (chance := max(0, min(args_dict["reply_chance"], 1)))
):
Console Session
$ python example.py
args as 'Results':
  Results(message='', reply_chance=0.01, ping_on_reply=False, daily_limit=10)
args as a 'dict':
  {'message': '', 'reply_chance': 0.01, 'ping_on_reply': False, 'daily_limit': 10}

> Random replies are disabled.

$ python example.py -m "hi, friend!" -d -1 -p
args as 'Results':
  Results(message='hi, friend!', reply_chance=0.01, ping_on_reply=True, daily_limit=-1)
args as a 'dict':
  {'message': 'hi, friend!', 'reply_chance': 0.01, 'ping_on_reply': True, 'daily_limit': -1}

> Random replies are enabled.
  - 1% chance of replying with 'hi, friend!'.
  - Will ping the original sender.

$ python example.py -m "cool story" -r 0.03 -d 100
args as 'Results':
  Results(message='cool story', reply_chance=0.03, ping_on_reply=False, daily_limit=100)
args as a 'dict':
  {'message': 'cool story', 'reply_chance': 0.03, 'ping_on_reply': False, 'daily_limit': 100}

> Random replies are enabled.
  - 3% chance of replying with 'cool story'.
  - Will not ping the original sender.
  - This will occur a maximum of 100 times per day.