Skip to content

Commit

Permalink
2 new tools: display-{fpathconf.maxcanon}.py
Browse files Browse the repository at this point in the history
tests/test_maxcanon.py has been deleted and turned into
an "autodetection" tool of sorts, no longer attempting
to assert exacting values, but determine it programmatically.
  • Loading branch information
jquast committed Oct 6, 2015
1 parent 0b7fee3 commit ae932d1
Show file tree
Hide file tree
Showing 4 changed files with 128 additions and 186 deletions.
14 changes: 7 additions & 7 deletions pexpect/pty_spawn.py
Original file line number Diff line number Diff line change
Expand Up @@ -492,9 +492,9 @@ def send(self, s):
This value may be discovered using fpathconf(3)::
>>> from os import fpathconf
>>> print(fpathconf(0, 'PC_MAX_CANON'))
256
>>> from os import fpathconf
>>> print(fpathconf(0, 'PC_MAX_CANON'))
256
On such a system, only 256 bytes may be received per line. Any
subsequent bytes received will be discarded. BEL (``'\a'``) is then
Expand All @@ -505,10 +505,10 @@ def send(self, s):
Canonical input processing may be disabled altogether by executing
a shell, then stty(1), before executing the final program::
>>> bash = pexpect.spawn('/bin/bash', echo=False)
>>> bash.sendline('stty -icanon')
>>> bash.sendline('base64')
>>> bash.sendline('x' * 5000)
>>> bash = pexpect.spawn('/bin/bash', echo=False)
>>> bash.sendline('stty -icanon')
>>> bash.sendline('base64')
>>> bash.sendline('x' * 5000)
'''

time.sleep(self.delaybeforesend)
Expand Down
179 changes: 0 additions & 179 deletions tests/test_maxcanon.py

This file was deleted.

41 changes: 41 additions & 0 deletions tools/display-fpathconf.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#!/usr/bin/env python
"""Displays os.fpathconf values related to terminals. """
from __future__ import print_function
import sys
import os


def display_fpathconf():
DISP_VALUES = (
('PC_MAX_CANON', ('Max no. of bytes in a '
'terminal canonical input line.')),
('PC_MAX_INPUT', ('Max no. of bytes for which '
'space is available in a terminal input queue.')),
('PC_PIPE_BUF', ('Max no. of bytes which will '
'be written atomically to a pipe.')),
('PC_VDISABLE', 'Terminal character disabling value.')
)
FMT = '{name:<13} {value:<5} {description}'

# column header
print(FMT.format(name='name', value='value', description='description'))
print(FMT.format(name=('-' * 13), value=('-' * 5), description=('-' * 11)))

fd = sys.stdin.fileno()
for name, description in DISP_VALUES:
key = os.pathconf_names.get(name, None)
if key is None:
value = 'UNDEF'
else:
try:
value = os.fpathconf(fd, name)
except OSError as err:
value = 'OSErrno {0.errno}'.format(err)
if name == 'PC_VDISABLE':
value = hex(value)
print(FMT.format(name=name, value=value, description=description))
print()


if __name__ == '__main__':
display_fpathconf()
80 changes: 80 additions & 0 deletions tools/display-maxcanon.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
#!/usr/bin/env python
"""
This tool uses pexpect to test expected Canonical mode length.
All systems use the value of MAX_CANON which can be found using
fpathconf(3) value PC_MAX_CANON -- with the exception of Linux
and FreeBSD.
Linux, though defining a value of 255, actually honors the value
of 4096 from linux kernel include file tty.h definition
N_TTY_BUF_SIZE.
Linux also does not honor IMAXBEL. termios(3) states, "Linux does not
implement this bit, and acts as if it is always set." Although these
tests ensure it is enabled, this is a non-op for Linux.
FreeBSD supports neither, and instead uses a fraction (1/5) of the tty
speed which is always 9600. Therefor, the maximum limited input line
length is 9600 / 5 = 1920.
These tests only ensure the correctness of the behavior described by
the sendline() docstring -- the values listed there, and above should
be equal to the output of the given OS described, but no promises!
"""
# std import
from __future__ import print_function
import sys
import os


def detect_maxcanon():
import pexpect
bashrc = os.path.join(
# re-use pexpect/replwrap.py's bashrc file,
os.path.dirname(__file__), os.path.pardir, 'pexpect', 'bashrc.sh')

child = pexpect.spawn('bash', ['--rcfile', bashrc],
echo=True, encoding='utf8', timeout=3)

child.sendline(u'echo -n READY_; echo GO')
child.expect_exact(u'READY_GO')

child.sendline(u'stty icanon imaxbel erase ^H; echo -n retval: $?')
child.expect_exact(u'retval: 0')

child.sendline(u'echo -n GO_; echo AGAIN')
child.expect_exact(u'GO_AGAIN')
child.sendline(u'cat')

child.delaybeforesend = 0

column, blocksize = 0, 64
ch_marker = u'_'

print('auto-detecting MAX_CANON: ', end='')
sys.stdout.flush()

while True:
child.send(ch_marker * blocksize)
result = child.expect([ch_marker * blocksize, u'\a'])
if result == 0:
# entire block fit without emitting bel
column += blocksize
elif result == 1:
# an '\a' was emitted, count the number of ch_markers
# found since last blocksize, determining our MAX_CANON
column += child.before.count(ch_marker)
break
print(column)

if __name__ == '__main__':
try:
detect_maxcanon()
except ImportError:
# we'd like to use this with CI -- but until we integrate
# with tox, we can't determine a period in testing when
# the pexpect module has been installed
print('warning: pexpect not in module path, MAX_CANON '
'could not be determined by systems test.',
file=sys.stderr)

0 comments on commit ae932d1

Please sign in to comment.