Add your description here
Project description
MoleQL
Expressive URL-query to MongoDB query conversion library.
Overview
MoleQL allows your REST APIs or data layers to accept
URL-style query strings (e.g. ?age>30&status=in(active,pending))
and converts them into MongoDB-compatible query dictionaries.
It supports filters, sorting, skip/limit, projection and text search.
Example:
from moleql import parse
query = parse("age>30&country=US&name=/^John/i")
# yields:
# {
# "filter": {"age": {"$gt": 30}, "country": "US", "name": {"$regex": "^John", "$options": "i"}},
# "sort": None,
# "skip": 0,
# "limit": 0,
# "projection": None
# }
✨ Features
- 🧠 Intuitive syntax:
=, !=, <, <=, >, >= - 📋 List operators:
in(...), ... - 🔍 Regex:
/pattern/flags → $regex + $options - 🧾 Pagination:
skip=10, limit=50 - ⚙️ Sorting:
sort=-created_at,name - 🧩 Projection:
fields=name,email,age - 🔠 Text search:
text=free text here - 🧱 Type casters:
custom value transformations - 🚫 Blacklist: skip parsing of restricted fields
- 🧪 Tested: full pytest coverage, Ruff linting
🧰 Installation
With uv (recommended):
uv add moleql
pip install moleql
🚀 Quick Start
from moleql import parse
query = parse("age>30&country=US&name=/^John/i") print(query)
from moleql import parse
query = parse("age>30&country=US&name=/^John/i")
print(query)
# {
# "filter": {
# "age": {"$gt": 30},
# "country": "US",
# "name": {"$regex": "^John", "$options": "i"}
# },
# "sort": None,
# "skip": 0,
# "limit": 0,
# "projection": None
# }
Extended example
from moleql import parse
query = parse(
"age>=18&status=in(active,pending)"
"&sort=-created_at,name"
"&skip=10&limit=20"
"&fields=name,email,age"
)
Output:
{
"filter": {
"age": {"$gte": 18},
"status": {"$in": ["active", "pending"]}
},
"sort": {"created_at": -1, "name": 1},
"skip": 10,
"limit": 20,
"projection": {"name": 1, "email": 1, "age": 1}
}
🔣 Supported Operators
| Expression | Mongo Operator | Example |
|---|---|---|
= |
direct match | age=20 → {"age": 20} |
!= |
$ne |
status!=active |
> / >= |
$gt / $gte |
score>=80 |
< / <= |
$lt / $lte |
price<10 |
in(...) |
$in |
role=in(admin,user) |
!=in(...) |
$nin |
tier!=in(gold,platinum) |
/pattern/flags |
$regex |
name=/^Jo/i |
text= |
$text |
text=free search text |
fields= |
projection | fields=name,email |
sort= |
sort directive | sort=-created_at,name |
🧱 Quick API Reference
parse(moleql_query: str, blacklist=None, casters=None) -> dict
from moleql import parse
parse("age>25&active=true")
Returns a dictionary with:
filter, sort, skip, limit, projection
moleqularize(moleql_query: str, blacklist=None, casters=None) -> MoleQL
Parse a MoleQL string and return the internal MoleQL object for advanced inspection and debugging.
from moleql import moleqularize
m = moleqularize("age>25")
print(m.mongo_query)
🧩 Custom Casters
You can define custom casters to control type conversions.
from moleql import parse, get_casters
def to_bool(value: str) -> bool:
return value.lower() in ("true", "1", "yes")
custom_casters = {"bool": to_bool}
q = parse("active=bool(true)&age>30", casters=custom_casters)
🧠 Design Philosophy
- Transparency — The query string is readable and reversible.
- Safety — No eval, injection-safe parsing.
- Extensibility — Easy to plug in custom handlers.
- Predictability — Every operator maps 1:1 to Mongo semantics.
- Minimal dependencies — Pure Python, no ODM required.
⚙️ Integration Examples
FastAPI
from fastapi import FastAPI, Request
from moleql import parse
from pymongo import MongoClient
db = MongoClient()["app"]
app = FastAPI()
@app.get("/users")
def list_users(request: Request):
q = parse(request.url.query.lstrip("?"))
return list(db.users.find(q["filter"]))
Flask
from flask import Flask, request, jsonify
from moleql import parse
app = Flask(__name__)
@app.get("/orders")
def orders():
q = parse(request.query_string.decode())
return jsonify(q)
🧪 Testing
Run the full suite using uv:
uv sync --all-extras --dev
uv run pytest -vv
Generate coverage:
uv run pytest --cov=moleql --cov-report=term-missing
🧹 Code Quality
This repository uses:
- Ruff — Linting + formatting (UP / pyupgrade rules)
- pre-commit — automatic checks
- pytest — testing
- uv — environment & packaging
Set up hooks:
uv run pre-commit install
uv run pre-commit run --all-files
🧭 Roadmap
- [] Add exists(field) and between(a,b) operators
- [] Add alias for text= → $search convenience
- [] Add optional CLI (moleql "age>20" --as-json)
- [] Extended docs and tutorials
🤝 Contributing
-
Fork this repository
-
Create your feature branch
git checkout -b feat/awesome-change
-
Run formatting and tests
uv run pre-commit run --all-files uv run pytest
-
Commit and push your changes
-
Open a Pull Request 🚀
🌟 Acknowledgments
Built and maintained by @OneTesseractInMultiverse Inspired by the need for readable, typed, and safe Mongo queries in API environments.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file moleql-0.1.1.tar.gz.
File metadata
- Download URL: moleql-0.1.1.tar.gz
- Upload date:
- Size: 11.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5d486b29b111cebb9b8bf9734888792e5dde29ad3afaf0baefc3f006163672f0
|
|
| MD5 |
fc9bef2a702784235db3e85d8030eeba
|
|
| BLAKE2b-256 |
854caf6587606ad84cdd0a3aa91a6a0676dbd51bfb1aaf805bb50dc1327ca2fd
|
Provenance
The following attestation bundles were made for moleql-0.1.1.tar.gz:
Publisher:
release.yml on OneTesseractInMultiverse/moleql
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
moleql-0.1.1.tar.gz -
Subject digest:
5d486b29b111cebb9b8bf9734888792e5dde29ad3afaf0baefc3f006163672f0 - Sigstore transparency entry: 683592880
- Sigstore integration time:
-
Permalink:
OneTesseractInMultiverse/moleql@76dce042b3f1527374d844fa383f5ca7d944b5f0 -
Branch / Tag:
refs/tags/v0.1.3 - Owner: https://github.com/OneTesseractInMultiverse
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@76dce042b3f1527374d844fa383f5ca7d944b5f0 -
Trigger Event:
push
-
Statement type:
File details
Details for the file moleql-0.1.1-py3-none-any.whl.
File metadata
- Download URL: moleql-0.1.1-py3-none-any.whl
- Upload date:
- Size: 16.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5918570d2a7ae429df0948a2c93680d28cd1a8b012f40c1c2f3bd0e32bf1d036
|
|
| MD5 |
121c173e5bd705fbfa26db3efede4179
|
|
| BLAKE2b-256 |
56dd306570c4fcdca627e0041d993abcb1d0fe3bff1d38718b9ee3201d2169b1
|
Provenance
The following attestation bundles were made for moleql-0.1.1-py3-none-any.whl:
Publisher:
release.yml on OneTesseractInMultiverse/moleql
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
moleql-0.1.1-py3-none-any.whl -
Subject digest:
5918570d2a7ae429df0948a2c93680d28cd1a8b012f40c1c2f3bd0e32bf1d036 - Sigstore transparency entry: 683592923
- Sigstore integration time:
-
Permalink:
OneTesseractInMultiverse/moleql@76dce042b3f1527374d844fa383f5ca7d944b5f0 -
Branch / Tag:
refs/tags/v0.1.3 - Owner: https://github.com/OneTesseractInMultiverse
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@76dce042b3f1527374d844fa383f5ca7d944b5f0 -
Trigger Event:
push
-
Statement type: