ssc_codegen 0.41.0__tar.gz → 0.42.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.41.0 → ssc_codegen-0.42.0}/PKG-INFO +1 -1
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/pyproject.toml +1 -1
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/naming.py +17 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/targets/javascript/rest.py +31 -105
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/targets/javascript/visitor.py +32 -58
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/targets/python/rest.py +29 -98
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/targets/python/visitor.py +114 -130
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/traversal/utils.py +17 -23
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/.gitignore +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/LICENSE +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/README.md +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/__init__.py +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/_logging.py +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/ast/__init__.py +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/ast/array.py +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/ast/base.py +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/ast/cast.py +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/ast/control.py +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/ast/extension.py +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/ast/extract.py +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/ast/function.py +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/ast/jsondef.py +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/ast/module.py +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/ast/predicate_containers.py +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/ast/predicate_ops.py +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/ast/regex.py +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/ast/rest.py +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/ast/selectors.py +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/ast/string.py +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/ast/struct.py +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/ast/typedef.py +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/ast/types.py +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/core/__init__.py +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/core/contexts.py +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/core/expressions.py +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/core/extensions.py +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/core/format.py +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/core/imports.py +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/core/linter.py +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/core/module_handler.py +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/core/predicates.py +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/core/reader.py +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/core/rest_artifacts.py +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/core/struct_parser.py +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/core/type_checking.py +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/exceptions.py +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/explore.py +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/generation/__init__.py +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/generation/builder.py +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/generation/runtime.py +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/health.py +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/json_to_kdl.py +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/main.py +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/parsers/__init__.py +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/parsers/curl.py +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/parsers/http.py +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/regex_utils.py +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/request_spec.py +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/symbols.py +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/targets/__init__.py +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/targets/golang/__init__.py +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/targets/golang/http_libs/__init__.py +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/targets/golang/http_libs/base.py +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/targets/golang/http_libs/nethttp.py +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/targets/golang/literals.py +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/targets/golang/regex.py +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/targets/golang/rest.py +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/targets/golang/runtime.py +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/targets/golang/visitor.py +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/targets/javascript/__init__.py +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/targets/javascript/http_libs/__init__.py +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/targets/javascript/http_libs/axios.py +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/targets/javascript/http_libs/base.py +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/targets/javascript/http_libs/fetch.py +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/targets/profile.py +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/targets/python/__init__.py +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/targets/python/html_libs/__init__.py +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/targets/python/html_libs/base.py +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/targets/python/html_libs/bs4.py +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/targets/python/html_libs/lxml.py +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/targets/python/html_libs/parsel.py +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/targets/python/html_libs/slax.py +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/targets/python/http_libs/__init__.py +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/targets/python/http_libs/aiohttp.py +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/targets/python/http_libs/base.py +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/targets/python/http_libs/httpx.py +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/targets/python/http_libs/requests.py +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/targets/resolver.py +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/targets/rust/__init__.py +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/targets/rust/regex.py +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/targets/rust/rest.py +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/targets/rust/runtime.py +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/targets/rust/visitor.py +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/targets/spec.py +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/traversal/__init__.py +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.0}/ssc_codegen/traversal/context.py +0 -0
- {ssc_codegen-0.41.0 → ssc_codegen-0.42.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.42.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
|
|
@@ -22,6 +22,23 @@ def to_snake_case(s: str) -> str:
|
|
|
22
22
|
return s.lower()
|
|
23
23
|
|
|
24
24
|
|
|
25
|
+
def json_descriptor_var_name(name: str) -> str:
|
|
26
|
+
"""Format canonical module-level JSON descriptor constant identifier.
|
|
27
|
+
|
|
28
|
+
Args:
|
|
29
|
+
name: Struct, type, or response schema name to format.
|
|
30
|
+
|
|
31
|
+
Returns:
|
|
32
|
+
Canonical uppercase identifier prefixed with ``JSON_DESCRIPTOR_``.
|
|
33
|
+
|
|
34
|
+
Examples:
|
|
35
|
+
'Episode' -> 'JSON_DESCRIPTOR_EPISODE'
|
|
36
|
+
'CatalogReleasesResponse' -> 'JSON_DESCRIPTOR_CATALOG_RELEASES_RESPONSE'
|
|
37
|
+
"""
|
|
38
|
+
clean_name = to_snake_case(name).lstrip("_").upper()
|
|
39
|
+
return f"JSON_DESCRIPTOR_{clean_name}"
|
|
40
|
+
|
|
41
|
+
|
|
25
42
|
def to_pascal_case(s: str) -> str:
|
|
26
43
|
"""
|
|
27
44
|
'my_field_name' -> 'MyFieldName'
|
|
@@ -8,14 +8,12 @@ Called by JsVisitor via thin delegate methods. The HTTP library strategy
|
|
|
8
8
|
from __future__ import annotations
|
|
9
9
|
|
|
10
10
|
import json
|
|
11
|
-
from typing import Mapping
|
|
12
11
|
|
|
13
12
|
from ssc_codegen.ast import (
|
|
14
13
|
JsonDef,
|
|
15
14
|
MatcherListDef,
|
|
16
15
|
MethodFetch,
|
|
17
16
|
MethodRest,
|
|
18
|
-
Module,
|
|
19
17
|
PlaceholderSpec,
|
|
20
18
|
PlaceholderTemplate,
|
|
21
19
|
ResultAliasDef,
|
|
@@ -23,18 +21,21 @@ from ssc_codegen.ast import (
|
|
|
23
21
|
StructBase,
|
|
24
22
|
)
|
|
25
23
|
from ssc_codegen.ast.struct import RequestHttp
|
|
26
|
-
from ssc_codegen.naming import
|
|
24
|
+
from ssc_codegen.naming import (
|
|
25
|
+
json_descriptor_var_name,
|
|
26
|
+
to_camel_case,
|
|
27
|
+
to_pascal_case,
|
|
28
|
+
to_snake_case,
|
|
29
|
+
)
|
|
27
30
|
from ssc_codegen.request_spec import parse_json_template
|
|
28
31
|
from ssc_codegen.targets.javascript.http_libs.base import JsHttpLibStrategy
|
|
29
32
|
from ssc_codegen.traversal.context import WalkContext
|
|
30
33
|
from ssc_codegen.traversal.utils import (
|
|
31
34
|
dict_needs_builder,
|
|
32
35
|
err_subclass_name,
|
|
33
|
-
|
|
34
|
-
json_def_mapping,
|
|
36
|
+
find_enclosing_module,
|
|
35
37
|
)
|
|
36
38
|
|
|
37
|
-
|
|
38
39
|
# ===========================================================================
|
|
39
40
|
# REST shared runtime source (Ok/Err/sscDispatchErr/etc.)
|
|
40
41
|
# ===========================================================================
|
|
@@ -287,8 +288,7 @@ def js_name(name: str) -> str:
|
|
|
287
288
|
def ok_payload_type(node: MethodRest) -> str:
|
|
288
289
|
if not node.response_schema:
|
|
289
290
|
return "null"
|
|
290
|
-
|
|
291
|
-
module = struct.parent if struct is not None else None
|
|
291
|
+
module = find_enclosing_module(node)
|
|
292
292
|
schema_type = f"{to_pascal_case(node.response_schema)}Json"
|
|
293
293
|
if module is not None:
|
|
294
294
|
for n in module.body:
|
|
@@ -376,21 +376,28 @@ def emit_method_rest(
|
|
|
376
376
|
)
|
|
377
377
|
|
|
378
378
|
fn_name = http.fn_name
|
|
379
|
-
|
|
379
|
+
module = find_enclosing_module(node)
|
|
380
|
+
has_response_schema = False
|
|
381
|
+
if node.response_schema and module is not None:
|
|
382
|
+
has_response_schema = any(
|
|
383
|
+
isinstance(n, JsonDef) and n.name == node.response_schema
|
|
384
|
+
for n in module.body
|
|
385
|
+
)
|
|
386
|
+
|
|
380
387
|
if node.response_path:
|
|
381
388
|
accessor = "".join(
|
|
382
389
|
f"[{json.dumps(p)}]" for p in node.response_path.split(".")
|
|
383
390
|
)
|
|
384
|
-
if
|
|
385
|
-
|
|
391
|
+
if has_response_schema:
|
|
392
|
+
desc_var = json_descriptor_var_name(node.response_schema)
|
|
393
|
+
value_fn = f"(_b) => sscJsonProject(_b{accessor}, {desc_var})"
|
|
386
394
|
else:
|
|
387
|
-
value_fn = f"(_b) =>
|
|
395
|
+
value_fn = f"(_b) => _b{accessor}"
|
|
388
396
|
elif not node.response_schema:
|
|
389
397
|
value_fn = "(_b) => null"
|
|
390
|
-
elif
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
)
|
|
398
|
+
elif has_response_schema:
|
|
399
|
+
desc_var = json_descriptor_var_name(node.response_schema)
|
|
400
|
+
value_fn = f"(_b) => sscJsonProject(_b, {desc_var})"
|
|
394
401
|
else:
|
|
395
402
|
value_fn = "null"
|
|
396
403
|
|
|
@@ -466,82 +473,6 @@ def emit_method_rest(
|
|
|
466
473
|
return lines
|
|
467
474
|
|
|
468
475
|
|
|
469
|
-
def _response_descriptors(
|
|
470
|
-
node: MethodRest,
|
|
471
|
-
) -> dict[str, tuple[str, bool, bool, object]] | None:
|
|
472
|
-
if not node.response_schema:
|
|
473
|
-
return None
|
|
474
|
-
module = node.parent.parent if node.parent is not None else None
|
|
475
|
-
if not isinstance(module, Module):
|
|
476
|
-
return None
|
|
477
|
-
definitions = {n.name: n for n in module.body if isinstance(n, JsonDef)}
|
|
478
|
-
definition = definitions.get(node.response_schema)
|
|
479
|
-
if definition is None:
|
|
480
|
-
return None
|
|
481
|
-
return json_def_descriptors(definition, definitions)
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
def _render_descriptors(descriptors: Mapping[str, object]) -> str:
|
|
485
|
-
def render(value: object) -> str:
|
|
486
|
-
if value is None:
|
|
487
|
-
return "null"
|
|
488
|
-
if isinstance(value, bool):
|
|
489
|
-
return "true" if value else "false"
|
|
490
|
-
if isinstance(value, str):
|
|
491
|
-
return json.dumps(value)
|
|
492
|
-
if isinstance(value, tuple):
|
|
493
|
-
return "[" + ", ".join(render(x) for x in value) + "]"
|
|
494
|
-
if isinstance(value, list):
|
|
495
|
-
return "[" + ", ".join(render(item) for item in value) + "]"
|
|
496
|
-
if isinstance(value, dict):
|
|
497
|
-
return (
|
|
498
|
-
"{"
|
|
499
|
-
+ ", ".join(
|
|
500
|
-
f"{json.dumps(key)}: {render(item)}"
|
|
501
|
-
for key, item in value.items()
|
|
502
|
-
)
|
|
503
|
-
+ "}"
|
|
504
|
-
)
|
|
505
|
-
raise TypeError(f"unsupported JSON descriptor value: {value!r}")
|
|
506
|
-
|
|
507
|
-
return render(descriptors)
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
def _response_mapping(node: MethodRest) -> dict[str, object] | None:
|
|
511
|
-
if not node.response_schema:
|
|
512
|
-
return None
|
|
513
|
-
module = node.parent.parent if node.parent is not None else None
|
|
514
|
-
if not isinstance(module, Module):
|
|
515
|
-
return None
|
|
516
|
-
definitions = {n.name: n for n in module.body if isinstance(n, JsonDef)}
|
|
517
|
-
definition = definitions.get(node.response_schema)
|
|
518
|
-
if definition is None or not definition.has_alias_key:
|
|
519
|
-
return None
|
|
520
|
-
return json_def_mapping(definition, definitions)
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
def _render_mapping(mapping: dict[str, object]) -> str:
|
|
524
|
-
def render(value: object) -> str:
|
|
525
|
-
if isinstance(value, str):
|
|
526
|
-
return json.dumps(value)
|
|
527
|
-
if isinstance(value, tuple):
|
|
528
|
-
return "[" + json.dumps(value[0]) + ", " + render(value[1]) + "]"
|
|
529
|
-
if isinstance(value, list):
|
|
530
|
-
return "[" + ", ".join(render(item) for item in value) + "]"
|
|
531
|
-
if isinstance(value, dict):
|
|
532
|
-
return (
|
|
533
|
-
"{"
|
|
534
|
-
+ ", ".join(
|
|
535
|
-
f"{json.dumps(key)}: {render(item)}"
|
|
536
|
-
for key, item in value.items()
|
|
537
|
-
)
|
|
538
|
-
+ "}"
|
|
539
|
-
)
|
|
540
|
-
raise TypeError(f"unsupported JSON mapping value: {value!r}")
|
|
541
|
-
|
|
542
|
-
return render(mapping)
|
|
543
|
-
|
|
544
|
-
|
|
545
476
|
def emit_method_fetch(
|
|
546
477
|
node: MethodFetch, ctx: WalkContext, http: JsHttpLibStrategy
|
|
547
478
|
) -> list[str]:
|
|
@@ -679,26 +610,21 @@ def emit_result_alias_def(node: ResultAliasDef) -> list[str]:
|
|
|
679
610
|
def emit_matcher_list_def(node: MatcherListDef) -> list[str]:
|
|
680
611
|
var = f"_{to_snake_case(node.struct_name)}Matchers"
|
|
681
612
|
lines = [f"const {var} = ["]
|
|
682
|
-
module = (
|
|
683
|
-
node.parent
|
|
684
|
-
if isinstance(node.parent, Module)
|
|
685
|
-
else (node.parent.parent if node.parent is not None else None)
|
|
686
|
-
)
|
|
613
|
+
module = find_enclosing_module(node)
|
|
687
614
|
definitions = (
|
|
688
615
|
{n.name: n for n in module.body if isinstance(n, JsonDef)}
|
|
689
|
-
if
|
|
616
|
+
if module is not None
|
|
690
617
|
else {}
|
|
691
618
|
)
|
|
692
619
|
for e in node.entries:
|
|
693
620
|
check = render_js_condition_check(e.required_keys, e.conditions)
|
|
694
621
|
check_arg = check if check else "null"
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
value_expr = f"sscJsonProject(_b, {desc})" if desc is not None else "_b"
|
|
622
|
+
desc_var = None
|
|
623
|
+
if e.error_schema and e.error_schema in definitions:
|
|
624
|
+
desc_var = json_descriptor_var_name(e.error_schema)
|
|
625
|
+
value_expr = (
|
|
626
|
+
f"sscJsonProject(_b, {desc_var})" if desc_var is not None else "_b"
|
|
627
|
+
)
|
|
702
628
|
lines.append(
|
|
703
629
|
f" {{ status: {e.status}, check: {check_arg}, "
|
|
704
630
|
f"factory: (_s, _h, _b) => ({{ isOk: false, status: _s, "
|
|
@@ -18,8 +18,8 @@ import re as _re
|
|
|
18
18
|
from typing import Any
|
|
19
19
|
|
|
20
20
|
from ssc_codegen.ast import (
|
|
21
|
-
Attr,
|
|
22
21
|
Assert,
|
|
22
|
+
Attr,
|
|
23
23
|
CheckMethod,
|
|
24
24
|
CodeEndHook,
|
|
25
25
|
CodeStartHook,
|
|
@@ -33,14 +33,14 @@ from ssc_codegen.ast import (
|
|
|
33
33
|
Filter,
|
|
34
34
|
Fmt,
|
|
35
35
|
FunctionDef,
|
|
36
|
+
Index,
|
|
36
37
|
Init,
|
|
37
38
|
InitField,
|
|
38
39
|
InitFieldCall,
|
|
39
|
-
|
|
40
|
+
Join,
|
|
40
41
|
JsonDef,
|
|
41
42
|
JsonDefField,
|
|
42
43
|
Jsonify,
|
|
43
|
-
Join,
|
|
44
44
|
Key,
|
|
45
45
|
Len,
|
|
46
46
|
LogicAnd,
|
|
@@ -49,12 +49,12 @@ from ssc_codegen.ast import (
|
|
|
49
49
|
Lower,
|
|
50
50
|
Ltrim,
|
|
51
51
|
Match,
|
|
52
|
+
MatcherListDef,
|
|
52
53
|
MethodFetch,
|
|
53
54
|
MethodRest,
|
|
54
55
|
Module,
|
|
55
56
|
Nested,
|
|
56
57
|
NormalizeSpace,
|
|
57
|
-
PreValidate,
|
|
58
58
|
PredAttrContains,
|
|
59
59
|
PredAttrEnds,
|
|
60
60
|
PredAttrEq,
|
|
@@ -83,15 +83,15 @@ from ssc_codegen.ast import (
|
|
|
83
83
|
PredTextRe,
|
|
84
84
|
PredTextStarts,
|
|
85
85
|
PredXpath,
|
|
86
|
+
PreValidate,
|
|
86
87
|
Raw,
|
|
87
88
|
Re,
|
|
88
89
|
ReAll,
|
|
89
|
-
ReSub,
|
|
90
90
|
Repl,
|
|
91
91
|
ReplMap,
|
|
92
|
+
ReSub,
|
|
92
93
|
ResultAliasDef,
|
|
93
94
|
ResultVariantDef,
|
|
94
|
-
MatcherListDef,
|
|
95
95
|
Return,
|
|
96
96
|
RmPrefix,
|
|
97
97
|
RmPrefixSuffix,
|
|
@@ -105,7 +105,6 @@ from ssc_codegen.ast import (
|
|
|
105
105
|
Struct,
|
|
106
106
|
StructBase,
|
|
107
107
|
StructRest,
|
|
108
|
-
StructType as ST,
|
|
109
108
|
TableConfig,
|
|
110
109
|
TableMatchKey,
|
|
111
110
|
TableRows,
|
|
@@ -117,36 +116,44 @@ from ssc_codegen.ast import (
|
|
|
117
116
|
TypeDef,
|
|
118
117
|
TypeDefField,
|
|
119
118
|
TypeInfo,
|
|
120
|
-
Unique,
|
|
121
119
|
Unescape,
|
|
120
|
+
Unique,
|
|
122
121
|
Upper,
|
|
123
122
|
Utilities,
|
|
124
123
|
Value,
|
|
125
|
-
VariableType as VT,
|
|
126
124
|
XpathRemove,
|
|
127
125
|
XpathSelect,
|
|
128
126
|
XpathSelectAll,
|
|
129
127
|
)
|
|
128
|
+
from ssc_codegen.ast import (
|
|
129
|
+
StructType as ST,
|
|
130
|
+
)
|
|
131
|
+
from ssc_codegen.ast import (
|
|
132
|
+
VariableType as VT,
|
|
133
|
+
)
|
|
130
134
|
from ssc_codegen.exceptions import BuildTimeError
|
|
131
|
-
from ssc_codegen.
|
|
135
|
+
from ssc_codegen.generation.builder import ModuleBuilder
|
|
136
|
+
from ssc_codegen.naming import (
|
|
137
|
+
json_descriptor_var_name,
|
|
138
|
+
to_camel_case,
|
|
139
|
+
to_pascal_case,
|
|
140
|
+
)
|
|
141
|
+
from ssc_codegen.targets.javascript import rest
|
|
142
|
+
from ssc_codegen.targets.javascript.http_libs.axios import AxiosStrategy
|
|
143
|
+
from ssc_codegen.targets.javascript.http_libs.base import JsHttpLibStrategy
|
|
144
|
+
from ssc_codegen.targets.javascript.http_libs.fetch import FetchStrategy
|
|
145
|
+
from ssc_codegen.traversal.context import WalkContext
|
|
132
146
|
from ssc_codegen.traversal.utils import (
|
|
147
|
+
DescriptorRef,
|
|
148
|
+
find_enclosing_module,
|
|
133
149
|
find_predicate_container,
|
|
134
150
|
json_def_descriptors,
|
|
135
|
-
json_def_mapping,
|
|
136
151
|
jsonify_path_to_segments,
|
|
137
152
|
module_has_rest,
|
|
138
153
|
resolve_json_def,
|
|
139
154
|
)
|
|
140
|
-
|
|
141
|
-
from ssc_codegen.generation.builder import ModuleBuilder
|
|
142
|
-
from ssc_codegen.targets.javascript import rest
|
|
143
|
-
from ssc_codegen.targets.javascript.http_libs.axios import AxiosStrategy
|
|
144
|
-
from ssc_codegen.targets.javascript.http_libs.base import JsHttpLibStrategy
|
|
145
|
-
from ssc_codegen.targets.javascript.http_libs.fetch import FetchStrategy
|
|
146
|
-
from ssc_codegen.traversal.context import WalkContext
|
|
147
155
|
from ssc_codegen.traversal.walker import BaseWalker
|
|
148
156
|
|
|
149
|
-
|
|
150
157
|
_JS_JSON_PROJECT_HELPER = """class SscJsonError extends Error {
|
|
151
158
|
constructor(message) {
|
|
152
159
|
super(message);
|
|
@@ -286,8 +293,6 @@ function sscRemapJsonKeys(value, mapping) {
|
|
|
286
293
|
return result;
|
|
287
294
|
}"""
|
|
288
295
|
|
|
289
|
-
_JS_JSON_REMAP_HELPER = _JS_JSON_PROJECT_HELPER
|
|
290
|
-
|
|
291
296
|
|
|
292
297
|
def _js_json_descriptors(
|
|
293
298
|
node: JsonDef, definitions: dict[str, JsonDef]
|
|
@@ -295,6 +300,8 @@ def _js_json_descriptors(
|
|
|
295
300
|
descriptors = json_def_descriptors(node, definitions)
|
|
296
301
|
|
|
297
302
|
def render(value: object) -> str:
|
|
303
|
+
if isinstance(value, DescriptorRef):
|
|
304
|
+
return json_descriptor_var_name(value.schema_name)
|
|
298
305
|
if value is None:
|
|
299
306
|
return "null"
|
|
300
307
|
if isinstance(value, bool):
|
|
@@ -317,36 +324,7 @@ def _js_json_descriptors(
|
|
|
317
324
|
raise TypeError(f"unsupported JSON descriptor value: {value!r}")
|
|
318
325
|
|
|
319
326
|
return [
|
|
320
|
-
f"const
|
|
321
|
-
"",
|
|
322
|
-
]
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
def _js_json_mapping(
|
|
326
|
-
node: JsonDef, definitions: dict[str, JsonDef]
|
|
327
|
-
) -> list[str]:
|
|
328
|
-
mapping = json_def_mapping(node, definitions)
|
|
329
|
-
|
|
330
|
-
def render(value: object) -> str:
|
|
331
|
-
if isinstance(value, str):
|
|
332
|
-
return json.dumps(value)
|
|
333
|
-
if isinstance(value, tuple):
|
|
334
|
-
return "[" + json.dumps(value[0]) + ", " + render(value[1]) + "]"
|
|
335
|
-
if isinstance(value, list):
|
|
336
|
-
return "[" + ", ".join(render(item) for item in value) + "]"
|
|
337
|
-
if isinstance(value, dict):
|
|
338
|
-
return (
|
|
339
|
-
"{"
|
|
340
|
-
+ ", ".join(
|
|
341
|
-
f"{json.dumps(key)}: {render(item)}"
|
|
342
|
-
for key, item in value.items()
|
|
343
|
-
)
|
|
344
|
-
+ "}"
|
|
345
|
-
)
|
|
346
|
-
raise TypeError(f"unsupported JSON mapping value: {value!r}")
|
|
347
|
-
|
|
348
|
-
return [
|
|
349
|
-
f"const _{to_snake_case(node.name)}JsonMapping = {render(mapping)};",
|
|
327
|
+
f"const {json_descriptor_var_name(node.name)} = {render(descriptors)};",
|
|
350
328
|
"",
|
|
351
329
|
]
|
|
352
330
|
|
|
@@ -728,9 +706,7 @@ class JsVisitor(BaseWalker):
|
|
|
728
706
|
f" * @typedef {{Record<{key_type}, {val_type}>}} {name}Json",
|
|
729
707
|
" */",
|
|
730
708
|
]
|
|
731
|
-
module = node
|
|
732
|
-
while module is not None and not isinstance(module, Module):
|
|
733
|
-
module = module.parent
|
|
709
|
+
module = find_enclosing_module(node)
|
|
734
710
|
if isinstance(module, Module):
|
|
735
711
|
definitions = {
|
|
736
712
|
n.name: n for n in module.body if isinstance(n, JsonDef)
|
|
@@ -744,9 +720,7 @@ class JsVisitor(BaseWalker):
|
|
|
744
720
|
lines = ["/**", f" * @typedef {{Object}} {name}Json"]
|
|
745
721
|
lines.extend(self.walk_children(node, ctx))
|
|
746
722
|
lines.append(" */")
|
|
747
|
-
module = node
|
|
748
|
-
while module is not None and not isinstance(module, Module):
|
|
749
|
-
module = module.parent
|
|
723
|
+
module = find_enclosing_module(node)
|
|
750
724
|
if isinstance(module, Module):
|
|
751
725
|
definitions = {
|
|
752
726
|
n.name: n for n in module.body if isinstance(n, JsonDef)
|
|
@@ -1530,7 +1504,7 @@ class JsVisitor(BaseWalker):
|
|
|
1530
1504
|
self._builder.require_std(
|
|
1531
1505
|
"sscJsonProject", code=_JS_JSON_PROJECT_HELPER
|
|
1532
1506
|
)
|
|
1533
|
-
desc_name =
|
|
1507
|
+
desc_name = json_descriptor_var_name(node.schema_name)
|
|
1534
1508
|
return [
|
|
1535
1509
|
f"{ctx.indent}let {ctx.nxt} = sscJsonProject({raw_expr}, {desc_name});"
|
|
1536
1510
|
]
|
|
@@ -7,7 +7,7 @@ Called by PythonVisitor via thin delegate methods. The HTTP library strategy
|
|
|
7
7
|
|
|
8
8
|
from __future__ import annotations
|
|
9
9
|
|
|
10
|
-
from typing import
|
|
10
|
+
from typing import cast
|
|
11
11
|
|
|
12
12
|
from ssc_codegen.ast import (
|
|
13
13
|
JsonDef,
|
|
@@ -22,18 +22,21 @@ from ssc_codegen.ast import (
|
|
|
22
22
|
StructBase,
|
|
23
23
|
)
|
|
24
24
|
from ssc_codegen.ast.struct import RequestHttp
|
|
25
|
-
from ssc_codegen.naming import
|
|
25
|
+
from ssc_codegen.naming import (
|
|
26
|
+
json_descriptor_var_name,
|
|
27
|
+
to_pascal_case,
|
|
28
|
+
to_snake_case,
|
|
29
|
+
)
|
|
26
30
|
from ssc_codegen.request_spec import parse_json_template
|
|
27
31
|
from ssc_codegen.targets.python.http_libs.base import HttpLibStrategy
|
|
28
32
|
from ssc_codegen.traversal.context import WalkContext
|
|
29
33
|
from ssc_codegen.traversal.utils import (
|
|
30
34
|
dict_needs_builder,
|
|
35
|
+
find_enclosing_module,
|
|
31
36
|
module_has_html_struct,
|
|
32
37
|
module_has_rest,
|
|
33
|
-
json_def_descriptors,
|
|
34
38
|
)
|
|
35
39
|
|
|
36
|
-
|
|
37
40
|
# ===========================================================================
|
|
38
41
|
# Placeholder / Template rendering (pure functions)
|
|
39
42
|
# ===========================================================================
|
|
@@ -464,21 +467,27 @@ def emit_method_rest(
|
|
|
464
467
|
pre_lines, kw_lines = _build_kw_dict(spec, i2, i3)
|
|
465
468
|
|
|
466
469
|
value_kwarg: list[str] = []
|
|
467
|
-
|
|
470
|
+
module = find_enclosing_module(node)
|
|
471
|
+
has_response_schema = False
|
|
472
|
+
if node.response_schema and isinstance(module, Module):
|
|
473
|
+
has_response_schema = any(
|
|
474
|
+
isinstance(n, JsonDef) and n.name == node.response_schema
|
|
475
|
+
for n in module.body
|
|
476
|
+
)
|
|
477
|
+
|
|
468
478
|
if node.response_path:
|
|
469
479
|
accessor = "".join(f"[{p!r}]" for p in node.response_path.split("."))
|
|
470
|
-
if
|
|
471
|
-
value_kwarg = [f"{i3}value_fn=lambda _b: _b{accessor},"]
|
|
472
|
-
else:
|
|
480
|
+
if has_response_schema:
|
|
473
481
|
value_kwarg = [
|
|
474
|
-
f"{i3}value_fn=lambda _b: ssc_json_project(_b{accessor}, {
|
|
482
|
+
f"{i3}value_fn=lambda _b: ssc_json_project(_b{accessor}, {json_descriptor_var_name(node.response_schema)}),"
|
|
475
483
|
]
|
|
484
|
+
else:
|
|
485
|
+
value_kwarg = [f"{i3}value_fn=lambda _b: _b{accessor},"]
|
|
476
486
|
elif not node.response_schema:
|
|
477
487
|
value_kwarg = [f"{i3}value_fn=lambda _: None,"]
|
|
478
|
-
elif
|
|
479
|
-
desc_str = _render_descriptors(response_desc)
|
|
488
|
+
elif has_response_schema:
|
|
480
489
|
value_kwarg = [
|
|
481
|
-
f"{i3}value_fn=lambda _b: ssc_json_project(_b, {
|
|
490
|
+
f"{i3}value_fn=lambda _b: ssc_json_project(_b, {json_descriptor_var_name(node.response_schema)}),"
|
|
482
491
|
]
|
|
483
492
|
|
|
484
493
|
def _body(fn_name: str, await_kw: str) -> list[str]:
|
|
@@ -518,82 +527,6 @@ def emit_method_rest(
|
|
|
518
527
|
return lines
|
|
519
528
|
|
|
520
529
|
|
|
521
|
-
def _response_descriptors(
|
|
522
|
-
node: MethodRest,
|
|
523
|
-
) -> dict[str, tuple[str, bool, bool, object]] | None:
|
|
524
|
-
if not node.response_schema:
|
|
525
|
-
return None
|
|
526
|
-
module = node.parent.parent if node.parent is not None else None
|
|
527
|
-
if not isinstance(module, Module):
|
|
528
|
-
return None
|
|
529
|
-
definitions = {n.name: n for n in module.body if isinstance(n, JsonDef)}
|
|
530
|
-
definition = definitions.get(node.response_schema)
|
|
531
|
-
if definition is None:
|
|
532
|
-
return None
|
|
533
|
-
return json_def_descriptors(definition, definitions)
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
def _schema_descriptors_for_entry(
|
|
537
|
-
entry: object, module: Module | None
|
|
538
|
-
) -> dict[str, tuple[str, bool, bool, object]] | None:
|
|
539
|
-
schema = getattr(entry, "error_schema", "")
|
|
540
|
-
if not schema or not isinstance(module, Module):
|
|
541
|
-
return None
|
|
542
|
-
definitions = {n.name: n for n in module.body if isinstance(n, JsonDef)}
|
|
543
|
-
definition = definitions.get(schema)
|
|
544
|
-
if definition is None:
|
|
545
|
-
return None
|
|
546
|
-
return json_def_descriptors(definition, definitions)
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
def _render_descriptors(descriptors: Mapping[str, object]) -> str:
|
|
550
|
-
def render(value: object) -> str:
|
|
551
|
-
if value is None:
|
|
552
|
-
return "None"
|
|
553
|
-
if isinstance(value, bool):
|
|
554
|
-
return "True" if value else "False"
|
|
555
|
-
if isinstance(value, str):
|
|
556
|
-
return repr(value)
|
|
557
|
-
if isinstance(value, tuple):
|
|
558
|
-
return "(" + ", ".join(render(x) for x in value) + ")"
|
|
559
|
-
if isinstance(value, list):
|
|
560
|
-
return "[" + ", ".join(render(item) for item in value) + "]"
|
|
561
|
-
if isinstance(value, dict):
|
|
562
|
-
return (
|
|
563
|
-
"{"
|
|
564
|
-
+ ", ".join(
|
|
565
|
-
f"{key!r}: {render(item)}" for key, item in value.items()
|
|
566
|
-
)
|
|
567
|
-
+ "}"
|
|
568
|
-
)
|
|
569
|
-
raise TypeError(f"unsupported JSON descriptor value: {value!r}")
|
|
570
|
-
|
|
571
|
-
return render(descriptors)
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
def _render_mapping(mapping: dict[str, object]) -> str:
|
|
575
|
-
def render(value: object) -> str:
|
|
576
|
-
if isinstance(value, str):
|
|
577
|
-
return repr(value)
|
|
578
|
-
if isinstance(value, tuple):
|
|
579
|
-
return f"({value[0]!r}, {_render_mapping(value[1])})"
|
|
580
|
-
if isinstance(value, list):
|
|
581
|
-
return (
|
|
582
|
-
"[" + ", ".join(_render_mapping(item) for item in value) + "]"
|
|
583
|
-
)
|
|
584
|
-
if isinstance(value, dict):
|
|
585
|
-
return (
|
|
586
|
-
"{"
|
|
587
|
-
+ ", ".join(
|
|
588
|
-
f"{key!r}: {render(item)}" for key, item in value.items()
|
|
589
|
-
)
|
|
590
|
-
+ "}"
|
|
591
|
-
)
|
|
592
|
-
raise TypeError(f"unsupported JSON mapping value: {value!r}")
|
|
593
|
-
|
|
594
|
-
return render(mapping)
|
|
595
|
-
|
|
596
|
-
|
|
597
530
|
def emit_result_variant_def(node: ResultVariantDef) -> list[str]:
|
|
598
531
|
if node.schema_name:
|
|
599
532
|
base = f"{to_pascal_case(node.schema_name)}Json"
|
|
@@ -626,22 +559,20 @@ def emit_result_alias_def(node: ResultAliasDef) -> list[str]:
|
|
|
626
559
|
def emit_matcher_list_def(node: MatcherListDef) -> list[str]:
|
|
627
560
|
var = f"{to_snake_case(node.struct_name).upper()}_MATCHERS"
|
|
628
561
|
lines = [f"{var}: List[ErrMatcher] = ["]
|
|
562
|
+
module = find_enclosing_module(node)
|
|
563
|
+
definitions = (
|
|
564
|
+
{n.name: n for n in module.body if isinstance(n, JsonDef)}
|
|
565
|
+
if isinstance(module, Module)
|
|
566
|
+
else {}
|
|
567
|
+
)
|
|
629
568
|
for e in node.entries:
|
|
630
569
|
check = render_py_condition_lambda(e.required_keys, e.conditions)
|
|
631
570
|
check_arg = check if check else "None"
|
|
632
|
-
module = (
|
|
633
|
-
node.parent
|
|
634
|
-
if isinstance(node.parent, Module)
|
|
635
|
-
else (node.parent.parent if node.parent is not None else None)
|
|
636
|
-
)
|
|
637
|
-
desc = _schema_descriptors_for_entry(
|
|
638
|
-
e, module if isinstance(module, Module) else None
|
|
639
|
-
)
|
|
640
571
|
factory = e.factory_name
|
|
641
|
-
if
|
|
572
|
+
if e.error_schema and e.error_schema in definitions:
|
|
642
573
|
factory = (
|
|
643
574
|
f"lambda headers, value: {e.factory_name}(headers=headers, "
|
|
644
|
-
f"value=ssc_json_project(value, {
|
|
575
|
+
f"value=ssc_json_project(value, {json_descriptor_var_name(e.error_schema)}))"
|
|
645
576
|
)
|
|
646
577
|
lines.append(f" ErrMatcher({e.status}, {check_arg}, {factory}),")
|
|
647
578
|
lines.append("]")
|