ssc_codegen 0.8.0__tar.gz → 0.8.1__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.

Files changed (51) hide show
  1. {ssc_codegen-0.8.0 → ssc_codegen-0.8.1}/PKG-INFO +1 -1
  2. {ssc_codegen-0.8.0 → ssc_codegen-0.8.1}/pyproject.toml +1 -1
  3. {ssc_codegen-0.8.0 → ssc_codegen-0.8.1}/ssc_codegen/__init__.py +1 -1
  4. {ssc_codegen-0.8.0 → ssc_codegen-0.8.1}/ssc_codegen/ast_build/main.py +23 -6
  5. {ssc_codegen-0.8.0 → ssc_codegen-0.8.1}/ssc_codegen/cli/code_callbacks.py +2 -2
  6. {ssc_codegen-0.8.0 → ssc_codegen-0.8.1}/ssc_codegen/converters/py_base.py +14 -11
  7. {ssc_codegen-0.8.0 → ssc_codegen-0.8.1}/ssc_codegen/converters/py_parsel.py +5 -7
  8. {ssc_codegen-0.8.0 → ssc_codegen-0.8.1}/ssc_codegen/schema.py +2 -3
  9. {ssc_codegen-0.8.0 → ssc_codegen-0.8.1}/ssc_codegen/str_utils.py +12 -0
  10. {ssc_codegen-0.8.0 → ssc_codegen-0.8.1}/.gitignore +0 -0
  11. {ssc_codegen-0.8.0 → ssc_codegen-0.8.1}/LICENSE +0 -0
  12. {ssc_codegen-0.8.0 → ssc_codegen-0.8.1}/README.md +0 -0
  13. {ssc_codegen-0.8.0 → ssc_codegen-0.8.1}/ssc_codegen/_compat.py +0 -0
  14. {ssc_codegen-0.8.0 → ssc_codegen-0.8.1}/ssc_codegen/ast_/__init__.py +0 -0
  15. {ssc_codegen-0.8.0 → ssc_codegen-0.8.1}/ssc_codegen/ast_/base.py +0 -0
  16. {ssc_codegen-0.8.0 → ssc_codegen-0.8.1}/ssc_codegen/ast_/nodes_array.py +0 -0
  17. {ssc_codegen-0.8.0 → ssc_codegen-0.8.1}/ssc_codegen/ast_/nodes_cast.py +0 -0
  18. {ssc_codegen-0.8.0 → ssc_codegen-0.8.1}/ssc_codegen/ast_/nodes_core.py +0 -0
  19. {ssc_codegen-0.8.0 → ssc_codegen-0.8.1}/ssc_codegen/ast_/nodes_selectors.py +0 -0
  20. {ssc_codegen-0.8.0 → ssc_codegen-0.8.1}/ssc_codegen/ast_/nodes_string.py +0 -0
  21. {ssc_codegen-0.8.0 → ssc_codegen-0.8.1}/ssc_codegen/ast_/nodes_validate.py +0 -0
  22. {ssc_codegen-0.8.0 → ssc_codegen-0.8.1}/ssc_codegen/ast_build/__init__.py +0 -0
  23. {ssc_codegen-0.8.0 → ssc_codegen-0.8.1}/ssc_codegen/ast_build/utils.py +0 -0
  24. {ssc_codegen-0.8.0 → ssc_codegen-0.8.1}/ssc_codegen/cli/__init__.py +0 -0
  25. {ssc_codegen-0.8.0 → ssc_codegen-0.8.1}/ssc_codegen/cli/cli_callbacks.py +0 -0
  26. {ssc_codegen-0.8.0 → ssc_codegen-0.8.1}/ssc_codegen/cli/cli_utils.py +0 -0
  27. {ssc_codegen-0.8.0 → ssc_codegen-0.8.1}/ssc_codegen/cli/consts.py +0 -0
  28. {ssc_codegen-0.8.0 → ssc_codegen-0.8.1}/ssc_codegen/cli/main.py +0 -0
  29. {ssc_codegen-0.8.0 → ssc_codegen-0.8.1}/ssc_codegen/cli/runtime_parse_runners.py +0 -0
  30. {ssc_codegen-0.8.0 → ssc_codegen-0.8.1}/ssc_codegen/compiler.py +0 -0
  31. {ssc_codegen-0.8.0 → ssc_codegen-0.8.1}/ssc_codegen/consts.py +0 -0
  32. {ssc_codegen-0.8.0 → ssc_codegen-0.8.1}/ssc_codegen/converters/__init__.py +0 -0
  33. {ssc_codegen-0.8.0 → ssc_codegen-0.8.1}/ssc_codegen/converters/base.py +0 -0
  34. {ssc_codegen-0.8.0 → ssc_codegen-0.8.1}/ssc_codegen/converters/go_goquery.py +0 -0
  35. {ssc_codegen-0.8.0 → ssc_codegen-0.8.1}/ssc_codegen/converters/helpers.py +0 -0
  36. {ssc_codegen-0.8.0 → ssc_codegen-0.8.1}/ssc_codegen/converters/js_pure.py +0 -0
  37. {ssc_codegen-0.8.0 → ssc_codegen-0.8.1}/ssc_codegen/converters/py_bs4.py +0 -0
  38. {ssc_codegen-0.8.0 → ssc_codegen-0.8.1}/ssc_codegen/converters/py_selectolax.py +0 -0
  39. {ssc_codegen-0.8.0 → ssc_codegen-0.8.1}/ssc_codegen/converters/templates/__init__.py +0 -0
  40. {ssc_codegen-0.8.0 → ssc_codegen-0.8.1}/ssc_codegen/converters/templates/go_goquery.py +0 -0
  41. {ssc_codegen-0.8.0 → ssc_codegen-0.8.1}/ssc_codegen/converters/templates/js_pure.py +0 -0
  42. {ssc_codegen-0.8.0 → ssc_codegen-0.8.1}/ssc_codegen/document.py +0 -0
  43. {ssc_codegen-0.8.0 → ssc_codegen-0.8.1}/ssc_codegen/document_utlis.py +0 -0
  44. {ssc_codegen-0.8.0 → ssc_codegen-0.8.1}/ssc_codegen/json_struct.py +0 -0
  45. {ssc_codegen-0.8.0 → ssc_codegen-0.8.1}/ssc_codegen/json_to_scc.py +0 -0
  46. {ssc_codegen-0.8.0 → ssc_codegen-0.8.1}/ssc_codegen/logs.py +0 -0
  47. {ssc_codegen-0.8.0 → ssc_codegen-0.8.1}/ssc_codegen/selector_utils.py +0 -0
  48. {ssc_codegen-0.8.0 → ssc_codegen-0.8.1}/ssc_codegen/static_checker/__init__.py +0 -0
  49. {ssc_codegen-0.8.0 → ssc_codegen-0.8.1}/ssc_codegen/static_checker/base.py +0 -0
  50. {ssc_codegen-0.8.0 → ssc_codegen-0.8.1}/ssc_codegen/static_checker/callbacks.py +0 -0
  51. {ssc_codegen-0.8.0 → ssc_codegen-0.8.1}/ssc_codegen/tokens.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ssc_codegen
3
- Version: 0.8.0
3
+ Version: 0.8.1
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
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "ssc_codegen"
3
- version = "0.8.0"
3
+ version = "0.8.1"
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.8.0"
10
+ VERSION = "0.8.1"
11
11
 
12
12
 
13
13
  class __MISSING(object):
@@ -236,9 +236,18 @@ def _fetch_field_nodes(
236
236
  parent=st_ref,
237
237
  ret_type=ret_type,
238
238
  )
239
- document.stack.append(
240
- ExprReturn(accept_type=ret_type, ret_type=ret_type)
241
- )
239
+ # TODO: add ast tests
240
+ # in inheritance schemas, child classes use same fields are used as in the parent class
241
+ # avoid duplicate ExprReturn node
242
+ # second case used in ExprDefaultValueWrapper cases
243
+ if (
244
+ document.stack[-1].kind != ExprReturn.kind
245
+ and document.stack[-1].kind != TokenType.EXPR_DEFAULT_END
246
+ ):
247
+ document.stack.append(
248
+ ExprReturn(accept_type=ret_type, ret_type=ret_type)
249
+ )
250
+
242
251
  _unwrap_default_node(document, ret_type)
243
252
  for i in document.stack:
244
253
  i.parent = method
@@ -255,7 +264,6 @@ def _fetch_field_nodes(
255
264
  cls_name = None
256
265
  body_parse_method_expr.append(
257
266
  ExprCallStructMethod(
258
- # parent=method,
259
267
  kwargs={
260
268
  "name": field_name,
261
269
  "type": ret_type,
@@ -298,9 +306,18 @@ def _try_fetch_split_doc_node(
298
306
  ) -> None:
299
307
  if fields.get("__SPLIT_DOC__"):
300
308
  split_doc = fields.pop("__SPLIT_DOC__")
301
- # always sequence of elements
302
309
  method = StructPartDocMethod(parent=st_ref)
303
- split_doc.stack.append(ExprReturn(ret_type=VariableType.LIST_DOCUMENT))
310
+
311
+ # in inheritance schemas, child classes use same fields are used as in the parent class
312
+ # second case used in ExprDefaultValueWrapper cases
313
+ if (
314
+ split_doc.stack[-1].kind != ExprReturn.kind
315
+ and split_doc.stack[-1].kind != TokenType.EXPR_DEFAULT_END
316
+ ):
317
+ # always returns sequence of elements
318
+ split_doc.stack.append(
319
+ ExprReturn(ret_type=VariableType.LIST_DOCUMENT)
320
+ )
304
321
  for i in split_doc.stack:
305
322
  i.parent = method
306
323
  method.body = split_doc.stack
@@ -4,8 +4,8 @@ from typing import Callable
4
4
  from ssc_codegen.str_utils import (
5
5
  go_unimport_naive,
6
6
  py_optimize_return_naive,
7
- py_str_format_to_fstring,
8
7
  js_pure_optimize_return,
8
+ py_remove_unused_none_type_import,
9
9
  )
10
10
 
11
11
 
@@ -31,7 +31,7 @@ class BaseCodeCallback:
31
31
 
32
32
 
33
33
  CB_PY_CODE = BaseCodeCallback(
34
- py_optimize_return_naive, py_str_format_to_fstring
34
+ py_optimize_return_naive, py_remove_unused_none_type_import
35
35
  )
36
36
  CB_GO_CODE = BaseCodeCallback(go_unimport_naive, remove_empty_lines=True)
37
37
  CB_DART_CODE = BaseCodeCallback(remove_empty_lines=True)
@@ -150,7 +150,6 @@ MAGIC_METHODS = {
150
150
 
151
151
  # used old style typing for support old python versions (3.8)
152
152
  IMPORTS_MIN = """
153
- from __future__ import annotations
154
153
  import re
155
154
  import sys
156
155
  import json
@@ -281,7 +280,7 @@ def get_field_method_ret_type(node: StructFieldMethod) -> str:
281
280
  def pre_docstring(node: Docstring) -> str:
282
281
  value, *_ = node.unpack_args()
283
282
  if value:
284
- return '"""' + value + '""""'
283
+ return '"""' + value + '"""'
285
284
  return ""
286
285
 
287
286
 
@@ -368,7 +367,8 @@ def pre_struct_parser(node: StructParser) -> str:
368
367
 
369
368
 
370
369
  def pre_ret(node: ExprReturn) -> str:
371
- expr = f"return v{node.index_prev}"
370
+ prv, _ = prev_next_var(node)
371
+ expr = f"return {prv}"
372
372
  if have_default_expr(node):
373
373
  return INDENT_DEFAULT_BODY + expr
374
374
  return INDENT_METHOD_BODY + expr
@@ -670,13 +670,12 @@ def pre_str_regex(node: ExprStringRegex) -> str:
670
670
  )
671
671
  prv, nxt = prev_next_var(node)
672
672
  pattern, group, ignore_case = node.unpack_args()
673
- pattern = repr(pattern)
674
673
  if ignore_case:
675
674
  return (
676
675
  indent
677
- + f"{nxt} = re.search({pattern}, {prv}, re.IGNORECASE)[{group}]"
676
+ + f"{nxt} = re.search(r{pattern!r}, {prv}, re.IGNORECASE)[{group}]"
678
677
  )
679
- return indent + f"{nxt} = re.search({pattern}, {prv})[{group}]"
678
+ return indent + f"{nxt} = re.search(r{pattern!r}, {prv})[{group}]"
680
679
 
681
680
 
682
681
  def pre_str_regex_all(node: ExprStringRegexAll) -> str:
@@ -686,8 +685,10 @@ def pre_str_regex_all(node: ExprStringRegexAll) -> str:
686
685
  prv, nxt = prev_next_var(node)
687
686
  pattern, ignore_case = node.unpack_args()
688
687
  if ignore_case:
689
- return indent + f"{nxt} = re.findall({pattern!r}, {prv}, re.IGNORECASE)"
690
- return indent + f"{nxt} = re.findall({pattern!r}, {prv})"
688
+ return (
689
+ indent + f"{nxt} = re.findall(r{pattern!r}, {prv}, re.IGNORECASE)"
690
+ )
691
+ return indent + f"{nxt} = re.findall(r{pattern!r}, {prv})"
691
692
 
692
693
 
693
694
  def pre_str_regex_sub(node: ExprStringRegexSub) -> str:
@@ -696,7 +697,7 @@ def pre_str_regex_sub(node: ExprStringRegexSub) -> str:
696
697
  )
697
698
  prv, nxt = prev_next_var(node)
698
699
  pattern, repl = node.unpack_args()
699
- return indent + f"{nxt} = re.sub({pattern!r}, {repl!r}, {prv})"
700
+ return indent + f"{nxt} = re.sub(r{pattern!r}, {repl!r}, {prv})"
700
701
 
701
702
 
702
703
  def pre_list_str_regex_sub(node: ExprListStringRegexSub) -> str:
@@ -705,7 +706,9 @@ def pre_list_str_regex_sub(node: ExprListStringRegexSub) -> str:
705
706
  )
706
707
  prv, nxt = prev_next_var(node)
707
708
  pattern, repl = node.unpack_args()
708
- return indent + f"{nxt} = [re.sub({pattern!r}, {repl!r}, i) for i in {prv}]"
709
+ return (
710
+ indent + f"{nxt} = [re.sub(r{pattern!r}, {repl!r}, i) for i in {prv}]"
711
+ )
709
712
 
710
713
 
711
714
  def pre_index(node: ExprIndex) -> str:
@@ -777,7 +780,7 @@ def pre_is_regex(node: ExprIsRegex) -> str:
777
780
  )
778
781
  prv, nxt = prev_next_var(node)
779
782
  pattern, ignore_case, msg = node.unpack_args()
780
- expr = indent + f"assert re.search({pattern!r}, {prv}), {msg!r}"
783
+ expr = indent + f"assert re.search(r{pattern!r}, {prv}), {msg!r}"
781
784
  if is_last_var_no_ret(node):
782
785
  return expr
783
786
  # HACK: avoid recalc variables
@@ -38,7 +38,7 @@ CONVERTER = BasePyCodeConverter()
38
38
  def pre_init(_node: StructInitMethod) -> str:
39
39
  return (
40
40
  INDENT_METHOD
41
- + "def __init__(self, document: Union[str, _SelectorType]) -> None:\n"
41
+ + "def __init__(self, document: Union[str, Selector]) -> None:\n"
42
42
  + INDENT_METHOD_BODY
43
43
  + "self._document = Selector(document) if isinstance(document, str) else document"
44
44
  )
@@ -48,7 +48,7 @@ def pre_init(_node: StructInitMethod) -> str:
48
48
  def pre_struct_pre_validate(_node: StructPreValidateMethod) -> str:
49
49
  return (
50
50
  INDENT_METHOD
51
- + "def _pre_validate(self, v: Union[Selector, _SelectorType]) -> None:"
51
+ + "def _pre_validate(self, v: Union[Selector, SelectorList]) -> None:"
52
52
  )
53
53
 
54
54
 
@@ -56,7 +56,7 @@ def pre_struct_pre_validate(_node: StructPreValidateMethod) -> str:
56
56
  def pre_struct_part_doc_method(_node: StructPartDocMethod) -> str:
57
57
  return (
58
58
  INDENT_METHOD
59
- + "def _split_doc(self, v: Union[Selector, _SelectorType]) -> SelectorList:"
59
+ + "def _split_doc(self, v: Union[Selector, SelectorList]) -> SelectorList:"
60
60
  )
61
61
 
62
62
 
@@ -67,15 +67,13 @@ def pre_struct_field_method(node: StructFieldMethod) -> str:
67
67
  name = MAGIC_METHODS.get(name, name)
68
68
  return (
69
69
  INDENT_METHOD
70
- + f"def _parse_{name}(self, v: Union[Selector, _SelectorType]) -> {type_}:"
70
+ + f"def _parse_{name}(self, v: Union[Selector, SelectorList]) -> {type_}:"
71
71
  )
72
72
 
73
73
 
74
74
  @CONVERTER.post(ModuleImports.kind)
75
75
  def post_imports(_: ModuleImports) -> str:
76
- return """from parsel import Selector, SelectorList
77
- from parsel.selector import _SelectorType # noqa
78
- """
76
+ return """from parsel import Selector, SelectorList"""
79
77
 
80
78
 
81
79
  @CONVERTER(ExprCss.kind)
@@ -86,9 +86,8 @@ class BaseSchema:
86
86
  ].kwargs["schema_name"]
87
87
  signature[key] = cls.__NESTED_SCHEMAS__[name].__class_signature__()
88
88
  elif field.stack_last_ret == VariableType.JSON:
89
- json_cls = cls.__JSON_SCHEMAS__[
90
- field.stack[-1].kwargs["json_struct_name"]
91
- ]
89
+ name = [e for e in field.stack if e.kind == TokenType.TO_JSON][0].kwargs["json_struct_name"]
90
+ json_cls = cls.__JSON_SCHEMAS__[name]
92
91
  signature[key] = json_struct_to_signature(json_cls)
93
92
  else:
94
93
  signature[key] = SIGNATURE_MAP[field.stack_last_ret]
@@ -16,6 +16,7 @@ __all__ = [
16
16
  "py_str_format_to_fstring",
17
17
  "py_optimize_return_naive",
18
18
  "js_pure_optimize_return",
19
+ "py_remove_unused_none_type_import",
19
20
  ]
20
21
 
21
22
 
@@ -178,6 +179,17 @@ RE_JS_METHOD_BLOCK = re.compile(
178
179
  )
179
180
 
180
181
 
182
+ RE_PY_REMOVE_NONE_TYPE_IMPORT = re.compile(
183
+ r"if sys\.version_info >= \(3, 10\):[^)]*\(None\)", flags=re.MULTILINE
184
+ )
185
+
186
+
187
+ def py_remove_unused_none_type_import(py_code: str) -> str:
188
+ if len(re.findall(r"\bNoneType\b", py_code)) == 2:
189
+ return RE_PY_REMOVE_NONE_TYPE_IMPORT.sub("", py_code)
190
+ return py_code
191
+
192
+
181
193
  def js_pure_optimize_return(js_code: str) -> str:
182
194
  tmp_code = js_code
183
195
  for method_code in RE_JS_METHOD_BLOCK.finditer(tmp_code):
File without changes
File without changes
File without changes