Skip to content

Instantly share code, notes, and snippets.

@FutureBody
Forked from xsduan/async_sqlite.py
Created January 19, 2024 06:06
Show Gist options
  • Save FutureBody/d1e7291916b3fd79b9251155e0e918b8 to your computer and use it in GitHub Desktop.
Save FutureBody/d1e7291916b3fd79b9251155e0e918b8 to your computer and use it in GitHub Desktop.

Revisions

  1. @xsduan xsduan revised this gist Mar 24, 2019. 1 changed file with 3 additions and 6 deletions.
    9 changes: 3 additions & 6 deletions async_sqlite.py
    Original file line number Diff line number Diff line change
    @@ -24,9 +24,8 @@ def __init__(self, *, database=None, loop=None, timeout=None, **kwargs):

    async def acquire(self):
    conn = aiosqlite.connect(database=self.database, **self.connect_kwargs)
    await conn.__aenter__()
    self._created_connections.append(conn)
    return conn
    return await conn.__aenter__()

    async def release(self, conn):
    if conn in self._created_connections:
    @@ -88,7 +87,5 @@ def init(self, database, **kwargs):
    self.init_async()


    class SqliteExtDatabase(AsyncSqliteMixin, sqlite_ext.SqliteExtDatabase):
    def init(self, database, **kwargs):
    super().init(database, **kwargs)
    self.init_async()
    class SqliteExtDatabase(SqliteDatabase, sqlite_ext.SqliteExtDatabase):
    pass
  2. @xsduan xsduan revised this gist Mar 24, 2019. 1 changed file with 20 additions and 8 deletions.
    28 changes: 20 additions & 8 deletions async_sqlite.py
    Original file line number Diff line number Diff line change
    @@ -1,12 +1,17 @@
    """
    Temporary module to allow for sqlite databases during development. Remove once
    we get an actual database.
    """
    import peewee
    from peewee_async import AsyncDatabase
    import playhouse.sqlite_ext as sqlite_ext

    try:
    import aiosqlite
    except ImportError:
    aiosqlite = None

    __all__ = ["SqliteDatabase"]
    __all__ = ["SqliteDatabase", "SqliteExtDatabase"]


    class AsyncSqliteConnection:
    @@ -26,6 +31,7 @@ async def acquire(self):
    async def release(self, conn):
    if conn in self._created_connections:
    self._created_connections.remove(conn)
    await conn.commit()
    await conn.__aexit__(None, None, None)

    async def connect(self):
    @@ -61,22 +67,28 @@ class AsyncSqliteMixin(AsyncDatabase):
    Error = sqlite3.Error

    def init_async(self, conn_class=AsyncSqliteConnection):
    if not aiosqlite:
    raise Exception("Error, aiosqlite is not installed!")
    self._async_conn_cls = conn_class

    @property
    def connect_kwargs_async(self):
    return {**self.connect_kwargs}

    async def last_insert_id_async(self, cursor, model):
    """Get ID of last inserted row.
    """
    if model._meta.auto_increment:
    return cursor.lastrowid


    class SqliteDatabase(AsyncSqliteMixin, peewee.SqliteDatabase):
    def init(self, database, **kwargs):
    if not aiosqlite:
    raise Exception("Error, aiosqlite is not installed!")
    super().init(database, **kwargs)
    self.init_async()

    async def last_insert_id_async(self, cursor, model):
    """Get ID of last inserted row.
    """
    if model._meta.auto_increment:
    return cursor.lastrowid

    class SqliteExtDatabase(AsyncSqliteMixin, sqlite_ext.SqliteExtDatabase):
    def init(self, database, **kwargs):
    super().init(database, **kwargs)
    self.init_async()
  3. @xsduan xsduan revised this gist Mar 24, 2019. 1 changed file with 7 additions and 13 deletions.
    20 changes: 7 additions & 13 deletions async_sqlite.py
    Original file line number Diff line number Diff line change
    @@ -11,36 +11,30 @@

    class AsyncSqliteConnection:
    def __init__(self, *, database=None, loop=None, timeout=None, **kwargs):
    self._connections = []
    self._used_connections = []
    self._created_connections = []
    self.loop = loop
    self.database = database
    self.timeout = timeout
    self.connect_kwargs = kwargs

    async def acquire(self):
    if self._connections:
    conn = self._connections.pop()
    else:
    conn = aiosqlite.connect(database=self.database, **self.connect_kwargs)

    conn = aiosqlite.connect(database=self.database, **self.connect_kwargs)
    await conn.__aenter__()
    self._used_connections.append(conn)
    self._created_connections.append(conn)
    return conn

    async def release(self, conn):
    if conn in self._used_connections:
    self._used_connections.remove(conn)
    if conn in self._created_connections:
    self._created_connections.remove(conn)
    await conn.__aexit__(None, None, None)
    self._connections.append(conn)

    async def connect(self):
    pass

    async def close(self):
    for conn in self._used_connections:
    for conn in self._created_connections:
    await conn.__aexit__(None, None, None)
    self._used_connections = self._connections = None
    self._created_connections = []

    async def cursor(self, conn=None, *args, **kwargs):
    in_transaction = conn is not None
  4. @xsduan xsduan revised this gist Mar 24, 2019. 1 changed file with 6 additions and 4 deletions.
    10 changes: 6 additions & 4 deletions async_sqlite.py
    Original file line number Diff line number Diff line change
    @@ -25,20 +25,22 @@ async def acquire(self):
    conn = aiosqlite.connect(database=self.database, **self.connect_kwargs)

    await conn.__aenter__()
    self._connections.append(conn)
    self._used_connections.append(conn)
    return conn

    async def release(self, conn):
    if conn in self._connections:
    self._connections.remove(conn)
    if conn in self._used_connections:
    self._used_connections.remove(conn)
    await conn.__aexit__(None, None, None)
    self._connections.append(conn)

    async def connect(self):
    pass

    async def close(self):
    for conn in self._connections:
    for conn in self._used_connections:
    await conn.__aexit__(None, None, None)
    self._used_connections = self._connections = None

    async def cursor(self, conn=None, *args, **kwargs):
    in_transaction = conn is not None
  5. @xsduan xsduan created this gist Mar 24, 2019.
    86 changes: 86 additions & 0 deletions async_sqlite.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,86 @@
    import peewee
    from peewee_async import AsyncDatabase

    try:
    import aiosqlite
    except ImportError:
    aiosqlite = None

    __all__ = ["SqliteDatabase"]


    class AsyncSqliteConnection:
    def __init__(self, *, database=None, loop=None, timeout=None, **kwargs):
    self._connections = []
    self._used_connections = []
    self.loop = loop
    self.database = database
    self.timeout = timeout
    self.connect_kwargs = kwargs

    async def acquire(self):
    if self._connections:
    conn = self._connections.pop()
    else:
    conn = aiosqlite.connect(database=self.database, **self.connect_kwargs)

    await conn.__aenter__()
    self._connections.append(conn)
    return conn

    async def release(self, conn):
    if conn in self._connections:
    self._connections.remove(conn)
    await conn.__aexit__(None, None, None)

    async def connect(self):
    pass

    async def close(self):
    for conn in self._connections:
    await conn.__aexit__(None, None, None)

    async def cursor(self, conn=None, *args, **kwargs):
    in_transaction = conn is not None
    if not conn:
    conn = await self.acquire()
    cursor = await conn.cursor()
    # cursor.release is a coroutine
    cursor.release = self.release_cursor( # pylint: disable = assignment-from-no-return
    cursor, in_transaction
    )
    return cursor

    async def release_cursor(self, cursor, in_transaction=False):
    conn = cursor._conn
    await cursor.__aexit__(None, None, None)
    if not in_transaction:
    await self.release(conn)


    class AsyncSqliteMixin(AsyncDatabase):
    if aiosqlite:
    import sqlite3

    Error = sqlite3.Error

    def init_async(self, conn_class=AsyncSqliteConnection):
    self._async_conn_cls = conn_class

    @property
    def connect_kwargs_async(self):
    return {**self.connect_kwargs}


    class SqliteDatabase(AsyncSqliteMixin, peewee.SqliteDatabase):
    def init(self, database, **kwargs):
    if not aiosqlite:
    raise Exception("Error, aiosqlite is not installed!")
    super().init(database, **kwargs)
    self.init_async()

    async def last_insert_id_async(self, cursor, model):
    """Get ID of last inserted row.
    """
    if model._meta.auto_increment:
    return cursor.lastrowid
    48 changes: 48 additions & 0 deletions main.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,48 @@
    """Taken directly from readme - a good "unit test" of sorts"""
    import asyncio
    import peewee
    import peewee_async

    from async_sqlite import SqliteDatabase

    # Nothing special, just define model and database:

    database = SqliteDatabase('a.sqlite')

    class TestModel(peewee.Model):
    text = peewee.CharField()

    class Meta:
    database = database

    # Look, sync code is working!

    TestModel.create_table(True)
    TestModel.create(text="Yo, I can do it sync!")
    database.close()

    # Create async models manager:

    objects = peewee_async.Manager(database)

    # No need for sync anymore!

    database.set_allow_sync(False)

    async def handler():
    await objects.create(TestModel, text="Not bad. Watch this, I'm async!")
    all_objects = await objects.execute(TestModel.select())
    for obj in all_objects:
    print(obj.text)

    loop = asyncio.get_event_loop()
    loop.run_until_complete(handler())
    loop.close()

    # Clean up, can do it sync again:
    with objects.allow_sync():
    TestModel.drop_table(True)

    # Expected output:
    # Yo, I can do it sync!
    # Not bad. Watch this, I'm async!
    35 changes: 35 additions & 0 deletions poetry.lock
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,35 @@
    [[package]]
    category = "main"
    description = "asyncio bridge to the standard sqlite3 module"
    name = "aiosqlite"
    optional = false
    python-versions = "*"
    version = "0.9.0"

    [[package]]
    category = "main"
    description = "a little orm"
    name = "peewee"
    optional = false
    python-versions = "*"
    version = "2.10.2"

    [[package]]
    category = "main"
    description = "Asynchronous interface for peewee ORM powered by asyncio."
    name = "peewee-async"
    optional = false
    python-versions = "*"
    version = "0.5.12"

    [package.dependencies]
    peewee = ">=2.8.0,<=2.10.2"

    [metadata]
    content-hash = "7b142de08db0c014422b2311cbe01615de0ecaee987eb7f2edb0d693f183d8c4"
    python-versions = "^3.7"

    [metadata.hashes]
    aiosqlite = ["af4fed9e778756fa0ffffc7a8b14c4d7b1a57155dc5669f18e45107313f6019e"]
    peewee = ["2342067f48a779e35956a44cd547df883dda35153daa9fe994d970585aaec281"]
    peewee-async = ["1376774637b6f5cfb9192a06380a8e987fed206e0e229bbadd50da6a4578557b", "ab64a2a376033ce5621406b33735cb064659af05f5c2570af0fba08f6eab6282"]
    16 changes: 16 additions & 0 deletions pyproject.toml
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,16 @@
    [tool.poetry]
    name = "test"
    version = "0.1.0"
    description = ""
    authors = ["Shane Duan <[email protected]>"]

    [tool.poetry.dependencies]
    python = "^3.7"
    peewee-async = "^0.5.12"
    aiosqlite = "^0.9.0"

    [tool.poetry.dev-dependencies]

    [build-system]
    requires = ["poetry>=0.12"]
    build-backend = "poetry.masonry.api"