snakemake-executor-plugin-aws-batch-flex 0.1.0__tar.gz → 0.1.1__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 (114) hide show
  1. snakemake_executor_plugin_aws_batch_flex-0.1.1/.release-please-manifest.json +3 -0
  2. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/CHANGELOG.md +10 -0
  3. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/PKG-INFO +1 -1
  4. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/docs/reference.md +1 -1
  5. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/docs/setup.md +3 -2
  6. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/pyproject.toml +1 -1
  7. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/src/snakemake_executor_plugin_aws_batch_flex/bootstrap.py +21 -12
  8. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/src/snakemake_executor_plugin_aws_batch_flex/executor.py +12 -6
  9. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/src/snakemake_executor_plugin_aws_batch_flex/transfer.py +7 -3
  10. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/src/snakemake_executor_plugin_aws_batch_flex/usage.py +3 -1
  11. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/tests/test_integration.py +2 -2
  12. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/tests/test_prereqs.py +8 -2
  13. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/tests/test_smkflex.py +7 -0
  14. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/tests/test_units.py +21 -2
  15. snakemake_executor_plugin_aws_batch_flex-0.1.0/.release-please-manifest.json +0 -3
  16. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/.github/workflows/release.yml +0 -0
  17. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/.github/workflows/tests.yml +0 -0
  18. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/.gitignore +0 -0
  19. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/LICENSE +0 -0
  20. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/README.md +0 -0
  21. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/docs/further.md +0 -0
  22. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/docs/guide.md +0 -0
  23. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/docs/intro.md +0 -0
  24. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/environment.yml +0 -0
  25. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/examples/conformance/auto.smk +0 -0
  26. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/examples/conformance/benchmark.smk +0 -0
  27. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/examples/conformance/checkpoint.smk +0 -0
  28. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/examples/conformance/conda.smk +0 -0
  29. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/examples/conformance/conda_named.smk +0 -0
  30. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/examples/conformance/config/pdsheet.tsv +0 -0
  31. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/examples/conformance/directory.smk +0 -0
  32. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/examples/conformance/disk.smk +0 -0
  33. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/examples/conformance/ecr.smk +0 -0
  34. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/examples/conformance/entrypoint.smk +0 -0
  35. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/examples/conformance/envs/tiny.yaml +0 -0
  36. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/examples/conformance/fanout.smk +0 -0
  37. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/examples/conformance/fargate.smk +0 -0
  38. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/examples/conformance/find-profile.sh +0 -0
  39. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/examples/conformance/group.smk +0 -0
  40. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/examples/conformance/mixed.smk +0 -0
  41. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/examples/conformance/oom.smk +0 -0
  42. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/examples/conformance/orphan-test.sh +0 -0
  43. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/examples/conformance/orphans.smk +0 -0
  44. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/examples/conformance/pdsheet.smk +0 -0
  45. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/examples/conformance/pipeline.smk +0 -0
  46. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/examples/conformance/pyimage.smk +0 -0
  47. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/examples/conformance/pyrule.smk +0 -0
  48. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/examples/conformance/retries.smk +0 -0
  49. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/examples/conformance/rscript.smk +0 -0
  50. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/examples/conformance/run.sh +0 -0
  51. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/examples/conformance/script.smk +0 -0
  52. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/examples/conformance/scripts/pandas_script.py +0 -0
  53. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/examples/conformance/scripts/py_script.py +0 -0
  54. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/examples/conformance/scripts/r_script.R +0 -0
  55. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/examples/conformance/scripts/sh_script.sh +0 -0
  56. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/examples/conformance/scripts/which_python.py +0 -0
  57. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/examples/conformance/shadow.smk +0 -0
  58. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/examples/conformance/shm.smk +0 -0
  59. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/examples/conformance/tempdir.smk +0 -0
  60. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/examples/conformance/wrapper.smk +0 -0
  61. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/examples/smoke-test/README.md +0 -0
  62. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/examples/smoke-test/Snakefile +0 -0
  63. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/release-please-config.json +0 -0
  64. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/scripts/bake-ami.sh +0 -0
  65. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/scripts/cleanup-ami.sh +0 -0
  66. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/scripts/cleanup-jobdefs.sh +0 -0
  67. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/scripts/setup.sh +0 -0
  68. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/scripts/update-ami.sh +0 -0
  69. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/src/snakemake_executor_plugin_aws_batch_flex/__init__.py +0 -0
  70. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/src/snakemake_executor_plugin_aws_batch_flex/bundle.py +0 -0
  71. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/src/snakemake_executor_plugin_aws_batch_flex/check.py +0 -0
  72. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/src/snakemake_executor_plugin_aws_batch_flex/condacache.py +0 -0
  73. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/src/snakemake_executor_plugin_aws_batch_flex/headjob.py +0 -0
  74. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/src/snakemake_executor_plugin_aws_batch_flex/hints.py +0 -0
  75. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/src/snakemake_executor_plugin_aws_batch_flex/hostenv.py +0 -0
  76. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/src/snakemake_executor_plugin_aws_batch_flex/imageinfo.py +0 -0
  77. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/src/snakemake_executor_plugin_aws_batch_flex/jobdefs.py +0 -0
  78. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/src/snakemake_executor_plugin_aws_batch_flex/jobfixes.py +0 -0
  79. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/src/snakemake_executor_plugin_aws_batch_flex/jobmonitor.py +0 -0
  80. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/src/snakemake_executor_plugin_aws_batch_flex/naming.py +0 -0
  81. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/src/snakemake_executor_plugin_aws_batch_flex/orphans.py +0 -0
  82. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/src/snakemake_executor_plugin_aws_batch_flex/patches.py +0 -0
  83. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/src/snakemake_executor_plugin_aws_batch_flex/preflight.py +0 -0
  84. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/src/snakemake_executor_plugin_aws_batch_flex/profiles.py +0 -0
  85. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/src/snakemake_executor_plugin_aws_batch_flex/remote.py +0 -0
  86. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/src/snakemake_executor_plugin_aws_batch_flex/settings.py +0 -0
  87. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/src/snakemake_executor_plugin_aws_batch_flex/sizing.py +0 -0
  88. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/src/snakemake_executor_plugin_aws_batch_flex/sources.py +0 -0
  89. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/src/snakemake_executor_plugin_aws_batch_flex/tags.py +0 -0
  90. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/terraform/.terraform.lock.hcl +0 -0
  91. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/terraform/README.md +0 -0
  92. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/terraform/fargate.tf +0 -0
  93. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/terraform/main.tf +0 -0
  94. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/terraform/outputs.tf +0 -0
  95. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/terraform/spot.tf +0 -0
  96. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/terraform/terraform.tfvars.example +0 -0
  97. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/terraform/userdata.snakemake.txt +0 -0
  98. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/terraform/variables.tf +0 -0
  99. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/terraform/versions.tf +0 -0
  100. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/tests/conftest.py +0 -0
  101. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/tests/fakeaws/sitecustomize.py +0 -0
  102. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/tests/fixtures/existing_userdata.txt +0 -0
  103. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/tests/test_bake_script.py +0 -0
  104. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/tests/test_cleanup_ami.py +0 -0
  105. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/tests/test_cleanup_jobdefs.py +0 -0
  106. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/tests/test_conda_mount.py +0 -0
  107. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/tests/test_condacache.py +0 -0
  108. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/tests/test_conformance.py +0 -0
  109. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/tests/test_host_env.py +0 -0
  110. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/tests/test_imageinfo.py +0 -0
  111. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/tests/test_script_python.py +0 -0
  112. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/tests/test_setup.py +0 -0
  113. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/tests/test_tags.py +0 -0
  114. {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/tests/test_userdata.py +0 -0
@@ -1,5 +1,15 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.1.1](https://github.com/SSmith-NUIG/snakemake-executor-plugin-aws-batch-flex/compare/v0.1.0...v0.1.1) (2026-10-29)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * big runs read peak memory from jobs across the whole run, not only the last ones ([147a054](https://github.com/SSmith-NUIG/snakemake-executor-plugin-aws-batch-flex/commit/147a054053c7e7dbfee38029c95d9fa92dd44f00))
9
+ * cancelling a run stops every job, also those Snakemake is checking on ([9edb388](https://github.com/SSmith-NUIG/snakemake-executor-plugin-aws-batch-flex/commit/9edb3880575bb8d3c4fb2aceb469f7a120bfb3a4))
10
+ * non-root images without curl get uv from their own conda at job start ([374cc30](https://github.com/SSmith-NUIG/snakemake-executor-plugin-aws-batch-flex/commit/374cc303e6d1d42b17255dc36fe05c76ec84beff))
11
+ * smkflex push gives the .gitignore note only when it uploaded, and no rate for tiny transfers ([6be28ad](https://github.com/SSmith-NUIG/snakemake-executor-plugin-aws-batch-flex/commit/6be28ad2efe30a30f13c4c9bd077969f573024fb))
12
+
3
13
  ## 0.1.0 (2026-10-28)
4
14
 
5
15
  First release. Needs Snakemake 9 (9.5 or newer) and Python 3.11 to 3.13. Tested on Linux; macOS
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: snakemake-executor-plugin-aws-batch-flex
3
- Version: 0.1.0
3
+ Version: 0.1.1
4
4
  Summary: Snakemake executor plugin for AWS Batch that runs every rule in its own container image
5
5
  Project-URL: Homepage, https://github.com/SSmith-NUIG/snakemake-executor-plugin-aws-batch-flex
6
6
  Project-URL: Documentation, https://github.com/SSmith-NUIG/snakemake-executor-plugin-aws-batch-flex#getting-started
@@ -51,7 +51,7 @@ from the machine image (`host`); otherwise it's installed when each job starts,
51
51
  | `host-env-wait-seconds` | `120` | How long a job waits for that Snakemake if its machine is still setting it up when the job starts. A machine image made by `setup.sh` has it from the start, so 0 is fine there. |
52
52
  | `extra-packages` | *none* | Extra pip packages to install along with Snakemake when a job starts (e.g. `[pandas]`, or other Snakemake plugins). |
53
53
  | `python-version` | *the one you run Snakemake with* | The Python version to install Snakemake with when a job starts. |
54
- | `install-prereqs` | `false` | When installing at start: first install `curl` into images that have none of `curl`, `wget` or `pip`. |
54
+ | `install-prereqs` | `false` | When installing at start, for images that have none of `curl`, `wget` or `pip`: get uv with the image's conda, mamba or micromamba (any user), or else install `curl` with its package manager (images that run as root). |
55
55
  | `script-python` | `image` | Which Python runs Python `script:` rules. `image`: the image's own, if it's 3.10 or newer, so the script can use the image's packages. `host`: always Snakemake's own. |
56
56
 
57
57
  **Memory, disk and Spot**
@@ -149,8 +149,9 @@ lines like `executor: aws-batch-flex` and `aws-batch-flex-queue: smkflex-queue`.
149
149
  To try the plugin on an existing Batch queue without building an AMI, set
150
150
  `aws-batch-flex-bootstrap: auto` in the profile instead of `host`. Snakemake is then installed into
151
151
  each container when its job starts (about 10-15 s per job), which needs internet access and
152
- `curl`, `wget` or `pip` in the image (`--aws-batch-flex-install-prereqs` installs `curl` first if
153
- missing).
152
+ `curl`, `wget` or `pip` in the image. Without them, `--aws-batch-flex-install-prereqs` gets uv
153
+ with the image's own conda, mamba or micromamba if it has one (as any user), or else installs
154
+ `curl` with its package manager, which needs an image that runs as root.
154
155
 
155
156
  Or install the Snakemake env on each instance as it boots, with the stock ECS image and no AMI of
156
157
  your own: every new instance then spends about a minute on it before its first job (not yet
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "snakemake-executor-plugin-aws-batch-flex"
7
- version = "0.1.0"
7
+ version = "0.1.1"
8
8
  description = "Snakemake executor plugin for AWS Batch that runs every rule in its own container image"
9
9
  dynamic = ["readme"]
10
10
  requires-python = ">=3.11"
@@ -70,20 +70,29 @@ else
70
70
  fi"""
71
71
 
72
72
 
73
- # Installs curl (for uv) in an image without curl, wget or pip: only with install_prereqs
73
+ # For an image without curl, wget or pip (only with install_prereqs): uv from the image's own
74
+ # conda, mamba or micromamba into $SMK_BOOT, which works as any user and leaves the image's
75
+ # environments alone; else curl from its package manager, which needs root
74
76
  _PREREQS = r'''
75
77
  if ! command -v curl >/dev/null 2>&1 && ! command -v wget >/dev/null 2>&1 \
76
78
  && ! { command -v python3 >/dev/null 2>&1 && python3 -m pip --version >/dev/null 2>&1; }; then
77
- echo "[snakemake-batch] no curl/wget/pip in the image: installing curl, ca-certificates and bash" >&2
78
- if [ "$(id -u)" != 0 ]; then
79
- echo "[snakemake-batch] cannot install prerequisites: the image runs as a non-root user" >&2
80
- elif command -v apt-get >/dev/null 2>&1; then
81
- apt-get update -qq >&2 && DEBIAN_FRONTEND=noninteractive apt-get install -y -qq --no-install-recommends curl ca-certificates bash >&2 || true
82
- elif command -v apk >/dev/null 2>&1; then apk add -q --no-cache curl ca-certificates bash >&2 || true
83
- elif command -v dnf >/dev/null 2>&1; then dnf install -y -q curl ca-certificates bash >&2 || true
84
- elif command -v microdnf >/dev/null 2>&1; then microdnf install -y curl ca-certificates bash >&2 || true
85
- elif command -v yum >/dev/null 2>&1; then yum install -y -q curl ca-certificates bash >&2 || true
86
- else echo "[snakemake-batch] no known package manager in the image" >&2
79
+ SMK_CONDA=$(command -v micromamba || command -v mamba || command -v conda || true)
80
+ if [ -n "$SMK_CONDA" ]; then
81
+ echo "[snakemake-batch] no curl/wget/pip in the image: getting uv with its $SMK_CONDA" >&2
82
+ CONDA_PKGS_DIRS="$SMK_BOOT/pkgs" "$SMK_CONDA" create -y -q -p "$SMK_BOOT/uvenv" -c conda-forge "uv=@@UVVER@@" >&2 \
83
+ && mkdir -p "$SMK_BOOT/bin" && ln -sf "$SMK_BOOT/uvenv/bin/uv" "$SMK_BOOT/bin/uv" || true
84
+ elif [ "$(id -u)" != 0 ]; then
85
+ echo "[snakemake-batch] no curl/wget/pip/conda in the image, and it runs as a non-root user, so none can be installed. Add curl to the image (or USER root), or run the rule on EC2 (batch_queue), where Snakemake comes from the AMI" >&2
86
+ else
87
+ echo "[snakemake-batch] no curl/wget/pip in the image: installing curl, ca-certificates and bash" >&2
88
+ if command -v apt-get >/dev/null 2>&1; then
89
+ apt-get update -qq >&2 && DEBIAN_FRONTEND=noninteractive apt-get install -y -qq --no-install-recommends curl ca-certificates bash >&2 || true
90
+ elif command -v apk >/dev/null 2>&1; then apk add -q --no-cache curl ca-certificates bash >&2 || true
91
+ elif command -v dnf >/dev/null 2>&1; then dnf install -y -q curl ca-certificates bash >&2 || true
92
+ elif command -v microdnf >/dev/null 2>&1; then microdnf install -y curl ca-certificates bash >&2 || true
93
+ elif command -v yum >/dev/null 2>&1; then yum install -y -q curl ca-certificates bash >&2 || true
94
+ else echo "[snakemake-batch] no known package manager in the image" >&2
95
+ fi
87
96
  fi
88
97
  fi
89
98
  '''
@@ -277,7 +286,7 @@ def build_prelude(
277
286
  _TEMPLATE.replace("@@WORKDIR@@", WORKDIR)
278
287
  .replace("@@CHECK@@", check)
279
288
  .replace("@@PYVER@@", shlex.quote(python_version))
280
- .replace("@@PREREQS@@", _PREREQS if install_prereqs else "")
289
+ .replace("@@PREREQS@@", _PREREQS.replace("@@UVVER@@", UV_VERSION) if install_prereqs else "")
281
290
  .replace("@@REQS@@", reqs)
282
291
  .replace("@@NEWER@@", f"--exclude-newer {shlex.quote(resolved_at)} " if resolved_at else "")
283
292
  .replace("@@UV@@", uv_snippet("$SMK_BOOT/bin", "$SMK_BOOT/uvlib"))
@@ -156,6 +156,9 @@ class Executor(RemoteExecutor):
156
156
  self._warned_fargate_shm = False
157
157
  self._said_resolved = False
158
158
  self._warned_tags: set = set()
159
+ # Batch jobs submitted and not seen to end. Cancelling stops these too: while Snakemake
160
+ # checks on its running jobs, it takes them out of the list it would hand cancel_jobs.
161
+ self._unfinished: set = set()
159
162
  self._warned_disk: set = set()
160
163
  self._existing_defs: dict = {} # ref -> ExistingJobDefinition
161
164
  self._fair_share: dict = {} # queue -> has a scheduling policy
@@ -578,6 +581,7 @@ class Executor(RemoteExecutor):
578
581
  f"Submitted {job.name} as AWS Batch job {resp['jobId']} "
579
582
  f"({image}, {req.vcpu} vCPU, {req.memory_mib} MiB, queue {queue}, {platform})"
580
583
  )
584
+ self._unfinished.add(resp["jobId"])
581
585
  self.report_job_submission(
582
586
  SubmittedJobInfo(
583
587
  job,
@@ -608,6 +612,8 @@ class Executor(RemoteExecutor):
608
612
 
609
613
  for jid, info in by_id.items():
610
614
  d = described.get(jid)
615
+ if d is None or d["status"] in ("SUCCEEDED", "FAILED"):
616
+ self._unfinished.discard(jid)
611
617
  if d is None:
612
618
  self.report_job_error(
613
619
  info, msg=f"AWS Batch no longer knows job {jid} (expired?)."
@@ -658,16 +664,16 @@ class Executor(RemoteExecutor):
658
664
  def cancel_jobs(self, active_jobs: List[SubmittedJobInfo]):
659
665
  # In parallel: a head job that is stopped has little time (ECS_CONTAINER_STOP_TIMEOUT)
660
666
  # to cancel every job and save its state.
661
- def cancel(info):
667
+ def cancel(jid):
662
668
  try:
663
- self.batch.terminate_job(
664
- jobId=info.external_jobid, reason="Cancelled by Snakemake"
665
- )
669
+ self.batch.terminate_job(jobId=jid, reason="Cancelled by Snakemake")
666
670
  except (ClientError, BotoCoreError) as e:
667
- self.logger.warning(f"Could not terminate {info.external_jobid}: {e}")
671
+ self.logger.warning(f"Could not terminate {jid}: {e}")
668
672
 
673
+ # set() copies at once, so the status checks can't change it meanwhile
674
+ ids = {i.external_jobid for i in active_jobs} | set(self._unfinished)
669
675
  with ThreadPoolExecutor(CANCEL_THREADS) as pool:
670
- list(pool.map(cancel, active_jobs))
676
+ list(pool.map(cancel, sorted(ids)))
671
677
 
672
678
  def _warn_if_stuck(self, d: dict, info: SubmittedJobInfo):
673
679
  sub = _sub(info)
@@ -78,8 +78,11 @@ def _transfer(jobs, work, verb):
78
78
  return done, total, secs
79
79
 
80
80
  def _rate(total, secs):
81
- mb = total / 1e6
82
- return f"{mb:.1f} MB in {secs:.0f} s ({mb / secs:.1f} MB/s)" if total else ""
81
+ """How much was sent, and how fast when that means something (1 MB or more, over a second)."""
82
+ if not total:
83
+ return ""
84
+ size = f"{total / 1e6:.1f} MB" if total >= 1e5 else f"{total / 1e3:.1f} kB" if total >= 1e3 else f"{total} bytes"
85
+ return f"{size} in {secs:.0f} s ({total / 1e6 / secs:.1f} MB/s)" if total >= 1e6 and secs >= 1 else size
83
86
 
84
87
  def cmd_pull(a):
85
88
  _dir, profile = _load_profile(a.profile)
@@ -176,7 +179,8 @@ def cmd_push(a):
176
179
  rate = _rate(total, secs)
177
180
  print(f"{sent} uploaded to {prefix}" + (f" ({rate})" if rate else "")
178
181
  + (f", {skipped} already there (unchanged; --force sends them again)" if skipped else ""))
179
- _hint_gitignore([p for p in a.paths if not os.path.isabs(p)])
182
+ if sent: # not again on every push that had nothing new
183
+ _hint_gitignore([p for p in a.paths if not os.path.isabs(p)])
180
184
  return 0
181
185
 
182
186
  def _hint_gitignore(paths):
@@ -83,8 +83,10 @@ class Usage:
83
83
  todo = []
84
84
  for rule, streams in self.logs.items():
85
85
  if total > ALL_PEAKS and len(streams) > PEAK_SAMPLE:
86
+ # spread over the run: a rule's biggest inputs aren't always its last jobs
86
87
  self.sampled = True
87
- streams = streams[-PEAK_SAMPLE:]
88
+ step = len(streams) / PEAK_SAMPLE
89
+ streams = [streams[int(i * step)] for i in range(PEAK_SAMPLE)]
88
90
  todo += [(rule, g, st) for g, st in streams]
89
91
 
90
92
  def one(item):
@@ -469,8 +469,8 @@ def test_workdir_directive_stops_before_submitting(tmp_path):
469
469
 
470
470
 
471
471
  def test_job_commands_fit_what_ecs_allows(tmp_path):
472
- # installing Snakemake at job start makes the longest commands
473
- r, calls = run(tmp_path, SNAKEFILE, "--aws-batch-flex-bootstrap", "always")
472
+ # installing Snakemake at job start, with the prerequisites, makes the longest commands
473
+ r, calls = run(tmp_path, SNAKEFILE, "--aws-batch-flex-bootstrap", "always", "--aws-batch-flex-install-prereqs")
474
474
  assert r.returncode == 0, r.stdout + r.stderr
475
475
  sizes = [c["overrides_chars"] for c in calls if c["call"] == "submit_job"]
476
476
  assert sizes and max(sizes) < 8192 - 500, sizes # room for a longer storage prefix and the like
@@ -1,4 +1,4 @@
1
- """The curl/ca-certificates fallback, run in a stripped PATH with stub package managers."""
1
+ """The fallbacks for images without curl, wget or pip, run in a stripped PATH with stub tools."""
2
2
  import os, stat, subprocess
3
3
  from snakemake_executor_plugin_aws_batch_flex.bootstrap import build_prelude
4
4
 
@@ -42,7 +42,13 @@ def test_off_by_default_installs_nothing_and_fails_clearly(tmp_path):
42
42
 
43
43
  def test_non_root_is_reported_not_attempted(tmp_path):
44
44
  r, calls = _run(tmp_path, True, ["apt-get"], uid="1000")
45
- assert calls == "" and "non-root" in r.stderr
45
+ assert calls == "" and "non-root" in r.stderr and "batch_queue" in r.stderr
46
+
47
+
48
+ def test_uv_from_the_images_conda_as_any_user(tmp_path):
49
+ # mambaorg/micromamba: non-root, no curl; its micromamba fetches uv into the job's folder
50
+ r, calls = _run(tmp_path, True, ["apt-get", "micromamba"], uid="1000")
51
+ assert "micromamba create -y -q -p" in calls and "-c conda-forge uv=" in calls and "apt-get" not in calls
46
52
 
47
53
 
48
54
  def test_skipped_when_curl_already_present(tmp_path):
@@ -336,6 +336,13 @@ def test_push(tmp_path):
336
336
  assert (tmp_path / "store" / "data" / "a.fq").read_text() == "CCC"
337
337
  r, _ = smkflex(wf, "push", "../x")
338
338
  assert r.returncode == 2 and "outside the workflow folder" in r.stderr
339
+ # a folder smkflex run would send too: said once, not on every push with nothing new
340
+ (wf / "refs").mkdir()
341
+ (wf / "refs" / "g.fa").write_text(">g\n")
342
+ r, _ = smkflex(wf, "push", "refs")
343
+ assert "add to .gitignore:\nrefs/" in r.stdout and "uploaded to" in r.stdout and "MB/s" not in r.stdout
344
+ r, _ = smkflex(wf, "push", "refs")
345
+ assert "0 uploaded" in r.stdout and ".gitignore" not in r.stdout
339
346
 
340
347
 
341
348
  def test_push_absolute_paths_and_many_files(tmp_path):
@@ -221,6 +221,7 @@ def test_sources_patch_leaves_other_executors_alone(tmp_path, monkeypatch):
221
221
 
222
222
 
223
223
  def test_cancel_terminates_jobs_in_parallel_and_goes_on_after_errors():
224
+ # also j20, which Snakemake leaves out of the list while it checks on it
224
225
  import threading, time, types
225
226
  from botocore.exceptions import ClientError
226
227
  from snakemake_executor_plugin_aws_batch_flex.executor import Executor
@@ -235,12 +236,12 @@ def test_cancel_terminates_jobs_in_parallel_and_goes_on_after_errors():
235
236
  done.append(jobId)
236
237
 
237
238
  me = types.SimpleNamespace(batch=types.SimpleNamespace(terminate_job=terminate_job),
238
- logger=types.SimpleNamespace(warning=warnings.append))
239
+ logger=types.SimpleNamespace(warning=warnings.append), _unfinished={"j1", "j20"})
239
240
  jobs = [types.SimpleNamespace(external_jobid=f"j{i}") for i in range(20)]
240
241
  start = time.time()
241
242
  Executor.cancel_jobs(me, jobs)
242
243
  assert time.time() - start < 2 # one at a time would take 4 s
243
- assert sorted(done) == sorted(f"j{i}" for i in range(20) if i != 3)
244
+ assert sorted(done) == sorted(f"j{i}" for i in range(21) if i != 3) # j1 once
244
245
  assert len(warnings) == 1 and "j3" in warnings[0]
245
246
 
246
247
 
@@ -316,6 +317,24 @@ def test_rules_whose_jobs_ran_out_get_no_memory_suggestion(tmp_path, monkeypatch
316
317
  assert "Hint: in killed's jobs, Linux killed 2 process(es) for lack of memory" in u.table(256)
317
318
 
318
319
 
320
+ def test_big_runs_sample_jobs_from_the_whole_run():
321
+ from snakemake_executor_plugin_aws_batch_flex import usage
322
+ u = usage.Usage()
323
+ for i in range(usage.ALL_PEAKS + 100): # the first jobs took the most memory
324
+ u.add("align", {"startedAt": 0, "stoppedAt": 1000}, 1, 4352, "ec2")
325
+ u.add_log("align", "g", str(i))
326
+ client = types.SimpleNamespace(get_log_events=lambda logGroupName, logStreamName, **kw: {
327
+ "events": [{"message": f"[snakemake-batch] peak-memory-bytes={(4000 - int(logStreamName)) << 20}"}]})
328
+ u.fetch_peaks(client)
329
+ assert len(u.peaks["align"]) == usage.PEAK_SAMPLE and max(u.peaks["align"]) == 4000
330
+
331
+
332
+ def test_transfer_sizes():
333
+ from snakemake_executor_plugin_aws_batch_flex.transfer import _rate
334
+ assert (_rate(0, 1), _rate(12, 0.01), _rate(4300, 0.01)) == ("", "12 bytes", "4.3 kB")
335
+ assert _rate(250_000_000, 10) == "250.0 MB in 10 s (25.0 MB/s)"
336
+
337
+
319
338
  def test_hint_for_a_script_that_wasnt_sent():
320
339
  from snakemake_executor_plugin_aws_batch_flex.hints import known_problem_hints as hints
321
340
  py = ["python: can't open file '/tmp/snakemake-job-7/scripts/synthetic/gen.py': [Errno 2] No such file or directory"]