def testPositional(self): """ Tests positional arguments """ def command(io_handler, arg1, arg2): """ Sample command """ return arg1, arg2 # Register the command self.shell.register_command('test', 'command', command) # Valid execution session = beans.ShellSession(beans.IOHandler(sys.stdin, sys.stdout)) self.assertTrue(self.shell.execute('test.command a 2', session)) result = session.last_result self.assertEqual(result, ('a', '2')) # Invalid call for invalid in ([1], (1, 2, 3)): args = ' '.join(str(arg) for arg in invalid) self.assertFalse( self.shell.execute('test.command {0}'.format(args)), "Invalid call passed")
def _make_session(self): """ Prepares a ShellSession object for _run_command """ # String output str_output = StringIO() # Session bean session = beans.ShellSession(beans.IOHandler(None, str_output)) return session, str_output
def _run_local_command(self, command, *args): """ Runs the given command and returns the output stream """ # String output str_output = StringIO() # Format command if args: command = command.format(*args) # Run command session = beans.ShellSession(beans.IOHandler(None, str_output)) self.shell.execute(command, session) return str_output.getvalue().strip()
def testKeywords(self): """ Tests positional arguments """ def command(io_handler, arg1='15', **kwargs): """ Sample command """ return arg1, kwargs # Register the command self.shell.register_command('test', 'command', command) # Prepare the session session = beans.ShellSession(beans.IOHandler(sys.stdin, sys.stdout)) # Valid execution self.shell.execute('test.command arg1=12 a=2 b=abc', session) result = session.last_result self.assertEqual(result, ('12', { 'a': '2', 'b': 'abc' }), "Invalid result: {0}".format(result)) self.shell.execute('test.command 12', session) result = session.last_result self.assertEqual(result, ('12', {}), "Invalid result: {0}".format(result)) self.shell.execute('test.command a=12', session) result = session.last_result self.assertEqual(result, ('15', { 'a': '12' }), "Invalid result: {0}".format(result)) # First '=' sign is the assignment one, # shlex.split removes slashes self.shell.execute('test.command a=a=b b\=a=b', session) result = session.last_result self.assertEqual(result, ('15', { 'a': 'a=b', 'b': 'a=b' }), "Invalid result: {0}".format(result)) # Invalid call (2 arguments) self.assertFalse(self.shell.execute('test.command 1 2'), "Invalid call passed")
def _run_command(self, command, *args): """ Runs the given shell command """ # String output str_output = StringIO() # Format command if args: command = command.format(*args) # Add the namespace prefix command = 'config.{0}'.format(command) # Run command session = beans.ShellSession(beans.IOHandler(None, str_output)) self.shell.execute(command, session) return str_output.getvalue()
def test_run_file(self): """ Tests the run shell command """ # Check bad file error self.assertFalse(self.shell.execute("run __fake_file__")) # Compute test file name filename = os.path.join(os.path.dirname(__file__), "rshell_starter.pelix") # Install iPOPO self.context.install_bundle('pelix.ipopo.core').start() self.context.install_bundle('pelix.shell.ipopo').start() # Prepare a session port = 9001 session = beans.ShellSession(beans.IOHandler(sys.stdin, sys.stdout), {"port": port}) # Run the file a first time self.assertTrue( self.shell.execute("run '{0}'".format(filename), session)) # Check the result self.assertEqual(session.get("rshell.name"), "rshell") # Check the bundle rshell_bundle = int(session.get("rshell.bundle")) bundle = self.context.get_bundle(rshell_bundle) self.assertEqual(bundle.get_symbolic_name(), "pelix.shell.remote") # Check the instance properties with use_ipopo(self.context) as ipopo: details = ipopo.get_instance_details(session.get("rshell.name")) self.assertEqual(int(details["properties"]["pelix.shell.port"]), port) # Run the file a second time: it must fail self.assertFalse( self.shell.execute("run '{0}'".format(filename), session))
def handle_message(self, source_jid, content): """ Handles an XMPP message and reply to the source :param source_jid: JID of the message sender :param content: Content of the message """ try: # Use the existing session session = self.__sessions[source_jid] except KeyError: # Subscribe to presence messages self.__bot.sendPresence(pto=source_jid, ptype='subscribe') # Create and store the session session = self.__sessions[source_jid] = beans.ShellSession( beans.IOHandler(_XmppInStream(self, source_jid), _XmppOutStream(self.__bot, source_jid)), {"xmpp.jid": source_jid}) self._shell.execute(content, session)
def _run_command(self, command, *args, **kwargs): """ Runs the given command and returns the output stream. A keyword argument 'session' can be given to use a custom ShellSession. """ # Format command if args: command = command.format(*args) try: # Get the given session session = kwargs['session'] str_output = kwargs['output'] str_output.truncate(0) str_output.seek(0) except KeyError: # No session given str_output = StringIO() session = beans.ShellSession(beans.IOHandler(None, str_output)) # Run command self.shell.execute(command, session) return str_output.getvalue()
def handle(self): """ Handles a TCP client """ _logger.info("RemoteConsole client connected: [%s]:%d", self.client_address[0], self.client_address[1]) # Prepare the session session = beans.ShellSession( beans.IOHandler(self.rfile, self.wfile), {"remote_client_ip": self.client_address[0]}) # Print the banner def get_ps1(): """ Gets the prompt string from the session of the shell service :return: The prompt string """ try: return session.get("PS1") except KeyError: return self._shell.get_ps1() self.send(self._shell.get_banner()) self.send(get_ps1()) try: while self._active.get_value(): # Wait for data rlist = select([self.connection], [], [], .5)[0] if not rlist: # Nothing to do (poll timed out) continue data = self.rfile.readline() if not data: # End of stream (client gone) break # Strip the line line = data.strip() if not data: # Empty line continue # Execute it try: self._shell.handle_line(line, session) except KeyboardInterrupt: # Stop there on interruption self.send("\nInterruption received.") return except IOError as ex: # I/O errors are fatal _logger.exception( "Error communicating with a client: %s", ex) break except Exception as ex: # Other exceptions are not important import traceback self.send("\nError during last command: {0}\n".format(ex)) self.send(traceback.format_exc()) # Print the prompt self.send(get_ps1()) finally: _logger.info("RemoteConsole client gone: [%s]:%d", self.client_address[0], self.client_address[1]) try: # Be polite self.send("\nSession closed. Good bye.\n") self.finish() except IOError as ex: _logger.warning("Error cleaning up connection: %s", ex)
def execute(self, cmdline, session=None): """ Executes the command corresponding to the given line :param cmdline: Command line to parse :param session: Current shell session :return: True if command succeeded, else False """ if session is None: # Default session session = beans.ShellSession( beans.IOHandler(sys.stdin, sys.stdout), {}) assert isinstance(session, beans.ShellSession) # Split the command line if not cmdline: return False # Convert the line into a string cmdline = to_str(cmdline) try: line_split = shlex.split(cmdline, True, True) except ValueError as ex: session.write_line("Error reading line: {0}", ex) return False if not line_split: return False try: # Extract command information namespace, command = self.get_ns_command(line_split[0]) except ValueError as ex: # Unknown command session.write_line(str(ex)) return False # Get the content of the name space space = self._commands.get(namespace, None) if not space: session.write_line("Unknown name space {0}", namespace) return False # Get the method object method = space.get(command, None) if method is None: session.write_line("Unknown command: {0}.{1}", namespace, command) return False # Make arguments and keyword arguments args, kwargs = _make_args(line_split[1:], session, self._framework.get_properties()) try: # Execute it result = method(session, *args, **kwargs) # Store the result as $? if result is not None: session.set(beans.RESULT_VAR_NAME, result) # 0, None are considered as success, so don't use not nor bool return result is not False except TypeError as ex: # Invalid arguments... self._logger.error("Error calling %s.%s: %s", namespace, command, ex) session.write_line("Invalid method call: {0}", ex) self.__print_namespace_help(session, namespace, command) return False except Exception as ex: # Error self._logger.exception("Error calling %s.%s: %s", namespace, command, ex) session.write_line("{0}: {1}", type(ex).__name__, str(ex)) return False finally: # Try to flush in any case try: session.flush() except IOError: pass