PyDAO

is very thin object-relational mapper similar to

Hibernate

(but much simpler). It's created to speed-up application development. It's very simple, but powerful, based on

POPO

(Plain Old Python Objects).

Main features

  • can use any database that has DB-API interface
  • can work without database at all (useful for early phases of development)
  • speeds up unit testing (dedicated in memory database)

What is not handled

  • automatic scheme generation (one have to create scheme "by hand")
  • separate query language (it's possible to use plain SQL if filtering by example is not sufficient)
  • automated handling of associations (foreign keys are visible in source code)

Download

You can reach latest version of PyDAO on SourceForge:

http://sourceforge.net/projects/pydao

Small example how to use PyDAO

    class User:
        def __init__(self):
            self.id = None
            self.login = None
            self.password = None

    dao = pydao.InMemoryDao()

    # filling database
    user = User()
    user.login = "user1"
    user.password = "roh8OoPh"
    dao.save(user)

    # filtering based on example
    userSearch = User()
    userSearch.login = "user1"
    userList = dao.list(userSearch)

    # updating
    user.password = "eew8Me8g"
    dao.update(user)

More examples how to use API can be found in AbstractDaoTest.py and SqlDaoTest.py. Also see: PyDAO User Guide.

Supported databases

  • InMemoryDao - objects stored in memory
  • MysqlDao - objects stored in MySQL database (tested with MySQLdb)
  • PostgresqlDao - objects stored in PostgreSQL database (tested with psycopg)

Logging

You can redirect logs to any open stream (sys.stderr for example) to see API calls and resulting SQL queries (if back-end is SQL type).

  save(): User {login='u1' }
    INSERT INTO TEST_USER(login,password,companyID) VALUES(%s,%s,%s)
  list(): User {}
    SELECT T.*, TC.NAME AS _companyName FROM TEST_USER T
    LEFT JOIN TEST_COMPANY TC ON T.COMPANYID = TC.ID
  save(): User {login='u2' }
    INSERT INTO TEST_USER(login,password,companyID) VALUES(%s,%s,%s)
  list(): User {}
    SELECT T.*, TC.NAME AS _companyName FROM TEST_USER T
    LEFT JOIN TEST_COMPANY TC ON T.COMPANYID = TC.ID
  delete(): User {}
    DELETE FROM TEST_USER

API

  • AbstractDao
    • SimpleDao
      • InMemoryDao
      • XmlStorageDao
    • SqlDao
      • MysqlDao
      • PostgresqlDao
  • Condition
    • InRangeCondition
    • InSequenceCondition
    • IsNullCondition
    • NotNullCondition
    • LikeCondition
    • ArbitraryCondition

Quality Assurance

  • Project is tested using unit tests. Quality of testing is visible in coverage report. Coverage is based on coverage.py module (thanks to Ned Batchelder).
  • Additionally public API is instrumented with Design By Contract expressions. I'm using pycontract module (thanks to Terence Way).
  • Method of declaring attributes is compatible with lint-like tools for Python. For static analysis I'm currently using pylint.

edit