How to dispatch methods of a superclass?

Question:

I would like to decorate the shapely.geometry.Point class to instantiate it from a dendropy.datamodel.basemodel.AnnotationSet object. I chose the multimethod package to dispatch __init__ of the superclass as it dispatches this method into a simple class without any problems:

from multimethod import multimeta

class Example(metaclass=multimeta):
    def __init__(self, *args, **kwargs):
        print("DEFAULT")

    def __init__(self, x: str):
        print("Initialising from a string")

    def __init__(self, x: int):
        print("Initialising from an integer")

However, it does not work in my case with the inheritance:

class Point(Point, metaclass=multimeta):
    def __init__(self, annotations: AnnotationSet):
        try:
            super().__init__(
                float(annotations.get_value(LONGITUDE_ALIAS)),
                float(annotations.get_value(LATITUDE_ALIAS)),
            )
        except (TypeError, ValueError):
            raise ValueError(
                f"There is no coordinates in the annotations:n{annotations}"
            )

It initialises from AnnotationSet but not from default arguments:

Point(6, 4)

---------------------------------------------------------------------------
DispatchError                             Traceback (most recent call last)
Cell In [461], line 1
----> 1 Point(6, 4)

File ~anaconda3envsbioinfolibsite-packagesmultimethod__init__.py:313, in multimethod.__call__(self, *args, **kwargs)
    311 if self.pending:  # check first to avoid function call
    312     self.evaluate()
--> 313 func = self[tuple(func(arg) for func, arg in zip(self.type_checkers, args))]
    314 try:
    315     return func(*args, **kwargs)

File ~anaconda3envsbioinfolibsite-packagesmultimethod__init__.py:307, in multimethod.__missing__(self, types)
    305     return self.setdefault(types, *funcs)  # type: ignore
    306 msg = f"{self.__name__}: {len(keys)} methods found"  # type: ignore
--> 307 raise DispatchError(msg, types, keys)

DispatchError: ('__init__: 0 methods found', (<class '__main__.Point'>, <class 'int'>), [])

Are there ways to dispatch the superclass methods? I am not interested in multimethod specifically; maybe there is any way besides?

Asked By: Vovin

||

Answers:

This is a paraphrase of Coady’s answer with their consent.

To dispatch a supermethod, we need to specify it manually, wrapping it into a multimethod instance & using the register method as a decorator for the first of new multimethods. For instance, in my case:

class Point(Point):
    @multimethod(Point.__init__).register
    def __init__(self, annotations: AnnotationSet):
        try:
            super().__init__(
                float(annotations.get_value(LONGITUDE_ALIAS)),
                float(annotations.get_value(LATITUDE_ALIAS)),
            )
        except (TypeError, ValueError):
            raise ValueError(
                f"There is no coordinates in the annotations:n{annotations}"
            )
Answered By: Vovin