Python magical main() signature like Perl 6 - python

Does python have any way to easily and quickly make CLI utilities without lots of argument parsing boilerplate?
In Perl 6, the signature for the MAIN sub automagically parses command line arguments.
Is there any way to do something similar in Python without lots of boilerplate? If there is not, what would be the best way to do it? I'm thinking a function decorator that will perform some introspection and do the right thing. If there's nothing already like it, I'm thinking something like what I have below. Is this a good idea?
#MagicMain
def main(one, two=None, *args, **kwargs):
print one # Either --one or first non-dash argument
print two # Optional --arg with default value (None)
print args # Any other non-dash arguments
print kwargs # Any other --arguments
if __name__ == '__main__':
main(sys.argv)

The Baker library contains some convenient decorators to "automagically" create arg parsers from method signatures.
For example:
#baker.command
def test(start, end=None, sortby="time"):
print "start=", start, "end=", end, "sort=", sortby
$ script.py --sortby name 1
start= 1 end= sortby= name

I'm not really sure what you consider to be parsing boilerplate. The 'current' approach is to use the argparse system for python. The older system is getopt.

Simon Willison's optfunc module tries to provide the functionality you're looking for.

The opterator module handles this.
https://github.com/buchuki/opterator

Python has the getopts module for doing this.

Recently I came across the begins project for decorating and simplifying command line handling.
It seems to offer a lot of the same functions you are looking for.

Related

Python having issues to implement eval + high order functions/ decorator

I hope someone will be able to help me with my issue:
Working with schedule module, according documentation job needs to be called like this:
schedule.every(10).minutes.do(job)
I need to create a wrapper function to pass instead (10).minutes.do dynamic values according documentation from this module( (10).minutes.do or ().hour.do e t.c.) from args.
And intead job needs to call my function with parameters copy_from_to(absolute_path_to_the_file: str, destination: str) .
I'd like to get and run something like that using eval and high order function or a decorator:
def schedule_task(*given_time: str,function):
eval(('schedule.every')+''.join(map(str, given_time)+function()))
to get something like this:
eval(('schedule.every')+''.join(map(str, given_time)+function()))
When i'm trying to run
schedule_task('(10).minutes.do',copy_from_to('C:\Projects\python\comcast\paramiko\\1.txt','/c/'))
but i'm geiitng error: schedule_task() missing 1 required keyword-only argument: 'function'
What I'm doing wrong? How should I implement that?
Thank you so much for any help.
Thank you for all your comments, i'll try to clarify my intensions: i wanna create function for copying file using ssh when i could dynamically pass which file i wanna copy and where and also how often i wanna do that func(file_patn, destination, how often). I still couldn't implement that. Maybe there is easier way to do that? Thank you – Vladimir 14 hours ago
This is my function
def schedule_task(*given_time: str, function): eval_func = (('schedule.every') + ''.join(map(str, given_time))+'('+f'{function()}'+')') print(eval_func)
when i'm trying to run
schedule_task('(10).minutes.do', function=lambda: copy_from_to( 'C:\Projects\python\comcast\paramiko\1.txt', '/c/')) and print it, i'm getting schedule.every(10).minutes.do(None)
but instead none should be a lambda function above, why it doesn't happen?

Is there an eval in ruby

Does ruby have something like pythons eval? I'm searching google and I don't know if it's how i'm searching but I can't find anything on it or how to use it if there is one
In python I would something like this
def doEval(object):
return repr(eval(object))
The code above you would do in python's idle or something and run doEval('print("hello")') it would print "hello" then return "None" to say it was executed, in ruby I don't mind if it doesn't do nil, but I would like it to eval
Anything like this in ruby? thanks.
Googling "ruby eval" quickly reveals that the answer is yes.
eval(string [, binding [, filename [,lineno]]]) → obj
Evaluates the Ruby expression(s) in string. If binding is given, which
must be a Binding object, the evaluation is performed in its context.
If the optional filename and lineno parameters are present, they will
be used when reporting syntax errors.
Try this:
command = "puts 1"
eval(command)
http://www.ruby-doc.org/core-2.0.0/Kernel.html#method-i-eval

Python dir command to determine the methods

I am using Python's dir() function to determine what attributes and methods a class has.
For example to determine the methods in wx.Frame, I use dir(wx.Frame)
Is there any command to determine the list of arguments for each method? For example, if I want to know what arguments belong to wx.Frame.CreateToolBar().
As mentioned in the comments, you can use help(fun) to enter the help editor with the function's signature and docstring. You can also simply use print fun.__doc__ and for most mature libraries you should get reasonable documentation about the parameters and the function signature.
If you're talking about interactive help, consider using IPython which has some useful extras. For instance you could type %psource fun to get a printout of the source code for the function fun, and with tab completion you could just type wx.Frame. and then hit TAB to see a list of all of the methods and attributes available within wx.Frame.
Even though GP89 seems to have already answered this question, I thought I'd jump in with a little more detail.
First, GP89's suggestion was the use Python's built-in help() method. This is a method you can use in the interactive console. For methods, it will print the method's declaration line along with the class' docstring, if it is defined. You can also access this with <object>.__doc__ For example:
>>> def testHelp(arg1, arg2=0):
... """This is the docstring that will print when you
... call help(testHelp). testHelp.__doc__ will also
... return this string. Here is where you should
... describe your method and all its arguments."""
...
>>> help(testHelp)
Help on function testHelp in module __main__:
testHelp(arg1, arg2=0)
This is the docstring that will print when you
call help(testHelp). testHelp.__doc__ will also
return this string. Here is where you should
describe your method and all its arguments.
>>>
However, another extremely important tool for understanding methods, classes and functions is the toolkit's API. For built-in Python functions, you should check the Python Doc Library. That's where I found the documentation for the help() function. You're using wxPython, whose API can be found here, so a quick search for "wx.Frame api" and you can find this page describing all of wx.Frame's methods and variables. Unfortunately, CreatteToolBar() isn't particularly well documented but you can still see it's arguments:
CreateToolBar(self, style, winid, name)
Happy coding!

Parsing arbitrary number of arguments in Python OptParser

How can I define an option with an arbitrary number of arguments in Python's OptParser?
I'd like something like:
python my_program.py --my-option X,Y # one argument passed, "X,Y"
python my_prgoram.py --my-option X,Y Z,W # two arguments passed, "X,Y" and "Z,W"
the nargs= option of OptParser limits me to a defined number. How can I do something like this?
parser.add_option("--my-options", dest="my_options", action="append", nargs="*")
which will simply take whatever's after --my-option and put it into a list? E.g. for case 1, it should be ["X,Y"], for case 2 it should be ["X,Y", "Z,W"].
What's a way to do this with OptParser?
thanks.
The optarse module is deprecated in python 2.7 (which has just been released!). If you can upgrade, then you can use its replacement the argparse module. I think that has what you want. It supports a '*' value for nargs.
http://docs.python.org/library/argparse.html#nargs
Have you tried ommitting the n_args bit? The examples in the docs suggest you don't need it.

Ruby equivalent to Python's help()?

When working in interactive Python, I tend to rely on the built-in help() function to tell me what something expects and/or returns, and print out any documentation that might help me. Is there a Ruby equivalent to this function?
I'm looking for something I could use in irb. For example, in interactive Python I could type:
>>> help(1)
which would then print
Help on int object:
class int(object) | int(x[, base])
-> integer | |
Convert a string or number to an integer, if possible. A ...
It's now late 2014 and here's the two ways to get the Python help() *similarity, as long as you have the Ruby Docs installed:
From inside irb, You can call the help method with a string describing what you're looking for.
Example 1: help 'Array' for the Array class
Example 2: help 'Array#each' for the Array class each method.
From the command line, outside of irb, you can use the ri program:
Example 1: ri 'Array' for the Array class
Example 2: ri 'Array#each' for the Array class each method.
* Not quite as good as Python's, but still better than nothing
It's definitely a poor cousin to iPython's help, and one of the main features I miss after moving to Ruby, but you can also use ri from within irb. I'd recommend the wirble gem as an easy way to set this up.
Try using ri from the command line.
It takes a class name, method, or module as an argument, and gives you appropriate documentation. Many popular gems come with this form of documentation, as well, so it should typically work even beyond the scope of core Ruby modules.
There's supposed to be irb_help. But like mentioned in that post, it's broken in my ruby install as well.
For quick shell access to ruby documentation, just type ri followed by the method you're wanting to learn more about (from your shell).
For example:
ri puts
This must be fired up in your shell, not your irb (interactive ruby environment)
If you're in your irb environment, then another way, is to simply type help followed by the method you want to learn more about as follows:
help puts
However, this assumes that you have configured your Ruby environment correctly for that (help) to work properly within irb. I usually just have another shell open, and just use the ri directly for quick access when I'm in doubt about a certain method or arguments to a method.

Categories