moru 0.1.0__py3-none-any.whl
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.
- moru/__init__.py +174 -0
- moru/api/__init__.py +164 -0
- moru/api/client/__init__.py +8 -0
- moru/api/client/api/__init__.py +1 -0
- moru/api/client/api/sandboxes/__init__.py +1 -0
- moru/api/client/api/sandboxes/delete_sandboxes_sandbox_id.py +161 -0
- moru/api/client/api/sandboxes/get_sandboxes.py +176 -0
- moru/api/client/api/sandboxes/get_sandboxes_metrics.py +173 -0
- moru/api/client/api/sandboxes/get_sandboxes_sandbox_id.py +163 -0
- moru/api/client/api/sandboxes/get_sandboxes_sandbox_id_logs.py +199 -0
- moru/api/client/api/sandboxes/get_sandboxes_sandbox_id_metrics.py +212 -0
- moru/api/client/api/sandboxes/get_v2_sandboxes.py +230 -0
- moru/api/client/api/sandboxes/post_sandboxes.py +172 -0
- moru/api/client/api/sandboxes/post_sandboxes_sandbox_id_connect.py +193 -0
- moru/api/client/api/sandboxes/post_sandboxes_sandbox_id_pause.py +165 -0
- moru/api/client/api/sandboxes/post_sandboxes_sandbox_id_refreshes.py +181 -0
- moru/api/client/api/sandboxes/post_sandboxes_sandbox_id_resume.py +189 -0
- moru/api/client/api/sandboxes/post_sandboxes_sandbox_id_timeout.py +193 -0
- moru/api/client/api/templates/__init__.py +1 -0
- moru/api/client/api/templates/delete_templates_template_id.py +157 -0
- moru/api/client/api/templates/get_templates.py +172 -0
- moru/api/client/api/templates/get_templates_template_id.py +195 -0
- moru/api/client/api/templates/get_templates_template_id_builds_build_id_status.py +217 -0
- moru/api/client/api/templates/get_templates_template_id_files_hash.py +180 -0
- moru/api/client/api/templates/patch_templates_template_id.py +183 -0
- moru/api/client/api/templates/post_templates.py +172 -0
- moru/api/client/api/templates/post_templates_template_id.py +181 -0
- moru/api/client/api/templates/post_templates_template_id_builds_build_id.py +170 -0
- moru/api/client/api/templates/post_v2_templates.py +172 -0
- moru/api/client/api/templates/post_v3_templates.py +172 -0
- moru/api/client/api/templates/post_v_2_templates_template_id_builds_build_id.py +192 -0
- moru/api/client/client.py +286 -0
- moru/api/client/errors.py +16 -0
- moru/api/client/models/__init__.py +123 -0
- moru/api/client/models/aws_registry.py +85 -0
- moru/api/client/models/aws_registry_type.py +8 -0
- moru/api/client/models/build_log_entry.py +89 -0
- moru/api/client/models/build_status_reason.py +95 -0
- moru/api/client/models/connect_sandbox.py +59 -0
- moru/api/client/models/created_access_token.py +100 -0
- moru/api/client/models/created_team_api_key.py +166 -0
- moru/api/client/models/disk_metrics.py +91 -0
- moru/api/client/models/error.py +67 -0
- moru/api/client/models/gcp_registry.py +69 -0
- moru/api/client/models/gcp_registry_type.py +8 -0
- moru/api/client/models/general_registry.py +77 -0
- moru/api/client/models/general_registry_type.py +8 -0
- moru/api/client/models/identifier_masking_details.py +83 -0
- moru/api/client/models/listed_sandbox.py +154 -0
- moru/api/client/models/log_level.py +11 -0
- moru/api/client/models/max_team_metric.py +78 -0
- moru/api/client/models/mcp_type_0.py +44 -0
- moru/api/client/models/new_access_token.py +59 -0
- moru/api/client/models/new_sandbox.py +172 -0
- moru/api/client/models/new_team_api_key.py +59 -0
- moru/api/client/models/node.py +155 -0
- moru/api/client/models/node_detail.py +165 -0
- moru/api/client/models/node_metrics.py +122 -0
- moru/api/client/models/node_status.py +11 -0
- moru/api/client/models/node_status_change.py +79 -0
- moru/api/client/models/post_sandboxes_sandbox_id_refreshes_body.py +59 -0
- moru/api/client/models/post_sandboxes_sandbox_id_timeout_body.py +59 -0
- moru/api/client/models/resumed_sandbox.py +68 -0
- moru/api/client/models/sandbox.py +145 -0
- moru/api/client/models/sandbox_detail.py +183 -0
- moru/api/client/models/sandbox_log.py +70 -0
- moru/api/client/models/sandbox_log_entry.py +93 -0
- moru/api/client/models/sandbox_log_entry_fields.py +44 -0
- moru/api/client/models/sandbox_logs.py +91 -0
- moru/api/client/models/sandbox_metric.py +118 -0
- moru/api/client/models/sandbox_network_config.py +92 -0
- moru/api/client/models/sandbox_state.py +9 -0
- moru/api/client/models/sandboxes_with_metrics.py +59 -0
- moru/api/client/models/team.py +83 -0
- moru/api/client/models/team_api_key.py +158 -0
- moru/api/client/models/team_metric.py +86 -0
- moru/api/client/models/team_user.py +68 -0
- moru/api/client/models/template.py +217 -0
- moru/api/client/models/template_build.py +139 -0
- moru/api/client/models/template_build_file_upload.py +70 -0
- moru/api/client/models/template_build_info.py +126 -0
- moru/api/client/models/template_build_request.py +115 -0
- moru/api/client/models/template_build_request_v2.py +88 -0
- moru/api/client/models/template_build_request_v3.py +88 -0
- moru/api/client/models/template_build_start_v2.py +184 -0
- moru/api/client/models/template_build_status.py +11 -0
- moru/api/client/models/template_legacy.py +207 -0
- moru/api/client/models/template_request_response_v3.py +83 -0
- moru/api/client/models/template_step.py +91 -0
- moru/api/client/models/template_update_request.py +59 -0
- moru/api/client/models/template_with_builds.py +148 -0
- moru/api/client/models/update_team_api_key.py +59 -0
- moru/api/client/py.typed +1 -0
- moru/api/client/types.py +54 -0
- moru/api/client_async/__init__.py +50 -0
- moru/api/client_sync/__init__.py +52 -0
- moru/api/metadata.py +14 -0
- moru/connection_config.py +217 -0
- moru/envd/api.py +59 -0
- moru/envd/filesystem/filesystem_connect.py +193 -0
- moru/envd/filesystem/filesystem_pb2.py +76 -0
- moru/envd/filesystem/filesystem_pb2.pyi +233 -0
- moru/envd/process/process_connect.py +155 -0
- moru/envd/process/process_pb2.py +92 -0
- moru/envd/process/process_pb2.pyi +304 -0
- moru/envd/rpc.py +61 -0
- moru/envd/versions.py +6 -0
- moru/exceptions.py +95 -0
- moru/sandbox/commands/command_handle.py +69 -0
- moru/sandbox/commands/main.py +39 -0
- moru/sandbox/filesystem/filesystem.py +94 -0
- moru/sandbox/filesystem/watch_handle.py +60 -0
- moru/sandbox/main.py +210 -0
- moru/sandbox/mcp.py +1120 -0
- moru/sandbox/network.py +8 -0
- moru/sandbox/sandbox_api.py +210 -0
- moru/sandbox/signature.py +45 -0
- moru/sandbox/utils.py +34 -0
- moru/sandbox_async/commands/command.py +336 -0
- moru/sandbox_async/commands/command_handle.py +196 -0
- moru/sandbox_async/commands/pty.py +240 -0
- moru/sandbox_async/filesystem/filesystem.py +531 -0
- moru/sandbox_async/filesystem/watch_handle.py +62 -0
- moru/sandbox_async/main.py +734 -0
- moru/sandbox_async/paginator.py +69 -0
- moru/sandbox_async/sandbox_api.py +325 -0
- moru/sandbox_async/utils.py +7 -0
- moru/sandbox_sync/commands/command.py +328 -0
- moru/sandbox_sync/commands/command_handle.py +150 -0
- moru/sandbox_sync/commands/pty.py +230 -0
- moru/sandbox_sync/filesystem/filesystem.py +518 -0
- moru/sandbox_sync/filesystem/watch_handle.py +69 -0
- moru/sandbox_sync/main.py +726 -0
- moru/sandbox_sync/paginator.py +69 -0
- moru/sandbox_sync/sandbox_api.py +308 -0
- moru/template/consts.py +30 -0
- moru/template/dockerfile_parser.py +275 -0
- moru/template/logger.py +232 -0
- moru/template/main.py +1360 -0
- moru/template/readycmd.py +138 -0
- moru/template/types.py +105 -0
- moru/template/utils.py +320 -0
- moru/template_async/build_api.py +202 -0
- moru/template_async/main.py +366 -0
- moru/template_sync/build_api.py +199 -0
- moru/template_sync/main.py +371 -0
- moru-0.1.0.dist-info/METADATA +63 -0
- moru-0.1.0.dist-info/RECORD +152 -0
- moru-0.1.0.dist-info/WHEEL +4 -0
- moru-0.1.0.dist-info/licenses/LICENSE +9 -0
- moru_connect/__init__.py +1 -0
- moru_connect/client.py +493 -0
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
moru/__init__.py,sha256=OTepvrwEO-_wqXdxox-BB0_PEcbK0gCaq8iuCvMTJe8,4044
|
|
2
|
+
moru/api/__init__.py,sha256=Kex7ww-Wsd9n13YP4V0szE31tDsg4nwAMs3KOetkvU8,5292
|
|
3
|
+
moru/api/client/__init__.py,sha256=b28MpwoIgPULais3BheaYT1RIUdlNVBhXD1vrn4oE6A,151
|
|
4
|
+
moru/api/client/api/__init__.py,sha256=zTSiG_ujSjAqWPyc435YXaX9XTlpMjiJWBbV-f-YtdA,45
|
|
5
|
+
moru/api/client/api/sandboxes/__init__.py,sha256=5vd9uJWAjRqa9xzxzYkLD1yoZ12Ld_bAaNB5WX4fbE8,56
|
|
6
|
+
moru/api/client/api/sandboxes/delete_sandboxes_sandbox_id.py,sha256=exBkD4FP0t730uuuKvNPWwm9PMOE68BDeaKmt98gPlg,3945
|
|
7
|
+
moru/api/client/api/sandboxes/get_sandboxes.py,sha256=cte-9oyXExgevw28JmoYcFF_GiCeCr0vkCf47LGtLxA,4745
|
|
8
|
+
moru/api/client/api/sandboxes/get_sandboxes_metrics.py,sha256=KCF1aSbx_1PL2xAhfFqBYIueLYyzCiRomjSgXOU9HBA,4613
|
|
9
|
+
moru/api/client/api/sandboxes/get_sandboxes_sandbox_id.py,sha256=M4a8lrM0NgaIF4G6rMw2LcoLs2FK6b4Dfc15JoroSkc,4133
|
|
10
|
+
moru/api/client/api/sandboxes/get_sandboxes_sandbox_id_logs.py,sha256=EQmwi1HGcadWZOCSQ3UrtrT3quNHnJkPnanvd-gW0sM,5217
|
|
11
|
+
moru/api/client/api/sandboxes/get_sandboxes_sandbox_id_metrics.py,sha256=jE5r70f4aVA7raa9nRw3syGmXWjmKMdLD7-NrVLjdl0,5909
|
|
12
|
+
moru/api/client/api/sandboxes/get_v2_sandboxes.py,sha256=vSR1tqr1cawaQqPBmX8hj79R46fluIIOKQwPlAGMNns,6705
|
|
13
|
+
moru/api/client/api/sandboxes/post_sandboxes.py,sha256=XygFg6q9nF5aNZUOEMn-W1cL0O0rNmtCRY9vXrLSiag,4269
|
|
14
|
+
moru/api/client/api/sandboxes/post_sandboxes_sandbox_id_connect.py,sha256=V8hxnasDuLaAwk-V5g0iT-RcpCtep2qv-JP2pdG0Vik,5148
|
|
15
|
+
moru/api/client/api/sandboxes/post_sandboxes_sandbox_id_pause.py,sha256=dD0M7vx5MV-tCw4o2by1csKnIDVmO2YxaPkKDxNpEJc,4082
|
|
16
|
+
moru/api/client/api/sandboxes/post_sandboxes_sandbox_id_refreshes.py,sha256=euCZrWCPDvSGFq7_0qLgXSF6Ff95jobfQMdgnpLQG80,4753
|
|
17
|
+
moru/api/client/api/sandboxes/post_sandboxes_sandbox_id_resume.py,sha256=rGHH24aBNYrMHkvDoQkC15yvS6Ku8TjznauD7vcUtzg,4728
|
|
18
|
+
moru/api/client/api/sandboxes/post_sandboxes_sandbox_id_timeout.py,sha256=PDthaR57kLmY6Nz1FrpcDqPWZm_F-KaR338-bQagrk0,5674
|
|
19
|
+
moru/api/client/api/templates/__init__.py,sha256=5vd9uJWAjRqa9xzxzYkLD1yoZ12Ld_bAaNB5WX4fbE8,56
|
|
20
|
+
moru/api/client/api/templates/delete_templates_template_id.py,sha256=kuk9ZCyk1LNb1khjW-PcwP7YrMXYpzO0rnAWgXXH-YQ,3854
|
|
21
|
+
moru/api/client/api/templates/get_templates.py,sha256=ZN3PG1_HsJnLmJZ00ZzFk9XGf9mTM6JxLNlT95F3A0w,4598
|
|
22
|
+
moru/api/client/api/templates/get_templates_template_id.py,sha256=yzbvqTmLXw4ky4yGBL5Uqax-oC3q1RHzsKJHP2vGob8,5342
|
|
23
|
+
moru/api/client/api/templates/get_templates_template_id_builds_build_id_status.py,sha256=Iv1g0rxGp1HJc0Zthq-s0xkdnEzBw795M1gB4I_o-EI,6039
|
|
24
|
+
moru/api/client/api/templates/get_templates_template_id_files_hash.py,sha256=7ntCFSxZER4f2KURZwttJAw0i-hCEueZKdHu9GZCCi8,4914
|
|
25
|
+
moru/api/client/api/templates/patch_templates_template_id.py,sha256=RMCVX8WXVMuwgGqmpeqAedVZ8SVjuLR7uL0MgK87Igk,4593
|
|
26
|
+
moru/api/client/api/templates/post_templates.py,sha256=-Z4ZlPCDXSy-AJLglk6IHc0MJsPMVm8xVbHaboaHeKw,4420
|
|
27
|
+
moru/api/client/api/templates/post_templates_template_id.py,sha256=YiGS01zYOHgVXdRD5hhSEHzXfuTRzJUdL35hjR_ZG44,4660
|
|
28
|
+
moru/api/client/api/templates/post_templates_template_id_builds_build_id.py,sha256=xCkIlP3CV0ZHsfsIp4qi4yNBqPlc4rjG0M_vxgdpwTo,4165
|
|
29
|
+
moru/api/client/api/templates/post_v2_templates.py,sha256=hJczq9aJpaPo4i_ubo5bQzL-h5AYuY21YOsLJAFLFuA,4446
|
|
30
|
+
moru/api/client/api/templates/post_v3_templates.py,sha256=3AgCaMwzVHaXjCsBm5z7FhTdOpW9-NaEAnyBIoAY58Y,4591
|
|
31
|
+
moru/api/client/api/templates/post_v_2_templates_template_id_builds_build_id.py,sha256=Uqrs2EpcoYBKe9lz_369BOxt6J0S-Np5hHct_p4T3NA,4785
|
|
32
|
+
moru/api/client/client.py,sha256=O6MiIbTg_Z-szhiNi8RhaBwI7chi3y9xvPfnYiGXMb4,12581
|
|
33
|
+
moru/api/client/errors.py,sha256=gO8GBmKqmSNgAg-E5oT-oOyxztvp7V_6XG7OUTT15q0,546
|
|
34
|
+
moru/api/client/models/__init__.py,sha256=UoFfw_fpf5ZA_Z6Q1vr4zc9vLINWJmu_YSjSY22ETzU,4099
|
|
35
|
+
moru/api/client/models/aws_registry.py,sha256=YKwQXCuutv3XwgEJWbBTyX6KmLi866-ASsHpu-n0H2w,2486
|
|
36
|
+
moru/api/client/models/aws_registry_type.py,sha256=8gBrOkfd2OaBDPRRJDmF6t2luvz01A0QExzfHRsgUg8,136
|
|
37
|
+
moru/api/client/models/build_log_entry.py,sha256=JKbGEBu5YMNL8o62xuX7YhrOi8T8EBV-e_gotu8jOj8,2379
|
|
38
|
+
moru/api/client/models/build_status_reason.py,sha256=rGwEYbmIFjSG3QPpPm-iX1rDVDPC3Jkn33dDljbLyWM,2878
|
|
39
|
+
moru/api/client/models/connect_sandbox.py,sha256=095nNrudNKwrD1fjsTTNeaf-4D_jJ2NsvIEQhYAVBHY,1561
|
|
40
|
+
moru/api/client/models/created_access_token.py,sha256=VjU_tuW67zrtc3V1po-MVtPo8J1dtRkwy-6uTe2AEf0,2639
|
|
41
|
+
moru/api/client/models/created_team_api_key.py,sha256=QO2jAIR8u1Xxn26jnftkDNYCI1mEqDMt-ZUIQS1y1NU,5040
|
|
42
|
+
moru/api/client/models/disk_metrics.py,sha256=2bZEe84P2wBqQb9_RR-xR743ZDKCzjbzXmjmTDsXwI8,2442
|
|
43
|
+
moru/api/client/models/error.py,sha256=xGvyYQQHv0ZrxvhrVvFlXPaosmt24ivIh3U4gItpBKY,1594
|
|
44
|
+
moru/api/client/models/gcp_registry.py,sha256=jU0_iH1H0JBGHyl0IVuQl44yQ18qyTqYaPNd8S_yZyg,1923
|
|
45
|
+
moru/api/client/models/gcp_registry_type.py,sha256=QcMwg9qUyr6e7VRinI0iRa9lhYvryj7vZEeTK0yEZVM,136
|
|
46
|
+
moru/api/client/models/general_registry.py,sha256=J_-i7kLmsPy018YFhBKDH5YAToey4MnCIivPUKSpTc8,2052
|
|
47
|
+
moru/api/client/models/general_registry_type.py,sha256=VwyEKt25wUh0y8Qj4Wpeolus-Cpt31Snhhy-UM_DfMk,150
|
|
48
|
+
moru/api/client/models/identifier_masking_details.py,sha256=97xSg4Nr3D5xbjGDuZ16doEMOlck0EtyjMxtHQR9TKk,2496
|
|
49
|
+
moru/api/client/models/listed_sandbox.py,sha256=zyuxeHjkrar1GTnKVCvgRXV4Zvdfq8FcZGOXnxHQ5a8,4382
|
|
50
|
+
moru/api/client/models/log_level.py,sha256=uv6u1nkqfzdxTjJAxLZdWuH5goVI_g-ULLhh6TU5dw8,189
|
|
51
|
+
moru/api/client/models/max_team_metric.py,sha256=HQuDBFHMIsTJbWTl0kOX4ADIfWb1E97J-PB0NNoRJCw,2187
|
|
52
|
+
moru/api/client/models/mcp_type_0.py,sha256=U_8DsmxiUkD4s4_ODbE6sAlURThIqS6v1rUpt3CE1FE,1220
|
|
53
|
+
moru/api/client/models/new_access_token.py,sha256=sjlQ7dEj4ByCgwud750SbxwyjggAKB1s-o_N7dRCo7s,1480
|
|
54
|
+
moru/api/client/models/new_sandbox.py,sha256=a9puqtwleHhMr_z8h_WE58eXtE6QNPNl4Huar44I_oU,5603
|
|
55
|
+
moru/api/client/models/new_team_api_key.py,sha256=neYLvvvzyPcpXYV5gDHVkv_ovjKdIBKUTX04cD5QKGA,1473
|
|
56
|
+
moru/api/client/models/node.py,sha256=P6x2a_6Nj58YlqiLjU1xqJ8nF0VGcvqdN-w-CwMpHVg,4352
|
|
57
|
+
moru/api/client/models/node_detail.py,sha256=KXosKYhqOyVwgBPSlb2xVnlECIlONZzD0UiiIKf_wko,4782
|
|
58
|
+
moru/api/client/models/node_metrics.py,sha256=EveG1M2dLWteatFWvFQMa9aKzz8urRlOOZ7QD_8Xd0o,3642
|
|
59
|
+
moru/api/client/models/node_status.py,sha256=bZkWsNgKncRmFxatPdKlJTu9H4GTBbgQ2XF9JNvW16I,219
|
|
60
|
+
moru/api/client/models/node_status_change.py,sha256=g59HSBpip8R7egNghe7QxYZ_MH-bgijGac36S5-WdYg,2236
|
|
61
|
+
moru/api/client/models/post_sandboxes_sandbox_id_refreshes_body.py,sha256=VwMoBB9y2vFP7kcLDJ0Q9kVGOBqD2W3VvAEKv_XHd2Y,1763
|
|
62
|
+
moru/api/client/models/post_sandboxes_sandbox_id_timeout_body.py,sha256=iay4pLjwIryb6J8fjx3UjThsNJ5AvqArzAwr5K8LnNs,1668
|
|
63
|
+
moru/api/client/models/resumed_sandbox.py,sha256=spSSP0TXWz8QmDoJprqIRToktgd8pvmiPTwZt5pKB2w,1964
|
|
64
|
+
moru/api/client/models/sandbox.py,sha256=z5OUJActzzFq2us2ttM-BQU-pJ9esi0qBjKtrqNhjE0,4600
|
|
65
|
+
moru/api/client/models/sandbox_detail.py,sha256=L3QNx7SlJyrqpWtchieKmXRh5MrOJfP2CF2CCibJpiI,5494
|
|
66
|
+
moru/api/client/models/sandbox_log.py,sha256=tXw35j3poz7DMJrLeoxr4oYdbcYJV5ep3E0bVdQsS2o,1806
|
|
67
|
+
moru/api/client/models/sandbox_log_entry.py,sha256=rbwY2MBahRLhcCP081XczQI3AksuLMbflNh9pOeCfjA,2502
|
|
68
|
+
moru/api/client/models/sandbox_log_entry_fields.py,sha256=SYwtEgNOKPtmf9BqIiRS44bEgcbbbHMq2qdCShpj8QI,1256
|
|
69
|
+
moru/api/client/models/sandbox_logs.py,sha256=3UC3ngilUpl7Wye7rl5Md9DR1loa_7chGTBx9tRb6LY,2658
|
|
70
|
+
moru/api/client/models/sandbox_metric.py,sha256=j90tDplFtQwdzHKpBVk5044T4uVrLwVTGBvAAkVaGdI,3280
|
|
71
|
+
moru/api/client/models/sandbox_network_config.py,sha256=iBSiOsOpPBkdHvIfwlVSxRRjgdffkMP_p7hDNFEhKco,3290
|
|
72
|
+
moru/api/client/models/sandbox_state.py,sha256=iztDupSF2SrYQGV2UTcnZRH_U3GxSmHYKHMMUksO_7M,163
|
|
73
|
+
moru/api/client/models/sandboxes_with_metrics.py,sha256=CuOZ1ismyjPLrxPcKaDqLKZL5Iun0njN70Qqhubc1Ps,1535
|
|
74
|
+
moru/api/client/models/team.py,sha256=rGLOfphzsP7VA9SLmQn8vnUfxB9KILfMwNfh4hVy3IE,2042
|
|
75
|
+
moru/api/client/models/team_api_key.py,sha256=4aqRT8gF32WJwuteq6h7ag2wdpZuVCpaOEZuj1j3Dx4,4844
|
|
76
|
+
moru/api/client/models/team_metric.py,sha256=itcMm3hTxv_S7DG14JYI2LTOIPwrc_1rhP-UmRQRt84,2619
|
|
77
|
+
moru/api/client/models/team_user.py,sha256=UCF9Ajj0QOrE_RxFusWnDM9N4PI0DOZHZaksMILLdS4,1631
|
|
78
|
+
moru/api/client/models/template.py,sha256=HcA4xZqCf-YyNhALo3ysvM9_V0dRc8fXsBjo2DG1tw8,6739
|
|
79
|
+
moru/api/client/models/template_build.py,sha256=5GpCKpvI6vi86r7wV2Ylv3qQxJEL3wBbrXCRx7lTFQo,4323
|
|
80
|
+
moru/api/client/models/template_build_file_upload.py,sha256=iqgQEKVJxWD8ezd_w44NoYmFCVDyTSUcH474KRCaXDY,1879
|
|
81
|
+
moru/api/client/models/template_build_info.py,sha256=IXZM16g5tWbwqtGMnzUj3IRkd3H9HmsYwpNCEEp_AkQ,3798
|
|
82
|
+
moru/api/client/models/template_build_request.py,sha256=iMy655tp09fTr8gNgu8uHwQm4IA_8IUx4xWQxZQnzjI,3433
|
|
83
|
+
moru/api/client/models/template_build_request_v2.py,sha256=KoETYShWCXHBo6Mt4WF_WHHJnHxd66cbAQ0JMum8Ino,2459
|
|
84
|
+
moru/api/client/models/template_build_request_v3.py,sha256=jfEfMfOtUyGRPOId16RJgocDd1uBcb32-mtCBHUF7mE,2459
|
|
85
|
+
moru/api/client/models/template_build_start_v2.py,sha256=TIZjDcqPCwGQeHOWXMYPbf3W1fkbbCMqI9xo8DhQREY,6543
|
|
86
|
+
moru/api/client/models/template_build_status.py,sha256=MpTZ_bM8-_WvttJg1Q08_ZGHdrJ6JTEl_6pv8NFETyM,214
|
|
87
|
+
moru/api/client/models/template_legacy.py,sha256=MQ0GpvoH-VDyh-07sQYqnud3AZx4A4AhK-SpTCkS444,6399
|
|
88
|
+
moru/api/client/models/template_request_response_v3.py,sha256=fU2pqGzWNiKLaaO9G0WlwKRk7Yj2ZniV-3m7dlzHCLM,2307
|
|
89
|
+
moru/api/client/models/template_step.py,sha256=qmCseK5OJXN2Ffirl0A0J4neqyfDqA-a-mYZbmwKOyM,2561
|
|
90
|
+
moru/api/client/models/template_update_request.py,sha256=KMlSyGf7hX75GqXxEP-OiExnABql4MKdLBfHPd02gFo,1663
|
|
91
|
+
moru/api/client/models/template_with_builds.py,sha256=D_euGW7ByyN8BKHUNN_SEgF6YbZl5ZsCbWDRhwz3J_0,4606
|
|
92
|
+
moru/api/client/models/update_team_api_key.py,sha256=UEHHUJxwHWTOd-AuDE-Z26E4lX2Ck9SPq8MO-Trc9Uc,1493
|
|
93
|
+
moru/api/client/py.typed,sha256=8ZJUsxZiuOy1oJeVhsTWQhTG_6pTVHVXk5hJL79ebTk,25
|
|
94
|
+
moru/api/client/types.py,sha256=AX4orxQZQJat3vZrgjJ-TYb2sNBL8kNo9yqYDT-n8y8,1391
|
|
95
|
+
moru/api/client_async/__init__.py,sha256=AZ3Ju_yzZLdWwZ98AR2__PGr5t-uClxOJ4Y22HII7Sk,1337
|
|
96
|
+
moru/api/client_sync/__init__.py,sha256=9GzuwlCxcJEHgH2HTvUrqTXHIkCHwpk0V9EewkZUt8o,1313
|
|
97
|
+
moru/api/metadata.py,sha256=ytPkGmfWh6FJ4yUOPQA_-BRW7b27hLdgxQFn07MtXhQ,320
|
|
98
|
+
moru/connection_config.py,sha256=LZCS95mhGyjb6VWqlo2vXYTTnXOT8C-3umQoiEfWlXk,6799
|
|
99
|
+
moru/envd/api.py,sha256=eK_ka4Pj3h-5pDic-wLzr94fFnYpGQYqIALPkPFr4kg,1491
|
|
100
|
+
moru/envd/filesystem/filesystem_connect.py,sha256=mJwggEN7UPSEHDWD_m9NTpFD3LtY8hKhI1aMJJ1_RfA,7528
|
|
101
|
+
moru/envd/filesystem/filesystem_pb2.py,sha256=PaXEqiiGUeIfsZmx488TpDBwZn4AcV6eUugdYVhc61w,8024
|
|
102
|
+
moru/envd/filesystem/filesystem_pb2.pyi,sha256=8LnxvXgCosUrTtiXKkyN-ZroQ2JKf8FjnaJ8jGqlRVo,7631
|
|
103
|
+
moru/envd/process/process_connect.py,sha256=bn8svNcgvgwjjOWspvLZkB7gxNbxBrXnVbTx6licVfg,5693
|
|
104
|
+
moru/envd/process/process_pb2.py,sha256=EGGYkdTw7NZFAXLJHpXZZhTytl9ExgIE8roDfi4hPbA,9794
|
|
105
|
+
moru/envd/process/process_pb2.pyi,sha256=ufwRFK1P7p_UHEazlxNiUs2itEhgYZtdOV-YY8RRu94,9688
|
|
106
|
+
moru/envd/rpc.py,sha256=ueOxpa9HyeUToMWZFHDADxXG5HrQRu0T-Ks2Zvktk-0,2237
|
|
107
|
+
moru/envd/versions.py,sha256=hX1p5B7268L73ZZTgG9W_oWFqPspyRHH7I2KUizveIk,205
|
|
108
|
+
moru/exceptions.py,sha256=E97UKGcnMTnMXRR1XpHDg5dfjZdWxFjqX3hzDiRueRo,2229
|
|
109
|
+
moru/sandbox/commands/command_handle.py,sha256=Kr0NoZc9QwzRPw7zdXWY4hFP-xr37geK08WbfTL1mmc,1078
|
|
110
|
+
moru/sandbox/commands/main.py,sha256=t8hk44wZX27OqRrYHo_FhvhzfOvIVK-6NO4HpfiOhpo,692
|
|
111
|
+
moru/sandbox/filesystem/filesystem.py,sha256=Yk2DBMkTDkVz_c6XVwHNLhTRPVECo2tHeDl6cTtNOJE,1880
|
|
112
|
+
moru/sandbox/filesystem/watch_handle.py,sha256=8oUe5mx0xIvv40LzBDYCYeDOirya-2pbut7FDaM86aQ,1387
|
|
113
|
+
moru/sandbox/main.py,sha256=6t_MR9IIO6XTmk38vu3vqwmSz5DmfM0MjDklDAl3w4o,6267
|
|
114
|
+
moru/sandbox/mcp.py,sha256=CRwNOla9Raz2j5Q5g4d65sE6hZ3Adj8RCZ0USold25s,23142
|
|
115
|
+
moru/sandbox/network.py,sha256=tmOG2Ya1MyYk58_BnV546xsQVQHfqnHgsa-H5HB6XZE,133
|
|
116
|
+
moru/sandbox/sandbox_api.py,sha256=vfqzl-rCF51YQFTtHUioOwiI05bEC4LUq7Wrffeipgg,5923
|
|
117
|
+
moru/sandbox/signature.py,sha256=QIMpJHE_UD00iQiwsGAdO8gJpqoP2MP1zHV8bbGWKDc,1203
|
|
118
|
+
moru/sandbox/utils.py,sha256=grMOJpeyk9YeS6dE7qCwBaJUaqgvrE4aKkGc9nVVfhI,1300
|
|
119
|
+
moru/sandbox_async/commands/command.py,sha256=b60rBXH6Akg_ioQqDp8fOye3ngfFu1lkLMA_QFlCrZ4,12485
|
|
120
|
+
moru/sandbox_async/commands/command_handle.py,sha256=5M05YMdMrNxboOpOSqy9htlGQOq9jCNkU78zBWzg5t4,5771
|
|
121
|
+
moru/sandbox_async/commands/pty.py,sha256=yIi-e_iWg0XWBXnze9UXyZTtQ8PNNEuV8cbXSopDKwA,7982
|
|
122
|
+
moru/sandbox_async/filesystem/filesystem.py,sha256=gKZzuQVB6g4U1Y6JPHcb1OgSBSeMw9b08yOhgc2pbig,18707
|
|
123
|
+
moru/sandbox_async/filesystem/watch_handle.py,sha256=EWe7Rd5r3LkCtF8jAKSNO400FxBnGqiXfVMYWEyXlgc,1969
|
|
124
|
+
moru/sandbox_async/main.py,sha256=EhRJX32q2VT9ORXCKZF9NbemwSC1ycgRJI2Ltm5Nn_o,23583
|
|
125
|
+
moru/sandbox_async/paginator.py,sha256=eW5hKXItevPPEuuAuItSao2zvLBOOQjeMaoJ3NlnbUI,2296
|
|
126
|
+
moru/sandbox_async/sandbox_api.py,sha256=a9g5KeSjbht64PAKrXtJ1PgITQuNPO7tvSXc7CwoeoE,9995
|
|
127
|
+
moru/sandbox_async/utils.py,sha256=mplhnoDat1PswDksAlnz2Zp4zzUGSIdr_76kiFYZQK8,159
|
|
128
|
+
moru/sandbox_sync/commands/command.py,sha256=dI1GrzzdUBB4wnzFegPh3oWfzVSRltNRtzcld_M1f4g,11626
|
|
129
|
+
moru/sandbox_sync/commands/command_handle.py,sha256=d1HDROr_hw3I9JW2yaCJcKOyDnSI2V1JHvTKHWwgG3k,4633
|
|
130
|
+
moru/sandbox_sync/commands/pty.py,sha256=IZUpyR0-XaEDcEn2MLxb-WtF9DFa3eK0bzdLKkeqLac,7590
|
|
131
|
+
moru/sandbox_sync/filesystem/filesystem.py,sha256=MMdW-zMCXWPmJRQuri5jWn51xLhQihg9u1F4R_vG7iI,17852
|
|
132
|
+
moru/sandbox_sync/filesystem/watch_handle.py,sha256=R5KnqUFQjb_nfQ29B0jfG4Imm-YjK09tYrRUU36n5hM,2059
|
|
133
|
+
moru/sandbox_sync/main.py,sha256=K6cg4lt8nqgWByBerPhjS9drPi_EPs_XKSxDQfczUtQ,22948
|
|
134
|
+
moru/sandbox_sync/paginator.py,sha256=FqWhMm7ykqmDYITc8cz7muUH-AUsi3cydBiJYWqsaZo,2264
|
|
135
|
+
moru/sandbox_sync/sandbox_api.py,sha256=f2-m8mIMmHR9qAWOlACiJOGLOn9DTt6NvUFkNoI1LUo,9171
|
|
136
|
+
moru/template/consts.py,sha256=opZ2iHQxt1gpR67PlbJvpxYfHlzsAB8q7XD0a98cu5o,756
|
|
137
|
+
moru/template/dockerfile_parser.py,sha256=SzOeZdyk5bI0f9PDTP4ST4ZTBUOoBwsC0vUvY2PoilM,8996
|
|
138
|
+
moru/template/logger.py,sha256=_L8HSaoAcWaBHcqbJ-7gUkAf_ccqSi2ZtQfGGL6rwQg,6088
|
|
139
|
+
moru/template/main.py,sha256=F1byCKH4pPbMctU6oydqxYNWumEpmZsJjSe7RzhAWeg,43618
|
|
140
|
+
moru/template/readycmd.py,sha256=7GP9p-epA4nP0F5IvjQ1V67XWVpLHlu8UX_ZMauheks,3210
|
|
141
|
+
moru/template/types.py,sha256=81eOKx63GpjvlgsdoBGJhXL1like2Cy7mmxo9omu_f8,2291
|
|
142
|
+
moru/template/utils.py,sha256=tCacYCwzI5puclQjlRwfPXk9gp4tDhVycBjkkXbbj38,9655
|
|
143
|
+
moru/template_async/build_api.py,sha256=98OrYIGcuDroT5bihx8RejAm0ge0ADg_YX1ms6axF6k,6076
|
|
144
|
+
moru/template_async/main.py,sha256=T9AKqw7ekdagDj8WKBAmAEvkqpj8kOMwdVENagyoLZE,11943
|
|
145
|
+
moru/template_sync/build_api.py,sha256=4SM9WDlX5HyVlA2NdJAquM1c8ax_9cc_wKr1MGwu9p4,5951
|
|
146
|
+
moru/template_sync/main.py,sha256=NSFhKjhv_n5vV4Ra2bc1zBDxcBFRumBlUnV_lPfBZCI,11901
|
|
147
|
+
moru_connect/__init__.py,sha256=ToGN4_2p-tV3QVUKcfHNg6U1qbbERaUjym8SJN3VCls,81
|
|
148
|
+
moru_connect/client.py,sha256=u1kYyb1wuE0-rdGw-ymCftxGH_o-8mb1w3Q8NFVSJ8E,13030
|
|
149
|
+
moru-0.1.0.dist-info/METADATA,sha256=SBdbX-AIBCbXizCg-HCm6bnq4NBBO4uCtAWpEcw_8Nw,1691
|
|
150
|
+
moru-0.1.0.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
|
|
151
|
+
moru-0.1.0.dist-info/licenses/LICENSE,sha256=ONtx_RW5j6C0mPjF7nBaSVcOMREIXCd_uJteoQfsTcs,1074
|
|
152
|
+
moru-0.1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 FOUNDRYLABS, INC.
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
6
|
+
|
|
7
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
8
|
+
|
|
9
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
moru_connect/__init__.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from .client import Client, GzipCompressor, ConnectException, Code # noqa: F401
|
moru_connect/client.py
ADDED
|
@@ -0,0 +1,493 @@
|
|
|
1
|
+
import gzip
|
|
2
|
+
import inspect
|
|
3
|
+
import json
|
|
4
|
+
import struct
|
|
5
|
+
import typing
|
|
6
|
+
|
|
7
|
+
from httpcore import (
|
|
8
|
+
ConnectionPool,
|
|
9
|
+
AsyncConnectionPool,
|
|
10
|
+
RemoteProtocolError,
|
|
11
|
+
Response,
|
|
12
|
+
)
|
|
13
|
+
from enum import Flag, Enum
|
|
14
|
+
from typing import Callable, Optional, Dict, Any, Generator, Tuple
|
|
15
|
+
from google.protobuf import json_format
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class EnvelopeFlags(Flag):
|
|
19
|
+
compressed = 0b00000001
|
|
20
|
+
end_stream = 0b00000010
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class Code(Enum):
|
|
24
|
+
canceled = "canceled"
|
|
25
|
+
unknown = "unknown"
|
|
26
|
+
invalid_argument = "invalid_argument"
|
|
27
|
+
deadline_exceeded = "deadline_exceeded"
|
|
28
|
+
not_found = "not_found"
|
|
29
|
+
already_exists = "already_exists"
|
|
30
|
+
permission_denied = "permission_denied"
|
|
31
|
+
resource_exhausted = "resource_exhausted"
|
|
32
|
+
failed_precondition = "failed_precondition"
|
|
33
|
+
aborted = "aborted"
|
|
34
|
+
out_of_range = "out_of_range"
|
|
35
|
+
unimplemented = "unimplemented"
|
|
36
|
+
internal = "internal"
|
|
37
|
+
unavailable = "unavailable"
|
|
38
|
+
data_loss = "data_loss"
|
|
39
|
+
unauthenticated = "unauthenticated"
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def make_error_from_http_code(http_code: int):
|
|
43
|
+
error_code_map = {
|
|
44
|
+
400: Code.invalid_argument,
|
|
45
|
+
401: Code.unauthenticated,
|
|
46
|
+
403: Code.permission_denied,
|
|
47
|
+
404: Code.not_found,
|
|
48
|
+
409: Code.already_exists,
|
|
49
|
+
413: Code.resource_exhausted,
|
|
50
|
+
429: Code.resource_exhausted,
|
|
51
|
+
499: Code.canceled,
|
|
52
|
+
500: Code.internal,
|
|
53
|
+
501: Code.unimplemented,
|
|
54
|
+
502: Code.unavailable,
|
|
55
|
+
503: Code.unavailable,
|
|
56
|
+
504: Code.deadline_exceeded,
|
|
57
|
+
505: Code.unimplemented,
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return error_code_map.get(http_code, Code.unknown)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
class ConnectException(Exception):
|
|
64
|
+
def __init__(self, status: Code, message: str):
|
|
65
|
+
self.status = status
|
|
66
|
+
self.message = message
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
envelope_header_length = 5
|
|
70
|
+
envelope_header_pack = ">BI"
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def encode_envelope(*, flags: EnvelopeFlags, data):
|
|
74
|
+
return encode_envelope_header(flags=flags.value, data=data) + data
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def encode_envelope_header(*, flags, data):
|
|
78
|
+
return struct.pack(envelope_header_pack, flags, len(data))
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def decode_envelope_header(header):
|
|
82
|
+
flags, data_len = struct.unpack(envelope_header_pack, header)
|
|
83
|
+
return EnvelopeFlags(flags), data_len
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def error_for_response(http_resp: Response):
|
|
87
|
+
try:
|
|
88
|
+
error = json.loads(http_resp.content)
|
|
89
|
+
return make_error(error)
|
|
90
|
+
except (json.decoder.JSONDecodeError, KeyError):
|
|
91
|
+
error = {"code": http_resp.status, "message": http_resp.content.decode("utf-8")}
|
|
92
|
+
return make_error(error)
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def make_error(error):
|
|
96
|
+
status = None
|
|
97
|
+
try:
|
|
98
|
+
code_value = error.get("code")
|
|
99
|
+
# return error code from http status code
|
|
100
|
+
if isinstance(code_value, int):
|
|
101
|
+
status = make_error_from_http_code(code_value)
|
|
102
|
+
else:
|
|
103
|
+
status = Code(code_value)
|
|
104
|
+
except (KeyError, ValueError):
|
|
105
|
+
status = Code.unknown
|
|
106
|
+
|
|
107
|
+
return ConnectException(status, error.get("message", ""))
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def _sync_retry(func, exc, retries):
|
|
111
|
+
def retry(*args, **kwargs):
|
|
112
|
+
for _ in range(retries):
|
|
113
|
+
try:
|
|
114
|
+
return func(*args, **kwargs)
|
|
115
|
+
except exc:
|
|
116
|
+
continue
|
|
117
|
+
|
|
118
|
+
return func(*args, **kwargs)
|
|
119
|
+
|
|
120
|
+
return retry
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def _async_retry(func, exc, retries):
|
|
124
|
+
async def retry(*args, **kwargs):
|
|
125
|
+
for _ in range(retries):
|
|
126
|
+
try:
|
|
127
|
+
return await func(*args, **kwargs)
|
|
128
|
+
except exc:
|
|
129
|
+
continue
|
|
130
|
+
|
|
131
|
+
return await func(*args, **kwargs)
|
|
132
|
+
|
|
133
|
+
return retry
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
def _retry(exc: typing.Type[Exception], retries: int):
|
|
137
|
+
def decorator(func):
|
|
138
|
+
if inspect.iscoroutinefunction(func):
|
|
139
|
+
return _async_retry(func, exc, retries)
|
|
140
|
+
|
|
141
|
+
return _sync_retry(func, exc, retries)
|
|
142
|
+
|
|
143
|
+
return decorator
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
class GzipCompressor:
|
|
147
|
+
name = "gzip"
|
|
148
|
+
decompress = gzip.decompress
|
|
149
|
+
compress = gzip.compress
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
class JSONCodec:
|
|
153
|
+
content_type = "json"
|
|
154
|
+
|
|
155
|
+
@staticmethod
|
|
156
|
+
def encode(msg):
|
|
157
|
+
return json_format.MessageToJson(msg).encode("utf8")
|
|
158
|
+
|
|
159
|
+
@staticmethod
|
|
160
|
+
def decode(data, *, msg_type):
|
|
161
|
+
msg = msg_type()
|
|
162
|
+
json_format.Parse(data.decode("utf8"), msg, ignore_unknown_fields=True)
|
|
163
|
+
return msg
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
class ProtobufCodec:
|
|
167
|
+
content_type = "proto"
|
|
168
|
+
|
|
169
|
+
@staticmethod
|
|
170
|
+
def encode(msg):
|
|
171
|
+
return msg.SerializeToString()
|
|
172
|
+
|
|
173
|
+
@staticmethod
|
|
174
|
+
def decode(data, *, msg_type):
|
|
175
|
+
msg = msg_type()
|
|
176
|
+
msg.ParseFromString(data)
|
|
177
|
+
return msg
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
class Client:
|
|
181
|
+
def __init__(
|
|
182
|
+
self,
|
|
183
|
+
*,
|
|
184
|
+
pool: Optional[ConnectionPool] = None,
|
|
185
|
+
async_pool: Optional[AsyncConnectionPool] = None,
|
|
186
|
+
url: str,
|
|
187
|
+
response_type,
|
|
188
|
+
compressor=None,
|
|
189
|
+
json: Optional[bool] = False,
|
|
190
|
+
headers: Optional[Dict[str, str]] = None,
|
|
191
|
+
):
|
|
192
|
+
if headers is None:
|
|
193
|
+
headers = {}
|
|
194
|
+
|
|
195
|
+
self.pool = pool
|
|
196
|
+
self.async_pool = async_pool
|
|
197
|
+
self.url = url
|
|
198
|
+
self._codec = JSONCodec if json else ProtobufCodec
|
|
199
|
+
self._response_type = response_type
|
|
200
|
+
self._compressor = compressor
|
|
201
|
+
self._headers = headers
|
|
202
|
+
self._connection_retries = 3
|
|
203
|
+
|
|
204
|
+
def _prepare_unary_request(
|
|
205
|
+
self,
|
|
206
|
+
req,
|
|
207
|
+
request_timeout=None,
|
|
208
|
+
headers: Optional[dict] = None,
|
|
209
|
+
**opts,
|
|
210
|
+
) -> dict:
|
|
211
|
+
data = self._codec.encode(req)
|
|
212
|
+
|
|
213
|
+
if self._compressor is not None:
|
|
214
|
+
data = self._compressor.compress(data)
|
|
215
|
+
|
|
216
|
+
if headers is None:
|
|
217
|
+
headers = {}
|
|
218
|
+
|
|
219
|
+
extensions = (
|
|
220
|
+
None
|
|
221
|
+
if request_timeout is None
|
|
222
|
+
else {
|
|
223
|
+
"timeout": {
|
|
224
|
+
"connect": request_timeout,
|
|
225
|
+
"pool": request_timeout,
|
|
226
|
+
"read": request_timeout,
|
|
227
|
+
"write": request_timeout,
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
)
|
|
231
|
+
|
|
232
|
+
return {
|
|
233
|
+
"method": "POST",
|
|
234
|
+
"url": self.url,
|
|
235
|
+
"content": data,
|
|
236
|
+
"extensions": extensions,
|
|
237
|
+
"headers": {
|
|
238
|
+
**self._headers,
|
|
239
|
+
**headers,
|
|
240
|
+
**opts.get("headers", {}),
|
|
241
|
+
"connect-protocol-version": "1",
|
|
242
|
+
"content-encoding": (
|
|
243
|
+
"identity" if self._compressor is None else self._compressor.name
|
|
244
|
+
),
|
|
245
|
+
"content-type": f"application/{self._codec.content_type}",
|
|
246
|
+
},
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
def _process_unary_response(
|
|
250
|
+
self,
|
|
251
|
+
http_resp: Response,
|
|
252
|
+
):
|
|
253
|
+
if http_resp.status != 200:
|
|
254
|
+
raise error_for_response(http_resp)
|
|
255
|
+
|
|
256
|
+
content = http_resp.content
|
|
257
|
+
|
|
258
|
+
if self._compressor is not None:
|
|
259
|
+
content = self._compressor.decompress(content)
|
|
260
|
+
|
|
261
|
+
return self._codec.decode(
|
|
262
|
+
content,
|
|
263
|
+
msg_type=self._response_type,
|
|
264
|
+
)
|
|
265
|
+
|
|
266
|
+
@_retry(RemoteProtocolError, 3)
|
|
267
|
+
async def acall_unary(
|
|
268
|
+
self,
|
|
269
|
+
req,
|
|
270
|
+
request_timeout=None,
|
|
271
|
+
headers: Optional[dict] = None,
|
|
272
|
+
**opts,
|
|
273
|
+
):
|
|
274
|
+
if self.async_pool is None:
|
|
275
|
+
raise ValueError("async_pool is required")
|
|
276
|
+
|
|
277
|
+
req_data = self._prepare_unary_request(
|
|
278
|
+
req,
|
|
279
|
+
request_timeout,
|
|
280
|
+
headers,
|
|
281
|
+
**opts,
|
|
282
|
+
)
|
|
283
|
+
|
|
284
|
+
res = await self.async_pool.request(**req_data)
|
|
285
|
+
return self._process_unary_response(res)
|
|
286
|
+
|
|
287
|
+
@_retry(RemoteProtocolError, 3)
|
|
288
|
+
def call_unary(
|
|
289
|
+
self,
|
|
290
|
+
req,
|
|
291
|
+
request_timeout=None,
|
|
292
|
+
headers: Optional[dict] = None,
|
|
293
|
+
**opts,
|
|
294
|
+
):
|
|
295
|
+
if self.pool is None:
|
|
296
|
+
raise ValueError("pool is required")
|
|
297
|
+
|
|
298
|
+
req_data = self._prepare_unary_request(
|
|
299
|
+
req,
|
|
300
|
+
request_timeout,
|
|
301
|
+
headers,
|
|
302
|
+
**opts,
|
|
303
|
+
)
|
|
304
|
+
|
|
305
|
+
res = self.pool.request(**req_data)
|
|
306
|
+
return self._process_unary_response(res)
|
|
307
|
+
|
|
308
|
+
def _create_stream_timeout(self, timeout: Optional[int]):
|
|
309
|
+
if timeout:
|
|
310
|
+
return {"connect-timeout-ms": str(timeout * 1000)}
|
|
311
|
+
return {}
|
|
312
|
+
|
|
313
|
+
def _prepare_server_stream_request(
|
|
314
|
+
self,
|
|
315
|
+
req,
|
|
316
|
+
request_timeout=None,
|
|
317
|
+
timeout=None,
|
|
318
|
+
headers: Optional[dict] = None,
|
|
319
|
+
**opts,
|
|
320
|
+
) -> dict:
|
|
321
|
+
headers = headers or {}
|
|
322
|
+
data = self._codec.encode(req)
|
|
323
|
+
flags = EnvelopeFlags(0)
|
|
324
|
+
|
|
325
|
+
extensions = (
|
|
326
|
+
None
|
|
327
|
+
if request_timeout is None
|
|
328
|
+
else {"timeout": {"connect": request_timeout, "pool": request_timeout}}
|
|
329
|
+
)
|
|
330
|
+
|
|
331
|
+
if self._compressor is not None:
|
|
332
|
+
data = self._compressor.compress(data)
|
|
333
|
+
flags |= EnvelopeFlags.compressed
|
|
334
|
+
|
|
335
|
+
stream_timeout = self._create_stream_timeout(timeout)
|
|
336
|
+
|
|
337
|
+
return {
|
|
338
|
+
"method": "POST",
|
|
339
|
+
"url": self.url,
|
|
340
|
+
"content": encode_envelope(
|
|
341
|
+
flags=flags,
|
|
342
|
+
data=data,
|
|
343
|
+
),
|
|
344
|
+
"extensions": extensions,
|
|
345
|
+
"headers": {
|
|
346
|
+
**self._headers,
|
|
347
|
+
**headers,
|
|
348
|
+
**opts.get("headers", {}),
|
|
349
|
+
**stream_timeout,
|
|
350
|
+
"connect-protocol-version": "1",
|
|
351
|
+
"connect-content-encoding": (
|
|
352
|
+
"identity" if self._compressor is None else self._compressor.name
|
|
353
|
+
),
|
|
354
|
+
"content-type": f"application/connect+{self._codec.content_type}",
|
|
355
|
+
},
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
@_retry(RemoteProtocolError, 3)
|
|
359
|
+
async def acall_server_stream(
|
|
360
|
+
self,
|
|
361
|
+
req,
|
|
362
|
+
request_timeout=None,
|
|
363
|
+
timeout=None,
|
|
364
|
+
headers: Optional[dict] = None,
|
|
365
|
+
**opts,
|
|
366
|
+
):
|
|
367
|
+
if self.async_pool is None:
|
|
368
|
+
raise ValueError("async_pool is required")
|
|
369
|
+
|
|
370
|
+
req_data = self._prepare_server_stream_request(
|
|
371
|
+
req,
|
|
372
|
+
request_timeout,
|
|
373
|
+
timeout,
|
|
374
|
+
headers,
|
|
375
|
+
**opts,
|
|
376
|
+
)
|
|
377
|
+
|
|
378
|
+
parser = ServerStreamParser(
|
|
379
|
+
decode=self._codec.decode,
|
|
380
|
+
response_type=self._response_type,
|
|
381
|
+
)
|
|
382
|
+
|
|
383
|
+
async with self.async_pool.stream(**req_data) as http_resp:
|
|
384
|
+
if http_resp.status != 200:
|
|
385
|
+
await http_resp.aread()
|
|
386
|
+
raise error_for_response(http_resp)
|
|
387
|
+
|
|
388
|
+
async for chunk in http_resp.aiter_stream():
|
|
389
|
+
for parsed in parser.parse(chunk):
|
|
390
|
+
yield parsed
|
|
391
|
+
|
|
392
|
+
@_retry(RemoteProtocolError, 3)
|
|
393
|
+
def call_server_stream(
|
|
394
|
+
self,
|
|
395
|
+
req,
|
|
396
|
+
request_timeout=None,
|
|
397
|
+
timeout=None,
|
|
398
|
+
headers: Optional[dict] = None,
|
|
399
|
+
**opts,
|
|
400
|
+
):
|
|
401
|
+
if self.pool is None:
|
|
402
|
+
raise ValueError("pool is required")
|
|
403
|
+
|
|
404
|
+
req_data = self._prepare_server_stream_request(
|
|
405
|
+
req,
|
|
406
|
+
request_timeout,
|
|
407
|
+
timeout,
|
|
408
|
+
headers,
|
|
409
|
+
**opts,
|
|
410
|
+
)
|
|
411
|
+
|
|
412
|
+
parser = ServerStreamParser(
|
|
413
|
+
decode=self._codec.decode,
|
|
414
|
+
response_type=self._response_type,
|
|
415
|
+
)
|
|
416
|
+
|
|
417
|
+
with self.pool.stream(**req_data) as http_resp:
|
|
418
|
+
if http_resp.status != 200:
|
|
419
|
+
http_resp.read()
|
|
420
|
+
raise error_for_response(http_resp)
|
|
421
|
+
|
|
422
|
+
for chunk in http_resp.iter_stream():
|
|
423
|
+
for parsed in parser.parse(chunk):
|
|
424
|
+
yield parsed
|
|
425
|
+
|
|
426
|
+
def call_client_stream(self, req, **opts):
|
|
427
|
+
raise NotImplementedError("client stream not supported")
|
|
428
|
+
|
|
429
|
+
def acall_client_stream(self, req, **opts):
|
|
430
|
+
raise NotImplementedError("client stream not supported")
|
|
431
|
+
|
|
432
|
+
def call_bidi_stream(self, req, **opts):
|
|
433
|
+
raise NotImplementedError("bidi stream not supported")
|
|
434
|
+
|
|
435
|
+
def acall_bidi_stream(self, req, **opts):
|
|
436
|
+
raise NotImplementedError("bidi stream not supported")
|
|
437
|
+
|
|
438
|
+
|
|
439
|
+
DataLen = int
|
|
440
|
+
|
|
441
|
+
|
|
442
|
+
class ServerStreamParser:
|
|
443
|
+
def __init__(
|
|
444
|
+
self,
|
|
445
|
+
decode: Callable,
|
|
446
|
+
response_type: Any,
|
|
447
|
+
):
|
|
448
|
+
self.decode = decode
|
|
449
|
+
self.response_type = response_type
|
|
450
|
+
|
|
451
|
+
self.buffer: bytes = b""
|
|
452
|
+
self._header: Optional[tuple[EnvelopeFlags, DataLen]] = None
|
|
453
|
+
|
|
454
|
+
def shift_buffer(self, size: int):
|
|
455
|
+
buffer = self.buffer[:size]
|
|
456
|
+
self.buffer = self.buffer[size:]
|
|
457
|
+
return buffer
|
|
458
|
+
|
|
459
|
+
@property
|
|
460
|
+
def header(self) -> Tuple[EnvelopeFlags, DataLen]:
|
|
461
|
+
if self._header:
|
|
462
|
+
return self._header
|
|
463
|
+
|
|
464
|
+
header_data = self.shift_buffer(envelope_header_length)
|
|
465
|
+
self._header = decode_envelope_header(header_data)
|
|
466
|
+
|
|
467
|
+
return self._header
|
|
468
|
+
|
|
469
|
+
@header.deleter
|
|
470
|
+
def header(self):
|
|
471
|
+
self._header = None
|
|
472
|
+
|
|
473
|
+
def parse(self, chunk: bytes) -> Generator[Any, None, None]:
|
|
474
|
+
self.buffer += chunk
|
|
475
|
+
|
|
476
|
+
while len(self.buffer) >= envelope_header_length:
|
|
477
|
+
flags, data_len = self.header
|
|
478
|
+
|
|
479
|
+
if data_len > len(self.buffer):
|
|
480
|
+
break
|
|
481
|
+
|
|
482
|
+
data = self.shift_buffer(data_len)
|
|
483
|
+
|
|
484
|
+
if EnvelopeFlags.end_stream in flags:
|
|
485
|
+
data = json.loads(data)
|
|
486
|
+
|
|
487
|
+
if "error" in data:
|
|
488
|
+
raise make_error(data["error"])
|
|
489
|
+
|
|
490
|
+
return
|
|
491
|
+
|
|
492
|
+
yield self.decode(data, msg_type=self.response_type)
|
|
493
|
+
del self.header
|