#!/usr/bin/env python

"""Misc. useful functionality used by the rest of this package.

This module provides common functionality used by the other modules in
this package.

"""

import sys
import os
import subprocess


# Whether or not to show debug messages
DEBUG = False

def notify(msg, *args):
    """Print a message to stderr."""
    print >> sys.stderr, msg % args

def debug (msg, *args):
    """Print a debug message to stderr when DEBUG is enabled."""
    if DEBUG:
        print >> sys.stderr, msg % args

def error (msg, *args):
    """Print an error message to stderr."""
    print >> sys.stderr, "ERROR:", msg % args

def warn(msg, *args):
    """Print a warning message to stderr."""
    print >> sys.stderr, "warning:", msg % args

def die (msg, *args):
    """Print as error message to stderr and exit the program."""
    error(msg, *args)
    sys.exit(1)


class ProgressIndicator(object):

    """Simple progress indicator.

    Displayed as a spinning character by default, but can be customized
    by passing custom messages that overrides the spinning character.

    """

    States = ("|", "/", "-", "\\")

    def __init__ (self, prefix = "", f = sys.stdout):
        """Create a new ProgressIndicator, bound to the given file object."""
        self.n = 0  # Simple progress counter
        self.f = f  # Progress is written to this file object
        self.prev_len = 0  # Length of previous msg (to be overwritten)
        self.prefix = prefix  # Prefix prepended to each progress message
        self.prefix_lens = [] # Stack of prefix string lengths

    def pushprefix (self, prefix):
        """Append the given prefix onto the prefix stack."""
        self.prefix_lens.append(len(self.prefix))
        self.prefix += prefix

    def popprefix (self):
        """Remove the last prefix from the prefix stack."""
        prev_len = self.prefix_lens.pop()
        self.prefix = self.prefix[:prev_len]

    def __call__ (self, msg = None, lf = False):
        """Indicate progress, possibly with a custom message."""
        if msg is None:
            msg = self.States[self.n % len(self.States)]
        msg = self.prefix + msg
        print >> self.f, "\r%-*s" % (self.prev_len, msg),
        self.prev_len = len(msg.expandtabs())
        if lf:
            print >> self.f
            self.prev_len = 0
        self.n += 1

    def finish (self, msg = "done", noprefix = False):
        """Finalize progress indication with the given message."""
        if noprefix:
            self.prefix = ""
        self(msg, True)


def start_command (args, cwd = None, shell = False, add_env = None,
                   stdin = subprocess.PIPE, stdout = subprocess.PIPE,
                   stderr = subprocess.PIPE):
    """Start the given command, and return a subprocess object.

    This provides a simpler interface to the subprocess module.

    """
    env = None
    if add_env is not None:
        env = os.environ.copy()
        env.update(add_env)
    return subprocess.Popen(args, bufsize = 1, stdin = stdin, stdout = stdout,
                            stderr = stderr, cwd = cwd, shell = shell,
                            env = env, universal_newlines = True)


def run_command (args, cwd = None, shell = False, add_env = None,
                 flag_error = True):
    """Run the given command to completion, and return its results.

    This provides a simpler interface to the subprocess module.

    The results are formatted as a 3-tuple: (exit_code, output, errors)

    If flag_error is enabled, Error messages will be produced if the
    subprocess terminated with a non-zero exit code and/or stderr
    output.

    The other arguments are passed on to start_command().

    """
    process = start_command(args, cwd, shell, add_env)
    (output, errors) = process.communicate()
    exit_code = process.returncode
    if flag_error and errors:
        error("'%s' returned errors:\n---\n%s---", " ".join(args), errors)
    if flag_error and exit_code:
        error("'%s' returned exit code %i", " ".join(args), exit_code)
    return (exit_code, output, errors)


def file_reader_method (missing_ok = False):
    """Decorator for simplifying reading of files.

    If missing_ok is True, a failure to open a file for reading will
    not raise the usual IOError, but instead the wrapped method will be
    called with f == None.  The method must in this case properly
    handle f == None.

    """
    def _wrap (method):
        """Teach given method to handle both filenames and file objects.

        The given method must take a file object as its second argument
        (the first argument being 'self', of course).  This decorator
        will take a filename given as the second argument and promote
        it to a file object.

        """
        def _wrapped_method (self, filename, *args, **kwargs):
            if isinstance(filename, file):
                f = filename
            else:
                try:
                    f = open(filename, 'r')
                except IOError:
                    if missing_ok:
                        f = None
                    else:
                        raise
            try:
                return method(self, f, *args, **kwargs)
            finally:
                if not isinstance(filename, file) and f:
                    f.close()
        return _wrapped_method
    return _wrap


def file_writer_method (method):
    """Decorator for simplifying writing of files.

    Enables the given method to handle both filenames and file objects.

    The given method must take a file object as its second argument
    (the first argument being 'self', of course).  This decorator will
    take a filename given as the second argument and promote it to a
    file object.

    """
    def _new_method (self, filename, *args, **kwargs):
        if isinstance(filename, file):
            f = filename
        else:
            # Make sure the containing directory exists
            parent_dir = os.path.dirname(filename)
            if not os.path.isdir(parent_dir):
                os.makedirs(parent_dir)
            f = open(filename, 'w')
        try:
            return method(self, f, *args, **kwargs)
        finally:
            if not isinstance(filename, file):
                f.close()
    return _new_method
