summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff Quast <contact@jeffquast.com>2015-01-04 00:12:29 -0800
committerJeff Quast <contact@jeffquast.com>2015-01-04 00:12:29 -0800
commitecda1a296838ad696ec47dac0370e488c191c917 (patch)
treeceac3e730c66470d799ec4dbd79fb97d49f75374
parent9de69f600c0f928cd2f9f3561b282270cd73d4d5 (diff)
parente0111c8657ffbab53c65fe83ef5189a5926fa909 (diff)
downloadblessings-ecda1a296838ad696ec47dac0370e488c191c917.tar.gz
Merge pull request #40 from jquast/test-a-whole-lotta-terms
Use toe(1) to test wide variety of terminal types
-rw-r--r--.prospector.yaml2
-rw-r--r--README.rst4
-rw-r--r--blessed/_binterms.py872
-rw-r--r--blessed/sequences.py14
-rw-r--r--blessed/terminal.py24
-rw-r--r--blessed/tests/accessories.py52
-rw-r--r--blessed/tests/test_core.py4
-rw-r--r--blessed/tests/test_keyboard.py25
-rw-r--r--blessed/tests/test_length_sequence.py11
-rw-r--r--blessed/tests/test_sequences.py86
-rw-r--r--blessed/tests/test_wrap.py148
-rw-r--r--tox.ini8
12 files changed, 1036 insertions, 214 deletions
diff --git a/.prospector.yaml b/.prospector.yaml
index 3ccfbda..83c0c35 100644
--- a/.prospector.yaml
+++ b/.prospector.yaml
@@ -29,8 +29,6 @@ pep257:
pep8:
# style checking
run: true
- options:
- max-line-length: 100
pyflakes:
# preferring 'frosted' instead (a fork of)
diff --git a/README.rst b/README.rst
index 7949ded..e3c9a42 100644
--- a/README.rst
+++ b/README.rst
@@ -2,9 +2,9 @@
:alt: Travis Continous Integration
:target: https://travis-ci.org/jquast/blessed
-.. image:: https://img.shields.io/coveralls/jquast/blessed.svg
+.. image:: https://coveralls.io/repos/jquast/blessed/badge.png?branch=master
:alt: Coveralls Code Coverage
- :target: https://coveralls.io/r/jquast/blessed
+ :target: https://coveralls.io/r/jquast/blessed?branch=master
.. image:: https://img.shields.io/pypi/v/blessed.svg
:alt: Latest Version
diff --git a/blessed/_binterms.py b/blessed/_binterms.py
new file mode 100644
index 0000000..84f58fe
--- /dev/null
+++ b/blessed/_binterms.py
@@ -0,0 +1,872 @@
+""" Exports a list of binary terminals blessed is not able to cope with. """
+#: This list of terminals is manually managed, it describes all of the terminals
+#: that blessed cannot measure the sequence length for; they contain
+#: binary-packed capabilities instead of numerics, so it is not possible to
+#: build regular expressions in the way that sequences.py does.
+#:
+#: This may be generated by exporting TEST_BINTERMS, then analyzing the
+#: jUnit result xml written to the project folder.
+binary_terminals = u"""
+9term
+aaa+dec
+aaa+rv
+aaa+rv-100
+aaa+rv-30
+aaa-rv-unk
+abm80
+abm85
+abm85e
+abm85h
+abm85h-old
+act4
+act5
+addrinfo
+adds980
+adm+sgr
+adm+sgr-100
+adm+sgr-30
+adm11
+adm1178
+adm12
+adm1a
+adm2
+adm20
+adm21
+adm22
+adm3
+adm31
+adm31-old
+adm3a
+adm3a+
+adm42
+adm42-ns
+adm5
+aepro
+aj510
+aj830
+alto-h19
+altos4
+altos7
+altos7pc
+ampex175
+ampex175-b
+ampex210
+ampex232
+ampex232w
+ampex80
+annarbor4080
+ansi+arrows
+ansi+csr
+ansi+cup
+ansi+enq
+ansi+erase
+ansi+idc
+ansi+idl
+ansi+idl1
+ansi+inittabs
+ansi+local
+ansi+local1
+ansi+pp
+ansi+rca
+ansi+rep
+ansi+sgr
+ansi+sgrbold
+ansi+sgrdim
+ansi+sgrso
+ansi+sgrul
+ansi+tabs
+ansi-color-2-emx
+ansi-color-3-emx
+ansi-emx
+ansi-mini
+ansi-mr
+ansi-mtabs
+ansi-nt
+ansi.sys
+ansi.sys-old
+ansi.sysk
+ansi77
+apollo
+apple-80
+apple-ae
+apple-soroc
+apple-uterm
+apple-uterm-vb
+apple-videx
+apple-videx2
+apple-videx3
+apple-vm80
+apple2e
+apple2e-p
+apple80p
+appleII
+appleIIgs
+atari
+att4415+nl
+att4420
+att4424m
+att5310
+att5310-100
+att5310-30
+att5620-s
+avatar
+avatar0
+avatar0+
+avt+s
+aws
+awsc
+bantam
+basis
+beacon
+beehive
+blit
+bq300-8
+bq300-8-pc
+bq300-8-pc-rv
+bq300-8-pc-w
+bq300-8-pc-w-rv
+bq300-8rv
+bq300-8w
+bq300-w-8rv
+c100
+c100-rv
+c108
+c108-4p
+c108-rv
+c108-rv-4p
+c108-w
+ca22851
+cbblit
+cbunix
+cci
+cci-100
+cci-30
+cdc456
+cdc721
+cdc721-esc
+cdc721-esc-100
+cdc721-esc-30
+cdc721ll
+cdc752
+cdc756
+cit101e
+cit101e-132
+cit101e-n
+cit101e-n132
+cit80
+citoh
+citoh-6lpi
+citoh-8lpi
+citoh-comp
+citoh-elite
+citoh-pica
+citoh-prop
+coco3
+color_xterm
+commodore
+contel300
+contel301
+cops10
+ct8500
+ctrm
+ctrm-100
+ctrm-30
+cyb110
+cyb83
+d132
+d200
+d200-100
+d200-30
+d210-dg
+d210-dg-100
+d210-dg-30
+d211-dg
+d211-dg-100
+d211-dg-30
+d216-dg
+d216-dg-100
+d216-dg-30
+d216-unix
+d216-unix-25
+d217-unix
+d217-unix-25
+d220
+d220-100
+d220-30
+d220-7b
+d220-7b-100
+d220-7b-30
+d220-dg
+d220-dg-100
+d220-dg-30
+d230c
+d230c-100
+d230c-30
+d230c-dg
+d230c-dg-100
+d230c-dg-30
+d400
+d400-100
+d400-30
+d410-dg
+d410-dg-100
+d410-dg-30
+d412-dg
+d412-dg-100
+d412-dg-30
+d412-unix
+d412-unix-25
+d412-unix-s
+d412-unix-sr
+d412-unix-w
+d413-unix
+d413-unix-25
+d413-unix-s
+d413-unix-sr
+d413-unix-w
+d414-unix
+d414-unix-25
+d414-unix-s
+d414-unix-sr
+d414-unix-w
+d430c-dg
+d430c-dg-100
+d430c-dg-30
+d430c-dg-ccc
+d430c-dg-ccc-100
+d430c-dg-ccc-30
+d430c-unix
+d430c-unix-100
+d430c-unix-25
+d430c-unix-25-100
+d430c-unix-25-30
+d430c-unix-25-ccc
+d430c-unix-30
+d430c-unix-ccc
+d430c-unix-s
+d430c-unix-s-ccc
+d430c-unix-sr
+d430c-unix-sr-ccc
+d430c-unix-w
+d430c-unix-w-ccc
+d470c
+d470c-7b
+d470c-dg
+d555-dg
+d577-dg
+d800
+delta
+dg+ccc
+dg+color
+dg+color8
+dg+fixed
+dg-generic
+dg200
+dg210
+dg211
+dg450
+dg460-ansi
+dg6053
+dg6053-old
+dgkeys+11
+dgkeys+15
+dgkeys+7b
+dgkeys+8b
+dgmode+color
+dgmode+color8
+dgunix+ccc
+dgunix+fixed
+diablo1620
+diablo1620-m8
+diablo1640
+diablo1640-lm
+diablo1740-lm
+digilog
+djgpp203
+dm1520
+dm2500
+dm3025
+dm3045
+dmchat
+dmterm
+dp8242
+dt100
+dt100w
+dt110
+dt80-sas
+dtc300s
+dtc382
+dumb
+dw1
+dw2
+dw3
+dw4
+dwk
+ecma+color
+ecma+sgr
+elks
+elks-glasstty
+elks-vt52
+emu
+ep40
+ep48
+esprit
+esprit-am
+ex155
+f100
+f100-rv
+f110
+f110-14
+f110-14w
+f110-w
+f200
+f200-w
+f200vi
+f200vi-w
+falco
+falco-p
+fos
+fox
+gator-52
+gator-52t
+glasstty
+gnome
+gnome+pcfkeys
+gnome-2007
+gnome-2008
+gnome-256color
+gnome-fc5
+gnome-rh72
+gnome-rh80
+gnome-rh90
+go140
+go140w
+gs6300
+gsi
+gt40
+gt42
+guru+rv
+guru+s
+h19
+h19-bs
+h19-g
+h19-u
+h19-us
+h19k
+ha8675
+ha8686
+hft-old
+hmod1
+hp+arrows
+hp+color
+hp+labels
+hp+pfk+arrows
+hp+pfk+cr
+hp+pfk-cr
+hp+printer
+hp2
+hp236
+hp262x
+hp2641a
+hp300h
+hp700-wy
+hp70092
+hp9837
+hp9845
+hpterm
+hpterm-color
+hz1000
+hz1420
+hz1500
+hz1510
+hz1520
+hz1520-noesc
+hz1552
+hz1552-rv
+hz2000
+i100
+i400
+ibcs2
+ibm+16color
+ibm+color
+ibm-apl
+ibm-system1
+ibm3101
+ibm3151
+ibm3161
+ibm3161-C
+ibm3162
+ibm3164
+ibm327x
+ibm5081-c
+ibm8514-c
+ibmaed
+ibmapa8c
+ibmapa8c-c
+ibmega
+ibmega-c
+ibmmono
+ibmvga
+ibmvga-c
+icl6404
+icl6404-w
+ifmr
+ims-ansi
+ims950
+ims950-b
+ims950-rv
+intertube
+intertube2
+intext
+intext2
+kaypro
+kermit
+kermit-am
+klone+acs
+klone+color
+klone+koi8acs
+klone+sgr
+klone+sgr-dumb
+klone+sgr8
+konsole
+konsole+pcfkeys
+konsole-16color
+konsole-256color
+konsole-base
+konsole-linux
+konsole-solaris
+konsole-vt100
+konsole-vt420pc
+konsole-xf3x
+konsole-xf4x
+kt7
+kt7ix
+ln03
+ln03-w
+lpr
+luna
+megatek
+mgterm
+microb
+mime
+mime-fb
+mime-hb
+mime2a
+mime2a-s
+mime314
+mime3a
+mime3ax
+minitel1
+minitel1b
+mlterm+pcfkeys
+mm340
+modgraph2
+msk227
+msk22714
+msk227am
+mt70
+ncr160vppp
+ncr160vpwpp
+ncr160wy50+pp
+ncr160wy50+wpp
+ncr160wy60pp
+ncr160wy60wpp
+ncr260vppp
+ncr260vpwpp
+ncr260wy325pp
+ncr260wy325wpp
+ncr260wy350pp
+ncr260wy350wpp
+ncr260wy50+pp
+ncr260wy50+wpp
+ncr260wy60pp
+ncr260wy60wpp
+ncr7900i
+ncr7900iv
+ncr7901
+ncrvt100an
+ncrvt100wan
+ndr9500
+ndr9500-25
+ndr9500-25-mc
+ndr9500-25-mc-nl
+ndr9500-25-nl
+ndr9500-mc
+ndr9500-mc-nl
+ndr9500-nl
+nec5520
+newhpkeyboard
+nextshell
+northstar
+nsterm+c
+nsterm+c41
+nsterm+s
+nwp511
+oblit
+oc100
+oldpc3
+origpc3
+osborne
+osborne-w
+osexec
+otek4112
+owl
+p19
+pc-coherent
+pc-venix
+pc6300plus
+pcix
+pckermit
+pckermit120
+pe1251
+pe7000c
+pe7000m
+pilot
+pmcons
+prism2
+prism4
+prism5
+pro350
+psterm-fast
+psterm-fast-100
+psterm-fast-30
+pt100
+pt210
+pt250
+pty
+qansi
+qansi-g
+qansi-m
+qansi-t
+qansi-w
+qdss
+qnx
+qnx-100
+qnx-30
+qnxm
+qnxm-100
+qnxm-30
+qnxt
+qnxt-100
+qnxt-30
+qnxt2
+qnxtmono
+qnxtmono-100
+qnxtmono-30
+qnxw
+qnxw-100
+qnxw-30
+qume5
+qvt101
+qvt101+
+qvt102
+qvt119+
+qvt119+-25
+qvt119+-25-w
+qvt119+-w
+rbcomm
+rbcomm-nam
+rbcomm-w
+rca
+regent100
+regent20
+regent25
+regent40
+regent40+
+regent60
+rt6221
+rt6221-w
+rtpc
+rxvt+pcfkeys
+scanset
+screen+fkeys
+screen-16color
+screen-16color-bce
+screen-16color-bce-s
+screen-16color-s
+screen-256color
+screen-256color-bce
+screen-256color-bce-s
+screen-256color-s
+screen-bce
+screen-s
+screen-w
+screen.linux
+screen.rxvt
+screen.teraterm
+screen.xterm-r6
+screen2
+screen3
+screwpoint
+sibo
+simterm
+soroc120
+soroc140
+st52
+superbee-xsb
+superbeeic
+superbrain
+swtp
+synertek
+t10
+t1061
+t1061f
+t3700
+t3800
+tandem6510
+tandem653
+tandem653-100
+tandem653-30
+tek
+tek4013
+tek4014
+tek4014-sm
+tek4015
+tek4015-sm
+tek4023
+tek4105
+tek4107
+tek4113-nd
+tek4205
+tek4205-100
+tek4205-30
+tek4207-s
+teraterm
+teraterm2.3
+teraterm4.59
+terminet1200
+ti700
+ti931
+trs16
+trs2
+tt
+tty33
+tty37
+tty43
+tvi803
+tvi9065
+tvi910
+tvi910+
+tvi912
+tvi912b
+tvi912b+2p
+tvi912b+dim
+tvi912b+dim-100
+tvi912b+dim-30
+tvi912b+mc
+tvi912b+mc-100
+tvi912b+mc-30
+tvi912b+printer
+tvi912b+vb
+tvi912b-2p
+tvi912b-2p-mc
+tvi912b-2p-mc-100
+tvi912b-2p-mc-30
+tvi912b-2p-p
+tvi912b-2p-unk
+tvi912b-mc
+tvi912b-mc-100
+tvi912b-mc-30
+tvi912b-p
+tvi912b-unk
+tvi912b-vb
+tvi912b-vb-mc
+tvi912b-vb-mc-100
+tvi912b-vb-mc-30
+tvi912b-vb-p
+tvi912b-vb-unk
+tvi920b
+tvi920b+fn
+tvi920b-2p
+tvi920b-2p-mc
+tvi920b-2p-mc-100
+tvi920b-2p-mc-30
+tvi920b-2p-p
+tvi920b-2p-unk
+tvi920b-mc
+tvi920b-mc-100
+tvi920b-mc-30
+tvi920b-p
+tvi920b-unk
+tvi920b-vb
+tvi920b-vb-mc
+tvi920b-vb-mc-100
+tvi920b-vb-mc-30
+tvi920b-vb-p
+tvi920b-vb-unk
+tvi921
+tvi924
+tvi925
+tvi925-hi
+tvi92B
+tvi92D
+tvi950
+tvi950-2p
+tvi950-4p
+tvi950-rv
+tvi950-rv-2p
+tvi950-rv-4p
+tvipt
+unknown
+vanilla
+vc303
+vc404
+vc404-s
+vc414
+vc415
+vi200
+vi200-f
+vi200-rv
+vi50
+vi500
+vi50adm
+vi55
+viewpoint
+vp3a+
+vp60
+vp90
+vremote
+vt100+enq
+vt100+fnkeys
+vt100+keypad
+vt100+pfkeys
+vt100-s
+vt102+enq
+vt200-js
+vt220+keypad
+vt50h
+vt52
+vt61
+wsiris
+wy100
+wy100q
+wy120
+wy120-25
+wy120-vb
+wy160
+wy160-25
+wy160-42
+wy160-43
+wy160-tek
+wy160-tek-100
+wy160-tek-30
+wy160-vb
+wy30
+wy30-mc
+wy30-mc-100
+wy30-mc-30
+wy30-vb
+wy325
+wy325-25
+wy325-42
+wy325-43
+wy325-vb
+wy350
+wy350-100
+wy350-30
+wy350-vb
+wy350-vb-100
+wy350-vb-30
+wy350-w
+wy350-w-100
+wy350-w-30
+wy350-wvb
+wy350-wvb-100
+wy350-wvb-30
+wy370
+wy370-100
+wy370-105k
+wy370-105k-100
+wy370-105k-30
+wy370-30
+wy370-EPC
+wy370-EPC-100
+wy370-EPC-30
+wy370-nk
+wy370-nk-100
+wy370-nk-30
+wy370-rv
+wy370-rv-100
+wy370-rv-30
+wy370-tek
+wy370-tek-100
+wy370-tek-30
+wy370-vb
+wy370-vb-100
+wy370-vb-30
+wy370-w
+wy370-w-100
+wy370-w-30
+wy370-wvb
+wy370-wvb-100
+wy370-wvb-30
+wy50
+wy50-mc
+wy50-mc-100
+wy50-mc-30
+wy50-vb
+wy60
+wy60-25
+wy60-42
+wy60-43
+wy60-vb
+wy99-ansi
+wy99a-ansi
+wy99f
+wy99fa
+wy99gt
+wy99gt-25
+wy99gt-vb
+wy99gt-tek
+wyse-vp
+xerox1720
+xerox820
+xfce
+xnuppc+100x37
+xnuppc+112x37
+xnuppc+128x40
+xnuppc+128x48
+xnuppc+144x48
+xnuppc+160x64
+xnuppc+200x64
+xnuppc+200x75
+xnuppc+256x96
+xnuppc+80x25
+xnuppc+80x30
+xnuppc+90x30
+xnuppc+c
+xnuppc+c-100
+xnuppc+c-30
+xtalk
+xtalk-100
+xtalk-30
+xterm+256color
+xterm+256color-100
+xterm+256color-30
+xterm+88color
+xterm+88color-100
+xterm+88color-30
+xterm+app
+xterm+edit
+xterm+noapp
+xterm+pc+edit
+xterm+pcc0
+xterm+pcc1
+xterm+pcc2
+xterm+pcc3
+xterm+pce2
+xterm+pcf0
+xterm+pcf2
+xterm+pcfkeys
+xterm+r6f2
+xterm+vt+edit
+xterm-vt52
+z100
+z100bw
+z29
+zen30
+zen50
+ztx
+""".split()
+
+__all__ = ('binary_terminals',)
diff --git a/blessed/sequences.py b/blessed/sequences.py
index 2447e53..2862197 100644
--- a/blessed/sequences.py
+++ b/blessed/sequences.py
@@ -14,12 +14,15 @@ import math
import sys
import re
+# local
+from ._binterms import binary_terminals as _BINTERM_UNSUPPORTED
+
# 3rd-party
import wcwidth # https://github.com/jquast/wcwidth
-_BINTERM_UNSUPPORTED = ('kermit', 'avatar')
-_BINTERM_UNSUPPORTED_MSG = ('sequence-awareness for terminals emitting '
- 'binary-packed capabilities are not supported.')
+_BINTERM_UNSUPPORTED_MSG = (
+ u"Terminal kind {0!r} contains binary-packed capabilities, blessed "
+ u"is likely to fail to measure the length of its sequences.")
if sys.version_info[0] == 3:
text_type = str
@@ -263,7 +266,7 @@ def init_sequence_patterns(term):
printable length of a string.
"""
if term.kind in _BINTERM_UNSUPPORTED:
- warnings.warn(_BINTERM_UNSUPPORTED_MSG)
+ warnings.warn(_BINTERM_UNSUPPORTED_MSG.format(term.kind))
# Build will_move, a list of terminal capabilities that have
# indeterminate effects on the terminal cursor position.
@@ -322,9 +325,6 @@ def init_sequence_patterns(term):
class SequenceTextWrapper(textwrap.TextWrapper):
def __init__(self, width, term, **kwargs):
self.term = term
- assert kwargs.get('break_long_words', False) is False, (
- 'break_long_words is not sequence-safe')
- kwargs['break_long_words'] = False
textwrap.TextWrapper.__init__(self, width, **kwargs)
def _wrap_chunks(self, chunks):
diff --git a/blessed/terminal.py b/blessed/terminal.py
index 8f65321..1e17d73 100644
--- a/blessed/terminal.py
+++ b/blessed/terminal.py
@@ -4,6 +4,7 @@ import collections
import contextlib
import functools
import warnings
+import platform
import codecs
import curses
import locale
@@ -180,9 +181,16 @@ class Terminal(object):
# send them to stdout as a fallback, since they have to go
# somewhere.
try:
- curses.setupterm(self._kind, self._init_descriptor)
- except curses.error:
- warnings.warn('Failed to setupterm(kind=%s)' % (self._kind,))
+ if (platform.python_implementation() == 'PyPy' and
+ isinstance(self._kind, unicode)):
+ # pypy/2.4.0_2/libexec/lib_pypy/_curses.py, line 1131
+ # TypeError: initializer for ctype 'char *' must be a str
+ curses.setupterm(self._kind.encode('ascii'), self._init_descriptor)
+ else:
+ curses.setupterm(self._kind, self._init_descriptor)
+ except curses.error as err:
+ warnings.warn('Failed to setupterm(kind={0!r}): {1}'
+ .format(self._kind, err))
self._kind = None
self._does_styling = False
else:
@@ -515,16 +523,8 @@ class Terminal(object):
Returns a list of strings that may contain escape sequences. See
``textwrap.TextWrapper`` for all available additional kwargs to
customize wrapping behavior such as ``subsequent_indent``.
-
- Note that the keyword argument ``break_long_words`` may not be set,
- it is not sequence-safe!
"""
-
- _blw = 'break_long_words'
- assert (_blw not in kwargs or not kwargs[_blw]), (
- "keyword argument, '{}' is not sequence-safe".format(_blw))
-
- width = width is None and self.width or width
+ width = self.width if width is None else width
lines = []
for line in text.splitlines():
lines.extend(
diff --git a/blessed/tests/accessories.py b/blessed/tests/accessories.py
index 6785827..9c06688 100644
--- a/blessed/tests/accessories.py
+++ b/blessed/tests/accessories.py
@@ -3,9 +3,11 @@
# std
from __future__ import with_statement
import contextlib
+import subprocess
import functools
import traceback
import termios
+import random
import codecs
import curses
import sys
@@ -27,16 +29,25 @@ TestTerminal = functools.partial(Terminal, kind='xterm-256color')
SEND_SEMAPHORE = SEMAPHORE = b'SEMAPHORE\n'
RECV_SEMAPHORE = b'SEMAPHORE\r\n'
all_xterms_params = ['xterm', 'xterm-256color']
-all_terms_params = ['screen', 'vt220', 'rxvt', 'cons25', 'linux', 'ansi']
-binpacked_terminal_params = ['avatar', 'kermit']
many_lines_params = [30, 100]
-many_columns_params = [10, 100]
-if os.environ.get('TRAVIS', None) is None:
- # TRAVIS-CI has a limited type of terminals, the others ...
- all_terms_params.extend(['avatar', 'kermit', 'dtterm', 'wyse520',
- 'minix', 'eterm', 'aixterm', 'putty'])
-all_standard_terms_params = (set(all_terms_params) -
- set(binpacked_terminal_params))
+many_columns_params = [1, 25, 50]
+from blessed._binterms import binary_terminals
+default_all_terms = ['screen', 'vt220', 'rxvt', 'cons25', 'linux', 'ansi']
+try:
+ available_terms = [
+ _term.split(None, 1)[0].decode('ascii') for _term in
+ subprocess.Popen(["toe"], stdout=subprocess.PIPE, close_fds=True)
+ .communicate()[0].splitlines()]
+ if not os.environ.get('TEST_ALLTERMS'):
+ # we just pick 3 random terminal types, they're all as good as any so
+ # long as they're not in the binary_terminals list.
+ random.shuffle(available_terms)
+ available_terms = available_terms[:3]
+ all_terms_params = list(set(available_terms) - (
+ set(binary_terminals) if not os.environ.get('TEST_BINTERMS')
+ else set())) or default_all_terms
+except OSError:
+ all_terms_params = default_all_terms
class as_subprocess(object):
@@ -174,7 +185,10 @@ def echo_off(fd):
def unicode_cap(cap):
"""Return the result of ``tigetstr`` except as Unicode."""
- val = curses.tigetstr(cap)
+ try:
+ val = curses.tigetstr(cap)
+ except curses.error:
+ val = None
if val:
return val.decode('latin1')
return u''
@@ -182,15 +196,21 @@ def unicode_cap(cap):
def unicode_parm(cap, *parms):
"""Return the result of ``tparm(tigetstr())`` except as Unicode."""
- cap = curses.tigetstr(cap)
+ try:
+ cap = curses.tigetstr(cap)
+ except curses.error:
+ cap = None
if cap:
- val = curses.tparm(cap, *parms)
+ try:
+ val = curses.tparm(cap, *parms)
+ except curses.error:
+ val = None
if val:
return val.decode('latin1')
return u''
-@pytest.fixture(params=binpacked_terminal_params)
+@pytest.fixture(params=binary_terminals)
def unsupported_sequence_terminals(request):
"""Terminals that emit warnings for unsupported sequence-awareness."""
return request.param
@@ -208,12 +228,6 @@ def all_terms(request):
return request.param
-@pytest.fixture(params=all_standard_terms_params)
-def all_standard_terms(request):
- """Common kind values for all kinds of terminals (except binary-packed)."""
- return request.param
-
-
@pytest.fixture(params=many_lines_params)
def many_lines(request):
"""Various number of lines for screen height."""
diff --git a/blessed/tests/test_core.py b/blessed/tests/test_core.py
index effaa13..befcea3 100644
--- a/blessed/tests/test_core.py
+++ b/blessed/tests/test_core.py
@@ -212,7 +212,9 @@ def test_setupterm_invalid_issue39():
term = TestTerminal(kind='unknown', force_styling=True)
except UserWarning:
err = sys.exc_info()[1]
- assert err.args[0] == 'Failed to setupterm(kind=unknown)'
+ assert err.args[0] == (
+ "Failed to setupterm(kind='unknown'): "
+ "setupterm: could not find terminal")
else:
assert not term.is_a_tty and not term.does_styling, (
'Should have thrown exception')
diff --git a/blessed/tests/test_keyboard.py b/blessed/tests/test_keyboard.py
index e079c88..c81154f 100644
--- a/blessed/tests/test_keyboard.py
+++ b/blessed/tests/test_keyboard.py
@@ -1,5 +1,6 @@
# -*- coding: utf-8 -*-
"Tests for keyboard support."
+# std imports
import functools
import tempfile
try:
@@ -7,15 +8,17 @@ try:
except ImportError:
import io
StringIO = io.StringIO
+import platform
import signal
import curses
import time
import math
-import tty
+import tty # NOQA
import pty
import sys
import os
+# local
from .accessories import (
read_until_eof,
read_until_semaphore,
@@ -29,6 +32,8 @@ from .accessories import (
xterms,
)
+# 3rd-party
+import pytest
import mock
if sys.version_info[0] == 3:
@@ -422,6 +427,9 @@ def test_inkey_0s_cbreak_multibyte_utf8():
assert math.floor(time.time() - stime) == 0.0
+@pytest.mark.skipif(os.environ.get('TRAVIS', None) is not None or
+ platform.python_implementation() == 'PyPy',
+ reason="travis-ci nor pypy handle ^C very well.")
def test_inkey_0s_raw_ctrl_c():
"0-second inkey with raw allows receiving ^C."
pid, master_fd = pty.fork()
@@ -449,17 +457,9 @@ def test_inkey_0s_raw_ctrl_c():
stime = time.time()
output = read_until_eof(master_fd)
pid, status = os.waitpid(pid, 0)
- if os.environ.get('TRAVIS', None) is not None:
- # For some reason, setraw has no effect travis-ci,
- # is still accepts ^C, causing system exit on py26,
- # but exit 0 on py27, and either way on py33
- # .. strange, huh?
- assert output in (u'', u'\x03')
- assert os.WEXITSTATUS(status) in (0, 2)
- else:
- assert (output == u'\x03' or
- output == u'' and not os.isatty(0))
- assert os.WEXITSTATUS(status) == 0
+ assert (output == u'\x03' or
+ output == u'' and not os.isatty(0))
+ assert os.WEXITSTATUS(status) == 0
assert math.floor(time.time() - stime) == 0.0
@@ -698,7 +698,6 @@ def test_cuf1_and_cub1_as_RIGHT_LEFT(all_terms):
term = TestTerminal(kind=kind, force_styling=True)
keymap = get_keyboard_sequences(term)
if term._cuf1:
- assert term._cuf1 != u' '
assert term._cuf1 in keymap
assert keymap[term._cuf1] == term.KEY_RIGHT
if term._cub1:
diff --git a/blessed/tests/test_length_sequence.py b/blessed/tests/test_length_sequence.py
index 93aa2d1..88096dc 100644
--- a/blessed/tests/test_length_sequence.py
+++ b/blessed/tests/test_length_sequence.py
@@ -12,12 +12,11 @@ except ImportError:
from io import StringIO
from .accessories import (
- all_standard_terms,
+ all_terms,
as_subprocess,
TestTerminal,
many_columns,
many_lines,
- all_terms,
)
import pytest
@@ -244,7 +243,7 @@ def test_winsize(many_lines, many_columns):
@pytest.mark.skipif(platform.python_implementation() == 'PyPy',
reason='PyPy fails TIOCSWINSZ')
-def test_Sequence_alignment(all_terms, many_lines):
+def test_Sequence_alignment(all_terms):
"""Tests methods related to Sequence class, namely ljust, rjust, center."""
@as_subprocess
def child(kind, lines=25, cols=80):
@@ -270,7 +269,7 @@ def test_Sequence_alignment(all_terms, many_lines):
assert (t.length(radjusted.strip()) == pony_len)
assert (t.length(radjusted) == len(pony_msg.rjust(t.width)))
- child(kind=all_terms, lines=many_lines)
+ child(kind=all_terms)
def test_sequence_is_movement_false(all_terms):
@@ -310,7 +309,7 @@ def test_sequence_is_movement_false(all_terms):
child_mnemonics_wontmove(all_terms)
-def test_sequence_is_movement_true(all_standard_terms):
+def test_sequence_is_movement_true(all_terms):
"""Test parsers about sequences that move the cursor."""
@as_subprocess
def child_mnemonics_willmove(kind):
@@ -340,4 +339,4 @@ def test_sequence_is_movement_true(all_standard_terms):
assert not t.clear or (len(t.clear) ==
measure_length(t.clear, t))
- child_mnemonics_willmove(all_standard_terms)
+ child_mnemonics_willmove(all_terms)
diff --git a/blessed/tests/test_sequences.py b/blessed/tests/test_sequences.py
index 7a14ba0..6de77ec 100644
--- a/blessed/tests/test_sequences.py
+++ b/blessed/tests/test_sequences.py
@@ -1,16 +1,19 @@
# -*- coding: utf-8 -*-
"""Tests for Terminal() sequences and sequence-awareness."""
+# std imports
try:
from StringIO import StringIO
except ImportError:
from io import StringIO
import platform
+import random
import sys
import os
+# local
from .accessories import (
unsupported_sequence_terminals,
- all_standard_terms,
+ all_terms,
as_subprocess,
TestTerminal,
unicode_parm,
@@ -19,6 +22,7 @@ from .accessories import (
many_lines,
)
+# 3rd-party
import pytest
import mock
@@ -89,12 +93,14 @@ def test_stream_attr():
@pytest.mark.skipif(os.environ.get('TRAVIS', None) is not None,
reason="travis-ci does not have binary-packed terminals.")
-def test_emit_warnings_about_binpacked(unsupported_sequence_terminals):
+def test_emit_warnings_about_binpacked():
"""Test known binary-packed terminals (kermit, avatar) emit a warning."""
+ from blessed.sequences import _BINTERM_UNSUPPORTED_MSG
+ from blessed._binterms import binary_terminals
+
@as_subprocess
def child(kind):
import warnings
- from blessed.sequences import _BINTERM_UNSUPPORTED_MSG
warnings.filterwarnings("error", category=RuntimeWarning)
warnings.filterwarnings("error", category=UserWarning)
@@ -102,30 +108,33 @@ def test_emit_warnings_about_binpacked(unsupported_sequence_terminals):
TestTerminal(kind=kind, force_styling=True)
except UserWarning:
err = sys.exc_info()[1]
- assert (err.args[0] == _BINTERM_UNSUPPORTED_MSG or
- err.args[0].startswith('Unknown parameter in ')
+ assert (err.args[0] == _BINTERM_UNSUPPORTED_MSG.format(kind) or
+ err.args[0].startswith('Unknown parameter in ') or
+ err.args[0].startswith('Failed to setupterm(')
), err
else:
assert 'warnings should have been emitted.'
warnings.resetwarnings()
- child(unsupported_sequence_terminals)
+ # any binary terminal should do.
+ child(binary_terminals[random.randrange(len(binary_terminals))])
-def test_unit_binpacked_unittest(unsupported_sequence_terminals):
+def test_unit_binpacked_unittest():
"""Unit Test known binary-packed terminals emit a warning (travis-safe)."""
import warnings
+ from blessed._binterms import binary_terminals
from blessed.sequences import (_BINTERM_UNSUPPORTED_MSG,
init_sequence_patterns)
warnings.filterwarnings("error", category=UserWarning)
term = mock.Mock()
- term.kind = unsupported_sequence_terminals
+ term.kind = binary_terminals[random.randrange(len(binary_terminals))]
try:
init_sequence_patterns(term)
except UserWarning:
err = sys.exc_info()[1]
- assert err.args[0] == _BINTERM_UNSUPPORTED_MSG
+ assert err.args[0] == _BINTERM_UNSUPPORTED_MSG.format(term.kind)
else:
assert False, 'Previous stmt should have raised exception.'
warnings.resetwarnings()
@@ -139,7 +148,7 @@ def test_merge_sequences():
assert (_merge_sequences(input_list) == output_expected)
-def test_location_with_styling(all_standard_terms):
+def test_location_with_styling(all_terms):
"""Make sure ``location()`` works on all terminals."""
@as_subprocess
def child_with_styling(kind):
@@ -152,7 +161,7 @@ def test_location_with_styling(all_standard_terms):
u'hi', unicode_cap('rc')))
assert (t.stream.getvalue() == expected_output)
- child_with_styling(all_standard_terms)
+ child_with_styling(all_terms)
def test_location_without_styling():
@@ -170,7 +179,7 @@ def test_location_without_styling():
child_without_styling()
-def test_horizontal_location(all_standard_terms):
+def test_horizontal_location(all_terms):
"""Make sure we can move the cursor horizontally without changing rows."""
@as_subprocess
def child(kind):
@@ -181,14 +190,15 @@ def test_horizontal_location(all_standard_terms):
(unicode_cap('sc'),
unicode_parm('hpa', 5),
unicode_cap('rc')))
- assert (t.stream.getvalue() == expected_output)
+ assert (t.stream.getvalue() == expected_output), (
+ repr(t.stream.getvalue()), repr(expected_output))
# skip 'screen', hpa is proxied (see later tests)
- if all_standard_terms != 'screen':
- child(all_standard_terms)
+ if all_terms != 'screen':
+ child(all_terms)
-def test_vertical_location(all_standard_terms):
+def test_vertical_location(all_terms):
"""Make sure we can move the cursor horizontally without changing rows."""
@as_subprocess
def child(kind):
@@ -202,8 +212,8 @@ def test_vertical_location(all_standard_terms):
assert (t.stream.getvalue() == expected_output)
# skip 'screen', vpa is proxied (see later tests)
- if all_standard_terms != 'screen':
- child(all_standard_terms)
+ if all_terms != 'screen':
+ child(all_terms)
def test_inject_move_x():
@@ -262,7 +272,7 @@ def test_inject_civis_and_cnorm_for_ansi():
child('ansi')
-def test_zero_location(all_standard_terms):
+def test_zero_location(all_terms):
"""Make sure ``location()`` pays attention to 0-valued args."""
@as_subprocess
def child(kind):
@@ -275,10 +285,10 @@ def test_zero_location(all_standard_terms):
unicode_cap('rc')))
assert (t.stream.getvalue() == expected_output)
- child(all_standard_terms)
+ child(all_terms)
-def test_mnemonic_colors(all_standard_terms):
+def test_mnemonic_colors(all_terms):
"""Make sure color shortcuts work."""
@as_subprocess
def child(kind):
@@ -300,10 +310,10 @@ def test_mnemonic_colors(all_standard_terms):
assert (t.on_bright_black == on_color(t, 8))
assert (t.on_bright_green == on_color(t, 10))
- child(all_standard_terms)
+ child(all_terms)
-def test_callable_numeric_colors(all_standard_terms):
+def test_callable_numeric_colors(all_terms):
"""``color(n)`` should return a formatting wrapper."""
@as_subprocess
def child(kind):
@@ -333,10 +343,10 @@ def test_callable_numeric_colors(all_standard_terms):
else:
assert t.on_color(6)('smoo') == 'smoo'
- child(all_standard_terms)
+ child(all_terms)
-def test_null_callable_numeric_colors(all_standard_terms):
+def test_null_callable_numeric_colors(all_terms):
"""``color(n)`` should be a no-op on null terminals."""
@as_subprocess
def child(kind):
@@ -344,20 +354,20 @@ def test_null_callable_numeric_colors(all_standard_terms):
assert (t.color(5)('smoo') == 'smoo')
assert (t.on_color(6)('smoo') == 'smoo')
- child(all_standard_terms)
+ child(all_terms)
-def test_naked_color_cap(all_standard_terms):
+def test_naked_color_cap(all_terms):
"""``term.color`` should return a stringlike capability."""
@as_subprocess
def child(kind):
t = TestTerminal(kind=kind)
assert (t.color + '' == t.setaf + '')
- child(all_standard_terms)
+ child(all_terms)
-def test_formatting_functions(all_standard_terms):
+def test_formatting_functions(all_terms):
"""Test simple and compound formatting wrappers."""
@as_subprocess
def child(kind):
@@ -388,10 +398,10 @@ def test_formatting_functions(all_standard_terms):
assert (t.subscript(u'[1]') == expected_output)
- child(all_standard_terms)
+ child(all_terms)
-def test_compound_formatting(all_standard_terms):
+def test_compound_formatting(all_terms):
"""Test simple and compound formatting wrappers."""
@as_subprocess
def child(kind):
@@ -411,10 +421,10 @@ def test_compound_formatting(all_standard_terms):
assert (t.on_bright_red_bold_bright_green_underline('meh')
== expected_output)
- child(all_standard_terms)
+ child(all_terms)
-def test_formatting_functions_without_tty(all_standard_terms):
+def test_formatting_functions_without_tty(all_terms):
"""Test crazy-ass formatting wrappers when there's no tty."""
@as_subprocess
def child(kind):
@@ -426,10 +436,10 @@ def test_formatting_functions_without_tty(all_standard_terms):
assert (t.bold_underline_green_on_red('loo') == u'loo')
assert (t.on_bright_red_bold_bright_green_underline('meh') == u'meh')
- child(all_standard_terms)
+ child(all_terms)
-def test_nice_formatting_errors(all_standard_terms):
+def test_nice_formatting_errors(all_terms):
"""Make sure you get nice hints if you misspell a formatting wrapper."""
@as_subprocess
def child(kind):
@@ -463,10 +473,10 @@ def test_nice_formatting_errors(all_standard_terms):
e = sys.exc_info()[1]
assert 'probably misspelled' in e.args[0], e.args
- child(all_standard_terms)
+ child(all_terms)
-def test_null_callable_string(all_standard_terms):
+def test_null_callable_string(all_terms):
"""Make sure NullCallableString tolerates all kinds of args."""
@as_subprocess
def child(kind):
@@ -480,7 +490,7 @@ def test_null_callable_string(all_standard_terms):
assert (t.uhh(9876) == '')
assert (t.clear('x') == 'x')
- child(all_standard_terms)
+ child(all_terms)
def test_bnc_parameter_emits_warning():
diff --git a/blessed/tests/test_wrap.py b/blessed/tests/test_wrap.py
index 36e752d..dee3ebc 100644
--- a/blessed/tests/test_wrap.py
+++ b/blessed/tests/test_wrap.py
@@ -35,122 +35,50 @@ def test_SequenceWrapper_invalid_width():
child()
-def test_SequenceWrapper_drop_whitespace_subsequent_indent():
+@pytest.mark.parametrize("kwargs", [
+ dict(break_long_words=False,
+ drop_whitespace=False,
+ subsequent_indent=''),
+ dict(break_long_words=False,
+ drop_whitespace=True,
+ subsequent_indent=''),
+ dict(break_long_words=False,
+ drop_whitespace=False,
+ subsequent_indent=' '),
+ dict(break_long_words=False,
+ drop_whitespace=True,
+ subsequent_indent=' '),
+ # dict(break_long_words=True,
+ # drop_whitespace=False,
+ # subsequent_indent=''),
+ # dict(break_long_words=True,
+ # drop_whitespace=True,
+ # subsequent_indent=''),
+ # dict(break_long_words=True,
+ # drop_whitespace=False,
+ # subsequent_indent=' '),
+ # dict(break_long_words=True,
+ # drop_whitespace=True,
+ # subsequent_indent=' '),
+])
+def test_SequenceWrapper(all_terms, many_columns, kwargs):
"""Test that text wrapping matches internal extra options."""
- WIDTH = 10
-
@as_subprocess
- def child():
+ def child(term, width, kwargs):
# build a test paragraph, along with a very colorful version
t = TestTerminal()
- pgraph = u' '.join(
- ('a', 'ab', 'abc', 'abcd', 'abcde', 'abcdef', 'abcdefgh',
- 'abcdefghi', 'abcdefghij', 'abcdefghijk', 'abcdefghijkl',
- 'abcdefghijklm', 'abcdefghijklmn', 'abcdefghijklmno ',)
- * 4)
-
- pgraph_colored = u''.join([
- t.color(n % 7) + t.bold + ch if ch != ' ' else ' '
- for n, ch in enumerate(pgraph)])
-
- internal_wrapped = textwrap.wrap(pgraph, width=WIDTH,
- break_long_words=False,
- drop_whitespace=True,
- subsequent_indent=u' '*3)
- my_wrapped = t.wrap(pgraph, width=WIDTH,
- drop_whitespace=True,
- subsequent_indent=u' '*3)
- my_wrapped_colored = t.wrap(pgraph_colored, width=WIDTH,
- drop_whitespace=True,
- subsequent_indent=u' '*3)
-
- # ensure we textwrap ascii the same as python
- assert (internal_wrapped == my_wrapped)
-
- # ensure our first and last line wraps at its ends
- first_l = internal_wrapped[0]
- last_l = internal_wrapped[-1]
- my_first_l = my_wrapped_colored[0]
- my_last_l = my_wrapped_colored[-1]
- assert (len(first_l) == t.length(my_first_l))
- assert (len(last_l) == t.length(my_last_l)), (internal_wrapped,
- my_wrapped_colored)
- assert (len(internal_wrapped[-1]) == t.length(my_wrapped_colored[-1]))
-
- # ensure our colored textwrap is the same line length
- assert (len(internal_wrapped) == len(my_wrapped_colored))
-
- child()
-
-
-@pytest.mark.skipif(platform.python_implementation() == 'PyPy',
- reason='PyPy fails TIOCSWINSZ')
-def test_SequenceWrapper(all_terms, many_columns):
- """Test that text wrapping accounts for sequences correctly."""
- @as_subprocess
- def child(kind, lines=25, cols=80):
-
- # set the pty's virtual window size
- val = struct.pack('HHHH', lines, cols, 0, 0)
- fcntl.ioctl(sys.__stdout__.fileno(), termios.TIOCSWINSZ, val)
-
- # build a test paragraph, along with a very colorful version
- t = TestTerminal(kind=kind)
- pgraph = u' '.join(
- ('a', 'ab', 'abc', 'abcd', 'abcde', 'abcdef', 'abcdefgh',
- 'abcdefghi', 'abcdefghij', 'abcdefghijk', 'abcdefghijkl',
- 'abcdefghijklm', 'abcdefghijklmn', 'abcdefghijklmno',) * 4)
- pgraph_colored = u''.join([
- t.color(n % 7) + t.bold + ch
- for n, ch in enumerate(pgraph)])
-
- internal_wrapped = textwrap.wrap(pgraph, t.width,
- break_long_words=False)
- my_wrapped = t.wrap(pgraph)
- my_wrapped_colored = t.wrap(pgraph_colored)
-
- # ensure we textwrap ascii the same as python
- assert (internal_wrapped == my_wrapped)
-
- # ensure our first and last line wraps at its ends
- first_l = internal_wrapped[0]
- last_l = internal_wrapped[-1]
- my_first_l = my_wrapped_colored[0]
- my_last_l = my_wrapped_colored[-1]
- assert (len(first_l) == t.length(my_first_l))
- assert (len(last_l) == t.length(my_last_l))
- assert (len(internal_wrapped[-1]) == t.length(my_wrapped_colored[-1]))
-
- child(kind=all_terms, lines=25, cols=many_columns)
-
-
-def test_SequenceWrapper_27(all_terms):
- """Test that text wrapping accounts for sequences correctly."""
- WIDTH = 27
-
- @as_subprocess
- def child(kind):
- # build a test paragraph, along with a very colorful version
- t = TestTerminal(kind=kind)
- pgraph = u' '.join(
- ('a', 'ab', 'abc', 'abcd', 'abcde', 'abcdef', 'abcdefgh',
- 'abcdefghi', 'abcdefghij', 'abcdefghijk', 'abcdefghijkl',
- 'abcdefghijklm', 'abcdefghijklmn', 'abcdefghijklmno ',)
- * 8)
+ pgraph = u' '.join((
+ 'a', 'bc', 'def', 'ghij', 'klmno', 'pqrstu', 'vwxyz012',
+ '34567890A', 'BCDEFGHIJK', 'LMNOPQRSTUV', 'WXYZabcdefgh',
+ 'ijklmnopqrstu', 'vwxyz123456789', '0ABCDEFGHIJKLMN '))
pgraph_colored = u''.join([
- t.color(n % 7) + t.bold + ch
- for n, ch in enumerate(pgraph)])
+ t.color(idx % 7)(char) if char != ' ' else ' '
+ for idx, char in enumerate(pgraph)])
- internal_wrapped = textwrap.wrap(pgraph, width=WIDTH,
- break_long_words=False,
- drop_whitespace=False)
- my_wrapped = t.wrap(pgraph, width=WIDTH,
- break_long_words=False,
- drop_whitespace=False)
- my_wrapped_colored = t.wrap(pgraph_colored, width=WIDTH,
- break_long_words=False,
- drop_whitespace=False)
+ internal_wrapped = textwrap.wrap(pgraph, width=width, **kwargs)
+ my_wrapped = t.wrap(pgraph, width=width, **kwargs)
+ my_wrapped_colored = t.wrap(pgraph_colored, width=width, **kwargs)
# ensure we textwrap ascii the same as python
assert (internal_wrapped == my_wrapped)
@@ -167,4 +95,4 @@ def test_SequenceWrapper_27(all_terms):
# ensure our colored textwrap is the same line length
assert (len(internal_wrapped) == len(my_wrapped_colored))
- child(kind=all_terms)
+ child(all_terms, many_columns, kwargs)
diff --git a/tox.ini b/tox.ini
index 35227ee..2c9ee50 100644
--- a/tox.ini
+++ b/tox.ini
@@ -12,19 +12,19 @@ skip_missing_interpreters = true
whitelist_externals = /bin/bash /bin/mv
setenv = PYTHONIOENCODING=UTF8
deps = pytest-flakes
+ pytest-xdist
pytest-pep8
pytest-cov
pytest
mock
commands = {envbindir}/py.test \
- -x --strict --pep8 --flakes \
- --junit-xml=results.{envname}.xml \
- --verbose --verbose \
+ --strict --pep8 --flakes \
+ --junit-xml=results.{envname}.xml --verbose \
--cov blessed blessed/tests {posargs}
/bin/mv {toxinidir}/.coverage {toxinidir}/.coverage.{envname}
[testenv:static_analysis]
-deps = prospector[with_pep257,with_pyroma,with_vulture]
+deps = prospector[with_everything]
commands = prospector \
--die-on-tool-error \
--test-warnings \