Refactor read with timeout logic into its own function

This commit is contained in:
Kovid Goyal 2018-01-07 15:50:19 +05:30
parent f3cb68ee40
commit 1f976644bf
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
2 changed files with 31 additions and 22 deletions

View File

@ -7,22 +7,20 @@ import fcntl
import mimetypes import mimetypes
import os import os
import re import re
import selectors
import signal import signal
import struct import struct
import subprocess import subprocess
import sys import sys
import termios import termios
import tty
import zlib import zlib
from base64 import standard_b64encode from base64 import standard_b64encode
from collections import namedtuple from collections import namedtuple
from math import ceil, floor from math import ceil, floor
from tempfile import NamedTemporaryFile from tempfile import NamedTemporaryFile
from time import monotonic
from kitty.constants import appname from kitty.constants import appname
from kitty.cli import parse_args from kitty.cli import parse_args
from kitty.utils import read_with_timeout
try: try:
fsenc = sys.getfilesystemencoding() or 'utf-8' fsenc = sys.getfilesystemencoding() or 'utf-8'
@ -261,17 +259,11 @@ def scan(d):
def detect_support(wait_for=10, silent=False): def detect_support(wait_for=10, silent=False):
fd = sys.stdin.fileno()
old = termios.tcgetattr(fd)
oldfl = fcntl.fcntl(fd, fcntl.F_GETFL)
fcntl.fcntl(fd, fcntl.F_SETFL, oldfl | os.O_NONBLOCK)
if not silent: if not silent:
print('Checking for graphics ({}s max. wait)...'.format(wait_for), end='\r') print('Checking for graphics ({}s max. wait)...'.format(wait_for), end='\r')
sys.stdout.flush() sys.stdout.flush()
tty.setraw(fd)
try: try:
received = b'' received = b''
start_time = monotonic()
responses = {} responses = {}
def parse_responses(): def parse_responses():
@ -282,29 +274,20 @@ def detect_support(wait_for=10, silent=False):
if iid not in responses: if iid not in responses:
responses[iid] = m.group(2) == b'OK' responses[iid] = m.group(2) == b'OK'
def read(): def more_needed(data):
nonlocal received nonlocal received
d = sys.stdin.buffer.read() received += data
if not d: # EOF
responses[1] = responses[2] = False
return
received += d
parse_responses() parse_responses()
return 1 not in responses or 2 not in responses
with NamedTemporaryFile() as f: with NamedTemporaryFile() as f:
f.write(b'abcd'), f.flush() f.write(b'abcd'), f.flush()
write_gr_cmd(dict(a='q', s=1, v=1, i=1), standard_b64encode(b'abcd')) write_gr_cmd(dict(a='q', s=1, v=1, i=1), standard_b64encode(b'abcd'))
write_gr_cmd(dict(a='q', s=1, v=1, i=2, t='f'), standard_b64encode(f.name.encode(fsenc))) write_gr_cmd(dict(a='q', s=1, v=1, i=2, t='f'), standard_b64encode(f.name.encode(fsenc)))
sel = selectors.DefaultSelector() read_with_timeout(more_needed, timeout=wait_for)
sel.register(sys.stdin, selectors.EVENT_READ, read)
while monotonic() - start_time < wait_for and 1 not in responses and 2 not in responses:
for key, mask in sel.select(0.1):
read()
finally: finally:
if not silent: if not silent:
sys.stdout.buffer.write(b'\033[J'), sys.stdout.flush() sys.stdout.buffer.write(b'\033[J'), sys.stdout.flush()
termios.tcsetattr(fd, termios.TCSADRAIN, old)
fcntl.fcntl(fd, fcntl.F_SETFL, oldfl)
detect_support.has_files = bool(responses.get(2)) detect_support.has_files = bool(responses.get(2))
return responses.get(1, False) return responses.get(1, False)

View File

@ -12,6 +12,7 @@ import shlex
import socket import socket
import string import string
import subprocess import subprocess
import sys
import tempfile import tempfile
from contextlib import contextmanager from contextlib import contextmanager
from functools import lru_cache from functools import lru_cache
@ -264,3 +265,28 @@ def single_instance(group_id=None):
s.set_inheritable(False) s.set_inheritable(False)
atexit.register(remove_socket_file, s) atexit.register(remove_socket_file, s)
return True return True
def read_with_timeout(more_needed, timeout=10, src=sys.stdin):
import termios
import tty
import fcntl
import select
fd = src.fileno()
old = termios.tcgetattr(fd)
oldfl = fcntl.fcntl(fd, fcntl.F_GETFL)
fcntl.fcntl(fd, fcntl.F_SETFL, oldfl | os.O_NONBLOCK)
tty.setraw(fd)
start_time = monotonic()
try:
while timeout > monotonic() - start_time:
rd = select.select([fd], [], [], max(0, timeout - (monotonic() - start_time)))[0]
if rd:
data = sys.stdin.buffer.read()
if not data:
break # eof
if not more_needed(data):
break
finally:
termios.tcsetattr(fd, termios.TCSADRAIN, old)
fcntl.fcntl(fd, fcntl.F_SETFL, oldfl)