exonware-xwsystem 0.0.1.411__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 (342) 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 +73 -391
  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 +279 -14
  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 +199 -0
  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 +65 -33
  176. exonware/xwsystem/io/serialization/formats/text/json5.py +8 -4
  177. exonware/xwsystem/io/serialization/formats/text/jsonlines.py +113 -25
  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 +16 -0
  183. exonware/xwsystem/io/serialization/parsers/base.py +60 -0
  184. exonware/xwsystem/io/serialization/parsers/hybrid_parser.py +62 -0
  185. exonware/xwsystem/io/serialization/parsers/msgspec_parser.py +48 -0
  186. exonware/xwsystem/io/serialization/parsers/orjson_direct_parser.py +54 -0
  187. exonware/xwsystem/io/serialization/parsers/orjson_parser.py +62 -0
  188. exonware/xwsystem/io/serialization/parsers/pysimdjson_parser.py +55 -0
  189. exonware/xwsystem/io/serialization/parsers/rapidjson_parser.py +53 -0
  190. exonware/xwsystem/io/serialization/parsers/registry.py +91 -0
  191. exonware/xwsystem/io/serialization/parsers/standard.py +44 -0
  192. exonware/xwsystem/io/serialization/parsers/ujson_parser.py +53 -0
  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 +139 -480
  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 +4 -4
  332. {exonware_xwsystem-0.0.1.411.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/caching/USAGE_GUIDE.md +0 -779
  335. exonware/xwsystem/cli/__init__.py +0 -43
  336. exonware/xwsystem/cli/console.py +0 -113
  337. exonware/xwsystem/cli/defs.py +0 -134
  338. exonware/xwsystem/conf.py +0 -44
  339. exonware/xwsystem/security/auth.py +0 -484
  340. exonware_xwsystem-0.0.1.411.dist-info/RECORD +0 -274
  341. {exonware_xwsystem-0.0.1.411.dist-info → exonware_xwsystem-0.1.0.3.dist-info}/WHEEL +0 -0
  342. {exonware_xwsystem-0.0.1.411.dist-info → exonware_xwsystem-0.1.0.3.dist-info}/licenses/LICENSE +0 -0
@@ -1,8 +1,9 @@
1
+ #exonware/xwsystem/src/exonware/xwsystem/io/facade.py
1
2
  """
2
3
  Company: eXonware.com
3
4
  Author: Eng. Muhammad AlShehri
4
5
  Email: connect@exonware.com
5
- Version: 0.0.1.411
6
+ Version: 0.1.0.3
6
7
  Generation Date: September 04, 2025
7
8
 
8
9
  XWIO - Main facade for all I/O operations (MANDATORY facade pattern).
@@ -10,12 +11,14 @@ XWIO - Main facade for all I/O operations (MANDATORY facade pattern).
10
11
  This is the primary entry point for the IO module, following GUIDELINES_DEV.md.
11
12
  """
12
13
 
14
+ from __future__ import annotations
15
+
13
16
  import os
14
17
  import shutil
15
18
  import tempfile
16
19
  import time
17
20
  from pathlib import Path
18
- from typing import Any, Optional, Union, BinaryIO, TextIO
21
+ from typing import Any, Optional, BinaryIO, TextIO
19
22
 
20
23
  from .base import AUnifiedIO
21
24
  from .contracts import FileMode, FileType, PathType, OperationResult, LockType, IUnifiedIO
@@ -54,7 +57,7 @@ class XWIO(AUnifiedIO):
54
57
  - Delegates to specialized components
55
58
  """
56
59
 
57
- def __init__(self, file_path: Optional[Union[str, Path]] = None, **config):
60
+ def __init__(self, file_path: Optional[str | Path] = None, **config):
58
61
  """
59
62
  Initialize XWIO facade.
60
63
 
@@ -81,7 +84,7 @@ class XWIO(AUnifiedIO):
81
84
  # FILE OPERATIONS
82
85
  # ============================================================================
83
86
 
84
- def open_file(self, file_path: Optional[Union[str, Path]] = None, mode: FileMode = FileMode.READ) -> None:
87
+ def open_file(self, file_path: Optional[str | Path] = None, mode: FileMode = FileMode.READ) -> None:
85
88
  """Open file with validation and monitoring."""
86
89
  target_path = Path(file_path) if file_path else self.file_path
87
90
  if not target_path:
@@ -100,7 +103,7 @@ class XWIO(AUnifiedIO):
100
103
  self.file_path = target_path
101
104
  logger.debug(f"File opened: {target_path} in mode {mode.value}")
102
105
 
103
- def open_stream(self, stream: Union[BinaryIO, TextIO]) -> None:
106
+ def open_stream(self, stream: BinaryIO | TextIO) -> None:
104
107
  """Open stream for stream operations."""
105
108
  self._stream = stream
106
109
  self._position = 0
@@ -110,12 +113,12 @@ class XWIO(AUnifiedIO):
110
113
  # ABSTRACT METHOD IMPLEMENTATIONS (from AFile)
111
114
  # ============================================================================
112
115
 
113
- # Keep open() for backward compatibility - delegate to file operations
116
+ # Delegate to file operations
114
117
  def open(self, mode: FileMode = FileMode.READ) -> None:
115
118
  """Open file with validation and monitoring (alias for open_file())."""
116
119
  self.open_file(mode=mode)
117
120
 
118
- def read(self, size: Optional[int] = None) -> Union[str, bytes]:
121
+ def read(self, size: Optional[int] = None) -> str | bytes:
119
122
  """
120
123
  Read from file (implements AFile abstract method).
121
124
 
@@ -133,7 +136,7 @@ class XWIO(AUnifiedIO):
133
136
  # File operation
134
137
  return self.read_file(size)
135
138
 
136
- def write(self, data: Union[str, bytes]) -> int:
139
+ def write(self, data: str | bytes) -> int:
137
140
  """
138
141
  Write to file (implements AFile abstract method).
139
142
 
@@ -151,26 +154,7 @@ class XWIO(AUnifiedIO):
151
154
  # File operation
152
155
  return self.write_file(data)
153
156
 
154
- def save_as(self, path: Union[str, Path], data: Any, **kwargs) -> bool:
155
- """
156
- Save data to specific path (implements AFile abstract method).
157
-
158
- Args:
159
- path: Target file path
160
- data: Data to save
161
- **kwargs: Additional options
162
-
163
- Returns:
164
- True if successful, False otherwise
165
- """
166
- try:
167
- self.save(data, file_path=path, **kwargs)
168
- return True
169
- except Exception as e:
170
- logger.error(f"Failed to save data to {path}: {e}")
171
- return False
172
-
173
- def to_file(self, path: Union[str, Path], **kwargs) -> bool:
157
+ def to_file(self, path: str | Path, **kwargs) -> bool:
174
158
  """
175
159
  Write current data to file (implements AFile abstract method).
176
160
 
@@ -198,7 +182,7 @@ class XWIO(AUnifiedIO):
198
182
  logger.warning("No data to write to file")
199
183
  return False
200
184
 
201
- def from_file(self, path: Union[str, Path], **kwargs) -> 'XWIO':
185
+ def from_file(self, path: str | Path, **kwargs) -> XWIO:
202
186
  """
203
187
  Load data from file and return new XWIO instance (implements AFile abstract method).
204
188
 
@@ -212,8 +196,17 @@ class XWIO(AUnifiedIO):
212
196
  new_instance = XWIO(file_path=path, **self.__dict__.get('_config', {}))
213
197
  new_instance._current_data = new_instance.load(file_path=path, **kwargs)
214
198
  return new_instance
199
+
200
+ def load_from(self, path: str | Path, **kwargs) -> Any:
201
+ """
202
+ Load data from a specific path (convenience alias).
203
+
204
+ This matches the facade-style API used in core tests:
205
+ - `load_from(path)` delegates to `load(file_path=...)`.
206
+ """
207
+ return self.load(file_path=path, **kwargs)
215
208
 
216
- def read_file(self, size: Optional[int] = None) -> Union[str, bytes]:
209
+ def read_file(self, size: Optional[int] = None) -> str | bytes:
217
210
  """Read from file with validation."""
218
211
  if not self.is_open():
219
212
  raise ValueError("File not open")
@@ -226,7 +219,7 @@ class XWIO(AUnifiedIO):
226
219
 
227
220
  return data
228
221
 
229
- def write_file(self, data: Union[str, bytes]) -> int:
222
+ def write_file(self, data: str | bytes) -> int:
230
223
  """Write to file with validation."""
231
224
  if not self.is_open():
232
225
  raise ValueError("File not open")
@@ -238,14 +231,20 @@ class XWIO(AUnifiedIO):
238
231
  return self._handle.write(data)
239
232
 
240
233
 
241
- def save(self, data: Any, file_path: Optional[Union[str, Path]] = None) -> None:
242
- """Save data to file with atomic operations."""
234
+ def save(self, data: Any, file_path: Optional[str | Path] = None) -> bool:
235
+ """
236
+ Save data to file with atomic operations.
237
+
238
+ Returns:
239
+ True if successful.
240
+ """
243
241
  target_path = Path(file_path) if file_path else self.file_path
244
242
  if not target_path:
245
243
  raise ValueError("No file path specified")
246
244
 
247
245
  if self.validate_paths:
248
- self._path_validator.validate_path(target_path)
246
+ # Saving is a write operation; allow creating new files in valid directories.
247
+ self._path_validator.validate_path(target_path, for_writing=True, create_dirs=True)
249
248
 
250
249
  if self.validate_data:
251
250
  self._data_validator.validate_data(data)
@@ -253,18 +252,21 @@ class XWIO(AUnifiedIO):
253
252
  with performance_monitor("file_save"):
254
253
  if self.use_atomic_operations:
255
254
  # Use atomic file writer
256
- with AtomicFileWriter(target_path, backup=self.auto_backup) as writer:
257
- if isinstance(data, str):
258
- writer.write(data.encode('utf-8'))
259
- else:
255
+ if isinstance(data, bytes):
256
+ with AtomicFileWriter(target_path, mode="wb", backup=self.auto_backup) as writer:
257
+ writer.write(data)
258
+ else:
259
+ # Treat as text (most common path for XWIO facade)
260
+ with AtomicFileWriter(target_path, mode="w", encoding="utf-8", backup=self.auto_backup) as writer:
260
261
  writer.write(data)
261
262
  else:
262
263
  # Direct write
263
264
  target_path.parent.mkdir(parents=True, exist_ok=True)
264
265
  with open(target_path, 'wb' if isinstance(data, bytes) else 'w') as f:
265
266
  f.write(data)
267
+ return True
266
268
 
267
- def load(self, file_path: Optional[Union[str, Path]] = None) -> Any:
269
+ def load(self, file_path: Optional[str | Path] = None) -> Any:
268
270
  """Load data from file with validation."""
269
271
  target_path = Path(file_path) if file_path else self.file_path
270
272
  if not target_path:
@@ -342,7 +344,7 @@ class XWIO(AUnifiedIO):
342
344
  # ATOMIC OPERATIONS
343
345
  # ============================================================================
344
346
 
345
- def atomic_write(self, file_path: Union[str, Path], data: Union[str, bytes],
347
+ def atomic_write(self, file_path: str | Path, data: str | bytes,
346
348
  backup: bool = True) -> OperationResult:
347
349
  """Atomically write data to file."""
348
350
  target_path = Path(file_path)
@@ -365,7 +367,7 @@ class XWIO(AUnifiedIO):
365
367
  logger.error(f"Atomic write failed for {target_path}: {e}")
366
368
  return OperationResult.FAILED
367
369
 
368
- def atomic_copy(self, source: Union[str, Path], destination: Union[str, Path]) -> OperationResult:
370
+ def atomic_copy(self, source: str | Path, destination: str | Path) -> OperationResult:
369
371
  """Atomically copy file."""
370
372
  source_path = Path(source)
371
373
  dest_path = Path(destination)
@@ -385,7 +387,7 @@ class XWIO(AUnifiedIO):
385
387
  logger.error(f"Atomic copy failed from {source_path} to {dest_path}: {e}")
386
388
  return OperationResult.FAILED
387
389
 
388
- def atomic_move(self, source: Union[str, Path], destination: Union[str, Path]) -> OperationResult:
390
+ def atomic_move(self, source: str | Path, destination: str | Path) -> OperationResult:
389
391
  """Atomically move file."""
390
392
  source_path = Path(source)
391
393
  dest_path = Path(destination)
@@ -411,7 +413,7 @@ class XWIO(AUnifiedIO):
411
413
  logger.error(f"Atomic move failed from {source_path} to {dest_path}: {e}")
412
414
  return OperationResult.FAILED
413
415
 
414
- def atomic_delete(self, file_path: Union[str, Path], backup: bool = True) -> OperationResult:
416
+ def atomic_delete(self, file_path: str | Path, backup: bool = True) -> OperationResult:
415
417
  """Atomically delete file."""
416
418
  target_path = Path(file_path)
417
419
 
@@ -431,7 +433,7 @@ class XWIO(AUnifiedIO):
431
433
  logger.error(f"Atomic delete failed for {target_path}: {e}")
432
434
  return OperationResult.FAILED
433
435
 
434
- def atomic_rename(self, old_path: Union[str, Path], new_path: Union[str, Path]) -> OperationResult:
436
+ def atomic_rename(self, old_path: str | Path, new_path: str | Path) -> OperationResult:
435
437
  """Atomically rename file."""
436
438
  old_file = Path(old_path)
437
439
  new_file = Path(new_path)
@@ -455,7 +457,7 @@ class XWIO(AUnifiedIO):
455
457
  # BACKUP OPERATIONS
456
458
  # ============================================================================
457
459
 
458
- def create_backup(self, source: Union[str, Path], backup_dir: Union[str, Path]) -> Optional[Path]:
460
+ def create_backup(self, source: str | Path, backup_dir: str | Path) -> Optional[Path]:
459
461
  """Create backup of file or directory."""
460
462
  source_path = Path(source)
461
463
  backup_path = Path(backup_dir)
@@ -484,7 +486,7 @@ class XWIO(AUnifiedIO):
484
486
  logger.error(f"Backup creation failed for {source_path}: {e}")
485
487
  return None
486
488
 
487
- def restore_backup(self, backup_path: Union[str, Path], target: Union[str, Path]) -> OperationResult:
489
+ def restore_backup(self, backup_path: str | Path, target: str | Path) -> OperationResult:
488
490
  """Restore from backup."""
489
491
  backup = Path(backup_path)
490
492
  target_path = Path(target)
@@ -553,7 +555,7 @@ class XWIO(AUnifiedIO):
553
555
  # ASYNC OPERATIONS
554
556
  # ============================================================================
555
557
 
556
- async def aread(self, size: Optional[int] = None) -> Union[str, bytes]:
558
+ async def aread(self, size: Optional[int] = None) -> str | bytes:
557
559
  """Async read operation."""
558
560
  if not self._async_stream:
559
561
  raise ValueError("Async stream not initialized")
@@ -561,7 +563,7 @@ class XWIO(AUnifiedIO):
561
563
  with performance_monitor("async_read"):
562
564
  return await self._async_stream.read(size)
563
565
 
564
- async def awrite(self, data: Union[str, bytes]) -> int:
566
+ async def awrite(self, data: str | bytes) -> int:
565
567
  """Async write operation."""
566
568
  if not self._async_stream:
567
569
  raise ValueError("Async stream not initialized")
@@ -640,7 +642,7 @@ class XWIO(AUnifiedIO):
640
642
  # CODEC INTEGRATION (UniversalCodecRegistry)
641
643
  # ============================================================================
642
644
 
643
- def serialize(self, data: Any, format_id: str, **options) -> Union[bytes, str]:
645
+ def serialize(self, data: Any, format_id: str, **options) -> bytes | str:
644
646
  """
645
647
  Serialize data using specified format.
646
648
 
@@ -669,7 +671,7 @@ class XWIO(AUnifiedIO):
669
671
 
670
672
  return codec.encode(data, options=options or None)
671
673
 
672
- def deserialize(self, data: Union[bytes, str], format_id: str, **options) -> Any:
674
+ def deserialize(self, data: bytes | str, format_id: str, **options) -> Any:
673
675
  """
674
676
  Deserialize data using specified format.
675
677
 
@@ -698,7 +700,7 @@ class XWIO(AUnifiedIO):
698
700
 
699
701
  return codec.decode(data, options=options or None)
700
702
 
701
- def save_serialized(self, data: Any, file_path: Union[str, Path], format_id: Optional[str] = None, **options) -> None:
703
+ def save_serialized(self, data: Any, file_path: str | Path, format_id: Optional[str] = None, **options) -> None:
702
704
  """
703
705
  Serialize and save data to file.
704
706
 
@@ -742,7 +744,7 @@ class XWIO(AUnifiedIO):
742
744
  else:
743
745
  path.write_text(repr_data, encoding='utf-8')
744
746
 
745
- def load_serialized(self, file_path: Union[str, Path], format_id: Optional[str] = None, **options) -> Any:
747
+ def load_serialized(self, file_path: str | Path, format_id: Optional[str] = None, **options) -> Any:
746
748
  """
747
749
  Load and deserialize data from file.
748
750
 
@@ -789,7 +791,7 @@ class XWIO(AUnifiedIO):
789
791
  # CONVENIENCE ALIASES (User-friendly API)
790
792
  # ============================================================================
791
793
 
792
- def load_as(self, file_path: Union[str, Path], format_id: str, **options) -> Any:
794
+ def load_as(self, file_path: str | Path, format_id: str, **options) -> Any:
793
795
  """
794
796
  Load data from file using specified format (convenience alias).
795
797
 
@@ -810,16 +812,30 @@ class XWIO(AUnifiedIO):
810
812
  """
811
813
  return self.load_serialized(file_path, format_id=format_id, **options)
812
814
 
813
- def save_as(self, file_path: Union[str, Path], data: Any, format_id: str, **options) -> None:
815
+ def save_as(
816
+ self,
817
+ file_path: str | Path,
818
+ data: Any,
819
+ format_id: Optional[str] = None,
820
+ **options,
821
+ ) -> bool:
814
822
  """
815
- Save data to file using specified format (convenience alias).
823
+ Save data to a specific path.
824
+
825
+ This method intentionally supports **two** usage patterns:
826
+
827
+ 1) **File-like save** (AFile-style):
828
+ - `save_as(path, data)` → writes raw text/bytes to the target path
829
+
830
+ 2) **Serialization save** (format-aware):
831
+ - `save_as(path, data, format_id="json", ...)` → serializes and writes via codec registry
816
832
 
817
- Alias for save_serialized() with explicit format.
833
+ If you want a more explicit serialization name, prefer `write_as(...)`.
818
834
 
819
835
  Args:
820
836
  file_path: Path to save to
821
837
  data: Data to serialize
822
- format_id: Format identifier (e.g., 'json', 'yaml', 'xml')
838
+ format_id: Optional format identifier (e.g., 'json', 'yaml', 'xml')
823
839
  **options: Format-specific options
824
840
 
825
841
  Examples:
@@ -827,9 +843,19 @@ class XWIO(AUnifiedIO):
827
843
  >>> io.save_as("config.yml", config_dict, "yaml", indent=2)
828
844
  >>> io.save_as("users.xml", users_list, "xml", pretty=True)
829
845
  """
830
- self.save_serialized(data, file_path, format_id=format_id, **options)
846
+ try:
847
+ if format_id is None:
848
+ # Raw save (string/bytes) with path validation + atomic ops
849
+ return bool(self.save(data, file_path=file_path))
850
+
851
+ # Format-aware save via codec registry
852
+ self.save_serialized(data, file_path, format_id=format_id, **options)
853
+ return True
854
+ except Exception as e:
855
+ logger.error(f"Failed to save data to {file_path}: {e}")
856
+ return False
831
857
 
832
- def read_as(self, file_path: Union[str, Path], format_id: Optional[str] = None, **options) -> Any:
858
+ def read_as(self, file_path: str | Path, format_id: Optional[str] = None, **options) -> Any:
833
859
  """
834
860
  Read and deserialize file (auto-detect or explicit format).
835
861
 
@@ -850,7 +876,7 @@ class XWIO(AUnifiedIO):
850
876
  """
851
877
  return self.load_serialized(file_path, format_id=format_id, **options)
852
878
 
853
- def write_as(self, file_path: Union[str, Path], data: Any, format_id: Optional[str] = None, **options) -> None:
879
+ def write_as(self, file_path: str | Path, data: Any, format_id: Optional[str] = None, **options) -> None:
854
880
  """
855
881
  Serialize and write to file (auto-detect or explicit format).
856
882
 
@@ -902,7 +928,7 @@ class XWIO(AUnifiedIO):
902
928
 
903
929
  # Close async stream
904
930
  if self._async_stream:
905
- # Note: This should be called in async context
931
+ # Note: Called in async context
906
932
  logger.warning("Async stream still open - call aclose() in async context")
907
933
 
908
934
  # Cleanup temporary resources
@@ -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.411
7
+ Version: 0.1.0.3
8
8
  Generation Date: 30-Oct-2025
9
9
 
10
10
  File-specific implementations and utilities.
@@ -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.411
7
+ Version: 0.1.0.3
8
8
  Generation Date: 30-Oct-2025
9
9
 
10
10
  Base classes for file operations.
@@ -20,7 +20,7 @@ Priority 5 (Extensibility): Ready for new file types
20
20
 
21
21
  from abc import ABC, abstractmethod
22
22
  from pathlib import Path
23
- from typing import Union, Optional, Any
23
+ from typing import Optional, Any
24
24
 
25
25
  from ..contracts import IFileSource, IPagedSource, IPagingStrategy
26
26
  from ..defs import PagingMode
@@ -38,7 +38,7 @@ class AFileSource(IFileSource, ABC):
38
38
  Provides common file source functionality.
39
39
  """
40
40
 
41
- def __init__(self, path: Union[str, Path], mode: str = 'rb', encoding: Optional[str] = None):
41
+ def __init__(self, path: str | Path, mode: str = 'rb', encoding: Optional[str] = None):
42
42
  """Initialize file source."""
43
43
  self._path = Path(path)
44
44
  self._mode = mode
@@ -64,12 +64,12 @@ class AFileSource(IFileSource, ABC):
64
64
  self._path.unlink()
65
65
 
66
66
  @abstractmethod
67
- def read(self, **options) -> Union[bytes, str]:
67
+ def read(self, **options) -> bytes | str:
68
68
  """Read entire file content."""
69
69
  pass
70
70
 
71
71
  @abstractmethod
72
- def write(self, data: Union[bytes, str], **options) -> None:
72
+ def write(self, data: bytes | str, **options) -> None:
73
73
  """Write entire content to file."""
74
74
  pass
75
75
 
@@ -84,7 +84,7 @@ class APagedSource(IPagedSource, ABC):
84
84
 
85
85
  def __init__(
86
86
  self,
87
- path: Union[str, Path],
87
+ path: str | Path,
88
88
  mode: str = 'rb',
89
89
  encoding: Optional[str] = None,
90
90
  paging_strategy: Optional[IPagingStrategy] = None
@@ -116,7 +116,7 @@ class APagedSource(IPagedSource, ABC):
116
116
  return -1
117
117
  return self._path.stat().st_size
118
118
 
119
- def read_page(self, page: int, page_size: int, **options) -> Union[bytes, str]:
119
+ def read_page(self, page: int, page_size: int, **options) -> bytes | str:
120
120
  """Read specific page using strategy."""
121
121
  return self._paging_strategy.read_page(
122
122
  self._path,
@@ -138,7 +138,7 @@ class APagedSource(IPagedSource, ABC):
138
138
  )
139
139
 
140
140
  @abstractmethod
141
- def read_chunk(self, offset: int, size: int, **options) -> Union[bytes, str]:
141
+ def read_chunk(self, offset: int, size: int, **options) -> bytes | str:
142
142
  """Read chunk by byte offset."""
143
143
  pass
144
144
 
@@ -146,4 +146,3 @@ class APagedSource(IPagedSource, ABC):
146
146
  def iter_chunks(self, chunk_size: int, **options):
147
147
  """Iterate over chunks."""
148
148
  pass
149
-
@@ -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.411
7
+ Version: 0.1.0.3
8
8
  Generation Date: November 1, 2025
9
9
 
10
10
  File Format Conversion - Convert between compatible formats.
@@ -22,7 +22,7 @@ Priority 5 (Extensibility): Works with any registered codec
22
22
  """
23
23
 
24
24
  from pathlib import Path
25
- from typing import Any, Optional, Union
25
+ from typing import Any, Optional
26
26
 
27
27
  from ..codec.base import get_global_registry
28
28
  from ..contracts import ICodec
@@ -241,4 +241,3 @@ def convert_file(
241
241
  >>> convert_file(Path("data.json"), Path("data.yaml"))
242
242
  """
243
243
  _converter.convert_file(source_path, target_path, source_format, target_format, **options)
244
-
@@ -1,20 +1,29 @@
1
+ #exonware/xwsystem/src/exonware/xwsystem/io/file/file.py
1
2
  """
2
3
  Company: eXonware.com
3
4
  Author: Eng. Muhammad AlShehri
4
5
  Email: connect@exonware.com
5
- Version: 0.0.1.411
6
+ Version: 0.1.0.3
6
7
  Generation Date: September 04, 2025
7
8
 
8
9
  XWFile - Concrete implementation of file operations.
10
+
11
+ Handles reading from local paths and URIs (file, http, https, ftp, etc.)
12
+ when source_config is provided. Security and allowed schemes are configured
13
+ via SourceLoadConfig (from xwdata); xwsystem enforces it.
9
14
  """
10
15
 
16
+ from __future__ import annotations
17
+
18
+ import asyncio
11
19
  import os
12
20
  from pathlib import Path
13
- from typing import Any, Optional, Union, BinaryIO, TextIO
21
+ from typing import Any, Optional, BinaryIO, TextIO
14
22
 
15
23
  from ..base import AFile
16
24
  from ..contracts import FileMode, OperationResult, IFile
17
25
  from ..common.atomic import AtomicFileWriter
26
+ from ..source_reader import get_scheme, read_source_text, SourceLoadConfig
18
27
  from ...config.logging_setup import get_logger
19
28
  from ...security.path_validator import PathValidator
20
29
  from ...validation.data_validator import DataValidator
@@ -30,23 +39,29 @@ class XWFile(AFile):
30
39
  """
31
40
  Concrete implementation of file operations with both static and instance methods.
32
41
 
33
- This class provides a complete, production-ready implementation of file
34
- operations with xwsystem integration for security, validation, and monitoring.
42
+ Handles local paths and URIs (http, https, ftp, etc.) when source_config is set.
43
+ All read-from-URI logic and security checks live in xwsystem (source_reader);
44
+ config is supplied by callers (e.g. xwdata).
35
45
 
36
46
  Features:
37
47
  - File I/O operations (read, write, save, load)
48
+ - URI loading (file, http, https, ftp) with SourceLoadConfig
38
49
  - File metadata operations (size, permissions, timestamps)
39
- - File validation and safety checks
40
- - Static utility methods for file operations
41
50
  - xwsystem integration (security, validation, monitoring)
42
51
  """
43
52
 
44
- def __init__(self, file_path: Union[str, Path], **config):
53
+ def __init__(
54
+ self,
55
+ file_path: str | Path,
56
+ source_config: Optional[SourceLoadConfig] = None,
57
+ **config
58
+ ):
45
59
  """
46
60
  Initialize XWFile with xwsystem integration.
47
61
 
48
62
  Args:
49
- file_path: Path to file
63
+ file_path: Path to file or URI (http://..., ftp://..., etc.)
64
+ source_config: If set, load() can read from URIs; security from this config.
50
65
  **config: Configuration options for file operations
51
66
  """
52
67
  super().__init__(file_path)
@@ -54,6 +69,7 @@ class XWFile(AFile):
54
69
  # Initialize xwsystem utilities
55
70
  self._path_validator = PathValidator()
56
71
  self._data_validator = DataValidator()
72
+ self._source_config = source_config
57
73
 
58
74
  # Configuration
59
75
  self.validate_paths = config.get('validate_paths', True)
@@ -84,7 +100,7 @@ class XWFile(AFile):
84
100
  self._handle = open(self.file_path, mode.value)
85
101
  logger.debug(f"File opened: {self.file_path} in mode {mode.value}")
86
102
 
87
- def read(self, size: Optional[int] = None) -> Union[str, bytes]:
103
+ def read(self, size: Optional[int] = None) -> str | bytes:
88
104
  """Read from file with validation."""
89
105
  if not self._handle:
90
106
  raise ValueError("File not open")
@@ -97,7 +113,7 @@ class XWFile(AFile):
97
113
 
98
114
  return data
99
115
 
100
- def write(self, data: Union[str, bytes]) -> int:
116
+ def write(self, data: str | bytes) -> int:
101
117
  """Write to file with validation."""
102
118
  if not self._handle:
103
119
  raise ValueError("File not open")
@@ -138,7 +154,27 @@ class XWFile(AFile):
138
154
  return False
139
155
 
140
156
  def load(self, **kwargs) -> Any:
141
- """Load data from file with validation."""
157
+ """Load data from file or URI. For URIs uses source_reader (config-driven)."""
158
+ uri_or_path = str(self.file_path)
159
+ scheme = get_scheme(uri_or_path)
160
+
161
+ # URI (http, https, ftp): use source_reader with config (sync wrapper)
162
+ if scheme != 'file' and self._source_config is not None:
163
+ with performance_monitor("file_load"):
164
+ loop = asyncio.new_event_loop()
165
+ try:
166
+ asyncio.set_event_loop(loop)
167
+ content, _ = loop.run_until_complete(
168
+ read_source_text(uri_or_path, config=self._source_config)
169
+ )
170
+ if self.validate_data:
171
+ self._data_validator.validate_data(content)
172
+ return content
173
+ finally:
174
+ loop.close()
175
+ asyncio.set_event_loop(None)
176
+
177
+ # Local file path
142
178
  if not self.file_path.exists():
143
179
  raise FileNotFoundError(f"File not found: {self.file_path}")
144
180
 
@@ -147,7 +183,6 @@ class XWFile(AFile):
147
183
 
148
184
  with performance_monitor("file_load"):
149
185
  try:
150
- # Try to read as text first, then binary
151
186
  try:
152
187
  with open(self.file_path, 'r', encoding='utf-8') as f:
153
188
  data = f.read()
@@ -163,7 +198,7 @@ class XWFile(AFile):
163
198
  logger.error(f"Load failed for {self.file_path}: {e}")
164
199
  raise
165
200
 
166
- def save_as(self, path: Union[str, Path], data: Any, **kwargs) -> bool:
201
+ def save_as(self, path: str | Path, data: Any, **kwargs) -> bool:
167
202
  """Save data to specific path."""
168
203
  target_path = Path(path)
169
204
 
@@ -193,13 +228,13 @@ class XWFile(AFile):
193
228
  logger.error(f"Save as failed for {target_path}: {e}")
194
229
  return False
195
230
 
196
- def to_file(self, path: Union[str, Path], **kwargs) -> bool:
231
+ def to_file(self, path: str | Path, **kwargs) -> bool:
197
232
  """Write current object to file."""
198
233
  # This would depend on the specific object being saved
199
234
  # For now, we'll use the file path as the data
200
235
  return self.save_as(path, str(self.file_path), **kwargs)
201
236
 
202
- def from_file(self, path: Union[str, Path], **kwargs) -> 'File':
237
+ def from_file(self, path: str | Path, **kwargs) -> File:
203
238
  """Load object from file."""
204
239
  # Create new XWFile instance for the given path
205
240
  new_file = XWFile(path, **kwargs)
@@ -210,6 +245,14 @@ class XWFile(AFile):
210
245
  # UTILITY METHODS
211
246
  # ============================================================================
212
247
 
248
+ def exists(self) -> bool:
249
+ """Check if file exists (instance method)."""
250
+ return AFile.exists(self.file_path)
251
+
252
+ def get_size(self) -> int:
253
+ """Get file size (instance method)."""
254
+ return AFile.size(self.file_path)
255
+
213
256
  def get_info(self) -> dict[str, Any]:
214
257
  """Get comprehensive file information."""
215
258
  return {
@@ -244,8 +287,8 @@ class XWFile(AFile):
244
287
 
245
288
  @staticmethod
246
289
  def convert(
247
- source_path: Union[str, Path],
248
- target_path: Union[str, Path],
290
+ source_path: str | Path,
291
+ target_path: str | Path,
249
292
  source_format: Optional[str] = None,
250
293
  target_format: Optional[str] = None,
251
294
  **options
@@ -288,7 +331,7 @@ class XWFile(AFile):
288
331
 
289
332
  def save_as(
290
333
  self,
291
- target_path: Union[str, Path],
334
+ target_path: str | Path,
292
335
  target_format: Optional[str] = None,
293
336
  **options
294
337
  ) -> None: