Skip to main content

Add your description here

Project description

MoleQL

Expressive URL-query to MongoDB query conversion library.

CI License PyPI Python Versions

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

  1. Fork this repository

  2. Create your feature branch

    git checkout -b feat/awesome-change
    
  3. Run formatting and tests

    uv run pre-commit run --all-files
    uv run pytest
    
  4. Commit and push your changes

  5. 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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

moleql-0.1.1.tar.gz (11.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

moleql-0.1.1-py3-none-any.whl (16.9 kB view details)

Uploaded Python 3

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

Hashes for moleql-0.1.1.tar.gz
Algorithm Hash digest
SHA256 5d486b29b111cebb9b8bf9734888792e5dde29ad3afaf0baefc3f006163672f0
MD5 fc9bef2a702784235db3e85d8030eeba
BLAKE2b-256 854caf6587606ad84cdd0a3aa91a6a0676dbd51bfb1aaf805bb50dc1327ca2fd

See more details on using hashes here.

Provenance

The following attestation bundles were made for moleql-0.1.1.tar.gz:

Publisher: release.yml on OneTesseractInMultiverse/moleql

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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

Hashes for moleql-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 5918570d2a7ae429df0948a2c93680d28cd1a8b012f40c1c2f3bd0e32bf1d036
MD5 121c173e5bd705fbfa26db3efede4179
BLAKE2b-256 56dd306570c4fcdca627e0041d993abcb1d0fe3bff1d38718b9ee3201d2169b1

See more details on using hashes here.

Provenance

The following attestation bundles were made for moleql-0.1.1-py3-none-any.whl:

Publisher: release.yml on OneTesseractInMultiverse/moleql

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page