Skip to content

Commit 2d75fdc

Browse files
authored
Bugfix for term.split_seqs('term.right(3)') #197
* Bugfix for term.split_seqs('term.right(3)') In version 1.18.0 and earlier, >> term.split_seqs(term.move_right(333) + 'xyz', maxsplit=1) ['\x1b[333C', '333', 'xyz'] This is a bug, it duplicates the matched parameter, this is now corrected: ['\x1b[3C', 'xyz'] Previously, we documented "same arguments as "re.split", so we must also implement maxsplit and flags. Also, - fix flake8 linting of tests by moving fixtures to conftest.py, fixes "unused" or "re-definition from import" errors. - version stamp blessed/__init__.py like a codegen step i guess - remove run_codecov.py, its been fixed upstream codecov/codecov-python#158 (comment)
1 parent b6025ec commit 2d75fdc

17 files changed

+159
-115
lines changed

.travis.yml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ matrix:
1616
env: TOXENV=py37,codecov TEST_QUICK=1 COVERAGE_ID=travis-ci
1717
- python: 3.8
1818
env: TOXENV=py38,codecov COVERAGE_ID=travis-ci TEST_RAW=yes
19-
- python: 3.9-dev
19+
- python: 3.9
2020
env: TOXENV=py39,codecov TEST_QUICK=1 COVERAGE_ID=travis-ci TOXPYTHON=3.9
2121
- python: 3.10-dev
2222
env: TOXENV=py310,codecov TEST_QUICK=1 COVERAGE_ID=travis-ci TOXPYTHON=3.10
@@ -38,7 +38,6 @@ matrix:
3838
env: PATH=/c/Python38:/c/Python38/Scripts:$PATH TOXENV=py38,codecov COVERAGE_ID=travis-ci TEST_KEYBOARD=no
3939

4040
allow_failures:
41-
- python: 3.9-dev
4241
- python: 3.10-dev
4342

4443
install:

blessed/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,4 @@
1919
'support due to http://bugs.python.org/issue10570.')
2020

2121
__all__ = ('Terminal',)
22-
__version__ = '1.18.0'
22+
__version__ = "1.18.1"

blessed/_capabilities.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
import re
44
from collections import OrderedDict
55

6-
76
__all__ = (
87
'CAPABILITY_DATABASE',
98
'CAPABILITIES_RAW_MIXIN',

blessed/terminal.py

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1100,20 +1100,33 @@ def strip_seqs(self, text):
11001100
"""
11011101
return Sequence(text, self).strip_seqs()
11021102

1103-
def split_seqs(self, text, **kwds):
1103+
def split_seqs(self, text, maxsplit=0):
11041104
r"""
11051105
Return ``text`` split by individual character elements and sequences.
11061106
11071107
:arg str text: String containing sequences
1108-
:arg kwds: remaining keyword arguments for :func:`re.split`.
1108+
:arg int maxsplit: When maxsplit is nonzero, at most maxsplit splits
1109+
occur, and the remainder of the string is returned as the final element
1110+
of the list (same meaning is argument for :func:`re.split`).
11091111
:rtype: list[str]
11101112
:returns: List of sequences and individual characters
11111113
11121114
>>> term.split_seqs(term.underline(u'xyz'))
11131115
['\x1b[4m', 'x', 'y', 'z', '\x1b(B', '\x1b[m']
1116+
1117+
>>> term.split_seqs(term.underline(u'xyz'), 1)
1118+
['\x1b[4m', r'xyz\x1b(B\x1b[m']
11141119
"""
11151120
pattern = self._caps_unnamed_any
1116-
return list(filter(None, re.split(pattern, text, **kwds)))
1121+
result = []
1122+
for idx, match in enumerate(re.finditer(pattern, text)):
1123+
result.append(match.group())
1124+
if maxsplit and idx == maxsplit:
1125+
remaining = text[match.end():]
1126+
if remaining:
1127+
result[-1] += remaining
1128+
break
1129+
return result
11171130

11181131
def wrap(self, text, width=None, **kwargs):
11191132
"""

blessed/terminal.pyi

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ class Terminal:
8888
def rstrip(self, text: str, chars: Optional[str] = ...) -> str: ...
8989
def lstrip(self, text: str, chars: Optional[str] = ...) -> str: ...
9090
def strip_seqs(self, text: str) -> str: ...
91-
def split_seqs(self, text: str, **kwds: Any) -> List[str]: ...
91+
def split_seqs(self, text: str, maxsplit: int) -> List[str]: ...
9292
def wrap(
9393
self, text: str, width: Optional[int] = ..., **kwargs: Any
9494
) -> List[str]: ...

docs/history.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
Version History
22
===============
33
1.18
4+
* bugfix: :meth:`~Terminal.split_seqs` for some sequences
5+
like ``term.move_left(3)``, :ghissue:`197`.
46
* introduced: type annotations, :ghissue:`192` by :ghuser:`dlax`.
57
* bugfix: do not fail when ``sys.stdin`` is unset, :ghissue:`195` by
68
:ghuser:`Olen`

run_codecov.py

Lines changed: 0 additions & 47 deletions
This file was deleted.

tests/accessories.py

Lines changed: 1 addition & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
# -*- coding: utf-8 -*-
22
"""Accessories for automated py.test runner."""
3-
# standard imports
43
from __future__ import print_function, with_statement
54

65
# std imports
@@ -11,11 +10,9 @@
1110
import functools
1211
import traceback
1312
import contextlib
14-
import subprocess
1513

1614
# 3rd party
1715
import six
18-
import pytest
1916

2017
# local
2118
from blessed import Terminal
@@ -40,31 +37,6 @@
4037
TestTerminal = functools.partial(Terminal, kind=test_kind) # type: Callable[..., Terminal]
4138
SEND_SEMAPHORE = SEMAPHORE = b'SEMAPHORE\n'
4239
RECV_SEMAPHORE = b'SEMAPHORE\r\n'
43-
many_lines_params = [40, 80]
44-
# we must test a '1' column for conditional in _handle_long_word
45-
many_columns_params = [1, 10]
46-
47-
if os.environ.get('TEST_QUICK'):
48-
many_lines_params = [80, ]
49-
many_columns_params = [25, ]
50-
51-
all_terms_params = 'xterm screen ansi vt220 rxvt cons25 linux'.split()
52-
53-
if os.environ.get('TEST_FULL'):
54-
try:
55-
all_terms_params = [
56-
# use all values of the first column of data in output of 'toe -a'
57-
_term.split(None, 1)[0] for _term in
58-
subprocess.Popen(('toe', '-a'),
59-
stdout=subprocess.PIPE,
60-
close_fds=True)
61-
.communicate()[0].splitlines()]
62-
except OSError:
63-
pass
64-
elif platform.system() == 'Windows':
65-
all_terms_params = ['vtwin10', ]
66-
elif os.environ.get('TEST_QUICK'):
67-
all_terms_params = 'xterm screen ansi linux'.split()
6840

6941

7042
def init_subproc_coverage(run_note):
@@ -164,8 +136,7 @@ def __call__(self, *args, **kwargs):
164136
assert os.WEXITSTATUS(status) == 0
165137

166138

167-
def read_until_semaphore(fd, semaphore=RECV_SEMAPHORE,
168-
encoding='utf8', timeout=10):
139+
def read_until_semaphore(fd, semaphore=RECV_SEMAPHORE, encoding='utf8'):
169140
"""
170141
Read file descriptor ``fd`` until ``semaphore`` is found.
171142
@@ -254,21 +225,3 @@ def unicode_parm(cap, *parms):
254225
if val:
255226
return val.decode('latin1')
256227
return u''
257-
258-
259-
@pytest.fixture(params=all_terms_params)
260-
def all_terms(request):
261-
"""Common kind values for all kinds of terminals."""
262-
return request.param
263-
264-
265-
@pytest.fixture(params=many_lines_params)
266-
def many_lines(request):
267-
"""Various number of lines for screen height."""
268-
return request.param
269-
270-
271-
@pytest.fixture(params=many_columns_params)
272-
def many_columns(request):
273-
"""Various number of columns for screen width."""
274-
return request.param

tests/conftest.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# std imports
2+
import os
3+
import platform
4+
import subprocess
5+
6+
# 3rd party
7+
import pytest
8+
9+
all_terms_params = 'xterm screen ansi vt220 rxvt cons25 linux'.split()
10+
many_lines_params = [40, 80]
11+
# we must test a '1' column for conditional in _handle_long_word
12+
many_columns_params = [1, 10]
13+
14+
if os.environ.get('TEST_FULL'):
15+
try:
16+
all_terms_params = [
17+
# use all values of the first column of data in output of 'toe -a'
18+
_term.split(None, 1)[0] for _term in
19+
subprocess.Popen(('toe', '-a'),
20+
stdout=subprocess.PIPE,
21+
close_fds=True)
22+
.communicate()[0].splitlines()]
23+
except OSError:
24+
pass
25+
elif platform.system() == 'Windows':
26+
all_terms_params = ['vtwin10', ]
27+
elif os.environ.get('TEST_QUICK'):
28+
all_terms_params = 'xterm screen ansi linux'.split()
29+
30+
31+
if os.environ.get('TEST_QUICK'):
32+
many_lines_params = [80, ]
33+
many_columns_params = [25, ]
34+
35+
36+
@pytest.fixture(params=all_terms_params)
37+
def all_terms(request):
38+
"""Common kind values for all kinds of terminals."""
39+
return request.param
40+
41+
42+
@pytest.fixture(params=many_lines_params)
43+
def many_lines(request):
44+
"""Various number of lines for screen height."""
45+
return request.param
46+
47+
48+
@pytest.fixture(params=many_columns_params)
49+
def many_columns(request):
50+
"""Various number of columns for screen width."""
51+
return request.param

tests/test_core.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
from six.moves import reload_module
1919

2020
# local
21-
from .accessories import TestTerminal, all_terms, unicode_cap, as_subprocess
21+
from .accessories import TestTerminal, unicode_cap, as_subprocess
2222

2323

2424
def test_export_only_Terminal():

tests/test_keyboard.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
import pytest
1212

1313
# local
14-
from .accessories import TestTerminal, all_terms, as_subprocess
14+
from .accessories import TestTerminal, as_subprocess
1515

1616
if platform.system() != 'Windows':
1717
import curses

tests/test_length_sequence.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@
1010
import six
1111
import pytest
1212

13-
from .accessories import ( # isort:skip
14-
TestTerminal, as_subprocess, all_terms, many_lines, many_columns)
13+
# local
14+
from .accessories import TestTerminal, as_subprocess
1515

1616
if platform.system() != 'Windows':
1717
import fcntl

tests/test_sequences.py

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
import pytest
1010

1111
# local
12-
from .accessories import TestTerminal, all_terms, unicode_cap, unicode_parm, as_subprocess
12+
from .accessories import TestTerminal, unicode_cap, unicode_parm, as_subprocess
1313

1414

1515
@pytest.mark.skipif(platform.system() == 'Windows', reason="requires real tty")
@@ -543,9 +543,57 @@ def child(kind):
543543
result = list(term.split_seqs(given_text))
544544
assert result == expected
545545

546+
child(all_terms)
547+
548+
549+
def test_split_seqs_maxsplit1(all_terms):
550+
"""Test Terminal.split_seqs with maxsplit=1."""
551+
@as_subprocess
552+
def child(kind):
553+
from blessed import Terminal
554+
term = Terminal(kind)
555+
546556
if term.bold:
547557
given_text = term.bold + 'bbq'
548-
expected = [term.bold, 'b', 'b', 'q']
558+
expected = [term.bold, 'bbq']
559+
result = list(term.split_seqs(given_text, 1))
560+
assert result == expected
561+
562+
child(all_terms)
563+
564+
565+
def test_split_seqs_term_right(all_terms):
566+
"""Test Terminal.split_seqs with parameterized sequence"""
567+
@as_subprocess
568+
def child(kind):
569+
from blessed import Terminal
570+
term = Terminal(kind)
571+
572+
if term.move_up:
573+
given_text = 'XY' + term.move_right + 'VK'
574+
expected = ['X', 'Y', term.move_right, 'V', 'K']
575+
result = list(term.split_seqs(given_text))
576+
assert result == expected
577+
578+
child(all_terms)
579+
580+
581+
def test_split_seqs_maxsplit3_and_term_right(all_terms):
582+
"""Test Terminal.split_seqs with parameterized sequence."""
583+
@as_subprocess
584+
def child(kind):
585+
from blessed import Terminal
586+
term = Terminal(kind)
587+
588+
if term.move_right(32):
589+
given_text = 'PQ' + term.move_right(32) + 'RS'
590+
expected = ['P', 'Q', term.move_right(32), 'RS']
591+
result = list(term.split_seqs(given_text, 3))
592+
assert result == expected
593+
594+
if term.move_up(45):
595+
given_text = 'XY' + term.move_up(45) + 'VK'
596+
expected = ['X', 'Y', term.move_up(45), 'V', 'K']
549597
result = list(term.split_seqs(given_text))
550598
assert result == expected
551599

tests/test_wrap.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import pytest
77

88
# local
9-
from .accessories import TestTerminal, many_columns, as_subprocess
9+
from .accessories import TestTerminal, as_subprocess
1010

1111
TEXTWRAP_KEYWORD_COMBINATIONS = [
1212
dict(break_long_words=False,

0 commit comments

Comments
 (0)