proj-flow 0.20.3__tar.gz → 0.21.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.
Files changed (173) hide show
  1. {proj_flow-0.20.3 → proj_flow-0.21.0}/CHANGELOG.rst +14 -0
  2. {proj_flow-0.20.3 → proj_flow-0.21.0}/PKG-INFO +17 -7
  3. {proj_flow-0.20.3 → proj_flow-0.21.0}/pyproject.toml +25 -6
  4. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/__init__.py +1 -1
  5. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/api/arg.py +2 -0
  6. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/api/env.py +8 -2
  7. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/api/step.py +13 -2
  8. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/ext/cplusplus/cmake/presets.py +8 -4
  9. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/ext/cplusplus/cmake/steps.py +9 -3
  10. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/ext/cplusplus/conan/__init__.py +2 -0
  11. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/ext/github/cli.py +1 -3
  12. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/ext/python/rtdocs.py +35 -6
  13. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/minimal/list.py +126 -10
  14. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/project/api.py +1 -0
  15. {proj_flow-0.20.3 → proj_flow-0.21.0}/.flow/config.yaml +0 -0
  16. {proj_flow-0.20.3 → proj_flow-0.21.0}/.gitignore +0 -0
  17. {proj_flow-0.20.3 → proj_flow-0.21.0}/.readthedocs.yaml +0 -0
  18. {proj_flow-0.20.3 → proj_flow-0.21.0}/LICENSE +0 -0
  19. {proj_flow-0.20.3 → proj_flow-0.21.0}/README.md +0 -0
  20. {proj_flow-0.20.3 → proj_flow-0.21.0}/ROADMAP.md +0 -0
  21. {proj_flow-0.20.3 → proj_flow-0.21.0}/actions/bootstrap/action.yml +0 -0
  22. {proj_flow-0.20.3 → proj_flow-0.21.0}/actions/bootstrap/version.py +0 -0
  23. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/__main__.py +0 -0
  24. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/api/__init__.py +0 -0
  25. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/api/completers.py +0 -0
  26. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/api/ctx.py +0 -0
  27. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/api/init.py +0 -0
  28. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/api/makefile.py +0 -0
  29. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/api/release.py +0 -0
  30. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/base/__cmake_version__.py +0 -0
  31. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/base/__init__.py +0 -0
  32. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/base/cmd.py +0 -0
  33. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/base/inspect.py +0 -0
  34. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/base/matrix.py +0 -0
  35. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/base/name_list.py +0 -0
  36. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/base/plugins.py +0 -0
  37. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/base/registry.py +0 -0
  38. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/base/uname.py +0 -0
  39. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/cli/__init__.py +0 -0
  40. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/cli/argument.py +0 -0
  41. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/cli/finder.py +0 -0
  42. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/dependency.py +0 -0
  43. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/ext/__init__.py +0 -0
  44. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/ext/cplusplus/__init__.py +0 -0
  45. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/ext/cplusplus/cmake/__init__.py +0 -0
  46. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/ext/cplusplus/cmake/parser.py +0 -0
  47. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/ext/cplusplus/cmake/project.py +0 -0
  48. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/ext/cplusplus/conan/_conan.py +0 -0
  49. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/ext/github/__init__.py +0 -0
  50. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/ext/github/hosting.py +0 -0
  51. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/ext/github/publishing.py +0 -0
  52. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/ext/github/switches.py +0 -0
  53. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/ext/markdown_changelog.py +0 -0
  54. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/ext/python/__init__.py +0 -0
  55. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/ext/python/steps.py +0 -0
  56. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/ext/python/version.py +0 -0
  57. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/ext/re_structured_changelog.py +0 -0
  58. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/ext/sign/__init__.py +0 -0
  59. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/ext/sign/api.py +0 -0
  60. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/ext/sign/win32.py +0 -0
  61. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/ext/store.py +0 -0
  62. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/ext/tools/__init__.py +0 -0
  63. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/ext/tools/pragma_once.py +0 -0
  64. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/ext/tools/run_linter.py +0 -0
  65. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/ext/webidl/__init__.py +0 -0
  66. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/ext/webidl/base/__init__.py +0 -0
  67. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/ext/webidl/base/config.py +0 -0
  68. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/ext/webidl/cli/__init__.py +0 -0
  69. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/ext/webidl/cli/cmake.py +0 -0
  70. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/ext/webidl/cli/depfile.py +0 -0
  71. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/ext/webidl/cli/gen.py +0 -0
  72. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/ext/webidl/cli/init.py +0 -0
  73. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/ext/webidl/cli/root.py +0 -0
  74. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/ext/webidl/cli/updater.py +0 -0
  75. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/ext/webidl/data/init/flow_webidl.cmake +0 -0
  76. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/ext/webidl/data/templates/cmake.mustache +0 -0
  77. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/ext/webidl/data/templates/depfile.mustache +0 -0
  78. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/ext/webidl/data/templates/partials/cxx/attribute-decl.mustache +0 -0
  79. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/ext/webidl/data/templates/partials/cxx/in-out.mustache +0 -0
  80. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/ext/webidl/data/templates/partials/cxx/includes.mustache +0 -0
  81. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/ext/webidl/data/templates/partials/cxx/operation-decl.mustache +0 -0
  82. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/ext/webidl/data/templates/partials/cxx/type.mustache +0 -0
  83. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/ext/webidl/data/types/cxx.json +0 -0
  84. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/ext/webidl/model/__init__.py +0 -0
  85. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/ext/webidl/model/ast.py +0 -0
  86. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/ext/webidl/model/builders.py +0 -0
  87. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/ext/webidl/registry.py +0 -0
  88. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/flow/__init__.py +0 -0
  89. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/flow/configs.py +0 -0
  90. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/flow/layer.py +0 -0
  91. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/flow/steps.py +0 -0
  92. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/log/__init__.py +0 -0
  93. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/log/commit.py +0 -0
  94. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/log/error.py +0 -0
  95. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/log/fmt.py +0 -0
  96. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/log/format.py +0 -0
  97. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/log/hosting/__init__.py +0 -0
  98. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/log/hosting/github.py +0 -0
  99. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/log/msg.py +0 -0
  100. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/log/release.py +0 -0
  101. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/log/rich_text/__init__.py +0 -0
  102. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/log/rich_text/api.py +0 -0
  103. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/log/rich_text/markdown.py +0 -0
  104. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/log/rich_text/re_structured_text.py +0 -0
  105. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/minimal/__init__.py +0 -0
  106. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/minimal/base.py +0 -0
  107. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/minimal/bootstrap.py +0 -0
  108. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/minimal/ext/bug_report.py +0 -0
  109. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/minimal/init.py +0 -0
  110. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/minimal/run.py +0 -0
  111. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/minimal/system.py +0 -0
  112. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/project/__init__.py +0 -0
  113. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/project/cplusplus/__init__.py +0 -0
  114. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/project/cplusplus/cmake_context.py +0 -0
  115. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/project/cplusplus/conan_context.py +0 -0
  116. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/project/cplusplus/project.py +0 -0
  117. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/project/data.py +0 -0
  118. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/project/interact.py +0 -0
  119. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/template/layers/base/.clang-format +0 -0
  120. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/template/layers/base/.flow/config.yml +0 -0
  121. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/template/layers/base/.flow/flow.py.mustache +0 -0
  122. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/template/layers/base/.flow/matrix.yml +0 -0
  123. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/template/layers/base/.flow/official.yml +0 -0
  124. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/template/layers/base/.gitignore +0 -0
  125. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/template/layers/base/README.md.mustache +0 -0
  126. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/template/layers/base/flow +0 -0
  127. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/template/layers/base/flow.cmd +0 -0
  128. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/template/layers/base.json +0 -0
  129. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/template/layers/cmake/.flow/cmake/common.cmake.mustache +0 -0
  130. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/template/layers/cmake/.flow/extensions/wall/__init__.py.mustache +0 -0
  131. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/template/layers/cmake/.flow/extensions/wall/icons/__init__.py.mustache +0 -0
  132. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/template/layers/cmake/.flow/extensions/wall/icons/magick.py.mustache +0 -0
  133. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/template/layers/cmake/.flow/packages/base.cmake.mustache +0 -0
  134. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/template/layers/cmake/.flow/packages/config.cmake +0 -0
  135. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/template/layers/cmake/.flow/packages/cpack.cmake +0 -0
  136. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/template/layers/cmake/.flow/packages/wix/cpack.cmake.mustache +0 -0
  137. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/template/layers/cmake/.flow/packages/wix/patches.in.wix +0 -0
  138. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/template/layers/cmake/.flow/packages/wix.cmake.mustache +0 -0
  139. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/template/layers/cmake/CMakeGraphVizOptions.cmake +0 -0
  140. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/template/layers/cmake/CMakeLists.txt.mustache +0 -0
  141. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/template/layers/cmake/CMakePresets.json +0 -0
  142. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/template/layers/cmake/data/assets/appicon.ico +0 -0
  143. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/template/layers/cmake/data/assets/appicon.png +0 -0
  144. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/template/layers/cmake/data/assets/wix_banner.bmp +0 -0
  145. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/template/layers/cmake/data/assets/wix_dialog.bmp +0 -0
  146. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/template/layers/cmake/data/icons/.gitignore +0 -0
  147. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/template/layers/cmake/data/icons/appicon-mask.svg +0 -0
  148. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/template/layers/cmake/data/icons/appicon.svg +0 -0
  149. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/template/layers/cmake/src/main.cc.mustache +0 -0
  150. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/template/layers/cmake/src/version.hpp.in.mustache +0 -0
  151. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/template/layers/cmake/tests/test.cc.mustache +0 -0
  152. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/template/layers/cmake.json +0 -0
  153. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/template/layers/conan/.flow/cmake/libcxx_toolchain.cmake +0 -0
  154. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/template/layers/conan/.flow/cmake/output_dirs_setup.cmake +0 -0
  155. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/template/layers/conan/conanfile.txt +0 -0
  156. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/template/layers/conan.json +0 -0
  157. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/template/layers/github_actions/.github/linters/.isort.cfg +0 -0
  158. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/template/layers/github_actions/.github/linters/.mypy.ini +0 -0
  159. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/template/layers/github_actions/.github/workflows/build.yml.auto-release +0 -0
  160. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/template/layers/github_actions/.github/workflows/build.yml.basic +0 -0
  161. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/template/layers/github_actions/.github/workflows/linter.yml +0 -0
  162. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/template/layers/github_actions/CPPLINT.cfg +0 -0
  163. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/template/layers/github_actions.json +0 -0
  164. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/template/layers/github_social/.github/ISSUE_TEMPLATE/bug_report.md.mustache +0 -0
  165. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/template/layers/github_social/.github/ISSUE_TEMPLATE/feature_request.md.mustache +0 -0
  166. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/template/layers/github_social/CODE_OF_CONDUCT.md.mustache +0 -0
  167. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/template/layers/github_social/CONTRIBUTING.md +0 -0
  168. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/template/layers/github_social.json +0 -0
  169. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/template/licenses/0BSD.mustache +0 -0
  170. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/template/licenses/MIT.mustache +0 -0
  171. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/template/licenses/Unlicense.mustache +0 -0
  172. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/template/licenses/WTFPL.mustache +0 -0
  173. {proj_flow-0.20.3 → proj_flow-0.21.0}/src/proj_flow/template/licenses/Zlib.mustache +0 -0
@@ -4,6 +4,20 @@ Changelog
4
4
 
5
5
  All notable changes to this project will be documented in this file.
6
6
 
7
+ `0.21.0 <https://github.com/mzdun/proj-flow/compare/v0.20.3...v0.21.0>`_ (2026-02-03)
8
+ =====================================================================================
9
+
10
+ New Features
11
+ ------------
12
+
13
+ - recursively list known commands (`991b120 <https://github.com/mzdun/proj-flow/commit/991b120df9da90fee9047d440c2d0cc133ce740c>`_)
14
+ - **list**: wrap cmd help around terminal width (`64bd30c <https://github.com/mzdun/proj-flow/commit/64bd30cfd3c05da92be705a436f5d9cfcad14630>`_)
15
+
16
+ Bug Fixes
17
+ ---------
18
+
19
+ - **docs**: touchup on documentation (`4c374be <https://github.com/mzdun/proj-flow/commit/4c374be954f8af5597ba6a25f13cd332bf7bcc5e>`_)
20
+
7
21
  `0.20.3 <https://github.com/mzdun/proj-flow/compare/v0.20.2...v0.20.3>`_ (2026-01-30)
8
22
  =====================================================================================
9
23
 
@@ -1,12 +1,13 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: proj-flow
3
- Version: 0.20.3
3
+ Version: 0.21.0
4
4
  Summary: C++ project maintenance, automated
5
5
  Project-URL: Changelog, https://github.com/mzdun/proj-flow/blob/main/CHANGELOG.rst
6
6
  Project-URL: Documentation, https://proj-flow.readthedocs.io/en/latest/
7
7
  Project-URL: Homepage, https://pypi.org/project/proj-flow/
8
8
  Project-URL: Source Code, https://github.com/mzdun/proj-flow
9
9
  Author-email: Marcin Zdun <marcin.zdun@gmail.com>
10
+ License-Expression: MIT
10
11
  License-File: LICENSE
11
12
  Keywords: C/C++,build-tool,c++,ci-cd,continuous-integration,cpp,dependencies,dependency-manager,developer,developer-tools,development,meta-build-tool,pipeline,tools-and-automation
12
13
  Classifier: Development Status :: 4 - Beta
@@ -17,13 +18,22 @@ Classifier: Programming Language :: Python :: 3
17
18
  Classifier: Programming Language :: Python :: 3.10
18
19
  Classifier: Topic :: Software Development :: Build Tools
19
20
  Requires-Python: >=3.10
20
- Requires-Dist: argcomplete
21
+ Requires-Dist: argcomplete~=3.5
21
22
  Requires-Dist: chevron2021
22
- Requires-Dist: prompt-toolkit
23
- Requires-Dist: pywebidl2
24
- Requires-Dist: pyyaml
25
- Requires-Dist: requests-cache
26
- Requires-Dist: toml
23
+ Requires-Dist: prompt-toolkit~=3.0
24
+ Requires-Dist: pywebidl2~=0.1
25
+ Requires-Dist: pyyaml~=6.0
26
+ Requires-Dist: requests-cache~=1.3
27
+ Requires-Dist: toml~=0.10
28
+ Provides-Extra: dev
29
+ Requires-Dist: black~=25.0; extra == 'dev'
30
+ Requires-Dist: build~=1.4; extra == 'dev'
31
+ Requires-Dist: isort~=6.0; extra == 'dev'
32
+ Requires-Dist: sphinx~=9.1; extra == 'dev'
33
+ Requires-Dist: twine<=6.0.1; extra == 'dev'
34
+ Requires-Dist: types-chevron~=0.14; extra == 'dev'
35
+ Requires-Dist: types-pyyaml~=6.0; extra == 'dev'
36
+ Requires-Dist: types-toml~=0.10; extra == 'dev'
27
37
  Description-Content-Type: text/markdown
28
38
 
29
39
  # Project Flow
@@ -23,13 +23,13 @@ classifiers = [
23
23
  "Programming Language :: Python :: 3.10",
24
24
  ]
25
25
  dependencies = [
26
- "argcomplete",
26
+ "argcomplete~=3.5",
27
27
  "chevron2021",
28
- "prompt_toolkit",
29
- "PyYAML",
30
- "toml",
31
- "pywebidl2",
32
- "requests_cache",
28
+ "prompt_toolkit~=3.0",
29
+ "PyYAML~=6.0",
30
+ "toml~=0.10",
31
+ "pywebidl2~=0.1",
32
+ "requests-cache~=1.3",
33
33
  ]
34
34
  description = "C++ project maintenance, automated"
35
35
  dynamic = ["version"]
@@ -49,6 +49,7 @@ keywords = [
49
49
  'pipeline',
50
50
  'tools-and-automation',
51
51
  ]
52
+ license = "MIT"
52
53
  name = "proj-flow"
53
54
  readme = "README.md"
54
55
  requires-python = ">=3.10"
@@ -61,3 +62,21 @@ Homepage = "https://pypi.org/project/proj-flow/"
61
62
 
62
63
  [project.scripts]
63
64
  proj-flow = "proj_flow.cli:main"
65
+
66
+ [project.optional-dependencies]
67
+ dev = [
68
+ "build~=1.4",
69
+ "twine<=6.0.1",
70
+ "sphinx~=9.1",
71
+ "black~=25.0",
72
+ "isort~=6.0",
73
+ "types-PyYAML~=6.0",
74
+ "types-chevron~=0.14",
75
+ "types-toml~=0.10",
76
+ ]
77
+
78
+ [tool.black]
79
+ target-version = ["py310", "py311", "py312", "py313"]
80
+
81
+ [tool.isort]
82
+ profile = "black"
@@ -6,4 +6,4 @@ The **proj_flow** contains only ``__version__`` to be updated, nothing more.
6
6
  This is in an attempt to make this module easy to load initially.
7
7
  """
8
8
 
9
- __version__ = "0.20.3"
9
+ __version__ = "0.21.0"
@@ -159,6 +159,8 @@ def command(*name: str):
159
159
  doc = orig_doc or ""
160
160
  if doc:
161
161
  doc += "\n\n"
162
+ doc += f":call: ``proj-flow {' '.join(name)}``\n\n"
163
+ doc += f":call: ``./flow {' '.join(name)}``\n\n"
162
164
 
163
165
  for arg in _inspect.signature(entry):
164
166
  help = ""
@@ -173,11 +173,17 @@ def load_extensions(extensions: List[str]):
173
173
  for extension in extensions:
174
174
  try:
175
175
  importlib.import_module(extension)
176
- except ModuleNotFoundError:
176
+ except ImportError as ex:
177
177
  print(
178
- f"-- error: module `{extension}` was no found, ignoring",
178
+ f"-- error: loading module `{extension}` resulted in import error: {ex}",
179
179
  file=sys.stderr,
180
180
  )
181
+ except BaseException as ex:
182
+ print(
183
+ f"-- error: there was an error while loading module `{extension}`: {ex}",
184
+ file=sys.stderr,
185
+ )
186
+
181
187
 
182
188
  class FlowConfig:
183
189
  _cfg: dict
@@ -87,8 +87,10 @@ def _register_step(step: Step, replace: bool):
87
87
  return
88
88
 
89
89
  if "READTHEDOCS" not in os.environ:
90
- raise NameError(f"Step {name} is marked as replacing, but there is no previous step with that name")
91
-
90
+ raise NameError(
91
+ f"Step {name} is marked as replacing, but there is no previous step with that name"
92
+ )
93
+
92
94
  if name in [step.name for step in __steps]:
93
95
  if "READTHEDOCS" not in os.environ:
94
96
  raise NameError(f"Step {name} already registered")
@@ -133,6 +135,12 @@ def _make_private(f: _inspect.Function):
133
135
  f.__doc__ = ":meta private:\n"
134
136
 
135
137
 
138
+ def _make_private_property(f):
139
+ if isinstance(f, property):
140
+ _make_private(cast(_inspect.Function, f))
141
+ return
142
+
143
+
136
144
  _dummy_config = Config(
137
145
  {
138
146
  "os": "${os}",
@@ -163,6 +171,9 @@ def _extend_docstring(conv, step: Step):
163
171
  doc = conv.__doc__ or "*Docstring is missing!*"
164
172
  conv.__doc__ = f"{doc}\n{info}"
165
173
 
174
+ _make_private_property(conv.name)
175
+ _make_private_property(conv.runs_before)
176
+ _make_private_property(conv.runs_after)
166
177
  _make_private(conv.is_active)
167
178
  _make_private(conv.run)
168
179
  _make_private(conv.platform_dependencies)
@@ -135,10 +135,14 @@ class Presets:
135
135
 
136
136
  @staticmethod
137
137
  def __load_file(filename: Path):
138
- with open(filename, encoding="UTF-8") as f:
139
- data = json.load(f)
140
- includes = cast(list[str], data.get("include", []))
141
- presets = cast(list[dict], data.get("configurePresets", []))
138
+ try:
139
+ with open(filename, encoding="UTF-8") as f:
140
+ data = json.load(f)
141
+ includes = cast(list[str], data.get("include", []))
142
+ presets = cast(list[dict], data.get("configurePresets", []))
143
+ except FileNotFoundError:
144
+ includes: list[str] = []
145
+ presets: list[dict] = []
142
146
 
143
147
  return (includes, presets)
144
148
 
@@ -22,14 +22,17 @@ class CMakeBase(api.step.Step):
22
22
 
23
23
  @property
24
24
  def name(self):
25
+ """:meta private:"""
25
26
  return self._name
26
27
 
27
28
  @property
28
29
  def runs_after(self):
30
+ """:meta private:"""
29
31
  return self._runs_after
30
32
 
31
33
  @property
32
34
  def runs_before(self):
35
+ """:meta private:"""
33
36
  return self._runs_before
34
37
 
35
38
  def __init__(
@@ -47,6 +50,7 @@ class CMakeBase(api.step.Step):
47
50
  return [f"cmake>={CMAKE_VERSION}"]
48
51
 
49
52
  def dep_with_tool(self, tool: str):
53
+ """:meta private:"""
50
54
  return [f"cmake>={CMAKE_VERSION}", f"{tool}>={CMAKE_VERSION}"]
51
55
 
52
56
 
@@ -64,7 +68,9 @@ class CMakeConfig(CMakeBase):
64
68
  def directories_to_remove(self, config: env.Config) -> List[str]:
65
69
  binary_dir = self.binary_dirs.get(f"{config.preset}-{config.build_generator}")
66
70
  if not binary_dir:
67
- return []
71
+ if "READTHEDOCS" not in os.environ:
72
+ return []
73
+ return [f"build/{config.preset}"]
68
74
  return [binary_dir]
69
75
 
70
76
  def run(self, config: env.Config, rt: env.Runtime) -> int:
@@ -78,10 +84,10 @@ class CMakeConfig(CMakeBase):
78
84
  value = value[1:]
79
85
 
80
86
  if value.startswith("config:"):
81
- value = value[len("config:"):]
87
+ value = value[len("config:") :]
82
88
  value = config.get_path(value)
83
89
  elif value.startswith("runtime:"):
84
- value = value[len("runtime:"):]
90
+ value = value[len("runtime:") :]
85
91
  value = getattr(rt, value, None)
86
92
 
87
93
  if is_flag:
@@ -23,7 +23,9 @@ CONAN_PROFILE_GEN = "_profile-build_type"
23
23
  class ConanConfig:
24
24
  """Configures the project for ``preset`` config using ``build_type`` config."""
25
25
 
26
+ #: :meta private:
26
27
  name = "Conan"
28
+ #: :meta private:
27
29
  runs_before = ["CMake"]
28
30
 
29
31
  def platform_dependencies(self):
@@ -32,9 +32,7 @@ def github():
32
32
 
33
33
  @arg.command("github", "matrix")
34
34
  def matrix(
35
- pretty: typing.Annotated[
36
- bool, arg.FlagArgument(help="Indent JSON document")
37
- ],
35
+ pretty: typing.Annotated[bool, arg.FlagArgument(help="Indent JSON document")],
38
36
  official: typing.Annotated[
39
37
  bool, arg.FlagArgument(help="Cut matrix to release builds only")
40
38
  ],
@@ -3,7 +3,7 @@
3
3
 
4
4
  """
5
5
  The **proj_flow.ext.python.rtdocs** defines RTDocs step (`"RTD"`), which uses
6
- .readthedocs.yaml to build the HTML documentation.
6
+ ``.readthedocs.yaml`` to build the HTML documentation.
7
7
  """
8
8
 
9
9
  import os
@@ -20,7 +20,11 @@ from proj_flow.base import cmd
20
20
 
21
21
  @step.register
22
22
  class RTDocs:
23
- name = "RTD"
23
+ """Runs the jobs defined by ``.readthedocs.yaml`` to build the docs"""
24
+
25
+ @property
26
+ def name(self):
27
+ return "RTD"
24
28
 
25
29
  def platform_dependencies(self):
26
30
  return ["python -m PyYAML"]
@@ -100,6 +104,8 @@ class RTDocs:
100
104
 
101
105
 
102
106
  class Builder(ABC):
107
+ """Base class for any recognized builder in the ``.readthedocs.yaml`` config."""
108
+
103
109
  @property
104
110
  @abstractmethod
105
111
  def READTHEDOCS_OUTPUT(self) -> str: ...
@@ -112,17 +118,40 @@ class Builder(ABC):
112
118
 
113
119
 
114
120
  class Sphinx(Builder):
115
- READTHEDOCS_OUTPUT: str = ""
121
+ """Builder used, if Sphinx config is found in the config file.
122
+
123
+ :param config: filename of a Python script Sphinx should use for the configuration
124
+ """
125
+
126
+ @property
127
+ def READTHEDOCS_OUTPUT(self) -> str:
128
+ """A ``build/`` subdirectory placed in the same dir, as ``config`` parameter"""
129
+ return self.output
116
130
 
117
131
  def __init__(self, config: str):
118
132
  self.config = config
119
133
  self.source = os.path.dirname(config)
120
- self.READTHEDOCS_OUTPUT = os.path.join(os.path.dirname(self.source), "build")
134
+ self.output = os.path.join(os.path.dirname(self.source), "build")
121
135
 
122
- def build(self, target: str):
136
+ def build(self, target: str) -> int:
137
+ """Uses ``spinx-build`` to create the documentation.
138
+
139
+ :param target: name of the docs format from YAML config
140
+ :returns: exit code forwarded from the build tool
141
+ """
123
142
  builder = "latex" if target == "pdf" else target
143
+ print(shutil.which("sphinx-build"))
144
+
124
145
  return subprocess.run(
125
- ["sphinx-build", "-M", builder, self.source, self.READTHEDOCS_OUTPUT],
146
+ [
147
+ PYTHON_EXECUTABLE,
148
+ "-m",
149
+ "sphinx.cmd.build",
150
+ "-M",
151
+ builder,
152
+ self.source,
153
+ self.READTHEDOCS_OUTPUT,
154
+ ],
126
155
  shell=False,
127
156
  ).returncode
128
157
 
@@ -6,12 +6,20 @@ The **proj_flow.minimal.list** implements ``./flow list`` command.
6
6
  """
7
7
 
8
8
  import os
9
- from typing import Annotated, Dict, List, Set, cast
9
+ import re
10
+ import sys
11
+ from typing import Annotated, Dict, Iterable, List, Set, cast
10
12
 
11
13
  from proj_flow import cli
12
14
  from proj_flow.api import arg, env, step
13
15
  from proj_flow.base import matrix
14
16
 
17
+ if sys.platform == "win32":
18
+ import ctypes
19
+ import ctypes.wintypes
20
+ else:
21
+ import termios
22
+
15
23
 
16
24
  @arg.command("list")
17
25
  def main(
@@ -39,10 +47,7 @@ def main(
39
47
  configs = True
40
48
 
41
49
  if builtin:
42
- root = menu
43
- while root.parent is not None:
44
- root = root.parent
45
- builtin_entries = list(sorted((cmd.name, cmd.doc) for cmd in root.children))
50
+ builtin_entries = list(sorted(_walk_menu(menu)))
46
51
  if not pipe and len(builtin_entries) > 0:
47
52
  print("Builtin commands")
48
53
  print("----------------")
@@ -54,7 +59,10 @@ def main(
54
59
 
55
60
  name = f"{bold}{entry_name}{reset}"
56
61
  if entry_doc:
57
- print(f"- {name}: {entry_doc}")
62
+ print(f"- {name}:", end=" ")
63
+ _write_console_para(
64
+ " ".join(para.split("\n")) for para in entry_doc.split("\n\n")
65
+ )
58
66
  else:
59
67
  print(f"- {name}")
60
68
 
@@ -76,7 +84,8 @@ def main(
76
84
  continue
77
85
 
78
86
  name = f"{bold}{run_alias.name}{reset}"
79
- print(f"- {name}: {', '.join(run_alias.steps)}")
87
+ print(f"- {name}:", end=" ")
88
+ _write_console_para([", ".join(run_alias.steps)])
80
89
 
81
90
  printed_something = True
82
91
 
@@ -109,8 +118,10 @@ def main(
109
118
  print(f"- {name}*")
110
119
 
111
120
  if some_unused:
112
- print(
113
- f"*step can only be run by explicitly calling through {bold}run{reset}."
121
+ _write_console_para(
122
+ [
123
+ f"*step can only be run by explicitly calling through {bold}run{reset}."
124
+ ]
114
125
  )
115
126
 
116
127
  printed_something = True
@@ -147,7 +158,8 @@ def main(
147
158
  value = ", ".join(values.get(key, empty))
148
159
  name = f"{bold}{key}{reset}"
149
160
  if value:
150
- print(f"- {name}: {value}")
161
+ print(f"- {name}:", end=" ")
162
+ _write_console_para([value])
151
163
  else:
152
164
  print(f"- {name}")
153
165
 
@@ -157,6 +169,110 @@ def main(
157
169
  print(f"Use {bold}--help{reset} to see, which listings are available")
158
170
 
159
171
 
172
+ def _iterate_levels(menu: cli.argument.Command, prefix: str):
173
+ yield [(f"{prefix}{cmd.name}", cmd.doc) for cmd in menu.children]
174
+ for cmd in menu.children:
175
+ child_prefix = f"{prefix}{cmd.name} "
176
+ for layer in _iterate_levels(cmd, child_prefix):
177
+ yield layer
178
+
179
+
180
+ def _walk_menu(menu: cli.argument.Command):
181
+ root = menu
182
+ while root.parent is not None:
183
+ root = root.parent
184
+
185
+ items: list[tuple[str, str]] = []
186
+ for layer in _iterate_levels(root, ""):
187
+ items.extend(layer)
188
+
189
+ return items
190
+
191
+
192
+ def _cursor_pos():
193
+ if sys.platform == "win32":
194
+ old_stdin_mode = ctypes.wintypes.DWORD()
195
+ old_stdout_mode = ctypes.wintypes.DWORD()
196
+ kernel32 = ctypes.windll.kernel32
197
+ kernel32.GetConsoleMode(
198
+ kernel32.GetStdHandle(-10), ctypes.byref(old_stdin_mode)
199
+ )
200
+ kernel32.SetConsoleMode(kernel32.GetStdHandle(-10), 0)
201
+ kernel32.GetConsoleMode(
202
+ kernel32.GetStdHandle(-11), ctypes.byref(old_stdout_mode)
203
+ )
204
+ kernel32.SetConsoleMode(kernel32.GetStdHandle(-11), 7)
205
+ else:
206
+ old_stdin_mode = termios.tcgetattr(sys.stdin)
207
+ _ = termios.tcgetattr(sys.stdin)
208
+ _[3] = _[3] & ~(termios.ECHO | termios.ICANON)
209
+ termios.tcsetattr(sys.stdin, termios.TCSAFLUSH, _)
210
+ try:
211
+ _ = ""
212
+ sys.stdout.write("\x1b[6n")
213
+ sys.stdout.flush()
214
+ while not (_ := _ + sys.stdin.read(1)).endswith("R"):
215
+ pass
216
+ res = re.match(r".*\[(?P<y>\d*);(?P<x>\d*)R", _)
217
+ finally:
218
+ if sys.platform == "win32":
219
+ kernel32.SetConsoleMode(kernel32.GetStdHandle(-10), old_stdin_mode)
220
+ kernel32.SetConsoleMode(kernel32.GetStdHandle(-11), old_stdout_mode)
221
+ else:
222
+ termios.tcsetattr(sys.stdin, termios.TCSAFLUSH, old_stdin_mode)
223
+ if res:
224
+ return (int(res.group("x")), int(res.group("y")))
225
+ return (1, 1)
226
+
227
+
228
+ def _write_console_para(text: Iterable[str]):
229
+ term_width = os.get_terminal_size().columns
230
+ margin = min(_cursor_pos()[0], term_width // 2) - 1
231
+ width = term_width - 1
232
+ pos = margin
233
+ for para in text:
234
+ for word in para.split():
235
+ if not word:
236
+ continue
237
+ word_len = len(word)
238
+ next_pos = pos + word_len + 1
239
+
240
+ if next_pos >= width:
241
+ orig = pos
242
+ if orig == margin:
243
+ pos = margin - word_len
244
+ print(word, end="")
245
+
246
+ print()
247
+ print(" " * margin, end="")
248
+
249
+ if orig != margin:
250
+ pos = margin
251
+ print(word, end=" ")
252
+ else:
253
+ print(word, end=" ")
254
+
255
+ pos += word_len + 1
256
+
257
+ continue
258
+ if (word_len + 1) > term_width:
259
+ first_word = pos == margin
260
+ if first_word:
261
+ print(word, end="")
262
+
263
+ print(f"\n{' ' * margin}", end="")
264
+ pos = margin
265
+
266
+ if not first_word:
267
+ print(word, "", end="")
268
+ pos += word_len + 1
269
+ continue
270
+
271
+ print(word, "", end="")
272
+ pos += word_len + 1
273
+ print()
274
+
275
+
160
276
  def _load_flow_data(rt: env.Runtime):
161
277
  paths = [os.path.join(".flow", "matrix.yml")]
162
278
  m, keys = matrix.load_matrix(*paths)
@@ -67,5 +67,6 @@ def get_project_type(id: str):
67
67
  raise ProjectNotFound(id)
68
68
  return result
69
69
 
70
+
70
71
  def load_common_init_setting_extensions():
71
72
  env.load_extensions(["proj_flow.ext.github.switches"])
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes