Metadata-Version: 2.4
Name: rPickle
Version: 0.4.0
Summary: A safe and efficient Python serialization library
Author-email: Rainwalker <lmx1w3r@outlook.com>
License: MIT
Keywords: serialization,pickle,binary
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Description-Content-Type: text/markdown
License-File: LICENSE
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == "dev"
Requires-Dist: pytest-benchmark; extra == "dev"
Dynamic: license-file

# rPickle

A safe and efficient Python serialization library.

## Features

  - 🔒 **Safe** - No arbitrary code execution, unlike `pickle`
  - ⚡ **Fast** - Optimized binary format
  - 📦 **Compact** - Small serialized size
  - 🔄 **Circular references** - Handles self-referential structures
  - 🎨 **Extensible** - Custom type support via extensions

## 🔒 Safety

rPickle is **safe** in the sense that it **does not execute arbitrary code** during deserialization.

Unlike `pickle` (which can call arbitrary functions during `loads()`), rPickle only reconstructs data structures.  
It does not use `__reduce__()`, no implicit imports, and no function calls.

> ✅ `rPickle.loads(data)` does not execute any code — it only restores data.  
❌ `pickle.loads(data)` may execute arbitrary code defined in `__reduce__`.

**However, safety is not absolute:**
  - If you use custom extensions (`Extension`), you are responsible for the code you provide — the library author is not liable.
  - rPickle does not encrypt data or prevent tampering. If you need integrity or confidentiality, take additional measures.

## Requirements

  - Python 3.15+ (preview)
  - Python 3.10+ (full)

## Installation

```bash
pip install rPickle
```

## Quick Start
```python
import rPickle

# Serialize
data = {'name': 'Alice', 'scores': [95, 87, 92]}
packed = rPickle.dumps(data)

# Deserialize
restored = rPickle.loads(packed)
print(restored)  # {'name': 'Alice', 'scores': [95, 87, 92]}
```

## API

### Core Function

| Function        | Description               |
| --------------- | ------------------------- |
| dumps(obj)      | Serialize object to bytes |
| loads(data)     | Deserialize from bytes    |
| dump(obj, file) | Serialize to file         |
| load(file)      | Deserialize from file     |

## Extensions

```python
from datetime import datetime

data = {'created': datetime.now()}
packed = rPickle.dumps(data, extensions=rPickle.ext.datetime_ext)
restored = rPickle.loads(packed, extensions=rPickle.ext.datetime_ext)
```

### Custom Extensions

Add support for your own types using the `extensions` parameter.

```python
from datetime import datetime

# 1. Define dump function (type → bytes)
def dump_datetime(dt: datetime) -> bytes:
    return dt.timestamp().to_bytes(8, 'little')

# 2. Define load function (bytes → type)
def load_datetime(data: bytes) -> datetime:
    timestamp = int.from_bytes(data, 'little')
    return datetime.fromtimestamp(timestamp)

# 3. Register your extension
my_extensions = rPickle.ext.Extension(typ=datetime, load_func=load_datetime, dump_func=dump_datetime)

# 4. Use it
data = {'created': datetime.now()}
packed = rPickle.dumps(data, extensions=my_extensions)
restored = rPickle.loads(packed, extensions=my_extensions)
```

## Supported Types
  - `None`, `bool`, `int`, `float`, `complex`, `str`
  - `bytes`, `bytearray`
  - `list`, `tuple`, `set`, `frozenset`
  - `dict`, `frozendict` (Python 3.15+)
  - `range`, `slice`
  - `Ellipsis`, `NotImplemented`
  - `sentinel` (Python 3.15+)
  - Custom types

## Built-in Extensions

rPickle comes with ready-to-use extensions for common types:
see the list below.


| Name           | Type                 |
|----------------|----------------------|
| `datetime_ext` | `datetime.datetime`  |
| `Decimal_ext`  | `decimal.Decimal`    |
| `UUID_ext`     | `uuid.UUID`          |
| `Fraction_ext` | `fractions.Fraction` |

## License

MIT
