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.
- 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 +73 -391
- 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 +279 -14
- 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 +199 -0
- 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 +65 -33
- exonware/xwsystem/io/serialization/formats/text/json5.py +8 -4
- exonware/xwsystem/io/serialization/formats/text/jsonlines.py +113 -25
- 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 +16 -0
- exonware/xwsystem/io/serialization/parsers/base.py +60 -0
- exonware/xwsystem/io/serialization/parsers/hybrid_parser.py +62 -0
- exonware/xwsystem/io/serialization/parsers/msgspec_parser.py +48 -0
- exonware/xwsystem/io/serialization/parsers/orjson_direct_parser.py +54 -0
- exonware/xwsystem/io/serialization/parsers/orjson_parser.py +62 -0
- exonware/xwsystem/io/serialization/parsers/pysimdjson_parser.py +55 -0
- exonware/xwsystem/io/serialization/parsers/rapidjson_parser.py +53 -0
- exonware/xwsystem/io/serialization/parsers/registry.py +91 -0
- exonware/xwsystem/io/serialization/parsers/standard.py +44 -0
- exonware/xwsystem/io/serialization/parsers/ujson_parser.py +53 -0
- 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 +139 -480
- 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 +4 -4
- {exonware_xwsystem-0.0.1.411.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/caching/USAGE_GUIDE.md +0 -779
- 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.0.1.411.dist-info/RECORD +0 -274
- {exonware_xwsystem-0.0.1.411.dist-info → exonware_xwsystem-0.1.0.3.dist-info}/WHEEL +0 -0
- {exonware_xwsystem-0.0.1.411.dist-info → exonware_xwsystem-0.1.0.3.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
#exonware/xwsystem/src/exonware/xwsystem/console/defs.py
|
|
3
|
+
#exonware/xwsystem/console/defs.py
|
|
4
|
+
"""
|
|
5
|
+
Company: eXonware.com
|
|
6
|
+
Author: Eng. Muhammad AlShehri
|
|
7
|
+
Email: connect@exonware.com
|
|
8
|
+
Version: 0.1.0.3
|
|
9
|
+
Generation Date: 2025-01-27
|
|
10
|
+
|
|
11
|
+
Type definitions and constants for console module.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from typing import Literal, Any, Optional
|
|
15
|
+
from dataclasses import dataclass
|
|
16
|
+
from enum import Enum
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
# ============================================================================
|
|
20
|
+
# TYPE DEFINITIONS FOR STRUCTURED LOGGING
|
|
21
|
+
# ============================================================================
|
|
22
|
+
|
|
23
|
+
LogLevel = Literal['log', 'error', 'warn', 'info', 'debug']
|
|
24
|
+
ConsoleEventType = Literal[
|
|
25
|
+
'log', 'info', 'warn', 'error', 'debug', 'trace',
|
|
26
|
+
'group', 'groupCollapsed', 'groupEnd', 'table', 'success', 'system'
|
|
27
|
+
]
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
@dataclass
|
|
31
|
+
class ConsoleEvent:
|
|
32
|
+
"""
|
|
33
|
+
Console event structure for structured logging.
|
|
34
|
+
|
|
35
|
+
Attributes:
|
|
36
|
+
id: Unique identifier for the event
|
|
37
|
+
type: Type of console event
|
|
38
|
+
timestamp: Unix timestamp (seconds or milliseconds) or ISO string
|
|
39
|
+
color: CSS color for the event display
|
|
40
|
+
label: Short label for the badge
|
|
41
|
+
msg: Human-readable message
|
|
42
|
+
source: Optional source/operation/module name
|
|
43
|
+
level: Optional explicit log level (overrides type mapping)
|
|
44
|
+
data: Optional additional structured data
|
|
45
|
+
"""
|
|
46
|
+
id: int
|
|
47
|
+
type: ConsoleEventType
|
|
48
|
+
timestamp: float | int | str # Unix timestamp or ISO string
|
|
49
|
+
color: str
|
|
50
|
+
label: str
|
|
51
|
+
msg: str
|
|
52
|
+
source: Optional[str] = None
|
|
53
|
+
level: Optional[LogLevel] = None
|
|
54
|
+
data: Optional[Any] = None
|
|
55
|
+
|
|
56
|
+
def to_dict(self) -> dict:
|
|
57
|
+
"""Convert to dictionary for JSON serialization."""
|
|
58
|
+
result = {
|
|
59
|
+
'id': self.id,
|
|
60
|
+
'type': self.type,
|
|
61
|
+
'timestamp': self.timestamp,
|
|
62
|
+
'color': self.color,
|
|
63
|
+
'label': self.label,
|
|
64
|
+
'msg': self.msg,
|
|
65
|
+
}
|
|
66
|
+
if self.source is not None:
|
|
67
|
+
result['source'] = self.source
|
|
68
|
+
if self.level is not None:
|
|
69
|
+
result['level'] = self.level
|
|
70
|
+
if self.data is not None:
|
|
71
|
+
result['data'] = self.data
|
|
72
|
+
return result
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
# ============================================================================
|
|
76
|
+
# GENERAL CONSOLE ENUMS (moved from CLI - general console concepts)
|
|
77
|
+
# ============================================================================
|
|
78
|
+
|
|
79
|
+
class Alignment(Enum):
|
|
80
|
+
"""Text alignment options."""
|
|
81
|
+
LEFT = "left"
|
|
82
|
+
CENTER = "center"
|
|
83
|
+
RIGHT = "right"
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
class BorderStyle(Enum):
|
|
87
|
+
"""Table border styles."""
|
|
88
|
+
NONE = "none"
|
|
89
|
+
ASCII = "ascii"
|
|
90
|
+
SIMPLE = "simple"
|
|
91
|
+
ROUNDED = "rounded"
|
|
92
|
+
DOUBLE = "double"
|
|
93
|
+
THICK = "thick"
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
class Colors(Enum):
|
|
97
|
+
"""ANSI color codes."""
|
|
98
|
+
# Standard colors
|
|
99
|
+
BLACK = "\033[30m"
|
|
100
|
+
RED = "\033[31m"
|
|
101
|
+
GREEN = "\033[32m"
|
|
102
|
+
YELLOW = "\033[33m"
|
|
103
|
+
BLUE = "\033[34m"
|
|
104
|
+
MAGENTA = "\033[35m"
|
|
105
|
+
CYAN = "\033[36m"
|
|
106
|
+
WHITE = "\033[37m"
|
|
107
|
+
|
|
108
|
+
# Bright colors
|
|
109
|
+
BRIGHT_BLACK = "\033[90m"
|
|
110
|
+
BRIGHT_RED = "\033[91m"
|
|
111
|
+
BRIGHT_GREEN = "\033[92m"
|
|
112
|
+
BRIGHT_YELLOW = "\033[93m"
|
|
113
|
+
BRIGHT_BLUE = "\033[94m"
|
|
114
|
+
BRIGHT_MAGENTA = "\033[95m"
|
|
115
|
+
BRIGHT_CYAN = "\033[96m"
|
|
116
|
+
BRIGHT_WHITE = "\033[97m"
|
|
117
|
+
|
|
118
|
+
# Background colors
|
|
119
|
+
BG_BLACK = "\033[40m"
|
|
120
|
+
BG_RED = "\033[41m"
|
|
121
|
+
BG_GREEN = "\033[42m"
|
|
122
|
+
BG_YELLOW = "\033[43m"
|
|
123
|
+
BG_BLUE = "\033[44m"
|
|
124
|
+
BG_MAGENTA = "\033[45m"
|
|
125
|
+
BG_CYAN = "\033[46m"
|
|
126
|
+
BG_WHITE = "\033[47m"
|
|
127
|
+
|
|
128
|
+
# Reset
|
|
129
|
+
RESET = "\033[0m"
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
class Style(Enum):
|
|
133
|
+
"""ANSI style codes."""
|
|
134
|
+
RESET = "\033[0m"
|
|
135
|
+
BOLD = "\033[1m"
|
|
136
|
+
DIM = "\033[2m"
|
|
137
|
+
ITALIC = "\033[3m"
|
|
138
|
+
UNDERLINE = "\033[4m"
|
|
139
|
+
BLINK = "\033[5m"
|
|
140
|
+
REVERSE = "\033[7m"
|
|
141
|
+
STRIKETHROUGH = "\033[9m"
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
__all__ = [
|
|
145
|
+
# Structured logging types
|
|
146
|
+
'LogLevel',
|
|
147
|
+
'ConsoleEventType',
|
|
148
|
+
'ConsoleEvent',
|
|
149
|
+
# General console enums
|
|
150
|
+
'Alignment',
|
|
151
|
+
'BorderStyle',
|
|
152
|
+
'Colors',
|
|
153
|
+
'Style',
|
|
154
|
+
]
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
#exonware/xwsystem/src/exonware/xwsystem/console/errors.py
|
|
3
|
+
#exonware/xwsystem/console/errors.py
|
|
4
|
+
"""
|
|
5
|
+
Company: eXonware.com
|
|
6
|
+
Author: Eng. Muhammad AlShehri
|
|
7
|
+
Email: connect@exonware.com
|
|
8
|
+
Version: 0.1.0.3
|
|
9
|
+
Generation Date: 2025-01-27
|
|
10
|
+
|
|
11
|
+
Console module errors - exception classes for console functionality.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class ConsoleError(Exception):
|
|
16
|
+
"""Base exception for console errors."""
|
|
17
|
+
pass
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class EventLoggerError(ConsoleError):
|
|
21
|
+
"""Raised when event logger operation fails."""
|
|
22
|
+
pass
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class ConsoleWriterError(ConsoleError):
|
|
26
|
+
"""Raised when console writer operation fails."""
|
|
27
|
+
pass
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
__all__ = [
|
|
31
|
+
'ConsoleError',
|
|
32
|
+
'EventLoggerError',
|
|
33
|
+
'ConsoleWriterError',
|
|
34
|
+
]
|
|
@@ -0,0 +1,385 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
#exonware/xwsystem/src/exonware/xwsystem/console/event_logger.py
|
|
3
|
+
#exonware/xwsystem/console/event_logger.py
|
|
4
|
+
"""
|
|
5
|
+
Company: eXonware.com
|
|
6
|
+
Author: Eng. Muhammad AlShehri
|
|
7
|
+
Email: connect@exonware.com
|
|
8
|
+
Version: 0.1.0.3
|
|
9
|
+
Generation Date: 2025-01-27
|
|
10
|
+
|
|
11
|
+
Console Event Logger implementation for structured logging.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
import time
|
|
15
|
+
import threading
|
|
16
|
+
from typing import Optional, Any
|
|
17
|
+
from .base import AEventLogger
|
|
18
|
+
from .defs import LogLevel, ConsoleEventType, ConsoleEvent
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class ConsoleEventLogger(AEventLogger):
|
|
22
|
+
"""
|
|
23
|
+
Console event logger for structured logging.
|
|
24
|
+
|
|
25
|
+
This logger generates structured events with consistent formatting.
|
|
26
|
+
All other loggers in xwsystem should reuse this for structured logging.
|
|
27
|
+
|
|
28
|
+
Example:
|
|
29
|
+
logger = ConsoleEventLogger()
|
|
30
|
+
logger.log("App initialized", source="app.init")
|
|
31
|
+
logger.error("Failed to connect", source="api.client", data={"endpoint": "/api/users"})
|
|
32
|
+
events = logger.get_events() # Returns list of ConsoleEvent dicts
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
# Default colors for each event type
|
|
36
|
+
DEFAULT_COLORS = {
|
|
37
|
+
'log': '#ffffff',
|
|
38
|
+
'info': '#4aa3ff',
|
|
39
|
+
'warn': '#ffb020',
|
|
40
|
+
'error': '#ff4d4f',
|
|
41
|
+
'debug': '#b38cff',
|
|
42
|
+
'trace': '#ff85c0',
|
|
43
|
+
'group': '#ffd666',
|
|
44
|
+
'groupCollapsed': '#ffd666',
|
|
45
|
+
'groupEnd': '#ffd666',
|
|
46
|
+
'table': '#40a9ff',
|
|
47
|
+
'success': '#2ecc71',
|
|
48
|
+
'system': '#888',
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
# Default labels for each event type
|
|
52
|
+
DEFAULT_LABELS = {
|
|
53
|
+
'log': 'LOG',
|
|
54
|
+
'info': 'INFO',
|
|
55
|
+
'warn': 'WARN',
|
|
56
|
+
'error': 'ERROR',
|
|
57
|
+
'debug': 'DEBUG',
|
|
58
|
+
'trace': 'TRACE',
|
|
59
|
+
'group': 'GROUP',
|
|
60
|
+
'groupCollapsed': 'GROUP',
|
|
61
|
+
'groupEnd': 'END',
|
|
62
|
+
'table': 'TABLE',
|
|
63
|
+
'success': 'OK',
|
|
64
|
+
'system': 'SYSTEM',
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
# Type to level mapping (when level not explicitly provided)
|
|
68
|
+
TYPE_TO_LEVEL: dict[ConsoleEventType, LogLevel] = {
|
|
69
|
+
'error': 'error',
|
|
70
|
+
'warn': 'warn',
|
|
71
|
+
'info': 'info',
|
|
72
|
+
'debug': 'debug',
|
|
73
|
+
'trace': 'debug',
|
|
74
|
+
'log': 'log',
|
|
75
|
+
'success': 'log',
|
|
76
|
+
'system': 'log',
|
|
77
|
+
'table': 'log',
|
|
78
|
+
'group': 'log',
|
|
79
|
+
'groupCollapsed': 'log',
|
|
80
|
+
'groupEnd': 'log',
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
def __init__(
|
|
84
|
+
self,
|
|
85
|
+
max_entries: int = 1000,
|
|
86
|
+
use_milliseconds: bool = True,
|
|
87
|
+
default_source: Optional[str] = None
|
|
88
|
+
):
|
|
89
|
+
"""
|
|
90
|
+
Initialize console event logger.
|
|
91
|
+
|
|
92
|
+
Args:
|
|
93
|
+
max_entries: Maximum number of events to keep in memory
|
|
94
|
+
use_milliseconds: If True, timestamps in milliseconds; if False, in seconds
|
|
95
|
+
default_source: Default source name for all events (can be overridden per event)
|
|
96
|
+
"""
|
|
97
|
+
self.max_entries = max_entries
|
|
98
|
+
self.use_milliseconds = use_milliseconds
|
|
99
|
+
self.default_source = default_source
|
|
100
|
+
self._events: list[ConsoleEvent] = []
|
|
101
|
+
self._event_id_counter = 0
|
|
102
|
+
self._lock = threading.Lock()
|
|
103
|
+
|
|
104
|
+
def _get_timestamp(self) -> float:
|
|
105
|
+
"""Get current timestamp in the configured format."""
|
|
106
|
+
if self.use_milliseconds:
|
|
107
|
+
return time.time() * 1000 # Milliseconds
|
|
108
|
+
return time.time() # Seconds
|
|
109
|
+
|
|
110
|
+
def _get_next_id(self) -> int:
|
|
111
|
+
"""Get next event ID (thread-safe)."""
|
|
112
|
+
with self._lock:
|
|
113
|
+
self._event_id_counter += 1
|
|
114
|
+
return self._event_id_counter
|
|
115
|
+
|
|
116
|
+
def _add_event(
|
|
117
|
+
self,
|
|
118
|
+
event_type: ConsoleEventType,
|
|
119
|
+
msg: str,
|
|
120
|
+
source: Optional[str] = None,
|
|
121
|
+
level: Optional[LogLevel] = None,
|
|
122
|
+
color: Optional[str] = None,
|
|
123
|
+
label: Optional[str] = None,
|
|
124
|
+
timestamp: Optional[float | int | str] = None,
|
|
125
|
+
data: Optional[Any] = None
|
|
126
|
+
) -> ConsoleEvent:
|
|
127
|
+
"""
|
|
128
|
+
Add an event to the log (internal method).
|
|
129
|
+
|
|
130
|
+
Args:
|
|
131
|
+
event_type: Type of console event
|
|
132
|
+
msg: Message text
|
|
133
|
+
source: Source/operation/module name (uses default_source if not provided)
|
|
134
|
+
level: Explicit log level (derived from type if not provided)
|
|
135
|
+
color: Color for display (uses default for type if not provided)
|
|
136
|
+
label: Label for badge (uses default for type if not provided)
|
|
137
|
+
timestamp: Timestamp (uses current time if not provided)
|
|
138
|
+
data: Additional structured data
|
|
139
|
+
|
|
140
|
+
Returns:
|
|
141
|
+
Created ConsoleEvent
|
|
142
|
+
"""
|
|
143
|
+
event_id = self._get_next_id()
|
|
144
|
+
event_timestamp = timestamp if timestamp is not None else self._get_timestamp()
|
|
145
|
+
event_source = source if source is not None else self.default_source
|
|
146
|
+
event_level = level if level is not None else self.TYPE_TO_LEVEL.get(event_type, 'log')
|
|
147
|
+
event_color = color if color is not None else self.DEFAULT_COLORS.get(event_type, '#ffffff')
|
|
148
|
+
event_label = label if label is not None else self.DEFAULT_LABELS.get(event_type, 'LOG')
|
|
149
|
+
|
|
150
|
+
event = ConsoleEvent(
|
|
151
|
+
id=event_id,
|
|
152
|
+
type=event_type,
|
|
153
|
+
timestamp=event_timestamp,
|
|
154
|
+
color=event_color,
|
|
155
|
+
label=event_label,
|
|
156
|
+
msg=msg,
|
|
157
|
+
source=event_source,
|
|
158
|
+
level=event_level,
|
|
159
|
+
data=data
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
with self._lock:
|
|
163
|
+
self._events.append(event)
|
|
164
|
+
# Limit entries
|
|
165
|
+
if len(self._events) > self.max_entries:
|
|
166
|
+
self._events = self._events[-self.max_entries:]
|
|
167
|
+
|
|
168
|
+
return event
|
|
169
|
+
|
|
170
|
+
# Public API methods matching common logging patterns
|
|
171
|
+
|
|
172
|
+
def log(
|
|
173
|
+
self,
|
|
174
|
+
msg: str,
|
|
175
|
+
source: Optional[str] = None,
|
|
176
|
+
data: Optional[Any] = None,
|
|
177
|
+
color: Optional[str] = None,
|
|
178
|
+
label: Optional[str] = None
|
|
179
|
+
) -> ConsoleEvent:
|
|
180
|
+
"""Log a general message."""
|
|
181
|
+
return self._add_event('log', msg, source=source, data=data, color=color, label=label)
|
|
182
|
+
|
|
183
|
+
def info(
|
|
184
|
+
self,
|
|
185
|
+
msg: str,
|
|
186
|
+
source: Optional[str] = None,
|
|
187
|
+
data: Optional[Any] = None
|
|
188
|
+
) -> ConsoleEvent:
|
|
189
|
+
"""Log an info message."""
|
|
190
|
+
return self._add_event('info', msg, source=source, data=data)
|
|
191
|
+
|
|
192
|
+
def warn(
|
|
193
|
+
self,
|
|
194
|
+
msg: str,
|
|
195
|
+
source: Optional[str] = None,
|
|
196
|
+
data: Optional[Any] = None
|
|
197
|
+
) -> ConsoleEvent:
|
|
198
|
+
"""Log a warning message."""
|
|
199
|
+
return self._add_event('warn', msg, source=source, data=data)
|
|
200
|
+
|
|
201
|
+
def error(
|
|
202
|
+
self,
|
|
203
|
+
msg: str,
|
|
204
|
+
source: Optional[str] = None,
|
|
205
|
+
data: Optional[Any] = None,
|
|
206
|
+
stack: Optional[str] = None
|
|
207
|
+
) -> ConsoleEvent:
|
|
208
|
+
"""Log an error message."""
|
|
209
|
+
error_data = data
|
|
210
|
+
if stack is not None:
|
|
211
|
+
error_data = error_data or {}
|
|
212
|
+
if isinstance(error_data, dict):
|
|
213
|
+
error_data['stack'] = stack
|
|
214
|
+
return self._add_event('error', msg, source=source, data=error_data)
|
|
215
|
+
|
|
216
|
+
def debug(
|
|
217
|
+
self,
|
|
218
|
+
msg: str,
|
|
219
|
+
source: Optional[str] = None,
|
|
220
|
+
data: Optional[Any] = None
|
|
221
|
+
) -> ConsoleEvent:
|
|
222
|
+
"""Log a debug message."""
|
|
223
|
+
return self._add_event('debug', msg, source=source, data=data)
|
|
224
|
+
|
|
225
|
+
def trace(
|
|
226
|
+
self,
|
|
227
|
+
msg: str,
|
|
228
|
+
source: Optional[str] = None,
|
|
229
|
+
data: Optional[Any] = None
|
|
230
|
+
) -> ConsoleEvent:
|
|
231
|
+
"""Log a trace message."""
|
|
232
|
+
return self._add_event('trace', msg, source=source, data=data)
|
|
233
|
+
|
|
234
|
+
def success(
|
|
235
|
+
self,
|
|
236
|
+
msg: str,
|
|
237
|
+
source: Optional[str] = None,
|
|
238
|
+
data: Optional[Any] = None
|
|
239
|
+
) -> ConsoleEvent:
|
|
240
|
+
"""Log a success message."""
|
|
241
|
+
return self._add_event('success', msg, source=source, data=data)
|
|
242
|
+
|
|
243
|
+
def system(
|
|
244
|
+
self,
|
|
245
|
+
msg: str,
|
|
246
|
+
source: Optional[str] = None,
|
|
247
|
+
data: Optional[Any] = None
|
|
248
|
+
) -> ConsoleEvent:
|
|
249
|
+
"""Log a system message."""
|
|
250
|
+
return self._add_event('system', msg, source=source, data=data)
|
|
251
|
+
|
|
252
|
+
def group(
|
|
253
|
+
self,
|
|
254
|
+
msg: str,
|
|
255
|
+
source: Optional[str] = None,
|
|
256
|
+
data: Optional[Any] = None
|
|
257
|
+
) -> ConsoleEvent:
|
|
258
|
+
"""Start a log group."""
|
|
259
|
+
return self._add_event('group', msg, source=source, data=data)
|
|
260
|
+
|
|
261
|
+
def group_collapsed(
|
|
262
|
+
self,
|
|
263
|
+
msg: str,
|
|
264
|
+
source: Optional[str] = None,
|
|
265
|
+
data: Optional[Any] = None
|
|
266
|
+
) -> ConsoleEvent:
|
|
267
|
+
"""Start a collapsed log group."""
|
|
268
|
+
return self._add_event('groupCollapsed', msg, source=source, data=data)
|
|
269
|
+
|
|
270
|
+
def group_end(
|
|
271
|
+
self,
|
|
272
|
+
msg: str = "",
|
|
273
|
+
source: Optional[str] = None
|
|
274
|
+
) -> ConsoleEvent:
|
|
275
|
+
"""End a log group."""
|
|
276
|
+
return self._add_event('groupEnd', msg, source=source)
|
|
277
|
+
|
|
278
|
+
def table(
|
|
279
|
+
self,
|
|
280
|
+
msg: str,
|
|
281
|
+
source: Optional[str] = None,
|
|
282
|
+
data: Optional[Any] = None
|
|
283
|
+
) -> ConsoleEvent:
|
|
284
|
+
"""Log a table message."""
|
|
285
|
+
return self._add_event('table', msg, source=source, data=data)
|
|
286
|
+
|
|
287
|
+
def add_event(
|
|
288
|
+
self,
|
|
289
|
+
event_type: ConsoleEventType,
|
|
290
|
+
msg: str,
|
|
291
|
+
source: Optional[str] = None,
|
|
292
|
+
level: Optional[LogLevel] = None,
|
|
293
|
+
color: Optional[str] = None,
|
|
294
|
+
label: Optional[str] = None,
|
|
295
|
+
timestamp: Optional[float | int | str] = None,
|
|
296
|
+
data: Optional[Any] = None
|
|
297
|
+
) -> ConsoleEvent:
|
|
298
|
+
"""
|
|
299
|
+
Add a custom event with full control over all fields.
|
|
300
|
+
|
|
301
|
+
Args:
|
|
302
|
+
event_type: Type of console event
|
|
303
|
+
msg: Message text
|
|
304
|
+
source: Source/operation/module name
|
|
305
|
+
level: Explicit log level
|
|
306
|
+
color: Color for display
|
|
307
|
+
label: Label for badge
|
|
308
|
+
timestamp: Timestamp (Unix timestamp or ISO string)
|
|
309
|
+
data: Additional structured data
|
|
310
|
+
|
|
311
|
+
Returns:
|
|
312
|
+
Created ConsoleEvent
|
|
313
|
+
"""
|
|
314
|
+
return self._add_event(
|
|
315
|
+
event_type, msg,
|
|
316
|
+
source=source,
|
|
317
|
+
level=level,
|
|
318
|
+
color=color,
|
|
319
|
+
label=label,
|
|
320
|
+
timestamp=timestamp,
|
|
321
|
+
data=data
|
|
322
|
+
)
|
|
323
|
+
|
|
324
|
+
def get_events(
|
|
325
|
+
self,
|
|
326
|
+
event_type: Optional[ConsoleEventType] = None,
|
|
327
|
+
level: Optional[LogLevel] = None,
|
|
328
|
+
source: Optional[str] = None,
|
|
329
|
+
limit: Optional[int] = None
|
|
330
|
+
) -> list[dict]:
|
|
331
|
+
"""
|
|
332
|
+
Get logged events as dictionaries.
|
|
333
|
+
|
|
334
|
+
Args:
|
|
335
|
+
event_type: Filter by event type
|
|
336
|
+
level: Filter by log level
|
|
337
|
+
source: Filter by source
|
|
338
|
+
limit: Maximum number of events to return (most recent)
|
|
339
|
+
|
|
340
|
+
Returns:
|
|
341
|
+
List of event dictionaries in ConsoleEvent format
|
|
342
|
+
"""
|
|
343
|
+
with self._lock:
|
|
344
|
+
events = self._events.copy()
|
|
345
|
+
|
|
346
|
+
# Apply filters
|
|
347
|
+
if event_type is not None:
|
|
348
|
+
events = [e for e in events if e.type == event_type]
|
|
349
|
+
if level is not None:
|
|
350
|
+
events = [e for e in events if (e.level or self.TYPE_TO_LEVEL.get(e.type, 'log')) == level]
|
|
351
|
+
if source is not None:
|
|
352
|
+
events = [e for e in events if e.source == source]
|
|
353
|
+
|
|
354
|
+
# Apply limit (most recent)
|
|
355
|
+
if limit is not None and limit > 0:
|
|
356
|
+
events = events[-limit:]
|
|
357
|
+
|
|
358
|
+
# Convert to dictionaries
|
|
359
|
+
return [e.to_dict() for e in events]
|
|
360
|
+
|
|
361
|
+
def get_events_raw(self) -> list[ConsoleEvent]:
|
|
362
|
+
"""
|
|
363
|
+
Get logged events as ConsoleEvent objects.
|
|
364
|
+
|
|
365
|
+
Returns:
|
|
366
|
+
List of ConsoleEvent objects
|
|
367
|
+
"""
|
|
368
|
+
with self._lock:
|
|
369
|
+
return self._events.copy()
|
|
370
|
+
|
|
371
|
+
def clear(self) -> None:
|
|
372
|
+
"""Clear all logged events."""
|
|
373
|
+
with self._lock:
|
|
374
|
+
self._events.clear()
|
|
375
|
+
self._event_id_counter = 0
|
|
376
|
+
|
|
377
|
+
def count(self) -> int:
|
|
378
|
+
"""Get the number of logged events."""
|
|
379
|
+
with self._lock:
|
|
380
|
+
return len(self._events)
|
|
381
|
+
|
|
382
|
+
|
|
383
|
+
__all__ = [
|
|
384
|
+
'ConsoleEventLogger',
|
|
385
|
+
]
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
#exonware/xwsystem/src/exonware/xwsystem/console/writer.py
|
|
3
|
+
#exonware/xwsystem/console/writer.py
|
|
4
|
+
"""
|
|
5
|
+
Company: eXonware.com
|
|
6
|
+
Author: Eng. Muhammad AlShehri
|
|
7
|
+
Email: connect@exonware.com
|
|
8
|
+
Version: 0.1.0.3
|
|
9
|
+
Generation Date: 2025-01-27
|
|
10
|
+
|
|
11
|
+
Console Writer implementation for user interaction (not logging).
|
|
12
|
+
Can be used as a base class for bots and other user interaction systems.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
import os
|
|
16
|
+
import platform
|
|
17
|
+
import sys
|
|
18
|
+
from typing import Optional
|
|
19
|
+
from .base import AConsoleWriter
|
|
20
|
+
from .errors import ConsoleWriterError
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class ConsoleWriter(AConsoleWriter):
|
|
24
|
+
"""
|
|
25
|
+
Console writer for user interaction (not logging).
|
|
26
|
+
|
|
27
|
+
This class provides methods for writing to and reading from the console.
|
|
28
|
+
Can be used as a base class for bots and other user interaction systems.
|
|
29
|
+
|
|
30
|
+
Example:
|
|
31
|
+
writer = ConsoleWriter()
|
|
32
|
+
writer.write_line("Hello, user!")
|
|
33
|
+
name = writer.read("Enter your name: ")
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
def __init__(self):
|
|
37
|
+
"""Initialize console writer."""
|
|
38
|
+
self._supports_color = self._check_color_support()
|
|
39
|
+
self._is_interactive = self._check_interactive()
|
|
40
|
+
|
|
41
|
+
def _check_color_support(self) -> bool:
|
|
42
|
+
"""Check if terminal supports color."""
|
|
43
|
+
try:
|
|
44
|
+
return (
|
|
45
|
+
hasattr(sys.stdout, 'isatty') and
|
|
46
|
+
sys.stdout.isatty() and
|
|
47
|
+
os.getenv('TERM') != 'dumb' and
|
|
48
|
+
os.getenv('NO_COLOR') is None
|
|
49
|
+
)
|
|
50
|
+
except (AttributeError, OSError, RuntimeError):
|
|
51
|
+
# Catch specific exceptions - stdout may not support isatty
|
|
52
|
+
return False
|
|
53
|
+
|
|
54
|
+
def _check_interactive(self) -> bool:
|
|
55
|
+
"""Check if console is interactive."""
|
|
56
|
+
try:
|
|
57
|
+
return hasattr(sys.stdin, 'isatty') and sys.stdin.isatty()
|
|
58
|
+
except (AttributeError, OSError, RuntimeError):
|
|
59
|
+
# Catch specific exceptions - stdin may not support isatty
|
|
60
|
+
return False
|
|
61
|
+
|
|
62
|
+
def write(self, text: str, **kwargs) -> None:
|
|
63
|
+
"""
|
|
64
|
+
Write text to console.
|
|
65
|
+
|
|
66
|
+
Args:
|
|
67
|
+
text: Text to write
|
|
68
|
+
**kwargs: Additional arguments passed to print()
|
|
69
|
+
"""
|
|
70
|
+
try:
|
|
71
|
+
print(text, end='', **kwargs)
|
|
72
|
+
sys.stdout.flush()
|
|
73
|
+
except Exception as e:
|
|
74
|
+
raise ConsoleWriterError(f"Failed to write to console: {e}")
|
|
75
|
+
|
|
76
|
+
def write_line(self, text: str = "", **kwargs) -> None:
|
|
77
|
+
"""
|
|
78
|
+
Write a line to console.
|
|
79
|
+
|
|
80
|
+
Args:
|
|
81
|
+
text: Text to write (default: empty string)
|
|
82
|
+
**kwargs: Additional arguments passed to print()
|
|
83
|
+
"""
|
|
84
|
+
try:
|
|
85
|
+
print(text, **kwargs)
|
|
86
|
+
sys.stdout.flush()
|
|
87
|
+
except Exception as e:
|
|
88
|
+
raise ConsoleWriterError(f"Failed to write line to console: {e}")
|
|
89
|
+
|
|
90
|
+
def read(self, prompt: str = "") -> str:
|
|
91
|
+
"""
|
|
92
|
+
Read input from console.
|
|
93
|
+
|
|
94
|
+
Args:
|
|
95
|
+
prompt: Prompt text to display before reading
|
|
96
|
+
|
|
97
|
+
Returns:
|
|
98
|
+
User input string
|
|
99
|
+
|
|
100
|
+
Raises:
|
|
101
|
+
ConsoleWriterError: If console is not interactive
|
|
102
|
+
"""
|
|
103
|
+
try:
|
|
104
|
+
if not self._is_interactive:
|
|
105
|
+
raise ConsoleWriterError("Console is not interactive")
|
|
106
|
+
|
|
107
|
+
return input(prompt)
|
|
108
|
+
except Exception as e:
|
|
109
|
+
raise ConsoleWriterError(f"Failed to read from console: {e}")
|
|
110
|
+
|
|
111
|
+
def clear(self) -> None:
|
|
112
|
+
"""Clear console screen using Python's native platform detection."""
|
|
113
|
+
try:
|
|
114
|
+
if platform.system() == 'Windows':
|
|
115
|
+
os.system('cls')
|
|
116
|
+
else: # Unix/Linux/macOS
|
|
117
|
+
os.system('clear')
|
|
118
|
+
except Exception as e:
|
|
119
|
+
raise ConsoleWriterError(f"Failed to clear console: {e}")
|
|
120
|
+
|
|
121
|
+
def is_interactive(self) -> bool:
|
|
122
|
+
"""Check if console is interactive."""
|
|
123
|
+
return self._is_interactive
|
|
124
|
+
|
|
125
|
+
def supports_color(self) -> bool:
|
|
126
|
+
"""Check if console supports color."""
|
|
127
|
+
return self._supports_color
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
__all__ = [
|
|
131
|
+
'ConsoleWriter',
|
|
132
|
+
]
|