Skip to main content

Modern async Python wrapper for rclone

Project description

rclone-adapter

PyPI Downloads License Python Version Build Status

A modern, async-first Python wrapper for rclone with comprehensive type hints, progress tracking, and structured logging.

Overview

rclone-adapter provides a Pythonic, async-first interface to rclone for cloud storage operations. Instead of running shell commands, you can use intuitive Python methods and async/await patterns to interact with cloud storage providers.

Key Features

  • ๐Ÿš€ Async-First Design: Full async/await support with AsyncIterator for streaming progress
  • ๐Ÿ“ฆ Bundled rclone: Latest rclone binary included in wheels for all platforms
  • ๐ŸŽฏ Type Safe: Comprehensive type hints for IDE autocomplete and type checking
  • ๐Ÿ“Š Progress Tracking: Real-time progress events with adaptive interval throttling
  • ๐Ÿ”ง Full Command Support: All 54 rclone subcommands with auto-generated type-safe options
  • ๐Ÿ“ Structured Logging: Built-in structured logging with structlog
  • ๐ŸŒˆ Pretty Output: Terminal-friendly progress bars and formatted output with rich
  • โš™๏ธ Flexible Configuration: Support for environment variables and rclone config files
  • ๐ŸŽ“ Well Documented: Comprehensive CLAUDE.md guide for developers

Installation

pip install rclone-adapter

Platform-Specific Details

Linux (x86_64, ARM64):

  • Wheels include bundled rclone binaries - no separate installation needed
  • pip install rclone-adapter is all you need!

macOS, Windows:

  • Source distribution (sdist) available, but no pre-built wheels yet
  • Install rclone separately: https://rclone.org/install/
  • Then: pip install rclone-adapter

Using system rclone (any platform):

  • If you prefer your system's rclone installation, it will be used automatically
  • The bundled binary is used as a fallback if system rclone is not found

Supported Python Versions

  • Python 3.10, 3.11, 3.12, 3.13, 3.14+

Quick Start

Async Usage (Recommended)

import asyncio
from rclone import RClone, RCloneConfig

async def main():
    # Create config (uses bundled rclone binary automatically)
    config = RCloneConfig(
        env_vars={
            "RCLONE_S3_PROVIDER": "AWS",
            "RCLONE_S3_REGION": "us-west-2",
        }
    )

    # Initialize client
    rc = RClone(config)

    # Simple API - returns only final result
    result = await rc.sync(source="/local/path", dest="s3:mybucket/path")
    print(f"Transferred: {result.files_transferred} files ({result.bytes_transferred} bytes)")

    # Streaming API - get real-time progress events
    async for event in rc.sync_stream(source="/local", dest="s3:mybucket/"):
        if hasattr(event, 'progress'):
            print(f"Progress: {event.progress:.1%}")
        elif hasattr(event, 'message'):
            print(f"Info: {event.message}")

asyncio.run(main())

Sync Usage

from rclone import RClone

# For non-async code
rc = RClone()

# Blocking wrapper
result = rc.sync_blocking(
    source="/local/path",
    dest="s3:mybucket/path"
)

if result.success:
    print(f"โœ“ Success! Transferred {result.files_transferred} files")
else:
    print(f"โœ— Failed with {len(result.errors)} errors")

Usage Examples

Copy with Progress Tracking

import asyncio
from rclone import RClone, ProgressEvent, ErrorEvent

async def copy_with_progress():
    rc = RClone()

    async for event in rc.copy_stream(
        source="/source/path",
        dest="/dest/path"
    ):
        if isinstance(event, ProgressEvent):
            print(f"Progress: {event.bytes_transferred:,} / {event.total_bytes:,} bytes")
        elif isinstance(event, ErrorEvent):
            print(f"Error: {event.message}")

asyncio.run(copy_with_progress())

Using Environment Variables

from rclone import RClone, RCloneConfig

config = RCloneConfig(
    env_vars={
        "RCLONE_S3_PROVIDER": "AWS",
        "RCLONE_S3_ACCESS_KEY_ID": "your-key",
        "RCLONE_S3_SECRET_ACCESS_KEY": "your-secret",
    }
)

rc = RClone(config)
result = await rc.sync(source="s3:bucket1/", dest="s3:bucket2/")

Using rclone Config File

from pathlib import Path
from rclone import RClone, RCloneConfig

config = RCloneConfig(
    config_file=Path("~/.config/rclone/rclone.conf")
)

rc = RClone(config)
result = await rc.sync(source="gdrive:/", dest="/local/backup/")

Architecture

Core Design

  • Async-First: All main operations are async-first with sync wrappers available
  • Event Streaming: Operations yield events for progress, errors, and completion
  • Type Safe: Pydantic v2 for configuration validation, dataclass models for results
  • Modular: Separate modules for client, models, process management, and parsing

Bundled Binary

The wheels include platform-specific rclone binaries:

  • Linux x86_64, ARM64
  • macOS Intel, Apple Silicon
  • Windows x86_64

The find_rclone_binary() utility automatically selects the correct binary for your platform.

Generated Command Options

All 54 rclone subcommands are supported with auto-generated Pydantic models:

  • SyncOptions, CopyOptions, MoveOptions - File transfer operations
  • LsOptions, LsdOptions, LsjsonOptions - Listing operations
  • CheckOptions, ChecksumOptions - Verification operations
  • And more!

Development

Setting Up Development Environment

# Clone and install in editable mode
git clone https://github.com/dirkpetersen/rclone-adapter.git
cd rclone-adapter

# Install with development dependencies
pip install -e ".[dev]"

# Run tests
pytest tests/ -v

# Run linting
ruff check rclone/ tests/
mypy rclone/ --strict

Project Structure

rclone-adapter/
โ”œโ”€โ”€ rclone/
โ”‚   โ”œโ”€โ”€ __init__.py          # Main package exports
โ”‚   โ”œโ”€โ”€ client.py            # RClone async client
โ”‚   โ”œโ”€โ”€ models.py            # Pydantic models (config, events, results)
โ”‚   โ”œโ”€โ”€ process.py           # Subprocess management
โ”‚   โ”œโ”€โ”€ parser.py            # rclone log parsing
โ”‚   โ”œโ”€โ”€ util.py              # Utility functions
โ”‚   โ”œโ”€โ”€ exceptions.py        # Exception hierarchy
โ”‚   โ”œโ”€โ”€ py.typed             # PEP 561 marker for type hints
โ”‚   โ”œโ”€โ”€ bin/                 # Platform-specific rclone binaries
โ”‚   โ””โ”€โ”€ _generated/          # Auto-generated command options
โ”œโ”€โ”€ tests/                   # Test suite
โ”œโ”€โ”€ examples/                # Usage examples
โ”œโ”€โ”€ CLAUDE.md               # Developer guide
โ””โ”€โ”€ README.md               # This file

Running Tests

# All tests
pytest tests/

# Unit tests only (no integration tests)
pytest tests/ -m "not integration"

# With coverage
pytest tests/ --cov=rclone --cov-report=html

# Specific test file
pytest tests/test_client.py -v

API Reference

RClone Client

Main async client for rclone operations.

class RClone:
    async def sync(
        source: str,
        dest: str,
        options: SyncOptions | None = None
    ) -> SyncResult

    async def sync_stream(
        source: str,
        dest: str,
        options: SyncOptions | None = None
    ) -> AsyncIterator[ProgressEvent | ErrorEvent | SyncResult]

    def sync_blocking(
        source: str,
        dest: str,
        options: SyncOptions | None = None
    ) -> SyncResult

    # Similar methods for: copy, move, ls, lsd, check, etc.

RCloneConfig

Configuration for the client with validation.

config = RCloneConfig(
    config_file=Path("~/.config/rclone/rclone.conf"),  # Optional
    env_vars={                                           # Optional
        "RCLONE_S3_PROVIDER": "AWS",
        "RCLONE_S3_REGION": "us-west-2",
    },
    rclone_path="/usr/bin/rclone",  # Optional, auto-detected
    log_level="INFO",                # Optional
)

Events

Operations yield typed events for progress and errors:

class ProgressEvent:
    bytes_transferred: int
    total_bytes: int
    progress: float  # 0.0 to 1.0
    transfer_rate: int  # bytes/sec
    eta_seconds: Optional[int]
    current_file: Optional[str]

class ErrorEvent:
    message: str
    file: Optional[str]
    error_category: str  # "network", "permission", "not_found", etc.
    is_retryable: bool

Results

Operations return typed result objects:

class SyncResult:
    success: bool
    return_code: int
    bytes_transferred: int
    files_transferred: int
    errors: list[ErrorEvent]
    duration_seconds: float
    stats: dict  # Full rclone stats

Contributing

Contributions are welcome! Please:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Make your changes with tests
  4. Run linting and type checking:
    ruff check --fix rclone/ tests/
    mypy rclone/ --strict
    pytest tests/
    
  5. Commit your changes (git commit -m 'Add amazing feature')
  6. Push to your branch (git push origin feature/amazing-feature)
  7. Open a Pull Request

See CLAUDE.md for detailed development guidance.

License

MIT License - see LICENSE file for details.

Support

Related Projects

  • rclone - The main rclone project
  • python-pwalk - Modern Python packaging template
  • froster - Previous rclone wrapper (being replaced)

Changelog

See CHANGELOG.md for release history and version changes.


Status: Alpha (0.1.0) - API is stable but may receive enhancements before 1.0 release.

Latest Release: v0.1.0 (2025-10-19)

  • Initial public release on PyPI
  • Full async/await support
  • All 54 rclone subcommands
  • Linux wheels with bundled rclone binaries
  • Comprehensive test suite and CI/CD

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

rclone_adapter-0.2.0.tar.gz (23.2 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

rclone_adapter-0.2.0-py3-none-any.whl (23.3 MB view details)

Uploaded Python 3

File details

Details for the file rclone_adapter-0.2.0.tar.gz.

File metadata

  • Download URL: rclone_adapter-0.2.0.tar.gz
  • Upload date:
  • Size: 23.2 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for rclone_adapter-0.2.0.tar.gz
Algorithm Hash digest
SHA256 45f7df9b9019ed46f7e29fd29a3997194a57a5d50b0a23859cd591138bd181d9
MD5 6911cfe25fabdd69d1ec0a67f09b9380
BLAKE2b-256 665b41eb6130a7b7a96604030c3031cea0a89c91e91ff9f1367b9ffaa5c805ed

See more details on using hashes here.

Provenance

The following attestation bundles were made for rclone_adapter-0.2.0.tar.gz:

Publisher: publish-pypi.yml on dirkpetersen/rclone-adapter

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file rclone_adapter-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: rclone_adapter-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 23.3 MB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for rclone_adapter-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 dd6efd116a17180916feebc0526c274fd0cf5191e403afab6497d48e4258136c
MD5 40a2f33c23581d8e1e129220ad9afc01
BLAKE2b-256 6bbceebd03e25188540a3e03197438204ac522c80a3d012e47d3d234fc1f5210

See more details on using hashes here.

Provenance

The following attestation bundles were made for rclone_adapter-0.2.0-py3-none-any.whl:

Publisher: publish-pypi.yml on dirkpetersen/rclone-adapter

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page