chalkcompute 2.1.2__tar.gz → 2.1.8__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (129) hide show
  1. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/PKG-INFO +6 -2
  2. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/README.md +4 -0
  3. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/__init__.py +6 -0
  4. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/__init__.pyi +8 -0
  5. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_auth_config.py +4 -6
  6. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_cls.py +15 -14
  7. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_concurrency.py +1 -3
  8. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_connect.py +46 -2
  9. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_container.py +99 -33
  10. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_function.py +34 -129
  11. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_ignore.py +1 -1
  12. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_image.py +9 -3
  13. chalkcompute-2.1.8/chalkcompute/_local_dev.py +185 -0
  14. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_model.py +3 -1
  15. chalkcompute-2.1.8/chalkcompute/_native.pyi +124 -0
  16. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_proto_pool.py +7 -1
  17. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_remote_call_client.py +80 -10
  18. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_remote_function_tracing.py +1 -2
  19. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_sandbox.py +8 -2
  20. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_scaling_group.py +12 -7
  21. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_secret.py +4 -4
  22. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_volume.py +30 -25
  23. chalkcompute-2.1.8/chalkcompute/_vvolume.py +1280 -0
  24. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/pyproject.toml +11 -4
  25. {chalkcompute-2.1.2/rust/chalkcompute_remote_client → chalkcompute-2.1.8/rust/chalkcompute_native}/Cargo.lock +835 -31
  26. {chalkcompute-2.1.2/rust/chalkcompute_remote_client → chalkcompute-2.1.8/rust/chalkcompute_native}/Cargo.toml +3 -2
  27. {chalkcompute-2.1.2/rust/chalkcompute_remote_client → chalkcompute-2.1.8/rust/chalkcompute_native}/src/lib.rs +3 -2
  28. chalkcompute-2.1.2/chalkcompute/_remote_call_native.pyi +0 -52
  29. chalkcompute-2.1.2/chalkcompute/_vvolume.py +0 -1437
  30. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_arrow_schema.py +0 -0
  31. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/__init__.py +0 -0
  32. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/buf/__init__.py +0 -0
  33. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/buf/validate/__init__.py +0 -0
  34. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/buf/validate/validate_pb2.py +0 -0
  35. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/buf/validate/validate_pb2.pyi +0 -0
  36. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/chalk/__init__.py +0 -0
  37. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/chalk/arrow/__init__.py +0 -0
  38. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/chalk/arrow/v1/__init__.py +0 -0
  39. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/chalk/arrow/v1/arrow_pb2.py +0 -0
  40. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/chalk/arrow/v1/arrow_pb2.pyi +0 -0
  41. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/chalk/arrow/v1/arrow_pb2_grpc.py +0 -0
  42. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/chalk/arrow/v1/arrow_pb2_grpc.pyi +0 -0
  43. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/chalk/auth/__init__.py +0 -0
  44. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/chalk/auth/v1/__init__.py +0 -0
  45. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/chalk/auth/v1/agent_pb2.py +0 -0
  46. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/chalk/auth/v1/agent_pb2.pyi +0 -0
  47. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/chalk/auth/v1/agent_pb2_grpc.py +0 -0
  48. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/chalk/auth/v1/agent_pb2_grpc.pyi +0 -0
  49. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/chalk/auth/v1/audit_pb2.py +0 -0
  50. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/chalk/auth/v1/audit_pb2.pyi +0 -0
  51. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/chalk/auth/v1/audit_pb2_grpc.py +0 -0
  52. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/chalk/auth/v1/audit_pb2_grpc.pyi +0 -0
  53. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/chalk/auth/v1/displayagent_pb2.py +0 -0
  54. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/chalk/auth/v1/displayagent_pb2.pyi +0 -0
  55. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/chalk/auth/v1/displayagent_pb2_grpc.py +0 -0
  56. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/chalk/auth/v1/displayagent_pb2_grpc.pyi +0 -0
  57. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/chalk/auth/v1/featurepermission_pb2.py +0 -0
  58. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/chalk/auth/v1/featurepermission_pb2.pyi +0 -0
  59. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/chalk/auth/v1/featurepermission_pb2_grpc.py +0 -0
  60. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/chalk/auth/v1/featurepermission_pb2_grpc.pyi +0 -0
  61. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/chalk/auth/v1/permissions_pb2.py +0 -0
  62. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/chalk/auth/v1/permissions_pb2.pyi +0 -0
  63. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/chalk/auth/v1/permissions_pb2_grpc.py +0 -0
  64. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/chalk/auth/v1/permissions_pb2_grpc.pyi +0 -0
  65. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/chalk/common/__init__.py +0 -0
  66. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/chalk/common/v1/__init__.py +0 -0
  67. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/chalk/common/v1/chalk_error_pb2.py +0 -0
  68. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/chalk/common/v1/chalk_error_pb2.pyi +0 -0
  69. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/chalk/container/__init__.py +0 -0
  70. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/chalk/container/v1/__init__.py +0 -0
  71. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/chalk/container/v1/service_pb2.py +0 -0
  72. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/chalk/container/v1/service_pb2.pyi +0 -0
  73. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/chalk/container/v1/service_pb2_grpc.py +0 -0
  74. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/chalk/container/v1/service_pb2_grpc.pyi +0 -0
  75. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/chalk/externalfunctioncatalog/__init__.py +0 -0
  76. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/chalk/externalfunctioncatalog/v1/__init__.py +0 -0
  77. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/chalk/externalfunctioncatalog/v1/service_pb2.py +0 -0
  78. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/chalk/externalfunctioncatalog/v1/service_pb2.pyi +0 -0
  79. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/chalk/externalfunctioncatalog/v1/service_pb2_grpc.py +0 -0
  80. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/chalk/externalfunctioncatalog/v1/service_pb2_grpc.pyi +0 -0
  81. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/chalk/runtime/__init__.py +0 -0
  82. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/chalk/runtime/v1/__init__.py +0 -0
  83. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/chalk/runtime/v1/remote_python_call_pb2.py +0 -0
  84. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/chalk/runtime/v1/remote_python_call_pb2.pyi +0 -0
  85. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/chalk/sandbox/__init__.py +0 -0
  86. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/chalk/sandbox/v1/__init__.py +0 -0
  87. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/chalk/sandbox/v1/service_pb2.py +0 -0
  88. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/chalk/sandbox/v1/service_pb2.pyi +0 -0
  89. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/chalk/sandbox/v1/service_pb2_grpc.py +0 -0
  90. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/chalk/sandbox/v1/service_pb2_grpc.pyi +0 -0
  91. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/chalk/scalinggroup/__init__.py +0 -0
  92. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/chalk/scalinggroup/v1/__init__.py +0 -0
  93. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/chalk/scalinggroup/v1/service_pb2.py +0 -0
  94. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/chalk/scalinggroup/v1/service_pb2.pyi +0 -0
  95. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/chalk/scalinggroup/v1/service_pb2_grpc.py +0 -0
  96. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/chalk/scalinggroup/v1/service_pb2_grpc.pyi +0 -0
  97. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/chalk/utils/__init__.py +0 -0
  98. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/chalk/utils/v1/__init__.py +0 -0
  99. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/chalk/utils/v1/encoding_pb2.py +0 -0
  100. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/chalk/utils/v1/encoding_pb2.pyi +0 -0
  101. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/chalk/utils/v1/encoding_pb2_grpc.py +0 -0
  102. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/chalk/utils/v1/encoding_pb2_grpc.pyi +0 -0
  103. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/chalk/utils/v1/field_change_pb2.py +0 -0
  104. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/chalk/utils/v1/field_change_pb2.pyi +0 -0
  105. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/chalk/utils/v1/field_change_pb2_grpc.py +0 -0
  106. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/chalk/utils/v1/field_change_pb2_grpc.pyi +0 -0
  107. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/chalk/utils/v1/sensitive_pb2.py +0 -0
  108. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/chalk/utils/v1/sensitive_pb2.pyi +0 -0
  109. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/chalk/utils/v1/sensitive_pb2_grpc.py +0 -0
  110. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/chalk/utils/v1/sensitive_pb2_grpc.pyi +0 -0
  111. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/chalk/volume/__init__.py +0 -0
  112. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/chalk/volume/v1/__init__.py +0 -0
  113. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/chalk/volume/v1/volume_pb2.py +0 -0
  114. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/chalk/volume/v1/volume_pb2.pyi +0 -0
  115. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/chalk/volume/v1/volume_pb2_grpc.py +0 -0
  116. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/chalk/volume/v1/volume_pb2_grpc.pyi +0 -0
  117. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/chalk/volume/v2/__init__.py +0 -0
  118. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/chalk/volume/v2/volume_pb2.py +0 -0
  119. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/chalk/volume/v2/volume_pb2.pyi +0 -0
  120. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/chalk/volume/v2/volume_pb2_grpc.py +0 -0
  121. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_gen/chalk/volume/v2/volume_pb2_grpc.pyi +0 -0
  122. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_logging.py +0 -0
  123. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_naming.py +0 -0
  124. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_progress.py +0 -0
  125. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_quota.py +0 -0
  126. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_rate_limit.py +0 -0
  127. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_retry.py +0 -0
  128. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/_tracing.py +0 -0
  129. {chalkcompute-2.1.2 → chalkcompute-2.1.8}/chalkcompute/py.typed +0 -0
@@ -1,11 +1,11 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: chalkcompute
3
- Version: 2.1.2
3
+ Version: 2.1.8
4
4
  Requires-Dist: grpcio>=1.60.0
5
5
  Requires-Dist: protobuf>=4.25.0
6
6
  Requires-Dist: httpx>=0.25.0
7
7
  Requires-Dist: blake3>=1.0.0
8
- Requires-Dist: chalk-remote-call-python>=1.6.3
8
+ Requires-Dist: chalk-remote-call-python>=1.8.1
9
9
  Requires-Dist: pyyaml>=6.0.0
10
10
  Requires-Dist: opentelemetry-api>=1.20.0
11
11
  Requires-Dist: opentelemetry-sdk>=1.20.0
@@ -25,6 +25,10 @@ Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
25
25
 
26
26
  Python SDK for the Chalk Sandbox gRPC service. Create sandboxes, execute commands, and stream output over bidirectional gRPC streams.
27
27
 
28
+ Contributor note: for testing deployed functions against local `chalkcompute`
29
+ or local `chalk-remote-call-python` changes, see
30
+ `local-sdk-remote-call-testing.md`.
31
+
28
32
  ## Install
29
33
 
30
34
  ```
@@ -2,6 +2,10 @@
2
2
 
3
3
  Python SDK for the Chalk Sandbox gRPC service. Create sandboxes, execute commands, and stream output over bidirectional gRPC streams.
4
4
 
5
+ Contributor note: for testing deployed functions against local `chalkcompute`
6
+ or local `chalk-remote-call-python` changes, see
7
+ `local-sdk-remote-call-testing.md`.
8
+
5
9
  ## Install
6
10
 
7
11
  ```
@@ -18,6 +18,7 @@ _LAZY_MAP: dict[str, tuple[str, str]] = {
18
18
  "AllowedRoute": ("chalkcompute._container", "AllowedRoute"),
19
19
  "ImageBuildError": ("chalkcompute._container", "ImageBuildError"),
20
20
  "KernelPolicy": ("chalkcompute._container", "KernelPolicy"),
21
+ "ComputeClass": ("chalkcompute._container", "ComputeClass"),
21
22
  "NetworkPolicy": ("chalkcompute._container", "NetworkPolicy"),
22
23
  "PortRange": ("chalkcompute._container", "PortRange"),
23
24
  # _cls.py
@@ -65,6 +66,7 @@ _LAZY_MAP: dict[str, tuple[str, str]] = {
65
66
  "LazyLocalFile": ("chalkcompute._image", "LazyLocalFile"),
66
67
  # _secret.py
67
68
  "Secret": ("chalkcompute._secret", "Secret"),
69
+ "resolve_lazy_secrets": ("chalkcompute._secret", "resolve_lazy_secrets"),
68
70
  # _sandbox.py
69
71
  "ExecError": ("chalkcompute._sandbox", "ExecError"),
70
72
  "ExecEvent": ("chalkcompute._sandbox", "ExecEvent"),
@@ -92,6 +94,10 @@ _LAZY_MAP: dict[str, tuple[str, str]] = {
92
94
  "VolumeFileNotFoundError": ("chalkcompute._volume", "VolumeFileNotFoundError"),
93
95
  "VolumeInfo": ("chalkcompute._volume", "VolumeInfo"),
94
96
  "VolumeNotFoundError": ("chalkcompute._volume", "VolumeNotFoundError"),
97
+ "resolve_referenced_volume_type": (
98
+ "chalkcompute._volume",
99
+ "resolve_referenced_volume_type",
100
+ ),
95
101
  # _vvolume.py
96
102
  "VersionInfo": ("chalkcompute._vvolume", "VersionInfo"),
97
103
  "VersionedVolume": ("chalkcompute._vvolume", "VersionedVolume"),
@@ -18,6 +18,7 @@ from chalkcompute._container import ContainerInfo as ContainerInfo
18
18
  from chalkcompute._container import ContainerSecurityPolicy as ContainerSecurityPolicy
19
19
  from chalkcompute._container import ExecResult as ContainerExecResult
20
20
  from chalkcompute._container import ImageBuildError as ImageBuildError
21
+ from chalkcompute._container import ComputeClass as ComputeClass
21
22
  from chalkcompute._container import KernelPolicy as KernelPolicy
22
23
  from chalkcompute._container import NetworkPolicy as NetworkPolicy
23
24
  from chalkcompute._container import PortRange as PortRange
@@ -55,6 +56,7 @@ from chalkcompute._scaling_group import ScalingGroupBuildError as ScalingGroupBu
55
56
  from chalkcompute._scaling_group import ScalingGroupError as ScalingGroupError
56
57
  from chalkcompute._scaling_group import ScalingGroupInfo as ScalingGroupInfo
57
58
  from chalkcompute._secret import Secret as Secret
59
+ from chalkcompute._secret import resolve_lazy_secrets as resolve_lazy_secrets
58
60
  from chalkcompute._tracing import span as span
59
61
  from chalkcompute._tracing import traced as traced
60
62
  from chalkcompute._volume import FileInfo as FileInfo
@@ -66,6 +68,9 @@ from chalkcompute._volume import VolumeError as VolumeError
66
68
  from chalkcompute._volume import VolumeFileNotFoundError as VolumeFileNotFoundError
67
69
  from chalkcompute._volume import VolumeInfo as VolumeInfo
68
70
  from chalkcompute._volume import VolumeNotFoundError as VolumeNotFoundError
71
+ from chalkcompute._volume import (
72
+ resolve_referenced_volume_type as resolve_referenced_volume_type,
73
+ )
69
74
  from chalkcompute._vvolume import VersionInfo as VersionInfo
70
75
  from chalkcompute._vvolume import VersionedVolume as VersionedVolume
71
76
  from chalkcompute._vvolume import VersionedVolumeClient as VersionedVolumeClient
@@ -78,6 +83,7 @@ __all__ = [
78
83
  "ContainerExecResult",
79
84
  "AllowedRoute",
80
85
  "ImageBuildError",
86
+ "ComputeClass",
81
87
  "KernelPolicy",
82
88
  "NetworkPolicy",
83
89
  "PortRange",
@@ -113,6 +119,7 @@ __all__ = [
113
119
  "Image",
114
120
  "LazyLocalFile",
115
121
  "Secret",
122
+ "resolve_lazy_secrets",
116
123
  "ExecError",
117
124
  "ExecEvent",
118
125
  "ExecProcess",
@@ -137,6 +144,7 @@ __all__ = [
137
144
  "VolumeFileNotFoundError",
138
145
  "VolumeInfo",
139
146
  "VolumeNotFoundError",
147
+ "resolve_referenced_volume_type",
140
148
  "VersionInfo",
141
149
  "VersionedVolume",
142
150
  "VersionedVolumeClient",
@@ -152,11 +152,7 @@ def load_token(
152
152
  activeEnvironment=active_environment,
153
153
  )
154
154
 
155
- global_cfg = (
156
- _load_global_config_uncached()
157
- if skip_cache
158
- else _load_global_config()
159
- )
155
+ global_cfg = _load_global_config_uncached() if skip_cache else _load_global_config()
160
156
  if global_cfg is None:
161
157
  return None
162
158
 
@@ -186,7 +182,9 @@ def _load_project_config_at_path(filename: Path) -> ProjectSettings | None:
186
182
  except OSError:
187
183
  return None
188
184
  except ValueError as exc:
189
- raise ValueError(f"Failed to load project config from {filename}: {exc}") from exc
185
+ raise ValueError(
186
+ f"Failed to load project config from {filename}: {exc}"
187
+ ) from exc
190
188
 
191
189
 
192
190
  def load_project_config() -> ProjectSettings | None:
@@ -54,15 +54,8 @@ from dataclasses import dataclass, field
54
54
  from pathlib import Path
55
55
  from typing import TYPE_CHECKING, Any, Callable, TypeVar, overload
56
56
 
57
+ from chalkcompute._concurrency import ConcurrencyPolicy
57
58
  from chalkcompute._connect import ConnectClient
58
- from chalkcompute._naming import sanitize_dns_label, validate_dns_label, validate_env
59
- from chalkcompute._tracing import _instrumented
60
- from chalkcompute._volume import (
61
- VolumeDriver,
62
- VolumeMount,
63
- _resolve_driver,
64
- resolve_referenced_volume_type,
65
- )
66
59
  from chalkcompute._function import (
67
60
  _CATALOG_SVC,
68
61
  _REMOTE_ENV_VAR,
@@ -85,10 +78,18 @@ from chalkcompute._function import (
85
78
  _source_text_for_deploy,
86
79
  _write_temp,
87
80
  )
88
- from chalkcompute._concurrency import ConcurrencyPolicy
81
+ from chalkcompute._naming import sanitize_dns_label, validate_dns_label, validate_env
89
82
  from chalkcompute._quota import QueuePolicy
90
83
  from chalkcompute._rate_limit import RateLimitPolicy
91
84
  from chalkcompute._retry import RetryPolicy
85
+ from chalkcompute._tracing import _instrumented
86
+ from chalkcompute._volume import (
87
+ VolumeDriver,
88
+ VolumeMount,
89
+ cleanup_owned_volumes,
90
+ resolve_referenced_volume_type,
91
+ )
92
+ from chalkcompute._vvolume import VersionedVolumeClient
92
93
 
93
94
  if TYPE_CHECKING:
94
95
  from chalkcompute._image import Image as _Image
@@ -1163,8 +1164,7 @@ class RemoteClass:
1163
1164
  if resp.status_code != 200:
1164
1165
  progress_fail(mkey)
1165
1166
  raise ClassBuildError(
1166
- f"CreateExternalFunctionVersion failed for "
1167
- f"'{func_name}': {resp.text}"
1167
+ f"CreateExternalFunctionVersion failed for '{func_name}': {resp.text}"
1168
1168
  )
1169
1169
 
1170
1170
  data = resp.json()
@@ -1294,9 +1294,10 @@ class RemoteClass:
1294
1294
  if self._volumes:
1295
1295
  # Driver is used here only to perform the delete action, not to
1296
1296
  # derive a mount type.
1297
- driver = self._volume_driver or _resolve_driver(self._client)
1298
- for v in self._volumes:
1299
- driver.delete_volume(v.name)
1297
+ driver = self._volume_driver or VersionedVolumeClient.from_connect(
1298
+ self._client
1299
+ )
1300
+ cleanup_owned_volumes(driver, self._volumes, self._referenced_volumes)
1300
1301
  self._volumes = []
1301
1302
  self._volume_driver = None
1302
1303
  self._deployed = False
@@ -26,9 +26,7 @@ class ConcurrencyPolicy:
26
26
  return d
27
27
 
28
28
  @classmethod
29
- def from_int_or_policy(
30
- cls, value: int | ConcurrencyPolicy
31
- ) -> ConcurrencyPolicy:
29
+ def from_int_or_policy(cls, value: int | ConcurrencyPolicy) -> ConcurrencyPolicy:
32
30
  if isinstance(value, bool):
33
31
  raise TypeError(f"Expected int or {cls.__name__}, got bool")
34
32
  if isinstance(value, int):
@@ -44,6 +44,38 @@ def service_auth_context_from_env() -> ServiceAuthContext | None:
44
44
  return None
45
45
 
46
46
 
47
+ def chalk_client_from_env(
48
+ *,
49
+ api_server: str | None = None,
50
+ environment: str | None = None,
51
+ additional_headers: dict[str, str] | None = None,
52
+ **kwargs: Any,
53
+ ) -> Any:
54
+ from chalk.client import ChalkClient
55
+
56
+ headers = additional_headers
57
+ has_authorization = any(key.lower() == "authorization" for key in headers or {})
58
+ service_auth = service_auth_context_from_env()
59
+ if service_auth is not None and not has_authorization:
60
+ client = ConnectClient()
61
+ client._ensure_auth()
62
+ assert client._access_token is not None
63
+ assert client._api_server is not None
64
+ headers = {
65
+ **(headers or {}),
66
+ "Authorization": f"Bearer {client._access_token}",
67
+ }
68
+ api_server = api_server or client._api_server
69
+ environment = environment or service_auth.environment_id
70
+
71
+ if api_server is not None:
72
+ kwargs["api_server"] = api_server
73
+ if environment is not None:
74
+ kwargs["environment"] = environment
75
+ kwargs["additional_headers"] = headers
76
+ return ChalkClient(**kwargs)
77
+
78
+
47
79
  class ConnectClient:
48
80
  """Authenticated Connect-protocol (HTTP/JSON) client for Chalk APIs.
49
81
 
@@ -97,6 +129,14 @@ class ConnectClient:
97
129
  resp.raise_for_status()
98
130
  data = resp.json()
99
131
  self._access_token = data.get("accessToken") or data["access_token"]
132
+ self._grpc_engines = _string_map(
133
+ data.get("grpcEngines")
134
+ or data.get("grpc_engines")
135
+ or data.get("engines"),
136
+ )
137
+ self._environment_id_to_name = _string_map(
138
+ data.get("environment_id_to_name") or data.get("environmentIdToName"),
139
+ )
100
140
  self._env_id = self._resolve_environment_id(service_auth.environment_id)
101
141
  self._headers = {
102
142
  "Content-Type": "application/json",
@@ -430,12 +470,16 @@ def build_image_with_volumes(
430
470
  from chalkcompute._volume import VolumeClient
431
471
 
432
472
  image_uri = build_image(
433
- client, image, poll_interval=poll_interval, timeout=timeout,
473
+ client,
474
+ image,
475
+ poll_interval=poll_interval,
476
+ timeout=timeout,
434
477
  )
435
478
  volumes: list[VolumeMount] = []
436
479
  if image.lazy_local_files:
437
480
  volumes = VolumeClient.from_connect(client).upload_lazy_files(
438
- image, volume_prefix=volume_prefix,
481
+ image,
482
+ volume_prefix=volume_prefix,
439
483
  )
440
484
  return image_uri, volumes
441
485
 
@@ -28,20 +28,26 @@ from enum import Enum
28
28
  from typing import TYPE_CHECKING, Any
29
29
 
30
30
  from chalkcompute._connect import ConnectClient
31
+ from chalkcompute._naming import (
32
+ sanitize_dns_label,
33
+ validate_dns_label,
34
+ validate_env,
35
+ )
36
+ from chalkcompute._tracing import _instrumented
31
37
  from chalkcompute._volume import (
32
38
  VolumeDriver,
33
39
  VolumeError,
34
40
  VolumeMount,
35
- _resolve_driver,
41
+ cleanup_owned_volumes,
36
42
  resolve_referenced_volume_type,
37
43
  )
38
- from chalkcompute._naming import sanitize_dns_label, validate_dns_label, validate_env
39
- from chalkcompute._tracing import _instrumented
44
+ from chalkcompute._vvolume import VersionedVolumeClient
40
45
 
41
46
  logger = logging.getLogger(__name__)
42
47
 
43
48
  if TYPE_CHECKING:
44
49
  from collections.abc import Iterable
50
+
45
51
  from chalkcompute._image import Image as _Image
46
52
  from chalkcompute._secret import Secret
47
53
 
@@ -53,6 +59,7 @@ _IMAGE_SVC = "chalk.sandbox.v1.CustomImageService"
53
59
  # Exceptions
54
60
  # ---------------------------------------------------------------------------
55
61
 
62
+
56
63
  class ContainerError(Exception):
57
64
  """Base exception for Container errors."""
58
65
 
@@ -65,6 +72,7 @@ class ImageBuildError(ContainerError):
65
72
  # Data classes
66
73
  # ---------------------------------------------------------------------------
67
74
 
75
+
68
76
  @dataclass
69
77
  class ExecResult:
70
78
  """Result of a one-shot command executed inside a container.
@@ -107,6 +115,11 @@ class KernelPolicy(Enum):
107
115
  OPEN = "OPEN"
108
116
 
109
117
 
118
+ class ComputeClass(Enum):
119
+ K8S = "COMPUTE_CLASS_K8S"
120
+ HOST = "COMPUTE_CLASS_HOST"
121
+
122
+
110
123
  @dataclass
111
124
  class ContainerSecurityPolicy:
112
125
  """Security policy settings for a container.
@@ -233,6 +246,7 @@ class ContainerInfo:
233
246
  # Container
234
247
  # ---------------------------------------------------------------------------
235
248
 
249
+
236
250
  class Container:
237
251
  """A managed container backed by the Chalk ``ContainerService``.
238
252
 
@@ -277,6 +291,7 @@ class Container:
277
291
  enable_ssh: bool = False,
278
292
  security_policy: ContainerSecurityPolicy | None = None,
279
293
  network_policy: NetworkPolicy | None = None,
294
+ compute_class: ComputeClass | None = None,
280
295
  tags: dict[str, str] | None = None,
281
296
  chalk_client: Any | None = None,
282
297
  ) -> None:
@@ -287,7 +302,9 @@ class Container:
287
302
  if cpu is not None and not isinstance(cpu, str):
288
303
  raise TypeError(f"cpu must be a string such as '2' or '500m', got {cpu!r}")
289
304
  if memory is not None and not isinstance(memory, str):
290
- raise TypeError(f"memory must be a string such as '2Gi' or '512Mi', got {memory!r}")
305
+ raise TypeError(
306
+ f"memory must be a string such as '2Gi' or '512Mi', got {memory!r}"
307
+ )
291
308
  if gpu is not None and not isinstance(gpu, str):
292
309
  raise TypeError(f"gpu must be a string such as 'nvidia-l4', got {gpu!r}")
293
310
  self._cpu = cpu
@@ -299,7 +316,11 @@ class Container:
299
316
  referenced_volumes: list[tuple[str, str]] = []
300
317
  if volumes is not None:
301
318
  for item in volumes:
302
- if not (isinstance(item, (tuple, list)) and len(item) == 2 and all(isinstance(s, str) for s in item)):
319
+ if not (
320
+ isinstance(item, (tuple, list))
321
+ and len(item) == 2
322
+ and all(isinstance(s, str) for s in item)
323
+ ):
303
324
  raise ValueError(
304
325
  f"Each volumes entry must be a (name, mount_path) string tuple, got {item!r}. "
305
326
  f"Example: volumes=[('my-volume', '/data')]"
@@ -320,6 +341,7 @@ class Container:
320
341
  if lifetime is not None:
321
342
  from google.protobuf import duration_pb2
322
343
  from google.protobuf.json_format import Parse, ParseError
344
+
323
345
  try:
324
346
  _parsed_lifetime = Parse(f'"{lifetime}"', duration_pb2.Duration()) # ty: ignore[unresolved-attribute]
325
347
  except ParseError:
@@ -336,6 +358,7 @@ class Container:
336
358
  self._enable_ssh = enable_ssh
337
359
  self._security_policy = security_policy
338
360
  self._network_policy = network_policy
361
+ self._compute_class = compute_class
339
362
  self._tags: dict[str, str] = dict(tags or {})
340
363
 
341
364
  # Set after .run()
@@ -349,7 +372,9 @@ class Container:
349
372
  # -- Alternate constructors ------------------------------------------------
350
373
 
351
374
  @classmethod
352
- def from_id(cls, container_id: str, *, chalk_client: Any | None = None) -> Container:
375
+ def from_id(
376
+ cls, container_id: str, *, chalk_client: Any | None = None
377
+ ) -> Container:
353
378
  """Attach to an existing container by ID.
354
379
 
355
380
  Parameters
@@ -421,7 +446,10 @@ class Container:
421
446
  resp = c._client.rpc(_SVC, "ListContainers", {})
422
447
  if resp.status_code != 200:
423
448
  raise ContainerError(f"ListContainers failed: {resp.text}")
424
- return [_parse_container_response(item) for item in resp.json().get("containers", [])]
449
+ return [
450
+ _parse_container_response(item)
451
+ for item in resp.json().get("containers", [])
452
+ ]
425
453
 
426
454
  @classmethod
427
455
  def _make_empty(cls, *, chalk_client: Any | None = None) -> Container:
@@ -453,7 +481,10 @@ class Container:
453
481
  # -- Image building (Container uses BuildCustomImage with retries) ---------
454
482
 
455
483
  def _build_image(
456
- self, *, poll_interval: float = 0.5, timeout: float = 600.0,
484
+ self,
485
+ *,
486
+ poll_interval: float = 0.5,
487
+ timeout: float = 600.0,
457
488
  ) -> str:
458
489
  """Build the ``Image`` spec via ``CustomImageService`` and return the URI.
459
490
 
@@ -480,8 +511,10 @@ class Container:
480
511
  assert isinstance(self._image, Image)
481
512
  try:
482
513
  return build_image(
483
- self._client, self._image,
484
- poll_interval=poll_interval, timeout=timeout,
514
+ self._client,
515
+ self._image,
516
+ poll_interval=poll_interval,
517
+ timeout=timeout,
485
518
  )
486
519
  except ConnectError as e:
487
520
  raise ImageBuildError(str(e)) from e
@@ -586,20 +619,24 @@ class Container:
586
619
  >>> c.stop()
587
620
  """
588
621
  if self._container_id is not None:
589
- raise ContainerError("Container is already running. Call .stop() before calling .run() again.")
622
+ raise ContainerError(
623
+ "Container is already running. Call .stop() before calling .run() again."
624
+ )
590
625
 
626
+ from chalkcompute._image import Image
591
627
  from chalkcompute._progress import (
592
628
  progress_add,
593
629
  progress_done,
594
630
  progress_fail,
595
631
  progress_finish,
596
632
  )
597
- from chalkcompute._image import Image
598
633
 
599
- container_name = sanitize_dns_label(self._name or f"container-{uuid.uuid4().hex[:8]}")
634
+ container_name = sanitize_dns_label(
635
+ self._name or f"container-{uuid.uuid4().hex[:8]}"
636
+ )
600
637
  self._name = container_name
601
638
  ckey = f"container:{container_name}"
602
- progress_add(ckey, "container", f"Container \"{container_name}\"")
639
+ progress_add(ckey, "container", f'Container "{container_name}"')
603
640
 
604
641
  try:
605
642
  # 1. Resolve image URI
@@ -608,10 +645,13 @@ class Container:
608
645
  progress_add(ikey, "image", "Building image", parent=ckey)
609
646
  logger.info("Building image from %r...", self._image)
610
647
  self._built_image_uri = self._build_image(
611
- poll_interval=poll_interval, timeout=build_timeout,
648
+ poll_interval=poll_interval,
649
+ timeout=build_timeout,
612
650
  )
613
651
  logger.info("Image built: %s", self._built_image_uri)
614
- progress_done(ikey, detail="cached" if self._built_image_uri else "built")
652
+ progress_done(
653
+ ikey, detail="cached" if self._built_image_uri else "built"
654
+ )
615
655
  else:
616
656
  self._built_image_uri = self._image
617
657
 
@@ -628,24 +668,33 @@ class Container:
628
668
 
629
669
  # 2b. Upload lazy local files to a volume (if any)
630
670
  lazy_files = (
631
- self._image.lazy_local_files if isinstance(self._image, Image) else set()
671
+ self._image.lazy_local_files
672
+ if isinstance(self._image, Image)
673
+ else set()
632
674
  )
633
675
  if lazy_files:
634
676
  vkey = f"volume:{container_name}"
635
677
  progress_add(
636
- vkey, "volume",
678
+ vkey,
679
+ "volume",
637
680
  f"Uploading {len(lazy_files)} file(s)",
638
681
  parent=ckey,
639
682
  )
640
- logger.info("Uploading %d local file(s) to volume(s)...", len(lazy_files))
683
+ logger.info(
684
+ "Uploading %d local file(s) to volume(s)...",
685
+ len(lazy_files),
686
+ )
641
687
  assert isinstance(self._image, Image)
642
- driver = _resolve_driver(self._client)
688
+ driver = VersionedVolumeClient.from_connect(self._client)
643
689
  self._volume_driver = driver
644
690
  self._volumes += driver.upload_lazy_files(
645
- self._image, volume_prefix="container-files",
691
+ self._image,
692
+ volume_prefix="container-files",
646
693
  )
647
694
  for v in self._volumes:
648
- logger.info(" Volume created: %s (mount: %s)", v.name, v.mount_path)
695
+ logger.info(
696
+ " Volume created: %s (mount: %s)", v.name, v.mount_path
697
+ )
649
698
  progress_done(vkey)
650
699
 
651
700
  # 3. Resolve lazy secrets (from_local_env / from_local_env_file)
@@ -657,7 +706,10 @@ class Container:
657
706
  resolved, upserted = resolve_lazy_secrets(self._secrets, self._client)
658
707
  self._secrets = resolved
659
708
  self._upserted_secret_names = upserted
660
- logger.info("Upserted %d secret(s) from local environment.", len(upserted))
709
+ logger.info(
710
+ "Upserted %d secret(s) from local environment.",
711
+ len(upserted),
712
+ )
661
713
  progress_done(skey, detail=f"{len(upserted)} secret(s)")
662
714
 
663
715
  # 4. Build the ContainerService spec
@@ -679,6 +731,8 @@ class Container:
679
731
  spec["securityPolicy"] = self._security_policy.to_dict()
680
732
  if self._network_policy is not None:
681
733
  spec["networkPolicy"] = self._network_policy.to_dict()
734
+ if self._compute_class is not None:
735
+ spec["computeClass"] = self._compute_class.value
682
736
  if self._tags:
683
737
  spec["tags"] = dict(self._tags)
684
738
 
@@ -706,7 +760,10 @@ class Container:
706
760
 
707
761
  logger.info("Starting container '%s'...", container_name)
708
762
  resp = self._client.rpc(
709
- _SVC, "RunContainer", {"container": {"spec": spec}}, timeout=60,
763
+ _SVC,
764
+ "RunContainer",
765
+ {"container": {"spec": spec}},
766
+ timeout=60,
710
767
  )
711
768
  if resp.status_code != 200:
712
769
  raise ContainerError(f"RunContainer failed: {resp.text}")
@@ -716,7 +773,8 @@ class Container:
716
773
  self._container_id = self._container_info.id
717
774
  logger.info(
718
775
  "Container created: %s (status=%s)",
719
- self._container_id, self._container_info.status,
776
+ self._container_id,
777
+ self._container_info.status,
720
778
  )
721
779
 
722
780
  # 5. Poll until Running
@@ -725,7 +783,8 @@ class Container:
725
783
 
726
784
  progress_update(ckey, detail="booting")
727
785
  self._poll_until_running(
728
- poll_interval=poll_interval, timeout=ready_timeout,
786
+ poll_interval=poll_interval,
787
+ timeout=ready_timeout,
729
788
  )
730
789
 
731
790
  # 6. Wait for ChalkFS volume files to become visible
@@ -747,7 +806,10 @@ class Container:
747
806
  return self
748
807
 
749
808
  def _poll_until_running(
750
- self, *, poll_interval: float, timeout: float,
809
+ self,
810
+ *,
811
+ poll_interval: float,
812
+ timeout: float,
751
813
  ) -> None:
752
814
  assert self._container_id is not None
753
815
  deadline = time.monotonic() + timeout
@@ -773,12 +835,14 @@ class Container:
773
835
  time.sleep(poll_interval)
774
836
  status = self._container_info.status if self._container_info else "unknown"
775
837
  raise ContainerError(
776
- f"Container {self._container_id} timed out after {timeout}s "
777
- f"(last status: {status})"
838
+ f"Container {self._container_id} timed out after {timeout}s (last status: {status})"
778
839
  )
779
840
 
780
841
  def _wait_for_volume_files(
781
- self, *, timeout: float = 120.0, poll_interval: float = 0.5,
842
+ self,
843
+ *,
844
+ timeout: float = 120.0,
845
+ poll_interval: float = 0.5,
782
846
  ) -> None:
783
847
  """Poll until at least one uploaded file is visible in the ChalkFS mount.
784
848
 
@@ -934,9 +998,10 @@ class Container:
934
998
  if self._volumes:
935
999
  # Driver is used here only to perform the delete action, not to
936
1000
  # derive a mount type.
937
- driver = self._volume_driver or _resolve_driver(self._client)
938
- for v in self._volumes:
939
- driver.delete_volume(v.name)
1001
+ driver = self._volume_driver or VersionedVolumeClient.from_connect(
1002
+ self._client
1003
+ )
1004
+ cleanup_owned_volumes(driver, self._volumes, self._referenced_volumes)
940
1005
  self._volumes = []
941
1006
  self._volume_driver = None
942
1007
 
@@ -1005,6 +1070,7 @@ class Container:
1005
1070
  # Helpers
1006
1071
  # ---------------------------------------------------------------------------
1007
1072
 
1073
+
1008
1074
  def _parse_container_response(data: dict) -> ContainerInfo:
1009
1075
  return ContainerInfo(
1010
1076
  id=data["id"],