CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-mopidy

Mopidy is an extensible music server written in Python

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

configuration.mddocs/

Configuration System

Mopidy's configuration system provides schema-based configuration management with validation, type safety, and support for multiple configuration sources. It enables both core functionality and extensions to define, validate, and access configuration settings in a consistent manner.

Capabilities

Configuration Loading and Management

Core functions for loading, parsing, and managing configuration from multiple sources.

def load(files, ext_schemas, ext_defaults, overrides):
    """
    Load configuration from multiple sources.
    
    Parameters:
    - files (list[str]): Configuration file paths
    - ext_schemas (list[ConfigSchema]): Extension schemas
    - ext_defaults (list[str]): Extension default configs
    - overrides (list[tuple]): Command-line overrides
    
    Returns:
    - tuple[dict, dict]: (config, errors) - Parsed config and validation errors
    """
    ...

def format(config, ext_schemas, comments=None, display=True):
    """
    Format configuration for display or output.
    
    Parameters:
    - config (dict): Configuration to format
    - ext_schemas (list[ConfigSchema]): Extension schemas
    - comments (dict, optional): Comments to include
    - display (bool): Whether to format for display
    
    Returns:
    - str: Formatted configuration string
    """
    ...

def format_initial(extensions_data):
    """
    Format initial configuration template with defaults.
    
    Parameters:
    - extensions_data (list[ExtensionData]): Extension data
    
    Returns:
    - str: Initial configuration template
    """
    ...

def read(config_file):
    """
    Read configuration file content.
    
    Parameters:
    - config_file (str): Path to configuration file
    
    Returns:
    - str: Configuration file content
    """
    ...

Usage example:

from mopidy import config

# Load configuration
config_data, errors = config.load(
    files=["/etc/mopidy/mopidy.conf", "~/.config/mopidy/mopidy.conf"],
    ext_schemas=[spotify_schema, local_schema],
    ext_defaults=[spotify_defaults, local_defaults],
    overrides=[("core", "cache_dir", "/tmp/mopidy")]
)

if errors:
    print("Configuration errors:", errors)

Configuration Schemas

Schema definition system for validating and organizing configuration sections.

class ConfigSchema:
    """
    Configuration schema for a section.
    
    Parameters:
    - name (str): Schema section name
    """
    def __init__(self, name): ...
    
    name: str  # Section name
    
    def __setitem__(self, key, value):
        """
        Add configuration field to schema.
        
        Parameters:
        - key (str): Configuration key
        - value (ConfigValue): Field validator
        """
        ...
    
    def __getitem__(self, key):
        """Get configuration field validator."""
        ...
    
    def deserialize(self, values):
        """
        Deserialize configuration values.
        
        Parameters:
        - values (dict): Raw configuration values
        
        Returns:
        - tuple[dict, dict]: (parsed_values, errors)
        """
        ...
    
    def serialize(self, values, display=False):
        """
        Serialize configuration values.
        
        Parameters:
        - values (dict): Configuration values to serialize
        - display (bool): Whether formatting for display
        
        Returns:
        - dict: Serialized values
        """
        ...

class MapConfigSchema(ConfigSchema):
    """
    Schema for map-like configuration sections.
    
    Parameters:
    - name (str): Schema section name
    - value_type (ConfigValue): Validator for all values
    """
    def __init__(self, name, value_type): ...

Usage example:

from mopidy.config.schemas import ConfigSchema
from mopidy.config.types import String, Integer, Boolean, Secret

# Define schema for an extension
schema = ConfigSchema("spotify")
schema["username"] = String()
schema["password"] = Secret()  # Hidden in output
schema["enabled"] = Boolean()
schema["timeout"] = Integer(minimum=1, maximum=300)
schema["playlists"] = List()

Configuration Value Types

Strongly-typed configuration value validators with built-in validation and conversion.

class ConfigValue:
    """Base class for configuration value types."""
    
    def __init__(self, optional=False):
        """
        Initialize config value.
        
        Parameters:
        - optional (bool): Whether value is optional
        """
        ...
    
    def deserialize(self, value):
        """
        Convert string value to Python type.
        
        Parameters:
        - value (str): Raw configuration value
        
        Returns:
        - tuple[Any, str]: (converted_value, error_message)
        """
        ...
    
    def serialize(self, value, display=False):
        """
        Convert Python value to string.
        
        Parameters:
        - value: Python value to serialize
        - display (bool): Whether formatting for display
        
        Returns:
        - str: Serialized value
        """
        ...

class String(ConfigValue):
    """String configuration value."""
    def __init__(self, optional=False, choices=None): ...

class Integer(ConfigValue):
    """
    Integer configuration value.
    
    Parameters:
    - optional (bool): Whether value is optional
    - minimum (int, optional): Minimum allowed value
    - maximum (int, optional): Maximum allowed value
    """
    def __init__(self, optional=False, minimum=None, maximum=None): ...

class Float(ConfigValue):
    """
    Float configuration value.
    
    Parameters:
    - optional (bool): Whether value is optional
    - minimum (float, optional): Minimum allowed value
    - maximum (float, optional): Maximum allowed value
    """
    def __init__(self, optional=False, minimum=None, maximum=None): ...

class Boolean(ConfigValue):
    """Boolean configuration value (true/false, yes/no, 1/0)."""
    def __init__(self, optional=False): ...

class List(ConfigValue):
    """
    List configuration value (comma-separated).
    
    Parameters:
    - optional (bool): Whether value is optional
    - separator (str): List item separator (default: comma)
    """
    def __init__(self, optional=False, separator=","): ...

class Pair(ConfigValue):
    """
    Key-value pair configuration value.
    
    Parameters:
    - optional (bool): Whether value is optional
    - separator (str): Key-value separator (default: pipe)
    """
    def __init__(self, optional=False, separator="|"): ...

class Secret(ConfigValue):
    """Secret configuration value (hidden in output)."""
    def __init__(self, optional=False): ...

class Path(ConfigValue):
    """File system path configuration value."""
    def __init__(self, optional=False): ...

class Hostname(ConfigValue):
    """Network hostname configuration value."""
    def __init__(self, optional=False): ...

class Port(ConfigValue):
    """
    Network port configuration value.
    
    Parameters:
    - optional (bool): Whether value is optional
    - choices (list[int], optional): Allowed port numbers
    """
    def __init__(self, optional=False, choices=None): ...

class LogLevel(ConfigValue):
    """Logging level configuration value."""
    def __init__(self, optional=False): ...

class LogColor(ConfigValue):
    """Log color configuration value."""
    def __init__(self, optional=False): ...

Usage example:

# Configure different value types
schema["server_host"] = Hostname()
schema["server_port"] = Port(choices=[8080, 8081, 8082])
schema["log_level"] = LogLevel()
schema["api_timeout"] = Integer(minimum=1, maximum=300)
schema["cache_dir"] = Path()
schema["enabled_formats"] = List()
schema["database_url"] = Secret()  # Won't be shown in config output

Deprecated Configuration Handling

Support for handling deprecated configuration options with warnings and migration.

class Deprecated(ConfigValue):
    """Marks a configuration option as deprecated."""
    def __init__(self, message=None): ...

class DeprecatedValue:
    """Wrapper for deprecated configuration values."""
    def __init__(self, value, message): ...

Usage example:

# Mark old configuration options as deprecated
schema["old_option"] = Deprecated("Use 'new_option' instead")
schema["legacy_setting"] = Deprecated()

Configuration Proxy

Proxy object providing convenient access to nested configuration values.

class Proxy:
    """
    Configuration proxy for convenient access to nested values.
    
    Parameters:
    - data (dict): Configuration data to wrap
    """
    def __init__(self, data): ...
    
    def __getitem__(self, key): ...
    def __iter__(self): ...
    def __len__(self): ...
    def __repr__(self): ...

Usage example:

config_proxy = Proxy(config_data)

# Access nested configuration values
cache_dir = config_proxy["core"]["cache_dir"]
spotify_username = config_proxy["spotify"]["username"]

# Proxy maintains dict-like interface
for section_name in config_proxy:
    section = config_proxy[section_name]
    print(f"Section {section_name} has {len(section)} options")

Core Configuration Schemas

Built-in configuration schemas for Mopidy's core functionality.

# Core system configuration
_core_schema = ConfigSchema("core")
_core_schema["cache_dir"] = Path()
_core_schema["config_dir"] = Path()
_core_schema["data_dir"] = Path()
_core_schema["max_tracklist_length"] = Integer(minimum=1)
_core_schema["restore_state"] = Boolean(optional=True)

# Logging configuration
_logging_schema = ConfigSchema("logging")
_logging_schema["verbosity"] = Integer(minimum=-1, maximum=4)
_logging_schema["format"] = String()
_logging_schema["color"] = Boolean()
_logging_schema["config_file"] = Path(optional=True)

# Audio system configuration
_audio_schema = ConfigSchema("audio")
_audio_schema["mixer"] = String()
_audio_schema["mixer_volume"] = Integer(optional=True, minimum=0, maximum=100)
_audio_schema["output"] = String()
_audio_schema["buffer_time"] = Integer(optional=True, minimum=1)

# HTTP proxy configuration
_proxy_schema = ConfigSchema("proxy")
_proxy_schema["scheme"] = String(optional=True, choices=["http", "https", "socks4", "socks5"])
_proxy_schema["hostname"] = Hostname(optional=True)
_proxy_schema["port"] = Port(optional=True)
_proxy_schema["username"] = String(optional=True)
_proxy_schema["password"] = Secret(optional=True)

# Per-module log levels
_loglevels_schema = MapConfigSchema("loglevels", LogLevel())

# Per-module log colors  
_logcolors_schema = MapConfigSchema("logcolors", LogColor())

Configuration File Locations

Standard configuration file search paths and loading order:

# Standard configuration locations (in search order):
# 1. /etc/mopidy/mopidy.conf
# 2. /etc/mopidy/conf.d/*.conf  
# 3. $XDG_CONFIG_HOME/mopidy/mopidy.conf (defaults to ~/.config/mopidy/mopidy.conf)
# 4. $XDG_CONFIG_HOME/mopidy/conf.d/*.conf
# 5. Command-line overrides

# Configuration can also be loaded from directories:
config_data, errors = config.load(
    files=[
        "/etc/mopidy/mopidy.conf",
        "/etc/mopidy/conf.d/",  # Will load all .conf files
        "~/.config/mopidy/mopidy.conf"
    ],
    ext_schemas=schemas,
    ext_defaults=defaults,
    overrides=[]
)

Configuration Validation and Error Handling

Comprehensive validation with detailed error reporting:

# Configuration loading returns both config and errors
config_data, errors = config.load(files, schemas, defaults, overrides)

# Errors are organized by section
if errors:
    for section_name, section_errors in errors.items():
        print(f"Errors in [{section_name}]:")
        for field, error_msg in section_errors.items():
            print(f"  {field}: {error_msg}")

# Example error output:
# Errors in [spotify]:
#   username: Required field is missing
#   timeout: Value must be between 1 and 300

Environment Integration

Integration with environment variables and system paths:

import os
from pathlib import Path

# Environment variable support in configuration
config_template = """
[core]
cache_dir = ${XDG_CACHE_HOME}/mopidy
data_dir = ${XDG_DATA_HOME}/mopidy

[myext]
api_key = ${MYEXT_API_KEY}
"""

# Path expansion and validation
path_config = Path()
expanded_path = path_config.deserialize("~/music")  # Expands to full path

Configuration Best Practices

Extension Configuration Design

from mopidy.config.schemas import ConfigSchema
from mopidy.config.types import String, Integer, Boolean, Secret, List

class MyExtension(Extension):
    def get_config_schema(self):
        schema = super().get_config_schema()
        
        # Required settings
        schema["api_key"] = Secret()  # Never shown in output
        schema["endpoint"] = String()
        
        # Optional settings with defaults
        schema["timeout"] = Integer(minimum=1, maximum=300)
        schema["max_results"] = Integer(minimum=1, maximum=1000)
        schema["enabled"] = Boolean()
        
        # List and choice settings
        schema["supported_formats"] = List()
        schema["quality"] = String(choices=["low", "medium", "high"])
        
        return schema
    
    def get_default_config(self):
        return """\
[myext]
enabled = true
api_key = 
endpoint = https://api.example.com
timeout = 30
max_results = 100
supported_formats = mp3, flac, ogg
quality = medium
"""

Configuration Access in Extensions

class MyBackend(Backend):
    def __init__(self, config, audio):
        super().__init__(config, audio)
        
        # Access extension configuration
        ext_config = config["myext"]
        self.api_key = ext_config["api_key"]
        self.endpoint = ext_config["endpoint"]
        self.timeout = ext_config["timeout"]
        
        # Validate required settings
        if not self.api_key:
            raise ExtensionError("MyExt requires api_key configuration")

Dynamic Configuration Updates

# Configuration can be reloaded at runtime
def reload_config():
    new_config, errors = config.load(
        files=config_files,
        ext_schemas=schemas,
        ext_defaults=defaults,
        overrides=[]
    )
    
    if not errors:
        # Update components with new configuration
        update_backends(new_config)
        update_frontends(new_config)

docs

audio-system.md

backend-system.md

configuration.md

core-controllers.md

extension-system.md

index.md

models.md

tile.json