Skip to main content

Python Library that builds a complete CLI given one or more functions using introspection

Project description

Freyja โšก

Freyja

Freyja is a no-dependency, zero-configuration CLI tool to build command-line interfaces purely from python classes.

Summary

Transform your Python classes into powerful command-line applications in seconds!

Freyja uses your class to generate a powerful CLI:

  • Methods become commands with automatic usage, help and validation.
  • Type annotations and docstrings are used to enhance CLI functionality.
  • Inner classes can be used to organize commands into groups.

โš ๏ธ Important: All constructor parameters MUST have default values for CLI generation to work. Parameters without defaults will cause CLI creation to fail.

๐ŸŽ‰ What's New in v1.1.5

Enhanced Features

  • ๐Ÿ”„ ExecutionSpinner: Beautiful progress indicators with command context tracking
  • ๐ŸŽจ Theme Adjustments: Dynamic theme customization with multiple adjustment strategies
  • ๐Ÿ“Š Dependency Analysis: New tools for analyzing project dependencies
  • ๐Ÿ›ก๏ธ Improved Error Handling: Better validation and clearer error messages
  • โšก Performance Improvements: Faster command discovery and execution

Table of Contents

๐Ÿš€ Why Freyja?

Build CLIs in under 5 minutes! No configuration files, no complex setup, no learning curve. Just add type annotations to your class methods and Freyja does the rest.

pip install freyja
# That's it! No dependencies, no configuration needed.

Before Freyja:

python script.py --config-file /path/to/config --database-host localhost --database-port 5432 --username admin --password secret --table-name users --action create --data '{"name": "Alice", "email": "alice@example.com"}'

After Freyja:

python script.py database create-user --name Alice --email alice@example.com
# Global config handled automatically, clean syntax, built-in help

โšก Quick Start

Step 1: Install Freyja

pip install freyja

Step 2: Create a class with typed methods

from freyja import FreyjaCLI


class Greeter:
    """Simple greeting application."""

    def __init__(self, default_name: str = "World", verbose: bool = False):
        """Initialize greeter with default name."""
        self.default_name = default_name
        self.verbose = verbose

    def greet(self, name: str = None, excited: bool = False) -> None:
        """Greet someone by name."""
        actual_name = name or self.default_name
        greeting = f"Hello, {actual_name}!"
        if excited:
            greeting += " ๐ŸŽ‰"
        print(greeting)

Step 3: Add 3 lines of Freyja code

if __name__ == '__main__':
    cli = FreyjaCLI(Greeter, title="My CLI")
    cli.run()

Step 4: Use your new CLI!

python script.py greet --name Alice --excited
# Output: Hello, Alice! ๐ŸŽ‰

python script.py --help
# Automatic help generation with beautiful formatting

# With verbose mode (shows execution spinner in v1.1.5+)
python script.py --verbose greet --name Bob
# Output: Executing greet [greet:name:Bob]
#         Hello, Bob!

๐Ÿ—๏ธ Class-based CLI

Freyja transforms your Python classes into powerful CLI applications. Supports flexible patterns for organizing your commands:

Direct Methods Pattern

Simple and clean - each method becomes a command:

# calculator.py
from freyja import FreyjaCLI


class Calculator:
    """Advanced calculator with memory and history."""

    def __init__(self, precision: int = 2, memory_enabled: bool = True):
        """Initialize calculator with global settings."""
        self.precision = precision
        self.memory = 0 if memory_enabled else None

    def add(self, a: float, b: float, store_result: bool = False) -> None:
        """Add two numbers together."""
        result = round(a + b, self.precision)
        print(f"{a} + {b} = {result}")
        
        if store_result and self.memory is not None:
            self.memory = result
            print(f"Result stored in memory: {result}")

    def multiply(self, a: float, b: float) -> None:
        """Multiply two numbers."""
        result = round(a * b, self.precision)
        print(f"{a} ร— {b} = {result}")


if __name__ == '__main__':
    cli = FreyjaCLI(Calculator, title="Advanced Calculator")
    cli.run()

Usage:

python calculator.py --precision 4 add 3.14159 --b 2.71828 --store-result
# Output: 3.14159 + 2.71828 = 5.8599
#         Result stored in memory: 5.8599

Inner Classes Pattern

Organize complex applications with hierarchical command structure using space-separated commands:

# project_manager.py
from freyja import FreyjaCLI
from pathlib import Path


class ProjectManager:
    """Complete project management suite with organized command structure."""

    def __init__(self, config_file: str = "config.json", debug: bool = False):
        """Initialize with global settings."""
        self.config_file = config_file
        self.debug = debug

    class Database:
        """Database operations and management."""

        def __init__(self, connection_string: str = "sqlite:///projects.db", timeout: int = 30):
            """Initialize database connection."""
            self.connection_string = connection_string
            self.timeout = timeout

        def migrate(self, version: str = "latest", dry_run: bool = False) -> None:
            """Run database migrations."""
            action = "Would run" if dry_run else "Running"
            print(f"{action} migration to version: {version}")
            print(f"Connection: {self.connection_string}")

        def backup(self, output_path: Path, compress: bool = True) -> None:
            """Create database backup."""
            compression = "compressed" if compress else "uncompressed"
            print(f"Creating {compression} backup at: {output_path}")

    class Projects:
        """Project creation and management operations."""

        def __init__(self, workspace: str = "./projects", auto_save: bool = True):
            """Initialize project operations."""
            self.workspace = workspace
            self.auto_save = auto_save

        def create(self, name: str, template: str = "basic", description: str = "") -> None:
            """Create a new project from template."""
            print(f"Creating project '{name}' using '{template}' template")
            print(f"Workspace: {self.workspace}")
            print(f"Description: {description}")
            print(f"Auto-save: {'enabled' if self.auto_save else 'disabled'}")

        def deploy(self, project_name: str, environment: str = "staging", force: bool = False) -> None:
            """Deploy project to specified environment."""
            action = "Force deploying" if force else "Deploying"
            print(f"{action} {project_name} to {environment}")


if __name__ == '__main__':
    cli = FreyjaCLI(ProjectManager, title="Project Management Suite")
    cli.run()

Usage with Hierarchical Commands:

# Global + Sub-global + Command arguments (hierarchical structure)
python project_manager.py --config-file prod.json --debug \
  database migrate --timeout 60 --version 2.1.0 --dry-run

# Create new project with custom workspace  
python project_manager.py projects create --workspace /prod/projects --auto-save \
  --name "web-app" --template "react" --description "Production web application"

# Deploy with force flag
python project_manager.py projects deploy --project-name web-app --environment production --force

# Beautiful help shows all commands organized by group
python project_manager.py --help

โš ๏ธ Important: Freyja uses ONLY hierarchical space-separated commands. Flat dash-separated syntax (e.g., database--migrate or system__completion__install) is NOT supported.

๐Ÿ”„ ExecutionSpinner (NEW)

Freyja v1.1.5+ includes an enhanced execution feedback system that provides visual progress indicators:

from freyja import FreyjaCLI
from freyja.utils.spinner import ExecutionSpinner, CommandContext
import time


class DataProcessor:
    """Data processing with progress feedback."""
    
    def __init__(self, verbose: bool = False):
        """Initialize with verbose mode support."""
        self.verbose = verbose
    
    def process_large_file(self, input_file: str, chunk_size: int = 1024) -> None:
        """Process a large file with progress indication."""
        # ExecutionSpinner is automatically integrated when verbose=True
        print(f"Processing {input_file} in {chunk_size}-byte chunks")
        
        # Simulate processing
        for i in range(5):
            time.sleep(0.5)
            print(f"  Processed chunk {i+1}/5")
        
        print("โœ“ Processing complete!")


if __name__ == '__main__':
    cli = FreyjaCLI(DataProcessor, title="Data Processor")
    cli.run()

Usage with ExecutionSpinner:

# Verbose mode shows execution context
python processor.py --verbose process-large-file input.csv --chunk-size 2048
# Output: Executing process-large-file [positional:0:input.csv, process-large-file:chunk_size:2048]
#         Processing input.csv in 2048-byte chunks
#         ...

# Normal mode (no spinner for quick operations)
python processor.py process-large-file input.csv

Key ExecutionSpinner Features:

  • Automatic Integration: Works with any Freyja CLI when verbose=True
  • Command Context: Shows namespace, command, and all arguments
  • Thread-Safe: Handles concurrent operations properly
  • Custom Status: Can augment status during execution
  • Clean Output: Proper cleanup on success or failure

โœจ Key Features

๐Ÿš€ Zero Configuration - Works out of the box with just type annotations โšก Lightning Fast - No runtime dependencies, minimal overhead ๐ŸŽฏ Type Safe - Automatic validation from your type hints ๐Ÿ”„ ExecutionSpinner - Beautiful progress indicators with command context (v1.1.5+) ๐Ÿ›ก๏ธ Guard Clauses - Built-in parameter validation with declarative guards ๐Ÿ“š Auto Documentation - Help text generated from your docstrings ๐ŸŽจ Beautiful Output - Professional themes with dynamic adjustment capabilities ๐Ÿ”ง Flexible Architecture - Direct methods or inner class patterns ๐Ÿ“ฆ No Dependencies - Uses only Python standard library ๐ŸŒˆ Shell Completion - Bash, Zsh, Fish, and PowerShell support ๐Ÿ“Š Dependency Analysis - Built-in tools for analyzing project dependencies (v1.1.5+) โœ… Production Ready - Battle-tested in enterprise applications

๐Ÿ“š Documentation

๐Ÿ“– Complete Documentation Hub - Everything you need to master Freyja

Quick Links

New in v1.1.5 Documentation

๐Ÿ› ๏ธ Development

See Development Environment Setup for detailed instructions.

๐Ÿ“– Development Guide - Comprehensive guide for contributors

Development Commands

poetry install                    # Install dependencies
./bin/dev-tools test run          # Run tests with coverage
./bin/dev-tools build lint        # Run all linters and formatters
./bin/dev-tools build compile     # Build package
./bin/dev-tools build publish     # Publish to PyPI (maintainers)
./bin/dev-tools build tag-version # Create version tags

โš™๏ธ Requirements

  • Python 3.13.5+ (recommended) or Python 3.8+
  • Zero runtime dependencies - uses only Python standard library
  • Type annotations required - for automatic CLI generation
  • Constructor defaults required - all constructor parameters must have default values
  • Docstrings recommended - for automatic help text generation

Command Syntax Rules

โœ… CORRECT - Hierarchical Commands:

my_cli database migrate             # Hierarchical with spaces
my_cli system completion install    # Multi-level hierarchy
my_cli projects create              # Clean and intuitive

โŒ INCORRECT - Forbidden Syntax:

my_cli database--migrate            # Double-dash syntax NOT supported
my_cli system__completion__install  # Dunder syntax NOT supported
my_cli data-ops--process           # Mixed syntax NOT supported

Ready to transform your Python code into powerful CLIs?

pip install freyja
# Start building amazing command-line tools in minutes! โšก

๐Ÿ“š Get Started Now โ†’ | ๐ŸŽ‰ What's New โ†’

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

freyja-1.2.4.tar.gz (93.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

freyja-1.2.4-py3-none-any.whl (116.0 kB view details)

Uploaded Python 3

File details

Details for the file freyja-1.2.4.tar.gz.

File metadata

  • Download URL: freyja-1.2.4.tar.gz
  • Upload date:
  • Size: 93.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.2.1 CPython/3.13.7 Darwin/25.0.0

File hashes

Hashes for freyja-1.2.4.tar.gz
Algorithm Hash digest
SHA256 a46d75b8f7bae86b283dbd34ac657c24f5718aa4bfdac59ca7c1aea5daad5ad3
MD5 92f9164f1990452891604ba8d0941f38
BLAKE2b-256 057b17a70de0b7a2132cf71cc74edb96fe549c0cc05fcb41c60485319da87cde

See more details on using hashes here.

File details

Details for the file freyja-1.2.4-py3-none-any.whl.

File metadata

  • Download URL: freyja-1.2.4-py3-none-any.whl
  • Upload date:
  • Size: 116.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.2.1 CPython/3.13.7 Darwin/25.0.0

File hashes

Hashes for freyja-1.2.4-py3-none-any.whl
Algorithm Hash digest
SHA256 c83169308959dd46fbc8c1792af873168e47b7817d6185ab23207b4aeac46a53
MD5 ee93492ab31b1f4ca503857d5668a595
BLAKE2b-256 f351b0398abe95907972be9c05797ecec2a55ddd5aa032dbb3a1dcbbdc298d1c

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page