chalkcompute 2.3.2__tar.gz → 2.3.4__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 (161) hide show
  1. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/PKG-INFO +1 -1
  2. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/__init__.py +9 -0
  3. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/__init__.pyi +16 -0
  4. chalkcompute-2.3.4/chalkcompute/_artifact.py +352 -0
  5. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_cls.py +17 -11
  6. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_container.py +13 -17
  7. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_function.py +9 -6
  8. chalkcompute-2.3.4/chalkcompute/_gen/chalk/artifactstore/v1/service_pb2.py +131 -0
  9. chalkcompute-2.3.4/chalkcompute/_gen/chalk/artifactstore/v1/service_pb2.pyi +374 -0
  10. chalkcompute-2.3.4/chalkcompute/_gen/chalk/artifactstore/v1/service_pb2_grpc.py +354 -0
  11. chalkcompute-2.3.4/chalkcompute/_gen/chalk/artifactstore/v1/service_pb2_grpc.pyi +120 -0
  12. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/chalk/auth/v1/agent_pb2.py +6 -6
  13. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/chalk/auth/v1/agent_pb2.pyi +10 -1
  14. chalkcompute-2.3.4/chalkcompute/_gen/chalk/container/v1/service_pb2.py +288 -0
  15. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/chalk/container/v1/service_pb2.pyi +42 -4
  16. chalkcompute-2.3.4/chalkcompute/_gen/chalk/sandbox/v1/runtime_service_pb2.py +72 -0
  17. chalkcompute-2.3.4/chalkcompute/_gen/chalk/sandbox/v1/runtime_service_pb2.pyi +170 -0
  18. chalkcompute-2.3.4/chalkcompute/_gen/chalk/sandbox/v1/runtime_service_pb2_grpc.py +82 -0
  19. chalkcompute-2.3.4/chalkcompute/_gen/chalk/sandbox/v1/runtime_service_pb2_grpc.pyi +41 -0
  20. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/chalk/sandbox/v1/service_pb2.py +54 -54
  21. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/chalk/sandbox/v1/service_pb2.pyi +42 -6
  22. chalkcompute-2.3.4/chalkcompute/_gen/chalk/volume/v1/__init__.py +0 -0
  23. chalkcompute-2.3.4/chalkcompute/_gen/chalk/volume/v2/__init__.py +0 -0
  24. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_sandbox.py +195 -0
  25. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_scaling_group.py +82 -7
  26. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_secret.py +65 -24
  27. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/pyproject.toml +1 -1
  28. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/rust/chalkcompute_native/Cargo.lock +14 -12
  29. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/rust/chalkcompute_native/Cargo.toml +1 -1
  30. chalkcompute-2.3.2/chalkcompute/_gen/chalk/container/v1/service_pb2.py +0 -282
  31. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/README.md +0 -0
  32. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_arrow_schema.py +0 -0
  33. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_auth_config.py +0 -0
  34. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_concurrency.py +0 -0
  35. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_connect.py +0 -0
  36. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/__init__.py +0 -0
  37. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/buf/__init__.py +0 -0
  38. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/buf/validate/__init__.py +0 -0
  39. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/buf/validate/validate_pb2.py +0 -0
  40. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/buf/validate/validate_pb2.pyi +0 -0
  41. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/buf/validate/validate_pb2_grpc.py +0 -0
  42. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/buf/validate/validate_pb2_grpc.pyi +0 -0
  43. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/chalk/__init__.py +0 -0
  44. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/chalk/argo/__init__.py +0 -0
  45. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/chalk/argo/v1/__init__.py +0 -0
  46. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/chalk/argo/v1/workflow_pb2.py +0 -0
  47. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/chalk/argo/v1/workflow_pb2.pyi +0 -0
  48. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/chalk/argo/v1/workflow_pb2_grpc.py +0 -0
  49. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/chalk/argo/v1/workflow_pb2_grpc.pyi +0 -0
  50. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/chalk/arrow/__init__.py +0 -0
  51. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/chalk/arrow/v1/__init__.py +0 -0
  52. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/chalk/arrow/v1/arrow_pb2.py +0 -0
  53. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/chalk/arrow/v1/arrow_pb2.pyi +0 -0
  54. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/chalk/arrow/v1/arrow_pb2_grpc.py +0 -0
  55. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/chalk/arrow/v1/arrow_pb2_grpc.pyi +0 -0
  56. {chalkcompute-2.3.2/chalkcompute/_gen/chalk/auth → chalkcompute-2.3.4/chalkcompute/_gen/chalk/artifactstore}/__init__.py +0 -0
  57. {chalkcompute-2.3.2/chalkcompute/_gen/chalk/auth → chalkcompute-2.3.4/chalkcompute/_gen/chalk/artifactstore}/v1/__init__.py +0 -0
  58. {chalkcompute-2.3.2/chalkcompute/_gen/chalk/common → chalkcompute-2.3.4/chalkcompute/_gen/chalk/auth}/__init__.py +0 -0
  59. {chalkcompute-2.3.2/chalkcompute/_gen/chalk/common → chalkcompute-2.3.4/chalkcompute/_gen/chalk/auth}/v1/__init__.py +0 -0
  60. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/chalk/auth/v1/agent_pb2_grpc.py +0 -0
  61. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/chalk/auth/v1/agent_pb2_grpc.pyi +0 -0
  62. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/chalk/auth/v1/audit_pb2.py +0 -0
  63. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/chalk/auth/v1/audit_pb2.pyi +0 -0
  64. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/chalk/auth/v1/audit_pb2_grpc.py +0 -0
  65. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/chalk/auth/v1/audit_pb2_grpc.pyi +0 -0
  66. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/chalk/auth/v1/displayagent_pb2.py +0 -0
  67. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/chalk/auth/v1/displayagent_pb2.pyi +0 -0
  68. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/chalk/auth/v1/displayagent_pb2_grpc.py +0 -0
  69. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/chalk/auth/v1/displayagent_pb2_grpc.pyi +0 -0
  70. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/chalk/auth/v1/featurepermission_pb2.py +0 -0
  71. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/chalk/auth/v1/featurepermission_pb2.pyi +0 -0
  72. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/chalk/auth/v1/featurepermission_pb2_grpc.py +0 -0
  73. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/chalk/auth/v1/featurepermission_pb2_grpc.pyi +0 -0
  74. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/chalk/auth/v1/permissions_pb2.py +0 -0
  75. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/chalk/auth/v1/permissions_pb2.pyi +0 -0
  76. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/chalk/auth/v1/permissions_pb2_grpc.py +0 -0
  77. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/chalk/auth/v1/permissions_pb2_grpc.pyi +0 -0
  78. {chalkcompute-2.3.2/chalkcompute/_gen/chalk/container → chalkcompute-2.3.4/chalkcompute/_gen/chalk/common}/__init__.py +0 -0
  79. {chalkcompute-2.3.2/chalkcompute/_gen/chalk/container → chalkcompute-2.3.4/chalkcompute/_gen/chalk/common}/v1/__init__.py +0 -0
  80. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/chalk/common/v1/chalk_error_pb2.py +0 -0
  81. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/chalk/common/v1/chalk_error_pb2.pyi +0 -0
  82. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/chalk/common/v1/chalk_error_pb2_grpc.py +0 -0
  83. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/chalk/common/v1/chalk_error_pb2_grpc.pyi +0 -0
  84. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/chalk/common/v1/log_pb2.py +0 -0
  85. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/chalk/common/v1/log_pb2.pyi +0 -0
  86. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/chalk/common/v1/log_pb2_grpc.py +0 -0
  87. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/chalk/common/v1/log_pb2_grpc.pyi +0 -0
  88. {chalkcompute-2.3.2/chalkcompute/_gen/chalk/externalfunctioncatalog → chalkcompute-2.3.4/chalkcompute/_gen/chalk/container}/__init__.py +0 -0
  89. {chalkcompute-2.3.2/chalkcompute/_gen/chalk/externalfunctioncatalog → chalkcompute-2.3.4/chalkcompute/_gen/chalk/container}/v1/__init__.py +0 -0
  90. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/chalk/container/v1/service_pb2_grpc.py +0 -0
  91. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/chalk/container/v1/service_pb2_grpc.pyi +0 -0
  92. {chalkcompute-2.3.2/chalkcompute/_gen/chalk/flags → chalkcompute-2.3.4/chalkcompute/_gen/chalk/externalfunctioncatalog}/__init__.py +0 -0
  93. {chalkcompute-2.3.2/chalkcompute/_gen/chalk/flags → chalkcompute-2.3.4/chalkcompute/_gen/chalk/externalfunctioncatalog}/v1/__init__.py +0 -0
  94. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/chalk/externalfunctioncatalog/v1/service_pb2.py +0 -0
  95. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/chalk/externalfunctioncatalog/v1/service_pb2.pyi +0 -0
  96. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/chalk/externalfunctioncatalog/v1/service_pb2_grpc.py +0 -0
  97. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/chalk/externalfunctioncatalog/v1/service_pb2_grpc.pyi +0 -0
  98. {chalkcompute-2.3.2/chalkcompute/_gen/chalk/runtime → chalkcompute-2.3.4/chalkcompute/_gen/chalk/flags}/__init__.py +0 -0
  99. {chalkcompute-2.3.2/chalkcompute/_gen/chalk/runtime → chalkcompute-2.3.4/chalkcompute/_gen/chalk/flags}/v1/__init__.py +0 -0
  100. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/chalk/flags/v1/flags_pb2.py +0 -0
  101. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/chalk/flags/v1/flags_pb2.pyi +0 -0
  102. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/chalk/flags/v1/flags_pb2_grpc.py +0 -0
  103. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/chalk/flags/v1/flags_pb2_grpc.pyi +0 -0
  104. {chalkcompute-2.3.2/chalkcompute/_gen/chalk/sandbox → chalkcompute-2.3.4/chalkcompute/_gen/chalk/runtime}/__init__.py +0 -0
  105. {chalkcompute-2.3.2/chalkcompute/_gen/chalk/sandbox → chalkcompute-2.3.4/chalkcompute/_gen/chalk/runtime}/v1/__init__.py +0 -0
  106. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/chalk/runtime/v1/remote_python_call_pb2.py +0 -0
  107. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/chalk/runtime/v1/remote_python_call_pb2.pyi +0 -0
  108. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/chalk/runtime/v1/remote_python_call_pb2_grpc.py +0 -0
  109. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/chalk/runtime/v1/remote_python_call_pb2_grpc.pyi +0 -0
  110. {chalkcompute-2.3.2/chalkcompute/_gen/chalk/scalinggroup → chalkcompute-2.3.4/chalkcompute/_gen/chalk/sandbox}/__init__.py +0 -0
  111. {chalkcompute-2.3.2/chalkcompute/_gen/chalk/scalinggroup → chalkcompute-2.3.4/chalkcompute/_gen/chalk/sandbox}/v1/__init__.py +0 -0
  112. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/chalk/sandbox/v1/service_pb2_grpc.py +0 -0
  113. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/chalk/sandbox/v1/service_pb2_grpc.pyi +0 -0
  114. {chalkcompute-2.3.2/chalkcompute/_gen/chalk/utils → chalkcompute-2.3.4/chalkcompute/_gen/chalk/scalinggroup}/__init__.py +0 -0
  115. {chalkcompute-2.3.2/chalkcompute/_gen/chalk/utils → chalkcompute-2.3.4/chalkcompute/_gen/chalk/scalinggroup}/v1/__init__.py +0 -0
  116. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/chalk/scalinggroup/v1/service_pb2.py +0 -0
  117. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/chalk/scalinggroup/v1/service_pb2.pyi +0 -0
  118. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/chalk/scalinggroup/v1/service_pb2_grpc.py +0 -0
  119. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/chalk/scalinggroup/v1/service_pb2_grpc.pyi +0 -0
  120. {chalkcompute-2.3.2/chalkcompute/_gen/chalk/volume → chalkcompute-2.3.4/chalkcompute/_gen/chalk/utils}/__init__.py +0 -0
  121. {chalkcompute-2.3.2/chalkcompute/_gen/chalk/volume → chalkcompute-2.3.4/chalkcompute/_gen/chalk/utils}/v1/__init__.py +0 -0
  122. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/chalk/utils/v1/encoding_pb2.py +0 -0
  123. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/chalk/utils/v1/encoding_pb2.pyi +0 -0
  124. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/chalk/utils/v1/encoding_pb2_grpc.py +0 -0
  125. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/chalk/utils/v1/encoding_pb2_grpc.pyi +0 -0
  126. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/chalk/utils/v1/field_change_pb2.py +0 -0
  127. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/chalk/utils/v1/field_change_pb2.pyi +0 -0
  128. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/chalk/utils/v1/field_change_pb2_grpc.py +0 -0
  129. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/chalk/utils/v1/field_change_pb2_grpc.pyi +0 -0
  130. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/chalk/utils/v1/sensitive_pb2.py +0 -0
  131. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/chalk/utils/v1/sensitive_pb2.pyi +0 -0
  132. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/chalk/utils/v1/sensitive_pb2_grpc.py +0 -0
  133. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/chalk/utils/v1/sensitive_pb2_grpc.pyi +0 -0
  134. {chalkcompute-2.3.2/chalkcompute/_gen/chalk/volume/v2 → chalkcompute-2.3.4/chalkcompute/_gen/chalk/volume}/__init__.py +0 -0
  135. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/chalk/volume/v1/volume_pb2.py +0 -0
  136. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/chalk/volume/v1/volume_pb2.pyi +0 -0
  137. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/chalk/volume/v1/volume_pb2_grpc.py +0 -0
  138. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/chalk/volume/v1/volume_pb2_grpc.pyi +0 -0
  139. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/chalk/volume/v2/volume_pb2.py +0 -0
  140. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/chalk/volume/v2/volume_pb2.pyi +0 -0
  141. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/chalk/volume/v2/volume_pb2_grpc.py +0 -0
  142. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_gen/chalk/volume/v2/volume_pb2_grpc.pyi +0 -0
  143. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_ignore.py +0 -0
  144. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_image.py +0 -0
  145. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_local_dev.py +0 -0
  146. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_logging.py +0 -0
  147. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_model.py +0 -0
  148. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_naming.py +0 -0
  149. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_native.pyi +0 -0
  150. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_progress.py +0 -0
  151. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_proto_pool.py +0 -0
  152. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_quota.py +0 -0
  153. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_rate_limit.py +0 -0
  154. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_remote_call_client.py +0 -0
  155. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_remote_function_tracing.py +0 -0
  156. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_retry.py +0 -0
  157. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_tracing.py +0 -0
  158. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_volume.py +0 -0
  159. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/_vvolume.py +0 -0
  160. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/chalkcompute/py.typed +0 -0
  161. {chalkcompute-2.3.2 → chalkcompute-2.3.4}/rust/chalkcompute_native/src/lib.rs +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: chalkcompute
3
- Version: 2.3.2
3
+ Version: 2.3.4
4
4
  Requires-Dist: grpcio>=1.60.0
5
5
  Requires-Dist: protobuf>=4.25.0
6
6
  Requires-Dist: httpx>=0.25.0
@@ -9,6 +9,11 @@ _setup_logging()
9
9
  # Keep top-level imports lazy so `import chalkcompute` does not eagerly import
10
10
  # the grpc/protobuf/client modules. Update `__init__.pyi` when adding exports.
11
11
  _LAZY_MAP: dict[str, tuple[str, str]] = {
12
+ # _artifact.py
13
+ "Artifact": ("chalkcompute._artifact", "Artifact"),
14
+ "ArtifactClient": ("chalkcompute._artifact", "ArtifactClient"),
15
+ "ArtifactError": ("chalkcompute._artifact", "ArtifactError"),
16
+ "ArtifactNotFoundError": ("chalkcompute._artifact", "ArtifactNotFoundError"),
12
17
  # _container.py
13
18
  "Container": ("chalkcompute._container", "Container"),
14
19
  "ContainerError": ("chalkcompute._container", "ContainerError"),
@@ -71,12 +76,15 @@ _LAZY_MAP: dict[str, tuple[str, str]] = {
71
76
  "LazyLocalFile": ("chalkcompute._image", "LazyLocalFile"),
72
77
  # _secret.py
73
78
  "Secret": ("chalkcompute._secret", "Secret"),
79
+ "SecretScope": ("chalkcompute._secret", "SecretScope"),
74
80
  "resolve_lazy_secrets": ("chalkcompute._secret", "resolve_lazy_secrets"),
75
81
  # _sandbox.py
76
82
  "ExecError": ("chalkcompute._sandbox", "ExecError"),
77
83
  "ExecEvent": ("chalkcompute._sandbox", "ExecEvent"),
78
84
  "ExecProcess": ("chalkcompute._sandbox", "ExecProcess"),
79
85
  "ExecResult": ("chalkcompute._sandbox", "ExecResult"),
86
+ "PythonExecution": ("chalkcompute._sandbox", "PythonExecution"),
87
+ "PythonSkippedArtifact": ("chalkcompute._sandbox", "PythonSkippedArtifact"),
80
88
  "Sandbox": ("chalkcompute._sandbox", "Sandbox"),
81
89
  "SandboxBuildError": ("chalkcompute._sandbox", "SandboxBuildError"),
82
90
  "SandboxClient": ("chalkcompute._sandbox", "SandboxClient"),
@@ -89,6 +97,7 @@ _LAZY_MAP: dict[str, tuple[str, str]] = {
89
97
  "ScalingGroupBuildError": ("chalkcompute._scaling_group", "ScalingGroupBuildError"),
90
98
  "ScalingGroupError": ("chalkcompute._scaling_group", "ScalingGroupError"),
91
99
  "ScalingGroupInfo": ("chalkcompute._scaling_group", "ScalingGroupInfo"),
100
+ "ReadinessProbe": ("chalkcompute._scaling_group", "ReadinessProbe"),
92
101
  # _volume.py
93
102
  "FileInfo": ("chalkcompute._volume", "FileInfo"),
94
103
  "Volume": ("chalkcompute._volume", "make_volume"),
@@ -1,3 +1,7 @@
1
+ from chalkcompute._artifact import Artifact as Artifact
2
+ from chalkcompute._artifact import ArtifactClient as ArtifactClient
3
+ from chalkcompute._artifact import ArtifactError as ArtifactError
4
+ from chalkcompute._artifact import ArtifactNotFoundError as ArtifactNotFoundError
1
5
  from chalkcompute._cls import ClassBuildError as ClassBuildError
2
6
  from chalkcompute._cls import ClassError as ClassError
3
7
  from chalkcompute._cls import RemoteClass as RemoteClass
@@ -47,6 +51,8 @@ from chalkcompute._sandbox import ExecError as ExecError
47
51
  from chalkcompute._sandbox import ExecEvent as ExecEvent
48
52
  from chalkcompute._sandbox import ExecProcess as ExecProcess
49
53
  from chalkcompute._sandbox import ExecResult as ExecResult
54
+ from chalkcompute._sandbox import PythonExecution as PythonExecution
55
+ from chalkcompute._sandbox import PythonSkippedArtifact as PythonSkippedArtifact
50
56
  from chalkcompute._sandbox import Sandbox as Sandbox
51
57
  from chalkcompute._sandbox import SandboxBuildError as SandboxBuildError
52
58
  from chalkcompute._sandbox import SandboxClient as SandboxClient
@@ -58,7 +64,9 @@ from chalkcompute._scaling_group import ScalingGroup as ScalingGroup
58
64
  from chalkcompute._scaling_group import ScalingGroupBuildError as ScalingGroupBuildError
59
65
  from chalkcompute._scaling_group import ScalingGroupError as ScalingGroupError
60
66
  from chalkcompute._scaling_group import ScalingGroupInfo as ScalingGroupInfo
67
+ from chalkcompute._scaling_group import ReadinessProbe as ReadinessProbe
61
68
  from chalkcompute._secret import Secret as Secret
69
+ from chalkcompute._secret import SecretScope as SecretScope
62
70
  from chalkcompute._secret import resolve_lazy_secrets as resolve_lazy_secrets
63
71
  from chalkcompute._tracing import span as span
64
72
  from chalkcompute._tracing import traced as traced
@@ -79,6 +87,10 @@ from chalkcompute._vvolume import VersionedVolume as VersionedVolume
79
87
  from chalkcompute._vvolume import VersionedVolumeClient as VersionedVolumeClient
80
88
 
81
89
  __all__ = [
90
+ "Artifact",
91
+ "ArtifactClient",
92
+ "ArtifactError",
93
+ "ArtifactNotFoundError",
82
94
  "Container",
83
95
  "ContainerError",
84
96
  "ContainerInfo",
@@ -123,11 +135,14 @@ __all__ = [
123
135
  "Image",
124
136
  "LazyLocalFile",
125
137
  "Secret",
138
+ "SecretScope",
126
139
  "resolve_lazy_secrets",
127
140
  "ExecError",
128
141
  "ExecEvent",
129
142
  "ExecProcess",
130
143
  "ExecResult",
144
+ "PythonExecution",
145
+ "PythonSkippedArtifact",
131
146
  "Sandbox",
132
147
  "SandboxBuildError",
133
148
  "SandboxClient",
@@ -139,6 +154,7 @@ __all__ = [
139
154
  "ScalingGroupBuildError",
140
155
  "ScalingGroupError",
141
156
  "ScalingGroupInfo",
157
+ "ReadinessProbe",
142
158
  "FileInfo",
143
159
  "Volume",
144
160
  "SimpleVolume",
@@ -0,0 +1,352 @@
1
+ """
2
+ Client for the Chalk artifact store (chalk.artifactstore.v1.ArtifactService).
3
+
4
+ Artifacts are durable, environment-scoped outputs: charts captured from
5
+ ``Sandbox.execute_python``, files saved with the in-sandbox ``save_artifact``
6
+ helper, or content stored directly through :meth:`ArtifactClient.create`.
7
+
8
+ Usage:
9
+ from chalkcompute import ArtifactClient, Sandbox
10
+
11
+ sandbox = Sandbox(image="python:3.12-slim").run()
12
+ execution = sandbox.execute_python(
13
+ "import altair as alt..."
14
+ )
15
+ for chart in execution.charts:
16
+ print(chart.name, chart.chart_encoding)
17
+
18
+ client = ArtifactClient.from_env()
19
+ for artifact in client.list(kinds=["chart"]):
20
+ print(artifact.id, artifact.name)
21
+ """
22
+
23
+ from __future__ import annotations
24
+
25
+ from collections.abc import Iterator
26
+ from dataclasses import dataclass, field
27
+ from typing import Any
28
+
29
+ import grpc
30
+
31
+ from chalkcompute._connect import (
32
+ ConnectClient,
33
+ grpc_target_from_url,
34
+ raise_for_grpc_error,
35
+ )
36
+ from chalkcompute._gen.chalk.artifactstore.v1 import service_pb2 as pb
37
+ from chalkcompute._gen.chalk.artifactstore.v1 import service_pb2_grpc as pb_grpc
38
+ from chalkcompute._tracing import _instrumented
39
+
40
+ # Aliases defined before ArtifactClient, which has a ``.list()`` method that
41
+ # would otherwise shadow the builtin ``list`` in class-scope name resolution.
42
+ _GrpcMetadata = list[tuple[str, str]]
43
+ _StrList = list[str]
44
+
45
+ _KIND_TO_PROTO: dict[str, pb.ArtifactKind] = {
46
+ "file": pb.ARTIFACT_KIND_FILE,
47
+ "chart": pb.ARTIFACT_KIND_CHART,
48
+ "html": pb.ARTIFACT_KIND_HTML,
49
+ "image": pb.ARTIFACT_KIND_IMAGE,
50
+ }
51
+ _KIND_FROM_PROTO: dict[pb.ArtifactKind, str] = {v: k for k, v in _KIND_TO_PROTO.items()}
52
+
53
+ _PRODUCER_TO_PROTO: dict[str, pb.ArtifactProducer] = {
54
+ "user": pb.ARTIFACT_PRODUCER_USER,
55
+ "system": pb.ARTIFACT_PRODUCER_SYSTEM,
56
+ }
57
+ _PRODUCER_FROM_PROTO: dict[pb.ArtifactProducer, str] = {
58
+ v: k for k, v in _PRODUCER_TO_PROTO.items()
59
+ }
60
+
61
+
62
+ class ArtifactError(Exception):
63
+ """Base exception for artifact store errors."""
64
+
65
+ pass
66
+
67
+
68
+ class ArtifactNotFoundError(ArtifactError):
69
+ """Raised when an artifact is not found."""
70
+
71
+ pass
72
+
73
+
74
+ @dataclass
75
+ class Artifact:
76
+ """A stored artifact.
77
+
78
+ Small artifacts carry their content inline in ``data``; larger ones are
79
+ blob-backed and fetched on :meth:`download`.
80
+ """
81
+
82
+ id: str
83
+ """Artifact identifier."""
84
+
85
+ name: str
86
+ """User-facing label."""
87
+
88
+ kind: str
89
+ """One of ``"file"``, ``"chart"``, ``"html"``, ``"image"``."""
90
+
91
+ producer: str
92
+ """``"user"`` (saved explicitly) or ``"system"`` (discovered by Chalk)."""
93
+
94
+ content_type: str
95
+ """MIME type of the content."""
96
+
97
+ byte_size: int
98
+ """Content size in bytes."""
99
+
100
+ sandbox_id: str | None = None
101
+ """The sandbox that produced this artifact, when it came from one."""
102
+
103
+ execution_id: str | None = None
104
+ """The ExecutePython execution that produced this artifact, if any."""
105
+
106
+ chart_encoding: str | None = None
107
+ """For charts: ``"vega_lite"``, ``"tabular"``, or ``"plotly"``."""
108
+
109
+ chart_variable_name: str | None = None
110
+ """For captured charts: the variable the figure was bound to."""
111
+
112
+ data: bytes | None = None
113
+ """Inline content, when the artifact is small enough to travel inline."""
114
+
115
+ _client: ArtifactClient | None = field(default=None, repr=False, compare=False)
116
+
117
+ def download(self) -> bytes:
118
+ """Return the artifact's content bytes, fetching them if not inline."""
119
+ if self.data is not None:
120
+ return self.data
121
+ if self._client is None:
122
+ raise ArtifactError(
123
+ "Artifact has no attached client. Fetch it via ArtifactClient to download content."
124
+ )
125
+ self.data = self._client.download(self.id)
126
+ return self.data
127
+
128
+
129
+ def _artifact_from_proto(msg: pb.Artifact, client: ArtifactClient | None) -> Artifact:
130
+ chart_encoding: str | None = None
131
+ chart_variable_name: str | None = None
132
+ if msg.HasField("chart"):
133
+ chart_variable_name = msg.chart.variable_name or None
134
+ which = msg.chart.WhichOneof("chart")
135
+ if which == "vega_lite":
136
+ chart_encoding = "vega_lite"
137
+ elif which == "tabular":
138
+ chart_encoding = "tabular"
139
+ elif which == "plotly":
140
+ chart_encoding = "plotly"
141
+
142
+ sandbox_id: str | None = None
143
+ execution_id: str | None = None
144
+ if msg.origin.WhichOneof("origin") == "sandbox_exec":
145
+ sandbox_id = msg.origin.sandbox_exec.sandbox_id or None
146
+ execution_id = msg.origin.sandbox_exec.execution_id or None
147
+
148
+ data: bytes | None = None
149
+ byte_size = 0
150
+ if msg.WhichOneof("content") == "inline":
151
+ data = msg.inline.data
152
+ byte_size = len(data)
153
+ elif msg.WhichOneof("content") == "blob":
154
+ byte_size = msg.blob.byte_size
155
+
156
+ return Artifact(
157
+ id=msg.id,
158
+ name=msg.name,
159
+ kind=_KIND_FROM_PROTO.get(msg.kind, "file"),
160
+ producer=_PRODUCER_FROM_PROTO.get(msg.producer, "user"),
161
+ content_type=msg.content_type,
162
+ byte_size=byte_size,
163
+ sandbox_id=sandbox_id,
164
+ execution_id=execution_id,
165
+ chart_encoding=chart_encoding,
166
+ chart_variable_name=chart_variable_name,
167
+ data=data,
168
+ _client=client,
169
+ )
170
+
171
+
172
+ class ArtifactClient:
173
+ """Client for the artifact store gRPC service."""
174
+
175
+ def __init__(
176
+ self,
177
+ target: str = "localhost:50051",
178
+ *,
179
+ credentials: grpc.ChannelCredentials | None = None,
180
+ metadata: _GrpcMetadata | None = None,
181
+ ) -> None:
182
+ self._target = target
183
+ self._metadata = metadata
184
+ if credentials is not None:
185
+ self._channel = grpc.secure_channel(target, credentials)
186
+ else:
187
+ self._channel = grpc.insecure_channel(target)
188
+ self._stub = pb_grpc.ArtifactServiceStub(self._channel)
189
+
190
+ @classmethod
191
+ def _from_channel(
192
+ cls, channel: grpc.Channel, metadata: _GrpcMetadata | None
193
+ ) -> ArtifactClient:
194
+ """Internal: wrap an existing authenticated channel (no new connection)."""
195
+ client = cls.__new__(cls)
196
+ client._target = ""
197
+ client._metadata = metadata
198
+ client._channel = channel
199
+ client._stub = pb_grpc.ArtifactServiceStub(channel)
200
+ return client
201
+
202
+ @classmethod
203
+ def from_env(cls, *, chalk_client: Any | None = None) -> ArtifactClient:
204
+ """Create an ``ArtifactClient`` from ambient Chalk credentials."""
205
+ connect = ConnectClient(chalk_client=chalk_client)
206
+ connect._ensure_auth()
207
+ host, use_tls = grpc_target_from_url(connect._api_server or "")
208
+ return cls(
209
+ host,
210
+ credentials=grpc.ssl_channel_credentials() if use_tls else None,
211
+ metadata=[
212
+ ("authorization", f"Bearer {connect._access_token}"),
213
+ ("x-chalk-env-id", connect._env_id or ""),
214
+ ("x-chalk-server", "go-api"),
215
+ ],
216
+ )
217
+
218
+ def __enter__(self) -> ArtifactClient:
219
+ return self
220
+
221
+ def __exit__(self, *_args: object) -> None:
222
+ self.close()
223
+
224
+ def close(self) -> None:
225
+ """Close the gRPC channel."""
226
+ self._channel.close()
227
+
228
+ @_instrumented("chalkcompute.artifact.create")
229
+ def create(
230
+ self,
231
+ data: bytes | str,
232
+ *,
233
+ name: str,
234
+ kind: str = "file",
235
+ content_type: str = "application/octet-stream",
236
+ ) -> Artifact:
237
+ """Store an artifact with inline content (up to a few MiB)."""
238
+ if isinstance(data, str):
239
+ data = data.encode("utf-8")
240
+ if kind not in _KIND_TO_PROTO:
241
+ raise ArtifactError(
242
+ f"unknown artifact kind {kind!r}; expected one of {sorted(_KIND_TO_PROTO)}"
243
+ )
244
+ spec = pb.Artifact(
245
+ name=name,
246
+ kind=_KIND_TO_PROTO[kind],
247
+ producer=pb.ARTIFACT_PRODUCER_USER,
248
+ content_type=content_type,
249
+ inline=pb.ArtifactInlineContent(data=data),
250
+ )
251
+ try:
252
+ resp = self._stub.CreateArtifact(
253
+ pb.CreateArtifactRequest(artifact=spec), metadata=self._metadata
254
+ )
255
+ except grpc.RpcError as e:
256
+ _handle_artifact_rpc_error(e, name)
257
+ raise
258
+ return _artifact_from_proto(resp.artifact, self)
259
+
260
+ @_instrumented("chalkcompute.artifact.get")
261
+ def get(self, artifact_id: str) -> Artifact:
262
+ """Fetch a single artifact by id."""
263
+ try:
264
+ resp = self._stub.GetArtifact(
265
+ pb.GetArtifactRequest(artifact_id=artifact_id), metadata=self._metadata
266
+ )
267
+ except grpc.RpcError as e:
268
+ _handle_artifact_rpc_error(e, artifact_id)
269
+ raise
270
+ return _artifact_from_proto(resp.artifact, self)
271
+
272
+ @_instrumented("chalkcompute.artifact.list")
273
+ def list(
274
+ self,
275
+ *,
276
+ kinds: _StrList | None = None,
277
+ producers: _StrList | None = None,
278
+ sandbox_id: str | None = None,
279
+ limit: int | None = None,
280
+ ) -> Iterator[Artifact]:
281
+ """Iterate artifacts, newest first, paging transparently."""
282
+ cursor: str | None = None
283
+ remaining = limit
284
+ while True:
285
+ req = pb.ListArtifactsRequest(
286
+ kinds=[_KIND_TO_PROTO[k] for k in kinds or []],
287
+ producers=[_PRODUCER_TO_PROTO[p] for p in producers or []],
288
+ )
289
+ if sandbox_id is not None:
290
+ req.sandbox_id = sandbox_id
291
+ if cursor is not None:
292
+ req.cursor = cursor
293
+ if remaining is not None:
294
+ req.limit = min(remaining, 100)
295
+ try:
296
+ resp = self._stub.ListArtifacts(req, metadata=self._metadata)
297
+ except grpc.RpcError as e:
298
+ _handle_artifact_rpc_error(e, "list")
299
+ raise
300
+ for msg in resp.artifacts:
301
+ yield _artifact_from_proto(msg, self)
302
+ if remaining is not None:
303
+ remaining -= 1
304
+ if remaining <= 0:
305
+ return
306
+ if not resp.HasField("next_cursor") or not resp.next_cursor:
307
+ return
308
+ cursor = resp.next_cursor
309
+
310
+ @_instrumented("chalkcompute.artifact.download")
311
+ def download(self, artifact_id: str) -> bytes:
312
+ """Download an artifact's content bytes."""
313
+ chunks: list[bytes] = []
314
+ try:
315
+ for frame in self._stub.DownloadArtifact(
316
+ pb.DownloadArtifactRequest(artifact_id=artifact_id),
317
+ metadata=self._metadata,
318
+ ):
319
+ chunks.append(frame.data)
320
+ except grpc.RpcError as e:
321
+ _handle_artifact_rpc_error(e, artifact_id)
322
+ raise
323
+ return b"".join(chunks)
324
+
325
+ @_instrumented("chalkcompute.artifact.delete")
326
+ def delete(self, artifact_id: str) -> None:
327
+ """Delete an artifact and its stored content."""
328
+ try:
329
+ self._stub.DeleteArtifact(
330
+ pb.DeleteArtifactRequest(artifact_id=artifact_id),
331
+ metadata=self._metadata,
332
+ )
333
+ except grpc.RpcError as e:
334
+ _handle_artifact_rpc_error(e, artifact_id)
335
+ raise
336
+
337
+
338
+ def _handle_artifact_rpc_error(e: grpc.RpcError, subject: str) -> None:
339
+ """Translate mapped gRPC status codes to typed artifact errors.
340
+
341
+ Unmapped codes return so the caller re-raises the original gRPC error,
342
+ matching the sandbox/volume client convention.
343
+ """
344
+ raise_for_grpc_error(
345
+ e,
346
+ {
347
+ grpc.StatusCode.NOT_FOUND: (
348
+ ArtifactNotFoundError,
349
+ f"Artifact not found: {subject}",
350
+ ),
351
+ },
352
+ )
@@ -874,7 +874,7 @@ class RemoteClass:
874
874
  @classmethod
875
875
  def _make_empty(cls, name: str, *, chalk_client: Any | None = None) -> RemoteClass:
876
876
  rc = cls.__new__(cls)
877
- rc._user_cls = None # type: ignore[assignment]
877
+ rc._user_cls = None # ty: ignore[invalid-assignment]
878
878
  rc._class_name = name
879
879
  rc._explicit_name = name
880
880
  rc._image = None
@@ -1059,6 +1059,20 @@ class RemoteClass:
1059
1059
  self._volume_driver = driver
1060
1060
  _cleanup_temp_files(temp_files)
1061
1061
 
1062
+ # Resolve lazy secrets once, into a local rather than
1063
+ # self._secrets: they're shared by every method (one FUNCTION
1064
+ # scope for the class), and keeping self._secrets as the user's
1065
+ # lazy originals means a later .deploy() on the same object
1066
+ # re-upserts instead of reusing a stale resolution.
1067
+ resolved_secrets = self._secrets
1068
+ if self._secrets and any(s.is_lazy for s in self._secrets):
1069
+ from chalkcompute._secret import SecretScope, resolve_lazy_secrets
1070
+
1071
+ scope = SecretScope.function(self._explicit_name or self._class_name)
1072
+ resolved_secrets, _upserted = resolve_lazy_secrets(
1073
+ self._secrets, self._client, scope=scope
1074
+ )
1075
+
1062
1076
  # 3. Register each method as a function version
1063
1077
  sg_names: list[str] = []
1064
1078
  for method_info in self._methods.values():
@@ -1089,17 +1103,9 @@ class RemoteClass:
1089
1103
  volumes=self._volumes,
1090
1104
  )
1091
1105
 
1092
- # Resolve lazy secrets and add to container spec
1093
- if self._secrets:
1094
- from chalkcompute._secret import resolve_lazy_secrets
1095
-
1096
- if any(s.is_lazy for s in self._secrets):
1097
- resolved, _upserted = resolve_lazy_secrets(
1098
- self._secrets, self._client
1099
- )
1100
- self._secrets = resolved
1106
+ if resolved_secrets:
1101
1107
  container_spec["secretRefs"] = [
1102
- s._to_proto_dict() for s in self._secrets
1108
+ s._to_proto_dict() for s in resolved_secrets
1103
1109
  ]
1104
1110
 
1105
1111
  scaling_spec: dict[str, Any] = {
@@ -1011,7 +1011,6 @@ class Container:
1011
1011
  self._built_image_uri: str | None = None
1012
1012
  self._container_id: str | None = None
1013
1013
  self._container_info: ContainerInfo | None = None
1014
- self._upserted_secret_names: list[str] = []
1015
1014
 
1016
1015
  self._client = ConnectClient(chalk_client=chalk_client)
1017
1016
  self._session_client: ContainerSessionClient | None = None
@@ -1101,7 +1100,7 @@ class Container:
1101
1100
  @classmethod
1102
1101
  def _make_empty(cls, *, chalk_client: Any | None = None) -> Container:
1103
1102
  c = cls.__new__(cls)
1104
- c._image = None # type: ignore[assignment]
1103
+ c._image = None # ty: ignore[invalid-assignment]
1105
1104
  c._name = None
1106
1105
  c._cpu = None
1107
1106
  c._memory = None
@@ -1121,7 +1120,6 @@ class Container:
1121
1120
  c._built_image_uri = None
1122
1121
  c._container_id = None
1123
1122
  c._container_info = None
1124
- c._upserted_secret_names = []
1125
1123
  c._client = ConnectClient(chalk_client=chalk_client)
1126
1124
  c._session_client = None
1127
1125
  return c
@@ -1345,15 +1343,19 @@ class Container:
1345
1343
  )
1346
1344
  progress_done(vkey)
1347
1345
 
1348
- # 3. Resolve lazy secrets (from_local_env / from_local_env_file)
1346
+ # 3. Resolve lazy secrets (from_local_env / from_local_env_file).
1347
+ # Resolved into a local, not self._secrets, so a later .run() on
1348
+ # the same object re-upserts instead of reusing a stale resolution.
1349
+ resolved_secrets = self._secrets
1349
1350
  if any(s.is_lazy for s in self._secrets):
1350
1351
  skey = f"secret:{container_name}"
1351
1352
  progress_add(skey, "secret", "Resolving secrets", parent=ckey)
1352
- from chalkcompute._secret import resolve_lazy_secrets
1353
+ from chalkcompute._secret import SecretScope, resolve_lazy_secrets
1353
1354
 
1354
- resolved, upserted = resolve_lazy_secrets(self._secrets, self._client)
1355
- self._secrets = resolved
1356
- self._upserted_secret_names = upserted
1355
+ scope = SecretScope.sandbox(container_name)
1356
+ resolved_secrets, upserted = resolve_lazy_secrets(
1357
+ self._secrets, self._client, scope=scope
1358
+ )
1357
1359
  logger.info(
1358
1360
  "Upserted %d secret(s) from local environment.",
1359
1361
  len(upserted),
@@ -1403,8 +1405,8 @@ class Container:
1403
1405
  )
1404
1406
  spec["volumes"] = [v.to_spec_dict() for v in self._volumes]
1405
1407
 
1406
- if self._secrets:
1407
- spec["secretRefs"] = [s._to_proto_dict() for s in self._secrets]
1408
+ if resolved_secrets:
1409
+ spec["secretRefs"] = [s._to_proto_dict() for s in resolved_secrets]
1408
1410
 
1409
1411
  logger.info("Starting container '%s'...", container_name)
1410
1412
  resp = self._client.rpc(
@@ -1687,7 +1689,7 @@ class Container:
1687
1689
 
1688
1690
  @_instrumented("chalkcompute.container.stop")
1689
1691
  def stop(self, grace_period_seconds: int | None = None) -> None:
1690
- """Stop the container and clean up temporary volumes and secrets.
1692
+ """Stop the container and clean up temporary volumes.
1691
1693
 
1692
1694
  Parameters
1693
1695
  ----------
@@ -1718,12 +1720,6 @@ class Container:
1718
1720
  self._volumes = []
1719
1721
  self._volume_driver = None
1720
1722
 
1721
- if self._upserted_secret_names:
1722
- from chalkcompute._secret import delete_secrets
1723
-
1724
- delete_secrets(self._client, self._upserted_secret_names)
1725
- self._upserted_secret_names = []
1726
-
1727
1723
  def refresh(self) -> ContainerInfo:
1728
1724
  """Fetch latest container status from the server.
1729
1725
 
@@ -1943,17 +1943,20 @@ class RemoteFunction:
1943
1943
  "scalingSpec": scaling_spec,
1944
1944
  }
1945
1945
 
1946
- # 5b. Resolve lazy secrets and add to container spec
1946
+ # 5b. Resolve lazy secrets and add to container spec. Resolved
1947
+ # into a local, not self._secrets, so a later .deploy() on the
1948
+ # same object re-upserts instead of reusing a stale resolution.
1947
1949
  if self._secrets:
1948
- from chalkcompute._secret import resolve_lazy_secrets
1950
+ from chalkcompute._secret import SecretScope, resolve_lazy_secrets
1949
1951
 
1952
+ resolved_secrets = self._secrets
1950
1953
  if any(s.is_lazy for s in self._secrets):
1951
- resolved, _upserted = resolve_lazy_secrets(
1952
- self._secrets, self._client
1954
+ scope = SecretScope.function(self._explicit_name or self._func_name)
1955
+ resolved_secrets, _upserted = resolve_lazy_secrets(
1956
+ self._secrets, self._client, scope=scope
1953
1957
  )
1954
- self._secrets = resolved
1955
1958
  container_spec["secretRefs"] = [
1956
- s._to_proto_dict() for s in self._secrets
1959
+ s._to_proto_dict() for s in resolved_secrets
1957
1960
  ]
1958
1961
 
1959
1962
  # 5c. Build function-level config