CliBuilder not reading past first argument - groovy

I am trying to write a groovy script which uses CliBuilder to read command line arguments.
Here's my code
def cli = new CliBuilder(usage:'groovy -s "server name" -r "file name"')
cli.s('Name of the server', required: true)
cli.r('Name of the file', required: true)
def args = ['-s', 'ServerEx', '-r', 'RakeEx']
def opt = cli.parse(args)
when I run this script, it gives me error Missing required option: r
even though I have provided the argument r.
I searched for the solution but I found reading multiple arguments for the same flags,
eg. -s arg1 arg2, but not reading multiple arguments for different flags.
Any help is really appreciated. Thank you.

Well, as it turns out, I have to specify the args:1 as a property when defining flags. I just found this from this article from Javaworld: http://www.javaworld.com/article/2073443/explicitly-specifying--args--property-with-groovy-clibuilder.html
Also, as an added bonus, now I can directly access the value provided by using opt.r. It used to show boolean true/false before adding args:1

Related

exec() not working when trying to execute a string containing the command "abs.__doc__"

I am trying to execute the command abs.__ doc__ inside the exec() function but for some reason it does not work.
function = input("Please enter the name of a function: ")
proper_string = str(function) + "." + "__doc__"
exec(proper_string)
Essentially, I am going through a series of exercises and one of them asks to provide a short description of the entered function using the __ doc__ attribute. I am trying with abs.__ doc__ but my command line comes empty. When I run python in the command line and type in abs.__ doc__ without anything else it works, but for some reason when I try to input it as a string into the exec() command I can't get any output. Any help would be greatly appreciated. (I have deliberately added spaces in this description concerning the attribute I am trying to use because I get bold type without any of the underscores showing.)
As a note, I do not think I have imported any libraries that could interfere, but these are the libraries that I have imported so far:
import sys
import datetime
from math import pi
My Python version is Python 3.10.4. My operating system is Windows 10.
abs.__doc__ is a string. You should use eval instead of exec to get the string.
Example:
function = input("Please enter the name of a function: ")
proper_string = str(function) + "." + "__doc__"
doc = eval(proper_string)
You can access it using globals():
def func():
"""Func"""
pass
mine = input("Please enter the name of a function: ")
print(globals()[mine].__doc__)
globals() return a dictionary that keeps track of all the module-level definitions. globals()[mine] is just trying to lookup for the name stored in mine; which is a function object if you assign mine to "func".
As for abs and int -- since these are builtins -- you can look it up directly using getattr(abs, "__doc__") or a more explicit: getattr(__builtins__, "abs").__doc__.
There are different ways to lookup for a python object corresponding to a given string; it's better not to use exec and eval unless really needed.

Python Subprocess The filename, directory name, or volume label syntax is incorrect

I am trying to download an audio dataset, I have all the audio's link stored in a csv. I read the csv and get all the links now I have to download the audio's one by one. Here's the code.
if not os.path.exists(audio_path_orig):
line = f"wget {episode_url}"
print('command:',line)
process = subprocess.Popen([(line)],shell=True)
process.wait()
for a sample, the line variable contains
wget https://stutterrockstar.files.wordpress.com/2012/08/male-episode-14-with-grant.mp3
Note that the url works and you can check for yourself, but when I try to download it using python it gives me the below error.
error: The filename, directory name, or volume label syntax is incorrect
Look at the documentation for Popen:
args should be a sequence of program arguments or else a single string or path-like object. By default, the program to execute is the first item in args if args is a sequence.
And:
Unless otherwise stated, it is recommended to pass args as a sequence.
Also:
The recommended approach to invoking subprocesses is to use the run() function for all use cases it can handle.
So use:
if not os.path.exists(audio_path_orig):
args = ["wget", f"{episode_url}"]
print('command:', " ".join(args))
result = subprocess.run(
args, capture_output=True, text=True
)
if result.returncode != 0:
print(f"wget returned error {result.returncode}")
print("Standard output:")
print(result.stdout)
print("Error output:")
print(result.stderr)

Python argparse with possibly empty string value

I would like to use argparse to pass some values throughout my main function. When calling the python file, I would always like to include the flag for the argument, while either including or excluding its string argument. This is because some external code, where the python file is being called, becomes a lot simpler if this would be possible.
When adding the arguments by calling parser.add_argument, I've tried setting the default value to default=None and also setting it to default=''. I can't make this work on my own it seems..
def main():
parser = argparse.ArgumentParser()
parser.add_argument('-p', '--projects_to_build', default='')
args = parser.parse_args()
This call works fine:
py .\python_file.py -p proj_1,proj_2,proj_3
This call does not:
py .\python_file.py -p
python_file.py: error: argument -p/--projects_to_build: expected one argument
You need to pass a nargs value of '?' with const=''
parser.add_argument('-p', '--projects_to_build', nargs='?', const='')
You should also consider adding required=True so you don't have to pass default='' as well.

Is it possible to inherit required options in argparse subparsers?

I am trying to write a command line application that has several modes in which it can run (similar to git having clone, pull, etc.). Each of my subcommands have their own options, but I also wanted them to share a set of required options, so I tried using a parent parser to implement this. However, it seems that inheriting a required option is causing the subparser to keep asking for it. Here is an example recreating the behavior:
import argparse
parent_parser = argparse.ArgumentParser(description="The parent parser")
parent_parser.add_argument("-p", type=int, required=True,
help="set the parent required parameter")
subparsers = parent_parser.add_subparsers(title="actions", required=True, dest='command')
parser_command1 = subparsers.add_parser("command1", parents=[parent_parser],
add_help=False,
description="The command1 parser",
help="Do command1")
parser_command1.add_argument("--option1", help="Run with option1")
parser_command2 = subparsers.add_parser("command2", parents=[parent_parser],
add_help=False,
description="The command2 parser",
help="Do command2")
args = parent_parser.parse_args()
So now if I run python test.py I get:
usage: test.py [-h] -p P {command1,command2} ...
test.py: error: the following arguments are required: -p, command
Ok, so far so good. Then if I try to specify just the -p option with python test.py -p 3 I get:
usage: test.py [-h] -p P {command1,command2} ...
test.py: error: the following arguments are required: command
But then if I run python test.py -p 3 command1
I get:
usage: test.py command1 [-h] -p P [--option1 OPTION1] {command1,command2} ...
test.py command1: error: the following arguments are required: -p, command
If I add another -p 3 it still asks to specify command again, and then if I add that again it asks for another -p 3 etc.
If I don't make the -p option required the problem is fixed, but is there a way to share required options among multiple subparsers without just copy pasting them within each subparser? Or am I going about this entirely the wrong way?
Separate the main parser and parent parser functionality:
import argparse
parent_parser = argparse.ArgumentParser(description="The parent parser", add_help=False)
parent_parser.add_argument("-p", type=int, required=True,
help="set the parent required parameter")
main_parser = argparse.ArgumentParser()
subparsers = main_parser.add_subparsers(title="actions", required=True, dest='command')
parser_command1 = subparsers.add_parser("command1", parents=[parent_parser],
description="The command1 parser",
help="Do command1")
parser_command1.add_argument("--option1", help="Run with option1")
parser_command2 = subparsers.add_parser("command2", parents=[parent_parser],
description="The command2 parser",
help="Do command2")
args = main_parser.parse_args()
The main parser and subparser both write to the same args namespace. If both define a 'p' argument, the subparser's value (or default) will overwrite any value set by the main. So it's possible to use the same 'dest' in both, but it is generally not a good idea. And each parser has to meet its own 'required' specifications. There's no 'sharing'.
The parents mechanism copies arguments from the parent to the child. So it saves typing or copy-n-paste, but little else. It's most useful when the parent is defined elsewhere and imported. Actually it copies by reference, which sometimes raises problems. In general it isn't a good idea to run both the parent and child. Use a 'dummy' parent.

How to pass parameter while executing command in Groovy Script

command = ["C:/Users/Desktop/try.bat"]
def command1=command
def cmd = command1.execute()
cmd.waitFor()
This is my code. But I need to pass 4 arguments to try.bat. Out of these one argument is optional. How to handle it?
add more items in the array
["command", "param1", "param2"].execute()
as stated in the official docs http://groovy.codehaus.org/Executing+External+Processes+From+Groovy
Maybe you should try
def command = """C:/Users/Desktop/try.bat arg1 arg2 arg3 arg4"""
as the official docs provided suggest http://groovy.codehaus.org/Executing+External+Processes+From+Groovy

Resources