import dis


class ServerMaker(type):
    """ Metaclass for server matching. """

    def __init__(cls, cls_name, bases, cls_dict):
        methods, attrs = [], []
        for func in cls_dict:
            try:
                ret = dis.get_instructions(cls_dict[func])
            except TypeError:
                pass
            else:
                for i in ret:
                    if i.opname == 'LOAD_GLOBAL':
                        if i.argval not in methods:
                            methods.append(i.argval)
                    elif i.opname == 'LOAD_ATTR':
                        if i.argval not in attrs:
                            attrs.append(i.argval)

        if 'connect' in methods:
            raise TypeError('Использование метода connect недопустима в серверном классе.')
        if not ('AF_INET' in methods and 'SOCK_STREAM' in methods):
            raise TypeError('Некорректная инициализация сокета.')

        super().__init__(cls_name, bases, cls_dict)


class ClientMaker(type):
    """ Metaclass for client matching. """

    def __init__(cls, cls_name, bases, cls_dict):
        methods = []
        for func in cls_dict:
            try:
                ret = dis.get_instructions(cls_dict[func])
            except TypeError:
                pass
            else:
                for i in ret:
                    if i.opname == 'LOAD_GLOBAL':
                        if i.argval not in methods:
                            methods.append(i.argval)

        for command in ('accept', 'listen', 'socket'):
            if command in methods:
                raise TypeError(f'Использование метода {command} недопустима в клиентском классе.')
        if 'get_message' in methods or 'send_message' in methods:
            pass
        else:
            raise TypeError('Отсутствуют вызовы функций, работающих с сокетами.')

        super().__init__(cls_name, bases, cls_dict)
