latch 2.41.3__tar.gz → 2.41.3.dev1__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.
Files changed (183) hide show
  1. {latch-2.41.3/latch.egg-info → latch-2.41.3.dev1}/PKG-INFO +1 -1
  2. {latch-2.41.3 → latch-2.41.3.dev1}/latch/ldata/type.py +7 -1
  3. {latch-2.41.3 → latch-2.41.3.dev1}/latch/resources/tasks.py +39 -0
  4. {latch-2.41.3 → latch-2.41.3.dev1}/latch/types/metadata.py +63 -18
  5. {latch-2.41.3 → latch-2.41.3.dev1/latch.egg-info}/PKG-INFO +1 -1
  6. {latch-2.41.3 → latch-2.41.3.dev1}/latch.egg-info/SOURCES.txt +14 -0
  7. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/centromere/ctx.py +41 -4
  8. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/docker_utils/__init__.py +16 -1
  9. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/main.py +46 -2
  10. latch-2.41.3.dev1/latch_cli/nextflow/dependencies.py +91 -0
  11. latch-2.41.3.dev1/latch_cli/nextflow/workflow.py +169 -0
  12. latch-2.41.3.dev1/latch_cli/services/init/__pycache__/__init__.cpython-310.pyc +0 -0
  13. latch-2.41.3.dev1/latch_cli/services/init/__pycache__/__init__.cpython-311.pyc +0 -0
  14. latch-2.41.3.dev1/latch_cli/services/init/__pycache__/__init__.cpython-38.pyc +0 -0
  15. latch-2.41.3.dev1/latch_cli/services/init/__pycache__/__init__.cpython-39.pyc +0 -0
  16. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/services/init/__pycache__/init.cpython-310.pyc +0 -0
  17. latch-2.41.3.dev1/latch_cli/services/init/__pycache__/init.cpython-311.pyc +0 -0
  18. latch-2.41.3.dev1/latch_cli/services/init/__pycache__/init.cpython-38.pyc +0 -0
  19. latch-2.41.3.dev1/latch_cli/services/init/__pycache__/init.cpython-39.pyc +0 -0
  20. latch-2.41.3.dev1/latch_cli/services/init/assemble_and_sort/__pycache__/__init__.cpython-310.pyc +0 -0
  21. latch-2.41.3.dev1/latch_cli/services/init/example_conda/__pycache__/__init__.cpython-310.pyc +0 -0
  22. latch-2.41.3.dev1/latch_cli/services/init/example_nf_integration/latch_metadata/__pycache__/__init__.cpython-311.pyc +0 -0
  23. latch-2.41.3.dev1/latch_cli/services/init/example_r/__pycache__/__init__.cpython-310.pyc +0 -0
  24. latch-2.41.3.dev1/latch_cli/services/init/template/__pycache__/__init__.cpython-310.pyc +0 -0
  25. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/services/register/register.py +66 -24
  26. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/snakemake/config/utils.py +20 -6
  27. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/utils/__init__.py +1 -0
  28. {latch-2.41.3 → latch-2.41.3.dev1}/setup.py +1 -1
  29. latch-2.41.3.dev1/tests/__init__.py +0 -0
  30. latch-2.41.3/latch_cli/services/init/__pycache__/__init__.cpython-310.pyc +0 -0
  31. {latch-2.41.3 → latch-2.41.3.dev1}/LICENSE +0 -0
  32. {latch-2.41.3 → latch-2.41.3.dev1}/MANIFEST.in +0 -0
  33. {latch-2.41.3 → latch-2.41.3.dev1}/README.md +0 -0
  34. {latch-2.41.3 → latch-2.41.3.dev1}/latch/__init__.py +0 -0
  35. {latch-2.41.3 → latch-2.41.3.dev1}/latch/account.py +0 -0
  36. {latch-2.41.3 → latch-2.41.3.dev1}/latch/executions.py +0 -0
  37. {latch-2.41.3 → latch-2.41.3.dev1}/latch/functions/__init__.py +0 -0
  38. {latch-2.41.3 → latch-2.41.3.dev1}/latch/functions/messages.py +0 -0
  39. {latch-2.41.3 → latch-2.41.3.dev1}/latch/functions/operators.py +0 -0
  40. {latch-2.41.3 → latch-2.41.3.dev1}/latch/functions/secrets.py +0 -0
  41. {latch-2.41.3 → latch-2.41.3.dev1}/latch/ldata/__init__.py +0 -0
  42. {latch-2.41.3 → latch-2.41.3.dev1}/latch/ldata/_transfer/__init__.py +0 -0
  43. {latch-2.41.3 → latch-2.41.3.dev1}/latch/ldata/_transfer/download.py +0 -0
  44. {latch-2.41.3 → latch-2.41.3.dev1}/latch/ldata/_transfer/manager.py +0 -0
  45. {latch-2.41.3 → latch-2.41.3.dev1}/latch/ldata/_transfer/node.py +0 -0
  46. {latch-2.41.3 → latch-2.41.3.dev1}/latch/ldata/_transfer/progress.py +0 -0
  47. {latch-2.41.3 → latch-2.41.3.dev1}/latch/ldata/_transfer/remote_copy.py +0 -0
  48. {latch-2.41.3 → latch-2.41.3.dev1}/latch/ldata/_transfer/throttle.py +0 -0
  49. {latch-2.41.3 → latch-2.41.3.dev1}/latch/ldata/_transfer/upload.py +0 -0
  50. {latch-2.41.3 → latch-2.41.3.dev1}/latch/ldata/_transfer/utils.py +0 -0
  51. {latch-2.41.3 → latch-2.41.3.dev1}/latch/ldata/path.py +0 -0
  52. {latch-2.41.3 → latch-2.41.3.dev1}/latch/registry/__init__.py +0 -0
  53. {latch-2.41.3 → latch-2.41.3.dev1}/latch/registry/project.py +0 -0
  54. {latch-2.41.3 → latch-2.41.3.dev1}/latch/registry/record.py +0 -0
  55. {latch-2.41.3 → latch-2.41.3.dev1}/latch/registry/table.py +0 -0
  56. {latch-2.41.3 → latch-2.41.3.dev1}/latch/registry/types.py +0 -0
  57. {latch-2.41.3 → latch-2.41.3.dev1}/latch/registry/upstream_types/__init__.py +0 -0
  58. {latch-2.41.3 → latch-2.41.3.dev1}/latch/registry/upstream_types/types.py +0 -0
  59. {latch-2.41.3 → latch-2.41.3.dev1}/latch/registry/upstream_types/values.py +0 -0
  60. {latch-2.41.3 → latch-2.41.3.dev1}/latch/registry/utils.py +0 -0
  61. {latch-2.41.3 → latch-2.41.3.dev1}/latch/resources/__init__.py +0 -0
  62. {latch-2.41.3 → latch-2.41.3.dev1}/latch/resources/conditional.py +0 -0
  63. {latch-2.41.3 → latch-2.41.3.dev1}/latch/resources/dynamic.py +0 -0
  64. {latch-2.41.3 → latch-2.41.3.dev1}/latch/resources/launch_plan.py +0 -0
  65. {latch-2.41.3 → latch-2.41.3.dev1}/latch/resources/map_tasks.py +0 -0
  66. {latch-2.41.3 → latch-2.41.3.dev1}/latch/resources/reference_workflow.py +0 -0
  67. {latch-2.41.3 → latch-2.41.3.dev1}/latch/resources/workflow.py +0 -0
  68. {latch-2.41.3 → latch-2.41.3.dev1}/latch/types/__init__.py +0 -0
  69. {latch-2.41.3 → latch-2.41.3.dev1}/latch/types/directory.py +0 -0
  70. {latch-2.41.3 → latch-2.41.3.dev1}/latch/types/file.py +0 -0
  71. {latch-2.41.3 → latch-2.41.3.dev1}/latch/types/glob.py +0 -0
  72. {latch-2.41.3 → latch-2.41.3.dev1}/latch/types/json.py +0 -0
  73. {latch-2.41.3 → latch-2.41.3.dev1}/latch/types/utils.py +0 -0
  74. {latch-2.41.3 → latch-2.41.3.dev1}/latch/utils.py +0 -0
  75. {latch-2.41.3 → latch-2.41.3.dev1}/latch/verified/__init__.py +0 -0
  76. {latch-2.41.3 → latch-2.41.3.dev1}/latch/verified/deseq2.py +0 -0
  77. {latch-2.41.3 → latch-2.41.3.dev1}/latch/verified/mafft.py +0 -0
  78. {latch-2.41.3 → latch-2.41.3.dev1}/latch/verified/pathway.py +0 -0
  79. {latch-2.41.3 → latch-2.41.3.dev1}/latch/verified/rnaseq.py +0 -0
  80. {latch-2.41.3 → latch-2.41.3.dev1}/latch/verified/trim_galore.py +0 -0
  81. {latch-2.41.3 → latch-2.41.3.dev1}/latch.egg-info/dependency_links.txt +0 -0
  82. {latch-2.41.3 → latch-2.41.3.dev1}/latch.egg-info/entry_points.txt +0 -0
  83. {latch-2.41.3 → latch-2.41.3.dev1}/latch.egg-info/requires.txt +0 -0
  84. {latch-2.41.3 → latch-2.41.3.dev1}/latch.egg-info/top_level.txt +0 -0
  85. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/__init__.py +0 -0
  86. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/auth/__init__.py +0 -0
  87. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/auth/csrf.py +0 -0
  88. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/auth/oauth2.py +0 -0
  89. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/auth/pkce.py +0 -0
  90. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/auth/utils.py +0 -0
  91. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/centromere/__init__.py +0 -0
  92. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/centromere/utils.py +0 -0
  93. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/click_utils.py +0 -0
  94. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/constants.py +0 -0
  95. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/exceptions/__init__.py +0 -0
  96. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/exceptions/cache.py +0 -0
  97. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/exceptions/errors.py +0 -0
  98. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/exceptions/handler.py +0 -0
  99. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/exceptions/traceback.py +0 -0
  100. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/menus.py +0 -0
  101. {latch-2.41.3/latch_cli/services/cp → latch-2.41.3.dev1/latch_cli/nextflow}/__init__.py +0 -0
  102. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/services/__init__.py +0 -0
  103. {latch-2.41.3/latch_cli/services/execute → latch-2.41.3.dev1/latch_cli/services/cp}/__init__.py +0 -0
  104. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/services/cp/autocomplete.py +0 -0
  105. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/services/cp/glob.py +0 -0
  106. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/services/cp/main.py +0 -0
  107. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/services/cp/utils.py +0 -0
  108. {latch-2.41.3/latch_cli/services/test_data → latch-2.41.3.dev1/latch_cli/services/execute}/__init__.py +0 -0
  109. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/services/execute/main.py +0 -0
  110. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/services/execute/utils.py +0 -0
  111. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/services/get.py +0 -0
  112. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/services/get_executions.py +0 -0
  113. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/services/get_params.py +0 -0
  114. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/services/init/__init__.py +0 -0
  115. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/services/init/assemble_and_sort/.env +0 -0
  116. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/services/init/assemble_and_sort/LICENSE +0 -0
  117. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/services/init/assemble_and_sort/README.md +0 -0
  118. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/services/init/assemble_and_sort/__init__.py +0 -0
  119. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/services/init/assemble_and_sort/assemble.py +0 -0
  120. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/services/init/assemble_and_sort/sort.py +0 -0
  121. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/services/init/assemble_and_sort/system-requirements.txt +0 -0
  122. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/services/init/common/.dockerignore +0 -0
  123. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/services/init/example_conda/__init__.py +0 -0
  124. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/services/init/example_conda/conda_task.py +0 -0
  125. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/services/init/example_conda/environment.yaml +0 -0
  126. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/services/init/example_docker/__init__.py +0 -0
  127. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/services/init/example_docker/task.py +0 -0
  128. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/services/init/example_nfcore/Dockerfile +0 -0
  129. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/services/init/example_nfcore/__init__.py +0 -0
  130. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/services/init/example_nfcore/task.py +0 -0
  131. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/services/init/example_r/__init__.py +0 -0
  132. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/services/init/example_r/environment.R +0 -0
  133. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/services/init/example_r/r_task.py +0 -0
  134. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/services/init/example_snakemake/.latch/latch_entrypoint +0 -0
  135. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/services/init/example_snakemake/Dockerfile +0 -0
  136. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/services/init/example_snakemake/Snakefile +0 -0
  137. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/services/init/example_snakemake/config.yaml +0 -0
  138. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/services/init/example_snakemake/environment.yaml +0 -0
  139. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/services/init/example_snakemake/latch_metadata.py +0 -0
  140. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/services/init/example_snakemake/scripts/plot-quals.py +0 -0
  141. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/services/init/example_snakemake/version +0 -0
  142. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/services/init/init.py +0 -0
  143. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/services/init/template/LICENSE +0 -0
  144. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/services/init/template/README.md +0 -0
  145. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/services/init/template/__init__.py +0 -0
  146. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/services/init/template/task.py +0 -0
  147. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/services/launch.py +0 -0
  148. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/services/local_dev.py +0 -0
  149. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/services/local_dev_old.py +0 -0
  150. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/services/login.py +0 -0
  151. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/services/ls.py +0 -0
  152. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/services/mkdir.py +0 -0
  153. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/services/move.py +0 -0
  154. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/services/preview.py +0 -0
  155. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/services/register/__init__.py +0 -0
  156. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/services/register/constants.py +0 -0
  157. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/services/register/utils.py +0 -0
  158. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/services/rm.py +0 -0
  159. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/services/stop_pod.py +0 -0
  160. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/services/sync.py +0 -0
  161. {latch-2.41.3/latch_cli/snakemake → latch-2.41.3.dev1/latch_cli/services/test_data}/__init__.py +0 -0
  162. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/services/test_data/ls.py +0 -0
  163. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/services/test_data/remove.py +0 -0
  164. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/services/test_data/upload.py +0 -0
  165. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/services/test_data/utils.py +0 -0
  166. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/services/workspace.py +0 -0
  167. {latch-2.41.3/latch_cli/snakemake/config → latch-2.41.3.dev1/latch_cli/snakemake}/__init__.py +0 -0
  168. {latch-2.41.3/latch_cli/tui → latch-2.41.3.dev1/latch_cli/snakemake/config}/__init__.py +0 -0
  169. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/snakemake/config/parser.py +0 -0
  170. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/snakemake/serialize.py +0 -0
  171. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/snakemake/serialize_utils.py +0 -0
  172. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/snakemake/single_task_snakemake.py +0 -0
  173. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/snakemake/utils.py +0 -0
  174. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/snakemake/workflow.py +0 -0
  175. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/tinyrequests.py +0 -0
  176. {latch-2.41.3/tests → latch-2.41.3.dev1/latch_cli/tui}/__init__.py +0 -0
  177. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/utils/path.py +0 -0
  178. {latch-2.41.3 → latch-2.41.3.dev1}/latch_cli/workflow_config.py +0 -0
  179. {latch-2.41.3 → latch-2.41.3.dev1}/pyproject.toml +0 -0
  180. {latch-2.41.3 → latch-2.41.3.dev1}/setup.cfg +0 -0
  181. {latch-2.41.3 → latch-2.41.3.dev1}/tests/cp/__init__.py +0 -0
  182. {latch-2.41.3 → latch-2.41.3.dev1}/tests/fixtures.py +0 -0
  183. {latch-2.41.3 → latch-2.41.3.dev1}/tests/test_ls.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: latch
3
- Version: 2.41.3
3
+ Version: 2.41.3.dev1
4
4
  Summary: The Latch SDK
5
5
  Author-email: kenny@latch.bio
6
6
  Classifier: Programming Language :: Python :: 3.8
@@ -1,8 +1,14 @@
1
1
  from enum import Enum
2
+ from typing import Optional
2
3
 
3
4
 
4
5
  class LatchPathError(RuntimeError):
5
- def __init__(self, message: str, remote_path: str = None, acc_id: str = None):
6
+ def __init__(
7
+ self,
8
+ message: str,
9
+ remote_path: Optional[str] = None,
10
+ acc_id: Optional[str] = None,
11
+ ):
6
12
  super().__init__(message)
7
13
  self.message = message
8
14
  self.remote_path = remote_path
@@ -33,9 +33,12 @@ from flytekit import task
33
33
  from flytekitplugins.pod import Pod
34
34
  from kubernetes.client.models import (
35
35
  V1Container,
36
+ V1PersistentVolumeClaimVolumeSource,
36
37
  V1PodSpec,
37
38
  V1ResourceRequirements,
38
39
  V1Toleration,
40
+ V1Volume,
41
+ V1VolumeMount,
39
42
  )
40
43
 
41
44
  from .dynamic import DynamicTaskConfig
@@ -179,6 +182,40 @@ def _get_small_pod() -> Pod:
179
182
  )
180
183
 
181
184
 
185
+ def _get_nextflow_runtime_pod() -> Pod:
186
+ primary_container = V1Container(name="primary")
187
+ resources = V1ResourceRequirements(
188
+ requests={"cpu": "2", "memory": "4Gi", "ephemeral-storage": "100Gi"},
189
+ limits={"cpu": "2", "memory": "4Gi", "ephemeral-storage": "100Gi"},
190
+ )
191
+ primary_container.resources = resources
192
+ volume_mounts = [V1VolumeMount(mount_path="/nf-workdir", name="nextflow-workdir")]
193
+ primary_container.volume_mounts = volume_mounts
194
+
195
+ return Pod(
196
+ annotations={
197
+ "io.kubernetes.cri-o.userns-mode": (
198
+ "private:uidmapping=0:1048576:65536;gidmapping=0:1048576:65536"
199
+ )
200
+ },
201
+ pod_spec=V1PodSpec(
202
+ runtime_class_name="sysbox-runc",
203
+ service_account_name="rahul-test",
204
+ containers=[primary_container],
205
+ volumes=[
206
+ V1Volume(
207
+ name="nextflow-workdir",
208
+ persistent_volume_claim=V1PersistentVolumeClaimVolumeSource(
209
+ # this value will be injected by flytepropeller
210
+ claim_name="nextflow-pvc-placeholder"
211
+ ),
212
+ )
213
+ ],
214
+ ),
215
+ primary_container_name="primary",
216
+ )
217
+
218
+
182
219
  large_gpu_task = functools.partial(task, task_config=_get_large_gpu_pod())
183
220
  """This task will get scheduled on a large GPU-enabled node.
184
221
 
@@ -314,6 +351,8 @@ small_task = functools.partial(task, task_config=_get_small_pod())
314
351
  - False
315
352
  """
316
353
 
354
+ nextflow_runtime_task = functools.partial(task, task_config=_get_nextflow_runtime_pod())
355
+
317
356
 
318
357
  def custom_memory_optimized_task(cpu: int, memory: int):
319
358
  """Returns a custom task configuration requesting
@@ -3,11 +3,24 @@ from dataclasses import Field, asdict, dataclass, field
3
3
  from enum import Enum
4
4
  from pathlib import Path
5
5
  from textwrap import indent
6
- from typing import Any, ClassVar, Dict, List, Optional, Protocol, Tuple, Type, Union
6
+ from typing import (
7
+ Any,
8
+ ClassVar,
9
+ Collection,
10
+ Dict,
11
+ Generic,
12
+ List,
13
+ Optional,
14
+ Protocol,
15
+ Tuple,
16
+ Type,
17
+ TypeVar,
18
+ Union,
19
+ )
7
20
 
8
21
  import click
9
22
  import yaml
10
- from typing_extensions import TypeAlias
23
+ from typing_extensions import Annotated, TypeAlias
11
24
 
12
25
  from latch_cli.snakemake.config.utils import validate_snakemake_type
13
26
  from latch_cli.utils import identifier_suffix_from_str
@@ -16,7 +29,6 @@ from .directory import LatchDir
16
29
  from .file import LatchFile
17
30
 
18
31
 
19
- @dataclass
20
32
  class LatchRule:
21
33
  """Class describing a rule that a parameter input must follow"""
22
34
 
@@ -388,31 +400,33 @@ class _IsDataclass(Protocol):
388
400
 
389
401
 
390
402
  ParameterType: TypeAlias = Union[
391
- Type[None],
392
- Type[int],
393
- Type[float],
394
- Type[str],
395
- Type[bool],
396
- Type[Enum],
397
- Type[_IsDataclass],
398
- Type[List["ParameterType"]],
399
- Type[LatchFile],
400
- Type[LatchDir],
403
+ None,
404
+ int,
405
+ float,
406
+ str,
407
+ bool,
408
+ LatchFile,
409
+ LatchDir,
410
+ Enum,
411
+ _IsDataclass,
412
+ Collection["ParameterType"],
401
413
  ]
402
414
 
403
415
 
416
+ T = TypeVar("T", bound=ParameterType)
417
+
418
+
404
419
  @dataclass
405
- class SnakemakeParameter(LatchParameter):
406
- type: Optional[ParameterType] = None
420
+ class SnakemakeParameter(Generic[T], LatchParameter):
421
+ type: Optional[Type[T]] = None
407
422
  """
408
423
  The python type of the parameter.
409
424
  """
410
- # todo(ayush): needs to be typed properly
411
- default: Optional[Any] = None
425
+ default: Optional[T] = None
412
426
 
413
427
 
414
428
  @dataclass
415
- class SnakemakeFileParameter(SnakemakeParameter):
429
+ class SnakemakeFileParameter(SnakemakeParameter[Union[LatchFile, LatchDir]]):
416
430
  """
417
431
  Deprecated: use `file_metadata` keyword in `SnakemakeMetadata` instead
418
432
  """
@@ -456,6 +470,19 @@ class SnakemakeFileMetadata:
456
470
  """
457
471
 
458
472
 
473
+ @dataclass
474
+ class NextflowParameter(Generic[T], LatchParameter):
475
+ type: Optional[Type[T]] = None
476
+ """
477
+ The python type of the parameter.
478
+ """
479
+ default: Optional[T] = None
480
+
481
+ def __post_init__(self):
482
+ if self.samplesheet is True:
483
+ self.type = Annotated[self.type, "samplesheet"]
484
+
485
+
459
486
  @dataclass
460
487
  class LatchMetadata:
461
488
  """Class for organizing workflow metadata
@@ -651,3 +678,21 @@ class SnakemakeMetadata(LatchMetadata):
651
678
 
652
679
 
653
680
  _snakemake_metadata: Optional[SnakemakeMetadata] = None
681
+
682
+
683
+ @dataclass
684
+ class NextflowMetadata(LatchMetadata):
685
+ name: Optional[str] = None
686
+ parameters: Dict[str, NextflowParameter] = field(default_factory=dict)
687
+
688
+ def __post_init__(self):
689
+ if self.name is None:
690
+ self.name = f"nf_{identifier_suffix_from_str(self.display_name.lower())}"
691
+ else:
692
+ self.name = identifier_suffix_from_str(self.name)
693
+
694
+ global _nextflow_metadata
695
+ _nextflow_metadata = self
696
+
697
+
698
+ _nextflow_metadata: Optional[NextflowMetadata] = None
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: latch
3
- Version: 2.41.3
3
+ Version: 2.41.3.dev1
4
4
  Summary: The Latch SDK
5
5
  Author-email: kenny@latch.bio
6
6
  Classifier: Programming Language :: Python :: 3.8
@@ -80,6 +80,9 @@ latch_cli/exceptions/cache.py
80
80
  latch_cli/exceptions/errors.py
81
81
  latch_cli/exceptions/handler.py
82
82
  latch_cli/exceptions/traceback.py
83
+ latch_cli/nextflow/__init__.py
84
+ latch_cli/nextflow/dependencies.py
85
+ latch_cli/nextflow/workflow.py
83
86
  latch_cli/services/__init__.py
84
87
  latch_cli/services/get.py
85
88
  latch_cli/services/get_executions.py
@@ -107,7 +110,13 @@ latch_cli/services/execute/utils.py
107
110
  latch_cli/services/init/__init__.py
108
111
  latch_cli/services/init/init.py
109
112
  latch_cli/services/init/__pycache__/__init__.cpython-310.pyc
113
+ latch_cli/services/init/__pycache__/__init__.cpython-311.pyc
114
+ latch_cli/services/init/__pycache__/__init__.cpython-38.pyc
115
+ latch_cli/services/init/__pycache__/__init__.cpython-39.pyc
110
116
  latch_cli/services/init/__pycache__/init.cpython-310.pyc
117
+ latch_cli/services/init/__pycache__/init.cpython-311.pyc
118
+ latch_cli/services/init/__pycache__/init.cpython-38.pyc
119
+ latch_cli/services/init/__pycache__/init.cpython-39.pyc
111
120
  latch_cli/services/init/assemble_and_sort/.env
112
121
  latch_cli/services/init/assemble_and_sort/LICENSE
113
122
  latch_cli/services/init/assemble_and_sort/README.md
@@ -115,18 +124,22 @@ latch_cli/services/init/assemble_and_sort/__init__.py
115
124
  latch_cli/services/init/assemble_and_sort/assemble.py
116
125
  latch_cli/services/init/assemble_and_sort/sort.py
117
126
  latch_cli/services/init/assemble_and_sort/system-requirements.txt
127
+ latch_cli/services/init/assemble_and_sort/__pycache__/__init__.cpython-310.pyc
118
128
  latch_cli/services/init/common/.dockerignore
119
129
  latch_cli/services/init/example_conda/__init__.py
120
130
  latch_cli/services/init/example_conda/conda_task.py
121
131
  latch_cli/services/init/example_conda/environment.yaml
132
+ latch_cli/services/init/example_conda/__pycache__/__init__.cpython-310.pyc
122
133
  latch_cli/services/init/example_docker/__init__.py
123
134
  latch_cli/services/init/example_docker/task.py
135
+ latch_cli/services/init/example_nf_integration/latch_metadata/__pycache__/__init__.cpython-311.pyc
124
136
  latch_cli/services/init/example_nfcore/Dockerfile
125
137
  latch_cli/services/init/example_nfcore/__init__.py
126
138
  latch_cli/services/init/example_nfcore/task.py
127
139
  latch_cli/services/init/example_r/__init__.py
128
140
  latch_cli/services/init/example_r/environment.R
129
141
  latch_cli/services/init/example_r/r_task.py
142
+ latch_cli/services/init/example_r/__pycache__/__init__.cpython-310.pyc
130
143
  latch_cli/services/init/example_snakemake/Dockerfile
131
144
  latch_cli/services/init/example_snakemake/Snakefile
132
145
  latch_cli/services/init/example_snakemake/config.yaml
@@ -139,6 +152,7 @@ latch_cli/services/init/template/LICENSE
139
152
  latch_cli/services/init/template/README.md
140
153
  latch_cli/services/init/template/__init__.py
141
154
  latch_cli/services/init/template/task.py
155
+ latch_cli/services/init/template/__pycache__/__init__.cpython-310.pyc
142
156
  latch_cli/services/register/__init__.py
143
157
  latch_cli/services/register/constants.py
144
158
  latch_cli/services/register/register.py
@@ -59,6 +59,7 @@ class _CentromereCtx:
59
59
  default_container: _Container
60
60
  workflow_type: WorkflowType
61
61
  snakefile: Optional[Path]
62
+ nf_script: Optional[Path]
62
63
 
63
64
  latch_register_api_url = config.api.workflow.register
64
65
  latch_image_api_url = config.api.workflow.upload_image
@@ -80,6 +81,7 @@ class _CentromereCtx:
80
81
  disable_auto_version: bool = False,
81
82
  remote: bool = False,
82
83
  snakefile: Optional[Path] = None,
84
+ nf_script: Optional[Path] = None,
83
85
  use_new_centromere: bool = False,
84
86
  ):
85
87
  self.use_new_centromere = use_new_centromere
@@ -93,13 +95,22 @@ class _CentromereCtx:
93
95
  self.dkr_repo = config.dkr_repo
94
96
  self.pkg_root = pkg_root.resolve()
95
97
 
96
- if snakefile is None:
97
- self.workflow_type = WorkflowType.latchbiosdk
98
- else:
98
+ if snakefile and nf_script:
99
+ raise ValueError(
100
+ "Cannot provide both a snakefile and nextflow script to the"
101
+ " register command."
102
+ )
103
+ if snakefile is not None:
99
104
  self.workflow_type = WorkflowType.snakemake
100
105
  self.snakefile = snakefile
106
+ elif nf_script is not None:
107
+ self.workflow_type = WorkflowType.nextflow
108
+ self.nf_script = nf_script
109
+ else:
110
+ self.workflow_type = WorkflowType.latchbiosdk
101
111
 
102
112
  self.container_map: Dict[str, _Container] = {}
113
+
103
114
  if self.workflow_type == WorkflowType.latchbiosdk:
104
115
  _import_flyte_objects([self.pkg_root])
105
116
  for entity in FlyteEntities.entities:
@@ -126,7 +137,7 @@ class _CentromereCtx:
126
137
  fg="red",
127
138
  )
128
139
  raise click.exceptions.Exit(1)
129
- else:
140
+ elif self.workflow_type == WorkflowType.snakemake:
130
141
  assert snakefile is not None
131
142
 
132
143
  import latch.types.metadata as metadata
@@ -231,6 +242,32 @@ class _CentromereCtx:
231
242
  # todo(kenny): support per container task and custom workflow
232
243
  # name for snakemake
233
244
  self.workflow_name = f"{metadata._snakemake_metadata.name}_jit_register"
245
+ else:
246
+ assert nf_script is not None
247
+
248
+ import latch.types.metadata as metadata
249
+
250
+ from ..services.register.utils import import_module_by_path
251
+
252
+ meta = pkg_root / "latch_metadata" / "__init__.py"
253
+ if meta.exists():
254
+ click.echo(f"Using metadata file {click.style(meta, italic=True)}")
255
+ import_module_by_path(meta)
256
+
257
+ if metadata._nextflow_metadata is None:
258
+ click.secho(
259
+ dedent("""
260
+ Failed to register Nextflow workflow.
261
+ Make sure the project root contains a `wf/__init__.py`
262
+ with a `NextflowMetadata` object defined.
263
+ """),
264
+ fg="red",
265
+ )
266
+ raise click.exceptions.Exit(1)
267
+
268
+ self.workflow_name = metadata._nextflow_metadata.name
269
+
270
+ assert self.workflow_name is not None
234
271
 
235
272
  version_file = self.pkg_root / "version"
236
273
  try:
@@ -39,7 +39,7 @@ def get_prologue(
39
39
  library_name = '"latch[snakemake]"'
40
40
  else:
41
41
  library_name = "latch"
42
- return [
42
+ directives = [
43
43
  "# DO NOT CHANGE",
44
44
  f"from {config.base_image}",
45
45
  "",
@@ -68,6 +68,11 @@ def get_prologue(
68
68
  f"run pip install {library_name}=={config.latch_version}",
69
69
  "run mkdir /opt/latch",
70
70
  ]
71
+ if wf_type == WorkflowType.nextflow:
72
+ directives.append(
73
+ "run apt-get update && apt-get install -y default-jre-headless"
74
+ )
75
+ return directives
71
76
 
72
77
 
73
78
  def get_epilogue(wf_type: WorkflowType = WorkflowType.latchbiosdk) -> List[str]:
@@ -78,8 +83,18 @@ def get_epilogue(wf_type: WorkflowType = WorkflowType.latchbiosdk) -> List[str]:
78
83
  "",
79
84
  "# Latch snakemake workflow entrypoint",
80
85
  "# DO NOT CHANGE",
86
+ "",
81
87
  "copy .latch/snakemake_jit_entrypoint.py /root/snakemake_jit_entrypoint.py",
82
88
  ]
89
+ elif wf_type == WorkflowType.nextflow:
90
+ cmds += [
91
+ "",
92
+ "# Latch nextflow workflow entrypoint",
93
+ "# DO NOT CHANGE",
94
+ "",
95
+ "copy .latch/bin/nextflow /root/nextflow",
96
+ "copy .latch/.nextflow /root/.nextflow",
97
+ ]
83
98
 
84
99
  cmds += [
85
100
  "",
@@ -192,7 +192,15 @@ def init(
192
192
  type=bool,
193
193
  help="Generate a Dockerfile with arguments needed for Snakemake compatability",
194
194
  )
195
- def dockerfile(pkg_root: str, snakemake: bool = False):
195
+ @click.option(
196
+ "-n",
197
+ "--nextflow",
198
+ is_flag=True,
199
+ default=False,
200
+ type=bool,
201
+ help="Generate a Dockerfile with arguments needed for Nextflow compatability",
202
+ )
203
+ def dockerfile(pkg_root: str, snakemake: bool = False, nextflow: bool = False):
196
204
  """Generates a user editable dockerfile for a workflow and saves under `pkg_root/Dockerfile`.
197
205
 
198
206
  Visit docs.latch.bio to learn more.
@@ -201,6 +209,14 @@ def dockerfile(pkg_root: str, snakemake: bool = False):
201
209
  crash_handler.message = "Failed to generate Dockerfile."
202
210
  crash_handler.pkg_root = pkg_root
203
211
 
212
+ if snakemake is True and nextflow is True:
213
+ click.secho(
214
+ f"Please specify only one workflow type to generate metadata for. Use"
215
+ f" either `--snakemake` or `--nextflow`.",
216
+ fg="red",
217
+ )
218
+ raise click.exceptions.Exit(1)
219
+
204
220
  from latch_cli.docker_utils import generate_dockerfile
205
221
 
206
222
  source = Path(pkg_root)
@@ -209,11 +225,14 @@ def dockerfile(pkg_root: str, snakemake: bool = False):
209
225
  f"Dockerfile already exists at `{dest}`. Overwrite?"
210
226
  ):
211
227
  return
228
+
212
229
  workflow_type = WorkflowType.latchbiosdk
213
230
  if snakemake is True:
214
231
  workflow_type = WorkflowType.snakemake
215
- generate_dockerfile(source, dest, wf_type=workflow_type)
232
+ elif nextflow is True:
233
+ workflow_type = WorkflowType.nextflow
216
234
 
235
+ generate_dockerfile(source, dest, wf_type=workflow_type)
217
236
  click.secho(f"Successfully generated dockerfile `{dest}`", fg="green")
218
237
 
219
238
 
@@ -412,6 +431,25 @@ def execute(
412
431
  " provided."
413
432
  ),
414
433
  )
434
+ @click.option(
435
+ "--nf-script",
436
+ type=click.Path(exists=True, dir_okay=False, path_type=Path),
437
+ default=None,
438
+ help="Path to a nextflow script to register.",
439
+ )
440
+ @click.option(
441
+ "--redownload-dependencies",
442
+ type=bool,
443
+ is_flag=True,
444
+ default=False,
445
+ help="Redownload external Nextflow dependencies",
446
+ )
447
+ @click.option(
448
+ "--execution-profile",
449
+ type=str,
450
+ default=None,
451
+ help="Set execution profile for Nextflow workflow",
452
+ )
415
453
  @requires_login
416
454
  def register(
417
455
  pkg_root: str,
@@ -422,6 +460,9 @@ def register(
422
460
  open: bool,
423
461
  snakefile: Optional[Path],
424
462
  cache_tasks: bool,
463
+ nf_script: Optional[Path],
464
+ redownload_dependencies: bool,
465
+ execution_profile: Optional[str],
425
466
  ):
426
467
  """Register local workflow code to Latch.
427
468
 
@@ -442,6 +483,9 @@ def register(
442
483
  skip_confirmation=yes,
443
484
  open=open,
444
485
  snakefile=snakefile,
486
+ nf_script=nf_script,
487
+ nf_redownload_dependencies=redownload_dependencies,
488
+ nf_execution_profile=execution_profile,
445
489
  progress_plain=(docker_progress == "auto" and not sys.stdout.isatty())
446
490
  or docker_progress == "plain",
447
491
  use_new_centromere=use_new_centromere,
@@ -0,0 +1,91 @@
1
+ import shutil
2
+ import subprocess
3
+ from concurrent.futures import ProcessPoolExecutor
4
+ from ctypes import c_int
5
+ from multiprocessing.managers import SyncManager
6
+ from pathlib import Path
7
+ from urllib.parse import urljoin
8
+
9
+ import boto3
10
+ import click
11
+
12
+ from latch_cli import tinyrequests
13
+ from latch_cli.utils import dedent
14
+
15
+
16
+ def _do_download(
17
+ url: str,
18
+ output_path: Path,
19
+ total_count: int,
20
+ counter,
21
+ lock,
22
+ ): # todo(ayush): figure out the right type annotation for counter/lock
23
+ res = tinyrequests.get(url)
24
+ output_path.parent.mkdir(parents=True, exist_ok=True)
25
+ output_path.write_bytes(res.content)
26
+
27
+ with lock:
28
+ counter.value += 1
29
+ progress_str = f"{counter.value}/{total_count}"
30
+
31
+ click.echo("\x1b[0K", nl=False)
32
+ click.secho(progress_str, dim=True, italic=True, nl=False)
33
+ click.echo(f"\x1b[{len(progress_str)}D", nl=False)
34
+
35
+
36
+ def download_nf_jars(pkg_root: Path):
37
+ s3_resource = boto3.resource("s3")
38
+ bucket = s3_resource.Bucket("latch-public")
39
+
40
+ objects = list(bucket.objects.filter(Prefix=".nextflow/"))
41
+
42
+ click.secho(" Downloading Nextflow binaries: \x1b[?25l", italic=True, nl=False)
43
+
44
+ with SyncManager() as man:
45
+ counter = man.Value(c_int, 0)
46
+ lock = man.Lock()
47
+ with ProcessPoolExecutor() as exec:
48
+ for obj in objects:
49
+ url = urljoin(
50
+ "https://latch-public.s3.us-west-2.amazonaws.com/", obj.key
51
+ )
52
+ obj_path = pkg_root / ".latch" / obj.key
53
+
54
+ exec.submit(_do_download, url, obj_path, len(objects), counter, lock)
55
+
56
+ click.echo("\x1b[0K", nl=False)
57
+ click.secho("Done. \x1b[?25h", italic=True)
58
+
59
+
60
+ def ensure_nf_dependencies(pkg_root: Path, *, force_redownload: bool = False):
61
+ try:
62
+ subprocess.run(["java", "--version"], check=True, capture_output=True)
63
+ except (subprocess.CalledProcessError, FileNotFoundError) as e:
64
+ click.secho(
65
+ dedent("""\
66
+ Java is not installed - this is a requirement to run Nextflow.
67
+ Please install Java and try again.
68
+ """),
69
+ fg="red",
70
+ )
71
+ raise click.exceptions.Exit(1) from e
72
+
73
+ nf_executable = pkg_root / ".latch" / "bin" / "nextflow"
74
+ nf_jars = pkg_root / ".latch" / ".nextflow"
75
+
76
+ if force_redownload:
77
+ nf_executable.unlink(missing_ok=True)
78
+ if nf_jars.exists():
79
+ shutil.rmtree(nf_jars)
80
+
81
+ if not nf_executable.exists():
82
+ res = tinyrequests.get(
83
+ "https://latch-public.s3.us-west-2.amazonaws.com/nextflow"
84
+ )
85
+ nf_executable.parent.mkdir(parents=True, exist_ok=True)
86
+
87
+ nf_executable.write_bytes(res.content)
88
+ nf_executable.chmod(0o700)
89
+
90
+ if not nf_jars.exists():
91
+ download_nf_jars(pkg_root)