{"action":"created","comment":{"url":"https://api.github.com/repos/uber/tchannel-python/pulls/comments/37336674","id":37336674,"diff_hunk":"@@ -35,97 +42,107 @@ class ProtocolError(TChannelError):\n         'tracing',\n     )\n \n+    code = None\n+\n     def __init__(\n         self,\n-        code,\n-        description,\n+        description=None,\n         id=None,\n         tracing=None,\n     ):\n         super(TChannelError, self).__init__(description)\n-        self.code = code\n         self.tracing = tracing\n         self.id = id\n         self.description = description\n \n+    @classmethod\n+    def from_code(cls, code, **kw):\n+        return {\n+            TIMEOUT: TimeoutError,\n+            CANCELED: CanceledError,\n+            BUSY: BusyError,\n+            DECLINED: DeclinedError,\n+            UNEXPECTED_ERROR: UnexpectedError,\n+            BAD_REQUEST: BadRequestError,\n+            NETWORK_ERROR: NetworkError,\n+            UNHEALTHY: UnhealthyError,\n+            FATAL: FatalProtocolError,\n+        }[code](**kw)\n+\n+\n+class AlwaysRetryableError(TChannelError):\n+    pass\n+\n \n-class InvalidMessageError(TChannelError):\n-    \"\"\"Represent an invalid message.\"\"\"\n+class PossiblyRetryableError(TChannelError):","path":"tchannel/errors.py","position":66,"original_position":66,"commit_id":"f2c715373562fd9dec1be7f666dd7f1083bd44b8","original_commit_id":"40d0db3b4b197146cb938bc048679743757b2041","user":{"login":"abhinav","id":41730,"avatar_url":"https://avatars.githubusercontent.com/u/41730?v=3","gravatar_id":"","url":"https://api.github.com/users/abhinav","html_url":"https://github.com/abhinav","followers_url":"https://api.github.com/users/abhinav/followers","following_url":"https://api.github.com/users/abhinav/following{/other_user}","gists_url":"https://api.github.com/users/abhinav/gists{/gist_id}","starred_url":"https://api.github.com/users/abhinav/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/abhinav/subscriptions","organizations_url":"https://api.github.com/users/abhinav/orgs","repos_url":"https://api.github.com/users/abhinav/repos","events_url":"https://api.github.com/users/abhinav/events{/privacy}","received_events_url":"https://api.github.com/users/abhinav/received_events","type":"User","site_admin":false},"body":"I agree that 'always retryable' and 'possibly retryable' could be confusing; especially because always retryable sounds like immediately and infinitely retryable. \r\n\r\nHow about just Retryable and with some sort of property that is true if the original request might have made it to the server?","created_at":"2015-08-18T18:41:13Z","updated_at":"2015-08-18T18:41:13Z","html_url":"https://github.com/uber/tchannel-python/pull/114#discussion_r37336674","pull_request_url":"https://api.github.com/repos/uber/tchannel-python/pulls/114","_links":{"self":{"href":"https://api.github.com/repos/uber/tchannel-python/pulls/comments/37336674"},"html":{"href":"https://github.com/uber/tchannel-python/pull/114#discussion_r37336674"},"pull_request":{"href":"https://api.github.com/repos/uber/tchannel-python/pulls/114"}}},"pull_request":{"url":"https://api.github.com/repos/uber/tchannel-python/pulls/114","id":42501872,"html_url":"https://github.com/uber/tchannel-python/pull/114","diff_url":"https://github.com/uber/tchannel-python/pull/114.diff","patch_url":"https://github.com/uber/tchannel-python/pull/114.patch","issue_url":"https://api.github.com/repos/uber/tchannel-python/issues/114","number":114,"state":"open","locked":false,"title":"improvments for exception handling","user":{"login":"blampe","id":848843,"avatar_url":"https://avatars.githubusercontent.com/u/848843?v=3","gravatar_id":"","url":"https://api.github.com/users/blampe","html_url":"https://github.com/blampe","followers_url":"https://api.github.com/users/blampe/followers","following_url":"https://api.github.com/users/blampe/following{/other_user}","gists_url":"https://api.github.com/users/blampe/gists{/gist_id}","starred_url":"https://api.github.com/users/blampe/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/blampe/subscriptions","organizations_url":"https://api.github.com/users/blampe/orgs","repos_url":"https://api.github.com/users/blampe/repos","events_url":"https://api.github.com/users/blampe/events{/privacy}","received_events_url":"https://api.github.com/users/blampe/received_events","type":"User","site_admin":false},"body":"Please pay attention to the hierarchy in `errors.py` and the exceptions we're now catching in tests. Compare these against [the spec](http://tchannel.readthedocs.org/en/latest/protocol/#code1_1).\r\n\r\n* Get rid of `ProtocolError`. That's a very particular error (`0xff`) that we don't want everything subclassing. \r\n* Add `AlwaysRetryableError`, `PossiblyRetryableError`, and `UnretryableError` to make the individual exceptions more actionable.\r\n* Got rid of some of the other exception classes like `TChannelApplicationError` (unused), `ConnectionClosedError` (already captured by `NetworkError`), `InvalidEndpointError ` (already captured by `BadRequest`), etc. \r\n* We were catching `InvalidChecksumError` and `StreamingError` and always returning those as `BadRequest`, now we return the original error.\r\n* Switched the default handler to not use defaultdict because it's slow.\r\n* I'm duplicating error codes (they're already in the message definition) but I didn't want this file importing from messages because it shouldn't have any dependencies.","created_at":"2015-08-14T21:57:11Z","updated_at":"2015-08-18T18:41:13Z","closed_at":null,"merged_at":null,"merge_commit_sha":"3575495150c8480a5415489c71a90648554b24dc","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/uber/tchannel-python/pulls/114/commits","review_comments_url":"https://api.github.com/repos/uber/tchannel-python/pulls/114/comments","review_comment_url":"https://api.github.com/repos/uber/tchannel-python/pulls/comments{/number}","comments_url":"https://api.github.com/repos/uber/tchannel-python/issues/114/comments","statuses_url":"https://api.github.com/repos/uber/tchannel-python/statuses/f2c715373562fd9dec1be7f666dd7f1083bd44b8","head":{"label":"uber:bryce_exceptions","ref":"bryce_exceptions","sha":"f2c715373562fd9dec1be7f666dd7f1083bd44b8","user":{"login":"uber","id":538264,"avatar_url":"https://avatars.githubusercontent.com/u/538264?v=3","gravatar_id":"","url":"https://api.github.com/users/uber","html_url":"https://github.com/uber","followers_url":"https://api.github.com/users/uber/followers","following_url":"https://api.github.com/users/uber/following{/other_user}","gists_url":"https://api.github.com/users/uber/gists{/gist_id}","starred_url":"https://api.github.com/users/uber/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/uber/subscriptions","organizations_url":"https://api.github.com/users/uber/orgs","repos_url":"https://api.github.com/users/uber/repos","events_url":"https://api.github.com/users/uber/events{/privacy}","received_events_url":"https://api.github.com/users/uber/received_events","type":"Organization","site_admin":false},"repo":{"id":38906603,"name":"tchannel-python","full_name":"uber/tchannel-python","owner":{"login":"uber","id":538264,"avatar_url":"https://avatars.githubusercontent.com/u/538264?v=3","gravatar_id":"","url":"https://api.github.com/users/uber","html_url":"https://github.com/uber","followers_url":"https://api.github.com/users/uber/followers","following_url":"https://api.github.com/users/uber/following{/other_user}","gists_url":"https://api.github.com/users/uber/gists{/gist_id}","starred_url":"https://api.github.com/users/uber/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/uber/subscriptions","organizations_url":"https://api.github.com/users/uber/orgs","repos_url":"https://api.github.com/users/uber/repos","events_url":"https://api.github.com/users/uber/events{/privacy}","received_events_url":"https://api.github.com/users/uber/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/uber/tchannel-python","description":"Python implementation of the TChannel protocol.","fork":false,"url":"https://api.github.com/repos/uber/tchannel-python","forks_url":"https://api.github.com/repos/uber/tchannel-python/forks","keys_url":"https://api.github.com/repos/uber/tchannel-python/keys{/key_id}","collaborators_url":"https://api.github.com/repos/uber/tchannel-python/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/uber/tchannel-python/teams","hooks_url":"https://api.github.com/repos/uber/tchannel-python/hooks","issue_events_url":"https://api.github.com/repos/uber/tchannel-python/issues/events{/number}","events_url":"https://api.github.com/repos/uber/tchannel-python/events","assignees_url":"https://api.github.com/repos/uber/tchannel-python/assignees{/user}","branches_url":"https://api.github.com/repos/uber/tchannel-python/branches{/branch}","tags_url":"https://api.github.com/repos/uber/tchannel-python/tags","blobs_url":"https://api.github.com/repos/uber/tchannel-python/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/uber/tchannel-python/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/uber/tchannel-python/git/refs{/sha}","trees_url":"https://api.github.com/repos/uber/tchannel-python/git/trees{/sha}","statuses_url":"https://api.github.com/repos/uber/tchannel-python/statuses/{sha}","languages_url":"https://api.github.com/repos/uber/tchannel-python/languages","stargazers_url":"https://api.github.com/repos/uber/tchannel-python/stargazers","contributors_url":"https://api.github.com/repos/uber/tchannel-python/contributors","subscribers_url":"https://api.github.com/repos/uber/tchannel-python/subscribers","subscription_url":"https://api.github.com/repos/uber/tchannel-python/subscription","commits_url":"https://api.github.com/repos/uber/tchannel-python/commits{/sha}","git_commits_url":"https://api.github.com/repos/uber/tchannel-python/git/commits{/sha}","comments_url":"https://api.github.com/repos/uber/tchannel-python/comments{/number}","issue_comment_url":"https://api.github.com/repos/uber/tchannel-python/issues/comments{/number}","contents_url":"https://api.github.com/repos/uber/tchannel-python/contents/{+path}","compare_url":"https://api.github.com/repos/uber/tchannel-python/compare/{base}...{head}","merges_url":"https://api.github.com/repos/uber/tchannel-python/merges","archive_url":"https://api.github.com/repos/uber/tchannel-python/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/uber/tchannel-python/downloads","issues_url":"https://api.github.com/repos/uber/tchannel-python/issues{/number}","pulls_url":"https://api.github.com/repos/uber/tchannel-python/pulls{/number}","milestones_url":"https://api.github.com/repos/uber/tchannel-python/milestones{/number}","notifications_url":"https://api.github.com/repos/uber/tchannel-python/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/uber/tchannel-python/labels{/name}","releases_url":"https://api.github.com/repos/uber/tchannel-python/releases{/id}","created_at":"2015-07-10T23:35:17Z","updated_at":"2015-07-28T15:38:06Z","pushed_at":"2015-08-18T17:24:00Z","git_url":"git://github.com/uber/tchannel-python.git","ssh_url":"git@github.com:uber/tchannel-python.git","clone_url":"https://github.com/uber/tchannel-python.git","svn_url":"https://github.com/uber/tchannel-python","homepage":null,"size":3454,"stargazers_count":7,"watchers_count":7,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":1,"mirror_url":null,"open_issues_count":23,"forks":1,"open_issues":23,"watchers":7,"default_branch":"master"}},"base":{"label":"uber:master","ref":"master","sha":"e2ef5e984ffe1469bcffe8f1010e1eab40548c2f","user":{"login":"uber","id":538264,"avatar_url":"https://avatars.githubusercontent.com/u/538264?v=3","gravatar_id":"","url":"https://api.github.com/users/uber","html_url":"https://github.com/uber","followers_url":"https://api.github.com/users/uber/followers","following_url":"https://api.github.com/users/uber/following{/other_user}","gists_url":"https://api.github.com/users/uber/gists{/gist_id}","starred_url":"https://api.github.com/users/uber/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/uber/subscriptions","organizations_url":"https://api.github.com/users/uber/orgs","repos_url":"https://api.github.com/users/uber/repos","events_url":"https://api.github.com/users/uber/events{/privacy}","received_events_url":"https://api.github.com/users/uber/received_events","type":"Organization","site_admin":false},"repo":{"id":38906603,"name":"tchannel-python","full_name":"uber/tchannel-python","owner":{"login":"uber","id":538264,"avatar_url":"https://avatars.githubusercontent.com/u/538264?v=3","gravatar_id":"","url":"https://api.github.com/users/uber","html_url":"https://github.com/uber","followers_url":"https://api.github.com/users/uber/followers","following_url":"https://api.github.com/users/uber/following{/other_user}","gists_url":"https://api.github.com/users/uber/gists{/gist_id}","starred_url":"https://api.github.com/users/uber/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/uber/subscriptions","organizations_url":"https://api.github.com/users/uber/orgs","repos_url":"https://api.github.com/users/uber/repos","events_url":"https://api.github.com/users/uber/events{/privacy}","received_events_url":"https://api.github.com/users/uber/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/uber/tchannel-python","description":"Python implementation of the TChannel protocol.","fork":false,"url":"https://api.github.com/repos/uber/tchannel-python","forks_url":"https://api.github.com/repos/uber/tchannel-python/forks","keys_url":"https://api.github.com/repos/uber/tchannel-python/keys{/key_id}","collaborators_url":"https://api.github.com/repos/uber/tchannel-python/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/uber/tchannel-python/teams","hooks_url":"https://api.github.com/repos/uber/tchannel-python/hooks","issue_events_url":"https://api.github.com/repos/uber/tchannel-python/issues/events{/number}","events_url":"https://api.github.com/repos/uber/tchannel-python/events","assignees_url":"https://api.github.com/repos/uber/tchannel-python/assignees{/user}","branches_url":"https://api.github.com/repos/uber/tchannel-python/branches{/branch}","tags_url":"https://api.github.com/repos/uber/tchannel-python/tags","blobs_url":"https://api.github.com/repos/uber/tchannel-python/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/uber/tchannel-python/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/uber/tchannel-python/git/refs{/sha}","trees_url":"https://api.github.com/repos/uber/tchannel-python/git/trees{/sha}","statuses_url":"https://api.github.com/repos/uber/tchannel-python/statuses/{sha}","languages_url":"https://api.github.com/repos/uber/tchannel-python/languages","stargazers_url":"https://api.github.com/repos/uber/tchannel-python/stargazers","contributors_url":"https://api.github.com/repos/uber/tchannel-python/contributors","subscribers_url":"https://api.github.com/repos/uber/tchannel-python/subscribers","subscription_url":"https://api.github.com/repos/uber/tchannel-python/subscription","commits_url":"https://api.github.com/repos/uber/tchannel-python/commits{/sha}","git_commits_url":"https://api.github.com/repos/uber/tchannel-python/git/commits{/sha}","comments_url":"https://api.github.com/repos/uber/tchannel-python/comments{/number}","issue_comment_url":"https://api.github.com/repos/uber/tchannel-python/issues/comments{/number}","contents_url":"https://api.github.com/repos/uber/tchannel-python/contents/{+path}","compare_url":"https://api.github.com/repos/uber/tchannel-python/compare/{base}...{head}","merges_url":"https://api.github.com/repos/uber/tchannel-python/merges","archive_url":"https://api.github.com/repos/uber/tchannel-python/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/uber/tchannel-python/downloads","issues_url":"https://api.github.com/repos/uber/tchannel-python/issues{/number}","pulls_url":"https://api.github.com/repos/uber/tchannel-python/pulls{/number}","milestones_url":"https://api.github.com/repos/uber/tchannel-python/milestones{/number}","notifications_url":"https://api.github.com/repos/uber/tchannel-python/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/uber/tchannel-python/labels{/name}","releases_url":"https://api.github.com/repos/uber/tchannel-python/releases{/id}","created_at":"2015-07-10T23:35:17Z","updated_at":"2015-07-28T15:38:06Z","pushed_at":"2015-08-18T17:24:00Z","git_url":"git://github.com/uber/tchannel-python.git","ssh_url":"git@github.com:uber/tchannel-python.git","clone_url":"https://github.com/uber/tchannel-python.git","svn_url":"https://github.com/uber/tchannel-python","homepage":null,"size":3454,"stargazers_count":7,"watchers_count":7,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":1,"mirror_url":null,"open_issues_count":23,"forks":1,"open_issues":23,"watchers":7,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/uber/tchannel-python/pulls/114"},"html":{"href":"https://github.com/uber/tchannel-python/pull/114"},"issue":{"href":"https://api.github.com/repos/uber/tchannel-python/issues/114"},"comments":{"href":"https://api.github.com/repos/uber/tchannel-python/issues/114/comments"},"review_comments":{"href":"https://api.github.com/repos/uber/tchannel-python/pulls/114/comments"},"review_comment":{"href":"https://api.github.com/repos/uber/tchannel-python/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/uber/tchannel-python/pulls/114/commits"},"statuses":{"href":"https://api.github.com/repos/uber/tchannel-python/statuses/f2c715373562fd9dec1be7f666dd7f1083bd44b8"}}}}