{"action":"created","comment":{"url":"https://api.github.com/repos/metabrainz/picard/pulls/comments/62851694","id":62851694,"diff_hunk":"@@ -134,6 +135,87 @@ def _read_xml(stream):\n     return document\n \n \n+class WsRequest(object):\n+\n+    def __init__(self, method, host, port, path, data, handler, xml,\n+                 mblogin=False, cacheloadcontrol=None, refresh=None,\n+                 access_token=None, queryargs=None, retries=0,\n+                 priority=False, important=False):\n+        self.method = method\n+        self.host = host\n+        self.port = port\n+        self.path = path\n+        self.data = data\n+        self.handler = handler\n+        self.xml = xml\n+        self.mblogin = mblogin\n+        self.cacheloadcontrol = cacheloadcontrol\n+        self.refresh = refresh\n+        self.access_token = access_token\n+        self.queryargs = queryargs\n+        self.priority = priority\n+        self.important = important\n+        self.retries = retries\n+\n+        self._qrequest = None\n+\n+    def get_host_key(self):\n+        return (self.host, self.port)\n+\n+    @property\n+    def qrequest(self):\n+        if self._qrequest is None:\n+            url = build_qurl(self.host, self.port, path=self.path,\n+                             mblogin=self.mblogin,\n+                             queryargs=self.queryargs)\n+            self._qrequest = QtNetwork.QNetworkRequest(url)\n+        return self._qrequest\n+\n+    def send(self, request_methods):\n+        if self.mblogin and self.access_token:\n+            self.qrequest.setRawHeader(\"Authorization\", \"Bearer %s\" % self.access_token)\n+        if self.mblogin or (self.method == \"GET\" and self.refresh):\n+            self.qrequest.setPriority(QtNetwork.QNetworkRequest.HighPriority)\n+            self.qrequest.setAttribute(QtNetwork.QNetworkRequest.CacheLoadControlAttribute,\n+                                 QtNetwork.QNetworkRequest.AlwaysNetwork)\n+        elif self.method in (\"PUT\", \"DELETE\"):\n+            self.qrequest.setPriority(QtNetwork.QNetworkRequest.HighPriority)\n+        elif self.cacheloadcontrol is not None:\n+            self.qrequest.setAttribute(QtNetwork.QNetworkRequest.CacheLoadControlAttribute,\n+                                 self.cacheloadcontrol)\n+        self.qrequest.setRawHeader(\"User-Agent\", USER_AGENT_STRING)\n+        if self.xml:\n+            self.qrequest.setRawHeader(\"Accept\", \"application/xml\")\n+        if self.data is not None:\n+            if (self.method == \"POST\"\n+                and self.host == config.setting[\"server_host\"]\n+                and self.xml):\n+                self.qrequest.setHeader(QtNetwork.QNetworkRequest.ContentTypeHeader, \"application/xml; charset=utf-8\")\n+            else:\n+                self.qrequest.setHeader(QtNetwork.QNetworkRequest.ContentTypeHeader, \"application/x-www-form-urlencoded\")\n+        send = request_methods[self.method]","path":"picard/webservice.py","position":70,"original_position":70,"commit_id":"1b4a347838478a4558f013a44a546973d609a3eb","original_commit_id":"1b4a347838478a4558f013a44a546973d609a3eb","user":{"login":"zas","id":151042,"avatar_url":"https://avatars.githubusercontent.com/u/151042?v=3","gravatar_id":"","url":"https://api.github.com/users/zas","html_url":"https://github.com/zas","followers_url":"https://api.github.com/users/zas/followers","following_url":"https://api.github.com/users/zas/following{/other_user}","gists_url":"https://api.github.com/users/zas/gists{/gist_id}","starred_url":"https://api.github.com/users/zas/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/zas/subscriptions","organizations_url":"https://api.github.com/users/zas/orgs","repos_url":"https://api.github.com/users/zas/repos","events_url":"https://api.github.com/users/zas/events{/privacy}","received_events_url":"https://api.github.com/users/zas/received_events","type":"User","site_admin":false},"body":"Ok, any name suggestion ?","created_at":"2016-05-11T13:54:38Z","updated_at":"2016-05-11T13:54:38Z","html_url":"https://github.com/metabrainz/picard/pull/473#discussion_r62851694","pull_request_url":"https://api.github.com/repos/metabrainz/picard/pulls/473","_links":{"self":{"href":"https://api.github.com/repos/metabrainz/picard/pulls/comments/62851694"},"html":{"href":"https://github.com/metabrainz/picard/pull/473#discussion_r62851694"},"pull_request":{"href":"https://api.github.com/repos/metabrainz/picard/pulls/473"}}},"pull_request":{"url":"https://api.github.com/repos/metabrainz/picard/pulls/473","id":69580821,"html_url":"https://github.com/metabrainz/picard/pull/473","diff_url":"https://github.com/metabrainz/picard/pull/473.diff","patch_url":"https://github.com/metabrainz/picard/pull/473.patch","issue_url":"https://api.github.com/repos/metabrainz/picard/issues/473","number":473,"state":"open","locked":false,"title":"PICARD-807: retry on temporarily failures","user":{"login":"zas","id":151042,"avatar_url":"https://avatars.githubusercontent.com/u/151042?v=3","gravatar_id":"","url":"https://api.github.com/users/zas","html_url":"https://github.com/zas","followers_url":"https://api.github.com/users/zas/followers","following_url":"https://api.github.com/users/zas/following{/other_user}","gists_url":"https://api.github.com/users/zas/gists{/gist_id}","starred_url":"https://api.github.com/users/zas/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/zas/subscriptions","organizations_url":"https://api.github.com/users/zas/orgs","repos_url":"https://api.github.com/users/zas/repos","events_url":"https://api.github.com/users/zas/events{/privacy}","received_events_url":"https://api.github.com/users/zas/received_events","type":"User","site_admin":false},"body":"This PR introduces WsRequest class to simplify code a bit.\r\n\r\n- It uses a workaround to PICARD-809, which prevents a simple http code test to work ...\r\n- It implements retries as suggested in PICARD-807 description\r\n- It retries up to 5 times\r\n\r\nhttp://tickets.musicbrainz.org/browse/PICARD-807","created_at":"2016-05-10T21:26:21Z","updated_at":"2016-05-11T13:54:38Z","closed_at":null,"merged_at":null,"merge_commit_sha":"eb4eb395685f10ecdf2ac848790543a38a2c87ad","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/metabrainz/picard/pulls/473/commits","review_comments_url":"https://api.github.com/repos/metabrainz/picard/pulls/473/comments","review_comment_url":"https://api.github.com/repos/metabrainz/picard/pulls/comments{/number}","comments_url":"https://api.github.com/repos/metabrainz/picard/issues/473/comments","statuses_url":"https://api.github.com/repos/metabrainz/picard/statuses/1b4a347838478a4558f013a44a546973d609a3eb","head":{"label":"zas:wsrequest","ref":"wsrequest","sha":"1b4a347838478a4558f013a44a546973d609a3eb","user":{"login":"zas","id":151042,"avatar_url":"https://avatars.githubusercontent.com/u/151042?v=3","gravatar_id":"","url":"https://api.github.com/users/zas","html_url":"https://github.com/zas","followers_url":"https://api.github.com/users/zas/followers","following_url":"https://api.github.com/users/zas/following{/other_user}","gists_url":"https://api.github.com/users/zas/gists{/gist_id}","starred_url":"https://api.github.com/users/zas/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/zas/subscriptions","organizations_url":"https://api.github.com/users/zas/orgs","repos_url":"https://api.github.com/users/zas/repos","events_url":"https://api.github.com/users/zas/events{/privacy}","received_events_url":"https://api.github.com/users/zas/received_events","type":"User","site_admin":false},"repo":{"id":7479305,"name":"picard","full_name":"zas/picard","owner":{"login":"zas","id":151042,"avatar_url":"https://avatars.githubusercontent.com/u/151042?v=3","gravatar_id":"","url":"https://api.github.com/users/zas","html_url":"https://github.com/zas","followers_url":"https://api.github.com/users/zas/followers","following_url":"https://api.github.com/users/zas/following{/other_user}","gists_url":"https://api.github.com/users/zas/gists{/gist_id}","starred_url":"https://api.github.com/users/zas/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/zas/subscriptions","organizations_url":"https://api.github.com/users/zas/orgs","repos_url":"https://api.github.com/users/zas/repos","events_url":"https://api.github.com/users/zas/events{/privacy}","received_events_url":"https://api.github.com/users/zas/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/zas/picard","description":"MusicBrainz Picard","fork":true,"url":"https://api.github.com/repos/zas/picard","forks_url":"https://api.github.com/repos/zas/picard/forks","keys_url":"https://api.github.com/repos/zas/picard/keys{/key_id}","collaborators_url":"https://api.github.com/repos/zas/picard/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/zas/picard/teams","hooks_url":"https://api.github.com/repos/zas/picard/hooks","issue_events_url":"https://api.github.com/repos/zas/picard/issues/events{/number}","events_url":"https://api.github.com/repos/zas/picard/events","assignees_url":"https://api.github.com/repos/zas/picard/assignees{/user}","branches_url":"https://api.github.com/repos/zas/picard/branches{/branch}","tags_url":"https://api.github.com/repos/zas/picard/tags","blobs_url":"https://api.github.com/repos/zas/picard/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/zas/picard/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/zas/picard/git/refs{/sha}","trees_url":"https://api.github.com/repos/zas/picard/git/trees{/sha}","statuses_url":"https://api.github.com/repos/zas/picard/statuses/{sha}","languages_url":"https://api.github.com/repos/zas/picard/languages","stargazers_url":"https://api.github.com/repos/zas/picard/stargazers","contributors_url":"https://api.github.com/repos/zas/picard/contributors","subscribers_url":"https://api.github.com/repos/zas/picard/subscribers","subscription_url":"https://api.github.com/repos/zas/picard/subscription","commits_url":"https://api.github.com/repos/zas/picard/commits{/sha}","git_commits_url":"https://api.github.com/repos/zas/picard/git/commits{/sha}","comments_url":"https://api.github.com/repos/zas/picard/comments{/number}","issue_comment_url":"https://api.github.com/repos/zas/picard/issues/comments{/number}","contents_url":"https://api.github.com/repos/zas/picard/contents/{+path}","compare_url":"https://api.github.com/repos/zas/picard/compare/{base}...{head}","merges_url":"https://api.github.com/repos/zas/picard/merges","archive_url":"https://api.github.com/repos/zas/picard/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/zas/picard/downloads","issues_url":"https://api.github.com/repos/zas/picard/issues{/number}","pulls_url":"https://api.github.com/repos/zas/picard/pulls{/number}","milestones_url":"https://api.github.com/repos/zas/picard/milestones{/number}","notifications_url":"https://api.github.com/repos/zas/picard/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/zas/picard/labels{/name}","releases_url":"https://api.github.com/repos/zas/picard/releases{/id}","deployments_url":"https://api.github.com/repos/zas/picard/deployments","created_at":"2013-01-07T08:45:26Z","updated_at":"2015-02-04T07:46:28Z","pushed_at":"2016-05-10T21:21:36Z","git_url":"git://github.com/zas/picard.git","ssh_url":"git@github.com:zas/picard.git","clone_url":"https://github.com/zas/picard.git","svn_url":"https://github.com/zas/picard","homepage":"http://musicbrainz.org/doc/MusicBrainz_Picard","size":22221,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":1,"mirror_url":null,"open_issues_count":0,"forks":1,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"metabrainz:master","ref":"master","sha":"5cf0ceb0f096dc6c22056c97fdea57f749877e3e","user":{"login":"metabrainz","id":293421,"avatar_url":"https://avatars.githubusercontent.com/u/293421?v=3","gravatar_id":"","url":"https://api.github.com/users/metabrainz","html_url":"https://github.com/metabrainz","followers_url":"https://api.github.com/users/metabrainz/followers","following_url":"https://api.github.com/users/metabrainz/following{/other_user}","gists_url":"https://api.github.com/users/metabrainz/gists{/gist_id}","starred_url":"https://api.github.com/users/metabrainz/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/metabrainz/subscriptions","organizations_url":"https://api.github.com/users/metabrainz/orgs","repos_url":"https://api.github.com/users/metabrainz/repos","events_url":"https://api.github.com/users/metabrainz/events{/privacy}","received_events_url":"https://api.github.com/users/metabrainz/received_events","type":"Organization","site_admin":false},"repo":{"id":2218679,"name":"picard","full_name":"metabrainz/picard","owner":{"login":"metabrainz","id":293421,"avatar_url":"https://avatars.githubusercontent.com/u/293421?v=3","gravatar_id":"","url":"https://api.github.com/users/metabrainz","html_url":"https://github.com/metabrainz","followers_url":"https://api.github.com/users/metabrainz/followers","following_url":"https://api.github.com/users/metabrainz/following{/other_user}","gists_url":"https://api.github.com/users/metabrainz/gists{/gist_id}","starred_url":"https://api.github.com/users/metabrainz/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/metabrainz/subscriptions","organizations_url":"https://api.github.com/users/metabrainz/orgs","repos_url":"https://api.github.com/users/metabrainz/repos","events_url":"https://api.github.com/users/metabrainz/events{/privacy}","received_events_url":"https://api.github.com/users/metabrainz/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/metabrainz/picard","description":"MusicBrainz Picard","fork":false,"url":"https://api.github.com/repos/metabrainz/picard","forks_url":"https://api.github.com/repos/metabrainz/picard/forks","keys_url":"https://api.github.com/repos/metabrainz/picard/keys{/key_id}","collaborators_url":"https://api.github.com/repos/metabrainz/picard/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/metabrainz/picard/teams","hooks_url":"https://api.github.com/repos/metabrainz/picard/hooks","issue_events_url":"https://api.github.com/repos/metabrainz/picard/issues/events{/number}","events_url":"https://api.github.com/repos/metabrainz/picard/events","assignees_url":"https://api.github.com/repos/metabrainz/picard/assignees{/user}","branches_url":"https://api.github.com/repos/metabrainz/picard/branches{/branch}","tags_url":"https://api.github.com/repos/metabrainz/picard/tags","blobs_url":"https://api.github.com/repos/metabrainz/picard/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/metabrainz/picard/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/metabrainz/picard/git/refs{/sha}","trees_url":"https://api.github.com/repos/metabrainz/picard/git/trees{/sha}","statuses_url":"https://api.github.com/repos/metabrainz/picard/statuses/{sha}","languages_url":"https://api.github.com/repos/metabrainz/picard/languages","stargazers_url":"https://api.github.com/repos/metabrainz/picard/stargazers","contributors_url":"https://api.github.com/repos/metabrainz/picard/contributors","subscribers_url":"https://api.github.com/repos/metabrainz/picard/subscribers","subscription_url":"https://api.github.com/repos/metabrainz/picard/subscription","commits_url":"https://api.github.com/repos/metabrainz/picard/commits{/sha}","git_commits_url":"https://api.github.com/repos/metabrainz/picard/git/commits{/sha}","comments_url":"https://api.github.com/repos/metabrainz/picard/comments{/number}","issue_comment_url":"https://api.github.com/repos/metabrainz/picard/issues/comments{/number}","contents_url":"https://api.github.com/repos/metabrainz/picard/contents/{+path}","compare_url":"https://api.github.com/repos/metabrainz/picard/compare/{base}...{head}","merges_url":"https://api.github.com/repos/metabrainz/picard/merges","archive_url":"https://api.github.com/repos/metabrainz/picard/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/metabrainz/picard/downloads","issues_url":"https://api.github.com/repos/metabrainz/picard/issues{/number}","pulls_url":"https://api.github.com/repos/metabrainz/picard/pulls{/number}","milestones_url":"https://api.github.com/repos/metabrainz/picard/milestones{/number}","notifications_url":"https://api.github.com/repos/metabrainz/picard/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/metabrainz/picard/labels{/name}","releases_url":"https://api.github.com/repos/metabrainz/picard/releases{/id}","deployments_url":"https://api.github.com/repos/metabrainz/picard/deployments","created_at":"2011-08-16T22:30:23Z","updated_at":"2016-05-09T13:30:37Z","pushed_at":"2016-05-10T21:26:21Z","git_url":"git://github.com/metabrainz/picard.git","ssh_url":"git@github.com:metabrainz/picard.git","clone_url":"https://github.com/metabrainz/picard.git","svn_url":"https://github.com/metabrainz/picard","homepage":"http://musicbrainz.org/doc/MusicBrainz_Picard","size":42532,"stargazers_count":714,"watchers_count":714,"language":"Python","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":150,"mirror_url":null,"open_issues_count":21,"forks":150,"open_issues":21,"watchers":714,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/metabrainz/picard/pulls/473"},"html":{"href":"https://github.com/metabrainz/picard/pull/473"},"issue":{"href":"https://api.github.com/repos/metabrainz/picard/issues/473"},"comments":{"href":"https://api.github.com/repos/metabrainz/picard/issues/473/comments"},"review_comments":{"href":"https://api.github.com/repos/metabrainz/picard/pulls/473/comments"},"review_comment":{"href":"https://api.github.com/repos/metabrainz/picard/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/metabrainz/picard/pulls/473/commits"},"statuses":{"href":"https://api.github.com/repos/metabrainz/picard/statuses/1b4a347838478a4558f013a44a546973d609a3eb"}}}}