urwid 4.0.2__tar.gz → 4.0.4__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 (317) hide show
  1. {urwid-4.0.2 → urwid-4.0.4}/.github/workflows/documentation.yml +1 -1
  2. {urwid-4.0.2 → urwid-4.0.4}/.github/workflows/isolated_static_check.yml +3 -3
  3. {urwid-4.0.2 → urwid-4.0.4}/.github/workflows/pythonpackage.yml +6 -6
  4. {urwid-4.0.2 → urwid-4.0.4}/.github/workflows/yamllint.yml +1 -1
  5. {urwid-4.0.2 → urwid-4.0.4}/.pre-commit-config.yaml +13 -7
  6. {urwid-4.0.2 → urwid-4.0.4}/PKG-INFO +5 -4
  7. {urwid-4.0.2 → urwid-4.0.4}/docs/changelog.rst +39 -0
  8. {urwid-4.0.2 → urwid-4.0.4}/docs/examples/bigtext.py +1 -1
  9. {urwid-4.0.2 → urwid-4.0.4}/docs/examples/graph.py +40 -25
  10. {urwid-4.0.2 → urwid-4.0.4}/docs/examples/pop_up.py +3 -3
  11. {urwid-4.0.2 → urwid-4.0.4}/docs/examples/real_browse.py +7 -7
  12. {urwid-4.0.2 → urwid-4.0.4}/docs/examples/real_edit.py +4 -4
  13. {urwid-4.0.2 → urwid-4.0.4}/docs/examples/tour.py +3 -3
  14. {urwid-4.0.2 → urwid-4.0.4}/examples/bigtext.py +1 -1
  15. {urwid-4.0.2 → urwid-4.0.4}/examples/browse.py +7 -7
  16. {urwid-4.0.2 → urwid-4.0.4}/examples/calc.py +40 -29
  17. {urwid-4.0.2 → urwid-4.0.4}/examples/edit.py +4 -4
  18. {urwid-4.0.2 → urwid-4.0.4}/examples/fib.py +2 -2
  19. {urwid-4.0.2 → urwid-4.0.4}/examples/graph.py +40 -25
  20. {urwid-4.0.2 → urwid-4.0.4}/examples/input_test.py +2 -2
  21. {urwid-4.0.2 → urwid-4.0.4}/examples/pop_up.py +3 -3
  22. {urwid-4.0.2 → urwid-4.0.4}/examples/terminal.py +3 -3
  23. {urwid-4.0.2 → urwid-4.0.4}/examples/tour.py +3 -3
  24. {urwid-4.0.2 → urwid-4.0.4}/examples/treesample.py +15 -8
  25. {urwid-4.0.2 → urwid-4.0.4}/examples/twisted_serve_ssh.py +2 -11
  26. urwid-4.0.4/pylint-requirements.txt +1 -0
  27. {urwid-4.0.2 → urwid-4.0.4}/pyproject.toml +257 -215
  28. urwid-4.0.4/requirements.txt +2 -0
  29. urwid-4.0.4/ruff-requirements.txt +1 -0
  30. {urwid-4.0.2 → urwid-4.0.4}/tests/test_canvas.py +0 -8
  31. {urwid-4.0.2 → urwid-4.0.4}/tests/test_tree.py +2 -2
  32. {urwid-4.0.2 → urwid-4.0.4}/tests/test_vterm.py +145 -35
  33. {urwid-4.0.2 → urwid-4.0.4}/urwid/__init__.py +1 -1
  34. {urwid-4.0.2 → urwid-4.0.4}/urwid/canvas.py +196 -118
  35. {urwid-4.0.2 → urwid-4.0.4}/urwid/command_map.py +11 -1
  36. {urwid-4.0.2 → urwid-4.0.4}/urwid/display/__init__.py +1 -1
  37. {urwid-4.0.2 → urwid-4.0.4}/urwid/display/_posix_raw_display.py +31 -19
  38. {urwid-4.0.2 → urwid-4.0.4}/urwid/display/_raw_display_base.py +118 -108
  39. {urwid-4.0.2 → urwid-4.0.4}/urwid/display/_win32_raw_display.py +17 -5
  40. {urwid-4.0.2 → urwid-4.0.4}/urwid/display/common.py +35 -24
  41. {urwid-4.0.2 → urwid-4.0.4}/urwid/display/curses.py +33 -28
  42. {urwid-4.0.2 → urwid-4.0.4}/urwid/display/escape.py +59 -43
  43. {urwid-4.0.2 → urwid-4.0.4}/urwid/display/html_fragment.py +15 -8
  44. {urwid-4.0.2 → urwid-4.0.4}/urwid/display/lcd.py +12 -12
  45. {urwid-4.0.2 → urwid-4.0.4}/urwid/display/raw.py +1 -1
  46. {urwid-4.0.2 → urwid-4.0.4}/urwid/display/web.py +25 -19
  47. {urwid-4.0.2 → urwid-4.0.4}/urwid/event_loop/abstract_loop.py +5 -5
  48. {urwid-4.0.2 → urwid-4.0.4}/urwid/event_loop/asyncio_loop.py +3 -3
  49. {urwid-4.0.2 → urwid-4.0.4}/urwid/event_loop/glib_loop.py +8 -9
  50. {urwid-4.0.2 → urwid-4.0.4}/urwid/event_loop/main_loop.py +19 -14
  51. {urwid-4.0.2 → urwid-4.0.4}/urwid/event_loop/tornado_loop.py +6 -3
  52. {urwid-4.0.2 → urwid-4.0.4}/urwid/event_loop/twisted_loop.py +15 -8
  53. {urwid-4.0.2 → urwid-4.0.4}/urwid/graphics.py +9 -4
  54. {urwid-4.0.2 → urwid-4.0.4}/urwid/numedit.py +26 -24
  55. {urwid-4.0.2 → urwid-4.0.4}/urwid/signals.py +15 -9
  56. {urwid-4.0.2 → urwid-4.0.4}/urwid/split_repr.py +18 -10
  57. {urwid-4.0.2 → urwid-4.0.4}/urwid/str_util.py +2 -2
  58. {urwid-4.0.2 → urwid-4.0.4}/urwid/text_layout.py +110 -64
  59. {urwid-4.0.2 → urwid-4.0.4}/urwid/util.py +60 -35
  60. {urwid-4.0.2 → urwid-4.0.4}/urwid/version.py +3 -3
  61. {urwid-4.0.2 → urwid-4.0.4}/urwid/vterm.py +55 -41
  62. {urwid-4.0.2 → urwid-4.0.4}/urwid/widget/attr_map.py +6 -6
  63. {urwid-4.0.2 → urwid-4.0.4}/urwid/widget/attr_wrap.py +12 -6
  64. {urwid-4.0.2 → urwid-4.0.4}/urwid/widget/bar_graph.py +12 -2
  65. {urwid-4.0.2 → urwid-4.0.4}/urwid/widget/big_text.py +9 -8
  66. {urwid-4.0.2 → urwid-4.0.4}/urwid/widget/box_adapter.py +6 -3
  67. {urwid-4.0.2 → urwid-4.0.4}/urwid/widget/columns.py +167 -88
  68. {urwid-4.0.2 → urwid-4.0.4}/urwid/widget/constants.py +6 -6
  69. {urwid-4.0.2 → urwid-4.0.4}/urwid/widget/container.py +45 -14
  70. {urwid-4.0.2 → urwid-4.0.4}/urwid/widget/edit.py +7 -5
  71. {urwid-4.0.2 → urwid-4.0.4}/urwid/widget/filler.py +1 -1
  72. {urwid-4.0.2 → urwid-4.0.4}/urwid/widget/frame.py +49 -42
  73. {urwid-4.0.2 → urwid-4.0.4}/urwid/widget/grid_flow.py +27 -19
  74. {urwid-4.0.2 → urwid-4.0.4}/urwid/widget/line_box.py +11 -6
  75. {urwid-4.0.2 → urwid-4.0.4}/urwid/widget/listbox.py +9 -8
  76. {urwid-4.0.2 → urwid-4.0.4}/urwid/widget/monitored_list.py +12 -4
  77. {urwid-4.0.2 → urwid-4.0.4}/urwid/widget/overlay.py +40 -21
  78. {urwid-4.0.2 → urwid-4.0.4}/urwid/widget/padding.py +84 -26
  79. {urwid-4.0.2 → urwid-4.0.4}/urwid/widget/pile.py +125 -62
  80. {urwid-4.0.2 → urwid-4.0.4}/urwid/widget/popup.py +8 -4
  81. {urwid-4.0.2 → urwid-4.0.4}/urwid/widget/progress_bar.py +5 -5
  82. {urwid-4.0.2 → urwid-4.0.4}/urwid/widget/text.py +10 -6
  83. {urwid-4.0.2 → urwid-4.0.4}/urwid/widget/treetools.py +36 -23
  84. {urwid-4.0.2 → urwid-4.0.4}/urwid/widget/widget.py +59 -30
  85. {urwid-4.0.2 → urwid-4.0.4}/urwid/widget/wimp.py +22 -8
  86. {urwid-4.0.2 → urwid-4.0.4}/urwid.egg-info/PKG-INFO +5 -4
  87. {urwid-4.0.2 → urwid-4.0.4}/urwid.egg-info/SOURCES.txt +2 -0
  88. {urwid-4.0.2 → urwid-4.0.4}/urwid.egg-info/requires.txt +2 -1
  89. urwid-4.0.4/urwid.egg-info/scm_file_list.json +307 -0
  90. urwid-4.0.4/urwid.egg-info/scm_version.json +8 -0
  91. urwid-4.0.2/pylint-requirements.txt +0 -1
  92. urwid-4.0.2/requirements.txt +0 -1
  93. urwid-4.0.2/ruff-requirements.txt +0 -1
  94. {urwid-4.0.2 → urwid-4.0.4}/.coveralls.yml +0 -0
  95. {urwid-4.0.2 → urwid-4.0.4}/.devcontainer/dev.dockerfile +0 -0
  96. {urwid-4.0.2 → urwid-4.0.4}/.devcontainer/devcontainer.json +0 -0
  97. {urwid-4.0.2 → urwid-4.0.4}/.dockerignore +0 -0
  98. {urwid-4.0.2 → urwid-4.0.4}/.editorconfig +0 -0
  99. {urwid-4.0.2 → urwid-4.0.4}/.github/CODE_OF_CONDUCT.md +0 -0
  100. {urwid-4.0.2 → urwid-4.0.4}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  101. {urwid-4.0.2 → urwid-4.0.4}/.github/ISSUE_TEMPLATE/docs.md +0 -0
  102. {urwid-4.0.2 → urwid-4.0.4}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  103. {urwid-4.0.2 → urwid-4.0.4}/.github/ISSUE_TEMPLATE/question.md +0 -0
  104. {urwid-4.0.2 → urwid-4.0.4}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  105. {urwid-4.0.2 → urwid-4.0.4}/.github/dependabot.yml +0 -0
  106. {urwid-4.0.2 → urwid-4.0.4}/.github/labeler.yml +0 -0
  107. {urwid-4.0.2 → urwid-4.0.4}/.github/release.yml +0 -0
  108. {urwid-4.0.2 → urwid-4.0.4}/.github/workflows/labels.yml +0 -0
  109. {urwid-4.0.2 → urwid-4.0.4}/.gitignore +0 -0
  110. {urwid-4.0.2 → urwid-4.0.4}/.yamllint.yml +0 -0
  111. {urwid-4.0.2 → urwid-4.0.4}/COPYING +0 -0
  112. {urwid-4.0.2 → urwid-4.0.4}/MANIFEST.in +0 -0
  113. {urwid-4.0.2 → urwid-4.0.4}/README.rst +0 -0
  114. {urwid-4.0.2 → urwid-4.0.4}/SECURITY.md +0 -0
  115. {urwid-4.0.2 → urwid-4.0.4}/classifiers.txt +0 -0
  116. {urwid-4.0.2 → urwid-4.0.4}/docs/Makefile +0 -0
  117. {urwid-4.0.2 → urwid-4.0.4}/docs/conf.py +0 -0
  118. {urwid-4.0.2 → urwid-4.0.4}/docs/examples/bigtext.py.xdotool +0 -0
  119. {urwid-4.0.2 → urwid-4.0.4}/docs/examples/bigtext1.png +0 -0
  120. {urwid-4.0.2 → urwid-4.0.4}/docs/examples/bigtext2.png +0 -0
  121. {urwid-4.0.2 → urwid-4.0.4}/docs/examples/bigtext3.png +0 -0
  122. {urwid-4.0.2 → urwid-4.0.4}/docs/examples/browse.py +0 -0
  123. {urwid-4.0.2 → urwid-4.0.4}/docs/examples/browse.py.xdotool +0 -0
  124. {urwid-4.0.2 → urwid-4.0.4}/docs/examples/browse1.png +0 -0
  125. {urwid-4.0.2 → urwid-4.0.4}/docs/examples/browse2.png +0 -0
  126. {urwid-4.0.2 → urwid-4.0.4}/docs/examples/edit.py +0 -0
  127. {urwid-4.0.2 → urwid-4.0.4}/docs/examples/edit.py.xdotool +0 -0
  128. {urwid-4.0.2 → urwid-4.0.4}/docs/examples/edit1.png +0 -0
  129. {urwid-4.0.2 → urwid-4.0.4}/docs/examples/edit2.png +0 -0
  130. {urwid-4.0.2 → urwid-4.0.4}/docs/examples/edit_text.txt +0 -0
  131. {urwid-4.0.2 → urwid-4.0.4}/docs/examples/graph.py.xdotool +0 -0
  132. {urwid-4.0.2 → urwid-4.0.4}/docs/examples/graph1.png +0 -0
  133. {urwid-4.0.2 → urwid-4.0.4}/docs/examples/graph2.png +0 -0
  134. {urwid-4.0.2 → urwid-4.0.4}/docs/examples/index.rst +0 -0
  135. {urwid-4.0.2 → urwid-4.0.4}/docs/examples/palette_test.py +0 -0
  136. {urwid-4.0.2 → urwid-4.0.4}/docs/examples/palette_test.py.xdotool +0 -0
  137. {urwid-4.0.2 → urwid-4.0.4}/docs/examples/palette_test1.png +0 -0
  138. {urwid-4.0.2 → urwid-4.0.4}/docs/examples/palette_test2.png +0 -0
  139. {urwid-4.0.2 → urwid-4.0.4}/docs/examples/pop_up.py.xdotool +0 -0
  140. {urwid-4.0.2 → urwid-4.0.4}/docs/examples/pop_up1.png +0 -0
  141. {urwid-4.0.2 → urwid-4.0.4}/docs/examples/pop_up2.png +0 -0
  142. {urwid-4.0.2 → urwid-4.0.4}/docs/examples/subproc.py +0 -0
  143. {urwid-4.0.2 → urwid-4.0.4}/docs/examples/subproc.py.xdotool +0 -0
  144. {urwid-4.0.2 → urwid-4.0.4}/docs/examples/subproc1.png +0 -0
  145. {urwid-4.0.2 → urwid-4.0.4}/docs/examples/subproc2.png +0 -0
  146. {urwid-4.0.2 → urwid-4.0.4}/docs/examples/subproc2.py +0 -0
  147. {urwid-4.0.2 → urwid-4.0.4}/docs/examples/tour.py.xdotool +0 -0
  148. {urwid-4.0.2 → urwid-4.0.4}/docs/examples/tour1.png +0 -0
  149. {urwid-4.0.2 → urwid-4.0.4}/docs/examples/tour2.png +0 -0
  150. {urwid-4.0.2 → urwid-4.0.4}/docs/index.rst +0 -0
  151. {urwid-4.0.2 → urwid-4.0.4}/docs/manual/bright_combinations.py +0 -0
  152. {urwid-4.0.2 → urwid-4.0.4}/docs/manual/bright_combinations.py.xdotool +0 -0
  153. {urwid-4.0.2 → urwid-4.0.4}/docs/manual/bright_combinations1.png +0 -0
  154. {urwid-4.0.2 → urwid-4.0.4}/docs/manual/canvascache.rst +0 -0
  155. {urwid-4.0.2 → urwid-4.0.4}/docs/manual/displayattributes.rst +0 -0
  156. {urwid-4.0.2 → urwid-4.0.4}/docs/manual/displaymodules.rst +0 -0
  157. {urwid-4.0.2 → urwid-4.0.4}/docs/manual/encodings.rst +0 -0
  158. {urwid-4.0.2 → urwid-4.0.4}/docs/manual/images/display_modules.png +0 -0
  159. {urwid-4.0.2 → urwid-4.0.4}/docs/manual/images/introduction.png +0 -0
  160. {urwid-4.0.2 → urwid-4.0.4}/docs/manual/images/urwid_widgets.svgz +0 -0
  161. {urwid-4.0.2 → urwid-4.0.4}/docs/manual/images/urwid_widgets_1.png +0 -0
  162. {urwid-4.0.2 → urwid-4.0.4}/docs/manual/images/urwid_widgets_1.xcf +0 -0
  163. {urwid-4.0.2 → urwid-4.0.4}/docs/manual/images/urwid_widgets_2.png +0 -0
  164. {urwid-4.0.2 → urwid-4.0.4}/docs/manual/images/urwid_widgets_2.xcf +0 -0
  165. {urwid-4.0.2 → urwid-4.0.4}/docs/manual/images/widget_layout.png +0 -0
  166. {urwid-4.0.2 → urwid-4.0.4}/docs/manual/index.rst +0 -0
  167. {urwid-4.0.2 → urwid-4.0.4}/docs/manual/mainloop.rst +0 -0
  168. {urwid-4.0.2 → urwid-4.0.4}/docs/manual/overview.rst +0 -0
  169. {urwid-4.0.2 → urwid-4.0.4}/docs/manual/safe_combinations.py +0 -0
  170. {urwid-4.0.2 → urwid-4.0.4}/docs/manual/safe_combinations.py.xdotool +0 -0
  171. {urwid-4.0.2 → urwid-4.0.4}/docs/manual/safe_combinations1.png +0 -0
  172. {urwid-4.0.2 → urwid-4.0.4}/docs/manual/textlayout.rst +0 -0
  173. {urwid-4.0.2 → urwid-4.0.4}/docs/manual/userinput.rst +0 -0
  174. {urwid-4.0.2 → urwid-4.0.4}/docs/manual/wanat.py +0 -0
  175. {urwid-4.0.2 → urwid-4.0.4}/docs/manual/wanat_multi.py +0 -0
  176. {urwid-4.0.2 → urwid-4.0.4}/docs/manual/wcur1.py +0 -0
  177. {urwid-4.0.2 → urwid-4.0.4}/docs/manual/wcur2.py +0 -0
  178. {urwid-4.0.2 → urwid-4.0.4}/docs/manual/widgets.rst +0 -0
  179. {urwid-4.0.2 → urwid-4.0.4}/docs/manual/wmod.py +0 -0
  180. {urwid-4.0.2 → urwid-4.0.4}/docs/manual/wsel.py +0 -0
  181. {urwid-4.0.2 → urwid-4.0.4}/docs/reference/attrspec.rst +0 -0
  182. {urwid-4.0.2 → urwid-4.0.4}/docs/reference/canvas.rst +0 -0
  183. {urwid-4.0.2 → urwid-4.0.4}/docs/reference/command_map.rst +0 -0
  184. {urwid-4.0.2 → urwid-4.0.4}/docs/reference/constants.rst +0 -0
  185. {urwid-4.0.2 → urwid-4.0.4}/docs/reference/deprecated.rst +0 -0
  186. {urwid-4.0.2 → urwid-4.0.4}/docs/reference/display_modules.rst +0 -0
  187. {urwid-4.0.2 → urwid-4.0.4}/docs/reference/exceptions.rst +0 -0
  188. {urwid-4.0.2 → urwid-4.0.4}/docs/reference/global_settings.rst +0 -0
  189. {urwid-4.0.2 → urwid-4.0.4}/docs/reference/index.rst +0 -0
  190. {urwid-4.0.2 → urwid-4.0.4}/docs/reference/list_walkers.rst +0 -0
  191. {urwid-4.0.2 → urwid-4.0.4}/docs/reference/main_loop.rst +0 -0
  192. {urwid-4.0.2 → urwid-4.0.4}/docs/reference/meta.rst +0 -0
  193. {urwid-4.0.2 → urwid-4.0.4}/docs/reference/signals.rst +0 -0
  194. {urwid-4.0.2 → urwid-4.0.4}/docs/reference/text_layout.rst +0 -0
  195. {urwid-4.0.2 → urwid-4.0.4}/docs/reference/widget.rst +0 -0
  196. {urwid-4.0.2 → urwid-4.0.4}/docs/tools/compile_pngs.sh +0 -0
  197. {urwid-4.0.2 → urwid-4.0.4}/docs/tools/screenshots.sh +0 -0
  198. {urwid-4.0.2 → urwid-4.0.4}/docs/tools/static/.placeholder +0 -0
  199. {urwid-4.0.2 → urwid-4.0.4}/docs/tools/templates/indexcontent.html +0 -0
  200. {urwid-4.0.2 → urwid-4.0.4}/docs/tools/templates/indexsidebar.html +0 -0
  201. {urwid-4.0.2 → urwid-4.0.4}/docs/tools/templates/localtoc.html +0 -0
  202. {urwid-4.0.2 → urwid-4.0.4}/docs/tutorial/adventure.py +0 -0
  203. {urwid-4.0.2 → urwid-4.0.4}/docs/tutorial/adventure.py.xdotool +0 -0
  204. {urwid-4.0.2 → urwid-4.0.4}/docs/tutorial/adventure1.png +0 -0
  205. {urwid-4.0.2 → urwid-4.0.4}/docs/tutorial/adventure2.png +0 -0
  206. {urwid-4.0.2 → urwid-4.0.4}/docs/tutorial/adventure3.png +0 -0
  207. {urwid-4.0.2 → urwid-4.0.4}/docs/tutorial/adventure4.png +0 -0
  208. {urwid-4.0.2 → urwid-4.0.4}/docs/tutorial/cmenu.py +0 -0
  209. {urwid-4.0.2 → urwid-4.0.4}/docs/tutorial/cmenu.py.xdotool +0 -0
  210. {urwid-4.0.2 → urwid-4.0.4}/docs/tutorial/cmenu1.png +0 -0
  211. {urwid-4.0.2 → urwid-4.0.4}/docs/tutorial/cmenu2.png +0 -0
  212. {urwid-4.0.2 → urwid-4.0.4}/docs/tutorial/cmenu3.png +0 -0
  213. {urwid-4.0.2 → urwid-4.0.4}/docs/tutorial/cmenu4.png +0 -0
  214. {urwid-4.0.2 → urwid-4.0.4}/docs/tutorial/highcolors.py +0 -0
  215. {urwid-4.0.2 → urwid-4.0.4}/docs/tutorial/highcolors.py.xdotool +0 -0
  216. {urwid-4.0.2 → urwid-4.0.4}/docs/tutorial/highcolors1.png +0 -0
  217. {urwid-4.0.2 → urwid-4.0.4}/docs/tutorial/hmenu.py +0 -0
  218. {urwid-4.0.2 → urwid-4.0.4}/docs/tutorial/hmenu.py.xdotool +0 -0
  219. {urwid-4.0.2 → urwid-4.0.4}/docs/tutorial/hmenu1.png +0 -0
  220. {urwid-4.0.2 → urwid-4.0.4}/docs/tutorial/hmenu2.png +0 -0
  221. {urwid-4.0.2 → urwid-4.0.4}/docs/tutorial/hmenu3.png +0 -0
  222. {urwid-4.0.2 → urwid-4.0.4}/docs/tutorial/hmenu4.png +0 -0
  223. {urwid-4.0.2 → urwid-4.0.4}/docs/tutorial/index.rst +0 -0
  224. {urwid-4.0.2 → urwid-4.0.4}/docs/tutorial/input.py +0 -0
  225. {urwid-4.0.2 → urwid-4.0.4}/docs/tutorial/input.py.xdotool +0 -0
  226. {urwid-4.0.2 → urwid-4.0.4}/docs/tutorial/input1.png +0 -0
  227. {urwid-4.0.2 → urwid-4.0.4}/docs/tutorial/input2.png +0 -0
  228. {urwid-4.0.2 → urwid-4.0.4}/docs/tutorial/input3.png +0 -0
  229. {urwid-4.0.2 → urwid-4.0.4}/docs/tutorial/input4.png +0 -0
  230. {urwid-4.0.2 → urwid-4.0.4}/docs/tutorial/input5.png +0 -0
  231. {urwid-4.0.2 → urwid-4.0.4}/docs/tutorial/menu25.png +0 -0
  232. {urwid-4.0.2 → urwid-4.0.4}/docs/tutorial/minimal.py +0 -0
  233. {urwid-4.0.2 → urwid-4.0.4}/docs/tutorial/minimal.py.xdotool +0 -0
  234. {urwid-4.0.2 → urwid-4.0.4}/docs/tutorial/minimal1.png +0 -0
  235. {urwid-4.0.2 → urwid-4.0.4}/docs/tutorial/multiple.py +0 -0
  236. {urwid-4.0.2 → urwid-4.0.4}/docs/tutorial/multiple.py.xdotool +0 -0
  237. {urwid-4.0.2 → urwid-4.0.4}/docs/tutorial/multiple1.png +0 -0
  238. {urwid-4.0.2 → urwid-4.0.4}/docs/tutorial/multiple2.png +0 -0
  239. {urwid-4.0.2 → urwid-4.0.4}/docs/tutorial/multiple3.png +0 -0
  240. {urwid-4.0.2 → urwid-4.0.4}/docs/tutorial/multiple4.png +0 -0
  241. {urwid-4.0.2 → urwid-4.0.4}/docs/tutorial/qa.py +0 -0
  242. {urwid-4.0.2 → urwid-4.0.4}/docs/tutorial/qa.py.xdotool +0 -0
  243. {urwid-4.0.2 → urwid-4.0.4}/docs/tutorial/qa1.png +0 -0
  244. {urwid-4.0.2 → urwid-4.0.4}/docs/tutorial/qa2.png +0 -0
  245. {urwid-4.0.2 → urwid-4.0.4}/docs/tutorial/qa3.png +0 -0
  246. {urwid-4.0.2 → urwid-4.0.4}/docs/tutorial/sig.py +0 -0
  247. {urwid-4.0.2 → urwid-4.0.4}/docs/tutorial/sig.py.xdotool +0 -0
  248. {urwid-4.0.2 → urwid-4.0.4}/docs/tutorial/sig1.png +0 -0
  249. {urwid-4.0.2 → urwid-4.0.4}/docs/tutorial/sig2.png +0 -0
  250. {urwid-4.0.2 → urwid-4.0.4}/docs/tutorial/sig3.png +0 -0
  251. {urwid-4.0.2 → urwid-4.0.4}/docs/tutorial/sig4.png +0 -0
  252. {urwid-4.0.2 → urwid-4.0.4}/docs/tutorial/smenu.py +0 -0
  253. {urwid-4.0.2 → urwid-4.0.4}/docs/tutorial/smenu.py.xdotool +0 -0
  254. {urwid-4.0.2 → urwid-4.0.4}/docs/tutorial/smenu1.png +0 -0
  255. {urwid-4.0.2 → urwid-4.0.4}/docs/tutorial/smenu2.png +0 -0
  256. {urwid-4.0.2 → urwid-4.0.4}/docs/tutorial/smenu3.png +0 -0
  257. {urwid-4.0.2 → urwid-4.0.4}/docs/tutorial/urwid_attr.py +0 -0
  258. {urwid-4.0.2 → urwid-4.0.4}/docs/tutorial/urwid_attr.py.xdotool +0 -0
  259. {urwid-4.0.2 → urwid-4.0.4}/docs/tutorial/urwid_attr1.png +0 -0
  260. {urwid-4.0.2 → urwid-4.0.4}/docs/tutorial/urwid_attr2.png +0 -0
  261. {urwid-4.0.2 → urwid-4.0.4}/docs/tutorial/urwid_attr3.png +0 -0
  262. {urwid-4.0.2 → urwid-4.0.4}/docs/tutorial/urwid_attr4.png +0 -0
  263. {urwid-4.0.2 → urwid-4.0.4}/docs/urwid-logo.png +0 -0
  264. {urwid-4.0.2 → urwid-4.0.4}/examples/asyncio_socket_server.py +0 -0
  265. {urwid-4.0.2 → urwid-4.0.4}/examples/dialog.py +0 -0
  266. {urwid-4.0.2 → urwid-4.0.4}/examples/lcd_cf635.py +0 -0
  267. {urwid-4.0.2 → urwid-4.0.4}/examples/palette_test.py +0 -0
  268. {urwid-4.0.2 → urwid-4.0.4}/examples/subproc.py +0 -0
  269. {urwid-4.0.2 → urwid-4.0.4}/examples/subproc2.py +0 -0
  270. {urwid-4.0.2 → urwid-4.0.4}/examples/twisted_serve_ssh.tac +0 -0
  271. {urwid-4.0.2 → urwid-4.0.4}/setup.cfg +0 -0
  272. {urwid-4.0.2 → urwid-4.0.4}/test_requirements.txt +0 -0
  273. {urwid-4.0.2 → urwid-4.0.4}/tests/__init__.py +0 -0
  274. {urwid-4.0.2 → urwid-4.0.4}/tests/test_columns.py +0 -0
  275. {urwid-4.0.2 → urwid-4.0.4}/tests/test_container.py +0 -0
  276. {urwid-4.0.2 → urwid-4.0.4}/tests/test_doctests.py +0 -0
  277. {urwid-4.0.2 → urwid-4.0.4}/tests/test_escapes.py +0 -0
  278. {urwid-4.0.2 → urwid-4.0.4}/tests/test_event_loops.py +0 -0
  279. {urwid-4.0.2 → urwid-4.0.4}/tests/test_filler.py +0 -0
  280. {urwid-4.0.2 → urwid-4.0.4}/tests/test_floatedit.py +0 -0
  281. {urwid-4.0.2 → urwid-4.0.4}/tests/test_font.py +0 -0
  282. {urwid-4.0.2 → urwid-4.0.4}/tests/test_frame.py +0 -0
  283. {urwid-4.0.2 → urwid-4.0.4}/tests/test_grapheme_clusters.py +0 -0
  284. {urwid-4.0.2 → urwid-4.0.4}/tests/test_graphics.py +0 -0
  285. {urwid-4.0.2 → urwid-4.0.4}/tests/test_grid_flow.py +0 -0
  286. {urwid-4.0.2 → urwid-4.0.4}/tests/test_line_box.py +0 -0
  287. {urwid-4.0.2 → urwid-4.0.4}/tests/test_listbox.py +0 -0
  288. {urwid-4.0.2 → urwid-4.0.4}/tests/test_main_loop.py +0 -0
  289. {urwid-4.0.2 → urwid-4.0.4}/tests/test_overlay.py +0 -0
  290. {urwid-4.0.2 → urwid-4.0.4}/tests/test_padding.py +0 -0
  291. {urwid-4.0.2 → urwid-4.0.4}/tests/test_pile.py +0 -0
  292. {urwid-4.0.2 → urwid-4.0.4}/tests/test_raw_display.py +0 -0
  293. {urwid-4.0.2 → urwid-4.0.4}/tests/test_scrollable.py +0 -0
  294. {urwid-4.0.2 → urwid-4.0.4}/tests/test_signals.py +0 -0
  295. {urwid-4.0.2 → urwid-4.0.4}/tests/test_str_util.py +0 -0
  296. {urwid-4.0.2 → urwid-4.0.4}/tests/test_text_layout.py +0 -0
  297. {urwid-4.0.2 → urwid-4.0.4}/tests/test_util.py +0 -0
  298. {urwid-4.0.2 → urwid-4.0.4}/tests/test_widget.py +0 -0
  299. {urwid-4.0.2 → urwid-4.0.4}/tests/util.py +0 -0
  300. {urwid-4.0.2 → urwid-4.0.4}/tox.ini +0 -0
  301. {urwid-4.0.2 → urwid-4.0.4}/urwid/display/_web.css +0 -0
  302. {urwid-4.0.2 → urwid-4.0.4}/urwid/display/_web.js +0 -0
  303. {urwid-4.0.2 → urwid-4.0.4}/urwid/display/_win32.py +0 -0
  304. {urwid-4.0.2 → urwid-4.0.4}/urwid/event_loop/__init__.py +0 -0
  305. {urwid-4.0.2 → urwid-4.0.4}/urwid/event_loop/select_loop.py +0 -0
  306. {urwid-4.0.2 → urwid-4.0.4}/urwid/event_loop/trio_loop.py +0 -0
  307. {urwid-4.0.2 → urwid-4.0.4}/urwid/event_loop/zmq_loop.py +0 -0
  308. {urwid-4.0.2 → urwid-4.0.4}/urwid/font.py +0 -0
  309. {urwid-4.0.2 → urwid-4.0.4}/urwid/py.typed +0 -0
  310. {urwid-4.0.2 → urwid-4.0.4}/urwid/widget/__init__.py +0 -0
  311. {urwid-4.0.2 → urwid-4.0.4}/urwid/widget/divider.py +0 -0
  312. {urwid-4.0.2 → urwid-4.0.4}/urwid/widget/scrollable.py +0 -0
  313. {urwid-4.0.2 → urwid-4.0.4}/urwid/widget/solid_fill.py +0 -0
  314. {urwid-4.0.2 → urwid-4.0.4}/urwid/widget/widget_decoration.py +0 -0
  315. {urwid-4.0.2 → urwid-4.0.4}/urwid.egg-info/dependency_links.txt +0 -0
  316. {urwid-4.0.2 → urwid-4.0.4}/urwid.egg-info/not-zip-safe +0 -0
  317. {urwid-4.0.2 → urwid-4.0.4}/urwid.egg-info/top_level.txt +0 -0
@@ -23,7 +23,7 @@ jobs:
23
23
  Build:
24
24
  runs-on: ubuntu-latest
25
25
  steps:
26
- - uses: actions/checkout@v6
26
+ - uses: actions/checkout@v7
27
27
  with:
28
28
  fetch-depth: 0 # need for setuptools_scm
29
29
  - name: Set up Python
@@ -14,7 +14,7 @@ jobs:
14
14
  name: Validate formatting
15
15
  runs-on: ubuntu-latest
16
16
  steps:
17
- - uses: actions/checkout@v6
17
+ - uses: actions/checkout@v7
18
18
  - name: Set up Python
19
19
  uses: actions/setup-python@v6
20
20
  with:
@@ -32,7 +32,7 @@ jobs:
32
32
  name: Check with Ruff
33
33
  runs-on: ubuntu-latest
34
34
  steps:
35
- - uses: actions/checkout@v6
35
+ - uses: actions/checkout@v7
36
36
  - name: Set up Python
37
37
  uses: actions/setup-python@v6
38
38
  with:
@@ -50,7 +50,7 @@ jobs:
50
50
  name: Check with pylint
51
51
  runs-on: ubuntu-latest
52
52
  steps:
53
- - uses: actions/checkout@v6
53
+ - uses: actions/checkout@v7
54
54
  - name: Install Ubuntu dependencies
55
55
  run: |
56
56
  sudo apt-get -qq update
@@ -30,7 +30,7 @@ jobs:
30
30
  name: Validate formatting
31
31
  runs-on: ubuntu-latest
32
32
  steps:
33
- - uses: actions/checkout@v6
33
+ - uses: actions/checkout@v7
34
34
  - name: Set up Python
35
35
  uses: actions/setup-python@v6
36
36
  with:
@@ -48,7 +48,7 @@ jobs:
48
48
  name: Check with Ruff
49
49
  runs-on: ubuntu-latest
50
50
  steps:
51
- - uses: actions/checkout@v6
51
+ - uses: actions/checkout@v7
52
52
  - name: Set up Python
53
53
  uses: actions/setup-python@v6
54
54
  with:
@@ -66,7 +66,7 @@ jobs:
66
66
  name: Check with pylint
67
67
  runs-on: ubuntu-latest
68
68
  steps:
69
- - uses: actions/checkout@v6
69
+ - uses: actions/checkout@v7
70
70
  - name: Install Ubuntu dependencies
71
71
  run: |
72
72
  sudo apt-get -qq update
@@ -102,7 +102,7 @@ jobs:
102
102
  python-version: "3.14"
103
103
 
104
104
  steps:
105
- - uses: actions/checkout@v6
105
+ - uses: actions/checkout@v7
106
106
  with:
107
107
  fetch-depth: 0 # need for setuptools_scm
108
108
  - name: Set up Python ${{ matrix.python-version }}
@@ -158,7 +158,7 @@ jobs:
158
158
  needs: [ Test, Ruff-format, Ruff, PyLint ]
159
159
  runs-on: ubuntu-latest
160
160
  steps:
161
- - uses: actions/checkout@v6
161
+ - uses: actions/checkout@v7
162
162
  with:
163
163
  fetch-depth: 0 # need for setuptools_scm
164
164
 
@@ -189,7 +189,7 @@ jobs:
189
189
  runs-on: ubuntu-latest
190
190
  needs: [ build ]
191
191
  steps:
192
- - uses: actions/checkout@v6
192
+ - uses: actions/checkout@v7
193
193
  - name: Set up Python
194
194
  uses: actions/setup-python@v6
195
195
  with:
@@ -10,7 +10,7 @@ jobs:
10
10
  check:
11
11
  runs-on: ubuntu-latest
12
12
  steps:
13
- - uses: actions/checkout@v6
13
+ - uses: actions/checkout@v7
14
14
  - name: Set up Python
15
15
  uses: actions/setup-python@v6
16
16
  with:
@@ -2,23 +2,29 @@ repos:
2
2
  - repo: https://github.com/pre-commit/pre-commit-hooks
3
3
  rev: v6.0.0
4
4
  hooks:
5
- - id: check-yaml
6
5
  - id: end-of-file-fixer
7
6
  - id: trailing-whitespace
8
7
  - id: mixed-line-ending
8
+ args: [ --fix=lf ]
9
+ - id: check-yaml
10
+ - id: check-toml
11
+ - id: check-json
12
+ - id: check-merge-conflict
9
13
 
10
14
  - repo: https://github.com/astral-sh/ruff-pre-commit
11
- # Ruff version.
12
- rev: v0.14.5
15
+ rev: v0.15.18
13
16
  hooks:
14
- # Run the linter.
15
17
  - id: ruff-check
16
- args: [ --fix ]
17
- # Run the formatter.
18
+ args: [ --show-fixes, --fix ]
18
19
  - id: ruff-format
19
20
 
21
+ - repo: https://github.com/tox-dev/pyproject-fmt
22
+ rev: v2.25.0
23
+ hooks:
24
+ - id: pyproject-fmt
25
+
20
26
  - repo: https://github.com/adrienverge/yamllint.git
21
- rev: v1.37.1
27
+ rev: v1.38.0
22
28
  hooks:
23
29
  - id: yamllint
24
30
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: urwid
3
- Version: 4.0.2
3
+ Version: 4.0.4
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
@@ -8,7 +8,7 @@ Project-URL: Homepage, https://urwid.org/
8
8
  Project-URL: Documentation, https://urwid.org/manual/index.html
9
9
  Project-URL: Repository, https://github.com/urwid/urwid
10
10
  Project-URL: Bug Tracker, https://github.com/urwid/urwid/issues
11
- Keywords: curses,ui,widget,scroll,listbox,user interface,text layout,console,ncurses
11
+ Keywords: console,curses,listbox,ncurses,scroll,text layout,ui,user interface,widget
12
12
  Platform: unix-like
13
13
  Classifier: Development Status :: 5 - Production/Stable
14
14
  Classifier: Environment :: Console
@@ -34,15 +34,16 @@ Requires-Python: >=3.9.0
34
34
  Description-Content-Type: text/x-rst
35
35
  License-File: COPYING
36
36
  Requires-Dist: wcwidth>=0.4
37
+ Requires-Dist: typing-extensions
37
38
  Provides-Extra: curses
38
39
  Requires-Dist: windows-curses; sys_platform == "win32" and extra == "curses"
39
40
  Provides-Extra: glib
40
- Requires-Dist: PyGObject; extra == "glib"
41
+ Requires-Dist: pygobject; extra == "glib"
41
42
  Provides-Extra: tornado
42
43
  Requires-Dist: tornado>=5.0; extra == "tornado"
43
44
  Provides-Extra: trio
44
- Requires-Dist: trio>=0.24.0; extra == "trio"
45
45
  Requires-Dist: exceptiongroup; python_version < "3.11" and extra == "trio"
46
+ Requires-Dist: trio>=0.24.0; extra == "trio"
46
47
  Provides-Extra: twisted
47
48
  Requires-Dist: twisted; extra == "twisted"
48
49
  Provides-Extra: zmq
@@ -2,6 +2,45 @@
2
2
  Changelog
3
3
  ---------
4
4
 
5
+ Urwid 4.0.4
6
+ ===========
7
+
8
+ 2026-07-13
9
+
10
+ New features 🗹
11
+ +++++++++++++++
12
+ * urwid.Colmns: re-calculate column_widths only if pack widgets changed by @penguinolog in https://github.com/urwid/urwid/pull/1178
13
+ Bug fixes 🕷
14
+ ++++++++++++
15
+ * Fix IndexError in decompose_tagmarkup when a nested sublist is empty by @gaoflow in https://github.com/urwid/urwid/pull/1172
16
+ Documentation 🕮
17
+ ++++++++++++++++
18
+ * Typing: partially annotate examples and fix annotations by @penguinolog in https://github.com/urwid/urwid/pull/1173
19
+ * urwid.WidgetContainerMixin: return use protocol base class by @penguinolog in https://github.com/urwid/urwid/pull/1181
20
+
21
+ New Contributors
22
+ ++++++++++++++++
23
+ * @gaoflow made their first contribution in https://github.com/urwid/urwid/pull/1172
24
+
25
+ **Full Changelog**: https://github.com/urwid/urwid/compare/4.0.3...4.0.4
26
+
27
+ Urwid 4.0.3
28
+ ===========
29
+
30
+ 2026-06-25
31
+
32
+ Deprecations ⚡
33
+ ++++++++++++++
34
+ * Deprecate `content_delta` as unused by @penguinolog in https://github.com/urwid/urwid/pull/1151
35
+ Bug fixes 🕷
36
+ ++++++++++++
37
+ * Fix `shard_body_row`: falsy content_iter raises ValueError by @penguinolog in https://github.com/urwid/urwid/pull/1162
38
+ Documentation 🕮
39
+ ++++++++++++++++
40
+ * Mass typing annotations fixes.
41
+
42
+ **Full Changelog**: https://github.com/urwid/urwid/compare/4.0.2...4.0.3
43
+
5
44
  Urwid 4.0.2
6
45
  ===========
7
46
 
@@ -48,7 +48,7 @@ class SwitchingPadding(urwid.Padding[_Wrapped]):
48
48
 
49
49
 
50
50
  class BigTextDisplay:
51
- palette: typing.ClassVar[list[tuple[str, str, str, ...]]] = [
51
+ palette: typing.ClassVar[list[tuple[str, str, str] | tuple[str, str, str, str]]] = [
52
52
  ("body", "black", "light gray", "standout"),
53
53
  ("header", "white", "dark red", "bold"),
54
54
  ("button normal", "light gray", "dark blue", "standout"),
@@ -33,6 +33,9 @@ import typing
33
33
 
34
34
  import urwid
35
35
 
36
+ if typing.TYPE_CHECKING:
37
+ from collections.abc import Callable
38
+
36
39
  UPDATE_INTERVAL = 0.2
37
40
 
38
41
 
@@ -52,7 +55,7 @@ class GraphModel:
52
55
 
53
56
  data_max_value = 100
54
57
 
55
- def __init__(self):
58
+ def __init__(self) -> None:
56
59
  data = [
57
60
  ("Saw", list(range(0, 100, 2)) * 2),
58
61
  ("Square", [0] * 30 + [100] * 30),
@@ -66,13 +69,13 @@ class GraphModel:
66
69
  self.modes.append(m)
67
70
  self.data[m] = d
68
71
 
69
- def get_modes(self):
72
+ def get_modes(self) -> list[str]:
70
73
  return self.modes
71
74
 
72
- def set_mode(self, m) -> None:
75
+ def set_mode(self, m: str) -> None:
73
76
  self.current_mode = m
74
77
 
75
- def get_data(self, offset, r):
78
+ def get_data(self, offset: int, r):
76
79
  """
77
80
  Return the data in [offset:offset+r], the maximum value
78
81
  for items returned, and the offset at which the data
@@ -95,7 +98,7 @@ class GraphView(urwid.WidgetWrap):
95
98
  graph display.
96
99
  """
97
100
 
98
- palette: typing.ClassVar[tuple[str, str, str, ...]] = [
101
+ palette: typing.ClassVar[list[tuple[str, str, str] | tuple[str, str, str, str]]] = [
99
102
  ("body", "black", "light gray", "standout"),
100
103
  ("header", "white", "dark red", "bold"),
101
104
  ("screen edge", "light blue", "dark cyan"),
@@ -118,7 +121,7 @@ class GraphView(urwid.WidgetWrap):
118
121
  graph_num_bars = 5
119
122
  graph_offset_per_second = 5
120
123
 
121
- def __init__(self, controller):
124
+ def __init__(self, controller) -> None:
122
125
  self.controller = controller
123
126
  self.started = True
124
127
  self.start_time = None
@@ -126,7 +129,7 @@ class GraphView(urwid.WidgetWrap):
126
129
  self.last_offset = None
127
130
  super().__init__(self.main_window())
128
131
 
129
- def get_offset_now(self):
132
+ def get_offset_now(self) -> int:
130
133
  if self.start_time is None:
131
134
  return 0
132
135
  if not self.started:
@@ -134,7 +137,7 @@ class GraphView(urwid.WidgetWrap):
134
137
  tdelta = time.time() - self.start_time
135
138
  return int(self.offset + (tdelta * self.graph_offset_per_second))
136
139
 
137
- def update_graph(self, force_update=False):
140
+ def update_graph(self, force_update: bool = False) -> bool:
138
141
  o = self.get_offset_now()
139
142
  if o == self.last_offset and not force_update:
140
143
  return False
@@ -164,32 +167,32 @@ class GraphView(urwid.WidgetWrap):
164
167
  self.animate_progress.current = prog
165
168
  return True
166
169
 
167
- def on_animate_button(self, button):
170
+ def on_animate_button(self, button: urwid.AttrMap[urwid.Button]) -> None:
168
171
  """Toggle started state and button text."""
169
172
  if self.started: # stop animation
170
- button.base_widget.set_label("Start")
173
+ button.set_label("Start")
171
174
  self.offset = self.get_offset_now()
172
175
  self.started = False
173
176
  self.controller.stop_animation()
174
177
  else:
175
- button.base_widget.set_label("Stop")
178
+ button.set_label("Stop")
176
179
  self.started = True
177
180
  self.start_time = time.time()
178
181
  self.controller.animate_graph()
179
182
 
180
- def on_reset_button(self, w):
183
+ def on_reset_button(self, w: urwid.Button) -> None:
181
184
  self.offset = 0
182
185
  self.start_time = time.time()
183
186
  self.update_graph(True)
184
187
 
185
- def on_mode_button(self, button, state):
188
+ def on_mode_button(self, button: urwid.RadioButton, state: bool) -> None:
186
189
  """Notify the controller of a new mode setting."""
187
190
  if state:
188
191
  # The new mode is the label of the button
189
192
  self.controller.set_mode(button.get_label())
190
193
  self.last_offset = None
191
194
 
192
- def on_mode_change(self, m):
195
+ def on_mode_change(self, m: str) -> None:
193
196
  """Handle external mode change by updating radio buttons."""
194
197
  for rb in self.mode_buttons:
195
198
  if rb.base_widget.label == m:
@@ -197,7 +200,7 @@ class GraphView(urwid.WidgetWrap):
197
200
  break
198
201
  self.last_offset = None
199
202
 
200
- def on_unicode_checkbox(self, w, state):
203
+ def on_unicode_checkbox(self, w: urwid.CheckBox, state: bool) -> None:
201
204
  self.graph = self.bar_graph(state)
202
205
  self.graph_wrap._w = self.graph
203
206
  self.animate_progress = self.progress_bar(state)
@@ -235,30 +238,42 @@ class GraphView(urwid.WidgetWrap):
235
238
  )
236
239
  return w
237
240
 
238
- def bar_graph(self, smooth=False):
241
+ def bar_graph(self, smooth: bool = False) -> urwid.BarGraph:
239
242
  satt = None
240
243
  if smooth:
241
244
  satt = {(1, 0): "bg 1 smooth", (2, 0): "bg 2 smooth"}
242
245
  w = urwid.BarGraph(["bg background", "bg 1", "bg 2"], satt=satt)
243
246
  return w
244
247
 
245
- def button(self, t, fn):
248
+ def button(
249
+ self,
250
+ t: str,
251
+ fn: Callable[[urwid.Button], None],
252
+ ) -> urwid.AttrMap[urwid.Button]:
246
253
  w = urwid.Button(t, fn)
247
254
  w = urwid.AttrMap(w, "button normal", "button select")
248
255
  return w
249
256
 
250
- def radio_button(self, g, label, fn):
257
+ def radio_button(
258
+ self,
259
+ g: list[urwid.RadioButton],
260
+ label: str,
261
+ fn: Callable[[urwid.RadioButton, bool], None],
262
+ ) -> urwid.AttrMap[urwid.RadioButton]:
251
263
  w = urwid.RadioButton(g, label, False, on_state_change=fn)
252
264
  w = urwid.AttrMap(w, "button normal", "button select")
253
265
  return w
254
266
 
255
- def progress_bar(self, smooth=False):
256
- if smooth:
257
- return urwid.ProgressBar("pg normal", "pg complete", 0, 1, "pg smooth")
258
-
259
- return urwid.ProgressBar("pg normal", "pg complete", 0, 1)
267
+ def progress_bar(self, smooth: bool = False) -> urwid.ProgressBar:
268
+ return urwid.ProgressBar(
269
+ "pg normal",
270
+ "pg complete",
271
+ 0,
272
+ 1,
273
+ "pg smooth" if smooth else None,
274
+ )
260
275
 
261
- def exit_program(self, w):
276
+ def exit_program(self, w) -> typing.NoReturn:
262
277
  raise urwid.ExitMainLoop()
263
278
 
264
279
  def graph_controls(self):
@@ -271,7 +286,7 @@ class GraphView(urwid.WidgetWrap):
271
286
  self.mode_buttons.append(rb)
272
287
  # setup animate button
273
288
  self.animate_button = self.button("", self.on_animate_button)
274
- self.on_animate_button(self.animate_button)
289
+ self.on_animate_button(self.animate_button.original_widget)
275
290
  self.offset = 0
276
291
  self.animate_progress = self.progress_bar()
277
292
  animate_controls = urwid.GridFlow(
@@ -7,12 +7,12 @@ import typing
7
7
  import urwid
8
8
 
9
9
 
10
- class PopUpDialog(urwid.WidgetWrap):
10
+ class PopUpDialog(urwid.WidgetWrap[urwid.AttrMap[urwid.Filler[urwid.Pile]]]):
11
11
  """A dialog that appears with nothing but a close button"""
12
12
 
13
13
  signals: typing.ClassVar[list[str]] = ["close"]
14
14
 
15
- def __init__(self):
15
+ def __init__(self) -> None:
16
16
  close_button = urwid.Button("that's pretty cool")
17
17
  urwid.connect_signal(close_button, "click", lambda button: self._emit("close"))
18
18
  pile = urwid.Pile(
@@ -24,7 +24,7 @@ class PopUpDialog(urwid.WidgetWrap):
24
24
  super().__init__(urwid.AttrMap(urwid.Filler(pile), "popbg"))
25
25
 
26
26
 
27
- class ThingWithAPopUp(urwid.PopUpLauncher):
27
+ class ThingWithAPopUp(urwid.PopUpLauncher[urwid.Button]):
28
28
  def __init__(self) -> None:
29
29
  super().__init__(urwid.Button("click-me"))
30
30
  urwid.connect_signal(self.original_widget, "click", lambda button: self.open_pop_up())
@@ -178,9 +178,9 @@ class DirectoryNode(urwid.ParentNode):
178
178
  parent.set_child_node(self.get_key(), self)
179
179
  return parent
180
180
 
181
- def load_child_keys(self):
182
- dirs = []
183
- files = []
181
+ def load_child_keys(self) -> list[str] | list[None]:
182
+ dirs: list[str] = []
183
+ files: list[str] = []
184
184
  try:
185
185
  path = self.get_value()
186
186
  # separate dirs and files
@@ -207,7 +207,7 @@ class DirectoryNode(urwid.ParentNode):
207
207
  keys = [None]
208
208
  return keys
209
209
 
210
- def load_child_node(self, key) -> EmptyNode | DirectoryNode | FileNode:
210
+ def load_child_node(self, key: Hashable) -> EmptyNode | DirectoryNode | FileNode:
211
211
  """Return either a FileNode or DirectoryNode"""
212
212
  index = self.get_child_index(key)
213
213
  if key is None:
@@ -225,11 +225,11 @@ class DirectoryNode(urwid.ParentNode):
225
225
 
226
226
 
227
227
  class DirectoryBrowser:
228
- palette: typing.ClassVar[list[tuple[str, str, str, ...]]] = [
228
+ palette: typing.ClassVar[list[tuple[str, ...] | tuple[str, str, str, str]]] = [
229
229
  ("body", "black", "light gray"),
230
- ("flagged", "black", "dark green", ("bold", "underline")),
230
+ ("flagged", "black", "dark green", "bold,underline"),
231
231
  ("focus", "light gray", "dark blue", "standout"),
232
- ("flagged focus", "yellow", "dark cyan", ("bold", "standout", "underline")),
232
+ ("flagged focus", "yellow", "dark cyan", "bold,standout,underline"),
233
233
  ("head", "yellow", "black", "standout"),
234
234
  ("foot", "light gray", "black"),
235
235
  ("key", "light cyan", "black", "underline"),
@@ -51,10 +51,10 @@ class LineWalker(urwid.ListWalker):
51
51
  if self.file is not None:
52
52
  self.file.close()
53
53
 
54
- def get_focus(self):
54
+ def get_focus(self) -> tuple[urwid.Edit, int] | tuple[None, None]:
55
55
  return self._get_at_pos(self.focus)
56
56
 
57
- def set_focus(self, focus) -> None:
57
+ def set_focus(self, focus: int) -> None:
58
58
  self.focus = focus
59
59
  self._modified()
60
60
 
@@ -145,7 +145,7 @@ class LineWalker(urwid.ListWalker):
145
145
 
146
146
 
147
147
  class EditDisplay:
148
- palette: typing.ClassVar[list[tuple[str, str, str, ...]]] = [
148
+ palette: typing.ClassVar[list[tuple[str, str, str] | tuple[str, str, str, str]]] = [
149
149
  ("body", "default", "default"),
150
150
  ("foot", "dark cyan", "dark blue", "bold"),
151
151
  ("key", "light cyan", "dark blue", "underline"),
@@ -231,7 +231,7 @@ class EditDisplay:
231
231
  prefix = "\n"
232
232
 
233
233
 
234
- def re_tab(s) -> str:
234
+ def re_tab(s: str) -> str:
235
235
  """Return a tabbed string from an expanded one."""
236
236
  line = []
237
237
  p = 0
@@ -159,7 +159,7 @@ def main():
159
159
  " widget is used to keep the instructions at the top of the screen.",
160
160
  ]
161
161
 
162
- def button_press(button):
162
+ def button_press(button: urwid.Button) -> None:
163
163
  frame.footer = urwid.AttrMap(urwid.Text(["Pressed: ", button.get_label()]), "header")
164
164
 
165
165
  radio_button_group = []
@@ -355,11 +355,11 @@ def main():
355
355
  ("body", "black", "light gray", "standout"),
356
356
  ("reverse", "light gray", "black"),
357
357
  ("header", "white", "dark red", "bold"),
358
- ("important", "dark blue", "light gray", ("standout", "underline")),
358
+ ("important", "dark blue", "light gray", "standout,underline"),
359
359
  ("editfc", "white", "dark blue", "bold"),
360
360
  ("editbx", "light gray", "dark blue"),
361
361
  ("editcp", "black", "light gray", "standout"),
362
- ("bright", "dark gray", "light gray", ("bold", "standout")),
362
+ ("bright", "dark gray", "light gray", "bold,standout"),
363
363
  ("buttn", "black", "dark cyan"),
364
364
  ("buttnf", "white", "dark blue", "bold"),
365
365
  ]
@@ -48,7 +48,7 @@ class SwitchingPadding(urwid.Padding[_Wrapped]):
48
48
 
49
49
 
50
50
  class BigTextDisplay:
51
- palette: typing.ClassVar[list[tuple[str, str, str, ...]]] = [
51
+ palette: typing.ClassVar[list[tuple[str, str, str] | tuple[str, str, str, str]]] = [
52
52
  ("body", "black", "light gray", "standout"),
53
53
  ("header", "white", "dark red", "bold"),
54
54
  ("button normal", "light gray", "dark blue", "standout"),
@@ -178,9 +178,9 @@ class DirectoryNode(urwid.ParentNode):
178
178
  parent.set_child_node(self.get_key(), self)
179
179
  return parent
180
180
 
181
- def load_child_keys(self):
182
- dirs = []
183
- files = []
181
+ def load_child_keys(self) -> list[str] | list[None]:
182
+ dirs: list[str] = []
183
+ files: list[str] = []
184
184
  try:
185
185
  path = self.get_value()
186
186
  # separate dirs and files
@@ -207,7 +207,7 @@ class DirectoryNode(urwid.ParentNode):
207
207
  keys = [None]
208
208
  return keys
209
209
 
210
- def load_child_node(self, key) -> EmptyNode | DirectoryNode | FileNode:
210
+ def load_child_node(self, key: Hashable) -> EmptyNode | DirectoryNode | FileNode:
211
211
  """Return either a FileNode or DirectoryNode"""
212
212
  index = self.get_child_index(key)
213
213
  if key is None:
@@ -225,11 +225,11 @@ class DirectoryNode(urwid.ParentNode):
225
225
 
226
226
 
227
227
  class DirectoryBrowser:
228
- palette: typing.ClassVar[list[tuple[str, str, str, ...]]] = [
228
+ palette: typing.ClassVar[list[tuple[str, ...] | tuple[str, str, str, str]]] = [
229
229
  ("body", "black", "light gray"),
230
- ("flagged", "black", "dark green", ("bold", "underline")),
230
+ ("flagged", "black", "dark green", "bold,underline"),
231
231
  ("focus", "light gray", "dark blue", "standout"),
232
- ("flagged focus", "yellow", "dark cyan", ("bold", "standout", "underline")),
232
+ ("flagged focus", "yellow", "dark cyan", "bold,standout,underline"),
233
233
  ("head", "yellow", "black", "standout"),
234
234
  ("foot", "light gray", "black"),
235
235
  ("key", "light cyan", "black", "underline"),