cutseq 0.0.71__tar.gz → 0.0.72__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 (185) hide show
  1. {cutseq-0.0.71 → cutseq-0.0.72}/PKG-INFO +2 -2
  2. {cutseq-0.0.71 → cutseq-0.0.72}/cutseq/grammar.py +36 -67
  3. {cutseq-0.0.71 → cutseq-0.0.72}/pyproject.toml +1 -1
  4. {cutseq-0.0.71 → cutseq-0.0.72}/scripts/update_adapter_docs.py +0 -1
  5. {cutseq-0.0.71 → cutseq-0.0.72}/test/test_rename_engine.py +27 -3
  6. {cutseq-0.0.71 → cutseq-0.0.72}/uv.lock +1 -1
  7. {cutseq-0.0.71 → cutseq-0.0.72}/.github/FUNDING.yml +0 -0
  8. {cutseq-0.0.71 → cutseq-0.0.72}/.github/workflows/docs.yaml +0 -0
  9. {cutseq-0.0.71 → cutseq-0.0.72}/.github/workflows/python-publish.yml +0 -0
  10. {cutseq-0.0.71 → cutseq-0.0.72}/.github/workflows/tests.yaml +0 -0
  11. {cutseq-0.0.71 → cutseq-0.0.72}/.gitignore +0 -0
  12. {cutseq-0.0.71 → cutseq-0.0.72}/.pre-commit-config.yaml +0 -0
  13. {cutseq-0.0.71 → cutseq-0.0.72}/README.md +0 -0
  14. {cutseq-0.0.71 → cutseq-0.0.72}/cutseq/__init__.py +0 -0
  15. {cutseq-0.0.71 → cutseq-0.0.72}/cutseq/adapters.toml +0 -0
  16. {cutseq-0.0.71 → cutseq-0.0.72}/cutseq/common.py +0 -0
  17. {cutseq-0.0.71 → cutseq-0.0.72}/cutseq/primers.py +0 -0
  18. {cutseq-0.0.71 → cutseq-0.0.72}/cutseq/run.py +0 -0
  19. {cutseq-0.0.71 → cutseq-0.0.72}/docs/CNAME +0 -0
  20. {cutseq-0.0.71 → cutseq-0.0.72}/docs/_config.yml +0 -0
  21. {cutseq-0.0.71 → cutseq-0.0.72}/docs/adapters.md +0 -0
  22. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/10XCRISPR.dna +0 -0
  23. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/10XCRISPR.gb +0 -0
  24. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/10XFB_3PRIME.dna +0 -0
  25. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/10XFB_3PRIME.gb +0 -0
  26. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/10XFB_5PRIME.dna +0 -0
  27. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/10XFB_5PRIME.gb +0 -0
  28. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/10XFB_VDJ_5PRIME.dna +0 -0
  29. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/10XFB_VDJ_5PRIME.gb +0 -0
  30. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/10XV3_SCRNASEQ_ELEMENT_ADEPT_TRUSEQ_DUAL.dna +0 -0
  31. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/10XV3_SCRNASEQ_ELEMENT_ADEPT_TRUSEQ_DUAL.gb +0 -0
  32. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/10XV3_SCRNASEQ_ILLUMINA_TRUSEQ_DUAL.dna +0 -0
  33. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/10XV3_SCRNASEQ_ILLUMINA_TRUSEQ_DUAL.gb +0 -0
  34. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/10X_ATAC.dna +0 -0
  35. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/10X_ATAC.gb +0 -0
  36. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/10X_RNA_5PRIME.dna +0 -0
  37. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/10X_RNA_5PRIME.gb +0 -0
  38. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/10X_RNA_ATAC.dna +0 -0
  39. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/10X_RNA_ATAC.gb +0 -0
  40. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/10X_RNA_ATAC_MULTI.dna +0 -0
  41. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/10X_RNA_ATAC_MULTI.gb +0 -0
  42. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/10X_RNA_V1.dna +0 -0
  43. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/10X_RNA_V1.gb +0 -0
  44. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/10X_RNA_V2.dna +0 -0
  45. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/10X_RNA_V2.gb +0 -0
  46. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/10X_RNA_V3.dna +0 -0
  47. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/10X_RNA_V3.gb +0 -0
  48. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/BD_RHAPSODY_EB.dna +0 -0
  49. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/BD_RHAPSODY_EB.gb +0 -0
  50. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/BD_RHAPSODY_V1.dna +0 -0
  51. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/BD_RHAPSODY_V1.gb +0 -0
  52. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/CEL_SEQ.dna +0 -0
  53. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/CEL_SEQ.gb +0 -0
  54. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/CEL_SEQ2.dna +0 -0
  55. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/CEL_SEQ2.gb +0 -0
  56. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/DBITSEQ.dna +0 -0
  57. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/DBITSEQ.gb +0 -0
  58. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/DOGMASEQ_DIG.dna +0 -0
  59. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/DOGMASEQ_DIG.gb +0 -0
  60. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/DOGMASEQ_LLL.dna +0 -0
  61. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/DOGMASEQ_LLL.gb +0 -0
  62. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/DROP_SEQ.dna +0 -0
  63. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/DROP_SEQ.gb +0 -0
  64. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/DSLIGATION.dna +0 -0
  65. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/DSLIGATION.gb +0 -0
  66. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/ECLIP10.dna +0 -0
  67. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/ECLIP10.gb +0 -0
  68. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/ECLIP6.dna +0 -0
  69. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/ECLIP6.gb +0 -0
  70. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/ILLUMINARNA.dna +0 -0
  71. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/ILLUMINARNA.gb +0 -0
  72. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/INDROPV2.dna +0 -0
  73. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/INDROPV2.gb +0 -0
  74. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/INLINE.dna +0 -0
  75. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/INLINE.gb +0 -0
  76. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/ISSAAC_SEQ.dna +0 -0
  77. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/ISSAAC_SEQ.gb +0 -0
  78. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/M6AARTR.dna +0 -0
  79. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/M6AARTR.gb +0 -0
  80. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/MARS_SEQ.dna +0 -0
  81. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/MARS_SEQ.gb +0 -0
  82. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/MCSCRB_SEQ.dna +0 -0
  83. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/MCSCRB_SEQ.gb +0 -0
  84. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/MICROWELL_SEQ.dna +0 -0
  85. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/MICROWELL_SEQ.gb +0 -0
  86. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/NEXTERA.dna +0 -0
  87. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/NEXTERA.gb +0 -0
  88. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/PARSE_WT_V2.dna +0 -0
  89. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/PARSE_WT_V2.gb +0 -0
  90. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/PBAT.dna +0 -0
  91. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/PBAT.gb +0 -0
  92. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/PIPSEQV2.dna +0 -0
  93. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/PIPSEQV2.gb +0 -0
  94. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/PIPSEQV3.dna +0 -0
  95. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/PIPSEQV3.gb +0 -0
  96. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/PI_ATAC_SEQ.dna +0 -0
  97. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/PI_ATAC_SEQ.gb +0 -0
  98. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/QUARTZ_SEQ.dna +0 -0
  99. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/QUARTZ_SEQ.gb +0 -0
  100. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/QUARTZ_SEQ2.dna +0 -0
  101. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/QUARTZ_SEQ2.gb +0 -0
  102. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/SACSEQ.dna +0 -0
  103. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/SACSEQ.gb +0 -0
  104. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/SACSEQV3.dna +0 -0
  105. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/SACSEQV3.gb +0 -0
  106. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/SCCRISPRA.dna +0 -0
  107. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/SCCRISPRA.gb +0 -0
  108. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/SCIFI_RNA_SEQ.dna +0 -0
  109. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/SCIFI_RNA_SEQ.gb +0 -0
  110. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/SCI_RNA_SEQ.dna +0 -0
  111. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/SCI_RNA_SEQ.gb +0 -0
  112. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/SCI_RNA_SEQ3.dna +0 -0
  113. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/SCI_RNA_SEQ3.gb +0 -0
  114. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/SEQ_WELL.dna +0 -0
  115. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/SEQ_WELL.gb +0 -0
  116. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/SEQ_WELL_S3.dna +0 -0
  117. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/SEQ_WELL_S3.gb +0 -0
  118. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/SHARE_SEQ.dna +0 -0
  119. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/SHARE_SEQ.gb +0 -0
  120. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/SMALLRNA.dna +0 -0
  121. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/SMALLRNA.gb +0 -0
  122. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/SMART_SEQ2.dna +0 -0
  123. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/SMART_SEQ2.gb +0 -0
  124. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/SMART_SEQ3.dna +0 -0
  125. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/SMART_SEQ3.gb +0 -0
  126. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/SMRNA.dna +0 -0
  127. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/SMRNA.gb +0 -0
  128. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/SNMCTSEQ.dna +0 -0
  129. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/SNMCTSEQ.gb +0 -0
  130. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/SN_M3C_SEQ.dna +0 -0
  131. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/SN_M3C_SEQ.gb +0 -0
  132. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/SPLIT_SEQ.dna +0 -0
  133. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/SPLIT_SEQ.gb +0 -0
  134. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/STRANDED.dna +0 -0
  135. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/STRANDED.gb +0 -0
  136. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/STRT_SEQ.dna +0 -0
  137. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/STRT_SEQ.gb +0 -0
  138. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/STRT_SEQ_2I.dna +0 -0
  139. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/STRT_SEQ_2I.gb +0 -0
  140. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/STRT_SEQ_C1.dna +0 -0
  141. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/STRT_SEQ_C1.gb +0 -0
  142. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/SUGARSEQ.dna +0 -0
  143. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/SUGARSEQ.gb +0 -0
  144. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/SURECELL.dna +0 -0
  145. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/SURECELL.gb +0 -0
  146. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/TAKARAV2.dna +0 -0
  147. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/TAKARAV2.gb +0 -0
  148. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/TAKARAV3.dna +0 -0
  149. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/TAKARAV3.gb +0 -0
  150. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/TANG2009.dna +0 -0
  151. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/TANG2009.gb +0 -0
  152. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/TEMPLATE.dna +0 -0
  153. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/TEMPLATE.gb +0 -0
  154. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/UNSTRANDED.dna +0 -0
  155. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/UNSTRANDED.gb +0 -0
  156. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/VASA_SEQ_DROP.dna +0 -0
  157. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/VASA_SEQ_DROP.gb +0 -0
  158. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/VASA_SEQ_PLATE.dna +0 -0
  159. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/VASA_SEQ_PLATE.gb +0 -0
  160. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/XGENMETHY.dna +0 -0
  161. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/XGENMETHY.gb +0 -0
  162. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/XGENRNA.dna +0 -0
  163. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/XGENRNA.gb +0 -0
  164. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/XGENSNMC.dna +0 -0
  165. {cutseq-0.0.71 → cutseq-0.0.72}/docs/constructs/XGENSNMC.gb +0 -0
  166. {cutseq-0.0.71 → cutseq-0.0.72}/docs/explain_library.png +0 -0
  167. {cutseq-0.0.71 → cutseq-0.0.72}/docs/favicon.ico +0 -0
  168. {cutseq-0.0.71 → cutseq-0.0.72}/docs/index.md +0 -0
  169. {cutseq-0.0.71 → cutseq-0.0.72}/docs/logo.svg +0 -0
  170. {cutseq-0.0.71 → cutseq-0.0.72}/docs/quickstart.md +0 -0
  171. {cutseq-0.0.71 → cutseq-0.0.72}/docs/rename.md +0 -0
  172. {cutseq-0.0.71 → cutseq-0.0.72}/docs/spatial.md +0 -0
  173. {cutseq-0.0.71 → cutseq-0.0.72}/docs/takaraV3.png +0 -0
  174. {cutseq-0.0.71 → cutseq-0.0.72}/test/input_R1.fq.gz +0 -0
  175. {cutseq-0.0.71 → cutseq-0.0.72}/test/input_R2.fq.gz +0 -0
  176. {cutseq-0.0.71 → cutseq-0.0.72}/test/test_cli_fixes.py +0 -0
  177. {cutseq-0.0.71 → cutseq-0.0.72}/test/test_discard_file.py +0 -0
  178. {cutseq-0.0.71 → cutseq-0.0.72}/test/test_engine_extensibility.py +0 -0
  179. {cutseq-0.0.71 → cutseq-0.0.72}/test/test_grammar_bugs.py +0 -0
  180. {cutseq-0.0.71 → cutseq-0.0.72}/test/test_grammar_fuzzy.py +0 -0
  181. {cutseq-0.0.71 → cutseq-0.0.72}/test/test_grammar_nospace.py +0 -0
  182. {cutseq-0.0.71 → cutseq-0.0.72}/test/test_primer_autodetect.py +0 -0
  183. {cutseq-0.0.71 → cutseq-0.0.72}/test/test_reconnected_flags.py +0 -0
  184. {cutseq-0.0.71 → cutseq-0.0.72}/test/test_scg_migrated.py +0 -0
  185. {cutseq-0.0.71 → cutseq-0.0.72}/test/test_yaml_scheme.py +0 -0
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.4
1
+ Metadata-Version: 2.5
2
2
  Name: cutseq
3
- Version: 0.0.71
3
+ Version: 0.0.72
4
4
  Summary: Automatically cut adapter / barcode / UMI from NGS data
5
5
  Project-URL: Repository, https://github.com/y9c/cutseq
6
6
  Author-email: Ye Chang <yech1990@gmail.com>
@@ -980,73 +980,51 @@ def _r2_five_emitter(kind):
980
980
  return _EMITTERS[kind][0]
981
981
 
982
982
 
983
- def _se_id_name(read, info):
984
- """``{id}``: strip any trailing comment (identical to cutadapt Renamer)."""
985
- read.name = read.name.split(maxsplit=1)[0]
986
- return read
983
+ class _FastSingleEndRenamer:
984
+ """Fast, picklable single-end renamer for the default cutseq templates.
987
985
 
988
-
989
- def _make_fast_renamer(paired, has_captures, name_format):
990
- """Build a lean renamer that computes only the variables its template needs.
991
-
992
- cutadapt's generic ``Renamer``/``PairedEndRenamer`` builds a full variable
993
- dict (comment, header, adapter_name, match_sequence, ...) plus a
994
- ``SimpleNamespace`` per read on every call even when the template uses just
986
+ cutadapt's generic ``Renamer`` builds a full variable dict (comment,
987
+ header, adapter_name, match_sequence, ...) plus a ``SimpleNamespace`` per
988
+ read on every call even when the template uses just
995
989
  ``id``/``cut_prefix``/``cut_suffix``. The default cutseq templates only use
996
- those, so we special-case them and fall back to the native renamer for any
997
- custom ``--name-format`` template. Output is byte-identical to the native
998
- renamer for the same template.
990
+ those, so we compute them directly. This is a module-level class (not a
991
+ closure) so it pickles for cutadapt's multiprocessing runner.
999
992
  """
1000
- if name_format is not None:
1001
- return None
1002
- if not has_captures:
1003
- tpl = "{id}"
1004
- if paired:
1005
-
1006
- def _rename(read1, read2, info1, info2):
1007
- read1.name = read1.name.split(maxsplit=1)[0]
1008
- read2.name = read2.name.split(maxsplit=1)[0]
1009
- return read1, read2
1010
-
1011
- _rename._template = tpl
1012
- return _rename
1013
- _se_id_name._template = tpl
1014
- return _se_id_name
1015
- if paired:
1016
- tpl = "{id}_{r1.cut_prefix}{r2.cut_prefix}"
1017
-
1018
- def _rename(read1, read2, info1, info2):
1019
- id1 = read1.name.split(maxsplit=1)[0]
1020
- id2 = read2.name.split(maxsplit=1)[0]
1021
- p1 = info1.cut_prefix if info1.cut_prefix else ""
1022
- p2 = info2.cut_prefix if info2.cut_prefix else ""
1023
- read1.name = f"{id1}_{p1}{p2}"
1024
- read2.name = f"{id2}_{p1}{p2}"
1025
- return read1, read2
1026
993
 
1027
- _rename._template = tpl
1028
- return _rename
1029
- tpl = "{id}_{cut_prefix}{cut_suffix}"
994
+ def __init__(self, has_captures):
995
+ self.has_captures = bool(has_captures)
996
+ self._template = "{id}_{cut_prefix}{cut_suffix}" if has_captures else "{id}"
1030
997
 
1031
- def _rename(read, info):
1032
- p = info.cut_prefix if info.cut_prefix else ""
1033
- s = info.cut_suffix if info.cut_suffix else ""
1034
- read.name = f"{read.name.split(maxsplit=1)[0]}_{p}{s}"
998
+ def __call__(self, read, info):
999
+ read.name = read.name.split(maxsplit=1)[0]
1000
+ if self.has_captures:
1001
+ p = info.cut_prefix if info.cut_prefix else ""
1002
+ s = info.cut_suffix if info.cut_suffix else ""
1003
+ read.name = f"{read.name}_{p}{s}"
1035
1004
  return read
1036
1005
 
1037
- _rename._template = tpl
1038
- return _rename
1039
-
1040
1006
 
1041
1007
  class _FastPairedEndRenamer(_mods.PairedEndModifier):
1042
- """Wraps a fast paired rename callable so it plugs into the pipeline."""
1008
+ """Fast, picklable paired-end renamer for the default cutseq templates."""
1043
1009
 
1044
- def __init__(self, fn):
1045
- self._fn = fn
1046
- self._template = fn._template
1010
+ def __init__(self, has_captures):
1011
+ self.has_captures = bool(has_captures)
1012
+ self._template = (
1013
+ "{id}_{r1.cut_prefix}{r2.cut_prefix}" if has_captures else "{id}"
1014
+ )
1047
1015
 
1048
1016
  def __call__(self, read1, read2, info1, info2):
1049
- return self._fn(read1, read2, info1, info2)
1017
+ id1 = read1.name.split(maxsplit=1)[0]
1018
+ id2 = read2.name.split(maxsplit=1)[0]
1019
+ if not self.has_captures:
1020
+ read1.name = id1
1021
+ read2.name = id2
1022
+ else:
1023
+ p1 = info1.cut_prefix if info1.cut_prefix else ""
1024
+ p2 = info2.cut_prefix if info2.cut_prefix else ""
1025
+ read1.name = f"{id1}_{p1}{p2}"
1026
+ read2.name = f"{id2}_{p1}{p2}"
1027
+ return read1, read2
1050
1028
 
1051
1029
 
1052
1030
  # --- labeled-capture template engine ----------------------------------------
@@ -1447,18 +1425,9 @@ def make_renamer(paired, has_captures=False, name_format=None, left=None, right=
1447
1425
  return _LabeledRenamer(fields, name_format)
1448
1426
 
1449
1427
  _RENAME_NEEDS_CAPTURES = False
1450
- if not has_captures:
1451
- tpl = "{id}"
1452
- elif paired:
1453
- tpl = "{id}_{r1.cut_prefix}{r2.cut_prefix}"
1454
- else:
1455
- tpl = "{id}_{cut_prefix}{cut_suffix}"
1456
- fast = _make_fast_renamer(paired, has_captures, name_format)
1457
- if fast is not None:
1458
- if paired:
1459
- return _FastPairedEndRenamer(fast)
1460
- return fast
1461
- return _mods.PairedEndRenamer(tpl) if paired else _mods.Renamer(tpl)
1428
+ if paired:
1429
+ return _FastPairedEndRenamer(has_captures)
1430
+ return _FastSingleEndRenamer(has_captures)
1462
1431
 
1463
1432
 
1464
1433
  class CompiledScheme:
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "cutseq"
3
- version = "0.0.71"
3
+ version = "0.0.72"
4
4
  description = "Automatically cut adapter / barcode / UMI from NGS data"
5
5
  authors = [{ name = "Ye Chang", email = "yech1990@gmail.com" }]
6
6
  requires-python = "~=3.9"
@@ -462,7 +462,6 @@ def _write_exports(name, construct, constructs_dir):
462
462
 
463
463
 
464
464
  def main():
465
- adapters_toml = project_root / "cutseq" / "adapters.toml"
466
465
  out_md = project_root / "docs" / "adapters.md"
467
466
  schemes = _load_schemes()
468
467
  if not schemes:
@@ -222,6 +222,31 @@ def test_threaded_rename_deterministic():
222
222
  assert a and a == b
223
223
 
224
224
 
225
+ def test_default_renamer_picklable():
226
+ """The default fast renamers (no --rename) must pickle so cutadapt's
227
+ ``ParallelPipelineRunner`` (multiprocessing) can ship the pipeline to
228
+ workers. They are module-level classes, not local closures, because
229
+ closures raise on spawn-based platforms (macOS/Windows) where
230
+ ``-t N`` broke. ``--rename '{id}'`` hid the bug by swapping in the
231
+ native picklable renamer.
232
+ """
233
+ import pickle
234
+
235
+ for paired in (False, True):
236
+ for has_captures in (False, True):
237
+ pickle.dumps(grammar.make_renamer(paired, has_captures, None))
238
+
239
+ s = CutadaptConfig()
240
+ cs = _build_scheme(
241
+ "AAGCAGTGGTATCAACGCAGAGTGAATGGG...GGG:"
242
+ "N12AGTCGTACGCCGATGCGAAACATCGGCCAC"
243
+ "N8CGAATGCTCTGGCCTCTCAAGCACGTGGAT"
244
+ "N8AGATGCGAGAAGCCAACGCTTG",
245
+ s,
246
+ )
247
+ pickle.dumps(_scheme_modifiers(cs, paired=True, settings=s))
248
+
249
+
225
250
  # --- spatial (DBiT) interleaved 3' structure ---------------------------------
226
251
  #
227
252
  # m6A-ARTR-DBiT / Glori style, Read 1 (single-end):
@@ -375,9 +400,8 @@ def test_polytail_direction_auto_detected():
375
400
  from the current position (never a global rightmost search, which would
376
401
  over-trim real insert). The read-through mirror is a back adapter. ``N``s
377
402
  in the run count as the base."""
378
- from cutseq.grammar import (RightmostFrontAdapter,
379
- BackAdapter, _poly_seq, _mark_poly_front,
380
- _poly_head_trim_index, tokenize)
403
+ from cutseq.grammar import (_mark_poly_front, _poly_seq, BackAdapter,
404
+ tokenize)
381
405
  from cutseq.grammar import _PolyRunTrim, _Token
382
406
  from cutadapt.modifiers import AdapterCutter
383
407
  from cutadapt.info import ModificationInfo
@@ -163,7 +163,7 @@ wheels = [
163
163
 
164
164
  [[package]]
165
165
  name = "cutseq"
166
- version = "0.0.71"
166
+ version = "0.0.72"
167
167
  source = { editable = "." }
168
168
  dependencies = [
169
169
  { name = "cutadapt" },
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes