{"action":"created","comment":{"url":"https://api.github.com/repos/obspy/obspy/pulls/comments/51351132","id":51351132,"diff_hunk":"@@ -0,0 +1,602 @@\n+#!/usr/bin/env python\n+# -*- coding: utf-8 -*-\n+\"\"\"\n+ObsPy client for the IRIS Syngine service.\n+\n+:copyright:\n+    The ObsPy Development Team (devs@obspy.org)\n+:license:\n+    GNU Lesser General Public License, Version 3\n+    (http://www.gnu.org/copyleft/lesser.html)\n+\"\"\"\n+from __future__ import (absolute_import, division, print_function,\n+                        unicode_literals)\n+from future.builtins import *  # NOQA\n+from future.utils import native_str\n+\n+import collections\n+import io\n+import zipfile\n+\n+import numpy as np\n+\n+import obspy\n+from obspy.core import AttribDict\n+\n+from ..base import WaveformClient, HTTPClient, DEFAULT_USER_AGENT, \\\n+    ClientHTTPException\n+\n+\n+class Client(WaveformClient, HTTPClient):\n+    \"\"\"\n+    Client for the IRIS Syngine service.\n+    \"\"\"\n+    def __init__(self, base_url=\"http://service.iris.edu/irisws/syngine/1\",\n+                 user_agent=DEFAULT_USER_AGENT, debug=False, timeout=20):\n+        \"\"\"\n+        Initializes a Syngine Client.\n+\n+        :param base_url: The base URL of the service.\n+        :type base_url: str\n+        :param user_agent: The user agent sent along the HTTP request.\n+        :type user_agent: str\n+        :param debug: Debug on/off.\n+        :type debug: bool\n+        :param timeout: The socket timeout.\n+        :type timeout: float\n+        \"\"\"\n+        HTTPClient.__init__(self, debug=debug, timeout=timeout,\n+                            user_agent=user_agent)\n+\n+        # Make sure the base_url does not end with a slash.\n+        base_url = base_url.rstrip(\"/\")\n+        self._base_url = base_url\n+\n+    def _get_url(self, path):\n+        return \"/\".join([self._base_url.rstrip(\"/\"), path])\n+\n+    def _handle_requests_http_error(self, r):\n+        msg = \"HTTP code %i when downloading '%s':\\n\\n%s\" % (\n+            r.status_code, r.url, r.text)\n+        raise ClientHTTPException(msg.strip())\n+\n+    def get_model_info(self, model_name):\n+        \"\"\"\n+        Get some information about a particular model.\n+\n+        .. rubric:: Example\n+\n+        >>> from obspy.clients.syngine import Client\n+        >>> c = Client()\n+        >>> db_info = c.get_model_info(model_name=\"ak135f_5s\")\n+        >>> print(db_info.period)\n+        5.125\n+\n+        :param model_name: The name of the model. Case insensitive.\n+        :type model_name: str\n+        :returns: A dictionary with more information about any model.\n+        :rtype: :class:`obspy.core.util.attribdict.AttribDict`\n+        \"\"\"\n+        model_name = model_name.strip().lower()\n+        r = self._download(self._get_url(\"info\"),\n+                           params={\"model\": model_name})\n+        info = AttribDict(r.json())\n+        # Convert slip and sliprate into numpy arrays for easier handling.\n+        info.slip = np.array(info.slip, dtype=np.float64)\n+        info.sliprate = np.array(info.sliprate, dtype=np.float64)\n+        return info\n+\n+    def get_available_models(self):\n+        \"\"\"\n+        Get information about all available velocity models.\n+        \"\"\"\n+        return self._download(self._get_url(\"models\")).json()\n+\n+    def get_service_version(self):\n+        \"\"\"\n+        Get the service version of the remote Syngine server.\n+        \"\"\"\n+        r = self._download(self._get_url(\"version\"))\n+        # Decoding and what not is handled by the requests library.\n+        return r.text\n+\n+    def _convert_parameters(self, model, **kwargs):\n+        model = model.strip().lower()\n+        if not model:\n+            raise ValueError(\"Model must be given.\")\n+\n+        params = {\"model\": model}\n+\n+        # Error handling is mostly delegated to the actual Syngine service.\n+        # Here we just check that the types are compatible.\n+        str_arguments = [\"network\", \"station\", \"networkcode\", \"stationcode\",\n+                         \"locationcode\", \"eventid\", \"label\", \"components\",\n+                         \"units\", \"format\"]\n+        float_arguments = [\"receiverlatitude\", \"receiverlongitude\",\n+                           \"sourcelatitude\", \"sourcelongitude\",\n+                           \"sourcedepthinmeters\", \"scale\", \"dt\"]\n+        int_arguments = [\"kernelwidth\"]\n+        time_arguments = [\"origintime\"]\n+\n+        for keys, t in ((str_arguments, native_str),\n+                        (float_arguments, float),\n+                        (int_arguments, int),\n+                        (time_arguments, obspy.UTCDateTime)):\n+            for key in keys:\n+                try:\n+                    value = kwargs[key]\n+                except KeyError:\n+                    continue\n+                if value is None:\n+                    continue\n+                value = t(value)\n+                # String arguments are stripped and empty strings are not\n+                # allowed.\n+                if t is str:\n+                    value = value.strip()\n+                    if not value:\n+                        raise ValueError(\"String argument '%s' must not be \"\n+                                         \"an empty string.\" % key)\n+                params[key] = t(value)\n+\n+        # These can be absolute times, relative times or phase relative times.\n+        # jo\n+        temporal_bounds = [\"starttime\", \"endtime\"]\n+        for key in temporal_bounds:\n+            try:\n+                value = kwargs[key]\n+            except KeyError:\n+                continue\n+            if value is None:\n+                continue\n+            # If a number, convert to a float.\n+            elif isinstance(value, (int, float)):\n+                value = float(value)\n+            # If a string like object, attempt to parse it to a datetime\n+            # object, otherwise assume its a phase-relative time and let the\n+            # Syngine service deal with the erorr handling.\n+            elif isinstance(value, (str, native_str)):\n+                try:\n+                    value = obspy.UTCDateTime(value)\n+                except:\n+                    value = (value)\n+            # Last but not least just try to pass it to the datetime\n+            # constructor without catching the error.\n+            else:\n+                value = obspy.UTCDateTime(value)\n+            params[key] = native_str(value)\n+\n+        # These all have to be lists of floats. Otherwise it fails.\n+        source_mecs = [\"sourcemomenttensor\",\n+                       \"sourcedoublecouple\",\n+                       \"sourceforce\"]\n+        for key in source_mecs:\n+            try:\n+                value = kwargs[key]\n+            except KeyError:\n+                continue\n+            if value is None:\n+                continue\n+            value = \",\".join([\"%g\" % float(_i) for _i in value])\n+            params[key] = value\n+\n+        return params\n+\n+    def __read_to_stream(self, r):\n+        with io.BytesIO(r.content) as buf:\n+            # First try to read the file in a normal way, otherwise assume\n+            # its a saczip file.\n+            try:\n+                st = obspy.read(buf)\n+            except:\n+                st = obspy.Stream()\n+                zip_obj = zipfile.ZipFile(io.BytesIO(r.content))","path":"obspy/clients/syngine/client.py","position":193,"original_position":193,"commit_id":"604181f47e877efc3e27224337166a595a4f6beb","original_commit_id":"604181f47e877efc3e27224337166a595a4f6beb","user":{"login":"QuLogic","id":302469,"avatar_url":"https://avatars.githubusercontent.com/u/302469?v=3","gravatar_id":"","url":"https://api.github.com/users/QuLogic","html_url":"https://github.com/QuLogic","followers_url":"https://api.github.com/users/QuLogic/followers","following_url":"https://api.github.com/users/QuLogic/following{/other_user}","gists_url":"https://api.github.com/users/QuLogic/gists{/gist_id}","starred_url":"https://api.github.com/users/QuLogic/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/QuLogic/subscriptions","organizations_url":"https://api.github.com/users/QuLogic/orgs","repos_url":"https://api.github.com/users/QuLogic/repos","events_url":"https://api.github.com/users/QuLogic/events{/privacy}","received_events_url":"https://api.github.com/users/QuLogic/received_events","type":"User","site_admin":false},"body":"Can you not just `buf.seek(0)` and reuse the existing `BytesIO` object?","created_at":"2016-01-30T21:19:24Z","updated_at":"2016-01-30T21:19:24Z","html_url":"https://github.com/obspy/obspy/pull/1227#discussion_r51351132","pull_request_url":"https://api.github.com/repos/obspy/obspy/pulls/1227","_links":{"self":{"href":"https://api.github.com/repos/obspy/obspy/pulls/comments/51351132"},"html":{"href":"https://github.com/obspy/obspy/pull/1227#discussion_r51351132"},"pull_request":{"href":"https://api.github.com/repos/obspy/obspy/pulls/1227"}}},"pull_request":{"url":"https://api.github.com/repos/obspy/obspy/pulls/1227","id":56894906,"html_url":"https://github.com/obspy/obspy/pull/1227","diff_url":"https://github.com/obspy/obspy/pull/1227.diff","patch_url":"https://github.com/obspy/obspy/pull/1227.patch","issue_url":"https://api.github.com/repos/obspy/obspy/issues/1227","number":1227,"state":"open","locked":false,"title":"Client for the IRIS Syngine Service","user":{"login":"krischer","id":800487,"avatar_url":"https://avatars.githubusercontent.com/u/800487?v=3","gravatar_id":"","url":"https://api.github.com/users/krischer","html_url":"https://github.com/krischer","followers_url":"https://api.github.com/users/krischer/followers","following_url":"https://api.github.com/users/krischer/following{/other_user}","gists_url":"https://api.github.com/users/krischer/gists{/gist_id}","starred_url":"https://api.github.com/users/krischer/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/krischer/subscriptions","organizations_url":"https://api.github.com/users/krischer/orgs","repos_url":"https://api.github.com/users/krischer/repos","events_url":"https://api.github.com/users/krischer/events{/privacy}","received_events_url":"https://api.github.com/users/krischer/received_events","type":"User","site_admin":false},"body":"This PR adds a new client `obspy.clients.syngine` to provide an interface with the [IRIS Syngine](http://service.iris.edu/irisws/syngine/1) service. It supports the full service including GET and POST requests and corresponding ObsPy methods.\r\n\r\nTests should be fairly comprehensive and are mix of mock and actual network tests that download stuff.\r\n\r\n### Usage Examples\r\n\r\n```python\r\n>>> from obspy.clients.syngine import Client\r\n>>> client = Client()\r\n\r\n>>> st = client.get_waveforms(model=\"ak135f_5s\", network=\"IU\", station=\"ANMO\",\r\n                              eventid=\"GCMT:C201002270634A\")\r\n>>> print(st)\r\n3 Trace(s) in Stream:\r\nIU.ANMO.SE.MXZ | 2010-02-27T06:35:14... - ... | 4.0 Hz, 15520 samples\r\nIU.ANMO.SE.MXN | 2010-02-27T06:35:14... - ... | 4.0 Hz, 15520 samples\r\nIU.ANMO.SE.MXE | 2010-02-27T06:35:14... - ... | 4.0 Hz, 15520 samples\r\n```\r\n\r\n```python\r\n>>> bulk = [{\"latitude\": 10.1, \"longitude\": 12.2, \"stacode\": \"AA\"},\r\n...         {\"latitude\": 14.5, \"longitude\": 10.0, \"stacode\": \"BB\"}]\r\n>>> st = client.get_waveforms_bulk(\r\n...     model=\"ak135f_5s\", eventid=\"GCMT:C201002270634A\",\r\n...     bulk=bulk, starttime=\"P-10\", endtime=\"P+20\")\r\n>>> print(st)  \r\n6 Trace(s) in Stream:\r\nXX.AA.SE.MXZ | 2010-02-27T06:48:11.500000Z - ... | 4.0 Hz, 120 samples\r\nXX.AA.SE.MXN | 2010-02-27T06:48:11.500000Z - ... | 4.0 Hz, 120 samples\r\nXX.AA.SE.MXE | 2010-02-27T06:48:11.500000Z - ... | 4.0 Hz, 120 samples\r\nXX.BB.SE.MXZ | 2010-02-27T06:48:15.250000Z - ... | 4.0 Hz, 120 samples\r\nXX.BB.SE.MXN | 2010-02-27T06:48:15.250000Z - ... | 4.0 Hz, 120 samples\r\nXX.BB.SE.MXE | 2010-02-27T06:48:15.250000Z - ... | 4.0 Hz, 120 samples\r\n```\r\n\r\n### Additional Things\r\n\r\n* This PR introduces a new dependency to ObsPy: The [requests](http://docs.python-requests.org) module. It is one of the most used Python modules and thus should prove no problem to packaging people. I think we should base all future (and potentially) existing HTTP clients on the `requests` library - it just makes things much simpler.\r\n* (@jkmacc-LANL) It also continues ideas from #1212 and introduces two new mix-in classes `RemoteBaseClient` (a base class for all remote clients) and `HTTPClient` (a base class for all clients downloading over HTTP). The later also contains actual downloading methods so it does not have to be reimplemented in each client. The Syngine client is based on these.","created_at":"2016-01-22T14:38:39Z","updated_at":"2016-01-30T21:19:24Z","closed_at":null,"merged_at":null,"merge_commit_sha":"6b54570767f436e821cc5aedf1ff2cd7bebe1681","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/obspy/obspy/pulls/1227/commits","review_comments_url":"https://api.github.com/repos/obspy/obspy/pulls/1227/comments","review_comment_url":"https://api.github.com/repos/obspy/obspy/pulls/comments{/number}","comments_url":"https://api.github.com/repos/obspy/obspy/issues/1227/comments","statuses_url":"https://api.github.com/repos/obspy/obspy/statuses/604181f47e877efc3e27224337166a595a4f6beb","head":{"label":"obspy:iris_syngine","ref":"iris_syngine","sha":"604181f47e877efc3e27224337166a595a4f6beb","user":{"login":"obspy","id":1701221,"avatar_url":"https://avatars.githubusercontent.com/u/1701221?v=3","gravatar_id":"","url":"https://api.github.com/users/obspy","html_url":"https://github.com/obspy","followers_url":"https://api.github.com/users/obspy/followers","following_url":"https://api.github.com/users/obspy/following{/other_user}","gists_url":"https://api.github.com/users/obspy/gists{/gist_id}","starred_url":"https://api.github.com/users/obspy/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/obspy/subscriptions","organizations_url":"https://api.github.com/users/obspy/orgs","repos_url":"https://api.github.com/users/obspy/repos","events_url":"https://api.github.com/users/obspy/events{/privacy}","received_events_url":"https://api.github.com/users/obspy/received_events","type":"Organization","site_admin":false},"repo":{"id":5731348,"name":"obspy","full_name":"obspy/obspy","owner":{"login":"obspy","id":1701221,"avatar_url":"https://avatars.githubusercontent.com/u/1701221?v=3","gravatar_id":"","url":"https://api.github.com/users/obspy","html_url":"https://github.com/obspy","followers_url":"https://api.github.com/users/obspy/followers","following_url":"https://api.github.com/users/obspy/following{/other_user}","gists_url":"https://api.github.com/users/obspy/gists{/gist_id}","starred_url":"https://api.github.com/users/obspy/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/obspy/subscriptions","organizations_url":"https://api.github.com/users/obspy/orgs","repos_url":"https://api.github.com/users/obspy/repos","events_url":"https://api.github.com/users/obspy/events{/privacy}","received_events_url":"https://api.github.com/users/obspy/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/obspy/obspy","description":"ObsPy: A Python Toolbox for seismology/seismological observatories.","fork":false,"url":"https://api.github.com/repos/obspy/obspy","forks_url":"https://api.github.com/repos/obspy/obspy/forks","keys_url":"https://api.github.com/repos/obspy/obspy/keys{/key_id}","collaborators_url":"https://api.github.com/repos/obspy/obspy/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/obspy/obspy/teams","hooks_url":"https://api.github.com/repos/obspy/obspy/hooks","issue_events_url":"https://api.github.com/repos/obspy/obspy/issues/events{/number}","events_url":"https://api.github.com/repos/obspy/obspy/events","assignees_url":"https://api.github.com/repos/obspy/obspy/assignees{/user}","branches_url":"https://api.github.com/repos/obspy/obspy/branches{/branch}","tags_url":"https://api.github.com/repos/obspy/obspy/tags","blobs_url":"https://api.github.com/repos/obspy/obspy/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/obspy/obspy/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/obspy/obspy/git/refs{/sha}","trees_url":"https://api.github.com/repos/obspy/obspy/git/trees{/sha}","statuses_url":"https://api.github.com/repos/obspy/obspy/statuses/{sha}","languages_url":"https://api.github.com/repos/obspy/obspy/languages","stargazers_url":"https://api.github.com/repos/obspy/obspy/stargazers","contributors_url":"https://api.github.com/repos/obspy/obspy/contributors","subscribers_url":"https://api.github.com/repos/obspy/obspy/subscribers","subscription_url":"https://api.github.com/repos/obspy/obspy/subscription","commits_url":"https://api.github.com/repos/obspy/obspy/commits{/sha}","git_commits_url":"https://api.github.com/repos/obspy/obspy/git/commits{/sha}","comments_url":"https://api.github.com/repos/obspy/obspy/comments{/number}","issue_comment_url":"https://api.github.com/repos/obspy/obspy/issues/comments{/number}","contents_url":"https://api.github.com/repos/obspy/obspy/contents/{+path}","compare_url":"https://api.github.com/repos/obspy/obspy/compare/{base}...{head}","merges_url":"https://api.github.com/repos/obspy/obspy/merges","archive_url":"https://api.github.com/repos/obspy/obspy/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/obspy/obspy/downloads","issues_url":"https://api.github.com/repos/obspy/obspy/issues{/number}","pulls_url":"https://api.github.com/repos/obspy/obspy/pulls{/number}","milestones_url":"https://api.github.com/repos/obspy/obspy/milestones{/number}","notifications_url":"https://api.github.com/repos/obspy/obspy/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/obspy/obspy/labels{/name}","releases_url":"https://api.github.com/repos/obspy/obspy/releases{/id}","deployments_url":"https://api.github.com/repos/obspy/obspy/deployments","created_at":"2012-09-08T19:17:46Z","updated_at":"2016-01-30T03:30:00Z","pushed_at":"2016-01-29T18:26:56Z","git_url":"git://github.com/obspy/obspy.git","ssh_url":"git@github.com:obspy/obspy.git","clone_url":"https://github.com/obspy/obspy.git","svn_url":"https://github.com/obspy/obspy","homepage":"http://www.obspy.org","size":82169,"stargazers_count":180,"watchers_count":180,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":132,"mirror_url":null,"open_issues_count":117,"forks":132,"open_issues":117,"watchers":180,"default_branch":"master"}},"base":{"label":"obspy:master","ref":"master","sha":"b1ab176cb48561411020d5cd042c8aa2e0cb9498","user":{"login":"obspy","id":1701221,"avatar_url":"https://avatars.githubusercontent.com/u/1701221?v=3","gravatar_id":"","url":"https://api.github.com/users/obspy","html_url":"https://github.com/obspy","followers_url":"https://api.github.com/users/obspy/followers","following_url":"https://api.github.com/users/obspy/following{/other_user}","gists_url":"https://api.github.com/users/obspy/gists{/gist_id}","starred_url":"https://api.github.com/users/obspy/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/obspy/subscriptions","organizations_url":"https://api.github.com/users/obspy/orgs","repos_url":"https://api.github.com/users/obspy/repos","events_url":"https://api.github.com/users/obspy/events{/privacy}","received_events_url":"https://api.github.com/users/obspy/received_events","type":"Organization","site_admin":false},"repo":{"id":5731348,"name":"obspy","full_name":"obspy/obspy","owner":{"login":"obspy","id":1701221,"avatar_url":"https://avatars.githubusercontent.com/u/1701221?v=3","gravatar_id":"","url":"https://api.github.com/users/obspy","html_url":"https://github.com/obspy","followers_url":"https://api.github.com/users/obspy/followers","following_url":"https://api.github.com/users/obspy/following{/other_user}","gists_url":"https://api.github.com/users/obspy/gists{/gist_id}","starred_url":"https://api.github.com/users/obspy/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/obspy/subscriptions","organizations_url":"https://api.github.com/users/obspy/orgs","repos_url":"https://api.github.com/users/obspy/repos","events_url":"https://api.github.com/users/obspy/events{/privacy}","received_events_url":"https://api.github.com/users/obspy/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/obspy/obspy","description":"ObsPy: A Python Toolbox for seismology/seismological observatories.","fork":false,"url":"https://api.github.com/repos/obspy/obspy","forks_url":"https://api.github.com/repos/obspy/obspy/forks","keys_url":"https://api.github.com/repos/obspy/obspy/keys{/key_id}","collaborators_url":"https://api.github.com/repos/obspy/obspy/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/obspy/obspy/teams","hooks_url":"https://api.github.com/repos/obspy/obspy/hooks","issue_events_url":"https://api.github.com/repos/obspy/obspy/issues/events{/number}","events_url":"https://api.github.com/repos/obspy/obspy/events","assignees_url":"https://api.github.com/repos/obspy/obspy/assignees{/user}","branches_url":"https://api.github.com/repos/obspy/obspy/branches{/branch}","tags_url":"https://api.github.com/repos/obspy/obspy/tags","blobs_url":"https://api.github.com/repos/obspy/obspy/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/obspy/obspy/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/obspy/obspy/git/refs{/sha}","trees_url":"https://api.github.com/repos/obspy/obspy/git/trees{/sha}","statuses_url":"https://api.github.com/repos/obspy/obspy/statuses/{sha}","languages_url":"https://api.github.com/repos/obspy/obspy/languages","stargazers_url":"https://api.github.com/repos/obspy/obspy/stargazers","contributors_url":"https://api.github.com/repos/obspy/obspy/contributors","subscribers_url":"https://api.github.com/repos/obspy/obspy/subscribers","subscription_url":"https://api.github.com/repos/obspy/obspy/subscription","commits_url":"https://api.github.com/repos/obspy/obspy/commits{/sha}","git_commits_url":"https://api.github.com/repos/obspy/obspy/git/commits{/sha}","comments_url":"https://api.github.com/repos/obspy/obspy/comments{/number}","issue_comment_url":"https://api.github.com/repos/obspy/obspy/issues/comments{/number}","contents_url":"https://api.github.com/repos/obspy/obspy/contents/{+path}","compare_url":"https://api.github.com/repos/obspy/obspy/compare/{base}...{head}","merges_url":"https://api.github.com/repos/obspy/obspy/merges","archive_url":"https://api.github.com/repos/obspy/obspy/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/obspy/obspy/downloads","issues_url":"https://api.github.com/repos/obspy/obspy/issues{/number}","pulls_url":"https://api.github.com/repos/obspy/obspy/pulls{/number}","milestones_url":"https://api.github.com/repos/obspy/obspy/milestones{/number}","notifications_url":"https://api.github.com/repos/obspy/obspy/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/obspy/obspy/labels{/name}","releases_url":"https://api.github.com/repos/obspy/obspy/releases{/id}","deployments_url":"https://api.github.com/repos/obspy/obspy/deployments","created_at":"2012-09-08T19:17:46Z","updated_at":"2016-01-30T03:30:00Z","pushed_at":"2016-01-29T18:26:56Z","git_url":"git://github.com/obspy/obspy.git","ssh_url":"git@github.com:obspy/obspy.git","clone_url":"https://github.com/obspy/obspy.git","svn_url":"https://github.com/obspy/obspy","homepage":"http://www.obspy.org","size":82169,"stargazers_count":180,"watchers_count":180,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":132,"mirror_url":null,"open_issues_count":117,"forks":132,"open_issues":117,"watchers":180,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/obspy/obspy/pulls/1227"},"html":{"href":"https://github.com/obspy/obspy/pull/1227"},"issue":{"href":"https://api.github.com/repos/obspy/obspy/issues/1227"},"comments":{"href":"https://api.github.com/repos/obspy/obspy/issues/1227/comments"},"review_comments":{"href":"https://api.github.com/repos/obspy/obspy/pulls/1227/comments"},"review_comment":{"href":"https://api.github.com/repos/obspy/obspy/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/obspy/obspy/pulls/1227/commits"},"statuses":{"href":"https://api.github.com/repos/obspy/obspy/statuses/604181f47e877efc3e27224337166a595a4f6beb"}}}}