# XProfile

A Python package for Xapian-based user profile management with schema validation and automatic index routing.

## Overview

`xprofile` provides the `XProfile` model class, built on top of `xapian_model.base.BaseXapianModel`. It offers a comprehensive schema for storing and managing user profiles in Xapian indexes with automatic routing based on entity ID and profile admin API ID.

## Features

- **Xapian-Based Storage**: Leverages Xapian for efficient full-text search and retrieval
- **Automatic Index Routing**: Routes documents to appropriate indexes using configurable templates
- **Comprehensive Schema**: Includes fields for personal, business, reseller, and other profile types
- **Async API**: Built on top of `xapian_model>=0.4.0` with full async/await support via `httpx`
- **Type-Safe**: Full type hints support for Python 3.12+
- **Well-Documented**: Google-style docstrings throughout the codebase

## Installation

```bash
pip install xapian-profile
```

### Development Installation

**Requirements**: Python 3.12 or higher (specified in `.python-version`)

Clone the repository and install in editable mode:

```bash
git clone git@github.com:Dubalu-Development-Team/xprofile.git
cd xprofile
python3.12 -m venv .venv
source .venv/bin/activate
pip install -e .
```

**Using direnv** (recommended): If you have [direnv](https://direnv.net/) installed, the virtual environment with the correct Python version will be automatically created and activated when you enter the project directory. Just run:

```bash
direnv allow
```

## Usage

### Security Configuration

For security reasons, `INDEX_TEMPLATE` and schema `_foreign` field must be defined in your application code:

```python
from xprofile import XProfile
from xprofile.utils import get_encoded_uuid, get_slug

# Define your own profile identifiers (keep these secret!)
PROFILES_ADMIN_API = "Your Profile Admin API Name"
PROFILE_ADMIN_API_ID = get_encoded_uuid(get_slug(PROFILES_ADMIN_API))
PROFILE_SCHEMA = "Your Profile Schema Name"
PROFILE_SCHEMA_ID = get_encoded_uuid(get_slug(PROFILE_SCHEMA))

# Create a subclass with your configuration
class MyProfile(XProfile):
    INDEX_TEMPLATE = '{entity_id}/{profile_admin_api_id}'

# Configure the schema _foreign field
MyProfile.SCHEMA['_schema']['_foreign'] = f'.schemas/{PROFILE_SCHEMA_ID}'
MyProfile.SCHEMA['_schema']['_meta']['description'] = PROFILE_SCHEMA

# Now use your profile
profile = MyProfile(
    entity_id="your-entity-id",
    profile_admin_api_id=PROFILE_ADMIN_API_ID
)
```

### Basic Usage

```python
# Access the schema
schema = MyProfile.SCHEMA

# The schema includes fields for:
# - Basic info: name, slug, is_active
# - Profile types: personal, business, reseller, etc.
# - Contact info: email, phone with validation
# - Timestamps: created_at, updated_at, deleted_at
# - And more...

# Create, save, and query are async operations (xapian_model 0.3.0+)
profile = await MyProfile.objects.create(
    entity_id="your-entity-id",
    profile_admin_api_id=PROFILE_ADMIN_API_ID,
    name="Example",
)
await profile.save()
results = await MyProfile.objects.filter(query="Example", entity_id="your-entity-id")
```

## Profile Types

XProfile supports multiple profile types:

- `personal` - Personal user profiles
- `business` - Business organization profiles
- `reseller` - Reseller accounts
- `referral` - Referral program participants
- `supplier` - Supplier accounts
- `mashup` - Mashup service profiles
- `affinity` - Affinity group profiles
- `dssupplier` - Data supplier profiles

## Schema

The profile schema includes comprehensive field definitions with:

- Type validation (string, uuid, boolean, date, json, etc.)
- Index configuration (terms, field_terms, field_all, none)
- Required/optional field markers
- Null value handling
- Default values
- Field-specific constraints

Access the complete schema via `XProfile.SCHEMA` or import `get_profile_schema()` from `xprofile.schemas`.

## Project Structure

```
xprofile/
├── src/
│   └── xprofile/
│       ├── __init__.py      # Package exports
│       ├── models.py        # XProfile model class
│       ├── schemas.py       # Schema definitions and constants
│       └── utils.py         # Utility functions (slug, UUID generation)
├── tests/
│   ├── conftest.py          # Test fixtures (session reset, commit mode)
│   └── test_integration.py  # Integration tests against Xapiand
├── pyproject.toml           # Project configuration
├── CLAUDE.md                # Development guidelines
└── README.md                # This file
```

## Development

### Requirements

- Python 3.12 or higher
- `xapian_model>=0.4.0` package (for BaseXapianModel, async API via `pyxapiand>=2.1.0`)

### Code Style

- Line length: 120 characters
- Type hints required for all public functions and methods
- Google-style docstrings for all classes, methods, and functions
- PEP 695 type hints and modern Python syntax

### Testing

Integration tests require a running Xapiand server on `localhost:8880`:

```bash
pip install pytest pytest-asyncio
.venv/bin/pytest tests/test_integration.py -v
```

### Building

The project uses [Hatchling](https://hatch.pypa.io/) as the build backend:

```bash
pip install build
python -m build
```

## License

Copyright (c) 2019-2026 Dubalu International LLC. All Rights Reserved.

See LICENSE for license details.

## Authors

Dubalu Framework Team. See AUTHORS for full list of contributors.

## Links

- GitHub: [Dubalu-Development-Team/xprofile](https://github.com/Dubalu-Development-Team/xprofile)
- Dubalu Framework: [https://dubalu.com](https://dubalu.com)
