{ "info": { "author": "Lele Gaifax", "author_email": "lele@metapensiero.it", "bugtrack_url": null, "classifiers": [ "Development Status :: 3 - Alpha", "Programming Language :: Python", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6" ], "description": ".. -*- coding: utf-8 -*-\n.. :Project: metapensiero.sqlalchemy.asyncpg -- SQLAlchemy adaptor for asyncpg\n.. :Created: Tue 20 Dec 2016 21:17:12 CET\n.. :Author: Lele Gaifax \n.. :License: GNU General Public License version 3 or later\n.. :Copyright: \u00a9 2016, 2017 Lele Gaifax\n..\n\n=================================\n metapensiero.sqlalchemy.asyncpg\n=================================\n\nSQLAlchemy adaptor for asyncpg\n==============================\n\n :author: Lele Gaifax\n :contact: lele@metapensiero.it\n :license: GNU General Public License version 3 or later\n\nThis is a Python 3 package, spin-off from the proprietary ``Ytefas`` application, that\nimplements the ability of executing SQLAlchemy core statements through asyncpg__, in a\ncleaner way than asyncpgsa__ (I'm biased, of course \ud83d\ude1c): the main difference is that it\nuses explicitly typed parameter placeholders, to avoid `the problem`__ that initially\nprompted me to write this package.\n\nIt emits ``DEBUG`` logs with `prettified`__ SQL statements, with *parameters* resolved to\nthe actual *values*, and supplies an asyncpg variant of `metapensiero.sqlalchemy.proxy`__\n\\ 's ProxiedQuery__.\n\n\n__ https://pypi.python.org/pypi/asyncpg\n__ https://pypi.python.org/pypi/asyncpgsa\n__ https://github.com/MagicStack/asyncpg/issues/32\n__ https://pypi.python.org/pypi/metapensiero.sqlalchemy.proxy\n__ http://metapensierosqlalchemyproxy.readthedocs.io/en/latest/\\\n core.html#metapensiero.sqlalchemy.proxy.core.ProxiedQuery\n__ http://pg-query.readthedocs.io/en/latest/\n\n\nTypical usage\n-------------\n\nThe following script:\n\n.. code-block:: python\n\n import asyncio\n from datetime import date\n import logging\n\n import sqlalchemy as sa\n from asyncpg import create_pool\n from asyncpg.types import Range\n from metapensiero.sqlalchemy import asyncpg as sasyncpg\n\n\n async def dml_tests(connection):\n sasyncpg_test = sa.Table('sasyncpg_test', sa.MetaData(),\n sa.Column('id', sa.types.Integer, primary_key=True),\n sa.Column('value', sa.types.Text),\n sa.Column('period', sa.dialects.postgresql.DATERANGE))\n\n value = 'First test'\n insert_stmt = sasyncpg_test.insert().values(id=1, value=value)\n await connection.execute(insert_stmt)\n\n new_value = 'Second test'\n update_stmt = (sasyncpg_test.update()\n .values(value=new_value,\n period=Range(date(2016, 2, 1), date(2016, 3, 1)))\n .where(sasyncpg_test.c.id == 1))\n await connection.execute(update_stmt)\n\n select_stmt = (sa.select([sasyncpg_test.c.value])\n .where(sasyncpg_test.c.id == sa.bindparam('id')))\n for row in await connection.fetchall(select_stmt, named_args={'id': 1}):\n print('Row:', row)\n\n single_row = (sa.select([sasyncpg_test])\n .where(sasyncpg_test.c.period.contains(date(2016, 2, 15))))\n print('Row:', await connection.fetchone(single_row))\n\n\n async def run(loop):\n pool = await create_pool(database=\"test\", loop=loop)\n\n async with pool.acquire() as apgc:\n connection = sasyncpg.Connection(apgc)\n\n query = sa.select([sa.func.version()])\n result = await connection.scalar(query)\n print(\"PostgreSQL version:\", result)\n\n await connection.execute('create table sasyncpg_test ('\n ' id integer not null primary key,'\n ' value text,'\n ' period daterange)')\n\n try:\n await dml_tests(connection)\n finally:\n await connection.execute('DROP TABLE sasyncpg_test')\n\n\n def main():\n loop = asyncio.get_event_loop()\n loop.run_until_complete(run(loop))\n\n\n if __name__ == '__main__':\n logging.basicConfig(level=logging.DEBUG)\n main()\n\nproduces something like::\n\n DEBUG:asyncio:Using selector: EpollSelector\n DEBUG:metapensiero.sqlalchemy.asyncpg.funcs:Fetching scalar in transaction 9ddb60:\n SELECT version() AS version_1\n DEBUG:metapensiero.sqlalchemy.asyncpg.funcs:Fetched value in 869 \u00b5sec\n PostgreSQL version: PostgreSQL 9.6.6 on x86_64-pc-linux-gnu, compiled by gcc (Debian 7.2.0-12) 7.2.1 20171025, 64-bit\n DEBUG:metapensiero.sqlalchemy.asyncpg.funcs:Executing in transaction 9ddb60:\n CREATE TABLE sasyncpg_test (\n id integer NOT NULL PRIMARY KEY, value text, period daterange\n )\n DEBUG:metapensiero.sqlalchemy.asyncpg.funcs:Execution took 97.1 msec\n DEBUG:metapensiero.sqlalchemy.asyncpg.funcs:Executing in transaction 9ddb60:\n INSERT INTO sasyncpg_test (id, value)\n VALUES (1::integer, 'First test'::text)\n DEBUG:metapensiero.sqlalchemy.asyncpg.funcs:Execution took 1.26 msec\n DEBUG:metapensiero.sqlalchemy.asyncpg.funcs:Executing in transaction 9ddb60:\n UPDATE sasyncpg_test\n SET value = 'Second test'::text, period = '[2016-02-01,2016-03-01)'::daterange\n WHERE sasyncpg_test.id = 1::integer\n DEBUG:metapensiero.sqlalchemy.asyncpg.funcs:Execution took 14.1 msec\n DEBUG:metapensiero.sqlalchemy.asyncpg.funcs:Fetching rows in transaction 9ddb60:\n SELECT sasyncpg_test.value\n FROM sasyncpg_test\n WHERE sasyncpg_test.id = 1::integer\n DEBUG:metapensiero.sqlalchemy.asyncpg.funcs:Fetched 1 records in 909 \u00b5sec\n Row: \n DEBUG:metapensiero.sqlalchemy.asyncpg.funcs:Fetching row in transaction 9ddb60:\n SELECT sasyncpg_test.id, sasyncpg_test.value, sasyncpg_test.period\n FROM sasyncpg_test\n WHERE sasyncpg_test.period @> datetime.date(2016, 2, 15)::date\n DEBUG:metapensiero.sqlalchemy.asyncpg.funcs:Fetched one record in 951 \u00b5sec\n Row: >\n DEBUG:metapensiero.sqlalchemy.asyncpg.funcs:Executing in transaction 9ddb60:\n DROP TABLE sasyncpg_test RESTRICT\n DEBUG:metapensiero.sqlalchemy.asyncpg.funcs:Execution took 12 msec\n\n\n.. -*- coding: utf-8 -*-\n\nChanges\n-------\n\n0.1 (2017-12-03)\n~~~~~~~~~~~~~~~~\n\n- Standalone package, released under GPLv3\n\n\n0.0 (unreleased)\n~~~~~~~~~~~~~~~~\n\n- Initial effort.\n", "description_content_type": null, "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://gitlab.com/metapensiero/metapensiero.sqlalchemy.asyncpg.git", "keywords": "", "license": "GPLv3+", "maintainer": "", "maintainer_email": "", "name": "metapensiero.sqlalchemy.asyncpg", "package_url": "https://pypi.org/project/metapensiero.sqlalchemy.asyncpg/", "platform": "", "project_url": "https://pypi.org/project/metapensiero.sqlalchemy.asyncpg/", "project_urls": { "Homepage": "https://gitlab.com/metapensiero/metapensiero.sqlalchemy.asyncpg.git" }, "release_url": "https://pypi.org/project/metapensiero.sqlalchemy.asyncpg/0.1/", "requires_dist": null, "requires_python": "", "summary": "SQLAlchemy adaptor for asyncpg", "version": "0.1" }, "last_serial": 3384600, "releases": { "0.1": [ { "comment_text": "", "digests": { "md5": "b2b583094f60f78fffcb634093148a71", "sha256": "0399642907cb00d3c9f2c8401867747defd3f19981d4af8b9a9153c0d4599dcb" }, "downloads": -1, "filename": "metapensiero.sqlalchemy.asyncpg-0.1.tar.gz", "has_sig": false, "md5_digest": "b2b583094f60f78fffcb634093148a71", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 19599, "upload_time": "2017-12-03T11:56:31", "url": "https://files.pythonhosted.org/packages/da/b1/c94df67930b6fe2e382734f991a1908207166dbf2f322ff92f06a777c2e9/metapensiero.sqlalchemy.asyncpg-0.1.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "b2b583094f60f78fffcb634093148a71", "sha256": "0399642907cb00d3c9f2c8401867747defd3f19981d4af8b9a9153c0d4599dcb" }, "downloads": -1, "filename": "metapensiero.sqlalchemy.asyncpg-0.1.tar.gz", "has_sig": false, "md5_digest": "b2b583094f60f78fffcb634093148a71", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 19599, "upload_time": "2017-12-03T11:56:31", "url": "https://files.pythonhosted.org/packages/da/b1/c94df67930b6fe2e382734f991a1908207166dbf2f322ff92f06a777c2e9/metapensiero.sqlalchemy.asyncpg-0.1.tar.gz" } ] }