{"action":"created","comment":{"url":"https://api.github.com/repos/quantopian/serializable-traitlets/pulls/comments/84933728","pull_request_review_id":5679110,"id":84933728,"diff_hunk":"@@ -0,0 +1,101 @@\n+from __future__ import absolute_import\n+\n+from operator import itemgetter\n+\n+import click\n+\n+from straitlets import MultipleTraitErrors\n+from traitlets import TraitError\n+\n+\n+def _indent(msg):\n+    return '\\n'.join('  ' + line for line in msg.splitlines())\n+\n+\n+class _ConfigFile(click.File):\n+    def __init__(self, config_type, encoding=None):\n+        super(_ConfigFile, self).__init__(\n+            mode='r',\n+            encoding=None,\n+            errors='strict',\n+            lazy=False,\n+            atomic=False,\n+        )\n+        self.config = config_type\n+\n+    def _reader(self, f):  # pragma: no cover\n+        raise NotImplementedError('_reader')\n+\n+    @property\n+    def name(self):  # pragma: no cover\n+        raise NotImplementedError('name')\n+\n+    def convert(self, value, param, ctx):\n+        f = super(_ConfigFile, self).convert(value, param, ctx)\n+        try:\n+            return self._reader(f)\n+        except MultipleTraitErrors as e:\n+            self.fail(\n+                'Failed to validate the schema:\\n\\n' + '\\n'.join(\n+                    '%s:\\n%s' % (key, _indent(str(err)))\n+                    for key, err in sorted(e.errors.items(), key=itemgetter(0))\n+                ),\n+                param,\n+                ctx,\n+            )\n+        except TraitError as e:\n+            self.fail(\n+                'Failed to validate the schema:\\n%s' % _indent(str(e)),\n+                param,\n+                ctx,\n+            )\n+\n+\n+class JsonConfigFile(_ConfigFile):\n+    \"\"\"A click parameter type for reading a :class:`~straitlets.Serializable`\n+    object out of json file.\n+\n+    Parameters\n+    ----------\n+    config_type : type[Serializable]\n+        A subclass of :class:`~straitlets.Serializable`.\n+\n+    Notes\n+    -----\n+    Normal :class:`~straitlets.Serializable` are not eagerly validated, if you\n+    want to check the schema of the file at read time you should use a\n+    :class:`~straitlets.StrictSerializable`.\n+    \"\"\"\n+    name = 'JSON-FILE'\n+\n+    def _reader(self, f):\n+        return self.config.from_json(f.read())\n+\n+\n+class YamlConfigFile(_ConfigFile):\n+    \"\"\"A click parameter type for reading a :class:`~straitlets.Serializable`\n+    object out of base64 encoded json file. This is often used with stdin input","path":"straitlets/ext/click.py","position":77,"original_position":77,"commit_id":"625a32c27e6c3222d572f7b961abb7ce561df793","original_commit_id":"625a32c27e6c3222d572f7b961abb7ce561df793","user":{"login":"ssanderson","id":1588357,"avatar_url":"https://avatars.githubusercontent.com/u/1588357?v=3","gravatar_id":"","url":"https://api.github.com/users/ssanderson","html_url":"https://github.com/ssanderson","followers_url":"https://api.github.com/users/ssanderson/followers","following_url":"https://api.github.com/users/ssanderson/following{/other_user}","gists_url":"https://api.github.com/users/ssanderson/gists{/gist_id}","starred_url":"https://api.github.com/users/ssanderson/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ssanderson/subscriptions","organizations_url":"https://api.github.com/users/ssanderson/orgs","repos_url":"https://api.github.com/users/ssanderson/repos","events_url":"https://api.github.com/users/ssanderson/events{/privacy}","received_events_url":"https://api.github.com/users/ssanderson/received_events","type":"User","site_admin":false},"body":"wrong doc here?","created_at":"2016-10-25T15:41:48Z","updated_at":"2016-10-25T15:53:31Z","html_url":"https://github.com/quantopian/serializable-traitlets/pull/8#discussion_r84933728","pull_request_url":"https://api.github.com/repos/quantopian/serializable-traitlets/pulls/8","_links":{"self":{"href":"https://api.github.com/repos/quantopian/serializable-traitlets/pulls/comments/84933728"},"html":{"href":"https://github.com/quantopian/serializable-traitlets/pull/8#discussion_r84933728"},"pull_request":{"href":"https://api.github.com/repos/quantopian/serializable-traitlets/pulls/8"}}},"pull_request":{"url":"https://api.github.com/repos/quantopian/serializable-traitlets/pulls/8","id":90724563,"html_url":"https://github.com/quantopian/serializable-traitlets/pull/8","diff_url":"https://github.com/quantopian/serializable-traitlets/pull/8.diff","patch_url":"https://github.com/quantopian/serializable-traitlets/pull/8.patch","issue_url":"https://api.github.com/repos/quantopian/serializable-traitlets/issues/8","number":8,"state":"open","locked":false,"title":"ENH: Add click extension types","user":{"login":"llllllllll","id":3064397,"avatar_url":"https://avatars.githubusercontent.com/u/3064397?v=3","gravatar_id":"","url":"https://api.github.com/users/llllllllll","html_url":"https://github.com/llllllllll","followers_url":"https://api.github.com/users/llllllllll/followers","following_url":"https://api.github.com/users/llllllllll/following{/other_user}","gists_url":"https://api.github.com/users/llllllllll/gists{/gist_id}","starred_url":"https://api.github.com/users/llllllllll/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/llllllllll/subscriptions","organizations_url":"https://api.github.com/users/llllllllll/orgs","repos_url":"https://api.github.com/users/llllllllll/repos","events_url":"https://api.github.com/users/llllllllll/events{/privacy}","received_events_url":"https://api.github.com/users/llllllllll/received_events","type":"User","site_admin":false},"body":"Adds click param types for config files.","created_at":"2016-10-25T01:42:42Z","updated_at":"2016-10-25T15:53:31Z","closed_at":null,"merged_at":null,"merge_commit_sha":"0e44970e16883fc270f135d17163c696e5e24a34","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/quantopian/serializable-traitlets/pulls/8/commits","review_comments_url":"https://api.github.com/repos/quantopian/serializable-traitlets/pulls/8/comments","review_comment_url":"https://api.github.com/repos/quantopian/serializable-traitlets/pulls/comments{/number}","comments_url":"https://api.github.com/repos/quantopian/serializable-traitlets/issues/8/comments","statuses_url":"https://api.github.com/repos/quantopian/serializable-traitlets/statuses/625a32c27e6c3222d572f7b961abb7ce561df793","head":{"label":"quantopian:click-extension","ref":"click-extension","sha":"625a32c27e6c3222d572f7b961abb7ce561df793","user":{"login":"quantopian","id":1393215,"avatar_url":"https://avatars.githubusercontent.com/u/1393215?v=3","gravatar_id":"","url":"https://api.github.com/users/quantopian","html_url":"https://github.com/quantopian","followers_url":"https://api.github.com/users/quantopian/followers","following_url":"https://api.github.com/users/quantopian/following{/other_user}","gists_url":"https://api.github.com/users/quantopian/gists{/gist_id}","starred_url":"https://api.github.com/users/quantopian/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/quantopian/subscriptions","organizations_url":"https://api.github.com/users/quantopian/orgs","repos_url":"https://api.github.com/users/quantopian/repos","events_url":"https://api.github.com/users/quantopian/events{/privacy}","received_events_url":"https://api.github.com/users/quantopian/received_events","type":"Organization","site_admin":false},"repo":{"id":48727906,"name":"serializable-traitlets","full_name":"quantopian/serializable-traitlets","owner":{"login":"quantopian","id":1393215,"avatar_url":"https://avatars.githubusercontent.com/u/1393215?v=3","gravatar_id":"","url":"https://api.github.com/users/quantopian","html_url":"https://github.com/quantopian","followers_url":"https://api.github.com/users/quantopian/followers","following_url":"https://api.github.com/users/quantopian/following{/other_user}","gists_url":"https://api.github.com/users/quantopian/gists{/gist_id}","starred_url":"https://api.github.com/users/quantopian/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/quantopian/subscriptions","organizations_url":"https://api.github.com/users/quantopian/orgs","repos_url":"https://api.github.com/users/quantopian/repos","events_url":"https://api.github.com/users/quantopian/events{/privacy}","received_events_url":"https://api.github.com/users/quantopian/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/quantopian/serializable-traitlets","description":"JSON-Serializable IPython Traitlets","fork":false,"url":"https://api.github.com/repos/quantopian/serializable-traitlets","forks_url":"https://api.github.com/repos/quantopian/serializable-traitlets/forks","keys_url":"https://api.github.com/repos/quantopian/serializable-traitlets/keys{/key_id}","collaborators_url":"https://api.github.com/repos/quantopian/serializable-traitlets/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/quantopian/serializable-traitlets/teams","hooks_url":"https://api.github.com/repos/quantopian/serializable-traitlets/hooks","issue_events_url":"https://api.github.com/repos/quantopian/serializable-traitlets/issues/events{/number}","events_url":"https://api.github.com/repos/quantopian/serializable-traitlets/events","assignees_url":"https://api.github.com/repos/quantopian/serializable-traitlets/assignees{/user}","branches_url":"https://api.github.com/repos/quantopian/serializable-traitlets/branches{/branch}","tags_url":"https://api.github.com/repos/quantopian/serializable-traitlets/tags","blobs_url":"https://api.github.com/repos/quantopian/serializable-traitlets/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/quantopian/serializable-traitlets/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/quantopian/serializable-traitlets/git/refs{/sha}","trees_url":"https://api.github.com/repos/quantopian/serializable-traitlets/git/trees{/sha}","statuses_url":"https://api.github.com/repos/quantopian/serializable-traitlets/statuses/{sha}","languages_url":"https://api.github.com/repos/quantopian/serializable-traitlets/languages","stargazers_url":"https://api.github.com/repos/quantopian/serializable-traitlets/stargazers","contributors_url":"https://api.github.com/repos/quantopian/serializable-traitlets/contributors","subscribers_url":"https://api.github.com/repos/quantopian/serializable-traitlets/subscribers","subscription_url":"https://api.github.com/repos/quantopian/serializable-traitlets/subscription","commits_url":"https://api.github.com/repos/quantopian/serializable-traitlets/commits{/sha}","git_commits_url":"https://api.github.com/repos/quantopian/serializable-traitlets/git/commits{/sha}","comments_url":"https://api.github.com/repos/quantopian/serializable-traitlets/comments{/number}","issue_comment_url":"https://api.github.com/repos/quantopian/serializable-traitlets/issues/comments{/number}","contents_url":"https://api.github.com/repos/quantopian/serializable-traitlets/contents/{+path}","compare_url":"https://api.github.com/repos/quantopian/serializable-traitlets/compare/{base}...{head}","merges_url":"https://api.github.com/repos/quantopian/serializable-traitlets/merges","archive_url":"https://api.github.com/repos/quantopian/serializable-traitlets/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/quantopian/serializable-traitlets/downloads","issues_url":"https://api.github.com/repos/quantopian/serializable-traitlets/issues{/number}","pulls_url":"https://api.github.com/repos/quantopian/serializable-traitlets/pulls{/number}","milestones_url":"https://api.github.com/repos/quantopian/serializable-traitlets/milestones{/number}","notifications_url":"https://api.github.com/repos/quantopian/serializable-traitlets/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/quantopian/serializable-traitlets/labels{/name}","releases_url":"https://api.github.com/repos/quantopian/serializable-traitlets/releases{/id}","deployments_url":"https://api.github.com/repos/quantopian/serializable-traitlets/deployments","created_at":"2015-12-29T04:46:21Z","updated_at":"2016-10-25T00:58:50Z","pushed_at":"2016-10-25T15:36:45Z","git_url":"git://github.com/quantopian/serializable-traitlets.git","ssh_url":"git@github.com:quantopian/serializable-traitlets.git","clone_url":"https://github.com/quantopian/serializable-traitlets.git","svn_url":"https://github.com/quantopian/serializable-traitlets","homepage":null,"size":56,"stargazers_count":1,"watchers_count":1,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":1,"forks":0,"open_issues":1,"watchers":1,"default_branch":"master"}},"base":{"label":"quantopian:master","ref":"master","sha":"4bf0786fb7f15fd35884b3f8ae29e298b0ded1fd","user":{"login":"quantopian","id":1393215,"avatar_url":"https://avatars.githubusercontent.com/u/1393215?v=3","gravatar_id":"","url":"https://api.github.com/users/quantopian","html_url":"https://github.com/quantopian","followers_url":"https://api.github.com/users/quantopian/followers","following_url":"https://api.github.com/users/quantopian/following{/other_user}","gists_url":"https://api.github.com/users/quantopian/gists{/gist_id}","starred_url":"https://api.github.com/users/quantopian/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/quantopian/subscriptions","organizations_url":"https://api.github.com/users/quantopian/orgs","repos_url":"https://api.github.com/users/quantopian/repos","events_url":"https://api.github.com/users/quantopian/events{/privacy}","received_events_url":"https://api.github.com/users/quantopian/received_events","type":"Organization","site_admin":false},"repo":{"id":48727906,"name":"serializable-traitlets","full_name":"quantopian/serializable-traitlets","owner":{"login":"quantopian","id":1393215,"avatar_url":"https://avatars.githubusercontent.com/u/1393215?v=3","gravatar_id":"","url":"https://api.github.com/users/quantopian","html_url":"https://github.com/quantopian","followers_url":"https://api.github.com/users/quantopian/followers","following_url":"https://api.github.com/users/quantopian/following{/other_user}","gists_url":"https://api.github.com/users/quantopian/gists{/gist_id}","starred_url":"https://api.github.com/users/quantopian/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/quantopian/subscriptions","organizations_url":"https://api.github.com/users/quantopian/orgs","repos_url":"https://api.github.com/users/quantopian/repos","events_url":"https://api.github.com/users/quantopian/events{/privacy}","received_events_url":"https://api.github.com/users/quantopian/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/quantopian/serializable-traitlets","description":"JSON-Serializable IPython Traitlets","fork":false,"url":"https://api.github.com/repos/quantopian/serializable-traitlets","forks_url":"https://api.github.com/repos/quantopian/serializable-traitlets/forks","keys_url":"https://api.github.com/repos/quantopian/serializable-traitlets/keys{/key_id}","collaborators_url":"https://api.github.com/repos/quantopian/serializable-traitlets/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/quantopian/serializable-traitlets/teams","hooks_url":"https://api.github.com/repos/quantopian/serializable-traitlets/hooks","issue_events_url":"https://api.github.com/repos/quantopian/serializable-traitlets/issues/events{/number}","events_url":"https://api.github.com/repos/quantopian/serializable-traitlets/events","assignees_url":"https://api.github.com/repos/quantopian/serializable-traitlets/assignees{/user}","branches_url":"https://api.github.com/repos/quantopian/serializable-traitlets/branches{/branch}","tags_url":"https://api.github.com/repos/quantopian/serializable-traitlets/tags","blobs_url":"https://api.github.com/repos/quantopian/serializable-traitlets/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/quantopian/serializable-traitlets/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/quantopian/serializable-traitlets/git/refs{/sha}","trees_url":"https://api.github.com/repos/quantopian/serializable-traitlets/git/trees{/sha}","statuses_url":"https://api.github.com/repos/quantopian/serializable-traitlets/statuses/{sha}","languages_url":"https://api.github.com/repos/quantopian/serializable-traitlets/languages","stargazers_url":"https://api.github.com/repos/quantopian/serializable-traitlets/stargazers","contributors_url":"https://api.github.com/repos/quantopian/serializable-traitlets/contributors","subscribers_url":"https://api.github.com/repos/quantopian/serializable-traitlets/subscribers","subscription_url":"https://api.github.com/repos/quantopian/serializable-traitlets/subscription","commits_url":"https://api.github.com/repos/quantopian/serializable-traitlets/commits{/sha}","git_commits_url":"https://api.github.com/repos/quantopian/serializable-traitlets/git/commits{/sha}","comments_url":"https://api.github.com/repos/quantopian/serializable-traitlets/comments{/number}","issue_comment_url":"https://api.github.com/repos/quantopian/serializable-traitlets/issues/comments{/number}","contents_url":"https://api.github.com/repos/quantopian/serializable-traitlets/contents/{+path}","compare_url":"https://api.github.com/repos/quantopian/serializable-traitlets/compare/{base}...{head}","merges_url":"https://api.github.com/repos/quantopian/serializable-traitlets/merges","archive_url":"https://api.github.com/repos/quantopian/serializable-traitlets/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/quantopian/serializable-traitlets/downloads","issues_url":"https://api.github.com/repos/quantopian/serializable-traitlets/issues{/number}","pulls_url":"https://api.github.com/repos/quantopian/serializable-traitlets/pulls{/number}","milestones_url":"https://api.github.com/repos/quantopian/serializable-traitlets/milestones{/number}","notifications_url":"https://api.github.com/repos/quantopian/serializable-traitlets/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/quantopian/serializable-traitlets/labels{/name}","releases_url":"https://api.github.com/repos/quantopian/serializable-traitlets/releases{/id}","deployments_url":"https://api.github.com/repos/quantopian/serializable-traitlets/deployments","created_at":"2015-12-29T04:46:21Z","updated_at":"2016-10-25T00:58:50Z","pushed_at":"2016-10-25T15:36:45Z","git_url":"git://github.com/quantopian/serializable-traitlets.git","ssh_url":"git@github.com:quantopian/serializable-traitlets.git","clone_url":"https://github.com/quantopian/serializable-traitlets.git","svn_url":"https://github.com/quantopian/serializable-traitlets","homepage":null,"size":56,"stargazers_count":1,"watchers_count":1,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":1,"forks":0,"open_issues":1,"watchers":1,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/quantopian/serializable-traitlets/pulls/8"},"html":{"href":"https://github.com/quantopian/serializable-traitlets/pull/8"},"issue":{"href":"https://api.github.com/repos/quantopian/serializable-traitlets/issues/8"},"comments":{"href":"https://api.github.com/repos/quantopian/serializable-traitlets/issues/8/comments"},"review_comments":{"href":"https://api.github.com/repos/quantopian/serializable-traitlets/pulls/8/comments"},"review_comment":{"href":"https://api.github.com/repos/quantopian/serializable-traitlets/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/quantopian/serializable-traitlets/pulls/8/commits"},"statuses":{"href":"https://api.github.com/repos/quantopian/serializable-traitlets/statuses/625a32c27e6c3222d572f7b961abb7ce561df793"}}}}
{"actor":{"display_login":"ssanderson"}}