<commit_before># -*- coding: utf-8 -*-
'''
Return salt data via hipchat.

.. versionadded:: 2015.5.0

The following fields can be set in the minion conf file::

    hipchat.room_id (required)
    hipchat.api_key (required)
    hipchat.api_version (required)
    hipchat.from_name (required)
    hipchat.color (optional)
    hipchat.notify (optional)
    hipchat.profile (optional)
    hipchat.url (optional)

Alternative configuration values can be used by prefacing the configuration.
Any values not found in the alternative configuration will be pulled from
the default location::

    hipchat.room_id
    hipchat.api_key
    hipchat.api_version
    hipchat.from_name

Hipchat settings may also be configured as:

.. code-block:: yaml

    hipchat:
      room_id: RoomName
      api_key: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
      api_version: v1
      from_name: user@email.com

    alternative.hipchat:
      room_id: RoomName
      api_key: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
      api_version: v1
      from_name: user@email.com

    hipchat_profile:
      hipchat.api_key: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
      hipchat.api_version: v1
      hipchat.from_name: user@email.com

    hipchat:
      profile: hipchat_profile
      room_id: RoomName

    alternative.hipchat:
      profile: hipchat_profile
      room_id: RoomName

    hipchat:
      room_id: RoomName
      api_key: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
      api_version: v1
      api_url: api.hipchat.com
      from_name: user@email.com

To use the HipChat returner, append '--return hipchat' to the salt command.

.. code-block:: bash

    salt '*' test.ping --return hipchat

To use the alternative configuration, append '--return_config alternative' to the salt command.

.. versionadded:: 2015.5.0

.. code-block:: bash

    salt '*' test.ping --return hipchat --return_config alternative

To override individual configuration items, append --return_kwargs '{"key:": "value"}' to the salt command.

.. versionadded:: Boron

.. code-block:: bash

    salt '*' test.ping --return hipchat --return_kwargs '{"room_id": "another-room"}'

'''
from __future__ import absolute_import

# Import Python libs
import json
import pprint
import logging

# pylint: disable=import-error,no-name-in-module
from salt.ext.six.moves.urllib.parse import urljoin as _urljoin
from salt.ext.six.moves.urllib.parse import urlencode as _urlencode
import salt.ext.six.moves.http_client
# pylint: enable=import-error

# Import Salt Libs
import salt.returners

log = logging.getLogger(__name__)
__virtualname__ = 'hipchat'

def _get_options(ret=None):
    '''
    Get the hipchat options from salt.
    '''

    defaults = {'color': 'yellow',
                'notify': False,
                'api_url': 'api.hipchat.com'}

    attrs = {'hipchat_profile': 'profile',
             'room_id': 'room_id',
             'from_name': 'from_name',
             'api_key': 'api_key',
             'api_version': 'api_version',
             'color': 'color',
             'notify': 'notify',
             'api_url': 'api_url',
             }

    profile_attr = 'hipchat_profile'

    profile_attrs = {'from_jid': 'from_jid',
                     'api_key': 'api_key',
                     'api_version': 'api_key',
                     'api_url': 'api_url',
                     }

    _options = salt.returners.get_returner_options(__virtualname__,
                                                   ret,
                                                   attrs,
                                                   profile_attr=profile_attr,
                                                   profile_attrs=profile_attrs,
                                                   __salt__=__salt__,
                                                   __opts__=__opts__,
                                                   defaults=defaults)
    return _options

def __virtual__():
    '''
    Return virtual name of the module.

    :return: The virtual name of the module.
    '''
    return __virtualname__

def _query(function,
           api_key=None,
           api_version=None,
           room_id=None,
           api_url=None,
           method='GET',
           data=None):
    '''
    HipChat object method function to construct and execute on the API URL.

    :param api_key:     The HipChat api key.
    :param function:    The HipChat api function to perform.
    :param api_version: The HipChat api version (v1 or v2).
    :param method:      The HTTP method, e.g. GET or POST.
    :param data:        The data to be sent for POST method.
    :return:            The json response from the API call or False.
    '''
    headers = {}
    query_params = {}

    if room_id:
        room_id = 'room/{0}/notification'.format(str(room_id))
    else:
        room_id = 'room/0/notification'

    hipchat_functions = {
        'v1': {
            'rooms': {
                'request': 'rooms/list',
                'response': 'rooms',
            },
            'users': {
                'request': 'users/list',
                'response': 'users',
            },
            'message': {
                'request': 'rooms/message',
                'response': 'status',
            },
        },
        'v2': {
            'rooms': {
                'request': 'room',
                'response': 'items',
            },
            'users': {
                'request': 'user',
                'response': 'items',
            },
            'message': {
                'request': room_id,
                'response': None,
            },
        },
    }

    api_url = 'https://{0}'.format(api_url)
    base_url = _urljoin(api_url, api_version + '/')
    path = hipchat_functions.get(api_version).get(function).get('request')
    url = _urljoin(base_url, path, False)

    if api_version == 'v1':
        query_params['format'] = 'json'
        query_params['auth_token'] = api_key

        if method == 'POST':
            headers['Content-Type'] = 'application/x-www-form-urlencoded'

        if data:
            if data.get('notify'):
                data['notify'] = 1
            else:
                data['notify'] = 0
            data = _urlencode(data)
    elif api_version == 'v2':
        headers['Content-Type'] = 'application/json'
        headers['Authorization'] = 'Bearer {0}'.format(api_key)
        if data:
            data = json.dumps(data)
    else:
        log.error('Unsupported HipChat API version')
        return False

    result = salt.utils.http.query(
        url,
        method,
        params=query_params,
        data=data,
        decode=True,
        status=True,
        header_dict=headers,
        opts=__opts__,
    )

    if result.get('status', None) == salt.ext.six.moves.http_client.OK:
        response = hipchat_functions.get(api_version).get(function).get('response')
        return result.get('dict', {}).get(response, None)
    elif result.get('status', None) == salt.ext.six.moves.http_client.NO_CONTENT:
        return False
    else:
        log.debug(url)
        log.debug(query_params)
        log.debug(data)
        log.debug(result)
        if result.get('error'):
            log.error(result)
        return False

def _send_message(room_id,
                  message,
                  from_name,
                  api_key=None,
                  api_version=None,
                  api_url=None,
                  color=None,
                  notify=False):
    '''
    Send a message to a HipChat room.
    :param room_id:     The room id or room name, either will work.
    :param message:     The message to send to the HipChat room.
    :param from_name:   Specify who the message is from.
    :param api_key:     The HipChat api key, if not specified in the configuration.
    :param api_version: The HipChat api version, if not specified in the configuration.
    :param color:       The color for the message, default: yellow.
    :param notify:      Whether to notify the room, default: False.
    :return:            Boolean if message was sent successfully.
    '''

    parameters = dict()
    parameters['room_id'] = room_id
    parameters['from'] = from_name[:15]
    parameters['message'] = message[:10000]
    parameters['message_format'] = 'text'
    parameters['color'] = color
    parameters['notify'] = notify

    result = _query(function='message',
                    api_key=api_key,
                    api_version=api_version,
                    room_id=room_id,
                    api_url=api_url,
                    method='POST',
                    data=parameters)

    if result:
        return True
    else:
        return False

def _verify_options(options):
    '''
    Verify Hipchat options and log warnings

    Returns True if all options can be verified,
    otherwise False
    '''
    if not options.get('room_id'):
        log.error('hipchat.room_id not defined in salt config')
        return False

    if not options.get('from_name'):
        log.error('hipchat.from_name not defined in salt config')
        return False

    if not options.get('api_key'):
        log.error('hipchat.api_key not defined in salt config')
        return False

    if not options.get('api_version'):
        log.error('hipchat.api_version not defined in salt config')
        return False

    return True

def returner(ret):
    '''
    Send an hipchat message with the return data from a job
    '''

    _options = _get_options(ret)

    if not _verify_options(_options):
        return

    message = ('id: {0}\r\n'
               'function: {1}\r\n'
               'function args: {2}\r\n'
               'jid: {3}\r\n'
               'return: {4}\r\n').format(
                    ret.get('id'),
                    ret.get('fun'),
                    ret.get('fun_args'),
                    ret.get('jid'),
                    pprint.pformat(ret.get('return')))

    if ret.get('retcode') == 0:
        color = _options.get('color')
    else:
        color = 'red'

    hipchat = _send_message(_options.get('room_id'),
                            message,
                            _options.get('from_name'),
                            _options.get('api_key'),
                            _options.get('api_version'),
                            _options.get('api_url'),
                            color,
                            _options.get('notify'))

    return hipchat

def event_return(events):
    '''
    Return event data to hipchat
    '''
    _options = _get_options()

    for event in events:
        # TODO:
        # Pre-process messages to apply individualized colors for various
        # event types.
        log.trace('Hipchat returner received event: {0}'.format(event))
        _send_message(_options.get('room_id'),
                      event['data'],
                      _options.get('from_name'),
                      _options.get('api_key'),
                      _options.get('api_version'),
                      _options.get('api_url'),
                      _options.get('color'),
                      _options.get('notify'))
<commit_msg>cleaned up lint errors<commit_after># -*- coding: utf-8 -*-
'''
Return salt data via hipchat.

.. versionadded:: 2015.5.0

The following fields can be set in the minion conf file::

    hipchat.room_id (required)
    hipchat.api_key (required)
    hipchat.api_version (required)
    hipchat.from_name (required)
    hipchat.color (optional)
    hipchat.notify (optional)
    hipchat.profile (optional)
    hipchat.url (optional)

Alternative configuration values can be used by prefacing the configuration.
Any values not found in the alternative configuration will be pulled from
the default location::

    hipchat.room_id
    hipchat.api_key
    hipchat.api_version
    hipchat.from_name

Hipchat settings may also be configured as:

.. code-block:: yaml

    hipchat:
      room_id: RoomName
      api_key: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
      api_version: v1
      from_name: user@email.com

    alternative.hipchat:
      room_id: RoomName
      api_key: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
      api_version: v1
      from_name: user@email.com

    hipchat_profile:
      hipchat.api_key: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
      hipchat.api_version: v1
      hipchat.from_name: user@email.com

    hipchat:
      profile: hipchat_profile
      room_id: RoomName

    alternative.hipchat:
      profile: hipchat_profile
      room_id: RoomName

    hipchat:
      room_id: RoomName
      api_key: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
      api_version: v1
      api_url: api.hipchat.com
      from_name: user@email.com

To use the HipChat returner, append '--return hipchat' to the salt command.

.. code-block:: bash

    salt '*' test.ping --return hipchat

To use the alternative configuration, append '--return_config alternative' to the salt command.

.. versionadded:: 2015.5.0

.. code-block:: bash

    salt '*' test.ping --return hipchat --return_config alternative

To override individual configuration items, append --return_kwargs '{"key:": "value"}' to the salt command.

.. versionadded:: Boron

.. code-block:: bash

    salt '*' test.ping --return hipchat --return_kwargs '{"room_id": "another-room"}'

'''
from __future__ import absolute_import

# Import Python libs
import json
import pprint
import logging

# pylint: disable=import-error,no-name-in-module
from salt.ext.six.moves.urllib.parse import urljoin as _urljoin
from salt.ext.six.moves.urllib.parse import urlencode as _urlencode
import salt.ext.six.moves.http_client
# pylint: enable=import-error

# Import Salt Libs
import salt.returners

log = logging.getLogger(__name__)
__virtualname__ = 'hipchat'

def _get_options(ret=None):
    '''
    Get the hipchat options from salt.
    '''

    defaults = {'color': 'yellow',
                'notify': False,
                'api_url': 'api.hipchat.com'}

    attrs = {'hipchat_profile': 'profile',
             'room_id': 'room_id',
             'from_name': 'from_name',
             'api_key': 'api_key',
             'api_version': 'api_version',
             'color': 'color',
             'notify': 'notify',
             'api_url': 'api_url',
             }

    profile_attr = 'hipchat_profile'

    profile_attrs = {'from_jid': 'from_jid',
                     'api_key': 'api_key',
                     'api_version': 'api_key',
                     'api_url': 'api_url',
                     }

    _options = salt.returners.get_returner_options(__virtualname__,
                                                   ret,
                                                   attrs,
                                                   profile_attr=profile_attr,
                                                   profile_attrs=profile_attrs,
                                                   __salt__=__salt__,
                                                   __opts__=__opts__,
                                                   defaults=defaults)
    return _options

def __virtual__():
    '''
    Return virtual name of the module.

    :return: The virtual name of the module.
    '''
    return __virtualname__

def _query(function,
           api_key=None,
           api_version=None,
           room_id=None,
           api_url=None,
           method='GET',
           data=None):
    '''
    HipChat object method function to construct and execute on the API URL.

    :param api_key:     The HipChat api key.
    :param function:    The HipChat api function to perform.
    :param api_version: The HipChat api version (v1 or v2).
    :param method:      The HTTP method, e.g. GET or POST.
    :param data:        The data to be sent for POST method.
    :return:            The json response from the API call or False.
    '''
    headers = {}
    query_params = {}

    if room_id:
        room_id = 'room/{0}/notification'.format(str(room_id))
    else:
        room_id = 'room/0/notification'

    hipchat_functions = {
        'v1': {
            'rooms': {
                'request': 'rooms/list',
                'response': 'rooms',
            },
            'users': {
                'request': 'users/list',
                'response': 'users',
            },
            'message': {
                'request': 'rooms/message',
                'response': 'status',
            },
        },
        'v2': {
            'rooms': {
                'request': 'room',
                'response': 'items',
            },
            'users': {
                'request': 'user',
                'response': 'items',
            },
            'message': {
                'request': room_id,
                'response': None,
            },
        },
    }

    api_url = 'https://{0}'.format(api_url)
    base_url = _urljoin(api_url, api_version + '/')
    path = hipchat_functions.get(api_version).get(function).get('request')
    url = _urljoin(base_url, path, False)

    if api_version == 'v1':
        query_params['format'] = 'json'
        query_params['auth_token'] = api_key

        if method == 'POST':
            headers['Content-Type'] = 'application/x-www-form-urlencoded'

        if data:
            if data.get('notify'):
                data['notify'] = 1
            else:
                data['notify'] = 0
            data = _urlencode(data)
    elif api_version == 'v2':
        headers['Content-Type'] = 'application/json'
        headers['Authorization'] = 'Bearer {0}'.format(api_key)
        if data:
            data = json.dumps(data)
    else:
        log.error('Unsupported HipChat API version')
        return False

    result = salt.utils.http.query(
        url,
        method,
        params=query_params,
        data=data,
        decode=True,
        status=True,
        header_dict=headers,
        opts=__opts__,
    )

    if result.get('status', None) == salt.ext.six.moves.http_client.OK:
        response = hipchat_functions.get(api_version).get(function).get('response')
        return result.get('dict', {}).get(response, None)
    elif result.get('status', None) == salt.ext.six.moves.http_client.NO_CONTENT:
        return False
    else:
        log.debug(url)
        log.debug(query_params)
        log.debug(data)
        log.debug(result)
        if result.get('error'):
            log.error(result)
        return False

def _send_message(room_id,
                  message,
                  from_name,
                  api_key=None,
                  api_version=None,
                  api_url=None,
                  color=None,
                  notify=False):
    '''
    Send a message to a HipChat room.
    :param room_id:     The room id or room name, either will work.
    :param message:     The message to send to the HipChat room.
    :param from_name:   Specify who the message is from.
    :param api_key:     The HipChat api key, if not specified in the configuration.
    :param api_version: The HipChat api version, if not specified in the configuration.
    :param color:       The color for the message, default: yellow.
    :param notify:      Whether to notify the room, default: False.
    :return:            Boolean if message was sent successfully.
    '''

    parameters = dict()
    parameters['room_id'] = room_id
    parameters['from'] = from_name[:15]
    parameters['message'] = message[:10000]
    parameters['message_format'] = 'text'
    parameters['color'] = color
    parameters['notify'] = notify

    result = _query(function='message',
                    api_key=api_key,
                    api_version=api_version,
                    room_id=room_id,
                    api_url=api_url,
                    method='POST',
                    data=parameters)

    if result:
        return True
    else:
        return False

def _verify_options(options):
    '''
    Verify Hipchat options and log warnings

    Returns True if all options can be verified,
    otherwise False
    '''
    if not options.get('room_id'):
        log.error('hipchat.room_id not defined in salt config')
        return False

    if not options.get('from_name'):
        log.error('hipchat.from_name not defined in salt config')
        return False

    if not options.get('api_key'):
        log.error('hipchat.api_key not defined in salt config')
        return False

    if not options.get('api_version'):
        log.error('hipchat.api_version not defined in salt config')
        return False

    return True

def returner(ret):
    '''
    Send an hipchat message with the return data from a job
    '''

    _options = _get_options(ret)

    if not _verify_options(_options):
        return

    message = ('id: {0}\r\n'
               'function: {1}\r\n'
               'function args: {2}\r\n'
               'jid: {3}\r\n'
               'return: {4}\r\n').format(
                    ret.get('id'),
                    ret.get('fun'),
                    ret.get('fun_args'),
                    ret.get('jid'),
                    pprint.pformat(ret.get('return')))

    if ret.get('retcode') == 0:
        color = _options.get('color')
    else:
        color = 'red'

    hipchat = _send_message(_options.get('room_id'),
                            message,
                            _options.get('from_name'),
                            _options.get('api_key'),
                            _options.get('api_version'),
                            _options.get('api_url'),
                            color,
                            _options.get('notify'))

    return hipchat

def event_return(events):
    '''
    Return event data to hipchat
    '''
    _options = _get_options()

    for event in events:
        # TODO:
        # Pre-process messages to apply individualized colors for various
        # event types.
        log.trace('Hipchat returner received event: {0}'.format(event))
        _send_message(_options.get('room_id'),
                      event['data'],
                      _options.get('from_name'),
                      _options.get('api_key'),
                      _options.get('api_version'),
                      _options.get('api_url'),
                      _options.get('color'),
                      _options.get('notify'))
<|endoftext|>


<commit_before>import numpy as np
import neuroimaging.core.api as api
from neuroimaging.core.reference import nifti, axis, coordinate_system
reload(nifti)

shape = np.arange(1,8)
output_axes = [api.RegularAxis(s, step=i+1) for i, s in enumerate('xyztuvw')]

input_axes = [api.VoxelAxis(s, length=shape[i]) for i, s in enumerate('ijklmno')]
input_coords = api.VoxelCoordinateSystem('input', input_axes)

def test_validate1():

    output_coords = api.DiagonalCoordinateSystem('output', output_axes[:4])
    input_coords = api.CoordinateSystem('input', input_axes[:4])
    cmap = api.CoordinateMap(api.Affine(output_coords.affine), input_coords, output_coords)
    print nifti.coordmap4io(cmap)

def test_validate2():
    """
    this should raise a warning about the first three input coordinates,
    and one about the last axis not being in the correct order. this also
    will give a warning about the pixdim.
    """

    ninput_axes = [input_axes[0], input_axes[3], input_axes[1], input_axes[2]]
    input_coords = api.VoxelCoordinateSystem('input', ninput_axes)
    output_coords = api.DiagonalCoordinateSystem('output', output_axes[:4])
    cmap = api.CoordinateMap(api.Affine(output_coords.affine), input_coords, output_coords)
    newcmap, order, pixdim, diminfo = nifti.coordmap4io(cmap)
    assert newcmap.input_coords.name == 'input-reordered'
    assert order == (0,2,3,1)
    x = np.zeros(cmap.shape)
    X = np.transpose(x, order)
    assert(X.shape, newcmap.shape)
    assert np.allclose(pixdim, np.arange(4)+1)
    return newcmap, order, pixdim, diminfo

def test_validate3():
    """
    this should raise an exception about
    not having axis names ['ijkl'].

    some warnings are printed during the try/except
    """

    ninput_axes = [input_axes[0], input_axes[1], input_axes[2], input_axes[5]]
    input_coords = api.VoxelCoordinateSystem('input', ninput_axes)
    output_coords = api.DiagonalCoordinateSystem('output', output_axes[:4])
    cmap = api.CoordinateMap(api.Affine(output_coords.affine), input_coords, output_coords)
    try:
        nifti.coordmap4io(cmap)
    except:
        return
    raise ValueError, 'an exception should have been raised earlier'

def test_validate4():
    """
    this should raise a warning about the last 2 axes not being in order,
    and one about the loss of information from a non-diagonal
    matrix. this also means that the pixdim will be wrong
    """

    ninput_axes = [input_axes[0], input_axes[1], input_axes[2], input_axes[4],
                   input_axes[3]]
    input_coords = api.VoxelCoordinateSystem('input', ninput_axes)
    output_coords = api.DiagonalCoordinateSystem('output', output_axes[:5])
    cmap = api.CoordinateMap(api.Affine(output_coords.affine), input_coords, output_coords)

    newcmap, order, pixdim, diminfo = nifti.coordmap4io(cmap)
    assert newcmap.input_coords.name == 'input-reordered'
    assert order == (0,1,2,4,3)
    assert np.allclose(pixdim, np.arange(5)+1)
    x = np.zeros(cmap.shape)
    X = np.transpose(x, order)
    assert(X.shape, newcmap.shape)

    ndim = cmap.ndim[0]
    perm = np.zeros((ndim+1,ndim+1))
    perm[-1,-1] = 1
    for i, j in enumerate(order):
        perm[i,j] = 1
    B = np.dot(output_coords.affine, perm)

    assert np.allclose(newcmap.affine, B)
    X = np.random.standard_normal((5,))
    Xr = [X[i] for i in order]
    assert np.allclose(newcmap(Xr), cmap(X))
    return newcmap, order, pixdim, diminfo

def test_validate5():
    """
    this should raise a warning about the last 2 axes not being in order,
    and one about the loss of information from a non-diagonal
    matrix, and also one about the nifti output coordinates.
    again, this will have a pixdim warning like test_validate4
    """

    ninput_axes = [input_axes[0], input_axes[1], input_axes[2], input_axes[4],
                   input_axes[3]]
    input_coords = api.VoxelCoordinateSystem('input', ninput_axes)
    output_coords = api.DiagonalCoordinateSystem('output', output_axes[:5][::-1])
    cmap = api.CoordinateMap(api.Affine(output_coords.affine), input_coords, output_coords)
    newcmap, order, pixdim, diminfo = nifti.coordmap4io(cmap)
    assert newcmap.input_coords.name == 'input-reordered'
    assert newcmap.output_coords.name == 'output-reordered'
    assert order == (0,1,2,4,3)
    assert np.allclose(pixdim, np.arange(5)+1)

    x = np.zeros(cmap.shape)
    X = np.transpose(x, order)
    assert(X.shape, newcmap.shape)

    ndim = cmap.ndim[0]
    perm = np.zeros((ndim+1,ndim+1))
    perm[-1,-1] = 1
    for i, j in enumerate(order):
        perm[i,j] = 1
    B = np.dot(output_coords.affine, perm)

    r = np.zeros((6,6))
    r[5,5] =1.
    for i in range(5):
        r[i, 4-i] = 1.

    assert np.allclose(newcmap.affine,
                       np.dot(r, B))
    X = np.random.standard_normal((5,))
    Xr = [X[i] for i in order]
    assert np.allclose(newcmap(Xr)[::-1], cmap(X))

def test_validate6():
    """
    this should not raise any warnings
    """

    ninput_axes = [input_axes[1], input_axes[2], input_axes[0], input_axes[3]]
    input_coords = api.VoxelCoordinateSystem('input', ninput_axes)
    output_coords = api.DiagonalCoordinateSystem('output', output_axes[:4])
    cmap = api.CoordinateMap(api.Affine(output_coords.affine), input_coords, output_coords)
    newcmap, order, pixdim, diminfo = nifti.coordmap4io(cmap)
    assert newcmap.input_coords.name == 'input'
    assert newcmap.output_coords.name == 'output'
    assert order == (0,1,2,3)

    x = np.zeros(cmap.shape)
    X = np.transpose(x, order)
    assert(X.shape, newcmap.shape)

    assert newcmap.input_coords.axisnames() == ['j','k','i','l']
    assert np.allclose(pixdim, np.arange(4)+1)

def test_validate7():
    """
    same as test_validate6, but should raise
    a warning about negative pixdim
    """

    output_axes = [api.RegularAxis(s, step=-i) for i, s in enumerate('xyztuvw')]
    ninput_axes = [input_axes[1], input_axes[2], input_axes[0], input_axes[3]]
    input_coords = api.VoxelCoordinateSystem('input', ninput_axes)
    output_coords = api.DiagonalCoordinateSystem('output', output_axes[:4])
    cmap = api.CoordinateMap(api.Affine(output_coords.affine), input_coords, output_coords)
    newcmap, order, pixdim, diminfo = nifti.coordmap4io(cmap)
    assert newcmap.input_coords.name == 'input'
    assert newcmap.output_coords.name == 'output'
    assert order == (0,1,2,3)

    x = np.zeros(cmap.shape)
    X = np.transpose(x, order)
    assert(X.shape, newcmap.shape)

    assert newcmap.input_coords.axisnames() == ['j','k','i','l']
    assert np.allclose(pixdim, np.arange(4)+1)

def test_ijk1():
    assert(nifti.ijk_from_diminfo(nifti._diminfo_from_fps(-1,-1,-1)) == 'ijk')
    assert(nifti.ijk_from_diminfo(nifti._diminfo_from_fps(2,-1,-1)) == 'jki')

def test_ijk2():
    """
    Test that the phase, freq, time, slice axes work for valid NIFTI headers
    """

    ninput_axes = [input_axes[1], input_axes[2], input_axes[0], input_axes[3]]
    input_coords = api.VoxelCoordinateSystem('input', ninput_axes)
    output_coords = api.DiagonalCoordinateSystem('output', output_axes[:4])
    cmap = api.CoordinateMap(api.Affine(output_coords.affine), input_coords, output_coords)

    assert nifti.get_time_axis(cmap) == 3
    assert nifti.get_freq_axis(cmap) == 0
    assert nifti.get_slice_axis(cmap) == 1
    assert nifti.get_phase_axis(cmap) == 2

def test_ijk3():
    '''
    Same as test_ijk2, but the order of the output coordinates is reversed
    '''

    ninput_axes = [input_axes[1], input_axes[2], input_axes[0], input_axes[3]]
    input_coords = api.VoxelCoordinateSystem('input', ninput_axes)
    output_coords = api.DiagonalCoordinateSystem('output', output_axes[:4][::-1])
    cmap = api.CoordinateMap(api.Affine(output_coords.affine), input_coords, output_coords)

    assert nifti.get_time_axis(cmap) == 3
    assert nifti.get_freq_axis(cmap) == 0
    assert nifti.get_slice_axis(cmap) == 1
    assert nifti.get_phase_axis(cmap) == 2

def test_ijk4():
    """
    Test that the phase, freq, time, slice axes work for coercable NIFTI headers
    """

    ninput_axes = [input_axes[0], input_axes[1], input_axes[2], input_axes[4],
                   input_axes[3]]
    input_coords = api.VoxelCoordinateSystem('input', ninput_axes)
    output_coords = api.DiagonalCoordinateSystem('output', output_axes[:5][::-1])
    cmap = api.CoordinateMap(api.Affine(output_coords.affine), input_coords, output_coords)

    cmap = api.CoordinateMap(api.Affine(output_coords.affine), input_coords, output_coords)

    assert nifti.get_time_axis(cmap) == 4
    assert nifti.get_freq_axis(cmap) == 1
    assert nifti.get_slice_axis(cmap) == 2
    assert nifti.get_phase_axis(cmap) == 0

    newcmap, _ = nifti.coerce_coordmap(cmap)

    assert nifti.get_time_axis(newcmap) == 3
    assert nifti.get_freq_axis(newcmap) == 1
    assert nifti.get_slice_axis(newcmap) == 2
    assert nifti.get_phase_axis(newcmap) == 0
<commit_msg>two more tests<commit_after>import numpy as np
import neuroimaging.core.api as api
from neuroimaging.core.reference import nifti, axis, coordinate_system
reload(nifti)

shape = np.arange(1,8)
output_axes = [api.RegularAxis(s, step=i+1) for i, s in enumerate('xyztuvw')]

input_axes = [api.VoxelAxis(s, length=shape[i]) for i, s in enumerate('ijklmno')]
input_coords = api.VoxelCoordinateSystem('input', input_axes)

def test_validate1():

    """
    this should work without any warnings
    """

    output_coords = api.DiagonalCoordinateSystem('output', output_axes[:4])
    input_coords = api.CoordinateSystem('input', input_axes[:4])
    cmap = api.CoordinateMap(api.Affine(output_coords.affine), input_coords, output_coords)
    newcmap, order, pixdim, diminfo = nifti.coordmap4io(cmap)
    assert newcmap.input_coords.name == 'input'
    assert newcmap.output_coords.name == 'output'
    assert order == (0,1,2,3)
    assert np.allclose(pixdim, np.arange(4)+1)

def test_validate1a():

    """
    this should work without any warnings
    """

    output_coords = api.DiagonalCoordinateSystem('output', output_axes[:3])
    input_coords = api.CoordinateSystem('input', input_axes[:3][::-1])
    cmap = api.CoordinateMap(api.Affine(output_coords.affine), input_coords, output_coords)
    newcmap, order, pixdim, diminfo = nifti.coordmap4io(cmap)
    assert newcmap.input_coords.name == 'input'
    assert newcmap.output_coords.name == 'output'
    assert order == (0,1,2)
    assert np.allclose(pixdim, np.arange(3)+1)

def test_validate1b():

    """
    this should work without any warnings
    """

    output_coords = api.DiagonalCoordinateSystem('output', output_axes[:4])
    input_coords = api.CoordinateSystem('input', [input_axes[2],
                                                  input_axes[0],
                                                  input_axes[1],
                                                  input_axes[3]])
    cmap = api.CoordinateMap(api.Affine(output_coords.affine), input_coords, output_coords)
    newcmap, order, pixdim, diminfo = nifti.coordmap4io(cmap)
    assert newcmap.input_coords.name == 'input'
    assert newcmap.output_coords.name == 'output'
    assert order == (0,1,2,3)
    assert np.allclose(pixdim, np.arange(4)+1)

def test_validate2():
    """
    this should raise a warning about the first three input coordinates,
    and one about the last axis not being in the correct order. this also
    will give a warning about the pixdim.
    """

    ninput_axes = [input_axes[0], input_axes[3], input_axes[1], input_axes[2]]
    input_coords = api.VoxelCoordinateSystem('input', ninput_axes)
    output_coords = api.DiagonalCoordinateSystem('output', output_axes[:4])
    cmap = api.CoordinateMap(api.Affine(output_coords.affine), input_coords, output_coords)
    newcmap, order, pixdim, diminfo = nifti.coordmap4io(cmap)
    assert newcmap.input_coords.name == 'input-reordered'
    assert order == (0,2,3,1)
    x = np.zeros(cmap.shape)
    X = np.transpose(x, order)
    assert(X.shape, newcmap.shape)
    assert np.allclose(pixdim, np.arange(4)+1)
    return newcmap, order, pixdim, diminfo

def test_validate3():
    """
    this should raise an exception about
    not having axis names ['ijkl'].

    some warnings are printed during the try/except
    """

    ninput_axes = [input_axes[0], input_axes[1], input_axes[2], input_axes[5]]
    input_coords = api.VoxelCoordinateSystem('input', ninput_axes)
    output_coords = api.DiagonalCoordinateSystem('output', output_axes[:4])
    cmap = api.CoordinateMap(api.Affine(output_coords.affine), input_coords, output_coords)
    try:
        nifti.coordmap4io(cmap)
    except:
        return
    raise ValueError, 'an exception should have been raised earlier'

def test_validate4():
    """
    this should raise a warning about the last 2 axes not being in order,
    and one about the loss of information from a non-diagonal
    matrix. this also means that the pixdim will be wrong
    """

    ninput_axes = [input_axes[0], input_axes[1], input_axes[2], input_axes[4],
                   input_axes[3]]
    input_coords = api.VoxelCoordinateSystem('input', ninput_axes)
    output_coords = api.DiagonalCoordinateSystem('output', output_axes[:5])
    cmap = api.CoordinateMap(api.Affine(output_coords.affine), input_coords, output_coords)

    newcmap, order, pixdim, diminfo = nifti.coordmap4io(cmap)
    assert newcmap.input_coords.name == 'input-reordered'
    assert order == (0,1,2,4,3)
    assert np.allclose(pixdim, np.arange(5)+1)
    x = np.zeros(cmap.shape)
    X = np.transpose(x, order)
    assert(X.shape, newcmap.shape)

    ndim = cmap.ndim[0]
    perm = np.zeros((ndim+1,ndim+1))
    perm[-1,-1] = 1
    for i, j in enumerate(order):
        perm[i,j] = 1
    B = np.dot(output_coords.affine, perm)

    assert np.allclose(newcmap.affine, B)
    X = np.random.standard_normal((5,))
    Xr = [X[i] for i in order]
    assert np.allclose(newcmap(Xr), cmap(X))
    return newcmap, order, pixdim, diminfo

def test_validate5():
    """
    this should raise a warning about the last 2 axes not being in order,
    and one about the loss of information from a non-diagonal
    matrix, and also one about the nifti output coordinates.
    again, this will have a pixdim warning like test_validate4
    """

    ninput_axes = [input_axes[0], input_axes[1], input_axes[2], input_axes[4],
                   input_axes[3]]
    input_coords = api.VoxelCoordinateSystem('input', ninput_axes)
    output_coords = api.DiagonalCoordinateSystem('output', output_axes[:5][::-1])
    cmap = api.CoordinateMap(api.Affine(output_coords.affine), input_coords, output_coords)
    newcmap, order, pixdim, diminfo = nifti.coordmap4io(cmap)
    assert newcmap.input_coords.name == 'input-reordered'
    assert newcmap.output_coords.name == 'output-reordered'
    assert order == (0,1,2,4,3)
    assert np.allclose(pixdim, np.arange(5)+1)

    x = np.zeros(cmap.shape)
    X = np.transpose(x, order)
    assert(X.shape, newcmap.shape)

    ndim = cmap.ndim[0]
    perm = np.zeros((ndim+1,ndim+1))
    perm[-1,-1] = 1
    for i, j in enumerate(order):
        perm[i,j] = 1
    B = np.dot(output_coords.affine, perm)

    r = np.zeros((6,6))
    r[5,5] =1.
    for i in range(5):
        r[i, 4-i] = 1.

    assert np.allclose(newcmap.affine,
                       np.dot(r, B))
    X = np.random.standard_normal((5,))
    Xr = [X[i] for i in order]
    assert np.allclose(newcmap(Xr)[::-1], cmap(X))

def test_validate6():
    """
    this should not raise any warnings
    """

    ninput_axes = [input_axes[1], input_axes[2], input_axes[0], input_axes[3]]
    input_coords = api.VoxelCoordinateSystem('input', ninput_axes)
    output_coords = api.DiagonalCoordinateSystem('output', output_axes[:4])
    cmap = api.CoordinateMap(api.Affine(output_coords.affine), input_coords, output_coords)
    newcmap, order, pixdim, diminfo = nifti.coordmap4io(cmap)
    assert newcmap.input_coords.name == 'input'
    assert newcmap.output_coords.name == 'output'
    assert order == (0,1,2,3)

    x = np.zeros(cmap.shape)
    X = np.transpose(x, order)
    assert(X.shape, newcmap.shape)

    assert newcmap.input_coords.axisnames() == ['j','k','i','l']
    assert np.allclose(pixdim, np.arange(4)+1)

def test_validate7():
    """
    same as test_validate6, but should raise
    a warning about negative pixdim
    """

    output_axes = [api.RegularAxis(s, step=-i) for i, s in enumerate('xyztuvw')]
    ninput_axes = [input_axes[1], input_axes[2], input_axes[0], input_axes[3]]
    input_coords = api.VoxelCoordinateSystem('input', ninput_axes)
    output_coords = api.DiagonalCoordinateSystem('output', output_axes[:4])
    cmap = api.CoordinateMap(api.Affine(output_coords.affine), input_coords, output_coords)
    newcmap, order, pixdim, diminfo = nifti.coordmap4io(cmap)
    assert newcmap.input_coords.name == 'input'
    assert newcmap.output_coords.name == 'output'
    assert order == (0,1,2,3)

    x = np.zeros(cmap.shape)
    X = np.transpose(x, order)
    assert(X.shape, newcmap.shape)

    assert newcmap.input_coords.axisnames() == ['j','k','i','l']
    assert np.allclose(pixdim, np.arange(4)+1)

def test_ijk1():
    assert(nifti.ijk_from_diminfo(nifti._diminfo_from_fps(-1,-1,-1)) == 'ijk')
    assert(nifti.ijk_from_diminfo(nifti._diminfo_from_fps(2,-1,-1)) == 'jki')

def test_ijk2():
    """
    Test that the phase, freq, time, slice axes work for valid NIFTI headers
    """

    ninput_axes = [input_axes[1], input_axes[2], input_axes[0], input_axes[3]]
    input_coords = api.VoxelCoordinateSystem('input', ninput_axes)
    output_coords = api.DiagonalCoordinateSystem('output', output_axes[:4])
    cmap = api.CoordinateMap(api.Affine(output_coords.affine), input_coords, output_coords)

    assert nifti.get_time_axis(cmap) == 3
    assert nifti.get_freq_axis(cmap) == 0
    assert nifti.get_slice_axis(cmap) == 1
    assert nifti.get_phase_axis(cmap) == 2

def test_ijk3():
    '''
    Same as test_ijk2, but the order of the output coordinates is reversed
    '''

    ninput_axes = [input_axes[1], input_axes[2], input_axes[0], input_axes[3]]
    input_coords = api.VoxelCoordinateSystem('input', ninput_axes)
    output_coords = api.DiagonalCoordinateSystem('output', output_axes[:4][::-1])
    cmap = api.CoordinateMap(api.Affine(output_coords.affine), input_coords, output_coords)

    assert nifti.get_time_axis(cmap) == 3
    assert nifti.get_freq_axis(cmap) == 0
    assert nifti.get_slice_axis(cmap) == 1
    assert nifti.get_phase_axis(cmap) == 2

def test_ijk4():
    """
    Test that the phase, freq, time, slice axes work for coercable NIFTI headers
    """

    ninput_axes = [input_axes[0], input_axes[1], input_axes[2], input_axes[4],
                   input_axes[3]]
    input_coords = api.VoxelCoordinateSystem('input', ninput_axes)
    output_coords = api.DiagonalCoordinateSystem('output', output_axes[:5][::-1])
    cmap = api.CoordinateMap(api.Affine(output_coords.affine), input_coords, output_coords)

    cmap = api.CoordinateMap(api.Affine(output_coords.affine), input_coords, output_coords)

    assert nifti.get_time_axis(cmap) == 4
    assert nifti.get_freq_axis(cmap) == 1
    assert nifti.get_slice_axis(cmap) == 2
    assert nifti.get_phase_axis(cmap) == 0

    newcmap, _ = nifti.coerce_coordmap(cmap)

    assert nifti.get_time_axis(newcmap) == 3
    assert nifti.get_freq_axis(newcmap) == 1
    assert nifti.get_slice_axis(newcmap) == 2
    assert nifti.get_phase_axis(newcmap) == 0
<|endoftext|>


<commit_before>#3D Reconstruct from a tilt series using Direct Fourier Method
#
#NOTE: Tilt Axis needs to be in the third dimension
#
#developed as part of the tomviz project (www.tomviz.com)

def transform_scalars(dataset):
    from tomviz import utils
    import numpy as np

    #----USER SPECIFIED VARIABLES-----#
    TILT_AXIS  = []  #Specify the tilt axis, if none is specified
                     #it assume it is the smallest dimension
    ANGLES = []  #Specify the angles used in the tiltseries
                 #For example, ANGLES = np.linspace(0,140,70)
    #---------------------------------#

    data_py = utils.get_array(dataset)
    if data_py is None:
        raise RuntimeError("No scalars found!")

    if TILT_AXIS == []: #If tilt axis is not given, find it
    #Find smallest array dimension, assume it is the tilt angle axis
        if data_py.ndim == 3:
            TILT_AXIS = np.argmin( data_py.shape )
        elif data_py.ndim == 2:
            raise RuntimeError("Data Array is 2 dimensions, it should be 3!")
        else:
            raise RuntimeError("Data Array is not 2 or 3 dimensions!")

    if ANGLES == []: #If angles are not given, assume 2 degree tilts
        angles = np.linspace(0,146,74)

    dimx = np.size(data_py,0) #IN THE FUTURE THIS SHOULD NOT BE ASSUMED
    result3D = dfm3(data_py,angles,dimx)

    # set the result as the new scalars.
    utils.set_array(dataset, result3D)
    print('Reconsruction Complete')

#dfm3(input,angles,Npad)
#3D Direct Fourier Method
#Use numpy fft
#
#Yi Jiang
#08/25/2014
#input: aligned data
#angles: projection angles
#N_pad: size of padded projection. typical choice: twice as the original projection

import numpy as np

def dfm3(input,angles,Npad):
    print "You are using 3D direct fourier method, be patient."
    input = np.double(input)
    (Nx,Ny,Np) = input.shape
    angles = np.double(angles)
    cen = np.floor(Ny/2)
    cen_pad = np.floor(Npad/2)
    pad_post = np.ceil((Npad-Ny)/2); pad_pre = np.floor((Npad-Ny)/2)
    #initialize value and weight matrix
    print "initialization"
    Nz = Ny
    w = np.zeros((Nx,Ny,Nz))
    v = np.zeros((Nx,Ny,Nz)) + 1j*np.zeros((Nx,Ny,Nz))

    dk = np.double(Ny)/np.double(Npad) *1

    for a in range(0,Np):
        print angles[a]
        ang = angles[a]*np.pi/180
	projection = input[:,:,a] #projection
        p = np.lib.pad(projection,((0,0),(pad_pre,pad_post)),'constant',constant_values=(0,0)) #pad zeros
        p = np.fft.ifftshift(p)
	pF = np.fft.fft2(p)
	pF = np.fft.fftshift(pF)

        #bilinear extrapolation
        for i in range(0, np.int(Npad)):
            ky = (i-cen_pad)*dk;  #kz = 0;
            ky_new = np.cos(ang)*ky #new coord. after rotation
            kz_new = np.sin(ang)*ky
	    sy = abs(np.floor(ky_new) - ky_new) #calculate weights
            sz = abs(np.floor(kz_new) - kz_new)
            for b in range(1,5): #bilinear extrapolation
                pz,py,weight = bilinear(kz_new,ky_new,sz,sy,Ny,b)
		pz = pz + cen;
		py = py + cen;
                if (py>=0 and py<Ny and pz>=0 and pz<Nz):
                   w[:,py,pz] = w[:,py,pz] + weight
	           v[:,py,pz] = v[:,py,pz] + weight * pF[:,i]
    v[w!=0] = v[w!=0]/w[w!=0]
    v = np.fft.ifftshift(v)
    recon = np.real(np.fft.ifftn(v))
    recon = np.fft.fftshift(recon)
    return recon

def bilinear(kz_new,ky_new,sz,sy,N,p):
    if p==1:
       py = np.floor(ky_new)
       pz = np.floor(kz_new)
       weight = (1-sy)*(1-sz)
    elif p==2:
       py = np.ceil(ky_new) #P2
       pz = np.floor(kz_new)
       weight = sy*(1-sz)
    elif p==3:
       py = np.floor(ky_new) #P3
       pz = np.ceil(kz_new)
       weight = (1-sy)*sz
    elif p==4:
       py = np.ceil(ky_new) #P4
       pz = np.ceil(kz_new)
       weight = sy*sz
    if py<0:
       py = N+py
    else:
       py = py
    return (pz,py,weight)

<commit_msg>Change output of reconstruct to be float not double<commit_after>#3D Reconstruct from a tilt series using Direct Fourier Method
#
#NOTE: Tilt Axis needs to be in the third dimension
#
#developed as part of the tomviz project (www.tomviz.com)

def transform_scalars(dataset):
    from tomviz import utils
    import numpy as np

    #----USER SPECIFIED VARIABLES-----#
    TILT_AXIS  = []  #Specify the tilt axis, if none is specified
                     #it assume it is the smallest dimension
    ANGLES = []  #Specify the angles used in the tiltseries
                 #For example, ANGLES = np.linspace(0,140,70)
    #---------------------------------#

    data_py = utils.get_array(dataset)
    if data_py is None:
        raise RuntimeError("No scalars found!")

    if TILT_AXIS == []: #If tilt axis is not given, find it
    #Find smallest array dimension, assume it is the tilt angle axis
        if data_py.ndim == 3:
            TILT_AXIS = np.argmin( data_py.shape )
        elif data_py.ndim == 2:
            raise RuntimeError("Data Array is 2 dimensions, it should be 3!")
        else:
            raise RuntimeError("Data Array is not 2 or 3 dimensions!")

    if ANGLES == []: #If angles are not given, assume 2 degree tilts
        angles = np.linspace(0,146,74)

    dimx = np.size(data_py,0) #IN THE FUTURE THIS SHOULD NOT BE ASSUMED
    result3D = dfm3(data_py,angles,dimx)

    # set the result as the new scalars.
    utils.set_array(dataset, result3D)
    print('Reconsruction Complete')

#dfm3(input,angles,Npad)
#3D Direct Fourier Method
#Use numpy fft
#
#Yi Jiang
#08/25/2014
#input: aligned data
#angles: projection angles
#N_pad: size of padded projection. typical choice: twice as the original projection

import numpy as np

def dfm3(input,angles,Npad):
    print "You are using 3D direct fourier method, be patient."
    input = np.double(input)
    (Nx,Ny,Np) = input.shape
    angles = np.double(angles)
    cen = np.floor(Ny/2)
    cen_pad = np.floor(Npad/2)
    pad_post = np.ceil((Npad-Ny)/2); pad_pre = np.floor((Npad-Ny)/2)
    #initialize value and weight matrix
    print "initialization"
    Nz = Ny
    w = np.zeros((Nx,Ny,Nz))
    v = np.zeros((Nx,Ny,Nz)) + 1j*np.zeros((Nx,Ny,Nz))

    dk = np.double(Ny)/np.double(Npad) *1

    for a in range(0,Np):
        print angles[a]
        ang = angles[a]*np.pi/180
	projection = input[:,:,a] #projection
        p = np.lib.pad(projection,((0,0),(pad_pre,pad_post)),'constant',constant_values=(0,0)) #pad zeros
        p = np.fft.ifftshift(p)
	pF = np.fft.fft2(p)
	pF = np.fft.fftshift(pF)

        #bilinear extrapolation
        for i in range(0, np.int(Npad)):
            ky = (i-cen_pad)*dk;  #kz = 0;
            ky_new = np.cos(ang)*ky #new coord. after rotation
            kz_new = np.sin(ang)*ky
	    sy = abs(np.floor(ky_new) - ky_new) #calculate weights
            sz = abs(np.floor(kz_new) - kz_new)
            for b in range(1,5): #bilinear extrapolation
                pz,py,weight = bilinear(kz_new,ky_new,sz,sy,Ny,b)
		pz = pz + cen;
		py = py + cen;
                if (py>=0 and py<Ny and pz>=0 and pz<Nz):
                   w[:,py,pz] = w[:,py,pz] + weight
	           v[:,py,pz] = v[:,py,pz] + weight * pF[:,i]
    v[w!=0] = v[w!=0]/w[w!=0]
    v = np.fft.ifftshift(v)
    recon = np.real(np.fft.ifftn(v))
    recon = np.fft.fftshift(recon)
    return recon.astype(np.float32)

def bilinear(kz_new,ky_new,sz,sy,N,p):
    if p==1:
       py = np.floor(ky_new)
       pz = np.floor(kz_new)
       weight = (1-sy)*(1-sz)
    elif p==2:
       py = np.ceil(ky_new) #P2
       pz = np.floor(kz_new)
       weight = sy*(1-sz)
    elif p==3:
       py = np.floor(ky_new) #P3
       pz = np.ceil(kz_new)
       weight = (1-sy)*sz
    elif p==4:
       py = np.ceil(ky_new) #P4
       pz = np.ceil(kz_new)
       weight = sy*sz
    if py<0:
       py = N+py
    else:
       py = py
    return (pz,py,weight)

<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
'''
Manage Windows features via the ServerManager powershell module
'''

def __virtual__():
    '''
    Load only if win_servermanager is loaded
    '''
    return 'win_servermanager' if 'win_servermanager.install' in __salt__ else False

def installed(name, recurse=False, force=False):
    '''
    Install the windows feature

    name:
        short name of the feature (the right column in win_servermanager.list_available)

    recurse:
        install all sub-features as well

    force:
        if the feature is installed but on of its sub-features are not installed set this to True to force
        the installation of the sub-features

    Note:
    Some features requires reboot after un/installation, if so until the server is restarted
    Other features can not be installed !
    '''
    ret = {'name': name,
           'result': True,
           'changes': {},
           'comment': ''}

    # Determine if the feature is installed
    if name not in __salt__['win_servermanager.list_installed']():
        ret['changes'] = {'feature': '{0} will be installed recurse={1}'.format(name, recurse)}
    elif force and recurse:
        ret['changes'] = {'feature': 'already installed but might install sub-features'.format(name)}
    else:
        ret['comment'] = 'The feature {0} is already installed'.format(name)
        return ret

    if __opts__['test']:
        ret['result'] = None
        return ret

    # Install the features
    ret['changes'] = {'feature': __salt__['win_servermanager.install'](name, recurse)}

    if 'Success' in ret['changes']['feature']:
        ret['result'] = ret['changes']['feature']['Success'] == 'True'
        if not ret['result']:
            ret['comment'] = 'failed to install the feature: {0}'.format(ret['changes']['feature']['ExitCode'])
    else:
        ret['result'] = False
        ret['comment'] = 'Failed to install {0}.\nError Message:\n{1}'.format(name, ret['changes']['feature']['message'])
        ret['changes'] = {}

    return ret
<commit_msg>Fixed capitalization... Failed and Already<commit_after># -*- coding: utf-8 -*-
'''
Manage Windows features via the ServerManager powershell module
'''

def __virtual__():
    '''
    Load only if win_servermanager is loaded
    '''
    return 'win_servermanager' if 'win_servermanager.install' in __salt__ else False

def installed(name, recurse=False, force=False):
    '''
    Install the windows feature

    name:
        short name of the feature (the right column in win_servermanager.list_available)

    recurse:
        install all sub-features as well

    force:
        if the feature is installed but on of its sub-features are not installed set this to True to force
        the installation of the sub-features

    Note:
    Some features requires reboot after un/installation, if so until the server is restarted
    Other features can not be installed !
    '''
    ret = {'name': name,
           'result': True,
           'changes': {},
           'comment': ''}

    # Determine if the feature is installed
    if name not in __salt__['win_servermanager.list_installed']():
        ret['changes'] = {'feature': '{0} will be installed recurse={1}'.format(name, recurse)}
    elif force and recurse:
        ret['changes'] = {'feature': 'Already installed but might install sub-features'.format(name)}
    else:
        ret['comment'] = 'The feature {0} is already installed'.format(name)
        return ret

    if __opts__['test']:
        ret['result'] = None
        return ret

    # Install the features
    ret['changes'] = {'feature': __salt__['win_servermanager.install'](name, recurse)}

    if 'Success' in ret['changes']['feature']:
        ret['result'] = ret['changes']['feature']['Success'] == 'True'
        if not ret['result']:
            ret['comment'] = 'Failed to install the feature: {0}'.format(ret['changes']['feature']['ExitCode'])
    else:
        ret['result'] = False
        ret['comment'] = 'Failed to install {0}.\nError Message:\n{1}'.format(name, ret['changes']['feature']['message'])
        ret['changes'] = {}

    return ret
<|endoftext|>


<commit_before>
#
#       util.py
#
#       Copyright 2012 alex arsenovic <arsenovic@virginia.edu>
#
#       This program is free software; you can redistribute it and/or modify
#       it under the terms of the GNU General Public License as published by
#       the Free Software Foundation; either version 2 of the License, or
#       (at your option) any later versionpy.
#
#       This program is distributed in the hope that it will be useful,
#       but WITHOUT ANY WARRANTY; without even the implied warranty of
#       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#       GNU General Public License for more details.
#
#       You should have received a copy of the GNU General Public License
#       along with this program; if not, write to the Free Software
#       Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
#       MA 02110-1301, USA.

'''

.. currentmodule:: skrf.util
========================================
util (:mod:`skrf.util`)
========================================

Holds utility functions that are general conveniences.

General
------------
.. autosummary::
   :toctree: generated/

   now_string
   find_nearest
   find_nearest_index
   get_fid
   get_extn

'''

import mathFunctions as mf

import warnings
import os
import cPickle as pickle
import pylab as plb
import numpy as npy
from scipy.constants import mil
from datetime import datetime
import collections, pprint
from subprocess import Popen,PIPE
# globals

# other
def now_string():
    '''
    returns a unique sortable string, representing the current time

    nice for generating date-time stamps to be used in file-names,
    the companion function :func:`now_string_2_dt` can be used
    to read these string back into datetime objects.

    See Also
    ------------
    now_string_2_dt

    '''
    return datetime.now().__str__().replace('-','.').replace(':','.').replace(' ','.')

def now_string_2_dt(s):
    '''
    Converts the output of  :func:`now_string` to a datetime object.

    See Also
    -----------
    now_string

    '''
    return datetime(*[int(k) for k in s.split('.')])

def find_nearest(array,value):
    '''
    find nearest value in array.

    taken from  http://stackoverflow.com/questions/2566412/find-nearest-value-in-numpy-array

    Parameters
    ----------
    array :  numpy.ndarray
        array we are searching for a value in
    value : element of the array
        value to search for

    Returns
    --------
    found_value : an element of the array
        the value that is numerically closest to `value`

    '''
    idx=(npy.abs(array-value)).argmin()
    return array[idx]

def find_nearest_index(array,value):
    '''
    find nearest value in array.

    Parameters
    ----------
    array :  numpy.ndarray
        array we are searching for a value in
    value : element of the array
        value to search for

    Returns
    --------
    found_index : int
        the index at which the  numerically closest element to `value`
        was found at

    taken from  http://stackoverflow.com/questions/2566412/find-nearest-value-in-numpy-array

    '''
    return (npy.abs(array-value)).argmin()

# file IO

def get_fid(file, *args, **kwargs):
    '''
    Returns a file object, given a filename or file object

    Useful  when you want to allow the arguments of a function to
    be either files or filenames

    Parameters
    -------------
    file : str or file-object
        file to open
    \*args, \*\*kwargs : arguments and keyword arguments
        passed through to pickle.load
    '''
    if isinstance(file, basestring):
        return open(file, *args, **kwargs)
    else:
        return file

def get_extn(filename):
    '''
    Get the extension from a filename.

    The extension is defined as everything passed the last '.'.
    Returns None if it aint got one

    Parameters
    ------------
    filename : string
        the filename

    Returns
    --------
    ext : string, None
        either the extension (not including '.') or None if there
        isnt one

    '''
    ext = os.path.splitext(filename)[-1]
    if len(ext)==0:
        return None
    else:
        return ext[1:]

def basename_noext(filename):
    '''
    gets the basename and strips extension
    '''
    return os.path.splitext(os.path.basename(filename))[0]

# git
def git_version( modname):
    '''
    Returns output 'git describe', executed in a modules root directory.
    '''
    mod = __import__(modname)
    mod_dir =os.path.split(mod.__file__)[0]
    p = Popen(['git', 'describe'], stdout = PIPE,stderr=PIPE, cwd =mod_dir )

    try:
        out,er = p.communicate()
    except(OSError):
        return None

    out = out.strip('\n')
    if out == '':
        return None
    return out

# general purpose objects

class HomoList(collections.Sequence):
    '''

    A Homogeneous Sequence

    Provides a class for a list-like object which contains
    homogeneous values. Attributes of the values can be accessed through
    the attributes of HomoList. Searching is done like numpy arrays.

    Initialized from a list  of all the same type

    >>> h = HomoDict([Foo(...), Foo(...)])

    The individual values of `h` can be access in identical fashion to
    Lists.

    >>> h[0]

    Assuming that `Foo` has property `prop`  and function `func` ...

    Access elements' properties:

    >>> h.prop

    Access elements' functions:

    >>> h.func()

    Searching:

    >>> h[h.prop == value]
    >>> h[h.prop < value]

    Multiple search:

    >>> h[set(h.prop==value1) & set( h.prop2==value2)]

    Combos:

    >>> h[h.prop==value].func()
    '''

    def __init__(self, list_):
        self.store = list(list_)

    def __eq__(self, value):
        return [k for k in range(len(self)) if self.store[k] == value ]

    def __ne__(self, value):
        return [k for k in range(len(self)) if self.store[k] != value ]

    def __gt__(self, value):
        return [k for k in range(len(self)) if self.store[k] > value ]

    def __ge__(self, value):
        return [k for k in range(len(self)) if self.store[k] >= value ]

    def __lt__(self, value):
        return [k for k in range(len(self)) if self.store[k] < value ]

    def __le__(self, value):
        return [k for k in range(len(self)) if self.store[k] <= value ]

    def __getattr__(self, name):
        return self.__class__(
            [k.__getattribute__(name) for k in self.store])

    def __getitem__(self, idx):
        try:
            return self.store[idx]
        except(TypeError):
            return self.__class__([self.store[k] for k in idx])

    def __call__(self, *args, **kwargs):
        return self.__class__(
            [k(*args,**kwargs) for k in self.store])

    def __setitem__(self, idx, value):
        self.store[idx] = value

    def __delitem__(self, idx):
        del self.store[idx]

    def __iter__(self):
        return iter(self.store)

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

    def __str__(self):
        return pprint.pformat(self.store)

    def __repr__(self):
        return pprint.pformat(self.store)

class HomoDict(collections.MutableMapping):
    '''
    A Homogeneous Mutable Mapping

    Provides a class for a dictionary-like object which contains
    homogeneous values. Attributes of the values can be accessed through
    the attributes of HomoDict. Searching is done like numpy arrays.

    Initialized from a dictionary containing values of all the same type

    >>> h = HomoDict({'a':Foo(...),'b': Foo(...), 'c':Foo(..)})

    The individual values of `h` can be access in identical fashion to
    Dictionaries.

    >>> h['key']

    Assuming that `Foo` has property `prop`  and function `func` ...

    Access elements' properties:

    >>> h.prop

    Access elements' functions:

    >>> h.func()

    Searching:

    >>> h[h.prop == value]
    >>> h[h.prop < value]

    Multiple search:

    >>> h[set(h.prop==value1) & set( h.prop2==value2)]

    Combos:

    >>> h[h.prop==value].func()
    '''
    def __init__(self, dict_):
        self.store = dict(dict_)

    def __eq__(self, value):
        return [k for k in self.store if self.store[k] == value ]

    def __ne__(self, value):
        return [k for k in self.store if self.store[k] != value ]

    def __gt__(self, value):
        return [k for k in self.store if self.store[k] > value ]

    def __ge__(self, value):
        return [k for k in self.store if self.store[k] >= value ]

    def __lt__(self, value):
        return [k for k in self.store if self.store[k] < value ]

    def __le__(self, value):
        return [k for k in self.store if self.store[k] <= value ]

    def __getattr__(self, name):
        return self.__class__(
            {k: getattr(self.store[k],name) for k in self.store})

    def __getitem__(self, key):
        if isinstance(key, str):
            return self.store[key]
        else:
            c =   self.__class__({k:self.store[k] for k in key})
        return c
        #if len(c) == 1:
        #    return c.store.values()[0]
        #else:
        #    return c

    def __call__(self, *args, **kwargs):
        return self.__class__(
            {k: self.store[k](*args, **kwargs) for k in self.store})

    def __setitem__(self, key, value):
        self.store[key] = value

    def __delitem__(self, key):
        del self.store[key]

    def __iter__(self):
        return iter(self.store)

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

    def __str__(self):
        return pprint.pformat(self.store)

    def __repr__(self):
        return pprint.pformat(self.store)

<commit_msg>added filter_nones function to Homodict<commit_after>
#
#       util.py
#
#       Copyright 2012 alex arsenovic <arsenovic@virginia.edu>
#
#       This program is free software; you can redistribute it and/or modify
#       it under the terms of the GNU General Public License as published by
#       the Free Software Foundation; either version 2 of the License, or
#       (at your option) any later versionpy.
#
#       This program is distributed in the hope that it will be useful,
#       but WITHOUT ANY WARRANTY; without even the implied warranty of
#       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#       GNU General Public License for more details.
#
#       You should have received a copy of the GNU General Public License
#       along with this program; if not, write to the Free Software
#       Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
#       MA 02110-1301, USA.

'''

.. currentmodule:: skrf.util
========================================
util (:mod:`skrf.util`)
========================================

Holds utility functions that are general conveniences.

General
------------
.. autosummary::
   :toctree: generated/

   now_string
   find_nearest
   find_nearest_index
   get_fid
   get_extn

'''

import mathFunctions as mf

import warnings
import os
import cPickle as pickle
import pylab as plb
import numpy as npy
from scipy.constants import mil
from datetime import datetime
import collections, pprint
from subprocess import Popen,PIPE
# globals

# other
def now_string():
    '''
    returns a unique sortable string, representing the current time

    nice for generating date-time stamps to be used in file-names,
    the companion function :func:`now_string_2_dt` can be used
    to read these string back into datetime objects.

    See Also
    ------------
    now_string_2_dt

    '''
    return datetime.now().__str__().replace('-','.').replace(':','.').replace(' ','.')

def now_string_2_dt(s):
    '''
    Converts the output of  :func:`now_string` to a datetime object.

    See Also
    -----------
    now_string

    '''
    return datetime(*[int(k) for k in s.split('.')])

def find_nearest(array,value):
    '''
    find nearest value in array.

    taken from  http://stackoverflow.com/questions/2566412/find-nearest-value-in-numpy-array

    Parameters
    ----------
    array :  numpy.ndarray
        array we are searching for a value in
    value : element of the array
        value to search for

    Returns
    --------
    found_value : an element of the array
        the value that is numerically closest to `value`

    '''
    idx=(npy.abs(array-value)).argmin()
    return array[idx]

def find_nearest_index(array,value):
    '''
    find nearest value in array.

    Parameters
    ----------
    array :  numpy.ndarray
        array we are searching for a value in
    value : element of the array
        value to search for

    Returns
    --------
    found_index : int
        the index at which the  numerically closest element to `value`
        was found at

    taken from  http://stackoverflow.com/questions/2566412/find-nearest-value-in-numpy-array

    '''
    return (npy.abs(array-value)).argmin()

# file IO

def get_fid(file, *args, **kwargs):
    '''
    Returns a file object, given a filename or file object

    Useful  when you want to allow the arguments of a function to
    be either files or filenames

    Parameters
    -------------
    file : str or file-object
        file to open
    \*args, \*\*kwargs : arguments and keyword arguments
        passed through to pickle.load
    '''
    if isinstance(file, basestring):
        return open(file, *args, **kwargs)
    else:
        return file

def get_extn(filename):
    '''
    Get the extension from a filename.

    The extension is defined as everything passed the last '.'.
    Returns None if it aint got one

    Parameters
    ------------
    filename : string
        the filename

    Returns
    --------
    ext : string, None
        either the extension (not including '.') or None if there
        isnt one

    '''
    ext = os.path.splitext(filename)[-1]
    if len(ext)==0:
        return None
    else:
        return ext[1:]

def basename_noext(filename):
    '''
    gets the basename and strips extension
    '''
    return os.path.splitext(os.path.basename(filename))[0]

# git
def git_version( modname):
    '''
    Returns output 'git describe', executed in a modules root directory.
    '''
    mod = __import__(modname)
    mod_dir =os.path.split(mod.__file__)[0]
    p = Popen(['git', 'describe'], stdout = PIPE,stderr=PIPE, cwd =mod_dir )

    try:
        out,er = p.communicate()
    except(OSError):
        return None

    out = out.strip('\n')
    if out == '':
        return None
    return out

# general purpose objects

class HomoList(collections.Sequence):
    '''

    A Homogeneous Sequence

    Provides a class for a list-like object which contains
    homogeneous values. Attributes of the values can be accessed through
    the attributes of HomoList. Searching is done like numpy arrays.

    Initialized from a list  of all the same type

    >>> h = HomoDict([Foo(...), Foo(...)])

    The individual values of `h` can be access in identical fashion to
    Lists.

    >>> h[0]

    Assuming that `Foo` has property `prop`  and function `func` ...

    Access elements' properties:

    >>> h.prop

    Access elements' functions:

    >>> h.func()

    Searching:

    >>> h[h.prop == value]
    >>> h[h.prop < value]

    Multiple search:

    >>> h[set(h.prop==value1) & set( h.prop2==value2)]

    Combos:

    >>> h[h.prop==value].func()
    '''

    def __init__(self, list_):
        self.store = list(list_)

    def __eq__(self, value):
        return [k for k in range(len(self)) if self.store[k] == value ]

    def __ne__(self, value):
        return [k for k in range(len(self)) if self.store[k] != value ]

    def __gt__(self, value):
        return [k for k in range(len(self)) if self.store[k] > value ]

    def __ge__(self, value):
        return [k for k in range(len(self)) if self.store[k] >= value ]

    def __lt__(self, value):
        return [k for k in range(len(self)) if self.store[k] < value ]

    def __le__(self, value):
        return [k for k in range(len(self)) if self.store[k] <= value ]

    def __getattr__(self, name):
        return self.__class__(
            [k.__getattribute__(name) for k in self.store])

    def __getitem__(self, idx):
        try:
            return self.store[idx]
        except(TypeError):
            return self.__class__([self.store[k] for k in idx])

    def __call__(self, *args, **kwargs):
        return self.__class__(
            [k(*args,**kwargs) for k in self.store])

    def __setitem__(self, idx, value):
        self.store[idx] = value

    def __delitem__(self, idx):
        del self.store[idx]

    def __iter__(self):
        return iter(self.store)

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

    def __str__(self):
        return pprint.pformat(self.store)

    def __repr__(self):
        return pprint.pformat(self.store)

class HomoDict(collections.MutableMapping):
    '''
    A Homogeneous Mutable Mapping

    Provides a class for a dictionary-like object which contains
    homogeneous values. Attributes of the values can be accessed through
    the attributes of HomoDict. Searching is done like numpy arrays.

    Initialized from a dictionary containing values of all the same type

    >>> h = HomoDict({'a':Foo(...),'b': Foo(...), 'c':Foo(..)})

    The individual values of `h` can be access in identical fashion to
    Dictionaries.

    >>> h['key']

    Assuming that `Foo` has property `prop`  and function `func` ...

    Access elements' properties:

    >>> h.prop

    Access elements' functions:

    >>> h.func()

    Searching:

    >>> h[h.prop == value]
    >>> h[h.prop < value]

    Multiple search:

    >>> h[set(h.prop==value1) & set( h.prop2==value2)]

    Combos:

    >>> h[h.prop==value].func()
    '''
    def __init__(self, dict_):
        self.store = dict(dict_)

    def __eq__(self, value):
        return [k for k in self.store if self.store[k] == value ]

    def __ne__(self, value):
        return [k for k in self.store if self.store[k] != value ]

    def __gt__(self, value):
        return [k for k in self.store if self.store[k] > value ]

    def __ge__(self, value):
        return [k for k in self.store if self.store[k] >= value ]

    def __lt__(self, value):
        return [k for k in self.store if self.store[k] < value ]

    def __le__(self, value):
        return [k for k in self.store if self.store[k] <= value ]

    def __getattr__(self, name):
        return self.__class__(
            {k: getattr(self.store[k],name) for k in self.store})

    def __getitem__(self, key):
        if isinstance(key, str):
            return self.store[key]
        else:
            c =   self.__class__({k:self.store[k] for k in key})
        return c
        #if len(c) == 1:
        #    return c.store.values()[0]
        #else:
        #    return c

    def __call__(self, *args, **kwargs):
        return self.__class__(
            {k: self.store[k](*args, **kwargs) for k in self.store})

    def __setitem__(self, key, value):
        self.store[key] = value

    def __delitem__(self, key):
        del self.store[key]

    def __iter__(self):
        return iter(self.store)

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

    def __str__(self):
        return pprint.pformat(self.store)

    def __repr__(self):
        return pprint.pformat(self.store)

    def filter_nones(self):
        self.store =  {k:self.store[k] for k in self.store \
                        if self.store[k] is not None}

<|endoftext|>


<commit_before>import json
import logging

from django.conf import settings
from django.http import HttpResponse
from django.shortcuts import render, redirect, render_to_response
from django.template import RequestContext

from api.models import UserPreferences, MaintenanceRecord
from troposphere.version import get_version
from .emulation import is_emulated_session
from .maintenance import get_maintenance

logger = logging.getLogger(__name__)

#TODO: Move this into a settings file.
STAFF_LIST_USERNAMES = ['estevetest01', 'estevetest02','estevetest03','estevetest04',
                        'estevetest13', 'sgregory', 'lenards', 'tharon', 'cdosborn']

def root(request):
    return redirect('application')

def _should_show_troposphere_only():
    # `SHOW_TROPOSPHERE_ONLY` may not be present in `settings`, so use
    # `hasattr` to handle when it is not present & avoid 500 errors on load.
    return hasattr(settings, "SHOW_TROPOSPHERE_ONLY") and settings.SHOW_TROPOSPHERE_ONLY is True

def _populate_template_params(request, maintenance_records, disabled_login, public=False):
    """
    Creates a dict of parameters for later template merge given the arguments,
    request session, and django settings (defined in `default.py` or overidden
    in `local.py`).
    """
    show_troposphere_only = _should_show_troposphere_only()

    template_params = {
        'access_token': request.session.get('access_token'),
        'emulator_token': request.session.get('emulator_token'),
        'emulated_by': request.session.get('emulated_by'),
        'records': maintenance_records,
        'show_troposphere_only': show_troposphere_only,
        'show_public_site': public
    }

    show_instance_metrics = getattr(settings, "SHOW_INSTANCE_METRICS", False)

    if public:
        template_params['disable_login'] = disabled_login
    else:
        logger.info("public was false... ")
        template_params['disable_login'] = False
        template_params['show_instance_metrics'] = show_instance_metrics
        # Only include Intercom information when rendering the authenticated
        # version of the site.
        if hasattr(settings, "INTERCOM_APP_ID"):
            template_params['intercom_app_id'] = settings.INTERCOM_APP_ID
            template_params['intercom_company_id'] = settings.INTERCOM_COMPANY_ID
            template_params['intercom_company_name'] = settings.INTERCOM_COMPANY_NAME

    template_params['SITE_TITLE'] = settings.SITE_TITLE
    template_params['SITE_FOOTER'] = settings.SITE_FOOTER
    template_params['SUPPORT_EMAIL'] = settings.SUPPORT_EMAIL
    template_params['UI_VERSION'] = settings.UI_VERSION
    template_params['BADGE_HOST'] = getattr(settings, "BADGE_HOST", None)

    #TODO: Replace this line when theme support is re-enabled.
    #template_params["THEME_URL"] = "assets/"
    template_params["THEME_URL"] = "/themes/%s" % settings.THEME_NAME
    template_params['ORG_NAME'] = settings.ORG_NAME

    if hasattr(settings, "BASE_URL"):
        template_params['BASE_URL'] = settings.BASE_URL

    if hasattr(settings, "API_ROOT"):
        template_params['API_ROOT'] = settings.API_ROOT

    if hasattr(settings, "API_V2_ROOT"):
        template_params['API_V2_ROOT'] = settings.API_V2_ROOT

    if hasattr(settings, "USE_GATE_ONE_API"):
        template_params["USE_GATE_ONE_API"] = settings.USE_GATE_ONE_API
        template_params["WEB_SH_URL"] = settings.WEB_SH_URL

    return template_params, show_troposphere_only

def _handle_public_application_request(request, maintenance_records, disabled_login=False):
    """
    Deal with unauthenticated requests:

    - For troposphere, there is the opportunity to browser the Public Image Catalog.
    - For airport, there is nothing to do but ask for people to `login.html`.
    """
    template_params, show_troposphere_only = _populate_template_params(request,
            maintenance_records, disabled_login, True)

    # If show airport_ui flag in query params, set the session value to that
    if "airport_ui" in request.GET:
        request.session['airport_ui'] = request.GET['airport_ui'].lower()

    # only honor `?beta=false` from the query string...
    if "beta" in request.GET and request.GET['beta'].lower() is 'false':
        request.session['beta'] = request.GET['beta'].lower()

    if "airport_ui" not in request.session:
        request.session['airport_ui'] = 'false'
        # the absence flag to show the airport_ui would be equal to 'false'

    show_airport = request.session['airport_ui'] == 'true'

    # Return the new Troposphere UI
    if not show_airport or show_troposphere_only:
        response = render_to_response(
            'index.html',
            template_params,
            context_instance=RequestContext(request)
        )
    else: # Return the old Airport UI
        response = render_to_response(
            'login.html',
            template_params,
            context_instance=RequestContext(request)
        )

    response.set_cookie('beta', request.session['beta'])
    response.set_cookie('airport_ui', request.session['airport_ui'])
    return response

def _handle_authenticated_application_request(request, maintenance_records):
    """
    Deals with request verified identities via `iplantauth` module.
    """
    template_params, show_troposphere_only = _populate_template_params(request,
            maintenance_records, disabled_login=False, public=False)

    user_preferences, created = UserPreferences.objects\
        .get_or_create(user=request.user)
    prefs_modified = False

    # TODO - once phased out, we should ignore show_beta_interface altogether
    # ----
    # If beta flag in query params, set the session value to that
    if "beta" in request.GET:
        prefs_modified = True
        request.session['beta'] = request.GET['beta'].lower()
        user_preferences.show_beta_interface = (
            request.session['beta'] is 'true')

    # Moving forward, the UI version shown will be controlled by
    # `airport_ui=<bool>` - and `beta` will be removed.
    if "airport_ui" in request.GET:
        prefs_modified = True
        request.session['airport_ui'] = request.GET['airport_ui'].lower()
        user_preferences.airport_ui = (
            request.session['airport_ui'] is 'true')

    if prefs_modified and not is_emulated_session(request):
        user_preferences.save()

    chose_airport = (user_preferences.airport_ui or
        not user_preferences.show_beta_interface)

    # show airport-ui if it's true and we are showing the option
    # of switching UIs
    # ----------
    # Return the old Airport UI
    if chose_airport and not show_troposphere_only:
        response = render_to_response(
            'cf2.html',
            template_params,
            context_instance=RequestContext(request)
        )
    else: # Return the new Troposphere UI
        response = render_to_response(
            'index.html',
            template_params,
            context_instance=RequestContext(request)
        )

    return response

def application_backdoor(request):
    response = HttpResponse()
    maintenance_records, disabled_login = get_maintenance(request)
    # This should only apply when in maintenance//login is disabled
    if not disabled_login or maintenance_records.count() == 0:
        return application(request)

    if request.user.is_authenticated() and request.user.username not in STAFF_LIST_USERNAMES:
        logger.warn('[Backdoor] %s is NOT in staff_list_usernames' % request.user.username)
        return redirect('maintenance')
    disabled_login = False
    maintenance_records = MaintenanceRecord.objects.none()
    if request.user.is_authenticated():
        return _handle_authenticated_application_request(request, maintenance_records)
    else:
        return _handle_public_application_request(request, maintenance_records, disabled_login=disabled_login)

def application(request):
    response = HttpResponse()
    maintenance_records, disabled_login = get_maintenance(request)

    if disabled_login and request.user.is_staff is not True and request.user.username not in STAFF_LIST_USERNAMES:
        logger.warn('[App] %s logged in but is NOT in staff_list_usernames' % request.user.username)
        return redirect('maintenance')
    if request.user.is_authenticated():
        return _handle_authenticated_application_request(request, maintenance_records)
    else:
        return _handle_public_application_request(request, maintenance_records, disabled_login=disabled_login)

def forbidden(request):
    """
    View used when someone tries to log in and is an authenticated iPlant
    user, but was found to be unauthorized to use Atmosphere by OAuth.
    Returns HTTP status code 403 Forbidden
    """

    # If banner message in query params, pass it into the template
    template_params = {}

    template_params["THEME_URL"] = "/themes/%s" % settings.THEME_NAME
    template_params['ORG_NAME'] = settings.ORG_NAME
    template_params['SITE_TITLE'] = settings.SITE_TITLE
    template_params['SITE_FOOTER'] = settings.SITE_FOOTER
    if hasattr(settings, "BASE_URL"):
        template_params['BASE_URL'] = settings.BASE_URL

    if "banner" in request.GET:
        template_params['banner'] = request.GET['banner']
    response = render_to_response(
        'no_user.html',
        template_params,
        context_instance=RequestContext(request)
    )
    return response

def version(request):
    v = get_version()
    v["commit_date"] = v["commit_date"].isoformat()
    v_json = json.dumps(v)
    return HttpResponse(v_json, content_type='application/json')

def tests(request):

    template_params = {
        'test': request.GET['test'].lower()
    }

    return render(request, 'tests.html', template_params)
<commit_msg>Reformat<commit_after>import json
import logging

from django.conf import settings
from django.http import HttpResponse
from django.shortcuts import render, redirect, render_to_response
from django.template import RequestContext

from api.models import UserPreferences, MaintenanceRecord
from troposphere.version import get_version
from .emulation import is_emulated_session
from .maintenance import get_maintenance

logger = logging.getLogger(__name__)

#TODO: Move this into a settings file.
STAFF_LIST_USERNAMES = ['estevetest01', 'estevetest02','estevetest03','estevetest04',
                        'estevetest13', 'sgregory', 'lenards', 'tharon', 'cdosborn']

def root(request):
    return redirect('application')

def _should_show_troposphere_only():
    # `SHOW_TROPOSPHERE_ONLY` may not be present in `settings`, so use
    # `hasattr` to handle when it is not present & avoid 500 errors on load.
    return hasattr(settings, "SHOW_TROPOSPHERE_ONLY") and settings.SHOW_TROPOSPHERE_ONLY is True

def _populate_template_params(request, maintenance_records, disabled_login, public=False):
    """
    Creates a dict of parameters for later template merge given the arguments,
    request session, and django settings (defined in `default.py` or overidden
    in `local.py`).
    """
    show_troposphere_only = _should_show_troposphere_only()

    template_params = {
        'access_token': request.session.get('access_token'),
        'emulator_token': request.session.get('emulator_token'),
        'emulated_by': request.session.get('emulated_by'),
        'records': maintenance_records,
        'show_troposphere_only': show_troposphere_only,
        'show_public_site': public
    }

    show_instance_metrics = getattr(settings, "SHOW_INSTANCE_METRICS", False)

    if public:
        template_params['disable_login'] = disabled_login
    else:
        logger.info("public was false... ")
        template_params['disable_login'] = False
        template_params['show_instance_metrics'] = show_instance_metrics
        # Only include Intercom information when rendering the authenticated
        # version of the site.
        if hasattr(settings, "INTERCOM_APP_ID"):
            template_params['intercom_app_id'] = settings.INTERCOM_APP_ID
            template_params['intercom_company_id'] = settings.INTERCOM_COMPANY_ID
            template_params['intercom_company_name'] = settings.INTERCOM_COMPANY_NAME

    template_params['SITE_TITLE'] = settings.SITE_TITLE
    template_params['SITE_FOOTER'] = settings.SITE_FOOTER
    template_params['SUPPORT_EMAIL'] = settings.SUPPORT_EMAIL
    template_params['UI_VERSION'] = settings.UI_VERSION
    template_params['BADGE_HOST'] = getattr(settings, "BADGE_HOST", None)

    #TODO: Replace this line when theme support is re-enabled.
    #template_params["THEME_URL"] = "assets/"
    template_params["THEME_URL"] = "/themes/%s" % settings.THEME_NAME
    template_params['ORG_NAME'] = settings.ORG_NAME

    if hasattr(settings, "BASE_URL"):
        template_params['BASE_URL'] = settings.BASE_URL

    if hasattr(settings, "API_ROOT"):
        template_params['API_ROOT'] = settings.API_ROOT

    if hasattr(settings, "API_V2_ROOT"):
        template_params['API_V2_ROOT'] = settings.API_V2_ROOT

    if hasattr(settings, "USE_GATE_ONE_API"):
        template_params["USE_GATE_ONE_API"] = settings.USE_GATE_ONE_API
        template_params["WEB_SH_URL"] = settings.WEB_SH_URL

    return template_params, show_troposphere_only

def _handle_public_application_request(request, maintenance_records, disabled_login=False):
    """
    Deal with unauthenticated requests:

    - For troposphere, there is the opportunity to browser the Public Image Catalog.
    - For airport, there is nothing to do but ask for people to `login.html`.
    """
    template_params, show_troposphere_only = _populate_template_params(request,
            maintenance_records, disabled_login, True)

    # If show airport_ui flag in query params, set the session value to that
    if "airport_ui" in request.GET:
        request.session['airport_ui'] = request.GET['airport_ui'].lower()

    # only honor `?beta=false` from the query string...
    if "beta" in request.GET and request.GET['beta'].lower() is 'false':
        request.session['beta'] = request.GET['beta'].lower()

    if "airport_ui" not in request.session:
        request.session['airport_ui'] = 'false'
        # the absence flag to show the airport_ui would be equal to 'false'

    show_airport = request.session['airport_ui'] == 'true'

    # Return the new Troposphere UI
    if not show_airport or show_troposphere_only:
        response = render_to_response(
            'index.html',
            template_params,
            context_instance=RequestContext(request)
        )
    else: # Return the old Airport UI
        response = render_to_response(
            'login.html',
            template_params,
            context_instance=RequestContext(request)
        )

    response.set_cookie('beta', request.session['beta'])
    response.set_cookie('airport_ui', request.session['airport_ui'])
    return response

def _handle_authenticated_application_request(request, maintenance_records):
    """
    Deals with request verified identities via `iplantauth` module.
    """
    template_params, show_troposphere_only = _populate_template_params(request,
            maintenance_records, disabled_login=False, public=False)

    user_preferences, created = UserPreferences.objects\
        .get_or_create(user=request.user)
    prefs_modified = False

    # TODO - once phased out, we should ignore show_beta_interface altogether
    # ----
    # If beta flag in query params, set the session value to that
    if "beta" in request.GET:
        prefs_modified = True
        request.session['beta'] = request.GET['beta'].lower()
        user_preferences.show_beta_interface = (
            request.session['beta'] is 'true')

    # Moving forward, the UI version shown will be controlled by
    # `airport_ui=<bool>` - and `beta` will be removed.
    if "airport_ui" in request.GET:
        prefs_modified = True
        request.session['airport_ui'] = request.GET['airport_ui'].lower()
        user_preferences.airport_ui = (
            request.session['airport_ui'] is 'true')

    if prefs_modified and not is_emulated_session(request):
        user_preferences.save()

    chose_airport = (user_preferences.airport_ui or
        not user_preferences.show_beta_interface)

    # show airport-ui if it's true and we are showing the option
    # of switching UIs
    # ----------
    # Return the old Airport UI
    if chose_airport and not show_troposphere_only:
        response = render_to_response(
            'cf2.html',
            template_params,
            context_instance=RequestContext(request)
        )
    else: # Return the new Troposphere UI
        response = render_to_response(
            'index.html',
            template_params,
            context_instance=RequestContext(request)
        )

    return response

def application_backdoor(request):
    response = HttpResponse()
    maintenance_records, disabled_login = get_maintenance(request)
    # This should only apply when in maintenance//login is disabled
    if not disabled_login or maintenance_records.count() == 0:
        return application(request)

    if request.user.is_authenticated() and request.user.username not in STAFF_LIST_USERNAMES:
        logger.warn('[Backdoor] %s is NOT in staff_list_usernames' % request.user.username)
        return redirect('maintenance')
    disabled_login = False
    maintenance_records = MaintenanceRecord.objects.none()
    if request.user.is_authenticated():
        return _handle_authenticated_application_request(request, maintenance_records)
    else:
        return _handle_public_application_request(request, maintenance_records, disabled_login=disabled_login)

def application(request):
    response = HttpResponse()
    maintenance_records, disabled_login = get_maintenance(request)

    if disabled_login and request.user.is_staff is not True and request.user.username not in STAFF_LIST_USERNAMES:
        logger.warn('[App] %s logged in but is NOT in staff_list_usernames' % request.user.username)
        return redirect('maintenance')
    if request.user.is_authenticated():
        return _handle_authenticated_application_request(request, maintenance_records)
    else:
        return _handle_public_application_request(request, maintenance_records, disabled_login=disabled_login)

def forbidden(request):
    """
    View used when someone tries to log in and is an authenticated iPlant
    user, but was found to be unauthorized to use Atmosphere by OAuth.
    Returns HTTP status code 403 Forbidden
    """

    # If banner message in query params, pass it into the template
    template_params = {}

    template_params["THEME_URL"] = "/themes/%s" % settings.THEME_NAME
    template_params['ORG_NAME'] = settings.ORG_NAME
    template_params['SITE_TITLE'] = settings.SITE_TITLE
    template_params['SITE_FOOTER'] = settings.SITE_FOOTER
    if hasattr(settings, "BASE_URL"):
        template_params['BASE_URL'] = settings.BASE_URL

    if "banner" in request.GET:
        template_params['banner'] = request.GET['banner']
    response = render_to_response(
        'no_user.html',
        template_params,
        context_instance=RequestContext(request)
    )
    return response

def version(request):
    v = get_version()
    v["commit_date"] = v["commit_date"].isoformat()
    v_json = json.dumps(v)
    return HttpResponse(v_json, content_type='application/json')

def tests(request):

    template_params = {
        'test': request.GET['test'].lower()
    }

    return render(request, 'tests.html', template_params)
<|endoftext|>