latch 2.45.6__tar.gz → 2.45.6.dev2__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.45.6/latch.egg-info → latch-2.45.6.dev2}/PKG-INFO +1 -1
- {latch-2.45.6 → latch-2.45.6.dev2}/latch/resources/tasks.py +7 -3
- {latch-2.45.6 → latch-2.45.6.dev2}/latch/types/metadata.py +31 -1
- {latch-2.45.6 → latch-2.45.6.dev2/latch.egg-info}/PKG-INFO +1 -1
- {latch-2.45.6 → latch-2.45.6.dev2}/latch.egg-info/SOURCES.txt +1 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/main.py +44 -11
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/nextflow/config.py +3 -3
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/nextflow/dependencies.py +34 -6
- latch-2.45.6.dev2/latch_cli/nextflow/types.py +6 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/nextflow/workflow.py +40 -11
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/services/register/register.py +11 -11
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/snakemake/config/utils.py +2 -4
- {latch-2.45.6 → latch-2.45.6.dev2}/setup.py +1 -1
- {latch-2.45.6 → latch-2.45.6.dev2}/LICENSE +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/MANIFEST.in +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/README.md +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch/__init__.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch/account.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch/executions.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch/functions/__init__.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch/functions/messages.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch/functions/operators.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch/functions/secrets.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch/ldata/__init__.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch/ldata/_transfer/__init__.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch/ldata/_transfer/download.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch/ldata/_transfer/manager.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch/ldata/_transfer/node.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch/ldata/_transfer/progress.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch/ldata/_transfer/remote_copy.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch/ldata/_transfer/throttle.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch/ldata/_transfer/upload.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch/ldata/_transfer/utils.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch/ldata/path.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch/ldata/type.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch/registry/__init__.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch/registry/project.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch/registry/record.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch/registry/table.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch/registry/types.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch/registry/upstream_types/__init__.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch/registry/upstream_types/types.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch/registry/upstream_types/values.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch/registry/utils.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch/resources/__init__.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch/resources/conditional.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch/resources/dynamic.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch/resources/launch_plan.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch/resources/map_tasks.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch/resources/reference_workflow.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch/resources/workflow.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch/types/__init__.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch/types/directory.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch/types/file.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch/types/glob.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch/types/json.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch/types/utils.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch/utils.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch/verified/__init__.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch/verified/deseq2.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch/verified/mafft.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch/verified/pathway.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch/verified/rnaseq.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch/verified/trim_galore.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch.egg-info/dependency_links.txt +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch.egg-info/entry_points.txt +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch.egg-info/requires.txt +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch.egg-info/top_level.txt +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/__init__.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/auth/__init__.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/auth/csrf.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/auth/oauth2.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/auth/pkce.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/auth/utils.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/centromere/__init__.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/centromere/ctx.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/centromere/utils.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/click_utils.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/constants.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/docker_utils/__init__.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/exceptions/__init__.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/exceptions/cache.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/exceptions/errors.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/exceptions/handler.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/exceptions/traceback.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/menus.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/nextflow/__init__.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/nextflow/utils.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/services/__init__.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/services/cp/__init__.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/services/cp/autocomplete.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/services/cp/glob.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/services/cp/main.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/services/cp/utils.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/services/execute/__init__.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/services/execute/main.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/services/execute/utils.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/services/get.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/services/get_executions.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/services/get_params.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/services/init/__init__.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/services/init/__pycache__/__init__.cpython-310.pyc +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/services/init/__pycache__/init.cpython-310.pyc +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/services/init/assemble_and_sort/.env +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/services/init/assemble_and_sort/LICENSE +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/services/init/assemble_and_sort/README.md +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/services/init/assemble_and_sort/__init__.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/services/init/assemble_and_sort/assemble.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/services/init/assemble_and_sort/sort.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/services/init/assemble_and_sort/system-requirements.txt +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/services/init/common/.dockerignore +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/services/init/example_conda/__init__.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/services/init/example_conda/conda_task.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/services/init/example_conda/environment.yaml +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/services/init/example_docker/__init__.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/services/init/example_docker/task.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/services/init/example_nfcore/Dockerfile +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/services/init/example_nfcore/__init__.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/services/init/example_nfcore/task.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/services/init/example_r/__init__.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/services/init/example_r/environment.R +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/services/init/example_r/r_task.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/services/init/example_snakemake/.latch/latch_entrypoint +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/services/init/example_snakemake/Dockerfile +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/services/init/example_snakemake/Snakefile +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/services/init/example_snakemake/config.yaml +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/services/init/example_snakemake/environment.yaml +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/services/init/example_snakemake/latch_metadata.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/services/init/example_snakemake/scripts/plot-quals.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/services/init/example_snakemake/version +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/services/init/init.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/services/init/template/LICENSE +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/services/init/template/README.md +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/services/init/template/__init__.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/services/init/template/task.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/services/launch.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/services/local_dev.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/services/local_dev_old.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/services/login.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/services/ls.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/services/mkdir.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/services/move.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/services/preview.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/services/register/__init__.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/services/register/constants.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/services/register/utils.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/services/rm.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/services/stop_pod.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/services/sync.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/services/test_data/__init__.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/services/test_data/ls.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/services/test_data/remove.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/services/test_data/upload.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/services/test_data/utils.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/services/workspace.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/snakemake/__init__.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/snakemake/config/__init__.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/snakemake/config/parser.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/snakemake/serialize.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/snakemake/serialize_utils.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/snakemake/single_task_snakemake.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/snakemake/utils.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/snakemake/workflow.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/tinyrequests.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/tui/__init__.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/utils/__init__.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/utils/path.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/workflow_config.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/pyproject.toml +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/setup.cfg +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/tests/__init__.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/tests/cp/__init__.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/tests/fixtures.py +0 -0
- {latch-2.45.6 → latch-2.45.6.dev2}/tests/test_ls.py +0 -0
|
@@ -479,15 +479,19 @@ def custom_task(
|
|
|
479
479
|
)
|
|
480
480
|
|
|
481
481
|
|
|
482
|
-
def nextflow_runtime_task(cpu: int, memory: int):
|
|
482
|
+
def nextflow_runtime_task(cpu: int, memory: int, storage_gib: int = 50):
|
|
483
483
|
primary_container = V1Container(name="primary")
|
|
484
484
|
resources = V1ResourceRequirements(
|
|
485
485
|
requests={
|
|
486
486
|
"cpu": str(cpu),
|
|
487
487
|
"memory": f"{memory}Gi",
|
|
488
|
-
"ephemeral-storage": "
|
|
488
|
+
"ephemeral-storage": f"{storage_gib}Gi",
|
|
489
|
+
},
|
|
490
|
+
limits={
|
|
491
|
+
"cpu": str(cpu),
|
|
492
|
+
"memory": f"{memory}Gi",
|
|
493
|
+
"ephemeral-storage": f"{storage_gib}Gi",
|
|
489
494
|
},
|
|
490
|
-
limits={"cpu": str(cpu), "memory": f"{memory}Gi", "ephemeral-storage": "20Gi"},
|
|
491
495
|
)
|
|
492
496
|
primary_container.resources = resources
|
|
493
497
|
volume_mounts = [V1VolumeMount(mount_path="/nf-workdir", name="nextflow-workdir")]
|
|
@@ -26,7 +26,7 @@ from typing import (
|
|
|
26
26
|
|
|
27
27
|
import click
|
|
28
28
|
import yaml
|
|
29
|
-
from typing_extensions import
|
|
29
|
+
from typing_extensions import TypeAlias
|
|
30
30
|
|
|
31
31
|
from latch_cli.snakemake.config.utils import validate_snakemake_type
|
|
32
32
|
from latch_cli.utils import identifier_suffix_from_str
|
|
@@ -794,8 +794,38 @@ class NextflowMetadata(LatchMetadata):
|
|
|
794
794
|
"""
|
|
795
795
|
Directory to dump Nextflow logs
|
|
796
796
|
"""
|
|
797
|
+
about_page_path: Optional[Path] = None
|
|
798
|
+
"""
|
|
799
|
+
Path to a markdown file containing information about the pipeline - rendered in the About page.
|
|
800
|
+
"""
|
|
801
|
+
|
|
802
|
+
def validate(self):
|
|
803
|
+
if self.about_page_path is not None:
|
|
804
|
+
if not self.about_page_path.exists():
|
|
805
|
+
click.secho(
|
|
806
|
+
f"Path to about page documentation ({self.about_page_path})"
|
|
807
|
+
" doesn't exist.",
|
|
808
|
+
fg="red",
|
|
809
|
+
)
|
|
810
|
+
raise click.exceptions.Exit(1)
|
|
811
|
+
|
|
812
|
+
if not self.about_page_path.is_file():
|
|
813
|
+
click.secho(
|
|
814
|
+
f"About page documentation ({self.about_page_path}) must be a"
|
|
815
|
+
" file.",
|
|
816
|
+
fg="red",
|
|
817
|
+
)
|
|
818
|
+
raise click.exceptions.Exit(1)
|
|
819
|
+
|
|
820
|
+
@property
|
|
821
|
+
def dict(self):
|
|
822
|
+
d = super().dict
|
|
823
|
+
del d["__metadata__"]["about_page_path"]
|
|
824
|
+
return d
|
|
797
825
|
|
|
798
826
|
def __post_init__(self):
|
|
827
|
+
self.validate()
|
|
828
|
+
|
|
799
829
|
if self.name is None:
|
|
800
830
|
if self.display_name is None:
|
|
801
831
|
click.secho(
|
|
@@ -83,6 +83,7 @@ latch_cli/exceptions/traceback.py
|
|
|
83
83
|
latch_cli/nextflow/__init__.py
|
|
84
84
|
latch_cli/nextflow/config.py
|
|
85
85
|
latch_cli/nextflow/dependencies.py
|
|
86
|
+
latch_cli/nextflow/types.py
|
|
86
87
|
latch_cli/nextflow/utils.py
|
|
87
88
|
latch_cli/nextflow/workflow.py
|
|
88
89
|
latch_cli/services/__init__.py
|
|
@@ -14,6 +14,7 @@ import latch_cli.click_utils
|
|
|
14
14
|
from latch.ldata._transfer.progress import Progress as _Progress
|
|
15
15
|
from latch_cli.click_utils import EnumChoice
|
|
16
16
|
from latch_cli.exceptions.handler import CrashHandler
|
|
17
|
+
from latch_cli.nextflow.types import NextflowProcessExecutor
|
|
17
18
|
from latch_cli.services.cp.autocomplete import complete as cp_complete
|
|
18
19
|
from latch_cli.services.cp.autocomplete import remote_complete
|
|
19
20
|
from latch_cli.services.init.init import template_flag_to_option
|
|
@@ -346,8 +347,17 @@ def generate_metadata(
|
|
|
346
347
|
default=None,
|
|
347
348
|
help="Set execution profile for Nextflow workflow",
|
|
348
349
|
)
|
|
350
|
+
@click.option(
|
|
351
|
+
"--process-executor",
|
|
352
|
+
type=EnumChoice(NextflowProcessExecutor, case_sensitive=False),
|
|
353
|
+
default=None,
|
|
354
|
+
help="Set process executor for Nextflow workflow",
|
|
355
|
+
)
|
|
349
356
|
def generate_entrypoint(
|
|
350
|
-
pkg_root: Path,
|
|
357
|
+
pkg_root: Path,
|
|
358
|
+
nf_script: Path,
|
|
359
|
+
execution_profile: Optional[str],
|
|
360
|
+
process_executor: Optional[NextflowProcessExecutor],
|
|
351
361
|
):
|
|
352
362
|
"""Generate a `wf/entrypoint.py` file from a Nextflow workflow"""
|
|
353
363
|
|
|
@@ -384,6 +394,7 @@ def generate_entrypoint(
|
|
|
384
394
|
nf_script,
|
|
385
395
|
dest,
|
|
386
396
|
execution_profile=execution_profile,
|
|
397
|
+
process_executor=process_executor,
|
|
387
398
|
)
|
|
388
399
|
|
|
389
400
|
|
|
@@ -549,18 +560,23 @@ def execute(
|
|
|
549
560
|
help="Path to a nextflow script to register.",
|
|
550
561
|
)
|
|
551
562
|
@click.option(
|
|
552
|
-
"--
|
|
553
|
-
type=
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
help="Redownload external Nextflow dependencies",
|
|
563
|
+
"--nf-version",
|
|
564
|
+
type=str,
|
|
565
|
+
default=None,
|
|
566
|
+
help="Version of Nextflow runtime to use",
|
|
557
567
|
)
|
|
558
568
|
@click.option(
|
|
559
|
-
"--execution-profile",
|
|
569
|
+
"--nf-execution-profile",
|
|
560
570
|
type=str,
|
|
561
571
|
default=None,
|
|
562
572
|
help="Set execution profile for Nextflow workflow",
|
|
563
573
|
)
|
|
574
|
+
@click.option(
|
|
575
|
+
"--nf-process-executor",
|
|
576
|
+
type=EnumChoice(NextflowProcessExecutor, case_sensitive=False),
|
|
577
|
+
default=None,
|
|
578
|
+
help="Set process executor for Nextflow workflow",
|
|
579
|
+
)
|
|
564
580
|
@requires_login
|
|
565
581
|
def register(
|
|
566
582
|
pkg_root: str,
|
|
@@ -572,8 +588,9 @@ def register(
|
|
|
572
588
|
snakefile: Optional[Path],
|
|
573
589
|
cache_tasks: bool,
|
|
574
590
|
nf_script: Optional[Path],
|
|
575
|
-
|
|
576
|
-
|
|
591
|
+
nf_version: Optional[str],
|
|
592
|
+
nf_execution_profile: Optional[str],
|
|
593
|
+
nf_process_executor: Optional[NextflowProcessExecutor],
|
|
577
594
|
):
|
|
578
595
|
"""Register local workflow code to Latch.
|
|
579
596
|
|
|
@@ -585,6 +602,21 @@ def register(
|
|
|
585
602
|
crash_handler.message = "Unable to register workflow."
|
|
586
603
|
crash_handler.pkg_root = pkg_root
|
|
587
604
|
|
|
605
|
+
if nf_script is None and (
|
|
606
|
+
nf_version is not None
|
|
607
|
+
or nf_execution_profile is not None
|
|
608
|
+
or nf_process_executor is not None
|
|
609
|
+
):
|
|
610
|
+
click.secho(
|
|
611
|
+
dedent("""
|
|
612
|
+
Command Invalid:
|
|
613
|
+
--nf-version, --execution-profile, and --process-executor flags
|
|
614
|
+
are only valid when registering a Nextflow workflow.
|
|
615
|
+
"""),
|
|
616
|
+
fg="red",
|
|
617
|
+
)
|
|
618
|
+
raise click.exceptions.Exit(1)
|
|
619
|
+
|
|
588
620
|
from latch_cli.services.register import register
|
|
589
621
|
|
|
590
622
|
register(
|
|
@@ -595,8 +627,9 @@ def register(
|
|
|
595
627
|
open=open,
|
|
596
628
|
snakefile=snakefile,
|
|
597
629
|
nf_script=nf_script,
|
|
598
|
-
|
|
599
|
-
nf_execution_profile=
|
|
630
|
+
nf_version=nf_version,
|
|
631
|
+
nf_execution_profile=nf_execution_profile,
|
|
632
|
+
nf_process_executor=nf_process_executor,
|
|
600
633
|
progress_plain=(docker_progress == "auto" and not sys.stdout.isatty())
|
|
601
634
|
or docker_progress == "plain",
|
|
602
635
|
use_new_centromere=use_new_centromere,
|
|
@@ -5,7 +5,7 @@ from typing import Any, Optional, Type
|
|
|
5
5
|
|
|
6
6
|
import click
|
|
7
7
|
|
|
8
|
-
from latch.types.directory import LatchDir
|
|
8
|
+
from latch.types.directory import LatchDir, LatchOutputDir
|
|
9
9
|
from latch.types.file import LatchFile
|
|
10
10
|
from latch_cli.snakemake.config.utils import type_repr
|
|
11
11
|
from latch_cli.snakemake.utils import reindent
|
|
@@ -103,7 +103,7 @@ def generate_metadata(
|
|
|
103
103
|
else:
|
|
104
104
|
section_title = None
|
|
105
105
|
|
|
106
|
-
t = get_param_type(details)
|
|
106
|
+
t = LatchOutputDir if param == "outdir" else get_param_type(details)
|
|
107
107
|
if param not in required_params:
|
|
108
108
|
t = Optional[t]
|
|
109
109
|
|
|
@@ -140,7 +140,7 @@ def generate_metadata(
|
|
|
140
140
|
|
|
141
141
|
from latch.types.metadata import NextflowParameter
|
|
142
142
|
from latch.types.file import LatchFile
|
|
143
|
-
from latch.types.directory import LatchDir
|
|
143
|
+
from latch.types.directory import LatchDir, LatchOutputDir
|
|
144
144
|
|
|
145
145
|
# Import these into your `__init__.py` file:
|
|
146
146
|
#
|
|
@@ -3,6 +3,7 @@ from concurrent.futures import ProcessPoolExecutor
|
|
|
3
3
|
from ctypes import c_int
|
|
4
4
|
from multiprocessing.managers import SyncManager
|
|
5
5
|
from pathlib import Path
|
|
6
|
+
from typing import Optional
|
|
6
7
|
from urllib.parse import urljoin
|
|
7
8
|
|
|
8
9
|
import boto3
|
|
@@ -32,12 +33,12 @@ def _do_download(
|
|
|
32
33
|
click.echo(f"\x1b[{len(progress_str)}D", nl=False)
|
|
33
34
|
|
|
34
35
|
|
|
35
|
-
def download_nf_jars(pkg_root: Path):
|
|
36
|
+
def download_nf_jars(pkg_root: Path, nf_version: str):
|
|
36
37
|
s3_resource = boto3.resource("s3")
|
|
37
38
|
s3_resource.meta.client.meta.events.register("choose-signer.s3.*", disable_signing)
|
|
38
39
|
bucket = s3_resource.Bucket("latch-public")
|
|
39
40
|
|
|
40
|
-
subdir = "nextflow-v2/"
|
|
41
|
+
subdir = f"nextflow-v2/{nf_version}/"
|
|
41
42
|
objects = list(bucket.objects.filter(Prefix=f"{subdir}.nextflow/"))
|
|
42
43
|
|
|
43
44
|
click.secho(" Downloading Nextflow binaries: \x1b[?25l", italic=True, nl=False)
|
|
@@ -57,18 +58,42 @@ def download_nf_jars(pkg_root: Path):
|
|
|
57
58
|
click.secho("Done. \x1b[?25h", italic=True)
|
|
58
59
|
|
|
59
60
|
|
|
60
|
-
def
|
|
61
|
+
def _get_current_version(nf_version_path: Path):
|
|
62
|
+
if not nf_version_path.exists():
|
|
63
|
+
return None
|
|
64
|
+
|
|
65
|
+
with open(nf_version_path, "r") as f:
|
|
66
|
+
return f.read().strip()
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def ensure_nf_dependencies(pkg_root: Path, *, nf_version: Optional[str] = None):
|
|
70
|
+
nf_version_path = pkg_root / ".latch" / "nextflow_version"
|
|
61
71
|
nf_executable = pkg_root / ".latch" / "bin" / "nextflow"
|
|
62
72
|
nf_jars = pkg_root / ".latch" / ".nextflow"
|
|
63
73
|
|
|
64
|
-
if
|
|
74
|
+
if nf_version is None and nf_version_path.exists():
|
|
75
|
+
# rahul: if the version file exists locally and there
|
|
76
|
+
# was no request for update, don't do anything
|
|
77
|
+
return
|
|
78
|
+
|
|
79
|
+
if nf_version is None or nf_version.lower() == "latest":
|
|
80
|
+
res = tinyrequests.get(
|
|
81
|
+
"https://latch-public.s3.us-west-2.amazonaws.com/nextflow-v2/LATEST"
|
|
82
|
+
)
|
|
83
|
+
res.raise_for_status()
|
|
84
|
+
nf_version = res.content.decode("utf-8").strip()
|
|
85
|
+
|
|
86
|
+
current = _get_current_version(nf_version_path)
|
|
87
|
+
if current != nf_version:
|
|
88
|
+
click.secho(f"Updating Nextflow to version {nf_version}", fg="yellow")
|
|
89
|
+
nf_version_path.unlink(missing_ok=True)
|
|
65
90
|
nf_executable.unlink(missing_ok=True)
|
|
66
91
|
if nf_jars.exists():
|
|
67
92
|
shutil.rmtree(nf_jars)
|
|
68
93
|
|
|
69
94
|
if not nf_executable.exists():
|
|
70
95
|
res = tinyrequests.get(
|
|
71
|
-
"https://latch-public.s3.us-west-2.amazonaws.com/nextflow-v2/nextflow"
|
|
96
|
+
f"https://latch-public.s3.us-west-2.amazonaws.com/nextflow-v2/{nf_version}/nextflow"
|
|
72
97
|
)
|
|
73
98
|
nf_executable.parent.mkdir(parents=True, exist_ok=True)
|
|
74
99
|
|
|
@@ -76,4 +101,7 @@ def ensure_nf_dependencies(pkg_root: Path, *, force_redownload: bool = False):
|
|
|
76
101
|
nf_executable.chmod(0o700)
|
|
77
102
|
|
|
78
103
|
if not nf_jars.exists():
|
|
79
|
-
download_nf_jars(pkg_root)
|
|
104
|
+
download_nf_jars(pkg_root, nf_version)
|
|
105
|
+
|
|
106
|
+
with open(nf_version_path, "w") as f:
|
|
107
|
+
f.write(nf_version)
|
|
@@ -9,6 +9,7 @@ import click
|
|
|
9
9
|
import latch.types.metadata as metadata
|
|
10
10
|
from latch.types.directory import LatchDir, LatchOutputDir
|
|
11
11
|
from latch.types.file import LatchFile
|
|
12
|
+
from latch_cli.nextflow.types import NextflowProcessExecutor
|
|
12
13
|
from latch_cli.snakemake.config.utils import get_preamble, type_repr
|
|
13
14
|
from latch_cli.snakemake.utils import reindent
|
|
14
15
|
from latch_cli.utils import identifier_from_str, urljoins
|
|
@@ -37,6 +38,13 @@ from flytekit.core.annotation import FlyteAnnotation
|
|
|
37
38
|
|
|
38
39
|
import latch_metadata
|
|
39
40
|
|
|
41
|
+
from latch_cli.services.register.utils import import_module_by_path
|
|
42
|
+
|
|
43
|
+
meta = Path("latch_metadata") / "__init__.py"
|
|
44
|
+
if meta.exists():
|
|
45
|
+
import_module_by_path(meta)
|
|
46
|
+
|
|
47
|
+
|
|
40
48
|
@custom_task(cpu=0.25, memory=0.5, storage_gib=1)
|
|
41
49
|
def initialize() -> str:
|
|
42
50
|
token = os.environ.get("FLYTE_INTERNAL_EXECUTION_ID")
|
|
@@ -63,7 +71,7 @@ def initialize() -> str:
|
|
|
63
71
|
|
|
64
72
|
{samplesheet_funs}
|
|
65
73
|
|
|
66
|
-
@nextflow_runtime_task(cpu={cpu}, memory={memory})
|
|
74
|
+
@nextflow_runtime_task(cpu={cpu}, memory={memory}, storage_gib={storage_gib})
|
|
67
75
|
def nextflow_runtime(pvc_name: str, {param_signature}) -> None:
|
|
68
76
|
try:
|
|
69
77
|
shared_dir = Path("/nf-workdir")
|
|
@@ -151,6 +159,10 @@ def nextflow_runtime(pvc_name: str, {param_signature}) -> None:
|
|
|
151
159
|
|
|
152
160
|
@workflow(metadata._nextflow_metadata)
|
|
153
161
|
def {workflow_func_name}({param_signature_with_defaults}) -> None:
|
|
162
|
+
\"\"\"
|
|
163
|
+
{docstring}
|
|
164
|
+
\"\"\"
|
|
165
|
+
|
|
154
166
|
pvc_name: str = initialize()
|
|
155
167
|
nextflow_runtime(pvc_name=pvc_name, {param_args})
|
|
156
168
|
|
|
@@ -187,18 +199,23 @@ def get_flag(name: str, val: Any) -> List[str]:
|
|
|
187
199
|
return [flag, str(val)]
|
|
188
200
|
|
|
189
201
|
|
|
190
|
-
def generate_nextflow_config(
|
|
202
|
+
def generate_nextflow_config(
|
|
203
|
+
pkg_root: Path, process_executor: Optional[NextflowProcessExecutor]
|
|
204
|
+
):
|
|
205
|
+
if process_executor is None:
|
|
206
|
+
process_executor = NextflowProcessExecutor.k8s
|
|
207
|
+
|
|
191
208
|
config_path = Path(pkg_root) / "latch.config"
|
|
192
|
-
config_path.write_text(dedent("""\
|
|
193
|
-
process {
|
|
194
|
-
executor = '
|
|
195
|
-
}
|
|
209
|
+
config_path.write_text(dedent(f"""\
|
|
210
|
+
process {{
|
|
211
|
+
executor = '{process_executor.value}'
|
|
212
|
+
}}
|
|
196
213
|
|
|
197
|
-
aws {
|
|
198
|
-
client {
|
|
214
|
+
aws {{
|
|
215
|
+
client {{
|
|
199
216
|
anonymous = true
|
|
200
|
-
}
|
|
201
|
-
}
|
|
217
|
+
}}
|
|
218
|
+
}}
|
|
202
219
|
"""))
|
|
203
220
|
|
|
204
221
|
click.secho(f"Nextflow Latch config written to {config_path}", fg="green")
|
|
@@ -210,8 +227,9 @@ def generate_nextflow_workflow(
|
|
|
210
227
|
dest: Path,
|
|
211
228
|
*,
|
|
212
229
|
execution_profile: Optional[str] = None,
|
|
230
|
+
process_executor: Optional[NextflowProcessExecutor] = None,
|
|
213
231
|
):
|
|
214
|
-
generate_nextflow_config(pkg_root)
|
|
232
|
+
generate_nextflow_config(pkg_root, process_executor)
|
|
215
233
|
|
|
216
234
|
assert metadata._nextflow_metadata is not None
|
|
217
235
|
|
|
@@ -284,8 +302,19 @@ def generate_nextflow_workflow(
|
|
|
284
302
|
log_dir = metadata._nextflow_metadata.log_dir._raw_remote_path
|
|
285
303
|
log_dir = urljoins(log_dir, wf_name)
|
|
286
304
|
|
|
305
|
+
desc = f"Sample Description"
|
|
306
|
+
if metadata._nextflow_metadata.about_page_path is not None:
|
|
307
|
+
desc = metadata._nextflow_metadata.about_page_path.read_text()
|
|
308
|
+
|
|
309
|
+
display_name = wf_name
|
|
310
|
+
if metadata._nextflow_metadata.display_name is not None:
|
|
311
|
+
display_name = metadata._nextflow_metadata.display_name
|
|
312
|
+
|
|
313
|
+
docstring = f"{display_name}\n\n{desc}"
|
|
314
|
+
|
|
287
315
|
entrypoint = template.format(
|
|
288
316
|
workflow_func_name=identifier_from_str(wf_name),
|
|
317
|
+
docstring=reindent(docstring, 1),
|
|
289
318
|
nf_script=nf_script.resolve().relative_to(pkg_root.resolve()),
|
|
290
319
|
param_signature_with_defaults=", ".join(
|
|
291
320
|
no_defaults + [f"{name} = {val}" for name, val in defaults]
|
|
@@ -15,19 +15,19 @@ from flytekit.core.workflow import WorkflowBase
|
|
|
15
15
|
from scp import SCPClient
|
|
16
16
|
|
|
17
17
|
from latch.utils import current_workspace, get_workspaces
|
|
18
|
-
|
|
19
|
-
from
|
|
20
|
-
from
|
|
21
|
-
from
|
|
22
|
-
from
|
|
23
|
-
from .
|
|
24
|
-
from .utils import (
|
|
18
|
+
from latch_cli.centromere.ctx import _CentromereCtx
|
|
19
|
+
from latch_cli.centromere.utils import MaybeRemoteDir
|
|
20
|
+
from latch_cli.constants import latch_constants
|
|
21
|
+
from latch_cli.nextflow.types import NextflowProcessExecutor
|
|
22
|
+
from latch_cli.services.register.constants import ANSI_REGEX, MAX_LINES
|
|
23
|
+
from latch_cli.services.register.utils import (
|
|
25
24
|
DockerBuildLogItem,
|
|
26
25
|
build_image,
|
|
27
26
|
register_serialized_pkg,
|
|
28
27
|
serialize_pkg_in_container,
|
|
29
28
|
upload_image,
|
|
30
29
|
)
|
|
30
|
+
from latch_cli.utils import WorkflowType
|
|
31
31
|
|
|
32
32
|
|
|
33
33
|
def _delete_lines(num: int):
|
|
@@ -262,8 +262,9 @@ def register(
|
|
|
262
262
|
skip_confirmation: bool = False,
|
|
263
263
|
snakefile: Optional[Path] = None,
|
|
264
264
|
nf_script: Optional[Path] = None,
|
|
265
|
-
|
|
265
|
+
nf_version: Optional[str] = None,
|
|
266
266
|
nf_execution_profile: Optional[str] = None,
|
|
267
|
+
nf_process_executor: Optional[NextflowProcessExecutor] = None,
|
|
267
268
|
progress_plain: bool = False,
|
|
268
269
|
cache_tasks: bool = False,
|
|
269
270
|
use_new_centromere: bool = False,
|
|
@@ -411,9 +412,7 @@ def register(
|
|
|
411
412
|
from ...nextflow.dependencies import ensure_nf_dependencies
|
|
412
413
|
from ...nextflow.workflow import generate_nextflow_workflow
|
|
413
414
|
|
|
414
|
-
ensure_nf_dependencies(
|
|
415
|
-
ctx.pkg_root, force_redownload=nf_redownload_dependencies
|
|
416
|
-
)
|
|
415
|
+
ensure_nf_dependencies(ctx.pkg_root, nf_version=nf_version)
|
|
417
416
|
|
|
418
417
|
dest = ctx.pkg_root / "wf" / "entrypoint.py"
|
|
419
418
|
dest.parent.mkdir(exist_ok=True)
|
|
@@ -422,6 +421,7 @@ def register(
|
|
|
422
421
|
ctx.nf_script,
|
|
423
422
|
dest,
|
|
424
423
|
execution_profile=nf_execution_profile,
|
|
424
|
+
process_executor=nf_process_executor,
|
|
425
425
|
)
|
|
426
426
|
|
|
427
427
|
click.secho("\nInitializing registration", bold=True)
|
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
from dataclasses import
|
|
1
|
+
from dataclasses import fields, is_dataclass, make_dataclass
|
|
2
2
|
from enum import Enum
|
|
3
|
-
from textwrap import dedent
|
|
4
3
|
from typing import Any, Dict, List, Optional, Type, Union, get_args, get_origin
|
|
5
4
|
|
|
6
|
-
import click
|
|
7
5
|
from flytekit.core.annotation import FlyteAnnotation
|
|
8
|
-
from typing_extensions import Annotated, TypeAlias, TypeGuard
|
|
6
|
+
from typing_extensions import Annotated, TypeAlias, TypeGuard
|
|
9
7
|
|
|
10
8
|
from latch.types.directory import LatchDir
|
|
11
9
|
from latch.types.file import LatchFile
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/services/init/__pycache__/__init__.cpython-310.pyc
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/services/init/assemble_and_sort/system-requirements.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/services/init/example_snakemake/.latch/latch_entrypoint
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/services/init/example_snakemake/environment.yaml
RENAMED
|
File without changes
|
{latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/services/init/example_snakemake/latch_metadata.py
RENAMED
|
File without changes
|
{latch-2.45.6 → latch-2.45.6.dev2}/latch_cli/services/init/example_snakemake/scripts/plot-quals.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|