# p3orm
<a href="https://rafalstapinski.github.io/p3orm">
<img src="https://rafalstapinski.github.io/p3orm/img/logo.svg" alt="p3orm logo" />
</a>
<p align="center">
<strong>
<em>
Utilitarian Python ORM for Postgres/SQLite powered by <a href="https://github.com/MagicStack/asyncpg">asyncpg</a>/<a href="https://github.com/omnilib/aiosqlite">aiosqlite</a>, <a href="https://github.com/samuelcolvin/pydantic">Pydantic</a>, and <a href="https://github.com/kayak/pypika">PyPika</a>
</em>
</strong>
</p>
---
**Documentation**: <a href="https://rafalstapinski.github.io/p3orm">https://rafalstapinski.github.io/p3orm</a>
**Source Code**: <a href="https://github.com/rafalstapinski/p3orm">https://github.com/rafalstapinski/p3orm</a>
---
<p align="center">
<a href="https://github.com/rafalstapinski/p3orm/actions/workflows/test.yml" target="_blank">
<img src="https://github.com/rafalstapinski/p3orm/actions/workflows/test.yml/badge.svg" alt="Test Status" />
</a>
<a href="https://pypi.org/project/p3orm" target="_blank">
<img src="https://img.shields.io/pypi/v/p3orm?color=%2334D058" alt="pypi" />
</a>
<a href="https://pypi.org/project/p3orm" target="_blank">
<img src="https://img.shields.io/pypi/pyversions/p3orm?color=%23334D058" alt="Supported Python Versions: 3.8, 3.9, 3.10" />
</a>
<a href="https://github.com/rafalstapinski/p3orm/blob/master/LICENSE" target="_blank">
<img src="https://img.shields.io/pypi/l/p3orm?color=%23334D058" alt="MIT License" />
</a>
</p>
---
<h2>Philosophy</h2>
90% of the time we talk to a database is with a CRUD operation. p3orm provides convenience helpers for fetching (one, first, many), inserting (one, many), updating (one), and deleting (one, many).
The remaining 10% is a bit more complicated. p3orm doesn't attempt to hide SQL queries or database interactions behind any magic. Instead, it empowers you to write direct and legible SQL queries with [PyPika](https://github.com/kayak/pypika) and execute them explicitly against the database.
Notably, objects created or fetched by p3orm are dead, they're just [Pydantic](https://github.com/samuelcolvin/pydantic) models. If you want to interact with the database, you do so explicitly.
### tl;dr - p3orm makes easy things easy, and hard things possible
---
<h2>Features</h2>
- Comprehensive type annotations (full intellisense support)
- String type validation an parsing powered by `Pydantic`
- Support for `PyPika` queries
- Support for all `postgres` [datatypes](https://magicstack.github.io/asyncpg/current/usage.html#type-conversion)
- Support for all `sqlite` [datatypes](https://www.sqlite.org/datatype3.html)
---
<h2>Installation</h2>
Install with `poetry`
```sh
poetry add p3orm[sqlite]
# or
poetry add p3orm[postgres]
```
or with `pip`
```sh
pip install p3orm[sqlite]
# or
pip install p3orm[postgres]
```
The `[sqlite]` extra installs `aiosqlite` as p3orm's database driver, whereas `[postgres]` installs `asyncpg`.
---
<h2>Basic Usage</h2>
```python
from datetime import datetime
from p3orm import Column, Table
from p3orm import sqlite as db
# or: from p3orm import postgres as db
class Thing(Table):
id = Column(int, pk=True, autogen=True)
name = Column(str)
created_at = Column(datetime, autogen=True)
await db().connect(":memory:")
thing = Thing(name="Name")
inserted = await Thing.insert_one(thing)
fetched = await Thing.fetch_first(Thing.id == 1)
fetched.name = "Changed"
updated = await Thing.update_one(fetched)
deleted = await Thing.delete_where(Thing.id == updated.id)
await db().disconnect()
```
Raw data
{
"_id": null,
"home_page": "https://rafalstapinski.github.io/p3orm",
"name": "p3orm",
"maintainer": "",
"docs_url": null,
"requires_python": ">=3.9,<4.0",
"maintainer_email": "",
"keywords": "postgres,sqlite,async,orm",
"author": "Rafal Stapinski",
"author_email": "stapinskirafal@gmail.com",
"download_url": "https://files.pythonhosted.org/packages/ca/98/4a7102897228b0d6f6b9eba6e9e630ee1c376dedfdf2d0bea04ac2c94e6a/p3orm-0.10.3.tar.gz",
"platform": null,
"description": "# p3orm\n\n<a href=\"https://rafalstapinski.github.io/p3orm\">\n <img src=\"https://rafalstapinski.github.io/p3orm/img/logo.svg\" alt=\"p3orm logo\" />\n</a>\n\n<p align=\"center\">\n <strong>\n <em>\n Utilitarian Python ORM for Postgres/SQLite powered by <a href=\"https://github.com/MagicStack/asyncpg\">asyncpg</a>/<a href=\"https://github.com/omnilib/aiosqlite\">aiosqlite</a>, <a href=\"https://github.com/samuelcolvin/pydantic\">Pydantic</a>, and <a href=\"https://github.com/kayak/pypika\">PyPika</a>\n </em>\n </strong>\n</p>\n\n---\n\n**Documentation**: <a href=\"https://rafalstapinski.github.io/p3orm\">https://rafalstapinski.github.io/p3orm</a>\n\n**Source Code**: <a href=\"https://github.com/rafalstapinski/p3orm\">https://github.com/rafalstapinski/p3orm</a>\n\n---\n\n<p align=\"center\">\n <a href=\"https://github.com/rafalstapinski/p3orm/actions/workflows/test.yml\" target=\"_blank\">\n <img src=\"https://github.com/rafalstapinski/p3orm/actions/workflows/test.yml/badge.svg\" alt=\"Test Status\" />\n </a>\n <a href=\"https://pypi.org/project/p3orm\" target=\"_blank\">\n <img src=\"https://img.shields.io/pypi/v/p3orm?color=%2334D058\" alt=\"pypi\" />\n </a>\n <a href=\"https://pypi.org/project/p3orm\" target=\"_blank\">\n <img src=\"https://img.shields.io/pypi/pyversions/p3orm?color=%23334D058\" alt=\"Supported Python Versions: 3.8, 3.9, 3.10\" />\n </a>\n <a href=\"https://github.com/rafalstapinski/p3orm/blob/master/LICENSE\" target=\"_blank\">\n <img src=\"https://img.shields.io/pypi/l/p3orm?color=%23334D058\" alt=\"MIT License\" />\n </a>\n</p>\n\n---\n<h2>Philosophy</h2>\n\n90% of the time we talk to a database is with a CRUD operation. p3orm provides convenience helpers for fetching (one, first, many), inserting (one, many), updating (one), and deleting (one, many).\n\nThe remaining 10% is a bit more complicated. p3orm doesn't attempt to hide SQL queries or database interactions behind any magic. Instead, it empowers you to write direct and legible SQL queries with [PyPika](https://github.com/kayak/pypika) and execute them explicitly against the database.\n\nNotably, objects created or fetched by p3orm are dead, they're just [Pydantic](https://github.com/samuelcolvin/pydantic) models. If you want to interact with the database, you do so explicitly.\n\n### tl;dr - p3orm makes easy things easy, and hard things possible\n\n---\n<h2>Features</h2>\n\n- Comprehensive type annotations (full intellisense support)\n- String type validation an parsing powered by `Pydantic`\n- Support for `PyPika` queries\n- Support for all `postgres` [datatypes](https://magicstack.github.io/asyncpg/current/usage.html#type-conversion)\n- Support for all `sqlite` [datatypes](https://www.sqlite.org/datatype3.html)\n\n---\n<h2>Installation</h2>\n\nInstall with `poetry`\n```sh\npoetry add p3orm[sqlite]\n# or\npoetry add p3orm[postgres]\n```\n\nor with `pip`\n\n```sh\npip install p3orm[sqlite]\n# or\npip install p3orm[postgres]\n```\n\nThe `[sqlite]` extra installs `aiosqlite` as p3orm's database driver, whereas `[postgres]` installs `asyncpg`.\n\n---\n<h2>Basic Usage</h2>\n\n```python\nfrom datetime import datetime\nfrom p3orm import Column, Table\n\nfrom p3orm import sqlite as db\n# or: from p3orm import postgres as db\n\nclass Thing(Table):\n id = Column(int, pk=True, autogen=True)\n name = Column(str)\n created_at = Column(datetime, autogen=True)\n\nawait db().connect(\":memory:\")\n\nthing = Thing(name=\"Name\")\n\ninserted = await Thing.insert_one(thing)\n\nfetched = await Thing.fetch_first(Thing.id == 1)\n\nfetched.name = \"Changed\"\n\nupdated = await Thing.update_one(fetched)\n\ndeleted = await Thing.delete_where(Thing.id == updated.id)\n\nawait db().disconnect()\n```\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Utilitarian Python ORM for Postgres/SQLite, backed by asyncpg/aiosqlite, Pydantic, and PyPika",
"version": "0.10.3",
"project_urls": {
"Homepage": "https://rafalstapinski.github.io/p3orm",
"Repository": "https://github.com/rafalstapinski/p3orm"
},
"split_keywords": [
"postgres",
"sqlite",
"async",
"orm"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "b74e0b6809c061a2c96af08a5c02ba5fd823a48b72297d1142694b25a74f165f",
"md5": "fe83131b7b0808b94f665a78e3140c8c",
"sha256": "238c2cfb06a29e0057dd40ee83146d04a10e3c15233cf3b0daf6f443c7377c93"
},
"downloads": -1,
"filename": "p3orm-0.10.3-py3-none-any.whl",
"has_sig": false,
"md5_digest": "fe83131b7b0808b94f665a78e3140c8c",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.9,<4.0",
"size": 13511,
"upload_time": "2023-11-30T05:13:09",
"upload_time_iso_8601": "2023-11-30T05:13:09.096839Z",
"url": "https://files.pythonhosted.org/packages/b7/4e/0b6809c061a2c96af08a5c02ba5fd823a48b72297d1142694b25a74f165f/p3orm-0.10.3-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "ca984a7102897228b0d6f6b9eba6e9e630ee1c376dedfdf2d0bea04ac2c94e6a",
"md5": "732af7a3f96655b909dea2cc6b3a4c7a",
"sha256": "7438bef916283fcd4c4094a5b916380a19330913ad70517b31be41869aca0cc7"
},
"downloads": -1,
"filename": "p3orm-0.10.3.tar.gz",
"has_sig": false,
"md5_digest": "732af7a3f96655b909dea2cc6b3a4c7a",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.9,<4.0",
"size": 11748,
"upload_time": "2023-11-30T05:13:10",
"upload_time_iso_8601": "2023-11-30T05:13:10.868335Z",
"url": "https://files.pythonhosted.org/packages/ca/98/4a7102897228b0d6f6b9eba6e9e630ee1c376dedfdf2d0bea04ac2c94e6a/p3orm-0.10.3.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2023-11-30 05:13:10",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "rafalstapinski",
"github_project": "p3orm",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "p3orm"
}