Comments (10)
I'm not sure what you mean with the utility class.
from typedload.
It's supposed to be an interface / abstract class. The user can inherit from it to provide the serialization/deserialization functions within their class. The handler could then just check if issubclass(T, LoadDumpable) then use the member functions.
(Also i realized since the value is not necessarily a dict the functions should probably be called something like from_untyped
and `to_untyped instead.)
from typedload.
I could add a property like "serializer methods", none by default, that look for those names in the objects and calls them. I'm a bit afraid if people have to_dict that do other unrelated stuff :D I wouldn't want to call it by default.
from typedload.
What about objects that use a constructor to do that?
Would it be easier to add a decorator that tells typedload to use that method as a non-recursive loader?
from typedload.
I could add a property like "serializer methods"
Another issue I didn't think about is that the interface of the method should probably not be as simple as I wrote above since you'll want to be able to receive the loader / dumper instance as well. So i don't think allowing arbitrary function names would work too well, because the interface of the function would be pretty specific.
So right now I think inheriting from a abstract class would be the best solution. That way you also don't have any issue of accidentally calling the wrong function and the whole thing can be enabled by default. Here's the full code I'm using:
def issubclass_safe(sub: Any, sup: type) -> bool:
"""check if sub is a subclass of sup, without making any assumptions about the type of sub"""
if typing.get_origin(sub) is not None:
# is an instantiation of a generic type, so compare also the unparameterized type
if issubclass_safe(typing.get_origin(sub), sup):
return True
return inspect.isclass(sub) and issubclass(sub, sup)
class LoadDumpable:
"""class that provides it's own load and dump methods"""
@staticmethod
@abstractmethod
def from_untyped(selftype: Any, loader: dataloader.Loader, data: Any) -> Any:
"selftype is the generic instantiation of the class type. @classmethod only provides the current class but not the generic instantiation"
raise NotImplementedError("no implementation")
@abstractmethod
def to_untyped(self, dumper: datadumper.Dumper) -> dict[Any, Any]:
raise NotImplementedError("no implementation")
loader.handlers.append(
(
lambda t: issubclass_safe(t, LoadDumpable),
lambda loader, value, ty: ty.from_untyped(ty, loader, value),
)
)
dumper.handlers.append(
(lambda v: isinstance(v, LoadDumpable), lambda dumper, value: value.to_untyped(dumper))
)
What about objects that use a constructor to do that?
The constructor is sometimes used for this, but not always -- so here the from_untyped method would call the constructor
Would it be easier to add a decorator that tells typedload to use that method as a non-recursive loader?
Maybe, but I don't think that would really be much more convenient than adding a specific function that then calls whatever other function the user already has.
from typedload.
Eh in my view a from_dict should be self sufficient and not require typedload. Otherwise it should be an handler function that should do this job, since handlers are typedload-aware.
from typedload.
That also makes sense, I guess. In my case my code base uses typedload in multiple places anyways, and my main reason for wanting this is that I don't want to register handlers for each class that can be serialized separately as well as for all possible loader instances. But I do need the loader instance in the from_untyped function of at least one of those classes (for deserialization of an inner member).
from typedload.
an advantage of a decorator might be that it could detect whether or not the method accepts a loader
argument so it could be made optional. But with a decorator the from_dict method is again not really self-sufficient
from typedload.
You can just do an handler that checks if "from" method is present like you sent me and calls it with whatever parameters you want. The function is called with the loader the type and the value to load, so you can then just call your object and decide if you want to pass the loader or not. But all of this is not very generic so I don't think it would make much sense to add it in this form.
I have used such handlers myself at work, but normally never passing the loader object or the type, but just calling type(**data) or type.from_dict(data).
Yeah another problem if it should be called normally or with **
from typedload.
No clear definition of what this should do. Closing.
from typedload.
Related Issues (20)
- Support typing.NewType
- doc package fixe HOT 1
- Lack of type safety due to `**kwargs` HOT 1
- Inherited fields not serialized HOT 1
- handle from __future__ import annotations / ForwardRefs better HOT 8
- typedload.dataloader.is_union(int | str) == False HOT 1
- `typing.NotRequired[]` not supported HOT 5
- support decimal and fraction HOT 4
- Dictionary produced by dump() missing field its value is the default value HOT 1
- use typing extensions to support types on older py versions HOT 1
- crash
- Look into dataclass transform HOT 1
- Package not available in conda channels. HOT 2
- See whatever the hell this deprecation means
- compare to msgspec
- Possible to disable error on type which cannot be dealt with? HOT 2
- Why not cattrs HOT 1
- License compatibility with MPL-2 HOT 6
- type definition out of date compared to the documentation
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from typedload.