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
@@ -0,0 +1,701 @@
1
+ #exonware/xwsystem/src/exonware/xwsystem/caching/external_caching_python.py
2
+ """
3
+ External Python caching library implementations.
4
+
5
+ Company: eXonware.com
6
+ Author: Eng. Muhammad AlShehri
7
+ Email: connect@exonware.com
8
+ Version: 0.1.0.3
9
+ Generation Date: 01-Nov-2025
10
+
11
+ Wrappers for external caching libraries:
12
+ - cachebox: Rust-based Python cache (fastest)
13
+ - functools.lru_cache: Standard library LRU (C implementation)
14
+ - cachetools: Flexible caching with TTL, LFU, RR policies
15
+ """
16
+
17
+ import time
18
+ from typing import Any, Optional, Hashable
19
+ from functools import lru_cache as std_lru_cache
20
+ from collections import OrderedDict
21
+
22
+ from .base import ACache
23
+ from .contracts import ICache
24
+
25
+ # Optional dependencies: cachebox and cachetools
26
+ import importlib.util
27
+
28
+ # Check for cachebox
29
+ _cachebox_spec = importlib.util.find_spec('cachebox')
30
+ if _cachebox_spec is not None:
31
+ import cachebox
32
+ HAS_CACHEBOX = True
33
+ else:
34
+ HAS_CACHEBOX = False
35
+ cachebox = None
36
+
37
+ # Check for cachetools
38
+ _cachetools_spec = importlib.util.find_spec('cachetools')
39
+ if _cachetools_spec is not None:
40
+ import cachetools
41
+ from cachetools import (
42
+ LRUCache as CachetoolsLRU,
43
+ LFUCache as CachetoolsLFU,
44
+ TTLCache as CachetoolsTTL,
45
+ RRCache as CachetoolsRR,
46
+ )
47
+ HAS_CACHETOOLS = True
48
+ else:
49
+ HAS_CACHETOOLS = False
50
+ cachetools = None
51
+ CachetoolsLRU = None
52
+ CachetoolsLFU = None
53
+ CachetoolsTTL = None
54
+ CachetoolsRR = None
55
+
56
+
57
+ # ============================================================================
58
+ # CACHEBOX IMPLEMENTATION
59
+ # ============================================================================
60
+
61
+ class CacheboxCache(ACache):
62
+ """
63
+ Cachebox wrapper - Rust-based high-performance cache.
64
+
65
+ This is a Python wrapper around Rust's caching primitives,
66
+ providing excellent performance for large datasets.
67
+ """
68
+
69
+ def __init__(self, capacity: int = 128, ttl: Optional[float] = None, **kwargs):
70
+ """
71
+ Initialize Cachebox cache.
72
+
73
+ Args:
74
+ capacity: Maximum cache size
75
+ ttl: Time to live in seconds (not directly supported by cachebox)
76
+ """
77
+ if not HAS_CACHEBOX:
78
+ raise ImportError(
79
+ "cachebox not available. Install with: pip install cachebox"
80
+ )
81
+
82
+ super().__init__(capacity=capacity, ttl=int(ttl) if ttl else None)
83
+
84
+ # cachebox uses maxsize parameter
85
+ self._cache = cachebox.Cache(maxsize=capacity)
86
+ self._hits = 0
87
+ self._misses = 0
88
+ self._evictions = 0
89
+
90
+ def get(self, key: Hashable, default: Any = None) -> Any:
91
+ """Get value from cache."""
92
+ try:
93
+ value = self._cache.get(key, default)
94
+ if value is not default:
95
+ self._hits += 1
96
+ else:
97
+ self._misses += 1
98
+ return value
99
+ except Exception:
100
+ self._misses += 1
101
+ return default
102
+
103
+ def put(self, key: Hashable, value: Any) -> None:
104
+ """Put value in cache."""
105
+ # Check if we need to evict (cachebox handles this automatically)
106
+ if len(self._cache) >= self.capacity and key not in self._cache:
107
+ self._evictions += 1
108
+
109
+ self._cache[key] = value
110
+
111
+ def delete(self, key: Hashable) -> bool:
112
+ """Delete key from cache."""
113
+ try:
114
+ del self._cache[key]
115
+ return True
116
+ except KeyError:
117
+ return False
118
+
119
+ def clear(self) -> None:
120
+ """Clear cache."""
121
+ self._cache.clear()
122
+ self._hits = 0
123
+ self._misses = 0
124
+ self._evictions = 0
125
+
126
+ def size(self) -> int:
127
+ """Get cache size."""
128
+ return len(self._cache)
129
+
130
+ def is_full(self) -> bool:
131
+ """Check if cache is full."""
132
+ return len(self._cache) >= self.capacity
133
+
134
+ def evict(self) -> None:
135
+ """Evict entries (handled automatically by cachebox)."""
136
+ # cachebox handles eviction automatically
137
+ pass
138
+
139
+ def keys(self) -> list[Hashable]:
140
+ """Get list of all cache keys."""
141
+ return list(self._cache.keys())
142
+
143
+ def values(self) -> list[Any]:
144
+ """Get list of all cache values."""
145
+ return list(self._cache.values())
146
+
147
+ def items(self) -> list[tuple[Hashable, Any]]:
148
+ """Get list of all key-value pairs."""
149
+ return list(self._cache.items())
150
+
151
+ def get_stats(self) -> dict[str, Any]:
152
+ """Get cache statistics."""
153
+ total = self._hits + self._misses
154
+ hit_rate = (self._hits / total) if total > 0 else 0.0
155
+
156
+ return {
157
+ "hits": self._hits,
158
+ "misses": self._misses,
159
+ "evictions": self._evictions,
160
+ "hit_rate": hit_rate,
161
+ "size": self.size(),
162
+ "capacity": self.capacity,
163
+ }
164
+
165
+ # ICache interface compatibility
166
+ def set(self, key: str, value: Any, ttl: Optional[int] = None) -> bool:
167
+ """Set value in cache (ICache interface)."""
168
+ self.put(key, value)
169
+ return True
170
+
171
+ def exists(self, key: str) -> bool:
172
+ """Check if key exists (ICache interface)."""
173
+ return key in self._cache
174
+
175
+
176
+ # ============================================================================
177
+ # FUNCTOOLS LRU_CACHE IMPLEMENTATION
178
+ # ============================================================================
179
+
180
+ class FunctoolsLRUCache(ACache):
181
+ """
182
+ functools.lru_cache wrapper - Standard library LRU cache.
183
+
184
+ This is implemented in C (CPython core), making it extremely fast
185
+ for simple function memoization. However, it's a decorator, so we
186
+ implement a manual LRU cache that mimics its behavior.
187
+ """
188
+
189
+ def __init__(self, capacity: int = 128, ttl: Optional[float] = None, **kwargs):
190
+ """
191
+ Initialize functools-style LRU cache.
192
+
193
+ Args:
194
+ capacity: Maximum cache size
195
+ ttl: Time to live in seconds (not supported by functools)
196
+ """
197
+ super().__init__(capacity=capacity, ttl=int(ttl) if ttl else None)
198
+
199
+ # Use OrderedDict for LRU behavior
200
+ self._cache: OrderedDict[Hashable, Any] = OrderedDict()
201
+ self._hits = 0
202
+ self._misses = 0
203
+ self._evictions = 0
204
+
205
+ def get(self, key: Hashable, default: Any = None) -> Any:
206
+ """Get value from cache."""
207
+ if key in self._cache:
208
+ # Move to end (most recently used)
209
+ value = self._cache.pop(key)
210
+ self._cache[key] = value
211
+ self._hits += 1
212
+ return value
213
+
214
+ self._misses += 1
215
+ return default
216
+
217
+ def put(self, key: Hashable, value: Any) -> None:
218
+ """Put value in cache."""
219
+ if key in self._cache:
220
+ # Update existing - move to end
221
+ self._cache.pop(key)
222
+ else:
223
+ # Ensure capacity is int (handle case where it might be string from config)
224
+ capacity = int(self.capacity) if isinstance(self.capacity, str) else self.capacity
225
+ if len(self._cache) >= capacity:
226
+ # Evict least recently used (first item)
227
+ if self._cache:
228
+ self._cache.popitem(last=False) # Remove first (oldest)
229
+ self._evictions += 1
230
+
231
+ self._cache[key] = value
232
+
233
+ def delete(self, key: Hashable) -> bool:
234
+ """Delete key from cache."""
235
+ if key in self._cache:
236
+ del self._cache[key]
237
+ return True
238
+ return False
239
+
240
+ def clear(self) -> None:
241
+ """Clear cache."""
242
+ self._cache.clear()
243
+ self._hits = 0
244
+ self._misses = 0
245
+ self._evictions = 0
246
+
247
+ def size(self) -> int:
248
+ """Get cache size."""
249
+ return len(self._cache)
250
+
251
+ def is_full(self) -> bool:
252
+ """Check if cache is full."""
253
+ return len(self._cache) >= self.capacity
254
+
255
+ def evict(self) -> None:
256
+ """Evict least recently used entry."""
257
+ if self._cache:
258
+ self._cache.popitem(last=False)
259
+ self._evictions += 1
260
+
261
+ def keys(self) -> list[Hashable]:
262
+ """Get list of all cache keys."""
263
+ return list(self._cache.keys())
264
+
265
+ def values(self) -> list[Any]:
266
+ """Get list of all cache values."""
267
+ return list(self._cache.values())
268
+
269
+ def items(self) -> list[tuple[Hashable, Any]]:
270
+ """Get list of all key-value pairs."""
271
+ return list(self._cache.items())
272
+
273
+ def get_stats(self) -> dict[str, Any]:
274
+ """Get cache statistics."""
275
+ total = self._hits + self._misses
276
+ hit_rate = (self._hits / total) if total > 0 else 0.0
277
+
278
+ return {
279
+ "hits": self._hits,
280
+ "misses": self._misses,
281
+ "evictions": self._evictions,
282
+ "hit_rate": hit_rate,
283
+ "size": self.size(),
284
+ "capacity": self.capacity,
285
+ }
286
+
287
+ # ICache interface compatibility
288
+ def set(self, key: str, value: Any, ttl: Optional[int] = None) -> bool:
289
+ """Set value in cache (ICache interface)."""
290
+ self.put(key, value)
291
+ return True
292
+
293
+ def exists(self, key: str) -> bool:
294
+ """Check if key exists (ICache interface)."""
295
+ return key in self._cache
296
+
297
+
298
+ # ============================================================================
299
+ # CACHETOOLS IMPLEMENTATIONS
300
+ # ============================================================================
301
+
302
+ class CachetoolsLRUCache(ACache):
303
+ """Cachetools LRUCache wrapper."""
304
+
305
+ def __init__(self, capacity: int = 128, ttl: Optional[float] = None, **kwargs):
306
+ """Initialize Cachetools LRU cache."""
307
+ if not HAS_CACHETOOLS:
308
+ raise ImportError(
309
+ "cachetools not available. Install with: pip install cachetools"
310
+ )
311
+
312
+ super().__init__(capacity=capacity, ttl=int(ttl) if ttl else None)
313
+ self._cache = CachetoolsLRU(maxsize=capacity)
314
+ self._hits = 0
315
+ self._misses = 0
316
+ self._evictions = 0
317
+
318
+ def get(self, key: Hashable, default: Any = None) -> Any:
319
+ """Get value from cache."""
320
+ value = self._cache.get(key, default)
321
+ if value is not default:
322
+ self._hits += 1
323
+ else:
324
+ self._misses += 1
325
+ return value
326
+
327
+ def put(self, key: Hashable, value: Any) -> None:
328
+ """Put value in cache."""
329
+ if len(self._cache) >= self.capacity and key not in self._cache:
330
+ self._evictions += 1
331
+ self._cache[key] = value
332
+
333
+ def delete(self, key: Hashable) -> bool:
334
+ """Delete key from cache."""
335
+ try:
336
+ del self._cache[key]
337
+ return True
338
+ except KeyError:
339
+ return False
340
+
341
+ def clear(self) -> None:
342
+ """Clear cache."""
343
+ self._cache.clear()
344
+ self._hits = 0
345
+ self._misses = 0
346
+ self._evictions = 0
347
+
348
+ def size(self) -> int:
349
+ """Get cache size."""
350
+ return len(self._cache)
351
+
352
+ def is_full(self) -> bool:
353
+ """Check if cache is full."""
354
+ return len(self._cache) >= self.capacity
355
+
356
+ def evict(self) -> None:
357
+ """Evict entries (handled automatically)."""
358
+ pass
359
+
360
+ def keys(self) -> list[Hashable]:
361
+ """Get list of all cache keys."""
362
+ return list(self._cache.keys())
363
+
364
+ def values(self) -> list[Any]:
365
+ """Get list of all cache values."""
366
+ return list(self._cache.values())
367
+
368
+ def items(self) -> list[tuple[Hashable, Any]]:
369
+ """Get list of all key-value pairs."""
370
+ return list(self._cache.items())
371
+
372
+ def get_stats(self) -> dict[str, Any]:
373
+ """Get cache statistics."""
374
+ total = self._hits + self._misses
375
+ hit_rate = (self._hits / total) if total > 0 else 0.0
376
+
377
+ return {
378
+ "hits": self._hits,
379
+ "misses": self._misses,
380
+ "evictions": self._evictions,
381
+ "hit_rate": hit_rate,
382
+ "size": self.size(),
383
+ "capacity": self.capacity,
384
+ }
385
+
386
+ # ICache interface compatibility
387
+ def set(self, key: str, value: Any, ttl: Optional[int] = None) -> bool:
388
+ """Set value in cache (ICache interface)."""
389
+ self.put(key, value)
390
+ return True
391
+
392
+ def exists(self, key: str) -> bool:
393
+ """Check if key exists (ICache interface)."""
394
+ return key in self._cache
395
+
396
+
397
+ class CachetoolsLFUCache(ACache):
398
+ """Cachetools LFUCache wrapper."""
399
+
400
+ def __init__(self, capacity: int = 128, ttl: Optional[float] = None, **kwargs):
401
+ """Initialize Cachetools LFU cache."""
402
+ if not HAS_CACHETOOLS:
403
+ raise ImportError(
404
+ "cachetools not available. Install with: pip install cachetools"
405
+ )
406
+
407
+ super().__init__(capacity=capacity, ttl=int(ttl) if ttl else None)
408
+ self._cache = CachetoolsLFU(maxsize=capacity)
409
+ self._hits = 0
410
+ self._misses = 0
411
+ self._evictions = 0
412
+
413
+ def get(self, key: Hashable, default: Any = None) -> Any:
414
+ """Get value from cache."""
415
+ value = self._cache.get(key, default)
416
+ if value is not default:
417
+ self._hits += 1
418
+ else:
419
+ self._misses += 1
420
+ return value
421
+
422
+ def put(self, key: Hashable, value: Any) -> None:
423
+ """Put value in cache."""
424
+ if len(self._cache) >= self.capacity and key not in self._cache:
425
+ self._evictions += 1
426
+ self._cache[key] = value
427
+
428
+ def delete(self, key: Hashable) -> bool:
429
+ """Delete key from cache."""
430
+ try:
431
+ del self._cache[key]
432
+ return True
433
+ except KeyError:
434
+ return False
435
+
436
+ def clear(self) -> None:
437
+ """Clear cache."""
438
+ self._cache.clear()
439
+ self._hits = 0
440
+ self._misses = 0
441
+ self._evictions = 0
442
+
443
+ def size(self) -> int:
444
+ """Get cache size."""
445
+ return len(self._cache)
446
+
447
+ def is_full(self) -> bool:
448
+ """Check if cache is full."""
449
+ return len(self._cache) >= self.capacity
450
+
451
+ def evict(self) -> None:
452
+ """Evict entries (handled automatically)."""
453
+ pass
454
+
455
+ def keys(self) -> list[Hashable]:
456
+ """Get list of all cache keys."""
457
+ return list(self._cache.keys())
458
+
459
+ def values(self) -> list[Any]:
460
+ """Get list of all cache values."""
461
+ return list(self._cache.values())
462
+
463
+ def items(self) -> list[tuple[Hashable, Any]]:
464
+ """Get list of all key-value pairs."""
465
+ return list(self._cache.items())
466
+
467
+ def get_stats(self) -> dict[str, Any]:
468
+ """Get cache statistics."""
469
+ total = self._hits + self._misses
470
+ hit_rate = (self._hits / total) if total > 0 else 0.0
471
+
472
+ return {
473
+ "hits": self._hits,
474
+ "misses": self._misses,
475
+ "evictions": self._evictions,
476
+ "hit_rate": hit_rate,
477
+ "size": self.size(),
478
+ "capacity": self.capacity,
479
+ }
480
+
481
+ # ICache interface compatibility
482
+ def set(self, key: str, value: Any, ttl: Optional[int] = None) -> bool:
483
+ """Set value in cache (ICache interface)."""
484
+ self.put(key, value)
485
+ return True
486
+
487
+ def exists(self, key: str) -> bool:
488
+ """Check if key exists (ICache interface)."""
489
+ return key in self._cache
490
+
491
+
492
+ class CachetoolsTTLCache(ACache):
493
+ """Cachetools TTLCache wrapper."""
494
+
495
+ def __init__(self, capacity: int = 128, ttl: Optional[float] = None, **kwargs):
496
+ """
497
+ Initialize Cachetools TTL cache.
498
+
499
+ Args:
500
+ capacity: Maximum cache size
501
+ ttl: Time to live in seconds (default: 3600)
502
+ """
503
+ if not HAS_CACHETOOLS:
504
+ raise ImportError(
505
+ "cachetools not available. Install with: pip install cachetools"
506
+ )
507
+
508
+ # Use provided ttl or default to 3600 seconds
509
+ ttl_value = float(ttl) if ttl else 3600.0
510
+
511
+ super().__init__(capacity=capacity, ttl=int(ttl_value))
512
+ self._cache = CachetoolsTTL(maxsize=capacity, ttl=ttl_value)
513
+ self._hits = 0
514
+ self._misses = 0
515
+ self._evictions = 0
516
+
517
+ def get(self, key: Hashable, default: Any = None) -> Any:
518
+ """Get value from cache."""
519
+ value = self._cache.get(key, default)
520
+ if value is not default:
521
+ self._hits += 1
522
+ else:
523
+ self._misses += 1
524
+ return value
525
+
526
+ def put(self, key: Hashable, value: Any) -> None:
527
+ """Put value in cache."""
528
+ if len(self._cache) >= self.capacity and key not in self._cache:
529
+ self._evictions += 1
530
+ self._cache[key] = value
531
+
532
+ def delete(self, key: Hashable) -> bool:
533
+ """Delete key from cache."""
534
+ try:
535
+ del self._cache[key]
536
+ return True
537
+ except KeyError:
538
+ return False
539
+
540
+ def clear(self) -> None:
541
+ """Clear cache."""
542
+ self._cache.clear()
543
+ self._hits = 0
544
+ self._misses = 0
545
+ self._evictions = 0
546
+
547
+ def size(self) -> int:
548
+ """Get cache size."""
549
+ return len(self._cache)
550
+
551
+ def is_full(self) -> bool:
552
+ """Check if cache is full."""
553
+ return len(self._cache) >= self.capacity
554
+
555
+ def evict(self) -> None:
556
+ """Evict entries (handled automatically by TTL)."""
557
+ pass
558
+
559
+ def keys(self) -> list[Hashable]:
560
+ """Get list of all cache keys."""
561
+ return list(self._cache.keys())
562
+
563
+ def values(self) -> list[Any]:
564
+ """Get list of all cache values."""
565
+ return list(self._cache.values())
566
+
567
+ def items(self) -> list[tuple[Hashable, Any]]:
568
+ """Get list of all key-value pairs."""
569
+ return list(self._cache.items())
570
+
571
+ def get_stats(self) -> dict[str, Any]:
572
+ """Get cache statistics."""
573
+ total = self._hits + self._misses
574
+ hit_rate = (self._hits / total) if total > 0 else 0.0
575
+
576
+ return {
577
+ "hits": self._hits,
578
+ "misses": self._misses,
579
+ "evictions": self._evictions,
580
+ "hit_rate": hit_rate,
581
+ "size": self.size(),
582
+ "capacity": self.capacity,
583
+ "ttl": self.ttl,
584
+ }
585
+
586
+ # ICache interface compatibility
587
+ def set(self, key: str, value: Any, ttl: Optional[int] = None) -> bool:
588
+ """Set value in cache (ICache interface)."""
589
+ self.put(key, value)
590
+ return True
591
+
592
+ def exists(self, key: str) -> bool:
593
+ """Check if key exists (ICache interface)."""
594
+ return key in self._cache
595
+
596
+
597
+ class CachetoolsRRCache(ACache):
598
+ """Cachetools RRCache (Random Replacement) wrapper."""
599
+
600
+ def __init__(self, capacity: int = 128, ttl: Optional[float] = None, **kwargs):
601
+ """Initialize Cachetools RR cache."""
602
+ if not HAS_CACHETOOLS:
603
+ raise ImportError(
604
+ "cachetools not available. Install with: pip install cachetools"
605
+ )
606
+
607
+ super().__init__(capacity=capacity, ttl=int(ttl) if ttl else None)
608
+ self._cache = CachetoolsRR(maxsize=capacity)
609
+ self._hits = 0
610
+ self._misses = 0
611
+ self._evictions = 0
612
+
613
+ def get(self, key: Hashable, default: Any = None) -> Any:
614
+ """Get value from cache."""
615
+ value = self._cache.get(key, default)
616
+ if value is not default:
617
+ self._hits += 1
618
+ else:
619
+ self._misses += 1
620
+ return value
621
+
622
+ def put(self, key: Hashable, value: Any) -> None:
623
+ """Put value in cache."""
624
+ if len(self._cache) >= self.capacity and key not in self._cache:
625
+ self._evictions += 1
626
+ self._cache[key] = value
627
+
628
+ def delete(self, key: Hashable) -> bool:
629
+ """Delete key from cache."""
630
+ try:
631
+ del self._cache[key]
632
+ return True
633
+ except KeyError:
634
+ return False
635
+
636
+ def clear(self) -> None:
637
+ """Clear cache."""
638
+ self._cache.clear()
639
+ self._hits = 0
640
+ self._misses = 0
641
+ self._evictions = 0
642
+
643
+ def size(self) -> int:
644
+ """Get cache size."""
645
+ return len(self._cache)
646
+
647
+ def is_full(self) -> bool:
648
+ """Check if cache is full."""
649
+ return len(self._cache) >= self.capacity
650
+
651
+ def evict(self) -> None:
652
+ """Evict entries (handled automatically)."""
653
+ pass
654
+
655
+ def keys(self) -> list[Hashable]:
656
+ """Get list of all cache keys."""
657
+ return list(self._cache.keys())
658
+
659
+ def values(self) -> list[Any]:
660
+ """Get list of all cache values."""
661
+ return list(self._cache.values())
662
+
663
+ def items(self) -> list[tuple[Hashable, Any]]:
664
+ """Get list of all key-value pairs."""
665
+ return list(self._cache.items())
666
+
667
+ def get_stats(self) -> dict[str, Any]:
668
+ """Get cache statistics."""
669
+ total = self._hits + self._misses
670
+ hit_rate = (self._hits / total) if total > 0 else 0.0
671
+
672
+ return {
673
+ "hits": self._hits,
674
+ "misses": self._misses,
675
+ "evictions": self._evictions,
676
+ "hit_rate": hit_rate,
677
+ "size": self.size(),
678
+ "capacity": self.capacity,
679
+ }
680
+
681
+ # ICache interface compatibility
682
+ def set(self, key: str, value: Any, ttl: Optional[int] = None) -> bool:
683
+ """Set value in cache (ICache interface)."""
684
+ self.put(key, value)
685
+ return True
686
+
687
+ def exists(self, key: str) -> bool:
688
+ """Check if key exists (ICache interface)."""
689
+ return key in self._cache
690
+
691
+
692
+ __all__ = [
693
+ 'CacheboxCache',
694
+ 'FunctoolsLRUCache',
695
+ 'CachetoolsLRUCache',
696
+ 'CachetoolsLFUCache',
697
+ 'CachetoolsTTLCache',
698
+ 'CachetoolsRRCache',
699
+ 'HAS_CACHEBOX',
700
+ 'HAS_CACHETOOLS',
701
+ ]