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
@@ -0,0 +1,185 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ #exonware/xwsystem/src/exonware/xwsystem/utils/test_runner.py
4
+
5
+ Reusable pytest runner utilities for all eXonware libraries.
6
+
7
+ Implements the hierarchical runner utilities described in:
8
+ - docs/guides/GUIDE_DEV.md
9
+ - docs/guides/GUIDE_TEST.md
10
+
11
+ Company: eXonware.com
12
+ Author: Eng. Muhammad AlShehri
13
+ Email: connect@exonware.com
14
+ Version: 0.1.0.4
15
+ Generation Date: 28-Dec-2025
16
+ """
17
+
18
+ from __future__ import annotations
19
+
20
+ import sys
21
+ import subprocess
22
+ from dataclasses import dataclass
23
+ from datetime import datetime
24
+ from pathlib import Path
25
+ from typing import Any, Optional
26
+
27
+ from exonware.xwsystem.console.cli import ensure_utf8_console
28
+
29
+
30
+ def format_path(path: Path) -> str:
31
+ """Format a path as a full absolute path string."""
32
+ return str(path.resolve())
33
+
34
+
35
+ class DualOutput:
36
+ """
37
+ Capture output for terminal and Markdown file simultaneously.
38
+ """
39
+
40
+ def __init__(self, output_file: Path):
41
+ self.output_file = output_file
42
+ self._markdown_lines: list[str] = []
43
+
44
+ def print(self, text: str, markdown_format: Optional[str] = None, *, emoji: Optional[str] = None) -> None:
45
+ prefix = f"{emoji} " if emoji else ""
46
+ line = f"{prefix}{text}"
47
+ print(line)
48
+ self._markdown_lines.append(markdown_format if markdown_format is not None else line)
49
+
50
+ def save(self, header_info: Optional[dict[str, Any]] = None) -> None:
51
+ header_info = header_info or {}
52
+ header = (
53
+ "# Test Runner Output\n\n"
54
+ f"**Library:** {header_info.get('library', '')} \n"
55
+ f"**Layer:** {header_info.get('layer', '')} \n"
56
+ f"**Generated:** {datetime.now().strftime('%d-%b-%Y %H:%M:%S')} \n"
57
+ f"**Runner:** {header_info.get('runner', 'TestRunner')} \n\n"
58
+ "---\n\n"
59
+ )
60
+ self.output_file.write_text(header + "\n".join(self._markdown_lines) + "\n", encoding="utf-8")
61
+
62
+
63
+ def print_header(title: str, output: Optional[DualOutput] = None) -> None:
64
+ sep = "=" * 80
65
+ if output is None:
66
+ print(sep)
67
+ print(title)
68
+ print(sep)
69
+ return
70
+ output.print(sep)
71
+ output.print(title)
72
+ output.print(sep)
73
+
74
+
75
+ def print_section(title: str, output: Optional[DualOutput] = None) -> None:
76
+ if output is None:
77
+ print(f"\n{'=' * 80}\n{title}\n{'=' * 80}\n")
78
+ return
79
+ output.print(f"\n{title}", f"\n## {title}\n")
80
+
81
+
82
+ def print_status(success: bool, message: str, output: Optional[DualOutput] = None) -> None:
83
+ emoji = "✅" if success else "❌"
84
+ if output is None:
85
+ print(f"{emoji} {message}")
86
+ return
87
+ output.print(message, f"**Result:** {emoji} {message}", emoji=emoji)
88
+
89
+
90
+ @dataclass(frozen=True)
91
+ class PytestRunResult:
92
+ exit_code: int
93
+
94
+
95
+ def run_pytest(
96
+ *,
97
+ test_dir: Path,
98
+ markers: Optional[list[str]] = None,
99
+ extra_args: Optional[list[str]] = None,
100
+ cwd: Optional[Path] = None,
101
+ ) -> PytestRunResult:
102
+ """
103
+ Run pytest as a subprocess with standard eXonware flags.
104
+ """
105
+ markers = markers or []
106
+ extra_args = extra_args or []
107
+ cwd = cwd or test_dir
108
+
109
+ args: list[str] = [
110
+ sys.executable,
111
+ "-m",
112
+ "pytest",
113
+ str(test_dir),
114
+ "-v",
115
+ "--tb=short",
116
+ "-x",
117
+ "--strict-markers",
118
+ ]
119
+ if markers:
120
+ args.extend(["-m", " and ".join(markers)])
121
+ args.extend(extra_args)
122
+
123
+ completed = subprocess.run(args, cwd=str(cwd))
124
+ return PytestRunResult(exit_code=int(completed.returncode))
125
+
126
+
127
+ class TestRunner:
128
+ """
129
+ Simple reusable test runner for a single directory/layer.
130
+ """
131
+
132
+ def __init__(
133
+ self,
134
+ *,
135
+ library_name: str,
136
+ layer_name: str,
137
+ description: str,
138
+ test_dir: Path,
139
+ markers: Optional[list[str]] = None,
140
+ output_file: Optional[Path] = None,
141
+ ):
142
+ self.library_name = library_name
143
+ self.layer_name = layer_name
144
+ self.description = description
145
+ self.test_dir = test_dir
146
+ self.markers = markers or []
147
+
148
+ # Layer runners should pass output_file=None to not write files
149
+ # Only main runner writes to docs/logs/tests/
150
+ self.output_file = output_file
151
+ if self.output_file is None:
152
+ # Layer runner - create dummy output that won't save
153
+ # Use a temporary path that we'll ignore
154
+ import tempfile
155
+ dummy_file = Path(tempfile.gettempdir()) / "xwsystem_test_runner_dummy.md"
156
+ self.output = DualOutput(dummy_file)
157
+ self._is_layer_runner = True
158
+ else:
159
+ self.output = DualOutput(self.output_file)
160
+ self._is_layer_runner = False
161
+
162
+ def run(self) -> int:
163
+ ensure_utf8_console()
164
+
165
+ print_header(self.description, self.output)
166
+ self.output.print(
167
+ f"Directory: {format_path(self.test_dir)}",
168
+ f"**Directory:** `{format_path(self.test_dir)}`",
169
+ emoji="📂",
170
+ )
171
+
172
+ result = run_pytest(test_dir=self.test_dir, markers=self.markers)
173
+ ok = result.exit_code == 0
174
+ print_status(ok, "PASSED" if ok else "FAILED", self.output)
175
+
176
+ # Layer runners don't write files - only main runner writes to docs/logs/tests/
177
+ if not self._is_layer_runner:
178
+ self.output.save(
179
+ {
180
+ "library": self.library_name,
181
+ "layer": self.layer_name,
182
+ "runner": "TestRunner",
183
+ }
184
+ )
185
+ return result.exit_code
@@ -1,10 +1,11 @@
1
1
  #!/usr/bin/env python3
2
+ #exonware/xwsystem/src/exonware/xwsystem/utils/utils_contracts.py
2
3
  #exonware/xwsystem/utils/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
  Utils types and enums for XWSystem.
@@ -0,0 +1,110 @@
1
+ #!/usr/bin/env python3
2
+ #exonware/xwsystem/src/exonware/xwsystem/utils/web.py
3
+ """
4
+ Company: eXonware.com
5
+ Author: Eng. Muhammad AlShehri
6
+ Email: connect@exonware.com
7
+ Version: 0.1.0.4
8
+ Generation Date: January 2025
9
+
10
+ Web utility functions for XSystem.
11
+ """
12
+
13
+ from typing import Optional
14
+ from urllib.parse import urlparse
15
+
16
+ # Prevent BeautifulSoup from trying to import lxml (which has Python 2 syntax issues)
17
+ # Block lxml import before BeautifulSoup tries to import it
18
+ import sys
19
+ if 'lxml' not in sys.modules:
20
+ # Create a dummy module to prevent lxml from being imported
21
+ class DummyModule:
22
+ pass
23
+ sys.modules['lxml'] = DummyModule()
24
+ sys.modules['lxml.etree'] = DummyModule()
25
+ sys.modules['lxml.html'] = DummyModule()
26
+
27
+
28
+ def validate_url_accessible(url: str, timeout: int = 10) -> bool:
29
+ """
30
+ Validate that a URL is accessible.
31
+
32
+ Args:
33
+ url: URL to validate
34
+ timeout: Request timeout in seconds
35
+
36
+ Returns:
37
+ True if URL is accessible (status 200), False otherwise
38
+
39
+ Examples:
40
+ >>> validate_url_accessible("https://www.example.com")
41
+ True
42
+ >>> validate_url_accessible("https://invalid-url-that-does-not-exist.com")
43
+ False
44
+ """
45
+ try:
46
+ parsed_url = urlparse(url)
47
+ if not all([parsed_url.scheme in ["http", "https"], parsed_url.netloc]):
48
+ return False
49
+
50
+ # Optional dependency: requests
51
+ import importlib.util
52
+ _requests_spec = importlib.util.find_spec('requests')
53
+ if _requests_spec is None:
54
+ # If requests is not available, we can't validate
55
+ return False
56
+ import requests
57
+
58
+ try:
59
+ # First try a HEAD request (more efficient)
60
+ response = requests.head(url, allow_redirects=True, timeout=timeout)
61
+ except requests.RequestException:
62
+ # If HEAD request fails, try a GET request
63
+ response = requests.get(url, allow_redirects=True, timeout=timeout)
64
+
65
+ # Check if the status code indicates success
66
+ return response.status_code == 200
67
+
68
+ except (requests.RequestException, Exception):
69
+ return False
70
+
71
+
72
+ def extract_webpage_text(url: str) -> str:
73
+ """
74
+ Extract text content from a webpage.
75
+
76
+ Args:
77
+ url: URL to extract text from
78
+
79
+ Returns:
80
+ Extracted text content
81
+
82
+ Examples:
83
+ >>> text = extract_webpage_text("https://www.example.com")
84
+ >>> len(text) > 0
85
+ True
86
+ """
87
+ from urllib.request import urlopen
88
+ from bs4 import BeautifulSoup
89
+
90
+ html = urlopen(url).read()
91
+ soup = BeautifulSoup(html, features="html.parser")
92
+
93
+ # Remove script and style elements
94
+ for script in soup(["script", "style"]):
95
+ script.extract()
96
+
97
+ # Get text
98
+ text = soup.get_text()
99
+
100
+ # Break into lines and remove leading/trailing space
101
+ lines = (line.strip() for line in text.splitlines())
102
+ chunks = (phrase.strip() for line in lines for phrase in line.split(" "))
103
+ # Drop blank lines
104
+ return '\n'.join(chunk for chunk in chunks if chunk)
105
+
106
+
107
+ __all__ = [
108
+ 'validate_url_accessible',
109
+ 'extract_webpage_text',
110
+ ]
@@ -1,8 +1,9 @@
1
+ #exonware/xwsystem/src/exonware/xwsystem/validation/__init__.py
1
2
  """
2
3
  Company: eXonware.com
3
4
  Author: Eng. Muhammad AlShehri
4
5
  Email: connect@exonware.com
5
- Version: 0.1.0.1
6
+ Version: 0.1.0.4
6
7
  Generation Date: September 04, 2025
7
8
 
8
9
  XSystem Validation Package
@@ -12,10 +13,33 @@ Declarative validation with type hints, automatic coercion, and Pydantic-style m
12
13
 
13
14
  from .declarative import XModel, Field, ValidationError
14
15
  from .type_safety import validate_untrusted_data
16
+ from .contracts import ISchemaProvider
17
+ from .schema_discovery import (
18
+ DEFAULT_SCHEMA_VALIDATOR_ENTRYPOINT_GROUP,
19
+ SchemaValidatorDiscoveryResult,
20
+ discover_schema_validators,
21
+ get_schema_validator,
22
+ set_schema_validator,
23
+ available_schema_validators,
24
+ )
25
+
26
+ # Unified Facade
27
+ from .facade import XWValidator
15
28
 
16
29
  __all__ = [
30
+ # Unified Facade
31
+ "XWValidator",
32
+ # Core Classes
17
33
  "XModel",
18
34
  "Field",
19
35
  "ValidationError",
20
36
  "validate_untrusted_data",
37
+ # Schema validation contracts + discovery (optional providers)
38
+ "ISchemaProvider",
39
+ "DEFAULT_SCHEMA_VALIDATOR_ENTRYPOINT_GROUP",
40
+ "SchemaValidatorDiscoveryResult",
41
+ "discover_schema_validators",
42
+ "get_schema_validator",
43
+ "set_schema_validator",
44
+ "available_schema_validators",
21
45
  ]
@@ -1,16 +1,17 @@
1
+ #exonware/xwsystem/src/exonware/xwsystem/validation/base.py
1
2
  #exonware/xwsystem/validation/base.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 base classes - abstract classes for validation functionality.
10
11
  """
11
12
 
12
13
  from abc import ABC, abstractmethod
13
- from typing import Any, Optional, Union, Callable
14
+ from typing import Any, Optional, Callable
14
15
  # Root cause: Migrating to Python 3.12 built-in generic syntax for consistency
15
16
  # Priority #3: Maintainability - Modern type annotations improve code clarity
16
17
  from .contracts import ValidationType, ValidationLevel, ConstraintType, SchemaType
@@ -102,13 +103,13 @@ class ADataValidatorBase(ABC):
102
103
  pass
103
104
 
104
105
  @abstractmethod
105
- def validate_range(self, data: Union[int, float], min_value: Optional[Union[int, float]] = None,
106
- max_value: Optional[Union[int, float]] = None) -> bool:
106
+ def validate_range(self, data: int | float, min_value: Optional[int | float] = None,
107
+ max_value: Optional[int | float] = None) -> bool:
107
108
  """Validate data range."""
108
109
  pass
109
110
 
110
111
  @abstractmethod
111
- def validate_length(self, data: Union[str, list, dict], min_length: Optional[int] = None,
112
+ def validate_length(self, data: str | list | dict, min_length: Optional[int] = None,
112
113
  max_length: Optional[int] = None) -> bool:
113
114
  """Validate data length."""
114
115
  pass
@@ -1,17 +1,16 @@
1
1
  #!/usr/bin/env python3
2
+ #exonware/xwsystem/src/exonware/xwsystem/validation/contracts.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 protocol interfaces for XWSystem.
10
11
  """
11
12
 
12
- from abc import ABC, abstractmethod
13
- from typing import Any, Optional, Union, Iterator, Callable, Protocol
14
- from typing_extensions import runtime_checkable
13
+ from typing import Any, Optional, Iterator, Callable, Protocol, runtime_checkable
15
14
 
16
15
  # Import enums from types module
17
16
  from .defs import (
@@ -25,14 +24,14 @@ from .defs import (
25
24
  # VALIDATION INTERFACES
26
25
  # ============================================================================
27
26
 
28
- class IValidatable(ABC):
27
+ @runtime_checkable
28
+ class IValidatable(Protocol):
29
29
  """
30
30
  Interface for objects that can be validated.
31
31
 
32
32
  Enforces consistent validation behavior across XWSystem.
33
33
  """
34
34
 
35
- @abstractmethod
36
35
  def validate(self) -> bool:
37
36
  """
38
37
  Validate this object.
@@ -40,9 +39,8 @@ class IValidatable(ABC):
40
39
  Returns:
41
40
  True if valid
42
41
  """
43
- pass
42
+ ...
44
43
 
45
- @abstractmethod
46
44
  def is_valid(self) -> bool:
47
45
  """
48
46
  Check if object is valid.
@@ -50,9 +48,8 @@ class IValidatable(ABC):
50
48
  Returns:
51
49
  True if valid
52
50
  """
53
- pass
51
+ ...
54
52
 
55
- @abstractmethod
56
53
  def get_errors(self) -> list[str]:
57
54
  """
58
55
  Get validation errors.
@@ -60,16 +57,14 @@ class IValidatable(ABC):
60
57
  Returns:
61
58
  List of error messages
62
59
  """
63
- pass
60
+ ...
64
61
 
65
- @abstractmethod
66
62
  def clear_errors(self) -> None:
67
63
  """
68
64
  Clear validation errors.
69
65
  """
70
- pass
66
+ ...
71
67
 
72
- @abstractmethod
73
68
  def has_errors(self) -> bool:
74
69
  """
75
70
  Check if object has validation errors.
@@ -77,9 +72,8 @@ class IValidatable(ABC):
77
72
  Returns:
78
73
  True if has errors
79
74
  """
80
- pass
75
+ ...
81
76
 
82
- @abstractmethod
83
77
  def add_error(self, error: str) -> None:
84
78
  """
85
79
  Add validation error.
@@ -87,21 +81,21 @@ class IValidatable(ABC):
87
81
  Args:
88
82
  error: Error message
89
83
  """
90
- pass
84
+ ...
91
85
 
92
86
 
93
87
  # ============================================================================
94
88
  # VALIDATION MANAGER INTERFACES
95
89
  # ============================================================================
96
90
 
97
- class IValidationManager(ABC):
91
+ @runtime_checkable
92
+ class IValidationManager(Protocol):
98
93
  """
99
94
  Interface for validation management.
100
95
 
101
96
  Enforces consistent validation management across XWSystem.
102
97
  """
103
98
 
104
- @abstractmethod
105
99
  def add_validator(self, name: str, validator: Callable[[Any], bool]) -> None:
106
100
  """
107
101
  Add validator function.
@@ -110,9 +104,8 @@ class IValidationManager(ABC):
110
104
  name: Validator name
111
105
  validator: Validator function
112
106
  """
113
- pass
107
+ ...
114
108
 
115
- @abstractmethod
116
109
  def remove_validator(self, name: str) -> bool:
117
110
  """
118
111
  Remove validator.
@@ -123,9 +116,8 @@ class IValidationManager(ABC):
123
116
  Returns:
124
117
  True if removed
125
118
  """
126
- pass
119
+ ...
127
120
 
128
- @abstractmethod
129
121
  def validate_object(self, obj: Any, validators: list[str]) -> tuple[bool, list[str]]:
130
122
  """
131
123
  Validate object with specified validators.
@@ -137,9 +129,8 @@ class IValidationManager(ABC):
137
129
  Returns:
138
130
  Tuple of (is_valid, error_messages)
139
131
  """
140
- pass
132
+ ...
141
133
 
142
- @abstractmethod
143
134
  def get_validators(self) -> list[str]:
144
135
  """
145
136
  Get list of available validators.
@@ -147,21 +138,22 @@ class IValidationManager(ABC):
147
138
  Returns:
148
139
  List of validator names
149
140
  """
150
- pass
141
+ ...
151
142
 
152
143
 
153
144
  # ============================================================================
154
- # SCHEMA VALIDATION INTERFACES
145
+ # SCHEMA VALIDATION INTERFACES (Schema Provider)
155
146
  # ============================================================================
156
147
 
157
- class ISchemaValidator(ABC):
148
+ @runtime_checkable
149
+ class ISchemaProvider(Protocol):
158
150
  """
159
- Interface for schema validation.
151
+ Interface for schema validation (schema provider).
160
152
 
161
153
  Enforces consistent schema validation across XWSystem.
154
+ Implementations are discovered via entry point xwsystem.schema_validators.
162
155
  """
163
156
 
164
- @abstractmethod
165
157
  def validate_schema(self, data: Any, schema: dict[str, Any]) -> tuple[bool, list[str]]:
166
158
  """
167
159
  Validate data against schema.
@@ -173,9 +165,8 @@ class ISchemaValidator(ABC):
173
165
  Returns:
174
166
  Tuple of (is_valid, error_messages)
175
167
  """
176
- pass
168
+ ...
177
169
 
178
- @abstractmethod
179
170
  def create_schema(self, data: Any) -> dict[str, Any]:
180
171
  """
181
172
  Create schema from data.
@@ -186,9 +177,8 @@ class ISchemaValidator(ABC):
186
177
  Returns:
187
178
  Schema definition
188
179
  """
189
- pass
180
+ ...
190
181
 
191
- @abstractmethod
192
182
  def validate_type(self, data: Any, expected_type: str) -> bool:
193
183
  """
194
184
  Validate data type.
@@ -200,9 +190,8 @@ class ISchemaValidator(ABC):
200
190
  Returns:
201
191
  True if type matches
202
192
  """
203
- pass
193
+ ...
204
194
 
205
- @abstractmethod
206
195
  def validate_range(self, data: Any, min_value: Any, max_value: Any) -> bool:
207
196
  """
208
197
  Validate data range.
@@ -215,9 +204,8 @@ class ISchemaValidator(ABC):
215
204
  Returns:
216
205
  True if in range
217
206
  """
218
- pass
207
+ ...
219
208
 
220
- @abstractmethod
221
209
  def validate_pattern(self, data: str, pattern: str) -> bool:
222
210
  """
223
211
  Validate string pattern.
@@ -229,7 +217,7 @@ class ISchemaValidator(ABC):
229
217
  Returns:
230
218
  True if pattern matches
231
219
  """
232
- pass
220
+ ...
233
221
 
234
222
 
235
223
  # ============================================================================
@@ -237,8 +225,8 @@ class ISchemaValidator(ABC):
237
225
  # ============================================================================
238
226
 
239
227
  @runtime_checkable
240
- class Validatable(Protocol):
241
- """Protocol for objects that support data validation."""
228
+ class IValidatableSimple(Protocol):
229
+ """Protocol for objects that support data validation (simpler interface than IValidatable)."""
242
230
 
243
231
  def validate(self, data: Any, **kwargs: Any) -> bool:
244
232
  """Validate data against rules."""
@@ -1,3 +1,4 @@
1
+ #exonware/xwsystem/src/exonware/xwsystem/validation/data_validator.py
1
2
  """
2
3
  Data Validation Utilities for XSystem
3
4
 
@@ -1,13 +1,16 @@
1
+ #exonware/xwsystem/src/exonware/xwsystem/validation/declarative.py
1
2
  """
2
3
  Company: eXonware.com
3
4
  Author: Eng. Muhammad AlShehri
4
5
  Email: connect@exonware.com
5
- Version: 0.1.0.1
6
+ Version: 0.1.0.4
6
7
  Generation Date: September 04, 2025
7
8
 
8
9
  Pydantic-style declarative validation with type hints and automatic coercion.
9
10
  """
10
11
 
12
+ from __future__ import annotations
13
+
11
14
  import inspect
12
15
  import json
13
16
  from dataclasses import dataclass, field
@@ -58,10 +61,10 @@ class Field:
58
61
  description: Optional[str] = None
59
62
 
60
63
  # Validation constraints
61
- gt: Optional[Union[int, float]] = None # Greater than
62
- ge: Optional[Union[int, float]] = None # Greater than or equal
63
- lt: Optional[Union[int, float]] = None # Less than
64
- le: Optional[Union[int, float]] = None # Less than or equal
64
+ gt: Optional[int | float] = None # Greater than
65
+ ge: Optional[int | float] = None # Greater than or equal
66
+ lt: Optional[int | float] = None # Less than
67
+ le: Optional[int | float] = None # Less than or equal
65
68
  min_length: Optional[int] = None
66
69
  max_length: Optional[int] = None
67
70
  pattern: Optional[str] = None
@@ -73,7 +76,7 @@ class Field:
73
76
  to_upper: bool = False
74
77
 
75
78
  # Advanced constraints
76
- multiple_of: Optional[Union[int, float]] = None
79
+ multiple_of: Optional[int | float] = None
77
80
  allow_inf_nan: bool = True
78
81
 
79
82
  # Metadata
@@ -442,12 +445,12 @@ class XModel(metaclass=ModelMeta):
442
445
  raise ValidationError(f"Value must be one of: {field_config.enum}")
443
446
 
444
447
  @classmethod
445
- def model_validate(cls, data: dict[str, Any]) -> 'XModel':
448
+ def model_validate(cls, data: dict[str, Any]) -> XModel:
446
449
  """Create and validate model from dictionary data."""
447
450
  return cls(**data)
448
451
 
449
452
  @classmethod
450
- def model_validate_json(cls, json_data: str) -> 'XModel':
453
+ def model_validate_json(cls, json_data: str) -> XModel:
451
454
  """Create and validate model from JSON string."""
452
455
  data = json.loads(json_data)
453
456
  return cls.model_validate(data)