- gRPC service with MusicBrainz provider - PostgreSQL schema with migrations - Service layer with database-first caching - Repository pattern for data access - YAML configuration support - Research documentation for 17 music metadata projects
16 KiB
minim: Deployment
Deployment Model
minim is a Python library, not a deployable service. There is no server, no daemon, no container to deploy. Users install the library and import it into their own Python code.
Installation Target: Developer workstations, scripts, Jupyter notebooks, personal automation tools.
Not Applicable: Production web servers, cloud deployments, containerized services, serverless functions.
Installation Methods
From Source (Current)
Clone Repository:
git clone https://github.com/bbye98/minim.git
cd minim
Install in Development Mode:
python -m pip install -e .
Install in Production Mode:
python -m pip install .
Editable Install (-e):
- Changes to source code immediately reflected without reinstalling
- Useful for development and testing
- Creates symlink to source directory
Production Install:
- Copies files to site-packages
- Requires reinstall after code changes
- Cleaner for end users
Via Conda
Environment File:
# environment.yml
name: minim
channels:
- conda-forge
- defaults
dependencies:
- python>=3.9
- cryptography
- mutagen
- requests
- pip
- pip:
- -e .
Create Environment:
conda env create -f environment.yml
conda activate minim
Update Environment:
conda env update -f environment.yml
Via PyPI (Planned for v2)
Not Yet Available. minim is not published to PyPI as of v1.1.0.
Planned for v2:
pip install minim
Package Metadata (setup.py):
from setuptools import setup, find_packages
setup(
name="minim",
version="1.1.0",
author="Benjamin Ye",
author_email="bbye98@gmail.com",
description="Comprehensive music metadata library",
long_description=open("README.md").read(),
long_description_content_type="text/markdown",
url="https://github.com/bbye98/minim",
packages=find_packages(),
classifiers=[
"Development Status :: 4 - Beta",
"Intended Audience :: Developers",
"License :: OSI Approved :: GNU General Public License v3 (GPLv3)",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
],
python_requires=">=3.9",
install_requires=[
"cryptography",
"mutagen",
"requests",
],
extras_require={
"full": [
"ffmpeg-python",
"flask",
"levenshtein",
"numpy",
"pillow",
"playwright",
],
},
)
Dependencies
Required (Core)
cryptography:
- Purpose: TIDAL manifest decryption, secure token handling
- Version: Not pinned (latest compatible)
- Install:
pip install cryptography
mutagen:
- Purpose: Audio file metadata reading/writing
- Version: Not pinned
- Install:
pip install mutagen
requests:
- Purpose: HTTP client for all API calls
- Version: Not pinned
- Install:
pip install requests
Optional (Features)
ffmpeg:
- Purpose: Audio format conversion
- Type: System binary (not Python package)
- Install:
apt install ffmpeg(Ubuntu),brew install ffmpeg(macOS), download from ffmpeg.org (Windows) - Detection:
shutil.which("ffmpeg")
flask:
- Purpose: OAuth callback server (alternative to http.server)
- Install:
pip install flask
levenshtein:
- Purpose: Fuzzy string matching for search results
- Install:
pip install levenshtein
numpy:
- Purpose: Audio analysis features
- Install:
pip install numpy
pillow:
- Purpose: Image processing for album artwork
- Install:
pip install pillow
playwright:
- Purpose: Browser automation for OAuth flows
- Install:
pip install playwright && playwright install chromium
Dependency Management
No Lock File: minim does not use requirements.txt or Pipfile.lock for version pinning.
Version Constraints: None specified. Uses latest compatible versions.
Risk: Dependency updates may introduce breaking changes.
Recommendation for Production:
# Generate lock file
pip freeze > requirements.txt
# Install from lock file
pip install -r requirements.txt
System Requirements
Python Version
Minimum: Python 3.9
Tested: Python 3.9, 3.10, 3.11
Recommended: Python 3.11 (latest stable)
Version-Specific Features:
- Type hints (PEP 585):
list[str]instead ofList[str](requires 3.9+) - Union operator:
str | Noneinstead ofOptional[str](requires 3.10+, not used in v1)
Operating Systems
Supported:
- Linux (Ubuntu 20.04+, Debian 11+, Fedora 35+, Arch)
- macOS (10.15 Catalina+)
- Windows (10, 11)
Tested in CI: Ubuntu 22.04 (GitHub Actions)
Platform-Specific Considerations:
Linux:
- FFmpeg available via package manager (
apt,dnf,pacman) - Config file at
~/.minim.cfgor/home/username/minim.cfg
macOS:
- FFmpeg via Homebrew (
brew install ffmpeg) - Config file at
~/minim.cfgor/Users/username/minim.cfg
Windows:
- FFmpeg requires manual download and PATH configuration
- Config file at
C:\Users\username\minim.cfg - Path handling uses
os.path.expanduser("~")(cross-platform)
External Dependencies
FFmpeg (Optional):
- Required for audio format conversion
- Not required for metadata reading/writing or API access
- Version: 4.0+ recommended
Browser (Optional):
- Required for OAuth flows using Playwright
- Chromium installed via
playwright install chromium - Not required for http.server or Flask callback methods
Configuration
Environment Variables
minim checks environment variables for credentials:
Discogs:
DISCOGS_CONSUMER_KEYDISCOGS_CONSUMER_SECRETDISCOGS_ACCESS_TOKENDISCOGS_ACCESS_TOKEN_SECRETDISCOGS_PERSONAL_ACCESS_TOKEN
Qobuz:
QOBUZ_APP_IDQOBUZ_APP_SECRETQOBUZ_EMAILQOBUZ_PASSWORD
Spotify:
SPOTIFY_CLIENT_IDSPOTIFY_CLIENT_SECRETSPOTIFY_REDIRECT_URI
TIDAL:
TIDAL_CLIENT_IDTIDAL_CLIENT_SECRETTIDAL_REDIRECT_URI
Precedence: Environment variables > config file > constructor parameters
Use Case: CI/CD pipelines, containerized environments, shared systems
Example:
export SPOTIFY_CLIENT_ID="abc123"
export SPOTIFY_CLIENT_SECRET="def456"
python script.py # Automatically uses environment variables
Config File
Location: ~/minim.cfg
Format: INI-style (ConfigParser)
Auto-Creation: Created automatically when tokens are saved via set_access_token()
Manual Creation:
[spotify]
client_id = abc123
client_secret = def456
access_token = BQC...
refresh_token = AQD...
expires_at = 1672531200
Permissions: Default (0644 on Unix). Recommendation: chmod 600 ~/minim.cfg for security.
CI/CD
GitHub Actions
Workflow File: .github/workflows/ci.yml
name: CI
on:
push:
branches: [main, dev]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.9'
- name: Install FFmpeg
run: sudo apt-get update && sudo apt-get install -y ffmpeg
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -e .
pip install pytest ruff
- name: Lint with ruff
run: ruff check .
- name: Run tests
env:
SPOTIFY_CLIENT_ID: ${{ secrets.SPOTIFY_CLIENT_ID }}
SPOTIFY_CLIENT_SECRET: ${{ secrets.SPOTIFY_CLIENT_SECRET }}
TIDAL_CLIENT_ID: ${{ secrets.TIDAL_CLIENT_ID }}
TIDAL_CLIENT_SECRET: ${{ secrets.TIDAL_CLIENT_SECRET }}
run: pytest tests/
Secrets Management:
- API credentials stored in GitHub Secrets
- Accessed via
${{ secrets.SECRET_NAME }} - Not exposed in logs
Test Execution:
- Real API calls (not mocked)
- Requires valid credentials
- May fail if rate limits exceeded or services change APIs
Linting:
ruff: Fast Python linter (replaces flake8, pylint)- Configuration in
pyproject.tomlorruff.toml
Coverage
Tool: coverage.py
Configuration: .coveragerc
[run]
source = minim
omit =
*/tests/*
*/__init__.py
*/site-packages/*
[report]
exclude_lines =
pragma: no cover
def __repr__
raise AssertionError
raise NotImplementedError
if __name__ == .__main__.:
Execution:
coverage run -m pytest tests/
coverage report
coverage html # Generate HTML report
Current Coverage: Not documented in repository. Likely 60-80% based on test file count.
Documentation
ReadTheDocs
URL: https://minim.readthedocs.io
Build System: Sphinx
Configuration: docs/conf.py
project = 'minim'
author = 'Benjamin Ye'
release = '1.1.0'
extensions = [
'sphinx.ext.autodoc',
'sphinx.ext.napoleon',
'sphinx.ext.viewcode',
]
html_theme = 'sphinx_rtd_theme'
Auto-Deploy:
- Triggered on push to
mainbranch - Builds from
docs/directory - Parses docstrings from source code
Docstring Format: Google-style
def search(self, query: str, types: list[str] = ["track"]) -> dict:
"""
Search Spotify catalog.
Args:
query: Search query string
types: Result types (track, album, artist, playlist)
Returns:
Dict with type-specific results arrays
Raises:
RuntimeError: If API request fails
Example:
>>> api = WebAPI(client_id="...", client_secret="...")
>>> results = api.search("Radiohead", types=["artist"])
>>> print(results["artists"]["items"][0]["name"])
Radiohead
"""
Local Documentation Build
cd docs
pip install sphinx sphinx_rtd_theme
make html
open _build/html/index.html
Versioning
Scheme: Semantic Versioning (SemVer)
Format: MAJOR.MINOR.PATCH
Current Version: 1.1.0
Version History:
- 1.0.0: Initial release
- 1.1.0: Bug fixes, minor feature additions
Version Location: minim/__init__.py
__version__ = "1.1.0"
Git Tags:
git tag v1.1.0
git push origin v1.1.0
Release Process
Current (Manual):
- Update version in
minim/__init__.py - Update
CHANGELOG.md(if exists) - Commit changes:
git commit -m "Bump version to 1.1.0" - Create tag:
git tag v1.1.0 - Push:
git push origin main --tags - GitHub automatically triggers ReadTheDocs build
Planned for v2 (Automated):
- Create release branch:
git checkout -b release/1.2.0 - Update version and changelog
- Open pull request
- Merge to main
- GitHub Actions workflow:
- Run tests
- Build package:
python -m build - Publish to PyPI:
twine upload dist/* - Create GitHub release with changelog
- Trigger ReadTheDocs build
Distribution Channels
Current
GitHub Releases:
- Source code archives (
.tar.gz,.zip) - No pre-built binaries
- Download: https://github.com/bbye98/minim/releases
ReadTheDocs:
- Documentation only
- No package distribution
Planned (v2)
PyPI:
pip install minim- Versioned releases
- Automatic dependency resolution
Conda-Forge:
conda install -c conda-forge minim- Cross-platform binaries
- Dependency management via conda
Containerization
Not Applicable: minim is a library, not a service.
Hypothetical Use Case: Containerized script using minim
Dockerfile:
FROM python:3.11-slim
# Install FFmpeg
RUN apt-get update && apt-get install -y ffmpeg && rm -rf /var/lib/apt/lists/*
# Install minim
WORKDIR /app
COPY . .
RUN pip install --no-cache-dir -e .
# Run script
CMD ["python", "script.py"]
Docker Compose:
version: '3.8'
services:
minim-script:
build: .
environment:
- SPOTIFY_CLIENT_ID=${SPOTIFY_CLIENT_ID}
- SPOTIFY_CLIENT_SECRET=${SPOTIFY_CLIENT_SECRET}
volumes:
- ./audio:/app/audio
- ./config:/root/.minim.cfg
Monitoring and Logging
Not Applicable: minim is a library. Monitoring and logging are the responsibility of the calling application.
Library Behavior:
- No built-in logging (uses
warningsmodule for non-critical issues) - Errors raised as exceptions (caller handles logging)
- No metrics, no telemetry, no health checks
Caller Responsibility:
import logging
from minim import spotify
# Configure logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
# Use minim with logging
try:
api = spotify.WebAPI(client_id="...", client_secret="...")
api.set_flow("client_credentials")
api.set_access_token()
results = api.search("Radiohead", types=["artist"])
logger.info(f"Found {len(results['artists']['items'])} artists")
except RuntimeError as e:
logger.error(f"API error: {e}")
except Exception as e:
logger.exception(f"Unexpected error: {e}")
Security Considerations
Credential Storage
Risk: Plain text tokens in ~/minim.cfg
Mitigation (Not Implemented):
- Encrypt config file
- Use OS keychain (Keyring library)
- Use environment variables only
- Set restrictive file permissions (
chmod 600)
Dependency Vulnerabilities
Risk: Outdated dependencies with known CVEs
Mitigation:
# Scan for vulnerabilities
pip install safety
safety check
# Update dependencies
pip install --upgrade cryptography mutagen requests
API Key Exposure
Risk: Hardcoded credentials in scripts
Mitigation:
- Use environment variables
- Use config file outside version control
- Add
minim.cfgto.gitignore
Private API Usage
Risk: Terms of service violations (Qobuz, TIDAL, Spotify lyrics)
Mitigation:
- Use only public APIs in production
- Document risks in README
- Obtain official API access if possible
Scalability
Not Applicable: minim is a library for personal use, not a scalable service.
Limitations:
- Synchronous, blocking operations
- No connection pooling
- No rate limiting
- No caching
- Single-threaded
For High-Volume Use:
- Implement async version using
aiohttp - Add connection pooling
- Implement rate limiting and backoff
- Cache API responses (Redis, Memcached)
- Use task queue (Celery, RQ) for background processing
Backup and Recovery
Config File Backup:
# Backup
cp ~/minim.cfg ~/minim.cfg.backup
# Restore
cp ~/minim.cfg.backup ~/minim.cfg
Recommendation: Exclude from cloud backup (contains sensitive tokens) or encrypt backups.
Maintenance
Current Status: v1 in maintenance mode
Maintenance Activities:
- Bug fixes for critical issues
- Security updates for dependencies
- No new features
Active Development: v2 rewrite on dev branch
Support Channels:
- GitHub Issues: https://github.com/bbye98/minim/issues
- GitHub Discussions: https://github.com/bbye98/minim/discussions
Summary
minim deployment is straightforward:
- Install from source:
git clone+pip install -e . - Configure credentials: Environment variables or
~/minim.cfg - Import and use:
from minim import spotify
No server deployment, no containers, no orchestration. The library runs in the caller's Python process.
For production use cases requiring scalability, security, and robustness, consider:
- Wrapping minim in a web service (Flask, FastAPI)
- Implementing async operations
- Adding rate limiting and caching
- Using secure credential storage
- Monitoring and logging
The v2 rewrite addresses many deployment concerns (PyPI publication, async support, secure storage) while maintaining the simple library architecture.