ssc_codegen 0.40.0__tar.gz → 0.41.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.
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/PKG-INFO +1 -1
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/pyproject.toml +124 -124
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/generation/builder.py +9 -2
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/generation/runtime.py +9 -3
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/main.py +39 -1
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/targets/python/html_libs/base.py +5 -1
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/targets/python/html_libs/bs4.py +59 -9
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/targets/python/http_libs/aiohttp.py +81 -59
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/targets/python/http_libs/base.py +6 -1
- ssc_codegen-0.41.0/ssc_codegen/targets/python/http_libs/httpx.py +181 -0
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/targets/python/http_libs/requests.py +67 -44
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/targets/python/rest.py +92 -51
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/targets/python/visitor.py +55 -16
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/targets/resolver.py +282 -227
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/targets/spec.py +67 -61
- ssc_codegen-0.40.0/ssc_codegen/targets/python/http_libs/httpx.py +0 -139
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/.gitignore +0 -0
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/LICENSE +0 -0
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/README.md +0 -0
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/__init__.py +0 -0
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/_logging.py +0 -0
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/ast/__init__.py +0 -0
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/ast/array.py +0 -0
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/ast/base.py +0 -0
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/ast/cast.py +0 -0
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/ast/control.py +0 -0
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/ast/extension.py +0 -0
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/ast/extract.py +0 -0
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/ast/function.py +0 -0
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/ast/jsondef.py +0 -0
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/ast/module.py +0 -0
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/ast/predicate_containers.py +0 -0
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/ast/predicate_ops.py +0 -0
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/ast/regex.py +0 -0
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/ast/rest.py +0 -0
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/ast/selectors.py +0 -0
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/ast/string.py +0 -0
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/ast/struct.py +0 -0
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/ast/typedef.py +0 -0
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/ast/types.py +0 -0
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/core/__init__.py +0 -0
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/core/contexts.py +0 -0
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/core/expressions.py +0 -0
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/core/extensions.py +0 -0
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/core/format.py +0 -0
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/core/imports.py +0 -0
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/core/linter.py +0 -0
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/core/module_handler.py +0 -0
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/core/predicates.py +0 -0
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/core/reader.py +0 -0
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/core/rest_artifacts.py +0 -0
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/core/struct_parser.py +0 -0
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/core/type_checking.py +0 -0
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/exceptions.py +0 -0
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/explore.py +0 -0
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/generation/__init__.py +0 -0
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/health.py +0 -0
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/json_to_kdl.py +0 -0
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/naming.py +0 -0
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/parsers/__init__.py +0 -0
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/parsers/curl.py +0 -0
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/parsers/http.py +0 -0
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/regex_utils.py +0 -0
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/request_spec.py +0 -0
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/symbols.py +0 -0
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/targets/__init__.py +0 -0
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/targets/golang/__init__.py +0 -0
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/targets/golang/http_libs/__init__.py +0 -0
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/targets/golang/http_libs/base.py +0 -0
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/targets/golang/http_libs/nethttp.py +0 -0
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/targets/golang/literals.py +0 -0
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/targets/golang/regex.py +0 -0
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/targets/golang/rest.py +0 -0
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/targets/golang/runtime.py +0 -0
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/targets/golang/visitor.py +0 -0
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/targets/javascript/__init__.py +0 -0
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/targets/javascript/http_libs/__init__.py +0 -0
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/targets/javascript/http_libs/axios.py +0 -0
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/targets/javascript/http_libs/base.py +0 -0
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/targets/javascript/http_libs/fetch.py +0 -0
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/targets/javascript/rest.py +0 -0
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/targets/javascript/visitor.py +0 -0
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/targets/profile.py +0 -0
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/targets/python/__init__.py +0 -0
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/targets/python/html_libs/__init__.py +0 -0
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/targets/python/html_libs/lxml.py +0 -0
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/targets/python/html_libs/parsel.py +0 -0
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/targets/python/html_libs/slax.py +0 -0
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/targets/python/http_libs/__init__.py +0 -0
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/targets/rust/__init__.py +0 -0
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/targets/rust/regex.py +0 -0
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/targets/rust/rest.py +0 -0
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/targets/rust/runtime.py +0 -0
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/targets/rust/visitor.py +0 -0
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/traversal/__init__.py +0 -0
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/traversal/context.py +0 -0
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/traversal/utils.py +0 -0
- {ssc_codegen-0.40.0 → ssc_codegen-0.41.0}/ssc_codegen/traversal/walker.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: ssc_codegen
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.41.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
|
|
@@ -1,124 +1,124 @@
|
|
|
1
|
-
[project]
|
|
2
|
-
name = "ssc_codegen"
|
|
3
|
-
version = "0.
|
|
4
|
-
description = "Python-dsl code converter to html parser for web scraping "
|
|
5
|
-
readme = "README.md"
|
|
6
|
-
requires-python = ">=3.10"
|
|
7
|
-
dependencies = [
|
|
8
|
-
"bs4>=0.0.2",
|
|
9
|
-
"colorama>=0.4.6 ; sys_platform == 'win32'",
|
|
10
|
-
"cssselect>=1.2.0",
|
|
11
|
-
"lxml>=5.3.0",
|
|
12
|
-
"soupsieve>=2.6",
|
|
13
|
-
"typer>0.26",
|
|
14
|
-
"typing_extensions;python_version<'3.11'",
|
|
15
|
-
"kdlquery>=1.3.0",
|
|
16
|
-
"httpx>=0.28.1",
|
|
17
|
-
]
|
|
18
|
-
|
|
19
|
-
classifiers = [
|
|
20
|
-
"Development Status :: 3 - Alpha",
|
|
21
|
-
"Environment :: Console",
|
|
22
|
-
"Intended Audience :: Developers",
|
|
23
|
-
"License :: OSI Approved :: MIT License",
|
|
24
|
-
"Topic :: Software Development :: Code Generators",
|
|
25
|
-
"Topic :: Text Processing :: Markup :: HTML",
|
|
26
|
-
"Topic :: Utilities",
|
|
27
|
-
"Programming Language :: Python :: 3.10",
|
|
28
|
-
"Programming Language :: Python :: 3.11",
|
|
29
|
-
"Programming Language :: Python :: 3.12",
|
|
30
|
-
"Programming Language :: Python :: 3.13",
|
|
31
|
-
]
|
|
32
|
-
|
|
33
|
-
[project.urls]
|
|
34
|
-
Documentation = "https://github.com/vypivshiy/selector_schema_codegen#readme"
|
|
35
|
-
Issues = "https://github.com/vypivshiy/selector_schema_codegen/issues"
|
|
36
|
-
Source = "https://github.com/vypivshiy/selector_schema_codegen"
|
|
37
|
-
Examples = "https://github.com/vypivshiy/selector_schema_codegen/examples"
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
[project.scripts]
|
|
41
|
-
ssc-gen = 'ssc_codegen.main:main'
|
|
42
|
-
|
|
43
|
-
[build-system]
|
|
44
|
-
requires = ["hatchling"]
|
|
45
|
-
build-backend = "hatchling.build"
|
|
46
|
-
|
|
47
|
-
[tool.hatch.build.targets.sdist]
|
|
48
|
-
include = [
|
|
49
|
-
"ssc_codegen/**",
|
|
50
|
-
]
|
|
51
|
-
|
|
52
|
-
[tool.hatch.build.targets.wheel]
|
|
53
|
-
packages = ["ssc_codegen"]
|
|
54
|
-
|
|
55
|
-
[dependency-groups]
|
|
56
|
-
dev = [
|
|
57
|
-
"aiohttp>=3.9,<3.12", # aioresponses 0.7.x breaks on 3.12+ (stream_writer)
|
|
58
|
-
"aioresponses>=0.7",
|
|
59
|
-
"bs4>=0.0.2",
|
|
60
|
-
"coverage>=7.6.12",
|
|
61
|
-
"httpx>=0.28.1",
|
|
62
|
-
"hypothesis>=6.151.9",
|
|
63
|
-
"lxml>=5.3.0",
|
|
64
|
-
"mypy>=1.14.1",
|
|
65
|
-
"parsel>=1.9.1",
|
|
66
|
-
"pytest>=8.3.4",
|
|
67
|
-
"pytest-xdist>=3.6.0",
|
|
68
|
-
"respx>=0.23.1",
|
|
69
|
-
"responses>=0.25",
|
|
70
|
-
"ruff>=0.9.3",
|
|
71
|
-
"selectolax>=0.3.27",
|
|
72
|
-
]
|
|
73
|
-
docs = [
|
|
74
|
-
"mkdocs>=1.6.0",
|
|
75
|
-
"mkdocs-material>=9.5.0",
|
|
76
|
-
"mkdocstrings[python]>=0.27.0",
|
|
77
|
-
"mkdocs-click>=0.8.1",
|
|
78
|
-
]
|
|
79
|
-
|
|
80
|
-
[tool.ruff]
|
|
81
|
-
target-version = "py310"
|
|
82
|
-
line-length = 80
|
|
83
|
-
exclude = ["__init__.py"]
|
|
84
|
-
|
|
85
|
-
[tool.mypy]
|
|
86
|
-
python_version = "3.10"
|
|
87
|
-
show_error_codes = true
|
|
88
|
-
[[tool.mypy.overrides]]
|
|
89
|
-
module="tests.*"
|
|
90
|
-
disallow_untyped_defs = false
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
[[tool.mypy.overrides]]
|
|
94
|
-
module = ["colorama", "lxml", "lxml.*"]
|
|
95
|
-
ignore_missing_imports = true
|
|
96
|
-
|
|
97
|
-
[tool.coverage.report]
|
|
98
|
-
exclude_also = [
|
|
99
|
-
'def __repr__',
|
|
100
|
-
'if self.debug:',
|
|
101
|
-
'if settings.DEBUG',
|
|
102
|
-
'raise AssertionError',
|
|
103
|
-
'raise NotImplementedError',
|
|
104
|
-
'if 0:',
|
|
105
|
-
'if __name__ == .__main__.:',
|
|
106
|
-
'if TYPE_CHECKING:',
|
|
107
|
-
'class .*\bProtocol\):',
|
|
108
|
-
'@(abc\.)?abstractmethod',
|
|
109
|
-
]
|
|
110
|
-
|
|
111
|
-
[tool.coverage.run]
|
|
112
|
-
source = ["ssc_codegen"]
|
|
113
|
-
omit = [
|
|
114
|
-
"*/.venv/*",
|
|
115
|
-
"*/scripts/*",
|
|
116
|
-
"*/tests/*"
|
|
117
|
-
]
|
|
118
|
-
|
|
119
|
-
[tool.pytest.ini_options]
|
|
120
|
-
testpaths = ["tests"]
|
|
121
|
-
markers = [
|
|
122
|
-
"toolchain: Tests requiring external toolchains (Rust cargo, Go compiler, Node.js)",
|
|
123
|
-
]
|
|
124
|
-
|
|
1
|
+
[project]
|
|
2
|
+
name = "ssc_codegen"
|
|
3
|
+
version = "0.41.0"
|
|
4
|
+
description = "Python-dsl code converter to html parser for web scraping "
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.10"
|
|
7
|
+
dependencies = [
|
|
8
|
+
"bs4>=0.0.2",
|
|
9
|
+
"colorama>=0.4.6 ; sys_platform == 'win32'",
|
|
10
|
+
"cssselect>=1.2.0",
|
|
11
|
+
"lxml>=5.3.0",
|
|
12
|
+
"soupsieve>=2.6",
|
|
13
|
+
"typer>0.26",
|
|
14
|
+
"typing_extensions;python_version<'3.11'",
|
|
15
|
+
"kdlquery>=1.3.0",
|
|
16
|
+
"httpx>=0.28.1",
|
|
17
|
+
]
|
|
18
|
+
|
|
19
|
+
classifiers = [
|
|
20
|
+
"Development Status :: 3 - Alpha",
|
|
21
|
+
"Environment :: Console",
|
|
22
|
+
"Intended Audience :: Developers",
|
|
23
|
+
"License :: OSI Approved :: MIT License",
|
|
24
|
+
"Topic :: Software Development :: Code Generators",
|
|
25
|
+
"Topic :: Text Processing :: Markup :: HTML",
|
|
26
|
+
"Topic :: Utilities",
|
|
27
|
+
"Programming Language :: Python :: 3.10",
|
|
28
|
+
"Programming Language :: Python :: 3.11",
|
|
29
|
+
"Programming Language :: Python :: 3.12",
|
|
30
|
+
"Programming Language :: Python :: 3.13",
|
|
31
|
+
]
|
|
32
|
+
|
|
33
|
+
[project.urls]
|
|
34
|
+
Documentation = "https://github.com/vypivshiy/selector_schema_codegen#readme"
|
|
35
|
+
Issues = "https://github.com/vypivshiy/selector_schema_codegen/issues"
|
|
36
|
+
Source = "https://github.com/vypivshiy/selector_schema_codegen"
|
|
37
|
+
Examples = "https://github.com/vypivshiy/selector_schema_codegen/examples"
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
[project.scripts]
|
|
41
|
+
ssc-gen = 'ssc_codegen.main:main'
|
|
42
|
+
|
|
43
|
+
[build-system]
|
|
44
|
+
requires = ["hatchling"]
|
|
45
|
+
build-backend = "hatchling.build"
|
|
46
|
+
|
|
47
|
+
[tool.hatch.build.targets.sdist]
|
|
48
|
+
include = [
|
|
49
|
+
"ssc_codegen/**",
|
|
50
|
+
]
|
|
51
|
+
|
|
52
|
+
[tool.hatch.build.targets.wheel]
|
|
53
|
+
packages = ["ssc_codegen"]
|
|
54
|
+
|
|
55
|
+
[dependency-groups]
|
|
56
|
+
dev = [
|
|
57
|
+
"aiohttp>=3.9,<3.12", # aioresponses 0.7.x breaks on 3.12+ (stream_writer)
|
|
58
|
+
"aioresponses>=0.7",
|
|
59
|
+
"bs4>=0.0.2",
|
|
60
|
+
"coverage>=7.6.12",
|
|
61
|
+
"httpx>=0.28.1",
|
|
62
|
+
"hypothesis>=6.151.9",
|
|
63
|
+
"lxml>=5.3.0",
|
|
64
|
+
"mypy>=1.14.1",
|
|
65
|
+
"parsel>=1.9.1",
|
|
66
|
+
"pytest>=8.3.4",
|
|
67
|
+
"pytest-xdist>=3.6.0",
|
|
68
|
+
"respx>=0.23.1",
|
|
69
|
+
"responses>=0.25",
|
|
70
|
+
"ruff>=0.9.3",
|
|
71
|
+
"selectolax>=0.3.27",
|
|
72
|
+
]
|
|
73
|
+
docs = [
|
|
74
|
+
"mkdocs>=1.6.0",
|
|
75
|
+
"mkdocs-material>=9.5.0",
|
|
76
|
+
"mkdocstrings[python]>=0.27.0",
|
|
77
|
+
"mkdocs-click>=0.8.1",
|
|
78
|
+
]
|
|
79
|
+
|
|
80
|
+
[tool.ruff]
|
|
81
|
+
target-version = "py310"
|
|
82
|
+
line-length = 80
|
|
83
|
+
exclude = ["__init__.py"]
|
|
84
|
+
|
|
85
|
+
[tool.mypy]
|
|
86
|
+
python_version = "3.10"
|
|
87
|
+
show_error_codes = true
|
|
88
|
+
[[tool.mypy.overrides]]
|
|
89
|
+
module="tests.*"
|
|
90
|
+
disallow_untyped_defs = false
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
[[tool.mypy.overrides]]
|
|
94
|
+
module = ["colorama", "lxml", "lxml.*"]
|
|
95
|
+
ignore_missing_imports = true
|
|
96
|
+
|
|
97
|
+
[tool.coverage.report]
|
|
98
|
+
exclude_also = [
|
|
99
|
+
'def __repr__',
|
|
100
|
+
'if self.debug:',
|
|
101
|
+
'if settings.DEBUG',
|
|
102
|
+
'raise AssertionError',
|
|
103
|
+
'raise NotImplementedError',
|
|
104
|
+
'if 0:',
|
|
105
|
+
'if __name__ == .__main__.:',
|
|
106
|
+
'if TYPE_CHECKING:',
|
|
107
|
+
'class .*\bProtocol\):',
|
|
108
|
+
'@(abc\.)?abstractmethod',
|
|
109
|
+
]
|
|
110
|
+
|
|
111
|
+
[tool.coverage.run]
|
|
112
|
+
source = ["ssc_codegen"]
|
|
113
|
+
omit = [
|
|
114
|
+
"*/.venv/*",
|
|
115
|
+
"*/scripts/*",
|
|
116
|
+
"*/tests/*"
|
|
117
|
+
]
|
|
118
|
+
|
|
119
|
+
[tool.pytest.ini_options]
|
|
120
|
+
testpaths = ["tests"]
|
|
121
|
+
markers = [
|
|
122
|
+
"toolchain: Tests requiring external toolchains (Rust cargo, Go compiler, Node.js)",
|
|
123
|
+
]
|
|
124
|
+
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
+
import inspect
|
|
6
|
+
|
|
5
7
|
|
|
6
8
|
class ModuleBuilder:
|
|
7
9
|
"""Language-agnostic accumulator for imports and helper definitions.
|
|
@@ -50,12 +52,17 @@ class ModuleBuilder:
|
|
|
50
52
|
def require_import(self, line: str) -> None:
|
|
51
53
|
"""Register a top-level import line.
|
|
52
54
|
|
|
53
|
-
Deduplicated and order-preserving.
|
|
55
|
+
Deduplicated and order-preserving. Multi-line blocks are normalized
|
|
56
|
+
with `inspect.cleandoc` to remove uniform indentation.
|
|
54
57
|
|
|
55
58
|
Args:
|
|
56
59
|
line: The verbatim import statement line for the target language.
|
|
57
60
|
"""
|
|
58
|
-
|
|
61
|
+
if "\n" in line:
|
|
62
|
+
cleaned = inspect.cleandoc(line)
|
|
63
|
+
else:
|
|
64
|
+
cleaned = line
|
|
65
|
+
self._imports.setdefault(cleaned, None)
|
|
59
66
|
|
|
60
67
|
def require_std(
|
|
61
68
|
self,
|
|
@@ -6,7 +6,6 @@ from collections.abc import Callable
|
|
|
6
6
|
from typing import Any
|
|
7
7
|
|
|
8
8
|
import ssc_codegen.ast as a
|
|
9
|
-
|
|
10
9
|
from ssc_codegen.targets.python.http_libs.base import HttpLibStrategy
|
|
11
10
|
from ssc_codegen.targets.python.http_libs.httpx import HttpxStrategy
|
|
12
11
|
from ssc_codegen.traversal.utils import module_has_rest
|
|
@@ -439,7 +438,7 @@ def runtime_module_content(
|
|
|
439
438
|
lines.extend(_BASE_UTILITY_LINES)
|
|
440
439
|
lines.append("")
|
|
441
440
|
if has_rest:
|
|
442
|
-
lines.extend(strategy.rest_runtime_lines())
|
|
441
|
+
lines.extend(strategy.rest_runtime_lines(http_io="both"))
|
|
443
442
|
if extension_defs:
|
|
444
443
|
for _imports, code in extension_defs.values():
|
|
445
444
|
lines.append("")
|
|
@@ -485,10 +484,17 @@ def register_runtime_file(
|
|
|
485
484
|
|
|
486
485
|
@converter.file(f"{runtime_name}.py")
|
|
487
486
|
def _runtime_provider(module_ast: a.Module, meta):
|
|
487
|
+
strat = http_strategy
|
|
488
|
+
if (
|
|
489
|
+
meta
|
|
490
|
+
and meta.get("http_client")
|
|
491
|
+
and hasattr(converter, "http_strategy_for")
|
|
492
|
+
):
|
|
493
|
+
strat = converter.http_strategy_for(meta.get("http_client"))
|
|
488
494
|
return _apply_fallback(
|
|
489
495
|
runtime_module_content(
|
|
490
496
|
module_ast,
|
|
491
|
-
http_strategy=
|
|
497
|
+
http_strategy=strat,
|
|
492
498
|
extension_defs=_extension_runtime_defs([module_ast]),
|
|
493
499
|
)
|
|
494
500
|
)
|
|
@@ -152,6 +152,8 @@ def _run_generate(
|
|
|
152
152
|
skip_lint: bool = False,
|
|
153
153
|
verbose: bool = False,
|
|
154
154
|
fmt: FmtType = FmtType.TEXT,
|
|
155
|
+
bs4_parser: Optional[str] = None,
|
|
156
|
+
http_io: Optional[str] = None,
|
|
155
157
|
) -> None:
|
|
156
158
|
"""Execute the shared compilation pipeline for all code generator subcommands.
|
|
157
159
|
|
|
@@ -216,6 +218,10 @@ def _run_generate(
|
|
|
216
218
|
meta: dict = {"package": package or default_package}
|
|
217
219
|
if http_client:
|
|
218
220
|
meta["http_client"] = http_client
|
|
221
|
+
if bs4_parser:
|
|
222
|
+
meta["bs4_parser"] = bs4_parser
|
|
223
|
+
if http_io:
|
|
224
|
+
meta["http_io"] = http_io
|
|
219
225
|
|
|
220
226
|
if separate_runtime:
|
|
221
227
|
from ssc_codegen.generation.runtime import register_runtime_file
|
|
@@ -385,6 +391,16 @@ def generate_python(
|
|
|
385
391
|
help="HTML parsing library. Default: bs4.",
|
|
386
392
|
),
|
|
387
393
|
] = None,
|
|
394
|
+
bs4_parser: Annotated[
|
|
395
|
+
Optional[str],
|
|
396
|
+
typer.Option(
|
|
397
|
+
"--bs4-parser",
|
|
398
|
+
help=(
|
|
399
|
+
"Underlying HTML parser engine for bs4: "
|
|
400
|
+
"lxml (default) | html.parser | html5lib."
|
|
401
|
+
),
|
|
402
|
+
),
|
|
403
|
+
] = None,
|
|
388
404
|
verbose: Annotated[
|
|
389
405
|
bool,
|
|
390
406
|
typer.Option(
|
|
@@ -413,10 +429,17 @@ def generate_python(
|
|
|
413
429
|
"--http-client",
|
|
414
430
|
help=(
|
|
415
431
|
"HTTP client for @request codegen: "
|
|
416
|
-
"httpx (default) | aiohttp | requests."
|
|
432
|
+
"httpx (default) | httpx2 | aiohttp | requests."
|
|
417
433
|
),
|
|
418
434
|
),
|
|
419
435
|
] = None,
|
|
436
|
+
http_io: Annotated[
|
|
437
|
+
Optional[str],
|
|
438
|
+
typer.Option(
|
|
439
|
+
"--http-io",
|
|
440
|
+
help="HTTP I/O mode for generated methods: both (default) | sync | async.",
|
|
441
|
+
),
|
|
442
|
+
] = None,
|
|
420
443
|
separate_runtime: Annotated[
|
|
421
444
|
bool,
|
|
422
445
|
typer.Option(
|
|
@@ -452,6 +475,8 @@ def generate_python(
|
|
|
452
475
|
lib=lib.value if lib else None,
|
|
453
476
|
http_client=http_client,
|
|
454
477
|
separate_runtime=separate_runtime,
|
|
478
|
+
bs4_parser=bs4_parser,
|
|
479
|
+
http_io=http_io,
|
|
455
480
|
)
|
|
456
481
|
)
|
|
457
482
|
except ResolutionError as exc:
|
|
@@ -474,6 +499,8 @@ def generate_python(
|
|
|
474
499
|
skip_lint=skip_lint,
|
|
475
500
|
verbose=verbose,
|
|
476
501
|
fmt=fmt,
|
|
502
|
+
bs4_parser=bs4_parser,
|
|
503
|
+
http_io=http_io,
|
|
477
504
|
)
|
|
478
505
|
|
|
479
506
|
|
|
@@ -886,6 +913,16 @@ def run(
|
|
|
886
913
|
help="HTML parsing library. Default: bs4.",
|
|
887
914
|
),
|
|
888
915
|
] = None,
|
|
916
|
+
bs4_parser: Annotated[
|
|
917
|
+
Optional[str],
|
|
918
|
+
typer.Option(
|
|
919
|
+
"--bs4-parser",
|
|
920
|
+
help=(
|
|
921
|
+
"Underlying HTML parser engine for bs4: "
|
|
922
|
+
"lxml (default) | html.parser | html5lib."
|
|
923
|
+
),
|
|
924
|
+
),
|
|
925
|
+
] = None,
|
|
889
926
|
input_file: Annotated[
|
|
890
927
|
Path | None,
|
|
891
928
|
typer.Option(
|
|
@@ -984,6 +1021,7 @@ def run(
|
|
|
984
1021
|
TargetSpec(
|
|
985
1022
|
lang="python",
|
|
986
1023
|
lib=lib.value if lib else None,
|
|
1024
|
+
bs4_parser=bs4_parser,
|
|
987
1025
|
)
|
|
988
1026
|
)
|
|
989
1027
|
except ResolutionError as exc:
|
|
@@ -29,8 +29,8 @@ from ssc_codegen.ast.selectors import (
|
|
|
29
29
|
XpathSelect,
|
|
30
30
|
XpathSelectAll,
|
|
31
31
|
)
|
|
32
|
-
from ssc_codegen.traversal.context import WalkContext as ConverterContext
|
|
33
32
|
from ssc_codegen.generation.builder import ModuleBuilder
|
|
33
|
+
from ssc_codegen.traversal.context import WalkContext as ConverterContext
|
|
34
34
|
|
|
35
35
|
|
|
36
36
|
class DomSpelling(ABC):
|
|
@@ -54,6 +54,8 @@ class DomSpelling(ABC):
|
|
|
54
54
|
document_type: Type annotation string for a single parsed HTML element/document.
|
|
55
55
|
document_array_type: Type annotation string for a collection of elements.
|
|
56
56
|
init_arg_type: Type annotation string accepted by `__init__` (e.g. `Union[str, ...]`).
|
|
57
|
+
init_extra_params: Optional keyword parameter signature fragment for `__init__`.
|
|
58
|
+
fn_extra_params: Optional keyword parameter signature fragment for function definitions.
|
|
57
59
|
init_from_str_expr: Python expression parsing a string `document` into a DOM tree.
|
|
58
60
|
extra_utilities: Module-level helper constants or definitions.
|
|
59
61
|
supports_xpath: `True` if this DOM library supports XPath expressions natively.
|
|
@@ -78,6 +80,8 @@ class DomSpelling(ABC):
|
|
|
78
80
|
document_type: str = "Any"
|
|
79
81
|
document_array_type: str = "List[Any]"
|
|
80
82
|
init_arg_type: str = "Any"
|
|
83
|
+
init_extra_params: str = ""
|
|
84
|
+
fn_extra_params: str = ""
|
|
81
85
|
init_from_str_expr: str = "document"
|
|
82
86
|
extra_utilities: tuple[str, ...] = ()
|
|
83
87
|
supports_xpath: bool = False
|
|
@@ -27,8 +27,9 @@ from ssc_codegen.ast.selectors import (
|
|
|
27
27
|
XpathSelect,
|
|
28
28
|
XpathSelectAll,
|
|
29
29
|
)
|
|
30
|
-
from ssc_codegen.
|
|
30
|
+
from ssc_codegen.generation.builder import ModuleBuilder
|
|
31
31
|
from ssc_codegen.targets.python.html_libs.base import DomSpelling
|
|
32
|
+
from ssc_codegen.traversal.context import WalkContext as ConverterContext
|
|
32
33
|
|
|
33
34
|
|
|
34
35
|
class Bs4DomSpelling(DomSpelling):
|
|
@@ -38,24 +39,71 @@ class Bs4DomSpelling(DomSpelling):
|
|
|
38
39
|
(such as ``select_one``, ``select``, ``decompose``, ``get_text``, and tag attributes).
|
|
39
40
|
|
|
40
41
|
Attributes:
|
|
41
|
-
parser_imports: Imports ``from bs4 import BeautifulSoup, ResultSet, Tag``.
|
|
42
|
+
parser_imports: Imports ``from bs4 import BeautifulSoup, ResultSet, Tag`` and ``Literal``.
|
|
42
43
|
document_type: Type annotation ``Union[Tag, BeautifulSoup]``.
|
|
43
44
|
document_array_type: Type annotation ``ResultSet[Tag]``.
|
|
44
45
|
init_arg_type: Accepted input type ``Union[str, BeautifulSoup, Tag]``.
|
|
45
|
-
|
|
46
|
-
|
|
46
|
+
init_extra_params: Keyword argument signature with default ``features: Literal[...] = BS4_FEATURES``.
|
|
47
|
+
fn_extra_params: Function keyword argument signature with default ``features: Literal[...] = BS4_FEATURES``.
|
|
48
|
+
init_from_str_expr: Expression ``BeautifulSoup(document, features=features)``.
|
|
49
|
+
extra_utilities: Defines ``BS4_FEATURES: Literal["html.parser", "lxml", "html5lib"] = ...``.
|
|
47
50
|
supports_xpath: `False` (BeautifulSoup4 does not support XPath natively).
|
|
48
51
|
"""
|
|
49
52
|
|
|
50
53
|
# === DATA ===
|
|
51
|
-
parser_imports = (
|
|
54
|
+
parser_imports = (
|
|
55
|
+
"from bs4 import BeautifulSoup, ResultSet, Tag",
|
|
56
|
+
"from typing import Literal",
|
|
57
|
+
)
|
|
52
58
|
document_type = "Union[Tag, BeautifulSoup]"
|
|
53
59
|
document_array_type = "ResultSet[Tag]"
|
|
54
60
|
init_arg_type = "Union[str, BeautifulSoup, Tag]"
|
|
55
|
-
|
|
56
|
-
|
|
61
|
+
init_extra_params = ', *, features: Literal["html.parser", "lxml", "html5lib"] = BS4_FEATURES'
|
|
62
|
+
fn_extra_params = ', *, features: Literal["html.parser", "lxml", "html5lib"] = BS4_FEATURES'
|
|
63
|
+
init_from_str_expr = "BeautifulSoup(document, features=features)"
|
|
64
|
+
extra_utilities: tuple[str, ...] = (
|
|
65
|
+
'BS4_FEATURES: Literal["html.parser", "lxml", "html5lib"] = \'lxml\'',
|
|
66
|
+
"",
|
|
67
|
+
)
|
|
57
68
|
supports_xpath = False
|
|
58
69
|
|
|
70
|
+
def __init__(self, builder: ModuleBuilder, parser: str = "lxml") -> None:
|
|
71
|
+
"""Initialize the BeautifulSoup4 DOM spelling instance.
|
|
72
|
+
|
|
73
|
+
Args:
|
|
74
|
+
builder: Module builder used for registering imports and runtime helpers.
|
|
75
|
+
parser: Underlying HTML parser feature engine ("lxml", "html.parser",
|
|
76
|
+
or "html5lib"). Defaults to "lxml".
|
|
77
|
+
"""
|
|
78
|
+
super().__init__(builder)
|
|
79
|
+
self._parser = parser
|
|
80
|
+
self.extra_utilities = (
|
|
81
|
+
f'BS4_FEATURES: Literal["html.parser", "lxml", "html5lib"] = {parser!r}',
|
|
82
|
+
"",
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
@property
|
|
86
|
+
def parser(self) -> str:
|
|
87
|
+
"""Get the underlying HTML parser feature engine.
|
|
88
|
+
|
|
89
|
+
Returns:
|
|
90
|
+
Configured HTML parser engine name ("lxml", "html.parser", or "html5lib").
|
|
91
|
+
"""
|
|
92
|
+
return self._parser
|
|
93
|
+
|
|
94
|
+
@parser.setter
|
|
95
|
+
def parser(self, value: str) -> None:
|
|
96
|
+
"""Set the underlying HTML parser feature engine and update module constants.
|
|
97
|
+
|
|
98
|
+
Args:
|
|
99
|
+
value: HTML parser engine name ("lxml", "html.parser", or "html5lib").
|
|
100
|
+
"""
|
|
101
|
+
self._parser = value
|
|
102
|
+
self.extra_utilities = (
|
|
103
|
+
f'BS4_FEATURES: Literal["html.parser", "lxml", "html5lib"] = {value!r}',
|
|
104
|
+
"",
|
|
105
|
+
)
|
|
106
|
+
|
|
59
107
|
# === EXPRESSIONS ===
|
|
60
108
|
|
|
61
109
|
def css_select(self, ctx: ConverterContext, node: CssSelect) -> list[str]:
|
|
@@ -167,8 +215,10 @@ class Bs4DomSpelling(DomSpelling):
|
|
|
167
215
|
if node.accept_type_info.is_array:
|
|
168
216
|
return [f"{ctx.indent}{ctx.nxt} = len({ctx.prv}) > 0"]
|
|
169
217
|
return [
|
|
170
|
-
|
|
171
|
-
|
|
218
|
+
(
|
|
219
|
+
f"{ctx.indent}{ctx.nxt} = not ({ctx.prv} is None or {ctx.prv} == '' "
|
|
220
|
+
f"or (type({ctx.prv}) is int and {ctx.prv} == 0))"
|
|
221
|
+
)
|
|
172
222
|
]
|
|
173
223
|
|
|
174
224
|
# === PREDICATES ===
|