-
-
Notifications
You must be signed in to change notification settings - Fork 286
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
Return TypedDict instances from Metadata.to_dict() #2099
base: main
Are you sure you want to change the base?
Return TypedDict instances from Metadata.to_dict() #2099
Conversation
I experimented with making the Making the # src/zarr/abc/metadata.py
...
T = TypeVar("T", bound=dict[str, JSON])
@dataclass(frozen=True)
class Metadata(Generic[T]):
def to_dict(self) -> T:
... However, I ran into issues with the # src/zarr/core/chunk_key_encodings.py
...
class ChunkKeyEncodingDict(TypedDict):
"""A dictionary representing a chunk key encoding configuration."""
name: str
configuration: dict[Literal["separator"], SeparatorLiteral]
@dataclass(frozen=True)
class ChunkKeyEncoding(Metadata[ChunkKeyEncodingDict]): # Type argument "ChunkKeyEncodingDict" of "Metadata" must be a subtype of "dict[str, JSON]"
name: str
separator: SeparatorLiteral = "." It seems like we need a way to bound the Is it possible that this is not supported? Would appreciate any guidance @jhamman @d-v-b |
I think the problem is specifying the type bound to be Second, for some reason Here's an example that I got working: from abc import abstractmethod
from dataclasses import dataclass
from typing import Any, Generic, TypeVar, Mapping, TypedDict
T = TypeVar('T', bound=Mapping[str, object])
class Meta(Generic[T]):
@abstractmethod
def to_dict(self) -> T:
...
class ExampleSpec(TypedDict):
a: str
b: str
@dataclass
class Example(Meta[ExampleSpec]):
a: str
b: str
def to_dict(self) -> ExampleSpec:
return {'a': self.a, 'b': self.b}
x = Example(a='10', b='10')
y = x.to_dict()
reveal_type(y)
"""
Revealed type is "TypedDict('tessel.ExampleSpec', {'a': builtins.str, 'b': builtins.str})"
""" |
26efbff
to
0e9ae08
Compare
Define TypedDict classes for metadata models that have a well-typed dict representation and set the return value of the the model's to_dict() method to the TypedDict
Redefine `Metadata` class to be generic and refactor downstream classes
0e9ae08
to
e56547c
Compare
Hello @d-v-b! I rebased and pushed commits to make the When you have a moment, a review would be super helpful! |
Summary
This is a
partialimplementation for #1773.So far, I have done the following:
Metadata
abc generic overMapping[str, object]
TypedDict
classes for the metadata models that have a well-typed dict representationto_dict()
method to the relevantTypedDict
from_dict()
methods to the relevantTypedDict
Closes #1773
Notes
Metadata
abc is generic over a type bound byMapping[str, object]
. I haven't been able to getMapping[str, JSON]
to work as a type boundTypedDict
s for the various Metadata classes were inferred from each respective classes'from_dict()
,to_dict()
, and initializer methodsfrom_dict()
methods utilize a variant of the overloadedparse_named_configuration
function. This accepts aJSON
data type, causing it to raise a mypy error when called w/ one of theTypedDict
classes. This is the case even if we coerce the TypedDict back to adict
before calling it. I assume this method is performing runtime validation, so we would not want to substitute it w/ dev-time validation provided by theCodecDict
classesArrayV2Metadata.from_dict()
method raise mypy errors due to the theArrayV2MetadataDict
being coerced to adict
to allow it to be mutatedQuestions
from_dict()
methods, would it be appropriate to ignore the mypyarg-type
errors that are raised byparse_named_configuration()
? Alternatively,parse_named_configuration()
's signature can be modified to accept aMapping[str, Any]
rather thanJSON
. This is not equivalent toJSON
, but seems to be a sufficient substitute for each place thatparse_named_configuration
is currently calledarg-type
errors in the body ofArrayV2Metadata.from_dict()
?node_type
is never found when the dictionaryzgroup
is unpacked. However,node_type
is defined w/NotRequired
. I searched around and was unable to find any documentation on this -- guidance on next steps would be appreciated!Checklist
TODO: