exonware-xwsystem 0.1.0.1__py3-none-any.whl → 0.1.0.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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.4.dist-info}/METADATA +71 -4
- exonware_xwsystem-0.1.0.4.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.4.dist-info}/WHEEL +0 -0
- {exonware_xwsystem-0.1.0.1.dist-info → exonware_xwsystem-0.1.0.4.dist-info}/licenses/LICENSE +0 -0
exonware/xwsystem/ipc/pipes.py
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
#exonware/xwsystem/src/exonware/xwsystem/ipc/pipes.py
|
|
1
2
|
"""
|
|
2
3
|
Pipe Communication Utilities
|
|
3
4
|
============================
|
|
@@ -12,10 +13,11 @@ Generation Date: September 05, 2025
|
|
|
12
13
|
|
|
13
14
|
import asyncio
|
|
14
15
|
import os
|
|
16
|
+
import platform
|
|
15
17
|
import sys
|
|
16
18
|
import threading
|
|
17
19
|
import multiprocessing as mp
|
|
18
|
-
from typing import Any, Optional,
|
|
20
|
+
from typing import Any, Optional, Callable, BinaryIO
|
|
19
21
|
import pickle
|
|
20
22
|
import struct
|
|
21
23
|
import logging
|
|
@@ -46,8 +48,8 @@ class Pipe:
|
|
|
46
48
|
self.duplex = duplex
|
|
47
49
|
self.buffer_size = buffer_size
|
|
48
50
|
|
|
49
|
-
# Create pipe
|
|
50
|
-
if
|
|
51
|
+
# Create pipe using Python's native platform detection
|
|
52
|
+
if platform.system() == 'Windows':
|
|
51
53
|
# Windows named pipes
|
|
52
54
|
import uuid
|
|
53
55
|
self.pipe_name = f"\\\\.\\pipe\\xwsystem_{uuid.uuid4().hex}"
|
|
@@ -61,37 +63,41 @@ class Pipe:
|
|
|
61
63
|
|
|
62
64
|
def _create_windows_pipe(self):
|
|
63
65
|
"""Create Windows named pipe."""
|
|
64
|
-
#
|
|
65
|
-
|
|
66
|
-
|
|
66
|
+
# Use conditional import - pywin32 is optional for Windows optimizations
|
|
67
|
+
# If not available, fallback to multiprocessing pipe
|
|
68
|
+
if platform.system() == 'Windows':
|
|
69
|
+
import importlib.util
|
|
70
|
+
# Check if pywin32 is available without try/except
|
|
71
|
+
spec = importlib.util.find_spec('win32pipe')
|
|
72
|
+
if spec is not None:
|
|
73
|
+
win32pipe = importlib.import_module('win32pipe')
|
|
74
|
+
win32file = importlib.import_module('win32file')
|
|
75
|
+
|
|
76
|
+
# Create named pipe
|
|
77
|
+
self._pipe_handle = win32pipe.CreateNamedPipe(
|
|
78
|
+
self.pipe_name,
|
|
79
|
+
win32pipe.PIPE_ACCESS_DUPLEX if self.duplex else win32pipe.PIPE_ACCESS_OUTBOUND,
|
|
80
|
+
win32pipe.PIPE_TYPE_BYTE | win32pipe.PIPE_READMODE_BYTE | win32pipe.PIPE_WAIT,
|
|
81
|
+
1, # max instances
|
|
82
|
+
self.buffer_size, # out buffer size
|
|
83
|
+
self.buffer_size, # in buffer size
|
|
84
|
+
0, # default timeout
|
|
85
|
+
None # security attributes
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
self._read_handle = self._pipe_handle
|
|
89
|
+
self._write_handle = self._pipe_handle
|
|
90
|
+
return
|
|
67
91
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
win32pipe.PIPE_ACCESS_DUPLEX if self.duplex else win32pipe.PIPE_ACCESS_OUTBOUND,
|
|
73
|
-
win32pipe.PIPE_TYPE_BYTE | win32pipe.PIPE_READMODE_BYTE | win32pipe.PIPE_WAIT,
|
|
74
|
-
1, # max instances
|
|
75
|
-
self.buffer_size, # out buffer size
|
|
76
|
-
self.buffer_size, # in buffer size
|
|
77
|
-
0, # default timeout
|
|
78
|
-
None # security attributes
|
|
79
|
-
)
|
|
80
|
-
|
|
81
|
-
self._read_handle = self._pipe_handle
|
|
82
|
-
self._write_handle = self._pipe_handle
|
|
83
|
-
|
|
84
|
-
except Exception as e:
|
|
85
|
-
# Fallback to multiprocessing pipe if named pipe creation fails
|
|
86
|
-
logger.warning(f"Windows named pipe creation failed: {e}, using multiprocessing pipe")
|
|
87
|
-
self._read_conn, self._write_conn = mp.Pipe(self.duplex)
|
|
88
|
-
self._read_handle = self._read_conn
|
|
89
|
-
self._write_handle = self._write_conn
|
|
92
|
+
# Fallback to multiprocessing pipe (if not Windows or pywin32 not available)
|
|
93
|
+
self._read_conn, self._write_conn = mp.Pipe(self.duplex)
|
|
94
|
+
self._read_handle = self._read_conn
|
|
95
|
+
self._write_handle = self._write_conn
|
|
90
96
|
|
|
91
97
|
def _create_unix_pipe(self):
|
|
92
98
|
"""Create Unix pipe."""
|
|
93
99
|
try:
|
|
94
|
-
# Try to use os.pipe() for
|
|
100
|
+
# Try to use os.pipe() for performance
|
|
95
101
|
read_fd, write_fd = os.pipe()
|
|
96
102
|
self._read_handle = os.fdopen(read_fd, 'rb')
|
|
97
103
|
self._write_handle = os.fdopen(write_fd, 'wb')
|
|
@@ -277,7 +283,7 @@ class AsyncPipe:
|
|
|
277
283
|
async def connect(self) -> bool:
|
|
278
284
|
"""Connect to the async pipe."""
|
|
279
285
|
try:
|
|
280
|
-
if
|
|
286
|
+
if platform.system() != 'Windows':
|
|
281
287
|
# Unix domain socket
|
|
282
288
|
if not self._server:
|
|
283
289
|
await self._create_unix_socket()
|
|
@@ -287,10 +293,40 @@ class AsyncPipe:
|
|
|
287
293
|
self._setup_complete.set()
|
|
288
294
|
|
|
289
295
|
else:
|
|
290
|
-
# Windows: Use asyncio
|
|
291
|
-
# This
|
|
292
|
-
|
|
293
|
-
|
|
296
|
+
# Windows: Use multiprocessing pipes wrapped in asyncio for cross-platform parity
|
|
297
|
+
# This ensures Windows and Linux have the same capabilities
|
|
298
|
+
# Create multiprocessing pipe and wrap in asyncio streams
|
|
299
|
+
self._read_conn, self._write_conn = mp.Pipe(duplex=True)
|
|
300
|
+
|
|
301
|
+
# Wrap multiprocessing connection in asyncio streams
|
|
302
|
+
# Use loop.run_in_executor for blocking operations
|
|
303
|
+
loop = asyncio.get_event_loop()
|
|
304
|
+
|
|
305
|
+
# Create reader/writer from file descriptors
|
|
306
|
+
# Note: multiprocessing.Pipe() returns Connection objects, not file descriptors
|
|
307
|
+
# We need to use a different approach - use asyncio subprocess pipes
|
|
308
|
+
# For true cross-platform parity, we'll use the same Unix socket approach on Windows
|
|
309
|
+
# by using a temporary named pipe path that works on both platforms
|
|
310
|
+
import tempfile
|
|
311
|
+
temp_dir = tempfile.gettempdir()
|
|
312
|
+
self._pipe_path = os.path.join(temp_dir, f"xwsystem_pipe_{os.getpid()}")
|
|
313
|
+
|
|
314
|
+
# On Windows, use TCP localhost socket instead (works same as Unix sockets)
|
|
315
|
+
# This ensures exact same capabilities on both platforms
|
|
316
|
+
self._server = await asyncio.start_server(
|
|
317
|
+
self._handle_client,
|
|
318
|
+
'127.0.0.1',
|
|
319
|
+
0 # Let OS assign port
|
|
320
|
+
)
|
|
321
|
+
# Get the actual port
|
|
322
|
+
sock = self._server.sockets[0]
|
|
323
|
+
self._pipe_port = sock.getsockname()[1]
|
|
324
|
+
|
|
325
|
+
# Connect as client
|
|
326
|
+
self._reader, self._writer = await asyncio.open_connection('127.0.0.1', self._pipe_port)
|
|
327
|
+
self._setup_complete.set()
|
|
328
|
+
|
|
329
|
+
logger.debug(f"Created async TCP localhost pipe on Windows (port {self._pipe_port}) for cross-platform parity")
|
|
294
330
|
|
|
295
331
|
logger.debug("Connected to async pipe")
|
|
296
332
|
return True
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
#exonware/xwsystem/src/exonware/xwsystem/ipc/process_manager.py
|
|
1
2
|
"""
|
|
2
3
|
Process Management Utilities
|
|
3
4
|
============================
|
|
@@ -11,12 +12,13 @@ Generation Date: September 05, 2025
|
|
|
11
12
|
"""
|
|
12
13
|
|
|
13
14
|
import os
|
|
15
|
+
import platform
|
|
14
16
|
import sys
|
|
15
17
|
import time
|
|
16
18
|
import signal
|
|
17
19
|
import subprocess
|
|
18
20
|
import multiprocessing as mp
|
|
19
|
-
from typing import Optional, Callable, Any
|
|
21
|
+
from typing import Optional, Callable, Any
|
|
20
22
|
from dataclasses import dataclass
|
|
21
23
|
from threading import Lock, Event
|
|
22
24
|
import logging
|
|
@@ -74,7 +76,7 @@ class ProcessManager:
|
|
|
74
76
|
|
|
75
77
|
def start_process(self,
|
|
76
78
|
name: str,
|
|
77
|
-
command:
|
|
79
|
+
command: str | list[str],
|
|
78
80
|
cwd: Optional[str] = None,
|
|
79
81
|
env: Optional[dict[str, str]] = None,
|
|
80
82
|
shell: bool = False) -> bool:
|
|
@@ -115,7 +117,7 @@ class ProcessManager:
|
|
|
115
117
|
shell=shell,
|
|
116
118
|
stdout=subprocess.PIPE,
|
|
117
119
|
stderr=subprocess.PIPE,
|
|
118
|
-
preexec_fn=None if
|
|
120
|
+
preexec_fn=None if platform.system() == 'Windows' else os.setsid
|
|
119
121
|
)
|
|
120
122
|
|
|
121
123
|
# Store process info
|
|
@@ -162,7 +164,7 @@ class ProcessManager:
|
|
|
162
164
|
return True
|
|
163
165
|
|
|
164
166
|
# Try graceful shutdown first
|
|
165
|
-
if
|
|
167
|
+
if platform.system() != 'Windows':
|
|
166
168
|
os.killpg(os.getpgid(process.pid), signal.SIGTERM)
|
|
167
169
|
else:
|
|
168
170
|
process.terminate()
|
|
@@ -178,7 +180,7 @@ class ProcessManager:
|
|
|
178
180
|
except subprocess.TimeoutExpired:
|
|
179
181
|
# Force kill if graceful shutdown failed
|
|
180
182
|
logger.warning(f"Process '{name}' did not stop gracefully, force killing")
|
|
181
|
-
if
|
|
183
|
+
if platform.system() != 'Windows':
|
|
182
184
|
os.killpg(os.getpgid(process.pid), signal.SIGKILL)
|
|
183
185
|
else:
|
|
184
186
|
process.kill()
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
#exonware/xwsystem/src/exonware/xwsystem/ipc/process_pool.py
|
|
1
2
|
"""
|
|
2
3
|
Process Pool Utilities
|
|
3
4
|
======================
|
|
@@ -17,7 +18,7 @@ import logging
|
|
|
17
18
|
import multiprocessing as mp
|
|
18
19
|
import time
|
|
19
20
|
from dataclasses import dataclass
|
|
20
|
-
from typing import Any, Callable, Optional
|
|
21
|
+
from typing import Any, Callable, Optional
|
|
21
22
|
|
|
22
23
|
logger = logging.getLogger(__name__)
|
|
23
24
|
|
|
@@ -48,7 +49,7 @@ class ProcessPool:
|
|
|
48
49
|
|
|
49
50
|
def __init__(self,
|
|
50
51
|
max_workers: Optional[int] = None,
|
|
51
|
-
size: Optional[int] = None,
|
|
52
|
+
size: Optional[int] = None,
|
|
52
53
|
initializer: Optional[Callable] = None,
|
|
53
54
|
initargs: tuple = (),
|
|
54
55
|
timeout: Optional[float] = None):
|
|
@@ -57,12 +58,12 @@ class ProcessPool:
|
|
|
57
58
|
|
|
58
59
|
Args:
|
|
59
60
|
max_workers: Maximum number of worker processes
|
|
60
|
-
size: Alias for max_workers
|
|
61
|
+
size: Alias for max_workers
|
|
61
62
|
initializer: Function to run in each worker on startup
|
|
62
63
|
initargs: Arguments for initializer function
|
|
63
64
|
timeout: Default timeout for tasks
|
|
64
65
|
"""
|
|
65
|
-
# Handle
|
|
66
|
+
# Handle 'size' parameter as alias for max_workers
|
|
66
67
|
if size is not None and max_workers is None:
|
|
67
68
|
max_workers = size
|
|
68
69
|
|
|
@@ -188,7 +189,7 @@ class ProcessPool:
|
|
|
188
189
|
# Wait for completion
|
|
189
190
|
future.result(timeout=timeout)
|
|
190
191
|
|
|
191
|
-
#
|
|
192
|
+
# In completed tasks now
|
|
192
193
|
for result in self._completed_tasks:
|
|
193
194
|
if result.task_id == task_id:
|
|
194
195
|
return result.result
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
#exonware/xwsystem/src/exonware/xwsystem/ipc/shared_memory.py
|
|
1
2
|
"""
|
|
2
3
|
Shared Memory Utilities
|
|
3
4
|
=======================
|
|
@@ -11,12 +12,13 @@ Generation Date: September 05, 2025
|
|
|
11
12
|
"""
|
|
12
13
|
|
|
13
14
|
import os
|
|
15
|
+
import platform
|
|
14
16
|
import sys
|
|
15
17
|
import mmap
|
|
16
18
|
import struct
|
|
17
19
|
import pickle
|
|
18
20
|
import threading
|
|
19
|
-
from typing import Any, Optional
|
|
21
|
+
from typing import Any, Optional
|
|
20
22
|
# Root cause: Migrating to Python 3.12 built-in generic syntax for consistency
|
|
21
23
|
# Priority #3: Maintainability - Modern type annotations improve code clarity
|
|
22
24
|
from contextlib import contextmanager
|
|
@@ -24,6 +26,11 @@ import logging
|
|
|
24
26
|
|
|
25
27
|
logger = logging.getLogger(__name__)
|
|
26
28
|
|
|
29
|
+
# Global registry for shared memory segments (cross-platform)
|
|
30
|
+
# Used to enable attachment to existing segments on both Windows and Unix
|
|
31
|
+
_shared_memory_registry: dict[str, dict] = {}
|
|
32
|
+
_registry_lock = threading.RLock()
|
|
33
|
+
|
|
27
34
|
|
|
28
35
|
class SharedData[T]:
|
|
29
36
|
"""
|
|
@@ -60,7 +67,7 @@ class SharedData[T]:
|
|
|
60
67
|
def _create_segment(self):
|
|
61
68
|
"""Create a new shared memory segment."""
|
|
62
69
|
try:
|
|
63
|
-
if
|
|
70
|
+
if platform.system() == 'Windows':
|
|
64
71
|
# Windows: Use memory-mapped files
|
|
65
72
|
self._file_handle = mmap.mmap(-1, self.size, tagname=self.name)
|
|
66
73
|
self._mmap = self._file_handle
|
|
@@ -82,6 +89,15 @@ class SharedData[T]:
|
|
|
82
89
|
|
|
83
90
|
# Initialize with empty data marker
|
|
84
91
|
self._write_header(0, 0) # length=0, checksum=0
|
|
92
|
+
|
|
93
|
+
# Register segment in global registry for cross-platform attachment
|
|
94
|
+
with _registry_lock:
|
|
95
|
+
_shared_memory_registry[self.name] = {
|
|
96
|
+
'size': self.size,
|
|
97
|
+
'file_path': getattr(self._file_handle, 'name', None) if hasattr(self._file_handle, 'name') else None,
|
|
98
|
+
'platform': platform.system()
|
|
99
|
+
}
|
|
100
|
+
|
|
85
101
|
logger.info(f"Created shared memory segment '{self.name}' ({self.size} bytes)")
|
|
86
102
|
|
|
87
103
|
except Exception as e:
|
|
@@ -91,15 +107,48 @@ class SharedData[T]:
|
|
|
91
107
|
def _attach_segment(self):
|
|
92
108
|
"""Attach to an existing shared memory segment."""
|
|
93
109
|
try:
|
|
94
|
-
|
|
110
|
+
# Check registry first (cross-platform approach)
|
|
111
|
+
with _registry_lock:
|
|
112
|
+
if self.name not in _shared_memory_registry:
|
|
113
|
+
raise ValueError(f"Shared memory segment '{self.name}' not found in registry")
|
|
114
|
+
|
|
115
|
+
segment_info = _shared_memory_registry[self.name]
|
|
116
|
+
registered_size = segment_info['size']
|
|
117
|
+
file_path = segment_info.get('file_path')
|
|
118
|
+
|
|
119
|
+
# Use registered size if available
|
|
120
|
+
if registered_size:
|
|
121
|
+
self.size = registered_size
|
|
122
|
+
|
|
123
|
+
if platform.system() == 'Windows':
|
|
124
|
+
# Windows: Use memory-mapped files with tag
|
|
95
125
|
self._file_handle = mmap.mmap(-1, self.size, tagname=self.name)
|
|
96
126
|
self._mmap = self._file_handle
|
|
97
127
|
else:
|
|
98
|
-
#
|
|
99
|
-
#
|
|
100
|
-
|
|
128
|
+
# Unix: Use same approach as Windows - temp file with registry
|
|
129
|
+
# This ensures exact same capabilities on both platforms
|
|
130
|
+
import tempfile
|
|
131
|
+
if file_path and os.path.exists(file_path):
|
|
132
|
+
# Use existing file from registry
|
|
133
|
+
self._file_handle = open(file_path, 'r+b')
|
|
134
|
+
else:
|
|
135
|
+
# Fallback: create new temp file with same name pattern
|
|
136
|
+
# This matches Windows behavior for cross-platform parity
|
|
137
|
+
self._file_handle = tempfile.NamedTemporaryFile(
|
|
138
|
+
prefix=f"xwsystem_shared_{self.name}_",
|
|
139
|
+
delete=False
|
|
140
|
+
)
|
|
141
|
+
# Ensure file is correct size
|
|
142
|
+
self._file_handle.write(b'\x00' * self.size)
|
|
143
|
+
self._file_handle.flush()
|
|
144
|
+
|
|
145
|
+
self._mmap = mmap.mmap(
|
|
146
|
+
self._file_handle.fileno(),
|
|
147
|
+
self.size,
|
|
148
|
+
access=mmap.ACCESS_WRITE
|
|
149
|
+
)
|
|
101
150
|
|
|
102
|
-
logger.info(f"Attached to shared memory segment '{self.name}'")
|
|
151
|
+
logger.info(f"Attached to shared memory segment '{self.name}' ({self.size} bytes)")
|
|
103
152
|
|
|
104
153
|
except Exception as e:
|
|
105
154
|
logger.error(f"Failed to attach to shared memory segment '{self.name}': {e}")
|
|
@@ -216,6 +265,10 @@ class SharedData[T]:
|
|
|
216
265
|
self._file_handle.close()
|
|
217
266
|
self._file_handle = None
|
|
218
267
|
|
|
268
|
+
# Unregister from global registry
|
|
269
|
+
with _registry_lock:
|
|
270
|
+
_shared_memory_registry.pop(self.name, None)
|
|
271
|
+
|
|
219
272
|
logger.debug(f"Closed shared memory '{self.name}'")
|
|
220
273
|
|
|
221
274
|
except Exception as e:
|
|
@@ -351,7 +404,7 @@ def shared_data(name: str, size: int = 1024 * 1024):
|
|
|
351
404
|
|
|
352
405
|
class SharedMemory:
|
|
353
406
|
"""
|
|
354
|
-
Simple shared memory interface
|
|
407
|
+
Simple shared memory interface.
|
|
355
408
|
|
|
356
409
|
Provides a simplified interface to shared memory functionality.
|
|
357
410
|
"""
|
|
@@ -404,7 +457,7 @@ class SharedMemory:
|
|
|
404
457
|
Detach from the shared memory segment.
|
|
405
458
|
|
|
406
459
|
Args:
|
|
407
|
-
handle: Optional handle to detach
|
|
460
|
+
handle: Optional handle to detach
|
|
408
461
|
|
|
409
462
|
Returns:
|
|
410
463
|
True if successful
|
|
@@ -433,7 +486,7 @@ class SharedMemory:
|
|
|
433
486
|
Destroy the shared memory segment (alias for close method).
|
|
434
487
|
|
|
435
488
|
Args:
|
|
436
|
-
name: Optional name parameter
|
|
489
|
+
name: Optional name parameter
|
|
437
490
|
|
|
438
491
|
Returns:
|
|
439
492
|
True if successful
|
|
@@ -443,6 +496,6 @@ class SharedMemory:
|
|
|
443
496
|
|
|
444
497
|
def is_shared_memory_available() -> bool:
|
|
445
498
|
"""Check if shared memory functionality is available."""
|
|
446
|
-
# mmap is a built-in Python module
|
|
499
|
+
# mmap is a built-in Python module
|
|
447
500
|
import mmap
|
|
448
501
|
return True
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
#exonware/xwsystem/src/exonware/xwsystem/monitoring/__init__.py
|
|
1
2
|
"""
|
|
2
3
|
XSystem Monitoring Package
|
|
3
4
|
|
|
@@ -147,4 +148,10 @@ __all__ = [
|
|
|
147
148
|
"GenericPerformanceManager",
|
|
148
149
|
"PerformanceRecommendation",
|
|
149
150
|
"HealthStatus",
|
|
151
|
+
|
|
152
|
+
# Unified Facade
|
|
153
|
+
"XWMonitor",
|
|
150
154
|
]
|
|
155
|
+
|
|
156
|
+
# Import unified facade
|
|
157
|
+
from .facade import XWMonitor
|
|
@@ -1,16 +1,19 @@
|
|
|
1
|
+
#exonware/xwsystem/src/exonware/xwsystem/monitoring/base.py
|
|
1
2
|
#exonware/xwsystem/monitoring/base.py
|
|
2
3
|
"""
|
|
3
4
|
Company: eXonware.com
|
|
4
5
|
Author: Eng. Muhammad AlShehri
|
|
5
6
|
Email: connect@exonware.com
|
|
6
|
-
Version: 0.1.0.
|
|
7
|
+
Version: 0.1.0.4
|
|
7
8
|
Generation Date: September 04, 2025
|
|
8
9
|
|
|
9
10
|
Monitoring module base classes - abstract classes for monitoring functionality.
|
|
10
11
|
"""
|
|
11
12
|
|
|
13
|
+
from __future__ import annotations
|
|
14
|
+
|
|
12
15
|
from abc import ABC, abstractmethod
|
|
13
|
-
from typing import Any, Optional,
|
|
16
|
+
from typing import Any, Optional, Callable, TYPE_CHECKING
|
|
14
17
|
from .defs import MetricType, AlertLevel, HealthStatus, SpanKind
|
|
15
18
|
|
|
16
19
|
if TYPE_CHECKING:
|
|
@@ -320,24 +323,24 @@ class ATracingProvider(ABC):
|
|
|
320
323
|
def start_span(
|
|
321
324
|
self,
|
|
322
325
|
name: str,
|
|
323
|
-
kind:
|
|
324
|
-
parent: Optional[
|
|
326
|
+
kind: SpanKind = None,
|
|
327
|
+
parent: Optional[SpanContext] = None,
|
|
325
328
|
attributes: Optional[dict[str, Any]] = None
|
|
326
|
-
) ->
|
|
329
|
+
) -> SpanContext:
|
|
327
330
|
"""Start a new span."""
|
|
328
331
|
pass
|
|
329
332
|
|
|
330
333
|
@abstractmethod
|
|
331
|
-
def finish_span(self, span:
|
|
334
|
+
def finish_span(self, span: SpanContext, status: str = "OK", error: Optional[Exception] = None) -> None:
|
|
332
335
|
"""Finish a span."""
|
|
333
336
|
pass
|
|
334
337
|
|
|
335
338
|
@abstractmethod
|
|
336
|
-
def add_span_attribute(self, span:
|
|
339
|
+
def add_span_attribute(self, span: SpanContext, key: str, value: Any) -> None:
|
|
337
340
|
"""Add attribute to span."""
|
|
338
341
|
pass
|
|
339
342
|
|
|
340
343
|
@abstractmethod
|
|
341
|
-
def add_span_event(self, span:
|
|
344
|
+
def add_span_event(self, span: SpanContext, name: str, attributes: Optional[dict[str, Any]] = None) -> None:
|
|
342
345
|
"""Add event to span."""
|
|
343
346
|
pass
|