easqlite


Nameeasqlite JSON
Version 1.1.0 PyPI version JSON
download
home_pageNone
SummaryAn executor-based async sqlite wrapper
upload_time2023-04-27 22:35:27
maintainerNone
docs_urlNone
authorNone
requires_python>=3.8
licenseNone
keywords asyncio sqlite
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # easqlite
A simple Executor-based async sqlite wrapper.

This is used very similarly to the standard `sqlite3` module.

By default, `ThreadPoolExecutor(max_workers=1)` is used as the executor.  If you
pass your own executor, you are responsible for shutting it down and ensuring it
only uses one thread.

Differences from `sqlite3`:

* `connect` is not a function, but just an alias to the `Connection` class.
* `Connect` `check_same_thread` defaults to `__debug__` instead of `True`
* `Connection`'s constructor takes an optional `executor` argument.
* Every method, function, context manager, property accessor, and iterator is
  awaitable.
  * `Connection.interrupt` operates immediately without being `awaited`, and its
    returned coroutine is actually a no-op.
* Every call that takes a factory uses the factory for the internal calls, and
  defers to a statically defined wrapper class.  The internal calls will still
  use the factories.
* All objects with a `close` method are async context managers.
* All properties are now methods with an optional setter parameter, so they
  are properly awaitable and set and get on the same thread.
  * An exception to this is `Cursor.connection`, which is still a property.
* `Blob.__getitem__` is async, but `Blob.__setitem__` can not be.  `Blob.set` is
  provided instead, with the exact same semantics (it can be passed a `slice`).
  You can use `Blob.__setitem__`, but it doesn't actually directly set the blob,
  but rather queues a set to be run on flush.  Any other coroutine flushes the
  blob, or you can use an explicit `Blob.flush`, or just let the blob exit its
  context manager.
* `Blob.__len__` and `Blob.__bool__` block on the executor. `Blob.len` and
  `blob.bool` are async replacements for these.

`Connection`, `Cursor`, and `Blob` are lazy.  They will not open on
construction, but will open when awaited, or when entered as an asynchronous
context manager.

All these objects must be either awaited or used as an asynchronous context manager:

```python
# OK: The cursor was awaited
cursor = await connection.cursor()
await cursor.execute(sql)
async for row in cursor:
  do_something_with(row)

# ERROR: the cursor is not opened
cursor = connection.cursor()
await cursor.execute(sql)
async for row in cursor:
  do_something_with(row)

# OK: The cursor was entered (the preferred style)
async with connection.cursor() as cursor:
  await cursor.execute(sql)
  async for row in cursor:
    do_something_with(row)

# The connection.execute family are coroutines, and must be awaited.

# OK: The coroutine was awaited, and returns an open cursor.
async with await connection.execute(sql) as cursor:
  async for row in cursor:
    do_something_with(row)

# ERROR: The connection.execute result is a coroutine.  It is not a context manager
async with connection.execute(sql) as cursor:
  async for row in cursor:
    do_something_with(row)

# OK: connection.execute opens its cursor, it can just be iterated.
async for row in await connection.execute(sql):
  do_something_with(row)

# ERROR: __aiter__ is not defined on a running coroutine.  It must be awaited.
async for row in connection.execute(sql):
  do_something_with(row)
```

This can be used nearly identically to the regular sqlite module if you sprinkle
an `await` on every function call, but it is preferred to use the async context
managers everywhere possible.  You can't easily go wrong when using the context
managers.

Constants are not re-exported, so this library should usually be used in
conjunction with the core sqlite3 library.

This is very similar in spirit to the
[aiosqlite](https://github.com/omnilib/aiosqlite) project, but this one takes a
more earnest attempt at deferring responsibility to other components.  This one
also should be more responsive on close, because it doesn't rely on a timeout to
shut itself off.

This one also pushes much more extremely on async use, and defers everything it
can to the executor thread, even properties.

If you want a more mature and battle-tested package, use `aiosqlite`.  In my
rough tests, it performs better than this package as well.

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "easqlite",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.8",
    "maintainer_email": null,
    "keywords": "asyncio,sqlite",
    "author": null,
    "author_email": "\"Taylor C. Richberger\" <tcr@absolute-performance.com>",
    "download_url": "https://files.pythonhosted.org/packages/23/01/674e43e0c5f0d8f656bae59b8a434f49946b48630bc877498ad0924cc576/easqlite-1.1.0.tar.gz",
    "platform": null,
    "description": "# easqlite\nA simple Executor-based async sqlite wrapper.\n\nThis is used very similarly to the standard `sqlite3` module.\n\nBy default, `ThreadPoolExecutor(max_workers=1)` is used as the executor.  If you\npass your own executor, you are responsible for shutting it down and ensuring it\nonly uses one thread.\n\nDifferences from `sqlite3`:\n\n* `connect` is not a function, but just an alias to the `Connection` class.\n* `Connect` `check_same_thread` defaults to `__debug__` instead of `True`\n* `Connection`'s constructor takes an optional `executor` argument.\n* Every method, function, context manager, property accessor, and iterator is\n  awaitable.\n  * `Connection.interrupt` operates immediately without being `awaited`, and its\n    returned coroutine is actually a no-op.\n* Every call that takes a factory uses the factory for the internal calls, and\n  defers to a statically defined wrapper class.  The internal calls will still\n  use the factories.\n* All objects with a `close` method are async context managers.\n* All properties are now methods with an optional setter parameter, so they\n  are properly awaitable and set and get on the same thread.\n  * An exception to this is `Cursor.connection`, which is still a property.\n* `Blob.__getitem__` is async, but `Blob.__setitem__` can not be.  `Blob.set` is\n  provided instead, with the exact same semantics (it can be passed a `slice`).\n  You can use `Blob.__setitem__`, but it doesn't actually directly set the blob,\n  but rather queues a set to be run on flush.  Any other coroutine flushes the\n  blob, or you can use an explicit `Blob.flush`, or just let the blob exit its\n  context manager.\n* `Blob.__len__` and `Blob.__bool__` block on the executor. `Blob.len` and\n  `blob.bool` are async replacements for these.\n\n`Connection`, `Cursor`, and `Blob` are lazy.  They will not open on\nconstruction, but will open when awaited, or when entered as an asynchronous\ncontext manager.\n\nAll these objects must be either awaited or used as an asynchronous context manager:\n\n```python\n# OK: The cursor was awaited\ncursor = await connection.cursor()\nawait cursor.execute(sql)\nasync for row in cursor:\n  do_something_with(row)\n\n# ERROR: the cursor is not opened\ncursor = connection.cursor()\nawait cursor.execute(sql)\nasync for row in cursor:\n  do_something_with(row)\n\n# OK: The cursor was entered (the preferred style)\nasync with connection.cursor() as cursor:\n  await cursor.execute(sql)\n  async for row in cursor:\n    do_something_with(row)\n\n# The connection.execute family are coroutines, and must be awaited.\n\n# OK: The coroutine was awaited, and returns an open cursor.\nasync with await connection.execute(sql) as cursor:\n  async for row in cursor:\n    do_something_with(row)\n\n# ERROR: The connection.execute result is a coroutine.  It is not a context manager\nasync with connection.execute(sql) as cursor:\n  async for row in cursor:\n    do_something_with(row)\n\n# OK: connection.execute opens its cursor, it can just be iterated.\nasync for row in await connection.execute(sql):\n  do_something_with(row)\n\n# ERROR: __aiter__ is not defined on a running coroutine.  It must be awaited.\nasync for row in connection.execute(sql):\n  do_something_with(row)\n```\n\nThis can be used nearly identically to the regular sqlite module if you sprinkle\nan `await` on every function call, but it is preferred to use the async context\nmanagers everywhere possible.  You can't easily go wrong when using the context\nmanagers.\n\nConstants are not re-exported, so this library should usually be used in\nconjunction with the core sqlite3 library.\n\nThis is very similar in spirit to the\n[aiosqlite](https://github.com/omnilib/aiosqlite) project, but this one takes a\nmore earnest attempt at deferring responsibility to other components.  This one\nalso should be more responsive on close, because it doesn't rely on a timeout to\nshut itself off.\n\nThis one also pushes much more extremely on async use, and defers everything it\ncan to the executor thread, even properties.\n\nIf you want a more mature and battle-tested package, use `aiosqlite`.  In my\nrough tests, it performs better than this package as well.\n",
    "bugtrack_url": null,
    "license": null,
    "summary": "An executor-based async sqlite wrapper",
    "version": "1.1.0",
    "split_keywords": [
        "asyncio",
        "sqlite"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "dabd0a1d88c2d2e5c58c0585a20f5a28009438ab7c13d50c646bf53867b11ff7",
                "md5": "0b137ef4a21d77f3ec877e8981e667b8",
                "sha256": "080d7e8f62733a23114b59cb840dc1902298ad9c0ed2f97ca2385f150cf8db24"
            },
            "downloads": -1,
            "filename": "easqlite-1.1.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "0b137ef4a21d77f3ec877e8981e667b8",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.8",
            "size": 10777,
            "upload_time": "2023-04-27T22:35:24",
            "upload_time_iso_8601": "2023-04-27T22:35:24.868518Z",
            "url": "https://files.pythonhosted.org/packages/da/bd/0a1d88c2d2e5c58c0585a20f5a28009438ab7c13d50c646bf53867b11ff7/easqlite-1.1.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "2301674e43e0c5f0d8f656bae59b8a434f49946b48630bc877498ad0924cc576",
                "md5": "3f9ef109654b1267b2fdf591b602b275",
                "sha256": "1587aae4b6c720db374e2f49d3e182db2de72bbcc514e600cbf854a6c6faac2a"
            },
            "downloads": -1,
            "filename": "easqlite-1.1.0.tar.gz",
            "has_sig": false,
            "md5_digest": "3f9ef109654b1267b2fdf591b602b275",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.8",
            "size": 12299,
            "upload_time": "2023-04-27T22:35:27",
            "upload_time_iso_8601": "2023-04-27T22:35:27.374115Z",
            "url": "https://files.pythonhosted.org/packages/23/01/674e43e0c5f0d8f656bae59b8a434f49946b48630bc877498ad0924cc576/easqlite-1.1.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2023-04-27 22:35:27",
    "github": false,
    "gitlab": false,
    "bitbucket": false,
    "lcname": "easqlite"
}
        
Elapsed time: 0.06433s