In python cmd module, when I press the TAB button, I get the list of possible commands that are available and that I have defined in my cmd.Cmd class.
My question is whether it is possible to show a set of commands based on the context like in a Cisco router CLI for instance?
I don't have any experience with this lib, but doc says
If completion is enabled, completing commands will be done automatically, and completing of commands args is done by calling complete_foo() with arguments text, line, begidx, and endidx. text is the string prefix we are attempting to match: all returned matches must begin with it. line is the current input line with leading whitespace removed, begidx and endidx are the beginning and ending indexes of the prefix text, which could be used to provide different completion depending upon which position the argument is in.
So, may be you can implement context based completion in complete_foo function
I have found an answer to my question. One can use nested interpreters, so a nested interpreter is another interpreter object that will have its own commands, this way each context can be modeled by a nested interpreter. Here is a nice explanation and example:
object inheritance and nested cmd
If you want something like Cisco take a look at ishell,
ishell helps you to easily create an interactive shell for your application. It supports command completion, dynamic arguments, a command history, and chaining of commands.
https://github.com/italorossi/ishell
There's a cisco like cli example at https://github.com/italorossi/ishell/blob/master/examples/cisco.py
PS: I'm the author.
Related
I define an argsparse object like this:
parser = argparse.ArgumentParser(description='{desc}', formatter_class=argparse.ArgumentDefaultsHelpFormatter)\
.format(desc=description)
Then I add arguments like this:
parser.add_argument("--config", "-c", help='config',
default='dbConf').format(dbConf=dbConfig)
Since I use these two lines in many scripts, I want to embed them into a function.
However, to my understanding the parser.add_argument() listens to the command line.
Is it possible to embed these lines into a function?
Is it possible to embed these lines into a function?
Yes. add_argument doesn't interact with the command line at all, though even if it did that would make little difference.
The one bit of argparse which interacts with the CLI input is the parse_args method, and what it does by default is access the global sys.argv attribute and process it. I wrote by default because you can also provide a list of strings as first parameter and it'll process that instead (if you click the link you'll see the official documentation does that to demonstrate various things in the examples).
So yes, you can very much have a function which creates an ArgumentParser and starts configuring it, then returns it for more configuration and ultimately, well, parsing the arguments.
I am looking for a good module that is already out there for parsing arguments on custom CLI interfaces. If you can imagine there is a CLI that gives you a prompt:
framework> commands go here....
It starts to get tedious when you add in arguments, example:
framework> command <argument1> <argument2> ...
I'd like to know if there is any sort of module that will not only make it easy to create these CLI interfaces, but one that has tab completion for each argument in a command chain. I'm tired of reinventing the wheel each time I create something like this!
framework> comma<tab>
framework> command arg<tab>
framework> command argument parame<tab>
framework> command argument parameter
You get the idea. If there is no module already out there for this sort of thing, any suggestions on an elegant solution to creating something like this in a modularized fashion, it would be much appreciated.
Please note that I do not want to parse arguments passed in through the parent process command shell (such as bash), I want to do the processing from within an infinite while loop within the script itself. For example:
while (True):
cmd = raw_input("framework> ")
framework.process_command(cmd)
Take a look at Click, "a Python package for creating beautiful command line interfaces in a composable way with as little code as necessary": http://click.pocoo.org/5/
in python you have a build in module called argparse to manage CLI parameters application, now take a look to this module argparse extension for tab completion https://pypi.python.org/pypi/argcomplete/0.8.4
Looks like the builtin cmd module offers what you're looking for. It supports tab completion for commands and arguments. Here's a tutorial from PyMOTW. Another example here.
If you need some more customizations, there's also cmd2 which extends the builtin cmd.
Think about this scenario:
I debug my Django project and I step through the code (in and out). The debugger sometimes enters Django libraries or other external libraries.
Does anyone know how to prevent the debugger from entering external code? Or at least a 'big' step out to get the debugger back to the project code?
Does anyone know how to prevent the debugger from entering external code?
Yes, Dmitry Trofimov knows;
(...) add modules you don't want to trace to the dict DONT_TRACE in <pycharm-distr>/helpers/pydev/pydevd.py
That is a hacky solution (...)
If you want this feature to be less hacky you can vote on it by visiting issue
PY-9101 Implement "Do not step into the classes" option for Python debugger
Those using pdb might be interested to know there is such a feature in pdb;
Starting with Python 3.1, Pdb class has a new argument called skip -
class pdb.Pdb(completekey='tab', stdin=None, stdout=None, skip=None, nosigint=False)
The skip argument, if given, must be an iterable of glob-style module
name patterns. The debugger will not step into frames that originate
in a module that matches one of these patterns. 1
1 Whether a frame is considered to originate in a certain module is
determined by the __name__ in the frame globals.
The example given in the docs shows how to skip Django's packages -
import pdb; pdb.Pdb(skip=['django.*']).set_trace()
Everything looks the same to the debugger, it can't distinguish between your code or Django's code – it's all Python. So it will run everything, however if you want to stop it from drilling down so low you'll have to start “stepping over” lines of code instead of “stepping into” them.
According to the PyCharm docs you'll want to use F8 when ever you see a line of code that looks like it could be a gateway into Django's internals. If you accidently find yourself inside Django's source code you can hit Shift+F8 until you're out of it.
I'm developing a system that operates on (arbitrary) data from databases. The data may need some preprocessing before the system can work with it. To allow the user the specify possibly complex rules I though of giving the user the possibility to input Python code which is used to do this task. The system is pure Python.
My plan is to introduce the tables and columns as variables and let the user to anything Python can do (including access to the standard libs). Now to my problem:
How do I take a string (the user entered), compile it to Python (after adding code to provide the input data) and get the output. I think the easiest way would be to use the user-entered data a the body of a method and take the return value of that function a my new data.
Is this possible? If yes, how? It's unimportant that the user may enter malicious code since the worst thing that could happen is, that he screws up his own system, which is thankfully not my problem ;)
Python provides an exec() statement which should do what you want. You will want to pass in the variables that you want available as the second and/or third arguments to the function (globals and locals respectively) as those control the environment that the exec is run in.
For example:
env = {'somevar': 'somevalue'}
exec(code, env)
Alternatively, execfile() can be used in a similar way, if the code that you want executed is stored in its own file.
If you only have a single expression that you want to execute, you can also use eval.
Is this possible?
If it doesn't involve time travel, anti-gravity or perpetual motion the answer to this question is always "YES". You don't need to ask that.
The right way to proceed is as follows.
You build a framework with some handy libraries and packages.
You build a few sample applications that implement this requirement: "The data may need some preprocessing before the system can work with it."
You write documentation about how that application imports and uses modules from your framework.
You turn the framework, the sample applications and the documentation over to users to let them build these applications.
Don't waste time on "take a string (the user entered), compile it to Python (after adding code to provide the input data) and get the output".
The user should write applications like this.
from your_framework import the_file_loop
def their_function( one_line_as_dict ):
one_line_as_dict['field']= some stuff
the_file_loop( their_function )
That can actually be the entire program.
You'll have to write the_file_loop, which will look something like this.
def the_file_loop( some_function ):
with open('input') as source:
with open('output') as target:
for some_line in source:
the_data = make_a_dictionary( some_line )
some_function( the_data )
target.write( make_a_line( the_data ) )
By creating a framework, and allowing users to write their own programs, you'll be a lot happier with the results. Less magic.
2 choices:
You take his input and put it in a file, then you execute it.
You use exec()
If you just want to set some local values and then provide a python shell, check out the code module.
You can start an instance of a shell that is similar to the python shell, as well as initialize it with whatever local variables you want. This would assume that whatever functionality you want to use the resulting values is built into the classes you are passing in as locals.
Example:
shell = code.InteractiveConsole({'foo': myVar1, 'bar': myVar2})
What you actually want is exec, since eval is limited to taking an expression and returning a value. With exec, you can have code blocks (statements) and work on arbitrarily complex data, passed in as the globals and locals of the code.
The result is then returned by the code via some convention (like binding it to result).
well, you're describing compile()
But... I think I'd still implement this using regular python source files. Add a special location to the path, say '~/.myapp/plugins', and just __import__ everything there. Probably you'll want to provide some convenient base classes that expose the interface you're trying to offer, so that your users can inherit from them.
Ok i have these commands used in batch and i wanted to know the commands in python that would have a similar affect, just to be clear i dont want to just use os.system("command here") for each of them. For example in batch if you wanted a list of commands you would type help but in python you would type help() and then modules... I am not trying to use batch in a python script, i just wanna know the similarities in both languages. Like in english you say " Hello" but in french you say "Bonjour" not mix the two languages. (heres the list of commands/functions id like to know:
change the current directory
clear the screen in the console
change the prompt to something other than >>>
how to make a loop function
redirections/pipes
start an exteral program (like notepad or paint) from within a script
how to call or import another python script
how to get help with a specific module without having to type help()
#8: (in batch it would be command /?)
EDITED COMPLETELY
Thanks in Adnvance!
You can't just mechanically translate batch script to Python and hope that it works. It's a different language, with different idioms and ways of doing things, not to mention the different purpose.
I've listed some functions related to what you want below, but there's no substitute for just going and learning Python!
os.chdir
os.system("cls") is probably the simplest solution
Change sys.ps1 and sys.ps2.
Nope, there are no gotos in Python. Use for and while loops instead.
Doesn't make sense, use Python's IO instead.
subprocess.Popen
Doesn't make sense, use import or subprocess.Popen instead.
help
Most of the things you've mentioned (start, cls etc.) are not "batch commands", they're executable programs which perform certain tasks. The DOS "shell" simply executes these when it encounters them in a file. In this sense, "python" is the equivalent of a single executable (like cls).
Now that that's clear, cd (and most other OS specific tasks) are accomplished using the os module. There's no single Python statement to clear the screen - that would be wasteful. Changing the prompt of the python interpreter can be done by assigning to sys.ps1. Loops are done using while or for. Redirection doesn't happen. YOu can however use the subprocess module to run subcommands and send their outputs to files or other streams. Starting commands is done using the subprocess.Popen function. For getting help, you can either do help("command") or if you're using ipython, just say command? and hit enter.
You should really go through the tutorial rather than trying to map batch commands to Python.
The Python docs are excellent, and are the place to start. For doing shell-script like things, you'll want to check out:
http://docs.python.org/library/os.html?module-os
http://docs.python.org/library/os.path.html#module-os.path
http://docs.python.org/library/shutil.html#module-shutil
http://docs.python.org/library/subprocess.html#module-subprocess
Python is not a system shell, Python is a multi-paradigm programming language.
If you want to compare .bat with anything, compare it with sh or bash. (You can have those on various platforms too - for example, sh for windows is in the MinGW package).
I am pretty much facing the same problem as you, daniel11. As a solution, I am learning BATCH commands and their meaning. After I understand those, I am going to write a program in Python that does the same or accomplishes the same task.
Thanks to Adam V. and katrielatex for their insight and suggestions.