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.
- {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/PKG-INFO +1 -1
- {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/pyproject.toml +24 -1
- {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/__init__.py +1 -1
- {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/ast_build/utils.py +9 -2
- {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/converters/py_base.py +7 -11
- {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/document.py +0 -1
- {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/schema.py +3 -1
- {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/str_utils.py +13 -1
- {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/.gitignore +0 -0
- {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/LICENSE +0 -0
- {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/README.md +0 -0
- {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/_compat.py +0 -0
- {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/ast_/__init__.py +0 -0
- {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/ast_/base.py +0 -0
- {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/ast_/nodes_array.py +0 -0
- {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/ast_/nodes_cast.py +0 -0
- {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/ast_/nodes_core.py +0 -0
- {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/ast_/nodes_selectors.py +0 -0
- {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/ast_/nodes_string.py +0 -0
- {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/ast_/nodes_validate.py +0 -0
- {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/ast_build/__init__.py +0 -0
- {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/ast_build/main.py +0 -0
- {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/cli/__init__.py +0 -0
- {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/cli/cli_callbacks.py +0 -0
- {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/cli/cli_utils.py +0 -0
- {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/cli/code_callbacks.py +0 -0
- {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/cli/consts.py +0 -0
- {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/cli/main.py +0 -0
- {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/cli/runtime_parse_runners.py +0 -0
- {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/compiler.py +0 -0
- {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/consts.py +0 -0
- {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/converters/__init__.py +0 -0
- {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/converters/base.py +0 -0
- {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/converters/go_goquery.py +0 -0
- {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/converters/helpers.py +0 -0
- {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/converters/js_pure.py +0 -0
- {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/converters/py_bs4.py +0 -0
- {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/converters/py_parsel.py +0 -0
- {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/converters/py_selectolax.py +0 -0
- {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/converters/templates/__init__.py +0 -0
- {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/converters/templates/go_goquery.py +0 -0
- {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/converters/templates/js_pure.py +0 -0
- {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/document_utlis.py +0 -0
- {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/json_struct.py +0 -0
- {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/json_to_scc.py +0 -0
- {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/logs.py +0 -0
- {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/selector_utils.py +0 -0
- {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/static_checker/__init__.py +0 -0
- {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/static_checker/base.py +0 -0
- {ssc_codegen-0.8.2 → ssc_codegen-0.8.4}/ssc_codegen/static_checker/callbacks.py +0 -0
- {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.
|
|
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.
|
|
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
|
+
]
|
|
@@ -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
|
-
|
|
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(
|
|
676
|
+
+ f"{nxt} = re.search({pattern!r}, {prv}, re.IGNORECASE)[{group}]"
|
|
677
677
|
)
|
|
678
|
-
return indent + f"{nxt} = re.search(
|
|
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
|
-
|
|
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(
|
|
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(
|
|
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
|
|
@@ -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][
|
|
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
|
-
#
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|