cellpycore 0.2.4__tar.gz → 0.2.5__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 (260) hide show
  1. {cellpycore-0.2.4/.issueflows/02-partly-solved-issues → cellpycore-0.2.5/.issueflows/03-solved-issues}/issue100_status.md +1 -1
  2. cellpycore-0.2.5/.issueflows/03-solved-issues/issue142_original.md +48 -0
  3. cellpycore-0.2.5/.issueflows/03-solved-issues/issue142_plan.md +86 -0
  4. cellpycore-0.2.5/.issueflows/03-solved-issues/issue142_status.md +20 -0
  5. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/04-designs-and-guides/cellpy-core-integration-roadmap.md +14 -10
  6. cellpycore-0.2.5/.vscode/settings.json +14 -0
  7. {cellpycore-0.2.4 → cellpycore-0.2.5}/HISTORY.md +2 -0
  8. {cellpycore-0.2.4 → cellpycore-0.2.5}/PKG-INFO +2 -2
  9. {cellpycore-0.2.4 → cellpycore-0.2.5}/pyproject.toml +1 -1
  10. {cellpycore-0.2.4 → cellpycore-0.2.5}/src/cellpycore/cell_core.py +40 -18
  11. {cellpycore-0.2.4 → cellpycore-0.2.5}/uv.lock +1 -1
  12. cellpycore-0.2.4/.vscode/settings.json +0 -7
  13. {cellpycore-0.2.4 → cellpycore-0.2.5}/.aliases +0 -0
  14. {cellpycore-0.2.4 → cellpycore-0.2.5}/.cursor/rules/cellpy-core-migration.mdc +0 -0
  15. {cellpycore-0.2.4 → cellpycore-0.2.5}/.cursor/rules/graphify.mdc +0 -0
  16. {cellpycore-0.2.4 → cellpycore-0.2.5}/.cursor/rules/issueflow-rules.mdc +0 -0
  17. {cellpycore-0.2.4 → cellpycore-0.2.5}/.cursor/rules/kiss.mdc +0 -0
  18. {cellpycore-0.2.4 → cellpycore-0.2.5}/.cursor/rules/this-project.mdc +0 -0
  19. {cellpycore-0.2.4 → cellpycore-0.2.5}/.cursor/skills/caveman/SKILL.md +0 -0
  20. {cellpycore-0.2.4 → cellpycore-0.2.5}/.cursor/skills/grill-me/SKILL.md +0 -0
  21. {cellpycore-0.2.4 → cellpycore-0.2.5}/.cursor/skills/iflow/SKILL.md +0 -0
  22. {cellpycore-0.2.4 → cellpycore-0.2.5}/.cursor/skills/iflow-archive/SKILL.md +0 -0
  23. {cellpycore-0.2.4 → cellpycore-0.2.5}/.cursor/skills/iflow-cleanup/SKILL.md +0 -0
  24. {cellpycore-0.2.4 → cellpycore-0.2.5}/.cursor/skills/iflow-close/SKILL.md +0 -0
  25. {cellpycore-0.2.4 → cellpycore-0.2.5}/.cursor/skills/iflow-comments/SKILL.md +0 -0
  26. {cellpycore-0.2.4 → cellpycore-0.2.5}/.cursor/skills/iflow-cycle/SKILL.md +0 -0
  27. {cellpycore-0.2.4 → cellpycore-0.2.5}/.cursor/skills/iflow-epic/SKILL.md +0 -0
  28. {cellpycore-0.2.4 → cellpycore-0.2.5}/.cursor/skills/iflow-fix/SKILL.md +0 -0
  29. {cellpycore-0.2.4 → cellpycore-0.2.5}/.cursor/skills/iflow-graphify/SKILL.md +0 -0
  30. {cellpycore-0.2.4 → cellpycore-0.2.5}/.cursor/skills/iflow-history-update/SKILL.md +0 -0
  31. {cellpycore-0.2.4 → cellpycore-0.2.5}/.cursor/skills/iflow-init/SKILL.md +0 -0
  32. {cellpycore-0.2.4 → cellpycore-0.2.5}/.cursor/skills/iflow-pause/SKILL.md +0 -0
  33. {cellpycore-0.2.4 → cellpycore-0.2.5}/.cursor/skills/iflow-pick/SKILL.md +0 -0
  34. {cellpycore-0.2.4 → cellpycore-0.2.5}/.cursor/skills/iflow-plan/SKILL.md +0 -0
  35. {cellpycore-0.2.4 → cellpycore-0.2.5}/.cursor/skills/iflow-start/SKILL.md +0 -0
  36. {cellpycore-0.2.4 → cellpycore-0.2.5}/.cursor/skills/iflow-status/SKILL.md +0 -0
  37. {cellpycore-0.2.4 → cellpycore-0.2.5}/.cursor/skills/iflow-version-bump/SKILL.md +0 -0
  38. {cellpycore-0.2.4 → cellpycore-0.2.5}/.cursor/skills/iflow-yolo/SKILL.md +0 -0
  39. {cellpycore-0.2.4 → cellpycore-0.2.5}/.gitattributes +0 -0
  40. {cellpycore-0.2.4 → cellpycore-0.2.5}/.gitignore +0 -0
  41. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/00-tools/.gitkeep +0 -0
  42. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/00-tools/README.md +0 -0
  43. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/01-current-issues/.gitkeep +0 -0
  44. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/02-partly-solved-issues/.gitkeep +0 -0
  45. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/.gitkeep +0 -0
  46. {cellpycore-0.2.4/.issueflows/02-partly-solved-issues → cellpycore-0.2.5/.issueflows/03-solved-issues}/issue100_original.md +0 -0
  47. {cellpycore-0.2.4/.issueflows/02-partly-solved-issues → cellpycore-0.2.5/.issueflows/03-solved-issues}/issue100_plan.md +0 -0
  48. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue10_original.md +0 -0
  49. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue10_plan.md +0 -0
  50. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue10_status.md +0 -0
  51. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue110_original.md +0 -0
  52. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue110_plan.md +0 -0
  53. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue110_status.md +0 -0
  54. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue112_original.md +0 -0
  55. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue112_plan.md +0 -0
  56. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue112_status.md +0 -0
  57. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue114_original.md +0 -0
  58. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue114_plan.md +0 -0
  59. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue114_status.md +0 -0
  60. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue115_original.md +0 -0
  61. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue115_plan.md +0 -0
  62. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue115_status.md +0 -0
  63. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue116_original.md +0 -0
  64. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue116_plan.md +0 -0
  65. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue116_status.md +0 -0
  66. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue117_original.md +0 -0
  67. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue117_plan.md +0 -0
  68. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue117_status.md +0 -0
  69. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue118_original.md +0 -0
  70. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue118_plan.md +0 -0
  71. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue118_status.md +0 -0
  72. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue121_original.md +0 -0
  73. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue121_plan.md +0 -0
  74. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue121_status.md +0 -0
  75. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue12_original.md +0 -0
  76. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue12_plan.md +0 -0
  77. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue12_status.md +0 -0
  78. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue136_original.md +0 -0
  79. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue136_plan.md +0 -0
  80. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue136_status.md +0 -0
  81. {cellpycore-0.2.4/.issueflows/01-current-issues → cellpycore-0.2.5/.issueflows/03-solved-issues}/issue138_original.md +0 -0
  82. {cellpycore-0.2.4/.issueflows/01-current-issues → cellpycore-0.2.5/.issueflows/03-solved-issues}/issue138_plan.md +0 -0
  83. {cellpycore-0.2.4/.issueflows/01-current-issues → cellpycore-0.2.5/.issueflows/03-solved-issues}/issue138_status.md +0 -0
  84. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue139_original.md +0 -0
  85. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue139_plan.md +0 -0
  86. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue139_status.md +0 -0
  87. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue13_original.md +0 -0
  88. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue13_plan.md +0 -0
  89. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue13_status.md +0 -0
  90. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue21_original.md +0 -0
  91. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue21_plan.md +0 -0
  92. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue21_status.md +0 -0
  93. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue22_original.md +0 -0
  94. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue22_plan.md +0 -0
  95. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue22_status.md +0 -0
  96. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue23_original.md +0 -0
  97. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue23_plan.md +0 -0
  98. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue23_status.md +0 -0
  99. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue24_original.md +0 -0
  100. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue24_status.md +0 -0
  101. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue29_original.md +0 -0
  102. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue29_plan.md +0 -0
  103. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue29_status.md +0 -0
  104. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue30_original.md +0 -0
  105. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue30_plan.md +0 -0
  106. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue30_status.md +0 -0
  107. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue32_original.md +0 -0
  108. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue32_plan.md +0 -0
  109. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue32_status.md +0 -0
  110. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue34_original.md +0 -0
  111. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue34_plan.md +0 -0
  112. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue36_original.md +0 -0
  113. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue36_status.md +0 -0
  114. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue39_original.md +0 -0
  115. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue39_plan.md +0 -0
  116. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue39_status.md +0 -0
  117. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue40_original.md +0 -0
  118. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue40_plan.md +0 -0
  119. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue40_status.md +0 -0
  120. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue41_original.md +0 -0
  121. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue41_plan.md +0 -0
  122. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue41_status.md +0 -0
  123. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue42_original.md +0 -0
  124. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue42_plan.md +0 -0
  125. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue42_status.md +0 -0
  126. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue43_original.md +0 -0
  127. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue43_plan.md +0 -0
  128. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue43_status.md +0 -0
  129. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue44_original.md +0 -0
  130. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue44_status.md +0 -0
  131. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue45_original.md +0 -0
  132. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue45_plan.md +0 -0
  133. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue45_status.md +0 -0
  134. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue50_original.md +0 -0
  135. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue50_plan.md +0 -0
  136. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue50_status.md +0 -0
  137. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue54_original.md +0 -0
  138. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue54_plan.md +0 -0
  139. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue54_status.md +0 -0
  140. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue55_original.md +0 -0
  141. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue55_plan.md +0 -0
  142. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue55_status.md +0 -0
  143. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue56_original.md +0 -0
  144. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue56_plan.md +0 -0
  145. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue56_status.md +0 -0
  146. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue62_original.md +0 -0
  147. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue62_plan.md +0 -0
  148. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue62_status.md +0 -0
  149. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue64_original.md +0 -0
  150. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue64_plan.md +0 -0
  151. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue64_status.md +0 -0
  152. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue66_original.md +0 -0
  153. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue66_plan.md +0 -0
  154. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue66_status.md +0 -0
  155. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue67_original.md +0 -0
  156. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue67_plan.md +0 -0
  157. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue67_status.md +0 -0
  158. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue68_original.md +0 -0
  159. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue68_plan.md +0 -0
  160. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue68_status.md +0 -0
  161. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue69_original.md +0 -0
  162. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue69_plan.md +0 -0
  163. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue69_status.md +0 -0
  164. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue70_original.md +0 -0
  165. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue70_plan.md +0 -0
  166. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue70_status.md +0 -0
  167. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue72_original.md +0 -0
  168. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue72_status.md +0 -0
  169. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue77_original.md +0 -0
  170. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue77_plan.md +0 -0
  171. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue77_status.md +0 -0
  172. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue82_original.md +0 -0
  173. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue82_status.md +0 -0
  174. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue84_original.md +0 -0
  175. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue84_plan.md +0 -0
  176. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue84_status.md +0 -0
  177. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue86_original.md +0 -0
  178. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue86_plan.md +0 -0
  179. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue86_status.md +0 -0
  180. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue91_original.md +0 -0
  181. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue91_plan.md +0 -0
  182. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue91_status.md +0 -0
  183. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue95_original.md +0 -0
  184. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue95_plan.md +0 -0
  185. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue95_status.md +0 -0
  186. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue96_original.md +0 -0
  187. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue96_plan.md +0 -0
  188. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue96_status.md +0 -0
  189. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue97_original.md +0 -0
  190. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue97_plan.md +0 -0
  191. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue97_status.md +0 -0
  192. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue98_original.md +0 -0
  193. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue98_plan.md +0 -0
  194. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue98_status.md +0 -0
  195. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue99_original.md +0 -0
  196. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue99_plan.md +0 -0
  197. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/03-solved-issues/issue99_status.md +0 -0
  198. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/04-designs-and-guides/.gitkeep +0 -0
  199. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/04-designs-and-guides/bdf-io-placement.md +0 -0
  200. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/04-designs-and-guides/cellpy-core-integration-into-cellpy.md +0 -0
  201. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/04-designs-and-guides/cellpy-core-migration.md +0 -0
  202. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/04-designs-and-guides/code-review-2026-07.md +0 -0
  203. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/04-designs-and-guides/column-headers-review.md +0 -0
  204. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/04-designs-and-guides/legacy-bridge-test-id.md +0 -0
  205. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/04-designs-and-guides/legacy-raw-energy-mapping.md +0 -0
  206. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/04-designs-and-guides/metadata-scaffolding.md +0 -0
  207. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/04-designs-and-guides/nom-cap-naming.md +0 -0
  208. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/04-designs-and-guides/rawcols-dtype-map.md +0 -0
  209. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/04-designs-and-guides/release-procedure.md +0 -0
  210. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/04-designs-and-guides/selector-dead-code-deferral.md +0 -0
  211. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/04-designs-and-guides/step-c-rate-split.md +0 -0
  212. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/04-designs-and-guides/step-table-polars-migration.md +0 -0
  213. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/04-designs-and-guides/summary-extractors.md +0 -0
  214. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/04-designs-and-guides/test-data-and-fixtures.md +0 -0
  215. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/04-designs-and-guides/test-metadata-and-merging.md +0 -0
  216. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/04-designs-and-guides/this-project.md +0 -0
  217. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/04-designs-and-guides/zensical-docs.md +0 -0
  218. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/05-epics/.gitkeep +0 -0
  219. {cellpycore-0.2.4 → cellpycore-0.2.5}/.issueflows/config.toml +0 -0
  220. {cellpycore-0.2.4 → cellpycore-0.2.5}/.pre-commit-config.yaml +0 -0
  221. {cellpycore-0.2.4 → cellpycore-0.2.5}/.python-version +0 -0
  222. {cellpycore-0.2.4 → cellpycore-0.2.5}/.readthedocs.yaml +0 -0
  223. {cellpycore-0.2.4 → cellpycore-0.2.5}/AGENTS.md +0 -0
  224. {cellpycore-0.2.4 → cellpycore-0.2.5}/LICENSE +0 -0
  225. {cellpycore-0.2.4 → cellpycore-0.2.5}/README.md +0 -0
  226. {cellpycore-0.2.4 → cellpycore-0.2.5}/ROADMAP.md +0 -0
  227. {cellpycore-0.2.4 → cellpycore-0.2.5}/SCRATCHPAD.md +0 -0
  228. {cellpycore-0.2.4 → cellpycore-0.2.5}/graphify-out/.graphify_labels.json +0 -0
  229. {cellpycore-0.2.4 → cellpycore-0.2.5}/graphify-out/.graphify_root +0 -0
  230. {cellpycore-0.2.4 → cellpycore-0.2.5}/graphify-out/GRAPH_REPORT.md +0 -0
  231. {cellpycore-0.2.4 → cellpycore-0.2.5}/graphify-out/graph.html +0 -0
  232. {cellpycore-0.2.4 → cellpycore-0.2.5}/graphify-out/graph.json +0 -0
  233. {cellpycore-0.2.4 → cellpycore-0.2.5}/graphify-out/manifest.json +0 -0
  234. {cellpycore-0.2.4 → cellpycore-0.2.5}/src/cellpycore/__init__.py +0 -0
  235. {cellpycore-0.2.4 → cellpycore-0.2.5}/src/cellpycore/config.py +0 -0
  236. {cellpycore-0.2.4 → cellpycore-0.2.5}/src/cellpycore/curves.py +0 -0
  237. {cellpycore-0.2.4 → cellpycore-0.2.5}/src/cellpycore/exceptions.py +0 -0
  238. {cellpycore-0.2.4 → cellpycore-0.2.5}/src/cellpycore/extractors.py +0 -0
  239. {cellpycore-0.2.4 → cellpycore-0.2.5}/src/cellpycore/legacy/__init__.py +0 -0
  240. {cellpycore-0.2.4 → cellpycore-0.2.5}/src/cellpycore/legacy/headers.py +0 -0
  241. {cellpycore-0.2.4 → cellpycore-0.2.5}/src/cellpycore/legacy/limits.py +0 -0
  242. {cellpycore-0.2.4 → cellpycore-0.2.5}/src/cellpycore/legacy/mapping.py +0 -0
  243. {cellpycore-0.2.4 → cellpycore-0.2.5}/src/cellpycore/legacy/meta.py +0 -0
  244. {cellpycore-0.2.4 → cellpycore-0.2.5}/src/cellpycore/legacy/meta_mapping.py +0 -0
  245. {cellpycore-0.2.4 → cellpycore-0.2.5}/src/cellpycore/legacy/mock_core.py +0 -0
  246. {cellpycore-0.2.4 → cellpycore-0.2.5}/src/cellpycore/legacy/selectors.py +0 -0
  247. {cellpycore-0.2.4 → cellpycore-0.2.5}/src/cellpycore/merge.py +0 -0
  248. {cellpycore-0.2.4 → cellpycore-0.2.5}/src/cellpycore/metadata/__init__.py +0 -0
  249. {cellpycore-0.2.4 → cellpycore-0.2.5}/src/cellpycore/metadata/io.py +0 -0
  250. {cellpycore-0.2.4 → cellpycore-0.2.5}/src/cellpycore/metadata/models.py +0 -0
  251. {cellpycore-0.2.4 → cellpycore-0.2.5}/src/cellpycore/py.typed +0 -0
  252. {cellpycore-0.2.4 → cellpycore-0.2.5}/src/cellpycore/settings_base.py +0 -0
  253. {cellpycore-0.2.4 → cellpycore-0.2.5}/src/cellpycore/summarizers.py +0 -0
  254. {cellpycore-0.2.4 → cellpycore-0.2.5}/src/cellpycore/testing/__init__.py +0 -0
  255. {cellpycore-0.2.4 → cellpycore-0.2.5}/src/cellpycore/testing/mock_data.py +0 -0
  256. {cellpycore-0.2.4 → cellpycore-0.2.5}/src/cellpycore/timestamps.py +0 -0
  257. {cellpycore-0.2.4 → cellpycore-0.2.5}/src/cellpycore/units/__init__.py +0 -0
  258. {cellpycore-0.2.4 → cellpycore-0.2.5}/src/cellpycore/units/converters.py +0 -0
  259. {cellpycore-0.2.4 → cellpycore-0.2.5}/src/cellpycore/units/spec.py +0 -0
  260. {cellpycore-0.2.4 → cellpycore-0.2.5}/zensical.toml +0 -0
@@ -1,6 +1,6 @@
1
1
  # Issue #100 — status
2
2
 
3
- - [ ] Done
3
+ - [x] Done
4
4
 
5
5
  ## What's done
6
6
 
@@ -0,0 +1,48 @@
1
+ # Issue #142: Harden cycle_mode unwrapping in OldCellpyCellCore / _cycle_mode_to_test_mode
2
+
3
+ Source: https://github.com/cellpy/cellpy-core/issues/142
4
+
5
+ ## Original issue text
6
+
7
+ ## Context
8
+
9
+ Found while working **jepegit/cellpy#668** (v1.x batch notebook): after a custom `update_cell` → `make_step_table()` → `make_summary()`, the legacy bridge crashes with:
10
+
11
+ ```text
12
+ AttributeError: 'list' object has no attribute 'strip'
13
+ ```
14
+
15
+ in `cellpycore.cell_core._cycle_mode_to_test_mode` when `OldCellpyCellCore.cycle_mode` is still list-shaped (often double-nested from cellpy-file meta, e.g. `[['anode']]`).
16
+
17
+ ### Why this is a core issue (not just v1.x)
18
+
19
+ - `cellpy` **master** already mitigates on the **consumer load path** via recursive `test_meta._unwrap` after `meta_test_dependent.update(as_list=True, …)` (and has unit tests).
20
+ - The **engine/bridge** still assumes a scalar string:
21
+ - `OldCellpyCellCore.cycle_mode` getter only does one-level `m[0]`
22
+ - setter **keeps** list values (`[x.lower() for x in cycle_mode]`) instead of storing a scalar
23
+ - `_cycle_mode_to_test_mode` calls `cycle_mode.strip()` with no list/tuple handling
24
+
25
+ Any path that skips consumer unwrap (legacy loads, in-memory meta mutation, older cellpy pins) can still hit this. v1.x (#668) will add a consumer-side unwrap backport; core should still be defensive.
26
+
27
+ ## What to do
28
+
29
+ 1. **Getter** (`OldCellpyCellCore.cycle_mode`): recursively unwrap 1-element `list`/`tuple` to a scalar (same semantics as cellpy `test_meta._unwrap`).
30
+ 2. **Setter**: unwrap first, then store a **scalar** string (or `None`) — do not persist a list of lowered strings.
31
+ 3. **`_cycle_mode_to_test_mode`**: if given a list/tuple, unwrap before `.strip()`; keep existing string / `None` / unknown-spelling behaviour.
32
+ 4. **Tests** covering at least:
33
+ - `'anode'` / `'full_cell'`
34
+ - `['anode']`
35
+ - `[['anode']]`
36
+ - `None`
37
+ - make_summary / make_core_summary does not raise on nested list meta
38
+
39
+ ## Acceptance
40
+
41
+ - Nested list `cycle_mode` no longer crashes summarization through the legacy bridge.
42
+ - Existing CE / inverted-convention tests (issue #129 era) stay green.
43
+ - No API break for callers that already pass a plain string.
44
+
45
+ ## Links
46
+
47
+ - Downstream report: https://github.com/jepegit/cellpy/issues/668
48
+ - Related consumer mitigation on master: unwrap in `cellpy.readers.cellpy_file.read` / `test_meta._unwrap`
@@ -0,0 +1,86 @@
1
+ # Issue #142 — plan: harden `cycle_mode` unwrapping
2
+
3
+ ## Goal
4
+
5
+ Stop nested list-shaped `cycle_mode` (e.g. `[['anode']]`) from crashing
6
+ `_cycle_mode_to_test_mode` / summarization on the legacy bridge; store and
7
+ expose a scalar string (or `None`) from the `cycle_mode` property.
8
+
9
+ ## Constraints
10
+
11
+ - Back-compat: plain string callers unchanged; issue #127 spelling tables and
12
+ issue #129 bridge CE polarity tests stay green.
13
+ - KISS: no new package/module; private helper next to existing translator in
14
+ `cell_core.py`. No numpy dependency (cellpy’s `_unwrap` also peels numpy
15
+ scalars / NaN — out of scope here; meta on the bridge is Python
16
+ `list`/`tuple`/`str`/`None`).
17
+ - Metadata boundary unchanged: still optional; only normalize this one field
18
+ at the property / translator edge.
19
+ - Scope: getter, setter, `_cycle_mode_to_test_mode` (+ tests). No cellpy
20
+ consumer changes (jepegit/cellpy#668 stays separate).
21
+
22
+ ### Prior art
23
+
24
+ - `cellpy.readers.test_meta._unwrap` — recursive peel of 1-element
25
+ `list`/`tuple`; multi-element left as-is. **Mirror** that rule in core
26
+ (list/tuple only).
27
+ - `_cycle_mode_to_test_mode` + `#127` tests in `tests/test_schema.py` —
28
+ spelling / warning contract; **extend**, don’t rewrite.
29
+ - `CellpyCellCore.cycle_mode` getter already does one-level `m[0]`; setter
30
+ wrongly keeps a lowered **list**. `OldCellpyCellCore` inherits this
31
+ property (no override).
32
+ - `test_bridge_summary_respects_cycle_mode` (`tests/test_golden.py`) — CE
33
+ polarity regression for string `"anode"`; keep green; add a nested-list
34
+ smoke if cheap.
35
+ - Toolbox: empty (nothing reusable). Graph: `cycle_mode` /
36
+ `_cycle_mode_to_test_mode` / `OldCellpyCellCore` communities confirm the
37
+ change set is `cell_core.py` + `test_schema.py`.
38
+
39
+ ## Approach
40
+
41
+ 1. Add `_unwrap_meta_scalar(value)` in `cell_core.py` (module-private):
42
+ while `list`/`tuple` and `len == 1`, recurse; else return value.
43
+ 2. **Getter:** unwrap `meta_test_dependent.cycle_mode`; if still
44
+ `list`/`tuple`, take `[0]` when non-empty else `None` (preserves today’s
45
+ first-element behaviour for multi-element placeholders).
46
+ 3. **Setter:** unwrap first; if still sequence, take first or `None`; then
47
+ store **scalar** `str.lower()` or `None` on both meta and `_cycle_mode`
48
+ (never a list of lowered strings). Handle `None` without calling `.lower()`.
49
+ 4. **`_cycle_mode_to_test_mode`:** unwrap (+ first-element if still sequence)
50
+ before `.strip()`; keep existing `None` / empty / known / unknown+warn
51
+ behaviour. Type hint can widen to `Optional[str | list | tuple]` or stay
52
+ loose — behaviour matters more than the annotation.
53
+ 5. No public API export of the helper.
54
+
55
+ Multi-element lists (`['anode','cathode']`) are not a real cellpy-file shape
56
+ today; taking `[0]` matches the old getter and avoids a new failure mode.
57
+
58
+ ## Files to touch
59
+
60
+ | Path | Change |
61
+ |------|--------|
62
+ | [`src/cellpycore/cell_core.py`](../../src/cellpycore/cell_core.py) | `_unwrap_meta_scalar`; harden getter / setter / `_cycle_mode_to_test_mode` |
63
+ | [`tests/test_schema.py`](../../tests/test_schema.py) | Parametrize unwrap cases next to `#127` block; nested-list → INVERTED; setter stores scalar; optional `make_core_summary` / `make_summary` smoke with nested meta |
64
+
65
+ ## Test strategy
66
+
67
+ ```bash
68
+ uv run pytest tests/test_schema.py -k cycle_mode
69
+ uv run pytest # full suite before close
70
+ uv run ruff check && uv run ruff format --check
71
+ ```
72
+
73
+ New coverage (minimum from issue):
74
+
75
+ - `_cycle_mode_to_test_mode`: `'anode'`, `'full_cell'`, `['anode']`,
76
+ `[['anode']]`, `None` (and keep existing spelling params green).
77
+ - Getter/setter: set `[['anode']]` or assign list → property returns
78
+ `"anode"`; stored meta is a `str`, not a list.
79
+ - Smoke: `OldCellpyCellCore` (or `CellpyCellCore`) with nested list on
80
+ `meta_test_dependent.cycle_mode` → `make_core_summary` / `make_summary`
81
+ does not raise.
82
+
83
+ ## Open questions
84
+
85
+ None blocking — defaults above match the issue + cellpy `_unwrap`. Say if
86
+ you want multi-element lists to warn instead of silently taking `[0]`.
@@ -0,0 +1,20 @@
1
+ # Issue #142 — status
2
+
3
+ - [x] Done
4
+
5
+ ## What's done
6
+
7
+ - Plan confirmed (`issue142_plan.md`).
8
+ - Added `_unwrap_meta_scalar` / `_as_cycle_mode_scalar` in `cell_core.py`.
9
+ - Hardened `CellpyCellCore.cycle_mode` getter/setter to store/return scalar
10
+ (or `None`); nested lists no longer persist as lowered lists.
11
+ - `_cycle_mode_to_test_mode` unwraps list/tuple before `.strip()`.
12
+ - Tests in `tests/test_schema.py` (issue #142 block): translator shapes,
13
+ setter scalar store, getter unwrap, `OldCellpyCellCore.make_core_summary`
14
+ smoke with `[['anode']]` meta.
15
+ - Full suite: 281 passed; ruff green.
16
+ - `HISTORY.md` Unreleased bullet added.
17
+
18
+ ## Remaining work
19
+
20
+ - None (close / PR).
@@ -46,7 +46,7 @@ Reconciled against the actual repo state on **2026-06-26**. Status legend: ✅ d
46
46
  | STEP-09 Harmonize headers | ✅ done | `config.Cols` + spec tests; `legacy/mapping.py` gives lossless/total `config.Cols` ↔ legacy `Headers*` round-trip (`tests/test_header_mapping.py`) (#34/#35) |
47
47
  | STEP-10 Metadata scaffolding | ✅ done | `cellpycore.metadata` (`models.py`/`io.py`); `TestMeta`/`CellMeta`/`TestMetaCollection` + (de)serialize/merge; graceful-degradation guard (`tests/test_metadata.py`) (#37) |
48
48
  | STEP-11 Timestamp representation | ✅ done | `epoch_time_utc` + `first/last_epoch_time_utc` are int64-ns UTC; `cellpycore.timestamps` conversion helpers + fixture regenerated (`tests/test_timestamps.py`) (#32, PR #38) |
49
- | STEP-12 Unit-handling boundary | 🟡 partly done | `CellpyUnits` schema in `units/spec.py` (#40/#112) + `units.py` tooling behind the optional `units` extra; factors cross the seam by value; `cellpy` still keeps duplicate converters (delegation pending) |
49
+ | STEP-12 Unit-handling boundary | ✅ done | `CellpyUnits` schema in `units/spec.py` (#40/#112) + `units.py` tooling behind the optional `units` extra; factors cross the seam by value; `cellpy` now delegates `get_converter_to_specific` / `nominal_capacity_as_absolute` to `cellpycore.units` (jepegit/cellpy #451) — the duplicate converters are retired |
50
50
 
51
51
  Per-step `Status:` lines below repeat this for context; this table is the quick reference.
52
52
  The forward work beyond these twelve steps (STEP-13+) is enumerated in
@@ -266,12 +266,15 @@ Adopt the internal int64-ns timestamp representation.
266
266
 
267
267
  ## STEP-12 Unit-handling boundary (scaffolding/tooling in core; population & policy upstream)
268
268
 
269
- **Status:** 🟡 partly done — the `CellpyUnits` schema lives in `cellpycore.units.spec`
269
+ **Status:** ✅ done — the `CellpyUnits` schema lives in `cellpycore.units.spec`
270
270
  (#40, #112) and the pint-based conversion tooling (`cellpycore.units`:
271
271
  `get_converter_to_specific`, `nominal_capacity_as_absolute`, `Q`, output-unit defaults)
272
- already exist behind the optional `units` extra, attached to the `OldCellpyCellCore`
273
- bridge, and conversion factors already cross the seam **by value**. Remaining on the
274
- **cellpy** side only: duplicate converter functions not yet delegated to core.
272
+ exists behind the optional `units` extra, attached to the `OldCellpyCellCore`
273
+ bridge, and conversion factors cross the seam **by value**. The final cellpy-side move
274
+ has landed: `CellpyCell.get_converter_to_specific` / `nominal_capacity_as_absolute`
275
+ (and `convert_value` / `calculate_scaler`) now delegate to `cellpycore.units`
276
+ (jepegit/cellpy #451, unit plan Phase 2), guarded by converter-parity fixtures on both
277
+ sides — the duplicated converters are retired.
275
278
 
276
279
  **Codebase:** `cellpy-core` (scaffolding/tooling — `legacy.py` + `units.py`); population
277
280
  (`raw_units` from loaders) and the decision to delegate are `cellpy`'s opt-in.
@@ -299,8 +302,9 @@ already did for headers and the step engine).
299
302
 
300
303
  ## Remaining work (STEP-13+) — finalized 2026-06-28 (issue #39)
301
304
 
302
- The original twelve steps are complete except for the two intentionally-continuous /
303
- partly-done ones (STEP-06 golden fixtures, STEP-12 unit boundary). Going through the
305
+ The original twelve steps are complete except for the one intentionally-continuous
306
+ one (STEP-06 golden fixtures); STEP-12 (unit boundary) closed once the cellpy-side
307
+ converter delegation landed (jepegit/cellpy #451). Going through the
304
308
  roadmap and the companion design docs surfaced the remaining work below. Each item is now
305
309
  tracked as its own **cellpy-core** GitHub issue (the cellpy-side delegation work stays on
306
310
  jepegit/cellpy). Captured under issue #39.
@@ -339,12 +343,12 @@ flowchart TD
339
343
  S08 --> S09["STEP-09 Harmonize headers ✅"]
340
344
  S08 --> S10["STEP-10 Metadata scaffolding ✅"]
341
345
  S08 --> S11["STEP-11 Timestamp representation ✅"]
342
- S03 --> S12["STEP-12 Unit-handling boundary 🟡"]
346
+ S03 --> S12["STEP-12 Unit-handling boundary ✅"]
343
347
  S07["STEP-07 Build-backend swap ✅"] -.independent.-> S08
344
348
 
345
349
  classDef done fill:#d4edda,stroke:#28a745,color:#155724;
346
350
  classDef partly fill:#fff3cd,stroke:#ffc107,color:#856404;
347
351
  classDef todo fill:#f8d7da,stroke:#dc3545,color:#721c24;
348
- class S01,S02,S03,S04,S05,S07,S08,S09,S10,S11 done;
349
- class S06,S12 partly;
352
+ class S01,S02,S03,S04,S05,S07,S08,S09,S10,S11,S12 done;
353
+ class S06 partly;
350
354
  ```
@@ -0,0 +1,14 @@
1
+ {
2
+ "python.testing.pytestArgs": [
3
+ "tests"
4
+ ],
5
+ "python.testing.unittestEnabled": false,
6
+ "python.testing.pytestEnabled": true,
7
+ "python-envs.pythonProjects": [
8
+ {
9
+ "path": ".",
10
+ "envManager": "ms-python.python:venv",
11
+ "packageManager": "ms-python.python:pip"
12
+ }
13
+ ]
14
+ }
@@ -4,6 +4,8 @@ All notable changes to this project will be documented in this file.
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ - Harden `cycle_mode` unwrapping in `OldCellpyCellCore` / `_cycle_mode_to_test_mode`. (#142)
8
+
7
9
  ## [0.2.4] - 2026-07-23
8
10
 
9
11
  - Add Equivalent Full Cycles (EFC) utilities (#138). `summarizers.throughput_to_raw`
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.4
1
+ Metadata-Version: 2.5
2
2
  Name: cellpycore
3
- Version: 0.2.4
3
+ Version: 0.2.5
4
4
  Summary: Core engine for cellpy: fast, thread-safe step and cycle summarization of battery-cycling raw data
5
5
  License-Expression: MIT
6
6
  License-File: LICENSE
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "cellpycore"
3
- version = "0.2.4"
3
+ version = "0.2.5"
4
4
  license = "MIT"
5
5
  license-files = ["LICEN[CS]E*"]
6
6
  description = "Core engine for cellpy: fast, thread-safe step and cycle summarization of battery-cycling raw data"
@@ -1,7 +1,7 @@
1
1
  import datetime
2
2
  import logging
3
3
  import time
4
- from typing import Callable, Iterable, List, Optional, Sequence, TypeVar, Union
4
+ from typing import Any, Callable, Iterable, List, Optional, Sequence, TypeVar, Union
5
5
 
6
6
  from cellpycore import config
7
7
  from cellpycore.exceptions import NoDataFound
@@ -24,7 +24,31 @@ _NORMAL_CYCLE_MODES = frozenset(
24
24
  )
25
25
 
26
26
 
27
- def _cycle_mode_to_test_mode(cycle_mode: Optional[str]) -> config.TestMode:
27
+ def _unwrap_meta_scalar(value: Any) -> Any:
28
+ """Recursively peel 1-element ``list``/``tuple`` wrappers.
29
+
30
+ Mirrors cellpy's ``test_meta._unwrap`` for the shapes that show up in
31
+ cellpy-file meta (often nested once, e.g. ``[['anode']]``). Multi-element
32
+ sequences are left unchanged.
33
+ """
34
+ if isinstance(value, (list, tuple)) and len(value) == 1:
35
+ return _unwrap_meta_scalar(value[0])
36
+ return value
37
+
38
+
39
+ def _as_cycle_mode_scalar(value: Any) -> Optional[str]:
40
+ """Normalize ``cycle_mode`` to a scalar string or ``None``.
41
+
42
+ Unwraps 1-element list/tuple nesting, then takes the first element of any
43
+ remaining multi-element sequence (legacy getter behaviour).
44
+ """
45
+ value = _unwrap_meta_scalar(value)
46
+ if isinstance(value, (list, tuple)):
47
+ return value[0] if value else None
48
+ return value
49
+
50
+
51
+ def _cycle_mode_to_test_mode(cycle_mode: Any) -> config.TestMode:
28
52
  """Map a legacy ``cycle_mode`` string to a :class:`config.TestMode`.
29
53
 
30
54
  The inverted (anode half-cell) convention is selected by any of ``"anode"``
@@ -33,16 +57,19 @@ def _cycle_mode_to_test_mode(cycle_mode: Optional[str]) -> config.TestMode:
33
57
  ``None`` and the recognized normal-convention spellings map to
34
58
  ``TestMode.NORMAL``.
35
59
 
36
- An *unrecognized* non-empty value also maps to ``NORMAL`` but logs a warning,
37
- so a mistyped or unmapped mode fails loudly instead of silently flipping the
38
- ``coulombic_efficiency`` / ``coulombic_difference`` sign conventions.
60
+ Nested 1-element ``list``/``tuple`` wrappers (cellpy-file meta shape) are
61
+ unwrapped before matching. An *unrecognized* non-empty value also maps to
62
+ ``NORMAL`` but logs a warning, so a mistyped or unmapped mode fails loudly
63
+ instead of silently flipping the ``coulombic_efficiency`` /
64
+ ``coulombic_difference`` sign conventions.
39
65
 
40
66
  Args:
41
- cycle_mode: Legacy mode string, or ``None``.
67
+ cycle_mode: Legacy mode string, nested list/tuple wrappers, or ``None``.
42
68
 
43
69
  Returns:
44
70
  The corresponding ``TestMode`` for summary sign conventions.
45
71
  """
72
+ cycle_mode = _as_cycle_mode_scalar(cycle_mode)
46
73
  if cycle_mode is None:
47
74
  return config.TestMode.NORMAL
48
75
  key = cycle_mode.strip().lower()
@@ -370,23 +397,18 @@ class CellpyCellCore:
370
397
  # TODO: v2.0 edit this from scalar to list
371
398
  try:
372
399
  data = self.data
373
- m = data.meta_test_dependent.cycle_mode
374
- # cellpy saves this as a list (ready for v2.0),
375
- # but we want to return a scalar for the moment
376
- # Temporary fix to make sure that cycle_mode is a scalar:
377
- if isinstance(m, (tuple, list)):
378
- return m[0]
379
- return m
400
+ # cellpy-file meta often stores 1-element (sometimes nested) lists;
401
+ # expose a scalar for the current engine.
402
+ return _as_cycle_mode_scalar(data.meta_test_dependent.cycle_mode)
380
403
  except NoDataFound:
381
404
  return self._cycle_mode
382
405
 
383
406
  @cycle_mode.setter
384
- def cycle_mode(self, cycle_mode: str):
385
- if isinstance(cycle_mode, (tuple, list)):
386
- cycle_mode = [cycle_mode.lower() for cycle_mode in cycle_mode]
387
- else:
388
- cycle_mode = cycle_mode.lower()
407
+ def cycle_mode(self, cycle_mode: Any):
389
408
  # TODO: v2.0 edit this from scalar to list
409
+ cycle_mode = _as_cycle_mode_scalar(cycle_mode)
410
+ if cycle_mode is not None:
411
+ cycle_mode = cycle_mode.lower()
390
412
  logger.debug(f"-> cycle_mode: {cycle_mode}")
391
413
  try:
392
414
  data = self.data
@@ -73,7 +73,7 @@ css = [
73
73
 
74
74
  [[package]]
75
75
  name = "cellpycore"
76
- version = "0.2.4"
76
+ version = "0.2.5"
77
77
  source = { editable = "." }
78
78
  dependencies = [
79
79
  { name = "pandas" },
@@ -1,7 +0,0 @@
1
- {
2
- "python.testing.pytestArgs": [
3
- "tests"
4
- ],
5
- "python.testing.unittestEnabled": false,
6
- "python.testing.pytestEnabled": true
7
- }
File without changes
File without changes
File without changes