zerofilesystem 0.1.0__tar.gz
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.
- zerofilesystem-0.1.0/.github/workflows/ci.yml +99 -0
- zerofilesystem-0.1.0/.github/workflows/publish.yml +40 -0
- zerofilesystem-0.1.0/.github/workflows/release.yml +18 -0
- zerofilesystem-0.1.0/.gitignore +42 -0
- zerofilesystem-0.1.0/CHANGELOG.md +34 -0
- zerofilesystem-0.1.0/LICENSE +21 -0
- zerofilesystem-0.1.0/PKG-INFO +383 -0
- zerofilesystem-0.1.0/README.md +359 -0
- zerofilesystem-0.1.0/docs/API_REFERENCE.md +2235 -0
- zerofilesystem-0.1.0/docs/ARCHITECTURE.md +264 -0
- zerofilesystem-0.1.0/docs/FUNCTIONAL_ANALYSIS.md +646 -0
- zerofilesystem-0.1.0/examples/01_basic_io.py +136 -0
- zerofilesystem-0.1.0/examples/02_json_operations.py +162 -0
- zerofilesystem-0.1.0/examples/03_file_discovery.py +195 -0
- zerofilesystem-0.1.0/examples/04_file_locking.py +179 -0
- zerofilesystem-0.1.0/examples/05_transactions.py +204 -0
- zerofilesystem-0.1.0/examples/06_archives.py +217 -0
- zerofilesystem-0.1.0/examples/07_directory_ops.py +213 -0
- zerofilesystem-0.1.0/examples/08_complete_example.py +250 -0
- zerofilesystem-0.1.0/examples/09_finder.py +284 -0
- zerofilesystem-0.1.0/examples/10_watcher.py +338 -0
- zerofilesystem-0.1.0/pyproject.toml +155 -0
- zerofilesystem-0.1.0/src/zerofilesystem/__init__.py +326 -0
- zerofilesystem-0.1.0/src/zerofilesystem/_platform.py +13 -0
- zerofilesystem-0.1.0/src/zerofilesystem/classes/__init__.py +84 -0
- zerofilesystem-0.1.0/src/zerofilesystem/classes/_internal.py +107 -0
- zerofilesystem-0.1.0/src/zerofilesystem/classes/archive_handler.py +348 -0
- zerofilesystem-0.1.0/src/zerofilesystem/classes/directory_ops.py +450 -0
- zerofilesystem-0.1.0/src/zerofilesystem/classes/exceptions.py +164 -0
- zerofilesystem-0.1.0/src/zerofilesystem/classes/file_lock.py +171 -0
- zerofilesystem-0.1.0/src/zerofilesystem/classes/file_permissions.py +320 -0
- zerofilesystem-0.1.0/src/zerofilesystem/classes/file_transaction.py +377 -0
- zerofilesystem-0.1.0/src/zerofilesystem/classes/files.py +444 -0
- zerofilesystem-0.1.0/src/zerofilesystem/classes/finder.py +603 -0
- zerofilesystem-0.1.0/src/zerofilesystem/classes/integrity_checker.py +391 -0
- zerofilesystem-0.1.0/src/zerofilesystem/classes/io.py +374 -0
- zerofilesystem-0.1.0/src/zerofilesystem/classes/path_utils.py +301 -0
- zerofilesystem-0.1.0/src/zerofilesystem/classes/secure_ops.py +255 -0
- zerofilesystem-0.1.0/src/zerofilesystem/classes/watcher.py +996 -0
- zerofilesystem-0.1.0/src/zerofilesystem/py.typed +0 -0
- zerofilesystem-0.1.0/src/zerofilesystem/zerofilesystem.py +608 -0
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [ main, develop ]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [ main, develop ]
|
|
8
|
+
|
|
9
|
+
concurrency:
|
|
10
|
+
group: ${{ github.workflow }}-${{ github.ref }}
|
|
11
|
+
cancel-in-progress: true
|
|
12
|
+
|
|
13
|
+
permissions:
|
|
14
|
+
contents: read
|
|
15
|
+
|
|
16
|
+
jobs:
|
|
17
|
+
commit-messages:
|
|
18
|
+
name: Validate Commit Messages
|
|
19
|
+
if: github.event_name == 'pull_request'
|
|
20
|
+
runs-on: ubuntu-latest
|
|
21
|
+
steps:
|
|
22
|
+
- uses: actions/checkout@v4
|
|
23
|
+
with:
|
|
24
|
+
fetch-depth: 0
|
|
25
|
+
|
|
26
|
+
- name: Check commits are Conventional Commits
|
|
27
|
+
uses: webiny/action-conventional-commits@v1.3.0
|
|
28
|
+
|
|
29
|
+
lint:
|
|
30
|
+
name: Lint and Type Check
|
|
31
|
+
runs-on: ubuntu-latest
|
|
32
|
+
|
|
33
|
+
steps:
|
|
34
|
+
- uses: actions/checkout@v4
|
|
35
|
+
|
|
36
|
+
- name: Set up Python
|
|
37
|
+
uses: actions/setup-python@v5
|
|
38
|
+
with:
|
|
39
|
+
python-version: "3.12"
|
|
40
|
+
|
|
41
|
+
- name: Install uv
|
|
42
|
+
uses: astral-sh/setup-uv@v3
|
|
43
|
+
with:
|
|
44
|
+
enable-cache: false
|
|
45
|
+
|
|
46
|
+
- name: Install dependencies
|
|
47
|
+
run: uv sync
|
|
48
|
+
|
|
49
|
+
- name: Lint with ruff
|
|
50
|
+
run: |
|
|
51
|
+
uv run ruff check .
|
|
52
|
+
uv run ruff format --check .
|
|
53
|
+
|
|
54
|
+
- name: Type check with mypy
|
|
55
|
+
run: uv run mypy --package zerofilesystem
|
|
56
|
+
|
|
57
|
+
- name: Security check with bandit
|
|
58
|
+
run: uv run bandit -c pyproject.toml -r .
|
|
59
|
+
|
|
60
|
+
- name: Dead code check with vulture
|
|
61
|
+
run: uv run vulture src/
|
|
62
|
+
|
|
63
|
+
test:
|
|
64
|
+
name: Test Suite
|
|
65
|
+
runs-on: ${{ matrix.os }}
|
|
66
|
+
strategy:
|
|
67
|
+
fail-fast: false
|
|
68
|
+
matrix:
|
|
69
|
+
os: [ubuntu-latest, windows-latest, macos-latest]
|
|
70
|
+
python-version: ["3.12", "3.13"]
|
|
71
|
+
|
|
72
|
+
steps:
|
|
73
|
+
- uses: actions/checkout@v4
|
|
74
|
+
|
|
75
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
76
|
+
uses: actions/setup-python@v5
|
|
77
|
+
with:
|
|
78
|
+
python-version: ${{ matrix.python-version }}
|
|
79
|
+
|
|
80
|
+
- name: Install uv
|
|
81
|
+
uses: astral-sh/setup-uv@v3
|
|
82
|
+
with:
|
|
83
|
+
enable-cache: false
|
|
84
|
+
|
|
85
|
+
- name: Install dependencies
|
|
86
|
+
run: uv sync
|
|
87
|
+
|
|
88
|
+
- name: Run tests with coverage
|
|
89
|
+
run: uv run pytest --cov --cov-report=xml --cov-report=term --cov-report=html
|
|
90
|
+
|
|
91
|
+
- name: Upload coverage reports
|
|
92
|
+
uses: actions/upload-artifact@v4
|
|
93
|
+
if: matrix.os == 'ubuntu-latest' && matrix.python-version == '3.12'
|
|
94
|
+
with:
|
|
95
|
+
name: coverage-reports
|
|
96
|
+
path: |
|
|
97
|
+
coverage.xml
|
|
98
|
+
htmlcov/
|
|
99
|
+
retention-days: 30
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
|
|
6
|
+
jobs:
|
|
7
|
+
build:
|
|
8
|
+
name: Build distribution
|
|
9
|
+
runs-on: ubuntu-latest
|
|
10
|
+
steps:
|
|
11
|
+
- uses: actions/checkout@v4
|
|
12
|
+
|
|
13
|
+
- name: Install uv
|
|
14
|
+
uses: astral-sh/setup-uv@v3
|
|
15
|
+
|
|
16
|
+
- name: Build package
|
|
17
|
+
run: uv build
|
|
18
|
+
|
|
19
|
+
- name: Upload dist artifacts
|
|
20
|
+
uses: actions/upload-artifact@v4
|
|
21
|
+
with:
|
|
22
|
+
name: dist
|
|
23
|
+
path: dist/
|
|
24
|
+
|
|
25
|
+
publish:
|
|
26
|
+
name: Publish to PyPI
|
|
27
|
+
needs: build
|
|
28
|
+
runs-on: ubuntu-latest
|
|
29
|
+
environment: pypi
|
|
30
|
+
permissions:
|
|
31
|
+
id-token: write
|
|
32
|
+
steps:
|
|
33
|
+
- name: Download dist artifacts
|
|
34
|
+
uses: actions/download-artifact@v4
|
|
35
|
+
with:
|
|
36
|
+
name: dist
|
|
37
|
+
path: dist/
|
|
38
|
+
|
|
39
|
+
- name: Publish to PyPI
|
|
40
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
contents: write
|
|
9
|
+
pull-requests: write
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
release-please:
|
|
13
|
+
name: Release Please
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
steps:
|
|
16
|
+
- uses: googleapis/release-please-action@v4
|
|
17
|
+
with:
|
|
18
|
+
release-type: python
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
__pycache__/
|
|
2
|
+
*.py[cod]
|
|
3
|
+
*.egg-info/
|
|
4
|
+
|
|
5
|
+
# Build artifacts
|
|
6
|
+
dist/
|
|
7
|
+
build/
|
|
8
|
+
.coverage
|
|
9
|
+
htmlcov/
|
|
10
|
+
|
|
11
|
+
# All hidden directories (starts with .)
|
|
12
|
+
.*/
|
|
13
|
+
|
|
14
|
+
# Keep .gitignore and .github
|
|
15
|
+
!.gitignore
|
|
16
|
+
!.github/
|
|
17
|
+
|
|
18
|
+
# Hidden files to ignore
|
|
19
|
+
.DS_Store
|
|
20
|
+
.coverage
|
|
21
|
+
.env
|
|
22
|
+
|
|
23
|
+
# Lock file (library - not committed)
|
|
24
|
+
uv.lock
|
|
25
|
+
|
|
26
|
+
# Other files
|
|
27
|
+
*.swp
|
|
28
|
+
*.swo
|
|
29
|
+
*.log
|
|
30
|
+
*.bak
|
|
31
|
+
|
|
32
|
+
# Virtual environments (non-hidden)
|
|
33
|
+
env/
|
|
34
|
+
venv/
|
|
35
|
+
/.scripts/
|
|
36
|
+
/.venv/
|
|
37
|
+
|
|
38
|
+
# Hidden helper files
|
|
39
|
+
.run.sh
|
|
40
|
+
.setup.sh
|
|
41
|
+
.setup.bat
|
|
42
|
+
.check_quality.py
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## 0.1.0 (2026-03-29)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Features
|
|
12
|
+
|
|
13
|
+
* initial release of zerofilesystem 0.1.0 ([39400c2](https://github.com/francescofavi/zerofilesystem/commit/39400c26a41f1e5d21ac59dcf3bd6841ce778981))
|
|
14
|
+
|
|
15
|
+
## [0.1.0] - 2026-02-19
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
|
|
19
|
+
- Initial release
|
|
20
|
+
- Cross-platform file system utilities
|
|
21
|
+
- File I/O operations (text, bytes, JSON, gzip)
|
|
22
|
+
- File discovery and walking
|
|
23
|
+
- File locking and transactions
|
|
24
|
+
- File watching and monitoring
|
|
25
|
+
- Directory operations and sync
|
|
26
|
+
- File integrity and hashing
|
|
27
|
+
- Secure delete operations
|
|
28
|
+
- Archive handling (tar, zip)
|
|
29
|
+
- Path utilities and normalization
|
|
30
|
+
- File permissions and metadata
|
|
31
|
+
- Comprehensive test suite
|
|
32
|
+
- Full type hints with py.typed marker
|
|
33
|
+
|
|
34
|
+
[0.1.0]: https://github.com/francescofavi/zerofilesystem/releases/tag/v0.1.0
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Francesco Favi
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,383 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: zerofilesystem
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Cross-platform file system utilities for Python
|
|
5
|
+
Project-URL: Homepage, https://github.com/francescofavi/zerofilesystem
|
|
6
|
+
Project-URL: Repository, https://github.com/francescofavi/zerofilesystem
|
|
7
|
+
Project-URL: Issues, https://github.com/francescofavi/zerofilesystem/issues
|
|
8
|
+
Project-URL: Documentation, https://github.com/francescofavi/zerofilesystem#readme
|
|
9
|
+
Project-URL: Changelog, https://github.com/francescofavi/zerofilesystem/blob/main/CHANGELOG.md
|
|
10
|
+
Author-email: Francesco Favi <14098835+francescofavi@users.noreply.github.com>
|
|
11
|
+
License: MIT
|
|
12
|
+
License-File: LICENSE
|
|
13
|
+
Keywords: cross-platform,files,filesystem,io,pathlib,utilities
|
|
14
|
+
Classifier: Development Status :: 4 - Beta
|
|
15
|
+
Classifier: Intended Audience :: Developers
|
|
16
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
17
|
+
Classifier: Operating System :: OS Independent
|
|
18
|
+
Classifier: Programming Language :: Python :: 3
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Classifier: Typing :: Typed
|
|
22
|
+
Requires-Python: >=3.12
|
|
23
|
+
Description-Content-Type: text/markdown
|
|
24
|
+
|
|
25
|
+
# zerofilesystem
|
|
26
|
+
|
|
27
|
+
[](https://pypi.org/project/zerofilesystem/)
|
|
28
|
+
[](https://pypi.org/project/zerofilesystem/)
|
|
29
|
+
[](https://github.com/francescofavi/zerofilesystem/blob/main/LICENSE)
|
|
30
|
+
|
|
31
|
+
Cross-platform file system utilities for Python 3.12+
|
|
32
|
+
|
|
33
|
+
## Why This Project Exists
|
|
34
|
+
|
|
35
|
+
Working with files in Python often requires combining multiple standard library modules (`os`, `shutil`, `pathlib`, `json`, `gzip`, `tarfile`, `zipfile`) with careful attention to platform differences, atomic operations, and error handling. **zerofilesystem** consolidates these operations into a single, cohesive library that handles the complexity for you.
|
|
36
|
+
|
|
37
|
+
The library solves common pain points: ensuring atomic writes don't corrupt files on crash, managing cross-platform file locking, handling path normalization across Windows and Unix, and providing transactional file operations with automatic rollback. Whether you're building a configuration manager, a backup utility, or any application that needs reliable file operations, zerofilesystem provides battle-tested primitives that work consistently across platforms.
|
|
38
|
+
|
|
39
|
+
## Technical Choices and Design
|
|
40
|
+
|
|
41
|
+
zerofilesystem uses **only the Python standard library** with no external dependencies. This deliberate choice ensures maximum compatibility, minimal installation footprint, and no dependency conflicts.
|
|
42
|
+
|
|
43
|
+
The library is organized around single-responsibility classes, each handling one category of file operations. All public functions accept both `str` and `pathlib.Path` objects via the `Pathish` type alias. Atomic operations use the temp-file-plus-rename pattern to ensure crash safety on POSIX-compliant filesystems.
|
|
44
|
+
|
|
45
|
+
Platform-specific behavior (file locking via `fcntl`/`msvcrt`, hidden file attributes, executable permissions) is abstracted behind unified APIs that do the right thing on each platform.
|
|
46
|
+
|
|
47
|
+
## High-Level Component Overview
|
|
48
|
+
|
|
49
|
+
The library is structured into functional modules:
|
|
50
|
+
|
|
51
|
+
- **Basic I/O** (`FileIO`, `JsonHandler`, `GzipHandler`) - Text and binary file reading/writing with atomic support, JSON serialization, and gzip compression
|
|
52
|
+
- **File Discovery** (`FileFinder`, `Finder`) - Glob-based file search with custom filters and lazy iteration; `Finder` provides a fluent builder API
|
|
53
|
+
- **File Operations** (`FileSync`, `FileHasher`, `FileMeta`, `FileUtils`) - Conditional copy/move, cryptographic hashing, metadata access, and filename sanitization
|
|
54
|
+
- **Path Utilities** (`PathUtils`) - Cross-platform path normalization, expansion, and validation
|
|
55
|
+
- **Permissions** (`FilePermissions`) - Read/write/execute attributes and timestamp manipulation
|
|
56
|
+
- **Directory Operations** (`DirectoryOps`) - Tree copy, move, sync, and temporary directories
|
|
57
|
+
- **Integrity** (`IntegrityChecker`) - Directory hashing, manifest creation, and verification
|
|
58
|
+
- **Transactions** (`FileTransaction`) - Multi-file atomic operations with rollback
|
|
59
|
+
- **Security** (`SecureOps`) - Secure file deletion and private directory creation
|
|
60
|
+
- **Archives** (`ArchiveHandler`) - Tar and zip creation/extraction with filtering
|
|
61
|
+
- **File Watching** (`FileWatcher`, `Watcher`) - Polling-based filesystem monitoring; `Watcher` provides a fluent builder API with debouncing
|
|
62
|
+
- **Locking** (`FileLock`) - Cross-platform advisory file locking
|
|
63
|
+
|
|
64
|
+
## Meaningful Usage Example
|
|
65
|
+
|
|
66
|
+
Here's a realistic example showing how zerofilesystem components work together to create a simple backup system with integrity verification:
|
|
67
|
+
|
|
68
|
+
```python
|
|
69
|
+
import zerofilesystem as zo
|
|
70
|
+
|
|
71
|
+
# Create a backup of a project directory
|
|
72
|
+
source_dir = "./my_project"
|
|
73
|
+
backup_dir = "./backups"
|
|
74
|
+
|
|
75
|
+
# Create timestamped backup archive
|
|
76
|
+
zo.ensure_dir(backup_dir)
|
|
77
|
+
archive_path = zo.create_zip(
|
|
78
|
+
source_dir,
|
|
79
|
+
f"{backup_dir}/backup_2024.zip",
|
|
80
|
+
filter_fn=lambda p: not p.name.startswith("."), # Exclude hidden files
|
|
81
|
+
compression="deflated"
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
# Generate integrity manifest for verification
|
|
85
|
+
manifest = zo.create_manifest(source_dir, algorithm="sha256")
|
|
86
|
+
zo.save_manifest(manifest, f"{backup_dir}/backup_2024.manifest")
|
|
87
|
+
|
|
88
|
+
# Later: verify the backup matches the manifest
|
|
89
|
+
loaded_manifest, algo = zo.load_manifest(f"{backup_dir}/backup_2024.manifest")
|
|
90
|
+
result = zo.verify_manifest(source_dir, loaded_manifest, algorithm=algo)
|
|
91
|
+
|
|
92
|
+
if result.is_valid:
|
|
93
|
+
print("Backup integrity verified!")
|
|
94
|
+
else:
|
|
95
|
+
print(f"Modified: {result.modified}, Missing: {result.missing}")
|
|
96
|
+
|
|
97
|
+
# Use transactions for multi-file config updates
|
|
98
|
+
with zo.FileTransaction() as tx:
|
|
99
|
+
tx.write_text("config/app.json", '{"version": 2}')
|
|
100
|
+
tx.write_text("config/db.json", '{"host": "localhost"}')
|
|
101
|
+
# Both files written atomically, or neither if an error occurs
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## Installation
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
pip install zerofilesystem
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Or install from source:
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
git clone https://github.com/francescofavi/zerofilesystem.git
|
|
114
|
+
cd zerofilesystem
|
|
115
|
+
pip install -e .
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### Requirements
|
|
119
|
+
|
|
120
|
+
- **Python 3.12+**
|
|
121
|
+
- **No external dependencies** - uses only the Python standard library
|
|
122
|
+
|
|
123
|
+
## Main Functions and APIs
|
|
124
|
+
|
|
125
|
+
### File I/O
|
|
126
|
+
|
|
127
|
+
**`read_text(path, encoding="utf-8")`** - Read text file contents.
|
|
128
|
+
```python
|
|
129
|
+
# Simple
|
|
130
|
+
content = zo.read_text("config.txt")
|
|
131
|
+
|
|
132
|
+
# With encoding
|
|
133
|
+
content = zo.read_text("data.txt", encoding="latin-1")
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
**`write_text(path, data, atomic=True, create_dirs=True)`** - Write text with atomic safety.
|
|
137
|
+
```python
|
|
138
|
+
# Simple
|
|
139
|
+
zo.write_text("output.txt", "Hello World")
|
|
140
|
+
|
|
141
|
+
# Non-atomic write to existing directory
|
|
142
|
+
zo.write_text("logs/app.log", log_data, atomic=False, create_dirs=False)
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
**`read_json(path)` / `write_json(path, obj)`** - JSON file operations.
|
|
146
|
+
```python
|
|
147
|
+
# Simple
|
|
148
|
+
config = zo.read_json("settings.json")
|
|
149
|
+
|
|
150
|
+
# Write with custom formatting
|
|
151
|
+
zo.write_json("data.json", {"users": users}, indent=4, atomic=True)
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### File Discovery
|
|
155
|
+
|
|
156
|
+
**`find_files(base_dir, pattern, filter_fn, recursive, max_results)`** - Find files matching criteria.
|
|
157
|
+
```python
|
|
158
|
+
# Simple - find all Python files
|
|
159
|
+
py_files = zo.find_files("./src", pattern="*.py")
|
|
160
|
+
|
|
161
|
+
# Complex - find large log files, limit results
|
|
162
|
+
large_logs = zo.find_files(
|
|
163
|
+
"./logs",
|
|
164
|
+
pattern="*.log",
|
|
165
|
+
filter_fn=lambda p: p.stat().st_size > 1024 * 1024,
|
|
166
|
+
recursive=True,
|
|
167
|
+
max_results=100
|
|
168
|
+
)
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
**`walk_files(base_dir, pattern)`** - Memory-efficient generator for large directories.
|
|
172
|
+
```python
|
|
173
|
+
# Process millions of files without loading all paths
|
|
174
|
+
for path in zo.walk_files("/data", pattern="*.csv"):
|
|
175
|
+
process_file(path)
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### Finder (Fluent API)
|
|
179
|
+
|
|
180
|
+
**`Finder(base_dir)`** - Powerful file finder with fluent builder API.
|
|
181
|
+
```python
|
|
182
|
+
from zerofilesystem import Finder
|
|
183
|
+
|
|
184
|
+
# Find Python files modified in last 7 days
|
|
185
|
+
files = (Finder("./src")
|
|
186
|
+
.patterns("*.py")
|
|
187
|
+
.modified_last_days(7)
|
|
188
|
+
.not_hidden()
|
|
189
|
+
.find())
|
|
190
|
+
|
|
191
|
+
# Complex search with multiple filters
|
|
192
|
+
files = (Finder("./project")
|
|
193
|
+
.patterns("*.py", "*.json")
|
|
194
|
+
.exclude("__pycache__", ".git", "*.pyc")
|
|
195
|
+
.size_min("1KB")
|
|
196
|
+
.size_max("10MB")
|
|
197
|
+
.not_empty()
|
|
198
|
+
.max_depth(5)
|
|
199
|
+
.limit(100)
|
|
200
|
+
.find())
|
|
201
|
+
|
|
202
|
+
# Memory-efficient iteration
|
|
203
|
+
for path in Finder("./logs").patterns("*.log").walk():
|
|
204
|
+
process_log(path)
|
|
205
|
+
|
|
206
|
+
# Quick checks
|
|
207
|
+
count = Finder("./src").patterns("*.py").count()
|
|
208
|
+
has_tests = Finder("./tests").patterns("test_*.py").exists()
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
### Watcher (Fluent API)
|
|
212
|
+
|
|
213
|
+
**`Watcher(base_dir)`** - File system watcher with fluent builder API and debouncing.
|
|
214
|
+
```python
|
|
215
|
+
from zerofilesystem import Watcher, EventType
|
|
216
|
+
|
|
217
|
+
# Simple watch
|
|
218
|
+
watcher = (Watcher("./src")
|
|
219
|
+
.patterns("*.py")
|
|
220
|
+
.on_any(lambda e: print(f"{e.type.name}: {e.path}"))
|
|
221
|
+
.start())
|
|
222
|
+
|
|
223
|
+
# Watch with filtering and debouncing
|
|
224
|
+
watcher = (Watcher("./project")
|
|
225
|
+
.patterns("*.py", "*.json")
|
|
226
|
+
.exclude("__pycache__", ".git")
|
|
227
|
+
.not_hidden()
|
|
228
|
+
.poll_fast() # 0.1 second polling
|
|
229
|
+
.debounce(0.5) # Wait 500ms after last change
|
|
230
|
+
.on_created(handle_new)
|
|
231
|
+
.on_modified(handle_change)
|
|
232
|
+
.on_deleted(handle_remove)
|
|
233
|
+
.start())
|
|
234
|
+
|
|
235
|
+
# Context manager
|
|
236
|
+
with Watcher("./config").patterns("*.yaml").on_any(reload) as w:
|
|
237
|
+
run_server() # Watcher stops automatically on exit
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
### File Locking
|
|
241
|
+
|
|
242
|
+
**`FileLock(path, timeout)`** - Cross-platform advisory file lock.
|
|
243
|
+
```python
|
|
244
|
+
# Simple - blocking lock
|
|
245
|
+
with zo.FileLock("/tmp/myapp.lock"):
|
|
246
|
+
do_critical_work()
|
|
247
|
+
|
|
248
|
+
# With timeout
|
|
249
|
+
try:
|
|
250
|
+
with zo.FileLock("/tmp/myapp.lock", timeout=5.0):
|
|
251
|
+
do_critical_work()
|
|
252
|
+
except TimeoutError:
|
|
253
|
+
print("Could not acquire lock")
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
### Transactions
|
|
257
|
+
|
|
258
|
+
**`FileTransaction()`** - Atomic multi-file operations with rollback.
|
|
259
|
+
```python
|
|
260
|
+
# Simple
|
|
261
|
+
with zo.FileTransaction() as tx:
|
|
262
|
+
tx.write_text("a.txt", "content a")
|
|
263
|
+
tx.write_text("b.txt", "content b")
|
|
264
|
+
|
|
265
|
+
# With explicit control
|
|
266
|
+
tx = zo.FileTransaction()
|
|
267
|
+
try:
|
|
268
|
+
tx.write_text("config.json", new_config)
|
|
269
|
+
tx.copy_file("template.txt", "output.txt")
|
|
270
|
+
tx.commit()
|
|
271
|
+
except Exception:
|
|
272
|
+
tx.rollback()
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
### Archives
|
|
276
|
+
|
|
277
|
+
**`create_zip(source, output)` / `create_tar(source, output)`** - Create archives.
|
|
278
|
+
```python
|
|
279
|
+
# Simple
|
|
280
|
+
zo.create_zip("./project", "backup.zip")
|
|
281
|
+
|
|
282
|
+
# With compression and filtering
|
|
283
|
+
zo.create_tar(
|
|
284
|
+
"./data",
|
|
285
|
+
"archive.tar.gz",
|
|
286
|
+
compression="gz",
|
|
287
|
+
filter_fn=lambda p: p.suffix != ".tmp"
|
|
288
|
+
)
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
**`extract(archive, destination)`** - Auto-detect and extract archives.
|
|
292
|
+
```python
|
|
293
|
+
# Auto-detects format
|
|
294
|
+
zo.extract("backup.zip", "./restored")
|
|
295
|
+
zo.extract("archive.tar.gz", "./restored")
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
### Integrity Checking
|
|
299
|
+
|
|
300
|
+
**`file_hash(path, algo)`** - Compute file hash.
|
|
301
|
+
```python
|
|
302
|
+
# Simple
|
|
303
|
+
sha = zo.file_hash("document.pdf")
|
|
304
|
+
|
|
305
|
+
# With progress callback for large files
|
|
306
|
+
def progress(done, total):
|
|
307
|
+
print(f"\r{done}/{total} bytes", end="")
|
|
308
|
+
|
|
309
|
+
sha = zo.file_hash("large.iso", algo="sha256", progress_callback=progress)
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
**`directory_hash(path)`** - Hash entire directory tree.
|
|
313
|
+
```python
|
|
314
|
+
# Detect any changes in a directory
|
|
315
|
+
before = zo.directory_hash("./config")
|
|
316
|
+
# ... operations ...
|
|
317
|
+
after = zo.directory_hash("./config")
|
|
318
|
+
if before != after:
|
|
319
|
+
print("Configuration changed!")
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
### Directory Operations
|
|
323
|
+
|
|
324
|
+
**`copy_tree(src, dst)` / `move_tree(src, dst)`** - Recursive directory operations.
|
|
325
|
+
```python
|
|
326
|
+
# Simple copy
|
|
327
|
+
result = zo.copy_tree("./src", "./backup")
|
|
328
|
+
print(f"Copied {len(result.copied)} files")
|
|
329
|
+
|
|
330
|
+
# Sync with conflict handling
|
|
331
|
+
result = zo.copy_tree(
|
|
332
|
+
"./new_version",
|
|
333
|
+
"./deploy",
|
|
334
|
+
on_conflict="only_if_newer",
|
|
335
|
+
preserve_metadata=True
|
|
336
|
+
)
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
**`sync_dirs(src, dst, delete_extra)`** - Mirror directories.
|
|
340
|
+
```python
|
|
341
|
+
# One-way sync, optionally delete extra files in destination
|
|
342
|
+
result = zo.sync_dirs("./source", "./mirror", delete_extra=True)
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
### Secure Operations
|
|
346
|
+
|
|
347
|
+
**`secure_delete(path, passes)`** - Overwrite before deletion.
|
|
348
|
+
```python
|
|
349
|
+
# Simple
|
|
350
|
+
zo.secure_delete("sensitive.txt")
|
|
351
|
+
|
|
352
|
+
# Multiple passes with random data
|
|
353
|
+
zo.secure_delete("credentials.json", passes=7, random_data=True)
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
## Development
|
|
357
|
+
|
|
358
|
+
This project uses [uv](https://github.com/astral-sh/uv) for dependency management.
|
|
359
|
+
|
|
360
|
+
```bash
|
|
361
|
+
# Install dependencies
|
|
362
|
+
uv sync
|
|
363
|
+
|
|
364
|
+
# Run tests
|
|
365
|
+
uv run pytest
|
|
366
|
+
|
|
367
|
+
# Linting and formatting
|
|
368
|
+
uv run ruff check .
|
|
369
|
+
uv run ruff format .
|
|
370
|
+
|
|
371
|
+
# Type checking
|
|
372
|
+
uv run mypy src
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
## Further Documentation
|
|
376
|
+
|
|
377
|
+
- [Full API Reference](https://github.com/francescofavi/zerofilesystem/blob/main/docs/API_REFERENCE.md) - Detailed documentation of all public functions, parameters, and return types
|
|
378
|
+
- [Architecture](https://github.com/francescofavi/zerofilesystem/blob/main/docs/ARCHITECTURE.md) - Internal structure, module organization, dependency graph, and design decisions
|
|
379
|
+
- [Functional Analysis](https://github.com/francescofavi/zerofilesystem/blob/main/docs/FUNCTIONAL_ANALYSIS.md) - High-level view of processes, flows, and feature mapping
|
|
380
|
+
|
|
381
|
+
## License
|
|
382
|
+
|
|
383
|
+
[MIT License](https://github.com/francescofavi/zerofilesystem/blob/main/LICENSE)
|