cfinterface 1.9.0__tar.gz → 1.9.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.
- {cfinterface-1.9.0 → cfinterface-1.9.1}/CHANGELOG.md +9 -1
- cfinterface-1.9.1/CONTRIBUTING.md +36 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/PKG-INFO +1 -1
- {cfinterface-1.9.0 → cfinterface-1.9.1}/cfinterface/__init__.py +1 -1
- {cfinterface-1.9.0 → cfinterface-1.9.1}/docs/source/conf.py +1 -1
- cfinterface-1.9.1/docs/source/getting_started/contributing.rst +103 -0
- cfinterface-1.9.1/docs/source/guides/architecture.rst +454 -0
- cfinterface-1.9.1/docs/source/guides/faq.rst +274 -0
- cfinterface-1.9.1/docs/source/guides/migration-v1.9.rst +281 -0
- cfinterface-1.9.1/docs/source/guides/performance.rst +212 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/docs/source/index.rst +11 -11
- cfinterface-1.9.1/examples/plot_block_file.py +201 -0
- cfinterface-1.9.1/examples/plot_section_file.py +201 -0
- cfinterface-1.9.0/CONTRIBUTING.md +0 -37
- cfinterface-1.9.0/docs/source/getting_started/contributing.rst +0 -104
- cfinterface-1.9.0/docs/source/guides/architecture.rst +0 -455
- cfinterface-1.9.0/docs/source/guides/faq.rst +0 -278
- cfinterface-1.9.0/docs/source/guides/migration-v1.9.rst +0 -283
- cfinterface-1.9.0/docs/source/guides/performance.rst +0 -217
- cfinterface-1.9.0/examples/plot_block_file.py +0 -201
- cfinterface-1.9.0/examples/plot_section_file.py +0 -201
- {cfinterface-1.9.0 → cfinterface-1.9.1}/.github/workflows/benchmark.yml +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/.github/workflows/docs.yml +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/.github/workflows/main.yml +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/.github/workflows/publish.yml +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/.gitignore +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/.pre-commit-config.yaml +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/LICENSE +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/README.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/benchmarks/__init__.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/benchmarks/bench_floatfield_write.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/cfinterface/_utils/__init__.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/cfinterface/adapters/__init__.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/cfinterface/adapters/components/__init__.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/cfinterface/adapters/components/line/__init__.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/cfinterface/adapters/components/line/repository.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/cfinterface/adapters/components/repository.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/cfinterface/adapters/reading/__init__.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/cfinterface/adapters/reading/repository.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/cfinterface/adapters/writing/__init__.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/cfinterface/adapters/writing/repository.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/cfinterface/components/__init__.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/cfinterface/components/block.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/cfinterface/components/datetimefield.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/cfinterface/components/defaultblock.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/cfinterface/components/defaultregister.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/cfinterface/components/defaultsection.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/cfinterface/components/field.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/cfinterface/components/floatfield.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/cfinterface/components/integerfield.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/cfinterface/components/line.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/cfinterface/components/literalfield.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/cfinterface/components/register.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/cfinterface/components/section.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/cfinterface/components/tabular.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/cfinterface/data/__init__.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/cfinterface/data/blockdata.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/cfinterface/data/registerdata.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/cfinterface/data/sectiondata.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/cfinterface/files/__init__.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/cfinterface/files/blockfile.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/cfinterface/files/registerfile.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/cfinterface/files/sectionfile.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/cfinterface/py.typed +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/cfinterface/reading/__init__.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/cfinterface/reading/blockreading.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/cfinterface/reading/registerreading.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/cfinterface/reading/sectionreading.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/cfinterface/storage.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/cfinterface/versioning.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/cfinterface/writing/__init__.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/cfinterface/writing/blockwriting.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/cfinterface/writing/registerwriting.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/cfinterface/writing/sectionwriting.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/docs/source/_static/logo_cfinterface.svg +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/docs/source/getting_started/tutorial.rst +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/docs/source/install/install.rst +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/docs/source/reference/adapters/files/components.rst +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/docs/source/reference/adapters/files/line.rst +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/docs/source/reference/adapters/files/reading.rst +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/docs/source/reference/adapters/files/writing.rst +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/docs/source/reference/adapters/index.rst +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/docs/source/reference/blocks/files/block.rst +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/docs/source/reference/blocks/files/blockdata.rst +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/docs/source/reference/blocks/files/blockfile.rst +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/docs/source/reference/blocks/index.rst +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/docs/source/reference/fields/components/datetimefield.rst +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/docs/source/reference/fields/components/field.rst +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/docs/source/reference/fields/components/floatfield.rst +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/docs/source/reference/fields/components/integerfield.rst +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/docs/source/reference/fields/components/literalfield.rst +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/docs/source/reference/fields/index.rst +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/docs/source/reference/line/index.rst +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/docs/source/reference/registers/files/register.rst +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/docs/source/reference/registers/files/registerdata.rst +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/docs/source/reference/registers/files/registerfile.rst +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/docs/source/reference/registers/index.rst +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/docs/source/reference/sections/files/section.rst +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/docs/source/reference/sections/files/sectiondata.rst +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/docs/source/reference/sections/files/sectionfile.rst +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/docs/source/reference/sections/index.rst +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/docs/source/reference/storage/files/storagetype.rst +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/docs/source/reference/storage/index.rst +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/docs/source/reference/tabular/files/tabularparser.rst +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/docs/source/reference/tabular/files/tabularsection.rst +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/docs/source/reference/tabular/index.rst +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/docs/source/reference/versioning/files/versioning.rst +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/docs/source/reference/versioning/index.rst +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/examples/README.rst +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/examples/__init__.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/examples/plot_register_file.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/examples/plot_tabular_parsing.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/examples/plot_versioned_file.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/cfinterface-architecture-improvement/.implementation-state.json +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/cfinterface-architecture-improvement/00-master-plan.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/cfinterface-architecture-improvement/README.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/cfinterface-architecture-improvement/epic-01-remove-pandas-dependency/00-epic-overview.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/cfinterface-architecture-improvement/epic-01-remove-pandas-dependency/learnings.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/cfinterface-architecture-improvement/epic-01-remove-pandas-dependency/ticket-001-create-null-checking-utility.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/cfinterface-architecture-improvement/epic-01-remove-pandas-dependency/ticket-002-replace-pd-isnull-in-fields.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/cfinterface-architecture-improvement/epic-01-remove-pandas-dependency/ticket-003-lazy-pandas-import-in-registerfile.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/cfinterface-architecture-improvement/epic-01-remove-pandas-dependency/ticket-004-move-pandas-to-optional-dependency.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/cfinterface-architecture-improvement/epic-02-compile-regex-and-storage-enum/00-epic-overview.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/cfinterface-architecture-improvement/epic-02-compile-regex-and-storage-enum/learnings.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/cfinterface-architecture-improvement/epic-02-compile-regex-and-storage-enum/ticket-005-compile-regex-patterns.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/cfinterface-architecture-improvement/epic-02-compile-regex-and-storage-enum/ticket-006-create-storagetype-enum.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/cfinterface-architecture-improvement/epic-02-compile-regex-and-storage-enum/ticket-007-update-factory-functions.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/cfinterface-architecture-improvement/epic-02-compile-regex-and-storage-enum/ticket-008-migrate-internal-storage-usage.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/cfinterface-architecture-improvement/epic-02-compile-regex-and-storage-enum/ticket-009-add-deprecation-warnings.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/cfinterface-architecture-improvement/epic-03-optimize-float-field-write/00-epic-overview.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/cfinterface-architecture-improvement/epic-03-optimize-float-field-write/learnings.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/cfinterface-architecture-improvement/epic-03-optimize-float-field-write/ticket-010-optimize-floatfield-write.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/cfinterface-architecture-improvement/epic-03-optimize-float-field-write/ticket-011-add-floatfield-benchmarks.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/cfinterface-architecture-improvement/epic-04-array-backed-data-containers/00-epic-overview.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/cfinterface-architecture-improvement/epic-04-array-backed-data-containers/learnings.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/cfinterface-architecture-improvement/epic-04-array-backed-data-containers/ticket-012-list-backed-registerdata.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/cfinterface-architecture-improvement/epic-04-array-backed-data-containers/ticket-013-list-backed-blockdata.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/cfinterface-architecture-improvement/epic-04-array-backed-data-containers/ticket-014-list-backed-sectiondata.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/cfinterface-architecture-improvement/epic-04-array-backed-data-containers/ticket-015-computed-prev-next-properties.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/cfinterface-architecture-improvement/epic-04-array-backed-data-containers/ticket-016-type-indexed-lookup.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/cfinterface-architecture-improvement/epic-05-type-safe-text-binary-dispatch/00-epic-overview.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/cfinterface-architecture-improvement/epic-05-type-safe-text-binary-dispatch/learnings.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/cfinterface-architecture-improvement/epic-05-type-safe-text-binary-dispatch/ticket-017-typed-field-protocol.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/cfinterface-architecture-improvement/epic-05-type-safe-text-binary-dispatch/ticket-018-typed-repository-signatures.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/cfinterface-architecture-improvement/epic-05-type-safe-text-binary-dispatch/ticket-019-typed-line-dispatch.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/cfinterface-architecture-improvement/epic-05-type-safe-text-binary-dispatch/ticket-020-typed-component-io.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/cfinterface-architecture-improvement/epic-06-generic-tabular-parser/00-epic-overview.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/cfinterface-architecture-improvement/epic-06-generic-tabular-parser/ticket-021-tabular-parser-engine.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/cfinterface-architecture-improvement/epic-06-generic-tabular-parser/ticket-022-tabular-section-base.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/cfinterface-architecture-improvement/epic-06-generic-tabular-parser/ticket-023-delimited-tabular-parsing.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/cfinterface-architecture-improvement/epic-07-schema-versioning-and-batch-ops/00-epic-overview.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/cfinterface-architecture-improvement/epic-07-schema-versioning-and-batch-ops/learnings.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/cfinterface-architecture-improvement/epic-07-schema-versioning-and-batch-ops/ticket-024-schema-version-descriptor.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/cfinterface-architecture-improvement/epic-07-schema-versioning-and-batch-ops/ticket-025-instance-level-version-binding.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/cfinterface-architecture-improvement/epic-07-schema-versioning-and-batch-ops/ticket-026-batch-read-api.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/cfinterface-architecture-improvement/epic-07-schema-versioning-and-batch-ops/ticket-027-version-validation.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/cfinterface-architecture-improvement/learnings/epic-01-summary.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/cfinterface-architecture-improvement/learnings/epic-02-summary.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/cfinterface-architecture-improvement/learnings/epic-03-summary.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/cfinterface-architecture-improvement/learnings/epic-04-summary.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/cfinterface-architecture-improvement/learnings/epic-05-summary.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/cfinterface-architecture-improvement/learnings/epic-06-summary.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/cfinterface-architecture-improvement/learnings/epic-07-summary.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/cfinterface-quality-and-ci/.implementation-state.json +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/cfinterface-quality-and-ci/00-master-plan.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/cfinterface-quality-and-ci/README.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/cfinterface-quality-and-ci/epic-01-pyproject-and-tool-config/00-epic-overview.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/cfinterface-quality-and-ci/epic-01-pyproject-and-tool-config/ticket-001-update-classifiers-and-metadata.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/cfinterface-quality-and-ci/epic-01-pyproject-and-tool-config/ticket-002-add-pytest-configuration.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/cfinterface-quality-and-ci/epic-01-pyproject-and-tool-config/ticket-003-add-mypy-configuration.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/cfinterface-quality-and-ci/epic-01-pyproject-and-tool-config/ticket-004-fix-mypy-strict-errors.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/cfinterface-quality-and-ci/epic-01-pyproject-and-tool-config/ticket-005-add-coverage-and-ruff-config.md +0 -0
- {cfinterface-1.9.0 → 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 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/cfinterface-quality-and-ci/epic-02-ci-overhaul/00-epic-overview.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/cfinterface-quality-and-ci/epic-02-ci-overhaul/ticket-007-expand-test-matrix.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/cfinterface-quality-and-ci/epic-02-ci-overhaul/ticket-008-extract-lint-job.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/cfinterface-quality-and-ci/epic-02-ci-overhaul/ticket-009-create-benchmark-workflow.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/cfinterface-quality-and-ci/epic-02-ci-overhaul/ticket-010-update-docs-and-publish-workflows.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/cfinterface-quality-and-ci/epic-03-test-infrastructure/00-epic-overview.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/cfinterface-quality-and-ci/epic-03-test-infrastructure/ticket-011-create-conftest-and-fixtures.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/cfinterface-quality-and-ci/epic-03-test-infrastructure/ticket-012-add-hypothesis-field-tests.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/cfinterface-quality-and-ci/epic-03-test-infrastructure/ticket-013-add-hypothesis-tabular-tests.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/cfinterface-quality-and-ci/epic-03-test-infrastructure/ticket-014-migrate-to-pytest-benchmark.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/cfinterface-quality-and-ci/epic-04-sphinx-docs/00-epic-overview.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/cfinterface-quality-and-ci/epic-04-sphinx-docs/ticket-015-add-tabular-reference-pages.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/cfinterface-quality-and-ci/epic-04-sphinx-docs/ticket-016-add-versioning-reference-page.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/cfinterface-quality-and-ci/epic-04-sphinx-docs/ticket-017-add-storage-and-adapter-pages.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/cfinterface-quality-and-ci/epic-04-sphinx-docs/ticket-018-fix-docstrings-and-index.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/cfinterface-quality-and-ci/epic-05-changelog-and-release-prep/00-epic-overview.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/cfinterface-quality-and-ci/epic-05-changelog-and-release-prep/ticket-019-create-changelog.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/cfinterface-quality-and-ci/epic-05-changelog-and-release-prep/ticket-020-release-prep-review.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/infra-docs-overhaul/.implementation-state.json +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/infra-docs-overhaul/00-master-plan.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/infra-docs-overhaul/README.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/infra-docs-overhaul/epic-01-ci-and-developer-tooling/00-epic-overview.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/infra-docs-overhaul/epic-01-ci-and-developer-tooling/ticket-001-add-pre-commit-configuration.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/infra-docs-overhaul/epic-01-ci-and-developer-tooling/ticket-002-upgrade-github-actions-versions.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/infra-docs-overhaul/epic-01-ci-and-developer-tooling/ticket-003-migrate-docs-deployment.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/infra-docs-overhaul/epic-02-sphinx-modernization/00-epic-overview.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/infra-docs-overhaul/epic-02-sphinx-modernization/ticket-004-migrate-sphinx-theme-to-furo.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/infra-docs-overhaul/epic-02-sphinx-modernization/ticket-005-add-sphinx-gallery-examples.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/infra-docs-overhaul/epic-02-sphinx-modernization/ticket-006-update-conf-language-intersphinx.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/infra-docs-overhaul/epic-03-documentation-content/00-epic-overview.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/infra-docs-overhaul/epic-03-documentation-content/ticket-007-create-architecture-overview.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/infra-docs-overhaul/epic-03-documentation-content/ticket-008-create-faq-page.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/infra-docs-overhaul/epic-03-documentation-content/ticket-009-create-migration-guide.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/infra-docs-overhaul/epic-03-documentation-content/ticket-010-create-performance-tips-page.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/infra-docs-overhaul/epic-03-documentation-content/ticket-011-update-contributing-rst.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/infra-docs-overhaul/epic-04-repository-polish/00-epic-overview.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/infra-docs-overhaul/epic-04-repository-polish/ticket-012-create-root-contributing-md.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/infra-docs-overhaul/epic-04-repository-polish/ticket-013-restructure-index-rst.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/infra-docs-overhaul/learnings/epic-01-summary.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/infra-docs-overhaul/learnings/epic-02-summary.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/plans/infra-docs-overhaul/learnings/epic-03-summary.md +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/pyproject.toml +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/tests/__init__.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/tests/_utils/__init__.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/tests/_utils/test_is_null.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/tests/adapters/__init__.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/tests/adapters/components/__init__.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/tests/adapters/components/test_blockrepository.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/tests/adapters/components/test_factory.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/tests/adapters/components/test_linerepository.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/tests/adapters/components/test_pattern_cache.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/tests/adapters/components/test_registerrepository.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/tests/adapters/components/test_sectionrepository.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/tests/adapters/reading/__init__.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/tests/adapters/reading/test_readingrepository.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/tests/adapters/writing/__init__.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/tests/adapters/writing/test_writingrepository.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/tests/components/__init__.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/tests/components/conftest.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/tests/components/test_block.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/tests/components/test_datetimefield.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/tests/components/test_defaultblock.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/tests/components/test_defaultregister.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/tests/components/test_defaultsection.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/tests/components/test_field.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/tests/components/test_field_hypothesis.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/tests/components/test_floatfield.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/tests/components/test_floatfield_benchmark.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/tests/components/test_integerfield.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/tests/components/test_line.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/tests/components/test_literalfield.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/tests/components/test_register.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/tests/components/test_section.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/tests/components/test_storage_integration.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/tests/components/test_tabular.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/tests/components/test_tabular_hypothesis.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/tests/conftest.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/tests/data/__init__.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/tests/data/test_blockdata.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/tests/data/test_registerdata.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/tests/data/test_sectiondata.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/tests/files/__init__.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/tests/files/test_blockfile.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/tests/files/test_registerfile.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/tests/files/test_sectionfile.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/tests/mocks/__init__.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/tests/mocks/mock_open.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/tests/reading/__init__.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/tests/reading/test_blockreading.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/tests/reading/test_registerreading.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/tests/reading/test_sectionreading.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/tests/test_storage.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/tests/test_storage_deprecation.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/tests/test_versioning.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/tests/writing/__init__.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/tests/writing/test_blockwriting.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/tests/writing/test_registerwriting.py +0 -0
- {cfinterface-1.9.0 → cfinterface-1.9.1}/tests/writing/test_sectionwriting.py +0 -0
|
@@ -7,6 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [1.9.1] - 2026-03-08
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- Translate all documentation and examples from pt-BR to English, matching the project's established language
|
|
15
|
+
- Change Sphinx language setting from `pt_BR` to `en`
|
|
16
|
+
|
|
10
17
|
## [1.9.0] - 2026-03-08
|
|
11
18
|
|
|
12
19
|
### Added
|
|
@@ -67,5 +74,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
67
74
|
- Null value detection in `Field` write methods now uses `math.isnan()` instead of `pd.isnull()`, eliminating the unnecessary pandas import at module level
|
|
68
75
|
- `RegisterFile._as_df()` now performs a lazy pandas import, only importing the library when the method is actually called
|
|
69
76
|
|
|
70
|
-
[Unreleased]: https://github.com/rjmalves/cfinterface/compare/v1.9.
|
|
77
|
+
[Unreleased]: https://github.com/rjmalves/cfinterface/compare/v1.9.1...HEAD
|
|
78
|
+
[1.9.1]: https://github.com/rjmalves/cfinterface/compare/v1.9.0...v1.9.1
|
|
71
79
|
[1.9.0]: https://github.com/rjmalves/cfinterface/compare/v1.8.3...v1.9.0
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
Thank you for your interest in contributing to **cfinterface**! This page
|
|
4
|
+
summarises the essential steps. For detailed instructions, see the
|
|
5
|
+
[full contribution documentation](https://rjmalves.github.io/cfinterface/getting_started/contributing.html).
|
|
6
|
+
|
|
7
|
+
## Reporting Bugs
|
|
8
|
+
|
|
9
|
+
Found unexpected behavior? Open an
|
|
10
|
+
[issue on GitHub](https://github.com/rjmalves/cfinterface/issues) describing
|
|
11
|
+
the problem. Include the Python version, the operating system, and a code
|
|
12
|
+
snippet that allows the error to be reproduced.
|
|
13
|
+
|
|
14
|
+
## Submitting Pull Requests
|
|
15
|
+
|
|
16
|
+
Fixes and improvements are welcome via
|
|
17
|
+
[pull request](https://github.com/rjmalves/cfinterface/pulls). Before
|
|
18
|
+
submitting, read the full documentation to ensure that the code follows the
|
|
19
|
+
project conventions and that all tests and quality checks pass.
|
|
20
|
+
|
|
21
|
+
## Quick Setup
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
git clone https://github.com/rjmalves/cfinterface.git
|
|
25
|
+
cd cfinterface
|
|
26
|
+
uv sync --extra dev
|
|
27
|
+
uv run pre-commit install
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Full Documentation
|
|
31
|
+
|
|
32
|
+
See the contribution page in the project documentation for details on
|
|
33
|
+
pre-commit hooks, code conventions, running tests, and building the
|
|
34
|
+
documentation:
|
|
35
|
+
|
|
36
|
+
<https://rjmalves.github.io/cfinterface/getting_started/contributing.html>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cfinterface
|
|
3
|
-
Version: 1.9.
|
|
3
|
+
Version: 1.9.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/
|
|
@@ -58,7 +58,7 @@ templates_path = ["_templates"]
|
|
|
58
58
|
#
|
|
59
59
|
# This is also used if you do content translation via gettext catalogs.
|
|
60
60
|
# Usually you set "language" from the command line for these cases.
|
|
61
|
-
language = "
|
|
61
|
+
language = "en"
|
|
62
62
|
|
|
63
63
|
# The suffix of source filenames.
|
|
64
64
|
source_suffix = ".rst"
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
Contributing
|
|
2
|
+
============
|
|
3
|
+
|
|
4
|
+
To report unexpected behavior, open an
|
|
5
|
+
`issue <https://github.com/rjmalves/cfinterface/issues>`_ in the repository.
|
|
6
|
+
When doing so, it is recommended to provide basic information (Python version,
|
|
7
|
+
operating system) along with a code snippet that allows the problem to be
|
|
8
|
+
reproduced. If you have found a possible fix for an existing issue,
|
|
9
|
+
`pull requests <https://github.com/rjmalves/cfinterface/pulls>`_
|
|
10
|
+
are welcome. In that case, please review the content of this page before
|
|
11
|
+
submitting your contribution.
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
Development Environment Setup
|
|
15
|
+
-------------------------------
|
|
16
|
+
|
|
17
|
+
To install the development dependencies, run the commands below:
|
|
18
|
+
|
|
19
|
+
.. code-block:: bash
|
|
20
|
+
|
|
21
|
+
git clone https://github.com/rjmalves/cfinterface.git
|
|
22
|
+
cd cfinterface
|
|
23
|
+
uv sync --extra dev
|
|
24
|
+
uv run pre-commit install
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
Pre-commit Hooks
|
|
28
|
+
-----------------
|
|
29
|
+
|
|
30
|
+
The project uses `pre-commit <https://pre-commit.com/>`_ to automatically
|
|
31
|
+
enforce code quality before each commit. Three hooks are configured:
|
|
32
|
+
|
|
33
|
+
- **ruff** (v0.9.10): linter with automatic fixes (``--fix``)
|
|
34
|
+
- **ruff-format** (v0.9.10): code formatting
|
|
35
|
+
- **mypy** (v1.19.1): static type checking, applied only to the
|
|
36
|
+
``cfinterface/`` directory
|
|
37
|
+
|
|
38
|
+
To run all hooks manually against all files:
|
|
39
|
+
|
|
40
|
+
.. code-block:: bash
|
|
41
|
+
|
|
42
|
+
uv run pre-commit run --all-files
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
Code Conventions
|
|
46
|
+
-----------------
|
|
47
|
+
|
|
48
|
+
The project uses ``ruff`` for linting and formatting, and ``mypy`` for static
|
|
49
|
+
typing. To run the checks manually:
|
|
50
|
+
|
|
51
|
+
.. code-block:: bash
|
|
52
|
+
|
|
53
|
+
uv run ruff check ./cfinterface
|
|
54
|
+
uv run ruff format --check ./cfinterface
|
|
55
|
+
uv run mypy ./cfinterface
|
|
56
|
+
|
|
57
|
+
These same checks are run in the CI workflows. For a version to be published
|
|
58
|
+
successfully, all requirements must be met.
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
Tests
|
|
62
|
+
------
|
|
63
|
+
|
|
64
|
+
The adopted testing framework is `pytest <https://docs.pytest.org/en/stable/>`_.
|
|
65
|
+
|
|
66
|
+
To run all tests:
|
|
67
|
+
|
|
68
|
+
.. code-block:: bash
|
|
69
|
+
|
|
70
|
+
uv run pytest ./tests
|
|
71
|
+
|
|
72
|
+
To run only the performance tests with
|
|
73
|
+
`pytest-benchmark <https://pytest-benchmark.readthedocs.io/>`_:
|
|
74
|
+
|
|
75
|
+
.. code-block:: bash
|
|
76
|
+
|
|
77
|
+
uv run pytest ./tests --benchmark-only
|
|
78
|
+
|
|
79
|
+
To check test coverage with
|
|
80
|
+
`pytest-cov <https://pytest-cov.readthedocs.io/>`_:
|
|
81
|
+
|
|
82
|
+
.. code-block:: bash
|
|
83
|
+
|
|
84
|
+
uv run pytest ./tests --cov=cfinterface
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
Documentation
|
|
88
|
+
--------------
|
|
89
|
+
|
|
90
|
+
The documentation is built with `Sphinx <https://www.sphinx-doc.org/>`_ and the
|
|
91
|
+
`Furo <https://pradyunsg.me/furo/>`_ theme. To generate the documentation
|
|
92
|
+
locally:
|
|
93
|
+
|
|
94
|
+
.. code-block:: bash
|
|
95
|
+
|
|
96
|
+
uv run sphinx-build -W -b html docs/source docs/build/html
|
|
97
|
+
|
|
98
|
+
.. note::
|
|
99
|
+
|
|
100
|
+
The content generated by the build **must not be committed** to the
|
|
101
|
+
repository. Artifacts are built and published automatically by the
|
|
102
|
+
`GitHub Actions <https://github.com/features/actions>`_ workflows on
|
|
103
|
+
every change to the ``main`` branch.
|
|
@@ -0,0 +1,454 @@
|
|
|
1
|
+
Architecture Overview
|
|
2
|
+
=====================
|
|
3
|
+
|
|
4
|
+
``cfinterface`` is a declarative framework for building low-level interfaces with text or binary
|
|
5
|
+
files of complex structure. Instead of writing imperative code to iterate over file lines, the
|
|
6
|
+
developer declares the schema -- which fields exist, at which positions, how to identify each
|
|
7
|
+
record -- and the framework handles reading and writing. This approach makes the file schema
|
|
8
|
+
explicit, reusable, and independently testable.
|
|
9
|
+
|
|
10
|
+
The design follows a layered composition principle: atomic components are grouped into
|
|
11
|
+
intermediate components, which in turn are orchestrated by high-level file classes.
|
|
12
|
+
An adapter layer isolates the differences between textual and binary storage from the rest of
|
|
13
|
+
the code.
|
|
14
|
+
|
|
15
|
+
Component Hierarchy
|
|
16
|
+
--------------------
|
|
17
|
+
|
|
18
|
+
The full component hierarchy is illustrated below:
|
|
19
|
+
|
|
20
|
+
.. code-block:: text
|
|
21
|
+
|
|
22
|
+
Field (FloatField, IntegerField, LiteralField, DatetimeField)
|
|
23
|
+
|
|
|
24
|
+
v
|
|
25
|
+
Line (ordered sequence of Fields; delegates I/O to the adapter)
|
|
26
|
+
|
|
|
27
|
+
v
|
|
28
|
+
Register / Block / Section (intermediate components; operate on file handles)
|
|
29
|
+
|
|
|
30
|
+
v
|
|
31
|
+
RegisterFile / BlockFile / SectionFile (high-level file classes)
|
|
32
|
+
|
|
33
|
+
Each layer depends only on the layer immediately below it, keeping coupling minimal and
|
|
34
|
+
allowing each level to be tested and reused independently.
|
|
35
|
+
|
|
36
|
+
Fields
|
|
37
|
+
-------
|
|
38
|
+
|
|
39
|
+
:class:`cfinterface.components.field.Field` is the atomic unit of the framework. A ``Field``
|
|
40
|
+
represents a single positional value within a file line: it knows its starting position
|
|
41
|
+
(``starting_position``), its size in characters or bytes (``size``), and the current value
|
|
42
|
+
(``value``). The public methods :meth:`~cfinterface.components.field.Field.read` and
|
|
43
|
+
:meth:`~cfinterface.components.field.Field.write` accept both ``str`` and ``bytes``,
|
|
44
|
+
delegating internally to ``_textual_read``/``_binary_read`` or
|
|
45
|
+
``_textual_write``/``_binary_write``.
|
|
46
|
+
|
|
47
|
+
The framework provides four concrete subclasses ready for use:
|
|
48
|
+
|
|
49
|
+
:class:`cfinterface.components.floatfield.FloatField`
|
|
50
|
+
Reads and writes floating-point numbers. Supports fixed notation (``format="F"``),
|
|
51
|
+
scientific notation (``format="E"`` or ``format="D"``), and a configurable decimal
|
|
52
|
+
separator. For binary storage uses ``numpy`` (``float16``, ``float32``, or ``float64``
|
|
53
|
+
depending on ``size``).
|
|
54
|
+
|
|
55
|
+
:class:`cfinterface.components.integerfield.IntegerField`
|
|
56
|
+
Reads and writes integers. In binary mode uses ``numpy`` (``int16``, ``int32``, or ``int64``).
|
|
57
|
+
|
|
58
|
+
:class:`cfinterface.components.literalfield.LiteralField`
|
|
59
|
+
Reads and writes fixed-width strings, stripping whitespace from the edges when reading
|
|
60
|
+
and left-aligning when writing.
|
|
61
|
+
|
|
62
|
+
:class:`cfinterface.components.datetimefield.DatetimeField`
|
|
63
|
+
Reads and writes :class:`datetime.datetime` objects from one or more format strings.
|
|
64
|
+
|
|
65
|
+
Example -- defining a textual field:
|
|
66
|
+
|
|
67
|
+
.. code-block:: python
|
|
68
|
+
|
|
69
|
+
from cfinterface import LiteralField, FloatField
|
|
70
|
+
|
|
71
|
+
name = LiteralField(size=20, starting_position=0)
|
|
72
|
+
balance = FloatField(size=12, starting_position=20, decimal_digits=2)
|
|
73
|
+
|
|
74
|
+
line = "Current Account -1234.56 "
|
|
75
|
+
name.read(line) # "Current Account"
|
|
76
|
+
balance.read(line) # -1234.56
|
|
77
|
+
|
|
78
|
+
Line
|
|
79
|
+
-----
|
|
80
|
+
|
|
81
|
+
:class:`cfinterface.components.line.Line` aggregates an ordered list of
|
|
82
|
+
:class:`~cfinterface.components.field.Field` instances and provides the methods
|
|
83
|
+
:meth:`~cfinterface.components.line.Line.read` and
|
|
84
|
+
:meth:`~cfinterface.components.line.Line.write` to operate on the entire line at once.
|
|
85
|
+
Internally, ``Line`` does not perform I/O directly: it instantiates a repository via the
|
|
86
|
+
function :func:`cfinterface.adapters.components.line.repository.factory`, passing the
|
|
87
|
+
configured ``StorageType``. That repository is what executes reading and writing according
|
|
88
|
+
to the storage backend (textual or binary).
|
|
89
|
+
|
|
90
|
+
``Line`` accepts an optional ``delimiter``: when provided, fields are separated by that
|
|
91
|
+
character instead of occupying fixed positions.
|
|
92
|
+
|
|
93
|
+
.. code-block:: python
|
|
94
|
+
|
|
95
|
+
from cfinterface import LiteralField, FloatField
|
|
96
|
+
from cfinterface.components.line import Line
|
|
97
|
+
from cfinterface.storage import StorageType
|
|
98
|
+
|
|
99
|
+
fields = [
|
|
100
|
+
LiteralField(size=20, starting_position=0),
|
|
101
|
+
FloatField(size=10, starting_position=20, decimal_digits=2),
|
|
102
|
+
]
|
|
103
|
+
line = Line(fields, storage=StorageType.TEXT)
|
|
104
|
+
values = line.read("Current Account -1234.56 ")
|
|
105
|
+
# values == ["Current Account", -1234.56]
|
|
106
|
+
|
|
107
|
+
Intermediate Components
|
|
108
|
+
------------------------
|
|
109
|
+
|
|
110
|
+
Intermediate components operate directly on file handles (``IO[Any]``) and implement the
|
|
111
|
+
logic for identifying and delimiting content blocks.
|
|
112
|
+
|
|
113
|
+
Register
|
|
114
|
+
~~~~~~~~~
|
|
115
|
+
|
|
116
|
+
:class:`cfinterface.components.register.Register` represents a single file line identified
|
|
117
|
+
by a fixed prefix. The class attribute ``IDENTIFIER`` defines the prefix (``str`` or
|
|
118
|
+
``bytes``) and ``IDENTIFIER_DIGITS`` specifies the number of characters or bytes that form
|
|
119
|
+
this identifier. The class attribute ``LINE`` is an instance of
|
|
120
|
+
:class:`~cfinterface.components.line.Line` that describes the fields after the identifier.
|
|
121
|
+
|
|
122
|
+
The class method :meth:`~cfinterface.components.register.Register.matches` checks whether a
|
|
123
|
+
line belongs to this record type by comparing its beginning with ``IDENTIFIER``.
|
|
124
|
+
|
|
125
|
+
.. code-block:: python
|
|
126
|
+
|
|
127
|
+
from cfinterface.components.register import Register
|
|
128
|
+
from cfinterface.components.line import Line
|
|
129
|
+
from cfinterface.components.floatfield import FloatField
|
|
130
|
+
|
|
131
|
+
class MonthlyValue(Register):
|
|
132
|
+
IDENTIFIER = "VM"
|
|
133
|
+
IDENTIFIER_DIGITS = 2
|
|
134
|
+
LINE = Line([FloatField(size=10, starting_position=2, decimal_digits=2)])
|
|
135
|
+
|
|
136
|
+
Block
|
|
137
|
+
~~~~~~
|
|
138
|
+
|
|
139
|
+
:class:`cfinterface.components.block.Block` represents a block delimited by begin and end
|
|
140
|
+
patterns. The class attributes ``BEGIN_PATTERN`` and ``END_PATTERN`` are regular expressions
|
|
141
|
+
(``str`` or ``bytes``) that indicate where the block starts and ends. The attribute
|
|
142
|
+
``MAX_LINES`` (default: 10000) limits the number of lines processed per block as a safeguard
|
|
143
|
+
against infinite reads.
|
|
144
|
+
|
|
145
|
+
The class methods :meth:`~cfinterface.components.block.Block.begins` and
|
|
146
|
+
:meth:`~cfinterface.components.block.Block.ends` test a line against the corresponding
|
|
147
|
+
patterns. The methods :meth:`~cfinterface.components.block.Block.read` and
|
|
148
|
+
:meth:`~cfinterface.components.block.Block.write` must be implemented by the subclass.
|
|
149
|
+
|
|
150
|
+
.. code-block:: python
|
|
151
|
+
|
|
152
|
+
from cfinterface.components.block import Block
|
|
153
|
+
|
|
154
|
+
class DataSection(Block):
|
|
155
|
+
BEGIN_PATTERN = r"^BEGIN"
|
|
156
|
+
END_PATTERN = r"^END"
|
|
157
|
+
|
|
158
|
+
def read(self, file, *args, **kwargs):
|
|
159
|
+
# custom read logic
|
|
160
|
+
return True
|
|
161
|
+
|
|
162
|
+
def write(self, file, *args, **kwargs):
|
|
163
|
+
# custom write logic
|
|
164
|
+
return True
|
|
165
|
+
|
|
166
|
+
Section
|
|
167
|
+
~~~~~~~~
|
|
168
|
+
|
|
169
|
+
:class:`cfinterface.components.section.Section` represents an ordered, sequential division
|
|
170
|
+
of the file, without begin or end patterns. Sections are processed in the order in which they
|
|
171
|
+
appear in ``SectionFile.SECTIONS``. The class attribute ``STORAGE`` (of type
|
|
172
|
+
:class:`~cfinterface.storage.StorageType`) indicates whether the section operates in textual
|
|
173
|
+
or binary mode. The methods :meth:`~cfinterface.components.section.Section.read` and
|
|
174
|
+
:meth:`~cfinterface.components.section.Section.write` must be implemented by the subclass.
|
|
175
|
+
|
|
176
|
+
File Classes
|
|
177
|
+
-------------
|
|
178
|
+
|
|
179
|
+
File classes are the framework's entry point for the end user. Each one aggregates a set of
|
|
180
|
+
intermediate components and provides the high-level methods
|
|
181
|
+
:meth:`read`, :meth:`write`, :meth:`read_many`, and :meth:`validate`.
|
|
182
|
+
|
|
183
|
+
:class:`cfinterface.files.registerfile.RegisterFile`
|
|
184
|
+
Models files composed of single-line records. The class attribute ``REGISTERS``
|
|
185
|
+
is a list of :class:`~cfinterface.components.register.Register` subclasses in the order
|
|
186
|
+
in which they may appear in the file.
|
|
187
|
+
|
|
188
|
+
:class:`cfinterface.files.blockfile.BlockFile`
|
|
189
|
+
Models files composed of delimited blocks. The class attribute ``BLOCKS`` is a list
|
|
190
|
+
of :class:`~cfinterface.components.block.Block` subclasses.
|
|
191
|
+
|
|
192
|
+
:class:`cfinterface.files.sectionfile.SectionFile`
|
|
193
|
+
Models files composed of sequential sections. The class attribute ``SECTIONS`` is a
|
|
194
|
+
list of :class:`~cfinterface.components.section.Section` subclasses.
|
|
195
|
+
|
|
196
|
+
Class attributes common to all file classes:
|
|
197
|
+
|
|
198
|
+
``STORAGE``
|
|
199
|
+
:class:`~cfinterface.storage.StorageType` that indicates the storage backend
|
|
200
|
+
(``StorageType.TEXT`` or ``StorageType.BINARY``). Default: ``StorageType.TEXT``.
|
|
201
|
+
|
|
202
|
+
``ENCODING``
|
|
203
|
+
Text encoding to use (``str``) or list of encodings tried in order
|
|
204
|
+
(``list[str]``). Default: ``["utf-8", "latin-1", "ascii"]``.
|
|
205
|
+
|
|
206
|
+
``VERSIONS``
|
|
207
|
+
Optional dictionary mapping version keys to lists of component types,
|
|
208
|
+
allowing the same file class to support multiple schema versions. See the
|
|
209
|
+
`Versioning`_ section for details.
|
|
210
|
+
|
|
211
|
+
.. code-block:: python
|
|
212
|
+
|
|
213
|
+
from cfinterface.files.registerfile import RegisterFile
|
|
214
|
+
from cfinterface.storage import StorageType
|
|
215
|
+
|
|
216
|
+
class MyFile(RegisterFile):
|
|
217
|
+
REGISTERS = [MonthlyValue]
|
|
218
|
+
STORAGE = StorageType.TEXT
|
|
219
|
+
ENCODING = "utf-8"
|
|
220
|
+
|
|
221
|
+
file = MyFile.read("/path/to/file.txt")
|
|
222
|
+
file.write("/path/to/output.txt")
|
|
223
|
+
|
|
224
|
+
Adapter Layer
|
|
225
|
+
--------------
|
|
226
|
+
|
|
227
|
+
The adapter layer isolates the differences between textual and binary storage from the rest
|
|
228
|
+
of the framework. The module :mod:`cfinterface.adapters.components.repository` defines the
|
|
229
|
+
hierarchy:
|
|
230
|
+
|
|
231
|
+
- :class:`~cfinterface.adapters.components.repository.Repository` -- abstract interface with
|
|
232
|
+
static methods ``matches``, ``begins``, ``ends``, ``read``, and ``write``.
|
|
233
|
+
- :class:`~cfinterface.adapters.components.repository.TextualRepository` -- implementation for
|
|
234
|
+
text files; uses ``file.readline()`` for reading and regex-based comparisons on strings.
|
|
235
|
+
- :class:`~cfinterface.adapters.components.repository.BinaryRepository` -- implementation for
|
|
236
|
+
binary files; uses ``file.read(linesize)`` and byte comparisons.
|
|
237
|
+
|
|
238
|
+
The function :func:`cfinterface.adapters.components.repository.factory` receives a
|
|
239
|
+
:class:`~cfinterface.storage.StorageType` and returns the appropriate repository class.
|
|
240
|
+
When ``StorageType.TEXT`` is passed, it returns ``TextualRepository``; when
|
|
241
|
+
``StorageType.BINARY``, it returns ``BinaryRepository``. This factory pattern is the central
|
|
242
|
+
point that allows the framework to be agnostic to the storage type.
|
|
243
|
+
|
|
244
|
+
The regular expressions used by the adapters are compiled and cached on first use
|
|
245
|
+
(``_pattern_cache``), eliminating recompilation per call.
|
|
246
|
+
|
|
247
|
+
TabularParser
|
|
248
|
+
--------------
|
|
249
|
+
|
|
250
|
+
Introduced in version 1.9.0, :class:`cfinterface.components.tabular.TabularParser` provides
|
|
251
|
+
a declarative approach for parsing tabular content -- blocks of lines where each line
|
|
252
|
+
represents a data row with columns defined by fixed positions or by a delimiter.
|
|
253
|
+
|
|
254
|
+
The column schema is declared as a list of :class:`cfinterface.components.tabular.ColumnDef`,
|
|
255
|
+
a ``NamedTuple`` with two fields:
|
|
256
|
+
|
|
257
|
+
``name``
|
|
258
|
+
Column name (key in the output dictionary).
|
|
259
|
+
|
|
260
|
+
``field``
|
|
261
|
+
Instance of :class:`~cfinterface.components.field.Field` that defines the type, position,
|
|
262
|
+
and size of the column. Each ``ColumnDef`` must use its own ``Field`` instance -- the
|
|
263
|
+
``Line.read()`` method mutates field values in-place, so sharing instances between columns
|
|
264
|
+
produces incorrect results.
|
|
265
|
+
|
|
266
|
+
The main methods are:
|
|
267
|
+
|
|
268
|
+
:meth:`~cfinterface.components.tabular.TabularParser.parse_lines`
|
|
269
|
+
Receives a list of strings and returns a dictionary whose keys are column names
|
|
270
|
+
and whose values are lists of values read line by line.
|
|
271
|
+
|
|
272
|
+
:meth:`~cfinterface.components.tabular.TabularParser.format_rows`
|
|
273
|
+
Inverse operation: receives a dictionary in the same format and returns a list of
|
|
274
|
+
formatted strings.
|
|
275
|
+
|
|
276
|
+
:meth:`~cfinterface.components.tabular.TabularParser.to_dataframe`
|
|
277
|
+
Converts the dictionary returned by ``parse_lines`` into a ``pandas.DataFrame``. Requires
|
|
278
|
+
the optional dependency ``cfinterface[pandas]``.
|
|
279
|
+
|
|
280
|
+
For integrated use with ``SectionFile``, the class
|
|
281
|
+
:class:`cfinterface.components.tabular.TabularSection` extends
|
|
282
|
+
:class:`~cfinterface.components.section.Section` and implements ``read()`` and ``write()``
|
|
283
|
+
automatically based on the class attributes ``COLUMNS``, ``HEADER_LINES``, ``END_PATTERN``,
|
|
284
|
+
and ``DELIMITER``.
|
|
285
|
+
|
|
286
|
+
.. code-block:: python
|
|
287
|
+
|
|
288
|
+
from cfinterface.components.tabular import TabularParser, ColumnDef
|
|
289
|
+
from cfinterface.components.literalfield import LiteralField
|
|
290
|
+
from cfinterface.components.floatfield import FloatField
|
|
291
|
+
|
|
292
|
+
columns = [
|
|
293
|
+
ColumnDef(name="name", field=LiteralField(size=20, starting_position=0)),
|
|
294
|
+
ColumnDef(name="value", field=FloatField(size=10, starting_position=20, decimal_digits=2)),
|
|
295
|
+
]
|
|
296
|
+
parser = TabularParser(columns)
|
|
297
|
+
|
|
298
|
+
lines = [
|
|
299
|
+
"Product A 12.50 ",
|
|
300
|
+
"Product B 7.99 ",
|
|
301
|
+
]
|
|
302
|
+
data = parser.parse_lines(lines)
|
|
303
|
+
# data == {"name": ["Product A", "Product B"], "value": [12.5, 7.99]}
|
|
304
|
+
|
|
305
|
+
Versioning
|
|
306
|
+
-----------
|
|
307
|
+
|
|
308
|
+
The module :mod:`cfinterface.versioning` provides support for files whose schema evolves over
|
|
309
|
+
time, allowing the same file class to read content from different versions without needing
|
|
310
|
+
separate classes.
|
|
311
|
+
|
|
312
|
+
:class:`cfinterface.versioning.SchemaVersion`
|
|
313
|
+
``NamedTuple`` with three fields: ``key`` (version identifier as a string), ``components``
|
|
314
|
+
(list of component types corresponding to this version), and ``description`` (optional text).
|
|
315
|
+
|
|
316
|
+
``VERSIONS``
|
|
317
|
+
Class attribute of file classes (``RegisterFile``, ``BlockFile``, ``SectionFile``).
|
|
318
|
+
It is a dictionary mapping version keys (strings compared lexicographically) to lists
|
|
319
|
+
of component types. Example: ``{"1.0": [RegV1], "2.0": [RegV1, RegV2]}``.
|
|
320
|
+
|
|
321
|
+
:func:`cfinterface.versioning.resolve_version`
|
|
322
|
+
Receives a requested version key and the ``VERSIONS`` dictionary. Returns the list of
|
|
323
|
+
components whose key is the most recent available that is less than or equal to the
|
|
324
|
+
requested version (lexicographic comparison). Returns ``None`` if the requested version
|
|
325
|
+
is earlier than all available ones.
|
|
326
|
+
|
|
327
|
+
:func:`cfinterface.versioning.validate_version`
|
|
328
|
+
Validates the read content against the expected component types. Returns a
|
|
329
|
+
:class:`~cfinterface.versioning.VersionMatchResult` with the fields ``matched``,
|
|
330
|
+
``expected_types``, ``found_types``, ``missing_types``, ``unexpected_types``, and
|
|
331
|
+
``default_ratio``.
|
|
332
|
+
|
|
333
|
+
.. code-block:: python
|
|
334
|
+
|
|
335
|
+
from cfinterface.files.registerfile import RegisterFile
|
|
336
|
+
from cfinterface.storage import StorageType
|
|
337
|
+
|
|
338
|
+
class VersionedFile(RegisterFile):
|
|
339
|
+
REGISTERS = [MonthlyValueV2]
|
|
340
|
+
VERSIONS = {
|
|
341
|
+
"1.0": [MonthlyValueV1],
|
|
342
|
+
"2.0": [MonthlyValueV2],
|
|
343
|
+
}
|
|
344
|
+
STORAGE = StorageType.TEXT
|
|
345
|
+
|
|
346
|
+
# Reading while selecting a version without mutating the class
|
|
347
|
+
file = VersionedFile.read("/path/to/file.txt", version="1.5")
|
|
348
|
+
# resolve_version("1.5", VERSIONS) will return the components for "1.0"
|
|
349
|
+
|
|
350
|
+
# Validating the read content
|
|
351
|
+
result = file.validate(version="1.0")
|
|
352
|
+
print(result.matched) # True if the content matches the 1.0 schema
|
|
353
|
+
|
|
354
|
+
StorageType
|
|
355
|
+
------------
|
|
356
|
+
|
|
357
|
+
:class:`cfinterface.storage.StorageType` is an enumeration (``str``, ``Enum``) that replaces
|
|
358
|
+
the use of literal strings ``"TEXT"`` and ``"BINARY"`` to identify the storage backend.
|
|
359
|
+
It inherits from ``str``, which ensures backward compatibility: ``StorageType.TEXT == "TEXT"``
|
|
360
|
+
is ``True``.
|
|
361
|
+
|
|
362
|
+
The two available values are:
|
|
363
|
+
|
|
364
|
+
``StorageType.TEXT``
|
|
365
|
+
Indicates textual storage. The file is opened in text mode and operations use
|
|
366
|
+
``str``.
|
|
367
|
+
|
|
368
|
+
``StorageType.BINARY``
|
|
369
|
+
Indicates binary storage. The file is opened in binary mode and operations use
|
|
370
|
+
``bytes``.
|
|
371
|
+
|
|
372
|
+
The use of literal strings ``"TEXT"`` and ``"BINARY"`` in the ``STORAGE`` attribute of file
|
|
373
|
+
classes has been deprecated since version 1.9.0. The internal function ``_ensure_storage_type``
|
|
374
|
+
emits a :class:`DeprecationWarning` when a plain string is detected instead of an enumeration
|
|
375
|
+
member.
|
|
376
|
+
|
|
377
|
+
.. code-block:: python
|
|
378
|
+
|
|
379
|
+
from cfinterface.storage import StorageType
|
|
380
|
+
|
|
381
|
+
# Correct -- always use the enumeration
|
|
382
|
+
class MyBinaryFile(RegisterFile):
|
|
383
|
+
REGISTERS = [...]
|
|
384
|
+
STORAGE = StorageType.BINARY
|
|
385
|
+
|
|
386
|
+
# Deprecated -- do not use
|
|
387
|
+
# STORAGE = "BINARY"
|
|
388
|
+
|
|
389
|
+
Extension Points
|
|
390
|
+
-----------------
|
|
391
|
+
|
|
392
|
+
``cfinterface`` is designed to be extended through subclassing. The main extension points for
|
|
393
|
+
downstream library developers are:
|
|
394
|
+
|
|
395
|
+
Field Subclasses
|
|
396
|
+
~~~~~~~~~~~~~~~~~
|
|
397
|
+
|
|
398
|
+
Create a subclass of :class:`~cfinterface.components.field.Field` to support data types not
|
|
399
|
+
covered by the native implementations. Implement the four abstract methods:
|
|
400
|
+
``_textual_read``, ``_binary_read``, ``_textual_write``, and ``_binary_write``.
|
|
401
|
+
|
|
402
|
+
.. code-block:: python
|
|
403
|
+
|
|
404
|
+
from cfinterface.components.field import Field
|
|
405
|
+
|
|
406
|
+
class BooleanField(Field):
|
|
407
|
+
def _textual_read(self, line: str) -> bool:
|
|
408
|
+
return line[self._starting_position:self._ending_position].strip() == "S"
|
|
409
|
+
|
|
410
|
+
def _binary_read(self, line: bytes) -> bool:
|
|
411
|
+
return line[self._starting_position:self._ending_position] == b"\x01"
|
|
412
|
+
|
|
413
|
+
def _textual_write(self) -> str:
|
|
414
|
+
return ("S" if self._value else "N").ljust(self._size)
|
|
415
|
+
|
|
416
|
+
def _binary_write(self) -> bytes:
|
|
417
|
+
return b"\x01" if self._value else b"\x00"
|
|
418
|
+
|
|
419
|
+
Register Subclasses
|
|
420
|
+
~~~~~~~~~~~~~~~~~~~~
|
|
421
|
+
|
|
422
|
+
Declare ``IDENTIFIER``, ``IDENTIFIER_DIGITS``, and ``LINE`` to define a new record type
|
|
423
|
+
identified by a prefix. No methods need to be overridden for the standard case of positional
|
|
424
|
+
reading and writing.
|
|
425
|
+
|
|
426
|
+
Block Subclasses
|
|
427
|
+
~~~~~~~~~~~~~~~~~
|
|
428
|
+
|
|
429
|
+
Declare ``BEGIN_PATTERN`` and ``END_PATTERN`` and implement ``read()`` and ``write()`` with
|
|
430
|
+
the processing logic specific to the block.
|
|
431
|
+
|
|
432
|
+
Section Subclasses
|
|
433
|
+
~~~~~~~~~~~~~~~~~~~
|
|
434
|
+
|
|
435
|
+
Declare ``STORAGE`` and implement ``read()`` and ``write()``. For tabular sections, prefer
|
|
436
|
+
subclassing :class:`~cfinterface.components.tabular.TabularSection` and declaring only
|
|
437
|
+
``COLUMNS``, ``HEADER_LINES``, ``END_PATTERN``, and ``DELIMITER``.
|
|
438
|
+
|
|
439
|
+
VERSIONS Dictionaries
|
|
440
|
+
~~~~~~~~~~~~~~~~~~~~~~
|
|
441
|
+
|
|
442
|
+
Add the class attribute ``VERSIONS`` to any subclass of
|
|
443
|
+
:class:`~cfinterface.files.registerfile.RegisterFile`,
|
|
444
|
+
:class:`~cfinterface.files.blockfile.BlockFile`, or
|
|
445
|
+
:class:`~cfinterface.files.sectionfile.SectionFile` to enable schema selection by version at
|
|
446
|
+
read time, without needing to create separate subclasses for each version.
|
|
447
|
+
|
|
448
|
+
TabularParser with Custom Schemas
|
|
449
|
+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
450
|
+
|
|
451
|
+
Instantiate :class:`~cfinterface.components.tabular.TabularParser` with a list of
|
|
452
|
+
:class:`~cfinterface.components.tabular.ColumnDef` instances to parse any tabular block,
|
|
453
|
+
whether fixed-width or delimited. The same instance can be reused for multiple files
|
|
454
|
+
with the same schema.
|