FastQL
A code-first, decorator-driven GraphQL framework for Python with a hand-built engine (lexer → parser → validator → executor), a built-in dependency-injection / context layer, and a web-framework-agnostic core — zero runtime dependencies, Python 3.11+.
Status: early development. The core engine (parse → build → validate → execute, with dependency injection and introspection) is in place.
Documentation: Start at fastql.vachagan.dev, then use
the capability catalog
to trace documented behavior to its canonical OpenSpec requirements. Documentation
sources and publishing instructions live under docs/.
Quickstart
Define types and operations with decorators — field and argument types come from your
Python type hints. Resolvers are plain functions; the executor injects arguments, the
parent object, resolve info, and the Context based on each resolver's signature.
import asyncio
from typing import Annotated
from fastql import Argument, Context, Field, Query, Schema, Type, execute
@Type
class User: # just fields — constructor/repr/eq are auto-generated
id: int
full_name: str
@Field
def loud_name(self) -> str: # exposed as loudName by default
return self.full_name.upper()
class AppContext(Context):
def __init__(self, users):
self.users = users
@Query # group related queries on a class…
class Queries:
@Field
async def user(
self,
user_id: Annotated[int, Argument(name="id")],
ctx: Context,
) -> "User | None":
return ctx.users.get(user_id)
@Field
def ping(self) -> str: # sync resolvers work alongside async ones
return "pong"
schema = Schema(query=Queries)
async def main():
ctx = AppContext(users={1: User(1, "Ada Lovelace")})
result = await execute(schema, "{ user(id: 1) { id fullName loudName } ping }", context=ctx)
print(result.data) # {'user': {'id': 1, 'fullName': 'Ada Lovelace', 'loudName': 'ADA LOVELACE'}, 'ping': 'pong'}
asyncio.run(main())
@Type and @Input classes get generated constructors, repr, and equality unless they define
their own methods. Python snake_case fields and arguments become GraphQL camelCase by default;
pass SchemaConfig(auto_camel_case=False) to Schema to preserve Python names. Explicit name=
metadata always wins. build_schema() remains available for applications that intentionally merge
multiple globally decorated root classes.
execute returns an ExecutionResult with data, errors, and extensions, and a
.formatted() helper that produces the GraphQL-over-HTTP response shape. Introspection
(__schema, __type, __typename) is built in.
A fuller, runnable version — covering every type kind, mutations, subscriptions,
DataLoaders, permissions, and extensions — lives in examples/app, the
showcase schema that the per-framework projects under examples/projects
all reuse.
The documentation quickstart and first-schema examples are also executed by the test
suite from docs/snippets.
Dev server & playground
Try a schema in the browser with the built-in, zero-dependency dev server:
python -m fastql serve examples.app:schema # http://127.0.0.1:7691
It serves, on the default port 7691:
| Route | Description |
|---|---|
GET / |
GraphiQL IDE (loaded from CDN) |
POST/GET /graphql |
the GraphQL endpoint ({data, errors} JSON) |
GET /schema.graphql |
the schema as SDL |
GET /schema.json |
the schema as an introspection result |
Override the binding with --host / --port. If your resolvers need a Context,
point --context at a value or zero-arg factory:
python -m fastql serve examples.app:schema --context examples.app:make_context
Or call it programmatically:
import fastql
from examples.app import schema, make_context
fastql.serve(schema, port=7691, context_factory=make_context) # blocking; Ctrl-C to stop
The dev server lives outside the agnostic core (in fastql.server) and only
consumes build_schema / execute — it is a developer convenience, not a
production transport (no TLS, auth, or subscriptions).
Design at a glance
@Type / @Input / root class decorators ← unified type-hint-driven authoring
▼
Schema(query=...) / build_schema() ← compiles decorators into the type-system IR
▼
Type-system IR (Schema, ObjectType, Field, scalars, wrappers)
▼
execute() ── validation ── coercion ── async resolution + DI/context
▲
language: Source → Lexer → Parser → AST ← hand-built front-end
The core never imports an HTTP framework. Transports (an optional built-in dev server,
plus FastAPI/Django/Flask/ASGI adapters) plug in on top and consume build_schema / execute.
Web framework integrations
Install only the framework adapter an application uses:
pip install mygenx-fastql[fastapi] # or starlette, flask, django
from fastapi import FastAPI
from fastql.integrations.fastapi import create_fastapi_router
app = FastAPI()
app.include_router(create_fastapi_router(schema, graphiql=True))
The base installation includes the dependency-free GraphQLASGI adapter. See
the integration documentation for mounting,
request context, endpoint configuration, and supported versions.
Runnable per-framework projects — FastAPI, Starlette, Flask, Django, and raw ASGI, each
mounting the same examples/app schema — live under
examples/projects. Reusing one schema across every adapter is the
proof that the core is framework-agnostic; each project differs only in a few lines of glue.
Development
pip install -e ".[dev]"
pytest
Metadata
Release files for mygenx-fastql 1.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| mygenx_fastql-1.0.0.tar.gz | 80.5 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| mygenx_fastql-1.0.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 187.4 kB
Release files / mygenx_fastql-1.0.0.tar.gz
| Download URL | mygenx_fastql-1.0.0.tar.gz |
|---|---|
| Size | 80.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
7065466f32ca12067bce50fafd044c641374280b2600a2a8a9d6a35354ef0847
|
|
BLAKE2b-256 checksum How to use checksums |
191e3976ee1477128e705d6bed2b5c3dbdec360197546a3369e848db834763d4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jun 11, 2026.
Transparency logRelease files / mygenx_fastql-1.0.0-py3-none-any.whl
| Download URL | mygenx_fastql-1.0.0-py3-none-any.whl |
|---|---|
| Size | 106.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
6cfd846e6ee9fa63fa11283ac65fb32f843ca745a7446843953a449285e9fcf1
|
|
BLAKE2b-256 checksum How to use checksums |
75e0598a0efa96bf54e2c92034a804ef1b2dc31b07dada510364f9f322f75a83
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jun 11, 2026.
Transparency logSecurity for mygenx-fastql 1.0.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for mygenx_fastql-1.0.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jun 11, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.