{"action":"created","comment":{"url":"https://api.github.com/repos/mitmproxy/mitmproxy/pulls/comments/64996744","id":64996744,"diff_hunk":"@@ -147,23 +167,63 @@ def __call__(self, msg=False):\n NO_REPLY = object()\n \n \n-class Reply(object):\n+def handler(f):\n+    @functools.wraps(f)\n+    def wrapper(*args, **kwargs):\n+        if len(args) == 1:\n+            message = args[0]\n+        elif len(args) == 2:\n+            message = args[1]\n+        else:\n+            raise ControlError(\"Handler takes one argument: a message\")\n+\n+        if not hasattr(message, \"reply\"):\n+            raise ControlError(\"Message %s has no reply attribute\"%message)\n+\n+        handling = False\n+        # We're the first handler - ack responsibility is ours\n+        if not message.reply.handled:\n+            handling = True\n+            message.reply.handled = True\n+\n+        ret = f(*args, **kwargs)\n \n+        if handling and not message.reply.acked and not message.reply.taken:\n+            message.reply()\n+        return ret\n+    wrapper.func_dict[\"__handler\"] = True","path":"mitmproxy/controller.py","position":211,"original_position":211,"commit_id":"0176f50e4f4994be4b19be212f3a3db053a18d0c","original_commit_id":"0176f50e4f4994be4b19be212f3a3db053a18d0c","user":{"login":"cortesi","id":22544,"avatar_url":"https://avatars.githubusercontent.com/u/22544?v=3","gravatar_id":"","url":"https://api.github.com/users/cortesi","html_url":"https://github.com/cortesi","followers_url":"https://api.github.com/users/cortesi/followers","following_url":"https://api.github.com/users/cortesi/following{/other_user}","gists_url":"https://api.github.com/users/cortesi/gists{/gist_id}","starred_url":"https://api.github.com/users/cortesi/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cortesi/subscriptions","organizations_url":"https://api.github.com/users/cortesi/orgs","repos_url":"https://api.github.com/users/cortesi/repos","events_url":"https://api.github.com/users/cortesi/events{/privacy}","received_events_url":"https://api.github.com/users/cortesi/received_events","type":"User","site_admin":false},"body":"Using func_dict is mildly more explicit about what we're doing. I don't have strong feelings here.","created_at":"2016-05-29T02:16:51Z","updated_at":"2016-05-29T02:16:51Z","html_url":"https://github.com/mitmproxy/mitmproxy/pull/1172#discussion_r64996744","pull_request_url":"https://api.github.com/repos/mitmproxy/mitmproxy/pulls/1172","_links":{"self":{"href":"https://api.github.com/repos/mitmproxy/mitmproxy/pulls/comments/64996744"},"html":{"href":"https://github.com/mitmproxy/mitmproxy/pull/1172#discussion_r64996744"},"pull_request":{"href":"https://api.github.com/repos/mitmproxy/mitmproxy/pulls/1172"}}},"pull_request":{"url":"https://api.github.com/repos/mitmproxy/mitmproxy/pulls/1172","id":71815430,"html_url":"https://github.com/mitmproxy/mitmproxy/pull/1172","diff_url":"https://github.com/mitmproxy/mitmproxy/pull/1172.diff","patch_url":"https://github.com/mitmproxy/mitmproxy/pull/1172.patch","issue_url":"https://api.github.com/repos/mitmproxy/mitmproxy/issues/1172","number":1172,"state":"open","locked":false,"title":"First steps to solidifying the core","user":{"login":"cortesi","id":22544,"avatar_url":"https://avatars.githubusercontent.com/u/22544?v=3","gravatar_id":"","url":"https://api.github.com/users/cortesi","html_url":"https://github.com/cortesi","followers_url":"https://api.github.com/users/cortesi/followers","following_url":"https://api.github.com/users/cortesi/following{/other_user}","gists_url":"https://api.github.com/users/cortesi/gists{/gist_id}","starred_url":"https://api.github.com/users/cortesi/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cortesi/subscriptions","organizations_url":"https://api.github.com/users/cortesi/orgs","repos_url":"https://api.github.com/users/cortesi/repos","events_url":"https://api.github.com/users/cortesi/events{/privacy}","received_events_url":"https://api.github.com/users/cortesi/received_events","type":"User","site_admin":false},"body":"This is a hefty patch that takes some first steps towards solidifying our core comms mechanism. Highlights include:\r\n\r\n- Introduce a @controller.handler decorator that automatically replys() to messages\r\n- Introduce a reply.take() method to take control of a message and prevent automatic reply. This makes the default use case the easy one, and lets us explicitly audit the codebase for places where extra care must be take to ensure that a message is eventually acked. \r\n- Handers are no longer named handle_message. The decorator makes clear what is a handler, so it's just \"message\" now.\r\n- Add an explicit list of permitted messages. This clarifies our mechanisms, and will be the start of better message documentation and more sophisticated handling mechanisms down the track.\r\n- Add a bunch of sanity checks for messages that are acked twice, or never, or are given invalid arguments. Use this to catch numerous occurrences throughout the codebase.\r\n- Simplify the class hierarchy in controller by merging Master and ServerMaster. \r\n\r\n\r\n\r\n\r\n","created_at":"2016-05-29T01:01:44Z","updated_at":"2016-05-29T02:16:51Z","closed_at":null,"merged_at":null,"merge_commit_sha":"7328a856475fd84a96a3f976bca53eb88ef4281b","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/mitmproxy/mitmproxy/pulls/1172/commits","review_comments_url":"https://api.github.com/repos/mitmproxy/mitmproxy/pulls/1172/comments","review_comment_url":"https://api.github.com/repos/mitmproxy/mitmproxy/pulls/comments{/number}","comments_url":"https://api.github.com/repos/mitmproxy/mitmproxy/issues/1172/comments","statuses_url":"https://api.github.com/repos/mitmproxy/mitmproxy/statuses/0176f50e4f4994be4b19be212f3a3db053a18d0c","head":{"label":"cortesi:solidcore","ref":"solidcore","sha":"0176f50e4f4994be4b19be212f3a3db053a18d0c","user":{"login":"cortesi","id":22544,"avatar_url":"https://avatars.githubusercontent.com/u/22544?v=3","gravatar_id":"","url":"https://api.github.com/users/cortesi","html_url":"https://github.com/cortesi","followers_url":"https://api.github.com/users/cortesi/followers","following_url":"https://api.github.com/users/cortesi/following{/other_user}","gists_url":"https://api.github.com/users/cortesi/gists{/gist_id}","starred_url":"https://api.github.com/users/cortesi/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cortesi/subscriptions","organizations_url":"https://api.github.com/users/cortesi/orgs","repos_url":"https://api.github.com/users/cortesi/repos","events_url":"https://api.github.com/users/cortesi/events{/privacy}","received_events_url":"https://api.github.com/users/cortesi/received_events","type":"User","site_admin":false},"repo":{"id":52783278,"name":"mitmproxy","full_name":"cortesi/mitmproxy","owner":{"login":"cortesi","id":22544,"avatar_url":"https://avatars.githubusercontent.com/u/22544?v=3","gravatar_id":"","url":"https://api.github.com/users/cortesi","html_url":"https://github.com/cortesi","followers_url":"https://api.github.com/users/cortesi/followers","following_url":"https://api.github.com/users/cortesi/following{/other_user}","gists_url":"https://api.github.com/users/cortesi/gists{/gist_id}","starred_url":"https://api.github.com/users/cortesi/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cortesi/subscriptions","organizations_url":"https://api.github.com/users/cortesi/orgs","repos_url":"https://api.github.com/users/cortesi/repos","events_url":"https://api.github.com/users/cortesi/events{/privacy}","received_events_url":"https://api.github.com/users/cortesi/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/cortesi/mitmproxy","description":"An interactive SSL-capable intercepting HTTP proxy for penetration testers and software developers","fork":true,"url":"https://api.github.com/repos/cortesi/mitmproxy","forks_url":"https://api.github.com/repos/cortesi/mitmproxy/forks","keys_url":"https://api.github.com/repos/cortesi/mitmproxy/keys{/key_id}","collaborators_url":"https://api.github.com/repos/cortesi/mitmproxy/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/cortesi/mitmproxy/teams","hooks_url":"https://api.github.com/repos/cortesi/mitmproxy/hooks","issue_events_url":"https://api.github.com/repos/cortesi/mitmproxy/issues/events{/number}","events_url":"https://api.github.com/repos/cortesi/mitmproxy/events","assignees_url":"https://api.github.com/repos/cortesi/mitmproxy/assignees{/user}","branches_url":"https://api.github.com/repos/cortesi/mitmproxy/branches{/branch}","tags_url":"https://api.github.com/repos/cortesi/mitmproxy/tags","blobs_url":"https://api.github.com/repos/cortesi/mitmproxy/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/cortesi/mitmproxy/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/cortesi/mitmproxy/git/refs{/sha}","trees_url":"https://api.github.com/repos/cortesi/mitmproxy/git/trees{/sha}","statuses_url":"https://api.github.com/repos/cortesi/mitmproxy/statuses/{sha}","languages_url":"https://api.github.com/repos/cortesi/mitmproxy/languages","stargazers_url":"https://api.github.com/repos/cortesi/mitmproxy/stargazers","contributors_url":"https://api.github.com/repos/cortesi/mitmproxy/contributors","subscribers_url":"https://api.github.com/repos/cortesi/mitmproxy/subscribers","subscription_url":"https://api.github.com/repos/cortesi/mitmproxy/subscription","commits_url":"https://api.github.com/repos/cortesi/mitmproxy/commits{/sha}","git_commits_url":"https://api.github.com/repos/cortesi/mitmproxy/git/commits{/sha}","comments_url":"https://api.github.com/repos/cortesi/mitmproxy/comments{/number}","issue_comment_url":"https://api.github.com/repos/cortesi/mitmproxy/issues/comments{/number}","contents_url":"https://api.github.com/repos/cortesi/mitmproxy/contents/{+path}","compare_url":"https://api.github.com/repos/cortesi/mitmproxy/compare/{base}...{head}","merges_url":"https://api.github.com/repos/cortesi/mitmproxy/merges","archive_url":"https://api.github.com/repos/cortesi/mitmproxy/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/cortesi/mitmproxy/downloads","issues_url":"https://api.github.com/repos/cortesi/mitmproxy/issues{/number}","pulls_url":"https://api.github.com/repos/cortesi/mitmproxy/pulls{/number}","milestones_url":"https://api.github.com/repos/cortesi/mitmproxy/milestones{/number}","notifications_url":"https://api.github.com/repos/cortesi/mitmproxy/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/cortesi/mitmproxy/labels{/name}","releases_url":"https://api.github.com/repos/cortesi/mitmproxy/releases{/id}","deployments_url":"https://api.github.com/repos/cortesi/mitmproxy/deployments","created_at":"2016-02-29T10:30:53Z","updated_at":"2016-05-24T06:09:48Z","pushed_at":"2016-05-29T00:55:05Z","git_url":"git://github.com/cortesi/mitmproxy.git","ssh_url":"git@github.com:cortesi/mitmproxy.git","clone_url":"https://github.com/cortesi/mitmproxy.git","svn_url":"https://github.com/cortesi/mitmproxy","homepage":"http://mitmproxy.org","size":28110,"stargazers_count":3,"watchers_count":3,"language":"JavaScript","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":3,"default_branch":"master"}},"base":{"label":"mitmproxy:master","ref":"master","sha":"7971dce2231bc32c25b962d425d8ad935568a699","user":{"login":"mitmproxy","id":4652787,"avatar_url":"https://avatars.githubusercontent.com/u/4652787?v=3","gravatar_id":"","url":"https://api.github.com/users/mitmproxy","html_url":"https://github.com/mitmproxy","followers_url":"https://api.github.com/users/mitmproxy/followers","following_url":"https://api.github.com/users/mitmproxy/following{/other_user}","gists_url":"https://api.github.com/users/mitmproxy/gists{/gist_id}","starred_url":"https://api.github.com/users/mitmproxy/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mitmproxy/subscriptions","organizations_url":"https://api.github.com/users/mitmproxy/orgs","repos_url":"https://api.github.com/users/mitmproxy/repos","events_url":"https://api.github.com/users/mitmproxy/events{/privacy}","received_events_url":"https://api.github.com/users/mitmproxy/received_events","type":"Organization","site_admin":false},"repo":{"id":519832,"name":"mitmproxy","full_name":"mitmproxy/mitmproxy","owner":{"login":"mitmproxy","id":4652787,"avatar_url":"https://avatars.githubusercontent.com/u/4652787?v=3","gravatar_id":"","url":"https://api.github.com/users/mitmproxy","html_url":"https://github.com/mitmproxy","followers_url":"https://api.github.com/users/mitmproxy/followers","following_url":"https://api.github.com/users/mitmproxy/following{/other_user}","gists_url":"https://api.github.com/users/mitmproxy/gists{/gist_id}","starred_url":"https://api.github.com/users/mitmproxy/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mitmproxy/subscriptions","organizations_url":"https://api.github.com/users/mitmproxy/orgs","repos_url":"https://api.github.com/users/mitmproxy/repos","events_url":"https://api.github.com/users/mitmproxy/events{/privacy}","received_events_url":"https://api.github.com/users/mitmproxy/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/mitmproxy/mitmproxy","description":"An interactive SSL-capable intercepting HTTP proxy for penetration testers and software developers","fork":false,"url":"https://api.github.com/repos/mitmproxy/mitmproxy","forks_url":"https://api.github.com/repos/mitmproxy/mitmproxy/forks","keys_url":"https://api.github.com/repos/mitmproxy/mitmproxy/keys{/key_id}","collaborators_url":"https://api.github.com/repos/mitmproxy/mitmproxy/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/mitmproxy/mitmproxy/teams","hooks_url":"https://api.github.com/repos/mitmproxy/mitmproxy/hooks","issue_events_url":"https://api.github.com/repos/mitmproxy/mitmproxy/issues/events{/number}","events_url":"https://api.github.com/repos/mitmproxy/mitmproxy/events","assignees_url":"https://api.github.com/repos/mitmproxy/mitmproxy/assignees{/user}","branches_url":"https://api.github.com/repos/mitmproxy/mitmproxy/branches{/branch}","tags_url":"https://api.github.com/repos/mitmproxy/mitmproxy/tags","blobs_url":"https://api.github.com/repos/mitmproxy/mitmproxy/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/mitmproxy/mitmproxy/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/mitmproxy/mitmproxy/git/refs{/sha}","trees_url":"https://api.github.com/repos/mitmproxy/mitmproxy/git/trees{/sha}","statuses_url":"https://api.github.com/repos/mitmproxy/mitmproxy/statuses/{sha}","languages_url":"https://api.github.com/repos/mitmproxy/mitmproxy/languages","stargazers_url":"https://api.github.com/repos/mitmproxy/mitmproxy/stargazers","contributors_url":"https://api.github.com/repos/mitmproxy/mitmproxy/contributors","subscribers_url":"https://api.github.com/repos/mitmproxy/mitmproxy/subscribers","subscription_url":"https://api.github.com/repos/mitmproxy/mitmproxy/subscription","commits_url":"https://api.github.com/repos/mitmproxy/mitmproxy/commits{/sha}","git_commits_url":"https://api.github.com/repos/mitmproxy/mitmproxy/git/commits{/sha}","comments_url":"https://api.github.com/repos/mitmproxy/mitmproxy/comments{/number}","issue_comment_url":"https://api.github.com/repos/mitmproxy/mitmproxy/issues/comments{/number}","contents_url":"https://api.github.com/repos/mitmproxy/mitmproxy/contents/{+path}","compare_url":"https://api.github.com/repos/mitmproxy/mitmproxy/compare/{base}...{head}","merges_url":"https://api.github.com/repos/mitmproxy/mitmproxy/merges","archive_url":"https://api.github.com/repos/mitmproxy/mitmproxy/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/mitmproxy/mitmproxy/downloads","issues_url":"https://api.github.com/repos/mitmproxy/mitmproxy/issues{/number}","pulls_url":"https://api.github.com/repos/mitmproxy/mitmproxy/pulls{/number}","milestones_url":"https://api.github.com/repos/mitmproxy/mitmproxy/milestones{/number}","notifications_url":"https://api.github.com/repos/mitmproxy/mitmproxy/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/mitmproxy/mitmproxy/labels{/name}","releases_url":"https://api.github.com/repos/mitmproxy/mitmproxy/releases{/id}","deployments_url":"https://api.github.com/repos/mitmproxy/mitmproxy/deployments","created_at":"2010-02-16T04:10:13Z","updated_at":"2016-05-28T20:20:19Z","pushed_at":"2016-05-29T02:10:51Z","git_url":"git://github.com/mitmproxy/mitmproxy.git","ssh_url":"git@github.com:mitmproxy/mitmproxy.git","clone_url":"https://github.com/mitmproxy/mitmproxy.git","svn_url":"https://github.com/mitmproxy/mitmproxy","homepage":"http://mitmproxy.org","size":31146,"stargazers_count":4997,"watchers_count":4997,"language":"JavaScript","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":718,"mirror_url":null,"open_issues_count":64,"forks":718,"open_issues":64,"watchers":4997,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/mitmproxy/mitmproxy/pulls/1172"},"html":{"href":"https://github.com/mitmproxy/mitmproxy/pull/1172"},"issue":{"href":"https://api.github.com/repos/mitmproxy/mitmproxy/issues/1172"},"comments":{"href":"https://api.github.com/repos/mitmproxy/mitmproxy/issues/1172/comments"},"review_comments":{"href":"https://api.github.com/repos/mitmproxy/mitmproxy/pulls/1172/comments"},"review_comment":{"href":"https://api.github.com/repos/mitmproxy/mitmproxy/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/mitmproxy/mitmproxy/pulls/1172/commits"},"statuses":{"href":"https://api.github.com/repos/mitmproxy/mitmproxy/statuses/0176f50e4f4994be4b19be212f3a3db053a18d0c"}}}}
{"actor":{"display_login":"cortesi"}}