Skip to main content

A code-first, decorator-driven GraphQL framework for Python with a hand-built engine and a web-framework-agnostic core.

Project description

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 with the FastQL documentation, then use the capability catalog to trace documented behavior to its canonical OpenSpec requirements.

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

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

mygenx_fastql-0.0.1.tar.gz (62.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

mygenx_fastql-0.0.1-py3-none-any.whl (82.8 kB view details)

Uploaded Python 3

File details

Details for the file mygenx_fastql-0.0.1.tar.gz.

File metadata

  • Download URL: mygenx_fastql-0.0.1.tar.gz
  • Upload date:
  • Size: 62.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for mygenx_fastql-0.0.1.tar.gz
Algorithm Hash digest
SHA256 0717bc7dd6e0a2f1cc3a82b26285a4c50e35cff03afd8ed823391ab988760cd5
MD5 8183e22f25f3d835263d0af3f413e3fd
BLAKE2b-256 afa474b7bc891262fd44033e1477cce1b50eaf1ed5f6a5672b6daa8379890e75

See more details on using hashes here.

Provenance

The following attestation bundles were made for mygenx_fastql-0.0.1.tar.gz:

Publisher: publish.yml on MyGenX/FastQL

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file mygenx_fastql-0.0.1-py3-none-any.whl.

File metadata

  • Download URL: mygenx_fastql-0.0.1-py3-none-any.whl
  • Upload date:
  • Size: 82.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for mygenx_fastql-0.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 e89a67984b5dc4bf71e1b58726f393c00e4e11ad6427d00f3c5a68b8a24c0534
MD5 03622c238f1dd132f7289112475ec1d5
BLAKE2b-256 40fb7c8cb0d97678617e199cc26bcc421ec9664262775476b197ee1ac40c306d

See more details on using hashes here.

Provenance

The following attestation bundles were made for mygenx_fastql-0.0.1-py3-none-any.whl:

Publisher: publish.yml on MyGenX/FastQL

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page