Metadata-Version: 2.4
Name: xfilepy
Version: 0.5.2
Summary: Cross-platform, file handler using native pickers and security models.
Keywords: kivy,android,ios,desktop,files,document picker
Author: Moritz R. Schäfer
Author-email: Moritz R. Schäfer <moritz.schaefer-f91@rub.de>
License-Expression: GPL-3.0-or-later
License-File: LICENSE
Requires-Dist: crossfiledialog>=1.1.0
Requires-Dist: dbus-next>=0.2.3 ; sys_platform == 'linux'
Requires-Dist: typing-extensions>=4.5.0
Requires-Dist: kivy ; extra == 'android'
Requires-Dist: pyjnius ; extra == 'android'
Requires-Dist: kivy ; extra == 'ios'
Requires-Dist: pyobjus ; extra == 'ios'
Maintainer: Moritz R. Schäfer
Maintainer-email: Moritz R. Schäfer <moritz.schaefer-f91@rub.de>
Requires-Python: >=3.11
Project-URL: Repository, https://gitlab.com/M0M097/xfilepy
Project-URL: Documentation, https://xfile-fb4acf.gitlab.io/
Project-URL: Issues, https://gitlab.com/M0M097/xfilepy/-/issues
Provides-Extra: android
Provides-Extra: ios
Description-Content-Type: text/markdown

# xfilepy

---

Cross-platform, file handler using native pickers and security models.

Provides overloads for creating file handlers via native file pickers and
saving/loading persistent access grants. Supported platforms are Android, iOS,
and Desktop (Windows, macOS, Linux, BSDs). On all platforms you can choose
files outside your app's sandbox using the native file picker without asking
the user for broad filesystem permissions. Access to the chosen files is
mediated by platform-specific security models (e.g., SAF on Android,
security-scoped bookmarks on iOS, xdg-desktop-portal (if available) on linux).
This allows your app to write to the files later without re-prompting the user,
even across app restarts.

## Usage
See [API Documentation](https://xfile-fb4acf.gitlab.io/) for full
details. Here is a brief example:

```python
import asyncio

from xfilepy import FileHandler, UserCancelledError

# Open via native picker
try:  # The user may cancel the picker, so we catch that exception
    fh = asyncio.run(FileHandler.create_via_picker())
    with fh.open() as f:
        data = f.read()
        print(data)
except UserCancelledError:
    print("User cancelled the file picker.")

# Save via native "Save as…"
fh = asyncio.run(FileHandler.create_via_save_dialog())
with fh.open(mode="w", encoding="utf-8") as f:
    f.write("Hello, world!")

# Serialize back to store in your settings
persist = fh.to_uri_string()
if persist is None:
    raise RuntimeError("This file handler cannot be persisted.")

# Rehydrate a previously granted URI/bookmark
fh = FileHandler.from_uri_string(persist, require_write=True)
with fh.open(mode="a") as f:
    f.write("Appended line.")

# Best-effort metadata, useful for cache invalidation
stat = fh.stat()
print(stat.display_name, stat.size, stat.mtime_ns)
```

`FileHandler.stat()` returns metadata when the platform/provider exposes it.
Fields such as `size` and `mtime_ns` may be `None`, especially for document
providers on mobile. If you need a reliable content fingerprint, hash the
stream returned by `open("rb")`.
