RaenonX
RaenonX

Reputation: 111

Dynamically create a class which derived from an ABC class

I am using PyMongo custom bson encoder. Because the encoder cannot be inherited, it needs to be created for every class, so I want to dynamically create an encoder for it.

The problem is that the base encoder (TypeEncoder) is created from ABC class. When I was trying to create the class using this code:

from bson.codec_options import TypeEncoder

cls_encoder = type(f"Flag{cls.__name__}Encoder", 
                   (TypeEncoder,),
                   {"transform_python": lambda self, value: value.code,
                    "python_type": property(lambda self: cls)})

The result will be

>> isinstance(cls_encoder, TypeEncoder)
False
>> type(cls_encoder)
<class 'abc.FlagAutoReplyContentTypeEncoder'>
>> super(cls_encoder)
<super: <class 'FlagAutoReplyContentTypeEncoder'>, NULL>

The expected result should be

>> isinstance(cls_encoder, TypeEncoder)
True

Note: the cls variable will be an Enum Note: python_type is an abstractproperty; transform_python is a function which accepts the value in the type of python_type and returns something which type is valid for bson serialization.


I have tried this:

class FlagBsonEncoder(TypeEncoder):
    def transform_python(self, value):
        return value.code

cls_encoder = type(f"Flag{cls.__name__}Encoder", 
                   (FlagBsonEncoder,),
                   {"python_type": property(lambda self: cls)})

But still the same result:

>> isinstance(cls_encoder, TypeEncoder)
False

Here is the official example of how to use custom type encoding: http://api.mongodb.com/python/current/api/bson/codec_options.html http://api.mongodb.com/python/current/examples/custom_type.html#custom-type-type-codec

Upvotes: 2

Views: 156

Answers (1)

gmds
gmds

Reputation: 19885

You misunderstand what isinstance does, I think.

isinstance(cls_encoder, TypeEncoder) asks if the class object cls_encoder is an instance of TypeEncoder. Of course it is not - it is a type!

What you want is isinstance(cls_encoder(), TypeEncoder), which asks if an instance of cls_encoder is also an instance of TypeEncoder, which of course must be true.

If you want to check if the class cls_encoder is a subclass of TypeEncoder, you can use issubclass(cls_encoder, TypeEncoder).

Upvotes: 1

Related Questions