latch 2.76.1__tar.gz → 2.76.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {latch-2.76.1 → latch-2.76.3}/PKG-INFO +3 -4
- {latch-2.76.1 → latch-2.76.3}/pyproject.toml +4 -5
- {latch-2.76.1 → latch-2.76.3}/src/latch/types/file.py +4 -1
- {latch-2.76.1 → latch-2.76.3}/src/latch/utils.py +9 -21
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/centromere/ctx.py +2 -22
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/centromere/utils.py +4 -49
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/constants.py +2 -3
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/main.py +55 -223
- latch-2.76.3/src/latch_cli/services/launch.py +262 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/services/local_dev_old.py +18 -11
- latch-2.76.3/src/latch_cli/services/login.py +95 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/services/register/register.py +2 -14
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/services/register/utils.py +2 -19
- latch-2.76.3/src/latch_cli/services/stop_pod.py +32 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/snakemake/serialize.py +25 -14
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/utils/__init__.py +0 -13
- {latch-2.76.1 → latch-2.76.3}/src/latch_sdk_config/latch.py +11 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_sdk_gql/execute.py +2 -6
- latch-2.76.1/src/latch_cli/services/gql/pod_ssh.graphql +0 -10
- latch-2.76.1/src/latch_cli/services/gql/pods_list.graphql +0 -48
- latch-2.76.1/src/latch_cli/services/login.py +0 -160
- latch-2.76.1/src/latch_cli/services/pods.py +0 -435
- latch-2.76.1/src/latch_cli/services/stop_pod.py +0 -3
- {latch-2.76.1 → latch-2.76.3}/.gitignore +0 -0
- {latch-2.76.1 → latch-2.76.3}/LICENSE +0 -0
- {latch-2.76.1 → latch-2.76.3}/README.md +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch/__init__.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch/account.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch/executions.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch/functions/__init__.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch/functions/messages.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch/functions/operators.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch/functions/secrets.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch/idl/admin/common.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch/idl/admin/launch_plan.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch/idl/admin/schedule.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch/idl/admin/workflow.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch/idl/core/condition.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch/idl/core/execution.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch/idl/core/identifier.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch/idl/core/interface.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch/idl/core/literals.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch/idl/core/security.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch/idl/core/tasks.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch/idl/core/types.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch/idl/core/workflow.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch/idl/utils.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch/ldata/__init__.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch/ldata/_transfer/__init__.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch/ldata/_transfer/download.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch/ldata/_transfer/manager.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch/ldata/_transfer/node.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch/ldata/_transfer/progress.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch/ldata/_transfer/remote_copy.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch/ldata/_transfer/throttle.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch/ldata/_transfer/upload.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch/ldata/_transfer/utils.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch/ldata/path.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch/ldata/type.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch/py.typed +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch/registry/__init__.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch/registry/project.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch/registry/record.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch/registry/table.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch/registry/types.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch/registry/upstream_types/__init__.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch/registry/upstream_types/types.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch/registry/upstream_types/values.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch/registry/utils.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch/resources/__init__.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch/resources/conditional.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch/resources/dynamic.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch/resources/launch_plan.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch/resources/map_tasks.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch/resources/reference_workflow.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch/resources/tasks.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch/resources/workflow.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch/types/__init__.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch/types/directory.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch/types/glob.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch/types/json.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch/types/metadata.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch/types/plots.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch/types/samplesheet_item.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch/types/utils.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch/verified/__init__.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch/verified/deseq2.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch/verified/mafft.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch/verified/pathway.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch/verified/rnaseq.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch/verified/trim_galore.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/__init__.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/auth/__init__.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/auth/csrf.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/auth/oauth2.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/auth/pkce.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/auth/utils.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/centromere/__init__.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/centromere/ast_parsing.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/click_utils.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/docker_utils/__init__.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/exceptions/__init__.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/exceptions/cache.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/exceptions/errors.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/exceptions/handler.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/exceptions/traceback.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/menus.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/nextflow/__init__.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/nextflow/config.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/nextflow/forch_register.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/nextflow/parse_schema.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/nextflow/utils.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/nextflow/workflow.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/py.typed +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/services/__init__.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/services/cp/__init__.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/services/cp/autocomplete.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/services/cp/glob.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/services/cp/main.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/services/cp/utils.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/services/docker/__init__.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/services/docker/utils.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/services/get.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/services/get_executions.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/services/get_params.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/services/init/__init__.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/services/init/assemble_and_sort/.env +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/services/init/assemble_and_sort/LICENSE +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/services/init/assemble_and_sort/README.md +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/services/init/assemble_and_sort/__init__.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/services/init/assemble_and_sort/assemble.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/services/init/assemble_and_sort/sort.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/services/init/assemble_and_sort/system-requirements.txt +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/services/init/common/.dockerignore +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/services/init/example_conda/__init__.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/services/init/example_conda/conda_task.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/services/init/example_conda/environment.yaml +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/services/init/example_docker/__init__.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/services/init/example_docker/task.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/services/init/example_nfcore/Dockerfile +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/services/init/example_nfcore/__init__.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/services/init/example_nfcore/task.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/services/init/example_r/__init__.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/services/init/example_r/environment.R +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/services/init/example_r/r_task.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/services/init/example_snakemake/.latch/latch_entrypoint +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/services/init/example_snakemake/Dockerfile +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/services/init/example_snakemake/Snakefile +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/services/init/example_snakemake/config.yaml +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/services/init/example_snakemake/environment.yaml +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/services/init/example_snakemake/latch_metadata.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/services/init/example_snakemake/scripts/plot-quals.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/services/init/example_snakemake/version +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/services/init/init.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/services/init/template/LICENSE +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/services/init/template/README.md +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/services/init/template/__init__.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/services/init/template/task.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/services/k8s/__init__.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/services/k8s/attach.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/services/k8s/develop.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/services/k8s/execute.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/services/k8s/utils.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/services/k8s/ws_utils.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/services/launch/__init__.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/services/launch/interface.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/services/launch/launch.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/services/launch/launch_v2.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/services/launch/type_converter.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/services/ls.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/services/mkdir.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/services/move.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/services/preview.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/services/private_images.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/services/register/__init__.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/services/register/constants.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/services/register/staging.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/services/rm.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/services/sync.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/services/test_data/__init__.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/services/test_data/ls.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/services/test_data/remove.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/services/test_data/upload.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/services/test_data/utils.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/services/workspace.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/snakemake/__init__.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/snakemake/config/__init__.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/snakemake/config/parser.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/snakemake/config/utils.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/snakemake/serialize_utils.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/snakemake/single_task_snakemake.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/snakemake/utils.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/snakemake/workflow.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/tinyrequests.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/tui/__init__.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/utils/path.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_cli/workflow_config.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_sdk_config/__init__.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_sdk_config/py.typed +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_sdk_config/user.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_sdk_gql/__init__.py +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_sdk_gql/py.typed +0 -0
- {latch-2.76.1 → latch-2.76.3}/src/latch_sdk_gql/utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: latch
|
|
3
|
-
Version: 2.76.
|
|
3
|
+
Version: 2.76.3
|
|
4
4
|
Summary: The Latch SDK
|
|
5
5
|
Project-URL: Homepage, https://latch.bio
|
|
6
6
|
Project-URL: Documentation, https://latch.wiki
|
|
@@ -41,6 +41,7 @@ Classifier: Topic :: Scientific/Engineering
|
|
|
41
41
|
Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
|
|
42
42
|
Classifier: Topic :: Software Development :: Build Tools
|
|
43
43
|
Requires-Python: >=3.9
|
|
44
|
+
Requires-Dist: aioconsole==0.6.1
|
|
44
45
|
Requires-Dist: apscheduler>=3.10.0
|
|
45
46
|
Requires-Dist: asyncssh==2.13.2
|
|
46
47
|
Requires-Dist: boto3>=1.26.0
|
|
@@ -56,18 +57,16 @@ Requires-Dist: lytekit==0.15.35
|
|
|
56
57
|
Requires-Dist: lytekitplugins-pods==0.7.4
|
|
57
58
|
Requires-Dist: orjson>=3.10.12
|
|
58
59
|
Requires-Dist: paramiko>=3.4.0
|
|
59
|
-
Requires-Dist: pydantic<3,>=2
|
|
60
60
|
Requires-Dist: pyjwt>=0.2.0
|
|
61
61
|
Requires-Dist: python-dateutil>=2.8
|
|
62
62
|
Requires-Dist: pyxattr>=0.8.1
|
|
63
63
|
Requires-Dist: requests-toolbelt==1.0.0
|
|
64
64
|
Requires-Dist: requests>=2.28.1
|
|
65
|
-
Requires-Dist: rich>=14.0.0
|
|
66
65
|
Requires-Dist: scp>=0.14.0
|
|
67
66
|
Requires-Dist: tqdm>=4.63.0
|
|
68
67
|
Requires-Dist: typing-extensions>=4.12.0
|
|
69
68
|
Requires-Dist: watchfiles==1.1.1
|
|
70
|
-
Requires-Dist: websockets
|
|
69
|
+
Requires-Dist: websockets>=15.0.1
|
|
71
70
|
Provides-Extra: pandas
|
|
72
71
|
Requires-Dist: pandas>=2.0.0; extra == 'pandas'
|
|
73
72
|
Provides-Extra: snakemake
|
|
@@ -3,7 +3,7 @@ requires = ["hatchling"]
|
|
|
3
3
|
build-backend = "hatchling.build"
|
|
4
4
|
|
|
5
5
|
[tool.hatch.build.targets.sdist]
|
|
6
|
-
include = ["src/**/*.py", "src
|
|
6
|
+
include = ["src/**/*.py", "src/**/py.typed", "src/latch_cli/services/init/*"]
|
|
7
7
|
|
|
8
8
|
[tool.hatch.build.targets.wheel.force-include]
|
|
9
9
|
"src/latch_cli" = "latch_cli"
|
|
@@ -12,7 +12,7 @@ include = ["src/**/*.py", "src/**/*.graphql", "src/**/py.typed", "src/latch_cli/
|
|
|
12
12
|
|
|
13
13
|
[project]
|
|
14
14
|
name = "latch"
|
|
15
|
-
version = "2.76.
|
|
15
|
+
version = "2.76.3"
|
|
16
16
|
description = "The Latch SDK"
|
|
17
17
|
authors = [{ name = "Kenny Workman", email = "kenny@latch.bio" }]
|
|
18
18
|
maintainers = [{ name = "Kenny Workman", email = "kenny@latch.bio" }]
|
|
@@ -39,12 +39,11 @@ dependencies = [
|
|
|
39
39
|
"graphql-core==3.2.3",
|
|
40
40
|
"requests-toolbelt==1.0.0",
|
|
41
41
|
"python-dateutil>=2.8",
|
|
42
|
-
"pydantic>=2,<3",
|
|
43
|
-
"rich>=14.0.0",
|
|
44
42
|
"GitPython==3.1.40",
|
|
45
43
|
# for old latch develop, to be removed
|
|
44
|
+
"aioconsole==0.6.1",
|
|
46
45
|
"asyncssh==2.13.2",
|
|
47
|
-
"websockets>=
|
|
46
|
+
"websockets>=15.0.1",
|
|
48
47
|
"watchfiles==1.1.1",
|
|
49
48
|
"pyxattr>=0.8.1",
|
|
50
49
|
"orjson>=3.10.12",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import os
|
|
2
2
|
from os import PathLike
|
|
3
3
|
from pathlib import Path
|
|
4
|
-
from typing import Annotated, Optional, Union
|
|
4
|
+
from typing import Annotated, Optional, Union, get_args, get_origin
|
|
5
5
|
from urllib.parse import urlparse
|
|
6
6
|
|
|
7
7
|
import gql
|
|
@@ -249,6 +249,9 @@ class LatchFilePathTransformer(FlyteFilePathTransformer):
|
|
|
249
249
|
"Casting from Pathlike to LatchFile is currently not supported."
|
|
250
250
|
)
|
|
251
251
|
|
|
252
|
+
while get_origin(expected_python_type) == Annotated:
|
|
253
|
+
expected_python_type = get_args(expected_python_type)[0]
|
|
254
|
+
|
|
252
255
|
if not issubclass(expected_python_type, LatchFile):
|
|
253
256
|
raise TypeError(
|
|
254
257
|
f"Neither os.PathLike nor LatchFile specified {expected_python_type}"
|
|
@@ -4,39 +4,27 @@ from typing import Dict, TypedDict
|
|
|
4
4
|
|
|
5
5
|
import gql
|
|
6
6
|
import jwt
|
|
7
|
-
|
|
8
7
|
from latch_sdk_config.user import user_config
|
|
9
8
|
from latch_sdk_gql.execute import execute
|
|
10
9
|
|
|
11
10
|
|
|
12
11
|
def account_id_from_token(token: str) -> str:
|
|
13
|
-
"""
|
|
12
|
+
"""Exchanges a valid JWT for a Latch account ID.
|
|
14
13
|
|
|
15
14
|
Latch account IDs are needed for any user-specific request, eg. register
|
|
16
15
|
workflows or copy files to Latch.
|
|
17
16
|
|
|
18
17
|
Args:
|
|
19
|
-
token:
|
|
18
|
+
token: JWT
|
|
20
19
|
|
|
21
20
|
Returns:
|
|
22
|
-
A Latch account ID.
|
|
21
|
+
A Latch account ID (UUID).
|
|
23
22
|
"""
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
id
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
""")
|
|
33
|
-
)
|
|
34
|
-
aic = res.get("accountInfoCurrent")
|
|
35
|
-
if aic is None or aic.get("id") is None:
|
|
36
|
-
raise ValueError(
|
|
37
|
-
"Your Latch access token is invalid or could not be resolved to an account."
|
|
38
|
-
)
|
|
39
|
-
return aic["id"]
|
|
23
|
+
decoded_jwt = jwt.decode(token, options={"verify_signature": False})
|
|
24
|
+
try:
|
|
25
|
+
return decoded_jwt.get("id")
|
|
26
|
+
except KeyError as e:
|
|
27
|
+
raise ValueError("Your Latch access token is malformed") from e
|
|
40
28
|
|
|
41
29
|
|
|
42
30
|
def retrieve_or_login() -> str:
|
|
@@ -182,7 +170,7 @@ def current_workspace() -> str:
|
|
|
182
170
|
}
|
|
183
171
|
}
|
|
184
172
|
}
|
|
185
|
-
""")
|
|
173
|
+
"""),
|
|
186
174
|
)["accountInfoCurrent"]
|
|
187
175
|
|
|
188
176
|
if res is not None:
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
from logging import getLogger
|
|
2
1
|
import re
|
|
3
2
|
import sys
|
|
4
3
|
import traceback
|
|
@@ -31,8 +30,6 @@ from latch_cli.utils import (
|
|
|
31
30
|
)
|
|
32
31
|
from latch_sdk_config.latch import config
|
|
33
32
|
|
|
34
|
-
log = getLogger(__name__)
|
|
35
|
-
|
|
36
33
|
|
|
37
34
|
@dataclass
|
|
38
35
|
class _Container:
|
|
@@ -94,14 +91,12 @@ class _CentromereCtx:
|
|
|
94
91
|
use_new_centromere: bool = False,
|
|
95
92
|
overwrite: bool = False,
|
|
96
93
|
dockerfile_path: Optional[Path] = None,
|
|
97
|
-
account_id: Optional[str] = None,
|
|
98
94
|
):
|
|
99
95
|
self.use_new_centromere = use_new_centromere
|
|
100
96
|
self.remote = remote
|
|
101
97
|
self.disable_auto_version = disable_auto_version
|
|
102
98
|
self.wf_module = wf_module if wf_module is not None else "wf"
|
|
103
99
|
|
|
104
|
-
log.debug("Initializing CentromereCtx")
|
|
105
100
|
if self.wf_module.startswith("."):
|
|
106
101
|
click.secho(
|
|
107
102
|
dedent(f"""\
|
|
@@ -112,15 +107,10 @@ class _CentromereCtx:
|
|
|
112
107
|
raise click.exceptions.Exit(1)
|
|
113
108
|
|
|
114
109
|
try:
|
|
115
|
-
log.debug("retrieve_or_login")
|
|
116
110
|
self.token = retrieve_or_login()
|
|
117
|
-
|
|
118
|
-
self.account_id = (
|
|
119
|
-
account_id if account_id is not None else current_workspace()
|
|
120
|
-
)
|
|
111
|
+
self.account_id = current_workspace()
|
|
121
112
|
|
|
122
113
|
self.dkr_repo = config.dkr_repo
|
|
123
|
-
log.debug("resolving pkg_root")
|
|
124
114
|
self.pkg_root = pkg_root.resolve()
|
|
125
115
|
|
|
126
116
|
if snakefile is not None and nf_script is not None:
|
|
@@ -141,7 +131,6 @@ class _CentromereCtx:
|
|
|
141
131
|
else:
|
|
142
132
|
self.workflow_type = WorkflowType.latchbiosdk
|
|
143
133
|
|
|
144
|
-
log.debug("Determining version")
|
|
145
134
|
version_file = self.pkg_root / "version"
|
|
146
135
|
try:
|
|
147
136
|
self.version = version_file.read_text()
|
|
@@ -154,7 +143,6 @@ class _CentromereCtx:
|
|
|
154
143
|
|
|
155
144
|
self.version = self.version.strip()
|
|
156
145
|
|
|
157
|
-
log.debug("Loading the git repo")
|
|
158
146
|
try:
|
|
159
147
|
from git import GitError, Repo
|
|
160
148
|
|
|
@@ -174,7 +162,6 @@ class _CentromereCtx:
|
|
|
174
162
|
fg="yellow",
|
|
175
163
|
)
|
|
176
164
|
|
|
177
|
-
log.debug("Auto-versioning")
|
|
178
165
|
if not self.disable_auto_version:
|
|
179
166
|
hash = ""
|
|
180
167
|
|
|
@@ -211,7 +198,6 @@ class _CentromereCtx:
|
|
|
211
198
|
),
|
|
212
199
|
)
|
|
213
200
|
|
|
214
|
-
log.debug("Loading Flyte objects")
|
|
215
201
|
try:
|
|
216
202
|
if not module_path.exists():
|
|
217
203
|
click.secho(error_msg, fg="red")
|
|
@@ -440,7 +426,6 @@ class _CentromereCtx:
|
|
|
440
426
|
self.ssh_key_path, add_to_agent=False
|
|
441
427
|
)
|
|
442
428
|
|
|
443
|
-
log.debug("use_new_centromere=%s", use_new_centromere)
|
|
444
429
|
if use_new_centromere:
|
|
445
430
|
self.internal_ip, self.username = (
|
|
446
431
|
self.provision_register_deployment()
|
|
@@ -463,7 +448,6 @@ class _CentromereCtx:
|
|
|
463
448
|
def _patched_connect(self): ...
|
|
464
449
|
|
|
465
450
|
def _patched_create_paramiko_client(self, base_url):
|
|
466
|
-
log.debug("_patched_create_paramiko_client")
|
|
467
451
|
self.ssh_client = ssh_client
|
|
468
452
|
|
|
469
453
|
SSHHTTPAdapter._create_paramiko_client = _patched_create_paramiko_client
|
|
@@ -530,7 +514,6 @@ class _CentromereCtx:
|
|
|
530
514
|
return f"{self.image}:{self.version}"
|
|
531
515
|
|
|
532
516
|
def task_image_name(self, task_name: str) -> str:
|
|
533
|
-
log.debug("task_image_name: %s", task_name)
|
|
534
517
|
task_name = identifier_suffix_from_str(task_name).lower()
|
|
535
518
|
task_name = docker_image_name_illegal_pat.sub("_", task_name)
|
|
536
519
|
|
|
@@ -572,7 +555,6 @@ class _CentromereCtx:
|
|
|
572
555
|
|
|
573
556
|
def provision_register_deployment(self) -> Tuple[str, str]:
|
|
574
557
|
"""Retrieve centromere IP + username."""
|
|
575
|
-
log.debug("provision_register_deployment")
|
|
576
558
|
click.echo("Provisioning register instance. This may take a few minutes.")
|
|
577
559
|
|
|
578
560
|
assert self.ssh_key_path is not None
|
|
@@ -628,11 +610,9 @@ class _CentromereCtx:
|
|
|
628
610
|
def nucleus_check_version(self, version: str, workflow_name: str) -> bool:
|
|
629
611
|
"""Check if version has already been registered for given workflow"""
|
|
630
612
|
|
|
631
|
-
log.debug("nucleus_check_version")
|
|
632
|
-
|
|
633
613
|
headers = {"Authorization": f"Bearer {self.token}"}
|
|
634
614
|
|
|
635
|
-
ws_id =
|
|
615
|
+
ws_id = current_workspace()
|
|
636
616
|
if ws_id is None or ws_id == "":
|
|
637
617
|
ws_id = account_id_from_token(retrieve_or_login())
|
|
638
618
|
|
|
@@ -6,7 +6,6 @@ import string
|
|
|
6
6
|
import sys
|
|
7
7
|
import tempfile
|
|
8
8
|
from dataclasses import dataclass
|
|
9
|
-
from logging import getLogger
|
|
10
9
|
from pathlib import Path
|
|
11
10
|
from types import ModuleType
|
|
12
11
|
from typing import Callable, Iterator, List, Optional, TypeVar
|
|
@@ -18,8 +17,6 @@ from typing_extensions import ParamSpec
|
|
|
18
17
|
|
|
19
18
|
from latch_cli.constants import latch_constants
|
|
20
19
|
|
|
21
|
-
log = getLogger(__name__)
|
|
22
|
-
|
|
23
20
|
|
|
24
21
|
@dataclass
|
|
25
22
|
class RemoteConnInfo:
|
|
@@ -112,7 +109,6 @@ def _construct_dkr_client(ssh_host: Optional[str] = None):
|
|
|
112
109
|
If `ssh_host` is passed, we attempt to make a connection with a remote
|
|
113
110
|
machine.
|
|
114
111
|
"""
|
|
115
|
-
log.debug("Creating docker client: %s", ssh_host)
|
|
116
112
|
|
|
117
113
|
def _from_env():
|
|
118
114
|
host = environment.get("DOCKER_HOST")
|
|
@@ -128,8 +124,6 @@ def _construct_dkr_client(ssh_host: Optional[str] = None):
|
|
|
128
124
|
|
|
129
125
|
enable_tls = tls_verify or cert_path is not None
|
|
130
126
|
|
|
131
|
-
log.debug("Determined Docker host from environment: %s", host)
|
|
132
|
-
|
|
133
127
|
dkr_client = None
|
|
134
128
|
try:
|
|
135
129
|
if not enable_tls:
|
|
@@ -170,19 +164,8 @@ def _construct_dkr_client(ssh_host: Optional[str] = None):
|
|
|
170
164
|
if host is not None and host != "":
|
|
171
165
|
return _from_env()
|
|
172
166
|
else:
|
|
173
|
-
try:
|
|
174
|
-
base_url = f"unix:/{Path.home()}/.docker/run/docker.sock"
|
|
175
|
-
log.debug(
|
|
176
|
-
"Using default Docker host: unix://$HOME/run/docker.sock (%s)", base_url
|
|
177
|
-
)
|
|
178
|
-
return docker.APIClient(base_url=base_url)
|
|
179
|
-
except docker.errors.DockerException:
|
|
180
|
-
tracebac
|
|
181
|
-
pass
|
|
182
|
-
|
|
183
167
|
try:
|
|
184
168
|
# TODO: platform specific socket defaults
|
|
185
|
-
log.debug("Using default Docker host: unix://var/run/docker.sock")
|
|
186
169
|
return docker.APIClient(base_url="unix://var/run/docker.sock")
|
|
187
170
|
except docker.errors.DockerException as de:
|
|
188
171
|
raise OSError(
|
|
@@ -194,66 +177,40 @@ def _construct_dkr_client(ssh_host: Optional[str] = None):
|
|
|
194
177
|
def _construct_ssh_client(
|
|
195
178
|
remote_conn_info: RemoteConnInfo, *, use_gateway: bool = True
|
|
196
179
|
) -> paramiko.SSHClient:
|
|
197
|
-
log.debug(
|
|
198
|
-
"_construct_ssh_client conn_info=%s use_gateway=%s",
|
|
199
|
-
remote_conn_info,
|
|
200
|
-
use_gateway,
|
|
201
|
-
)
|
|
202
|
-
|
|
203
180
|
if use_gateway:
|
|
204
181
|
gateway = paramiko.SSHClient()
|
|
205
|
-
|
|
206
|
-
log.debug("Loading system host keys")
|
|
207
182
|
gateway.load_system_host_keys()
|
|
208
|
-
|
|
209
|
-
log.debug("Setting missing host key policy")
|
|
210
183
|
gateway.set_missing_host_key_policy(paramiko.MissingHostKeyPolicy)
|
|
211
184
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
gateway_pkey = paramiko.PKey.from_path(path=path)
|
|
215
|
-
|
|
216
|
-
log.debug(
|
|
217
|
-
"Connecting to gateway: %s@%s",
|
|
218
|
-
latch_constants.jump_user,
|
|
219
|
-
latch_constants.jump_host,
|
|
185
|
+
gateway_pkey = paramiko.PKey.from_path(
|
|
186
|
+
path=str(remote_conn_info.jump_key_path.resolve())
|
|
220
187
|
)
|
|
188
|
+
|
|
221
189
|
gateway.connect(
|
|
222
190
|
latch_constants.jump_host,
|
|
223
191
|
username=latch_constants.jump_user,
|
|
224
192
|
pkey=gateway_pkey,
|
|
225
193
|
)
|
|
226
194
|
|
|
227
|
-
log.debug("Getting gateway transport")
|
|
228
195
|
gateway_transport = gateway.get_transport()
|
|
229
196
|
if gateway_transport is None:
|
|
230
197
|
raise ConnectionError("unable to create connection to jump host")
|
|
231
198
|
|
|
232
|
-
log.debug("Opening gateway channel")
|
|
233
199
|
sock = gateway_transport.open_channel(
|
|
234
200
|
kind="direct-tcpip", dest_addr=(remote_conn_info.ip, 22), src_addr=("", 0)
|
|
235
201
|
)
|
|
236
202
|
else:
|
|
237
203
|
sock = None
|
|
238
204
|
|
|
239
|
-
|
|
240
|
-
log.debug("Loading public key")
|
|
241
|
-
pkey = paramiko.PKey.from_path(path=path)
|
|
205
|
+
pkey = paramiko.PKey.from_path(path=str(remote_conn_info.ssh_key_path.resolve()))
|
|
242
206
|
|
|
243
207
|
ssh = paramiko.SSHClient()
|
|
244
|
-
|
|
245
|
-
log.debug("Loading system host keys")
|
|
246
208
|
ssh.load_system_host_keys()
|
|
247
|
-
|
|
248
|
-
log.debug("Setting missing host key policy")
|
|
249
209
|
ssh.set_missing_host_key_policy(paramiko.MissingHostKeyPolicy)
|
|
250
|
-
|
|
251
|
-
log.debug("Connecting to remote")
|
|
252
210
|
ssh.connect(
|
|
253
211
|
remote_conn_info.ip, username=remote_conn_info.username, sock=sock, pkey=pkey
|
|
254
212
|
)
|
|
255
213
|
|
|
256
|
-
log.debug("Getting transport")
|
|
257
214
|
transport = ssh.get_transport()
|
|
258
215
|
if transport is None:
|
|
259
216
|
raise ConnectionError(
|
|
@@ -262,7 +219,6 @@ def _construct_ssh_client(
|
|
|
262
219
|
|
|
263
220
|
# (kenny) Equivalent of OpenSSH configuration `ServerAliveInterval`
|
|
264
221
|
# No analogue for `ServerAliveCountMax` in paramiko I could find.
|
|
265
|
-
log.debug("Setting Keep-Alive")
|
|
266
222
|
transport.set_keepalive(latch_constants.centromere_keepalive_interval)
|
|
267
223
|
|
|
268
224
|
return ssh
|
|
@@ -286,7 +242,6 @@ class MaybeRemoteDir:
|
|
|
286
242
|
self.reconnect_info = reconnect_info
|
|
287
243
|
|
|
288
244
|
def __enter__(self):
|
|
289
|
-
log.debug("MaybeRemoteDir.__enter__")
|
|
290
245
|
return self.create()
|
|
291
246
|
|
|
292
247
|
def __exit__(self, exc_type, exc_value, tb):
|
|
@@ -57,11 +57,10 @@ latch_constants = LatchConstants()
|
|
|
57
57
|
|
|
58
58
|
@dataclass(frozen=True)
|
|
59
59
|
class OAuth2Constants:
|
|
60
|
-
client_id: str = "
|
|
60
|
+
client_id: str = "jzFBOhIbfp4EPRYZ8wmx4YyvL27LFDeB"
|
|
61
61
|
"""Identifies the authentication server in 0Auth2.0 flow"""
|
|
62
62
|
|
|
63
|
-
authz_server_host: str = "https://
|
|
64
|
-
|
|
63
|
+
authz_server_host: str = "https://latchai.us.auth0.com"
|
|
65
64
|
"""Host of the authentication server used in 0Auth2.0 flow."""
|
|
66
65
|
|
|
67
66
|
redirect_url: str = "http://127.0.0.1:5050/callback"
|