Skip to content

Latest commit

 

History

History
124 lines (92 loc) · 5.46 KB

README.md

File metadata and controls

124 lines (92 loc) · 5.46 KB

PyQt6 SSH Terminal Widget: UglierPTY

Overview

UglierPTY is a very functional proof-of-concept (POC) application created to construct a fully functional SSH Terminal Widget using PyQt6. This POC is inspired by its sister project, UglyPTY, a full-featured SSH client that utilizes xterm.js. The aim is to offer a similar, if not superior, feature set without relying on browser technologies or JavaScript, resulting in a more streamlined and resource-efficient solution.

This is a work in progress, but feel free to give it a try! REPO: https://github.com/scottpeterman/UglierPTY

A Note About UglyPTY

If your interested in the PyQt6/XTerm.js version of this application take a look here: https://github.com/scottpeterman/UglyPTY

Features

  • Fully functional SSH terminal built with PyQt6
  • Credentials manager for easy login
  • Portable session files in YAML (Compatible with UglyPTY)
  • Terminal history and screen ratio control via pyte
  • Terminal screen render via QPaint
  • Modular design for easy embedding into other PyQt6 projects
  • Pure Python - Free of Web technology (no xterm.js)

Architecture

  • Python 3.x
  • PyQt6
  • Paramiko
  • pyte
  • SQLAlchemy
  • PyYaml

Screenshots

Here are some snapshots of Uglier in action:

screen
screen
screen

Installation

  1. Clone the repository:

    git clone https://github.com/scottpeterman/UglierPTY
  2. Navigate into the project directory:

    cd UglierPTY
  3. Install the required Python packages:

    pip install -r requirements.txt

Usage

The primary entry point for this POC is the uglierpty.py script. To launch the application:

If you cloned the repo

python run_test.py

If you installed via PIP

python -m uglierpty
or 
pythonw -m uglierpty

SSH Terminal Flow

<title>SSH Terminal Flow</title>

SSH Terminal Flow

+--------------------+       +-------------------+       +-------------------+       +------------+       +------------------+
| SSHTerminalWidget  |       |    SSHLib Class   |       |  Communication    |       |    pyte    |       | Remote SSH Host  |
|                    |       |                   |       |                   |       |            |       |                  |
|  keyPressEvent()   |------>|     write(data)   |------>|   sendDataToSSH() |------>|            |------>|   Shell Process  |
|                    |       |                   |       |                   |       |            |       |                  |
+--------------------+       +-------------------+       +-------------------+       +------------+       +------------------+
                ^                                       ^                          ^                           ^                     
                |                                       |                          |                           |                             
                |                                       |                          |                           |
                |                                       |                          |                           |
                |                                       |                          |                           |      
+--------------------+       +-------------------+       +-------------------+       +------------+       +------------------+
| SSHTerminalWidget  |       |    SSHLib Class   |       |  Communication    |       |    pyte    |       | Remote SSH Host  |
|                    |       |                   |       |                   |       |            |       |                  |
|    paintEvent()    |<------|      read()       |<------|  receiveDataFromSSH() |<------|   feed()   |<------|   Shell Process  |
|                    |       |                   |       |                   |       | stream.attach(screen) |       |                  |
+--------------------+       +-------------------+       +-------------------+       +------------+       +------------------+

Step-by-Step Explanation:

  1. Keystroke in SSHTerminalWidget: The keyPressEvent() function captures the keystroke and sends it to the SSHLib class via write(data).
  2. Sending to SSH Channel: The write() method sends the data through an SSH channel, probably utilizing paramiko.SSHClient. This is done in Communication.sendDataToSSH().
  3. SSH to Remote Host: The keystroke reaches the shell process running on the remote SSH host.
  4. Remote Host to pyte: Once the shell process echoes the output, it's read by Communication.receiveDataFromSSH() and fed to pyte's Stream object via feed() in SSHLib.read().
  5. pyte to GUI: The Stream object updates the Screen object, which the SSHTerminalWidget.paintEvent() method uses to draw on the GUI, completing the round trip.