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.
- truss/__init__.py +10 -3
- truss/api/__init__.py +123 -0
- truss/api/definitions.py +51 -0
- truss/base/constants.py +116 -0
- truss/base/custom_types.py +29 -0
- truss/{errors.py → base/errors.py} +4 -0
- truss/base/trt_llm_config.py +310 -0
- truss/{truss_config.py → base/truss_config.py} +344 -31
- truss/{truss_spec.py → base/truss_spec.py} +20 -6
- truss/{validation.py → base/validation.py} +60 -11
- truss/cli/cli.py +841 -88
- truss/{remote → cli}/remote_cli.py +2 -7
- truss/contexts/docker_build_setup.py +67 -0
- truss/contexts/image_builder/cache_warmer.py +2 -8
- truss/contexts/image_builder/image_builder.py +1 -1
- truss/contexts/image_builder/serving_image_builder.py +292 -46
- truss/contexts/image_builder/util.py +1 -3
- truss/contexts/local_loader/docker_build_emulator.py +58 -0
- truss/contexts/local_loader/load_model_local.py +2 -2
- truss/contexts/local_loader/truss_module_loader.py +1 -1
- truss/contexts/local_loader/utils.py +1 -1
- truss/local/local_config.py +2 -6
- truss/local/local_config_handler.py +20 -5
- truss/patch/__init__.py +1 -0
- truss/patch/hash.py +4 -70
- truss/patch/signature.py +4 -16
- truss/patch/truss_dir_patch_applier.py +3 -78
- truss/remote/baseten/api.py +308 -23
- truss/remote/baseten/auth.py +3 -3
- truss/remote/baseten/core.py +257 -50
- truss/remote/baseten/custom_types.py +44 -0
- truss/remote/baseten/error.py +4 -0
- truss/remote/baseten/remote.py +369 -118
- truss/remote/baseten/service.py +118 -11
- truss/remote/baseten/utils/status.py +29 -0
- truss/remote/baseten/utils/tar.py +34 -22
- truss/remote/baseten/utils/transfer.py +36 -23
- truss/remote/remote_factory.py +14 -5
- truss/remote/truss_remote.py +72 -45
- truss/templates/base.Dockerfile.jinja +18 -16
- truss/templates/cache.Dockerfile.jinja +3 -3
- truss/{server → templates/control}/control/application.py +14 -35
- truss/{server → templates/control}/control/endpoints.py +39 -9
- truss/{server/control/patch/types.py → templates/control/control/helpers/custom_types.py} +13 -52
- truss/{server → templates/control}/control/helpers/inference_server_controller.py +4 -8
- truss/{server → templates/control}/control/helpers/inference_server_process_controller.py +2 -4
- truss/{server → templates/control}/control/helpers/inference_server_starter.py +5 -10
- truss/{server/control → templates/control/control/helpers}/truss_patch/model_code_patch_applier.py +8 -6
- truss/{server/control/patch → templates/control/control/helpers/truss_patch}/model_container_patch_applier.py +18 -26
- truss/templates/control/control/helpers/truss_patch/requirement_name_identifier.py +66 -0
- truss/{server → templates/control}/control/server.py +11 -6
- truss/templates/control/requirements.txt +9 -0
- truss/templates/custom_python_dx/my_model.py +28 -0
- truss/templates/docker_server/proxy.conf.jinja +42 -0
- truss/templates/docker_server/supervisord.conf.jinja +27 -0
- truss/templates/docker_server_requirements.txt +1 -0
- truss/templates/server/common/errors.py +231 -0
- truss/{server → templates/server}/common/patches/whisper/patch.py +1 -0
- truss/{server/common/patches/__init__.py → templates/server/common/patches.py} +1 -3
- truss/{server → templates/server}/common/retry.py +1 -0
- truss/{server → templates/server}/common/schema.py +11 -9
- truss/templates/server/common/tracing.py +157 -0
- truss/templates/server/main.py +9 -0
- truss/templates/server/model_wrapper.py +961 -0
- truss/templates/server/requirements.txt +21 -0
- truss/templates/server/truss_server.py +447 -0
- truss/templates/server.Dockerfile.jinja +62 -14
- truss/templates/shared/dynamic_config_resolver.py +28 -0
- truss/templates/shared/lazy_data_resolver.py +164 -0
- truss/templates/shared/log_config.py +125 -0
- truss/{server → templates}/shared/secrets_resolver.py +1 -2
- truss/{server → templates}/shared/serialization.py +31 -9
- truss/{server → templates}/shared/util.py +3 -13
- truss/templates/trtllm-audio/model/model.py +49 -0
- truss/templates/trtllm-audio/packages/sigint_patch.py +14 -0
- truss/templates/trtllm-audio/packages/whisper_trt/__init__.py +215 -0
- truss/templates/trtllm-audio/packages/whisper_trt/assets.py +25 -0
- truss/templates/trtllm-audio/packages/whisper_trt/batching.py +52 -0
- truss/templates/trtllm-audio/packages/whisper_trt/custom_types.py +26 -0
- truss/templates/trtllm-audio/packages/whisper_trt/modeling.py +184 -0
- truss/templates/trtllm-audio/packages/whisper_trt/tokenizer.py +185 -0
- truss/templates/trtllm-audio/packages/whisper_trt/utils.py +245 -0
- truss/templates/trtllm-briton/src/extension.py +64 -0
- truss/tests/conftest.py +302 -94
- truss/tests/contexts/image_builder/test_serving_image_builder.py +74 -31
- truss/tests/contexts/local_loader/test_load_local.py +2 -2
- truss/tests/contexts/local_loader/test_truss_module_finder.py +1 -1
- truss/tests/patch/test_calc_patch.py +439 -127
- truss/tests/patch/test_dir_signature.py +3 -12
- truss/tests/patch/test_hash.py +1 -1
- truss/tests/patch/test_signature.py +1 -1
- truss/tests/patch/test_truss_dir_patch_applier.py +23 -11
- truss/tests/patch/test_types.py +2 -2
- truss/tests/remote/baseten/test_api.py +153 -58
- truss/tests/remote/baseten/test_auth.py +2 -1
- truss/tests/remote/baseten/test_core.py +160 -12
- truss/tests/remote/baseten/test_remote.py +489 -77
- truss/tests/remote/baseten/test_service.py +55 -0
- truss/tests/remote/test_remote_factory.py +16 -18
- truss/tests/remote/test_truss_remote.py +26 -17
- truss/tests/templates/control/control/helpers/test_context_managers.py +11 -0
- truss/tests/templates/control/control/helpers/test_model_container_patch_applier.py +184 -0
- truss/tests/templates/control/control/helpers/test_requirement_name_identifier.py +89 -0
- truss/tests/{server → templates/control}/control/test_server.py +79 -24
- truss/tests/{server → templates/control}/control/test_server_integration.py +24 -16
- truss/tests/templates/core/server/test_dynamic_config_resolver.py +108 -0
- truss/tests/templates/core/server/test_lazy_data_resolver.py +329 -0
- truss/tests/templates/core/server/test_lazy_data_resolver_v2.py +79 -0
- truss/tests/{server → templates}/core/server/test_secrets_resolver.py +1 -1
- truss/tests/{server → templates/server}/common/test_retry.py +3 -3
- truss/tests/templates/server/test_model_wrapper.py +248 -0
- truss/tests/{server → templates/server}/test_schema.py +3 -5
- truss/tests/{server/core/server/common → templates/server}/test_truss_server.py +8 -5
- truss/tests/test_build.py +9 -52
- truss/tests/test_config.py +336 -77
- truss/tests/test_context_builder_image.py +3 -11
- truss/tests/test_control_truss_patching.py +7 -12
- truss/tests/test_custom_server.py +38 -0
- truss/tests/test_data/context_builder_image_test/test.py +3 -0
- truss/tests/test_data/happy.ipynb +56 -0
- truss/tests/test_data/model_load_failure_test/config.yaml +2 -0
- truss/tests/test_data/model_load_failure_test/model/__init__.py +0 -0
- truss/tests/test_data/patch_ping_test_server/__init__.py +0 -0
- truss/{test_data → tests/test_data}/patch_ping_test_server/app.py +3 -9
- truss/{test_data → tests/test_data}/server.Dockerfile +20 -21
- truss/tests/test_data/server_conformance_test_truss/__init__.py +0 -0
- truss/tests/test_data/server_conformance_test_truss/model/__init__.py +0 -0
- truss/{test_data → tests/test_data}/server_conformance_test_truss/model/model.py +1 -3
- truss/tests/test_data/test_async_truss/__init__.py +0 -0
- truss/tests/test_data/test_async_truss/model/__init__.py +0 -0
- truss/tests/test_data/test_basic_truss/__init__.py +0 -0
- truss/tests/test_data/test_basic_truss/config.yaml +16 -0
- truss/tests/test_data/test_basic_truss/model/__init__.py +0 -0
- truss/tests/test_data/test_build_commands/__init__.py +0 -0
- truss/tests/test_data/test_build_commands/config.yaml +13 -0
- truss/tests/test_data/test_build_commands/model/__init__.py +0 -0
- truss/{test_data/test_streaming_async_generator_truss → tests/test_data/test_build_commands}/model/model.py +2 -3
- truss/tests/test_data/test_build_commands_failure/__init__.py +0 -0
- truss/tests/test_data/test_build_commands_failure/config.yaml +14 -0
- truss/tests/test_data/test_build_commands_failure/model/__init__.py +0 -0
- truss/tests/test_data/test_build_commands_failure/model/model.py +17 -0
- truss/tests/test_data/test_concurrency_truss/__init__.py +0 -0
- truss/tests/test_data/test_concurrency_truss/config.yaml +4 -0
- truss/tests/test_data/test_concurrency_truss/model/__init__.py +0 -0
- truss/tests/test_data/test_custom_server_truss/__init__.py +0 -0
- truss/tests/test_data/test_custom_server_truss/config.yaml +20 -0
- truss/tests/test_data/test_custom_server_truss/test_docker_image/Dockerfile +17 -0
- truss/tests/test_data/test_custom_server_truss/test_docker_image/README.md +10 -0
- truss/tests/test_data/test_custom_server_truss/test_docker_image/VERSION +1 -0
- truss/tests/test_data/test_custom_server_truss/test_docker_image/__init__.py +0 -0
- truss/tests/test_data/test_custom_server_truss/test_docker_image/app.py +19 -0
- truss/tests/test_data/test_custom_server_truss/test_docker_image/build_upload_new_image.sh +6 -0
- truss/tests/test_data/test_openai/__init__.py +0 -0
- truss/{test_data/test_basic_truss → tests/test_data/test_openai}/config.yaml +1 -2
- truss/tests/test_data/test_openai/model/__init__.py +0 -0
- truss/tests/test_data/test_openai/model/model.py +15 -0
- truss/tests/test_data/test_pyantic_v1/__init__.py +0 -0
- truss/tests/test_data/test_pyantic_v1/model/__init__.py +0 -0
- truss/tests/test_data/test_pyantic_v1/model/model.py +28 -0
- truss/tests/test_data/test_pyantic_v1/requirements.txt +1 -0
- truss/tests/test_data/test_pyantic_v2/__init__.py +0 -0
- truss/tests/test_data/test_pyantic_v2/config.yaml +13 -0
- truss/tests/test_data/test_pyantic_v2/model/__init__.py +0 -0
- truss/tests/test_data/test_pyantic_v2/model/model.py +30 -0
- truss/tests/test_data/test_pyantic_v2/requirements.txt +1 -0
- truss/tests/test_data/test_requirements_file_truss/__init__.py +0 -0
- truss/tests/test_data/test_requirements_file_truss/config.yaml +13 -0
- truss/tests/test_data/test_requirements_file_truss/model/__init__.py +0 -0
- truss/{test_data → tests/test_data}/test_requirements_file_truss/model/model.py +1 -0
- truss/tests/test_data/test_streaming_async_generator_truss/__init__.py +0 -0
- truss/tests/test_data/test_streaming_async_generator_truss/config.yaml +4 -0
- truss/tests/test_data/test_streaming_async_generator_truss/model/__init__.py +0 -0
- truss/tests/test_data/test_streaming_async_generator_truss/model/model.py +7 -0
- truss/tests/test_data/test_streaming_read_timeout/__init__.py +0 -0
- truss/tests/test_data/test_streaming_read_timeout/model/__init__.py +0 -0
- truss/tests/test_data/test_streaming_truss/__init__.py +0 -0
- truss/tests/test_data/test_streaming_truss/config.yaml +4 -0
- truss/tests/test_data/test_streaming_truss/model/__init__.py +0 -0
- truss/tests/test_data/test_streaming_truss_with_error/__init__.py +0 -0
- truss/tests/test_data/test_streaming_truss_with_error/model/__init__.py +0 -0
- truss/{test_data → tests/test_data}/test_streaming_truss_with_error/model/model.py +3 -11
- truss/tests/test_data/test_streaming_truss_with_error/packages/__init__.py +0 -0
- truss/tests/test_data/test_streaming_truss_with_error/packages/helpers_1.py +5 -0
- truss/tests/test_data/test_streaming_truss_with_error/packages/helpers_2.py +2 -0
- truss/tests/test_data/test_streaming_truss_with_tracing/__init__.py +0 -0
- truss/tests/test_data/test_streaming_truss_with_tracing/config.yaml +43 -0
- truss/tests/test_data/test_streaming_truss_with_tracing/model/__init__.py +0 -0
- truss/tests/test_data/test_streaming_truss_with_tracing/model/model.py +65 -0
- truss/tests/test_data/test_trt_llm_truss/__init__.py +0 -0
- truss/tests/test_data/test_trt_llm_truss/config.yaml +15 -0
- truss/tests/test_data/test_trt_llm_truss/model/__init__.py +0 -0
- truss/tests/test_data/test_trt_llm_truss/model/model.py +15 -0
- truss/tests/test_data/test_truss/__init__.py +0 -0
- truss/tests/test_data/test_truss/config.yaml +4 -0
- truss/tests/test_data/test_truss/model/__init__.py +0 -0
- truss/tests/test_data/test_truss/model/dummy +0 -0
- truss/tests/test_data/test_truss/packages/__init__.py +0 -0
- truss/tests/test_data/test_truss/packages/test_package/__init__.py +0 -0
- truss/tests/test_data/test_truss_server_caching_truss/__init__.py +0 -0
- truss/tests/test_data/test_truss_server_caching_truss/model/__init__.py +0 -0
- truss/tests/test_data/test_truss_with_error/__init__.py +0 -0
- truss/tests/test_data/test_truss_with_error/config.yaml +4 -0
- truss/tests/test_data/test_truss_with_error/model/__init__.py +0 -0
- truss/tests/test_data/test_truss_with_error/model/model.py +8 -0
- truss/tests/test_data/test_truss_with_error/packages/__init__.py +0 -0
- truss/tests/test_data/test_truss_with_error/packages/helpers_1.py +5 -0
- truss/tests/test_data/test_truss_with_error/packages/helpers_2.py +2 -0
- truss/tests/test_docker.py +2 -1
- truss/tests/test_model_inference.py +1340 -292
- truss/tests/test_model_schema.py +33 -26
- truss/tests/test_testing_utilities_for_other_tests.py +50 -5
- truss/tests/test_truss_gatherer.py +3 -5
- truss/tests/test_truss_handle.py +62 -59
- truss/tests/test_util.py +2 -1
- truss/tests/test_validation.py +15 -13
- truss/tests/trt_llm/test_trt_llm_config.py +41 -0
- truss/tests/trt_llm/test_validation.py +91 -0
- truss/tests/util/test_config_checks.py +40 -0
- truss/tests/util/test_env_vars.py +14 -0
- truss/tests/util/test_path.py +10 -23
- truss/trt_llm/config_checks.py +43 -0
- truss/trt_llm/validation.py +42 -0
- truss/truss_handle/__init__.py +0 -0
- truss/truss_handle/build.py +122 -0
- truss/{decorators.py → truss_handle/decorators.py} +1 -1
- truss/truss_handle/patch/__init__.py +0 -0
- truss/{patch → truss_handle/patch}/calc_patch.py +146 -92
- truss/{types.py → truss_handle/patch/custom_types.py} +35 -27
- truss/{patch → truss_handle/patch}/dir_signature.py +1 -1
- truss/truss_handle/patch/hash.py +71 -0
- truss/{patch → truss_handle/patch}/local_truss_patch_applier.py +6 -4
- truss/truss_handle/patch/signature.py +22 -0
- truss/truss_handle/patch/truss_dir_patch_applier.py +87 -0
- truss/{readme_generator.py → truss_handle/readme_generator.py} +3 -2
- truss/{truss_gatherer.py → truss_handle/truss_gatherer.py} +3 -2
- truss/{truss_handle.py → truss_handle/truss_handle.py} +174 -78
- truss/util/.truss_ignore +3 -0
- truss/{docker.py → util/docker.py} +6 -2
- truss/util/download.py +6 -15
- truss/util/env_vars.py +41 -0
- truss/util/log_utils.py +52 -0
- truss/util/path.py +20 -20
- truss/util/requirements.py +11 -0
- {truss-0.10.0rc1.dist-info → truss-0.60.0.dist-info}/METADATA +18 -16
- truss-0.60.0.dist-info/RECORD +324 -0
- {truss-0.10.0rc1.dist-info → truss-0.60.0.dist-info}/WHEEL +1 -1
- truss-0.60.0.dist-info/entry_points.txt +4 -0
- truss_chains/__init__.py +71 -0
- truss_chains/definitions.py +756 -0
- truss_chains/deployment/__init__.py +0 -0
- truss_chains/deployment/code_gen.py +816 -0
- truss_chains/deployment/deployment_client.py +871 -0
- truss_chains/framework.py +1480 -0
- truss_chains/public_api.py +231 -0
- truss_chains/py.typed +0 -0
- truss_chains/pydantic_numpy.py +131 -0
- truss_chains/reference_code/reference_chainlet.py +34 -0
- truss_chains/reference_code/reference_model.py +10 -0
- truss_chains/remote_chainlet/__init__.py +0 -0
- truss_chains/remote_chainlet/model_skeleton.py +60 -0
- truss_chains/remote_chainlet/stub.py +380 -0
- truss_chains/remote_chainlet/utils.py +332 -0
- truss_chains/streaming.py +378 -0
- truss_chains/utils.py +178 -0
- CODE_OF_CONDUCT.md +0 -131
- CONTRIBUTING.md +0 -48
- README.md +0 -137
- context_builder.Dockerfile +0 -24
- truss/blob/blob_backend.py +0 -10
- truss/blob/blob_backend_registry.py +0 -23
- truss/blob/http_public_blob_backend.py +0 -23
- truss/build/__init__.py +0 -2
- truss/build/build.py +0 -143
- truss/build/configure.py +0 -63
- truss/cli/__init__.py +0 -2
- truss/cli/console.py +0 -5
- truss/cli/create.py +0 -5
- truss/config/trt_llm.py +0 -81
- truss/constants.py +0 -61
- truss/model_inference.py +0 -123
- truss/patch/types.py +0 -30
- truss/pytest.ini +0 -7
- truss/server/common/errors.py +0 -100
- truss/server/common/termination_handler_middleware.py +0 -64
- truss/server/common/truss_server.py +0 -389
- truss/server/control/patch/model_code_patch_applier.py +0 -46
- truss/server/control/patch/requirement_name_identifier.py +0 -17
- truss/server/inference_server.py +0 -29
- truss/server/model_wrapper.py +0 -434
- truss/server/shared/logging.py +0 -81
- truss/templates/trtllm/model/model.py +0 -97
- truss/templates/trtllm/packages/build_engine_utils.py +0 -34
- truss/templates/trtllm/packages/constants.py +0 -11
- truss/templates/trtllm/packages/schema.py +0 -216
- truss/templates/trtllm/packages/tensorrt_llm_model_repository/ensemble/config.pbtxt +0 -246
- truss/templates/trtllm/packages/tensorrt_llm_model_repository/postprocessing/1/model.py +0 -181
- truss/templates/trtllm/packages/tensorrt_llm_model_repository/postprocessing/config.pbtxt +0 -64
- truss/templates/trtllm/packages/tensorrt_llm_model_repository/preprocessing/1/model.py +0 -260
- truss/templates/trtllm/packages/tensorrt_llm_model_repository/preprocessing/config.pbtxt +0 -99
- truss/templates/trtllm/packages/tensorrt_llm_model_repository/tensorrt_llm/config.pbtxt +0 -208
- truss/templates/trtllm/packages/triton_client.py +0 -150
- truss/templates/trtllm/packages/utils.py +0 -43
- truss/test_data/context_builder_image_test/test.py +0 -4
- truss/test_data/happy.ipynb +0 -54
- truss/test_data/model_load_failure_test/config.yaml +0 -2
- truss/test_data/test_concurrency_truss/config.yaml +0 -2
- truss/test_data/test_streaming_async_generator_truss/config.yaml +0 -2
- truss/test_data/test_streaming_truss/config.yaml +0 -3
- truss/test_data/test_truss/config.yaml +0 -2
- truss/tests/server/common/test_termination_handler_middleware.py +0 -93
- truss/tests/server/control/test_model_container_patch_applier.py +0 -203
- truss/tests/server/core/server/common/test_util.py +0 -19
- truss/tests/server/test_model_wrapper.py +0 -87
- truss/util/data_structures.py +0 -16
- truss-0.10.0rc1.dist-info/RECORD +0 -216
- truss-0.10.0rc1.dist-info/entry_points.txt +0 -3
- truss/{server/shared → base}/__init__.py +0 -0
- truss/{server → templates/control}/control/helpers/context_managers.py +0 -0
- truss/{server/control → templates/control/control/helpers}/errors.py +0 -0
- truss/{server/control/patch → templates/control/control/helpers/truss_patch}/__init__.py +0 -0
- truss/{server/control/patch → templates/control/control/helpers/truss_patch}/system_packages.py +0 -0
- truss/{test_data/annotated_types_truss/model → templates/server}/__init__.py +0 -0
- truss/{server → templates/server}/common/__init__.py +0 -0
- truss/{test_data/gcs_fix/model → templates/shared}/__init__.py +0 -0
- truss/templates/{trtllm → trtllm-briton}/README.md +0 -0
- truss/{test_data/server_conformance_test_truss/model → tests/test_data}/__init__.py +0 -0
- truss/{test_data/test_basic_truss/model → tests/test_data/annotated_types_truss}/__init__.py +0 -0
- truss/{test_data → tests/test_data}/annotated_types_truss/config.yaml +0 -0
- truss/{test_data/test_requirements_file_truss → tests/test_data/annotated_types_truss}/model/__init__.py +0 -0
- truss/{test_data → tests/test_data}/annotated_types_truss/model/model.py +0 -0
- truss/{test_data → tests/test_data}/auto-mpg.data +0 -0
- truss/{test_data → tests/test_data}/context_builder_image_test/Dockerfile +0 -0
- truss/{test_data/test_truss/model → tests/test_data/context_builder_image_test}/__init__.py +0 -0
- truss/{test_data/test_truss_server_caching_truss/model → tests/test_data/gcs_fix}/__init__.py +0 -0
- truss/{test_data → tests/test_data}/gcs_fix/config.yaml +0 -0
- truss/tests/{local → test_data/gcs_fix/model}/__init__.py +0 -0
- truss/{test_data → tests/test_data}/gcs_fix/model/model.py +0 -0
- truss/{test_data/test_truss/model/dummy → tests/test_data/model_load_failure_test/__init__.py} +0 -0
- truss/{test_data → tests/test_data}/model_load_failure_test/model/model.py +0 -0
- truss/{test_data → tests/test_data}/pima-indians-diabetes.csv +0 -0
- truss/{test_data → tests/test_data}/readme_int_example.md +0 -0
- truss/{test_data → tests/test_data}/readme_no_example.md +0 -0
- truss/{test_data → tests/test_data}/readme_str_example.md +0 -0
- truss/{test_data → tests/test_data}/server_conformance_test_truss/config.yaml +0 -0
- truss/{test_data → tests/test_data}/test_async_truss/config.yaml +0 -0
- truss/{test_data → tests/test_data}/test_async_truss/model/model.py +3 -3
- /truss/{test_data → tests/test_data}/test_basic_truss/model/model.py +0 -0
- /truss/{test_data → tests/test_data}/test_concurrency_truss/model/model.py +0 -0
- /truss/{test_data/test_requirements_file_truss → tests/test_data/test_pyantic_v1}/config.yaml +0 -0
- /truss/{test_data → tests/test_data}/test_requirements_file_truss/requirements.txt +0 -0
- /truss/{test_data → tests/test_data}/test_streaming_read_timeout/config.yaml +0 -0
- /truss/{test_data → tests/test_data}/test_streaming_read_timeout/model/model.py +0 -0
- /truss/{test_data → tests/test_data}/test_streaming_truss/model/model.py +0 -0
- /truss/{test_data → tests/test_data}/test_streaming_truss_with_error/config.yaml +0 -0
- /truss/{test_data → tests/test_data}/test_truss/examples.yaml +0 -0
- /truss/{test_data → tests/test_data}/test_truss/model/model.py +0 -0
- /truss/{test_data → tests/test_data}/test_truss/packages/test_package/test.py +0 -0
- /truss/{test_data → tests/test_data}/test_truss_server_caching_truss/config.yaml +0 -0
- /truss/{test_data → tests/test_data}/test_truss_server_caching_truss/model/model.py +0 -0
- /truss/{patch → truss_handle/patch}/constants.py +0 -0
- /truss/{notebook.py → util/notebook.py} +0 -0
- {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
|
-
|
|
7
|
-
from truss.
|
|
8
|
-
from truss.
|
|
9
|
-
from truss.
|
|
10
|
-
from truss.
|
|
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.
|
|
25
|
-
|
|
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
|
-
|
|
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.
|
|
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
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
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
|
-
) ->
|
|
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 =
|
|
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 =
|
|
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
|
|
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
|
|
215
|
-
|
|
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
|
-
|
|
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, *
|
|
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
|
-
|
|
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
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
24
|
-
|
|
25
|
-
|
|
11
|
+
class TrussSignature:
|
|
12
|
+
"""Truss signature stores information for calculating patches for future
|
|
13
|
+
changes to Truss.
|
|
26
14
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
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
|
-
"
|
|
37
|
-
"
|
|
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:
|
|
@@ -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.
|
|
7
|
-
from truss.
|
|
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.
|
|
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
|
+
)
|