ssc_codegen 0.7.7__tar.gz → 0.8.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.
Potentially problematic release.
This version of ssc_codegen might be problematic. Click here for more details.
- {ssc_codegen-0.7.7 → ssc_codegen-0.8.0}/PKG-INFO +32 -30
- {ssc_codegen-0.7.7 → ssc_codegen-0.8.0}/README.md +29 -29
- {ssc_codegen-0.7.7 → ssc_codegen-0.8.0}/pyproject.toml +3 -1
- {ssc_codegen-0.7.7 → ssc_codegen-0.8.0}/ssc_codegen/__init__.py +15 -8
- ssc_codegen-0.8.0/ssc_codegen/ast_/__init__.py +32 -0
- ssc_codegen-0.8.0/ssc_codegen/ast_/base.py +88 -0
- ssc_codegen-0.8.0/ssc_codegen/ast_/nodes_array.py +33 -0
- ssc_codegen-0.8.0/ssc_codegen/ast_/nodes_cast.py +70 -0
- ssc_codegen-0.8.0/ssc_codegen/ast_/nodes_core.py +234 -0
- ssc_codegen-0.8.0/ssc_codegen/ast_/nodes_selectors.py +82 -0
- ssc_codegen-0.8.0/ssc_codegen/ast_/nodes_string.py +194 -0
- ssc_codegen-0.8.0/ssc_codegen/ast_/nodes_validate.py +90 -0
- ssc_codegen-0.8.0/ssc_codegen/ast_build/__init__.py +1 -0
- ssc_codegen-0.8.0/ssc_codegen/ast_build/main.py +339 -0
- ssc_codegen-0.8.0/ssc_codegen/ast_build/utils.py +96 -0
- {ssc_codegen-0.7.7 → ssc_codegen-0.8.0}/ssc_codegen/cli/cli_utils.py +4 -12
- {ssc_codegen-0.7.7 → ssc_codegen-0.8.0}/ssc_codegen/cli/consts.py +0 -6
- {ssc_codegen-0.7.7 → ssc_codegen-0.8.0}/ssc_codegen/cli/main.py +52 -99
- {ssc_codegen-0.7.7 → ssc_codegen-0.8.0}/ssc_codegen/cli/runtime_parse_runners.py +1 -1
- {ssc_codegen-0.7.7 → ssc_codegen-0.8.0}/ssc_codegen/compiler.py +2 -2
- {ssc_codegen-0.7.7 → ssc_codegen-0.8.0}/ssc_codegen/consts.py +6 -0
- ssc_codegen-0.8.0/ssc_codegen/converters/__init__.py +0 -0
- ssc_codegen-0.8.0/ssc_codegen/converters/base.py +265 -0
- ssc_codegen-0.8.0/ssc_codegen/converters/go_goquery.py +1204 -0
- ssc_codegen-0.8.0/ssc_codegen/converters/helpers.py +49 -0
- ssc_codegen-0.8.0/ssc_codegen/converters/js_pure.py +641 -0
- ssc_codegen-0.8.0/ssc_codegen/converters/py_base.py +841 -0
- ssc_codegen-0.8.0/ssc_codegen/converters/py_bs4.py +189 -0
- ssc_codegen-0.8.0/ssc_codegen/converters/py_parsel.py +200 -0
- ssc_codegen-0.8.0/ssc_codegen/converters/py_selectolax.py +187 -0
- ssc_codegen-0.8.0/ssc_codegen/converters/templates/__init__.py +3 -0
- ssc_codegen-0.8.0/ssc_codegen/converters/templates/go_goquery.py +411 -0
- ssc_codegen-0.8.0/ssc_codegen/converters/templates/js_pure.py +102 -0
- ssc_codegen-0.8.0/ssc_codegen/document.py +1110 -0
- {ssc_codegen-0.7.7 → ssc_codegen-0.8.0}/ssc_codegen/document_utlis.py +58 -44
- ssc_codegen-0.8.0/ssc_codegen/json_struct.py +162 -0
- ssc_codegen-0.7.7/ssc_codegen/converters/json_to_schema.py → ssc_codegen-0.8.0/ssc_codegen/json_to_scc.py +1 -1
- ssc_codegen-0.8.0/ssc_codegen/logs.py +49 -0
- {ssc_codegen-0.7.7 → ssc_codegen-0.8.0}/ssc_codegen/schema.py +13 -10
- ssc_codegen-0.8.0/ssc_codegen/static_checker/__init__.py +56 -0
- ssc_codegen-0.8.0/ssc_codegen/static_checker/base.py +88 -0
- ssc_codegen-0.8.0/ssc_codegen/static_checker/callbacks.py +363 -0
- {ssc_codegen-0.7.7 → ssc_codegen-0.8.0}/ssc_codegen/str_utils.py +17 -2
- {ssc_codegen-0.7.7 → ssc_codegen-0.8.0}/ssc_codegen/tokens.py +42 -9
- ssc_codegen-0.7.7/ssc_codegen/ast_build_utils.py +0 -259
- ssc_codegen-0.7.7/ssc_codegen/ast_builder.py +0 -336
- ssc_codegen-0.7.7/ssc_codegen/ast_ssc.py +0 -1326
- ssc_codegen-0.7.7/ssc_codegen/converters/__init__.py +0 -1
- ssc_codegen-0.7.7/ssc_codegen/converters/ast_utils.py +0 -70
- ssc_codegen-0.7.7/ssc_codegen/converters/base.py +0 -287
- ssc_codegen-0.7.7/ssc_codegen/converters/dart_universal_html.py +0 -563
- ssc_codegen-0.7.7/ssc_codegen/converters/go_goquery.py +0 -803
- ssc_codegen-0.7.7/ssc_codegen/converters/js_pure.py +0 -489
- ssc_codegen-0.7.7/ssc_codegen/converters/py_base.py +0 -583
- ssc_codegen-0.7.7/ssc_codegen/converters/py_bs4.py +0 -223
- ssc_codegen-0.7.7/ssc_codegen/converters/py_parsel.py +0 -224
- ssc_codegen-0.7.7/ssc_codegen/converters/py_scrapy.py +0 -219
- ssc_codegen-0.7.7/ssc_codegen/converters/py_selectolax.py +0 -192
- ssc_codegen-0.7.7/ssc_codegen/converters/templates/dart.py +0 -340
- ssc_codegen-0.7.7/ssc_codegen/converters/templates/go.py +0 -987
- ssc_codegen-0.7.7/ssc_codegen/converters/templates/js.py +0 -284
- ssc_codegen-0.7.7/ssc_codegen/converters/templates/py.py +0 -237
- ssc_codegen-0.7.7/ssc_codegen/converters/templates/template_bindings.py +0 -99
- ssc_codegen-0.7.7/ssc_codegen/document.py +0 -804
- ssc_codegen-0.7.7/ssc_codegen/json_struct.py +0 -176
- {ssc_codegen-0.7.7 → ssc_codegen-0.8.0}/.gitignore +0 -0
- {ssc_codegen-0.7.7 → ssc_codegen-0.8.0}/LICENSE +0 -0
- {ssc_codegen-0.7.7 → ssc_codegen-0.8.0}/ssc_codegen/_compat.py +0 -0
- {ssc_codegen-0.7.7 → ssc_codegen-0.8.0}/ssc_codegen/cli/__init__.py +0 -0
- {ssc_codegen-0.7.7 → ssc_codegen-0.8.0}/ssc_codegen/cli/cli_callbacks.py +0 -0
- {ssc_codegen-0.7.7 → ssc_codegen-0.8.0}/ssc_codegen/cli/code_callbacks.py +0 -0
- {ssc_codegen-0.7.7 → ssc_codegen-0.8.0}/ssc_codegen/selector_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.8.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
|
|
@@ -19,9 +19,11 @@ Classifier: Topic :: Software Development :: Code Generators
|
|
|
19
19
|
Classifier: Topic :: Text Processing :: Markup :: HTML
|
|
20
20
|
Classifier: Topic :: Utilities
|
|
21
21
|
Requires-Python: >=3.10
|
|
22
|
+
Requires-Dist: colorama>=0.4.6; sys_platform == 'win32'
|
|
22
23
|
Requires-Dist: cssselect>=1.2.0
|
|
23
24
|
Requires-Dist: httpx>=0.28.1
|
|
24
25
|
Requires-Dist: ichrome>=4.0.4
|
|
26
|
+
Requires-Dist: jinja2>=3.1.6
|
|
25
27
|
Requires-Dist: lxml>=5.3.0
|
|
26
28
|
Requires-Dist: parsel>=1.10.0
|
|
27
29
|
Requires-Dist: typer>=0.15.1
|
|
@@ -32,12 +34,12 @@ Description-Content-Type: text/markdown
|
|
|
32
34
|
|
|
33
35
|
## Introduction
|
|
34
36
|
|
|
35
|
-
ssc-gen - based-python DSL language for writing html parsers in dataclass style for
|
|
37
|
+
ssc-gen - based-python DSL language for writing html parsers in dataclass style for translating to targeting language.
|
|
36
38
|
|
|
37
39
|
Project solving next problems:
|
|
38
40
|
|
|
39
|
-
- boilerplate code
|
|
40
|
-
- create types (type annotations) and documentation
|
|
41
|
+
- decrease boilerplate code
|
|
42
|
+
- create types (or type annotations if possible) and documentation
|
|
41
43
|
- simplify code support
|
|
42
44
|
- portability to other languages
|
|
43
45
|
|
|
@@ -45,30 +47,28 @@ Project solving next problems:
|
|
|
45
47
|
|
|
46
48
|
Current support converters
|
|
47
49
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
|
52
|
-
| ... |
|
|
53
|
-
|
|
|
54
|
-
|
|
|
55
|
-
| Dart (3) | universal_html | N | Y | record, List, Map | dart format |
|
|
56
|
-
| js (ES6) | pure (firefox/chrome) | Y | Y | Array, Map** | - |
|
|
57
|
-
| go (1.10+) | goquery | N | Y | struct(json anchors include), array, map | gofmt |
|
|
50
|
+
| Language | Library (html parser backend) | XPath Support | CSS Support | Generated types | Code formatter |
|
|
51
|
+
|---------------|-------------------------------|---------------|-------------|------------------------------------------|----------------|
|
|
52
|
+
| Python (3.8+) | bs4 | N | Y | TypedDict*, list, dict | ruff |
|
|
53
|
+
| ... | parsel | Y | Y | ... | - |
|
|
54
|
+
| ... | selectolax (modest) | N | Y | ... | - |
|
|
55
|
+
| js (ES6) | pure (firefox/chrome/nodejs) | Y | Y | Array, Map** | - |
|
|
56
|
+
| go (1.10+) | goquery | N | Y | struct(json anchors include), array, map | gofmt |
|
|
58
57
|
|
|
59
58
|
- *this annotation type was deliberately chosen as a compromise reasons.
|
|
60
|
-
Python has many ways of serialization: `
|
|
59
|
+
Python has many ways of serialization: `namedtuple, dataclass, attrs, pydantic, msgspec, etc`
|
|
61
60
|
- TypedDict is like a build-in dict, but with IDE and linter hint support, and you can easily implement an adapter for the required structure.
|
|
62
|
-
- **js
|
|
61
|
+
- **js exclude build-in serialization methods
|
|
63
62
|
|
|
64
63
|
### Limitations
|
|
65
64
|
|
|
66
65
|
For maximum portability of the configuration to the target language:
|
|
67
66
|
|
|
68
67
|
- Use CSS selectors: they are guaranteed to be converted to XPATH
|
|
69
|
-
- Unlike javascript, most html parse libs implement [CSS3 selectors standard](https://www.w3.org/TR/selectors-3/)
|
|
70
|
-
|
|
71
|
-
-
|
|
68
|
+
- Unlike javascript, most html parse libs implement [CSS3 selectors standard](https://www.w3.org/TR/selectors-3/).
|
|
69
|
+
check in target lib complex selectors before implement:
|
|
70
|
+
- basic selectors: (`tag`, `.class`, `#id`, `tag1,tag2`)
|
|
71
|
+
- combined: (`div p`, `ul > li`, `h2 +p`, `title ~head`\[1])
|
|
72
72
|
- attribute: (`a[href]`, `input[type='text']`)\[2]
|
|
73
73
|
- pseudo classes: (`:nth-child(n)`, `:first-child`, `:last-child`)\[3]
|
|
74
74
|
- **often, not support more complex, dynamic styles**: (`:has()`, `:nth-of-type()`, `:where()`, `:is()`)
|
|
@@ -177,15 +177,14 @@ Code output looks like this (code formatted by IDE):
|
|
|
177
177
|
|
|
178
178
|
```javascript
|
|
179
179
|
// autogenerated by ssc-gen DO NOT_EDIT
|
|
180
|
-
|
|
181
|
-
*
|
|
180
|
+
/***
|
|
182
181
|
*
|
|
183
182
|
* {
|
|
184
183
|
* "title": "String",
|
|
185
184
|
* "a_hrefs": "Array<String>"
|
|
186
|
-
* }
|
|
187
|
-
*/
|
|
185
|
+
* }*/
|
|
188
186
|
class HelloWorld {
|
|
187
|
+
|
|
189
188
|
constructor(doc) {
|
|
190
189
|
if (typeof doc === 'string') {
|
|
191
190
|
this._doc = new DOMParser().parseFromString(doc, 'text/html');
|
|
@@ -196,18 +195,21 @@ class HelloWorld {
|
|
|
196
195
|
}
|
|
197
196
|
}
|
|
198
197
|
|
|
199
|
-
_parseTitle(
|
|
200
|
-
let
|
|
201
|
-
return typeof
|
|
198
|
+
_parseTitle(v) {
|
|
199
|
+
let v0 = v.querySelector('title');
|
|
200
|
+
return typeof v0.textContent === "undefined" ? v0.documentElement.textContent : v0.textContent;
|
|
202
201
|
}
|
|
203
202
|
|
|
204
|
-
_parseAHrefs(
|
|
205
|
-
let
|
|
206
|
-
return
|
|
203
|
+
_parseAHrefs(v) {
|
|
204
|
+
let v0 = Array.from(v.querySelectorAll('a'));
|
|
205
|
+
return v0.map(e => e.getAttribute('href'));
|
|
207
206
|
}
|
|
208
207
|
|
|
209
208
|
parse() {
|
|
210
|
-
return {
|
|
209
|
+
return {
|
|
210
|
+
title: this._parseTitle(this._doc),
|
|
211
|
+
a_hrefs: this._parseAHrefs(this._doc),
|
|
212
|
+
};
|
|
211
213
|
}
|
|
212
214
|
}
|
|
213
215
|
```
|
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
## Introduction
|
|
4
4
|
|
|
5
|
-
ssc-gen - based-python DSL language for writing html parsers in dataclass style for
|
|
5
|
+
ssc-gen - based-python DSL language for writing html parsers in dataclass style for translating to targeting language.
|
|
6
6
|
|
|
7
7
|
Project solving next problems:
|
|
8
8
|
|
|
9
|
-
- boilerplate code
|
|
10
|
-
- create types (type annotations) and documentation
|
|
9
|
+
- decrease boilerplate code
|
|
10
|
+
- create types (or type annotations if possible) and documentation
|
|
11
11
|
- simplify code support
|
|
12
12
|
- portability to other languages
|
|
13
13
|
|
|
@@ -15,30 +15,28 @@ Project solving next problems:
|
|
|
15
15
|
|
|
16
16
|
Current support converters
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
|
22
|
-
| ... |
|
|
23
|
-
|
|
|
24
|
-
|
|
|
25
|
-
| Dart (3) | universal_html | N | Y | record, List, Map | dart format |
|
|
26
|
-
| js (ES6) | pure (firefox/chrome) | Y | Y | Array, Map** | - |
|
|
27
|
-
| go (1.10+) | goquery | N | Y | struct(json anchors include), array, map | gofmt |
|
|
18
|
+
| Language | Library (html parser backend) | XPath Support | CSS Support | Generated types | Code formatter |
|
|
19
|
+
|---------------|-------------------------------|---------------|-------------|------------------------------------------|----------------|
|
|
20
|
+
| Python (3.8+) | bs4 | N | Y | TypedDict*, list, dict | ruff |
|
|
21
|
+
| ... | parsel | Y | Y | ... | - |
|
|
22
|
+
| ... | selectolax (modest) | N | Y | ... | - |
|
|
23
|
+
| js (ES6) | pure (firefox/chrome/nodejs) | Y | Y | Array, Map** | - |
|
|
24
|
+
| go (1.10+) | goquery | N | Y | struct(json anchors include), array, map | gofmt |
|
|
28
25
|
|
|
29
26
|
- *this annotation type was deliberately chosen as a compromise reasons.
|
|
30
|
-
Python has many ways of serialization: `
|
|
27
|
+
Python has many ways of serialization: `namedtuple, dataclass, attrs, pydantic, msgspec, etc`
|
|
31
28
|
- TypedDict is like a build-in dict, but with IDE and linter hint support, and you can easily implement an adapter for the required structure.
|
|
32
|
-
- **js
|
|
29
|
+
- **js exclude build-in serialization methods
|
|
33
30
|
|
|
34
31
|
### Limitations
|
|
35
32
|
|
|
36
33
|
For maximum portability of the configuration to the target language:
|
|
37
34
|
|
|
38
35
|
- Use CSS selectors: they are guaranteed to be converted to XPATH
|
|
39
|
-
- Unlike javascript, most html parse libs implement [CSS3 selectors standard](https://www.w3.org/TR/selectors-3/)
|
|
40
|
-
|
|
41
|
-
-
|
|
36
|
+
- Unlike javascript, most html parse libs implement [CSS3 selectors standard](https://www.w3.org/TR/selectors-3/).
|
|
37
|
+
check in target lib complex selectors before implement:
|
|
38
|
+
- basic selectors: (`tag`, `.class`, `#id`, `tag1,tag2`)
|
|
39
|
+
- combined: (`div p`, `ul > li`, `h2 +p`, `title ~head`\[1])
|
|
42
40
|
- attribute: (`a[href]`, `input[type='text']`)\[2]
|
|
43
41
|
- pseudo classes: (`:nth-child(n)`, `:first-child`, `:last-child`)\[3]
|
|
44
42
|
- **often, not support more complex, dynamic styles**: (`:has()`, `:nth-of-type()`, `:where()`, `:is()`)
|
|
@@ -147,15 +145,14 @@ Code output looks like this (code formatted by IDE):
|
|
|
147
145
|
|
|
148
146
|
```javascript
|
|
149
147
|
// autogenerated by ssc-gen DO NOT_EDIT
|
|
150
|
-
|
|
151
|
-
*
|
|
148
|
+
/***
|
|
152
149
|
*
|
|
153
150
|
* {
|
|
154
151
|
* "title": "String",
|
|
155
152
|
* "a_hrefs": "Array<String>"
|
|
156
|
-
* }
|
|
157
|
-
*/
|
|
153
|
+
* }*/
|
|
158
154
|
class HelloWorld {
|
|
155
|
+
|
|
159
156
|
constructor(doc) {
|
|
160
157
|
if (typeof doc === 'string') {
|
|
161
158
|
this._doc = new DOMParser().parseFromString(doc, 'text/html');
|
|
@@ -166,18 +163,21 @@ class HelloWorld {
|
|
|
166
163
|
}
|
|
167
164
|
}
|
|
168
165
|
|
|
169
|
-
_parseTitle(
|
|
170
|
-
let
|
|
171
|
-
return typeof
|
|
166
|
+
_parseTitle(v) {
|
|
167
|
+
let v0 = v.querySelector('title');
|
|
168
|
+
return typeof v0.textContent === "undefined" ? v0.documentElement.textContent : v0.textContent;
|
|
172
169
|
}
|
|
173
170
|
|
|
174
|
-
_parseAHrefs(
|
|
175
|
-
let
|
|
176
|
-
return
|
|
171
|
+
_parseAHrefs(v) {
|
|
172
|
+
let v0 = Array.from(v.querySelectorAll('a'));
|
|
173
|
+
return v0.map(e => e.getAttribute('href'));
|
|
177
174
|
}
|
|
178
175
|
|
|
179
176
|
parse() {
|
|
180
|
-
return {
|
|
177
|
+
return {
|
|
178
|
+
title: this._parseTitle(this._doc),
|
|
179
|
+
a_hrefs: this._parseAHrefs(this._doc),
|
|
180
|
+
};
|
|
181
181
|
}
|
|
182
182
|
}
|
|
183
183
|
```
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "ssc_codegen"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.8.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"
|
|
7
7
|
dependencies = [
|
|
8
|
+
"colorama>=0.4.6 ; sys_platform == 'win32'",
|
|
8
9
|
"cssselect>=1.2.0",
|
|
9
10
|
"httpx>=0.28.1",
|
|
10
11
|
"ichrome>=4.0.4",
|
|
12
|
+
"jinja2>=3.1.6",
|
|
11
13
|
"lxml>=5.3.0",
|
|
12
14
|
"parsel>=1.10.0",
|
|
13
15
|
"typer>=0.15.1",
|
|
@@ -1,15 +1,22 @@
|
|
|
1
|
-
from .document import HTMLDocument, StringDocument, ArrayDocument, AssertDocument, NestedDocument,
|
|
1
|
+
from ssc_codegen.document import HTMLDocument, StringDocument, ArrayDocument, AssertDocument, NestedDocument, \
|
|
2
|
+
DefaultDocument, \
|
|
2
3
|
NumericDocument, JsonDocument, BooleanDocument
|
|
3
|
-
from .json_struct import Json
|
|
4
|
-
from .
|
|
4
|
+
from ssc_codegen.json_struct import Json
|
|
5
|
+
from ssc_codegen.logs import setup_logger
|
|
6
|
+
from ssc_codegen.schema import ItemSchema, DictSchema, ListSchema, FlatListSchema
|
|
7
|
+
|
|
8
|
+
setup_logger()
|
|
9
|
+
|
|
10
|
+
VERSION = "0.8.0"
|
|
5
11
|
|
|
6
|
-
VERSION = "0.7.7"
|
|
7
12
|
|
|
8
13
|
class __MISSING(object):
|
|
9
14
|
pass
|
|
10
15
|
|
|
16
|
+
|
|
11
17
|
_NO_DEFAULT = __MISSING()
|
|
12
18
|
|
|
19
|
+
|
|
13
20
|
class Document(
|
|
14
21
|
HTMLDocument,
|
|
15
22
|
StringDocument,
|
|
@@ -27,12 +34,12 @@ class Nested(HTMLDocument, NestedDocument, ArrayDocument, AssertDocument):
|
|
|
27
34
|
pass
|
|
28
35
|
|
|
29
36
|
|
|
30
|
-
def D(default: None | str | int | float | __MISSING =_NO_DEFAULT) -> Document: # noqa
|
|
37
|
+
def D(default: None | str | int | float | __MISSING = _NO_DEFAULT) -> Document: # noqa
|
|
31
38
|
"""Shortcut as a Document() object
|
|
32
39
|
|
|
33
40
|
:param default: .default() operator shortcut
|
|
34
41
|
"""
|
|
35
|
-
if default==_NO_DEFAULT:
|
|
42
|
+
if default == _NO_DEFAULT:
|
|
36
43
|
return Document()
|
|
37
44
|
return Document().default(value=default) # type: ignore
|
|
38
45
|
|
|
@@ -42,12 +49,12 @@ def N() -> Nested: # noqa
|
|
|
42
49
|
return Nested()
|
|
43
50
|
|
|
44
51
|
|
|
45
|
-
def R(default: None | str | int | float | __MISSING =_NO_DEFAULT) -> Document:
|
|
52
|
+
def R(default: None | str | int | float | __MISSING = _NO_DEFAULT) -> Document: # noqa
|
|
46
53
|
"""Shortcut as a Document().raw() object.
|
|
47
54
|
For regex and format string operations
|
|
48
55
|
|
|
49
56
|
:param default: .default() operator shortcut
|
|
50
57
|
"""
|
|
51
|
-
if default==_NO_DEFAULT:
|
|
58
|
+
if default == _NO_DEFAULT:
|
|
52
59
|
return Document().raw()
|
|
53
60
|
return Document().default(default).raw() # type: ignore
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
from .base import BaseAstNode
|
|
2
|
+
from .nodes_array import ExprIndex, ExprToListLength, ExprListStringJoin
|
|
3
|
+
from .nodes_cast import ExprNested, ExprJsonify, ExprToInt, ExprToFloat, ExprToListInt, ExprToListFloat, ExprToBool
|
|
4
|
+
from .nodes_core import (ExprReturn,
|
|
5
|
+
ExprNoReturn,
|
|
6
|
+
ExprDefaultValueEnd,
|
|
7
|
+
ExprDefaultValueStart,
|
|
8
|
+
ExprDefaultValueWrapper,
|
|
9
|
+
ModuleProgram,
|
|
10
|
+
Docstring,
|
|
11
|
+
ModuleImports,
|
|
12
|
+
StructInitMethod,
|
|
13
|
+
StructPreValidateMethod,
|
|
14
|
+
StructFieldMethod,
|
|
15
|
+
StructPartDocMethod,
|
|
16
|
+
StartParseMethod,
|
|
17
|
+
StructParser,
|
|
18
|
+
JsonStruct,
|
|
19
|
+
JsonStructField,
|
|
20
|
+
TypeDef,
|
|
21
|
+
TypeDefField,
|
|
22
|
+
ExprCallStructMethod)
|
|
23
|
+
from .nodes_selectors import ExprCss, ExprCssAll, ExprXpathAll, ExprXpath, ExprGetHtmlText, ExprGetHtmlRaw, \
|
|
24
|
+
ExprGetHtmlAttr, ExprGetHtmlAttrAll, ExprGetHtmlRawAll, ExprGetHtmlTextAll
|
|
25
|
+
|
|
26
|
+
from .nodes_string import ExprStringTrim, ExprStringRegex, ExprStringSplit, ExprStringReplace, ExprStringLeftTrim, \
|
|
27
|
+
ExprStringFormat, ExprListStringTrim, ExprStringRegexAll, ExprStringRegexSub, ExprStringRightTrim, \
|
|
28
|
+
ExprListStringFormat, ExprListStringReplace, ExprListStringRightTrim, ExprListStringLeftTrim, \
|
|
29
|
+
ExprListStringRegexSub, \
|
|
30
|
+
ExprStringRmPrefix, ExprStringRmSuffix, ExprStringRmPrefixAndSuffix, ExprListStringRmPrefixAndSuffix, \
|
|
31
|
+
ExprListStringRmPrefix, ExprListStringRmSuffix
|
|
32
|
+
from .nodes_validate import ExprIsCss, ExprIsEqual, ExprIsRegex, ExprIsXpath, ExprIsNotEqual, ExprIsContains
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
from dataclasses import dataclass, field
|
|
2
|
+
from typing import (
|
|
3
|
+
ClassVar,
|
|
4
|
+
Mapping,
|
|
5
|
+
TypeVar,
|
|
6
|
+
Generic,
|
|
7
|
+
Any,
|
|
8
|
+
TypedDict,
|
|
9
|
+
Optional,
|
|
10
|
+
MutableSequence,
|
|
11
|
+
Sequence,
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
from ssc_codegen.tokens import TokenType, VariableType
|
|
15
|
+
|
|
16
|
+
T_ARGUMENTS = TypeVar("T_ARGUMENTS")
|
|
17
|
+
T_MAPPING_FIELD = TypeVar("T_MAPPING_FIELD", bound=Mapping[str, Any])
|
|
18
|
+
T_EMPTY_KWARGS = TypedDict("T_EMPTY_KWARGS", {})
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@dataclass(kw_only=True)
|
|
22
|
+
class BaseAstNode(Generic[T_MAPPING_FIELD, T_ARGUMENTS]):
|
|
23
|
+
"""base AST container"""
|
|
24
|
+
|
|
25
|
+
kind: ClassVar[TokenType]
|
|
26
|
+
kwargs: T_MAPPING_FIELD = field(default_factory=dict) # type: ignore[assignment]
|
|
27
|
+
|
|
28
|
+
body: MutableSequence["BaseAstNode"] = field(default_factory=list)
|
|
29
|
+
parent: Optional["BaseAstNode"] = field(default=None, repr=False)
|
|
30
|
+
|
|
31
|
+
# used for type check expressions
|
|
32
|
+
accept_type: VariableType = VariableType.ANY
|
|
33
|
+
ret_type: VariableType = VariableType.ANY
|
|
34
|
+
exclude_types: Sequence[VariableType] = field(default_factory=tuple)
|
|
35
|
+
|
|
36
|
+
def unpack_args(self) -> T_ARGUMENTS:
|
|
37
|
+
"""extract all values from kwargs field wout keys"""
|
|
38
|
+
return tuple(self.kwargs.values()) # type: ignore
|
|
39
|
+
|
|
40
|
+
# todo: cached property?
|
|
41
|
+
@property
|
|
42
|
+
def index(self) -> int:
|
|
43
|
+
if self.parent:
|
|
44
|
+
return self.parent.body.index(self)
|
|
45
|
+
return -1
|
|
46
|
+
|
|
47
|
+
@property
|
|
48
|
+
def index_next(self) -> int:
|
|
49
|
+
if self.parent and len(self.parent.body) > self.index:
|
|
50
|
+
return self.index + 1
|
|
51
|
+
return -1
|
|
52
|
+
|
|
53
|
+
@property
|
|
54
|
+
def index_prev(self) -> int:
|
|
55
|
+
if self.parent and self.index == 0:
|
|
56
|
+
return -1
|
|
57
|
+
elif self.index == -1:
|
|
58
|
+
return -1
|
|
59
|
+
return self.index - 1
|
|
60
|
+
|
|
61
|
+
def __getattr__(self, name: str) -> Any:
|
|
62
|
+
# modify for provide extract argument from kwargs container (like property)
|
|
63
|
+
try:
|
|
64
|
+
return super().__getattribute__(name)
|
|
65
|
+
except AttributeError as e:
|
|
66
|
+
if self.kwargs.get(name):
|
|
67
|
+
return self.kwargs[name]
|
|
68
|
+
raise e
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
@dataclass(kw_only=True)
|
|
72
|
+
class _DisableReprBody(BaseAstNode):
|
|
73
|
+
"""special class for disable repr unnecessary node fields"""
|
|
74
|
+
|
|
75
|
+
body: MutableSequence[BaseAstNode] = field(default_factory=list, repr=False)
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
@dataclass(kw_only=True)
|
|
79
|
+
class _DisableReprAcceptAndRetType(BaseAstNode):
|
|
80
|
+
accept_type: VariableType = field(default=VariableType.ANY, repr=False)
|
|
81
|
+
ret_type: VariableType = field(default=VariableType.ANY, repr=False)
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
@dataclass(kw_only=True)
|
|
85
|
+
class _DisableRepr(_DisableReprBody, _DisableReprAcceptAndRetType):
|
|
86
|
+
body: MutableSequence[BaseAstNode] = field(default_factory=list, repr=False)
|
|
87
|
+
accept_type: VariableType = field(default=VariableType.ANY, repr=False)
|
|
88
|
+
ret_type: VariableType = field(default=VariableType.ANY, repr=False)
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
from typing import TypedDict, ClassVar
|
|
3
|
+
|
|
4
|
+
from ssc_codegen.ast_.base import BaseAstNode, T_EMPTY_KWARGS
|
|
5
|
+
from ssc_codegen.tokens import TokenType, VariableType
|
|
6
|
+
|
|
7
|
+
KW_EXPR_INDEX = TypedDict("KW_EXPR_INDEX", {"index": int})
|
|
8
|
+
ARGS_EXPR_INDEX = tuple[int]
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@dataclass(kw_only=True)
|
|
12
|
+
class ExprIndex(BaseAstNode[KW_EXPR_INDEX, ARGS_EXPR_INDEX]):
|
|
13
|
+
kind: ClassVar[TokenType] = TokenType.EXPR_LIST_ANY_INDEX
|
|
14
|
+
accept_type: VariableType = VariableType.LIST_ANY
|
|
15
|
+
ret_type: VariableType = VariableType.ANY
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
KW_EXPR_JOIN = TypedDict("KW_EXPR_JOIN", {"sep": str})
|
|
19
|
+
ARGS_EXPR_JOIN = tuple[str]
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@dataclass(kw_only=True)
|
|
23
|
+
class ExprListStringJoin(BaseAstNode[KW_EXPR_JOIN, ARGS_EXPR_JOIN]):
|
|
24
|
+
kind: ClassVar[TokenType] = TokenType.EXPR_LIST_JOIN
|
|
25
|
+
accept_type: VariableType = VariableType.LIST_STRING
|
|
26
|
+
ret_type: VariableType = VariableType.STRING
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
@dataclass(kw_only=True)
|
|
30
|
+
class ExprToListLength(BaseAstNode[T_EMPTY_KWARGS, tuple]):
|
|
31
|
+
kind: ClassVar[TokenType] = TokenType.EXPR_LIST_LEN
|
|
32
|
+
accept_type: VariableType = VariableType.LIST_ANY
|
|
33
|
+
ret_type: VariableType = VariableType.INT
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
from typing import TypedDict, Type, TYPE_CHECKING, TypeAlias, ClassVar
|
|
3
|
+
|
|
4
|
+
from ssc_codegen.tokens import TokenType, VariableType, StructType
|
|
5
|
+
from ssc_codegen.ast_.base import BaseAstNode, T_EMPTY_KWARGS
|
|
6
|
+
|
|
7
|
+
if TYPE_CHECKING:
|
|
8
|
+
from ssc_codegen.schema import BaseSchema
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@dataclass(kw_only=True)
|
|
12
|
+
class ExprToInt(BaseAstNode[T_EMPTY_KWARGS, tuple]):
|
|
13
|
+
kind: ClassVar[TokenType] = TokenType.TO_INT
|
|
14
|
+
accept_type: VariableType = VariableType.STRING
|
|
15
|
+
ret_type: VariableType = VariableType.INT
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@dataclass(kw_only=True)
|
|
19
|
+
class ExprToListInt(BaseAstNode[T_EMPTY_KWARGS, tuple]):
|
|
20
|
+
kind: ClassVar[TokenType] = TokenType.TO_INT_LIST
|
|
21
|
+
accept_type: VariableType = VariableType.LIST_STRING
|
|
22
|
+
ret_type: VariableType = VariableType.LIST_INT
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@dataclass(kw_only=True)
|
|
26
|
+
class ExprToFloat(BaseAstNode[T_EMPTY_KWARGS, tuple]):
|
|
27
|
+
kind: ClassVar[TokenType] = TokenType.TO_FLOAT
|
|
28
|
+
accept_type: VariableType = VariableType.STRING
|
|
29
|
+
ret_type: VariableType = VariableType.FLOAT
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
@dataclass(kw_only=True)
|
|
33
|
+
class ExprToListFloat(BaseAstNode[T_EMPTY_KWARGS, tuple]):
|
|
34
|
+
kind: ClassVar[TokenType] = TokenType.TO_FLOAT_LIST
|
|
35
|
+
accept_type: VariableType = VariableType.LIST_STRING
|
|
36
|
+
ret_type: VariableType = VariableType.LIST_FLOAT
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
@dataclass(kw_only=True)
|
|
40
|
+
class ExprToBool(BaseAstNode[T_EMPTY_KWARGS, tuple]):
|
|
41
|
+
kind: ClassVar[TokenType] = TokenType.TO_BOOL
|
|
42
|
+
accept_type: VariableType = VariableType.ANY
|
|
43
|
+
ret_type: VariableType = VariableType.BOOL
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
_T_SCHEMA: TypeAlias = Type["BaseSchema"]
|
|
47
|
+
KW_EXPR_NESTED = TypedDict(
|
|
48
|
+
"KW_EXPR_NESTED", {"schema_name": str, "schema_type": StructType}
|
|
49
|
+
)
|
|
50
|
+
EXPR_NESTED_ARGS = tuple[str, StructType]
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
@dataclass(kw_only=True)
|
|
54
|
+
class ExprNested(BaseAstNode[KW_EXPR_NESTED, EXPR_NESTED_ARGS]):
|
|
55
|
+
kind: ClassVar[TokenType] = TokenType.EXPR_NESTED
|
|
56
|
+
accept_type: VariableType = VariableType.DOCUMENT
|
|
57
|
+
ret_type: VariableType = VariableType.NESTED
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
KW_EXPR_JSONIFY = TypedDict(
|
|
61
|
+
"KW_EXPR_JSONIFY", {"json_struct_name": str, "is_array": bool}
|
|
62
|
+
)
|
|
63
|
+
ARGS_EXPR_JSONIFY = tuple[str, bool]
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
@dataclass(kw_only=True)
|
|
67
|
+
class ExprJsonify(BaseAstNode[KW_EXPR_JSONIFY, ARGS_EXPR_JSONIFY]):
|
|
68
|
+
kind: ClassVar[TokenType] = TokenType.TO_JSON
|
|
69
|
+
accept_type: VariableType = VariableType.STRING
|
|
70
|
+
ret_type: VariableType = VariableType.JSON
|