latch 2.45.1__tar.gz → 2.45.2.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 (186) hide show
  1. latch-2.45.2.dev1/PKG-INFO +39 -0
  2. {latch-2.45.1 → latch-2.45.2.dev1}/latch/ldata/type.py +7 -1
  3. {latch-2.45.1 → latch-2.45.2.dev1}/latch/resources/tasks.py +43 -0
  4. {latch-2.45.1 → latch-2.45.2.dev1}/latch/types/directory.py +2 -0
  5. {latch-2.45.1 → latch-2.45.2.dev1}/latch/types/file.py +2 -0
  6. {latch-2.45.1 → latch-2.45.2.dev1}/latch/types/metadata.py +94 -18
  7. latch-2.45.2.dev1/latch.egg-info/PKG-INFO +39 -0
  8. {latch-2.45.1 → latch-2.45.2.dev1}/latch.egg-info/SOURCES.txt +4 -11
  9. {latch-2.45.1 → latch-2.45.2.dev1}/latch.egg-info/requires.txt +1 -1
  10. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/centromere/ctx.py +45 -8
  11. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/docker_utils/__init__.py +16 -1
  12. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/main.py +46 -2
  13. latch-2.45.2.dev1/latch_cli/nextflow/dependencies.py +81 -0
  14. latch-2.45.2.dev1/latch_cli/nextflow/utils.py +27 -0
  15. latch-2.45.2.dev1/latch_cli/nextflow/workflow.py +232 -0
  16. latch-2.45.2.dev1/latch_cli/services/init/__pycache__/__init__.cpython-310.pyc +0 -0
  17. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/services/init/__pycache__/init.cpython-310.pyc +0 -0
  18. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/services/register/register.py +66 -24
  19. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/snakemake/config/utils.py +20 -6
  20. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/utils/__init__.py +1 -0
  21. {latch-2.45.1 → latch-2.45.2.dev1}/setup.py +2 -2
  22. latch-2.45.2.dev1/tests/__init__.py +0 -0
  23. latch-2.45.1/PKG-INFO +0 -13
  24. latch-2.45.1/latch.egg-info/PKG-INFO +0 -13
  25. latch-2.45.1/latch_cli/services/init/__pycache__/__init__.cpython-310.pyc +0 -0
  26. latch-2.45.1/latch_cli/services/init/__pycache__/__init__.cpython-311.pyc +0 -0
  27. latch-2.45.1/latch_cli/services/init/__pycache__/__init__.cpython-38.pyc +0 -0
  28. latch-2.45.1/latch_cli/services/init/__pycache__/__init__.cpython-39.pyc +0 -0
  29. latch-2.45.1/latch_cli/services/init/__pycache__/init.cpython-311.pyc +0 -0
  30. latch-2.45.1/latch_cli/services/init/__pycache__/init.cpython-38.pyc +0 -0
  31. latch-2.45.1/latch_cli/services/init/__pycache__/init.cpython-39.pyc +0 -0
  32. latch-2.45.1/latch_cli/services/init/assemble_and_sort/__pycache__/__init__.cpython-310.pyc +0 -0
  33. latch-2.45.1/latch_cli/services/init/example_conda/__pycache__/__init__.cpython-310.pyc +0 -0
  34. latch-2.45.1/latch_cli/services/init/example_nf_integration/latch_metadata/__pycache__/__init__.cpython-311.pyc +0 -0
  35. latch-2.45.1/latch_cli/services/init/example_r/__pycache__/__init__.cpython-310.pyc +0 -0
  36. latch-2.45.1/latch_cli/services/init/template/__pycache__/__init__.cpython-310.pyc +0 -0
  37. {latch-2.45.1 → latch-2.45.2.dev1}/LICENSE +0 -0
  38. {latch-2.45.1 → latch-2.45.2.dev1}/MANIFEST.in +0 -0
  39. {latch-2.45.1 → latch-2.45.2.dev1}/README.md +0 -0
  40. {latch-2.45.1 → latch-2.45.2.dev1}/latch/__init__.py +0 -0
  41. {latch-2.45.1 → latch-2.45.2.dev1}/latch/account.py +0 -0
  42. {latch-2.45.1 → latch-2.45.2.dev1}/latch/executions.py +0 -0
  43. {latch-2.45.1 → latch-2.45.2.dev1}/latch/functions/__init__.py +0 -0
  44. {latch-2.45.1 → latch-2.45.2.dev1}/latch/functions/messages.py +0 -0
  45. {latch-2.45.1 → latch-2.45.2.dev1}/latch/functions/operators.py +0 -0
  46. {latch-2.45.1 → latch-2.45.2.dev1}/latch/functions/secrets.py +0 -0
  47. {latch-2.45.1 → latch-2.45.2.dev1}/latch/ldata/__init__.py +0 -0
  48. {latch-2.45.1 → latch-2.45.2.dev1}/latch/ldata/_transfer/__init__.py +0 -0
  49. {latch-2.45.1 → latch-2.45.2.dev1}/latch/ldata/_transfer/download.py +0 -0
  50. {latch-2.45.1 → latch-2.45.2.dev1}/latch/ldata/_transfer/manager.py +0 -0
  51. {latch-2.45.1 → latch-2.45.2.dev1}/latch/ldata/_transfer/node.py +0 -0
  52. {latch-2.45.1 → latch-2.45.2.dev1}/latch/ldata/_transfer/progress.py +0 -0
  53. {latch-2.45.1 → latch-2.45.2.dev1}/latch/ldata/_transfer/remote_copy.py +0 -0
  54. {latch-2.45.1 → latch-2.45.2.dev1}/latch/ldata/_transfer/throttle.py +0 -0
  55. {latch-2.45.1 → latch-2.45.2.dev1}/latch/ldata/_transfer/upload.py +0 -0
  56. {latch-2.45.1 → latch-2.45.2.dev1}/latch/ldata/_transfer/utils.py +0 -0
  57. {latch-2.45.1 → latch-2.45.2.dev1}/latch/ldata/path.py +0 -0
  58. {latch-2.45.1 → latch-2.45.2.dev1}/latch/registry/__init__.py +0 -0
  59. {latch-2.45.1 → latch-2.45.2.dev1}/latch/registry/project.py +0 -0
  60. {latch-2.45.1 → latch-2.45.2.dev1}/latch/registry/record.py +0 -0
  61. {latch-2.45.1 → latch-2.45.2.dev1}/latch/registry/table.py +0 -0
  62. {latch-2.45.1 → latch-2.45.2.dev1}/latch/registry/types.py +0 -0
  63. {latch-2.45.1 → latch-2.45.2.dev1}/latch/registry/upstream_types/__init__.py +0 -0
  64. {latch-2.45.1 → latch-2.45.2.dev1}/latch/registry/upstream_types/types.py +0 -0
  65. {latch-2.45.1 → latch-2.45.2.dev1}/latch/registry/upstream_types/values.py +0 -0
  66. {latch-2.45.1 → latch-2.45.2.dev1}/latch/registry/utils.py +0 -0
  67. {latch-2.45.1 → latch-2.45.2.dev1}/latch/resources/__init__.py +0 -0
  68. {latch-2.45.1 → latch-2.45.2.dev1}/latch/resources/conditional.py +0 -0
  69. {latch-2.45.1 → latch-2.45.2.dev1}/latch/resources/dynamic.py +0 -0
  70. {latch-2.45.1 → latch-2.45.2.dev1}/latch/resources/launch_plan.py +0 -0
  71. {latch-2.45.1 → latch-2.45.2.dev1}/latch/resources/map_tasks.py +0 -0
  72. {latch-2.45.1 → latch-2.45.2.dev1}/latch/resources/reference_workflow.py +0 -0
  73. {latch-2.45.1 → latch-2.45.2.dev1}/latch/resources/workflow.py +0 -0
  74. {latch-2.45.1 → latch-2.45.2.dev1}/latch/types/__init__.py +0 -0
  75. {latch-2.45.1 → latch-2.45.2.dev1}/latch/types/glob.py +0 -0
  76. {latch-2.45.1 → latch-2.45.2.dev1}/latch/types/json.py +0 -0
  77. {latch-2.45.1 → latch-2.45.2.dev1}/latch/types/utils.py +0 -0
  78. {latch-2.45.1 → latch-2.45.2.dev1}/latch/utils.py +0 -0
  79. {latch-2.45.1 → latch-2.45.2.dev1}/latch/verified/__init__.py +0 -0
  80. {latch-2.45.1 → latch-2.45.2.dev1}/latch/verified/deseq2.py +0 -0
  81. {latch-2.45.1 → latch-2.45.2.dev1}/latch/verified/mafft.py +0 -0
  82. {latch-2.45.1 → latch-2.45.2.dev1}/latch/verified/pathway.py +0 -0
  83. {latch-2.45.1 → latch-2.45.2.dev1}/latch/verified/rnaseq.py +0 -0
  84. {latch-2.45.1 → latch-2.45.2.dev1}/latch/verified/trim_galore.py +0 -0
  85. {latch-2.45.1 → latch-2.45.2.dev1}/latch.egg-info/dependency_links.txt +0 -0
  86. {latch-2.45.1 → latch-2.45.2.dev1}/latch.egg-info/entry_points.txt +0 -0
  87. {latch-2.45.1 → latch-2.45.2.dev1}/latch.egg-info/top_level.txt +0 -0
  88. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/__init__.py +0 -0
  89. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/auth/__init__.py +0 -0
  90. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/auth/csrf.py +0 -0
  91. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/auth/oauth2.py +0 -0
  92. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/auth/pkce.py +0 -0
  93. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/auth/utils.py +0 -0
  94. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/centromere/__init__.py +0 -0
  95. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/centromere/utils.py +0 -0
  96. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/click_utils.py +0 -0
  97. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/constants.py +0 -0
  98. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/exceptions/__init__.py +0 -0
  99. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/exceptions/cache.py +0 -0
  100. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/exceptions/errors.py +0 -0
  101. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/exceptions/handler.py +0 -0
  102. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/exceptions/traceback.py +0 -0
  103. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/menus.py +0 -0
  104. {latch-2.45.1/latch_cli/services/cp → latch-2.45.2.dev1/latch_cli/nextflow}/__init__.py +0 -0
  105. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/services/__init__.py +0 -0
  106. {latch-2.45.1/latch_cli/services/execute → latch-2.45.2.dev1/latch_cli/services/cp}/__init__.py +0 -0
  107. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/services/cp/autocomplete.py +0 -0
  108. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/services/cp/glob.py +0 -0
  109. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/services/cp/main.py +0 -0
  110. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/services/cp/utils.py +0 -0
  111. {latch-2.45.1/latch_cli/services/test_data → latch-2.45.2.dev1/latch_cli/services/execute}/__init__.py +0 -0
  112. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/services/execute/main.py +0 -0
  113. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/services/execute/utils.py +0 -0
  114. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/services/get.py +0 -0
  115. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/services/get_executions.py +0 -0
  116. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/services/get_params.py +0 -0
  117. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/services/init/__init__.py +0 -0
  118. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/services/init/assemble_and_sort/.env +0 -0
  119. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/services/init/assemble_and_sort/LICENSE +0 -0
  120. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/services/init/assemble_and_sort/README.md +0 -0
  121. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/services/init/assemble_and_sort/__init__.py +0 -0
  122. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/services/init/assemble_and_sort/assemble.py +0 -0
  123. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/services/init/assemble_and_sort/sort.py +0 -0
  124. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/services/init/assemble_and_sort/system-requirements.txt +0 -0
  125. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/services/init/common/.dockerignore +0 -0
  126. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/services/init/example_conda/__init__.py +0 -0
  127. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/services/init/example_conda/conda_task.py +0 -0
  128. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/services/init/example_conda/environment.yaml +0 -0
  129. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/services/init/example_docker/__init__.py +0 -0
  130. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/services/init/example_docker/task.py +0 -0
  131. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/services/init/example_nfcore/Dockerfile +0 -0
  132. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/services/init/example_nfcore/__init__.py +0 -0
  133. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/services/init/example_nfcore/task.py +0 -0
  134. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/services/init/example_r/__init__.py +0 -0
  135. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/services/init/example_r/environment.R +0 -0
  136. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/services/init/example_r/r_task.py +0 -0
  137. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/services/init/example_snakemake/.latch/latch_entrypoint +0 -0
  138. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/services/init/example_snakemake/Dockerfile +0 -0
  139. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/services/init/example_snakemake/Snakefile +0 -0
  140. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/services/init/example_snakemake/config.yaml +0 -0
  141. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/services/init/example_snakemake/environment.yaml +0 -0
  142. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/services/init/example_snakemake/latch_metadata.py +0 -0
  143. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/services/init/example_snakemake/scripts/plot-quals.py +0 -0
  144. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/services/init/example_snakemake/version +0 -0
  145. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/services/init/init.py +0 -0
  146. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/services/init/template/LICENSE +0 -0
  147. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/services/init/template/README.md +0 -0
  148. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/services/init/template/__init__.py +0 -0
  149. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/services/init/template/task.py +0 -0
  150. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/services/launch.py +0 -0
  151. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/services/local_dev.py +0 -0
  152. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/services/local_dev_old.py +0 -0
  153. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/services/login.py +0 -0
  154. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/services/ls.py +0 -0
  155. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/services/mkdir.py +0 -0
  156. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/services/move.py +0 -0
  157. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/services/preview.py +0 -0
  158. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/services/register/__init__.py +0 -0
  159. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/services/register/constants.py +0 -0
  160. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/services/register/utils.py +0 -0
  161. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/services/rm.py +0 -0
  162. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/services/stop_pod.py +0 -0
  163. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/services/sync.py +0 -0
  164. {latch-2.45.1/latch_cli/snakemake → latch-2.45.2.dev1/latch_cli/services/test_data}/__init__.py +0 -0
  165. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/services/test_data/ls.py +0 -0
  166. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/services/test_data/remove.py +0 -0
  167. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/services/test_data/upload.py +0 -0
  168. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/services/test_data/utils.py +0 -0
  169. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/services/workspace.py +0 -0
  170. {latch-2.45.1/latch_cli/snakemake/config → latch-2.45.2.dev1/latch_cli/snakemake}/__init__.py +0 -0
  171. {latch-2.45.1/latch_cli/tui → latch-2.45.2.dev1/latch_cli/snakemake/config}/__init__.py +0 -0
  172. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/snakemake/config/parser.py +0 -0
  173. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/snakemake/serialize.py +0 -0
  174. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/snakemake/serialize_utils.py +0 -0
  175. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/snakemake/single_task_snakemake.py +0 -0
  176. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/snakemake/utils.py +0 -0
  177. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/snakemake/workflow.py +0 -0
  178. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/tinyrequests.py +0 -0
  179. {latch-2.45.1/tests → latch-2.45.2.dev1/latch_cli/tui}/__init__.py +0 -0
  180. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/utils/path.py +0 -0
  181. {latch-2.45.1 → latch-2.45.2.dev1}/latch_cli/workflow_config.py +0 -0
  182. {latch-2.45.1 → latch-2.45.2.dev1}/pyproject.toml +0 -0
  183. {latch-2.45.1 → latch-2.45.2.dev1}/setup.cfg +0 -0
  184. {latch-2.45.1 → latch-2.45.2.dev1}/tests/cp/__init__.py +0 -0
  185. {latch-2.45.1 → latch-2.45.2.dev1}/tests/fixtures.py +0 -0
  186. {latch-2.45.1 → latch-2.45.2.dev1}/tests/test_ls.py +0 -0
@@ -0,0 +1,39 @@
1
+ Metadata-Version: 2.1
2
+ Name: latch
3
+ Version: 2.45.2.dev1
4
+ Summary: The Latch SDK
5
+ Author-email: kenny@latch.bio
6
+ Classifier: Programming Language :: Python :: 3.8
7
+ Classifier: Programming Language :: Python :: 3.9
8
+ Classifier: Programming Language :: Python :: 3.10
9
+ Classifier: Programming Language :: Python :: 3.11
10
+ Requires-Python: >=3.8,<3.12
11
+ License-File: LICENSE
12
+ Requires-Dist: kubernetes>=24.2.0
13
+ Requires-Dist: pyjwt>=0.2.0
14
+ Requires-Dist: requests>=2.28.1
15
+ Requires-Dist: click>=8.0
16
+ Requires-Dist: docker>=7.1.0
17
+ Requires-Dist: paramiko>=3.2.0
18
+ Requires-Dist: scp>=0.14.0
19
+ Requires-Dist: boto3>=1.26.0
20
+ Requires-Dist: tqdm>=4.63.0
21
+ Requires-Dist: lytekit==0.15.8
22
+ Requires-Dist: lytekitplugins-pods==0.6.2
23
+ Requires-Dist: typing-extensions==4.7.1
24
+ Requires-Dist: apscheduler==3.9.1
25
+ Requires-Dist: gql==3.4.0
26
+ Requires-Dist: graphql-core==3.2.3
27
+ Requires-Dist: requests-toolbelt==0.10.1
28
+ Requires-Dist: latch-sdk-gql==0.0.6
29
+ Requires-Dist: latch-sdk-config==0.0.4
30
+ Requires-Dist: python-dateutil>=2.8
31
+ Requires-Dist: aioconsole==0.6.1
32
+ Requires-Dist: asyncssh==2.13.2
33
+ Requires-Dist: websockets==11.0.3
34
+ Requires-Dist: watchfiles==0.19.0
35
+ Provides-Extra: snakemake
36
+ Requires-Dist: snakemake<7.30.2,>=7.18.0; extra == "snakemake"
37
+ Requires-Dist: pulp<2.8,>=2.0; extra == "snakemake"
38
+ Provides-Extra: pandas
39
+ Requires-Dist: pandas>=2.0.0; extra == "pandas"
@@ -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
@@ -34,9 +34,12 @@ from flytekit import task
34
34
  from flytekitplugins.pod import Pod
35
35
  from kubernetes.client.models import (
36
36
  V1Container,
37
+ V1PersistentVolumeClaimVolumeSource,
37
38
  V1PodSpec,
38
39
  V1ResourceRequirements,
39
40
  V1Toleration,
41
+ V1Volume,
42
+ V1VolumeMount,
40
43
  )
41
44
 
42
45
  from latch_cli.constants import Units
@@ -474,3 +477,43 @@ def custom_task(
474
477
  return functools.partial(
475
478
  task, task_config=_custom_task_config(cpu, memory, storage_gib), timeout=timeout
476
479
  )
480
+
481
+
482
+ def nextflow_runtime_task(cpu: int, memory: int):
483
+ primary_container = V1Container(name="primary")
484
+ resources = V1ResourceRequirements(
485
+ requests={
486
+ "cpu": str(cpu),
487
+ "memory": f"{memory}Gi",
488
+ "ephemeral-storage": "20Gi",
489
+ },
490
+ limits={"cpu": str(cpu), "memory": f"{memory}Gi", "ephemeral-storage": "20Gi"},
491
+ )
492
+ primary_container.resources = resources
493
+ volume_mounts = [V1VolumeMount(mount_path="/nf-workdir", name="nextflow-workdir")]
494
+ primary_container.volume_mounts = volume_mounts
495
+
496
+ task_config = Pod(
497
+ annotations={
498
+ "io.kubernetes.cri-o.userns-mode": (
499
+ "private:uidmapping=0:1048576:65536;gidmapping=0:1048576:65536"
500
+ )
501
+ },
502
+ pod_spec=V1PodSpec(
503
+ runtime_class_name="sysbox-runc",
504
+ automount_service_account_token=True,
505
+ containers=[primary_container],
506
+ volumes=[
507
+ V1Volume(
508
+ name="nextflow-workdir",
509
+ persistent_volume_claim=V1PersistentVolumeClaimVolumeSource(
510
+ # this value will be injected by flytepropeller
511
+ claim_name="nextflow-pvc-placeholder"
512
+ ),
513
+ )
514
+ ],
515
+ ),
516
+ primary_container_name="primary",
517
+ )
518
+
519
+ return functools.partial(task, task_config=task_config)
@@ -114,8 +114,10 @@ class LatchDir(FlyteDirectory):
114
114
  self._path_generated = False
115
115
 
116
116
  if is_valid_url(self.path) and remote_path is None:
117
+ self._raw_remote_path = str(path)
117
118
  self._remote_directory = self.path
118
119
  else:
120
+ self._raw_remote_path = str(remote_path)
119
121
  self._remote_directory = None if remote_path is None else str(remote_path)
120
122
 
121
123
  if kwargs.get("downloader") is not None:
@@ -77,8 +77,10 @@ class LatchFile(FlyteFile):
77
77
  self._path_generated = False
78
78
 
79
79
  if is_valid_url(self.path) and remote_path is None:
80
+ self._raw_remote_path = str(path)
80
81
  self._remote_path = str(path)
81
82
  else:
83
+ self._raw_remote_path = str(remote_path)
82
84
  self._remote_path = None if remote_path is None else str(remote_path)
83
85
 
84
86
  if kwargs.get("downloader") is not None:
@@ -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,34 @@ 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
+
486
+ @dataclass(frozen=True)
487
+ class NextflowRuntimeResources:
488
+ """Resources for Nextflow runtime tasks"""
489
+
490
+ cpus: Optional[int] = 4
491
+ """
492
+ Number of CPUs required for the task
493
+ """
494
+ memory: Optional[str] = 8
495
+ """
496
+ Memory required for the task (e.g. "1 GB")
497
+ """
498
+ storage_gib: Optional[int] = 100
499
+
500
+
459
501
  @dataclass
460
502
  class LatchMetadata:
461
503
  """Class for organizing workflow metadata
@@ -651,3 +693,37 @@ class SnakemakeMetadata(LatchMetadata):
651
693
 
652
694
 
653
695
  _snakemake_metadata: Optional[SnakemakeMetadata] = None
696
+
697
+
698
+ @dataclass
699
+ class NextflowMetadata(LatchMetadata):
700
+ name: Optional[str] = None
701
+ """
702
+ Name of the workflow
703
+ """
704
+ parameters: Dict[str, NextflowParameter] = field(default_factory=dict)
705
+ """
706
+ A dictionary mapping parameter names (strings) to `NextflowParameter` objects
707
+ """
708
+ runtime_resources: NextflowRuntimeResources = field(
709
+ default_factory=NextflowRuntimeResources
710
+ )
711
+ """
712
+ Resources (cpu/memory/storage) for Nextflow runtime task
713
+ """
714
+ output_dir: Optional[LatchDir] = None
715
+ """
716
+ Directory to dump Nextflow logs
717
+ """
718
+
719
+ def __post_init__(self):
720
+ if self.name is None:
721
+ self.name = f"nf_{identifier_suffix_from_str(self.display_name.lower())}"
722
+ else:
723
+ self.name = identifier_suffix_from_str(self.name)
724
+
725
+ global _nextflow_metadata
726
+ _nextflow_metadata = self
727
+
728
+
729
+ _nextflow_metadata: Optional[NextflowMetadata] = None
@@ -0,0 +1,39 @@
1
+ Metadata-Version: 2.1
2
+ Name: latch
3
+ Version: 2.45.2.dev1
4
+ Summary: The Latch SDK
5
+ Author-email: kenny@latch.bio
6
+ Classifier: Programming Language :: Python :: 3.8
7
+ Classifier: Programming Language :: Python :: 3.9
8
+ Classifier: Programming Language :: Python :: 3.10
9
+ Classifier: Programming Language :: Python :: 3.11
10
+ Requires-Python: >=3.8,<3.12
11
+ License-File: LICENSE
12
+ Requires-Dist: kubernetes>=24.2.0
13
+ Requires-Dist: pyjwt>=0.2.0
14
+ Requires-Dist: requests>=2.28.1
15
+ Requires-Dist: click>=8.0
16
+ Requires-Dist: docker>=7.1.0
17
+ Requires-Dist: paramiko>=3.2.0
18
+ Requires-Dist: scp>=0.14.0
19
+ Requires-Dist: boto3>=1.26.0
20
+ Requires-Dist: tqdm>=4.63.0
21
+ Requires-Dist: lytekit==0.15.8
22
+ Requires-Dist: lytekitplugins-pods==0.6.2
23
+ Requires-Dist: typing-extensions==4.7.1
24
+ Requires-Dist: apscheduler==3.9.1
25
+ Requires-Dist: gql==3.4.0
26
+ Requires-Dist: graphql-core==3.2.3
27
+ Requires-Dist: requests-toolbelt==0.10.1
28
+ Requires-Dist: latch-sdk-gql==0.0.6
29
+ Requires-Dist: latch-sdk-config==0.0.4
30
+ Requires-Dist: python-dateutil>=2.8
31
+ Requires-Dist: aioconsole==0.6.1
32
+ Requires-Dist: asyncssh==2.13.2
33
+ Requires-Dist: websockets==11.0.3
34
+ Requires-Dist: watchfiles==0.19.0
35
+ Provides-Extra: snakemake
36
+ Requires-Dist: snakemake<7.30.2,>=7.18.0; extra == "snakemake"
37
+ Requires-Dist: pulp<2.8,>=2.0; extra == "snakemake"
38
+ Provides-Extra: pandas
39
+ Requires-Dist: pandas>=2.0.0; extra == "pandas"
@@ -80,6 +80,10 @@ 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/utils.py
86
+ latch_cli/nextflow/workflow.py
83
87
  latch_cli/services/__init__.py
84
88
  latch_cli/services/get.py
85
89
  latch_cli/services/get_executions.py
@@ -107,13 +111,7 @@ latch_cli/services/execute/utils.py
107
111
  latch_cli/services/init/__init__.py
108
112
  latch_cli/services/init/init.py
109
113
  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
113
114
  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
117
115
  latch_cli/services/init/assemble_and_sort/.env
118
116
  latch_cli/services/init/assemble_and_sort/LICENSE
119
117
  latch_cli/services/init/assemble_and_sort/README.md
@@ -121,22 +119,18 @@ latch_cli/services/init/assemble_and_sort/__init__.py
121
119
  latch_cli/services/init/assemble_and_sort/assemble.py
122
120
  latch_cli/services/init/assemble_and_sort/sort.py
123
121
  latch_cli/services/init/assemble_and_sort/system-requirements.txt
124
- latch_cli/services/init/assemble_and_sort/__pycache__/__init__.cpython-310.pyc
125
122
  latch_cli/services/init/common/.dockerignore
126
123
  latch_cli/services/init/example_conda/__init__.py
127
124
  latch_cli/services/init/example_conda/conda_task.py
128
125
  latch_cli/services/init/example_conda/environment.yaml
129
- latch_cli/services/init/example_conda/__pycache__/__init__.cpython-310.pyc
130
126
  latch_cli/services/init/example_docker/__init__.py
131
127
  latch_cli/services/init/example_docker/task.py
132
- latch_cli/services/init/example_nf_integration/latch_metadata/__pycache__/__init__.cpython-311.pyc
133
128
  latch_cli/services/init/example_nfcore/Dockerfile
134
129
  latch_cli/services/init/example_nfcore/__init__.py
135
130
  latch_cli/services/init/example_nfcore/task.py
136
131
  latch_cli/services/init/example_r/__init__.py
137
132
  latch_cli/services/init/example_r/environment.R
138
133
  latch_cli/services/init/example_r/r_task.py
139
- latch_cli/services/init/example_r/__pycache__/__init__.cpython-310.pyc
140
134
  latch_cli/services/init/example_snakemake/Dockerfile
141
135
  latch_cli/services/init/example_snakemake/Snakefile
142
136
  latch_cli/services/init/example_snakemake/config.yaml
@@ -149,7 +143,6 @@ latch_cli/services/init/template/LICENSE
149
143
  latch_cli/services/init/template/README.md
150
144
  latch_cli/services/init/template/__init__.py
151
145
  latch_cli/services/init/template/task.py
152
- latch_cli/services/init/template/__pycache__/__init__.cpython-310.pyc
153
146
  latch_cli/services/register/__init__.py
154
147
  latch_cli/services/register/constants.py
155
148
  latch_cli/services/register/register.py
@@ -7,7 +7,7 @@ paramiko>=3.2.0
7
7
  scp>=0.14.0
8
8
  boto3>=1.26.0
9
9
  tqdm>=4.63.0
10
- lytekit==0.15.7
10
+ lytekit==0.15.8
11
11
  lytekitplugins-pods==0.6.2
12
12
  typing-extensions==4.7.1
13
13
  apscheduler==3.9.1
@@ -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,11 +137,7 @@ class _CentromereCtx:
126
137
  fg="red",
127
138
  )
128
139
  raise click.exceptions.Exit(1)
129
-
130
- name_path = pkg_root / latch_constants.pkg_workflow_name
131
- if name_path.exists():
132
- self.workflow_name = name_path.read_text().strip()
133
- else:
140
+ elif self.workflow_type == WorkflowType.snakemake:
134
141
  assert snakefile is not None
135
142
 
136
143
  import latch.types.metadata as metadata
@@ -142,6 +149,10 @@ class _CentromereCtx:
142
149
  )
143
150
  from ..snakemake.utils import load_snakemake_metadata
144
151
 
152
+ name_path = pkg_root / latch_constants.pkg_workflow_name
153
+ if name_path.exists():
154
+ self.workflow_name = name_path.read_text().strip()
155
+
145
156
  meta_file = load_snakemake_metadata(pkg_root)
146
157
  if meta_file is not None:
147
158
  click.echo(
@@ -235,6 +246,32 @@ class _CentromereCtx:
235
246
  # todo(kenny): support per container task and custom workflow
236
247
  # name for snakemake
237
248
  self.workflow_name = f"{metadata._snakemake_metadata.name}_jit_register"
249
+ else:
250
+ assert nf_script is not None
251
+
252
+ import latch.types.metadata as metadata
253
+
254
+ from ..services.register.utils import import_module_by_path
255
+
256
+ meta = pkg_root / "latch_metadata" / "__init__.py"
257
+ if meta.exists():
258
+ click.echo(f"Using metadata file {click.style(meta, italic=True)}")
259
+ import_module_by_path(meta)
260
+
261
+ if metadata._nextflow_metadata is None:
262
+ click.secho(
263
+ dedent("""
264
+ Failed to register Nextflow workflow.
265
+ Make sure the project root contains a `latch_metadata/__init__.py`
266
+ with a `NextflowMetadata` object defined.
267
+ """),
268
+ fg="red",
269
+ )
270
+ raise click.exceptions.Exit(1)
271
+
272
+ self.workflow_name = metadata._nextflow_metadata.name
273
+
274
+ assert self.workflow_name is not None
238
275
 
239
276
  version_file = self.pkg_root / "version"
240
277
  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,