<commit_before># Copyright 2015-2017 F-Secure

# Licensed under the Apache License, Version 2.0 (the "License"); you
# may not use this file except in compliance with the License.  You may
# obtain a copy of the License at

#     http://www.apache.org/licenses/LICENSE-2.0

# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.  See the License for the specific language governing
# permissions and limitations under the License.

from traceback import print_exc
from threading import RLock, Thread
from collections import defaultdict, namedtuple

from see.events import Event

class Observatory(object):
    """
    Base class for observers and observables.
    """
    def __init__(self, identifier):
        self._identifier = identifier

    @property
    def identifier(self):
        return self._identifier

class Observer(Observatory):
    """The observer is the entity listening for events.

    Through the Context attribute it can subscribe/unsubscribe its own handlers
    to the given Events.
    """
    def __init__(self, identifier, context):
        super(Observer, self).__init__(identifier)
        self._context = context

    @property
    def context(self):
        return self._context

class Observable(Observatory):
    def __init__(self, identifier):
        super(Observable, self).__init__(identifier)
        self._handlers = Handlers(defaultdict(list), defaultdict(list), RLock())

    def subscribe(self, event, handler):
        """
        Subscribes a Handler for the given Event.

        @param event: (str|see.Event) event to react to.
        @param handler: (callable) function or method to subscribe.
        """
        self._handlers.sync_handlers[event].append(handler)

    def subscribe_async(self, event, handler):
        """
        Subscribes an asynchronous Handler for the given Event.

        An asynchronous handler is executed concurrently to the others
        without blocking the Events flow.

        @param event: (str|see.Event) event to react to.
        @param handler: (callable) function or method to subscribe.
        """
        self._handlers.async_handlers[event].append(handler)

    def unsubscribe(self, event, handler):
        """
        Unsubscribes the Handler from the given Event.
        Both synchronous and asynchronous handlers are removed.

        @param event: (str|see.Event) event to which the handler is subscribed.
        @param handler: (callable) function or method to unsubscribe.
        """
        try:
            self._handlers.sync_handlers[event].remove(handler)
        except ValueError:
            self._handlers.async_handlers[event].remove(handler)
        else:
            try:
                self._handlers.async_handlers[event].remove(handler)
            except ValueError:
                pass

    def trigger(self, event, **kwargs):
        """
        Triggers an event.

        All subscribed handlers will be executed, asynchronous ones
        won't block this call.

        @param event: (str|see.Event) event intended to be raised.
        """
        with self._handlers.trigger_mutex:
            event = prime_event(event, self.__class__.__name__, **kwargs)

            for handler in self._handlers.async_handlers[event]:
                asynchronous(handler, event)
            for handler in self._handlers.sync_handlers[event]:
                synchronous(handler, event)

Handlers = namedtuple('Handlers', ('sync_handlers',
                                   'async_handlers',
                                   'trigger_mutex'))

def prime_event(event, source, **kwargs):
    """
    Returns the event ready to be triggered.

    If the given event is a string an Event instance is generated from it.
    """
    if not isinstance(event, Event):
        event = Event(event, source=source, **kwargs)

    return event

def asynchronous(function, *args, **kwargs):
    """
    Runs the function asynchronously taking care of exceptions.
    """
    thread = Thread(target=function, args=args, kwargs=kwargs)
    thread.daemon = True
    thread.start()

def synchronous(function, *args, **kwargs):
    """
    Runs the function synchronously taking care of exceptions.
    """
    try:
        function(*args, **kwargs)
    except Exception:
        print_exc()
<commit_msg>observer: use logging to log Hook handler errors<commit_after># Copyright 2015-2017 F-Secure

# Licensed under the Apache License, Version 2.0 (the "License"); you
# may not use this file except in compliance with the License.  You may
# obtain a copy of the License at

#     http://www.apache.org/licenses/LICENSE-2.0

# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.  See the License for the specific language governing
# permissions and limitations under the License.

import logging
from threading import RLock, Thread
from collections import defaultdict, namedtuple

from see.events import Event

class Observatory(object):
    """
    Base class for observers and observables.
    """
    def __init__(self, identifier):
        self._identifier = identifier

    @property
    def identifier(self):
        return self._identifier

class Observer(Observatory):
    """The observer is the entity listening for events.

    Through the Context attribute it can subscribe/unsubscribe its own handlers
    to the given Events.
    """
    def __init__(self, identifier, context):
        super(Observer, self).__init__(identifier)
        self._context = context

    @property
    def context(self):
        return self._context

class Observable(Observatory):
    def __init__(self, identifier):
        super(Observable, self).__init__(identifier)
        self._handlers = Handlers(defaultdict(list), defaultdict(list), RLock())

    def subscribe(self, event, handler):
        """
        Subscribes a Handler for the given Event.

        @param event: (str|see.Event) event to react to.
        @param handler: (callable) function or method to subscribe.
        """
        self._handlers.sync_handlers[event].append(handler)

    def subscribe_async(self, event, handler):
        """
        Subscribes an asynchronous Handler for the given Event.

        An asynchronous handler is executed concurrently to the others
        without blocking the Events flow.

        @param event: (str|see.Event) event to react to.
        @param handler: (callable) function or method to subscribe.
        """
        self._handlers.async_handlers[event].append(handler)

    def unsubscribe(self, event, handler):
        """
        Unsubscribes the Handler from the given Event.
        Both synchronous and asynchronous handlers are removed.

        @param event: (str|see.Event) event to which the handler is subscribed.
        @param handler: (callable) function or method to unsubscribe.
        """
        try:
            self._handlers.sync_handlers[event].remove(handler)
        except ValueError:
            self._handlers.async_handlers[event].remove(handler)
        else:
            try:
                self._handlers.async_handlers[event].remove(handler)
            except ValueError:
                pass

    def trigger(self, event, **kwargs):
        """
        Triggers an event.

        All subscribed handlers will be executed, asynchronous ones
        won't block this call.

        @param event: (str|see.Event) event intended to be raised.
        """
        with self._handlers.trigger_mutex:
            event = prime_event(event, self.__class__.__name__, **kwargs)

            for handler in self._handlers.async_handlers[event]:
                asynchronous(handler, event)
            for handler in self._handlers.sync_handlers[event]:
                synchronous(handler, event)

Handlers = namedtuple('Handlers', ('sync_handlers',
                                   'async_handlers',
                                   'trigger_mutex'))

def prime_event(event, source, **kwargs):
    """
    Returns the event ready to be triggered.

    If the given event is a string an Event instance is generated from it.
    """
    if not isinstance(event, Event):
        event = Event(event, source=source, **kwargs)

    return event

def asynchronous(function, event):
    """
    Runs the function asynchronously taking care of exceptions.
    """
    thread = Thread(target=synchronous, args=(function, event))
    thread.daemon = True
    thread.start()

def synchronous(function, event):
    """
    Runs the function synchronously taking care of exceptions.
    """
    try:
        function(event)
    except Exception as error:
        logger = get_function_logger(function)
        logger.exception(error)

def get_function_logger(function):
    if hasattr(function, '__self__'):
        return logging.getLogger(
            "%s.%s" % (function.__module__,
                       function.__self__.__class__.__name__))
    else:
        return logging.getLogger(function.__module__)
<|endoftext|>


<commit_before>from devicehive.transports.transport import Transport
from devicehive.transports.transport import TransportError
import requests
import threading
import sys

class HttpTransport(Transport):
    """Http transport class."""

    RESPONSE_SUCCESS_STATUS = 'success'
    RESPONSE_ERROR_STATUS = 'error'
    RESPONSE_STATUS_KEY = 'status'
    RESPONSE_CODE_KEY = 'code'
    RESPONSE_ERROR_KEY = 'error'
    RESPONSE_SUBSCRIBE_ID_KEY = 'subscriptionId'

    def __init__(self, data_format_class, data_format_options, handler_class,
                 handler_options):
        Transport.__init__(self, 'http', HttpTransportError, data_format_class,
                           data_format_options, handler_class, handler_options)
        self._url = None
        self._options = None
        self._events_queue = []
        self._subscribe_threads = {}
        self._success_codes = [200, 201, 204]

    def _connect(self, url, **options):
        self._url = url
        self._options = options
        if not self._url.endswith('/'):
            self._url += '/'
        self._connected = True
        self._handle_connect()

    def _receive(self):
        while self._connected and not self._exception_info:
            if not self._events_queue:
                continue
            for event in self._events_queue.pop(0):
                self._handle_event(event)
                if not self._connected:
                    return

    def _disconnect(self):
        self._events_queue = []
        self._subscribe_threads = {}
        self._handle_disconnect()

    def _request_call(self, method, url, **params):
        options = self._options.copy()
        options.update(params)
        try:
            response = requests.request(method, url, **options)
            code = response.status_code
            if self._text_data_type:
                return code, response.text
            return code, response.content
        except requests.RequestException as http_error:
            error = http_error
        raise self._error(error)

    def _request(self, action, request, **params):
        method = params.pop('method', 'GET')
        url = self._url + params.pop('url')
        request_delete_keys = params.pop('request_delete_keys', [])
        request_key = params.pop('request_key', None)
        response_key = params.pop('response_key', None)
        for request_delete_key in request_delete_keys:
            del request[request_delete_key]
        if request:
            if request_key:
                request = request[request_key]
            params['data'] = self._encode(request)
        code, data = self._request_call(method, url, **params)
        response = {self.REQUEST_ID_KEY: self._uuid(),
                    self.REQUEST_ACTION_KEY: action}
        if code in self._success_codes:
            response[self.RESPONSE_STATUS_KEY] = self.RESPONSE_SUCCESS_STATUS
            if not data:
                return response
            if response_key:
                response[response_key] = self._decode(data)
                return response
            response.update(self._decode(data))
            return response
        response[self.RESPONSE_STATUS_KEY] = self.RESPONSE_ERROR_STATUS
        response[self.RESPONSE_CODE_KEY] = code
        if not data:
            return response
        try:
            error = self._decode(data)['message']
        except Exception:
            error = data
        response[self.RESPONSE_ERROR_KEY] = error
        return response

    def _subscribe_requests(self, action, subscribe_requests):
        subscribe_id = self._uuid()
        subscribe_threads = []
        for action, request, params in subscribe_requests:
            name = '%s-transport-subscribe-%s-%s'
            subscribe_thread_name = name % (self._name, subscribe_id,
                                            len(subscribe_threads))
            subscribe_thread = threading.Thread(target=self._subscribe,
                                                args=(subscribe_id, action,
                                                      request, params))
            subscribe_thread.daemon = True
            subscribe_thread.name = subscribe_thread_name
            subscribe_thread.start()
            subscribe_threads.append(subscribe_thread)
        self._subscribe_threads[subscribe_id] = subscribe_threads
        return {self.REQUEST_ID_KEY: self._uuid(),
                self.REQUEST_ACTION_KEY: action,
                self.RESPONSE_STATUS_KEY: self.RESPONSE_SUCCESS_STATUS,
                self.RESPONSE_SUBSCRIBE_ID_KEY: subscribe_id}

    def _subscribe(self, subscribe_id, action, request, params):
        response_key = params['response_key']
        params_timestamp_key = params.pop('params_timestamp_key', 'timestamp')
        response_timestamp_key = params.pop('response_timestamp_key',
                                            'timestamp')
        while self._connected and not self._exception_info:
            try:
                response = self._request(action, request.copy(), **params)
                response_status = response[self.RESPONSE_STATUS_KEY]
                if response_status != self.RESPONSE_SUCCESS_STATUS:
                    # TODO: handle error response.
                    return
                events = response[response_key]
                if not len(events):
                    continue
                timestamp = events[-1][response_timestamp_key]
                if not params.get('params'):
                    params['params'] = {}
                params['params'][params_timestamp_key] = timestamp
                events = [{self.REQUEST_ACTION_KEY: action,
                           response_key: event,
                           self.RESPONSE_SUBSCRIBE_ID_KEY: subscribe_id}
                          for event in events]
                self._events_queue.append(events)
            except BaseException:
                self._exception_info = sys.exc_info()

    def send_request(self, action, request, **params):
        # TODO: add unsubscribe.
        self._ensure_connected()
        subscribe_requests = params.pop('subscribe_requests', [])
        if subscribe_requests:
            response = self._subscribe_requests(action, subscribe_requests)
            self._events_queue.append([response])
            return response[self.REQUEST_ID_KEY]
        response = self._request(action, request, **params)
        self._events_queue.append([response])
        return response[self.REQUEST_ID_KEY]

    def request(self, action, request, **params):
        # TODO: add unsubscribe.
        self._ensure_connected()
        subscribe_requests = params.pop('subscribe_requests', [])
        if subscribe_requests:
            return self._subscribe_requests(action, subscribe_requests)
        return self._request(action, request, **params)

class HttpTransportError(TransportError):
    """Http transport error."""
<commit_msg>Add response error handling<commit_after>from devicehive.transports.transport import Transport
from devicehive.transports.transport import TransportError
import requests
import threading
import sys

class HttpTransport(Transport):
    """Http transport class."""

    RESPONSE_SUCCESS_STATUS = 'success'
    RESPONSE_ERROR_STATUS = 'error'
    RESPONSE_STATUS_KEY = 'status'
    RESPONSE_CODE_KEY = 'code'
    RESPONSE_ERROR_KEY = 'error'
    RESPONSE_SUBSCRIBE_ID_KEY = 'subscriptionId'

    def __init__(self, data_format_class, data_format_options, handler_class,
                 handler_options):
        Transport.__init__(self, 'http', HttpTransportError, data_format_class,
                           data_format_options, handler_class, handler_options)
        self._url = None
        self._options = None
        self._events_queue = []
        self._subscribe_threads = {}
        self._success_codes = [200, 201, 204]

    def _connect(self, url, **options):
        self._url = url
        self._options = options
        if not self._url.endswith('/'):
            self._url += '/'
        self._connected = True
        self._handle_connect()

    def _receive(self):
        while self._connected and not self._exception_info:
            if not self._events_queue:
                continue
            for event in self._events_queue.pop(0):
                self._handle_event(event)
                if not self._connected:
                    return

    def _disconnect(self):
        self._events_queue = []
        self._subscribe_threads = {}
        self._handle_disconnect()

    def _request_call(self, method, url, **params):
        options = self._options.copy()
        options.update(params)
        try:
            response = requests.request(method, url, **options)
            code = response.status_code
            if self._text_data_type:
                return code, response.text
            return code, response.content
        except requests.RequestException as http_error:
            error = http_error
        raise self._error(error)

    def _request(self, action, request, **params):
        method = params.pop('method', 'GET')
        url = self._url + params.pop('url')
        request_delete_keys = params.pop('request_delete_keys', [])
        request_key = params.pop('request_key', None)
        response_key = params.pop('response_key', None)
        for request_delete_key in request_delete_keys:
            del request[request_delete_key]
        if request:
            if request_key:
                request = request[request_key]
            params['data'] = self._encode(request)
        code, data = self._request_call(method, url, **params)
        response = {self.REQUEST_ID_KEY: self._uuid(),
                    self.REQUEST_ACTION_KEY: action}
        if code in self._success_codes:
            response[self.RESPONSE_STATUS_KEY] = self.RESPONSE_SUCCESS_STATUS
            if not data:
                return response
            if response_key:
                response[response_key] = self._decode(data)
                return response
            response.update(self._decode(data))
            return response
        response[self.RESPONSE_STATUS_KEY] = self.RESPONSE_ERROR_STATUS
        response[self.RESPONSE_CODE_KEY] = code
        if not data:
            return response
        try:
            response_error = self._decode(data)['message']
        except Exception:
            response_error = data
        response[self.RESPONSE_ERROR_KEY] = response_error
        return response

    def _subscribe_requests(self, action, subscribe_requests):
        subscribe_id = self._uuid()
        subscribe_threads = []
        for action, request, params in subscribe_requests:
            name = '%s-transport-subscribe-%s-%s'
            subscribe_thread_name = name % (self._name, subscribe_id,
                                            len(subscribe_threads))
            subscribe_thread = threading.Thread(target=self._subscribe,
                                                args=(subscribe_id, action,
                                                      request, params))
            subscribe_thread.daemon = True
            subscribe_thread.name = subscribe_thread_name
            subscribe_thread.start()
            subscribe_threads.append(subscribe_thread)
        self._subscribe_threads[subscribe_id] = subscribe_threads
        return {self.REQUEST_ID_KEY: self._uuid(),
                self.REQUEST_ACTION_KEY: action,
                self.RESPONSE_STATUS_KEY: self.RESPONSE_SUCCESS_STATUS,
                self.RESPONSE_SUBSCRIBE_ID_KEY: subscribe_id}

    def _subscribe(self, subscribe_id, action, request, params):
        response_error_handler = params.pop('response_error_handler', None)
        response_error_handler_args = params.pop('response_error_handler_args',
                                                 None)
        response_key = params['response_key']
        params_timestamp_key = params.pop('params_timestamp_key', 'timestamp')
        response_timestamp_key = params.pop('response_timestamp_key',
                                            'timestamp')
        while self._connected and not self._exception_info:
            try:
                response = self._request(action, request.copy(), **params)
                response_status = response[self.RESPONSE_STATUS_KEY]
                if response_status != self.RESPONSE_SUCCESS_STATUS:
                    response_code = response[self.RESPONSE_CODE_KEY]
                    error = 'Subscribe request error. Action: %s. Code: %s.'
                    error = error % (action, response_code)
                    if not response_error_handler:
                        raise self._error(error)
                    if not response_error_handler(params, response_code,
                                                  *response_error_handler_args):
                        raise self._error(error)
                    response = self._request(action, request.copy(), **params)
                    response_status = response[self.RESPONSE_STATUS_KEY]
                    if response_status != self.RESPONSE_SUCCESS_STATUS:
                        raise self._error(error)
                events = response[response_key]
                if not len(events):
                    continue
                timestamp = events[-1][response_timestamp_key]
                if not params.get('params'):
                    params['params'] = {}
                params['params'][params_timestamp_key] = timestamp
                events = [{self.REQUEST_ACTION_KEY: action,
                           response_key: event,
                           self.RESPONSE_SUBSCRIBE_ID_KEY: subscribe_id}
                          for event in events]
                self._events_queue.append(events)
            except BaseException:
                self._exception_info = sys.exc_info()

    def send_request(self, action, request, **params):
        # TODO: add unsubscribe.
        self._ensure_connected()
        subscribe_requests = params.pop('subscribe_requests', [])
        if subscribe_requests:
            response = self._subscribe_requests(action, subscribe_requests)
            self._events_queue.append([response])
            return response[self.REQUEST_ID_KEY]
        response = self._request(action, request, **params)
        self._events_queue.append([response])
        return response[self.REQUEST_ID_KEY]

    def request(self, action, request, **params):
        # TODO: add unsubscribe.
        self._ensure_connected()
        subscribe_requests = params.pop('subscribe_requests', [])
        if subscribe_requests:
            return self._subscribe_requests(action, subscribe_requests)
        return self._request(action, request, **params)

class HttpTransportError(TransportError):
    """Http transport error."""
<|endoftext|>


<commit_before>import pyglet
import vecrec
import autoprop

from vecrec import Vector, Rect
from glooey.widget import Widget
from glooey.containers import Bin, Stack
from glooey.helpers import *

@autoprop
class Root(Stack):
    custom_one_child_gets_mouse = True

    def __init__(self, window, batch=None, group=None):
        super().__init__()

        self._parent = self
        self._window = window
        self._batch = batch or pyglet.graphics.Batch()
        self._group = group or pyglet.graphics.Group()
        self._spurious_leave_event = False

        window.push_handlers(self)

    @update_function
    def repack(self):
        self.claim()

        too_narrow = self.territory.width < self.claimed_width
        too_short = self.territory.height < self.claimed_height

        # Complain if the root widget needs more space than it claimed.
        if too_narrow or too_short:
            message = "{} is only {}x{}, but its children are {}x{}."
            raise RuntimeError(
                    message.format(
                        self,
                        self.territory.width, self.territory.height,
                        self.claimed_width, self.claimed_height,
            ))

        self.resize(self.territory)

    def regroup(self, group):
        # We need to replace None with an actual group, because glooey
        # interprets None as "my parent hasn't given me a group yet."
        super().regroup(group or pyglet.graphics.Group())

    def on_mouse_enter(self, x, y):
        # For some reason, whenever the mouse is clicked, X11 generates a
        # on_mouse_leave event followed by a on_mouse_enter event.  There's no
        # way to tell whether or not that happened in this handler alone, so we
        # check a flag that would be set in on_mouse_leave() if a spurious
        # event was detected.  If the event is spurious, reset the flag, ignore
        # the event, and stop it from propagating.

        if self._spurious_leave_event:
            self._spurious_leave_event = False
            return True
        else:
            super().on_mouse_enter(x, y)

    def on_mouse_leave(self, x, y):
        # For some reason, whenever the mouse is clicked, X11 generates a
        # on_mouse_leave event followed by a on_mouse_enter event.  We can tell
        # that this is happening in this handler because the mouse coordinates
        # will still be under the widget.  In this case, set a flag so
        # on_mouse_enter() will know to ignore the spurious event to follow and
        # to stop it from propagating.

        if self.is_under_mouse(x, y):
            self._spurious_leave_event = True
            return True
        else:
            super().on_mouse_leave(x, y)

    def get_root(self):
        return self

    def get_window(self):
        return self._window

    def get_batch(self):
        return self._batch

    def get_group(self):
        return self._group

    def get_territory(self):
        raise NotImplementedError

    @property
    def is_hidden(self):
        return self._is_hidden

@autoprop
class Gui(Root):

    def on_draw(self):
        self.window.clear()
        self.batch.draw()

    def on_resize(self, width, height):
        self.repack()

    def get_territory(self):
        return Rect.from_pyglet_window(self.window)

    def set_cursor(self, image, hot_spot):
        hx, hy = Vector.from_anything(hot_spot)
        cursor = pyglet.window.ImageMouseCursor(image, hx, hy)
        self.window.set_mouse_cursor(cursor)

@autoprop
class PanningGui(Gui):
    """
    A window with mouse exclusivity enabled.  This makes it possible to
    emit mouse pan events, but it also complicates a lot of things.  First of
    all, an image must be provided so that the mouse can be manually drawn.
    Second, the mouse coordinates must be manually tracked and fed to the event
    handlers.
    """

    def __init__(self, window, cursor, hotspot, batch=None, group=None):
        mouse_group = pyglet.graphics.OrderedGroup(1, parent=group)
        gui_group = pyglet.graphics.OrderedGroup(0, parent=group)

        super().__init__(window, batch, gui_group)
        window.set_exclusive_mouse(True)

        hotspot = vecrec.cast_anything_to_vector(hotspot)
        cursor.anchor_x = hotspot.x
        cursor.anchor_y = hotspot.y

        self.mouse = self.territory.center
        self.shadow_mouse = None
        self.cursor = pyglet.sprite.Sprite(
                cursor, batch=self.batch, group=mouse_group)

    def do_resize(self):
        self.mouse = self.territory.center

    def do_draw(self):
        self.cursor.visible = True
        self.cursor.position = self.mouse.tuple

    def do_undraw(self):
        self.cursor.visible = False

    def on_mouse_press(self, x, y, button, modifiers):
        super().on_mouse_press(self.mouse.x, self.mouse.y, button, modifiers)

    def on_mouse_release(self, x, y, button, modifiers):
        super().on_mouse_release(self.mouse.x, self.mouse.y, button, modifiers)

    def on_mouse_motion(self, x, y, dx, dy):
        self._update_mouse(dx, dy)
        super().on_mouse_motion(self.mouse.x, self.mouse.y, dx, dy)

    def on_mouse_enter(self, x, y):
        # The mouse never really enters or exits a window with mouse
        # exclusivity enabled, so mouse_enter and mouse_exits events should
        # never get triggered.  However, there is at least one scenario where
        # pyglet will do just that.
        #
        # This scenario can be triggered by instantly moving the window by more
        # than half of its width or height.  The issue is that, with mouse
        # exclusivity enabled, pyglet keeps the mouse in the center of the
        # screen.  If the window is moved far enough in one frame to put the
        # old mouse position outside the window, a spurious set of mouse_exit
        # and mouse_enter events get triggered.
        #
        # The solution to this problem is simply to ignore mouse_enter and
        # mouse_exit events for PanningGui objects.
        return True

    def on_mouse_leave(self, x, y):
        # See comment in on_mouse_enter().
        return True

    def on_mouse_drag(self, x, y, dx, dy, buttons, modifiers):
        self._update_mouse(dx, dy)
        super().on_mouse_drag(self.mouse.x, self.mouse.y, dx, dy, buttons, modifiers)

    def on_mouse_drag_enter(self, x, y):
        super().on_mouse_drag_enter(self.mouse.x, self.mouse.y)

    def on_mouse_drag_leave(self, x, y):
        super().on_mouse_drag_leave(self.mouse.x, self.mouse.y)

    def on_mouse_scroll(self, x, y, scroll_x, scroll_y):
        super().on_mouse_scroll(self.mouse.x, self.mouse.y, scroll_x, scroll_y)

    def _update_mouse(self, dx, dy):
        self.mouse += (dx, dy)

        # Decide whether or to start or stop panning.

        if self.mouse not in self.territory:
            if self.shadow_mouse is None:
                self._start_mouse_pan()

        if self.shadow_mouse is not None:
            if self.mouse in self.territory.get_shrunk(5):
                self._stop_mouse_pan()

        # Move the shadow mouse.

        if self.shadow_mouse is not None:
            self.shadow_mouse += (dx, dy)

            if self.territory.left < self.mouse.x < self.territory.right:
                self.shadow_mouse.x = self.mouse.x
            if self.territory.bottom < self.mouse.y < self.territory.top:
                self.shadow_mouse.y = self.mouse.y

        # Keep the mouse on screen.  This feels like there should be a function
        # for this in vecrec...

        if self.mouse.x < self.territory.left:
            self.mouse.x = self.territory.left
        if self.mouse.x > self.territory.right:
            self.mouse.x = self.territory.right
        if self.mouse.y < self.territory.bottom:
            self.mouse.y = self.territory.bottom
        if self.mouse.y > self.territory.top:
            self.mouse.y = self.territory.top

        # Update the mouse sprite.

        self.draw()

    def _start_mouse_pan(self):
        self.shadow_mouse = self.mouse.copy()
        pyglet.clock.schedule_interval(self._update_mouse_pan, 1/60)

    def _stop_mouse_pan(self):
        self.shadow_mouse = None
        pyglet.clock.unschedule(self._update_mouse_pan)

    def _update_mouse_pan(self, dt):
        direction = self.shadow_mouse - self.mouse
        self.dispatch_event('on_mouse_pan', direction, dt)

PanningGui.register_event_type('on_mouse_pan')

class Dialog(Widget):
    custom_alignment = 'center'

    def open(self, gui):
        self.close()
        gui.add(self)

    def close(self):
        if self.root is not None:
            self.root.remove(self)

<commit_msg>Don't repack if the window doesn't change size.<commit_after>import pyglet
import vecrec
import autoprop

from vecrec import Vector, Rect
from glooey.widget import Widget
from glooey.containers import Bin, Stack
from glooey.helpers import *

@autoprop
class Root(Stack):
    custom_one_child_gets_mouse = True

    def __init__(self, window, batch=None, group=None):
        super().__init__()

        self._parent = self
        self._window = window
        self._batch = batch or pyglet.graphics.Batch()
        self._group = group or pyglet.graphics.Group()
        self._spurious_leave_event = False

        window.push_handlers(self)

    @update_function
    def repack(self):
        self.claim()

        too_narrow = self.territory.width < self.claimed_width
        too_short = self.territory.height < self.claimed_height

        # Complain if the root widget needs more space than it claimed.
        if too_narrow or too_short:
            message = "{} is only {}x{}, but its children are {}x{}."
            raise RuntimeError(
                    message.format(
                        self,
                        self.territory.width, self.territory.height,
                        self.claimed_width, self.claimed_height,
            ))

        self.resize(self.territory)

    def regroup(self, group):
        # We need to replace None with an actual group, because glooey
        # interprets None as "my parent hasn't given me a group yet."
        super().regroup(group or pyglet.graphics.Group())

    def on_mouse_enter(self, x, y):
        # For some reason, whenever the mouse is clicked, X11 generates a
        # on_mouse_leave event followed by a on_mouse_enter event.  There's no
        # way to tell whether or not that happened in this handler alone, so we
        # check a flag that would be set in on_mouse_leave() if a spurious
        # event was detected.  If the event is spurious, reset the flag, ignore
        # the event, and stop it from propagating.

        if self._spurious_leave_event:
            self._spurious_leave_event = False
            return True
        else:
            super().on_mouse_enter(x, y)

    def on_mouse_leave(self, x, y):
        # For some reason, whenever the mouse is clicked, X11 generates a
        # on_mouse_leave event followed by a on_mouse_enter event.  We can tell
        # that this is happening in this handler because the mouse coordinates
        # will still be under the widget.  In this case, set a flag so
        # on_mouse_enter() will know to ignore the spurious event to follow and
        # to stop it from propagating.

        if self.is_under_mouse(x, y):
            self._spurious_leave_event = True
            return True
        else:
            super().on_mouse_leave(x, y)

    def get_root(self):
        return self

    def get_window(self):
        return self._window

    def get_batch(self):
        return self._batch

    def get_group(self):
        return self._group

    def get_territory(self):
        raise NotImplementedError

    @property
    def is_hidden(self):
        return self._is_hidden

@autoprop
class Gui(Root):

    def on_draw(self):
        self.window.clear()
        self.batch.draw()

    def on_resize(self, width, height):
        # Make sure the window actually changed size before starting a repack.
        width -= self.left_padding + self.right_padding
        height -= self.top_padding + self.bottom_padding
        if self.rect.size != (width, height):
            self.repack()

    def get_territory(self):
        return Rect.from_pyglet_window(self.window)

    def set_cursor(self, image, hot_spot):
        hx, hy = Vector.from_anything(hot_spot)
        cursor = pyglet.window.ImageMouseCursor(image, hx, hy)
        self.window.set_mouse_cursor(cursor)

@autoprop
class PanningGui(Gui):
    """
    A window with mouse exclusivity enabled.  This makes it possible to
    emit mouse pan events, but it also complicates a lot of things.  First of
    all, an image must be provided so that the mouse can be manually drawn.
    Second, the mouse coordinates must be manually tracked and fed to the event
    handlers.
    """

    def __init__(self, window, cursor, hotspot, batch=None, group=None):
        mouse_group = pyglet.graphics.OrderedGroup(1, parent=group)
        gui_group = pyglet.graphics.OrderedGroup(0, parent=group)

        super().__init__(window, batch, gui_group)
        window.set_exclusive_mouse(True)

        hotspot = vecrec.cast_anything_to_vector(hotspot)
        cursor.anchor_x = hotspot.x
        cursor.anchor_y = hotspot.y

        self.mouse = self.territory.center
        self.shadow_mouse = None
        self.cursor = pyglet.sprite.Sprite(
                cursor, batch=self.batch, group=mouse_group)

    def do_resize(self):
        self.mouse = self.territory.center

    def do_draw(self):
        self.cursor.visible = True
        self.cursor.position = self.mouse.tuple

    def do_undraw(self):
        self.cursor.visible = False

    def on_mouse_press(self, x, y, button, modifiers):
        super().on_mouse_press(self.mouse.x, self.mouse.y, button, modifiers)

    def on_mouse_release(self, x, y, button, modifiers):
        super().on_mouse_release(self.mouse.x, self.mouse.y, button, modifiers)

    def on_mouse_motion(self, x, y, dx, dy):
        self._update_mouse(dx, dy)
        super().on_mouse_motion(self.mouse.x, self.mouse.y, dx, dy)

    def on_mouse_enter(self, x, y):
        # The mouse never really enters or exits a window with mouse
        # exclusivity enabled, so mouse_enter and mouse_exits events should
        # never get triggered.  However, there is at least one scenario where
        # pyglet will do just that.
        #
        # This scenario can be triggered by instantly moving the window by more
        # than half of its width or height.  The issue is that, with mouse
        # exclusivity enabled, pyglet keeps the mouse in the center of the
        # screen.  If the window is moved far enough in one frame to put the
        # old mouse position outside the window, a spurious set of mouse_exit
        # and mouse_enter events get triggered.
        #
        # The solution to this problem is simply to ignore mouse_enter and
        # mouse_exit events for PanningGui objects.
        return True

    def on_mouse_leave(self, x, y):
        # See comment in on_mouse_enter().
        return True

    def on_mouse_drag(self, x, y, dx, dy, buttons, modifiers):
        self._update_mouse(dx, dy)
        super().on_mouse_drag(self.mouse.x, self.mouse.y, dx, dy, buttons, modifiers)

    def on_mouse_drag_enter(self, x, y):
        super().on_mouse_drag_enter(self.mouse.x, self.mouse.y)

    def on_mouse_drag_leave(self, x, y):
        super().on_mouse_drag_leave(self.mouse.x, self.mouse.y)

    def on_mouse_scroll(self, x, y, scroll_x, scroll_y):
        super().on_mouse_scroll(self.mouse.x, self.mouse.y, scroll_x, scroll_y)

    def _update_mouse(self, dx, dy):
        self.mouse += (dx, dy)

        # Decide whether or to start or stop panning.

        if self.mouse not in self.territory:
            if self.shadow_mouse is None:
                self._start_mouse_pan()

        if self.shadow_mouse is not None:
            if self.mouse in self.territory.get_shrunk(5):
                self._stop_mouse_pan()

        # Move the shadow mouse.

        if self.shadow_mouse is not None:
            self.shadow_mouse += (dx, dy)

            if self.territory.left < self.mouse.x < self.territory.right:
                self.shadow_mouse.x = self.mouse.x
            if self.territory.bottom < self.mouse.y < self.territory.top:
                self.shadow_mouse.y = self.mouse.y

        # Keep the mouse on screen.  This feels like there should be a function
        # for this in vecrec...

        if self.mouse.x < self.territory.left:
            self.mouse.x = self.territory.left
        if self.mouse.x > self.territory.right:
            self.mouse.x = self.territory.right
        if self.mouse.y < self.territory.bottom:
            self.mouse.y = self.territory.bottom
        if self.mouse.y > self.territory.top:
            self.mouse.y = self.territory.top

        # Update the mouse sprite.

        self.draw()

    def _start_mouse_pan(self):
        self.shadow_mouse = self.mouse.copy()
        pyglet.clock.schedule_interval(self._update_mouse_pan, 1/60)

    def _stop_mouse_pan(self):
        self.shadow_mouse = None
        pyglet.clock.unschedule(self._update_mouse_pan)

    def _update_mouse_pan(self, dt):
        direction = self.shadow_mouse - self.mouse
        self.dispatch_event('on_mouse_pan', direction, dt)

PanningGui.register_event_type('on_mouse_pan')

class Dialog(Widget):
    custom_alignment = 'center'

    def open(self, gui):
        self.close()
        gui.add(self)

    def close(self):
        if self.root is not None:
            self.root.remove(self)

<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
"""
Display disk information.

Configuration parameters:
    cache_timeout: refresh interval for this module. (default 10)
    disk: show stats for disk or partition, i.e. `sda1`. None for all disks.
        (default None)
    format: display format for this module.
        (default "{disk}: {used_percent}% ({total})")
    format_rate: display format for rates value
        (default "[\?min_length=11 {value:.1f} {unit}]")
    format_space: display format for disk space values
        (default "[\?min_length=5 {value:.1f}]")
    sector_size: size of the disk's sectors.
        (default 512)
    si_units: use SI units
        (default False)
    thresholds: thresholds to use for color changes
        *(default {'free': [(0, 'bad'), (10, 'degraded'), (100, 'good')],
        'total': [(0, "good"), (1024, 'degraded'), (1024 * 1024, 'bad')]})*
    unit: unit to use. If the unit contains a multiplier prefix, only this
        exact unit will ever be used
        (default "B/s")

Format placeholders:
    {disk} the selected disk
    {free} free space on disk in GB
    {used} used space on disk in GB
    {used_percent} used space on disk in %
    {read} reading rate
    {total} total IO rate
    {write} writing rate

format_rate placeholders:
    {unit} name of the unit
    {value} numeric value of the rate

format_space placeholders:
    {value} numeric value of the free/used space on the device

Color thresholds:
    {free} Change color based on the value of free
    {used} Change color based on the value of used_percent
    {read} Change color based on the value of read
    {total} Change color based on the value of total
    {write} Change color based on the value of write

@author guiniol
@license BSD
"""

from __future__ import division  # python2 compatibility
from time import time

class Py3status:
    """
    """
    # available configuration parameters
    cache_timeout = 10
    disk = None
    format = "{disk}: {used_percent}% ({total})"
    format_rate = "[\?min_length=11 {value:.1f} {unit}]"
    format_space = "[\?min_length=5 {value:.1f}]"
    sector_size = 512
    si_units = False
    thresholds = {
        'free': [(0, "bad"), (10, "degraded"), (100, "good")],
        'total': [(0, "good"), (1024, "degraded"), (1024 * 1024, "bad")]
    }
    unit = "B/s"

    def post_config_hook(self):
        """
        Format of total, up and down placeholders under self.format.
        As default, substitutes self.left_align and self.precision as %s and %s
        Placeholders:
            value - value (float)
            unit - unit (string)
        """
        self.last_interface = None
        self.last_stat = self._get_io_stats(self.disk)
        self.last_time = time()

    def space_and_io(self):
        self.values = {'disk': self.disk if self.disk else 'all'}

        if (self.py3.format_contains(self.format, 'read') or
                self.py3.format_contains(self.format, 'write') or
                self.py3.format_contains(self.format, 'total')):
            # time from previous check
            ios = self._get_io_stats(self.disk)
            timedelta = time() - self.last_time

            read = ios[0] - self.last_stat[0]
            write = ios[1] - self.last_stat[1]

            # update last_ info
            self.last_stat = self._get_io_stats(self.disk)
            self.last_time = time()

            read /= timedelta
            write /= timedelta

            total = read + write

            self.values['read'] = self._format_rate(read)
            self.values['total'] = self._format_rate(total)
            self.values['write'] = self._format_rate(write)
            self.py3.threshold_get_color(read, 'read')
            self.py3.threshold_get_color(total, 'total')
            self.py3.threshold_get_color(write, 'write')

        if (self.py3.format_contains(self.format, 'free') or
                self.py3.format_contains(self.format, 'used*')):
            free, used, used_percent = self._get_free_space(self.disk)

            self.values['free'] = self.py3.safe_format(self.format_space, {'value': free})
            self.values['used'] = self.py3.safe_format(self.format_space, {'value': used})
            self.values['used_percent'] = self.py3.safe_format(self.format_space,
                                                               {'value': used_percent})
            self.py3.threshold_get_color(free, 'free')
            self.py3.threshold_get_color(used, 'used')

        return {
            'cached_until': self.py3.time_in(self.cache_timeout),
            'full_text': self.py3.safe_format(self.format, self.values)
        }

    def _get_free_space(self, disk):
        if disk and not disk.startswith('/dev/'):
            disk = '/dev/' + disk

        total = 0
        used = 0
        free = 0
        devs = []

        df = self.py3.command_output('df')
        for line in df.splitlines():
            if (disk and line.startswith(disk)) or (disk is None and line.startswith('/dev/')):
                data = line.split()
                if data[0] in devs:
                    continue
                total += int(data[1]) / 1024 / 1024
                used += int(data[2]) / 1024 / 1024
                free += int(data[3]) / 1024 / 1024
                devs.append(data[0])

        if total == 0:
            return free, used, 'err'

        return free, used, 100 * used / total

    def _get_io_stats(self, disk):
        if disk and disk.startswith('/dev/'):
            disk = disk[5:]
        read = 0
        write = 0
        with open('/proc/diskstats', 'r') as fd:
            for line in fd:
                if disk and disk in line:
                    data = line.split()
                    read += int(data[5]) * self.sector_size
                    write += int(data[9]) * self.sector_size
                else:
                    data = line.split()
                    if data[1] == '0':
                        read += int(data[5]) * self.sector_size
                        write += int(data[9]) * self.sector_size
        return read, write

    def _format_rate(self, value):
        """
        Return formatted string
        """
        value, unit = self.py3.format_units(value, unit=self.unit, si=self.si_units)
        return self.py3.safe_format(self.format_rate, {'value': value, 'unit': unit})

if __name__ == "__main__":
    """
    Run module in test mode.
    """
    from py3status.module_test import module_test
    module_test(Py3status)
<commit_msg>Update diskdata.py<commit_after># -*- coding: utf-8 -*-
"""
Display disk information.

Configuration parameters:
    cache_timeout: refresh interval for this module. (default 10)
    disk: show stats for disk or partition, i.e. `sda1`. None for all disks.
        (default None)
    format: display format for this module.
        (default "{disk}: {used_percent}% ({total})")
    format_rate: display format for rates value
        (default "[\?min_length=11 {value:.1f} {unit}]")
    format_space: display format for disk space values
        (default "[\?min_length=5 {value:.1f}]")
    sector_size: size of the disk's sectors.
        (default 512)
    si_units: use SI units
        (default False)
    thresholds: thresholds to use for color changes
        *(default {'free': [(0, 'bad'), (10, 'degraded'), (100, 'good')],
        'total': [(0, "good"), (1024, 'degraded'), (1024 * 1024, 'bad')]})*
    unit: unit to use. If the unit contains a multiplier prefix, only this
        exact unit will ever be used
        (default "B/s")

Format placeholders:
    {disk} the selected disk
    {free} free space on disk in GB
    {used} used space on disk in GB
    {used_percent} used space on disk in %
    {read} reading rate
    {total} total IO rate
    {write} writing rate

format_rate placeholders:
    {unit} name of the unit
    {value} numeric value of the rate

format_space placeholders:
    {value} numeric value of the free/used space on the device

Color thresholds:
    {free} Change color based on the value of free
    {used} Change color based on the value of used_percent
    {read} Change color based on the value of read
    {total} Change color based on the value of total
    {write} Change color based on the value of write

@author guiniol
@license BSD
"""

from __future__ import division  # python2 compatibility
from time import time

class Py3status:
    """
    """
    # available configuration parameters
    cache_timeout = 10
    disk = None
    format = "{disk}: {used_percent}% ({total})"
    format_rate = "[\?min_length=11 {value:.1f} {unit}]"
    format_space = "[\?min_length=5 {value:.1f}]"
    sector_size = 512
    si_units = False
    thresholds = {
        'free': [(0, "bad"), (10, "degraded"), (100, "good")],
        'total': [(0, "good"), (1024, "degraded"), (1024 * 1024, "bad")]
    }
    unit = "B/s"

    def post_config_hook(self):
        """
        Format of total, up and down placeholders under self.format.
        As default, substitutes self.left_align and self.precision as %s and %s
        Placeholders:
            value - value (float)
            unit - unit (string)
        """
        self.last_interface = None
        self.last_stat = self._get_io_stats(self.disk)
        self.last_time = time()

    def space_and_io(self):
        self.values = {'disk': self.disk if self.disk else 'all'}

        if (self.py3.format_contains(self.format, 'read') or
                self.py3.format_contains(self.format, 'write') or
                self.py3.format_contains(self.format, 'total')):
            # time from previous check
            ios = self._get_io_stats(self.disk)
            timedelta = time() - self.last_time

            read = ios[0] - self.last_stat[0]
            write = ios[1] - self.last_stat[1]

            # update last_ info
            self.last_stat = self._get_io_stats(self.disk)
            self.last_time = time()

            read /= timedelta
            write /= timedelta

            total = read + write

            self.values['read'] = self._format_rate(read)
            self.values['total'] = self._format_rate(total)
            self.values['write'] = self._format_rate(write)
            self.py3.threshold_get_color(read, 'read')
            self.py3.threshold_get_color(total, 'total')
            self.py3.threshold_get_color(write, 'write')

        if (self.py3.format_contains(self.format, 'free') or
                self.py3.format_contains(self.format, 'used*')):
            free, used, used_percent = self._get_free_space(self.disk)

            self.values['free'] = self.py3.safe_format(self.format_space, {'value': free})
            self.values['used'] = self.py3.safe_format(self.format_space, {'value': used})
            self.values['used_percent'] = self.py3.safe_format(self.format_space,
                                                               {'value': used_percent})
            self.py3.threshold_get_color(free, 'free')
            self.py3.threshold_get_color(used, 'used')

        return {
            'cached_until': self.py3.time_in(self.cache_timeout),
            'full_text': self.py3.safe_format(self.format, self.values)
        }

    def _get_free_space(self, disk):
        if disk and not disk.startswith('/dev/'):
            disk = '/dev/' + disk

        total = 0
        used = 0
        free = 0
        devs = []

        df = self.py3.command_output('df')
        for line in df.splitlines():
            if (disk and line.startswith(disk)) or (disk is None and line.startswith('/dev/')):
                data = line.split()
                if data[0] in devs:
                    # Make sure to count each block device only one time
                    continue
                total += int(data[1]) / 1024 / 1024
                used += int(data[2]) / 1024 / 1024
                free += int(data[3]) / 1024 / 1024
                devs.append(data[0])

        if total == 0:
            return free, used, 'err'

        return free, used, 100 * used / total

    def _get_io_stats(self, disk):
        if disk and disk.startswith('/dev/'):
            disk = disk[5:]
        read = 0
        write = 0
        with open('/proc/diskstats', 'r') as fd:
            for line in fd:
                if disk and disk in line:
                    data = line.split()
                    read += int(data[5]) * self.sector_size
                    write += int(data[9]) * self.sector_size
                else:
                    data = line.split()
                    if data[1] == '0':
                        read += int(data[5]) * self.sector_size
                        write += int(data[9]) * self.sector_size
        return read, write

    def _format_rate(self, value):
        """
        Return formatted string
        """
        value, unit = self.py3.format_units(value, unit=self.unit, si=self.si_units)
        return self.py3.safe_format(self.format_rate, {'value': value, 'unit': unit})

if __name__ == "__main__":
    """
    Run module in test mode.
    """
    from py3status.module_test import module_test
    module_test(Py3status)
<|endoftext|>


<commit_before>import sys
import logging
from argparse import ArgumentParser, ArgumentDefaultsHelpFormatter

import numpy as NP
import pandas as PD

from ..gmd.calc_e import apply_transfer_function as tf_1D
from ..gmd.calc_e_3d import apply_transfer_function as tf_3D
from ..mag.iaga2hdf import read_hdf, write_hdf
from ..usarray_emtf.index import get_index, Index
from usgs_regions import get_region

logger = logging.getLogger('pyrsss.gmd.e2hdf')

def find_1D(header):
    """
    """
    lat = header['geodetic_latitude']
    lon = header['geodetic_longitude']
    region = get_region(lat, lon)
    if region:
        region = region.replace('-', '_')
    return region

def find_3D(index,
            header,
            max_distance,
            quality=5):
    """
    ???

    max_distance is in km
    """
    lat = header['geodetic_latitude']
    lon = header['geodetic_longitude']
    return index.quality_subset(min_quality=quality).by_distance(lat, lon, max_distance)

def apply_emtf(df_E,
               df_B,
               emtf_key,
               index):
    """
    """
    logger.info('applying transfer function {}'.format(emtf_key))
    interval = NP.diff(df_B.index.values[:2])[0] / NP.timedelta64(1, 's')
    Bx = df_B.Bx.values
    By = df_B.By.values
    if emtf_key.startswith('USArray'):
        xml_fname = index[emtf_key][1]
        Ex, Ey = tf_3D(Bx, By, interval, xml_fname)
    else:
        Ex, Ey = tf_1D(Bx, By, interval, emtf_key)
    df_E[emtf_key + '_Ex'] = Ex
    df_E[emtf_key + '_Ey'] = Ey
    return df_E

def e2hdf(hdf_fname,
          source_key='B',
          key='E',
          replace=False,
          include=[],
          exclude=[],
          _3D=None,
          _1D=False,
          quality=5):
    """
    """
    # setup target DataFrame
    df, header = read_hdf(hdf_fname, source_key)
    def empty_record():
        return PD.DataFrame(index=df.index)
    if replace:
        logger.info('creating new E record')
        df_e = empty_record()
    else:
        try:
            df_e, _ = read_hdf(hdf_fname, key)
            logger.info('appending to existing E record')
        except KeyError:
            logger.info('creating new E record')
            df_e = empty_record()
    # determine which EMTFs to use
    emtf_set = set(include) - set(exclude)
    if _1D:
        emtf_1D = find_1D(header)
        if emtf_1D is not None:
            emtf_set.add(emtf_1D)
    if _3D is not None:
        d_km, repository_path = _3D
        index = get_index(repository_path)
        for emtf_3D in find_3D(index, header, d_km):
            emtf_set.add(emtf_3D)
    else:
        index = None
    # apply EMTFs
    for emtf_key in sorted(emtf_set):
        df_e = apply_emtf(df_e, df, emtf_key, index)
    # output DataFrame
    write_hdf(hdf_fname, df_e, key, header)
    return hdf_fname

def float_or_str(x):
    """
    """
    try:
        return float(x)
    except:
        return x

def main(argv=None):
    if argv is None:
        argv = sys.argv

    parser = ArgumentParser('Added modeled E field records to HDF file containing processed B field data.',
                            formatter_class=ArgumentDefaultsHelpFormatter)
    parser.add_argument('hdf_fnames',
                        type=str,
                        nargs='*',
                        metavar='hdf_fname',
                        help='HDF file record to process')
    parser.add_argument('--source-key',
                        '-s',
                        type=str,
                        default='B',
                        help='')
    parser.add_argument('--key',
                        '-k',
                        type=str,
                        default='E',
                        help='key to associate with the processed records')
    parser.add_argument('--replace',
                        '-r',
                        action='store_true',
                        help='replace modeled E field record (otherwise, append to the existing record)')
    parser.add_argument('--include',
                        '-i',
                        nargs='+',
                        type=str,
                        default=[],
                        help='EMTFs to include')
    parser.add_argument('--exclude',
                        '-e',
                        nargs='+',
                        type=str,
                        default=[],
                        help='EMTFs to exclude')
    parser.add_argument('--1D',
                        action='store_true',
                        help='include Fernberg 1-D model result for the physiographic region at the measurement location (if interior to a physiographic region)')
    parser.add_argument('--3D',
                        type=float_or_str,
                        nargs=2,
                        help='two arguments: 1) include USArray 3-D model results within the specified geodetic distance (in km) from the measurement location and 2) the path to the USArray EMTF .xml repository')
    parser.add_argument('--quality',
                        '-q',
                        choices=range(6),
                        type=int,
                        default=5,
                        help='minimum acceptable quality USArray EMTF (i.e., 0 means use all and 5 means use only highest flagged transfer functions)')
    args = parser.parse_args(argv[1:])

    for hdf_fname in args.hdf_fnames:
        e2hdf(hdf_fname,
              source_key=args.source_key,
              key=args.key,
              replace=args.replace,
              include=args.include,
              exclude=args.exclude,
              _3D=getattr(args, '3D'),
              _1D=getattr(args, '1D'),
              quality=args.quality)

if __name__ == '__main__':
    logging.basicConfig(level=logging.INFO)
    sys.exit(main())
<commit_msg>Removed E from column keys.<commit_after>import sys
import logging
from argparse import ArgumentParser, ArgumentDefaultsHelpFormatter

import numpy as NP
import pandas as PD

from ..gmd.calc_e import apply_transfer_function as tf_1D
from ..gmd.calc_e_3d import apply_transfer_function as tf_3D
from ..mag.iaga2hdf import read_hdf, write_hdf
from ..usarray_emtf.index import get_index, Index
from usgs_regions import get_region

logger = logging.getLogger('pyrsss.gmd.e2hdf')

def find_1D(header):
    """
    """
    lat = header['geodetic_latitude']
    lon = header['geodetic_longitude']
    region = get_region(lat, lon)
    if region:
        region = region.replace('-', '_')
    return region

def find_3D(index,
            header,
            max_distance,
            quality=5):
    """
    ???

    max_distance is in km
    """
    lat = header['geodetic_latitude']
    lon = header['geodetic_longitude']
    return index.quality_subset(min_quality=quality).by_distance(lat, lon, max_distance)

def apply_emtf(df_E,
               df_B,
               emtf_key,
               index):
    """
    """
    logger.info('applying transfer function {}'.format(emtf_key))
    interval = NP.diff(df_B.index.values[:2])[0] / NP.timedelta64(1, 's')
    Bx = df_B.Bx.values
    By = df_B.By.values
    if emtf_key.startswith('USArray'):
        xml_fname = index[emtf_key][1]
        Ex, Ey = tf_3D(Bx, By, interval, xml_fname)
    else:
        Ex, Ey = tf_1D(Bx, By, interval, emtf_key)
    df_E[emtf_key + '_x'] = Ex
    df_E[emtf_key + '_y'] = Ey
    return df_E

def e2hdf(hdf_fname,
          source_key='B',
          key='E',
          replace=False,
          include=[],
          exclude=[],
          _3D=None,
          _1D=False,
          quality=5):
    """
    """
    # setup target DataFrame
    df, header = read_hdf(hdf_fname, source_key)
    def empty_record():
        return PD.DataFrame(index=df.index)
    if replace:
        logger.info('creating new E record')
        df_e = empty_record()
    else:
        try:
            df_e, _ = read_hdf(hdf_fname, key)
            logger.info('appending to existing E record')
        except KeyError:
            logger.info('creating new E record')
            df_e = empty_record()
    # determine which EMTFs to use
    emtf_set = set(include) - set(exclude)
    if _1D:
        emtf_1D = find_1D(header)
        if emtf_1D is not None:
            emtf_set.add(emtf_1D)
    if _3D is not None:
        d_km, repository_path = _3D
        index = get_index(repository_path)
        for emtf_3D in find_3D(index, header, d_km):
            emtf_set.add(emtf_3D)
    else:
        index = None
    # apply EMTFs
    for emtf_key in sorted(emtf_set):
        df_e = apply_emtf(df_e, df, emtf_key, index)
    # output DataFrame
    write_hdf(hdf_fname, df_e, key, header)
    return hdf_fname

def float_or_str(x):
    """
    """
    try:
        return float(x)
    except:
        return x

def main(argv=None):
    if argv is None:
        argv = sys.argv

    parser = ArgumentParser('Added modeled E field records to HDF file containing processed B field data.',
                            formatter_class=ArgumentDefaultsHelpFormatter)
    parser.add_argument('hdf_fnames',
                        type=str,
                        nargs='*',
                        metavar='hdf_fname',
                        help='HDF file record to process')
    parser.add_argument('--source-key',
                        '-s',
                        type=str,
                        default='B',
                        help='')
    parser.add_argument('--key',
                        '-k',
                        type=str,
                        default='E',
                        help='key to associate with the processed records')
    parser.add_argument('--replace',
                        '-r',
                        action='store_true',
                        help='replace modeled E field record (otherwise, append to the existing record)')
    parser.add_argument('--include',
                        '-i',
                        nargs='+',
                        type=str,
                        default=[],
                        help='EMTFs to include')
    parser.add_argument('--exclude',
                        '-e',
                        nargs='+',
                        type=str,
                        default=[],
                        help='EMTFs to exclude')
    parser.add_argument('--1D',
                        action='store_true',
                        help='include Fernberg 1-D model result for the physiographic region at the measurement location (if interior to a physiographic region)')
    parser.add_argument('--3D',
                        type=float_or_str,
                        nargs=2,
                        help='two arguments: 1) include USArray 3-D model results within the specified geodetic distance (in km) from the measurement location and 2) the path to the USArray EMTF .xml repository')
    parser.add_argument('--quality',
                        '-q',
                        choices=range(6),
                        type=int,
                        default=5,
                        help='minimum acceptable quality USArray EMTF (i.e., 0 means use all and 5 means use only highest flagged transfer functions)')
    args = parser.parse_args(argv[1:])

    for hdf_fname in args.hdf_fnames:
        e2hdf(hdf_fname,
              source_key=args.source_key,
              key=args.key,
              replace=args.replace,
              include=args.include,
              exclude=args.exclude,
              _3D=getattr(args, '3D'),
              _1D=getattr(args, '1D'),
              quality=args.quality)

if __name__ == '__main__':
    logging.basicConfig(level=logging.INFO)
    sys.exit(main())
<|endoftext|>


<commit_before>#!/usr/bin/python
#
#   Copyright (C) 2013, Jonathan Davies <jpdavs@gmail.com>
#
#   Redistribution and use in source and binary forms, with or without
#   modification, are permitted provided that the following conditions are met:
#
#   1. Redistributions of source code must retain the above copyright notice,
#      this list of conditions and the following disclaimer.
#   2. Redistributions in binary form must reproduce the above copyright
#      notice, this list of conditions and the following disclaimer in the
#      documentation and/or other materials provided with the distribution.
#
#   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
#   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
#   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
#   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
#   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
#   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
#   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
#   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
#   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
#   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
#   POSSIBILITY OF SUCH DAMAGE.
#

import datetime
import os
import shutil
import sys
import unittest

sys.path.append("..")

import entrymgr

class EnsureDirectoryExists(unittest.TestCase):
    # Test our entrymgr.ensure_directory_exists() function works.
    _date = "2013/09/23"
    _target_test_directory = "tests/fakediary/"

    def runTest(self):
        # Create the directory structure based on the fake date above.
        entrymgr.ensure_directory_exists(
            self._target_test_directory + self._date)

        self.assertTrue(os.path.isdir(
            self._target_test_directory + self._date))

    def tearDown(self):
        # Remove the above directory.
        shutil.rmtree(self._target_test_directory)

        self.assertFalse(os.path.isdir(
            self._target_test_directory + self._date))

class FormulateDateStructureTestCase(unittest.TestCase):
    # Make sure that we create proper strings.
    def runTest(self):
        fake_date = datetime.datetime(2013, 9, 23)
        function_result = entrymgr.formulate_directory_structure(fake_date)
        self.assertEqual(function_result, "2013/09/23")

class CheckLicenseTestCase(unittest.TestCase):
    # Simple dummy test to ensure that even unittest is working.
    def runTest(self):
        self.assertEqual(entrymgr.__license__, "BSD")

class GenerateDatestampTestCase(unittest.TestCase):
    # Ensure that we can generate valid datestamps for entry directories.
    def runTest(self):
        control = datetime.datetime(2013, 9, 23)
        date = entrymgr.generate_datestamp("2013/09/23")
        self.assertEqual(date, control)

class EntryLifeCycleTestCase(unittest.TestCase):
    # Ensure that we can create an entry.
    _entry_title = "Testing Lifecycle"
    _entry_date = entrymgr.generate_datestamp("2013/09/23")
    _target_result = "Testing Lifecycle\n================="

    def runTest(self):
        entrymgr.create_entry(self._entry_title, self._entry_date)

        entry_text = open("2013/09/23/testing-lifecycle.md", 'r').read()

        self.assertEqual(entry_text, self._target_result)

        self.assertTrue(os.path.isfile("2013/09/23/testing-lifecycle.md"))

        entrymgr.delete_entry(self._entry_title, self._entry_date)

        self.assertFalse(os.path.isfile("2013/09/23/testing-lifecycle.md"))

    def tearDown(self):
        # Remove the above directory.
        shutil.rmtree("2013")
<commit_msg>test_entrymgr.py: Ensure EntryLifeCycleTestCase takes place in a subdirectory under tests.<commit_after>#!/usr/bin/python
#
#   Copyright (C) 2013, Jonathan Davies <jpdavs@gmail.com>
#
#   Redistribution and use in source and binary forms, with or without
#   modification, are permitted provided that the following conditions are met:
#
#   1. Redistributions of source code must retain the above copyright notice,
#      this list of conditions and the following disclaimer.
#   2. Redistributions in binary form must reproduce the above copyright
#      notice, this list of conditions and the following disclaimer in the
#      documentation and/or other materials provided with the distribution.
#
#   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
#   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
#   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
#   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
#   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
#   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
#   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
#   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
#   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
#   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
#   POSSIBILITY OF SUCH DAMAGE.
#

import datetime
import os
import shutil
import sys
import unittest

sys.path.append("..")

import entrymgr

class EnsureDirectoryExists(unittest.TestCase):
    # Test our entrymgr.ensure_directory_exists() function works.
    _date = "2013/09/23"
    _target_test_directory = "tests/fakediary/"

    def runTest(self):
        # Create the directory structure based on the fake date above.
        entrymgr.ensure_directory_exists(
            self._target_test_directory + self._date)

        self.assertTrue(os.path.isdir(
            self._target_test_directory + self._date))

    def tearDown(self):
        # Remove the above directory.
        shutil.rmtree(self._target_test_directory)

        self.assertFalse(os.path.isdir(
            self._target_test_directory + self._date))

class FormulateDateStructureTestCase(unittest.TestCase):
    # Make sure that we create proper strings.
    def runTest(self):
        fake_date = datetime.datetime(2013, 9, 23)
        function_result = entrymgr.formulate_directory_structure(fake_date)
        self.assertEqual(function_result, "2013/09/23")

class CheckLicenseTestCase(unittest.TestCase):
    # Simple dummy test to ensure that even unittest is working.
    def runTest(self):
        self.assertEqual(entrymgr.__license__, "BSD")

class GenerateDatestampTestCase(unittest.TestCase):
    # Ensure that we can generate valid datestamps for entry directories.
    def runTest(self):
        control = datetime.datetime(2013, 9, 23)
        date = entrymgr.generate_datestamp("2013/09/23")
        self.assertEqual(date, control)

class EntryLifeCycleTestCase(unittest.TestCase):
    # Ensure that we can create an entry.
    _entry_title = "Testing Lifecycle"
    _entry_date = entrymgr.generate_datestamp("2013/09/23")
    _target_result = "Testing Lifecycle\n================="

    def runTest(self):
        # Create a fake directory and move our tests there.
        entrymgr.ensure_directory_exists("tests/fakediary")
        os.chdir("tests/fakediary")

        entrymgr.create_entry(self._entry_title, self._entry_date)

        entry_text = open("2013/09/23/testing-lifecycle.md", 'r').read()

        self.assertEqual(entry_text, self._target_result)

        self.assertTrue(os.path.isfile("2013/09/23/testing-lifecycle.md"))

        entrymgr.delete_entry(self._entry_title, self._entry_date)

        self.assertFalse(os.path.isfile("2013/09/23/testing-lifecycle.md"))
        self.assertTrue(os.path.isdir("2013/09/23"))

    def tearDown(self):
        # Remove the above directory.
        os.chdir("..")
        shutil.rmtree("fakediary")
<|endoftext|>


<commit_before># coding: utf-8
from socketIO_client import SocketIO
import pigpio

io_client = SocketIO('52.43.75.183', 8000)

def lock_control(action, pin_num=18):
    pi = pigpio.pi()
    avail_actions = {
        'unlock': 600,
        'lock': 2400,
    }
    pulsewidth = avail_actions.get(action, None)
    if not pulsewidth:
        raise ValueError('Action not permitted')
    pi.set_servo_pulsewidth(pin_num, pulsewidth)
    pi.stop()
    return pi.get_servo_pulsewidth(pin_num)

io_client.on('unlock', lambda: lock_control('unlock'))
io_client.on('lock', lambda: lock_control('lock'))

io_client.wait()
<commit_msg>refactor lambda<commit_after># coding: utf-8
from socketIO_client import SocketIO
import pigpio

io_client = SocketIO('52.43.75.183', 8000)

def lock_control(action, pin_num=18):
    pi = pigpio.pi()
    avail_actions = {
        'unlock': 600,
        'lock': 2400,
    }
    pulsewidth = avail_actions.get(action, None)
    if not pulsewidth:
        raise ValueError('Action not permitted')
    pi.set_servo_pulsewidth(pin_num, pulsewidth)
    pi.stop()
    return pi.get_servo_pulsewidth(pin_num)

io_client.on('unlock', lambda x: lock_control('unlock'))
io_client.on('lock', lambda x: lock_control('lock'))

io_client.wait()
<|endoftext|>


<commit_before>version = '0.4.1'

<commit_msg>version bump for 0.4.2.<commit_after>version = '0.4.2'

<|endoftext|>


<commit_before># pylint: disable=C0111,R0903

"""Displays the number of todo items from a text file

Parameters:
    * todo.file: File to read TODOs from (defaults to ~/Documents/todo.txt)
"""

import bumblebee.input
import bumblebee.output
import bumblebee.engine
import os.path

class Module(bumblebee.engine.Module):

    def __init__(self, engine, config):
        super(Module, self).__init__(engine, config,
            bumblebee.output.Widget(full_text=self.output)
        )
        self._doc = os.path.expanduser(self.parameter("file", "~/Documents/todo.txt"))
        self._todos = self.count_items()

    def output(self, widget):
       self._todos = self.count_items()
       return str(self._todos)

    def state(self, widgets):
        if self._todos == 0:
            return "empty"
        return "items"

    def count_items(self):
        try:
            i = -1
            with open(self._doc) as f:
                for i, l in enumerate(f):
                    pass
            return i+1
        except Exception:
            return 0
<commit_msg>[modules/todo] Update to latest API<commit_after># pylint: disable=C0111,R0903

"""Displays the number of todo items from a text file

Parameters:
    * todo.file: File to read TODOs from (defaults to ~/Documents/todo.txt)
"""

import os.path

import core.module
import core.widget

class Module(core.module.Module):
    def __init__(self, config):
        super().__init__(config, core.widget.Widget(self.output))

        self.__doc = os.path.expanduser(self.parameter('file', '~/Documents/todo.txt'))
        self.__todos = self.count_items()

    def output(self, widget):
       return str(self.__todos)

    def update(self):
       self.__todos = self.count_items()

    def state(self, widgets):
        if self.__todos == 0:
            return 'empty'
        return 'items'

    def count_items(self):
        try:
            i = -1
            with open(self.__doc) as f:
                for i, l in enumerate(f):
                    pass
            return i+1
        except Exception:
            return 0

# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
<|endoftext|>


<commit_before>"""Webdriver support for lettuce"""
import time

from lettuce import step
from lettuce import world

from lettuce_webdriver.util import (assert_true,
                                    assert_false,
                                    AssertContextManager,
                                    find_button,
                                    find_field,
                                    find_option,
                                    site_url)

from selenium.webdriver.support.ui import Select
from selenium.common.exceptions import (
    NoSuchElementException,
    StaleElementReferenceException)

def contains_content(browser, content):
    # Search for an element that contains the whole of the text we're looking
    #  for in it or its subelements, but whose children do NOT contain that
    #  text - otherwise matches <body> or <html> or other similarly useless
    #  things.
    for elem in browser.find_elements_by_xpath(
        '//*[contains(normalize-space(.),"{content}") ' \
        'and not(./*[contains(normalize-space(.),"{content}")])]' \
        .format(content=content)):

        try:
            if elem.is_displayed():
                return True
        except StaleElementReferenceException:
            pass

    return False

def wait_for_elem(browser, xpath, timeout=15):
    start = time.time()
    elems = []
    while time.time() - start < timeout:
        elems = browser.find_elements_by_xpath(xpath)
        if elems:
            return elems
        time.sleep(0.2)
    return elems

def wait_for_content(step, browser, content, timeout=15):
    start = time.time()
    while time.time() - start < timeout:
        if contains_content(world.browser, content):
            return
        time.sleep(0.2)
    assert_true(step, contains_content(world.browser, content))

## URLS
@step('I visit "(.*?)"$')
def visit(step, url):
    with AssertContextManager(step):
        world.browser.get(url)

@step(r'I visit site page "([^"]*)"')
def visit_page(step, page):
    """
    Visit the specific page of the site.
    """

    step.given('I visit "%s"' % site_url(page))

@step('I go to "(.*?)"$')
def goto(step, url):
    step.given('I visit "%s"' % url)

## Links
@step('I click "(.*?)"$')
def click(step, name):
    with AssertContextManager(step):
        elem = world.browser.find_element_by_link_text(name)
        elem.click()

@step('I should see a link with the url "(.*?)"$')
def should_see_link(step, link_url):
    assert_true(step, world.browser.
            find_element_by_xpath('//a[@href="%s"]' % link_url))

@step('I should see a link to "(.*?)" with the url "(.*?)"$')
def should_see_link_text(step, link_text, link_url):
    assert_true(step, world.browser.find_element_by_xpath('//a[@href="%s"][./text()="%s"]' %
        (link_url, link_text)))

@step('I should see a link that contains the text "(.*?)" and the url "(.*?)"$')
def should_include_link_text(step, link_text, link_url):
    return world.browser.find_element_by_xpath('//a[@href="%s"][contains(., %s)]' %
        (link_url, link_text))

## General
@step('The element with id of "(.*?)" contains "(.*?)"$')
def element_contains(step, element_id, value):
    return world.browser.find_element_by_xpath('//*[@id="%s"][contains(., "%s")]' %
        (element_id, value))

@step('The element with id of "(.*?)" does not contain "(.*?)"$')
def element_not_contains(step, element_id, value):
    elem = world.browser.find_element_by_xpath('//*[@id="%s"]' % element_id)
    assert_true(step, value not in elem.text)

@step('I should see an element with id of "(.*?)" within (\d+) seconds?$')
def should_see_id_in_seconds(step, element_id, timeout):
    elem = wait_for_elem(world.browser, '//*[@id="%s"]' % element_id, int(timeout))
    assert_true(step, elem)
    elem = elem[0]
    assert_true(step, elem.is_displayed())

@step('I should see an element with id of "(.*?)"$')
def should_see_id(step, element_id):
    elem = world.browser.find_element_by_xpath('//*[@id="%s"]' % element_id)
    assert_true(step, elem.is_displayed())

@step('I should not see an element with id of "(.*?)"$')
def should_not_see_id(step, element_id):
    try:
        elem = world.browser.find_element_by_xpath('//*[@id="%s"]' % element_id)
        assert_true(step, not elem.is_displayed())
    except NoSuchElementException:
        pass

@step('I should see "([^"]+)" within (\d+) seconds?$')
def should_see_in_seconds(step, text, timeout):
    wait_for_content(step, world.browser, text, int(timeout))

@step('I should see "([^"]+)"$')
def should_see(step, text):
    assert_true(step, contains_content(world.browser, text))

@step('I see "([^"]+)"$')
def see(step, text):
    assert_true(step, contains_content(world.browser, text))

@step('I should not see "([^"]+)"$')
def should_not_see(step, text):
    assert_true(step, not contains_content(world.browser, text))

@step('I should be at "(.*?)"$')
def url_should_be(step, url):
    assert_true(step, url == world.browser.current_url)

## Browser
@step('The browser\'s URL should be "(.*?)"$')
def browser_url_should_be(step, url):
    assert_true(step, url == world.browser.current_url)

@step ('The browser\'s URL should contain "(.*?)"$')
def url_should_contain(step, url):
    assert_true(step, url in world.browser.current_url)

@step ('The browser\'s URL should not contain "(.*?)"$')
def url_should_not_contain(step, url):
    assert_true(step, url not in world.browser.current_url)

## Forms
@step('I should see a form that goes to "(.*?)"$')
def see_form(step, url):
    return world.browser.find_element_by_xpath('//form[@action="%s"]' % url)

@step('I fill in "(.*?)" with "(.*?)"$')
def fill_in_textfield(step, field_name, value):
    with AssertContextManager(step):
        text_field = find_field(world.browser, 'text', field_name) or \
            find_field(world.browser, 'textarea', field_name) or \
            find_field(world.browser, 'password', field_name) or \
            find_field(world.browser, 'datetime', field_name) or \
            find_field(world.browser, 'datetime-local', field_name) or \
            find_field(world.browser, 'date', field_name) or \
            find_field(world.browser, 'month', field_name) or \
            find_field(world.browser, 'time', field_name) or \
            find_field(world.browser, 'week', field_name) or \
            find_field(world.browser, 'number', field_name) or \
            find_field(world.browser, 'range', field_name) or \
            find_field(world.browser, 'email', field_name) or \
            find_field(world.browser, 'url', field_name) or \
            find_field(world.browser, 'search', field_name) or \
            find_field(world.browser, 'tel', field_name) or \
            find_field(world.browser, 'color', field_name)
        assert_false(step, text_field is False,'Can not find a field named "%s"' % field_name)
        text_field.clear()
        text_field.send_keys(value)

@step('I press "(.*?)"$')
def press_button(step, value):
    with AssertContextManager(step):
        button = find_button(world.browser, value)
        button.click()

@step('I check "(.*?)"$')
def check_checkbox(step, value):
    with AssertContextManager(step):
        check_box = find_field(world.browser, 'checkbox', value)
        if not check_box.is_selected():
            check_box.click()

@step('I uncheck "(.*?)"$')
def uncheck_checkbox(step, value):
    with AssertContextManager(step):
        check_box = find_field(world.browser, 'checkbox', value)
        if check_box.is_selected():
            check_box.click()

@step('The "(.*?)" checkbox should be checked$')
def assert_checked_checkbox(step, value):
    check_box = find_field(world.browser, 'checkbox', value)
    assert_true(step, check_box.is_selected())

@step('The "(.*?)" checkbox should not be checked$')
def assert_not_checked_checkbox(step, value):
    check_box = find_field(world.browser, 'checkbox', value)
    assert_true(step, not check_box.is_selected())

@step('I select "(.*?)" from "(.*?)"$')
def select_single_item(step, option_name, select_name):
    with AssertContextManager(step):
        option_box = find_option(world.browser, select_name, option_name)
        option_box.click()

@step('I select the following from "([^"]*?)":?$')
def select_multi_items(step, select_name):
    with AssertContextManager(step):
        # Ensure only the options selected are actually selected
        option_names = step.multiline.split('\n')
        select_box = find_field(world.browser, 'select', select_name)

        select = Select(select_box)
        select.deselect_all()

        for option in option_names:
            try:
                select.select_by_value(option)
            except NoSuchElementException:
                select.select_by_visible_text(option)

@step('The "(.*?)" option from "(.*?)" should be selected$')
def assert_single_selected(step, option_name, select_name):
    option_box = find_option(world.browser, select_name, option_name)
    assert_true(step, option_box.is_selected())

@step('The following options from "([^"]*?)" should be selected:?$')
def assert_multi_selected(step, select_name):
    with AssertContextManager(step):
        # Ensure its not selected unless its one of our options
        option_names = step.multiline.split('\n')
        select_box = find_field(world.browser, 'select', select_name)
        option_elems = select_box.find_elements_by_xpath('./option')
        for option in option_elems:
            if option.get_attribute('id') in option_names or \
               option.get_attribute('name') in option_names or \
               option.get_attribute('value') in option_names or \
               option.text in option_names:
                assert_true(step, option.is_selected())
            else:
                assert_true(step, not option.is_selected())

@step('I choose "(.*?)"$')
def choose_radio(step, value):
    with AssertContextManager(step):
        box = find_field(world.browser, 'radio', value)
        box.click()

@step('The "(.*?)" option should be chosen$')
def assert_radio_selected(step, value):
    box = find_field(world.browser, 'radio', value)
    assert_true(step, box.is_selected())

@step('The "(.*?)" option should not be chosen$')
def assert_radio_not_selected(step, value):
    box = find_field(world.browser, 'radio', value)
    assert_true(step, not box.is_selected())
<commit_msg>Support for accepting and dismissing alerts<commit_after>"""Webdriver support for lettuce"""
import time

from lettuce import step
from lettuce import world

from lettuce_webdriver.util import (assert_true,
                                    assert_false,
                                    AssertContextManager,
                                    find_button,
                                    find_field,
                                    find_option,
                                    site_url)

from selenium.webdriver.support.ui import Select, Alert
from selenium.common.exceptions import (
    NoSuchElementException,
    StaleElementReferenceException,
    WebDriverException)

def contains_content(browser, content):
    # Search for an element that contains the whole of the text we're looking
    #  for in it or its subelements, but whose children do NOT contain that
    #  text - otherwise matches <body> or <html> or other similarly useless
    #  things.
    for elem in browser.find_elements_by_xpath(
        '//*[contains(normalize-space(.),"{content}") ' \
        'and not(./*[contains(normalize-space(.),"{content}")])]' \
        .format(content=content)):

        try:
            if elem.is_displayed():
                return True
        except StaleElementReferenceException:
            pass

    return False

def wait_for_elem(browser, xpath, timeout=15):
    start = time.time()
    elems = []
    while time.time() - start < timeout:
        elems = browser.find_elements_by_xpath(xpath)
        if elems:
            return elems
        time.sleep(0.2)
    return elems

def wait_for_content(step, browser, content, timeout=15):
    start = time.time()
    while time.time() - start < timeout:
        if contains_content(world.browser, content):
            return
        time.sleep(0.2)
    assert_true(step, contains_content(world.browser, content))

## URLS
@step('I visit "(.*?)"$')
def visit(step, url):
    with AssertContextManager(step):
        world.browser.get(url)

@step(r'I visit site page "([^"]*)"')
def visit_page(step, page):
    """
    Visit the specific page of the site.
    """

    step.given('I visit "%s"' % site_url(page))

@step('I go to "(.*?)"$')
def goto(step, url):
    step.given('I visit "%s"' % url)

## Links
@step('I click "(.*?)"$')
def click(step, name):
    with AssertContextManager(step):
        elem = world.browser.find_element_by_link_text(name)
        elem.click()

@step('I should see a link with the url "(.*?)"$')
def should_see_link(step, link_url):
    assert_true(step, world.browser.
            find_element_by_xpath('//a[@href="%s"]' % link_url))

@step('I should see a link to "(.*?)" with the url "(.*?)"$')
def should_see_link_text(step, link_text, link_url):
    assert_true(step, world.browser.find_element_by_xpath('//a[@href="%s"][./text()="%s"]' %
        (link_url, link_text)))

@step('I should see a link that contains the text "(.*?)" and the url "(.*?)"$')
def should_include_link_text(step, link_text, link_url):
    return world.browser.find_element_by_xpath('//a[@href="%s"][contains(., %s)]' %
        (link_url, link_text))

## General
@step('The element with id of "(.*?)" contains "(.*?)"$')
def element_contains(step, element_id, value):
    return world.browser.find_element_by_xpath('//*[@id="%s"][contains(., "%s")]' %
        (element_id, value))

@step('The element with id of "(.*?)" does not contain "(.*?)"$')
def element_not_contains(step, element_id, value):
    elem = world.browser.find_element_by_xpath('//*[@id="%s"]' % element_id)
    assert_true(step, value not in elem.text)

@step('I should see an element with id of "(.*?)" within (\d+) seconds?$')
def should_see_id_in_seconds(step, element_id, timeout):
    elem = wait_for_elem(world.browser, '//*[@id="%s"]' % element_id, int(timeout))
    assert_true(step, elem)
    elem = elem[0]
    assert_true(step, elem.is_displayed())

@step('I should see an element with id of "(.*?)"$')
def should_see_id(step, element_id):
    elem = world.browser.find_element_by_xpath('//*[@id="%s"]' % element_id)
    assert_true(step, elem.is_displayed())

@step('I should not see an element with id of "(.*?)"$')
def should_not_see_id(step, element_id):
    try:
        elem = world.browser.find_element_by_xpath('//*[@id="%s"]' % element_id)
        assert_true(step, not elem.is_displayed())
    except NoSuchElementException:
        pass

@step('I should see "([^"]+)" within (\d+) seconds?$')
def should_see_in_seconds(step, text, timeout):
    wait_for_content(step, world.browser, text, int(timeout))

@step('I should see "([^"]+)"$')
def should_see(step, text):
    assert_true(step, contains_content(world.browser, text))

@step('I see "([^"]+)"$')
def see(step, text):
    assert_true(step, contains_content(world.browser, text))

@step('I should not see "([^"]+)"$')
def should_not_see(step, text):
    assert_true(step, not contains_content(world.browser, text))

@step('I should be at "(.*?)"$')
def url_should_be(step, url):
    assert_true(step, url == world.browser.current_url)

## Browser
@step('The browser\'s URL should be "(.*?)"$')
def browser_url_should_be(step, url):
    assert_true(step, url == world.browser.current_url)

@step ('The browser\'s URL should contain "(.*?)"$')
def url_should_contain(step, url):
    assert_true(step, url in world.browser.current_url)

@step ('The browser\'s URL should not contain "(.*?)"$')
def url_should_not_contain(step, url):
    assert_true(step, url not in world.browser.current_url)

## Forms
@step('I should see a form that goes to "(.*?)"$')
def see_form(step, url):
    return world.browser.find_element_by_xpath('//form[@action="%s"]' % url)

@step('I fill in "(.*?)" with "(.*?)"$')
def fill_in_textfield(step, field_name, value):
    with AssertContextManager(step):
        text_field = find_field(world.browser, 'text', field_name) or \
            find_field(world.browser, 'textarea', field_name) or \
            find_field(world.browser, 'password', field_name) or \
            find_field(world.browser, 'datetime', field_name) or \
            find_field(world.browser, 'datetime-local', field_name) or \
            find_field(world.browser, 'date', field_name) or \
            find_field(world.browser, 'month', field_name) or \
            find_field(world.browser, 'time', field_name) or \
            find_field(world.browser, 'week', field_name) or \
            find_field(world.browser, 'number', field_name) or \
            find_field(world.browser, 'range', field_name) or \
            find_field(world.browser, 'email', field_name) or \
            find_field(world.browser, 'url', field_name) or \
            find_field(world.browser, 'search', field_name) or \
            find_field(world.browser, 'tel', field_name) or \
            find_field(world.browser, 'color', field_name)
        assert_false(step, text_field is False,'Can not find a field named "%s"' % field_name)
        text_field.clear()
        text_field.send_keys(value)

@step('I press "(.*?)"$')
def press_button(step, value):
    with AssertContextManager(step):
        button = find_button(world.browser, value)
        button.click()

@step('I check "(.*?)"$')
def check_checkbox(step, value):
    with AssertContextManager(step):
        check_box = find_field(world.browser, 'checkbox', value)
        if not check_box.is_selected():
            check_box.click()

@step('I uncheck "(.*?)"$')
def uncheck_checkbox(step, value):
    with AssertContextManager(step):
        check_box = find_field(world.browser, 'checkbox', value)
        if check_box.is_selected():
            check_box.click()

@step('The "(.*?)" checkbox should be checked$')
def assert_checked_checkbox(step, value):
    check_box = find_field(world.browser, 'checkbox', value)
    assert_true(step, check_box.is_selected())

@step('The "(.*?)" checkbox should not be checked$')
def assert_not_checked_checkbox(step, value):
    check_box = find_field(world.browser, 'checkbox', value)
    assert_true(step, not check_box.is_selected())

@step('I select "(.*?)" from "(.*?)"$')
def select_single_item(step, option_name, select_name):
    with AssertContextManager(step):
        option_box = find_option(world.browser, select_name, option_name)
        option_box.click()

@step('I select the following from "([^"]*?)":?$')
def select_multi_items(step, select_name):
    with AssertContextManager(step):
        # Ensure only the options selected are actually selected
        option_names = step.multiline.split('\n')
        select_box = find_field(world.browser, 'select', select_name)

        select = Select(select_box)
        select.deselect_all()

        for option in option_names:
            try:
                select.select_by_value(option)
            except NoSuchElementException:
                select.select_by_visible_text(option)

@step('The "(.*?)" option from "(.*?)" should be selected$')
def assert_single_selected(step, option_name, select_name):
    option_box = find_option(world.browser, select_name, option_name)
    assert_true(step, option_box.is_selected())

@step('The following options from "([^"]*?)" should be selected:?$')
def assert_multi_selected(step, select_name):
    with AssertContextManager(step):
        # Ensure its not selected unless its one of our options
        option_names = step.multiline.split('\n')
        select_box = find_field(world.browser, 'select', select_name)
        option_elems = select_box.find_elements_by_xpath('./option')
        for option in option_elems:
            if option.get_attribute('id') in option_names or \
               option.get_attribute('name') in option_names or \
               option.get_attribute('value') in option_names or \
               option.text in option_names:
                assert_true(step, option.is_selected())
            else:
                assert_true(step, not option.is_selected())

@step('I choose "(.*?)"$')
def choose_radio(step, value):
    with AssertContextManager(step):
        box = find_field(world.browser, 'radio', value)
        box.click()

@step('The "(.*?)" option should be chosen$')
def assert_radio_selected(step, value):
    box = find_field(world.browser, 'radio', value)
    assert_true(step, box.is_selected())

@step('The "(.*?)" option should not be chosen$')
def assert_radio_not_selected(step, value):
    box = find_field(world.browser, 'radio', value)
    assert_true(step, not box.is_selected())

@step('I accept the alert')
def accept_alert(step):
    """
    Accept the alert
    """

    try:
        alert = Alert(world.browser)
        alert.accept()
    except WebDriverException:
        # PhantomJS is kinda poor
        pass

@step('I dismiss the alert')
def dismiss_alert(step):
    """
    Dismiss the alert
    """

    try:
        alert = Alert(world.browser)
        alert.dismiss()
    except WebDriverException:
        # PhantomJS is kinda poor
        pass
<|endoftext|>