exonware-xwsystem 0.1.0.1__py3-none-any.whl → 0.1.0.3__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 (341) hide show
  1. exonware/__init__.py +2 -1
  2. exonware/conf.py +2 -2
  3. exonware/xwsystem/__init__.py +115 -43
  4. exonware/xwsystem/base.py +30 -0
  5. exonware/xwsystem/caching/__init__.py +39 -13
  6. exonware/xwsystem/caching/base.py +24 -6
  7. exonware/xwsystem/caching/bloom_cache.py +2 -2
  8. exonware/xwsystem/caching/cache_manager.py +2 -1
  9. exonware/xwsystem/caching/conditional.py +2 -2
  10. exonware/xwsystem/caching/contracts.py +85 -139
  11. exonware/xwsystem/caching/decorators.py +6 -19
  12. exonware/xwsystem/caching/defs.py +2 -1
  13. exonware/xwsystem/caching/disk_cache.py +2 -1
  14. exonware/xwsystem/caching/distributed.py +2 -1
  15. exonware/xwsystem/caching/errors.py +2 -1
  16. exonware/xwsystem/caching/events.py +110 -27
  17. exonware/xwsystem/caching/eviction_strategies.py +2 -2
  18. exonware/xwsystem/caching/external_caching_python.py +701 -0
  19. exonware/xwsystem/caching/facade.py +253 -0
  20. exonware/xwsystem/caching/factory.py +300 -0
  21. exonware/xwsystem/caching/fluent.py +14 -12
  22. exonware/xwsystem/caching/integrity.py +21 -6
  23. exonware/xwsystem/caching/lfu_cache.py +2 -1
  24. exonware/xwsystem/caching/lfu_optimized.py +18 -6
  25. exonware/xwsystem/caching/lru_cache.py +7 -4
  26. exonware/xwsystem/caching/memory_bounded.py +2 -2
  27. exonware/xwsystem/caching/metrics_exporter.py +2 -2
  28. exonware/xwsystem/caching/observable_cache.py +2 -2
  29. exonware/xwsystem/caching/pluggable_cache.py +2 -2
  30. exonware/xwsystem/caching/rate_limiter.py +2 -2
  31. exonware/xwsystem/caching/read_through.py +2 -2
  32. exonware/xwsystem/caching/secure_cache.py +81 -28
  33. exonware/xwsystem/caching/serializable.py +9 -7
  34. exonware/xwsystem/caching/stats.py +2 -2
  35. exonware/xwsystem/caching/tagging.py +2 -2
  36. exonware/xwsystem/caching/ttl_cache.py +4 -3
  37. exonware/xwsystem/caching/two_tier_cache.py +6 -3
  38. exonware/xwsystem/caching/utils.py +30 -12
  39. exonware/xwsystem/caching/validation.py +2 -2
  40. exonware/xwsystem/caching/warming.py +6 -3
  41. exonware/xwsystem/caching/write_behind.py +15 -6
  42. exonware/xwsystem/config/__init__.py +11 -17
  43. exonware/xwsystem/config/base.py +5 -5
  44. exonware/xwsystem/config/contracts.py +93 -153
  45. exonware/xwsystem/config/defaults.py +3 -2
  46. exonware/xwsystem/config/defs.py +3 -2
  47. exonware/xwsystem/config/errors.py +2 -5
  48. exonware/xwsystem/config/logging.py +12 -8
  49. exonware/xwsystem/config/logging_setup.py +3 -2
  50. exonware/xwsystem/config/performance.py +1 -46
  51. exonware/xwsystem/config/performance_modes.py +9 -8
  52. exonware/xwsystem/config/version_manager.py +1 -0
  53. exonware/xwsystem/config.py +27 -0
  54. exonware/xwsystem/console/__init__.py +53 -0
  55. exonware/xwsystem/console/base.py +133 -0
  56. exonware/xwsystem/console/cli/__init__.py +61 -0
  57. exonware/xwsystem/{cli → console/cli}/args.py +27 -24
  58. exonware/xwsystem/{cli → console/cli}/base.py +18 -87
  59. exonware/xwsystem/{cli → console/cli}/colors.py +15 -13
  60. exonware/xwsystem/console/cli/console.py +98 -0
  61. exonware/xwsystem/{cli → console/cli}/contracts.py +51 -69
  62. exonware/xwsystem/console/cli/defs.py +87 -0
  63. exonware/xwsystem/console/cli/encoding.py +69 -0
  64. exonware/xwsystem/{cli → console/cli}/errors.py +8 -3
  65. exonware/xwsystem/console/cli/event_logger.py +166 -0
  66. exonware/xwsystem/{cli → console/cli}/progress.py +25 -21
  67. exonware/xwsystem/{cli → console/cli}/prompts.py +3 -2
  68. exonware/xwsystem/{cli → console/cli}/tables.py +27 -24
  69. exonware/xwsystem/console/contracts.py +113 -0
  70. exonware/xwsystem/console/defs.py +154 -0
  71. exonware/xwsystem/console/errors.py +34 -0
  72. exonware/xwsystem/console/event_logger.py +385 -0
  73. exonware/xwsystem/console/writer.py +132 -0
  74. exonware/xwsystem/contracts.py +28 -0
  75. exonware/xwsystem/data_structures/__init__.py +23 -0
  76. exonware/xwsystem/data_structures/trie.py +34 -0
  77. exonware/xwsystem/data_structures/union_find.py +144 -0
  78. exonware/xwsystem/defs.py +17 -0
  79. exonware/xwsystem/errors.py +23 -0
  80. exonware/xwsystem/facade.py +62 -0
  81. exonware/xwsystem/http_client/__init__.py +22 -1
  82. exonware/xwsystem/http_client/advanced_client.py +8 -5
  83. exonware/xwsystem/http_client/base.py +3 -2
  84. exonware/xwsystem/http_client/client.py +7 -4
  85. exonware/xwsystem/http_client/contracts.py +42 -56
  86. exonware/xwsystem/http_client/defs.py +2 -1
  87. exonware/xwsystem/http_client/errors.py +2 -1
  88. exonware/xwsystem/http_client/facade.py +156 -0
  89. exonware/xwsystem/io/__init__.py +22 -3
  90. exonware/xwsystem/io/archive/__init__.py +8 -2
  91. exonware/xwsystem/io/archive/archive.py +1 -1
  92. exonware/xwsystem/io/archive/archive_files.py +4 -7
  93. exonware/xwsystem/io/archive/archivers.py +120 -10
  94. exonware/xwsystem/io/archive/base.py +4 -5
  95. exonware/xwsystem/io/archive/codec_integration.py +1 -2
  96. exonware/xwsystem/io/archive/compression.py +1 -2
  97. exonware/xwsystem/io/archive/facade.py +263 -0
  98. exonware/xwsystem/io/archive/formats/__init__.py +2 -3
  99. exonware/xwsystem/io/archive/formats/brotli_format.py +20 -7
  100. exonware/xwsystem/io/archive/formats/lz4_format.py +20 -7
  101. exonware/xwsystem/io/archive/formats/rar.py +11 -5
  102. exonware/xwsystem/io/archive/formats/sevenzip.py +12 -6
  103. exonware/xwsystem/io/archive/formats/squashfs_format.py +1 -2
  104. exonware/xwsystem/io/archive/formats/tar.py +52 -7
  105. exonware/xwsystem/io/archive/formats/wim_format.py +11 -5
  106. exonware/xwsystem/io/archive/formats/zip.py +1 -2
  107. exonware/xwsystem/io/archive/formats/zpaq_format.py +1 -2
  108. exonware/xwsystem/io/archive/formats/zstandard.py +20 -7
  109. exonware/xwsystem/io/base.py +119 -115
  110. exonware/xwsystem/io/codec/__init__.py +4 -2
  111. exonware/xwsystem/io/codec/base.py +19 -13
  112. exonware/xwsystem/io/codec/contracts.py +59 -2
  113. exonware/xwsystem/io/codec/registry.py +67 -21
  114. exonware/xwsystem/io/common/__init__.py +1 -1
  115. exonware/xwsystem/io/common/atomic.py +29 -16
  116. exonware/xwsystem/io/common/base.py +11 -10
  117. exonware/xwsystem/io/common/lock.py +6 -5
  118. exonware/xwsystem/io/common/path_manager.py +2 -1
  119. exonware/xwsystem/io/common/watcher.py +1 -2
  120. exonware/xwsystem/io/contracts.py +301 -433
  121. exonware/xwsystem/io/contracts_1.py +1180 -0
  122. exonware/xwsystem/io/data_operations.py +19 -20
  123. exonware/xwsystem/io/defs.py +4 -3
  124. exonware/xwsystem/io/errors.py +3 -2
  125. exonware/xwsystem/io/facade.py +87 -61
  126. exonware/xwsystem/io/file/__init__.py +1 -1
  127. exonware/xwsystem/io/file/base.py +8 -9
  128. exonware/xwsystem/io/file/conversion.py +2 -3
  129. exonware/xwsystem/io/file/file.py +61 -18
  130. exonware/xwsystem/io/file/paged_source.py +8 -8
  131. exonware/xwsystem/io/file/paging/__init__.py +1 -2
  132. exonware/xwsystem/io/file/paging/byte_paging.py +4 -5
  133. exonware/xwsystem/io/file/paging/line_paging.py +2 -3
  134. exonware/xwsystem/io/file/paging/record_paging.py +2 -3
  135. exonware/xwsystem/io/file/paging/registry.py +1 -2
  136. exonware/xwsystem/io/file/source.py +13 -17
  137. exonware/xwsystem/io/filesystem/__init__.py +1 -1
  138. exonware/xwsystem/io/filesystem/base.py +1 -2
  139. exonware/xwsystem/io/filesystem/local.py +3 -4
  140. exonware/xwsystem/io/folder/__init__.py +1 -1
  141. exonware/xwsystem/io/folder/base.py +1 -2
  142. exonware/xwsystem/io/folder/folder.py +16 -7
  143. exonware/xwsystem/io/indexing/__init__.py +14 -0
  144. exonware/xwsystem/io/indexing/facade.py +443 -0
  145. exonware/xwsystem/io/path_parser.py +98 -0
  146. exonware/xwsystem/io/serialization/__init__.py +21 -3
  147. exonware/xwsystem/io/serialization/auto_serializer.py +146 -20
  148. exonware/xwsystem/io/serialization/base.py +84 -34
  149. exonware/xwsystem/io/serialization/contracts.py +50 -73
  150. exonware/xwsystem/io/serialization/defs.py +2 -1
  151. exonware/xwsystem/io/serialization/errors.py +2 -1
  152. exonware/xwsystem/io/serialization/flyweight.py +154 -7
  153. exonware/xwsystem/io/serialization/format_detector.py +15 -14
  154. exonware/xwsystem/io/serialization/formats/__init__.py +8 -5
  155. exonware/xwsystem/io/serialization/formats/binary/bson.py +15 -6
  156. exonware/xwsystem/io/serialization/formats/binary/cbor.py +5 -5
  157. exonware/xwsystem/io/serialization/formats/binary/marshal.py +5 -5
  158. exonware/xwsystem/io/serialization/formats/binary/msgpack.py +5 -5
  159. exonware/xwsystem/io/serialization/formats/binary/pickle.py +5 -5
  160. exonware/xwsystem/io/serialization/formats/binary/plistlib.py +5 -5
  161. exonware/xwsystem/io/serialization/formats/database/dbm.py +7 -7
  162. exonware/xwsystem/io/serialization/formats/database/shelve.py +7 -7
  163. exonware/xwsystem/io/serialization/formats/database/sqlite3.py +7 -7
  164. exonware/xwsystem/io/serialization/formats/tabular/__init__.py +27 -0
  165. exonware/xwsystem/io/serialization/formats/tabular/base.py +89 -0
  166. exonware/xwsystem/io/serialization/formats/tabular/csv.py +319 -0
  167. exonware/xwsystem/io/serialization/formats/tabular/df.py +249 -0
  168. exonware/xwsystem/io/serialization/formats/tabular/excel.py +291 -0
  169. exonware/xwsystem/io/serialization/formats/tabular/googlesheets.py +374 -0
  170. exonware/xwsystem/io/serialization/formats/text/__init__.py +1 -1
  171. exonware/xwsystem/io/serialization/formats/text/append_only_log.py +5 -7
  172. exonware/xwsystem/io/serialization/formats/text/configparser.py +5 -5
  173. exonware/xwsystem/io/serialization/formats/text/csv.py +7 -5
  174. exonware/xwsystem/io/serialization/formats/text/formdata.py +5 -5
  175. exonware/xwsystem/io/serialization/formats/text/json.py +27 -18
  176. exonware/xwsystem/io/serialization/formats/text/json5.py +8 -4
  177. exonware/xwsystem/io/serialization/formats/text/jsonlines.py +18 -14
  178. exonware/xwsystem/io/serialization/formats/text/multipart.py +5 -5
  179. exonware/xwsystem/io/serialization/formats/text/toml.py +8 -6
  180. exonware/xwsystem/io/serialization/formats/text/xml.py +25 -20
  181. exonware/xwsystem/io/serialization/formats/text/yaml.py +8 -6
  182. exonware/xwsystem/io/serialization/parsers/__init__.py +3 -2
  183. exonware/xwsystem/io/serialization/parsers/base.py +6 -5
  184. exonware/xwsystem/io/serialization/parsers/hybrid_parser.py +7 -6
  185. exonware/xwsystem/io/serialization/parsers/msgspec_parser.py +10 -7
  186. exonware/xwsystem/io/serialization/parsers/orjson_direct_parser.py +7 -6
  187. exonware/xwsystem/io/serialization/parsers/orjson_parser.py +11 -8
  188. exonware/xwsystem/io/serialization/parsers/pysimdjson_parser.py +13 -9
  189. exonware/xwsystem/io/serialization/parsers/rapidjson_parser.py +10 -7
  190. exonware/xwsystem/io/serialization/parsers/registry.py +11 -10
  191. exonware/xwsystem/io/serialization/parsers/standard.py +7 -6
  192. exonware/xwsystem/io/serialization/parsers/ujson_parser.py +10 -7
  193. exonware/xwsystem/io/serialization/registry.py +4 -4
  194. exonware/xwsystem/io/serialization/serializer.py +168 -79
  195. exonware/xwsystem/io/serialization/universal_options.py +367 -0
  196. exonware/xwsystem/io/serialization/utils/__init__.py +1 -2
  197. exonware/xwsystem/io/serialization/utils/path_ops.py +5 -6
  198. exonware/xwsystem/io/source_reader.py +223 -0
  199. exonware/xwsystem/io/stream/__init__.py +1 -1
  200. exonware/xwsystem/io/stream/async_operations.py +61 -14
  201. exonware/xwsystem/io/stream/base.py +1 -2
  202. exonware/xwsystem/io/stream/codec_io.py +6 -7
  203. exonware/xwsystem/ipc/__init__.py +1 -0
  204. exonware/xwsystem/ipc/async_fabric.py +4 -4
  205. exonware/xwsystem/ipc/base.py +6 -5
  206. exonware/xwsystem/ipc/contracts.py +41 -66
  207. exonware/xwsystem/ipc/defs.py +2 -1
  208. exonware/xwsystem/ipc/errors.py +2 -1
  209. exonware/xwsystem/ipc/message_queue.py +5 -2
  210. exonware/xwsystem/ipc/pipes.py +70 -34
  211. exonware/xwsystem/ipc/process_manager.py +7 -5
  212. exonware/xwsystem/ipc/process_pool.py +6 -5
  213. exonware/xwsystem/ipc/shared_memory.py +64 -11
  214. exonware/xwsystem/monitoring/__init__.py +7 -0
  215. exonware/xwsystem/monitoring/base.py +11 -8
  216. exonware/xwsystem/monitoring/contracts.py +86 -144
  217. exonware/xwsystem/monitoring/defs.py +2 -1
  218. exonware/xwsystem/monitoring/error_recovery.py +16 -3
  219. exonware/xwsystem/monitoring/errors.py +2 -1
  220. exonware/xwsystem/monitoring/facade.py +183 -0
  221. exonware/xwsystem/monitoring/memory_monitor.py +1 -0
  222. exonware/xwsystem/monitoring/metrics.py +1 -0
  223. exonware/xwsystem/monitoring/performance_manager_generic.py +7 -7
  224. exonware/xwsystem/monitoring/performance_monitor.py +1 -0
  225. exonware/xwsystem/monitoring/performance_validator.py +1 -0
  226. exonware/xwsystem/monitoring/system_monitor.py +6 -5
  227. exonware/xwsystem/monitoring/tracing.py +18 -16
  228. exonware/xwsystem/monitoring/tracker.py +2 -1
  229. exonware/xwsystem/operations/__init__.py +5 -50
  230. exonware/xwsystem/operations/base.py +3 -44
  231. exonware/xwsystem/operations/contracts.py +25 -15
  232. exonware/xwsystem/operations/defs.py +1 -1
  233. exonware/xwsystem/operations/diff.py +5 -4
  234. exonware/xwsystem/operations/errors.py +1 -1
  235. exonware/xwsystem/operations/merge.py +6 -4
  236. exonware/xwsystem/operations/patch.py +5 -4
  237. exonware/xwsystem/patterns/__init__.py +1 -0
  238. exonware/xwsystem/patterns/base.py +2 -1
  239. exonware/xwsystem/patterns/context_manager.py +2 -1
  240. exonware/xwsystem/patterns/contracts.py +215 -256
  241. exonware/xwsystem/patterns/defs.py +2 -1
  242. exonware/xwsystem/patterns/dynamic_facade.py +1 -0
  243. exonware/xwsystem/patterns/errors.py +2 -4
  244. exonware/xwsystem/patterns/handler_factory.py +2 -3
  245. exonware/xwsystem/patterns/import_registry.py +1 -0
  246. exonware/xwsystem/patterns/object_pool.py +1 -0
  247. exonware/xwsystem/patterns/registry.py +4 -43
  248. exonware/xwsystem/plugins/__init__.py +2 -1
  249. exonware/xwsystem/plugins/base.py +6 -5
  250. exonware/xwsystem/plugins/contracts.py +94 -158
  251. exonware/xwsystem/plugins/defs.py +2 -1
  252. exonware/xwsystem/plugins/errors.py +2 -1
  253. exonware/xwsystem/py.typed +3 -0
  254. exonware/xwsystem/query/__init__.py +36 -0
  255. exonware/xwsystem/query/contracts.py +56 -0
  256. exonware/xwsystem/query/errors.py +22 -0
  257. exonware/xwsystem/query/registry.py +128 -0
  258. exonware/xwsystem/runtime/__init__.py +2 -1
  259. exonware/xwsystem/runtime/base.py +4 -3
  260. exonware/xwsystem/runtime/contracts.py +39 -60
  261. exonware/xwsystem/runtime/defs.py +2 -1
  262. exonware/xwsystem/runtime/env.py +11 -9
  263. exonware/xwsystem/runtime/errors.py +2 -1
  264. exonware/xwsystem/runtime/reflection.py +3 -2
  265. exonware/xwsystem/security/__init__.py +68 -11
  266. exonware/xwsystem/security/audit.py +167 -0
  267. exonware/xwsystem/security/base.py +121 -24
  268. exonware/xwsystem/security/contracts.py +91 -146
  269. exonware/xwsystem/security/crypto.py +17 -16
  270. exonware/xwsystem/security/defs.py +2 -1
  271. exonware/xwsystem/security/errors.py +2 -1
  272. exonware/xwsystem/security/facade.py +321 -0
  273. exonware/xwsystem/security/file_security.py +330 -0
  274. exonware/xwsystem/security/hazmat.py +11 -8
  275. exonware/xwsystem/security/monitor.py +372 -0
  276. exonware/xwsystem/security/path_validator.py +140 -18
  277. exonware/xwsystem/security/policy.py +357 -0
  278. exonware/xwsystem/security/resource_limits.py +1 -0
  279. exonware/xwsystem/security/validator.py +455 -0
  280. exonware/xwsystem/shared/__init__.py +14 -1
  281. exonware/xwsystem/shared/base.py +285 -2
  282. exonware/xwsystem/shared/contracts.py +415 -126
  283. exonware/xwsystem/shared/defs.py +2 -1
  284. exonware/xwsystem/shared/errors.py +2 -2
  285. exonware/xwsystem/shared/xwobject.py +316 -0
  286. exonware/xwsystem/structures/__init__.py +1 -0
  287. exonware/xwsystem/structures/base.py +3 -2
  288. exonware/xwsystem/structures/circular_detector.py +15 -14
  289. exonware/xwsystem/structures/contracts.py +53 -76
  290. exonware/xwsystem/structures/defs.py +2 -1
  291. exonware/xwsystem/structures/errors.py +2 -1
  292. exonware/xwsystem/structures/tree_walker.py +2 -1
  293. exonware/xwsystem/threading/__init__.py +21 -4
  294. exonware/xwsystem/threading/async_primitives.py +6 -5
  295. exonware/xwsystem/threading/base.py +3 -2
  296. exonware/xwsystem/threading/contracts.py +87 -143
  297. exonware/xwsystem/threading/defs.py +2 -1
  298. exonware/xwsystem/threading/errors.py +2 -1
  299. exonware/xwsystem/threading/facade.py +175 -0
  300. exonware/xwsystem/threading/locks.py +1 -0
  301. exonware/xwsystem/threading/safe_factory.py +1 -0
  302. exonware/xwsystem/utils/__init__.py +40 -0
  303. exonware/xwsystem/utils/base.py +22 -21
  304. exonware/xwsystem/utils/contracts.py +50 -73
  305. exonware/xwsystem/utils/dt/__init__.py +19 -3
  306. exonware/xwsystem/utils/dt/base.py +5 -4
  307. exonware/xwsystem/utils/dt/contracts.py +22 -29
  308. exonware/xwsystem/utils/dt/defs.py +2 -1
  309. exonware/xwsystem/utils/dt/errors.py +2 -5
  310. exonware/xwsystem/utils/dt/formatting.py +88 -2
  311. exonware/xwsystem/utils/dt/humanize.py +10 -9
  312. exonware/xwsystem/utils/dt/parsing.py +56 -5
  313. exonware/xwsystem/utils/dt/timezone_utils.py +2 -24
  314. exonware/xwsystem/utils/errors.py +2 -4
  315. exonware/xwsystem/utils/paths.py +1 -0
  316. exonware/xwsystem/utils/string.py +49 -0
  317. exonware/xwsystem/utils/test_runner.py +185 -0
  318. exonware/xwsystem/utils/utils_contracts.py +2 -1
  319. exonware/xwsystem/utils/web.py +110 -0
  320. exonware/xwsystem/validation/__init__.py +25 -1
  321. exonware/xwsystem/validation/base.py +6 -5
  322. exonware/xwsystem/validation/contracts.py +29 -41
  323. exonware/xwsystem/validation/data_validator.py +1 -0
  324. exonware/xwsystem/validation/declarative.py +11 -8
  325. exonware/xwsystem/validation/defs.py +2 -1
  326. exonware/xwsystem/validation/errors.py +2 -1
  327. exonware/xwsystem/validation/facade.py +198 -0
  328. exonware/xwsystem/validation/fluent_validator.py +22 -19
  329. exonware/xwsystem/validation/schema_discovery.py +210 -0
  330. exonware/xwsystem/validation/type_safety.py +2 -1
  331. exonware/xwsystem/version.py +2 -2
  332. {exonware_xwsystem-0.1.0.1.dist-info → exonware_xwsystem-0.1.0.3.dist-info}/METADATA +71 -4
  333. exonware_xwsystem-0.1.0.3.dist-info/RECORD +337 -0
  334. exonware/xwsystem/cli/__init__.py +0 -43
  335. exonware/xwsystem/cli/console.py +0 -113
  336. exonware/xwsystem/cli/defs.py +0 -134
  337. exonware/xwsystem/conf.py +0 -44
  338. exonware/xwsystem/security/auth.py +0 -484
  339. exonware_xwsystem-0.1.0.1.dist-info/RECORD +0 -284
  340. {exonware_xwsystem-0.1.0.1.dist-info → exonware_xwsystem-0.1.0.3.dist-info}/WHEEL +0 -0
  341. {exonware_xwsystem-0.1.0.1.dist-info → exonware_xwsystem-0.1.0.3.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,319 @@
1
+ #exonware/xwsystem/src/exonware/xwsystem/io/serialization/formats/tabular/csv.py
2
+ """
3
+ Company: eXonware.com
4
+ Author: Eng. Muhammad AlShehri
5
+ Email: connect@exonware.com
6
+ Version: 0.1.0.3
7
+ Generation Date: January 2025
8
+
9
+ CSV serialization - Comma-separated values format.
10
+
11
+ Following I→A→ATabular pattern:
12
+ - I: ISerialization (interface)
13
+ - A: ASerialization (abstract base)
14
+ - ATabular: ATabularSerialization (tabular base)
15
+ - Concrete: CsvSerializer
16
+
17
+ Moved from text/csv.py and updated to extend ATabularSerialization.
18
+ """
19
+
20
+ import csv
21
+ import io
22
+ from typing import Any, Optional
23
+ from pathlib import Path
24
+
25
+ import pandas as pd
26
+
27
+ from .base import ATabularSerialization
28
+ from ....contracts import EncodeOptions, DecodeOptions
29
+ from ....defs import CodecCapability
30
+ from ....errors import SerializationError
31
+
32
+
33
+ class CsvSerializer(ATabularSerialization):
34
+ """
35
+ CSV serializer - follows the I→A→ATabular pattern.
36
+
37
+ I: ISerialization (interface)
38
+ A: ASerialization (abstract base)
39
+ ATabular: ATabularSerialization (tabular base)
40
+ Concrete: CsvSerializer
41
+
42
+ Uses Python's built-in csv module and pandas for DataFrame operations.
43
+
44
+ Examples:
45
+ >>> serializer = CsvSerializer()
46
+ >>>
47
+ >>> # Encode list of dicts
48
+ >>> csv_str = serializer.encode([
49
+ ... {"name": "John", "age": 30},
50
+ ... {"name": "Jane", "age": 25}
51
+ ... ])
52
+ >>>
53
+ >>> # Decode to list of dicts
54
+ >>> data = serializer.decode(csv_str)
55
+ >>>
56
+ >>> # Convert DataFrame to CSV
57
+ >>> csv_str = serializer.from_df(df)
58
+ >>>
59
+ >>> # Convert CSV to DataFrame
60
+ >>> df = serializer.to_df(csv_str)
61
+ >>>
62
+ >>> # Save to file
63
+ >>> serializer.save_file(rows, "data.csv")
64
+ >>>
65
+ >>> # Load from file
66
+ >>> rows = serializer.load_file("data.csv")
67
+ """
68
+
69
+ # ========================================================================
70
+ # CODEC METADATA
71
+ # ========================================================================
72
+
73
+ @property
74
+ def codec_id(self) -> str:
75
+ return "csv"
76
+
77
+ @property
78
+ def media_types(self) -> list[str]:
79
+ return ["text/csv", "application/csv"]
80
+
81
+ @property
82
+ def file_extensions(self) -> list[str]:
83
+ return [".csv", ".tsv", ".psv"]
84
+
85
+ @property
86
+ def format_name(self) -> str:
87
+ return "CSV"
88
+
89
+ @property
90
+ def mime_type(self) -> str:
91
+ return "text/csv"
92
+
93
+ @property
94
+ def is_binary_format(self) -> bool:
95
+ return False # CSV is text-based
96
+
97
+ @property
98
+ def supports_streaming(self) -> bool:
99
+ return True # CSV naturally supports streaming (row by row)
100
+
101
+ @property
102
+ def capabilities(self) -> CodecCapability:
103
+ return CodecCapability.BIDIRECTIONAL
104
+
105
+ @property
106
+ def aliases(self) -> list[str]:
107
+ return ["csv", "CSV", "tsv", "TSV"]
108
+
109
+ @property
110
+ def codec_types(self) -> list[str]:
111
+ """CSV is primarily a data exchange format."""
112
+ return ["data", "tabular"]
113
+
114
+ # ========================================================================
115
+ # CORE ENCODE/DECODE (Using csv module)
116
+ # ========================================================================
117
+
118
+ def encode(self, value: Any, *, options: Optional[EncodeOptions] = None) -> str:
119
+ """
120
+ Encode data to CSV string.
121
+
122
+ Uses csv.DictWriter or csv.writer.
123
+
124
+ Args:
125
+ value: Data to serialize (list of dicts, list of lists, or DataFrame)
126
+ options: CSV options (delimiter, quoting, etc.)
127
+
128
+ Returns:
129
+ CSV string
130
+
131
+ Raises:
132
+ SerializationError: If encoding fails
133
+ """
134
+ try:
135
+ # If DataFrame, use from_df
136
+ if isinstance(value, pd.DataFrame):
137
+ return self.from_df(value, **(options or {}))
138
+
139
+ opts = options or {}
140
+
141
+ # Get CSV options
142
+ delimiter = opts.get('delimiter', ',')
143
+ quoting = opts.get('quoting', csv.QUOTE_MINIMAL)
144
+
145
+ # Create string buffer
146
+ output = io.StringIO()
147
+
148
+ if isinstance(value, list) and value:
149
+ if isinstance(value[0], dict):
150
+ # List of dicts - use DictWriter
151
+ fieldnames = opts.get('fieldnames', list(value[0].keys()))
152
+ writer = csv.DictWriter(
153
+ output,
154
+ fieldnames=fieldnames,
155
+ delimiter=delimiter,
156
+ quoting=quoting
157
+ )
158
+
159
+ # Write header
160
+ if opts.get('header', True):
161
+ writer.writeheader()
162
+
163
+ # Write rows
164
+ writer.writerows(value)
165
+ else:
166
+ # List of lists - use regular writer
167
+ writer = csv.writer(
168
+ output,
169
+ delimiter=delimiter,
170
+ quoting=quoting
171
+ )
172
+ writer.writerows(value)
173
+
174
+ return output.getvalue()
175
+
176
+ except Exception as e:
177
+ raise SerializationError(
178
+ f"Failed to encode CSV: {e}",
179
+ format_name=self.format_name,
180
+ original_error=e
181
+ )
182
+
183
+ def decode(self, repr: bytes | str, *, options: Optional[DecodeOptions] = None) -> Any:
184
+ """
185
+ Decode CSV string to data.
186
+
187
+ Uses csv.DictReader or csv.reader.
188
+
189
+ Args:
190
+ repr: CSV string (bytes or str)
191
+ options: CSV options (delimiter, has_header, etc.)
192
+
193
+ Returns:
194
+ List of dicts (if header) or list of lists
195
+
196
+ Raises:
197
+ SerializationError: If decoding fails
198
+ """
199
+ try:
200
+ # Convert bytes to str if needed
201
+ if isinstance(repr, bytes):
202
+ repr = repr.decode('utf-8')
203
+
204
+ opts = options or {}
205
+
206
+ # Get CSV options
207
+ delimiter = opts.get('delimiter', ',')
208
+ has_header = opts.get('header', True)
209
+
210
+ # Create string buffer
211
+ input_stream = io.StringIO(repr)
212
+
213
+ if has_header:
214
+ # Use DictReader for header-based CSV
215
+ reader = csv.DictReader(input_stream, delimiter=delimiter)
216
+ data = list(reader)
217
+ else:
218
+ # Use regular reader for headerless CSV
219
+ reader = csv.reader(input_stream, delimiter=delimiter)
220
+ data = list(reader)
221
+
222
+ return data
223
+
224
+ except (Exception, UnicodeDecodeError) as e:
225
+ raise SerializationError(
226
+ f"Failed to decode CSV: {e}",
227
+ format_name=self.format_name,
228
+ original_error=e
229
+ )
230
+
231
+ # ========================================================================
232
+ # TABULAR METHODS (to_df/from_df)
233
+ # ========================================================================
234
+
235
+ def to_df(
236
+ self,
237
+ csv_content: bytes | str | Path,
238
+ sheet_name: Optional[str | list[str]] = None,
239
+ **options
240
+ ) -> pd.DataFrame:
241
+ """
242
+ Convert CSV content to DataFrame.
243
+
244
+ Note: CSV doesn't support multiple sheets, so sheet_name is ignored.
245
+
246
+ Args:
247
+ csv_content: CSV content as bytes, string, or file path
248
+ sheet_name: Ignored (CSV doesn't support multiple sheets)
249
+ **options: Additional pandas read_csv options (delimiter, header, etc.)
250
+
251
+ Returns:
252
+ DataFrame
253
+
254
+ Examples:
255
+ >>> serializer = CsvSerializer()
256
+ >>> df = serializer.to_df(csv_str)
257
+ >>> df = serializer.to_df("data.csv")
258
+ """
259
+ try:
260
+ # Handle file path
261
+ if isinstance(csv_content, (str, Path)):
262
+ file_path = str(csv_content)
263
+ return pd.read_csv(file_path, **options)
264
+
265
+ # Handle bytes or string
266
+ if isinstance(csv_content, bytes):
267
+ csv_content = csv_content.decode('utf-8')
268
+
269
+ # Use StringIO for in-memory CSV
270
+ csv_io = io.StringIO(csv_content)
271
+ return pd.read_csv(csv_io, **options)
272
+
273
+ except Exception as e:
274
+ raise SerializationError(
275
+ f"Failed to convert CSV to DataFrame: {e}",
276
+ format_name=self.format_name,
277
+ original_error=e
278
+ )
279
+
280
+ def from_df(
281
+ self,
282
+ df: pd.DataFrame,
283
+ **options
284
+ ) -> str:
285
+ """
286
+ Convert DataFrame to CSV string.
287
+
288
+ Note: CSV doesn't support multiple sheets, so dict input is not supported.
289
+
290
+ Args:
291
+ df: Single DataFrame
292
+ **options: Additional pandas to_csv options (index, delimiter, etc.)
293
+
294
+ Returns:
295
+ CSV string
296
+
297
+ Examples:
298
+ >>> serializer = CsvSerializer()
299
+ >>> csv_str = serializer.from_df(df)
300
+ """
301
+ try:
302
+ if isinstance(df, dict):
303
+ raise ValueError("CSV format does not support multiple sheets. Use a single DataFrame.")
304
+
305
+ # Use StringIO to capture CSV output
306
+ output = io.StringIO()
307
+ df.to_csv(
308
+ output,
309
+ index=options.get('index', False),
310
+ **{k: v for k, v in options.items() if k != 'index'}
311
+ )
312
+ return output.getvalue()
313
+
314
+ except Exception as e:
315
+ raise SerializationError(
316
+ f"Failed to convert DataFrame to CSV: {e}",
317
+ format_name=self.format_name,
318
+ original_error=e
319
+ )
@@ -0,0 +1,249 @@
1
+ #exonware/xwsystem/src/exonware/xwsystem/io/serialization/formats/tabular/df.py
2
+ """
3
+ Company: eXonware.com
4
+ Author: Eng. Muhammad AlShehri
5
+ Email: connect@exonware.com
6
+ Version: 0.1.0.3
7
+ Generation Date: January 2025
8
+
9
+ DataFrame serialization - Direct pandas DataFrame operations.
10
+
11
+ Following I→A→ATabular pattern:
12
+ - I: ISerialization (interface)
13
+ - A: ASerialization (abstract base)
14
+ - ATabular: ATabularSerialization (tabular base)
15
+ - Concrete: DataFrameSerializer
16
+
17
+ Useful for intermediate DataFrame processing and format conversion.
18
+ """
19
+
20
+ from typing import Any, Optional
21
+ from pathlib import Path
22
+
23
+ import pandas as pd
24
+
25
+ from .base import ATabularSerialization
26
+ from ....contracts import EncodeOptions, DecodeOptions
27
+ from ....defs import CodecCapability
28
+ from ....errors import SerializationError
29
+
30
+
31
+ class DataFrameSerializer(ATabularSerialization):
32
+ """
33
+ DataFrame serializer - follows the I→A→ATabular pattern.
34
+
35
+ I: ISerialization (interface)
36
+ A: ASerialization (abstract base)
37
+ ATabular: ATabularSerialization (tabular base)
38
+ Concrete: DataFrameSerializer
39
+
40
+ Direct DataFrame operations - useful for intermediate processing.
41
+
42
+ Examples:
43
+ >>> serializer = DataFrameSerializer()
44
+ >>>
45
+ >>> # Convert DataFrame to bytes (pickle)
46
+ >>> df_bytes = serializer.from_df(df)
47
+ >>>
48
+ >>> # Convert bytes to DataFrame
49
+ >>> df = serializer.to_df(df_bytes)
50
+ >>>
51
+ >>> # Save DataFrame
52
+ >>> serializer.save_file(df, "data.pkl")
53
+ >>>
54
+ >>> # Load DataFrame
55
+ >>> df = serializer.load_file("data.pkl")
56
+ """
57
+
58
+ # ========================================================================
59
+ # CODEC METADATA
60
+ # ========================================================================
61
+
62
+ @property
63
+ def codec_id(self) -> str:
64
+ return "dataframe"
65
+
66
+ @property
67
+ def media_types(self) -> list[str]:
68
+ return [
69
+ "application/x-pandas-dataframe",
70
+ "application/x-pickle",
71
+ ]
72
+
73
+ @property
74
+ def file_extensions(self) -> list[str]:
75
+ return [".pkl", ".pickle", ".df"]
76
+
77
+ @property
78
+ def format_name(self) -> str:
79
+ return "DataFrame"
80
+
81
+ @property
82
+ def mime_type(self) -> str:
83
+ return "application/x-pandas-dataframe"
84
+
85
+ @property
86
+ def is_binary_format(self) -> bool:
87
+ return True # DataFrame pickle is binary
88
+
89
+ @property
90
+ def supports_streaming(self) -> bool:
91
+ return False # DataFrames don't naturally support streaming
92
+
93
+ @property
94
+ def capabilities(self) -> CodecCapability:
95
+ return CodecCapability.BIDIRECTIONAL
96
+
97
+ @property
98
+ def aliases(self) -> list[str]:
99
+ return ["dataframe", "DataFrame", "df", "pandas", "pkl"]
100
+
101
+ @property
102
+ def codec_types(self) -> list[str]:
103
+ """DataFrame is an intermediate data format."""
104
+ return ["data", "tabular", "intermediate"]
105
+
106
+ # ========================================================================
107
+ # CORE ENCODE/DECODE (Using pickle)
108
+ # ========================================================================
109
+
110
+ def encode(self, value: Any, *, options: Optional[EncodeOptions] = None) -> bytes:
111
+ """
112
+ Encode DataFrame to pickle bytes.
113
+
114
+ Args:
115
+ value: DataFrame or dict of {sheet_name: DataFrame}
116
+ options: Pickle options (protocol, etc.)
117
+
118
+ Returns:
119
+ Pickled DataFrame as bytes
120
+
121
+ Raises:
122
+ SerializationError: If encoding fails
123
+ """
124
+ try:
125
+ import pickle
126
+
127
+ opts = options or {}
128
+ protocol = opts.get('protocol', pickle.HIGHEST_PROTOCOL)
129
+
130
+ return pickle.dumps(value, protocol=protocol)
131
+
132
+ except Exception as e:
133
+ raise SerializationError(
134
+ f"Failed to encode DataFrame: {e}",
135
+ format_name=self.format_name,
136
+ original_error=e
137
+ )
138
+
139
+ def decode(self, repr: bytes | str, *, options: Optional[DecodeOptions] = None) -> Any:
140
+ """
141
+ Decode pickle bytes to DataFrame(s).
142
+
143
+ Args:
144
+ repr: Pickled DataFrame as bytes, or file path
145
+ options: Decode options
146
+
147
+ Returns:
148
+ DataFrame or dict of {sheet_name: DataFrame}
149
+
150
+ Raises:
151
+ SerializationError: If decoding fails
152
+ """
153
+ try:
154
+ import pickle
155
+
156
+ # Handle file path
157
+ if isinstance(repr, (str, Path)):
158
+ with open(repr, 'rb') as f:
159
+ return pickle.load(f)
160
+
161
+ # Handle bytes
162
+ if isinstance(repr, str):
163
+ repr = repr.encode('utf-8')
164
+
165
+ return pickle.loads(repr)
166
+
167
+ except Exception as e:
168
+ raise SerializationError(
169
+ f"Failed to decode DataFrame: {e}",
170
+ format_name=self.format_name,
171
+ original_error=e
172
+ )
173
+
174
+ # ========================================================================
175
+ # TABULAR METHODS (to_df/from_df)
176
+ # ========================================================================
177
+
178
+ def to_df(
179
+ self,
180
+ data: bytes | str | Path,
181
+ sheet_name: Optional[str | list[str]] = None,
182
+ **options
183
+ ) -> pd.DataFrame | dict[str, pd.DataFrame]:
184
+ """
185
+ Convert pickled data to DataFrame(s).
186
+
187
+ Args:
188
+ data: Pickled DataFrame as bytes, or file path
189
+ sheet_name: Ignored (pickle preserves structure)
190
+ **options: Decode options
191
+
192
+ Returns:
193
+ DataFrame or dict of {sheet_name: DataFrame} (as stored)
194
+
195
+ Examples:
196
+ >>> serializer = DataFrameSerializer()
197
+ >>> df = serializer.to_df(pickled_bytes)
198
+ >>> df = serializer.to_df("data.pkl")
199
+ """
200
+ try:
201
+ # Use decode method
202
+ result = self.decode(data, **(options or {}))
203
+
204
+ # If sheet_name specified and result is dict, filter
205
+ if sheet_name is not None and isinstance(result, dict):
206
+ if isinstance(sheet_name, str):
207
+ return result.get(sheet_name)
208
+ else:
209
+ return {name: result.get(name) for name in sheet_name if name in result}
210
+
211
+ return result
212
+
213
+ except Exception as e:
214
+ raise SerializationError(
215
+ f"Failed to convert to DataFrame: {e}",
216
+ format_name=self.format_name,
217
+ original_error=e
218
+ )
219
+
220
+ def from_df(
221
+ self,
222
+ df: pd.DataFrame | dict[str, pd.DataFrame],
223
+ **options
224
+ ) -> bytes:
225
+ """
226
+ Convert DataFrame(s) to pickle bytes.
227
+
228
+ Args:
229
+ df: Single DataFrame or dict of {sheet_name: DataFrame}
230
+ **options: Pickle options (protocol, etc.)
231
+
232
+ Returns:
233
+ Pickled DataFrame as bytes
234
+
235
+ Examples:
236
+ >>> serializer = DataFrameSerializer()
237
+ >>> bytes = serializer.from_df(df)
238
+ >>> bytes = serializer.from_df({"Sheet1": df1, "Sheet2": df2})
239
+ """
240
+ try:
241
+ # Use encode method
242
+ return self.encode(df, **(options or {}))
243
+
244
+ except Exception as e:
245
+ raise SerializationError(
246
+ f"Failed to convert DataFrame: {e}",
247
+ format_name=self.format_name,
248
+ original_error=e
249
+ )