cfinterface 1.5.2__tar.gz → 1.7.0__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 (95) hide show
  1. {cfinterface-1.5.2 → cfinterface-1.7.0}/PKG-INFO +3 -1
  2. {cfinterface-1.5.2 → cfinterface-1.7.0}/cfinterface/__init__.py +1 -1
  3. {cfinterface-1.5.2 → cfinterface-1.7.0}/cfinterface/adapters/reading/repository.py +9 -0
  4. {cfinterface-1.5.2 → cfinterface-1.7.0}/cfinterface/adapters/writing/repository.py +9 -0
  5. {cfinterface-1.5.2 → cfinterface-1.7.0}/cfinterface/components/block.py +2 -0
  6. cfinterface-1.7.0/cfinterface/components/datetimefield.py +96 -0
  7. {cfinterface-1.5.2 → cfinterface-1.7.0}/cfinterface/components/defaultblock.py +2 -0
  8. {cfinterface-1.5.2 → cfinterface-1.7.0}/cfinterface/components/defaultregister.py +2 -0
  9. {cfinterface-1.5.2 → cfinterface-1.7.0}/cfinterface/components/defaultsection.py +2 -0
  10. {cfinterface-1.5.2 → cfinterface-1.7.0}/cfinterface/components/field.py +2 -0
  11. {cfinterface-1.5.2 → cfinterface-1.7.0}/cfinterface/components/floatfield.py +2 -0
  12. {cfinterface-1.5.2 → cfinterface-1.7.0}/cfinterface/components/integerfield.py +2 -0
  13. {cfinterface-1.5.2 → cfinterface-1.7.0}/cfinterface/components/line.py +9 -0
  14. {cfinterface-1.5.2 → cfinterface-1.7.0}/cfinterface/components/literalfield.py +2 -0
  15. {cfinterface-1.5.2 → cfinterface-1.7.0}/cfinterface/components/register.py +2 -0
  16. {cfinterface-1.5.2 → cfinterface-1.7.0}/cfinterface/components/section.py +2 -0
  17. {cfinterface-1.5.2 → cfinterface-1.7.0}/cfinterface/data/blockdata.py +18 -0
  18. {cfinterface-1.5.2 → cfinterface-1.7.0}/cfinterface/data/registerdata.py +20 -0
  19. {cfinterface-1.5.2 → cfinterface-1.7.0}/cfinterface/data/sectiondata.py +20 -0
  20. {cfinterface-1.5.2 → cfinterface-1.7.0}/cfinterface/files/blockfile.py +2 -0
  21. {cfinterface-1.5.2 → cfinterface-1.7.0}/cfinterface/files/registerfile.py +2 -0
  22. {cfinterface-1.5.2 → cfinterface-1.7.0}/cfinterface/files/sectionfile.py +2 -0
  23. {cfinterface-1.5.2 → cfinterface-1.7.0}/cfinterface/reading/blockreading.py +9 -0
  24. {cfinterface-1.5.2 → cfinterface-1.7.0}/cfinterface/reading/registerreading.py +9 -0
  25. {cfinterface-1.5.2 → cfinterface-1.7.0}/cfinterface/reading/sectionreading.py +9 -0
  26. {cfinterface-1.5.2 → cfinterface-1.7.0}/cfinterface/writing/blockwriting.py +6 -0
  27. {cfinterface-1.5.2 → cfinterface-1.7.0}/cfinterface/writing/registerwriting.py +6 -0
  28. {cfinterface-1.5.2 → cfinterface-1.7.0}/cfinterface/writing/sectionwriting.py +6 -0
  29. {cfinterface-1.5.2 → cfinterface-1.7.0}/cfinterface.egg-info/PKG-INFO +3 -1
  30. {cfinterface-1.5.2 → cfinterface-1.7.0}/tests/components/test_datetimefield.py +19 -0
  31. {cfinterface-1.5.2 → cfinterface-1.7.0}/tests/data/test_blockdata.py +9 -0
  32. {cfinterface-1.5.2 → cfinterface-1.7.0}/tests/data/test_registerdata.py +11 -2
  33. {cfinterface-1.5.2 → cfinterface-1.7.0}/tests/data/test_sectiondata.py +9 -0
  34. cfinterface-1.5.2/cfinterface/components/datetimefield.py +0 -66
  35. {cfinterface-1.5.2 → cfinterface-1.7.0}/LICENSE.md +0 -0
  36. {cfinterface-1.5.2 → cfinterface-1.7.0}/README.md +0 -0
  37. {cfinterface-1.5.2 → cfinterface-1.7.0}/cfinterface/_utils/__init__.py +0 -0
  38. {cfinterface-1.5.2 → cfinterface-1.7.0}/cfinterface/adapters/__init__.py +0 -0
  39. {cfinterface-1.5.2 → cfinterface-1.7.0}/cfinterface/adapters/components/__init__.py +0 -0
  40. {cfinterface-1.5.2 → cfinterface-1.7.0}/cfinterface/adapters/components/line/__init__.py +0 -0
  41. {cfinterface-1.5.2 → cfinterface-1.7.0}/cfinterface/adapters/components/line/repository.py +0 -0
  42. {cfinterface-1.5.2 → cfinterface-1.7.0}/cfinterface/adapters/components/repository.py +0 -0
  43. {cfinterface-1.5.2 → cfinterface-1.7.0}/cfinterface/adapters/reading/__init__.py +0 -0
  44. {cfinterface-1.5.2 → cfinterface-1.7.0}/cfinterface/adapters/writing/__init__.py +0 -0
  45. {cfinterface-1.5.2 → cfinterface-1.7.0}/cfinterface/components/__init__.py +0 -0
  46. {cfinterface-1.5.2 → cfinterface-1.7.0}/cfinterface/data/__init__.py +0 -0
  47. {cfinterface-1.5.2 → cfinterface-1.7.0}/cfinterface/files/__init__.py +0 -0
  48. {cfinterface-1.5.2 → cfinterface-1.7.0}/cfinterface/py.typed +0 -0
  49. {cfinterface-1.5.2 → cfinterface-1.7.0}/cfinterface/reading/__init__.py +0 -0
  50. {cfinterface-1.5.2 → cfinterface-1.7.0}/cfinterface/writing/__init__.py +0 -0
  51. {cfinterface-1.5.2 → cfinterface-1.7.0}/cfinterface.egg-info/SOURCES.txt +0 -0
  52. {cfinterface-1.5.2 → cfinterface-1.7.0}/cfinterface.egg-info/dependency_links.txt +0 -0
  53. {cfinterface-1.5.2 → cfinterface-1.7.0}/cfinterface.egg-info/requires.txt +0 -0
  54. {cfinterface-1.5.2 → cfinterface-1.7.0}/cfinterface.egg-info/top_level.txt +0 -0
  55. {cfinterface-1.5.2 → cfinterface-1.7.0}/examples/__init__.py +0 -0
  56. {cfinterface-1.5.2 → cfinterface-1.7.0}/setup.cfg +0 -0
  57. {cfinterface-1.5.2 → cfinterface-1.7.0}/setup.py +0 -0
  58. {cfinterface-1.5.2 → cfinterface-1.7.0}/tests/__init__.py +0 -0
  59. {cfinterface-1.5.2 → cfinterface-1.7.0}/tests/adapters/__init__.py +0 -0
  60. {cfinterface-1.5.2 → cfinterface-1.7.0}/tests/adapters/components/__init__.py +0 -0
  61. {cfinterface-1.5.2 → cfinterface-1.7.0}/tests/adapters/components/test_blockrepository.py +0 -0
  62. {cfinterface-1.5.2 → cfinterface-1.7.0}/tests/adapters/components/test_linerepository.py +0 -0
  63. {cfinterface-1.5.2 → cfinterface-1.7.0}/tests/adapters/components/test_registerrepository.py +0 -0
  64. {cfinterface-1.5.2 → cfinterface-1.7.0}/tests/adapters/components/test_sectionrepository.py +0 -0
  65. {cfinterface-1.5.2 → cfinterface-1.7.0}/tests/adapters/reading/__init__.py +0 -0
  66. {cfinterface-1.5.2 → cfinterface-1.7.0}/tests/adapters/reading/test_readingrepository.py +0 -0
  67. {cfinterface-1.5.2 → cfinterface-1.7.0}/tests/adapters/writing/__init__.py +0 -0
  68. {cfinterface-1.5.2 → cfinterface-1.7.0}/tests/adapters/writing/test_writingrepository.py +0 -0
  69. {cfinterface-1.5.2 → cfinterface-1.7.0}/tests/components/__init__.py +0 -0
  70. {cfinterface-1.5.2 → cfinterface-1.7.0}/tests/components/test_block.py +0 -0
  71. {cfinterface-1.5.2 → cfinterface-1.7.0}/tests/components/test_defaultblock.py +0 -0
  72. {cfinterface-1.5.2 → cfinterface-1.7.0}/tests/components/test_defaultregister.py +0 -0
  73. {cfinterface-1.5.2 → cfinterface-1.7.0}/tests/components/test_defaultsection.py +0 -0
  74. {cfinterface-1.5.2 → cfinterface-1.7.0}/tests/components/test_field.py +0 -0
  75. {cfinterface-1.5.2 → cfinterface-1.7.0}/tests/components/test_floatfield.py +0 -0
  76. {cfinterface-1.5.2 → cfinterface-1.7.0}/tests/components/test_integerfield.py +0 -0
  77. {cfinterface-1.5.2 → cfinterface-1.7.0}/tests/components/test_line.py +0 -0
  78. {cfinterface-1.5.2 → cfinterface-1.7.0}/tests/components/test_literalfield.py +0 -0
  79. {cfinterface-1.5.2 → cfinterface-1.7.0}/tests/components/test_register.py +0 -0
  80. {cfinterface-1.5.2 → cfinterface-1.7.0}/tests/components/test_section.py +0 -0
  81. {cfinterface-1.5.2 → cfinterface-1.7.0}/tests/data/__init__.py +0 -0
  82. {cfinterface-1.5.2 → cfinterface-1.7.0}/tests/files/__init__.py +0 -0
  83. {cfinterface-1.5.2 → cfinterface-1.7.0}/tests/files/test_blockfile.py +0 -0
  84. {cfinterface-1.5.2 → cfinterface-1.7.0}/tests/files/test_registerfile.py +0 -0
  85. {cfinterface-1.5.2 → cfinterface-1.7.0}/tests/files/test_sectionfile.py +0 -0
  86. {cfinterface-1.5.2 → cfinterface-1.7.0}/tests/mocks/__init__.py +0 -0
  87. {cfinterface-1.5.2 → cfinterface-1.7.0}/tests/mocks/mock_open.py +0 -0
  88. {cfinterface-1.5.2 → cfinterface-1.7.0}/tests/reading/__init__.py +0 -0
  89. {cfinterface-1.5.2 → cfinterface-1.7.0}/tests/reading/test_blockreading.py +0 -0
  90. {cfinterface-1.5.2 → cfinterface-1.7.0}/tests/reading/test_registerreading.py +0 -0
  91. {cfinterface-1.5.2 → cfinterface-1.7.0}/tests/reading/test_sectionreading.py +0 -0
  92. {cfinterface-1.5.2 → cfinterface-1.7.0}/tests/writing/__init__.py +0 -0
  93. {cfinterface-1.5.2 → cfinterface-1.7.0}/tests/writing/test_blockwriting.py +0 -0
  94. {cfinterface-1.5.2 → cfinterface-1.7.0}/tests/writing/test_registerwriting.py +0 -0
  95. {cfinterface-1.5.2 → cfinterface-1.7.0}/tests/writing/test_sectionwriting.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: cfinterface
3
- Version: 1.5.2
3
+ Version: 1.7.0
4
4
  Summary: Interface for handling custom formatted files
5
5
  Home-page: https://github.com/rjmalves/cfi
6
6
  Author: Rogerio Alves
@@ -12,6 +12,8 @@ Classifier: Development Status :: 4 - Beta
12
12
  Requires-Python: >=3.8
13
13
  Description-Content-Type: text/markdown
14
14
  License-File: LICENSE.md
15
+ Requires-Dist: numpy
16
+ Requires-Dist: pandas
15
17
 
16
18
  # cfinterface
17
19
 
@@ -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.5.2"
9
+ __version__ = "1.7.0"
10
10
 
11
11
  from . import components # noqa
12
12
  from . import data # noqa
@@ -4,6 +4,9 @@ from io import BytesIO, StringIO
4
4
 
5
5
 
6
6
  class Repository(ABC):
7
+
8
+ __slots__ = ["_content", "_wrap_io"]
9
+
7
10
  def __init__(
8
11
  self, content: Union[str, bytes], wrap_io: bool = False, *args
9
12
  ) -> None:
@@ -36,6 +39,9 @@ class Repository(ABC):
36
39
 
37
40
 
38
41
  class BinaryRepository(Repository):
42
+
43
+ __slots__ = ["_filepointer"]
44
+
39
45
  def __init__(
40
46
  self, content: Union[str, bytes], wrap_io: bool = False, *args
41
47
  ) -> None:
@@ -72,6 +78,9 @@ class BinaryRepository(Repository):
72
78
 
73
79
 
74
80
  class TextualRepository(Repository):
81
+
82
+ __slots__ = ["_filepointer", "_encoding"]
83
+
75
84
  def __init__(
76
85
  self,
77
86
  content: str,
@@ -3,6 +3,9 @@ from abc import ABC, abstractmethod
3
3
 
4
4
 
5
5
  class Repository(ABC):
6
+
7
+ __slots__ = ["_to", "_wrap_io"]
8
+
6
9
  def __init__(self, to: Union[str, IO], *args) -> None:
7
10
  self._to = to
8
11
  self._wrap_io = isinstance(to, str)
@@ -30,6 +33,9 @@ class Repository(ABC):
30
33
 
31
34
 
32
35
  class BinaryRepository(Repository):
36
+
37
+ __slots__ = ["_filepointer"]
38
+
33
39
  def __init__(self, path: str, *args) -> None:
34
40
  super().__init__(path)
35
41
  self._filepointer: BinaryIO = None # type: ignore
@@ -59,6 +65,9 @@ class BinaryRepository(Repository):
59
65
 
60
66
 
61
67
  class TextualRepository(Repository):
68
+
69
+ __slots__ = ["_filepointer", "_encoding"]
70
+
62
71
  def __init__(self, path: str, encoding: str) -> None:
63
72
  super().__init__(path)
64
73
  self._filepointer: TextIO = None # type: ignore
@@ -9,6 +9,8 @@ class Block:
9
9
  for beginning and end and reading states.
10
10
  """
11
11
 
12
+ __slots__ = ["__previous", "__next", "__data"]
13
+
12
14
  BEGIN_PATTERN: Union[str, bytes] = ""
13
15
  END_PATTERN: Union[str, bytes] = ""
14
16
  MAX_LINES = 10000
@@ -0,0 +1,96 @@
1
+ from datetime import datetime
2
+ import pandas as pd # type: ignore
3
+ from typing import Optional, Union, List
4
+
5
+ from cfinterface.components.field import Field
6
+
7
+
8
+ class DatetimeField(Field):
9
+ """
10
+ Class for representing an datetime field for being read from and
11
+ written to a file. The format to read and write the value is given
12
+ by an optional argument.
13
+ """
14
+
15
+ __slots__ = ["__format"]
16
+
17
+ def __init__(
18
+ self,
19
+ size: int = 16,
20
+ starting_position: int = 0,
21
+ format: Union[str, List[str]] = "%Y/%m/%d",
22
+ value: Optional[datetime] = None,
23
+ ) -> None:
24
+ super().__init__(size, starting_position, value)
25
+ self.__format = format
26
+
27
+ # Override
28
+ def _binary_read(self, line: bytes) -> datetime:
29
+ formats = (
30
+ [self.__format]
31
+ if isinstance(self.__format, str)
32
+ else self.__format
33
+ )
34
+ for fmt in formats:
35
+ try:
36
+ return datetime.strptime(
37
+ line[self._starting_position : self._ending_position]
38
+ .decode("utf-8")
39
+ .strip(),
40
+ fmt,
41
+ )
42
+ except ValueError:
43
+ pass
44
+ raise ValueError("Could not read datetime")
45
+
46
+ # Override
47
+ def _textual_read(self, line: str) -> datetime:
48
+ formats = (
49
+ [self.__format]
50
+ if isinstance(self.__format, str)
51
+ else self.__format
52
+ )
53
+ for fmt in formats:
54
+ try:
55
+ return datetime.strptime(
56
+ line[
57
+ self._starting_position : self._ending_position
58
+ ].strip(),
59
+ fmt,
60
+ )
61
+ except ValueError:
62
+ pass
63
+ raise ValueError("Could not read datetime")
64
+
65
+ # Override
66
+ def _binary_write(self) -> bytes:
67
+ if self.value is None or pd.isnull(self.value):
68
+ return b"".ljust(self.size)
69
+ else:
70
+ format = (
71
+ self.__format
72
+ if isinstance(self.__format, str)
73
+ else self.__format[0]
74
+ )
75
+ return self.value.strftime(format).ljust(self.size).encode("utf-8")
76
+
77
+ # Override
78
+ def _textual_write(self) -> str:
79
+ if self.value is None or pd.isnull(self.value):
80
+ value = ""
81
+ else:
82
+ format = (
83
+ self.__format
84
+ if isinstance(self.__format, str)
85
+ else self.__format[0]
86
+ )
87
+ value = self.value.strftime(format)
88
+ return value.ljust(self._size)
89
+
90
+ @property
91
+ def value(self) -> Optional[datetime]:
92
+ return self._value
93
+
94
+ @value.setter
95
+ def value(self, val: datetime):
96
+ self._value = val
@@ -8,6 +8,8 @@ class DefaultBlock(Block):
8
8
  the data from the read line. Mainly used for comments.
9
9
  """
10
10
 
11
+ __slots__ = []
12
+
11
13
  def __eq__(self, o: object) -> bool:
12
14
  if not isinstance(o, DefaultBlock):
13
15
  return False
@@ -8,6 +8,8 @@ class DefaultRegister(Register):
8
8
  the data from the read line. Mainly used for comments.
9
9
  """
10
10
 
11
+ __slots__ = []
12
+
11
13
  def __init__(self, previous=None, next=None, data=None) -> None:
12
14
  super().__init__(previous, next, data)
13
15
 
@@ -8,6 +8,8 @@ class DefaultSection(Section):
8
8
  and is used for representing empty data.
9
9
  """
10
10
 
11
+ __slots__ = []
12
+
11
13
  def __eq__(self, o: object) -> bool:
12
14
  if not isinstance(o, DefaultSection):
13
15
  return False
@@ -8,6 +8,8 @@ class Field:
8
8
  in a file.
9
9
  """
10
10
 
11
+ __slots__ = ["_size", "_starting_position", "_ending_position", "_value"]
12
+
11
13
  T = TypeVar("T", str, bytes)
12
14
 
13
15
  def __init__(
@@ -12,6 +12,8 @@ class FloatField(Field):
12
12
  by 'F' for fixed point notation and 'E' for scientific notation.
13
13
  """
14
14
 
15
+ __slots__ = ["__decimal_digits", "__format", "__sep", "__type"]
16
+
15
17
  TYPES = {
16
18
  2: np.float16,
17
19
  4: np.float32,
@@ -12,6 +12,8 @@ class IntegerField(Field):
12
12
  written to a file.
13
13
  """
14
14
 
15
+ __slots__ = ["__type"]
16
+
15
17
  TYPES = {
16
18
  2: np.int16,
17
19
  4: np.int32,
@@ -13,6 +13,15 @@ class Line:
13
13
  of fields and can be read from or written to a file.
14
14
  """
15
15
 
16
+ __slots__ = [
17
+ "_delimiter",
18
+ "_fields",
19
+ "_values",
20
+ "_storage",
21
+ "_repository",
22
+ "_size",
23
+ ]
24
+
16
25
  def __init__(
17
26
  self,
18
27
  fields: List[Field],
@@ -9,6 +9,8 @@ class LiteralField(Field):
9
9
  written to a file.
10
10
  """
11
11
 
12
+ __slots__ = []
13
+
12
14
  def __init__(
13
15
  self,
14
16
  size: int = 80,
@@ -14,6 +14,8 @@ class Register:
14
14
  which is located at the beginning of the line.
15
15
  """
16
16
 
17
+ __slots__ = ["__previous", "__next", "__data", "__identifier_field"]
18
+
17
19
  IDENTIFIER: Union[str, bytes] = ""
18
20
  IDENTIFIER_DIGITS = 0
19
21
  LINE = Line([])
@@ -7,6 +7,8 @@ class Section:
7
7
  a given order
8
8
  """
9
9
 
10
+ __slots__ = ["__previous", "__next", "__data"]
11
+
10
12
  STORAGE: str = "TEXT"
11
13
 
12
14
  def __init__(
@@ -8,6 +8,8 @@ class BlockData:
8
8
  Class for a storing, managing and accessing data for a block file.
9
9
  """
10
10
 
11
+ __slots__ = ["__root", "__head"]
12
+
11
13
  T = TypeVar("T")
12
14
 
13
15
  def __init__(self, root: Block) -> None:
@@ -148,6 +150,22 @@ class BlockData:
148
150
  else:
149
151
  return filtered_blocks
150
152
 
153
+ def remove_blocks_of_type(self, t: Type[T], **kwargs):
154
+ """
155
+ Removes a set of blocks given a type and an optional group of
156
+ filters, similar to `get_blocks_of_type()`
157
+
158
+ :param t: The block type that is desired
159
+ :type t: Type[T]
160
+ """
161
+ filtered_blocks = self.get_blocks_of_type(t, **kwargs)
162
+ if isinstance(filtered_blocks, Block):
163
+ self.remove(filtered_blocks)
164
+ elif isinstance(filtered_blocks, list):
165
+ for b in filtered_blocks:
166
+ if isinstance(b, Block) and b != self.__root:
167
+ self.remove(b)
168
+
151
169
  @property
152
170
  def first(self) -> Block:
153
171
  return self.__root
@@ -8,6 +8,8 @@ class RegisterData:
8
8
  Class for a storing, managing and accessing data for a register file.
9
9
  """
10
10
 
11
+ __slots__ = ["__root", "__head"]
12
+
11
13
  T = TypeVar("T")
12
14
 
13
15
  def __init__(self, root: Register) -> None:
@@ -147,6 +149,24 @@ class RegisterData:
147
149
  else:
148
150
  return filtered_registers
149
151
 
152
+ def remove_registers_of_type(self, t: Type[T], **kwargs):
153
+ """
154
+ Removes a set of registers given a type and an optional group of
155
+ filters, similar to `get_registers_of_type()`
156
+
157
+ :param t: The register type that is desired
158
+ :type t: Type[T]
159
+ """
160
+ filtered_registers = self.get_registers_of_type(t, **kwargs)
161
+ if isinstance(filtered_registers, t) and isinstance(
162
+ filtered_registers, Register
163
+ ):
164
+ self.remove(filtered_registers)
165
+ elif isinstance(filtered_registers, list):
166
+ for r in filtered_registers:
167
+ if isinstance(r, Register) and r != self.__root:
168
+ self.remove(r)
169
+
150
170
  @property
151
171
  def first(self) -> Register:
152
172
  return self.__root
@@ -8,6 +8,8 @@ class SectionData:
8
8
  Class for a storing, managing and accessing data for a section file.
9
9
  """
10
10
 
11
+ __slots__ = ["__root", "__head"]
12
+
11
13
  T = TypeVar("T")
12
14
 
13
15
  def __init__(self, root: Section) -> None:
@@ -148,6 +150,24 @@ class SectionData:
148
150
  else:
149
151
  return filtered_sections
150
152
 
153
+ def remove_sections_of_type(self, t: Type[T], **kwargs):
154
+ """
155
+ Removes a set of sections given a type and an optional group of
156
+ filters, similar to `get_sections_of_type()`
157
+
158
+ :param t: The section type that is desired
159
+ :type t: Type[T]
160
+ """
161
+ filtered_sections = self.get_sections_of_type(t, **kwargs)
162
+ if isinstance(filtered_sections, t) and isinstance(
163
+ filtered_sections, Section
164
+ ):
165
+ self.remove(filtered_sections)
166
+ elif isinstance(filtered_sections, list):
167
+ for s in filtered_sections:
168
+ if isinstance(s, Section) and s != self.__root:
169
+ self.remove(s)
170
+
151
171
  @property
152
172
  def first(self) -> Section:
153
173
  return self.__root
@@ -13,6 +13,8 @@ class BlockFile:
13
13
  and writing are given by a series of blocks.
14
14
  """
15
15
 
16
+ __slots__ = ["__data", "__storage", "__encoding"]
17
+
16
18
  VERSIONS: Dict[str, List[Type[Block]]] = {}
17
19
  BLOCKS: List[Type[Block]] = []
18
20
  ENCODING = "utf-8"
@@ -13,6 +13,8 @@ class RegisterFile:
13
13
  and writing are given by a series of registers.
14
14
  """
15
15
 
16
+ __slots__ = ["__data", "__storage", "__encoding"]
17
+
16
18
  VERSIONS: Dict[str, List[Type[Register]]] = {}
17
19
  REGISTERS: List[Type[Register]] = []
18
20
  ENCODING = "utf-8"
@@ -13,6 +13,8 @@ class SectionFile:
13
13
  and writing are given by a series of registers.
14
14
  """
15
15
 
16
+ __slots__ = ["__data", "__storage", "__encoding"]
17
+
16
18
  VERSIONS: Dict[str, List[Type[Section]]] = {}
17
19
  SECTIONS: List[Type[Section]] = []
18
20
  ENCODING = "utf-8"
@@ -13,6 +13,15 @@ class BlockReading:
13
13
  Class for reading custom files based on a BlockData structure.
14
14
  """
15
15
 
16
+ __slots__ = [
17
+ "__allowed_blocks",
18
+ "__data",
19
+ "__last_position_filepointer",
20
+ "__storage",
21
+ "__linesize",
22
+ "__repository",
23
+ ]
24
+
16
25
  def __init__(
17
26
  self,
18
27
  allowed_blocks: List[Type[Block]],
@@ -13,6 +13,15 @@ class RegisterReading:
13
13
  Class for reading custom files based on a RegisterData structure.
14
14
  """
15
15
 
16
+ __slots__ = [
17
+ "__allowed_registers",
18
+ "__data",
19
+ "__last_position_filepointer",
20
+ "__storage",
21
+ "__linesize",
22
+ "__repository",
23
+ ]
24
+
16
25
  def __init__(
17
26
  self,
18
27
  allowed_registers: List[Type[Register]],
@@ -13,6 +13,15 @@ class SectionReading:
13
13
  Class for reading custom files based on a SectionData structure.
14
14
  """
15
15
 
16
+ __slots__ = [
17
+ "__sections",
18
+ "__data",
19
+ "__last_position_filepointer",
20
+ "__storage",
21
+ "__linesize",
22
+ "__repository",
23
+ ]
24
+
16
25
  def __init__(
17
26
  self,
18
27
  sections: List[Type[Section]],
@@ -11,6 +11,12 @@ class BlockWriting:
11
11
  Class for writing custom files based on a BlockData structure.
12
12
  """
13
13
 
14
+ __slots__ = [
15
+ "__data",
16
+ "__storage",
17
+ "__repository",
18
+ ]
19
+
14
20
  def __init__(self, data: BlockData, storage: str = "") -> None:
15
21
  self.__data = data
16
22
  self.__storage = storage
@@ -12,6 +12,12 @@ class RegisterWriting:
12
12
  Class for writing custom files based on a RegisterData structure.
13
13
  """
14
14
 
15
+ __slots__ = [
16
+ "__data",
17
+ "__storage",
18
+ "__repository",
19
+ ]
20
+
15
21
  def __init__(self, data: RegisterData, storage: str = "") -> None:
16
22
  self.__data = data
17
23
  self.__storage = storage
@@ -12,6 +12,12 @@ class SectionWriting:
12
12
  Class for writing custom files based on a SectionData structure.
13
13
  """
14
14
 
15
+ __slots__ = [
16
+ "__data",
17
+ "__storage",
18
+ "__repository",
19
+ ]
20
+
15
21
  def __init__(self, data: SectionData, storage: str = "") -> None:
16
22
  self.__data = data
17
23
  self.__storage = storage
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: cfinterface
3
- Version: 1.5.2
3
+ Version: 1.7.0
4
4
  Summary: Interface for handling custom formatted files
5
5
  Home-page: https://github.com/rjmalves/cfi
6
6
  Author: Rogerio Alves
@@ -12,6 +12,8 @@ Classifier: Development Status :: 4 - Beta
12
12
  Requires-Python: >=3.8
13
13
  Description-Content-Type: text/markdown
14
14
  License-File: LICENSE.md
15
+ Requires-Dist: numpy
16
+ Requires-Dist: pandas
15
17
 
16
18
  # cfinterface
17
19
 
@@ -21,6 +21,15 @@ def test_datetimefield_read():
21
21
  assert field.value == datetime.strptime(data, format)
22
22
 
23
23
 
24
+ def test_datetimefield_read_format_list():
25
+ data = "2020/01/10"
26
+ formats = ["%Y-%m-%d", "%Y/%m/%d"]
27
+ field = DatetimeField(10, 0, format=formats)
28
+ line = f"{data}-something-else"
29
+ field.read(line)
30
+ assert field.value == datetime.strptime(data, formats[1])
31
+
32
+
24
33
  def test_datetimefield_write():
25
34
  data = "2020/01/10"
26
35
  format = "%Y/%m/%d"
@@ -31,6 +40,16 @@ def test_datetimefield_write():
31
40
  assert line_before == line_after
32
41
 
33
42
 
43
+ def test_datetimefield_write_format_list():
44
+ data = "2020/01/10"
45
+ formats = ["%Y-%m-%d", "%Y/%m/%d"]
46
+ line_before = f"field-{data}-else"
47
+ date_data = datetime.strptime(data, formats[1])
48
+ field = DatetimeField(10, 6, format=formats, value=date_data)
49
+ line_after = field.write(line_before)
50
+ assert line_before.replace("/", "-") == line_after
51
+
52
+
34
53
  def test_datetimefield_write_empty():
35
54
  field = DatetimeField(5, 0)
36
55
  assert len(field.write("")) == 5
@@ -125,3 +125,12 @@ def test_blockdata_get_blocks_of_type_filter():
125
125
  bd.append(DummyBlock(data=11))
126
126
  assert len(bd.get_blocks_of_type(DummyBlock)) == 3
127
127
  assert bd.get_blocks_of_type(DummyBlock, my_data=10) == b1
128
+
129
+
130
+ def test_blockdata_remove_blocks_of_type_no_filter():
131
+ b1 = DummyBlock(data=10)
132
+ bd = BlockData(b1)
133
+ bd.append(DummyBlock())
134
+ bd.append(DummyBlock(data=11))
135
+ bd.remove_blocks_of_type(DummyBlock)
136
+ assert len(bd) == 1
@@ -108,17 +108,26 @@ def test_registerdata_of_type():
108
108
  assert len([b for b in rd.of_type(DummyRegister)]) == 2
109
109
 
110
110
 
111
- def test_RegisterData_get_registers_of_type_no_filter():
111
+ def test_registerdata_get_registers_of_type_no_filter():
112
112
  r1 = DummyRegister(data=[10])
113
113
  rd = RegisterData(r1)
114
114
  rd.append(Register())
115
115
  assert rd.get_registers_of_type(DummyRegister) == r1
116
116
 
117
117
 
118
- def test_RegisterData_get_registers_of_type_filter():
118
+ def test_registerdata_get_registers_of_type_filter():
119
119
  r1 = DummyRegister(data=[10])
120
120
  rd = RegisterData(r1)
121
121
  rd.append(DummyRegister())
122
122
  rd.append(DummyRegister(data=[11]))
123
123
  assert len(rd.get_registers_of_type(DummyRegister)) == 3
124
124
  assert rd.get_registers_of_type(DummyRegister, my_data=10) == r1
125
+
126
+
127
+ def test_registerdata_remove_registers_of_type_no_filter():
128
+ r1 = DummyRegister(data=[10])
129
+ rd = RegisterData(r1)
130
+ rd.append(DummyRegister())
131
+ rd.append(DummyRegister(data=[11]))
132
+ rd.remove_registers_of_type(DummyRegister)
133
+ assert len(rd) == 1
@@ -122,3 +122,12 @@ def test_sectiondata_get_sections_of_type_filter():
122
122
  bd.append(DummySection(data=11))
123
123
  assert len(bd.get_sections_of_type(DummySection)) == 3
124
124
  assert bd.get_sections_of_type(DummySection, my_data=10) == b1
125
+
126
+
127
+ def test_sectiondata_remove_sections_of_type_no_filter():
128
+ b1 = DummySection(data=10)
129
+ bd = SectionData(b1)
130
+ bd.append(DummySection())
131
+ bd.append(DummySection(data=11))
132
+ bd.remove_sections_of_type(DummySection)
133
+ assert len(bd) == 1
@@ -1,66 +0,0 @@
1
- from datetime import datetime
2
- import pandas as pd # type: ignore
3
- from typing import Optional
4
-
5
- from cfinterface.components.field import Field
6
-
7
-
8
- class DatetimeField(Field):
9
- """
10
- Class for representing an datetime field for being read from and
11
- written to a file. The format to read and write the value is given
12
- by an optional argument.
13
- """
14
-
15
- def __init__(
16
- self,
17
- size: int = 16,
18
- starting_position: int = 0,
19
- format: str = "%Y/%m/%d",
20
- value: Optional[datetime] = None,
21
- ) -> None:
22
- super().__init__(size, starting_position, value)
23
- self.__format = format
24
-
25
- # Override
26
- def _binary_read(self, line: bytes) -> datetime:
27
- return datetime.strptime(
28
- line[self._starting_position : self._ending_position]
29
- .decode("utf-8")
30
- .strip(),
31
- self.__format,
32
- )
33
-
34
- # Override
35
- def _textual_read(self, line: str) -> datetime:
36
- return datetime.strptime(
37
- line[self._starting_position : self._ending_position].strip(),
38
- self.__format,
39
- )
40
-
41
- # Override
42
- def _binary_write(self) -> bytes:
43
- if self.value is None or pd.isnull(self.value):
44
- return b"".ljust(self.size)
45
- else:
46
- return (
47
- self.value.strftime(self.__format)
48
- .ljust(self.size)
49
- .encode("utf-8")
50
- )
51
-
52
- # Override
53
- def _textual_write(self) -> str:
54
- if self.value is None or pd.isnull(self.value):
55
- value = ""
56
- else:
57
- value = self.value.strftime(self.__format)
58
- return value.ljust(self._size)
59
-
60
- @property
61
- def value(self) -> Optional[datetime]:
62
- return self._value
63
-
64
- @value.setter
65
- def value(self, val: datetime):
66
- self._value = val
File without changes
File without changes
File without changes
File without changes