Metadata-Version: 2.4
Name: ouroboros_random
Version: 1.0.0
Summary: Deterministic & secure random generation toolkit — reproducible PRNG for simulation/testing and CSPRNG for security-sensitive material.
Author: Flavio Brandolini
License: Copyright (c) 2026 Flavio Brandolini
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
Project-URL: Homepage, https://github.com/FlavioBrandolini91/ouroboros_random
Project-URL: Repository, https://github.com/FlavioBrandolini91/ouroboros_random
Project-URL: Bug Tracker, https://github.com/FlavioBrandolini91/ouroboros_random/issues
Project-URL: Changelog, https://github.com/FlavioBrandolini91/ouroboros_random/blob/main/CHANGELOG.md
Keywords: random,rng,prng,csprng,seed,deterministic,reproducible,simulation,testing,entropy,toolkit,poisson,gaussian,streaming,ouroboros
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Science/Research
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: License :: OSI Approved :: MIT License
Classifier: Typing :: Typed
Classifier: Operating System :: OS Independent
Classifier: Topic :: Scientific/Engineering
Classifier: Topic :: Security
Classifier: Topic :: Software Development :: Libraries
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Software Development :: Testing
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Provides-Extra: test
Requires-Dist: pytest>=7.0; extra == "test"
Requires-Dist: pytest-cov; extra == "test"
Provides-Extra: dev
Requires-Dist: ouroboros_random[test]; extra == "dev"
Requires-Dist: ruff; extra == "dev"
Requires-Dist: mypy; extra == "dev"
Dynamic: license-file

# ouroboros_random

A professional, zero-dependency, production-ready random generation toolkit for Python.  
Designed for deterministic simulation, reproducible testing, temporal traffic synthesis, and security-grade entropy — all in a single, auditable library.

`ouroboros_random` provides two complementary classes with a strict separation of concerns:

| Class | Engine | Purpose |
|---|---|---|
| `BaseRandom` | Mersenne Twister (MT19937) seeded PRNG | Simulation, testing, benchmarking, statistical analysis |
| `BaseEntropy` | OS CSPRNG via `secrets` | Tokens, keys, UUIDs, session IDs, secure bytes |

> **Why two classes?**  
> Mixing reproducible PRNG output with security-sensitive material is a common source of bugs.  
> This separation makes code review trivial: `BaseRandom` = simulation; `BaseEntropy` = security.

---

## Table of Contents

1. [Features](#features)
   - [BaseRandom — Deterministic Generator](#baserandom--deterministic-generator)
   - [BaseEntropy — Secure Generator](#baseentropy--secure-generator)
   - [Typed Exception Hierarchy](#typed-exception-hierarchy)
2. [Installation](#installation)
3. [Python Compatibility](#python-compatibility)
4. [Usage Examples](#usage-examples)
   - [Basic deterministic generation](#basic-deterministic-generation)
   - [Weighted selection](#weighted-selection)
   - [Sampling without replacement](#sampling-without-replacement)
   - [Enum support](#enum-support)
   - [State snapshots for replay](#state-snapshots-for-replay)
   - [Base64 snapshot (portable)](#base64-snapshot-portable)
   - [Secure generation (tokens, keys)](#secure-generation-tokens-keys)
   - [Temporal traffic synthesis](#temporal-traffic-synthesis)
5. [Architecture](#architecture)
6. [Design Principles](#design-principles)
7. [Testing](#testing)
8. [Development Dependencies](#development-dependencies)
9. [Security Considerations](#security-considerations)
10. [License](#license)

---

## Features

### BaseRandom — Deterministic Generator

- **Full reproducibility** — same seed + same call sequence = identical output, cross-platform
- **State snapshots** — `snapshot()` / `restore()` and Base64 serialization for replay
- **Core primitives** — `random()`, `randint()`, `uniform()`, `gauss()`, `choice()`, `choices()`
- **Weighted & unweighted selection** — `weighted_choice()`, `sample()` (without replacement), `shuffle()`
- **Typed generators** — `int`, `long`, `float`, `double`, `byte`, `bytes`, `boolean`, `date`, `time`, `datetime`, `epoch_millis`
- **Geo generators** — `latitude`, `longitude`, `geopoint`
- **Identifiers & strings** — `deterministic_hex_id`, `generate_string`, `generate_base64_string`, `generate_base64_utf8_text`
- **Network generators** — `IPv4`, `IPv6`, `MAC address`, `hostname` (all deterministic, no OS entropy)
- **Enum support** — `generate_enum()` picks a deterministic member from any `enum.Enum` subclass
- **Temporal distributions (streaming)** — `stream_uniform`, `stream_poisson`, `stream_gaussian`, `stream_exponential`, `stream_burst`
- **Dependency-free Poisson** — exact Knuth algorithm + normal approximation fallback, no NumPy required

### BaseEntropy — Secure Generator

- **UUIDv4** — `secure_uuid()`
- **Tokens** — `secure_token_urlsafe()`, `secure_token_hex()`
- **Bytes** — `secure_bytes()`
- **Integers** — `secure_int(a, b)` via rejection sampling
- **Strings** — `secure_string()` with custom alphabets
- **Network** — `secure_ipv4()`, `secure_ipv6()`, `secure_mac()`

### Typed Exception Hierarchy

All exceptions inherit from `RandomToolkitError` for clean `except` handling:

```
RandomToolkitError
├── InvalidParameterError
├── EmptyPopulationError
├── InsufficientPopulationError
├── StateRestorationError
└── GenerationError
```

---

## Installation

### Local (development)
```bash
pip install -e .
```

### From Git repository
```bash
pip install git+https://your.git.server/ouroboros_random.git
```

### Inside CI/CD (Docker / Jenkins)
```bash
pip install git+https://your.git.server/ouroboros_random.git
```

---

## Python Compatibility

**Python 3.9 - 3.13**

Zero runtime dependencies. The entire library uses only the Python standard library.

---

## Usage Examples

### Basic deterministic generation

```python
from ouroboros_random import BaseRandom

rng = BaseRandom(seed=42)

rng.generate_int(0, 100)          # deterministic integer
rng.generate_float(0.0, 1.0)      # deterministic float
rng.generate_boolean(p_true=0.7)  # biased coin flip
rng.generate_string(16)           # alphanumeric string
rng.generate_ipv4(kind="private") # RFC1918 address
rng.generate_geopoint()           # (lat, lon) tuple
rng.deterministic_hex_id(32)      # hex identifier
```

### Weighted selection

```python
from ouroboros_random import BaseRandom

rng = BaseRandom(seed=99)

items = ["critical", "warning", "info", "debug"]
weights = [1.0, 5.0, 20.0, 74.0]

rng.weighted_choice(items, weights)  # probabilistic but deterministic
```

### Sampling without replacement

```python
rng.sample(["A", "B", "C", "D", "E"], k=3)  # 3 unique elements
rng.shuffle([1, 2, 3, 4, 5])                  # new shuffled list (original untouched)
```

### Enum support

```python
import enum
from ouroboros_random import BaseRandom

class Color(enum.Enum):
    RED = 1
    GREEN = 2
    BLUE = 3

rng = BaseRandom(seed=7)
rng.generate_enum(Color)  # deterministic Color member
```

### State snapshots for replay

```python
from ouroboros_random import BaseRandom

rng = BaseRandom(seed=42)
snap = rng.snapshot()

a = [rng.randint(0, 100) for _ in range(10)]

rng.restore(snap)
b = [rng.randint(0, 100) for _ in range(10)]

assert a == b  # identical sequences
```

### Base64 snapshot (portable)

```python
encoded = rng.snapshot_b64()
# ... persist / transmit ...
rng.restore_b64(encoded)
```

### Secure generation (tokens, keys)

```python
from ouroboros_random import BaseEntropy

BaseEntropy.secure_uuid()                # UUIDv4
BaseEntropy.secure_token_urlsafe(32)     # URL-safe token
BaseEntropy.secure_token_hex(32)         # hex token
BaseEntropy.secure_bytes(64)             # raw bytes
BaseEntropy.secure_int(1, 1_000_000)     # secure integer
BaseEntropy.secure_string(24)            # random string
BaseEntropy.secure_ipv4(kind="global")   # secure public IPv4
BaseEntropy.secure_mac(uppercase=True)   # secure MAC address
```

### Temporal traffic synthesis

```python
from datetime import datetime
from ouroboros_random import BaseRandom

rng = BaseRandom(seed=1)

# 7-day window, 5-minute granularity
intervals = BaseRandom.generate_intervals(
    period_days=7,
    granularity_minutes=5,
    now=datetime(2026, 1, 1),
)

# Uniform distribution: 10k events
timestamps = list(rng.stream_uniform(intervals, 10_000, jitter_ms=60_000))

# Poisson distribution: ~3 events per bin
timestamps = list(rng.stream_poisson(intervals, mean_per_interval=3.0))

# Gaussian-shaped: peak at center
timestamps = list(rng.stream_gaussian(intervals, 10_000))

# Exponential decay: front-loaded
timestamps = list(rng.stream_exponential(intervals, 10_000, scale=0.5))

# Burst: 80% of events in a narrow spike
timestamps = list(rng.stream_burst(intervals, 10_000, burst_ratio=0.8, burst_width=0.05))
```

---

## Architecture

```
ouroboros_random/
├── __init__.py       # Public API surface & __all__
├── base.py           # Backward-compatible re-export module
├── _types.py         # Type aliases (Millis) and type variables
├── _config.py        # PoissonPolicy configuration dataclass
├── _state.py         # PRNG state management mixin (snapshot / restore)
├── _core.py          # Core PRNG primitives mixin (random, choice, sample, ...)
├── _generators.py    # Typed generators mixin (int, float, bool, date, geo, enum)
├── _strings.py       # String & identifier generators mixin (hex, base64, ...)
├── _network.py       # Network generators mixin (IPv4, IPv6, MAC, hostname)
├── _temporal.py      # Temporal distributions mixin (stream_*, Poisson, intervals)
├── _prng.py          # BaseRandom — composes all mixins into a single class
├── _entropy.py       # BaseEntropy — CSPRNG-backed secure generator
├── exceptions.py     # Typed exception hierarchy
├── py.typed          # PEP 561 marker for type checkers
tests/
├── conftest.py       # Shared fixtures (seeded BaseRandom)
├── test_core.py      # Core primitives & selection tests
├── test_state.py     # State snapshot & restore tests
├── test_generators.py# Typed generators tests
├── test_strings.py   # String & identifier tests
├── test_network.py   # Network address generation tests
├── test_temporal.py  # Temporal distribution & Poisson tests
├── test_entropy.py   # BaseEntropy (secure) tests
├── test_exceptions.py# Exception hierarchy tests
└── test_backward_compat.py  # Import compatibility tests
```

---

## Design Principles

1. **Zero dependencies** — stdlib only; no NumPy, no SciPy, no external C extensions.
2. **Strict PRNG/CSPRNG separation** — impossible to accidentally use a non-secure generator for secrets.
3. **Full reproducibility** — seed to deterministic output. State snapshots for checkpoint/replay.
4. **Mixin-based architecture** — each domain (core, generators, network, temporal, strings, state) lives in its own module with a focused mixin class, composed into `BaseRandom` via multiple inheritance.
5. **Streaming architecture** — temporal distributions yield timestamps lazily (`Iterator`), enabling memory-efficient processing of millions of events.
6. **Typed exceptions** — catch `RandomToolkitError` for the entire family, or discriminate specific failure modes.
7. **Backward compatibility** — `base.py` re-exports all symbols so existing `from ouroboros_random.base import ...` code keeps working.
8. **Python 3.9+ compatibility** — uses `from __future__ import annotations` and `typing` aliases for broad support.

---

## Testing

```bash
# Install dev dependencies
pip install -e ".[dev]"

# Run tests
pytest -v

# With coverage
pytest --cov=ouroboros_random --cov-report=term-missing

# Type checking
mypy ouroboros_random/
```

---

## Development Dependencies

```
pytest >= 7.0
pytest-cov
ruff
mypy
```

---

## Security Considerations

| Aspect | `BaseRandom` | `BaseEntropy` |
|---|---|---|
| Engine | MT19937 (not crypto-safe) | OS CSPRNG (`secrets`) |
| Predictability | **Yes** — 624 outputs allow full state recovery | **No** — computationally infeasible |
| Use for tokens/keys | Never | Designed for this |
| Reproducibility | Full (seed-based) | Not applicable (by design) |
| State serialization | `snapshot_b64()` — uses `pickle` (trusted sources only) | N/A |

> **pickle warning**: `restore_b64()` deserializes with `pickle`. Never restore snapshots from untrusted sources.

---

## License

This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.

---

## Authors

Flavio Brandolini
