Giter Site home page Giter Site logo

ishell's People

Contributors

gitter-badger avatar ihuro avatar italorossi avatar oldhammade avatar rafaelnovello avatar rednixon avatar svenchmie avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ishell's Issues

The command auto-completion will have problems when it hits a slash string

from ishell.command import Command
class SetTimezoneCommand(Command):
   command_list = ['Africa/Dakar', 'Africa/Conakry']
   def args(self):
       return self.command_list 
   def run(self, line):
       pass
linux@louis$ python myshell.py
>>>>>>>>>>>>>Hello<<<<<<<<<<
> set timezone Africa

The string behind the tab slash cannot be displayed, Is this a bug? Or is there another way to write this problem?

Save return value of self.args() in Command

When using the autocomplete function in the console for dynamic arguments, self.args() is called 8 (!) times for each completion. That might not be a big issue when it just returns a list, but once the functions becomes more complex it adds a lot of overhead.
The function could be called once and the return value stored locally.

Command.args() has no command line visibility

It would be useful to have visibility into the command line being completed in Command.args().

For instance, if you wanted to do bash-style path completion, you could simply:

from ishell.console import Console
from ishell.command import Command
import glob

class ExampleCommand(Command):
   def args(self, line):
      line_without_command_name = ''.join(line.split()[1:])
      return glob.glob(line_without_command_name + '*')
   def run(self, line):
      print "This is an example command."

example = ExampleCommand('example', dynamic_args=True)
console = Console()
console.addChild(example)

Problem installing readline dep.

As we can see, the readline project at PyPI is deprecated because of it's name: https://pypi.org/project/readline/

We need to change it for https://pypi.org/project/gnureadline/.

When I have tried install I got the error below:

============ Building the readline extension module ============
  
  running bdist_wheel
  running build
  running build_ext
  building 'readline' extension
  creating build
  creating build/temp.linux-x86_64-2.7
  creating build/temp.linux-x86_64-2.7/Modules
  creating build/temp.linux-x86_64-2.7/Modules/2.x
  x86_64-linux-gnu-gcc -pthread -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -fno-strict-aliasing -Wdate-time -D_FORTIFY_SOURCE=2 -g -fdebug-prefix-map=/build/python2.7-nbjU53/python2.7-2.7.15~rc1=. -fstack-protector-strong -Wformat -Werror=format-security -fPIC -DHAVE_RL_CALLBACK -DHAVE_RL_CATCH_SIGNAL -DHAVE_RL_COMPLETION_APPEND_CHARACTER -DHAVE_RL_COMPLETION_DISPLAY_MATCHES_HOOK -DHAVE_RL_COMPLETION_MATCHES -DHAVE_RL_COMPLETION_SUPPRESS_APPEND -DHAVE_RL_PRE_INPUT_HOOK -I. -I/usr/include/python2.7 -c Modules/2.x/readline.c -o build/temp.linux-x86_64-2.7/Modules/2.x/readline.o -Wno-strict-prototypes
  creating build/lib.linux-x86_64-2.7
  x86_64-linux-gnu-gcc -pthread -shared -Wl,-O1 -Wl,-Bsymbolic-functions -Wl,-Bsymbolic-functions -Wl,-z,relro -fno-strict-aliasing -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -Wdate-time -D_FORTIFY_SOURCE=2 -g -fdebug-prefix-map=/build/python2.7-nbjU53/python2.7-2.7.15~rc1=. -fstack-protector-strong -Wformat -Werror=format-security -Wl,-Bsymbolic-functions -Wl,-z,relro -Wdate-time -D_FORTIFY_SOURCE=2 -g -fdebug-prefix-map=/build/python2.7-nbjU53/python2.7-2.7.15~rc1=. -fstack-protector-strong -Wformat -Werror=format-security build/temp.linux-x86_64-2.7/Modules/2.x/readline.o readline/libreadline.a readline/libhistory.a -lncurses -o build/lib.linux-x86_64-2.7/readline.so
  /usr/bin/x86_64-linux-gnu-ld: não foi possível localizar -lncurses
  collect2: error: ld returned 1 exit status
  error: command 'x86_64-linux-gnu-gcc' failed with exit status 1
  
  ----------------------------------------
  Failed building wheel for readline
  Running setup.py clean for readline
Failed to build readline
Installing collected packages: readline
  Running setup.py install for readline ... error
    Complete output from command /home/rafael/.virtualenvs/ishell_poc/bin/python2 -u -c "import setuptools, tokenize;__file__='/tmp/pip-install-xzLi3U/readline/setup.py';f=getattr(tokenize, 'open', open)(__file__);code=f.read().replace('\r\n', '\n');f.close();exec(compile(code, __file__, 'exec'))" install --record /tmp/pip-record-sKWvZX/install-record.txt --single-version-externally-managed --compile --install-headers /home/rafael/.virtualenvs/ishell_poc/include/site/python2.7/readline:
    running install
    running build
    running build_ext
    building 'readline' extension
    creating build
    creating build/temp.linux-x86_64-2.7
    creating build/temp.linux-x86_64-2.7/Modules
    creating build/temp.linux-x86_64-2.7/Modules/2.x
    x86_64-linux-gnu-gcc -pthread -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -fno-strict-aliasing -Wdate-time -D_FORTIFY_SOURCE=2 -g -fdebug-prefix-map=/build/python2.7-nbjU53/python2.7-2.7.15~rc1=. -fstack-protector-strong -Wformat -Werror=format-security -fPIC -DHAVE_RL_CALLBACK -DHAVE_RL_CATCH_SIGNAL -DHAVE_RL_COMPLETION_APPEND_CHARACTER -DHAVE_RL_COMPLETION_DISPLAY_MATCHES_HOOK -DHAVE_RL_COMPLETION_MATCHES -DHAVE_RL_COMPLETION_SUPPRESS_APPEND -DHAVE_RL_PRE_INPUT_HOOK -I. -I/usr/include/python2.7 -c Modules/2.x/readline.c -o build/temp.linux-x86_64-2.7/Modules/2.x/readline.o -Wno-strict-prototypes
    creating build/lib.linux-x86_64-2.7
    x86_64-linux-gnu-gcc -pthread -shared -Wl,-O1 -Wl,-Bsymbolic-functions -Wl,-Bsymbolic-functions -Wl,-z,relro -fno-strict-aliasing -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -Wdate-time -D_FORTIFY_SOURCE=2 -g -fdebug-prefix-map=/build/python2.7-nbjU53/python2.7-2.7.15~rc1=. -fstack-protector-strong -Wformat -Werror=format-security -Wl,-Bsymbolic-functions -Wl,-z,relro -Wdate-time -D_FORTIFY_SOURCE=2 -g -fdebug-prefix-map=/build/python2.7-nbjU53/python2.7-2.7.15~rc1=. -fstack-protector-strong -Wformat -Werror=format-security build/temp.linux-x86_64-2.7/Modules/2.x/readline.o readline/libreadline.a readline/libhistory.a -lncurses -o build/lib.linux-x86_64-2.7/readline.so
    /usr/bin/x86_64-linux-gnu-ld: não foi possível localizar -lncurses
    collect2: error: ld returned 1 exit status
    error: command 'x86_64-linux-gnu-gcc' failed with exit status 1
    
    ----------------------------------------
Command "/home/rafael/.virtualenvs/ishell_poc/bin/python2 -u -c "import setuptools, tokenize;__file__='/tmp/pip-install-xzLi3U/readline/setup.py';f=getattr(tokenize, 'open', open)(__file__);code=f.read().replace('\r\n', '\n');f.close();exec(compile(code, __file__, 'exec'))" install --record /tmp/pip-record-sKWvZX/install-record.txt --single-version-externally-managed --compile --install-headers /home/rafael/.virtualenvs/ishell_poc/include/site/python2.7/readline" failed with error code 1 in /tmp/pip-install-xzLi3U/readline/

Support dynamic_args with spaces

The console should support dynamic arguments that contain spaces. Now every space is considered the end of a command or argument.
Therefore, arguments with spaces can show up in the autocompletion, but they can not be selected.
These arguments should be recognized by the parser and handled as one atomic argument.

Autocompletion completes to command, where it should complete to dynamic argument

There is a command with a dynamic argument, let's say "calls" is the command, "continuous" is the dynamic arg. There is also another command that starts with the same letter as the dynamic arg, say "call".
If I now type "calls c" and hit TAB for autocompletion, the console completes the "c" to "call", rather than "continuous".
This does not happen, if the "call" command does not exist.

The debug log looks like this:

2014-04-10 12:22:09,903 DEBUG(40) Line=>['show', 'calls', 'call']
2014-04-10 12:22:09,905 DEBUG(49) Found existing command=>show
2014-04-10 12:22:09,905 DEBUG(34) Walked to: show
2014-04-10 12:22:09,906 DEBUG(54) More than one candidate, not walking in call
2014-04-10 12:22:09,906 DEBUG(103) PossibleCompletions=>['call ', 'calls ', None]
2014-04-10 12:22:09,906 DEBUG(40) Line=>['show', 'calls', 'call']
2014-04-10 12:22:09,906 DEBUG(49) Found existing command=>show
2014-04-10 12:22:09,906 DEBUG(34) Walked to: show
2014-04-10 12:22:09,906 DEBUG(54) More than one candidate, not walking in call
2014-04-10 12:22:09,907 DEBUG(103) PossibleCompletions=>['call ', 'calls ', None]
2014-04-10 12:22:09,907 DEBUG(40) Line=>['show', 'calls', 'call']
2014-04-10 12:22:09,907 DEBUG(49) Found existing command=>show
2014-04-10 12:22:09,907 DEBUG(34) Walked to: show
2014-04-10 12:22:09,907 DEBUG(54) More than one candidate, not walking in call
2014-04-10 12:22:09,907 DEBUG(103) PossibleCompletions=>['call ', 'calls ', None]

The example program to demonstrate the bug is this:

#!/usr/local/pythonenv/evolux/bin/python
# -*- coding: utf-8 -*-

import logging

from ishell.console import Console
from ishell.command import Command
from ishell.utils import _print
from ishell.log import logger


class SomeClass(object):
    def __init__(self):
        self.var = 1

    def some_function(self):
        self.var += 1
        _print(str(self.var))


class ShowCommand(Command):
    """ show first level command. """

    def run(self, line):
        _print("Missing parameter. Hit tab for possible completions")


class ShowCalls(Command):
    def args(self):
        return ["raw", "continuous"]

    def run(self, line):
        _print("This is the show calls command")


class ShowCall(Command):
    def args(self):
        return ["100", "101", "103"]

    def run(self, line):
        _print("This is the show call command")


def main():
    logger.setLevel(logging.DEBUG)
    console = Console("")
    show = ShowCommand("show")
    calls = ShowCalls("calls", dynamic_args=True)
    call = ShowCall("call", dynamic_args=True)
    show.addChild(calls)
    show.addChild(call)
    console.addChild(show)

    try:
        console.loop()
    except (KeyboardInterrupt, EOFError):
        pass

if __name__ == "__main__":
    main()

Windows-compatible ishell not yet uploaded to PyPI

The version of ishell on PyPI fails to install on Windows since the latest pull request which fixes that issue has not been put up on PyPI.

(Yes, I know you only accepted that PR yesterday but I'm very excited for FeatherDuster to finally be installable via pip :)

Child command behavior

Apologies if this isn't an appropriate use of the issue tracker. I'm new at this...

I came across ishell recently and it looks very nice! Seems like a good fit for a CLI I'm trying to build. Something like the Cisco example.
But the behavior of child commands is not quite what I expect - I'm probably not using it correctly, so any help would be greatly appreciated.

I've started with a very simple example with a 'show' command and 3 sub-commands - 'modules', 'hosts' and 'ports'. The first 2 are just stubs, and I'm trying to get the correct nested command behavior with "ports". There are 4 ports defined, each just a key-value pair, (port number and description) for now.

This mostly works as I would expect. I'll just list what doesn't work.

  • Typing 'show ports 10' at the base prompt should display the details for port 10. That doesn't work, But if I type 'show' and then tab-complete my way to 'ports 10' it works.
  • Once I've done that, I'm in the "show ports" command, so I should be able to 'TAB' to get a list of ports or just type a port number to show details for that port number. Neither of these work. I have to back out to the CLI root and then tab-complete my way in again.
  • Sometimes after running 'show ports XX' the prompt is '(show)' and sometimes it's '(show ports)'. I don't understand the inconsistency.

I'm sure I'm just not using the library correctly. I've tried a bunch of variations and can't get the expected behavior. Any guidance you can give would be appreciated. My minimal code is below.

Thanks,
ws

from ishell.console import Console
from ishell.command import Command
from ishell.utils import _print

def get_ports():
    # return a dicitonary of ports for testing
    port_info = {'10': "blah", '20' : "blah blah", '30': "blahdy blah blah", '40': "blahdy blahdy blah"}
    return port_info


class Hosts(Command):
    def run(self, line):
        _print("Here are the Hosts: Sunnyvale  Cupertino  Palo Alto")


class Modules(Command):
    def run(self, line):
        _print("Here are the Modules:  Hub1, Leaf1, Leaf2, Leaf3")


class Ports(Command):
    def args(self):
        return(get_ports().keys())

    def run(self, line):
        self.prompt = '(show ports)'
        port_info = get_ports()
        arg = line.split()[-1]
        if arg != 'ports':    # print details for a single port for "show ports 10" e.g.
            ss = "%s: %s" % (arg, port_info[arg])
            _print(ss)
        else:                 # print the list of port numbers for "show ports"  e.g.
            for port in port_info.keys():
                ss = "%s" % port
                _print(ss)

        self.loop()


class Show(Command):
    """
    Children:  ports, modules, hosts
    """
    def args(self):
        return ['ports', 'modules', 'hosts']

    def run(self, line):
        pass
        self.prompt = '(show)'
        ports = Ports('ports', help='Ports', dynamic_args=True)
        modules = Modules('modules', help='Modules', dynamic_args=True)
        hosts = Hosts('hosts', help='Hosts', dynamic_args=True)

        self.addChild(ports)
        self.addChild(modules)
        self.addChild(hosts)

        self.loop()


def main():
    console = Console(prompt="TEST_CLI", prompt_delim =">")

    show = Show("show", help="Show resources", dynamic_args=True)
    console.addChild(show)
    console.loop()


if __name__ == '__main__':
    main()

Error on test shell file.

When I run python test_shell.py I got the error below:

$ python test_shell.py 
Traceback (most recent call last):
  File "test_shell.py", line 2, in <module>
    from ishell.console import Console
  File "/home/rafael/prjs/ishell/ishell/console.py", line 6, in <module>
    from builtins import input
ImportError: No module named builtins

We need to install future to solve it, then it could be done at setup.py and/or requirements.txt

ctrl+d exits uncleanly

Hitting ctrl+d, a common exit command, exits uncleanly and throws a traceback. This should act in the same way as ctrl+d does.

License missing?

I see this is set as MIT, but I dont see a license file nor do I see any comments for a license in any py file. Can you add a license file for this tool please?

Chained commands do not have nested help

Given the following chain:

console.addChild(Command('show')).addChild(Command('disk')).addChild(DiskIO('io'))

Issuing the help command (return with a blank line) shows the following:

Help:
    show - No help provided

If possible it should show something like:

Help:
  show disk io - no help provided

The parents/prefixes should be repeated for each child command, for example:

Help:
  show disk io - no help provided
  show disk space - no help provided
  show cpu info - no help provided
  show cpu usage - no help provided

Support for arbitrary arguments to commands

It would be nice to be able to allow arbitrary arguments in command sequences. For example for your example Cisco-like CLI...

interface encapsulation dot1ad dot1q

The arbitrary elements could be defined by regex. I'm not sure how iShell's classes would manage this.

If you have suggestions for how to do this, I could try to implement it.

Chained command shows ugly message to user when chain is incomplete

Given the following chain:

console.addChild(Command('show')).addChild(Command('disk')).addChild(DiskIO('io'))

Issuing the command:

show disk

Results in:

Exec all(line=show disk), overwrite this method!

If all understands that it has children it should provide autocomplete results, otherwise it should show a clean/simple "unable to find command" message.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.