Name | ariadne-codegen JSON |
Version |
0.14.0
JSON |
| download |
home_page | None |
Summary | Generate fully typed GraphQL client from schema, queries and mutations! |
upload_time | 2024-07-17 13:29:26 |
maintainer | None |
docs_url | None |
author | None |
requires_python | None |
license | BSD 3-Clause License Copyright (c) 2023, Mirumee Labs All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
keywords |
|
VCS |
 |
bugtrack_url |
|
requirements |
No requirements were recorded.
|
Travis-CI |
No Travis.
|
coveralls test coverage |
No coveralls.
|
[](https://ariadnegraphql.org)
[](https://github.com/mirumee/ariadne-codegen/actions)
- - - - -
# Ariadne Code Generator
Python code generator that takes graphql schema, queries, mutations and subscriptions and generates Python package with fully typed and asynchronous GraphQL client.
It's available as `ariadne-codegen` command and reads configuration from the `pyproject.toml` file:
```
$ ariadne-codegen
```
It can also be run as `python -m ariadne_codegen`.
## Features
- Generate pydantic models from schema types, inputs and enums.
- Generate pydantic models for GraphQL results.
- Generate client package with each GraphQL operation available as async method.
## Installation
Ariadne Code Generator can be installed with pip:
```
$ pip install ariadne-codegen
```
To support subscriptions, default base client requires `websockets` package:
```
$ pip install ariadne-codegen[subscriptions]
```
## Configuration
`ariadne-codegen` reads configuration from `[tool.ariadne-codegen]` section in your `pyproject.toml`. You can use other configuration file with `--config` option, eg. `ariadne-codegen --config custom_file.toml`
Minimal configuration for client generation:
```toml
[tool.ariadne-codegen]
schema_path = "schema.graphql"
queries_path = "queries.graphql"
```
Required settings:
- `queries_path` - path to file/directory with queries (Can be optional if `enable_custom_operations` is used)
One of the following 2 parameters is required, in case of providing both of them `schema_path` is prioritized:
- `schema_path` - path to file/directory with graphql schema
- `remote_schema_url` - url to graphql server, where introspection query can be perfomed
Optional settings:
- `remote_schema_headers` - extra headers that are passed along with introspection query, eg. `{"Authorization" = "Bearer: token"}`. To include an environment variable in a header value, prefix the variable with `$`, eg. `{"Authorization" = "$AUTH_TOKEN"}`
- `remote_schema_verify_ssl` (defaults to `true`) - a flag that specifies wheter to verify ssl while introspecting remote schema
- `target_package_name` (defaults to `"graphql_client"`) - name of generated package
- `target_package_path` (defaults to cwd) - path where to generate package
- `client_name` (defaults to `"Client"`) - name of generated client class
- `client_file_name` (defaults to `"client"`) - name of file with generated client class
- `base_client_name` (defaults to `"AsyncBaseClient"`) - name of base client class
- `base_client_file_path` (defaults to `.../ariadne_codegen/client_generators/dependencies/async_base_client.py`) - path to file where `base_client_name` is defined
- `enums_module_name` (defaults to `"enums"`) - name of file with generated enums models
- `input_types_module_name` (defaults to `"input_types"`) - name of file with generated input types models
- `fragments_module_name` (defaults to `"fragments"`) - name of file with generated fragments models
- `include_comments` (defaults to `"stable"`) - option which sets content of comments included at the top of every generated file. Valid choices are: `"none"` (no comments), `"timestamp"` (comment with generation timestamp), `"stable"` (comment contains a message that this is a generated file)
- `convert_to_snake_case` (defaults to `true`) - a flag that specifies whether to convert fields and arguments names to snake case
- `include_all_inputs` (defaults to `true`) - a flag specifying whether to include all inputs defined in the schema, or only those used in supplied operations
- `include_all_enums` (defaults to `true`) - a flag specifying whether to include all enums defined in the schema, or only those used in supplied operations
- `async_client` (defaults to `true`) - default generated client is `async`, change this to option `false` to generate synchronous client instead
- `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.
- `files_to_include` (defaults to `[]`) - list of files which will be copied into generated package
- `plugins` (defaults to `[]`) - list of plugins to use during generation
- `enable_custom_operations` (defaults to `false`) - enables building custom operations. Generates additional files that contains all the classes and methods for generation.
## Custom operation builder
The custom operation builder allows you to create complex GraphQL queries in a structured and intuitive way.
### Example Code
```python
import asyncio
from graphql_client import Client
from graphql_client.custom_fields import (
ProductFields,
ProductTranslatableContentFields,
ProductTranslationFields,
TranslatableItemConnectionFields,
TranslatableItemEdgeFields,
)
from graphql_client.custom_queries import Query
from graphql_client.enums import LanguageCodeEnum, TranslatableKinds
async def get_products():
# Create a client instance with the specified URL and headers
client = Client(
url="https://saleor.cloud/graphql/",
headers={"authorization": "bearer ..."},
)
# Build the queries
product_query = Query.product(id="...", channel="channel-uk").fields(
ProductFields.id,
ProductFields.name,
)
translation_query = Query.translations(kind=TranslatableKinds.PRODUCT, first=10).fields(
TranslatableItemConnectionFields.edges().alias("aliased_edges").fields(
TranslatableItemEdgeFields.node.on(
"ProductTranslatableContent",
ProductTranslatableContentFields.id,
ProductTranslatableContentFields.product_id,
ProductTranslatableContentFields.name,
)
)
)
# Execute the queries with an operation name
response = await client.query(
product_query,
translation_query,
operation_name="get_products",
)
print(response)
# Run the async function
asyncio.run(get_products())
```
### Explanation
1. Building the Product Query:
1. The Query.product(id="...", channel="channel-uk") initiates a query for a product with the specified ID and channel.
2. .fields(ProductFields.id, ProductFields.name) specifies the fields to retrieve for the product: id and name.
2. Building the Translation Query:
1. The Query.translations(kind=TranslatableKinds.PRODUCT, first=10) initiates a query for product translations.
2. .fields(...) specifies the fields to retrieve for the translations.
3. .alias("aliased_edges") renames the edges field to aliased_edges.
4. .on("ProductTranslatableContent", ...) specifies the fields to retrieve if the node is of type ProductTranslatableContent: id, product_id, and name.
3. Executing the Queries:
1. The client.query(...) method is called with the built queries and an operation name "get_products".
2. This method sends the queries to the server and retrieves the response.
### Example pyproject.toml configuration.
`Note: queries_path is optional when enable_custom_operations is set to true`
```toml
[tool.ariadne-codegen]
schema_path = "schema.graphql"
include_comments = "none"
target_package_name = "example_client"
enable_custom_operations = true
```
## Plugins
Ariadne Codegen implements a plugin system that enables further customization and fine-tuning of generated Python code. It’s documentation is available separately in the [PLUGINS.md](https://github.com/mirumee/ariadne-codegen/blob/main/PLUGINS.md) file.
### Standard plugins
Ariadne Codegen ships with optional plugins importable from the `ariadne_codegen.contrib` package:
- [`ariadne_codegen.contrib.shorter_results.ShorterResultsPlugin`](ariadne_codegen/contrib/shorter_results.py) - This plugin processes generated client methods for operations where only single top field is requested, so they return this field's value directly instead of operation's result type. For example get_user method generated for query `GetUser() { user(...) { ... }}` will return value of user field directly instead of `GetUserResult`.
- [`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.:
```toml
[tool.ariadne-codegen]
...
plugins = ["ariadne_codegen.contrib.extract_operations.ExtractOperationsPlugin"]
[tool.ariadne-codegen.extract_operations]
operations_module_name = "custom_operations_module_name"
```
- [`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.
- [`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.
## Using generated client
Generated client can be imported from package:
```py
from {target_package_name}.{client_file_name} import {client_name}
```
Example with default settings:
```py
from graphql_client.client import Client
```
### Passing headers to client
Client (with default base client), takes passed headers and attaches them to every sent request.
```py
client = Client("https://example.com/graphql", {"Authorization": "Bearer token"})
```
For more complex scenarios, you can pass your own http client:
```py
client = Client(http_client=CustomComplexHttpClient())
```
`CustomComplexHttpClient` needs to be an instance of `httpx.AsyncClient` for async client, or `httpx.Client` for sync.
### Websockets
To handle subscriptions, default `AsyncBaseClient` uses [websockets](https://github.com/python-websockets/websockets) and implements [graphql-transport-ws](https://github.com/enisdenjo/graphql-ws/blob/master/PROTOCOL.md) subprotocol. Arguments `ws_origin` and `ws_headers` are added as headers to the handshake request and `ws_connection_init_payload` is used as payload of [ConnectionInit](https://github.com/enisdenjo/graphql-ws/blob/master/PROTOCOL.md#connectioninit) message.
### File upload
Default base client (`AsyncBaseClient` or `BaseClient`) checks if any part of `variables` dictionary is an instance of `Upload`. If at least one instance is found then client sends multipart request according to [GraphQL multipart request specification](https://github.com/jaydenseric/graphql-multipart-request-spec).
Class `Upload` is included in generated client and can be imported from it:
```py
from {target_package_name} import Upload
```
By default we use this class to represent graphql scalar `Upload`. For schema with different name for this scalar, you can still use `Upload` and default client for file uploads:
```toml
[tool.ariadne-codegen.scalars.OTHERSCALAR]
type = "Upload"
```
### Open Telemetry
When config option `opentelemetry_client` is set to `true` then default, included base client is replaced with one that implements the opt-in Open Telemetry support. By default this support does nothing but when the `opentelemetry-api` package is installed and the `tracer` argument is provided then the client will create spans with data about performed requests.
Tracing arguments handled by `BaseClientOpenTelemetry`:
- `tracer`: `Optional[Union[str, Tracer]] = None` - tracer object or name which will be passed to the `get_tracer` method
- `root_context`: `Optional[Context] = None` - optional context added to root span
- `root_span_name`: `str = "GraphQL Operation"` - name of root span
`AsyncBaseClientOpenTelemetry` supports all arguments which `BaseClientOpenTelemetry` does, but also exposes additional arguments regarding websockets:
- `ws_root_context`: `Optional[Context] = None` - optional context added to root span for websocket connection
- `ws_root_span_name`: `str = "GraphQL Subscription"` - name of root span for websocket connection
## Custom scalars
By default, not built-in scalars are represented as `typing.Any` in generated client.
You can provide information about specific scalar by adding section to `pyproject.toml`:
```toml
[tool.ariadne-codegen.scalars.{graphql scalar name}]
type = "(required) python type name"
serialize = "function used to serialize scalar"
parse = "function used to create scalar instance from serialized form"
```
For each custom scalar client will use given `type` in all occurrences of `{graphql scalar name}`. If provided, `serialize` and `parse` will be used for serialization and deserialization. In result models `type` will be annotated with `BeforeValidator`, eg. `Annotated[type, BeforeValidator(parse)]`. In inputs annotation will use `PlainSerializer`, eg. `Annotated[type, PlainSerializer(serialize)]`.
If `type`/`serialize`/`parse` contains at least one `.` then string will be split by it's last occurrence. First part will be used as module to import from, and second part as type/method name. For example, `type = "custom_scalars.a.ScalarA"` will produce `from custom_scalars.a import ScalarA`.
### Example with scalar mapped to built-in type
In this case scalar is mapped to built-in `str` which doesn't require custom `serialize ` and `parse` methods.
```toml
[tool.ariadne-codegen.scalars.SCALARA]
type = "str"
```
### Example with type supported by pydantic
In this scenario scalar is represented as `datetime`, so it needs to be imported. Pydantic handles serialization and deserialization so custom `parse` and `serialize` is not necessary.
```toml
[tool.ariadne-codegen.scalars.DATETIME]
type = "datetime.datetime"
```
### Example with fully custom type
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.
```toml
[tool.ariadne-codegen]
...
files_to_include = [".../type_b.py"]
[tool.ariadne-codegen.scalars.SCALARB]
type = ".type_b.TypeB"
parse = ".type_b.parse_b"
serialize = ".type_b.serialize_b"
```
```py
# inputs.py
class TestInput(BaseModel):
value_b: Annotated[TypeB, PlainSerializer(serialize_b)]
```
```py
# get_b.py
class GetB(BaseModel):
query_b: Annotated[TypeB, BeforeValidator(parse_b)]
```
```py
# client.py
class Client(AsyncBaseClient):
async def test_mutation(self, value: TypeB) -> TestMutation:
...
variables: Dict[str, object] = {
"value": serialize_b(value),
}
...
```
## Extending generated types
### Extending models with custom mixins
`mixin` directive allows to extend class generated for query/mutation field with custom logic.
`mixin` takes two required arguments:
- `from` - name of a module to import from
- `import` - name of a parent class
Generated class will use `import` as extra base class, and import will be added to the file.
```py
from {from} import {import}
...
class OperationNameField(BaseModel, {import}):
...
```
This directive can be used along with `files_to_include` option to extend functionality of generated classes.
#### Example of usage of `mixin` and `files_to_include`:
Query with `mixin` directive:
```gql
query listUsers {
users @mixin(from: ".mixins", import: "UsersMixin") {
id
}
}
```
Part of `pyproject.toml` with `files_to_include` (`mixins.py` contains `UsersMixin` implementation)
```toml
files_to_include = [".../mixins.py"]
```
Part of generated `list_users.py` file:
```py
...
from .mixins import UsersMixin
...
class ListUsersUsers(BaseModel, UsersMixin):
...
```
## Multiple clients
To generate multiple different clients you can store config for each in different file, then provide path to config file by `--config` option, eg.
```
ariadne-codegen --config clientA.toml
ariadne-codegen --config clientB.toml
```
## Generated code dependencies
Generated code requires:
- [pydantic](https://github.com/pydantic/pydantic)
- [httpx](https://github.com/encode/httpx)
- [websockets](https://github.com/python-websockets/websockets) (only for default async base client)
Both `httpx` and `websockets` dependencies can be avoided by providing another base client class with `base_client_file_path` and `base_client_name` options.
## Example
Example with simple schema and few queries and mutations is available [here](https://github.com/mirumee/ariadne-codegen/blob/main/EXAMPLE.md).
## Generating a copy of GraphSQL schema
Instead of generating a client, you can generate a file with a copy of a GraphQL schema. To do this call `ariadne-codegen` with `graphqlschema` argument:
```
ariadne-codegen graphqlschema
```
`graphqlschema` mode reads configuration from the same place as [`client`](#configuration) but uses only `schema_path`, `remote_schema_url`, `remote_schema_headers`, `remote_schema_verify_ssl` options to retrieve the schema and `plugins` option to load plugins.
In addition to the above, `graphqlschema` mode also accepts additional settings specific to it:
### `target_file_path`
A string with destination path for generated file. Must be either a Python (`.py`), or GraphQL (`.graphql` or `.gql`) file.
Defaults to `schema.py`.
Generated Python file will contain:
- Necessary imports
- Type map declaration `{type_map_variable_name}: TypeMap = {...}`
- Schema declaration `{schema_variable_name}: GraphQLSchema = GraphQLSchema(...)`
Generated GraphQL file will contain a formatted output of the `print_schema` function from the `graphql-core` package.
### `schema_variable_name`
A string with a name for schema variable, must be valid python identifier.
Defaults to `"schema"`. Used only if target is a Python file.
### `type_map_variable_name`
A string with a name for type map variable, must be valid python identifier.
Defaults to `"type_map"`. Used only if target is a Python file.
## Contributing
We welcome all contributions to Ariadne! If you've found a bug or issue, feel free to use [GitHub issues](https://github.com/mirumee/ariadne-codegen/issues). If you have any questions or feedback, don't hesitate to catch us on [GitHub discussions](https://github.com/mirumee/ariadne/discussions/).
For guidance and instructions, please see [CONTRIBUTING.md](CONTRIBUTING.md).
Also make sure you follow [@AriadneGraphQL](https://twitter.com/AriadneGraphQL) on Twitter for latest updates, news and random musings!
## **Crafted with ❤️ by [Mirumee Software](http://mirumee.com)** hello@mirumee.com
Raw data
{
"_id": null,
"home_page": null,
"name": "ariadne-codegen",
"maintainer": null,
"docs_url": null,
"requires_python": null,
"maintainer_email": null,
"keywords": null,
"author": null,
"author_email": "Mirumee Software <hello@mirumee.com>",
"download_url": "https://files.pythonhosted.org/packages/f4/96/4f389335fd40db4ee685f594835181fec2692f8b362c51a6606e42bc904d/ariadne_codegen-0.14.0.tar.gz",
"platform": null,
"description": "[](https://ariadnegraphql.org)\n\n[](https://github.com/mirumee/ariadne-codegen/actions)\n\n- - - - -\n\n# Ariadne Code Generator\n\nPython code generator that takes graphql schema, queries, mutations and subscriptions and generates Python package with fully typed and asynchronous GraphQL client.\n\nIt's available as `ariadne-codegen` command and reads configuration from the `pyproject.toml` file:\n\n```\n$ ariadne-codegen\n```\n\nIt can also be run as `python -m ariadne_codegen`.\n\n\n## Features\n\n- Generate pydantic models from schema types, inputs and enums.\n- Generate pydantic models for GraphQL results.\n- Generate client package with each GraphQL operation available as async method.\n\n\n## Installation\n\nAriadne Code Generator can be installed with pip:\n\n```\n$ pip install ariadne-codegen\n```\n\nTo support subscriptions, default base client requires `websockets` package:\n\n```\n$ pip install ariadne-codegen[subscriptions]\n```\n\n\n## Configuration\n\n`ariadne-codegen` reads configuration from `[tool.ariadne-codegen]` section in your `pyproject.toml`. You can use other configuration file with `--config` option, eg. `ariadne-codegen --config custom_file.toml`\n\nMinimal configuration for client generation:\n\n```toml\n[tool.ariadne-codegen]\nschema_path = \"schema.graphql\"\nqueries_path = \"queries.graphql\"\n```\n\nRequired settings:\n\n- `queries_path` - path to file/directory with queries (Can be optional if `enable_custom_operations` is used)\n\nOne of the following 2 parameters is required, in case of providing both of them `schema_path` is prioritized:\n\n- `schema_path` - path to file/directory with graphql schema\n- `remote_schema_url` - url to graphql server, where introspection query can be perfomed\n\nOptional settings:\n\n- `remote_schema_headers` - extra headers that are passed along with introspection query, eg. `{\"Authorization\" = \"Bearer: token\"}`. To include an environment variable in a header value, prefix the variable with `$`, eg. `{\"Authorization\" = \"$AUTH_TOKEN\"}`\n- `remote_schema_verify_ssl` (defaults to `true`) - a flag that specifies wheter to verify ssl while introspecting remote schema\n- `target_package_name` (defaults to `\"graphql_client\"`) - name of generated package\n- `target_package_path` (defaults to cwd) - path where to generate package\n- `client_name` (defaults to `\"Client\"`) - name of generated client class\n- `client_file_name` (defaults to `\"client\"`) - name of file with generated client class\n- `base_client_name` (defaults to `\"AsyncBaseClient\"`) - name of base client class\n- `base_client_file_path` (defaults to `.../ariadne_codegen/client_generators/dependencies/async_base_client.py`) - path to file where `base_client_name` is defined\n- `enums_module_name` (defaults to `\"enums\"`) - name of file with generated enums models\n- `input_types_module_name` (defaults to `\"input_types\"`) - name of file with generated input types models\n- `fragments_module_name` (defaults to `\"fragments\"`) - name of file with generated fragments models\n- `include_comments` (defaults to `\"stable\"`) - option which sets content of comments included at the top of every generated file. Valid choices are: `\"none\"` (no comments), `\"timestamp\"` (comment with generation timestamp), `\"stable\"` (comment contains a message that this is a generated file)\n- `convert_to_snake_case` (defaults to `true`) - a flag that specifies whether to convert fields and arguments names to snake case\n- `include_all_inputs` (defaults to `true`) - a flag specifying whether to include all inputs defined in the schema, or only those used in supplied operations\n- `include_all_enums` (defaults to `true`) - a flag specifying whether to include all enums defined in the schema, or only those used in supplied operations\n- `async_client` (defaults to `true`) - default generated client is `async`, change this to option `false` to generate synchronous client instead\n- `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.\n- `files_to_include` (defaults to `[]`) - list of files which will be copied into generated package\n- `plugins` (defaults to `[]`) - list of plugins to use during generation\n- `enable_custom_operations` (defaults to `false`) - enables building custom operations. Generates additional files that contains all the classes and methods for generation.\n\n\n## Custom operation builder\n\nThe custom operation builder allows you to create complex GraphQL queries in a structured and intuitive way. \n\n### Example Code\n\n```python\nimport asyncio\nfrom graphql_client import Client\nfrom graphql_client.custom_fields import (\n ProductFields,\n ProductTranslatableContentFields,\n ProductTranslationFields,\n TranslatableItemConnectionFields,\n TranslatableItemEdgeFields,\n)\nfrom graphql_client.custom_queries import Query\nfrom graphql_client.enums import LanguageCodeEnum, TranslatableKinds\n\n\nasync def get_products():\n # Create a client instance with the specified URL and headers\n client = Client(\n url=\"https://saleor.cloud/graphql/\",\n headers={\"authorization\": \"bearer ...\"},\n )\n\n # Build the queries\n product_query = Query.product(id=\"...\", channel=\"channel-uk\").fields(\n ProductFields.id,\n ProductFields.name,\n )\n\n translation_query = Query.translations(kind=TranslatableKinds.PRODUCT, first=10).fields(\n TranslatableItemConnectionFields.edges().alias(\"aliased_edges\").fields(\n TranslatableItemEdgeFields.node.on(\n \"ProductTranslatableContent\",\n ProductTranslatableContentFields.id,\n ProductTranslatableContentFields.product_id,\n ProductTranslatableContentFields.name,\n )\n )\n )\n\n # Execute the queries with an operation name\n response = await client.query(\n product_query,\n translation_query,\n operation_name=\"get_products\",\n )\n\n print(response)\n\n# Run the async function\nasyncio.run(get_products())\n```\n\n### Explanation\n\n\n1. Building the Product Query:\n 1. The Query.product(id=\"...\", channel=\"channel-uk\") initiates a query for a product with the specified ID and channel.\n 2. .fields(ProductFields.id, ProductFields.name) specifies the fields to retrieve for the product: id and name.\n2. Building the Translation Query:\n 1. The Query.translations(kind=TranslatableKinds.PRODUCT, first=10) initiates a query for product translations.\n 2. .fields(...) specifies the fields to retrieve for the translations.\n 3. .alias(\"aliased_edges\") renames the edges field to aliased_edges.\n 4. .on(\"ProductTranslatableContent\", ...) specifies the fields to retrieve if the node is of type ProductTranslatableContent: id, product_id, and name.\n3. Executing the Queries:\n 1. The client.query(...) method is called with the built queries and an operation name \"get_products\". \n 2. This method sends the queries to the server and retrieves the response.\n\n\n### Example pyproject.toml configuration. \n\n`Note: queries_path is optional when enable_custom_operations is set to true`\n\n```toml\n[tool.ariadne-codegen]\nschema_path = \"schema.graphql\"\ninclude_comments = \"none\"\ntarget_package_name = \"example_client\"\nenable_custom_operations = true\n```\n\n\n## Plugins\n\nAriadne Codegen implements a plugin system that enables further customization and fine-tuning of generated Python code. It\u2019s documentation is available separately in the [PLUGINS.md](https://github.com/mirumee/ariadne-codegen/blob/main/PLUGINS.md) file.\n\n\n### Standard plugins\n\nAriadne Codegen ships with optional plugins importable from the `ariadne_codegen.contrib` package:\n\n- [`ariadne_codegen.contrib.shorter_results.ShorterResultsPlugin`](ariadne_codegen/contrib/shorter_results.py) - This plugin processes generated client methods for operations where only single top field is requested, so they return this field's value directly instead of operation's result type. For example get_user method generated for query `GetUser() { user(...) { ... }}` will return value of user field directly instead of `GetUserResult`.\n\n- [`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.:\n\n ```toml\n [tool.ariadne-codegen]\n ...\n plugins = [\"ariadne_codegen.contrib.extract_operations.ExtractOperationsPlugin\"]\n \n [tool.ariadne-codegen.extract_operations]\n operations_module_name = \"custom_operations_module_name\"\n ```\n\n- [`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.\n\n- [`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.\n\n\n## Using generated client\n\nGenerated client can be imported from package:\n```py\nfrom {target_package_name}.{client_file_name} import {client_name}\n```\n\nExample with default settings:\n```py\nfrom graphql_client.client import Client\n```\n\n### Passing headers to client\n\nClient (with default base client), takes passed headers and attaches them to every sent request.\n```py\nclient = Client(\"https://example.com/graphql\", {\"Authorization\": \"Bearer token\"})\n```\n\nFor more complex scenarios, you can pass your own http client:\n```py\nclient = Client(http_client=CustomComplexHttpClient())\n```\n\n`CustomComplexHttpClient` needs to be an instance of `httpx.AsyncClient` for async client, or `httpx.Client` for sync.\n\n\n### Websockets\n\nTo handle subscriptions, default `AsyncBaseClient` uses [websockets](https://github.com/python-websockets/websockets) and implements [graphql-transport-ws](https://github.com/enisdenjo/graphql-ws/blob/master/PROTOCOL.md) subprotocol. Arguments `ws_origin` and `ws_headers` are added as headers to the handshake request and `ws_connection_init_payload` is used as payload of [ConnectionInit](https://github.com/enisdenjo/graphql-ws/blob/master/PROTOCOL.md#connectioninit) message.\n\n\n### File upload\n\nDefault base client (`AsyncBaseClient` or `BaseClient`) checks if any part of `variables` dictionary is an instance of `Upload`. If at least one instance is found then client sends multipart request according to [GraphQL multipart request specification](https://github.com/jaydenseric/graphql-multipart-request-spec).\n\nClass `Upload` is included in generated client and can be imported from it: \n\n```py\nfrom {target_package_name} import Upload\n```\n\nBy default we use this class to represent graphql scalar `Upload`. For schema with different name for this scalar, you can still use `Upload` and default client for file uploads:\n\n```toml\n[tool.ariadne-codegen.scalars.OTHERSCALAR]\ntype = \"Upload\"\n```\n\n\n### Open Telemetry\n\nWhen config option `opentelemetry_client` is set to `true` then default, included base client is replaced with one that implements the opt-in Open Telemetry support. By default this support does nothing but when the `opentelemetry-api` package is installed and the `tracer` argument is provided then the client will create spans with data about performed requests.\n\nTracing arguments handled by `BaseClientOpenTelemetry`:\n- `tracer`: `Optional[Union[str, Tracer]] = None` - tracer object or name which will be passed to the `get_tracer` method\n- `root_context`: `Optional[Context] = None` - optional context added to root span\n- `root_span_name`: `str = \"GraphQL Operation\"` - name of root span\n\n`AsyncBaseClientOpenTelemetry` supports all arguments which `BaseClientOpenTelemetry` does, but also exposes additional arguments regarding websockets:\n- `ws_root_context`: `Optional[Context] = None` - optional context added to root span for websocket connection\n- `ws_root_span_name`: `str = \"GraphQL Subscription\"` - name of root span for websocket connection\n\n\n## Custom scalars\n\nBy default, not built-in scalars are represented as `typing.Any` in generated client.\nYou can provide information about specific scalar by adding section to `pyproject.toml`:\n\n```toml\n[tool.ariadne-codegen.scalars.{graphql scalar name}]\ntype = \"(required) python type name\"\nserialize = \"function used to serialize scalar\"\nparse = \"function used to create scalar instance from serialized form\"\n```\n\nFor each custom scalar client will use given `type` in all occurrences of `{graphql scalar name}`. If provided, `serialize` and `parse` will be used for serialization and deserialization. In result models `type` will be annotated with `BeforeValidator`, eg. `Annotated[type, BeforeValidator(parse)]`. In inputs annotation will use `PlainSerializer`, eg. `Annotated[type, PlainSerializer(serialize)]`.\nIf `type`/`serialize`/`parse` contains at least one `.` then string will be split by it's last occurrence. First part will be used as module to import from, and second part as type/method name. For example, `type = \"custom_scalars.a.ScalarA\"` will produce `from custom_scalars.a import ScalarA`.\n\n\n### Example with scalar mapped to built-in type\n\nIn this case scalar is mapped to built-in `str` which doesn't require custom `serialize ` and `parse` methods.\n\n```toml\n[tool.ariadne-codegen.scalars.SCALARA]\ntype = \"str\"\n```\n\n\n### Example with type supported by pydantic\n\nIn this scenario scalar is represented as `datetime`, so it needs to be imported. Pydantic handles serialization and deserialization so custom `parse` and `serialize` is not necessary.\n\n```toml\n[tool.ariadne-codegen.scalars.DATETIME]\ntype = \"datetime.datetime\"\n```\n\n### Example with fully custom type\n\nIn 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.\n\n```toml\n[tool.ariadne-codegen]\n...\nfiles_to_include = [\".../type_b.py\"]\n\n[tool.ariadne-codegen.scalars.SCALARB]\ntype = \".type_b.TypeB\"\nparse = \".type_b.parse_b\"\nserialize = \".type_b.serialize_b\"\n```\n\n```py\n# inputs.py\n\nclass TestInput(BaseModel):\n value_b: Annotated[TypeB, PlainSerializer(serialize_b)]\n```\n\n```py\n# get_b.py\n\nclass GetB(BaseModel):\n query_b: Annotated[TypeB, BeforeValidator(parse_b)]\n```\n\n```py\n# client.py\n\nclass Client(AsyncBaseClient):\n async def test_mutation(self, value: TypeB) -> TestMutation:\n ...\n variables: Dict[str, object] = {\n \"value\": serialize_b(value),\n }\n ...\n```\n\n\n## Extending generated types\n\n### Extending models with custom mixins\n\n`mixin` directive allows to extend class generated for query/mutation field with custom logic.\n`mixin` takes two required arguments:\n- `from` - name of a module to import from\n- `import` - name of a parent class\n\nGenerated class will use `import` as extra base class, and import will be added to the file.\n```py\nfrom {from} import {import}\n...\nclass OperationNameField(BaseModel, {import}):\n ...\n```\n\nThis directive can be used along with `files_to_include` option to extend functionality of generated classes.\n\n\n#### Example of usage of `mixin` and `files_to_include`:\n\nQuery with `mixin` directive:\n\n```gql\nquery listUsers {\n users @mixin(from: \".mixins\", import: \"UsersMixin\") {\n id\n }\n}\n```\n\nPart of `pyproject.toml` with `files_to_include` (`mixins.py` contains `UsersMixin` implementation)\n```toml\nfiles_to_include = [\".../mixins.py\"]\n```\n\nPart of generated `list_users.py` file:\n```py\n...\nfrom .mixins import UsersMixin\n...\nclass ListUsersUsers(BaseModel, UsersMixin):\n ...\n```\n\n\n## Multiple clients\n\nTo generate multiple different clients you can store config for each in different file, then provide path to config file by `--config` option, eg.\n```\nariadne-codegen --config clientA.toml\nariadne-codegen --config clientB.toml\n```\n\n\n## Generated code dependencies\n\nGenerated code requires:\n\n- [pydantic](https://github.com/pydantic/pydantic)\n- [httpx](https://github.com/encode/httpx)\n- [websockets](https://github.com/python-websockets/websockets) (only for default async base client)\n\nBoth `httpx` and `websockets` dependencies can be avoided by providing another base client class with `base_client_file_path` and `base_client_name` options.\n\n\n## Example\n\nExample with simple schema and few queries and mutations is available [here](https://github.com/mirumee/ariadne-codegen/blob/main/EXAMPLE.md).\n\n\n## Generating a copy of GraphSQL schema\n\nInstead of generating a client, you can generate a file with a copy of a GraphQL schema. To do this call `ariadne-codegen` with `graphqlschema` argument:\n\n```\nariadne-codegen graphqlschema\n```\n\n`graphqlschema` mode reads configuration from the same place as [`client`](#configuration) but uses only `schema_path`, `remote_schema_url`, `remote_schema_headers`, `remote_schema_verify_ssl` options to retrieve the schema and `plugins` option to load plugins.\n\nIn addition to the above, `graphqlschema` mode also accepts additional settings specific to it:\n\n\n### `target_file_path`\n\nA string with destination path for generated file. Must be either a Python (`.py`), or GraphQL (`.graphql` or `.gql`) file.\n\nDefaults to `schema.py`.\n\nGenerated Python file will contain:\n\n- Necessary imports\n- Type map declaration `{type_map_variable_name}: TypeMap = {...}`\n- Schema declaration `{schema_variable_name}: GraphQLSchema = GraphQLSchema(...)`\n\nGenerated GraphQL file will contain a formatted output of the `print_schema` function from the `graphql-core` package.\n\n\n### `schema_variable_name`\n\nA string with a name for schema variable, must be valid python identifier.\n\nDefaults to `\"schema\"`. Used only if target is a Python file.\n\n\n### `type_map_variable_name`\n\nA string with a name for type map variable, must be valid python identifier.\n\nDefaults to `\"type_map\"`. Used only if target is a Python file.\n\n\n## Contributing\n\nWe welcome all contributions to Ariadne! If you've found a bug or issue, feel free to use [GitHub issues](https://github.com/mirumee/ariadne-codegen/issues). If you have any questions or feedback, don't hesitate to catch us on [GitHub discussions](https://github.com/mirumee/ariadne/discussions/).\n\nFor guidance and instructions, please see [CONTRIBUTING.md](CONTRIBUTING.md).\n\nAlso make sure you follow [@AriadneGraphQL](https://twitter.com/AriadneGraphQL) on Twitter for latest updates, news and random musings!\n\n\n## **Crafted with \u2764\ufe0f by [Mirumee Software](http://mirumee.com)** hello@mirumee.com\n",
"bugtrack_url": null,
"license": "BSD 3-Clause License Copyright (c) 2023, Mirumee Labs All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.",
"summary": "Generate fully typed GraphQL client from schema, queries and mutations!",
"version": "0.14.0",
"project_urls": {
"Bug Tracker": "https://github.com/mirumee/ariadne-codegen/issues",
"Community": "https://github.com/mirumee/ariadne/discussions",
"Homepage": "https://ariadnegraphql.org/",
"Repository": "https://github.com/mirumee/ariadne-codegen",
"Twitter": "https://twitter.com/AriadneGraphQL"
},
"split_keywords": [],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "a9b02643c64d50df13ea2cc43ae4133292cad62ea6f95b7c377288592b385c4c",
"md5": "13d9a9386729826587f49938f49085b1",
"sha256": "e0553960bd298ddc49aeeb748a0be3a37acbdfdee7d7c26fce7154715fa826e0"
},
"downloads": -1,
"filename": "ariadne_codegen-0.14.0-py2.py3-none-any.whl",
"has_sig": false,
"md5_digest": "13d9a9386729826587f49938f49085b1",
"packagetype": "bdist_wheel",
"python_version": "py2.py3",
"requires_python": null,
"size": 95806,
"upload_time": "2024-07-17T13:29:24",
"upload_time_iso_8601": "2024-07-17T13:29:24.231424Z",
"url": "https://files.pythonhosted.org/packages/a9/b0/2643c64d50df13ea2cc43ae4133292cad62ea6f95b7c377288592b385c4c/ariadne_codegen-0.14.0-py2.py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "f4964f389335fd40db4ee685f594835181fec2692f8b362c51a6606e42bc904d",
"md5": "c9123cca9cb232c76bc7a21d211c7b67",
"sha256": "d5b15470195c3858b88a2bae855b5c04602ffae40228077b6cfb26a57d3f14f6"
},
"downloads": -1,
"filename": "ariadne_codegen-0.14.0.tar.gz",
"has_sig": false,
"md5_digest": "c9123cca9cb232c76bc7a21d211c7b67",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 65172,
"upload_time": "2024-07-17T13:29:26",
"upload_time_iso_8601": "2024-07-17T13:29:26.395757Z",
"url": "https://files.pythonhosted.org/packages/f4/96/4f389335fd40db4ee685f594835181fec2692f8b362c51a6606e42bc904d/ariadne_codegen-0.14.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-07-17 13:29:26",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "mirumee",
"github_project": "ariadne-codegen",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "ariadne-codegen"
}