msra-codegen 0.1.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 (68) hide show
  1. msra_codegen/README.md +23 -0
  2. msra_codegen/__init__.py +6 -0
  3. msra_codegen/__main__.py +5 -0
  4. msra_codegen/bridge.py +29 -0
  5. msra_codegen/cli.py +105 -0
  6. msra_codegen/codegen_context.py +1690 -0
  7. msra_codegen/config.toml +164 -0
  8. msra_codegen/core_naming.py +155 -0
  9. msra_codegen/docs_generator.py +346 -0
  10. msra_codegen/file_utils.py +8 -0
  11. msra_codegen/funcresult.py +156 -0
  12. msra_codegen/generator.py +6 -0
  13. msra_codegen/generator_config.py +35 -0
  14. msra_codegen/github_workflows.py +129 -0
  15. msra_codegen/gitignore.py +31 -0
  16. msra_codegen/issue_templates.py +100 -0
  17. msra_codegen/logo_assets.py +99 -0
  18. msra_codegen/msra_serializer.py +205 -0
  19. msra_codegen/node_export.js +296 -0
  20. msra_codegen/package_metadata.py +306 -0
  21. msra_codegen/package_writer.py +175 -0
  22. msra_codegen/project_model.py +490 -0
  23. msra_codegen/python_formatting.py +88 -0
  24. msra_codegen/python_render.py +242 -0
  25. msra_codegen/readme_pipeline.py +519 -0
  26. msra_codegen/requirements.txt +5 -0
  27. msra_codegen/template_engine.py +26 -0
  28. msra_codegen/templates/Makefile.tpl +44 -0
  29. msra_codegen/templates/README.md.tpl +55 -0
  30. msra_codegen/templates/abstraction/__init__.py.tpl +188 -0
  31. msra_codegen/templates/abstraction/regexes.py.tpl +25 -0
  32. msra_codegen/templates/docs/requirements.txt.tpl +3 -0
  33. msra_codegen/templates/docs/source/Makefile.tpl +20 -0
  34. msra_codegen/templates/docs/source/api.rst.tpl +9 -0
  35. msra_codegen/templates/docs/source/conf.py.tpl +88 -0
  36. msra_codegen/templates/docs/source/index.rst.tpl +14 -0
  37. msra_codegen/templates/docs/source/module.rst.tpl +34 -0
  38. msra_codegen/templates/docs/source/quick_start.rst.tpl +19 -0
  39. msra_codegen/templates/endpoints_init.py.tpl +15 -0
  40. msra_codegen/templates/example.py.tpl +1 -0
  41. msra_codegen/templates/function.py.tpl +364 -0
  42. msra_codegen/templates/github/issue_templates/bug_report.yml.tpl +55 -0
  43. msra_codegen/templates/github/issue_templates/config.yml.tpl +8 -0
  44. msra_codegen/templates/github/issue_templates/documentation_issue.yml.tpl +33 -0
  45. msra_codegen/templates/github/issue_templates/feature_request.yml.tpl +36 -0
  46. msra_codegen/templates/github/workflows/publish.yml.tpl +100 -0
  47. msra_codegen/templates/github/workflows/source-sync.yml.tpl +177 -0
  48. msra_codegen/templates/github/workflows/tests.yml.tpl +69 -0
  49. msra_codegen/templates/gitignore.tpl +3 -0
  50. msra_codegen/templates/group.py.tpl +56 -0
  51. msra_codegen/templates/group_init.py.tpl +14 -0
  52. msra_codegen/templates/init.py.tpl +4 -0
  53. msra_codegen/templates/licenses/GPL-3.0-or-later.txt.tpl +674 -0
  54. msra_codegen/templates/licenses/MIT.txt.tpl +21 -0
  55. msra_codegen/templates/manager.py.tpl +257 -0
  56. msra_codegen/templates/pyproject.toml.tpl +38 -0
  57. msra_codegen/templates/tests/api_test.py.tpl +49 -0
  58. msra_codegen/templates/tests/conftest.py.tpl +21 -0
  59. msra_codegen/templates/variable.py.tpl +54 -0
  60. msra_codegen/tests_generator.py +988 -0
  61. msra_codegen/typespec.py +275 -0
  62. msra_codegen/validation.py +118 -0
  63. msra_codegen-0.1.0.dist-info/METADATA +47 -0
  64. msra_codegen-0.1.0.dist-info/RECORD +68 -0
  65. msra_codegen-0.1.0.dist-info/WHEEL +5 -0
  66. msra_codegen-0.1.0.dist-info/entry_points.txt +2 -0
  67. msra_codegen-0.1.0.dist-info/licenses/LICENSE +674 -0
  68. msra_codegen-0.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,275 @@
1
+ from __future__ import annotations
2
+
3
+ import re
4
+ from typing import Any
5
+
6
+ from .python_render import get_plain_value, regex_class_name, render_expr, render_simple_value
7
+
8
+
9
+ def should_render_setter(variable: dict[str, Any]) -> bool:
10
+ if variable["name"] == "token":
11
+ return False
12
+ return not bool(variable.get("read_only", False))
13
+
14
+
15
+ def variable_type_names(variable: dict[str, Any]) -> set[str]:
16
+ types = variable.get("types")
17
+ if isinstance(types, dict):
18
+ kind = types.get("kind")
19
+ if kind == "array":
20
+ result = set()
21
+ for item in types.get("items", []):
22
+ if isinstance(item, dict) and item.get("kind") == "inline_table":
23
+ item_dict = inline_table_to_dict(item)
24
+ type_name = item_dict.get("type")
25
+ if type_name:
26
+ result.add(str(type_name))
27
+ return result
28
+ if kind == "inline_table":
29
+ item_dict = inline_table_to_dict(types)
30
+ type_name = item_dict.get("type")
31
+ return {str(type_name)} if type_name else set()
32
+ type_name = types.get("type")
33
+ return {str(type_name)} if type_name else set()
34
+ if isinstance(types, list):
35
+ result = set()
36
+ for item in types:
37
+ if isinstance(item, dict):
38
+ type_name = item.get("type")
39
+ if type_name:
40
+ result.add(str(type_name))
41
+ return result
42
+ if isinstance(types, str):
43
+ return {types}
44
+ return set()
45
+
46
+
47
+ def extract_variable_match(types_expr: dict[str, Any] | None) -> dict[str, Any] | None:
48
+ if not isinstance(types_expr, dict) or types_expr.get("kind") != "array":
49
+ return None
50
+ for item in types_expr.get("items", []):
51
+ if not isinstance(item, dict) or item.get("kind") != "inline_table":
52
+ continue
53
+ for inline_item in item.get("items", []):
54
+ if inline_item.get("key") == "match":
55
+ return inline_item.get("value")
56
+ return None
57
+
58
+
59
+ def type_annotation_from_types(type_names: set[str], *, nullable: bool = False) -> str:
60
+ if not type_names:
61
+ return "Any | None" if nullable else "Any"
62
+ non_null = {name for name in type_names if name != "null"}
63
+ base = {
64
+ "string": "str",
65
+ "integer": "int",
66
+ "boolean": "bool",
67
+ "number": "float",
68
+ "array": "list[Any]",
69
+ "object": "dict[str, Any]",
70
+ }
71
+ if not non_null:
72
+ return "Any | None"
73
+ annotation = base.get(next(iter(non_null)), "Any")
74
+ if nullable or "null" in type_names:
75
+ return f"{annotation} | None"
76
+ return annotation
77
+
78
+
79
+ def type_annotation_from_expr(expr: dict[str, Any] | None) -> str:
80
+ if is_list_type_expr(expr):
81
+ item_expr = list_item_type_expr(expr)
82
+ return f"list[{type_annotation_from_expr(item_expr)}]"
83
+ if is_abstraction_reference_expr(expr):
84
+ return "Any"
85
+ type_names = type_names_from_expr(expr)
86
+ return type_annotation_from_types(type_names)
87
+
88
+
89
+ def primary_type_name(type_names: set[str]) -> str | None:
90
+ for candidate in ("integer", "number", "boolean", "string", "array", "object", "null"):
91
+ if candidate in type_names:
92
+ return candidate
93
+ return None
94
+
95
+
96
+ def inline_array_to_list(expr: dict[str, Any] | None) -> list[dict[str, Any]]:
97
+ if not expr or expr.get("kind") != "array":
98
+ return []
99
+ result: list[dict[str, Any]] = []
100
+ for item in expr.get("items", []):
101
+ if item and item.get("kind") == "inline_table":
102
+ result.append(inline_table_to_dict(item))
103
+ return result
104
+
105
+
106
+ def inline_table_to_dict(expr: dict[str, Any]) -> dict[str, Any]:
107
+ result: dict[str, Any] = {"kind": expr.get("kind")}
108
+ for item in expr.get("items", []):
109
+ result[item["key"]] = get_plain_value(item["value"])
110
+ return result
111
+
112
+
113
+ def escape_docstring(text: str) -> str:
114
+ return text.replace('"""', '\\"\\"\\"')
115
+
116
+
117
+ def variable_match_pattern(variable: dict[str, Any]) -> str | None:
118
+ match = variable.get("match")
119
+ return match_to_pattern(match)
120
+
121
+
122
+ def match_to_values(expr: dict[str, Any] | None) -> list[Any] | None:
123
+ if not expr or expr.get("kind") != "array":
124
+ return None
125
+ values: list[Any] = []
126
+ for item in expr.get("items", []):
127
+ value, ok = scalar_value_from_expr(item)
128
+ if not ok:
129
+ return None
130
+ values.append(value)
131
+ return values
132
+
133
+
134
+ def match_to_pattern(expr: dict[str, Any] | None) -> str | None:
135
+ if not expr:
136
+ return None
137
+ if expr.get("kind") == "string":
138
+ return render_simple_value(expr.get("value"))
139
+ if expr.get("kind") == "ref":
140
+ parts = [part["value"] for part in expr.get("parts", []) if part.get("kind") == "name"]
141
+ if len(parts) >= 3 and parts[0] == "DOCUMENT" and parts[1] == "REGEXES":
142
+ return f"abstraction.{regex_class_name(parts[2])}.REGEX"
143
+ return None
144
+
145
+
146
+ def match_to_error(expr: dict[str, Any] | None) -> str | None:
147
+ if not expr or expr.get("kind") != "ref":
148
+ return None
149
+ parts = [part["value"] for part in expr.get("parts", []) if part.get("kind") == "name"]
150
+ if len(parts) >= 3 and parts[0] == "DOCUMENT" and parts[1] == "REGEXES":
151
+ return f"abstraction.{regex_class_name(parts[2])}.ERROR"
152
+ return None
153
+
154
+
155
+ def match_to_check_expr(expr: dict[str, Any] | None, value_expr: str) -> str | None:
156
+ if not expr:
157
+ return None
158
+ if expr.get("kind") == "string":
159
+ pattern = render_simple_value(expr.get("value"))
160
+ return f"re.fullmatch({pattern}, str({value_expr})) is not None"
161
+ if expr.get("kind") != "ref":
162
+ return None
163
+ parts = [part["value"] for part in expr.get("parts", []) if part.get("kind") == "name"]
164
+ if len(parts) >= 3 and parts[0] == "DOCUMENT" and parts[1] == "REGEXES":
165
+ return f"abstraction.{regex_class_name(parts[2])}.match({value_expr})"
166
+ return None
167
+
168
+
169
+ def match_to_range(expr: dict[str, Any] | None) -> tuple[int | float | None, int | float | None] | None:
170
+ if not expr or expr.get("kind") != "inline_table":
171
+ return None
172
+ values = inline_table_to_dict(expr)
173
+ has_lower = "from" in values
174
+ has_upper = "to" in values
175
+ if not has_lower and not has_upper:
176
+ return None
177
+ lower = values.get("from")
178
+ upper = values.get("to")
179
+ if has_lower and (isinstance(lower, bool) or not isinstance(lower, (int, float))):
180
+ return None
181
+ if has_upper and (isinstance(upper, bool) or not isinstance(upper, (int, float))):
182
+ return None
183
+ return (lower if has_lower else None, upper if has_upper else None)
184
+
185
+
186
+ def scalar_value_from_expr(expr: dict[str, Any] | None) -> tuple[Any, bool]:
187
+ if not isinstance(expr, dict):
188
+ return None, False
189
+ kind = expr.get("kind")
190
+ if kind == "string":
191
+ return expr.get("value"), True
192
+ if kind == "number":
193
+ return expr.get("value"), True
194
+ if kind == "bool":
195
+ return bool(expr.get("value")), True
196
+ if kind == "null":
197
+ return None, True
198
+ return None, False
199
+
200
+
201
+ def normalize_name(text: str) -> str:
202
+ return re.sub(r"[^a-z0-9]+", "", text.lower())
203
+
204
+
205
+ def type_names_from_expr(expr: dict[str, Any] | None) -> set[str]:
206
+ if is_list_type_expr(expr):
207
+ item_expr = list_item_type_expr(expr)
208
+ return type_names_from_expr(item_expr)
209
+ plain = get_plain_value(expr)
210
+ if isinstance(plain, str):
211
+ return {plain}
212
+ if isinstance(plain, list):
213
+ result = set()
214
+ for item in plain:
215
+ if isinstance(item, dict) and item.get("type"):
216
+ result.add(str(item["type"]))
217
+ return result
218
+ if isinstance(plain, dict) and plain.get("type"):
219
+ return {str(plain["type"])}
220
+ return set()
221
+
222
+
223
+ def is_list_type_expr(expr: dict[str, Any] | None) -> bool:
224
+ if not isinstance(expr, dict) or expr.get("kind") != "sequence":
225
+ return False
226
+ items = expr.get("items", [])
227
+ if len(items) != 2:
228
+ return False
229
+ if get_plain_value(items[0]) != "list":
230
+ return False
231
+ return isinstance(items[1], dict) and items[1].get("kind") == "array"
232
+
233
+
234
+ def list_item_type_expr(expr: dict[str, Any] | None) -> dict[str, Any] | None:
235
+ if not is_list_type_expr(expr):
236
+ return None
237
+ items = expr.get("items", [])
238
+ if len(items) != 2:
239
+ return None
240
+ inner = items[1]
241
+ if not isinstance(inner, dict):
242
+ return None
243
+ inner_items = inner.get("items", [])
244
+ if not inner_items:
245
+ return None
246
+ first = inner_items[0]
247
+ return first if isinstance(first, dict) else None
248
+
249
+
250
+ def ref_input_name(expr: dict[str, Any] | None) -> str | None:
251
+ if not isinstance(expr, dict) or expr.get("kind") != "ref":
252
+ return None
253
+ parts = [part["value"] for part in expr.get("parts", []) if part.get("kind") == "name"]
254
+ if len(parts) >= 2 and parts[0] == "INPUT":
255
+ return parts[1]
256
+ return None
257
+
258
+
259
+ def is_abstraction_reference_expr(expr: dict[str, Any] | None) -> bool:
260
+ if not isinstance(expr, dict) or expr.get("kind") != "ref":
261
+ return False
262
+ parts = [part["value"] for part in expr.get("parts", []) if part.get("kind") == "name"]
263
+ return len(parts) >= 2 and parts[0] == "ABSTRACTIONS"
264
+
265
+
266
+ def selectable_values_from_plain_values(values: Any) -> list[Any]:
267
+ if not isinstance(values, list):
268
+ return []
269
+ if all(not isinstance(item, dict) for item in values):
270
+ return list(values)
271
+ return [
272
+ item["value"]
273
+ for item in values
274
+ if isinstance(item, dict) and item.get("value") is not None
275
+ ]
@@ -0,0 +1,118 @@
1
+ from __future__ import annotations
2
+
3
+ import subprocess
4
+ import sys
5
+ from pathlib import Path
6
+ from typing import Any
7
+
8
+ import tomllib
9
+
10
+ from .generator_config import config_section
11
+
12
+
13
+ def validate_generated_project(output_root: Path) -> None:
14
+ output_root = output_root.resolve()
15
+ package_name = read_generated_package_name(output_root)
16
+ validation_config = config_section("validation")
17
+ checks = validation_config.get("checks", [])
18
+ if not isinstance(checks, list) or not checks:
19
+ raise RuntimeError("msra_codegen/config.toml must define validation.checks.")
20
+
21
+ context = {
22
+ "output_root": str(output_root),
23
+ "package_name": package_name,
24
+ "python_executable": sys.executable,
25
+ }
26
+ for raw_check in checks:
27
+ check = normalize_check(raw_check)
28
+ run_validation_check(output_root, check, context)
29
+
30
+
31
+ def read_generated_package_name(output_root: Path) -> str:
32
+ pyproject_path = output_root / "pyproject.toml"
33
+ if not pyproject_path.exists():
34
+ raise FileNotFoundError(pyproject_path)
35
+
36
+ with pyproject_path.open("rb") as handle:
37
+ pyproject = tomllib.load(handle)
38
+ if not isinstance(pyproject, dict):
39
+ raise RuntimeError(f"Unexpected TOML structure in {pyproject_path}.")
40
+
41
+ project = pyproject.get("project")
42
+ if not isinstance(project, dict):
43
+ raise RuntimeError(f"Missing [project] table in {pyproject_path}.")
44
+
45
+ package_name = str(project.get("name", "")).strip()
46
+ if not package_name:
47
+ raise RuntimeError(f"Missing project.name in {pyproject_path}.")
48
+ return package_name
49
+
50
+
51
+ def normalize_check(raw_check: Any) -> dict[str, list[str] | str]:
52
+ if not isinstance(raw_check, dict):
53
+ raise RuntimeError("validation.checks entries must be tables.")
54
+
55
+ name = str(raw_check.get("name", "")).strip()
56
+ if not name:
57
+ raise RuntimeError("validation.checks entries must define a non-empty name.")
58
+
59
+ argv = raw_check.get("argv", [])
60
+ if not isinstance(argv, list) or not argv:
61
+ raise RuntimeError(f"validation.checks.{name}.argv must be a non-empty list.")
62
+
63
+ targets = raw_check.get("targets", [])
64
+ if not isinstance(targets, list):
65
+ raise RuntimeError(f"validation.checks.{name}.targets must be a list.")
66
+
67
+ return {
68
+ "name": name,
69
+ "argv": [str(part) for part in argv],
70
+ "targets": [str(target) for target in targets],
71
+ }
72
+
73
+
74
+ def run_validation_check(
75
+ output_root: Path,
76
+ check: dict[str, list[str] | str],
77
+ context: dict[str, str],
78
+ ) -> None:
79
+ name = str(check["name"])
80
+ argv = [expand_placeholder(part, context) for part in check["argv"]]
81
+ targets = [resolve_validation_target(target, output_root, context) for target in check["targets"]]
82
+ command = [*argv, *targets]
83
+ process = subprocess.run(
84
+ command,
85
+ cwd=output_root,
86
+ capture_output=True,
87
+ text=True,
88
+ encoding="utf-8",
89
+ errors="replace",
90
+ check=False,
91
+ )
92
+ if process.returncode == 0:
93
+ return
94
+
95
+ stderr = process.stderr.strip()
96
+ stdout = process.stdout.strip()
97
+ details = stderr or stdout or "validation command failed without output"
98
+ raise RuntimeError(
99
+ f"Validation check {name!r} failed with exit code {process.returncode}.\n"
100
+ f"Command: {' '.join(command)}\n"
101
+ f"{details}"
102
+ )
103
+
104
+
105
+ def resolve_validation_target(target: str, output_root: Path, context: dict[str, str]) -> str:
106
+ rendered = expand_placeholder(target, context)
107
+ rendered_path = Path(rendered)
108
+ if rendered_path.is_absolute():
109
+ return str(rendered_path)
110
+ return rendered
111
+
112
+
113
+ def expand_placeholder(value: str, context: dict[str, str]) -> str:
114
+ try:
115
+ return value.format(**context)
116
+ except KeyError as exc:
117
+ missing_key = exc.args[0]
118
+ raise RuntimeError(f"Unknown validation placeholder {{{missing_key}}} in {value!r}.") from exc
@@ -0,0 +1,47 @@
1
+ Metadata-Version: 2.4
2
+ Name: msra-codegen
3
+ Version: 0.1.0
4
+ Summary: MSRA to async Python client generator
5
+ License-Expression: GPL-3.0-or-later
6
+ Project-URL: Homepage, https://github.com/Open-Inflation/engine-reverse-ide
7
+ Project-URL: Repository, https://github.com/Open-Inflation/engine-reverse-ide
8
+ Project-URL: Issues, https://github.com/Open-Inflation/engine-reverse-ide/issues
9
+ Keywords: msra,codegen,generator,python,api
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: 3.11
12
+ Classifier: Programming Language :: Python :: 3.12
13
+ Classifier: Topic :: Software Development :: Code Generators
14
+ Classifier: Topic :: Software Development :: Libraries
15
+ Requires-Python: >=3.11
16
+ Description-Content-Type: text/markdown
17
+ License-File: LICENSE
18
+ Requires-Dist: jinja2>=3.1
19
+ Requires-Dist: packaging>=24.0
20
+ Requires-Dist: Pillow>=10.0
21
+ Requires-Dist: ruff>=0.6
22
+ Requires-Dist: mypy>=1.11
23
+ Dynamic: license-file
24
+
25
+ # msra-codegen
26
+
27
+ MSRA to async Python client generator.
28
+
29
+ ## Install
30
+
31
+ ```powershell
32
+ pip install msra-codegen
33
+ ```
34
+
35
+ ## Usage
36
+
37
+ ```powershell
38
+ msra-codegen generate .\examples\example\example.msra -o .\generated
39
+ msra-codegen validate .\generated
40
+ ```
41
+
42
+ The module entrypoint stays available as well:
43
+
44
+ ```powershell
45
+ python -m msra_codegen generate .\examples\example\example.msra -o .\generated
46
+ python -m msra_codegen validate .\generated
47
+ ```
@@ -0,0 +1,68 @@
1
+ msra_codegen/README.md,sha256=QZ7cgcMzZdmVH01Cor_1l_XaSmzMQ-zieLEL3ncuG8I,433
2
+ msra_codegen/__init__.py,sha256=TgrFRwIE1SARuKmA8-zwUPCrRPZRmVs0wDXDUaUl_2M,145
3
+ msra_codegen/__main__.py,sha256=PSQ4rpL0dG6f-qH4N7H-gD9igQkdHzH4yVZDcW8lfZo,80
4
+ msra_codegen/bridge.py,sha256=8tPvo1dFSBk4JvxTxO6jHNXTq7niEbHXOGarNoG7KMA,787
5
+ msra_codegen/cli.py,sha256=L2FbDrlf1n0FlnNN7OoQpCVVeMcyTkKn6sBa6sFO1FY,3414
6
+ msra_codegen/codegen_context.py,sha256=VpwV539GFoP17qxiPPyTxXpiCpCSAbbm9RqRndjdVpU,81135
7
+ msra_codegen/config.toml,sha256=_QifB5o0nUPqAykEQnM3TGyCd-UxaWbwx7WYISAit5k,4416
8
+ msra_codegen/core_naming.py,sha256=r3w4eMhrGibaeRZjXcuqXGdcF3a1S_yeXF4RywhgtMM,4880
9
+ msra_codegen/docs_generator.py,sha256=oA70yOXXjmaDGL6nJEccq_J9BE7te2pcCpsgjtDG4mA,12983
10
+ msra_codegen/file_utils.py,sha256=rOdyQodNfFZgv7wjyO-pxAp5lhHd1A3Tn86VmzTJp9M,211
11
+ msra_codegen/funcresult.py,sha256=cG9YZfja-o4PbT8B5KJTW9bjQgHxfZ6lxUvt8BujYko,5964
12
+ msra_codegen/generator.py,sha256=KOrDZKxG3SBs1_W0wTw-RUpWwFKnYSIMBnJQwQm8Y_4,171
13
+ msra_codegen/generator_config.py,sha256=1e4-VGn9ZlK4Fxd5hkKYRjHGBZ_eDczp27oNTW6pAWI,928
14
+ msra_codegen/github_workflows.py,sha256=PhoBiG8AlAMe9S2Ic4wDNMJDxZi7rYDxQwhUTRXpgL4,6860
15
+ msra_codegen/gitignore.py,sha256=ewGikQoiwHLYQZj-OcNfeASoHode55__YSAPcZhAh6w,1004
16
+ msra_codegen/issue_templates.py,sha256=Mk1lLciCRd6ZqvhnA2_hcrMHEKLNlPSjVu1rYeTbRHg,3458
17
+ msra_codegen/logo_assets.py,sha256=BtU5iuOU2FhdhLFH70QDuBxTwpbUBH1-y6e12sTfyRk,3642
18
+ msra_codegen/msra_serializer.py,sha256=eUSDFE2dw4QCtBqUSQkW0yLqEeZQoXDVn4ps76kFAmQ,7817
19
+ msra_codegen/node_export.js,sha256=WrKjmLU7N9QM-2BAHhnJztvKG66vAZirqyXqPdYMRaE,7519
20
+ msra_codegen/package_metadata.py,sha256=qU2ulFWUxXLJXLmk6uSksfcuCx9_BB3FrRDPMeBzk_s,11353
21
+ msra_codegen/package_writer.py,sha256=2dNfGA4GXLVrhnVOq8cpQVDP0AcaZZzqHBwdkRsaKhk,6950
22
+ msra_codegen/project_model.py,sha256=iJ1VtifcCloseMrr-0-ZprqD8t0ndQt6g6qiiLPiFP0,20088
23
+ msra_codegen/python_formatting.py,sha256=nz8_ek7Psx4Nrmf0pT8bXcsxMiaQhzhWcGqZ0HL9xJ0,2520
24
+ msra_codegen/python_render.py,sha256=QIRDyRidbp6XhpWuC7Yt9S-VyZzYDpmacwhwA7B6qEw,10031
25
+ msra_codegen/readme_pipeline.py,sha256=wstRsOoiiwr2DltlhWpsvDEvlIdy7jl0okaqgKWB3p8,20480
26
+ msra_codegen/requirements.txt,sha256=TGEOcSBPBq31lUJYl5s2mfYXDbUjWzIsZwjmpI3o-y8,62
27
+ msra_codegen/template_engine.py,sha256=E2saVQMAwfrRMGy6jA0u8PoyFLuijbOAJJvAbSGK_NI,749
28
+ msra_codegen/tests_generator.py,sha256=7FPHC_X9JnzNhiYF3R-C4kSAknWXpOBMhtv0n4cvGcE,38026
29
+ msra_codegen/typespec.py,sha256=YPnfNoaaNh9NKDy7G5vInhvEVxiYjbTizcLjKrSr2b0,9531
30
+ msra_codegen/validation.py,sha256=LPHWfpcAO8O7RPSZA69eGWRJHntGkD0SROSmSghU-8I,3897
31
+ msra_codegen/templates/Makefile.tpl,sha256=UaPHmXcX7iIU8gRZQdnZJb4YN42nog_xf42-CHFhsxk,1180
32
+ msra_codegen/templates/README.md.tpl,sha256=vERzjz7H57WRBIG2bz8c_FG9xg5rUlLzXLkmo_BNdJ0,1493
33
+ msra_codegen/templates/endpoints_init.py.tpl,sha256=2V8gqXGRS-HV3yG-Fo5ZGc6dUrLVAx-fkGn2r2u6gIA,349
34
+ msra_codegen/templates/example.py.tpl,sha256=_nfryVxniYskaAnzk8Dc20rzcuTS3D1hvejMyKf2ZE0,27
35
+ msra_codegen/templates/function.py.tpl,sha256=zh9DTbff7Kyg8GBLlWjoS35GC7cFJ7-YJSqkFUI6iD0,17040
36
+ msra_codegen/templates/gitignore.tpl,sha256=tbDU-LuUp6VTfKAZIxBECyw_-fqwLvtfKcldrAf0iXo,58
37
+ msra_codegen/templates/group.py.tpl,sha256=LOesecFGYzBf77STFejJ7Iunn6X1mOw4NexV338izWw,1307
38
+ msra_codegen/templates/group_init.py.tpl,sha256=zv3zYtvFlfWKZrT_X-TRO28QmWrnEJd3-xd343Xi0Ec,456
39
+ msra_codegen/templates/init.py.tpl,sha256=pQYEPc1dTWr0KPzxNX7e4CkTRBqxfrwdQfq-08fvfhs,114
40
+ msra_codegen/templates/manager.py.tpl,sha256=e2tfTqHLkC-zYWV0h7qW-hSBsBBB3VaCrb2XevWMxRE,8427
41
+ msra_codegen/templates/pyproject.toml.tpl,sha256=vntgHtJGycTlC-rVPA07Vhp0UEw1KH24a9tFq7D0KI0,979
42
+ msra_codegen/templates/variable.py.tpl,sha256=G9ZBoUl_9fCRhgaWJ_Vj9f5c6KnK-vHweCutpAxoEPY,2152
43
+ msra_codegen/templates/abstraction/__init__.py.tpl,sha256=2pjmpE5SS6yXTZ8qW90QHj02eLlqNhGmP8fDXC-DQm0,5327
44
+ msra_codegen/templates/abstraction/regexes.py.tpl,sha256=hEq-wdoaN4VbttxcDDlPEGwfO59yOCWBNB7074ssKy4,502
45
+ msra_codegen/templates/docs/requirements.txt.tpl,sha256=LisN4V35t7YXySkjwF3nFxwU9XiW29-mo2epckFASEE,33
46
+ msra_codegen/templates/docs/source/Makefile.tpl,sha256=i2WHuFlgfyAPEW4ssEP8NY4cOibDJrVjvzSEU8_Ggwc,634
47
+ msra_codegen/templates/docs/source/api.rst.tpl,sha256=aq671_12LJfwUdbzMc2VE2KVRKjscMhen6Dfu-XooDM,123
48
+ msra_codegen/templates/docs/source/conf.py.tpl,sha256=mHi4MuOViH-Qi8hQtOhbr3XwnutBbh7Fa0I6eMCGGxo,1992
49
+ msra_codegen/templates/docs/source/index.rst.tpl,sha256=l2QftkvlNdRquxK3g37YQpTtjnP72fTC_C_4xvKT6KQ,165
50
+ msra_codegen/templates/docs/source/module.rst.tpl,sha256=WXn8KvvywJnQl09qU8-mscXxJlccdz898TjqNxHf8Tw,517
51
+ msra_codegen/templates/docs/source/quick_start.rst.tpl,sha256=tJ1-yy7Kroqa2AUKgA08zPRvn023ZkJWhiP71V7RUHk,351
52
+ msra_codegen/templates/github/issue_templates/bug_report.yml.tpl,sha256=0rn2Qt6-VrYUwbyiWk2SE05kH9lumbeqLXxUFIQNcx4,1308
53
+ msra_codegen/templates/github/issue_templates/config.yml.tpl,sha256=kABVkxMluwWauCtF71BUcoF0YJ6xWzgxuUSipUbnYN0,203
54
+ msra_codegen/templates/github/issue_templates/documentation_issue.yml.tpl,sha256=XOqeptXf4sgx6HDCXhBeiPKfWM0Q7TzzSlgKwmDXfdE,766
55
+ msra_codegen/templates/github/issue_templates/feature_request.yml.tpl,sha256=34wXm6kC93T_E36S3V2hWnTX4bL-tz3SW9FMolM7Pfc,988
56
+ msra_codegen/templates/github/workflows/publish.yml.tpl,sha256=4BvhQ_q53xLn1HYEX-1DN5XM0JTyEk6i7SOof4fIoqA,2731
57
+ msra_codegen/templates/github/workflows/source-sync.yml.tpl,sha256=XrgqzfSSesCNU-8ELNMfc9iF2ooWd5FwQ9tOJg-fiv0,6548
58
+ msra_codegen/templates/github/workflows/tests.yml.tpl,sha256=zuJIZmmhY2EgK8e9XzlLg0Atgd6fSS4nu77FSMzpMts,1751
59
+ msra_codegen/templates/licenses/GPL-3.0-or-later.txt.tpl,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
60
+ msra_codegen/templates/licenses/MIT.txt.tpl,sha256=2tAP1iRu8_2JMv1tCn3BSV8mdUn7YJVxs1TeXZsLspw,1086
61
+ msra_codegen/templates/tests/api_test.py.tpl,sha256=2tLFajzKtDjRD_orAHRbEoph0mbKt_CpKY9hwIXSMrk,1077
62
+ msra_codegen/templates/tests/conftest.py.tpl,sha256=jsrA4Gl54CCVF9c1wUu5wFlROmM-nJvzsqoZbCVtZhg,451
63
+ msra_codegen-0.1.0.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
64
+ msra_codegen-0.1.0.dist-info/METADATA,sha256=r5KTJ1S_Sy0VOSdWYUqvVVktCUFNK3KOtYzxij2S7K0,1364
65
+ msra_codegen-0.1.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
66
+ msra_codegen-0.1.0.dist-info/entry_points.txt,sha256=qSDNB8315HFeLaYf9imJT-s5kyyoLWF2z1oDcvuz17w,55
67
+ msra_codegen-0.1.0.dist-info/top_level.txt,sha256=z8EcNhplJZTF_sruniZrAogi85X5zNywxKeeNSSW09U,13
68
+ msra_codegen-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (82.0.1)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ msra-codegen = msra_codegen.cli:main