replit-river 0.17.13__tar.gz → 0.17.15__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.
- {replit_river-0.17.13 → replit_river-0.17.15}/PKG-INFO +1 -1
- {replit_river-0.17.13 → replit_river-0.17.15}/pyproject.toml +1 -1
- {replit_river-0.17.13 → replit_river-0.17.15}/src/replit_river/codegen/client.py +59 -25
- replit_river-0.17.15/tests/v1/codegen/snapshot/snapshots/test_anyof_mixed_types/__init__.py +13 -0
- replit_river-0.17.15/tests/v1/codegen/snapshot/snapshots/test_anyof_mixed_types/test_service/__init__.py +44 -0
- replit_river-0.17.15/tests/v1/codegen/snapshot/snapshots/test_anyof_mixed_types/test_service/anyof_mixed_method.py +118 -0
- replit_river-0.17.15/tests/v1/codegen/snapshot/test_anyof_mixed.py +20 -0
- replit_river-0.17.15/tests/v1/codegen/types/anyof_mixed_schema.json +85 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/.envrc +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/.github/CODEOWNERS +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/.github/pull_request_template.md +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/.github/release-drafter.yml +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/.github/workflows/ci.yml +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/.github/workflows/python-publish.yml +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/.github/workflows/release-drafter.yml +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/.gitignore +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/.python-version +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/.replit +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/LICENSE +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/Makefile +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/README.md +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/flake.lock +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/flake.nix +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/mypy.ini +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/py.typed +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/pyrightconfig.json +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/replit.nix +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/scripts/lint/README.md +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/scripts/lint/pyproject.toml +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/scripts/lint/src/lint/__init__.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/src/replit_river/__init__.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/src/replit_river/client.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/src/replit_river/client_session.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/src/replit_river/client_transport.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/src/replit_river/codegen/__init__.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/src/replit_river/codegen/__main__.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/src/replit_river/codegen/format.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/src/replit_river/codegen/run.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/src/replit_river/codegen/schema.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/src/replit_river/codegen/server.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/src/replit_river/codegen/typing.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/src/replit_river/common_session.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/src/replit_river/error_schema.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/src/replit_river/message_buffer.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/src/replit_river/messages.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/src/replit_river/py.typed +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/src/replit_river/rate_limiter.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/src/replit_river/rpc.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/src/replit_river/seq_manager.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/src/replit_river/server.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/src/replit_river/server_session.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/src/replit_river/server_transport.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/src/replit_river/session.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/src/replit_river/task_manager.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/src/replit_river/transport_options.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/src/replit_river/v2/__init__.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/src/replit_river/v2/client.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/src/replit_river/v2/client_transport.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/src/replit_river/v2/session.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/src/replit_river/websocket_wrapper.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/__init__.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/conftest.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/fixtures/codegen_snapshot_fixtures.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/v1/codegen/rpc/generated/__init__.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/v1/codegen/rpc/generated/test_service/__init__.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/v1/codegen/rpc/generated/test_service/rpc_method.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/v1/codegen/rpc/generated_special_chars/__init__.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/v1/codegen/rpc/generated_special_chars/test_service/__init__.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/v1/codegen/rpc/generated_special_chars/test_service/rpc_method.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/v1/codegen/rpc/input-collision-schema.json +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/v1/codegen/rpc/input-special-chars-schema.json +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/v1/codegen/rpc/invalid-schema.json +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/v1/codegen/rpc/schema.json +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/v1/codegen/snapshot/parity/__init__.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/v1/codegen/snapshot/parity/check_parity.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/v1/codegen/snapshot/parity/gen.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/v1/codegen/snapshot/parity/schema.json +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/v1/codegen/snapshot/snapshots/parity/pydantic_inputs/__init__.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/v1/codegen/snapshot/snapshots/parity/pydantic_inputs/agentToolLanguageServer/__init__.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/v1/codegen/snapshot/snapshots/parity/pydantic_inputs/agentToolLanguageServer/openDocument.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/v1/codegen/snapshot/snapshots/parity/pydantic_inputs/aiExec/__init__.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/v1/codegen/snapshot/snapshots/parity/pydantic_inputs/aiExec/exec.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/v1/codegen/snapshot/snapshots/parity/pydantic_inputs/conmanFilesystem/__init__.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/v1/codegen/snapshot/snapshots/parity/pydantic_inputs/conmanFilesystem/persist.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/v1/codegen/snapshot/snapshots/parity/pydantic_inputs/replspaceApi/__init__.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/v1/codegen/snapshot/snapshots/parity/pydantic_inputs/replspaceApi/init.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/v1/codegen/snapshot/snapshots/parity/pydantic_inputs/shellExec/__init__.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/v1/codegen/snapshot/snapshots/parity/pydantic_inputs/shellExec/spawn.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/v1/codegen/snapshot/snapshots/parity/typeddict_inputs/__init__.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/v1/codegen/snapshot/snapshots/parity/typeddict_inputs/agentToolLanguageServer/__init__.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/v1/codegen/snapshot/snapshots/parity/typeddict_inputs/agentToolLanguageServer/openDocument.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/v1/codegen/snapshot/snapshots/parity/typeddict_inputs/aiExec/__init__.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/v1/codegen/snapshot/snapshots/parity/typeddict_inputs/aiExec/exec.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/v1/codegen/snapshot/snapshots/parity/typeddict_inputs/conmanFilesystem/__init__.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/v1/codegen/snapshot/snapshots/parity/typeddict_inputs/conmanFilesystem/persist.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/v1/codegen/snapshot/snapshots/parity/typeddict_inputs/replspaceApi/__init__.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/v1/codegen/snapshot/snapshots/parity/typeddict_inputs/replspaceApi/init.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/v1/codegen/snapshot/snapshots/parity/typeddict_inputs/shellExec/__init__.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/v1/codegen/snapshot/snapshots/parity/typeddict_inputs/shellExec/spawn.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/v1/codegen/snapshot/snapshots/test_basic_stream/__init__.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/v1/codegen/snapshot/snapshots/test_basic_stream/test_service/__init__.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/v1/codegen/snapshot/snapshots/test_basic_stream/test_service/emit_error.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/v1/codegen/snapshot/snapshots/test_basic_stream/test_service/stream_method.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/v1/codegen/snapshot/snapshots/test_pathological_types/__init__.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/v1/codegen/snapshot/snapshots/test_pathological_types/test_service/__init__.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/v1/codegen/snapshot/snapshots/test_pathological_types/test_service/pathological_method.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/v1/codegen/snapshot/snapshots/test_recursive_types/__init__.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/v1/codegen/snapshot/snapshots/test_recursive_types/recursiveService/__init__.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/v1/codegen/snapshot/snapshots/test_recursive_types/recursiveService/getTree.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/v1/codegen/snapshot/snapshots/test_unknown_enum/__init__.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/v1/codegen/snapshot/snapshots/test_unknown_enum/enumService/__init__.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/v1/codegen/snapshot/snapshots/test_unknown_enum/enumService/needsEnum.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/v1/codegen/snapshot/snapshots/test_unknown_enum/enumService/needsEnumObject.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/v1/codegen/snapshot/test_enum.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/v1/codegen/snapshot/test_pathological.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/v1/codegen/snapshot/test_recursive.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/v1/codegen/stream/schema.json +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/v1/codegen/stream/test_stream.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/v1/codegen/test_input_special_chars.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/v1/codegen/test_invalid_schema.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/v1/codegen/test_rpc.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/v1/codegen/types/recursive_schema.json +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/v1/codegen/types/schema.json +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/v1/common_handlers.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/v1/river_fixtures/clientserver.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/v1/river_fixtures/logging.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/v1/test_communication.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/v1/test_handshake.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/v1/test_message_buffer.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/v1/test_opentelemetry.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/v1/test_rate_limiter.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/v1/test_seq_manager.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/v1/test_timeout.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/v2/codegen/snapshot/snapshots/test_basic_rpc/__init__.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/v2/codegen/snapshot/snapshots/test_basic_rpc/test_service/__init__.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/v2/codegen/snapshot/snapshots/test_basic_rpc/test_service/rpc_method.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/v2/codegen/snapshot/snapshots/test_basic_stream/__init__.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/v2/codegen/snapshot/snapshots/test_basic_stream/test_service/__init__.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/v2/codegen/snapshot/snapshots/test_basic_stream/test_service/emit_error.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/v2/codegen/snapshot/snapshots/test_basic_stream/test_service/stream_method.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/v2/datagrams.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/v2/fixtures/bound_client.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/v2/fixtures/raw_ws_server.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/v2/interpreter.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/v2/test_rpc.schema.json +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/v2/test_stream.schema.json +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/v2/test_v2_cancellation.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/v2/test_v2_rpc.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/v2/test_v2_session_lifecycle.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/tests/v2/test_v2_stream.py +0 -0
- {replit_river-0.17.13 → replit_river-0.17.15}/uv.lock +0 -0
|
@@ -389,7 +389,8 @@ def encode_type(
|
|
|
389
389
|
type = original_type
|
|
390
390
|
any_of: list[TypeExpression] = []
|
|
391
391
|
|
|
392
|
-
|
|
392
|
+
# Collect (type_check, encoder_expr) pairs for building ternary chain
|
|
393
|
+
encoder_parts: list[tuple[str | None, str]] = []
|
|
393
394
|
for i, t in enumerate(type.anyOf):
|
|
394
395
|
type_name, _, contents, _ = encode_type(
|
|
395
396
|
t,
|
|
@@ -403,34 +404,65 @@ def encode_type(
|
|
|
403
404
|
chunks.extend(contents)
|
|
404
405
|
if isinstance(t, RiverConcreteType):
|
|
405
406
|
if t.type == "string":
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
# TODO(dstewart): This structure changed since we were incorrectly
|
|
409
|
-
# leaking ListTypeExprs into codegen. This generated
|
|
410
|
-
# code is probably wrong.
|
|
407
|
+
encoder_parts.append(("isinstance(x, str)", "x"))
|
|
408
|
+
elif t.type == "array":
|
|
411
409
|
match type_name:
|
|
412
|
-
case ListTypeExpr(inner_type_name)
|
|
413
|
-
|
|
414
|
-
|
|
410
|
+
case ListTypeExpr(inner_type_name) if isinstance(
|
|
411
|
+
inner_type_name, TypeName
|
|
412
|
+
):
|
|
413
|
+
# Primitives don't need encoding
|
|
414
|
+
inner_type_str = render_literal_type(inner_type_name)
|
|
415
|
+
if inner_type_str in ("str", "int", "float", "bool", "Any"):
|
|
416
|
+
encoder_parts.append(("isinstance(x, list)", "list(x)"))
|
|
417
|
+
else:
|
|
418
|
+
encoder_parts.append(
|
|
419
|
+
(
|
|
420
|
+
"isinstance(x, list)",
|
|
421
|
+
f"[encode_{inner_type_str}(y) for y in x]",
|
|
422
|
+
)
|
|
423
|
+
)
|
|
424
|
+
case _:
|
|
425
|
+
encoder_parts.append(("isinstance(x, list)", "list(x)"))
|
|
426
|
+
elif t.type == "object":
|
|
427
|
+
match type_name:
|
|
428
|
+
case TypeName(value):
|
|
429
|
+
encoder_parts.append(
|
|
430
|
+
("isinstance(x, dict)", f"encode_{value}(x)")
|
|
415
431
|
)
|
|
432
|
+
case _:
|
|
433
|
+
encoder_parts.append(("isinstance(x, dict)", "dict(x)"))
|
|
434
|
+
elif t.type in ("number", "integer"):
|
|
435
|
+
match type_name:
|
|
416
436
|
case LiteralTypeExpr(const):
|
|
417
|
-
|
|
437
|
+
encoder_parts.append((f"x == {repr(const)}", repr(const)))
|
|
438
|
+
case _:
|
|
439
|
+
encoder_parts.append(("isinstance(x, (int, float))", "x"))
|
|
440
|
+
elif t.type == "boolean":
|
|
441
|
+
encoder_parts.append(("isinstance(x, bool)", "x"))
|
|
442
|
+
elif t.type == "null" or t.type == "undefined":
|
|
443
|
+
encoder_parts.append(("x is None", "None"))
|
|
444
|
+
else:
|
|
445
|
+
# Fallback for other types
|
|
446
|
+
match type_name:
|
|
418
447
|
case TypeName(value):
|
|
419
|
-
|
|
448
|
+
encoder_parts.append((None, f"encode_{value}(x)"))
|
|
449
|
+
case LiteralTypeExpr(const):
|
|
450
|
+
encoder_parts.append((None, repr(const)))
|
|
420
451
|
case NoneTypeExpr():
|
|
421
|
-
|
|
422
|
-
case
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
452
|
+
encoder_parts.append((None, "None"))
|
|
453
|
+
case _:
|
|
454
|
+
encoder_parts.append((None, "x"))
|
|
455
|
+
|
|
456
|
+
# Build the ternary chain from encoder_parts
|
|
457
|
+
typeddict_encoder = list[str]()
|
|
458
|
+
for i, (type_check, encoder_expr) in enumerate(encoder_parts):
|
|
459
|
+
is_last = i == len(encoder_parts) - 1
|
|
460
|
+
if is_last or type_check is None:
|
|
461
|
+
# Last item or no type check - just the expression
|
|
462
|
+
typeddict_encoder.append(encoder_expr)
|
|
463
|
+
else:
|
|
464
|
+
# Add expression with type check
|
|
465
|
+
typeddict_encoder.append(f"{encoder_expr} if {type_check} else")
|
|
434
466
|
if permit_unknown_members:
|
|
435
467
|
union = _make_open_union_type_expr(any_of)
|
|
436
468
|
else:
|
|
@@ -603,7 +635,9 @@ def encode_type(
|
|
|
603
635
|
f"encode_{render_literal_type(type_name)}"
|
|
604
636
|
)
|
|
605
637
|
encoder_names.add(encoder_name)
|
|
606
|
-
typeddict_encoder.append(
|
|
638
|
+
typeddict_encoder.append(
|
|
639
|
+
f"{render_literal_type(encoder_name)}(x[{repr(name)}])"
|
|
640
|
+
)
|
|
607
641
|
elif isinstance(prop, RiverConcreteType):
|
|
608
642
|
if name == "$kind":
|
|
609
643
|
safe_name = "kind"
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Code generated by river.codegen. DO NOT EDIT.
|
|
2
|
+
from pydantic import BaseModel
|
|
3
|
+
from typing import Literal
|
|
4
|
+
|
|
5
|
+
import replit_river as river
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
from .test_service import Test_ServiceService
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class AnyOfMixedClient:
|
|
12
|
+
def __init__(self, client: river.Client[Literal[None]]):
|
|
13
|
+
self.test_service = Test_ServiceService(client)
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Code generated by river.codegen. DO NOT EDIT.
|
|
2
|
+
from collections.abc import AsyncIterable, AsyncIterator
|
|
3
|
+
from typing import Any
|
|
4
|
+
import datetime
|
|
5
|
+
|
|
6
|
+
from pydantic import TypeAdapter
|
|
7
|
+
|
|
8
|
+
from replit_river.error_schema import RiverError, RiverErrorTypeAdapter
|
|
9
|
+
import replit_river as river
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
from .anyof_mixed_method import (
|
|
13
|
+
Anyof_Mixed_MethodInput,
|
|
14
|
+
Anyof_Mixed_MethodOutput,
|
|
15
|
+
Anyof_Mixed_MethodOutputTypeAdapter,
|
|
16
|
+
encode_Anyof_Mixed_MethodInput,
|
|
17
|
+
encode_Anyof_Mixed_MethodInputNumber_Or_String,
|
|
18
|
+
encode_Anyof_Mixed_MethodInputRun_Command,
|
|
19
|
+
encode_Anyof_Mixed_MethodInputValue_Or_Null,
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class Test_ServiceService:
|
|
24
|
+
def __init__(self, client: river.Client[Any]):
|
|
25
|
+
self.client = client
|
|
26
|
+
|
|
27
|
+
async def anyof_mixed_method(
|
|
28
|
+
self,
|
|
29
|
+
input: Anyof_Mixed_MethodInput,
|
|
30
|
+
timeout: datetime.timedelta,
|
|
31
|
+
) -> Anyof_Mixed_MethodOutput:
|
|
32
|
+
return await self.client.send_rpc(
|
|
33
|
+
"test_service",
|
|
34
|
+
"anyof_mixed_method",
|
|
35
|
+
input,
|
|
36
|
+
encode_Anyof_Mixed_MethodInput,
|
|
37
|
+
lambda x: Anyof_Mixed_MethodOutputTypeAdapter.validate_python(
|
|
38
|
+
x # type: ignore[arg-type]
|
|
39
|
+
),
|
|
40
|
+
lambda x: RiverErrorTypeAdapter.validate_python(
|
|
41
|
+
x # type: ignore[arg-type]
|
|
42
|
+
),
|
|
43
|
+
timeout,
|
|
44
|
+
)
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
# Code generated by river.codegen. DO NOT EDIT.
|
|
2
|
+
from collections.abc import AsyncIterable, AsyncIterator
|
|
3
|
+
import datetime
|
|
4
|
+
from typing import (
|
|
5
|
+
Any,
|
|
6
|
+
Literal,
|
|
7
|
+
Mapping,
|
|
8
|
+
NotRequired,
|
|
9
|
+
TypedDict,
|
|
10
|
+
)
|
|
11
|
+
from typing_extensions import Annotated
|
|
12
|
+
|
|
13
|
+
from pydantic import BaseModel, Field, TypeAdapter, WrapValidator
|
|
14
|
+
from replit_river.error_schema import RiverError
|
|
15
|
+
from replit_river.client import (
|
|
16
|
+
RiverUnknownError,
|
|
17
|
+
translate_unknown_error,
|
|
18
|
+
RiverUnknownValue,
|
|
19
|
+
translate_unknown_value,
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
import replit_river as river
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
Anyof_Mixed_MethodInputNumber_Or_String = float | str
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def encode_Anyof_Mixed_MethodInputNumber_Or_String(
|
|
29
|
+
x: "Anyof_Mixed_MethodInputNumber_Or_String",
|
|
30
|
+
) -> Any:
|
|
31
|
+
return x
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def encode_Anyof_Mixed_MethodInputRun_CommandAnyOf_0(
|
|
35
|
+
x: "Anyof_Mixed_MethodInputRun_CommandAnyOf_0",
|
|
36
|
+
) -> Any:
|
|
37
|
+
return {
|
|
38
|
+
k: v
|
|
39
|
+
for (k, v) in (
|
|
40
|
+
{
|
|
41
|
+
"args": x.get("args"),
|
|
42
|
+
"env": x.get("env"),
|
|
43
|
+
}
|
|
44
|
+
).items()
|
|
45
|
+
if v is not None
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class Anyof_Mixed_MethodInputRun_CommandAnyOf_0(TypedDict):
|
|
50
|
+
args: list[str]
|
|
51
|
+
env: NotRequired[dict[str, str] | None]
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
Anyof_Mixed_MethodInputRun_Command = (
|
|
55
|
+
Anyof_Mixed_MethodInputRun_CommandAnyOf_0 | str | list[str]
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def encode_Anyof_Mixed_MethodInputRun_Command(
|
|
60
|
+
x: "Anyof_Mixed_MethodInputRun_Command",
|
|
61
|
+
) -> Any:
|
|
62
|
+
return (
|
|
63
|
+
encode_Anyof_Mixed_MethodInputRun_CommandAnyOf_0(x)
|
|
64
|
+
if isinstance(x, dict)
|
|
65
|
+
else x
|
|
66
|
+
if isinstance(x, str)
|
|
67
|
+
else list(x)
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
Anyof_Mixed_MethodInputValue_Or_Null = str | None
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def encode_Anyof_Mixed_MethodInputValue_Or_Null(
|
|
75
|
+
x: "Anyof_Mixed_MethodInputValue_Or_Null",
|
|
76
|
+
) -> Any:
|
|
77
|
+
return x
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def encode_Anyof_Mixed_MethodInput(
|
|
81
|
+
x: "Anyof_Mixed_MethodInput",
|
|
82
|
+
) -> Any:
|
|
83
|
+
return {
|
|
84
|
+
k: v
|
|
85
|
+
for (k, v) in (
|
|
86
|
+
{
|
|
87
|
+
"number_or_string": encode_Anyof_Mixed_MethodInputNumber_Or_String(
|
|
88
|
+
x["number_or_string"]
|
|
89
|
+
)
|
|
90
|
+
if "number_or_string" in x and x["number_or_string"]
|
|
91
|
+
else None,
|
|
92
|
+
"run_command": encode_Anyof_Mixed_MethodInputRun_Command(
|
|
93
|
+
x["run_command"]
|
|
94
|
+
),
|
|
95
|
+
"value_or_null": encode_Anyof_Mixed_MethodInputValue_Or_Null(
|
|
96
|
+
x["value_or_null"]
|
|
97
|
+
)
|
|
98
|
+
if "value_or_null" in x and x["value_or_null"]
|
|
99
|
+
else None,
|
|
100
|
+
}
|
|
101
|
+
).items()
|
|
102
|
+
if v is not None
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
class Anyof_Mixed_MethodInput(TypedDict):
|
|
107
|
+
number_or_string: NotRequired[Anyof_Mixed_MethodInputNumber_Or_String | None]
|
|
108
|
+
run_command: Anyof_Mixed_MethodInputRun_Command
|
|
109
|
+
value_or_null: NotRequired[Anyof_Mixed_MethodInputValue_Or_Null | None]
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
class Anyof_Mixed_MethodOutput(BaseModel):
|
|
113
|
+
success: bool
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
Anyof_Mixed_MethodOutputTypeAdapter: TypeAdapter[Anyof_Mixed_MethodOutput] = (
|
|
117
|
+
TypeAdapter(Anyof_Mixed_MethodOutput)
|
|
118
|
+
)
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
from pytest_snapshot.plugin import Snapshot
|
|
2
|
+
|
|
3
|
+
from tests.fixtures.codegen_snapshot_fixtures import validate_codegen
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
async def test_anyof_mixed_types(snapshot: Snapshot) -> None:
|
|
7
|
+
"""Test codegen for anyOf unions with mixed types (object, string, array).
|
|
8
|
+
|
|
9
|
+
This tests the fix for the bug where non-discriminated anyOf unions
|
|
10
|
+
with mixed types like [object, string, array] would generate malformed
|
|
11
|
+
Python code with broken ternary expressions.
|
|
12
|
+
"""
|
|
13
|
+
validate_codegen(
|
|
14
|
+
snapshot=snapshot,
|
|
15
|
+
snapshot_dir="tests/v1/codegen/snapshot/snapshots",
|
|
16
|
+
read_schema=lambda: open("tests/v1/codegen/types/anyof_mixed_schema.json"),
|
|
17
|
+
target_path="test_anyof_mixed_types",
|
|
18
|
+
client_name="AnyOfMixedClient",
|
|
19
|
+
protocol_version="v1.1",
|
|
20
|
+
)
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
{
|
|
2
|
+
"services": {
|
|
3
|
+
"test_service": {
|
|
4
|
+
"procedures": {
|
|
5
|
+
"anyof_mixed_method": {
|
|
6
|
+
"input": {
|
|
7
|
+
"type": "object",
|
|
8
|
+
"properties": {
|
|
9
|
+
"run_command": {
|
|
10
|
+
"description": "Command can be object with args, string, or array of strings",
|
|
11
|
+
"anyOf": [
|
|
12
|
+
{
|
|
13
|
+
"type": "object",
|
|
14
|
+
"properties": {
|
|
15
|
+
"args": {
|
|
16
|
+
"type": "array",
|
|
17
|
+
"items": {
|
|
18
|
+
"type": "string"
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"env": {
|
|
22
|
+
"type": "object",
|
|
23
|
+
"patternProperties": {
|
|
24
|
+
"^(.*)$": {
|
|
25
|
+
"type": "string"
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
"required": ["args"]
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"type": "string"
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"type": "array",
|
|
37
|
+
"items": {
|
|
38
|
+
"type": "string"
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
]
|
|
42
|
+
},
|
|
43
|
+
"value_or_null": {
|
|
44
|
+
"description": "Value can be string or null",
|
|
45
|
+
"anyOf": [
|
|
46
|
+
{
|
|
47
|
+
"type": "string"
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
"type": "null"
|
|
51
|
+
}
|
|
52
|
+
]
|
|
53
|
+
},
|
|
54
|
+
"number_or_string": {
|
|
55
|
+
"description": "Can be number or string",
|
|
56
|
+
"anyOf": [
|
|
57
|
+
{
|
|
58
|
+
"type": "number"
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
"type": "string"
|
|
62
|
+
}
|
|
63
|
+
]
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
"required": ["run_command"]
|
|
67
|
+
},
|
|
68
|
+
"output": {
|
|
69
|
+
"type": "object",
|
|
70
|
+
"properties": {
|
|
71
|
+
"success": {
|
|
72
|
+
"type": "boolean"
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
"required": ["success"]
|
|
76
|
+
},
|
|
77
|
+
"errors": {
|
|
78
|
+
"not": {}
|
|
79
|
+
},
|
|
80
|
+
"type": "rpc"
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
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
|
|
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
|
{replit_river-0.17.13 → replit_river-0.17.15}/tests/v1/codegen/rpc/input-collision-schema.json
RENAMED
|
File without changes
|
{replit_river-0.17.13 → replit_river-0.17.15}/tests/v1/codegen/rpc/input-special-chars-schema.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{replit_river-0.17.13 → replit_river-0.17.15}/tests/v1/codegen/snapshot/parity/check_parity.py
RENAMED
|
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
|
{replit_river-0.17.13 → replit_river-0.17.15}/tests/v1/codegen/snapshot/test_pathological.py
RENAMED
|
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
|