Skip to content

Nya-Foundation/NekoConf

Repository files navigation

NekoConf

The purr-fect balance of power and simplicity for configuration management.

πŸ‡ΊπŸ‡Έ English | πŸ‡¨πŸ‡³ δΈ­ζ–‡ | πŸ‡―πŸ‡΅ ζ—₯本θͺž

PyPI version Python versions License PyPI Downloads Docker Pulls Ask DeepWiki
Code Coverage CodeQL & Dependencies Scan CI/CD Builds

🐱 What is NekoConf?

Warning

This project is currently under active development. Documentation may not reflect the latest changes. If you encounter unexpected behavior, please consider using a previous stable version or report issues on our GitHub repository.

NekoConf is a dynamic and flexible configuration management system for Python applications. It simplifies handling configuration files (YAML, JSON, TOML) and provides real-time updates, environment variable overrides, and schema validation.

Feature Description
Configuration as Code Store configuration in human-readable YAML, JSON, or TOML files.
Centralized Management Access and modify configuration via a Python API, CLI, or optional Web UI.
Dynamic Updates React instantly to configuration changes using a built-in event system.
Environment Overrides Seamlessly override file settings with environment variables.
Schema Validation Ensure configuration integrity and prevent errors using JSON Schema.
Concurrency Safe Uses file locking to prevent race conditions during file access.
Remote Configuration Connect to a remote NekoConf server for centralized configuration.

Tip

NekoConf is ideal for applications with complex configuration needs, microservice architectures, or any scenario where you need to update configuration without service restarts.

πŸ› οΈ Prerequisites

  • Python 3.10 or higher
  • Docker (optional, for containerized deployment)

πŸ“¦ Installation

NekoConf follows a modular design with optional dependencies for different features:

# Basic installation with core features (local)
pip install nekoconf

# With webui server (FastAPI-based)
pip install nekoconf[server]

# With schema validation
pip install nekoconf[schema]

# With remote client (conntect to a NekoConf server)
pip install nekoconf[remote]

# For development and testing
pip install nekoconf[dev]

# Install all optional features
pip install nekoconf[all]

Optional Features

Feature Extra Dependencies Purpose
Core (none) pyyaml, colorlog, tomli, tomli-w Basic configuration operations
Web Server/API server fastapi, uvicorn, etc. Run a web server to manage configuration
Schema Validation schema jsonschema, rfc3987 Validate configuration against JSON Schema
Remote Config remote requests, websocket-client Connect to a remote NekoConf server
Development Tools dev pytest, pytest-cov, etc. For development and testing
All Features all All of the above Complete installation with all features

πŸš€ Quick Start

from nekoconf import NekoConf

# Initialize with configuration file path (creates file if it doesn't exist)
config = NekoConf("config.yaml", event_emission_enabled=True)

# Register a handler to react to configuration changes
@config.on_change("database.*")
def handle_db_change(path, old_value, new_value, **kwargs):
    print(f"Database configuration changed: {path}")
    print(f"  {old_value} -> {new_value}")
    # Reconnect to database or apply changes...

# Get configuration values (supports nested keys with dot notation)
db_host = config.get("database.host", default="localhost")
db_port = config.get("database.port", default=5432)

# Set configuration values
config.set("database.pool_size", 10) # trigger `handle_db_change`
config.set("features.dark_mode", True) # won't trigger `handle_db_change`

# Save changes to file
config.save()

πŸ”§ Core Features

πŸ”„ Configuration Management

Load, access, and modify configuration data using dot notation expressions.

sample_config = {
    "database": {
        "host": "127.0.0.1",
        "port": "8080"
    },
    "features": {
        "enabled": False
    }
}

# in-memory configuration for demo purposes
config = NekoConf(sample_config)

# Access values with type conversion
host = config.get("database.host") # "127.0.0.1"
port = config.get_int("database.port", default=5432) # 8080
is_enabled = config.get_bool("features.enabled", default=False) # False

# Update multiple values at once, or use replace to set the entire config
config.update({
    "logging": {
        "level": "DEBUG",
        "format": "%(asctime)s - %(levelname)s - %(message)s"
    }
})
print(config.json()) 

🌍 Environment Variable Overrides

Override configuration with environment variables. By default, variables are mapped as: database.host β†’ NEKOCONF_DATABASE_HOST

# Override configuration values with environment variables
export NEKOCONF_DATABASE_HOST=production-db.example.com
export NEKOCONF_DATABASE_PORT=5433
export NEKOCONF_FEATURES_ENABLED=true
# These values will reflect environment variables automatically
config = NekoConf("config.yaml", env_override_enabled=True)
print(config.get("database.host"))  # "production-db.example.com" 
print(config.get_int("database.port"))  # 5433
print(config.get_bool("features.enabled"))  # True

You can customize the environment variable prefix and delimiter:

config = NekoConf(
    "config.yaml",
    env_override_enabled=True
    env_prefix="MYAPP",
    env_nested_delimiter="_"
)

The above would overwrite database.host with MYAPP_DATABASE_HOST.

πŸ“’ Event System

React to configuration changes in real-time:

from nekoconf import NekoConf, EventType

config = NekoConf("config.yaml", event_emission_enabled=True)

# React to any change to database configuration
@config.on_change("database.*")
def handle_db_change(path, old_value, new_value, **kwargs):
    print(f"Database config {path} changed: {old_value} -> {new_value}")

# React to specific event types
@config.on_event([EventType.CREATE, EventType.UPDATE], "cache.*")
def handle_cache_config(event_type, path,new_value, **kwargs):
    if event_type == EventType.CREATE:
        print(f"New cache setting created: {path} = {new_value}")
    else:
        print(f"Cache setting updated: {path} = {new_value}")

# Change configuration to trigger events
config.set("database.timeout", 30)  # Triggers handle_db_change
config.set("cache.ttl", 600)  # Triggers handle_cache_config Create event
config.set("cache.ttl", 300)  # Triggers handle_cache_config Update event

🌐 Remote Configuration

Connect to a remote NekoConf server for centralized configuration (requires nekoconf[remote]):

from nekoconf import NekoConf, RemoteStorageBackend

remote_storage = RemoteStorageBackend(
    url="https://config-server.example.com/api/config",
    app_name="CustomApp"
    api_key="secure-key",
)

config = NekoConf(
    storage=remote_storage,  # Use remote storage backend
    event_emission_enabled=True # Enable event observer 
)

# Use exactly the same API as with local files
db_host = config.get("database.host")

# React to changes from the remote server
@config.on_change("features.*")
def handle_feature_change(path, new_value, **kwargs):
    print(f"Feature flag changed: {path} = {new_value}")
    # Apply feature change...

# Set a new value
config.set("features.dark_mode", True) # This will trigger the `handle_feature_change` callback

βœ… Schema Validation

Ensure configuration integrity using JSON Schema (requires nekoconf[schema]):

# schema.json
{
    "type": "object",
    "properties": {
        "database": {
            "type": "object",
            "required": ["host", "port"],
            "properties": {
                "host": {"type": "string"},
                "port": {"type": "integer", "minimum": 1024}
            }
        }
    },
    "required": ["database"]
}
# Initialize with schema
config = NekoConf("config.yaml", schema_path="schema.json")

# Validate configuration
errors = config.validate()
if errors:
    for error in errors:
        print(f"Error: {error}")
    
# Set invalid value and validate
config.set("database.port", "not-a-port")
errors = config.validate()
print(errors)  # Shows validation error

πŸ–₯️ Web UI & REST API

NekoConf includes a web server built with FastAPI to manage configuration remotely (requires nekoconf[server]):

from nekoconf import NekoConf, NekoConfOrchestrator

config = NekoConf("config.yaml")
apps = {
    "My_Config_Server": config
    # add more config app instances as needed
}
server = NekoConfOrchestrator(apps, api_key="secure-key", read_only=False)
server.run(host="0.0.0.0", port=8000)

Integrating with Existing FastAPI Applications

You can also mount the NekoConf orchestrator into your existing FastAPI application:

from fastapi import FastAPI
from nekoconf import NekoConf, NekoConfOrchestrator

# Your existing FastAPI app
app = FastAPI(title="My Application")

@app.get("/")
def read_root():
    return {"message": "Hello from my main app!"}

# Create NekoConf orchestrator
config = NekoConf("config.yaml")
apps = {"MyApp": config}
orchestrator = NekoConfOrchestrator(apps, api_key="secure-key")

# Mount the configuration orchestrator under /config
app.mount("/config", orchestrator.app)

# Now your app serves both your endpoints and config management:
# - http://localhost:8000/ - Your main app
# - http://localhost:8000/config/ - Configuration dashboard
# - http://localhost:8000/config/docs - Configuration API docs
# - http://localhost:8000/config/api/apps - Configuration API endpoints

if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=8000)

Access at http://localhost:8000 for the web UI or use REST endpoints:

Tip

Interactive API Documentation: FastAPI automatically generates interactive API documentation available at:

These provide a complete interactive interface to test all API endpoints directly from your browser.

Health & System Endpoints

Endpoint Method Description
/health GET Health check and system status

App Management Endpoints

Endpoint Method Description
/api/apps GET List all managed apps with their information
/api/apps POST Create a new configuration app
/api/apps/{app_name} GET Get information about a specific app
/api/apps/{app_name} PUT Update an app's configuration and metadata
/api/apps/{app_name} DELETE Delete an app and clean up its resources
/api/apps/{app_name}/metadata PATCH Update app metadata (name and/or description)

Configuration Management Endpoints

Endpoint Method Description
/api/apps/{app_name}/config GET Get entire configuration for a specific app
/api/apps/{app_name}/config PUT Update entire configuration for a specific app
/api/apps/{app_name}/config/{path} GET Get specific configuration value by path
/api/apps/{app_name}/config/{path} PUT Set specific configuration value by path
/api/apps/{app_name}/config/{path} DELETE Delete specific configuration value by path
/api/apps/{app_name}/validate POST Validate configuration against schema

WebSocket Endpoints

Endpoint Protocol Description
/ws/{app_name} WebSocket Real-time configuration updates for specific app

Static File Endpoints

Endpoint Method Description
/ GET Serve orchestrator dashboard
/{app_name} GET Serve configuration page for specific app
/static/{file_path} GET Serve static assets (CSS, JS, images)
/favicon.ico GET Serve favicon

The server supports WebSocket connections for real-time configuration updates on a per-app basis.

Warning

Secure your API with an API key in production environments.

Web UI Showcases

Configuration Management Interface

Dashboard & Overview

πŸ’» Command-Line Interface

NekoConf provides a comprehensive command-line interface for managing configuration:

Basic Usage

# View help and version
nekoconf --help
nekoconf --version

# Enable debug logging for any command
nekoconf --debug <command>

Server Management

# Start web server (requires nekoconf[server])
nekoconf server --config config.yaml --port 8000 --api-key "secure-key"

# Start server with additional options
nekoconf server \
  --host 0.0.0.0 \
  --port 8000 \
  --config config.yaml \
  --schema schema.json \
  --api-key "secure-key" \
  --app-name "MyApp" \
  --event true \
  --read-only false \
  --reload true

Configuration Management

# Initialize new configuration with templates
nekoconf init config.yaml --template default
nekoconf init api-config.yaml --template api-service
nekoconf init web-config.yaml --template web-app
nekoconf init micro-config.yaml --template microservice
nekoconf init empty-config.yaml --template empty

# Get configuration value
nekoconf get database.host --config config.yaml

# Get entire configuration with different formats
nekoconf get --config config.yaml --format json
nekoconf get --config config.yaml --format yaml
nekoconf get --config config.yaml --format raw

# Set configuration value
nekoconf set database.port 5432 --config config.yaml

# Set with schema validation
nekoconf set database.port 5432 --config config.yaml --schema schema.json

# Delete configuration value
nekoconf delete old.setting --config config.yaml

# Validate configuration (requires nekoconf[schema])
nekoconf validate --config config.yaml --schema schema.json

Remote Configuration

# Connect to a remote NekoConf server (requires nekoconf[remote])
nekoconf connect --remote http://config-server:8000 --api-key "secure-key" --format json

# Connect with specific app name
nekoconf connect --remote http://config-server:8000 --app-name "MyApp" --api-key "secure-key"

# Get value from remote server
nekoconf get database.host --remote http://config-server:8000 --api-key "secure-key"

# Set value on remote server
nekoconf set cache.ttl 600 --remote http://config-server:8000 --api-key "secure-key"

# Delete value on remote server
nekoconf delete old.setting --remote http://config-server:8000 --api-key "secure-key"

# Validate remote configuration
nekoconf validate --remote http://config-server:8000 --api-key "secure-key" --schema schema.json

Configuration Templates

The init command supports several built-in templates:

Template Description Use Case
empty πŸ“„ Empty Configuration Start with a blank configuration
default βš™οΈ Default Configuration Basic configuration template
web-app 🌐 Web Application Frontend application with server and API settings
api-service πŸ”Œ API Service Backend service with database and auth configuration
microservice 🐳 Microservice Containerized service with logging and metrics

❀️ Discord Community

Discord

Note

Need support? Contact k3scat@gmail.com or join our discord community at Nya Foundation

πŸ“ License

This project is licensed under the MIT License - see the LICENSE file for details.

Packages

 
 
 

Contributors 2

  •  
  •