Open ju1m opened 3 years ago
All tests run through for me with a fresh venv on 3.9.6 and all other Python versions.
@rndusr, git bisect
ing Nixpkgs blames a natsort
update:
1573e35ba0cb5b85dac35aa827ed9bad4775dc15 is the first bad commit
commit 1573e35ba0cb5b85dac35aa827ed9bad4775dc15
Author: Fabian Affolter <mail@fabian-affolter.ch>
Date: Tue Nov 9 01:08:07 2021 +0100
python3Packages.natsort: 7.1.1 -> 8.0.0
.../development/python-modules/natsort/default.nix | 53 +++++++++++-----------
1 file changed, 26 insertions(+), 27 deletions(-)
succès de la bissection
Ping @fabaff
I'm using natsort 8.0.0 and everything works.
natsort 8.0.0 doesn't seem to have any breaking changes: https://pypi.org/project/natsort/#deprecation-schedule
The only issue I found is that stig still supports Python 3.5 but natsort doesn't. I've dropped support for 3.5 in master, maybe that helps?
@rndusr same python version used in Nixpkgs.
$ nix eval -f . python3.version
"3.9.6"
Turns out natsort
was not correctly updated to 8.0.0
in Nixpkgs, but after fixing this the test still fails.
Can you reproduce this in a normal venv without using anything specific to Nix?
@rndusr, I cannot reproduce with make clean && make venv && source venv/bin/activate && pytest
, but I was able to bisect 1573e35ba0cb5b85dac35aa827ed9bad4775dc15 further down to its addition of PyICU
into the propagatedBuildInputs
of natsort
.
https://pypi.org/project/natsort says:
It is recommended that you install PyICU if you wish to sort in a locale-dependent manner, see https://natsort.readthedocs.io/en/master/locale_issues.html for an explanation why.
I naively tried to reproduce in a venv with this diff, but to no avail. I guess it's not enough to make natsort
use PyICU
:
diff --git a/setup.py b/setup.py
index 76fdc152..915469af 100644
--- a/setup.py
+++ b/setup.py
@@ -50,6 +50,7 @@ setup(
'pyxdg',
'blinker',
'natsort',
+ 'PyICU',
],
extras_require = {
'setproctitle': ['setproctitle'],
FTR, I'm using this stig/shell.nix
(nix develop -f shell.nix
) to get an environment with python
, ICU
and gcc
, in order to make clean && make venv && source venv/bin/activate && pytest
:
{ pkgs ? import /home/julm/src/nix/nixpkgs {} }:
(pkgs.buildFHSUserEnv {
name = "stig-venv";
targetPkgs = ps: (with ps; [
python39
python39Packages.pip
python39Packages.virtualenv
icu.dev
pkg-config
pkgs.gcc
]);
runScript = "bash";
}).env
I don't think this is a locale issue. "B" and "a" are just ASCII characters. They should always be sorted naturally.
Just my opinion. I don't really know anything about natsort and locales.
@rndusr, I'm no pythoner but could the problem stems from the Candidate()
wrapping the characters in one case but not the other?
stig> E - (Candidate('B'), Candidate('a'))
stig> E + ('a', 'B')
If that were the case, I shouldn't have any trouble reproducing the failed tests.
This must be something that is specific to your environment.
The tests run fine for me with PyICU installed, so that can't be it.
I know nothing about packaging, but maybe you can take a look at the natsort package to see if you need to set the locale or something? Just a wild guess.
We are experiencing nowadays more errors on NixOS:
============================= test session starts ==============================
platform linux -- Python 3.10.13, pytest-7.4.4, pluggy-1.4.0
rootdir: /build/source
configfile: pytest.ini
collected 1128 items / 1 deselected / 1127 selected
tests/client_test/base_test.py ........ [ 0%]
tests/client_test/client_utils_test.py ................................. [ 3%]
............................................... [ 7%]
tests/client_test/constants_test.py ... [ 8%]
tests/client_test/poll_test.py ........ [ 8%]
tests/client_test/trequestpool_test.py ..... [ 9%]
tests/client_test/ttypes_test.py ........ [ 9%]
tests/client_test/aiotransmission_test/api_freespace_test.py .. [ 10%]
tests/client_test/aiotransmission_test/api_status_test.py .. [ 10%]
tests/client_test/aiotransmission_test/api_torrent_test.py ............. [ 11%]
....... [ 12%]
tests/client_test/aiotransmission_test/rpc_test.py ................... [ 13%]
tests/client_test/aiotransmission_test/torrent_test.py .......... [ 14%]
tests/client_test/filters_test/file_filter_test.py ............ [ 15%]
tests/client_test/filters_test/filter_specs_test.py .. [ 15%]
tests/client_test/filters_test/filters_base_test.py .................... [ 17%]
............................................ [ 21%]
tests/client_test/filters_test/peer_filter_test.py ............ [ 22%]
tests/client_test/filters_test/setting_filter_test.py ............ [ 23%]
tests/client_test/filters_test/torrent_filter_test.py .................. [ 25%]
.................... [ 27%]
tests/client_test/filters_test/tracker_filter_test.py .................. [ 28%]
[ 28%]
tests/client_test/sorters_test/peer_sorter_test.py ........... [ 29%]
tests/client_test/sorters_test/setting_sorter_test.py ..... [ 30%]
tests/client_test/sorters_test/sorters_base_test.py .............. [ 31%]
tests/client_test/sorters_test/torrent_sorter_test.py .................. [ 32%]
........ [ 33%]
tests/client_test/sorters_test/tracker_sorter_test.py ............. [ 34%]
tests/commands_test/cmdbase_test.py ........... [ 35%]
tests/commands_test/cmdmanager_test.py ................................. [ 38%]
[ 38%]
tests/commands_test/commands_utils_test.py ... [ 38%]
tests/commands_test/config_cmds_test.py ................................ [ 41%]
................ [ 43%]
tests/commands_test/guess_ui_test.py ...... [ 43%]
tests/commands_test/misc_cmds_test.py ..... [ 44%]
tests/commands_test/torrent_cmds_test.py ..s............................ [ 46%]
......................................... [ 50%]
tests/commands_test/tui_cmds_test.py ..................... [ 52%]
tests/completion_test/candidates_test.py ............................... [ 55%]
...... [ 55%]
tests/completion_test/classes_test.py ....................... [ 57%]
tests/completion_test/completion_utils_test.py .......... [ 58%]
tests/settings_test/rcfile_test.py ..... [ 59%]
tests/settings_test/settings_test.py ................................... [ 62%]
.. [ 62%]
tests/tui_test/cli_test.py .......E [ 62%]
tests/tui_test/completer_test.py .......................... [ 65%]
tests/tui_test/group_test.py ................. [ 66%]
tests/tui_test/keymap_test.py .......................................... [ 70%]
......... [ 71%]
tests/tui_test/scroll_test.py F..FF.........F.FF..F.F [ 73%]
tests/tui_test/tabs_test.py ............................................ [ 77%]
[ 77%]
tests/tui_test/theme_test.py .......... [ 78%]
tests/tui_test/urwidpatches_test.py ..E [ 78%]
tests/utils_test/cliparser_test.py ..................................... [ 81%]
........................................................................ [ 88%]
............................................... [ 92%]
tests/utils_test/converter_test.py .......... [ 93%]
tests/utils_test/string_test.py .......... [ 93%]
tests/utils_test/usertypes_test.py ..................................... [ 97%]
............................. [ 99%]
tests/utils_test/utils_test.py .. [100%]
==================================== ERRORS ====================================
___________ ERROR at teardown of TestCLIEditWidget.test_no_completer ___________
self = <module 'tui_test.cli_test' from '/build/source/tests/tui_test/cli_test.py'>
def tearDownModule(self):
# Remove monkey patches
from stig.tui import urwidpatches
urwidpatches.revert_patches()
import urwid
> assert not hasattr(urwid.ListBox, 'get_scrollpos')
E AssertionError
tests/tui_test/_handle_urwidpatches.py:17: AssertionError
------------------------------ Captured log call -------------------------------
Using selector: EpollSelector
Exception in callback _redraw_screen() at /build/source/stig/tui/main.py:85
handle: <Handle _redraw_screen() at /build/source/stig/tui/main.py:85>
Traceback (most recent call last):
File "/nix/store/9d1gknfymymdfm8fwry11vxvh80q7sj6-python3-3.10.13/lib/python3.10/asyncio/events.py", line 80, in _run
self._context.run(self._callback, *self._args)
File "/build/source/stig/tui/main.py", line 88, in _redraw_screen
urwidloop.draw_screen()
File "/nix/store/gm7ws9n7w3wacipxrwac8f2sjfrwgj4r-python3.10-urwid-2.6.8/lib/python3.10/site-packages/urwid/event_loop/main_loop.py", line 667, in draw_screen
canvas = self._topmost_widget.render(self.screen_size, focus=True)
File "/nix/store/gm7ws9n7w3wacipxrwac8f2sjfrwgj4r-python3.10-urwid-2.6.8/lib/python3.10/site-packages/urwid/widget/widget.py", line 112, in cached_render
canv = fn(self, size, focus=focus)
File "/nix/store/gm7ws9n7w3wacipxrwac8f2sjfrwgj4r-python3.10-urwid-2.6.8/lib/python3.10/site-packages/urwid/widget/widget.py", line 711, in render
canv = get_delegate(self).render(size, focus=focus)
File "/nix/store/gm7ws9n7w3wacipxrwac8f2sjfrwgj4r-python3.10-urwid-2.6.8/lib/python3.10/site-packages/urwid/widget/widget.py", line 112, in cached_render
canv = fn(self, size, focus=focus)
File "/nix/store/gm7ws9n7w3wacipxrwac8f2sjfrwgj4r-python3.10-urwid-2.6.8/lib/python3.10/site-packages/urwid/widget/pile.py", line 866, in render
_widths, heights, size_args = self.get_rows_sizes(size, focus)
File "/nix/store/gm7ws9n7w3wacipxrwac8f2sjfrwgj4r-python3.10-urwid-2.6.8/lib/python3.10/site-packages/urwid/widget/pile.py", line 778, in get_rows_sizes
item_rows = self.get_item_rows(size, focus)
File "/nix/store/gm7ws9n7w3wacipxrwac8f2sjfrwgj4r-python3.10-urwid-2.6.8/lib/python3.10/site-packages/urwid/widget/pile.py", line 835, in get_item_rows
rows = w.rows((maxcol,), focus=focus and self.focus == w)
File "/nix/store/gm7ws9n7w3wacipxrwac8f2sjfrwgj4r-python3.10-urwid-2.6.8/lib/python3.10/site-packages/urwid/widget/widget.py", line 181, in cached_rows
return fn(self, size, focus)
File "/nix/store/gm7ws9n7w3wacipxrwac8f2sjfrwgj4r-python3.10-urwid-2.6.8/lib/python3.10/site-packages/urwid/widget/columns.py", line 1186, in rows
_, heights, _ = self.get_column_sizes(size, focus)
File "/nix/store/gm7ws9n7w3wacipxrwac8f2sjfrwgj4r-python3.10-urwid-2.6.8/lib/python3.10/site-packages/urwid/widget/columns.py", line 927, in get_column_sizes
widths = tuple(self.column_widths(size=size, focus=focus))
File "/nix/store/gm7ws9n7w3wacipxrwac8f2sjfrwgj4r-python3.10-urwid-2.6.8/lib/python3.10/site-packages/urwid/widget/columns.py", line 780, in column_widths
if w_sizing & frozenset((Sizing.FIXED, Sizing.FLOW)):
TypeError: unsupported operand type(s) for &: 'list' and 'frozenset'
_________ ERROR at teardown of TestListBox_scrolling_API.test_rows_max _________
self = <module 'tui_test.urwidpatches_test' from '/build/source/tests/tui_test/urwidpatches_test.py'>
def tearDownModule(self):
# Remove monkey patches
from stig.tui import urwidpatches
urwidpatches.revert_patches()
import urwid
> assert not hasattr(urwid.ListBox, 'get_scrollpos')
E AssertionError
tests/tui_test/_handle_urwidpatches.py:17: AssertionError
=================================== FAILURES ===================================
_______________________ TestScrollable.test_empty_widget _______________________
self = <tui_test.scroll_test.TestScrollable testMethod=test_empty_widget>
def test_empty_widget(self):
for w in (Scrollable(urwid.Text('')),
Scrollable(urwid.Pile([]))):
> self.check(w, size=(5, 10), text=(' ' * 5,) * 10)
tests/tui_test/scroll_test.py:57:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
tests/tui_test/scroll_test.py:46: in check
content = tuple(get_canvas_text(row) for row in canv.content())
tests/tui_test/scroll_test.py:46: in <genexpr>
content = tuple(get_canvas_text(row) for row in canv.content())
/nix/store/gm7ws9n7w3wacipxrwac8f2sjfrwgj4r-python3.10-urwid-2.6.8/lib/python3.10/site-packages/urwid/canvas.py:719: in content
yield shard_body_row(sbody)
/nix/store/gm7ws9n7w3wacipxrwac8f2sjfrwgj4r-python3.10-urwid-2.6.8/lib/python3.10/site-packages/urwid/canvas.py:934: in shard_body_row
row.extend(next(content_iter))
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <TextCanvas finalized=True cols=0 rows=1 at 0x7FFFF28DC430>
trim_left = 0, trim_top = 0, cols = 0, rows = 1, attr = None
def content(
self,
trim_left: int = 0,
trim_top: int = 0,
cols: int | None = 0,
rows: int | None = 0,
attr=None,
) -> Iterable[tuple[object, Literal["0", "U"] | None, bytes]]:
"""
Return the canvas content as a list of rows where each row
is a list of (attr, cs, text) tuples.
trim_left, trim_top, cols, rows may be set by
CompositeCanvas when rendering a partially obscured
canvas.
"""
maxcol, maxrow = self.cols(), self.rows()
if not cols:
cols = maxcol - trim_left
if not rows:
rows = maxrow - trim_top
if not ((0 <= trim_left < maxcol) and (cols > 0 and trim_left + cols <= maxcol)):
> raise ValueError(trim_left)
E ValueError: 0
/nix/store/gm7ws9n7w3wacipxrwac8f2sjfrwgj4r-python3.10-urwid-2.6.8/lib/python3.10/site-packages/urwid/canvas.py:496: ValueError
_______________________ TestScrollable.test_mouse_event ________________________
self = <tui_test.scroll_test.TestScrollable testMethod=test_mouse_event>
def test_mouse_event(self):
w = Scrollable(
urwid.Pile([urwid.Text('t1'),
urwid.Text('t2'),
urwid.Edit('', 'eXXX'),
urwid.Text('t3'),
urwid.Edit('', 'eYYY'),
urwid.Text('t4'),
urwid.Text('t5')])
)
size = (10, 2)
self.check(w, size, cursor_pos=None, text=('t1'.ljust(size[0]),
't2'.ljust(size[0])))
size = (10, 5)
> self.check(w, size, cursor_pos=(4, 2), text=('t1'.ljust(size[0]),
't2'.ljust(size[0]),
'eXXX'.ljust(size[0]),
't3'.ljust(size[0]),
'eYYY'.ljust(size[0])))
tests/tui_test/scroll_test.py:267:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
tests/tui_test/scroll_test.py:48: in check
self.assertEqual(content, content_exp)
E AssertionError: Tuples differ: ('t1 ', 't2 ', 'eX ', 'X ', 't3 ') != ('t1 ', 't2 ', 'eXXX ', 't3 ', 'eYYY ')
E
E First differing element 2:
E 'eX '
E 'eXXX '
E
E - ('t1 ', 't2 ', 'eX ', 'X ', 't3 ')
E ? ^^ --------------
E
E + ('t1 ', 't2 ', 'eXXX ', 't3 ', 'eYYY ')
E ? ^^ ++++++++++++++
___________________ TestScrollable.test_moving_focus_up_down ___________________
self = <tui_test.scroll_test.TestScrollable testMethod=test_moving_focus_up_down>
def test_moving_focus_up_down(self):
w = Scrollable(
urwid.Pile([urwid.Text('t1'),
urwid.Text('t2'),
urwid.Edit('', 'e3'),
urwid.Text('t4'),
urwid.Text('t5'),
urwid.Edit('', 'e6'),
urwid.Text('t7'),
urwid.Text('t8')])
)
size = (10, 2)
self.check(w, size, text=('t1'.ljust(size[0]),
't2'.ljust(size[0])))
w.keypress(size, 'down')
> self.check(w, size, text=('t2'.ljust(size[0]),
'e3'.ljust(size[0])))
tests/tui_test/scroll_test.py:240:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
tests/tui_test/scroll_test.py:48: in check
self.assertEqual(content, content_exp)
E AssertionError: Tuples differ: ('t2 ', '3 ') != ('t2 ', 'e3 ')
E
E First differing element 1:
E '3 '
E 'e3 '
E
E - ('t2 ', '3 ')
E ? -
E
E + ('t2 ', 'e3 ')
E ? +
_____ TestScrollable.test_widget_with_cursor_gets_keypress_only_if_visible _____
self = <tui_test.scroll_test.TestScrollable testMethod=test_widget_with_cursor_gets_keypress_only_if_visible>
def test_widget_with_cursor_gets_keypress_only_if_visible(self):
w = Scrollable(
urwid.Pile([urwid.Text('t1'),
urwid.Text('t2'),
urwid.Edit('', 'e3')])
)
size = (5, 2)
def press_keys():
for key in ('backspace', 'backspace', 'f', 'o', 'o'):
w.keypress(size, key)
self.check(w, size, text=('t1'.ljust(size[0]),
't2'.ljust(size[0])))
press_keys()
self.check(w, size, text=('t1'.ljust(size[0]),
't2'.ljust(size[0])))
w.set_scrollpos(1)
> self.check(w, size, text=('t2'.ljust(size[0]),
'e3'.ljust(size[0])))
tests/tui_test/scroll_test.py:178:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
tests/tui_test/scroll_test.py:48: in check
self.assertEqual(content, content_exp)
E AssertionError: Tuples differ: ('t2 ', '3 ') != ('t2 ', 'e3 ')
E
E First differing element 1:
E '3 '
E 'e3 '
E
E - ('t2 ', '3 ')
E ? -
E
E + ('t2 ', 'e3 ')
E ? +
________________ TestScrollBarWithScrollable.test_empty_widget _________________
self = <tui_test.scroll_test.TestScrollBarWithScrollable testMethod=test_empty_widget>
def test_empty_widget(self):
for w in (ScrollBar(Scrollable(urwid.Text(''))),
ScrollBar(Scrollable(urwid.Pile([])))):
> self.check(w, size=(5, 10), text=(' ' * 5,) * 10)
tests/tui_test/scroll_test.py:321:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
tests/tui_test/scroll_test.py:310: in check
content = tuple(get_canvas_text(row) for row in canv.content())
tests/tui_test/scroll_test.py:310: in <genexpr>
content = tuple(get_canvas_text(row) for row in canv.content())
/nix/store/gm7ws9n7w3wacipxrwac8f2sjfrwgj4r-python3.10-urwid-2.6.8/lib/python3.10/site-packages/urwid/canvas.py:719: in content
yield shard_body_row(sbody)
/nix/store/gm7ws9n7w3wacipxrwac8f2sjfrwgj4r-python3.10-urwid-2.6.8/lib/python3.10/site-packages/urwid/canvas.py:934: in shard_body_row
row.extend(next(content_iter))
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <TextCanvas finalized=True cols=0 rows=1 at 0x7FFFF1FC8130>
trim_left = 0, trim_top = 0, cols = 0, rows = 1, attr = None
def content(
self,
trim_left: int = 0,
trim_top: int = 0,
cols: int | None = 0,
rows: int | None = 0,
attr=None,
) -> Iterable[tuple[object, Literal["0", "U"] | None, bytes]]:
"""
Return the canvas content as a list of rows where each row
is a list of (attr, cs, text) tuples.
trim_left, trim_top, cols, rows may be set by
CompositeCanvas when rendering a partially obscured
canvas.
"""
maxcol, maxrow = self.cols(), self.rows()
if not cols:
cols = maxcol - trim_left
if not rows:
rows = maxrow - trim_top
if not ((0 <= trim_left < maxcol) and (cols > 0 and trim_left + cols <= maxcol)):
> raise ValueError(trim_left)
E ValueError: 0
/nix/store/gm7ws9n7w3wacipxrwac8f2sjfrwgj4r-python3.10-urwid-2.6.8/lib/python3.10/site-packages/urwid/canvas.py:496: ValueError
_________________ TestScrollBarWithScrollable.test_mouse_event _________________
self = <tui_test.scroll_test.TestScrollBarWithScrollable testMethod=test_mouse_event>
def test_mouse_event(self):
scrl = Scrollable(
urwid.Pile([urwid.Text('t1'),
urwid.Text('t2'),
urwid.Edit('', 'eXXX'),
urwid.Text('t3'),
urwid.Edit('', 'eYYY'),
urwid.Text('t4'),
urwid.Text('t5')])
)
sb = ScrollBar(scrl, thumb_char='#', trough_char='|')
size = (10, 5)
> self.check(sb, size, cursor_pos=(4, 2), text=('t1'.ljust(size[0] - 1) + '#',
't2'.ljust(size[0] - 1) + '#',
'eXXX'.ljust(size[0] - 1) + '#',
't3'.ljust(size[0] - 1) + '#',
'eYYY'.ljust(size[0] - 1) + '|'))
tests/tui_test/scroll_test.py:405:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
tests/tui_test/scroll_test.py:312: in check
self.assertEqual(content, content_exp)
E AssertionError: Tuples differ: ('t1 #', 't2 #', 'eX #', 'X |', 't3 |') != ('t1 #', 't2 #', 'eXXX #', 't3 #', 'eYYY |')
E
E First differing element 2:
E 'eX #'
E 'eXXX #'
E
E - ('t1 #', 't2 #', 'eX #', 'X |', 't3 |')
E ? ^^ --------------
E
E + ('t1 #', 't2 #', 'eXXX #', 't3 #', 'eYYY |')
E ? ^^ ++++++++++++++
_________________ TestScrollBarWithScrollable.test_shards_bug __________________
self = <tui_test.scroll_test.TestScrollBarWithScrollable testMethod=test_shards_bug>
def test_shards_bug(self):
scrl = Scrollable(
urwid.Pile([urwid.Columns([urwid.Text("text")] * 3)] * 3)
)
sb = ScrollBar(scrl, thumb_char='#', trough_char='|', width=3)
area = urwid.Overlay(urwid.SolidFill("O"), sb, "center", 4, "middle", 5)
> self.check(area, (10, 5), cursor_pos=(), text=(
'tetOOOO###',
'xttOOOO###',
'tetOOOO###',
'xttOOOO###',
'tetOOOO|||',
))
tests/tui_test/scroll_test.py:440:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
tests/tui_test/scroll_test.py:312: in check
self.assertEqual(content, content_exp)
E AssertionError: Tuples differ: ('texOOOOtte', 'texOOOOtte', 'texOOOOtte', ' OOOO ', ' OOOO ') != ('tetOOOO###', 'xttOOOO###', 'tetOOOO###', 'xttOOOO###', 'tetOOOO|||')
E
E First differing element 0:
E 'texOOOOtte'
E 'tetOOOO###'
E
E - ('texOOOOtte', 'texOOOOtte', 'texOOOOtte', ' OOOO ', ' OOOO ')
E + ('tetOOOO###', 'xttOOOO###', 'tetOOOO###', 'xttOOOO###', 'tetOOOO|||')
________________ TestScrollBarWithScrollable.test_wrapping_bug _________________
self = <tui_test.scroll_test.TestScrollBarWithScrollable testMethod=test_wrapping_bug>
def test_wrapping_bug(self):
scrl = Scrollable(
urwid.Pile([urwid.Columns([urwid.Text("long text")] * 2)] * 2)
)
sb = ScrollBar(scrl, thumb_char='#', trough_char='|', width=3)
widget = urwid.Columns([urwid.Pile([urwid.LineBox(sb)])] * 2)
> self.check(widget, (9, 6), cursor_pos=(), text=(
'┌───┐┌──┐',
'│###││##│',
'│###││##│',
'│###││##│',
'│###││##│',
'└───┘└──┘',
))
tests/tui_test/scroll_test.py:456:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
tests/tui_test/scroll_test.py:312: in check
self.assertEqual(content, content_exp)
E AssertionError: Tuples differ: ('┌───┐┌──┐', '│lon││lo│', '│lon││lo│', '│ ││ │', '│ ││ │', '└───┘└──┘') != ('┌───┐┌──┐', '│###││##│', '│###││##│', '│###││##│', '│###││##│', '└───┘└──┘')
E
E First differing element 1:
E '│lon││lo│'
E '│###││##│'
E
E - ('┌───┐┌──┐', '│lon││lo│', '│lon││lo│', '│ ││ │', '│ ││ │', '└───┘└──┘')
E + ('┌───┐┌──┐', '│###││##│', '│###││##│', '│###││##│', '│###││##│', '└───┘└──┘')
=============================== warnings summary ===============================
../../nix/store/gm7ws9n7w3wacipxrwac8f2sjfrwgj4r-python3.10-urwid-2.6.8/lib/python3.10/site-packages/urwid/widget/grid_flow.py:81: 1 warning
tests/tui_test/tabs_test.py: 43 warnings
/nix/store/gm7ws9n7w3wacipxrwac8f2sjfrwgj4r-python3.10-urwid-2.6.8/lib/python3.10/site-packages/urwid/widget/grid_flow.py:81: GridFlowWarning: Size is smaller than cell width (-1 < 20)
super().__init__(self.generate_display_widget((self._cache_maxcol,)))
-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
=========================== short test summary info ============================
FAILED tests/tui_test/scroll_test.py::TestScrollable::test_empty_widget - ValueError: 0
FAILED tests/tui_test/scroll_test.py::TestScrollable::test_mouse_event - AssertionError: Tuples differ: ('t1 ', 't2 ', 'eX ', '...
FAILED tests/tui_test/scroll_test.py::TestScrollable::test_moving_focus_up_down - AssertionError: Tuples differ: ('t2 ', '3 ') != ('t2 ...
FAILED tests/tui_test/scroll_test.py::TestScrollable::test_widget_with_cursor_gets_keypress_only_if_visible - AssertionError: Tuples differ: ('t2 ', '3 ') != ('t2 ', 'e3 ')
FAILED tests/tui_test/scroll_test.py::TestScrollBarWithScrollable::test_empty_widget - ValueError: 0
FAILED tests/tui_test/scroll_test.py::TestScrollBarWithScrollable::test_mouse_event - AssertionError: Tuples differ: ('t1 #', 't2 #', 'eX #', '...
FAILED tests/tui_test/scroll_test.py::TestScrollBarWithScrollable::test_shards_bug - AssertionError: Tuples differ: ('texOOOOtte', 'texOOOOtte', 'texOOOOtte', '...
FAILED tests/tui_test/scroll_test.py::TestScrollBarWithScrollable::test_wrapping_bug - AssertionError: Tuples differ: ('┌───┐┌──┐', '│lon││lo│', '│lon││lo│', '│ ...
ERROR tests/tui_test/cli_test.py::TestCLIEditWidget::test_no_completer - AssertionError
ERROR tests/tui_test/urwidpatches_test.py::TestListBox_scrolling_API::test_rows_max - AssertionError
= 8 failed, 1118 passed, 1 skipped, 1 deselected, 44 warnings, 2 errors in 7.58s =
I'm surprised you got that many tests to pass. I haven't tried to run them for years. asyntest has been deprecated for a long time now.
I'm sorry if this complicates your work flow. Maybe simply not running the tests is an option? stig isn't going to get any new features and any bug fixes will not get new tests.
Without running the tests, I got the following error on startup:
/nix/store/gm7ws9n7w3wacipxrwac8f2sjfrwgj4r-python3.10-urwid-2.6.8/lib/python3.10/site-packages/urwid/widget/grid_flow.py:81: GridFlowWarning: Size is smaller than cell width (-1 < 20)
super().__init__(self.generate_display_widget((self._cache_maxcol,)))
Traceback (most recent call last):
File "/nix/store/hvb5n6lj1glvp9vnnlfq551q0q1mi5ag-stig-0.12.8a0/bin/.stig-wrapped", line 9, in <module>
sys.exit(run())
File "/nix/store/hvb5n6lj1glvp9vnnlfq551q0q1mi5ag-stig-0.12.8a0/lib/python3.10/site-packages/stig/__init__.py", line 25, in run
main.run()
File "/nix/store/hvb5n6lj1glvp9vnnlfq551q0q1mi5ag-stig-0.12.8a0/lib/python3.10/site-packages/stig/main.py", line 102, in run
if not tui.run(run_commands):
File "/nix/store/hvb5n6lj1glvp9vnnlfq551q0q1mi5ag-stig-0.12.8a0/lib/python3.10/site-packages/stig/tui/main.py", line 61, in run
tuiobjects.urwidloop.run()
File "/nix/store/gm7ws9n7w3wacipxrwac8f2sjfrwgj4r-python3.10-urwid-2.6.8/lib/python3.10/site-packages/urwid/event_loop/main_loop.py", line 337, in run
self._run()
File "/nix/store/gm7ws9n7w3wacipxrwac8f2sjfrwgj4r-python3.10-urwid-2.6.8/lib/python3.10/site-packages/urwid/event_loop/main_loop.py", line 439, in _run
self.event_loop.run()
File "/nix/store/hvb5n6lj1glvp9vnnlfq551q0q1mi5ag-stig-0.12.8a0/lib/python3.10/site-packages/stig/tui/urwidpatches.py", line 194, in run
raise self._exc_info
File "/nix/store/9d1gknfymymdfm8fwry11vxvh80q7sj6-python3-3.10.13/lib/python3.10/asyncio/events.py", line 80, in _run
self._context.run(self._callback, *self._args)
File "/nix/store/gm7ws9n7w3wacipxrwac8f2sjfrwgj4r-python3.10-urwid-2.6.8/lib/python3.10/site-packages/urwid/event_loop/asyncio_loop.py", line 104, in wrapper
return callback(*args, **kwargs)
File "/nix/store/gm7ws9n7w3wacipxrwac8f2sjfrwgj4r-python3.10-urwid-2.6.8/lib/python3.10/site-packages/urwid/event_loop/main_loop.py", line 650, in entering_idle
self.draw_screen()
File "/nix/store/gm7ws9n7w3wacipxrwac8f2sjfrwgj4r-python3.10-urwid-2.6.8/lib/python3.10/site-packages/urwid/event_loop/main_loop.py", line 667, in draw_screen
canvas = self._topmost_widget.render(self.screen_size, focus=True)
File "/nix/store/gm7ws9n7w3wacipxrwac8f2sjfrwgj4r-python3.10-urwid-2.6.8/lib/python3.10/site-packages/urwid/widget/widget.py", line 112, in cached_render
canv = fn(self, size, focus=focus)
File "/nix/store/gm7ws9n7w3wacipxrwac8f2sjfrwgj4r-python3.10-urwid-2.6.8/lib/python3.10/site-packages/urwid/widget/widget.py", line 711, in render
canv = get_delegate(self).render(size, focus=focus)
File "/nix/store/gm7ws9n7w3wacipxrwac8f2sjfrwgj4r-python3.10-urwid-2.6.8/lib/python3.10/site-packages/urwid/widget/widget.py", line 112, in cached_render
canv = fn(self, size, focus=focus)
File "/nix/store/gm7ws9n7w3wacipxrwac8f2sjfrwgj4r-python3.10-urwid-2.6.8/lib/python3.10/site-packages/urwid/widget/pile.py", line 866, in render
_widths, heights, size_args = self.get_rows_sizes(size, focus)
File "/nix/store/gm7ws9n7w3wacipxrwac8f2sjfrwgj4r-python3.10-urwid-2.6.8/lib/python3.10/site-packages/urwid/widget/pile.py", line 778, in get_rows_sizes
item_rows = self.get_item_rows(size, focus)
File "/nix/store/gm7ws9n7w3wacipxrwac8f2sjfrwgj4r-python3.10-urwid-2.6.8/lib/python3.10/site-packages/urwid/widget/pile.py", line 835, in get_item_rows
rows = w.rows((maxcol,), focus=focus and self.focus == w)
File "/nix/store/gm7ws9n7w3wacipxrwac8f2sjfrwgj4r-python3.10-urwid-2.6.8/lib/python3.10/site-packages/urwid/widget/widget.py", line 181, in cached_rows
return fn(self, size, focus)
File "/nix/store/gm7ws9n7w3wacipxrwac8f2sjfrwgj4r-python3.10-urwid-2.6.8/lib/python3.10/site-packages/urwid/widget/columns.py", line 1186, in rows
_, heights, _ = self.get_column_sizes(size, focus)
File "/nix/store/gm7ws9n7w3wacipxrwac8f2sjfrwgj4r-python3.10-urwid-2.6.8/lib/python3.10/site-packages/urwid/widget/columns.py", line 927, in get_column_sizes
widths = tuple(self.column_widths(size=size, focus=focus))
File "/nix/store/gm7ws9n7w3wacipxrwac8f2sjfrwgj4r-python3.10-urwid-2.6.8/lib/python3.10/site-packages/urwid/widget/columns.py", line 780, in column_widths
if w_sizing & frozenset((Sizing.FIXED, Sizing.FLOW)):
TypeError: unsupported operand type(s) for &: 'list' and 'frozenset'
What's the urwid version you are using?
urwid
, version 2.6.8urwidtrees
, version 1.0.3You need urwid 2.2.*. This is specified in setup.py.