urwid 4.2.0__tar.gz → 4.2.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (117) hide show
  1. {urwid-4.2.0/urwid.egg-info → urwid-4.2.1}/PKG-INFO +1 -1
  2. {urwid-4.2.0 → urwid-4.2.1}/urwid/canvas.py +4 -1
  3. {urwid-4.2.0 → urwid-4.2.1}/urwid/text_layout.py +18 -5
  4. {urwid-4.2.0 → urwid-4.2.1}/urwid/version.py +3 -3
  5. {urwid-4.2.0 → urwid-4.2.1}/urwid/widget/edit.py +2 -1
  6. {urwid-4.2.0 → urwid-4.2.1/urwid.egg-info}/PKG-INFO +1 -1
  7. {urwid-4.2.0 → urwid-4.2.1}/urwid.egg-info/scm_version.json +2 -2
  8. {urwid-4.2.0 → urwid-4.2.1}/.devcontainer/dev.dockerfile +0 -0
  9. {urwid-4.2.0 → urwid-4.2.1}/.devcontainer/devcontainer.json +0 -0
  10. {urwid-4.2.0 → urwid-4.2.1}/.dockerignore +0 -0
  11. {urwid-4.2.0 → urwid-4.2.1}/.editorconfig +0 -0
  12. {urwid-4.2.0 → urwid-4.2.1}/.github/CODE_OF_CONDUCT.md +0 -0
  13. {urwid-4.2.0 → urwid-4.2.1}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  14. {urwid-4.2.0 → urwid-4.2.1}/.github/ISSUE_TEMPLATE/docs.md +0 -0
  15. {urwid-4.2.0 → urwid-4.2.1}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  16. {urwid-4.2.0 → urwid-4.2.1}/.github/ISSUE_TEMPLATE/question.md +0 -0
  17. {urwid-4.2.0 → urwid-4.2.1}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  18. {urwid-4.2.0 → urwid-4.2.1}/.github/dependabot.yml +0 -0
  19. {urwid-4.2.0 → urwid-4.2.1}/.github/labeler.yml +0 -0
  20. {urwid-4.2.0 → urwid-4.2.1}/.github/release.yml +0 -0
  21. {urwid-4.2.0 → urwid-4.2.1}/.github/workflows/documentation.yml +0 -0
  22. {urwid-4.2.0 → urwid-4.2.1}/.github/workflows/isolated_mypy.yml +0 -0
  23. {urwid-4.2.0 → urwid-4.2.1}/.github/workflows/isolated_pylint.yml +0 -0
  24. {urwid-4.2.0 → urwid-4.2.1}/.github/workflows/labels.yml +0 -0
  25. {urwid-4.2.0 → urwid-4.2.1}/.github/workflows/pythonpackage.yml +0 -0
  26. {urwid-4.2.0 → urwid-4.2.1}/.github/workflows/yamllint.yml +0 -0
  27. {urwid-4.2.0 → urwid-4.2.1}/.gitignore +0 -0
  28. {urwid-4.2.0 → urwid-4.2.1}/.pre-commit-config.yaml +0 -0
  29. {urwid-4.2.0 → urwid-4.2.1}/.yamllint.yml +0 -0
  30. {urwid-4.2.0 → urwid-4.2.1}/COPYING +0 -0
  31. {urwid-4.2.0 → urwid-4.2.1}/MANIFEST.in +0 -0
  32. {urwid-4.2.0 → urwid-4.2.1}/README.rst +0 -0
  33. {urwid-4.2.0 → urwid-4.2.1}/SECURITY.md +0 -0
  34. {urwid-4.2.0 → urwid-4.2.1}/classifiers.txt +0 -0
  35. {urwid-4.2.0 → urwid-4.2.1}/conftest.py +0 -0
  36. {urwid-4.2.0 → urwid-4.2.1}/mypy-requirements.txt +0 -0
  37. {urwid-4.2.0 → urwid-4.2.1}/pylint-requirements.txt +0 -0
  38. {urwid-4.2.0 → urwid-4.2.1}/pyproject.toml +0 -0
  39. {urwid-4.2.0 → urwid-4.2.1}/pytest_requirements.txt +0 -0
  40. {urwid-4.2.0 → urwid-4.2.1}/requirements.txt +0 -0
  41. {urwid-4.2.0 → urwid-4.2.1}/setup.cfg +0 -0
  42. {urwid-4.2.0 → urwid-4.2.1}/tox.ini +0 -0
  43. {urwid-4.2.0 → urwid-4.2.1}/urwid/__init__.py +0 -0
  44. {urwid-4.2.0 → urwid-4.2.1}/urwid/ansi_parser.py +0 -0
  45. {urwid-4.2.0 → urwid-4.2.1}/urwid/command_map.py +0 -0
  46. {urwid-4.2.0 → urwid-4.2.1}/urwid/display/__init__.py +0 -0
  47. {urwid-4.2.0 → urwid-4.2.1}/urwid/display/_posix_raw_display.py +0 -0
  48. {urwid-4.2.0 → urwid-4.2.1}/urwid/display/_raw_display_base.py +0 -0
  49. {urwid-4.2.0 → urwid-4.2.1}/urwid/display/_web.css +0 -0
  50. {urwid-4.2.0 → urwid-4.2.1}/urwid/display/_web.js +0 -0
  51. {urwid-4.2.0 → urwid-4.2.1}/urwid/display/_win32.py +0 -0
  52. {urwid-4.2.0 → urwid-4.2.1}/urwid/display/_win32_raw_display.py +0 -0
  53. {urwid-4.2.0 → urwid-4.2.1}/urwid/display/common.py +0 -0
  54. {urwid-4.2.0 → urwid-4.2.1}/urwid/display/curses.py +0 -0
  55. {urwid-4.2.0 → urwid-4.2.1}/urwid/display/escape.py +0 -0
  56. {urwid-4.2.0 → urwid-4.2.1}/urwid/display/html_fragment.py +0 -0
  57. {urwid-4.2.0 → urwid-4.2.1}/urwid/display/lcd.py +0 -0
  58. {urwid-4.2.0 → urwid-4.2.1}/urwid/display/raw.py +0 -0
  59. {urwid-4.2.0 → urwid-4.2.1}/urwid/display/web.py +0 -0
  60. {urwid-4.2.0 → urwid-4.2.1}/urwid/event_loop/__init__.py +0 -0
  61. {urwid-4.2.0 → urwid-4.2.1}/urwid/event_loop/abstract_loop.py +0 -0
  62. {urwid-4.2.0 → urwid-4.2.1}/urwid/event_loop/asyncio_loop.py +0 -0
  63. {urwid-4.2.0 → urwid-4.2.1}/urwid/event_loop/glib_loop.py +0 -0
  64. {urwid-4.2.0 → urwid-4.2.1}/urwid/event_loop/main_loop.py +0 -0
  65. {urwid-4.2.0 → urwid-4.2.1}/urwid/event_loop/select_loop.py +0 -0
  66. {urwid-4.2.0 → urwid-4.2.1}/urwid/event_loop/tornado_loop.py +0 -0
  67. {urwid-4.2.0 → urwid-4.2.1}/urwid/event_loop/trio_loop.py +0 -0
  68. {urwid-4.2.0 → urwid-4.2.1}/urwid/event_loop/twisted_loop.py +0 -0
  69. {urwid-4.2.0 → urwid-4.2.1}/urwid/event_loop/zmq_loop.py +0 -0
  70. {urwid-4.2.0 → urwid-4.2.1}/urwid/font.py +0 -0
  71. {urwid-4.2.0 → urwid-4.2.1}/urwid/graphics.py +0 -0
  72. {urwid-4.2.0 → urwid-4.2.1}/urwid/numedit.py +0 -0
  73. {urwid-4.2.0 → urwid-4.2.1}/urwid/py.typed +0 -0
  74. {urwid-4.2.0 → urwid-4.2.1}/urwid/signals.py +0 -0
  75. {urwid-4.2.0 → urwid-4.2.1}/urwid/split_repr.py +0 -0
  76. {urwid-4.2.0 → urwid-4.2.1}/urwid/str_util.py +0 -0
  77. {urwid-4.2.0 → urwid-4.2.1}/urwid/util.py +0 -0
  78. {urwid-4.2.0 → urwid-4.2.1}/urwid/vterm.py +0 -0
  79. {urwid-4.2.0 → urwid-4.2.1}/urwid/widget/__init__.py +0 -0
  80. {urwid-4.2.0 → urwid-4.2.1}/urwid/widget/ansi_text.py +0 -0
  81. {urwid-4.2.0 → urwid-4.2.1}/urwid/widget/attr_map.py +0 -0
  82. {urwid-4.2.0 → urwid-4.2.1}/urwid/widget/attr_wrap.py +0 -0
  83. {urwid-4.2.0 → urwid-4.2.1}/urwid/widget/bar_graph.py +0 -0
  84. {urwid-4.2.0 → urwid-4.2.1}/urwid/widget/big_text.py +0 -0
  85. {urwid-4.2.0 → urwid-4.2.1}/urwid/widget/box_adapter.py +0 -0
  86. {urwid-4.2.0 → urwid-4.2.1}/urwid/widget/columns.py +0 -0
  87. {urwid-4.2.0 → urwid-4.2.1}/urwid/widget/constants.py +0 -0
  88. {urwid-4.2.0 → urwid-4.2.1}/urwid/widget/container.py +0 -0
  89. {urwid-4.2.0 → urwid-4.2.1}/urwid/widget/deque_walker.py +0 -0
  90. {urwid-4.2.0 → urwid-4.2.1}/urwid/widget/divider.py +0 -0
  91. {urwid-4.2.0 → urwid-4.2.1}/urwid/widget/filler.py +0 -0
  92. {urwid-4.2.0 → urwid-4.2.1}/urwid/widget/frame.py +0 -0
  93. {urwid-4.2.0 → urwid-4.2.1}/urwid/widget/grid_flow.py +0 -0
  94. {urwid-4.2.0 → urwid-4.2.1}/urwid/widget/line_box.py +0 -0
  95. {urwid-4.2.0 → urwid-4.2.1}/urwid/widget/list_walker.py +0 -0
  96. {urwid-4.2.0 → urwid-4.2.1}/urwid/widget/listbox.py +0 -0
  97. {urwid-4.2.0 → urwid-4.2.1}/urwid/widget/monitored_deque.py +0 -0
  98. {urwid-4.2.0 → urwid-4.2.1}/urwid/widget/monitored_list.py +0 -0
  99. {urwid-4.2.0 → urwid-4.2.1}/urwid/widget/overlay.py +0 -0
  100. {urwid-4.2.0 → urwid-4.2.1}/urwid/widget/padding.py +0 -0
  101. {urwid-4.2.0 → urwid-4.2.1}/urwid/widget/pile.py +0 -0
  102. {urwid-4.2.0 → urwid-4.2.1}/urwid/widget/popup.py +0 -0
  103. {urwid-4.2.0 → urwid-4.2.1}/urwid/widget/progress_bar.py +0 -0
  104. {urwid-4.2.0 → urwid-4.2.1}/urwid/widget/scrollable.py +0 -0
  105. {urwid-4.2.0 → urwid-4.2.1}/urwid/widget/solid_fill.py +0 -0
  106. {urwid-4.2.0 → urwid-4.2.1}/urwid/widget/text.py +0 -0
  107. {urwid-4.2.0 → urwid-4.2.1}/urwid/widget/treetools.py +0 -0
  108. {urwid-4.2.0 → urwid-4.2.1}/urwid/widget/widget.py +0 -0
  109. {urwid-4.2.0 → urwid-4.2.1}/urwid/widget/widget_decoration.py +0 -0
  110. {urwid-4.2.0 → urwid-4.2.1}/urwid/widget/wimp.py +0 -0
  111. {urwid-4.2.0 → urwid-4.2.1}/urwid.egg-info/SOURCES.txt +0 -0
  112. {urwid-4.2.0 → urwid-4.2.1}/urwid.egg-info/dependency_links.txt +0 -0
  113. {urwid-4.2.0 → urwid-4.2.1}/urwid.egg-info/not-zip-safe +0 -0
  114. {urwid-4.2.0 → urwid-4.2.1}/urwid.egg-info/requires.txt +0 -0
  115. {urwid-4.2.0 → urwid-4.2.1}/urwid.egg-info/scm_file_list.json +0 -0
  116. {urwid-4.2.0 → urwid-4.2.1}/urwid.egg-info/top_level.txt +0 -0
  117. {urwid-4.2.0 → urwid-4.2.1}/yamllint-requirements.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: urwid
3
- Version: 4.2.0
3
+ Version: 4.2.1
4
4
  Summary: A full-featured console (xterm et al.) user interface library
5
5
  Author-email: Ian Ward <ian@excess.org>
6
6
  License-Expression: LGPL-2.1-only
@@ -535,7 +535,10 @@ class TextCanvas(Canvas):
535
535
  if not rows:
536
536
  rows = maxrow - trim_top
537
537
 
538
- if not ((0 <= trim_left < maxcol) and (cols > 0 and trim_left + cols <= maxcol)):
538
+ # a canvas without columns (empty text) has one region only: all of it, zero columns wide
539
+ if not (
540
+ (0 <= trim_left < maxcol and cols > 0 and trim_left + cols <= maxcol) or maxcol == trim_left == cols == 0
541
+ ):
539
542
  raise ValueError(trim_left)
540
543
  if not ((0 <= trim_top < maxrow) and (rows > 0 and trim_top + rows <= maxrow)):
541
544
  raise ValueError(trim_top)
@@ -121,26 +121,33 @@ class StandardTextLayout(TextLayout):
121
121
  A tab character advances to the next tab stop, measured in rendered screen columns
122
122
  from the start of the displayed line: explicit *tab_stops* are used first,
123
123
  then stops repeat every *tab_stop_every* columns counted from column 0.
124
+ With *tab_stop_every* ``0`` a tab past the last explicit stop takes no columns.
124
125
 
125
126
  :param tab_stops: screen columns of explicit tab stops.
126
- :param tab_stop_every: interval of the default tab stops.
127
- :raises ValueError: *tab_stop_every* or one of *tab_stops* is not a positive column.
127
+ :param tab_stop_every: interval of the default tab stops, ``0`` for none.
128
+ :raises ValueError: *tab_stop_every* is negative, or one of *tab_stops* is not a positive column.
128
129
  """
129
130
  self.tab_stops: tuple[int, ...] = tuple(sorted(set(tab_stops)))
130
- if tab_stop_every < 1 or (self.tab_stops and self.tab_stops[0] < 1):
131
+ if tab_stop_every < 0 or (self.tab_stops and self.tab_stops[0] < 1):
131
132
  raise ValueError(f"Tab stops must be positive: {tab_stops=!r}, {tab_stop_every=!r}")
132
133
  self.tab_stop_every = tab_stop_every
133
134
 
134
135
  def next_tab_stop(self, column: int) -> int:
135
136
  """Return the screen column of the first tab stop after *column*.
136
137
 
138
+ When there is no stop after *column*, return *column* itself: the tab takes no columns.
139
+
137
140
  >>> StandardTextLayout(tab_stops=(4, 10)).next_tab_stop(5)
138
141
  10
139
142
  >>> StandardTextLayout(tab_stops=(4, 10)).next_tab_stop(10)
140
143
  16
144
+ >>> StandardTextLayout(tab_stops=(4, 10), tab_stop_every=0).next_tab_stop(10)
145
+ 10
141
146
  """
142
147
  if (idx := bisect.bisect_right(self.tab_stops, column)) < len(self.tab_stops):
143
148
  return self.tab_stops[idx]
149
+ if not self.tab_stop_every:
150
+ return column
144
151
  return (column // self.tab_stop_every + 1) * self.tab_stop_every
145
152
 
146
153
  def supports_align_mode(self, align: Literal["left", "center", "right"] | Align) -> bool:
@@ -305,7 +312,10 @@ class StandardTextLayout(TextLayout):
305
312
  pos = start
306
313
  while pos < end:
307
314
  if text[pos : pos + 1] == tab:
308
- tab_width = self.next_tab_stop(column) - column
315
+ if not (tab_width := self.next_tab_stop(column) - column):
316
+ line.append((0, pos))
317
+ pos += 1
318
+ continue
309
319
  if limit is not None and column + tab_width > limit:
310
320
  if limit > column:
311
321
  line.append((limit - column, pos, b" " * (limit - column)))
@@ -355,7 +365,10 @@ class StandardTextLayout(TextLayout):
355
365
  pos = start
356
366
  while pos < end:
357
367
  if text[pos : pos + 1] == tab:
358
- if column < width:
368
+ if self.next_tab_stop(column) == column:
369
+ line.append((0, pos))
370
+ pos += 1
371
+ elif column < width:
359
372
  tab_width = min(self.next_tab_stop(column), width) - column
360
373
  line.append((tab_width, pos, b" " * tab_width))
361
374
  column += tab_width
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
18
18
  commit_id: str | None
19
19
  __commit_id__: str | None
20
20
 
21
- __version__ = version = '4.2.0'
22
- __version_tuple__ = version_tuple = (4, 2, 0)
21
+ __version__ = version = '4.2.1'
22
+ __version_tuple__ = version_tuple = (4, 2, 1)
23
23
 
24
- __commit_id__ = commit_id = 'g15c2c59b0'
24
+ __commit_id__ = commit_id = 'gf0dabd13b'
@@ -487,7 +487,8 @@ class Edit(WidgetWrap[Text]):
487
487
  if idx:
488
488
  column = layout.next_tab_stop(column)
489
489
  column += calc_width(chunk, 0, len(chunk))
490
- self.insert_text(" " * (layout.next_tab_stop(column) - column))
490
+ if spaces := layout.next_tab_stop(column) - column:
491
+ self.insert_text(" " * spaces)
491
492
  return None
492
493
 
493
494
  if key == "enter" and self.multiline:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: urwid
3
- Version: 4.2.0
3
+ Version: 4.2.1
4
4
  Summary: A full-featured console (xterm et al.) user interface library
5
5
  Author-email: Ian Ward <ian@excess.org>
6
6
  License-Expression: LGPL-2.1-only
@@ -1,7 +1,7 @@
1
1
  {
2
- "tag": "4.2.0",
2
+ "tag": "4.2.1",
3
3
  "distance": 0,
4
- "node": "g15c2c59b010d1ffe65453e7ded5dd05fae5ae6ab",
4
+ "node": "gf0dabd13b6489029422d8d7883f60e98215d811f",
5
5
  "dirty": false,
6
6
  "branch": "HEAD",
7
7
  "node_date": "2026-09-29"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes