latch 2.41.3__tar.gz → 2.41.3.dev0__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 (180) hide show
  1. {latch-2.41.3/latch.egg-info → latch-2.41.3.dev0}/PKG-INFO +1 -1
  2. {latch-2.41.3 → latch-2.41.3.dev0}/latch/ldata/type.py +7 -1
  3. {latch-2.41.3 → latch-2.41.3.dev0}/latch/resources/tasks.py +39 -0
  4. {latch-2.41.3 → latch-2.41.3.dev0}/latch/types/metadata.py +63 -18
  5. {latch-2.41.3 → latch-2.41.3.dev0/latch.egg-info}/PKG-INFO +1 -1
  6. {latch-2.41.3 → latch-2.41.3.dev0}/latch.egg-info/SOURCES.txt +11 -0
  7. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/centromere/ctx.py +41 -4
  8. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/docker_utils/__init__.py +16 -1
  9. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/main.py +46 -2
  10. latch-2.41.3.dev0/latch_cli/services/init/__pycache__/__init__.cpython-310.pyc +0 -0
  11. latch-2.41.3.dev0/latch_cli/services/init/__pycache__/__init__.cpython-311.pyc +0 -0
  12. latch-2.41.3.dev0/latch_cli/services/init/__pycache__/__init__.cpython-38.pyc +0 -0
  13. latch-2.41.3.dev0/latch_cli/services/init/__pycache__/__init__.cpython-39.pyc +0 -0
  14. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/services/init/__pycache__/init.cpython-310.pyc +0 -0
  15. latch-2.41.3.dev0/latch_cli/services/init/__pycache__/init.cpython-311.pyc +0 -0
  16. latch-2.41.3.dev0/latch_cli/services/init/__pycache__/init.cpython-38.pyc +0 -0
  17. latch-2.41.3.dev0/latch_cli/services/init/__pycache__/init.cpython-39.pyc +0 -0
  18. latch-2.41.3.dev0/latch_cli/services/init/assemble_and_sort/__pycache__/__init__.cpython-310.pyc +0 -0
  19. latch-2.41.3.dev0/latch_cli/services/init/example_conda/__pycache__/__init__.cpython-310.pyc +0 -0
  20. latch-2.41.3.dev0/latch_cli/services/init/example_nf_integration/latch_metadata/__pycache__/__init__.cpython-311.pyc +0 -0
  21. latch-2.41.3.dev0/latch_cli/services/init/example_r/__pycache__/__init__.cpython-310.pyc +0 -0
  22. latch-2.41.3.dev0/latch_cli/services/init/template/__pycache__/__init__.cpython-310.pyc +0 -0
  23. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/services/register/register.py +66 -24
  24. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/utils/__init__.py +1 -0
  25. {latch-2.41.3 → latch-2.41.3.dev0}/setup.py +1 -1
  26. latch-2.41.3/latch_cli/services/init/__pycache__/__init__.cpython-310.pyc +0 -0
  27. {latch-2.41.3 → latch-2.41.3.dev0}/LICENSE +0 -0
  28. {latch-2.41.3 → latch-2.41.3.dev0}/MANIFEST.in +0 -0
  29. {latch-2.41.3 → latch-2.41.3.dev0}/README.md +0 -0
  30. {latch-2.41.3 → latch-2.41.3.dev0}/latch/__init__.py +0 -0
  31. {latch-2.41.3 → latch-2.41.3.dev0}/latch/account.py +0 -0
  32. {latch-2.41.3 → latch-2.41.3.dev0}/latch/executions.py +0 -0
  33. {latch-2.41.3 → latch-2.41.3.dev0}/latch/functions/__init__.py +0 -0
  34. {latch-2.41.3 → latch-2.41.3.dev0}/latch/functions/messages.py +0 -0
  35. {latch-2.41.3 → latch-2.41.3.dev0}/latch/functions/operators.py +0 -0
  36. {latch-2.41.3 → latch-2.41.3.dev0}/latch/functions/secrets.py +0 -0
  37. {latch-2.41.3 → latch-2.41.3.dev0}/latch/ldata/__init__.py +0 -0
  38. {latch-2.41.3 → latch-2.41.3.dev0}/latch/ldata/_transfer/__init__.py +0 -0
  39. {latch-2.41.3 → latch-2.41.3.dev0}/latch/ldata/_transfer/download.py +0 -0
  40. {latch-2.41.3 → latch-2.41.3.dev0}/latch/ldata/_transfer/manager.py +0 -0
  41. {latch-2.41.3 → latch-2.41.3.dev0}/latch/ldata/_transfer/node.py +0 -0
  42. {latch-2.41.3 → latch-2.41.3.dev0}/latch/ldata/_transfer/progress.py +0 -0
  43. {latch-2.41.3 → latch-2.41.3.dev0}/latch/ldata/_transfer/remote_copy.py +0 -0
  44. {latch-2.41.3 → latch-2.41.3.dev0}/latch/ldata/_transfer/throttle.py +0 -0
  45. {latch-2.41.3 → latch-2.41.3.dev0}/latch/ldata/_transfer/upload.py +0 -0
  46. {latch-2.41.3 → latch-2.41.3.dev0}/latch/ldata/_transfer/utils.py +0 -0
  47. {latch-2.41.3 → latch-2.41.3.dev0}/latch/ldata/path.py +0 -0
  48. {latch-2.41.3 → latch-2.41.3.dev0}/latch/registry/__init__.py +0 -0
  49. {latch-2.41.3 → latch-2.41.3.dev0}/latch/registry/project.py +0 -0
  50. {latch-2.41.3 → latch-2.41.3.dev0}/latch/registry/record.py +0 -0
  51. {latch-2.41.3 → latch-2.41.3.dev0}/latch/registry/table.py +0 -0
  52. {latch-2.41.3 → latch-2.41.3.dev0}/latch/registry/types.py +0 -0
  53. {latch-2.41.3 → latch-2.41.3.dev0}/latch/registry/upstream_types/__init__.py +0 -0
  54. {latch-2.41.3 → latch-2.41.3.dev0}/latch/registry/upstream_types/types.py +0 -0
  55. {latch-2.41.3 → latch-2.41.3.dev0}/latch/registry/upstream_types/values.py +0 -0
  56. {latch-2.41.3 → latch-2.41.3.dev0}/latch/registry/utils.py +0 -0
  57. {latch-2.41.3 → latch-2.41.3.dev0}/latch/resources/__init__.py +0 -0
  58. {latch-2.41.3 → latch-2.41.3.dev0}/latch/resources/conditional.py +0 -0
  59. {latch-2.41.3 → latch-2.41.3.dev0}/latch/resources/dynamic.py +0 -0
  60. {latch-2.41.3 → latch-2.41.3.dev0}/latch/resources/launch_plan.py +0 -0
  61. {latch-2.41.3 → latch-2.41.3.dev0}/latch/resources/map_tasks.py +0 -0
  62. {latch-2.41.3 → latch-2.41.3.dev0}/latch/resources/reference_workflow.py +0 -0
  63. {latch-2.41.3 → latch-2.41.3.dev0}/latch/resources/workflow.py +0 -0
  64. {latch-2.41.3 → latch-2.41.3.dev0}/latch/types/__init__.py +0 -0
  65. {latch-2.41.3 → latch-2.41.3.dev0}/latch/types/directory.py +0 -0
  66. {latch-2.41.3 → latch-2.41.3.dev0}/latch/types/file.py +0 -0
  67. {latch-2.41.3 → latch-2.41.3.dev0}/latch/types/glob.py +0 -0
  68. {latch-2.41.3 → latch-2.41.3.dev0}/latch/types/json.py +0 -0
  69. {latch-2.41.3 → latch-2.41.3.dev0}/latch/types/utils.py +0 -0
  70. {latch-2.41.3 → latch-2.41.3.dev0}/latch/utils.py +0 -0
  71. {latch-2.41.3 → latch-2.41.3.dev0}/latch/verified/__init__.py +0 -0
  72. {latch-2.41.3 → latch-2.41.3.dev0}/latch/verified/deseq2.py +0 -0
  73. {latch-2.41.3 → latch-2.41.3.dev0}/latch/verified/mafft.py +0 -0
  74. {latch-2.41.3 → latch-2.41.3.dev0}/latch/verified/pathway.py +0 -0
  75. {latch-2.41.3 → latch-2.41.3.dev0}/latch/verified/rnaseq.py +0 -0
  76. {latch-2.41.3 → latch-2.41.3.dev0}/latch/verified/trim_galore.py +0 -0
  77. {latch-2.41.3 → latch-2.41.3.dev0}/latch.egg-info/dependency_links.txt +0 -0
  78. {latch-2.41.3 → latch-2.41.3.dev0}/latch.egg-info/entry_points.txt +0 -0
  79. {latch-2.41.3 → latch-2.41.3.dev0}/latch.egg-info/requires.txt +0 -0
  80. {latch-2.41.3 → latch-2.41.3.dev0}/latch.egg-info/top_level.txt +0 -0
  81. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/__init__.py +0 -0
  82. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/auth/__init__.py +0 -0
  83. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/auth/csrf.py +0 -0
  84. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/auth/oauth2.py +0 -0
  85. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/auth/pkce.py +0 -0
  86. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/auth/utils.py +0 -0
  87. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/centromere/__init__.py +0 -0
  88. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/centromere/utils.py +0 -0
  89. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/click_utils.py +0 -0
  90. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/constants.py +0 -0
  91. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/exceptions/__init__.py +0 -0
  92. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/exceptions/cache.py +0 -0
  93. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/exceptions/errors.py +0 -0
  94. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/exceptions/handler.py +0 -0
  95. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/exceptions/traceback.py +0 -0
  96. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/menus.py +0 -0
  97. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/services/__init__.py +0 -0
  98. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/services/cp/__init__.py +0 -0
  99. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/services/cp/autocomplete.py +0 -0
  100. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/services/cp/glob.py +0 -0
  101. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/services/cp/main.py +0 -0
  102. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/services/cp/utils.py +0 -0
  103. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/services/execute/__init__.py +0 -0
  104. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/services/execute/main.py +0 -0
  105. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/services/execute/utils.py +0 -0
  106. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/services/get.py +0 -0
  107. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/services/get_executions.py +0 -0
  108. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/services/get_params.py +0 -0
  109. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/services/init/__init__.py +0 -0
  110. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/services/init/assemble_and_sort/.env +0 -0
  111. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/services/init/assemble_and_sort/LICENSE +0 -0
  112. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/services/init/assemble_and_sort/README.md +0 -0
  113. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/services/init/assemble_and_sort/__init__.py +0 -0
  114. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/services/init/assemble_and_sort/assemble.py +0 -0
  115. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/services/init/assemble_and_sort/sort.py +0 -0
  116. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/services/init/assemble_and_sort/system-requirements.txt +0 -0
  117. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/services/init/common/.dockerignore +0 -0
  118. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/services/init/example_conda/__init__.py +0 -0
  119. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/services/init/example_conda/conda_task.py +0 -0
  120. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/services/init/example_conda/environment.yaml +0 -0
  121. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/services/init/example_docker/__init__.py +0 -0
  122. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/services/init/example_docker/task.py +0 -0
  123. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/services/init/example_nfcore/Dockerfile +0 -0
  124. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/services/init/example_nfcore/__init__.py +0 -0
  125. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/services/init/example_nfcore/task.py +0 -0
  126. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/services/init/example_r/__init__.py +0 -0
  127. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/services/init/example_r/environment.R +0 -0
  128. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/services/init/example_r/r_task.py +0 -0
  129. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/services/init/example_snakemake/.latch/latch_entrypoint +0 -0
  130. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/services/init/example_snakemake/Dockerfile +0 -0
  131. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/services/init/example_snakemake/Snakefile +0 -0
  132. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/services/init/example_snakemake/config.yaml +0 -0
  133. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/services/init/example_snakemake/environment.yaml +0 -0
  134. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/services/init/example_snakemake/latch_metadata.py +0 -0
  135. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/services/init/example_snakemake/scripts/plot-quals.py +0 -0
  136. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/services/init/example_snakemake/version +0 -0
  137. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/services/init/init.py +0 -0
  138. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/services/init/template/LICENSE +0 -0
  139. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/services/init/template/README.md +0 -0
  140. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/services/init/template/__init__.py +0 -0
  141. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/services/init/template/task.py +0 -0
  142. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/services/launch.py +0 -0
  143. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/services/local_dev.py +0 -0
  144. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/services/local_dev_old.py +0 -0
  145. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/services/login.py +0 -0
  146. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/services/ls.py +0 -0
  147. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/services/mkdir.py +0 -0
  148. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/services/move.py +0 -0
  149. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/services/preview.py +0 -0
  150. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/services/register/__init__.py +0 -0
  151. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/services/register/constants.py +0 -0
  152. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/services/register/utils.py +0 -0
  153. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/services/rm.py +0 -0
  154. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/services/stop_pod.py +0 -0
  155. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/services/sync.py +0 -0
  156. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/services/test_data/__init__.py +0 -0
  157. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/services/test_data/ls.py +0 -0
  158. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/services/test_data/remove.py +0 -0
  159. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/services/test_data/upload.py +0 -0
  160. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/services/test_data/utils.py +0 -0
  161. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/services/workspace.py +0 -0
  162. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/snakemake/__init__.py +0 -0
  163. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/snakemake/config/__init__.py +0 -0
  164. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/snakemake/config/parser.py +0 -0
  165. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/snakemake/config/utils.py +0 -0
  166. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/snakemake/serialize.py +0 -0
  167. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/snakemake/serialize_utils.py +0 -0
  168. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/snakemake/single_task_snakemake.py +0 -0
  169. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/snakemake/utils.py +0 -0
  170. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/snakemake/workflow.py +0 -0
  171. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/tinyrequests.py +0 -0
  172. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/tui/__init__.py +0 -0
  173. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/utils/path.py +0 -0
  174. {latch-2.41.3 → latch-2.41.3.dev0}/latch_cli/workflow_config.py +0 -0
  175. {latch-2.41.3 → latch-2.41.3.dev0}/pyproject.toml +0 -0
  176. {latch-2.41.3 → latch-2.41.3.dev0}/setup.cfg +0 -0
  177. {latch-2.41.3 → latch-2.41.3.dev0}/tests/__init__.py +0 -0
  178. {latch-2.41.3 → latch-2.41.3.dev0}/tests/cp/__init__.py +0 -0
  179. {latch-2.41.3 → latch-2.41.3.dev0}/tests/fixtures.py +0 -0
  180. {latch-2.41.3 → latch-2.41.3.dev0}/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.dev0
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.dev0
4
4
  Summary: The Latch SDK
5
5
  Author-email: kenny@latch.bio
6
6
  Classifier: Programming Language :: Python :: 3.8
@@ -107,7 +107,13 @@ latch_cli/services/execute/utils.py
107
107
  latch_cli/services/init/__init__.py
108
108
  latch_cli/services/init/init.py
109
109
  latch_cli/services/init/__pycache__/__init__.cpython-310.pyc
110
+ latch_cli/services/init/__pycache__/__init__.cpython-311.pyc
111
+ latch_cli/services/init/__pycache__/__init__.cpython-38.pyc
112
+ latch_cli/services/init/__pycache__/__init__.cpython-39.pyc
110
113
  latch_cli/services/init/__pycache__/init.cpython-310.pyc
114
+ latch_cli/services/init/__pycache__/init.cpython-311.pyc
115
+ latch_cli/services/init/__pycache__/init.cpython-38.pyc
116
+ latch_cli/services/init/__pycache__/init.cpython-39.pyc
111
117
  latch_cli/services/init/assemble_and_sort/.env
112
118
  latch_cli/services/init/assemble_and_sort/LICENSE
113
119
  latch_cli/services/init/assemble_and_sort/README.md
@@ -115,18 +121,22 @@ latch_cli/services/init/assemble_and_sort/__init__.py
115
121
  latch_cli/services/init/assemble_and_sort/assemble.py
116
122
  latch_cli/services/init/assemble_and_sort/sort.py
117
123
  latch_cli/services/init/assemble_and_sort/system-requirements.txt
124
+ latch_cli/services/init/assemble_and_sort/__pycache__/__init__.cpython-310.pyc
118
125
  latch_cli/services/init/common/.dockerignore
119
126
  latch_cli/services/init/example_conda/__init__.py
120
127
  latch_cli/services/init/example_conda/conda_task.py
121
128
  latch_cli/services/init/example_conda/environment.yaml
129
+ latch_cli/services/init/example_conda/__pycache__/__init__.cpython-310.pyc
122
130
  latch_cli/services/init/example_docker/__init__.py
123
131
  latch_cli/services/init/example_docker/task.py
132
+ latch_cli/services/init/example_nf_integration/latch_metadata/__pycache__/__init__.cpython-311.pyc
124
133
  latch_cli/services/init/example_nfcore/Dockerfile
125
134
  latch_cli/services/init/example_nfcore/__init__.py
126
135
  latch_cli/services/init/example_nfcore/task.py
127
136
  latch_cli/services/init/example_r/__init__.py
128
137
  latch_cli/services/init/example_r/environment.R
129
138
  latch_cli/services/init/example_r/r_task.py
139
+ latch_cli/services/init/example_r/__pycache__/__init__.cpython-310.pyc
130
140
  latch_cli/services/init/example_snakemake/Dockerfile
131
141
  latch_cli/services/init/example_snakemake/Snakefile
132
142
  latch_cli/services/init/example_snakemake/config.yaml
@@ -139,6 +149,7 @@ latch_cli/services/init/template/LICENSE
139
149
  latch_cli/services/init/template/README.md
140
150
  latch_cli/services/init/template/__init__.py
141
151
  latch_cli/services/init/template/task.py
152
+ latch_cli/services/init/template/__pycache__/__init__.cpython-310.pyc
142
153
  latch_cli/services/register/__init__.py
143
154
  latch_cli/services/register/constants.py
144
155
  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,
@@ -11,6 +11,7 @@ from typing import Iterable, List, Optional
11
11
  import click
12
12
  import gql
13
13
  import latch_sdk_gql.execute as l_gql
14
+ from flytekit.core.workflow import WorkflowBase
14
15
  from scp import SCPClient
15
16
 
16
17
  from latch.utils import current_workspace, get_workspaces
@@ -198,40 +199,25 @@ def _build_and_serialize(
198
199
  dockerfile: Optional[Path] = None,
199
200
  *,
200
201
  progress_plain: bool = False,
201
- cache_tasks: bool = False,
202
+ sm_jit_wf: Optional[WorkflowBase] = None,
202
203
  ):
203
204
  assert ctx.pkg_root is not None
204
205
 
205
- jit_wf = None
206
- if ctx.workflow_type == WorkflowType.snakemake:
207
- assert ctx.snakefile is not None
208
- assert ctx.version is not None
209
-
210
- from ...snakemake.serialize import generate_jit_register_code
211
- from ...snakemake.workflow import build_jit_register_wrapper
212
-
213
- jit_wf = build_jit_register_wrapper(cache_tasks)
214
- generate_jit_register_code(
215
- jit_wf,
216
- ctx.pkg_root,
217
- ctx.snakefile,
218
- ctx.version,
219
- image_name,
220
- current_workspace(),
221
- )
222
-
223
206
  image_build_logs = build_image(ctx, image_name, context_path, dockerfile)
224
207
  print_and_write_build_logs(
225
208
  image_build_logs, image_name, ctx.pkg_root, progress_plain=progress_plain
226
209
  )
227
210
 
228
211
  if ctx.workflow_type == WorkflowType.snakemake:
229
- assert jit_wf is not None
230
- assert ctx.dkr_repo is not None
212
+ from ...snakemake.serialize import (
213
+ JITRegisterWorkflow,
214
+ serialize_jit_register_workflow,
215
+ )
231
216
 
232
- from ...snakemake.serialize import serialize_jit_register_workflow
217
+ assert sm_jit_wf is not None and isinstance(sm_jit_wf, JITRegisterWorkflow)
218
+ assert ctx.dkr_repo is not None
233
219
 
234
- serialize_jit_register_workflow(jit_wf, tmp_dir, image_name, ctx.dkr_repo)
220
+ serialize_jit_register_workflow(sm_jit_wf, tmp_dir, image_name, ctx.dkr_repo)
235
221
  else:
236
222
  serialize_logs, container_id = serialize_pkg_in_container(
237
223
  ctx, image_name, tmp_dir
@@ -274,6 +260,9 @@ def register(
274
260
  open: bool = False,
275
261
  skip_confirmation: bool = False,
276
262
  snakefile: Optional[Path] = None,
263
+ nf_script: Optional[Path] = None,
264
+ nf_redownload_dependencies: bool = False,
265
+ nf_execution_profile: Optional[str] = None,
277
266
  progress_plain: bool = False,
278
267
  cache_tasks: bool = False,
279
268
  use_new_centromere: bool = False,
@@ -335,6 +324,7 @@ def register(
335
324
  disable_auto_version=disable_auto_version,
336
325
  remote=remote,
337
326
  snakefile=snakefile,
327
+ nf_script=nf_script,
338
328
  use_new_centromere=use_new_centromere,
339
329
  ) as ctx:
340
330
  assert ctx.workflow_name is not None, "Unable to determine workflow name"
@@ -372,6 +362,25 @@ def register(
372
362
  ])
373
363
  )
374
364
 
365
+ click.echo(
366
+ " ".join([
367
+ click.style("Workflow type:", fg="bright_blue"),
368
+ ctx.workflow_type.value,
369
+ ])
370
+ )
371
+ if ctx.workflow_type == WorkflowType.snakemake:
372
+ click.echo(
373
+ " ".join(
374
+ [click.style("Snakefile:", fg="bright_blue"), str(ctx.snakefile)]
375
+ )
376
+ )
377
+ elif ctx.workflow_type == WorkflowType.nextflow:
378
+ click.echo(
379
+ " ".join(
380
+ [click.style("NF script:", fg="bright_blue"), str(ctx.nf_script)]
381
+ )
382
+ )
383
+
375
384
  if use_new_centromere:
376
385
  click.secho("Using experimental registration server.", fg="yellow")
377
386
 
@@ -382,6 +391,39 @@ def register(
382
391
  else:
383
392
  click.secho("Skipping confirmation because of --yes", bold=True)
384
393
 
394
+ sm_jit_wf = None
395
+ if ctx.workflow_type == WorkflowType.snakemake:
396
+ assert ctx.snakefile is not None
397
+ assert ctx.version is not None
398
+
399
+ from ...snakemake.serialize import generate_jit_register_code
400
+ from ...snakemake.workflow import build_jit_register_wrapper
401
+
402
+ sm_jit_wf = build_jit_register_wrapper(cache_tasks)
403
+ generate_jit_register_code(
404
+ sm_jit_wf,
405
+ ctx.pkg_root,
406
+ ctx.snakefile,
407
+ ctx.version,
408
+ ctx.default_container.image_name,
409
+ current_workspace(),
410
+ )
411
+ elif ctx.workflow_type == WorkflowType.nextflow:
412
+ assert ctx.nf_script is not None
413
+
414
+ from ...nextflow.dependencies import ensure_nf_dependencies
415
+ from ...nextflow.workflow import generate_nextflow_workflow
416
+
417
+ ensure_nf_dependencies(
418
+ Path(pkg_root), force_redownload=nf_redownload_dependencies
419
+ )
420
+ generate_nextflow_workflow(
421
+ ctx.pkg_root,
422
+ ctx.workflow_name,
423
+ ctx.nf_script,
424
+ execution_profile=nf_execution_profile,
425
+ )
426
+
385
427
  click.secho("\nInitializing registration", bold=True)
386
428
  transport = None
387
429
  scp = None
@@ -416,7 +458,7 @@ def register(
416
458
  td,
417
459
  dockerfile=ctx.default_container.dockerfile,
418
460
  progress_plain=progress_plain,
419
- cache_tasks=cache_tasks,
461
+ sm_jit_wf=sm_jit_wf,
420
462
  )
421
463
 
422
464
  if remote and snakefile is None:
@@ -384,6 +384,7 @@ class TemporarySSHCredentials:
384
384
  class WorkflowType(Enum):
385
385
  latchbiosdk = "latchbiosdk"
386
386
  snakemake = "snakemake"
387
+ nextflow = "nextflow"
387
388
 
388
389
 
389
390
  def identifier_suffix_from_str(x: str) -> str: