Command lines¶
Automating parser creation¶
Write parsers for a command line is quite annoying and it is often just wrapping a function. Why not using the signature and the docstring to create it?
pyquickhelper.cli.create_cli_parser
(f, prog = None, layout = ‘sphinx’, skip_parameters = (‘fLOG’,), cleandoc = (‘epkg’, ‘link’), positional = None, cls = None, options)
Automatically creates a parser based on a function, its signature with annotation and its documentation (assuming this documentation is written using Sphinx syntax).
The function is parsing the doctring to extract the documentation for each parameter. It raises an exception whenever the documentation list does not correspond to the signature.
<<<
from pyquickhelper.cli import create_cli_parser
def fpars(anint: int, bstring="r", creal: float = None):
"""
Builds a unique string with the received information.
:param anint: one integer
:param bstring: one string
:param creal: one real
:return: concatenation
"""
return "'{0}' - '{1}' - '{2}'".format(anint, bstring, creal)
pars = create_cli_parser(fpars)
doc = pars.format_help()
print(doc)
>>>
usage: fpars [-h] [-a ANINT] [-b BSTRING] [-c CREAL]
Builds a unique string with the received information.
optional arguments:
-h, --help show this help message and exit
-a ANINT, --anint ANINT
one integer (default: None)
-b BSTRING, --bstring BSTRING
one string (default: r)
-c CREAL, --creal CREAL
one real (default: None)
The function does not handle all the types but the list of supported scenario will grow. This function is used by function:
pyquickhelper.cli.call_cli_function
(f, args = None, parser = None, fLOG = <built-in function print>, skip_parameters = (‘fLOG’,), cleandoc = (‘epkg’, ‘link’), prog = None, options)
Calls a function f given parsed arguments.
One command line is defined based on the previous function. The code of the command line is reduced.
def pyq_sync(fLOG=print, args=None):
"""
Synchronizer folder ecrypt using function @see fn synchronize_folder.
@param fLOG logging function
@param args to overwrite ``sys.args``
.. cmdref::
:title: synchronize two folders
:cmd: pyquickhelper.cli.pyq_sync_cli:pyq_sync
Synchronize two folders from the command line.
"""
try:
from pyquickhelper.filehelper.synchelper import synchronize_folder
from pyquickhelper.cli.cli_helper import call_cli_function
except ImportError:
folder = os.path.normpath(os.path.join(
os.path.abspath(os.path.dirname(__file__)), "..", ".."))
sys.path.append(folder)
from pyquickhelper.filehelper.synchelper import synchronize_folder
from pyquickhelper.cli.cli_helper import call_cli_function
call_cli_function(synchronize_folder, args=args, fLOG=fLOG,
skip_parameters=('fLOG', 'operations', 'log1'))
Automating __main__ creation¶
That’s the purpose of function
cli_main_helper
.
The purpose is to make it easier to implement a command line
such as python -m pyquickhelper <command> <args>
.
The function automates the parsing and the documentation.
It takes a simple dictionary whose values are the function
to call and the keys the command to run.
import sys
def main(args, fLOG=print):
'''
Implements ``python -m pyquickhelper <command> <args>``.
@param args command line arguments
@param fLOG logging function
'''
try:
from .pandashelper import df2rst
from .pycode import clean_files
from .cli import cli_main_helper
except ImportError:
from pyquickhelper.pandashelper import df2rst
from pyquickhelper.pycode import clean_files
from pyquickhelper.cli import cli_main_helper
fcts = dict(df2rst=df2rst, clean_files=clean_files)
cli_main_helper(fcts, args=args, fLOG=fLOG)
if __name__ == "__main__":
main(sys.argv[1:])
Documentation fo function
cli_main_helper
shows the output of python -m pyquickhelper clean_files --help
.