def construct(cls: Type[TF], env: Environment) -> TF: """ Constructs concrete infrastructure factory for given named application. Reads and resolves persistence topic from environment variable 'PERSISTENCE_MODULE'. """ factory_cls: Type[TF] # noinspection SpellCheckingInspection topic = ( env.get( "INFRASTRUCTURE_FACTORY", # Legacy. "", ) or env.get( "FACTORY_TOPIC", # Legacy. "", ) or env.get( cls.PERSISTENCE_MODULE, "eventsourcing.popo:Factory", )) try: obj: Union[Type[TF], ModuleType] = resolve_topic(topic) except TopicError as e: raise EnvironmentError( "Failed to resolve persistence module topic: " f"'{topic}' from environment " f"variable '{cls.PERSISTENCE_MODULE}'") from e if isinstance(obj, ModuleType): # Find the factory in the module. factory_classes: List[Type[TF]] = [] for member in obj.__dict__.values(): if (isinstance(member, type) and issubclass(member, InfrastructureFactory) and member != InfrastructureFactory): factory_classes.append(cast(Type[TF], member)) if len(factory_classes) == 1: factory_cls = factory_classes[0] else: raise AssertionError( f"Found {len(factory_classes)} infrastructure factory classes in" f" '{topic}', expected 1.") elif isinstance(obj, type) and issubclass(obj, InfrastructureFactory): factory_cls = obj else: raise AssertionError( f"Not an infrastructure factory class or module: {topic}") return factory_cls(env=env)
def __init__(self, environment: Environment): """ Initialises AES cipher with ``cipher_key``. :param str cipher_key: 16, 24, or 32 bytes encoded as base64 """ cipher_key = environment.get(self.CIPHER_KEY) if not cipher_key: raise EnvironmentError(f"'{self.CIPHER_KEY}' not set in env") key = b64decode(cipher_key.encode("utf8")) AESCipher.check_key_size(len(key)) self.key = key