ariadne-codegen 0.14.0.dev2__tar.gz → 0.15.0.dev1__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.
- {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/LICENSE +1 -1
- {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/PKG-INFO +117 -52
- {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/README.md +98 -11
- ariadne_codegen-0.15.0.dev1/ariadne_codegen/__about__.py +1 -0
- {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/client_generators/client.py +95 -41
- {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/client_generators/comments.py +0 -1
- {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/client_generators/constants.py +6 -0
- ariadne_codegen-0.15.0.dev1/ariadne_codegen/client_generators/custom_arguments.py +277 -0
- ariadne_codegen-0.15.0.dev1/ariadne_codegen/client_generators/custom_fields.py +389 -0
- ariadne_codegen-0.15.0.dev1/ariadne_codegen/client_generators/custom_fields_typing.py +155 -0
- ariadne_codegen-0.15.0.dev1/ariadne_codegen/client_generators/custom_operation.py +191 -0
- {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/client_generators/dependencies/async_base_client.py +5 -3
- {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/client_generators/dependencies/async_base_client_open_telemetry.py +5 -3
- {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/client_generators/dependencies/base_model.py +2 -1
- {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/client_generators/dependencies/base_operation.py +53 -15
- {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/client_generators/dependencies/exceptions.py +1 -1
- {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/client_generators/input_fields.py +25 -21
- {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/client_generators/input_types.py +2 -1
- {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/client_generators/package.py +9 -9
- {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/client_generators/result_fields.py +4 -3
- {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/client_generators/result_types.py +2 -1
- {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/codegen.py +61 -44
- {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/contrib/client_forward_refs.py +10 -9
- {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/contrib/extract_operations.py +4 -1
- {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/exceptions.py +1 -1
- {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/graphql_schema_generators/schema.py +48 -44
- {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/plugins/base.py +0 -14
- {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/plugins/manager.py +0 -1
- {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/schema.py +3 -3
- {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/settings.py +1 -1
- ariadne_codegen-0.15.0.dev1/pyproject.toml +179 -0
- ariadne_codegen-0.14.0.dev2/ariadne_codegen/client_generators/custom_fields.py +0 -400
- ariadne_codegen-0.14.0.dev2/ariadne_codegen/client_generators/custom_fields_typing.py +0 -112
- ariadne_codegen-0.14.0.dev2/ariadne_codegen/client_generators/custom_operation.py +0 -363
- ariadne_codegen-0.14.0.dev2/pyproject.toml +0 -84
- {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/.gitignore +0 -0
- {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/__init__.py +0 -0
- {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/__main__.py +0 -0
- {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/client_generators/__init__.py +0 -0
- {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/client_generators/arguments.py +0 -0
- /ariadne_codegen-0.14.0.dev2/ariadne_codegen/client_generators/utils.py → /ariadne_codegen-0.15.0.dev1/ariadne_codegen/client_generators/custom_generator_utils.py +0 -0
- {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/client_generators/dependencies/__init__.py +0 -0
- {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/client_generators/dependencies/base_client.py +0 -0
- {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/client_generators/dependencies/base_client_open_telemetry.py +0 -0
- {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/client_generators/enums.py +0 -0
- {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/client_generators/fragments.py +0 -0
- {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/client_generators/init_file.py +0 -0
- {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/client_generators/scalars.py +0 -0
- {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/client_generators/types.py +0 -0
- {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/config.py +0 -0
- {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/contrib/__init__.py +0 -0
- {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/contrib/no_reimports.py +0 -0
- {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/contrib/shorter_results.py +0 -0
- {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/graphql_schema_generators/__init__.py +0 -0
- {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/graphql_schema_generators/constants.py +0 -0
- {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/graphql_schema_generators/directives.py +0 -0
- {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/graphql_schema_generators/fields.py +0 -0
- {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/graphql_schema_generators/named_types.py +0 -0
- {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/graphql_schema_generators/utils.py +0 -0
- {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/main.py +0 -0
- {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/plugins/__init__.py +0 -0
- {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/plugins/explorer.py +0 -0
- {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/py.typed +0 -0
- {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: ariadne-codegen
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.15.0.dev1
|
|
4
4
|
Summary: Generate fully typed GraphQL client from schema, queries and mutations!
|
|
5
5
|
Project-URL: Homepage, https://ariadnegraphql.org/
|
|
6
6
|
Project-URL: Repository, https://github.com/mirumee/ariadne-codegen
|
|
@@ -8,35 +8,7 @@ Project-URL: Bug Tracker, https://github.com/mirumee/ariadne-codegen/issues
|
|
|
8
8
|
Project-URL: Community, https://github.com/mirumee/ariadne/discussions
|
|
9
9
|
Project-URL: Twitter, https://twitter.com/AriadneGraphQL
|
|
10
10
|
Author-email: Mirumee Software <hello@mirumee.com>
|
|
11
|
-
License: BSD
|
|
12
|
-
|
|
13
|
-
Copyright (c) 2023, Mirumee Labs
|
|
14
|
-
All rights reserved.
|
|
15
|
-
|
|
16
|
-
Redistribution and use in source and binary forms, with or without
|
|
17
|
-
modification, are permitted provided that the following conditions are met:
|
|
18
|
-
|
|
19
|
-
1. Redistributions of source code must retain the above copyright notice, this
|
|
20
|
-
list of conditions and the following disclaimer.
|
|
21
|
-
|
|
22
|
-
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
23
|
-
this list of conditions and the following disclaimer in the documentation
|
|
24
|
-
and/or other materials provided with the distribution.
|
|
25
|
-
|
|
26
|
-
3. Neither the name of the copyright holder nor the names of its
|
|
27
|
-
contributors may be used to endorse or promote products derived from
|
|
28
|
-
this software without specific prior written permission.
|
|
29
|
-
|
|
30
|
-
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
31
|
-
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
32
|
-
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
33
|
-
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
34
|
-
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
35
|
-
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
36
|
-
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
37
|
-
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
38
|
-
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
39
|
-
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
11
|
+
License-Expression: BSD-3-Clause
|
|
40
12
|
License-File: LICENSE
|
|
41
13
|
Classifier: Development Status :: 4 - Beta
|
|
42
14
|
Classifier: Intended Audience :: Developers
|
|
@@ -47,7 +19,9 @@ Classifier: Programming Language :: Python :: 3.9
|
|
|
47
19
|
Classifier: Programming Language :: Python :: 3.10
|
|
48
20
|
Classifier: Programming Language :: Python :: 3.11
|
|
49
21
|
Classifier: Programming Language :: Python :: 3.12
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
50
23
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
24
|
+
Requires-Python: >=3.9
|
|
51
25
|
Requires-Dist: autoflake
|
|
52
26
|
Requires-Dist: black
|
|
53
27
|
Requires-Dist: click~=8.1
|
|
@@ -57,20 +31,24 @@ Requires-Dist: isort
|
|
|
57
31
|
Requires-Dist: pydantic<3.0.0,>=2.0.0
|
|
58
32
|
Requires-Dist: toml~=0.10
|
|
59
33
|
Provides-Extra: dev
|
|
60
|
-
Requires-Dist:
|
|
61
|
-
Requires-Dist: freezegun; extra == 'dev'
|
|
62
|
-
Requires-Dist: mypy; extra == 'dev'
|
|
63
|
-
Requires-Dist: pylint; extra == 'dev'
|
|
64
|
-
Requires-Dist: pytest; extra == 'dev'
|
|
65
|
-
Requires-Dist: pytest-asyncio; extra == 'dev'
|
|
66
|
-
Requires-Dist: pytest-httpx; extra == 'dev'
|
|
67
|
-
Requires-Dist: pytest-mock; extra == 'dev'
|
|
68
|
-
Requires-Dist: requests-toolbelt; extra == 'dev'
|
|
69
|
-
Requires-Dist: types-toml; extra == 'dev'
|
|
34
|
+
Requires-Dist: ipdb; extra == 'dev'
|
|
70
35
|
Provides-Extra: opentelemetry
|
|
71
36
|
Requires-Dist: opentelemetry-api; extra == 'opentelemetry'
|
|
72
37
|
Provides-Extra: subscriptions
|
|
73
38
|
Requires-Dist: websockets~=11.0; extra == 'subscriptions'
|
|
39
|
+
Provides-Extra: test
|
|
40
|
+
Requires-Dist: ariadne; extra == 'test'
|
|
41
|
+
Requires-Dist: freezegun; extra == 'test'
|
|
42
|
+
Requires-Dist: opentelemetry-api; extra == 'test'
|
|
43
|
+
Requires-Dist: pytest; extra == 'test'
|
|
44
|
+
Requires-Dist: pytest-asyncio; extra == 'test'
|
|
45
|
+
Requires-Dist: pytest-httpx; extra == 'test'
|
|
46
|
+
Requires-Dist: pytest-mock; extra == 'test'
|
|
47
|
+
Requires-Dist: requests-toolbelt; extra == 'test'
|
|
48
|
+
Requires-Dist: types-toml; extra == 'test'
|
|
49
|
+
Requires-Dist: websockets~=11.0; extra == 'test'
|
|
50
|
+
Provides-Extra: types
|
|
51
|
+
Requires-Dist: mypy>=1.0.0; extra == 'types'
|
|
74
52
|
Description-Content-Type: text/markdown
|
|
75
53
|
|
|
76
54
|
[](https://ariadnegraphql.org)
|
|
@@ -128,7 +106,7 @@ queries_path = "queries.graphql"
|
|
|
128
106
|
|
|
129
107
|
Required settings:
|
|
130
108
|
|
|
131
|
-
- `queries_path` - path to file/directory with queries
|
|
109
|
+
- `queries_path` - path to file/directory with queries (Can be optional if `enable_custom_operations` is used)
|
|
132
110
|
|
|
133
111
|
One of the following 2 parameters is required, in case of providing both of them `schema_path` is prioritized:
|
|
134
112
|
|
|
@@ -156,6 +134,93 @@ Optional settings:
|
|
|
156
134
|
- `opentelemetry_client` (defaults to `false`) - default base clients don't support any performance tracing. Change this option to `true` to use the base client with Open Telemetry support.
|
|
157
135
|
- `files_to_include` (defaults to `[]`) - list of files which will be copied into generated package
|
|
158
136
|
- `plugins` (defaults to `[]`) - list of plugins to use during generation
|
|
137
|
+
- `enable_custom_operations` (defaults to `false`) - enables building custom operations. Generates additional files that contains all the classes and methods for generation.
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
## Custom operation builder
|
|
141
|
+
|
|
142
|
+
The custom operation builder allows you to create complex GraphQL queries in a structured and intuitive way.
|
|
143
|
+
|
|
144
|
+
### Example Code
|
|
145
|
+
|
|
146
|
+
```python
|
|
147
|
+
import asyncio
|
|
148
|
+
from graphql_client import Client
|
|
149
|
+
from graphql_client.custom_fields import (
|
|
150
|
+
ProductFields,
|
|
151
|
+
ProductTranslatableContentFields,
|
|
152
|
+
ProductTranslationFields,
|
|
153
|
+
TranslatableItemConnectionFields,
|
|
154
|
+
TranslatableItemEdgeFields,
|
|
155
|
+
)
|
|
156
|
+
from graphql_client.custom_queries import Query
|
|
157
|
+
from graphql_client.enums import LanguageCodeEnum, TranslatableKinds
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
async def get_products():
|
|
161
|
+
# Create a client instance with the specified URL and headers
|
|
162
|
+
client = Client(
|
|
163
|
+
url="https://saleor.cloud/graphql/",
|
|
164
|
+
headers={"authorization": "bearer ..."},
|
|
165
|
+
)
|
|
166
|
+
|
|
167
|
+
# Build the queries
|
|
168
|
+
product_query = Query.product(id="...", channel="channel-uk").fields(
|
|
169
|
+
ProductFields.id,
|
|
170
|
+
ProductFields.name,
|
|
171
|
+
)
|
|
172
|
+
|
|
173
|
+
translation_query = Query.translations(kind=TranslatableKinds.PRODUCT, first=10).fields(
|
|
174
|
+
TranslatableItemConnectionFields.edges().alias("aliased_edges").fields(
|
|
175
|
+
TranslatableItemEdgeFields.node.on(
|
|
176
|
+
"ProductTranslatableContent",
|
|
177
|
+
ProductTranslatableContentFields.id,
|
|
178
|
+
ProductTranslatableContentFields.product_id,
|
|
179
|
+
ProductTranslatableContentFields.name,
|
|
180
|
+
)
|
|
181
|
+
)
|
|
182
|
+
)
|
|
183
|
+
|
|
184
|
+
# Execute the queries with an operation name
|
|
185
|
+
response = await client.query(
|
|
186
|
+
product_query,
|
|
187
|
+
translation_query,
|
|
188
|
+
operation_name="get_products",
|
|
189
|
+
)
|
|
190
|
+
|
|
191
|
+
print(response)
|
|
192
|
+
|
|
193
|
+
# Run the async function
|
|
194
|
+
asyncio.run(get_products())
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
### Explanation
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
1. Building the Product Query:
|
|
201
|
+
1. The Query.product(id="...", channel="channel-uk") initiates a query for a product with the specified ID and channel.
|
|
202
|
+
2. .fields(ProductFields.id, ProductFields.name) specifies the fields to retrieve for the product: id and name.
|
|
203
|
+
2. Building the Translation Query:
|
|
204
|
+
1. The Query.translations(kind=TranslatableKinds.PRODUCT, first=10) initiates a query for product translations.
|
|
205
|
+
2. .fields(...) specifies the fields to retrieve for the translations.
|
|
206
|
+
3. .alias("aliased_edges") renames the edges field to aliased_edges.
|
|
207
|
+
4. .on("ProductTranslatableContent", ...) specifies the fields to retrieve if the node is of type ProductTranslatableContent: id, product_id, and name.
|
|
208
|
+
3. Executing the Queries:
|
|
209
|
+
1. The client.query(...) method is called with the built queries and an operation name "get_products".
|
|
210
|
+
2. This method sends the queries to the server and retrieves the response.
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
### Example pyproject.toml configuration.
|
|
214
|
+
|
|
215
|
+
`Note: queries_path is optional when enable_custom_operations is set to true`
|
|
216
|
+
|
|
217
|
+
```toml
|
|
218
|
+
[tool.ariadne-codegen]
|
|
219
|
+
schema_path = "schema.graphql"
|
|
220
|
+
include_comments = "none"
|
|
221
|
+
target_package_name = "example_client"
|
|
222
|
+
enable_custom_operations = true
|
|
223
|
+
```
|
|
159
224
|
|
|
160
225
|
|
|
161
226
|
## Plugins
|
|
@@ -171,16 +236,16 @@ Ariadne Codegen ships with optional plugins importable from the `ariadne_codegen
|
|
|
171
236
|
|
|
172
237
|
- [`ariadne_codegen.contrib.extract_operations.ExtractOperationsPlugin`](ariadne_codegen/contrib/extract_operations.py) - This extracts query strings from generated client's methods into separate `operations.py` module. It also modifies the generated client to import these definitions. Generated module name can be customized by adding `operations_module_name="custom_name"` to the `[tool.ariadne-codegen.operations]` section in config. Eg.:
|
|
173
238
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
[
|
|
178
|
-
|
|
179
|
-
|
|
239
|
+
```toml
|
|
240
|
+
[tool.ariadne-codegen]
|
|
241
|
+
...
|
|
242
|
+
plugins = ["ariadne_codegen.contrib.extract_operations.ExtractOperationsPlugin"]
|
|
243
|
+
|
|
244
|
+
[tool.ariadne-codegen.extract_operations]
|
|
245
|
+
operations_module_name = "custom_operations_module_name"
|
|
246
|
+
```
|
|
180
247
|
|
|
181
|
-
[
|
|
182
|
-
operations_module_name = "custom_operations_module_name"
|
|
183
|
-
```
|
|
248
|
+
- [`ariadne_codegen.contrib.client_forward_refs.ClientForwardRefsPlugin`](ariadne_codegen/contrib/client_forward_refs.py) - This plugin changes generated client module moving all Pydantic models imports under the `TYPE_CHECKING` condition, making them forward references. This greatly improves the import performance of the `client` module.
|
|
184
249
|
|
|
185
250
|
- [`ariadne_codegen.contrib.no_reimports.NoReimportsPlugin`](ariadne_codegen/contrib/no_reimports.py) - This plugin removes content of generated `__init__.py`. This is useful in scenarios where generated plugins contain so many Pydantic models that client's eager initialization of entire package on first import is very slow.
|
|
186
251
|
|
|
@@ -286,7 +351,7 @@ type = "datetime.datetime"
|
|
|
286
351
|
|
|
287
352
|
### Example with fully custom type
|
|
288
353
|
|
|
289
|
-
In this example scalar is represented as class `TypeB`. Pydantic can
|
|
354
|
+
In this example scalar is represented as class `TypeB`. Pydantic can't handle serialization and deserialization so custom `parse` and `serialize` is necessary. To provide `type`, `parse` and `serialize` implementation we can use `files_to_include` to copy `type_b.py` file.
|
|
290
355
|
|
|
291
356
|
```toml
|
|
292
357
|
[tool.ariadne-codegen]
|
|
@@ -53,7 +53,7 @@ queries_path = "queries.graphql"
|
|
|
53
53
|
|
|
54
54
|
Required settings:
|
|
55
55
|
|
|
56
|
-
- `queries_path` - path to file/directory with queries
|
|
56
|
+
- `queries_path` - path to file/directory with queries (Can be optional if `enable_custom_operations` is used)
|
|
57
57
|
|
|
58
58
|
One of the following 2 parameters is required, in case of providing both of them `schema_path` is prioritized:
|
|
59
59
|
|
|
@@ -81,6 +81,93 @@ Optional settings:
|
|
|
81
81
|
- `opentelemetry_client` (defaults to `false`) - default base clients don't support any performance tracing. Change this option to `true` to use the base client with Open Telemetry support.
|
|
82
82
|
- `files_to_include` (defaults to `[]`) - list of files which will be copied into generated package
|
|
83
83
|
- `plugins` (defaults to `[]`) - list of plugins to use during generation
|
|
84
|
+
- `enable_custom_operations` (defaults to `false`) - enables building custom operations. Generates additional files that contains all the classes and methods for generation.
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
## Custom operation builder
|
|
88
|
+
|
|
89
|
+
The custom operation builder allows you to create complex GraphQL queries in a structured and intuitive way.
|
|
90
|
+
|
|
91
|
+
### Example Code
|
|
92
|
+
|
|
93
|
+
```python
|
|
94
|
+
import asyncio
|
|
95
|
+
from graphql_client import Client
|
|
96
|
+
from graphql_client.custom_fields import (
|
|
97
|
+
ProductFields,
|
|
98
|
+
ProductTranslatableContentFields,
|
|
99
|
+
ProductTranslationFields,
|
|
100
|
+
TranslatableItemConnectionFields,
|
|
101
|
+
TranslatableItemEdgeFields,
|
|
102
|
+
)
|
|
103
|
+
from graphql_client.custom_queries import Query
|
|
104
|
+
from graphql_client.enums import LanguageCodeEnum, TranslatableKinds
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
async def get_products():
|
|
108
|
+
# Create a client instance with the specified URL and headers
|
|
109
|
+
client = Client(
|
|
110
|
+
url="https://saleor.cloud/graphql/",
|
|
111
|
+
headers={"authorization": "bearer ..."},
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
# Build the queries
|
|
115
|
+
product_query = Query.product(id="...", channel="channel-uk").fields(
|
|
116
|
+
ProductFields.id,
|
|
117
|
+
ProductFields.name,
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
translation_query = Query.translations(kind=TranslatableKinds.PRODUCT, first=10).fields(
|
|
121
|
+
TranslatableItemConnectionFields.edges().alias("aliased_edges").fields(
|
|
122
|
+
TranslatableItemEdgeFields.node.on(
|
|
123
|
+
"ProductTranslatableContent",
|
|
124
|
+
ProductTranslatableContentFields.id,
|
|
125
|
+
ProductTranslatableContentFields.product_id,
|
|
126
|
+
ProductTranslatableContentFields.name,
|
|
127
|
+
)
|
|
128
|
+
)
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
# Execute the queries with an operation name
|
|
132
|
+
response = await client.query(
|
|
133
|
+
product_query,
|
|
134
|
+
translation_query,
|
|
135
|
+
operation_name="get_products",
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
print(response)
|
|
139
|
+
|
|
140
|
+
# Run the async function
|
|
141
|
+
asyncio.run(get_products())
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### Explanation
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
1. Building the Product Query:
|
|
148
|
+
1. The Query.product(id="...", channel="channel-uk") initiates a query for a product with the specified ID and channel.
|
|
149
|
+
2. .fields(ProductFields.id, ProductFields.name) specifies the fields to retrieve for the product: id and name.
|
|
150
|
+
2. Building the Translation Query:
|
|
151
|
+
1. The Query.translations(kind=TranslatableKinds.PRODUCT, first=10) initiates a query for product translations.
|
|
152
|
+
2. .fields(...) specifies the fields to retrieve for the translations.
|
|
153
|
+
3. .alias("aliased_edges") renames the edges field to aliased_edges.
|
|
154
|
+
4. .on("ProductTranslatableContent", ...) specifies the fields to retrieve if the node is of type ProductTranslatableContent: id, product_id, and name.
|
|
155
|
+
3. Executing the Queries:
|
|
156
|
+
1. The client.query(...) method is called with the built queries and an operation name "get_products".
|
|
157
|
+
2. This method sends the queries to the server and retrieves the response.
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
### Example pyproject.toml configuration.
|
|
161
|
+
|
|
162
|
+
`Note: queries_path is optional when enable_custom_operations is set to true`
|
|
163
|
+
|
|
164
|
+
```toml
|
|
165
|
+
[tool.ariadne-codegen]
|
|
166
|
+
schema_path = "schema.graphql"
|
|
167
|
+
include_comments = "none"
|
|
168
|
+
target_package_name = "example_client"
|
|
169
|
+
enable_custom_operations = true
|
|
170
|
+
```
|
|
84
171
|
|
|
85
172
|
|
|
86
173
|
## Plugins
|
|
@@ -96,16 +183,16 @@ Ariadne Codegen ships with optional plugins importable from the `ariadne_codegen
|
|
|
96
183
|
|
|
97
184
|
- [`ariadne_codegen.contrib.extract_operations.ExtractOperationsPlugin`](ariadne_codegen/contrib/extract_operations.py) - This extracts query strings from generated client's methods into separate `operations.py` module. It also modifies the generated client to import these definitions. Generated module name can be customized by adding `operations_module_name="custom_name"` to the `[tool.ariadne-codegen.operations]` section in config. Eg.:
|
|
98
185
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
[
|
|
103
|
-
|
|
104
|
-
|
|
186
|
+
```toml
|
|
187
|
+
[tool.ariadne-codegen]
|
|
188
|
+
...
|
|
189
|
+
plugins = ["ariadne_codegen.contrib.extract_operations.ExtractOperationsPlugin"]
|
|
190
|
+
|
|
191
|
+
[tool.ariadne-codegen.extract_operations]
|
|
192
|
+
operations_module_name = "custom_operations_module_name"
|
|
193
|
+
```
|
|
105
194
|
|
|
106
|
-
[
|
|
107
|
-
operations_module_name = "custom_operations_module_name"
|
|
108
|
-
```
|
|
195
|
+
- [`ariadne_codegen.contrib.client_forward_refs.ClientForwardRefsPlugin`](ariadne_codegen/contrib/client_forward_refs.py) - This plugin changes generated client module moving all Pydantic models imports under the `TYPE_CHECKING` condition, making them forward references. This greatly improves the import performance of the `client` module.
|
|
109
196
|
|
|
110
197
|
- [`ariadne_codegen.contrib.no_reimports.NoReimportsPlugin`](ariadne_codegen/contrib/no_reimports.py) - This plugin removes content of generated `__init__.py`. This is useful in scenarios where generated plugins contain so many Pydantic models that client's eager initialization of entire package on first import is very slow.
|
|
111
198
|
|
|
@@ -211,7 +298,7 @@ type = "datetime.datetime"
|
|
|
211
298
|
|
|
212
299
|
### Example with fully custom type
|
|
213
300
|
|
|
214
|
-
In this example scalar is represented as class `TypeB`. Pydantic can
|
|
301
|
+
In this example scalar is represented as class `TypeB`. Pydantic can't handle serialization and deserialization so custom `parse` and `serialize` is necessary. To provide `type`, `parse` and `serialize` implementation we can use `files_to_include` to copy `type_b.py` file.
|
|
215
302
|
|
|
216
303
|
```toml
|
|
217
304
|
[tool.ariadne-codegen]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.15.0.dev1" # This is overwritten by Hatch in CI/CD, don't change it.
|
|
@@ -505,7 +505,28 @@ class ClientGenerator:
|
|
|
505
505
|
return_type=generate_name("DocumentNode"),
|
|
506
506
|
)
|
|
507
507
|
|
|
508
|
-
def create_execute_custom_operation_method(self):
|
|
508
|
+
def create_execute_custom_operation_method(self, async_client: bool):
|
|
509
|
+
execute_call = generate_call(
|
|
510
|
+
func=generate_attribute(value=generate_name("self"), attr="execute"),
|
|
511
|
+
args=[
|
|
512
|
+
generate_call(
|
|
513
|
+
func=generate_name("print_ast"),
|
|
514
|
+
args=[generate_name("operation_ast")],
|
|
515
|
+
)
|
|
516
|
+
],
|
|
517
|
+
keywords=[
|
|
518
|
+
generate_keyword(
|
|
519
|
+
arg="variables", value=generate_name('combined_variables["values"]')
|
|
520
|
+
),
|
|
521
|
+
generate_keyword(
|
|
522
|
+
arg="operation_name", value=generate_name("operation_name")
|
|
523
|
+
),
|
|
524
|
+
],
|
|
525
|
+
)
|
|
526
|
+
response_value = (
|
|
527
|
+
generate_await(value=execute_call) if async_client else execute_call
|
|
528
|
+
)
|
|
529
|
+
|
|
509
530
|
method_body = [
|
|
510
531
|
generate_assign(
|
|
511
532
|
targets=["selections"],
|
|
@@ -549,54 +570,31 @@ class ClientGenerator:
|
|
|
549
570
|
],
|
|
550
571
|
),
|
|
551
572
|
),
|
|
552
|
-
generate_assign(
|
|
553
|
-
targets=["response"],
|
|
554
|
-
value=generate_await(
|
|
555
|
-
value=generate_call(
|
|
556
|
-
func=generate_attribute(
|
|
557
|
-
value=generate_name("self"),
|
|
558
|
-
attr="execute",
|
|
559
|
-
),
|
|
560
|
-
args=[
|
|
561
|
-
generate_call(
|
|
562
|
-
func=generate_name("print_ast"),
|
|
563
|
-
args=[generate_name("operation_ast")],
|
|
564
|
-
)
|
|
565
|
-
],
|
|
566
|
-
keywords=[
|
|
567
|
-
generate_keyword(
|
|
568
|
-
arg="variables",
|
|
569
|
-
value=generate_name('combined_variables["values"]'),
|
|
570
|
-
),
|
|
571
|
-
generate_keyword(
|
|
572
|
-
arg="operation_name",
|
|
573
|
-
value=generate_name("operation_name"),
|
|
574
|
-
),
|
|
575
|
-
],
|
|
576
|
-
)
|
|
577
|
-
),
|
|
578
|
-
),
|
|
573
|
+
generate_assign(targets=["response"], value=response_value),
|
|
579
574
|
generate_return(
|
|
580
575
|
value=generate_call(
|
|
581
576
|
func=generate_attribute(
|
|
582
|
-
value=generate_name("self"),
|
|
583
|
-
attr="get_data",
|
|
577
|
+
value=generate_name("self"), attr="get_data"
|
|
584
578
|
),
|
|
585
579
|
args=[generate_name("response")],
|
|
586
580
|
)
|
|
587
581
|
),
|
|
588
582
|
]
|
|
589
|
-
|
|
583
|
+
|
|
584
|
+
method_definition = (
|
|
585
|
+
generate_async_method_definition
|
|
586
|
+
if async_client
|
|
587
|
+
else generate_method_definition
|
|
588
|
+
)
|
|
589
|
+
|
|
590
|
+
return method_definition(
|
|
590
591
|
name="execute_custom_operation",
|
|
591
592
|
arguments=generate_arguments(
|
|
592
593
|
args=[
|
|
593
594
|
generate_arg("self"),
|
|
594
595
|
generate_arg("*fields", annotation=generate_name("GraphQLField")),
|
|
595
596
|
generate_arg(
|
|
596
|
-
"operation_type",
|
|
597
|
-
annotation=generate_name(
|
|
598
|
-
"OperationType",
|
|
599
|
-
),
|
|
597
|
+
"operation_type", annotation=generate_name("OperationType")
|
|
600
598
|
),
|
|
601
599
|
generate_arg("operation_name", annotation=generate_name("str")),
|
|
602
600
|
]
|
|
@@ -655,7 +653,7 @@ class ClientGenerator:
|
|
|
655
653
|
),
|
|
656
654
|
)
|
|
657
655
|
|
|
658
|
-
def add_execute_custom_operation_method(self):
|
|
656
|
+
def add_execute_custom_operation_method(self, async_client: bool):
|
|
659
657
|
self._add_import(
|
|
660
658
|
generate_import_from(
|
|
661
659
|
[
|
|
@@ -679,13 +677,20 @@ class ClientGenerator:
|
|
|
679
677
|
)
|
|
680
678
|
self._add_import(generate_import_from([DICT, TUPLE, LIST, ANY], "typing"))
|
|
681
679
|
|
|
682
|
-
self._class_def.body.append(
|
|
680
|
+
self._class_def.body.append(
|
|
681
|
+
self.create_execute_custom_operation_method(async_client)
|
|
682
|
+
)
|
|
683
683
|
self._class_def.body.append(self.create_combine_variables_method())
|
|
684
684
|
self._class_def.body.append(self.create_build_variable_definitions_method())
|
|
685
685
|
self._class_def.body.append(self.create_build_operation_ast_method())
|
|
686
686
|
self._class_def.body.append(self.create_build_selection_set())
|
|
687
687
|
|
|
688
|
-
def create_custom_operation_method(
|
|
688
|
+
def create_custom_operation_method(
|
|
689
|
+
self,
|
|
690
|
+
name: str,
|
|
691
|
+
operation_type: str,
|
|
692
|
+
async_client: bool,
|
|
693
|
+
):
|
|
689
694
|
self._add_import(
|
|
690
695
|
generate_import_from(
|
|
691
696
|
[
|
|
@@ -694,6 +699,55 @@ class ClientGenerator:
|
|
|
694
699
|
GRAPHQL_MODULE,
|
|
695
700
|
)
|
|
696
701
|
)
|
|
702
|
+
if async_client:
|
|
703
|
+
def_query = self._create_async_operation_method(name, operation_type)
|
|
704
|
+
else:
|
|
705
|
+
def_query = self._create_sync_operation_method(name, operation_type)
|
|
706
|
+
self._class_def.body.append(def_query)
|
|
707
|
+
|
|
708
|
+
def _create_sync_operation_method(self, name: str, operation_type: str):
|
|
709
|
+
body_return = generate_return(
|
|
710
|
+
value=generate_call(
|
|
711
|
+
func=generate_attribute(
|
|
712
|
+
value=generate_name("self"),
|
|
713
|
+
attr="execute_custom_operation",
|
|
714
|
+
),
|
|
715
|
+
args=[
|
|
716
|
+
generate_name("*fields"),
|
|
717
|
+
],
|
|
718
|
+
keywords=[
|
|
719
|
+
generate_keyword(
|
|
720
|
+
arg="operation_type",
|
|
721
|
+
value=generate_attribute(
|
|
722
|
+
value=generate_name("OperationType"),
|
|
723
|
+
attr=operation_type,
|
|
724
|
+
),
|
|
725
|
+
),
|
|
726
|
+
generate_keyword(
|
|
727
|
+
arg="operation_name", value=generate_name("operation_name")
|
|
728
|
+
),
|
|
729
|
+
],
|
|
730
|
+
)
|
|
731
|
+
)
|
|
732
|
+
|
|
733
|
+
def_query = generate_method_definition(
|
|
734
|
+
name=name,
|
|
735
|
+
arguments=generate_arguments(
|
|
736
|
+
args=[
|
|
737
|
+
generate_arg("self"),
|
|
738
|
+
generate_arg("*fields", annotation=generate_name("GraphQLField")),
|
|
739
|
+
generate_arg("operation_name", annotation=generate_name("str")),
|
|
740
|
+
],
|
|
741
|
+
),
|
|
742
|
+
body=[body_return],
|
|
743
|
+
return_type=generate_subscript(
|
|
744
|
+
generate_name(DICT),
|
|
745
|
+
generate_tuple([generate_name("str"), generate_name("Any")]),
|
|
746
|
+
),
|
|
747
|
+
)
|
|
748
|
+
return def_query
|
|
749
|
+
|
|
750
|
+
def _create_async_operation_method(self, name: str, operation_type: str):
|
|
697
751
|
body_return = generate_return(
|
|
698
752
|
value=generate_await(
|
|
699
753
|
value=generate_call(
|
|
@@ -734,7 +788,7 @@ class ClientGenerator:
|
|
|
734
788
|
generate_tuple([generate_name("str"), generate_name("Any")]),
|
|
735
789
|
),
|
|
736
790
|
)
|
|
737
|
-
|
|
791
|
+
return async_def_query
|
|
738
792
|
|
|
739
793
|
def get_variable_names(self, arguments: ast.arguments) -> Dict[str, str]:
|
|
740
794
|
mapped_variable_names = [
|
|
@@ -840,7 +894,7 @@ class ClientGenerator:
|
|
|
840
894
|
value=generate_call(
|
|
841
895
|
func=generate_name(self._gql_func_name),
|
|
842
896
|
args=[
|
|
843
|
-
[generate_constant(l + "\n") for l in operation_str.splitlines()]
|
|
897
|
+
[generate_constant(l + "\n") for l in operation_str.splitlines()] # noqa: E741
|
|
844
898
|
],
|
|
845
899
|
),
|
|
846
900
|
lineno=lineno,
|
|
@@ -850,7 +904,7 @@ class ClientGenerator:
|
|
|
850
904
|
self, variable_names: Dict[str, str], arguments_dict: ast.Dict, lineno: int = 1
|
|
851
905
|
) -> ast.AnnAssign:
|
|
852
906
|
return generate_ann_assign(
|
|
853
|
-
target=variable_names[self._variables_dict_variable],
|
|
907
|
+
target=generate_name(variable_names[self._variables_dict_variable]),
|
|
854
908
|
annotation=generate_subscript(
|
|
855
909
|
generate_name(DICT),
|
|
856
910
|
generate_tuple([generate_name("str"), generate_name("object")]),
|
|
@@ -125,3 +125,9 @@ SCALARS_PARSE_DICT_NAME = "SCALARS_PARSE_FUNCTIONS"
|
|
|
125
125
|
SCALARS_SERIALIZE_DICT_NAME = "SCALARS_SERIALIZE_FUNCTIONS"
|
|
126
126
|
|
|
127
127
|
OPERATION_TYPES = ("Query", "Mutation", "Subscription")
|
|
128
|
+
|
|
129
|
+
GRAPHQL_OBJECT_SUFFIX = "Fields"
|
|
130
|
+
GRAPHQL_INTERFACE_SUFFIX = "Interface"
|
|
131
|
+
GRAPHQL_FIELD_SUFFIX = "GraphQLField"
|
|
132
|
+
GRAPHQL_UNION_SUFFIX = "Union"
|
|
133
|
+
GRAPHQL_BASE_FIELD_CLASS = "GraphQLField"
|