From 755c9a84dfa2cd6bdb75a1f04155a1a5f119427f Mon Sep 17 00:00:00 2001 From: Thibault Derousseaux <6574550+tibdex@users.noreply.github.com> Date: Mon, 2 Nov 2026 21:09:39 -0500 Subject: [PATCH 1/7] Create graphql-codegen.md --- .../python/client/graphql-codegen.md | 86 +++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 src/code/language-support/python/client/graphql-codegen.md diff --git a/src/code/language-support/python/client/graphql-codegen.md b/src/code/language-support/python/client/graphql-codegen.md new file mode 100644 index 0000000000..55bbf1869e --- /dev/null +++ b/src/code/language-support/python/client/graphql-codegen.md @@ -0,0 +1,86 @@ +--- +name: GraphQL Python codegen +description: Compile GraphQL documents into a typed Python package with no imposed transport, no runtime dependencies, and no redundant validation. +github: tibdex/graphql-codegen +tags: + - tools-and-libraries + - frontend +--- + +Install graphql-codegen: + +``` +$ pip install graphql-codegen +``` + +Write your operations in a `bookshop/get_order.graphql` file: + +```graphql +query GetOrder($id: ID!) { + order(id: $id) { + id + status + } +} +``` + +Point a `bookshop/graphql.config.yml` file at your schema and documents: + +```yaml +schema: schema.graphqls +documents: "*.graphql" +extensions: + pythonCodegen: + moduleRoot: .. + package: bookshop.graphql +``` + +Generate the package: + +``` +$ graphql-codegen bookshop/graphql.config.yml +``` + +Bring your own transport, here with the standard library alone: + +```python +from typing import Literal +from urllib.request import Request as HTTPRequest, urlopen + +from bookshop.graphql.runtime import Request + + +def send[Data](request: Request[Literal["query", "mutation"], Data], /) -> Data: + prepared = request.prepare() + http_request = HTTPRequest( + "https://bookshop.example/graphql", + data=bytes(prepared), + headers={ + "Accept": "application/graphql-response+json", + "Content-Type": "application/json", + }, + ) + + with urlopen(http_request) as response: + return prepared.parse(response.read()) +``` + +And let your type checker verify every variable and every field of the response: + +```python +from typing import Literal, assert_type + +from bookshop.get_order_graphql import GetOrder +from bookshop.transport import send + +data = send(GetOrder({"id": "o1"})) +order = data["order"] + +# `Query.order` is nullable, so the type checker requires this check. +if order is None: + print("No such order.") +else: + assert_type(order["id"], str) + assert_type(order["status"], Literal["PENDING", "SHIPPED", "DELIVERED", "CANCELED"]) + print(f"Order {order['id']} is {order['status']}.") +``` From f51327892f98f77c31e79907879cb1cd402333d8 Mon Sep 17 00:00:00 2001 From: Thibault Derousseaux <6574550+tibdex@users.noreply.github.com> Date: Mon, 2 Nov 2026 21:13:54 -0500 Subject: [PATCH 2/7] Update graphql-codegen.md --- .../language-support/python/client/graphql-codegen.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/code/language-support/python/client/graphql-codegen.md b/src/code/language-support/python/client/graphql-codegen.md index 55bbf1869e..98f0359bda 100644 --- a/src/code/language-support/python/client/graphql-codegen.md +++ b/src/code/language-support/python/client/graphql-codegen.md @@ -9,8 +9,8 @@ tags: Install graphql-codegen: -``` -$ pip install graphql-codegen +```bash +pip install graphql-codegen ``` Write your operations in a `bookshop/get_order.graphql` file: @@ -37,8 +37,8 @@ extensions: Generate the package: -``` -$ graphql-codegen bookshop/graphql.config.yml +```bash +graphql-codegen bookshop/graphql.config.yml ``` Bring your own transport, here with the standard library alone: From 74e3e70e2ab5fc4cbf5b8c90ad87fe01e4883519 Mon Sep 17 00:00:00 2001 From: Thibault Derousseaux <6574550+tibdex@users.noreply.github.com> Date: Mon, 2 Nov 2026 21:19:06 -0500 Subject: [PATCH 3/7] Update graphql-codegen.md --- src/code/language-support/python/client/graphql-codegen.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/code/language-support/python/client/graphql-codegen.md b/src/code/language-support/python/client/graphql-codegen.md index 98f0359bda..48460fa688 100644 --- a/src/code/language-support/python/client/graphql-codegen.md +++ b/src/code/language-support/python/client/graphql-codegen.md @@ -7,6 +7,12 @@ tags: - frontend --- +The generated package has: + +- **no imposed transport**: bytes in, bytes out; +- **no runtime dependencies**: nothing to install or upgrade (apart from `typing-extensions` before Python 3.15); +- **no redundant validation**: just dicts, statically checked (by mypy, Pyright, Pyrefly, ty, etc.). + Install graphql-codegen: ```bash From 5fe43b5255f8f8944b2f205e52a576d7ca9d1c98 Mon Sep 17 00:00:00 2001 From: Thibault Derousseaux <6574550+tibdex@users.noreply.github.com> Date: Mon, 2 Nov 2026 21:27:01 -0500 Subject: [PATCH 4/7] Update graphql-codegen.md --- src/code/language-support/python/client/graphql-codegen.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/code/language-support/python/client/graphql-codegen.md b/src/code/language-support/python/client/graphql-codegen.md index 48460fa688..db3b49d0f6 100644 --- a/src/code/language-support/python/client/graphql-codegen.md +++ b/src/code/language-support/python/client/graphql-codegen.md @@ -47,7 +47,7 @@ Generate the package: graphql-codegen bookshop/graphql.config.yml ``` -Bring your own transport, here with the standard library alone: +Bring your own transport, here in `bookshop/transport.py` and with the standard library alone: ```python from typing import Literal From 9239eae727c3d2d35c36df53211b2d5c37a3d121 Mon Sep 17 00:00:00 2001 From: Thibault Derousseaux <6574550+tibdex@users.noreply.github.com> Date: Tue, 3 Nov 2026 22:19:37 -0500 Subject: [PATCH 5/7] Rebrand --- .../python/client/graphql-codegen.md | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/code/language-support/python/client/graphql-codegen.md b/src/code/language-support/python/client/graphql-codegen.md index db3b49d0f6..adf5c1d756 100644 --- a/src/code/language-support/python/client/graphql-codegen.md +++ b/src/code/language-support/python/client/graphql-codegen.md @@ -1,22 +1,26 @@ --- -name: GraphQL Python codegen +name: Spartan GraphQL description: Compile GraphQL documents into a typed Python package with no imposed transport, no runtime dependencies, and no redundant validation. -github: tibdex/graphql-codegen +github: tibdex/spartan-graphql tags: - tools-and-libraries - frontend --- -The generated package has: +> **Spartan**, *adj.* … distinguished by simplicity, frugality, courage, or brevity of speech. +> +> — *Oxford English Dictionary* + +Spartan GraphQL compiles GraphQL documents into a typed Python package, and stops there: - **no imposed transport**: bytes in, bytes out; - **no runtime dependencies**: nothing to install or upgrade (apart from `typing-extensions` before Python 3.15); - **no redundant validation**: just dicts, statically checked (by mypy, Pyright, Pyrefly, ty, etc.). -Install graphql-codegen: +Install spartan-graphql: ```bash -pip install graphql-codegen +pip install spartan-graphql ``` Write your operations in a `bookshop/get_order.graphql` file: @@ -36,7 +40,7 @@ Point a `bookshop/graphql.config.yml` file at your schema and documents: schema: schema.graphqls documents: "*.graphql" extensions: - pythonCodegen: + spartan: moduleRoot: .. package: bookshop.graphql ``` @@ -44,7 +48,7 @@ extensions: Generate the package: ```bash -graphql-codegen bookshop/graphql.config.yml +spartan-graphql bookshop/graphql.config.yml ``` Bring your own transport, here in `bookshop/transport.py` and with the standard library alone: From 041de3a5dce83582e1d4f5f8962bf6b1d73916ff Mon Sep 17 00:00:00 2001 From: Thibault Derousseaux <6574550+tibdex@users.noreply.github.com> Date: Tue, 3 Nov 2026 22:19:55 -0500 Subject: [PATCH 6/7] Rename graphql-codegen.md to spartan-graphql.md --- .../python/client/{graphql-codegen.md => spartan-graphql.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/code/language-support/python/client/{graphql-codegen.md => spartan-graphql.md} (100%) diff --git a/src/code/language-support/python/client/graphql-codegen.md b/src/code/language-support/python/client/spartan-graphql.md similarity index 100% rename from src/code/language-support/python/client/graphql-codegen.md rename to src/code/language-support/python/client/spartan-graphql.md From aaecea52f734cb1aa74f6f7d3a91cf6bdb6c5417 Mon Sep 17 00:00:00 2001 From: Martin Bonnin Date: Wed, 4 Nov 2026 10:38:52 +0100 Subject: [PATCH 7/7] Format --- src/code/language-support/python/client/spartan-graphql.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/code/language-support/python/client/spartan-graphql.md b/src/code/language-support/python/client/spartan-graphql.md index adf5c1d756..8594c6bae6 100644 --- a/src/code/language-support/python/client/spartan-graphql.md +++ b/src/code/language-support/python/client/spartan-graphql.md @@ -7,9 +7,9 @@ tags: - frontend --- -> **Spartan**, *adj.* … distinguished by simplicity, frugality, courage, or brevity of speech. +> **Spartan**, _adj._ … distinguished by simplicity, frugality, courage, or brevity of speech. > -> — *Oxford English Dictionary* +> — _Oxford English Dictionary_ Spartan GraphQL compiles GraphQL documents into a typed Python package, and stops there: