graphql-api 1.4.18__tar.gz → 1.4.20__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.
Files changed (77) hide show
  1. graphql_api-1.4.20/.github/workflows/pages.yml +77 -0
  2. graphql_api-1.4.20/.github/workflows/python-package.yml +78 -0
  3. graphql_api-1.4.20/.gitignore +23 -0
  4. graphql_api-1.4.20/.vscode/settings.json +7 -0
  5. {graphql_api-1.4.18/graphql_api.egg-info → graphql_api-1.4.20}/PKG-INFO +68 -38
  6. {graphql_api-1.4.18 → graphql_api-1.4.20}/README.md +57 -10
  7. graphql_api-1.4.20/VERSION +1 -0
  8. graphql_api-1.4.20/docs/README.md +81 -0
  9. graphql_api-1.4.20/docs/content/_index.md +71 -0
  10. graphql_api-1.4.20/docs/content/docs/_index.md +38 -0
  11. graphql_api-1.4.20/docs/content/docs/advanced.md +202 -0
  12. graphql_api-1.4.20/docs/content/docs/api-reference.md +551 -0
  13. graphql_api-1.4.20/docs/content/docs/async-and-subscriptions.md +161 -0
  14. graphql_api-1.4.20/docs/content/docs/contributing.md +442 -0
  15. graphql_api-1.4.20/docs/content/docs/defining-schemas.md +279 -0
  16. graphql_api-1.4.20/docs/content/docs/examples.md +528 -0
  17. graphql_api-1.4.20/docs/content/docs/federation.md +147 -0
  18. graphql_api-1.4.20/docs/content/docs/getting-started.md +140 -0
  19. graphql_api-1.4.20/docs/content/docs/pydantic-and-dataclasses.md +184 -0
  20. graphql_api-1.4.20/docs/hugo.toml +86 -0
  21. graphql_api-1.4.20/docs/index.md +212 -0
  22. {graphql_api-1.4.18 → graphql_api-1.4.20}/graphql_api/api.py +157 -23
  23. {graphql_api-1.4.18 → graphql_api-1.4.20}/graphql_api/dataclass_mapping.py +8 -4
  24. {graphql_api-1.4.18 → graphql_api-1.4.20}/graphql_api/directives.py +6 -3
  25. {graphql_api-1.4.18 → graphql_api-1.4.20}/graphql_api/executor.py +6 -3
  26. {graphql_api-1.4.18 → graphql_api-1.4.20}/graphql_api/federation/directives.py +4 -2
  27. {graphql_api-1.4.18 → graphql_api-1.4.20}/graphql_api/federation/federation.py +4 -2
  28. {graphql_api-1.4.18 → graphql_api-1.4.20}/graphql_api/mapper.py +68 -20
  29. {graphql_api-1.4.18 → graphql_api-1.4.20}/graphql_api/pydantic.py +4 -2
  30. {graphql_api-1.4.18 → graphql_api-1.4.20}/graphql_api/reduce.py +28 -14
  31. {graphql_api-1.4.18 → graphql_api-1.4.20}/graphql_api/remote.py +18 -9
  32. {graphql_api-1.4.18 → graphql_api-1.4.20}/graphql_api/schema.py +11 -5
  33. {graphql_api-1.4.18 → graphql_api-1.4.20}/graphql_api/types.py +4 -2
  34. {graphql_api-1.4.18 → graphql_api-1.4.20}/graphql_api/utils.py +4 -2
  35. {graphql_api-1.4.18 → graphql_api-1.4.20/graphql_api.egg-info}/PKG-INFO +68 -38
  36. {graphql_api-1.4.18 → graphql_api-1.4.20}/graphql_api.egg-info/SOURCES.txt +23 -4
  37. graphql_api-1.4.20/graphql_api.egg-info/requires.txt +6 -0
  38. {graphql_api-1.4.18 → graphql_api-1.4.20}/graphql_api.egg-info/top_level.txt +0 -1
  39. graphql_api-1.4.20/pyproject.toml +80 -0
  40. graphql_api-1.4.20/setup.cfg +4 -0
  41. {graphql_api-1.4.18 → graphql_api-1.4.20}/tests/test_async.py +2 -1
  42. {graphql_api-1.4.18 → graphql_api-1.4.20}/tests/test_calculator.py +5 -5
  43. {graphql_api-1.4.18 → graphql_api-1.4.20}/tests/test_custom_types.py +17 -15
  44. {graphql_api-1.4.18 → graphql_api-1.4.20}/tests/test_dataclass.py +66 -33
  45. {graphql_api-1.4.18 → graphql_api-1.4.20}/tests/test_directives.py +26 -18
  46. {graphql_api-1.4.18 → graphql_api-1.4.20}/tests/test_docstrings.py +36 -24
  47. {graphql_api-1.4.18 → graphql_api-1.4.20}/tests/test_error.py +6 -6
  48. {graphql_api-1.4.18 → graphql_api-1.4.20}/tests/test_federation.py +4 -3
  49. graphql_api-1.4.20/tests/test_federation_example.graphql +83 -0
  50. {graphql_api-1.4.18 → graphql_api-1.4.20}/tests/test_federation_example.py +8 -8
  51. {graphql_api-1.4.18 → graphql_api-1.4.20}/tests/test_filtering.py +109 -71
  52. {graphql_api-1.4.18 → graphql_api-1.4.20}/tests/test_graphql.py +82 -72
  53. {graphql_api-1.4.18 → graphql_api-1.4.20}/tests/test_middleware.py +3 -3
  54. {graphql_api-1.4.18 → graphql_api-1.4.20}/tests/test_pydantic.py +44 -33
  55. {graphql_api-1.4.18 → graphql_api-1.4.20}/tests/test_relay.py +1 -1
  56. {graphql_api-1.4.18 → graphql_api-1.4.20}/tests/test_remote.py +73 -44
  57. {graphql_api-1.4.18 → graphql_api-1.4.20}/tests/test_schema.py +9 -8
  58. {graphql_api-1.4.18 → graphql_api-1.4.20}/tests/test_subscriptions.py +16 -13
  59. graphql_api-1.4.20/tests/test_unified_vs_explicit_schema.py +241 -0
  60. graphql_api-1.4.20/uv.lock +948 -0
  61. graphql_api-1.4.18/MANIFEST.in +0 -3
  62. graphql_api-1.4.18/VERSION +0 -1
  63. graphql_api-1.4.18/graphql_api.egg-info/requires.txt +0 -12
  64. graphql_api-1.4.18/setup.cfg +0 -15
  65. graphql_api-1.4.18/setup.py +0 -46
  66. {graphql_api-1.4.18 → graphql_api-1.4.20}/LICENSE +0 -0
  67. {graphql_api-1.4.18 → graphql_api-1.4.20}/graphql_api/__init__.py +0 -0
  68. {graphql_api-1.4.18 → graphql_api-1.4.20}/graphql_api/context.py +0 -0
  69. {graphql_api-1.4.18 → graphql_api-1.4.20}/graphql_api/decorators.py +0 -0
  70. {graphql_api-1.4.18 → graphql_api-1.4.20}/graphql_api/error.py +0 -0
  71. {graphql_api-1.4.18 → graphql_api-1.4.20}/graphql_api/exception.py +0 -0
  72. {graphql_api-1.4.18 → graphql_api-1.4.20}/graphql_api/federation/__init__.py +0 -0
  73. {graphql_api-1.4.18 → graphql_api-1.4.20}/graphql_api/federation/types.py +0 -0
  74. {graphql_api-1.4.18 → graphql_api-1.4.20}/graphql_api/middleware.py +0 -0
  75. {graphql_api-1.4.18 → graphql_api-1.4.20}/graphql_api/relay.py +0 -0
  76. {graphql_api-1.4.18 → graphql_api-1.4.20}/graphql_api.egg-info/dependency_links.txt +0 -0
  77. {graphql_api-1.4.18 → graphql_api-1.4.20}/tests/__init__.py +0 -0
@@ -0,0 +1,77 @@
1
+ name: Deploy Hugo site to GitHub Pages
2
+
3
+ on:
4
+ push:
5
+ branches: [ main ]
6
+ paths: [ 'docs/**' ]
7
+ pull_request:
8
+ branches: [ main ]
9
+ paths: [ 'docs/**' ]
10
+ workflow_dispatch:
11
+
12
+ permissions:
13
+ contents: read
14
+ pages: write
15
+ id-token: write
16
+
17
+ concurrency:
18
+ group: "pages"
19
+ cancel-in-progress: false
20
+
21
+ jobs:
22
+ build:
23
+ runs-on: ubuntu-latest
24
+ env:
25
+ HUGO_VERSION: 0.146.0
26
+ steps:
27
+ - name: Checkout
28
+ uses: actions/checkout@v4
29
+ with:
30
+ submodules: recursive
31
+ fetch-depth: 0
32
+ - name: Install Hugo CLI
33
+ run: |
34
+ wget -O ${{ runner.temp }}/hugo.deb https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_extended_${HUGO_VERSION}_linux-amd64.deb \
35
+ && sudo dpkg -i ${{ runner.temp }}/hugo.deb
36
+ - name: Install Dart Sass
37
+ run: sudo snap install dart-sass
38
+ - name: Setup Pages
39
+ id: pages
40
+ uses: actions/configure-pages@v4
41
+ with:
42
+ enablement: true
43
+ - name: Install Node.js dependencies
44
+ working-directory: ./docs
45
+ run: "[[ -f package-lock.json || -f npm-shrinkwrap.json ]] && npm ci || true"
46
+ - name: Setup Hugo Book theme
47
+ working-directory: ./docs
48
+ run: |
49
+ if [ ! -d "themes/hugo-book" ]; then
50
+ git clone --depth 1 https://github.com/alex-shpak/hugo-book.git themes/hugo-book
51
+ fi
52
+ - name: Build with Hugo
53
+ env:
54
+ HUGO_ENVIRONMENT: production
55
+ HUGO_ENV: production
56
+ working-directory: ./docs
57
+ run: |
58
+ hugo \
59
+ --gc \
60
+ --minify \
61
+ --baseURL "${{ steps.pages.outputs.base_url }}/"
62
+ - name: Upload artifact
63
+ uses: actions/upload-pages-artifact@v3
64
+ with:
65
+ path: ./docs/public
66
+
67
+ deploy:
68
+ environment:
69
+ name: github-pages
70
+ url: ${{ steps.deployment.outputs.page_url }}
71
+ runs-on: ubuntu-latest
72
+ needs: build
73
+ if: github.ref == 'refs/heads/main'
74
+ steps:
75
+ - name: Deploy to GitHub Pages
76
+ id: deployment
77
+ uses: actions/deploy-pages@v4
@@ -0,0 +1,78 @@
1
+ name: Python Package CI/CD
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main # Or your default branch
7
+ tags:
8
+ - '*.*.*' # For publishing to PyPI
9
+ pull_request:
10
+ branches:
11
+ - main # Or your default branch
12
+
13
+ jobs:
14
+ build_and_test:
15
+ name: Build and Test (Python ${{ matrix.python-version }})
16
+ runs-on: ubuntu-latest
17
+ strategy:
18
+ fail-fast: false
19
+ matrix:
20
+ python-version: ["3.11", "3.12"] # graphql-api requires Python 3.11+
21
+
22
+ steps:
23
+ - name: Checkout repository
24
+ uses: actions/checkout@v4
25
+
26
+ - name: Set up Python ${{ matrix.python-version }}
27
+ uses: actions/setup-python@v5
28
+ with:
29
+ python-version: ${{ matrix.python-version }}
30
+
31
+ - name: Install UV
32
+ uses: astral-sh/setup-uv@v3
33
+
34
+ - name: Install dependencies
35
+ run: uv sync --dev
36
+
37
+ - name: Lint with Flake8
38
+ run: uv run flake8 graphql_api tests
39
+
40
+ - name: Test with Pytest
41
+ run: uv run pytest
42
+
43
+ publish:
44
+ name: Publish to PyPI
45
+ needs: build_and_test # Ensure tests pass before publishing
46
+ runs-on: ubuntu-latest
47
+ if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')
48
+ permissions:
49
+ id-token: write
50
+
51
+ steps:
52
+ - name: Validate tag format (e.g., 1.0.0)
53
+ run: |
54
+ TAG_NAME="${{ github.ref_name }}"
55
+ if ! [[ "$TAG_NAME" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
56
+ echo "Error: Tag '$TAG_NAME' is not in the required X.Y.Z numeric format (e.g., 1.0.0)."
57
+ exit 1
58
+ fi
59
+ echo "Tag '$TAG_NAME' is valid."
60
+ shell: bash
61
+
62
+ - name: Checkout repository
63
+ uses: actions/checkout@v4
64
+
65
+ - name: Set up Python
66
+ uses: actions/setup-python@v5
67
+ with:
68
+ python-version: '3.12' # Use compatible Python version
69
+
70
+ - name: Install UV
71
+ uses: astral-sh/setup-uv@v3
72
+
73
+ - name: Update VERSION file
74
+ run: echo "${{ github.ref_name }}" > VERSION
75
+ shell: bash
76
+
77
+ - name: Build and publish package to PyPI
78
+ run: uv build && uv publish
@@ -0,0 +1,23 @@
1
+ .idea
2
+ .DS_Store
3
+ .coverage
4
+ .pytest_cache
5
+
6
+ # Virtual environments
7
+ .venv/
8
+ env/
9
+ venv/
10
+
11
+ # Build artifacts
12
+ build/
13
+ dist/
14
+ *.egg-info/
15
+
16
+ # Testing
17
+ tests/logs/
18
+ tests/htmlcov/
19
+ htmlcov/
20
+
21
+ # Python
22
+ *.pyc
23
+ __pycache__/
@@ -0,0 +1,7 @@
1
+ {
2
+ "python.testing.pytestArgs": [
3
+ "tests"
4
+ ],
5
+ "python.testing.unittestEnabled": false,
6
+ "python.testing.pytestEnabled": true
7
+ }
@@ -1,44 +1,27 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: graphql_api
3
- Version: 1.4.18
3
+ Version: 1.4.20
4
4
  Summary: A framework for building Python GraphQL APIs.
5
- Home-page: https://gitlab.com/parob/graphql-api
6
- Download-URL: https://gitlab.com/parob/graphql/-/archive/v1.4.18/graphql_api-v1.4.18.tar.gz
7
- Author: Robert Parker
8
- Author-email: rob@parob.com
5
+ Author-email: Robert Parker <rob@parob.com>
9
6
  License: MIT
7
+ Project-URL: Homepage, https://gitlab.com/parob/graphql-api
8
+ Project-URL: Repository, https://gitlab.com/parob/graphql-api
10
9
  Keywords: GraphQL,GraphQL-API,GraphQLAPI,Server
11
10
  Classifier: Development Status :: 3 - Alpha
12
11
  Classifier: Intended Audience :: Developers
13
12
  Classifier: Programming Language :: Python :: 3
14
13
  Classifier: License :: OSI Approved :: MIT License
15
14
  Classifier: Operating System :: OS Independent
15
+ Requires-Python: <3.13,>=3.11
16
16
  Description-Content-Type: text/markdown
17
17
  License-File: LICENSE
18
- Requires-Dist: graphql-core~=3.1
19
- Requires-Dist: requests~=2.24
20
- Requires-Dist: typing-inspect~=0.6
21
- Requires-Dist: aiohttp~=3.8
22
- Requires-Dist: docstring-parser~=0.15
23
- Requires-Dist: pydantic~=2.0
24
- Provides-Extra: dev
25
- Requires-Dist: pytest~=5.4; extra == "dev"
26
- Requires-Dist: pytest-cov~=2.10; extra == "dev"
27
- Requires-Dist: coverage~=5.2; extra == "dev"
28
- Requires-Dist: faker~=4.1; extra == "dev"
29
- Dynamic: author
30
- Dynamic: author-email
31
- Dynamic: classifier
32
- Dynamic: description
33
- Dynamic: description-content-type
34
- Dynamic: download-url
35
- Dynamic: home-page
36
- Dynamic: keywords
37
- Dynamic: license
18
+ Requires-Dist: graphql-core
19
+ Requires-Dist: requests
20
+ Requires-Dist: typing-inspect
21
+ Requires-Dist: aiohttp
22
+ Requires-Dist: docstring-parser
23
+ Requires-Dist: pydantic
38
24
  Dynamic: license-file
39
- Dynamic: provides-extra
40
- Dynamic: requires-dist
41
- Dynamic: summary
42
25
 
43
26
  # GraphQL API for Python
44
27
 
@@ -54,6 +37,7 @@ A powerful and intuitive Python library for building GraphQL APIs, designed with
54
37
 
55
38
  - **Decorator-Based Schema:** Define your GraphQL schema declaratively using simple and intuitive decorators.
56
39
  - **Type Hinting:** Automatically converts Python type hints into GraphQL types.
40
+ - **Implicit Type Inference:** Automatically maps Pydantic models, dataclasses, and classes with fields - no explicit decorators needed.
57
41
  - **Pydantic & Dataclass Support:** Seamlessly use Pydantic and Dataclass models as GraphQL types.
58
42
  - **Asynchronous Execution:** Full support for `async` and `await` for high-performance, non-blocking resolvers.
59
43
  - **Apollo Federation:** Built-in support for creating federated services.
@@ -126,6 +110,7 @@ class Book(BaseModel):
126
110
  title: str
127
111
  author: str
128
112
 
113
+ @api.type(is_root_type=True)
129
114
  class BookAPI:
130
115
  @api.field
131
116
  def get_books(self) -> List[Book]:
@@ -134,7 +119,7 @@ class BookAPI:
134
119
  Book(title="1984", author="George Orwell"),
135
120
  ]
136
121
 
137
- api = GraphQLAPI(root_type=BookAPI)
122
+ api = GraphQLAPI()
138
123
 
139
124
  graphql_query = """
140
125
  query {
@@ -157,13 +142,14 @@ Define async resolvers for non-blocking I/O operations.
157
142
  import asyncio
158
143
  from graphql_api.api import GraphQLAPI
159
144
 
145
+ @api.type(is_root_type=True)
160
146
  class AsyncAPI:
161
147
  @api.field
162
148
  async def fetch_data(self) -> str:
163
149
  await asyncio.sleep(1)
164
150
  return "Data fetched successfully!"
165
151
 
166
- api = GraphQLAPI(root_type=AsyncAPI)
152
+ api = GraphQLAPI()
167
153
 
168
154
  # To execute async queries, you'll need an async executor
169
155
  # or to run it within an async context.
@@ -184,11 +170,11 @@ if __name__ == "__main__":
184
170
 
185
171
  ### Mutations with Dataclasses
186
172
 
187
- Use dataclasses to define the structure of your mutation inputs.
173
+ Use dataclasses to define the structure of your data, and mark fields as mutable to automatically separate them into the GraphQL Mutation type.
188
174
 
189
175
  ```python
190
176
  from dataclasses import dataclass
191
- from graphql_api.api import GraphQLAPI, field
177
+ from graphql_api.api import GraphQLAPI
192
178
 
193
179
  @dataclass
194
180
  class User:
@@ -198,22 +184,66 @@ class User:
198
184
  # A simple in-memory database
199
185
  db = {1: User(id=1, name="Alice")}
200
186
 
187
+ api = GraphQLAPI()
188
+
189
+ @api.type(is_root_type=True)
201
190
  class Root:
202
- @field
191
+ @api.field
203
192
  def get_user(self, user_id: int) -> User:
204
193
  return db.get(user_id)
205
194
 
206
- class Mutations:
207
- @field
195
+ @api.field(mutable=True)
208
196
  def add_user(self, user_id: int, name: str) -> User:
209
197
  new_user = User(id=user_id, name=name)
210
198
  db[user_id] = new_user
211
199
  return new_user
200
+ ```
201
+
202
+ GraphQL automatically separates queries and mutations - you don't need separate classes. Fields marked with `mutable=True` are placed in the Mutation type, while regular fields go in the Query type. Fields with `AsyncGenerator` return types are automatically detected as subscriptions. This automatic mapping means you can define all your operations in a single class and let `graphql-api` handle the schema organization for you.
203
+
204
+ ## Two Approaches for Complex Schemas
205
+
206
+ `graphql-api` supports two approaches for organizing your GraphQL schema:
207
+
208
+ ### Single Root Type (Recommended)
209
+ ```python
210
+ @api.type(is_root_type=True)
211
+ class Root:
212
+ @api.field
213
+ def query_field(self) -> str: ...
214
+
215
+ @api.field(mutable=True)
216
+ def mutation_field(self) -> str: ...
217
+
218
+ @api.field
219
+ async def subscription_field(self) -> AsyncGenerator[str, None]: ...
220
+
221
+ api = GraphQLAPI(root_type=Root)
222
+ ```
223
+
224
+ ### Explicit Types
225
+ ```python
226
+ @api.type
227
+ class Query:
228
+ @api.field
229
+ def query_field(self) -> str: ...
230
+
231
+ @api.type
232
+ class Mutation:
233
+ @api.field
234
+ def mutation_field(self) -> str: ...
235
+
236
+ @api.type
237
+ class Subscription:
238
+ @api.field
239
+ async def subscription_field(self) -> AsyncGenerator[str, None]: ...
212
240
 
213
- # The GraphQLAPI constructor will need to be updated to support mutations separately
214
- # api = GraphQLAPI(root_type=Root, mutation_type=Mutations)
241
+ api = GraphQLAPI(
242
+ query_type=Query,
243
+ mutation_type=Mutation,
244
+ subscription_type=Subscription
245
+ )
215
246
  ```
216
- *Note: The mutation API is illustrative. The library's `GraphQLAPI` constructor may need to be extended to support mutations as shown.*
217
247
 
218
248
  ## Running Tests
219
249
 
@@ -12,6 +12,7 @@ A powerful and intuitive Python library for building GraphQL APIs, designed with
12
12
 
13
13
  - **Decorator-Based Schema:** Define your GraphQL schema declaratively using simple and intuitive decorators.
14
14
  - **Type Hinting:** Automatically converts Python type hints into GraphQL types.
15
+ - **Implicit Type Inference:** Automatically maps Pydantic models, dataclasses, and classes with fields - no explicit decorators needed.
15
16
  - **Pydantic & Dataclass Support:** Seamlessly use Pydantic and Dataclass models as GraphQL types.
16
17
  - **Asynchronous Execution:** Full support for `async` and `await` for high-performance, non-blocking resolvers.
17
18
  - **Apollo Federation:** Built-in support for creating federated services.
@@ -84,6 +85,7 @@ class Book(BaseModel):
84
85
  title: str
85
86
  author: str
86
87
 
88
+ @api.type(is_root_type=True)
87
89
  class BookAPI:
88
90
  @api.field
89
91
  def get_books(self) -> List[Book]:
@@ -92,7 +94,7 @@ class BookAPI:
92
94
  Book(title="1984", author="George Orwell"),
93
95
  ]
94
96
 
95
- api = GraphQLAPI(root_type=BookAPI)
97
+ api = GraphQLAPI()
96
98
 
97
99
  graphql_query = """
98
100
  query {
@@ -115,13 +117,14 @@ Define async resolvers for non-blocking I/O operations.
115
117
  import asyncio
116
118
  from graphql_api.api import GraphQLAPI
117
119
 
120
+ @api.type(is_root_type=True)
118
121
  class AsyncAPI:
119
122
  @api.field
120
123
  async def fetch_data(self) -> str:
121
124
  await asyncio.sleep(1)
122
125
  return "Data fetched successfully!"
123
126
 
124
- api = GraphQLAPI(root_type=AsyncAPI)
127
+ api = GraphQLAPI()
125
128
 
126
129
  # To execute async queries, you'll need an async executor
127
130
  # or to run it within an async context.
@@ -142,11 +145,11 @@ if __name__ == "__main__":
142
145
 
143
146
  ### Mutations with Dataclasses
144
147
 
145
- Use dataclasses to define the structure of your mutation inputs.
148
+ Use dataclasses to define the structure of your data, and mark fields as mutable to automatically separate them into the GraphQL Mutation type.
146
149
 
147
150
  ```python
148
151
  from dataclasses import dataclass
149
- from graphql_api.api import GraphQLAPI, field
152
+ from graphql_api.api import GraphQLAPI
150
153
 
151
154
  @dataclass
152
155
  class User:
@@ -156,22 +159,66 @@ class User:
156
159
  # A simple in-memory database
157
160
  db = {1: User(id=1, name="Alice")}
158
161
 
162
+ api = GraphQLAPI()
163
+
164
+ @api.type(is_root_type=True)
159
165
  class Root:
160
- @field
166
+ @api.field
161
167
  def get_user(self, user_id: int) -> User:
162
168
  return db.get(user_id)
163
169
 
164
- class Mutations:
165
- @field
170
+ @api.field(mutable=True)
166
171
  def add_user(self, user_id: int, name: str) -> User:
167
172
  new_user = User(id=user_id, name=name)
168
173
  db[user_id] = new_user
169
174
  return new_user
175
+ ```
176
+
177
+ GraphQL automatically separates queries and mutations - you don't need separate classes. Fields marked with `mutable=True` are placed in the Mutation type, while regular fields go in the Query type. Fields with `AsyncGenerator` return types are automatically detected as subscriptions. This automatic mapping means you can define all your operations in a single class and let `graphql-api` handle the schema organization for you.
178
+
179
+ ## Two Approaches for Complex Schemas
180
+
181
+ `graphql-api` supports two approaches for organizing your GraphQL schema:
182
+
183
+ ### Single Root Type (Recommended)
184
+ ```python
185
+ @api.type(is_root_type=True)
186
+ class Root:
187
+ @api.field
188
+ def query_field(self) -> str: ...
189
+
190
+ @api.field(mutable=True)
191
+ def mutation_field(self) -> str: ...
192
+
193
+ @api.field
194
+ async def subscription_field(self) -> AsyncGenerator[str, None]: ...
195
+
196
+ api = GraphQLAPI(root_type=Root)
197
+ ```
198
+
199
+ ### Explicit Types
200
+ ```python
201
+ @api.type
202
+ class Query:
203
+ @api.field
204
+ def query_field(self) -> str: ...
205
+
206
+ @api.type
207
+ class Mutation:
208
+ @api.field
209
+ def mutation_field(self) -> str: ...
210
+
211
+ @api.type
212
+ class Subscription:
213
+ @api.field
214
+ async def subscription_field(self) -> AsyncGenerator[str, None]: ...
170
215
 
171
- # The GraphQLAPI constructor will need to be updated to support mutations separately
172
- # api = GraphQLAPI(root_type=Root, mutation_type=Mutations)
216
+ api = GraphQLAPI(
217
+ query_type=Query,
218
+ mutation_type=Mutation,
219
+ subscription_type=Subscription
220
+ )
173
221
  ```
174
- *Note: The mutation API is illustrative. The library's `GraphQLAPI` constructor may need to be extended to support mutations as shown.*
175
222
 
176
223
  ## Running Tests
177
224
 
@@ -0,0 +1 @@
1
+ 1.4.20
@@ -0,0 +1,81 @@
1
+ # GraphQL API Documentation
2
+
3
+ This directory contains the documentation for the GraphQL API library, built with Jekyll and deployed to GitHub Pages.
4
+
5
+ ## Local Development
6
+
7
+ ### Prerequisites
8
+
9
+ - Ruby 2.7 or newer
10
+ - Bundler gem
11
+
12
+ ### Setup
13
+
14
+ 1. Install dependencies:
15
+ ```bash
16
+ cd docs
17
+ bundle install
18
+ ```
19
+
20
+ 2. Serve the site locally:
21
+ ```bash
22
+ bundle exec jekyll serve
23
+ ```
24
+
25
+ 3. Open http://localhost:4000 in your browser
26
+
27
+ ### Project Structure
28
+
29
+ ```
30
+ docs/
31
+ ├── _config.yml # Jekyll configuration
32
+ ├── _layouts/ # Page layouts
33
+ │ └── default.html # Main layout template
34
+ ├── assets/ # CSS, JS, and other assets
35
+ │ └── css/
36
+ │ └── style.scss # Main stylesheet
37
+ ├── index.md # Homepage
38
+ ├── getting-started.md # Getting started guide
39
+ ├── examples.md # Examples and tutorials
40
+ ├── api-reference.md # Complete API reference
41
+ ├── contributing.md # Contributing guidelines
42
+ ├── Gemfile # Ruby dependencies
43
+ └── README.md # This file
44
+ ```
45
+
46
+ ## Adding Content
47
+
48
+ ### New Pages
49
+
50
+ 1. Create a new Markdown file in the docs directory
51
+ 2. Add front matter at the top:
52
+ ```yaml
53
+ ---
54
+ layout: default
55
+ title: "Page Title"
56
+ description: "Page description"
57
+ ---
58
+ ```
59
+ 3. Add the page to navigation in `_config.yml` if needed
60
+
61
+ ### Updating Existing Content
62
+
63
+ Simply edit the corresponding Markdown files. The site will rebuild automatically when changes are pushed to the main branch.
64
+
65
+ ## Deployment
66
+
67
+ The documentation is automatically deployed to GitHub Pages via GitHub Actions when changes are pushed to the main branch. The workflow is defined in `.github/workflows/pages.yml`.
68
+
69
+ ## Customization
70
+
71
+ ### Styling
72
+
73
+ The main stylesheet is in `assets/css/style.scss`. It imports the base theme and adds custom styling for the documentation.
74
+
75
+ ### Layout
76
+
77
+ The main layout template is in `_layouts/default.html`. It includes the header, navigation, content area, and footer.
78
+
79
+ ### Configuration
80
+
81
+ Site configuration is in `_config.yml`. This includes site metadata, navigation, and Jekyll settings.
@@ -0,0 +1,71 @@
1
+ ---
2
+ title: "GraphQL API for Python"
3
+ type: docs
4
+ ---
5
+
6
+ > **A powerful and intuitive Python library for building GraphQL APIs with a code-first, decorator-based approach.**
7
+
8
+ # GraphQL API for Python
9
+
10
+ [![PyPI version](https://badge.fury.io/py/graphql-api.svg)](https://badge.fury.io/py/graphql-api)
11
+ [![Python versions](https://img.shields.io/pypi/pyversions/graphql-api.svg)](https://pypi.org/project/graphql-api/)
12
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
13
+
14
+ ## Why GraphQL API?
15
+
16
+ `graphql-api` simplifies schema definition by leveraging Python's type hints, dataclasses, and Pydantic models, allowing you to build robust and maintainable GraphQL services with minimal boilerplate.
17
+
18
+ ## Key Features
19
+
20
+ | Feature | Description |
21
+ |---------|-------------|
22
+ | 🎯 **Code-First Approach** | Define your GraphQL schema using Python decorators and type hints. No SDL required. |
23
+ | ⚡ **Type Safety** | Automatic type conversion from Python types to GraphQL types with full type checking support. |
24
+ | 🔄 **Async Support** | Built-in support for async/await patterns and real-time subscriptions. |
25
+ | 🧩 **Pydantic Integration** | Seamlessly use Pydantic models and dataclasses as GraphQL types. |
26
+ | 🌐 **Federation Ready** | Built-in Apollo Federation support for microservice architectures. |
27
+ | 🎛️ **Flexible Schema** | Choose between unified root types or explicit query/mutation/subscription separation. |
28
+
29
+ ## Quick Start
30
+
31
+ Get up and running in minutes:
32
+
33
+ ```bash
34
+ pip install graphql-api
35
+ ```
36
+
37
+ ```python
38
+ from graphql_api.api import GraphQLAPI
39
+
40
+ # Initialize the API
41
+ api = GraphQLAPI()
42
+
43
+ # Define your schema with decorators
44
+ @api.type(is_root_type=True)
45
+ class Query:
46
+ @api.field
47
+ def hello(self, name: str = "World") -> str:
48
+ return f"Hello, {name}!"
49
+
50
+ # Execute queries
51
+ result = api.execute('{ hello(name: "Developer") }')
52
+ print(result.data) # {'hello': 'Hello, Developer!'}
53
+ ```
54
+
55
+ ## Key Features
56
+
57
+ - **Decorator-Based Schema:** Define your GraphQL schema declaratively using simple and intuitive decorators
58
+ - **Type Hinting:** Automatically converts Python type hints into GraphQL types
59
+ - **Implicit Type Inference:** Automatically maps Pydantic models, dataclasses, and classes with fields
60
+ - **Pydantic & Dataclass Support:** Seamlessly use Pydantic and Dataclass models as GraphQL types
61
+ - **Asynchronous Execution:** Full support for `async` and `await` for high-performance, non-blocking resolvers
62
+ - **Apollo Federation:** Built-in support for creating federated services
63
+ - **Subscriptions:** Implement real-time functionality with GraphQL subscriptions
64
+ - **Middleware:** Add custom logic to your resolvers with a flexible middleware system
65
+ - **Relay Support:** Includes helpers for building Relay-compliant schemas
66
+
67
+ ## What's Next?
68
+
69
+ - 📚 **[Getting Started](docs/getting-started/)** - Learn the basics with our comprehensive guide
70
+ - 💡 **[Examples](docs/examples/)** - Explore practical examples and tutorials for real-world scenarios
71
+ - 📖 **[API Reference](docs/api-reference/)** - Check out the complete API documentation
@@ -0,0 +1,38 @@
1
+ ---
2
+ title: "Documentation"
3
+ weight: 1
4
+ bookCollapseSection: false
5
+ bookFlatSection: true
6
+ ---
7
+
8
+ > **Complete documentation for GraphQL API, from basic concepts to advanced features.**
9
+
10
+ Welcome to the GraphQL API documentation! This section contains everything you need to know to build powerful GraphQL APIs with Python.
11
+
12
+ ## Getting Started
13
+
14
+ New to GraphQL API? Start here:
15
+
16
+ - **[Getting Started](getting-started/)** - Installation and your first API
17
+
18
+ ## Guides
19
+
20
+ Step-by-step guides for common tasks:
21
+
22
+ - **[Examples & Tutorials](examples/)** - Practical examples and tutorials
23
+ - **[Schema Definition](defining-schemas/)** - How to define types and fields
24
+ - **[Pydantic & Dataclasses](pydantic-and-dataclasses/)** - Working with data models
25
+ - **[Async & Subscriptions](async-and-subscriptions/)** - Real-time functionality
26
+
27
+ ## Advanced Topics
28
+
29
+ For experienced users:
30
+
31
+ - **[Apollo Federation](federation/)** - Building distributed graphs
32
+ - **[Advanced Features](advanced/)** - Middleware, directives, and more
33
+
34
+ ## Reference
35
+
36
+ Complete API documentation:
37
+
38
+ - **[API Reference](api-reference/)** - Classes, methods, and functions