exonware-xwsystem 0.1.0.1__py3-none-any.whl → 0.1.0.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- exonware/__init__.py +2 -1
- exonware/conf.py +2 -2
- exonware/xwsystem/__init__.py +115 -43
- exonware/xwsystem/base.py +30 -0
- exonware/xwsystem/caching/__init__.py +39 -13
- exonware/xwsystem/caching/base.py +24 -6
- exonware/xwsystem/caching/bloom_cache.py +2 -2
- exonware/xwsystem/caching/cache_manager.py +2 -1
- exonware/xwsystem/caching/conditional.py +2 -2
- exonware/xwsystem/caching/contracts.py +85 -139
- exonware/xwsystem/caching/decorators.py +6 -19
- exonware/xwsystem/caching/defs.py +2 -1
- exonware/xwsystem/caching/disk_cache.py +2 -1
- exonware/xwsystem/caching/distributed.py +2 -1
- exonware/xwsystem/caching/errors.py +2 -1
- exonware/xwsystem/caching/events.py +110 -27
- exonware/xwsystem/caching/eviction_strategies.py +2 -2
- exonware/xwsystem/caching/external_caching_python.py +701 -0
- exonware/xwsystem/caching/facade.py +253 -0
- exonware/xwsystem/caching/factory.py +300 -0
- exonware/xwsystem/caching/fluent.py +14 -12
- exonware/xwsystem/caching/integrity.py +21 -6
- exonware/xwsystem/caching/lfu_cache.py +2 -1
- exonware/xwsystem/caching/lfu_optimized.py +18 -6
- exonware/xwsystem/caching/lru_cache.py +7 -4
- exonware/xwsystem/caching/memory_bounded.py +2 -2
- exonware/xwsystem/caching/metrics_exporter.py +2 -2
- exonware/xwsystem/caching/observable_cache.py +2 -2
- exonware/xwsystem/caching/pluggable_cache.py +2 -2
- exonware/xwsystem/caching/rate_limiter.py +2 -2
- exonware/xwsystem/caching/read_through.py +2 -2
- exonware/xwsystem/caching/secure_cache.py +81 -28
- exonware/xwsystem/caching/serializable.py +9 -7
- exonware/xwsystem/caching/stats.py +2 -2
- exonware/xwsystem/caching/tagging.py +2 -2
- exonware/xwsystem/caching/ttl_cache.py +4 -3
- exonware/xwsystem/caching/two_tier_cache.py +6 -3
- exonware/xwsystem/caching/utils.py +30 -12
- exonware/xwsystem/caching/validation.py +2 -2
- exonware/xwsystem/caching/warming.py +6 -3
- exonware/xwsystem/caching/write_behind.py +15 -6
- exonware/xwsystem/config/__init__.py +11 -17
- exonware/xwsystem/config/base.py +5 -5
- exonware/xwsystem/config/contracts.py +93 -153
- exonware/xwsystem/config/defaults.py +3 -2
- exonware/xwsystem/config/defs.py +3 -2
- exonware/xwsystem/config/errors.py +2 -5
- exonware/xwsystem/config/logging.py +12 -8
- exonware/xwsystem/config/logging_setup.py +3 -2
- exonware/xwsystem/config/performance.py +1 -46
- exonware/xwsystem/config/performance_modes.py +9 -8
- exonware/xwsystem/config/version_manager.py +1 -0
- exonware/xwsystem/config.py +27 -0
- exonware/xwsystem/console/__init__.py +53 -0
- exonware/xwsystem/console/base.py +133 -0
- exonware/xwsystem/console/cli/__init__.py +61 -0
- exonware/xwsystem/{cli → console/cli}/args.py +27 -24
- exonware/xwsystem/{cli → console/cli}/base.py +18 -87
- exonware/xwsystem/{cli → console/cli}/colors.py +15 -13
- exonware/xwsystem/console/cli/console.py +98 -0
- exonware/xwsystem/{cli → console/cli}/contracts.py +51 -69
- exonware/xwsystem/console/cli/defs.py +87 -0
- exonware/xwsystem/console/cli/encoding.py +69 -0
- exonware/xwsystem/{cli → console/cli}/errors.py +8 -3
- exonware/xwsystem/console/cli/event_logger.py +166 -0
- exonware/xwsystem/{cli → console/cli}/progress.py +25 -21
- exonware/xwsystem/{cli → console/cli}/prompts.py +3 -2
- exonware/xwsystem/{cli → console/cli}/tables.py +27 -24
- exonware/xwsystem/console/contracts.py +113 -0
- exonware/xwsystem/console/defs.py +154 -0
- exonware/xwsystem/console/errors.py +34 -0
- exonware/xwsystem/console/event_logger.py +385 -0
- exonware/xwsystem/console/writer.py +132 -0
- exonware/xwsystem/contracts.py +28 -0
- exonware/xwsystem/data_structures/__init__.py +23 -0
- exonware/xwsystem/data_structures/trie.py +34 -0
- exonware/xwsystem/data_structures/union_find.py +144 -0
- exonware/xwsystem/defs.py +17 -0
- exonware/xwsystem/errors.py +23 -0
- exonware/xwsystem/facade.py +62 -0
- exonware/xwsystem/http_client/__init__.py +22 -1
- exonware/xwsystem/http_client/advanced_client.py +8 -5
- exonware/xwsystem/http_client/base.py +3 -2
- exonware/xwsystem/http_client/client.py +7 -4
- exonware/xwsystem/http_client/contracts.py +42 -56
- exonware/xwsystem/http_client/defs.py +2 -1
- exonware/xwsystem/http_client/errors.py +2 -1
- exonware/xwsystem/http_client/facade.py +156 -0
- exonware/xwsystem/io/__init__.py +22 -3
- exonware/xwsystem/io/archive/__init__.py +8 -2
- exonware/xwsystem/io/archive/archive.py +1 -1
- exonware/xwsystem/io/archive/archive_files.py +4 -7
- exonware/xwsystem/io/archive/archivers.py +120 -10
- exonware/xwsystem/io/archive/base.py +4 -5
- exonware/xwsystem/io/archive/codec_integration.py +1 -2
- exonware/xwsystem/io/archive/compression.py +1 -2
- exonware/xwsystem/io/archive/facade.py +263 -0
- exonware/xwsystem/io/archive/formats/__init__.py +2 -3
- exonware/xwsystem/io/archive/formats/brotli_format.py +20 -7
- exonware/xwsystem/io/archive/formats/lz4_format.py +20 -7
- exonware/xwsystem/io/archive/formats/rar.py +11 -5
- exonware/xwsystem/io/archive/formats/sevenzip.py +12 -6
- exonware/xwsystem/io/archive/formats/squashfs_format.py +1 -2
- exonware/xwsystem/io/archive/formats/tar.py +52 -7
- exonware/xwsystem/io/archive/formats/wim_format.py +11 -5
- exonware/xwsystem/io/archive/formats/zip.py +1 -2
- exonware/xwsystem/io/archive/formats/zpaq_format.py +1 -2
- exonware/xwsystem/io/archive/formats/zstandard.py +20 -7
- exonware/xwsystem/io/base.py +119 -115
- exonware/xwsystem/io/codec/__init__.py +4 -2
- exonware/xwsystem/io/codec/base.py +19 -13
- exonware/xwsystem/io/codec/contracts.py +59 -2
- exonware/xwsystem/io/codec/registry.py +67 -21
- exonware/xwsystem/io/common/__init__.py +1 -1
- exonware/xwsystem/io/common/atomic.py +29 -16
- exonware/xwsystem/io/common/base.py +11 -10
- exonware/xwsystem/io/common/lock.py +6 -5
- exonware/xwsystem/io/common/path_manager.py +2 -1
- exonware/xwsystem/io/common/watcher.py +1 -2
- exonware/xwsystem/io/contracts.py +301 -433
- exonware/xwsystem/io/contracts_1.py +1180 -0
- exonware/xwsystem/io/data_operations.py +19 -20
- exonware/xwsystem/io/defs.py +4 -3
- exonware/xwsystem/io/errors.py +3 -2
- exonware/xwsystem/io/facade.py +87 -61
- exonware/xwsystem/io/file/__init__.py +1 -1
- exonware/xwsystem/io/file/base.py +8 -9
- exonware/xwsystem/io/file/conversion.py +2 -3
- exonware/xwsystem/io/file/file.py +61 -18
- exonware/xwsystem/io/file/paged_source.py +8 -8
- exonware/xwsystem/io/file/paging/__init__.py +1 -2
- exonware/xwsystem/io/file/paging/byte_paging.py +4 -5
- exonware/xwsystem/io/file/paging/line_paging.py +2 -3
- exonware/xwsystem/io/file/paging/record_paging.py +2 -3
- exonware/xwsystem/io/file/paging/registry.py +1 -2
- exonware/xwsystem/io/file/source.py +13 -17
- exonware/xwsystem/io/filesystem/__init__.py +1 -1
- exonware/xwsystem/io/filesystem/base.py +1 -2
- exonware/xwsystem/io/filesystem/local.py +3 -4
- exonware/xwsystem/io/folder/__init__.py +1 -1
- exonware/xwsystem/io/folder/base.py +1 -2
- exonware/xwsystem/io/folder/folder.py +16 -7
- exonware/xwsystem/io/indexing/__init__.py +14 -0
- exonware/xwsystem/io/indexing/facade.py +443 -0
- exonware/xwsystem/io/path_parser.py +98 -0
- exonware/xwsystem/io/serialization/__init__.py +21 -3
- exonware/xwsystem/io/serialization/auto_serializer.py +146 -20
- exonware/xwsystem/io/serialization/base.py +84 -34
- exonware/xwsystem/io/serialization/contracts.py +50 -73
- exonware/xwsystem/io/serialization/defs.py +2 -1
- exonware/xwsystem/io/serialization/errors.py +2 -1
- exonware/xwsystem/io/serialization/flyweight.py +154 -7
- exonware/xwsystem/io/serialization/format_detector.py +15 -14
- exonware/xwsystem/io/serialization/formats/__init__.py +8 -5
- exonware/xwsystem/io/serialization/formats/binary/bson.py +15 -6
- exonware/xwsystem/io/serialization/formats/binary/cbor.py +5 -5
- exonware/xwsystem/io/serialization/formats/binary/marshal.py +5 -5
- exonware/xwsystem/io/serialization/formats/binary/msgpack.py +5 -5
- exonware/xwsystem/io/serialization/formats/binary/pickle.py +5 -5
- exonware/xwsystem/io/serialization/formats/binary/plistlib.py +5 -5
- exonware/xwsystem/io/serialization/formats/database/dbm.py +7 -7
- exonware/xwsystem/io/serialization/formats/database/shelve.py +7 -7
- exonware/xwsystem/io/serialization/formats/database/sqlite3.py +7 -7
- exonware/xwsystem/io/serialization/formats/tabular/__init__.py +27 -0
- exonware/xwsystem/io/serialization/formats/tabular/base.py +89 -0
- exonware/xwsystem/io/serialization/formats/tabular/csv.py +319 -0
- exonware/xwsystem/io/serialization/formats/tabular/df.py +249 -0
- exonware/xwsystem/io/serialization/formats/tabular/excel.py +291 -0
- exonware/xwsystem/io/serialization/formats/tabular/googlesheets.py +374 -0
- exonware/xwsystem/io/serialization/formats/text/__init__.py +1 -1
- exonware/xwsystem/io/serialization/formats/text/append_only_log.py +5 -7
- exonware/xwsystem/io/serialization/formats/text/configparser.py +5 -5
- exonware/xwsystem/io/serialization/formats/text/csv.py +7 -5
- exonware/xwsystem/io/serialization/formats/text/formdata.py +5 -5
- exonware/xwsystem/io/serialization/formats/text/json.py +27 -18
- exonware/xwsystem/io/serialization/formats/text/json5.py +8 -4
- exonware/xwsystem/io/serialization/formats/text/jsonlines.py +18 -14
- exonware/xwsystem/io/serialization/formats/text/multipart.py +5 -5
- exonware/xwsystem/io/serialization/formats/text/toml.py +8 -6
- exonware/xwsystem/io/serialization/formats/text/xml.py +25 -20
- exonware/xwsystem/io/serialization/formats/text/yaml.py +8 -6
- exonware/xwsystem/io/serialization/parsers/__init__.py +3 -2
- exonware/xwsystem/io/serialization/parsers/base.py +6 -5
- exonware/xwsystem/io/serialization/parsers/hybrid_parser.py +7 -6
- exonware/xwsystem/io/serialization/parsers/msgspec_parser.py +10 -7
- exonware/xwsystem/io/serialization/parsers/orjson_direct_parser.py +7 -6
- exonware/xwsystem/io/serialization/parsers/orjson_parser.py +11 -8
- exonware/xwsystem/io/serialization/parsers/pysimdjson_parser.py +13 -9
- exonware/xwsystem/io/serialization/parsers/rapidjson_parser.py +10 -7
- exonware/xwsystem/io/serialization/parsers/registry.py +11 -10
- exonware/xwsystem/io/serialization/parsers/standard.py +7 -6
- exonware/xwsystem/io/serialization/parsers/ujson_parser.py +10 -7
- exonware/xwsystem/io/serialization/registry.py +4 -4
- exonware/xwsystem/io/serialization/serializer.py +168 -79
- exonware/xwsystem/io/serialization/universal_options.py +367 -0
- exonware/xwsystem/io/serialization/utils/__init__.py +1 -2
- exonware/xwsystem/io/serialization/utils/path_ops.py +5 -6
- exonware/xwsystem/io/source_reader.py +223 -0
- exonware/xwsystem/io/stream/__init__.py +1 -1
- exonware/xwsystem/io/stream/async_operations.py +61 -14
- exonware/xwsystem/io/stream/base.py +1 -2
- exonware/xwsystem/io/stream/codec_io.py +6 -7
- exonware/xwsystem/ipc/__init__.py +1 -0
- exonware/xwsystem/ipc/async_fabric.py +4 -4
- exonware/xwsystem/ipc/base.py +6 -5
- exonware/xwsystem/ipc/contracts.py +41 -66
- exonware/xwsystem/ipc/defs.py +2 -1
- exonware/xwsystem/ipc/errors.py +2 -1
- exonware/xwsystem/ipc/message_queue.py +5 -2
- exonware/xwsystem/ipc/pipes.py +70 -34
- exonware/xwsystem/ipc/process_manager.py +7 -5
- exonware/xwsystem/ipc/process_pool.py +6 -5
- exonware/xwsystem/ipc/shared_memory.py +64 -11
- exonware/xwsystem/monitoring/__init__.py +7 -0
- exonware/xwsystem/monitoring/base.py +11 -8
- exonware/xwsystem/monitoring/contracts.py +86 -144
- exonware/xwsystem/monitoring/defs.py +2 -1
- exonware/xwsystem/monitoring/error_recovery.py +16 -3
- exonware/xwsystem/monitoring/errors.py +2 -1
- exonware/xwsystem/monitoring/facade.py +183 -0
- exonware/xwsystem/monitoring/memory_monitor.py +1 -0
- exonware/xwsystem/monitoring/metrics.py +1 -0
- exonware/xwsystem/monitoring/performance_manager_generic.py +7 -7
- exonware/xwsystem/monitoring/performance_monitor.py +1 -0
- exonware/xwsystem/monitoring/performance_validator.py +1 -0
- exonware/xwsystem/monitoring/system_monitor.py +6 -5
- exonware/xwsystem/monitoring/tracing.py +18 -16
- exonware/xwsystem/monitoring/tracker.py +2 -1
- exonware/xwsystem/operations/__init__.py +5 -50
- exonware/xwsystem/operations/base.py +3 -44
- exonware/xwsystem/operations/contracts.py +25 -15
- exonware/xwsystem/operations/defs.py +1 -1
- exonware/xwsystem/operations/diff.py +5 -4
- exonware/xwsystem/operations/errors.py +1 -1
- exonware/xwsystem/operations/merge.py +6 -4
- exonware/xwsystem/operations/patch.py +5 -4
- exonware/xwsystem/patterns/__init__.py +1 -0
- exonware/xwsystem/patterns/base.py +2 -1
- exonware/xwsystem/patterns/context_manager.py +2 -1
- exonware/xwsystem/patterns/contracts.py +215 -256
- exonware/xwsystem/patterns/defs.py +2 -1
- exonware/xwsystem/patterns/dynamic_facade.py +1 -0
- exonware/xwsystem/patterns/errors.py +2 -4
- exonware/xwsystem/patterns/handler_factory.py +2 -3
- exonware/xwsystem/patterns/import_registry.py +1 -0
- exonware/xwsystem/patterns/object_pool.py +1 -0
- exonware/xwsystem/patterns/registry.py +4 -43
- exonware/xwsystem/plugins/__init__.py +2 -1
- exonware/xwsystem/plugins/base.py +6 -5
- exonware/xwsystem/plugins/contracts.py +94 -158
- exonware/xwsystem/plugins/defs.py +2 -1
- exonware/xwsystem/plugins/errors.py +2 -1
- exonware/xwsystem/py.typed +3 -0
- exonware/xwsystem/query/__init__.py +36 -0
- exonware/xwsystem/query/contracts.py +56 -0
- exonware/xwsystem/query/errors.py +22 -0
- exonware/xwsystem/query/registry.py +128 -0
- exonware/xwsystem/runtime/__init__.py +2 -1
- exonware/xwsystem/runtime/base.py +4 -3
- exonware/xwsystem/runtime/contracts.py +39 -60
- exonware/xwsystem/runtime/defs.py +2 -1
- exonware/xwsystem/runtime/env.py +11 -9
- exonware/xwsystem/runtime/errors.py +2 -1
- exonware/xwsystem/runtime/reflection.py +3 -2
- exonware/xwsystem/security/__init__.py +68 -11
- exonware/xwsystem/security/audit.py +167 -0
- exonware/xwsystem/security/base.py +121 -24
- exonware/xwsystem/security/contracts.py +91 -146
- exonware/xwsystem/security/crypto.py +17 -16
- exonware/xwsystem/security/defs.py +2 -1
- exonware/xwsystem/security/errors.py +2 -1
- exonware/xwsystem/security/facade.py +321 -0
- exonware/xwsystem/security/file_security.py +330 -0
- exonware/xwsystem/security/hazmat.py +11 -8
- exonware/xwsystem/security/monitor.py +372 -0
- exonware/xwsystem/security/path_validator.py +140 -18
- exonware/xwsystem/security/policy.py +357 -0
- exonware/xwsystem/security/resource_limits.py +1 -0
- exonware/xwsystem/security/validator.py +455 -0
- exonware/xwsystem/shared/__init__.py +14 -1
- exonware/xwsystem/shared/base.py +285 -2
- exonware/xwsystem/shared/contracts.py +415 -126
- exonware/xwsystem/shared/defs.py +2 -1
- exonware/xwsystem/shared/errors.py +2 -2
- exonware/xwsystem/shared/xwobject.py +316 -0
- exonware/xwsystem/structures/__init__.py +1 -0
- exonware/xwsystem/structures/base.py +3 -2
- exonware/xwsystem/structures/circular_detector.py +15 -14
- exonware/xwsystem/structures/contracts.py +53 -76
- exonware/xwsystem/structures/defs.py +2 -1
- exonware/xwsystem/structures/errors.py +2 -1
- exonware/xwsystem/structures/tree_walker.py +2 -1
- exonware/xwsystem/threading/__init__.py +21 -4
- exonware/xwsystem/threading/async_primitives.py +6 -5
- exonware/xwsystem/threading/base.py +3 -2
- exonware/xwsystem/threading/contracts.py +87 -143
- exonware/xwsystem/threading/defs.py +2 -1
- exonware/xwsystem/threading/errors.py +2 -1
- exonware/xwsystem/threading/facade.py +175 -0
- exonware/xwsystem/threading/locks.py +1 -0
- exonware/xwsystem/threading/safe_factory.py +1 -0
- exonware/xwsystem/utils/__init__.py +40 -0
- exonware/xwsystem/utils/base.py +22 -21
- exonware/xwsystem/utils/contracts.py +50 -73
- exonware/xwsystem/utils/dt/__init__.py +19 -3
- exonware/xwsystem/utils/dt/base.py +5 -4
- exonware/xwsystem/utils/dt/contracts.py +22 -29
- exonware/xwsystem/utils/dt/defs.py +2 -1
- exonware/xwsystem/utils/dt/errors.py +2 -5
- exonware/xwsystem/utils/dt/formatting.py +88 -2
- exonware/xwsystem/utils/dt/humanize.py +10 -9
- exonware/xwsystem/utils/dt/parsing.py +56 -5
- exonware/xwsystem/utils/dt/timezone_utils.py +2 -24
- exonware/xwsystem/utils/errors.py +2 -4
- exonware/xwsystem/utils/paths.py +1 -0
- exonware/xwsystem/utils/string.py +49 -0
- exonware/xwsystem/utils/test_runner.py +185 -0
- exonware/xwsystem/utils/utils_contracts.py +2 -1
- exonware/xwsystem/utils/web.py +110 -0
- exonware/xwsystem/validation/__init__.py +25 -1
- exonware/xwsystem/validation/base.py +6 -5
- exonware/xwsystem/validation/contracts.py +29 -41
- exonware/xwsystem/validation/data_validator.py +1 -0
- exonware/xwsystem/validation/declarative.py +11 -8
- exonware/xwsystem/validation/defs.py +2 -1
- exonware/xwsystem/validation/errors.py +2 -1
- exonware/xwsystem/validation/facade.py +198 -0
- exonware/xwsystem/validation/fluent_validator.py +22 -19
- exonware/xwsystem/validation/schema_discovery.py +210 -0
- exonware/xwsystem/validation/type_safety.py +2 -1
- exonware/xwsystem/version.py +2 -2
- {exonware_xwsystem-0.1.0.1.dist-info → exonware_xwsystem-0.1.0.3.dist-info}/METADATA +71 -4
- exonware_xwsystem-0.1.0.3.dist-info/RECORD +337 -0
- exonware/xwsystem/cli/__init__.py +0 -43
- exonware/xwsystem/cli/console.py +0 -113
- exonware/xwsystem/cli/defs.py +0 -134
- exonware/xwsystem/conf.py +0 -44
- exonware/xwsystem/security/auth.py +0 -484
- exonware_xwsystem-0.1.0.1.dist-info/RECORD +0 -284
- {exonware_xwsystem-0.1.0.1.dist-info → exonware_xwsystem-0.1.0.3.dist-info}/WHEEL +0 -0
- {exonware_xwsystem-0.1.0.1.dist-info → exonware_xwsystem-0.1.0.3.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
#exonware/xwsystem/src/exonware/xwsystem/caching/facade.py
|
|
2
|
+
"""
|
|
3
|
+
Company: eXonware.com
|
|
4
|
+
Author: Eng. Muhammad AlShehri
|
|
5
|
+
Email: connect@exonware.com
|
|
6
|
+
Version: 0.1.0.3
|
|
7
|
+
Generation Date: January 2026
|
|
8
|
+
|
|
9
|
+
XWCache - Unified Caching Facade
|
|
10
|
+
|
|
11
|
+
Simplified API for all caching strategies:
|
|
12
|
+
- LRU, LFU, TTL
|
|
13
|
+
- Memory-bounded, Two-tier, Secure
|
|
14
|
+
- Async support
|
|
15
|
+
- Decorator support
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
from typing import Any, Optional, Callable
|
|
19
|
+
from functools import wraps
|
|
20
|
+
|
|
21
|
+
from . import (
|
|
22
|
+
LRUCache, AsyncLRUCache,
|
|
23
|
+
LFUCache, AsyncLFUCache,
|
|
24
|
+
TTLCache, AsyncTTLCache,
|
|
25
|
+
OptimizedLFUCache, AsyncOptimizedLFUCache,
|
|
26
|
+
MemoryBoundedLRUCache, MemoryBoundedLFUCache,
|
|
27
|
+
TwoTierCache,
|
|
28
|
+
SecureLRUCache, SecureLFUCache, SecureTTLCache,
|
|
29
|
+
xwcached, xw_async_cached,
|
|
30
|
+
)
|
|
31
|
+
from .factory import CacheFactory, CacheType
|
|
32
|
+
from ..config.logging_setup import get_logger
|
|
33
|
+
|
|
34
|
+
logger = get_logger(__name__)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class XWCache:
|
|
38
|
+
"""
|
|
39
|
+
Unified caching facade - simple API for all cache strategies.
|
|
40
|
+
|
|
41
|
+
Examples:
|
|
42
|
+
>>> # Simple LRU cache
|
|
43
|
+
>>> cache = XWCache(strategy="LRU", capacity=1000)
|
|
44
|
+
>>> cache.put("key", "value")
|
|
45
|
+
>>> value = cache.get("key")
|
|
46
|
+
|
|
47
|
+
>>> # Named cache instance
|
|
48
|
+
>>> user_cache = XWCache(strategy="LRU", name="users", capacity=500)
|
|
49
|
+
|
|
50
|
+
>>> # TTL cache
|
|
51
|
+
>>> session_cache = XWCache(strategy="TTL", ttl=3600)
|
|
52
|
+
|
|
53
|
+
>>> # Async cache
|
|
54
|
+
>>> async_cache = XWCache(strategy="LRU", async=True, capacity=1000)
|
|
55
|
+
|
|
56
|
+
>>> # Advanced features
|
|
57
|
+
>>> cache = XWCache(
|
|
58
|
+
... strategy="LRU",
|
|
59
|
+
... capacity=1000,
|
|
60
|
+
... memory_bounded=True,
|
|
61
|
+
... two_tier=True,
|
|
62
|
+
... )
|
|
63
|
+
|
|
64
|
+
>>> # Decorator
|
|
65
|
+
>>> @XWCache.cached(strategy="LRU", ttl=3600)
|
|
66
|
+
>>> def expensive_function(x):
|
|
67
|
+
... return x * 2
|
|
68
|
+
"""
|
|
69
|
+
|
|
70
|
+
# Registry for named caches
|
|
71
|
+
_cache_registry: dict[str, Any] = {}
|
|
72
|
+
|
|
73
|
+
def __init__(
|
|
74
|
+
self,
|
|
75
|
+
strategy: str = "LRU",
|
|
76
|
+
*,
|
|
77
|
+
name: Optional[str] = None,
|
|
78
|
+
capacity: int = 1000,
|
|
79
|
+
ttl: Optional[int] = None,
|
|
80
|
+
async_mode: bool = False,
|
|
81
|
+
memory_bounded: bool = False,
|
|
82
|
+
two_tier: bool = False,
|
|
83
|
+
secure: bool = False,
|
|
84
|
+
**kwargs
|
|
85
|
+
):
|
|
86
|
+
"""
|
|
87
|
+
Initialize unified cache.
|
|
88
|
+
|
|
89
|
+
Args:
|
|
90
|
+
strategy: Cache strategy ("LRU", "LFU", "TTL", "OPTIMIZED_LFU")
|
|
91
|
+
name: Optional name for cache instance (for multiple caches)
|
|
92
|
+
capacity: Maximum cache size
|
|
93
|
+
ttl: Time to live in seconds (for TTL strategy)
|
|
94
|
+
async_mode: Use async cache implementation
|
|
95
|
+
memory_bounded: Use memory-bounded cache
|
|
96
|
+
two_tier: Use two-tier cache (memory + disk)
|
|
97
|
+
secure: Use secure cache (with rate limiting)
|
|
98
|
+
**kwargs: Additional cache-specific options
|
|
99
|
+
"""
|
|
100
|
+
self.strategy = strategy.upper()
|
|
101
|
+
self.name = name
|
|
102
|
+
self.capacity = capacity
|
|
103
|
+
self.ttl = ttl
|
|
104
|
+
self.async_mode = async_mode
|
|
105
|
+
self.memory_bounded = memory_bounded
|
|
106
|
+
self.two_tier = two_tier
|
|
107
|
+
self.secure = secure
|
|
108
|
+
self.kwargs = kwargs
|
|
109
|
+
|
|
110
|
+
# Create cache instance
|
|
111
|
+
self._cache = self._create_cache()
|
|
112
|
+
|
|
113
|
+
# Register named cache
|
|
114
|
+
if name:
|
|
115
|
+
XWCache._cache_registry[name] = self._cache
|
|
116
|
+
|
|
117
|
+
def _create_cache(self):
|
|
118
|
+
"""Create cache instance based on strategy and options."""
|
|
119
|
+
strategy_map = {
|
|
120
|
+
"LRU": (LRUCache, AsyncLRUCache),
|
|
121
|
+
"LFU": (LFUCache, AsyncLFUCache),
|
|
122
|
+
"TTL": (TTLCache, AsyncTTLCache),
|
|
123
|
+
"OPTIMIZED_LFU": (OptimizedLFUCache, AsyncOptimizedLFUCache),
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
# Secure variants
|
|
127
|
+
if self.secure:
|
|
128
|
+
secure_map = {
|
|
129
|
+
"LRU": SecureLRUCache,
|
|
130
|
+
"LFU": SecureLFUCache,
|
|
131
|
+
"TTL": SecureTTLCache,
|
|
132
|
+
}
|
|
133
|
+
if self.strategy in secure_map:
|
|
134
|
+
cache_class = secure_map[self.strategy]
|
|
135
|
+
return cache_class(capacity=self.capacity, ttl=self.ttl, **self.kwargs)
|
|
136
|
+
|
|
137
|
+
# Memory-bounded variants
|
|
138
|
+
if self.memory_bounded:
|
|
139
|
+
if self.strategy == "LRU":
|
|
140
|
+
return MemoryBoundedLRUCache(capacity=self.capacity, **self.kwargs)
|
|
141
|
+
elif self.strategy == "LFU":
|
|
142
|
+
return MemoryBoundedLFUCache(capacity=self.capacity, **self.kwargs)
|
|
143
|
+
|
|
144
|
+
# Two-tier cache
|
|
145
|
+
if self.two_tier:
|
|
146
|
+
return TwoTierCache(
|
|
147
|
+
namespace=self.name or "default",
|
|
148
|
+
memory_capacity=self.capacity,
|
|
149
|
+
**self.kwargs
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
# Standard cache
|
|
153
|
+
if self.strategy not in strategy_map:
|
|
154
|
+
raise ValueError(f"Unknown cache strategy: {self.strategy}")
|
|
155
|
+
|
|
156
|
+
cache_class = strategy_map[self.strategy][1 if self.async_mode else 0]
|
|
157
|
+
|
|
158
|
+
# TTL-specific handling
|
|
159
|
+
if self.strategy == "TTL" and self.ttl:
|
|
160
|
+
return cache_class(capacity=self.capacity, ttl=self.ttl, **self.kwargs)
|
|
161
|
+
|
|
162
|
+
return cache_class(capacity=self.capacity, **self.kwargs)
|
|
163
|
+
|
|
164
|
+
def get(self, key: Any, default: Any = None) -> Any:
|
|
165
|
+
"""Get value from cache."""
|
|
166
|
+
return self._cache.get(key, default)
|
|
167
|
+
|
|
168
|
+
def put(self, key: Any, value: Any) -> None:
|
|
169
|
+
"""Put value in cache."""
|
|
170
|
+
self._cache.put(key, value)
|
|
171
|
+
|
|
172
|
+
def delete(self, key: Any) -> bool:
|
|
173
|
+
"""Delete value from cache."""
|
|
174
|
+
return self._cache.delete(key)
|
|
175
|
+
|
|
176
|
+
def clear(self) -> None:
|
|
177
|
+
"""Clear all cache entries."""
|
|
178
|
+
self._cache.clear()
|
|
179
|
+
|
|
180
|
+
def size(self) -> int:
|
|
181
|
+
"""Get cache size."""
|
|
182
|
+
return self._cache.size()
|
|
183
|
+
|
|
184
|
+
def __getitem__(self, key: Any) -> Any:
|
|
185
|
+
"""Support dict-like access."""
|
|
186
|
+
return self.get(key)
|
|
187
|
+
|
|
188
|
+
def __setitem__(self, key: Any, value: Any) -> None:
|
|
189
|
+
"""Support dict-like access."""
|
|
190
|
+
self.put(key, value)
|
|
191
|
+
|
|
192
|
+
def __delitem__(self, key: Any) -> None:
|
|
193
|
+
"""Support dict-like access."""
|
|
194
|
+
self.delete(key)
|
|
195
|
+
|
|
196
|
+
@classmethod
|
|
197
|
+
def get_cache(cls, name: str) -> Any:
|
|
198
|
+
"""Get named cache instance."""
|
|
199
|
+
return cls._cache_registry.get(name)
|
|
200
|
+
|
|
201
|
+
@classmethod
|
|
202
|
+
def cached(
|
|
203
|
+
cls,
|
|
204
|
+
strategy: str = "LRU",
|
|
205
|
+
capacity: int = 1000,
|
|
206
|
+
ttl: Optional[int] = None,
|
|
207
|
+
async_mode: bool = False,
|
|
208
|
+
**kwargs
|
|
209
|
+
):
|
|
210
|
+
"""
|
|
211
|
+
Decorator for caching function results.
|
|
212
|
+
|
|
213
|
+
Examples:
|
|
214
|
+
>>> @XWCache.cached(strategy="LRU", ttl=3600)
|
|
215
|
+
>>> def expensive_function(x):
|
|
216
|
+
... return x * 2
|
|
217
|
+
"""
|
|
218
|
+
# Create cache instance based on strategy
|
|
219
|
+
strategy_map = {
|
|
220
|
+
"LRU": (LRUCache, AsyncLRUCache),
|
|
221
|
+
"LFU": (LFUCache, AsyncLFUCache),
|
|
222
|
+
"TTL": (TTLCache, AsyncTTLCache),
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
if strategy.upper() not in strategy_map:
|
|
226
|
+
raise ValueError(f"Unknown cache strategy: {strategy}")
|
|
227
|
+
|
|
228
|
+
cache_class = strategy_map[strategy.upper()][1 if async_mode else 0]
|
|
229
|
+
|
|
230
|
+
if strategy.upper() == "TTL" and ttl:
|
|
231
|
+
cache = cache_class(capacity=capacity, ttl=ttl, **kwargs)
|
|
232
|
+
else:
|
|
233
|
+
cache = cache_class(capacity=capacity, **kwargs)
|
|
234
|
+
|
|
235
|
+
if async_mode:
|
|
236
|
+
return xw_async_cached(cache=cache, ttl=ttl, **kwargs)
|
|
237
|
+
else:
|
|
238
|
+
return xwcached(cache=cache, ttl=ttl, **kwargs)
|
|
239
|
+
|
|
240
|
+
@classmethod
|
|
241
|
+
def create(
|
|
242
|
+
cls,
|
|
243
|
+
strategy: str = "LRU",
|
|
244
|
+
capacity: int = 1000,
|
|
245
|
+
**kwargs
|
|
246
|
+
) -> "XWCache":
|
|
247
|
+
"""
|
|
248
|
+
Factory method for creating cache instances.
|
|
249
|
+
|
|
250
|
+
Examples:
|
|
251
|
+
>>> cache = XWCache.create(strategy="LRU", capacity=1000)
|
|
252
|
+
"""
|
|
253
|
+
return cls(strategy=strategy, capacity=capacity, **kwargs)
|
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
#exonware/xwsystem/src/exonware/xwsystem/caching/factory.py
|
|
2
|
+
"""
|
|
3
|
+
Cache Factory - Configurable cache creation utility.
|
|
4
|
+
|
|
5
|
+
Company: eXonware.com
|
|
6
|
+
Author: Eng. Muhammad AlShehri
|
|
7
|
+
Email: connect@exonware.com
|
|
8
|
+
Version: 0.1.0.3
|
|
9
|
+
Generation Date: January 2025
|
|
10
|
+
|
|
11
|
+
Provides configurable cache factory that allows choosing different caching engines
|
|
12
|
+
via settings/environment variables. Defaults to FunctoolsLRUCache (fastest Python cache - 3,333 ops/sec MIXED, 33,335 ops/sec GET).
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
import os
|
|
16
|
+
from typing import Any, Optional, Type
|
|
17
|
+
from enum import Enum
|
|
18
|
+
|
|
19
|
+
from ..config.logging_setup import get_logger
|
|
20
|
+
from .base import ACache
|
|
21
|
+
from .lru_cache import LRUCache
|
|
22
|
+
from .lfu_cache import LFUCache
|
|
23
|
+
from .ttl_cache import TTLCache
|
|
24
|
+
from .lfu_optimized import OptimizedLFUCache
|
|
25
|
+
from .memory_bounded import MemoryBoundedLRUCache, MemoryBoundedLFUCache
|
|
26
|
+
from .secure_cache import SecureLRUCache, SecureLFUCache, SecureTTLCache
|
|
27
|
+
from .external_caching_python import FunctoolsLRUCache
|
|
28
|
+
|
|
29
|
+
logger = get_logger("xwsystem.caching.factory")
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class CacheType(str, Enum):
|
|
33
|
+
"""Supported cache types."""
|
|
34
|
+
FUNCTOOLS_LRU = "functools_lru" # Default - fastest Python cache (3,333 ops/sec MIXED, 33,335 ops/sec GET)
|
|
35
|
+
LRU = "lru"
|
|
36
|
+
LFU = "lfu"
|
|
37
|
+
TTL = "ttl"
|
|
38
|
+
OPTIMIZED_LFU = "optimized_lfu"
|
|
39
|
+
MEMORY_BOUNDED_LRU = "memory_bounded_lru"
|
|
40
|
+
MEMORY_BOUNDED_LFU = "memory_bounded_lfu"
|
|
41
|
+
SECURE_LRU = "secure_lru"
|
|
42
|
+
SECURE_LFU = "secure_lfu"
|
|
43
|
+
SECURE_TTL = "secure_ttl"
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class CacheFactory:
|
|
47
|
+
"""
|
|
48
|
+
Configurable cache factory.
|
|
49
|
+
|
|
50
|
+
Allows choosing different caching engines via:
|
|
51
|
+
- Environment variable: XWSYSTEM_CACHE_TYPE (default: 'functools_lru')
|
|
52
|
+
- Settings: 'xwsystem.cache.type' (default: 'functools_lru')
|
|
53
|
+
- Per-instance configuration
|
|
54
|
+
|
|
55
|
+
Supported cache types:
|
|
56
|
+
- 'functools_lru' (default) - FunctoolsLRUCache - Fastest Python cache (3,333 ops/sec MIXED, 33,335 ops/sec GET)
|
|
57
|
+
- 'lfu' - LFUCache - Least Frequently Used
|
|
58
|
+
- 'lru' - LRUCache - Least Recently Used
|
|
59
|
+
- 'ttl' - TTLCache - Time-To-Live expiration
|
|
60
|
+
- 'optimized_lfu' - OptimizedLFUCache - O(1) LFU eviction
|
|
61
|
+
- 'memory_bounded_lru' - MemoryBoundedLRUCache - Memory-bounded LRU
|
|
62
|
+
- 'memory_bounded_lfu' - MemoryBoundedLFUCache - Memory-bounded LFU
|
|
63
|
+
- 'secure_lru' - SecureLRUCache - Secure LRU with rate limiting
|
|
64
|
+
- 'secure_lfu' - SecureLFUCache - Secure LFU with rate limiting
|
|
65
|
+
- 'secure_ttl' - SecureTTLCache - Secure TTL with rate limiting
|
|
66
|
+
|
|
67
|
+
Example:
|
|
68
|
+
# Use default (FunctoolsLRUCache - fastest)
|
|
69
|
+
cache = CacheFactory.create(capacity=1000)
|
|
70
|
+
|
|
71
|
+
# Override via environment variable
|
|
72
|
+
# export XWSYSTEM_CACHE_TYPE=lru
|
|
73
|
+
cache = CacheFactory.create(capacity=1000)
|
|
74
|
+
|
|
75
|
+
# Override programmatically
|
|
76
|
+
cache = CacheFactory.create(capacity=1000, cache_type='ttl', ttl=3600)
|
|
77
|
+
|
|
78
|
+
# Package-specific override
|
|
79
|
+
cache = CacheFactory.create(capacity=1000, namespace='xwstorage')
|
|
80
|
+
"""
|
|
81
|
+
|
|
82
|
+
# Global settings registry (can be set by packages)
|
|
83
|
+
_settings: dict[str, Any] = {}
|
|
84
|
+
|
|
85
|
+
# Cache type registry
|
|
86
|
+
_cache_types: dict[str, Type[ACache]] = {
|
|
87
|
+
CacheType.FUNCTOOLS_LRU: FunctoolsLRUCache, # Default - fastest Python cache
|
|
88
|
+
CacheType.LRU: LRUCache,
|
|
89
|
+
CacheType.LFU: LFUCache,
|
|
90
|
+
CacheType.TTL: TTLCache,
|
|
91
|
+
CacheType.OPTIMIZED_LFU: OptimizedLFUCache,
|
|
92
|
+
CacheType.MEMORY_BOUNDED_LRU: MemoryBoundedLRUCache,
|
|
93
|
+
CacheType.MEMORY_BOUNDED_LFU: MemoryBoundedLFUCache,
|
|
94
|
+
CacheType.SECURE_LRU: SecureLRUCache,
|
|
95
|
+
CacheType.SECURE_LFU: SecureLFUCache,
|
|
96
|
+
CacheType.SECURE_TTL: SecureTTLCache,
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
@classmethod
|
|
100
|
+
def set_setting(cls, key: str, value: Any) -> None:
|
|
101
|
+
"""
|
|
102
|
+
Set factory setting.
|
|
103
|
+
|
|
104
|
+
Args:
|
|
105
|
+
key: Setting key (e.g., 'cache.type', 'cache.default_capacity')
|
|
106
|
+
value: Setting value
|
|
107
|
+
"""
|
|
108
|
+
cls._settings[key] = value
|
|
109
|
+
logger.debug(f"CacheFactory setting updated: {key}={value}")
|
|
110
|
+
|
|
111
|
+
@classmethod
|
|
112
|
+
def get_setting(cls, key: str, default: Any = None) -> Any:
|
|
113
|
+
"""
|
|
114
|
+
Get factory setting.
|
|
115
|
+
|
|
116
|
+
Args:
|
|
117
|
+
key: Setting key
|
|
118
|
+
default: Default value if not found
|
|
119
|
+
|
|
120
|
+
Returns:
|
|
121
|
+
Setting value or default
|
|
122
|
+
"""
|
|
123
|
+
return cls._settings.get(key, default)
|
|
124
|
+
|
|
125
|
+
@classmethod
|
|
126
|
+
def get_cache_type(cls, namespace: Optional[str] = None) -> str:
|
|
127
|
+
"""
|
|
128
|
+
Get cache type from configuration.
|
|
129
|
+
|
|
130
|
+
Priority:
|
|
131
|
+
1. Namespace-specific setting: 'cache.type.{namespace}'
|
|
132
|
+
2. Global setting: 'cache.type' or 'xwsystem.cache.type'
|
|
133
|
+
3. Environment variable: XWSYSTEM_CACHE_TYPE or XWSYSTEM_CACHE_TYPE_{NAMESPACE}
|
|
134
|
+
4. Default: 'functools_lru' (fastest Python cache - 3,333 ops/sec MIXED, 33,335 ops/sec GET)
|
|
135
|
+
|
|
136
|
+
Args:
|
|
137
|
+
namespace: Optional namespace for namespace-specific configuration
|
|
138
|
+
|
|
139
|
+
Returns:
|
|
140
|
+
Cache type string
|
|
141
|
+
"""
|
|
142
|
+
# Check namespace-specific setting first
|
|
143
|
+
if namespace:
|
|
144
|
+
# Namespace-specific setting
|
|
145
|
+
ns_key = f'cache.type.{namespace}'
|
|
146
|
+
cache_type = cls.get_setting(ns_key)
|
|
147
|
+
if cache_type:
|
|
148
|
+
return cache_type
|
|
149
|
+
|
|
150
|
+
# Namespace-specific environment variable
|
|
151
|
+
env_key = f'XWSYSTEM_CACHE_TYPE_{namespace.upper()}'
|
|
152
|
+
cache_type = os.getenv(env_key)
|
|
153
|
+
if cache_type:
|
|
154
|
+
return cache_type.lower()
|
|
155
|
+
|
|
156
|
+
# Check global setting
|
|
157
|
+
cache_type = cls.get_setting('cache.type') or cls.get_setting('xwsystem.cache.type')
|
|
158
|
+
if cache_type:
|
|
159
|
+
return cache_type
|
|
160
|
+
|
|
161
|
+
# Check environment variable
|
|
162
|
+
cache_type = os.getenv('XWSYSTEM_CACHE_TYPE', 'functools_lru')
|
|
163
|
+
return cache_type.lower()
|
|
164
|
+
|
|
165
|
+
@classmethod
|
|
166
|
+
def create(
|
|
167
|
+
cls,
|
|
168
|
+
capacity: int = 128,
|
|
169
|
+
cache_type: Optional[str] = None,
|
|
170
|
+
namespace: Optional[str] = None,
|
|
171
|
+
name: Optional[str] = None,
|
|
172
|
+
**kwargs
|
|
173
|
+
) -> ACache:
|
|
174
|
+
"""
|
|
175
|
+
Create cache instance based on configuration.
|
|
176
|
+
|
|
177
|
+
Args:
|
|
178
|
+
capacity: Cache capacity (default: 128)
|
|
179
|
+
cache_type: Override cache type (optional)
|
|
180
|
+
namespace: Namespace for namespace-specific configuration (optional)
|
|
181
|
+
name: Cache name for debugging (optional)
|
|
182
|
+
**kwargs: Additional cache-specific parameters (e.g., ttl, memory_budget_mb)
|
|
183
|
+
|
|
184
|
+
Returns:
|
|
185
|
+
Cache instance
|
|
186
|
+
|
|
187
|
+
Raises:
|
|
188
|
+
ValueError: If cache type is invalid
|
|
189
|
+
"""
|
|
190
|
+
# Determine cache type
|
|
191
|
+
if cache_type is None:
|
|
192
|
+
cache_type = cls.get_cache_type(namespace)
|
|
193
|
+
else:
|
|
194
|
+
cache_type = cache_type.lower()
|
|
195
|
+
|
|
196
|
+
# Get cache class
|
|
197
|
+
cache_class = cls._cache_types.get(cache_type)
|
|
198
|
+
if cache_class is None:
|
|
199
|
+
# Try to find by partial match
|
|
200
|
+
cache_class = next(
|
|
201
|
+
(cls._cache_types[ct] for ct in cls._cache_types.keys()
|
|
202
|
+
if cache_type in ct.lower() or ct.lower() in cache_type),
|
|
203
|
+
None
|
|
204
|
+
)
|
|
205
|
+
if cache_class is None:
|
|
206
|
+
logger.warning(
|
|
207
|
+
f"Unknown cache type '{cache_type}', using default FunctoolsLRU. "
|
|
208
|
+
f"Available types: {list(cls._cache_types.keys())}"
|
|
209
|
+
)
|
|
210
|
+
cache_class = FunctoolsLRUCache
|
|
211
|
+
cache_type = CacheType.FUNCTOOLS_LRU
|
|
212
|
+
|
|
213
|
+
# Prepare cache parameters
|
|
214
|
+
cache_params = {'capacity': capacity}
|
|
215
|
+
if name:
|
|
216
|
+
cache_params['name'] = name
|
|
217
|
+
|
|
218
|
+
# Add cache-specific parameters
|
|
219
|
+
if cache_type == CacheType.TTL or cache_type == CacheType.SECURE_TTL:
|
|
220
|
+
if 'ttl' not in kwargs:
|
|
221
|
+
# Get TTL from settings or use default
|
|
222
|
+
ttl = cls.get_setting('cache.ttl') or cls.get_setting('xwsystem.cache.ttl') or 3600
|
|
223
|
+
cache_params['ttl'] = float(ttl)
|
|
224
|
+
else:
|
|
225
|
+
cache_params['ttl'] = kwargs.pop('ttl')
|
|
226
|
+
|
|
227
|
+
if cache_type in (CacheType.MEMORY_BOUNDED_LRU, CacheType.MEMORY_BOUNDED_LFU):
|
|
228
|
+
if 'memory_budget_mb' not in kwargs:
|
|
229
|
+
memory_budget = cls.get_setting('cache.memory_budget_mb') or 100.0
|
|
230
|
+
cache_params['memory_budget_mb'] = float(memory_budget)
|
|
231
|
+
else:
|
|
232
|
+
cache_params['memory_budget_mb'] = kwargs.pop('memory_budget_mb')
|
|
233
|
+
|
|
234
|
+
# Add any remaining kwargs
|
|
235
|
+
cache_params.update(kwargs)
|
|
236
|
+
|
|
237
|
+
# Create cache instance
|
|
238
|
+
try:
|
|
239
|
+
cache = cache_class(**cache_params)
|
|
240
|
+
logger.debug(
|
|
241
|
+
f"Created {cache_type} cache: capacity={capacity}, "
|
|
242
|
+
f"namespace={namespace}, name={name}"
|
|
243
|
+
)
|
|
244
|
+
return cache
|
|
245
|
+
except Exception as e:
|
|
246
|
+
logger.error(f"Failed to create {cache_type} cache: {e}, falling back to FunctoolsLRU")
|
|
247
|
+
return FunctoolsLRUCache(capacity=capacity, name=name)
|
|
248
|
+
|
|
249
|
+
@classmethod
|
|
250
|
+
def register_cache_type(cls, cache_type: str, cache_class: Type[ACache]) -> None:
|
|
251
|
+
"""
|
|
252
|
+
Register custom cache type.
|
|
253
|
+
|
|
254
|
+
Args:
|
|
255
|
+
cache_type: Cache type identifier
|
|
256
|
+
cache_class: Cache class
|
|
257
|
+
"""
|
|
258
|
+
cls._cache_types[cache_type.lower()] = cache_class
|
|
259
|
+
logger.info(f"Registered custom cache type: {cache_type}")
|
|
260
|
+
|
|
261
|
+
@classmethod
|
|
262
|
+
def get_available_types(cls) -> list[str]:
|
|
263
|
+
"""Get list of available cache types."""
|
|
264
|
+
return list(cls._cache_types.keys())
|
|
265
|
+
|
|
266
|
+
|
|
267
|
+
# Convenience function for easy access
|
|
268
|
+
def create_cache(
|
|
269
|
+
capacity: int = 128,
|
|
270
|
+
cache_type: Optional[str] = None,
|
|
271
|
+
namespace: Optional[str] = None,
|
|
272
|
+
name: Optional[str] = None,
|
|
273
|
+
**kwargs
|
|
274
|
+
) -> ACache:
|
|
275
|
+
"""
|
|
276
|
+
Create cache instance (convenience function).
|
|
277
|
+
|
|
278
|
+
Example:
|
|
279
|
+
from exonware.xwsystem.caching import create_cache
|
|
280
|
+
|
|
281
|
+
# Use default (FunctoolsLRUCache - fastest Python cache)
|
|
282
|
+
cache = create_cache(capacity=1000)
|
|
283
|
+
|
|
284
|
+
# Override type
|
|
285
|
+
cache = create_cache(capacity=1000, cache_type='lru')
|
|
286
|
+
|
|
287
|
+
# Namespace-specific
|
|
288
|
+
cache = create_cache(capacity=1000, namespace='xwstorage')
|
|
289
|
+
|
|
290
|
+
# Override via environment variable
|
|
291
|
+
# export XWSYSTEM_CACHE_TYPE=lfu
|
|
292
|
+
cache = create_cache(capacity=1000)
|
|
293
|
+
"""
|
|
294
|
+
return CacheFactory.create(
|
|
295
|
+
capacity=capacity,
|
|
296
|
+
cache_type=cache_type,
|
|
297
|
+
namespace=namespace,
|
|
298
|
+
name=name,
|
|
299
|
+
**kwargs
|
|
300
|
+
)
|
|
@@ -1,16 +1,19 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
|
+
#exonware/xwsystem/src/exonware/xwsystem/caching/fluent.py
|
|
2
3
|
#exonware/xwsystem/caching/fluent.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.
|
|
8
|
+
Version: 0.1.0.3
|
|
8
9
|
Generation Date: 01-Nov-2025
|
|
9
10
|
|
|
10
11
|
Fluent API wrappers for caching module.
|
|
11
|
-
Usability Priority #2 - Method chaining for
|
|
12
|
+
Usability Priority #2 - Method chaining for developer experience.
|
|
12
13
|
"""
|
|
13
14
|
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
14
17
|
from typing import Any, Optional, Hashable
|
|
15
18
|
from .lru_cache import LRUCache
|
|
16
19
|
from .lfu_cache import LFUCache
|
|
@@ -30,7 +33,7 @@ class FluentLRUCache(LRUCache):
|
|
|
30
33
|
cache.delete("k1").delete("k2").clear() # Chain operations
|
|
31
34
|
"""
|
|
32
35
|
|
|
33
|
-
def put(self, key: Hashable, value: Any) ->
|
|
36
|
+
def put(self, key: Hashable, value: Any) -> FluentLRUCache:
|
|
34
37
|
"""
|
|
35
38
|
Put value and return self for chaining.
|
|
36
39
|
|
|
@@ -44,7 +47,7 @@ class FluentLRUCache(LRUCache):
|
|
|
44
47
|
super().put(key, value)
|
|
45
48
|
return self
|
|
46
49
|
|
|
47
|
-
def delete(self, key: Hashable) ->
|
|
50
|
+
def delete(self, key: Hashable) -> FluentLRUCache:
|
|
48
51
|
"""
|
|
49
52
|
Delete key and return self for chaining.
|
|
50
53
|
|
|
@@ -57,7 +60,7 @@ class FluentLRUCache(LRUCache):
|
|
|
57
60
|
super().delete(key)
|
|
58
61
|
return self
|
|
59
62
|
|
|
60
|
-
def clear(self) ->
|
|
63
|
+
def clear(self) -> FluentLRUCache:
|
|
61
64
|
"""
|
|
62
65
|
Clear cache and return self for chaining.
|
|
63
66
|
|
|
@@ -77,17 +80,17 @@ class FluentLFUCache(LFUCache):
|
|
|
77
80
|
cache.put("k1", "v1").put("k2", "v2").put("k3", "v3")
|
|
78
81
|
"""
|
|
79
82
|
|
|
80
|
-
def put(self, key: Hashable, value: Any) ->
|
|
83
|
+
def put(self, key: Hashable, value: Any) -> FluentLFUCache:
|
|
81
84
|
"""Put value and return self for chaining."""
|
|
82
85
|
super().put(key, value)
|
|
83
86
|
return self
|
|
84
87
|
|
|
85
|
-
def delete(self, key: Hashable) ->
|
|
88
|
+
def delete(self, key: Hashable) -> FluentLFUCache:
|
|
86
89
|
"""Delete key and return self for chaining."""
|
|
87
90
|
super().delete(key)
|
|
88
91
|
return self
|
|
89
92
|
|
|
90
|
-
def clear(self) ->
|
|
93
|
+
def clear(self) -> FluentLFUCache:
|
|
91
94
|
"""Clear cache and return self for chaining."""
|
|
92
95
|
super().clear()
|
|
93
96
|
return self
|
|
@@ -102,17 +105,17 @@ class FluentTTLCache(TTLCache):
|
|
|
102
105
|
cache.put("k1", "v1").put("k2", "v2", ttl=60.0).put("k3", "v3")
|
|
103
106
|
"""
|
|
104
107
|
|
|
105
|
-
def put(self, key: str, value: Any, ttl: Optional[float] = None) ->
|
|
108
|
+
def put(self, key: str, value: Any, ttl: Optional[float] = None) -> FluentTTLCache:
|
|
106
109
|
"""Put value and return self for chaining."""
|
|
107
110
|
super().put(key, value, ttl)
|
|
108
111
|
return self
|
|
109
112
|
|
|
110
|
-
def delete(self, key: str) ->
|
|
113
|
+
def delete(self, key: str) -> FluentTTLCache:
|
|
111
114
|
"""Delete key and return self for chaining."""
|
|
112
115
|
super().delete(key)
|
|
113
116
|
return self
|
|
114
117
|
|
|
115
|
-
def clear(self) ->
|
|
118
|
+
def clear(self) -> FluentTTLCache:
|
|
116
119
|
"""Clear cache and return self for chaining."""
|
|
117
120
|
super().clear()
|
|
118
121
|
return self
|
|
@@ -123,4 +126,3 @@ __all__ = [
|
|
|
123
126
|
'FluentLFUCache',
|
|
124
127
|
'FluentTTLCache',
|
|
125
128
|
]
|
|
126
|
-
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
|
+
#exonware/xwsystem/src/exonware/xwsystem/caching/integrity.py
|
|
2
3
|
#exonware/xwsystem/caching/integrity.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.
|
|
8
|
+
Version: 0.1.0.3
|
|
8
9
|
Generation Date: 01-Nov-2025
|
|
9
10
|
|
|
10
11
|
Cache integrity verification - Security Priority #1.
|
|
@@ -55,12 +56,27 @@ class CacheEntry:
|
|
|
55
56
|
f"Cache may have been tampered with."
|
|
56
57
|
)
|
|
57
58
|
return True
|
|
59
|
+
except CacheIntegrityError:
|
|
60
|
+
# Re-raise integrity errors as-is (already properly formatted)
|
|
61
|
+
raise
|
|
62
|
+
except (ValueError, TypeError, AttributeError) as e:
|
|
63
|
+
# Handle specific errors that can occur during checksum computation
|
|
64
|
+
# This follows GUIDE_TEST.md by handling specific exceptions
|
|
65
|
+
# rather than catching all exceptions
|
|
66
|
+
raise CacheIntegrityError(
|
|
67
|
+
f"Integrity verification failed for key {self.key}: "
|
|
68
|
+
f"Cannot compute checksum - {type(e).__name__}: {e}. "
|
|
69
|
+
f"This may indicate corrupted cache data."
|
|
70
|
+
) from e
|
|
58
71
|
except Exception as e:
|
|
59
|
-
|
|
60
|
-
|
|
72
|
+
# Catch-all for unexpected errors during integrity check
|
|
73
|
+
# This is acceptable per GUIDE_TEST.md as we're wrapping it
|
|
74
|
+
# in a proper CacheIntegrityError with context
|
|
61
75
|
raise CacheIntegrityError(
|
|
62
|
-
f"
|
|
63
|
-
|
|
76
|
+
f"Unexpected error during integrity verification for key {self.key}: "
|
|
77
|
+
f"{type(e).__name__}: {e}. "
|
|
78
|
+
f"Cache integrity cannot be verified."
|
|
79
|
+
) from e
|
|
64
80
|
|
|
65
81
|
|
|
66
82
|
def create_secure_entry(
|
|
@@ -126,4 +142,3 @@ __all__ = [
|
|
|
126
142
|
'verify_entry_integrity',
|
|
127
143
|
'update_entry_checksum',
|
|
128
144
|
]
|
|
129
|
-
|