-
Notifications
You must be signed in to change notification settings - Fork 12
Decode stdout using preferred encoding not ascii, and combine multibyte as necessary #13
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -29,6 +29,7 @@ | |
|
|
||
| import errno | ||
| import fcntl | ||
| import locale | ||
| import os | ||
| import select | ||
| import signal | ||
|
|
@@ -102,10 +103,12 @@ def write(self, buffer): | |
| else: | ||
| telnetlib.Telnet.write(self, buffer) | ||
|
|
||
| def interact(self): | ||
| def interact(self, encoding=None): | ||
| encoding = encoding or locale.getpreferredencoding() | ||
| self.set_raw_mode() | ||
| try: | ||
| self.updateTerminalSize() | ||
| remaining_text = b"" | ||
| while not self.eof: | ||
| readyWriters = [] | ||
| readyReaders = [] | ||
|
|
@@ -143,13 +146,25 @@ def interact(self): | |
| print('*** Connection closed by remote host ***') | ||
| break | ||
| if text: | ||
| sys.stdout.write(text.decode('ascii')) | ||
| all_text = remaining_text + text | ||
| try: | ||
| unicode_text = all_text.decode(encoding) | ||
| remaining_text = b"" | ||
| except UnicodeDecodeError as e: | ||
| assert e.start < 0, f"Got an unexpected negative start for unicode: {e.start}" | ||
| unicode_text = all_text[:e.start].decode(encoding) | ||
| remaining_text = all_text[e.start:] | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am sorry, i now see i had added my comment on the wrong line. Here, remaining_text gets reinitialized with a slice from all_text. If e.start is 0 and the first char is not a valid Unicode start sequence, then remaining_text will be appended to, but will always fail to decode, which, if I am right, leads to the infinite loop. Just re-raising the exception if e.start <= 0 should be safe i think
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I just had to use this patch again to realize that we never finished this PR. For e.start < 0 - I accepted my own assertion above since I think it should simply never happen. For e.start == 0 -- I think it is unlikely but legit case whenever we read only few bytes which are beginning of an incomplete unicode. Then we just store it all and append to next block -- I do not see how we could get an infinite loop here since we are not adding any looping and should exit at eof (would still do) ... the only thing would be left is at the end to assert that we have no remaining_text left -- as if incomplete unicode at the end was provided and we failed to decode it. I will add a stab for that. |
||
| sys.stdout.write(unicode_text) | ||
| sys.stdout.flush() | ||
| if sys.stdin in readyReaders and self in readyWriters: | ||
| line = sys.stdin.read(4096) | ||
| if not line: | ||
| break | ||
| self.write(line.encode('ascii')) | ||
| self.write(line.encode(encoding)) | ||
yarikoptic marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| if remaining_text: | ||
| # trying to decode remaining text which should fail and raise exception | ||
| # but that would be just what it is -- there was a non-decodable remainder | ||
| sys.stdout.write(remaining_text.decode(encoding)) | ||
| finally: | ||
| self.restore_terminal() | ||
|
|
||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.