|
| 1 | +# Contributing to Redis OM Python |
| 2 | + |
| 3 | +Thank you for your interest in contributing to Redis OM Python! We welcome contributions from the community and are grateful for any help you can provide. |
| 4 | + |
| 5 | +## Table of Contents |
| 6 | + |
| 7 | +- [Getting Started](#getting-started) |
| 8 | +- [Development Setup](#development-setup) |
| 9 | +- [Project Architecture](#project-architecture) |
| 10 | +- [Development Workflow](#development-workflow) |
| 11 | +- [Testing](#testing) |
| 12 | +- [Code Style](#code-style) |
| 13 | +- [Submitting Changes](#submitting-changes) |
| 14 | +- [Reporting Issues](#reporting-issues) |
| 15 | + |
| 16 | +## Getting Started |
| 17 | + |
| 18 | +Redis OM Python is an object mapping library for Redis that provides declarative models built on Pydantic. Before contributing, please: |
| 19 | + |
| 20 | +1. Read the [README.md](README.md) to understand the project |
| 21 | +2. Check existing [issues](https://github.com/redis/redis-om-python/issues) and [pull requests](https://github.com/redis/redis-om-python/pulls) |
| 22 | +3. Review this contributing guide thoroughly |
| 23 | + |
| 24 | +## Development Setup |
| 25 | + |
| 26 | +### Prerequisites |
| 27 | + |
| 28 | +- Python 3.8 or higher (we test on 3.8-3.13) |
| 29 | +- [Poetry](https://python-poetry.org/docs/#installation) for dependency management |
| 30 | +- Docker and Docker Compose for running Redis |
| 31 | +- Make (for running development commands) |
| 32 | + |
| 33 | +### Initial Setup |
| 34 | + |
| 35 | +1. **Fork and clone the repository:** |
| 36 | + |
| 37 | + ```bash |
| 38 | + git clone https://github.com/YOUR_USERNAME/redis-om-python.git |
| 39 | + cd redis-om-python |
| 40 | + ``` |
| 41 | + |
| 42 | +2. **Install dependencies:** |
| 43 | + |
| 44 | + ```bash |
| 45 | + make install |
| 46 | + ``` |
| 47 | + |
| 48 | + This will use Poetry to install all dependencies in a virtual environment. |
| 49 | + |
| 50 | +3. **Start Redis containers:** |
| 51 | + |
| 52 | + ```bash |
| 53 | + make redis |
| 54 | + ``` |
| 55 | + |
| 56 | + This starts two Redis instances: |
| 57 | + - Redis Stack (port 6380) - includes RediSearch and RedisJSON modules |
| 58 | + - Redis OSS (port 6381) - standard Redis for compatibility testing |
| 59 | + |
| 60 | +4. **Enter the Poetry shell (optional):** |
| 61 | + |
| 62 | + ```bash |
| 63 | + make shell |
| 64 | + ``` |
| 65 | + |
| 66 | +## Project Architecture |
| 67 | + |
| 68 | +### � Critical: Dual Async/Sync Architecture |
| 69 | + |
| 70 | +This project uses a unique dual-codebase approach: |
| 71 | + |
| 72 | +- **`/aredis_om/`** - The PRIMARY source code (async implementation) |
| 73 | +- **`/redis_om/`** - GENERATED sync version (DO NOT EDIT DIRECTLY) |
| 74 | +- **`/tests/`** - Async tests |
| 75 | +- **`/tests_sync/`** - GENERATED sync tests |
| 76 | + |
| 77 | +**IMPORTANT:** |
| 78 | + |
| 79 | +- Always implement features in `/aredis_om/` first |
| 80 | +- Never directly edit files in `/redis_om/` or `/tests_sync/` |
| 81 | +- After making changes, run `make sync` to generate the sync versions |
| 82 | + |
| 83 | +### Key Components |
| 84 | + |
| 85 | +- **Models**: `HashModel` (Redis Hashes) and `JsonModel` (RedisJSON documents) |
| 86 | +- **Query System**: Expression-based queries with Django ORM-like syntax |
| 87 | +- **Field System**: Pydantic fields extended with Redis-specific features |
| 88 | +- **Migration System**: Automatic RediSearch index management |
| 89 | + |
| 90 | +## Development Workflow |
| 91 | + |
| 92 | +### 1. Making Code Changes |
| 93 | + |
| 94 | +For any new feature or bug fix: |
| 95 | + |
| 96 | +```bash |
| 97 | +# 1. Create a new branch |
| 98 | +git checkout -b feature/your-feature-name |
| 99 | + |
| 100 | +# 2. Make changes in /aredis_om/ (async code) |
| 101 | +# Edit files... |
| 102 | + |
| 103 | +# 3. Generate sync version |
| 104 | +make sync |
| 105 | + |
| 106 | +# 4. Format your code |
| 107 | +make format |
| 108 | + |
| 109 | +# 5. Run linters |
| 110 | +make lint |
| 111 | + |
| 112 | +# 6. Run tests |
| 113 | +make test |
| 114 | +``` |
| 115 | + |
| 116 | +### 2. Common Development Commands |
| 117 | + |
| 118 | +```bash |
| 119 | +make install # Install dependencies |
| 120 | +make redis # Start Redis containers |
| 121 | +make sync # Generate sync code from async |
| 122 | +make format # Format code with black and isort |
| 123 | +make lint # Run all linters (flake8, mypy, bandit) |
| 124 | +make test # Run full test suite against Redis Stack |
| 125 | +make test_oss # Run tests against OSS Redis |
| 126 | +make clean # Remove generated files and containers |
| 127 | +make all # Run lint, format, and test |
| 128 | +``` |
| 129 | + |
| 130 | +### 3. Development Cycle Example |
| 131 | + |
| 132 | +Here's a typical development cycle for adding a new feature: |
| 133 | + |
| 134 | +```bash |
| 135 | +# 1. Start Redis |
| 136 | +make redis |
| 137 | + |
| 138 | +# 2. Create your feature in /aredis_om/ |
| 139 | +vim aredis_om/model/model.py |
| 140 | + |
| 141 | +# 3. Generate sync version |
| 142 | +make sync |
| 143 | + |
| 144 | +# 4. Write tests in /tests/ |
| 145 | +vim tests/test_your_feature.py |
| 146 | + |
| 147 | +# 5. Run tests iteratively |
| 148 | +poetry run pytest tests/test_your_feature.py -vv |
| 149 | + |
| 150 | +# 6. Format and lint |
| 151 | +make format |
| 152 | +make lint |
| 153 | + |
| 154 | +# 7. Run full test suite |
| 155 | +make test |
| 156 | +``` |
| 157 | + |
| 158 | +## Testing |
| 159 | + |
| 160 | +### Running Tests |
| 161 | + |
| 162 | +```bash |
| 163 | +# Run all tests |
| 164 | +make test |
| 165 | + |
| 166 | +# Run specific test file |
| 167 | +poetry run pytest tests/test_hash_model.py -vv |
| 168 | + |
| 169 | +# Run specific test |
| 170 | +poetry run pytest tests/test_hash_model.py::test_saves_model -vv |
| 171 | + |
| 172 | +# Run with coverage |
| 173 | +poetry run pytest --cov=aredis_om --cov=redis_om --cov-report=term-missing |
| 174 | + |
| 175 | +# Run tests in parallel |
| 176 | +poetry run pytest -n auto |
| 177 | + |
| 178 | +# Test against OSS Redis (without modules) |
| 179 | +make test_oss |
| 180 | +``` |
| 181 | + |
| 182 | +### Writing Tests |
| 183 | + |
| 184 | +1. Write async tests in `/tests/` |
| 185 | +2. Use fixtures from `conftest.py` for Redis connections |
| 186 | +3. Mark module-dependent tests appropriately: |
| 187 | + |
| 188 | + ```python |
| 189 | + @pytest.mark.asyncio |
| 190 | + async def test_json_model_feature(): |
| 191 | + # Test requiring RedisJSON |
| 192 | + pass |
| 193 | + ``` |
| 194 | + |
| 195 | +4. Ensure tests work with both Redis Stack and OSS Redis where applicable |
| 196 | + |
| 197 | +### Test Coverage |
| 198 | + |
| 199 | +We aim for high test coverage. New features should include comprehensive tests covering: |
| 200 | + |
| 201 | +- Happy path scenarios |
| 202 | +- Edge cases |
| 203 | +- Error conditions |
| 204 | +- Both async and sync versions (sync tests are auto-generated) |
| 205 | + |
| 206 | +## Code Style |
| 207 | + |
| 208 | +### Formatting and Linting |
| 209 | + |
| 210 | +We use several tools to maintain code quality: |
| 211 | + |
| 212 | +- **black** - Code formatting |
| 213 | +- **isort** - Import sorting |
| 214 | +- **flake8** - Style guide enforcement |
| 215 | +- **mypy** - Static type checking |
| 216 | +- **bandit** - Security linting |
| 217 | + |
| 218 | +Run all checks with: |
| 219 | + |
| 220 | +```bash |
| 221 | +make format # Auto-format code |
| 222 | +make lint # Check for issues |
| 223 | +``` |
| 224 | + |
| 225 | +### Style Guidelines |
| 226 | + |
| 227 | +1. **Type Hints**: Use type hints for all function signatures |
| 228 | +2. **Docstrings**: Add docstrings to public methods and classes |
| 229 | +3. **Async First**: Implement in async (`/aredis_om/`) first |
| 230 | +4. **Pydantic Models**: Leverage Pydantic's validation features |
| 231 | +5. **Error Messages**: Provide clear, actionable error messages |
| 232 | + |
| 233 | +### Example Code Style |
| 234 | + |
| 235 | +```python |
| 236 | +from typing import Optional, List |
| 237 | +from pydantic import Field |
| 238 | +from aredis_om import HashModel |
| 239 | + |
| 240 | +class Customer(HashModel): |
| 241 | + """A customer model stored as a Redis Hash.""" |
| 242 | + |
| 243 | + first_name: str = Field(index=True) |
| 244 | + last_name: str = Field(index=True) |
| 245 | + email: str = Field(index=True) |
| 246 | + age: int = Field(index=True, ge=0, le=120) |
| 247 | + |
| 248 | + class Meta: |
| 249 | + database = get_redis_connection() |
| 250 | +``` |
| 251 | + |
| 252 | +## Submitting Changes |
| 253 | + |
| 254 | +### Pull Request Process |
| 255 | + |
| 256 | +1. **Ensure all tests pass:** |
| 257 | + |
| 258 | + ```bash |
| 259 | + make test |
| 260 | + ``` |
| 261 | + |
| 262 | +2. **Update documentation:** |
| 263 | + - Add docstrings for new functions/classes |
| 264 | + - Update README.md if adding major features |
| 265 | + - Add examples for new functionality |
| 266 | + |
| 267 | +3. **Create Pull Request:** |
| 268 | + - Use a clear, descriptive title |
| 269 | + - Reference any related issues |
| 270 | + - Describe what changes you made and why |
| 271 | + - Include examples of how to use new features |
| 272 | + |
| 273 | +### Pull Request Checklist |
| 274 | + |
| 275 | +- [ ] Code is in `/aredis_om/` (async implementation) |
| 276 | +- [ ] Ran `make sync` to generate sync version |
| 277 | +- [ ] All tests pass (`make test`) |
| 278 | +- [ ] Code is formatted (`make format`) |
| 279 | +- [ ] Linters pass (`make lint`) |
| 280 | +- [ ] Added/updated tests for changes |
| 281 | +- [ ] Added docstrings for public APIs |
| 282 | +- [ ] Commits are logical and well-described |
| 283 | + |
| 284 | +### Commit Messages |
| 285 | + |
| 286 | +Use clear, descriptive commit messages: |
| 287 | + |
| 288 | +- Start with a verb (Add, Fix, Update, Remove) |
| 289 | +- Keep the first line under 50 characters |
| 290 | +- Reference issues when applicable |
| 291 | + |
| 292 | +Examples: |
| 293 | + |
| 294 | +``` |
| 295 | +Add support for vector similarity search |
| 296 | +Fix index creation for nested JSON models |
| 297 | +Update dependencies to support Python 3.13 |
| 298 | +Remove deprecated query methods |
| 299 | +``` |
| 300 | + |
| 301 | +## Reporting Issues |
| 302 | + |
| 303 | +### Bug Reports |
| 304 | + |
| 305 | +When reporting bugs, please include: |
| 306 | + |
| 307 | +1. **Environment details:** |
| 308 | + - Python version |
| 309 | + - Redis OM version |
| 310 | + - Redis server version |
| 311 | + - OS and version |
| 312 | + |
| 313 | +2. **Minimal reproducible example:** |
| 314 | + |
| 315 | + ```python |
| 316 | + # Your code that demonstrates the issue |
| 317 | + ``` |
| 318 | + |
| 319 | +3. **Expected vs actual behavior** |
| 320 | + |
| 321 | +4. **Full error messages and stack traces** |
| 322 | + |
| 323 | +### Feature Requests |
| 324 | + |
| 325 | +For feature requests, please describe: |
| 326 | + |
| 327 | +- The use case you're trying to solve |
| 328 | +- How you envision the feature working |
| 329 | +- Code examples of the proposed API |
| 330 | + |
| 331 | +## Additional Resources |
| 332 | + |
| 333 | +- [Redis OM Documentation](https://redis.io/docs/stack/get-started/tutorials/stack-python/) |
| 334 | +- [RediSearch Documentation](https://redis.io/docs/stack/search/) |
| 335 | +- [RedisJSON Documentation](https://redis.io/docs/stack/json/) |
| 336 | +- [Pydantic Documentation](https://docs.pydantic.dev/) |
| 337 | + |
| 338 | +## Getting Help |
| 339 | + |
| 340 | +- **Issues**: [GitHub Issues](https://github.com/redis/redis-om-python/issues) |
| 341 | +- **Discussions**: [GitHub Discussions](https://github.com/redis/redis-om-python/discussions) |
| 342 | +- **Discord**: [Redis Discord Server](https://discord.gg/redis) |
| 343 | + |
| 344 | +## License |
| 345 | + |
| 346 | +By contributing to Redis OM Python, you agree that your contributions will be licensed under the [MIT License](LICENSE). |
| 347 | + |
| 348 | +## Thank You |
| 349 | + |
| 350 | +Thank you for contributing to Redis OM Python! Your efforts help make this library better for everyone in the Redis community. |
0 commit comments