PrEditor 0.9.0__tar.gz → 1.0.0__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.

Potentially problematic release.


This version of PrEditor might be problematic. Click here for more details.

Files changed (209) hide show
  1. {preditor-0.9.0 → preditor-1.0.0}/.github/workflows/static-analysis-and-test.yml +3 -7
  2. {preditor-0.9.0 → preditor-1.0.0}/.pre-commit-config.yaml +5 -6
  3. {preditor-0.9.0 → preditor-1.0.0}/CONTRIBUTING.md +3 -2
  4. {preditor-0.9.0 → preditor-1.0.0}/PKG-INFO +16 -10
  5. {preditor-0.9.0 → preditor-1.0.0}/PrEditor.egg-info/PKG-INFO +16 -10
  6. {preditor-0.9.0 → preditor-1.0.0}/PrEditor.egg-info/SOURCES.txt +5 -4
  7. {preditor-0.9.0 → preditor-1.0.0}/PrEditor.egg-info/requires.txt +2 -3
  8. {preditor-0.9.0 → preditor-1.0.0}/README.md +7 -2
  9. {preditor-0.9.0 → preditor-1.0.0}/examples/add_to_app.py +2 -2
  10. {preditor-0.9.0 → preditor-1.0.0}/preditor/__init__.py +70 -87
  11. {preditor-0.9.0 → preditor-1.0.0}/preditor/about_module.py +1 -6
  12. preditor-1.0.0/preditor/config.py +302 -0
  13. preditor-1.0.0/preditor/cores/core.py +20 -0
  14. {preditor-0.9.0 → preditor-1.0.0}/preditor/dccs/maya/plug-ins/PrEditor_maya.py +2 -0
  15. preditor-1.0.0/preditor/debug.py +144 -0
  16. {preditor-0.9.0 → preditor-1.0.0}/preditor/delayable_engine/__init__.py +3 -11
  17. preditor-1.0.0/preditor/excepthooks.py +131 -0
  18. {preditor-0.9.0 → preditor-1.0.0}/preditor/gui/app.py +1 -0
  19. {preditor-0.9.0 → preditor-1.0.0}/preditor/gui/console.py +1 -2
  20. {preditor-0.9.0 → preditor-1.0.0}/preditor/gui/dialog.py +2 -2
  21. preditor-1.0.0/preditor/gui/errordialog.py +68 -0
  22. {preditor-0.9.0 → preditor-1.0.0}/preditor/gui/group_tab_widget/__init__.py +1 -2
  23. {preditor-0.9.0 → preditor-1.0.0}/preditor/gui/level_buttons.py +1 -5
  24. {preditor-0.9.0 → preditor-1.0.0}/preditor/gui/loggerwindow.py +2 -3
  25. {preditor-0.9.0 → preditor-1.0.0}/preditor/gui/set_text_editor_path_dialog.py +1 -1
  26. {preditor-0.9.0 → preditor-1.0.0}/preditor/gui/ui/errordialog.ui +9 -16
  27. {preditor-0.9.0 → preditor-1.0.0}/preditor/gui/window.py +2 -2
  28. {preditor-0.9.0 → preditor-1.0.0}/preditor/plugins.py +13 -12
  29. {preditor-0.9.0 → preditor-1.0.0}/preditor/scintilla/documenteditor.py +1 -2
  30. preditor-1.0.0/preditor/version.py +21 -0
  31. preditor-1.0.0/pyproject.toml +130 -0
  32. preditor-1.0.0/requirements.txt +6 -0
  33. preditor-1.0.0/setup.cfg +4 -0
  34. preditor-1.0.0/tests/conftest.py +23 -0
  35. preditor-1.0.0/tests/test_config.py +251 -0
  36. preditor-1.0.0/tests/test_prefs.py +38 -0
  37. {preditor-0.9.0 → preditor-1.0.0}/tests/test_stream.py +6 -7
  38. preditor-1.0.0/tox.ini +57 -0
  39. preditor-0.9.0/preditor/cores/core.py +0 -59
  40. preditor-0.9.0/preditor/debug.py +0 -294
  41. preditor-0.9.0/preditor/gui/errordialog.py +0 -101
  42. preditor-0.9.0/preditor/gui/redmine_login_dialog.py +0 -63
  43. preditor-0.9.0/preditor/gui/ui/redmine_login_dialog.ui +0 -124
  44. preditor-0.9.0/preditor/version.py +0 -5
  45. preditor-0.9.0/pyproject.toml +0 -17
  46. preditor-0.9.0/requirements.txt +0 -6
  47. preditor-0.9.0/setup.cfg +0 -107
  48. preditor-0.9.0/setup.py +0 -7
  49. preditor-0.9.0/tox.ini +0 -76
  50. {preditor-0.9.0 → preditor-1.0.0}/.coveragerc +0 -0
  51. {preditor-0.9.0 → preditor-1.0.0}/.github/ISSUE_TEMPLATE/BUG_REPORT.md +0 -0
  52. {preditor-0.9.0 → preditor-1.0.0}/.github/ISSUE_TEMPLATE/FEATURE_REQUEST.md +0 -0
  53. {preditor-0.9.0 → preditor-1.0.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  54. {preditor-0.9.0 → preditor-1.0.0}/.github/workflows/release.yml +0 -0
  55. {preditor-0.9.0 → preditor-1.0.0}/.gitignore +0 -0
  56. {preditor-0.9.0 → preditor-1.0.0}/CODE_OF_CONDUCT.md +0 -0
  57. {preditor-0.9.0 → preditor-1.0.0}/LICENSE +0 -0
  58. {preditor-0.9.0 → preditor-1.0.0}/MANIFEST.in +0 -0
  59. {preditor-0.9.0 → preditor-1.0.0}/PrEditor.egg-info/dependency_links.txt +0 -0
  60. {preditor-0.9.0 → preditor-1.0.0}/PrEditor.egg-info/entry_points.txt +0 -0
  61. {preditor-0.9.0 → preditor-1.0.0}/PrEditor.egg-info/top_level.txt +0 -0
  62. {preditor-0.9.0 → preditor-1.0.0}/examples/output_capture_and_show.py +0 -0
  63. {preditor-0.9.0 → preditor-1.0.0}/preditor/__main__.py +0 -0
  64. {preditor-0.9.0 → preditor-1.0.0}/preditor/cli.py +0 -0
  65. {preditor-0.9.0 → preditor-1.0.0}/preditor/contexts.py +0 -0
  66. {preditor-0.9.0 → preditor-1.0.0}/preditor/cores/__init__.py +0 -0
  67. {preditor-0.9.0 → preditor-1.0.0}/preditor/dccs/maya/PrEditor_maya.mod +0 -0
  68. {preditor-0.9.0 → preditor-1.0.0}/preditor/delayable_engine/delayables.py +0 -0
  69. {preditor-0.9.0 → preditor-1.0.0}/preditor/enum.py +0 -0
  70. {preditor-0.9.0 → preditor-1.0.0}/preditor/gui/__init__.py +0 -0
  71. {preditor-0.9.0 → preditor-1.0.0}/preditor/gui/codehighlighter.py +0 -0
  72. {preditor-0.9.0 → preditor-1.0.0}/preditor/gui/completer.py +0 -0
  73. {preditor-0.9.0 → preditor-1.0.0}/preditor/gui/drag_tab_bar.py +0 -0
  74. {preditor-0.9.0 → preditor-1.0.0}/preditor/gui/editor_chooser.py +0 -0
  75. {preditor-0.9.0 → preditor-1.0.0}/preditor/gui/find_files.py +0 -0
  76. {preditor-0.9.0 → preditor-1.0.0}/preditor/gui/fuzzy_search/__init__.py +0 -0
  77. {preditor-0.9.0 → preditor-1.0.0}/preditor/gui/fuzzy_search/fuzzy_search.py +0 -0
  78. {preditor-0.9.0 → preditor-1.0.0}/preditor/gui/group_tab_widget/grouped_tab_menu.py +0 -0
  79. {preditor-0.9.0 → preditor-1.0.0}/preditor/gui/group_tab_widget/grouped_tab_models.py +0 -0
  80. {preditor-0.9.0 → preditor-1.0.0}/preditor/gui/group_tab_widget/grouped_tab_widget.py +0 -0
  81. {preditor-0.9.0 → preditor-1.0.0}/preditor/gui/group_tab_widget/one_tab_widget.py +0 -0
  82. {preditor-0.9.0 → preditor-1.0.0}/preditor/gui/logger_window_handler.py +0 -0
  83. {preditor-0.9.0 → preditor-1.0.0}/preditor/gui/logger_window_plugin.py +0 -0
  84. {preditor-0.9.0 → preditor-1.0.0}/preditor/gui/newtabwidget.py +0 -0
  85. {preditor-0.9.0 → preditor-1.0.0}/preditor/gui/status_label.py +0 -0
  86. {preditor-0.9.0 → preditor-1.0.0}/preditor/gui/suggest_path_quotes_dialog.py +0 -0
  87. {preditor-0.9.0 → preditor-1.0.0}/preditor/gui/ui/editor_chooser.ui +0 -0
  88. {preditor-0.9.0 → preditor-1.0.0}/preditor/gui/ui/find_files.ui +0 -0
  89. {preditor-0.9.0 → preditor-1.0.0}/preditor/gui/ui/loggerwindow.ui +0 -0
  90. {preditor-0.9.0 → preditor-1.0.0}/preditor/gui/ui/set_text_editor_path_dialog.ui +0 -0
  91. {preditor-0.9.0 → preditor-1.0.0}/preditor/gui/ui/suggest_path_quotes_dialog.ui +0 -0
  92. {preditor-0.9.0 → preditor-1.0.0}/preditor/gui/workbox_mixin.py +0 -0
  93. {preditor-0.9.0 → preditor-1.0.0}/preditor/gui/workbox_text_edit.py +0 -0
  94. {preditor-0.9.0 → preditor-1.0.0}/preditor/gui/workboxwidget.py +0 -0
  95. {preditor-0.9.0 → preditor-1.0.0}/preditor/logging_config.py +0 -0
  96. {preditor-0.9.0 → preditor-1.0.0}/preditor/osystem.py +0 -0
  97. {preditor-0.9.0 → preditor-1.0.0}/preditor/prefs.py +0 -0
  98. {preditor-0.9.0 → preditor-1.0.0}/preditor/resource/environment_variables.html +0 -0
  99. {preditor-0.9.0 → preditor-1.0.0}/preditor/resource/error_mail.html +0 -0
  100. {preditor-0.9.0 → preditor-1.0.0}/preditor/resource/error_mail_inline.html +0 -0
  101. {preditor-0.9.0 → preditor-1.0.0}/preditor/resource/img/README.md +0 -0
  102. {preditor-0.9.0 → preditor-1.0.0}/preditor/resource/img/arrow_forward.png +0 -0
  103. {preditor-0.9.0 → preditor-1.0.0}/preditor/resource/img/check-bold.png +0 -0
  104. {preditor-0.9.0 → preditor-1.0.0}/preditor/resource/img/chevron-down.png +0 -0
  105. {preditor-0.9.0 → preditor-1.0.0}/preditor/resource/img/chevron-up.png +0 -0
  106. {preditor-0.9.0 → preditor-1.0.0}/preditor/resource/img/close-thick.png +0 -0
  107. {preditor-0.9.0 → preditor-1.0.0}/preditor/resource/img/comment-edit.png +0 -0
  108. {preditor-0.9.0 → preditor-1.0.0}/preditor/resource/img/content-copy.png +0 -0
  109. {preditor-0.9.0 → preditor-1.0.0}/preditor/resource/img/content-cut.png +0 -0
  110. {preditor-0.9.0 → preditor-1.0.0}/preditor/resource/img/content-duplicate.png +0 -0
  111. {preditor-0.9.0 → preditor-1.0.0}/preditor/resource/img/content-paste.png +0 -0
  112. {preditor-0.9.0 → preditor-1.0.0}/preditor/resource/img/content-save.png +0 -0
  113. {preditor-0.9.0 → preditor-1.0.0}/preditor/resource/img/debug_disabled.png +0 -0
  114. {preditor-0.9.0 → preditor-1.0.0}/preditor/resource/img/eye-check.png +0 -0
  115. {preditor-0.9.0 → preditor-1.0.0}/preditor/resource/img/file-plus.png +0 -0
  116. {preditor-0.9.0 → preditor-1.0.0}/preditor/resource/img/file-remove.png +0 -0
  117. {preditor-0.9.0 → preditor-1.0.0}/preditor/resource/img/format-align-left.png +0 -0
  118. {preditor-0.9.0 → preditor-1.0.0}/preditor/resource/img/format-letter-case-lower.png +0 -0
  119. {preditor-0.9.0 → preditor-1.0.0}/preditor/resource/img/format-letter-case-upper.png +0 -0
  120. {preditor-0.9.0 → preditor-1.0.0}/preditor/resource/img/format-letter-case.svg +0 -0
  121. {preditor-0.9.0 → preditor-1.0.0}/preditor/resource/img/information.png +0 -0
  122. {preditor-0.9.0 → preditor-1.0.0}/preditor/resource/img/logging_critical.png +0 -0
  123. {preditor-0.9.0 → preditor-1.0.0}/preditor/resource/img/logging_custom.png +0 -0
  124. {preditor-0.9.0 → preditor-1.0.0}/preditor/resource/img/logging_debug.png +0 -0
  125. {preditor-0.9.0 → preditor-1.0.0}/preditor/resource/img/logging_error.png +0 -0
  126. {preditor-0.9.0 → preditor-1.0.0}/preditor/resource/img/logging_info.png +0 -0
  127. {preditor-0.9.0 → preditor-1.0.0}/preditor/resource/img/logging_not_set.png +0 -0
  128. {preditor-0.9.0 → preditor-1.0.0}/preditor/resource/img/logging_warning.png +0 -0
  129. {preditor-0.9.0 → preditor-1.0.0}/preditor/resource/img/marker.png +0 -0
  130. {preditor-0.9.0 → preditor-1.0.0}/preditor/resource/img/play.png +0 -0
  131. {preditor-0.9.0 → preditor-1.0.0}/preditor/resource/img/playlist-play.png +0 -0
  132. {preditor-0.9.0 → preditor-1.0.0}/preditor/resource/img/plus-minus-variant.png +0 -0
  133. {preditor-0.9.0 → preditor-1.0.0}/preditor/resource/img/preditor.ico +0 -0
  134. {preditor-0.9.0 → preditor-1.0.0}/preditor/resource/img/preditor.png +0 -0
  135. {preditor-0.9.0 → preditor-1.0.0}/preditor/resource/img/preditor.psd +0 -0
  136. {preditor-0.9.0 → preditor-1.0.0}/preditor/resource/img/preditor.svg +0 -0
  137. {preditor-0.9.0 → preditor-1.0.0}/preditor/resource/img/regex.svg +0 -0
  138. {preditor-0.9.0 → preditor-1.0.0}/preditor/resource/img/restart.svg +0 -0
  139. {preditor-0.9.0 → preditor-1.0.0}/preditor/resource/img/skip-forward-outline.png +0 -0
  140. {preditor-0.9.0 → preditor-1.0.0}/preditor/resource/img/skip-next-outline.png +0 -0
  141. {preditor-0.9.0 → preditor-1.0.0}/preditor/resource/img/skip-next.png +0 -0
  142. {preditor-0.9.0 → preditor-1.0.0}/preditor/resource/img/skip-previous.png +0 -0
  143. {preditor-0.9.0 → preditor-1.0.0}/preditor/resource/img/subdirectory-arrow-right.png +0 -0
  144. {preditor-0.9.0 → preditor-1.0.0}/preditor/resource/img/text-search-variant.png +0 -0
  145. {preditor-0.9.0 → preditor-1.0.0}/preditor/resource/img/warning-big.png +0 -0
  146. {preditor-0.9.0 → preditor-1.0.0}/preditor/resource/lang/python.json +0 -0
  147. {preditor-0.9.0 → preditor-1.0.0}/preditor/resource/settings.ini +0 -0
  148. {preditor-0.9.0 → preditor-1.0.0}/preditor/resource/stylesheet/Bright.css +0 -0
  149. {preditor-0.9.0 → preditor-1.0.0}/preditor/resource/stylesheet/Dark.css +0 -0
  150. {preditor-0.9.0 → preditor-1.0.0}/preditor/scintilla/__init__.py +0 -0
  151. {preditor-0.9.0 → preditor-1.0.0}/preditor/scintilla/delayables/__init__.py +0 -0
  152. {preditor-0.9.0 → preditor-1.0.0}/preditor/scintilla/delayables/smart_highlight.py +0 -0
  153. {preditor-0.9.0 → preditor-1.0.0}/preditor/scintilla/delayables/spell_check.py +0 -0
  154. {preditor-0.9.0 → preditor-1.0.0}/preditor/scintilla/finddialog.py +0 -0
  155. {preditor-0.9.0 → preditor-1.0.0}/preditor/scintilla/lang/__init__.py +0 -0
  156. {preditor-0.9.0 → preditor-1.0.0}/preditor/scintilla/lang/config/bash.ini +0 -0
  157. {preditor-0.9.0 → preditor-1.0.0}/preditor/scintilla/lang/config/batch.ini +0 -0
  158. {preditor-0.9.0 → preditor-1.0.0}/preditor/scintilla/lang/config/cpp.ini +0 -0
  159. {preditor-0.9.0 → preditor-1.0.0}/preditor/scintilla/lang/config/css.ini +0 -0
  160. {preditor-0.9.0 → preditor-1.0.0}/preditor/scintilla/lang/config/eyeonscript.ini +0 -0
  161. {preditor-0.9.0 → preditor-1.0.0}/preditor/scintilla/lang/config/html.ini +0 -0
  162. {preditor-0.9.0 → preditor-1.0.0}/preditor/scintilla/lang/config/javascript.ini +0 -0
  163. {preditor-0.9.0 → preditor-1.0.0}/preditor/scintilla/lang/config/lua.ini +0 -0
  164. {preditor-0.9.0 → preditor-1.0.0}/preditor/scintilla/lang/config/maxscript.ini +0 -0
  165. {preditor-0.9.0 → preditor-1.0.0}/preditor/scintilla/lang/config/mel.ini +0 -0
  166. {preditor-0.9.0 → preditor-1.0.0}/preditor/scintilla/lang/config/mu.ini +0 -0
  167. {preditor-0.9.0 → preditor-1.0.0}/preditor/scintilla/lang/config/nsi.ini +0 -0
  168. {preditor-0.9.0 → preditor-1.0.0}/preditor/scintilla/lang/config/perl.ini +0 -0
  169. {preditor-0.9.0 → preditor-1.0.0}/preditor/scintilla/lang/config/puppet.ini +0 -0
  170. {preditor-0.9.0 → preditor-1.0.0}/preditor/scintilla/lang/config/python.ini +0 -0
  171. {preditor-0.9.0 → preditor-1.0.0}/preditor/scintilla/lang/config/ruby.ini +0 -0
  172. {preditor-0.9.0 → preditor-1.0.0}/preditor/scintilla/lang/config/sql.ini +0 -0
  173. {preditor-0.9.0 → preditor-1.0.0}/preditor/scintilla/lang/config/xml.ini +0 -0
  174. {preditor-0.9.0 → preditor-1.0.0}/preditor/scintilla/lang/config/yaml.ini +0 -0
  175. {preditor-0.9.0 → preditor-1.0.0}/preditor/scintilla/lang/language.py +0 -0
  176. {preditor-0.9.0 → preditor-1.0.0}/preditor/scintilla/lexers/__init__.py +0 -0
  177. {preditor-0.9.0 → preditor-1.0.0}/preditor/scintilla/lexers/cpplexer.py +0 -0
  178. {preditor-0.9.0 → preditor-1.0.0}/preditor/scintilla/lexers/javascriptlexer.py +0 -0
  179. {preditor-0.9.0 → preditor-1.0.0}/preditor/scintilla/lexers/maxscriptlexer.py +0 -0
  180. {preditor-0.9.0 → preditor-1.0.0}/preditor/scintilla/lexers/mellexer.py +0 -0
  181. {preditor-0.9.0 → preditor-1.0.0}/preditor/scintilla/lexers/mulexer.py +0 -0
  182. {preditor-0.9.0 → preditor-1.0.0}/preditor/scintilla/lexers/pythonlexer.py +0 -0
  183. {preditor-0.9.0 → preditor-1.0.0}/preditor/scintilla/ui/finddialog.ui +0 -0
  184. {preditor-0.9.0 → preditor-1.0.0}/preditor/settings.py +0 -0
  185. {preditor-0.9.0 → preditor-1.0.0}/preditor/stream/__init__.py +0 -0
  186. {preditor-0.9.0 → preditor-1.0.0}/preditor/stream/director.py +0 -0
  187. {preditor-0.9.0 → preditor-1.0.0}/preditor/stream/manager.py +0 -0
  188. {preditor-0.9.0 → preditor-1.0.0}/preditor/streamhandler_helper.py +0 -0
  189. {preditor-0.9.0 → preditor-1.0.0}/preditor/utils/__init__.py +0 -0
  190. {preditor-0.9.0 → preditor-1.0.0}/preditor/utils/cute.py +0 -0
  191. {preditor-0.9.0 → preditor-1.0.0}/preditor/utils/stylesheets.py +0 -0
  192. {preditor-0.9.0 → preditor-1.0.0}/preditor/utils/text_search.py +0 -0
  193. {preditor-0.9.0 → preditor-1.0.0}/preditor/weakref.py +0 -0
  194. {preditor-0.9.0 → preditor-1.0.0}/tests/find_files/re_greedy_False_0_True.md +0 -0
  195. {preditor-0.9.0 → preditor-1.0.0}/tests/find_files/re_greedy_False_2_True.md +0 -0
  196. {preditor-0.9.0 → preditor-1.0.0}/tests/find_files/re_greedy_True_2_True.md +0 -0
  197. {preditor-0.9.0 → preditor-1.0.0}/tests/find_files/re_greedy_upper_True_2_True.md +0 -0
  198. {preditor-0.9.0 → preditor-1.0.0}/tests/find_files/re_simple_False_0_True.md +0 -0
  199. {preditor-0.9.0 → preditor-1.0.0}/tests/find_files/re_simple_False_2_True.md +0 -0
  200. {preditor-0.9.0 → preditor-1.0.0}/tests/find_files/re_simple_False_3_True.md +0 -0
  201. {preditor-0.9.0 → preditor-1.0.0}/tests/find_files/re_simple_True_2_True.md +0 -0
  202. {preditor-0.9.0 → preditor-1.0.0}/tests/find_files/simple_False_0_False.md +0 -0
  203. {preditor-0.9.0 → preditor-1.0.0}/tests/find_files/simple_False_1_False.md +0 -0
  204. {preditor-0.9.0 → preditor-1.0.0}/tests/find_files/simple_False_2_False.md +0 -0
  205. {preditor-0.9.0 → preditor-1.0.0}/tests/find_files/simple_False_3_False.md +0 -0
  206. {preditor-0.9.0 → preditor-1.0.0}/tests/find_files/simple_True_2_False.md +0 -0
  207. {preditor-0.9.0 → preditor-1.0.0}/tests/find_files/tab_text.txt +0 -0
  208. {preditor-0.9.0 → preditor-1.0.0}/tests/find_files/test_find_files.py +0 -0
  209. {preditor-0.9.0 → preditor-1.0.0}/tests/ide/test_delayable_engine.py +0 -0
@@ -27,7 +27,7 @@ jobs:
27
27
  - name: Install dependencies
28
28
  run: |
29
29
  python -m pip install --upgrade pip
30
- python -m pip install tox
30
+ python -m pip install tox coverage[toml]
31
31
 
32
32
  - name: Lint with flake8
33
33
  run: tox -e flake8
@@ -35,9 +35,6 @@ jobs:
35
35
  - name: Format with black
36
36
  run: tox -e black
37
37
 
38
- - name: Py 2 and 3 compatibility
39
- run: tox -e modernize
40
-
41
38
 
42
39
  test:
43
40
  # We want to run on external PRs, but not on our own internal PRs as they'll
@@ -49,9 +46,9 @@ jobs:
49
46
 
50
47
  strategy:
51
48
  matrix:
52
- os: ['ubuntu-latest']
49
+ os: ['ubuntu-latest', 'windows-latest']
53
50
  python: ['3.8', '3.9', '3.10', '3.11']
54
- # Works around the depreciation of python 3.6, 3.7 for ubuntu
51
+ # Works around the depreciation of python 3.7 for ubuntu
55
52
  # https://github.com/actions/setup-python/issues/544
56
53
  include:
57
54
  - os: 'ubuntu-22.04'
@@ -85,7 +82,6 @@ jobs:
85
82
  include-hidden-files: true
86
83
  retention-days: 1
87
84
 
88
-
89
85
  coverage:
90
86
  # We want to run on external PRs, but not on our own internal PRs as they'll
91
87
  # be run by the push to the branch. Without this if check, checks are
@@ -1,4 +1,8 @@
1
1
  ---
2
+ ci:
3
+ autoupdate_schedule: quarterly
4
+ skip: [black, flake8]
5
+
2
6
  repos:
3
7
 
4
8
  - repo: https://github.com/psf/black
@@ -12,14 +16,9 @@ repos:
12
16
  - id: flake8
13
17
  additional_dependencies:
14
18
  - flake8-bugbear==22.12.6
19
+ - Flake8-pyproject
15
20
  - pep8-naming==0.13.3
16
21
 
17
- - repo: https://github.com/asottile/setup-cfg-fmt
18
- rev: v2.2.0
19
- hooks:
20
- - id: setup-cfg-fmt
21
- args: [--min-py3-version=3.6]
22
-
23
22
  - repo: https://github.com/pre-commit/pre-commit-hooks
24
23
  rev: v4.4.0
25
24
  hooks:
@@ -56,7 +56,7 @@ A set of GitHub Action workflows are in place to perform the following style and
56
56
 
57
57
  **Styling**
58
58
 
59
- Styling or linting is performed via [flake8] along with the plugins [flake8-bugbear] & [pep8-naming]. A minor amount of configuration has been added to _[setup.cfg]_ in order to provide better compatibility with our formatter black (see next section).
59
+ Styling or linting is performed via [flake8] along with the plugins [flake8-bugbear], [Flake8-pyproject] & [pep8-naming]. A minor amount of configuration has been added to _[pyproject.toml]_ in order to provide better compatibility with our formatter black (see next section).
60
60
 
61
61
  **Formatting**
62
62
 
@@ -69,8 +69,9 @@ Releases are made manually by project managers and will automatically be uploade
69
69
 
70
70
  [flake8]: https://github.com/PyCQA/flake8
71
71
  [flake8-bugbear]: https://github.com/PyCQA/flake8-bugbear
72
+ [Flake8-pyproject]: https://github.com/john-hen/Flake8-pyproject
72
73
  [pep8-naming]: https://github.com/PyCQA/pep8-naming
73
- [setup.cfg]: https://github.com/blurstudio/preditor/blob/master/setup.cfg
74
+ [pyproject.toml]: https://github.com/blurstudio/hab/blob/master/pyproject.toml
74
75
  [black]: https://github.com/psf/black
75
76
  [Issues]: https://github.com/blurstudio/preditor/issues
76
77
  [create a new issue]: https://github.com/blurstudio/preditor/issues/new
@@ -1,39 +1,40 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: PrEditor
3
- Version: 0.9.0
3
+ Version: 1.0.0
4
4
  Summary: A python REPL and Editor and console based on Qt.
5
- Home-page: https://github.com/blurstudio/PrEditor.git
6
- Author: Blur Studio
7
- Author-email: opensource@blur.com
5
+ Author-email: Blur Studio <opensource@blur.com>
8
6
  License: LGPL-3.0
7
+ Project-URL: Homepage, https://github.com/blurstudio/PrEditor
8
+ Project-URL: Source, https://github.com/blurstudio/PrEditor
9
+ Project-URL: Tracker, https://github.com/blurstudio/PrEditor/issues
9
10
  Platform: any
10
11
  Classifier: Development Status :: 5 - Production/Stable
11
12
  Classifier: Intended Audience :: Developers
12
13
  Classifier: License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)
13
14
  Classifier: Operating System :: OS Independent
14
15
  Classifier: Programming Language :: Python
15
- Classifier: Programming Language :: Python :: 2
16
16
  Classifier: Programming Language :: Python :: 3
17
17
  Classifier: Programming Language :: Python :: Implementation :: CPython
18
18
  Classifier: Programming Language :: Python :: Implementation :: PyPy
19
- Requires-Python: !=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7
19
+ Requires-Python: >=3.7
20
20
  Description-Content-Type: text/markdown
21
21
  License-File: LICENSE
22
22
  Requires-Dist: Qt.py
23
23
  Requires-Dist: configparser>=4.0.2
24
24
  Requires-Dist: future>=0.18.2
25
- Requires-Dist: python-redmine>=2.1.1
26
25
  Requires-Dist: signalslot>=0.1.2
27
- Requires-Dist: importlib-metadata>=4.8.3; python_version >= "3.6"
26
+ Requires-Dist: importlib-metadata>=4.8.3
28
27
  Provides-Extra: cli
29
28
  Requires-Dist: click>=7.1.2; extra == "cli"
30
29
  Requires-Dist: click-default-group; extra == "cli"
31
30
  Provides-Extra: dev
32
31
  Requires-Dist: black; extra == "dev"
32
+ Requires-Dist: build; extra == "dev"
33
33
  Requires-Dist: covdefaults; extra == "dev"
34
34
  Requires-Dist: coverage; extra == "dev"
35
35
  Requires-Dist: flake8; extra == "dev"
36
36
  Requires-Dist: flake8-bugbear; extra == "dev"
37
+ Requires-Dist: Flake8-pyproject; extra == "dev"
37
38
  Requires-Dist: pep8-naming; extra == "dev"
38
39
  Requires-Dist: pytest; extra == "dev"
39
40
  Requires-Dist: tox; extra == "dev"
@@ -127,6 +128,12 @@ preditor.launch()
127
128
  preditor.shutdown()
128
129
  ```
129
130
 
131
+ Up to the point where the PrEditor instance is created you can update the config
132
+ data set by `preditor.configure`. For example you can change the name(used to load
133
+ a set of user prefs) by calling `preditor.config.name = 'NewName'`. This is useful
134
+ for configuring PrEditor before you import your specific setup code that implements
135
+ a better `parent_callback`.
136
+
130
137
  # Installing
131
138
 
132
139
  `pip install preditor`
@@ -165,8 +172,7 @@ The more mature QScintilla workbox requires a few extra dependencies that must
165
172
  be passed manually. It hasn't been added to `extras_require` because we plan to
166
173
  split it into its own pip module due to it requiring PyQt5 which is a little hard
167
174
  to get working inside of DCC's that ship with PySide2 by default. Here is the
168
- python 3 pip install command(For python 2 you will need to compile QScintilla
169
- yourself.)
175
+ python 3 pip install command.
170
176
 
171
177
  - `pip install preditor PyQt5, QScintilla>=2.11.4 aspell-python-py3`
172
178
 
@@ -1,39 +1,40 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: PrEditor
3
- Version: 0.9.0
3
+ Version: 1.0.0
4
4
  Summary: A python REPL and Editor and console based on Qt.
5
- Home-page: https://github.com/blurstudio/PrEditor.git
6
- Author: Blur Studio
7
- Author-email: opensource@blur.com
5
+ Author-email: Blur Studio <opensource@blur.com>
8
6
  License: LGPL-3.0
7
+ Project-URL: Homepage, https://github.com/blurstudio/PrEditor
8
+ Project-URL: Source, https://github.com/blurstudio/PrEditor
9
+ Project-URL: Tracker, https://github.com/blurstudio/PrEditor/issues
9
10
  Platform: any
10
11
  Classifier: Development Status :: 5 - Production/Stable
11
12
  Classifier: Intended Audience :: Developers
12
13
  Classifier: License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)
13
14
  Classifier: Operating System :: OS Independent
14
15
  Classifier: Programming Language :: Python
15
- Classifier: Programming Language :: Python :: 2
16
16
  Classifier: Programming Language :: Python :: 3
17
17
  Classifier: Programming Language :: Python :: Implementation :: CPython
18
18
  Classifier: Programming Language :: Python :: Implementation :: PyPy
19
- Requires-Python: !=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7
19
+ Requires-Python: >=3.7
20
20
  Description-Content-Type: text/markdown
21
21
  License-File: LICENSE
22
22
  Requires-Dist: Qt.py
23
23
  Requires-Dist: configparser>=4.0.2
24
24
  Requires-Dist: future>=0.18.2
25
- Requires-Dist: python-redmine>=2.1.1
26
25
  Requires-Dist: signalslot>=0.1.2
27
- Requires-Dist: importlib-metadata>=4.8.3; python_version >= "3.6"
26
+ Requires-Dist: importlib-metadata>=4.8.3
28
27
  Provides-Extra: cli
29
28
  Requires-Dist: click>=7.1.2; extra == "cli"
30
29
  Requires-Dist: click-default-group; extra == "cli"
31
30
  Provides-Extra: dev
32
31
  Requires-Dist: black; extra == "dev"
32
+ Requires-Dist: build; extra == "dev"
33
33
  Requires-Dist: covdefaults; extra == "dev"
34
34
  Requires-Dist: coverage; extra == "dev"
35
35
  Requires-Dist: flake8; extra == "dev"
36
36
  Requires-Dist: flake8-bugbear; extra == "dev"
37
+ Requires-Dist: Flake8-pyproject; extra == "dev"
37
38
  Requires-Dist: pep8-naming; extra == "dev"
38
39
  Requires-Dist: pytest; extra == "dev"
39
40
  Requires-Dist: tox; extra == "dev"
@@ -127,6 +128,12 @@ preditor.launch()
127
128
  preditor.shutdown()
128
129
  ```
129
130
 
131
+ Up to the point where the PrEditor instance is created you can update the config
132
+ data set by `preditor.configure`. For example you can change the name(used to load
133
+ a set of user prefs) by calling `preditor.config.name = 'NewName'`. This is useful
134
+ for configuring PrEditor before you import your specific setup code that implements
135
+ a better `parent_callback`.
136
+
130
137
  # Installing
131
138
 
132
139
  `pip install preditor`
@@ -165,8 +172,7 @@ The more mature QScintilla workbox requires a few extra dependencies that must
165
172
  be passed manually. It hasn't been added to `extras_require` because we plan to
166
173
  split it into its own pip module due to it requiring PyQt5 which is a little hard
167
174
  to get working inside of DCC's that ship with PySide2 by default. Here is the
168
- python 3 pip install command(For python 2 you will need to compile QScintilla
169
- yourself.)
175
+ python 3 pip install command.
170
176
 
171
177
  - `pip install preditor PyQt5, QScintilla>=2.11.4 aspell-python-py3`
172
178
 
@@ -8,8 +8,6 @@ MANIFEST.in
8
8
  README.md
9
9
  pyproject.toml
10
10
  requirements.txt
11
- setup.cfg
12
- setup.py
13
11
  tox.ini
14
12
  .github/PULL_REQUEST_TEMPLATE.md
15
13
  .github/ISSUE_TEMPLATE/BUG_REPORT.md
@@ -28,9 +26,11 @@ preditor/__init__.py
28
26
  preditor/__main__.py
29
27
  preditor/about_module.py
30
28
  preditor/cli.py
29
+ preditor/config.py
31
30
  preditor/contexts.py
32
31
  preditor/debug.py
33
32
  preditor/enum.py
33
+ preditor/excepthooks.py
34
34
  preditor/logging_config.py
35
35
  preditor/osystem.py
36
36
  preditor/plugins.py
@@ -60,7 +60,6 @@ preditor/gui/logger_window_handler.py
60
60
  preditor/gui/logger_window_plugin.py
61
61
  preditor/gui/loggerwindow.py
62
62
  preditor/gui/newtabwidget.py
63
- preditor/gui/redmine_login_dialog.py
64
63
  preditor/gui/set_text_editor_path_dialog.py
65
64
  preditor/gui/status_label.py
66
65
  preditor/gui/suggest_path_quotes_dialog.py
@@ -79,7 +78,6 @@ preditor/gui/ui/editor_chooser.ui
79
78
  preditor/gui/ui/errordialog.ui
80
79
  preditor/gui/ui/find_files.ui
81
80
  preditor/gui/ui/loggerwindow.ui
82
- preditor/gui/ui/redmine_login_dialog.ui
83
81
  preditor/gui/ui/set_text_editor_path_dialog.ui
84
82
  preditor/gui/ui/suggest_path_quotes_dialog.ui
85
83
  preditor/resource/environment_variables.html
@@ -176,6 +174,9 @@ preditor/utils/__init__.py
176
174
  preditor/utils/cute.py
177
175
  preditor/utils/stylesheets.py
178
176
  preditor/utils/text_search.py
177
+ tests/conftest.py
178
+ tests/test_config.py
179
+ tests/test_prefs.py
179
180
  tests/test_stream.py
180
181
  tests/find_files/re_greedy_False_0_True.md
181
182
  tests/find_files/re_greedy_False_2_True.md
@@ -1,10 +1,7 @@
1
1
  Qt.py
2
2
  configparser>=4.0.2
3
3
  future>=0.18.2
4
- python-redmine>=2.1.1
5
4
  signalslot>=0.1.2
6
-
7
- [:python_version >= "3.6"]
8
5
  importlib-metadata>=4.8.3
9
6
 
10
7
  [cli]
@@ -13,10 +10,12 @@ click-default-group
13
10
 
14
11
  [dev]
15
12
  black
13
+ build
16
14
  covdefaults
17
15
  coverage
18
16
  flake8
19
17
  flake8-bugbear
18
+ Flake8-pyproject
20
19
  pep8-naming
21
20
  pytest
22
21
  tox
@@ -84,6 +84,12 @@ preditor.launch()
84
84
  preditor.shutdown()
85
85
  ```
86
86
 
87
+ Up to the point where the PrEditor instance is created you can update the config
88
+ data set by `preditor.configure`. For example you can change the name(used to load
89
+ a set of user prefs) by calling `preditor.config.name = 'NewName'`. This is useful
90
+ for configuring PrEditor before you import your specific setup code that implements
91
+ a better `parent_callback`.
92
+
87
93
  # Installing
88
94
 
89
95
  `pip install preditor`
@@ -122,8 +128,7 @@ The more mature QScintilla workbox requires a few extra dependencies that must
122
128
  be passed manually. It hasn't been added to `extras_require` because we plan to
123
129
  split it into its own pip module due to it requiring PyQt5 which is a little hard
124
130
  to get working inside of DCC's that ship with PySide2 by default. Here is the
125
- python 3 pip install command(For python 2 you will need to compile QScintilla
126
- yourself.)
131
+ python 3 pip install command.
127
132
 
128
133
  - `pip install preditor PyQt5, QScintilla>=2.11.4 aspell-python-py3`
129
134
 
@@ -41,9 +41,9 @@ if __name__ == '__main__':
41
41
  # specific to this application.
42
42
  'add_to_app',
43
43
  )
44
- import preditor.debug
44
+ import preditor.excepthooks
45
45
 
46
- preditor.debug.BlurExcepthook.install()
46
+ preditor.excepthooks.PreditorExceptHook.install()
47
47
 
48
48
  # Create a Gui Application allowing the user to show PrEditor
49
49
  app = QApplication(sys.argv)
@@ -1,20 +1,19 @@
1
1
  from __future__ import absolute_import, print_function
2
2
 
3
- import logging # noqa: E402
4
- import os # noqa: E402
5
- import sys # noqa: E402
3
+ import logging
4
+ import os
5
+ import sys
6
6
 
7
- from Qt.QtCore import Qt # noqa: E402
7
+ from Qt.QtCore import Qt
8
8
 
9
- from . import osystem # noqa: E402
10
- from .plugins import Plugins # noqa: E402
11
- from .version import version as __version__ # noqa: E402,F401
9
+ from . import osystem
10
+ from .config import PreditorConfig
11
+ from .plugins import Plugins
12
+ from .version import version as __version__
12
13
 
13
14
  DEFAULT_CORE_NAME = "PrEditor"
14
15
  """The default name to use for the core name."""
15
16
 
16
- _global_config = {}
17
-
18
17
  core = None # create a managed Core instance
19
18
  """
20
19
  The blurdev managed :class:`Core` object from the :mod:`blurdev.cores` module.
@@ -31,6 +30,11 @@ _logger.addHandler(logging.NullHandler())
31
30
 
32
31
  plugins = Plugins()
33
32
 
33
+ config = PreditorConfig()
34
+ """This config is used to setup the instance of PrEditor. It can be edited up
35
+ to the point the instance is created. After that changes will be ignored.
36
+ """
37
+
34
38
 
35
39
  def about_preditor(instance=None):
36
40
  """Useful info about installed packages generated by plugins.
@@ -65,57 +69,72 @@ def init():
65
69
  plugin()
66
70
 
67
71
 
68
- def configure(name, parent_callback=None, excepthook=True, logging=True, streams=True):
69
- """Global configuration of PrEditor. Nothing is done if called more than once.
72
+ def configure(
73
+ name,
74
+ parent_callback=None,
75
+ excepthook=True,
76
+ logging=True,
77
+ streams=True,
78
+ headless_callback=None,
79
+ ):
80
+ """Global configuration of PrEditor. Safe to re-call until the instance is created.
81
+
82
+ Configures the instance of PrEditor without creating the GUI. It should be run
83
+ as early as possible in the applications initialization to allow PrEditor to
84
+ show as much stdout/err text as possible even the text printed before the
85
+ application's GUI is created.
86
+
87
+ This is a convenience method that sets useful defaults on `preditor.config`.
88
+ You can directly set the values on there instead of calling this function.
89
+ If you use that make sure to enable each feature as it doesn't by default.
90
+
91
+ Once `preditor.instance(create=True)` is called this will return without
92
+ making any changes. Otherwise unless noted with "First call only." each time
93
+ this function is called it will update any previously set values. This allows
94
+ you to minimally configure PrEditor and as more of the application comes
95
+ online enable more advanced features.
70
96
 
71
97
  Args:
72
98
  name (str): The core_name to use for the global instance of PrEditor.
73
99
  Once this has been set, you can call `launch` without passing name
74
- to access the main instance.
100
+ to access the main instance. The core_name controls what preferences
101
+ are loaded and used by PrEditor including the workbox tabs.
75
102
  parent_callback (callable, optional): Callback that returns a QWidget
76
103
  to use as the parent of the LoggerWindow when its first created.
77
104
  This can be used by DCC's to set the parent to their main window.
78
- excepthook (bool, optional): Replaces `sys.excepthook` with a interactive
79
- exception handler that prompts the user to show PrEditor when an
80
- python exception is raised.
81
- logging (bool, optional): Restore the python logging configuration that
82
- was recorded the last time PrEditor prefs were saved.
83
- streams (bool, optional): Install the stream manager to capture any
84
- stdout/stderr text written. Later when calling launch, the
105
+ excepthook (bool, optional): First call only. Replaces `sys.excepthook`
106
+ with a interactive exception handler that prompts the user to show
107
+ PrEditor when an python exception is raised. It is recommended that
108
+ you only add the excepthook once the Qt UI is initialized.
109
+ logging (bool, optional): Restore the python logging configuration settings
110
+ that were recorded the last time PrEditor prefs were saved. If called
111
+ multiple times with different core_name's before the instance is
112
+ created, this will reset the logging configuration from the previous
113
+ core_name if logging prefs exist.
114
+ streams (bool, optional): First call only. Install the stream manager to
115
+ capture any stdout/stderr text written. Later when calling launch, the
85
116
  LoggerWindow will show all of the captured text. This lets you only
86
- create the LoggerWindow IF you need to, but when you do it will have
87
- all of the std stream text written after this call.
117
+ create the LoggerWindow IF you need to show it, but when you do it
118
+ will have all of the std stream text written after this call.
119
+ headless_callback (callable, optional): Callback that returns a bool
120
+ indicating if PrEditor should attempt to create GUI elements.
88
121
  """
89
- # Once this has been set, configure should not do anything
90
- if 'core_name' in _global_config:
91
- return
92
-
93
- # Store the core_name,.
94
- _global_config['core_name'] = name
95
- if parent_callback:
96
- set_parent_callback(parent_callback)
97
-
98
- if streams:
99
- # Install the stream manager to capture output
100
- from preditor.stream import install_to_std
101
-
102
- install_to_std()
103
-
104
- if logging:
105
- from .logging_config import LoggingConfig
106
-
107
- cfg = LoggingConfig(core_name=name)
108
- cfg.load()
109
-
110
- if excepthook:
111
- import preditor.debug
112
-
113
- preditor.debug.BlurExcepthook.install()
122
+ # The name should always be set first. The logging setting depends on it,
123
+ # and the others may depend on it in the future.
124
+ config.name = name
125
+ config.logging = logging
126
+ # Capture stdout/err streams and install the excepthook so we start capturing
127
+ # output as early as possible if enabled.
128
+ config.streams = streams
129
+ config.excepthook = excepthook
130
+ # These will be used to create the GUI instance if PrEditor needs shown.
131
+ config.parent_callback = parent_callback
132
+ config.headless_callback = headless_callback
114
133
 
115
134
 
116
135
  def get_core_name():
117
136
  """Returns the configured core_name or DEFAULT_CORE_NAME."""
118
- return _global_config.get('core_name', DEFAULT_CORE_NAME)
137
+ return config.name
119
138
 
120
139
 
121
140
  def launch(run_workbox=False, app_id=None, name=None, standalone=False):
@@ -141,11 +160,11 @@ def launch(run_workbox=False, app_id=None, name=None, standalone=False):
141
160
  if name is None:
142
161
  # If the name wasn't passed we will get it from the name stored when
143
162
  # configure was called.
144
- if 'core_name' not in _global_config:
163
+ if config.name is None:
145
164
  raise RuntimeError(
146
165
  "You call configure before calling launch if not passing name"
147
166
  )
148
- name = _global_config['core_name']
167
+ name = config.name
149
168
  else:
150
169
  # A name was provided, call configure to ensure it has been called
151
170
  configure(name=name)
@@ -218,17 +237,6 @@ def resourcePath(relpath=''):
218
237
  return os.path.join(relativePath(__file__), 'resource', relpath)
219
238
 
220
239
 
221
- def root_window():
222
- # If a parent widget callback was configured, use it
223
- if 'parent_callback' in _global_config:
224
- return _global_config['parent_callback']()
225
-
226
- # Otherwise, attempt to find the top level widget from Qt
227
- from .gui.app import App
228
-
229
- return App.root_window()
230
-
231
-
232
240
  def parent_callback():
233
241
  """Returns the parent_callback or None.
234
242
 
@@ -236,30 +244,7 @@ def parent_callback():
236
244
  LoggerWindow when its first created. This can be used by DCC's to set the
237
245
  parent to their main window.
238
246
  """
239
- return _global_config.get("parent_callback")
240
-
241
-
242
- def set_parent_callback(parent_callback, if_unset=True):
243
- """Update the parent_callback even if it was already set.
244
-
245
- This is useful for cases where `configure` is called before it's possible to
246
- provide the parent_callback.
247
-
248
- Note: Changing this does not re-parent an existing instance of LoggerWindows.
249
- If you change this after the LoggerWindow instance has been created you will
250
- need to manually re-parent it.
251
-
252
- Args:
253
- if_unset(bool): If True then only set this value if the parent_callback
254
- hasn't already been set.
255
-
256
- Returns:
257
- bool: Returns False if if_unset is True and it was already set.
258
- """
259
- if "parent_callback" in _global_config and not if_unset:
260
- return False
261
- _global_config["parent_callback"] = parent_callback
262
- return True
247
+ return config.parent_callback
263
248
 
264
249
 
265
250
  def connect_preditor(
@@ -311,9 +296,7 @@ def instance(parent=None, run_workbox=False, create=True):
311
296
  than once, the same instance will be returned. If create is False, it may
312
297
  return None.
313
298
  """
314
- from .gui.loggerwindow import LoggerWindow
315
-
316
- return LoggerWindow.instance(parent=parent, run_workbox=run_workbox, create=create)
299
+ return config.instance(parent=parent, run_workbox=run_workbox, create=create)
317
300
 
318
301
 
319
302
  def shutdown():
@@ -5,7 +5,6 @@ import os
5
5
  import sys
6
6
  import textwrap
7
7
 
8
- import six
9
8
  from future.utils import with_metaclass
10
9
 
11
10
  import preditor
@@ -52,11 +51,7 @@ class AboutModule(with_metaclass(abc.ABCMeta, object)):
52
51
  text = plug.text()
53
52
  except Exception as error:
54
53
  text = "Error processing: {}".format(error)
55
- if six.PY3:
56
- text = textwrap.indent(text, cls.indent)
57
- else:
58
- text = ['{}{}'.format(cls.indent, line) for line in text.split('\n')]
59
- text = "\n".join(text)
54
+ text = textwrap.indent(text, cls.indent)
60
55
 
61
56
  # Build the output string including the version information if provided.
62
57
  if version is not None: