-
Notifications
You must be signed in to change notification settings - Fork 3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
139 graphql strawberry #141
base: main
Are you sure you want to change the base?
Conversation
# 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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@callumforrester I am not tied to dataclass, but I have a requirement for positional args. I have a choice of directions for you:
- Continue using dataclasses, add support to strawberry, probably using something like what I needed to do to autodoc_pydantic
- Ditch dataclasses and make a BaseModel subclass with positional arg support. I think we could make this work both at runtime using something like this and at static analysis by overriding the dataclass_transform. The closed issue would suggest that pydantic would never accept such an approach upstream.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To elaborate on 2, this works for both static analysis and at runtime:
from __future__ import annotations
from abc import ABCMeta
from typing import Any
from pydantic import BaseModel, Field
from typing_extensions import dataclass_transform
# TODO: not sure about the others like NoInitField and PrivateAttr
@dataclass_transform(field_specifiers=(Field,))
class PosargsMeta(type(BaseModel), ABCMeta):
def __new__(
mcs,
cls_name: str,
bases: tuple[type[Any], ...],
namespace: dict[str, Any],
**kwargs: Any,
) -> type:
cls = super().__new__(mcs, cls_name, bases, namespace, **kwargs)
original_init = cls.__init__
def patched_init(self, *args, **kwargs):
for k, v in zip(cls.model_fields, args, strict=False):
kwargs[k] = v
original_init(self, **kwargs)
cls.__init__ = patched_init
return cls
class Spec(BaseModel, metaclass=PosargsMeta):
pass
class Line(Spec):
start: float = Field(description="Midpoint of the first point of the line")
stop: float = Field(description="Midpoint of the last point of the line")
num: int = Field(min=1, description="Number of frames to produce")
# pyright and pydantic are happy with this...
obj = Line(3, 4, 5)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have no particular preference, we should discuss with @paula-mg since she'll be doing the work.
No description provided.