<commit_before>import json

try:  # Python 3
    import urllib.request as urllib_request
    from urllib.parse import urlencode as urllib_encode
    PYTHON_VER = 3

except ImportError:  # Python 2
    import urllib2 as urllib_request
    from urllib import urlencode as urllib_encode
    PYTHON_VER = 2

_MAX_EXPIRE = 86400
_MIN_RETRY = 30

class Sounds(object):
    """
    Sounds - Collection of Push Notification sounds.

    This is to be used with the 'sounds' argument of the PushOverManager.push_notification method.

    see also: https://pushover.net/api#sounds
    """
    Short_Pushover = 'pushover'
    Short_Bike = 'bike'
    Short_Bugle = 'bugle'
    Short_Cash_Register = 'cashregister'
    Short_Classical = 'classical'
    Short_Cosmic = 'cosmic'
    Short_Gamelan = 'gamelan'
    Short_Incoming = 'incoming'
    Short_Intermission = 'intermission'
    Short_Magic = 'magic'
    Short_Mechanical = 'mechanical'
    Short_Piano_Bar = 'pianobar'
    Short_Siren = 'siren'
    Short_Space_Alarm = 'spacealarm'
    Short_Tug_Boat = 'tugboat'
    Long_Alien_Alarm = 'alien'
    Long_Climb = 'climb'
    Long_Persistent = 'persistent'
    Long_Pushover_Echo = 'echo'
    Long_Up_Down = 'updown'
    Silent = 'none'

class Priority(object):
    """
    Priority - Collection of Priorities.

    This is to be used with the 'priority' arguemnt of the PushOverManager.push_notification method.

    see also: https://pushover.net/api#priority
    """
    Lowest = -2     # no notification/alert
    Low = -1        # quiet notification
    Normal = 0      # normal
    High = 1        # high-priority (bypass user's quiet hours)
    Emergency = 2   # require confirmation from the user (bypass users's quiet hours)

class PushOverManager(object):
    """
    Push Over Manager - Class for interfacing with the Pushover API.

    Properties:
    -----------
    latest_response

    Methods:
    --------
    push_notification - pushes a notification to a device, user or group.
    check_receipt
    cancel_retries
    validate_user
    validate_group
    """
    _push_url = "https://api.pushover.net/1/messages.json"
    _validate_url = "https://api.pushover.net/1/users/validate.json"
    _receipt_url = "https://api.pushover.net/1/receipts/{receipt}.json?token={app_token}"
    _cancel_receipt_url = "https://api.pushover.net/1/receipts/{receipt}/cancel.json"

    def __init__(self, app_token, client_key=None):
        """

        :param str app_token: Application token generated from PushOver site
        :param str client_key: User or Group key generated from PushOver site
        """
        self._app_token = app_token
        self._client_key = client_key  # Can be a user or group key
        self.latest_response = None
        self._latest_json_response = None

    def push_message(self, message, **kwargs):
        """
        Send message to selected user/group/device.

        :param str message: your message
        :param str client: user or group id to send the message to
        :param str title: your message's title, otherwise your app's name is used
        :param str device: your user's device name to send the message directly to that device
        :param list device: your user's devices names to send the message directly to that device
        :param str url: a supplementary URL to show with your message
        :param str url_title: a title for your supplementary URL, otherwise just the URL is shown
        :param int priority: message priority (Use the Priority class to select)
        :param int retry: how often (in seconds) the Pushover servers will retry the notification to the user (required
                          only with priority level of Emergency)
        :param int expire: how many seconds your notification will continue to be retried (required only with priority
                           level of Emergency)
        :param int timestamp: a Unix timestamp of your message's date and time to display to the user
        :param str sound: the name of the sound to override the user's default sound choice
                          (Use the Sounds class to select)
        """

        # determine if client key has already been saved.  If not then get argument
        client_key = self._client_key
        if 'client' in kwargs:
            client_key = kwargs['client']

        # client key required to push message
        if client_key is None:
            raise ValueError('`client` argument must be set to the group or user id')

        data_out = {
            'token': self._app_token,
            'user': client_key,  # can be a user or group key
            'message': message
        }

        # Support for non-required parameters of PushOver
        if 'title' in kwargs:
            data_out['title'] = kwargs['title']
        if 'device' in kwargs:
            temp = kwargs['device']
            if type(temp) == list:
                data_out['device'] = ','.join(temp)
            else:
                data_out['device'] = temp
            data_out['device'] = kwargs['device']
        if 'url' in kwargs:
            data_out['url'] = kwargs['url']
        if 'url_title' in kwargs:
            data_out['url_title'] = kwargs['url_title']
        if 'priority' in kwargs:
            data_out['priority'] = kwargs['priority']

            # Emergency prioritized messages require 'retry' and 'expire' to be defined
            if data_out['priority'] == Priority.Emergency:
                if 'retry' not in kwargs:
                    raise TypeError('Missing `retry` argument required for message priority of Emergency')
                else:
                    retry_val = kwargs['retry']

                    # 'retry' val must be a minimum of _MIN_RETRY and max of _MAX_EXPIRE
                    if _MAX_EXPIRE < retry_val < _MIN_RETRY:
                        raise ValueError('`retry` argument must be at a minimum of {} and a maximum of {}'.format(
                            _MIN_RETRY, _MAX_EXPIRE
                        ))

                    data_out['retry'] = retry_val
                if 'expire' not in kwargs:
                    raise TypeError('Missing `expire` arguemnt required for message priority of Emergency')
                else:
                    expire_val = kwargs['expire']

                    # 'expire' val must be a minimum of _MIN_RETRY and max of _MAX_EXPIRE
                    if _MAX_EXPIRE < expire_val < _MIN_RETRY:
                        raise ValueError('`expire` argument must be at a minimum of {} and a maximum of {}'.format(
                            _MIN_RETRY, _MAX_EXPIRE
                        ))

                    data_out['expire'] = expire_val

        if 'timestamp' in kwargs:
            data_out['timestamp'] = kwargs['timestamp']
        if 'sound' in kwargs:
            data_out['sound'] = kwargs['sound']

        self._send(self._push_url, data_out)

    def check_receipt(self, receipt=None):
        """
        Gets the receipt status of the selected notificiation.  Returns a dictionary of the results

        see also https://pushover.net/api#receipt
        :param string receipt: the notification receipt to check
        :return dict:
        """
        receipt_to_check = None

        # check to see if previous response had a `receipt`
        if 'receipt' in self._latest_json_response:
            receipt_to_check = self._latest_json_response['receipt']

        # function `receipt` argument takes precedence
        if receipt:
            receipt_to_check = receipt

        # no receipt supplied from either last call or function argument.  Raise error
        if receipt_to_check is None:
            raise TypeError('Missing required `receipt` argument')

        url_to_send = self._receipt_url.format(receipt=receipt_to_check, app_token=self._app_token)
        self._send(url_to_send)
        return self._latest_json_response

    def cancel_retries(self, receipt=None):
        """
        Cancel an emergency-priority notification early.
        :param string receipt:
        """
        receipt_to_check = None

        # check to see if previous response had a `receipt`
        if 'receipt' in self._latest_json_response:
            receipt_to_check = self._latest_json_response['receipt']

        # function `receipt` argument takes precedence
        if receipt:
            receipt_to_check = receipt

        # no receipt supplied from either last call or function argument.  Raise error
        if receipt_to_check is None:
            raise TypeError('Missing required `receipt` argument')

        url_to_send = self._cancel_receipt_url.format(receipt=receipt_to_check)
        self._send(url_to_send, data_out={'token': self._app_token})

    def validate_user(self, user_id, device=None):
        """
        Validates whether a userID is a valid id and returns a Boolean as a result

        :param user_id:
        :return bool:
        """
        return self.validate_group(user_id, device)

    def validate_group(self, group_id, device=None):
        """
        Validates whether a groupID is a valid ID and returns a Boolean as a result

        :param group_id:
        :return bool:
        """
        param_data = {
            'token': self._app_token,
            'user': group_id
        }

        if device:
            param_data['device'] = device

        self._send(self._validate_url, param_data, check_response=False)

        if self._latest_json_response['status'] == 1:
            return True
        else:
            return False

    def _send(self, url, data_out=None, check_response=True):
        """
        Sends a formatted request to the supplied url.  If data_out is present, then the data is encoded and sent as
        well.  A check_response value of False the HTTP response code is checked.  A customized HTTPError is raised if
        an error is detected.

        :param string url: url of the site to send the request to (http://www.site.com)
        :param dict data_out: data to be encoded with the url (?token=<app_token>&user=<user_id>)
        :param bool check_response: check http response and raise exception if an error is detected
        """
        if data_out:
            param_data = urllib_encode(data_out)
            if PYTHON_VER == 3:
                param_data = param_data.encode("utf-8")
        else:
            param_data = ''
        req = urllib_request.Request(url, param_data)

        try:
            self.latest_response = urllib_request.urlopen(req)
        except urllib_request.HTTPError as req:
            self.latest_response = req

        if PYTHON_VER == 3:
            self._latest_json_response = json.loads(self.latest_response.readall().decode('utf-8'))
        else:
            self._latest_json_response = json.loads(self.latest_response.read())

        if check_response:
            self._response_check(self.latest_response)

    def _response_check(self, response):
        """
        Checks the HTTP Response code and raises a customized HTTPError based on the Pushover 'errors' response.

        :param Request response: response from server
        """
        if response.code == 200:
            return

        elif 400 <= response.code < 500:
            error = self._latest_json_response['errors']
            self.latest_response.msg = error
            raise self.latest_response

        else:
            raise self.latest_response<commit_msg>Working the Group API<commit_after>import json

try:  # Python 3
    import urllib.request as urllib_request
    from urllib.parse import urlencode as urllib_encode
    PYTHON_VER = 3

except ImportError:  # Python 2
    import urllib2 as urllib_request
    from urllib import urlencode as urllib_encode
    PYTHON_VER = 2

_MAX_EXPIRE = 86400
_MIN_RETRY = 30

class Sounds(object):
    """
    Sounds - Collection of Push Notification sounds.

    This is to be used with the 'sounds' argument of the PushOverManager.push_notification method.

    see also: https://pushover.net/api#sounds
    """
    Short_Pushover = 'pushover'
    Short_Bike = 'bike'
    Short_Bugle = 'bugle'
    Short_Cash_Register = 'cashregister'
    Short_Classical = 'classical'
    Short_Cosmic = 'cosmic'
    Short_Gamelan = 'gamelan'
    Short_Incoming = 'incoming'
    Short_Intermission = 'intermission'
    Short_Magic = 'magic'
    Short_Mechanical = 'mechanical'
    Short_Piano_Bar = 'pianobar'
    Short_Siren = 'siren'
    Short_Space_Alarm = 'spacealarm'
    Short_Tug_Boat = 'tugboat'
    Long_Alien_Alarm = 'alien'
    Long_Climb = 'climb'
    Long_Persistent = 'persistent'
    Long_Pushover_Echo = 'echo'
    Long_Up_Down = 'updown'
    Silent = 'none'

class Priority(object):
    """
    Priority - Collection of Priorities.

    This is to be used with the 'priority' arguemnt of the PushOverManager.push_notification method.

    see also: https://pushover.net/api#priority
    """
    Lowest = -2     # no notification/alert
    Low = -1        # quiet notification
    Normal = 0      # normal
    High = 1        # high-priority (bypass user's quiet hours)
    Emergency = 2   # require confirmation from the user (bypass users's quiet hours)

class PushOverManager(object):
    """
    Push Over Manager - Class for interfacing with the Pushover API.

    Properties:
    -----------
    latest_response

    Methods:
    --------
    push_notification - pushes a notification to a device, user or group.
    check_receipt
    cancel_retries
    validate_user
    validate_group
    """
    _push_url = "https://api.pushover.net/1/messages.json"
    _validate_url = "https://api.pushover.net/1/users/validate.json"
    _receipt_url = "https://api.pushover.net/1/receipts/{receipt}.json?token={app_token}"
    _cancel_receipt_url = "https://api.pushover.net/1/receipts/{receipt}/cancel.json"

    def __init__(self, app_token, client_key=None):
        """

        :param str app_token: Application token generated from PushOver site
        :param str client_key: User or Group key generated from PushOver site
        """
        self._app_token = app_token
        self._client_key = client_key  # Can be a user or group key
        self.latest_response = None
        self._latest_json_response = None

    def push_message(self, message, **kwargs):
        """
        Send message to selected user/group/device.

        :param str message: your message
        :param str client: user or group id to send the message to
        :param str title: your message's title, otherwise your app's name is used
        :param str device: your user's device name to send the message directly to that device
        :param list device: your user's devices names to send the message directly to that device
        :param str url: a supplementary URL to show with your message
        :param str url_title: a title for your supplementary URL, otherwise just the URL is shown
        :param int priority: message priority (Use the Priority class to select)
        :param int retry: how often (in seconds) the Pushover servers will retry the notification to the user (required
                          only with priority level of Emergency)
        :param int expire: how many seconds your notification will continue to be retried (required only with priority
                           level of Emergency)
        :param int timestamp: a Unix timestamp of your message's date and time to display to the user
        :param str sound: the name of the sound to override the user's default sound choice
                          (Use the Sounds class to select)
        """

        # determine if client key has already been saved.  If not then get argument
        client_key = self._client_key
        if 'client' in kwargs:
            client_key = kwargs['client']

        # client key required to push message
        if client_key is None:
            raise ValueError('`client` argument must be set to the group or user id')

        data_out = {
            'token': self._app_token,
            'user': client_key,  # can be a user or group key
            'message': message
        }

        # Support for non-required parameters of PushOver
        if 'title' in kwargs:
            data_out['title'] = kwargs['title']
        if 'device' in kwargs:
            temp = kwargs['device']
            if type(temp) == list:
                data_out['device'] = ','.join(temp)
            else:
                data_out['device'] = temp
            data_out['device'] = kwargs['device']
        if 'url' in kwargs:
            data_out['url'] = kwargs['url']
        if 'url_title' in kwargs:
            data_out['url_title'] = kwargs['url_title']
        if 'priority' in kwargs:
            data_out['priority'] = kwargs['priority']

            # Emergency prioritized messages require 'retry' and 'expire' to be defined
            if data_out['priority'] == Priority.Emergency:
                if 'retry' not in kwargs:
                    raise TypeError('Missing `retry` argument required for message priority of Emergency')
                else:
                    retry_val = kwargs['retry']

                    # 'retry' val must be a minimum of _MIN_RETRY and max of _MAX_EXPIRE
                    if _MAX_EXPIRE < retry_val < _MIN_RETRY:
                        raise ValueError('`retry` argument must be at a minimum of {} and a maximum of {}'.format(
                            _MIN_RETRY, _MAX_EXPIRE
                        ))

                    data_out['retry'] = retry_val
                if 'expire' not in kwargs:
                    raise TypeError('Missing `expire` arguemnt required for message priority of Emergency')
                else:
                    expire_val = kwargs['expire']

                    # 'expire' val must be a minimum of _MIN_RETRY and max of _MAX_EXPIRE
                    if _MAX_EXPIRE < expire_val < _MIN_RETRY:
                        raise ValueError('`expire` argument must be at a minimum of {} and a maximum of {}'.format(
                            _MIN_RETRY, _MAX_EXPIRE
                        ))

                    data_out['expire'] = expire_val

        if 'timestamp' in kwargs:
            data_out['timestamp'] = kwargs['timestamp']
        if 'sound' in kwargs:
            data_out['sound'] = kwargs['sound']

        self._send(self._push_url, data_out)

    def check_receipt(self, receipt=None):
        """
        Gets the receipt status of the selected notificiation.  Returns a dictionary of the results

        see also https://pushover.net/api#receipt
        :param string receipt: the notification receipt to check
        :return dict:
        """
        receipt_to_check = None

        # check to see if previous response had a `receipt`
        if 'receipt' in self._latest_json_response:
            receipt_to_check = self._latest_json_response['receipt']

        # function `receipt` argument takes precedence
        if receipt:
            receipt_to_check = receipt

        # no receipt supplied from either last call or function argument.  Raise error
        if receipt_to_check is None:
            raise TypeError('Missing required `receipt` argument')

        url_to_send = self._receipt_url.format(receipt=receipt_to_check, app_token=self._app_token)
        self._send(url_to_send)
        return self._latest_json_response

    def cancel_retries(self, receipt=None):
        """
        Cancel an emergency-priority notification early.
        :param string receipt:
        """
        receipt_to_check = None

        # check to see if previous response had a `receipt`
        if 'receipt' in self._latest_json_response:
            receipt_to_check = self._latest_json_response['receipt']

        # function `receipt` argument takes precedence
        if receipt:
            receipt_to_check = receipt

        # no receipt supplied from either last call or function argument.  Raise error
        if receipt_to_check is None:
            raise TypeError('Missing required `receipt` argument')

        url_to_send = self._cancel_receipt_url.format(receipt=receipt_to_check)
        self._send(url_to_send, data_out={'token': self._app_token})

    def validate_user(self, user_id, device=None):
        """
        Validates whether a userID is a valid id and returns a Boolean as a result

        :param user_id:
        :return bool:
        """
        return self.validate_group(user_id, device)

    def validate_group(self, group_id, device=None):
        """
        Validates whether a groupID is a valid ID and returns a Boolean as a result

        :param group_id:
        :return bool:
        """
        param_data = {
            'token': self._app_token,
            'user': group_id
        }

        if device:
            param_data['device'] = device

        self._send(self._validate_url, param_data, check_response=False)

        if self._latest_json_response['status'] == 1:
            return True
        else:
            return False

    def group_info(self):
        raise NotImplementedError

    def group_add_user(self):
        raise NotImplementedError

    def group_remove_user(self):
        raise NotImplementedError

    def group_disable_user(self):
        raise NotImplementedError

    def group_enable_user(self):
        raise NotImplementedError

    def group_rename(self):
        raise NotImplementedError

    def _send(self, url, data_out=None, check_response=True):
        """
        Sends a formatted request to the supplied url.  If data_out is present, then the data is encoded and sent as
        well.  A check_response value of False the HTTP response code is checked.  A customized HTTPError is raised if
        an error is detected.

        :param string url: url of the site to send the request to (http://www.site.com)
        :param dict data_out: data to be encoded with the url (?token=<app_token>&user=<user_id>)
        :param bool check_response: check http response and raise exception if an error is detected
        """
        if data_out:
            param_data = urllib_encode(data_out)
            if PYTHON_VER == 3:
                param_data = param_data.encode("utf-8")
        else:
            param_data = ''
        req = urllib_request.Request(url, param_data)

        try:
            self.latest_response = urllib_request.urlopen(req)
        except urllib_request.HTTPError as req:
            self.latest_response = req

        if PYTHON_VER == 3:
            self._latest_json_response = json.loads(self.latest_response.readall().decode('utf-8'))
        else:
            self._latest_json_response = json.loads(self.latest_response.read())

        if check_response:
            self._response_check(self.latest_response)

    def _response_check(self, response):
        """
        Checks the HTTP Response code and raises a customized HTTPError based on the Pushover 'errors' response.

        :param Request response: response from server
        """
        if response.code == 200:
            return

        elif 400 <= response.code < 500:
            error = self._latest_json_response['errors']
            self.latest_response.msg = error
            raise self.latest_response

        else:
            raise self.latest_response<|endoftext|>


<commit_before>"""
Overlapped
----------

A module containing Windows functions for working with OVERLAPPED objects.
"""

from pywincffi.core import dist
from pywincffi.core.checks import NON_ZERO, input_check, error_check
from pywincffi.exceptions import WindowsAPIError
from pywincffi.wintypes import HANDLE, OVERLAPPED, wintype_to_cdata

def GetOverlappedResult(hFile, lpOverlapped, bWait):
    """
    Retrieves the results of an overlapped operation on the specified file,
    named pipe, or communications device. To specify a timeout interval or
    wait on an alertable thread, use GetOverlappedResultEx.

    .. seealso::

        https://msdn.microsoft.com/en-us/library/ms683209

    :param HANDLE hFile:
        A handle to the file, named pipe, or communications device.
        This is the same handle that was specified when the overlapped
        operation was started by a call to the ReadFile, WriteFile,
        ConnectNamedPipe, TransactNamedPipe, DeviceIoControl, or WaitCommEvent
        function.

    :param OVERLAPPED lpOverlapped:
        The an OVERLAPPED object that was specified when the overlapped
        operation was started

    :param bool bWait:
        If this parameter is TRUE, and the Internal member of the lpOverlapped
        structure is STATUS_PENDING, the function does not return until the
        operation has been completed. If this parameter is FALSE and the
        operation is still pending, the function returns FALSE and the
        GetLastError function returns ERROR_IO_INCOMPLETE

    :returns:
        The number of bytes that were actually transferred by a read or write
        operation. For a TransactNamedPipe operation, this is the number of
        bytes that were read from the pipe. For a DeviceIoControl operation,
        this is the number of bytes of output data returned by the device
        driver. For a ConnectNamedPipe or WaitCommEvent operation, this value
        is undefined.
    """
    input_check("hFile", hFile, HANDLE)
    input_check("lpOverlapped", lpOverlapped, OVERLAPPED)
    input_check("bWait", bWait, bool)

    ffi, library = dist.load()

    lpNumberOfBytesTransferred = ffi.new("DWORD[1]")

    result = library.GetOverlappedResult(
        wintype_to_cdata(hFile),
        wintype_to_cdata(lpOverlapped),
        lpNumberOfBytesTransferred,
        ffi.cast("BOOL", bWait),
    )

    try:
        error_check("GetOverlappedResult", result, NON_ZERO)
    except WindowsAPIError as error:
        if error.errno != library.ERROR_ALREADY_EXISTS:
            raise

    return int(lpNumberOfBytesTransferred[0])
<commit_msg>GetOverlappedResult adjustments following review<commit_after>"""
Overlapped
----------

A module containing Windows functions for working with OVERLAPPED objects.
"""

from pywincffi.core import dist
from pywincffi.core.checks import NON_ZERO, input_check, error_check
from pywincffi.exceptions import WindowsAPIError
from pywincffi.wintypes import HANDLE, OVERLAPPED, wintype_to_cdata

def GetOverlappedResult(hFile, lpOverlapped, bWait):
    """
    Retrieves the results of an overlapped operation on the specified file,
    named pipe, or communications device. To specify a timeout interval or
    wait on an alertable thread, use GetOverlappedResultEx.

    .. seealso::

        https://msdn.microsoft.com/en-us/library/ms683209

    :param pywincffi.wintypes.HANDLE hFile:
        A handle to the file, named pipe, or communications device.
        This is the same handle that was specified when the overlapped
        operation was started by a call to the ReadFile, WriteFile,
        ConnectNamedPipe, TransactNamedPipe, DeviceIoControl, or WaitCommEvent
        function.

    :param pywincffi.wintypes.OVERLAPPED lpOverlapped:
        The an OVERLAPPED object that was specified when the overlapped
        operation was started

    :param bool bWait:
        If this parameter is TRUE, and the Internal member of the lpOverlapped
        structure is STATUS_PENDING, the function does not return until the
        operation has been completed. If this parameter is FALSE and the
        operation is still pending, the function returns FALSE and the
        GetLastError function returns ERROR_IO_INCOMPLETE

    :returns:
        The number of bytes that were actually transferred by a read or write
        operation. For a TransactNamedPipe operation, this is the number of
        bytes that were read from the pipe. For a DeviceIoControl operation,
        this is the number of bytes of output data returned by the device
        driver. For a ConnectNamedPipe or WaitCommEvent operation, this value
        is undefined.
    """
    input_check("hFile", hFile, HANDLE)
    input_check("lpOverlapped", lpOverlapped, OVERLAPPED)
    input_check("bWait", bWait, allowed_values=(True, False))

    ffi, library = dist.load()

    lpNumberOfBytesTransferred = ffi.new("DWORD[1]")

    result = library.GetOverlappedResult(
        wintype_to_cdata(hFile),
        wintype_to_cdata(lpOverlapped),
        lpNumberOfBytesTransferred,
        ffi.cast("BOOL", bWait),
    )

    try:
        error_check("GetOverlappedResult", result, NON_ZERO)
    except WindowsAPIError as error:
        if error.errno != library.ERROR_ALREADY_EXISTS:
            raise

    return int(lpNumberOfBytesTransferred[0])
<|endoftext|>


<commit_before>from contextlib import contextmanager
from os.path import abspath, dirname, join
from unittest import TestCase

from mock import MagicMock, patch

from provy.core.roles import DistroInfo

PROJECT_ROOT = abspath(join(dirname(__file__), '..', '..', '..'))

class ProvyTestCase(TestCase):
    @contextmanager
    def using_stub(self, role):
        mock_role = MagicMock(spec=role)

        @contextmanager
        def stub_using(self, klass):
            yield mock_role

        with patch('provy.core.roles.Role.using', stub_using):
            yield mock_role

    @contextmanager
    def execute_mock(self):
        with patch('provy.core.roles.Role.execute') as execute:
            yield execute

    @contextmanager
    def mock_role_method(self, method):
        with patch('provy.core.roles.Role.%s' % method) as mock:
            yield mock

    def debian_info(self):
        distro_info = DistroInfo()
        distro_info.distributor_id = 'Debian'
        distro_info.description = 'Debian GNU/Linux 6.0.5 (squeeze)'
        distro_info.release = '6.0.5'
        distro_info.codename = 'squeeze'
        return distro_info

    def ubuntu_info(self):
        distro_info = DistroInfo()
        distro_info.distributor_id = 'Ubuntu'
        distro_info.description = 'Ubuntu 12.04.1 LTS'
        distro_info.release = '12.04'
        distro_info.codename = 'precise'
        return distro_info

    @contextmanager
    def provisioning_to(self, distro):
        with self.mock_role_method('get_distro_info') as get_distro_info:
            if distro == 'ubuntu':
                distro_info = self.ubuntu_info()
            else:
                distro_info = self.debian_info()
            get_distro_info.return_value = distro_info
            yield

    @contextmanager
    def warn_only(self):
        test_case = self

        @contextmanager
        def settings(warn_only):
            test_case.assertTrue(warn_only)
            yield

        with patch('fabric.api.settings', settings):
            yield
<commit_msg>Making mock_role_method() stick to current role instance<commit_after>from contextlib import contextmanager
from os.path import abspath, dirname, join
from unittest import TestCase

from mock import MagicMock, patch

from provy.core.roles import DistroInfo, Role

PROJECT_ROOT = abspath(join(dirname(__file__), '..', '..', '..'))

class ProvyTestCase(TestCase):
    def setUp(self):
        self.role = Role(prov=None, context={})

    @contextmanager
    def using_stub(self, role):
        mock_role = MagicMock(spec=role)

        @contextmanager
        def stub_using(self, klass):
            yield mock_role

        with patch('provy.core.roles.Role.using', stub_using):
            yield mock_role

    @contextmanager
    def execute_mock(self):
        with patch('provy.core.roles.Role.execute') as execute:
            yield execute

    @contextmanager
    def mock_role_method(self, method):
        '''
        Mocks a method in the current role instance's class - i.e., not necessarily provy.core.roles.Role, depends on the object that self.role holds.
        '''
        with patch.object(self.role.__class__, method) as mock:
            yield mock

    def debian_info(self):
        distro_info = DistroInfo()
        distro_info.distributor_id = 'Debian'
        distro_info.description = 'Debian GNU/Linux 6.0.5 (squeeze)'
        distro_info.release = '6.0.5'
        distro_info.codename = 'squeeze'
        return distro_info

    def ubuntu_info(self):
        distro_info = DistroInfo()
        distro_info.distributor_id = 'Ubuntu'
        distro_info.description = 'Ubuntu 12.04.1 LTS'
        distro_info.release = '12.04'
        distro_info.codename = 'precise'
        return distro_info

    @contextmanager
    def provisioning_to(self, distro):
        with self.mock_role_method('get_distro_info') as get_distro_info:
            if distro == 'ubuntu':
                distro_info = self.ubuntu_info()
            else:
                distro_info = self.debian_info()
            get_distro_info.return_value = distro_info
            yield

    @contextmanager
    def warn_only(self):
        test_case = self

        @contextmanager
        def settings(warn_only):
            test_case.assertTrue(warn_only)
            yield

        with patch('fabric.api.settings', settings):
            yield
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
# Import Python libs
from __future__ import absolute_import

# Import Salt Testing libs
from salttesting import skipIf
from salttesting import TestCase
from salttesting.helpers import ensure_in_syspath
from salttesting.mock import NO_MOCK, NO_MOCK_REASON, patch
ensure_in_syspath('../../')

# Import salt libs
from salt.utils import network

LINUX = '''\
eth0      Link encap:Ethernet  HWaddr e0:3f:49:85:6a:af
          inet addr:10.10.10.56  Bcast:10.10.10.255  Mask:255.255.252.0
          inet6 addr: fe80::e23f:49ff:fe85:6aaf/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:643363 errors:0 dropped:0 overruns:0 frame:0
          TX packets:196539 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:386388355 (368.4 MiB)  TX bytes:25600939 (24.4 MiB)

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:548901 errors:0 dropped:0 overruns:0 frame:0
          TX packets:548901 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:613479895 (585.0 MiB)  TX bytes:613479895 (585.0 MiB)
'''

FREEBSD = '''
em0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
        options=4219b<RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,VLAN_HWCSUM,TSO4,WOL_MAGIC,VLAN_HWTSO>
        ether 00:30:48:ff:ff:ff
        inet 10.10.10.250 netmask 0xffffffe0 broadcast 10.10.10.255
        inet 10.10.10.56 netmask 0xffffffc0 broadcast 10.10.10.63
        media: Ethernet autoselect (1000baseT <full-duplex>)
        status: active
em1: flags=8c02<BROADCAST,OACTIVE,SIMPLEX,MULTICAST> metric 0 mtu 1500
        options=4219b<RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,VLAN_HWCSUM,TSO4,WOL_MAGIC,VLAN_HWTSO>
        ether 00:30:48:aa:aa:aa
        media: Ethernet autoselect
        status: no carrier
plip0: flags=8810<POINTOPOINT,SIMPLEX,MULTICAST> metric 0 mtu 1500
lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> metric 0 mtu 16384
        options=3<RXCSUM,TXCSUM>
        inet6 fe80::1%lo0 prefixlen 64 scopeid 0x8
        inet6 ::1 prefixlen 128
        inet 127.0.0.1 netmask 0xff000000
        nd6 options=3<PERFORMNUD,ACCEPT_RTADV>
tun0: flags=8051<UP,POINTOPOINT,RUNNING,MULTICAST> metric 0 mtu 1500
        options=80000<LINKSTATE>
        inet 10.12.0.1 --> 10.12.0.2 netmask 0xffffffff
        Opened by PID 1964
'''

SOLARIS = '''\
lo0: flags=2001000849<UP,LOOPBACK,RUNNING,MULTICAST,IPv4,VIRTUAL> mtu 8232 index 1
        inet 127.0.0.1 netmask ff000000
net0: flags=100001100943<UP,BROADCAST,RUNNING,PROMISC,MULTICAST,ROUTER,IPv4,PHYSRUNNING> mtu 1500 index 2
        inet 10.10.10.38 netmask ffffffe0 broadcast 10.10.10.63
ilbint0: flags=110001100843<UP,BROADCAST,RUNNING,MULTICAST,ROUTER,IPv4,VRRP,PHYSRUNNING> mtu 1500 index 3
        inet 10.6.0.11 netmask ffffff00 broadcast 10.6.0.255
ilbext0: flags=110001100843<UP,BROADCAST,RUNNING,MULTICAST,ROUTER,IPv4,VRRP,PHYSRUNNING> mtu 1500 index 4
        inet 10.10.11.11 netmask ffffffe0 broadcast 10.10.11.31
ilbext0:1: flags=110001100843<UP,BROADCAST,RUNNING,MULTICAST,ROUTER,IPv4,VRRP,PHYSRUNNING> mtu 1500 index 4
        inet 10.10.11.12 netmask ffffffe0 broadcast 10.10.11.31
vpn0: flags=1000011008d1<UP,POINTOPOINT,RUNNING,NOARP,MULTICAST,ROUTER,IPv4,PHYSRUNNING> mtu 1480 index 5
        inet tunnel src 10.10.11.12 tunnel dst 10.10.5.5
        tunnel hop limit 64
        inet 10.6.0.14 --> 10.6.0.15 netmask ff000000
lo0: flags=2002000849<UP,LOOPBACK,RUNNING,MULTICAST,IPv6,VIRTUAL> mtu 8252 index 1
        inet6 ::1/128
net0: flags=120002004941<UP,RUNNING,PROMISC,MULTICAST,DHCP,IPv6,PHYSRUNNING> mtu 1500 index 2
        inet6 fe80::221:9bff:fefd:2a22/10
ilbint0: flags=120002000840<RUNNING,MULTICAST,IPv6,PHYSRUNNING> mtu 1500 index 3
        inet6 ::/0
ilbext0: flags=120002000840<RUNNING,MULTICAST,IPv6,PHYSRUNNING> mtu 1500 index 4
        inet6 ::/0
vpn0: flags=120002200850<POINTOPOINT,RUNNING,MULTICAST,NONUD,IPv6,PHYSRUNNING> mtu 1480 index 5
        inet tunnel src 10.10.11.12 tunnel dst 10.10.5.5
        tunnel hop limit 64
        inet6 ::/0 --> fe80::b2d6:7c10
'''

FREEBSD_SOCKSTAT = '''\
USER    COMMAND     PID     FD  PROTO  LOCAL ADDRESS    FOREIGN ADDRESS
root    python2.7   1294    41  tcp4   127.0.0.1:61115  127.0.0.1:4506
'''

@skipIf(NO_MOCK, NO_MOCK_REASON)
class NetworkTestCase(TestCase):

    def test_interfaces_ifconfig_linux(self):
        interfaces = network._interfaces_ifconfig(LINUX)
        self.assertEqual(interfaces,
                         {'eth0': {'hwaddr': 'e0:3f:49:85:6a:af',
                                   'inet': [{'address': '10.10.10.56',
                                             'broadcast': '10.10.10.255',
                                             'netmask': '255.255.252.0'}],
                                   'inet6': [{'address': 'fe80::e23f:49ff:fe85:6aaf',
                                              'prefixlen': '64',
                                              'scope': 'link'}],
                                   'up': True},
                          'lo': {'inet': [{'address': '127.0.0.1',
                                           'netmask': '255.0.0.0'}],
                                 'inet6': [{'address': '::1',
                                            'prefixlen': '128',
                                            'scope': 'host'}],
                                 'up': True}}
        )

    def test_interfaces_ifconfig_freebsd(self):
        interfaces = network._interfaces_ifconfig(FREEBSD)
        self.assertEqual(interfaces,
                         {'': {'up': False},
                          'em0': {'hwaddr': '00:30:48:ff:ff:ff',
                                  'inet': [{'address': '10.10.10.250',
                                            'broadcast': '10.10.10.255',
                                            'netmask': '255.255.255.224'},
                                           {'address': '10.10.10.56',
                                            'broadcast': '10.10.10.63',
                                            'netmask': '255.255.255.192'}],
                                  'up': True},
                          'em1': {'hwaddr': '00:30:48:aa:aa:aa',
                                  'up': False},
                          'lo0': {'inet': [{'address': '127.0.0.1',
                                            'netmask': '255.0.0.0'}],
                                  'inet6': [{'address': 'fe80::1',
                                             'prefixlen': '64',
                                             'scope': '0x8'},
                                            {'address': '::1',
                                             'prefixlen': '128',
                                             'scope': None}],
                                  'up': True},
                          'plip0': {'up': False},
                          'tun0': {'inet': [{'address': '10.12.0.1',
                                             'netmask': '255.255.255.255'}],
                                   'up': True}}

        )

    def test_interfaces_ifconfig_solaris(self):
        with patch('salt.utils.is_sunos', lambda: True):
            interfaces = network._interfaces_ifconfig(SOLARIS)
            self.assertEqual(interfaces,
                             {'ilbext0': {'inet': [{'address': '10.10.11.11',
                                                    'broadcast': '10.10.11.31',
                                                    'netmask': '255.255.255.224'}],
                                          'inet6': [{'address': '::',
                                                     'prefixlen': '0'}],
                                          'up': True},
                              'ilbint0': {'inet': [{'address': '10.6.0.11',
                                                    'broadcast': '10.6.0.255',
                                                    'netmask': '255.255.255.0'}],
                                          'inet6': [{'address': '::',
                                                     'prefixlen': '0'}],
                                          'up': True},
                              'lo0': {'inet': [{'address': '127.0.0.1',
                                                'netmask': '255.0.0.0'}],
                                      'inet6': [{'address': '::1',
                                                 'prefixlen': '128'}],
                                      'up': True},
                              'net0': {'inet': [{'address': '10.10.10.38',
                                                 'broadcast': '10.10.10.63',
                                                 'netmask': '255.255.255.224'}],
                                       'inet6': [{'address': 'fe80::221:9bff:fefd:2a22',
                                                  'prefixlen': '10'}],
                                       'up': True},
                              'vpn0': {'inet': [{'address': '10.6.0.14',
                                                 'netmask': '255.0.0.0'}],
                                       'inet6': [{'address': '::',
                                                  'prefixlen': '0'}],
                                       'up': True}}
            )

    def test_freebsd_remotes_on(self):
        with patch('salt.utils.is_sunos', lambda: False):
            with patch('salt.utils.is_freebsd', lambda: True):
                with patch('subprocess.check_output',
                           return_value=FREEBSD_SOCKSTAT):
                    remotes = network._freebsd_remotes_on('4506', 'remote')
                    self.assertEqual(remotes, set(['127.0.0.1']))

if __name__ == '__main__':
    from integration import run_tests
    run_tests(NetworkTestCase, needs_daemon=False)
<commit_msg>Fixed _interfaces_ifconfig output for SunOS test<commit_after># -*- coding: utf-8 -*-
# Import Python libs
from __future__ import absolute_import

# Import Salt Testing libs
from salttesting import skipIf
from salttesting import TestCase
from salttesting.helpers import ensure_in_syspath
from salttesting.mock import NO_MOCK, NO_MOCK_REASON, patch
ensure_in_syspath('../../')

# Import salt libs
from salt.utils import network

LINUX = '''\
eth0      Link encap:Ethernet  HWaddr e0:3f:49:85:6a:af
          inet addr:10.10.10.56  Bcast:10.10.10.255  Mask:255.255.252.0
          inet6 addr: fe80::e23f:49ff:fe85:6aaf/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:643363 errors:0 dropped:0 overruns:0 frame:0
          TX packets:196539 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:386388355 (368.4 MiB)  TX bytes:25600939 (24.4 MiB)

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:548901 errors:0 dropped:0 overruns:0 frame:0
          TX packets:548901 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:613479895 (585.0 MiB)  TX bytes:613479895 (585.0 MiB)
'''

FREEBSD = '''
em0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
        options=4219b<RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,VLAN_HWCSUM,TSO4,WOL_MAGIC,VLAN_HWTSO>
        ether 00:30:48:ff:ff:ff
        inet 10.10.10.250 netmask 0xffffffe0 broadcast 10.10.10.255
        inet 10.10.10.56 netmask 0xffffffc0 broadcast 10.10.10.63
        media: Ethernet autoselect (1000baseT <full-duplex>)
        status: active
em1: flags=8c02<BROADCAST,OACTIVE,SIMPLEX,MULTICAST> metric 0 mtu 1500
        options=4219b<RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,VLAN_HWCSUM,TSO4,WOL_MAGIC,VLAN_HWTSO>
        ether 00:30:48:aa:aa:aa
        media: Ethernet autoselect
        status: no carrier
plip0: flags=8810<POINTOPOINT,SIMPLEX,MULTICAST> metric 0 mtu 1500
lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> metric 0 mtu 16384
        options=3<RXCSUM,TXCSUM>
        inet6 fe80::1%lo0 prefixlen 64 scopeid 0x8
        inet6 ::1 prefixlen 128
        inet 127.0.0.1 netmask 0xff000000
        nd6 options=3<PERFORMNUD,ACCEPT_RTADV>
tun0: flags=8051<UP,POINTOPOINT,RUNNING,MULTICAST> metric 0 mtu 1500
        options=80000<LINKSTATE>
        inet 10.12.0.1 --> 10.12.0.2 netmask 0xffffffff
        Opened by PID 1964
'''

SOLARIS = '''\
lo0: flags=2001000849<UP,LOOPBACK,RUNNING,MULTICAST,IPv4,VIRTUAL> mtu 8232 index 1
        inet 127.0.0.1 netmask ff000000
net0: flags=100001100943<UP,BROADCAST,RUNNING,PROMISC,MULTICAST,ROUTER,IPv4,PHYSRUNNING> mtu 1500 index 2
        inet 10.10.10.38 netmask ffffffe0 broadcast 10.10.10.63
ilbint0: flags=110001100843<UP,BROADCAST,RUNNING,MULTICAST,ROUTER,IPv4,VRRP,PHYSRUNNING> mtu 1500 index 3
        inet 10.6.0.11 netmask ffffff00 broadcast 10.6.0.255
ilbext0: flags=110001100843<UP,BROADCAST,RUNNING,MULTICAST,ROUTER,IPv4,VRRP,PHYSRUNNING> mtu 1500 index 4
        inet 10.10.11.11 netmask ffffffe0 broadcast 10.10.11.31
ilbext0:1: flags=110001100843<UP,BROADCAST,RUNNING,MULTICAST,ROUTER,IPv4,VRRP,PHYSRUNNING> mtu 1500 index 4
        inet 10.10.11.12 netmask ffffffe0 broadcast 10.10.11.31
vpn0: flags=1000011008d1<UP,POINTOPOINT,RUNNING,NOARP,MULTICAST,ROUTER,IPv4,PHYSRUNNING> mtu 1480 index 5
        inet tunnel src 10.10.11.12 tunnel dst 10.10.5.5
        tunnel hop limit 64
        inet 10.6.0.14 --> 10.6.0.15 netmask ff000000
lo0: flags=2002000849<UP,LOOPBACK,RUNNING,MULTICAST,IPv6,VIRTUAL> mtu 8252 index 1
        inet6 ::1/128
net0: flags=120002004941<UP,RUNNING,PROMISC,MULTICAST,DHCP,IPv6,PHYSRUNNING> mtu 1500 index 2
        inet6 fe80::221:9bff:fefd:2a22/10
ilbint0: flags=120002000840<RUNNING,MULTICAST,IPv6,PHYSRUNNING> mtu 1500 index 3
        inet6 ::/0
ilbext0: flags=120002000840<RUNNING,MULTICAST,IPv6,PHYSRUNNING> mtu 1500 index 4
        inet6 ::/0
vpn0: flags=120002200850<POINTOPOINT,RUNNING,MULTICAST,NONUD,IPv6,PHYSRUNNING> mtu 1480 index 5
        inet tunnel src 10.10.11.12 tunnel dst 10.10.5.5
        tunnel hop limit 64
        inet6 ::/0 --> fe80::b2d6:7c10
'''

FREEBSD_SOCKSTAT = '''\
USER    COMMAND     PID     FD  PROTO  LOCAL ADDRESS    FOREIGN ADDRESS
root    python2.7   1294    41  tcp4   127.0.0.1:61115  127.0.0.1:4506
'''

@skipIf(NO_MOCK, NO_MOCK_REASON)
class NetworkTestCase(TestCase):

    def test_interfaces_ifconfig_linux(self):
        interfaces = network._interfaces_ifconfig(LINUX)
        self.assertEqual(interfaces,
                         {'eth0': {'hwaddr': 'e0:3f:49:85:6a:af',
                                   'inet': [{'address': '10.10.10.56',
                                             'broadcast': '10.10.10.255',
                                             'netmask': '255.255.252.0'}],
                                   'inet6': [{'address': 'fe80::e23f:49ff:fe85:6aaf',
                                              'prefixlen': '64',
                                              'scope': 'link'}],
                                   'up': True},
                          'lo': {'inet': [{'address': '127.0.0.1',
                                           'netmask': '255.0.0.0'}],
                                 'inet6': [{'address': '::1',
                                            'prefixlen': '128',
                                            'scope': 'host'}],
                                 'up': True}}
        )

    def test_interfaces_ifconfig_freebsd(self):
        interfaces = network._interfaces_ifconfig(FREEBSD)
        self.assertEqual(interfaces,
                         {'': {'up': False},
                          'em0': {'hwaddr': '00:30:48:ff:ff:ff',
                                  'inet': [{'address': '10.10.10.250',
                                            'broadcast': '10.10.10.255',
                                            'netmask': '255.255.255.224'},
                                           {'address': '10.10.10.56',
                                            'broadcast': '10.10.10.63',
                                            'netmask': '255.255.255.192'}],
                                  'up': True},
                          'em1': {'hwaddr': '00:30:48:aa:aa:aa',
                                  'up': False},
                          'lo0': {'inet': [{'address': '127.0.0.1',
                                            'netmask': '255.0.0.0'}],
                                  'inet6': [{'address': 'fe80::1',
                                             'prefixlen': '64',
                                             'scope': '0x8'},
                                            {'address': '::1',
                                             'prefixlen': '128',
                                             'scope': None}],
                                  'up': True},
                          'plip0': {'up': False},
                          'tun0': {'inet': [{'address': '10.12.0.1',
                                             'netmask': '255.255.255.255'}],
                                   'up': True}}

        )

    def test_interfaces_ifconfig_solaris(self):
        with patch('salt.utils.is_sunos', lambda: True):
            interfaces = network._interfaces_ifconfig(SOLARIS)
            self.assertEqual(interfaces,
                             {'ilbext0': {'inet': [{'address': '10.10.11.11',
                                                    'broadcast': '10.10.11.31',
                                                    'netmask': '255.255.255.224'},
                                                    {'address': '10.10.11.12',
                                                    'broadcast': '10.10.11.31',
                                                    'netmask': '255.255.255.224'}],
                                          'inet6': [],
                                          'up': True},
                              'ilbint0': {'inet': [{'address': '10.6.0.11',
                                                    'broadcast': '10.6.0.255',
                                                    'netmask': '255.255.255.0'}],
                                          'inet6': [],
                                          'up': True},
                              'lo0': {'inet': [{'address': '127.0.0.1',
                                                'netmask': '255.0.0.0'}],
                                      'inet6': [{'address': '::1',
                                                 'prefixlen': '128'}],
                                      'up': True},
                              'net0': {'inet': [{'address': '10.10.10.38',
                                                 'broadcast': '10.10.10.63',
                                                 'netmask': '255.255.255.224'}],
                                       'inet6': [{'address': 'fe80::221:9bff:fefd:2a22',
                                                  'prefixlen': '10'}],
                                       'up': True},
                              'vpn0': {'inet': [{'address': '10.6.0.14',
                                                 'netmask': '255.0.0.0'}],
                                       'inet6': [],
                                       'up': True}}
            )

    def test_freebsd_remotes_on(self):
        with patch('salt.utils.is_sunos', lambda: False):
            with patch('salt.utils.is_freebsd', lambda: True):
                with patch('subprocess.check_output',
                           return_value=FREEBSD_SOCKSTAT):
                    remotes = network._freebsd_remotes_on('4506', 'remote')
                    self.assertEqual(remotes, set(['127.0.0.1']))

if __name__ == '__main__':
    from integration import run_tests
    run_tests(NetworkTestCase, needs_daemon=False)
<|endoftext|>


<commit_before>import logging, argparse, os, sys, re
import numpy as np
from collections import OrderedDict
from .utils import getWorkDirs, checkSymLink
from ..ccsgp.ccsgp import make_panel
from ..ccsgp.utils import getOpts
from ..ccsgp.config import default_colors

def gp_panel(version):
  """example for a panel plot using QM12 data (see gp_xfac)

  .. image:: pics/panelQM12.png
     :width: 700 px

  :param version: plot version / input subdir name
  :type version: str
  """
  inDir, outDir = getWorkDirs()
  inDir = os.path.join(inDir, version)
  data = {}
  for file in os.listdir(inDir):
    energy = re.compile('\d+').search(file).group()
    data_type = re.sub('%s\.dat' % energy, '', file)
    file_url = os.path.join(inDir, file)
    data_import = np.loadtxt(open(file_url, 'rb'))
    if energy not in data: data[energy] = [ data_import ]
    else: data[energy].append(data_import)
  make_panel(
    dpt_dict = OrderedDict(
      (' '.join([k, 'GeV']), [
        data[k], [
          'with filledcurves lt 1 lw 4 pt 0 lc %s' % default_colors[8],
          'with lines lc 0 lw 5 lt 1',
          'lt 1 lw 4 ps 1.5 lc %s pt 18' % default_colors[0]
        ], [ '+medium', 'cocktail', 'data' ]
      ]) for k in sorted(data, key=int)
    ), # 'lc 0' works here because no error plotting necessary
    name = os.path.join(outDir, 'panel%s' % version),
    ylabel = 'dielectron pair production rate',
    xlabel = 'dielectron mass (GeV/c^{2})',
    ylog = True, xr = [0, 1.1], yr = [1e-4, 20],
    lmargin = 0.08, bmargin = 0.15,
    gpcalls = ['mxtics 2']
  )
  return 'done'

if __name__ == '__main__':
  checkSymLink()
  parser = argparse.ArgumentParser()
  parser.add_argument("version", help="version = subdir name of input dir")
  parser.add_argument("--log", help="show log output", action="store_true")
  args = parser.parse_args()
  loglevel = 'DEBUG' if args.log else 'WARNING'
  logging.basicConfig(
    format='%(message)s', level=getattr(logging, loglevel)
  )
  print gp_panel(args.version)
<commit_msg>gp_panel: fix cocktail error band<commit_after>import logging, argparse, os, sys, re
import numpy as np
from collections import OrderedDict
from .utils import getWorkDirs, checkSymLink
from ..ccsgp.ccsgp import make_panel
from ..ccsgp.utils import getOpts
from ..ccsgp.config import default_colors

def gp_panel(version):
  """example for a panel plot using QM12 data (see gp_xfac)

  .. image:: pics/panelQM12.png
     :width: 700 px

  :param version: plot version / input subdir name
  :type version: str
  """
  inDir, outDir = getWorkDirs()
  inDir = os.path.join(inDir, version)
  data = {}
  for file in os.listdir(inDir):
    energy = re.compile('\d+').search(file).group()
    data_type = re.sub('%s\.dat' % energy, '', file)
    file_url = os.path.join(inDir, file)
    data_import = np.loadtxt(open(file_url, 'rb'))
    if data_type == 'cocktail': data_import[:, 4] *= 0.
    if energy not in data: data[energy] = [ data_import ]
    else: data[energy].append(data_import)
  make_panel(
    dpt_dict = OrderedDict(
      (' '.join([k, 'GeV']), [
        data[k], [
          'with filledcurves lt 1 lw 4 pt 0 lc %s' % default_colors[8],
          'with lines lc 0 lw 5 lt 1',
          'lt 1 lw 4 ps 1.5 lc %s pt 18' % default_colors[0]
        ], [ '+medium', 'cocktail', 'data' ]
      ]) for k in sorted(data, key=int)
    ), # 'lc 0' works here because no error plotting necessary
    name = os.path.join(outDir, 'panel%s' % version),
    ylabel = 'dielectron pair production rate',
    xlabel = 'dielectron mass (GeV/c^{2})',
    ylog = True, xr = [0, 1.1], yr = [1e-4, 20],
    lmargin = 0.08, bmargin = 0.15,
    gpcalls = ['mxtics 2']
  )
  return 'done'

if __name__ == '__main__':
  checkSymLink()
  parser = argparse.ArgumentParser()
  parser.add_argument("version", help="version = subdir name of input dir")
  parser.add_argument("--log", help="show log output", action="store_true")
  args = parser.parse_args()
  loglevel = 'DEBUG' if args.log else 'WARNING'
  logging.basicConfig(
    format='%(message)s', level=getattr(logging, loglevel)
  )
  print gp_panel(args.version)
<|endoftext|>


<commit_before>#!/usr/bin/env python

import json

import cloudfeaster.spider
import importlib
import logging
import optparse
import os
import pip
import pkgutil
import time

_logger = logging.getLogger(__name__)

class CommandLineParser(optparse.OptionParser):

    def __init__(self):
        description = (
            "Utility to discover all spiders and thier associated metadata."
        )
        optparse.OptionParser.__init__(
            self,
            "usage: %prog [options] <package>",
            description=description)

    def parse_args(self, *args, **kwargs):
        (clo, cla) = optparse.OptionParser.parse_args(self, *args, **kwargs)
        if 0 != len(cla):
            self.error("try again ...")
        return (clo, cla)

if __name__ == "__main__":
    #
    # parse the command line ...
    #
    clp = CommandLineParser()
    (clo, cla) = clp.parse_args()

    #
    # configure logging ...
    #
    # remember gmt = utc
    logging.Formatter.converter = time.gmtime
    logging.basicConfig(
        level=logging.INFO,
        datefmt="%Y-%m-%dT%H:%M:%S",
        format="%(asctime)s.%(msecs)03d+00:00 %(process)d "
        "%(levelname)5s %(module)s:%(lineno)d %(message)s")

    #
    # Run the spider and dump results to stdout
    #
    spiders = {}
    for i in pip.get_installed_distributions():
        if not i.key.endswith("-spiders"):
            continue

        spider_package_name = i.egg_name()[:-len("-%s-py%s" % (i.version, i.py_version))]

        spider_package = importlib.import_module(spider_package_name)

        spider_package_dir_name = os.path.dirname(spider_package.__file__)

        for (module_loader, name, ispkg) in pkgutil.iter_modules([spider_package_dir_name]):
            importlib.import_module(spider_package_name + "." + name)

    for spider_class in cloudfeaster.spider.Spider.__subclasses__():
        full_spider_name = spider_class.__module__ + "." + spider_class.__name__
        spiders[full_spider_name] = spider_class.get_validated_metadata()

    print json.dumps(spiders)
<commit_msg>improve spiders.py egg name parsing<commit_after>#!/usr/bin/env python

import json

import cloudfeaster.spider
import importlib
import logging
import optparse
import os
import pip
import pkgutil
import re
import time

_logger = logging.getLogger(__name__)

#
# egg_name_reg_ex is used to extract module names from egg_names
# like ```gaming_spiders-0.1.0-py2.7```.
#
_egg_name_reg_ex = re.compile(
    "^\s*(?P<egg_name>.+spiders)-\d+\.\d+\.\d+\-py\d+\.\d+\s*$",
    re.IGNORECASE)

class CommandLineParser(optparse.OptionParser):

    def __init__(self):
        description = (
            "Utility to discover all spiders and thier associated metadata."
        )
        optparse.OptionParser.__init__(
            self,
            "usage: %prog [options] <package>",
            description=description)

    def parse_args(self, *args, **kwargs):
        (clo, cla) = optparse.OptionParser.parse_args(self, *args, **kwargs)
        if 0 != len(cla):
            self.error("try again ...")
        return (clo, cla)

if __name__ == "__main__":
    #
    # parse the command line ...
    #
    clp = CommandLineParser()
    (clo, cla) = clp.parse_args()

    #
    # configure logging ...
    #
    # remember gmt = utc
    logging.Formatter.converter = time.gmtime
    logging.basicConfig(
        level=logging.INFO,
        datefmt="%Y-%m-%dT%H:%M:%S",
        format="%(asctime)s.%(msecs)03d+00:00 %(process)d "
        "%(levelname)5s %(module)s:%(lineno)d %(message)s")

    #
    # Run the spider and dump results to stdout
    #
    spiders = {}
    for i in pip.get_installed_distributions():
        match = _egg_name_reg_ex.match(i.egg_name())
        if not match:
            continue

        spider_package_name = match.group("egg_name")

        spider_package = importlib.import_module(spider_package_name)

        spider_package_dir_name = os.path.dirname(spider_package.__file__)

        for (module_loader, name, ispkg) in pkgutil.iter_modules([spider_package_dir_name]):
            importlib.import_module(spider_package_name + "." + name)

    for spider_class in cloudfeaster.spider.Spider.__subclasses__():
        full_spider_name = spider_class.__module__ + "." + spider_class.__name__
        spiders[full_spider_name] = spider_class.get_validated_metadata()

    print json.dumps(spiders)
<|endoftext|>


<commit_before># Copyright Hybrid Logic Ltd.  See LICENSE file for details.

"""
Sphinx extension to add a ``task`` directive

This directive allows sharing code between documentation and provisioning code.

.. code-block:: rest

   .. task:: name_of_task

``name_of_task`` must the name of a task in ``flocker.provision._tasks``,
without the ``task_`` prefix. A task must take a single runner argument.
"""

from inspect import getsourcefile
from docutils.parsers.rst import Directive
from docutils import nodes
from docutils.statemachine import StringList

from flocker import __version__ as version

from flocker.docs import get_installable_version
from flocker.docs.version_extensions import PLACEHOLDER

from . import _tasks as tasks
from ._install import Run, Sudo, Comment, Put

def run(command):
    return command.command

def sudo(command):
    return "sudo %s" % (command.command,)

def comment(command):
    return "# %s" % (command.comment)

def put(command):
    return [
        "cat <<EOF > %s" % (command.path,),
    ] + command.content.splitlines() + [
        "EOF",
    ]

HANDLERS = {
    Run: run,
    Sudo: sudo,
    Comment: comment,
    Put: put,
}

class TaskDirective(Directive):
    """
    Implementation of the C{task} directive.
    """
    required_arguments = 1
    optional_arguments = 1
    final_argument_whitespace = True

    option_spec = {
        'prompt': str
    }

    def run(self):
        task = getattr(tasks, 'task_%s' % (self.arguments[0],))
        prompt = self.options.get('prompt', '$')
        if len(self.arguments) > 1:
            latest = get_installable_version(version)
            task_arguments = [item.replace(PLACEHOLDER, latest) for
                              item in self.arguments[1].split()]
        else:
            task_arguments = []

        commands = task(*task_arguments)
        lines = ['.. prompt:: bash %s,> auto' % (prompt,), '']

        for command in commands:
            try:
                handler = HANDLERS[type(command)]
            except KeyError:
                raise self.error("task: %s not supported"
                                 % (type(command).__name__,))
            # handler can return either a string or a list.  If it returns a
            # list, treat the elements after the first as continuation lines.
            command_line = handler(command)
            if isinstance(command_line, list):
                lines.append('   %s %s' % (prompt, command_line[0],))
                lines.extend(['   > %s' % (line,)
                              for line in command_line[1:]])
            else:
                lines.append('   %s %s' % (prompt, command_line,))

        # The following three lines record (some?) of the dependencies of the
        # directive, so automatic regeneration happens.  Specifically, it
        # records this file, and the file where the task is declared.
        task_file = getsourcefile(task)
        tasks_file = getsourcefile(tasks)
        self.state.document.settings.record_dependencies.add(task_file)
        self.state.document.settings.record_dependencies.add(tasks_file)
        self.state.document.settings.record_dependencies.add(__file__)

        node = nodes.Element()
        text = StringList(lines)
        self.state.nested_parse(text, self.content_offset, node)
        return node.children

def setup(app):
    """
    Entry point for sphinx extension.
    """
    app.add_directive('task', TaskDirective)
<commit_msg>Comment about replacing latest version<commit_after># Copyright Hybrid Logic Ltd.  See LICENSE file for details.

"""
Sphinx extension to add a ``task`` directive

This directive allows sharing code between documentation and provisioning code.

.. code-block:: rest

   .. task:: name_of_task

``name_of_task`` must the name of a task in ``flocker.provision._tasks``,
without the ``task_`` prefix. A task must take a single runner argument.
"""

from inspect import getsourcefile
from docutils.parsers.rst import Directive
from docutils import nodes
from docutils.statemachine import StringList

from flocker import __version__ as version

from flocker.docs import get_installable_version
from flocker.docs.version_extensions import PLACEHOLDER

from . import _tasks as tasks
from ._install import Run, Sudo, Comment, Put

def run(command):
    return command.command

def sudo(command):
    return "sudo %s" % (command.command,)

def comment(command):
    return "# %s" % (command.comment)

def put(command):
    return [
        "cat <<EOF > %s" % (command.path,),
    ] + command.content.splitlines() + [
        "EOF",
    ]

HANDLERS = {
    Run: run,
    Sudo: sudo,
    Comment: comment,
    Put: put,
}

class TaskDirective(Directive):
    """
    Implementation of the C{task} directive.
    """
    required_arguments = 1
    optional_arguments = 1
    final_argument_whitespace = True

    option_spec = {
        'prompt': str
    }

    def run(self):
        task = getattr(tasks, 'task_%s' % (self.arguments[0],))
        prompt = self.options.get('prompt', '$')
        if len(self.arguments) > 1:
            # Some tasks can include the latest installable version as (part
            # of) an argument. This replaces a placeholder with that version.
            latest = get_installable_version(version)
            task_arguments = [item.replace(PLACEHOLDER, latest) for
                              item in self.arguments[1].split()]
        else:
            task_arguments = []

        commands = task(*task_arguments)
        lines = ['.. prompt:: bash %s,> auto' % (prompt,), '']

        for command in commands:
            try:
                handler = HANDLERS[type(command)]
            except KeyError:
                raise self.error("task: %s not supported"
                                 % (type(command).__name__,))
            # handler can return either a string or a list.  If it returns a
            # list, treat the elements after the first as continuation lines.
            command_line = handler(command)
            if isinstance(command_line, list):
                lines.append('   %s %s' % (prompt, command_line[0],))
                lines.extend(['   > %s' % (line,)
                              for line in command_line[1:]])
            else:
                lines.append('   %s %s' % (prompt, command_line,))

        # The following three lines record (some?) of the dependencies of the
        # directive, so automatic regeneration happens.  Specifically, it
        # records this file, and the file where the task is declared.
        task_file = getsourcefile(task)
        tasks_file = getsourcefile(tasks)
        self.state.document.settings.record_dependencies.add(task_file)
        self.state.document.settings.record_dependencies.add(tasks_file)
        self.state.document.settings.record_dependencies.add(__file__)

        node = nodes.Element()
        text = StringList(lines)
        self.state.nested_parse(text, self.content_offset, node)
        return node.children

def setup(app):
    """
    Entry point for sphinx extension.
    """
    app.add_directive('task', TaskDirective)
<|endoftext|>


<commit_before>import logging, argparse, os, sys, re
import numpy as np
from fnmatch import fnmatch
from collections import OrderedDict
from .utils import getWorkDirs, checkSymLink
from ..ccsgp.ccsgp import make_plot
from ..ccsgp.utils import getOpts
from ..ccsgp.config import default_colors

shift = { '200': 200., '62': 15., '39': 0.5, '19': 0.01 }
cocktail_style = 'with filledcurves pt 0 lc %s lw 5 lt 1' % default_colors[8]
pseudo_point = np.array([ [-1,1e-7,0,0,1] ])

def gp_stack(version):
  """example for a plot w/ stacked graphs using QM12 data (see gp_panel)

  * how to omit keys from the legend
  * manually add legend entries
  * automatically plot arrows for error bars larger than data point value

  .. image:: pics/stackQM12.png
     :width: 550px

  :param version: plot version / input subdir name
  :type version: str
  """
  inDir, outDir = getWorkDirs()
  inDir = os.path.join(inDir, version)
  data, cocktail = OrderedDict(), OrderedDict()
  for file in os.listdir(inDir):
    energy = re.compile('\d+').search(file).group()
    data_type = re.sub('%s\.dat' % energy, '', file)
    file_url = os.path.join(inDir, file)
    data_import = np.loadtxt(open(file_url, 'rb'))
    # following scaling is wrong for y < 0 && shift != 1
    data_import[:,(1,3,4)] *= shift[energy]
    if fnmatch(file, 'data*'):
      data[energy] = data_import
    else:
      data_import[:,2] = 0 # don't plot dx for cocktail
      if energy == '19' and version == 'QM12':
        # cut of cocktail above 1.1 GeV/c^2
        cocktail[energy] = data_import[data_import[:,0] < 1.3]
      else:
        cocktail[energy] = data_import
  dataOrdered = OrderedDict(
    (' '.join([k, 'GeV', '{/Symbol \264} %g' % shift[k]]), data[k])
    for k in sorted(data, key=int)
  )
  nSetsData, nSetsCocktail = len(dataOrdered), len(cocktail)
  make_plot(
    data = cocktail.values() + [ pseudo_point ] + dataOrdered.values(),
    properties = [ cocktail_style ] * (nSetsCocktail+1) + [
      'lt 1 lw 4 ps 1.5 lc %s pt 18' % default_colors[i]
      for i in xrange(nSetsData)
    ],
    titles = [''] * nSetsCocktail + ['Cocktail w/o {/Symbol \162}'] + dataOrdered.keys(),
    name = os.path.join(outDir, 'stack%s' % version),
    ylabel = 'dielectron pair production rate',
    xlabel = 'dielectron mass (GeV/c^{2})',
    ylog = True, xr = [0, 3.5], yr = [3e-7 if version == 'QM12' else 1e-8, 2e3],
    lmargin = 0.07, key = ['width -3', 'at graph 0.85,0.98'],
    #arrows = [ # example arrow
    #  [ [2.4, 5e-5], [2.3, 1e-5], 'head filled lc 1 lw 5 lt 1 front' ],
    #],
  )
  return 'done'

if __name__ == '__main__':
  checkSymLink()
  parser = argparse.ArgumentParser()
  parser.add_argument("version", help="version = subdir name of input dir")
  parser.add_argument("--log", help="show log output", action="store_true")
  args = parser.parse_args()
  loglevel = 'DEBUG' if args.log else 'WARNING'
  logging.basicConfig(
    format='%(message)s', level=getattr(logging, loglevel)
  )
  print gp_stack(args.version)
<commit_msg>gp_stack: dont plot dy, set arrow_offset<commit_after>import logging, argparse, os, sys, re
import numpy as np
from fnmatch import fnmatch
from collections import OrderedDict
from .utils import getWorkDirs, checkSymLink
from ..ccsgp.ccsgp import make_plot
from ..ccsgp.utils import getOpts
from ..ccsgp.config import default_colors

shift = { '200': 200., '62': 15., '39': 0.5, '19': 0.01 }
cocktail_style = 'with filledcurves pt 0 lc %s lw 5 lt 1' % default_colors[8]
pseudo_point = np.array([ [-1,1e-7,0,0,1] ])

def gp_stack(version):
  """example for a plot w/ stacked graphs using QM12 data (see gp_panel)

  * how to omit keys from the legend
  * manually add legend entries
  * automatically plot arrows for error bars larger than data point value

  .. image:: pics/stackQM12.png
     :width: 550px

  :param version: plot version / input subdir name
  :type version: str
  """
  inDir, outDir = getWorkDirs()
  inDir = os.path.join(inDir, version)
  data, cocktail = OrderedDict(), OrderedDict()
  for file in os.listdir(inDir):
    energy = re.compile('\d+').search(file).group()
    data_type = re.sub('%s\.dat' % energy, '', file)
    file_url = os.path.join(inDir, file)
    data_import = np.loadtxt(open(file_url, 'rb'))
    # following scaling is wrong for y < 0 && shift != 1
    data_import[:,(1,3,4)] *= shift[energy]
    if fnmatch(file, 'data*'):
      data[energy] = data_import
    else:
      data_import[:,(2,3)] = 0 # don't plot dx,dy for cocktail
      if energy == '19' and version == 'QM12':
        # cut of cocktail above 1.1 GeV/c^2
        cocktail[energy] = data_import[data_import[:,0] < 1.3]
      else:
        cocktail[energy] = data_import
  dataOrdered = OrderedDict(
    (' '.join([k, 'GeV', '{/Symbol \264} %g' % shift[k]]), data[k])
    for k in sorted(data, key=int)
  )
  nSetsData, nSetsCocktail = len(dataOrdered), len(cocktail)
  make_plot(
    data = cocktail.values() + [ pseudo_point ] + dataOrdered.values(),
    properties = [ cocktail_style ] * (nSetsCocktail+1) + [
      'lt 1 lw 4 ps 1.5 lc %s pt 18' % default_colors[i]
      for i in xrange(nSetsData)
    ],
    titles = [''] * nSetsCocktail + ['Cocktail w/o {/Symbol \162}'] + dataOrdered.keys(),
    name = os.path.join(outDir, 'stack%s' % version),
    ylabel = 'dielectron pair production rate',
    xlabel = 'dielectron mass (GeV/c^{2})',
    ylog = True, xr = [0, 3.5], yr = [3e-7 if version == 'QM12' else 1e-8, 2e3],
    lmargin = 0.07, key = ['width -3', 'at graph 0.85,0.98'],
    arrow_offset = 0.8,
    #arrows = [ # example arrow
    #  [ [2.4, 5e-5], [2.3, 1e-5], 'head filled lc 1 lw 5 lt 1 front' ],
    #],
  )
  return 'done'

if __name__ == '__main__':
  checkSymLink()
  parser = argparse.ArgumentParser()
  parser.add_argument("version", help="version = subdir name of input dir")
  parser.add_argument("--log", help="show log output", action="store_true")
  args = parser.parse_args()
  loglevel = 'DEBUG' if args.log else 'WARNING'
  logging.basicConfig(
    format='%(message)s', level=getattr(logging, loglevel)
  )
  print gp_stack(args.version)
<|endoftext|>