CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-beets

A comprehensive music library management system and command-line application for organizing and maintaining digital music collections

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

configuration.mddocs/

Configuration

Global configuration management with YAML-based settings, environment variable support, and plugin configuration integration. The configuration system provides flexible, hierarchical settings management for all aspects of beets functionality.

Capabilities

Global Configuration Object

The central configuration instance that manages all beets settings.

config: IncludeLazyConfig  # Global configuration object available as beets.config

class IncludeLazyConfig:
    """Configuration class with lazy loading and include support."""
    
    def read(self, user: bool = True, defaults: bool = True) -> None:
        """
        Read configuration from files.
        
        Parameters:
        - user: Whether to read user configuration file
        - defaults: Whether to read default configuration
        """
    
    def set_file(self, filename: str) -> None:
        """
        Load additional configuration from file.
        
        Parameters:
        - filename: Path to YAML configuration file
        """
    
    def set_args(self, args: argparse.Namespace) -> None:
        """
        Set configuration from command-line arguments.
        
        Parameters:
        - args: Parsed command-line arguments
        """
    
    def __getitem__(self, key: str) -> ConfigView:
        """
        Get configuration section or value.
        
        Parameters:
        - key: Configuration key or section name
        
        Returns:
        ConfigView object for further access
        """
    
    def user_config_path(self) -> str:
        """
        Get path to user configuration file.
        
        Returns:
        Path to user's config.yaml file
        """
    
    def config_dir(self) -> str:
        """
        Get beets configuration directory path.
        
        Returns:
        Path to beets configuration directory
        """

Configuration Views

Objects representing configuration sections and values with type conversion.

class ConfigView:
    """View into configuration hierarchy with type conversion."""
    
    def get(self, typ: Type = None) -> Any:
        """
        Get configuration value with optional type conversion.
        
        Parameters:
        - typ: Type to convert value to (str, int, bool, list, dict)
        
        Returns:
        Configuration value converted to specified type
        """
    
    def as_str(self) -> str:
        """
        Get configuration value as string.
        
        Returns:
        String representation of configuration value
        """
    
    def as_filename(self) -> str:
        """
        Get configuration value as filename with path expansion.
        
        Returns:
        Expanded filename path
        """
    
    def as_str_seq(self, split: bool = True) -> List[str]:
        """
        Get configuration value as list of strings.
        
        Parameters:
        - split: Whether to split string values on whitespace/commas
        
        Returns:
        List of string values
        """
    
    def __getitem__(self, key: str) -> 'ConfigView':
        """
        Get nested configuration section.
        
        Parameters:
        - key: Nested key name
        
        Returns:
        ConfigView for nested section
        """
    
    def items(self) -> Iterator[Tuple[str, 'ConfigView']]:
        """
        Iterate over configuration key-value pairs.
        
        Returns:
        Iterator of (key, ConfigView) tuples
        """
    
    def keys(self) -> Iterator[str]:
        """
        Get all configuration keys in this section.
        
        Returns:
        Iterator over key names
        """

Core Configuration Sections

Library Configuration

Settings for database and music directory management.

# Library database file path
library: ~/.config/beets/musiclibrary.db

# Root directory for music files  
directory: ~/Music

# Path format templates
paths:
  default: $albumartist/$album/$track $title
  singleton: Non-Album/$artist - $title
  comp: Compilations/$album/$track $title
  albumtype:soundtrack: Soundtracks/$album/$track $title
  albumtype:live: Live/$albumartist/$album/$track $title
# Access library configuration
from beets import config

library_path = config['library'].as_filename()
music_dir = config['directory'].as_filename()
path_formats = config['paths'].get(dict)

Import Configuration

Settings controlling the import process and metadata handling.

import:
  # Write tags to files after import
  write: yes
  
  # Copy files vs move files
  copy: no
  
  # Resume interrupted imports
  resume: ask
  
  # Skip unchanged directories
  incremental: no
  
  # Quiet fallback for timeouts
  quiet_fallback: skip
  
  # Default action for ambiguous matches
  timid: no
  
  # Enabled metadata sources
  sources: [filesystem, musicbrainz, discogs]
  
  # Search by specific IDs
  search_ids: []
# Access import configuration
from beets import config

write_tags = config['import']['write'].get(bool)
copy_files = config['import']['copy'].get(bool)
resume_mode = config['import']['resume'].get(str)
sources = config['import']['sources'].as_str_seq()

UI Configuration

User interface settings including colors and terminal behavior.

ui:
  # Enable terminal colors
  color: yes
  
  # Terminal width override
  terminal_width: 80
  
  # Color scheme
  colors:
    text_success: [green]
    text_warning: [yellow]
    text_error: [red]
    text_highlight: [bold, blue]
    action_default: [bold, turquoise]
    action: [turquoise]
# Access UI configuration
from beets import config

color_enabled = config['ui']['color'].get(bool)
terminal_width = config['ui']['terminal_width'].get(int)
colors = config['ui']['colors'].get(dict)

Plugin Configuration

Plugin loading and individual plugin settings.

plugins: 
  - fetchart
  - lyrics
  - discogs
  - replaygain
  - web

# Plugin-specific configuration
fetchart:
  auto: yes
  sources: coverart lastfm amazon
  minwidth: 300
  
lyrics:
  auto: yes
  sources: genius lyricwiki musixmatch
  
web:
  host: 127.0.0.1
  port: 8337
# Access plugin configuration
from beets import config

enabled_plugins = config['plugins'].as_str_seq()
fetchart_auto = config['fetchart']['auto'].get(bool)
fetchart_sources = config['fetchart']['sources'].as_str_seq()
web_host = config['web']['host'].get(str)
web_port = config['web']['port'].get(int)

Configuration File Management

Configuration File Locations

# Default configuration file locations
# Linux/macOS: ~/.config/beets/config.yaml
# Windows: %APPDATA%\beets\config.yaml

from beets import config

# Get configuration file path
config_path = config.user_config_path()

# Get configuration directory
config_dir = config.config_dir()

# Get default config values
default_config = config.default_config_path()

Loading Configuration

from beets import config

# Load default configuration
config.read()

# Load additional config file
config.set_file('/path/to/additional/config.yaml')

# Set values from command line
import argparse
parser = argparse.ArgumentParser()
args = parser.parse_args()
config.set_args(args)

Include System

The configuration system supports including other YAML files.

# Main config.yaml
include:
  - paths.yaml
  - plugins.yaml
  - colors.yaml

library: ~/.config/beets/musiclibrary.db
directory: ~/Music
# paths.yaml
paths:
  default: $albumartist/$album/$track $title
  classical: Classical/$composer/$album/$track $title
  
# plugins.yaml  
plugins:
  - fetchart
  - lyrics
  - discogs
  
fetchart:
  auto: yes
  sources: coverart lastfm

Configuration Access Patterns

Type-Safe Value Access

from beets import config

# String values
library_path = config['library'].as_filename()
music_dir = config['directory'].as_filename()

# Boolean values  
write_tags = config['import']['write'].get(bool)
color_enabled = config['ui']['color'].get(bool)

# Integer values
terminal_width = config['ui']['terminal_width'].get(int)
web_port = config['web']['port'].get(int)

# List values
plugins = config['plugins'].as_str_seq()
sources = config['import']['sources'].as_str_seq()

# Dictionary values
paths = config['paths'].get(dict)
colors = config['ui']['colors'].get(dict)

Default Values and Fallbacks

from beets import config

# Provide default values
timeout = config['import']['timeout'].get(int, 5)
max_width = config['ui']['max_width'].get(int, 80)

# Check if value exists
if 'api_key' in config['discogs']:
    api_key = config['discogs']['api_key'].get(str)
else:
    print("No Discogs API key configured")

# Conditional configuration
if config['import']['write'].get(bool):
    # Enable tag writing
    pass

Plugin Configuration Access

from beets import config
from beets.plugins import BeetsPlugin

class MyPlugin(BeetsPlugin):
    def __init__(self, name):
        super().__init__(name)
        
        # Set plugin defaults
        config[name].add({
            'enabled': True,
            'timeout': 10,
            'sources': ['default'],
        })
    
    def get_config_value(self, key, default=None):
        """Get plugin-specific configuration value."""
        return config[self.name][key].get(default)
    
    def is_enabled(self):
        """Check if plugin is enabled."""
        return self.get_config_value('enabled', True)

Environment Variable Support

Configuration values can reference environment variables and support path expansion.

# Environment variable expansion
library: $BEETS_LIBRARY_PATH
directory: $MUSIC_DIR

# Path expansion  
library: ~/beets/library.db
directory: ~/Music

# Mixed expansion
directory: $HOME/Music/Library
import os
from beets import config

# Set environment variables
os.environ['BEETS_LIBRARY_PATH'] = '/custom/path/library.db'
os.environ['MUSIC_DIR'] = '/mnt/music'

# Configuration will automatically expand these
library_path = config['library'].as_filename()
# Result: '/custom/path/library.db'

Dynamic Configuration

Runtime Configuration Changes

from beets import config

# Modify configuration at runtime
config['import']['write'] = True
config['ui']['color'] = False

# Add new sections
config['mycustom'] = {
    'setting1': 'value1',
    'setting2': 42
}

# Plugin configuration
config['myplugin']['enabled'] = True

Temporary Configuration Context

from beets import config
import contextlib

@contextlib.contextmanager
def temp_config(**overrides):
    """Temporarily override configuration values."""
    old_values = {}
    
    for key, value in overrides.items():
        old_values[key] = config[key].get()
        config[key] = value
    
    try:
        yield
    finally:
        for key, old_value in old_values.items():
            config[key] = old_value

# Usage
with temp_config(import_write=False, ui_color=True):
    # Configuration temporarily modified
    perform_operation()
# Configuration restored

Configuration Validation

Type Validation

from beets import config
import confuse

def validate_config():
    """Validate configuration values."""
    
    try:
        # Validate required settings
        library_path = config['library'].as_filename()
        if not library_path:
            raise ValueError("Library path is required")
        
        # Validate numeric ranges
        port = config['web']['port'].get(int)
        if not 1024 <= port <= 65535:
            raise ValueError(f"Invalid port number: {port}")
        
        # Validate choices
        log_level = config['log_level'].get(str, 'INFO')
        if log_level not in ['DEBUG', 'INFO', 'WARNING', 'ERROR']:
            raise ValueError(f"Invalid log level: {log_level}")
            
    except confuse.ConfigError as e:
        print(f"Configuration error: {e}")
        raise

Custom Validation

from beets import config
from beets.plugins import BeetsPlugin

class ValidatedPlugin(BeetsPlugin):
    def __init__(self, name):
        super().__init__(name)
        
        # Set defaults with validation
        config[name].add({
            'timeout': 10,
            'retries': 3,
            'sources': ['default']
        })
        
        self.validate_config()
    
    def validate_config(self):
        """Validate plugin configuration."""
        timeout = config[self.name]['timeout'].get(int)
        if timeout <= 0:
            raise ValueError(f"{self.name}: timeout must be positive")
        
        retries = config[self.name]['retries'].get(int)
        if retries < 0:
            raise ValueError(f"{self.name}: retries cannot be negative")
        
        sources = config[self.name]['sources'].as_str_seq()
        if not sources:
            raise ValueError(f"{self.name}: at least one source required")

Error Handling

class ConfigError(Exception):
    """Base exception for configuration errors."""

class ConfigTypeError(ConfigError):
    """Raised when configuration value has wrong type."""

class ConfigReadError(ConfigError):
    """Raised when configuration file cannot be read."""

Configuration Error Examples

from beets import config
import confuse

def safe_config_access():
    """Safely access configuration with error handling."""
    
    try:
        # Access configuration values
        library_path = config['library'].as_filename()
        plugins = config['plugins'].as_str_seq()
        
    except confuse.NotFoundError:
        print("Required configuration section not found")
        
    except confuse.ConfigTypeError as e:
        print(f"Configuration type error: {e}")
        
    except confuse.ConfigReadError as e:
        print(f"Cannot read configuration file: {e}")

This comprehensive configuration system provides flexible, type-safe access to all beets settings with support for environment variables, includes, validation, and runtime modification.

Install with Tessl CLI

npx tessl i tessl/pypi-beets

docs

configuration.md

import-autotag.md

index.md

library-management.md

plugin-system.md

query-system.md

user-interface.md

utilities-templates.md

tile.json