latch 2.53.7.dev2__tar.gz → 2.53.8__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.53.7.dev2/latch.egg-info → latch-2.53.8}/PKG-INFO +1 -3
- {latch-2.53.7.dev2 → latch-2.53.8}/latch/ldata/_transfer/upload.py +1 -1
- {latch-2.53.7.dev2 → latch-2.53.8}/latch/ldata/type.py +1 -1
- {latch-2.53.7.dev2 → latch-2.53.8/latch.egg-info}/PKG-INFO +1 -3
- {latch-2.53.7.dev2 → latch-2.53.8}/latch.egg-info/SOURCES.txt +5 -10
- {latch-2.53.7.dev2 → latch-2.53.8}/latch.egg-info/requires.txt +0 -2
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/main.py +19 -14
- latch-2.53.8/latch_cli/services/cp/main.py +106 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/services/cp/utils.py +4 -22
- latch-2.53.8/latch_cli/services/k8s/attach.py +77 -0
- latch-2.53.8/latch_cli/services/k8s/execute.py +78 -0
- {latch-2.53.7.dev2/latch_cli/services/execute → latch-2.53.8/latch_cli/services/k8s}/utils.py +73 -12
- latch-2.53.7.dev2/latch_cli/services/execute/main.py → latch-2.53.8/latch_cli/services/k8s/ws_utils.py +19 -71
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/utils/__init__.py +1 -2
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/utils/path.py +21 -27
- {latch-2.53.7.dev2 → latch-2.53.8}/setup.py +1 -4
- latch-2.53.7.dev2/latch_cli/services/cp/download/main.py +0 -208
- latch-2.53.7.dev2/latch_cli/services/cp/download/worker.py +0 -121
- latch-2.53.7.dev2/latch_cli/services/cp/http_utils.py +0 -91
- latch-2.53.7.dev2/latch_cli/services/cp/main.py +0 -101
- latch-2.53.7.dev2/latch_cli/services/cp/upload/main.py +0 -124
- latch-2.53.7.dev2/latch_cli/services/cp/upload/worker.py +0 -223
- latch-2.53.7.dev2/latch_cli/tui/__init__.py +0 -0
- latch-2.53.7.dev2/tests/__init__.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/LICENSE +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/MANIFEST.in +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/README.md +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch/__init__.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch/account.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch/executions.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch/functions/__init__.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch/functions/messages.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch/functions/operators.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch/functions/secrets.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch/ldata/__init__.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch/ldata/_transfer/__init__.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch/ldata/_transfer/download.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch/ldata/_transfer/manager.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch/ldata/_transfer/node.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch/ldata/_transfer/progress.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch/ldata/_transfer/remote_copy.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch/ldata/_transfer/throttle.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch/ldata/_transfer/utils.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch/ldata/path.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch/registry/__init__.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch/registry/project.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch/registry/record.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch/registry/table.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch/registry/types.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch/registry/upstream_types/__init__.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch/registry/upstream_types/types.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch/registry/upstream_types/values.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch/registry/utils.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch/resources/__init__.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch/resources/conditional.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch/resources/dynamic.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch/resources/launch_plan.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch/resources/map_tasks.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch/resources/reference_workflow.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch/resources/tasks.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch/resources/workflow.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch/types/__init__.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch/types/directory.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch/types/file.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch/types/glob.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch/types/json.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch/types/metadata.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch/types/utils.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch/utils.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch/verified/__init__.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch/verified/deseq2.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch/verified/mafft.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch/verified/pathway.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch/verified/rnaseq.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch/verified/trim_galore.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch.egg-info/dependency_links.txt +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch.egg-info/entry_points.txt +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch.egg-info/top_level.txt +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/__init__.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/auth/__init__.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/auth/csrf.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/auth/oauth2.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/auth/pkce.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/auth/utils.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/centromere/__init__.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/centromere/ctx.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/centromere/utils.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/click_utils.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/constants.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/docker_utils/__init__.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/exceptions/__init__.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/exceptions/cache.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/exceptions/errors.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/exceptions/handler.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/exceptions/traceback.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/menus.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/nextflow/__init__.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/nextflow/config.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/nextflow/utils.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/nextflow/workflow.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/services/__init__.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/services/cp/__init__.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/services/cp/autocomplete.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/services/cp/glob.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/services/get.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/services/get_executions.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/services/get_params.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/services/init/__init__.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/services/init/__pycache__/__init__.cpython-310.pyc +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/services/init/__pycache__/__init__.cpython-311.pyc +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/services/init/__pycache__/__init__.cpython-38.pyc +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/services/init/__pycache__/__init__.cpython-39.pyc +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/services/init/__pycache__/init.cpython-310.pyc +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/services/init/__pycache__/init.cpython-311.pyc +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/services/init/__pycache__/init.cpython-38.pyc +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/services/init/__pycache__/init.cpython-39.pyc +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/services/init/assemble_and_sort/.env +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/services/init/assemble_and_sort/LICENSE +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/services/init/assemble_and_sort/README.md +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/services/init/assemble_and_sort/__init__.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/services/init/assemble_and_sort/__pycache__/__init__.cpython-310.pyc +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/services/init/assemble_and_sort/assemble.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/services/init/assemble_and_sort/sort.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/services/init/assemble_and_sort/system-requirements.txt +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/services/init/common/.dockerignore +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/services/init/example_conda/__init__.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/services/init/example_conda/__pycache__/__init__.cpython-310.pyc +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/services/init/example_conda/conda_task.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/services/init/example_conda/environment.yaml +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/services/init/example_docker/__init__.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/services/init/example_docker/task.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/services/init/example_nf_integration/latch_metadata/__pycache__/__init__.cpython-311.pyc +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/services/init/example_nfcore/Dockerfile +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/services/init/example_nfcore/__init__.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/services/init/example_nfcore/task.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/services/init/example_r/__init__.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/services/init/example_r/__pycache__/__init__.cpython-310.pyc +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/services/init/example_r/environment.R +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/services/init/example_r/r_task.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/services/init/example_snakemake/.latch/latch_entrypoint +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/services/init/example_snakemake/Dockerfile +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/services/init/example_snakemake/Snakefile +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/services/init/example_snakemake/config.yaml +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/services/init/example_snakemake/environment.yaml +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/services/init/example_snakemake/latch_metadata.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/services/init/example_snakemake/scripts/plot-quals.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/services/init/example_snakemake/version +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/services/init/init.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/services/init/template/LICENSE +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/services/init/template/README.md +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/services/init/template/__init__.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/services/init/template/__pycache__/__init__.cpython-310.pyc +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/services/init/template/task.py +0 -0
- {latch-2.53.7.dev2/latch_cli/services/cp/download → latch-2.53.8/latch_cli/services/k8s}/__init__.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/services/launch.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/services/local_dev.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/services/local_dev_old.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/services/login.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/services/ls.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/services/mkdir.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/services/move.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/services/preview.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/services/register/__init__.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/services/register/constants.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/services/register/register.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/services/register/utils.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/services/rm.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/services/stop_pod.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/services/sync.py +0 -0
- {latch-2.53.7.dev2/latch_cli/services/cp/upload → latch-2.53.8/latch_cli/services/test_data}/__init__.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/services/test_data/ls.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/services/test_data/remove.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/services/test_data/upload.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/services/test_data/utils.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/services/workspace.py +0 -0
- {latch-2.53.7.dev2/latch_cli/services/execute → latch-2.53.8/latch_cli/snakemake}/__init__.py +0 -0
- {latch-2.53.7.dev2/latch_cli/services/test_data → latch-2.53.8/latch_cli/snakemake/config}/__init__.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/snakemake/config/parser.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/snakemake/config/utils.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/snakemake/serialize.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/snakemake/serialize_utils.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/snakemake/single_task_snakemake.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/snakemake/utils.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/snakemake/workflow.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/tinyrequests.py +0 -0
- {latch-2.53.7.dev2/latch_cli/snakemake → latch-2.53.8/latch_cli/tui}/__init__.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/latch_cli/workflow_config.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/pyproject.toml +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/setup.cfg +0 -0
- {latch-2.53.7.dev2/latch_cli/snakemake/config → latch-2.53.8/tests}/__init__.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/tests/cp/__init__.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/tests/fixtures.py +0 -0
- {latch-2.53.7.dev2 → latch-2.53.8}/tests/test_ls.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: latch
|
|
3
|
-
Version: 2.53.
|
|
3
|
+
Version: 2.53.8
|
|
4
4
|
Summary: The Latch SDK
|
|
5
5
|
Author-email: kenny@latch.bio
|
|
6
6
|
Classifier: Programming Language :: Python :: 3.8
|
|
@@ -34,8 +34,6 @@ Requires-Dist: aioconsole==0.6.1
|
|
|
34
34
|
Requires-Dist: asyncssh==2.13.2
|
|
35
35
|
Requires-Dist: websockets==11.0.3
|
|
36
36
|
Requires-Dist: watchfiles==0.19.0
|
|
37
|
-
Requires-Dist: uvloop==0.19.0
|
|
38
|
-
Requires-Dist: aiohttp==3.9.5
|
|
39
37
|
Provides-Extra: snakemake
|
|
40
38
|
Requires-Dist: snakemake<7.30.2,>=7.18.0; extra == "snakemake"
|
|
41
39
|
Requires-Dist: pulp<2.8,>=2.0; extra == "snakemake"
|
|
@@ -71,7 +71,7 @@ def upload(
|
|
|
71
71
|
dest_data = node_data.data[dest]
|
|
72
72
|
|
|
73
73
|
if not (dest_data.exists() or dest_data.is_direct_parent()) and not create_parents:
|
|
74
|
-
raise LatchPathError("no such Latch file or directory", dest
|
|
74
|
+
raise LatchPathError("no such Latch file or directory", dest)
|
|
75
75
|
|
|
76
76
|
dest_is_dir = dest_data.type in {
|
|
77
77
|
LDataNodeType.account_root,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: latch
|
|
3
|
-
Version: 2.53.
|
|
3
|
+
Version: 2.53.8
|
|
4
4
|
Summary: The Latch SDK
|
|
5
5
|
Author-email: kenny@latch.bio
|
|
6
6
|
Classifier: Programming Language :: Python :: 3.8
|
|
@@ -34,8 +34,6 @@ Requires-Dist: aioconsole==0.6.1
|
|
|
34
34
|
Requires-Dist: asyncssh==2.13.2
|
|
35
35
|
Requires-Dist: websockets==11.0.3
|
|
36
36
|
Requires-Dist: watchfiles==0.19.0
|
|
37
|
-
Requires-Dist: uvloop==0.19.0
|
|
38
|
-
Requires-Dist: aiohttp==3.9.5
|
|
39
37
|
Provides-Extra: snakemake
|
|
40
38
|
Requires-Dist: snakemake<7.30.2,>=7.18.0; extra == "snakemake"
|
|
41
39
|
Requires-Dist: pulp<2.8,>=2.0; extra == "snakemake"
|
|
@@ -103,18 +103,8 @@ latch_cli/services/workspace.py
|
|
|
103
103
|
latch_cli/services/cp/__init__.py
|
|
104
104
|
latch_cli/services/cp/autocomplete.py
|
|
105
105
|
latch_cli/services/cp/glob.py
|
|
106
|
-
latch_cli/services/cp/http_utils.py
|
|
107
106
|
latch_cli/services/cp/main.py
|
|
108
107
|
latch_cli/services/cp/utils.py
|
|
109
|
-
latch_cli/services/cp/download/__init__.py
|
|
110
|
-
latch_cli/services/cp/download/main.py
|
|
111
|
-
latch_cli/services/cp/download/worker.py
|
|
112
|
-
latch_cli/services/cp/upload/__init__.py
|
|
113
|
-
latch_cli/services/cp/upload/main.py
|
|
114
|
-
latch_cli/services/cp/upload/worker.py
|
|
115
|
-
latch_cli/services/execute/__init__.py
|
|
116
|
-
latch_cli/services/execute/main.py
|
|
117
|
-
latch_cli/services/execute/utils.py
|
|
118
108
|
latch_cli/services/init/__init__.py
|
|
119
109
|
latch_cli/services/init/init.py
|
|
120
110
|
latch_cli/services/init/__pycache__/__init__.cpython-310.pyc
|
|
@@ -161,6 +151,11 @@ latch_cli/services/init/template/README.md
|
|
|
161
151
|
latch_cli/services/init/template/__init__.py
|
|
162
152
|
latch_cli/services/init/template/task.py
|
|
163
153
|
latch_cli/services/init/template/__pycache__/__init__.cpython-310.pyc
|
|
154
|
+
latch_cli/services/k8s/__init__.py
|
|
155
|
+
latch_cli/services/k8s/attach.py
|
|
156
|
+
latch_cli/services/k8s/execute.py
|
|
157
|
+
latch_cli/services/k8s/utils.py
|
|
158
|
+
latch_cli/services/k8s/ws_utils.py
|
|
164
159
|
latch_cli/services/register/__init__.py
|
|
165
160
|
latch_cli/services/register/constants.py
|
|
166
161
|
latch_cli/services/register/register.py
|
|
@@ -4,13 +4,15 @@ import os
|
|
|
4
4
|
import sys
|
|
5
5
|
from pathlib import Path
|
|
6
6
|
from textwrap import dedent
|
|
7
|
-
from typing import Callable, List,
|
|
7
|
+
from typing import Callable, List, Optional, Tuple, TypeVar, Union
|
|
8
8
|
|
|
9
9
|
import click
|
|
10
10
|
from packaging.version import parse as parse_version
|
|
11
11
|
from typing_extensions import ParamSpec
|
|
12
12
|
|
|
13
13
|
import latch_cli.click_utils
|
|
14
|
+
from latch.ldata._transfer.progress import Progress as _Progress
|
|
15
|
+
from latch_cli.click_utils import EnumChoice
|
|
14
16
|
from latch_cli.exceptions.handler import CrashHandler
|
|
15
17
|
from latch_cli.services.cp.autocomplete import complete as cp_complete
|
|
16
18
|
from latch_cli.services.cp.autocomplete import remote_complete
|
|
@@ -435,7 +437,7 @@ def execute(
|
|
|
435
437
|
):
|
|
436
438
|
"""Drops the user into an interactive shell from within a task."""
|
|
437
439
|
|
|
438
|
-
from latch_cli.services.execute
|
|
440
|
+
from latch_cli.services.k8s.execute import exec
|
|
439
441
|
|
|
440
442
|
exec(execution_id=execution_id, egn_id=egn_id, container_index=container_index)
|
|
441
443
|
|
|
@@ -691,7 +693,7 @@ LDATA COMMANDS
|
|
|
691
693
|
@click.option(
|
|
692
694
|
"--progress",
|
|
693
695
|
help="Type of progress information to show while copying",
|
|
694
|
-
type=
|
|
696
|
+
type=EnumChoice(_Progress, case_sensitive=False),
|
|
695
697
|
default="tasks",
|
|
696
698
|
show_default=True,
|
|
697
699
|
)
|
|
@@ -703,14 +705,6 @@ LDATA COMMANDS
|
|
|
703
705
|
default=False,
|
|
704
706
|
show_default=True,
|
|
705
707
|
)
|
|
706
|
-
@click.option(
|
|
707
|
-
"--force",
|
|
708
|
-
"-f",
|
|
709
|
-
help="Don't ask to confirm when overwriting files",
|
|
710
|
-
is_flag=True,
|
|
711
|
-
default=False,
|
|
712
|
-
show_default=True,
|
|
713
|
-
)
|
|
714
708
|
@click.option(
|
|
715
709
|
"--no-glob",
|
|
716
710
|
"-G",
|
|
@@ -733,9 +727,8 @@ LDATA COMMANDS
|
|
|
733
727
|
def cp(
|
|
734
728
|
src: List[str],
|
|
735
729
|
dest: str,
|
|
736
|
-
progress:
|
|
730
|
+
progress: _Progress,
|
|
737
731
|
verbose: bool,
|
|
738
|
-
force: bool,
|
|
739
732
|
no_glob: bool,
|
|
740
733
|
cores: Optional[int] = None,
|
|
741
734
|
chunk_size_mib: Optional[int] = None,
|
|
@@ -754,7 +747,6 @@ def cp(
|
|
|
754
747
|
src,
|
|
755
748
|
dest,
|
|
756
749
|
progress=progress,
|
|
757
|
-
force=force,
|
|
758
750
|
verbose=verbose,
|
|
759
751
|
expand_globs=not no_glob,
|
|
760
752
|
cores=cores,
|
|
@@ -1007,6 +999,19 @@ def generate_entrypoint(
|
|
|
1007
999
|
)
|
|
1008
1000
|
|
|
1009
1001
|
|
|
1002
|
+
@nextflow.command("attach")
|
|
1003
|
+
@click.option(
|
|
1004
|
+
"--execution-id", "-e", type=str, help="Optional execution ID to inspect."
|
|
1005
|
+
)
|
|
1006
|
+
@requires_login
|
|
1007
|
+
def attach(execution_id: Optional[str]):
|
|
1008
|
+
"""Drops the user into an interactive shell to inspect the workdir of a nextflow execution."""
|
|
1009
|
+
|
|
1010
|
+
from latch_cli.services.k8s.attach import attach
|
|
1011
|
+
|
|
1012
|
+
attach(execution_id)
|
|
1013
|
+
|
|
1014
|
+
|
|
1010
1015
|
"""
|
|
1011
1016
|
POD COMMANDS
|
|
1012
1017
|
"""
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
from textwrap import dedent
|
|
3
|
+
from typing import List, Optional
|
|
4
|
+
|
|
5
|
+
import click
|
|
6
|
+
|
|
7
|
+
from latch.ldata._transfer.download import download as _download
|
|
8
|
+
from latch.ldata._transfer.progress import Progress
|
|
9
|
+
from latch.ldata._transfer.remote_copy import remote_copy as _remote_copy
|
|
10
|
+
from latch.ldata._transfer.upload import upload as _upload
|
|
11
|
+
from latch.ldata.type import LatchPathError
|
|
12
|
+
from latch_cli.services.cp.glob import expand_pattern
|
|
13
|
+
from latch_cli.utils import human_readable_time, with_si_suffix
|
|
14
|
+
from latch_cli.utils.path import get_path_error, is_remote_path
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def _copy_and_print(src: str, dst: str, progress: Progress) -> None:
|
|
18
|
+
_remote_copy(src, dst)
|
|
19
|
+
if progress != Progress.none:
|
|
20
|
+
click.echo(dedent(f"""
|
|
21
|
+
{click.style("Copy Requested.", fg="green")}
|
|
22
|
+
{click.style("Source: ", fg="blue")}{(src)}
|
|
23
|
+
{click.style("Destination: ", fg="blue")}{(dst)}"""))
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def _download_and_print(src: str, dst: Path, progress: Progress, verbose: bool) -> None:
|
|
27
|
+
if progress != Progress.none:
|
|
28
|
+
click.secho(f"Downloading {dst.name}", fg="blue")
|
|
29
|
+
res = _download(src, dst, progress, verbose)
|
|
30
|
+
if progress != Progress.none:
|
|
31
|
+
click.echo(dedent(f"""
|
|
32
|
+
{click.style("Download Complete", fg="green")}
|
|
33
|
+
{click.style("Time Elapsed: ", fg="blue")}{human_readable_time(res.total_time)}
|
|
34
|
+
{click.style("Files Downloaded: ", fg="blue")}{res.num_files} ({with_si_suffix(res.total_bytes)})
|
|
35
|
+
"""))
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
# todo(ayush): come up with a better behavior scheme than unix cp
|
|
39
|
+
def cp(
|
|
40
|
+
srcs: List[str],
|
|
41
|
+
dest: str,
|
|
42
|
+
*,
|
|
43
|
+
progress: Progress,
|
|
44
|
+
verbose: bool,
|
|
45
|
+
expand_globs: bool,
|
|
46
|
+
cores: Optional[int] = None,
|
|
47
|
+
chunk_size_mib: Optional[int] = None,
|
|
48
|
+
):
|
|
49
|
+
if chunk_size_mib is not None and chunk_size_mib < 5:
|
|
50
|
+
click.secho(
|
|
51
|
+
"The chunk size specified by --chunk-size-mib must be at least 5. You"
|
|
52
|
+
f" provided `{chunk_size_mib}`",
|
|
53
|
+
fg="red",
|
|
54
|
+
)
|
|
55
|
+
raise click.exceptions.Exit(1)
|
|
56
|
+
|
|
57
|
+
dest_remote = is_remote_path(dest)
|
|
58
|
+
|
|
59
|
+
for src in srcs:
|
|
60
|
+
src_remote = is_remote_path(src)
|
|
61
|
+
|
|
62
|
+
try:
|
|
63
|
+
if src_remote and not dest_remote:
|
|
64
|
+
if expand_globs:
|
|
65
|
+
[
|
|
66
|
+
_download_and_print(p, Path(dest), progress, verbose)
|
|
67
|
+
for p in expand_pattern(src)
|
|
68
|
+
]
|
|
69
|
+
else:
|
|
70
|
+
_download_and_print(src, Path(dest), progress, verbose)
|
|
71
|
+
elif not src_remote and dest_remote:
|
|
72
|
+
if progress != Progress.none:
|
|
73
|
+
click.secho(f"Uploading {src}", fg="blue")
|
|
74
|
+
res = _upload(
|
|
75
|
+
src,
|
|
76
|
+
dest,
|
|
77
|
+
progress=progress,
|
|
78
|
+
verbose=verbose,
|
|
79
|
+
cores=cores,
|
|
80
|
+
chunk_size_mib=chunk_size_mib,
|
|
81
|
+
)
|
|
82
|
+
if progress != Progress.none:
|
|
83
|
+
click.echo(dedent(f"""
|
|
84
|
+
{click.style("Upload Complete", fg="green")}
|
|
85
|
+
{click.style("Time Elapsed: ", fg="blue")}{human_readable_time(res.total_time)}
|
|
86
|
+
{click.style("Files Uploaded: ", fg="blue")}{res.num_files} ({with_si_suffix(res.total_bytes)})
|
|
87
|
+
"""))
|
|
88
|
+
elif src_remote and dest_remote:
|
|
89
|
+
if expand_globs:
|
|
90
|
+
[_copy_and_print(p, dest, progress) for p in expand_pattern(src)]
|
|
91
|
+
else:
|
|
92
|
+
_copy_and_print(src, dest, progress)
|
|
93
|
+
else:
|
|
94
|
+
raise ValueError(
|
|
95
|
+
dedent(f"""
|
|
96
|
+
`latch cp` cannot be used for purely local file copying.
|
|
97
|
+
|
|
98
|
+
Please ensure at least one of your arguments is a remote path (beginning with `latch://`)
|
|
99
|
+
""").strip("\n"),
|
|
100
|
+
)
|
|
101
|
+
except LatchPathError as e:
|
|
102
|
+
click.secho(get_path_error(e.remote_path, e.message, e.acc_id), fg="red")
|
|
103
|
+
raise click.exceptions.Exit(1) from e
|
|
104
|
+
except Exception as e:
|
|
105
|
+
click.secho(str(e), fg="red")
|
|
106
|
+
raise click.exceptions.Exit(1) from e
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import
|
|
2
|
-
from typing import Iterable, List, TypedDict, TypeVar
|
|
1
|
+
from typing import List, TypedDict
|
|
3
2
|
|
|
4
|
-
|
|
3
|
+
try:
|
|
5
4
|
from functools import cache
|
|
6
|
-
|
|
5
|
+
except ImportError:
|
|
7
6
|
from functools import lru_cache as cache
|
|
8
7
|
|
|
9
8
|
import gql
|
|
@@ -102,7 +101,7 @@ class AccountInfoCurrent(TypedDict):
|
|
|
102
101
|
|
|
103
102
|
# todo(taras): support for gcp and azure mounts
|
|
104
103
|
# skipping now due to time. This decision does not
|
|
105
|
-
# influence
|
|
104
|
+
# influence correcetness of the CLI and only
|
|
106
105
|
# reduces the set of returned autocomplete
|
|
107
106
|
# suggestions
|
|
108
107
|
@cache
|
|
@@ -163,20 +162,3 @@ def _get_known_domains_for_account() -> List[str]:
|
|
|
163
162
|
res.extend(f"{x}.mount" for x in buckets)
|
|
164
163
|
|
|
165
164
|
return res
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
chunk_batch_size = 3
|
|
169
|
-
|
|
170
|
-
T = TypeVar("T")
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
def chunked(iter: Iterable[T]) -> Iterable[List[T]]:
|
|
174
|
-
chunk = []
|
|
175
|
-
for x in iter:
|
|
176
|
-
if len(chunk) == chunk_batch_size:
|
|
177
|
-
yield chunk
|
|
178
|
-
chunk = []
|
|
179
|
-
|
|
180
|
-
chunk.append(x)
|
|
181
|
-
|
|
182
|
-
yield chunk
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
import json
|
|
3
|
+
import secrets
|
|
4
|
+
import sys
|
|
5
|
+
from typing import Optional
|
|
6
|
+
from urllib.parse import urljoin, urlparse
|
|
7
|
+
|
|
8
|
+
import click
|
|
9
|
+
import websockets.client as websockets
|
|
10
|
+
import websockets.exceptions as ws_exceptions
|
|
11
|
+
from latch_sdk_config.latch import NUCLEUS_URL
|
|
12
|
+
|
|
13
|
+
from latch_cli.utils import get_auth_header
|
|
14
|
+
|
|
15
|
+
from .utils import get_pvc_info
|
|
16
|
+
from .ws_utils import forward_stdio
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
async def connect(execution_id: str, session_id: str):
|
|
20
|
+
async with websockets.connect(
|
|
21
|
+
urlparse(urljoin(NUCLEUS_URL, "/workflows/cli/attach-nf-workdir"))
|
|
22
|
+
._replace(scheme="wss")
|
|
23
|
+
.geturl(),
|
|
24
|
+
close_timeout=0,
|
|
25
|
+
extra_headers={"Authorization": get_auth_header()},
|
|
26
|
+
) as ws:
|
|
27
|
+
request = {"execution_id": int(execution_id), "session_id": session_id}
|
|
28
|
+
|
|
29
|
+
await ws.send(json.dumps(request))
|
|
30
|
+
data = await ws.recv()
|
|
31
|
+
|
|
32
|
+
msg = ""
|
|
33
|
+
try:
|
|
34
|
+
res = json.loads(data)
|
|
35
|
+
if "error" in res:
|
|
36
|
+
raise RuntimeError(res["error"])
|
|
37
|
+
except json.JSONDecodeError:
|
|
38
|
+
msg = "Unable to connect to pod - internal error."
|
|
39
|
+
except RuntimeError as e:
|
|
40
|
+
msg = str(e)
|
|
41
|
+
|
|
42
|
+
if msg != "":
|
|
43
|
+
raise RuntimeError(msg)
|
|
44
|
+
|
|
45
|
+
await forward_stdio(ws)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def get_session_id():
|
|
49
|
+
return secrets.token_bytes(8).hex()
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def attach(execution_id: Optional[str] = None):
|
|
53
|
+
execution_id = get_pvc_info(execution_id)
|
|
54
|
+
session_id = get_session_id()
|
|
55
|
+
|
|
56
|
+
click.secho(
|
|
57
|
+
"Attaching to workdir - this may take a few seconds...", dim=True, italic=True
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
import termios
|
|
61
|
+
import tty
|
|
62
|
+
|
|
63
|
+
old_settings_stdin = termios.tcgetattr(sys.stdin.fileno())
|
|
64
|
+
tty.setraw(sys.stdin)
|
|
65
|
+
|
|
66
|
+
msg = ""
|
|
67
|
+
try:
|
|
68
|
+
asyncio.run(connect(execution_id, session_id))
|
|
69
|
+
except ws_exceptions.ConnectionClosedError as e:
|
|
70
|
+
msg = json.loads(e.reason)["error"]
|
|
71
|
+
except RuntimeError as e:
|
|
72
|
+
msg = str(e)
|
|
73
|
+
finally:
|
|
74
|
+
termios.tcsetattr(sys.stdin.fileno(), termios.TCSANOW, old_settings_stdin)
|
|
75
|
+
|
|
76
|
+
if msg != "":
|
|
77
|
+
click.secho(msg, fg="red")
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
import json
|
|
3
|
+
import sys
|
|
4
|
+
from typing import Optional
|
|
5
|
+
from urllib.parse import urljoin, urlparse
|
|
6
|
+
|
|
7
|
+
import websockets.client as websockets
|
|
8
|
+
from latch_sdk_config.latch import NUCLEUS_URL
|
|
9
|
+
|
|
10
|
+
from latch_cli.services.k8s.utils import (
|
|
11
|
+
ContainerNode,
|
|
12
|
+
EGNNode,
|
|
13
|
+
ExecutionInfoNode,
|
|
14
|
+
get_container_info,
|
|
15
|
+
get_egn_info,
|
|
16
|
+
get_execution_info,
|
|
17
|
+
)
|
|
18
|
+
from latch_cli.utils import get_auth_header
|
|
19
|
+
|
|
20
|
+
from .ws_utils import forward_stdio
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
async def connect(egn_info: EGNNode, container_info: Optional[ContainerNode]):
|
|
24
|
+
async with websockets.connect(
|
|
25
|
+
urlparse(urljoin(NUCLEUS_URL, "/workflows/cli/shell"))
|
|
26
|
+
._replace(scheme="wss")
|
|
27
|
+
.geturl(),
|
|
28
|
+
close_timeout=0,
|
|
29
|
+
extra_headers={"Authorization": get_auth_header()},
|
|
30
|
+
) as ws:
|
|
31
|
+
request = {
|
|
32
|
+
"egn_id": egn_info["id"],
|
|
33
|
+
"container_index": (
|
|
34
|
+
container_info["index"] if container_info is not None else None
|
|
35
|
+
),
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
await ws.send(json.dumps(request))
|
|
39
|
+
data = await ws.recv()
|
|
40
|
+
|
|
41
|
+
msg = ""
|
|
42
|
+
try:
|
|
43
|
+
res = json.loads(data)
|
|
44
|
+
if "error" in res:
|
|
45
|
+
raise RuntimeError(res["error"])
|
|
46
|
+
except json.JSONDecodeError:
|
|
47
|
+
msg = "Unable to connect to pod - internal error."
|
|
48
|
+
except RuntimeError as e:
|
|
49
|
+
msg = str(e)
|
|
50
|
+
|
|
51
|
+
if msg != "":
|
|
52
|
+
raise RuntimeError(msg)
|
|
53
|
+
|
|
54
|
+
await forward_stdio(ws)
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def exec(
|
|
58
|
+
execution_id: Optional[str] = None,
|
|
59
|
+
egn_id: Optional[str] = None,
|
|
60
|
+
container_index: Optional[int] = None,
|
|
61
|
+
):
|
|
62
|
+
execution_info: Optional[ExecutionInfoNode] = None
|
|
63
|
+
if egn_id is None:
|
|
64
|
+
execution_info = get_execution_info(execution_id)
|
|
65
|
+
|
|
66
|
+
egn_info = get_egn_info(execution_info, egn_id)
|
|
67
|
+
container_info = get_container_info(egn_info, container_index)
|
|
68
|
+
|
|
69
|
+
import termios
|
|
70
|
+
import tty
|
|
71
|
+
|
|
72
|
+
old_settings_stdin = termios.tcgetattr(sys.stdin.fileno())
|
|
73
|
+
tty.setraw(sys.stdin)
|
|
74
|
+
|
|
75
|
+
try:
|
|
76
|
+
asyncio.run(connect(egn_info, container_info))
|
|
77
|
+
finally:
|
|
78
|
+
termios.tcsetattr(sys.stdin.fileno(), termios.TCSANOW, old_settings_stdin)
|
{latch-2.53.7.dev2/latch_cli/services/execute → latch-2.53.8/latch_cli/services/k8s}/utils.py
RENAMED
|
@@ -9,7 +9,6 @@ from latch_sdk_gql.execute import execute
|
|
|
9
9
|
|
|
10
10
|
from latch_cli.click_utils import bold, color
|
|
11
11
|
from latch_cli.menus import select_tui
|
|
12
|
-
from latch_cli.utils import current_workspace
|
|
13
12
|
|
|
14
13
|
|
|
15
14
|
# todo(ayush): put this into latch_sdk_gql
|
|
@@ -179,35 +178,39 @@ def get_execution_info(execution_id: Optional[str]) -> ExecutionInfoNode:
|
|
|
179
178
|
"""),
|
|
180
179
|
*fragments,
|
|
181
180
|
),
|
|
182
|
-
{"createdBy":
|
|
181
|
+
{"createdBy": user_config.workspace_id},
|
|
183
182
|
)["runningExecutions"]
|
|
184
183
|
|
|
185
|
-
|
|
186
|
-
|
|
184
|
+
nodes = res["nodes"]
|
|
185
|
+
|
|
186
|
+
if len(nodes) == 0:
|
|
187
|
+
click.secho(
|
|
188
|
+
f"You have no executions currently running.",
|
|
189
|
+
dim=True,
|
|
190
|
+
)
|
|
187
191
|
raise click.exceptions.Exit(0)
|
|
188
192
|
|
|
189
|
-
if len(
|
|
190
|
-
execution =
|
|
193
|
+
if len(nodes) == 1:
|
|
194
|
+
execution = nodes[0]
|
|
191
195
|
click.secho(
|
|
192
196
|
"Selecting execution"
|
|
193
197
|
f" {color(execution['displayName'])} as it is"
|
|
194
|
-
" the only"
|
|
195
|
-
" one currently running in Workspace"
|
|
198
|
+
" the only one currently running in Workspace"
|
|
196
199
|
f" {color(workspace_str)}.",
|
|
197
200
|
)
|
|
198
201
|
|
|
199
202
|
return execution
|
|
200
203
|
|
|
201
204
|
selected_execution = select_tui(
|
|
202
|
-
"You have multiple executions running in
|
|
203
|
-
f" ({color(workspace_str)}). Which"
|
|
204
|
-
"
|
|
205
|
+
"You have multiple executions running in"
|
|
206
|
+
f" this workspace ({color(workspace_str)}). Which execution would you like to"
|
|
207
|
+
" inspect?",
|
|
205
208
|
[
|
|
206
209
|
{
|
|
207
210
|
"display_name": f'{x["displayName"]} ({x["workflow"]["displayName"]})',
|
|
208
211
|
"value": x,
|
|
209
212
|
}
|
|
210
|
-
for x in
|
|
213
|
+
for x in nodes
|
|
211
214
|
],
|
|
212
215
|
clear_terminal=False,
|
|
213
216
|
)
|
|
@@ -368,3 +371,61 @@ def get_container_info(
|
|
|
368
371
|
raise click.exceptions.Exit(0)
|
|
369
372
|
|
|
370
373
|
return selected_container_info
|
|
374
|
+
|
|
375
|
+
|
|
376
|
+
class Node(TypedDict):
|
|
377
|
+
id: str
|
|
378
|
+
displayName: str
|
|
379
|
+
|
|
380
|
+
|
|
381
|
+
class nfAvailablePvcs(TypedDict):
|
|
382
|
+
nodes: List[Node]
|
|
383
|
+
|
|
384
|
+
|
|
385
|
+
def get_pvc_info(execution_id: Optional[str]) -> str:
|
|
386
|
+
if execution_id is not None:
|
|
387
|
+
return execution_id
|
|
388
|
+
|
|
389
|
+
workspace_str: str = user_config.workspace_name or user_config.workspace_id
|
|
390
|
+
|
|
391
|
+
res: nfAvailablePvcs = execute(
|
|
392
|
+
gql.gql("""
|
|
393
|
+
query NFWorkdirs($wsId: BigInt!) {
|
|
394
|
+
nfAvailablePvcs(argWsId: $wsId) {
|
|
395
|
+
nodes {
|
|
396
|
+
id
|
|
397
|
+
displayName
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
"""),
|
|
402
|
+
{"wsId": user_config.workspace_id},
|
|
403
|
+
)["nfAvailablePvcs"]
|
|
404
|
+
|
|
405
|
+
nodes = res["nodes"]
|
|
406
|
+
|
|
407
|
+
if len(nodes) == 0:
|
|
408
|
+
click.secho(
|
|
409
|
+
f"You have no available workdirs (all have expired).",
|
|
410
|
+
dim=True,
|
|
411
|
+
)
|
|
412
|
+
raise click.exceptions.Exit(0)
|
|
413
|
+
|
|
414
|
+
if len(nodes) == 1:
|
|
415
|
+
execution = nodes[0]
|
|
416
|
+
click.secho(
|
|
417
|
+
f"Selecting execution {color(execution['displayName'])} as it is the only"
|
|
418
|
+
f" one without an expired workDir in Workspace {color(workspace_str)}.",
|
|
419
|
+
)
|
|
420
|
+
return execution["id"]
|
|
421
|
+
|
|
422
|
+
selected_execution = select_tui(
|
|
423
|
+
"You have multiple available workDirs in this workspace"
|
|
424
|
+
f" ({color(workspace_str)}). Which execution would you like to attach to?",
|
|
425
|
+
options=[{"display_name": x["displayName"], "value": x["id"]} for x in nodes],
|
|
426
|
+
)
|
|
427
|
+
if selected_execution is None:
|
|
428
|
+
click.secho("No execution selected. Exiting.", dim=True)
|
|
429
|
+
raise click.exceptions.Exit(0)
|
|
430
|
+
|
|
431
|
+
return selected_execution
|