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.
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 thedefault
andchoices
fields when instantiating this class. Effectively,default
will behave as if it were set toFalse
, andchoices
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 thedefault
andchoices
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 toTrue
. - 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))
- This creates a flag named
--disable-auto-sync
(or-d
for short) with a default value ofFalse
.
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
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."),
)
$ 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
from botstrap import Botstrap, Option
Botstrap().parse_args(
pizza_topping=Option(
default="cheese", # (1)!
choices=("mushrooms", "olives", "pepperoni", "sausage"),
),
)
- If the specified
default
value is not included inchoices
, Botstrap will automatically prepend it to ensure consistent and predictable behavior.
$ 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
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)
$ 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
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.")
- Note:
args
is an instance ofOption.Results
. The following line createsargs_dict
, which is adict[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)))
):
$ 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.