graphql-api 1.4.19__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 (85) hide show
  1. graphql_api-1.4.20/.github/workflows/pages.yml +77 -0
  2. {graphql_api-1.4.19 → graphql_api-1.4.20}/PKG-INFO +58 -11
  3. {graphql_api-1.4.19 → graphql_api-1.4.20}/README.md +57 -10
  4. graphql_api-1.4.20/VERSION +1 -0
  5. graphql_api-1.4.20/docs/README.md +81 -0
  6. graphql_api-1.4.20/docs/content/_index.md +71 -0
  7. graphql_api-1.4.20/docs/content/docs/_index.md +38 -0
  8. {graphql_api-1.4.19/docs_md → graphql_api-1.4.20/docs/content/docs}/advanced.md +25 -13
  9. graphql_api-1.4.20/docs/content/docs/api-reference.md +551 -0
  10. {graphql_api-1.4.19/docs_md → graphql_api-1.4.20/docs/content/docs}/async-and-subscriptions.md +79 -11
  11. graphql_api-1.4.20/docs/content/docs/contributing.md +442 -0
  12. {graphql_api-1.4.19/docs_md → graphql_api-1.4.20/docs/content/docs}/defining-schemas.md +27 -5
  13. graphql_api-1.4.20/docs/content/docs/examples.md +528 -0
  14. {graphql_api-1.4.19/docs_md → graphql_api-1.4.20/docs/content/docs}/federation.md +8 -0
  15. {graphql_api-1.4.19/docs_md → graphql_api-1.4.20/docs/content/docs}/getting-started.md +5 -0
  16. {graphql_api-1.4.19/docs_md → graphql_api-1.4.20/docs/content/docs}/pydantic-and-dataclasses.md +8 -0
  17. graphql_api-1.4.20/docs/hugo.toml +86 -0
  18. graphql_api-1.4.20/docs/index.md +212 -0
  19. {graphql_api-1.4.19 → graphql_api-1.4.20}/graphql_api/api.py +137 -13
  20. {graphql_api-1.4.19 → graphql_api-1.4.20}/graphql_api/mapper.py +36 -4
  21. {graphql_api-1.4.19 → graphql_api-1.4.20}/graphql_api.egg-info/PKG-INFO +58 -11
  22. {graphql_api-1.4.19 → graphql_api-1.4.20}/graphql_api.egg-info/SOURCES.txt +17 -19
  23. {graphql_api-1.4.19 → graphql_api-1.4.20}/tests/test_async.py +2 -1
  24. {graphql_api-1.4.19 → graphql_api-1.4.20}/tests/test_calculator.py +5 -5
  25. {graphql_api-1.4.19 → graphql_api-1.4.20}/tests/test_custom_types.py +13 -13
  26. {graphql_api-1.4.19 → graphql_api-1.4.20}/tests/test_dataclass.py +7 -7
  27. {graphql_api-1.4.19 → graphql_api-1.4.20}/tests/test_directives.py +11 -11
  28. {graphql_api-1.4.19 → graphql_api-1.4.20}/tests/test_docstrings.py +10 -10
  29. {graphql_api-1.4.19 → graphql_api-1.4.20}/tests/test_error.py +6 -6
  30. {graphql_api-1.4.19 → graphql_api-1.4.20}/tests/test_federation.py +4 -6
  31. {graphql_api-1.4.19 → graphql_api-1.4.20}/tests/test_federation_example.py +8 -8
  32. {graphql_api-1.4.19 → graphql_api-1.4.20}/tests/test_filtering.py +39 -38
  33. {graphql_api-1.4.19 → graphql_api-1.4.20}/tests/test_graphql.py +58 -61
  34. {graphql_api-1.4.19 → graphql_api-1.4.20}/tests/test_middleware.py +3 -3
  35. {graphql_api-1.4.19 → graphql_api-1.4.20}/tests/test_pydantic.py +22 -22
  36. {graphql_api-1.4.19 → graphql_api-1.4.20}/tests/test_relay.py +1 -1
  37. {graphql_api-1.4.19 → graphql_api-1.4.20}/tests/test_remote.py +62 -76
  38. {graphql_api-1.4.19 → graphql_api-1.4.20}/tests/test_schema.py +10 -11
  39. {graphql_api-1.4.19 → graphql_api-1.4.20}/tests/test_subscriptions.py +10 -10
  40. graphql_api-1.4.20/tests/test_unified_vs_explicit_schema.py +241 -0
  41. graphql_api-1.4.19/VERSION +0 -1
  42. graphql_api-1.4.19/docs/_static/favicon.ico +0 -0
  43. graphql_api-1.4.19/docs/_static/logo.png +0 -0
  44. graphql_api-1.4.19/docs/_templates/sidebarlogo.html +0 -7
  45. graphql_api-1.4.19/docs/conf.py +0 -39
  46. graphql_api-1.4.19/docs/images/python_to_graphql.png +0 -0
  47. graphql_api-1.4.19/docs/images/schema_structure.png +0 -0
  48. graphql_api-1.4.19/docs/index.rst +0 -107
  49. graphql_api-1.4.19/docs/installation.rst +0 -25
  50. graphql_api-1.4.19/docs/quickstart.rst +0 -431
  51. graphql_api-1.4.19/docs/schemas.rst +0 -405
  52. graphql_api-1.4.19/docs/types.rst +0 -140
  53. graphql_api-1.4.19/docs_md/index.md +0 -14
  54. {graphql_api-1.4.19 → graphql_api-1.4.20}/.github/workflows/python-package.yml +0 -0
  55. {graphql_api-1.4.19 → graphql_api-1.4.20}/.gitignore +0 -0
  56. {graphql_api-1.4.19 → graphql_api-1.4.20}/.vscode/settings.json +0 -0
  57. {graphql_api-1.4.19 → graphql_api-1.4.20}/LICENSE +0 -0
  58. {graphql_api-1.4.19 → graphql_api-1.4.20}/graphql_api/__init__.py +0 -0
  59. {graphql_api-1.4.19 → graphql_api-1.4.20}/graphql_api/context.py +0 -0
  60. {graphql_api-1.4.19 → graphql_api-1.4.20}/graphql_api/dataclass_mapping.py +0 -0
  61. {graphql_api-1.4.19 → graphql_api-1.4.20}/graphql_api/decorators.py +0 -0
  62. {graphql_api-1.4.19 → graphql_api-1.4.20}/graphql_api/directives.py +0 -0
  63. {graphql_api-1.4.19 → graphql_api-1.4.20}/graphql_api/error.py +0 -0
  64. {graphql_api-1.4.19 → graphql_api-1.4.20}/graphql_api/exception.py +0 -0
  65. {graphql_api-1.4.19 → graphql_api-1.4.20}/graphql_api/executor.py +0 -0
  66. {graphql_api-1.4.19 → graphql_api-1.4.20}/graphql_api/federation/__init__.py +0 -0
  67. {graphql_api-1.4.19 → graphql_api-1.4.20}/graphql_api/federation/directives.py +0 -0
  68. {graphql_api-1.4.19 → graphql_api-1.4.20}/graphql_api/federation/federation.py +0 -0
  69. {graphql_api-1.4.19 → graphql_api-1.4.20}/graphql_api/federation/types.py +0 -0
  70. {graphql_api-1.4.19 → graphql_api-1.4.20}/graphql_api/middleware.py +0 -0
  71. {graphql_api-1.4.19 → graphql_api-1.4.20}/graphql_api/pydantic.py +0 -0
  72. {graphql_api-1.4.19 → graphql_api-1.4.20}/graphql_api/reduce.py +0 -0
  73. {graphql_api-1.4.19 → graphql_api-1.4.20}/graphql_api/relay.py +0 -0
  74. {graphql_api-1.4.19 → graphql_api-1.4.20}/graphql_api/remote.py +0 -0
  75. {graphql_api-1.4.19 → graphql_api-1.4.20}/graphql_api/schema.py +0 -0
  76. {graphql_api-1.4.19 → graphql_api-1.4.20}/graphql_api/types.py +0 -0
  77. {graphql_api-1.4.19 → graphql_api-1.4.20}/graphql_api/utils.py +0 -0
  78. {graphql_api-1.4.19 → graphql_api-1.4.20}/graphql_api.egg-info/dependency_links.txt +0 -0
  79. {graphql_api-1.4.19 → graphql_api-1.4.20}/graphql_api.egg-info/requires.txt +0 -0
  80. {graphql_api-1.4.19 → graphql_api-1.4.20}/graphql_api.egg-info/top_level.txt +0 -0
  81. {graphql_api-1.4.19 → graphql_api-1.4.20}/pyproject.toml +0 -0
  82. {graphql_api-1.4.19 → graphql_api-1.4.20}/setup.cfg +0 -0
  83. {graphql_api-1.4.19 → graphql_api-1.4.20}/tests/__init__.py +0 -0
  84. {graphql_api-1.4.19 → graphql_api-1.4.20}/tests/test_federation_example.graphql +0 -0
  85. {graphql_api-1.4.19 → graphql_api-1.4.20}/uv.lock +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
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: graphql_api
3
- Version: 1.4.19
3
+ Version: 1.4.20
4
4
  Summary: A framework for building Python GraphQL APIs.
5
5
  Author-email: Robert Parker <rob@parob.com>
6
6
  License: MIT
@@ -37,6 +37,7 @@ A powerful and intuitive Python library for building GraphQL APIs, designed with
37
37
 
38
38
  - **Decorator-Based Schema:** Define your GraphQL schema declaratively using simple and intuitive decorators.
39
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.
40
41
  - **Pydantic & Dataclass Support:** Seamlessly use Pydantic and Dataclass models as GraphQL types.
41
42
  - **Asynchronous Execution:** Full support for `async` and `await` for high-performance, non-blocking resolvers.
42
43
  - **Apollo Federation:** Built-in support for creating federated services.
@@ -109,6 +110,7 @@ class Book(BaseModel):
109
110
  title: str
110
111
  author: str
111
112
 
113
+ @api.type(is_root_type=True)
112
114
  class BookAPI:
113
115
  @api.field
114
116
  def get_books(self) -> List[Book]:
@@ -117,7 +119,7 @@ class BookAPI:
117
119
  Book(title="1984", author="George Orwell"),
118
120
  ]
119
121
 
120
- api = GraphQLAPI(root_type=BookAPI)
122
+ api = GraphQLAPI()
121
123
 
122
124
  graphql_query = """
123
125
  query {
@@ -140,13 +142,14 @@ Define async resolvers for non-blocking I/O operations.
140
142
  import asyncio
141
143
  from graphql_api.api import GraphQLAPI
142
144
 
145
+ @api.type(is_root_type=True)
143
146
  class AsyncAPI:
144
147
  @api.field
145
148
  async def fetch_data(self) -> str:
146
149
  await asyncio.sleep(1)
147
150
  return "Data fetched successfully!"
148
151
 
149
- api = GraphQLAPI(root_type=AsyncAPI)
152
+ api = GraphQLAPI()
150
153
 
151
154
  # To execute async queries, you'll need an async executor
152
155
  # or to run it within an async context.
@@ -167,11 +170,11 @@ if __name__ == "__main__":
167
170
 
168
171
  ### Mutations with Dataclasses
169
172
 
170
- 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.
171
174
 
172
175
  ```python
173
176
  from dataclasses import dataclass
174
- from graphql_api.api import GraphQLAPI, field
177
+ from graphql_api.api import GraphQLAPI
175
178
 
176
179
  @dataclass
177
180
  class User:
@@ -181,22 +184,66 @@ class User:
181
184
  # A simple in-memory database
182
185
  db = {1: User(id=1, name="Alice")}
183
186
 
187
+ api = GraphQLAPI()
188
+
189
+ @api.type(is_root_type=True)
184
190
  class Root:
185
- @field
191
+ @api.field
186
192
  def get_user(self, user_id: int) -> User:
187
193
  return db.get(user_id)
188
194
 
189
- class Mutations:
190
- @field
195
+ @api.field(mutable=True)
191
196
  def add_user(self, user_id: int, name: str) -> User:
192
197
  new_user = User(id=user_id, name=name)
193
198
  db[user_id] = new_user
194
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]: ...
195
240
 
196
- # The GraphQLAPI constructor will need to be updated to support mutations separately
197
- # api = GraphQLAPI(root_type=Root, mutation_type=Mutations)
241
+ api = GraphQLAPI(
242
+ query_type=Query,
243
+ mutation_type=Mutation,
244
+ subscription_type=Subscription
245
+ )
198
246
  ```
199
- *Note: The mutation API is illustrative. The library's `GraphQLAPI` constructor may need to be extended to support mutations as shown.*
200
247
 
201
248
  ## Running Tests
202
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
@@ -1,3 +1,11 @@
1
+ ---
2
+ title: "Advanced Topics"
3
+ linkTitle: "Advanced"
4
+ weight: 7
5
+ description: >
6
+ Explore advanced features like middleware, directives, and Relay support
7
+ ---
8
+
1
9
  # Advanced Topics
2
10
 
3
11
  This section covers some of the more advanced features of `graphql-api`, including middleware, error handling, resolver context, directives, and Relay support.
@@ -55,12 +63,14 @@ class UserNotFoundError(GraphQLError):
55
63
  )
56
64
 
57
65
  # In a resolver, you can raise this exception
58
- @api.field
59
- def get_user_by_id(self, user_id: int) -> User:
60
- user = find_user_in_db(user_id)
61
- if not user:
62
- raise UserNotFoundError(user_id)
63
- return user
66
+ @api.type(is_root_type=True)
67
+ class Query:
68
+ @api.field
69
+ def get_user_by_id(self, user_id: int) -> User:
70
+ user = find_user_in_db(user_id)
71
+ if not user:
72
+ raise UserNotFoundError(user_id)
73
+ return user
64
74
  ```
65
75
 
66
76
  When this resolver is executed with an invalid ID, the client will receive a structured error in the response:
@@ -109,15 +119,17 @@ result = api.execute(
109
119
  The context is available via the `info` argument (which is of type `GraphQLResolveInfo`) that is passed to every resolver.
110
120
 
111
121
  ```python
112
- @api.field
113
- def get_my_profile(self, info) -> User:
114
- # Access the context from the `info` object.
115
- current_user = info.context.get("current_user")
122
+ @api.type(is_root_type=True)
123
+ class Query:
124
+ @api.field
125
+ def get_my_profile(self, info) -> User:
126
+ # Access the context from the `info` object.
127
+ current_user = info.context.get("current_user")
116
128
 
117
- if not current_user:
118
- raise PermissionError("You must be logged in to view your profile.")
129
+ if not current_user:
130
+ raise PermissionError("You must be logged in to view your profile.")
119
131
 
120
- return current_user
132
+ return current_user
121
133
  ```
122
134
 
123
135
  Using the context is the recommended way to provide resolvers with request-scoped data, keeping them decoupled from the transport layer (e.g., HTTP).