proj-flow 0.9.3__py3-none-any.whl → 0.10.0__py3-none-any.whl
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.
- proj_flow/__init__.py +6 -1
- proj_flow/api/arg.py +47 -24
- proj_flow/api/ctx.py +43 -23
- proj_flow/api/env.py +7 -2
- proj_flow/api/makefile.py +1 -1
- proj_flow/api/step.py +3 -5
- proj_flow/base/name_list.py +19 -0
- proj_flow/base/plugins.py +1 -36
- proj_flow/base/registry.py +19 -4
- proj_flow/cli/__init__.py +2 -4
- proj_flow/cli/argument.py +3 -3
- proj_flow/{flow/dependency.py → dependency.py} +1 -1
- proj_flow/ext/cplusplus/__init__.py +10 -0
- proj_flow/ext/cplusplus/cmake/__init__.py +12 -0
- proj_flow/{plugins → ext/cplusplus}/cmake/__version__.py +5 -0
- proj_flow/{plugins → ext/cplusplus}/cmake/context.py +10 -8
- proj_flow/{plugins → ext/cplusplus}/cmake/parser.py +6 -28
- proj_flow/ext/cplusplus/cmake/steps.py +142 -0
- proj_flow/ext/cplusplus/cmake/version.py +35 -0
- proj_flow/{plugins → ext/cplusplus}/conan/__init__.py +7 -3
- proj_flow/{plugins → ext/cplusplus}/conan/_conan.py +8 -3
- proj_flow/ext/github/__init__.py +2 -2
- proj_flow/ext/github/cli.py +2 -11
- proj_flow/{plugins/github.py → ext/github/switches.py} +3 -3
- proj_flow/ext/{markdown_changelist.py → markdown_changelog.py} +2 -1
- proj_flow/ext/python/rtdocs.py +1 -1
- proj_flow/ext/python/version.py +1 -2
- proj_flow/ext/{re_structured_changelist.py → re_structured_changelog.py} +3 -1
- proj_flow/{plugins → ext}/sign/__init__.py +64 -44
- proj_flow/ext/sign/api.py +83 -0
- proj_flow/ext/sign/win32.py +152 -0
- proj_flow/{plugins/store/store_packages.py → ext/store.py} +51 -9
- proj_flow/flow/__init__.py +2 -2
- proj_flow/log/release.py +1 -1
- proj_flow/log/rich_text/markdown.py +1 -1
- proj_flow/log/rich_text/re_structured_text.py +1 -1
- proj_flow/minimal/__init__.py +2 -2
- proj_flow/{plugins → minimal}/base.py +3 -2
- proj_flow/{plugins/commands → minimal}/init.py +44 -11
- proj_flow/minimal/run.py +1 -2
- proj_flow/project/__init__.py +11 -0
- proj_flow/project/api.py +51 -0
- proj_flow/project/cplusplus.py +17 -0
- proj_flow/project/data.py +14 -0
- proj_flow/{flow → project}/interact.py +114 -13
- {proj_flow-0.9.3.dist-info → proj_flow-0.10.0.dist-info}/METADATA +3 -2
- {proj_flow-0.9.3.dist-info → proj_flow-0.10.0.dist-info}/RECORD +50 -55
- proj_flow/flow/init.py +0 -65
- proj_flow/plugins/__init__.py +0 -8
- proj_flow/plugins/cmake/__init__.py +0 -11
- proj_flow/plugins/cmake/build.py +0 -29
- proj_flow/plugins/cmake/config.py +0 -59
- proj_flow/plugins/cmake/pack.py +0 -37
- proj_flow/plugins/cmake/test.py +0 -29
- proj_flow/plugins/commands/__init__.py +0 -12
- proj_flow/plugins/commands/ci/__init__.py +0 -17
- proj_flow/plugins/commands/ci/changelog.py +0 -47
- proj_flow/plugins/commands/ci/matrix.py +0 -46
- proj_flow/plugins/commands/ci/release.py +0 -116
- proj_flow/plugins/sign/win32.py +0 -191
- proj_flow/plugins/store/__init__.py +0 -11
- proj_flow/plugins/store/store_both.py +0 -22
- proj_flow/plugins/store/store_tests.py +0 -21
- {proj_flow-0.9.3.dist-info → proj_flow-0.10.0.dist-info}/WHEEL +0 -0
- {proj_flow-0.9.3.dist-info → proj_flow-0.10.0.dist-info}/entry_points.txt +0 -0
- {proj_flow-0.9.3.dist-info → proj_flow-0.10.0.dist-info}/licenses/LICENSE +0 -0
proj_flow/__init__.py
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
# Copyright (c) 2025 Marcin Zdun
|
|
2
2
|
# This code is licensed under MIT license (see LICENSE for details)
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
"""
|
|
5
|
+
The **proj_flow** contains only ``__version__`` to be updated, nothing more.
|
|
6
|
+
This is in an attempt to make this module easy to load initially.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
__version__ = "0.10.0"
|
proj_flow/api/arg.py
CHANGED
|
@@ -12,48 +12,71 @@ from dataclasses import dataclass, field
|
|
|
12
12
|
|
|
13
13
|
from proj_flow.base import inspect as _inspect
|
|
14
14
|
|
|
15
|
+
T = typing.TypeVar("T")
|
|
16
|
+
LazyArgument = typing.Union[T, typing.Callable[[], T]]
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def _eval(arg: LazyArgument[T]) -> T:
|
|
20
|
+
if callable(arg):
|
|
21
|
+
return typing.cast(T, arg())
|
|
22
|
+
return arg
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class _Completable(typing.Protocol):
|
|
26
|
+
completer: _inspect.Function
|
|
27
|
+
|
|
15
28
|
|
|
16
29
|
@dataclass
|
|
17
30
|
class Argument:
|
|
18
|
-
help: str = ""
|
|
31
|
+
help: LazyArgument[str] = ""
|
|
19
32
|
pos: bool = False
|
|
20
|
-
names: typing.List[str] = field(default_factory=list)
|
|
21
|
-
nargs: typing.Union[str, int, None] = None
|
|
22
|
-
opt: typing.Optional[bool] = None
|
|
23
|
-
meta: typing.Optional[str] = None
|
|
24
|
-
action: typing.Union[str, argparse.Action, None] = None
|
|
25
|
-
default: typing.Optional[typing.Any] = None
|
|
26
|
-
choices: typing.Optional[typing.List[str]] = None
|
|
33
|
+
names: LazyArgument[typing.List[str]] = field(default_factory=list)
|
|
34
|
+
nargs: LazyArgument[typing.Union[str, int, None]] = None
|
|
35
|
+
opt: LazyArgument[typing.Optional[bool]] = None
|
|
36
|
+
meta: LazyArgument[typing.Optional[str]] = None
|
|
37
|
+
action: LazyArgument[typing.Union[str, argparse.Action, None]] = None
|
|
38
|
+
default: LazyArgument[typing.Optional[typing.Any]] = None
|
|
39
|
+
choices: LazyArgument[typing.Optional[typing.List[str]]] = None
|
|
27
40
|
completer: typing.Optional[_inspect.Function] = None
|
|
28
41
|
|
|
29
42
|
def visit(self, parser: argparse.ArgumentParser, name: str):
|
|
30
43
|
kwargs = {}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
if
|
|
42
|
-
kwargs["
|
|
44
|
+
|
|
45
|
+
self_help = _eval(self.help)
|
|
46
|
+
self_names = _eval(self.names)
|
|
47
|
+
self_nargs = _eval(self.nargs)
|
|
48
|
+
self_opt = _eval(self.opt)
|
|
49
|
+
self_meta = _eval(self.meta)
|
|
50
|
+
self_action = _eval(self.action)
|
|
51
|
+
self_default = _eval(self.default)
|
|
52
|
+
self_choices = _eval(self.choices)
|
|
53
|
+
|
|
54
|
+
if self_help is not None:
|
|
55
|
+
kwargs["help"] = self_help
|
|
56
|
+
if self_nargs is not None:
|
|
57
|
+
kwargs["nargs"] = self_nargs
|
|
58
|
+
if self_meta is not None:
|
|
59
|
+
kwargs["metavar"] = self_meta
|
|
60
|
+
if self_default is not None:
|
|
61
|
+
kwargs["default"] = self_default
|
|
62
|
+
if self_action is not None:
|
|
63
|
+
kwargs["action"] = self_action
|
|
64
|
+
if self_choices is not None:
|
|
65
|
+
kwargs["choices"] = self_choices
|
|
43
66
|
|
|
44
67
|
names = (
|
|
45
|
-
[name] if self.pos else
|
|
68
|
+
[name] if self.pos else self_names if len(self_names) > 0 else [f"--{name}"]
|
|
46
69
|
)
|
|
47
70
|
|
|
48
71
|
if self.pos:
|
|
49
|
-
kwargs["nargs"] = "?" if
|
|
72
|
+
kwargs["nargs"] = "?" if self_opt else 1
|
|
50
73
|
else:
|
|
51
74
|
kwargs["dest"] = name
|
|
52
|
-
kwargs["required"] = not
|
|
75
|
+
kwargs["required"] = not self_opt
|
|
53
76
|
|
|
54
77
|
action = parser.add_argument(*names, **kwargs)
|
|
55
78
|
if self.completer:
|
|
56
|
-
action.completer = self.completer
|
|
79
|
+
typing.cast(_Completable, action).completer = self.completer
|
|
57
80
|
|
|
58
81
|
return action
|
|
59
82
|
|
proj_flow/api/ctx.py
CHANGED
|
@@ -9,9 +9,10 @@ import datetime
|
|
|
9
9
|
import inspect
|
|
10
10
|
import os
|
|
11
11
|
from dataclasses import dataclass
|
|
12
|
-
from typing import Callable, Dict, Iterable, List, Optional, Union
|
|
12
|
+
from typing import Any, Callable, Dict, Iterable, List, Optional, Union, cast
|
|
13
13
|
|
|
14
14
|
from proj_flow.base import cmd
|
|
15
|
+
from proj_flow.base import inspect as _inspect
|
|
15
16
|
|
|
16
17
|
package_root = os.path.dirname(os.path.dirname(__file__))
|
|
17
18
|
template_dir = "template"
|
|
@@ -26,32 +27,44 @@ SettingsType = Dict[str, StrOrBool]
|
|
|
26
27
|
class Setting:
|
|
27
28
|
json_key: str
|
|
28
29
|
prompt: str = ""
|
|
29
|
-
value: Union[Values, Callable[[], Values]] = ""
|
|
30
|
+
value: Union[Values, Callable[[], Values], Callable[[SettingsType], Values]] = ""
|
|
30
31
|
fix: Optional[str] = None
|
|
31
32
|
force_fix: bool = False
|
|
33
|
+
project: Optional[str] = None
|
|
32
34
|
|
|
33
35
|
def calc_value(self, previous: SettingsType):
|
|
34
|
-
if
|
|
36
|
+
if callable(self.value):
|
|
35
37
|
kwargs = {}
|
|
36
38
|
|
|
37
39
|
params = inspect.signature(self.value).parameters
|
|
38
40
|
if "settings" in params:
|
|
39
41
|
kwargs["settings"] = previous
|
|
40
42
|
|
|
41
|
-
return self.value(**kwargs)
|
|
43
|
+
return cast(_inspect.Function, self.value)(**kwargs)
|
|
42
44
|
|
|
43
45
|
return self.value
|
|
44
46
|
|
|
45
47
|
|
|
46
|
-
def register_init_setting(*
|
|
48
|
+
def register_init_setting(*settings: Setting, is_hidden=False, project: Optional[str]):
|
|
49
|
+
if project is not None:
|
|
50
|
+
for setting in settings:
|
|
51
|
+
setting.project = project
|
|
52
|
+
(hidden if is_hidden else defaults).extend(settings)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def register_common_init_setting(*setting: Setting, is_hidden=False):
|
|
47
56
|
(hidden if is_hidden else defaults).extend(setting)
|
|
48
57
|
|
|
49
58
|
|
|
50
|
-
def register_switch(key: str, prompt: str, enabled: bool):
|
|
59
|
+
def register_switch(key: str, prompt: str, enabled: bool, project: Optional[str]):
|
|
60
|
+
switches.append(Setting(key, prompt, value=enabled, project=project))
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def register_common_switch(key: str, prompt: str, enabled: bool):
|
|
51
64
|
switches.append(Setting(key, prompt, value=enabled))
|
|
52
65
|
|
|
53
66
|
|
|
54
|
-
def register_internal(key: str, value:
|
|
67
|
+
def register_internal(key: str, value: Any):
|
|
55
68
|
internals[key] = value
|
|
56
69
|
|
|
57
70
|
|
|
@@ -59,17 +72,20 @@ def _git_config(name: str):
|
|
|
59
72
|
def wrap():
|
|
60
73
|
proc = cmd.run("git", "config", name, capture_output=True)
|
|
61
74
|
if proc is None or proc.returncode != 0:
|
|
62
|
-
return
|
|
75
|
+
return ""
|
|
63
76
|
return proc.stdout.strip()
|
|
64
77
|
|
|
65
78
|
return wrap
|
|
66
79
|
|
|
67
80
|
|
|
68
|
-
def move_to_front(preferred: str, values: Iterable[str]):
|
|
81
|
+
def move_to_front(preferred: str, values: Iterable[Optional[str]]):
|
|
69
82
|
result: List[str] = []
|
|
70
83
|
|
|
71
84
|
has_preferred = False
|
|
72
85
|
for value in values:
|
|
86
|
+
if value is None:
|
|
87
|
+
continue
|
|
88
|
+
|
|
73
89
|
if value == preferred:
|
|
74
90
|
has_preferred = True
|
|
75
91
|
else:
|
|
@@ -94,7 +110,7 @@ def _enum_licenses():
|
|
|
94
110
|
root = os.path.abspath(os.path.join(package_root, template_dir, "licenses"))
|
|
95
111
|
for _, dirnames, filenames in os.walk(root):
|
|
96
112
|
dirnames[:] = []
|
|
97
|
-
iter =
|
|
113
|
+
iter = map(_as_mustache, filenames)
|
|
98
114
|
return move_to_front("MIT", iter)
|
|
99
115
|
return []
|
|
100
116
|
|
|
@@ -114,11 +130,11 @@ def _get_nothing(_: SettingsType) -> StrOrBool:
|
|
|
114
130
|
|
|
115
131
|
|
|
116
132
|
def _map(internal_key: str):
|
|
117
|
-
def impl(key:
|
|
133
|
+
def impl(key: StrOrBool) -> StrOrBool:
|
|
118
134
|
mapped = internals.get(internal_key)
|
|
119
135
|
if not isinstance(mapped, dict):
|
|
120
|
-
return
|
|
121
|
-
return mapped.get(key)
|
|
136
|
+
return ""
|
|
137
|
+
return mapped.get(key, "")
|
|
122
138
|
|
|
123
139
|
return impl
|
|
124
140
|
|
|
@@ -152,12 +168,12 @@ def _build_fixup(settings: SettingsType, fixup: str):
|
|
|
152
168
|
value = code(settings)
|
|
153
169
|
|
|
154
170
|
if result:
|
|
155
|
-
result
|
|
171
|
+
result = f"{result}{value}"
|
|
156
172
|
else:
|
|
157
173
|
result = value
|
|
158
174
|
|
|
159
175
|
if verbose:
|
|
160
|
-
result
|
|
176
|
+
result = f"{result}{verbose}"
|
|
161
177
|
|
|
162
178
|
return result
|
|
163
179
|
|
|
@@ -169,7 +185,7 @@ def _fixed(fixup: str):
|
|
|
169
185
|
return wrap
|
|
170
186
|
|
|
171
187
|
|
|
172
|
-
internals = {}
|
|
188
|
+
internals: Dict[str, Any] = {}
|
|
173
189
|
|
|
174
190
|
switches: List[Setting] = []
|
|
175
191
|
|
|
@@ -200,18 +216,21 @@ defaults: List[Setting] = [
|
|
|
200
216
|
"INCLUDE_PREFIX",
|
|
201
217
|
'Prefix for includes (as in #include "{PREFIX}/version.hpp")',
|
|
202
218
|
_fixed("{PROJECT.NAME}"),
|
|
219
|
+
project="cxx",
|
|
203
220
|
),
|
|
204
221
|
Setting(
|
|
205
222
|
"NAME_PREFIX",
|
|
206
223
|
"CMake variable name prefix",
|
|
207
224
|
_fixed("{PROJECT.NAME$safe$upper}"),
|
|
225
|
+
project="cxx",
|
|
208
226
|
),
|
|
209
227
|
Setting(
|
|
210
228
|
"NAMESPACE",
|
|
211
229
|
"C++ namespace for the project",
|
|
212
230
|
_fixed("{PROJECT.NAME$safe}"),
|
|
231
|
+
project="cxx",
|
|
213
232
|
),
|
|
214
|
-
Setting("EXT", "Extension for code files", _list_ext),
|
|
233
|
+
Setting("EXT", "Extension for code files", _list_ext, project="cxx"),
|
|
215
234
|
Setting("SRCDIR", "Directory for code files", "src"),
|
|
216
235
|
Setting(
|
|
217
236
|
"INCLUDEDIR",
|
|
@@ -219,20 +238,21 @@ defaults: List[Setting] = [
|
|
|
219
238
|
"include",
|
|
220
239
|
"{INCLUDEDIR}/{INCLUDE_PREFIX}",
|
|
221
240
|
force_fix=True,
|
|
241
|
+
project="cxx",
|
|
222
242
|
),
|
|
223
243
|
]
|
|
224
244
|
|
|
225
245
|
hidden: List[Setting] = [
|
|
226
|
-
Setting("EXT.cxx", fix="{EXT}"),
|
|
227
|
-
Setting("EXT.hxx", fix="{EXT.cxx$header}"),
|
|
246
|
+
Setting("EXT.cxx", fix="{EXT}", project="cxx"),
|
|
247
|
+
Setting("EXT.hxx", fix="{EXT.cxx$header}", project="cxx"),
|
|
228
248
|
]
|
|
229
249
|
|
|
230
250
|
_fileext = {".cc": ".hh", ".cxx": ".hxx", ".cpp": ".hpp"}
|
|
231
251
|
|
|
232
252
|
|
|
233
253
|
_filters: Dict[str, Callable[[StrOrBool], StrOrBool]] = {
|
|
234
|
-
"safe": lambda value: value.replace("-", "_"),
|
|
235
|
-
"upper": lambda value: value.upper(),
|
|
236
|
-
"lower": lambda value: value.lower(),
|
|
237
|
-
"header": lambda cxx_ext: _fileext.get(cxx_ext, ".hpp"),
|
|
254
|
+
"safe": lambda value: str(value).replace("-", "_"),
|
|
255
|
+
"upper": lambda value: str(value).upper(),
|
|
256
|
+
"lower": lambda value: str(value).lower(),
|
|
257
|
+
"header": lambda cxx_ext: _fileext.get(str(cxx_ext), ".hpp"),
|
|
238
258
|
}
|
proj_flow/api/env.py
CHANGED
|
@@ -24,7 +24,6 @@ from enum import Enum
|
|
|
24
24
|
from typing import Any, Callable, Dict, List, Optional, Union, cast
|
|
25
25
|
|
|
26
26
|
from proj_flow.base import plugins, uname
|
|
27
|
-
from proj_flow.base.plugins import load_module_plugins
|
|
28
27
|
|
|
29
28
|
platform = uname.uname()[0]
|
|
30
29
|
|
|
@@ -152,7 +151,13 @@ class FlowConfig:
|
|
|
152
151
|
sys.path.insert(0, local_extensions)
|
|
153
152
|
|
|
154
153
|
for extension in extensions:
|
|
155
|
-
|
|
154
|
+
try:
|
|
155
|
+
importlib.import_module(extension)
|
|
156
|
+
except ModuleNotFoundError:
|
|
157
|
+
print(
|
|
158
|
+
f"-- error: module `{extension}` was no found, ignoring",
|
|
159
|
+
file=sys.stderr,
|
|
160
|
+
)
|
|
156
161
|
|
|
157
162
|
@property
|
|
158
163
|
def entry(self) -> Dict[str, dict]:
|
proj_flow/api/makefile.py
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
# This code is licensed under MIT license (see LICENSE for details)
|
|
3
3
|
|
|
4
4
|
"""
|
|
5
|
-
The **proj_flow.api.
|
|
5
|
+
The **proj_flow.api.makefile** exposes simple makefile APIs, so extensions can
|
|
6
6
|
easily provide run steps with multiple scripts being called.
|
|
7
7
|
"""
|
|
8
8
|
|
proj_flow/api/step.py
CHANGED
|
@@ -12,6 +12,7 @@ from typing import List, cast
|
|
|
12
12
|
from proj_flow.api.env import Config, Runtime
|
|
13
13
|
from proj_flow.base import inspect as _inspect
|
|
14
14
|
from proj_flow.base import matrix
|
|
15
|
+
from proj_flow.base.name_list import name_list
|
|
15
16
|
|
|
16
17
|
|
|
17
18
|
class Step(ABC):
|
|
@@ -111,11 +112,8 @@ def _name_list(label: str, names: List[str], template="`{}`") -> str:
|
|
|
111
112
|
if len(names) == 0:
|
|
112
113
|
return ""
|
|
113
114
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
if prefix:
|
|
117
|
-
prefix += " and "
|
|
118
|
-
return f"\n:{label}: {prefix}{em[-1]}"
|
|
115
|
+
joined = name_list([template.format(name) for name in names])
|
|
116
|
+
return f"\n:{label}: {joined}"
|
|
119
117
|
|
|
120
118
|
|
|
121
119
|
def _make_private(f: _inspect.Function):
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Copyright (c) 2025 Marcin Zdun
|
|
2
|
+
# This code is licensed under MIT license (see LICENSE for details)
|
|
3
|
+
|
|
4
|
+
"""
|
|
5
|
+
The **proj_flow.base.name_list** provides name list helper for arguments with
|
|
6
|
+
choices
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from typing import List
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def name_list(names: List[str]) -> str:
|
|
13
|
+
if len(names) == 0:
|
|
14
|
+
return ""
|
|
15
|
+
|
|
16
|
+
prefix = ", ".join(names[:-1])
|
|
17
|
+
if prefix:
|
|
18
|
+
prefix += " and "
|
|
19
|
+
return f"{prefix}{names[-1]}"
|
proj_flow/base/plugins.py
CHANGED
|
@@ -5,11 +5,9 @@
|
|
|
5
5
|
The **proj_flow.base.plugins** provide the plugin enumeration helpers.
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
|
-
import importlib
|
|
9
8
|
import json
|
|
10
9
|
import os
|
|
11
|
-
from
|
|
12
|
-
from typing import Optional, cast
|
|
10
|
+
from typing import cast
|
|
13
11
|
|
|
14
12
|
import yaml
|
|
15
13
|
|
|
@@ -48,36 +46,3 @@ def load_data(filename: str):
|
|
|
48
46
|
pass
|
|
49
47
|
|
|
50
48
|
return {}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
def _load_plugins(directory: str, package: Optional[str], can_fail=False):
|
|
54
|
-
for _, dirnames, filenames in os.walk(directory):
|
|
55
|
-
for dirname in dirnames:
|
|
56
|
-
if dirname == "__pycache__":
|
|
57
|
-
continue
|
|
58
|
-
|
|
59
|
-
try:
|
|
60
|
-
importlib.import_module(f".{dirname}", package=package)
|
|
61
|
-
except ModuleNotFoundError as err:
|
|
62
|
-
if not can_fail:
|
|
63
|
-
raise err
|
|
64
|
-
for filename in filenames:
|
|
65
|
-
if filename == "__init__.py":
|
|
66
|
-
continue
|
|
67
|
-
|
|
68
|
-
try:
|
|
69
|
-
importlib.import_module(
|
|
70
|
-
f".{os.path.splitext(filename)[0]}", package=package
|
|
71
|
-
)
|
|
72
|
-
except ModuleNotFoundError as err:
|
|
73
|
-
if not can_fail:
|
|
74
|
-
raise err
|
|
75
|
-
dirnames[:] = []
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
def load_module_plugins(mod: ModuleType, can_fail=False):
|
|
79
|
-
spec = mod.__spec__
|
|
80
|
-
if not spec:
|
|
81
|
-
return
|
|
82
|
-
for location in spec.submodule_search_locations: # type: ignore
|
|
83
|
-
_load_plugins(location, spec.name, can_fail)
|
proj_flow/base/registry.py
CHANGED
|
@@ -2,10 +2,12 @@
|
|
|
2
2
|
# This code is licensed under MIT license (see LICENSE for details)
|
|
3
3
|
|
|
4
4
|
"""
|
|
5
|
-
The **proj_flow.base.registry**
|
|
5
|
+
The **proj_flow.base.registry** allows building extension points, with ability
|
|
6
|
+
to register the plugins with a decorator.
|
|
6
7
|
"""
|
|
7
8
|
|
|
8
9
|
import typing
|
|
10
|
+
from collections import OrderedDict
|
|
9
11
|
|
|
10
12
|
T = typing.TypeVar("T")
|
|
11
13
|
K = typing.TypeVar("K")
|
|
@@ -100,6 +102,19 @@ _debug_copies: typing.List[Registry] = []
|
|
|
100
102
|
def verbose_info():
|
|
101
103
|
for registry in _debug_copies:
|
|
102
104
|
for item in registry.container:
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
)
|
|
105
|
+
full_name = f"{item.__module__}.{item.__class__.__name__}"
|
|
106
|
+
|
|
107
|
+
kw = OrderedDict()
|
|
108
|
+
|
|
109
|
+
if hasattr(item, "name"):
|
|
110
|
+
kw["name"] = getattr(item, "name")
|
|
111
|
+
elif hasattr(item, "__name__"):
|
|
112
|
+
kw["name"] = getattr(item, "__name__")
|
|
113
|
+
|
|
114
|
+
if hasattr(item, "id"):
|
|
115
|
+
kw["id"] = getattr(item, "id")
|
|
116
|
+
|
|
117
|
+
items = ", ".join([f"{key}={value}" for key, value in kw.items()])
|
|
118
|
+
if len(items) > 0:
|
|
119
|
+
items = f" ({items})"
|
|
120
|
+
print(f"-- {registry.name}: adding `{full_name}`{items}")
|
proj_flow/cli/__init__.py
CHANGED
|
@@ -10,10 +10,8 @@ The **proj_flow.cli** provides command-line entry for the *Project Flow*.
|
|
|
10
10
|
import argparse
|
|
11
11
|
import os
|
|
12
12
|
import sys
|
|
13
|
-
from pprint import pprint
|
|
14
|
-
from typing import Dict, Optional, Tuple
|
|
15
13
|
|
|
16
|
-
from proj_flow.api import
|
|
14
|
+
from proj_flow.api import env
|
|
17
15
|
from proj_flow.cli import argument, finder
|
|
18
16
|
from proj_flow.flow import steps
|
|
19
17
|
|
|
@@ -31,7 +29,7 @@ def main():
|
|
|
31
29
|
def _change_dir():
|
|
32
30
|
root = argparse.ArgumentParser(
|
|
33
31
|
prog="proj-flow",
|
|
34
|
-
usage="proj-flow [-h] [--version] [-C [dir]]
|
|
32
|
+
usage="proj-flow [-h] [--version] [-C [dir]] command ...",
|
|
35
33
|
add_help=False,
|
|
36
34
|
)
|
|
37
35
|
root.add_argument("-C", dest="cd", nargs="?")
|
proj_flow/cli/argument.py
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
# This code is licensed under MIT license (see LICENSE for details)
|
|
3
3
|
|
|
4
4
|
"""
|
|
5
|
-
The **proj_flow.cli.
|
|
5
|
+
The **proj_flow.cli.argument** provides command-line builders and runners,
|
|
6
6
|
supporting the functions decorated with :func:`@arg.command()
|
|
7
7
|
<proj_flow.api.arg.command>`.
|
|
8
8
|
"""
|
|
@@ -192,7 +192,7 @@ class Command:
|
|
|
192
192
|
if len(self.children):
|
|
193
193
|
subparsers = parser.add_subparsers(
|
|
194
194
|
dest=f"command_{level}",
|
|
195
|
-
metavar="
|
|
195
|
+
metavar="command",
|
|
196
196
|
help="Known command name, see below",
|
|
197
197
|
)
|
|
198
198
|
subparsers.parent = parser # type: ignore
|
|
@@ -254,7 +254,7 @@ def _argparse_visit_all(
|
|
|
254
254
|
parser.shortcuts = shortcut_configs
|
|
255
255
|
|
|
256
256
|
subparsers = parser.add_subparsers(
|
|
257
|
-
dest="command", metavar="
|
|
257
|
+
dest="command", metavar="command", help="Known command name, see below"
|
|
258
258
|
)
|
|
259
259
|
|
|
260
260
|
subparsers.parent = parser # type: ignore
|
|
@@ -0,0 +1,12 @@
|
|
|
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.cmake** provides ``"CMake"``, ``"Build"``,
|
|
6
|
+
``"Pack"`` and ``"Test"`` steps, as well as CMake-specific initialization
|
|
7
|
+
context.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from . import context, parser, steps, version
|
|
11
|
+
|
|
12
|
+
__all__ = ["context", "parser", "steps", "version"]
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
# This code is licensed under MIT license (see LICENSE for details)
|
|
3
3
|
|
|
4
4
|
"""
|
|
5
|
-
The **proj_flow.
|
|
6
|
-
context.
|
|
5
|
+
The **proj_flow.ext.cplusplus.cmake.context** provides CMake-specific
|
|
6
|
+
initialization context.
|
|
7
7
|
"""
|
|
8
8
|
|
|
9
9
|
import re
|
|
@@ -11,7 +11,8 @@ import uuid
|
|
|
11
11
|
|
|
12
12
|
import chevron
|
|
13
13
|
|
|
14
|
-
from proj_flow import api,
|
|
14
|
+
from proj_flow import api, project
|
|
15
|
+
from proj_flow.project import cplusplus
|
|
15
16
|
|
|
16
17
|
from .__version__ import CMAKE_VERSION
|
|
17
18
|
|
|
@@ -49,22 +50,23 @@ class CMakeInit(api.init.InitStep):
|
|
|
49
50
|
def _list_cmake_types():
|
|
50
51
|
return api.ctx.move_to_front(
|
|
51
52
|
"console-application",
|
|
52
|
-
sorted(key for key in
|
|
53
|
+
sorted(key for key in project.data.get_internal("cmake").keys() if key),
|
|
53
54
|
)
|
|
54
55
|
|
|
55
56
|
|
|
56
57
|
api.init.register_init_step(CMakeInit())
|
|
57
|
-
|
|
58
|
+
|
|
59
|
+
cplusplus.project.register_init_setting(
|
|
58
60
|
api.ctx.Setting("PROJECT.TYPE", "CMake project type", _list_cmake_types)
|
|
59
61
|
)
|
|
60
|
-
|
|
62
|
+
cplusplus.project.register_init_setting(
|
|
61
63
|
api.ctx.Setting("cmake", fix="{PROJECT.TYPE$map:cmake}"),
|
|
62
64
|
api.ctx.Setting("CMAKE_VERSION", value=CMAKE_VERSION),
|
|
63
65
|
api.ctx.Setting("PROJECT.WIX.UPGRADE_GUID", value=lambda: str(uuid.uuid4())),
|
|
64
66
|
is_hidden=True,
|
|
65
67
|
)
|
|
66
|
-
|
|
67
|
-
|
|
68
|
+
cplusplus.project.register_switch("with_cmake", "Use CMake", True)
|
|
69
|
+
cplusplus.project.register_internal(
|
|
68
70
|
"cmake",
|
|
69
71
|
{
|
|
70
72
|
"": {"cmd": "add_executable", "type": ""},
|
|
@@ -2,13 +2,15 @@
|
|
|
2
2
|
# This code is licensed under MIT license (see LICENSE for details)
|
|
3
3
|
|
|
4
4
|
"""
|
|
5
|
-
The **proj_flow.
|
|
5
|
+
The **proj_flow.ext.cplusplus.cmake.parser** contains simple CMake parser.
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
8
|
import os
|
|
9
9
|
import re
|
|
10
10
|
from typing import Iterator, List, NamedTuple, Optional
|
|
11
11
|
|
|
12
|
+
from proj_flow.api.release import NO_ARG, Arg
|
|
13
|
+
|
|
12
14
|
TOKENS = [
|
|
13
15
|
("COMMENT", r"#.*"),
|
|
14
16
|
("STR", r'"[^"]*"'),
|
|
@@ -25,39 +27,18 @@ class Token(NamedTuple):
|
|
|
25
27
|
offset: int
|
|
26
28
|
|
|
27
29
|
|
|
28
|
-
class Arg(NamedTuple):
|
|
29
|
-
value: str
|
|
30
|
-
offset: int
|
|
31
|
-
|
|
32
|
-
|
|
33
30
|
class Command(NamedTuple):
|
|
34
31
|
name: str
|
|
35
32
|
args: List[Arg]
|
|
36
33
|
offset: int
|
|
37
34
|
|
|
38
35
|
|
|
39
|
-
class
|
|
36
|
+
class CMakeProject(NamedTuple):
|
|
40
37
|
name: Arg
|
|
41
38
|
version: Arg
|
|
42
39
|
stability: Arg
|
|
43
40
|
description: Arg
|
|
44
41
|
|
|
45
|
-
def set_version(self, directory: str, next_version: str):
|
|
46
|
-
_patch(directory, self.version, next_version)
|
|
47
|
-
return ["proj_flow/__init__.py"]
|
|
48
|
-
|
|
49
|
-
@property
|
|
50
|
-
def ver(self):
|
|
51
|
-
return f"{self.version.value}{self.stability.value}"
|
|
52
|
-
|
|
53
|
-
@property
|
|
54
|
-
def pkg(self):
|
|
55
|
-
return f"{self.name.value}-{self.ver}"
|
|
56
|
-
|
|
57
|
-
@property
|
|
58
|
-
def tag(self):
|
|
59
|
-
return f"v{self.ver}"
|
|
60
|
-
|
|
61
42
|
|
|
62
43
|
def _token_stream(text: str) -> Iterator[Token]:
|
|
63
44
|
tok_regex = "|".join("(?P<%s>%s)" % pair for pair in TOKENS)
|
|
@@ -121,10 +102,7 @@ def _patch(directory: str, arg: Arg, value: str):
|
|
|
121
102
|
input.write(patched)
|
|
122
103
|
|
|
123
104
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
def get_project(dirname: str) -> Optional[Project]:
|
|
105
|
+
def get_project(dirname: str) -> Optional[CMakeProject]:
|
|
128
106
|
try:
|
|
129
107
|
commands = _cmake(os.path.join(dirname, "CMakeLists.txt"))
|
|
130
108
|
except FileNotFoundError:
|
|
@@ -158,7 +136,7 @@ def get_project(dirname: str) -> Optional[Project]:
|
|
|
158
136
|
if version_stability is None:
|
|
159
137
|
version_stability = NO_ARG
|
|
160
138
|
|
|
161
|
-
return
|
|
139
|
+
return CMakeProject(
|
|
162
140
|
name=project_name,
|
|
163
141
|
version=version,
|
|
164
142
|
stability=version_stability,
|