ssc_codegen 0.8.2__tar.gz → 0.8.4__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 (51) hide show
  1. {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/PKG-INFO +1 -1
  2. {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/pyproject.toml +24 -1
  3. {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/__init__.py +1 -1
  4. {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/ast_build/utils.py +9 -2
  5. {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/converters/py_base.py +7 -11
  6. {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/document.py +0 -1
  7. {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/schema.py +3 -1
  8. {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/str_utils.py +13 -1
  9. {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/.gitignore +0 -0
  10. {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/LICENSE +0 -0
  11. {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/README.md +0 -0
  12. {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/_compat.py +0 -0
  13. {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/ast_/__init__.py +0 -0
  14. {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/ast_/base.py +0 -0
  15. {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/ast_/nodes_array.py +0 -0
  16. {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/ast_/nodes_cast.py +0 -0
  17. {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/ast_/nodes_core.py +0 -0
  18. {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/ast_/nodes_selectors.py +0 -0
  19. {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/ast_/nodes_string.py +0 -0
  20. {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/ast_/nodes_validate.py +0 -0
  21. {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/ast_build/__init__.py +0 -0
  22. {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/ast_build/main.py +0 -0
  23. {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/cli/__init__.py +0 -0
  24. {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/cli/cli_callbacks.py +0 -0
  25. {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/cli/cli_utils.py +0 -0
  26. {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/cli/code_callbacks.py +0 -0
  27. {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/cli/consts.py +0 -0
  28. {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/cli/main.py +0 -0
  29. {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/cli/runtime_parse_runners.py +0 -0
  30. {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/compiler.py +0 -0
  31. {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/consts.py +0 -0
  32. {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/converters/__init__.py +0 -0
  33. {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/converters/base.py +0 -0
  34. {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/converters/go_goquery.py +0 -0
  35. {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/converters/helpers.py +0 -0
  36. {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/converters/js_pure.py +0 -0
  37. {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/converters/py_bs4.py +0 -0
  38. {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/converters/py_parsel.py +0 -0
  39. {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/converters/py_selectolax.py +0 -0
  40. {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/converters/templates/__init__.py +0 -0
  41. {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/converters/templates/go_goquery.py +0 -0
  42. {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/converters/templates/js_pure.py +0 -0
  43. {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/document_utlis.py +0 -0
  44. {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/json_struct.py +0 -0
  45. {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/json_to_scc.py +0 -0
  46. {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/logs.py +0 -0
  47. {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/selector_utils.py +0 -0
  48. {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/static_checker/__init__.py +0 -0
  49. {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/static_checker/base.py +0 -0
  50. {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/static_checker/callbacks.py +0 -0
  51. {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/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.2
3
+ Version: 0.8.4
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.2"
3
+ version = "0.8.4"
4
4
  description = "Python-dsl code converter to html parser for web scraping "
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.10"
@@ -84,3 +84,26 @@ exclude = [
84
84
  [[tool.mypy.overrides]]
85
85
  module="tests.*"
86
86
  disallow_untyped_defs = false
87
+
88
+
89
+ [tool.coverage.report]
90
+ exclude_also = [
91
+ 'def __repr__',
92
+ 'if self.debug:',
93
+ 'if settings.DEBUG',
94
+ 'raise AssertionError',
95
+ 'raise NotImplementedError',
96
+ 'if 0:',
97
+ 'if __name__ == .__main__.:',
98
+ 'if TYPE_CHECKING:',
99
+ 'class .*\bProtocol\):',
100
+ '@(abc\.)?abstractmethod',
101
+ ]
102
+
103
+ [tool.coverage.run]
104
+ source = ["ssc_codegen"]
105
+ omit = [
106
+ "*/.venv/*",
107
+ "*/scripts/*",
108
+ "*/tests/*"
109
+ ]
@@ -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.2"
10
+ VERSION = "0.8.4"
11
11
 
12
12
 
13
13
  class __MISSING(object):
@@ -1,5 +1,6 @@
1
1
  import json
2
2
  import logging
3
+ import sys
3
4
  from pathlib import Path
4
5
  from types import ModuleType
5
6
  from typing import Any, Type
@@ -87,10 +88,16 @@ def extract_json_structs_from_module(module: ModuleType) -> list[Type[Json]]:
87
88
  ]
88
89
 
89
90
 
90
- def exec_module_code(path: str | Path) -> ModuleType:
91
+ def exec_module_code(path: str | Path, add_sys_path: bool = True) -> ModuleType:
92
+ # apologize, input - real python file
91
93
  if isinstance(path, str):
92
94
  path = Path(path)
93
95
  module = ModuleType("_")
94
- code = Path(path.resolve()).read_text()
96
+ abs_path = path.resolve()
97
+ # required for correct imports (eg: constants)
98
+ if add_sys_path and str(abs_path.parent) not in sys.path:
99
+ sys.path.append(str(abs_path.parent))
100
+
101
+ code = Path(abs_path).read_text()
95
102
  exec(code, module.__dict__)
96
103
  return module
@@ -673,9 +673,9 @@ def pre_str_regex(node: ExprStringRegex) -> str:
673
673
  if ignore_case:
674
674
  return (
675
675
  indent
676
- + f"{nxt} = re.search(r{pattern!r}, {prv}, re.IGNORECASE)[{group}]"
676
+ + f"{nxt} = re.search({pattern!r}, {prv}, re.IGNORECASE)[{group}]"
677
677
  )
678
- return indent + f"{nxt} = re.search(r{pattern!r}, {prv})[{group}]"
678
+ return indent + f"{nxt} = re.search({pattern!r}, {prv})[{group}]"
679
679
 
680
680
 
681
681
  def pre_str_regex_all(node: ExprStringRegexAll) -> str:
@@ -685,10 +685,8 @@ def pre_str_regex_all(node: ExprStringRegexAll) -> str:
685
685
  prv, nxt = prev_next_var(node)
686
686
  pattern, ignore_case = node.unpack_args()
687
687
  if ignore_case:
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})"
688
+ return indent + f"{nxt} = re.findall({pattern!r}, {prv}, re.IGNORECASE)"
689
+ return indent + f"{nxt} = re.findall({pattern!r}, {prv})"
692
690
 
693
691
 
694
692
  def pre_str_regex_sub(node: ExprStringRegexSub) -> str:
@@ -697,7 +695,7 @@ def pre_str_regex_sub(node: ExprStringRegexSub) -> str:
697
695
  )
698
696
  prv, nxt = prev_next_var(node)
699
697
  pattern, repl = node.unpack_args()
700
- return indent + f"{nxt} = re.sub(r{pattern!r}, {repl!r}, {prv})"
698
+ return indent + f"{nxt} = re.sub({pattern!r}, {repl!r}, {prv})"
701
699
 
702
700
 
703
701
  def pre_list_str_regex_sub(node: ExprListStringRegexSub) -> str:
@@ -706,9 +704,7 @@ def pre_list_str_regex_sub(node: ExprListStringRegexSub) -> str:
706
704
  )
707
705
  prv, nxt = prev_next_var(node)
708
706
  pattern, repl = node.unpack_args()
709
- return (
710
- indent + f"{nxt} = [re.sub(r{pattern!r}, {repl!r}, i) for i in {prv}]"
711
- )
707
+ return indent + f"{nxt} = [re.sub({pattern!r}, {repl!r}, i) for i in {prv}]"
712
708
 
713
709
 
714
710
  def pre_index(node: ExprIndex) -> str:
@@ -780,7 +776,7 @@ def pre_is_regex(node: ExprIsRegex) -> str:
780
776
  )
781
777
  prv, nxt = prev_next_var(node)
782
778
  pattern, ignore_case, msg = node.unpack_args()
783
- expr = indent + f"assert re.search(r{pattern!r}, {prv}), {msg!r}"
779
+ expr = indent + f"assert re.search({pattern!r}, {prv}), {msg!r}"
784
780
  if is_last_var_no_ret(node):
785
781
  return expr
786
782
  # HACK: avoid recalc variables
@@ -654,7 +654,6 @@ class StringDocument(BaseDocument):
654
654
 
655
655
  - accept STRING, return STRING
656
656
  """
657
- # TODO: implement, js, go, dart ignorecase flag
658
657
  if not isinstance(pattern, str):
659
658
  ignore_case = is_ignore_case_regex(pattern)
660
659
 
@@ -86,7 +86,9 @@ 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
- name = [e for e in field.stack if e.kind == TokenType.TO_JSON][0].kwargs["json_struct_name"]
89
+ name = [e for e in field.stack if e.kind == TokenType.TO_JSON][
90
+ 0
91
+ ].kwargs["json_struct_name"]
90
92
  json_cls = cls.__JSON_SCHEMAS__[name]
91
93
  signature[key] = json_struct_to_signature(json_cls)
92
94
  else:
@@ -144,11 +144,23 @@ def py_optimize_return_naive(py_code: str) -> str:
144
144
  tmp_code = py_code
145
145
  for method_block in RE_PY_METHOD_BLOCK.finditer(tmp_code):
146
146
  ret_var = method_block["ret_var"]
147
- # value6\s*=\s*(?P<expr>.*)$
147
+ # v6\s*=\s*(?P<expr>.*)$
148
148
  re_expr = f"{ret_var}\\s*=\\s*(?P<expr>.*)"
149
149
  if match := re.search(re_expr, method_block[0]):
150
150
  expr = match["expr"] # noqa
151
151
 
152
+ # optimization function convert double backslash to single (\\ -> \) in regex patterns
153
+ # add `r` prefix for avoid SyntaxWarning then compile generated code to cpython bytecode
154
+ def add_r_prefix(m: re.Match) -> str:
155
+ func, string = m.groups()
156
+ if not string.startswith(('r"', "r'")):
157
+ return f"{func}r{string}"
158
+ return match.group(0)
159
+
160
+ # in patterns codegen used single quotas literals
161
+ expr = re.sub(
162
+ r'(\bre\.\w+\()\s*(".*?"|\'.*?\')', add_r_prefix, expr
163
+ )
152
164
  new_method_block = re.sub(f"\\s*{re_expr}", "", method_block[0])
153
165
  new_method_block = re.sub(
154
166
  rf"return {ret_var}", f"return {expr}", new_method_block
File without changes
File without changes
File without changes