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
|
@@ -1,15 +1,18 @@
|
|
|
1
|
+
#exonware/xwsystem/src/exonware/xwsystem/io/contracts.py
|
|
1
2
|
"""
|
|
2
3
|
Company: eXonware.com
|
|
3
4
|
Author: Eng. Muhammad AlShehri
|
|
4
5
|
Email: connect@exonware.com
|
|
5
|
-
Version: 0.1.0.
|
|
6
|
+
Version: 0.1.0.4
|
|
6
7
|
Generation Date: September 04, 2025
|
|
7
8
|
|
|
8
9
|
IO module contracts - interfaces and enums for input/output operations.
|
|
9
10
|
"""
|
|
10
11
|
|
|
11
|
-
from
|
|
12
|
-
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
from typing import Protocol, runtime_checkable
|
|
15
|
+
from typing import Any, Optional, AsyncGenerator, BinaryIO, TextIO, Protocol, runtime_checkable, Callable, Iterator
|
|
13
16
|
from typing_extensions import TypeAlias
|
|
14
17
|
from pathlib import Path
|
|
15
18
|
|
|
@@ -36,7 +39,8 @@ from .defs import (
|
|
|
36
39
|
# FILE INTERFACES
|
|
37
40
|
# ============================================================================
|
|
38
41
|
|
|
39
|
-
|
|
42
|
+
@runtime_checkable
|
|
43
|
+
class IFile(Protocol):
|
|
40
44
|
"""
|
|
41
45
|
Interface for file operations with both static and instance methods.
|
|
42
46
|
|
|
@@ -51,234 +55,198 @@ class IFile(ABC):
|
|
|
51
55
|
# INSTANCE METHODS
|
|
52
56
|
# ============================================================================
|
|
53
57
|
|
|
54
|
-
@abstractmethod
|
|
55
58
|
def open(self, mode: FileMode = FileMode.READ) -> None:
|
|
56
59
|
"""Open file with specified mode."""
|
|
57
|
-
|
|
60
|
+
...
|
|
58
61
|
|
|
59
|
-
|
|
60
|
-
def read(self, size: Optional[int] = None) -> Union[str, bytes]:
|
|
62
|
+
def read(self, size: Optional[int] = None) -> str | bytes:
|
|
61
63
|
"""Read from file."""
|
|
62
|
-
|
|
64
|
+
...
|
|
63
65
|
|
|
64
|
-
|
|
65
|
-
def write(self, data: Union[str, bytes]) -> int:
|
|
66
|
+
def write(self, data: str | bytes) -> int:
|
|
66
67
|
"""Write to file."""
|
|
67
|
-
|
|
68
|
+
...
|
|
68
69
|
|
|
69
|
-
@abstractmethod
|
|
70
70
|
def close(self) -> None:
|
|
71
71
|
"""Close file."""
|
|
72
|
-
|
|
72
|
+
...
|
|
73
73
|
|
|
74
|
-
@abstractmethod
|
|
75
74
|
def save(self, data: Any, **kwargs) -> bool:
|
|
76
75
|
"""Save data to file."""
|
|
77
|
-
|
|
76
|
+
...
|
|
78
77
|
|
|
79
|
-
@abstractmethod
|
|
80
78
|
def load(self, **kwargs) -> Any:
|
|
81
79
|
"""Load data from file."""
|
|
82
|
-
|
|
80
|
+
...
|
|
83
81
|
|
|
84
|
-
|
|
85
|
-
def save_as(self, path: Union[str, Path], data: Any, **kwargs) -> bool:
|
|
82
|
+
def save_as(self, path: str | Path, data: Any, **kwargs) -> bool:
|
|
86
83
|
"""Save data to specific path."""
|
|
87
|
-
|
|
84
|
+
...
|
|
88
85
|
|
|
89
|
-
|
|
90
|
-
def to_file(self, path: Union[str, Path], **kwargs) -> bool:
|
|
86
|
+
def to_file(self, path: str | Path, **kwargs) -> bool:
|
|
91
87
|
"""Write current object to file."""
|
|
92
|
-
|
|
88
|
+
...
|
|
93
89
|
|
|
94
|
-
|
|
95
|
-
def from_file(self, path: Union[str, Path], **kwargs) -> 'IFile':
|
|
90
|
+
def from_file(self, path: str | Path, **kwargs) -> IFile:
|
|
96
91
|
"""Load object from file."""
|
|
97
|
-
|
|
92
|
+
...
|
|
98
93
|
|
|
99
94
|
# ============================================================================
|
|
100
95
|
# STATIC METHODS
|
|
101
96
|
# ============================================================================
|
|
102
97
|
|
|
103
98
|
@staticmethod
|
|
104
|
-
|
|
105
|
-
def exists(path: Union[str, Path]) -> bool:
|
|
99
|
+
def exists(path: str | Path) -> bool:
|
|
106
100
|
"""Check if file exists."""
|
|
107
|
-
|
|
101
|
+
...
|
|
108
102
|
|
|
109
103
|
@staticmethod
|
|
110
|
-
|
|
111
|
-
def size(path: Union[str, Path]) -> int:
|
|
104
|
+
def size(path: str | Path) -> int:
|
|
112
105
|
"""Get file size."""
|
|
113
|
-
|
|
106
|
+
...
|
|
114
107
|
|
|
115
108
|
@staticmethod
|
|
116
|
-
|
|
117
|
-
def delete(path: Union[str, Path]) -> bool:
|
|
109
|
+
def delete(path: str | Path) -> bool:
|
|
118
110
|
"""Delete file."""
|
|
119
|
-
|
|
111
|
+
...
|
|
120
112
|
|
|
121
113
|
@staticmethod
|
|
122
|
-
|
|
123
|
-
def copy(source: Union[str, Path], destination: Union[str, Path]) -> bool:
|
|
114
|
+
def copy(source: str | Path, destination: str | Path) -> bool:
|
|
124
115
|
"""Copy file."""
|
|
125
|
-
|
|
116
|
+
...
|
|
126
117
|
|
|
127
118
|
@staticmethod
|
|
128
|
-
|
|
129
|
-
def move(source: Union[str, Path], destination: Union[str, Path]) -> bool:
|
|
119
|
+
def move(source: str | Path, destination: str | Path) -> bool:
|
|
130
120
|
"""Move file."""
|
|
131
|
-
|
|
121
|
+
...
|
|
132
122
|
|
|
133
123
|
@staticmethod
|
|
134
|
-
|
|
135
|
-
def rename(old_path: Union[str, Path], new_path: Union[str, Path]) -> bool:
|
|
124
|
+
def rename(old_path: str | Path, new_path: str | Path) -> bool:
|
|
136
125
|
"""Rename file."""
|
|
137
|
-
|
|
126
|
+
...
|
|
138
127
|
|
|
139
128
|
@staticmethod
|
|
140
|
-
|
|
141
|
-
def get_modified_time(path: Union[str, Path]) -> float:
|
|
129
|
+
def get_modified_time(path: str | Path) -> float:
|
|
142
130
|
"""Get file modification time."""
|
|
143
|
-
|
|
131
|
+
...
|
|
144
132
|
|
|
145
133
|
@staticmethod
|
|
146
|
-
|
|
147
|
-
def get_created_time(path: Union[str, Path]) -> float:
|
|
134
|
+
def get_created_time(path: str | Path) -> float:
|
|
148
135
|
"""Get file creation time."""
|
|
149
|
-
|
|
136
|
+
...
|
|
150
137
|
|
|
151
138
|
@staticmethod
|
|
152
|
-
|
|
153
|
-
def get_permissions(path: Union[str, Path]) -> int:
|
|
139
|
+
def get_permissions(path: str | Path) -> int:
|
|
154
140
|
"""Get file permissions."""
|
|
155
|
-
|
|
141
|
+
...
|
|
156
142
|
|
|
157
143
|
@staticmethod
|
|
158
|
-
|
|
159
|
-
def is_readable(path: Union[str, Path]) -> bool:
|
|
144
|
+
def is_readable(path: str | Path) -> bool:
|
|
160
145
|
"""Check if file is readable."""
|
|
161
|
-
|
|
146
|
+
...
|
|
162
147
|
|
|
163
148
|
@staticmethod
|
|
164
|
-
|
|
165
|
-
def is_writable(path: Union[str, Path]) -> bool:
|
|
149
|
+
def is_writable(path: str | Path) -> bool:
|
|
166
150
|
"""Check if file is writable."""
|
|
167
|
-
|
|
151
|
+
...
|
|
168
152
|
|
|
169
153
|
@staticmethod
|
|
170
|
-
|
|
171
|
-
def is_executable(path: Union[str, Path]) -> bool:
|
|
154
|
+
def is_executable(path: str | Path) -> bool:
|
|
172
155
|
"""Check if file is executable."""
|
|
173
|
-
|
|
156
|
+
...
|
|
174
157
|
|
|
175
158
|
@staticmethod
|
|
176
|
-
|
|
177
|
-
def read_text(path: Union[str, Path], encoding: str = 'utf-8') -> str:
|
|
159
|
+
def read_text(path: str | Path, encoding: str = 'utf-8') -> str:
|
|
178
160
|
"""Read file as text."""
|
|
179
|
-
|
|
161
|
+
...
|
|
180
162
|
|
|
181
163
|
@staticmethod
|
|
182
|
-
|
|
183
|
-
def read_bytes(path: Union[str, Path]) -> bytes:
|
|
164
|
+
def read_bytes(path: str | Path) -> bytes:
|
|
184
165
|
"""Read file as bytes."""
|
|
185
|
-
|
|
166
|
+
...
|
|
186
167
|
|
|
187
168
|
@staticmethod
|
|
188
|
-
|
|
189
|
-
def write_text(path: Union[str, Path], content: str, encoding: str = 'utf-8') -> bool:
|
|
169
|
+
def write_text(path: str | Path, content: str, encoding: str = 'utf-8') -> bool:
|
|
190
170
|
"""Write text to file."""
|
|
191
|
-
|
|
171
|
+
...
|
|
192
172
|
|
|
193
173
|
@staticmethod
|
|
194
|
-
|
|
195
|
-
def write_bytes(path: Union[str, Path], content: bytes) -> bool:
|
|
174
|
+
def write_bytes(path: str | Path, content: bytes) -> bool:
|
|
196
175
|
"""Write bytes to file."""
|
|
197
|
-
|
|
176
|
+
...
|
|
198
177
|
|
|
199
178
|
@staticmethod
|
|
200
|
-
|
|
201
|
-
def safe_read_text(path: Union[str, Path], encoding: str = 'utf-8') -> Optional[str]:
|
|
179
|
+
def safe_read_text(path: str | Path, encoding: str = 'utf-8') -> Optional[str]:
|
|
202
180
|
"""Safely read text file, returning None on error."""
|
|
203
|
-
|
|
181
|
+
...
|
|
204
182
|
|
|
205
183
|
@staticmethod
|
|
206
|
-
|
|
207
|
-
def safe_read_bytes(path: Union[str, Path]) -> Optional[bytes]:
|
|
184
|
+
def safe_read_bytes(path: str | Path) -> Optional[bytes]:
|
|
208
185
|
"""Safely read binary file, returning None on error."""
|
|
209
|
-
|
|
186
|
+
...
|
|
210
187
|
|
|
211
188
|
@staticmethod
|
|
212
|
-
|
|
213
|
-
def safe_write_text(path: Union[str, Path], content: str, encoding: str = 'utf-8') -> bool:
|
|
189
|
+
def safe_write_text(path: str | Path, content: str, encoding: str = 'utf-8') -> bool:
|
|
214
190
|
"""Safely write text to file."""
|
|
215
|
-
|
|
191
|
+
...
|
|
216
192
|
|
|
217
193
|
@staticmethod
|
|
218
|
-
|
|
219
|
-
def safe_write_bytes(path: Union[str, Path], content: bytes) -> bool:
|
|
194
|
+
def safe_write_bytes(path: str | Path, content: bytes) -> bool:
|
|
220
195
|
"""Safely write bytes to file."""
|
|
221
|
-
|
|
196
|
+
...
|
|
222
197
|
|
|
223
198
|
# ============================================================================
|
|
224
199
|
# STATIC UTILITY METHODS (File Manager Features)
|
|
225
200
|
# ============================================================================
|
|
226
201
|
|
|
227
202
|
@staticmethod
|
|
228
|
-
|
|
229
|
-
def atomic_write(file_path: Union[str, Path], data: Union[str, bytes],
|
|
203
|
+
def atomic_write(file_path: str | Path, data: str | bytes,
|
|
230
204
|
backup: bool = True) -> OperationResult:
|
|
231
205
|
"""Atomically write data to file (static version)."""
|
|
232
|
-
|
|
206
|
+
...
|
|
233
207
|
|
|
234
208
|
@staticmethod
|
|
235
|
-
|
|
236
|
-
def atomic_copy(source: Union[str, Path], destination: Union[str, Path]) -> OperationResult:
|
|
209
|
+
def atomic_copy(source: str | Path, destination: str | Path) -> OperationResult:
|
|
237
210
|
"""Atomically copy file (static version)."""
|
|
238
|
-
|
|
211
|
+
...
|
|
239
212
|
|
|
240
213
|
@staticmethod
|
|
241
|
-
|
|
242
|
-
def atomic_move(source: Union[str, Path], destination: Union[str, Path]) -> OperationResult:
|
|
214
|
+
def atomic_move(source: str | Path, destination: str | Path) -> OperationResult:
|
|
243
215
|
"""Atomically move file (static version)."""
|
|
244
|
-
|
|
216
|
+
...
|
|
245
217
|
|
|
246
218
|
@staticmethod
|
|
247
|
-
|
|
248
|
-
def atomic_delete(file_path: Union[str, Path], backup: bool = True) -> OperationResult:
|
|
219
|
+
def atomic_delete(file_path: str | Path, backup: bool = True) -> OperationResult:
|
|
249
220
|
"""Atomically delete file (static version)."""
|
|
250
|
-
|
|
221
|
+
...
|
|
251
222
|
|
|
252
223
|
@staticmethod
|
|
253
|
-
|
|
254
|
-
def create_backup(source: Union[str, Path], backup_dir: Union[str, Path]) -> Optional[Path]:
|
|
224
|
+
def create_backup(source: str | Path, backup_dir: str | Path) -> Optional[Path]:
|
|
255
225
|
"""Create backup of file (static version)."""
|
|
256
|
-
|
|
226
|
+
...
|
|
257
227
|
|
|
258
228
|
@staticmethod
|
|
259
|
-
|
|
260
|
-
def restore_backup(backup_path: Union[str, Path], target: Union[str, Path]) -> OperationResult:
|
|
229
|
+
def restore_backup(backup_path: str | Path, target: str | Path) -> OperationResult:
|
|
261
230
|
"""Restore from backup (static version)."""
|
|
262
|
-
|
|
231
|
+
...
|
|
263
232
|
|
|
264
233
|
@staticmethod
|
|
265
|
-
@abstractmethod
|
|
266
234
|
def create_temp_file(suffix: Optional[str] = None, prefix: Optional[str] = None) -> Path:
|
|
267
235
|
"""Create temporary file (static version)."""
|
|
268
|
-
|
|
236
|
+
...
|
|
269
237
|
|
|
270
238
|
@staticmethod
|
|
271
|
-
@abstractmethod
|
|
272
239
|
def create_temp_directory(suffix: Optional[str] = None, prefix: Optional[str] = None) -> Path:
|
|
273
240
|
"""Create temporary directory (static version)."""
|
|
274
|
-
|
|
241
|
+
...
|
|
275
242
|
|
|
276
243
|
|
|
277
244
|
# ============================================================================
|
|
278
245
|
# FOLDER INTERFACES
|
|
279
246
|
# ============================================================================
|
|
280
247
|
|
|
281
|
-
|
|
248
|
+
@runtime_checkable
|
|
249
|
+
class IFolder(Protocol):
|
|
282
250
|
"""
|
|
283
251
|
Interface for folder/directory operations with both static and instance methods.
|
|
284
252
|
|
|
@@ -293,145 +261,123 @@ class IFolder(ABC):
|
|
|
293
261
|
# INSTANCE METHODS
|
|
294
262
|
# ============================================================================
|
|
295
263
|
|
|
296
|
-
@abstractmethod
|
|
297
264
|
def create(self, parents: bool = True, exist_ok: bool = True) -> bool:
|
|
298
265
|
"""Create directory."""
|
|
299
|
-
|
|
266
|
+
...
|
|
300
267
|
|
|
301
|
-
@abstractmethod
|
|
302
268
|
def delete(self, recursive: bool = False) -> bool:
|
|
303
269
|
"""Delete directory."""
|
|
304
|
-
|
|
270
|
+
...
|
|
305
271
|
|
|
306
|
-
@abstractmethod
|
|
307
272
|
def list_files(self, pattern: Optional[str] = None, recursive: bool = False) -> list[Path]:
|
|
308
273
|
"""List files in directory."""
|
|
309
|
-
|
|
274
|
+
...
|
|
310
275
|
|
|
311
|
-
@abstractmethod
|
|
312
276
|
def list_directories(self, recursive: bool = False) -> list[Path]:
|
|
313
277
|
"""List subdirectories."""
|
|
314
|
-
|
|
278
|
+
...
|
|
315
279
|
|
|
316
|
-
@abstractmethod
|
|
317
280
|
def walk(self) -> list[tuple[Path, list[str], list[str]]]:
|
|
318
281
|
"""Walk directory tree."""
|
|
319
|
-
|
|
282
|
+
...
|
|
320
283
|
|
|
321
|
-
@abstractmethod
|
|
322
284
|
def get_size(self) -> int:
|
|
323
285
|
"""Get directory size."""
|
|
324
|
-
|
|
286
|
+
...
|
|
325
287
|
|
|
326
|
-
@abstractmethod
|
|
327
288
|
def is_empty(self) -> bool:
|
|
328
289
|
"""Check if directory is empty."""
|
|
329
|
-
|
|
290
|
+
...
|
|
330
291
|
|
|
331
|
-
|
|
332
|
-
def copy_to(self, destination: Union[str, Path]) -> bool:
|
|
292
|
+
def copy_to(self, destination: str | Path) -> bool:
|
|
333
293
|
"""Copy directory to destination."""
|
|
334
|
-
|
|
294
|
+
...
|
|
335
295
|
|
|
336
|
-
|
|
337
|
-
def move_to(self, destination: Union[str, Path]) -> bool:
|
|
296
|
+
def move_to(self, destination: str | Path) -> bool:
|
|
338
297
|
"""Move directory to destination."""
|
|
339
|
-
|
|
298
|
+
...
|
|
340
299
|
|
|
341
300
|
# ============================================================================
|
|
342
301
|
# STATIC METHODS
|
|
343
302
|
# ============================================================================
|
|
344
303
|
|
|
345
304
|
@staticmethod
|
|
346
|
-
|
|
347
|
-
def exists(path: Union[str, Path]) -> bool:
|
|
305
|
+
def exists(path: str | Path) -> bool:
|
|
348
306
|
"""Check if directory exists."""
|
|
349
|
-
|
|
307
|
+
...
|
|
350
308
|
|
|
351
309
|
@staticmethod
|
|
352
|
-
|
|
353
|
-
def create_dir(path: Union[str, Path], parents: bool = True, exist_ok: bool = True) -> bool:
|
|
310
|
+
def create_dir(path: str | Path, parents: bool = True, exist_ok: bool = True) -> bool:
|
|
354
311
|
"""Create directory."""
|
|
355
|
-
|
|
312
|
+
...
|
|
356
313
|
|
|
357
314
|
@staticmethod
|
|
358
|
-
|
|
359
|
-
def delete_dir(path: Union[str, Path], recursive: bool = False) -> bool:
|
|
315
|
+
def delete_dir(path: str | Path, recursive: bool = False) -> bool:
|
|
360
316
|
"""Delete directory."""
|
|
361
|
-
|
|
317
|
+
...
|
|
362
318
|
|
|
363
319
|
@staticmethod
|
|
364
|
-
|
|
365
|
-
def list_files_static(path: Union[str, Path], pattern: Optional[str] = None, recursive: bool = False) -> list[Path]:
|
|
320
|
+
def list_files_static(path: str | Path, pattern: Optional[str] = None, recursive: bool = False) -> list[Path]:
|
|
366
321
|
"""List files in directory."""
|
|
367
|
-
|
|
322
|
+
...
|
|
368
323
|
|
|
369
324
|
@staticmethod
|
|
370
|
-
|
|
371
|
-
def list_directories_static(path: Union[str, Path], recursive: bool = False) -> list[Path]:
|
|
325
|
+
def list_directories_static(path: str | Path, recursive: bool = False) -> list[Path]:
|
|
372
326
|
"""List subdirectories."""
|
|
373
|
-
|
|
327
|
+
...
|
|
374
328
|
|
|
375
329
|
@staticmethod
|
|
376
|
-
|
|
377
|
-
def walk_static(path: Union[str, Path]) -> list[tuple[Path, list[str], list[str]]]:
|
|
330
|
+
def walk_static(path: str | Path) -> list[tuple[Path, list[str], list[str]]]:
|
|
378
331
|
"""Walk directory tree."""
|
|
379
|
-
|
|
332
|
+
...
|
|
380
333
|
|
|
381
334
|
@staticmethod
|
|
382
|
-
|
|
383
|
-
def get_size_static(path: Union[str, Path]) -> int:
|
|
335
|
+
def get_size_static(path: str | Path) -> int:
|
|
384
336
|
"""Get directory size."""
|
|
385
|
-
|
|
337
|
+
...
|
|
386
338
|
|
|
387
339
|
@staticmethod
|
|
388
|
-
|
|
389
|
-
def is_empty_static(path: Union[str, Path]) -> bool:
|
|
340
|
+
def is_empty_static(path: str | Path) -> bool:
|
|
390
341
|
"""Check if directory is empty."""
|
|
391
|
-
|
|
342
|
+
...
|
|
392
343
|
|
|
393
344
|
@staticmethod
|
|
394
|
-
|
|
395
|
-
def copy_dir(source: Union[str, Path], destination: Union[str, Path]) -> bool:
|
|
345
|
+
def copy_dir(source: str | Path, destination: str | Path) -> bool:
|
|
396
346
|
"""Copy directory."""
|
|
397
|
-
|
|
347
|
+
...
|
|
398
348
|
|
|
399
349
|
@staticmethod
|
|
400
|
-
|
|
401
|
-
def move_dir(source: Union[str, Path], destination: Union[str, Path]) -> bool:
|
|
350
|
+
def move_dir(source: str | Path, destination: str | Path) -> bool:
|
|
402
351
|
"""Move directory."""
|
|
403
|
-
|
|
352
|
+
...
|
|
404
353
|
|
|
405
354
|
@staticmethod
|
|
406
|
-
|
|
407
|
-
def get_permissions(path: Union[str, Path]) -> int:
|
|
355
|
+
def get_permissions(path: str | Path) -> int:
|
|
408
356
|
"""Get directory permissions."""
|
|
409
|
-
|
|
357
|
+
...
|
|
410
358
|
|
|
411
359
|
@staticmethod
|
|
412
|
-
|
|
413
|
-
def is_readable(path: Union[str, Path]) -> bool:
|
|
360
|
+
def is_readable(path: str | Path) -> bool:
|
|
414
361
|
"""Check if directory is readable."""
|
|
415
|
-
|
|
362
|
+
...
|
|
416
363
|
|
|
417
364
|
@staticmethod
|
|
418
|
-
|
|
419
|
-
def is_writable(path: Union[str, Path]) -> bool:
|
|
365
|
+
def is_writable(path: str | Path) -> bool:
|
|
420
366
|
"""Check if directory is writable."""
|
|
421
|
-
|
|
367
|
+
...
|
|
422
368
|
|
|
423
369
|
@staticmethod
|
|
424
|
-
|
|
425
|
-
def is_executable(path: Union[str, Path]) -> bool:
|
|
370
|
+
def is_executable(path: str | Path) -> bool:
|
|
426
371
|
"""Check if directory is executable."""
|
|
427
|
-
|
|
372
|
+
...
|
|
428
373
|
|
|
429
374
|
|
|
430
375
|
# ============================================================================
|
|
431
376
|
# PATH INTERFACES
|
|
432
377
|
# ============================================================================
|
|
433
378
|
|
|
434
|
-
|
|
379
|
+
@runtime_checkable
|
|
380
|
+
class IPath(Protocol):
|
|
435
381
|
"""
|
|
436
382
|
Interface for path operations with both static and instance methods.
|
|
437
383
|
|
|
@@ -446,107 +392,92 @@ class IPath(ABC):
|
|
|
446
392
|
# ============================================================================
|
|
447
393
|
|
|
448
394
|
@staticmethod
|
|
449
|
-
|
|
450
|
-
def normalize(path: Union[str, Path]) -> Path:
|
|
395
|
+
def normalize(path: str | Path) -> Path:
|
|
451
396
|
"""Normalize path."""
|
|
452
|
-
|
|
397
|
+
...
|
|
453
398
|
|
|
454
399
|
@staticmethod
|
|
455
|
-
|
|
456
|
-
def resolve(path: Union[str, Path]) -> Path:
|
|
400
|
+
def resolve(path: str | Path) -> Path:
|
|
457
401
|
"""Resolve path."""
|
|
458
|
-
|
|
402
|
+
...
|
|
459
403
|
|
|
460
404
|
@staticmethod
|
|
461
|
-
|
|
462
|
-
def absolute(path: Union[str, Path]) -> Path:
|
|
405
|
+
def absolute(path: str | Path) -> Path:
|
|
463
406
|
"""Get absolute path."""
|
|
464
|
-
|
|
407
|
+
...
|
|
465
408
|
|
|
466
409
|
@staticmethod
|
|
467
|
-
|
|
468
|
-
def relative(path: Union[str, Path], start: Optional[Union[str, Path]] = None) -> Path:
|
|
410
|
+
def relative(path: str | Path, start: Optional[str | Path] = None) -> Path:
|
|
469
411
|
"""Get relative path."""
|
|
470
|
-
|
|
412
|
+
...
|
|
471
413
|
|
|
472
414
|
@staticmethod
|
|
473
|
-
|
|
474
|
-
def join(*paths: Union[str, Path]) -> Path:
|
|
415
|
+
def join(*paths: str | Path) -> Path:
|
|
475
416
|
"""Join paths."""
|
|
476
|
-
|
|
417
|
+
...
|
|
477
418
|
|
|
478
419
|
@staticmethod
|
|
479
|
-
|
|
480
|
-
def split(path: Union[str, Path]) -> tuple[Path, str]:
|
|
420
|
+
def split(path: str | Path) -> tuple[Path, str]:
|
|
481
421
|
"""Split path into directory and filename."""
|
|
482
|
-
|
|
422
|
+
...
|
|
483
423
|
|
|
484
424
|
@staticmethod
|
|
485
|
-
|
|
486
|
-
def get_extension(path: Union[str, Path]) -> str:
|
|
425
|
+
def get_extension(path: str | Path) -> str:
|
|
487
426
|
"""Get file extension."""
|
|
488
|
-
|
|
427
|
+
...
|
|
489
428
|
|
|
490
429
|
@staticmethod
|
|
491
|
-
|
|
492
|
-
def get_stem(path: Union[str, Path]) -> str:
|
|
430
|
+
def get_stem(path: str | Path) -> str:
|
|
493
431
|
"""Get file stem (name without extension)."""
|
|
494
|
-
|
|
432
|
+
...
|
|
495
433
|
|
|
496
434
|
@staticmethod
|
|
497
|
-
|
|
498
|
-
def get_name(path: Union[str, Path]) -> str:
|
|
435
|
+
def get_name(path: str | Path) -> str:
|
|
499
436
|
"""Get file/directory name."""
|
|
500
|
-
|
|
437
|
+
...
|
|
501
438
|
|
|
502
439
|
@staticmethod
|
|
503
|
-
|
|
504
|
-
def get_parent(path: Union[str, Path]) -> Path:
|
|
440
|
+
def get_parent(path: str | Path) -> Path:
|
|
505
441
|
"""Get parent directory."""
|
|
506
|
-
|
|
442
|
+
...
|
|
507
443
|
|
|
508
444
|
@staticmethod
|
|
509
|
-
|
|
510
|
-
def is_absolute(path: Union[str, Path]) -> bool:
|
|
445
|
+
def is_absolute(path: str | Path) -> bool:
|
|
511
446
|
"""Check if path is absolute."""
|
|
512
|
-
|
|
447
|
+
...
|
|
513
448
|
|
|
514
449
|
@staticmethod
|
|
515
|
-
|
|
516
|
-
def is_relative(path: Union[str, Path]) -> bool:
|
|
450
|
+
def is_relative(path: str | Path) -> bool:
|
|
517
451
|
"""Check if path is relative."""
|
|
518
|
-
|
|
452
|
+
...
|
|
519
453
|
|
|
520
454
|
@staticmethod
|
|
521
|
-
|
|
522
|
-
def get_parts(path: Union[str, Path]) -> tuple:
|
|
455
|
+
def get_parts(path: str | Path) -> tuple:
|
|
523
456
|
"""Get path parts."""
|
|
524
|
-
|
|
457
|
+
...
|
|
525
458
|
|
|
526
459
|
@staticmethod
|
|
527
|
-
|
|
528
|
-
def match(path: Union[str, Path], pattern: str) -> bool:
|
|
460
|
+
def match(path: str | Path, pattern: str) -> bool:
|
|
529
461
|
"""Check if path matches pattern."""
|
|
530
|
-
|
|
462
|
+
...
|
|
531
463
|
|
|
532
464
|
@staticmethod
|
|
533
|
-
|
|
534
|
-
def with_suffix(path: Union[str, Path], suffix: str) -> Path:
|
|
465
|
+
def with_suffix(path: str | Path, suffix: str) -> Path:
|
|
535
466
|
"""Get path with new suffix."""
|
|
536
|
-
|
|
467
|
+
...
|
|
537
468
|
|
|
538
469
|
@staticmethod
|
|
539
|
-
|
|
540
|
-
def with_name(path: Union[str, Path], name: str) -> Path:
|
|
470
|
+
def with_name(path: str | Path, name: str) -> Path:
|
|
541
471
|
"""Get path with new name."""
|
|
542
|
-
|
|
472
|
+
...
|
|
543
473
|
|
|
544
474
|
|
|
545
475
|
# ============================================================================
|
|
546
476
|
# STREAM INTERFACES
|
|
547
477
|
# ============================================================================
|
|
548
478
|
|
|
549
|
-
|
|
479
|
+
@runtime_checkable
|
|
480
|
+
class IStream(Protocol):
|
|
550
481
|
"""
|
|
551
482
|
Interface for stream operations with both static and instance methods.
|
|
552
483
|
|
|
@@ -560,76 +491,66 @@ class IStream(ABC):
|
|
|
560
491
|
# INSTANCE METHODS
|
|
561
492
|
# ============================================================================
|
|
562
493
|
|
|
563
|
-
|
|
564
|
-
def read(self, size: Optional[int] = None) -> Union[str, bytes]:
|
|
494
|
+
def read(self, size: Optional[int] = None) -> str | bytes:
|
|
565
495
|
"""Read from stream."""
|
|
566
|
-
|
|
496
|
+
...
|
|
567
497
|
|
|
568
|
-
|
|
569
|
-
def write(self, data: Union[str, bytes]) -> int:
|
|
498
|
+
def write(self, data: str | bytes) -> int:
|
|
570
499
|
"""Write to stream."""
|
|
571
|
-
|
|
500
|
+
...
|
|
572
501
|
|
|
573
|
-
@abstractmethod
|
|
574
502
|
def seek(self, position: int, whence: int = 0) -> int:
|
|
575
503
|
"""Seek stream position."""
|
|
576
|
-
|
|
504
|
+
...
|
|
577
505
|
|
|
578
|
-
@abstractmethod
|
|
579
506
|
def tell(self) -> int:
|
|
580
507
|
"""Get current stream position."""
|
|
581
|
-
|
|
508
|
+
...
|
|
582
509
|
|
|
583
|
-
@abstractmethod
|
|
584
510
|
def flush(self) -> None:
|
|
585
511
|
"""Flush stream buffer."""
|
|
586
|
-
|
|
512
|
+
...
|
|
587
513
|
|
|
588
|
-
@abstractmethod
|
|
589
514
|
def close(self) -> None:
|
|
590
515
|
"""Close stream."""
|
|
591
|
-
|
|
516
|
+
...
|
|
592
517
|
|
|
593
518
|
# ============================================================================
|
|
594
519
|
# STATIC METHODS
|
|
595
520
|
# ============================================================================
|
|
596
521
|
|
|
597
522
|
@staticmethod
|
|
598
|
-
|
|
599
|
-
def open_file(path: Union[str, Path], mode: str = 'r', encoding: Optional[str] = None) -> Union[TextIO, BinaryIO]:
|
|
523
|
+
def open_file(path: str | Path, mode: str = 'r', encoding: Optional[str] = None) -> TextIO | BinaryIO:
|
|
600
524
|
"""Open file as stream."""
|
|
601
|
-
|
|
525
|
+
...
|
|
602
526
|
|
|
603
527
|
@staticmethod
|
|
604
|
-
|
|
605
|
-
def is_closed(stream: Union[TextIO, BinaryIO]) -> bool:
|
|
528
|
+
def is_closed(stream: TextIO | BinaryIO) -> bool:
|
|
606
529
|
"""Check if stream is closed."""
|
|
607
|
-
|
|
530
|
+
...
|
|
608
531
|
|
|
609
532
|
@staticmethod
|
|
610
|
-
|
|
611
|
-
def readable(stream: Union[TextIO, BinaryIO]) -> bool:
|
|
533
|
+
def readable(stream: TextIO | BinaryIO) -> bool:
|
|
612
534
|
"""Check if stream is readable."""
|
|
613
|
-
|
|
535
|
+
...
|
|
614
536
|
|
|
615
537
|
@staticmethod
|
|
616
|
-
|
|
617
|
-
def writable(stream: Union[TextIO, BinaryIO]) -> bool:
|
|
538
|
+
def writable(stream: TextIO | BinaryIO) -> bool:
|
|
618
539
|
"""Check if stream is writable."""
|
|
619
|
-
|
|
540
|
+
...
|
|
620
541
|
|
|
621
542
|
@staticmethod
|
|
622
|
-
|
|
623
|
-
def seekable(stream: Union[TextIO, BinaryIO]) -> bool:
|
|
543
|
+
def seekable(stream: TextIO | BinaryIO) -> bool:
|
|
624
544
|
"""Check if stream is seekable."""
|
|
625
|
-
|
|
545
|
+
...
|
|
626
546
|
|
|
627
547
|
|
|
628
548
|
# ============================================================================
|
|
629
549
|
# ASYNC I/O INTERFACES
|
|
630
550
|
# ============================================================================
|
|
631
551
|
|
|
632
|
-
|
|
552
|
+
@runtime_checkable
|
|
553
|
+
class IAsyncIO(Protocol):
|
|
633
554
|
"""
|
|
634
555
|
Interface for async I/O operations with both static and instance methods.
|
|
635
556
|
|
|
@@ -643,76 +564,66 @@ class IAsyncIO(ABC):
|
|
|
643
564
|
# INSTANCE METHODS
|
|
644
565
|
# ============================================================================
|
|
645
566
|
|
|
646
|
-
|
|
647
|
-
async def aread(self, size: Optional[int] = None) -> Union[str, bytes]:
|
|
567
|
+
async def aread(self, size: Optional[int] = None) -> str | bytes:
|
|
648
568
|
"""Async read operation."""
|
|
649
|
-
|
|
569
|
+
...
|
|
650
570
|
|
|
651
|
-
|
|
652
|
-
async def awrite(self, data: Union[str, bytes]) -> int:
|
|
571
|
+
async def awrite(self, data: str | bytes) -> int:
|
|
653
572
|
"""Async write operation."""
|
|
654
|
-
|
|
573
|
+
...
|
|
655
574
|
|
|
656
|
-
@abstractmethod
|
|
657
575
|
async def aseek(self, position: int, whence: int = 0) -> int:
|
|
658
576
|
"""Async seek operation."""
|
|
659
|
-
|
|
577
|
+
...
|
|
660
578
|
|
|
661
|
-
@abstractmethod
|
|
662
579
|
async def atell(self) -> int:
|
|
663
580
|
"""Async tell operation."""
|
|
664
|
-
|
|
581
|
+
...
|
|
665
582
|
|
|
666
|
-
@abstractmethod
|
|
667
583
|
async def aflush(self) -> None:
|
|
668
584
|
"""Async flush operation."""
|
|
669
|
-
|
|
585
|
+
...
|
|
670
586
|
|
|
671
|
-
@abstractmethod
|
|
672
587
|
async def aclose(self) -> None:
|
|
673
588
|
"""Async close operation."""
|
|
674
|
-
|
|
589
|
+
...
|
|
675
590
|
|
|
676
591
|
# ============================================================================
|
|
677
592
|
# STATIC METHODS
|
|
678
593
|
# ============================================================================
|
|
679
594
|
|
|
680
595
|
@staticmethod
|
|
681
|
-
|
|
682
|
-
async def aopen_file(path: Union[str, Path], mode: str = 'r', encoding: Optional[str] = None) -> Any:
|
|
596
|
+
async def aopen_file(path: str | Path, mode: str = 'r', encoding: Optional[str] = None) -> Any:
|
|
683
597
|
"""Async open file."""
|
|
684
|
-
|
|
598
|
+
...
|
|
685
599
|
|
|
686
600
|
@staticmethod
|
|
687
|
-
|
|
688
|
-
async def aread_text(path: Union[str, Path], encoding: str = 'utf-8') -> str:
|
|
601
|
+
async def aread_text(path: str | Path, encoding: str = 'utf-8') -> str:
|
|
689
602
|
"""Async read text file."""
|
|
690
|
-
|
|
603
|
+
...
|
|
691
604
|
|
|
692
605
|
@staticmethod
|
|
693
|
-
|
|
694
|
-
async def aread_bytes(path: Union[str, Path]) -> bytes:
|
|
606
|
+
async def aread_bytes(path: str | Path) -> bytes:
|
|
695
607
|
"""Async read binary file."""
|
|
696
|
-
|
|
608
|
+
...
|
|
697
609
|
|
|
698
610
|
@staticmethod
|
|
699
|
-
|
|
700
|
-
async def awrite_text(path: Union[str, Path], content: str, encoding: str = 'utf-8') -> bool:
|
|
611
|
+
async def awrite_text(path: str | Path, content: str, encoding: str = 'utf-8') -> bool:
|
|
701
612
|
"""Async write text to file."""
|
|
702
|
-
|
|
613
|
+
...
|
|
703
614
|
|
|
704
615
|
@staticmethod
|
|
705
|
-
|
|
706
|
-
async def awrite_bytes(path: Union[str, Path], content: bytes) -> bool:
|
|
616
|
+
async def awrite_bytes(path: str | Path, content: bytes) -> bool:
|
|
707
617
|
"""Async write bytes to file."""
|
|
708
|
-
|
|
618
|
+
...
|
|
709
619
|
|
|
710
620
|
|
|
711
621
|
# ============================================================================
|
|
712
622
|
# ATOMIC OPERATIONS INTERFACES
|
|
713
623
|
# ============================================================================
|
|
714
624
|
|
|
715
|
-
|
|
625
|
+
@runtime_checkable
|
|
626
|
+
class IAtomicOperations(Protocol):
|
|
716
627
|
"""
|
|
717
628
|
Interface for atomic operations with both static and instance methods.
|
|
718
629
|
|
|
@@ -726,73 +637,64 @@ class IAtomicOperations(ABC):
|
|
|
726
637
|
# INSTANCE METHODS
|
|
727
638
|
# ============================================================================
|
|
728
639
|
|
|
729
|
-
|
|
730
|
-
def atomic_write(self, file_path: Union[str, Path], data: Union[str, bytes],
|
|
640
|
+
def atomic_write(self, file_path: str | Path, data: str | bytes,
|
|
731
641
|
backup: bool = True) -> OperationResult:
|
|
732
642
|
"""Atomically write data to file."""
|
|
733
|
-
|
|
643
|
+
...
|
|
734
644
|
|
|
735
|
-
|
|
736
|
-
def atomic_copy(self, source: Union[str, Path], destination: Union[str, Path]) -> OperationResult:
|
|
645
|
+
def atomic_copy(self, source: str | Path, destination: str | Path) -> OperationResult:
|
|
737
646
|
"""Atomically copy file."""
|
|
738
|
-
|
|
647
|
+
...
|
|
739
648
|
|
|
740
|
-
|
|
741
|
-
def atomic_move(self, source: Union[str, Path], destination: Union[str, Path]) -> OperationResult:
|
|
649
|
+
def atomic_move(self, source: str | Path, destination: str | Path) -> OperationResult:
|
|
742
650
|
"""Atomically move file."""
|
|
743
|
-
|
|
651
|
+
...
|
|
744
652
|
|
|
745
|
-
|
|
746
|
-
def atomic_delete(self, file_path: Union[str, Path], backup: bool = True) -> OperationResult:
|
|
653
|
+
def atomic_delete(self, file_path: str | Path, backup: bool = True) -> OperationResult:
|
|
747
654
|
"""Atomically delete file."""
|
|
748
|
-
|
|
655
|
+
...
|
|
749
656
|
|
|
750
|
-
|
|
751
|
-
def atomic_rename(self, old_path: Union[str, Path], new_path: Union[str, Path]) -> OperationResult:
|
|
657
|
+
def atomic_rename(self, old_path: str | Path, new_path: str | Path) -> OperationResult:
|
|
752
658
|
"""Atomically rename file."""
|
|
753
|
-
|
|
659
|
+
...
|
|
754
660
|
|
|
755
661
|
# ============================================================================
|
|
756
662
|
# STATIC METHODS
|
|
757
663
|
# ============================================================================
|
|
758
664
|
|
|
759
665
|
@staticmethod
|
|
760
|
-
|
|
761
|
-
def atomic_write_static(file_path: Union[str, Path], data: Union[str, bytes],
|
|
666
|
+
def atomic_write_static(file_path: str | Path, data: str | bytes,
|
|
762
667
|
backup: bool = True) -> OperationResult:
|
|
763
668
|
"""Atomically write data to file."""
|
|
764
|
-
|
|
669
|
+
...
|
|
765
670
|
|
|
766
671
|
@staticmethod
|
|
767
|
-
|
|
768
|
-
def atomic_copy_static(source: Union[str, Path], destination: Union[str, Path]) -> OperationResult:
|
|
672
|
+
def atomic_copy_static(source: str | Path, destination: str | Path) -> OperationResult:
|
|
769
673
|
"""Atomically copy file."""
|
|
770
|
-
|
|
674
|
+
...
|
|
771
675
|
|
|
772
676
|
@staticmethod
|
|
773
|
-
|
|
774
|
-
def atomic_move_static(source: Union[str, Path], destination: Union[str, Path]) -> OperationResult:
|
|
677
|
+
def atomic_move_static(source: str | Path, destination: str | Path) -> OperationResult:
|
|
775
678
|
"""Atomically move file."""
|
|
776
|
-
|
|
679
|
+
...
|
|
777
680
|
|
|
778
681
|
@staticmethod
|
|
779
|
-
|
|
780
|
-
def atomic_delete_static(file_path: Union[str, Path], backup: bool = True) -> OperationResult:
|
|
682
|
+
def atomic_delete_static(file_path: str | Path, backup: bool = True) -> OperationResult:
|
|
781
683
|
"""Atomically delete file."""
|
|
782
|
-
|
|
684
|
+
...
|
|
783
685
|
|
|
784
686
|
@staticmethod
|
|
785
|
-
|
|
786
|
-
def atomic_rename_static(old_path: Union[str, Path], new_path: Union[str, Path]) -> OperationResult:
|
|
687
|
+
def atomic_rename_static(old_path: str | Path, new_path: str | Path) -> OperationResult:
|
|
787
688
|
"""Atomically rename file."""
|
|
788
|
-
|
|
689
|
+
...
|
|
789
690
|
|
|
790
691
|
|
|
791
692
|
# ============================================================================
|
|
792
693
|
# BACKUP OPERATIONS INTERFACES
|
|
793
694
|
# ============================================================================
|
|
794
695
|
|
|
795
|
-
|
|
696
|
+
@runtime_checkable
|
|
697
|
+
class IBackupOperations(Protocol):
|
|
796
698
|
"""
|
|
797
699
|
Interface for backup operations with both static and instance methods.
|
|
798
700
|
|
|
@@ -806,71 +708,62 @@ class IBackupOperations(ABC):
|
|
|
806
708
|
# INSTANCE METHODS
|
|
807
709
|
# ============================================================================
|
|
808
710
|
|
|
809
|
-
|
|
810
|
-
def create_backup(self, source: Union[str, Path], backup_dir: Union[str, Path]) -> Optional[Path]:
|
|
711
|
+
def create_backup(self, source: str | Path, backup_dir: str | Path) -> Optional[Path]:
|
|
811
712
|
"""Create backup of file or directory."""
|
|
812
|
-
|
|
713
|
+
...
|
|
813
714
|
|
|
814
|
-
|
|
815
|
-
def restore_backup(self, backup_path: Union[str, Path], target: Union[str, Path]) -> OperationResult:
|
|
715
|
+
def restore_backup(self, backup_path: str | Path, target: str | Path) -> OperationResult:
|
|
816
716
|
"""Restore from backup."""
|
|
817
|
-
|
|
717
|
+
...
|
|
818
718
|
|
|
819
|
-
|
|
820
|
-
def list_backups(self, backup_dir: Union[str, Path]) -> list[Path]:
|
|
719
|
+
def list_backups(self, backup_dir: str | Path) -> list[Path]:
|
|
821
720
|
"""List available backups."""
|
|
822
|
-
|
|
721
|
+
...
|
|
823
722
|
|
|
824
|
-
|
|
825
|
-
def cleanup_backups(self, backup_dir: Union[str, Path], max_age_days: int = 30) -> int:
|
|
723
|
+
def cleanup_backups(self, backup_dir: str | Path, max_age_days: int = 30) -> int:
|
|
826
724
|
"""Cleanup old backups."""
|
|
827
|
-
|
|
725
|
+
...
|
|
828
726
|
|
|
829
|
-
|
|
830
|
-
def verify_backup(self, backup_path: Union[str, Path]) -> bool:
|
|
727
|
+
def verify_backup(self, backup_path: str | Path) -> bool:
|
|
831
728
|
"""Verify backup integrity."""
|
|
832
|
-
|
|
729
|
+
...
|
|
833
730
|
|
|
834
731
|
# ============================================================================
|
|
835
732
|
# STATIC METHODS
|
|
836
733
|
# ============================================================================
|
|
837
734
|
|
|
838
735
|
@staticmethod
|
|
839
|
-
|
|
840
|
-
def create_backup_static(source: Union[str, Path], backup_dir: Union[str, Path]) -> Optional[Path]:
|
|
736
|
+
def create_backup_static(source: str | Path, backup_dir: str | Path) -> Optional[Path]:
|
|
841
737
|
"""Create backup of file or directory."""
|
|
842
|
-
|
|
738
|
+
...
|
|
843
739
|
|
|
844
740
|
@staticmethod
|
|
845
|
-
|
|
846
|
-
def restore_backup_static(backup_path: Union[str, Path], target: Union[str, Path]) -> OperationResult:
|
|
741
|
+
def restore_backup_static(backup_path: str | Path, target: str | Path) -> OperationResult:
|
|
847
742
|
"""Restore from backup."""
|
|
848
|
-
|
|
743
|
+
...
|
|
849
744
|
|
|
850
745
|
@staticmethod
|
|
851
|
-
|
|
852
|
-
def list_backups_static(backup_dir: Union[str, Path]) -> list[Path]:
|
|
746
|
+
def list_backups_static(backup_dir: str | Path) -> list[Path]:
|
|
853
747
|
"""List available backups."""
|
|
854
|
-
|
|
748
|
+
...
|
|
855
749
|
|
|
856
750
|
@staticmethod
|
|
857
|
-
|
|
858
|
-
def cleanup_backups_static(backup_dir: Union[str, Path], max_age_days: int = 30) -> int:
|
|
751
|
+
def cleanup_backups_static(backup_dir: str | Path, max_age_days: int = 30) -> int:
|
|
859
752
|
"""Cleanup old backups."""
|
|
860
|
-
|
|
753
|
+
...
|
|
861
754
|
|
|
862
755
|
@staticmethod
|
|
863
|
-
|
|
864
|
-
def verify_backup_static(backup_path: Union[str, Path]) -> bool:
|
|
756
|
+
def verify_backup_static(backup_path: str | Path) -> bool:
|
|
865
757
|
"""Verify backup integrity."""
|
|
866
|
-
|
|
758
|
+
...
|
|
867
759
|
|
|
868
760
|
|
|
869
761
|
# ============================================================================
|
|
870
762
|
# TEMPORARY OPERATIONS INTERFACES
|
|
871
763
|
# ============================================================================
|
|
872
764
|
|
|
873
|
-
|
|
765
|
+
@runtime_checkable
|
|
766
|
+
class ITemporaryOperations(Protocol):
|
|
874
767
|
"""
|
|
875
768
|
Interface for temporary operations with both static and instance methods.
|
|
876
769
|
|
|
@@ -884,59 +777,50 @@ class ITemporaryOperations(ABC):
|
|
|
884
777
|
# INSTANCE METHODS
|
|
885
778
|
# ============================================================================
|
|
886
779
|
|
|
887
|
-
@abstractmethod
|
|
888
780
|
def create_temp_file(self, suffix: Optional[str] = None, prefix: Optional[str] = None) -> Path:
|
|
889
781
|
"""Create temporary file."""
|
|
890
|
-
|
|
782
|
+
...
|
|
891
783
|
|
|
892
|
-
@abstractmethod
|
|
893
784
|
def create_temp_directory(self, suffix: Optional[str] = None, prefix: Optional[str] = None) -> Path:
|
|
894
785
|
"""Create temporary directory."""
|
|
895
|
-
|
|
786
|
+
...
|
|
896
787
|
|
|
897
|
-
|
|
898
|
-
def cleanup_temp(self, path: Union[str, Path]) -> bool:
|
|
788
|
+
def cleanup_temp(self, path: str | Path) -> bool:
|
|
899
789
|
"""Cleanup temporary file or directory."""
|
|
900
|
-
|
|
790
|
+
...
|
|
901
791
|
|
|
902
|
-
@abstractmethod
|
|
903
792
|
def cleanup_all_temp(self) -> int:
|
|
904
793
|
"""Cleanup all temporary files and directories."""
|
|
905
|
-
|
|
794
|
+
...
|
|
906
795
|
|
|
907
796
|
# ============================================================================
|
|
908
797
|
# STATIC METHODS
|
|
909
798
|
# ============================================================================
|
|
910
799
|
|
|
911
800
|
@staticmethod
|
|
912
|
-
@abstractmethod
|
|
913
801
|
def create_temp_file_static(suffix: Optional[str] = None, prefix: Optional[str] = None) -> Path:
|
|
914
802
|
"""Create temporary file."""
|
|
915
|
-
|
|
803
|
+
...
|
|
916
804
|
|
|
917
805
|
@staticmethod
|
|
918
|
-
@abstractmethod
|
|
919
806
|
def create_temp_directory_static(suffix: Optional[str] = None, prefix: Optional[str] = None) -> Path:
|
|
920
807
|
"""Create temporary directory."""
|
|
921
|
-
|
|
808
|
+
...
|
|
922
809
|
|
|
923
810
|
@staticmethod
|
|
924
|
-
|
|
925
|
-
def cleanup_temp_static(path: Union[str, Path]) -> bool:
|
|
811
|
+
def cleanup_temp_static(path: str | Path) -> bool:
|
|
926
812
|
"""Cleanup temporary file or directory."""
|
|
927
|
-
|
|
813
|
+
...
|
|
928
814
|
|
|
929
815
|
@staticmethod
|
|
930
|
-
@abstractmethod
|
|
931
816
|
def get_temp_base_dir() -> Path:
|
|
932
817
|
"""Get temporary base directory."""
|
|
933
|
-
|
|
818
|
+
...
|
|
934
819
|
|
|
935
820
|
@staticmethod
|
|
936
|
-
|
|
937
|
-
def is_temp(path: Union[str, Path]) -> bool:
|
|
821
|
+
def is_temp(path: str | Path) -> bool:
|
|
938
822
|
"""Check if path is temporary."""
|
|
939
|
-
|
|
823
|
+
...
|
|
940
824
|
|
|
941
825
|
|
|
942
826
|
# ============================================================================
|
|
@@ -963,7 +847,7 @@ class IUnifiedIO(IFile, IFolder, IPath, IStream, IAsyncIO, IAtomicOperations, IB
|
|
|
963
847
|
|
|
964
848
|
This interface follows the xwsystem pattern of combining existing interfaces
|
|
965
849
|
rather than creating new abstractions, maximizing code reuse and maintaining
|
|
966
|
-
|
|
850
|
+
code reuse.
|
|
967
851
|
"""
|
|
968
852
|
pass
|
|
969
853
|
|
|
@@ -1001,110 +885,103 @@ class IFileManager(IFile, IFolder, IPath, IAtomicOperations, IBackupOperations,
|
|
|
1001
885
|
# DATA SOURCE INTERFACES (Used by file/, stream/)
|
|
1002
886
|
# ============================================================================
|
|
1003
887
|
|
|
1004
|
-
|
|
888
|
+
@runtime_checkable
|
|
889
|
+
class IDataSource[T](Protocol):
|
|
1005
890
|
"""Universal data source interface for various data sources."""
|
|
1006
891
|
|
|
1007
|
-
@abstractmethod
|
|
1008
892
|
def read(self) -> T:
|
|
1009
893
|
"""Read data from source."""
|
|
1010
|
-
|
|
894
|
+
...
|
|
1011
895
|
|
|
1012
|
-
@abstractmethod
|
|
1013
896
|
def write(self, data: T) -> None:
|
|
1014
897
|
"""Write data to source."""
|
|
1015
|
-
|
|
898
|
+
...
|
|
1016
899
|
|
|
1017
900
|
|
|
1018
|
-
|
|
901
|
+
@runtime_checkable
|
|
902
|
+
class IPagedDataSource[T](Protocol):
|
|
1019
903
|
"""Paged data source interface for large data sets."""
|
|
1020
904
|
|
|
1021
|
-
@abstractmethod
|
|
1022
905
|
def read_page(self, page_number: int) -> list[T]:
|
|
1023
906
|
"""Read a specific page of data."""
|
|
1024
|
-
|
|
907
|
+
...
|
|
1025
908
|
|
|
1026
|
-
@abstractmethod
|
|
1027
909
|
def get_page_count(self) -> int:
|
|
1028
910
|
"""Get total number of pages."""
|
|
1029
|
-
|
|
911
|
+
...
|
|
1030
912
|
|
|
1031
913
|
|
|
1032
914
|
# ============================================================================
|
|
1033
915
|
# CODEC-INTEGRATED IO INTERFACES (Used by stream/)
|
|
1034
916
|
# ============================================================================
|
|
1035
917
|
|
|
1036
|
-
|
|
918
|
+
@runtime_checkable
|
|
919
|
+
class ICodecIO[T, R](Protocol):
|
|
1037
920
|
"""Codec-integrated IO interface with source type T and result type R."""
|
|
1038
921
|
|
|
1039
|
-
@abstractmethod
|
|
1040
922
|
def read_as(self, codec: str):
|
|
1041
923
|
"""Read and decode data using specified codec."""
|
|
1042
|
-
|
|
924
|
+
...
|
|
1043
925
|
|
|
1044
|
-
@abstractmethod
|
|
1045
926
|
def write_as(self, data, codec: str) -> None:
|
|
1046
927
|
"""Encode and write data using specified codec."""
|
|
1047
|
-
|
|
928
|
+
...
|
|
1048
929
|
|
|
1049
930
|
|
|
1050
|
-
|
|
931
|
+
@runtime_checkable
|
|
932
|
+
class IPagedCodecIO[T, R](Protocol):
|
|
1051
933
|
"""Paged codec-integrated IO interface with source type T and result type R."""
|
|
1052
934
|
|
|
1053
|
-
@abstractmethod
|
|
1054
935
|
def read_page_as(self, page_number: int, codec: str):
|
|
1055
936
|
"""Read and decode a page using specified codec."""
|
|
1056
|
-
|
|
937
|
+
...
|
|
1057
938
|
|
|
1058
939
|
|
|
1059
940
|
# ============================================================================
|
|
1060
941
|
# FILE SYSTEM INTERFACES (Used by common/, filesystem/)
|
|
1061
942
|
# ============================================================================
|
|
1062
943
|
|
|
1063
|
-
|
|
944
|
+
@runtime_checkable
|
|
945
|
+
class IFileWatcher(Protocol):
|
|
1064
946
|
"""Interface for watching file system changes."""
|
|
1065
947
|
|
|
1066
|
-
|
|
1067
|
-
def watch(self, path: Union[str, Path]) -> None:
|
|
948
|
+
def watch(self, path: str | Path) -> None:
|
|
1068
949
|
"""Start watching a path."""
|
|
1069
|
-
|
|
950
|
+
...
|
|
1070
951
|
|
|
1071
|
-
@abstractmethod
|
|
1072
952
|
def stop(self) -> None:
|
|
1073
953
|
"""Stop watching."""
|
|
1074
|
-
|
|
954
|
+
...
|
|
1075
955
|
|
|
1076
956
|
|
|
1077
|
-
|
|
957
|
+
@runtime_checkable
|
|
958
|
+
class IFileLock(Protocol):
|
|
1078
959
|
"""Interface for file locking."""
|
|
1079
960
|
|
|
1080
|
-
@abstractmethod
|
|
1081
961
|
def acquire(self) -> bool:
|
|
1082
962
|
"""Acquire the lock."""
|
|
1083
|
-
|
|
963
|
+
...
|
|
1084
964
|
|
|
1085
|
-
@abstractmethod
|
|
1086
965
|
def release(self) -> None:
|
|
1087
966
|
"""Release the lock."""
|
|
1088
|
-
|
|
967
|
+
...
|
|
1089
968
|
|
|
1090
969
|
|
|
1091
|
-
|
|
970
|
+
@runtime_checkable
|
|
971
|
+
class IFileSystem(Protocol):
|
|
1092
972
|
"""Virtual file system interface."""
|
|
1093
973
|
|
|
1094
|
-
@abstractmethod
|
|
1095
974
|
def read(self, path: str) -> bytes:
|
|
1096
975
|
"""Read file contents."""
|
|
1097
|
-
|
|
976
|
+
...
|
|
1098
977
|
|
|
1099
|
-
@abstractmethod
|
|
1100
978
|
def write(self, path: str, data: bytes) -> None:
|
|
1101
979
|
"""Write file contents."""
|
|
1102
|
-
|
|
980
|
+
...
|
|
1103
981
|
|
|
1104
|
-
@abstractmethod
|
|
1105
982
|
def exists(self, path: str) -> bool:
|
|
1106
983
|
"""Check if path exists."""
|
|
1107
|
-
|
|
984
|
+
...
|
|
1108
985
|
|
|
1109
986
|
|
|
1110
987
|
# ============================================================================
|
|
@@ -1393,7 +1270,7 @@ class IAtomicWriter(Protocol):
|
|
|
1393
1270
|
"""Write data atomically."""
|
|
1394
1271
|
...
|
|
1395
1272
|
|
|
1396
|
-
def __enter__(self) ->
|
|
1273
|
+
def __enter__(self) -> IAtomicWriter:
|
|
1397
1274
|
"""Enter context manager."""
|
|
1398
1275
|
...
|
|
1399
1276
|
|
|
@@ -1423,23 +1300,21 @@ class IArchiver[T](ICodec[T, bytes]):
|
|
|
1423
1300
|
NOT limited to file paths - works on data in RAM!
|
|
1424
1301
|
"""
|
|
1425
1302
|
|
|
1426
|
-
@abstractmethod
|
|
1427
1303
|
def compress(self, data: T, **options) -> bytes:
|
|
1428
1304
|
"""
|
|
1429
1305
|
Compress data to archive bytes (in RAM).
|
|
1430
1306
|
|
|
1431
1307
|
Delegates to encode() internally.
|
|
1432
1308
|
"""
|
|
1433
|
-
|
|
1309
|
+
...
|
|
1434
1310
|
|
|
1435
|
-
@abstractmethod
|
|
1436
1311
|
def extract(self, archive_bytes: bytes, **options) -> T:
|
|
1437
1312
|
"""
|
|
1438
1313
|
Extract archive bytes to data (in RAM).
|
|
1439
1314
|
|
|
1440
1315
|
Delegates to decode() internally.
|
|
1441
1316
|
"""
|
|
1442
|
-
|
|
1317
|
+
...
|
|
1443
1318
|
|
|
1444
1319
|
|
|
1445
1320
|
class IArchiveFile(IFile):
|
|
@@ -1455,28 +1330,25 @@ class IArchiveFile(IFile):
|
|
|
1455
1330
|
- Archive file management
|
|
1456
1331
|
"""
|
|
1457
1332
|
|
|
1458
|
-
@abstractmethod
|
|
1459
1333
|
def add_files(self, files: list[Path], **options) -> None:
|
|
1460
1334
|
"""Add files to archive (uses archiver.compress internally)."""
|
|
1461
|
-
|
|
1335
|
+
...
|
|
1462
1336
|
|
|
1463
|
-
@abstractmethod
|
|
1464
1337
|
def extract_to(self, dest: Path, **options) -> list[Path]:
|
|
1465
1338
|
"""Extract archive to destination (uses archiver.extract internally)."""
|
|
1466
|
-
|
|
1339
|
+
...
|
|
1467
1340
|
|
|
1468
|
-
@abstractmethod
|
|
1469
1341
|
def list_contents(self) -> list[str]:
|
|
1470
1342
|
"""List files in archive."""
|
|
1471
|
-
|
|
1343
|
+
...
|
|
1472
1344
|
|
|
1473
|
-
@abstractmethod
|
|
1474
1345
|
def get_archiver(self) -> IArchiver:
|
|
1475
1346
|
"""Get the underlying archiver codec."""
|
|
1476
|
-
|
|
1347
|
+
...
|
|
1477
1348
|
|
|
1478
1349
|
|
|
1479
|
-
|
|
1350
|
+
@runtime_checkable
|
|
1351
|
+
class ICompression(Protocol):
|
|
1480
1352
|
"""
|
|
1481
1353
|
Interface for raw compression operations (gzip, bz2, lzma, etc.).
|
|
1482
1354
|
|
|
@@ -1484,30 +1356,28 @@ class ICompression(ABC):
|
|
|
1484
1356
|
Separate from IArchiver which handles archive formats.
|
|
1485
1357
|
"""
|
|
1486
1358
|
|
|
1487
|
-
@abstractmethod
|
|
1488
1359
|
def compress(self, data: bytes, **options) -> bytes:
|
|
1489
1360
|
"""Compress raw bytes."""
|
|
1490
|
-
|
|
1361
|
+
...
|
|
1491
1362
|
|
|
1492
|
-
@abstractmethod
|
|
1493
1363
|
def decompress(self, data: bytes, **options) -> bytes:
|
|
1494
1364
|
"""Decompress raw bytes."""
|
|
1495
|
-
|
|
1365
|
+
...
|
|
1496
1366
|
|
|
1497
1367
|
|
|
1498
1368
|
@runtime_checkable
|
|
1499
1369
|
class IPathValidator(Protocol):
|
|
1500
1370
|
"""Interface for path validation and security checks."""
|
|
1501
1371
|
|
|
1502
|
-
def validate_path(self, path:
|
|
1372
|
+
def validate_path(self, path: str | Path) -> bool:
|
|
1503
1373
|
"""Validate path safety."""
|
|
1504
1374
|
...
|
|
1505
1375
|
|
|
1506
|
-
def is_safe_path(self, path:
|
|
1376
|
+
def is_safe_path(self, path: str | Path) -> bool:
|
|
1507
1377
|
"""Check if path is safe to use."""
|
|
1508
1378
|
...
|
|
1509
1379
|
|
|
1510
|
-
def normalize_path(self, path:
|
|
1380
|
+
def normalize_path(self, path: str | Path) -> Path:
|
|
1511
1381
|
"""Normalize and resolve path."""
|
|
1512
1382
|
...
|
|
1513
1383
|
|
|
@@ -1529,11 +1399,11 @@ class IFileSource(Protocol):
|
|
|
1529
1399
|
"""URI scheme."""
|
|
1530
1400
|
...
|
|
1531
1401
|
|
|
1532
|
-
def read(self, **options) ->
|
|
1402
|
+
def read(self, **options) -> bytes | str:
|
|
1533
1403
|
"""Read entire file content."""
|
|
1534
1404
|
...
|
|
1535
1405
|
|
|
1536
|
-
def write(self, data:
|
|
1406
|
+
def write(self, data: bytes | str, **options) -> None:
|
|
1537
1407
|
"""Write entire content to file."""
|
|
1538
1408
|
...
|
|
1539
1409
|
|
|
@@ -1554,19 +1424,19 @@ class IPagedSource(Protocol):
|
|
|
1554
1424
|
"""Total file size in bytes."""
|
|
1555
1425
|
...
|
|
1556
1426
|
|
|
1557
|
-
def read_page(self, page: int, page_size: int, **options) ->
|
|
1427
|
+
def read_page(self, page: int, page_size: int, **options) -> bytes | str:
|
|
1558
1428
|
"""Read specific page."""
|
|
1559
1429
|
...
|
|
1560
1430
|
|
|
1561
|
-
def read_chunk(self, offset: int, size: int, **options) ->
|
|
1431
|
+
def read_chunk(self, offset: int, size: int, **options) -> bytes | str:
|
|
1562
1432
|
"""Read chunk by byte offset."""
|
|
1563
1433
|
...
|
|
1564
1434
|
|
|
1565
|
-
def iter_pages(self, page_size: int, **options) -> Iterator[
|
|
1435
|
+
def iter_pages(self, page_size: int, **options) -> Iterator[bytes | str]:
|
|
1566
1436
|
"""Iterate over pages."""
|
|
1567
1437
|
...
|
|
1568
1438
|
|
|
1569
|
-
def iter_chunks(self, chunk_size: int, **options) -> Iterator[
|
|
1439
|
+
def iter_chunks(self, chunk_size: int, **options) -> Iterator[bytes | str]:
|
|
1570
1440
|
"""Iterate over chunks."""
|
|
1571
1441
|
...
|
|
1572
1442
|
|
|
@@ -1595,7 +1465,7 @@ class IPagingStrategy(Protocol):
|
|
|
1595
1465
|
mode: str = 'rb',
|
|
1596
1466
|
encoding: Optional[str] = None,
|
|
1597
1467
|
**options
|
|
1598
|
-
) ->
|
|
1468
|
+
) -> bytes | str:
|
|
1599
1469
|
"""
|
|
1600
1470
|
Read specific page using this strategy.
|
|
1601
1471
|
|
|
@@ -1619,7 +1489,7 @@ class IPagingStrategy(Protocol):
|
|
|
1619
1489
|
mode: str = 'rb',
|
|
1620
1490
|
encoding: Optional[str] = None,
|
|
1621
1491
|
**options
|
|
1622
|
-
) -> Iterator[
|
|
1492
|
+
) -> Iterator[bytes | str]:
|
|
1623
1493
|
"""
|
|
1624
1494
|
Iterate over pages using this strategy.
|
|
1625
1495
|
|
|
@@ -1698,12 +1568,10 @@ class IPagedCodecIO[T, R](ICodecIO[T, R]):
|
|
|
1698
1568
|
Interface for paged codec I/O.
|
|
1699
1569
|
"""
|
|
1700
1570
|
|
|
1701
|
-
@abstractmethod
|
|
1702
1571
|
def iter_items(self, page_size: int, **opts):
|
|
1703
1572
|
"""Iterate over decoded items."""
|
|
1704
1573
|
...
|
|
1705
1574
|
|
|
1706
|
-
@abstractmethod
|
|
1707
1575
|
def load_page(self, page: int, page_size: int, **opts) -> list[T]:
|
|
1708
1576
|
"""Load specific page."""
|
|
1709
1577
|
...
|