You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I think there are probably some more considerations in implementing support for generics where fields are annotated with TypeVars. But here are some examples use cases of where type vars / generics are currently not supported, but perhaps could be.
Use case where a field can be one of, but generics are used for safe typing, not a dynamic union type
frompathlibimportPathfromtypingimportGeneric, TypeVarimportserdeimportserde.json@serde.serdeclassS3Address:
bucket: strkey: strF=TypeVar("F", bound=Path|S3Address)
"""TypeVar for fields which correspond to files. Fields annotated with F are intended to either be a remote file or a local file. No subclasses are intended to be supported."""@serde.serdeclassMyFiles(Generic[F]):
example_file: F# Annotation with generic fails to deserialize.# For reference, the similar non-generic class deserializes successfully.@serde.serdeclassMyFilesDynamic:
example_file: Path|S3Address# Annotation with union deserializes successfully.# Aliases to demonstrate the intended usage of MyFiles's generic parameter.MyRemoteFiles=MyFiles[S3Address]
MyLocalFiles=MyFiles[Path]
original_remote_files=MyFiles(S3Address(bucket="my_bucket", key="my_key"))
json_remote_files=serde.json.to_json(original_remote_files)
# Deserialization fails with the following error:# serde.compat.SerdeError: Method __main__.MyFiles.__init__() parameter example_file={'bucket': 'my_bucket', 'key': 'my_key'} violates type hint ~I, as dict {'bucket': 'my_bucket', 'key': 'my_key'} not <class "__main__.S3Address"> or <class "pathlib.Path">.recovered_remote_files=serde.json.from_json(MyFiles[S3Address], json_remote_files)
assertrecovered_remote_files==original_remote_files
In this example, since the generic F, specifies that a type should be one of two possible types, and not some arbitrary type which has the same bounds, we could probably add support for this case in the same way that the MyFilesDynamic class is supported.
Use case where a field could be a subclass with additional fields
fromtypingimportGeneric, TypeVarimportserdeimportserde.json@serde.serdeclassMyBaseClass:
value: strT=TypeVar("T", bound=MyBaseClass)
@serde.serdeclassFoo(Generic[T]):
bar: T@serde.serdeclassMySpecificClass(MyBaseClass):
num: intoriginal=Foo(bar=MySpecificClass(str("bar"), num=42))
json=serde.json.to_json(original)
# Deserialization fails with the following error:# serde.compat.SerdeError: Method __main__.Foo.__init__() parameter bar={'value': 'bar', 'num': 42} violates type hint ~T, as dict {'value': 'bar', 'num': 42} not instance of <class "__main__.MyBaseClass">.recovered=serde.json.from_json(Foo[MySpecificClass], json)
print(recovered)
assertrecovered==original
To support this case we would need to get the concrete type of the generic parameter from the Foo[MySpecificClass] passed to from_json.
The text was updated successfully, but these errors were encountered:
I think there are probably some more considerations in implementing support for generics where fields are annotated with TypeVars. But here are some examples use cases of where type vars / generics are currently not supported, but perhaps could be.
Use case where a field can be one of, but generics are used for safe typing, not a dynamic union type
In this example, since the generic F, specifies that a type should be one of two possible types, and not some arbitrary type which has the same bounds, we could probably add support for this case in the same way that the
MyFilesDynamic
class is supported.Use case where a field could be a subclass with additional fields
To support this case we would need to get the concrete type of the generic parameter from the
Foo[MySpecificClass]
passed to from_json.The text was updated successfully, but these errors were encountered: