latch 2.39.0.dev24__tar.gz → 2.39.0.dev26__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.39.0.dev24/latch.egg-info → latch-2.39.0.dev26}/PKG-INFO +1 -1
  2. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch/types/metadata.py +2 -0
  3. {latch-2.39.0.dev24 → latch-2.39.0.dev26/latch.egg-info}/PKG-INFO +1 -1
  4. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch.egg-info/SOURCES.txt +3 -0
  5. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/docker_utils/__init__.py +3 -12
  6. latch-2.39.0.dev26/latch_cli/extras/common/config/parser.py +82 -0
  7. latch-2.39.0.dev26/latch_cli/extras/common/config/utils.py +235 -0
  8. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/extras/common/serialize.py +23 -9
  9. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/extras/common/utils.py +9 -2
  10. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/extras/nextflow/build.py +5 -3
  11. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/extras/nextflow/config.py +6 -2
  12. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/extras/nextflow/serialize.py +1 -1
  13. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/extras/nextflow/tasks/base.py +2 -2
  14. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/extras/nextflow/tasks/operator.py +2 -2
  15. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/extras/nextflow/tasks/process.py +2 -2
  16. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/extras/nextflow/workflow.py +33 -12
  17. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/setup.py +1 -1
  18. latch-2.39.0.dev26/tests/__init__.py +0 -0
  19. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/LICENSE +0 -0
  20. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/MANIFEST.in +0 -0
  21. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/README.md +0 -0
  22. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch/__init__.py +0 -0
  23. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch/account.py +0 -0
  24. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch/executions.py +0 -0
  25. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch/functions/__init__.py +0 -0
  26. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch/functions/messages.py +0 -0
  27. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch/functions/operators.py +0 -0
  28. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch/functions/secrets.py +0 -0
  29. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch/ldata/__init__.py +0 -0
  30. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch/ldata/_transfer/__init__.py +0 -0
  31. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch/ldata/_transfer/download.py +0 -0
  32. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch/ldata/_transfer/manager.py +0 -0
  33. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch/ldata/_transfer/node.py +0 -0
  34. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch/ldata/_transfer/progress.py +0 -0
  35. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch/ldata/_transfer/remote_copy.py +0 -0
  36. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch/ldata/_transfer/throttle.py +0 -0
  37. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch/ldata/_transfer/upload.py +0 -0
  38. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch/ldata/_transfer/utils.py +0 -0
  39. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch/ldata/path.py +0 -0
  40. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch/ldata/type.py +0 -0
  41. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch/registry/__init__.py +0 -0
  42. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch/registry/project.py +0 -0
  43. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch/registry/record.py +0 -0
  44. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch/registry/table.py +0 -0
  45. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch/registry/types.py +0 -0
  46. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch/registry/upstream_types/__init__.py +0 -0
  47. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch/registry/upstream_types/types.py +0 -0
  48. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch/registry/upstream_types/values.py +0 -0
  49. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch/registry/utils.py +0 -0
  50. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch/resources/__init__.py +0 -0
  51. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch/resources/conditional.py +0 -0
  52. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch/resources/launch_plan.py +0 -0
  53. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch/resources/map_tasks.py +0 -0
  54. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch/resources/reference_workflow.py +0 -0
  55. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch/resources/tasks.py +0 -0
  56. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch/resources/workflow.py +0 -0
  57. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch/types/__init__.py +0 -0
  58. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch/types/directory.py +0 -0
  59. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch/types/file.py +0 -0
  60. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch/types/glob.py +0 -0
  61. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch/types/json.py +0 -0
  62. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch/types/utils.py +0 -0
  63. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch/verified/__init__.py +0 -0
  64. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch/verified/deseq2.py +0 -0
  65. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch/verified/mafft.py +0 -0
  66. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch/verified/pathway.py +0 -0
  67. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch/verified/rnaseq.py +0 -0
  68. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch/verified/trim_galore.py +0 -0
  69. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch.egg-info/dependency_links.txt +0 -0
  70. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch.egg-info/entry_points.txt +0 -0
  71. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch.egg-info/requires.txt +0 -0
  72. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch.egg-info/top_level.txt +0 -0
  73. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/__init__.py +0 -0
  74. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/auth/__init__.py +0 -0
  75. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/auth/csrf.py +0 -0
  76. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/auth/oauth2.py +0 -0
  77. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/auth/pkce.py +0 -0
  78. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/auth/utils.py +0 -0
  79. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/centromere/__init__.py +0 -0
  80. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/centromere/ctx.py +0 -0
  81. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/centromere/utils.py +0 -0
  82. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/click_utils.py +0 -0
  83. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/constants.py +0 -0
  84. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/exceptions/__init__.py +0 -0
  85. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/exceptions/cache.py +0 -0
  86. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/exceptions/errors.py +0 -0
  87. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/exceptions/handler.py +0 -0
  88. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/exceptions/traceback.py +0 -0
  89. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/extras/__init__.py +0 -0
  90. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/extras/common/__init__.py +0 -0
  91. {latch-2.39.0.dev24/latch_cli/extras/nextflow → latch-2.39.0.dev26/latch_cli/extras/common/config}/__init__.py +0 -0
  92. {latch-2.39.0.dev24/latch_cli/extras/nextflow/tasks → latch-2.39.0.dev26/latch_cli/extras/nextflow}/__init__.py +0 -0
  93. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/extras/nextflow/channel.py +0 -0
  94. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/extras/nextflow/dag.py +0 -0
  95. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/extras/nextflow/file_persistence.py +0 -0
  96. {latch-2.39.0.dev24/latch_cli/extras/snakemake → latch-2.39.0.dev26/latch_cli/extras/nextflow/tasks}/__init__.py +0 -0
  97. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/extras/nextflow/tasks/adapters.py +0 -0
  98. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/extras/nextflow/tasks/conditional.py +0 -0
  99. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/extras/nextflow/tasks/input.py +0 -0
  100. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/extras/nextflow/tasks/map.py +0 -0
  101. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/extras/nextflow/tasks/merge.py +0 -0
  102. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/extras/nextflow/tasks/output.py +0 -0
  103. {latch-2.39.0.dev24/latch_cli/services/cp → latch-2.39.0.dev26/latch_cli/extras/snakemake}/__init__.py +0 -0
  104. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/extras/snakemake/config.py +0 -0
  105. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/extras/snakemake/serialize.py +0 -0
  106. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/extras/snakemake/single_task_snakemake.py +0 -0
  107. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/extras/snakemake/utils.py +0 -0
  108. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/extras/snakemake/workflow.py +0 -0
  109. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/main.py +0 -0
  110. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/menus.py +0 -0
  111. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/services/__init__.py +0 -0
  112. {latch-2.39.0.dev24/latch_cli/services/execute → latch-2.39.0.dev26/latch_cli/services/cp}/__init__.py +0 -0
  113. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/services/cp/autocomplete.py +0 -0
  114. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/services/cp/glob.py +0 -0
  115. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/services/cp/main.py +0 -0
  116. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/services/cp/utils.py +0 -0
  117. {latch-2.39.0.dev24/latch_cli/services/test_data → latch-2.39.0.dev26/latch_cli/services/execute}/__init__.py +0 -0
  118. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/services/execute/main.py +0 -0
  119. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/services/execute/utils.py +0 -0
  120. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/services/get.py +0 -0
  121. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/services/get_executions.py +0 -0
  122. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/services/get_params.py +0 -0
  123. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/services/init/__init__.py +0 -0
  124. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/services/init/__pycache__/__init__.cpython-310.pyc +0 -0
  125. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/services/init/__pycache__/__init__.cpython-311.pyc +0 -0
  126. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/services/init/__pycache__/__init__.cpython-38.pyc +0 -0
  127. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/services/init/__pycache__/__init__.cpython-39.pyc +0 -0
  128. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/services/init/__pycache__/init.cpython-310.pyc +0 -0
  129. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/services/init/__pycache__/init.cpython-311.pyc +0 -0
  130. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/services/init/__pycache__/init.cpython-38.pyc +0 -0
  131. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/services/init/__pycache__/init.cpython-39.pyc +0 -0
  132. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/services/init/assemble_and_sort/.env +0 -0
  133. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/services/init/assemble_and_sort/LICENSE +0 -0
  134. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/services/init/assemble_and_sort/README.md +0 -0
  135. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/services/init/assemble_and_sort/__init__.py +0 -0
  136. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/services/init/assemble_and_sort/__pycache__/__init__.cpython-310.pyc +0 -0
  137. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/services/init/assemble_and_sort/assemble.py +0 -0
  138. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/services/init/assemble_and_sort/sort.py +0 -0
  139. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/services/init/assemble_and_sort/system-requirements.txt +0 -0
  140. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/services/init/common/.dockerignore +0 -0
  141. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/services/init/example_conda/__init__.py +0 -0
  142. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/services/init/example_conda/__pycache__/__init__.cpython-310.pyc +0 -0
  143. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/services/init/example_conda/conda_task.py +0 -0
  144. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/services/init/example_conda/environment.yaml +0 -0
  145. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/services/init/example_docker/__init__.py +0 -0
  146. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/services/init/example_docker/task.py +0 -0
  147. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/services/init/example_nf_integration/Dockerfile +0 -0
  148. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/services/init/example_nf_integration/latch_metadata/__init__.py +0 -0
  149. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/services/init/example_nf_integration/latch_metadata/__pycache__/__init__.cpython-311.pyc +0 -0
  150. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/services/init/example_nf_integration/main.nf +0 -0
  151. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/services/init/example_nf_integration/workflow.nf +0 -0
  152. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/services/init/example_nfcore/Dockerfile +0 -0
  153. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/services/init/example_nfcore/__init__.py +0 -0
  154. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/services/init/example_nfcore/task.py +0 -0
  155. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/services/init/example_r/__init__.py +0 -0
  156. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/services/init/example_r/__pycache__/__init__.cpython-310.pyc +0 -0
  157. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/services/init/example_r/environment.R +0 -0
  158. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/services/init/example_r/r_task.py +0 -0
  159. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/services/init/example_snakemake/.latch/latch_entrypoint +0 -0
  160. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/services/init/example_snakemake/Dockerfile +0 -0
  161. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/services/init/example_snakemake/Snakefile +0 -0
  162. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/services/init/example_snakemake/config.yaml +0 -0
  163. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/services/init/example_snakemake/environment.yaml +0 -0
  164. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/services/init/example_snakemake/latch_metadata.py +0 -0
  165. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/services/init/example_snakemake/scripts/plot-quals.py +0 -0
  166. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/services/init/example_snakemake/version +0 -0
  167. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/services/init/init.py +0 -0
  168. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/services/init/template/LICENSE +0 -0
  169. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/services/init/template/README.md +0 -0
  170. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/services/init/template/__init__.py +0 -0
  171. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/services/init/template/__pycache__/__init__.cpython-310.pyc +0 -0
  172. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/services/init/template/task.py +0 -0
  173. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/services/launch.py +0 -0
  174. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/services/local_dev.py +0 -0
  175. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/services/local_dev_old.py +0 -0
  176. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/services/login.py +0 -0
  177. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/services/ls.py +0 -0
  178. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/services/mkdir.py +0 -0
  179. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/services/move.py +0 -0
  180. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/services/preview.py +0 -0
  181. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/services/register/__init__.py +0 -0
  182. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/services/register/constants.py +0 -0
  183. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/services/register/register.py +0 -0
  184. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/services/register/utils.py +0 -0
  185. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/services/rm.py +0 -0
  186. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/services/stop_pod.py +0 -0
  187. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/services/sync.py +0 -0
  188. {latch-2.39.0.dev24/latch_cli/tui → latch-2.39.0.dev26/latch_cli/services/test_data}/__init__.py +0 -0
  189. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/services/test_data/ls.py +0 -0
  190. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/services/test_data/remove.py +0 -0
  191. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/services/test_data/upload.py +0 -0
  192. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/services/test_data/utils.py +0 -0
  193. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/services/workspace.py +0 -0
  194. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/tinyrequests.py +0 -0
  195. {latch-2.39.0.dev24/tests → latch-2.39.0.dev26/latch_cli/tui}/__init__.py +0 -0
  196. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/utils/__init__.py +0 -0
  197. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/utils/path.py +0 -0
  198. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/utils/workflow.py +0 -0
  199. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/latch_cli/workflow_config.py +0 -0
  200. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/pyproject.toml +0 -0
  201. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/setup.cfg +0 -0
  202. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/tests/cp/__init__.py +0 -0
  203. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/tests/fixtures.py +0 -0
  204. {latch-2.39.0.dev24 → latch-2.39.0.dev26}/tests/test_ls.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: latch
3
- Version: 2.39.0.dev24
3
+ Version: 2.39.0.dev26
4
4
  Summary: The Latch SDK
5
5
  Author-email: kenny@latch.bio
6
6
  Classifier: Programming Language :: Python :: 3.8
@@ -696,6 +696,8 @@ class NextflowMetadata(LatchMetadata):
696
696
  def __post_init__(self):
697
697
  if self.name is None:
698
698
  self.name = f"nf_{identifier_suffix_from_str(self.display_name.lower())}"
699
+ else:
700
+ self.name = identifier_suffix_from_str(self.name)
699
701
 
700
702
  if self.output_directory is None:
701
703
  self.output_directory = LatchDir("latch:///Nextflow Outputs/")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: latch
3
- Version: 2.39.0.dev24
3
+ Version: 2.39.0.dev26
4
4
  Summary: The Latch SDK
5
5
  Author-email: kenny@latch.bio
6
6
  Classifier: Programming Language :: Python :: 3.8
@@ -82,6 +82,9 @@ latch_cli/extras/__init__.py
82
82
  latch_cli/extras/common/__init__.py
83
83
  latch_cli/extras/common/serialize.py
84
84
  latch_cli/extras/common/utils.py
85
+ latch_cli/extras/common/config/__init__.py
86
+ latch_cli/extras/common/config/parser.py
87
+ latch_cli/extras/common/config/utils.py
85
88
  latch_cli/extras/nextflow/__init__.py
86
89
  latch_cli/extras/nextflow/build.py
87
90
  latch_cli/extras/nextflow/channel.py
@@ -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
@@ -352,18 +353,8 @@ def generate_dockerfile(
352
353
  with (pkg_root / latch_constants.pkg_config).open("r") as f:
353
354
  config = LatchWorkflowConfig(**json.load(f))
354
355
 
355
- click.echo(
356
- " ".join([
357
- click.style("Base image:", fg="bright_blue"),
358
- config.base_image,
359
- ])
360
- )
361
- click.echo(
362
- " ".join([
363
- click.style("Latch SDK version:", fg="bright_blue"),
364
- config.latch_version,
365
- ])
366
- )
356
+ click.echo(" ".join([color("Base image:"), config.base_image]))
357
+ click.echo(" ".join([color("Latch SDK version:"), config.latch_version]))
367
358
  click.echo()
368
359
 
369
360
  with outfile.open("w") as f:
@@ -0,0 +1,82 @@
1
+ from pathlib import Path
2
+ from typing import Dict, Tuple, Type, TypeVar
3
+
4
+ import click
5
+
6
+ from ..utils import reindent
7
+ from .utils import JSONValue, parse_type, parse_value
8
+
9
+ T = TypeVar("T")
10
+
11
+
12
+ def parse_config(
13
+ config: JSONValue,
14
+ *,
15
+ infer_files: bool = False,
16
+ ) -> Dict[str, Tuple[Type[T], T]]:
17
+ parsed: Dict[str, Type] = {}
18
+ for k, v in config.items():
19
+ try:
20
+ typ = parse_type(v, k, infer_files=infer_files)
21
+ except ValueError as e:
22
+ click.secho(
23
+ f"WARNING: Skipping parameter {k}. Failed to parse type: {e}.",
24
+ fg="yellow",
25
+ )
26
+ continue
27
+ val, default = parse_value(typ, v)
28
+
29
+ parsed[k] = (typ, (val, default))
30
+
31
+ return parsed
32
+
33
+
34
+ def write_metadata(
35
+ metadata: str,
36
+ params: str,
37
+ *,
38
+ skip_confirmation: bool = False,
39
+ ) -> None:
40
+ metadata_root = Path("latch_metadata")
41
+ if metadata_root.is_file():
42
+ if not click.confirm("A file exists at `latch_metadata`. Delete it?"):
43
+ raise click.exceptions.Exit(0)
44
+
45
+ metadata_root.unlink()
46
+
47
+ metadata_root.mkdir(exist_ok=True)
48
+
49
+ metadata_path = metadata_root / Path("__init__.py")
50
+ old_metadata_path = Path("latch_metadata.py")
51
+
52
+ if old_metadata_path.exists() and not metadata_path.exists():
53
+ if click.confirm(
54
+ "Found legacy `latch_metadata.py` file in current directory. This is"
55
+ " deprecated and will be ignored in future releases. Move to"
56
+ " `latch_metadata/__init__.py`? (This will not change file contents)"
57
+ ):
58
+ old_metadata_path.rename(metadata_path)
59
+ elif old_metadata_path.exists() and metadata_path.exists():
60
+ click.secho(
61
+ "Warning: Found both `latch_metadata.py` and"
62
+ " `latch_metadata/__init__.py` in current directory."
63
+ " `latch_metadata.py` will be ignored.",
64
+ fg="yellow",
65
+ )
66
+
67
+ if not metadata_path.exists():
68
+ metadata_path.write_text(reindent(metadata, 0))
69
+ click.secho("Generated `latch_metadata/__init__.py`.", fg="green")
70
+
71
+ params_path = metadata_root / Path("parameters.py")
72
+ if (
73
+ params_path.exists()
74
+ and not skip_confirmation
75
+ and not click.confirm(
76
+ "File `latch_metadata/parameters.py` already exists. Overwrite?"
77
+ )
78
+ ):
79
+ raise click.exceptions.Exit(0)
80
+
81
+ params_path.write_text(reindent(params, 0))
82
+ click.secho("Generated `latch_metadata/parameters.py`.", fg="green")
@@ -0,0 +1,235 @@
1
+ from dataclasses import fields, is_dataclass, make_dataclass
2
+ from typing import Any, Dict, List, Optional, Type, Union, get_args, get_origin
3
+
4
+ from flytekit.core.annotation import FlyteAnnotation
5
+ from typing_extensions import Annotated, TypeAlias, TypeGuard
6
+
7
+ from latch.types.directory import LatchDir
8
+ from latch.types.file import LatchFile
9
+ from latch_cli.utils import identifier_from_str
10
+
11
+ from ..utils import is_primitive_type, is_primitive_value, type_repr
12
+
13
+ JSONValue: TypeAlias = Union[int, str, bool, float, None, List["JSONValue"], "JSONDict"]
14
+ JSONDict: TypeAlias = Dict[str, "JSONValue"]
15
+
16
+ # ayush: yoinked from console
17
+ valid_extensions = {
18
+ "bed",
19
+ "vcf",
20
+ "css",
21
+ "csv",
22
+ "gif",
23
+ "png",
24
+ "pdf",
25
+ "webp",
26
+ "xhtml",
27
+ "xlsx",
28
+ "xml",
29
+ "py",
30
+ "log",
31
+ "json",
32
+ "gz",
33
+ "mmtf",
34
+ "deseqreport",
35
+ "sam",
36
+ "bam",
37
+ "cram",
38
+ "tsv",
39
+ "tab",
40
+ "sf",
41
+ "txt",
42
+ "text",
43
+ "license",
44
+ "readme",
45
+ "r",
46
+ "rscript",
47
+ "md",
48
+ "markdown",
49
+ "markdn",
50
+ "mdown",
51
+ "htm",
52
+ "html",
53
+ "ipynb",
54
+ "jpeg",
55
+ "jpg",
56
+ "jif",
57
+ "jpe",
58
+ "jfif",
59
+ "js",
60
+ "mjs",
61
+ "es",
62
+ "ts",
63
+ "jsx",
64
+ "tsx",
65
+ "svg",
66
+ "svgz",
67
+ "fasta",
68
+ "fna",
69
+ "fa",
70
+ "ffn",
71
+ "faa",
72
+ "frn",
73
+ "fastq",
74
+ "fq",
75
+ "pdb",
76
+ "pdb1",
77
+ "ent",
78
+ "brk",
79
+ "ml2",
80
+ "mol2",
81
+ "sy2",
82
+ "hdf",
83
+ "h4",
84
+ "hdf4",
85
+ "he4",
86
+ "h5",
87
+ "hdf5",
88
+ "he5",
89
+ "h5ad",
90
+ "yaml",
91
+ "yml",
92
+ }
93
+
94
+
95
+ def parse_type(
96
+ v: JSONValue, name: Optional[str] = None, *, infer_files: bool = False
97
+ ) -> Type:
98
+ if v is None:
99
+ return str
100
+
101
+ if infer_files and isinstance(v, str):
102
+ if any([v.endswith(ext) for ext in valid_extensions]):
103
+ return LatchFile
104
+ elif v.endswith("/"):
105
+ return LatchDir
106
+
107
+ if is_primitive_value(v):
108
+ return type(v)
109
+
110
+ if isinstance(v, list):
111
+ parsed_types = tuple(
112
+ parse_type(
113
+ x,
114
+ name,
115
+ infer_files=infer_files,
116
+ )
117
+ for x in v
118
+ )
119
+
120
+ if len(set(parsed_types)) != 1:
121
+ raise ValueError(
122
+ "Generic Lists are not supported - please"
123
+ f" ensure that all elements in {name} are of the same type",
124
+ )
125
+ typ = parsed_types[0]
126
+ if typ in {LatchFile, LatchDir}:
127
+ return Annotated[List[typ], FlyteAnnotation({"size": len(v)})]
128
+ return List[typ]
129
+
130
+ assert isinstance(v, dict)
131
+
132
+ if name is None:
133
+ name = "SnakemakeRecord"
134
+
135
+ fields: Dict[str, Type] = {}
136
+ for k, x in v.items():
137
+ fields[identifier_from_str(k)] = parse_type(
138
+ x,
139
+ k,
140
+ infer_files=infer_files,
141
+ )
142
+
143
+ return make_dataclass(identifier_from_str(name), fields.items())
144
+
145
+
146
+ # returns raw value and generated default
147
+ def parse_value(t: Type, v: JSONValue):
148
+ if v is None:
149
+ return None, None
150
+
151
+ if get_origin(t) is Annotated:
152
+ args = get_args(t)
153
+ assert len(args) > 0
154
+ return parse_value(args[0], v)
155
+
156
+ if t in {LatchFile, LatchDir}:
157
+ # ayush: autogenerated defaults don't make sense for files/dirs since their
158
+ # value in the config is their local path
159
+ return v, None
160
+
161
+ if is_primitive_value(v):
162
+ return v, v
163
+
164
+ if isinstance(v, list):
165
+ assert get_origin(t) is list
166
+
167
+ args = get_args(t)
168
+ assert len(args) > 0
169
+
170
+ sub_type = args[0]
171
+ res = [parse_value(sub_type, x) for x in v]
172
+ return [x[0] for x in res], [x[1] for x in res]
173
+
174
+ assert isinstance(v, dict), v
175
+ assert is_dataclass(t), t
176
+
177
+ ret = {}
178
+ defaults = {}
179
+ fs = {identifier_from_str(f.name): f for f in fields(t)}
180
+
181
+ for k, x in v.items():
182
+ sanitized = identifier_from_str(k)
183
+ assert sanitized in fs, sanitized
184
+ val, default = parse_value(fs[sanitized].type, x)
185
+ ret[sanitized] = val
186
+ defaults[sanitized] = default
187
+
188
+ return t(**ret), t(**defaults)
189
+
190
+
191
+ def is_list_type(typ: Type) -> TypeGuard[Type[List]]:
192
+ return get_origin(typ) is list
193
+
194
+
195
+ def dataclass_repr(typ: Type, *, make_optionals: bool = False) -> str:
196
+ assert is_dataclass(typ)
197
+
198
+ lines = ["@dataclass", f"class {typ.__name__}:"]
199
+ for f in fields(typ):
200
+ t = f.type
201
+ if make_optionals:
202
+ t = Optional[t]
203
+
204
+ lines.append(f" {f.name}: {type_repr(t)}")
205
+
206
+ return "\n".join(lines) + "\n\n\n"
207
+
208
+
209
+ def get_preamble(typ: Type, *, make_optionals: bool = False) -> str:
210
+ if get_origin(typ) is Annotated:
211
+ args = get_args(typ)
212
+ assert len(args) > 0
213
+ return get_preamble(args[0], make_optionals=make_optionals)
214
+
215
+ if is_primitive_type(typ) or typ in {LatchFile, LatchDir}:
216
+ return ""
217
+
218
+ if get_origin(typ) in {Union, list}:
219
+ return "".join(
220
+ [get_preamble(t, make_optionals=make_optionals) for t in get_args(typ)]
221
+ )
222
+
223
+ assert is_dataclass(typ), typ
224
+
225
+ preambles = []
226
+ for f in fields(typ):
227
+ t = f.type
228
+ if make_optionals:
229
+ t = Optional[f.type]
230
+
231
+ preambles.append(get_preamble(t, make_optionals=make_optionals))
232
+
233
+ preamble = "".join(preambles)
234
+
235
+ return "".join([preamble, dataclass_repr(typ, make_optionals=make_optionals)])
@@ -1,7 +1,7 @@
1
1
  import sys
2
2
  from dataclasses import fields
3
3
  from pathlib import Path
4
- from typing import Any, Dict, Optional, Type, TypeVar, Union, get_args
4
+ from typing import Any, Dict, List, Optional, Type, TypeVar, Union, get_args
5
5
 
6
6
  import click
7
7
  from flyteidl.admin.launch_plan_pb2 import LaunchPlan as _idl_admin_LaunchPlan
@@ -292,7 +292,7 @@ RegistrableEntity = Union[
292
292
  ]
293
293
 
294
294
 
295
- def should_register_with_admin(entity: RegistrableEntity) -> bool:
295
+ def should_register_with_admin(entity: FlyteSerializableModel) -> bool:
296
296
  return isinstance(entity, get_args(RegistrableEntity))
297
297
 
298
298
 
@@ -327,15 +327,29 @@ def serialize(
327
327
  )
328
328
  admin_lp = get_serializable_launch_plan(lp, settings, registrable_entity_cache)
329
329
 
330
- registrable_entities = [
331
- x.to_flyte_idl()
332
- for x in list(
333
- filter(should_register_with_admin, list(registrable_entity_cache.values()))
334
- )
335
- + [admin_lp]
336
- ]
330
+ click.secho(
331
+ "\nBuilding flyte models: \x1b[?25l",
332
+ nl=False,
333
+ )
334
+
335
+ registrable_entities = []
336
+ i = 0
337
+ for x in list(registrable_entity_cache.values()) + [admin_lp]:
338
+ progress_str = f"{i + 1}/{len(registrable_entity_cache) + 1}"
339
+
340
+ click.echo("\x1b[0K", nl=False)
341
+ click.secho(progress_str, dim=True, italic=True, nl=False)
342
+ click.echo(f"\x1b[{len(progress_str)}D", nl=False)
343
+
344
+ i += 1
345
+
346
+ if not should_register_with_admin(x):
347
+ continue
348
+
349
+ registrable_entities.append(x.to_flyte_idl())
337
350
 
338
351
  click.secho("\nSerializing workflow entities", bold=True)
352
+
339
353
  persist_registrable_entities(registrable_entities, output_dir)
340
354
 
341
355
  if not write_spec:
@@ -3,7 +3,7 @@ from typing import Type, Union, get_args, get_origin
3
3
 
4
4
  from typing_extensions import Annotated, TypeGuard
5
5
 
6
- from latch.types.directory import LatchDir
6
+ from latch.types.directory import LatchDir, LatchOutputDir
7
7
  from latch.types.file import LatchFile
8
8
 
9
9
 
@@ -17,7 +17,7 @@ def reindent(x: str, level: int) -> str:
17
17
  def is_primitive_type(
18
18
  typ: Type,
19
19
  ) -> TypeGuard[Union[Type[None], Type[str], Type[bool], Type[int], Type[float]]]:
20
- return typ in {Type[None], str, bool, int, float}
20
+ return typ in {type(None), str, bool, int, float}
21
21
 
22
22
 
23
23
  def is_primitive_value(val: object) -> TypeGuard[Union[None, str, bool, int, float]]:
@@ -34,6 +34,13 @@ def is_blob_type(typ: Type) -> TypeGuard[Union[Type[LatchFile], Type[LatchDir]]]
34
34
  return typ in {LatchFile, LatchDir}
35
35
 
36
36
 
37
+ def is_downloadable_blob_type(typ: Type):
38
+ if not is_blob_type(typ):
39
+ return False
40
+
41
+ return typ is not LatchOutputDir
42
+
43
+
37
44
  def type_repr(t: Type, *, add_namespace: bool = False) -> str:
38
45
  if getattr(t, "__name__", None) == "NoneType":
39
46
  return "None"
@@ -19,6 +19,7 @@ from flytekit.models import literals as literals_models
19
19
  from latch_sdk_gql.execute import execute
20
20
 
21
21
  from latch_cli import tinyrequests
22
+ from latch_cli.extras.common.config.utils import get_preamble
22
23
  from latch_cli.extras.nextflow.tasks.base import NextflowBaseTask, NFTaskType
23
24
 
24
25
  from ...click_utils import italic
@@ -102,7 +103,7 @@ def build_from_nextflow_dag(
102
103
 
103
104
  output_name = "res"
104
105
  if len(dep.outputNames) > 0:
105
- idx = int(edge.label)
106
+ idx = int(edge.label or "0")
106
107
  input_name = f"{input_name}_{idx}"
107
108
  output_name = dep.outputNames[idx]
108
109
 
@@ -128,8 +129,6 @@ def build_from_nextflow_dag(
128
129
  upstream_nodes.append(node_map[dep.id])
129
130
 
130
131
  node_name = get_node_name(vertex.id)
131
- if vertex.type == VertexType.Merge:
132
- task_outputs = {k: Optional[str] for k in merge_sources.keys()}
133
132
 
134
133
  if vertex.type == VertexType.Process:
135
134
  pre_adapter_task = NextflowProcessPreAdapterTask(
@@ -513,6 +512,9 @@ def generate_nf_entrypoint(
513
512
  0,
514
513
  )
515
514
 
515
+ for t in wf.python_interface.inputs.values():
516
+ preamble += get_preamble(t, make_optionals=True)
517
+
516
518
  nf_script_path_in_container = nf_script.resolve().relative_to(pkg_root.resolve())
517
519
 
518
520
  entrypoint_code = [preamble]
@@ -2,7 +2,7 @@ import json
2
2
  import os
3
3
  import subprocess
4
4
  from pathlib import Path
5
- from typing import List
5
+ from typing import List, Optional
6
6
 
7
7
  import click
8
8
 
@@ -37,6 +37,7 @@ def generate_nf_metadata(
37
37
  skip_confirmation: bool = False,
38
38
  generate_defaults: bool = False,
39
39
  infer_files: bool = False,
40
+ make_optionals: bool = True,
40
41
  ):
41
42
  if not config_path.is_dir():
42
43
  click.secho(
@@ -103,7 +104,10 @@ def generate_nf_metadata(
103
104
  params: List[str] = []
104
105
 
105
106
  for k, (typ, (val, default)) in parsed.items():
106
- preambles.append(get_preamble(typ))
107
+ if make_optionals:
108
+ typ = Optional[typ]
109
+
110
+ preambles.append(get_preamble(typ, make_optionals=make_optionals))
107
111
 
108
112
  param_str = reindent(
109
113
  f"""\
@@ -15,7 +15,7 @@ def serialize_nf(
15
15
  image_name: str,
16
16
  dkr_repo: str,
17
17
  ):
18
- serialize(nf_wf, output_dir, image_name, dkr_repo, write_spec=True)
18
+ serialize(nf_wf, output_dir, image_name, dkr_repo)
19
19
 
20
20
 
21
21
  def add_task_metadata(wf: NextflowWorkflow):
@@ -47,8 +47,8 @@ class NextflowBaseTask(PythonAutoContainerTask[Pod]):
47
47
  wf: NextflowWorkflow,
48
48
  nf_task_type: NFTaskType,
49
49
  # todo(ayush): expose / infer these somehow
50
- cpu: int = 4,
51
- memory: int = 8,
50
+ cpu: float = 0.5,
51
+ memory: float = 1,
52
52
  ):
53
53
  self.id = id
54
54
  self.wf = wf
@@ -130,7 +130,7 @@ class NextflowOperatorTask(NextflowBaseTask):
130
130
  if {k} is not None:
131
131
  {k}_p = Path({k}).resolve()
132
132
  check_exists_and_rename({k}_p, Path("/root") / {k}_p.name)
133
- wf_paths[{k}] = Path("/root") / {k}_p.name
133
+ wf_paths["{k}"] = Path("/root") / {k}_p.name
134
134
 
135
135
  """,
136
136
  2,
@@ -140,7 +140,7 @@ class NextflowOperatorTask(NextflowBaseTask):
140
140
  f"""
141
141
  if {k} is not None:
142
142
  {k}_p = Path("/root/").resolve() # superhack
143
- wf_paths[{k}] = {k}_p
143
+ wf_paths["{k}"] = {k}_p
144
144
 
145
145
  """,
146
146
  2,
@@ -136,7 +136,7 @@ class NextflowProcessTask(NextflowBaseTask):
136
136
  if {k} is not None:
137
137
  {k}_p = Path({k}).resolve()
138
138
  check_exists_and_rename({k}_p, Path("/root") / {k}_p.name)
139
- wf_paths[{k}] = Path("/root") / {k}_p.name
139
+ wf_paths["{k}"] = Path("/root") / {k}_p.name
140
140
 
141
141
  """,
142
142
  1,
@@ -146,7 +146,7 @@ class NextflowProcessTask(NextflowBaseTask):
146
146
  f"""
147
147
  if {k} is not None:
148
148
  {k}_p = Path("/root/").resolve() # superhack
149
- wf_paths[{k}] = {k}_p
149
+ wf_paths["{k}"] = {k}_p
150
150
 
151
151
  """,
152
152
  1,
@@ -1,5 +1,6 @@
1
+ from dataclasses import fields, is_dataclass
1
2
  from pathlib import Path
2
- from typing import List
3
+ from typing import Any, Dict, List, Tuple, Type
3
4
 
4
5
  from flytekit.core.class_based_resolver import ClassStorageTaskResolver
5
6
  from flytekit.core.docstring import Docstring
@@ -13,10 +14,32 @@ from flytekit.core.workflow import (
13
14
  from flytekit.exceptions import scopes as exception_scopes
14
15
 
15
16
  from latch.types import metadata
16
- from latch.types.metadata import NextflowFileParameter
17
+ from latch_cli.extras.common.utils import is_blob_type, is_downloadable_blob_type
17
18
 
18
19
  from .dag import DAG
19
20
 
21
+ # def _get_flattened_inputs(
22
+ # key: str, t: Type, val: Any, inputs: Dict[str, Tuple[Type, Any]]
23
+ # ):
24
+ # if not is_dataclass(t):
25
+ # inputs[key] = (t, val)
26
+ # return
27
+
28
+ # for f in fields(t):
29
+ # v = val
30
+ # if val is not None:
31
+ # v = getattr()
32
+
33
+
34
+ def _get_flags_to_params(key: str, t: Type, flags: Dict[str, str]):
35
+ if is_blob_type(t):
36
+ flags[f"--{key}"] = f"wf_paths['wf_{key}']"
37
+ elif is_dataclass(t):
38
+ for f in fields(t):
39
+ _get_flags_to_params(f"{key}.{f.name}", f.type, flags)
40
+ else:
41
+ flags[f"--{key}"] = f"wf_{key}"
42
+
20
43
 
21
44
  class NextflowWorkflow(WorkflowBase, ClassStorageTaskResolver):
22
45
  def __init__(self, nf_script: Path, version: str, dag: DAG):
@@ -39,19 +62,17 @@ class NextflowWorkflow(WorkflowBase, ClassStorageTaskResolver):
39
62
  docstring=docstring,
40
63
  )
41
64
 
42
- self.flags_to_params = {
43
- f"--{k}": (
44
- f"wf_paths[wf_{k}]"
45
- if isinstance(v, NextflowFileParameter)
46
- else f"wf_{k}"
47
- )
48
- for k, v in metadata._nextflow_metadata.parameters.items()
49
- }
65
+ self.flattened_inputs = {}
66
+
67
+ self.flags_to_params = {}
68
+ for k, v in metadata._nextflow_metadata.parameters.items():
69
+ assert v.type is not None
70
+ _get_flags_to_params(k, v.type, self.flags_to_params)
50
71
 
51
72
  self.downloadable_params = {
52
- k: str(v.path)
73
+ k
53
74
  for k, v in metadata._nextflow_metadata.parameters.items()
54
- if isinstance(v, NextflowFileParameter) and v._download
75
+ if is_downloadable_blob_type(v.type)
55
76
  }
56
77
 
57
78
  name = metadata._nextflow_metadata.name
@@ -13,7 +13,7 @@ if cur_ver < (3, 8) or cur_ver > (3, 11):
13
13
 
14
14
  setup(
15
15
  name="latch",
16
- version="v2.39.0.dev24",
16
+ version="v2.39.0.dev26",
17
17
  author_email="kenny@latch.bio",
18
18
  description="The Latch SDK",
19
19
  packages=find_packages(),
File without changes
File without changes
File without changes
File without changes