{"action":"created","comment":{"url":"https://api.github.com/repos/scrapinghub/python-scrapinghub/pulls/comments/101744024","pull_request_review_id":22482316,"id":101744024,"diff_hunk":"@@ -305,6 +306,16 @@ def __init__(self, client, projectid, spiderid, spidername):\n         self.jobs = Jobs(client, projectid, self)\n         self._client = client\n \n+    @wrap_http_errors\n+    def update_tags(self, add=None, remove=None):\n+        params = get_tags_for_update(add=add, remove=remove)\n+        if not params:\n+            return\n+        path = 'v2/projects/{}/spiders/{}/tags'.format(self.projectid, self.id)\n+        url = urljoin(self._client._connection.url, path)\n+        response = self._client._connection._session.patch(url, json=params)","path":"scrapinghub/client.py","position":null,"original_position":19,"commit_id":"fdab51f51205bae792d6ef61ca34abfdf31355de","original_commit_id":"360a12fa3ab8db2d78745b0a0c93685afa379408","user":{"login":"chekunkov","id":744331,"avatar_url":"https://avatars.githubusercontent.com/u/744331?v=3","gravatar_id":"","url":"https://api.github.com/users/chekunkov","html_url":"https://github.com/chekunkov","followers_url":"https://api.github.com/users/chekunkov/followers","following_url":"https://api.github.com/users/chekunkov/following{/other_user}","gists_url":"https://api.github.com/users/chekunkov/gists{/gist_id}","starred_url":"https://api.github.com/users/chekunkov/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/chekunkov/subscriptions","organizations_url":"https://api.github.com/users/chekunkov/orgs","repos_url":"https://api.github.com/users/chekunkov/repos","events_url":"https://api.github.com/users/chekunkov/events{/privacy}","received_events_url":"https://api.github.com/users/chekunkov/received_events","type":"User","site_admin":false},"body":"Agree. Do we want to expose v2 api though?","created_at":"2017-02-17T12:08:17Z","updated_at":"2017-02-17T12:32:51Z","html_url":"https://github.com/scrapinghub/python-scrapinghub/pull/48#discussion_r101744024","pull_request_url":"https://api.github.com/repos/scrapinghub/python-scrapinghub/pulls/48","_links":{"self":{"href":"https://api.github.com/repos/scrapinghub/python-scrapinghub/pulls/comments/101744024"},"html":{"href":"https://github.com/scrapinghub/python-scrapinghub/pull/48#discussion_r101744024"},"pull_request":{"href":"https://api.github.com/repos/scrapinghub/python-scrapinghub/pulls/48"}}},"pull_request":{"url":"https://api.github.com/repos/scrapinghub/python-scrapinghub/pulls/48","id":105008950,"html_url":"https://github.com/scrapinghub/python-scrapinghub/pull/48","diff_url":"https://github.com/scrapinghub/python-scrapinghub/pull/48.diff","patch_url":"https://github.com/scrapinghub/python-scrapinghub/pull/48.patch","issue_url":"https://api.github.com/repos/scrapinghub/python-scrapinghub/issues/48","number":48,"state":"open","locked":false,"title":"Improvements and fixes for new python client","user":{"login":"vshlapakov","id":448111,"avatar_url":"https://avatars.githubusercontent.com/u/448111?v=3","gravatar_id":"","url":"https://api.github.com/users/vshlapakov","html_url":"https://github.com/vshlapakov","followers_url":"https://api.github.com/users/vshlapakov/followers","following_url":"https://api.github.com/users/vshlapakov/following{/other_user}","gists_url":"https://api.github.com/users/vshlapakov/gists{/gist_id}","starred_url":"https://api.github.com/users/vshlapakov/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/vshlapakov/subscriptions","organizations_url":"https://api.github.com/users/vshlapakov/orgs","repos_url":"https://api.github.com/users/vshlapakov/repos","events_url":"https://api.github.com/users/vshlapakov/events{/privacy}","received_events_url":"https://api.github.com/users/vshlapakov/received_events","type":"User","site_admin":false},"body":"The PR is created to cover the following minor things found after testing:\r\n- [x] fix inconsistencies between `project.id - spider.id - job.key` (use `key` or `id` everywhere)\r\n- [x] collection.set() should return None instead of a generator\r\n- [x] simplify and unify using HS `filter` param \r\n- [x] activity.add(): add client validation for project id\r\n- [x] collections.iter() should iterate through collections\r\n- [x] unify errors when apikey is wrong (now it's `InvalidUsage` or `ScrapinghubAPIError`)\r\n- [x] handle HTTP 401 from JobQ separately with providing a good message instead of html\r\n\r\nOther issues added after next step of testing at February 8th:\r\n- [x] collection.delete() should return None instead of a generator\r\n- [x] add validation for collection.delete input\r\n- [x] validate that update_tags method has any input\r\n\r\nAlso there's a new `spider.update_tags` method that will be added on server-side soon.\r\n\r\nEach of the points will be implemented in a separate commit(s) to simplify reviewing.","created_at":"2017-02-07T13:52:05Z","updated_at":"2017-02-17T12:32:51Z","closed_at":null,"merged_at":null,"merge_commit_sha":"10b50767d6d7eb6739a5a2d03a3a23c76ed40b72","assignee":{"login":"vshlapakov","id":448111,"avatar_url":"https://avatars.githubusercontent.com/u/448111?v=3","gravatar_id":"","url":"https://api.github.com/users/vshlapakov","html_url":"https://github.com/vshlapakov","followers_url":"https://api.github.com/users/vshlapakov/followers","following_url":"https://api.github.com/users/vshlapakov/following{/other_user}","gists_url":"https://api.github.com/users/vshlapakov/gists{/gist_id}","starred_url":"https://api.github.com/users/vshlapakov/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/vshlapakov/subscriptions","organizations_url":"https://api.github.com/users/vshlapakov/orgs","repos_url":"https://api.github.com/users/vshlapakov/repos","events_url":"https://api.github.com/users/vshlapakov/events{/privacy}","received_events_url":"https://api.github.com/users/vshlapakov/received_events","type":"User","site_admin":false},"assignees":[{"login":"vshlapakov","id":448111,"avatar_url":"https://avatars.githubusercontent.com/u/448111?v=3","gravatar_id":"","url":"https://api.github.com/users/vshlapakov","html_url":"https://github.com/vshlapakov","followers_url":"https://api.github.com/users/vshlapakov/followers","following_url":"https://api.github.com/users/vshlapakov/following{/other_user}","gists_url":"https://api.github.com/users/vshlapakov/gists{/gist_id}","starred_url":"https://api.github.com/users/vshlapakov/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/vshlapakov/subscriptions","organizations_url":"https://api.github.com/users/vshlapakov/orgs","repos_url":"https://api.github.com/users/vshlapakov/repos","events_url":"https://api.github.com/users/vshlapakov/events{/privacy}","received_events_url":"https://api.github.com/users/vshlapakov/received_events","type":"User","site_admin":false}],"milestone":null,"commits_url":"https://api.github.com/repos/scrapinghub/python-scrapinghub/pulls/48/commits","review_comments_url":"https://api.github.com/repos/scrapinghub/python-scrapinghub/pulls/48/comments","review_comment_url":"https://api.github.com/repos/scrapinghub/python-scrapinghub/pulls/comments{/number}","comments_url":"https://api.github.com/repos/scrapinghub/python-scrapinghub/issues/48/comments","statuses_url":"https://api.github.com/repos/scrapinghub/python-scrapinghub/statuses/fdab51f51205bae792d6ef61ca34abfdf31355de","head":{"label":"scrapinghub:sc1467-fixes","ref":"sc1467-fixes","sha":"fdab51f51205bae792d6ef61ca34abfdf31355de","user":{"login":"scrapinghub","id":699596,"avatar_url":"https://avatars.githubusercontent.com/u/699596?v=3","gravatar_id":"","url":"https://api.github.com/users/scrapinghub","html_url":"https://github.com/scrapinghub","followers_url":"https://api.github.com/users/scrapinghub/followers","following_url":"https://api.github.com/users/scrapinghub/following{/other_user}","gists_url":"https://api.github.com/users/scrapinghub/gists{/gist_id}","starred_url":"https://api.github.com/users/scrapinghub/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/scrapinghub/subscriptions","organizations_url":"https://api.github.com/users/scrapinghub/orgs","repos_url":"https://api.github.com/users/scrapinghub/repos","events_url":"https://api.github.com/users/scrapinghub/events{/privacy}","received_events_url":"https://api.github.com/users/scrapinghub/received_events","type":"Organization","site_admin":false},"repo":{"id":2211875,"name":"python-scrapinghub","full_name":"scrapinghub/python-scrapinghub","owner":{"login":"scrapinghub","id":699596,"avatar_url":"https://avatars.githubusercontent.com/u/699596?v=3","gravatar_id":"","url":"https://api.github.com/users/scrapinghub","html_url":"https://github.com/scrapinghub","followers_url":"https://api.github.com/users/scrapinghub/followers","following_url":"https://api.github.com/users/scrapinghub/following{/other_user}","gists_url":"https://api.github.com/users/scrapinghub/gists{/gist_id}","starred_url":"https://api.github.com/users/scrapinghub/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/scrapinghub/subscriptions","organizations_url":"https://api.github.com/users/scrapinghub/orgs","repos_url":"https://api.github.com/users/scrapinghub/repos","events_url":"https://api.github.com/users/scrapinghub/events{/privacy}","received_events_url":"https://api.github.com/users/scrapinghub/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/scrapinghub/python-scrapinghub","description":"A client interface for Scrapinghub's API","fork":false,"url":"https://api.github.com/repos/scrapinghub/python-scrapinghub","forks_url":"https://api.github.com/repos/scrapinghub/python-scrapinghub/forks","keys_url":"https://api.github.com/repos/scrapinghub/python-scrapinghub/keys{/key_id}","collaborators_url":"https://api.github.com/repos/scrapinghub/python-scrapinghub/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/scrapinghub/python-scrapinghub/teams","hooks_url":"https://api.github.com/repos/scrapinghub/python-scrapinghub/hooks","issue_events_url":"https://api.github.com/repos/scrapinghub/python-scrapinghub/issues/events{/number}","events_url":"https://api.github.com/repos/scrapinghub/python-scrapinghub/events","assignees_url":"https://api.github.com/repos/scrapinghub/python-scrapinghub/assignees{/user}","branches_url":"https://api.github.com/repos/scrapinghub/python-scrapinghub/branches{/branch}","tags_url":"https://api.github.com/repos/scrapinghub/python-scrapinghub/tags","blobs_url":"https://api.github.com/repos/scrapinghub/python-scrapinghub/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/scrapinghub/python-scrapinghub/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/scrapinghub/python-scrapinghub/git/refs{/sha}","trees_url":"https://api.github.com/repos/scrapinghub/python-scrapinghub/git/trees{/sha}","statuses_url":"https://api.github.com/repos/scrapinghub/python-scrapinghub/statuses/{sha}","languages_url":"https://api.github.com/repos/scrapinghub/python-scrapinghub/languages","stargazers_url":"https://api.github.com/repos/scrapinghub/python-scrapinghub/stargazers","contributors_url":"https://api.github.com/repos/scrapinghub/python-scrapinghub/contributors","subscribers_url":"https://api.github.com/repos/scrapinghub/python-scrapinghub/subscribers","subscription_url":"https://api.github.com/repos/scrapinghub/python-scrapinghub/subscription","commits_url":"https://api.github.com/repos/scrapinghub/python-scrapinghub/commits{/sha}","git_commits_url":"https://api.github.com/repos/scrapinghub/python-scrapinghub/git/commits{/sha}","comments_url":"https://api.github.com/repos/scrapinghub/python-scrapinghub/comments{/number}","issue_comment_url":"https://api.github.com/repos/scrapinghub/python-scrapinghub/issues/comments{/number}","contents_url":"https://api.github.com/repos/scrapinghub/python-scrapinghub/contents/{+path}","compare_url":"https://api.github.com/repos/scrapinghub/python-scrapinghub/compare/{base}...{head}","merges_url":"https://api.github.com/repos/scrapinghub/python-scrapinghub/merges","archive_url":"https://api.github.com/repos/scrapinghub/python-scrapinghub/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/scrapinghub/python-scrapinghub/downloads","issues_url":"https://api.github.com/repos/scrapinghub/python-scrapinghub/issues{/number}","pulls_url":"https://api.github.com/repos/scrapinghub/python-scrapinghub/pulls{/number}","milestones_url":"https://api.github.com/repos/scrapinghub/python-scrapinghub/milestones{/number}","notifications_url":"https://api.github.com/repos/scrapinghub/python-scrapinghub/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/scrapinghub/python-scrapinghub/labels{/name}","releases_url":"https://api.github.com/repos/scrapinghub/python-scrapinghub/releases{/id}","deployments_url":"https://api.github.com/repos/scrapinghub/python-scrapinghub/deployments","created_at":"2011-08-15T20:03:44Z","updated_at":"2017-02-16T15:21:12Z","pushed_at":"2017-02-17T12:26:03Z","git_url":"git://github.com/scrapinghub/python-scrapinghub.git","ssh_url":"git@github.com:scrapinghub/python-scrapinghub.git","clone_url":"https://github.com/scrapinghub/python-scrapinghub.git","svn_url":"https://github.com/scrapinghub/python-scrapinghub","homepage":"http://www.scrapinghub.com","size":1120,"stargazers_count":67,"watchers_count":67,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":27,"mirror_url":null,"open_issues_count":10,"forks":27,"open_issues":10,"watchers":67,"default_branch":"master"}},"base":{"label":"scrapinghub:sc1467-1","ref":"sc1467-1","sha":"8c3230e517ae2a533f0cda5ba5f4baeab0631a2b","user":{"login":"scrapinghub","id":699596,"avatar_url":"https://avatars.githubusercontent.com/u/699596?v=3","gravatar_id":"","url":"https://api.github.com/users/scrapinghub","html_url":"https://github.com/scrapinghub","followers_url":"https://api.github.com/users/scrapinghub/followers","following_url":"https://api.github.com/users/scrapinghub/following{/other_user}","gists_url":"https://api.github.com/users/scrapinghub/gists{/gist_id}","starred_url":"https://api.github.com/users/scrapinghub/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/scrapinghub/subscriptions","organizations_url":"https://api.github.com/users/scrapinghub/orgs","repos_url":"https://api.github.com/users/scrapinghub/repos","events_url":"https://api.github.com/users/scrapinghub/events{/privacy}","received_events_url":"https://api.github.com/users/scrapinghub/received_events","type":"Organization","site_admin":false},"repo":{"id":2211875,"name":"python-scrapinghub","full_name":"scrapinghub/python-scrapinghub","owner":{"login":"scrapinghub","id":699596,"avatar_url":"https://avatars.githubusercontent.com/u/699596?v=3","gravatar_id":"","url":"https://api.github.com/users/scrapinghub","html_url":"https://github.com/scrapinghub","followers_url":"https://api.github.com/users/scrapinghub/followers","following_url":"https://api.github.com/users/scrapinghub/following{/other_user}","gists_url":"https://api.github.com/users/scrapinghub/gists{/gist_id}","starred_url":"https://api.github.com/users/scrapinghub/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/scrapinghub/subscriptions","organizations_url":"https://api.github.com/users/scrapinghub/orgs","repos_url":"https://api.github.com/users/scrapinghub/repos","events_url":"https://api.github.com/users/scrapinghub/events{/privacy}","received_events_url":"https://api.github.com/users/scrapinghub/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/scrapinghub/python-scrapinghub","description":"A client interface for Scrapinghub's API","fork":false,"url":"https://api.github.com/repos/scrapinghub/python-scrapinghub","forks_url":"https://api.github.com/repos/scrapinghub/python-scrapinghub/forks","keys_url":"https://api.github.com/repos/scrapinghub/python-scrapinghub/keys{/key_id}","collaborators_url":"https://api.github.com/repos/scrapinghub/python-scrapinghub/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/scrapinghub/python-scrapinghub/teams","hooks_url":"https://api.github.com/repos/scrapinghub/python-scrapinghub/hooks","issue_events_url":"https://api.github.com/repos/scrapinghub/python-scrapinghub/issues/events{/number}","events_url":"https://api.github.com/repos/scrapinghub/python-scrapinghub/events","assignees_url":"https://api.github.com/repos/scrapinghub/python-scrapinghub/assignees{/user}","branches_url":"https://api.github.com/repos/scrapinghub/python-scrapinghub/branches{/branch}","tags_url":"https://api.github.com/repos/scrapinghub/python-scrapinghub/tags","blobs_url":"https://api.github.com/repos/scrapinghub/python-scrapinghub/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/scrapinghub/python-scrapinghub/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/scrapinghub/python-scrapinghub/git/refs{/sha}","trees_url":"https://api.github.com/repos/scrapinghub/python-scrapinghub/git/trees{/sha}","statuses_url":"https://api.github.com/repos/scrapinghub/python-scrapinghub/statuses/{sha}","languages_url":"https://api.github.com/repos/scrapinghub/python-scrapinghub/languages","stargazers_url":"https://api.github.com/repos/scrapinghub/python-scrapinghub/stargazers","contributors_url":"https://api.github.com/repos/scrapinghub/python-scrapinghub/contributors","subscribers_url":"https://api.github.com/repos/scrapinghub/python-scrapinghub/subscribers","subscription_url":"https://api.github.com/repos/scrapinghub/python-scrapinghub/subscription","commits_url":"https://api.github.com/repos/scrapinghub/python-scrapinghub/commits{/sha}","git_commits_url":"https://api.github.com/repos/scrapinghub/python-scrapinghub/git/commits{/sha}","comments_url":"https://api.github.com/repos/scrapinghub/python-scrapinghub/comments{/number}","issue_comment_url":"https://api.github.com/repos/scrapinghub/python-scrapinghub/issues/comments{/number}","contents_url":"https://api.github.com/repos/scrapinghub/python-scrapinghub/contents/{+path}","compare_url":"https://api.github.com/repos/scrapinghub/python-scrapinghub/compare/{base}...{head}","merges_url":"https://api.github.com/repos/scrapinghub/python-scrapinghub/merges","archive_url":"https://api.github.com/repos/scrapinghub/python-scrapinghub/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/scrapinghub/python-scrapinghub/downloads","issues_url":"https://api.github.com/repos/scrapinghub/python-scrapinghub/issues{/number}","pulls_url":"https://api.github.com/repos/scrapinghub/python-scrapinghub/pulls{/number}","milestones_url":"https://api.github.com/repos/scrapinghub/python-scrapinghub/milestones{/number}","notifications_url":"https://api.github.com/repos/scrapinghub/python-scrapinghub/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/scrapinghub/python-scrapinghub/labels{/name}","releases_url":"https://api.github.com/repos/scrapinghub/python-scrapinghub/releases{/id}","deployments_url":"https://api.github.com/repos/scrapinghub/python-scrapinghub/deployments","created_at":"2011-08-15T20:03:44Z","updated_at":"2017-02-16T15:21:12Z","pushed_at":"2017-02-17T12:26:03Z","git_url":"git://github.com/scrapinghub/python-scrapinghub.git","ssh_url":"git@github.com:scrapinghub/python-scrapinghub.git","clone_url":"https://github.com/scrapinghub/python-scrapinghub.git","svn_url":"https://github.com/scrapinghub/python-scrapinghub","homepage":"http://www.scrapinghub.com","size":1120,"stargazers_count":67,"watchers_count":67,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":27,"mirror_url":null,"open_issues_count":10,"forks":27,"open_issues":10,"watchers":67,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/scrapinghub/python-scrapinghub/pulls/48"},"html":{"href":"https://github.com/scrapinghub/python-scrapinghub/pull/48"},"issue":{"href":"https://api.github.com/repos/scrapinghub/python-scrapinghub/issues/48"},"comments":{"href":"https://api.github.com/repos/scrapinghub/python-scrapinghub/issues/48/comments"},"review_comments":{"href":"https://api.github.com/repos/scrapinghub/python-scrapinghub/pulls/48/comments"},"review_comment":{"href":"https://api.github.com/repos/scrapinghub/python-scrapinghub/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/scrapinghub/python-scrapinghub/pulls/48/commits"},"statuses":{"href":"https://api.github.com/repos/scrapinghub/python-scrapinghub/statuses/fdab51f51205bae792d6ef61ca34abfdf31355de"}}}}
{"actor":{"display_login":"chekunkov"}}