cfinterface 1.10.1__tar.gz → 1.10.2__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 (163) hide show
  1. {cfinterface-1.10.1 → cfinterface-1.10.2}/CHANGELOG.md +6 -0
  2. {cfinterface-1.10.1 → cfinterface-1.10.2}/PKG-INFO +2 -2
  3. {cfinterface-1.10.1 → cfinterface-1.10.2}/cfinterface/__init__.py +1 -1
  4. {cfinterface-1.10.1 → cfinterface-1.10.2}/cfinterface/files/blockfile.py +7 -5
  5. {cfinterface-1.10.1 → cfinterface-1.10.2}/cfinterface/files/registerfile.py +7 -5
  6. {cfinterface-1.10.1 → cfinterface-1.10.2}/cfinterface/files/sectionfile.py +7 -5
  7. cfinterface-1.10.2/tests/files/test_read_typing.py +38 -0
  8. {cfinterface-1.10.1 → cfinterface-1.10.2}/.github/workflows/benchmark.yml +0 -0
  9. {cfinterface-1.10.1 → cfinterface-1.10.2}/.github/workflows/docs.yml +0 -0
  10. {cfinterface-1.10.1 → cfinterface-1.10.2}/.github/workflows/main.yml +0 -0
  11. {cfinterface-1.10.1 → cfinterface-1.10.2}/.github/workflows/publish.yml +0 -0
  12. {cfinterface-1.10.1 → cfinterface-1.10.2}/.gitignore +0 -0
  13. {cfinterface-1.10.1 → cfinterface-1.10.2}/.pre-commit-config.yaml +0 -0
  14. {cfinterface-1.10.1 → cfinterface-1.10.2}/CONTRIBUTING.md +0 -0
  15. {cfinterface-1.10.1 → cfinterface-1.10.2}/LICENSE +0 -0
  16. {cfinterface-1.10.1 → cfinterface-1.10.2}/README.md +0 -0
  17. {cfinterface-1.10.1 → cfinterface-1.10.2}/benchmarks/__init__.py +0 -0
  18. {cfinterface-1.10.1 → cfinterface-1.10.2}/benchmarks/bench_floatfield_write.py +0 -0
  19. {cfinterface-1.10.1 → cfinterface-1.10.2}/cfinterface/_utils/__init__.py +0 -0
  20. {cfinterface-1.10.1 → cfinterface-1.10.2}/cfinterface/adapters/__init__.py +0 -0
  21. {cfinterface-1.10.1 → cfinterface-1.10.2}/cfinterface/adapters/components/__init__.py +0 -0
  22. {cfinterface-1.10.1 → cfinterface-1.10.2}/cfinterface/adapters/components/line/__init__.py +0 -0
  23. {cfinterface-1.10.1 → cfinterface-1.10.2}/cfinterface/adapters/components/line/repository.py +0 -0
  24. {cfinterface-1.10.1 → cfinterface-1.10.2}/cfinterface/adapters/components/repository.py +0 -0
  25. {cfinterface-1.10.1 → cfinterface-1.10.2}/cfinterface/adapters/reading/__init__.py +0 -0
  26. {cfinterface-1.10.1 → cfinterface-1.10.2}/cfinterface/adapters/reading/repository.py +0 -0
  27. {cfinterface-1.10.1 → cfinterface-1.10.2}/cfinterface/adapters/writing/__init__.py +0 -0
  28. {cfinterface-1.10.1 → cfinterface-1.10.2}/cfinterface/adapters/writing/repository.py +0 -0
  29. {cfinterface-1.10.1 → cfinterface-1.10.2}/cfinterface/components/__init__.py +0 -0
  30. {cfinterface-1.10.1 → cfinterface-1.10.2}/cfinterface/components/block.py +0 -0
  31. {cfinterface-1.10.1 → cfinterface-1.10.2}/cfinterface/components/datetimefield.py +0 -0
  32. {cfinterface-1.10.1 → cfinterface-1.10.2}/cfinterface/components/defaultblock.py +0 -0
  33. {cfinterface-1.10.1 → cfinterface-1.10.2}/cfinterface/components/defaultregister.py +0 -0
  34. {cfinterface-1.10.1 → cfinterface-1.10.2}/cfinterface/components/defaultsection.py +0 -0
  35. {cfinterface-1.10.1 → cfinterface-1.10.2}/cfinterface/components/field.py +0 -0
  36. {cfinterface-1.10.1 → cfinterface-1.10.2}/cfinterface/components/floatfield.py +0 -0
  37. {cfinterface-1.10.1 → cfinterface-1.10.2}/cfinterface/components/integerfield.py +0 -0
  38. {cfinterface-1.10.1 → cfinterface-1.10.2}/cfinterface/components/line.py +0 -0
  39. {cfinterface-1.10.1 → cfinterface-1.10.2}/cfinterface/components/literalfield.py +0 -0
  40. {cfinterface-1.10.1 → cfinterface-1.10.2}/cfinterface/components/register.py +0 -0
  41. {cfinterface-1.10.1 → cfinterface-1.10.2}/cfinterface/components/section.py +0 -0
  42. {cfinterface-1.10.1 → cfinterface-1.10.2}/cfinterface/components/tabular.py +0 -0
  43. {cfinterface-1.10.1 → cfinterface-1.10.2}/cfinterface/data/__init__.py +0 -0
  44. {cfinterface-1.10.1 → cfinterface-1.10.2}/cfinterface/data/blockdata.py +0 -0
  45. {cfinterface-1.10.1 → cfinterface-1.10.2}/cfinterface/data/registerdata.py +0 -0
  46. {cfinterface-1.10.1 → cfinterface-1.10.2}/cfinterface/data/sectiondata.py +0 -0
  47. {cfinterface-1.10.1 → cfinterface-1.10.2}/cfinterface/files/__init__.py +0 -0
  48. {cfinterface-1.10.1 → cfinterface-1.10.2}/cfinterface/py.typed +0 -0
  49. {cfinterface-1.10.1 → cfinterface-1.10.2}/cfinterface/reading/__init__.py +0 -0
  50. {cfinterface-1.10.1 → cfinterface-1.10.2}/cfinterface/reading/blockreading.py +0 -0
  51. {cfinterface-1.10.1 → cfinterface-1.10.2}/cfinterface/reading/registerreading.py +0 -0
  52. {cfinterface-1.10.1 → cfinterface-1.10.2}/cfinterface/reading/sectionreading.py +0 -0
  53. {cfinterface-1.10.1 → cfinterface-1.10.2}/cfinterface/storage.py +0 -0
  54. {cfinterface-1.10.1 → cfinterface-1.10.2}/cfinterface/versioning.py +0 -0
  55. {cfinterface-1.10.1 → cfinterface-1.10.2}/cfinterface/writing/__init__.py +0 -0
  56. {cfinterface-1.10.1 → cfinterface-1.10.2}/cfinterface/writing/blockwriting.py +0 -0
  57. {cfinterface-1.10.1 → cfinterface-1.10.2}/cfinterface/writing/registerwriting.py +0 -0
  58. {cfinterface-1.10.1 → cfinterface-1.10.2}/cfinterface/writing/sectionwriting.py +0 -0
  59. {cfinterface-1.10.1 → cfinterface-1.10.2}/docs/source/_static/logo_cfinterface.svg +0 -0
  60. {cfinterface-1.10.1 → cfinterface-1.10.2}/docs/source/conf.py +0 -0
  61. {cfinterface-1.10.1 → cfinterface-1.10.2}/docs/source/getting_started/contributing.rst +0 -0
  62. {cfinterface-1.10.1 → cfinterface-1.10.2}/docs/source/getting_started/tutorial.rst +0 -0
  63. {cfinterface-1.10.1 → cfinterface-1.10.2}/docs/source/guides/architecture.rst +0 -0
  64. {cfinterface-1.10.1 → cfinterface-1.10.2}/docs/source/guides/faq.rst +0 -0
  65. {cfinterface-1.10.1 → cfinterface-1.10.2}/docs/source/guides/migration-v1.9.rst +0 -0
  66. {cfinterface-1.10.1 → cfinterface-1.10.2}/docs/source/guides/performance.rst +0 -0
  67. {cfinterface-1.10.1 → cfinterface-1.10.2}/docs/source/index.rst +0 -0
  68. {cfinterface-1.10.1 → cfinterface-1.10.2}/docs/source/install/install.rst +0 -0
  69. {cfinterface-1.10.1 → cfinterface-1.10.2}/docs/source/reference/adapters/files/components.rst +0 -0
  70. {cfinterface-1.10.1 → cfinterface-1.10.2}/docs/source/reference/adapters/files/line.rst +0 -0
  71. {cfinterface-1.10.1 → cfinterface-1.10.2}/docs/source/reference/adapters/files/reading.rst +0 -0
  72. {cfinterface-1.10.1 → cfinterface-1.10.2}/docs/source/reference/adapters/files/writing.rst +0 -0
  73. {cfinterface-1.10.1 → cfinterface-1.10.2}/docs/source/reference/adapters/index.rst +0 -0
  74. {cfinterface-1.10.1 → cfinterface-1.10.2}/docs/source/reference/blocks/files/block.rst +0 -0
  75. {cfinterface-1.10.1 → cfinterface-1.10.2}/docs/source/reference/blocks/files/blockdata.rst +0 -0
  76. {cfinterface-1.10.1 → cfinterface-1.10.2}/docs/source/reference/blocks/files/blockfile.rst +0 -0
  77. {cfinterface-1.10.1 → cfinterface-1.10.2}/docs/source/reference/blocks/index.rst +0 -0
  78. {cfinterface-1.10.1 → cfinterface-1.10.2}/docs/source/reference/fields/components/datetimefield.rst +0 -0
  79. {cfinterface-1.10.1 → cfinterface-1.10.2}/docs/source/reference/fields/components/field.rst +0 -0
  80. {cfinterface-1.10.1 → cfinterface-1.10.2}/docs/source/reference/fields/components/floatfield.rst +0 -0
  81. {cfinterface-1.10.1 → cfinterface-1.10.2}/docs/source/reference/fields/components/integerfield.rst +0 -0
  82. {cfinterface-1.10.1 → cfinterface-1.10.2}/docs/source/reference/fields/components/literalfield.rst +0 -0
  83. {cfinterface-1.10.1 → cfinterface-1.10.2}/docs/source/reference/fields/index.rst +0 -0
  84. {cfinterface-1.10.1 → cfinterface-1.10.2}/docs/source/reference/line/index.rst +0 -0
  85. {cfinterface-1.10.1 → cfinterface-1.10.2}/docs/source/reference/registers/files/register.rst +0 -0
  86. {cfinterface-1.10.1 → cfinterface-1.10.2}/docs/source/reference/registers/files/registerdata.rst +0 -0
  87. {cfinterface-1.10.1 → cfinterface-1.10.2}/docs/source/reference/registers/files/registerfile.rst +0 -0
  88. {cfinterface-1.10.1 → cfinterface-1.10.2}/docs/source/reference/registers/index.rst +0 -0
  89. {cfinterface-1.10.1 → cfinterface-1.10.2}/docs/source/reference/sections/files/section.rst +0 -0
  90. {cfinterface-1.10.1 → cfinterface-1.10.2}/docs/source/reference/sections/files/sectiondata.rst +0 -0
  91. {cfinterface-1.10.1 → cfinterface-1.10.2}/docs/source/reference/sections/files/sectionfile.rst +0 -0
  92. {cfinterface-1.10.1 → cfinterface-1.10.2}/docs/source/reference/sections/index.rst +0 -0
  93. {cfinterface-1.10.1 → cfinterface-1.10.2}/docs/source/reference/storage/files/storagetype.rst +0 -0
  94. {cfinterface-1.10.1 → cfinterface-1.10.2}/docs/source/reference/storage/index.rst +0 -0
  95. {cfinterface-1.10.1 → cfinterface-1.10.2}/docs/source/reference/tabular/files/tabularparser.rst +0 -0
  96. {cfinterface-1.10.1 → cfinterface-1.10.2}/docs/source/reference/tabular/files/tabularsection.rst +0 -0
  97. {cfinterface-1.10.1 → cfinterface-1.10.2}/docs/source/reference/tabular/index.rst +0 -0
  98. {cfinterface-1.10.1 → cfinterface-1.10.2}/docs/source/reference/versioning/files/versioning.rst +0 -0
  99. {cfinterface-1.10.1 → cfinterface-1.10.2}/docs/source/reference/versioning/index.rst +0 -0
  100. {cfinterface-1.10.1 → cfinterface-1.10.2}/examples/README.rst +0 -0
  101. {cfinterface-1.10.1 → cfinterface-1.10.2}/examples/__init__.py +0 -0
  102. {cfinterface-1.10.1 → cfinterface-1.10.2}/examples/plot_block_file.py +0 -0
  103. {cfinterface-1.10.1 → cfinterface-1.10.2}/examples/plot_register_file.py +0 -0
  104. {cfinterface-1.10.1 → cfinterface-1.10.2}/examples/plot_section_file.py +0 -0
  105. {cfinterface-1.10.1 → cfinterface-1.10.2}/examples/plot_tabular_parsing.py +0 -0
  106. {cfinterface-1.10.1 → cfinterface-1.10.2}/examples/plot_versioned_file.py +0 -0
  107. {cfinterface-1.10.1 → cfinterface-1.10.2}/pyproject.toml +0 -0
  108. {cfinterface-1.10.1 → cfinterface-1.10.2}/tests/__init__.py +0 -0
  109. {cfinterface-1.10.1 → cfinterface-1.10.2}/tests/_utils/__init__.py +0 -0
  110. {cfinterface-1.10.1 → cfinterface-1.10.2}/tests/_utils/test_is_null.py +0 -0
  111. {cfinterface-1.10.1 → cfinterface-1.10.2}/tests/adapters/__init__.py +0 -0
  112. {cfinterface-1.10.1 → cfinterface-1.10.2}/tests/adapters/components/__init__.py +0 -0
  113. {cfinterface-1.10.1 → cfinterface-1.10.2}/tests/adapters/components/test_blockrepository.py +0 -0
  114. {cfinterface-1.10.1 → cfinterface-1.10.2}/tests/adapters/components/test_factory.py +0 -0
  115. {cfinterface-1.10.1 → cfinterface-1.10.2}/tests/adapters/components/test_linerepository.py +0 -0
  116. {cfinterface-1.10.1 → cfinterface-1.10.2}/tests/adapters/components/test_pattern_cache.py +0 -0
  117. {cfinterface-1.10.1 → cfinterface-1.10.2}/tests/adapters/components/test_registerrepository.py +0 -0
  118. {cfinterface-1.10.1 → cfinterface-1.10.2}/tests/adapters/components/test_sectionrepository.py +0 -0
  119. {cfinterface-1.10.1 → cfinterface-1.10.2}/tests/adapters/reading/__init__.py +0 -0
  120. {cfinterface-1.10.1 → cfinterface-1.10.2}/tests/adapters/reading/test_readingrepository.py +0 -0
  121. {cfinterface-1.10.1 → cfinterface-1.10.2}/tests/adapters/writing/__init__.py +0 -0
  122. {cfinterface-1.10.1 → cfinterface-1.10.2}/tests/adapters/writing/test_writingrepository.py +0 -0
  123. {cfinterface-1.10.1 → cfinterface-1.10.2}/tests/components/__init__.py +0 -0
  124. {cfinterface-1.10.1 → cfinterface-1.10.2}/tests/components/conftest.py +0 -0
  125. {cfinterface-1.10.1 → cfinterface-1.10.2}/tests/components/test_block.py +0 -0
  126. {cfinterface-1.10.1 → cfinterface-1.10.2}/tests/components/test_datetimefield.py +0 -0
  127. {cfinterface-1.10.1 → cfinterface-1.10.2}/tests/components/test_defaultblock.py +0 -0
  128. {cfinterface-1.10.1 → cfinterface-1.10.2}/tests/components/test_defaultregister.py +0 -0
  129. {cfinterface-1.10.1 → cfinterface-1.10.2}/tests/components/test_defaultsection.py +0 -0
  130. {cfinterface-1.10.1 → cfinterface-1.10.2}/tests/components/test_field.py +0 -0
  131. {cfinterface-1.10.1 → cfinterface-1.10.2}/tests/components/test_field_hypothesis.py +0 -0
  132. {cfinterface-1.10.1 → cfinterface-1.10.2}/tests/components/test_floatfield.py +0 -0
  133. {cfinterface-1.10.1 → cfinterface-1.10.2}/tests/components/test_floatfield_benchmark.py +0 -0
  134. {cfinterface-1.10.1 → cfinterface-1.10.2}/tests/components/test_integerfield.py +0 -0
  135. {cfinterface-1.10.1 → cfinterface-1.10.2}/tests/components/test_line.py +0 -0
  136. {cfinterface-1.10.1 → cfinterface-1.10.2}/tests/components/test_literalfield.py +0 -0
  137. {cfinterface-1.10.1 → cfinterface-1.10.2}/tests/components/test_register.py +0 -0
  138. {cfinterface-1.10.1 → cfinterface-1.10.2}/tests/components/test_section.py +0 -0
  139. {cfinterface-1.10.1 → cfinterface-1.10.2}/tests/components/test_storage_integration.py +0 -0
  140. {cfinterface-1.10.1 → cfinterface-1.10.2}/tests/components/test_tabular.py +0 -0
  141. {cfinterface-1.10.1 → cfinterface-1.10.2}/tests/components/test_tabular_hypothesis.py +0 -0
  142. {cfinterface-1.10.1 → cfinterface-1.10.2}/tests/conftest.py +0 -0
  143. {cfinterface-1.10.1 → cfinterface-1.10.2}/tests/data/__init__.py +0 -0
  144. {cfinterface-1.10.1 → cfinterface-1.10.2}/tests/data/test_blockdata.py +0 -0
  145. {cfinterface-1.10.1 → cfinterface-1.10.2}/tests/data/test_registerdata.py +0 -0
  146. {cfinterface-1.10.1 → cfinterface-1.10.2}/tests/data/test_sectiondata.py +0 -0
  147. {cfinterface-1.10.1 → cfinterface-1.10.2}/tests/files/__init__.py +0 -0
  148. {cfinterface-1.10.1 → cfinterface-1.10.2}/tests/files/test_blockfile.py +0 -0
  149. {cfinterface-1.10.1 → cfinterface-1.10.2}/tests/files/test_registerfile.py +0 -0
  150. {cfinterface-1.10.1 → cfinterface-1.10.2}/tests/files/test_sectionfile.py +0 -0
  151. {cfinterface-1.10.1 → cfinterface-1.10.2}/tests/mocks/__init__.py +0 -0
  152. {cfinterface-1.10.1 → cfinterface-1.10.2}/tests/mocks/mock_open.py +0 -0
  153. {cfinterface-1.10.1 → cfinterface-1.10.2}/tests/reading/__init__.py +0 -0
  154. {cfinterface-1.10.1 → cfinterface-1.10.2}/tests/reading/test_blockreading.py +0 -0
  155. {cfinterface-1.10.1 → cfinterface-1.10.2}/tests/reading/test_registerreading.py +0 -0
  156. {cfinterface-1.10.1 → cfinterface-1.10.2}/tests/reading/test_sectionreading.py +0 -0
  157. {cfinterface-1.10.1 → cfinterface-1.10.2}/tests/test_storage.py +0 -0
  158. {cfinterface-1.10.1 → cfinterface-1.10.2}/tests/test_storage_deprecation.py +0 -0
  159. {cfinterface-1.10.1 → cfinterface-1.10.2}/tests/test_versioning.py +0 -0
  160. {cfinterface-1.10.1 → cfinterface-1.10.2}/tests/writing/__init__.py +0 -0
  161. {cfinterface-1.10.1 → cfinterface-1.10.2}/tests/writing/test_blockwriting.py +0 -0
  162. {cfinterface-1.10.1 → cfinterface-1.10.2}/tests/writing/test_registerwriting.py +0 -0
  163. {cfinterface-1.10.1 → cfinterface-1.10.2}/tests/writing/test_sectionwriting.py +0 -0
@@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [1.10.2] - 2026-10-14
11
+
12
+ ### Fixed
13
+
14
+ - Type `SectionFile.read()`, `RegisterFile.read()` and `BlockFile.read()` (and their `read_many()`) as returning the calling subclass instead of the base class, so mypy sees the attributes of files such as `Dadger` or `Caso` read through them
15
+
10
16
  ## [1.10.1] - 2026-04-13
11
17
 
12
18
  ### Fixed
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.4
1
+ Metadata-Version: 2.5
2
2
  Name: cfinterface
3
- Version: 1.10.1
3
+ Version: 1.10.2
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.10.1"
9
+ __version__ = "1.10.2"
10
10
 
11
11
  from . import components # noqa
12
12
  from . import data # noqa
@@ -1,5 +1,5 @@
1
1
  import warnings
2
- from typing import IO, TYPE_CHECKING, Any
2
+ from typing import IO, TYPE_CHECKING, Any, TypeVar
3
3
 
4
4
  from cfinterface.components.block import Block
5
5
  from cfinterface.components.defaultblock import DefaultBlock
@@ -12,6 +12,8 @@ from cfinterface.writing.blockwriting import BlockWriting
12
12
  if TYPE_CHECKING:
13
13
  from cfinterface.versioning import VersionMatchResult
14
14
 
15
+ _BlockFileT = TypeVar("_BlockFileT", bound="BlockFile")
16
+
15
17
 
16
18
  class BlockFile:
17
19
  """
@@ -48,12 +50,12 @@ class BlockFile:
48
50
 
49
51
  @classmethod
50
52
  def read(
51
- cls,
53
+ cls: type[_BlockFileT],
52
54
  content: str | bytes,
53
55
  *args: Any,
54
56
  version: str | None = None,
55
57
  **kwargs: Any,
56
- ) -> "BlockFile":
58
+ ) -> _BlockFileT:
57
59
  """Read from a file path or buffer. ``version`` selects a component set
58
60
  from VERSIONS without mutating the class."""
59
61
  components = cls.BLOCKS
@@ -86,11 +88,11 @@ class BlockFile:
86
88
 
87
89
  @classmethod
88
90
  def read_many(
89
- cls,
91
+ cls: type[_BlockFileT],
90
92
  paths: list[str],
91
93
  *,
92
94
  version: str | None = None,
93
- ) -> dict[str, "BlockFile"]:
95
+ ) -> dict[str, _BlockFileT]:
94
96
  """Read multiple files and return a dict keyed by file path.
95
97
 
96
98
  Parameters
@@ -1,5 +1,5 @@
1
1
  import warnings
2
- from typing import IO, TYPE_CHECKING, Any
2
+ from typing import IO, TYPE_CHECKING, Any, TypeVar
3
3
 
4
4
  from cfinterface.components.defaultregister import DefaultRegister
5
5
  from cfinterface.components.register import Register
@@ -12,6 +12,8 @@ from cfinterface.writing.registerwriting import RegisterWriting
12
12
  if TYPE_CHECKING:
13
13
  from cfinterface.versioning import VersionMatchResult
14
14
 
15
+ _RegisterFileT = TypeVar("_RegisterFileT", bound="RegisterFile")
16
+
15
17
 
16
18
  class RegisterFile:
17
19
  """
@@ -65,12 +67,12 @@ class RegisterFile:
65
67
 
66
68
  @classmethod
67
69
  def read(
68
- cls,
70
+ cls: type[_RegisterFileT],
69
71
  content: str | bytes,
70
72
  *args: Any,
71
73
  version: str | None = None,
72
74
  **kwargs: Any,
73
- ) -> "RegisterFile":
75
+ ) -> _RegisterFileT:
74
76
  """Read from a file path or buffer. ``version`` selects a component set
75
77
  from VERSIONS without mutating the class."""
76
78
  components = cls.REGISTERS
@@ -103,11 +105,11 @@ class RegisterFile:
103
105
 
104
106
  @classmethod
105
107
  def read_many(
106
- cls,
108
+ cls: type[_RegisterFileT],
107
109
  paths: list[str],
108
110
  *,
109
111
  version: str | None = None,
110
- ) -> dict[str, "RegisterFile"]:
112
+ ) -> dict[str, _RegisterFileT]:
111
113
  """Read multiple files and return a dict keyed by file path.
112
114
 
113
115
  Parameters
@@ -1,5 +1,5 @@
1
1
  import warnings
2
- from typing import IO, TYPE_CHECKING, Any
2
+ from typing import IO, TYPE_CHECKING, Any, TypeVar
3
3
 
4
4
  from cfinterface.components.defaultsection import DefaultSection
5
5
  from cfinterface.components.section import Section
@@ -12,6 +12,8 @@ from cfinterface.writing.sectionwriting import SectionWriting
12
12
  if TYPE_CHECKING:
13
13
  from cfinterface.versioning import VersionMatchResult
14
14
 
15
+ _SectionFileT = TypeVar("_SectionFileT", bound="SectionFile")
16
+
15
17
 
16
18
  class SectionFile:
17
19
  """
@@ -48,12 +50,12 @@ class SectionFile:
48
50
 
49
51
  @classmethod
50
52
  def read(
51
- cls,
53
+ cls: type[_SectionFileT],
52
54
  content: str | bytes,
53
55
  *args: Any,
54
56
  version: str | None = None,
55
57
  **kwargs: Any,
56
- ) -> "SectionFile":
58
+ ) -> _SectionFileT:
57
59
  """Read from a file path or buffer. ``version`` selects a component set
58
60
  from VERSIONS without mutating the class."""
59
61
  components = cls.SECTIONS
@@ -86,11 +88,11 @@ class SectionFile:
86
88
 
87
89
  @classmethod
88
90
  def read_many(
89
- cls,
91
+ cls: type[_SectionFileT],
90
92
  paths: list[str],
91
93
  *,
92
94
  version: str | None = None,
93
- ) -> dict[str, "SectionFile"]:
95
+ ) -> dict[str, _SectionFileT]:
94
96
  """Read multiple files and return a dict keyed by file path.
95
97
 
96
98
  Parameters
@@ -0,0 +1,38 @@
1
+ from pathlib import Path
2
+
3
+ import pytest
4
+ from mypy import api
5
+
6
+ SUBCLASS_READS = """
7
+ from cfinterface.files.blockfile import BlockFile
8
+ from cfinterface.files.registerfile import RegisterFile
9
+ from cfinterface.files.sectionfile import SectionFile
10
+
11
+
12
+ class MySectionFile(SectionFile):
13
+ pass
14
+
15
+
16
+ class MyRegisterFile(RegisterFile):
17
+ pass
18
+
19
+
20
+ class MyBlockFile(BlockFile):
21
+ pass
22
+
23
+
24
+ section: MySectionFile = MySectionFile.read("file.txt")
25
+ register: MyRegisterFile = MyRegisterFile.read("file.txt")
26
+ block: MyBlockFile = MyBlockFile.read("file.txt")
27
+ sections: dict[str, MySectionFile] = MySectionFile.read_many(["file.txt"])
28
+ registers: dict[str, MyRegisterFile] = MyRegisterFile.read_many(["file.txt"])
29
+ blocks: dict[str, MyBlockFile] = MyBlockFile.read_many(["file.txt"])
30
+ """
31
+
32
+
33
+ @pytest.mark.slow
34
+ def test_read_is_typed_as_returning_the_subclass(tmp_path: Path):
35
+ stdout, stderr, status = api.run(
36
+ ["--cache-dir", str(tmp_path), "-c", SUBCLASS_READS]
37
+ )
38
+ assert status == 0, stdout + stderr
File without changes
File without changes
File without changes