From 3d8f9968b04037c78ace1ee07f8aeafd1f54ca98 Mon Sep 17 00:00:00 2001 From: Chad Smith Date: Tue, 10 Aug 2021 20:51:47 -0700 Subject: [PATCH 1/5] pin requirements and some cleanup --- CHANGELOG.md | 5 ++ MANIFEST.in | 2 +- README.md | 28 ++++---- noxfile.py | 6 ++ pyxtermjs/app.py | 10 +-- pyxtermjs/index.html | 156 ++++++++++++++++++++++--------------------- requirements.in | 1 + requirements.txt | 24 +++---- setup.py | 7 +- 9 files changed, 129 insertions(+), 110 deletions(-) create mode 100644 CHANGELOG.md create mode 100644 requirements.in diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..673dced --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,5 @@ +## 0.5.0.0 + +* Update dependencies xtermjs and socketio +* Turn off flask's logging +* Update setup.py to install from pinned dependencies in requirements.tx \ No newline at end of file diff --git a/MANIFEST.in b/MANIFEST.in index 761f5c8..74dab9c 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,2 +1,2 @@ -include README.md LICENSE +include README.md LICENSE requirements.txt recursive-include pyxtermjs * \ No newline at end of file diff --git a/README.md b/README.md index 5df3961..507117b 100644 --- a/README.md +++ b/README.md @@ -32,34 +32,32 @@ This is a There are a few ways to install and run. ### Clone & Run Locally -Clone this repository, enter the `pyxtermjs` directory, then run: +Clone this repository, enter the `pyxtermjs` directory. + +If you have [nox](https://github.com/theacodes/nox) you can run the following. ``` -> python -m venv venv # must be python3.6+ -> venv/bin/pip install -r requirements.txt -> venv/bin/python -m pyxtermjs -serving on http://127.0.0.1:5000 +> nox -s run ``` +Nox takes care of setting up a virtual environment and running the right command for you. -### Install or Run latest version on PyPI -You can use [pipx](https://github.com/pipxproject/pipx) to try it out. +If you don't have nox, you can run the following from inside a virtual environment. ``` -> pipx run pyxtermjs -serving on http://127.0.0.1:5000 +> pip install -r requirements.txt +> python -m pyxtermjs ``` -You can also and have `pyxtermjs` installed in an isolated environment, yet available on your $PATH with +### Install +You can install with [pipx](https://github.com/pipxproject/pipx) (recommended) or pip. ``` > pipx install pyxtermjs +> pyxtermjs ``` -### Run from GitHub source -Use [pipx](https://github.com/pipxproject/pipx) for this as well. +Or you can try run latest version on PyPI ``` -> pipx run --spec git+https://github.com/cs01/pyxtermjs.git pyxtermjs -serving on http://127.0.0.1:5000 +> pipx run pyxtermjs ``` - ## API ``` > pyxtermjs --help diff --git a/noxfile.py b/noxfile.py index c312711..0731f43 100644 --- a/noxfile.py +++ b/noxfile.py @@ -7,6 +7,12 @@ nox.options.reuse_existing_virtualenvs = True +@nox.session() +def run(session): + session.install(".") + session.run("python", "-m", "pyxtermjs", *session.posargs) + + def has_changes(): status = ( subprocess.run( diff --git a/pyxtermjs/app.py b/pyxtermjs/app.py index 19c65a7..f64c97d 100644 --- a/pyxtermjs/app.py +++ b/pyxtermjs/app.py @@ -10,15 +10,17 @@ import struct import fcntl import shlex +import logging +logging.getLogger("werkzeug").setLevel(logging.ERROR) -__version__ = "0.4.0.2" +__version__ = "0.5.0.0" app = Flask(__name__, template_folder=".", static_folder=".", static_url_path="") app.config["SECRET_KEY"] = "secret!" app.config["fd"] = None app.config["child_pid"] = None -socketio = SocketIO(app) +socketio = SocketIO(app, logger=False, engineio_logger=False) def set_winsize(fd, row, col, xpix=0, ypix=0): @@ -49,8 +51,8 @@ def pty_input(data): terminal. """ if app.config["fd"]: - # print("writing to ptd: %s" % data["input"]) - os.write(app.config["fd"], data["input"]["key"].encode()) + # print("writing to pty: %s" % data["input"]) + os.write(app.config["fd"], data["input"].encode()) @socketio.on("resize", namespace="/pty") diff --git a/pyxtermjs/index.html b/pyxtermjs/index.html index 36bea3a..7d5b7ba 100644 --- a/pyxtermjs/index.html +++ b/pyxtermjs/index.html @@ -1,93 +1,97 @@ - - - pyxterm.js - - - - + + + pyxterm.js + + + + + pyxterm.js    + status: + connecting... -pyxterm.js    -status: connecting... +
-
- -

- built by Chad Smith GitHub -

- - - - - + + + - + - + function debounce(func, wait_ms) { + let timeout; + return function (...args) { + const context = this; + clearTimeout(timeout); + timeout = setTimeout(() => func.apply(context, args), wait_ms); + }; + } - + const wait_ms = 50; + window.onresize = debounce(fitToscreen, wait_ms); + + diff --git a/requirements.in b/requirements.in new file mode 100644 index 0000000..5ecdfe5 --- /dev/null +++ b/requirements.in @@ -0,0 +1 @@ +flask-socketio==5.1.1 \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 582436a..67c5449 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,26 +1,26 @@ # -# This file is autogenerated by pip-compile +# This file is autogenerated by pip-compile with python 3.8 # To update, run: # -# pip-compile +# pip-compile requirements.in # bidict==0.21.2 # via python-socketio -click==7.1.2 +click==8.0.1 # via flask -flask-socketio==5.0.1 - # via pyxtermjs (setup.py) -flask==1.1.2 +flask==2.0.1 # via flask-socketio -itsdangerous==1.1.0 +flask-socketio==5.1.1 + # via -r requirements.in +itsdangerous==2.0.1 # via flask -jinja2==2.11.3 +jinja2==3.0.1 # via flask -markupsafe==1.1.1 +markupsafe==2.0.1 # via jinja2 -python-engineio==4.1.0 +python-engineio==4.2.1 # via python-socketio -python-socketio==5.2.1 +python-socketio==5.4.0 # via flask-socketio -werkzeug==1.0.1 +werkzeug==2.0.1 # via flask diff --git a/setup.py b/setup.py index ac92cbb..5a8b8fa 100644 --- a/setup.py +++ b/setup.py @@ -12,6 +12,7 @@ from typing import List # noqa E402 import ast # noqa E402 import re # noqa E402 +import distutils.text_file CURDIR = Path(__file__).parent @@ -35,7 +36,7 @@ def get_version() -> str: name="pyxtermjs", version=get_version(), author="Chad Smith", - author_email="grassfedcode@gmail.com", + author_email="chadsmith.software@gmail.com", description="interactive terminal in the browser", long_description=README, long_description_content_type="text/markdown", @@ -59,7 +60,9 @@ def get_version() -> str: extras_require={}, zip_safe=False, python_requires=">=3.6", - install_requires=["flask-socketio>=5.0, <6.0"], + install_requires=distutils.text_file.TextFile( + filename="./requirements.txt" + ).readlines(), classifiers=[ "Operating System :: OS Independent", "License :: OSI Approved :: MIT License", From c0ab8eda2a7425e4191758bd34bbe996e6ea44a1 Mon Sep 17 00:00:00 2001 From: Chad Smith Date: Tue, 10 Aug 2021 21:04:40 -0700 Subject: [PATCH 2/5] fix bug --- pyxtermjs/index.html | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/pyxtermjs/index.html b/pyxtermjs/index.html index 7d5b7ba..f912203 100644 --- a/pyxtermjs/index.html +++ b/pyxtermjs/index.html @@ -53,15 +53,15 @@ term.writeln("Welcome to pyxterm.js!"); term.writeln("https://github.com/cs01/pyxterm.js"); term.onData((data) => { - console.log("pressed key", data.input); - socket.emit("pty-input", { input: data.input }); + console.log("new input data", data); + socket.emit("pty-input", { input: data }); }); const socket = io.connect("/pty"); const status = document.getElementById("status"); socket.on("pty-output", function (data) { - console.log("new output", data); + console.log("new output received from server", data); term.write(data.output); }); @@ -78,7 +78,9 @@ function fitToscreen() { fit.fit(); - socket.emit("resize", { cols: term.cols, rows: term.rows }); + const dims = { cols: term.cols, rows: term.rows }; + console.log("sending new dimensions to server's pty", dims); + socket.emit("resize", dims); } function debounce(func, wait_ms) { From 1e6cdd7084296a5d6b12011e566a3c05e34edaf4 Mon Sep 17 00:00:00 2001 From: Chad Smith Date: Tue, 10 Aug 2021 21:25:58 -0700 Subject: [PATCH 3/5] add some additional logging --- README.md | 6 +++++- pyxtermjs/app.py | 25 ++++++++++++++++++------- pyxtermjs/index.html | 4 ++-- 3 files changed, 25 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 507117b..87f04b9 100644 --- a/README.md +++ b/README.md @@ -38,12 +38,16 @@ If you have [nox](https://github.com/theacodes/nox) you can run the following. ``` > nox -s run ``` -Nox takes care of setting up a virtual environment and running the right command for you. +Nox takes care of setting up a virtual environment and running the right command for you. You can pass arguments to the server like this +``` +> nox -s run -- --debug +``` If you don't have nox, you can run the following from inside a virtual environment. ``` > pip install -r requirements.txt > python -m pyxtermjs +> python -m pyxtermjs --debug ``` ### Install diff --git a/pyxtermjs/app.py b/pyxtermjs/app.py index f64c97d..e1c2ee1 100644 --- a/pyxtermjs/app.py +++ b/pyxtermjs/app.py @@ -11,6 +11,7 @@ import fcntl import shlex import logging +import sys logging.getLogger("werkzeug").setLevel(logging.ERROR) @@ -20,10 +21,11 @@ app.config["SECRET_KEY"] = "secret!" app.config["fd"] = None app.config["child_pid"] = None -socketio = SocketIO(app, logger=False, engineio_logger=False) +socketio = SocketIO(app) def set_winsize(fd, row, col, xpix=0, ypix=0): + logging.debug("setting window size with termios") winsize = struct.pack("HHHH", row, col, xpix, ypix) fcntl.ioctl(fd, termios.TIOCSWINSZ, winsize) @@ -51,20 +53,21 @@ def pty_input(data): terminal. """ if app.config["fd"]: - # print("writing to pty: %s" % data["input"]) + logging.debug("received input from browser: %s" % data["input"]) os.write(app.config["fd"], data["input"].encode()) @socketio.on("resize", namespace="/pty") def resize(data): if app.config["fd"]: + logging.debug(f"Resizing window to {data['rows']}x{data['cols']}") set_winsize(app.config["fd"], data["rows"], data["cols"]) @socketio.on("connect", namespace="/pty") def connect(): """new client connected""" - + logging.info("new client connected") if app.config["child_pid"]: # already started child process, don't start another return @@ -83,13 +86,13 @@ def connect(): app.config["child_pid"] = child_pid set_winsize(fd, 50, 50) cmd = " ".join(shlex.quote(c) for c in app.config["cmd"]) - print("child pid is", child_pid) - print( + logging.info("child pid is " + child_pid) + logging.info( f"starting background task with command `{cmd}` to continously read " "and forward pty output to client" ) socketio.start_background_task(target=read_and_forward_pty_output) - print("task started") + logging.info("task started") def main(): @@ -120,8 +123,16 @@ def main(): if args.version: print(__version__) exit(0) - print(f"serving on http://127.0.0.1:{args.port}") app.config["cmd"] = [args.command] + shlex.split(args.cmd_args) + green = "\033[92m" + end = "\033[0m" + log_format = green + "pyxtermjs > " + end + "%(levelname)s (%(funcName)s:%(lineno)s) %(message)s" + logging.basicConfig( + format=log_format, + stream=sys.stdout, + level=logging.DEBUG if args.debug else logging.INFO, + ) + logging.info(f"serving on http://127.0.0.1:{args.port}") socketio.run(app, debug=args.debug, port=args.port, host=args.host) diff --git a/pyxtermjs/index.html b/pyxtermjs/index.html index f912203..f3df3e2 100644 --- a/pyxtermjs/index.html +++ b/pyxtermjs/index.html @@ -53,7 +53,7 @@ term.writeln("Welcome to pyxterm.js!"); term.writeln("https://github.com/cs01/pyxterm.js"); term.onData((data) => { - console.log("new input data", data); + console.log("key pressed in browser:", data); socket.emit("pty-input", { input: data }); }); @@ -61,7 +61,7 @@ const status = document.getElementById("status"); socket.on("pty-output", function (data) { - console.log("new output received from server", data); + console.log("new output received from server:", data.output); term.write(data.output); }); From 32dae68f505dd068efc12c65b3878127026d21ab Mon Sep 17 00:00:00 2001 From: Chad Smith Date: Tue, 10 Aug 2021 21:41:27 -0700 Subject: [PATCH 4/5] fix bug with socketio not starting background task...? --- pyxtermjs/app.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pyxtermjs/app.py b/pyxtermjs/app.py index e1c2ee1..68d534b 100644 --- a/pyxtermjs/app.py +++ b/pyxtermjs/app.py @@ -86,12 +86,15 @@ def connect(): app.config["child_pid"] = child_pid set_winsize(fd, 50, 50) cmd = " ".join(shlex.quote(c) for c in app.config["cmd"]) + # logging/print statements must go after this because... I have no idea why + # but if they come before the background task never starts + socketio.start_background_task(target=read_and_forward_pty_output) + logging.info("child pid is " + child_pid) logging.info( f"starting background task with command `{cmd}` to continously read " "and forward pty output to client" ) - socketio.start_background_task(target=read_and_forward_pty_output) logging.info("task started") From 4fa578509eb9331ff45d89864feb614af6e3cb35 Mon Sep 17 00:00:00 2001 From: Chad Smith Date: Tue, 10 Aug 2021 21:47:01 -0700 Subject: [PATCH 5/5] update link --- pyxtermjs/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyxtermjs/index.html b/pyxtermjs/index.html index f3df3e2..10e178e 100644 --- a/pyxtermjs/index.html +++ b/pyxtermjs/index.html @@ -22,7 +22,7 @@

- built by Chad Smith + built by Chad Smith GitHub