Skip to content

Commit

Permalink
Add example of generating an input class
Browse files Browse the repository at this point in the history
  • Loading branch information
paula-mg committed Sep 6, 2024
1 parent b239efe commit df4d9eb
Showing 1 changed file with 61 additions and 2 deletions.
63 changes: 61 additions & 2 deletions src/scanspec/schema/schema.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,75 @@
from typing import Any

import strawberry
from fastapi import FastAPI
from resolvers import reduce_frames, validate_spec
from specs import Line, PointsResponse
from specs import PointsResponse
from strawberry.fastapi import GraphQLRouter

from scanspec.core import Path
from scanspec.specs import Line, Spec

# Here is the manual version of what we are trying to do

# @strawberry.input
# class LineInput(Line): ...


# @strawberry.input
# class ZipInput(Zip): ...


# @strawberry.input(one_of=True)
# class SpecInput:
# ...

# line: LineInput | None = strawberry.UNSET
# zip: ZipInput | None = strawberry.UNSET


def generate_input_class() -> type[Any]:
# This will be our input class, we're going to fiddle with it
# throughout this function
class SpecInput: ...

# We want to go through all the possible scan specs, this isn't
# currently possible but can be implemented.
# Raise an issue for a helper function to get all possible scanspec
# types.
for spec_type in Spec.types:
# We make a strawberry input classs using the scanspec pydantic models
# This isn't possible because scanspec models are actually pydantic
# dataclasses. We should have a word with Tom about it and probably
# raise an issue on strawberry.
@strawberry.experimental.pydantic.input(all_fields=True, model=spec_type)
class InputClass: ...

# Renaming the class to LineInput, ZipInput etc. so the
# schema looks neater
InputClass.__name__ = spec_type.__name__ + "Input"

# Add a field to the class called line, zip etc. and make it
# strawberry.UNSET
setattr(SpecInput, spec_type.__name__, strawberry.UNSET)

# Set the type annotation to line | none, zip | none, etc.
# Strawberry will read this and graphqlify it.
SpecInput.__annotations__[spec_type.__name__] = InputClass | None

# This is just a programtic equivalent of
# @strawberry.input(one_of=True)
# class SpecInput:
# ...
return strawberry.input(one_of=True)(SpecInput)


SpecInput = generate_input_class()


@strawberry.type
class Query:
@strawberry.field
def validate(self, spec: Line) -> str:
def validate(self, spec: SpecInput) -> str:
return validate_spec(spec)

@strawberry.field
Expand Down

0 comments on commit df4d9eb

Please sign in to comment.