跳转到主要内容

从模式、查询和突变生成完全类型的GraphQL客户端!

项目描述

Ariadne

Build Status


Ariadne代码生成器

Python代码生成器,从GraphQL模式、查询、突变和订阅中提取,生成具有完全类型和异步GraphQL客户端的Python包。

它作为ariadne-codegen命令提供,并从pyproject.toml文件读取配置。

$ ariadne-codegen

它也可以作为python -m ariadne_codegen运行。

特性

  • 从模式类型、输入和枚举生成pydantic模型。
  • 为GraphQL结果生成pydantic模型。
  • 生成客户端包,每个GraphQL操作都作为异步方法可用。

安装

Ariadne代码生成器可以使用pip安装。

$ pip install ariadne-codegen

要支持订阅,默认基础客户端需要websockets包。

$ pip install ariadne-codegen[subscriptions]

配置

ariadne-codegen 从您的 pyproject.toml 文件中的 [tool.ariadne-codegen] 节读取配置。您可以使用其他配置文件,通过 --config 选项,例如 ariadne-codegen --config custom_file.toml

客户端生成的最小配置

[tool.ariadne-codegen]
schema_path = "schema.graphql"
queries_path = "queries.graphql"

必填设置

  • queries_path - 包含查询的文件/目录路径(如果使用 enable_custom_operations,则可以是可选的)

以下两个参数中必须提供其中一个,如果两个都提供,则 schema_path 优先

  • schema_path - 包含 GraphQL 模式的文件/目录路径
  • remote_schema_url - 可执行 introspection 查询的 GraphQL 服务器的 URL

可选设置

  • remote_schema_headers - 附加头信息,随 introspection 查询一起传递,例如 {"Authorization" = "Bearer: token"}。要在头信息值中包含环境变量,请在该变量前加上 $,例如 {"Authorization" = "$AUTH_TOKEN"}
  • remote_schema_verify_ssl(默认为 true)- 一个标志,指定是否在检查远程模式时验证 SSL
  • target_package_name(默认为 "graphql_client")- 生成包的名称
  • target_package_path(默认为当前工作目录)- 生成包的路径
  • client_name(默认为 "Client")- 生成客户端类的名称
  • client_file_name(默认为 "client")- 包含生成客户端类的文件名称
  • base_client_name(默认为 "AsyncBaseClient")- 基础客户端类的名称
  • base_client_file_path(默认为 .../ariadne_codegen/client_generators/dependencies/async_base_client.py)- 定义 base_client_name 的文件路径
  • enums_module_name(默认为 "enums")- 包含生成枚举模型的文件名称
  • input_types_module_name(默认为 "input_types")- 包含生成输入类型模型的文件名称
  • fragments_module_name(默认为 "fragments")- 包含生成片段模型的文件名称
  • include_comments(默认为 "stable")- 设置每个生成文件顶部包含的注释内容。有效选项有:"none"(无注释)、"timestamp"(包含生成时间戳的注释)、"stable"(注释中包含这是一个生成文件的消息)
  • convert_to_snake_case(默认为 true)- 一个标志,指定是否将字段和参数名称转换为 snake_case
  • include_all_inputs(默认为 true)- 一个标志,指定是否包含模式中定义的所有输入,或仅包含在提供的操作中使用的输入
  • include_all_enums(默认为 true)- 一个标志,指定是否包含模式中定义的所有枚举,或仅包含在提供的操作中使用的枚举
  • async_client(默认为 true)- 默认生成的客户端是 async,将其更改为 false 以生成同步客户端
  • opentelemetry_client(默认为 false)- 默认基础客户端不支持任何性能跟踪。将此选项更改为 true 以使用具有 Open Telemetry 支持的基础客户端。
  • files_to_include(默认为 [])- 将复制到生成包中的文件列表
  • plugins(默认为 [])- 在生成过程中使用的插件列表
  • enable_custom_operations(默认为 false)- 启用自定义操作构建。生成包含所有类和方法的附加文件。

自定义操作构建器

自定义操作构建器允许您以结构化和直观的方式创建复杂的 GraphQL 查询。

示例代码

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())

说明

  1. 构建产品查询
    1. Query.product(id="...", channel="channel-uk") 启动了对具有指定 ID 和通道的产品进行查询。
    2. .fields(ProductFields.id, ProductFields.name) 指定要检索的产品字段:id 和 name。
  2. 构建翻译查询
    1. Query.translations(kind=TranslatableKinds.PRODUCT, first=10) 初始化对产品翻译的查询。
    2. .fields(...) 指定要检索的翻译字段。
    3. .alias("aliased_edges") 将 edges 字段重命名为 aliased_edges。
    4. .on("ProductTranslatableContent", ...) 指定如果节点类型为 ProductTranslatableContent 时要检索的字段:id、product_id 和 name。
  3. 执行查询
    1. 调用 client.query(...) 方法,传入构建的查询和操作名称 "get_products"。
    2. 此方法将查询发送到服务器并检索响应。

示例 pyproject.toml 配置。

注意:当 enable_custom_operations 设置为 true 时,queries_path 是可选的。

[tool.ariadne-codegen]
schema_path = "schema.graphql"
include_comments = "none"
target_package_name = "example_client"
enable_custom_operations = true

插件

Ariadne Codegen 实现了一个插件系统,该系统允许进一步自定义和微调生成的 Python 代码。它的文档可以在 PLUGINS.md 文件中单独查看。

标准插件

Ariadne Codegen 随附了可以从 ariadne_codegen.contrib 包导入的可选插件。

  • ariadne_codegen.contrib.shorter_results.ShorterResultsPlugin - 此插件处理生成客户端方法,对于只请求单个顶层字段的操作,它们直接返回此字段的值而不是操作的结果类型。例如,为查询 GetUser() { user(...) { ... }} 生成的 get_user 方法将直接返回 user 字段的值而不是 GetUserResult

  • ariadne_codegen.contrib.extract_operations.ExtractOperationsPlugin - 此插件将生成客户端方法的查询字符串提取到单独的 operations.py 模块中。它还修改了生成的客户端以导入这些定义。生成的模块名称可以通过在配置中的 [tool.ariadne-codegen.operations] 部分添加 operations_module_name="custom_name" 进行自定义。例如。

    [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 - 此插件更改生成的客户端模块,将所有 Pydantic 模型的导入移至 TYPE_CHECKING 条件下,使它们成为前向引用。这大大提高了 client 模块的导入性能。

  • ariadne_codegen.contrib.no_reimports.NoReimportsPlugin - 此插件移除生成的 __init__.py 的内容。这在生成的插件包含大量 Pydantic 模型且客户端在首次导入时整个包的 eager 初始化非常慢的场景中非常有用。

使用生成的客户端

可以从包中导入生成的客户端。

from {target_package_name}.{client_file_name} import {client_name}

默认设置示例

from graphql_client.client import Client

将标题传递给客户端

客户端(使用默认基本客户端),接收传递的标题并将它们附加到每个发送的请求。

client = Client("https://example.com/graphql", {"Authorization": "Bearer token"})

对于更复杂的场景,您可以传递自己的 http 客户端

client = Client(http_client=CustomComplexHttpClient())

CustomComplexHttpClient 需要是一个 httpx.AsyncClient 的实例(用于异步客户端),或 httpx.Client 的实例(用于同步)。

Websockets

为了处理订阅,默认的 AsyncBaseClient 使用 websockets 并实现 graphql-transport-ws 子协议。将 ws_originws_headers 参数添加为握手请求的标题,并使用 ws_connection_init_payload 作为 ConnectionInit 消息的有效负载。

文件上传

默认基本客户端(AsyncBaseClientBaseClient)检查 variables 字典的任何部分是否是 Upload 的实例。如果找到至少一个实例,则客户端根据 GraphQL 多部分请求规范 发送多部分请求。

Upload 包含在生成的客户端中,可以从其中导入。

from {target_package_name} import Upload

默认情况下,我们使用此类来表示 graphql 标量 Upload。对于具有不同名称的此标量的模式,您仍然可以使用 Upload 和默认客户端进行文件上传。

[tool.ariadne-codegen.scalars.OTHERSCALAR]
type = "Upload"

OpenTelemetry

当配置选项 opentelemetry_client 设置为 true 时,默认的基础客户端会被替换为支持可选 OpenTelemetry 的客户端。默认情况下,这种支持不会做任何事情,但当 opentelemetry-api 包已安装且提供了 tracer 参数时,客户端将创建关于执行请求的数据的跨度。

BaseClientOpenTelemetry 处理的跟踪参数

  • tracer: Optional[Union[str, Tracer]] = None - 将传递给 get_tracer 方法的跟踪对象或名称
  • root_context: Optional[Context] = None - 可选的上下文,添加到根跨度
  • root_span_name: str = "GraphQL Operation" - 根跨度名称

AsyncBaseClientOpenTelemetry 支持与 BaseClientOpenTelemetry 相同的所有参数,同时还公开了关于 WebSocket 的额外参数

  • ws_root_context: Optional[Context] = None - 可选的上下文,添加到 WebSocket 连接的根跨度
  • ws_root_span_name: str = "GraphQL Subscription" - WebSocket 连接的根跨度名称

自定义标量

默认情况下,非内置标量在生成的客户端中表示为 typing.Any。您可以通过向 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"

对于每个自定义标量,客户端将在所有 {graphql scalar name} 的出现中使用给定的 type。如果提供了 serializeparse,则将用于序列化和反序列化。结果模型中的 type 将使用 BeforeValidator 注解,例如 Annotated[type, BeforeValidator(parse)]。在输入注释中,将使用 PlainSerializer,例如 Annotated[type, PlainSerializer(serialize)]。如果 type/serialize/parse 至少包含一个 .,则字符串将根据其最后一个出现点分割。第一部分将用作导入的模块,第二部分将用作类型/方法名称。例如,type = "custom_scalars.a.ScalarA" 将生成 from custom_scalars.a import ScalarA

将标量映射到内置类型的示例

在这种情况下,标量映射到内置 str,不需要自定义的 serializeparse 方法。

[tool.ariadne-codegen.scalars.SCALARA]
type = "str"

pydantic 支持的类型的示例

在这种情况下,标量表示为 datetime,因此需要导入。Pydantic 处理序列化和反序列化,因此不需要自定义的 parseserialize

[tool.ariadne-codegen.scalars.DATETIME]
type = "datetime.datetime"

完全自定义类型的示例

在此示例中,标量表示为类 TypeB。Pydantic 无法处理序列化和反序列化,因此需要自定义 parseserialize。要提供 typeparseserialize 实现,我们可以使用 files_to_include 来复制 type_b.py 文件。

[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"
# inputs.py

class TestInput(BaseModel):
    value_b: Annotated[TypeB, PlainSerializer(serialize_b)]
# get_b.py

class GetB(BaseModel):
    query_b: Annotated[TypeB, BeforeValidator(parse_b)]
# client.py

class Client(AsyncBaseClient):
    async def test_mutation(self, value: TypeB) -> TestMutation:
        ...
        variables: Dict[str, object] = {
            "value": serialize_b(value),
        }
        ...

扩展生成的类型

使用自定义混合扩展模型

mixin 指令允许通过自定义逻辑扩展为查询/突变字段生成的类。 mixin 需要两个必需参数

  • from - 要从中导入的模块名称
  • import - 父类的名称

生成的类将使用 import 作为额外基类,并将导入添加到文件中。

from {from} import {import}
...
class OperationNameField(BaseModel, {import}):
    ...

此指令可以与 files_to_include 选项一起使用来扩展生成类的功能。

mixinfiles_to_include 的使用示例

带有 mixin 指令的查询

query listUsers {
    users @mixin(from: ".mixins", import: "UsersMixin") {
        id
    }
}

包含 files_to_includepyproject.toml 部分(mixins.py 包含 UsersMixin 实现)

files_to_include = [".../mixins.py"]

生成的 list_users.py 文件的一部分

...
from .mixins import UsersMixin
...
class ListUsersUsers(BaseModel, UsersMixin):
    ...

多个客户端

要生成多个不同的客户端,您可以将每个配置存储在不同的文件中,然后通过 --config 选项提供配置文件的路径,例如。

ariadne-codegen --config clientA.toml
ariadne-codegen --config clientB.toml

生成的代码依赖关系

生成的代码需要

可以通过提供另一个带有 base_client_file_pathbase_client_name 选项的基本客户端类来避免使用 httpxwebsockets 依赖。

示例

关于简单模式和少量查询及变异的示例,请参阅此处

生成 GraphSQL 模式的副本

您不仅可以生成客户端,还可以生成包含 GraphQL 模式副本的文件。为此,请使用带有 graphqlschema 参数调用 ariadne-codegen

ariadne-codegen graphqlschema

graphqlschema 模式从与 client 相同的位置读取配置,但仅使用 schema_pathremote_schema_urlremote_schema_headersremote_schema_verify_ssl 选项来检索模式,并使用 plugins 选项来加载插件。

除了上述内容外,graphqlschema 模式还接受特定于该模式的附加设置

target_file_path

一个包含生成文件目标路径的字符串。必须是 Python(.py)或 GraphQL(.graphql.gql)文件。

默认为 schema.py

生成的 Python 文件将包含

  • 必要的导入
  • 类型映射声明 {type_map_variable_name}: TypeMap = {...}
  • 模式声明 {schema_variable_name}: GraphQLSchema = GraphQLSchema(...)

生成的 GraphQL 文件将包含来自 graphql-core 包的 print_schema 函数的格式化输出。

schema_variable_name

一个用于模式变量的字符串名称,必须是有效的 Python 标识符。

默认为 "schema"。仅在目标是 Python 文件时使用。

type_map_variable_name

一个用于类型映射变量的字符串名称,必须是有效的 Python 标识符。

默认为 "type_map"。仅在目标是 Python 文件时使用。

贡献

我们欢迎所有人对 Ariadne 的贡献!如果您发现了错误或问题,请随时使用 GitHub 问题。如果您有任何问题或反馈,不要犹豫,在 GitHub 讨论中找到我们。

有关指导和说明,请参阅 CONTRIBUTING.md

同时,请确保您关注 @AriadneGraphQL 以获取最新的更新、新闻和随想!

Mirumee Software 用 ❤️ 制作 hello@mirumee.com

项目详情


下载文件

下载您平台的文件。如果您不确定选择哪个,请了解更多关于 安装软件包 的信息。

源分布

ariadne_codegen-0.14.0.tar.gz (65.2 kB 查看哈希)

上传时间

构建分发版

ariadne_codegen-0.14.0-py2.py3-none-any.whl (95.8 kB 查看哈希值)

上传于 Python 2 Python 3

由以下组织支持