ssc_codegen 0.10.0__tar.gz → 0.10.2__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 (61) hide show
  1. {ssc_codegen-0.10.0 → ssc_codegen-0.10.2}/PKG-INFO +5 -3
  2. {ssc_codegen-0.10.0 → ssc_codegen-0.10.2}/README.md +4 -2
  3. {ssc_codegen-0.10.0 → ssc_codegen-0.10.2}/pyproject.toml +1 -1
  4. {ssc_codegen-0.10.0 → ssc_codegen-0.10.2}/ssc_codegen/__init__.py +3 -1
  5. {ssc_codegen-0.10.0 → ssc_codegen-0.10.2}/ssc_codegen/ast_/__init__.py +1 -1
  6. {ssc_codegen-0.10.0 → ssc_codegen-0.10.2}/ssc_codegen/ast_/nodes_cast.py +13 -0
  7. {ssc_codegen-0.10.0 → ssc_codegen-0.10.2}/ssc_codegen/converters/go_goquery.py +1 -0
  8. {ssc_codegen-0.10.0 → ssc_codegen-0.10.2}/ssc_codegen/converters/helpers.py +1 -1
  9. {ssc_codegen-0.10.0 → ssc_codegen-0.10.2}/ssc_codegen/converters/js_pure.py +11 -0
  10. {ssc_codegen-0.10.0 → ssc_codegen-0.10.2}/ssc_codegen/converters/lua_htmlparser.py +14 -0
  11. {ssc_codegen-0.10.0 → ssc_codegen-0.10.2}/ssc_codegen/converters/py_base.py +16 -2
  12. {ssc_codegen-0.10.0 → ssc_codegen-0.10.2}/ssc_codegen/document.py +219 -309
  13. {ssc_codegen-0.10.0 → ssc_codegen-0.10.2}/ssc_codegen/tokens.py +1 -0
  14. {ssc_codegen-0.10.0 → ssc_codegen-0.10.2}/.gitignore +0 -0
  15. {ssc_codegen-0.10.0 → ssc_codegen-0.10.2}/LICENSE +0 -0
  16. {ssc_codegen-0.10.0 → ssc_codegen-0.10.2}/ssc_codegen/_compat.py +0 -0
  17. {ssc_codegen-0.10.0 → ssc_codegen-0.10.2}/ssc_codegen/ast_/base.py +0 -0
  18. {ssc_codegen-0.10.0 → ssc_codegen-0.10.2}/ssc_codegen/ast_/nodes_array.py +0 -0
  19. {ssc_codegen-0.10.0 → ssc_codegen-0.10.2}/ssc_codegen/ast_/nodes_core.py +0 -0
  20. {ssc_codegen-0.10.0 → ssc_codegen-0.10.2}/ssc_codegen/ast_/nodes_filter.py +0 -0
  21. {ssc_codegen-0.10.0 → ssc_codegen-0.10.2}/ssc_codegen/ast_/nodes_selectors.py +0 -0
  22. {ssc_codegen-0.10.0 → ssc_codegen-0.10.2}/ssc_codegen/ast_/nodes_string.py +0 -0
  23. {ssc_codegen-0.10.0 → ssc_codegen-0.10.2}/ssc_codegen/ast_/nodes_validate.py +0 -0
  24. {ssc_codegen-0.10.0 → ssc_codegen-0.10.2}/ssc_codegen/ast_build/__init__.py +0 -0
  25. {ssc_codegen-0.10.0 → ssc_codegen-0.10.2}/ssc_codegen/ast_build/main.py +0 -0
  26. {ssc_codegen-0.10.0 → ssc_codegen-0.10.2}/ssc_codegen/ast_build/utils.py +0 -0
  27. {ssc_codegen-0.10.0 → ssc_codegen-0.10.2}/ssc_codegen/ast_grep_rules/js_rules.yml +0 -0
  28. {ssc_codegen-0.10.0 → ssc_codegen-0.10.2}/ssc_codegen/ast_grep_rules/py_rules.yml +0 -0
  29. {ssc_codegen-0.10.0 → ssc_codegen-0.10.2}/ssc_codegen/cli/__init__.py +0 -0
  30. {ssc_codegen-0.10.0 → ssc_codegen-0.10.2}/ssc_codegen/cli/ast_grep.py +0 -0
  31. {ssc_codegen-0.10.0 → ssc_codegen-0.10.2}/ssc_codegen/cli/cli_callbacks.py +0 -0
  32. {ssc_codegen-0.10.0 → ssc_codegen-0.10.2}/ssc_codegen/cli/cli_utils.py +0 -0
  33. {ssc_codegen-0.10.0 → ssc_codegen-0.10.2}/ssc_codegen/cli/code_callbacks.py +0 -0
  34. {ssc_codegen-0.10.0 → ssc_codegen-0.10.2}/ssc_codegen/cli/consts.py +0 -0
  35. {ssc_codegen-0.10.0 → ssc_codegen-0.10.2}/ssc_codegen/cli/main.py +0 -0
  36. {ssc_codegen-0.10.0 → ssc_codegen-0.10.2}/ssc_codegen/cli/runtime_parse_runners.py +0 -0
  37. {ssc_codegen-0.10.0 → ssc_codegen-0.10.2}/ssc_codegen/compiler.py +0 -0
  38. {ssc_codegen-0.10.0 → ssc_codegen-0.10.2}/ssc_codegen/converters/__init__.py +0 -0
  39. {ssc_codegen-0.10.0 → ssc_codegen-0.10.2}/ssc_codegen/converters/base.py +0 -0
  40. {ssc_codegen-0.10.0 → ssc_codegen-0.10.2}/ssc_codegen/converters/py_bs4.py +0 -0
  41. {ssc_codegen-0.10.0 → ssc_codegen-0.10.2}/ssc_codegen/converters/py_lxml.py +0 -0
  42. {ssc_codegen-0.10.0 → ssc_codegen-0.10.2}/ssc_codegen/converters/py_parsel.py +0 -0
  43. {ssc_codegen-0.10.0 → ssc_codegen-0.10.2}/ssc_codegen/converters/py_selectolax.py +0 -0
  44. {ssc_codegen-0.10.0 → ssc_codegen-0.10.2}/ssc_codegen/converters/templates/__init__.py +0 -0
  45. {ssc_codegen-0.10.0 → ssc_codegen-0.10.2}/ssc_codegen/converters/templates/go_goquery.py +0 -0
  46. {ssc_codegen-0.10.0 → ssc_codegen-0.10.2}/ssc_codegen/converters/templates/js_pure.py +0 -0
  47. {ssc_codegen-0.10.0 → ssc_codegen-0.10.2}/ssc_codegen/converters/templates/lua_base.py +0 -0
  48. {ssc_codegen-0.10.0 → ssc_codegen-0.10.2}/ssc_codegen/converters/templates/lua_css_compat.py +0 -0
  49. {ssc_codegen-0.10.0 → ssc_codegen-0.10.2}/ssc_codegen/converters/templates/lua_re_compat.py +0 -0
  50. {ssc_codegen-0.10.0 → ssc_codegen-0.10.2}/ssc_codegen/converters/templates/py_base.py +0 -0
  51. {ssc_codegen-0.10.0 → ssc_codegen-0.10.2}/ssc_codegen/document_utlis.py +0 -0
  52. {ssc_codegen-0.10.0 → ssc_codegen-0.10.2}/ssc_codegen/json_struct.py +0 -0
  53. {ssc_codegen-0.10.0 → ssc_codegen-0.10.2}/ssc_codegen/json_to_scc.py +0 -0
  54. {ssc_codegen-0.10.0 → ssc_codegen-0.10.2}/ssc_codegen/logs.py +0 -0
  55. {ssc_codegen-0.10.0 → ssc_codegen-0.10.2}/ssc_codegen/pseudo_selectors.py +0 -0
  56. {ssc_codegen-0.10.0 → ssc_codegen-0.10.2}/ssc_codegen/schema.py +0 -0
  57. {ssc_codegen-0.10.0 → ssc_codegen-0.10.2}/ssc_codegen/selector_utils.py +0 -0
  58. {ssc_codegen-0.10.0 → ssc_codegen-0.10.2}/ssc_codegen/static_checker/__init__.py +0 -0
  59. {ssc_codegen-0.10.0 → ssc_codegen-0.10.2}/ssc_codegen/static_checker/base.py +0 -0
  60. {ssc_codegen-0.10.0 → ssc_codegen-0.10.2}/ssc_codegen/static_checker/callbacks.py +0 -0
  61. {ssc_codegen-0.10.0 → ssc_codegen-0.10.2}/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.10.0
3
+ Version: 0.10.2
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
@@ -247,7 +247,9 @@ You can use any html source:
247
247
 
248
248
  ## See also
249
249
 
250
- - [Brief](docs/brief.md) about css selectors and regular expressions.
250
+
251
+ - [Brief](docs/briefing.md) about css selectors and regular expressions.
252
+ - [LLM]("llm.md") experimental prompt for generate code
253
+ - [Quickstart](docs/quickstart.md) about css selectors and regular expressions.
251
254
  - [Tutorial](docs/tutorial.md) basic usage ssc-gen
252
- - [Reference](docs/reference.md) about lib API
253
255
  - [AST reference](docs/ast_reference.md) about generation code from AST
@@ -210,7 +210,9 @@ You can use any html source:
210
210
 
211
211
  ## See also
212
212
 
213
- - [Brief](docs/brief.md) about css selectors and regular expressions.
213
+
214
+ - [Brief](docs/briefing.md) about css selectors and regular expressions.
215
+ - [LLM]("llm.md") experimental prompt for generate code
216
+ - [Quickstart](docs/quickstart.md) about css selectors and regular expressions.
214
217
  - [Tutorial](docs/tutorial.md) basic usage ssc-gen
215
- - [Reference](docs/reference.md) about lib API
216
218
  - [AST reference](docs/ast_reference.md) about generation code from AST
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "ssc_codegen"
3
- version = "0.10.0"
3
+ version = "0.10.2"
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 +7,7 @@ from ssc_codegen.schema import ItemSchema, DictSchema, ListSchema, FlatListSchem
7
7
 
8
8
  setup_logger()
9
9
 
10
- VERSION = "0.10.0"
10
+ VERSION = "0.10.2"
11
11
 
12
12
 
13
13
  class __MISSING(object):
@@ -28,10 +28,12 @@ class Document(
28
28
  JsonDocument,
29
29
  BooleanDocument
30
30
  ):
31
+ """Special Common Document or Element marker manipulations"""
31
32
  pass
32
33
 
33
34
 
34
35
  class Nested(HTMLDocument, NestedDocument, ArrayDocument, AssertDocument):
36
+ """Special Common Document or Element marker for provide Nested structure parsers"""
35
37
  pass
36
38
 
37
39
 
@@ -1,6 +1,6 @@
1
1
  from .base import BaseAstNode
2
2
  from .nodes_array import ExprIndex, ExprToListLength, ExprListStringJoin, ExprListUnique
3
- from .nodes_cast import ExprNested, ExprJsonify, ExprToInt, ExprToFloat, ExprToListInt, ExprToListFloat, ExprToBool
3
+ from .nodes_cast import ExprNested, ExprJsonify, ExprToInt, ExprToFloat, ExprToListInt, ExprToListFloat, ExprToBool, ExprJsonifyDynamic
4
4
  from .nodes_core import (ExprReturn,
5
5
  ExprNoReturn,
6
6
  ExprDefaultValueEnd,
@@ -68,3 +68,16 @@ class ExprJsonify(BaseAstNode[KW_EXPR_JSONIFY, ARGS_EXPR_JSONIFY]):
68
68
  kind: ClassVar[TokenType] = TokenType.TO_JSON
69
69
  accept_type: VariableType = VariableType.STRING
70
70
  ret_type: VariableType = VariableType.JSON
71
+
72
+
73
+ KW_EXPR_JSONIFY_DYNAMIC = TypedDict("KW_EXPR_JSONIFY_DYNAMIC", {"query": str})
74
+ ARGS_EXPR_JSONIFY_DYNAMIC = tuple[str]
75
+
76
+
77
+ @dataclass(kw_only=True)
78
+ class ExprJsonifyDynamic(
79
+ BaseAstNode[KW_EXPR_JSONIFY_DYNAMIC, ARGS_EXPR_JSONIFY_DYNAMIC]
80
+ ):
81
+ kind: ClassVar[TokenType] = TokenType.TO_JSON_DYNAMIC
82
+ accept_type: VariableType = VariableType.STRING
83
+ ret_type: VariableType = VariableType.ANY # STUBBED
@@ -267,6 +267,7 @@ CONVERTER.TEST_EXCLUDE_NODES.extend(
267
267
  TokenType.STRUCT_INIT, # defined inside a struct
268
268
  TokenType.EXPR_DEFAULT_END, # emulated by defer func() + rescue
269
269
  TokenType.CLASSVAR, # emulated by type ST struct{ f1: T1, f2: T2, ...}; var ST {f1=V1, f2=V2, ...};
270
+ TokenType.TO_JSON_DYNAMIC, # golang exclude dynamic json structures (DDD aka dict driven development)
270
271
  ]
271
272
  )
272
273
 
@@ -141,7 +141,7 @@ def _js_default_cast_t(i) -> str:
141
141
  return "[" + ",".join(repr(j) for j in i) + "]"
142
142
  return "[]"
143
143
  elif isinstance(i, str):
144
- return repr(str)
144
+ return repr(i)
145
145
  elif isinstance(i, bool):
146
146
  return "true" if i else "false"
147
147
  # int, float types
@@ -106,6 +106,7 @@ from ssc_codegen.ast_ import (
106
106
  ExprListStringMapReplace,
107
107
  ExprClassVar,
108
108
  )
109
+ from ssc_codegen.ast_.nodes_cast import ExprJsonifyDynamic
109
110
  from ssc_codegen.ast_.nodes_core import ModuleImports
110
111
  from ssc_codegen.ast_.nodes_selectors import (
111
112
  ExprCssElementRemove,
@@ -1064,3 +1065,13 @@ def pre_xpath_remove(node: ExprXpathElementRemove) -> str:
1064
1065
  f"for (let {prv}r = document.evaluate({query}, document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null), {prv}i = {prv}r.snapshotLength; {prv}i--; ) {prv}r.snapshotItem({prv}i).remove(); "
1065
1066
  + f"let {nxt} = {prv}; "
1066
1067
  )
1068
+
1069
+
1070
+ @CONVERTER(ExprJsonifyDynamic.kind)
1071
+ def pre_jsonify_dynamic(node: ExprJsonifyDynamic) -> str:
1072
+ prv, nxt = prev_next_var(node)
1073
+ query = node.unpack_args()
1074
+
1075
+ expr = "".join(f"[{i}]" for i in jsonify_query_parse(query))
1076
+
1077
+ return f"let {nxt} = JSON.parse({prv}){expr};"
@@ -110,6 +110,7 @@ from ssc_codegen.ast_ import (
110
110
  ExprStringUnescape,
111
111
  ModuleImports,
112
112
  )
113
+ from ssc_codegen.ast_.nodes_cast import ExprJsonifyDynamic
113
114
  from ssc_codegen.ast_.nodes_core import (
114
115
  CodeEnd,
115
116
  ExprCallStructClassVar,
@@ -1380,3 +1381,16 @@ def pre_code_end(node: CodeEnd) -> str:
1380
1381
  ]
1381
1382
  names = [n.kwargs["name"] + "=" + n.kwargs["name"] for n in classes]
1382
1383
  return "return {" + ", ".join(names) + "}"
1384
+
1385
+
1386
+ @CONVERTER(ExprJsonifyDynamic.kind)
1387
+ def pre_jsonify_dynamic(node: ExprJsonifyDynamic) -> str:
1388
+ prv, nxt = prev_next_var(node)
1389
+ query = node.unpack_args()
1390
+ # lua index starts by 1, fix query
1391
+ expr = "".join(
1392
+ f"[{int(i) + 1}]" if i.isdigit() else f"[{i}]"
1393
+ for i in jsonify_query_parse(query)
1394
+ )
1395
+
1396
+ return f"local {nxt} = json.decode({prv}){expr}; "
@@ -107,6 +107,7 @@ from ssc_codegen.ast_ import (
107
107
  ExprStringMapReplace,
108
108
  ExprListStringMapReplace,
109
109
  )
110
+ from ssc_codegen.ast_.nodes_cast import ExprJsonifyDynamic
110
111
  from ssc_codegen.ast_.nodes_core import ExprClassVar
111
112
  from ssc_codegen.ast_.nodes_string import (
112
113
  ExprListStringUnescape,
@@ -270,6 +271,7 @@ class BasePyCodeConverter(BaseCodeConverter):
270
271
  ExprToListLength.kind: pre_to_len,
271
272
  ExprToBool.kind: pre_to_bool,
272
273
  ExprJsonify.kind: pre_jsonify,
274
+ ExprJsonifyDynamic.kind: pre_to_json_dynamic,
273
275
  # FILTER,
274
276
  ExprFilter.kind: pre_expr_filter,
275
277
  FilterAnd.kind: pre_filter_and,
@@ -949,9 +951,9 @@ def pre_is_regex(node: ExprStringIsRegex) -> str:
949
951
  else:
950
952
  flags = py_regex_flags(ignore_case)
951
953
  if flags:
952
- expr = f"re.search({pattern}, {prv}, re.I)"
954
+ expr = f"re.search({pattern!r}, {prv}, re.I)"
953
955
  else:
954
- expr = f"re.search({pattern}, {prv})"
956
+ expr = f"re.search({pattern!r}, {prv})"
955
957
 
956
958
  expr = indent + f"assert {expr}, {msg}"
957
959
  if is_last_var_no_ret(node):
@@ -1269,3 +1271,15 @@ def pre_list_str_unescape(node: ExprListStringUnescape) -> str:
1269
1271
  prv, nxt = prev_next_var(node)
1270
1272
  # ssc_unescape(s: str) -> str
1271
1273
  return f"{indent}{nxt} = [ssc_unescape(i) for i in {prv}]"
1274
+
1275
+
1276
+ def pre_to_json_dynamic(node: ExprJsonifyDynamic) -> str:
1277
+ indent = (
1278
+ INDENT_DEFAULT_BODY if have_default_expr(node) else INDENT_METHOD_BODY
1279
+ )
1280
+ prv, nxt = prev_next_var(node)
1281
+ query = node.unpack_args()
1282
+
1283
+ expr = "".join(f"[{i}]" for i in jsonify_query_parse(query))
1284
+
1285
+ return f"{indent}{nxt} = json.loads({prv}){expr}"