latch 2.40.4__tar.gz → 2.40.4.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 (204) hide show
  1. {latch-2.40.4/latch.egg-info → latch-2.40.4.dev0}/PKG-INFO +1 -1
  2. {latch-2.40.4 → latch-2.40.4.dev0}/latch/types/directory.py +6 -0
  3. {latch-2.40.4 → latch-2.40.4.dev0}/latch/types/file.py +3 -0
  4. {latch-2.40.4 → latch-2.40.4.dev0}/latch/types/metadata.py +83 -18
  5. {latch-2.40.4 → latch-2.40.4.dev0}/latch/utils.py +10 -2
  6. {latch-2.40.4 → latch-2.40.4.dev0/latch.egg-info}/PKG-INFO +1 -1
  7. {latch-2.40.4 → latch-2.40.4.dev0}/latch.egg-info/SOURCES.txt +33 -9
  8. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/auth/oauth2.py +7 -9
  9. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/centromere/ctx.py +82 -32
  10. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/click_utils.py +10 -3
  11. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/docker_utils/__init__.py +23 -13
  12. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/exceptions/handler.py +12 -18
  13. latch-2.40.4.dev0/latch_cli/extras/common/config/parser.py +82 -0
  14. {latch-2.40.4/latch_cli/snakemake → latch-2.40.4.dev0/latch_cli/extras/common}/config/utils.py +23 -106
  15. latch-2.40.4/latch_cli/snakemake/serialize_utils.py → latch-2.40.4.dev0/latch_cli/extras/common/serialize.py +188 -10
  16. latch-2.40.4.dev0/latch_cli/extras/common/utils.py +72 -0
  17. latch-2.40.4.dev0/latch_cli/extras/nextflow/build.py +536 -0
  18. latch-2.40.4.dev0/latch_cli/extras/nextflow/channel.py +89 -0
  19. latch-2.40.4.dev0/latch_cli/extras/nextflow/config.py +162 -0
  20. latch-2.40.4.dev0/latch_cli/extras/nextflow/dag.py +320 -0
  21. latch-2.40.4.dev0/latch_cli/extras/nextflow/file_persistence.py +239 -0
  22. latch-2.40.4.dev0/latch_cli/extras/nextflow/serialize.py +60 -0
  23. latch-2.40.4.dev0/latch_cli/extras/nextflow/tasks/adapters.py +232 -0
  24. latch-2.40.4.dev0/latch_cli/extras/nextflow/tasks/base.py +193 -0
  25. latch-2.40.4.dev0/latch_cli/extras/nextflow/tasks/conditional.py +51 -0
  26. latch-2.40.4.dev0/latch_cli/extras/nextflow/tasks/map.py +180 -0
  27. latch-2.40.4.dev0/latch_cli/extras/nextflow/tasks/merge.py +111 -0
  28. latch-2.40.4.dev0/latch_cli/extras/nextflow/tasks/operator.py +234 -0
  29. latch-2.40.4.dev0/latch_cli/extras/nextflow/tasks/process.py +258 -0
  30. latch-2.40.4.dev0/latch_cli/extras/nextflow/workflow.py +101 -0
  31. latch-2.40.4/latch_cli/snakemake/config/parser.py → latch-2.40.4.dev0/latch_cli/extras/snakemake/config.py +110 -132
  32. {latch-2.40.4/latch_cli → latch-2.40.4.dev0/latch_cli/extras}/snakemake/serialize.py +9 -40
  33. latch-2.40.4.dev0/latch_cli/extras/snakemake/utils.py +33 -0
  34. {latch-2.40.4/latch_cli → latch-2.40.4.dev0/latch_cli/extras}/snakemake/workflow.py +4 -79
  35. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/main.py +103 -18
  36. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/services/cp/autocomplete.py +1 -4
  37. latch-2.40.4.dev0/latch_cli/services/execute/__init__.py +0 -0
  38. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/services/get_executions.py +12 -10
  39. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/services/init/__pycache__/init.cpython-311.pyc +0 -0
  40. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/services/init/assemble_and_sort/__init__.py +1 -0
  41. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/services/init/common/.dockerignore +3 -0
  42. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/services/init/example_conda/conda_task.py +6 -8
  43. latch-2.40.4.dev0/latch_cli/services/init/example_nextflow/main.nf +7 -0
  44. latch-2.40.4.dev0/latch_cli/services/init/example_nextflow/nextflow.config +4 -0
  45. latch-2.40.4.dev0/latch_cli/services/init/example_nextflow/workflow.nf +50 -0
  46. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/services/init/example_nfcore/__init__.py +1 -0
  47. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/services/init/example_r/r_task.py +6 -8
  48. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/services/init/init.py +26 -5
  49. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/services/local_dev_old.py +7 -8
  50. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/services/login.py +0 -1
  51. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/services/move.py +1 -0
  52. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/services/preview.py +2 -1
  53. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/services/register/register.py +96 -54
  54. latch-2.40.4.dev0/latch_cli/services/test_data/__init__.py +0 -0
  55. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/services/workspace.py +7 -9
  56. latch-2.40.4.dev0/latch_cli/tui/__init__.py +0 -0
  57. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/utils/__init__.py +10 -31
  58. latch-2.40.4.dev0/latch_cli/utils/workflow.py +84 -0
  59. {latch-2.40.4 → latch-2.40.4.dev0}/setup.py +2 -6
  60. latch-2.40.4.dev0/tests/__init__.py +0 -0
  61. latch-2.40.4/latch_cli/snakemake/utils.py +0 -26
  62. {latch-2.40.4 → latch-2.40.4.dev0}/LICENSE +0 -0
  63. {latch-2.40.4 → latch-2.40.4.dev0}/MANIFEST.in +0 -0
  64. {latch-2.40.4 → latch-2.40.4.dev0}/README.md +0 -0
  65. {latch-2.40.4 → latch-2.40.4.dev0}/latch/__init__.py +0 -0
  66. {latch-2.40.4 → latch-2.40.4.dev0}/latch/account.py +0 -0
  67. {latch-2.40.4 → latch-2.40.4.dev0}/latch/executions.py +0 -0
  68. {latch-2.40.4 → latch-2.40.4.dev0}/latch/functions/__init__.py +0 -0
  69. {latch-2.40.4 → latch-2.40.4.dev0}/latch/functions/messages.py +0 -0
  70. {latch-2.40.4 → latch-2.40.4.dev0}/latch/functions/operators.py +0 -0
  71. {latch-2.40.4 → latch-2.40.4.dev0}/latch/functions/secrets.py +0 -0
  72. {latch-2.40.4 → latch-2.40.4.dev0}/latch/ldata/__init__.py +0 -0
  73. {latch-2.40.4 → latch-2.40.4.dev0}/latch/ldata/_transfer/__init__.py +0 -0
  74. {latch-2.40.4 → latch-2.40.4.dev0}/latch/ldata/_transfer/download.py +0 -0
  75. {latch-2.40.4 → latch-2.40.4.dev0}/latch/ldata/_transfer/manager.py +0 -0
  76. {latch-2.40.4 → latch-2.40.4.dev0}/latch/ldata/_transfer/node.py +0 -0
  77. {latch-2.40.4 → latch-2.40.4.dev0}/latch/ldata/_transfer/progress.py +0 -0
  78. {latch-2.40.4 → latch-2.40.4.dev0}/latch/ldata/_transfer/remote_copy.py +0 -0
  79. {latch-2.40.4 → latch-2.40.4.dev0}/latch/ldata/_transfer/throttle.py +0 -0
  80. {latch-2.40.4 → latch-2.40.4.dev0}/latch/ldata/_transfer/upload.py +0 -0
  81. {latch-2.40.4 → latch-2.40.4.dev0}/latch/ldata/_transfer/utils.py +0 -0
  82. {latch-2.40.4 → latch-2.40.4.dev0}/latch/ldata/path.py +0 -0
  83. {latch-2.40.4 → latch-2.40.4.dev0}/latch/ldata/type.py +0 -0
  84. {latch-2.40.4 → latch-2.40.4.dev0}/latch/registry/__init__.py +0 -0
  85. {latch-2.40.4 → latch-2.40.4.dev0}/latch/registry/project.py +0 -0
  86. {latch-2.40.4 → latch-2.40.4.dev0}/latch/registry/record.py +0 -0
  87. {latch-2.40.4 → latch-2.40.4.dev0}/latch/registry/table.py +0 -0
  88. {latch-2.40.4 → latch-2.40.4.dev0}/latch/registry/types.py +0 -0
  89. {latch-2.40.4 → latch-2.40.4.dev0}/latch/registry/upstream_types/__init__.py +0 -0
  90. {latch-2.40.4 → latch-2.40.4.dev0}/latch/registry/upstream_types/types.py +0 -0
  91. {latch-2.40.4 → latch-2.40.4.dev0}/latch/registry/upstream_types/values.py +0 -0
  92. {latch-2.40.4 → latch-2.40.4.dev0}/latch/registry/utils.py +0 -0
  93. {latch-2.40.4 → latch-2.40.4.dev0}/latch/resources/__init__.py +0 -0
  94. {latch-2.40.4 → latch-2.40.4.dev0}/latch/resources/conditional.py +0 -0
  95. {latch-2.40.4 → latch-2.40.4.dev0}/latch/resources/dynamic.py +0 -0
  96. {latch-2.40.4 → latch-2.40.4.dev0}/latch/resources/launch_plan.py +0 -0
  97. {latch-2.40.4 → latch-2.40.4.dev0}/latch/resources/map_tasks.py +0 -0
  98. {latch-2.40.4 → latch-2.40.4.dev0}/latch/resources/reference_workflow.py +0 -0
  99. {latch-2.40.4 → latch-2.40.4.dev0}/latch/resources/tasks.py +0 -0
  100. {latch-2.40.4 → latch-2.40.4.dev0}/latch/resources/workflow.py +0 -0
  101. {latch-2.40.4 → latch-2.40.4.dev0}/latch/types/__init__.py +0 -0
  102. {latch-2.40.4 → latch-2.40.4.dev0}/latch/types/glob.py +0 -0
  103. {latch-2.40.4 → latch-2.40.4.dev0}/latch/types/json.py +0 -0
  104. {latch-2.40.4 → latch-2.40.4.dev0}/latch/types/utils.py +0 -0
  105. {latch-2.40.4 → latch-2.40.4.dev0}/latch/verified/__init__.py +0 -0
  106. {latch-2.40.4 → latch-2.40.4.dev0}/latch/verified/deseq2.py +0 -0
  107. {latch-2.40.4 → latch-2.40.4.dev0}/latch/verified/mafft.py +0 -0
  108. {latch-2.40.4 → latch-2.40.4.dev0}/latch/verified/pathway.py +0 -0
  109. {latch-2.40.4 → latch-2.40.4.dev0}/latch/verified/rnaseq.py +0 -0
  110. {latch-2.40.4 → latch-2.40.4.dev0}/latch/verified/trim_galore.py +0 -0
  111. {latch-2.40.4 → latch-2.40.4.dev0}/latch.egg-info/dependency_links.txt +0 -0
  112. {latch-2.40.4 → latch-2.40.4.dev0}/latch.egg-info/entry_points.txt +0 -0
  113. {latch-2.40.4 → latch-2.40.4.dev0}/latch.egg-info/requires.txt +0 -0
  114. {latch-2.40.4 → latch-2.40.4.dev0}/latch.egg-info/top_level.txt +0 -0
  115. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/__init__.py +0 -0
  116. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/auth/__init__.py +0 -0
  117. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/auth/csrf.py +0 -0
  118. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/auth/pkce.py +0 -0
  119. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/auth/utils.py +0 -0
  120. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/centromere/__init__.py +0 -0
  121. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/centromere/utils.py +0 -0
  122. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/constants.py +0 -0
  123. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/exceptions/__init__.py +0 -0
  124. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/exceptions/cache.py +0 -0
  125. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/exceptions/errors.py +0 -0
  126. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/exceptions/traceback.py +0 -0
  127. {latch-2.40.4/latch_cli/services/cp → latch-2.40.4.dev0/latch_cli/extras}/__init__.py +0 -0
  128. {latch-2.40.4/latch_cli/services/execute → latch-2.40.4.dev0/latch_cli/extras/common}/__init__.py +0 -0
  129. {latch-2.40.4/latch_cli/services/test_data → latch-2.40.4.dev0/latch_cli/extras/common/config}/__init__.py +0 -0
  130. {latch-2.40.4/latch_cli/snakemake → latch-2.40.4.dev0/latch_cli/extras/nextflow}/__init__.py +0 -0
  131. {latch-2.40.4/latch_cli/snakemake/config → latch-2.40.4.dev0/latch_cli/extras/nextflow/tasks}/__init__.py +0 -0
  132. {latch-2.40.4/latch_cli/tui → latch-2.40.4.dev0/latch_cli/extras/snakemake}/__init__.py +0 -0
  133. {latch-2.40.4/latch_cli → latch-2.40.4.dev0/latch_cli/extras}/snakemake/single_task_snakemake.py +0 -0
  134. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/menus.py +0 -0
  135. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/services/__init__.py +0 -0
  136. {latch-2.40.4/tests → latch-2.40.4.dev0/latch_cli/services/cp}/__init__.py +0 -0
  137. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/services/cp/glob.py +0 -0
  138. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/services/cp/main.py +0 -0
  139. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/services/cp/utils.py +3 -3
  140. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/services/execute/main.py +0 -0
  141. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/services/execute/utils.py +0 -0
  142. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/services/get.py +0 -0
  143. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/services/get_params.py +0 -0
  144. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/services/init/__init__.py +0 -0
  145. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/services/init/__pycache__/__init__.cpython-310.pyc +0 -0
  146. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/services/init/__pycache__/__init__.cpython-311.pyc +0 -0
  147. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/services/init/__pycache__/__init__.cpython-38.pyc +0 -0
  148. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/services/init/__pycache__/__init__.cpython-39.pyc +0 -0
  149. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/services/init/__pycache__/init.cpython-310.pyc +0 -0
  150. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/services/init/__pycache__/init.cpython-38.pyc +0 -0
  151. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/services/init/__pycache__/init.cpython-39.pyc +0 -0
  152. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/services/init/assemble_and_sort/.env +0 -0
  153. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/services/init/assemble_and_sort/LICENSE +0 -0
  154. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/services/init/assemble_and_sort/README.md +0 -0
  155. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/services/init/assemble_and_sort/__pycache__/__init__.cpython-310.pyc +0 -0
  156. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/services/init/assemble_and_sort/assemble.py +0 -0
  157. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/services/init/assemble_and_sort/sort.py +0 -0
  158. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/services/init/assemble_and_sort/system-requirements.txt +0 -0
  159. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/services/init/example_conda/__init__.py +0 -0
  160. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/services/init/example_conda/__pycache__/__init__.cpython-310.pyc +0 -0
  161. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/services/init/example_conda/environment.yaml +0 -0
  162. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/services/init/example_docker/__init__.py +0 -0
  163. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/services/init/example_docker/task.py +0 -0
  164. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/services/init/example_nf_integration/latch_metadata/__pycache__/__init__.cpython-311.pyc +0 -0
  165. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/services/init/example_nfcore/Dockerfile +0 -0
  166. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/services/init/example_nfcore/task.py +0 -0
  167. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/services/init/example_r/__init__.py +0 -0
  168. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/services/init/example_r/__pycache__/__init__.cpython-310.pyc +0 -0
  169. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/services/init/example_r/environment.R +0 -0
  170. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/services/init/example_snakemake/.latch/latch_entrypoint +0 -0
  171. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/services/init/example_snakemake/Dockerfile +0 -0
  172. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/services/init/example_snakemake/Snakefile +0 -0
  173. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/services/init/example_snakemake/config.yaml +0 -0
  174. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/services/init/example_snakemake/environment.yaml +0 -0
  175. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/services/init/example_snakemake/latch_metadata.py +0 -0
  176. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/services/init/example_snakemake/scripts/plot-quals.py +0 -0
  177. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/services/init/example_snakemake/version +0 -0
  178. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/services/init/template/LICENSE +0 -0
  179. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/services/init/template/README.md +0 -0
  180. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/services/init/template/__init__.py +0 -0
  181. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/services/init/template/__pycache__/__init__.cpython-310.pyc +0 -0
  182. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/services/init/template/task.py +0 -0
  183. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/services/launch.py +0 -0
  184. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/services/local_dev.py +0 -0
  185. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/services/ls.py +0 -0
  186. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/services/mkdir.py +0 -0
  187. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/services/register/__init__.py +0 -0
  188. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/services/register/constants.py +0 -0
  189. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/services/register/utils.py +0 -0
  190. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/services/rm.py +0 -0
  191. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/services/stop_pod.py +0 -0
  192. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/services/sync.py +0 -0
  193. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/services/test_data/ls.py +0 -0
  194. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/services/test_data/remove.py +0 -0
  195. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/services/test_data/upload.py +0 -0
  196. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/services/test_data/utils.py +0 -0
  197. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/tinyrequests.py +0 -0
  198. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/utils/path.py +0 -0
  199. {latch-2.40.4 → latch-2.40.4.dev0}/latch_cli/workflow_config.py +0 -0
  200. {latch-2.40.4 → latch-2.40.4.dev0}/pyproject.toml +0 -0
  201. {latch-2.40.4 → latch-2.40.4.dev0}/setup.cfg +0 -0
  202. {latch-2.40.4 → latch-2.40.4.dev0}/tests/cp/__init__.py +0 -0
  203. {latch-2.40.4 → latch-2.40.4.dev0}/tests/fixtures.py +0 -0
  204. {latch-2.40.4 → latch-2.40.4.dev0}/tests/test_ls.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: latch
3
- Version: 2.40.4
3
+ Version: 2.40.4.dev0
4
4
  Summary: The Latch SDK
5
5
  Author-email: kenny@latch.bio
6
6
  Classifier: Programming Language :: Python :: 3.8
@@ -141,6 +141,9 @@ class LatchDir(FlyteDirectory):
141
141
 
142
142
  super().__init__(self.path, downloader, self._remote_directory)
143
143
 
144
+ def __hash__(self) -> int:
145
+ return hash(self.path)
146
+
144
147
  def _idempotent_set_path(self):
145
148
  if self._path_generated:
146
149
  return
@@ -268,6 +271,9 @@ LatchOutputDir = Annotated[
268
271
  {"output": True},
269
272
  ),
270
273
  ]
274
+
275
+ LatchOutputDir.__name__ = "LatchOutputDir"
276
+
271
277
  """A LatchDir tagged as the output of some workflow.
272
278
 
273
279
  The Latch Console uses this metadata to avoid checking for existence of the
@@ -120,6 +120,9 @@ class LatchFile(FlyteFile):
120
120
 
121
121
  super().__init__(self.path, downloader, self._remote_path)
122
122
 
123
+ def __hash__(self) -> int:
124
+ return hash(self.path)
125
+
123
126
  def size(self):
124
127
  return LPath(self.remote_path).size()
125
128
 
@@ -3,16 +3,28 @@ 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
23
  from typing_extensions import TypeAlias
11
24
 
12
- from latch_cli.snakemake.config.utils import validate_snakemake_type
13
25
  from latch_cli.utils import identifier_suffix_from_str
14
26
 
15
- from .directory import LatchDir
27
+ from .directory import LatchDir, LatchOutputDir
16
28
  from .file import LatchFile
17
29
 
18
30
 
@@ -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,29 @@ 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
+
482
+ @dataclass
483
+ class NextflowFileParameter(NextflowParameter[Union[LatchFile, LatchDir]]):
484
+ path: Optional[Path] = None
485
+ """
486
+ The path where the file passed to this parameter will be copied.
487
+ """
488
+
489
+ _download: bool = field(default=True, init=False)
490
+
491
+ def __post_init__(self):
492
+ if self.type is LatchOutputDir:
493
+ self._download = False
494
+
495
+
459
496
  @dataclass
460
497
  class LatchMetadata:
461
498
  """Class for organizing workflow metadata
@@ -571,6 +608,10 @@ class DockerMetadata:
571
608
  """
572
609
  The name of the Latch Secret that contains the password for the private repository
573
610
  """
611
+ server: Optional[str] = None
612
+ """
613
+ The name of a docker server to login to, if relevant (eg. registry.gitlab.com)
614
+ """
574
615
 
575
616
 
576
617
  @dataclass
@@ -628,6 +669,7 @@ class SnakemakeMetadata(LatchMetadata):
628
669
  """
629
670
 
630
671
  def validate(self):
672
+ from latch_cli.extras.snakemake.config import validate_snakemake_type
631
673
 
632
674
  for name, param in self.parameters.items():
633
675
  if param.default is None:
@@ -651,3 +693,26 @@ 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
+ parameters: Dict[str, NextflowParameter] = field(default_factory=dict)
702
+ output_directory: Optional[LatchDir] = None
703
+ docker_metadata: Optional[DockerMetadata] = None
704
+
705
+ def __post_init__(self):
706
+ if self.name is None:
707
+ self.name = f"nf_{identifier_suffix_from_str(self.display_name.lower())}"
708
+ else:
709
+ self.name = identifier_suffix_from_str(self.name)
710
+
711
+ if self.output_directory is None:
712
+ self.output_directory = LatchDir("latch:///Nextflow Outputs/")
713
+
714
+ global _nextflow_metadata
715
+ _nextflow_metadata = self
716
+
717
+
718
+ _nextflow_metadata: Optional[NextflowMetadata] = None
@@ -1,3 +1,4 @@
1
+ import os
1
2
  from typing import Dict
2
3
 
3
4
  import gql
@@ -84,17 +85,24 @@ def current_workspace() -> str:
84
85
  """
85
86
  ws = user_config.workspace_id
86
87
  if ws == "":
87
- default_ws = execute(
88
+ res = execute(
88
89
  gql.gql("""
89
90
  query DefaultAccountQuery {
90
91
  accountInfoCurrent {
92
+ id
91
93
  user {
92
94
  defaultAccount
93
95
  }
94
96
  }
95
97
  }
96
98
  """),
97
- )["accountInfoCurrent"]["user"]["defaultAccount"]
99
+ )["accountInfoCurrent"]
100
+
101
+ default_ws = res["id"]
102
+
103
+ is_local = os.environ.get("FLYTE_INTERNAL_EXECUTION_ID") is None
104
+ if is_local:
105
+ default_ws = res["user"]["defaultAccount"]
98
106
 
99
107
  if default_ws is not None:
100
108
  ws = default_ws
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: latch
3
- Version: 2.40.4
3
+ Version: 2.40.4.dev0
4
4
  Summary: The Latch SDK
5
5
  Author-email: kenny@latch.bio
6
6
  Classifier: Programming Language :: Python :: 3.8
@@ -80,6 +80,35 @@ 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/extras/__init__.py
84
+ latch_cli/extras/common/__init__.py
85
+ latch_cli/extras/common/serialize.py
86
+ latch_cli/extras/common/utils.py
87
+ latch_cli/extras/common/config/__init__.py
88
+ latch_cli/extras/common/config/parser.py
89
+ latch_cli/extras/common/config/utils.py
90
+ latch_cli/extras/nextflow/__init__.py
91
+ latch_cli/extras/nextflow/build.py
92
+ latch_cli/extras/nextflow/channel.py
93
+ latch_cli/extras/nextflow/config.py
94
+ latch_cli/extras/nextflow/dag.py
95
+ latch_cli/extras/nextflow/file_persistence.py
96
+ latch_cli/extras/nextflow/serialize.py
97
+ latch_cli/extras/nextflow/workflow.py
98
+ latch_cli/extras/nextflow/tasks/__init__.py
99
+ latch_cli/extras/nextflow/tasks/adapters.py
100
+ latch_cli/extras/nextflow/tasks/base.py
101
+ latch_cli/extras/nextflow/tasks/conditional.py
102
+ latch_cli/extras/nextflow/tasks/map.py
103
+ latch_cli/extras/nextflow/tasks/merge.py
104
+ latch_cli/extras/nextflow/tasks/operator.py
105
+ latch_cli/extras/nextflow/tasks/process.py
106
+ latch_cli/extras/snakemake/__init__.py
107
+ latch_cli/extras/snakemake/config.py
108
+ latch_cli/extras/snakemake/serialize.py
109
+ latch_cli/extras/snakemake/single_task_snakemake.py
110
+ latch_cli/extras/snakemake/utils.py
111
+ latch_cli/extras/snakemake/workflow.py
83
112
  latch_cli/services/__init__.py
84
113
  latch_cli/services/get.py
85
114
  latch_cli/services/get_executions.py
@@ -129,6 +158,9 @@ latch_cli/services/init/example_conda/environment.yaml
129
158
  latch_cli/services/init/example_conda/__pycache__/__init__.cpython-310.pyc
130
159
  latch_cli/services/init/example_docker/__init__.py
131
160
  latch_cli/services/init/example_docker/task.py
161
+ latch_cli/services/init/example_nextflow/main.nf
162
+ latch_cli/services/init/example_nextflow/nextflow.config
163
+ latch_cli/services/init/example_nextflow/workflow.nf
132
164
  latch_cli/services/init/example_nf_integration/latch_metadata/__pycache__/__init__.cpython-311.pyc
133
165
  latch_cli/services/init/example_nfcore/Dockerfile
134
166
  latch_cli/services/init/example_nfcore/__init__.py
@@ -159,18 +191,10 @@ latch_cli/services/test_data/ls.py
159
191
  latch_cli/services/test_data/remove.py
160
192
  latch_cli/services/test_data/upload.py
161
193
  latch_cli/services/test_data/utils.py
162
- latch_cli/snakemake/__init__.py
163
- latch_cli/snakemake/serialize.py
164
- latch_cli/snakemake/serialize_utils.py
165
- latch_cli/snakemake/single_task_snakemake.py
166
- latch_cli/snakemake/utils.py
167
- latch_cli/snakemake/workflow.py
168
- latch_cli/snakemake/config/__init__.py
169
- latch_cli/snakemake/config/parser.py
170
- latch_cli/snakemake/config/utils.py
171
194
  latch_cli/tui/__init__.py
172
195
  latch_cli/utils/__init__.py
173
196
  latch_cli/utils/path.py
197
+ latch_cli/utils/workflow.py
174
198
  tests/__init__.py
175
199
  tests/fixtures.py
176
200
  tests/test_ls.py
@@ -164,15 +164,13 @@ class OAuth2:
164
164
  """
165
165
 
166
166
  token_url = self.authz_server_host + "/oauth/token"
167
- token_body: bytes = json.dumps(
168
- {
169
- "grant_type": "authorization_code",
170
- "client_id": self.client_id,
171
- "code_verifier": self.pkce.verifier,
172
- "code": auth_code,
173
- "redirect_uri": self.redirect_url,
174
- }
175
- ).encode("utf-8")
167
+ token_body: bytes = json.dumps({
168
+ "grant_type": "authorization_code",
169
+ "client_id": self.client_id,
170
+ "code_verifier": self.pkce.verifier,
171
+ "code": auth_code,
172
+ "redirect_uri": self.redirect_url,
173
+ }).encode("utf-8")
176
174
  token_request = urllib.request.Request(token_url, token_body)
177
175
  token_request.add_header("Content-Type", "application/json")
178
176
  with urllib.request.urlopen(
@@ -1,10 +1,12 @@
1
+ import os
1
2
  import re
2
3
  import sys
4
+ import time
3
5
  import traceback
4
6
  from dataclasses import dataclass
5
7
  from pathlib import Path
6
8
  from textwrap import dedent
7
- from typing import Dict, Optional, Tuple
9
+ from typing import Dict, Optional, Tuple, cast
8
10
 
9
11
  import click
10
12
  import docker
@@ -51,7 +53,7 @@ class _CentromereCtx:
51
53
  dkr_repo: Optional[str] = None
52
54
  dkr_client: Optional[docker.APIClient] = None
53
55
  ssh_client: Optional[paramiko.SSHClient] = None
54
- pkg_root: Optional[Path] = None # root
56
+ pkg_root: Path # root
55
57
  disable_auto_version: bool = False
56
58
  image_full = None
57
59
  version = None
@@ -59,6 +61,7 @@ class _CentromereCtx:
59
61
  default_container: _Container
60
62
  workflow_type: WorkflowType
61
63
  snakefile: Optional[Path]
64
+ nf_script: Optional[Path]
62
65
 
63
66
  latch_register_api_url = config.api.workflow.register
64
67
  latch_image_api_url = config.api.workflow.upload_image
@@ -80,26 +83,37 @@ class _CentromereCtx:
80
83
  disable_auto_version: bool = False,
81
84
  remote: bool = False,
82
85
  snakefile: Optional[Path] = None,
86
+ nf_script: Optional[Path] = None,
83
87
  use_new_centromere: bool = False,
84
88
  ):
85
89
  self.use_new_centromere = use_new_centromere
86
90
  self.remote = remote
87
91
  self.disable_auto_version = disable_auto_version
92
+ self.pkg_root = pkg_root.resolve()
88
93
 
89
94
  try:
90
95
  self.token = retrieve_or_login()
91
96
  self.account_id = current_workspace()
92
97
 
93
98
  self.dkr_repo = config.dkr_repo
94
- self.pkg_root = pkg_root.resolve()
95
99
 
96
- if snakefile is None:
97
- self.workflow_type = WorkflowType.latchbiosdk
98
- else:
100
+ if snakefile and nf_script:
101
+ raise ValueError(
102
+ "Cannot provide both a snakefile and nextflow script to the"
103
+ " register command."
104
+ )
105
+
106
+ if snakefile is not None:
99
107
  self.workflow_type = WorkflowType.snakemake
100
108
  self.snakefile = snakefile
109
+ elif nf_script is not None:
110
+ self.workflow_type = WorkflowType.nextflow
111
+ self.nf_script = nf_script
112
+ else:
113
+ self.workflow_type = WorkflowType.latchbiosdk
101
114
 
102
115
  self.container_map: Dict[str, _Container] = {}
116
+
103
117
  if self.workflow_type == WorkflowType.latchbiosdk:
104
118
  _import_flyte_objects([self.pkg_root])
105
119
  for entity in FlyteEntities.entities:
@@ -107,36 +121,40 @@ class _CentromereCtx:
107
121
  self.workflow_name = entity.name
108
122
 
109
123
  if isinstance(entity, PythonTask):
110
- if (
111
- hasattr(entity, "dockerfile_path")
112
- and entity.dockerfile_path is not None
113
- ):
124
+ dockerfile_path: Optional[Path] = getattr(
125
+ entity, "dockerfile_path", None
126
+ )
127
+
128
+ if dockerfile_path is not None:
114
129
  self.container_map[entity.name] = _Container(
115
- dockerfile=entity.dockerfile_path,
130
+ dockerfile=dockerfile_path,
116
131
  image_name=self.task_image_name(entity.name),
117
- pkg_dir=entity.dockerfile_path.parent,
132
+ pkg_dir=dockerfile_path.parent,
118
133
  )
134
+
119
135
  if not hasattr(self, "workflow_name"):
120
136
  click.secho(
121
137
  dedent("""
122
- Unable to locate workflow code. If you
123
- are a registering a Snakemake project,
124
- make sure to pass the Snakefile path with
125
- the --snakefile flag."""),
138
+ Unable to locate workflow code.
139
+
140
+ If you are a registering a Snakemake/Nextflow project, make sure to pass the appropriate
141
+ script with either the --snakefile or --nf-script flag.
142
+ """),
126
143
  fg="red",
127
144
  )
128
145
  raise click.exceptions.Exit(1)
129
- else:
146
+
147
+ elif self.workflow_type == WorkflowType.snakemake:
130
148
  assert snakefile is not None
131
149
 
132
150
  import latch.types.metadata as metadata
133
151
 
134
- from ..services.register.utils import import_module_by_path
135
- from ..snakemake.serialize import (
152
+ from ..extras.snakemake.serialize import (
136
153
  get_snakemake_metadata_example,
137
154
  snakemake_workflow_extractor,
138
155
  )
139
- from ..snakemake.utils import load_snakemake_metadata
156
+ from ..extras.snakemake.utils import load_snakemake_metadata
157
+ from ..services.register.utils import import_module_by_path
140
158
 
141
159
  meta_file = load_snakemake_metadata(pkg_root)
142
160
  if meta_file is not None:
@@ -151,18 +169,17 @@ class _CentromereCtx:
151
169
  except (ImportError, FileNotFoundError):
152
170
  traceback.print_exc()
153
171
  click.secho(
154
- "\n\n\n"
155
- + "The above error occured when reading "
156
- + "the Snakefile to extract workflow metadata.",
172
+ "\n\n\nThe above error occurred when reading the Snakefile"
173
+ " to extract workflow metadata.",
157
174
  bold=True,
158
175
  fg="red",
159
176
  )
160
177
  click.secho(
161
- "\nIt is possible to avoid including the Snakefile"
162
- " prior to registration by providing a"
163
- " `latch_metadata.py` file in the workflow root.\nThis"
164
- " way it is not necessary to install dependencies or"
165
- " ensure that Snakemake inputs locally.",
178
+ "\nIt is possible to avoid including the Snakefile prior to"
179
+ " registration by providing a `latch_metadata.py` file in"
180
+ " the workflow root.\nThis way it is not necessary to"
181
+ " install dependencies or ensure that Snakemake inputs"
182
+ " locally.",
166
183
  fg="red",
167
184
  )
168
185
  click.secho("\nExample ", fg="red", nl=False)
@@ -207,15 +224,14 @@ class _CentromereCtx:
207
224
  elif system == "Darwin":
208
225
  res = subprocess.run(["open", new_meta]).returncode
209
226
  elif system == "Windows":
210
- import os
211
-
212
227
  res = os.system(str(new_meta.resolve()))
213
228
  else:
214
229
  res = None
215
230
 
216
231
  if res is not None and res != 0:
217
232
  click.secho("Failed to open file", fg="red")
218
- sys.exit(1)
233
+
234
+ raise click.exceptions.Exit(1)
219
235
 
220
236
  if metadata._snakemake_metadata is None:
221
237
  click.secho(
@@ -232,6 +248,34 @@ class _CentromereCtx:
232
248
  # name for snakemake
233
249
  self.workflow_name = f"{metadata._snakemake_metadata.name}_jit_register"
234
250
 
251
+ else:
252
+ assert nf_script is not None
253
+
254
+ import latch.types.metadata as metadata
255
+
256
+ from ..services.register.utils import import_module_by_path
257
+
258
+ meta = pkg_root / "latch_metadata" / "__init__.py"
259
+ if meta.exists():
260
+ click.echo(f"Using metadata file {click.style(meta, italic=True)}")
261
+ import_module_by_path(meta)
262
+
263
+ if metadata._nextflow_metadata is None:
264
+ click.secho(
265
+ dedent(
266
+ "Make sure a `latch_metadata` package exists in the"
267
+ " nextflow project root."
268
+ "\nYou can generate this package with the"
269
+ "`latch generate-metadata --nextflow <pkg_root>` command.",
270
+ ),
271
+ fg="red",
272
+ )
273
+ raise click.exceptions.Exit(1)
274
+
275
+ self.workflow_name = metadata._nextflow_metadata.name
276
+
277
+ assert self.workflow_name is not None
278
+
235
279
  version_file = self.pkg_root / "version"
236
280
  try:
237
281
  self.version = version_file.read_text()
@@ -246,7 +290,11 @@ class _CentromereCtx:
246
290
  if not self.disable_auto_version:
247
291
  hash = hash_directory(self.pkg_root)
248
292
  self.version = f"{self.version}-{hash[:6]}"
249
- click.echo(f" {self.version}\n")
293
+
294
+ if os.environ.get("LATCH_NEW_VERSION_ALWAYS") is not None:
295
+ self.version = f"{self.version}-{int(time.monotonic())}"
296
+
297
+ click.echo()
250
298
 
251
299
  if self.nucleus_check_version(self.version, self.workflow_name):
252
300
  click.secho(
@@ -324,6 +372,8 @@ class _CentromereCtx:
324
372
 
325
373
  from ..utils import identifier_suffix_from_str
326
374
 
375
+ assert self.workflow_name is not None
376
+
327
377
  wf_name = identifier_suffix_from_str(self.workflow_name).lower()
328
378
  wf_name = docker_image_name_illegal_pat.sub("_", wf_name)
329
379
 
@@ -110,6 +110,9 @@ class AnsiCodes:
110
110
  bold = "\x1b[1m"
111
111
  reset_bold = "\x1b[22m"
112
112
 
113
+ italic = "\x1b[3m"
114
+ reset_italic = "\x1b[23m"
115
+
113
116
  underline = "\x1b[4m"
114
117
  no_underline = "\x1b[24m"
115
118
 
@@ -119,13 +122,17 @@ class AnsiCodes:
119
122
  url_end = "\x1b]8;;\x1b\\"
120
123
 
121
124
 
122
- def bold(s: str) -> str:
125
+ def italic(s: object) -> str:
126
+ return f"{AnsiCodes.italic}{s}{AnsiCodes.reset_italic}"
127
+
128
+
129
+ def bold(s: object) -> str:
123
130
  return f"{AnsiCodes.bold}{s}{AnsiCodes.reset_bold}"
124
131
 
125
132
 
126
- def underline(s: str) -> str:
133
+ def underline(s: object) -> str:
127
134
  return f"{AnsiCodes.underline}{s}{AnsiCodes.no_underline}"
128
135
 
129
136
 
130
- def color(s: str, *, color: str = AnsiCodes.color):
137
+ def color(s: object, *, color: str = AnsiCodes.color):
131
138
  return f"{color}{s}{AnsiCodes.reset_color}"
@@ -9,6 +9,7 @@ from typing import List
9
9
  import click
10
10
  import yaml
11
11
 
12
+ from latch_cli.click_utils import color
12
13
  from latch_cli.constants import latch_constants
13
14
  from latch_cli.utils import WorkflowType
14
15
  from latch_cli.workflow_config import LatchWorkflowConfig, create_and_write_config
@@ -37,9 +38,12 @@ def get_prologue(
37
38
  ) -> List[str]:
38
39
  if wf_type == WorkflowType.snakemake:
39
40
  library_name = '"latch[snakemake]"'
41
+ elif wf_type == WorkflowType.nextflow:
42
+ library_name = '"latch[nextflow]"'
40
43
  else:
41
44
  library_name = "latch"
42
- return [
45
+
46
+ directives = [
43
47
  "# DO NOT CHANGE",
44
48
  f"from {config.base_image}",
45
49
  "",
@@ -68,6 +72,11 @@ def get_prologue(
68
72
  f"run pip install {library_name}=={config.latch_version}",
69
73
  "run mkdir /opt/latch",
70
74
  ]
75
+ if wf_type == WorkflowType.nextflow:
76
+ directives.append(
77
+ "run apt-get update && apt-get install -y default-jre-headless"
78
+ )
79
+ return directives
71
80
 
72
81
 
73
82
  def get_epilogue(wf_type: WorkflowType = WorkflowType.latchbiosdk) -> List[str]:
@@ -78,8 +87,19 @@ def get_epilogue(wf_type: WorkflowType = WorkflowType.latchbiosdk) -> List[str]:
78
87
  "",
79
88
  "# Latch snakemake workflow entrypoint",
80
89
  "# DO NOT CHANGE",
90
+ "",
81
91
  "copy .latch/snakemake_jit_entrypoint.py /root/snakemake_jit_entrypoint.py",
82
92
  ]
93
+ elif wf_type == WorkflowType.nextflow:
94
+ cmds += [
95
+ "",
96
+ "# Latch nextflow workflow entrypoint",
97
+ "# DO NOT CHANGE",
98
+ "",
99
+ "copy .latch/bin/nextflow /root/nextflow",
100
+ "copy .latch/.nextflow /root/.nextflow",
101
+ "copy .latch/nf_entrypoint.py /root/nf_entrypoint.py",
102
+ ]
83
103
 
84
104
  cmds += [
85
105
  "",
@@ -339,18 +359,8 @@ def generate_dockerfile(
339
359
  with (pkg_root / latch_constants.pkg_config).open("r") as f:
340
360
  config = LatchWorkflowConfig(**json.load(f))
341
361
 
342
- click.echo(
343
- " ".join([
344
- click.style("Base image:", fg="bright_blue"),
345
- config.base_image,
346
- ])
347
- )
348
- click.echo(
349
- " ".join([
350
- click.style("Latch SDK version:", fg="bright_blue"),
351
- config.latch_version,
352
- ])
353
- )
362
+ click.echo(" ".join([color("Base image:"), config.base_image]))
363
+ click.echo(" ".join([color("Latch SDK version:"), config.latch_version]))
354
364
  click.echo()
355
365
 
356
366
  with outfile.open("w") as f: