Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add REPL command #425

Closed
wants to merge 1 commit into from
Closed

Add REPL command #425

wants to merge 1 commit into from

Conversation

meeuw
Copy link

@meeuw meeuw commented Jul 4, 2021

I'd like to use ykman without restarting it everytime, it is possible to import import ykman.cli.__main__ and call ykman.cli.__main__.cli.main but then ykman messes with your log handlers etc. I figured it might be better to add a REPL option to ykman so ykman keeps running and you can send queries over stdin.

This script can be used as a proof of concept for this PR:

import subprocess
import time
import json
import sys

p = subprocess.Popen(
    ["ykman", "repl"],
    stdin=subprocess.PIPE,
    stdout=subprocess.PIPE,
    universal_newlines=True,
    bufsize=1,
)

while 1:
    p.stdin.write(json.dumps(["oath", "accounts", "code"]) + "\n")
    print(json.loads(p.stdout.readline())["stdout"][0])
    time.sleep(1)

This is a bit of a hack and might require a recent Python version (I'm using 3.9). For my use case JSON input/output is very useful, as a stand alone REPL python-prompt-toolkit might be better (or another readline implementation).

Please let me know what's required to get this merged in main.

@emlun
Copy link
Member

emlun commented Jul 13, 2021

Sorry, I don't think we want to commit to supporting something like this at this time. But you can still do this as a standalone application:

#!/usr/bin/python3

import contextlib
import io
import json
from ykman.cli.__main__ import cli

"""
Enter commands as REPL (formatted as JSON)
"""


while 1:
    line = input()
    if not line:
        break
    stdout = io.StringIO()
    stderr = io.StringIO()
    try:
        with contextlib.redirect_stderr(stderr), contextlib.redirect_stdout(stdout):
            cli.main(args=json.loads(line))
    except SystemExit:
        pass
    print(
        json.dumps(
            {
                "stdout": stdout.getvalue().splitlines(),
                "stderr": stderr.getvalue().splitlines(),
            }
        ),
        flush=True,
    )

Just note that we don't generally promise to keep text output stable for programmatic consumption, with a few exceptions like the --single option to oath accounts code.

@meeuw
Copy link
Author

meeuw commented Jul 15, 2021

Thanks a lot for your response @emlun! I figured that already. Very famliar snippet :-)

https://github.com/meeuw/yubikey-manager-lib/blob/master/yubikey_manager_repl.py

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants