marvelio 1.0.0
A fully-typed Python client for the Marvel Comics API.
License: MIT
Requires Python: >=3.11

# Marvelio - Unified Marvel Comics API Client

[![Python Version](https://img.shields.io/badge/python-3.8%2B-blue.svg)](https://python.org)
[![License](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
[![PyPI](https://img.shields.io/pypi/v/marvelio.svg)](https://pypi.org/project/marvelio/)

**Marvelio** is a unified, enterprise-grade Python client for the Marvel Comics API that provides everything you need in a single, powerful interface. No more juggling multiple clients or complex setup - everything is integrated and ready to use.

## 🚀 Features

### **Core API Access**
- ✅ **All Marvel API Endpoints** - Characters, Comics, Events, Series, Stories, Creators
- ✅ **Type-Safe Models** - Pydantic models for all API responses
- ✅ **Async/Await Support** - Full asynchronous programming support
- ✅ **Pagination** - Built-in pagination handling

### **Advanced Features**
- ✅ **Response Caching** - Intelligent caching with TTL and size limits
- ✅ **Rate Limiting** - Marvel API compliant rate limiting (per-second, per-hour, per-day)
- ✅ **Retry Logic** - Exponential backoff with jitter for failed requests
- ✅ **Request Logging** - Comprehensive request/response logging
- ✅ **Performance Optimizations** - Connection pooling and HTTP optimizations

### **Enterprise Features**
- ✅ **Search Engine** - Advanced search and filtering capabilities
- ✅ **Data Export** - Export to JSON, CSV, XML, and Markdown formats
- ✅ **Async Iterators** - Efficient processing of large datasets
- ✅ **Batch Processing** - Parallel processing of multiple requests
- ✅ **Metrics Collection** - Performance monitoring and analytics
- ✅ **Configuration Management** - Flexible configuration system
- ✅ **CLI Tool** - Command-line interface for direct API interaction

## 📦 Installation

```bash
pip install marvelio
```

## 🔑 Getting Started

### 1. Get Your API Keys

1. Visit [Marvel Developer Portal](https://developer.marvel.com/)
2. Create an account and get your API keys
3. Set environment variables (optional):

```bash
export MARVEL_PUBLIC_KEY="your_public_key"
export MARVEL_PRIVATE_KEY="your_private_key"
```

### 2. Basic Usage

```python
import asyncio
from marvelio import MarvelUnifiedClient

async def main():
    # Single client with all features enabled
    async with MarvelUnifiedClient("your_public_key", "your_private_key") as client:
        # Get characters
        characters = await client.characters.get_all(limit=10)
        for character in characters:
            print(f"Character: {character.name}")
        
        # Get a specific character
        spiderman = await client.characters.get_by_id(1009610)
        print(f"Spider-Man: {spiderman.name}")

asyncio.run(main())
```

## 🎯 Unified Client Features

### **Single Interface, All Features**

The `MarvelUnifiedClient` provides everything through one interface:

```python
async with MarvelUnifiedClient("public_key", "private_key") as client:
    # All these features work seamlessly together:
    
    # 1. Basic API operations
    characters = await client.characters.get_all(limit=20)
    comics = await client.comics.get_all(limit=20)
    
    # 2. Advanced search
    spider_chars = await client.search_characters("Spider")
    avenger_comics = await client.search_comics("Avengers")
    
    # 3. Data export
    await client.export_characters(characters, "json", "characters.json")
    await client.export_comics(comics, "csv", "comics.csv")
    
    # 4. Async iteration for large datasets
    async for character in client.iterate_characters(limit=1000):
        print(f"Processing: {character.name}")
    
    # 5. Batch processing
    character_ids = [1009610, 1009144, 1009146]  # Spider-Man, A.I.M., Abomination
    characters = await client.batch_get_characters(character_ids)
    
    # 6. Convenience methods
    spiderman = await client.get_character_by_name("Spider-Man")
    avengers_comics = await client.get_comics_by_character(1009610)
    
    # 7. Status and metrics
    cache_stats = client.get_cache_stats()
    rate_limit_status = client.get_rate_limit_status()
    metrics = client.get_metrics()
```

## 🔧 Configuration

### **Environment Variables**
```bash
export MARVEL_PUBLIC_KEY="your_public_key"
export MARVEL_PRIVATE_KEY="your_private_key"
export MARVEL_CACHE_TTL="300"
export MARVEL_RATE_LIMIT_PER_HOUR="100"
export MARVEL_ENABLE_LOGGING="true"
```

### **Configuration File**
Create `marvelio.json`:
```json
{
    "public_key": "your_public_key",
    "private_key": "your_private_key",
    "enable_cache": true,
    "cache_ttl": 300,
    "enable_rate_limiting": true,
    "requests_per_hour": 100,
    "enable_retry": true,
    "max_retry_attempts": 3,
    "enable_logging": true,
    "log_level": "INFO",
    "enable_metrics": true,
    "default_export_dir": "exports"
}
```

### **Programmatic Configuration**
```python
from marvelio import MarvelUnifiedClient, MarvelConfig

config = MarvelConfig(
    public_key="your_public_key",
    private_key="your_private_key",
    enable_cache=True,
    cache_ttl=600,
    enable_rate_limiting=True,
    requests_per_hour=200,
    enable_retry=True,
    max_retry_attempts=5,
    enable_logging=True,
    log_level="DEBUG",
    enable_metrics=True,
    default_export_dir="my_exports"
)

async with MarvelUnifiedClient(config=config) as client:
    # Use client with custom configuration
    pass
```

## 🔍 Advanced Features

### **Search Engine**
```python
async with MarvelUnifiedClient("public_key", "private_key") as client:
    # Search characters by name
    spider_chars = await client.search_characters("Spider", search_type="name")
    
    # Search comics by title
    avenger_comics = await client.search_comics("Avengers", search_type="title")
    
    # Advanced filtering
    characters = await client.characters.get_all(limit=100)
    filtered = client._search_engine.filter_by_name("Man").filter_by_description("superhero").search(characters)
```

### **Data Export**
```python
async with MarvelUnifiedClient("public_key", "private_key") as client:
    characters = await client.characters.get_all(limit=50)
    
    # Export to different formats
    json_file = await client.export_characters(characters, "json", "characters.json")
    csv_file = await client.export_characters(characters, "csv", "characters.csv")
    xml_file = await client.export_characters(characters, "xml", "characters.xml")
    md_file = await client.export_characters(characters, "md", "characters.md")
    
    print(f"Exported to: {json_file}")
```

### **Async Iterators**
```python
async with MarvelUnifiedClient("public_key", "private_key") as client:
    # Process large datasets efficiently
    async for character in client.iterate_characters(batch_size=20, max_items=1000):
        print(f"Processing: {character.name}")
        # Process each character without loading all into memory
```

### **Batch Processing**
```python
async with MarvelUnifiedClient("public_key", "private_key") as client:
    # Get multiple characters in parallel
    character_ids = [1009610, 1009144, 1009146, 1009148, 1009149]
    characters = await client.batch_get_characters(character_ids)
    
    # Get multiple comics in parallel
    comic_ids = [12345, 12346, 12347]
    comics = await client.batch_get_comics(comic_ids)
```

### **Metrics and Monitoring**
```python
async with MarvelUnifiedClient("public_key", "private_key") as client:
    # Get performance metrics
    metrics = client.get_metrics()
    print(f"Total requests: {metrics['total_requests']}")
    print(f"Success rate: {metrics['success_rate']:.2%}")
    print(f"Average response time: {metrics['avg_response_time']:.2f}ms")
    
    # Get cache statistics
    cache_stats = client.get_cache_stats()
    print(f"Cache size: {cache_stats['size']} items")
    print(f"Cache hit rate: {cache_stats['hit_rate']:.2%}")
    
    # Get rate limit status
    rate_limit = client.get_rate_limit_status()
    print(f"Requests remaining: {rate_limit['per_hour']['remaining']}")
```

## 🖥️ Command Line Interface

Marvelio includes a powerful CLI tool for direct API interaction:

```bash
# Get characters
python -m marvelio.cli characters --limit 10

# Search for characters
python -m marvelio.cli characters --search "Spider" --limit 5

# Export to file
python -m marvelio.cli characters --limit 20 --export json --output characters.json

# Get comics
python -m marvelio.cli comics --limit 10

# Get events
python -m marvelio.cli events --limit 5

# Get series
python -m marvelio.cli series --limit 10

# Get stories
python -m marvelio.cli stories --limit 10

# Get creators
python -m marvelio.cli creators --limit 10
```

## 📊 Performance Features

### **Caching**
- **Memory Cache** - In-memory caching with TTL
- **Configurable TTL** - Set cache expiration time
- **Size Limits** - Prevent memory overflow
- **Cache Statistics** - Monitor cache performance

### **Rate Limiting**
- **Marvel API Compliant** - Respects Marvel's rate limits
- **Per-Second Limiting** - Prevents burst requests
- **Per-Hour Limiting** - Manages daily quotas
- **Per-Day Limiting** - Long-term quota management

### **Retry Logic**
- **Exponential Backoff** - Intelligent retry delays
- **Jitter** - Prevents thundering herd
- **Configurable Attempts** - Set max retry attempts
- **Error Handling** - Graceful failure handling

### **Connection Pooling**
- **HTTP/2 Support** - Modern protocol support
- **Connection Reuse** - Efficient connection management
- **Timeout Handling** - Configurable timeouts
- **SSL/TLS** - Secure connections

## 🛠️ Error Handling

Marvelio provides comprehensive error handling:

```python
from marvelio import (
    MarvelAPIError,
    MarvelAuthenticationError,
    MarvelRateLimitError,
    MarvelValidationError
)

async with MarvelUnifiedClient("public_key", "private_key") as client:
    try:
        characters = await client.characters.get_all(limit=10)
    except MarvelAuthenticationError:
        print("Invalid API keys")
    except MarvelRateLimitError:
        print("Rate limit exceeded")
    except MarvelValidationError:
        print("Invalid request parameters")
    except MarvelAPIError as e:
        print(f"API error: {e}")
```

## 📈 Examples

### **Complete Example**
```python
import asyncio
from marvelio import MarvelUnifiedClient

async def comprehensive_example():
    async with MarvelUnifiedClient("public_key", "private_key") as client:
        print("🚀 Marvelio Comprehensive Example")
        print("=" * 50)
        
        # 1. Basic API operations
        print("\n1️⃣ Getting characters...")
        characters = await client.characters.get_all(limit=5)
        for char in characters:
            print(f"   - {char.name} (ID: {char.id})")
        
        # 2. Search functionality
        print("\n2️⃣ Searching for Spider characters...")
        spider_chars = await client.search_characters("Spider", limit=3)
        for char in spider_chars:
            print(f"   - {char.name}")
        
        # 3. Data export
        print("\n3️⃣ Exporting data...")
        json_file = await client.export_characters(characters, "json", "example_characters.json")
        print(f"   Exported to: {json_file}")
        
        # 4. Async iteration
        print("\n4️⃣ Processing characters asynchronously...")
        count = 0
        async for character in client.iterate_characters(batch_size=3, max_items=6):
            count += 1
            print(f"   {count}. {character.name}")
        
        # 5. Batch processing
        print("\n5️⃣ Batch processing...")
        character_ids = [1009610, 1009144, 1009146]  # Spider-Man, A.I.M., Abomination
        batch_chars = await client.batch_get_characters(character_ids)
        for char in batch_chars:
            print(f"   - {char.name}")
        
        # 6. Status information
        print("\n6️⃣ Client status...")
        cache_stats = client.get_cache_stats()
        rate_limit = client.get_rate_limit_status()
        print(f"   Cache: {cache_stats['size']} items")
        print(f"   Rate limit: {rate_limit['per_hour']['remaining']} requests remaining")
        
        print("\n🎉 Example complete!")

asyncio.run(comprehensive_example())
```

### **Real-World Use Cases**

#### **Data Analysis Pipeline**
```python
async def analyze_marvel_data():
    async with MarvelUnifiedClient("public_key", "private_key") as client:
        # Collect data
        all_characters = []
        async for character in client.iterate_characters(max_items=1000):
            all_characters.append(character)
        
        # Analyze data
        superheroes = [c for c in all_characters if "super" in c.description.lower()]
        print(f"Found {len(superheroes)} superheroes")
        
        # Export results
        await client.export_characters(superheroes, "csv", "superheroes.csv")
```

#### **Content Management System**
```python
async def cms_integration():
    async with MarvelUnifiedClient("public_key", "private_key") as client:
        # Get latest comics
        recent_comics = await client.comics.get_all(limit=50)
        
        # Process each comic
        for comic in recent_comics:
            # Get characters in this comic
            characters = await client.get_characters_by_comic(comic.id)
            
            # Export comic data
            comic_data = {
                "comic": comic,
                "characters": characters
            }
            
            # Save to CMS
            await save_to_cms(comic_data)
```

## 🔄 Migration from Legacy Clients

### **From MarvelClient**
```python
# Old way
from marvelio import MarvelClient
client = MarvelClient("public_key", "private_key")
characters = await client.characters.get_all(limit=10)

# New way (same functionality, more features)
from marvelio import MarvelUnifiedClient
async with MarvelUnifiedClient("public_key", "private_key") as client:
    characters = await client.characters.get_all(limit=10)
    # Plus: caching, rate limiting, retry logic, search, export, etc.
```

### **From EnhancedMarvelClient**
```python
# Old way
from marvelio import EnhancedMarvelClient
async with EnhancedMarvelClient("public_key", "private_key") as client:
    characters = await client.characters.get_all(limit=10)
    cache_stats = client.get_cache_stats()

# New way (same features, unified interface)
from marvelio import MarvelUnifiedClient
async with MarvelUnifiedClient("public_key", "private_key") as client:
    characters = await client.characters.get_all(limit=10)
    cache_stats = client.get_cache_stats()
    # Plus: search, export, async iterators, batch processing, etc.
```

## 📚 API Reference

### **MarvelUnifiedClient**

#### **Constructor Parameters**
- `public_key` (str): Marvel API public key
- `private_key` (str): Marvel API private key
- `config` (MarvelConfig): Configuration object
- `timeout` (float): Request timeout in seconds
- `enable_cache` (bool): Enable response caching (default: True)
- `enable_rate_limiting` (bool): Enable rate limiting (default: True)
- `enable_retry` (bool): Enable retry logic (default: True)
- `enable_logging` (bool): Enable logging (default: True)
- `cache_ttl` (int): Cache time-to-live in seconds (default: 300)
- `cache_max_size` (int): Maximum cache size (default: 1000)
- `requests_per_second` (int): Max requests per second (default: 10)
- `requests_per_hour` (int): Max requests per hour (default: 100)
- `requests_per_day` (int): Max requests per day (default: 1000)
- `max_retry_attempts` (int): Maximum retry attempts (default: 3)
- `retry_delay` (float): Initial retry delay (default: 1.0)
- `retry_backoff_factor` (float): Retry backoff factor (default: 2.0)
- `retry_jitter` (bool): Enable retry jitter (default: True)
- `log_level` (str): Logging level (default: "INFO")
- `log_file` (str): Log file path (default: None)
- `enable_metrics` (bool): Enable metrics collection (default: True)
- `enable_search` (bool): Enable search engine (default: True)
- `default_export_dir` (str): Default export directory (default: "exports")

#### **Core Methods**
- `characters`: CharactersEndpoint - Access to character operations
- `comics`: ComicsEndpoint - Access to comic operations
- `events`: EventsEndpoint - Access to event operations
- `series`: SeriesEndpoint - Access to series operations
- `stories`: StoriesEndpoint - Access to story operations
- `creators`: CreatorsEndpoint - Access to creator operations

#### **Search Methods**
- `search_characters(query, search_type="name", limit=20, **kwargs)`: Search characters
- `search_comics(query, search_type="title", limit=20, **kwargs)`: Search comics

#### **Export Methods**
- `export_characters(characters, format="json", output_file=None)`: Export characters
- `export_comics(comics, format="json", output_file=None)`: Export comics

#### **Async Iteration Methods**
- `iterate_characters(batch_size=20, max_items=None, **kwargs)`: Iterate characters
- `iterate_comics(batch_size=20, max_items=None, **kwargs)`: Iterate comics

#### **Batch Processing Methods**
- `batch_get_characters(character_ids)`: Get multiple characters
- `batch_get_comics(comic_ids)`: Get multiple comics

#### **Status Methods**
- `get_cache_stats()`: Get cache statistics
- `get_rate_limit_status()`: Get rate limiting status
- `get_retry_config()`: Get retry configuration
- `get_metrics()`: Get performance metrics
- `get_config()`: Get current configuration

#### **Convenience Methods**
- `get_character_by_name(name)`: Get character by exact name
- `get_comic_by_title(title)`: Get comic by exact title
- `get_characters_by_series(series_id, limit=20)`: Get characters in series
- `get_comics_by_character(character_id, limit=20)`: Get comics with character

## 🤝 Contributing

We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details.

## 📄 License

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

## 🙏 Acknowledgments

- Marvel Entertainment for providing the amazing API
- The Python community for excellent libraries
- All contributors who help make Marvelio better

## 📞 Support

- **Documentation**: [Full Documentation](https://marvelio.readthedocs.io)
- **Issues**: [GitHub Issues](https://github.com/your-username/marvelio/issues)
- **Discussions**: [GitHub Discussions](https://github.com/your-username/marvelio/discussions)

---

**Marvelio** - The unified, enterprise-grade Marvel Comics API client for Python. Everything you need, in one powerful interface. 🚀