exonware-xwsystem 0.0.1.410__py3-none-any.whl → 0.0.1.411__py3-none-any.whl

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 (246) hide show
  1. exonware/__init__.py +1 -1
  2. exonware/conf.py +1 -1
  3. exonware/xwsystem/__init__.py +2 -2
  4. exonware/xwsystem/caching/__init__.py +1 -1
  5. exonware/xwsystem/caching/base.py +2 -2
  6. exonware/xwsystem/caching/bloom_cache.py +2 -2
  7. exonware/xwsystem/caching/cache_manager.py +1 -1
  8. exonware/xwsystem/caching/conditional.py +2 -2
  9. exonware/xwsystem/caching/contracts.py +1 -1
  10. exonware/xwsystem/caching/decorators.py +2 -2
  11. exonware/xwsystem/caching/defs.py +1 -1
  12. exonware/xwsystem/caching/disk_cache.py +1 -1
  13. exonware/xwsystem/caching/distributed.py +1 -1
  14. exonware/xwsystem/caching/errors.py +1 -1
  15. exonware/xwsystem/caching/events.py +2 -2
  16. exonware/xwsystem/caching/eviction_strategies.py +1 -1
  17. exonware/xwsystem/caching/fluent.py +1 -1
  18. exonware/xwsystem/caching/integrity.py +1 -1
  19. exonware/xwsystem/caching/lfu_cache.py +2 -2
  20. exonware/xwsystem/caching/lfu_optimized.py +3 -3
  21. exonware/xwsystem/caching/lru_cache.py +2 -2
  22. exonware/xwsystem/caching/memory_bounded.py +2 -2
  23. exonware/xwsystem/caching/metrics_exporter.py +2 -2
  24. exonware/xwsystem/caching/observable_cache.py +1 -1
  25. exonware/xwsystem/caching/pluggable_cache.py +2 -2
  26. exonware/xwsystem/caching/rate_limiter.py +1 -1
  27. exonware/xwsystem/caching/read_through.py +2 -2
  28. exonware/xwsystem/caching/secure_cache.py +1 -1
  29. exonware/xwsystem/caching/serializable.py +2 -2
  30. exonware/xwsystem/caching/stats.py +1 -1
  31. exonware/xwsystem/caching/tagging.py +2 -2
  32. exonware/xwsystem/caching/ttl_cache.py +1 -1
  33. exonware/xwsystem/caching/two_tier_cache.py +1 -1
  34. exonware/xwsystem/caching/utils.py +1 -1
  35. exonware/xwsystem/caching/validation.py +1 -1
  36. exonware/xwsystem/caching/warming.py +2 -2
  37. exonware/xwsystem/caching/write_behind.py +2 -2
  38. exonware/xwsystem/cli/__init__.py +1 -1
  39. exonware/xwsystem/cli/args.py +1 -1
  40. exonware/xwsystem/cli/base.py +1 -1
  41. exonware/xwsystem/cli/colors.py +1 -1
  42. exonware/xwsystem/cli/console.py +1 -1
  43. exonware/xwsystem/cli/contracts.py +1 -1
  44. exonware/xwsystem/cli/defs.py +1 -1
  45. exonware/xwsystem/cli/errors.py +1 -1
  46. exonware/xwsystem/cli/progress.py +1 -1
  47. exonware/xwsystem/cli/prompts.py +1 -1
  48. exonware/xwsystem/cli/tables.py +1 -1
  49. exonware/xwsystem/config/__init__.py +1 -1
  50. exonware/xwsystem/config/base.py +2 -2
  51. exonware/xwsystem/config/contracts.py +1 -1
  52. exonware/xwsystem/config/defaults.py +1 -1
  53. exonware/xwsystem/config/defs.py +1 -1
  54. exonware/xwsystem/config/errors.py +2 -2
  55. exonware/xwsystem/config/logging.py +1 -1
  56. exonware/xwsystem/config/logging_setup.py +2 -2
  57. exonware/xwsystem/config/performance.py +1 -1
  58. exonware/xwsystem/http_client/__init__.py +1 -1
  59. exonware/xwsystem/http_client/advanced_client.py +2 -2
  60. exonware/xwsystem/http_client/base.py +2 -2
  61. exonware/xwsystem/http_client/client.py +2 -2
  62. exonware/xwsystem/http_client/contracts.py +1 -1
  63. exonware/xwsystem/http_client/defs.py +1 -1
  64. exonware/xwsystem/http_client/errors.py +2 -2
  65. exonware/xwsystem/io/__init__.py +1 -1
  66. exonware/xwsystem/io/archive/__init__.py +1 -1
  67. exonware/xwsystem/io/archive/archive.py +1 -1
  68. exonware/xwsystem/io/archive/archive_files.py +1 -1
  69. exonware/xwsystem/io/archive/archivers.py +2 -2
  70. exonware/xwsystem/io/archive/base.py +6 -6
  71. exonware/xwsystem/io/archive/codec_integration.py +1 -1
  72. exonware/xwsystem/io/archive/compression.py +1 -1
  73. exonware/xwsystem/io/archive/formats/__init__.py +1 -1
  74. exonware/xwsystem/io/archive/formats/brotli_format.py +6 -3
  75. exonware/xwsystem/io/archive/formats/lz4_format.py +6 -3
  76. exonware/xwsystem/io/archive/formats/rar.py +6 -3
  77. exonware/xwsystem/io/archive/formats/sevenzip.py +6 -3
  78. exonware/xwsystem/io/archive/formats/squashfs_format.py +1 -1
  79. exonware/xwsystem/io/archive/formats/tar.py +1 -1
  80. exonware/xwsystem/io/archive/formats/wim_format.py +6 -3
  81. exonware/xwsystem/io/archive/formats/zip.py +1 -1
  82. exonware/xwsystem/io/archive/formats/zpaq_format.py +1 -1
  83. exonware/xwsystem/io/archive/formats/zstandard.py +6 -3
  84. exonware/xwsystem/io/base.py +1 -1
  85. exonware/xwsystem/io/codec/__init__.py +1 -1
  86. exonware/xwsystem/io/codec/base.py +6 -6
  87. exonware/xwsystem/io/codec/contracts.py +1 -1
  88. exonware/xwsystem/io/codec/registry.py +5 -5
  89. exonware/xwsystem/io/common/__init__.py +1 -1
  90. exonware/xwsystem/io/common/base.py +1 -1
  91. exonware/xwsystem/io/common/lock.py +1 -1
  92. exonware/xwsystem/io/common/watcher.py +1 -1
  93. exonware/xwsystem/io/contracts.py +1 -1
  94. exonware/xwsystem/io/data_operations.py +480 -0
  95. exonware/xwsystem/io/defs.py +1 -1
  96. exonware/xwsystem/io/errors.py +1 -1
  97. exonware/xwsystem/io/facade.py +2 -2
  98. exonware/xwsystem/io/file/__init__.py +1 -1
  99. exonware/xwsystem/io/file/base.py +1 -1
  100. exonware/xwsystem/io/file/conversion.py +1 -1
  101. exonware/xwsystem/io/file/file.py +8 -6
  102. exonware/xwsystem/io/file/paged_source.py +8 -1
  103. exonware/xwsystem/io/file/paging/__init__.py +1 -1
  104. exonware/xwsystem/io/file/paging/byte_paging.py +1 -1
  105. exonware/xwsystem/io/file/paging/line_paging.py +1 -1
  106. exonware/xwsystem/io/file/paging/record_paging.py +1 -1
  107. exonware/xwsystem/io/file/paging/registry.py +4 -4
  108. exonware/xwsystem/io/file/source.py +20 -9
  109. exonware/xwsystem/io/filesystem/__init__.py +1 -1
  110. exonware/xwsystem/io/filesystem/base.py +1 -1
  111. exonware/xwsystem/io/filesystem/local.py +9 -1
  112. exonware/xwsystem/io/folder/__init__.py +1 -1
  113. exonware/xwsystem/io/folder/base.py +1 -1
  114. exonware/xwsystem/io/folder/folder.py +2 -2
  115. exonware/xwsystem/io/serialization/__init__.py +1 -1
  116. exonware/xwsystem/io/serialization/auto_serializer.py +52 -39
  117. exonware/xwsystem/io/serialization/base.py +165 -1
  118. exonware/xwsystem/io/serialization/contracts.py +88 -1
  119. exonware/xwsystem/io/serialization/defs.py +1 -1
  120. exonware/xwsystem/io/serialization/errors.py +1 -1
  121. exonware/xwsystem/io/serialization/flyweight.py +10 -10
  122. exonware/xwsystem/io/serialization/format_detector.py +8 -5
  123. exonware/xwsystem/io/serialization/formats/__init__.py +1 -1
  124. exonware/xwsystem/io/serialization/formats/binary/bson.py +1 -1
  125. exonware/xwsystem/io/serialization/formats/binary/cbor.py +1 -1
  126. exonware/xwsystem/io/serialization/formats/binary/marshal.py +1 -1
  127. exonware/xwsystem/io/serialization/formats/binary/msgpack.py +1 -1
  128. exonware/xwsystem/io/serialization/formats/binary/pickle.py +1 -1
  129. exonware/xwsystem/io/serialization/formats/binary/plistlib.py +1 -1
  130. exonware/xwsystem/io/serialization/formats/database/dbm.py +53 -1
  131. exonware/xwsystem/io/serialization/formats/database/shelve.py +48 -1
  132. exonware/xwsystem/io/serialization/formats/database/sqlite3.py +85 -1
  133. exonware/xwsystem/io/serialization/formats/text/configparser.py +1 -1
  134. exonware/xwsystem/io/serialization/formats/text/csv.py +1 -1
  135. exonware/xwsystem/io/serialization/formats/text/formdata.py +1 -1
  136. exonware/xwsystem/io/serialization/formats/text/json.py +1 -1
  137. exonware/xwsystem/io/serialization/formats/text/json5.py +7 -5
  138. exonware/xwsystem/io/serialization/formats/text/jsonlines.py +229 -19
  139. exonware/xwsystem/io/serialization/formats/text/multipart.py +1 -1
  140. exonware/xwsystem/io/serialization/formats/text/toml.py +19 -3
  141. exonware/xwsystem/io/serialization/formats/text/xml.py +8 -1
  142. exonware/xwsystem/io/serialization/formats/text/yaml.py +52 -2
  143. exonware/xwsystem/io/serialization/registry.py +1 -1
  144. exonware/xwsystem/io/serialization/serializer.py +175 -3
  145. exonware/xwsystem/io/serialization/utils/__init__.py +1 -1
  146. exonware/xwsystem/io/serialization/utils/path_ops.py +1 -1
  147. exonware/xwsystem/io/stream/__init__.py +1 -1
  148. exonware/xwsystem/io/stream/async_operations.py +1 -1
  149. exonware/xwsystem/io/stream/base.py +1 -1
  150. exonware/xwsystem/io/stream/codec_io.py +1 -1
  151. exonware/xwsystem/ipc/async_fabric.py +1 -2
  152. exonware/xwsystem/ipc/base.py +2 -2
  153. exonware/xwsystem/ipc/contracts.py +2 -2
  154. exonware/xwsystem/ipc/defs.py +1 -1
  155. exonware/xwsystem/ipc/errors.py +2 -2
  156. exonware/xwsystem/ipc/pipes.py +2 -2
  157. exonware/xwsystem/ipc/shared_memory.py +2 -2
  158. exonware/xwsystem/monitoring/base.py +2 -2
  159. exonware/xwsystem/monitoring/contracts.py +1 -1
  160. exonware/xwsystem/monitoring/defs.py +1 -1
  161. exonware/xwsystem/monitoring/error_recovery.py +2 -2
  162. exonware/xwsystem/monitoring/errors.py +2 -2
  163. exonware/xwsystem/monitoring/memory_monitor.py +1 -1
  164. exonware/xwsystem/monitoring/performance_manager_generic.py +2 -2
  165. exonware/xwsystem/monitoring/performance_validator.py +1 -1
  166. exonware/xwsystem/monitoring/system_monitor.py +2 -2
  167. exonware/xwsystem/monitoring/tracing.py +2 -2
  168. exonware/xwsystem/monitoring/tracker.py +1 -1
  169. exonware/xwsystem/operations/__init__.py +1 -1
  170. exonware/xwsystem/operations/base.py +1 -1
  171. exonware/xwsystem/operations/defs.py +1 -1
  172. exonware/xwsystem/operations/diff.py +1 -1
  173. exonware/xwsystem/operations/merge.py +1 -1
  174. exonware/xwsystem/operations/patch.py +1 -1
  175. exonware/xwsystem/patterns/base.py +2 -2
  176. exonware/xwsystem/patterns/context_manager.py +2 -2
  177. exonware/xwsystem/patterns/contracts.py +9 -9
  178. exonware/xwsystem/patterns/defs.py +1 -1
  179. exonware/xwsystem/patterns/dynamic_facade.py +8 -8
  180. exonware/xwsystem/patterns/errors.py +5 -5
  181. exonware/xwsystem/patterns/handler_factory.py +6 -6
  182. exonware/xwsystem/patterns/object_pool.py +7 -7
  183. exonware/xwsystem/patterns/registry.py +3 -3
  184. exonware/xwsystem/plugins/__init__.py +1 -1
  185. exonware/xwsystem/plugins/base.py +5 -5
  186. exonware/xwsystem/plugins/contracts.py +5 -5
  187. exonware/xwsystem/plugins/defs.py +1 -1
  188. exonware/xwsystem/plugins/errors.py +4 -4
  189. exonware/xwsystem/runtime/__init__.py +1 -1
  190. exonware/xwsystem/runtime/base.py +6 -6
  191. exonware/xwsystem/runtime/contracts.py +6 -6
  192. exonware/xwsystem/runtime/defs.py +1 -1
  193. exonware/xwsystem/runtime/env.py +2 -2
  194. exonware/xwsystem/runtime/errors.py +1 -1
  195. exonware/xwsystem/runtime/reflection.py +8 -8
  196. exonware/xwsystem/security/auth.py +1 -1
  197. exonware/xwsystem/security/base.py +2 -2
  198. exonware/xwsystem/security/contracts.py +1 -1
  199. exonware/xwsystem/security/crypto.py +2 -2
  200. exonware/xwsystem/security/defs.py +1 -1
  201. exonware/xwsystem/security/errors.py +2 -2
  202. exonware/xwsystem/security/hazmat.py +2 -2
  203. exonware/xwsystem/shared/__init__.py +1 -1
  204. exonware/xwsystem/shared/base.py +1 -1
  205. exonware/xwsystem/shared/contracts.py +1 -1
  206. exonware/xwsystem/shared/defs.py +1 -1
  207. exonware/xwsystem/shared/errors.py +1 -1
  208. exonware/xwsystem/structures/__init__.py +1 -1
  209. exonware/xwsystem/structures/base.py +2 -2
  210. exonware/xwsystem/structures/contracts.py +1 -1
  211. exonware/xwsystem/structures/defs.py +1 -1
  212. exonware/xwsystem/structures/errors.py +2 -2
  213. exonware/xwsystem/threading/async_primitives.py +2 -2
  214. exonware/xwsystem/threading/base.py +2 -2
  215. exonware/xwsystem/threading/contracts.py +1 -1
  216. exonware/xwsystem/threading/defs.py +1 -1
  217. exonware/xwsystem/threading/errors.py +2 -2
  218. exonware/xwsystem/threading/safe_factory.py +6 -6
  219. exonware/xwsystem/utils/base.py +2 -2
  220. exonware/xwsystem/utils/contracts.py +1 -1
  221. exonware/xwsystem/utils/dt/__init__.py +1 -1
  222. exonware/xwsystem/utils/dt/base.py +2 -2
  223. exonware/xwsystem/utils/dt/contracts.py +1 -1
  224. exonware/xwsystem/utils/dt/defs.py +1 -1
  225. exonware/xwsystem/utils/dt/errors.py +2 -2
  226. exonware/xwsystem/utils/dt/formatting.py +1 -1
  227. exonware/xwsystem/utils/dt/humanize.py +2 -2
  228. exonware/xwsystem/utils/dt/parsing.py +1 -1
  229. exonware/xwsystem/utils/dt/timezone_utils.py +1 -1
  230. exonware/xwsystem/utils/errors.py +2 -2
  231. exonware/xwsystem/utils/test_runner.py +1 -1
  232. exonware/xwsystem/utils/utils_contracts.py +1 -1
  233. exonware/xwsystem/validation/__init__.py +1 -1
  234. exonware/xwsystem/validation/base.py +15 -15
  235. exonware/xwsystem/validation/contracts.py +1 -1
  236. exonware/xwsystem/validation/data_validator.py +10 -0
  237. exonware/xwsystem/validation/declarative.py +9 -9
  238. exonware/xwsystem/validation/defs.py +1 -1
  239. exonware/xwsystem/validation/errors.py +2 -2
  240. exonware/xwsystem/validation/fluent_validator.py +4 -4
  241. exonware/xwsystem/version.py +2 -2
  242. {exonware_xwsystem-0.0.1.410.dist-info → exonware_xwsystem-0.0.1.411.dist-info}/METADATA +3 -3
  243. exonware_xwsystem-0.0.1.411.dist-info/RECORD +274 -0
  244. exonware_xwsystem-0.0.1.410.dist-info/RECORD +0 -273
  245. {exonware_xwsystem-0.0.1.410.dist-info → exonware_xwsystem-0.0.1.411.dist-info}/WHEEL +0 -0
  246. {exonware_xwsystem-0.0.1.410.dist-info → exonware_xwsystem-0.0.1.411.dist-info}/licenses/LICENSE +0 -0
@@ -4,7 +4,7 @@
4
4
  Company: eXonware.com
5
5
  Author: Eng. Muhammad AlShehri
6
6
  Email: connect@exonware.com
7
- Version: 0.0.1.410
7
+ Version: 0.0.1.411
8
8
  Generation Date: 30-Oct-2025
9
9
 
10
10
  File-based data source implementation.
@@ -66,12 +66,14 @@ class FileDataSource(IDataSource[Union[bytes, str]]):
66
66
  self._validate_path = validate_path
67
67
 
68
68
  if validate_path:
69
- # Use PathManager for validation if available
69
+ # Use PathValidator for validation if available
70
70
  try:
71
- from ..common.path_manager import PathManager
72
- pm = PathManager()
73
- if not pm.is_safe_path(self._path):
74
- raise ValueError(f"Unsafe path: {self._path}")
71
+ from ...security.path_validator import PathValidator
72
+ # Don't check existence during initialization - file may be created later
73
+ pv = PathValidator(check_existence=False)
74
+ # For write modes, allow creating the file (path doesn't exist yet)
75
+ for_writing = mode and ('w' in mode or 'a' in mode or '+' in mode)
76
+ pv.validate_path(str(self._path), for_writing=for_writing, create_dirs=True)
75
77
  except ImportError:
76
78
  pass
77
79
 
@@ -131,10 +133,19 @@ class FileDataSource(IDataSource[Union[bytes, str]]):
131
133
  if atomic:
132
134
  # Use AtomicFileWriter from common
133
135
  from ..common.atomic import AtomicFileWriter
134
- with AtomicFileWriter(self._path, backup=backup) as writer:
136
+ # Determine mode based on data type and stored mode
137
+ if isinstance(data, bytes):
138
+ # Binary mode
139
+ atomic_mode = 'wb'
140
+ encoding = None
141
+ else:
142
+ # Text mode
143
+ atomic_mode = 'w'
144
+ encoding = options.get('encoding', self._encoding or 'utf-8')
145
+
146
+ with AtomicFileWriter(self._path, mode=atomic_mode, encoding=encoding, backup=backup) as writer:
135
147
  if isinstance(data, str):
136
- encoding = options.get('encoding', self._encoding or 'utf-8')
137
- writer.write(data.encode(encoding))
148
+ writer.write(data)
138
149
  else:
139
150
  writer.write(data)
140
151
  else:
@@ -4,7 +4,7 @@
4
4
  Company: eXonware.com
5
5
  Author: Eng. Muhammad AlShehri
6
6
  Email: connect@exonware.com
7
- Version: 0.0.1.410
7
+ Version: 0.0.1.411
8
8
  Generation Date: 30-Oct-2025
9
9
 
10
10
  Virtual filesystem abstractions.
@@ -4,7 +4,7 @@
4
4
  Company: eXonware.com
5
5
  Author: Eng. Muhammad AlShehri
6
6
  Email: connect@exonware.com
7
- Version: 0.0.1.410
7
+ Version: 0.0.1.411
8
8
  Generation Date: 30-Oct-2025
9
9
 
10
10
  Base classes for virtual filesystem.
@@ -4,7 +4,7 @@
4
4
  Company: eXonware.com
5
5
  Author: Eng. Muhammad AlShehri
6
6
  Email: connect@exonware.com
7
- Version: 0.0.1.410
7
+ Version: 0.0.1.411
8
8
  Generation Date: 30-Oct-2025
9
9
 
10
10
  Local filesystem implementation.
@@ -144,4 +144,12 @@ class LocalFileSystem(IFileSystem):
144
144
  p = self._resolve_path(path)
145
145
  p.parent.mkdir(parents=True, exist_ok=True)
146
146
  p.write_bytes(content)
147
+
148
+ def read(self, path: str) -> bytes:
149
+ """Read file contents."""
150
+ return self.read_bytes(path)
151
+
152
+ def write(self, path: str, content: bytes) -> None:
153
+ """Write file contents."""
154
+ self.write_bytes(path, content)
147
155
 
@@ -4,7 +4,7 @@
4
4
  Company: eXonware.com
5
5
  Author: Eng. Muhammad AlShehri
6
6
  Email: connect@exonware.com
7
- Version: 0.0.1.410
7
+ Version: 0.0.1.411
8
8
  Generation Date: 30-Oct-2025
9
9
 
10
10
  Folder-specific implementations.
@@ -4,7 +4,7 @@
4
4
  Company: eXonware.com
5
5
  Author: Eng. Muhammad AlShehri
6
6
  Email: connect@exonware.com
7
- Version: 0.0.1.410
7
+ Version: 0.0.1.411
8
8
  Generation Date: 30-Oct-2025
9
9
 
10
10
  Base classes for folder operations.
@@ -2,7 +2,7 @@
2
2
  Company: eXonware.com
3
3
  Author: Eng. Muhammad AlShehri
4
4
  Email: connect@exonware.com
5
- Version: 0.0.1.410
5
+ Version: 0.0.1.411
6
6
  Generation Date: September 04, 2025
7
7
 
8
8
  XWFolder - Concrete implementation of folder operations.
@@ -65,7 +65,7 @@ class XWFolder(AFolder):
65
65
  def create(self, parents: bool = True, exist_ok: bool = True) -> bool:
66
66
  """Create directory with validation."""
67
67
  if self.validate_paths:
68
- self._path_validator.validate_path(self.dir_path)
68
+ self._path_validator.validate_path(self.dir_path, for_writing=True, create_dirs=parents)
69
69
 
70
70
  with performance_monitor("directory_create"):
71
71
  try:
@@ -2,7 +2,7 @@
2
2
  Company: eXonware.com
3
3
  Author: Eng. Muhammad AlShehri
4
4
  Email: connect@exonware.com
5
- Version: 0.0.1.410
5
+ Version: 0.0.1.411
6
6
  Generation Date: November 2, 2025
7
7
 
8
8
  Serialization module - 29+ serialization formats with I→A→XW pattern.
@@ -3,14 +3,14 @@
3
3
  Company: eXonware.com
4
4
  Author: Eng. Muhammad AlShehri
5
5
  Email: connect@exonware.com
6
- Version: 0.0.1.410
6
+ Version: 0.0.1.411
7
7
  Generation Date: September 04, 2025
8
8
 
9
9
  Automatic serializer that detects format and delegates to appropriate serializer.
10
10
  """
11
11
 
12
12
  from pathlib import Path
13
- from typing import Any, Optional, Type, Union
13
+ from typing import Any, Optional, Union
14
14
 
15
15
  from .format_detector import FormatDetector, detect_format
16
16
  from .contracts import ISerialization
@@ -39,7 +39,7 @@ class AutoSerializer:
39
39
  self._serializer_cache: dict[str, ISerialization] = {}
40
40
  self._default_format = default_format
41
41
 
42
- def _get_serializer_class(self, format_name: str) -> Type[ISerialization]:
42
+ def _get_serializer_class(self, format_name: str) -> type[ISerialization]:
43
43
  """
44
44
  Get serializer class for format name.
45
45
 
@@ -52,36 +52,45 @@ class AutoSerializer:
52
52
  Raises:
53
53
  ImportError: If format not available
54
54
  """
55
- # Dynamic import to avoid circular dependencies
55
+ # Dynamic import to avoid circular dependencies.
56
+ # Root cause fix: import concrete serializers from the canonical
57
+ # xwsystem.io.serialization.formats packages instead of a parallel
58
+ # exonware.xwsystem.serialization namespace (which should not exist).
56
59
  module_map = {
57
- 'JSON': ('json', 'JsonSerializer'),
58
- 'YAML': ('yaml', 'YamlSerializer'),
59
- 'TOML': ('toml', 'TomlSerializer'),
60
- 'XML': ('xml', 'XmlSerializer'),
61
- 'CSV': ('csv', 'CsvSerializer'),
62
- 'ConfigParser': ('configparser', 'ConfigParserSerializer'),
63
- 'FormData': ('formdata', 'FormDataSerializer'),
64
- 'Multipart': ('multipart', 'MultipartSerializer'),
65
-
66
- # Binary formats
67
- 'BSON': ('bson', 'BsonSerializer'),
68
- 'MessagePack': ('msgpack', 'MsgPackSerializer'),
69
- 'CBOR': ('cbor', 'CborSerializer'),
70
- 'Pickle': ('pickle', 'PickleSerializer'),
71
- 'Marshal': ('marshal', 'MarshalSerializer'),
72
- 'SQLite3': ('sqlite3', 'Sqlite3Serializer'),
73
- 'DBM': ('dbm', 'DbmSerializer'),
74
- 'Shelve': ('shelve', 'ShelveSerializer'),
75
- 'Plistlib': ('plistlib', 'PlistSerializer'),
76
-
77
- # Schema-based formats
78
- 'Avro': ('avro', 'AvroSerializer'),
79
- 'Protobuf': ('protobuf', 'ProtobufSerializer'),
80
- 'Thrift': ('thrift', 'ThriftSerializer'),
81
- 'Parquet': ('parquet', 'ParquetSerializer'),
82
- 'ORC': ('orc', 'OrcSerializer'),
83
- 'CapnProto': ('capnproto', 'CapnProtoSerializer'),
84
- 'FlatBuffers': ('flatbuffers', 'FlatBuffersSerializer'),
60
+ # Text formats
61
+ 'JSON': ('io.serialization.formats.text.json', 'JsonSerializer'),
62
+ 'JSONL': ('io.serialization.formats.text.jsonlines', 'JsonLinesSerializer'),
63
+ 'NDJSON': ('io.serialization.formats.text.jsonlines', 'JsonLinesSerializer'),
64
+ 'YAML': ('io.serialization.formats.text.yaml', 'YamlSerializer'),
65
+ 'TOML': ('io.serialization.formats.text.toml', 'TomlSerializer'),
66
+ 'XML': ('io.serialization.formats.text.xml', 'XmlSerializer'),
67
+ 'CSV': ('io.serialization.formats.text.csv', 'CsvSerializer'),
68
+ 'ConfigParser': ('io.serialization.formats.text.configparser', 'ConfigParserSerializer'),
69
+ 'FormData': ('io.serialization.formats.text.formdata', 'FormDataSerializer'),
70
+ 'Multipart': ('io.serialization.formats.text.multipart', 'MultipartSerializer'),
71
+
72
+ # Binary / database formats
73
+ 'BSON': ('io.serialization.formats.binary.bson', 'BsonSerializer'),
74
+ 'MessagePack': ('io.serialization.formats.binary.msgpack', 'MsgPackSerializer'),
75
+ 'CBOR': ('io.serialization.formats.binary.cbor', 'CborSerializer'),
76
+ 'Pickle': ('io.serialization.formats.binary.pickle', 'PickleSerializer'),
77
+ 'Marshal': ('io.serialization.formats.binary.marshal', 'MarshalSerializer'),
78
+ 'SQLite3': ('io.serialization.formats.database.sqlite3', 'Sqlite3Serializer'),
79
+ 'DBM': ('io.serialization.formats.database.dbm', 'DbmSerializer'),
80
+ 'Shelve': ('io.serialization.formats.database.shelve', 'ShelveSerializer'),
81
+ 'Plistlib': ('io.serialization.formats.binary.plistlib', 'PlistSerializer'),
82
+
83
+ # Schema-based / advanced formats (placeholders for future modules)
84
+ # These entries intentionally point to non-existent modules today.
85
+ # The lazy installation system will handle installing/adding them
86
+ # when the corresponding format implementations are introduced.
87
+ 'Avro': ('io.serialization.formats.schema.avro', 'AvroSerializer'),
88
+ 'Protobuf': ('io.serialization.formats.schema.protobuf', 'ProtobufSerializer'),
89
+ 'Thrift': ('io.serialization.formats.schema.thrift', 'ThriftSerializer'),
90
+ 'Parquet': ('io.serialization.formats.scientific.parquet', 'ParquetSerializer'),
91
+ 'ORC': ('io.serialization.formats.scientific.orc', 'OrcSerializer'),
92
+ 'CapnProto': ('io.serialization.formats.schema.capnproto', 'CapnProtoSerializer'),
93
+ 'FlatBuffers': ('io.serialization.formats.schema.flatbuffers', 'FlatBuffersSerializer'),
85
94
  }
86
95
 
87
96
  if format_name not in module_map:
@@ -90,9 +99,9 @@ class AutoSerializer:
90
99
  module_name, class_name = module_map[format_name]
91
100
 
92
101
  try:
93
- # Import from current package
94
- module = __import__(f'exonware.xwsystem.serialization.{module_name}',
95
- fromlist=[class_name])
102
+ # Import from canonical xwsystem.io serialization path
103
+ module = __import__(f'exonware.xwsystem.{module_name}',
104
+ fromlist=[class_name])
96
105
  return getattr(module, class_name)
97
106
  except (ImportError, AttributeError) as e:
98
107
  # Lazy installation system will handle missing dependencies
@@ -119,7 +128,8 @@ class AutoSerializer:
119
128
  self,
120
129
  data: Any,
121
130
  file_path: Optional[Union[str, Path]] = None,
122
- format_hint: Optional[str] = None
131
+ format_hint: Optional[str] = None,
132
+ **opts
123
133
  ) -> Union[str, bytes]:
124
134
  """
125
135
  Auto-detect format and serialize data.
@@ -128,6 +138,7 @@ class AutoSerializer:
128
138
  data: Data to serialize
129
139
  file_path: Optional file path for format detection
130
140
  format_hint: Optional format hint to use
141
+ **opts: Additional serializer-specific options (pretty, indent, etc.)
131
142
 
132
143
  Returns:
133
144
  Serialized data
@@ -145,7 +156,7 @@ class AutoSerializer:
145
156
  logger.debug(f"Using default format: {format_name}")
146
157
 
147
158
  serializer = self._get_serializer(format_name)
148
- return serializer.dumps(data)
159
+ return serializer.dumps(data, **opts)
149
160
 
150
161
  def detect_and_deserialize(
151
162
  self,
@@ -362,7 +373,8 @@ _global_auto_serializer = AutoSerializer()
362
373
  def auto_serialize(
363
374
  data: Any,
364
375
  file_path: Optional[Union[str, Path]] = None,
365
- format_hint: Optional[str] = None
376
+ format_hint: Optional[str] = None,
377
+ **opts
366
378
  ) -> Union[str, bytes]:
367
379
  """
368
380
  Convenience function for auto-serialization.
@@ -371,11 +383,12 @@ def auto_serialize(
371
383
  data: Data to serialize
372
384
  file_path: Optional file path for format detection
373
385
  format_hint: Optional format hint
386
+ **opts: Additional serializer options
374
387
 
375
388
  Returns:
376
389
  Serialized data
377
390
  """
378
- return _global_auto_serializer.detect_and_serialize(data, file_path, format_hint)
391
+ return _global_auto_serializer.detect_and_serialize(data, file_path, format_hint, **opts)
379
392
 
380
393
  def auto_deserialize(
381
394
  data: Union[str, bytes],
@@ -2,7 +2,7 @@
2
2
  Company: eXonware.com
3
3
  Author: Eng. Muhammad AlShehri
4
4
  Email: connect@exonware.com
5
- Version: 0.0.1.410
5
+ Version: 0.0.1.411
6
6
  Generation Date: November 2, 2025
7
7
 
8
8
  Serialization base classes - ASerialization abstract base.
@@ -275,6 +275,27 @@ class ASerialization(ACodec[Any, Union[bytes, str]], ISerialization):
275
275
  True if lazy loading is supported
276
276
  """
277
277
  return False
278
+
279
+ @property
280
+ def supports_record_streaming(self) -> bool:
281
+ """
282
+ Whether this serializer exposes record-level streaming operations
283
+ (stream_read_record / stream_update_record).
284
+
285
+ Default: False. Override in subclasses that provide efficient record
286
+ streaming on top of their underlying format.
287
+ """
288
+ return False
289
+
290
+ @property
291
+ def supports_record_paging(self) -> bool:
292
+ """
293
+ Whether this serializer supports efficient record-level paging.
294
+
295
+ Default: False. Override in subclasses that can page records without
296
+ loading the entire dataset.
297
+ """
298
+ return False
278
299
 
279
300
  # ========================================================================
280
301
  # FILE I/O METHODS (Default implementations using encode/decode)
@@ -373,6 +394,149 @@ class ASerialization(ACodec[Any, Union[bytes, str]], ISerialization):
373
394
  format_name=self.format_name,
374
395
  original_error=e
375
396
  )
397
+
398
+ # ========================================================================
399
+ # RECORD-LEVEL OPERATIONS (Generic defaults – can be overridden)
400
+ # ========================================================================
401
+
402
+ def stream_read_record(
403
+ self,
404
+ file_path: Union[str, Path],
405
+ match: callable,
406
+ projection: Optional[list[Any]] = None,
407
+ **options: Any,
408
+ ) -> Any:
409
+ """
410
+ Default record-level read:
411
+ - Load the entire file via load_file().
412
+ - If top-level is a list, scan until match(record) is True.
413
+ - Apply optional projection and return the first matching record.
414
+
415
+ This is format-agnostic but may be expensive for huge files. Formats
416
+ that support true streaming should override this method.
417
+ """
418
+ data = self.load_file(file_path, **options)
419
+
420
+ if isinstance(data, list):
421
+ for record in data:
422
+ if match(record):
423
+ return self._apply_projection(record, projection)
424
+
425
+ # Fallback: treat entire object as a single "record"
426
+ if match(data):
427
+ return self._apply_projection(data, projection)
428
+
429
+ raise KeyError("No matching record found")
430
+
431
+ def stream_update_record(
432
+ self,
433
+ file_path: Union[str, Path],
434
+ match: callable,
435
+ updater: callable,
436
+ *,
437
+ atomic: bool = True,
438
+ **options: Any,
439
+ ) -> int:
440
+ """
441
+ Default record-level update:
442
+ - Load entire file via load_file().
443
+ - If top-level is a list, apply updater() to matching records.
444
+ - Save the modified data back via save_file().
445
+
446
+ This is generic and honours the serializer's existing atomic/write
447
+ behavior, but may be expensive for huge files. Formats that support
448
+ streaming/partial updates should override this method.
449
+ """
450
+ data = self.load_file(file_path, **options)
451
+ updated = 0
452
+
453
+ if isinstance(data, list):
454
+ new_records: list[Any] = []
455
+ for record in data:
456
+ if match(record):
457
+ record = updater(record)
458
+ updated += 1
459
+ new_records.append(record)
460
+ data = new_records
461
+ else:
462
+ if match(data):
463
+ data = updater(data)
464
+ updated = 1
465
+
466
+ # Delegate to existing save_file() which may already be atomic.
467
+ self.save_file(data, file_path, **options)
468
+ return updated
469
+
470
+ def get_record_page(
471
+ self,
472
+ file_path: Union[str, Path],
473
+ page_number: int,
474
+ page_size: int,
475
+ **options: Any,
476
+ ) -> list[Any]:
477
+ """
478
+ Default record-level paging:
479
+ - Load entire file via load_file().
480
+ - If top-level is a list, return a slice corresponding to the requested page.
481
+
482
+ Formats that support indexed or streaming paging should override this
483
+ method for better performance on very large datasets.
484
+ """
485
+ if page_number < 1 or page_size <= 0:
486
+ raise ValueError("Invalid page_number or page_size")
487
+
488
+ data = self.load_file(file_path, **options)
489
+
490
+ if isinstance(data, list):
491
+ start = (page_number - 1) * page_size
492
+ end = start + page_size
493
+ return data[start:end]
494
+
495
+ # Non-list data: treat as a single record page
496
+ if page_number == 1 and page_size > 0:
497
+ return [data]
498
+
499
+ return []
500
+
501
+ def get_record_by_id(
502
+ self,
503
+ file_path: Union[str, Path],
504
+ id_value: Any,
505
+ *,
506
+ id_field: str = "id",
507
+ **options: Any,
508
+ ) -> Any:
509
+ """
510
+ Default record lookup by id:
511
+ - Load entire file via load_file().
512
+ - If top-level is a list of dict-like records, scan for record[id_field].
513
+ """
514
+ data = self.load_file(file_path, **options)
515
+
516
+ if isinstance(data, list):
517
+ for record in data:
518
+ if isinstance(record, dict) and record.get(id_field) == id_value:
519
+ return record
520
+
521
+ # Single-record fallback
522
+ if isinstance(data, dict) and data.get(id_field) == id_value:
523
+ return data
524
+
525
+ raise KeyError(f"Record with {id_field}={id_value!r} not found")
526
+
527
+ # Small helper for projection handling
528
+ def _apply_projection(self, record: Any, projection: Optional[list[Any]]) -> Any:
529
+ if not projection:
530
+ return record
531
+ current = record
532
+ for key in projection:
533
+ if isinstance(current, dict) and isinstance(key, str):
534
+ current = current[key]
535
+ elif isinstance(current, list) and isinstance(key, int):
536
+ current = current[key]
537
+ else:
538
+ raise KeyError(key)
539
+ return current
376
540
 
377
541
  # ========================================================================
378
542
  # VALIDATION METHODS (Default implementations)
@@ -2,7 +2,7 @@
2
2
  Company: eXonware.com
3
3
  Author: Eng. Muhammad AlShehri
4
4
  Email: connect@exonware.com
5
- Version: 0.0.1.410
5
+ Version: 0.0.1.411
6
6
  Generation Date: November 2, 2025
7
7
 
8
8
  Serialization contracts - ISerialization interface extending ICodec.
@@ -435,3 +435,90 @@ class ISerialization(ICodec[Any, Union[bytes, str]]):
435
435
  """
436
436
  pass
437
437
 
438
+ # ========================================================================
439
+ # RECORD-LEVEL OPERATIONS (Optional, generic defaults in ASerialization)
440
+ # ========================================================================
441
+
442
+ def stream_read_record(
443
+ self,
444
+ file_path: Union[str, Path],
445
+ match: callable,
446
+ projection: Optional[list[Any]] = None,
447
+ **options: Any,
448
+ ) -> Any:
449
+ """
450
+ Stream-style read of a single logical record from a file.
451
+
452
+ Semantics:
453
+ - Treat the underlying representation as a sequence of logical records
454
+ (e.g., list elements, table rows, NDJSON records).
455
+ - Return the first record that satisfies `match(record)`.
456
+ - If `projection` is provided, return only that sub-structure.
457
+
458
+ Concrete serializers may override this for efficient, true streaming
459
+ (e.g., NDJSON line-by-line). The default implementation in ASerialization
460
+ is allowed to load the full file and scan in memory.
461
+ """
462
+ raise NotImplementedError
463
+
464
+ def stream_update_record(
465
+ self,
466
+ file_path: Union[str, Path],
467
+ match: callable,
468
+ updater: callable,
469
+ *,
470
+ atomic: bool = True,
471
+ **options: Any,
472
+ ) -> int:
473
+ """
474
+ Stream-style update of logical records in a file.
475
+
476
+ Semantics:
477
+ - Apply `updater(record)` to each record for which `match(record)` is True.
478
+ - When `atomic=True`, must preserve atomicity guarantees (temp file +
479
+ replace, or equivalent) provided by the underlying serializer/I/O.
480
+ - Returns the number of updated records.
481
+
482
+ Concrete serializers may override this to avoid loading the full file.
483
+ The default implementation in ASerialization may be full-load.
484
+ """
485
+ raise NotImplementedError
486
+
487
+ def get_record_page(
488
+ self,
489
+ file_path: Union[str, Path],
490
+ page_number: int,
491
+ page_size: int,
492
+ **options: Any,
493
+ ) -> list[Any]:
494
+ """
495
+ Retrieve a logical page of records from a file.
496
+
497
+ Semantics:
498
+ - page_number is 1-based.
499
+ - page_size is the number of records.
500
+ - Returns a list of native records.
501
+
502
+ Concrete serializers may override this to use indexes or streaming.
503
+ The default implementation in ASerialization may load the entire file
504
+ and slice a top-level list.
505
+ """
506
+ raise NotImplementedError
507
+
508
+ def get_record_by_id(
509
+ self,
510
+ file_path: Union[str, Path],
511
+ id_value: Any,
512
+ *,
513
+ id_field: str = "id",
514
+ **options: Any,
515
+ ) -> Any:
516
+ """
517
+ Retrieve a logical record by identifier (e.g., record[id_field] == id_value).
518
+
519
+ Concrete serializers may override this to use an index or format-specific
520
+ mechanisms. The default implementation in ASerialization may perform a
521
+ linear scan over a top-level list.
522
+ """
523
+ raise NotImplementedError
524
+
@@ -4,7 +4,7 @@
4
4
  Company: eXonware.com
5
5
  Author: Eng. Muhammad AlShehri
6
6
  Email: connect@exonware.com
7
- Version: 0.0.1.410
7
+ Version: 0.0.1.411
8
8
  Generation Date: 07-Sep-2025
9
9
 
10
10
  Serialization types and enums for XWSystem.
@@ -3,7 +3,7 @@
3
3
  Company: eXonware.com
4
4
  Author: Eng. Muhammad AlShehri
5
5
  Email: connect@exonware.com
6
- Version: 0.0.1.410
6
+ Version: 0.0.1.411
7
7
  Generation Date: September 04, 2025
8
8
 
9
9
  Error classes for XWSystem serialization module.