Wrapper around asyncpg with a bit better experience.
Project description
asyncpg-engine
Small wrapper around asyncpg for specific experience and transactional testing.
Basic usage
from asyncpg_engine import Engine
engine = await Engine.create("postgres://guest:guest@localhost:5432/guest?sslmode=disable")
async with engine.acquire() as con:
# https://magicstack.github.io/asyncpg/current/api/index.html#asyncpg.connection.Connection
assert await con.fetchval("SELECT 1") == 1
Custom type conversions
You can specify custom encoder/decoder by subclassing Engine
:
from asyncpg_engine import Engine
import orjson
class MyEngine(Engine):
@staticmethod
async def _set_codecs(con: Connection) -> None:
# https://magicstack.github.io/asyncpg/current/api/index.html#asyncpg.connection.Connection.set_type_codec
await con.set_type_codec(
"json", encoder=orjson.dumps, decoder=orjson.loads, schema="pg_catalog"
)
Pytest plugin
Library includes pytest plugin with support for transactional testing.
To start using it install pytest
, enable plugin in your root conftest.py
and define postgres_url
fixture that returns database connection string:
pytest_plugins = ["asyncpg_engine"]
@pytest.fixture()
def postgres_url() -> str:
return "postgres://guest:guest@localhost:5432/guest?sslmode=disable"
Now you can use two fixtures:
db
that returnsEngine
instance:
async def test_returns_true(db):
async with db.acquire() as con:
assert await con.fetchval("SELECT true")
con
that returns already acquired connection:
async def test_returns_true(con):
assert await con.fetchval("SELECT true")
By default Engine
is configured for transactional testing, so every call to db.acquire
or con
usage will return the same connection with already started transaction. Transaction is rolled back at the end of test, so all your changes in db are rolled back too.
You can override this behaviour with asyncpg_engine
mark:
@pytest.mark.asyncpg_engine(transactional=False)
async def test_returns_true(con):
assert await con.fetchval("SELECT true")
@pytest.mark.asyncpg_engine(transactional=False)
async def test_returns_true_too(db):
async with db.acquire() as con:
assert await con.fetchval("SELECT true")
If you want to use your own custom Engine
subclass in tests you can define asyncpg_engine_cls
fixture that returns it:
from asyncpg_engine import Engine
class MyPrettyEngine(Engine):
pass
@pytest.fixture()
def asyncpg_engine_cls() -> typing.Type[MyPrettyEngine]:
return MyPrettyEngine
async def test_returns_my_pretty_engine(db: MyPrettyEngine) -> None:
assert isinstance(db, MyPrettyEngine)
Development and contribution
First of all you should install Poetry.
- install project dependencies
make install
- run linters
make lint
- run tests
make test
- feel free to contribute!
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
Built Distribution
File details
Details for the file asyncpg_engine-0.3.2.tar.gz
.
File metadata
- Download URL: asyncpg_engine-0.3.2.tar.gz
- Upload date:
- Size: 5.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/1.3.1 CPython/3.11.5 Linux/5.15.0-1041-azure
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | e345b5d6bcbfc4f4653ac4aa6c54e5006de46d979f0760a07b7eb346b495d423 |
|
MD5 | ed7a71f4829116a87607924a5a71d122 |
|
BLAKE2b-256 | 669fd2395374afa746fa051b89348a0e4a4951d7750cf1a3a37cb97e15032a48 |
File details
Details for the file asyncpg_engine-0.3.2-py3-none-any.whl
.
File metadata
- Download URL: asyncpg_engine-0.3.2-py3-none-any.whl
- Upload date:
- Size: 5.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/1.3.1 CPython/3.11.5 Linux/5.15.0-1041-azure
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 4d3b8686f7ae1cf08be73d681ae1afe391cc2dfc128b389d1503da3f80591bb2 |
|
MD5 | 09ac8572a1f49c5385ac19881bb7191a |
|
BLAKE2b-256 | 4626710006d4ff8651c5a0b06c1da62329f6594ed55e8e8ea1d5c56f5d4c0e47 |