Module redvox.cloud.config

This module contains capabilities for loading RedVox specific configurations from the user's environment if it exists.

Expand source code
"""
This module contains capabilities for loading RedVox specific configurations from the user's environment if it exists.
"""

from dataclasses import dataclass
import os
from pathlib import Path
from typing import Optional

# noinspection Mypy
import redvox.common.errors as errors

# noinspection PyPackageRequirements,Mypy
from serde import deserialize, serialize

# noinspection PyPackageRequirements,Mypy
from serde.toml import from_toml, to_toml

REDVOX_CONFIG_FILE_NAME: str = ".redvox.toml"
REDVOX_USERNAME_ENV_KEY: str = "REDVOX_USERNAME"
REDVOX_PASSWORD_ENV_KEY: str = "REDVOX_PASSWORD"
REDVOX_PROTOCOL_ENV_KEY: str = "REDVOX_PROTOCOL"
REDVOX_HOST_ENV_KEY: str = "REDVOX_HOST"
REDVOX_PORT_ENV_KEY: str = "REDVOX_PORT"
REDVOX_SECRET_TOKEN_ENV_KEY: str = "REDVOX_SECRET_TOKEN"


@serialize
@deserialize
@dataclass
class RedVoxConfig:
    """
    Configuration options specific for accessing the cloud services.
    """

    username: str
    password: str
    protocol: str = "https"
    host: str = "redvox.io"
    port: int = 8080
    secret_token: Optional[str] = None

    @staticmethod
    def from_auth_token(
            auth_token: str,
            protocol: str = "https",
            host: str = "redvox.io",
            port: int = 8080,
            secret_token: Optional[str] = None) -> "RedVoxConfig":
        return RedVoxConfig("auth_token", auth_token, protocol, host, port, secret_token)

    @staticmethod
    def from_env() -> "RedVoxConfig":
        """
        Attempts to load the configuration from the environment.
        :return: An instance of RedvoxConfig or raises a RedvoxError.
        """
        # At least the username and password must be provided
        username: Optional[str] = os.environ.get(REDVOX_USERNAME_ENV_KEY)
        password: Optional[str] = os.environ.get(REDVOX_PASSWORD_ENV_KEY)

        if username is None:
            raise errors.RedVoxError(
                f"{REDVOX_USERNAME_ENV_KEY} is not in the environment"
            )

        if password is None:
            raise errors.RedVoxError(
                f"{REDVOX_PASSWORD_ENV_KEY} is not in the environment"
            )

        redvox_config: RedVoxConfig = RedVoxConfig(username, password)

        # If anything else is provided, overwrite the defaults
        protocol: Optional[str] = os.environ.get(REDVOX_PROTOCOL_ENV_KEY)
        if protocol is not None:
            redvox_config.protocol = protocol

        host: Optional[str] = os.environ.get(REDVOX_HOST_ENV_KEY)
        if host is not None:
            redvox_config.host = host

        port: Optional[str] = os.environ.get(REDVOX_PORT_ENV_KEY)
        if port is not None:
            # Make sure the port is actually an integer and parse it as such
            try:
                port_int: int = int(port)
                redvox_config.port = port_int
            except ValueError:
                raise errors.RedVoxError(
                    f"Provided environment variable={REDVOX_PORT_ENV_KEY} for port={port} is not integer"
                )

        secret_token: Optional[str] = os.environ.get(REDVOX_SECRET_TOKEN_ENV_KEY)
        if secret_token is not None:
            redvox_config.secret_token = secret_token

        return redvox_config

    @staticmethod
    def from_file(path: Path) -> "RedVoxConfig":
        """
        Attempts to load the configuration from a TOML file.
        :return: An instance of RedvoxConfig or raises a RedvoxError.
        """
        with open(path, "r") as toml_in:
            content: str = toml_in.read()
            try:
                return from_toml(RedVoxConfig, content)
            except Exception as e:
                raise errors.RedVoxError(
                    f"Error parsing RedVox configuration file: {e}"
                )

    @staticmethod
    def from_home() -> "RedVoxConfig":
        """
        Attempts to load the configuration file .redvox.toml from the user's home directory.
        :return: An instance of RedvoxConfig or raises a RedvoxError.
        """
        home_path: Path = Path.home()
        credentials_path: Path = home_path.joinpath(REDVOX_CONFIG_FILE_NAME)

        if not credentials_path.exists():
            raise errors.RedVoxError("RedVox configuration file does not exist")

        return RedVoxConfig.from_file(credentials_path)

    @staticmethod
    def find() -> Optional["RedVoxConfig"]:
        """
        Attempts to load the configuration either from the user's home directory or from the environment.
        :return: An instance of RedvoxConfig or raises a RedvoxError.
        """

        # First try to load the configuration from the user's home directory
        try:
            return RedVoxConfig.from_home()
        except errors.RedVoxError:
            pass

        # If that doesn't work, try to load the configuration from the environment
        try:
            return RedVoxConfig.from_env()
        except errors.RedVoxError:
            return None

    def save_to_file(self, path: Path) -> None:
        """
        Saves this configuration to the specified file path.
        :param path: Path to save this configuration to.
        """
        with open(path, "w") as toml_out:
            toml_out.write(to_toml(self))

    def save_to_home(self) -> Path:
        """
        Saves this configuration file to the user's home directory as .redvox.toml.
        :return: The path that the configuration was saved to.
        """
        home_path: Path = Path.home()
        credentials_path: Path = home_path.joinpath(REDVOX_CONFIG_FILE_NAME)
        self.save_to_file(credentials_path)
        return credentials_path

    def url(self, end_point: str) -> str:
        """
        Formats the API URL.
        :param end_point: Endpoint to use.
        :return: The formatted API URL.
        """
        return f"{self.protocol}://{self.host}:{self.port}{end_point}"

Classes

class RedVoxConfig (username: str, password: str, protocol: str = 'https', host: str = 'redvox.io', port: int = 8080, secret_token: Optional[str] = None)

Configuration options specific for accessing the cloud services.

Expand source code
@serialize
@deserialize
@dataclass
class RedVoxConfig:
    """
    Configuration options specific for accessing the cloud services.
    """

    username: str
    password: str
    protocol: str = "https"
    host: str = "redvox.io"
    port: int = 8080
    secret_token: Optional[str] = None

    @staticmethod
    def from_auth_token(
            auth_token: str,
            protocol: str = "https",
            host: str = "redvox.io",
            port: int = 8080,
            secret_token: Optional[str] = None) -> "RedVoxConfig":
        return RedVoxConfig("auth_token", auth_token, protocol, host, port, secret_token)

    @staticmethod
    def from_env() -> "RedVoxConfig":
        """
        Attempts to load the configuration from the environment.
        :return: An instance of RedvoxConfig or raises a RedvoxError.
        """
        # At least the username and password must be provided
        username: Optional[str] = os.environ.get(REDVOX_USERNAME_ENV_KEY)
        password: Optional[str] = os.environ.get(REDVOX_PASSWORD_ENV_KEY)

        if username is None:
            raise errors.RedVoxError(
                f"{REDVOX_USERNAME_ENV_KEY} is not in the environment"
            )

        if password is None:
            raise errors.RedVoxError(
                f"{REDVOX_PASSWORD_ENV_KEY} is not in the environment"
            )

        redvox_config: RedVoxConfig = RedVoxConfig(username, password)

        # If anything else is provided, overwrite the defaults
        protocol: Optional[str] = os.environ.get(REDVOX_PROTOCOL_ENV_KEY)
        if protocol is not None:
            redvox_config.protocol = protocol

        host: Optional[str] = os.environ.get(REDVOX_HOST_ENV_KEY)
        if host is not None:
            redvox_config.host = host

        port: Optional[str] = os.environ.get(REDVOX_PORT_ENV_KEY)
        if port is not None:
            # Make sure the port is actually an integer and parse it as such
            try:
                port_int: int = int(port)
                redvox_config.port = port_int
            except ValueError:
                raise errors.RedVoxError(
                    f"Provided environment variable={REDVOX_PORT_ENV_KEY} for port={port} is not integer"
                )

        secret_token: Optional[str] = os.environ.get(REDVOX_SECRET_TOKEN_ENV_KEY)
        if secret_token is not None:
            redvox_config.secret_token = secret_token

        return redvox_config

    @staticmethod
    def from_file(path: Path) -> "RedVoxConfig":
        """
        Attempts to load the configuration from a TOML file.
        :return: An instance of RedvoxConfig or raises a RedvoxError.
        """
        with open(path, "r") as toml_in:
            content: str = toml_in.read()
            try:
                return from_toml(RedVoxConfig, content)
            except Exception as e:
                raise errors.RedVoxError(
                    f"Error parsing RedVox configuration file: {e}"
                )

    @staticmethod
    def from_home() -> "RedVoxConfig":
        """
        Attempts to load the configuration file .redvox.toml from the user's home directory.
        :return: An instance of RedvoxConfig or raises a RedvoxError.
        """
        home_path: Path = Path.home()
        credentials_path: Path = home_path.joinpath(REDVOX_CONFIG_FILE_NAME)

        if not credentials_path.exists():
            raise errors.RedVoxError("RedVox configuration file does not exist")

        return RedVoxConfig.from_file(credentials_path)

    @staticmethod
    def find() -> Optional["RedVoxConfig"]:
        """
        Attempts to load the configuration either from the user's home directory or from the environment.
        :return: An instance of RedvoxConfig or raises a RedvoxError.
        """

        # First try to load the configuration from the user's home directory
        try:
            return RedVoxConfig.from_home()
        except errors.RedVoxError:
            pass

        # If that doesn't work, try to load the configuration from the environment
        try:
            return RedVoxConfig.from_env()
        except errors.RedVoxError:
            return None

    def save_to_file(self, path: Path) -> None:
        """
        Saves this configuration to the specified file path.
        :param path: Path to save this configuration to.
        """
        with open(path, "w") as toml_out:
            toml_out.write(to_toml(self))

    def save_to_home(self) -> Path:
        """
        Saves this configuration file to the user's home directory as .redvox.toml.
        :return: The path that the configuration was saved to.
        """
        home_path: Path = Path.home()
        credentials_path: Path = home_path.joinpath(REDVOX_CONFIG_FILE_NAME)
        self.save_to_file(credentials_path)
        return credentials_path

    def url(self, end_point: str) -> str:
        """
        Formats the API URL.
        :param end_point: Endpoint to use.
        :return: The formatted API URL.
        """
        return f"{self.protocol}://{self.host}:{self.port}{end_point}"

Class variables

var host : str
var password : str
var port : int
var protocol : str
var secret_token : Optional[str]
var username : str

Static methods

def find() ‑> Optional[RedVoxConfig]

Attempts to load the configuration either from the user's home directory or from the environment. :return: An instance of RedvoxConfig or raises a RedvoxError.

Expand source code
@staticmethod
def find() -> Optional["RedVoxConfig"]:
    """
    Attempts to load the configuration either from the user's home directory or from the environment.
    :return: An instance of RedvoxConfig or raises a RedvoxError.
    """

    # First try to load the configuration from the user's home directory
    try:
        return RedVoxConfig.from_home()
    except errors.RedVoxError:
        pass

    # If that doesn't work, try to load the configuration from the environment
    try:
        return RedVoxConfig.from_env()
    except errors.RedVoxError:
        return None
def from_auth_token(auth_token: str, protocol: str = 'https', host: str = 'redvox.io', port: int = 8080, secret_token: Optional[str] = None) ‑> RedVoxConfig
Expand source code
@staticmethod
def from_auth_token(
        auth_token: str,
        protocol: str = "https",
        host: str = "redvox.io",
        port: int = 8080,
        secret_token: Optional[str] = None) -> "RedVoxConfig":
    return RedVoxConfig("auth_token", auth_token, protocol, host, port, secret_token)
def from_env() ‑> RedVoxConfig

Attempts to load the configuration from the environment. :return: An instance of RedvoxConfig or raises a RedvoxError.

Expand source code
@staticmethod
def from_env() -> "RedVoxConfig":
    """
    Attempts to load the configuration from the environment.
    :return: An instance of RedvoxConfig or raises a RedvoxError.
    """
    # At least the username and password must be provided
    username: Optional[str] = os.environ.get(REDVOX_USERNAME_ENV_KEY)
    password: Optional[str] = os.environ.get(REDVOX_PASSWORD_ENV_KEY)

    if username is None:
        raise errors.RedVoxError(
            f"{REDVOX_USERNAME_ENV_KEY} is not in the environment"
        )

    if password is None:
        raise errors.RedVoxError(
            f"{REDVOX_PASSWORD_ENV_KEY} is not in the environment"
        )

    redvox_config: RedVoxConfig = RedVoxConfig(username, password)

    # If anything else is provided, overwrite the defaults
    protocol: Optional[str] = os.environ.get(REDVOX_PROTOCOL_ENV_KEY)
    if protocol is not None:
        redvox_config.protocol = protocol

    host: Optional[str] = os.environ.get(REDVOX_HOST_ENV_KEY)
    if host is not None:
        redvox_config.host = host

    port: Optional[str] = os.environ.get(REDVOX_PORT_ENV_KEY)
    if port is not None:
        # Make sure the port is actually an integer and parse it as such
        try:
            port_int: int = int(port)
            redvox_config.port = port_int
        except ValueError:
            raise errors.RedVoxError(
                f"Provided environment variable={REDVOX_PORT_ENV_KEY} for port={port} is not integer"
            )

    secret_token: Optional[str] = os.environ.get(REDVOX_SECRET_TOKEN_ENV_KEY)
    if secret_token is not None:
        redvox_config.secret_token = secret_token

    return redvox_config
def from_file(path: pathlib.Path) ‑> RedVoxConfig

Attempts to load the configuration from a TOML file. :return: An instance of RedvoxConfig or raises a RedvoxError.

Expand source code
@staticmethod
def from_file(path: Path) -> "RedVoxConfig":
    """
    Attempts to load the configuration from a TOML file.
    :return: An instance of RedvoxConfig or raises a RedvoxError.
    """
    with open(path, "r") as toml_in:
        content: str = toml_in.read()
        try:
            return from_toml(RedVoxConfig, content)
        except Exception as e:
            raise errors.RedVoxError(
                f"Error parsing RedVox configuration file: {e}"
            )
def from_home() ‑> RedVoxConfig

Attempts to load the configuration file .redvox.toml from the user's home directory. :return: An instance of RedvoxConfig or raises a RedvoxError.

Expand source code
@staticmethod
def from_home() -> "RedVoxConfig":
    """
    Attempts to load the configuration file .redvox.toml from the user's home directory.
    :return: An instance of RedvoxConfig or raises a RedvoxError.
    """
    home_path: Path = Path.home()
    credentials_path: Path = home_path.joinpath(REDVOX_CONFIG_FILE_NAME)

    if not credentials_path.exists():
        raise errors.RedVoxError("RedVox configuration file does not exist")

    return RedVoxConfig.from_file(credentials_path)

Methods

def save_to_file(self, path: pathlib.Path) ‑> None

Saves this configuration to the specified file path. :param path: Path to save this configuration to.

Expand source code
def save_to_file(self, path: Path) -> None:
    """
    Saves this configuration to the specified file path.
    :param path: Path to save this configuration to.
    """
    with open(path, "w") as toml_out:
        toml_out.write(to_toml(self))
def save_to_home(self) ‑> pathlib.Path

Saves this configuration file to the user's home directory as .redvox.toml. :return: The path that the configuration was saved to.

Expand source code
def save_to_home(self) -> Path:
    """
    Saves this configuration file to the user's home directory as .redvox.toml.
    :return: The path that the configuration was saved to.
    """
    home_path: Path = Path.home()
    credentials_path: Path = home_path.joinpath(REDVOX_CONFIG_FILE_NAME)
    self.save_to_file(credentials_path)
    return credentials_path
def url(self, end_point: str) ‑> str

Formats the API URL. :param end_point: Endpoint to use. :return: The formatted API URL.

Expand source code
def url(self, end_point: str) -> str:
    """
    Formats the API URL.
    :param end_point: Endpoint to use.
    :return: The formatted API URL.
    """
    return f"{self.protocol}://{self.host}:{self.port}{end_point}"