exonware-xwsystem 0.1.0.1__py3-none-any.whl → 0.1.0.4__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.4.dist-info}/METADATA +71 -4
  333. exonware_xwsystem-0.1.0.4.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.4.dist-info}/WHEEL +0 -0
  341. {exonware_xwsystem-0.1.0.1.dist-info → exonware_xwsystem-0.1.0.4.dist-info}/licenses/LICENSE +0 -0
@@ -1,10 +1,11 @@
1
1
  #!/usr/bin/env python3
2
+ #exonware/xwsystem/src/exonware/xwsystem/validation/defs.py
2
3
  #exonware/xwsystem/validation/types.py
3
4
  """
4
5
  Company: eXonware.com
5
6
  Author: Eng. Muhammad AlShehri
6
7
  Email: connect@exonware.com
7
- Version: 0.1.0.1
8
+ Version: 0.1.0.4
8
9
  Generation Date: 07-Sep-2025
9
10
 
10
11
  Validation types and enums for XWSystem.
@@ -1,9 +1,10 @@
1
+ #exonware/xwsystem/src/exonware/xwsystem/validation/errors.py
1
2
  #exonware/xwsystem/validation/errors.py
2
3
  """
3
4
  Company: eXonware.com
4
5
  Author: Eng. Muhammad AlShehri
5
6
  Email: connect@exonware.com
6
- Version: 0.1.0.1
7
+ Version: 0.1.0.4
7
8
  Generation Date: September 04, 2025
8
9
 
9
10
  Validation module errors - exception classes for validation functionality.
@@ -0,0 +1,198 @@
1
+ #exonware/xwsystem/src/exonware/xwsystem/validation/facade.py
2
+ """
3
+ Company: eXonware.com
4
+ Author: Eng. Muhammad AlShehri
5
+ Email: connect@exonware.com
6
+ Version: 0.1.0.4
7
+ Generation Date: January 2026
8
+
9
+ XWValidator - Unified Validation Facade
10
+
11
+ Simplified API for validation operations:
12
+ - Quick validation
13
+ - Declarative models
14
+ - Path validation
15
+ - Data validation (depth, size)
16
+ """
17
+
18
+ from typing import Any, Optional, Dict, Type
19
+ from pathlib import Path
20
+
21
+ from .declarative import XModel, Field, ValidationError
22
+ from .data_validator import DataValidator, validate_path_input, check_data_depth, estimate_memory_usage
23
+ from .type_safety import validate_untrusted_data, SafeTypeValidator
24
+ from ..security.path_validator import PathValidator
25
+ from ..config.logging_setup import get_logger
26
+
27
+ logger = get_logger(__name__)
28
+
29
+
30
+ class XWValidator:
31
+ """
32
+ Unified validation facade - simple API for validation operations.
33
+
34
+ Examples:
35
+ >>> # Quick validation
36
+ >>> XWValidator.validate(data, rules={"age": "int", "name": "required"})
37
+
38
+ >>> # Declarative models
39
+ >>> class User(XWValidator.Model):
40
+ ... name: str = XWValidator.Field(required=True, min_length=3)
41
+ ... age: int = XWValidator.Field(min=0, max=150)
42
+
43
+ >>> user = User(name="John", age=30) # Validates automatically
44
+
45
+ >>> # Path validation
46
+ >>> XWValidator.validate_path("/safe/dir/file.txt", base_path="/safe")
47
+
48
+ >>> # Data validation
49
+ >>> XWValidator.validate_depth(data, max_depth=100)
50
+ >>> XWValidator.validate_size(data, max_size_mb=10)
51
+ """
52
+
53
+ # Re-export XModel and Field for convenience
54
+ Model = XModel
55
+ Field = Field
56
+
57
+ @staticmethod
58
+ def validate(data: Any, rules: Dict[str, Any]) -> bool:
59
+ """
60
+ Quick validation with rules dictionary.
61
+
62
+ Args:
63
+ data: Data to validate
64
+ rules: Validation rules (e.g., {"age": "int", "name": "required"})
65
+
66
+ Returns:
67
+ True if valid
68
+
69
+ Raises:
70
+ ValidationError: If validation fails
71
+ """
72
+ # Simple rule-based validation
73
+ if not isinstance(data, dict):
74
+ raise ValidationError("Data must be a dictionary")
75
+
76
+ for key, rule in rules.items():
77
+ if rule == "required" and key not in data:
78
+ raise ValidationError(f"Required field missing: {key}")
79
+ elif key in data:
80
+ value = data[key]
81
+ if rule == "int" and not isinstance(value, int):
82
+ raise ValidationError(f"Field {key} must be int, got {type(value).__name__}")
83
+ elif rule == "str" and not isinstance(value, str):
84
+ raise ValidationError(f"Field {key} must be str, got {type(value).__name__}")
85
+
86
+ return True
87
+
88
+ @staticmethod
89
+ def validate_path(path: str, base_path: Optional[str] = None, must_exist: bool = False) -> str:
90
+ """
91
+ Validate and sanitize file path.
92
+
93
+ Args:
94
+ path: Path to validate
95
+ base_path: Base directory (prevents directory traversal)
96
+ must_exist: Whether path must exist (default: False)
97
+
98
+ Returns:
99
+ Validated path
100
+
101
+ Raises:
102
+ ValidationError: If path is invalid
103
+ """
104
+ try:
105
+ validator = PathValidator(base_path) if base_path else PathValidator()
106
+ validated = validator.validate_path(path)
107
+
108
+ # Check existence if required
109
+ if must_exist and not Path(validated).exists():
110
+ raise ValidationError(f"Path does not exist: {validated}")
111
+
112
+ return validated
113
+ except ValidationError:
114
+ raise
115
+ except Exception as e:
116
+ raise ValidationError(f"Path validation failed: {e}") from e
117
+
118
+ @staticmethod
119
+ def validate_depth(data: Any, max_depth: int = 100) -> bool:
120
+ """
121
+ Validate data depth.
122
+
123
+ Args:
124
+ data: Data to validate
125
+ max_depth: Maximum allowed depth
126
+
127
+ Returns:
128
+ True if depth is within limits
129
+
130
+ Raises:
131
+ ValidationError: If depth exceeds limit
132
+ """
133
+ # check_data_depth raises exception if depth exceeds, returns None otherwise
134
+ try:
135
+ check_data_depth(data, max_depth=max_depth)
136
+ return True
137
+ except Exception as e:
138
+ raise ValidationError(f"Data depth validation failed: {e}") from e
139
+
140
+ @staticmethod
141
+ def validate_size(data: Any, max_size_mb: int = 10) -> bool:
142
+ """
143
+ Validate data size.
144
+
145
+ Args:
146
+ data: Data to validate
147
+ max_size_mb: Maximum size in MB
148
+
149
+ Returns:
150
+ True if size is within limits
151
+
152
+ Raises:
153
+ ValidationError: If size exceeds limit
154
+ """
155
+ size_mb = estimate_memory_usage(data) / (1024 * 1024)
156
+ if size_mb > max_size_mb:
157
+ raise ValidationError(f"Data size {size_mb:.2f}MB exceeds maximum {max_size_mb}MB")
158
+ return True
159
+
160
+ @staticmethod
161
+ def validate_untrusted(data: Any, max_depth: int = 100) -> bool:
162
+ """
163
+ Validate untrusted data with security checks.
164
+
165
+ Args:
166
+ data: Untrusted data to validate
167
+ max_depth: Maximum allowed depth
168
+
169
+ Returns:
170
+ True if valid
171
+
172
+ Raises:
173
+ ValidationError: If validation fails
174
+ """
175
+ return validate_untrusted_data(data, max_depth=max_depth)
176
+
177
+ @classmethod
178
+ def create_model(cls, **fields) -> Type[XModel]:
179
+ """
180
+ Create a model class dynamically.
181
+
182
+ Args:
183
+ **fields: Field definitions
184
+
185
+ Returns:
186
+ Model class
187
+ """
188
+ # Create a dynamic model class
189
+ class DynamicModel(XModel):
190
+ pass
191
+
192
+ for name, field_def in fields.items():
193
+ if isinstance(field_def, Field):
194
+ setattr(DynamicModel, name, field_def)
195
+ else:
196
+ setattr(DynamicModel, name, Field(default=field_def))
197
+
198
+ return DynamicModel
@@ -1,15 +1,18 @@
1
1
  #!/usr/bin/env python3
2
+ #exonware/xwsystem/src/exonware/xwsystem/validation/fluent_validator.py
2
3
  """
3
4
  Company: eXonware.com
4
5
  Author: Eng. Muhammad AlShehri
5
6
  Email: connect@exonware.com
6
- Version: 0.1.0.1
7
+ Version: 0.1.0.4
7
8
  Generation Date: October 26, 2025
8
9
 
9
10
  Fluent validator with chainable API for data validation.
10
11
  """
11
12
 
12
- from typing import Any, Callable, Optional, Union
13
+ from __future__ import annotations
14
+
15
+ from typing import Any, Callable, Optional
13
16
  from .errors import ValidationError
14
17
  from ..config.logging_setup import get_logger
15
18
 
@@ -40,7 +43,7 @@ class FluentValidator:
40
43
  self.errors: list[str] = []
41
44
  self.rules: list[dict[str, Any]] = []
42
45
 
43
- def require(self, field_name: str, message: Optional[str] = None) -> 'FluentValidator':
46
+ def require(self, field_name: str, message: Optional[str] = None) -> FluentValidator:
44
47
  """
45
48
  Require a field to be present and not None.
46
49
 
@@ -65,7 +68,7 @@ class FluentValidator:
65
68
 
66
69
  return self
67
70
 
68
- def type_check(self, expected_type: type, message: Optional[str] = None) -> 'FluentValidator':
71
+ def type_check(self, expected_type: type, message: Optional[str] = None) -> FluentValidator:
69
72
  """
70
73
  Check if data is of expected type.
71
74
 
@@ -88,10 +91,10 @@ class FluentValidator:
88
91
 
89
92
  def range_check(
90
93
  self,
91
- min_value: Optional[Union[int, float]] = None,
92
- max_value: Optional[Union[int, float]] = None,
94
+ min_value: Optional[int | float] = None,
95
+ max_value: Optional[int | float] = None,
93
96
  message: Optional[str] = None
94
- ) -> 'FluentValidator':
97
+ ) -> FluentValidator:
95
98
  """
96
99
  Check if numeric data is within range.
97
100
 
@@ -128,7 +131,7 @@ class FluentValidator:
128
131
  min_length: Optional[int] = None,
129
132
  max_length: Optional[int] = None,
130
133
  message: Optional[str] = None
131
- ) -> 'FluentValidator':
134
+ ) -> FluentValidator:
132
135
  """
133
136
  Check if data length is within range.
134
137
 
@@ -162,7 +165,7 @@ class FluentValidator:
162
165
 
163
166
  return self
164
167
 
165
- def pattern_check(self, pattern: str, message: Optional[str] = None) -> 'FluentValidator':
168
+ def pattern_check(self, pattern: str, message: Optional[str] = None) -> FluentValidator:
166
169
  """
167
170
  Check if string data matches pattern (regex).
168
171
 
@@ -191,7 +194,7 @@ class FluentValidator:
191
194
 
192
195
  return self
193
196
 
194
- def add_rule(self, validator_func: Callable[[Any], bool], message: Optional[str] = None) -> 'FluentValidator':
197
+ def add_rule(self, validator_func: Callable[[Any], bool], message: Optional[str] = None) -> FluentValidator:
195
198
  """
196
199
  Add custom validation rule.
197
200
 
@@ -216,7 +219,7 @@ class FluentValidator:
216
219
  """Check if data is valid (no errors)."""
217
220
  return len(self.errors) == 0
218
221
 
219
- def validate(self) -> 'FluentValidator':
222
+ def validate(self) -> FluentValidator:
220
223
  """
221
224
  Validate data and raise ValidationError if invalid.
222
225
 
@@ -234,12 +237,12 @@ class FluentValidator:
234
237
  """Get list of validation errors."""
235
238
  return self.errors.copy()
236
239
 
237
- def clear_errors(self) -> 'FluentValidator':
240
+ def clear_errors(self) -> FluentValidator:
238
241
  """Clear all validation errors."""
239
242
  self.errors.clear()
240
243
  return self
241
244
 
242
- def set_data(self, data: Any) -> 'FluentValidator':
245
+ def set_data(self, data: Any) -> FluentValidator:
243
246
  """Set data to validate."""
244
247
  self.data = data
245
248
  return self
@@ -248,8 +251,8 @@ class FluentValidator:
248
251
  self,
249
252
  field_name: str,
250
253
  field_data: Any,
251
- rules: list[Callable[['FluentValidator'], 'FluentValidator']]
252
- ) -> 'FluentValidator':
254
+ rules: list[Callable[[FluentValidator], FluentValidator]]
255
+ ) -> FluentValidator:
253
256
  """
254
257
  Validate a specific field with rules.
255
258
 
@@ -280,8 +283,8 @@ class FluentValidator:
280
283
 
281
284
  def validate_dict_fields(
282
285
  self,
283
- field_rules: dict[str, list[Callable[['FluentValidator'], 'FluentValidator']]]
284
- ) -> 'FluentValidator':
286
+ field_rules: dict[str, list[Callable[[FluentValidator], FluentValidator]]]
287
+ ) -> FluentValidator:
285
288
  """
286
289
  Validate multiple fields in a dictionary.
287
290
 
@@ -342,7 +345,7 @@ def validate_string(data: str) -> FluentValidator:
342
345
  return FluentValidator(data)
343
346
 
344
347
 
345
- def validate_numeric(data: Union[int, float]) -> FluentValidator:
348
+ def validate_numeric(data: int | float) -> FluentValidator:
346
349
  """
347
350
  Create a fluent validator for numeric data.
348
351
 
@@ -366,7 +369,7 @@ def is_type(expected_type: type) -> Callable[[FluentValidator], FluentValidator]
366
369
  return lambda v: v.type_check(expected_type)
367
370
 
368
371
 
369
- def is_in_range(min_val: Optional[Union[int, float]] = None, max_val: Optional[Union[int, float]] = None) -> Callable[[FluentValidator], FluentValidator]:
372
+ def is_in_range(min_val: Optional[int | float] = None, max_val: Optional[int | float] = None) -> Callable[[FluentValidator], FluentValidator]:
370
373
  """Create a range check rule."""
371
374
  return lambda v: v.range_check(min_val, max_val)
372
375
 
@@ -0,0 +1,210 @@
1
+ #!/usr/bin/env python3
2
+ #exonware/xwsystem/src/exonware/xwsystem/validation/schema_discovery.py
3
+ """
4
+ Schema validator discovery (plugin entry points).
5
+
6
+ This module provides a lightweight "plugin" mechanism (via Python packaging
7
+ entry points) to discover an implementation of
8
+ `xwsystem.validation.contracts.ISchemaProvider`.
9
+
10
+ Why this exists:
11
+ - Avoids hard dependency cycles (e.g., xwdata <-> xwschema)
12
+ - Keeps xwsystem as the stable contract owner
13
+ - Enables optional providers to be installed and discovered at runtime
14
+
15
+ Entry point group:
16
+ - xwsystem.schema_validators
17
+
18
+ Providers should register an entry point that resolves to either:
19
+ - an ISchemaProvider instance
20
+ - a class (constructible with no args) returning an ISchemaProvider instance
21
+ - a callable (factory) returning an ISchemaProvider instance
22
+ """
23
+
24
+ from __future__ import annotations
25
+
26
+ from dataclasses import dataclass
27
+ import threading
28
+ from typing import Any, Optional
29
+
30
+ from ..config.logging_setup import get_logger
31
+ from .contracts import ISchemaProvider
32
+
33
+ logger = get_logger("xwsystem.validation.schema_discovery")
34
+
35
+
36
+ DEFAULT_SCHEMA_VALIDATOR_ENTRYPOINT_GROUP = "xwsystem.schema_validators"
37
+
38
+
39
+ @dataclass(frozen=True)
40
+ class SchemaValidatorDiscoveryResult:
41
+ """Structured discovery information for observability/debugging."""
42
+
43
+ group: str
44
+ loaded: dict[str, str] # name -> provider repr
45
+ errors: dict[str, str] # name -> error string
46
+
47
+
48
+ _lock = threading.RLock()
49
+ _attempted_groups: set[str] = set()
50
+ _providers_by_group: dict[str, dict[str, ISchemaProvider]] = {}
51
+ _default_provider_by_group: dict[str, str] = {}
52
+
53
+
54
+ def _as_schema_provider(obj: Any) -> Optional[ISchemaProvider]:
55
+ """Coerce an entry-point loaded object into an ISchemaProvider instance."""
56
+ if obj is None:
57
+ return None
58
+
59
+ # 1) Direct instance
60
+ try:
61
+ if isinstance(obj, ISchemaProvider):
62
+ return obj
63
+ except Exception:
64
+ # Protocol runtime checks can raise if obj is weird; treat as not valid.
65
+ return None
66
+
67
+ # 2) Class -> instantiate
68
+ if isinstance(obj, type):
69
+ try:
70
+ inst = obj()
71
+ except Exception:
72
+ return None
73
+ try:
74
+ return inst if isinstance(inst, ISchemaProvider) else None
75
+ except Exception:
76
+ return None
77
+
78
+ # 3) Factory callable -> call
79
+ if callable(obj):
80
+ try:
81
+ inst = obj()
82
+ except Exception:
83
+ return None
84
+ try:
85
+ return inst if isinstance(inst, ISchemaProvider) else None
86
+ except Exception:
87
+ return None
88
+
89
+ return None
90
+
91
+
92
+ def discover_schema_validators(
93
+ *,
94
+ group: str = DEFAULT_SCHEMA_VALIDATOR_ENTRYPOINT_GROUP,
95
+ force: bool = False,
96
+ ) -> tuple[dict[str, ISchemaProvider], SchemaValidatorDiscoveryResult]:
97
+ """
98
+ Discover schema validator providers from entry points.
99
+
100
+ Args:
101
+ group: Entry-point group to search.
102
+ force: If True, re-run discovery even if already attempted.
103
+
104
+ Returns:
105
+ (providers, discovery_result)
106
+ """
107
+ with _lock:
108
+ already_attempted = group in _attempted_groups
109
+ if already_attempted and not force:
110
+ providers = dict(_providers_by_group.get(group, {}))
111
+ loaded_repr = {k: repr(v) for k, v in providers.items()}
112
+ return providers, SchemaValidatorDiscoveryResult(group=group, loaded=loaded_repr, errors={})
113
+
114
+ loaded: dict[str, ISchemaProvider] = {}
115
+ loaded_repr: dict[str, str] = {}
116
+ errors: dict[str, str] = {}
117
+
118
+ try:
119
+ from importlib.metadata import entry_points
120
+ eps = entry_points(group=group)
121
+ except Exception as e:
122
+ # Cache attempted to avoid repeated expensive failures.
123
+ with _lock:
124
+ _attempted_groups.add(group)
125
+ _providers_by_group.setdefault(group, {})
126
+ logger.debug(f"Schema validator discovery failed for group '{group}': {e}")
127
+ return {}, SchemaValidatorDiscoveryResult(group=group, loaded={}, errors={"__discovery__": str(e)})
128
+
129
+ for ep in eps:
130
+ name = getattr(ep, "name", "<unknown>")
131
+ try:
132
+ obj = ep.load()
133
+ inst = _as_schema_provider(obj)
134
+ if inst is None:
135
+ errors[name] = "Entry point did not resolve to an ISchemaProvider (instance/class/factory)."
136
+ continue
137
+ loaded[name] = inst
138
+ loaded_repr[name] = repr(inst)
139
+ except Exception as e:
140
+ errors[name] = str(e)
141
+
142
+ with _lock:
143
+ _attempted_groups.add(group)
144
+ _providers_by_group[group] = dict(loaded)
145
+ # Preserve existing default selection if still valid; else choose first.
146
+ if group not in _default_provider_by_group or _default_provider_by_group[group] not in loaded:
147
+ if loaded:
148
+ _default_provider_by_group[group] = sorted(loaded.keys())[0]
149
+
150
+ if errors:
151
+ logger.debug(f"Schema validator discovery had errors for group '{group}': {errors}")
152
+
153
+ return dict(loaded), SchemaValidatorDiscoveryResult(group=group, loaded=loaded_repr, errors=errors)
154
+
155
+
156
+ def set_schema_validator(
157
+ validator: ISchemaProvider,
158
+ *,
159
+ name: str = "manual",
160
+ group: str = DEFAULT_SCHEMA_VALIDATOR_ENTRYPOINT_GROUP,
161
+ make_default: bool = True,
162
+ ) -> None:
163
+ """Manually register a schema provider (useful for tests / custom wiring)."""
164
+ with _lock:
165
+ _attempted_groups.add(group)
166
+ _providers_by_group.setdefault(group, {})
167
+ _providers_by_group[group][name] = validator
168
+ if make_default:
169
+ _default_provider_by_group[group] = name
170
+
171
+
172
+ def get_schema_validator(
173
+ *,
174
+ name: Optional[str] = None,
175
+ group: str = DEFAULT_SCHEMA_VALIDATOR_ENTRYPOINT_GROUP,
176
+ ) -> Optional[ISchemaProvider]:
177
+ """
178
+ Get a schema provider (validator).
179
+
180
+ Args:
181
+ name: Optional provider name; if omitted, returns the group's default provider.
182
+ group: Entry-point group.
183
+
184
+ Returns:
185
+ ISchemaProvider instance or None if no providers available.
186
+ """
187
+ providers, _ = discover_schema_validators(group=group, force=False)
188
+ if not providers:
189
+ return None
190
+
191
+ if name:
192
+ return providers.get(name)
193
+
194
+ with _lock:
195
+ default_name = _default_provider_by_group.get(group)
196
+
197
+ if default_name and default_name in providers:
198
+ return providers[default_name]
199
+
200
+ # Fall back to deterministic choice
201
+ return providers[sorted(providers.keys())[0]]
202
+
203
+
204
+ def available_schema_validators(
205
+ *,
206
+ group: str = DEFAULT_SCHEMA_VALIDATOR_ENTRYPOINT_GROUP,
207
+ ) -> list[str]:
208
+ """List discovered provider names."""
209
+ providers, _ = discover_schema_validators(group=group, force=False)
210
+ return sorted(providers.keys())
@@ -1,3 +1,4 @@
1
+ #exonware/xwsystem/src/exonware/xwsystem/validation/type_safety.py
1
2
  """
2
3
  Generic type safety validation.
3
4
 
@@ -20,7 +21,7 @@ class SafeTypeValidator:
20
21
  # Allowed types for untrusted data
21
22
  SAFE_TYPES = (str, int, float, bool, list, dict, type(None))
22
23
 
23
- # Types that are always safe to cache
24
+ # Types that are safe to cache
24
25
  IMMUTABLE_TYPES = (str, int, float, bool, tuple, frozenset, type(None))
25
26
 
26
27
  @classmethod
@@ -14,13 +14,13 @@ All version references should import from this module to ensure consistency.
14
14
  # =============================================================================
15
15
 
16
16
  # Main version - update this to change version across entire project
17
- __version__ = "0.1.0.1"
17
+ __version__ = "0.1.0.4"
18
18
 
19
19
  # Version components for programmatic access
20
20
  VERSION_MAJOR = 0
21
21
  VERSION_MINOR = 1
22
22
  VERSION_PATCH = 0
23
- VERSION_BUILD = 1 # Set to None for releases, or build number for dev builds
23
+ VERSION_BUILD = 4 # Set to None for releases, or build number for dev builds
24
24
 
25
25
  # Version metadata
26
26
  VERSION_SUFFIX = "" # e.g., "dev", "alpha", "beta", "rc1"