Tool Shaping¶
Metadata¶
Metadata can be defined using dunders (double underscore variables) at the very beginning of the script/tool and is used by Tinyscript to format the help message.
from tinyscript import *
__author__ = "John Doe"
__contributors__ = [
{'author': "James McAdams", 'email': "j.mcadams@hotmail.com"},
{'author': "h4x0r1234", 'reason': "for his kind testing"},
]
__credits__ = "Thanks to Bob for his contribution"
__copyright__ = ("John Doe Inc.", 2020, 2023)
__description__ = "My Script"
__email__ = "john.doe@example.com"
__license__ = "agpl-3.0"
__version__ = "1.0"
__reference__ = "..."
__source__ = "..."
__training__ = "..."
__examples__ = ["..."]
__doc__ = "This tool ..."
initialize()
This gives the following help message:
$ python tool.py -h
My Script v1.0
Author : John Doe (john.doe@example.com)
Contributors: James McAdams (j.mcadams@hotmail.com)
h4x0r1234 - for his kind testing
Credits : Thanks to Bob for his contribution
Copyright : © 2020-2023 John Doe Inc.
License : GNU Affero General Public License v3.0
Reference : ...
Source : ...
Training : ...
usage: tool [-h] [-v]
This tool ...
extra arguments:
-h show usage message and exit
--help show this help message and exit
-v, --verbose verbose mode (default: False)
Usage examples:
python tool.py ...
For more detailed information about metadata fields, see this section.
Package requirements checking¶
(only for Python3.8+)
Required module can be added via the __requires__
dunder in order to check for requirements before the tool starts.
...
__requires__ = {'tinyscript': "1.23"}
...
initialize(...)
...
Help message styling¶
Help can be formatted using multiple markup languages for making the help text more user-friendly with colors and styling. This is configured by using the __docformat__
dunder (which can also be None
, meaning no formatting). This feature is supported by mdv
and the theme can be tuned by using the constant DOCFORMAT_THEME
.
Currently, the following markup languages are supported: HTML, Markdown, RestructuredText and Textile.
...
__docformat__ = "html" # None|"md"|"rst"|"textile"
...
DOCFORMAT_THEME = "Star"
...
Various formats support
The support for HTML, RestructuredText and Textile is based on document conversion with 'pypandoc' to get Markdown before using mdv
. In some cases with complex format text, Pandoc can cause issues with indentation or break the layout. It is then advised to only use Markdown directly to avoid any conversion.
List of themes
Unfortunately, the documentation of mdv
is a bit poor. However, one can find the names of the available themes in this JSON.
Script banner¶
Displaying a banner can be achieved in two ways:
- by passing a keyword argument
add_banner=True
; in this case, a random font is used
...
initialize(...
add_banner=True,
...)
...
- by defining the
BANNER_FONT
constant
The BANNER_STYLE
constant also allows to style the banner with the following properties:
adjust
: can beleft
|center
|right
; by default, the banner is centeredbgcolor
: determines the background colorfgcolor
: determines the foreground color
...
BANNER_FONT = "roman"
BANNER_STYLE = {'adjust': "right", 'fgcolor': "blue"}
...
Multi-level debugging¶
This is achieved by passing a keyword argument multi_level_debug=[boolean]
to initialize(...)
.
...
initialize(...
multi_level_debug=True,
...)
...
This modifies the classical -v
/--verbose
option to -v
/-vv
/-vvv
.
Debug levels
- '':
logging.ERROR
-v
:logging.WARNING
-vv
:logging.INFO
-vvv
:logging.DEBUG
Extended logging options¶
This is achieved by passing a keyword argument ext_logging=[boolean]
to initialize(...)
.
...
initialize(...
ext_logging=True,
...)
...
This adds multiple options:
-f
,--logfile
: This sets the log filename for saving logging messages.-r
,--relative
: This sets the log timestamps to the time relative to the start of the execution.-s
,--syslog
: This allows to save the log messages to/var/log/syslog
(Linux only).
Multi-level help¶
This is achieved by setting the __details__
metadata at the beginning of the script.
...
__details__ = [
"""Extra documentation, displayed when using -hh. """,
"""Other extra documentation, displayed when using -hhh. """
]
...
initialize(...)
...
This modifies the classical -h
/--help
option to -h
/-hh
/-hhh
.
Help levels
-h
: classical help message-hh
: classical help message + first string in details list-hhh
: classical help message + first and second strings in details list
Note: Strings beyond the two first elements of __details__
are not handled by purpose.
Short/Long help¶
This is enabled by the short_long_help
parameter of initialize(...)
and is set to True
by default.
...
initialize(...
short_long_help=False,
...)
...
When set to True
, -h
only displays usage information and --help
shows the full help message. If False
, -h
and --help
both displays the full help message.
Argument groups ordering¶
Groups can be ordered by using the after
and before
keyword-arguments in add_argument_group
.
...
parser.add_argument_group("custom arguments", before="extra arguments")
...
Subparser choices sorted per category¶
When defining subparsers under the main parser, it is possible to use the "category
" keyword to set a category to get the subparser sorted in. This allows, when there are lots of choices, to sort them and enhance readability of the help message.
...
cmds = parser.add_subparsers(dest="command", metavar="CMD", title="positional argument", description="command to be executed")
cmd1 = cmds.add_parser("command1", category="category1", help="this does something")
cmd2 = cmds.add_parser("command2", category="category2", help="this does something")
initialize()
...
This examples will yield a help message that proposes "CMD
", the command to be executed, with category1 holding command1 and category2 holding command2.
Automatic Bash auto-completion with argcomplete
¶
Using the related option, auto-completion can be enabled using argcomplete
. This only applies argcomplete.autocomplete
to the parser once initialized with the initialize(...)
function, meaning that setting up the script and the Bash console accordingly is required as documented on the README of `argcomplete´.
In Bash:
$ activate-global-python-argcomplete --user
Your script, let us say test.py
:
#!/usr/bin/python3
# PYTHON_ARGCOMPLETE_OK
...
parser.add_argument("test", choices=["a", "b", "c"])
initialize(autocomplete=True)
...
PATH
test.py
needs to be in a folder registered in the PATH
environment variable.
In Bash:
$ eval "$(register-python-argcomplete test.py)"