import urllib2
from gurumate.base import fail
from urllib2 import HTTPError, URLError

def check_url_accessibility(url, timeout=10):
    '''
    Check whether the URL accessible and returns HTTP 200 OK or not
    if not raises ValidationError
    '''
    if(url=='localhost'):
        url = 'http://127.0.0.1'
    try:
        req = urllib2.urlopen(url, timeout=timeout)
        if (req.getcode()==200):
            return True
    except Exception:
        pass
    fail("URL '%s' is not accessible from this machine" % url)

def url_has_contents(url, contents, case_sensitive=False, timeout=10):
    '''
    Check whether the HTML page contains the content or not and return boolean
    '''
    try:
        req = urllib2.urlopen(url, timeout=timeout)
    except Exception, _:
        False
    else:
        rep = req.read()
        if (not case_sensitive and rep.lower().find(contents.lower()) >= 0) or (case_sensitive and rep.find(contents) >= 0):
            return True
        else:
            return False

def get_response_code(url, timeout=10):
    '''
    Visit the URL and return the HTTP response code in 'int'
    '''
    try:
        req = urllib2.urlopen(url, timeout=timeout)
    except HTTPError, e:
        return e.getcode()
    except Exception, _:
        fail("Couldn't reach the URL '%s'" % url)
    else:
        return req.getcode()

def check_response_code(url, code, timeout=10):
    try:
        resp = get_response_code(url, timeout=timeout)
    except:
        return False

    if  resp != code:
        fail("The URL '%s' is reachable but returns HTTP response code of '%s' while I expected '%s'" % (url, resp, code))

def compare_content_type(url, content_type):
    '''
    Compare the content type header of url param with content_type param and returns boolean
    @param url -> string e.g. http://127.0.0.1/index
    @param content_type -> string e.g. text/html
    '''
    try:
        response = urllib2.urlopen(url)
    except:
        return False

    return response.headers.type == content_type

def compare_response_code(url, code):
    '''
    Compare the response code of url param with code param and returns boolean
    @param url -> string e.g. http://127.0.0.1/index
    @param content_type -> int e.g. 404, 500, 400 ..etc
    '''
    try:
        response = urllib2.urlopen(url)

    except HTTPError as e:
        return e.code == code

    except:
        return False

    return response.code == code


"""An interface for publishing rich data to frontends.

There are two components of the display system:

* Display formatters, which take a Python object and compute the
  representation of the object in various formats (text, HTML, SVg, etc.).
* The display publisher that is used to send the representation data to the
  various frontends.

This module defines the logic display publishing. The display publisher uses
the ``display_data`` message type that is defined in the IPython messaging
spec.

Authors:

* Brian Granger
"""

#-----------------------------------------------------------------------------
#       Copyright (C) 2008-2011 The IPython Development Team
#
#  Distributed under the terms of the BSD License.  The full license is in
#  the file COPYING, distributed as part of this software.
#-----------------------------------------------------------------------------

#-----------------------------------------------------------------------------
# Imports
#-----------------------------------------------------------------------------

from __future__ import print_function

from IPython.config.configurable import Configurable
from IPython.utils import io

#-----------------------------------------------------------------------------
# Main payload class
#-----------------------------------------------------------------------------

class DisplayPublisher(Configurable):
    """A traited class that publishes display data to frontends.

    Instances of this class are created by the main IPython object and should
    be accessed there.
    """

    def _validate_data(self, source, data, metadata=None):
        """Validate the display data.

        Parameters
        ----------
        source : str
            The fully dotted name of the callable that created the data, like
            :func:`foo.bar.my_formatter`.
        data : dict
            The formata data dictionary.
        metadata : dict
            Any metadata for the data.
        """

        if not isinstance(source, basestring):
            raise TypeError('source must be a str, got: %r' % source)
        if not isinstance(data, dict):
            raise TypeError('data must be a dict, got: %r' % data)
        if metadata is not None:
            if not isinstance(metadata, dict):
                raise TypeError('metadata must be a dict, got: %r' % data)

    def publish(self, source, data, metadata=None):
        """Publish data and metadata to all frontends.

        See the ``display_data`` message in the messaging documentation for
        more details about this message type.

        The following MIME types are currently implemented:

        * text/plain
        * text/html
        * text/latex
        * application/json
        * application/javascript
        * image/png
        * image/jpeg
        * image/svg+xml

        Parameters
        ----------
        source : str
            A string that give the function or method that created the data,
            such as 'IPython.core.page'.
        data : dict
            A dictionary having keys that are valid MIME types (like
            'text/plain' or 'image/svg+xml') and values that are the data for
            that MIME type. The data itself must be a JSON'able data
            structure. Minimally all data should have the 'text/plain' data,
            which can be displayed by all frontends. If more than the plain
            text is given, it is up to the frontend to decide which
            representation to use.
        metadata : dict
            A dictionary for metadata related to the data. This can contain
            arbitrary key, value pairs that frontends can use to interpret
            the data.
        """

        # The default is to simply write the plain text data using io.stdout.
        if data.has_key('text/plain'):
            print(data['text/plain'], file=io.stdout)

    def clear_output(self, stdout=True, stderr=True, other=True):
        """Clear the output of the cell receiving output."""
        if stdout:
            print('\033[2K\r', file=io.stdout, end='')
            io.stdout.flush()
        if stderr:
            print('\033[2K\r', file=io.stderr, end='')
            io.stderr.flush()

def publish_display_data(source, data, metadata=None):
    """Publish data and metadata to all frontends.

    See the ``display_data`` message in the messaging documentation for
    more details about this message type.

    The following MIME types are currently implemented:

    * text/plain
    * text/html
    * text/latex
    * application/json
    * application/javascript
    * image/png
    * image/jpeg
    * image/svg+xml

    Parameters
    ----------
    source : str
        A string that give the function or method that created the data,
        such as 'IPython.core.page'.
    data : dict
        A dictionary having keys that are valid MIME types (like
        'text/plain' or 'image/svg+xml') and values that are the data for
        that MIME type. The data itself must be a JSON'able data
        structure. Minimally all data should have the 'text/plain' data,
        which can be displayed by all frontends. If more than the plain
        text is given, it is up to the frontend to decide which
        representation to use.
    metadata : dict
        A dictionary for metadata related to the data. This can contain
        arbitrary key, value pairs that frontends can use to interpret
        the data.
    """
    from IPython.core.interactiveshell import InteractiveShell
    InteractiveShell.instance().display_pub.publish(
        source,
        data,
        metadata
    )

def publish_pretty(data, metadata=None):
    """Publish raw text data to all frontends.

    Parameters
    ----------
    data : unicode
        The raw text data to publish.
    metadata : dict
        A dictionary for metadata related to the data. This can contain
        arbitrary key, value pairs that frontends can use to interpret
        the data.
    """
    publish_display_data(
        u'IPython.core.displaypub.publish_pretty',
        {'text/plain':data},
        metadata=metadata
    )

def publish_html(data, metadata=None):
    """Publish raw HTML data to all frontends.

    Parameters
    ----------
    data : unicode
        The raw HTML data to publish.
    metadata : dict
        A dictionary for metadata related to the data. This can contain
        arbitrary key, value pairs that frontends can use to interpret
        the data.
    """
    publish_display_data(
        u'IPython.core.displaypub.publish_html',
        {'text/html':data},
        metadata=metadata
    )

def publish_latex(data, metadata=None):
    """Publish raw LaTeX data to all frontends.

    Parameters
    ----------
    data : unicode
        The raw LaTeX data to publish.
    metadata : dict
        A dictionary for metadata related to the data. This can contain
        arbitrary key, value pairs that frontends can use to interpret
        the data.
    """
    publish_display_data(
        u'IPython.core.displaypub.publish_latex',
        {'text/latex':data},
        metadata=metadata
    )

def publish_png(data, metadata=None):
    """Publish raw binary PNG data to all frontends.

    Parameters
    ----------
    data : str/bytes
        The raw binary PNG data to publish.
    metadata : dict
        A dictionary for metadata related to the data. This can contain
        arbitrary key, value pairs that frontends can use to interpret
        the data.
    """
    publish_display_data(
        u'IPython.core.displaypub.publish_png',
        {'image/png':data},
        metadata=metadata
    )

def publish_jpeg(data, metadata=None):
    """Publish raw binary JPEG data to all frontends.

    Parameters
    ----------
    data : str/bytes
        The raw binary JPEG data to publish.
    metadata : dict
        A dictionary for metadata related to the data. This can contain
        arbitrary key, value pairs that frontends can use to interpret
        the data.
    """
    publish_display_data(
        u'IPython.core.displaypub.publish_jpeg',
        {'image/jpeg':data},
        metadata=metadata
    )

def publish_svg(data, metadata=None):
    """Publish raw SVG data to all frontends.

    Parameters
    ----------
    data : unicode
        The raw SVG data to publish.
    metadata : dict
        A dictionary for metadata related to the data. This can contain
        arbitrary key, value pairs that frontends can use to interpret
        the data.
    """
    publish_display_data(
        u'IPython.core.displaypub.publish_svg',
        {'image/svg+xml':data},
        metadata=metadata
    )

def publish_json(data, metadata=None):
    """Publish raw JSON data to all frontends.

    Parameters
    ----------
    data : unicode
        The raw JSON data to publish.
    metadata : dict
        A dictionary for metadata related to the data. This can contain
        arbitrary key, value pairs that frontends can use to interpret
        the data.
    """
    publish_display_data(
        u'IPython.core.displaypub.publish_json',
        {'application/json':data},
        metadata=metadata
    )

def publish_javascript(data, metadata=None):
    """Publish raw Javascript data to all frontends.

    Parameters
    ----------
    data : unicode
        The raw Javascript data to publish.
    metadata : dict
        A dictionary for metadata related to the data. This can contain
        arbitrary key, value pairs that frontends can use to interpret
        the data.
    """
    publish_display_data(
        u'IPython.core.displaypub.publish_javascript',
        {'application/javascript':data},
        metadata=metadata
    )


# -*- coding: utf-8 -*-
"""
General finite difference utlity for generation of finite difference first
and second derivative functions given a scalar input function

Functions:

    grad: for ordinary scalar functions of one or two variables
    ndgrad: for scalar functions of numpy array objects
    clgrad: for derivatives of a class method with respect to an attribute
"""

import numpy
from .attributes import get_method_and_copy_of_attribute
DELTA = 5e-5

def grad(f, delta=DELTA):
    """
    Returns numerical gradient function of given input function
    Input: f, scalar function of one or two variables
           delta(optional), finite difference step
    Output: gradient function object
    """
    def grad_f(*args, **kwargs):
        if len(args) == 1:
            x, = args
            gradf_x = (
                f(x+delta/2) - f(x-delta/2)
                )/delta
            return gradf_x
        elif len(args) == 2:
            x, y = args
            if type(x) in [float, int] and type(y) in [float, int]:
                gradf_x = (f(x + delta/2, y) - f(x - delta/2, y))/delta
                gradf_y = (f(x, y + delta/2) - f(x, y - delta/2))/delta
                return gradf_x, gradf_y
    return grad_f

def hessian(f, delta=DELTA):
    """
    Returns numerical hessian function of given input function
    Input: f, scalar function of one or two variables
           delta(optional), finite difference step
    Output: hessian function object
    """
    def hessian_f(*args, **kwargs):
        if len(args) == 1:
            x, = args
            hessianf_x = (
                f(x+delta) + f(x-delta) - 2*f(x)
                )/delta**2
            return hessianf_x
        elif len(args) == 2:
            x, y = args
            if type(x) in [float, int] and type(y) in [float, int]:
                hess_xx = (
                    f(x + delta, y) + f(x - delta, y) - 2*f(x, y)
                    )/delta**2
                hess_yy = (
                    f(x, y + delta) + f(x, y - delta) - 2*f(x, y)
                    )/delta**2
                hess_xy = (
                    + f(x+delta/2, y+delta/2)
                    + f(x-delta/2, y-delta/2)
                    - f(x+delta/2, y-delta/2)
                    - f(x-delta/2, y+delta/2)
                    )/delta**2
                return hess_xx, hess_xy, hess_yy
    return hessian_f

def ndgrad(f, delta=DELTA):
    """
    Returns numerical gradient function of given input function
    Input: f, scalar function of an numpy array object
           delta(optional), finite difference step
    Output: gradient function object
    """
    def grad_f(*args, **kwargs):
        x = args[0]
        grad_val = numpy.zeros(x.shape)
        it = numpy.nditer(x, op_flags=['readwrite'], flags=['multi_index'])
        for xi in it:
            i = it.multi_index
            xi += delta/2
            fp = f(*args, **kwargs)
            xi -= delta
            fm = f(*args, **kwargs)
            xi += delta/2
            grad_val[i] = (fp - fm)/delta
        return grad_val
    return grad_f

def ndhess(f, delta=DELTA):
    """
    Returns numerical hessian function of given input function
    Input: f, scalar function of an numpy array object
           delta(optional), finite difference step
    Output: hessian function object
    """
    def hess_f(*args, **kwargs):
        x = args[0]
        hess_val = numpy.zeros(x.shape + x.shape)
        it = numpy.nditer(x, op_flags=['readwrite'], flags=['multi_index'])
        for xi in it:
            i = it.multi_index
            jt = numpy.nditer(x, op_flags=['readwrite'], flags=['multi_index'])
            for xj in jt:
                j = jt.multi_index
                xi += delta/2
                xj += delta/2
                fpp = f(x)
                xj -= delta
                fpm = f(x)
                xi -= delta
                fmm = f(x)
                xj += delta
                fmp = f(x)
                xi += delta/2
                xj -= delta/2
                hess_val[i + j] = (fpp + fmm - fpm - fmp)/delta**2
        return hess_val
    return hess_f

def clgrad(obj, exe, arg, delta=DELTA):
    """
    Returns numerical gradient function of given class method
    with respect to a class attribute
    Input: obj, general object
           exe (str), name of object method
           arg (str), name of object atribute
           delta(float, optional), finite difference step
    Output: gradient function object
    """
    f, x = get_method_and_copy_of_attribute(obj, exe, arg)
    def grad_f(*args, **kwargs):
        grad_val = numpy.zeros(x.shape)
        it = numpy.nditer(x, op_flags=['readwrite'], flags=['multi_index'])
        for xi in it:
            i = it.multi_index
            xi += delta/2
            fp = f(*args, **kwargs)
            xi -= delta
            fm = f(*args, **kwargs)
            xi += delta/2
            grad_val[i] = (fp - fm)/delta
        return grad_val
    return grad_f

def clhess(obj, exe, arg, delta=DELTA):
    """
    Returns numerical hessian function of given class method
    with respect to a class attribute
    Input: obj, general object
           exe (str), name of object method
           arg (str), name of object atribute
           delta(float, optional), finite difference step
    Output: Hessian function object
    """
    f, x = get_method_and_copy_of_attribute(obj, exe, arg)
    def hess_f(*args, **kwargs):
        hess_val = numpy.zeros(x.shape + x.shape)
        it = numpy.nditer(x, op_flags=['readwrite'], flags=['multi_index'])
        for xi in it:
            i = it.multi_index
            jt = numpy.nditer(x, op_flags=['readwrite'], flags=['multi_index'])
            for xj in jt:
                j = jt.multi_index
                xi += delta/2
                xj += delta/2
                fpp = f(*args, **kwargs)
                xj -= delta
                fpm = f(*args, **kwargs)
                xi -= delta
                fmm = f(*args, **kwargs)
                xj += delta
                fmp = f(*args, **kwargs)
                xi += delta/2
                xj -= delta/2
                hess_val[i + j] = (fpp + fmm - fpm - fmp)/delta**2
        return hess_val
    return hess_f

def clmixhess(obj, exe, arg1, arg2, delta=DELTA):
    """
    Returns numerical mixed Hessian function of given class method
    with respect to two class attributes
    Input: obj, general object
           exe (str), name of object method
           arg1(str), name of object attribute
           arg2(str), name of object attribute
           delta(float, optional), finite difference step
    Output: Hessian function object
    """
    f, x = get_method_and_copy_of_attribute(obj, exe, arg1)
    _, y = get_method_and_copy_of_attribute(obj, exe, arg2)
    def hess_f(*args, **kwargs):
        hess_val = numpy.zeros(x.shape + y.shape)
        it = numpy.nditer(x, op_flags=['readwrite'], flags=['multi_index'])
        for xi in it:
            i = it.multi_index
            jt = numpy.nditer(y, op_flags=['readwrite'], flags=['multi_index'])
            for yj in jt:
                j = jt.multi_index
                xi += delta/2
                yj += delta/2
                fpp = f(*args, **kwargs)
                yj -= delta
                fpm = f(*args, **kwargs)
                xi -= delta
                fmm = f(*args, **kwargs)
                yj += delta
                fmp = f(*args, **kwargs)
                xi += delta/2
                yj -= delta/2
                hess_val[i + j] = (fpp + fmm - fpm - fmp)/delta**2
        return hess_val
    return hess_f


# encoding: utf-8
"""
Utilities for working with external processes.
"""

#-----------------------------------------------------------------------------
#  Copyright (C) 2008-2011  The IPython Development Team
#
#  Distributed under the terms of the BSD License.  The full license is in
#  the file COPYING, distributed as part of this software.
#-----------------------------------------------------------------------------

#-----------------------------------------------------------------------------
# Imports
#-----------------------------------------------------------------------------
from __future__ import print_function

# Stdlib
import os
import sys
import shlex

# Our own
if sys.platform == 'win32':
    from ._process_win32 import _find_cmd, system, getoutput, AvoidUNCPath, arg_split
else:
    from ._process_posix import _find_cmd, system, getoutput, arg_split

from ._process_common import getoutputerror
from IPython.utils import py3compat

#-----------------------------------------------------------------------------
# Code
#-----------------------------------------------------------------------------

class FindCmdError(Exception):
    pass

def find_cmd(cmd):
    """Find absolute path to executable cmd in a cross platform manner.

    This function tries to determine the full path to a command line program
    using `which` on Unix/Linux/OS X and `win32api` on Windows.  Most of the
    time it will use the version that is first on the users `PATH`.  If
    cmd is `python` return `sys.executable`.

    Warning, don't use this to find IPython command line programs as there
    is a risk you will find the wrong one.  Instead find those using the
    following code and looking for the application itself::

        from IPython.utils.path import get_ipython_module_path
        from IPython.utils.process import pycmd2argv
        argv = pycmd2argv(get_ipython_module_path('IPython.frontend.terminal.ipapp'))

    Parameters
    ----------
    cmd : str
        The command line program to look for.
    """
    if cmd == 'python':
        return os.path.abspath(sys.executable)
    try:
        path = _find_cmd(cmd).rstrip()
    except OSError:
        raise FindCmdError('command could not be found: %s' % cmd)
    # which returns empty if not found
    if path == '':
        raise FindCmdError('command could not be found: %s' % cmd)
    return os.path.abspath(path)

def pycmd2argv(cmd):
    r"""Take the path of a python command and return a list (argv-style).

    This only works on Python based command line programs and will find the
    location of the ``python`` executable using ``sys.executable`` to make
    sure the right version is used.

    For a given path ``cmd``, this returns [cmd] if cmd's extension is .exe,
    .com or .bat, and [, cmd] otherwise.

    Parameters
    ----------
    cmd : string
      The path of the command.

    Returns
    -------
    argv-style list.
    """
    ext = os.path.splitext(cmd)[1]
    if ext in ['.exe', '.com', '.bat']:
        return [cmd]
    else:
        return [sys.executable, cmd]

def abbrev_cwd():
    """ Return abbreviated version of cwd, e.g. d:mydir """
    cwd = os.getcwdu().replace('\\','/')
    drivepart = ''
    tail = cwd
    if sys.platform == 'win32':
        if len(cwd) < 4:
            return cwd
        drivepart,tail = os.path.splitdrive(cwd)

    parts = tail.split('/')
    if len(parts) > 2:
        tail = '/'.join(parts[-2:])

    return (drivepart + (
        cwd == '/' and '/' or tail))


"""Code unit (module) handling for Coverage."""

import glob, os

from coverage.backward import open_source, string_class, StringIO
from coverage.misc import CoverageException

def code_unit_factory(morfs, file_locator):
    """Construct a list of CodeUnits from polymorphic inputs.

    `morfs` is a module or a filename, or a list of same.

    `file_locator` is a FileLocator that can help resolve filenames.

    Returns a list of CodeUnit objects.

    """
    # Be sure we have a list.
    if not isinstance(morfs, (list, tuple)):
        morfs = [morfs]

    # On Windows, the shell doesn't expand wildcards.  Do it here.
    globbed = []
    for morf in morfs:
        if isinstance(morf, string_class) and ('?' in morf or '*' in morf):
            globbed.extend(glob.glob(morf))
        else:
            globbed.append(morf)
    morfs = globbed

    code_units = [CodeUnit(morf, file_locator) for morf in morfs]

    return code_units

class CodeUnit(object):
    """Code unit: a filename or module.

    Instance attributes:

    `name` is a human-readable name for this code unit.
    `filename` is the os path from which we can read the source.
    `relative` is a boolean.

    """
    def __init__(self, morf, file_locator):
        self.file_locator = file_locator

        if hasattr(morf, '__file__'):
            f = morf.__file__
        else:
            f = morf
        # .pyc files should always refer to a .py instead.
        if f.endswith('.pyc') or f.endswith('.pyo'):
            f = f[:-1]
        elif f.endswith('$py.class'): # Jython
            f = f[:-9] + ".py"
        self.filename = self.file_locator.canonical_filename(f)

        if hasattr(morf, '__name__'):
            n = modname = morf.__name__
            self.relative = True
        else:
            n = os.path.splitext(morf)[0]
            rel = self.file_locator.relative_filename(n)
            if os.path.isabs(n):
                self.relative = (rel != n)
            else:
                self.relative = True
            n = rel
            modname = None
        self.name = n
        self.modname = modname

    def __repr__(self):
        return "<CodeUnit name=%r filename=%r>" % (self.name, self.filename)

    # Annoying comparison operators. Py3k wants __lt__ etc, and Py2k needs all
    # of them defined.

    def __lt__(self, other):
        return self.name < other.name
    def __le__(self, other):
        return self.name <= other.name
    def __eq__(self, other):
        return self.name == other.name
    def __ne__(self, other):
        return self.name != other.name
    def __gt__(self, other):
        return self.name > other.name
    def __ge__(self, other):
        return self.name >= other.name

    def flat_rootname(self):
        """A base for a flat filename to correspond to this code unit.

        Useful for writing files about the code where you want all the files in
        the same directory, but need to differentiate same-named files from
        different directories.

        For example, the file a/b/c.py might return 'a_b_c'

        """
        if self.modname:
            return self.modname.replace('.', '_')
        else:
            root = os.path.splitdrive(self.name)[1]
            return root.replace('\\', '_').replace('/', '_').replace('.', '_')

    def source_file(self):
        """Return an open file for reading the source of the code unit."""
        if os.path.exists(self.filename):
            # A regular text file: open it.
            return open_source(self.filename)

        # Maybe it's in a zip file?
        source = self.file_locator.get_zip_data(self.filename)
        if source is not None:
            return StringIO(source)

        # Couldn't find source.
        raise CoverageException(
            "No source for code '%s'." % self.filename
            )

    def should_be_python(self):
        """Does it seem like this file should contain Python?

        This is used to decide if a file reported as part of the exection of
        a program was really likely to have contained Python in the first
        place.

        """
        # Get the file extension.
        _, ext = os.path.splitext(self.filename)

        # Anything named *.py* should be Python.
        if ext.startswith('.py'):
            return True
        # A file with no extension should be Python.
        if not ext:
            return True
        # Everything else is probably not Python.
        return False


"""AsyncResult objects for the client

Authors:

* MinRK
"""
#-----------------------------------------------------------------------------
#  Copyright (C) 2010-2011  The IPython Development Team
#
#  Distributed under the terms of the BSD License.  The full license is in
#  the file COPYING, distributed as part of this software.
#-----------------------------------------------------------------------------

#-----------------------------------------------------------------------------
# Imports
#-----------------------------------------------------------------------------

from __future__ import print_function

import sys
import time
from datetime import datetime

from zmq import MessageTracker

from IPython.core.display import clear_output, display, display_pretty
from IPython.external.decorator import decorator
from IPython.parallel import error

#-----------------------------------------------------------------------------
# Functions
#-----------------------------------------------------------------------------

def _total_seconds(td):
    """timedelta.total_seconds was added in 2.7"""
    try:
        # Python >= 2.7
        return td.total_seconds()
    except AttributeError:
        # Python 2.6
        return 1e-6 * (td.microseconds + (td.seconds + td.days * 24 * 3600) * 10**6)

def _raw_text(s):
    display_pretty(s, raw=True)

#-----------------------------------------------------------------------------
# Classes
#-----------------------------------------------------------------------------

# global empty tracker that's always done:
finished_tracker = MessageTracker()

@decorator
def check_ready(f, self, *args, **kwargs):
    """Call spin() to sync state prior to calling the method."""
    self.wait(0)
    if not self._ready:
        raise error.TimeoutError("result not ready")
    return f(self, *args, **kwargs)

class AsyncResult(object):
    """Class for representing results of non-blocking calls.

    Provides the same interface as :py:class:`multiprocessing.pool.AsyncResult`.
    """

    msg_ids = None
    _targets = None
    _tracker = None
    _single_result = False

    def __init__(self, client, msg_ids, fname='unknown', targets=None, tracker=None):
        if isinstance(msg_ids, basestring):
            # always a list
            msg_ids = [msg_ids]
        if tracker is None:
            # default to always done
            tracker = finished_tracker
        self._client = client
        self.msg_ids = msg_ids
        self._fname=fname
        self._targets = targets
        self._tracker = tracker
        self._ready = False
        self._success = None
        self._metadata = None
        if len(msg_ids) == 1:
            self._single_result = not isinstance(targets, (list, tuple))
        else:
            self._single_result = False

    def __repr__(self):
        if self._ready:
            return "<%s: finished>"%(self.__class__.__name__)
        else:
            return "<%s: %s>"%(self.__class__.__name__,self._fname)

    def _reconstruct_result(self, res):
        """Reconstruct our result from actual result list (always a list)

        Override me in subclasses for turning a list of results
        into the expected form.
        """
        if self._single_result:
            return res[0]
        else:
            return res

    def get(self, timeout=-1):
        """Return the result when it arrives.

        If `timeout` is not ``None`` and the result does not arrive within
        `timeout` seconds then ``TimeoutError`` is raised. If the
        remote call raised an exception then that exception will be reraised
        by get() inside a `RemoteError`.
        """
        if not self.ready():
            self.wait(timeout)

        if self._ready:
            if self._success:
                return self._result
            else:
                raise self._exception
        else:
            raise error.TimeoutError("Result not ready.")

    def ready(self):
        """Return whether the call has completed."""
        if not self._ready:
            self.wait(0)
        return self._ready

    def wait(self, timeout=-1):
        """Wait until the result is available or until `timeout` seconds pass.

        This method always returns None.
        """
        if self._ready:
            return
        self._ready = self._client.wait(self.msg_ids, timeout)
        if self._ready:
            try:
                results = map(self._client.results.get, self.msg_ids)
                self._result = results
                if self._single_result:
                    r = results[0]
                    if isinstance(r, Exception):
                        raise r
                else:
                    results = error.collect_exceptions(results, self._fname)
                self._result = self._reconstruct_result(results)
            except Exception, e:
                self._exception = e
                self._success = False
            else:
                self._success = True
            finally:
                self._metadata = map(self._client.metadata.get, self.msg_ids)
                self._wait_for_outputs(10)

    def successful(self):
        """Return whether the call completed without raising an exception.

        Will raise ``AssertionError`` if the result is not ready.
        """
        assert self.ready()
        return self._success

    #----------------------------------------------------------------
    # Extra methods not in mp.pool.AsyncResult
    #----------------------------------------------------------------

    def get_dict(self, timeout=-1):
        """Get the results as a dict, keyed by engine_id.

        timeout behavior is described in `get()`.
        """

        results = self.get(timeout)
        engine_ids = [ md['engine_id'] for md in self._metadata ]
        bycount = sorted(engine_ids, key=lambda k: engine_ids.count(k))
        maxcount = bycount.count(bycount[-1])
        if maxcount > 1:
            raise ValueError("Cannot build dict, %i jobs ran on engine #%i"%(
                    maxcount, bycount[-1]))

        return dict(zip(engine_ids,results))

    @property
    def result(self):
        """result property wrapper for `get(timeout=0)`."""
        return self.get()

    # abbreviated alias:
    r = result

    @property
    @check_ready
    def metadata(self):
        """property for accessing execution metadata."""
        if self._single_result:
            return self._metadata[0]
        else:
            return self._metadata

    @property
    def result_dict(self):
        """result property as a dict."""
        return self.get_dict()

    def __dict__(self):
        return self.get_dict(0)

    def abort(self):
        """abort my tasks."""
        assert not self.ready(), "Can't abort, I am already done!"
        return self._client.abort(self.msg_ids, targets=self._targets, block=True)

    @property
    def sent(self):
        """check whether my messages have been sent."""
        return self._tracker.done

    def wait_for_send(self, timeout=-1):
        """wait for pyzmq send to complete.

        This is necessary when sending arrays that you intend to edit in-place.
        `timeout` is in seconds, and will raise TimeoutError if it is reached
        before the send completes.
        """
        return self._tracker.wait(timeout)

    #-------------------------------------
    # dict-access
    #-------------------------------------

    @check_ready
    def __getitem__(self, key):
        """getitem returns result value(s) if keyed by int/slice, or metadata if key is str.
        """
        if isinstance(key, int):
            return error.collect_exceptions([self._result[key]], self._fname)[0]
        elif isinstance(key, slice):
            return error.collect_exceptions(self._result[key], self._fname)
        elif isinstance(key, basestring):
            values = [ md[key] for md in self._metadata ]
            if self._single_result:
                return values[0]
            else:
                return values
        else:
            raise TypeError("Invalid key type %r, must be 'int','slice', or 'str'"%type(key))

    def __getattr__(self, key):
        """getattr maps to getitem for convenient attr access to metadata."""
        try:
            return self.__getitem__(key)
        except (error.TimeoutError, KeyError):
            raise AttributeError("%r object has no attribute %r"%(
                    self.__class__.__name__, key))

    # asynchronous iterator:
    def __iter__(self):
        if self._single_result:
            raise TypeError("AsyncResults with a single result are not iterable.")
        try:
            rlist = self.get(0)
        except error.TimeoutError:
            # wait for each result individually
            for msg_id in self.msg_ids:
                ar = AsyncResult(self._client, msg_id, self._fname)
                yield ar.get()
        else:
            # already done
            for r in rlist:
                yield r

    def __len__(self):
        return len(self.msg_ids)

    #-------------------------------------
    # Sugar methods and attributes
    #-------------------------------------

    def timedelta(self, start, end, start_key=min, end_key=max):
        """compute the difference between two sets of timestamps

        The default behavior is to use the earliest of the first
        and the latest of the second list, but this can be changed
        by passing a different

        Parameters
        ----------

        start : one or more datetime objects (e.g. ar.submitted)
        end : one or more datetime objects (e.g. ar.received)
        start_key : callable
            Function to call on `start` to extract the relevant
            entry [defalt: min]
        end_key : callable
            Function to call on `end` to extract the relevant
            entry [default: max]

        Returns
        -------

        dt : float
            The time elapsed (in seconds) between the two selected timestamps.
        """
        if not isinstance(start, datetime):
            # handle single_result AsyncResults, where ar.stamp is single object,
            # not a list
            start = start_key(start)
        if not isinstance(end, datetime):
            # handle single_result AsyncResults, where ar.stamp is single object,
            # not a list
            end = end_key(end)
        return _total_seconds(end - start)

    @property
    def progress(self):
        """the number of tasks which have been completed at this point.

        Fractional progress would be given by 1.0 * ar.progress / len(ar)
        """
        self.wait(0)
        return len(self) - len(set(self.msg_ids).intersection(self._client.outstanding))

    @property
    def elapsed(self):
        """elapsed time since initial submission"""
        if self.ready():
            return self.wall_time

        now = submitted = datetime.now()
        for msg_id in self.msg_ids:
            if msg_id in self._client.metadata:
                stamp = self._client.metadata[msg_id]['submitted']
                if stamp and stamp < submitted:
                    submitted = stamp
        return _total_seconds(now-submitted)

    @property
    @check_ready
    def serial_time(self):
        """serial computation time of a parallel calculation

        Computed as the sum of (completed-started) of each task
        """
        t = 0
        for md in self._metadata:
            t += _total_seconds(md['completed'] - md['started'])
        return t

    @property
    @check_ready
    def wall_time(self):
        """actual computation time of a parallel calculation

        Computed as the time between the latest `received` stamp
        and the earliest `submitted`.

        Only reliable if Client was spinning/waiting when the task finished, because
        the `received` timestamp is created when a result is pulled off of the zmq queue,
        which happens as a result of `client.spin()`.

        For similar comparison of other timestamp pairs, check out AsyncResult.timedelta.

        """
        return self.timedelta(self.submitted, self.received)

    def wait_interactive(self, interval=1., timeout=None):
        """interactive wait, printing progress at regular intervals"""
        N = len(self)
        tic = time.time()
        while not self.ready() and (timeout is None or time.time() - tic <= timeout):
            self.wait(interval)
            clear_output()
            print("%4i/%i tasks finished after %4i s" % (self.progress, N, self.elapsed), end="")
            sys.stdout.flush()
        print()
        print("done")

    def _republish_displaypub(self, content, eid):
        """republish individual displaypub content dicts"""
        try:
            ip = get_ipython()
        except NameError:
            # displaypub is meaningless outside IPython
            return
        md = content['metadata'] or {}
        md['engine'] = eid
        ip.display_pub.publish(content['source'], content['data'], md)

    def _display_stream(self, text, prefix='', file=None):
        if not text:
            # nothing to display
            return
        if file is None:
            file = sys.stdout
        end = '' if text.endswith('\n') else '\n'

        multiline = text.count('\n') > int(text.endswith('\n'))
        if prefix and multiline and not text.startswith('\n'):
            prefix = prefix + '\n'
        print("%s%s" % (prefix, text), file=file, end=end)

    def _display_single_result(self):
        self._display_stream(self.stdout)
        self._display_stream(self.stderr, file=sys.stderr)

        try:
            get_ipython()
        except NameError:
            # displaypub is meaningless outside IPython
            return

        for output in self.outputs:
            self._republish_displaypub(output, self.engine_id)

        if self.pyout is not None:
            display(self.get())

    def _wait_for_outputs(self, timeout=-1):
        """wait for the 'status=idle' message that indicates we have all outputs
        """
        if not self._success:
            # don't wait on errors
            return
        tic = time.time()
        while not all(md['outputs_ready'] for md in self._metadata):
            time.sleep(0.01)
            self._client._flush_iopub(self._client._iopub_socket)
            if timeout >= 0 and time.time() > tic + timeout:
                break

    @check_ready
    def display_outputs(self, groupby="type"):
        """republish the outputs of the computation

        Parameters
        ----------

        groupby : str [default: type]
            if 'type':
                Group outputs by type (show all stdout, then all stderr, etc.):

                [stdout:1] foo
                [stdout:2] foo
                [stderr:1] bar
                [stderr:2] bar
            if 'engine':
                Display outputs for each engine before moving on to the next:

                [stdout:1] foo
                [stderr:1] bar
                [stdout:2] foo
                [stderr:2] bar

            if 'order':
                Like 'type', but further collate individual displaypub
                outputs.  This is meant for cases of each command producing
                several plots, and you would like to see all of the first
                plots together, then all of the second plots, and so on.
        """
        if self._single_result:
            self._display_single_result()
            return

        stdouts = self.stdout
        stderrs = self.stderr
        pyouts  = self.pyout
        output_lists = self.outputs
        results = self.get()

        targets = self.engine_id

        if groupby == "engine":
            for eid,stdout,stderr,outputs,r,pyout in zip(
                    targets, stdouts, stderrs, output_lists, results, pyouts
                ):
                self._display_stream(stdout, '[stdout:%i] ' % eid)
                self._display_stream(stderr, '[stderr:%i] ' % eid, file=sys.stderr)

                try:
                    get_ipython()
                except NameError:
                    # displaypub is meaningless outside IPython
                    return

                if outputs or pyout is not None:
                    _raw_text('[output:%i]' % eid)

                for output in outputs:
                    self._republish_displaypub(output, eid)

                if pyout is not None:
                    display(r)

        elif groupby in ('type', 'order'):
            # republish stdout:
            for eid,stdout in zip(targets, stdouts):
                self._display_stream(stdout, '[stdout:%i] ' % eid)

            # republish stderr:
            for eid,stderr in zip(targets, stderrs):
                self._display_stream(stderr, '[stderr:%i] ' % eid, file=sys.stderr)

            try:
                get_ipython()
            except NameError:
                # displaypub is meaningless outside IPython
                return

            if groupby == 'order':
                output_dict = dict((eid, outputs) for eid,outputs in zip(targets, output_lists))
                N = max(len(outputs) for outputs in output_lists)
                for i in range(N):
                    for eid in targets:
                        outputs = output_dict[eid]
                        if len(outputs) >= N:
                            _raw_text('[output:%i]' % eid)
                            self._republish_displaypub(outputs[i], eid)
            else:
                # republish displaypub output
                for eid,outputs in zip(targets, output_lists):
                    if outputs:
                        _raw_text('[output:%i]' % eid)
                    for output in outputs:
                        self._republish_displaypub(output, eid)

            # finally, add pyout:
            for eid,r,pyout in zip(targets, results, pyouts):
                if pyout is not None:
                    display(r)

        else:
            raise ValueError("groupby must be one of 'type', 'engine', 'collate', not %r" % groupby)

class AsyncMapResult(AsyncResult):
    """Class for representing results of non-blocking gathers.

    This will properly reconstruct the gather.

    This class is iterable at any time, and will wait on results as they come.

    If ordered=False, then the first results to arrive will come first, otherwise
    results will be yielded in the order they were submitted.

    """

    def __init__(self, client, msg_ids, mapObject, fname='', ordered=True):
        AsyncResult.__init__(self, client, msg_ids, fname=fname)
        self._mapObject = mapObject
        self._single_result = False
        self.ordered = ordered

    def _reconstruct_result(self, res):
        """Perform the gather on the actual results."""
        return self._mapObject.joinPartitions(res)

    # asynchronous iterator:
    def __iter__(self):
        it = self._ordered_iter if self.ordered else self._unordered_iter
        for r in it():
            yield r

    # asynchronous ordered iterator:
    def _ordered_iter(self):
        """iterator for results *as they arrive*, preserving submission order."""
        try:
            rlist = self.get(0)
        except error.TimeoutError:
            # wait for each result individually
            for msg_id in self.msg_ids:
                ar = AsyncResult(self._client, msg_id, self._fname)
                rlist = ar.get()
                try:
                    for r in rlist:
                        yield r
                except TypeError:
                    # flattened, not a list
                    # this could get broken by flattened data that returns iterables
                    # but most calls to map do not expose the `flatten` argument
                    yield rlist
        else:
            # already done
            for r in rlist:
                yield r

    # asynchronous unordered iterator:
    def _unordered_iter(self):
        """iterator for results *as they arrive*, on FCFS basis, ignoring submission order."""
        try:
            rlist = self.get(0)
        except error.TimeoutError:
            pending = set(self.msg_ids)
            while pending:
                try:
                    self._client.wait(pending, 1e-3)
                except error.TimeoutError:
                    # ignore timeout error, because that only means
                    # *some* jobs are outstanding
                    pass
                # update ready set with those no longer outstanding:
                ready = pending.difference(self._client.outstanding)
                # update pending to exclude those that are finished
                pending = pending.difference(ready)
                while ready:
                    msg_id = ready.pop()
                    ar = AsyncResult(self._client, msg_id, self._fname)
                    rlist = ar.get()
                    try:
                        for r in rlist:
                            yield r
                    except TypeError:
                        # flattened, not a list
                        # this could get broken by flattened data that returns iterables
                        # but most calls to map do not expose the `flatten` argument
                        yield rlist
        else:
            # already done
            for r in rlist:
                yield r

class AsyncHubResult(AsyncResult):
    """Class to wrap pending results that must be requested from the Hub.

    Note that waiting/polling on these objects requires polling the Hubover the network,
    so use `AsyncHubResult.wait()` sparingly.
    """

    def _wait_for_outputs(self, timeout=None):
        """no-op, because HubResults are never incomplete"""
        return

    def wait(self, timeout=-1):
        """wait for result to complete."""
        start = time.time()
        if self._ready:
            return
        local_ids = filter(lambda msg_id: msg_id in self._client.outstanding, self.msg_ids)
        local_ready = self._client.wait(local_ids, timeout)
        if local_ready:
            remote_ids = filter(lambda msg_id: msg_id not in self._client.results, self.msg_ids)
            if not remote_ids:
                self._ready = True
            else:
                rdict = self._client.result_status(remote_ids, status_only=False)
                pending = rdict['pending']
                while pending and (timeout < 0 or time.time() < start+timeout):
                    rdict = self._client.result_status(remote_ids, status_only=False)
                    pending = rdict['pending']
                    if pending:
                        time.sleep(0.1)
                if not pending:
                    self._ready = True
        if self._ready:
            try:
                results = map(self._client.results.get, self.msg_ids)
                self._result = results
                if self._single_result:
                    r = results[0]
                    if isinstance(r, Exception):
                        raise r
                else:
                    results = error.collect_exceptions(results, self._fname)
                self._result = self._reconstruct_result(results)
            except Exception, e:
                self._exception = e
                self._success = False
            else:
                self._success = True
            finally:
                self._metadata = map(self._client.metadata.get, self.msg_ids)

__all__ = ['AsyncResult', 'AsyncMapResult', 'AsyncHubResult']


"""File wrangling."""

from coverage.backward import to_string
from coverage.misc import CoverageException
import fnmatch, os, os.path, re, sys
import ntpath, posixpath

class FileLocator(object):
    """Understand how filenames work."""

    def __init__(self):
        # The absolute path to our current directory.
        self.relative_dir = os.path.normcase(abs_file(os.curdir) + os.sep)

        # Cache of results of calling the canonical_filename() method, to
        # avoid duplicating work.
        self.canonical_filename_cache = {}

    def relative_filename(self, filename):
        """Return the relative form of `filename`.

        The filename will be relative to the current directory when the
        `FileLocator` was constructed.

        """
        fnorm = os.path.normcase(filename)
        if fnorm.startswith(self.relative_dir):
            filename = filename[len(self.relative_dir):]
        return filename

    def canonical_filename(self, filename):
        """Return a canonical filename for `filename`.

        An absolute path with no redundant components and normalized case.

        """
        if filename not in self.canonical_filename_cache:
            if not os.path.isabs(filename):
                for path in [os.curdir] + sys.path:
                    if path is None:
                        continue
                    f = os.path.join(path, filename)
                    if os.path.exists(f):
                        filename = f
                        break
            cf = abs_file(filename)
            self.canonical_filename_cache[filename] = cf
        return self.canonical_filename_cache[filename]

    def get_zip_data(self, filename):
        """Get data from `filename` if it is a zip file path.

        Returns the string data read from the zip file, or None if no zip file
        could be found or `filename` isn't in it.  The data returned will be
        an empty string if the file is empty.

        """
        import zipimport
        markers = ['.zip'+os.sep, '.egg'+os.sep]
        for marker in markers:
            if marker in filename:
                parts = filename.split(marker)
                try:
                    zi = zipimport.zipimporter(parts[0]+marker[:-1])
                except zipimport.ZipImportError:
                    continue
                try:
                    data = zi.get_data(parts[1])
                except IOError:
                    continue
                return to_string(data)
        return None

if sys.platform == 'win32':

    def actual_path(path):
        """Get the actual path of `path`, including the correct case."""
        if path in actual_path.cache:
            return actual_path.cache[path]

        head, tail = os.path.split(path)
        if not tail:
            actpath = head
        elif not head:
            actpath = tail
        else:
            head = actual_path(head)
            if head in actual_path.list_cache:
                files = actual_path.list_cache[head]
            else:
                try:
                    files = os.listdir(head)
                except OSError:
                    files = []
                actual_path.list_cache[head] = files
            normtail = os.path.normcase(tail)
            for f in files:
                if os.path.normcase(f) == normtail:
                    tail = f
                    break
            actpath = os.path.join(head, tail)
        actual_path.cache[path] = actpath
        return actpath

    actual_path.cache = {}
    actual_path.list_cache = {}

else:
    def actual_path(filename):
        """The actual path for non-Windows platforms."""
        return filename

def abs_file(filename):
    """Return the absolute normalized form of `filename`."""
    path = os.path.expandvars(os.path.expanduser(filename))
    path = os.path.abspath(os.path.realpath(path))
    path = actual_path(path)
    return path

def isabs_anywhere(filename):
    """Is `filename` an absolute path on any OS?"""
    return ntpath.isabs(filename) or posixpath.isabs(filename)

def prep_patterns(patterns):
    """Prepare the file patterns for use in a `FnmatchMatcher`.

    If a pattern starts with a wildcard, it is used as a pattern
    as-is.  If it does not start with a wildcard, then it is made
    absolute with the current directory.

    If `patterns` is None, an empty list is returned.

    """
    prepped = []
    for p in patterns or []:
        if p.startswith("*") or p.startswith("?"):
            prepped.append(p)
        else:
            prepped.append(abs_file(p))
    return prepped

class TreeMatcher(object):
    """A matcher for files in a tree."""
    def __init__(self, directories):
        self.dirs = directories[:]

    def __repr__(self):
        return "<TreeMatcher %r>" % self.dirs

    def info(self):
        """A list of strings for displaying when dumping state."""
        return self.dirs

    def add(self, directory):
        """Add another directory to the list we match for."""
        self.dirs.append(directory)

    def match(self, fpath):
        """Does `fpath` indicate a file in one of our trees?"""
        for d in self.dirs:
            if fpath.startswith(d):
                if fpath == d:
                    # This is the same file!
                    return True
                if fpath[len(d)] == os.sep:
                    # This is a file in the directory
                    return True
        return False

class FnmatchMatcher(object):
    """A matcher for files by filename pattern."""
    def __init__(self, pats):
        self.pats = pats[:]

    def __repr__(self):
        return "<FnmatchMatcher %r>" % self.pats

    def info(self):
        """A list of strings for displaying when dumping state."""
        return self.pats

    def match(self, fpath):
        """Does `fpath` match one of our filename patterns?"""
        for pat in self.pats:
            if fnmatch.fnmatch(fpath, pat):
                return True
        return False

def sep(s):
    """Find the path separator used in this string, or os.sep if none."""
    sep_match = re.search(r"[\\/]", s)
    if sep_match:
        the_sep = sep_match.group(0)
    else:
        the_sep = os.sep
    return the_sep

class PathAliases(object):
    """A collection of aliases for paths.

    When combining data files from remote machines, often the paths to source
    code are different, for example, due to OS differences, or because of
    serialized checkouts on continuous integration machines.

    A `PathAliases` object tracks a list of pattern/result pairs, and can
    map a path through those aliases to produce a unified path.

    `locator` is a FileLocator that is used to canonicalize the results.

    """
    def __init__(self, locator=None):
        self.aliases = []
        self.locator = locator

    def add(self, pattern, result):
        """Add the `pattern`/`result` pair to the list of aliases.

        `pattern` is an `fnmatch`-style pattern.  `result` is a simple
        string.  When mapping paths, if a path starts with a match against
        `pattern`, then that match is replaced with `result`.  This models
        isomorphic source trees being rooted at different places on two
        different machines.

        `pattern` can't end with a wildcard component, since that would
        match an entire tree, and not just its root.

        """
        # The pattern can't end with a wildcard component.
        pattern = pattern.rstrip(r"\/")
        if pattern.endswith("*"):
            raise CoverageException("Pattern must not end with wildcards.")
        pattern_sep = sep(pattern)

        # The pattern is meant to match a filepath.  Let's make it absolute
        # unless it already is, or is meant to match any prefix.
        if not pattern.startswith('*') and not isabs_anywhere(pattern):
            pattern = abs_file(pattern)
        pattern += pattern_sep

        # Make a regex from the pattern.  fnmatch always adds a \Z or $ to
        # match the whole string, which we don't want.
        regex_pat = fnmatch.translate(pattern).replace(r'\Z(', '(')
        if regex_pat.endswith("$"):
            regex_pat = regex_pat[:-1]
        # We want */a/b.py to match on Windows too, so change slash to match
        # either separator.
        regex_pat = regex_pat.replace(r"\/", r"[\\/]")
        # We want case-insensitive matching, so add that flag.
        regex = re.compile(r"(?i)" + regex_pat)

        # Normalize the result: it must end with a path separator.
        result_sep = sep(result)
        result = result.rstrip(r"\/") + result_sep
        self.aliases.append((regex, result, pattern_sep, result_sep))

    def map(self, path):
        """Map `path` through the aliases.

        `path` is checked against all of the patterns.  The first pattern to
        match is used to replace the root of the path with the result root.
        Only one pattern is ever used.  If no patterns match, `path` is
        returned unchanged.

        The separator style in the result is made to match that of the result
        in the alias.

        """
        for regex, result, pattern_sep, result_sep in self.aliases:
            m = regex.match(path)
            if m:
                new = path.replace(m.group(0), result)
                if pattern_sep != result_sep:
                    new = new.replace(pattern_sep, result_sep)
                if self.locator:
                    new = self.locator.canonical_filename(new)
                return new
        return path

def find_python_files(dirname):
    """Yield all of the importable Python files in `dirname`, recursively.

    To be importable, the files have to be in a directory with a __init__.py,
    except for `dirname` itself, which isn't required to have one.  The
    assumption is that `dirname` was specified directly, so the user knows
    best, but subdirectories are checked for a __init__.py to be sure we only
    find the importable files.

    """
    for i, (dirpath, dirnames, filenames) in enumerate(os.walk(dirname)):
        if i > 0 and '__init__.py' not in filenames:
            # If a directory doesn't have __init__.py, then it isn't
            # importable and neither are its files
            del dirnames[:]
            continue
        for filename in filenames:
            # We're only interested in files that look like reasonable Python
            # files: Must end with .py or .pyw, and must not have certain funny
            # characters that probably mean they are editor junk.
            if re.match(r"^[^.#~!$@%^&*()+=,]+\.pyw?$", filename):
                yield os.path.join(dirpath, filename)


# encoding: utf-8
"""Event loop integration for the ZeroMQ-based kernels.
"""

#-----------------------------------------------------------------------------
#  Copyright (C) 2011  The IPython Development Team

#  Distributed under the terms of the BSD License.  The full license is in
#  the file COPYING, distributed as part of this software.
#-----------------------------------------------------------------------------

#-----------------------------------------------------------------------------
# Imports
#-----------------------------------------------------------------------------

import sys

# System library imports.
import zmq

# Local imports.
from IPython.config.application import Application
from IPython.utils import io

#------------------------------------------------------------------------------
# Eventloops for integrating the Kernel into different GUIs
#------------------------------------------------------------------------------

def loop_qt4(kernel):
    """Start a kernel with PyQt4 event loop integration."""

    from IPython.external.qt_for_kernel import QtCore
    from IPython.lib.guisupport import get_app_qt4, start_event_loop_qt4

    kernel.app = get_app_qt4([" "])
    kernel.app.setQuitOnLastWindowClosed(False)
    kernel.timer = QtCore.QTimer()
    kernel.timer.timeout.connect(kernel.do_one_iteration)
    # Units for the timer are in milliseconds
    kernel.timer.start(1000*kernel._poll_interval)
    start_event_loop_qt4(kernel.app)

def loop_wx(kernel):
    """Start a kernel with wx event loop support."""

    import wx
    from IPython.lib.guisupport import start_event_loop_wx

    doi = kernel.do_one_iteration
     # Wx uses milliseconds
    poll_interval = int(1000*kernel._poll_interval)

    # We have to put the wx.Timer in a wx.Frame for it to fire properly.
    # We make the Frame hidden when we create it in the main app below.
    class TimerFrame(wx.Frame):
        def __init__(self, func):
            wx.Frame.__init__(self, None, -1)
            self.timer = wx.Timer(self)
            # Units for the timer are in milliseconds
            self.timer.Start(poll_interval)
            self.Bind(wx.EVT_TIMER, self.on_timer)
            self.func = func

        def on_timer(self, event):
            self.func()

    # We need a custom wx.App to create our Frame subclass that has the
    # wx.Timer to drive the ZMQ event loop.
    class IPWxApp(wx.App):
        def OnInit(self):
            self.frame = TimerFrame(doi)
            self.frame.Show(False)
            return True

    # The redirect=False here makes sure that wx doesn't replace
    # sys.stdout/stderr with its own classes.
    kernel.app = IPWxApp(redirect=False)

    # The import of wx on Linux sets the handler for signal.SIGINT
    # to 0.  This is a bug in wx or gtk.  We fix by just setting it
    # back to the Python default.
    import signal
    if not callable(signal.getsignal(signal.SIGINT)):
        signal.signal(signal.SIGINT, signal.default_int_handler)

    start_event_loop_wx(kernel.app)

def loop_tk(kernel):
    """Start a kernel with the Tk event loop."""

    import Tkinter
    doi = kernel.do_one_iteration
    # Tk uses milliseconds
    poll_interval = int(1000*kernel._poll_interval)
    # For Tkinter, we create a Tk object and call its withdraw method.
    class Timer(object):
        def __init__(self, func):
            self.app = Tkinter.Tk()
            self.app.withdraw()
            self.func = func

        def on_timer(self):
            self.func()
            self.app.after(poll_interval, self.on_timer)

        def start(self):
            self.on_timer()  # Call it once to get things going.
            self.app.mainloop()

    kernel.timer = Timer(doi)
    kernel.timer.start()

def loop_gtk(kernel):
    """Start the kernel, coordinating with the GTK event loop"""
    from .gui.gtkembed import GTKEmbed

    gtk_kernel = GTKEmbed(kernel)
    gtk_kernel.start()

def loop_cocoa(kernel):
    """Start the kernel, coordinating with the Cocoa CFRunLoop event loop
    via the matplotlib MacOSX backend.
    """
    import matplotlib
    if matplotlib.__version__ < '1.1.0':
        kernel.log.warn(
        "MacOSX backend in matplotlib %s doesn't have a Timer, "
        "falling back on Tk for CFRunLoop integration.  Note that "
        "even this won't work if Tk is linked against X11 instead of "
        "Cocoa (e.g. EPD).  To use the MacOSX backend in the kernel, "
        "you must use matplotlib >= 1.1.0, or a native libtk."
        )
        return loop_tk(kernel)

    from matplotlib.backends.backend_macosx import TimerMac, show

    # scale interval for sec->ms
    poll_interval = int(1000*kernel._poll_interval)

    real_excepthook = sys.excepthook
    def handle_int(etype, value, tb):
        """don't let KeyboardInterrupts look like crashes"""
        if etype is KeyboardInterrupt:
            io.raw_print("KeyboardInterrupt caught in CFRunLoop")
        else:
            real_excepthook(etype, value, tb)

    # add doi() as a Timer to the CFRunLoop
    def doi():
        # restore excepthook during IPython code
        sys.excepthook = real_excepthook
        kernel.do_one_iteration()
        # and back:
        sys.excepthook = handle_int

    t = TimerMac(poll_interval)
    t.add_callback(doi)
    t.start()

    # but still need a Poller for when there are no active windows,
    # during which time mainloop() returns immediately
    poller = zmq.Poller()
    if kernel.control_stream:
        poller.register(kernel.control_stream.socket, zmq.POLLIN)
    for stream in kernel.shell_streams:
        poller.register(stream.socket, zmq.POLLIN)

    while True:
        try:
            # double nested try/except, to properly catch KeyboardInterrupt
            # due to pyzmq Issue #130
            try:
                # don't let interrupts during mainloop invoke crash_handler:
                sys.excepthook = handle_int
                show.mainloop()
                sys.excepthook = real_excepthook
                # use poller if mainloop returned (no windows)
                # scale by extra factor of 10, since it's a real poll
                poller.poll(10*poll_interval)
                kernel.do_one_iteration()
            except:
                raise
        except KeyboardInterrupt:
            # Ctrl-C shouldn't crash the kernel
            io.raw_print("KeyboardInterrupt caught in kernel")
        finally:
            # ensure excepthook is restored
            sys.excepthook = real_excepthook

# mapping of keys to loop functions
loop_map = {
    'qt' : loop_qt4,
    'qt4': loop_qt4,
    'inline': None,
    'osx': loop_cocoa,
    'wx' : loop_wx,
    'tk' : loop_tk,
    'gtk': loop_gtk,
    None : None,
}

def enable_gui(gui, kernel=None):
    """Enable integration with a given GUI"""
    if gui not in loop_map:
        raise ValueError("GUI %r not supported" % gui)
    if kernel is None:
        if Application.initialized():
            kernel = getattr(Application.instance(), 'kernel', None)
        if kernel is None:
            raise RuntimeError("You didn't specify a kernel,"
                " and no IPython Application with a kernel appears to be running."
            )
    loop = loop_map[gui]
    if kernel.eventloop is not None and kernel.eventloop is not loop:
        raise RuntimeError("Cannot activate multiple GUI eventloops")
    kernel.eventloop = loop


#-------------------------------------------------------------------------------
# Core routines for computing properties of symmetric random matrices.
#-------------------------------------------------------------------------------

import numpy as np
ra = np.random
la = np.linalg

def GOE(N):
    """Creates an NxN element of the Gaussian Orthogonal Ensemble"""
    m = ra.standard_normal((N,N))
    m += m.T
    return m/2

def center_eigenvalue_diff(mat):
    """Compute the eigvals of mat and then find the center eigval difference."""
    N = len(mat)
    evals = np.sort(la.eigvals(mat))
    diff = np.abs(evals[N/2] - evals[N/2-1])
    return diff

def ensemble_diffs(num, N):
    """Return num eigenvalue diffs for the NxN GOE ensemble."""
    diffs = np.empty(num)
    for i in xrange(num):
        mat = GOE(N)
        diffs[i] = center_eigenvalue_diff(mat)
    return diffs

def normalize_diffs(diffs):
    """Normalize an array of eigenvalue diffs."""
    return diffs/diffs.mean()

def normalized_ensemble_diffs(num, N):
    """Return num *normalized* eigenvalue diffs for the NxN GOE ensemble."""
    diffs = ensemble_diffs(num, N)
    return normalize_diffs(diffs)