ssc_codegen 0.13.3__tar.gz → 0.14.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 (63) hide show
  1. {ssc_codegen-0.13.3 → ssc_codegen-0.14.0}/PKG-INFO +11 -12
  2. {ssc_codegen-0.13.3 → ssc_codegen-0.14.0}/README.md +10 -10
  3. {ssc_codegen-0.13.3 → ssc_codegen-0.14.0}/pyproject.toml +1 -2
  4. {ssc_codegen-0.13.3 → ssc_codegen-0.14.0}/ssc_codegen/__init__.py +1 -1
  5. {ssc_codegen-0.13.3 → ssc_codegen-0.14.0}/ssc_codegen/cli/code_callbacks.py +0 -2
  6. {ssc_codegen-0.13.3 → ssc_codegen-0.14.0}/ssc_codegen/cli/main.py +2 -4
  7. {ssc_codegen-0.13.3 → ssc_codegen-0.14.0}/ssc_codegen/converters/py_base.py +27 -27
  8. {ssc_codegen-0.13.3 → ssc_codegen-0.14.0}/ssc_codegen/converters/py_lxml.py +2 -3
  9. {ssc_codegen-0.13.3 → ssc_codegen-0.14.0}/ssc_codegen/converters/py_parsel.py +2 -2
  10. {ssc_codegen-0.13.3 → ssc_codegen-0.14.0}/ssc_codegen/converters/py_selectolax.py +1 -1
  11. {ssc_codegen-0.13.3 → ssc_codegen-0.14.0}/ssc_codegen/converters/templates/py_base.py +12 -5
  12. {ssc_codegen-0.13.3 → ssc_codegen-0.14.0}/.gitignore +0 -0
  13. {ssc_codegen-0.13.3 → ssc_codegen-0.14.0}/LICENSE +0 -0
  14. {ssc_codegen-0.13.3 → ssc_codegen-0.14.0}/ssc_codegen/_compat.py +0 -0
  15. {ssc_codegen-0.13.3 → ssc_codegen-0.14.0}/ssc_codegen/ast_/__init__.py +0 -0
  16. {ssc_codegen-0.13.3 → ssc_codegen-0.14.0}/ssc_codegen/ast_/base.py +0 -0
  17. {ssc_codegen-0.13.3 → ssc_codegen-0.14.0}/ssc_codegen/ast_/nodes_array.py +0 -0
  18. {ssc_codegen-0.13.3 → ssc_codegen-0.14.0}/ssc_codegen/ast_/nodes_cast.py +0 -0
  19. {ssc_codegen-0.13.3 → ssc_codegen-0.14.0}/ssc_codegen/ast_/nodes_core.py +0 -0
  20. {ssc_codegen-0.13.3 → ssc_codegen-0.14.0}/ssc_codegen/ast_/nodes_filter.py +0 -0
  21. {ssc_codegen-0.13.3 → ssc_codegen-0.14.0}/ssc_codegen/ast_/nodes_selectors.py +0 -0
  22. {ssc_codegen-0.13.3 → ssc_codegen-0.14.0}/ssc_codegen/ast_/nodes_string.py +0 -0
  23. {ssc_codegen-0.13.3 → ssc_codegen-0.14.0}/ssc_codegen/ast_/nodes_validate.py +0 -0
  24. {ssc_codegen-0.13.3 → ssc_codegen-0.14.0}/ssc_codegen/ast_build/__init__.py +0 -0
  25. {ssc_codegen-0.13.3 → ssc_codegen-0.14.0}/ssc_codegen/ast_build/builder.py +0 -0
  26. {ssc_codegen-0.13.3 → ssc_codegen-0.14.0}/ssc_codegen/ast_build/main.py +0 -0
  27. {ssc_codegen-0.13.3 → ssc_codegen-0.14.0}/ssc_codegen/ast_build/utils.py +0 -0
  28. {ssc_codegen-0.13.3 → ssc_codegen-0.14.0}/ssc_codegen/ast_grep_rules/js_rules.yml +0 -0
  29. {ssc_codegen-0.13.3 → ssc_codegen-0.14.0}/ssc_codegen/ast_grep_rules/py_drop_prefix_suffix_backport.yml +0 -0
  30. {ssc_codegen-0.13.3 → ssc_codegen-0.14.0}/ssc_codegen/ast_grep_rules/py_rules.yml +0 -0
  31. {ssc_codegen-0.13.3 → ssc_codegen-0.14.0}/ssc_codegen/cli/__init__.py +0 -0
  32. {ssc_codegen-0.13.3 → ssc_codegen-0.14.0}/ssc_codegen/cli/ast_grep.py +0 -0
  33. {ssc_codegen-0.13.3 → ssc_codegen-0.14.0}/ssc_codegen/cli/cli_callbacks.py +0 -0
  34. {ssc_codegen-0.13.3 → ssc_codegen-0.14.0}/ssc_codegen/cli/cli_utils.py +0 -0
  35. {ssc_codegen-0.13.3 → ssc_codegen-0.14.0}/ssc_codegen/cli/consts.py +0 -0
  36. {ssc_codegen-0.13.3 → ssc_codegen-0.14.0}/ssc_codegen/cli/runtime_parse_runners.py +0 -0
  37. {ssc_codegen-0.13.3 → ssc_codegen-0.14.0}/ssc_codegen/compiler.py +0 -0
  38. {ssc_codegen-0.13.3 → ssc_codegen-0.14.0}/ssc_codegen/converters/__init__.py +0 -0
  39. {ssc_codegen-0.13.3 → ssc_codegen-0.14.0}/ssc_codegen/converters/base.py +0 -0
  40. {ssc_codegen-0.13.3 → ssc_codegen-0.14.0}/ssc_codegen/converters/go_goquery.py +0 -0
  41. {ssc_codegen-0.13.3 → ssc_codegen-0.14.0}/ssc_codegen/converters/helpers.py +0 -0
  42. {ssc_codegen-0.13.3 → ssc_codegen-0.14.0}/ssc_codegen/converters/js_pure.py +0 -0
  43. {ssc_codegen-0.13.3 → ssc_codegen-0.14.0}/ssc_codegen/converters/lua_htmlparser.py +0 -0
  44. {ssc_codegen-0.13.3 → ssc_codegen-0.14.0}/ssc_codegen/converters/py_bs4.py +0 -0
  45. {ssc_codegen-0.13.3 → ssc_codegen-0.14.0}/ssc_codegen/converters/templates/__init__.py +0 -0
  46. {ssc_codegen-0.13.3 → ssc_codegen-0.14.0}/ssc_codegen/converters/templates/go_goquery.py +0 -0
  47. {ssc_codegen-0.13.3 → ssc_codegen-0.14.0}/ssc_codegen/converters/templates/js_pure.py +0 -0
  48. {ssc_codegen-0.13.3 → ssc_codegen-0.14.0}/ssc_codegen/converters/templates/lua_base.py +0 -0
  49. {ssc_codegen-0.13.3 → ssc_codegen-0.14.0}/ssc_codegen/converters/templates/lua_css_compat.py +0 -0
  50. {ssc_codegen-0.13.3 → ssc_codegen-0.14.0}/ssc_codegen/converters/templates/lua_re_compat.py +0 -0
  51. {ssc_codegen-0.13.3 → ssc_codegen-0.14.0}/ssc_codegen/document.py +0 -0
  52. {ssc_codegen-0.13.3 → ssc_codegen-0.14.0}/ssc_codegen/document_utlis.py +0 -0
  53. {ssc_codegen-0.13.3 → ssc_codegen-0.14.0}/ssc_codegen/json_struct.py +0 -0
  54. {ssc_codegen-0.13.3 → ssc_codegen-0.14.0}/ssc_codegen/json_to_scc.py +0 -0
  55. {ssc_codegen-0.13.3 → ssc_codegen-0.14.0}/ssc_codegen/logs.py +0 -0
  56. {ssc_codegen-0.13.3 → ssc_codegen-0.14.0}/ssc_codegen/pseudo_selectors.py +0 -0
  57. {ssc_codegen-0.13.3 → ssc_codegen-0.14.0}/ssc_codegen/schema.py +0 -0
  58. {ssc_codegen-0.13.3 → ssc_codegen-0.14.0}/ssc_codegen/selector_utils.py +0 -0
  59. {ssc_codegen-0.13.3 → ssc_codegen-0.14.0}/ssc_codegen/static_checker/__init__.py +0 -0
  60. {ssc_codegen-0.13.3 → ssc_codegen-0.14.0}/ssc_codegen/static_checker/base.py +0 -0
  61. {ssc_codegen-0.13.3 → ssc_codegen-0.14.0}/ssc_codegen/static_checker/callbacks.py +0 -0
  62. {ssc_codegen-0.13.3 → ssc_codegen-0.14.0}/ssc_codegen/str_utils.py +0 -0
  63. {ssc_codegen-0.13.3 → ssc_codegen-0.14.0}/ssc_codegen/tokens.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ssc_codegen
3
- Version: 0.13.3
3
+ Version: 0.14.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
@@ -27,7 +27,6 @@ Requires-Dist: cssselect>=1.2.0
27
27
  Requires-Dist: httpx>=0.28.1
28
28
  Requires-Dist: ichrome>=4.0.4
29
29
  Requires-Dist: lxml>=5.3.0
30
- Requires-Dist: parsel>=1.10.0
31
30
  Requires-Dist: soupsieve>=2.6
32
31
  Requires-Dist: tinycss2>=1.4.0
33
32
  Requires-Dist: typer>=0.15.1
@@ -59,15 +58,15 @@ ssc-gen - a python-based DSL to describe parsers for html documents, which is tr
59
58
 
60
59
  Current support converters
61
60
 
62
- | Language | HTML parser lib + dependencies | XPath | CSS3 | CSS4 | Generated annotations, types, structs | formatter dependency |
63
- | ---------------------------------------- | -------------------------------------- | ----- | ---- | ---- | ------------------------------------- | -------------------- |
64
- | Python (3.8+) | bs4, lxml | N | Y | Y | TypedDict`1`, list, dict | ruff |
65
- | ... | parsel | Y | Y | N | ... | ... |
66
- | ... | selectolax (lexbor) | N | Y | N | ... | ... |
67
- | ... | lxml | Y | Y | N | ... | ... |
68
- | js (ES6)`2` | pure (firefox/chrome extension/nodejs) | Y | Y | Y | JSDoc | prettier |
69
- | go (1.10+) **(UNSTABLE)** | goquery, gjson (`4`) | N | Y | N | struct(+json anchors), array, map | gofmt |
70
- | lua (5.2+), luajit(2+) **(UNSTABLE)**`5` | lua-htmlparser, lrexlib(opt), dkjson | N | Y | N | EmmyLua | LuaFormatter |
61
+ | Language | HTML parser lib + dependencies | XPath | CSS3 | CSS4 | Generated annotations, types, structs | formatter dependency |
62
+ | ---------------------------------------- | ------------------------------------------------------ | ----- | ---- | ---- | ------------------------------------- | -------------------- |
63
+ | Python (3.8-3.13) | bs4, lxml ( typing_extensions if py < 3.10 ) | N | Y | Y | TypedDict`1`, list, dict | ruff |
64
+ | ... | parsel ( typing_extensions if py < 3.10 ) | Y | Y | N | ... | ... |
65
+ | ... | selectolax (lexbor) ( typing_extensions if py < 3.10 ) | N | Y | N | ... | ... |
66
+ | ... | lxml ( typing_extensions if py < 3.10 ) | Y | Y | N | ... | ... |
67
+ | js (ES6)`2` | pure (firefox/chrome extension/nodejs) | Y | Y | Y | JSDoc | prettier |
68
+ | go (1.10+) **(UNSTABLE)** | goquery, gjson (`4`) | N | Y | N | struct(+json anchors), array, map | gofmt |
69
+ | lua (5.2+), luajit(2+) **(UNSTABLE)**`5` | lua-htmlparser, lrexlib(opt), dkjson | N | Y | N | EmmyLua | LuaFormatter |
71
70
 
72
71
  - **CSS3** means support next selectors:
73
72
  - basic: (`tag`, `.class`, `#id`, `tag1,tag2`)
@@ -100,6 +99,7 @@ For maximum portability of the configuration to the target language:
100
99
  Check the html parser lib documentation aboud CSS selectors before implement code. Examples:
101
100
  1. Several libs not support `+` operations (eg: [selectolax(modest)](https://github.com/rushter/selectolax), [dart.universal_html](https://pub.dev/packages/universal_html))
102
101
  2. For research purpose, lua_htmlparser include converter for unsupported CSS3 query syntax
102
+
103
103
  2. HTML parser libs maybe not supports attribute selectors: `*=`, `~=`, `|=`, `^=`, `$=`
104
104
  3. Several libs not support pseudo classes (eg: standard [dart.html](https://dart.dev/libraries/dart-html) lib miss this feature).
105
105
 
@@ -246,7 +246,6 @@ You can use any html source:
246
246
 
247
247
  ## See also
248
248
 
249
-
250
249
  - [Brief](docs/briefing.md) about css selectors and regular expressions
251
250
  - [Explain](docs/explain.md) short document on how to understand DSL syntax
252
251
  - [LLM](llm.md) experimental prompt for generate code
@@ -23,15 +23,15 @@ ssc-gen - a python-based DSL to describe parsers for html documents, which is tr
23
23
 
24
24
  Current support converters
25
25
 
26
- | Language | HTML parser lib + dependencies | XPath | CSS3 | CSS4 | Generated annotations, types, structs | formatter dependency |
27
- | ---------------------------------------- | -------------------------------------- | ----- | ---- | ---- | ------------------------------------- | -------------------- |
28
- | Python (3.8+) | bs4, lxml | N | Y | Y | TypedDict`1`, list, dict | ruff |
29
- | ... | parsel | Y | Y | N | ... | ... |
30
- | ... | selectolax (lexbor) | N | Y | N | ... | ... |
31
- | ... | lxml | Y | Y | N | ... | ... |
32
- | js (ES6)`2` | pure (firefox/chrome extension/nodejs) | Y | Y | Y | JSDoc | prettier |
33
- | go (1.10+) **(UNSTABLE)** | goquery, gjson (`4`) | N | Y | N | struct(+json anchors), array, map | gofmt |
34
- | lua (5.2+), luajit(2+) **(UNSTABLE)**`5` | lua-htmlparser, lrexlib(opt), dkjson | N | Y | N | EmmyLua | LuaFormatter |
26
+ | Language | HTML parser lib + dependencies | XPath | CSS3 | CSS4 | Generated annotations, types, structs | formatter dependency |
27
+ | ---------------------------------------- | ------------------------------------------------------ | ----- | ---- | ---- | ------------------------------------- | -------------------- |
28
+ | Python (3.8-3.13) | bs4, lxml ( typing_extensions if py < 3.10 ) | N | Y | Y | TypedDict`1`, list, dict | ruff |
29
+ | ... | parsel ( typing_extensions if py < 3.10 ) | Y | Y | N | ... | ... |
30
+ | ... | selectolax (lexbor) ( typing_extensions if py < 3.10 ) | N | Y | N | ... | ... |
31
+ | ... | lxml ( typing_extensions if py < 3.10 ) | Y | Y | N | ... | ... |
32
+ | js (ES6)`2` | pure (firefox/chrome extension/nodejs) | Y | Y | Y | JSDoc | prettier |
33
+ | go (1.10+) **(UNSTABLE)** | goquery, gjson (`4`) | N | Y | N | struct(+json anchors), array, map | gofmt |
34
+ | lua (5.2+), luajit(2+) **(UNSTABLE)**`5` | lua-htmlparser, lrexlib(opt), dkjson | N | Y | N | EmmyLua | LuaFormatter |
35
35
 
36
36
  - **CSS3** means support next selectors:
37
37
  - basic: (`tag`, `.class`, `#id`, `tag1,tag2`)
@@ -64,6 +64,7 @@ For maximum portability of the configuration to the target language:
64
64
  Check the html parser lib documentation aboud CSS selectors before implement code. Examples:
65
65
  1. Several libs not support `+` operations (eg: [selectolax(modest)](https://github.com/rushter/selectolax), [dart.universal_html](https://pub.dev/packages/universal_html))
66
66
  2. For research purpose, lua_htmlparser include converter for unsupported CSS3 query syntax
67
+
67
68
  2. HTML parser libs maybe not supports attribute selectors: `*=`, `~=`, `|=`, `^=`, `$=`
68
69
  3. Several libs not support pseudo classes (eg: standard [dart.html](https://dart.dev/libraries/dart-html) lib miss this feature).
69
70
 
@@ -210,7 +211,6 @@ You can use any html source:
210
211
 
211
212
  ## See also
212
213
 
213
-
214
214
  - [Brief](docs/briefing.md) about css selectors and regular expressions
215
215
  - [Explain](docs/explain.md) short document on how to understand DSL syntax
216
216
  - [LLM](llm.md) experimental prompt for generate code
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "ssc_codegen"
3
- version = "0.13.3"
3
+ version = "0.14.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"
@@ -11,7 +11,6 @@ dependencies = [
11
11
  "httpx>=0.28.1",
12
12
  "ichrome>=4.0.4",
13
13
  "lxml>=5.3.0",
14
- "parsel>=1.10.0",
15
14
  "soupsieve>=2.6",
16
15
  "typer>=0.15.1",
17
16
  "typing_extensions;python_version<'3.11'",
@@ -7,7 +7,7 @@ from ssc_codegen.schema import ItemSchema, DictSchema, ListSchema, FlatListSchem
7
7
 
8
8
  setup_logger()
9
9
 
10
- VERSION = "0.13.3"
10
+ VERSION = "0.14.0"
11
11
 
12
12
 
13
13
  class __MISSING(object):
@@ -3,7 +3,6 @@
3
3
  from typing import Callable
4
4
  from ssc_codegen.str_utils import (
5
5
  go_unimport_naive,
6
- py_remove_unused_none_type_import,
7
6
  )
8
7
 
9
8
 
@@ -28,7 +27,6 @@ class BaseCodeCallback:
28
27
  return code
29
28
 
30
29
 
31
- CB_PY_CODE = BaseCodeCallback(py_remove_unused_none_type_import)
32
30
  CB_GO_CODE = BaseCodeCallback(go_unimport_naive, remove_empty_lines=True)
33
31
  CB_DART_CODE = BaseCodeCallback(remove_empty_lines=True)
34
32
  CB_JS_CODE = BaseCodeCallback(remove_empty_lines=True)
@@ -25,7 +25,6 @@ from ssc_codegen.cli.cli_utils import (
25
25
  suggest_class_name,
26
26
  )
27
27
  from ssc_codegen.cli.code_callbacks import (
28
- CB_PY_CODE,
29
28
  CB_GO_CODE,
30
29
  CB_JS_CODE,
31
30
  )
@@ -208,7 +207,6 @@ def gen_py(
208
207
  xpath_to_css=to_css,
209
208
  css_to_xpath=to_xpath,
210
209
  debug_instructions=debug,
211
- code_cb=CB_PY_CODE,
212
210
  gen_docstring=docstring,
213
211
  )
214
212
 
@@ -439,7 +437,7 @@ def parse_from_file(
439
437
  ] = None,
440
438
  ) -> None:
441
439
  from ssc_codegen.compiler import Compiler
442
- from ssc_codegen.converters.py_parsel import CONVERTER
440
+ from ssc_codegen.converters.py_lxml import CONVERTER
443
441
 
444
442
  cls_target, schema_config = _validate_parser_target(cls_target)
445
443
 
@@ -563,7 +561,7 @@ def parse_from_chrome_(
563
561
  from ssc_codegen.converters.js_pure import CONVERTER as JS_CONVERTER
564
562
  import asyncio
565
563
  from ssc_codegen.compiler import Compiler
566
- from ssc_codegen.converters.py_parsel import CONVERTER
564
+ from ssc_codegen.converters.py_lxml import CONVERTER
567
565
 
568
566
  cls_target, schema_config = _validate_parser_target(cls_target)
569
567
 
@@ -143,24 +143,24 @@ INDENT_METHOD = INDENT_CH * 4
143
143
  INDENT_METHOD_BODY = INDENT_CH * (4 * 2)
144
144
  INDENT_DEFAULT_BODY = INDENT_CH * (4 * 3)
145
145
  TYPE_PREFIX = "T_{}"
146
- TYPE_DICT = "Dict[str, {}]"
147
- TYPE_LIST = "List[{}]"
146
+ TYPE_DICT = "dict[str, {}]"
147
+ TYPE_LIST = "list[{}]"
148
148
  TYPE_ITEM = "TypedDict({}, {})"
149
149
 
150
150
  TYPES = {
151
151
  VariableType.ANY: "Any",
152
152
  VariableType.STRING: "str",
153
- VariableType.LIST_STRING: "List[str]",
153
+ VariableType.LIST_STRING: "list[str]",
154
154
  VariableType.OPTIONAL_STRING: "Optional[str]",
155
- VariableType.OPTIONAL_LIST_STRING: "Optional[List[str]]",
155
+ VariableType.OPTIONAL_LIST_STRING: "Optional[list[str]]",
156
156
  VariableType.OPTIONAL_INT: "Optional[int]",
157
- VariableType.OPTIONAL_LIST_INT: "Optional[List[int]]",
157
+ VariableType.OPTIONAL_LIST_INT: "Optional[list[int]]",
158
158
  VariableType.OPTIONAL_FLOAT: "Optional[float]",
159
- VariableType.OPTIONAL_LIST_FLOAT: "Optional[List[float]]",
159
+ VariableType.OPTIONAL_LIST_FLOAT: "Optional[list[float]]",
160
160
  VariableType.INT: "int",
161
161
  VariableType.FLOAT: "float",
162
- VariableType.LIST_INT: "List[int]",
163
- VariableType.LIST_FLOAT: "List[float]",
162
+ VariableType.LIST_INT: "list[int]",
163
+ VariableType.LIST_FLOAT: "list[float]",
164
164
  VariableType.BOOL: "bool",
165
165
  }
166
166
 
@@ -174,11 +174,11 @@ JSON_TYPES = {
174
174
  JsonVariableType.OPTIONAL_NUMBER: "Optional[int]",
175
175
  JsonVariableType.OPTIONAL_FLOAT: "Optional[float]",
176
176
  JsonVariableType.OPTIONAL_BOOLEAN: "Optional[bool]",
177
- JsonVariableType.ARRAY: "List",
178
- JsonVariableType.ARRAY_FLOAT: "List[float]",
179
- JsonVariableType.ARRAY_NUMBER: "List[int]",
180
- JsonVariableType.ARRAY_STRING: "List[str]",
181
- JsonVariableType.ARRAY_BOOLEAN: "List[bool]",
177
+ JsonVariableType.ARRAY: "list",
178
+ JsonVariableType.ARRAY_FLOAT: "list[float]",
179
+ JsonVariableType.ARRAY_NUMBER: "list[int]",
180
+ JsonVariableType.ARRAY_STRING: "list[str]",
181
+ JsonVariableType.ARRAY_BOOLEAN: "list[bool]",
182
182
  }
183
183
 
184
184
  LITERAL_TYPES = {
@@ -327,11 +327,11 @@ def get_typedef_field_by_name(node: TypeDef, field_name: str) -> str:
327
327
  if value.kwargs["type"] == VariableType.NESTED:
328
328
  type_ = f"T_{value.kwargs['cls_nested']}"
329
329
  if value.kwargs["cls_nested_type"] == StructType.LIST:
330
- type_ = f"List[{type_}]"
330
+ type_ = f"list[{type_}]"
331
331
  elif value.kwargs["type"] == VariableType.JSON:
332
332
  type_ = f"J_{value.kwargs['cls_nested']}"
333
333
  if value.kwargs["cls_nested_type"] == StructType.LIST:
334
- type_ = f"List[{type_}]"
334
+ type_ = f"list[{type_}]"
335
335
  else:
336
336
  type_ = TYPES[value.kwargs["type"]]
337
337
  return type_
@@ -346,14 +346,14 @@ def get_field_method_ret_type(node: StructFieldMethod) -> str:
346
346
  schema_name, schema_type = last_expr.unpack_args()
347
347
  type_ = f"T_{schema_name}"
348
348
  if schema_type == StructType.LIST:
349
- type_ = f"List[{type_}]"
349
+ type_ = f"list[{type_}]"
350
350
  case VariableType.JSON:
351
351
  last_expr = node.body[-2]
352
352
  last_expr = cast(ExprJsonify, last_expr)
353
353
  json_struct_name, is_array, *_ = last_expr.unpack_args()
354
354
  type_ = f"J_{json_struct_name}"
355
355
  if is_array:
356
- type_ = f"List[{type_}]"
356
+ type_ = f"list[{type_}]"
357
357
  case _:
358
358
  type_ = TYPES[last_expr.ret_type]
359
359
  return type_
@@ -396,7 +396,7 @@ def post_typedef_list(_: TypeDef) -> str:
396
396
  def pre_typedef_dict(node: TypeDef) -> str:
397
397
  name, _ = node.unpack_args()
398
398
  type_ = get_typedef_field_by_name(node, "__VALUE__")
399
- return f"T_{name} = Dict[str, {type_}]"
399
+ return f"T_{name}: TypeAlias = dict[str, {type_}]"
400
400
 
401
401
 
402
402
  def post_typedef_dict(_: TypeDef) -> str:
@@ -406,7 +406,7 @@ def post_typedef_dict(_: TypeDef) -> str:
406
406
  def pre_typedef_flat_list(node: TypeDef) -> str:
407
407
  name, _ = node.unpack_args()
408
408
  type_ = get_typedef_field_by_name(node, "__VALUE__")
409
- return f"T_{name} = List[{type_}]"
409
+ return f"T_{name}: TypeAlias = list[{type_}]"
410
410
 
411
411
 
412
412
  def post_typedef_flat_list(_: TypeDef) -> str:
@@ -415,7 +415,7 @@ def post_typedef_flat_list(_: TypeDef) -> str:
415
415
 
416
416
  def pre_typedef_acc_list(node: TypeDef) -> str:
417
417
  name, _ = node.unpack_args()
418
- return f"T_{name} = List[str]"
418
+ return f"T_{name}: TypeAlias = list[str]"
419
419
 
420
420
 
421
421
  def post_typedef_acc_list(_: TypeDef) -> str:
@@ -438,11 +438,11 @@ def pre_typedef_field(node: TypeDefField) -> str:
438
438
  elif var_type == VariableType.NESTED:
439
439
  type_ = f"T_{cls_nested}"
440
440
  if cls_nested_type == StructType.LIST:
441
- type_ = f"List[{type_}]"
441
+ type_ = f"list[{type_}]"
442
442
  elif var_type == VariableType.JSON:
443
443
  type_ = f"J_{cls_nested}"
444
444
  if cls_nested_type == StructType.LIST:
445
- type_ = f"List[{type_}]"
445
+ type_ = f"list[{type_}]"
446
446
  else:
447
447
  type_ = TYPES[var_type]
448
448
  return f"{name!r}: {type_},"
@@ -466,7 +466,7 @@ def pre_json_field(node: JsonStructField) -> str:
466
466
  if json_type.type == JsonVariableType.OBJECT:
467
467
  type_ = f"J_{json_type.name}"
468
468
  elif json_type.type == JsonVariableType.ARRAY_OBJECTS:
469
- type_ = f"List[J_{json_type.name}]"
469
+ type_ = f"list[J_{json_type.name}]"
470
470
  else:
471
471
  type_ = JSON_TYPES[json_type.type]
472
472
 
@@ -529,7 +529,7 @@ def pre_start_parse(node: StartParseMethod) -> str:
529
529
  st_type = node.parent.kwargs["struct_type"]
530
530
  type_ = f"T_{name}"
531
531
  if st_type == StructType.LIST:
532
- type_ = f"List[{type_}]"
532
+ type_ = f"list[{type_}]"
533
533
  return INDENT_METHOD + f"def parse(self) -> {type_}:"
534
534
 
535
535
 
@@ -1010,7 +1010,7 @@ def pre_list_str_any_is_regex(node: ExprListStringAnyRegex) -> str:
1010
1010
  INDENT_DEFAULT_BODY if have_default_expr(node) else INDENT_METHOD_BODY
1011
1011
  )
1012
1012
  prv, nxt = prev_next_var(node)
1013
- pattern, ignore_case, msg = node.unpack_args()
1013
+ pattern, ignore_case, msg, _invert = node.unpack_args()
1014
1014
 
1015
1015
  if node.classvar_hooks.get("pattern"):
1016
1016
  pattern = py_get_classvar_hook_or_value(node, "pattern")
@@ -1033,7 +1033,7 @@ def pre_list_str_all_is_regex(node: ExprListStringAllRegex) -> str:
1033
1033
  INDENT_DEFAULT_BODY if have_default_expr(node) else INDENT_METHOD_BODY
1034
1034
  )
1035
1035
  prv, nxt = prev_next_var(node)
1036
- pattern, ignore_case, msg = node.unpack_args()
1036
+ pattern, ignore_case, msg, _invert = node.unpack_args()
1037
1037
 
1038
1038
  if node.classvar_hooks.get("pattern"):
1039
1039
  pattern = py_get_classvar_hook_or_value(node, "pattern")
@@ -1181,7 +1181,7 @@ def pre_filter_ends_with(node: FilterStrEnds) -> str:
1181
1181
  def pre_filter_re(node: FilterStrRe) -> str:
1182
1182
  pattern, ignore_case, *_ = node.unpack_args()
1183
1183
  if ignore_case:
1184
- expr = f"re.search({pattern!r}, i, re.IGNORECASE)"
1184
+ expr = f"re.search({pattern!r}, i, re.I)"
1185
1185
  else:
1186
1186
  expr = f"re.search({pattern!r}, i)"
1187
1187
  if not is_first_node_cond(node) and is_prev_node_atomic_cond(node):
@@ -107,7 +107,7 @@ def pre_struct_pre_validate(_node: StructPreValidateMethod) -> str:
107
107
  def pre_struct_part_doc_method(_node: StructPartDocMethod) -> str:
108
108
  return (
109
109
  INDENT_METHOD
110
- + "def _split_doc(self, v: html.HtmlElement) -> List[html.HtmlElement]:"
110
+ + "def _split_doc(self, v: html.HtmlElement) -> list[html.HtmlElement]:"
111
111
  )
112
112
 
113
113
 
@@ -128,8 +128,7 @@ def pre_imports(_: ModuleImports) -> str:
128
128
  # most mainsteram html parser libs use `FALLBACK_HTML_STR` stub value
129
129
  return (
130
130
  IMPORTS_MIN
131
- + """from lxml import html, etree
132
-
131
+ + """from lxml import html
133
132
  FALLBACK_HTML_STR = "<html><body></body></html>"
134
133
  """
135
134
  )
@@ -272,7 +272,7 @@ def pre_has_attr(node: ExprHasAttr) -> str:
272
272
  expr = indent + f"assert {expr}, {msg!r}"
273
273
  if is_last_var_no_ret(node):
274
274
  return expr
275
- return "\n".join(expr, indent + f"{nxt} = {prv}")
275
+ return "\n".join([expr, indent + f"{nxt} = {prv}"])
276
276
 
277
277
 
278
278
  @CONVERTER(ExprListHasAttr.kind)
@@ -292,7 +292,7 @@ def pre_list_has_attr(node: ExprListHasAttr) -> str:
292
292
 
293
293
  if is_last_var_no_ret(node):
294
294
  return expr
295
- return "\n".join(expr, indent + f"{nxt} = {prv}")
295
+ return "\n".join([expr, indent + f"{nxt} = {prv}"])
296
296
 
297
297
 
298
298
  @CONVERTER(ExprMapAttrs.kind)
@@ -84,7 +84,7 @@ def pre_struct_pre_validate(_node: StructPreValidateMethod) -> str:
84
84
  def pre_struct_part_doc_method(_node: StructPartDocMethod) -> str:
85
85
  return (
86
86
  INDENT_METHOD
87
- + "def _split_doc(self, v: Union[HTMLParser, Node]) -> List[Node]:"
87
+ + "def _split_doc(self, v: Union[HTMLParser, Node]) -> list[Node]:"
88
88
  )
89
89
 
90
90
 
@@ -1,19 +1,26 @@
1
- # used old style typing for support old python versions (3.8)
2
-
3
-
1
+ # from __future__ import annotations for support old python versions (3.8)
4
2
  IMPORTS_MIN = """
3
+ from __future__ import annotations
4
+
5
5
  import re
6
6
  import sys
7
7
  import json
8
8
  from html import unescape as _html_unescape
9
- from typing import List, Dict, TypedDict, Union, Optional, ClassVar
9
+ from typing import TypedDict, Union, Optional, ClassVar
10
10
  from contextlib import suppress
11
11
  from functools import reduce
12
12
 
13
13
  if sys.version_info >= (3, 10):
14
14
  from types import NoneType
15
+ from typing import TypeAlias
15
16
  else:
16
17
  NoneType = type(None)
18
+
19
+ try:
20
+ from typing_extensions import TypeAlias # noqa
21
+ except ImportError:
22
+ msg = "python < 3.10 required 'typing_extensions' dependency"
23
+ raise ImportError(msg)
17
24
  """
18
25
 
19
26
 
@@ -36,7 +43,7 @@ def ssc_unescape(s: str) -> str:
36
43
  return s
37
44
 
38
45
 
39
- def ssc_map_replace(s: str, replacements: Dict[str, str]) -> str:
46
+ def ssc_map_replace(s: str, replacements: dict[str, str]) -> str:
40
47
  return reduce(lambda acc, kv: acc.replace(kv[0], kv[1]), replacements.items(), s)
41
48
 
42
49
 
File without changes
File without changes