ssc_codegen 0.26.5__tar.gz → 0.28.0__tar.gz

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 (60) hide show
  1. {ssc_codegen-0.26.5 → ssc_codegen-0.28.0}/.gitignore +4 -0
  2. {ssc_codegen-0.26.5 → ssc_codegen-0.28.0}/PKG-INFO +12 -1
  3. {ssc_codegen-0.26.5 → ssc_codegen-0.28.0}/README.md +11 -0
  4. {ssc_codegen-0.26.5 → ssc_codegen-0.28.0}/pyproject.toml +2 -1
  5. {ssc_codegen-0.26.5 → ssc_codegen-0.28.0}/ssc_codegen/ast/__init__.py +189 -179
  6. {ssc_codegen-0.26.5 → ssc_codegen-0.28.0}/ssc_codegen/ast/module.py +108 -92
  7. {ssc_codegen-0.26.5 → ssc_codegen-0.28.0}/ssc_codegen/ast/struct.py +455 -379
  8. {ssc_codegen-0.26.5 → ssc_codegen-0.28.0}/ssc_codegen/converters/base.py +2 -2
  9. {ssc_codegen-0.26.5 → ssc_codegen-0.28.0}/ssc_codegen/converters/js_pure.py +216 -157
  10. {ssc_codegen-0.26.5 → ssc_codegen-0.28.0}/ssc_codegen/converters/py_bs4.py +681 -237
  11. {ssc_codegen-0.26.5 → ssc_codegen-0.28.0}/ssc_codegen/converters/py_lxml.py +29 -20
  12. {ssc_codegen-0.26.5 → ssc_codegen-0.28.0}/ssc_codegen/converters/py_parsel.py +18 -12
  13. {ssc_codegen-0.26.5 → ssc_codegen-0.28.0}/ssc_codegen/converters/py_slax.py +7 -8
  14. {ssc_codegen-0.26.5 → ssc_codegen-0.28.0}/ssc_codegen/core/expressions.py +4 -3
  15. {ssc_codegen-0.26.5 → ssc_codegen-0.28.0}/ssc_codegen/core/module_handler.py +22 -21
  16. {ssc_codegen-0.26.5 → ssc_codegen-0.28.0}/ssc_codegen/core/struct_parser.py +20 -12
  17. {ssc_codegen-0.26.5 → ssc_codegen-0.28.0}/ssc_codegen/kdl/reader.py +11 -0
  18. {ssc_codegen-0.26.5 → ssc_codegen-0.28.0}/ssc_codegen/main.py +3 -4
  19. ssc_codegen-0.26.5/ssc_codegen/converters/py_helpers.py +0 -561
  20. {ssc_codegen-0.26.5 → ssc_codegen-0.28.0}/LICENSE +0 -0
  21. {ssc_codegen-0.26.5 → ssc_codegen-0.28.0}/ssc_codegen/__init__.py +0 -0
  22. {ssc_codegen-0.26.5 → ssc_codegen-0.28.0}/ssc_codegen/_logging.py +0 -0
  23. {ssc_codegen-0.26.5 → ssc_codegen-0.28.0}/ssc_codegen/ast/array.py +0 -0
  24. {ssc_codegen-0.26.5 → ssc_codegen-0.28.0}/ssc_codegen/ast/base.py +0 -0
  25. {ssc_codegen-0.26.5 → ssc_codegen-0.28.0}/ssc_codegen/ast/cast.py +0 -0
  26. {ssc_codegen-0.26.5 → ssc_codegen-0.28.0}/ssc_codegen/ast/control.py +0 -0
  27. {ssc_codegen-0.26.5 → ssc_codegen-0.28.0}/ssc_codegen/ast/extract.py +0 -0
  28. {ssc_codegen-0.26.5 → ssc_codegen-0.28.0}/ssc_codegen/ast/helpers.py +0 -0
  29. {ssc_codegen-0.26.5 → ssc_codegen-0.28.0}/ssc_codegen/ast/jsondef.py +0 -0
  30. {ssc_codegen-0.26.5 → ssc_codegen-0.28.0}/ssc_codegen/ast/predicate_containers.py +0 -0
  31. {ssc_codegen-0.26.5 → ssc_codegen-0.28.0}/ssc_codegen/ast/predicate_ops.py +0 -0
  32. {ssc_codegen-0.26.5 → ssc_codegen-0.28.0}/ssc_codegen/ast/regex.py +0 -0
  33. {ssc_codegen-0.26.5 → ssc_codegen-0.28.0}/ssc_codegen/ast/selectors.py +0 -0
  34. {ssc_codegen-0.26.5 → ssc_codegen-0.28.0}/ssc_codegen/ast/string.py +0 -0
  35. {ssc_codegen-0.26.5 → ssc_codegen-0.28.0}/ssc_codegen/ast/transform.py +0 -0
  36. {ssc_codegen-0.26.5 → ssc_codegen-0.28.0}/ssc_codegen/ast/typedef.py +0 -0
  37. {ssc_codegen-0.26.5 → ssc_codegen-0.28.0}/ssc_codegen/ast/types.py +0 -0
  38. {ssc_codegen-0.26.5 → ssc_codegen-0.28.0}/ssc_codegen/converters/helpers.py +0 -0
  39. {ssc_codegen-0.26.5 → ssc_codegen-0.28.0}/ssc_codegen/converters/py_render.py +0 -0
  40. {ssc_codegen-0.26.5 → ssc_codegen-0.28.0}/ssc_codegen/converters/request_spec.py +0 -0
  41. {ssc_codegen-0.26.5 → ssc_codegen-0.28.0}/ssc_codegen/core/__init__.py +0 -0
  42. {ssc_codegen-0.26.5 → ssc_codegen-0.28.0}/ssc_codegen/core/adapter.py +0 -0
  43. {ssc_codegen-0.26.5 → ssc_codegen-0.28.0}/ssc_codegen/core/contexts.py +0 -0
  44. {ssc_codegen-0.26.5 → ssc_codegen-0.28.0}/ssc_codegen/core/format.py +0 -0
  45. {ssc_codegen-0.26.5 → ssc_codegen-0.28.0}/ssc_codegen/core/linting.py +0 -0
  46. {ssc_codegen-0.26.5 → ssc_codegen-0.28.0}/ssc_codegen/core/predicates.py +0 -0
  47. {ssc_codegen-0.26.5 → ssc_codegen-0.28.0}/ssc_codegen/core/reader.py +0 -0
  48. {ssc_codegen-0.26.5 → ssc_codegen-0.28.0}/ssc_codegen/core/type_checking.py +0 -0
  49. {ssc_codegen-0.26.5 → ssc_codegen-0.28.0}/ssc_codegen/document_utils.py +0 -0
  50. {ssc_codegen-0.26.5 → ssc_codegen-0.28.0}/ssc_codegen/exceptions.py +0 -0
  51. {ssc_codegen-0.26.5 → ssc_codegen-0.28.0}/ssc_codegen/health.py +0 -0
  52. {ssc_codegen-0.26.5 → ssc_codegen-0.28.0}/ssc_codegen/kdl/__init__.py +0 -0
  53. {ssc_codegen-0.26.5 → ssc_codegen-0.28.0}/ssc_codegen/kdl/dict_reader.py +0 -0
  54. {ssc_codegen-0.26.5 → ssc_codegen-0.28.0}/ssc_codegen/kdl/parser.py +0 -0
  55. {ssc_codegen-0.26.5 → ssc_codegen-0.28.0}/ssc_codegen/parsers/__init__.py +0 -0
  56. {ssc_codegen-0.26.5 → ssc_codegen-0.28.0}/ssc_codegen/parsers/curl.py +0 -0
  57. {ssc_codegen-0.26.5 → ssc_codegen-0.28.0}/ssc_codegen/parsers/http.py +0 -0
  58. {ssc_codegen-0.26.5 → ssc_codegen-0.28.0}/ssc_codegen/pseudo_selectors.py +0 -0
  59. {ssc_codegen-0.26.5 → ssc_codegen-0.28.0}/ssc_codegen/regex_utils.py +0 -0
  60. {ssc_codegen-0.26.5 → ssc_codegen-0.28.0}/ssc_codegen/selector_utils.py +0 -0
@@ -146,5 +146,9 @@ test_schemas/
146
146
  .idea/inspectionProfiles/Project_Default.xml
147
147
  .idea/libraries/Dart_SDK.xml
148
148
 
149
+ # Node.js
150
+ node_modules/
151
+ package-lock.json
152
+
149
153
  # slopmachines
150
154
  .claude/*
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ssc_codegen
3
- Version: 0.26.5
3
+ Version: 0.28.0
4
4
  Summary: Python-dsl code converter to html parser for web scraping
5
5
  Project-URL: Documentation, https://github.com/vypivshiy/selector_schema_codegen#readme
6
6
  Project-URL: Issues, https://github.com/vypivshiy/selector_schema_codegen/issues
@@ -154,3 +154,14 @@ uv build --wheel # build wheel
154
154
  uv run pytest # run tests
155
155
  uv run ruff check ssc_codegen/
156
156
  ```
157
+
158
+ ### Test dependencies
159
+
160
+ Python tests require only `uv sync`. JS integration tests additionally need:
161
+
162
+ ```bash
163
+ npm install # installs jsdom (dev dependency in package.json)
164
+ ```
165
+
166
+ Node.js must be installed and available as `node` in PATH. JS tests are automatically skipped if Node.js is not found.
167
+ ```
@@ -122,3 +122,14 @@ uv build --wheel # build wheel
122
122
  uv run pytest # run tests
123
123
  uv run ruff check ssc_codegen/
124
124
  ```
125
+
126
+ ### Test dependencies
127
+
128
+ Python tests require only `uv sync`. JS integration tests additionally need:
129
+
130
+ ```bash
131
+ npm install # installs jsdom (dev dependency in package.json)
132
+ ```
133
+
134
+ Node.js must be installed and available as `node` in PATH. JS tests are automatically skipped if Node.js is not found.
135
+ ```
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "ssc_codegen"
3
- version = "0.26.5"
3
+ version = "0.28.0"
4
4
  description = "Python-dsl code converter to html parser for web scraping "
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.10"
@@ -64,6 +64,7 @@ dev = [
64
64
  "mypy>=1.14.1",
65
65
  "parsel>=1.9.1",
66
66
  "pytest>=8.3.4",
67
+ "respx>=0.23.1",
67
68
  "ruff>=0.9.3",
68
69
  "selectolax>=0.3.27",
69
70
  ]
@@ -1,179 +1,189 @@
1
- # mypy: ignore-errors
2
- """
3
- AST nodes for the KDL Schema DSL.
4
-
5
- Import everything from here:
6
- from kdl_ast import Module, Field, CssSelect, ...
7
- """
8
- from .types import VariableType, StructType
9
-
10
- from .base import Node
11
-
12
- from .module import (
13
- Module,
14
- CodeStartHook,
15
- CodeEndHook,
16
- Docstring,
17
- Imports,
18
- Utilities,
19
- )
20
-
21
- from .typedef import TypeDef, TypeDefField
22
-
23
- from .jsondef import JsonDef, JsonDefField
24
-
25
- from .struct import (
26
- Struct,
27
- StructDocstring,
28
- PreValidate,
29
- CheckMethod,
30
- Init,
31
- InitField,
32
- SplitDoc,
33
- Key,
34
- Value,
35
- TableConfig,
36
- TableRow,
37
- TableMatchKey,
38
- RequestConfig,
39
- ErrorResponse,
40
- PlaceholderSpec,
41
- Field,
42
- StartParse,
43
- )
44
-
45
- from .selectors import (
46
- CssSelect,
47
- CssSelectAll,
48
- XpathSelect,
49
- XpathSelectAll,
50
- CssRemove,
51
- XpathRemove,
52
- )
53
-
54
- from .extract import Text, Raw, Attr
55
-
56
- from .string import (
57
- Trim,
58
- Ltrim,
59
- Rtrim,
60
- NormalizeSpace,
61
- RmPrefix,
62
- RmSuffix,
63
- RmPrefixSuffix,
64
- Fmt,
65
- Repl,
66
- ReplMap,
67
- Lower,
68
- Upper,
69
- Split,
70
- Join,
71
- Unescape,
72
- )
73
-
74
- from .regex import Re, ReAll, ReSub
75
-
76
- from .array import Index, Slice, Len, Unique
77
-
78
- from .cast import ToInt, ToFloat, ToBool, Jsonify, Nested
79
-
80
- from .control import Self, Fallback, FallbackStart, FallbackEnd, Return
81
-
82
- from .predicate_containers import Filter, Assert, Match
83
-
84
- from .predicate_ops import (
85
- PredEq,
86
- PredNe,
87
- PredGt,
88
- PredLt,
89
- PredGe,
90
- PredLe,
91
- PredRange,
92
- PredStarts,
93
- PredEnds,
94
- PredContains,
95
- PredIn,
96
- PredRe,
97
- PredReAny,
98
- PredReAll,
99
- PredCss,
100
- PredXpath,
101
- PredHasAttr,
102
- PredCountEq,
103
- PredCountGt,
104
- PredCountLt,
105
- PredCountNe,
106
- PredCountGe,
107
- PredCountLe,
108
- PredCountRange,
109
- PredAttrEnds,
110
- PredAttrEq,
111
- PredAttrNe,
112
- PredAttrRe,
113
- PredAttrStarts,
114
- PredAttrContains,
115
- PredTextContains,
116
- PredTextEnds,
117
- PredTextRe,
118
- PredTextStarts,
119
- LogicNot,
120
- LogicAnd,
121
- LogicOr,
122
- )
123
-
124
- from .transform import TransformDef, TransformTarget, TransformCall
125
-
126
- __all__ = [
127
- # types
128
- "VariableType", "StructType",
129
- # base
130
- "Node",
131
- # module
132
- "Module", "CodeStartHook", "CodeEndHook",
133
- "Docstring", "Imports", "Utilities",
134
- # typedef
135
- "TypeDef", "TypeDefField",
136
- # jsondef
137
- "JsonDef", "JsonDefField",
138
- # struct
139
- "Struct", "StructDocstring", "PreValidate", "CheckMethod",
140
- "Init", "InitField", "SplitDoc",
141
- "Key", "Value",
142
- "TableConfig", "TableRow", "TableMatchKey",
143
- "RequestConfig", "ErrorResponse", "PlaceholderSpec", "Field", "StartParse",
144
- # selectors
145
- "CssSelect", "CssSelectAll",
146
- "XpathSelect", "XpathSelectAll",
147
- "CssRemove", "XpathRemove",
148
- # extract
149
- "Text", "Raw", "Attr",
150
- # string
151
- "Trim", "Ltrim", "Rtrim", "NormalizeSpace",
152
- "RmPrefix", "RmSuffix", "RmPrefixSuffix",
153
- "Fmt", "Repl", "ReplMap",
154
- "Lower", "Upper", "Split", "Join", "Unescape",
155
- # regex
156
- "Re", "ReAll", "ReSub",
157
- # array
158
- "Index", "Slice", "Len", "Unique",
159
- # cast
160
- "ToInt", "ToFloat", "ToBool", "Jsonify", "Nested",
161
- # control
162
- "Self", "Fallback", "FallbackStart", "FallbackEnd", "Return",
163
- # predicate containers
164
- "Filter", "Assert", "Match",
165
- # predicate ops
166
- "PredEq", "PredNe",
167
- "PredGt", "PredLt", "PredGe", "PredLe", "PredRange",
168
- "PredStarts", "PredEnds", "PredContains", "PredIn",
169
- "PredRe", "PredReAny", "PredReAll",
170
- "PredCss", "PredXpath", "PredHasAttr",
171
- "PredAttrEq", "PredAttrNe",
172
- "PredAttrStarts", "PredAttrEnds", "PredAttrContains", "PredAttrRe",
173
- "PredTextStarts", "PredTextEnds", "PredTextContains", "PredTextRe",
174
- "PredCountEq", "PredCountGt", "PredCountLt",
175
- "PredCountNe", "PredCountGe", "PredCountLe", "PredCountRange",
176
- "LogicNot", "LogicAnd", "LogicOr",
177
- # transform
178
- "TransformDef", "TransformTarget", "TransformCall",
179
- ]
1
+ # mypy: ignore-errors
2
+ """
3
+ AST nodes for the KDL Schema DSL.
4
+
5
+ Import everything from here:
6
+ from kdl_ast import Module, Field, CssSelect, ...
7
+ """
8
+ from .types import VariableType, StructType
9
+
10
+ from .base import Node
11
+
12
+ from .module import (
13
+ Module,
14
+ CodeStartHook,
15
+ CodeEndHook,
16
+ Docstring,
17
+ Imports,
18
+ ImportsRest,
19
+ Utilities,
20
+ )
21
+
22
+ from .typedef import TypeDef, TypeDefField
23
+
24
+ from .jsondef import JsonDef, JsonDefField
25
+
26
+ from .struct import (
27
+ StructBase,
28
+ StructItem,
29
+ StructList,
30
+ StructFlatList,
31
+ StructDict,
32
+ StructTable,
33
+ StructRest,
34
+ Struct,
35
+ StructDocstring,
36
+ PreValidate,
37
+ CheckMethod,
38
+ Init,
39
+ InitField,
40
+ SplitDoc,
41
+ Key,
42
+ Value,
43
+ TableConfig,
44
+ TableRow,
45
+ TableMatchKey,
46
+ RequestConfig,
47
+ ErrorResponse,
48
+ PlaceholderSpec,
49
+ Field,
50
+ StartParse,
51
+ )
52
+
53
+ from .selectors import (
54
+ CssSelect,
55
+ CssSelectAll,
56
+ XpathSelect,
57
+ XpathSelectAll,
58
+ CssRemove,
59
+ XpathRemove,
60
+ )
61
+
62
+ from .extract import Text, Raw, Attr
63
+
64
+ from .string import (
65
+ Trim,
66
+ Ltrim,
67
+ Rtrim,
68
+ NormalizeSpace,
69
+ RmPrefix,
70
+ RmSuffix,
71
+ RmPrefixSuffix,
72
+ Fmt,
73
+ Repl,
74
+ ReplMap,
75
+ Lower,
76
+ Upper,
77
+ Split,
78
+ Join,
79
+ Unescape,
80
+ )
81
+
82
+ from .regex import Re, ReAll, ReSub
83
+
84
+ from .array import Index, Slice, Len, Unique
85
+
86
+ from .cast import ToInt, ToFloat, ToBool, Jsonify, Nested
87
+
88
+ from .control import Self, Fallback, FallbackStart, FallbackEnd, Return
89
+
90
+ from .predicate_containers import Filter, Assert, Match
91
+
92
+ from .predicate_ops import (
93
+ PredEq,
94
+ PredNe,
95
+ PredGt,
96
+ PredLt,
97
+ PredGe,
98
+ PredLe,
99
+ PredRange,
100
+ PredStarts,
101
+ PredEnds,
102
+ PredContains,
103
+ PredIn,
104
+ PredRe,
105
+ PredReAny,
106
+ PredReAll,
107
+ PredCss,
108
+ PredXpath,
109
+ PredHasAttr,
110
+ PredCountEq,
111
+ PredCountGt,
112
+ PredCountLt,
113
+ PredCountNe,
114
+ PredCountGe,
115
+ PredCountLe,
116
+ PredCountRange,
117
+ PredAttrEnds,
118
+ PredAttrEq,
119
+ PredAttrNe,
120
+ PredAttrRe,
121
+ PredAttrStarts,
122
+ PredAttrContains,
123
+ PredTextContains,
124
+ PredTextEnds,
125
+ PredTextRe,
126
+ PredTextStarts,
127
+ LogicNot,
128
+ LogicAnd,
129
+ LogicOr,
130
+ )
131
+
132
+ from .transform import TransformDef, TransformTarget, TransformCall
133
+
134
+ __all__ = [
135
+ # types
136
+ "VariableType", "StructType",
137
+ # base
138
+ "Node",
139
+ # module
140
+ "Module", "CodeStartHook", "CodeEndHook",
141
+ "Docstring", "Imports", "ImportsRest", "Utilities",
142
+ # typedef
143
+ "TypeDef", "TypeDefField",
144
+ # jsondef
145
+ "JsonDef", "JsonDefField",
146
+ # struct
147
+ "StructBase", "StructItem", "StructList", "StructFlatList",
148
+ "StructDict", "StructTable", "StructRest", "Struct",
149
+ "StructDocstring", "PreValidate", "CheckMethod",
150
+ "Init", "InitField", "SplitDoc",
151
+ "Key", "Value",
152
+ "TableConfig", "TableRow", "TableMatchKey",
153
+ "RequestConfig", "ErrorResponse", "PlaceholderSpec", "Field", "StartParse",
154
+ # selectors
155
+ "CssSelect", "CssSelectAll",
156
+ "XpathSelect", "XpathSelectAll",
157
+ "CssRemove", "XpathRemove",
158
+ # extract
159
+ "Text", "Raw", "Attr",
160
+ # string
161
+ "Trim", "Ltrim", "Rtrim", "NormalizeSpace",
162
+ "RmPrefix", "RmSuffix", "RmPrefixSuffix",
163
+ "Fmt", "Repl", "ReplMap",
164
+ "Lower", "Upper", "Split", "Join", "Unescape",
165
+ # regex
166
+ "Re", "ReAll", "ReSub",
167
+ # array
168
+ "Index", "Slice", "Len", "Unique",
169
+ # cast
170
+ "ToInt", "ToFloat", "ToBool", "Jsonify", "Nested",
171
+ # control
172
+ "Self", "Fallback", "FallbackStart", "FallbackEnd", "Return",
173
+ # predicate containers
174
+ "Filter", "Assert", "Match",
175
+ # predicate ops
176
+ "PredEq", "PredNe",
177
+ "PredGt", "PredLt", "PredGe", "PredLe", "PredRange",
178
+ "PredStarts", "PredEnds", "PredContains", "PredIn",
179
+ "PredRe", "PredReAny", "PredReAll",
180
+ "PredCss", "PredXpath", "PredHasAttr",
181
+ "PredAttrEq", "PredAttrNe",
182
+ "PredAttrStarts", "PredAttrEnds", "PredAttrContains", "PredAttrRe",
183
+ "PredTextStarts", "PredTextEnds", "PredTextContains", "PredTextRe",
184
+ "PredCountEq", "PredCountGt", "PredCountLt",
185
+ "PredCountNe", "PredCountGe", "PredCountLe", "PredCountRange",
186
+ "LogicNot", "LogicAnd", "LogicOr",
187
+ # transform
188
+ "TransformDef", "TransformTarget", "TransformCall",
189
+ ]
@@ -1,92 +1,108 @@
1
- from __future__ import annotations
2
- from dataclasses import dataclass, field
3
-
4
- from .base import Node
5
-
6
-
7
- @dataclass
8
- class Module(Node):
9
- """
10
- Root node.
11
- Build order of body:
12
- CodeStartHook → Docstring, Imports, Utilities
13
- → JsonDef entries → TypeDef entries → Struct entries
14
- → CodeEndHook
15
- """
16
-
17
- def __post_init__(self):
18
- self.body.extend(
19
- [
20
- Docstring(parent=self),
21
- Imports(parent=self),
22
- Utilities(parent=self),
23
- CodeStartHook(parent=self),
24
- ]
25
- )
26
-
27
- @property
28
- def docstring(self) -> Docstring:
29
- return self.body[0] # type: ignore
30
-
31
- @property
32
- def imports(self) -> Imports:
33
- return self.body[1] # type: ignore
34
-
35
- @property
36
- def utilities(self) -> Imports:
37
- return self.body[2] # type: ignore
38
-
39
- @property
40
- def code_start(self) -> Imports:
41
- return self.body[3] # type: ignore
42
-
43
-
44
- @dataclass
45
- class CodeStartHook(Node):
46
- """
47
- User code insertion point before all generated code.
48
- Codegen emits body content verbatim at the top of the output file.
49
- """
50
-
51
- pass
52
-
53
-
54
- @dataclass
55
- class CodeEndHook(Node):
56
- """
57
- User code insertion point after all generated structs.
58
- Codegen emits body content verbatim at the bottom of the output file.
59
- """
60
-
61
- pass
62
-
63
-
64
- @dataclass
65
- class Docstring(Node):
66
- """Module-level docstring. DSL: doc "text" """
67
-
68
- value: str = ""
69
-
70
-
71
- @dataclass
72
- class Imports(Node):
73
- """
74
- Technical node — codegen inserts required import statements into body.
75
- Not produced from DSL directly; populated during codegen phase.
76
-
77
- transform_imports: Dict of imports by target language (e.g., {"py": {...}, "js": {...}})
78
- Collected during parsing when TransformCall nodes are created.
79
- """
80
-
81
- libs: list[str] = field(default_factory=list)
82
- transform_imports: dict[str, set[str]] = field(default_factory=dict)
83
-
84
-
85
- @dataclass
86
- class Utilities(Node):
87
- """
88
- Technical node — codegen inserts shared helper functions into body.
89
- Not produced from DSL directly; populated during codegen phase.
90
- """
91
-
92
- pass
1
+ from __future__ import annotations
2
+ from dataclasses import dataclass, field
3
+
4
+ from .base import Node
5
+
6
+
7
+ @dataclass
8
+ class Module(Node):
9
+ """
10
+ Root node.
11
+ Build order of body:
12
+ CodeStartHook → Docstring, Imports, ImportsRest, Utilities
13
+ → JsonDef entries → TypeDef entries → Struct entries
14
+ → CodeEndHook
15
+ """
16
+
17
+ def __post_init__(self):
18
+ self.body.extend(
19
+ [
20
+ Docstring(parent=self),
21
+ Imports(parent=self),
22
+ ImportsRest(parent=self),
23
+ Utilities(parent=self),
24
+ CodeStartHook(parent=self),
25
+ ]
26
+ )
27
+
28
+ @property
29
+ def docstring(self) -> Docstring:
30
+ return self.body[0] # type: ignore
31
+
32
+ @property
33
+ def imports(self) -> Imports:
34
+ return self.body[1] # type: ignore
35
+
36
+ @property
37
+ def imports_rest(self) -> ImportsRest:
38
+ return self.body[2] # type: ignore
39
+
40
+ @property
41
+ def utilities(self) -> Utilities:
42
+ return self.body[3] # type: ignore
43
+
44
+ @property
45
+ def code_start(self) -> CodeStartHook:
46
+ return self.body[4] # type: ignore
47
+
48
+
49
+ @dataclass
50
+ class CodeStartHook(Node):
51
+ """
52
+ User code insertion point before all generated code.
53
+ Codegen emits body content verbatim at the top of the output file.
54
+ """
55
+
56
+ pass
57
+
58
+
59
+ @dataclass
60
+ class CodeEndHook(Node):
61
+ """
62
+ User code insertion point after all generated structs.
63
+ Codegen emits body content verbatim at the bottom of the output file.
64
+ """
65
+
66
+ pass
67
+
68
+
69
+ @dataclass
70
+ class Docstring(Node):
71
+ """Module-level docstring. DSL: doc "text" """
72
+
73
+ value: str = ""
74
+
75
+
76
+ @dataclass
77
+ class Imports(Node):
78
+ """
79
+ Technical node — codegen inserts required import statements into body.
80
+ Not produced from DSL directly; populated during codegen phase.
81
+
82
+ transform_imports: Dict of imports by target language (e.g., {"py": {...}, "js": {...}})
83
+ Collected during parsing when TransformCall nodes are created.
84
+ """
85
+
86
+ libs: list[str] = field(default_factory=list)
87
+ transform_imports: dict[str, set[str]] = field(default_factory=dict)
88
+
89
+
90
+ @dataclass
91
+ class ImportsRest(Node):
92
+ """
93
+ Technical node — REST-specific import statements.
94
+ Emitted only when the module contains at least one StructRest.
95
+ Populated during codegen phase.
96
+ """
97
+
98
+ libs: list[str] = field(default_factory=list)
99
+
100
+
101
+ @dataclass
102
+ class Utilities(Node):
103
+ """
104
+ Technical node — codegen inserts shared helper functions into body.
105
+ Not produced from DSL directly; populated during codegen phase.
106
+ """
107
+
108
+ pass