proj-flow 0.10.0__tar.gz → 0.11.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (141) hide show
  1. {proj_flow-0.10.0 → proj_flow-0.11.1}/CHANGELOG.rst +21 -0
  2. {proj_flow-0.10.0 → proj_flow-0.11.1}/PKG-INFO +1 -1
  3. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/__init__.py +1 -1
  4. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/api/env.py +65 -2
  5. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/api/init.py +3 -0
  6. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/base/registry.py +11 -3
  7. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/ext/cplusplus/cmake/__init__.py +2 -2
  8. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/ext/cplusplus/cmake/steps.py +1 -2
  9. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/ext/cplusplus/conan/__init__.py +0 -5
  10. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/minimal/__init__.py +2 -2
  11. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/minimal/base.py +5 -0
  12. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/minimal/init.py +5 -2
  13. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/project/api.py +20 -3
  14. proj_flow-0.11.1/src/proj_flow/project/cplusplus/__init__.py +10 -0
  15. proj_flow-0.10.0/src/proj_flow/ext/cplusplus/cmake/context.py → proj_flow-0.11.1/src/proj_flow/project/cplusplus/cmake_context.py +9 -10
  16. proj_flow-0.11.1/src/proj_flow/project/cplusplus/conan_context.py +10 -0
  17. proj_flow-0.11.1/src/proj_flow/project/cplusplus/project.py +29 -0
  18. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/project/interact.py +45 -25
  19. proj_flow-0.10.0/src/proj_flow/project/cplusplus.py +0 -17
  20. {proj_flow-0.10.0 → proj_flow-0.11.1}/.flow/config.yaml +0 -0
  21. {proj_flow-0.10.0 → proj_flow-0.11.1}/.gitignore +0 -0
  22. {proj_flow-0.10.0 → proj_flow-0.11.1}/.readthedocs.yaml +0 -0
  23. {proj_flow-0.10.0 → proj_flow-0.11.1}/LICENSE +0 -0
  24. {proj_flow-0.10.0 → proj_flow-0.11.1}/README.md +0 -0
  25. {proj_flow-0.10.0 → proj_flow-0.11.1}/pyproject.toml +0 -0
  26. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/__main__.py +0 -0
  27. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/api/__init__.py +0 -0
  28. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/api/arg.py +0 -0
  29. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/api/completers.py +0 -0
  30. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/api/ctx.py +0 -0
  31. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/api/makefile.py +0 -0
  32. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/api/release.py +0 -0
  33. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/api/step.py +0 -0
  34. /proj_flow-0.10.0/src/proj_flow/ext/cplusplus/cmake/__version__.py → /proj_flow-0.11.1/src/proj_flow/base/__cmake_version__.py +0 -0
  35. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/base/__init__.py +0 -0
  36. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/base/cmd.py +0 -0
  37. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/base/inspect.py +0 -0
  38. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/base/matrix.py +0 -0
  39. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/base/name_list.py +0 -0
  40. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/base/plugins.py +0 -0
  41. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/base/uname.py +0 -0
  42. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/cli/__init__.py +0 -0
  43. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/cli/argument.py +0 -0
  44. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/cli/finder.py +0 -0
  45. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/dependency.py +0 -0
  46. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/ext/__init__.py +0 -0
  47. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/ext/cplusplus/__init__.py +0 -0
  48. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/ext/cplusplus/cmake/parser.py +0 -0
  49. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/ext/cplusplus/cmake/version.py +0 -0
  50. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/ext/cplusplus/conan/_conan.py +0 -0
  51. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/ext/github/__init__.py +0 -0
  52. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/ext/github/cli.py +0 -0
  53. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/ext/github/hosting.py +0 -0
  54. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/ext/github/switches.py +0 -0
  55. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/ext/markdown_changelog.py +0 -0
  56. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/ext/python/__init__.py +0 -0
  57. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/ext/python/rtdocs.py +0 -0
  58. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/ext/python/steps.py +0 -0
  59. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/ext/python/version.py +0 -0
  60. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/ext/re_structured_changelog.py +0 -0
  61. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/ext/sign/__init__.py +0 -0
  62. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/ext/sign/api.py +0 -0
  63. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/ext/sign/win32.py +0 -0
  64. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/ext/store.py +0 -0
  65. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/flow/__init__.py +0 -0
  66. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/flow/configs.py +0 -0
  67. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/flow/layer.py +0 -0
  68. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/flow/steps.py +0 -0
  69. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/log/__init__.py +0 -0
  70. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/log/commit.py +0 -0
  71. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/log/error.py +0 -0
  72. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/log/fmt.py +0 -0
  73. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/log/format.py +0 -0
  74. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/log/hosting/__init__.py +0 -0
  75. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/log/hosting/github.py +0 -0
  76. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/log/msg.py +0 -0
  77. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/log/release.py +0 -0
  78. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/log/rich_text/__init__.py +0 -0
  79. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/log/rich_text/api.py +0 -0
  80. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/log/rich_text/markdown.py +0 -0
  81. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/log/rich_text/re_structured_text.py +0 -0
  82. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/minimal/bootstrap.py +0 -0
  83. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/minimal/list.py +0 -0
  84. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/minimal/run.py +0 -0
  85. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/minimal/system.py +0 -0
  86. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/project/__init__.py +0 -0
  87. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/project/data.py +0 -0
  88. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/template/layers/base/.clang-format +0 -0
  89. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/template/layers/base/.flow/config.yml +0 -0
  90. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/template/layers/base/.flow/flow.py.mustache +0 -0
  91. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/template/layers/base/.flow/matrix.yml +0 -0
  92. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/template/layers/base/.flow/official.yml +0 -0
  93. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/template/layers/base/.gitignore +0 -0
  94. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/template/layers/base/README.md.mustache +0 -0
  95. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/template/layers/base/flow +0 -0
  96. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/template/layers/base/flow.cmd +0 -0
  97. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/template/layers/base.json +0 -0
  98. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/template/layers/cmake/.flow/cmake/common.cmake.mustache +0 -0
  99. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/template/layers/cmake/.flow/extensions/wall/__init__.py.mustache +0 -0
  100. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/template/layers/cmake/.flow/extensions/wall/icons/__init__.py.mustache +0 -0
  101. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/template/layers/cmake/.flow/extensions/wall/icons/magick.py.mustache +0 -0
  102. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/template/layers/cmake/.flow/packages/base.cmake.mustache +0 -0
  103. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/template/layers/cmake/.flow/packages/config.cmake +0 -0
  104. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/template/layers/cmake/.flow/packages/cpack.cmake +0 -0
  105. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/template/layers/cmake/.flow/packages/wix/cpack.cmake.mustache +0 -0
  106. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/template/layers/cmake/.flow/packages/wix/patches.in.wix +0 -0
  107. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/template/layers/cmake/.flow/packages/wix.cmake.mustache +0 -0
  108. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/template/layers/cmake/CMakeGraphVizOptions.cmake +0 -0
  109. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/template/layers/cmake/CMakeLists.txt.mustache +0 -0
  110. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/template/layers/cmake/CMakePresets.json +0 -0
  111. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/template/layers/cmake/data/assets/appicon.ico +0 -0
  112. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/template/layers/cmake/data/assets/appicon.png +0 -0
  113. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/template/layers/cmake/data/assets/wix_banner.bmp +0 -0
  114. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/template/layers/cmake/data/assets/wix_dialog.bmp +0 -0
  115. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/template/layers/cmake/data/icons/.gitignore +0 -0
  116. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/template/layers/cmake/data/icons/appicon-mask.svg +0 -0
  117. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/template/layers/cmake/data/icons/appicon.svg +0 -0
  118. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/template/layers/cmake/src/main.cc.mustache +0 -0
  119. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/template/layers/cmake/src/version.hpp.in.mustache +0 -0
  120. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/template/layers/cmake/tests/test.cc.mustache +0 -0
  121. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/template/layers/cmake.json +0 -0
  122. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/template/layers/conan/.flow/cmake/libcxx_toolchain.cmake +0 -0
  123. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/template/layers/conan/.flow/cmake/output_dirs_setup.cmake +0 -0
  124. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/template/layers/conan/conanfile.txt +0 -0
  125. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/template/layers/conan.json +0 -0
  126. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/template/layers/github_actions/.github/linters/.isort.cfg +0 -0
  127. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/template/layers/github_actions/.github/linters/.mypy.ini +0 -0
  128. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/template/layers/github_actions/.github/workflows/build.yml +0 -0
  129. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/template/layers/github_actions/.github/workflows/linter.yml +0 -0
  130. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/template/layers/github_actions/CPPLINT.cfg +0 -0
  131. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/template/layers/github_actions.json +0 -0
  132. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/template/layers/github_social/.github/ISSUE_TEMPLATE/bug_report.md.mustache +0 -0
  133. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/template/layers/github_social/.github/ISSUE_TEMPLATE/feature_request.md.mustache +0 -0
  134. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/template/layers/github_social/CODE_OF_CONDUCT.md.mustache +0 -0
  135. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/template/layers/github_social/CONTRIBUTING.md +0 -0
  136. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/template/layers/github_social.json +0 -0
  137. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/template/licenses/0BSD.mustache +0 -0
  138. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/template/licenses/MIT.mustache +0 -0
  139. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/template/licenses/Unlicense.mustache +0 -0
  140. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/template/licenses/WTFPL.mustache +0 -0
  141. {proj_flow-0.10.0 → proj_flow-0.11.1}/src/proj_flow/template/licenses/Zlib.mustache +0 -0
@@ -4,6 +4,27 @@ Changelog
4
4
 
5
5
  All notable changes to this project will be documented in this file.
6
6
 
7
+ `0.11.1 <https://github.com/mzdun/proj-flow/compare/v0.11.0...v0.11.1>`_ (2025-02-19)
8
+ =====================================================================================
9
+
10
+ Bug Fixes
11
+ ---------
12
+
13
+ - bring back base ext (git initial commit) (`3f97d0a <https://github.com/mzdun/proj-flow/commit/3f97d0a6407b26728f4e99bf8985600e8d41acae>`_)
14
+
15
+ `0.11.0 <https://github.com/mzdun/proj-flow/compare/v0.10.0...v0.11.0>`_ (2025-02-09)
16
+ =====================================================================================
17
+
18
+ New Features
19
+ ------------
20
+
21
+ - read config in user directory (`8721d90 <https://github.com/mzdun/proj-flow/commit/8721d90ee9be579f544baadfa466f6d1621366e6>`_)
22
+
23
+ Bug Fixes
24
+ ---------
25
+
26
+ - bring back cmake and conan initailisation (`8148f52 <https://github.com/mzdun/proj-flow/commit/8148f52e6d3fda66349f552dfb02f524a81ee33c>`_)
27
+
7
28
  `0.10.0 <https://github.com/mzdun/proj-flow/compare/v0.9.4...v0.10.0>`_ (2025-02-09)
8
29
  ====================================================================================
9
30
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: proj-flow
3
- Version: 0.10.0
3
+ Version: 0.11.1
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/
@@ -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.10.0"
9
+ __version__ = "0.11.1"
@@ -23,6 +23,7 @@ from dataclasses import dataclass
23
23
  from enum import Enum
24
24
  from typing import Any, Callable, Dict, List, Optional, Union, cast
25
25
 
26
+ from proj_flow.api import ctx
26
27
  from proj_flow.base import plugins, uname
27
28
 
28
29
  platform = uname.uname()[0]
@@ -115,6 +116,59 @@ class RunAlias:
115
116
  return RunAlias(name, doc, steps)
116
117
 
117
118
 
119
+ def _merge_dicts(dst: dict, src: dict):
120
+ for key in src:
121
+ if key not in dst:
122
+ dst[key] = src[key]
123
+ continue
124
+
125
+ src_val = src[key]
126
+ dst_val = dst[key]
127
+
128
+ if isinstance(src_val, dict):
129
+ if isinstance(dst_val, dict):
130
+ _merge_dicts(dst_val, src_val)
131
+ continue
132
+
133
+ dst[key] = src_val
134
+
135
+
136
+ def _flatten_dict(dst: ctx.SettingsType, defaults: Dict[str, Any], prefix=""):
137
+ for key, val in defaults.items():
138
+ this_key = f"{prefix}{key}"
139
+
140
+ if isinstance(val, dict):
141
+ _flatten_dict(dst, val, f"{this_key}.")
142
+ continue
143
+
144
+ if val is None:
145
+ dst[this_key] = ""
146
+ continue
147
+
148
+ if isinstance(val, bool):
149
+ dst[this_key] = val
150
+ continue
151
+
152
+ dst[this_key] = str(val)
153
+
154
+
155
+ def _merge(cfg: dict, defaults: ctx.SettingsType, path: str):
156
+ config = plugins.load_data(path)
157
+ if not isinstance(config, dict):
158
+ return
159
+
160
+ stored_defaults = config.get("defaults", {})
161
+ try:
162
+ del config["defaults"]
163
+ except KeyError:
164
+ pass
165
+
166
+ _merge_dicts(cfg, config)
167
+
168
+ if isinstance(stored_defaults, dict):
169
+ _flatten_dict(defaults, stored_defaults)
170
+
171
+
118
172
  class FlowConfig:
119
173
  _cfg: dict
120
174
  steps: list = []
@@ -129,9 +183,18 @@ class FlowConfig:
129
183
  self.root = cfg.root
130
184
  else:
131
185
  self.root = os.path.abspath(root)
132
- self._cfg = plugins.load_data(
133
- os.path.join(self.root, ".flow", "config.json")
186
+ defaults: ctx.SettingsType = {}
187
+ dest: dict = {}
188
+
189
+ _merge(
190
+ dest,
191
+ defaults,
192
+ os.path.join(os.path.expanduser("~"), ".config", "proj-flow.json"),
134
193
  )
194
+ _merge(dest, defaults, os.path.join(self.root, ".flow", "config.json"))
195
+
196
+ self._cfg = dest
197
+ self._cfg["defaults"] = defaults
135
198
 
136
199
  self._propagate_compilers()
137
200
  self._load_extensions()
@@ -11,6 +11,9 @@ from proj_flow.api.env import Runtime
11
11
 
12
12
 
13
13
  class InitStep:
14
+ def priority(self):
15
+ return 100
16
+
14
17
  def platform_dependencies(self) -> List[str]:
15
18
  return []
16
19
 
@@ -99,6 +99,14 @@ class Registry(typing.Generic[T]):
99
99
  _debug_copies: typing.List[Registry] = []
100
100
 
101
101
 
102
+ def quoted(s: str) -> str:
103
+ if '"' in s:
104
+ return "'{}'".format(s.replace("\\", r"\\").replace("'", r"\'"))
105
+ if "'" in s or " " in s:
106
+ return '"{}"'.format(s)
107
+ return s
108
+
109
+
102
110
  def verbose_info():
103
111
  for registry in _debug_copies:
104
112
  for item in registry.container:
@@ -107,12 +115,12 @@ def verbose_info():
107
115
  kw = OrderedDict()
108
116
 
109
117
  if hasattr(item, "name"):
110
- kw["name"] = getattr(item, "name")
118
+ kw["name"] = quoted(getattr(item, "name"))
111
119
  elif hasattr(item, "__name__"):
112
- kw["name"] = getattr(item, "__name__")
120
+ kw["name"] = quoted(getattr(item, "__name__"))
113
121
 
114
122
  if hasattr(item, "id"):
115
- kw["id"] = getattr(item, "id")
123
+ kw["id"] = quoted(getattr(item, "id"))
116
124
 
117
125
  items = ", ".join([f"{key}={value}" for key, value in kw.items()])
118
126
  if len(items) > 0:
@@ -7,6 +7,6 @@ The **proj_flow.ext.cplusplus.cmake** provides ``"CMake"``, ``"Build"``,
7
7
  context.
8
8
  """
9
9
 
10
- from . import context, parser, steps, version
10
+ from . import parser, steps, version
11
11
 
12
- __all__ = ["context", "parser", "steps", "version"]
12
+ __all__ = ["parser", "steps", "version"]
@@ -11,8 +11,7 @@ from typing import Dict, List, cast
11
11
 
12
12
  from proj_flow import api
13
13
  from proj_flow.api import env, step
14
-
15
- from .__version__ import CMAKE_VERSION
14
+ from proj_flow.base.__cmake_version__ import CMAKE_VERSION
16
15
 
17
16
 
18
17
  class CMakeBase(api.step.Step):
@@ -63,8 +63,3 @@ class ConanConfig:
63
63
  if not rt.dry_run and os.path.exists("CMakeUserPresets.json"):
64
64
  os.remove("CMakeUserPresets.json")
65
65
  return 0
66
-
67
-
68
- cplusplus.project.register_switch(
69
- "with_conan", "Use Conan for dependency manager", True
70
- )
@@ -6,6 +6,6 @@ The **proj_flow.minimal** defines minimal extension package: ``bootstrap``
6
6
  and ``run`` commands, with basic set of steps.
7
7
  """
8
8
 
9
- from . import bootstrap, init, list, run, system
9
+ from . import base, bootstrap, init, list, run, system
10
10
 
11
- __all__ = ["bootstrap", "init", "list", "run", "system"]
11
+ __all__ = ["base", "bootstrap", "init", "list", "run", "system"]
@@ -6,10 +6,15 @@ The **proj_flow.minimal.base** provides basic initialization setup for all
6
6
  new projects.
7
7
  """
8
8
 
9
+ import sys
10
+
9
11
  from proj_flow import __version__, api
10
12
 
11
13
 
12
14
  class GitInit(api.init.InitStep):
15
+ def priority(self):
16
+ return sys.maxsize
17
+
13
18
  def platform_dependencies(self):
14
19
  return ["git"]
15
20
 
@@ -79,7 +79,7 @@ def main(
79
79
  print(f"proj-flow: {error}", file=sys.stderr)
80
80
  return 1
81
81
 
82
- context = current_project.get_context(not non_interactive)
82
+ context = current_project.get_context(not non_interactive, rt)
83
83
  if not non_interactive and not rt.silent:
84
84
  print()
85
85
 
@@ -104,5 +104,8 @@ def main(
104
104
  with open(".gitignore", "ab") as ignoref:
105
105
  ignoref.write("\n/.context.yaml\n".encode("UTF-8"))
106
106
 
107
- for step in init.__steps:
107
+ current_project.append_extensions(context)
108
+
109
+ steps = sorted((step.priority(), i, step) for i, step in enumerate(init.__steps))
110
+ for _, _, step in steps:
108
111
  step.postprocess(rt, context)
@@ -9,7 +9,7 @@ from abc import ABC, abstractmethod
9
9
  from typing import Any, List, NamedTuple, Optional
10
10
 
11
11
  from proj_flow import base
12
- from proj_flow.api import ctx
12
+ from proj_flow.api import ctx, env
13
13
  from proj_flow.project import interact
14
14
 
15
15
 
@@ -30,8 +30,25 @@ class ProjectType(ABC):
30
30
  def register_init_setting(self, *settings: ctx.Setting, is_hidden=False):
31
31
  ctx.register_init_setting(*settings, is_hidden=is_hidden, project=self.id)
32
32
 
33
- def get_context(self, interactive: bool):
34
- return interact.get_context(interactive, self.id)
33
+ def get_context(self, interactive: bool, rt: env.Runtime):
34
+ return interact.get_context(interactive, self.id, rt)
35
+
36
+ def append_extensions(self, context: dict):
37
+ extensions = self.get_extension_list(context)
38
+ if len(extensions) == 0:
39
+ return
40
+ text = "".join(f"\n - {ext}" for ext in extensions)
41
+ text = f"extensions:{text}\n\n"
42
+
43
+ with open(".flow/config.yml", encoding="UTF-8") as config_file:
44
+ content = config_file.read()
45
+
46
+ with open(".flow/config.yml", "w", encoding="UTF-8") as config_file:
47
+ config_file.write(text)
48
+ config_file.write(content)
49
+
50
+ @abstractmethod
51
+ def get_extension_list(self, context: dict) -> List[str]: ...
35
52
 
36
53
 
37
54
  project_type = base.registry.Registry[ProjectType]("ProjectType")
@@ -0,0 +1,10 @@
1
+ # Copyright (c) 2025 Marcin Zdun
2
+ # This code is licensed under MIT license (see LICENSE for details)
3
+
4
+ """
5
+ The **proj_flow.project.cplusplus** registers a ``"C++"`` projects support.
6
+ """
7
+
8
+ from proj_flow.project.cplusplus import cmake_context, conan_context
9
+
10
+ __all__ = ["cmake_context", "conan_context"]
@@ -12,9 +12,9 @@ import uuid
12
12
  import chevron
13
13
 
14
14
  from proj_flow import api, project
15
- from proj_flow.project import cplusplus
16
-
17
- from .__version__ import CMAKE_VERSION
15
+ from proj_flow.base.__cmake_version__ import CMAKE_VERSION
16
+ from proj_flow.project import data
17
+ from proj_flow.project.cplusplus import project
18
18
 
19
19
  config_json_mustache = """
20
20
  {{#with_cmake}}
@@ -23,7 +23,6 @@ cmake:
23
23
  {{NAME_PREFIX}}_COVERAGE: "?config:coverage"
24
24
  {{NAME_PREFIX}}_SANITIZE: "?config:sanitizer"
25
25
  {{NAME_PREFIX}}_CUTDOWN_OS: "?runtime:cutdown_os"
26
-
27
26
  {{/with_cmake}}
28
27
  """
29
28
 
@@ -35,7 +34,7 @@ class CMakeInit(api.init.InitStep):
35
34
  return
36
35
 
37
36
  with open(".flow/config.yml", encoding="UTF-8") as config_file:
38
- patched = re.split(r"(\nshortcuts:\n)", config_file.read())
37
+ patched = re.split(r"(\n\nshortcuts:\n)", config_file.read())
39
38
 
40
39
  if len(patched) != 3:
41
40
  return
@@ -50,23 +49,23 @@ class CMakeInit(api.init.InitStep):
50
49
  def _list_cmake_types():
51
50
  return api.ctx.move_to_front(
52
51
  "console-application",
53
- sorted(key for key in project.data.get_internal("cmake").keys() if key),
52
+ sorted(key for key in data.get_internal("cmake").keys() if key),
54
53
  )
55
54
 
56
55
 
57
56
  api.init.register_init_step(CMakeInit())
58
57
 
59
- cplusplus.project.register_init_setting(
58
+ project.cxx.register_init_setting(
60
59
  api.ctx.Setting("PROJECT.TYPE", "CMake project type", _list_cmake_types)
61
60
  )
62
- cplusplus.project.register_init_setting(
61
+ project.cxx.register_init_setting(
63
62
  api.ctx.Setting("cmake", fix="{PROJECT.TYPE$map:cmake}"),
64
63
  api.ctx.Setting("CMAKE_VERSION", value=CMAKE_VERSION),
65
64
  api.ctx.Setting("PROJECT.WIX.UPGRADE_GUID", value=lambda: str(uuid.uuid4())),
66
65
  is_hidden=True,
67
66
  )
68
- cplusplus.project.register_switch("with_cmake", "Use CMake", True)
69
- cplusplus.project.register_internal(
67
+ project.cxx.register_switch("with_cmake", "Use CMake", True)
68
+ project.cxx.register_internal(
70
69
  "cmake",
71
70
  {
72
71
  "": {"cmd": "add_executable", "type": ""},
@@ -0,0 +1,10 @@
1
+ # Copyright (c) 2025 Marcin Zdun
2
+ # This code is licensed under MIT license (see LICENSE for details)
3
+
4
+ """
5
+ The **proj_flow.ext.cplusplus.conan** provides the ``"Conan"`` step.
6
+ """
7
+
8
+ from proj_flow.project.cplusplus import project
9
+
10
+ project.cxx.register_switch("with_conan", "Use Conan for dependency manager", True)
@@ -0,0 +1,29 @@
1
+ # Copyright (c) 2025 Marcin Zdun
2
+ # This code is licensed under MIT license (see LICENSE for details)
3
+
4
+ """
5
+ The **proj_flow.project.cplusplus** registers a ``"C++"`` projects support.
6
+ """
7
+
8
+ from proj_flow.project import api
9
+
10
+ CPP_EXTENSIONS = [
11
+ "proj_flow.ext.cplusplus",
12
+ "proj_flow.ext.sign",
13
+ "proj_flow.ext.store",
14
+ ]
15
+
16
+
17
+ @api.project_type.add
18
+ class CPlusPlus(api.ProjectType):
19
+ def __init__(self):
20
+ super().__init__("C++ plus CMake plus Conan", "cxx")
21
+
22
+ def get_extension_list(self, context: dict):
23
+ with_github_actions = not not context.get("with_github_actions")
24
+ if with_github_actions:
25
+ return [*CPP_EXTENSIONS, "proj_flow.ext.github"]
26
+ return CPP_EXTENSIONS
27
+
28
+
29
+ cxx = api.get_project_type("cxx")
@@ -15,7 +15,7 @@ from prompt_toolkit.formatted_text.base import AnyFormattedText
15
15
  from prompt_toolkit.shortcuts import CompleteStyle
16
16
  from prompt_toolkit.validation import Validator
17
17
 
18
- from proj_flow.api import ctx
18
+ from proj_flow.api import ctx, env
19
19
 
20
20
 
21
21
  @dataclass
@@ -25,8 +25,18 @@ class _Question:
25
25
  value: ctx.Values
26
26
 
27
27
  @classmethod
28
- def load_default(cls, default: ctx.Setting, previous: ctx.SettingsType):
28
+ def load_default(
29
+ cls,
30
+ default: ctx.Setting,
31
+ previous: ctx.SettingsType,
32
+ override: Optional[ctx.StrOrBool],
33
+ ):
29
34
  value = default.calc_value(previous)
35
+ if override is not None:
36
+ if isinstance(value, (str, bool)) and type(value) == type(override):
37
+ value = override
38
+ elif isinstance(value, list) and isinstance(override, str):
39
+ value = ctx.move_to_front(override, value)
30
40
  return cls(default.json_key, default.prompt, value)
31
41
 
32
42
  def interact(self, counter: int, size: int) -> ctx.StrOrBool:
@@ -123,7 +133,9 @@ def _project_filter(project: Optional[str]):
123
133
  return impl
124
134
 
125
135
 
126
- def _prompt(wanted: Callable[[ctx.Setting], bool]) -> ctx.SettingsType:
136
+ def _prompt(
137
+ wanted: Callable[[ctx.Setting], bool], overrides: ctx.SettingsType
138
+ ) -> ctx.SettingsType:
127
139
  settings: ctx.SettingsType = {}
128
140
 
129
141
  defaults = [setting for setting in ctx.defaults if wanted(setting)]
@@ -132,22 +144,19 @@ def _prompt(wanted: Callable[[ctx.Setting], bool]) -> ctx.SettingsType:
132
144
  size = len(defaults) + len(switches)
133
145
  counter = 1
134
146
 
135
- for setting in defaults:
136
- loaded = _Question.load_default(setting, settings)
137
- value = loaded.interact(counter, size)
138
- settings[loaded.key] = value
139
- counter += 1
140
-
141
- for setting in switches:
142
- loaded = _Question.load_default(setting, settings)
143
- value = loaded.interact(counter, size)
144
- settings[loaded.key] = value
145
- counter += 1
147
+ for coll in [defaults, switches]:
148
+ for setting in coll:
149
+ loaded = _Question.load_default(
150
+ setting, settings, overrides.get(setting.json_key)
151
+ )
152
+ value = loaded.interact(counter, size)
153
+ settings[loaded.key] = value
154
+ counter += 1
146
155
 
147
156
  return settings
148
157
 
149
158
 
150
- def _all_default(wanted: Callable[[ctx.Setting], bool]):
159
+ def _all_default(wanted: Callable[[ctx.Setting], bool], overrides: ctx.SettingsType):
151
160
  """
152
161
  Chooses default answers for all details of newly-crated project.
153
162
 
@@ -160,13 +169,13 @@ def _all_default(wanted: Callable[[ctx.Setting], bool]):
160
169
  defaults = [setting for setting in ctx.defaults if wanted(setting)]
161
170
  switches = [setting for setting in ctx.switches if wanted(setting)]
162
171
 
163
- for setting in defaults:
164
- value = _get_default(setting, settings)
165
- settings[setting.json_key] = value
166
-
167
- for setting in switches:
168
- value = _get_default(setting, settings)
169
- settings[setting.json_key] = value
172
+ for coll in [defaults, switches]:
173
+ for setting in coll:
174
+ if setting.json_key in overrides:
175
+ settings[setting.json_key] = overrides[setting.json_key]
176
+ else:
177
+ value = _get_default(setting, settings)
178
+ settings[setting.json_key] = value
170
179
 
171
180
  return settings
172
181
 
@@ -217,19 +226,30 @@ def _fixup_context(settings: ctx.SettingsType, wanted: Callable[[ctx.Setting], b
217
226
  return result
218
227
 
219
228
 
220
- def get_context(interactive: bool, project: Optional[str]):
229
+ def get_context(interactive: bool, project: Optional[str], rt: env.Runtime):
221
230
  """
222
231
  Prompts user to provide details of newly-crated project. If `interactive`
223
232
  is true, however, this functions skips the prompts and chooses all the
224
233
  default answers.
225
234
 
226
235
  :param interactive: Selects, if the initialization process is done through
227
- prompts, or not
236
+ prompts, or not.
237
+
238
+ :param project: Alows to select questions for any given language.
239
+
240
+ :param rt: Runtime with config loaded in.
228
241
 
229
242
  :returns: Dictionary with answers to all interactive settings and switches.
230
243
  """
231
244
 
245
+ overrides = rt._cfg.get("defaults", {})
246
+
232
247
  wanted = _project_filter(project)
233
248
  return _fixup_context(
234
- _all_default(wanted) if not interactive else _prompt(wanted), wanted
249
+ (
250
+ _all_default(wanted, overrides)
251
+ if not interactive
252
+ else _prompt(wanted, overrides)
253
+ ),
254
+ wanted,
235
255
  )
@@ -1,17 +0,0 @@
1
- # Copyright (c) 2025 Marcin Zdun
2
- # This code is licensed under MIT license (see LICENSE for details)
3
-
4
- """
5
- The **proj_flow.project.cplusplus** registers a ``"C++"`` projects support.
6
- """
7
-
8
- from proj_flow.project import api
9
-
10
-
11
- @api.project_type.add
12
- class CPlusPlus(api.ProjectType):
13
- def __init__(self):
14
- super().__init__("C++ + CMake + Conan", "cxx")
15
-
16
-
17
- project = api.get_project_type("cxx")
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes