cfinterface 1.9.1__tar.gz → 1.10.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 (263) hide show
  1. {cfinterface-1.9.1 → cfinterface-1.10.1}/.gitignore +3 -0
  2. {cfinterface-1.9.1 → cfinterface-1.10.1}/CHANGELOG.md +16 -0
  3. {cfinterface-1.9.1 → cfinterface-1.10.1}/PKG-INFO +1 -1
  4. {cfinterface-1.9.1 → cfinterface-1.10.1}/cfinterface/__init__.py +1 -1
  5. {cfinterface-1.9.1 → cfinterface-1.10.1}/cfinterface/components/floatfield.py +14 -1
  6. {cfinterface-1.9.1 → cfinterface-1.10.1}/cfinterface/reading/registerreading.py +1 -0
  7. {cfinterface-1.9.1 → cfinterface-1.10.1}/tests/components/test_floatfield.py +105 -0
  8. {cfinterface-1.9.1 → cfinterface-1.10.1}/tests/files/test_registerfile.py +42 -0
  9. cfinterface-1.9.1/plans/cfinterface-architecture-improvement/.implementation-state.json +0 -172
  10. cfinterface-1.9.1/plans/cfinterface-architecture-improvement/00-master-plan.md +0 -143
  11. cfinterface-1.9.1/plans/cfinterface-architecture-improvement/README.md +0 -55
  12. cfinterface-1.9.1/plans/cfinterface-architecture-improvement/epic-01-remove-pandas-dependency/00-epic-overview.md +0 -49
  13. cfinterface-1.9.1/plans/cfinterface-architecture-improvement/epic-01-remove-pandas-dependency/learnings.md +0 -91
  14. cfinterface-1.9.1/plans/cfinterface-architecture-improvement/epic-01-remove-pandas-dependency/ticket-001-create-null-checking-utility.md +0 -176
  15. cfinterface-1.9.1/plans/cfinterface-architecture-improvement/epic-01-remove-pandas-dependency/ticket-002-replace-pd-isnull-in-fields.md +0 -177
  16. cfinterface-1.9.1/plans/cfinterface-architecture-improvement/epic-01-remove-pandas-dependency/ticket-003-lazy-pandas-import-in-registerfile.md +0 -143
  17. cfinterface-1.9.1/plans/cfinterface-architecture-improvement/epic-01-remove-pandas-dependency/ticket-004-move-pandas-to-optional-dependency.md +0 -153
  18. cfinterface-1.9.1/plans/cfinterface-architecture-improvement/epic-02-compile-regex-and-storage-enum/00-epic-overview.md +0 -60
  19. cfinterface-1.9.1/plans/cfinterface-architecture-improvement/epic-02-compile-regex-and-storage-enum/learnings.md +0 -76
  20. cfinterface-1.9.1/plans/cfinterface-architecture-improvement/epic-02-compile-regex-and-storage-enum/ticket-005-compile-regex-patterns.md +0 -183
  21. cfinterface-1.9.1/plans/cfinterface-architecture-improvement/epic-02-compile-regex-and-storage-enum/ticket-006-create-storagetype-enum.md +0 -180
  22. cfinterface-1.9.1/plans/cfinterface-architecture-improvement/epic-02-compile-regex-and-storage-enum/ticket-007-update-factory-functions.md +0 -194
  23. cfinterface-1.9.1/plans/cfinterface-architecture-improvement/epic-02-compile-regex-and-storage-enum/ticket-008-migrate-internal-storage-usage.md +0 -243
  24. cfinterface-1.9.1/plans/cfinterface-architecture-improvement/epic-02-compile-regex-and-storage-enum/ticket-009-add-deprecation-warnings.md +0 -193
  25. cfinterface-1.9.1/plans/cfinterface-architecture-improvement/epic-03-optimize-float-field-write/00-epic-overview.md +0 -25
  26. cfinterface-1.9.1/plans/cfinterface-architecture-improvement/epic-03-optimize-float-field-write/learnings.md +0 -69
  27. cfinterface-1.9.1/plans/cfinterface-architecture-improvement/epic-03-optimize-float-field-write/ticket-010-optimize-floatfield-write.md +0 -242
  28. cfinterface-1.9.1/plans/cfinterface-architecture-improvement/epic-03-optimize-float-field-write/ticket-011-add-floatfield-benchmarks.md +0 -224
  29. cfinterface-1.9.1/plans/cfinterface-architecture-improvement/epic-04-array-backed-data-containers/00-epic-overview.md +0 -33
  30. cfinterface-1.9.1/plans/cfinterface-architecture-improvement/epic-04-array-backed-data-containers/learnings.md +0 -96
  31. cfinterface-1.9.1/plans/cfinterface-architecture-improvement/epic-04-array-backed-data-containers/ticket-012-list-backed-registerdata.md +0 -160
  32. cfinterface-1.9.1/plans/cfinterface-architecture-improvement/epic-04-array-backed-data-containers/ticket-013-list-backed-blockdata.md +0 -158
  33. cfinterface-1.9.1/plans/cfinterface-architecture-improvement/epic-04-array-backed-data-containers/ticket-014-list-backed-sectiondata.md +0 -156
  34. cfinterface-1.9.1/plans/cfinterface-architecture-improvement/epic-04-array-backed-data-containers/ticket-015-computed-prev-next-properties.md +0 -266
  35. cfinterface-1.9.1/plans/cfinterface-architecture-improvement/epic-04-array-backed-data-containers/ticket-016-type-indexed-lookup.md +0 -199
  36. cfinterface-1.9.1/plans/cfinterface-architecture-improvement/epic-05-type-safe-text-binary-dispatch/00-epic-overview.md +0 -29
  37. cfinterface-1.9.1/plans/cfinterface-architecture-improvement/epic-05-type-safe-text-binary-dispatch/learnings.md +0 -209
  38. cfinterface-1.9.1/plans/cfinterface-architecture-improvement/epic-05-type-safe-text-binary-dispatch/ticket-017-typed-field-protocol.md +0 -175
  39. cfinterface-1.9.1/plans/cfinterface-architecture-improvement/epic-05-type-safe-text-binary-dispatch/ticket-018-typed-repository-signatures.md +0 -210
  40. cfinterface-1.9.1/plans/cfinterface-architecture-improvement/epic-05-type-safe-text-binary-dispatch/ticket-019-typed-line-dispatch.md +0 -159
  41. cfinterface-1.9.1/plans/cfinterface-architecture-improvement/epic-05-type-safe-text-binary-dispatch/ticket-020-typed-component-io.md +0 -249
  42. cfinterface-1.9.1/plans/cfinterface-architecture-improvement/epic-06-generic-tabular-parser/00-epic-overview.md +0 -27
  43. cfinterface-1.9.1/plans/cfinterface-architecture-improvement/epic-06-generic-tabular-parser/ticket-021-tabular-parser-engine.md +0 -198
  44. cfinterface-1.9.1/plans/cfinterface-architecture-improvement/epic-06-generic-tabular-parser/ticket-022-tabular-section-base.md +0 -220
  45. cfinterface-1.9.1/plans/cfinterface-architecture-improvement/epic-06-generic-tabular-parser/ticket-023-delimited-tabular-parsing.md +0 -198
  46. cfinterface-1.9.1/plans/cfinterface-architecture-improvement/epic-07-schema-versioning-and-batch-ops/00-epic-overview.md +0 -32
  47. cfinterface-1.9.1/plans/cfinterface-architecture-improvement/epic-07-schema-versioning-and-batch-ops/learnings.md +0 -62
  48. cfinterface-1.9.1/plans/cfinterface-architecture-improvement/epic-07-schema-versioning-and-batch-ops/ticket-024-schema-version-descriptor.md +0 -133
  49. cfinterface-1.9.1/plans/cfinterface-architecture-improvement/epic-07-schema-versioning-and-batch-ops/ticket-025-instance-level-version-binding.md +0 -162
  50. cfinterface-1.9.1/plans/cfinterface-architecture-improvement/epic-07-schema-versioning-and-batch-ops/ticket-026-batch-read-api.md +0 -164
  51. cfinterface-1.9.1/plans/cfinterface-architecture-improvement/epic-07-schema-versioning-and-batch-ops/ticket-027-version-validation.md +0 -214
  52. cfinterface-1.9.1/plans/cfinterface-architecture-improvement/learnings/epic-01-summary.md +0 -41
  53. cfinterface-1.9.1/plans/cfinterface-architecture-improvement/learnings/epic-02-summary.md +0 -64
  54. cfinterface-1.9.1/plans/cfinterface-architecture-improvement/learnings/epic-03-summary.md +0 -80
  55. cfinterface-1.9.1/plans/cfinterface-architecture-improvement/learnings/epic-04-summary.md +0 -79
  56. cfinterface-1.9.1/plans/cfinterface-architecture-improvement/learnings/epic-05-summary.md +0 -96
  57. cfinterface-1.9.1/plans/cfinterface-architecture-improvement/learnings/epic-06-summary.md +0 -130
  58. cfinterface-1.9.1/plans/cfinterface-architecture-improvement/learnings/epic-07-summary.md +0 -125
  59. cfinterface-1.9.1/plans/cfinterface-quality-and-ci/.implementation-state.json +0 -449
  60. cfinterface-1.9.1/plans/cfinterface-quality-and-ci/00-master-plan.md +0 -119
  61. cfinterface-1.9.1/plans/cfinterface-quality-and-ci/README.md +0 -69
  62. cfinterface-1.9.1/plans/cfinterface-quality-and-ci/epic-01-pyproject-and-tool-config/00-epic-overview.md +0 -44
  63. cfinterface-1.9.1/plans/cfinterface-quality-and-ci/epic-01-pyproject-and-tool-config/ticket-001-update-classifiers-and-metadata.md +0 -117
  64. cfinterface-1.9.1/plans/cfinterface-quality-and-ci/epic-01-pyproject-and-tool-config/ticket-002-add-pytest-configuration.md +0 -118
  65. cfinterface-1.9.1/plans/cfinterface-quality-and-ci/epic-01-pyproject-and-tool-config/ticket-003-add-mypy-configuration.md +0 -157
  66. cfinterface-1.9.1/plans/cfinterface-quality-and-ci/epic-01-pyproject-and-tool-config/ticket-004-fix-mypy-strict-errors.md +0 -141
  67. cfinterface-1.9.1/plans/cfinterface-quality-and-ci/epic-01-pyproject-and-tool-config/ticket-005-add-coverage-and-ruff-config.md +0 -131
  68. cfinterface-1.9.1/plans/cfinterface-quality-and-ci/epic-01-pyproject-and-tool-config/ticket-006-add-py-typed-and-dev-deps.md +0 -138
  69. cfinterface-1.9.1/plans/cfinterface-quality-and-ci/epic-02-ci-overhaul/00-epic-overview.md +0 -41
  70. cfinterface-1.9.1/plans/cfinterface-quality-and-ci/epic-02-ci-overhaul/ticket-007-expand-test-matrix.md +0 -166
  71. cfinterface-1.9.1/plans/cfinterface-quality-and-ci/epic-02-ci-overhaul/ticket-008-extract-lint-job.md +0 -138
  72. cfinterface-1.9.1/plans/cfinterface-quality-and-ci/epic-02-ci-overhaul/ticket-009-create-benchmark-workflow.md +0 -135
  73. cfinterface-1.9.1/plans/cfinterface-quality-and-ci/epic-02-ci-overhaul/ticket-010-update-docs-and-publish-workflows.md +0 -189
  74. cfinterface-1.9.1/plans/cfinterface-quality-and-ci/epic-03-test-infrastructure/00-epic-overview.md +0 -40
  75. cfinterface-1.9.1/plans/cfinterface-quality-and-ci/epic-03-test-infrastructure/ticket-011-create-conftest-and-fixtures.md +0 -195
  76. cfinterface-1.9.1/plans/cfinterface-quality-and-ci/epic-03-test-infrastructure/ticket-012-add-hypothesis-field-tests.md +0 -205
  77. cfinterface-1.9.1/plans/cfinterface-quality-and-ci/epic-03-test-infrastructure/ticket-013-add-hypothesis-tabular-tests.md +0 -238
  78. cfinterface-1.9.1/plans/cfinterface-quality-and-ci/epic-03-test-infrastructure/ticket-014-migrate-to-pytest-benchmark.md +0 -179
  79. cfinterface-1.9.1/plans/cfinterface-quality-and-ci/epic-04-sphinx-docs/00-epic-overview.md +0 -41
  80. cfinterface-1.9.1/plans/cfinterface-quality-and-ci/epic-04-sphinx-docs/ticket-015-add-tabular-reference-pages.md +0 -155
  81. cfinterface-1.9.1/plans/cfinterface-quality-and-ci/epic-04-sphinx-docs/ticket-016-add-versioning-reference-page.md +0 -151
  82. cfinterface-1.9.1/plans/cfinterface-quality-and-ci/epic-04-sphinx-docs/ticket-017-add-storage-and-adapter-pages.md +0 -181
  83. cfinterface-1.9.1/plans/cfinterface-quality-and-ci/epic-04-sphinx-docs/ticket-018-fix-docstrings-and-index.md +0 -157
  84. cfinterface-1.9.1/plans/cfinterface-quality-and-ci/epic-05-changelog-and-release-prep/00-epic-overview.md +0 -33
  85. cfinterface-1.9.1/plans/cfinterface-quality-and-ci/epic-05-changelog-and-release-prep/ticket-019-create-changelog.md +0 -169
  86. cfinterface-1.9.1/plans/cfinterface-quality-and-ci/epic-05-changelog-and-release-prep/ticket-020-release-prep-review.md +0 -124
  87. cfinterface-1.9.1/plans/infra-docs-overhaul/.implementation-state.json +0 -337
  88. cfinterface-1.9.1/plans/infra-docs-overhaul/00-master-plan.md +0 -107
  89. cfinterface-1.9.1/plans/infra-docs-overhaul/README.md +0 -81
  90. cfinterface-1.9.1/plans/infra-docs-overhaul/epic-01-ci-and-developer-tooling/00-epic-overview.md +0 -26
  91. cfinterface-1.9.1/plans/infra-docs-overhaul/epic-01-ci-and-developer-tooling/ticket-001-add-pre-commit-configuration.md +0 -124
  92. cfinterface-1.9.1/plans/infra-docs-overhaul/epic-01-ci-and-developer-tooling/ticket-002-upgrade-github-actions-versions.md +0 -103
  93. cfinterface-1.9.1/plans/infra-docs-overhaul/epic-01-ci-and-developer-tooling/ticket-003-migrate-docs-deployment.md +0 -149
  94. cfinterface-1.9.1/plans/infra-docs-overhaul/epic-02-sphinx-modernization/00-epic-overview.md +0 -27
  95. cfinterface-1.9.1/plans/infra-docs-overhaul/epic-02-sphinx-modernization/ticket-004-migrate-sphinx-theme-to-furo.md +0 -119
  96. cfinterface-1.9.1/plans/infra-docs-overhaul/epic-02-sphinx-modernization/ticket-005-add-sphinx-gallery-examples.md +0 -119
  97. cfinterface-1.9.1/plans/infra-docs-overhaul/epic-02-sphinx-modernization/ticket-006-update-conf-language-intersphinx.md +0 -113
  98. cfinterface-1.9.1/plans/infra-docs-overhaul/epic-03-documentation-content/00-epic-overview.md +0 -30
  99. cfinterface-1.9.1/plans/infra-docs-overhaul/epic-03-documentation-content/ticket-007-create-architecture-overview.md +0 -132
  100. cfinterface-1.9.1/plans/infra-docs-overhaul/epic-03-documentation-content/ticket-008-create-faq-page.md +0 -129
  101. cfinterface-1.9.1/plans/infra-docs-overhaul/epic-03-documentation-content/ticket-009-create-migration-guide.md +0 -138
  102. cfinterface-1.9.1/plans/infra-docs-overhaul/epic-03-documentation-content/ticket-010-create-performance-tips-page.md +0 -131
  103. cfinterface-1.9.1/plans/infra-docs-overhaul/epic-03-documentation-content/ticket-011-update-contributing-rst.md +0 -130
  104. cfinterface-1.9.1/plans/infra-docs-overhaul/epic-04-repository-polish/00-epic-overview.md +0 -23
  105. cfinterface-1.9.1/plans/infra-docs-overhaul/epic-04-repository-polish/ticket-012-create-root-contributing-md.md +0 -106
  106. cfinterface-1.9.1/plans/infra-docs-overhaul/epic-04-repository-polish/ticket-013-restructure-index-rst.md +0 -142
  107. cfinterface-1.9.1/plans/infra-docs-overhaul/learnings/epic-01-summary.md +0 -29
  108. cfinterface-1.9.1/plans/infra-docs-overhaul/learnings/epic-02-summary.md +0 -31
  109. cfinterface-1.9.1/plans/infra-docs-overhaul/learnings/epic-03-summary.md +0 -28
  110. {cfinterface-1.9.1 → cfinterface-1.10.1}/.github/workflows/benchmark.yml +0 -0
  111. {cfinterface-1.9.1 → cfinterface-1.10.1}/.github/workflows/docs.yml +0 -0
  112. {cfinterface-1.9.1 → cfinterface-1.10.1}/.github/workflows/main.yml +0 -0
  113. {cfinterface-1.9.1 → cfinterface-1.10.1}/.github/workflows/publish.yml +0 -0
  114. {cfinterface-1.9.1 → cfinterface-1.10.1}/.pre-commit-config.yaml +0 -0
  115. {cfinterface-1.9.1 → cfinterface-1.10.1}/CONTRIBUTING.md +0 -0
  116. {cfinterface-1.9.1 → cfinterface-1.10.1}/LICENSE +0 -0
  117. {cfinterface-1.9.1 → cfinterface-1.10.1}/README.md +0 -0
  118. {cfinterface-1.9.1 → cfinterface-1.10.1}/benchmarks/__init__.py +0 -0
  119. {cfinterface-1.9.1 → cfinterface-1.10.1}/benchmarks/bench_floatfield_write.py +0 -0
  120. {cfinterface-1.9.1 → cfinterface-1.10.1}/cfinterface/_utils/__init__.py +0 -0
  121. {cfinterface-1.9.1 → cfinterface-1.10.1}/cfinterface/adapters/__init__.py +0 -0
  122. {cfinterface-1.9.1 → cfinterface-1.10.1}/cfinterface/adapters/components/__init__.py +0 -0
  123. {cfinterface-1.9.1 → cfinterface-1.10.1}/cfinterface/adapters/components/line/__init__.py +0 -0
  124. {cfinterface-1.9.1 → cfinterface-1.10.1}/cfinterface/adapters/components/line/repository.py +0 -0
  125. {cfinterface-1.9.1 → cfinterface-1.10.1}/cfinterface/adapters/components/repository.py +0 -0
  126. {cfinterface-1.9.1 → cfinterface-1.10.1}/cfinterface/adapters/reading/__init__.py +0 -0
  127. {cfinterface-1.9.1 → cfinterface-1.10.1}/cfinterface/adapters/reading/repository.py +0 -0
  128. {cfinterface-1.9.1 → cfinterface-1.10.1}/cfinterface/adapters/writing/__init__.py +0 -0
  129. {cfinterface-1.9.1 → cfinterface-1.10.1}/cfinterface/adapters/writing/repository.py +0 -0
  130. {cfinterface-1.9.1 → cfinterface-1.10.1}/cfinterface/components/__init__.py +0 -0
  131. {cfinterface-1.9.1 → cfinterface-1.10.1}/cfinterface/components/block.py +0 -0
  132. {cfinterface-1.9.1 → cfinterface-1.10.1}/cfinterface/components/datetimefield.py +0 -0
  133. {cfinterface-1.9.1 → cfinterface-1.10.1}/cfinterface/components/defaultblock.py +0 -0
  134. {cfinterface-1.9.1 → cfinterface-1.10.1}/cfinterface/components/defaultregister.py +0 -0
  135. {cfinterface-1.9.1 → cfinterface-1.10.1}/cfinterface/components/defaultsection.py +0 -0
  136. {cfinterface-1.9.1 → cfinterface-1.10.1}/cfinterface/components/field.py +0 -0
  137. {cfinterface-1.9.1 → cfinterface-1.10.1}/cfinterface/components/integerfield.py +0 -0
  138. {cfinterface-1.9.1 → cfinterface-1.10.1}/cfinterface/components/line.py +0 -0
  139. {cfinterface-1.9.1 → cfinterface-1.10.1}/cfinterface/components/literalfield.py +0 -0
  140. {cfinterface-1.9.1 → cfinterface-1.10.1}/cfinterface/components/register.py +0 -0
  141. {cfinterface-1.9.1 → cfinterface-1.10.1}/cfinterface/components/section.py +0 -0
  142. {cfinterface-1.9.1 → cfinterface-1.10.1}/cfinterface/components/tabular.py +0 -0
  143. {cfinterface-1.9.1 → cfinterface-1.10.1}/cfinterface/data/__init__.py +0 -0
  144. {cfinterface-1.9.1 → cfinterface-1.10.1}/cfinterface/data/blockdata.py +0 -0
  145. {cfinterface-1.9.1 → cfinterface-1.10.1}/cfinterface/data/registerdata.py +0 -0
  146. {cfinterface-1.9.1 → cfinterface-1.10.1}/cfinterface/data/sectiondata.py +0 -0
  147. {cfinterface-1.9.1 → cfinterface-1.10.1}/cfinterface/files/__init__.py +0 -0
  148. {cfinterface-1.9.1 → cfinterface-1.10.1}/cfinterface/files/blockfile.py +0 -0
  149. {cfinterface-1.9.1 → cfinterface-1.10.1}/cfinterface/files/registerfile.py +0 -0
  150. {cfinterface-1.9.1 → cfinterface-1.10.1}/cfinterface/files/sectionfile.py +0 -0
  151. {cfinterface-1.9.1 → cfinterface-1.10.1}/cfinterface/py.typed +0 -0
  152. {cfinterface-1.9.1 → cfinterface-1.10.1}/cfinterface/reading/__init__.py +0 -0
  153. {cfinterface-1.9.1 → cfinterface-1.10.1}/cfinterface/reading/blockreading.py +0 -0
  154. {cfinterface-1.9.1 → cfinterface-1.10.1}/cfinterface/reading/sectionreading.py +0 -0
  155. {cfinterface-1.9.1 → cfinterface-1.10.1}/cfinterface/storage.py +0 -0
  156. {cfinterface-1.9.1 → cfinterface-1.10.1}/cfinterface/versioning.py +0 -0
  157. {cfinterface-1.9.1 → cfinterface-1.10.1}/cfinterface/writing/__init__.py +0 -0
  158. {cfinterface-1.9.1 → cfinterface-1.10.1}/cfinterface/writing/blockwriting.py +0 -0
  159. {cfinterface-1.9.1 → cfinterface-1.10.1}/cfinterface/writing/registerwriting.py +0 -0
  160. {cfinterface-1.9.1 → cfinterface-1.10.1}/cfinterface/writing/sectionwriting.py +0 -0
  161. {cfinterface-1.9.1 → cfinterface-1.10.1}/docs/source/_static/logo_cfinterface.svg +0 -0
  162. {cfinterface-1.9.1 → cfinterface-1.10.1}/docs/source/conf.py +0 -0
  163. {cfinterface-1.9.1 → cfinterface-1.10.1}/docs/source/getting_started/contributing.rst +0 -0
  164. {cfinterface-1.9.1 → cfinterface-1.10.1}/docs/source/getting_started/tutorial.rst +0 -0
  165. {cfinterface-1.9.1 → cfinterface-1.10.1}/docs/source/guides/architecture.rst +0 -0
  166. {cfinterface-1.9.1 → cfinterface-1.10.1}/docs/source/guides/faq.rst +0 -0
  167. {cfinterface-1.9.1 → cfinterface-1.10.1}/docs/source/guides/migration-v1.9.rst +0 -0
  168. {cfinterface-1.9.1 → cfinterface-1.10.1}/docs/source/guides/performance.rst +0 -0
  169. {cfinterface-1.9.1 → cfinterface-1.10.1}/docs/source/index.rst +0 -0
  170. {cfinterface-1.9.1 → cfinterface-1.10.1}/docs/source/install/install.rst +0 -0
  171. {cfinterface-1.9.1 → cfinterface-1.10.1}/docs/source/reference/adapters/files/components.rst +0 -0
  172. {cfinterface-1.9.1 → cfinterface-1.10.1}/docs/source/reference/adapters/files/line.rst +0 -0
  173. {cfinterface-1.9.1 → cfinterface-1.10.1}/docs/source/reference/adapters/files/reading.rst +0 -0
  174. {cfinterface-1.9.1 → cfinterface-1.10.1}/docs/source/reference/adapters/files/writing.rst +0 -0
  175. {cfinterface-1.9.1 → cfinterface-1.10.1}/docs/source/reference/adapters/index.rst +0 -0
  176. {cfinterface-1.9.1 → cfinterface-1.10.1}/docs/source/reference/blocks/files/block.rst +0 -0
  177. {cfinterface-1.9.1 → cfinterface-1.10.1}/docs/source/reference/blocks/files/blockdata.rst +0 -0
  178. {cfinterface-1.9.1 → cfinterface-1.10.1}/docs/source/reference/blocks/files/blockfile.rst +0 -0
  179. {cfinterface-1.9.1 → cfinterface-1.10.1}/docs/source/reference/blocks/index.rst +0 -0
  180. {cfinterface-1.9.1 → cfinterface-1.10.1}/docs/source/reference/fields/components/datetimefield.rst +0 -0
  181. {cfinterface-1.9.1 → cfinterface-1.10.1}/docs/source/reference/fields/components/field.rst +0 -0
  182. {cfinterface-1.9.1 → cfinterface-1.10.1}/docs/source/reference/fields/components/floatfield.rst +0 -0
  183. {cfinterface-1.9.1 → cfinterface-1.10.1}/docs/source/reference/fields/components/integerfield.rst +0 -0
  184. {cfinterface-1.9.1 → cfinterface-1.10.1}/docs/source/reference/fields/components/literalfield.rst +0 -0
  185. {cfinterface-1.9.1 → cfinterface-1.10.1}/docs/source/reference/fields/index.rst +0 -0
  186. {cfinterface-1.9.1 → cfinterface-1.10.1}/docs/source/reference/line/index.rst +0 -0
  187. {cfinterface-1.9.1 → cfinterface-1.10.1}/docs/source/reference/registers/files/register.rst +0 -0
  188. {cfinterface-1.9.1 → cfinterface-1.10.1}/docs/source/reference/registers/files/registerdata.rst +0 -0
  189. {cfinterface-1.9.1 → cfinterface-1.10.1}/docs/source/reference/registers/files/registerfile.rst +0 -0
  190. {cfinterface-1.9.1 → cfinterface-1.10.1}/docs/source/reference/registers/index.rst +0 -0
  191. {cfinterface-1.9.1 → cfinterface-1.10.1}/docs/source/reference/sections/files/section.rst +0 -0
  192. {cfinterface-1.9.1 → cfinterface-1.10.1}/docs/source/reference/sections/files/sectiondata.rst +0 -0
  193. {cfinterface-1.9.1 → cfinterface-1.10.1}/docs/source/reference/sections/files/sectionfile.rst +0 -0
  194. {cfinterface-1.9.1 → cfinterface-1.10.1}/docs/source/reference/sections/index.rst +0 -0
  195. {cfinterface-1.9.1 → cfinterface-1.10.1}/docs/source/reference/storage/files/storagetype.rst +0 -0
  196. {cfinterface-1.9.1 → cfinterface-1.10.1}/docs/source/reference/storage/index.rst +0 -0
  197. {cfinterface-1.9.1 → cfinterface-1.10.1}/docs/source/reference/tabular/files/tabularparser.rst +0 -0
  198. {cfinterface-1.9.1 → cfinterface-1.10.1}/docs/source/reference/tabular/files/tabularsection.rst +0 -0
  199. {cfinterface-1.9.1 → cfinterface-1.10.1}/docs/source/reference/tabular/index.rst +0 -0
  200. {cfinterface-1.9.1 → cfinterface-1.10.1}/docs/source/reference/versioning/files/versioning.rst +0 -0
  201. {cfinterface-1.9.1 → cfinterface-1.10.1}/docs/source/reference/versioning/index.rst +0 -0
  202. {cfinterface-1.9.1 → cfinterface-1.10.1}/examples/README.rst +0 -0
  203. {cfinterface-1.9.1 → cfinterface-1.10.1}/examples/__init__.py +0 -0
  204. {cfinterface-1.9.1 → cfinterface-1.10.1}/examples/plot_block_file.py +0 -0
  205. {cfinterface-1.9.1 → cfinterface-1.10.1}/examples/plot_register_file.py +0 -0
  206. {cfinterface-1.9.1 → cfinterface-1.10.1}/examples/plot_section_file.py +0 -0
  207. {cfinterface-1.9.1 → cfinterface-1.10.1}/examples/plot_tabular_parsing.py +0 -0
  208. {cfinterface-1.9.1 → cfinterface-1.10.1}/examples/plot_versioned_file.py +0 -0
  209. {cfinterface-1.9.1 → cfinterface-1.10.1}/pyproject.toml +0 -0
  210. {cfinterface-1.9.1 → cfinterface-1.10.1}/tests/__init__.py +0 -0
  211. {cfinterface-1.9.1 → cfinterface-1.10.1}/tests/_utils/__init__.py +0 -0
  212. {cfinterface-1.9.1 → cfinterface-1.10.1}/tests/_utils/test_is_null.py +0 -0
  213. {cfinterface-1.9.1 → cfinterface-1.10.1}/tests/adapters/__init__.py +0 -0
  214. {cfinterface-1.9.1 → cfinterface-1.10.1}/tests/adapters/components/__init__.py +0 -0
  215. {cfinterface-1.9.1 → cfinterface-1.10.1}/tests/adapters/components/test_blockrepository.py +0 -0
  216. {cfinterface-1.9.1 → cfinterface-1.10.1}/tests/adapters/components/test_factory.py +0 -0
  217. {cfinterface-1.9.1 → cfinterface-1.10.1}/tests/adapters/components/test_linerepository.py +0 -0
  218. {cfinterface-1.9.1 → cfinterface-1.10.1}/tests/adapters/components/test_pattern_cache.py +0 -0
  219. {cfinterface-1.9.1 → cfinterface-1.10.1}/tests/adapters/components/test_registerrepository.py +0 -0
  220. {cfinterface-1.9.1 → cfinterface-1.10.1}/tests/adapters/components/test_sectionrepository.py +0 -0
  221. {cfinterface-1.9.1 → cfinterface-1.10.1}/tests/adapters/reading/__init__.py +0 -0
  222. {cfinterface-1.9.1 → cfinterface-1.10.1}/tests/adapters/reading/test_readingrepository.py +0 -0
  223. {cfinterface-1.9.1 → cfinterface-1.10.1}/tests/adapters/writing/__init__.py +0 -0
  224. {cfinterface-1.9.1 → cfinterface-1.10.1}/tests/adapters/writing/test_writingrepository.py +0 -0
  225. {cfinterface-1.9.1 → cfinterface-1.10.1}/tests/components/__init__.py +0 -0
  226. {cfinterface-1.9.1 → cfinterface-1.10.1}/tests/components/conftest.py +0 -0
  227. {cfinterface-1.9.1 → cfinterface-1.10.1}/tests/components/test_block.py +0 -0
  228. {cfinterface-1.9.1 → cfinterface-1.10.1}/tests/components/test_datetimefield.py +0 -0
  229. {cfinterface-1.9.1 → cfinterface-1.10.1}/tests/components/test_defaultblock.py +0 -0
  230. {cfinterface-1.9.1 → cfinterface-1.10.1}/tests/components/test_defaultregister.py +0 -0
  231. {cfinterface-1.9.1 → cfinterface-1.10.1}/tests/components/test_defaultsection.py +0 -0
  232. {cfinterface-1.9.1 → cfinterface-1.10.1}/tests/components/test_field.py +0 -0
  233. {cfinterface-1.9.1 → cfinterface-1.10.1}/tests/components/test_field_hypothesis.py +0 -0
  234. {cfinterface-1.9.1 → cfinterface-1.10.1}/tests/components/test_floatfield_benchmark.py +0 -0
  235. {cfinterface-1.9.1 → cfinterface-1.10.1}/tests/components/test_integerfield.py +0 -0
  236. {cfinterface-1.9.1 → cfinterface-1.10.1}/tests/components/test_line.py +0 -0
  237. {cfinterface-1.9.1 → cfinterface-1.10.1}/tests/components/test_literalfield.py +0 -0
  238. {cfinterface-1.9.1 → cfinterface-1.10.1}/tests/components/test_register.py +0 -0
  239. {cfinterface-1.9.1 → cfinterface-1.10.1}/tests/components/test_section.py +0 -0
  240. {cfinterface-1.9.1 → cfinterface-1.10.1}/tests/components/test_storage_integration.py +0 -0
  241. {cfinterface-1.9.1 → cfinterface-1.10.1}/tests/components/test_tabular.py +0 -0
  242. {cfinterface-1.9.1 → cfinterface-1.10.1}/tests/components/test_tabular_hypothesis.py +0 -0
  243. {cfinterface-1.9.1 → cfinterface-1.10.1}/tests/conftest.py +0 -0
  244. {cfinterface-1.9.1 → cfinterface-1.10.1}/tests/data/__init__.py +0 -0
  245. {cfinterface-1.9.1 → cfinterface-1.10.1}/tests/data/test_blockdata.py +0 -0
  246. {cfinterface-1.9.1 → cfinterface-1.10.1}/tests/data/test_registerdata.py +0 -0
  247. {cfinterface-1.9.1 → cfinterface-1.10.1}/tests/data/test_sectiondata.py +0 -0
  248. {cfinterface-1.9.1 → cfinterface-1.10.1}/tests/files/__init__.py +0 -0
  249. {cfinterface-1.9.1 → cfinterface-1.10.1}/tests/files/test_blockfile.py +0 -0
  250. {cfinterface-1.9.1 → cfinterface-1.10.1}/tests/files/test_sectionfile.py +0 -0
  251. {cfinterface-1.9.1 → cfinterface-1.10.1}/tests/mocks/__init__.py +0 -0
  252. {cfinterface-1.9.1 → cfinterface-1.10.1}/tests/mocks/mock_open.py +0 -0
  253. {cfinterface-1.9.1 → cfinterface-1.10.1}/tests/reading/__init__.py +0 -0
  254. {cfinterface-1.9.1 → cfinterface-1.10.1}/tests/reading/test_blockreading.py +0 -0
  255. {cfinterface-1.9.1 → cfinterface-1.10.1}/tests/reading/test_registerreading.py +0 -0
  256. {cfinterface-1.9.1 → cfinterface-1.10.1}/tests/reading/test_sectionreading.py +0 -0
  257. {cfinterface-1.9.1 → cfinterface-1.10.1}/tests/test_storage.py +0 -0
  258. {cfinterface-1.9.1 → cfinterface-1.10.1}/tests/test_storage_deprecation.py +0 -0
  259. {cfinterface-1.9.1 → cfinterface-1.10.1}/tests/test_versioning.py +0 -0
  260. {cfinterface-1.9.1 → cfinterface-1.10.1}/tests/writing/__init__.py +0 -0
  261. {cfinterface-1.9.1 → cfinterface-1.10.1}/tests/writing/test_blockwriting.py +0 -0
  262. {cfinterface-1.9.1 → cfinterface-1.10.1}/tests/writing/test_registerwriting.py +0 -0
  263. {cfinterface-1.9.1 → cfinterface-1.10.1}/tests/writing/test_sectionwriting.py +0 -0
@@ -134,5 +134,8 @@ dmypy.json
134
134
 
135
135
  .vscode/
136
136
 
137
+ # Implementation plans
138
+ plans/
139
+
137
140
  # Build system
138
141
  uv.lock
@@ -7,6 +7,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [1.10.1] - 2026-04-13
11
+
12
+ ### Fixed
13
+
14
+ - Resolve mypy `arg-type` error in `FloatField._apply_compact` by passing the numeric value as a parameter instead of accessing `self._value` directly
15
+
16
+ ## [1.10.0] - 2026-04-13
17
+
18
+ ### Added
19
+
20
+ - `compact` parameter on `FloatField` (`compact=False` by default) that omits the leading zero for values where `0 < |value| < 1`, matching Fortran fixed-width file conventions and preserving precision in narrow fields
21
+
22
+ ### Fixed
23
+
24
+ - `RegisterReading.read()` now resets its internal data before each call, preventing register duplication when `RegisterFile.read()` retries with fallback encodings after a mid-file `UnicodeDecodeError`
25
+
10
26
  ## [1.9.1] - 2026-03-08
11
27
 
12
28
  ### Fixed
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cfinterface
3
- Version: 1.9.1
3
+ Version: 1.10.1
4
4
  Summary: Interface for handling custom formatted files
5
5
  Project-URL: Documentation, https://rjmalves.github.io/cfinterface/
6
6
  Project-URL: Repository, https://github.com/rjmalves/cfinterface/
@@ -6,7 +6,7 @@ cfi is a Python module for handling custom formatted files
6
6
  and provide reading, storing and writing utilities.
7
7
  """
8
8
 
9
- __version__ = "1.9.1"
9
+ __version__ = "1.10.1"
10
10
 
11
11
  from . import components # noqa
12
12
  from . import data # noqa
@@ -13,7 +13,7 @@ class FloatField(Field):
13
13
  by 'F' for fixed point notation and 'E' or 'D' for scientific notation.
14
14
  """
15
15
 
16
- __slots__ = ["__decimal_digits", "__format", "__sep", "__type"]
16
+ __slots__ = ["__compact", "__decimal_digits", "__format", "__sep", "__type"]
17
17
 
18
18
  TYPES = {
19
19
  2: np.float16,
@@ -29,12 +29,14 @@ class FloatField(Field):
29
29
  format: str = "F",
30
30
  sep: str = ".",
31
31
  value: float | None = None,
32
+ compact: bool = False,
32
33
  ) -> None:
33
34
  super().__init__(
34
35
  size,
35
36
  starting_position,
36
37
  value,
37
38
  )
39
+ self.__compact = compact
38
40
  self.__decimal_digits = decimal_digits
39
41
  self.__format = format
40
42
  self.__sep = sep
@@ -63,6 +65,14 @@ class FloatField(Field):
63
65
  else:
64
66
  return np.array([self._value], dtype=self.__type).tobytes()
65
67
 
68
+ def _apply_compact(self, value: str, numeric: float) -> str:
69
+ if self.__compact and 0 < abs(numeric) < 1:
70
+ if value.startswith("0."):
71
+ return value[1:]
72
+ if value.startswith("-0."):
73
+ return "-" + value[2:]
74
+ return value
75
+
66
76
  def _textual_write(self) -> str:
67
77
  value = ""
68
78
  if self.value is not None and not _is_null(self.value):
@@ -97,6 +107,7 @@ class FloatField(Field):
97
107
  d=self.__decimal_digits,
98
108
  format=formatting_format,
99
109
  ).replace("E", self.__format)
110
+ value = self._apply_compact(value, self.value)
100
111
  if len(value) > self._size:
101
112
  excess = len(value) - self._size
102
113
  new_d = self.__decimal_digits - excess
@@ -107,6 +118,7 @@ class FloatField(Field):
107
118
  d=new_d,
108
119
  format=formatting_format,
109
120
  ).replace("E", self.__format)
121
+ value = self._apply_compact(value, self.value)
110
122
  if len(value) > self._size:
111
123
  new_d = max(0, new_d - 1)
112
124
  value = "{:.{d}{format}}".format(
@@ -114,6 +126,7 @@ class FloatField(Field):
114
126
  d=new_d,
115
127
  format=formatting_format,
116
128
  ).replace("E", self.__format)
129
+ value = self._apply_compact(value, self.value)
117
130
  return value.rjust(self.size)
118
131
 
119
132
  @property
@@ -82,6 +82,7 @@ class RegisterReading:
82
82
  :return: The data from the registers found in the file
83
83
  :rtype: RegisterData
84
84
  """
85
+ self.__data = RegisterData(DefaultRegister(data=""))
85
86
  self.__repository = factory(self.__storage)(
86
87
  content, not isfile(content), encoding
87
88
  )
@@ -196,3 +196,108 @@ def test_floatfield_write_fuzz_equivalence():
196
196
  f"Mismatch: fmt={fmt} size={size} dec={dec} val={val} "
197
197
  f"got={result!r} expected={expected!r}"
198
198
  )
199
+
200
+
201
+ def test_floatfield_compact_positive_small():
202
+ f = FloatField(5, 0, 4, format="F", value=0.0563, compact=True)
203
+ assert f._textual_write() == ".0563"
204
+
205
+
206
+ def test_floatfield_compact_negative_small():
207
+ f = FloatField(6, 0, 4, format="F", value=-0.0563, compact=True)
208
+ assert f._textual_write() == "-.0563"
209
+
210
+
211
+ def test_floatfield_compact_no_effect_above_one():
212
+ f = FloatField(5, 0, 2, format="F", value=1.50, compact=True)
213
+ assert f._textual_write() == " 1.50"
214
+
215
+
216
+ def test_floatfield_compact_no_effect_zero():
217
+ f = FloatField(6, 0, 3, format="F", value=0.0, compact=True)
218
+ assert f._textual_write() == " 0.000"
219
+
220
+
221
+ def test_floatfield_compact_default_false():
222
+ f = FloatField(5, 0, 3, format="F", value=0.0563)
223
+ assert f._textual_write() == "0.056"
224
+
225
+
226
+ def test_floatfield_compact_preserves_precision():
227
+ """Concrete example from issue: size=5, decimal_digits=4.
228
+
229
+ Without compact: "0.0563" (6 chars) overflows → reduced to "0.056" (0.53% error).
230
+ With compact: ".0563" fits in 5 chars → no precision loss.
231
+ """
232
+ f_default = FloatField(5, 0, 4, format="F", value=0.0563)
233
+ f_compact = FloatField(5, 0, 4, format="F", value=0.0563, compact=True)
234
+ assert f_default._textual_write() == "0.056"
235
+ assert f_compact._textual_write() == ".0563"
236
+
237
+
238
+ def test_floatfield_compact_read_roundtrip():
239
+ """Reading a compact-formatted value works because float('.0563') parses."""
240
+ f_write = FloatField(5, 0, 4, format="F", value=0.0563, compact=True)
241
+ written = f_write._textual_write()
242
+ assert written == ".0563"
243
+ line = written + "-rest"
244
+ f_read = FloatField(5, 0, 4, format="F")
245
+ f_read.read(line)
246
+ assert f_read.value == 0.0563
247
+
248
+
249
+ def test_floatfield_compact_negative_read_roundtrip():
250
+ f_write = FloatField(6, 0, 4, format="F", value=-0.0563, compact=True)
251
+ written = f_write._textual_write()
252
+ assert written == "-.0563"
253
+ line = written + "-rest"
254
+ f_read = FloatField(6, 0, 4, format="F")
255
+ f_read.read(line)
256
+ assert f_read.value == -0.0563
257
+
258
+
259
+ def test_floatfield_compact_no_effect_negative_zero():
260
+ f = FloatField(8, 0, 4, format="F", value=-0.0, compact=True)
261
+ assert f._textual_write() == " -0.0000"
262
+
263
+
264
+ def test_floatfield_compact_overflow_still_reduces():
265
+ """When compact alone doesn't prevent overflow, precision is still reduced."""
266
+ f = FloatField(4, 0, 4, format="F", value=0.0563, compact=True)
267
+ result = f._textual_write()
268
+ assert len(result) == 4
269
+ assert result == ".056"
270
+
271
+
272
+ def test_floatfield_compact_fuzz_properties():
273
+ """Fuzz: compact output fits field, parses correctly, is at least as precise."""
274
+ import random
275
+
276
+ random.seed(99)
277
+ for _ in range(50000):
278
+ size = random.randint(3, 20)
279
+ dec = random.randint(0, min(10, size - 1))
280
+ val = random.uniform(-0.999, 0.999)
281
+ if abs(val) < 1e-15:
282
+ continue
283
+ f_default = FloatField(size, 0, dec, format="F", value=val)
284
+ f_compact = FloatField(
285
+ size, 0, dec, format="F", value=val, compact=True
286
+ )
287
+ default_result = f_default._textual_write()
288
+ compact_result = f_compact._textual_write()
289
+ assert len(compact_result) == size, (
290
+ f"Wrong length: size={size} dec={dec} val={val} "
291
+ f"compact={compact_result!r} len={len(compact_result)}"
292
+ )
293
+ default_float = (
294
+ float(default_result.strip()) if default_result.strip() else 0.0
295
+ )
296
+ compact_float = (
297
+ float(compact_result.strip()) if compact_result.strip() else 0.0
298
+ )
299
+ # Compact must be at least as precise as default
300
+ assert abs(compact_float - val) <= abs(default_float - val) + 1e-15, (
301
+ f"Precision loss: size={size} dec={dec} val={val} "
302
+ f"default={default_result!r} compact={compact_result!r}"
303
+ )
@@ -1,3 +1,5 @@
1
+ import os
2
+ import tempfile
1
3
  import warnings
2
4
  from io import StringIO
3
5
  from unittest.mock import MagicMock, patch
@@ -10,6 +12,8 @@ from cfinterface.components.literalfield import LiteralField
10
12
  from cfinterface.components.register import Register
11
13
  from cfinterface.data.registerdata import RegisterData
12
14
  from cfinterface.files.registerfile import RegisterFile
15
+ from cfinterface.reading.registerreading import RegisterReading
16
+ from cfinterface.storage import StorageType
13
17
  from tests.mocks.mock_open import mock_open
14
18
 
15
19
 
@@ -259,3 +263,41 @@ def test_registerfile_validate_unknown_version():
259
263
  f = VersionedRegisterFile.read(filedata)
260
264
  result = f.validate(version="v0")
261
265
  assert result.matched is False
266
+
267
+
268
+ def test_registerreading_data_reset_between_reads():
269
+ """Verify that RegisterReading.__data is reset on each read() call."""
270
+ data = "Hello, world!"
271
+ filedata = DummyRegister.IDENTIFIER + " " + data + "\n"
272
+ reader = RegisterReading([DummyRegister], StorageType.TEXT)
273
+ result1 = reader.read(filedata, "utf-8")
274
+ assert len(result1) == 2 # root DefaultRegister + 1 DummyRegister
275
+ result2 = reader.read(filedata, "utf-8")
276
+ assert len(result2) == 2 # must be 2 again, not 4
277
+
278
+
279
+ def test_registerfile_read_encoding_fallback_no_duplication():
280
+ """Verify no data duplication when first encoding fails mid-file.
281
+
282
+ A Latin-1 file with a non-UTF-8 byte causes UTF-8 decoding to fail
283
+ partway through. The fallback to Latin-1 must not carry over partially
284
+ read data from the failed UTF-8 attempt.
285
+ """
286
+ line1 = DummyRegister.IDENTIFIER + " " + "Hello, world!" + "\n"
287
+ line2 = DummyRegister.IDENTIFIER + " " + "with acc\u00eant! " + "\n"
288
+
289
+ class FallbackFile(RegisterFile):
290
+ REGISTERS = [DummyRegister]
291
+ ENCODING = ["utf-8", "latin-1"]
292
+
293
+ with tempfile.NamedTemporaryFile(
294
+ mode="wb", suffix=".txt", delete=False
295
+ ) as f:
296
+ f.write((line1 + line2).encode("latin-1"))
297
+ tmppath = f.name
298
+ try:
299
+ result = FallbackFile.read(tmppath)
300
+ # root DefaultRegister + 2 DummyRegisters = 3
301
+ assert len(result.data) == 3
302
+ finally:
303
+ os.unlink(tmppath)
@@ -1,172 +0,0 @@
1
- {
2
- "plan": "cfinterface-architecture-improvement",
3
- "last_updated": "2026-02-23T23:30:00.000000+00:00",
4
- "progressive": true,
5
- "tickets": {
6
- "ticket-001-create-null-checking-utility.md": {
7
- "status": "completed",
8
- "detail_level": "detailed",
9
- "agent": "python-task-automation-developer"
10
- },
11
- "ticket-002-replace-pd-isnull-in-fields.md": {
12
- "status": "completed",
13
- "detail_level": "detailed",
14
- "agent": "python-task-automation-developer"
15
- },
16
- "ticket-003-lazy-pandas-import-in-registerfile.md": {
17
- "status": "completed",
18
- "detail_level": "detailed",
19
- "agent": "python-task-automation-developer"
20
- },
21
- "ticket-004-move-pandas-to-optional-dependency.md": {
22
- "status": "completed",
23
- "detail_level": "detailed",
24
- "agent": "python-task-automation-developer"
25
- },
26
- "ticket-005-compile-regex-patterns.md": {
27
- "status": "completed",
28
- "detail_level": "detailed",
29
- "agent": "python-task-automation-developer"
30
- },
31
- "ticket-006-create-storagetype-enum.md": {
32
- "status": "completed",
33
- "detail_level": "detailed",
34
- "agent": "python-task-automation-developer"
35
- },
36
- "ticket-007-update-factory-functions.md": {
37
- "status": "completed",
38
- "detail_level": "detailed",
39
- "agent": "python-task-automation-developer"
40
- },
41
- "ticket-008-migrate-internal-storage-usage.md": {
42
- "status": "completed",
43
- "detail_level": "detailed",
44
- "agent": "python-task-automation-developer"
45
- },
46
- "ticket-009-add-deprecation-warnings.md": {
47
- "status": "completed",
48
- "detail_level": "detailed",
49
- "agent": "python-task-automation-developer"
50
- },
51
- "ticket-010-optimize-floatfield-write.md": {
52
- "status": "completed",
53
- "detail_level": "refined",
54
- "agent": "python-task-automation-developer"
55
- },
56
- "ticket-011-add-floatfield-benchmarks.md": {
57
- "status": "completed",
58
- "detail_level": "refined",
59
- "agent": "python-task-automation-developer"
60
- },
61
- "ticket-012-list-backed-registerdata.md": {
62
- "status": "completed",
63
- "detail_level": "refined",
64
- "agent": "python-task-automation-developer"
65
- },
66
- "ticket-013-list-backed-blockdata.md": {
67
- "status": "completed",
68
- "detail_level": "refined",
69
- "agent": "python-task-automation-developer"
70
- },
71
- "ticket-014-list-backed-sectiondata.md": {
72
- "status": "completed",
73
- "detail_level": "refined",
74
- "agent": "python-task-automation-developer"
75
- },
76
- "ticket-015-computed-prev-next-properties.md": {
77
- "status": "completed",
78
- "detail_level": "refined",
79
- "agent": "python-task-automation-developer"
80
- },
81
- "ticket-016-type-indexed-lookup.md": {
82
- "status": "completed",
83
- "detail_level": "refined",
84
- "agent": "python-task-automation-developer"
85
- },
86
- "ticket-017-typed-field-protocol.md": {
87
- "status": "completed",
88
- "detail_level": "refined",
89
- "agent": "python-task-automation-developer"
90
- },
91
- "ticket-018-typed-repository-signatures.md": {
92
- "status": "completed",
93
- "detail_level": "refined",
94
- "agent": "python-task-automation-developer"
95
- },
96
- "ticket-019-typed-line-dispatch.md": {
97
- "status": "completed",
98
- "detail_level": "refined",
99
- "agent": "python-task-automation-developer"
100
- },
101
- "ticket-020-typed-component-io.md": {
102
- "status": "completed",
103
- "detail_level": "refined",
104
- "agent": "python-task-automation-developer"
105
- },
106
- "ticket-021-tabular-parser-engine.md": {
107
- "status": "completed",
108
- "detail_level": "refined",
109
- "agent": "python-task-automation-developer"
110
- },
111
- "ticket-022-tabular-section-base.md": {
112
- "status": "completed",
113
- "detail_level": "refined",
114
- "agent": "python-task-automation-developer"
115
- },
116
- "ticket-023-delimited-tabular-parsing.md": {
117
- "status": "completed",
118
- "detail_level": "refined",
119
- "agent": "python-task-automation-developer"
120
- },
121
- "ticket-024-schema-version-descriptor.md": {
122
- "status": "completed",
123
- "detail_level": "refined",
124
- "agent": "python-task-automation-developer"
125
- },
126
- "ticket-025-instance-level-version-binding.md": {
127
- "status": "completed",
128
- "detail_level": "refined",
129
- "agent": "python-task-automation-developer"
130
- },
131
- "ticket-026-batch-read-api.md": {
132
- "status": "completed",
133
- "detail_level": "refined",
134
- "agent": "python-task-automation-developer"
135
- },
136
- "ticket-027-version-validation.md": {
137
- "status": "completed",
138
- "detail_level": "refined",
139
- "agent": "python-task-automation-developer"
140
- }
141
- },
142
- "epics": {
143
- "epic-01-remove-pandas-dependency": {
144
- "phase": "completed",
145
- "learning_extracted": true
146
- },
147
- "epic-02-compile-regex-and-storage-enum": {
148
- "phase": "completed",
149
- "learning_extracted": true
150
- },
151
- "epic-03-optimize-float-field-write": {
152
- "phase": "completed",
153
- "learning_extracted": true
154
- },
155
- "epic-04-array-backed-data-containers": {
156
- "phase": "completed",
157
- "learning_extracted": true
158
- },
159
- "epic-05-type-safe-text-binary-dispatch": {
160
- "phase": "completed",
161
- "learning_extracted": true
162
- },
163
- "epic-06-generic-tabular-parser": {
164
- "phase": "completed",
165
- "learning_extracted": true
166
- },
167
- "epic-07-schema-versioning-and-batch-ops": {
168
- "phase": "completed",
169
- "learning_extracted": true
170
- }
171
- }
172
- }
@@ -1,143 +0,0 @@
1
- # Master Plan: cfinterface Architecture and Performance Improvement
2
-
3
- ## Executive Summary
4
-
5
- This plan addresses architectural debt and performance bottlenecks in cfinterface, a Python file schema modeling framework used to parse/write dozens of legacy HPC file formats. The improvements are ordered by impact and risk: foundational dependency removal and performance wins first (pandas removal, regex compilation, storage enum), followed by structural improvements (data containers, type-safe dispatch), and finally consumer-facing features (generic tabular parser, schema versioning). All changes maintain backward compatibility with 254+ downstream file type implementations in inewave and sintetizador-newave.
6
-
7
- ## Goals & Non-Goals
8
-
9
- ### Goals
10
-
11
- 1. Remove the unnecessary pandas runtime dependency from cfinterface core (pandas is only used for `pd.isnull()`)
12
- 2. Pre-compile and cache regex patterns used for identifier/block pattern matching
13
- 3. Replace magic string `"TEXT"`/`"BINARY"` storage parameters with a type-safe enum
14
- 4. Optimize `FloatField._textual_write()` to eliminate the O(decimal_digits) precision loop
15
- 5. Replace linked list data containers with array-backed containers for O(1) `len()` and indexed access
16
- 6. Introduce type-safe text/binary dispatch eliminating `Union[str, bytes]` threading
17
- 7. Provide a generic tabular parser to reduce per-file custom DataFrame parsing in consumers
18
- 8. Add schema versioning support and batch operations API
19
-
20
- ### Non-Goals
21
-
22
- - Modifying inewave or sintetizador-newave directly (cfinterface remains independent)
23
- - Breaking backward compatibility without a migration path
24
- - Adding streaming/chunked read support (deferred to future work after array-backed containers)
25
- - Property accessor generation for consumer wrappers (separate future initiative)
26
- - Typed `Section.data` generic parameter (separate future initiative, depends on Python version constraints)
27
-
28
- ## Architecture Overview
29
-
30
- ### Current State
31
-
32
- ```
33
- cfinterface v1.8.3
34
- Field (base) --> FloatField, IntegerField, LiteralField, DatetimeField
35
- - All import pandas for pd.isnull() null detection
36
- - FloatField has O(n) textual write loop
37
- Line --> composed of Fields
38
- - Takes storage: str = "" parameter
39
- Register/Block/Section --> contain linked-list prev/next pointers
40
- - re.search() called per line without pre-compilation
41
- - "TEXT"/"BINARY" magic strings threaded through all APIs
42
- RegisterData/BlockData/SectionData --> linked list containers
43
- - O(n) __len__(), O(n) type filtering, no indexing
44
- RegisterFile/BlockFile/SectionFile --> high-level APIs
45
- - RegisterFile imports pandas for _as_df() helper
46
- adapters/ --> Repository pattern with factory("TEXT"/"BINARY") dispatch
47
- ```
48
-
49
- ### Target State
50
-
51
- ```
52
- cfinterface v2.0.0
53
- Field (base) --> FloatField, IntegerField, LiteralField, DatetimeField
54
- - Native _is_null() helper using math.isnan/numpy, zero pandas dependency
55
- - FloatField uses direct format string, no precision loop
56
- StorageType enum --> TEXT, BINARY (replaces magic strings)
57
- Line --> composed of Fields, uses StorageType
58
- Register/Block/Section --> contain index into parent container (no linked-list pointers)
59
- - Compiled regex patterns cached at class level
60
- RegisterData/BlockData/SectionData --> list-backed containers
61
- - O(1) len(), indexed access, type-indexed lookups
62
- RegisterFile/BlockFile/SectionFile --> high-level APIs
63
- - pandas import deferred to _as_df() method only (optional dependency)
64
- - GenericTabularParser mixin for DataFrame construction
65
- - Schema versioning with explicit contracts
66
- adapters/ --> Repository pattern with StorageType enum dispatch
67
- ```
68
-
69
- ### Key Design Decisions
70
-
71
- 1. **pandas becomes optional**: Move pandas to optional dependency. Use `math.isnan()` + type checking for null detection in fields. The `_as_df()` method in RegisterFile keeps pandas but imports lazily.
72
- 2. **StorageType enum is additive**: The enum is introduced alongside the existing string API. Factory functions accept both `str` and `StorageType` during migration. The string API is deprecated but not removed.
73
- 3. **Array-backed containers preserve API**: `RegisterData`, `BlockData`, `SectionData` switch from linked lists to `list` internally. The `previous`/`next` properties on Register/Block/Section become computed from the parent container rather than stored pointers. The public API (`append`, `preppend`, `of_type`, `get_*_of_type`) is preserved.
74
- 4. **Regex compilation is transparent**: Patterns are compiled lazily at first use and cached as class attributes. No API change required.
75
-
76
- ## Technical Approach
77
-
78
- ### Tech Stack
79
-
80
- - Python >=3.10, numpy >=2.0.0
81
- - pandas >=2.2.3 (moved to optional dependency)
82
- - pytest, ruff, mypy (dev)
83
-
84
- ### Component/Module Breakdown
85
-
86
- | Epic | Component | Files Modified | Risk |
87
- | ---- | ----------------------------------------------------------- | -------------- | ------ |
88
- | 1 | Field subclasses, pyproject.toml | 6 files | Low |
89
- | 2 | adapters/components/repository.py, all storage string sites | 15 files | Low |
90
- | 3 | FloatField.\_textual_write() | 1 file | Low |
91
- | 4 | data/\*.py, Register/Block/Section prev/next | 9 files | Medium |
92
- | 5 | adapters/_, components/_, type annotations | 15 files | Medium |
93
- | 6 | New module: cfinterface/parsers/ | 3-5 new files | Medium |
94
- | 7 | files/\*.py, new module: cfinterface/versioning/ | 5-8 files | Medium |
95
-
96
- ### Data Flow
97
-
98
- ```
99
- File on disk
100
- --> ReadingRepository (opens file, manages IO)
101
- --> Reading class (dispatches lines to Register/Block/Section)
102
- --> Component.read(file, storage) (reads fields from line)
103
- --> Field.read(line) (extracts typed value from line slice)
104
- --> Data container stores components
105
- --> File class exposes data to consumer
106
- ```
107
-
108
- ### Testing Strategy
109
-
110
- - Every ticket includes unit tests for the specific change
111
- - Regression tests: run full existing test suite after each ticket
112
- - Performance benchmarks: add pytest-benchmark fixtures for regex matching, field write, data container operations
113
- - Integration validation: verify inewave test suite still passes (manual step at epic boundaries)
114
-
115
- ## Phases & Milestones
116
-
117
- | Phase | Epic | Duration | Milestone |
118
- | ----- | ---------------------------------------- | --------- | -------------------------------------------------------------------------------- |
119
- | 1 | Epic 1: Remove pandas dependency | 1 week | pandas is optional, all field tests pass without pandas installed |
120
- | 1 | Epic 2: Compile regex + StorageType enum | 1-2 weeks | All re.search() calls use compiled patterns, StorageType enum in place |
121
- | 2 | Epic 3: Optimize FloatField write | 3-5 days | FloatField.\_textual_write() uses direct formatting, benchmarks show improvement |
122
- | 2 | Epic 4: Array-backed data containers | 2-3 weeks | LinkedList replaced with list, O(1) len(), existing API preserved |
123
- | 3 | Epic 5: Type-safe text/binary dispatch | 2-3 weeks | Union[str, bytes] eliminated from core APIs, adapters use StorageType |
124
- | 4 | Epic 6: Generic tabular parser | 2-3 weeks | Reusable tabular parsing for consumers, reduces boilerplate |
125
- | 4 | Epic 7: Schema versioning + batch ops | 2-3 weeks | Version contracts, bulk read API |
126
-
127
- ## Risk Analysis
128
-
129
- | Risk | Impact | Mitigation |
130
- | --------------------------------------------------------- | ------ | --------------------------------------------------------------------------------------------------------- |
131
- | Breaking 254+ downstream file types | High | Backward-compatible changes only; deprecation before removal; string API preserved alongside enum |
132
- | pandas removal breaks consumers that pass NaN values | Medium | The \_is_null() function handles numpy NaN, float NaN, and None; comprehensive test coverage |
133
- | Linked list to array migration changes iteration behavior | Medium | Preserve exact API surface; comprehensive tests for edge cases (concurrent modification during iteration) |
134
- | Regex compilation overhead at import time | Low | Lazy compilation on first use, not at class definition time |
135
-
136
- ## Success Metrics
137
-
138
- 1. `pytest` passes with 100% of existing tests after each epic
139
- 2. pandas is no longer in `dependencies` (moved to `[project.optional-dependencies]`)
140
- 3. No `re.search()` calls with raw string patterns remain
141
- 4. `len(RegisterData)` is O(1) instead of O(n)
142
- 5. FloatField write benchmark shows measurable improvement
143
- 6. All `"TEXT"`/`"BINARY"` string literals replaced with `StorageType.TEXT`/`StorageType.BINARY`
@@ -1,55 +0,0 @@
1
- # cfinterface Architecture and Performance Improvement
2
-
3
- ## Overview
4
-
5
- Comprehensive architectural and performance improvement for the cfinterface Python package -- a file schema modeling framework used to parse/write dozens of legacy HPC file formats. Changes are ordered by impact and risk, starting with foundational improvements and progressing to consumer-facing features.
6
-
7
- ## Tech Stack
8
-
9
- - Python >=3.10, numpy >=2.0.0
10
- - pandas >=2.2.3 (moved to optional dependency in Epic 01)
11
- - pytest, ruff, mypy (dev tools)
12
-
13
- ## Epics
14
-
15
- | Epic | Name | Tickets | Detail Level | Phase |
16
- | ---- | -------------------------------- | ------- | ------------ | --------- |
17
- | 01 | Remove pandas dependency | 4 | Detailed | Completed |
18
- | 02 | Compile regex + StorageType enum | 5 | Detailed | Completed |
19
- | 03 | Optimize FloatField write | 2 | Refined | Completed |
20
- | 04 | Array-backed data containers | 5 | Refined | Completed |
21
- | 05 | Type-safe text/binary dispatch | 4 | Refined | Completed |
22
- | 06 | Generic tabular parser | 3 | Refined | Completed |
23
- | 07 | Schema versioning + batch ops | 4 | Refined | Completed |
24
-
25
- ## Progress
26
-
27
- | Ticket | Title | Epic | Status | Detail Level |
28
- | ---------- | --------------------------------------------------------------- | ------- | --------- | ------------ |
29
- | ticket-001 | Create native null-checking utility function | epic-01 | completed | Detailed |
30
- | ticket-002 | Replace pd.isnull() in all Field subclasses | epic-01 | completed | Detailed |
31
- | ticket-003 | Convert RegisterFile.\_as_df() to lazy pandas import | epic-01 | completed | Detailed |
32
- | ticket-004 | Move pandas to optional dependency in pyproject.toml | epic-01 | completed | Detailed |
33
- | ticket-005 | Add regex pattern compilation and caching | epic-02 | completed | Detailed |
34
- | ticket-006 | Create StorageType enum module | epic-02 | completed | Detailed |
35
- | ticket-007 | Update all factory functions to accept StorageType | epic-02 | completed | Detailed |
36
- | ticket-008 | Migrate internal storage parameter usage to StorageType | epic-02 | completed | Detailed |
37
- | ticket-009 | Add deprecation warnings for string-based storage | epic-02 | completed | Detailed |
38
- | ticket-010 | Optimize FloatField fixed-point textual write | epic-03 | completed | Refined |
39
- | ticket-011 | Add FloatField write benchmark tests | epic-03 | completed | Refined |
40
- | ticket-012 | Implement list-backed RegisterData container | epic-04 | completed | Refined |
41
- | ticket-013 | Implement list-backed BlockData container | epic-04 | completed | Refined |
42
- | ticket-014 | Implement list-backed SectionData container | epic-04 | completed | Refined |
43
- | ticket-015 | Migrate Register/Block/Section prev/next to computed properties | epic-04 | completed | Refined |
44
- | ticket-016 | Add type-indexed lookup optimization | epic-04 | completed | Refined |
45
- | ticket-017 | Design typed Field read/write protocol | epic-05 | completed | Refined |
46
- | ticket-018 | Separate TextualRepository and BinaryRepository type signatures | epic-05 | completed | Refined |
47
- | ticket-019 | Update Line class for typed dispatch | epic-05 | completed | Refined |
48
- | ticket-020 | Update Register/Block/Section for typed IO paths | epic-05 | completed | Refined |
49
- | ticket-021 | Implement TabularParser core engine | epic-06 | completed | Refined |
50
- | ticket-022 | Create TabularSection convenience base class | epic-06 | completed | Refined |
51
- | ticket-023 | Add delimited tabular parsing support | epic-06 | completed | Refined |
52
- | ticket-024 | Design SchemaVersion descriptor and version resolution utility | epic-07 | completed | Refined |
53
- | ticket-025 | Implement instance-level version binding for file classes | epic-07 | completed | Refined |
54
- | ticket-026 | Add batch read_many() API to file classes | epic-07 | completed | Refined |
55
- | ticket-027 | Add version validation and mismatch detection | epic-07 | completed | Refined |