proj-flow 0.20.2__py3-none-any.whl → 0.21.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 +1 -1
- proj_flow/api/arg.py +2 -0
- proj_flow/api/env.py +12 -2
- proj_flow/api/step.py +13 -2
- proj_flow/base/matrix.py +23 -0
- proj_flow/ext/cplusplus/cmake/presets.py +8 -4
- proj_flow/ext/cplusplus/cmake/steps.py +9 -3
- proj_flow/ext/cplusplus/conan/__init__.py +2 -0
- proj_flow/ext/github/cli.py +3 -0
- proj_flow/ext/python/rtdocs.py +35 -6
- proj_flow/flow/configs.py +16 -1
- proj_flow/minimal/list.py +126 -10
- proj_flow/project/api.py +1 -0
- {proj_flow-0.20.2.dist-info → proj_flow-0.21.0.dist-info}/METADATA +17 -7
- {proj_flow-0.20.2.dist-info → proj_flow-0.21.0.dist-info}/RECORD +18 -18
- {proj_flow-0.20.2.dist-info → proj_flow-0.21.0.dist-info}/WHEEL +0 -0
- {proj_flow-0.20.2.dist-info → proj_flow-0.21.0.dist-info}/entry_points.txt +0 -0
- {proj_flow-0.20.2.dist-info → proj_flow-0.21.0.dist-info}/licenses/LICENSE +0 -0
proj_flow/__init__.py
CHANGED
proj_flow/api/arg.py
CHANGED
proj_flow/api/env.py
CHANGED
|
@@ -173,12 +173,18 @@ def load_extensions(extensions: List[str]):
|
|
|
173
173
|
for extension in extensions:
|
|
174
174
|
try:
|
|
175
175
|
importlib.import_module(extension)
|
|
176
|
-
except
|
|
176
|
+
except ImportError as ex:
|
|
177
177
|
print(
|
|
178
|
-
f"-- error: module `{extension}`
|
|
178
|
+
f"-- error: loading module `{extension}` resulted in import error: {ex}",
|
|
179
|
+
file=sys.stderr,
|
|
180
|
+
)
|
|
181
|
+
except BaseException as ex:
|
|
182
|
+
print(
|
|
183
|
+
f"-- error: there was an error while loading module `{extension}`: {ex}",
|
|
179
184
|
file=sys.stderr,
|
|
180
185
|
)
|
|
181
186
|
|
|
187
|
+
|
|
182
188
|
class FlowConfig:
|
|
183
189
|
_cfg: dict
|
|
184
190
|
steps: list = []
|
|
@@ -253,6 +259,10 @@ class FlowConfig:
|
|
|
253
259
|
def postproc_exclude(self) -> List[dict]:
|
|
254
260
|
return self.postproc.get("exclude", [])
|
|
255
261
|
|
|
262
|
+
@property
|
|
263
|
+
def postproc_include(self) -> List[dict]:
|
|
264
|
+
return self.postproc.get("include", [])
|
|
265
|
+
|
|
256
266
|
@property
|
|
257
267
|
def shortcuts(self) -> Dict[str, dict]:
|
|
258
268
|
return self._cfg.get("shortcuts", {})
|
proj_flow/api/step.py
CHANGED
|
@@ -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(
|
|
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)
|
proj_flow/base/matrix.py
CHANGED
|
@@ -86,6 +86,29 @@ def matches(tested: dict, test: dict) -> bool:
|
|
|
86
86
|
return True
|
|
87
87
|
|
|
88
88
|
|
|
89
|
+
def partially_matches(tested: dict, test: dict) -> bool:
|
|
90
|
+
"""
|
|
91
|
+
Checks, if the tested dictionary contains some of the values from test
|
|
92
|
+
dictionary, with non-zero intersection between both dictionaries.
|
|
93
|
+
|
|
94
|
+
:param tested: Dictionary to check
|
|
95
|
+
:param test: Dictionary to check against
|
|
96
|
+
|
|
97
|
+
:returns: `True`, if all keys from `test` are in `tested` and have the same
|
|
98
|
+
values, `False` otherwise.
|
|
99
|
+
"""
|
|
100
|
+
|
|
101
|
+
intersection_size = 0
|
|
102
|
+
for key, value in test.items():
|
|
103
|
+
if key not in tested:
|
|
104
|
+
continue
|
|
105
|
+
val = tested.get(key)
|
|
106
|
+
if val != value:
|
|
107
|
+
return False
|
|
108
|
+
intersection_size += 1
|
|
109
|
+
return intersection_size > 0
|
|
110
|
+
|
|
111
|
+
|
|
89
112
|
def matches_any(tested: dict, tests: List[dict]):
|
|
90
113
|
"""
|
|
91
114
|
Checks, if the tested dictionary contains all the values from at least one
|
|
@@ -135,10 +135,14 @@ class Presets:
|
|
|
135
135
|
|
|
136
136
|
@staticmethod
|
|
137
137
|
def __load_file(filename: Path):
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
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
|
-
|
|
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):
|
proj_flow/ext/github/cli.py
CHANGED
|
@@ -32,6 +32,7 @@ def github():
|
|
|
32
32
|
|
|
33
33
|
@arg.command("github", "matrix")
|
|
34
34
|
def matrix(
|
|
35
|
+
pretty: typing.Annotated[bool, arg.FlagArgument(help="Indent JSON document")],
|
|
35
36
|
official: typing.Annotated[
|
|
36
37
|
bool, arg.FlagArgument(help="Cut matrix to release builds only")
|
|
37
38
|
],
|
|
@@ -60,6 +61,8 @@ def matrix(
|
|
|
60
61
|
print(f"matrix={var}", file=github_output)
|
|
61
62
|
else:
|
|
62
63
|
print(f"matrix={var}")
|
|
64
|
+
elif pretty:
|
|
65
|
+
json.dump(usable, sys.stdout, indent=2)
|
|
63
66
|
else:
|
|
64
67
|
json.dump(usable, sys.stdout)
|
|
65
68
|
|
proj_flow/ext/python/rtdocs.py
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
"""
|
|
5
5
|
The **proj_flow.ext.python.rtdocs** defines RTDocs step (`"RTD"`), which uses
|
|
6
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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
|
-
[
|
|
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
|
|
proj_flow/flow/configs.py
CHANGED
|
@@ -9,6 +9,7 @@ using ``-D`` switches.
|
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
import argparse
|
|
12
|
+
import copy
|
|
12
13
|
import datetime
|
|
13
14
|
import os
|
|
14
15
|
import sys
|
|
@@ -152,6 +153,19 @@ def _load_flow_data(rt: env.Runtime):
|
|
|
152
153
|
return configs, keys
|
|
153
154
|
|
|
154
155
|
|
|
156
|
+
def _apply_postproc_includes(config: dict, postproc_include: List[dict]):
|
|
157
|
+
clone = copy.deepcopy(config)
|
|
158
|
+
for ext in postproc_include:
|
|
159
|
+
if not matrix.partially_matches(config, ext):
|
|
160
|
+
continue
|
|
161
|
+
|
|
162
|
+
for key, value in ext.items():
|
|
163
|
+
if key in config:
|
|
164
|
+
continue
|
|
165
|
+
clone[key] = value
|
|
166
|
+
return clone
|
|
167
|
+
|
|
168
|
+
|
|
155
169
|
class Configs:
|
|
156
170
|
usable: List[env.Config] = []
|
|
157
171
|
|
|
@@ -186,8 +200,9 @@ class Configs:
|
|
|
186
200
|
)
|
|
187
201
|
|
|
188
202
|
postproc_exclude = rt.postproc_exclude
|
|
203
|
+
postproc_include = rt.postproc_include
|
|
189
204
|
usable = [
|
|
190
|
-
config
|
|
205
|
+
_apply_postproc_includes(config, postproc_include)
|
|
191
206
|
for config in turned
|
|
192
207
|
if len(postproc_exclude) == 0
|
|
193
208
|
or not matrix.matches_any(config, postproc_exclude)
|
proj_flow/minimal/list.py
CHANGED
|
@@ -6,12 +6,20 @@ The **proj_flow.minimal.list** implements ``./flow list`` command.
|
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
8
|
import os
|
|
9
|
-
|
|
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
|
-
|
|
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}:
|
|
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}:
|
|
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
|
-
|
|
113
|
-
|
|
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}:
|
|
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)
|
proj_flow/project/api.py
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: proj-flow
|
|
3
|
-
Version: 0.
|
|
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
|
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
proj_flow/__init__.py,sha256=
|
|
1
|
+
proj_flow/__init__.py,sha256=Ef26YQuXsAeNUbAaqbrbiJborj7G6r-Xkd-gLQdaSLQ,277
|
|
2
2
|
proj_flow/__main__.py,sha256=HUar_qQ9Ndmchmryegtzu__5wukwCLrFN_SGRl5Ol_M,233
|
|
3
3
|
proj_flow/dependency.py,sha256=CpcnR6El8AO9hlLc9lQtYQADYlkx3GMHlkLYbEAtdMI,4639
|
|
4
4
|
proj_flow/api/__init__.py,sha256=gV2f6kll_5JXtvkGASvnx7CbOWr34PHOdck-4ce-qEk,378
|
|
5
|
-
proj_flow/api/arg.py,sha256=
|
|
5
|
+
proj_flow/api/arg.py,sha256=0sVVEqdIOCqWmZtST_-u4rP6JkrResGJsKERQp3WYgc,5392
|
|
6
6
|
proj_flow/api/completers.py,sha256=NapNVu6QAQ_iF6dqcAzOV5kDHKD9MAMVX209Bklq-Mw,2464
|
|
7
7
|
proj_flow/api/ctx.py,sha256=IJu0q0Chivo6b2M4MKkAlV09oi7Cn9VxtDFeAeL_tnc,6646
|
|
8
|
-
proj_flow/api/env.py,sha256=
|
|
8
|
+
proj_flow/api/env.py,sha256=Tjgz73TPF6SotyxsZy1L7oid2FSnBQwJu8r1qDyC7WU,12994
|
|
9
9
|
proj_flow/api/init.py,sha256=p4ZDGfq6fw4bXbJu2iq0vEmVxbS7nALIhZfe-XnEs44,565
|
|
10
10
|
proj_flow/api/makefile.py,sha256=q0fBSsWTWfR5YwunwiRjWJKtiLeHdSKUgUTEgo5I7dE,3863
|
|
11
11
|
proj_flow/api/release.py,sha256=IM4axJ6dfyilCmpwL_Z8q43XGKsfHaPoMAdqSziwT7s,2810
|
|
12
|
-
proj_flow/api/step.py,sha256=
|
|
12
|
+
proj_flow/api/step.py,sha256=3yxWWCRqWB-2iro7oA_247xqykiMCrI4hKQV5uemJak,5205
|
|
13
13
|
proj_flow/base/__cmake_version__.py,sha256=imja0GnhpBvS8Crz-64eOUKhc4i6FeRrjBGRB68x_p0,239
|
|
14
14
|
proj_flow/base/__init__.py,sha256=V6IFRRtwxzvHuvtog6LIG9_6oivNpdcR5UmGobypvTo,930
|
|
15
15
|
proj_flow/base/cmd.py,sha256=XJk_r4Nlq_2XGgD_w92Us4WKwItmQAB8QWdT1pKxUFA,1746
|
|
16
16
|
proj_flow/base/inspect.py,sha256=lt5P19rvSZ-wMCTrCYAaQFCt2S9fUjEQXlrKK-Tmvwc,2786
|
|
17
|
-
proj_flow/base/matrix.py,sha256=
|
|
17
|
+
proj_flow/base/matrix.py,sha256=kH2BB6JRrLYdR71VJiJp58zfQSazwEOeiRXOPrayAcI,8446
|
|
18
18
|
proj_flow/base/name_list.py,sha256=KiHSnbDgYplJc25O3EehYhFAhD7Z3mHVAK6UYOdg5PQ,416
|
|
19
19
|
proj_flow/base/plugins.py,sha256=evn2Dym_NeoBaIZAu2YUtRd--15PCFpHD0h5zSsWkQE,978
|
|
20
20
|
proj_flow/base/registry.py,sha256=zbkB9KNfHnyPtzOurdvjwt714jrFpGHyOqeZL5sMvzI,3745
|
|
@@ -29,18 +29,18 @@ proj_flow/ext/store.py,sha256=zc9yh9M042V5OSLUZjWe9KazhdZ35h1JJsWvKughM0Y,3385
|
|
|
29
29
|
proj_flow/ext/cplusplus/__init__.py,sha256=dAmLMyGVQq586jJM_jiAuo5Ecw9U8agpvSRbzzPgh3g,245
|
|
30
30
|
proj_flow/ext/cplusplus/cmake/__init__.py,sha256=uQPclC2Bs5qVR_VnoYYPGUbzkzR2gU4RLThcTumYXUE,366
|
|
31
31
|
proj_flow/ext/cplusplus/cmake/parser.py,sha256=ZqQRZqS_VU5VtC8uwax-dknh7sfuLEvtazG8ChSqHDQ,3814
|
|
32
|
-
proj_flow/ext/cplusplus/cmake/presets.py,sha256=
|
|
32
|
+
proj_flow/ext/cplusplus/cmake/presets.py,sha256=hrAMgFj9TP8mguNsGgRKB4rDOMHIrC77sJKn2SzEAOM,5059
|
|
33
33
|
proj_flow/ext/cplusplus/cmake/project.py,sha256=Cp-5HwEsrQW4RjDThjMBQmaVJiRHo9QvYbw7IvjHKNQ,929
|
|
34
|
-
proj_flow/ext/cplusplus/cmake/steps.py,sha256=
|
|
35
|
-
proj_flow/ext/cplusplus/conan/__init__.py,sha256=
|
|
34
|
+
proj_flow/ext/cplusplus/cmake/steps.py,sha256=t4izW8CByc-kgzJEDoqGcKNh3c77e3GcwbsnCVSBkw4,4569
|
|
35
|
+
proj_flow/ext/cplusplus/conan/__init__.py,sha256=3PdwAeNthjg6rK4EaNDphMVVHvcG4Dx0vtYzSmBIgJY,1968
|
|
36
36
|
proj_flow/ext/cplusplus/conan/_conan.py,sha256=9xnji-f8uN7huXLqavVBUDC33CgnjBIyZX6wVcGm2RA,3352
|
|
37
37
|
proj_flow/ext/github/__init__.py,sha256=Mgx19YS6SYBXYB66_pOgIgwuB2WKRxqp5UGutq0B9Xk,282
|
|
38
|
-
proj_flow/ext/github/cli.py,sha256=
|
|
38
|
+
proj_flow/ext/github/cli.py,sha256=whK_VEUAG48tODyUYGfh3ZzZEa6vQgsNxY8yEfyDTzs,6441
|
|
39
39
|
proj_flow/ext/github/hosting.py,sha256=3iW8QjeJk7MyqKNbv92nB-5a_Yn_B5_eEIlw_cdgUT0,519
|
|
40
40
|
proj_flow/ext/github/publishing.py,sha256=5dUNFq47X_g9vo25R3lQRkSjV2IiAm2zkIhNe8gLDKs,1921
|
|
41
41
|
proj_flow/ext/github/switches.py,sha256=Y3pqJdiHYLoveCQtqZqELR84Phb2YF4u5y78TU7n2CQ,752
|
|
42
42
|
proj_flow/ext/python/__init__.py,sha256=GbEKEJJZ3PJ4sRHEykAWjGIR6yyyrYdlUFulldvsAGI,252
|
|
43
|
-
proj_flow/ext/python/rtdocs.py,sha256=
|
|
43
|
+
proj_flow/ext/python/rtdocs.py,sha256=tbWYKVg8BL2aGAjCDGPms-7EOth9PsB5B5E1N3tuCeE,7146
|
|
44
44
|
proj_flow/ext/python/steps.py,sha256=pDHGAe_CDzzdRFAzM1AIBvkbc14KB3SNUunusKZAaaY,1815
|
|
45
45
|
proj_flow/ext/python/version.py,sha256=pnyuKATyZwBh1p0gf9KmqbRSZx8hJ5285CiFK_tHEaY,3159
|
|
46
46
|
proj_flow/ext/sign/__init__.py,sha256=b9AN1_BalPtVy7YLBjvGhLamTujHEKcZP7npgDDDuSI,4296
|
|
@@ -73,7 +73,7 @@ proj_flow/ext/webidl/model/__init__.py,sha256=VJs_ODnF7-8DE0MbYKX-Bs-JDNqHgGdMkk
|
|
|
73
73
|
proj_flow/ext/webidl/model/ast.py,sha256=_CzJPAarYruonVbK6mxfUc7MgFoxFDpXWjX4OEkOp3M,19238
|
|
74
74
|
proj_flow/ext/webidl/model/builders.py,sha256=Ukjyhn4yJrSlU01P8VkLf0TE0kLqKlYw2KlyATceOpo,7665
|
|
75
75
|
proj_flow/flow/__init__.py,sha256=5Zo97zJsR7HMbl64jeMB9PbUuxCxpOlNuLmo3apWSVU,277
|
|
76
|
-
proj_flow/flow/configs.py,sha256=
|
|
76
|
+
proj_flow/flow/configs.py,sha256=zg32AXal2qbVOG6ToTfD05CTwRwt5rwF8yd-9UuB1nc,6999
|
|
77
77
|
proj_flow/flow/layer.py,sha256=IUANtCSOvlfzNSnq0VDdGdaXfB70Yr-rDGFxPDQTmpg,6187
|
|
78
78
|
proj_flow/flow/steps.py,sha256=PN_C_B6vNvqOsjpDpa5ESvH30Sc6RM1fSSqWqXgqg-4,2804
|
|
79
79
|
proj_flow/log/__init__.py,sha256=02EIgasE-K7mmbbNiIdX0IebWQMp2Co_D6H4ZBhJgcs,365
|
|
@@ -93,12 +93,12 @@ proj_flow/minimal/__init__.py,sha256=Yv32uwmS5a9SXSjaMVK0xKla9sWtcA8QkJHt15ffhiU
|
|
|
93
93
|
proj_flow/minimal/base.py,sha256=jFAiJICAD6izCBqsNgt7syZ_lynpC5goNuEsaQv1a44,1227
|
|
94
94
|
proj_flow/minimal/bootstrap.py,sha256=PcZfBsUmj8uDPGBC55iUgD5O7W4VSkpCQb6r9GEyAaQ,556
|
|
95
95
|
proj_flow/minimal/init.py,sha256=-ZNzhPFqAgZFAuN5hYOJFuFy_wHkPzjeSk90G2GUQfk,4365
|
|
96
|
-
proj_flow/minimal/list.py,sha256=
|
|
96
|
+
proj_flow/minimal/list.py,sha256=FIp49D0BW2UcOggibP_-5Ar1Ao_UmERMqHMDxNO7fRQ,8338
|
|
97
97
|
proj_flow/minimal/run.py,sha256=4qvGLqz2ayCZDvVBrq4tG094fjfcmDPon-xcGPQkM_U,4665
|
|
98
98
|
proj_flow/minimal/system.py,sha256=9FliH5TD103JYSAe2O5EU7hkOHDgVzTqu0Exxk-WrXE,1579
|
|
99
99
|
proj_flow/minimal/ext/bug_report.py,sha256=dKy2FzVanoF3LISN5fsoaj-0TatGvVnahKuhy9HE4os,2311
|
|
100
100
|
proj_flow/project/__init__.py,sha256=AROrwhbuMR5rJE-HC769eL4IXrMLQYpQb3HgpkOAYqg,293
|
|
101
|
-
proj_flow/project/api.py,sha256=
|
|
101
|
+
proj_flow/project/api.py,sha256=j0j3UBWi8vwGLIScSL7t2fWUr2-ezAilYkc1FM-EfYM,2103
|
|
102
102
|
proj_flow/project/data.py,sha256=TluhBDoJEYL4dnyTpInmhQ49Uvf8mkWmpU-YMLQPNhE,317
|
|
103
103
|
proj_flow/project/interact.py,sha256=t9brVfLC0HR3LUWs2RSBjMi7NgCBQc9_Ip1ut5oYVa4,9522
|
|
104
104
|
proj_flow/project/cplusplus/__init__.py,sha256=cBjTOL8unMiPBWx9QkY4-vahzlHXNVNAxdaUTtVBjZM,302
|
|
@@ -160,8 +160,8 @@ proj_flow/template/licenses/MIT.mustache,sha256=NncPoQaNsuy-WmRmboik3fyhJJ8m5pc2
|
|
|
160
160
|
proj_flow/template/licenses/Unlicense.mustache,sha256=awOCsWJ58m_2kBQwBUGWejVqZm6wuRtCL2hi9rfa0X4,1211
|
|
161
161
|
proj_flow/template/licenses/WTFPL.mustache,sha256=lvF4V_PrKKfZPa2TC8CZo8tlqaKvs3Bpv9G6XsWWQ4k,483
|
|
162
162
|
proj_flow/template/licenses/Zlib.mustache,sha256=uIj-mhSjes2HJ3rRapyy2ALflKRz4xQgS4mVM9827C0,868
|
|
163
|
-
proj_flow-0.
|
|
164
|
-
proj_flow-0.
|
|
165
|
-
proj_flow-0.
|
|
166
|
-
proj_flow-0.
|
|
167
|
-
proj_flow-0.
|
|
163
|
+
proj_flow-0.21.0.dist-info/METADATA,sha256=sTxFh9SPVTvanRQf1ccSU9Yo4_YbElioA_G5pI0YIW8,3472
|
|
164
|
+
proj_flow-0.21.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
165
|
+
proj_flow-0.21.0.dist-info/entry_points.txt,sha256=d_OmGKZzpY7FCWz0sZ4wnBAPZC75oMEzTgJZWtpDELo,49
|
|
166
|
+
proj_flow-0.21.0.dist-info/licenses/LICENSE,sha256=vpOQJ5QlrTedF3coEWvA4wJzVJH304f66ZitR7Od4iU,1068
|
|
167
|
+
proj_flow-0.21.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|