Argparse: is it possible to combine help texts from multiple parsers? - python-3.x

I'm writing a module with custom logging utilities to be imported in other scripts.
It's based on the standard-library logging module.
One of these utilities looks like this:
import argparse as ap
def parse_log_args() -> dict:
log_arg_parser = ap.ArgumentParser(description='Parses arguments that affect logging')
log_arg_parser.add_argument(
'--level',
dest='level',
help='Sets logging level',
choices=['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL']
)
log_args, _ = log_arg_parser.parse_known_args()
return vars(log_args)
This function looks for arguments that have to do with logging (even though only --level is defined for the time being) and parses those independently of (and before) all others so that the logging can be configured early on and used in the rest of the script.
The goal here is to remain flexible and be able to quickly plug-in support for these arguments, both in scripts that expect no other arguments and in those that do.
From the point of view of simply parsing arguments this works: this function runs first, parses --level and then the script-specific parser comes and handles the rest.
The problem, however, is the help text. When I run a script that calls this function with --help it only displays the help text from this first parser and not from the script-specific one. So something like this:
Parses arguments that affect logging
optional arguments:
-h, --help show this help message and exit
--level {DEBUG,INFO,WARNING,ERROR,CRITICAL}
Sets logging level
Is there a way to combine the help-texts from all the ArgumentParser instances in a script?
Alternatively: Is there a different way to achieve this in a flexible/plug-in kind of way, that is, without modifying existing ArgumentParsers or having to add them to scripts that don't yet use them?
PS: A similar question has been asked before here: Argparse combine --help directives but the proposed ideas don't really solve the problem:
Define the first parser with add_help=False: This would hide the option from the user which I would prefer not to do.
Use subcommands somehow: doesn't seem to be applicable here.

I think this might fit the bill:
import argparse
part1 = argparse.ArgumentParser(add_help=False)
#... some parsing takes place ...
part2 = argparse.ArgumentParser(add_help=True, parents=[part1])
part1 parser must be fully initialized for parents to work.
More on the topic:
https://docs.python.org/3/library/argparse.html#parents

Related

How to to pass a string to function arguments in python3

I'm building a command-line interface using the argparse library to parse user input. At one stage, I'd like to take user input such as "'test', x=False" and use it in a function such as func('test', x=False).
I've tried using ast.literal_eval to do this but it encounters a syntax error at the equals sign. (I did ast.literal_eval("("+args+")") where args was above example)
Does anyone know of a safe way to parse the user input like that? Preferably without eval although worst-case scenario I could use eval as, well, it's a CLI tool.
Edit (to people that have said to use input manually(): I need the tool to parse input from when the command is run (it's a python module that I want to be able to be called like python3 -m hmcli.raw --args "'test', x=False" where the args can be flexible as the function used can differ.

Using a commandline argument to call a class method

Aplogies if I have the terminology all wrong; I am still learning the basics of Python. I have been unable to google this issue, probably in large part because I don't know the terminology..
So. I have built a class within a .py script with LOTS of methods/functions. To keep this remotely simple, I want to call these from a commandline argument. I have no idea how to explain it, and I can't find anhy examples, so I will try to demo it:
Take for example mute_on as the function that I want to call. I run the script with the function/method in the argument, like:
python3 ./myscript.py mute_on
I assume we'd import sys(?), define the class and the function, and create the relevant object from the class:
import sys
class TelnetAVR(PioneerDevice):
def mute_on(self, mute):
self.telnet_command("MO")
mypioneer = PioneerDevice('Pioneer AVR', '192.168.2.89', 8102, 10)
...and lastly I would like the commandline argument to call the method/function - instead of calling it explicitly like:
mypioneer.mute_volume()
..I want to use the arg (sys.argv[1]) to dynamically call the function, like:
mypioneer.{sys.argv[1]}()
Any ideas, kind people? I have been auto-referred to What is getattr() exactly and how do I use it? but I have no idea how that information can help me here.
I have tried setting cmnd = 'turn_off' and then the following failed...;
getattr(mypioneer, str(cmnd))
getattr(mypioneer, cmnd)
Thanks!
This answer seems a little basic, but I cannot complain as to its efficacy;
mypioneer = PioneerDevice('Pioneer AVR', '192.168.2.89', 8102, 10)
exp = 'mypioneer.' + sys.argv[1] + '()'
print('Executing: ' + exp )
exec(exp)
I gave up loking for a graceful answer, and simply constructed a string that I wanted to execute (exp) based on the commandline argument. Works great.. Home Assistant can use the same script to call 50 telnet controls over my Pioneer AVR.

Add additional operations to existing method which is in Python module

I have a python module which has several methods:
module.py
def a():
return "This is a method"
I want to add some additional functionality to method a by calling it from script to avoid modification in module itself.
How can I add additional operations or arguments to that module calling it from script?
For example I imported module.py in my script and in that script I add two arguments to method "a" and addition of those arguments in addition to:
return "This is a method"
Well, you cannot really change any imported methods as far as I am aware. That does not mean it is completely impossible, I just wouldn't know how.
Question is though if that is actually what you want (as I believe it is a very uncommon way of handling code and I am guessing not an advisable one)?
Could it be that what you actually want to achieve is something more like this:
module_script.py
def a(variable):
return_value = "This is a " + str(variable) + " method!"
return return_value
second_script.py
import module_script
print(module_script.a("nice"))
The output of the second script would be:
"This is a nice method!"

python - how to let others to check info in triple quotes

I am writing detailed information for each function in a class, and hope when others use my python code, they could check the info for each function, by using something like help(function_name)
For example, I have created a python file called text_preprocess.py, in this file I have created a class which includes functions.
class Preprocess():
def str_process(self, row_string):
'''
This Standford CoreNLP package requires the text input as 1 single string.
The input annotators are in you command line input.
:param row_string: The string format input for Standford CoreNLP
:return: Json format output
'''
parsed_json = self.nlp.annotate(row_string, properties={
'annotators': self.standford_annotators,
'outputFormat': 'json'
})
return parsed_json
In this function, as you can see the info is within triple quotes.
But I don't know how could other users see this info without looking into my code.
I have checked many solutions online, people use help(function_name), but it seems that they wrote the code through terminal, and then type help(function_name), many of those examples do not have class either. Using --help through command line only gives them the parameter descriptions I added through argparse....
So, if I hope others could check the info of my function without looking into the code, where and how could they do that?
Either be in the same directory as your script, or make sure your script is in one of the directories listed in sys.path (usually, the first option is easier for simple things, but if you want to do the second, use a virtualenv rather than trying to install the module system-wide).
Run pydoc3 text_preprocess to get documentation for the whole module. This recursively includes all of the items below the module, such as classes, their members, and functions.
Run pydoc3 text_preprocess.Preprocess if you just want the class.
Run pydoc3 text_preprocess.Preprocess.str_process if you just want the method.
Use Sphinx if you want nicely-formatted HTML or other formats such as PDF.
You may also want to remove that empty line at the beginning of your docstring; some docstring-parsing code may misinterpret it.
Putting triple quoted strings just below the declaration of a class or method is called documentation. You can read this using Preprocess.str_process.__doc__.

Is there a module for getting user input from the command line in node.js?

First of all: I don't mean parsing arguments and options from the process.argv array, but prompting the user and handling input/output. I've looked through the Node.js official module list without finding any sections or subsections that mentions input. In fact a search for 'input' on that page only gets 1 result which has something to do with YAML.
Anyway, I suppose cli input should be asynchronous and I've solved this issue before using stdin.on('data') which was messy to say the least. This seems like a perfect task for a node module which could come with extra goodies such as progress bars, spinners, coloured output, input validation etc.
There probably are some modules out there that does this, but I can't find any of them.
Help!!
(To clarify, the only functionality I require is the simplification of handling user input)
Search for modules here: http://eirikb.github.com/nipster/
Prompt: https://github.com/jesusabdullah/node-prompt
Progress bar: https://github.com/substack/node-multimeter
Colors: https://github.com/Marak/colors.js
Input validation: https://github.com/chriso/node-validator
More input validation (webbish tho): https://github.com/caolan/forms
Also, if you want to write your own: http://nodejs.org/docs/latest/api/all.html#readline
#node.js IRC welcomes you: http://webchat.freenode.net/?channels=node.js

Resources