|
| 1 | +# Copilot Instructions for Mixpanel Python SDK |
| 2 | + |
| 3 | +## Project Overview |
| 4 | +This is the official Mixpanel Python library for server-side analytics integration. It provides event tracking, user profile updates, group analytics, and feature flags with both synchronous and asynchronous support. |
| 5 | + |
| 6 | +## Core Architecture |
| 7 | + |
| 8 | +### Main Components |
| 9 | +- **Mixpanel class** (`mixpanel/__init__.py`): Primary entry point supporting both sync/async operations |
| 10 | +- **Consumer pattern**: `Consumer` (immediate) vs `BufferedConsumer` (batched, default 50 messages) |
| 11 | +- **Feature Flags**: Local (client-side evaluation) vs Remote (server-side) providers in `mixpanel/flags/` |
| 12 | +- **Dual sync/async API**: Most flag operations have both variants (e.g., `get_variant`/`aget_variant`) |
| 13 | + |
| 14 | +### Key Design Patterns |
| 15 | +```python |
| 16 | +# Context manager pattern for resource cleanup |
| 17 | +async with Mixpanel(token, local_flags_config=config) as mp: |
| 18 | + await mp.local_flags.astart_polling_for_definitions() |
| 19 | + |
| 20 | +# Consumer customization for delivery behavior |
| 21 | +mp = Mixpanel(token, consumer=BufferedConsumer()) |
| 22 | + |
| 23 | +# Custom serialization via DatetimeSerializer |
| 24 | +mp = Mixpanel(token, serializer=CustomSerializer) |
| 25 | +``` |
| 26 | + |
| 27 | +## Development Workflows |
| 28 | + |
| 29 | +### Testing |
| 30 | +- **Run tests**: `pytest` (current Python) or `python -m tox` (all supported versions 3.9-3.13) |
| 31 | +- **Async testing**: Uses `pytest-asyncio` with `asyncio_mode = "auto"` in pyproject.toml |
| 32 | +- **HTTP mocking**: `responses` library for sync code, `respx` for async code |
| 33 | +- **Test structure**: `test_*.py` files in root and package directories |
| 34 | + |
| 35 | +### Building & Publishing |
| 36 | +```bash |
| 37 | +pip install -e .[test,dev] # Development setup |
| 38 | +python -m build # Build distributions |
| 39 | +python -m twine upload dist/* # Publish to PyPI |
| 40 | +``` |
| 41 | + |
| 42 | +## Important Conventions |
| 43 | + |
| 44 | +### API Endpoints & Authentication |
| 45 | +- Default endpoint: `api.mixpanel.com` (override via `api_host` parameter) |
| 46 | +- **API secret** (not key) required for `import` and `merge` endpoints |
| 47 | +- Feature flags use `/decide` endpoint; events use `/track` |
| 48 | + |
| 49 | +### Error Handling & Retries |
| 50 | +- All consumers use urllib3.Retry with exponential backoff (default 4 retries) |
| 51 | +- `MixpanelException` for domain-specific errors |
| 52 | +- Feature flag operations degrade gracefully with fallback values |
| 53 | + |
| 54 | +### Version & Dependencies Management |
| 55 | +- Version defined in `mixpanel/__init__.py` as `__version__` |
| 56 | +- Uses Pydantic v2+ for data validation (`mixpanel/flags/types.py`) |
| 57 | +- json-logic library for runtime flag evaluation rules |
| 58 | + |
| 59 | +## Feature Flag Specifics |
| 60 | + |
| 61 | +### Local Flags (Client-side evaluation) |
| 62 | +- Require explicit polling: `start_polling_for_definitions()` or context manager |
| 63 | +- Default 60s polling interval, configurable via `LocalFlagsConfig` |
| 64 | +- Runtime evaluation using json-logic for dynamic targeting |
| 65 | + |
| 66 | +### Remote Flags (Server-side evaluation) |
| 67 | +- Each evaluation makes API call to Mixpanel |
| 68 | +- Better for sensitive targeting logic |
| 69 | +- Configure via `RemoteFlagsConfig` |
| 70 | + |
| 71 | +### Flag Configuration Pattern |
| 72 | +```python |
| 73 | +local_config = mixpanel.LocalFlagsConfig( |
| 74 | + api_host="api-eu.mixpanel.com", # EU data residency |
| 75 | + enable_polling=True, |
| 76 | + polling_interval_in_seconds=90 |
| 77 | +) |
| 78 | +mp = Mixpanel(token, local_flags_config=local_config) |
| 79 | +``` |
| 80 | + |
| 81 | +## Testing Patterns |
| 82 | +- Mock HTTP with `responses.activate` decorator for sync tests |
| 83 | +- Use `respx.mock` for async HTTP testing |
| 84 | +- Test consumer behavior via `LogConsumer` pattern (see `test_mixpanel.py`) |
| 85 | +- Always test both sync and async variants of flag operations |
| 86 | + |
| 87 | +## Critical Implementation Notes |
| 88 | +- `alias()` method always uses synchronous Consumer regardless of main consumer type |
| 89 | +- Local flags require explicit startup; use context managers for proper cleanup |
| 90 | +- DateTime serialization handled by `DatetimeSerializer` class |
| 91 | +- All flag providers support custom API endpoints for data residency requirements |
0 commit comments