def _add_adapter(self, func, config: dict, options: dict, parser): message = config['target'] params = None if isinstance(message, str): service = self._context_map.locate_service(message) if service is not None: params = ffd.get_arguments(service.__call__) else: params = ffd.get_arguments(message) if params is None: raise ffd.FrameworkError(f'Could not locate service {message}') options['params'].update(params) options['alias'].update(config['alias'] if config['alias'] is not None else {}) options['help_'].update(config['help_'] if config['help_'] is not None else {}) options['middleware'].extend(config['middleware'] if config['middleware'] is not None else []) for name, config in options['params'].items(): args = [f'--{inflection.dasherize(name)}'] if name in options['alias']: args.append(f'-{options["alias"][name]}') kwargs = { 'default': config['default'], 'required': config['default'] is inspect.Parameter.empty, 'help': options['help_'][name] if name in options['help_'] else None, } if config['type'] == bool: kwargs['action'] = 'store_true' if not config['default'] else 'store_false' else: kwargs['type'] = config['type'] parser.add_argument(*args, **kwargs)
def __call__(self, entity) -> Repository: if not issubclass(entity, ffd.AggregateRoot): raise ffd.LogicError('Repositories can only be generated for aggregate roots') for k, v in self._cache.items(): if entity.same_type(k): return v if entity not in self._cache: for k, v in self._factories.items(): if issubclass(entity, k): self._cache[entity] = v(entity) break elif issubclass(k, entity): self._cache[entity] = v(k) break if entity not in self._cache: context = entity.get_class_context() if context in self._default_factory and self._default_factory[context] is not None: self._cache[entity] = self._default_factory[context](entity) if entity not in self._cache: raise ffd.FrameworkError( f'No registry found for entity {entity}. Have you configured a persistence mechanism or extension?' ) return self._cache[entity]
def batch_wrapper(cls: ffd.MetaAware): try: cls.add_annotation(self) setattr(cls, '_batch_size', batch_size) setattr(cls, '_batch_window', batch_window) except AttributeError: raise ffd.FrameworkError( '@authenticator used on invalid target') return cls
def __call__(self, **kwargs): self._load_factories() connections = {} factories = {} for context in self._context_map.contexts: storage = context.config.get('storage', {}) if 'services' in storage: for name, config in storage.get('services').items(): config = config or {} if name not in self._connection_factories and config.get('type') not in self._connection_factories: raise ffd.ConfigurationError(f"No ConnectionFactory configured for '{name}'") key = name if name in self._connection_factories else config.get('type') connections[name] = context.container.build(self._connection_factories[key])( **(config.get('connection') or {}) ) for context in self._context_map.contexts: storage = context.config.get('storage', {}) if 'services' in storage: for name, config in storage.get('services').items(): config = config or {} if name not in self._repository_factories and config.get('type') not in self._repository_factories: raise ffd.ConfigurationError(f"No RepositoryFactory configured for '{name}'") key = name if name in self._repository_factories else config.get('type') factory = context.container.autowire(self._repository_factories[key]) try: factories[name] = factory(connections[name], **(config.get('repository') or {})) except TypeError as e: if '__init__() takes exactly one argument' in str(e): raise ffd.FrameworkError(f"{factory.__name__}.__init__() must take a connection as " f"the first argument") raise e for context in self._context_map.contexts: if context.name == 'firefly': continue storage = context.config.get('storage', {}) registered_aggregates = [] if 'aggregates' in storage: for entity, service in storage.get('aggregates').items(): if not entity.startswith(context.name): entity = f'{context.name}.{entity}' entity = ffd.load_class(entity) registered_aggregates.append(entity) self._registry.register_factory(entity, factories[service]) if 'default' in storage: for entity in context.entities: if issubclass(entity, ffd.AggregateRoot) and entity is not ffd.AggregateRoot \ and entity not in registered_aggregates: self._registry.register_factory(entity, factories[storage.get('default')]) # TODO Get persistence working in these core services. # self._registry(ffd.ContextMap).add(self._context_map) self.dispatch(ffd.StorageConfigured())
def __call__(self, message: ffd.Message, next_: Callable) -> ffd.Message: if not self._initialized: self._initialize() self.debug('Message context: %s', message.get_context()) self.debug('This context: %s', self._context) self.debug('Environment: %s', self._ff_environment) if message.get_context() != 'firefly' and \ message.get_context() == self._context and \ not message.headers.get('external', False) and \ self._ff_environment != 'test': self.debug( 'EventResolvingMiddleware - event originated from this context. Dispatching.' ) self._publish_message(message) return next_(message) args = message.to_dict(recursive=False) args['_message'] = message if str(message) in self._event_listeners: services = self._event_listeners[str(message)] for service in services: try: if self._service_is_batch_capable( service) and self._batch_service.is_registered( service.__class__): self.debug('Deferring to batch service') return self._batch_service.handle(service, args) else: parsed_args = ffd.build_argument_list(args, service) self.debug('Calling service %s with arguments: %s', service.__class__.__name__, parsed_args) service(**parsed_args) except TypeError as e: self.exception(e) raise ffd.FrameworkError( f'Error calling {service.__class__.__name__}:\n\n{str(e)}' ) else: self.info('No event listener found for message %s', message) return next_(message)
def convert_type(message: Message, new_name: str, new_base: Union[Message, Tuple[Message]]): if not is_dataclass(message): raise ffd.FrameworkError('message must be a dataclass') types = get_type_hints(message.__class__) message_fields = [] for field_ in fields(message): message_fields.append((field_.name, types[field_.name], field_)) if not isinstance(new_base, tuple): new_base = (new_base, ) cls = make_dataclass(new_name, fields=message_fields, bases=new_base, eq=False, repr=False) return cls(**asdict(message))
def __call__(self, message: ffd.Message, next_: Callable) -> ffd.Message: if not self._initialized: self._initialize() if message.get_context() != 'firefly' and \ message.get_context() == self._context and \ not message.headers.get('external', False): self._publish_message(message) return next_(message) args = message.to_dict(recursive=False) args['_message'] = message if str(message) in self._event_listeners: services = self._event_listeners[str(message)] for service in services: try: service(**ffd.build_argument_list(args, service)) except TypeError as e: raise ffd.FrameworkError( f'Error calling {service.__class__.__name__}:\n\n{str(e)}' ) return next_(message)
def authenticator_wrapper(cls: ffd.MetaAware): try: cls.add_annotation(self) except AttributeError: raise ffd.FrameworkError('@authorizer used on invalid target') return cls