<commit_before>"""
Extension to MPL to support the binding of artists to key/mouse events.
"""
import sys
import logging

class Selection(object):
    """
    Store and compare selections.
    """
    # TODO: We need some way to check in prop matches, preferably
    # TODO: without imposing structure on prop.

    artist = None
    prop = {}

    def __init__(self, artist=None, prop={}):
        self.artist, self.prop = artist, self.prop

    def __eq__(self, other):
        return self.artist is other.artist

    def __ne__(self, other):
        return self.artist is not other.artist

    def __bool__(self):
        return self.artist is not None

class BindArtist(object):
    """
    """
    # Track keyboard modifiers for events.
    # TODO: Move keyboard modifier support into the backend.  We cannot
    # TODO: properly support it from outside the windowing system since there
    # TODO: is no way to recognized whether shift is held down when the mouse
    # TODO: first clicks on the the application window.
    control, shift, alt, meta = False, False, False, False

    # Track doubleclick
    dclick_threshhold = 0.25
    _last_button, _last_time = None, 0

    # Mouse/keyboard events we can bind to
    events = ['enter', 'leave', 'motion', 'click', 'dclick', 'drag', 'release',
              'scroll', 'key', 'keyup']
    # TODO: Need our own event structure

    def __init__(self, figure):
        canvas = figure.canvas

        # Link to keyboard/mouse
        try:
            self._connections = [
                canvas.mpl_connect('motion_notify_event', self._onMotion),
                canvas.mpl_connect('button_press_event', self._onClick),
                canvas.mpl_connect('button_release_event', self._onRelease),
                canvas.mpl_connect('key_press_event', self._onKey),
                canvas.mpl_connect('key_release_event', self._onKeyRelease),
                canvas.mpl_connect('scroll_event', self._onScroll)
            ]
        except:
            print("bypassing scroll_event: wrong matplotlib version")
            self._connections = [
                canvas.mpl_connect('motion_notify_event', self._onMotion),
                canvas.mpl_connect('button_press_event', self._onClick),
                canvas.mpl_connect('button_release_event', self._onRelease),
                canvas.mpl_connect('key_press_event', self._onKey),
                canvas.mpl_connect('key_release_event', self._onKeyRelease),
            ]

        self._current = None
        self._actions = {}
        self.canvas = canvas
        self.figure = figure
        self.clearall()

    def clear(self, *artists):
        """
        self.clear(h1,h2,...)
            Remove connections for artists h1, h2, ...

        Use clearall() to reset all connections.
        """

        for h in artists:
            for a in self.events:
                if h in self._actions[a]:
                    del self._actions[a][h]
            if h in self._artists:
                self._artists.remove(h)
        if self._current.artist in artists:
            self._current = Selection()
        if self._hasclick.artist in artists:
            self._hasclick = Selection()
        if self._haskey.artist in artists:
            self._haskey = Selection()

    def clearall(self):
        """
        Clear connections to all artists.

        Use clear(h1,h2,...) to reset specific artists.
        """
        # Don't monitor any actions
        self._actions = {}
        for action in self.events:
            self._actions[action] = {}

        # Need activity state
        self._artists = []
        self._current = Selection()
        self._hasclick = Selection()
        self._haskey = Selection()

    def disconnect(self):
        """
        In case we need to disconnect from the canvas...
        """
        try:
            for cid in self._connections: self.canvas.mpl_disconnect(cid)
        except:
            logging.error("Error disconnection canvas: %s" % sys.exc_info()[1])
        self._connections = []

    def __del__(self):
        self.disconnect()

    def __call__(self, trigger, artist, action):
        """Register a callback for an artist to a particular trigger event.

        usage:
            self.connect(eventname,artist,action)

        where:
            eventname is a string
            artist is the particular graph object to respond to the event
            action(event,**kw) is called when the event is triggered

        The action callback is associated with particular artists.
        Different artists will have different kwargs.  See documentation
        on the contains() method for each artist.  One common properties
        are ind for the index of the item under the cursor, which is
        returned by Line2D and by collections.

        The following events are supported:
            enter: mouse cursor moves into the artist or to a new index
            leave: mouse cursor leaves the artist
            click: mouse button pressed on the artist
            drag: mouse button pressed on the artist and cursor moves
            release: mouse button released for the artist
            key: key pressed when mouse is on the artist
            keyrelease: key released for the artist

        The event received by action has a number of attributes:
            name is the event name which was triggered
            artist is the object which triggered the event
            x,y are the screen coordinates of the mouse
            xdata,ydata are the graph coordinates of the mouse
            button is the mouse button being pressed/released
            key is the key being pressed/released
            shift,control,alt,meta are flags which are true if the
                corresponding key is pressed at the time of the event.
            details is a dictionary of artist specific details, such as the
                id(s) of the point that were clicked.

        When receiving an event, first check the modifier state to be
        sure it applies.  E.g., the callback for 'press' might be:
            if event.button == 1 and event.shift: process Shift-click

        TODO: Only receive events with the correct modifiers (e.g., S-click,
        TODO:   or *-click for any modifiers).
        TODO: Only receive button events for the correct button (e.g., click1
        TODO:   release3, or dclick* for any button)
        TODO: Support virtual artist, so that and artist can be flagged as
        TODO:   having a tag list and receive the correct events
        TODO: Support virtual events for binding to button-3 vs shift button-1
        TODO:   without changing callback code
        TODO: Attach multiple callbacks to the same event?
        TODO: Clean up interaction with toolbar modes
        TODO: push/pushclear/pop context so that binding changes for
             the duration
        TODO:   e.g., to support ? context sensitive help
        """
        # Check that the trigger is valid
        if trigger not in self._actions:
            raise ValueError("%s invalid --- valid triggers are %s"\
                 % (trigger, ", ".join(self.events)))

        # Register the trigger callback
        self._actions[trigger][artist] = action

        # Maintain a list of all artists
        if artist not in self._artists:
            self._artists.append(artist)

    def trigger(self, actor, action, ev):
        """
        Trigger a particular event for the artist.  Fallback to axes,
        to figure, and to 'all' if the event is not processed.
        """
        if action not in self.events:
            raise ValueError("Trigger expects " + ", ".join(self.events))

        # Tag the event with modifiers
        for mod in ('alt', 'control', 'shift', 'meta'):
            setattr(ev, mod, getattr(self, mod))
        setattr(ev, 'artist', None)
        setattr(ev, 'action', action)
        setattr(ev, 'prop', {})

        # Fallback scheme.  If the event does not return false, pass to parent.
        processed = False
        artist, prop = actor.artist, actor.prop
        if artist in self._actions[action]:
            ev.artist, ev.prop = artist, prop
            processed = self._actions[action][artist](ev)
        if not processed and ev.inaxes in self._actions[action]:
            ev.artist, ev.prop = ev.inaxes, {}
            processed = self._actions[action][ev.inaxes](ev)
        if not processed and self.figure in self._actions[action]:
            ev.artist, ev.prop = self.figure, {}
            processed = self._actions[action][self.figure](ev)
        if not processed and 'all' in self._actions[action]:
            ev.artist, ev.prop = None, {}
            processed = self._actions[action]['all'](ev)
        return processed

    def _find_current(self, event):
        """
        Find the artist who will receive the event.  Only search
        registered artists.  All others are invisible to the mouse.
        """
        # TODO: sort by zorder of axes then by zorder within axes
        found = Selection()
        self._artists.sort(key=lambda x: x.zorder, reverse=True)
        for artist in self._artists:
            # TODO: should contains() return false if invisible?
            if not artist.get_visible():
                continue
            # TODO: optimization - exclude artists not inaxes
            try:
                inside, prop = artist.contains(event)
            except:
                # Probably an old version of matplotlib
                inside = False
            if inside:
                found.artist, found.prop = artist, prop
                break

        # TODO: how to check if prop is equal?
        if found != self._current:
            self.trigger(self._current, 'leave', event)
            self.trigger(found, 'enter', event)
        self._current = found

        return found

    def _onMotion(self, event):
        """
        Track enter/leave/motion through registered artists; all
        other artists are invisible.
        """
        # # Can't kill double-click on motion since Windows produces
        # # spurious motion events.
        # self._last_button = None

        # Dibs on the motion event for the clicked artist
        if self._hasclick:
            # Make sure the x,y data use the coordinate system of the
            # artist rather than the default axes coordinates.

            transform = self._hasclick.artist.get_transform()
            # x,y = event.xdata,event.ydata
            x, y = event.x, event.y
            try:
                if transform.__class__.__name__ == "IdentityTransform":
                    x, y = transform.inverted().transform((x, y))
                else:
                    # # For interactive plottable apply transform is not working
                    # # don't know why maybe marker definition
                    # #transform ="CompositeGenericTransform" crash
                    pass
            except:
                # # CRUFT matplotlib-0.91 support
                # # exception for transform ="CompositeGenericTransform"
                # # crashes also here
                x, y = transform.inverse_xy_tup((x, y))

            # event.xdata, event.ydata = x, y
            self.trigger(self._hasclick, 'drag', event)
        else:
            found = self._find_current(event)
            self.trigger(found, 'motion', event)

    def _onClick(self, event):
        """
        Process button click
        """
        import time

        # Check for double-click
        event_time = time.time()
        if (event.button != self._last_button) or \
                (event_time > self._last_time + self.dclick_threshhold):
            action = 'click'
        else:
            action = 'dclick'
        self._last_button = event.button
        self._last_time = event_time

        # If an artist is already dragging, feed any additional button
        # presses to that artist.
        # TODO: do we want to force a single button model on the user?
        # TODO: that is, once a button is pressed, no other buttons
        # TODO: can come through?  I think this belongs in canvas, not here.
        if self._hasclick:
            found = self._hasclick
        else:
            found = self._find_current(event)
        # print "button %d pressed"%event.button
        # Note: it seems like if "click" returns False then hasclick should
        # not be set.  The problem is that there are two reasons it can
        # return false: because there is no click action for this artist
        # or because the click action returned false.  A related problem
        # is that click actions will go to the canvas if there is no click
        # action for the artist, even if the artist has a drag. I'll leave
        # it to future maintainers to sort out this problem.  For now the
        # recommendation is that users should define click if they have
        # drag or release on the artist.
        self.trigger(found, action, event)
        self._hasclick = found

    def _onDClick(self, event):
        """
        Process button double click
        """
        # If an artist is already dragging, feed any additional button
        # presses to that artist.
        # TODO: do we want to force a single button model on the user?
        # TODO: that is, once a button is pressed, no other buttons
        # TODO: can come through?  I think this belongs in canvas, not here.
        if self._hasclick:
            found = self._hasclick
        else:
            found = self._find_current(event)
        self.trigger(found, 'dclick', event)
        self._hasclick = found

    def _onRelease(self, event):
        """
        Process release release
        """
        self.trigger(self._hasclick, 'release', event)
        self._hasclick = Selection()

    def _onKey(self, event):
        """
        Process key click
        """
        # TODO: Do we really want keyboard focus separate from mouse focus?
        # TODO: Do we need an explicit focus command for keyboard?
        # TODO: Can we tab between items?
        # TODO: How do unhandled events get propogated to axes, figure and
        # TODO: finally to application?  Do we need to implement a full tags
        # TODO: architecture a la Tk?
        # TODO: Do modifiers cause a grab?  Does the artist see the modifiers?
        if event.key in ('alt', 'meta', 'control', 'shift'):
            setattr(self, event.key, True)
            return

        if self._haskey:
            found = self._haskey
        else:
            found = self._find_current(event)
        self.trigger(found, 'key', event)
        self._haskey = found

    def _onKeyRelease(self, event):
        """
        Process key release
        """
        if event.key in ('alt', 'meta', 'control', 'shift'):
            setattr(self, event.key, False)
            return

        if self._haskey:
            self.trigger(self._haskey, 'keyup', event)
        self._haskey = Selection()

    def _onScroll(self, event):
        """
        Process scroll event
        """
        found = self._find_current(event)
        self.trigger(found, 'scroll', event)

<commit_msg>Tidy up rst strings to avoid doc build warnings<commit_after>"""
Extension to MPL to support the binding of artists to key/mouse events.
"""
import sys
import logging

class Selection(object):
    """
    Store and compare selections.
    """
    # TODO: We need some way to check in prop matches, preferably
    # TODO: without imposing structure on prop.

    artist = None
    prop = {}

    def __init__(self, artist=None, prop={}):
        self.artist, self.prop = artist, self.prop

    def __eq__(self, other):
        return self.artist is other.artist

    def __ne__(self, other):
        return self.artist is not other.artist

    def __bool__(self):
        return self.artist is not None

class BindArtist(object):
    """
    """
    # Track keyboard modifiers for events.
    # TODO: Move keyboard modifier support into the backend.  We cannot
    # TODO: properly support it from outside the windowing system since there
    # TODO: is no way to recognized whether shift is held down when the mouse
    # TODO: first clicks on the the application window.
    control, shift, alt, meta = False, False, False, False

    # Track doubleclick
    dclick_threshhold = 0.25
    _last_button, _last_time = None, 0

    # Mouse/keyboard events we can bind to
    events = ['enter', 'leave', 'motion', 'click', 'dclick', 'drag', 'release',
              'scroll', 'key', 'keyup']
    # TODO: Need our own event structure

    def __init__(self, figure):
        canvas = figure.canvas

        # Link to keyboard/mouse
        try:
            self._connections = [
                canvas.mpl_connect('motion_notify_event', self._onMotion),
                canvas.mpl_connect('button_press_event', self._onClick),
                canvas.mpl_connect('button_release_event', self._onRelease),
                canvas.mpl_connect('key_press_event', self._onKey),
                canvas.mpl_connect('key_release_event', self._onKeyRelease),
                canvas.mpl_connect('scroll_event', self._onScroll)
            ]
        except:
            print("bypassing scroll_event: wrong matplotlib version")
            self._connections = [
                canvas.mpl_connect('motion_notify_event', self._onMotion),
                canvas.mpl_connect('button_press_event', self._onClick),
                canvas.mpl_connect('button_release_event', self._onRelease),
                canvas.mpl_connect('key_press_event', self._onKey),
                canvas.mpl_connect('key_release_event', self._onKeyRelease),
            ]

        self._current = None
        self._actions = {}
        self.canvas = canvas
        self.figure = figure
        self.clearall()

    def clear(self, *artists):
        """
        self.clear(h1,h2,...)
            Remove connections for artists h1, h2, ...

        Use clearall() to reset all connections.
        """

        for h in artists:
            for a in self.events:
                if h in self._actions[a]:
                    del self._actions[a][h]
            if h in self._artists:
                self._artists.remove(h)
        if self._current.artist in artists:
            self._current = Selection()
        if self._hasclick.artist in artists:
            self._hasclick = Selection()
        if self._haskey.artist in artists:
            self._haskey = Selection()

    def clearall(self):
        """
        Clear connections to all artists.

        Use clear(h1,h2,...) to reset specific artists.
        """
        # Don't monitor any actions
        self._actions = {}
        for action in self.events:
            self._actions[action] = {}

        # Need activity state
        self._artists = []
        self._current = Selection()
        self._hasclick = Selection()
        self._haskey = Selection()

    def disconnect(self):
        """
        In case we need to disconnect from the canvas...
        """
        try:
            for cid in self._connections: self.canvas.mpl_disconnect(cid)
        except:
            logging.error("Error disconnection canvas: %s" % sys.exc_info()[1])
        self._connections = []

    def __del__(self):
        self.disconnect()

    def __call__(self, trigger, artist, action):
        """Register a callback for an artist to a particular trigger event.

        usage:

            self.connect(eventname,artist,action)

        where:

            eventname is a string
            artist is the particular graph object to respond to the event
            action(event,**kw) is called when the event is triggered

        The action callback is associated with particular artists.
        Different artists will have different kwargs.  See documentation
        on the contains() method for each artist.  One common properties
        are ind for the index of the item under the cursor, which is
        returned by Line2D and by collections.

        The following events are supported:

            enter: mouse cursor moves into the artist or to a new index
            leave: mouse cursor leaves the artist
            click: mouse button pressed on the artist
            drag: mouse button pressed on the artist and cursor moves
            release: mouse button released for the artist
            key: key pressed when mouse is on the artist
            keyrelease: key released for the artist

        The event received by action has a number of attributes:

            name is the event name which was triggered
            artist is the object which triggered the event
            x,y are the screen coordinates of the mouse
            xdata,ydata are the graph coordinates of the mouse
            button is the mouse button being pressed/released
            key is the key being pressed/released
            shift,control,alt,meta are flags which are true if the
            corresponding key is pressed at the time of the event.
            details is a dictionary of artist specific details, such as the
            id(s) of the point that were clicked.

        When receiving an event, first check the modifier state to be
        sure it applies.  E.g., the callback for 'press' might be:

            if event.button == 1 and event.shift: process Shift-click

        TODO: Only receive events with the correct modifiers (e.g., S-click,
        TODO: or *-click for any modifiers).
        TODO: Only receive button events for the correct button (e.g., click1
        TODO: release3, or dclick* for any button)
        TODO: Support virtual artist, so that and artist can be flagged as
        TODO: having a tag list and receive the correct events
        TODO: Support virtual events for binding to button-3 vs shift button-1
        TODO: without changing callback code
        TODO: Attach multiple callbacks to the same event?
        TODO: Clean up interaction with toolbar modes
        TODO: push/pushclear/pop context so that binding changes for
        TODO: the duration
        TODO: e.g., to support ? context sensitive help
        """
        # Check that the trigger is valid
        if trigger not in self._actions:
            raise ValueError("%s invalid --- valid triggers are %s"\
                 % (trigger, ", ".join(self.events)))

        # Register the trigger callback
        self._actions[trigger][artist] = action

        # Maintain a list of all artists
        if artist not in self._artists:
            self._artists.append(artist)

    def trigger(self, actor, action, ev):
        """
        Trigger a particular event for the artist.  Fallback to axes,
        to figure, and to 'all' if the event is not processed.
        """
        if action not in self.events:
            raise ValueError("Trigger expects " + ", ".join(self.events))

        # Tag the event with modifiers
        for mod in ('alt', 'control', 'shift', 'meta'):
            setattr(ev, mod, getattr(self, mod))
        setattr(ev, 'artist', None)
        setattr(ev, 'action', action)
        setattr(ev, 'prop', {})

        # Fallback scheme.  If the event does not return false, pass to parent.
        processed = False
        artist, prop = actor.artist, actor.prop
        if artist in self._actions[action]:
            ev.artist, ev.prop = artist, prop
            processed = self._actions[action][artist](ev)
        if not processed and ev.inaxes in self._actions[action]:
            ev.artist, ev.prop = ev.inaxes, {}
            processed = self._actions[action][ev.inaxes](ev)
        if not processed and self.figure in self._actions[action]:
            ev.artist, ev.prop = self.figure, {}
            processed = self._actions[action][self.figure](ev)
        if not processed and 'all' in self._actions[action]:
            ev.artist, ev.prop = None, {}
            processed = self._actions[action]['all'](ev)
        return processed

    def _find_current(self, event):
        """
        Find the artist who will receive the event.  Only search
        registered artists.  All others are invisible to the mouse.
        """
        # TODO: sort by zorder of axes then by zorder within axes
        found = Selection()
        self._artists.sort(key=lambda x: x.zorder, reverse=True)
        for artist in self._artists:
            # TODO: should contains() return false if invisible?
            if not artist.get_visible():
                continue
            # TODO: optimization - exclude artists not inaxes
            try:
                inside, prop = artist.contains(event)
            except:
                # Probably an old version of matplotlib
                inside = False
            if inside:
                found.artist, found.prop = artist, prop
                break

        # TODO: how to check if prop is equal?
        if found != self._current:
            self.trigger(self._current, 'leave', event)
            self.trigger(found, 'enter', event)
        self._current = found

        return found

    def _onMotion(self, event):
        """
        Track enter/leave/motion through registered artists; all
        other artists are invisible.
        """
        # # Can't kill double-click on motion since Windows produces
        # # spurious motion events.
        # self._last_button = None

        # Dibs on the motion event for the clicked artist
        if self._hasclick:
            # Make sure the x,y data use the coordinate system of the
            # artist rather than the default axes coordinates.

            transform = self._hasclick.artist.get_transform()
            # x,y = event.xdata,event.ydata
            x, y = event.x, event.y
            try:
                if transform.__class__.__name__ == "IdentityTransform":
                    x, y = transform.inverted().transform((x, y))
                else:
                    # # For interactive plottable apply transform is not working
                    # # don't know why maybe marker definition
                    # #transform ="CompositeGenericTransform" crash
                    pass
            except:
                # # CRUFT matplotlib-0.91 support
                # # exception for transform ="CompositeGenericTransform"
                # # crashes also here
                x, y = transform.inverse_xy_tup((x, y))

            # event.xdata, event.ydata = x, y
            self.trigger(self._hasclick, 'drag', event)
        else:
            found = self._find_current(event)
            self.trigger(found, 'motion', event)

    def _onClick(self, event):
        """
        Process button click
        """
        import time

        # Check for double-click
        event_time = time.time()
        if (event.button != self._last_button) or \
                (event_time > self._last_time + self.dclick_threshhold):
            action = 'click'
        else:
            action = 'dclick'
        self._last_button = event.button
        self._last_time = event_time

        # If an artist is already dragging, feed any additional button
        # presses to that artist.
        # TODO: do we want to force a single button model on the user?
        # TODO: that is, once a button is pressed, no other buttons
        # TODO: can come through?  I think this belongs in canvas, not here.
        if self._hasclick:
            found = self._hasclick
        else:
            found = self._find_current(event)
        # print "button %d pressed"%event.button
        # Note: it seems like if "click" returns False then hasclick should
        # not be set.  The problem is that there are two reasons it can
        # return false: because there is no click action for this artist
        # or because the click action returned false.  A related problem
        # is that click actions will go to the canvas if there is no click
        # action for the artist, even if the artist has a drag. I'll leave
        # it to future maintainers to sort out this problem.  For now the
        # recommendation is that users should define click if they have
        # drag or release on the artist.
        self.trigger(found, action, event)
        self._hasclick = found

    def _onDClick(self, event):
        """
        Process button double click
        """
        # If an artist is already dragging, feed any additional button
        # presses to that artist.
        # TODO: do we want to force a single button model on the user?
        # TODO: that is, once a button is pressed, no other buttons
        # TODO: can come through?  I think this belongs in canvas, not here.
        if self._hasclick:
            found = self._hasclick
        else:
            found = self._find_current(event)
        self.trigger(found, 'dclick', event)
        self._hasclick = found

    def _onRelease(self, event):
        """
        Process release release
        """
        self.trigger(self._hasclick, 'release', event)
        self._hasclick = Selection()

    def _onKey(self, event):
        """
        Process key click
        """
        # TODO: Do we really want keyboard focus separate from mouse focus?
        # TODO: Do we need an explicit focus command for keyboard?
        # TODO: Can we tab between items?
        # TODO: How do unhandled events get propogated to axes, figure and
        # TODO: finally to application?  Do we need to implement a full tags
        # TODO: architecture a la Tk?
        # TODO: Do modifiers cause a grab?  Does the artist see the modifiers?
        if event.key in ('alt', 'meta', 'control', 'shift'):
            setattr(self, event.key, True)
            return

        if self._haskey:
            found = self._haskey
        else:
            found = self._find_current(event)
        self.trigger(found, 'key', event)
        self._haskey = found

    def _onKeyRelease(self, event):
        """
        Process key release
        """
        if event.key in ('alt', 'meta', 'control', 'shift'):
            setattr(self, event.key, False)
            return

        if self._haskey:
            self.trigger(self._haskey, 'keyup', event)
        self._haskey = Selection()

    def _onScroll(self, event):
        """
        Process scroll event
        """
        found = self._find_current(event)
        self.trigger(found, 'scroll', event)

<|endoftext|>


<commit_before>from   collections import defaultdict
import json
from   time        import sleep, time
from   urlparse    import urljoin
import requests
from   .base       import Region, Size
from   .droplet    import Droplet
from   .image      import Image
from   .action     import Action
from   .sshkey     import SSHKey

class doapi(object):
    def __init__(self, api_key, endpoint='https://api.digitalocean.com',
                 timeout=60, wait_interval=10, per_page=None):
        self.api_key = api_key
        self.endpoint = endpoint
        self.timeout = timeout
        self.wait_interval = wait_interval
        self.per_page = per_page
        self.last_response = None
        self.last_meta = None

    def request(self, url, params={}, data={}, method='GET'):
        if url[:1] == "/":
            url = urljoin(self.endpoint, url)
        attrs = {
            "headers": {
                "Authorization": "Bearer " + self.api_key,
                "Content-Type": "application/json"
            },
            "params": params,
            "timeout": self.timeout,
        }
        if method == 'GET':
            r = requests.get(url, **attrs)
        elif method == 'POST':
            r = requests.post(url, data=json.dumps(data), **attrs)
        elif method == 'PUT':
            r = requests.put(url, data=json.dumps(data), **attrs)
        elif method == 'DELETE':
            r = requests.delete(url, **attrs)
        else:
            raise ValueError('Unrecognized HTTP method: ' + repr(method))
        self.last_response = r
        self.last_meta = None
        r.raise_for_status()
        if method != 'DELETE':
            response = r.json()
            try:
                self.last_meta = response["meta"]
            except (KeyError, TypeError):
                pass
            return response

    @property
    def last_rate_limit(self):
        if self.last_response is None:
            return None
        else:
            ### Double-check this:
            return {k:v for k,v in self.last_response.headers.iteritems()
                        if k.startswith('ratelimit')}

    def raw_pages(self, path, params=None):
        if params is None:
            params = {}
        if self.per_page is not None:
            params["per_page"] = self.per_page
        while True:
            r = self.request(path, params=params)
            ### Could reusing `params` for non-first pages cause any problems?
            yield r
            try:
                path = r["links"]["pages"]["next"]
            except KeyError:
                break

    def paginate(self, path, key, params=None):
        data = []
        for page in self.raw_pages(path, params):
            data.extend(page[key])
        return data

    def droplet(self, obj):
        if isinstance(obj, (int, long)):
            dct = {"id": obj}
        elif isinstance(obj, Droplet):
            dct = obj._asdict()
        elif isinstance(obj, dict):
            dct = obj.copy()
        else:
            raise TypeError('argument must be integer, dict, or Droplet')
        dct["doapi_manager"] = self
        return Droplet(dct)

    def fetch_droplet(self, obj):
        return self.droplet(obj).fetch()

    def fetch_all_droplets(self):
        return map(self.droplet, self.paginate('/v2/droplets', 'droplets'))

    def fetch_droplets_by_name(self, name):
        for page in self.raw_pages('/v2/droplets'):
            for drop in page["droplets"]:
                if drop["name"] == name:
                    yield self.droplet(drop)

    def fetch_all_droplets_by_name(self):
        droplets = defaultdict(list)
        for page in self.raw_pages('/v2/droplets'):
            for drop in page["droplets"]:
                droplets[drop["name"]].append(self.droplet(drop))
        return droplets

    def fetch_droplet_upgrades(self):
        return self.request('/v2/droplet_upgrades')

    def create_droplet(self, name, image, size, region, **data):
        # Standard optional attributes: ssh_keys, backups, ipv6,
        #     private_networking, user_data
        data["name"] = name
        data["image"] = image.id if isinstance(image, Image) else image
        data["size"] = str(size)
        data["region"] = str(region)
        try:
            keys = data["ssh_keys"]
        except KeyError:
            pass
        else:
            data["ssh_keys"] = [k.id_or_fingerprint if isinstance(k, SSHKey)
                                                    else k for k in keys]
        return self.droplet(self.request('/v2/droplets', method='POST',
                                         data=data)["droplet"])

    def fetch_droplet_neighbors(self):
        return [map(self.droplet, hood)
                for hood in self.paginate('/v2/reports/droplet_neighbors',
                                          'neighbors')]

    def wait_droplets(self, droplets, status=None, interval=None, maxwait=-1):
        droplets = map(self.droplet, droplets)
        if status is None:
            for a in self.wait_actions([d.fetch_last_action()
                                        for d in droplets],
                                       interval=interval, maxwait=maxwait):
                yield a.fetch_resource()
        else:
            if interval is None:
                interval = self.wait_interval
            end_time = time() + maxwait if maxwait > 0 else None
            while droplets and (end_time is None or time() < end_time):
                next_droplets = []
                for d in droplets:
                    drop = d.fetch()
                    if drop.status == status:
                        yield drop
                    else:
                        next_droplets.append(drop)
                droplets = next_droplets
                if end_time is None:
                    sleep(interval)
                else:
                    sleep(min(interval, end_time - time()))

    def action(self, obj):
        if isinstance(obj, (int, long)):
            dct = {"id": obj}
        elif isinstance(obj, Action):
            dct = obj._asdict()
        elif isinstance(obj, dict):
            dct = obj.copy()
        else:
            raise TypeError('argument must be integer, dict, or Action')
        dct["doapi_manager"] = self
        return Action(dct)

    def fetch_action(self, obj):
        return self.action(obj).fetch()

    def fetch_all_actions(self):
        return map(self.action, self.paginate('/v2/actions', 'actions'))

    def wait_actions(self, actions, interval=None, maxwait=-1):
        actions = map(self.action, actions)
        if interval is None:
            interval = self.wait_interval
        end_time = time() + maxwait if maxwait > 0 else None
        while actions and (end_time is None or time() < end_time):
            next_actions = []
            for a in actions:
                act = a.fetch()
                if act.in_progress:
                    next_actions.append(act)
                else:
                    yield act
            actions = next_actions
            if end_time is None:
                sleep(interval)
            else:
                sleep(min(interval, end_time - time()))

    def sshkey(self, obj=None, **keyargs):
        if obj is None:
            ### Do `dct = keyargs` instead?
            if keyargs.get("id", None) is not None:
                dct = {"id": keyargs["id"]}  ### Apply `int`?
            elif keyargs.get("fingerprint", None) is not None:
                dct = {"fingerprint": keyargs["fingerprint"]}  ### Apply `str`?
            else:
                raise TypeError('Neither "id" nor "fingerprint" is defined')
            """ ### Alternative:
            try:
                dct = {"id": keyargs["id"]}
            except KeyError:
                dct = {"fingerprint": keyargs["fingerprint"]}
            """
        elif isinstance(obj, (int, long)):
            dct = {"id": obj}
        elif isinstance(obj, basestring):
            dct = {"fingerprint": obj}
        elif isinstance(obj, SSHKey):
            dct = obj._asdict()
        elif isinstance(obj, dict):
            dct = obj.copy()
        else:
            raise TypeError('argument must be integer, string, dict, or SSHKey')
        dct["doapi_manager"] = self
        return SSHKey(dct)

    def fetch_sshkey(self, obj=None, **keyargs):
        return self.sshkey(obj, **keyargs).fetch()

    def fetch_all_sshkeys(self):
        return map(self.sshkey, self.paginate('/v2/account/keys', 'ssh_keys'))

    def create_sshkey(self, name, public_key):
        return self.sshkey(self.request('/v2/account/keys', method='POST', data={"name": name, "public_key": public_key})["ssh_key"])

    def image(self, obj):
        if isinstance(obj, (int, long)):
            dct = {"id": obj}
        elif isinstance(obj, Image):
            dct = obj._asdict()
        elif isinstance(obj, dict):
            dct = obj.copy()
        else:
            raise TypeError('argument must be integer, dict, or Image')
        dct["doapi_manager"] = self
        return Image(dct)

    def fetch_image(self, obj):
        return self.image(obj).fetch()

    def fetch_all_images(self, type=None, private=False):
        params = {}
        if type is not None:
            params["type"] = type
        if private:
            params["private"] = 'true'
        return map(self.image, self.paginate('/v2/images', 'images',
                                             params=params))

    def fetch_all_distribution_images(self):
        return self.fetch_all_images(type='distribution')

    def fetch_all_application_images(self):
        return self.fetch_all_images(type='application')

    def fetch_all_private_images(self):
        return self.fetch_all_images(private=True)

    def region(self, obj):
        if isinstance(obj, Region):
            dct = obj._asdict()
        elif isinstance(obj, dict):
            dct = obj.copy()
        else:
            raise TypeError('argument must be dict or Region')
        dct["doapi_manager"] = self
        return Region(dct)

    def fetch_all_regions(self):
        return map(self.region, self.paginate('/v2/regions', 'regions'))

    def size(self, obj):
        if isinstance(obj, Size):
            dct = obj._asdict()
        elif isinstance(obj, dict):
            dct = obj.copy()
        else:
            raise TypeError('argument must be dict or Size')
        dct["doapi_manager"] = self
        return Size(dct)

    def fetch_all_sizes(self):
        return map(self.size, self.paginate('/v2/sizes', 'sizes'))

    ### fetch_droplet_upgrades
<commit_msg>`doapi.fetch_droplets_by_name` now returns a list instead of an iterator for consistency with other methods<commit_after>from   collections import defaultdict
import json
from   time        import sleep, time
from   urlparse    import urljoin
import requests
from   .base       import Region, Size
from   .droplet    import Droplet
from   .image      import Image
from   .action     import Action
from   .sshkey     import SSHKey

class doapi(object):
    def __init__(self, api_key, endpoint='https://api.digitalocean.com',
                 timeout=60, wait_interval=10, per_page=None):
        self.api_key = api_key
        self.endpoint = endpoint
        self.timeout = timeout
        self.wait_interval = wait_interval
        self.per_page = per_page
        self.last_response = None
        self.last_meta = None

    def request(self, url, params={}, data={}, method='GET'):
        if url[:1] == "/":
            url = urljoin(self.endpoint, url)
        attrs = {
            "headers": {
                "Authorization": "Bearer " + self.api_key,
                "Content-Type": "application/json"
            },
            "params": params,
            "timeout": self.timeout,
        }
        if method == 'GET':
            r = requests.get(url, **attrs)
        elif method == 'POST':
            r = requests.post(url, data=json.dumps(data), **attrs)
        elif method == 'PUT':
            r = requests.put(url, data=json.dumps(data), **attrs)
        elif method == 'DELETE':
            r = requests.delete(url, **attrs)
        else:
            raise ValueError('Unrecognized HTTP method: ' + repr(method))
        self.last_response = r
        self.last_meta = None
        r.raise_for_status()
        if method != 'DELETE':
            response = r.json()
            try:
                self.last_meta = response["meta"]
            except (KeyError, TypeError):
                pass
            return response

    @property
    def last_rate_limit(self):
        if self.last_response is None:
            return None
        else:
            ### Double-check this:
            return {k:v for k,v in self.last_response.headers.iteritems()
                        if k.startswith('ratelimit')}

    def raw_pages(self, path, params=None):
        if params is None:
            params = {}
        if self.per_page is not None:
            params["per_page"] = self.per_page
        while True:
            r = self.request(path, params=params)
            ### Could reusing `params` for non-first pages cause any problems?
            yield r
            try:
                path = r["links"]["pages"]["next"]
            except KeyError:
                break

    def paginate(self, path, key, params=None):
        data = []
        for page in self.raw_pages(path, params):
            data.extend(page[key])
        return data

    def droplet(self, obj):
        if isinstance(obj, (int, long)):
            dct = {"id": obj}
        elif isinstance(obj, Droplet):
            dct = obj._asdict()
        elif isinstance(obj, dict):
            dct = obj.copy()
        else:
            raise TypeError('argument must be integer, dict, or Droplet')
        dct["doapi_manager"] = self
        return Droplet(dct)

    def fetch_droplet(self, obj):
        return self.droplet(obj).fetch()

    def fetch_all_droplets(self):
        return map(self.droplet, self.paginate('/v2/droplets', 'droplets'))

    def fetch_droplets_by_name(self, name):
        return [self.droplet(drop) for page in self.raw_pages('/v2/droplets')
                                   for drop in page["droplets"]
                                   if drop["name"] == name]

    def fetch_all_droplets_by_name(self):
        droplets = defaultdict(list)
        for page in self.raw_pages('/v2/droplets'):
            for drop in page["droplets"]:
                droplets[drop["name"]].append(self.droplet(drop))
        return droplets

    def fetch_droplet_upgrades(self):
        return self.request('/v2/droplet_upgrades')

    def create_droplet(self, name, image, size, region, **data):
        # Standard optional attributes: ssh_keys, backups, ipv6,
        #     private_networking, user_data
        data["name"] = name
        data["image"] = image.id if isinstance(image, Image) else image
        data["size"] = str(size)
        data["region"] = str(region)
        try:
            keys = data["ssh_keys"]
        except KeyError:
            pass
        else:
            data["ssh_keys"] = [k.id_or_fingerprint if isinstance(k, SSHKey)
                                                    else k for k in keys]
        return self.droplet(self.request('/v2/droplets', method='POST',
                                         data=data)["droplet"])

    def fetch_droplet_neighbors(self):
        return [map(self.droplet, hood)
                for hood in self.paginate('/v2/reports/droplet_neighbors',
                                          'neighbors')]

    def wait_droplets(self, droplets, status=None, interval=None, maxwait=-1):
        droplets = map(self.droplet, droplets)
        if status is None:
            for a in self.wait_actions([d.fetch_last_action()
                                        for d in droplets],
                                       interval=interval, maxwait=maxwait):
                yield a.fetch_resource()
        else:
            if interval is None:
                interval = self.wait_interval
            end_time = time() + maxwait if maxwait > 0 else None
            while droplets and (end_time is None or time() < end_time):
                next_droplets = []
                for d in droplets:
                    drop = d.fetch()
                    if drop.status == status:
                        yield drop
                    else:
                        next_droplets.append(drop)
                droplets = next_droplets
                if end_time is None:
                    sleep(interval)
                else:
                    sleep(min(interval, end_time - time()))

    def action(self, obj):
        if isinstance(obj, (int, long)):
            dct = {"id": obj}
        elif isinstance(obj, Action):
            dct = obj._asdict()
        elif isinstance(obj, dict):
            dct = obj.copy()
        else:
            raise TypeError('argument must be integer, dict, or Action')
        dct["doapi_manager"] = self
        return Action(dct)

    def fetch_action(self, obj):
        return self.action(obj).fetch()

    def fetch_all_actions(self):
        return map(self.action, self.paginate('/v2/actions', 'actions'))

    def wait_actions(self, actions, interval=None, maxwait=-1):
        actions = map(self.action, actions)
        if interval is None:
            interval = self.wait_interval
        end_time = time() + maxwait if maxwait > 0 else None
        while actions and (end_time is None or time() < end_time):
            next_actions = []
            for a in actions:
                act = a.fetch()
                if act.in_progress:
                    next_actions.append(act)
                else:
                    yield act
            actions = next_actions
            if end_time is None:
                sleep(interval)
            else:
                sleep(min(interval, end_time - time()))

    def sshkey(self, obj=None, **keyargs):
        if obj is None:
            ### Do `dct = keyargs` instead?
            if keyargs.get("id", None) is not None:
                dct = {"id": keyargs["id"]}  ### Apply `int`?
            elif keyargs.get("fingerprint", None) is not None:
                dct = {"fingerprint": keyargs["fingerprint"]}  ### Apply `str`?
            else:
                raise TypeError('Neither "id" nor "fingerprint" is defined')
            """ ### Alternative:
            try:
                dct = {"id": keyargs["id"]}
            except KeyError:
                dct = {"fingerprint": keyargs["fingerprint"]}
            """
        elif isinstance(obj, (int, long)):
            dct = {"id": obj}
        elif isinstance(obj, basestring):
            dct = {"fingerprint": obj}
        elif isinstance(obj, SSHKey):
            dct = obj._asdict()
        elif isinstance(obj, dict):
            dct = obj.copy()
        else:
            raise TypeError('argument must be integer, string, dict, or SSHKey')
        dct["doapi_manager"] = self
        return SSHKey(dct)

    def fetch_sshkey(self, obj=None, **keyargs):
        return self.sshkey(obj, **keyargs).fetch()

    def fetch_all_sshkeys(self):
        return map(self.sshkey, self.paginate('/v2/account/keys', 'ssh_keys'))

    def create_sshkey(self, name, public_key):
        return self.sshkey(self.request('/v2/account/keys', method='POST', data={"name": name, "public_key": public_key})["ssh_key"])

    def image(self, obj):
        if isinstance(obj, (int, long)):
            dct = {"id": obj}
        elif isinstance(obj, Image):
            dct = obj._asdict()
        elif isinstance(obj, dict):
            dct = obj.copy()
        else:
            raise TypeError('argument must be integer, dict, or Image')
        dct["doapi_manager"] = self
        return Image(dct)

    def fetch_image(self, obj):
        return self.image(obj).fetch()

    def fetch_all_images(self, type=None, private=False):
        params = {}
        if type is not None:
            params["type"] = type
        if private:
            params["private"] = 'true'
        return map(self.image, self.paginate('/v2/images', 'images',
                                             params=params))

    def fetch_all_distribution_images(self):
        return self.fetch_all_images(type='distribution')

    def fetch_all_application_images(self):
        return self.fetch_all_images(type='application')

    def fetch_all_private_images(self):
        return self.fetch_all_images(private=True)

    def region(self, obj):
        if isinstance(obj, Region):
            dct = obj._asdict()
        elif isinstance(obj, dict):
            dct = obj.copy()
        else:
            raise TypeError('argument must be dict or Region')
        dct["doapi_manager"] = self
        return Region(dct)

    def fetch_all_regions(self):
        return map(self.region, self.paginate('/v2/regions', 'regions'))

    def size(self, obj):
        if isinstance(obj, Size):
            dct = obj._asdict()
        elif isinstance(obj, dict):
            dct = obj.copy()
        else:
            raise TypeError('argument must be dict or Size')
        dct["doapi_manager"] = self
        return Size(dct)

    def fetch_all_sizes(self):
        return map(self.size, self.paginate('/v2/sizes', 'sizes'))

    ### fetch_droplet_upgrades
<|endoftext|>


<commit_before>import os
from StringIO import StringIO
from mock import patch, call

from django.core.management.base import CommandError
from django.test import TestCase
from django.contrib.gis.geos import GEOSGeometry

from geotrek.core.factories import PathFactory
from geotrek.trekking.models import POI
from geotrek.trekking.management.commands.loadpoi import Command

class LoadPOITest(TestCase):
    def setUp(self):
        self.cmd = Command()
        self.filename = os.path.join(os.path.dirname(__file__),
                                     'data', 'poi.shp')
        PathFactory.create()

    def test_command_fails_if_no_arg(self):
        self.assertRaises(CommandError, self.cmd.execute)

    def test_command_fails_if_too_many_args(self):
        self.assertRaises(CommandError, self.cmd.execute, 'a', 'b')

    def test_command_fails_if_filename_missing(self):
        self.assertRaises(CommandError, self.cmd.execute, 'toto.shp')

    def test_command_shows_number_of_objects(self):
        output = StringIO()
        self.cmd.execute(self.filename, stdout=output)
        self.assertIn('2 objects found', output.getvalue())

    # def test_pois_are_created(self):
    #     before = len(POI.objects.all())
    #     self.cmd.execute(self.filename)
    #     after = len(POI.objects.all())
    #     self.assertEquals(after - before, 2)

    def test_create_pois_is_executed(self):
        with patch.object(Command, 'create_poi') as mocked:
            self.cmd.execute(self.filename)
            self.assertEquals(mocked.call_count, 2)

    def test_create_pois_receives_geometries(self):
        geom1 = call(GEOSGeometry('POINT(0 0)'))
        geom2 = call(GEOSGeometry('POINT(0 0)'))
        with patch.object(Command, 'create_poi') as mocked:
            self.cmd.execute(self.filename)
            self.assertEquals(mocked.call_list(), [geom1, geom2])
<commit_msg>Test reading of geometries from SHP<commit_after>import os
from StringIO import StringIO
from mock import patch, call

from django.core.management.base import CommandError
from django.test import TestCase
from django.contrib.gis.geos import GEOSGeometry

from geotrek.core.factories import PathFactory
from geotrek.trekking.models import POI
from geotrek.trekking.management.commands.loadpoi import Command

class LoadPOITest(TestCase):
    def setUp(self):
        self.cmd = Command()
        self.filename = os.path.join(os.path.dirname(__file__),
                                     'data', 'poi.shp')
        PathFactory.create()

    def test_command_fails_if_no_arg(self):
        self.assertRaises(CommandError, self.cmd.execute)

    def test_command_fails_if_too_many_args(self):
        self.assertRaises(CommandError, self.cmd.execute, 'a', 'b')

    def test_command_fails_if_filename_missing(self):
        self.assertRaises(CommandError, self.cmd.execute, 'toto.shp')

    def test_command_shows_number_of_objects(self):
        output = StringIO()
        self.cmd.execute(self.filename, stdout=output)
        self.assertIn('2 objects found', output.getvalue())

    # def test_pois_are_created(self):
    #     before = len(POI.objects.all())
    #     self.cmd.execute(self.filename)
    #     after = len(POI.objects.all())
    #     self.assertEquals(after - before, 2)

    def test_create_pois_is_executed(self):
        with patch.object(Command, 'create_poi') as mocked:
            self.cmd.execute(self.filename)
            self.assertEquals(mocked.call_count, 2)

    def test_create_pois_receives_geometries(self):
        geom1 = GEOSGeometry('POINT(-1.36308670782119 -5.98358469800134696)')
        geom2 = GEOSGeometry('POINT(-1.363087202331107 -5.98358423531846917)')
        with patch.object(Command, 'create_poi') as mocked:
            self.cmd.execute(self.filename)
            call1 = mocked.call_args_list[0][0]
            call2 = mocked.call_args_list[1][0]
            self.assertEquals(call1[0], geom1)
            self.assertEquals(call2[0], geom2)
<|endoftext|>


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

# KMHXcodeTools
# script.py
# Ken M. Haggerty
# CREATED: 2017 Mar 09
# EDITED:  2017 Apr 28

##### IMPORTS

from functions import *

##### INPUTS

filename = "Sample.xcodeproj/project.pbxproj"

##### CONSTANTS

directory = "source/"

##### CODE

print "---------- STARTING PYTHON ----------"

### Input

file = open(directory + filename, "r+")
text = "".join(file)

### Processing

order = processPBXProjOrder(text)

text = updatePBXBuildFileSection(text, order)
text = updatePBXFileReferenceSection(text, order)
text = updatePBXFrameworksBuildPhaseSection(text, order)
text = updatePBXGroupSection(text, order)
text = updatePBXResourcesBuildPhaseSection(text, order)
text = updatePBXSourcesBuildPhaseSection(text, order)

### Save To File

# file.seek(0)
# file.write(text)
# file.truncate()
# file.close()

print "---------- PYTHON COMPLETE ----------"
<commit_msg>Uncomments write-to-file in script.py.<commit_after>#!/usr/bin/env python

# KMHXcodeTools
# script.py
# Ken M. Haggerty
# CREATED: 2017 Mar 09
# EDITED:  2017 Apr 28

##### IMPORTS

from functions import *

##### INPUTS

filename = "Sample.xcodeproj/project.pbxproj"

##### CONSTANTS

directory = "source/"

##### CODE

print "---------- STARTING PYTHON ----------"

### Input

file = open(directory + filename, "r+")
text = "".join(file)

### Processing

order = processPBXProjOrder(text)

text = updatePBXBuildFileSection(text, order)
text = updatePBXFileReferenceSection(text, order)
text = updatePBXFrameworksBuildPhaseSection(text, order)
text = updatePBXGroupSection(text, order)
text = updatePBXResourcesBuildPhaseSection(text, order)
text = updatePBXSourcesBuildPhaseSection(text, order)

### Save To File

file.seek(0)
file.write(text)
file.truncate()
file.close()

print "---------- PYTHON COMPLETE ----------"
<|endoftext|>


<commit_before>#   Copyright (c) 2018 PaddlePaddle Authors. All Rights Reserved.
#
# 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 unittest
import numpy as np
import paddle.fluid.core as core
from paddle.fluid.op import Operator
from op_test import OpTest

class TestSGDOp(OpTest):
    def setUp(self):
        self.op_type = "sgd"
        w = np.random.random((102, 105)).astype("float32")
        g = np.random.random((102, 105)).astype("float32")
        lr = np.array([0.1]).astype("float32")

        self.inputs = {'Param': w, 'Grad': g, 'LearningRate': lr}
        self.outputs = {'ParamOut': w - lr * g}

    def test_check_output(self):
        self.check_output()

class TestSparseSGDOp(unittest.TestCase):
    def check_with_place(self, place):
        scope = core.Scope()

        # create and initialize Grad Variable
        height = 10
        rows = [0, 4, 7]
        row_numel = 12

        grad_selected_rows = scope.var('Grad').get_selected_rows()
        grad_selected_rows.set_height(height)
        grad_selected_rows.set_rows(rows)
        np_array = np.ones((len(rows), row_numel)).astype("float32")
        np_array[0, 0] = 2.0
        np_array[2, 8] = 4.0

        grad_tensor = grad_selected_rows.get_tensor()
        grad_tensor.set(np_array, place)

        # create and initialize Param Variable
        param = scope.var('Param').get_tensor()
        param_array = np.full((height, row_numel), 5.0).astype("float32")
        param.set(param_array, place)

        # create and initialize LeraningRate Variable
        lr = scope.var('LearningRate').get_tensor()
        lr_array = np.full((1), 2.0).astype("float32")
        lr.set(lr_array, place)

        # create and run sgd operator
        sgd_op = Operator(
            "sgd",
            Param='Param',
            Grad='Grad',
            ParamOut='Param',
            LearningRate='LearningRate')
        sgd_op.run(scope, place)

        # get and compare result
        result_array = np.array(param)

        # rows[0] = 0, 5.0 - 2.0 * 2.0
        self.assertAlmostEqual(1.0, result_array[rows[0], 0])
        # rows[0] = 0, 5.0 - 2.0 * 1.0
        self.assertAlmostEqual(3.0, result_array[rows[0], 2])
        # 5.0 - 2.0 * 0.0
        self.assertAlmostEqual(5.0, result_array[1, 0])
        # rows[1] = 4, 5.0 - 2.0 * 1.0
        self.assertAlmostEqual(3.0, result_array[rows[1], 10])
        # 5.0 - 2.0 * 0.0
        self.assertAlmostEqual(5.0, result_array[5, 8])
        # rows[2] = 7, 5.0 - 2.0 * 1.0
        self.assertAlmostEqual(3.0, result_array[rows[2], 1])
        # rows[2] = 7, 5.0 - 2.0 * 4.0
        self.assertAlmostEqual(-3.0, result_array[rows[2], 8])

    def test_sparse_sgd(self):
        places = [core.CPUPlace()]
        if core.is_compiled_with_cuda():
            places.append(core.CUDAPlace(0))
        for place in places:
            self.check_with_place(place)

if __name__ == "__main__":
    unittest.main()
<commit_msg>init TestSGDOpOptimizeSelectedRows<commit_after>#   Copyright (c) 2018 PaddlePaddle Authors. All Rights Reserved.
#
# 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 unittest
import numpy as np
import paddle.fluid.core as core
from paddle.fluid.op import Operator
from op_test import OpTest

class TestSGDOp(OpTest):
    def setUp(self):
        self.op_type = "sgd"
        w = np.random.random((102, 105)).astype("float32")
        g = np.random.random((102, 105)).astype("float32")
        lr = np.array([0.1]).astype("float32")

        self.inputs = {'Param': w, 'Grad': g, 'LearningRate': lr}
        self.outputs = {'ParamOut': w - lr * g}

    def test_check_output(self):
        self.check_output()

class TestSparseSGDOp(unittest.TestCase):
    def check_with_place(self, place):
        scope = core.Scope()

        # create and initialize Grad Variable
        height = 10
        rows = [0, 4, 7]
        row_numel = 12

        grad_selected_rows = scope.var('Grad').get_selected_rows()
        grad_selected_rows.set_height(height)
        grad_selected_rows.set_rows(rows)
        np_array = np.ones((len(rows), row_numel)).astype("float32")
        np_array[0, 0] = 2.0
        np_array[2, 8] = 4.0

        grad_tensor = grad_selected_rows.get_tensor()
        grad_tensor.set(np_array, place)

        # create and initialize Param Variable
        param = scope.var('Param').get_tensor()
        param_array = np.full((height, row_numel), 5.0).astype("float32")
        param.set(param_array, place)

        # create and initialize LeraningRate Variable
        lr = scope.var('LearningRate').get_tensor()
        lr_array = np.full((1), 2.0).astype("float32")
        lr.set(lr_array, place)

        # create and run sgd operator
        sgd_op = Operator(
            "sgd",
            Param='Param',
            Grad='Grad',
            ParamOut='Param',
            LearningRate='LearningRate')
        sgd_op.run(scope, place)

        # get and compare result
        result_array = np.array(param)

        # rows[0] = 0, 5.0 - 2.0 * 2.0
        self.assertAlmostEqual(1.0, result_array[rows[0], 0])
        # rows[0] = 0, 5.0 - 2.0 * 1.0
        self.assertAlmostEqual(3.0, result_array[rows[0], 2])
        # 5.0 - 2.0 * 0.0
        self.assertAlmostEqual(5.0, result_array[1, 0])
        # rows[1] = 4, 5.0 - 2.0 * 1.0
        self.assertAlmostEqual(3.0, result_array[rows[1], 10])
        # 5.0 - 2.0 * 0.0
        self.assertAlmostEqual(5.0, result_array[5, 8])
        # rows[2] = 7, 5.0 - 2.0 * 1.0
        self.assertAlmostEqual(3.0, result_array[rows[2], 1])
        # rows[2] = 7, 5.0 - 2.0 * 4.0
        self.assertAlmostEqual(-3.0, result_array[rows[2], 8])

    def test_sparse_sgd(self):
        places = [core.CPUPlace()]
        if core.is_compiled_with_cuda():
            places.append(core.CUDAPlace(0))
        for place in places:
            self.check_with_place(place)

class TestSGDOpOptimizeSelectedRows(unittest.TestCase):
    def check_with_place(self, place):
        scope = core.Scope()

        # create and initialize Grad Variable
        height = 10
        rows = [0, 4, 7]
        row_numel = 12

        grad_selected_rows = scope.var('Grad').get_selected_rows()
        grad_selected_rows.set_height(height)
        grad_selected_rows.set_rows(rows)
        np_array = np.ones((len(rows), row_numel)).astype("float32")
        np_array[0, 0] = 2.0
        np_array[2, 8] = 4.0

        grad_tensor = grad_selected_rows.get_tensor()
        grad_tensor.set(np_array, place)

        # create and initialize Param Variable
        param = scope.var('Param').get_tensor()
        param_array = np.full((height, row_numel), 5.0).astype("float32")
        param.set(param_array, place)

        # create and initialize LeraningRate Variable
        lr = scope.var('LearningRate').get_tensor()
        lr_array = np.full((1), 2.0).astype("float32")
        lr.set(lr_array, place)

        # create and run sgd operator
        sgd_op = Operator(
            "sgd",
            Param='Param',
            Grad='Grad',
            ParamOut='Param',
            LearningRate='LearningRate')
        sgd_op.run(scope, place)

        # get and compare result
        result_array = np.array(param)

        # rows[0] = 0, 5.0 - 2.0 * 2.0
        self.assertAlmostEqual(1.0, result_array[rows[0], 0])
        # rows[0] = 0, 5.0 - 2.0 * 1.0
        self.assertAlmostEqual(3.0, result_array[rows[0], 2])
        # 5.0 - 2.0 * 0.0
        self.assertAlmostEqual(5.0, result_array[1, 0])
        # rows[1] = 4, 5.0 - 2.0 * 1.0
        self.assertAlmostEqual(3.0, result_array[rows[1], 10])
        # 5.0 - 2.0 * 0.0
        self.assertAlmostEqual(5.0, result_array[5, 8])
        # rows[2] = 7, 5.0 - 2.0 * 1.0
        self.assertAlmostEqual(3.0, result_array[rows[2], 1])
        # rows[2] = 7, 5.0 - 2.0 * 4.0
        self.assertAlmostEqual(-3.0, result_array[rows[2], 8])

    def test_sparse_sgd(self):
        places = [core.CPUPlace()]
        if core.is_compiled_with_cuda():
            places.append(core.CUDAPlace(0))
        for place in places:
            self.check_with_place(place)

if __name__ == "__main__":
    unittest.main()
<|endoftext|>


<commit_before>
from __future__ import print_function

import sys
import re
import os.path
import subprocess
import argparse

import logging
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__)

import numpy as np

def check_qeb_args(x):
    if isinstance(x,tuple):
        return x
    m = re.match(r"^\((?P<f0>[0-9.e+-]+),(?P<Delta>[0-9.e+-]+),(?P<gamma>[0-9.e+-]+)\),(?P<Error>\d+)%$", x)
    if m is None:
        raise ValueError("check-qeb: expected argument in format \"(<f0>,<Delta>,<gamma>),<Error>%\"")
    return (float(m.group('f0')),float(m.group('Delta')),float(m.group('gamma')),float(m.group('Error'))/100.0)

def ftox_pair(ftoxstr):
    if isinstance(ftoxstr,tuple):
        return ftoxstr
    m = re.match(r"^\((?P<h>[0-9.e+-]+),(?P<s>[+-]?1)\)$", ftoxstr)
    if m is None:
        raise ValueError("ftox: expected \"(h,s)\" pair")
    return (float(m.group('h')), int(m.group('s')))

def percent_within_range_type(x):
    if isinstance(x, tuple):
        return x
    m = re.match(r"^(?P<percent>[0-9.e+-]+)%\s*\((?P<min>[0-9.e+-]+),\s*(?P<max>[0-9.e+-]+)\)$", x)
    if m is None:
        raise ValueError("percent_within_range: expected \"<percent>% (<min>,<max>)\" format")
    return (float(m.group('percent')), float(m.group('min')), float(m.group('max')))

def run_main():
    parser = argparse.ArgumentParser("test_tomorun_run")
    parser.add_argument("tomorun_argv", nargs='+')
    parser.add_argument("--setpath", action='store')
    parser.add_argument("--expect-exit-code", action='store', type=int, default=0)
    parser.add_argument("--no-further-checks", action='store_true', default=False)
    parser.add_argument("--check-histogram-file", action='store', default=None)
    parser.add_argument("--check-qeb", action='store', type=check_qeb_args)
    parser.add_argument("--use-qeb-hint", action='store_true', default=False)
    parser.add_argument("--ftox", action='store', type=ftox_pair, default=(0,1,))
    parser.add_argument("--check-percent-within-range", action='append', type=percent_within_range_type)

    args = parser.parse_args()

    # setup sys.path, if needed
    if hasattr(args,'setpath') and args.setpath is not None:
        for p in reversed(args.setpath.split(':')):
            if p:
                sys.path.insert(0, p)
        logger.debug("Set sys.path = {!r}".format(sys.path))

    # first, launch the tomorun process
    try:
        logger.debug("Launching tomorun process with argv={!r}".format(args.tomorun_argv))
        subprocess.check_call(args.tomorun_argv)
    except subprocess.CalledProcessError as e:
        if e.returncode != args.expect_exit_code:
            raise
        logger.debug("Got the expected return code %d"%(args.expect_exit_code))

    did_check = False

    # load the output histogram
    if args.check_histogram_file:

        if hasattr(args,'check_qeb') and args.check_qeb is not None:

            # check the quantum error bars
            do_check_qeb(args.check_histogram_file, args.check_qeb, ftox=args.ftox, use_qeb_hint=args.use_qeb_hint)
            did_check = True

        if hasattr(args,'check_percent_within_range') and args.check_percent_within_range is not None:

            # check that a certain percentatge of the total weight falls within the given
            # range (can be a list of ranges), if the option is specified multiple times
            for check_rng in args.check_percent_within_range:
                do_check_percent_within_range(args.check_histogram_file, check_rng)
            did_check = True

    if args.no_further_checks:
        return

    if not did_check:
        raise RuntimeError("Didn't check anything.")

def assert_approx_eq_rel(x, y, err):
    print("Testing {!r} =? {!r}  (to {!r} rel. precision) ...".format(x,y,err), end='')
    refom = np.maximum(np.absolute(x),np.absolute(y))
    assert np.absolute(x-y) < err*refom
    print(" OK")

def do_check_percent_within_range(hfile, percent_within_range):
    # only import tomographer here, after possibly having set sys.path
    import tomographer as t
    import tomographer.querrorbars as tq
    logger.debug("Loaded tomographer from {} and tomographer.querrorbars from {}".format(t.__path__, tq.__file__))

    h = tq.load_tomorun_csv_histogram_file(hfile)

    percent, rngmin, rngmax = percent_within_range

    if h.params.isWithinBounds(rngmin):
        idxmin = h.params.binIndex(rngmin)
    else:
        idxmin = 0
    if h.params.isWithinBounds(rngmax):
        idxmax = h.params.binIndex(rngmax)
    else:
        idxmax = h.numBins()-1

    w = np.sum(h.bins[idxmin:idxmax])

    logger.debug("Total weight within [{:.4g},{:.4g}] is {:.3g}%; required is {:.3g}%"
                 .format(rngmin,rngmax, w*100.0, percent))

    print("Testing {!r} > {!r} ... ".format(w, percent/100.0), end='')
    assert w > percent/100.0
    print(" OK")

def do_check_qeb(hfile, refqeb, ftox, use_qeb_hint):
    # only import tomographer here, after possibly having set sys.path
    import tomographer as t
    import tomographer.querrorbars as tq
    logger.debug("Loaded tomographer from {} and tomographer.querrorbars from {}".format(t.__path__, tq.__file__))

    h = tq.load_tomorun_csv_histogram_file(hfile)

    kwargs = {}
    if use_qeb_hint:
        kwargs['p0'] = tq.reskew_logmu_curve(*qu_error_bars_to_deskewed_c(ftox, *(refqeb[:3]),
                                                                          y0=np.maximum(h.bins)))
    a = tq.HistogramAnalysis(h, ftox=ftox, **kwargs)

    # make sure the fit was ok
    redchi2 = a.fitRedChi2()
    logger.debug("redchi2 = {:.4g}".format(redchi2))
    assert_approx_eq_rel(redchi2, 1.0, 0.5) # 0.5--1.5

    a.printQuantumErrorBars(print_func=logger.debug)
    qeb = a.quantumErrorBars()

    assert_approx_eq_rel(qeb.f0, refqeb[0], refqeb[3])
    assert_approx_eq_rel(qeb.Delta, refqeb[1], refqeb[3])
    assert_approx_eq_rel(qeb.gamma, refqeb[2], refqeb[3])

if __name__ == '__main__':
    run_main()
<commit_msg>fixed test script<commit_after>
from __future__ import print_function

import sys
import re
import os.path
import subprocess
import argparse

import logging
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__)

import numpy as np

def check_qeb_args(x):
    if isinstance(x,tuple):
        return x
    m = re.match(r"^\((?P<f0>[0-9.e+-]+),(?P<Delta>[0-9.e+-]+),(?P<gamma>[0-9.e+-]+)\),(?P<Error>\d+)%$", x)
    if m is None:
        raise ValueError("check-qeb: expected argument in format \"(<f0>,<Delta>,<gamma>),<Error>%\"")
    return (float(m.group('f0')),float(m.group('Delta')),float(m.group('gamma')),float(m.group('Error'))/100.0)

def ftox_pair(ftoxstr):
    if isinstance(ftoxstr,tuple):
        return ftoxstr
    m = re.match(r"^\((?P<h>[0-9.e+-]+),(?P<s>[+-]?1)\)$", ftoxstr)
    if m is None:
        raise ValueError("ftox: expected \"(h,s)\" pair")
    return (float(m.group('h')), int(m.group('s')))

def percent_within_range_type(x):
    if isinstance(x, tuple):
        return x
    m = re.match(r"^(?P<percent>[0-9.e+-]+)%\s*\((?P<min>[0-9.e+-]+),\s*(?P<max>[0-9.e+-]+)\)$", x)
    if m is None:
        raise ValueError("percent_within_range: expected \"<percent>% (<min>,<max>)\" format")
    return (float(m.group('percent')), float(m.group('min')), float(m.group('max')))

def run_main():
    parser = argparse.ArgumentParser("test_tomorun_run")
    parser.add_argument("tomorun_argv", nargs='+')
    parser.add_argument("--setpath", action='store')
    parser.add_argument("--expect-exit-code", action='store', type=int, default=0)
    parser.add_argument("--no-further-checks", action='store_true', default=False)
    parser.add_argument("--check-histogram-file", action='store', default=None)
    parser.add_argument("--check-qeb", action='store', type=check_qeb_args)
    parser.add_argument("--use-qeb-hint", action='store_true', default=False)
    parser.add_argument("--ftox", action='store', type=ftox_pair, default=(0,1,))
    parser.add_argument("--check-percent-within-range", action='append', type=percent_within_range_type)

    args = parser.parse_args()

    # setup sys.path, if needed
    if hasattr(args,'setpath') and args.setpath is not None:
        for p in reversed(args.setpath.split(':')):
            if p:
                sys.path.insert(0, p)
        logger.debug("Set sys.path = {!r}".format(sys.path))

    # first, launch the tomorun process
    try:
        logger.debug("Launching tomorun process with argv={!r}".format(args.tomorun_argv))
        subprocess.check_call(args.tomorun_argv)
    except subprocess.CalledProcessError as e:
        if e.returncode != args.expect_exit_code:
            raise
        logger.debug("Got the expected return code %d"%(args.expect_exit_code))

    did_check = False

    # load the output histogram
    if args.check_histogram_file:

        if hasattr(args,'check_qeb') and args.check_qeb is not None:

            # check the quantum error bars
            do_check_qeb(args.check_histogram_file, args.check_qeb, ftox=args.ftox, use_qeb_hint=args.use_qeb_hint)
            did_check = True

        if hasattr(args,'check_percent_within_range') and args.check_percent_within_range is not None:

            # check that a certain percentatge of the total weight falls within the given
            # range (can be a list of ranges), if the option is specified multiple times
            for check_rng in args.check_percent_within_range:
                do_check_percent_within_range(args.check_histogram_file, check_rng)
            did_check = True

    if args.no_further_checks:
        return

    if not did_check:
        raise RuntimeError("Didn't check anything.")

def assert_approx_eq_rel(x, y, err):
    print("Testing {!r} =? {!r}  (to {!r} rel. precision) ...".format(x,y,err), end='')
    refom = np.maximum(np.absolute(x),np.absolute(y))
    assert np.absolute(x-y) < err*refom
    print(" OK")

def do_check_percent_within_range(hfile, percent_within_range):
    # only import tomographer here, after possibly having set sys.path
    import tomographer as t
    import tomographer.querrorbars as tq
    logger.debug("Loaded tomographer from {} and tomographer.querrorbars from {}".format(t.__path__, tq.__file__))

    h = tq.load_tomorun_csv_histogram_file(hfile)

    percent, rngmin, rngmax = percent_within_range

    if h.params.isWithinBounds(rngmin):
        idxmin = h.params.binIndex(rngmin)
    else:
        idxmin = 0
    if h.params.isWithinBounds(rngmax):
        idxmax = h.params.binIndex(rngmax)
    else:
        idxmax = h.numBins()-1

    w = np.sum(h.bins[idxmin:idxmax])

    logger.debug("Total weight within [{:.4g},{:.4g}] is {:.3g}%; required is {:.3g}%"
                 .format(rngmin,rngmax, w*100.0, percent))

    print("Testing {!r} > {!r} ... ".format(w, percent/100.0), end='')
    assert w > percent/100.0
    print(" OK")

def do_check_qeb(hfile, refqeb, ftox, use_qeb_hint):
    # only import tomographer here, after possibly having set sys.path
    import tomographer as t
    import tomographer.querrorbars as tq
    logger.debug("Loaded tomographer from {} and tomographer.querrorbars from {}".format(t.__path__, tq.__file__))

    h = tq.load_tomorun_csv_histogram_file(hfile)

    kwargs = {}
    if use_qeb_hint:
        ftoxfn = lambda f: ftox[1]*(f - ftox[0])
        kwargs['p0'] = tq.reskew_logmu_curve(*tq.qu_error_bars_to_deskewed_c(ftoxfn, *(refqeb[:3]),
                                                                             y0=np.amax(h.bins)))
    a = tq.HistogramAnalysis(h, ftox=ftox, **kwargs)

    # make sure the fit was ok
    redchi2 = a.fitRedChi2()
    logger.debug("redchi2 = {:.4g}".format(redchi2))
    assert_approx_eq_rel(redchi2, 1.0, 0.5) # 0.5--1.5

    a.printQuantumErrorBars(print_func=logger.debug)
    qeb = a.quantumErrorBars()

    assert_approx_eq_rel(qeb.f0, refqeb[0], refqeb[3])
    assert_approx_eq_rel(qeb.Delta, refqeb[1], refqeb[3])
    assert_approx_eq_rel(qeb.gamma, refqeb[2], refqeb[3])

if __name__ == '__main__':
    run_main()
<|endoftext|>


<commit_before># Copyright 2013 Christoph Reiter
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.

from pgi.gir import GITypeTag, GIDirection, GITransfer, GIInfoType

class CallbackArgument(object):
    TAG = None

    is_aux = False
    py_type = None

    def __init__(self, backend, info, type_, name):
        self.info = info
        self.name = name
        self.backend = backend
        self.type = type_

    @classmethod
    def get_class(cls):
        return cls

    def setup(self):
        pass

    def process(self):
        return None, self.name

    def may_be_null(self):
        return self.info.may_be_null

    def is_direction_in(self):
        return self.direction in (GIDirection.INOUT, GIDirection.IN)

    def is_direction_out(self):
        return self.direction in (GIDirection.INOUT, GIDirection.OUT)

    def is_direction_inout(self):
        return self.direction == GIDirection.INOUT

    def transfer_nothing(self):
        return self.info.ownership_transfer.value == GITransfer.NOTHING

    def transfer_container(self):
        return self.info.ownership_transfer.value == GITransfer.CONTAINER

    def transfer_everything(self):
        return self.info.ownership_transfer.value == GITransfer.EVERYTHING

class InterfaceArgument(CallbackArgument):
    TAG = GITypeTag.INTERFACE
    py_type = object

    def process(self):
        iface = self.type.get_interface()
        iface_type = iface.type.value
        var = self.backend.get_type(self.type)

        if iface_type == GIInfoType.STRUCT or iface_type == GIInfoType.UNION:
            out = var.unpack(self.name)
        else:
            out = var.unpack_null(self.name)
        return var.block, out

class Utf8Argument(CallbackArgument):
    TAG = GITypeTag.UTF8
    py_type = str

class VoidArgument(CallbackArgument):
    TAG = GITypeTag.VOID
    py_type = int

_classes = {}

def _find_cbargs():
    global _classes
    for var in globals().values():
        if not isinstance(var, type):
            continue
        if issubclass(var, CallbackArgument) and var is not CallbackArgument:
            _classes[var.TAG] = var
_find_cbargs()

def get_cbarg_class(arg_type):
    global _classes
    tag_value = arg_type.tag.value
    try:
        cls = _classes[tag_value]
    except KeyError:
        raise NotImplementedError(
            "%r signal argument not implemented" % arg_type.tag)
    else:
        return cls.get_class()
<commit_msg>fix signal marshal<commit_after># Copyright 2013 Christoph Reiter
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.

from pgi.gir import GITypeTag, GIDirection, GITransfer, GIInfoType

class CallbackArgument(object):
    TAG = None

    is_aux = False
    py_type = None

    def __init__(self, backend, info, type_, name):
        self.info = info
        self.name = name
        self.backend = backend
        self.type = type_

    @classmethod
    def get_class(cls):
        return cls

    def setup(self):
        pass

    def process(self):
        return None, self.name

    def is_direction_in(self):
        return self.direction in (GIDirection.INOUT, GIDirection.IN)

    def is_direction_out(self):
        return self.direction in (GIDirection.INOUT, GIDirection.OUT)

    def is_direction_inout(self):
        return self.direction == GIDirection.INOUT

    def transfer_nothing(self):
        return self.info.ownership_transfer.value == GITransfer.NOTHING

    def transfer_container(self):
        return self.info.ownership_transfer.value == GITransfer.CONTAINER

    def transfer_everything(self):
        return self.info.ownership_transfer.value == GITransfer.EVERYTHING

class InterfaceArgument(CallbackArgument):
    TAG = GITypeTag.INTERFACE
    py_type = object

    def process(self):
        iface = self.type.get_interface()
        iface_type = iface.type.value
        var = self.backend.get_type(self.type)

        out = var.unpack(self.name)

        return var.block, out

class Utf8Argument(CallbackArgument):
    TAG = GITypeTag.UTF8
    py_type = str

class VoidArgument(CallbackArgument):
    TAG = GITypeTag.VOID
    py_type = int

_classes = {}

def _find_cbargs():
    global _classes
    for var in globals().values():
        if not isinstance(var, type):
            continue
        if issubclass(var, CallbackArgument) and var is not CallbackArgument:
            _classes[var.TAG] = var
_find_cbargs()

def get_cbarg_class(arg_type):
    global _classes
    tag_value = arg_type.tag.value
    try:
        cls = _classes[tag_value]
    except KeyError:
        raise NotImplementedError(
            "%r signal argument not implemented" % arg_type.tag)
    else:
        return cls.get_class()
<|endoftext|>