proj-flow 0.15.3__py3-none-any.whl → 0.17.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/ext/cplusplus/cmake/__init__.py +2 -2
- proj_flow/ext/cplusplus/cmake/presets.py +160 -0
- proj_flow/ext/cplusplus/cmake/steps.py +9 -4
- proj_flow/minimal/ext/bug_report.py +2 -0
- {proj_flow-0.15.3.dist-info → proj_flow-0.17.0.dist-info}/METADATA +1 -1
- {proj_flow-0.15.3.dist-info → proj_flow-0.17.0.dist-info}/RECORD +10 -9
- {proj_flow-0.15.3.dist-info → proj_flow-0.17.0.dist-info}/WHEEL +0 -0
- {proj_flow-0.15.3.dist-info → proj_flow-0.17.0.dist-info}/entry_points.txt +0 -0
- {proj_flow-0.15.3.dist-info → proj_flow-0.17.0.dist-info}/licenses/LICENSE +0 -0
proj_flow/__init__.py
CHANGED
|
@@ -7,6 +7,6 @@ The **proj_flow.ext.cplusplus.cmake** provides ``"CMake"``, ``"Build"``,
|
|
|
7
7
|
context.
|
|
8
8
|
"""
|
|
9
9
|
|
|
10
|
-
from . import parser, project, steps
|
|
10
|
+
from . import parser, presets, project, steps
|
|
11
11
|
|
|
12
|
-
__all__ = ["parser", "project", "steps"]
|
|
12
|
+
__all__ = ["parser", "presets", "project", "steps"]
|
|
@@ -0,0 +1,160 @@
|
|
|
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.presets** check build directories for CMake step.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import json
|
|
9
|
+
import os
|
|
10
|
+
import platform
|
|
11
|
+
from dataclasses import dataclass
|
|
12
|
+
from enum import Enum
|
|
13
|
+
from pathlib import Path
|
|
14
|
+
from typing import cast
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class MacroType(Enum):
|
|
18
|
+
PRESET_NAME = 1
|
|
19
|
+
GENERATOR = 2
|
|
20
|
+
FILE_DIR = 3
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
CMAKE_SOURCE_DIR = Path(".").resolve()
|
|
24
|
+
CMAKE_HOST_SYSTEM_NAME = platform.uname().system
|
|
25
|
+
|
|
26
|
+
MACROS: dict[str, Path | str | MacroType] = {
|
|
27
|
+
"${sourceDir}": CMAKE_SOURCE_DIR,
|
|
28
|
+
"${sourceParentDir}": CMAKE_SOURCE_DIR.parent,
|
|
29
|
+
"${sourceDirName}": CMAKE_SOURCE_DIR.name,
|
|
30
|
+
"${presetName}": MacroType.PRESET_NAME,
|
|
31
|
+
"${generator}": MacroType.GENERATOR,
|
|
32
|
+
"${hostSystemName}": CMAKE_HOST_SYSTEM_NAME,
|
|
33
|
+
"${fileDir}": MacroType.FILE_DIR,
|
|
34
|
+
"${dollar}": "$",
|
|
35
|
+
"${pathListSep}": os.pathsep,
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
@dataclass
|
|
40
|
+
class Preset:
|
|
41
|
+
name: str
|
|
42
|
+
binary_dir: str | None
|
|
43
|
+
generator: str | None
|
|
44
|
+
inherits: list[str]
|
|
45
|
+
file_dir: Path
|
|
46
|
+
|
|
47
|
+
def expand(self):
|
|
48
|
+
if not self.binary_dir:
|
|
49
|
+
return None
|
|
50
|
+
chunks = self.binary_dir.split("${")
|
|
51
|
+
parts: list[str | Path | MacroType] = [chunks[0]]
|
|
52
|
+
for chunk in chunks[1:]:
|
|
53
|
+
var_suffix = chunk.split("}", 1)
|
|
54
|
+
if len(var_suffix) != 2:
|
|
55
|
+
return None
|
|
56
|
+
key = f"${{{var_suffix[0]}}}"
|
|
57
|
+
value = MACROS.get(key, "")
|
|
58
|
+
if isinstance(value, MacroType):
|
|
59
|
+
if value == MacroType.PRESET_NAME:
|
|
60
|
+
value = self.name
|
|
61
|
+
elif value == MacroType.GENERATOR:
|
|
62
|
+
value = self.generator or ""
|
|
63
|
+
elif value == MacroType.FILE_DIR:
|
|
64
|
+
value = self.file_dir
|
|
65
|
+
elif isinstance(value, Path):
|
|
66
|
+
if value.is_absolute():
|
|
67
|
+
parts = []
|
|
68
|
+
value = str(value)
|
|
69
|
+
parts.append(value)
|
|
70
|
+
parts.append(var_suffix[1])
|
|
71
|
+
|
|
72
|
+
return Path("".join(str(part) for part in parts))
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
class Presets:
|
|
76
|
+
def __init__(self):
|
|
77
|
+
self.seen = cast(set[Path], set())
|
|
78
|
+
self.result = cast(dict[str, Preset], {})
|
|
79
|
+
|
|
80
|
+
def visit_file(self, filename: Path):
|
|
81
|
+
dirname = self.__parent_from_file(filename)
|
|
82
|
+
if dirname is None:
|
|
83
|
+
return self.result
|
|
84
|
+
|
|
85
|
+
includes, presets = Presets.__load_file(filename)
|
|
86
|
+
self.__visit_includes(dirname, includes)
|
|
87
|
+
for preset in presets:
|
|
88
|
+
self.__visit_preset(dirname, preset)
|
|
89
|
+
for preset in self.result.values():
|
|
90
|
+
self.__merge_preset(preset)
|
|
91
|
+
|
|
92
|
+
return self.result
|
|
93
|
+
|
|
94
|
+
def __parent_from_file(self, filename: Path):
|
|
95
|
+
key = filename.resolve()
|
|
96
|
+
if key in self.seen:
|
|
97
|
+
return None
|
|
98
|
+
self.seen.add(key)
|
|
99
|
+
return key.parent
|
|
100
|
+
|
|
101
|
+
def __visit_includes(self, dirname: Path, includes: list[str]):
|
|
102
|
+
for include in includes:
|
|
103
|
+
self.visit_file(dirname / include)
|
|
104
|
+
|
|
105
|
+
def __visit_preset(self, dirname: Path, preset: dict):
|
|
106
|
+
name = cast(str | None, preset.get("name"))
|
|
107
|
+
if name is None:
|
|
108
|
+
return
|
|
109
|
+
binary_dir = cast(str | None, preset.get("binaryDir"))
|
|
110
|
+
generator = cast(str | None, preset.get("generator"))
|
|
111
|
+
inherits = cast(list[str], preset.get("inherits", []))
|
|
112
|
+
self.result[name] = Preset(
|
|
113
|
+
name=name,
|
|
114
|
+
binary_dir=binary_dir,
|
|
115
|
+
generator=generator,
|
|
116
|
+
inherits=inherits,
|
|
117
|
+
file_dir=dirname,
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
def __merge_preset(self, preset: Preset):
|
|
121
|
+
inherits: list[str] = []
|
|
122
|
+
inherits.extend(preset.inherits)
|
|
123
|
+
while inherits:
|
|
124
|
+
parent = inherits[0]
|
|
125
|
+
inherits = inherits[1:]
|
|
126
|
+
if parent not in self.result:
|
|
127
|
+
continue
|
|
128
|
+
parent_preset = self.result[parent]
|
|
129
|
+
inherits.extend(parent_preset.inherits)
|
|
130
|
+
|
|
131
|
+
if parent_preset.binary_dir and not preset.binary_dir:
|
|
132
|
+
preset.binary_dir = parent_preset.binary_dir
|
|
133
|
+
if parent_preset.generator and not preset.generator:
|
|
134
|
+
preset.generator = parent_preset.generator
|
|
135
|
+
|
|
136
|
+
@staticmethod
|
|
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", []))
|
|
142
|
+
|
|
143
|
+
return (includes, presets)
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
def get_binary_dirs():
|
|
147
|
+
presets = Presets().visit_file(Path("CMakePresets.json"))
|
|
148
|
+
|
|
149
|
+
cwd = str(Path.cwd().as_posix()) + "/"
|
|
150
|
+
result: dict[str, str] = {}
|
|
151
|
+
for preset in presets.values():
|
|
152
|
+
dirname = preset.expand()
|
|
153
|
+
if dirname is None:
|
|
154
|
+
continue
|
|
155
|
+
rel = str(dirname.as_posix())
|
|
156
|
+
if rel[: len(cwd)] == cwd:
|
|
157
|
+
rel = rel[len(cwd) :]
|
|
158
|
+
result[preset.name] = rel
|
|
159
|
+
|
|
160
|
+
return result
|
|
@@ -12,6 +12,7 @@ from typing import Dict, List, cast
|
|
|
12
12
|
from proj_flow import api
|
|
13
13
|
from proj_flow.api import env, step
|
|
14
14
|
from proj_flow.base.__cmake_version__ import CMAKE_VERSION
|
|
15
|
+
from proj_flow.ext.cplusplus.cmake.presets import get_binary_dirs
|
|
15
16
|
|
|
16
17
|
|
|
17
18
|
class CMakeBase(api.step.Step):
|
|
@@ -39,7 +40,7 @@ class CMakeBase(api.step.Step):
|
|
|
39
40
|
self._runs_after = runs_after
|
|
40
41
|
self._runs_before = runs_before
|
|
41
42
|
|
|
42
|
-
def is_active(self, config: api.env.Config, rt: api.env.Runtime) ->
|
|
43
|
+
def is_active(self, config: api.env.Config, rt: api.env.Runtime) -> bool:
|
|
43
44
|
return os.path.isfile("CMakeLists.txt") and os.path.isfile("CMakePresets.json")
|
|
44
45
|
|
|
45
46
|
def platform_dependencies(self):
|
|
@@ -55,12 +56,16 @@ class CMakeConfig(CMakeBase):
|
|
|
55
56
|
|
|
56
57
|
def __init__(self):
|
|
57
58
|
super().__init__(name="CMake")
|
|
59
|
+
self.binary_dirs = get_binary_dirs()
|
|
58
60
|
|
|
59
|
-
def is_active(self, config: env.Config, rt: env.Runtime) ->
|
|
61
|
+
def is_active(self, config: env.Config, rt: env.Runtime) -> bool:
|
|
60
62
|
return os.path.isfile("CMakeLists.txt") and os.path.isfile("CMakePresets.json")
|
|
61
63
|
|
|
62
64
|
def directories_to_remove(self, config: env.Config) -> List[str]:
|
|
63
|
-
|
|
65
|
+
binary_dir = self.binary_dirs.get(f"{config.preset}-{config.build_generator}")
|
|
66
|
+
if not binary_dir:
|
|
67
|
+
return []
|
|
68
|
+
return [binary_dir]
|
|
64
69
|
|
|
65
70
|
def run(self, config: env.Config, rt: env.Runtime) -> int:
|
|
66
71
|
cmake_vars = cast(Dict[str, str], rt._cfg.get("cmake", {}).get("vars", {}))
|
|
@@ -130,7 +135,7 @@ class PackStep(CMakeBase):
|
|
|
130
135
|
def platform_dependencies(self):
|
|
131
136
|
return self.dep_with_tool("cpack")
|
|
132
137
|
|
|
133
|
-
def is_active(self, config: env.Config, rt: env.Runtime) ->
|
|
138
|
+
def is_active(self, config: env.Config, rt: env.Runtime) -> bool:
|
|
134
139
|
return (
|
|
135
140
|
super().is_active(config, rt)
|
|
136
141
|
and len(config.items.get("cpack_generator", [])) > 0
|
|
@@ -25,6 +25,7 @@ def _version(ver: str) -> Tuple[int, int, int, str]:
|
|
|
25
25
|
raise SystemExit(1)
|
|
26
26
|
return (int(m.group(1)), int(m.group(2)), int(m.group(3)), ver)
|
|
27
27
|
|
|
28
|
+
|
|
28
29
|
def _prev_version(new_version: str, tags: List[str]):
|
|
29
30
|
current = _version(new_version)
|
|
30
31
|
versions = [_version(tag) for tag in reversed(tags)]
|
|
@@ -40,6 +41,7 @@ def _prev_version(new_version: str, tags: List[str]):
|
|
|
40
41
|
|
|
41
42
|
return None if index > len(versions) else versions[index][-1]
|
|
42
43
|
|
|
44
|
+
|
|
43
45
|
@release.version_updaters.add
|
|
44
46
|
class VersionUpdater(release.VersionUpdater):
|
|
45
47
|
def on_version_change_tags(self, new_version: str, tags: List[str]):
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: proj-flow
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.17.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/
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
proj_flow/__init__.py,sha256=
|
|
1
|
+
proj_flow/__init__.py,sha256=8ysEUwuBhRMglNTkf4IxkACkbKNu6vsWbx4CnMt7JT4,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
|
|
@@ -27,10 +27,11 @@ proj_flow/ext/markdown_changelog.py,sha256=fRGL09jojnv2B-8vAX2prvgNp8e7uyq5NxboS
|
|
|
27
27
|
proj_flow/ext/re_structured_changelog.py,sha256=UF23W9eu_YgPO42MiaoDbEKu8In_48mQg6rH9--mI30,459
|
|
28
28
|
proj_flow/ext/store.py,sha256=zc9yh9M042V5OSLUZjWe9KazhdZ35h1JJsWvKughM0Y,3385
|
|
29
29
|
proj_flow/ext/cplusplus/__init__.py,sha256=dAmLMyGVQq586jJM_jiAuo5Ecw9U8agpvSRbzzPgh3g,245
|
|
30
|
-
proj_flow/ext/cplusplus/cmake/__init__.py,sha256=
|
|
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=iYtSlkIoY3fEa6GL95zJugJbmleV5NPPB9UhME8RbSA,4922
|
|
32
33
|
proj_flow/ext/cplusplus/cmake/project.py,sha256=Cp-5HwEsrQW4RjDThjMBQmaVJiRHo9QvYbw7IvjHKNQ,929
|
|
33
|
-
proj_flow/ext/cplusplus/cmake/steps.py,sha256=
|
|
34
|
+
proj_flow/ext/cplusplus/cmake/steps.py,sha256=PQiDByCwz_AApxGRrEx_LnjCIgMh06nU8Pb2_z321Dk,4351
|
|
34
35
|
proj_flow/ext/cplusplus/conan/__init__.py,sha256=Fv839SWsKPWMZs9ox9T-bofZ4xDJXOI5UfWKQkm0Vtg,1924
|
|
35
36
|
proj_flow/ext/cplusplus/conan/_conan.py,sha256=9xnji-f8uN7huXLqavVBUDC33CgnjBIyZX6wVcGm2RA,3352
|
|
36
37
|
proj_flow/ext/github/__init__.py,sha256=Mgx19YS6SYBXYB66_pOgIgwuB2WKRxqp5UGutq0B9Xk,282
|
|
@@ -69,7 +70,7 @@ proj_flow/minimal/init.py,sha256=Rx3wu2xDZQpaiU0vmNmsj1eS48DopvL023lB7eTf85A,431
|
|
|
69
70
|
proj_flow/minimal/list.py,sha256=RlOqammE8olNKXsnbv1enF5uriu0MZ2wFbht37Z2ETw,4810
|
|
70
71
|
proj_flow/minimal/run.py,sha256=4qvGLqz2ayCZDvVBrq4tG094fjfcmDPon-xcGPQkM_U,4665
|
|
71
72
|
proj_flow/minimal/system.py,sha256=9FliH5TD103JYSAe2O5EU7hkOHDgVzTqu0Exxk-WrXE,1579
|
|
72
|
-
proj_flow/minimal/ext/bug_report.py,sha256=
|
|
73
|
+
proj_flow/minimal/ext/bug_report.py,sha256=dKy2FzVanoF3LISN5fsoaj-0TatGvVnahKuhy9HE4os,2311
|
|
73
74
|
proj_flow/project/__init__.py,sha256=AROrwhbuMR5rJE-HC769eL4IXrMLQYpQb3HgpkOAYqg,293
|
|
74
75
|
proj_flow/project/api.py,sha256=fu7gW0JuC7brwdsR4TadXYRqeMdt-lBUCEV4Sf0kMfY,1999
|
|
75
76
|
proj_flow/project/data.py,sha256=TluhBDoJEYL4dnyTpInmhQ49Uvf8mkWmpU-YMLQPNhE,317
|
|
@@ -133,8 +134,8 @@ proj_flow/template/licenses/MIT.mustache,sha256=NncPoQaNsuy-WmRmboik3fyhJJ8m5pc2
|
|
|
133
134
|
proj_flow/template/licenses/Unlicense.mustache,sha256=awOCsWJ58m_2kBQwBUGWejVqZm6wuRtCL2hi9rfa0X4,1211
|
|
134
135
|
proj_flow/template/licenses/WTFPL.mustache,sha256=lvF4V_PrKKfZPa2TC8CZo8tlqaKvs3Bpv9G6XsWWQ4k,483
|
|
135
136
|
proj_flow/template/licenses/Zlib.mustache,sha256=uIj-mhSjes2HJ3rRapyy2ALflKRz4xQgS4mVM9827C0,868
|
|
136
|
-
proj_flow-0.
|
|
137
|
-
proj_flow-0.
|
|
138
|
-
proj_flow-0.
|
|
139
|
-
proj_flow-0.
|
|
140
|
-
proj_flow-0.
|
|
137
|
+
proj_flow-0.17.0.dist-info/METADATA,sha256=9WNbInHfvYfv8k7LLWI51yyMfds-2Cvn4UfURnmoWcI,2980
|
|
138
|
+
proj_flow-0.17.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
139
|
+
proj_flow-0.17.0.dist-info/entry_points.txt,sha256=d_OmGKZzpY7FCWz0sZ4wnBAPZC75oMEzTgJZWtpDELo,49
|
|
140
|
+
proj_flow-0.17.0.dist-info/licenses/LICENSE,sha256=vpOQJ5QlrTedF3coEWvA4wJzVJH304f66ZitR7Od4iU,1068
|
|
141
|
+
proj_flow-0.17.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|