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.
Files changed (64) hide show
  1. {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/LICENSE +1 -1
  2. {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/PKG-INFO +117 -52
  3. {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/README.md +98 -11
  4. ariadne_codegen-0.15.0.dev1/ariadne_codegen/__about__.py +1 -0
  5. {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/client_generators/client.py +95 -41
  6. {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/client_generators/comments.py +0 -1
  7. {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/client_generators/constants.py +6 -0
  8. ariadne_codegen-0.15.0.dev1/ariadne_codegen/client_generators/custom_arguments.py +277 -0
  9. ariadne_codegen-0.15.0.dev1/ariadne_codegen/client_generators/custom_fields.py +389 -0
  10. ariadne_codegen-0.15.0.dev1/ariadne_codegen/client_generators/custom_fields_typing.py +155 -0
  11. ariadne_codegen-0.15.0.dev1/ariadne_codegen/client_generators/custom_operation.py +191 -0
  12. {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/client_generators/dependencies/async_base_client.py +5 -3
  13. {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
  14. {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/client_generators/dependencies/base_model.py +2 -1
  15. {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/client_generators/dependencies/base_operation.py +53 -15
  16. {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/client_generators/dependencies/exceptions.py +1 -1
  17. {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/client_generators/input_fields.py +25 -21
  18. {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/client_generators/input_types.py +2 -1
  19. {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/client_generators/package.py +9 -9
  20. {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/client_generators/result_fields.py +4 -3
  21. {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/client_generators/result_types.py +2 -1
  22. {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/codegen.py +61 -44
  23. {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/contrib/client_forward_refs.py +10 -9
  24. {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/contrib/extract_operations.py +4 -1
  25. {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/exceptions.py +1 -1
  26. {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/graphql_schema_generators/schema.py +48 -44
  27. {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/plugins/base.py +0 -14
  28. {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/plugins/manager.py +0 -1
  29. {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/schema.py +3 -3
  30. {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/settings.py +1 -1
  31. ariadne_codegen-0.15.0.dev1/pyproject.toml +179 -0
  32. ariadne_codegen-0.14.0.dev2/ariadne_codegen/client_generators/custom_fields.py +0 -400
  33. ariadne_codegen-0.14.0.dev2/ariadne_codegen/client_generators/custom_fields_typing.py +0 -112
  34. ariadne_codegen-0.14.0.dev2/ariadne_codegen/client_generators/custom_operation.py +0 -363
  35. ariadne_codegen-0.14.0.dev2/pyproject.toml +0 -84
  36. {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/.gitignore +0 -0
  37. {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/__init__.py +0 -0
  38. {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/__main__.py +0 -0
  39. {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/client_generators/__init__.py +0 -0
  40. {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/client_generators/arguments.py +0 -0
  41. /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
  42. {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/client_generators/dependencies/__init__.py +0 -0
  43. {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/client_generators/dependencies/base_client.py +0 -0
  44. {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/client_generators/dependencies/base_client_open_telemetry.py +0 -0
  45. {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/client_generators/enums.py +0 -0
  46. {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/client_generators/fragments.py +0 -0
  47. {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/client_generators/init_file.py +0 -0
  48. {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/client_generators/scalars.py +0 -0
  49. {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/client_generators/types.py +0 -0
  50. {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/config.py +0 -0
  51. {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/contrib/__init__.py +0 -0
  52. {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/contrib/no_reimports.py +0 -0
  53. {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/contrib/shorter_results.py +0 -0
  54. {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/graphql_schema_generators/__init__.py +0 -0
  55. {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/graphql_schema_generators/constants.py +0 -0
  56. {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/graphql_schema_generators/directives.py +0 -0
  57. {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/graphql_schema_generators/fields.py +0 -0
  58. {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/graphql_schema_generators/named_types.py +0 -0
  59. {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/graphql_schema_generators/utils.py +0 -0
  60. {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/main.py +0 -0
  61. {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/plugins/__init__.py +0 -0
  62. {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/plugins/explorer.py +0 -0
  63. {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/py.typed +0 -0
  64. {ariadne_codegen-0.14.0.dev2 → ariadne_codegen-0.15.0.dev1}/ariadne_codegen/utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  BSD 3-Clause License
2
2
 
3
- Copyright (c) 2023, Mirumee Labs
3
+ Copyright (c) 2025, Mirumee Labs
4
4
  All rights reserved.
5
5
 
6
6
  Redistribution and use in source and binary forms, with or without
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.3
1
+ Metadata-Version: 2.4
2
2
  Name: ariadne-codegen
3
- Version: 0.14.0.dev2
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 3-Clause License
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: ariadne; extra == 'dev'
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
  [![Ariadne](https://ariadnegraphql.org/img/logo-horizontal-sm.png)](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
- - [`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.
175
-
176
- ```toml
177
- [tool.ariadne-codegen]
178
- ...
179
- plugins = ["ariadne_codegen.contrib.extract_operations.ExtractOperationsPlugin"]
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
- [tool.ariadne-codegen.extract_operations]
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\`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.
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
- - [`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.
100
-
101
- ```toml
102
- [tool.ariadne-codegen]
103
- ...
104
- plugins = ["ariadne_codegen.contrib.extract_operations.ExtractOperationsPlugin"]
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
- [tool.ariadne-codegen.extract_operations]
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\`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.
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
- return generate_async_method_definition(
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(self.create_execute_custom_operation_method())
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(self, name, operation_type):
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
- self._class_def.body.append(async_def_query)
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")]),
@@ -11,7 +11,6 @@ from .constants import (
11
11
 
12
12
 
13
13
  def get_comment(strategy: CommentsStrategy, source: Optional[str] = None) -> str:
14
- # pylint: disable=unused-argument
15
14
  def empty_comment_function(source: Optional[str] = None) -> str:
16
15
  return ""
17
16
 
@@ -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"