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.
- {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/PKG-INFO +2 -3
- {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/README.md +1 -1
- {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/pyproject.toml +3 -2
- {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/__init__.py +1 -1
- ssc_codegen-0.13.0/ssc_codegen/ast_/base.py +242 -0
- {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/ast_/nodes_array.py +42 -0
- {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/ast_/nodes_cast.py +71 -0
- ssc_codegen-0.13.0/ssc_codegen/ast_/nodes_core.py +553 -0
- ssc_codegen-0.13.0/ssc_codegen/ast_/nodes_filter.py +659 -0
- ssc_codegen-0.13.0/ssc_codegen/ast_/nodes_selectors.py +305 -0
- ssc_codegen-0.13.0/ssc_codegen/ast_/nodes_string.py +495 -0
- ssc_codegen-0.13.0/ssc_codegen/ast_/nodes_validate.py +207 -0
- {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/cli/main.py +1 -1
- {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/converters/go_goquery.py +53 -29
- {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/converters/js_pure.py +126 -51
- {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/converters/lua_htmlparser.py +18 -18
- {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/converters/py_base.py +21 -24
- {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/converters/py_bs4.py +19 -7
- {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/converters/py_lxml.py +27 -8
- {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/converters/py_parsel.py +28 -11
- {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/converters/py_selectolax.py +21 -9
- {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/converters/templates/go_goquery.py +34 -1
- ssc_codegen-0.13.0/ssc_codegen/converters/templates/js_pure.py +38 -0
- {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/document.py +234 -29
- {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/tokens.py +0 -1
- ssc_codegen-0.12.0/ssc_codegen/ast_/base.py +0 -135
- ssc_codegen-0.12.0/ssc_codegen/ast_/nodes_core.py +0 -304
- ssc_codegen-0.12.0/ssc_codegen/ast_/nodes_filter.py +0 -285
- ssc_codegen-0.12.0/ssc_codegen/ast_/nodes_selectors.py +0 -118
- ssc_codegen-0.12.0/ssc_codegen/ast_/nodes_string.py +0 -236
- ssc_codegen-0.12.0/ssc_codegen/ast_/nodes_validate.py +0 -122
- ssc_codegen-0.12.0/ssc_codegen/converters/templates/js_pure.py +0 -135
- {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/.gitignore +0 -0
- {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/LICENSE +0 -0
- {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/_compat.py +0 -0
- {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/ast_/__init__.py +0 -0
- {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/ast_build/__init__.py +0 -0
- {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/ast_build/builder.py +0 -0
- {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/ast_build/main.py +0 -0
- {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/ast_build/utils.py +0 -0
- {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/ast_grep_rules/js_rules.yml +0 -0
- {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/ast_grep_rules/py_rules.yml +0 -0
- {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/cli/__init__.py +0 -0
- {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/cli/ast_grep.py +0 -0
- {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/cli/cli_callbacks.py +0 -0
- {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/cli/cli_utils.py +0 -0
- {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/cli/code_callbacks.py +0 -0
- {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/cli/consts.py +0 -0
- {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/cli/runtime_parse_runners.py +0 -0
- {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/compiler.py +0 -0
- {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/converters/__init__.py +0 -0
- {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/converters/base.py +0 -0
- {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/converters/helpers.py +0 -0
- {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/converters/templates/__init__.py +0 -0
- {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/converters/templates/lua_base.py +0 -0
- {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/converters/templates/lua_css_compat.py +0 -0
- {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/converters/templates/lua_re_compat.py +0 -0
- {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/converters/templates/py_base.py +0 -0
- {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/document_utlis.py +0 -0
- {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/json_struct.py +0 -0
- {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/json_to_scc.py +0 -0
- {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/logs.py +0 -0
- {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/pseudo_selectors.py +0 -0
- {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/schema.py +0 -0
- {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/selector_utils.py +0 -0
- {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/static_checker/__init__.py +0 -0
- {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/static_checker/base.py +0 -0
- {ssc_codegen-0.12.0 → ssc_codegen-0.13.0}/ssc_codegen/static_checker/callbacks.py +0 -0
- {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.
|
|
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 |
|
|
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 |
|
|
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.
|
|
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 = [
|
|
@@ -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
|