Python code generator that takes graphql schema, queries and mutations 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
- 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.
Ariadne Code Generator can be installed with pip:
$ pip install ariadne-codegen
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
Required settings:
queries_path
- path to file/directory with queries
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 schemaremote_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 totrue
) - a flag that specifies wheter to verify ssl while introspecting remote schematarget_package_name
(defaults to"graphql_client"
) - name of generated packagetarget_package_path
(defaults to cwd) - path where to generate packageclient_name
(defaults to"Client"
) - name of generated client classclient_file_name
(defaults to"client"
) - name of file with generated client classbase_client_name
(defaults to"AsyncBaseClient"
) - name of base client classbase_client_file_path
(defaults to.../graphql_sdk_gen/generators/async_base_client.py
) - path to file wherebase_client_name
is definedenums_module_name
(defaults to"enums"
) - name of file with generated enums modelsinput_types_module_name
(defaults to"input_types"
) - name of file with generated input types modelsinclude_comments
(defaults totrue
) - a flag that specifies whether to include comments in generated filesconvert_to_snake_case
(defaults totrue
) - a flag that specifies whether to convert fields and arguments names to snake caseasync_client
(defaults totrue
) - default generated client isasync
, change this to optionfalse
to generate synchronous client insteadfiles_to_include
(defaults to[]
) - list of files which will be copied into generated packageplugins
(defaults to[]
) - list of plugins to use during generation
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 file.
Generated client can be imported from package:
from {target_package_name}.{client_file_name} import {client_name}
Example with default settings:
from graphql_client.client import Client
Client (with default base client), takes passed headers and attaches them to every sent request.
client = Client("https://example.com/graphql", {"Authorization": "Bearer token"})
For more complex scenarios, you can pass your own http client:
client = Client(http_client=CustomComplexHttpClient())
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
:
[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"
All occurrences of {graphql scalar name}
will be represented as type
. If provided, serialize
and parse
will be used for serialization and deserialization.
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
.
In this case scalar is mapped to built-in str
which doesn`t require custom serialize
and parse
methods.
[tool.ariadne-codegen.scalars.SCALARA]
type = "str"
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.
[tool.ariadne-codegen.scalars.DATETIME]
type = "datetime.datetime"
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.
[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"
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 fromimport
- name of a parent class
Generated class will use import
as extra base class, and import will be added to the file.
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.
Query with mixin
directive:
query listUsers {
users @mixin(from: ".mixins", import: "UsersMixin") {
id
}
}
Part of pyproject.toml
with files_to_include
(mixins.py
contains UsersMixin
implementation)
files_to_include = [".../mixins.py"]
Part of generated list_users.py
file:
...
from .mixins import UsersMixin
...
class ListUsersUsers(BaseModel, UsersMixin):
...
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 requires:
- pydantic
- httpx (can be avoided by providing another base client class with
base_client_file_path
andbase_client_name
parameters)
Example with simple schema and few queries and mutations is available here.
Instead of generating client, you can generate file with a copy of GraphQL schema as GraphQLSchema
declaration. To do this call ariadne-codegen
with graphqlschema
argument:
ariadne-codegen graphqlschema
graphqlschema
mode reads configuration from the same place as client
but uses only schema_path
, remote_schema_url
, remote_schema_headers
and remote_schema_verify_ssl
options with addition to some extra options specific to it:
target_file_path
(defaults to"schema.py"
) - destination path for generated fileschema_variable_name
(defaults to"schema"
) - name for schema variable, must be valid python identifiertype_map_variable_name
(defaults to"type_map"
) - name for type map variable, must be valid python identifier
Generated file contains:
- Necessary imports
- Type map declaration
{type_map_variable_name}: TypeMap = {...}
- Schema declaration
{schema_variable_name}: GraphQLSchema = GraphQLSchema(...)
We welcome all contributions to Ariadne! If you've found a bug or issue, feel free to use GitHub issues. If you have any questions or feedback, don't hesitate to catch us on GitHub discussions.
For guidance and instructions, please see CONTRIBUTING.md.
Also make sure you follow @AriadneGraphQL on Twitter for latest updates, news and random musings!