Skip to content

Multiple published documents search #29

@sv9388

Description

@sv9388

Multiple document search is supported by EPO 3.2. But I don't see an interface for the same in the code. A constructor overloading in Docdb would help achieve the same in Python3. Here is an edited version of models.py that I am using to achieve the same.

import inspect
import types

class MultiMethod:
    '''
    Represents a single multimethod.
    '''
    def __init__(self, name):
        self._methods = {}
        self.__name__ = name

    def register(self, meth):
        '''
        Register a new method as a multimethod
        '''
        sig = inspect.signature(meth)

        # Build a type-signature from the method's annotations
        types = []
        for name, parm in sig.parameters.items():
            if name == 'self': 
                continue
            if parm.annotation is inspect.Parameter.empty:
                raise TypeError(
                    'Argument {} must be annotated with a type'.format(name)
                    )
            if not isinstance(parm.annotation, type):
                raise TypeError(
                    'Argument {} annotation must be a type'.format(name)
                    )
            if parm.default is not inspect.Parameter.empty:
                self._methods[tuple(types)] = meth
            types.append(parm.annotation)

        self._methods[tuple(types)] = meth

    def __call__(self, *args):
        '''
        Call a method based on type signature of the arguments
        '''
        types = tuple(type(arg) for arg in args[1:])
        meth = self._methods.get(types, None)
        if meth:
            return meth(*args)
        else:
            raise TypeError('No matching method for types {}'.format(types))
        
    def __get__(self, instance, cls):
        '''
        Descriptor method needed to make calls work in a class
        '''
        if instance is not None:
            return types.MethodType(self, instance)
        else:
            return self
    
class MultiDict(dict):
    '''
    Special dictionary to build multimethods in a metaclass
    '''
    def __setitem__(self, key, value):
        if key in self:
            # If key already exists, it must be a multimethod or callable
            current_value = self[key]
            if isinstance(current_value, MultiMethod):
                current_value.register(value)
            else:
                mvalue = MultiMethod(key)
                mvalue.register(current_value)
                mvalue.register(value)
                super().__setitem__(key, mvalue)
        else:
            super().__setitem__(key, value)

class MultipleMeta(type):
    '''
    Metaclass that allows multiple dispatch of methods
    '''
    def __new__(cls, clsname, bases, clsdict):
        return type.__new__(cls, clsname, bases, dict(clsdict))

    @classmethod
    def __prepare__(cls, clsname, bases):
        return MultiDict()

## Actual Docdb change
class Docdb(BaseInput, metaclass=MultipleMeta):
    def __init__(self, number:str, country_code:str, kind_code:str, date:str=None):
        if not all([country_code, kind_code]):
            raise MissingRequiredValue(
                'number, country_code, and kind_code must be present'
            )
        super(Docdb, self).__init__(number, country_code, kind_code, date)

    def __init__(self, data_points:list):
        self.data_points = []
        for dp in data_points:
            d = Docdb(dp[0], dp[1], dp[2])
            self.data_points.append(d)

    def as_api_input(self):
        print(self.__dict__.keys(), )
        if hasattr(self, 'data_points'):
            print(self.data_points)
            print("#" * 20)
            return '\n'.join([x.as_api_input() for x in self.data_points])
        return super(Docdb, self).as_api_input()

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions