ssc_codegen 0.36.0__tar.gz → 0.36.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.
Files changed (88) hide show
  1. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/PKG-INFO +1 -1
  2. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/pyproject.toml +1 -1
  3. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/ssc_codegen/targets/golang/http_libs/nethttp.py +7 -0
  4. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/ssc_codegen/targets/golang/rest.py +59 -10
  5. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/ssc_codegen/targets/golang/runtime.py +1 -0
  6. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/ssc_codegen/targets/golang/visitor.py +4 -0
  7. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/.gitignore +0 -0
  8. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/LICENSE +0 -0
  9. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/README.md +0 -0
  10. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/ssc_codegen/__init__.py +0 -0
  11. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/ssc_codegen/_logging.py +0 -0
  12. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/ssc_codegen/ast/__init__.py +0 -0
  13. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/ssc_codegen/ast/array.py +0 -0
  14. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/ssc_codegen/ast/base.py +0 -0
  15. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/ssc_codegen/ast/cast.py +0 -0
  16. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/ssc_codegen/ast/control.py +0 -0
  17. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/ssc_codegen/ast/extract.py +0 -0
  18. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/ssc_codegen/ast/function.py +0 -0
  19. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/ssc_codegen/ast/helpers.py +0 -0
  20. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/ssc_codegen/ast/jsondef.py +0 -0
  21. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/ssc_codegen/ast/module.py +0 -0
  22. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/ssc_codegen/ast/predicate_containers.py +0 -0
  23. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/ssc_codegen/ast/predicate_ops.py +0 -0
  24. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/ssc_codegen/ast/regex.py +0 -0
  25. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/ssc_codegen/ast/rest.py +0 -0
  26. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/ssc_codegen/ast/selectors.py +0 -0
  27. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/ssc_codegen/ast/string.py +0 -0
  28. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/ssc_codegen/ast/struct.py +0 -0
  29. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/ssc_codegen/ast/typedef.py +0 -0
  30. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/ssc_codegen/ast/types.py +0 -0
  31. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/ssc_codegen/core/__init__.py +0 -0
  32. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/ssc_codegen/core/contexts.py +0 -0
  33. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/ssc_codegen/core/expressions.py +0 -0
  34. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/ssc_codegen/core/format.py +0 -0
  35. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/ssc_codegen/core/linter.py +0 -0
  36. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/ssc_codegen/core/module_handler.py +0 -0
  37. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/ssc_codegen/core/predicates.py +0 -0
  38. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/ssc_codegen/core/reader.py +0 -0
  39. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/ssc_codegen/core/rest_artifacts.py +0 -0
  40. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/ssc_codegen/core/struct_parser.py +0 -0
  41. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/ssc_codegen/core/type_checking.py +0 -0
  42. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/ssc_codegen/exceptions.py +0 -0
  43. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/ssc_codegen/explore.py +0 -0
  44. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/ssc_codegen/generation/__init__.py +0 -0
  45. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/ssc_codegen/generation/builder.py +0 -0
  46. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/ssc_codegen/generation/runtime.py +0 -0
  47. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/ssc_codegen/health.py +0 -0
  48. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/ssc_codegen/main.py +0 -0
  49. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/ssc_codegen/naming.py +0 -0
  50. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/ssc_codegen/parsers/__init__.py +0 -0
  51. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/ssc_codegen/parsers/curl.py +0 -0
  52. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/ssc_codegen/parsers/http.py +0 -0
  53. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/ssc_codegen/regex_utils.py +0 -0
  54. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/ssc_codegen/request_spec.py +0 -0
  55. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/ssc_codegen/targets/__init__.py +0 -0
  56. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/ssc_codegen/targets/golang/__init__.py +0 -0
  57. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/ssc_codegen/targets/golang/http_libs/__init__.py +0 -0
  58. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/ssc_codegen/targets/golang/http_libs/base.py +0 -0
  59. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/ssc_codegen/targets/golang/literals.py +0 -0
  60. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/ssc_codegen/targets/golang/regex.py +0 -0
  61. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/ssc_codegen/targets/javascript/__init__.py +0 -0
  62. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/ssc_codegen/targets/javascript/http_libs/__init__.py +0 -0
  63. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/ssc_codegen/targets/javascript/http_libs/axios.py +0 -0
  64. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/ssc_codegen/targets/javascript/http_libs/base.py +0 -0
  65. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/ssc_codegen/targets/javascript/http_libs/fetch.py +0 -0
  66. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/ssc_codegen/targets/javascript/rest.py +0 -0
  67. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/ssc_codegen/targets/javascript/visitor.py +0 -0
  68. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/ssc_codegen/targets/profile.py +0 -0
  69. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/ssc_codegen/targets/python/__init__.py +0 -0
  70. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/ssc_codegen/targets/python/html_libs/__init__.py +0 -0
  71. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/ssc_codegen/targets/python/html_libs/base.py +0 -0
  72. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/ssc_codegen/targets/python/html_libs/bs4.py +0 -0
  73. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/ssc_codegen/targets/python/html_libs/lxml.py +0 -0
  74. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/ssc_codegen/targets/python/html_libs/parsel.py +0 -0
  75. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/ssc_codegen/targets/python/html_libs/slax.py +0 -0
  76. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/ssc_codegen/targets/python/http_libs/__init__.py +0 -0
  77. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/ssc_codegen/targets/python/http_libs/aiohttp.py +0 -0
  78. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/ssc_codegen/targets/python/http_libs/base.py +0 -0
  79. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/ssc_codegen/targets/python/http_libs/httpx.py +0 -0
  80. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/ssc_codegen/targets/python/http_libs/requests.py +0 -0
  81. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/ssc_codegen/targets/python/rest.py +0 -0
  82. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/ssc_codegen/targets/python/visitor.py +0 -0
  83. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/ssc_codegen/targets/resolver.py +0 -0
  84. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/ssc_codegen/targets/spec.py +0 -0
  85. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/ssc_codegen/traversal/__init__.py +0 -0
  86. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/ssc_codegen/traversal/context.py +0 -0
  87. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/ssc_codegen/traversal/utils.py +0 -0
  88. {ssc_codegen-0.36.0 → ssc_codegen-0.36.1}/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.36.0
3
+ Version: 0.36.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.36.0"
3
+ version = "0.36.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"
@@ -38,6 +38,13 @@ _NETHTTP_REST_RUNTIME: list[str] = [
38
38
  "\t\t\t\t}",
39
39
  "\t\t\t}",
40
40
  "\t\t}",
41
+ "\t\tif len(opts.Cookies) > 0 {",
42
+ "\t\t\tfor name, vs := range opts.Cookies {",
43
+ "\t\t\t\tfor _, v := range vs {",
44
+ "\t\t\t\t\treq.AddCookie(&http.Cookie{Name: name, Value: v})",
45
+ "\t\t\t\t}",
46
+ "\t\t\t}",
47
+ "\t\t}",
41
48
  '\t\tif opts.Body != "" {',
42
49
  "\t\t\treq.Body = io.NopCloser(strings.NewReader(opts.Body))",
43
50
  "\t\t}",
@@ -90,17 +90,18 @@ def render_body_json(tmpl: PlaceholderTemplate) -> str:
90
90
  return f"fmt.Sprintf({_go_str(fmt_str)}, {', '.join(args)})"
91
91
 
92
92
 
93
- def render_form_body(body: dict[str, PlaceholderTemplate]) -> str:
94
- """Render a form-urlencoded dict body as ``url.Values{...}.Encode()``.
93
+ def render_url_values(d: dict[str, PlaceholderTemplate]) -> str:
94
+ """Render a ``dict[str, PlaceholderTemplate]`` as ``url.Values{...}.Encode()``.
95
95
 
96
- Keys are literal strings; values may contain placeholders (rendered via
97
- ``fmt.Sprintf`` through ``render_url``). ``url.Values`` properly escapes
98
- both keys and values per RFC 3986.
96
+ Shared by form-body and query-string rendering. Keys are literal
97
+ strings; values may contain placeholders (rendered via ``fmt.Sprintf``
98
+ through ``render_url``). ``url.Values`` properly escapes both keys
99
+ and values per RFC 3986. Empty dict → ``'""'``.
99
100
  """
100
- if not body:
101
+ if not d:
101
102
  return '""'
102
103
  parts: list[str] = []
103
- for k, tmpl in body.items():
104
+ for k, tmpl in d.items():
104
105
  val = (
105
106
  render_url(tmpl) if tmpl.has_placeholders else _go_str(tmpl.source)
106
107
  )
@@ -108,6 +109,43 @@ def render_form_body(body: dict[str, PlaceholderTemplate]) -> str:
108
109
  return f"url.Values{{{', '.join(parts)}}}.Encode()"
109
110
 
110
111
 
112
+ def render_form_body(body: dict[str, PlaceholderTemplate]) -> str:
113
+ """Form-urlencoded body via ``url.Values.Encode()``."""
114
+ return render_url_values(body)
115
+
116
+
117
+ def render_full_url(spec: RequestHttp) -> str:
118
+ """URL with query string from ``spec.params`` appended.
119
+
120
+ When params is empty, returns ``render_url(spec.url)`` unchanged.
121
+ Otherwise appends ``+ "?" + <url.Values.Encode()>`` to the base URL.
122
+ """
123
+ base = render_url(spec.url)
124
+ if not spec.params:
125
+ return base
126
+ return f'({base} + "?" + {render_url_values(spec.params)})'
127
+
128
+
129
+ def _render_cookie_pairs(
130
+ spec: RequestHttp,
131
+ ) -> list[tuple[str, str]]:
132
+ """Render each cookie as ``(key_expr, value_expr)`` pair.
133
+
134
+ Value uses ``fmt.Sprintf`` if it contains placeholders (via ``render_url``),
135
+ otherwise a plain string literal. Returns ``[]`` when ``spec.cookies`` is
136
+ empty. Used by both the inline HTML-@request path (``req.AddCookie``) and
137
+ the REST path (``sscReqOpts.Cookies``).
138
+ """
139
+ pairs: list[tuple[str, str]] = []
140
+ for k, tmpl in spec.cookies.items():
141
+ key = _go_str(k)
142
+ value = (
143
+ render_url(tmpl) if tmpl.has_placeholders else _go_str(tmpl.source)
144
+ )
145
+ pairs.append((key, value))
146
+ return pairs
147
+
148
+
111
149
  # ===========================================================================
112
150
  # Placeholder parameter signature
113
151
  # ===========================================================================
@@ -154,9 +192,10 @@ def _build_opts(spec: RequestHttp, indent: str) -> list[str]:
154
192
  """Build sscReqOpts construction lines."""
155
193
  lines: list[str] = []
156
194
  has_headers = bool(spec.headers)
195
+ has_cookies = bool(spec.cookies)
157
196
  has_body = spec.body_kind not in ("empty", None) and spec.body is not None
158
197
 
159
- if not has_headers and not has_body:
198
+ if not has_headers and not has_body and not has_cookies:
160
199
  return [f"{indent}nil"]
161
200
 
162
201
  lines.append(f"{indent}&sscReqOpts{{")
@@ -176,6 +215,9 @@ def _build_opts(spec: RequestHttp, indent: str) -> list[str]:
176
215
  val = _go_str(tmpl.source)
177
216
  parts.append(f"{_go_str(k)}: []string{{{val}}}")
178
217
  lines.append(f"{indent}\tHeaders: sscHeaders{{{', '.join(parts)}}},")
218
+ if has_cookies:
219
+ parts = [f"{k}: []string{{{v}}}" for k, v in _render_cookie_pairs(spec)]
220
+ lines.append(f"{indent}\tCookies: sscHeaders{{{', '.join(parts)}}},")
179
221
  lines.append(f"{indent}}}")
180
222
  return lines
181
223
 
@@ -206,7 +248,7 @@ def emit_method_fetch(
206
248
  method_suffix = to_pascal_case(node.name) if node.name else "Fetch"
207
249
  func_name = f"New{name}{method_suffix}"
208
250
  ph_params = placeholder_params(spec)
209
- url_expr = render_url(spec.url)
251
+ url_expr = render_full_url(spec)
210
252
 
211
253
  i1 = ctx.indent
212
254
  i2 = i1 + ctx.indent_char
@@ -226,6 +268,13 @@ def emit_method_fetch(
226
268
  )
227
269
  lines.append(f"{i2}req.Header.Set({_go_str(k)}, {val})")
228
270
 
271
+ # Cookies inline (per-cookie AddCookie — values may interpolate
272
+ # placeholders via fmt.Sprintf produced by _render_cookie_pairs).
273
+ for key, val in _render_cookie_pairs(spec):
274
+ lines.append(
275
+ f"{i2}req.AddCookie(&http.Cookie{{Name: {key}, Value: {val}}})"
276
+ )
277
+
229
278
  # Body inline (json/raw or form).
230
279
  if spec.body_kind in ("json", "raw") and spec.body is not None:
231
280
  if isinstance(spec.body, PlaceholderTemplate):
@@ -322,7 +371,7 @@ def emit_method_rest(
322
371
  method_name = to_pascal_case(node.name) if node.name else "Fetch"
323
372
  ph_params = placeholder_params(spec)
324
373
  matchers_var = f"{to_snake_case(struct.name)}Matchers"
325
- url_expr = render_url(spec.url)
374
+ url_expr = render_full_url(spec)
326
375
 
327
376
  # Resolve return type from AST response_schema (no `any`).
328
377
  if node.response_schema:
@@ -490,6 +490,7 @@ BASE_REST_RUNTIME: list[str] = [
490
490
  "",
491
491
  "type sscReqOpts struct {",
492
492
  "\tHeaders sscHeaders",
493
+ "\tCookies sscHeaders",
493
494
  "\tBody string",
494
495
  "}",
495
496
  "",
@@ -1890,6 +1890,8 @@ class GoVisitor(BaseWalker):
1890
1890
  spec = node.http_request
1891
1891
  if spec.body_kind == "form" and isinstance(spec.body, dict):
1892
1892
  self._builder.require_import('"net/url"')
1893
+ if spec.params:
1894
+ self._builder.require_import('"net/url"')
1893
1895
  self._builder.require_import('"' + self._http.import_path + '"')
1894
1896
  struct = node.parent
1895
1897
  name = (
@@ -1912,6 +1914,8 @@ class GoVisitor(BaseWalker):
1912
1914
  spec = node.http_request
1913
1915
  if spec.body_kind == "form" and isinstance(spec.body, dict):
1914
1916
  self._builder.require_import('"net/url"')
1917
+ if spec.params:
1918
+ self._builder.require_import('"net/url"')
1915
1919
  if node.response_path:
1916
1920
  self._builder.require_import('"github.com/tidwall/gjson"')
1917
1921
  return rest.emit_method_fetch(node, ctx, self._http)
File without changes
File without changes
File without changes