def start(self, evtcallback, cursorcallback): """ Launches the TerminalSession's process and adds to it the given callback to deal with modified lines. The callback takes the form callback(line_number, line). """ if self.running: raise SessionStateError("TerminalSession already running") self.running = True self.stream = pyte.ByteStream() self.screen = pyte.DiffScreen(self.params["cols"], self.params["rows"]) # self.screen.set_mode(pyte.modes.LNM) # This treats \ns as \r\ns. # Is this necessary/reasonable? self.stream.attach(self.screen) child_pid, self.child_fd = pty.fork() os.chdir(self.working_dir) os.environ['HOME'] = self.home_dir if not child_pid: # under what circumstances would it not be 0? os.execv(self.cmd, self.args) attr = termios.tcgetattr(self.child_fd) attr[3] = attr[3] & ~termios.ECHO # Disable echoing termios.tcsetattr(self.child_fd, termios.TCSANOW, attr) winsize = struct.pack("HHHH", self.params["rows"], self.params["cols"], 0, 0) fcntl.ioctl(self.child_fd, termios.TIOCSWINSZ, winsize) # set size self.callback = evtcallback self.cursor_callback = cursorcallback
def __init__(self, columns, lines, p_in): self.screen = pyte.DiffScreen(columns, lines) self.screen.set_mode(pyte.modes.LNM) self.screen.write_process_input = \ lambda data: p_in.write(data.encode()) self.stream = pyte.ByteStream() self.stream.attach(self.screen)
def __init__(self, manager=None, id=None, command=None, autoclose=False, autoclose_retain=5): self.width = 80 self.height = 25 self.id = id self.manager = manager self.autoclose = autoclose self.autoclose_retain = autoclose_retain self.output = BroadcastQueue() env = {} env.update(os.environ) env['TERM'] = 'linux' env['COLUMNS'] = str(self.width) env['LINES'] = str(self.height) env['LC_ALL'] = 'en_US.UTF8' self.command = command if not self.command: shell = os.environ.get('SHELL', None) if not shell: for sh in ['zsh', 'bash', 'sh']: try: shell = subprocess.check_output(['which', sh]) break except: pass self.command = shell args = ['sh', '-c', self.command] exe = 'sh' logging.info('Activating new terminal: %s', self.command) self.pid, self.fd = pty.fork() if self.pid == 0: setproctitle.setproctitle('%s terminal session #%i' % (sys.argv[0], os.getpid())) os.execvpe(exe, args, env) logging.info('Subprocess PID %s', self.pid) self.dead = False fl = fcntl.fcntl(self.fd, fcntl.F_GETFL) fcntl.fcntl(self.fd, fcntl.F_SETFL, fl | os.O_NONBLOCK) self.stream_in = os.fdopen(self.fd, 'rb', 0) self.stream_out = os.fdopen(self.fd, 'wb', 0) self.pyte_stream = pyte.Stream() self.screen = pyte.DiffScreen(self.width, self.height) self.pyte_stream.attach(self.screen) self.last_cursor_position = None self.reader = gevent.spawn(self.reader_fn)
def test_mark_whole_screen(): # .. this is straightforward -- make sure we have a dirty attribute # and whole screen is marked as dirty on initialization, reset, # resize etc. screen = pyte.DiffScreen(80, 24) # a) init. assert hasattr(screen, "dirty") assert isinstance(screen.dirty, set) assert screen.dirty == set(range(screen.lines)) # b) reset(). screen.dirty.clear() screen.reset() assert screen.dirty == set(range(screen.lines)) # c) resize(). screen.dirty.clear() screen.resize(130, 24) assert screen.dirty == set(range(screen.lines)) # d) alignment_display(). screen.dirty.clear() screen.alignment_display() assert screen.dirty == set(range(screen.lines))
def __init__(self, command=None, autoclose=False, **kwargs): self.protocol = None self.width = 160 self.height = 35 self.autoclose = autoclose env = {} env.update(os.environ) env['TERM'] = 'linux' env['COLUMNS'] = str(self.width) env['LINES'] = str(self.height) env['LC_ALL'] = 'en_US.UTF8' shell = os.environ.get('SHELL', None) if not shell: for sh in ['zsh', 'bash', 'sh']: try: shell = subprocess.check_output(['which', sh]) break except: pass command = ['sh', '-c', command or shell] logging.info('Terminal: %s' % command) pid, master = pty.fork() if pid == 0: os.execvpe('sh', command, env) self.screen = pyte.DiffScreen(self.width, self.height) self.protocol = PTYProtocol(pid, master, self.screen, **kwargs)
def __init__(self, command=None, autoclose=False): self.protocol = None self.width = 160 self.height = 35 self.autoclose = autoclose env = {} env.update(os.environ) env['TERM'] = 'linux' env['COLUMNS'] = str(self.width) env['LINES'] = str(self.height) env['LC_ALL'] = 'en_US.UTF8' command = command or 'sh -c \"$SHELL\"', pid, master = pty.fork() if pid == 0: p = sp.Popen( command, shell=True, stdin=None, stdout=None, stderr=None, close_fds=True, env=env, ) p.wait() ajenti.exit() return self.screen = pyte.DiffScreen(self.width, self.height) self.protocol = PTYProtocol(pid, master, self.screen)
def test_insert_delete_lines(): screen = pyte.DiffScreen(80, 24) screen.cursor_to_line(screen.lines // 2) for method in ["insert_lines", "delete_lines"]: screen.dirty.clear() getattr(screen, method)() assert screen.dirty == set(range(screen.cursor.y, screen.lines))
def test_modes(): # Making sure `DECSCNM` triggers a screen to be fully re-drawn. screen = pyte.DiffScreen(80, 24) screen.dirty.clear() screen.set_mode(mo.DECSCNM >> 5, private=True) assert screen.dirty == set(range(screen.lines)) screen.dirty.clear() screen.reset_mode(mo.DECSCNM >> 5, private=True) assert screen.dirty == set(range(screen.lines))
def test_index(): screen = pyte.DiffScreen(80, 24) screen.dirty.clear() # a) not at the bottom margin -- nothing is marked dirty. screen.index() assert not screen.dirty # b) whole screen is dirty. screen.cursor_to_line(24) screen.index() assert screen.dirty == set(range(screen.lines))
def test_reverse_index(): screen = pyte.DiffScreen(80, 24) screen.dirty.clear() # a) not at the top margin -- whole screen is dirty. screen.reverse_index() assert screen.dirty == set(range(screen.lines)) # b) nothing is marked dirty. screen.dirty.clear() screen.cursor_to_line(screen.lines // 2) screen.reverse_index() assert not screen.dirty
def __init__(self, proc, stream): self.data = '' self.proc = proc self.master = stream fd = self.master fl = fcntl.fcntl(fd, fcntl.F_GETFL) fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK) self.mstream = os.fdopen(self.master, 'r+') gevent.sleep(2) self.term = pyte.DiffScreen(TERM_W, TERM_H) self.stream = pyte.Stream() self.stream.attach(self.term) self.data = '' self.unblock()
def test_draw_wrap(): screen = pyte.DiffScreen(80, 24) screen.set_mode(mo.DECAWM) # fill every character cell on the first row for _ in range(80): screen.draw("g") assert screen.cursor.y == 0 screen.dirty.clear() # now write one more character which should cause wrapping screen.draw("h") assert screen.cursor.y == 1 # regression test issue #36 where the wrong line was marked as # dirty assert screen.dirty == set([0, 1])
def test_erase_in_display(): screen = pyte.DiffScreen(80, 24) screen.cursor_to_line(screen.lines // 2) # a) from cursor to the end of the screen. screen.dirty.clear() screen.erase_in_display() assert screen.dirty == set(range(screen.cursor.y, screen.lines)) # b) from the begining of the screen to cursor. screen.dirty.clear() screen.erase_in_display(1) assert screen.dirty == set(range(0, screen.cursor.y + 1)) # c) whole screen. screen.dirty.clear() screen.erase_in_display(2) assert screen.dirty == set(range(0, screen.lines))
def test_mark_single_line(): screen = pyte.DiffScreen(80, 24) # a) draw(). screen.dirty.clear() screen.draw("f") assert len(screen.dirty) == 1 assert screen.cursor.y in screen.dirty # b) rest ... for method in [ "insert_characters", "delete_characters", "erase_characters", "erase_in_line" ]: screen.dirty.clear() getattr(screen, method)() assert len(screen.dirty) == 1 assert screen.cursor.y in screen.dirty
def __init__(self, command=None, autoclose=False, **kwargs): self.protocol = None self.width = 160 self.height = 35 self.autoclose = autoclose env = {} env.update(os.environ) env['TERM'] = 'linux' env['COLUMNS'] = str(self.width) env['LINES'] = str(self.height) env['LC_ALL'] = 'en_US.UTF8' command = ['sh', '-c', command or 'sh'] pid, master = pty.fork() if pid == 0: os.execvpe('sh', command, env) self.screen = pyte.DiffScreen(self.width, self.height) self.protocol = PTYProtocol(pid, master, self.screen, **kwargs)
def __call__(self, window): # Don't wait for input when calling getch. window.nodelay(1) # Don't interpret escape sequences, we want to send them on. window.keypad(0) self.window = window # Set up terminal y, x = window.getmaxyx() self.screen = pyte.DiffScreen(x - 1, y) self.screen_stream = pyte.ByteStream() self.screen_stream.attach(self.screen) window.addstr( 0, 0, "Welcome to uterm. If a program is running you'll " "want to hit ctrl-c.") window.move(1, 0) while self.running: try: self.loop() except KeyboardInterrupt: if not self.accept_input: raise self.tx(b'\x03')
def __init__(self, manager=None, id=None, command=None, autoclose=False, autoclose_retain=5, redirect=None): """ Setup the environment for a new terminal. :param manager: TerminalManager object :type manager: TerminalManager :param id: Id fo the terminal :type id: hex :param command: Command to run :type command: string :param autoclose: Parameter to close the terminal after the command :type autoclose: bool :param autoclose_retain: Time to wait before closing in seconds :type autoclose_retain: integer :param redirect: Default redirect URL after closing :type redirect: string """ self.width = 80 self.height = 25 self.id = id self.manager = manager self.autoclose = autoclose self.autoclose_retain = autoclose_retain if redirect: self.redirect = redirect else: self.redirect = '/view/terminal' self.output = BroadcastQueue() env = {} env.update(os.environ) env['TERM'] = 'linux' env['COLUMNS'] = str(self.width) env['LINES'] = str(self.height) env['LC_ALL'] = 'en_US.UTF8' self.command = command if not self.command: shell = os.environ.get('SHELL', None) if not shell: for sh in ['zsh', 'bash', 'sh']: try: shell = subprocess.check_output(['which', sh]) break except Exception as e: pass self.command = shell args = ['sh', '-c', self.command] exe = 'sh' logging.info(f'Activating new terminal: {self.command}') self.pid, self.fd = pty.fork() if self.pid == 0: setproctitle.setproctitle( f'{sys.argv[0]} terminal session #{os.getpid():d}') os.execvpe(exe, args, env) logging.info(f'Subprocess PID {self.pid}') self.dead = False fl = fcntl.fcntl(self.fd, fcntl.F_GETFL) fcntl.fcntl(self.fd, fcntl.F_SETFL, fl | os.O_NONBLOCK) self.stream_in = os.fdopen(self.fd, 'rb', 0) self.stream_out = os.fdopen(self.fd, 'wb', 0) self.pyte_stream = pyte.Stream() self.screen = pyte.DiffScreen(self.width, self.height) self.pyte_stream.attach(self.screen) self.last_cursor_position = None self.reader = gevent.spawn(self.reader_fn)
def __init__(self, columns, lines): self.screen = pyte.DiffScreen(columns, lines) self.stream = pyte.ByteStream() self.stream.attach(self.screen)