# PyRipe

A modern Python client library for the RIPE Database REST API. PyRipe provides a clean, type-safe interface to interact with RIPE's RESTful web services, built with Pydantic for robust data validation and serialization.

## Features

- **Full REST API Coverage**: Support for all RIPE Database operations including search, create, update, and delete
- **Type Safety**: Built with Pydantic models for compile-time type checking and runtime validation
- **Dual Environment Support**: Seamless switching between production (RIPE) and test environments
- **Rich Query Options**: Advanced search capabilities with filtering, tagging, and flags
- **Error Handling**: Comprehensive exception handling with detailed error messages
- **Modern Python**: Requires Python 3.13+ and uses type hints throughout

## Installation

```bash
pip install pyripe
```

Or using Poetry:

```bash
poetry add pyripe
```

## Quick Start

### Initialize the Client

```python
from pyripe import RipeRestApiClient

# Use RIPE production environment
client = RipeRestApiClient(source="RIPE")

# Or use test environment
client = RipeRestApiClient(source="TEST")

# With basic authentication
client = RipeRestApiClient(source="RIPE", basic_auth="your_base64_auth")
```

### Search Objects

```python
# Simple search
result = client.search("192.168.1.1")

# Advanced search with filters
result = client.search(
    query="192.168.1.1",
    sources=["RIPE"],
    type_filters=["inetnum", "route"],
    limit=10,
    offset=0
)
```

### Get Object by Primary Key

```python
from pyripe.models import Attributes, Attribute

# Define the primary key attributes
pk = Attributes(attribute=[
    Attribute(name="inetnum", value="192.168.1.0 - 192.168.1.255")
])

# Get the object
result = client.get_object(pk)
```

### Create a New Object

```python
from pyripe.models import Object, Attributes, Attribute

# Create a new object
new_obj = Object(
    attributes=Attributes(attribute=[
        Attribute(name="inetnum", value="192.168.2.0 - 192.168.2.255"),
        Attribute(name="netname", value="MY-NETWORK"),
        # Add more attributes...
    ])
)

result = client.create_object(new_obj)
```

### Update an Object

```python
# Update existing object
updated_obj = Object(
    attributes=Attributes(attribute=[
        Attribute(name="inetnum", value="192.168.2.0 - 192.168.2.255"),
        Attribute(name="netname", value="MY-UPDATED-NETWORK"),
    ])
)

result = client.update_object(updated_obj)
```

### Delete an Object

```python
# Delete object by primary key
pk = Attributes(attribute=[
    Attribute(name="inetnum", value="192.168.2.0 - 192.168.2.255")
])

result = client.delete_object(pk)
```

## Supported Object Types

PyRipe supports all RIPE Database object types:

### Primary Objects
- `aut-num` - Autonomous System Number
- `domain` - Domain name
- `inet6num` - IPv6 address range
- `inetnum` - IPv4 address range
- `route` - IPv4 route
- `route6` - IPv6 route
- `as-set` - AS set
- `filter-set` - Filter set
- `inet-rtr` - Internet router
- `peering-set` - Peering set
- `route-set` - Route set
- `rtr-set` - Router set

### Secondary Objects
- `as-block` - AS block
- `irt` - Incident Response Team
- `key-cert` - Key certificate
- `mntner` - Maintainer
- `organisation` - Organization
- `person` - Person
- `role` - Role
- `poem` - Poem
- `poetic-form` - Poetic form

## API Reference

### RipeRestApiClient

The main client class for interacting with the RIPE REST API.

#### Methods

- `get_object(pk, unfiltered=False, managed_attributes=False, abuse_contact=False, resource_holder=False)` - Retrieve a specific object
- `search(query, sources=[], inverse_attributes=None, include_tags=None, exclude_tags=None, type_filters=None, flags=None, managed_attributes=False, abuse_contact=False, resource_holder=False, limit=None, offset=None)` - Search for objects
- `create_object(obj)` - Create a new object
- `update_object(obj)` - Update an existing object
- `delete_object(pk)` - Delete an object

### Data Models

All API responses and requests use Pydantic models for type safety and validation:

- `WhoisResources` - Main response container
- `Object` - RIPE database object
- `Attributes` - Object attributes
- `Attribute` - Individual attribute
- And many more...

## Error Handling

PyRipe provides specific exception types for different error scenarios:

```python
from pyripe.exceptions import (
    RipeRestApiError,
    RipeRestApiServerError,
    RipeRestApiInvalidPrimaryKeyError,
    RipeRestApiUnexpectedResponseError
)

try:
    result = client.search("invalid-query")
except RipeRestApiServerError as e:
    print(f"Server error: {e.http_status}")
    print(f"Error messages: {e.ripe_messages}")
except RipeRestApiInvalidPrimaryKeyError:
    print("Invalid primary key provided")
except RipeRestApiError as e:
    print(f"An error occurred: {e}")
```

## API Endpoints

- **Production**: `https://rest.db.ripe.net`
- **Test**: `https://rest-test.db.ripe.net`

For more information about the RIPE REST API, visit the [official documentation](https://docs.db.ripe.net/Update-Methods/RESTful-API).

## Requirements

- Python 3.13+
- requests >= 2.32.5
- pydantic >= 2.12.5

## License

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

## Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

## Support

For issues and questions:
- [GitHub Issues](https://github.com/rdp-studio/pyripe/issues)
- [RIPE Database Documentation](https://docs.db.ripe.net/Update-Methods/RESTful-API)

## Acknowledgments

- Built with [Pydantic](https://docs.pydantic.dev/)
- Uses [Requests](https://requests.readthedocs.io/) for HTTP communication
