Update installed plugin package(s).

    Each plugin package must have a directory (**NOT** a link) containing a
    ``properties.yml`` file with a ``package_name`` value in the following
    directory:

        <conda prefix>/share/microdrop/plugins/available/

    Parameters
    ----------
    *args
        Extra arguments to pass to Conda ``install`` command.

        See :func:`install`.
    package_name : str or list, optional
        Name(s) of MicroDrop plugin Conda package(s) to update.

        By default, all installed packages are updated.
    **kwargs
        See :func:`install`.

    Returns
    -------
    dict
        Conda installation log object (from JSON ``conda install`` output).

    Notes
    -----
    Only actual plugin directories are considered when updating (i.e., **NOT**
    directory links).

    This permits, for example, linking of a plugin into the ``available``
    plugins directory during development without risking overwriting during an
    update.

    Raises
    ------
    RuntimeError
        If one or more installed plugin packages cannot be updated.

        This can happen, for example, if the plugin package is not available in
        any of the specified Conda channels.

    See also
    --------
    :func:`installed_plugins`

def update(*args, **kwargs):
    '''
    Update installed plugin package(s).

    Each plugin package must have a directory (**NOT** a link) containing a
    ``properties.yml`` file with a ``package_name`` value in the following
    directory:

        <conda prefix>/share/microdrop/plugins/available/

    Parameters
    ----------
    *args
        Extra arguments to pass to Conda ``install`` command.

        See :func:`install`.
    package_name : str or list, optional
        Name(s) of MicroDrop plugin Conda package(s) to update.

        By default, all installed packages are updated.
    **kwargs
        See :func:`install`.

    Returns
    -------
    dict
        Conda installation log object (from JSON ``conda install`` output).

    Notes
    -----
    Only actual plugin directories are considered when updating (i.e., **NOT**
    directory links).

    This permits, for example, linking of a plugin into the ``available``
    plugins directory during development without risking overwriting during an
    update.

    Raises
    ------
    RuntimeError
        If one or more installed plugin packages cannot be updated.

        This can happen, for example, if the plugin package is not available in
        any of the specified Conda channels.

    See also
    --------
    :func:`installed_plugins`
    '''
    package_name = kwargs.pop('package_name', None)

    # Only consider **installed** plugins (see `installed_plugins()` docstring).
    installed_plugins_ = installed_plugins(only_conda=True)
    if installed_plugins_:
        plugin_packages = [plugin_i['package_name']
                           for plugin_i in installed_plugins_]
        if package_name is None:
            package_name = plugin_packages
        elif isinstance(package_name, types.StringTypes):
            package_name = [package_name]
        logger.info('Installing any available updates for plugins: %s',
                    ','.join('`{}`'.format(package_name_i)
                             for package_name_i in package_name))
        # Attempt to install plugin packages.
        try:
            install_log = install(package_name, *args, **kwargs)
        except RuntimeError, exception:
            if 'CondaHTTPError' in str(exception):
                raise IOError('Error accessing update server.')
            else:
                raise
        if 'actions' in install_log:
            logger.debug('Updated plugin(s): ```%s```', install_log['actions'])
        return install_log
    else:
        return {}