{"action":"created","comment":{"url":"https://api.github.com/repos/djc/couchdb-python/pulls/comments/64024456","id":64024456,"diff_hunk":"@@ -0,0 +1,583 @@\n+# -*- coding: utf-8 -*-\n+#\n+import unittest\n+\n+from functools import partial\n+from io import StringIO\n+\n+from couchdb import json\n+from couchdb.server import BaseQueryServer, SimpleQueryServer\n+from couchdb.server import exceptions\n+from couchdb.server.helpers import wrap_func_to_ddoc\n+\n+\n+class BaseQueryServerTestCase(unittest.TestCase):\n+\n+    def test_set_version(self):\n+        server = BaseQueryServer((1, 2, 3))\n+        self.assertEqual(server.version, (1, 2, 3))\n+\n+    def test_set_latest_version_by_default(self):\n+        server = BaseQueryServer()\n+        self.assertEqual(server.version, (999, 999, 999))\n+\n+    def test_set_config_option(self):\n+        server = BaseQueryServer(foo='bar')\n+        self.assertTrue('foo' in server.config)\n+        self.assertEqual(server.config['foo'], 'bar')\n+\n+    def test_config_option_handler(self):\n+        class CustomServer(BaseQueryServer):\n+            def config_foo(self, value):\n+                self.config['baz'] = value\n+        server = CustomServer(foo='bar')\n+        self.assertTrue('foo' not in server.config)\n+        self.assertTrue('baz' in server.config)\n+        self.assertEqual(server.config['baz'], 'bar')\n+\n+    def test_pass_server_instance_to_command_handler(self):\n+        server = BaseQueryServer()\n+        server.commands['foo'] = lambda s, x: server is s\n+        self.assertTrue(server.process_request(['foo', 'bar']))\n+\n+    def test_raise_fatal_error_on_unknown_command(self):\n+        server = BaseQueryServer(output=StringIO())\n+        try:\n+            server.process_request(['foo', 'bar'])\n+        except Exception as err:\n+            self.assertTrue(isinstance(err, exceptions.FatalError))\n+            self.assertEqual(err.args[0], 'unknown_command')\n+\n+    def test_handle_fatal_error(self):\n+        def command_foo(*a, **k):\n+            raise exceptions.FatalError('foo', 'bar')\n+\n+        def maybe_fatal_error(func):\n+            def wrapper(exc_type, exc_value, exc_traceback):\n+                assert exc_type is exceptions.FatalError\n+                return func(exc_type, exc_value, exc_traceback)\n+            return wrapper\n+\n+        output = StringIO()\n+        server = BaseQueryServer(output=output)\n+        server.handle_fatal_error = maybe_fatal_error(server.handle_fatal_error)\n+        server.commands['foo'] = command_foo\n+        try:\n+            server.process_request(['foo', 'bar'])\n+        except Exception as err:\n+            self.assertTrue(isinstance(err, exceptions.FatalError))\n+\n+    def test_response_for_fatal_error_oldstyle(self):\n+        def command_foo(*a, **k):\n+            raise exceptions.FatalError('foo', 'bar')\n+\n+        output = StringIO()\n+        server = BaseQueryServer(version=(0, 9, 0), output=output)\n+        server.commands['foo'] = command_foo\n+        expected = {'reason': 'bar', 'error': 'foo'}\n+        try:\n+            server.process_request(['foo', 'bar'])\n+        except Exception:\n+            pass","path":"couchdb/tests/server/qs.py","position":81,"original_position":81,"commit_id":"39131fd822c2a24d0e261063fe35e522bcdc16ca","original_commit_id":"39131fd822c2a24d0e261063fe35e522bcdc16ca","user":{"login":"iblis17","id":761623,"avatar_url":"https://avatars.githubusercontent.com/u/761623?v=3","gravatar_id":"","url":"https://api.github.com/users/iblis17","html_url":"https://github.com/iblis17","followers_url":"https://api.github.com/users/iblis17/followers","following_url":"https://api.github.com/users/iblis17/following{/other_user}","gists_url":"https://api.github.com/users/iblis17/gists{/gist_id}","starred_url":"https://api.github.com/users/iblis17/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/iblis17/subscriptions","organizations_url":"https://api.github.com/users/iblis17/orgs","repos_url":"https://api.github.com/users/iblis17/repos","events_url":"https://api.github.com/users/iblis17/events{/privacy}","received_events_url":"https://api.github.com/users/iblis17/received_events","type":"User","site_admin":false},"body":"Why we do not check exception type here? or maybe we can change whole `try-except` block into `assertRaises`.","created_at":"2016-05-20T11:07:06Z","updated_at":"2016-05-20T11:07:06Z","html_url":"https://github.com/djc/couchdb-python/pull/286#discussion_r64024456","pull_request_url":"https://api.github.com/repos/djc/couchdb-python/pulls/286","_links":{"self":{"href":"https://api.github.com/repos/djc/couchdb-python/pulls/comments/64024456"},"html":{"href":"https://github.com/djc/couchdb-python/pull/286#discussion_r64024456"},"pull_request":{"href":"https://api.github.com/repos/djc/couchdb-python/pulls/286"}}},"pull_request":{"url":"https://api.github.com/repos/djc/couchdb-python/pulls/286","id":70120109,"html_url":"https://github.com/djc/couchdb-python/pull/286","diff_url":"https://github.com/djc/couchdb-python/pull/286.diff","patch_url":"https://github.com/djc/couchdb-python/pull/286.patch","issue_url":"https://api.github.com/repos/djc/couchdb-python/issues/286","number":286,"state":"open","locked":false,"title":"Query Server package code review","user":{"login":"iblis17","id":761623,"avatar_url":"https://avatars.githubusercontent.com/u/761623?v=3","gravatar_id":"","url":"https://api.github.com/users/iblis17","html_url":"https://github.com/iblis17","followers_url":"https://api.github.com/users/iblis17/followers","following_url":"https://api.github.com/users/iblis17/following{/other_user}","gists_url":"https://api.github.com/users/iblis17/gists{/gist_id}","starred_url":"https://api.github.com/users/iblis17/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/iblis17/subscriptions","organizations_url":"https://api.github.com/users/iblis17/orgs","repos_url":"https://api.github.com/users/iblis17/repos","events_url":"https://api.github.com/users/iblis17/events{/privacy}","received_events_url":"https://api.github.com/users/iblis17/received_events","type":"User","site_admin":false},"body":"Let's review it commit-by-commit!\r\n\r\nSome highlight:\r\n- The `__main__.py` will invoke `server.__init__.SimpleQueryServer`\r\n- The `SimpleQueryServer` support some legacy query protocol. Are we still need them?\r\n\r\nHere is the snippet about the command support.\r\n```python\r\n        if (0, 9, 0) <= self.version < (0, 10, 0):\r\n            self.commands['show_doc'] = render.show_doc\r\n            self.commands['list_begin'] = render.list_begin\r\n            self.commands['list_row'] = render.list_row\r\n            self.commands['list_tail'] = render.list_tail\r\n            self.commands['validate'] = validate.validate\r\n\r\n        elif (0, 10, 0) <= self.version < (0, 11, 0):\r\n            self.commands['show'] = render.show\r\n            self.commands['list'] = render.list\r\n            self.commands['filter'] = filters.filter\r\n            self.commands['update'] = render.update\r\n            self.commands['validate'] = validate.validate\r\n\r\n        elif self.version >= (0, 11, 0):\r\n            ddoc_commands = {}\r\n            ddoc_commands['shows'] = render.ddoc_show\r\n            ddoc_commands['lists'] = render.ddoc_list\r\n            ddoc_commands['filters'] = filters.ddoc_filter\r\n            ddoc_commands['updates'] = render.ddoc_update\r\n            ddoc_commands['validate_doc_update'] = validate.ddoc_validate\r\n\r\n        if self.version >= (1, 1, 0):\r\n            self.commands['add_lib'] = state.add_lib\r\n            ddoc_commands['views'] = filters.ddoc_views\r\n\r\n        if self.version >= (0, 11, 0):\r\n            self.commands['ddoc'] = ddoc.DDoc(ddoc_commands)\r\n```","created_at":"2016-05-15T12:36:41Z","updated_at":"2016-05-20T11:07:06Z","closed_at":null,"merged_at":null,"merge_commit_sha":"51da74cdcc07c1cf63f2aa15f539277832313ffa","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/djc/couchdb-python/pulls/286/commits","review_comments_url":"https://api.github.com/repos/djc/couchdb-python/pulls/286/comments","review_comment_url":"https://api.github.com/repos/djc/couchdb-python/pulls/comments{/number}","comments_url":"https://api.github.com/repos/djc/couchdb-python/issues/286/comments","statuses_url":"https://api.github.com/repos/djc/couchdb-python/statuses/39131fd822c2a24d0e261063fe35e522bcdc16ca","head":{"label":"iblis17:issue-268","ref":"issue-268","sha":"39131fd822c2a24d0e261063fe35e522bcdc16ca","user":{"login":"iblis17","id":761623,"avatar_url":"https://avatars.githubusercontent.com/u/761623?v=3","gravatar_id":"","url":"https://api.github.com/users/iblis17","html_url":"https://github.com/iblis17","followers_url":"https://api.github.com/users/iblis17/followers","following_url":"https://api.github.com/users/iblis17/following{/other_user}","gists_url":"https://api.github.com/users/iblis17/gists{/gist_id}","starred_url":"https://api.github.com/users/iblis17/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/iblis17/subscriptions","organizations_url":"https://api.github.com/users/iblis17/orgs","repos_url":"https://api.github.com/users/iblis17/repos","events_url":"https://api.github.com/users/iblis17/events{/privacy}","received_events_url":"https://api.github.com/users/iblis17/received_events","type":"User","site_admin":false},"repo":{"id":52525290,"name":"couchdb-python","full_name":"iblis17/couchdb-python","owner":{"login":"iblis17","id":761623,"avatar_url":"https://avatars.githubusercontent.com/u/761623?v=3","gravatar_id":"","url":"https://api.github.com/users/iblis17","html_url":"https://github.com/iblis17","followers_url":"https://api.github.com/users/iblis17/followers","following_url":"https://api.github.com/users/iblis17/following{/other_user}","gists_url":"https://api.github.com/users/iblis17/gists{/gist_id}","starred_url":"https://api.github.com/users/iblis17/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/iblis17/subscriptions","organizations_url":"https://api.github.com/users/iblis17/orgs","repos_url":"https://api.github.com/users/iblis17/repos","events_url":"https://api.github.com/users/iblis17/events{/privacy}","received_events_url":"https://api.github.com/users/iblis17/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/iblis17/couchdb-python","description":"Python library for working with CouchDB","fork":true,"url":"https://api.github.com/repos/iblis17/couchdb-python","forks_url":"https://api.github.com/repos/iblis17/couchdb-python/forks","keys_url":"https://api.github.com/repos/iblis17/couchdb-python/keys{/key_id}","collaborators_url":"https://api.github.com/repos/iblis17/couchdb-python/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/iblis17/couchdb-python/teams","hooks_url":"https://api.github.com/repos/iblis17/couchdb-python/hooks","issue_events_url":"https://api.github.com/repos/iblis17/couchdb-python/issues/events{/number}","events_url":"https://api.github.com/repos/iblis17/couchdb-python/events","assignees_url":"https://api.github.com/repos/iblis17/couchdb-python/assignees{/user}","branches_url":"https://api.github.com/repos/iblis17/couchdb-python/branches{/branch}","tags_url":"https://api.github.com/repos/iblis17/couchdb-python/tags","blobs_url":"https://api.github.com/repos/iblis17/couchdb-python/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/iblis17/couchdb-python/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/iblis17/couchdb-python/git/refs{/sha}","trees_url":"https://api.github.com/repos/iblis17/couchdb-python/git/trees{/sha}","statuses_url":"https://api.github.com/repos/iblis17/couchdb-python/statuses/{sha}","languages_url":"https://api.github.com/repos/iblis17/couchdb-python/languages","stargazers_url":"https://api.github.com/repos/iblis17/couchdb-python/stargazers","contributors_url":"https://api.github.com/repos/iblis17/couchdb-python/contributors","subscribers_url":"https://api.github.com/repos/iblis17/couchdb-python/subscribers","subscription_url":"https://api.github.com/repos/iblis17/couchdb-python/subscription","commits_url":"https://api.github.com/repos/iblis17/couchdb-python/commits{/sha}","git_commits_url":"https://api.github.com/repos/iblis17/couchdb-python/git/commits{/sha}","comments_url":"https://api.github.com/repos/iblis17/couchdb-python/comments{/number}","issue_comment_url":"https://api.github.com/repos/iblis17/couchdb-python/issues/comments{/number}","contents_url":"https://api.github.com/repos/iblis17/couchdb-python/contents/{+path}","compare_url":"https://api.github.com/repos/iblis17/couchdb-python/compare/{base}...{head}","merges_url":"https://api.github.com/repos/iblis17/couchdb-python/merges","archive_url":"https://api.github.com/repos/iblis17/couchdb-python/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/iblis17/couchdb-python/downloads","issues_url":"https://api.github.com/repos/iblis17/couchdb-python/issues{/number}","pulls_url":"https://api.github.com/repos/iblis17/couchdb-python/pulls{/number}","milestones_url":"https://api.github.com/repos/iblis17/couchdb-python/milestones{/number}","notifications_url":"https://api.github.com/repos/iblis17/couchdb-python/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/iblis17/couchdb-python/labels{/name}","releases_url":"https://api.github.com/repos/iblis17/couchdb-python/releases{/id}","deployments_url":"https://api.github.com/repos/iblis17/couchdb-python/deployments","created_at":"2016-02-25T13:12:43Z","updated_at":"2016-02-25T13:12:44Z","pushed_at":"2016-05-20T02:49:58Z","git_url":"git://github.com/iblis17/couchdb-python.git","ssh_url":"git@github.com:iblis17/couchdb-python.git","clone_url":"https://github.com/iblis17/couchdb-python.git","svn_url":"https://github.com/iblis17/couchdb-python","homepage":null,"size":1065,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"djc:master","ref":"master","sha":"b4296412f2c21e93f5c0c97f3a7f68e81cee0d0f","user":{"login":"djc","id":158471,"avatar_url":"https://avatars.githubusercontent.com/u/158471?v=3","gravatar_id":"","url":"https://api.github.com/users/djc","html_url":"https://github.com/djc","followers_url":"https://api.github.com/users/djc/followers","following_url":"https://api.github.com/users/djc/following{/other_user}","gists_url":"https://api.github.com/users/djc/gists{/gist_id}","starred_url":"https://api.github.com/users/djc/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/djc/subscriptions","organizations_url":"https://api.github.com/users/djc/orgs","repos_url":"https://api.github.com/users/djc/repos","events_url":"https://api.github.com/users/djc/events{/privacy}","received_events_url":"https://api.github.com/users/djc/received_events","type":"User","site_admin":false},"repo":{"id":21768042,"name":"couchdb-python","full_name":"djc/couchdb-python","owner":{"login":"djc","id":158471,"avatar_url":"https://avatars.githubusercontent.com/u/158471?v=3","gravatar_id":"","url":"https://api.github.com/users/djc","html_url":"https://github.com/djc","followers_url":"https://api.github.com/users/djc/followers","following_url":"https://api.github.com/users/djc/following{/other_user}","gists_url":"https://api.github.com/users/djc/gists{/gist_id}","starred_url":"https://api.github.com/users/djc/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/djc/subscriptions","organizations_url":"https://api.github.com/users/djc/orgs","repos_url":"https://api.github.com/users/djc/repos","events_url":"https://api.github.com/users/djc/events{/privacy}","received_events_url":"https://api.github.com/users/djc/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/djc/couchdb-python","description":"Python library for working with CouchDB","fork":false,"url":"https://api.github.com/repos/djc/couchdb-python","forks_url":"https://api.github.com/repos/djc/couchdb-python/forks","keys_url":"https://api.github.com/repos/djc/couchdb-python/keys{/key_id}","collaborators_url":"https://api.github.com/repos/djc/couchdb-python/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/djc/couchdb-python/teams","hooks_url":"https://api.github.com/repos/djc/couchdb-python/hooks","issue_events_url":"https://api.github.com/repos/djc/couchdb-python/issues/events{/number}","events_url":"https://api.github.com/repos/djc/couchdb-python/events","assignees_url":"https://api.github.com/repos/djc/couchdb-python/assignees{/user}","branches_url":"https://api.github.com/repos/djc/couchdb-python/branches{/branch}","tags_url":"https://api.github.com/repos/djc/couchdb-python/tags","blobs_url":"https://api.github.com/repos/djc/couchdb-python/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/djc/couchdb-python/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/djc/couchdb-python/git/refs{/sha}","trees_url":"https://api.github.com/repos/djc/couchdb-python/git/trees{/sha}","statuses_url":"https://api.github.com/repos/djc/couchdb-python/statuses/{sha}","languages_url":"https://api.github.com/repos/djc/couchdb-python/languages","stargazers_url":"https://api.github.com/repos/djc/couchdb-python/stargazers","contributors_url":"https://api.github.com/repos/djc/couchdb-python/contributors","subscribers_url":"https://api.github.com/repos/djc/couchdb-python/subscribers","subscription_url":"https://api.github.com/repos/djc/couchdb-python/subscription","commits_url":"https://api.github.com/repos/djc/couchdb-python/commits{/sha}","git_commits_url":"https://api.github.com/repos/djc/couchdb-python/git/commits{/sha}","comments_url":"https://api.github.com/repos/djc/couchdb-python/comments{/number}","issue_comment_url":"https://api.github.com/repos/djc/couchdb-python/issues/comments{/number}","contents_url":"https://api.github.com/repos/djc/couchdb-python/contents/{+path}","compare_url":"https://api.github.com/repos/djc/couchdb-python/compare/{base}...{head}","merges_url":"https://api.github.com/repos/djc/couchdb-python/merges","archive_url":"https://api.github.com/repos/djc/couchdb-python/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/djc/couchdb-python/downloads","issues_url":"https://api.github.com/repos/djc/couchdb-python/issues{/number}","pulls_url":"https://api.github.com/repos/djc/couchdb-python/pulls{/number}","milestones_url":"https://api.github.com/repos/djc/couchdb-python/milestones{/number}","notifications_url":"https://api.github.com/repos/djc/couchdb-python/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/djc/couchdb-python/labels{/name}","releases_url":"https://api.github.com/repos/djc/couchdb-python/releases{/id}","deployments_url":"https://api.github.com/repos/djc/couchdb-python/deployments","created_at":"2014-07-12T13:43:41Z","updated_at":"2016-05-13T15:52:27Z","pushed_at":"2016-05-20T02:49:59Z","git_url":"git://github.com/djc/couchdb-python.git","ssh_url":"git@github.com:djc/couchdb-python.git","clone_url":"https://github.com/djc/couchdb-python.git","svn_url":"https://github.com/djc/couchdb-python","homepage":null,"size":1113,"stargazers_count":94,"watchers_count":94,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":34,"mirror_url":null,"open_issues_count":43,"forks":34,"open_issues":43,"watchers":94,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/djc/couchdb-python/pulls/286"},"html":{"href":"https://github.com/djc/couchdb-python/pull/286"},"issue":{"href":"https://api.github.com/repos/djc/couchdb-python/issues/286"},"comments":{"href":"https://api.github.com/repos/djc/couchdb-python/issues/286/comments"},"review_comments":{"href":"https://api.github.com/repos/djc/couchdb-python/pulls/286/comments"},"review_comment":{"href":"https://api.github.com/repos/djc/couchdb-python/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/djc/couchdb-python/pulls/286/commits"},"statuses":{"href":"https://api.github.com/repos/djc/couchdb-python/statuses/39131fd822c2a24d0e261063fe35e522bcdc16ca"}}}}
{"actor":{"display_login":"iblis17"}}