{"id":17305107,"url":"https://github.com/seandstewart/yesql","last_synced_at":"2025-04-14T13:22:20.708Z","repository":{"id":97741534,"uuid":"387822235","full_name":"seandstewart/yesql","owner":"seandstewart","description":"YeSQL is a SQL-first data manipulation library that will replace your ORM.","archived":false,"fork":false,"pushed_at":"2024-07-26T22:02:14.000Z","size":573,"stargazers_count":17,"open_issues_count":1,"forks_count":1,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-03-28T02:38:03.621Z","etag":null,"topics":["database","dbapi","dbapi2","orm","postgresql","sql","sqlite"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/seandstewart.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-07-20T14:42:32.000Z","updated_at":"2025-02-26T17:17:33.000Z","dependencies_parsed_at":"2024-07-26T23:22:44.925Z","dependency_job_id":"a582a97d-4405-4cd4-b4f9-93f927b9ed13","html_url":"https://github.com/seandstewart/yesql","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seandstewart%2Fyesql","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seandstewart%2Fyesql/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seandstewart%2Fyesql/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seandstewart%2Fyesql/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/seandstewart","download_url":"https://codeload.github.com/seandstewart/yesql/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248886513,"owners_count":21177680,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["database","dbapi","dbapi2","orm","postgresql","sql","sqlite"],"created_at":"2024-10-15T11:54:41.150Z","updated_at":"2025-04-14T13:22:20.678Z","avatar_url":"https://github.com/seandstewart.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# yesql\n\n[![image](https://img.shields.io/pypi/v/yesql.svg)](https://pypi.org/project/yesql/)\n[![image](https://img.shields.io/pypi/l/yesql.svg)](https://pypi.org/project/yesql/)\n[![image](https://img.shields.io/pypi/pyversions/yesql.svg)](https://pypi.org/project/yesql/)\n[![image](https://img.shields.io/github/languages/code-size/seandstewart/yesql.svg?style=flat)](https://github.com/seandstewart/yesql)\n[![Test \u0026 Lint](https://github.com/seandstewart/yesql/workflows/Test/badge.svg)](https://github.com/seandstewart/yesql/actions)\n[![Coverage](https://codecov.io/gh/seandstewart/yesql/branch/main/graph/badge.svg)](https://codecov.io/gh/seandstewart/yesql)\n[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/ambv/black)\n\n\nSay _yes_ to _SQL_ with **yesql**. \n\nyesql eliminates boilerplate without the baggage of an expensive or clunky ORM. \nSimply write your SQL, point yesql to the directory, and it does all the rest.\n\n## Quickstart\n\n### Installation\n\n```shell\npip install -U --pre yesql\n```\nor\n```shell\npoetry add --allow-prereleases yesql\n```\n\nyesql currently supports the following database drivers:\n\n- [asyncpg][1]\n- [psycopg][2]\n\nYou can select your driver as an extra when installing yesql _(recommended)_:\n\n```shell\npip install -U --pre \"yesql[psycopg]\"\n```\nor\n```shell\npoetry add --allow-prereleases yesql -E asyncpg\n```\n\n### Basic Usage\n\n```python\nfrom __future__ import annotations\n\nimport dataclasses\nimport datetime\nimport pathlib\n\nimport yesql\n\n\nQUERIES = pathlib.Path(__file__).resolve().parent / \"queries\"\n\n\n@dataclasses.dataclass(slots=True, kw_only=True)\nclass Post:\n    id: int | None = None\n    slug: str | None = None\n    title: str | None = None\n    subtitle: str | None = None\n    tagline: str | None = None\n    body: str | None = None\n    tags: set[str] = dataclasses.field(default_factory=set)\n    publication_date: datetime.date | None = None\n    created_at: datetime.datetime | None = None\n    updated_at: datetime.datetime | None = None\n\n\n\nclass PostsRepository(yesql.SyncQueryRepository[Post]):\n    \"\"\"An asyncio-native service for querying blog posts.\"\"\"\n\n    class metadata(yesql.QueryMetadata):\n        __querylib__ = QUERIES\n        __tablename__ = \"posts\"\n        __exclude_fields__ = frozenset((\"slug\",))\n\n\n\nposts = PostsRepository()\nposts.initialize()\nnew_post = Post(\n    title=\"My Great Blog Post\",\n    subtitle=\"It's super great. Trust me...\",\n    tagline=\"You'll be glad you read it.\",\n    tags={\"tips\", \"tricks\", \"cool stuff\"},\n)\nsaved_post = posts.create(instance=new_post)\n```\n\n#### Type-stub Generation (Experimental)\n\nyesql ships with simple CLI for generating type-stubs. This allows for more exact \nstatic type-analysis and enables auto-complete for your IDE.\n\nUsage:\n\n```shell\nyesql stubgen\n```\n\nYou can optionally supply any number of paths to directories or python modules. The \ncommand will default to the current working directory on the filesystem.\n\nIf you don't have [black][3] installed in your development environment, you should add \nthe `cli` extra as a development dependency.\n\n## Features\n\n- [x] Support for synchronous IO\n- [x] Support for asynchronous IO (asyncio)\n- [x] Support for PostgreSQL\n- [x] Plays well with MyPy\n- [x] Plays well with IDEs\n- [x] Encourages best-practices for data-access (Separation of Concerns, Repository \n  Pattern)\n\n## No ORMs?\n\n1. *ORMs are bad for you.*  \n   They are a leaky abstraction that cannot solve the problem they set out to do - which\n   is to abstract out the details of working with a database.\n\n2. *ORMs are slow.*  \n   ORMs depend upon a high level of abstraction in order to work across database \n   clients. They also attempt to bridge the gap of data validation and  state \n   management. By attempting to hide the details of managing state from the end\n   user, they suffer from large computational costs and predict\n\n3. *ORMs are wasteful.*  \n   As mentioned above, ORMs use a huge amount of resources to auto-magically determine\n   state for anything and everything currently pulled into your application's memory.\n   Because this is implicit, this takes a large amount of work to do right. In general,\n   your application is already aware of \"clean\" and \"dirty\" states. Your application\n   should be in charge of managing it.\n\n4. *ORMs encourage bad data modeling.*  \n   ORMs vastly simplify recursive data modeling (see: N+1 problem) which encourages lazy\n   solutions to simple problems and can result in extreme service degradation without\n   reasonable means of mitigation.\n\n\n## Why yesql?\n\nyesql takes a SQL-first approach to data management:\n\n1. *Focus on your SQL and your database.*\n   - Reduce developer overhead by having one less middleman between you and your data.\n   - Easily fine-tune your SQL to take full advantage of the RDBMS you choose.\n   - No guesswork about what SQL is actually being executed on your database.\n\n2. *Explicit state management.*\n   - No surprise writes or reads, you control when you read and when you write.\n   - There is no question whether data is in-memory or in the database.\n\n3. *Plain Ol' Data Objects.*\n   - Model your data with a mapping, a namedtuple, a dataclass, or just use the native\n     record objects of your preferred library.\n   - Loose ser/des based on your model, which can be overridden at any point.\n   - No implicit state mapping of data from a table to your model. Your query powers \n     your model.\n\n## v1.0.0 Roadmap\n\n- [x] Query Library Bootstrapping\n- [x] Dynamic Query Library\n- [ ] Full Documentation Coverage\n- [ ] Full Test Coverage\n- [ ] Dialect Support\n  - [x] Async PostgreSQL (via asyncpg \u0026 psycopg3)\n  - [ ] Async SQLite\n  - [ ] Async MySQL\n  - [x] Sync PostgreSQL\n  - [ ] Sync SQLite\n  - [ ] Sync MySQL\n\n## License\n\n[MIT](https://sean-dstewart.mit-license.org/)\n\n\n[1]: https://magicstack.github.io/asyncpg/current/\n[2]: https://www.psycopg.org/psycopg3/docs/\n[3]: https://black.readthedocs.io/en/stable/","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fseandstewart%2Fyesql","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fseandstewart%2Fyesql","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fseandstewart%2Fyesql/lists"}