urwid 2.6.9__tar.gz → 2.6.10__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 (318) hide show
  1. urwid-2.6.10/.editorconfig +22 -0
  2. {urwid-2.6.9 → urwid-2.6.10}/PKG-INFO +1 -1
  3. urwid-2.6.10/black-requirements.txt +1 -0
  4. {urwid-2.6.9 → urwid-2.6.10}/docs/examples/real_browse.py +10 -3
  5. {urwid-2.6.9 → urwid-2.6.10}/examples/browse.py +10 -3
  6. {urwid-2.6.9 → urwid-2.6.10}/pyproject.toml +4 -4
  7. urwid-2.6.10/ruff-requirements.txt +1 -0
  8. {urwid-2.6.9 → urwid-2.6.10}/tests/test_scrollable.py +57 -4
  9. {urwid-2.6.9 → urwid-2.6.10}/tox.ini +10 -10
  10. {urwid-2.6.9 → urwid-2.6.10}/urwid/version.py +2 -2
  11. {urwid-2.6.9 → urwid-2.6.10}/urwid/widget/listbox.py +25 -5
  12. {urwid-2.6.9 → urwid-2.6.10}/urwid/widget/scrollable.py +22 -10
  13. {urwid-2.6.9 → urwid-2.6.10}/urwid.egg-info/PKG-INFO +1 -1
  14. {urwid-2.6.9 → urwid-2.6.10}/urwid.egg-info/SOURCES.txt +1 -0
  15. urwid-2.6.9/black-requirements.txt +0 -1
  16. urwid-2.6.9/ruff-requirements.txt +0 -1
  17. {urwid-2.6.9 → urwid-2.6.10}/.coveralls.yml +0 -0
  18. {urwid-2.6.9 → urwid-2.6.10}/.devcontainer/dev.dockerfile +0 -0
  19. {urwid-2.6.9 → urwid-2.6.10}/.devcontainer/devcontainer.json +0 -0
  20. {urwid-2.6.9 → urwid-2.6.10}/.dockerignore +0 -0
  21. {urwid-2.6.9 → urwid-2.6.10}/.github/CODE_OF_CONDUCT.md +0 -0
  22. {urwid-2.6.9 → urwid-2.6.10}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  23. {urwid-2.6.9 → urwid-2.6.10}/.github/ISSUE_TEMPLATE/docs.md +0 -0
  24. {urwid-2.6.9 → urwid-2.6.10}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  25. {urwid-2.6.9 → urwid-2.6.10}/.github/ISSUE_TEMPLATE/question.md +0 -0
  26. {urwid-2.6.9 → urwid-2.6.10}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  27. {urwid-2.6.9 → urwid-2.6.10}/.github/dependabot.yml +0 -0
  28. {urwid-2.6.9 → urwid-2.6.10}/.github/labeler.yml +0 -0
  29. {urwid-2.6.9 → urwid-2.6.10}/.github/release.yml +0 -0
  30. {urwid-2.6.9 → urwid-2.6.10}/.github/workflows/documentation.yml +0 -0
  31. {urwid-2.6.9 → urwid-2.6.10}/.github/workflows/isolated_static_check.yml +0 -0
  32. {urwid-2.6.9 → urwid-2.6.10}/.github/workflows/labels.yml +0 -0
  33. {urwid-2.6.9 → urwid-2.6.10}/.github/workflows/pythonpackage.yml +0 -0
  34. {urwid-2.6.9 → urwid-2.6.10}/.github/workflows/yamllint.yml +0 -0
  35. {urwid-2.6.9 → urwid-2.6.10}/.gitignore +0 -0
  36. {urwid-2.6.9 → urwid-2.6.10}/.pre-commit-config.yaml +0 -0
  37. {urwid-2.6.9 → urwid-2.6.10}/.yamllint.yml +0 -0
  38. {urwid-2.6.9 → urwid-2.6.10}/COPYING +0 -0
  39. {urwid-2.6.9 → urwid-2.6.10}/MANIFEST.in +0 -0
  40. {urwid-2.6.9 → urwid-2.6.10}/README.rst +0 -0
  41. {urwid-2.6.9 → urwid-2.6.10}/classifiers.txt +0 -0
  42. {urwid-2.6.9 → urwid-2.6.10}/docs/Makefile +0 -0
  43. {urwid-2.6.9 → urwid-2.6.10}/docs/changelog.rst +0 -0
  44. {urwid-2.6.9 → urwid-2.6.10}/docs/conf.py +0 -0
  45. {urwid-2.6.9 → urwid-2.6.10}/docs/examples/bigtext.py +0 -0
  46. {urwid-2.6.9 → urwid-2.6.10}/docs/examples/bigtext.py.xdotool +0 -0
  47. {urwid-2.6.9 → urwid-2.6.10}/docs/examples/bigtext1.png +0 -0
  48. {urwid-2.6.9 → urwid-2.6.10}/docs/examples/bigtext2.png +0 -0
  49. {urwid-2.6.9 → urwid-2.6.10}/docs/examples/bigtext3.png +0 -0
  50. {urwid-2.6.9 → urwid-2.6.10}/docs/examples/browse.py +0 -0
  51. {urwid-2.6.9 → urwid-2.6.10}/docs/examples/browse.py.xdotool +0 -0
  52. {urwid-2.6.9 → urwid-2.6.10}/docs/examples/browse1.png +0 -0
  53. {urwid-2.6.9 → urwid-2.6.10}/docs/examples/browse2.png +0 -0
  54. {urwid-2.6.9 → urwid-2.6.10}/docs/examples/edit.py +0 -0
  55. {urwid-2.6.9 → urwid-2.6.10}/docs/examples/edit.py.xdotool +0 -0
  56. {urwid-2.6.9 → urwid-2.6.10}/docs/examples/edit1.png +0 -0
  57. {urwid-2.6.9 → urwid-2.6.10}/docs/examples/edit2.png +0 -0
  58. {urwid-2.6.9 → urwid-2.6.10}/docs/examples/edit_text.txt +0 -0
  59. {urwid-2.6.9 → urwid-2.6.10}/docs/examples/graph.py +0 -0
  60. {urwid-2.6.9 → urwid-2.6.10}/docs/examples/graph.py.xdotool +0 -0
  61. {urwid-2.6.9 → urwid-2.6.10}/docs/examples/graph1.png +0 -0
  62. {urwid-2.6.9 → urwid-2.6.10}/docs/examples/graph2.png +0 -0
  63. {urwid-2.6.9 → urwid-2.6.10}/docs/examples/index.rst +0 -0
  64. {urwid-2.6.9 → urwid-2.6.10}/docs/examples/palette_test.py +0 -0
  65. {urwid-2.6.9 → urwid-2.6.10}/docs/examples/palette_test.py.xdotool +0 -0
  66. {urwid-2.6.9 → urwid-2.6.10}/docs/examples/palette_test1.png +0 -0
  67. {urwid-2.6.9 → urwid-2.6.10}/docs/examples/palette_test2.png +0 -0
  68. {urwid-2.6.9 → urwid-2.6.10}/docs/examples/pop_up.py +0 -0
  69. {urwid-2.6.9 → urwid-2.6.10}/docs/examples/pop_up.py.xdotool +0 -0
  70. {urwid-2.6.9 → urwid-2.6.10}/docs/examples/pop_up1.png +0 -0
  71. {urwid-2.6.9 → urwid-2.6.10}/docs/examples/pop_up2.png +0 -0
  72. {urwid-2.6.9 → urwid-2.6.10}/docs/examples/real_edit.py +0 -0
  73. {urwid-2.6.9 → urwid-2.6.10}/docs/examples/subproc.py +0 -0
  74. {urwid-2.6.9 → urwid-2.6.10}/docs/examples/subproc.py.xdotool +0 -0
  75. {urwid-2.6.9 → urwid-2.6.10}/docs/examples/subproc1.png +0 -0
  76. {urwid-2.6.9 → urwid-2.6.10}/docs/examples/subproc2.png +0 -0
  77. {urwid-2.6.9 → urwid-2.6.10}/docs/examples/subproc2.py +0 -0
  78. {urwid-2.6.9 → urwid-2.6.10}/docs/examples/tour.py +0 -0
  79. {urwid-2.6.9 → urwid-2.6.10}/docs/examples/tour.py.xdotool +0 -0
  80. {urwid-2.6.9 → urwid-2.6.10}/docs/examples/tour1.png +0 -0
  81. {urwid-2.6.9 → urwid-2.6.10}/docs/examples/tour2.png +0 -0
  82. {urwid-2.6.9 → urwid-2.6.10}/docs/index.rst +0 -0
  83. {urwid-2.6.9 → urwid-2.6.10}/docs/manual/bright_combinations.py +0 -0
  84. {urwid-2.6.9 → urwid-2.6.10}/docs/manual/bright_combinations.py.xdotool +0 -0
  85. {urwid-2.6.9 → urwid-2.6.10}/docs/manual/bright_combinations1.png +0 -0
  86. {urwid-2.6.9 → urwid-2.6.10}/docs/manual/canvascache.rst +0 -0
  87. {urwid-2.6.9 → urwid-2.6.10}/docs/manual/displayattributes.rst +0 -0
  88. {urwid-2.6.9 → urwid-2.6.10}/docs/manual/displaymodules.rst +0 -0
  89. {urwid-2.6.9 → urwid-2.6.10}/docs/manual/encodings.rst +0 -0
  90. {urwid-2.6.9 → urwid-2.6.10}/docs/manual/images/display_modules.png +0 -0
  91. {urwid-2.6.9 → urwid-2.6.10}/docs/manual/images/introduction.png +0 -0
  92. {urwid-2.6.9 → urwid-2.6.10}/docs/manual/images/urwid_widgets.svgz +0 -0
  93. {urwid-2.6.9 → urwid-2.6.10}/docs/manual/images/urwid_widgets_1.png +0 -0
  94. {urwid-2.6.9 → urwid-2.6.10}/docs/manual/images/urwid_widgets_1.xcf +0 -0
  95. {urwid-2.6.9 → urwid-2.6.10}/docs/manual/images/urwid_widgets_2.png +0 -0
  96. {urwid-2.6.9 → urwid-2.6.10}/docs/manual/images/urwid_widgets_2.xcf +0 -0
  97. {urwid-2.6.9 → urwid-2.6.10}/docs/manual/images/widget_layout.png +0 -0
  98. {urwid-2.6.9 → urwid-2.6.10}/docs/manual/index.rst +0 -0
  99. {urwid-2.6.9 → urwid-2.6.10}/docs/manual/mainloop.rst +0 -0
  100. {urwid-2.6.9 → urwid-2.6.10}/docs/manual/overview.rst +0 -0
  101. {urwid-2.6.9 → urwid-2.6.10}/docs/manual/safe_combinations.py +0 -0
  102. {urwid-2.6.9 → urwid-2.6.10}/docs/manual/safe_combinations.py.xdotool +0 -0
  103. {urwid-2.6.9 → urwid-2.6.10}/docs/manual/safe_combinations1.png +0 -0
  104. {urwid-2.6.9 → urwid-2.6.10}/docs/manual/textlayout.rst +0 -0
  105. {urwid-2.6.9 → urwid-2.6.10}/docs/manual/userinput.rst +0 -0
  106. {urwid-2.6.9 → urwid-2.6.10}/docs/manual/wanat.py +0 -0
  107. {urwid-2.6.9 → urwid-2.6.10}/docs/manual/wanat_multi.py +0 -0
  108. {urwid-2.6.9 → urwid-2.6.10}/docs/manual/wcur1.py +0 -0
  109. {urwid-2.6.9 → urwid-2.6.10}/docs/manual/wcur2.py +0 -0
  110. {urwid-2.6.9 → urwid-2.6.10}/docs/manual/widgets.rst +0 -0
  111. {urwid-2.6.9 → urwid-2.6.10}/docs/manual/wmod.py +0 -0
  112. {urwid-2.6.9 → urwid-2.6.10}/docs/manual/wsel.py +0 -0
  113. {urwid-2.6.9 → urwid-2.6.10}/docs/reference/attrspec.rst +0 -0
  114. {urwid-2.6.9 → urwid-2.6.10}/docs/reference/canvas.rst +0 -0
  115. {urwid-2.6.9 → urwid-2.6.10}/docs/reference/command_map.rst +0 -0
  116. {urwid-2.6.9 → urwid-2.6.10}/docs/reference/constants.rst +0 -0
  117. {urwid-2.6.9 → urwid-2.6.10}/docs/reference/deprecated.rst +0 -0
  118. {urwid-2.6.9 → urwid-2.6.10}/docs/reference/display_modules.rst +0 -0
  119. {urwid-2.6.9 → urwid-2.6.10}/docs/reference/exceptions.rst +0 -0
  120. {urwid-2.6.9 → urwid-2.6.10}/docs/reference/global_settings.rst +0 -0
  121. {urwid-2.6.9 → urwid-2.6.10}/docs/reference/index.rst +0 -0
  122. {urwid-2.6.9 → urwid-2.6.10}/docs/reference/list_walkers.rst +0 -0
  123. {urwid-2.6.9 → urwid-2.6.10}/docs/reference/main_loop.rst +0 -0
  124. {urwid-2.6.9 → urwid-2.6.10}/docs/reference/meta.rst +0 -0
  125. {urwid-2.6.9 → urwid-2.6.10}/docs/reference/signals.rst +0 -0
  126. {urwid-2.6.9 → urwid-2.6.10}/docs/reference/text_layout.rst +0 -0
  127. {urwid-2.6.9 → urwid-2.6.10}/docs/reference/widget.rst +0 -0
  128. {urwid-2.6.9 → urwid-2.6.10}/docs/tools/compile_pngs.sh +0 -0
  129. {urwid-2.6.9 → urwid-2.6.10}/docs/tools/screenshots.sh +0 -0
  130. {urwid-2.6.9 → urwid-2.6.10}/docs/tools/static/.placeholder +0 -0
  131. {urwid-2.6.9 → urwid-2.6.10}/docs/tools/templates/indexcontent.html +0 -0
  132. {urwid-2.6.9 → urwid-2.6.10}/docs/tools/templates/indexsidebar.html +0 -0
  133. {urwid-2.6.9 → urwid-2.6.10}/docs/tools/templates/localtoc.html +0 -0
  134. {urwid-2.6.9 → urwid-2.6.10}/docs/tutorial/adventure.py +0 -0
  135. {urwid-2.6.9 → urwid-2.6.10}/docs/tutorial/adventure.py.xdotool +0 -0
  136. {urwid-2.6.9 → urwid-2.6.10}/docs/tutorial/adventure1.png +0 -0
  137. {urwid-2.6.9 → urwid-2.6.10}/docs/tutorial/adventure2.png +0 -0
  138. {urwid-2.6.9 → urwid-2.6.10}/docs/tutorial/adventure3.png +0 -0
  139. {urwid-2.6.9 → urwid-2.6.10}/docs/tutorial/adventure4.png +0 -0
  140. {urwid-2.6.9 → urwid-2.6.10}/docs/tutorial/cmenu.py +0 -0
  141. {urwid-2.6.9 → urwid-2.6.10}/docs/tutorial/cmenu.py.xdotool +0 -0
  142. {urwid-2.6.9 → urwid-2.6.10}/docs/tutorial/cmenu1.png +0 -0
  143. {urwid-2.6.9 → urwid-2.6.10}/docs/tutorial/cmenu2.png +0 -0
  144. {urwid-2.6.9 → urwid-2.6.10}/docs/tutorial/cmenu3.png +0 -0
  145. {urwid-2.6.9 → urwid-2.6.10}/docs/tutorial/cmenu4.png +0 -0
  146. {urwid-2.6.9 → urwid-2.6.10}/docs/tutorial/highcolors.py +0 -0
  147. {urwid-2.6.9 → urwid-2.6.10}/docs/tutorial/highcolors.py.xdotool +0 -0
  148. {urwid-2.6.9 → urwid-2.6.10}/docs/tutorial/highcolors1.png +0 -0
  149. {urwid-2.6.9 → urwid-2.6.10}/docs/tutorial/hmenu.py +0 -0
  150. {urwid-2.6.9 → urwid-2.6.10}/docs/tutorial/hmenu.py.xdotool +0 -0
  151. {urwid-2.6.9 → urwid-2.6.10}/docs/tutorial/hmenu1.png +0 -0
  152. {urwid-2.6.9 → urwid-2.6.10}/docs/tutorial/hmenu2.png +0 -0
  153. {urwid-2.6.9 → urwid-2.6.10}/docs/tutorial/hmenu3.png +0 -0
  154. {urwid-2.6.9 → urwid-2.6.10}/docs/tutorial/hmenu4.png +0 -0
  155. {urwid-2.6.9 → urwid-2.6.10}/docs/tutorial/index.rst +0 -0
  156. {urwid-2.6.9 → urwid-2.6.10}/docs/tutorial/input.py +0 -0
  157. {urwid-2.6.9 → urwid-2.6.10}/docs/tutorial/input.py.xdotool +0 -0
  158. {urwid-2.6.9 → urwid-2.6.10}/docs/tutorial/input1.png +0 -0
  159. {urwid-2.6.9 → urwid-2.6.10}/docs/tutorial/input2.png +0 -0
  160. {urwid-2.6.9 → urwid-2.6.10}/docs/tutorial/input3.png +0 -0
  161. {urwid-2.6.9 → urwid-2.6.10}/docs/tutorial/input4.png +0 -0
  162. {urwid-2.6.9 → urwid-2.6.10}/docs/tutorial/input5.png +0 -0
  163. {urwid-2.6.9 → urwid-2.6.10}/docs/tutorial/menu25.png +0 -0
  164. {urwid-2.6.9 → urwid-2.6.10}/docs/tutorial/minimal.py +0 -0
  165. {urwid-2.6.9 → urwid-2.6.10}/docs/tutorial/minimal.py.xdotool +0 -0
  166. {urwid-2.6.9 → urwid-2.6.10}/docs/tutorial/minimal1.png +0 -0
  167. {urwid-2.6.9 → urwid-2.6.10}/docs/tutorial/multiple.py +0 -0
  168. {urwid-2.6.9 → urwid-2.6.10}/docs/tutorial/multiple.py.xdotool +0 -0
  169. {urwid-2.6.9 → urwid-2.6.10}/docs/tutorial/multiple1.png +0 -0
  170. {urwid-2.6.9 → urwid-2.6.10}/docs/tutorial/multiple2.png +0 -0
  171. {urwid-2.6.9 → urwid-2.6.10}/docs/tutorial/multiple3.png +0 -0
  172. {urwid-2.6.9 → urwid-2.6.10}/docs/tutorial/multiple4.png +0 -0
  173. {urwid-2.6.9 → urwid-2.6.10}/docs/tutorial/qa.py +0 -0
  174. {urwid-2.6.9 → urwid-2.6.10}/docs/tutorial/qa.py.xdotool +0 -0
  175. {urwid-2.6.9 → urwid-2.6.10}/docs/tutorial/qa1.png +0 -0
  176. {urwid-2.6.9 → urwid-2.6.10}/docs/tutorial/qa2.png +0 -0
  177. {urwid-2.6.9 → urwid-2.6.10}/docs/tutorial/qa3.png +0 -0
  178. {urwid-2.6.9 → urwid-2.6.10}/docs/tutorial/sig.py +0 -0
  179. {urwid-2.6.9 → urwid-2.6.10}/docs/tutorial/sig.py.xdotool +0 -0
  180. {urwid-2.6.9 → urwid-2.6.10}/docs/tutorial/sig1.png +0 -0
  181. {urwid-2.6.9 → urwid-2.6.10}/docs/tutorial/sig2.png +0 -0
  182. {urwid-2.6.9 → urwid-2.6.10}/docs/tutorial/sig3.png +0 -0
  183. {urwid-2.6.9 → urwid-2.6.10}/docs/tutorial/sig4.png +0 -0
  184. {urwid-2.6.9 → urwid-2.6.10}/docs/tutorial/smenu.py +0 -0
  185. {urwid-2.6.9 → urwid-2.6.10}/docs/tutorial/smenu.py.xdotool +0 -0
  186. {urwid-2.6.9 → urwid-2.6.10}/docs/tutorial/smenu1.png +0 -0
  187. {urwid-2.6.9 → urwid-2.6.10}/docs/tutorial/smenu2.png +0 -0
  188. {urwid-2.6.9 → urwid-2.6.10}/docs/tutorial/smenu3.png +0 -0
  189. {urwid-2.6.9 → urwid-2.6.10}/docs/tutorial/urwid_attr.py +0 -0
  190. {urwid-2.6.9 → urwid-2.6.10}/docs/tutorial/urwid_attr.py.xdotool +0 -0
  191. {urwid-2.6.9 → urwid-2.6.10}/docs/tutorial/urwid_attr1.png +0 -0
  192. {urwid-2.6.9 → urwid-2.6.10}/docs/tutorial/urwid_attr2.png +0 -0
  193. {urwid-2.6.9 → urwid-2.6.10}/docs/tutorial/urwid_attr3.png +0 -0
  194. {urwid-2.6.9 → urwid-2.6.10}/docs/tutorial/urwid_attr4.png +0 -0
  195. {urwid-2.6.9 → urwid-2.6.10}/docs/urwid-logo.png +0 -0
  196. {urwid-2.6.9 → urwid-2.6.10}/examples/asyncio_socket_server.py +0 -0
  197. {urwid-2.6.9 → urwid-2.6.10}/examples/bigtext.py +0 -0
  198. {urwid-2.6.9 → urwid-2.6.10}/examples/calc.py +0 -0
  199. {urwid-2.6.9 → urwid-2.6.10}/examples/dialog.py +0 -0
  200. {urwid-2.6.9 → urwid-2.6.10}/examples/edit.py +0 -0
  201. {urwid-2.6.9 → urwid-2.6.10}/examples/fib.py +0 -0
  202. {urwid-2.6.9 → urwid-2.6.10}/examples/graph.py +0 -0
  203. {urwid-2.6.9 → urwid-2.6.10}/examples/input_test.py +0 -0
  204. {urwid-2.6.9 → urwid-2.6.10}/examples/lcd_cf635.py +0 -0
  205. {urwid-2.6.9 → urwid-2.6.10}/examples/palette_test.py +0 -0
  206. {urwid-2.6.9 → urwid-2.6.10}/examples/pop_up.py +0 -0
  207. {urwid-2.6.9 → urwid-2.6.10}/examples/subproc.py +0 -0
  208. {urwid-2.6.9 → urwid-2.6.10}/examples/subproc2.py +0 -0
  209. {urwid-2.6.9 → urwid-2.6.10}/examples/terminal.py +0 -0
  210. {urwid-2.6.9 → urwid-2.6.10}/examples/tour.py +0 -0
  211. {urwid-2.6.9 → urwid-2.6.10}/examples/treesample.py +0 -0
  212. {urwid-2.6.9 → urwid-2.6.10}/examples/twisted_serve_ssh.py +0 -0
  213. {urwid-2.6.9 → urwid-2.6.10}/examples/twisted_serve_ssh.tac +0 -0
  214. {urwid-2.6.9 → urwid-2.6.10}/isort-requirements.txt +0 -0
  215. {urwid-2.6.9 → urwid-2.6.10}/pylint-requirements.txt +0 -0
  216. {urwid-2.6.9 → urwid-2.6.10}/requirements.txt +0 -0
  217. {urwid-2.6.9 → urwid-2.6.10}/setup.cfg +0 -0
  218. {urwid-2.6.9 → urwid-2.6.10}/setup.py +0 -0
  219. {urwid-2.6.9 → urwid-2.6.10}/test_requirements.txt +0 -0
  220. {urwid-2.6.9 → urwid-2.6.10}/tests/__init__.py +0 -0
  221. {urwid-2.6.9 → urwid-2.6.10}/tests/test_canvas.py +0 -0
  222. {urwid-2.6.9 → urwid-2.6.10}/tests/test_columns.py +0 -0
  223. {urwid-2.6.9 → urwid-2.6.10}/tests/test_container.py +0 -0
  224. {urwid-2.6.9 → urwid-2.6.10}/tests/test_doctests.py +0 -0
  225. {urwid-2.6.9 → urwid-2.6.10}/tests/test_escapes.py +0 -0
  226. {urwid-2.6.9 → urwid-2.6.10}/tests/test_event_loops.py +0 -0
  227. {urwid-2.6.9 → urwid-2.6.10}/tests/test_filler.py +0 -0
  228. {urwid-2.6.9 → urwid-2.6.10}/tests/test_floatedit.py +0 -0
  229. {urwid-2.6.9 → urwid-2.6.10}/tests/test_font.py +0 -0
  230. {urwid-2.6.9 → urwid-2.6.10}/tests/test_frame.py +0 -0
  231. {urwid-2.6.9 → urwid-2.6.10}/tests/test_graphics.py +0 -0
  232. {urwid-2.6.9 → urwid-2.6.10}/tests/test_grid_flow.py +0 -0
  233. {urwid-2.6.9 → urwid-2.6.10}/tests/test_line_box.py +0 -0
  234. {urwid-2.6.9 → urwid-2.6.10}/tests/test_listbox.py +0 -0
  235. {urwid-2.6.9 → urwid-2.6.10}/tests/test_main_loop.py +0 -0
  236. {urwid-2.6.9 → urwid-2.6.10}/tests/test_moved_imports.py +0 -0
  237. {urwid-2.6.9 → urwid-2.6.10}/tests/test_overlay.py +0 -0
  238. {urwid-2.6.9 → urwid-2.6.10}/tests/test_padding.py +0 -0
  239. {urwid-2.6.9 → urwid-2.6.10}/tests/test_pile.py +0 -0
  240. {urwid-2.6.9 → urwid-2.6.10}/tests/test_raw_display.py +0 -0
  241. {urwid-2.6.9 → urwid-2.6.10}/tests/test_signals.py +0 -0
  242. {urwid-2.6.9 → urwid-2.6.10}/tests/test_str_util.py +0 -0
  243. {urwid-2.6.9 → urwid-2.6.10}/tests/test_text_layout.py +0 -0
  244. {urwid-2.6.9 → urwid-2.6.10}/tests/test_tree.py +0 -0
  245. {urwid-2.6.9 → urwid-2.6.10}/tests/test_util.py +0 -0
  246. {urwid-2.6.9 → urwid-2.6.10}/tests/test_vterm.py +0 -0
  247. {urwid-2.6.9 → urwid-2.6.10}/tests/test_widget.py +0 -0
  248. {urwid-2.6.9 → urwid-2.6.10}/tests/util.py +0 -0
  249. {urwid-2.6.9 → urwid-2.6.10}/urwid/__init__.py +0 -0
  250. {urwid-2.6.9 → urwid-2.6.10}/urwid/canvas.py +0 -0
  251. {urwid-2.6.9 → urwid-2.6.10}/urwid/command_map.py +0 -0
  252. {urwid-2.6.9 → urwid-2.6.10}/urwid/container.py +0 -0
  253. {urwid-2.6.9 → urwid-2.6.10}/urwid/decoration.py +0 -0
  254. {urwid-2.6.9 → urwid-2.6.10}/urwid/display/__init__.py +0 -0
  255. {urwid-2.6.9 → urwid-2.6.10}/urwid/display/_posix_raw_display.py +0 -0
  256. {urwid-2.6.9 → urwid-2.6.10}/urwid/display/_raw_display_base.py +0 -0
  257. {urwid-2.6.9 → urwid-2.6.10}/urwid/display/_web.css +0 -0
  258. {urwid-2.6.9 → urwid-2.6.10}/urwid/display/_web.js +0 -0
  259. {urwid-2.6.9 → urwid-2.6.10}/urwid/display/_win32.py +0 -0
  260. {urwid-2.6.9 → urwid-2.6.10}/urwid/display/_win32_raw_display.py +0 -0
  261. {urwid-2.6.9 → urwid-2.6.10}/urwid/display/common.py +0 -0
  262. {urwid-2.6.9 → urwid-2.6.10}/urwid/display/curses.py +0 -0
  263. {urwid-2.6.9 → urwid-2.6.10}/urwid/display/escape.py +0 -0
  264. {urwid-2.6.9 → urwid-2.6.10}/urwid/display/html_fragment.py +0 -0
  265. {urwid-2.6.9 → urwid-2.6.10}/urwid/display/lcd.py +0 -0
  266. {urwid-2.6.9 → urwid-2.6.10}/urwid/display/raw.py +0 -0
  267. {urwid-2.6.9 → urwid-2.6.10}/urwid/display/web.py +0 -0
  268. {urwid-2.6.9 → urwid-2.6.10}/urwid/event_loop/__init__.py +0 -0
  269. {urwid-2.6.9 → urwid-2.6.10}/urwid/event_loop/abstract_loop.py +0 -0
  270. {urwid-2.6.9 → urwid-2.6.10}/urwid/event_loop/asyncio_loop.py +0 -0
  271. {urwid-2.6.9 → urwid-2.6.10}/urwid/event_loop/glib_loop.py +0 -0
  272. {urwid-2.6.9 → urwid-2.6.10}/urwid/event_loop/main_loop.py +0 -0
  273. {urwid-2.6.9 → urwid-2.6.10}/urwid/event_loop/select_loop.py +0 -0
  274. {urwid-2.6.9 → urwid-2.6.10}/urwid/event_loop/tornado_loop.py +0 -0
  275. {urwid-2.6.9 → urwid-2.6.10}/urwid/event_loop/trio_loop.py +0 -0
  276. {urwid-2.6.9 → urwid-2.6.10}/urwid/event_loop/twisted_loop.py +0 -0
  277. {urwid-2.6.9 → urwid-2.6.10}/urwid/event_loop/zmq_loop.py +0 -0
  278. {urwid-2.6.9 → urwid-2.6.10}/urwid/font.py +0 -0
  279. {urwid-2.6.9 → urwid-2.6.10}/urwid/graphics.py +0 -0
  280. {urwid-2.6.9 → urwid-2.6.10}/urwid/numedit.py +0 -0
  281. {urwid-2.6.9 → urwid-2.6.10}/urwid/signals.py +0 -0
  282. {urwid-2.6.9 → urwid-2.6.10}/urwid/split_repr.py +0 -0
  283. {urwid-2.6.9 → urwid-2.6.10}/urwid/str_util.py +0 -0
  284. {urwid-2.6.9 → urwid-2.6.10}/urwid/text_layout.py +0 -0
  285. {urwid-2.6.9 → urwid-2.6.10}/urwid/util.py +0 -0
  286. {urwid-2.6.9 → urwid-2.6.10}/urwid/vterm.py +0 -0
  287. {urwid-2.6.9 → urwid-2.6.10}/urwid/widget/__init__.py +0 -0
  288. {urwid-2.6.9 → urwid-2.6.10}/urwid/widget/attr_map.py +0 -0
  289. {urwid-2.6.9 → urwid-2.6.10}/urwid/widget/attr_wrap.py +0 -0
  290. {urwid-2.6.9 → urwid-2.6.10}/urwid/widget/bar_graph.py +0 -0
  291. {urwid-2.6.9 → urwid-2.6.10}/urwid/widget/big_text.py +0 -0
  292. {urwid-2.6.9 → urwid-2.6.10}/urwid/widget/box_adapter.py +0 -0
  293. {urwid-2.6.9 → urwid-2.6.10}/urwid/widget/columns.py +0 -0
  294. {urwid-2.6.9 → urwid-2.6.10}/urwid/widget/constants.py +0 -0
  295. {urwid-2.6.9 → urwid-2.6.10}/urwid/widget/container.py +0 -0
  296. {urwid-2.6.9 → urwid-2.6.10}/urwid/widget/divider.py +0 -0
  297. {urwid-2.6.9 → urwid-2.6.10}/urwid/widget/edit.py +0 -0
  298. {urwid-2.6.9 → urwid-2.6.10}/urwid/widget/filler.py +0 -0
  299. {urwid-2.6.9 → urwid-2.6.10}/urwid/widget/frame.py +0 -0
  300. {urwid-2.6.9 → urwid-2.6.10}/urwid/widget/grid_flow.py +0 -0
  301. {urwid-2.6.9 → urwid-2.6.10}/urwid/widget/line_box.py +0 -0
  302. {urwid-2.6.9 → urwid-2.6.10}/urwid/widget/monitored_list.py +0 -0
  303. {urwid-2.6.9 → urwid-2.6.10}/urwid/widget/overlay.py +0 -0
  304. {urwid-2.6.9 → urwid-2.6.10}/urwid/widget/padding.py +0 -0
  305. {urwid-2.6.9 → urwid-2.6.10}/urwid/widget/pile.py +0 -0
  306. {urwid-2.6.9 → urwid-2.6.10}/urwid/widget/popup.py +0 -0
  307. {urwid-2.6.9 → urwid-2.6.10}/urwid/widget/progress_bar.py +0 -0
  308. {urwid-2.6.9 → urwid-2.6.10}/urwid/widget/solid_fill.py +0 -0
  309. {urwid-2.6.9 → urwid-2.6.10}/urwid/widget/text.py +0 -0
  310. {urwid-2.6.9 → urwid-2.6.10}/urwid/widget/treetools.py +0 -0
  311. {urwid-2.6.9 → urwid-2.6.10}/urwid/widget/widget.py +0 -0
  312. {urwid-2.6.9 → urwid-2.6.10}/urwid/widget/widget_decoration.py +0 -0
  313. {urwid-2.6.9 → urwid-2.6.10}/urwid/widget/wimp.py +0 -0
  314. {urwid-2.6.9 → urwid-2.6.10}/urwid/wimp.py +0 -0
  315. {urwid-2.6.9 → urwid-2.6.10}/urwid.egg-info/dependency_links.txt +0 -0
  316. {urwid-2.6.9 → urwid-2.6.10}/urwid.egg-info/not-zip-safe +0 -0
  317. {urwid-2.6.9 → urwid-2.6.10}/urwid.egg-info/requires.txt +0 -0
  318. {urwid-2.6.9 → urwid-2.6.10}/urwid.egg-info/top_level.txt +0 -0
@@ -0,0 +1,22 @@
1
+ root = true
2
+
3
+ [*]
4
+ charset = utf-8
5
+ end_of_line = lf
6
+ indent_style = space
7
+ insert_final_newline = true
8
+ trim_trailing_whitespace = true
9
+
10
+ [*.{py,pyi,pyx,pxd}]
11
+ indent_size = 4
12
+ max_line_length = 120
13
+
14
+ [*.{yml,yaml,json,ini,toml}]
15
+ indent_size = 2
16
+ max_line_length = 120
17
+
18
+ [*.{rst,md}]
19
+ indent_size = 2
20
+
21
+ [{Makefile,Makefile.in}]
22
+ indent_style = tab
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: urwid
3
- Version: 2.6.9
3
+ Version: 2.6.10
4
4
  Summary: A full-featured console (xterm et al.) user interface library
5
5
  Home-page: https://urwid.org/
6
6
  Author-email: Ian Ward <ian@excess.org>
@@ -0,0 +1 @@
1
+ black==24.3.0
@@ -274,7 +274,14 @@ class DirectoryBrowser:
274
274
  self.listbox.offset_rows = 1
275
275
  self.footer = urwid.AttrMap(urwid.Text(self.footer_text), "foot")
276
276
  self.view = urwid.Frame(
277
- urwid.AttrMap(urwid.ScrollBar(self.listbox), "body"),
277
+ urwid.AttrMap(
278
+ urwid.ScrollBar(
279
+ self.listbox,
280
+ thumb_char=urwid.ScrollBar.Symbols.FULL_BLOCK,
281
+ trough_char=urwid.ScrollBar.Symbols.LITE_SHADE,
282
+ ),
283
+ "body",
284
+ ),
278
285
  header=urwid.AttrMap(self.header, "head"),
279
286
  footer=self.footer,
280
287
  )
@@ -379,9 +386,9 @@ def escape_filename_sh_ansic(name: str) -> str:
379
386
  SPLIT_RE = re.compile(r"[a-zA-Z]+|\d+")
380
387
 
381
388
 
382
- def alphabetize(s):
389
+ def alphabetize(s: str) -> list[str]:
383
390
  L = []
384
- for isdigit, group in itertools.groupby(SPLIT_RE.findall(s), key=lambda x: x.isdigit()):
391
+ for isdigit, group in itertools.groupby(SPLIT_RE.findall(s), key=str.isdigit):
385
392
  if isdigit:
386
393
  L.extend(("", int(n)) for n in group)
387
394
  else:
@@ -274,7 +274,14 @@ class DirectoryBrowser:
274
274
  self.listbox.offset_rows = 1
275
275
  self.footer = urwid.AttrMap(urwid.Text(self.footer_text), "foot")
276
276
  self.view = urwid.Frame(
277
- urwid.AttrMap(urwid.ScrollBar(self.listbox), "body"),
277
+ urwid.AttrMap(
278
+ urwid.ScrollBar(
279
+ self.listbox,
280
+ thumb_char=urwid.ScrollBar.Symbols.FULL_BLOCK,
281
+ trough_char=urwid.ScrollBar.Symbols.LITE_SHADE,
282
+ ),
283
+ "body",
284
+ ),
278
285
  header=urwid.AttrMap(self.header, "head"),
279
286
  footer=self.footer,
280
287
  )
@@ -379,9 +386,9 @@ def escape_filename_sh_ansic(name: str) -> str:
379
386
  SPLIT_RE = re.compile(r"[a-zA-Z]+|\d+")
380
387
 
381
388
 
382
- def alphabetize(s):
389
+ def alphabetize(s: str) -> list[str]:
383
390
  L = []
384
- for isdigit, group in itertools.groupby(SPLIT_RE.findall(s), key=lambda x: x.isdigit()):
391
+ for isdigit, group in itertools.groupby(SPLIT_RE.findall(s), key=str.isdigit):
385
392
  if isdigit:
386
393
  L.extend(("", int(n)) for n in group)
387
394
  else:
@@ -2,9 +2,9 @@
2
2
  # Minimum requirements for the build system to execute.
3
3
  # PEP 508 specifications for PEP 518.
4
4
  requires = [
5
- "setuptools >= 61.0.0",
6
- "setuptools_scm[toml]>=7.0",
7
- "wheel",
5
+ "setuptools >= 61.0.0",
6
+ "setuptools_scm[toml]>=7.0",
7
+ "wheel",
8
8
  ]
9
9
  build-backend="setuptools.build_meta"
10
10
 
@@ -179,7 +179,7 @@ extend-select = [
179
179
  ]
180
180
  extend-ignore = [
181
181
  "PLR6301", "E203",
182
- # refactor rules (too many statements/arguments/branches)
182
+ # refactor rules (too many statements/arguments/branches)
183
183
  "PLR0904", "PLR0911", "PLR0912", "PLR0913", "PLR0914", "PLR0915", "PLR0917", "PLR2004",
184
184
  "PLC0415", # We have a lot of imports outside of top-level
185
185
  "RET504", # Unnecessary variable assignment before return statement
@@ -0,0 +1 @@
1
+ ruff==0.3.4
@@ -1,10 +1,14 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import string
4
+ import typing
4
5
  import unittest
5
6
 
6
7
  import urwid
7
8
 
9
+ if typing.TYPE_CHECKING:
10
+ from collections.abc import Iterable
11
+
8
12
  LGPL_HEADER = """
9
13
  Copyright (C) <year> <name of author>
10
14
 
@@ -264,15 +268,13 @@ class TestScrollBarListBox(unittest.TestCase):
264
268
 
265
269
  widget.keypress(reduced_size, "end")
266
270
 
267
- # Here we have ListBox issue: "end" really scroll not to the "dead end"
268
- # in case of the bottom focus position is multiline
269
271
  self.assertEqual(
270
272
  (
271
- "GNU Lesser General Public ",
272
273
  "License along with this library; if ",
273
274
  "not, write to the Free Software ",
274
275
  "Foundation, Inc., 51 Franklin Street, ",
275
- "Fifth Floor, Boston, MA 02110-1301",
276
+ "Fifth Floor, Boston, MA 02110-1301 ",
277
+ "USA █",
276
278
  ),
277
279
  widget.render(reduced_size).decoded_text,
278
280
  )
@@ -344,3 +346,54 @@ class TestScrollBarListBox(unittest.TestCase):
344
346
  widget.keypress(reduced_size, "down")
345
347
 
346
348
  self.assertEqual(pos_1_down_rendered, widget.render(reduced_size).decoded_text)
349
+
350
+ def test_hinted_len(self):
351
+ class HintedWalker(urwid.ListWalker):
352
+ def __init__(self, items: Iterable[str]) -> None:
353
+ self.items: tuple[str] = tuple(items)
354
+ self.focus = 0
355
+ self.requested_numbers: set[int] = set()
356
+
357
+ def __length_hint__(self) -> int:
358
+ return len(self.items)
359
+
360
+ def __getitem__(self, item: int) -> urwid.Text:
361
+ self.requested_numbers.add(item)
362
+ return urwid.Text(self.items[item])
363
+
364
+ def set_focus(self, item: int) -> None:
365
+ self.focus = item
366
+
367
+ def next_position(self, position: int) -> int:
368
+ if position + 1 < len(self.items):
369
+ return position + 1
370
+ raise IndexError
371
+
372
+ def prev_position(self, position: int) -> int:
373
+ if position - 1 >= 0:
374
+ return position - 1
375
+ raise IndexError
376
+
377
+ widget = urwid.ScrollBar(urwid.ListBox(HintedWalker((f"Line {idx:02}") for idx in range(1, 51))))
378
+ size = (10, 10)
379
+ widget.original_widget.focus_position = 19
380
+ self.assertEqual(
381
+ (
382
+ "Line 16 ",
383
+ "Line 17 ",
384
+ "Line 18 ",
385
+ "Line 19 █",
386
+ "Line 20 █",
387
+ "Line 21 ",
388
+ "Line 22 ",
389
+ "Line 23 ",
390
+ "Line 24 ",
391
+ "Line 25 ",
392
+ ),
393
+ widget.render(size).decoded_text,
394
+ )
395
+ self.assertNotIn(
396
+ 30,
397
+ widget.original_widget.body.requested_numbers,
398
+ "Requested index out of range [0, last shown]. This means not relative scroll bar built.",
399
+ )
@@ -7,8 +7,8 @@ usedevelop = true
7
7
  deps = -r {toxinidir}/test_requirements.txt
8
8
 
9
9
  commands =
10
- coverage run -m unittest discover -s tests -v
11
- coverage report
10
+ coverage run -m unittest discover -s tests -v
11
+ coverage report
12
12
 
13
13
  [testenv:readme]
14
14
  deps =
@@ -21,7 +21,7 @@ commands =
21
21
  [testenv:isort]
22
22
  skip_install = true
23
23
  deps =
24
- isort
24
+ isort
25
25
  commands =
26
26
  isort .
27
27
 
@@ -41,18 +41,18 @@ commands = ruff check .
41
41
 
42
42
  [testenv:docs]
43
43
  deps =
44
- -r {toxinidir}/test_requirements.txt
45
- PyGObject
46
- sphinx
47
- sphinx-github-changelog
44
+ -r {toxinidir}/test_requirements.txt
45
+ PyGObject
46
+ sphinx
47
+ sphinx-github-changelog
48
48
  commands = sphinx-build docs/ build/documentation
49
49
 
50
50
  [testenv:pylint]
51
51
  depends = black,isort
52
52
  deps =
53
- -r {toxinidir}/test_requirements.txt
54
- PyGObject
55
- pylint
53
+ -r {toxinidir}/test_requirements.txt
54
+ PyGObject
55
+ pylint
56
56
  commands = pylint urwid
57
57
 
58
58
  [testenv:refurb]
@@ -12,5 +12,5 @@ __version__: str
12
12
  __version_tuple__: VERSION_TUPLE
13
13
  version_tuple: VERSION_TUPLE
14
14
 
15
- __version__ = version = '2.6.9'
16
- __version_tuple__ = version_tuple = (2, 6, 9)
15
+ __version__ = version = '2.6.10'
16
+ __version_tuple__ = version_tuple = (2, 6, 10)
@@ -20,6 +20,7 @@
20
20
 
21
21
  from __future__ import annotations
22
22
 
23
+ import operator
23
24
  import typing
24
25
  import warnings
25
26
  from collections.abc import Iterable, Sized
@@ -77,6 +78,18 @@ class ScrollSupportingBody(Protocol):
77
78
  def get_prev(self, position: _K) -> tuple[Widget, _K] | tuple[None, None]: ...
78
79
 
79
80
 
81
+ @runtime_checkable
82
+ class EstimatedSized(Protocol):
83
+ """Widget can estimate it's size.
84
+
85
+ PEP 424 defines API for memory-efficiency.
86
+ For the ListBox it's a sign of the limited body length.
87
+ The main use-case is lazy-load, where real length calculation is expensive.
88
+ """
89
+
90
+ def __length_hint__(self) -> int: ...
91
+
92
+
80
93
  class ListWalker(metaclass=signals.MetaSignals): # pylint: disable=no-member, unsubscriptable-object
81
94
  # mixin not named as mixin
82
95
  signals: typing.ClassVar[list[str]] = ["modified"]
@@ -431,11 +444,18 @@ class ListBox(Widget, WidgetContainerMixin):
431
444
  )
432
445
  self.body = body
433
446
 
434
- def __len__(self) -> int:
447
+ @property
448
+ def __len__(self) -> Callable[[], int]:
435
449
  if isinstance(self._body, Sized):
436
- return len(self._body)
450
+ return self._body.__len__
437
451
  raise AttributeError(f"{self._body.__class__.__name__} is not Sized")
438
452
 
453
+ @property
454
+ def __length_hint__(self) -> Callable[[], int]: # pylint: disable=invalid-length-hint-returned
455
+ if isinstance(self._body, (Sized, EstimatedSized)):
456
+ return lambda: operator.length_hint(self._body)
457
+ raise AttributeError(f'{self._body.__class__.__name__} is not Sized and do not implement "__length_hint__"')
458
+
439
459
  def calculate_visible(
440
460
  self,
441
461
  size: tuple[int, int],
@@ -577,9 +597,9 @@ class ListBox(Widget, WidgetContainerMixin):
577
597
  if not isinstance(self._body, ScrollSupportingBody):
578
598
  raise ListBoxError(f"{self} body do not implement methods required for scrolling protocol")
579
599
 
580
- if not isinstance(self._body, (Sized, TreeWalker)):
600
+ if not isinstance(self._body, (Sized, EstimatedSized, TreeWalker)):
581
601
  raise ListBoxError(
582
- f"{self} body is not a Sized and not a TreeWalker."
602
+ f"{self} body is not a Sized, can not estimate it's size and not a TreeWalker."
583
603
  f"Scroll is not allowed due to risk of infinite cycle of widgets load."
584
604
  )
585
605
 
@@ -643,7 +663,7 @@ class ListBox(Widget, WidgetContainerMixin):
643
663
 
644
664
  def require_relative_scroll(self, size: tuple[int, int], focus: bool = False) -> bool:
645
665
  """Widget require relative scroll due to performance limitations of real lines count calculation."""
646
- return isinstance(self._body, Sized) and (size[1] * 3 < len(self))
666
+ return isinstance(self._body, (Sized, EstimatedSized)) and (size[1] * 3 < operator.length_hint(self.body))
647
667
 
648
668
  def get_first_visible_pos(self, size: tuple[int, int], focus: bool = False) -> int:
649
669
  self._check_support_scrolling()
@@ -130,8 +130,6 @@ class SupportsScroll(WidgetProto, Protocol):
130
130
  class SupportsRelativeScroll(WidgetProto, Protocol):
131
131
  """Relative scroll-specific methods."""
132
132
 
133
- def __len__(self) -> int: ...
134
-
135
133
  def require_relative_scroll(self, size: tuple[int, int], focus: bool = False) -> bool: ...
136
134
 
137
135
  def get_first_visible_pos(self, size: tuple[int, int], focus: bool = False) -> int: ...
@@ -516,18 +514,32 @@ class ScrollBar(WidgetDecoration[WrappedWidget]):
516
514
  ow = self._original_widget
517
515
  ow_base = self.scrolling_base_widget
518
516
 
519
- if isinstance(ow, SupportsRelativeScroll) and ow.require_relative_scroll(size, focus):
520
- if len(ow) == ow.get_visible_amount(size, focus):
521
- # Canvas fits without scrolling - no scrollbar needed
522
- return render_no_scrollbar()
517
+ # Use hasattr instead of protocol: hasattr will return False in case of getattr raise AttributeError
518
+ # Use __length_hint__ first since it's less resource intensive
519
+ use_relative = (
520
+ isinstance(ow_base, SupportsRelativeScroll)
521
+ and any(hasattr(ow_base, attrib) for attrib in ("__length_hint__", "__len__"))
522
+ and ow_base.require_relative_scroll(size, focus)
523
+ )
523
524
 
525
+ if use_relative:
526
+ # `operator.length_hint` is Protocol (Spec) over class based and can end false-negative on the instance
527
+ # use length_hint-like approach with safe `AttributeError` handling
528
+ ow_len = getattr(ow_base, "__len__", getattr(ow_base, "__length_hint__", lambda: 0))()
524
529
  ow_canv = render_for_scrollbar()
525
- visible_amount = ow.get_visible_amount(ow_size, focus)
530
+ visible_amount = ow_base.get_visible_amount(ow_size, focus)
526
531
  pos = ow_base.get_first_visible_pos(ow_size, focus)
527
- posmax = len(ow) - visible_amount
528
- thumb_weight = min(1.0, visible_amount / max(1, len(ow)))
529
532
 
530
- else:
533
+ # in the case of estimated length, it can be smaller than real widget length
534
+ ow_len = max(ow_len, visible_amount, pos)
535
+ posmax = ow_len - visible_amount
536
+ thumb_weight = min(1.0, visible_amount / max(1, ow_len))
537
+
538
+ if ow_len == visible_amount:
539
+ # Corner case: formally all contents indexes should be visible, but this does not mean all rows
540
+ use_relative = False
541
+
542
+ if not use_relative:
531
543
  ow_rows_max = ow_base.rows_max(size, focus)
532
544
  if ow_rows_max <= maxrow:
533
545
  # Canvas fits without scrolling - no scrollbar needed
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: urwid
3
- Version: 2.6.9
3
+ Version: 2.6.10
4
4
  Summary: A full-featured console (xterm et al.) user interface library
5
5
  Home-page: https://urwid.org/
6
6
  Author-email: Ian Ward <ian@excess.org>
@@ -1,5 +1,6 @@
1
1
  .coveralls.yml
2
2
  .dockerignore
3
+ .editorconfig
3
4
  .gitignore
4
5
  .pre-commit-config.yaml
5
6
  .yamllint.yml
@@ -1 +0,0 @@
1
- black==24.2.0
@@ -1 +0,0 @@
1
- ruff==0.3.2
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