0

I've got a Message class with some useful method in it (let's say validate, get_correlation_id, whatever, ...). This class has an init method with some required parameters (type, routing_key, etc...)

I've got a Param class that contains a validate_parameter method.

I've got a Status class that contains a validate_status method.

I've got a JobCreation class that inherits from Message and Param:

class JobCreation(Message, Param):
    msg_type = 'osb.job.ask'

    def __init__(self, parameters = {}, **kwargs):
        # Process reply_to
        reply_to = REPLY_TO_RESULTS
        if 'reply_to' in kwargs:
            reply_to = kwargs['reply_to'] 
            del kwargs['reply_to']

        # Init
        super().__init__(type=self.msg_type, **kwargs, reply_to=reply_to)
        self.parameters = parameters

    def validate(self):
        """Validate the JobCreation"""
        super().validate()
        self.validate_parameters()

I've got a JobResult class that inherits from Message, Param and Status:

class JobResult(Message, Param, Status):
    msg_type = 'osb.job.answer'

    def __init__(self, status=None, parameters={}, **kwargs):
        # Process routing_key
        routing_key = ROUTING_KEY_STATUS
        if 'routing_key' in kwargs:
            routing_key = kwargs['routing_key'] 
            del kwargs['routing_key']

        # Init
        super().__init__(type=self.msg_type, **kwargs, routing_key=ROUTING_KEY_STATUS)
        self.status = status
        self.parameters = parameters

    def validate(self):
        """Validate the JobResult"""
        super().validate()
        self.validate_status()
        self.validate_parameters()

And finally i've got a JobStatus class that inherits from Message and Status:

class JobStatus(Message, Status):
    msg_type = 'osb.job.info'

    def __init__(self, status=None, **kwargs):
        # Process routing_key
        routing_key = ROUTING_KEY_STATUS
        if 'routing_key' in kwargs:
            routing_key = kwargs['routing_key'] 
            del kwargs['routing_key']

        # Init
        super().__init__(type=self.msg_type, **kwargs, routing_key=ROUTING_KEY_STATUS)
        self.status = status

    def validate(self):
        """Validate the JobStatus"""
        super().validate()
        self.validate_status()

As you can see, depending on the type of 'Job' initialized, I want to validate it but it could be a parameter validation, a status validation or both.

The problem is, in my unit tests, it raises an error like this :

    class JobStatus(Message, Status):
TypeError: metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases

I've tried to create a Base class inheriting from ABC (abstract base class), and make my Message, Status and Param classes inherit from Base - doesn't seem to work.

Do you know how can I fix it?


[EDIT] As asked, the minimal reproductible example:

class Message:
    def __init__(self):
        print('Message init')

    def validate(self):
        print('Message validation')

class Status:
    def validate_status(self):
        print('Status validation')

class Param:
    def validate_parameters(self):
        print('Parameters validation')


class JobCreation(Message, Param):

    def __init__(self):
        print('Jobcreation init')
        super().__init__()

    def validate(self):
        super().validate()


class JobResult(Message, Param, Status):

    def __init__(self):
        print('Jobresult init')
        super().__init__()

    def validate(self):
        super().validate()
        self.validate_status()
        self.validate_parameters()

class JobStatus(Message, Status):

    def __init__(self):
        print('Jobresult init')
        super().__init__()

    def validate(self):
        super().validate()
        self.validate_status()


if __name__ == "__main__":
    job_creation = JobCreation()
    job_creation.validate()

    job_result = JobResult()
    job_result.validate()

    job_status = JobStatus()
    job_status.validate()
Bloodbee
  • 827
  • 8
  • 23
  • 1
    None of the classes shown use a metaclass. Do any of your base classes `Message`, `Status` or `Status` use a metaclass? Does the issue occur only during unit testing, and if so what test framework do you use? Can you please provide a [mre]? – MisterMiyagi Apr 22 '22 at 11:48
  • There is no metaclass because i have no abstract classes. I'm using unittest. – Bloodbee Apr 22 '22 at 11:50
  • Well, every class has a metaclass as it is constructed with `type`. In this case, I think it is failing to determine to correct metaclass after MRO. I could be completely wrong; I am not an expert. I suspect you will find helpful information in [this question](https://stackoverflow.com/questions/28720217/multiple-inheritance-metaclass-conflict) and [this question](https://stackoverflow.com/questions/11276037/resolving-metaclass-conflicts), and definitely in the [official Data model, Metaclasses](https://docs.python.org/3/reference/datamodel.html#metaclasses) documentation. – theherk Apr 22 '22 at 11:56
  • I've provided the minimal reproductible example. – Bloodbee Apr 22 '22 at 11:58
  • 1
    `class A(B)` and `class A(metaclass=B)` mean two entirely different things. The first *inherits* from `B`, the second *instantiates* `B`. – MisterMiyagi Apr 22 '22 at 12:01
  • 2
    @Bloodbee Your example produces no error. – theherk Apr 22 '22 at 12:01
  • @theherk It seems so, I think the problem is somewhere else. Maybe in the unit tests, I will investigate more. Thanks all. – Bloodbee Apr 22 '22 at 12:08

0 Answers0