graftql 1.21.0.dev44411__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,163 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ .dist
6
+
7
+ .idea/
8
+
9
+ # C extensions
10
+ *.so
11
+
12
+ # Distribution / packaging
13
+ .Python
14
+ build/
15
+ develop-eggs/
16
+ dist/
17
+ downloads/
18
+ eggs/
19
+ .eggs/
20
+ lib/
21
+ lib64/
22
+ parts/
23
+ sdist/
24
+ var/
25
+ wheels/
26
+ share/python-wheels/
27
+ *.egg-info/
28
+ .installed.cfg
29
+ *.egg
30
+ MANIFEST
31
+
32
+ # PyInstaller
33
+ # Usually these files are written by a python script from a template
34
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
35
+ *.manifest
36
+ *.spec
37
+
38
+ # Installer logs
39
+ pip-log.txt
40
+ pip-delete-this-directory.txt
41
+
42
+ # Unit test / coverage reports
43
+ htmlcov/
44
+ .tox/
45
+ .nox/
46
+ .coverage
47
+ .coverage.*
48
+ .cache
49
+ nosetests.xml
50
+ coverage.xml
51
+ *.cover
52
+ *.py,cover
53
+ .hypothesis/
54
+ .pytest_cache/
55
+ cover/
56
+
57
+ # Translations
58
+ *.mo
59
+ *.pot
60
+
61
+ # Django stuff:
62
+ *.log
63
+ local_settings.py
64
+ db.sqlite3
65
+ db.sqlite3-journal
66
+
67
+ # Flask stuff:
68
+ instance/
69
+ .webassets-cache
70
+
71
+ # Scrapy stuff:
72
+ .scrapy
73
+
74
+ # Sphinx documentation
75
+ docs/_build/
76
+
77
+ # PyBuilder
78
+ .pybuilder/
79
+ target/
80
+
81
+ # Jupyter Notebook
82
+ .ipynb_checkpoints
83
+
84
+ # IPython
85
+ profile_default/
86
+ ipython_config.py
87
+
88
+ # pyenv
89
+ # For a library or package, you might want to ignore these files since the code is
90
+ # intended to run in multiple environments; otherwise, check them in:
91
+ # .python-version
92
+
93
+ # pipenv
94
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
95
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
96
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
97
+ # install all needed dependencies.
98
+ #Pipfile.lock
99
+
100
+ # poetry
101
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
102
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
103
+ # commonly ignored for libraries.
104
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
105
+ #poetry.lock
106
+
107
+ # pdm
108
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
109
+ #pdm.lock
110
+ # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
111
+ # in version control.
112
+ # https://pdm.fming.dev/#use-with-ide
113
+ .pdm.toml
114
+
115
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
116
+ __pypackages__/
117
+
118
+ # Celery stuff
119
+ celerybeat-schedule
120
+ celerybeat.pid
121
+
122
+ # SageMath parsed files
123
+ *.sage.py
124
+
125
+ # Environments
126
+ .env
127
+ .venv
128
+ env/
129
+ venv/
130
+ ENV/
131
+ env.bak/
132
+ venv.bak/
133
+
134
+ # Spyder project settings
135
+ .spyderproject
136
+ .spyproject
137
+
138
+ # Rope project settings
139
+ .ropeproject
140
+
141
+ # mkdocs documentation
142
+ /site
143
+
144
+ # mypy
145
+ .mypy_cache/
146
+ .dmypy.json
147
+ dmypy.json
148
+
149
+ # Pyre type checker
150
+ .pyre/
151
+
152
+ # pytype static type analyzer
153
+ .pytype/
154
+
155
+ # Cython debug symbols
156
+ cython_debug/
157
+
158
+ # PyCharm
159
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
160
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
161
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
162
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
163
+ #.idea/
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 The Devs
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,177 @@
1
+ Metadata-Version: 2.5
2
+ Name: graftql
3
+ Version: v1.21.0.dev44411
4
+ Summary: GraftQL turns your SQLModel definitions into a fully-typed GraphQL API — no schema duplication, no glue code.
5
+ Project-URL: Homepage, https://github.com/lorrod/graftql
6
+ Project-URL: Documentation, https://lorrod.github.io/graftql/
7
+ Project-URL: Repository, https://github.com/lorrod/graftql
8
+ Project-URL: Issues, https://github.com/lorrod/graftql/issues
9
+ Author: lorrod
10
+ License: MIT
11
+ License-File: LICENSE
12
+ Keywords: api,fastapi,graphql,orm,sqlalchemy,sqlmodel,strawberry
13
+ Classifier: Development Status :: 5 - Production/Stable
14
+ Classifier: Framework :: FastAPI
15
+ Classifier: Intended Audience :: Developers
16
+ Classifier: License :: OSI Approved :: MIT License
17
+ Classifier: Natural Language :: English
18
+ Classifier: Programming Language :: Python :: 3
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Topic :: Database
22
+ Classifier: Topic :: Database :: Database Engines/Servers
23
+ Classifier: Typing :: Typed
24
+ Requires-Python: >=3.12
25
+ Requires-Dist: fastapi==0.133.1
26
+ Requires-Dist: sqlmodel==0.0.37
27
+ Requires-Dist: strawberry-graphql[debug-server]==0.307.1
28
+ Provides-Extra: dev
29
+ Requires-Dist: aiosqlite>=0.20.0; extra == 'dev'
30
+ Requires-Dist: fastapi-cli>=0.0.5; extra == 'dev'
31
+ Requires-Dist: httpx>=0.27.2; extra == 'dev'
32
+ Requires-Dist: isort>=5.12.0; extra == 'dev'
33
+ Requires-Dist: pytest-asyncio>=0.24.0; extra == 'dev'
34
+ Requires-Dist: pytest-cov>=4.1.0; extra == 'dev'
35
+ Requires-Dist: pytest-env>=1.1.1; extra == 'dev'
36
+ Requires-Dist: pytest>=8.3.3; extra == 'dev'
37
+ Requires-Dist: taskipy>=1.12.0; extra == 'dev'
38
+ Provides-Extra: doc
39
+ Requires-Dist: asyncpg>=0.29.0; extra == 'doc'
40
+ Requires-Dist: greenlet>=3.0.3; extra == 'doc'
41
+ Requires-Dist: jinja2>=3.1.2; extra == 'doc'
42
+ Requires-Dist: mdx-include>=1.4.2; extra == 'doc'
43
+ Requires-Dist: mkdocs-macros-plugin>=1.0.5; extra == 'doc'
44
+ Requires-Dist: mkdocs-material>=9.4.7; extra == 'doc'
45
+ Requires-Dist: mkdocs<2,>=1.6; extra == 'doc'
46
+ Requires-Dist: mkdocstrings-python>=1.11.1; extra == 'doc'
47
+ Requires-Dist: mkdocstrings>=0.26.1; extra == 'doc'
48
+ Description-Content-Type: text/markdown
49
+
50
+ <p align="center">
51
+ <picture>
52
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/lorrod/graftql/main/docs/assets/graftql-wordmark-dark.svg">
53
+ <img alt="GraftQL" src="https://raw.githubusercontent.com/lorrod/graftql/main/docs/assets/graftql-wordmark.svg" width="380">
54
+ </picture>
55
+ </p>
56
+
57
+ <p align="center"><strong>SQLModel in, typed GraphQL out.</strong></p>
58
+
59
+ <p align="center">
60
+ <a href="https://github.com/lorrod/graftql/actions/workflows/ci.yml"><img alt="CI" src="https://github.com/lorrod/graftql/actions/workflows/ci.yml/badge.svg"></a>
61
+ <a href="https://pypi.org/project/graftql/"><img alt="PyPI" src="https://img.shields.io/pypi/v/graftql?color=1f9d66"></a>
62
+ <a href="https://pypi.org/project/graftql/"><img alt="Python" src="https://img.shields.io/pypi/pyversions/graftql?color=1f9d66"></a>
63
+ <a href="https://lorrod.github.io/graftql/"><img alt="Docs" src="https://img.shields.io/badge/docs-lorrod.github.io%2Fgraftql-1f9d66"></a>
64
+ <a href="LICENSE"><img alt="License" src="https://img.shields.io/badge/license-MIT-1f9d66"></a>
65
+ </p>
66
+
67
+ GraftQL turns your SQLModel definitions into a fully-typed GraphQL API — no schema duplication, no glue code.
68
+
69
+ ---
70
+
71
+ ## Overview
72
+
73
+ **GraftQL** lets you define your data models once (as `GraftModel` subclasses) and get a
74
+ fully-typed GraphQL API automatically — no schema duplication, no glue code. It layers on top of
75
+ [SQLModel](https://sqlmodel.tiangolo.com/) for the ORM and [Strawberry](https://strawberry.rocks/)
76
+ for the GraphQL schema. Mount `GraftRouter` in any FastAPI app and your models are immediately
77
+ queryable and mutable over GraphQL — including paginated connections, filters, ordering, and
78
+ fine-grained permission hooks.
79
+
80
+ Async (SQLAlchemy async engines) and sync engines are both supported, and multiple database
81
+ engines can be registered under different names for multi-tenant or federated setups.
82
+
83
+ ---
84
+
85
+ ## Features
86
+
87
+ - **Single model class** — extend `GraftModel` instead of both `SQLModel` and a Strawberry type.
88
+ - **Auto GraphQL schema** — queries, mutations (PUT / DELETE), and paginated connections generated automatically.
89
+ - **DataLoaders** — declare relations with `Dl` and `ManyRelation`; N+1 queries solved out of the box.
90
+ - **Composable filters** — date ranges, ordering, and custom filter attributes, all typed.
91
+ - **Permission hooks** — override `permission_getter` per-model or supply a global `get_permission` function.
92
+ - **Async support** — pass an async SQLAlchemy engine and GraftQL handles the rest.
93
+ - **Multi-engine** — register multiple engines by name; each model picks its engine via `__enginename__`.
94
+ - **Federation-ready** — Strawberry federation directives can be applied through the schema DSL.
95
+
96
+ ---
97
+
98
+ ## Installation
99
+
100
+ ```bash
101
+ pip install graftql
102
+ ```
103
+
104
+ ---
105
+
106
+ ## Quick Start
107
+
108
+ ```python
109
+ from datetime import date
110
+
111
+ from fastapi import FastAPI
112
+ from sqlmodel import create_engine
113
+
114
+ from graftql import Field, GraftModel, GraftRouter
115
+
116
+ # 1. Define your models — once. No separate Pydantic/Strawberry types needed.
117
+ class Student(GraftModel, table=True):
118
+ id: int | None = Field(primary_key=True, default=None)
119
+ name: str
120
+ birth_date: date
121
+
122
+ # 2. Create tables and mount the router.
123
+ engine = create_engine("sqlite:///./dev.db")
124
+ GraftModel.metadata.create_all(engine)
125
+
126
+ app = FastAPI()
127
+ router = GraftRouter(
128
+ engine=engine,
129
+ enable_put_mutations=True,
130
+ enable_delete_mutations=True,
131
+ )
132
+ app.include_router(router, prefix="/graphql")
133
+
134
+ # 3. Run: uvicorn main:app --reload
135
+ # Visit: http://localhost:8000/graphql
136
+ ```
137
+
138
+ You can now run queries like:
139
+
140
+ ```graphql
141
+ mutation {
142
+ students {
143
+ put(input: { name: "Alice", birthDate: "2000-01-01" }) { id }
144
+ }
145
+ }
146
+
147
+ query {
148
+ students {
149
+ many { edges { node { id name birthDate } } }
150
+ }
151
+ }
152
+ ```
153
+
154
+ ---
155
+
156
+ ## Documentation
157
+
158
+ See the [documentation](https://lorrod.github.io/graftql/) for the full guide including relations, DataLoaders,
159
+ authentication, async engines, and federation.
160
+
161
+ ---
162
+
163
+ ## Contributing
164
+
165
+ 1. Fork [lorrod/graftql](https://github.com/lorrod/graftql).
166
+ 2. Create a feature branch: `git checkout -b feat/my-change`.
167
+ 3. Make your changes and add tests.
168
+ 4. Run the checks: `uv run --group dev ruff check . && uv run --group dev pytest`.
169
+ 5. Open a pull request.
170
+
171
+ All contributions are welcome — bug reports, documentation fixes, and new features alike.
172
+
173
+ ---
174
+
175
+ ## License
176
+
177
+ MIT — see [LICENSE](LICENSE).
@@ -0,0 +1,128 @@
1
+ <p align="center">
2
+ <picture>
3
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/lorrod/graftql/main/docs/assets/graftql-wordmark-dark.svg">
4
+ <img alt="GraftQL" src="https://raw.githubusercontent.com/lorrod/graftql/main/docs/assets/graftql-wordmark.svg" width="380">
5
+ </picture>
6
+ </p>
7
+
8
+ <p align="center"><strong>SQLModel in, typed GraphQL out.</strong></p>
9
+
10
+ <p align="center">
11
+ <a href="https://github.com/lorrod/graftql/actions/workflows/ci.yml"><img alt="CI" src="https://github.com/lorrod/graftql/actions/workflows/ci.yml/badge.svg"></a>
12
+ <a href="https://pypi.org/project/graftql/"><img alt="PyPI" src="https://img.shields.io/pypi/v/graftql?color=1f9d66"></a>
13
+ <a href="https://pypi.org/project/graftql/"><img alt="Python" src="https://img.shields.io/pypi/pyversions/graftql?color=1f9d66"></a>
14
+ <a href="https://lorrod.github.io/graftql/"><img alt="Docs" src="https://img.shields.io/badge/docs-lorrod.github.io%2Fgraftql-1f9d66"></a>
15
+ <a href="LICENSE"><img alt="License" src="https://img.shields.io/badge/license-MIT-1f9d66"></a>
16
+ </p>
17
+
18
+ GraftQL turns your SQLModel definitions into a fully-typed GraphQL API — no schema duplication, no glue code.
19
+
20
+ ---
21
+
22
+ ## Overview
23
+
24
+ **GraftQL** lets you define your data models once (as `GraftModel` subclasses) and get a
25
+ fully-typed GraphQL API automatically — no schema duplication, no glue code. It layers on top of
26
+ [SQLModel](https://sqlmodel.tiangolo.com/) for the ORM and [Strawberry](https://strawberry.rocks/)
27
+ for the GraphQL schema. Mount `GraftRouter` in any FastAPI app and your models are immediately
28
+ queryable and mutable over GraphQL — including paginated connections, filters, ordering, and
29
+ fine-grained permission hooks.
30
+
31
+ Async (SQLAlchemy async engines) and sync engines are both supported, and multiple database
32
+ engines can be registered under different names for multi-tenant or federated setups.
33
+
34
+ ---
35
+
36
+ ## Features
37
+
38
+ - **Single model class** — extend `GraftModel` instead of both `SQLModel` and a Strawberry type.
39
+ - **Auto GraphQL schema** — queries, mutations (PUT / DELETE), and paginated connections generated automatically.
40
+ - **DataLoaders** — declare relations with `Dl` and `ManyRelation`; N+1 queries solved out of the box.
41
+ - **Composable filters** — date ranges, ordering, and custom filter attributes, all typed.
42
+ - **Permission hooks** — override `permission_getter` per-model or supply a global `get_permission` function.
43
+ - **Async support** — pass an async SQLAlchemy engine and GraftQL handles the rest.
44
+ - **Multi-engine** — register multiple engines by name; each model picks its engine via `__enginename__`.
45
+ - **Federation-ready** — Strawberry federation directives can be applied through the schema DSL.
46
+
47
+ ---
48
+
49
+ ## Installation
50
+
51
+ ```bash
52
+ pip install graftql
53
+ ```
54
+
55
+ ---
56
+
57
+ ## Quick Start
58
+
59
+ ```python
60
+ from datetime import date
61
+
62
+ from fastapi import FastAPI
63
+ from sqlmodel import create_engine
64
+
65
+ from graftql import Field, GraftModel, GraftRouter
66
+
67
+ # 1. Define your models — once. No separate Pydantic/Strawberry types needed.
68
+ class Student(GraftModel, table=True):
69
+ id: int | None = Field(primary_key=True, default=None)
70
+ name: str
71
+ birth_date: date
72
+
73
+ # 2. Create tables and mount the router.
74
+ engine = create_engine("sqlite:///./dev.db")
75
+ GraftModel.metadata.create_all(engine)
76
+
77
+ app = FastAPI()
78
+ router = GraftRouter(
79
+ engine=engine,
80
+ enable_put_mutations=True,
81
+ enable_delete_mutations=True,
82
+ )
83
+ app.include_router(router, prefix="/graphql")
84
+
85
+ # 3. Run: uvicorn main:app --reload
86
+ # Visit: http://localhost:8000/graphql
87
+ ```
88
+
89
+ You can now run queries like:
90
+
91
+ ```graphql
92
+ mutation {
93
+ students {
94
+ put(input: { name: "Alice", birthDate: "2000-01-01" }) { id }
95
+ }
96
+ }
97
+
98
+ query {
99
+ students {
100
+ many { edges { node { id name birthDate } } }
101
+ }
102
+ }
103
+ ```
104
+
105
+ ---
106
+
107
+ ## Documentation
108
+
109
+ See the [documentation](https://lorrod.github.io/graftql/) for the full guide including relations, DataLoaders,
110
+ authentication, async engines, and federation.
111
+
112
+ ---
113
+
114
+ ## Contributing
115
+
116
+ 1. Fork [lorrod/graftql](https://github.com/lorrod/graftql).
117
+ 2. Create a feature branch: `git checkout -b feat/my-change`.
118
+ 3. Make your changes and add tests.
119
+ 4. Run the checks: `uv run --group dev ruff check . && uv run --group dev pytest`.
120
+ 5. Open a pull request.
121
+
122
+ All contributions are welcome — bug reports, documentation fixes, and new features alike.
123
+
124
+ ---
125
+
126
+ ## License
127
+
128
+ MIT — see [LICENSE](LICENSE).
@@ -0,0 +1,31 @@
1
+ import os
2
+
3
+ from sqlmodel import Field
4
+
5
+ from graftql.core.model import GraftModel
6
+ from graftql.core.router import GraftRouter
7
+ from graftql.core.setup import Setup
8
+ from graftql.loaders.dataloader import Dl, GraftLoader, ManyRelation
9
+
10
+
11
+ def import_files(path):
12
+ """
13
+ Recursively imports all Python files found in the specified directory and its subdirectories,
14
+ excluding `__init__.py`. This function is intended to facilitate the dynamic loading of modules,
15
+ particularly useful in scenarios like automatic model discovery in web applications.
16
+
17
+ Args:
18
+ path (str): The directory path from which Python files should be imported.
19
+
20
+ Note:
21
+ - This function modifies the global namespace by dynamically importing modules.
22
+ - Import paths are adjusted to be relative, considering the package structure.
23
+ """
24
+ for root, _dirs, files in os.walk(path):
25
+ for file in files:
26
+ if file.endswith(".py") and file != "__init__.py":
27
+ module_name = os.path.splitext(file)[0]
28
+ module_path = os.path.join(root, module_name)
29
+ module_path_rel = os.path.relpath(os.path.join(root, module_name))
30
+ module_path = module_path_rel.replace(os.path.sep, ".")
31
+ exec(f"import {module_path}")
@@ -0,0 +1,8 @@
1
+ """Core primitives for graftql.
2
+
3
+ These modules contain the main router, base model, and Setup registry.
4
+ """
5
+
6
+ from .model import GraftModel
7
+ from .router import GraftRouter
8
+ from .setup import Setup
@@ -0,0 +1,114 @@
1
+ import re
2
+ from typing import Any, Callable
3
+
4
+ from pydantic import ConfigDict
5
+ from sqlmodel import SQLModel
6
+ from strawberry.types.base import StrawberryType
7
+
8
+ from ..loaders.dataloader import Dl, ManyRelation
9
+ from ..schemas.generators import OrderBy, get_dl_function, get_many_relation_function
10
+ from .setup import Setup
11
+
12
+
13
+ class GraftModel(SQLModel):
14
+ """
15
+ An extension of SQLModel that integrates Strawberry GraphQL functionalities,
16
+ enabling the dynamic generation of GraphQL schemas directly from SQLModel definitions.
17
+ This class supports configuring GraphQL operations such as queries and mutations,
18
+ and facilitates the management of permissions for these operations.
19
+
20
+ Attributes:
21
+ __strawberry_schema__ (StrawberryType): Holds the GraphQL schema associated with
22
+ this model, allowing for integration with the Strawberry GraphQL library.
23
+ __enable_put_mutation__ (bool | None): Controls whether PUT mutations (update
24
+ operations) are enabled for this model in the GraphQL API. Set to `True` to
25
+ enable, `False` to disable, or `None` to use default settings.
26
+ __enable_delete_mutation__ (bool | None): Determines whether DELETE mutations
27
+ (delete operations) are enabled for this model in the GraphQL API. Set to
28
+ `True` to enable, `False` to disable, or `None` to use default settings.
29
+ __enable_query__ (bool | None): Specifies whether the model can be queried via
30
+ the GraphQL API. Set to `True` to enable queries, `False` to disable, or
31
+ `None` to leave it unset.
32
+ __queryname__ (str): Provides a custom name for GraphQL queries related to this
33
+ model. Defaults to the model's table name plus 's' (e.g., 'users' for a User
34
+ model) if not explicitly set.
35
+ __enginename__ (str): Identifier for the database engine used by this model,
36
+ useful for applications that connect to multiple databases or require
37
+ specific database configurations.
38
+ __filter_attributes__ (Optional[dict[str, dict[str, Any]]]): Definition of filters allowed by the model,
39
+ useful for filter attribute declarations. Defaults to `None`. Example
40
+ { "id": {"required": True, "description": "Filter by ID", default: None} }
41
+ __custom_resolvers__ (Optional[list[Callable]]): Definition of custom resolvers allowed by the model,
42
+ useful to make custom attributes. Defaults to `None`. Example
43
+ { full_name: Callable }. Can return basic types and strawberry types
44
+ __directives__ (List[Any]): Maps
45
+ Custom directives applied to model [Key(fields="id", resolvable=True)]
46
+ __mutation_permission_classes__ (Dict[str, List[Type[BasePermission]]]): Maps
47
+ specific mutation names to their respective permission classes. This allows
48
+ for fine-grained control over which permissions apply to each mutation. If a
49
+ mutation is not listed, it defaults to having no specific permissions.
50
+ __default_order_by__ (dict[str, OrderBy] | str): Order by for database queries. Can be a string for
51
+ backward compatibility or a dictionary with attribute as key and OrderBy as value.
52
+ Example: {"id": OrderBy.ASC}
53
+ __sql_preset_order_by__ (Optional[str]): Raw SQL string for setting a hidden ordering rule
54
+ __sql_preset_filter__ (Optional[str]): Raw SQL string for setting a hidden filter condition
55
+ for this model's queries.
56
+ Classes:
57
+ GraftModel: An extended SQLModel that incorporates GraphQL functionalities by using
58
+ Strawberry GraphQL. This class allows defining GraphQL schemas, query names,
59
+ engine names, and supports dynamic field resolution using dependency injection.
60
+
61
+ Strawberry: An inner class used to encapsulate GraphQL-specific configurations
62
+ and properties for the GraftModel class.
63
+ Methods:
64
+ __init_subclass__: Automatically called when a subclass of GraftModel is defined.
65
+ Sets up the necessary GraphQL configurations and registers the subclass in a
66
+ setup registry for further reference.
67
+ permission_getter: Async static method intended to be overridden to provide
68
+ custom logic for determining user permissions for executing GraphQL queries.
69
+ Should return `True` if the query is permitted, `False` otherwise.
70
+ """
71
+
72
+ __strawberry_schema__: StrawberryType = None
73
+ __enable_put_mutation__: bool | None = None
74
+ __enable_delete_mutation__: bool | None = None
75
+ __enable_query__: bool | None = None
76
+ __queryname__: str = ""
77
+ __enginename__: str = "default"
78
+ __default_order_by__: dict[str, OrderBy] = {"id": OrderBy.ASC}
79
+ __sql_preset_order_by__: str | None = None
80
+ __sql_preset_filter__: str | None = None
81
+ __filter_attributes__: dict[str, dict[str, Any]] | None = None
82
+ __custom_resolvers__: list[Callable] | None = None
83
+ __custom_mutations__: list[Callable] | None = None
84
+ __directives__: list | None = None
85
+ __mutation_permission_classes__ = {}
86
+ model_config = ConfigDict(arbitrary_types_allowed=True)
87
+
88
+ class Strawberry:
89
+ pass
90
+
91
+ def __init_subclass__(cls):
92
+ if not cls.__tablename__:
93
+ cls.__tablename__ = re.sub(r"(?<!^)(?=[A-Z])", "_", cls.__name__).lower()
94
+ cls.__queryname__ = cls.__queryname__ if cls.__queryname__ else cls.__tablename__ + "s"
95
+ Setup.classes[cls.__name__] = cls
96
+ to_remove = []
97
+ for attr_name, attr_type in cls.__annotations__.items():
98
+ if hasattr(cls, attr_name):
99
+ attr_value = getattr(cls, attr_name)
100
+ if isinstance(attr_value, Dl):
101
+ to_remove.append(attr_name)
102
+ dl_field = get_dl_function(attr_name, attr_type, attr_value)
103
+ setattr(cls, attr_name, dl_field)
104
+ elif isinstance(attr_value, ManyRelation):
105
+ to_remove.append(attr_name)
106
+ dl_field = get_many_relation_function(
107
+ attr_name, attr_type, attr_value, source_model=cls
108
+ )
109
+ setattr(cls, attr_name, dl_field)
110
+ for attr in to_remove:
111
+ del cls.__annotations__[attr]
112
+
113
+ async def permission_getter(self: dict, request_type: str) -> bool:
114
+ pass