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
@@ -1,10 +1,11 @@
1
+ import os
1
2
  from pathlib import Path
2
3
  from typing import Any, Callable, List, Optional
3
4
 
5
+ import pytest
4
6
  import yaml
5
- from truss.patch.calc_patch import calc_truss_patch, calc_unignored_paths
6
- from truss.patch.signature import calc_truss_signature
7
- from truss.server.control.patch.types import (
7
+ from truss.base.truss_config import TrussConfig
8
+ from truss.templates.control.control.helpers.custom_types import (
8
9
  Action,
9
10
  ConfigPatch,
10
11
  EnvVarPatch,
@@ -16,8 +17,13 @@ from truss.server.control.patch.types import (
16
17
  PythonRequirementPatch,
17
18
  SystemPackagePatch,
18
19
  )
19
- from truss.truss_config import TrussConfig
20
- from truss.truss_handle import TrussHandle
20
+ from truss.truss_handle.patch.calc_patch import (
21
+ _calc_python_requirements_patches,
22
+ _calc_unignored_paths,
23
+ calc_truss_patch,
24
+ )
25
+ from truss.truss_handle.patch.signature import calc_truss_signature
26
+ from truss.truss_handle.truss_handle import TrussHandle
21
27
 
22
28
 
23
29
  def test_calc_truss_patch_unsupported(custom_model_truss_dir: Path):
@@ -45,11 +51,7 @@ def test_calc_truss_patch_add_file(custom_model_truss_dir: Path):
45
51
  patch = patches[0]
46
52
  assert patch == Patch(
47
53
  type=PatchType.MODEL_CODE,
48
- body=ModelCodePatch(
49
- action=Action.ADD,
50
- path="dummy",
51
- content="content",
52
- ),
54
+ body=ModelCodePatch(action=Action.ADD, path="dummy", content="content"),
53
55
  )
54
56
 
55
57
 
@@ -64,11 +66,7 @@ def test_calc_truss_patch_add_under_new_directory(custom_model_truss_dir: Path):
64
66
  patch = patches[0]
65
67
  assert patch == Patch(
66
68
  type=PatchType.MODEL_CODE,
67
- body=ModelCodePatch(
68
- action=Action.ADD,
69
- path="dir/dummy",
70
- content="",
71
- ),
69
+ body=ModelCodePatch(action=Action.ADD, path="dir/dummy", content=""),
72
70
  )
73
71
 
74
72
 
@@ -81,10 +79,7 @@ def test_calc_truss_patch_remove_file(custom_model_truss_dir: Path):
81
79
  patch = patches[0]
82
80
  assert patch == Patch(
83
81
  type=PatchType.MODEL_CODE,
84
- body=ModelCodePatch(
85
- action=Action.REMOVE,
86
- path="model.py",
87
- ),
82
+ body=ModelCodePatch(action=Action.REMOVE, path="model.py"),
88
83
  )
89
84
 
90
85
 
@@ -118,10 +113,7 @@ def test_calc_truss_ignore_pycache(custom_model_truss_dir: Path):
118
113
  model_pycache_path.mkdir()
119
114
  (model_pycache_path / "foo.pyo").touch()
120
115
 
121
- patches = calc_truss_patch(
122
- custom_model_truss_dir,
123
- prev_sign,
124
- )
116
+ patches = calc_truss_patch(custom_model_truss_dir, prev_sign)
125
117
  assert len(patches) == 0
126
118
 
127
119
 
@@ -135,10 +127,7 @@ def test_calc_truss_ignore_pycache_existing(custom_model_truss_dir: Path):
135
127
  model_pycache_path.mkdir()
136
128
  (model_pycache_path / "foo.pyo").touch()
137
129
  sign = calc_truss_signature(custom_model_truss_dir)
138
- patches = calc_truss_patch(
139
- custom_model_truss_dir,
140
- sign,
141
- )
130
+ patches = calc_truss_patch(custom_model_truss_dir, sign)
142
131
  assert len(patches) == 0
143
132
 
144
133
 
@@ -153,19 +142,13 @@ def test_calc_truss_ignore_changes_outside_patch_relevant_dirs(
153
142
  git_dir.mkdir()
154
143
  (git_dir / "dummy").touch()
155
144
 
156
- patches = calc_truss_patch(
157
- custom_model_truss_dir,
158
- prev_sign,
159
- )
145
+ patches = calc_truss_patch(custom_model_truss_dir, prev_sign)
160
146
  assert len(patches) == 0
161
147
 
162
148
  # Removing should also be ignored
163
149
  new_sign = calc_truss_signature(custom_model_truss_dir)
164
150
  (git_dir / "dummy").unlink()
165
- patches = calc_truss_patch(
166
- custom_model_truss_dir,
167
- new_sign,
168
- )
151
+ patches = calc_truss_patch(custom_model_truss_dir, new_sign)
169
152
  assert len(patches) == 0
170
153
 
171
154
 
@@ -186,8 +169,7 @@ def test_calc_config_patches_add_python_requirement(custom_model_truss_dir: Path
186
169
  Patch(
187
170
  type=PatchType.PYTHON_REQUIREMENT,
188
171
  body=PythonRequirementPatch(
189
- action=Action.ADD,
190
- requirement="requests==1.0.0",
172
+ action=Action.ADD, requirement="requests==1.0.0"
191
173
  ),
192
174
  ),
193
175
  ]
@@ -204,11 +186,7 @@ def test_calc_truss_patch_add_package(custom_model_truss_dir: Path):
204
186
  patch = patches[0]
205
187
  assert patch == Patch(
206
188
  type=PatchType.PACKAGE,
207
- body=PackagePatch(
208
- action=Action.ADD,
209
- path="dir/dummy",
210
- content="",
211
- ),
189
+ body=PackagePatch(action=Action.ADD, path="dir/dummy", content=""),
212
190
  )
213
191
 
214
192
 
@@ -228,10 +206,7 @@ def test_calc_truss_patch_remove_package(
228
206
  patch = patches[0]
229
207
  assert patch == Patch(
230
208
  type=PatchType.PACKAGE,
231
- body=PackagePatch(
232
- action=Action.REMOVE,
233
- path="test_package/test.py",
234
- ),
209
+ body=PackagePatch(action=Action.REMOVE, path="test_package/test.py"),
235
210
  )
236
211
 
237
212
 
@@ -262,6 +237,267 @@ def test_calc_truss_patch_update_package(
262
237
  )
263
238
 
264
239
 
240
+ def test_calc_truss_patch_handles_requirements_file_name_change(
241
+ custom_model_truss_dir: Path,
242
+ ):
243
+ requirements_contents = """xformers"""
244
+
245
+ def pre_config_op(config: TrussConfig):
246
+ filename = "requirement.txt"
247
+ config.requirements.clear()
248
+ config.requirements_file = filename
249
+ with (custom_model_truss_dir / filename).open("w") as req_file:
250
+ req_file.write(requirements_contents)
251
+
252
+ def config_op(config: TrussConfig):
253
+ filename = "requirements.txt"
254
+ with (custom_model_truss_dir / filename).open("w") as req_file:
255
+ req_file.write(requirements_contents)
256
+ config.requirements_file = filename
257
+ config.requirements.clear()
258
+
259
+ patches = _apply_config_change_and_calc_patches(
260
+ custom_model_truss_dir, config_op=config_op, config_pre_op=pre_config_op
261
+ )
262
+ assert len(patches) == 1
263
+ assert patches == [
264
+ Patch(
265
+ type=PatchType.CONFIG,
266
+ body=ConfigPatch(
267
+ action=Action.UPDATE,
268
+ config=yaml.safe_load((custom_model_truss_dir / "config.yaml").open()),
269
+ ),
270
+ )
271
+ ]
272
+
273
+
274
+ def test_calc_truss_patch_handles_requirements_comments(custom_model_truss_dir: Path):
275
+ def pre_config_op(config: TrussConfig):
276
+ requirements_contents = """xformers\n#torch==2.0.1"""
277
+ filename = "./requirements.txt"
278
+ config.requirements_file = filename
279
+ with (custom_model_truss_dir / filename).open("w") as req_file:
280
+ req_file.write(requirements_contents)
281
+
282
+ def config_op(config: TrussConfig):
283
+ requirements_contents = """#xformers\ntorch==2.3.1\n"""
284
+ filename = "requirements.txt"
285
+ with (custom_model_truss_dir / filename).open("w") as req_file:
286
+ req_file.write(requirements_contents)
287
+
288
+ patches = _apply_config_change_and_calc_patches(
289
+ custom_model_truss_dir, config_op=config_op, config_pre_op=pre_config_op
290
+ )
291
+ assert len(patches) == 2
292
+ assert patches == [
293
+ Patch(
294
+ type=PatchType.PYTHON_REQUIREMENT,
295
+ body=PythonRequirementPatch(action=Action.REMOVE, requirement="xformers"),
296
+ ),
297
+ Patch(
298
+ type=PatchType.PYTHON_REQUIREMENT,
299
+ body=PythonRequirementPatch(action=Action.ADD, requirement="torch==2.3.1"),
300
+ ),
301
+ ]
302
+
303
+
304
+ def test_calc_truss_patch_handles_requirements_file_changes(
305
+ custom_model_truss_dir: Path,
306
+ ):
307
+ def pre_config_op(config: TrussConfig):
308
+ requirements_contents = """xformers\ntorch==2.0.1"""
309
+ filename = "./requirements.txt"
310
+ config.requirements_file = filename
311
+ with (custom_model_truss_dir / filename).open("w") as req_file:
312
+ req_file.write(requirements_contents)
313
+
314
+ def config_op(config: TrussConfig):
315
+ requirements_contents = """requests\ntorch==2.3.1\n"""
316
+ filename = "requirements.txt"
317
+ with (custom_model_truss_dir / filename).open("w") as req_file:
318
+ req_file.write(requirements_contents)
319
+
320
+ patches = _apply_config_change_and_calc_patches(
321
+ custom_model_truss_dir, config_op=config_op, config_pre_op=pre_config_op
322
+ )
323
+ assert len(patches) == 3
324
+ assert patches == [
325
+ # In this case, a Config Update patch is not issued. This does not cause issues on the backend
326
+ Patch(
327
+ type=PatchType.PYTHON_REQUIREMENT,
328
+ body=PythonRequirementPatch(action=Action.REMOVE, requirement="xformers"),
329
+ ),
330
+ Patch(
331
+ type=PatchType.PYTHON_REQUIREMENT,
332
+ body=PythonRequirementPatch(action=Action.ADD, requirement="requests"),
333
+ ),
334
+ Patch(
335
+ type=PatchType.PYTHON_REQUIREMENT,
336
+ body=PythonRequirementPatch(
337
+ action=Action.UPDATE, requirement="torch==2.3.1"
338
+ ),
339
+ ),
340
+ ]
341
+
342
+
343
+ def test_calc_truss_patch_handles_requirements_file_changes_and_config_changes(
344
+ custom_model_truss_dir: Path,
345
+ ):
346
+ def pre_config_op(config: TrussConfig):
347
+ requirements_contents = """xformers\ntorch==2.0.1"""
348
+ filename = "./requirements.txt"
349
+ config.requirements_file = filename
350
+ with (custom_model_truss_dir / filename).open("w") as req_file:
351
+ req_file.write(requirements_contents)
352
+
353
+ def config_op(config: TrussConfig):
354
+ requirements_contents = """requests\ntorch==2.3.1"""
355
+ filename = "requirement.txt"
356
+ with (custom_model_truss_dir / filename).open("w") as req_file:
357
+ req_file.write(requirements_contents)
358
+ config.requirements_file = filename
359
+
360
+ patches = _apply_config_change_and_calc_patches(
361
+ custom_model_truss_dir, config_op=config_op, config_pre_op=pre_config_op
362
+ )
363
+ assert len(patches) == 4
364
+ assert patches == [
365
+ Patch(
366
+ type=PatchType.CONFIG,
367
+ body=ConfigPatch(
368
+ action=Action.UPDATE,
369
+ config=yaml.safe_load((custom_model_truss_dir / "config.yaml").open()),
370
+ ),
371
+ ),
372
+ Patch(
373
+ type=PatchType.PYTHON_REQUIREMENT,
374
+ body=PythonRequirementPatch(action=Action.REMOVE, requirement="xformers"),
375
+ ),
376
+ Patch(
377
+ type=PatchType.PYTHON_REQUIREMENT,
378
+ body=PythonRequirementPatch(action=Action.ADD, requirement="requests"),
379
+ ),
380
+ Patch(
381
+ type=PatchType.PYTHON_REQUIREMENT,
382
+ body=PythonRequirementPatch(
383
+ action=Action.UPDATE, requirement="torch==2.3.1"
384
+ ),
385
+ ),
386
+ ]
387
+
388
+
389
+ def test_calc_truss_patch_handles_requirements_file_removal(
390
+ custom_model_truss_dir: Path,
391
+ ):
392
+ requirements_contents = """xformers"""
393
+ filename = "requirements.txt"
394
+
395
+ def pre_config_op(config: TrussConfig):
396
+ with (custom_model_truss_dir / filename).open("w") as req_file:
397
+ req_file.write(requirements_contents)
398
+ config.requirements_file = filename
399
+ config.requirements.clear()
400
+
401
+ def config_op(config: TrussConfig):
402
+ requirements_contents = ["xformers", "requests"]
403
+ config.requirements.extend(requirements_contents)
404
+ config.requirements_file = ""
405
+ os.remove(custom_model_truss_dir / filename)
406
+
407
+ patches = _apply_config_change_and_calc_patches(
408
+ custom_model_truss_dir, config_op=config_op, config_pre_op=pre_config_op
409
+ )
410
+ assert len(patches) == 2
411
+ assert patches == [
412
+ Patch(
413
+ type=PatchType.CONFIG,
414
+ body=ConfigPatch(
415
+ action=Action.UPDATE,
416
+ config=yaml.safe_load((custom_model_truss_dir / "config.yaml").open()),
417
+ ),
418
+ ),
419
+ Patch(
420
+ type=PatchType.PYTHON_REQUIREMENT,
421
+ body=PythonRequirementPatch(action=Action.ADD, requirement="requests"),
422
+ ),
423
+ ]
424
+
425
+
426
+ def test_calc_truss_signature_raises_for_invalid_requirements_file(
427
+ custom_model_truss_dir: Path,
428
+ ):
429
+ config_path = custom_model_truss_dir / "config.yaml"
430
+ config = TrussConfig.from_yaml(config_path)
431
+ config.requirements.clear()
432
+ config.requirements_file = "no_exist.txt"
433
+ config.write_to_yaml_file(config_path)
434
+
435
+ with pytest.raises(FileNotFoundError):
436
+ calc_truss_signature(custom_model_truss_dir)
437
+
438
+
439
+ def test_calc_truss_patch_handles_requirements_file_added_no_change(
440
+ custom_model_truss_dir: Path,
441
+ ):
442
+ requirements_contents = """xformers"""
443
+
444
+ def pre_config_op(config: TrussConfig):
445
+ config.requirements.append(requirements_contents)
446
+
447
+ def config_op(config: TrussConfig):
448
+ filename = "requirements.txt"
449
+ with (custom_model_truss_dir / filename).open("w") as req_file:
450
+ req_file.write(requirements_contents)
451
+ config.requirements_file = filename
452
+ config.requirements.clear()
453
+
454
+ patches = _apply_config_change_and_calc_patches(
455
+ custom_model_truss_dir, config_op=config_op, config_pre_op=pre_config_op
456
+ )
457
+ assert len(patches) == 1
458
+ assert patches == [
459
+ Patch(
460
+ type=PatchType.CONFIG,
461
+ body=ConfigPatch(
462
+ action=Action.UPDATE,
463
+ config=yaml.safe_load((custom_model_truss_dir / "config.yaml").open()),
464
+ ),
465
+ )
466
+ ]
467
+
468
+
469
+ def test_calc_truss_patch_handles_requirements_file_added_with_changes(
470
+ custom_model_truss_dir: Path,
471
+ ):
472
+ requirements_contents = """xformers"""
473
+
474
+ def config_op(config: TrussConfig):
475
+ filename = "requirements.txt"
476
+ with (custom_model_truss_dir / filename).open("w") as req_file:
477
+ req_file.write(requirements_contents)
478
+ config.requirements_file = filename
479
+ config.requirements.clear()
480
+
481
+ patches = _apply_config_change_and_calc_patches(
482
+ custom_model_truss_dir, config_op=config_op
483
+ )
484
+
485
+ assert len(patches) == 2
486
+ assert patches == [
487
+ Patch(
488
+ type=PatchType.CONFIG,
489
+ body=ConfigPatch(
490
+ action=Action.UPDATE,
491
+ config=yaml.safe_load((custom_model_truss_dir / "config.yaml").open()),
492
+ ),
493
+ ),
494
+ Patch(
495
+ type=PatchType.PYTHON_REQUIREMENT,
496
+ body=PythonRequirementPatch(action=Action.ADD, requirement="xformers"),
497
+ ),
498
+ ]
499
+
500
+
265
501
  def test_calc_config_patches_remove_python_requirement(custom_model_truss_dir: Path):
266
502
  patches = _apply_config_change_and_calc_patches(
267
503
  custom_model_truss_dir,
@@ -279,10 +515,7 @@ def test_calc_config_patches_remove_python_requirement(custom_model_truss_dir: P
279
515
  ),
280
516
  Patch(
281
517
  type=PatchType.PYTHON_REQUIREMENT,
282
- body=PythonRequirementPatch(
283
- action=Action.REMOVE,
284
- requirement="requests",
285
- ),
518
+ body=PythonRequirementPatch(action=Action.REMOVE, requirement="requests"),
286
519
  ),
287
520
  ]
288
521
 
@@ -297,6 +530,39 @@ def test_calc_config_patches_update_python_requirement(custom_model_truss_dir: P
297
530
  config_op=update_requests_version,
298
531
  )
299
532
  assert len(patches) == 2
533
+ assert patches == [
534
+ Patch(
535
+ type=PatchType.CONFIG,
536
+ body=ConfigPatch(
537
+ action=Action.UPDATE,
538
+ config=yaml.safe_load((custom_model_truss_dir / "config.yaml").open()),
539
+ ),
540
+ ),
541
+ Patch(
542
+ type=PatchType.PYTHON_REQUIREMENT,
543
+ body=PythonRequirementPatch(
544
+ action=Action.UPDATE, requirement="requests==2.0.0"
545
+ ),
546
+ ),
547
+ ]
548
+
549
+
550
+ def test_calc_config_patches_update_python_url_requirement_with_egg_tag(
551
+ custom_model_truss_dir: Path,
552
+ ):
553
+ def update_requests_version(config: TrussConfig):
554
+ config.requirements[0] = (
555
+ "git+https://github.com/huggingface/transformers.git#egg=transformers"
556
+ )
557
+
558
+ patches = _apply_config_change_and_calc_patches(
559
+ custom_model_truss_dir,
560
+ config_pre_op=lambda config: config.requirements.append(
561
+ "git+https://github.com/huggingface/transformers.git"
562
+ ),
563
+ config_op=update_requests_version,
564
+ )
565
+ assert len(patches) == 2
300
566
  assert patches == [
301
567
  Patch(
302
568
  type=PatchType.CONFIG,
@@ -309,33 +575,91 @@ def test_calc_config_patches_update_python_requirement(custom_model_truss_dir: P
309
575
  type=PatchType.PYTHON_REQUIREMENT,
310
576
  body=PythonRequirementPatch(
311
577
  action=Action.UPDATE,
312
- requirement="requests==2.0.0",
578
+ requirement="git+https://github.com/huggingface/transformers.git#egg=transformers",
313
579
  ),
314
580
  ),
315
581
  ]
316
582
 
317
583
 
318
- def test_calc_config_patches_add_remove_and_update_python_requirement(
584
+ def test_calc_config_patches_update_python_url_requirement_with_revision_tag(
585
+ custom_model_truss_dir: Path,
586
+ ):
587
+ def update_requests_version(config: TrussConfig):
588
+ config.requirements[0] = (
589
+ "git+https://github.com/huggingface/transformers.git@111111"
590
+ )
591
+
592
+ patches = _apply_config_change_and_calc_patches(
593
+ custom_model_truss_dir,
594
+ config_pre_op=lambda config: config.requirements.append(
595
+ "git+https://github.com/huggingface/transformers.git@000000"
596
+ ),
597
+ config_op=update_requests_version,
598
+ )
599
+ assert len(patches) == 2
600
+ assert patches == [
601
+ Patch(
602
+ type=PatchType.CONFIG,
603
+ body=ConfigPatch(
604
+ action=Action.UPDATE,
605
+ config=yaml.safe_load((custom_model_truss_dir / "config.yaml").open()),
606
+ ),
607
+ ),
608
+ Patch(
609
+ type=PatchType.PYTHON_REQUIREMENT,
610
+ body=PythonRequirementPatch(
611
+ action=Action.UPDATE,
612
+ requirement="git+https://github.com/huggingface/transformers.git@111111",
613
+ ),
614
+ ),
615
+ ]
616
+
617
+
618
+ def test_calc_config_patches_ignores_removal_of_url_based_requirements_without_egg_tag(
319
619
  custom_model_truss_dir: Path,
320
620
  ):
321
621
  def config_pre_op(config: TrussConfig):
322
622
  config.requirements = [
323
623
  "requests==1.0.0",
324
- "jinja==4.0.0",
624
+ "git+https://github.com/huggingface/transformers.git@111111",
325
625
  ]
326
626
 
327
627
  def config_op(config: TrussConfig):
628
+ config.requirements = ["requests==1.0.0"]
629
+
630
+ patches = _apply_config_change_and_calc_patches(
631
+ custom_model_truss_dir, config_pre_op=config_pre_op, config_op=config_op
632
+ )
633
+ assert len(patches) == 1
634
+ assert patches[0] == Patch(
635
+ type=PatchType.CONFIG,
636
+ body=ConfigPatch(
637
+ action=Action.UPDATE,
638
+ config=yaml.safe_load((custom_model_truss_dir / "config.yaml").open()),
639
+ ),
640
+ )
641
+ patches = patches[1:]
642
+ patches.sort(key=lambda patch: patch.body.requirement)
643
+ assert patches == []
644
+
645
+
646
+ def test_calc_config_patches_add_remove_and_update_python_requirement(
647
+ custom_model_truss_dir: Path,
648
+ ):
649
+ def config_pre_op(config: TrussConfig):
328
650
  config.requirements = [
329
- "requests==2.0.0",
330
- "numpy>=1.8",
651
+ "requests==1.0.0",
652
+ "jinja==4.0.0",
653
+ "git+https://github.com/huggingface/transformers.git@111111#egg=transformers",
331
654
  ]
332
655
 
656
+ def config_op(config: TrussConfig):
657
+ config.requirements = ["requests==2.0.0", "numpy>=1.8"]
658
+
333
659
  patches = _apply_config_change_and_calc_patches(
334
- custom_model_truss_dir,
335
- config_pre_op=config_pre_op,
336
- config_op=config_op,
660
+ custom_model_truss_dir, config_pre_op=config_pre_op, config_op=config_op
337
661
  )
338
- assert len(patches) == 4
662
+ assert len(patches) == 5
339
663
  assert patches[0] == Patch(
340
664
  type=PatchType.CONFIG,
341
665
  body=ConfigPatch(
@@ -350,29 +674,27 @@ def test_calc_config_patches_add_remove_and_update_python_requirement(
350
674
  type=PatchType.PYTHON_REQUIREMENT,
351
675
  body=PythonRequirementPatch(
352
676
  action=Action.REMOVE,
353
- requirement="jinja",
677
+ requirement="git+https://github.com/huggingface/transformers.git@111111#egg=transformers",
354
678
  ),
355
679
  ),
356
680
  Patch(
357
681
  type=PatchType.PYTHON_REQUIREMENT,
358
- body=PythonRequirementPatch(
359
- action=Action.ADD,
360
- requirement="numpy>=1.8",
361
- ),
682
+ body=PythonRequirementPatch(action=Action.REMOVE, requirement="jinja"),
683
+ ),
684
+ Patch(
685
+ type=PatchType.PYTHON_REQUIREMENT,
686
+ body=PythonRequirementPatch(action=Action.ADD, requirement="numpy>=1.8"),
362
687
  ),
363
688
  Patch(
364
689
  type=PatchType.PYTHON_REQUIREMENT,
365
690
  body=PythonRequirementPatch(
366
- action=Action.UPDATE,
367
- requirement="requests==2.0.0",
691
+ action=Action.UPDATE, requirement="requests==2.0.0"
368
692
  ),
369
693
  ),
370
694
  ]
371
695
 
372
696
 
373
- def test_calc_config_patches_add_env_var(
374
- custom_model_truss_dir: Path,
375
- ):
697
+ def test_calc_config_patches_add_env_var(custom_model_truss_dir: Path):
376
698
  patches = _apply_config_change_and_calc_patches(
377
699
  custom_model_truss_dir,
378
700
  config_op=lambda config: config.environment_variables.update({"foo": "bar"}),
@@ -388,17 +710,12 @@ def test_calc_config_patches_add_env_var(
388
710
  ),
389
711
  Patch(
390
712
  type=PatchType.ENVIRONMENT_VARIABLE,
391
- body=EnvVarPatch(
392
- action=Action.ADD,
393
- item={"foo": "bar"},
394
- ),
713
+ body=EnvVarPatch(action=Action.ADD, item={"foo": "bar"}),
395
714
  ),
396
715
  ]
397
716
 
398
717
 
399
- def test_calc_config_patches_add_remove_env_var(
400
- custom_model_truss_dir: Path,
401
- ):
718
+ def test_calc_config_patches_add_remove_env_var(custom_model_truss_dir: Path):
402
719
  patches = _apply_config_change_and_calc_patches(
403
720
  custom_model_truss_dir,
404
721
  config_pre_op=lambda config: config.environment_variables.update(
@@ -417,18 +734,14 @@ def test_calc_config_patches_add_remove_env_var(
417
734
  ),
418
735
  Patch(
419
736
  type=PatchType.ENVIRONMENT_VARIABLE,
420
- body=EnvVarPatch(
421
- action=Action.REMOVE,
422
- item={"foo": "bar"},
423
- ),
737
+ body=EnvVarPatch(action=Action.REMOVE, item={"foo": "bar"}),
424
738
  ),
425
739
  ]
426
740
 
427
741
 
428
742
  def test_calc_config_patches_add_system_package(custom_model_truss_dir: Path):
429
743
  patches = _apply_config_change_and_calc_patches(
430
- custom_model_truss_dir,
431
- lambda config: config.system_packages.append("curl"),
744
+ custom_model_truss_dir, lambda config: config.system_packages.append("curl")
432
745
  )
433
746
  assert len(patches) == 2
434
747
  assert patches == [
@@ -441,10 +754,7 @@ def test_calc_config_patches_add_system_package(custom_model_truss_dir: Path):
441
754
  ),
442
755
  Patch(
443
756
  type=PatchType.SYSTEM_PACKAGE,
444
- body=SystemPackagePatch(
445
- action=Action.ADD,
446
- package="curl",
447
- ),
757
+ body=SystemPackagePatch(action=Action.ADD, package="curl"),
448
758
  ),
449
759
  ]
450
760
 
@@ -466,10 +776,7 @@ def test_calc_config_patches_remove_system_package(custom_model_truss_dir: Path)
466
776
  ),
467
777
  Patch(
468
778
  type=PatchType.SYSTEM_PACKAGE,
469
- body=SystemPackagePatch(
470
- action=Action.REMOVE,
471
- package="curl",
472
- ),
779
+ body=SystemPackagePatch(action=Action.REMOVE, package="curl"),
473
780
  ),
474
781
  ]
475
782
 
@@ -478,21 +785,13 @@ def test_calc_config_patches_add_and_remove_system_package(
478
785
  custom_model_truss_dir: Path,
479
786
  ):
480
787
  def config_pre_op(config: TrussConfig):
481
- config.system_packages = [
482
- "curl",
483
- "jq",
484
- ]
788
+ config.system_packages = ["curl", "jq"]
485
789
 
486
790
  def config_op(config: TrussConfig):
487
- config.system_packages = [
488
- "curl",
489
- "libsnd",
490
- ]
791
+ config.system_packages = ["curl", "libsnd"]
491
792
 
492
793
  patches = _apply_config_change_and_calc_patches(
493
- custom_model_truss_dir,
494
- config_pre_op=config_pre_op,
495
- config_op=config_op,
794
+ custom_model_truss_dir, config_pre_op=config_pre_op, config_op=config_op
496
795
  )
497
796
  assert len(patches) == 3
498
797
  assert patches[0] == Patch(
@@ -507,17 +806,11 @@ def test_calc_config_patches_add_and_remove_system_package(
507
806
  assert patches == [
508
807
  Patch(
509
808
  type=PatchType.SYSTEM_PACKAGE,
510
- body=SystemPackagePatch(
511
- action=Action.REMOVE,
512
- package="jq",
513
- ),
809
+ body=SystemPackagePatch(action=Action.REMOVE, package="jq"),
514
810
  ),
515
811
  Patch(
516
812
  type=PatchType.SYSTEM_PACKAGE,
517
- body=SystemPackagePatch(
518
- action=Action.ADD,
519
- package="libsnd",
520
- ),
813
+ body=SystemPackagePatch(action=Action.ADD, package="libsnd"),
521
814
  ),
522
815
  ]
523
816
 
@@ -552,9 +845,7 @@ def test_calc_config_patches_add_external_data(
552
845
  config.external_data = None
553
846
 
554
847
  patches = _apply_config_change_and_calc_patches(
555
- path,
556
- config_pre_op=config_pre_op,
557
- config_op=config_op,
848
+ path, config_pre_op=config_pre_op, config_op=config_op
558
849
  )
559
850
  assert len(patches) == 2
560
851
 
@@ -583,10 +874,7 @@ def test_calc_config_patches_remove_external_data(
583
874
  def config_op(config: TrussConfig):
584
875
  config.external_data = None
585
876
 
586
- patches = _apply_config_change_and_calc_patches(
587
- path,
588
- config_op=config_op,
589
- )
877
+ patches = _apply_config_change_and_calc_patches(path, config_op=config_op)
590
878
  assert len(patches) == 2
591
879
  assert patches == [
592
880
  Patch(
@@ -606,11 +894,7 @@ def test_calc_config_patches_remove_external_data(
606
894
 
607
895
 
608
896
  def test_calc_unignored_paths():
609
- ignore_patterns = [
610
- ".mypy_cache/",
611
- "venv/",
612
- "*.tmp",
613
- ]
897
+ ignore_patterns = [".mypy_cache/", "venv/", "*.tmp"]
614
898
 
615
899
  root_relative_paths = {
616
900
  ".mypy_cache/should_ignore.json",
@@ -620,18 +904,15 @@ def test_calc_unignored_paths():
620
904
  "model/model.py",
621
905
  }
622
906
 
623
- unignored_paths = calc_unignored_paths(root_relative_paths, ignore_patterns)
624
- assert unignored_paths == {
625
- "config.yaml",
626
- "model/model.py",
627
- }
907
+ unignored_paths = _calc_unignored_paths(root_relative_paths, ignore_patterns)
908
+ assert unignored_paths == {"config.yaml", "model/model.py"}
628
909
 
629
910
 
630
911
  def _apply_config_change_and_calc_patches(
631
912
  custom_model_truss_dir: Path,
632
913
  config_op: Callable[[TrussConfig], Any],
633
914
  config_pre_op: Optional[Callable[[TrussConfig], Any]] = None,
634
- ) -> Optional[List[Patch]]:
915
+ ) -> List[Patch]:
635
916
  def modify_config(op):
636
917
  config_path = custom_model_truss_dir / "config.yaml"
637
918
  config = TrussConfig.from_yaml(config_path)
@@ -644,3 +925,34 @@ def _apply_config_change_and_calc_patches(
644
925
  prev_sign = calc_truss_signature(custom_model_truss_dir)
645
926
  modify_config(config_op)
646
927
  return calc_truss_patch(custom_model_truss_dir, prev_sign)
928
+
929
+
930
+ @pytest.mark.parametrize(
931
+ "desc, prev_raw_reqs, new_raw_reqs, expected_patches",
932
+ [
933
+ (
934
+ "handles single update",
935
+ ["requests==1.0.0"],
936
+ ["requests==2.0.0"],
937
+ [
938
+ Patch(
939
+ type=PatchType.PYTHON_REQUIREMENT,
940
+ body=PythonRequirementPatch(
941
+ action=Action.UPDATE, requirement="requests==2.0.0"
942
+ ),
943
+ )
944
+ ],
945
+ ),
946
+ (
947
+ "ignores url-based requirement without egg tag",
948
+ ["git+https://github.com/huggingface/transformers.git@000000"],
949
+ [],
950
+ [],
951
+ ),
952
+ ],
953
+ )
954
+ def test_calc_python_requirements_patches(
955
+ desc, prev_raw_reqs, new_raw_reqs, expected_patches
956
+ ):
957
+ actual = _calc_python_requirements_patches(prev_raw_reqs, new_raw_reqs)
958
+ assert actual == expected_patches, desc