truss 0.10.0rc1__py3-none-any.whl → 0.60.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.

Potentially problematic release.


This version of truss might be problematic. Click here for more details.

Files changed (362) hide show
  1. truss/__init__.py +10 -3
  2. truss/api/__init__.py +123 -0
  3. truss/api/definitions.py +51 -0
  4. truss/base/constants.py +116 -0
  5. truss/base/custom_types.py +29 -0
  6. truss/{errors.py → base/errors.py} +4 -0
  7. truss/base/trt_llm_config.py +310 -0
  8. truss/{truss_config.py → base/truss_config.py} +344 -31
  9. truss/{truss_spec.py → base/truss_spec.py} +20 -6
  10. truss/{validation.py → base/validation.py} +60 -11
  11. truss/cli/cli.py +841 -88
  12. truss/{remote → cli}/remote_cli.py +2 -7
  13. truss/contexts/docker_build_setup.py +67 -0
  14. truss/contexts/image_builder/cache_warmer.py +2 -8
  15. truss/contexts/image_builder/image_builder.py +1 -1
  16. truss/contexts/image_builder/serving_image_builder.py +292 -46
  17. truss/contexts/image_builder/util.py +1 -3
  18. truss/contexts/local_loader/docker_build_emulator.py +58 -0
  19. truss/contexts/local_loader/load_model_local.py +2 -2
  20. truss/contexts/local_loader/truss_module_loader.py +1 -1
  21. truss/contexts/local_loader/utils.py +1 -1
  22. truss/local/local_config.py +2 -6
  23. truss/local/local_config_handler.py +20 -5
  24. truss/patch/__init__.py +1 -0
  25. truss/patch/hash.py +4 -70
  26. truss/patch/signature.py +4 -16
  27. truss/patch/truss_dir_patch_applier.py +3 -78
  28. truss/remote/baseten/api.py +308 -23
  29. truss/remote/baseten/auth.py +3 -3
  30. truss/remote/baseten/core.py +257 -50
  31. truss/remote/baseten/custom_types.py +44 -0
  32. truss/remote/baseten/error.py +4 -0
  33. truss/remote/baseten/remote.py +369 -118
  34. truss/remote/baseten/service.py +118 -11
  35. truss/remote/baseten/utils/status.py +29 -0
  36. truss/remote/baseten/utils/tar.py +34 -22
  37. truss/remote/baseten/utils/transfer.py +36 -23
  38. truss/remote/remote_factory.py +14 -5
  39. truss/remote/truss_remote.py +72 -45
  40. truss/templates/base.Dockerfile.jinja +18 -16
  41. truss/templates/cache.Dockerfile.jinja +3 -3
  42. truss/{server → templates/control}/control/application.py +14 -35
  43. truss/{server → templates/control}/control/endpoints.py +39 -9
  44. truss/{server/control/patch/types.py → templates/control/control/helpers/custom_types.py} +13 -52
  45. truss/{server → templates/control}/control/helpers/inference_server_controller.py +4 -8
  46. truss/{server → templates/control}/control/helpers/inference_server_process_controller.py +2 -4
  47. truss/{server → templates/control}/control/helpers/inference_server_starter.py +5 -10
  48. truss/{server/control → templates/control/control/helpers}/truss_patch/model_code_patch_applier.py +8 -6
  49. truss/{server/control/patch → templates/control/control/helpers/truss_patch}/model_container_patch_applier.py +18 -26
  50. truss/templates/control/control/helpers/truss_patch/requirement_name_identifier.py +66 -0
  51. truss/{server → templates/control}/control/server.py +11 -6
  52. truss/templates/control/requirements.txt +9 -0
  53. truss/templates/custom_python_dx/my_model.py +28 -0
  54. truss/templates/docker_server/proxy.conf.jinja +42 -0
  55. truss/templates/docker_server/supervisord.conf.jinja +27 -0
  56. truss/templates/docker_server_requirements.txt +1 -0
  57. truss/templates/server/common/errors.py +231 -0
  58. truss/{server → templates/server}/common/patches/whisper/patch.py +1 -0
  59. truss/{server/common/patches/__init__.py → templates/server/common/patches.py} +1 -3
  60. truss/{server → templates/server}/common/retry.py +1 -0
  61. truss/{server → templates/server}/common/schema.py +11 -9
  62. truss/templates/server/common/tracing.py +157 -0
  63. truss/templates/server/main.py +9 -0
  64. truss/templates/server/model_wrapper.py +961 -0
  65. truss/templates/server/requirements.txt +21 -0
  66. truss/templates/server/truss_server.py +447 -0
  67. truss/templates/server.Dockerfile.jinja +62 -14
  68. truss/templates/shared/dynamic_config_resolver.py +28 -0
  69. truss/templates/shared/lazy_data_resolver.py +164 -0
  70. truss/templates/shared/log_config.py +125 -0
  71. truss/{server → templates}/shared/secrets_resolver.py +1 -2
  72. truss/{server → templates}/shared/serialization.py +31 -9
  73. truss/{server → templates}/shared/util.py +3 -13
  74. truss/templates/trtllm-audio/model/model.py +49 -0
  75. truss/templates/trtllm-audio/packages/sigint_patch.py +14 -0
  76. truss/templates/trtllm-audio/packages/whisper_trt/__init__.py +215 -0
  77. truss/templates/trtllm-audio/packages/whisper_trt/assets.py +25 -0
  78. truss/templates/trtllm-audio/packages/whisper_trt/batching.py +52 -0
  79. truss/templates/trtllm-audio/packages/whisper_trt/custom_types.py +26 -0
  80. truss/templates/trtllm-audio/packages/whisper_trt/modeling.py +184 -0
  81. truss/templates/trtllm-audio/packages/whisper_trt/tokenizer.py +185 -0
  82. truss/templates/trtllm-audio/packages/whisper_trt/utils.py +245 -0
  83. truss/templates/trtllm-briton/src/extension.py +64 -0
  84. truss/tests/conftest.py +302 -94
  85. truss/tests/contexts/image_builder/test_serving_image_builder.py +74 -31
  86. truss/tests/contexts/local_loader/test_load_local.py +2 -2
  87. truss/tests/contexts/local_loader/test_truss_module_finder.py +1 -1
  88. truss/tests/patch/test_calc_patch.py +439 -127
  89. truss/tests/patch/test_dir_signature.py +3 -12
  90. truss/tests/patch/test_hash.py +1 -1
  91. truss/tests/patch/test_signature.py +1 -1
  92. truss/tests/patch/test_truss_dir_patch_applier.py +23 -11
  93. truss/tests/patch/test_types.py +2 -2
  94. truss/tests/remote/baseten/test_api.py +153 -58
  95. truss/tests/remote/baseten/test_auth.py +2 -1
  96. truss/tests/remote/baseten/test_core.py +160 -12
  97. truss/tests/remote/baseten/test_remote.py +489 -77
  98. truss/tests/remote/baseten/test_service.py +55 -0
  99. truss/tests/remote/test_remote_factory.py +16 -18
  100. truss/tests/remote/test_truss_remote.py +26 -17
  101. truss/tests/templates/control/control/helpers/test_context_managers.py +11 -0
  102. truss/tests/templates/control/control/helpers/test_model_container_patch_applier.py +184 -0
  103. truss/tests/templates/control/control/helpers/test_requirement_name_identifier.py +89 -0
  104. truss/tests/{server → templates/control}/control/test_server.py +79 -24
  105. truss/tests/{server → templates/control}/control/test_server_integration.py +24 -16
  106. truss/tests/templates/core/server/test_dynamic_config_resolver.py +108 -0
  107. truss/tests/templates/core/server/test_lazy_data_resolver.py +329 -0
  108. truss/tests/templates/core/server/test_lazy_data_resolver_v2.py +79 -0
  109. truss/tests/{server → templates}/core/server/test_secrets_resolver.py +1 -1
  110. truss/tests/{server → templates/server}/common/test_retry.py +3 -3
  111. truss/tests/templates/server/test_model_wrapper.py +248 -0
  112. truss/tests/{server → templates/server}/test_schema.py +3 -5
  113. truss/tests/{server/core/server/common → templates/server}/test_truss_server.py +8 -5
  114. truss/tests/test_build.py +9 -52
  115. truss/tests/test_config.py +336 -77
  116. truss/tests/test_context_builder_image.py +3 -11
  117. truss/tests/test_control_truss_patching.py +7 -12
  118. truss/tests/test_custom_server.py +38 -0
  119. truss/tests/test_data/context_builder_image_test/test.py +3 -0
  120. truss/tests/test_data/happy.ipynb +56 -0
  121. truss/tests/test_data/model_load_failure_test/config.yaml +2 -0
  122. truss/tests/test_data/model_load_failure_test/model/__init__.py +0 -0
  123. truss/tests/test_data/patch_ping_test_server/__init__.py +0 -0
  124. truss/{test_data → tests/test_data}/patch_ping_test_server/app.py +3 -9
  125. truss/{test_data → tests/test_data}/server.Dockerfile +20 -21
  126. truss/tests/test_data/server_conformance_test_truss/__init__.py +0 -0
  127. truss/tests/test_data/server_conformance_test_truss/model/__init__.py +0 -0
  128. truss/{test_data → tests/test_data}/server_conformance_test_truss/model/model.py +1 -3
  129. truss/tests/test_data/test_async_truss/__init__.py +0 -0
  130. truss/tests/test_data/test_async_truss/model/__init__.py +0 -0
  131. truss/tests/test_data/test_basic_truss/__init__.py +0 -0
  132. truss/tests/test_data/test_basic_truss/config.yaml +16 -0
  133. truss/tests/test_data/test_basic_truss/model/__init__.py +0 -0
  134. truss/tests/test_data/test_build_commands/__init__.py +0 -0
  135. truss/tests/test_data/test_build_commands/config.yaml +13 -0
  136. truss/tests/test_data/test_build_commands/model/__init__.py +0 -0
  137. truss/{test_data/test_streaming_async_generator_truss → tests/test_data/test_build_commands}/model/model.py +2 -3
  138. truss/tests/test_data/test_build_commands_failure/__init__.py +0 -0
  139. truss/tests/test_data/test_build_commands_failure/config.yaml +14 -0
  140. truss/tests/test_data/test_build_commands_failure/model/__init__.py +0 -0
  141. truss/tests/test_data/test_build_commands_failure/model/model.py +17 -0
  142. truss/tests/test_data/test_concurrency_truss/__init__.py +0 -0
  143. truss/tests/test_data/test_concurrency_truss/config.yaml +4 -0
  144. truss/tests/test_data/test_concurrency_truss/model/__init__.py +0 -0
  145. truss/tests/test_data/test_custom_server_truss/__init__.py +0 -0
  146. truss/tests/test_data/test_custom_server_truss/config.yaml +20 -0
  147. truss/tests/test_data/test_custom_server_truss/test_docker_image/Dockerfile +17 -0
  148. truss/tests/test_data/test_custom_server_truss/test_docker_image/README.md +10 -0
  149. truss/tests/test_data/test_custom_server_truss/test_docker_image/VERSION +1 -0
  150. truss/tests/test_data/test_custom_server_truss/test_docker_image/__init__.py +0 -0
  151. truss/tests/test_data/test_custom_server_truss/test_docker_image/app.py +19 -0
  152. truss/tests/test_data/test_custom_server_truss/test_docker_image/build_upload_new_image.sh +6 -0
  153. truss/tests/test_data/test_openai/__init__.py +0 -0
  154. truss/{test_data/test_basic_truss → tests/test_data/test_openai}/config.yaml +1 -2
  155. truss/tests/test_data/test_openai/model/__init__.py +0 -0
  156. truss/tests/test_data/test_openai/model/model.py +15 -0
  157. truss/tests/test_data/test_pyantic_v1/__init__.py +0 -0
  158. truss/tests/test_data/test_pyantic_v1/model/__init__.py +0 -0
  159. truss/tests/test_data/test_pyantic_v1/model/model.py +28 -0
  160. truss/tests/test_data/test_pyantic_v1/requirements.txt +1 -0
  161. truss/tests/test_data/test_pyantic_v2/__init__.py +0 -0
  162. truss/tests/test_data/test_pyantic_v2/config.yaml +13 -0
  163. truss/tests/test_data/test_pyantic_v2/model/__init__.py +0 -0
  164. truss/tests/test_data/test_pyantic_v2/model/model.py +30 -0
  165. truss/tests/test_data/test_pyantic_v2/requirements.txt +1 -0
  166. truss/tests/test_data/test_requirements_file_truss/__init__.py +0 -0
  167. truss/tests/test_data/test_requirements_file_truss/config.yaml +13 -0
  168. truss/tests/test_data/test_requirements_file_truss/model/__init__.py +0 -0
  169. truss/{test_data → tests/test_data}/test_requirements_file_truss/model/model.py +1 -0
  170. truss/tests/test_data/test_streaming_async_generator_truss/__init__.py +0 -0
  171. truss/tests/test_data/test_streaming_async_generator_truss/config.yaml +4 -0
  172. truss/tests/test_data/test_streaming_async_generator_truss/model/__init__.py +0 -0
  173. truss/tests/test_data/test_streaming_async_generator_truss/model/model.py +7 -0
  174. truss/tests/test_data/test_streaming_read_timeout/__init__.py +0 -0
  175. truss/tests/test_data/test_streaming_read_timeout/model/__init__.py +0 -0
  176. truss/tests/test_data/test_streaming_truss/__init__.py +0 -0
  177. truss/tests/test_data/test_streaming_truss/config.yaml +4 -0
  178. truss/tests/test_data/test_streaming_truss/model/__init__.py +0 -0
  179. truss/tests/test_data/test_streaming_truss_with_error/__init__.py +0 -0
  180. truss/tests/test_data/test_streaming_truss_with_error/model/__init__.py +0 -0
  181. truss/{test_data → tests/test_data}/test_streaming_truss_with_error/model/model.py +3 -11
  182. truss/tests/test_data/test_streaming_truss_with_error/packages/__init__.py +0 -0
  183. truss/tests/test_data/test_streaming_truss_with_error/packages/helpers_1.py +5 -0
  184. truss/tests/test_data/test_streaming_truss_with_error/packages/helpers_2.py +2 -0
  185. truss/tests/test_data/test_streaming_truss_with_tracing/__init__.py +0 -0
  186. truss/tests/test_data/test_streaming_truss_with_tracing/config.yaml +43 -0
  187. truss/tests/test_data/test_streaming_truss_with_tracing/model/__init__.py +0 -0
  188. truss/tests/test_data/test_streaming_truss_with_tracing/model/model.py +65 -0
  189. truss/tests/test_data/test_trt_llm_truss/__init__.py +0 -0
  190. truss/tests/test_data/test_trt_llm_truss/config.yaml +15 -0
  191. truss/tests/test_data/test_trt_llm_truss/model/__init__.py +0 -0
  192. truss/tests/test_data/test_trt_llm_truss/model/model.py +15 -0
  193. truss/tests/test_data/test_truss/__init__.py +0 -0
  194. truss/tests/test_data/test_truss/config.yaml +4 -0
  195. truss/tests/test_data/test_truss/model/__init__.py +0 -0
  196. truss/tests/test_data/test_truss/model/dummy +0 -0
  197. truss/tests/test_data/test_truss/packages/__init__.py +0 -0
  198. truss/tests/test_data/test_truss/packages/test_package/__init__.py +0 -0
  199. truss/tests/test_data/test_truss_server_caching_truss/__init__.py +0 -0
  200. truss/tests/test_data/test_truss_server_caching_truss/model/__init__.py +0 -0
  201. truss/tests/test_data/test_truss_with_error/__init__.py +0 -0
  202. truss/tests/test_data/test_truss_with_error/config.yaml +4 -0
  203. truss/tests/test_data/test_truss_with_error/model/__init__.py +0 -0
  204. truss/tests/test_data/test_truss_with_error/model/model.py +8 -0
  205. truss/tests/test_data/test_truss_with_error/packages/__init__.py +0 -0
  206. truss/tests/test_data/test_truss_with_error/packages/helpers_1.py +5 -0
  207. truss/tests/test_data/test_truss_with_error/packages/helpers_2.py +2 -0
  208. truss/tests/test_docker.py +2 -1
  209. truss/tests/test_model_inference.py +1340 -292
  210. truss/tests/test_model_schema.py +33 -26
  211. truss/tests/test_testing_utilities_for_other_tests.py +50 -5
  212. truss/tests/test_truss_gatherer.py +3 -5
  213. truss/tests/test_truss_handle.py +62 -59
  214. truss/tests/test_util.py +2 -1
  215. truss/tests/test_validation.py +15 -13
  216. truss/tests/trt_llm/test_trt_llm_config.py +41 -0
  217. truss/tests/trt_llm/test_validation.py +91 -0
  218. truss/tests/util/test_config_checks.py +40 -0
  219. truss/tests/util/test_env_vars.py +14 -0
  220. truss/tests/util/test_path.py +10 -23
  221. truss/trt_llm/config_checks.py +43 -0
  222. truss/trt_llm/validation.py +42 -0
  223. truss/truss_handle/__init__.py +0 -0
  224. truss/truss_handle/build.py +122 -0
  225. truss/{decorators.py → truss_handle/decorators.py} +1 -1
  226. truss/truss_handle/patch/__init__.py +0 -0
  227. truss/{patch → truss_handle/patch}/calc_patch.py +146 -92
  228. truss/{types.py → truss_handle/patch/custom_types.py} +35 -27
  229. truss/{patch → truss_handle/patch}/dir_signature.py +1 -1
  230. truss/truss_handle/patch/hash.py +71 -0
  231. truss/{patch → truss_handle/patch}/local_truss_patch_applier.py +6 -4
  232. truss/truss_handle/patch/signature.py +22 -0
  233. truss/truss_handle/patch/truss_dir_patch_applier.py +87 -0
  234. truss/{readme_generator.py → truss_handle/readme_generator.py} +3 -2
  235. truss/{truss_gatherer.py → truss_handle/truss_gatherer.py} +3 -2
  236. truss/{truss_handle.py → truss_handle/truss_handle.py} +174 -78
  237. truss/util/.truss_ignore +3 -0
  238. truss/{docker.py → util/docker.py} +6 -2
  239. truss/util/download.py +6 -15
  240. truss/util/env_vars.py +41 -0
  241. truss/util/log_utils.py +52 -0
  242. truss/util/path.py +20 -20
  243. truss/util/requirements.py +11 -0
  244. {truss-0.10.0rc1.dist-info → truss-0.60.0.dist-info}/METADATA +18 -16
  245. truss-0.60.0.dist-info/RECORD +324 -0
  246. {truss-0.10.0rc1.dist-info → truss-0.60.0.dist-info}/WHEEL +1 -1
  247. truss-0.60.0.dist-info/entry_points.txt +4 -0
  248. truss_chains/__init__.py +71 -0
  249. truss_chains/definitions.py +756 -0
  250. truss_chains/deployment/__init__.py +0 -0
  251. truss_chains/deployment/code_gen.py +816 -0
  252. truss_chains/deployment/deployment_client.py +871 -0
  253. truss_chains/framework.py +1480 -0
  254. truss_chains/public_api.py +231 -0
  255. truss_chains/py.typed +0 -0
  256. truss_chains/pydantic_numpy.py +131 -0
  257. truss_chains/reference_code/reference_chainlet.py +34 -0
  258. truss_chains/reference_code/reference_model.py +10 -0
  259. truss_chains/remote_chainlet/__init__.py +0 -0
  260. truss_chains/remote_chainlet/model_skeleton.py +60 -0
  261. truss_chains/remote_chainlet/stub.py +380 -0
  262. truss_chains/remote_chainlet/utils.py +332 -0
  263. truss_chains/streaming.py +378 -0
  264. truss_chains/utils.py +178 -0
  265. CODE_OF_CONDUCT.md +0 -131
  266. CONTRIBUTING.md +0 -48
  267. README.md +0 -137
  268. context_builder.Dockerfile +0 -24
  269. truss/blob/blob_backend.py +0 -10
  270. truss/blob/blob_backend_registry.py +0 -23
  271. truss/blob/http_public_blob_backend.py +0 -23
  272. truss/build/__init__.py +0 -2
  273. truss/build/build.py +0 -143
  274. truss/build/configure.py +0 -63
  275. truss/cli/__init__.py +0 -2
  276. truss/cli/console.py +0 -5
  277. truss/cli/create.py +0 -5
  278. truss/config/trt_llm.py +0 -81
  279. truss/constants.py +0 -61
  280. truss/model_inference.py +0 -123
  281. truss/patch/types.py +0 -30
  282. truss/pytest.ini +0 -7
  283. truss/server/common/errors.py +0 -100
  284. truss/server/common/termination_handler_middleware.py +0 -64
  285. truss/server/common/truss_server.py +0 -389
  286. truss/server/control/patch/model_code_patch_applier.py +0 -46
  287. truss/server/control/patch/requirement_name_identifier.py +0 -17
  288. truss/server/inference_server.py +0 -29
  289. truss/server/model_wrapper.py +0 -434
  290. truss/server/shared/logging.py +0 -81
  291. truss/templates/trtllm/model/model.py +0 -97
  292. truss/templates/trtllm/packages/build_engine_utils.py +0 -34
  293. truss/templates/trtllm/packages/constants.py +0 -11
  294. truss/templates/trtllm/packages/schema.py +0 -216
  295. truss/templates/trtllm/packages/tensorrt_llm_model_repository/ensemble/config.pbtxt +0 -246
  296. truss/templates/trtllm/packages/tensorrt_llm_model_repository/postprocessing/1/model.py +0 -181
  297. truss/templates/trtllm/packages/tensorrt_llm_model_repository/postprocessing/config.pbtxt +0 -64
  298. truss/templates/trtllm/packages/tensorrt_llm_model_repository/preprocessing/1/model.py +0 -260
  299. truss/templates/trtllm/packages/tensorrt_llm_model_repository/preprocessing/config.pbtxt +0 -99
  300. truss/templates/trtllm/packages/tensorrt_llm_model_repository/tensorrt_llm/config.pbtxt +0 -208
  301. truss/templates/trtllm/packages/triton_client.py +0 -150
  302. truss/templates/trtllm/packages/utils.py +0 -43
  303. truss/test_data/context_builder_image_test/test.py +0 -4
  304. truss/test_data/happy.ipynb +0 -54
  305. truss/test_data/model_load_failure_test/config.yaml +0 -2
  306. truss/test_data/test_concurrency_truss/config.yaml +0 -2
  307. truss/test_data/test_streaming_async_generator_truss/config.yaml +0 -2
  308. truss/test_data/test_streaming_truss/config.yaml +0 -3
  309. truss/test_data/test_truss/config.yaml +0 -2
  310. truss/tests/server/common/test_termination_handler_middleware.py +0 -93
  311. truss/tests/server/control/test_model_container_patch_applier.py +0 -203
  312. truss/tests/server/core/server/common/test_util.py +0 -19
  313. truss/tests/server/test_model_wrapper.py +0 -87
  314. truss/util/data_structures.py +0 -16
  315. truss-0.10.0rc1.dist-info/RECORD +0 -216
  316. truss-0.10.0rc1.dist-info/entry_points.txt +0 -3
  317. truss/{server/shared → base}/__init__.py +0 -0
  318. truss/{server → templates/control}/control/helpers/context_managers.py +0 -0
  319. truss/{server/control → templates/control/control/helpers}/errors.py +0 -0
  320. truss/{server/control/patch → templates/control/control/helpers/truss_patch}/__init__.py +0 -0
  321. truss/{server/control/patch → templates/control/control/helpers/truss_patch}/system_packages.py +0 -0
  322. truss/{test_data/annotated_types_truss/model → templates/server}/__init__.py +0 -0
  323. truss/{server → templates/server}/common/__init__.py +0 -0
  324. truss/{test_data/gcs_fix/model → templates/shared}/__init__.py +0 -0
  325. truss/templates/{trtllm → trtllm-briton}/README.md +0 -0
  326. truss/{test_data/server_conformance_test_truss/model → tests/test_data}/__init__.py +0 -0
  327. truss/{test_data/test_basic_truss/model → tests/test_data/annotated_types_truss}/__init__.py +0 -0
  328. truss/{test_data → tests/test_data}/annotated_types_truss/config.yaml +0 -0
  329. truss/{test_data/test_requirements_file_truss → tests/test_data/annotated_types_truss}/model/__init__.py +0 -0
  330. truss/{test_data → tests/test_data}/annotated_types_truss/model/model.py +0 -0
  331. truss/{test_data → tests/test_data}/auto-mpg.data +0 -0
  332. truss/{test_data → tests/test_data}/context_builder_image_test/Dockerfile +0 -0
  333. truss/{test_data/test_truss/model → tests/test_data/context_builder_image_test}/__init__.py +0 -0
  334. truss/{test_data/test_truss_server_caching_truss/model → tests/test_data/gcs_fix}/__init__.py +0 -0
  335. truss/{test_data → tests/test_data}/gcs_fix/config.yaml +0 -0
  336. truss/tests/{local → test_data/gcs_fix/model}/__init__.py +0 -0
  337. truss/{test_data → tests/test_data}/gcs_fix/model/model.py +0 -0
  338. truss/{test_data/test_truss/model/dummy → tests/test_data/model_load_failure_test/__init__.py} +0 -0
  339. truss/{test_data → tests/test_data}/model_load_failure_test/model/model.py +0 -0
  340. truss/{test_data → tests/test_data}/pima-indians-diabetes.csv +0 -0
  341. truss/{test_data → tests/test_data}/readme_int_example.md +0 -0
  342. truss/{test_data → tests/test_data}/readme_no_example.md +0 -0
  343. truss/{test_data → tests/test_data}/readme_str_example.md +0 -0
  344. truss/{test_data → tests/test_data}/server_conformance_test_truss/config.yaml +0 -0
  345. truss/{test_data → tests/test_data}/test_async_truss/config.yaml +0 -0
  346. truss/{test_data → tests/test_data}/test_async_truss/model/model.py +3 -3
  347. /truss/{test_data → tests/test_data}/test_basic_truss/model/model.py +0 -0
  348. /truss/{test_data → tests/test_data}/test_concurrency_truss/model/model.py +0 -0
  349. /truss/{test_data/test_requirements_file_truss → tests/test_data/test_pyantic_v1}/config.yaml +0 -0
  350. /truss/{test_data → tests/test_data}/test_requirements_file_truss/requirements.txt +0 -0
  351. /truss/{test_data → tests/test_data}/test_streaming_read_timeout/config.yaml +0 -0
  352. /truss/{test_data → tests/test_data}/test_streaming_read_timeout/model/model.py +0 -0
  353. /truss/{test_data → tests/test_data}/test_streaming_truss/model/model.py +0 -0
  354. /truss/{test_data → tests/test_data}/test_streaming_truss_with_error/config.yaml +0 -0
  355. /truss/{test_data → tests/test_data}/test_truss/examples.yaml +0 -0
  356. /truss/{test_data → tests/test_data}/test_truss/model/model.py +0 -0
  357. /truss/{test_data → tests/test_data}/test_truss/packages/test_package/test.py +0 -0
  358. /truss/{test_data → tests/test_data}/test_truss_server_caching_truss/config.yaml +0 -0
  359. /truss/{test_data → tests/test_data}/test_truss_server_caching_truss/model/model.py +0 -0
  360. /truss/{patch → truss_handle/patch}/constants.py +0 -0
  361. /truss/{notebook.py → util/notebook.py} +0 -0
  362. {truss-0.10.0rc1.dist-info → truss-0.60.0.dist-info}/LICENSE +0 -0
@@ -3,12 +3,11 @@ from pathlib import Path
3
3
  from typing import Dict, List, Optional, Set
4
4
 
5
5
  import yaml
6
- from truss.constants import CONFIG_FILE
7
- from truss.patch.hash import file_content_hash_str
8
- from truss.patch.types import TrussSignature
9
- from truss.server.control.patch.requirement_name_identifier import reqs_by_name
10
- from truss.server.control.patch.system_packages import system_packages_set
11
- from truss.server.control.patch.types import (
6
+
7
+ from truss.base.constants import CONFIG_FILE
8
+ from truss.base.truss_config import ExternalData, TrussConfig
9
+ from truss.base.truss_spec import TrussSpec
10
+ from truss.templates.control.control.helpers.custom_types import (
12
11
  Action,
13
12
  ConfigPatch,
14
13
  DataPatch,
@@ -21,20 +20,19 @@ from truss.server.control.patch.types import (
21
20
  PythonRequirementPatch,
22
21
  SystemPackagePatch,
23
22
  )
24
- from truss.truss_config import ExternalData, TrussConfig
25
- from truss.truss_spec import TrussSpec
23
+ from truss.templates.control.control.helpers.truss_patch.requirement_name_identifier import (
24
+ RequirementMeta,
25
+ )
26
+ from truss.templates.control.control.helpers.truss_patch.system_packages import (
27
+ system_packages_set,
28
+ )
29
+ from truss.truss_handle.patch.custom_types import ChangedPaths, TrussSignature
30
+ from truss.truss_handle.patch.hash import file_content_hash_str
26
31
  from truss.util.path import get_ignored_relative_paths
27
32
 
28
33
  logger: logging.Logger = logging.getLogger(__name__)
29
- PYCACHE_IGNORE_PATTERNS = [
30
- "**/__pycache__/**/*",
31
- "**/__pycache__/**",
32
- ]
33
- UNPATCHABLE_CONFIG_KEYS = [
34
- "live_reload",
35
- "python_version",
36
- "resources",
37
- ]
34
+ PYCACHE_IGNORE_PATTERNS = ["**/__pycache__/**/*", "**/__pycache__/**"]
35
+ UNPATCHABLE_CONFIG_KEYS = ["live_reload", "python_version", "resources"]
38
36
 
39
37
 
40
38
  def calc_truss_patch(
@@ -62,11 +60,12 @@ def calc_truss_patch(
62
60
  ignore_patterns = PYCACHE_IGNORE_PATTERNS
63
61
 
64
62
  changed_paths = _calc_changed_paths(
65
- truss_dir,
66
- previous_truss_signature.content_hashes_by_path,
67
- ignore_patterns,
63
+ truss_dir, previous_truss_signature.content_hashes_by_path, ignore_patterns
68
64
  )
69
65
 
66
+ new_config = TrussConfig.from_yaml(truss_dir / CONFIG_FILE)
67
+ prev_config = TrussConfig.from_dict(yaml.safe_load(previous_truss_signature.config))
68
+
70
69
  truss_spec = TrussSpec(truss_dir)
71
70
  model_module_path = _relative_to_root(truss_spec.model_module_dir)
72
71
  data_dir_path = _relative_to_root(truss_spec.data_dir)
@@ -82,6 +81,7 @@ def calc_truss_patch(
82
81
  return _strictly_under(path, [data_dir_path])
83
82
 
84
83
  patches = []
84
+
85
85
  for path in changed_paths["removed"]:
86
86
  if _strictly_under(path, [model_module_path]):
87
87
  logger.info(f"Created patch to remove model code file: {path}")
@@ -89,8 +89,7 @@ def calc_truss_patch(
89
89
  Patch(
90
90
  type=PatchType.MODEL_CODE,
91
91
  body=ModelCodePatch(
92
- action=Action.REMOVE,
93
- path=_relative_to(path, model_module_path),
92
+ action=Action.REMOVE, path=_relative_to(path, model_module_path)
94
93
  ),
95
94
  )
96
95
  )
@@ -110,9 +109,10 @@ def calc_truss_patch(
110
109
  )
111
110
  )
112
111
  elif _under_unsupported_patch_dir(path):
113
- logger.warn(f"Patching not supported for removing {path}")
112
+ logger.warning(f"Patching not supported for removing {path}")
114
113
  return None
115
114
 
115
+ has_calculated_config = False
116
116
  for path in changed_paths["added"] + changed_paths["updated"]:
117
117
  action = Action.ADD if path in changed_paths["added"] else Action.UPDATE
118
118
  if _strictly_under(path, [model_module_path]):
@@ -134,12 +134,16 @@ def calc_truss_patch(
134
134
  ),
135
135
  )
136
136
  )
137
- elif path == CONFIG_FILE:
138
- new_config = TrussConfig.from_yaml(truss_dir / CONFIG_FILE)
139
- prev_config = TrussConfig.from_dict(
140
- yaml.safe_load(previous_truss_signature.config)
137
+ elif (
138
+ path == CONFIG_FILE or _changed_path_is_requirements_file(path, new_config)
139
+ ) and not has_calculated_config:
140
+ # we could enter this code block from the requirements file's path
141
+ # or from the config file's path. In any case, we only want to calculate these
142
+ # patches once.
143
+ has_calculated_config = True
144
+ config_patches = _calc_config_patches(
145
+ truss_dir, previous_truss_signature, prev_config, new_config
141
146
  )
142
- config_patches = calc_config_patches(prev_config, new_config)
143
147
  if config_patches:
144
148
  logger.info(f"Created patch to {action.value.lower()} config")
145
149
  patches.extend(config_patches)
@@ -164,20 +168,32 @@ def calc_truss_patch(
164
168
  return patches
165
169
 
166
170
 
171
+ def _changed_path_is_requirements_file(changed_path: str, new_config: TrussConfig):
172
+ """
173
+ _changed_path_is_requirements_file determines if `changed_path` is the same path
174
+ as the requirements file on a new configuration.
175
+ """
176
+ return new_config.requirements_file and Path(changed_path) == Path(
177
+ new_config.requirements_file
178
+ )
179
+
180
+
167
181
  def _calc_changed_paths(
168
182
  root: Path,
169
183
  previous_root_path_content_hashes: Dict[str, str],
170
184
  ignore_patterns: Optional[List[str]],
171
- ) -> Dict[str, List[str]]:
185
+ ) -> ChangedPaths:
172
186
  """
173
187
  TODO(pankaj) add support for directory creation in patch
174
188
  """
175
189
  root_relative_new_paths = set(
176
190
  (str(path.relative_to(root)) for path in root.glob("**/*"))
177
191
  )
178
- unignored_new_paths = calc_unignored_paths(root_relative_new_paths, ignore_patterns)
192
+ unignored_new_paths = _calc_unignored_paths(
193
+ root_relative_new_paths, ignore_patterns
194
+ )
179
195
  previous_root_relative_paths = set(previous_root_path_content_hashes.keys())
180
- unignored_prev_paths = calc_unignored_paths(
196
+ unignored_prev_paths = _calc_unignored_paths(
181
197
  previous_root_relative_paths, ignore_patterns
182
198
  )
183
199
 
@@ -201,9 +217,8 @@ def _calc_changed_paths(
201
217
  }
202
218
 
203
219
 
204
- def calc_unignored_paths(
205
- root_relative_paths: Set[str],
206
- ignore_patterns: Optional[List[str]] = None,
220
+ def _calc_unignored_paths(
221
+ root_relative_paths: Set[str], ignore_patterns: Optional[List[str]] = None
207
222
  ) -> Set[str]:
208
223
  ignored_paths = set(
209
224
  get_ignored_relative_paths(root_relative_paths, ignore_patterns)
@@ -211,8 +226,11 @@ def calc_unignored_paths(
211
226
  return root_relative_paths - ignored_paths # type: ignore
212
227
 
213
228
 
214
- def calc_config_patches(
215
- prev_config: TrussConfig, new_config: TrussConfig
229
+ def _calc_config_patches(
230
+ truss_dir: Path,
231
+ prev_signature: TrussSignature,
232
+ prev_config: TrussConfig,
233
+ new_config: TrussConfig,
216
234
  ) -> List[Patch]:
217
235
  """Calculate patch based on changes to config.
218
236
 
@@ -221,11 +239,11 @@ def calc_config_patches(
221
239
  """
222
240
  try:
223
241
  config_patches = _calc_general_config_patches(prev_config, new_config)
224
- python_requirement_patches = _calc_python_requirements_patches(
225
- prev_config, new_config
242
+ python_requirements_patches = _calc_requirements_patches(
243
+ truss_dir, prev_signature, prev_config, new_config
226
244
  )
227
245
  system_package_patches = _calc_system_packages_patches(prev_config, new_config)
228
- return [*config_patches, *python_requirement_patches, *system_package_patches]
246
+ return [*config_patches, *python_requirements_patches, *system_package_patches]
229
247
  except Exception as e:
230
248
  logger.error(f"Failed to calculate config patch with exception: {e}")
231
249
  raise
@@ -273,10 +291,7 @@ def _calc_env_var_patches(
273
291
  removed_items = prev_item_names.difference(new_item_names)
274
292
  for removed_item in removed_items:
275
293
  patches.append(
276
- _mk_env_var_patch(
277
- Action.REMOVE,
278
- {removed_item: prev_items[removed_item]},
279
- )
294
+ _mk_env_var_patch(Action.REMOVE, {removed_item: prev_items[removed_item]})
280
295
  )
281
296
  added_items = new_item_names.difference(prev_item_names)
282
297
  for added_item in added_items:
@@ -302,41 +317,101 @@ def _calc_external_data_patches(
302
317
 
303
318
  removed_items = [x for x in prev_items if x not in new_items]
304
319
  for removed_item in removed_items:
305
- patches.append(
306
- _mk_external_data_patch(
307
- Action.REMOVE,
308
- removed_item,
309
- )
310
- )
320
+ patches.append(_mk_external_data_patch(Action.REMOVE, removed_item))
311
321
  added_items = [x for x in new_items if x not in prev_items]
312
322
  for added_item in added_items:
313
323
  patches.append(_mk_external_data_patch(Action.ADD, added_item))
314
324
  return patches
315
325
 
316
326
 
327
+ def _calc_requirements_patches(
328
+ truss_dir: Path,
329
+ prev_signature: TrussSignature,
330
+ prev_config: TrussConfig,
331
+ new_config: TrussConfig,
332
+ ) -> List[Patch]:
333
+ """
334
+ requirements patches that are accounted for
335
+ - contents in the requirements file change
336
+ - requirements move from config file to requirements file
337
+ - requirements move from requirements file to config file
338
+ - requirement file changes (i.e. requirement.txt --> requirements.txt)
339
+ - requirements in the config file change
340
+
341
+ assumes that only one of requirements or requirements_file is present for a given config
342
+ """
343
+ prev_requirements = (
344
+ prev_config.requirements
345
+ if not prev_config.requirements_file
346
+ else prev_signature.requirements_file_requirements
347
+ )
348
+ new_requirements = (
349
+ new_config.requirements
350
+ if not new_config.requirements_file
351
+ else new_config.load_requirements_from_file(truss_dir)
352
+ )
353
+ return _calc_python_requirements_patches(prev_requirements, new_requirements)
354
+
355
+
317
356
  def _calc_python_requirements_patches(
318
- prev_config: TrussConfig, new_config: TrussConfig
357
+ prev_raw_reqs: List[str], new_raw_reqs: List[str]
319
358
  ) -> List[Patch]:
320
359
  """Calculate patch based on changes to python requirements.
321
360
 
322
361
  Empty list means no relevant differences found.
323
362
  """
324
363
  patches = []
325
- prev_reqs = reqs_by_name(prev_config.requirements)
326
- prev_req_names = set(prev_reqs.keys())
327
- new_reqs = reqs_by_name(new_config.requirements)
328
- new_req_names = set(new_reqs.keys())
329
- removed_reqs = prev_req_names.difference(new_req_names)
330
- for removed_req in removed_reqs:
331
- patches.append(_mk_python_requirement_patch(Action.REMOVE, removed_req))
332
-
333
- added_reqs = new_req_names.difference(prev_req_names)
334
- for added_req in added_reqs:
335
- patches.append(_mk_python_requirement_patch(Action.ADD, new_reqs[added_req]))
336
-
337
- for req in new_req_names.intersection(prev_req_names):
338
- if new_reqs[req] != prev_reqs[req]:
339
- patches.append(_mk_python_requirement_patch(Action.UPDATE, new_reqs[req]))
364
+
365
+ def create_requirement_map(raw_reqs: List[str]) -> Dict[str, RequirementMeta]:
366
+ req_map = {}
367
+ for raw_req in raw_reqs:
368
+ meta = RequirementMeta.from_req(raw_req)
369
+ req_map[meta.name] = meta
370
+ return req_map
371
+
372
+ prev_reqs_map = create_requirement_map(prev_raw_reqs)
373
+ new_reqs_map = create_requirement_map(new_raw_reqs)
374
+ prev_req_names = set(prev_reqs_map.keys())
375
+ new_req_names = set(new_reqs_map.keys())
376
+
377
+ removed_req_names = prev_req_names.difference(new_req_names)
378
+ for removed_req_name in removed_req_names:
379
+ removed_req_meta = prev_reqs_map[removed_req_name]
380
+ if removed_req_meta.is_url_based_requirement:
381
+ if not removed_req_meta.egg_tag:
382
+ logger.warning(
383
+ f"Url-based requirement `{removed_req_meta.requirement}` is missing egg tag. Ignoring removal. Use `truss push` if you want to remove this requirement."
384
+ )
385
+ continue
386
+ # make sure that the egg tag is included when removing the requirement
387
+ patches.append(
388
+ _mk_python_requirement_patch(
389
+ Action.REMOVE, removed_req_meta.requirement
390
+ )
391
+ )
392
+ else:
393
+ patches.append(
394
+ _mk_python_requirement_patch(Action.REMOVE, removed_req_meta.name)
395
+ )
396
+
397
+ # warn for new reqs
398
+ added_req_names = new_req_names.difference(prev_req_names)
399
+ for added_req_name in added_req_names:
400
+ added_req_meta = new_reqs_map[added_req_name]
401
+ patches.append(
402
+ _mk_python_requirement_patch(Action.ADD, added_req_meta.requirement)
403
+ )
404
+ if added_req_meta.is_url_based_requirement and not added_req_meta.egg_tag:
405
+ logger.warning(
406
+ f"Url-based requirement `{added_req_meta.requirement}` is missing egg tag. Removal will be ignored by `truss watch`"
407
+ )
408
+ for req_name in new_req_names.intersection(prev_req_names):
409
+ if prev_reqs_map[req_name].requirement != new_reqs_map[req_name].requirement:
410
+ patches.append(
411
+ _mk_python_requirement_patch(
412
+ Action.UPDATE, new_reqs_map[req_name].requirement
413
+ )
414
+ )
340
415
 
341
416
  return patches
342
417
 
@@ -363,60 +438,39 @@ def _calc_system_packages_patches(
363
438
 
364
439
 
365
440
  def _mk_config_patch(action: Action, config: dict) -> Patch:
366
- return Patch(
367
- type=PatchType.CONFIG,
368
- body=ConfigPatch(
369
- action=action,
370
- config=config,
371
- ),
372
- )
441
+ return Patch(type=PatchType.CONFIG, body=ConfigPatch(action=action, config=config))
373
442
 
374
443
 
375
444
  # Support for patching data changes yet to be implemented
376
445
  def _mk_data_patch(action: Action, item: str, path: str) -> Patch:
377
446
  return Patch(
378
- type=PatchType.DATA,
379
- body=DataPatch(action=action, content=item, path=path),
447
+ type=PatchType.DATA, body=DataPatch(action=action, content=item, path=path)
380
448
  )
381
449
 
382
450
 
383
451
  def _mk_env_var_patch(action: Action, item: dict) -> Patch:
384
452
  return Patch(
385
- type=PatchType.ENVIRONMENT_VARIABLE,
386
- body=EnvVarPatch(
387
- action=action,
388
- item=item,
389
- ),
453
+ type=PatchType.ENVIRONMENT_VARIABLE, body=EnvVarPatch(action=action, item=item)
390
454
  )
391
455
 
392
456
 
393
457
  def _mk_external_data_patch(action: Action, item: Dict[str, str]) -> Patch:
394
458
  return Patch(
395
- type=PatchType.EXTERNAL_DATA,
396
- body=ExternalDataPatch(
397
- action=action,
398
- item=item,
399
- ),
459
+ type=PatchType.EXTERNAL_DATA, body=ExternalDataPatch(action=action, item=item)
400
460
  )
401
461
 
402
462
 
403
463
  def _mk_python_requirement_patch(action: Action, requirement: str) -> Patch:
404
464
  return Patch(
405
465
  type=PatchType.PYTHON_REQUIREMENT,
406
- body=PythonRequirementPatch(
407
- action=action,
408
- requirement=requirement,
409
- ),
466
+ body=PythonRequirementPatch(action=action, requirement=requirement),
410
467
  )
411
468
 
412
469
 
413
470
  def _mk_system_package_patch(action: Action, package: str) -> Patch:
414
471
  return Patch(
415
472
  type=PatchType.SYSTEM_PACKAGE,
416
- body=SystemPackagePatch(
417
- action=action,
418
- package=package,
419
- ),
473
+ body=SystemPackagePatch(action=action, package=package),
420
474
  )
421
475
 
422
476
 
@@ -1,42 +1,50 @@
1
- from dataclasses import dataclass
2
- from enum import Enum
3
- from typing import Any, Dict, List
1
+ from dataclasses import dataclass, field
2
+ from typing import Dict, List
4
3
 
5
4
  from pydantic import BaseModel
6
- from truss.patch.types import TrussSignature
7
- from truss.server.control.patch.types import Patch
8
5
 
9
-
10
- class ModelFrameworkType(Enum):
11
- SKLEARN = "sklearn"
12
- TENSORFLOW = "tensorflow"
13
- KERAS = "keras"
14
- PYTORCH = "pytorch"
15
- HUGGINGFACE_TRANSFORMER = "huggingface_transformer"
16
- XGBOOST = "xgboost"
17
- LIGHTGBM = "lightgbm"
18
- MLFLOW = "mlflow"
19
- CUSTOM = "custom"
6
+ from truss.templates.control.control.helpers.custom_types import Patch
7
+ from truss.util.requirements import parse_requirement_string
20
8
 
21
9
 
22
10
  @dataclass
23
- class Example:
24
- name: str
25
- input: Any
11
+ class TrussSignature:
12
+ """Truss signature stores information for calculating patches for future
13
+ changes to Truss.
26
14
 
27
- @staticmethod
28
- def from_dict(example_dict):
29
- return Example(
30
- name=example_dict["name"],
31
- input=example_dict["input"],
32
- )
15
+ Currently, it stores hashes of all of the paths in the truss directory excluding the data dir,
16
+ and the truss config contents. Path hashes allow calculating added/updated/removes
17
+ paths in future trusses compared to this. Config contents allow calculating
18
+ config changes, such as add/update/remove of python requirements etc.
19
+ """
20
+
21
+ content_hashes_by_path: Dict[str, str]
22
+ config: str
23
+ requirements_file_requirements: List[str] = field(default_factory=list)
33
24
 
34
25
  def to_dict(self) -> dict:
35
26
  return {
36
- "name": self.name,
37
- "input": self.input,
27
+ "content_hashes_by_path": self.content_hashes_by_path,
28
+ "config": self.config,
29
+ "requirements_file_requirements": self.requirements_file_requirements,
38
30
  }
39
31
 
32
+ @staticmethod
33
+ def from_dict(d) -> "TrussSignature":
34
+ requirements = []
35
+ for req in d.get("requirements_file_requirements", []):
36
+ parsed_req = parse_requirement_string(req)
37
+ if parsed_req:
38
+ requirements.append(parsed_req)
39
+ return TrussSignature(
40
+ content_hashes_by_path=d["content_hashes_by_path"],
41
+ config=d["config"],
42
+ requirements_file_requirements=requirements,
43
+ )
44
+
45
+
46
+ ChangedPaths = Dict[str, List[str]]
47
+
40
48
 
41
49
  @dataclass
42
50
  class PatchDetails:
@@ -1,7 +1,7 @@
1
1
  from pathlib import Path
2
2
  from typing import Dict, List, Optional
3
3
 
4
- from truss.patch.hash import file_content_hash_str
4
+ from truss.truss_handle.patch.hash import file_content_hash_str
5
5
  from truss.util.path import get_unignored_relative_paths_from_root
6
6
 
7
7
 
@@ -0,0 +1,71 @@
1
+ from pathlib import Path
2
+ from typing import Any, List, Optional
3
+
4
+ from blake3 import blake3
5
+
6
+ from truss.util.path import get_unignored_relative_paths_from_root
7
+
8
+
9
+ def directory_content_hash(
10
+ root: Path, ignore_patterns: Optional[List[str]] = None
11
+ ) -> str:
12
+ """Calculate content based hash of a filesystem directory.
13
+
14
+ Rough algo: Sort all files by path, then take hash of a content stream, where
15
+ we write path hash to the stream followed by hash of content if path is a file.
16
+ Note the hash of hash aspect.
17
+
18
+ Also, note that name of the root directory is not taken into account, only the contents
19
+ underneath. The (root) Directory will have the same hash, even if renamed.
20
+ """
21
+ hasher = blake3()
22
+ paths = list(get_unignored_relative_paths_from_root(root, ignore_patterns))
23
+ paths.sort()
24
+ for path in paths:
25
+ hasher.update(str_hash(str(path)))
26
+ absolute_path = root / path
27
+ if absolute_path.is_file():
28
+ hasher.update(file_content_hash(absolute_path))
29
+ return hasher.hexdigest()
30
+
31
+
32
+ def file_content_hash(file: Path) -> bytes:
33
+ """Calculate blake3 hash of file content.
34
+ Returns: binary hash of content
35
+ """
36
+ return _file_content_hash_loaded_hasher(file).digest()
37
+
38
+
39
+ def file_content_hash_str(file: Path) -> str:
40
+ """Calculate blake3 hash of file content.
41
+
42
+ Returns: string hash of content
43
+ """
44
+ return _file_content_hash_loaded_hasher(file).hexdigest()
45
+
46
+
47
+ def _file_content_hash_loaded_hasher(file: Path) -> Any:
48
+ hasher = blake3()
49
+ buffer = bytearray(128 * 1024)
50
+ mem_view = memoryview(buffer)
51
+ with file.open("rb") as f:
52
+ done = False
53
+ while not done:
54
+ n = f.readinto(mem_view)
55
+ if n > 0:
56
+ hasher.update(mem_view[:n])
57
+ else:
58
+ done = True
59
+ return hasher
60
+
61
+
62
+ def str_hash(content: str) -> bytes:
63
+ hasher = blake3()
64
+ hasher.update(content.encode("utf-8"))
65
+ return hasher.digest()
66
+
67
+
68
+ def str_hash_str(content: str) -> str:
69
+ hasher = blake3()
70
+ hasher.update(content.encode("utf-8"))
71
+ return hasher.hexdigest()
@@ -3,16 +3,18 @@ import subprocess
3
3
  from pathlib import Path
4
4
  from typing import List
5
5
 
6
- from truss.server.control.errors import UnsupportedPatch
7
- from truss.server.control.patch.model_code_patch_applier import apply_code_patch
8
- from truss.server.control.patch.types import (
6
+ from truss.base.truss_config import TrussConfig
7
+ from truss.templates.control.control.helpers.custom_types import (
9
8
  Action,
10
9
  ModelCodePatch,
11
10
  Patch,
12
11
  PythonRequirementPatch,
13
12
  SystemPackagePatch,
14
13
  )
15
- from truss.truss_config import TrussConfig
14
+ from truss.templates.control.control.helpers.errors import UnsupportedPatch
15
+ from truss.templates.control.control.helpers.truss_patch.model_code_patch_applier import (
16
+ apply_code_patch,
17
+ )
16
18
 
17
19
 
18
20
  class LocalTrussPatchApplier:
@@ -0,0 +1,22 @@
1
+ from pathlib import Path
2
+ from typing import List, Optional
3
+
4
+ from truss.base.constants import CONFIG_FILE
5
+ from truss.base.truss_config import TrussConfig
6
+ from truss.truss_handle.patch.custom_types import TrussSignature
7
+ from truss.truss_handle.patch.dir_signature import directory_content_signature
8
+
9
+
10
+ def calc_truss_signature(
11
+ truss_dir: Path, ignore_patterns: Optional[List[str]] = None
12
+ ) -> TrussSignature:
13
+ content_signature = directory_content_signature(truss_dir, ignore_patterns)
14
+ config_path = truss_dir / CONFIG_FILE
15
+ with (config_path).open("r") as config_file:
16
+ config = config_file.read()
17
+ requirements = TrussConfig.load_requirements_file_from_filepath(config_path)
18
+ return TrussSignature(
19
+ content_hashes_by_path=content_signature,
20
+ config=config,
21
+ requirements_file_requirements=requirements,
22
+ )