Skip to content


PyPI version Documentation Status codecov License: MIT Code style: black Imports: isort PyPI - Python Version

A pure python library inspired by the NuGet library dapper.

pydapper is built on top of the database api (dbapi) 2.0 spec to provide more convenient methods for working with databases in python.


import datetime
from dataclasses import dataclass

from pydapper import connect

class Task:
    id: int
    description: str
    owner_id: int

with connect() as commands:
    data = commands.query("select * from task limit 1", model=Task)

# [Task(id=1, description='Set up a test database',, 12, 31), owner_id=1)]
(This script is complete, it should run "as is")

What's going on here?

  • connect handles creating a connection and returning the pydapper entrypoint for the dsn you pass in
  • the query method is executing the sql string and serializing each item in the result set to the model passed (Task)
  • the context manager is a proxy to whatever the underlying dbapi for the specified DSN has implemented (see database support docs)


Why would I use pydapper?

ORM queries are great...until they're not
Most ORMs in python (think SQLAlchemy, Django, Pony) provide an interface for mapping database results to python objects, but also implement their own api for interacting with the database. When these queries become complex, they are often hard to read and debug. Why not use SQL instead?
Safe from SQL injection
pydapper provides a consistent syntax for declaring query parameters and guarantees it is converted to the safest possible parameter substitution for the dbapi to deter SQL injection
You want a framework that lets you BYOC (bring your own connection)
Sometimes ORM frameworks abstract too much from you. pydapper allows you to use your own connection object and pass it into the using entrypoint. This gives you complete control over connection management when you don't want pydapper to manage it for you.

You use python dbapi interfaces often and are tired of writing this code

from psycopg2 import connect

with connect("postgresql://pydapper:pydapper@localhost/pydapper") as conn:
    with conn.cursor() as cursor:
        cursor.execute("select * from task")
        headers = [i[0] for i in cursor.description]
        data = cursor.fetchall()

list_data = [dict(zip(headers, row)) for row in data]

Buy me a coffee🔗

If you find this project useful, consider buying me a coffee!

Buy Me A Coffee