Development Setup
Everything you need to set up, build, and maintain pypaginate locally.
Prerequisites
Python 3.11+ (3.14 recommended for best performance)
uv – fast Python package manager
Git with conventional commits
curl -LsSf https://astral.sh/uv/install.sh | sh
Setup
1. Fork and Clone
git clone https://github.com/YOUR_USERNAME/pypaginate.git
cd pypaginate
git remote add upstream https://github.com/CybLow/paginate.git
2. Install Dependencies
uv sync --all-extras --dev
This installs:
Core: pydantic (fuzzy search is built into the native engine – no extra needed)
Optional extras: sqlalchemy, fastapi, msgspec, google-re2
Dev tools: pytest, mypy, ruff, hypothesis, pytest-benchmark
Docs: sphinx, myst-parser
3. Pre-commit Hooks (Optional)
uv run pre-commit install
4. Verify Setup
uv run ruff check src/ # Lint
uv run mypy src/ # Type check
uv run pytest tests/ --ignore=tests/perf -q # Tests
Project Structure
src/pypaginate/
├── __init__.py # Public API exports
├── _dispatch.py # Universal paginate() entry point
│
├── domain/ # Pure models, specs, protocols, exceptions
│ ├── enums.py # SortDirection, FilterLogic, FuzzyMode, etc.
│ ├── exceptions.py # PaginationError hierarchy
│ ├── pages.py # OffsetPage, CursorPage
│ ├── params.py # OffsetParams, CursorParams
│ ├── protocols.py # Backend protocol definitions
│ └── specs.py # FilterSpec, SortSpec, SearchSpec
│
├── engine/ # Core orchestration (backend-agnostic)
│ ├── paginator.py # Paginator, AsyncPaginator
│ ├── pipeline.py # SyncPipeline, AsyncPipeline
│ └── cursor.py # AsyncCursorPaginator
│
├── filtering/ # Filter engine + operators
├── sorting/ # Sort engine + null-aware keys
├── search/ # Search engine + fuzzy matching
├── text/ # Text normalization (LRU cached)
│
└── adapters/ # Backend implementations
├── memory/ # In-memory (list, tuple)
├── sqlalchemy/ # SQLAlchemy ORM (sync + async)
└── fastapi/ # FastAPI dependency injection
tests/
├── unit/ # Per-module unit tests
├── integration/ # Cross-module + database
├── e2e/ # Full workflows with FastAPI
├── property/ # Hypothesis invariants
├── architecture/ # Code quality enforcement
└── perf/ # Performance benchmarks
Daily Workflow
While Coding
uv run ruff format . # Format
uv run ruff check src/ # Lint
uv run mypy src/pypaginate/search/ # Type check what you changed
uv run pytest tests/unit/search/ -v # Run related tests
Before Committing
uv run ruff format . && uv run ruff check --fix . && uv run mypy src/ && uv run pytest tests/ --ignore=tests/perf -q
Before PR
# Full test suite including integration and e2e
uv run pytest tests/ --ignore=tests/perf -v
# If touching hot paths, run benchmarks
uv run pytest tests/perf/test_comparison.py --benchmark-enable --benchmark-only -q
Optional Extras
Extra |
Packages |
Purpose |
|---|---|---|
|
SQLAlchemy |
ORM pagination |
|
(none) |
No-op compat alias – fuzzy search is native |
|
FastAPI |
Dependency injection helpers |
|
msgspec |
Near-zero page construction |
|
google-re2 |
ReDoS-safe regex filtering |
|
Everything |
Full install |
uv add pypaginate[all] # Install with everything
uv add pypaginate[sqlalchemy] # Install with SQLAlchemy only
IDE Setup
PyCharm / IntelliJ
Set interpreter to
.venv/bin/pythonInstall Ruff plugin for real-time linting
Set line length to 100 (Editor > Code Style > Python)
Enable mypy integration
Set pytest as test runner
VS Code
{
"python.defaultInterpreterPath": ".venv/bin/python",
"[python]": {
"editor.formatOnSave": true,
"editor.defaultFormatter": "charliermarsh.ruff"
},
"python.analysis.typeCheckingMode": "strict",
"editor.rulers": [100]
}
Common Tasks
Adding a New Filter Operator
In-memory operators live in the native paginate-core Rust engine, so a new
operator spans both repos:
Add the operator to the engine crate (
crates/core/src/filter/) in thepaginate-corerepo and rebuild (maturin develop --release)Add SA mapping in
src/pypaginate/adapters/sqlalchemy/filters.pyAdd the literal value to the
FilterOperatortype insrc/pypaginate/domain/specs.pyAdd tests in
tests/unit/filtering/
Adding a New Backend Adapter
Create
src/pypaginate/adapters/mybackend/withbackend.pyImplement
PaginationBackend[T]protocol (orSyncPaginationBackend[T])Add
__slots__to all new classesOptionally implement
FilterBackend,SortBackend,SearchBackendAdd tests in
tests/unit/adapters/mybackend/
Optimizing a Hot Path
Benchmark first – save baseline with
--benchmark-save=beforeProfile – identify the actual bottleneck
Apply compile-once patterns, LRU cache, or string methods over regex
Verify all tests pass and benchmark shows improvement
Troubleshooting
Problem |
Solution |
|---|---|
|
|
mypy missing stubs |
|
Flaky benchmarks |
Close background apps, use |
Architecture test fails |
File exceeds 250 code lines – extract a helper module |
Pre-commit hook fails |
|
Next Steps
Architecture Guide – understand the codebase design
Testing Guide – write and run tests
Code Style – coding standards and patterns