class NonRootAPI(object): """ An API that will check for a Non Root API's """ def __init__(self, comp): """ A NonRootAPi constructor will init a logger and a comp property for an object that have to be compare with the existing registered protocols :param comp: :type comp: an input object as DynamicProtocol :return: void """ self.comp = comp self.__logger = Logger() def check(self): """ Will trying to match the candidate Non Root API check IJSONResourceAPI for more info :return: False if not success otherwise the response from matched API.method() """ for api in subscribers([self.comp], IJSONResourceAPI): if api.__class__.__name__.lower() in self.comp.to_dict().keys(): self.__logger.debug('Candidate API {} for {}'.format( api.__class__.__name__, self.comp.__class__.__name__)) candidate_api_name = self.comp.to_dict().get( api.__class__.__name__.lower()) try: # execute the candidate API method # and return the result candidate_api_result = getattr(api, candidate_api_name)() except AttributeError as e: msg = 'Candidate API {} for {} does not implement method {} error: {}' self.__logger.warning( msg.format(api.__class__.__name__, self.comp.__class__.__name__, candidate_api_name, e.message)) else: self.__logger.info('Successful apply API {} for {}'.format( api.__class__.__name__, self.comp.__class__.__name__)) return candidate_api_result return False
class Validator(BaseValidator): """ Our main validator will trying to resolve the type of incoming request """ def __init__(self, validate_msg): """ Accept message that have to be validated :param validate_msg: currently we supporting only a json validators """ super(Validator, self).__init__(validate_msg) self.__msg = Message(validate_msg) self.__logger = Logger() def validate(self): """ Will walk through all subscribers from IValidator type the first one will be returned as valid type. In this way we can supporting a lot of types on the same port/service :return: matched IValidator subscriber """ for sub in subscribers([self.__msg], IValidator): msg = sub.validate() self.is_valid = msg.is_valid self.message_type = msg.message_type self.message = msg.message # we want only one correct type of our message so # only one validator will response with True if self.is_valid is True: self.__logger.debug('Matched type is: {}'.format(self.message_type)) return self self.__logger.warning('Main Validator - There are no subscribers from type IValidator') return False
class Validator(BaseValidator): """ Our main validator will trying to resolve the type of incoming request """ def __init__(self, validate_msg): """ Accept message that have to be validated :param validate_msg: currently we supporting only a json validators """ super(Validator, self).__init__(validate_msg) self.__msg = Message(validate_msg) self.__logger = Logger() def validate(self): """ Will walk through all subscribers from IValidator type the first one will be returned as valid type. In this way we can supporting a lot of types on the same port/service :return: matched IValidator subscriber """ for sub in subscribers([self.__msg], IValidator): msg = sub.validate() self.is_valid = msg.is_valid self.message_type = msg.message_type self.message = msg.message # we want only one correct type of our message so # only one validator will response with True if self.is_valid is True: self.__logger.debug('Matched type is: {}'.format( self.message_type)) return self self.__logger.warning( 'Main Validator - There are no subscribers from type IValidator') return False
class Time(BaseRootAPI): def __init__(self, factory): super(Time, self).__init__(factory) self.factory = factory self.logger = Logger() def process_factory(self): if self.factory.time == 'get': self.factory.time = str(datetime.now()) else: self.factory.time = 'service unavailable' self.logger.debug('IN TIME API: {}'.format(self.factory.to_dict())) return self.factory
class RootAPI(object): """ An API that implements an IJSONResourceRootAPI """ def __init__(self, comp): """ A RootAPI constructor will init an logger and will initialize a public attribute - self.comp which representing an input object as DynamicProtocol :param comp: :type comp: DynamicProtocol :return: void """ self.comp = comp self.__logger = Logger() def check(self): """ Will trying to get a RootAPI and if match one will fired a process_factory of an implementation API :return: False if not success otherwise the response from process_factory """ for api in subscribers([self.comp], IJSONResourceRootAPI): if api.__class__.__name__.lower() in self.comp.to_dict().keys(): self.__logger.debug('Candidate API {} for {}'.format( api.__class__.__name__, self.comp.__class__.__name__ )) self.__logger.info('Successful apply API {} for {}'.format( api.__class__.__name__, self.comp.__class__.__name__ )) return api.process_factory() return False
class Clock(BaseRootAPIWampMixin): def __init__(self, factory=None): super(Clock, self).__init__(factory) self.logger = Logger() @staticmethod def print_result_callback(res, factory): factory.clock = res return factory @staticmethod def print_result_callback_error(err): print err return False def process_factory(self): self.logger.debug(self.factory.to_dict()) # we trying to get a wamo session session = self.get_session() # if exist we will get the time from a rpc with a name 'get_time' # registered as wamp component inside components/wamp/rpc if session: result = session.call('get_time') result.addCallback(self.print_result_callback, self.factory) result.addErrback(self.print_result_callback_error) return result else: # if does not exist self.factory.clock = str(datetime.now()) return self.factory
class Time(BaseRootAPI): def __init__(self, factory): super(Time, self).__init__(factory) self.factory = factory self.logger = Logger() def process_factory(self): if self.factory.time == 'get': self.factory.time = str(datetime.now()) else: self.factory.time = 'service unavailable' self.logger.debug('IN TIME API: {}'.format(self.factory.to_dict())) return self.factory
class Clock(BaseRootAPIWampMixin): def __init__(self, factory=None): super(Clock, self).__init__(factory) self.logger = Logger() @staticmethod def print_result_callback(res, factory): factory.clock = res return factory @staticmethod def print_result_callback_error(err): print err return False def process_factory(self): self.logger.debug(self.factory.to_dict()) # we trying to get a wamo session session = self.get_session() # if exist we will get the time from a rpc with a name 'get_time' # registered as wamp component inside components/wamp/rpc if session: result = session.call('get_time') result.addCallback(self.print_result_callback, self.factory) result.addErrback(self.print_result_callback_error) return result else: # if does not exist self.factory.clock = str(datetime.now()) return self.factory
class RootAPI(object): """ An API that implements an IJSONResourceRootAPI """ def __init__(self, comp): """ A RootAPI constructor will init an logger and will initialize a public attribute - self.comp which representing an input object as DynamicProtocol :param comp: :type comp: DynamicProtocol :return: void """ self.comp = comp self.__logger = Logger() def check(self): """ Will trying to get a RootAPI and if match one will fired a process_factory of an implementation API :return: False if not success otherwise the response from process_factory """ for api in subscribers([self.comp], IJSONResourceRootAPI): if api.__class__.__name__.lower() in self.comp.to_dict().keys(): self.__logger.debug('Candidate API {} for {}'.format( api.__class__.__name__, self.comp.__class__.__name__)) self.__logger.info('Successful apply API {} for {}'.format( api.__class__.__name__, self.comp.__class__.__name__)) return api.process_factory() return False
class NonRootAPI(object): """ An API that will check for a Non Root API's """ def __init__(self, comp): """ A NonRootAPi constructor will init a logger and a comp property for an object that have to be compare with the existing registered protocols :param comp: :type comp: an input object as DynamicProtocol :return: void """ self.comp = comp self.__logger = Logger() def check(self): """ Will trying to match the candidate Non Root API check IJSONResourceAPI for more info :return: False if not success otherwise the response from matched API.method() """ for api in subscribers([self.comp], IJSONResourceAPI): if api.__class__.__name__.lower() in self.comp.to_dict().keys(): self.__logger.debug('Candidate API {} for {}'.format( api.__class__.__name__, self.comp.__class__.__name__ )) candidate_api_name = self.comp.to_dict().get(api.__class__.__name__.lower()) try: # execute the candidate API method # and return the result candidate_api_result = getattr(api, candidate_api_name)() except AttributeError as e: msg = 'Candidate API {} for {} does not implement method {} error: {}' self.__logger.warning(msg.format( api.__class__.__name__, self.comp.__class__.__name__, candidate_api_name, e.message )) else: self.__logger.info('Successful apply API {} for {}'.format( api.__class__.__name__, self.comp.__class__.__name__ )) return candidate_api_result return False
class Dispatcher(object): """ Our Main dispatcher, Will trying to dispatch the request to API which provides functionality for it. The Dispatcher also adapts IValidator """ adapts(IValidator) def __init__(self, validator): """ The constructor will init a logger and will init a public attribute - self.validator that is a validated requests, here we have to determinate which protocol and API have to process this request :param validator: :type validator: IValidator :return: void """ self.validator = validator self.__logger = Logger() def __api_processor(self, valid_dispatch, valid_response, isubscriber): """ Will loop through a valid response objects and will compare it to a registered protocol subscribers :param valid_dispatch: :param valid_response: :param isubscriber: :return: The chosen API or False """ for sub in subscribers([valid_response], isubscriber): self.__logger.debug('Matched request subscribers: {}'.format(sub.__class__.__name__)) try: verifyObject(isubscriber, sub) except DoesNotImplement as e: self.__logger.warning('Incorrect implementation: {}'.format(e)) else: comp = sub.compare() if comp is not False and IJSONResource.providedBy(comp): self.__logger.debug('Signature compare to {}'.format(comp.__class__.__name__)) # trying to resolve API that will deal with these request if len(comp.to_dict().keys()) > 1: # process request without root element return NonRootAPI(comp).check() else: # root element return RootAPI(comp).check() # if there are no one subsciber from IJSONResource self.__logger.warning('The request {} from type {} was not recognized as a structure or an API'.format( valid_response.response, valid_dispatch.message_type )) return False def dispatch(self): """ When request is happening first will be validated, if valid_dispatch is False means we do not support this data type. You have to write your custom validator(s) inside components/validators :return: The response or False """ # validate for supporting types try: valid_dispatch = self.validator.validate() except Exception as e: self.__logger.debug('validate error: {}'.format(e.message)) return self.validator else: if valid_dispatch is False: return self.validator valid_response = ValidatorResponse(valid_dispatch.message) if valid_dispatch.message_type == 'JSON': return self.__api_processor( valid_dispatch, valid_response, IJSONResourceSubscriber )
class Dispatcher(object): """ Our Main dispatcher, Will trying to dispatch the request to API which provides functionality for it. The Dispatcher also adapts IValidator """ adapts(IValidator) def __init__(self, validator): """ The constructor will init a logger and will init a public attribute - self.validator that is a validated requests, here we have to determinate which protocol and API have to process this request :param validator: :type validator: IValidator :return: void """ self.validator = validator self.__logger = Logger() def __api_processor(self, valid_dispatch, valid_response, isubscriber): """ Will loop through a valid response objects and will compare it to a registered protocol subscribers :param valid_dispatch: :param valid_response: :param isubscriber: :return: The chosen API or False """ for sub in subscribers([valid_response], isubscriber): self.__logger.debug('Matched request subscribers: {}'.format( sub.__class__.__name__)) try: verifyObject(isubscriber, sub) except DoesNotImplement as e: self.__logger.warning('Incorrect implementation: {}'.format(e)) else: comp = sub.compare() if comp is not False and IJSONResource.providedBy(comp): self.__logger.debug('Signature compare to {}'.format( comp.__class__.__name__)) # trying to resolve API that will deal with these request if len(comp.to_dict().keys()) > 1: # process request without root element return NonRootAPI(comp).check() else: # root element return RootAPI(comp).check() # if there are no one subsciber from IJSONResource self.__logger.warning( 'The request {} from type {} was not recognized as a structure or an API' .format(valid_response.response, valid_dispatch.message_type)) return False def dispatch(self): """ When request is happening first will be validated, if valid_dispatch is False means we do not support this data type. You have to write your custom validator(s) inside components/validators :return: The response or False """ # validate for supporting types try: valid_dispatch = self.validator.validate() except Exception as e: self.__logger.debug('validate error: {}'.format(e.message)) return self.validator else: if valid_dispatch is False: return self.validator valid_response = ValidatorResponse(valid_dispatch.message) if valid_dispatch.message_type == 'JSON': return self.__api_processor(valid_dispatch, valid_response, IJSONResourceSubscriber)