ssc_codegen 0.12.0__tar.gz → 0.13.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 (69) hide show
  1. {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/PKG-INFO +2 -3
  2. {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/README.md +1 -1
  3. {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/pyproject.toml +3 -2
  4. {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/__init__.py +1 -1
  5. ssc_codegen-0.13.0/ssc_codegen/ast_/base.py +242 -0
  6. {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/ast_/nodes_array.py +42 -0
  7. {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/ast_/nodes_cast.py +71 -0
  8. ssc_codegen-0.13.0/ssc_codegen/ast_/nodes_core.py +553 -0
  9. ssc_codegen-0.13.0/ssc_codegen/ast_/nodes_filter.py +659 -0
  10. ssc_codegen-0.13.0/ssc_codegen/ast_/nodes_selectors.py +305 -0
  11. ssc_codegen-0.13.0/ssc_codegen/ast_/nodes_string.py +495 -0
  12. ssc_codegen-0.13.0/ssc_codegen/ast_/nodes_validate.py +207 -0
  13. {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/cli/main.py +1 -1
  14. {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/converters/go_goquery.py +53 -29
  15. {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/converters/js_pure.py +126 -51
  16. {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/converters/lua_htmlparser.py +18 -18
  17. {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/converters/py_base.py +21 -24
  18. {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/converters/py_bs4.py +19 -7
  19. {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/converters/py_lxml.py +27 -8
  20. {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/converters/py_parsel.py +28 -11
  21. {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/converters/py_selectolax.py +21 -9
  22. {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/converters/templates/go_goquery.py +34 -1
  23. ssc_codegen-0.13.0/ssc_codegen/converters/templates/js_pure.py +38 -0
  24. {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/document.py +234 -29
  25. {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/tokens.py +0 -1
  26. ssc_codegen-0.12.0/ssc_codegen/ast_/base.py +0 -135
  27. ssc_codegen-0.12.0/ssc_codegen/ast_/nodes_core.py +0 -304
  28. ssc_codegen-0.12.0/ssc_codegen/ast_/nodes_filter.py +0 -285
  29. ssc_codegen-0.12.0/ssc_codegen/ast_/nodes_selectors.py +0 -118
  30. ssc_codegen-0.12.0/ssc_codegen/ast_/nodes_string.py +0 -236
  31. ssc_codegen-0.12.0/ssc_codegen/ast_/nodes_validate.py +0 -122
  32. ssc_codegen-0.12.0/ssc_codegen/converters/templates/js_pure.py +0 -135
  33. {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/.gitignore +0 -0
  34. {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/LICENSE +0 -0
  35. {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/_compat.py +0 -0
  36. {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/ast_/__init__.py +0 -0
  37. {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/ast_build/__init__.py +0 -0
  38. {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/ast_build/builder.py +0 -0
  39. {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/ast_build/main.py +0 -0
  40. {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/ast_build/utils.py +0 -0
  41. {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/ast_grep_rules/js_rules.yml +0 -0
  42. {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/ast_grep_rules/py_rules.yml +0 -0
  43. {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/cli/__init__.py +0 -0
  44. {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/cli/ast_grep.py +0 -0
  45. {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/cli/cli_callbacks.py +0 -0
  46. {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/cli/cli_utils.py +0 -0
  47. {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/cli/code_callbacks.py +0 -0
  48. {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/cli/consts.py +0 -0
  49. {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/cli/runtime_parse_runners.py +0 -0
  50. {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/compiler.py +0 -0
  51. {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/converters/__init__.py +0 -0
  52. {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/converters/base.py +0 -0
  53. {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/converters/helpers.py +0 -0
  54. {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/converters/templates/__init__.py +0 -0
  55. {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/converters/templates/lua_base.py +0 -0
  56. {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/converters/templates/lua_css_compat.py +0 -0
  57. {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/converters/templates/lua_re_compat.py +0 -0
  58. {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/converters/templates/py_base.py +0 -0
  59. {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/document_utlis.py +0 -0
  60. {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/json_struct.py +0 -0
  61. {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/json_to_scc.py +0 -0
  62. {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/logs.py +0 -0
  63. {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/pseudo_selectors.py +0 -0
  64. {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/schema.py +0 -0
  65. {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/selector_utils.py +0 -0
  66. {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/static_checker/__init__.py +0 -0
  67. {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/static_checker/base.py +0 -0
  68. {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/static_checker/callbacks.py +0 -0
  69. {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/str_utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ssc_codegen
3
- Version: 0.12.0
3
+ Version: 0.13.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
@@ -26,7 +26,6 @@ Requires-Dist: colorama>=0.4.6; sys_platform == 'win32'
26
26
  Requires-Dist: cssselect>=1.2.0
27
27
  Requires-Dist: httpx>=0.28.1
28
28
  Requires-Dist: ichrome>=4.0.4
29
- Requires-Dist: jinja2>=3.1.6
30
29
  Requires-Dist: lxml>=5.3.0
31
30
  Requires-Dist: parsel>=1.10.0
32
31
  Requires-Dist: soupsieve>=2.6
@@ -66,7 +65,7 @@ Current support converters
66
65
  | ... | parsel | Y | Y | N | ... | ... |
67
66
  | ... | selectolax (lexbor) | N | Y | N | ... | ... |
68
67
  | ... | lxml | Y | Y | N | ... | ... |
69
- | js (ES6)`2` | pure (firefox/chrome extension/nodejs) | Y | Y | Y | Array, Map`3` | prettier |
68
+ | js (ES6)`2` | pure (firefox/chrome extension/nodejs) | Y | Y | Y | JSDoc | prettier |
70
69
  | go (1.10+) **(UNSTABLE)** | goquery, gjson (`4`) | N | Y | N | struct(+json anchors), array, map | gofmt |
71
70
  | lua (5.2+), luajit(2+) **(UNSTABLE)**`5` | lua-htmlparser, lrexlib(opt), dkjson | N | Y | N | EmmyLua | LuaFormatter |
72
71
 
@@ -29,7 +29,7 @@ Current support converters
29
29
  | ... | parsel | Y | Y | N | ... | ... |
30
30
  | ... | selectolax (lexbor) | N | Y | N | ... | ... |
31
31
  | ... | lxml | Y | Y | N | ... | ... |
32
- | js (ES6)`2` | pure (firefox/chrome extension/nodejs) | Y | Y | Y | Array, Map`3` | prettier |
32
+ | js (ES6)`2` | pure (firefox/chrome extension/nodejs) | Y | Y | Y | JSDoc | prettier |
33
33
  | go (1.10+) **(UNSTABLE)** | goquery, gjson (`4`) | N | Y | N | struct(+json anchors), array, map | gofmt |
34
34
  | lua (5.2+), luajit(2+) **(UNSTABLE)**`5` | lua-htmlparser, lrexlib(opt), dkjson | N | Y | N | EmmyLua | LuaFormatter |
35
35
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "ssc_codegen"
3
- version = "0.12.0"
3
+ version = "0.13.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"
@@ -10,7 +10,6 @@ dependencies = [
10
10
  "cssselect>=1.2.0",
11
11
  "httpx>=0.28.1",
12
12
  "ichrome>=4.0.4",
13
- "jinja2>=3.1.6",
14
13
  "lxml>=5.3.0",
15
14
  "parsel>=1.10.0",
16
15
  "soupsieve>=2.6",
@@ -61,8 +60,10 @@ dev = [
61
60
  "coverage>=7.6.12",
62
61
  "httpx>=0.28.1",
63
62
  "mypy>=1.14.1",
63
+ "parsel>=1.10.0",
64
64
  "pytest>=8.3.4",
65
65
  "ruff>=0.9.3",
66
+ "selectolax>=0.3.27",
66
67
  ]
67
68
  # python generated code tests
68
69
  tests = [
@@ -7,7 +7,7 @@ from ssc_codegen.schema import ItemSchema, DictSchema, ListSchema, FlatListSchem
7
7
 
8
8
  setup_logger()
9
9
 
10
- VERSION = "0.12.0"
10
+ VERSION = "0.13.0"
11
11
 
12
12
 
13
13
  class __MISSING(object):
@@ -0,0 +1,242 @@
1
+ from dataclasses import dataclass, field
2
+ from typing import (
3
+ Callable,
4
+ ClassVar,
5
+ Mapping,
6
+ TypeVar,
7
+ Generic,
8
+ Any,
9
+ TypedDict,
10
+ Optional,
11
+ MutableSequence,
12
+ Sequence,
13
+ TYPE_CHECKING,
14
+ )
15
+
16
+ from ssc_codegen.tokens import TokenType, VariableType
17
+
18
+ if TYPE_CHECKING:
19
+ from ssc_codegen.ast_.nodes_core import ExprClassVar
20
+
21
+ T_ARGUMENTS = TypeVar("T_ARGUMENTS")
22
+ T_MAPPING_FIELD = TypeVar("T_MAPPING_FIELD", bound=Mapping[str, Any])
23
+ T_EMPTY_KWARGS = TypedDict("T_EMPTY_KWARGS", {})
24
+
25
+
26
+ @dataclass(kw_only=True)
27
+ class BaseAstNode(Generic[T_MAPPING_FIELD, T_ARGUMENTS]):
28
+ """Base abstract syntax tree (AST) node.
29
+
30
+ This is the base class for all AST nodes in the code generation system.
31
+ It provides common functionality and properties for AST node manipulation,
32
+ including parent-child relationships, type checking, and dynamic attribute access.
33
+
34
+ Attributes:
35
+ kind: The token type that identifies the kind of AST node.
36
+ kwargs: A mapping containing arguments or properties for this node.
37
+ body: A mutable sequence of child AST nodes.
38
+ parent: A reference to the parent AST node, if any.
39
+ accept_type: The variable type that this node accepts as input.
40
+ ret_type: The variable type that this node type returns.
41
+ exclude_types: A sequence of variable types that should be excluded from processing.
42
+ classvar_hooks: Dictionary of class variable hooks for expression evaluation.
43
+ """
44
+
45
+ kind: ClassVar[TokenType]
46
+ kwargs: T_MAPPING_FIELD = field(default_factory=dict) # type: ignore[assignment]
47
+
48
+ body: MutableSequence["BaseAstNode"] = field(default_factory=list)
49
+ parent: Optional["BaseAstNode"] = field(default=None, repr=False)
50
+
51
+ # used for type check expressions
52
+ accept_type: VariableType = VariableType.ANY
53
+ ret_type: VariableType = VariableType.ANY
54
+ exclude_types: Sequence[VariableType] = field(
55
+ default_factory=tuple, repr=False
56
+ )
57
+ classvar_hooks: dict[str, "ExprClassVar"] = field(default_factory=dict)
58
+
59
+ def unpack_args(self) -> T_ARGUMENTS:
60
+ """Extract all values from the kwargs field without their keys.
61
+
62
+ Returns:
63
+ A tuple containing all values from the kwargs mapping, preserving their order.
64
+ """
65
+ return tuple(self.kwargs.values()) # type: ignore
66
+
67
+ @property
68
+ def index(self) -> int:
69
+ """Get the index of this node in its parent's body.
70
+
71
+ Returns:
72
+ The index of this node in the parent's body sequence.
73
+ Returns -1 if this node has no parent.
74
+ """
75
+ if self.parent:
76
+ # self.parent.body.index(self) add side effect if expr has same operations:
77
+ # 0 1 1 1
78
+ # D().raw().trim().trim().trim()
79
+ # use compare by id
80
+ for i, child in enumerate(self.parent.body):
81
+ if id(child) == id(self):
82
+ return i
83
+ return self.parent.body.index(self)
84
+ return -1
85
+
86
+ @property
87
+ def index_next(self) -> int:
88
+ """Get the index of the next node in the parent's body.
89
+
90
+ Returns:
91
+ The index of the next node in the parent's body sequence.
92
+ Returns -1 if there is no next node or no parent.
93
+ """
94
+ if self.parent and len(self.parent.body) > self.index:
95
+ return self.index + 1
96
+ return -1
97
+
98
+ @property
99
+ def index_prev(self) -> int:
100
+ """Get the index of the previous node in the parent's body.
101
+
102
+ Returns:
103
+ The index of the previous node in the parent's body sequence.
104
+ Returns -1 if there is no previous node, no parent, or current index is -1.
105
+ """
106
+ if self.parent and self.index == 0:
107
+ return -1
108
+ elif self.index == -1:
109
+ return -1
110
+ return self.index - 1
111
+
112
+ def __getattr__(self, name: str) -> Any:
113
+ """Provides dynamic attribute access from the kwargs container.
114
+
115
+ This method allows accessing values in the kwargs dictionary as if they
116
+ were instance attributes, enabling convenient property-like access.
117
+
118
+ Args:
119
+ name: The name of the attribute to access.
120
+
121
+ Returns:
122
+ The value from kwargs if it exists, otherwise raises AttributeError.
123
+
124
+ Raises:
125
+ AttributeError: If the attribute is not found in kwargs or regular attributes.
126
+ """
127
+ try:
128
+ return super().__getattribute__(name)
129
+ except AttributeError as e:
130
+ if self.kwargs.get(name):
131
+ return self.kwargs[name]
132
+ raise e
133
+
134
+ def find_node(
135
+ self, predicate: Callable[["BaseAstNode"], bool]
136
+ ) -> Optional["BaseAstNode"]:
137
+ """Finds the first node in the body that matches the given filter function.
138
+
139
+ Args:
140
+ func: A callable that takes a BaseAstNode and returns True if it matches the criteria.
141
+
142
+ Returns:
143
+ The first matching node, or None if no node matches or the body is empty.
144
+ """
145
+ if len(self.body) == 0:
146
+ return None
147
+
148
+ for n in self.body:
149
+ if predicate(n):
150
+ return n
151
+ return None
152
+
153
+ def find_node_all(
154
+ self, predicate: Callable[["BaseAstNode"], bool]
155
+ ) -> list["BaseAstNode"]:
156
+ """Finds all nodes in the body that match the given filter function.
157
+
158
+ Args:
159
+ func: A callable that takes a BaseAstNode and returns True if it matches the criteria.
160
+
161
+ Returns:
162
+ A list of all matching nodes, or an empty list if no nodes match or the body is empty.
163
+ """
164
+ if len(self.body) == 0:
165
+ return [] # type: ignore
166
+ return [i for i in self.body if predicate(i)]
167
+
168
+ def find_node_by_token(
169
+ self, token_type: TokenType
170
+ ) -> Optional["BaseAstNode"]:
171
+ """Finds the first node in the body with the specified token type.
172
+
173
+ Args:
174
+ token_type: The TokenType to search for.
175
+
176
+ Returns:
177
+ The first matching node, or None if no node matches or the body is empty.
178
+ """
179
+ return self.find_node(lambda n: n.kind == token_type)
180
+
181
+ def find_nodes_by_token(self, token_type: TokenType) -> list["BaseAstNode"]:
182
+ """Finds all nodes in the body with the specified token type.
183
+
184
+ Args:
185
+ token_type: The TokenType to search for.
186
+
187
+ Returns:
188
+ A list of all matching nodes, or an empty list if no nodes match or the body is empty.
189
+ """
190
+ return self.find_node_all(lambda n: n.kind == token_type)
191
+
192
+
193
+ @dataclass(kw_only=True)
194
+ class _DisableReprBody(BaseAstNode):
195
+ """Special class to disable representation of unnecessary node fields.
196
+
197
+ This class is used to prevent the 'body' field from being included in
198
+ string representations, which can be useful for preventing excessive
199
+ output during debugging or logging.
200
+
201
+ Attributes:
202
+ body: A mutable sequence of child AST nodes (not included in repr).
203
+ """
204
+
205
+ body: MutableSequence[BaseAstNode] = field(default_factory=list, repr=False)
206
+
207
+
208
+ @dataclass(kw_only=True)
209
+ class _DisableReprAcceptAndRetType(BaseAstNode):
210
+ """Special class to disable representation of type fields.
211
+
212
+ This class is used to prevent the 'accept_type' and 'ret_type' fields
213
+ from being included in string representations, which can help reduce
214
+ verbosity in debugging or logging output.
215
+
216
+ Attributes:
217
+ accept_type: The variable type that this node accepts as input (not included in repr).
218
+ ret_type: The variable type that this node returns (not included in repr).
219
+ """
220
+
221
+ accept_type: VariableType = field(default=VariableType.ANY, repr=False)
222
+ ret_type: VariableType = field(default=VariableType.ANY, repr=False)
223
+
224
+
225
+ @dataclass(kw_only=True)
226
+ class _DisableRepr(_DisableReprBody, _DisableReprAcceptAndRetType):
227
+ """Special class to disable representation of multiple node fields.
228
+
229
+ This class combines the functionality of _DisableReprBody and
230
+ _DisableReprAcceptAndRetType to prevent the 'body', 'accept_type',
231
+ and 'ret_type' fields from being included in string representations.
232
+ This provides a more concise output for debugging and logging.
233
+
234
+ Attributes:
235
+ body: A mutable sequence of child AST nodes (not included in repr).
236
+ accept_type: The variable type that this node accepts as input (not included in repr).
237
+ ret_type: The variable type that this node returns (not included in repr).
238
+ """
239
+
240
+ body: MutableSequence[BaseAstNode] = field(default_factory=list, repr=False)
241
+ accept_type: VariableType = field(default=VariableType.ANY, repr=False)
242
+ ret_type: VariableType = field(default=VariableType.ANY, repr=False)
@@ -10,6 +10,23 @@ ARGS_EXPR_INDEX = tuple[int]
10
10
 
11
11
  @dataclass(kw_only=True)
12
12
  class ExprIndex(BaseAstNode[KW_EXPR_INDEX, ARGS_EXPR_INDEX]):
13
+ """AST node representing an index access expression.
14
+
15
+ This node represents an operation that accesses an element at a specific index
16
+ in a list of any type.
17
+
18
+ Rules:
19
+ - first index starts from `0`. if target language index starts by `1`,
20
+ codegen should be automatically convert
21
+ - allow use negative indexes: last index starts by `-1`.
22
+ codegen should be automatically convert by (len(curr_value)-{index})
23
+ Note:
24
+ - if target html parser backend support pseudo selectors - recommended use it instead extract by index
25
+
26
+ Kwargs:
27
+ "index": int - index where need extract variable
28
+ """
29
+
13
30
  kind: ClassVar[TokenType] = TokenType.EXPR_LIST_ANY_INDEX
14
31
  accept_type: VariableType = VariableType.LIST_ANY
15
32
  ret_type: VariableType = VariableType.ANY
@@ -21,6 +38,15 @@ ARGS_EXPR_JOIN = tuple[str]
21
38
 
22
39
  @dataclass(kw_only=True)
23
40
  class ExprListStringJoin(BaseAstNode[KW_EXPR_JOIN, ARGS_EXPR_JOIN]):
41
+ """AST node representing a string join operation on a list of strings.
42
+
43
+ This node represents an operation that joins a list of strings using a
44
+ specified separator.
45
+
46
+ Kwargs:
47
+ "sep": str - separator for array of strings
48
+ """
49
+
24
50
  kind: ClassVar[TokenType] = TokenType.EXPR_LIST_JOIN
25
51
  accept_type: VariableType = VariableType.LIST_STRING
26
52
  ret_type: VariableType = VariableType.STRING
@@ -28,6 +54,11 @@ class ExprListStringJoin(BaseAstNode[KW_EXPR_JOIN, ARGS_EXPR_JOIN]):
28
54
 
29
55
  @dataclass(kw_only=True)
30
56
  class ExprToListLength(BaseAstNode[T_EMPTY_KWARGS, tuple]):
57
+ """AST node representing a list length operation.
58
+
59
+ This node represents an operation that returns the length of a list.
60
+ """
61
+
31
62
  kind: ClassVar[TokenType] = TokenType.EXPR_LIST_LEN
32
63
  accept_type: VariableType = VariableType.LIST_ANY
33
64
  ret_type: VariableType = VariableType.INT
@@ -39,6 +70,17 @@ ARGS_UNIQUE = tuple[bool]
39
70
 
40
71
  @dataclass(kw_only=True)
41
72
  class ExprListUnique(BaseAstNode[KW_UNIQUE, ARGS_UNIQUE]):
73
+ """AST node representing a unique elements operation on a list.
74
+
75
+ This node represents an operation that removes duplicate elements from a list
76
+ of strings, optionally preserving the order of elements.
77
+ Note: Currently only supports LIST_STRING, but TODO indicates support for
78
+ LIST_INT and LIST_FLOAT should be added.
79
+
80
+ Kwargs:
81
+ - keep_order: bool - guarante save order elements
82
+ """
83
+
42
84
  # TODO: support LIST_INT, LIST_FLOAT
43
85
  kind: ClassVar[TokenType] = TokenType.EXPR_LIST_UNIQUE
44
86
  accept_type: VariableType = VariableType.LIST_STRING
@@ -10,6 +10,11 @@ if TYPE_CHECKING:
10
10
 
11
11
  @dataclass(kw_only=True)
12
12
  class ExprToInt(BaseAstNode[T_EMPTY_KWARGS, tuple]):
13
+ """AST node representing an integer conversion expression.
14
+
15
+ This node represents an operation that converts a string value to an integer.
16
+ """
17
+
13
18
  kind: ClassVar[TokenType] = TokenType.TO_INT
14
19
  accept_type: VariableType = VariableType.STRING
15
20
  ret_type: VariableType = VariableType.INT
@@ -17,6 +22,11 @@ class ExprToInt(BaseAstNode[T_EMPTY_KWARGS, tuple]):
17
22
 
18
23
  @dataclass(kw_only=True)
19
24
  class ExprToListInt(BaseAstNode[T_EMPTY_KWARGS, tuple]):
25
+ """AST node representing a list of integers conversion expression.
26
+
27
+ This node represents an operation that converts a list of string values to a list of integers.
28
+ """
29
+
20
30
  kind: ClassVar[TokenType] = TokenType.TO_INT_LIST
21
31
  accept_type: VariableType = VariableType.LIST_STRING
22
32
  ret_type: VariableType = VariableType.LIST_INT
@@ -24,6 +34,11 @@ class ExprToListInt(BaseAstNode[T_EMPTY_KWARGS, tuple]):
24
34
 
25
35
  @dataclass(kw_only=True)
26
36
  class ExprToFloat(BaseAstNode[T_EMPTY_KWARGS, tuple]):
37
+ """AST node representing a float conversion expression.
38
+
39
+ This node represents an operation that converts a string value to a float.
40
+ """
41
+
27
42
  kind: ClassVar[TokenType] = TokenType.TO_FLOAT
28
43
  accept_type: VariableType = VariableType.STRING
29
44
  ret_type: VariableType = VariableType.FLOAT
@@ -31,6 +46,11 @@ class ExprToFloat(BaseAstNode[T_EMPTY_KWARGS, tuple]):
31
46
 
32
47
  @dataclass(kw_only=True)
33
48
  class ExprToListFloat(BaseAstNode[T_EMPTY_KWARGS, tuple]):
49
+ """AST node representing a list of floats conversion expression.
50
+
51
+ This node represents an operation that converts a list of string values to a list of floats.
52
+ """
53
+
34
54
  kind: ClassVar[TokenType] = TokenType.TO_FLOAT_LIST
35
55
  accept_type: VariableType = VariableType.LIST_STRING
36
56
  ret_type: VariableType = VariableType.LIST_FLOAT
@@ -38,6 +58,19 @@ class ExprToListFloat(BaseAstNode[T_EMPTY_KWARGS, tuple]):
38
58
 
39
59
  @dataclass(kw_only=True)
40
60
  class ExprToBool(BaseAstNode[T_EMPTY_KWARGS, tuple]):
61
+ """AST node representing a boolean conversion expression.
62
+
63
+ This node represents an operation that converts any value to a boolean.
64
+ Currently cast to bool logic:
65
+
66
+ returns `false` if value is:
67
+ - None
68
+ - empty sequence
69
+ - empty string
70
+
71
+ Other returns `true`
72
+ """
73
+
41
74
  kind: ClassVar[TokenType] = TokenType.TO_BOOL
42
75
  accept_type: VariableType = VariableType.ANY
43
76
  ret_type: VariableType = VariableType.BOOL
@@ -52,6 +85,17 @@ EXPR_NESTED_ARGS = tuple[str, StructType]
52
85
 
53
86
  @dataclass(kw_only=True)
54
87
  class ExprNested(BaseAstNode[KW_EXPR_NESTED, EXPR_NESTED_ARGS]):
88
+ """AST node representing a nested structure expression.
89
+
90
+ This node represents an operation that processes nested structures,
91
+ using a schema name and structure type to determine how to handle
92
+ the nested data.
93
+
94
+ Kwargs:
95
+ "schema_name": str - called nested schema name
96
+ "schema_type": StructType - called nested schema StructType
97
+ """
98
+
55
99
  kind: ClassVar[TokenType] = TokenType.EXPR_NESTED
56
100
  accept_type: VariableType = VariableType.DOCUMENT
57
101
  ret_type: VariableType = VariableType.NESTED
@@ -65,6 +109,19 @@ ARGS_EXPR_JSONIFY = tuple[str, bool, str]
65
109
 
66
110
  @dataclass(kw_only=True)
67
111
  class ExprJsonify(BaseAstNode[KW_EXPR_JSONIFY, ARGS_EXPR_JSONIFY]):
112
+ """AST node representing a JSON conversion expression.
113
+
114
+ This node represents an operation that converts a string to JSON format,
115
+ using a JSON structure name, array flag, and query to determine how to
116
+ structure the resulting JSON.
117
+
118
+ Kwargs:
119
+ "json_struct_name": str - json struct name
120
+ "is_array": bool - true if entrypoint array of structs
121
+ "query": str - optional query syntax where need start parse and serialize raw json data
122
+ maybe useful for skip non-nessesary data (eg: NEST.js states)
123
+ """
124
+
68
125
  kind: ClassVar[TokenType] = TokenType.TO_JSON
69
126
  accept_type: VariableType = VariableType.STRING
70
127
  ret_type: VariableType = VariableType.JSON
@@ -78,6 +135,20 @@ ARGS_EXPR_JSONIFY_DYNAMIC = tuple[str]
78
135
  class ExprJsonifyDynamic(
79
136
  BaseAstNode[KW_EXPR_JSONIFY_DYNAMIC, ARGS_EXPR_JSONIFY_DYNAMIC]
80
137
  ):
138
+ """AST node representing a dynamic JSON conversion expression.
139
+
140
+ This node represents an operation that dynamically converts a string to JSON format,
141
+ using a query to determine how to structure the resulting JSON. The return type
142
+ is currently stubbed to ANY.
143
+
144
+ NOTE:
145
+ maybe not supports in static-typed languages
146
+
147
+ Kwargs:
148
+ "query": str - optional query syntax where need start parse and serialize raw json data
149
+ maybe useful for skip non-nessesary data (eg: NEST.js states)
150
+ """
151
+
81
152
  kind: ClassVar[TokenType] = TokenType.TO_JSON_DYNAMIC
82
153
  accept_type: VariableType = VariableType.STRING
83
154
  ret_type: VariableType = VariableType.ANY # STUBBED