{"action":"created","comment":{"url":"https://api.github.com/repos/matplotlib/matplotlib/pulls/comments/23330690","id":23330690,"diff_hunk":"@@ -0,0 +1,928 @@\n+\"\"\"\n+Abstract base classes define the primitives for Tools.\n+These tools are used by `NavigationBase`\n+\n+:class:`ToolBase`\n+    Simple stateless tool\n+\n+:class:`ToolToggleBase`\n+    Tool that has two states, only one Toggle tool can be\n+    active at any given time for the same `Navigation`\n+\"\"\"\n+\n+\n+from matplotlib import rcParams\n+from matplotlib._pylab_helpers import Gcf\n+import matplotlib.cbook as cbook\n+from weakref import WeakKeyDictionary\n+import numpy as np\n+\n+\n+class Cursors(object):\n+    \"\"\"Simple namespace for cursor reference\"\"\"\n+    HAND, POINTER, SELECT_REGION, MOVE = list(range(4))\n+cursors = Cursors()\n+\n+\n+class ToolBase(object):\n+    \"\"\"Base tool class\n+\n+    A base tool, only implements `trigger` method or not method at all.\n+    The tool is instantiated by `matplotlib.backend_bases.NavigationBase`\n+\n+    Attributes\n+    ----------\n+    navigation: `matplotlib.backend_bases.NavigationBase`\n+        Navigation that controls this Tool\n+    figure: `FigureCanvas`\n+        Figure instance that is affected by this Tool\n+    name: String\n+        Used as **Id** of the tool, has to be unique among tools of the same\n+        Navigation\n+    \"\"\"\n+\n+    keymap = None\n+    \"\"\"Keymap to associate with this tool\n+\n+    **String**: List of comma separated keys that will be used to call this\n+    tool when the keypress event of *self.figure.canvas* is emited\n+    \"\"\"\n+\n+    description = None\n+    \"\"\"Description of the Tool\n+\n+    **String**: If the Tool is included in the Toolbar this text is used\n+    as a Tooltip\n+    \"\"\"\n+\n+    image = None\n+    \"\"\"Filename of the image\n+\n+    **String**: Filename of the image to use in the toolbar. If None, the\n+    `name` is used as a label in the toolbar button\n+    \"\"\"\n+\n+    def __init__(self, navigation, name):\n+        self._name = name\n+        self.figure = None\n+        self.navigation = navigation\n+        self.set_figure(navigation.canvas.figure)\n+\n+    def trigger(self, sender, event, data=None):\n+        \"\"\"Called when this tool gets used\n+\n+        This method is called by\n+        `matplotlib.backend_bases.NavigationBase.tool_trigger_event`\n+\n+        Parameters\n+        ----------\n+        event : `Event`\n+            The Canvas event that caused this tool to be called\n+        sender: object\n+            Object that requested the tool to be triggered\n+        data: object\n+            Extra data\n+        \"\"\"\n+\n+        pass\n+\n+    def set_figure(self, figure):\n+        \"\"\"Set the figure\n+\n+        Set the figure to be affected by this tool\n+\n+        Parameters\n+        ----------\n+        figure : `Figure`\n+        \"\"\"\n+\n+        self.figure = figure\n+\n+    @property\n+    def name(self):\n+        \"\"\"Tool Id\"\"\"\n+        return self._name\n+\n+    def destroy(self):\n+        \"\"\"Destroy the tool\n+\n+        This method is called when the tool is removed by\n+        `matplotlib.backend_bases.NavigationBase.remove_tool`\n+        \"\"\"\n+        pass\n+\n+\n+class ToolToggleBase(ToolBase):\n+    \"\"\"Toggleable tool\n+\n+    Every time it is triggered, it switches between enable and disable\n+    \"\"\"\n+\n+    radio_group = None\n+    \"\"\"Attribute to group 'radio' like tools (mutually exclusive)\n+\n+    **String** that identifies the group or **None** if not belonging to a\n+    group\n+    \"\"\"\n+\n+    cursor = None\n+    \"\"\"Cursor to use when the tool is active\"\"\"\n+\n+    def __init__(self, *args, **kwargs):\n+        ToolBase.__init__(self, *args, **kwargs)\n+        self._toggled = False\n+\n+    def trigger(self, sender, event, data=None):\n+        \"\"\"Calls `enable` or `disable` based on `toggled` value\"\"\"\n+        if self._toggled:\n+            self.disable(event)\n+        else:\n+            self.enable(event)\n+        self._toggled = not self._toggled\n+\n+    def enable(self, event=None):\n+        \"\"\"Enable the toggle tool\n+\n+        `trigger` calls this method when `toggled` is False\n+        \"\"\"\n+\n+        pass\n+\n+    def disable(self, event=None):\n+        \"\"\"Disable the toggle tool\n+\n+        `trigger` call this methond when `toggled` is True.\n+\n+        This can happen in different circumstances\n+\n+        * Click on the toolbar tool button\n+        * Call to `matplotlib.backend_bases.NavigationBase.tool_trigger_event`\n+        * Another `ToolToggleBase` derived tool is triggered\n+          (from the same `Navigation`)\n+        \"\"\"\n+\n+        pass\n+\n+    @property\n+    def toggled(self):\n+        \"\"\"State of the toggled tool\"\"\"\n+\n+        return self._toggled\n+\n+\n+class SetCursorBase(ToolBase):\n+    \"\"\"Change to the current cursor while inaxes\n+\n+    This tool, keeps track of all `ToolToggleBase` derived tools, and calls\n+    set_cursor when a tool gets triggered\n+    \"\"\"\n+    def __init__(self, *args, **kwargs):\n+        ToolBase.__init__(self, *args, **kwargs)\n+        self._idDrag = self.figure.canvas.mpl_connect(\n+            'motion_notify_event', self._set_cursor_cbk)\n+        self._cursor = None\n+        self._default_cursor = cursors.POINTER\n+        self._last_cursor = self._default_cursor\n+        self.navigation.mpl_connect('tool_added_event', self._add_tool_cbk)\n+\n+        # process current tools\n+        for tool in self.navigation.tools.values():\n+            self._add_tool(tool)\n+\n+    def _tool_trigger_cbk(self, event):\n+        if event.tool.toggled:\n+            self._cursor = event.tool.cursor\n+        else:\n+            self._cursor = None\n+\n+        self._set_cursor_cbk(event.canvasevent)\n+\n+    # If the tool is toggleable, set the cursor when the tool is triggered\n+    def _add_tool(self, tool):\n+        if getattr(tool, 'cursor', None) is not None:\n+            self.navigation.mpl_connect('tool_trigger_%s' % tool.name,\n+                                        self._tool_trigger_cbk)\n+\n+    # If tool is added, process it\n+    def _add_tool_cbk(self, event):\n+        if event.tool is self:\n+            return\n+\n+        self._add_tool(event.tool)\n+\n+    def _set_cursor_cbk(self, event):\n+        if not event:\n+            return\n+\n+        if not getattr(event, 'inaxes', False) or not self._cursor:\n+            if self._last_cursor != self._default_cursor:\n+                self.set_cursor(self._default_cursor)\n+                self._last_cursor = self._default_cursor\n+        else:\n+            if self._cursor:\n+                cursor = self._cursor\n+                if cursor and self._last_cursor != cursor:\n+                    self.set_cursor(cursor)\n+                    self._last_cursor = cursor\n+\n+    def set_cursor(self, cursor):\n+        \"\"\"Set the cursor\n+\n+        This method has to be implemented per backend\n+        \"\"\"\n+        pass\n+\n+\n+class ToolCursorPosition(ToolBase):\n+    \"\"\"Send message with the current pointer position\n+\n+    This tool runs in the background reporting the position of the cursor\n+    \"\"\"\n+    def __init__(self, *args, **kwargs):\n+        ToolBase.__init__(self, *args, **kwargs)\n+        self._idDrag = self.figure.canvas.mpl_connect(\n+            'motion_notify_event', self.send_message)\n+\n+    def send_message(self, event):\n+        \"\"\"Call `matplotlib.backend_bases.NavigationBase.message_event`\"\"\"\n+        if self.navigation.messagelock.locked():\n+            return\n+\n+        message = ' '\n+\n+        if event.inaxes and event.inaxes.get_navigate():\n+            try:\n+                s = event.inaxes.format_coord(event.xdata, event.ydata)\n+            except (ValueError, OverflowError):\n+                pass\n+            else:\n+                message = s\n+        self.navigation.message_event(message, self)\n+\n+\n+class RubberbandBase(ToolBase):\n+    \"\"\"Draw and remove rubberband\"\"\"\n+    def trigger(self, sender, event, data):\n+        \"\"\"Call `draw_rubberband` or `remove_rubberband` based on data\"\"\"\n+        if not self.figure.canvas.widgetlock.available(sender):\n+            return\n+        if data is not None:\n+            self.draw_rubberband(*data)\n+        else:\n+            self.remove_rubberband()\n+\n+    def draw_rubberband(self, *data):\n+        \"\"\"Draw rubberband\n+\n+        This method must get implemented per backend\n+        \"\"\"\n+        pass\n+\n+    def remove_rubberband(self):\n+        \"\"\"Remove rubberband\n+\n+        This method must get implemented per backend\n+        \"\"\"\n+        pass\n+\n+\n+class ToolQuit(ToolBase):\n+    \"\"\"Tool to call the figure manager destroy method\"\"\"\n+\n+    description = 'Quit the figure'\n+    keymap = rcParams['keymap.quit']\n+\n+    def trigger(self, sender, event, data=None):\n+        Gcf.destroy_fig(self.figure)\n+\n+\n+class ToolEnableAllNavigation(ToolBase):\n+    \"\"\"Tool to enable all axes for navigation interaction\"\"\"\n+\n+    description = 'Enables all axes navigation'\n+    keymap = rcParams['keymap.all_axes']\n+\n+    def trigger(self, sender, event, data=None):\n+        if event.inaxes is None:\n+            return\n+\n+        for a in self.figure.get_axes():\n+            if event.x is not None and event.y is not None \\\n+                    and a.in_axes(event):\n+                a.set_navigate(True)\n+\n+\n+class ToolEnableNavigation(ToolBase):\n+    \"\"\"Tool to enable a specific axes for navigation interaction\"\"\"\n+\n+    description = 'Enables one axes navigation'\n+    keymap = (1, 2, 3, 4, 5, 6, 7, 8, 9)\n+\n+    def trigger(self, sender, event, data=None):\n+        if event.inaxes is None:\n+            return\n+\n+        n = int(event.key) - 1\n+        for i, a in enumerate(self.figure.get_axes()):\n+            # consider axes, in which the event was raised\n+            # FIXME: Why only this axes?\n+            if event.x is not None and event.y is not None \\\n+                    and a.in_axes(event):\n+                    a.set_navigate(i == n)\n+\n+\n+class ToolGrid(ToolToggleBase):\n+    \"\"\"Tool to toggle the grid of the figure\"\"\"\n+\n+    description = 'Toogle Grid'\n+    keymap = rcParams['keymap.grid']\n+\n+    def trigger(self, sender, event, data=None):\n+        if event.inaxes is None:\n+            return\n+        ToolToggleBase.trigger(self, sender, event, data)\n+\n+    def enable(self, event):\n+        event.inaxes.grid(True)\n+        self.figure.canvas.draw()","path":"lib/matplotlib/backend_tools.py","position":null,"original_position":347,"commit_id":"737e9604d462f46eb62f412856e32e818d294339","original_commit_id":"d13c34653e7b32e3c1558c14dd9b38999a32ee42","user":{"login":"WeatherGod","id":291576,"avatar_url":"https://avatars.githubusercontent.com/u/291576?v=3","gravatar_id":"","url":"https://api.github.com/users/WeatherGod","html_url":"https://github.com/WeatherGod","followers_url":"https://api.github.com/users/WeatherGod/followers","following_url":"https://api.github.com/users/WeatherGod/following{/other_user}","gists_url":"https://api.github.com/users/WeatherGod/gists{/gist_id}","starred_url":"https://api.github.com/users/WeatherGod/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/WeatherGod/subscriptions","organizations_url":"https://api.github.com/users/WeatherGod/orgs","repos_url":"https://api.github.com/users/WeatherGod/repos","events_url":"https://api.github.com/users/WeatherGod/events{/privacy}","received_events_url":"https://api.github.com/users/WeatherGod/received_events","type":"User","site_admin":false},"body":"with respect to key_press_handler, it isn't implementing a method called\r\n\"mpl_connect\". It is using the mpl_connect because the default keypress\r\nhandler is getting connected to the canvas's callback registry. This is a\r\ndifferent callback registry. Elsewhere in mpl, we have widgets and other\r\nthings that instantiate their own callback registry, and they do not create\r\na method called mpl_connect() to add to it. I would just go with\r\n\"connect()\", but \"nav_connect()\" is fine, too.\r\n\r\nOn Wed, Jan 21, 2015 at 3:06 PM, Federico Ariza <notifications@github.com>\r\nwrote:\r\n\r\n> In lib/matplotlib/backend_tools.py\r\n> <https://github.com/matplotlib/matplotlib/pull/3652#discussion_r23329795>:\r\n>\r\n> > +\r\n> > +\r\n> > +class ToolGrid(ToolToggleBase):\r\n> > +    \"\"\"Tool to toggle the grid of the figure\"\"\"\r\n> > +\r\n> > +    description = 'Toogle Grid'\r\n> > +    keymap = rcParams['keymap.grid']\r\n> > +\r\n> > +    def trigger(self, sender, event, data=None):\r\n> > +        if event.inaxes is None:\r\n> > +            return\r\n> > +        ToolToggleBase.trigger(self, sender, event, data)\r\n> > +\r\n> > +    def enable(self, event):\r\n> > +        event.inaxes.grid(True)\r\n> > +        self.figure.canvas.draw()\r\n>\r\n> No problem, I'll change that, it is this way in key_press_handler\r\n> implementation, all I did was a (copy/paste)\r\n>\r\n> —\r\n> Reply to this email directly or view it on GitHub\r\n> <https://github.com/matplotlib/matplotlib/pull/3652/files#r23329795>.\r\n>","created_at":"2015-01-21T20:16:52Z","updated_at":"2015-01-21T20:16:52Z","html_url":"https://github.com/matplotlib/matplotlib/pull/3652#discussion_r23330690","pull_request_url":"https://api.github.com/repos/matplotlib/matplotlib/pulls/3652","_links":{"self":{"href":"https://api.github.com/repos/matplotlib/matplotlib/pulls/comments/23330690"},"html":{"href":"https://github.com/matplotlib/matplotlib/pull/3652#discussion_r23330690"},"pull_request":{"href":"https://api.github.com/repos/matplotlib/matplotlib/pulls/3652"}}},"pull_request":{"url":"https://api.github.com/repos/matplotlib/matplotlib/pulls/3652","id":22889335,"html_url":"https://github.com/matplotlib/matplotlib/pull/3652","diff_url":"https://github.com/matplotlib/matplotlib/pull/3652.diff","patch_url":"https://github.com/matplotlib/matplotlib/pull/3652.patch","issue_url":"https://api.github.com/repos/matplotlib/matplotlib/issues/3652","number":3652,"state":"open","locked":false,"title":"MEP22: Navigation by events","user":{"login":"fariza","id":1490153,"avatar_url":"https://avatars.githubusercontent.com/u/1490153?v=3","gravatar_id":"","url":"https://api.github.com/users/fariza","html_url":"https://github.com/fariza","followers_url":"https://api.github.com/users/fariza/followers","following_url":"https://api.github.com/users/fariza/following{/other_user}","gists_url":"https://api.github.com/users/fariza/gists{/gist_id}","starred_url":"https://api.github.com/users/fariza/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/fariza/subscriptions","organizations_url":"https://api.github.com/users/fariza/orgs","repos_url":"https://api.github.com/users/fariza/repos","events_url":"https://api.github.com/users/fariza/events{/privacy}","received_events_url":"https://api.github.com/users/fariza/received_events","type":"User","site_admin":false},"body":"This PR is the implementation of MEP22, it supersedes the https://github.com/matplotlib/matplotlib/pull/2759\r\n\r\nThe main differences are:\r\n* Navigation implement events\r\n* Toolbar connects to Navigation events to change its sate (add/remove tools, change toggle state)\r\n* Toolbar used `Navigation.tool_trigger_event` to trigger tools\r\n* Rubberband and SetCursor are implemented as tools\r\n\r\n**Edited**: for clarity","created_at":"2014-10-16T21:45:29Z","updated_at":"2015-01-21T20:16:52Z","closed_at":null,"merged_at":null,"merge_commit_sha":"0ec276e84b7b49269690e48cad70341d22a27779","assignee":null,"milestone":{"url":"https://api.github.com/repos/matplotlib/matplotlib/milestones/12","labels_url":"https://api.github.com/repos/matplotlib/matplotlib/milestones/12/labels","id":534144,"number":12,"title":"v1.5.x","description":null,"creator":{"login":"tacaswell","id":199813,"avatar_url":"https://avatars.githubusercontent.com/u/199813?v=3","gravatar_id":"","url":"https://api.github.com/users/tacaswell","html_url":"https://github.com/tacaswell","followers_url":"https://api.github.com/users/tacaswell/followers","following_url":"https://api.github.com/users/tacaswell/following{/other_user}","gists_url":"https://api.github.com/users/tacaswell/gists{/gist_id}","starred_url":"https://api.github.com/users/tacaswell/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tacaswell/subscriptions","organizations_url":"https://api.github.com/users/tacaswell/orgs","repos_url":"https://api.github.com/users/tacaswell/repos","events_url":"https://api.github.com/users/tacaswell/events{/privacy}","received_events_url":"https://api.github.com/users/tacaswell/received_events","type":"User","site_admin":false},"open_issues":245,"closed_issues":146,"state":"open","created_at":"2014-01-13T03:21:09Z","updated_at":"2015-01-20T16:22:13Z","due_on":null,"closed_at":null},"commits_url":"https://api.github.com/repos/matplotlib/matplotlib/pulls/3652/commits","review_comments_url":"https://api.github.com/repos/matplotlib/matplotlib/pulls/3652/comments","review_comment_url":"https://api.github.com/repos/matplotlib/matplotlib/pulls/comments/{number}","comments_url":"https://api.github.com/repos/matplotlib/matplotlib/issues/3652/comments","statuses_url":"https://api.github.com/repos/matplotlib/matplotlib/statuses/737e9604d462f46eb62f412856e32e818d294339","head":{"label":"fariza:navigation-by-events","ref":"navigation-by-events","sha":"737e9604d462f46eb62f412856e32e818d294339","user":{"login":"fariza","id":1490153,"avatar_url":"https://avatars.githubusercontent.com/u/1490153?v=3","gravatar_id":"","url":"https://api.github.com/users/fariza","html_url":"https://github.com/fariza","followers_url":"https://api.github.com/users/fariza/followers","following_url":"https://api.github.com/users/fariza/following{/other_user}","gists_url":"https://api.github.com/users/fariza/gists{/gist_id}","starred_url":"https://api.github.com/users/fariza/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/fariza/subscriptions","organizations_url":"https://api.github.com/users/fariza/orgs","repos_url":"https://api.github.com/users/fariza/repos","events_url":"https://api.github.com/users/fariza/events{/privacy}","received_events_url":"https://api.github.com/users/fariza/received_events","type":"User","site_admin":false},"repo":{"id":12761338,"name":"matplotlib","full_name":"fariza/matplotlib","owner":{"login":"fariza","id":1490153,"avatar_url":"https://avatars.githubusercontent.com/u/1490153?v=3","gravatar_id":"","url":"https://api.github.com/users/fariza","html_url":"https://github.com/fariza","followers_url":"https://api.github.com/users/fariza/followers","following_url":"https://api.github.com/users/fariza/following{/other_user}","gists_url":"https://api.github.com/users/fariza/gists{/gist_id}","starred_url":"https://api.github.com/users/fariza/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/fariza/subscriptions","organizations_url":"https://api.github.com/users/fariza/orgs","repos_url":"https://api.github.com/users/fariza/repos","events_url":"https://api.github.com/users/fariza/events{/privacy}","received_events_url":"https://api.github.com/users/fariza/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/fariza/matplotlib","description":"matplotlib: plotting with Python","fork":true,"url":"https://api.github.com/repos/fariza/matplotlib","forks_url":"https://api.github.com/repos/fariza/matplotlib/forks","keys_url":"https://api.github.com/repos/fariza/matplotlib/keys{/key_id}","collaborators_url":"https://api.github.com/repos/fariza/matplotlib/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/fariza/matplotlib/teams","hooks_url":"https://api.github.com/repos/fariza/matplotlib/hooks","issue_events_url":"https://api.github.com/repos/fariza/matplotlib/issues/events{/number}","events_url":"https://api.github.com/repos/fariza/matplotlib/events","assignees_url":"https://api.github.com/repos/fariza/matplotlib/assignees{/user}","branches_url":"https://api.github.com/repos/fariza/matplotlib/branches{/branch}","tags_url":"https://api.github.com/repos/fariza/matplotlib/tags","blobs_url":"https://api.github.com/repos/fariza/matplotlib/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/fariza/matplotlib/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/fariza/matplotlib/git/refs{/sha}","trees_url":"https://api.github.com/repos/fariza/matplotlib/git/trees{/sha}","statuses_url":"https://api.github.com/repos/fariza/matplotlib/statuses/{sha}","languages_url":"https://api.github.com/repos/fariza/matplotlib/languages","stargazers_url":"https://api.github.com/repos/fariza/matplotlib/stargazers","contributors_url":"https://api.github.com/repos/fariza/matplotlib/contributors","subscribers_url":"https://api.github.com/repos/fariza/matplotlib/subscribers","subscription_url":"https://api.github.com/repos/fariza/matplotlib/subscription","commits_url":"https://api.github.com/repos/fariza/matplotlib/commits{/sha}","git_commits_url":"https://api.github.com/repos/fariza/matplotlib/git/commits{/sha}","comments_url":"https://api.github.com/repos/fariza/matplotlib/comments{/number}","issue_comment_url":"https://api.github.com/repos/fariza/matplotlib/issues/comments/{number}","contents_url":"https://api.github.com/repos/fariza/matplotlib/contents/{+path}","compare_url":"https://api.github.com/repos/fariza/matplotlib/compare/{base}...{head}","merges_url":"https://api.github.com/repos/fariza/matplotlib/merges","archive_url":"https://api.github.com/repos/fariza/matplotlib/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/fariza/matplotlib/downloads","issues_url":"https://api.github.com/repos/fariza/matplotlib/issues{/number}","pulls_url":"https://api.github.com/repos/fariza/matplotlib/pulls{/number}","milestones_url":"https://api.github.com/repos/fariza/matplotlib/milestones{/number}","notifications_url":"https://api.github.com/repos/fariza/matplotlib/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/fariza/matplotlib/labels{/name}","releases_url":"https://api.github.com/repos/fariza/matplotlib/releases{/id}","created_at":"2013-09-11T16:28:02Z","updated_at":"2014-05-29T16:57:27Z","pushed_at":"2015-01-21T20:14:37Z","git_url":"git://github.com/fariza/matplotlib.git","ssh_url":"git@github.com:fariza/matplotlib.git","clone_url":"https://github.com/fariza/matplotlib.git","svn_url":"https://github.com/fariza/matplotlib","homepage":"http://matplotlib.org/","size":198278,"stargazers_count":1,"watchers_count":1,"language":"Python","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":1,"mirror_url":null,"open_issues_count":1,"forks":1,"open_issues":1,"watchers":1,"default_branch":"master"}},"base":{"label":"matplotlib:master","ref":"master","sha":"4aa6b7eaa87af5f835e1915b3e2037045dc2820f","user":{"login":"matplotlib","id":215947,"avatar_url":"https://avatars.githubusercontent.com/u/215947?v=3","gravatar_id":"","url":"https://api.github.com/users/matplotlib","html_url":"https://github.com/matplotlib","followers_url":"https://api.github.com/users/matplotlib/followers","following_url":"https://api.github.com/users/matplotlib/following{/other_user}","gists_url":"https://api.github.com/users/matplotlib/gists{/gist_id}","starred_url":"https://api.github.com/users/matplotlib/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/matplotlib/subscriptions","organizations_url":"https://api.github.com/users/matplotlib/orgs","repos_url":"https://api.github.com/users/matplotlib/repos","events_url":"https://api.github.com/users/matplotlib/events{/privacy}","received_events_url":"https://api.github.com/users/matplotlib/received_events","type":"Organization","site_admin":false},"repo":{"id":1385122,"name":"matplotlib","full_name":"matplotlib/matplotlib","owner":{"login":"matplotlib","id":215947,"avatar_url":"https://avatars.githubusercontent.com/u/215947?v=3","gravatar_id":"","url":"https://api.github.com/users/matplotlib","html_url":"https://github.com/matplotlib","followers_url":"https://api.github.com/users/matplotlib/followers","following_url":"https://api.github.com/users/matplotlib/following{/other_user}","gists_url":"https://api.github.com/users/matplotlib/gists{/gist_id}","starred_url":"https://api.github.com/users/matplotlib/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/matplotlib/subscriptions","organizations_url":"https://api.github.com/users/matplotlib/orgs","repos_url":"https://api.github.com/users/matplotlib/repos","events_url":"https://api.github.com/users/matplotlib/events{/privacy}","received_events_url":"https://api.github.com/users/matplotlib/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/matplotlib/matplotlib","description":"matplotlib: plotting with Python","fork":false,"url":"https://api.github.com/repos/matplotlib/matplotlib","forks_url":"https://api.github.com/repos/matplotlib/matplotlib/forks","keys_url":"https://api.github.com/repos/matplotlib/matplotlib/keys{/key_id}","collaborators_url":"https://api.github.com/repos/matplotlib/matplotlib/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/matplotlib/matplotlib/teams","hooks_url":"https://api.github.com/repos/matplotlib/matplotlib/hooks","issue_events_url":"https://api.github.com/repos/matplotlib/matplotlib/issues/events{/number}","events_url":"https://api.github.com/repos/matplotlib/matplotlib/events","assignees_url":"https://api.github.com/repos/matplotlib/matplotlib/assignees{/user}","branches_url":"https://api.github.com/repos/matplotlib/matplotlib/branches{/branch}","tags_url":"https://api.github.com/repos/matplotlib/matplotlib/tags","blobs_url":"https://api.github.com/repos/matplotlib/matplotlib/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/matplotlib/matplotlib/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/matplotlib/matplotlib/git/refs{/sha}","trees_url":"https://api.github.com/repos/matplotlib/matplotlib/git/trees{/sha}","statuses_url":"https://api.github.com/repos/matplotlib/matplotlib/statuses/{sha}","languages_url":"https://api.github.com/repos/matplotlib/matplotlib/languages","stargazers_url":"https://api.github.com/repos/matplotlib/matplotlib/stargazers","contributors_url":"https://api.github.com/repos/matplotlib/matplotlib/contributors","subscribers_url":"https://api.github.com/repos/matplotlib/matplotlib/subscribers","subscription_url":"https://api.github.com/repos/matplotlib/matplotlib/subscription","commits_url":"https://api.github.com/repos/matplotlib/matplotlib/commits{/sha}","git_commits_url":"https://api.github.com/repos/matplotlib/matplotlib/git/commits{/sha}","comments_url":"https://api.github.com/repos/matplotlib/matplotlib/comments{/number}","issue_comment_url":"https://api.github.com/repos/matplotlib/matplotlib/issues/comments/{number}","contents_url":"https://api.github.com/repos/matplotlib/matplotlib/contents/{+path}","compare_url":"https://api.github.com/repos/matplotlib/matplotlib/compare/{base}...{head}","merges_url":"https://api.github.com/repos/matplotlib/matplotlib/merges","archive_url":"https://api.github.com/repos/matplotlib/matplotlib/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/matplotlib/matplotlib/downloads","issues_url":"https://api.github.com/repos/matplotlib/matplotlib/issues{/number}","pulls_url":"https://api.github.com/repos/matplotlib/matplotlib/pulls{/number}","milestones_url":"https://api.github.com/repos/matplotlib/matplotlib/milestones{/number}","notifications_url":"https://api.github.com/repos/matplotlib/matplotlib/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/matplotlib/matplotlib/labels{/name}","releases_url":"https://api.github.com/repos/matplotlib/matplotlib/releases{/id}","created_at":"2011-02-19T03:17:12Z","updated_at":"2015-01-21T14:14:48Z","pushed_at":"2015-01-19T15:01:43Z","git_url":"git://github.com/matplotlib/matplotlib.git","ssh_url":"git@github.com:matplotlib/matplotlib.git","clone_url":"https://github.com/matplotlib/matplotlib.git","svn_url":"https://github.com/matplotlib/matplotlib","homepage":"http://matplotlib.org/","size":250247,"stargazers_count":2173,"watchers_count":2173,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":1065,"mirror_url":null,"open_issues_count":459,"forks":1065,"open_issues":459,"watchers":2173,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/matplotlib/matplotlib/pulls/3652"},"html":{"href":"https://github.com/matplotlib/matplotlib/pull/3652"},"issue":{"href":"https://api.github.com/repos/matplotlib/matplotlib/issues/3652"},"comments":{"href":"https://api.github.com/repos/matplotlib/matplotlib/issues/3652/comments"},"review_comments":{"href":"https://api.github.com/repos/matplotlib/matplotlib/pulls/3652/comments"},"review_comment":{"href":"https://api.github.com/repos/matplotlib/matplotlib/pulls/comments/{number}"},"commits":{"href":"https://api.github.com/repos/matplotlib/matplotlib/pulls/3652/commits"},"statuses":{"href":"https://api.github.com/repos/matplotlib/matplotlib/statuses/737e9604d462f46eb62f412856e32e818d294339"}}}}