python-postgres


Namepython-postgres JSON
Version 0.0.5 PyPI version JSON
download
home_pagehttps://github.com/VinzenzKlass/python-postgres
Summarypython-postgres aims to provide the simplest way to interact with PostgreSQL databases.
upload_time2024-12-04 07:02:19
maintainerNone
docs_urlNone
authorVinzenz Klass
requires_python>=3.11
licenseNone
keywords python-postgres postgres
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            <p align="center" style="margin: 0 0 10px">
<img width="200" height="200" src="https://www.postgresql.org/media/img/about/press/elephant.png" alt='Python' style="border-radius: 15px">
</p>

<h1 align="center" style="font-size: 3rem; font-weight: 400; margin: -15px 0">
Python Postgres
</h1>

---

Python Postgres is an abstraction over [psycopg](https://www.psycopg.org/psycopg3/docs/index.html) and aims to provide
the simplest way to interact with PostgreSQL databases in Python.

**I have just started this project, and it is not ready for production use. I am still working on every aspect of it and
may abandon it at any point without warning.**

---

### Installation

```shell
pip install python_postgres 
```

### Basic Usage

```python
from python_postgres import Postgres

pg = Postgres("pgadmin", "password", "pg-is-king.postgres.database.azure.com")


async def main():
    await pg.open()  # Open the connection pool, this requires a running event loop.
    files = await pg("SELECT * FROM files")
    await pg("INSERT INTO files (name, size) VALUES (%s, %s)", [("file1", 1024), ("file2", 2048)])

    async with pg.transaction() as tran:
        file_id = (
            await tran(
                "INSERT INTO files (name, size) VALUES VALUES (%s, %s) RETURNING file_id;",
                ("you_may_not_exist", 0),
            )
        )[0]
        await tran("INSERT INTO pages (page_number, file_id) VALUES (%s, %s);", (4, file_id))
        raise ValueError("Oopsie")
    await pg.close()  # Close the connection pool. Python Postgres will attempt to automatically
    # close the pool when the instance is garbage collected, but this is not guaranteed to succeed.
    # Be civilized and close it yourself.
```

### Pydantic Integration

Python Postgres supports [Pydantic](https://docs.pydantic.dev/latest/) Models as insert parameters.

```python
from pydantic import BaseModel


class File(BaseModel):
    file_name: str
    size: int


async def main():
    await pg.open()
    await pg(
        "INSERT INTO files (file_name, size) VALUES (%s, %s)",
        File(file_name="rubbish.pdf", size=8096),
    )
    await pg.close()
```

### A more in-depth look

The basic idea of this project is to provide one callable instance of the `Postgres` class. The `Postgres` class manages
a connection pool in the background and will get a connection from the pool when called, spawn a binary cursor on it,
run your query, return the results (or the number of rows affected), and then return the connection to the pool. As a
query, you can pass either a literal - string or bytes - or a `SQL` or
`Composed` [object](https://www.psycopg.org/psycopg3/docs/api/sql.html) from the `psycopg` library.

In Essence, the `Postgres` class is syntactic sugar for turning this:

```python
async def exec_query(
        query: LiteralString | bytes | SQL | Composed,
        params: tuple | list[tuple],
        is_retry: bool = False,
) -> list[tuple]:
    try:
        async with con_pool.connection() as con:  # type: psycopg.AsyncConnection
            async with con.cursor(binary=True) as cur:  # type: psycopg.AsyncCursor
                if isinstance(params, list):
                    await cur.executemany(query, params)
                else:
                    await cur.execute(query, params)
                await con.commit()
                return (
                    await cur.fetchall()
                    if cur.pgresult and cur.pgresult.ntuples > 0
                    else cur.rowcount or -1
                )
    except psycopg.OperationalError as error:
        if is_retry:
            raise IOError from error
        await con_pool.check()
        await exec_query(query, params, True)
    except psycopg.Error as error:
        raise IOError from error


await exec_query("SELECT * FROM files WHERE id = %s", (1234,))
```

into

```python
await pg("SELECT * FROM files WHERE id = %s", (1234,))
```

### Notes

Other than providing simpler syntax through a thin abstraction, this project inherits all the design choices of psycopg,
including the [caching of query execution plans](https://www.psycopg.org/psycopg3/docs/advanced/prepare.html#index-0)

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/VinzenzKlass/python-postgres",
    "name": "python-postgres",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.11",
    "maintainer_email": null,
    "keywords": "python-postgres, postgres",
    "author": "Vinzenz Klass",
    "author_email": "vinzenz.klass@ba.valantic.com",
    "download_url": "https://files.pythonhosted.org/packages/a1/7b/48a5f4a1a06609078298dbbb2f596f9c6432a01ad2421c57c6e09b9d6d25/python_postgres-0.0.5.tar.gz",
    "platform": null,
    "description": "<p align=\"center\" style=\"margin: 0 0 10px\">\n<img width=\"200\" height=\"200\" src=\"https://www.postgresql.org/media/img/about/press/elephant.png\" alt='Python' style=\"border-radius: 15px\">\n</p>\n\n<h1 align=\"center\" style=\"font-size: 3rem; font-weight: 400; margin: -15px 0\">\nPython Postgres\n</h1>\n\n---\n\nPython Postgres is an abstraction over [psycopg](https://www.psycopg.org/psycopg3/docs/index.html) and aims to provide\nthe simplest way to interact with PostgreSQL databases in Python.\n\n**I have just started this project, and it is not ready for production use. I am still working on every aspect of it and\nmay abandon it at any point without warning.**\n\n---\n\n### Installation\n\n```shell\npip install python_postgres \n```\n\n### Basic Usage\n\n```python\nfrom python_postgres import Postgres\n\npg = Postgres(\"pgadmin\", \"password\", \"pg-is-king.postgres.database.azure.com\")\n\n\nasync def main():\n    await pg.open()  # Open the connection pool, this requires a running event loop.\n    files = await pg(\"SELECT * FROM files\")\n    await pg(\"INSERT INTO files (name, size) VALUES (%s, %s)\", [(\"file1\", 1024), (\"file2\", 2048)])\n\n    async with pg.transaction() as tran:\n        file_id = (\n            await tran(\n                \"INSERT INTO files (name, size) VALUES VALUES (%s, %s) RETURNING file_id;\",\n                (\"you_may_not_exist\", 0),\n            )\n        )[0]\n        await tran(\"INSERT INTO pages (page_number, file_id) VALUES (%s, %s);\", (4, file_id))\n        raise ValueError(\"Oopsie\")\n    await pg.close()  # Close the connection pool. Python Postgres will attempt to automatically\n    # close the pool when the instance is garbage collected, but this is not guaranteed to succeed.\n    # Be civilized and close it yourself.\n```\n\n### Pydantic Integration\n\nPython Postgres supports [Pydantic](https://docs.pydantic.dev/latest/) Models as insert parameters.\n\n```python\nfrom pydantic import BaseModel\n\n\nclass File(BaseModel):\n    file_name: str\n    size: int\n\n\nasync def main():\n    await pg.open()\n    await pg(\n        \"INSERT INTO files (file_name, size) VALUES (%s, %s)\",\n        File(file_name=\"rubbish.pdf\", size=8096),\n    )\n    await pg.close()\n```\n\n### A more in-depth look\n\nThe basic idea of this project is to provide one callable instance of the `Postgres` class. The `Postgres` class manages\na connection pool in the background and will get a connection from the pool when called, spawn a binary cursor on it,\nrun your query, return the results (or the number of rows affected), and then return the connection to the pool. As a\nquery, you can pass either a literal - string or bytes - or a `SQL` or\n`Composed` [object](https://www.psycopg.org/psycopg3/docs/api/sql.html) from the `psycopg` library.\n\nIn Essence, the `Postgres` class is syntactic sugar for turning this:\n\n```python\nasync def exec_query(\n        query: LiteralString | bytes | SQL | Composed,\n        params: tuple | list[tuple],\n        is_retry: bool = False,\n) -> list[tuple]:\n    try:\n        async with con_pool.connection() as con:  # type: psycopg.AsyncConnection\n            async with con.cursor(binary=True) as cur:  # type: psycopg.AsyncCursor\n                if isinstance(params, list):\n                    await cur.executemany(query, params)\n                else:\n                    await cur.execute(query, params)\n                await con.commit()\n                return (\n                    await cur.fetchall()\n                    if cur.pgresult and cur.pgresult.ntuples > 0\n                    else cur.rowcount or -1\n                )\n    except psycopg.OperationalError as error:\n        if is_retry:\n            raise IOError from error\n        await con_pool.check()\n        await exec_query(query, params, True)\n    except psycopg.Error as error:\n        raise IOError from error\n\n\nawait exec_query(\"SELECT * FROM files WHERE id = %s\", (1234,))\n```\n\ninto\n\n```python\nawait pg(\"SELECT * FROM files WHERE id = %s\", (1234,))\n```\n\n### Notes\n\nOther than providing simpler syntax through a thin abstraction, this project inherits all the design choices of psycopg,\nincluding the [caching of query execution plans](https://www.psycopg.org/psycopg3/docs/advanced/prepare.html#index-0)\n",
    "bugtrack_url": null,
    "license": null,
    "summary": "python-postgres aims to provide the simplest way to interact with PostgreSQL databases.",
    "version": "0.0.5",
    "project_urls": {
        "Homepage": "https://github.com/VinzenzKlass/python-postgres",
        "Repository": "https://github.com/VinzenzKlass/python-postgres"
    },
    "split_keywords": [
        "python-postgres",
        " postgres"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "5372aeef55e06e11e2d962bb7fd350cac2b08d657acead574ee636ac30852c51",
                "md5": "a1be2524813bd48fbfc10b54f6e7342b",
                "sha256": "9fbfaf26a2e82968c2847780f820763b3513ee05b3763de111fd680183b2d928"
            },
            "downloads": -1,
            "filename": "python_postgres-0.0.5-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "a1be2524813bd48fbfc10b54f6e7342b",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.11",
            "size": 6145,
            "upload_time": "2024-12-04T07:02:17",
            "upload_time_iso_8601": "2024-12-04T07:02:17.830294Z",
            "url": "https://files.pythonhosted.org/packages/53/72/aeef55e06e11e2d962bb7fd350cac2b08d657acead574ee636ac30852c51/python_postgres-0.0.5-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "a17b48a5f4a1a06609078298dbbb2f596f9c6432a01ad2421c57c6e09b9d6d25",
                "md5": "4eda87c3084eb2fb306261e84e1eb363",
                "sha256": "aa923723a821e90c3e85607f3572667d81cbf7f90969b2125cc204bf2fc0b825"
            },
            "downloads": -1,
            "filename": "python_postgres-0.0.5.tar.gz",
            "has_sig": false,
            "md5_digest": "4eda87c3084eb2fb306261e84e1eb363",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.11",
            "size": 5159,
            "upload_time": "2024-12-04T07:02:19",
            "upload_time_iso_8601": "2024-12-04T07:02:19.313070Z",
            "url": "https://files.pythonhosted.org/packages/a1/7b/48a5f4a1a06609078298dbbb2f596f9c6432a01ad2421c57c6e09b9d6d25/python_postgres-0.0.5.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-12-04 07:02:19",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "VinzenzKlass",
    "github_project": "python-postgres",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "python-postgres"
}
        
Elapsed time: 4.24118s