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

behavior with use_rawinput=False differs with cmd #1020

Open
mrherman opened this issue Nov 19, 2020 · 6 comments
Open

behavior with use_rawinput=False differs with cmd #1020

mrherman opened this issue Nov 19, 2020 · 6 comments

Comments

@mrherman
Copy link

I've located a couple things with cmd2 that differ with the standard library cmd. I set stdin and stdout in the init to a file object that is attached to a socket like:

class FirstApp(cmd2.Cmd):
    def __init__(self,fd):
        super().__init__(stdin=fd, stdout=fd)
        self.use_rawinput = False

srv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
srv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
srv.bind(('localhost',9996))
srv.listen(0)
sock_resp, addr_resp = srv.accept()
file = sock_resp.makefile('rw',None)
c = FirstApp(file)
c.cmdloop()

comparing the behavior between cmd2 and cmd by just changing class FirstApp(cmd2.Cmd): to class FirstApp(cmd.Cmd): I see the following changes:

  1. cmd2 doesn't flush its output while cmd does resulting in no output being sent to the socket unless I call file.flush(). cmd does flush it's output while writing to stdout.

  2. cmd2 doesn't write the prompt to it's stdout (the fd), cmd does send the prompt.

For both of the above I think the behavior of cmd is the expected behavior while cmd2 is not. That could be up to opinion though.

As a workaround for number 1 I redefined file.write() to a new function that calls file.write() then file.flush() which seems to work.

@mrherman
Copy link
Author

I think both of the above behaviors is related to that file is not a tty and cmd2 checks isatty() on stdin and doesn't flush or print the prompt if it is not a tty.

The code for checking isatty and printing the prompt is here:

cmd2/cmd2/cmd2.py

Lines 2574 to 2593 in aac467e

# Otherwise read from self.stdin
else:
if self.stdin.isatty():
# on a tty, print the prompt first, then read the line
self.poutput(prompt, end='')
self.stdout.flush()
line = self.stdin.readline()
if len(line) == 0:
line = 'eof'
else:
# we are reading from a pipe, read the line to see if there is
# anything there, if so, then decide whether to print the
# prompt or not
line = self.stdin.readline()
if len(line):
# we read something, output the prompt and the something
if self.echo:
self.poutput('{}{}'.format(prompt, line))
else:
line = 'eof'

A workaround is that I can trick cmd2 by making file.isatty() return true. Not sure if this has any unintended side effects yet. I guess the question becomes is this the desired behavior of cmd2, should some options be made to set the desired behavior?

@kmvanbrunt
Copy link
Member

When input isn't coming from a tty, the prompt and input line are displayed only if self.echo is True.

@mrherman
Copy link
Author

echoing the prompt/command is different than displaying the prompt (the former comes after the command is entered and the later before the command is entered). In the case I presented above I can telnet in to the socket to interact with cmd2, but I don't get a prompt. If I turn echo on, I still don't get a prompt, but after I type the command I'll see the prompt/command displayed.

Maybe I am approaching connecting to cmd through a socket the wrong way, instead need to find a way to connect to it with a tty which would solve this for me at least.

@tleonhardt
Copy link
Member

@mrherman Did you ever find a solution to your problem?

@mrherman
Copy link
Author

Only sort of. I open a socket and makefile from the socket_response. I then change the file descriptor returned so that isatty() returns true and then pass that in as stdin and stdout to the cmd2 init. Changing isatty() to return true is might have repercussions I haven't foreseen yet, but it does give the expected behavior from CMD2 that I wanted to see.

I think the right approach would be to add an additional option to force the code a I included in the comment above to print the prompt on a non-tty connection.

@Layty
Copy link

Layty commented Jan 5, 2024

@mrherman can you show your demo ?

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

No branches or pull requests

4 participants