Open Samreay opened 1 year ago
At runtime, kwargs
is a dict[str, Any]
instance, so it makes sense for its type to be a TypedDict
. A TypedDict
is a structural definition of dict[str, Any]
, and it supports all of the same operations as a dict
.
I don't know what it would mean if kwargs
was typed as Person
as in your example above. You wouldn't be able to access it as a dataclass because it's a dict
. It sounds like what you want is a way to transform a dataclass type into a comparable TypedDict
class with the dataclass attributes and their types converted into TypedDict
keys and value types?
I don't understand what Unpack[function]
or Unpack[class]
would mean.
I don't know what it would mean if kwargs was typed as Person as in your example above.
In my mind, this would be "unpack person" aka "what is in person". Just like unpacking a typedict conceptually is looking inside the typed dict for what kwargs are acceptable, one can do the same (conceptually) for a dataclass.
I don't understand what Unpack[function] or Unpack[class] would mean.
Here's a use case I encounter all the time which makes me go to a webpage's docs instead of being able to use my IDE.
def plot_point(x: float, y: float, size: float = 1.0, color: str = "red"):
...
def plot_points(xs: list[float], ys: list[float], **kwargs):
for x, y in zip(xs, ys):
plot_point(x, y, **kwargs)
I bought up Unpack[function]
(not so much as a please implement it like this) but a "this is a very common thing which doesn't have type support", and happy to know if there are alternatives available.
To just stick to matplotlib, given its the most popular visualisation library, plot
passes through kwargs to Line2D
. scatter
passes kwargs directly to Collection
. bar
and barh
pass kwargs directly through to Rectangle
, etc.
Sorry, missed this comment:
It sounds like what you want is a way to transform a dataclass type into a comparable TypedDict class with the dataclass attributes and their types converted into TypedDict keys and value types?
This would also make me a happy dev!
This would be very handy when working with data (de)serialization. I'm sure many devs building on Marshmallow or Pydantic feel the same. Being able to easily convert dataclasses to TypedDicts (and back?) is a missing link in the current ecosystem.
Would be great to be able to do something like this and keep type annotations:
@dataclass
class MyClass:
a: str
my_class_instance = MyClass(a="hello")
my_class_dict = my_schema.dump(my_class_instance) # or even better, the hypothetical dataclass_to_typeddict(my_class_instance)
my_class_dict # this should be a properly typed TypedDict instance with MyClass attributes
a way to transform a dataclass type into a comparable TypedDict class with the dataclass attributes and their types converted into TypedDict keys and value types
IMO this would be really useful. For instance, pydantic models can have proper TypedDict
type hints on .model_dumps()
if we can transform a dataclass type into TypedDict. Currently, pydantic .model_dumps()
only returns a dict[str, Any]
. Also, considering we can apply @dataclass_transform
to SQLAlchemy's Base
class to make it behaves like a dataclass, we will be able to implement a fully-typed json_serialize
function for any SQLAlchemy model objects, so that we can statically type check to see whether it fulfills the requirement of the API endpoint's expected response structure.
Specifying that kwargs should match the fields of a given dataclass would be very useful indeed.
My last potential usage:
@dataclass(kw_only=True, frozen=True)
class CompilationOptions:
...
def updated(self, **update: dict[str, Any]) -> "CompilationOptions": # <- Unpack["CompilationOptions"] would be nice here
"""Create an updated copy of itself."""
return CompilationOptions(**(asdict(self) | update))
(This seems to be a recurrent request, btw. For example: https://discuss.python.org/t/typing-unpack-for-kwargs-with-self-or-dataclass-classes/43001/10 https://stackoverflow.com/questions/76939764/define-a-typeddict-from-a-dataclass)
Hi, I was trying to do the exact them thing as the OP described, that is to obtain the TypedDict type for a Pydantic model, so that I can use that to annotate a custom constructor function:
class MyModel(BaseModel):
a: int
b: str
def my_init(**kwargs: Unpack[MyModel]):
return MyModel.model_validate(kwargs)
I tried asking for thoughts about this on the Python Typing mailing list a while back (Aug. 2022), didn't get any responses there: https://mail.python.org/archives/list/typing-sig@python.org/message/44DVY777AJXOUXE6JMJORZGL3LYIHXMF/
The
Unpack
addition has been great, however a lot of our code has an existing library of dataclasses instead of typed dictionaries. Here's a dummy example using one of the more common patterns that will suffer from this: factory methods.Right now, the "fix" for us would be to duplicate the dataclass as TypedDict, but code duplication is obviously not ideal. If there's another way, please let me know, otherwise I think a really valuable enhancement to the Unpack method would be to allow it to accept other objects, such as a
dataclass
or a pydanticBaseModel
given the popularity of pydantic and FastAPI.Antoher use case I can think of would be to be able to
Unpack[function]
orUnpack[class]
. Common examples here would includematplotlib
andplotly
, where plotting functions often exposekwargs
which just get passed to a child function. That child function has all the documentation and type hinting you'd need, but its unusable unless its copied into a TypeDict (I believe). For a concrete example, the top levelmaptlotlib
plt.plot()
function takes kwargs which are passed to theLine2D
class