proj-flow 0.18.0__py3-none-any.whl → 0.19.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.
Files changed (29) hide show
  1. proj_flow/__init__.py +1 -1
  2. proj_flow/ext/webidl/__init__.py +12 -0
  3. proj_flow/ext/webidl/base/__init__.py +2 -0
  4. proj_flow/ext/webidl/base/config.py +425 -0
  5. proj_flow/ext/webidl/cli/__init__.py +10 -0
  6. proj_flow/ext/webidl/cli/cmake.py +82 -0
  7. proj_flow/ext/webidl/cli/depfile.py +83 -0
  8. proj_flow/ext/webidl/cli/gen.py +157 -0
  9. proj_flow/ext/webidl/cli/init.py +26 -0
  10. proj_flow/ext/webidl/cli/root.py +12 -0
  11. proj_flow/ext/webidl/cli/updater.py +20 -0
  12. proj_flow/ext/webidl/data/init/flow_webidl.cmake +26 -0
  13. proj_flow/ext/webidl/data/templates/cmake.mustache +45 -0
  14. proj_flow/ext/webidl/data/templates/depfile.mustache +6 -0
  15. proj_flow/ext/webidl/data/templates/partials/cxx/attribute-decl.mustache +1 -0
  16. proj_flow/ext/webidl/data/templates/partials/cxx/in-out.mustache +2 -0
  17. proj_flow/ext/webidl/data/templates/partials/cxx/includes.mustache +6 -0
  18. proj_flow/ext/webidl/data/templates/partials/cxx/operation-decl.mustache +12 -0
  19. proj_flow/ext/webidl/data/templates/partials/cxx/type.mustache +6 -0
  20. proj_flow/ext/webidl/data/types/cxx.json +47 -0
  21. proj_flow/ext/webidl/model/__init__.py +2 -0
  22. proj_flow/ext/webidl/model/ast.py +586 -0
  23. proj_flow/ext/webidl/model/builders.py +230 -0
  24. proj_flow/ext/webidl/registry.py +23 -0
  25. {proj_flow-0.18.0.dist-info → proj_flow-0.19.0.dist-info}/METADATA +2 -1
  26. {proj_flow-0.18.0.dist-info → proj_flow-0.19.0.dist-info}/RECORD +29 -6
  27. {proj_flow-0.18.0.dist-info → proj_flow-0.19.0.dist-info}/WHEEL +0 -0
  28. {proj_flow-0.18.0.dist-info → proj_flow-0.19.0.dist-info}/entry_points.txt +0 -0
  29. {proj_flow-0.18.0.dist-info → proj_flow-0.19.0.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,230 @@
1
+ # Copyright (c) 2026 Marcin Zdun
2
+ # This code is licensed under MIT license (see LICENSE for details)
3
+
4
+
5
+ import copy
6
+ import json
7
+ from dataclasses import dataclass, field
8
+ from pathlib import Path
9
+ from typing import Any, Callable, cast
10
+
11
+ from pywebidl2 import expr
12
+
13
+ package_root = Path(__file__).parent.parent
14
+
15
+ TR = list[str] | str | None
16
+
17
+
18
+ @dataclass
19
+ class TypeReplacement:
20
+ name: str
21
+ module_or_include: str | None = None
22
+
23
+ @staticmethod
24
+ def load_config(lang: str | None, types: Path | None):
25
+ data = {}
26
+ if lang:
27
+ path = package_root / "data" / "types" / f"{lang}.json"
28
+ with path.open(encoding="utf-8") as lang_file:
29
+ data.update(cast(dict, json.load(lang_file)))
30
+
31
+ if types:
32
+ with types.open(encoding="utf-8") as lang_file:
33
+ all_types_data = cast(dict[str, dict], json.load(lang_file))
34
+ if lang:
35
+ data.update(all_types_data.get(lang, {}))
36
+ else:
37
+ data.update(all_types_data.get("", {}))
38
+
39
+ result: dict[str, TypeReplacement] = {}
40
+ for key, value in data.items():
41
+ if value is None:
42
+ result[key] = TypeReplacement(name=key)
43
+
44
+ elif isinstance(value, str):
45
+ result[key] = TypeReplacement(name=value)
46
+
47
+ elif isinstance(value, list) and len(value) == 2:
48
+ mod, name = value
49
+ if isinstance(name, str) and (mod is None or isinstance(mod, str)):
50
+ result[key] = TypeReplacement(name=name, module_or_include=mod)
51
+
52
+ return result
53
+
54
+
55
+ def visit_flag_extended_attribute(
56
+ name: str, bag: dict[str, Any], attributes: dict[str, expr.ExtendedAttribute]
57
+ ):
58
+ bag[name] = attributes.get(name) != None
59
+
60
+
61
+ def visit_string_extended_attribute(
62
+ name: str, bag: dict[str, Any], attributes: dict[str, expr.ExtendedAttribute]
63
+ ):
64
+ bag[name] = None
65
+ try:
66
+ attr = attributes[name]
67
+ except KeyError:
68
+ return
69
+
70
+ if attr.rhs:
71
+ bag[name] = cast(str, attr.rhs.value)
72
+
73
+
74
+ def flag_extended_attribute(name: str):
75
+ def impl(bag: dict[str, Any], attributes: dict[str, expr.ExtendedAttribute]):
76
+ return visit_flag_extended_attribute(name, bag, attributes)
77
+
78
+ return impl
79
+
80
+
81
+ def string_extended_attribute(name: str):
82
+ def impl(bag: dict[str, Any], attributes: dict[str, expr.ExtendedAttribute]):
83
+ return visit_string_extended_attribute(name, bag, attributes)
84
+
85
+ return impl
86
+
87
+
88
+ ATTR_TYPE = {
89
+ "bool": flag_extended_attribute,
90
+ "str": string_extended_attribute,
91
+ }
92
+
93
+ ExtAttrsVisitor = Callable[[dict[str, Any], dict[str, expr.ExtendedAttribute]], None]
94
+
95
+
96
+ @dataclass
97
+ class ExtAttrsContextBuilder:
98
+ visitors: dict[str, ExtAttrsVisitor] = field(default_factory=dict)
99
+ applies_to_type: bool = False
100
+
101
+ def add_flag(self, name: str):
102
+ self.visitors[name] = flag_extended_attribute(name)
103
+
104
+ def add_string(self, name: str):
105
+ self.visitors[name] = string_extended_attribute(name)
106
+
107
+ def visit(self, bag: dict[str, Any], attributes: dict[str, expr.ExtendedAttribute]):
108
+ for visitor in self.visitors.values():
109
+ visitor(bag, attributes)
110
+
111
+ def merge(self, rhs: "ExtAttrsContextBuilder"):
112
+ left = copy.deepcopy(self.visitors)
113
+ right = copy.deepcopy(rhs.visitors)
114
+ left.update(right)
115
+ return ExtAttrsContextBuilder(
116
+ visitors=left,
117
+ applies_to_type=self.applies_to_type,
118
+ )
119
+
120
+
121
+ class BuilderBuilder:
122
+ tgt: ExtAttrsContextBuilder
123
+
124
+ def __init__(self, applies_to_type: bool = False):
125
+ self.tgt = ExtAttrsContextBuilder(applies_to_type=applies_to_type)
126
+
127
+ def flag(self, name: str):
128
+ self.tgt.add_flag(name)
129
+ return self
130
+
131
+ def string(self, name: str):
132
+ self.tgt.add_string(name)
133
+ return self
134
+
135
+ def build(self):
136
+ return self.tgt
137
+
138
+
139
+ @dataclass
140
+ class ExtAttrsContextBuilders:
141
+ enum: ExtAttrsContextBuilder = field(default_factory=ExtAttrsContextBuilder)
142
+ interface: ExtAttrsContextBuilder = field(default_factory=ExtAttrsContextBuilder)
143
+ attribute: ExtAttrsContextBuilder = field(default_factory=ExtAttrsContextBuilder)
144
+ operation: ExtAttrsContextBuilder = field(default_factory=ExtAttrsContextBuilder)
145
+ return_type: ExtAttrsContextBuilder = field(default_factory=ExtAttrsContextBuilder)
146
+ argument: ExtAttrsContextBuilder = field(default_factory=ExtAttrsContextBuilder)
147
+ type: ExtAttrsContextBuilder = field(default_factory=ExtAttrsContextBuilder)
148
+
149
+ def from_idl(
150
+ self,
151
+ selector: Callable[["ExtAttrsContextBuilders"], ExtAttrsContextBuilder],
152
+ ext_attrs: list[expr.ExtendedAttribute],
153
+ ):
154
+ result: dict[str, Any] = {}
155
+ attributes = {attr.name: attr for attr in ext_attrs}
156
+ builder = selector(self)
157
+ builder.visit(result, attributes)
158
+ if builder.applies_to_type:
159
+ self.type.visit(result, attributes)
160
+ return result
161
+
162
+ def merge(self, rhs: "ExtAttrsContextBuilders"):
163
+ return ExtAttrsContextBuilders(
164
+ enum=self.enum.merge(rhs.enum),
165
+ interface=self.interface.merge(rhs.interface),
166
+ attribute=self.attribute.merge(rhs.attribute),
167
+ operation=self.operation.merge(rhs.operation),
168
+ return_type=self.return_type.merge(rhs.return_type),
169
+ argument=self.argument.merge(rhs.argument),
170
+ type=self.type.merge(rhs.type),
171
+ )
172
+
173
+ @staticmethod
174
+ def from_config(data: dict):
175
+ ext_attrs = cast(dict[str, dict[str, str]], data.get("ext_attrs", {}))
176
+ result = ExtAttrsContextBuilders()
177
+ targets = [
178
+ ("enum", result.enum),
179
+ ("interface", result.interface),
180
+ ("attribute", result.attribute),
181
+ ("operation", result.operation),
182
+ ("return_type", result.return_type),
183
+ ("argument", result.argument),
184
+ ]
185
+ for key, target in targets:
186
+ group = ext_attrs.get(key, {})
187
+ for name, type_name in group.items():
188
+ ctor = ATTR_TYPE.get(type_name)
189
+ if not ctor:
190
+ message = f"unknown user-defined extended attribute `{type_name}' when reading {key}.{name}"
191
+ raise RuntimeError(message)
192
+ target.visitors[name] = ctor(name)
193
+ return result
194
+
195
+ def property_fixup(self, type: dict[str, Any], parent: dict[str, Any]):
196
+ for key in self.type.visitors:
197
+ if key in parent:
198
+ value = parent[key]
199
+ del parent[key]
200
+ if isinstance(value, bool):
201
+ type[key] = cast(bool, type.get(key, False)) or value
202
+ continue
203
+
204
+ if isinstance(value, str):
205
+ type[key] = cast(str, type.get(key, False)) or value
206
+ continue
207
+
208
+ @staticmethod
209
+ def builtin():
210
+ return ExtAttrsContextBuilders(
211
+ attribute=BuilderBuilder().string("default").build(),
212
+ operation=BuilderBuilder()
213
+ .flag("in")
214
+ .flag("out")
215
+ .flag("mutable")
216
+ .flag("throws")
217
+ .build(),
218
+ argument=BuilderBuilder()
219
+ .flag("defaulted")
220
+ .string("default")
221
+ .flag("in")
222
+ .flag("out")
223
+ .build(),
224
+ type=BuilderBuilder()
225
+ .flag("unique")
226
+ .flag("span")
227
+ .flag("nullable")
228
+ .string("key")
229
+ .build(),
230
+ )
@@ -0,0 +1,23 @@
1
+ # Copyright (c) 2026 Marcin Zdun
2
+ # This code is licensed under MIT license (see LICENSE for details)
3
+
4
+ from abc import ABC
5
+ from typing import Any
6
+
7
+ from pywebidl2 import expr
8
+
9
+ from proj_flow.base.registry import Registry
10
+ from proj_flow.ext.webidl.model.ast import MergedDefinitions
11
+
12
+
13
+ class WebIDLVisitor(ABC):
14
+ def on_definitions(self, definitions: MergedDefinitions): ...
15
+
16
+
17
+ class WebIDLCustomExtAttr(ABC):
18
+ def on_attribute(
19
+ self, name: str, ext_attrs: expr.ExtendedAttribute, result: dict[str, Any]
20
+ ): ...
21
+
22
+
23
+ webidl_visitors = Registry[WebIDLVisitor]("WebIDLVisitor")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: proj-flow
3
- Version: 0.18.0
3
+ Version: 0.19.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/
@@ -20,6 +20,7 @@ Requires-Python: >=3.10
20
20
  Requires-Dist: argcomplete
21
21
  Requires-Dist: chevron2021
22
22
  Requires-Dist: prompt-toolkit
23
+ Requires-Dist: pywebidl2
23
24
  Requires-Dist: pyyaml
24
25
  Requires-Dist: toml
25
26
  Description-Content-Type: text/markdown
@@ -1,4 +1,4 @@
1
- proj_flow/__init__.py,sha256=NKmPob4vpoR5qg9Iu-9Lgm4XUtGqoXzml3X0ANaL0IM,277
1
+ proj_flow/__init__.py,sha256=mcoLRnfbs2cN5EIdEz5liGKLp_d_SkFreWMn94VFFiU,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
@@ -46,6 +46,29 @@ proj_flow/ext/python/version.py,sha256=pnyuKATyZwBh1p0gf9KmqbRSZx8hJ5285CiFK_tHE
46
46
  proj_flow/ext/sign/__init__.py,sha256=b9AN1_BalPtVy7YLBjvGhLamTujHEKcZP7npgDDDuSI,4296
47
47
  proj_flow/ext/sign/api.py,sha256=l5SO5RHiHTwxg0aexkGOfApRdojWDcIBY_cfbKSKsC0,2286
48
48
  proj_flow/ext/sign/win32.py,sha256=yMAmO-DdIWZdOi_NxycRym8XM9WIsrWKtFANdIwthJ4,4968
49
+ proj_flow/ext/webidl/__init__.py,sha256=StPcfYM0l6Q3QNoXj5DfDpes6WwvhgfNnARQlhEoZco,316
50
+ proj_flow/ext/webidl/registry.py,sha256=x-UeflSrbUBMCH0nTSjpHisSnxZkQUNWfyXoSlDcavA,585
51
+ proj_flow/ext/webidl/base/__init__.py,sha256=VJs_ODnF7-8DE0MbYKX-Bs-JDNqHgGdMkk2w142bcYQ,101
52
+ proj_flow/ext/webidl/base/config.py,sha256=0r_E6NQldQJZXwL1FrU49WbIE6-y8T9O25mxv0UFgyU,13489
53
+ proj_flow/ext/webidl/cli/__init__.py,sha256=MBNjnuj5X4X-ich2zez3aQTqvEImFwN3nFJPm6SwhdI,402
54
+ proj_flow/ext/webidl/cli/cmake.py,sha256=ytK_eafS6lkH-6xv3LNGGCQ0TO0_hPtDiCQq4msqEP0,2446
55
+ proj_flow/ext/webidl/cli/depfile.py,sha256=XQdPDmxFSSRtm6uUNbX8lleTPXDWbGY-0UQn9jx6Tok,2442
56
+ proj_flow/ext/webidl/cli/gen.py,sha256=zwFVjxFudqADwSJHrjkmoFqSa5eE2-FT2fb_mqedtQM,5468
57
+ proj_flow/ext/webidl/cli/init.py,sha256=zYd1ElULZt_5nJEhvXAKQLQgRCQFSTk8RCKOHCLz1_U,841
58
+ proj_flow/ext/webidl/cli/root.py,sha256=wPznV0XU0UQ2dXrbfP7t5_6v4Uam1R3S0f0xESj_Zns,300
59
+ proj_flow/ext/webidl/cli/updater.py,sha256=usRfIsKkjN4x1FvYMna0EcdJuJha2lkBxQsCR7dF0NU,541
60
+ proj_flow/ext/webidl/data/init/flow_webidl.cmake,sha256=EBqToWUDex1HIcwFKyEo4AkGWORtRUGJd0Z2APIrcN8,876
61
+ proj_flow/ext/webidl/data/templates/cmake.mustache,sha256=tmi7AnnmosDmrPqgL52shkcRCIbs2Ze1fi9NZ8D9NpQ,1205
62
+ proj_flow/ext/webidl/data/templates/depfile.mustache,sha256=rdynmTyn1HhIZCZ9LYfnbkOCJNASeZHlKFfrU4BuaTY,108
63
+ proj_flow/ext/webidl/data/templates/partials/cxx/attribute-decl.mustache,sha256=lbH_9vRK9FuHSx25ScC9F3n11SEGHLwzkKaZpaijNnM,120
64
+ proj_flow/ext/webidl/data/templates/partials/cxx/in-out.mustache,sha256=92Zf2jVQ5LhYRCTt-zpQ9F_cPrrWCnBtIOczj8ZUxAs,120
65
+ proj_flow/ext/webidl/data/templates/partials/cxx/includes.mustache,sha256=FNQ6JRifRJQlpHdQX6NTpI_XTIvtNRLusVlimz18jl0,129
66
+ proj_flow/ext/webidl/data/templates/partials/cxx/operation-decl.mustache,sha256=-g46nh8AGfJwDDl3z0vSvsKmkz8-zbAZy8--jp4K_X4,588
67
+ proj_flow/ext/webidl/data/templates/partials/cxx/type.mustache,sha256=Oc6Dds-Waybwp_uch7Xk373I6VSdBClYfP5Pj4yRHBU,250
68
+ proj_flow/ext/webidl/data/types/cxx.json,sha256=f31q4U2hQIf4RwZylRK__MZroRQKbbQDjud2rwMf2eM,1545
69
+ proj_flow/ext/webidl/model/__init__.py,sha256=VJs_ODnF7-8DE0MbYKX-Bs-JDNqHgGdMkk2w142bcYQ,101
70
+ proj_flow/ext/webidl/model/ast.py,sha256=_CzJPAarYruonVbK6mxfUc7MgFoxFDpXWjX4OEkOp3M,19238
71
+ proj_flow/ext/webidl/model/builders.py,sha256=7MpSJm9NflY1rDbK8msWuKkq3X5jWzUEFCHytOZeKCY,7534
49
72
  proj_flow/flow/__init__.py,sha256=5Zo97zJsR7HMbl64jeMB9PbUuxCxpOlNuLmo3apWSVU,277
50
73
  proj_flow/flow/configs.py,sha256=PQZ5pLPmWwHJtSWmuy04bsnO-VvfWcJyP_UyKjiaG1g,6535
51
74
  proj_flow/flow/layer.py,sha256=IUANtCSOvlfzNSnq0VDdGdaXfB70Yr-rDGFxPDQTmpg,6187
@@ -134,8 +157,8 @@ proj_flow/template/licenses/MIT.mustache,sha256=NncPoQaNsuy-WmRmboik3fyhJJ8m5pc2
134
157
  proj_flow/template/licenses/Unlicense.mustache,sha256=awOCsWJ58m_2kBQwBUGWejVqZm6wuRtCL2hi9rfa0X4,1211
135
158
  proj_flow/template/licenses/WTFPL.mustache,sha256=lvF4V_PrKKfZPa2TC8CZo8tlqaKvs3Bpv9G6XsWWQ4k,483
136
159
  proj_flow/template/licenses/Zlib.mustache,sha256=uIj-mhSjes2HJ3rRapyy2ALflKRz4xQgS4mVM9827C0,868
137
- proj_flow-0.18.0.dist-info/METADATA,sha256=RtXLpv1l2n0-RHGb0o9QHJpG0TFYfo5htPhxYUYNTVE,2980
138
- proj_flow-0.18.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
139
- proj_flow-0.18.0.dist-info/entry_points.txt,sha256=d_OmGKZzpY7FCWz0sZ4wnBAPZC75oMEzTgJZWtpDELo,49
140
- proj_flow-0.18.0.dist-info/licenses/LICENSE,sha256=vpOQJ5QlrTedF3coEWvA4wJzVJH304f66ZitR7Od4iU,1068
141
- proj_flow-0.18.0.dist-info/RECORD,,
160
+ proj_flow-0.19.0.dist-info/METADATA,sha256=0SYn6uyzQ0xfGeduquoEvAK7eLVJ-OlUt1ITiNnwQHc,3005
161
+ proj_flow-0.19.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
162
+ proj_flow-0.19.0.dist-info/entry_points.txt,sha256=d_OmGKZzpY7FCWz0sZ4wnBAPZC75oMEzTgJZWtpDELo,49
163
+ proj_flow-0.19.0.dist-info/licenses/LICENSE,sha256=vpOQJ5QlrTedF3coEWvA4wJzVJH304f66ZitR7Od4iU,1068
164
+ proj_flow-0.19.0.dist-info/RECORD,,