dclassql


Namedclassql JSON
Version 0.1.3 PyPI version JSON
download
home_pageNone
SummaryA type-safe ORM generator for Python, creating fully type-hinted database clients from plain dataclass definitions.
upload_time2025-11-06 07:24:49
maintainerNone
docs_urlNone
authormyuanz
requires_python>=3.12
licenseMIT
keywords orm codegen sqlite dataclass typed
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # DataclassQL

DataclassQL 是一个基于 **平凡 dataclass 定义** 的 ORM 生成器, 可生成类型提示完整精巧的数据库客户端. 

模型文件保持干净、直观, 无需起手加一堆导入, 也没有 `mapped_column()`、`Annotation` 或额外的基类继承, 只需要 `dataclass`

---

## 设计目标

* **最小语法负担**: 模型定义就是合法平凡的 Python dataclass, Python 即 DSL
* **常用路径简洁**: 常用的定义只需要写少量的代码
* **静态类型安全**: 模型定义和生成代码全都类型安全. 本库作为 [prisma client python](https://prisma-client-py.readthedocs.io/en/stable/) 的精神继承者, 致力于完成如下体验: 

![](https://prisma-client-py.readthedocs.io/en/stable/showcase.gif)

---

## 示例

```python
from dataclasses import dataclass
from datetime import datetime

@dataclass
class User:
    id: int
    name: str
    email: str
    last_login: datetime

    def index(self):
        yield self.name
        yield self.last_login

    def unique_index(self):
        yield self.name, self.email
```

写出如下代码时: 

```python
from dclassql import client

client.user.insert({
    "name": "Alice",
    "email": "test@example.com",
})
```

将在类型空间得到报错: 

```
error: Argument of type "dict[str, str]" cannot be assigned to parameter "data" of type "UserInsertDict" in function "insert"
    "last_login" is required in "UserInsertDict" (reportArgumentType)
```


## 安装

```
uv add dclassql
```

## 当前状态

DataclassQL 仍在早期开发阶段, 已完成代码生成和 SQLite 支持, 后续将扩展更多数据库与查询功能. 

## 一份更长的例子

```python
from dataclasses import dataclass
from datetime import datetime

__datasource__ = {
    "provider": "sqlite",
    "url": "sqlite:///test.db",
}


@dataclass
class Address:
    id: int
    location: str
    user_id: int
    user: 'User'

    def foreign_key(self):
        yield self.user.id == self.user_id, User.addresses


@dataclass
class BirthDay:
    user_id: int
    user: 'User'
    date: datetime

    def primary_key(self):
        return self.user_id

    def foreign_key(self):
        yield self.user.id == self.user_id, User.birthday


@dataclass
class Book:
    id: int
    name: str
    users: list['UserBook']

    def index(self):
        return self.name


@dataclass
class UserBook:
    user_id: int
    book_id: int
    user: 'User'
    book: Book
    created_at: datetime

    def primary_key(self):
        return (self.user_id, self.book_id)

    def index(self):
        yield self.created_at

    def foreign_key(self):
        yield self.user.id == self.user_id, User.books
        yield self.book.id == self.book_id, Book.users


@dataclass
class User:
    id: int | None
    name: str
    email: str
    last_login: datetime
    birthday: BirthDay | None
    addresses: list[Address]
    books: list[UserBook]

    def index(self):
        yield self.name
        yield self.name, self.email
        yield self.last_login

    def unique_index(self):
        yield self.name, self.email

```

生成的代码请见: https://github.com/myuanz/dataclassql/blob/master/tests/results.py

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "dclassql",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.12",
    "maintainer_email": null,
    "keywords": "orm, codegen, sqlite, dataclass, typed",
    "author": "myuanz",
    "author_email": "myuanz <provefars@gmail.com>",
    "download_url": "https://files.pythonhosted.org/packages/e5/01/1a93eb29858040ebdfc3b8f593ac6492909ca7ef789987f5cc5dada2e110/dclassql-0.1.3.tar.gz",
    "platform": null,
    "description": "# DataclassQL\n\nDataclassQL \u662f\u4e00\u4e2a\u57fa\u4e8e **\u5e73\u51e1 dataclass \u5b9a\u4e49** \u7684 ORM \u751f\u6210\u5668, \u53ef\u751f\u6210\u7c7b\u578b\u63d0\u793a\u5b8c\u6574\u7cbe\u5de7\u7684\u6570\u636e\u5e93\u5ba2\u6237\u7aef. \n\n\u6a21\u578b\u6587\u4ef6\u4fdd\u6301\u5e72\u51c0\u3001\u76f4\u89c2, \u65e0\u9700\u8d77\u624b\u52a0\u4e00\u5806\u5bfc\u5165, \u4e5f\u6ca1\u6709 `mapped_column()`\u3001`Annotation` \u6216\u989d\u5916\u7684\u57fa\u7c7b\u7ee7\u627f, \u53ea\u9700\u8981 `dataclass`\n\n---\n\n## \u8bbe\u8ba1\u76ee\u6807\n\n* **\u6700\u5c0f\u8bed\u6cd5\u8d1f\u62c5**: \u6a21\u578b\u5b9a\u4e49\u5c31\u662f\u5408\u6cd5\u5e73\u51e1\u7684 Python dataclass, Python \u5373 DSL\n* **\u5e38\u7528\u8def\u5f84\u7b80\u6d01**: \u5e38\u7528\u7684\u5b9a\u4e49\u53ea\u9700\u8981\u5199\u5c11\u91cf\u7684\u4ee3\u7801\n* **\u9759\u6001\u7c7b\u578b\u5b89\u5168**: \u6a21\u578b\u5b9a\u4e49\u548c\u751f\u6210\u4ee3\u7801\u5168\u90fd\u7c7b\u578b\u5b89\u5168. \u672c\u5e93\u4f5c\u4e3a [prisma client python](https://prisma-client-py.readthedocs.io/en/stable/) \u7684\u7cbe\u795e\u7ee7\u627f\u8005, \u81f4\u529b\u4e8e\u5b8c\u6210\u5982\u4e0b\u4f53\u9a8c: \n\n![](https://prisma-client-py.readthedocs.io/en/stable/showcase.gif)\n\n---\n\n## \u793a\u4f8b\n\n```python\nfrom dataclasses import dataclass\nfrom datetime import datetime\n\n@dataclass\nclass User:\n    id: int\n    name: str\n    email: str\n    last_login: datetime\n\n    def index(self):\n        yield self.name\n        yield self.last_login\n\n    def unique_index(self):\n        yield self.name, self.email\n```\n\n\u5199\u51fa\u5982\u4e0b\u4ee3\u7801\u65f6: \n\n```python\nfrom dclassql import client\n\nclient.user.insert({\n    \"name\": \"Alice\",\n    \"email\": \"test@example.com\",\n})\n```\n\n\u5c06\u5728\u7c7b\u578b\u7a7a\u95f4\u5f97\u5230\u62a5\u9519: \n\n```\nerror: Argument of type \"dict[str, str]\" cannot be assigned to parameter \"data\" of type \"UserInsertDict\" in function \"insert\"\n    \"last_login\" is required in \"UserInsertDict\" (reportArgumentType)\n```\n\n\n## \u5b89\u88c5\n\n```\nuv add dclassql\n```\n\n## \u5f53\u524d\u72b6\u6001\n\nDataclassQL \u4ecd\u5728\u65e9\u671f\u5f00\u53d1\u9636\u6bb5, \u5df2\u5b8c\u6210\u4ee3\u7801\u751f\u6210\u548c SQLite \u652f\u6301, \u540e\u7eed\u5c06\u6269\u5c55\u66f4\u591a\u6570\u636e\u5e93\u4e0e\u67e5\u8be2\u529f\u80fd. \n\n## \u4e00\u4efd\u66f4\u957f\u7684\u4f8b\u5b50\n\n```python\nfrom dataclasses import dataclass\nfrom datetime import datetime\n\n__datasource__ = {\n    \"provider\": \"sqlite\",\n    \"url\": \"sqlite:///test.db\",\n}\n\n\n@dataclass\nclass Address:\n    id: int\n    location: str\n    user_id: int\n    user: 'User'\n\n    def foreign_key(self):\n        yield self.user.id == self.user_id, User.addresses\n\n\n@dataclass\nclass BirthDay:\n    user_id: int\n    user: 'User'\n    date: datetime\n\n    def primary_key(self):\n        return self.user_id\n\n    def foreign_key(self):\n        yield self.user.id == self.user_id, User.birthday\n\n\n@dataclass\nclass Book:\n    id: int\n    name: str\n    users: list['UserBook']\n\n    def index(self):\n        return self.name\n\n\n@dataclass\nclass UserBook:\n    user_id: int\n    book_id: int\n    user: 'User'\n    book: Book\n    created_at: datetime\n\n    def primary_key(self):\n        return (self.user_id, self.book_id)\n\n    def index(self):\n        yield self.created_at\n\n    def foreign_key(self):\n        yield self.user.id == self.user_id, User.books\n        yield self.book.id == self.book_id, Book.users\n\n\n@dataclass\nclass User:\n    id: int | None\n    name: str\n    email: str\n    last_login: datetime\n    birthday: BirthDay | None\n    addresses: list[Address]\n    books: list[UserBook]\n\n    def index(self):\n        yield self.name\n        yield self.name, self.email\n        yield self.last_login\n\n    def unique_index(self):\n        yield self.name, self.email\n\n```\n\n\u751f\u6210\u7684\u4ee3\u7801\u8bf7\u89c1: https://github.com/myuanz/dataclassql/blob/master/tests/results.py\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "A type-safe ORM generator for Python, creating fully type-hinted database clients from plain dataclass definitions.",
    "version": "0.1.3",
    "project_urls": {
        "Homepage": "https://github.com/myuanz/dataclassql"
    },
    "split_keywords": [
        "orm",
        " codegen",
        " sqlite",
        " dataclass",
        " typed"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "adb8d846c731cd6dc8f23ee3a4baffe8adfc9b5e9854417462bab0abe43a6ab1",
                "md5": "bec46b90ca12a9c8e38820c1d03a8d3b",
                "sha256": "b5a15e141784425b67365c091d930930747b71a299fe74750a56a323bba6b90a"
            },
            "downloads": -1,
            "filename": "dclassql-0.1.3-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "bec46b90ca12a9c8e38820c1d03a8d3b",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.12",
            "size": 42501,
            "upload_time": "2025-11-06T07:24:47",
            "upload_time_iso_8601": "2025-11-06T07:24:47.166478Z",
            "url": "https://files.pythonhosted.org/packages/ad/b8/d846c731cd6dc8f23ee3a4baffe8adfc9b5e9854417462bab0abe43a6ab1/dclassql-0.1.3-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "e5011a93eb29858040ebdfc3b8f593ac6492909ca7ef789987f5cc5dada2e110",
                "md5": "995ca1ac42853265c17102e292d35171",
                "sha256": "7fa85d987724918ee335a192575b7586a78b379260778a378c2f7040d73282cb"
            },
            "downloads": -1,
            "filename": "dclassql-0.1.3.tar.gz",
            "has_sig": false,
            "md5_digest": "995ca1ac42853265c17102e292d35171",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.12",
            "size": 30170,
            "upload_time": "2025-11-06T07:24:49",
            "upload_time_iso_8601": "2025-11-06T07:24:49.245073Z",
            "url": "https://files.pythonhosted.org/packages/e5/01/1a93eb29858040ebdfc3b8f593ac6492909ca7ef789987f5cc5dada2e110/dclassql-0.1.3.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-11-06 07:24:49",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "myuanz",
    "github_project": "dataclassql",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": false,
    "lcname": "dclassql"
}
        
Elapsed time: 1.60387s