{"action":"created","comment":{"url":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/pulls/comments/203148548","pull_request_review_id":137981783,"id":203148548,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDIwMzE0ODU0OA==","diff_hunk":"@@ -13,58 +11,125 @@\n               'json_schema/cgp/gen3/2.0.0/cgp_gen3_metadata.json')\n \n \n-class ParsedBundle(namedtuple('ParsedBundle', ['bundle_uuid', 'metadata_dict', 'data_objects'])):\n+class ParseError(Exception):\n+    \"\"\"To be thrown any time a bundle doesn't contain an expected field\"\"\"\n+\n+\n+class ParsedDataFile(typing.NamedTuple):\n+    \"\"\"local representation of data necessary to upload a single file\"\"\"\n+    filename: str\n+    file_uuid: str\n+    cloud_urls: typing.List[str]  # list of urls\n+    bundle_uuid: str\n+    file_guid: str\n+    file_version: str  # rfc3339\n+\n+\n+class ParsedBundle(typing.NamedTuple):\n+    bundle_uuid: str\n+    metadata_dict: dict\n+    data_files: typing.List[ParsedDataFile]\n \n     def pprint(self):\n         return pprint.pformat(self, indent=4)\n \n \n class StandardFormatBundleUploader:\n     _uuid_regex = re.compile('[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}')\n+    # adapted from http://mattallan.org/posts/rfc3339-date-time-validation/\n+    _rfc3339_regex = re.compile('^(?P<fullyear>\\d{4})'\n+                                '-(?P<month>0[1-9]|1[0-2])'\n+                                '-(?P<mday>0[1-9]|[12][0-9]|3[01])'\n+                                'T(?P<hour>[01][0-9]|2[0-3]):(?P<minute>[0-5][0-9]):(?P<second>[0-5][0-9]|60)'\n+                                '(?P<secfrac>\\.[0-9]+)?'\n+                                '(Z|(\\+|-)(?P<offset_hour>[01][0-9]|2[0-3]):(?P<offset_minute>[0-5][0-9]))?$')\n \n     def __init__(self, dss_uploader: DssUploader, metadata_file_uploader: MetadataFileUploader) -> None:\n         self.dss_uploader = dss_uploader\n         self.metadata_file_uploader = metadata_file_uploader\n-\n-    @staticmethod\n-    def _parse_bundle(bundle: dict) -> ParsedBundle:\n-        try:\n-            data_bundle = bundle['data_bundle']\n-            bundle_uuid = data_bundle['id']\n-            metadata_dict = data_bundle['user_metadata']\n-            data_objects = bundle['data_objects']\n-        except KeyError:\n-            # TODO: Make a bundle parse error that spits back whatever info we can get about the bundle\n-            raise\n-        return ParsedBundle(bundle_uuid, metadata_dict, data_objects)\n+        # these will probably need to be made into queues for parallelization\n+        self.bundles_parsed: typing.List[ParsedBundle] = []\n+        self.bundles_failed_unparsed: typing.List[dict] = []\n+        self.bundles_loaded: typing.List[ParsedBundle] = []\n+        self.bundles_failed_parsed: typing.List[ParsedBundle] = []\n \n     @classmethod\n     def _get_file_uuid(cls, file_guid: str):\n         result = cls._uuid_regex.findall(file_guid.lower())\n         if result is None:\n-            raise ValueError(f'Misformatted file_guid: {file_guid} should contain a uuid.')\n+            raise ParseError(f'Misformatted file_guid: {file_guid} should contain a uuid.')\n         if len(result) != 1:\n-            raise ValueError(f'Misformatted file_guid: {file_guid} contains multiple uuids. Only one was expected.')\n+            raise ParseError(f'Misformatted file_guid: {file_guid} contains multiple uuids. Only one was expected.')\n         return result[0]\n \n-    @staticmethod\n-    def _get_file_version(file_info: dict):\n+    @classmethod\n+    def _get_file_version(cls, file_info: dict):\n         \"\"\"Since date updated is optional, we default to date created when it's not updated\"\"\"\n-        try:\n-            return file_info['updated']\n-        except KeyError:\n-            return file_info['created']\n+        def parse_version_key(file_info_, key):\n+            \"\"\"return None if version cannot be found\"\"\"\n+            try:\n+                match = cls._rfc3339_regex.fullmatch(file_info_[key])\n+                if match is None:\n+                    logger.warning(f'Failed to parse file version from date {key}: {file_info_[key]}')\n+                    return None\n+                return file_info_[key]\n+            except KeyError:\n+                return None\n+        version = parse_version_key(file_info, 'updated')\n+        if version is None:\n+            version = parse_version_key(file_info, 'created')\n+        if version is None:\n+            raise ParseError('Either bundle had no updated / created time or it was not rfc3339 compliant')\n+        return version\n \n     @staticmethod\n     def _get_cloud_urls(file_info: dict):\n-        return {url_dict['url'] for url_dict in file_info['urls']}\n+        if 'urls' not in file_info:\n+            raise ParseError(f'URL field not present in file_info: \\n{file_info}')\n+        urls = file_info['urls']\n+        if len(urls) < 1:\n+            # FIXME: How many cloud URLs do we ACTUALLY need / expect?\n+            raise ParseError(f'Expected at least one cloud url in file_info: \\n{file_info}')\n+        for url in urls:\n+            if 'url' not in url:\n+                raise ParseError(f\"Expected 'url' as key for urls in file_info: \\n{file_info}\")\n+        return [url_dict['url'] for url_dict in urls]\n \n-    def _load_bundle(self, bundle_uuid, metadata_dict, data_objects):\n+    @classmethod\n+    def _parse_bundle(cls, bundle: dict) -> ParsedBundle:\n+        try:\n+            data_bundle = bundle['data_bundle']\n+            bundle_uuid = data_bundle['id']\n+            metadata_dict = data_bundle['user_metadata']\n+            data_objects = bundle['data_objects']\n+        except KeyError:\n+            logger.exception('Failed to parse bundle')","path":"loader/standard_loader.py","position":128,"original_position":128,"commit_id":"c729bcfb9cf233c7f78e8e48cdeafcfd0fe68c5c","original_commit_id":"c729bcfb9cf233c7f78e8e48cdeafcfd0fe68c5c","user":{"login":"jessebrennan","id":10734740,"node_id":"MDQ6VXNlcjEwNzM0NzQw","avatar_url":"https://avatars1.githubusercontent.com/u/10734740?v=4","gravatar_id":"","url":"https://api.github.com/users/jessebrennan","html_url":"https://github.com/jessebrennan","followers_url":"https://api.github.com/users/jessebrennan/followers","following_url":"https://api.github.com/users/jessebrennan/following{/other_user}","gists_url":"https://api.github.com/users/jessebrennan/gists{/gist_id}","starred_url":"https://api.github.com/users/jessebrennan/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jessebrennan/subscriptions","organizations_url":"https://api.github.com/users/jessebrennan/orgs","repos_url":"https://api.github.com/users/jessebrennan/repos","events_url":"https://api.github.com/users/jessebrennan/events{/privacy}","received_events_url":"https://api.github.com/users/jessebrennan/received_events","type":"User","site_admin":false},"body":"On more experimentation, just copying the message from the first exception won't tell you much about what actually went wrong parsing. Instead I'm using the `raise ... from` pattern so it's clear what happened. LMK if you disagree.","created_at":"2018-07-17T19:23:38Z","updated_at":"2018-07-17T19:23:38Z","html_url":"https://github.com/DataBiosphere/cgp-dss-data-loader/pull/31#discussion_r203148548","pull_request_url":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/pulls/31","author_association":"CONTRIBUTOR","_links":{"self":{"href":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/pulls/comments/203148548"},"html":{"href":"https://github.com/DataBiosphere/cgp-dss-data-loader/pull/31#discussion_r203148548"},"pull_request":{"href":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/pulls/31"}},"in_reply_to_id":203089466},"pull_request":{"url":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/pulls/31","id":201151175,"node_id":"MDExOlB1bGxSZXF1ZXN0MjAxMTUxMTc1","html_url":"https://github.com/DataBiosphere/cgp-dss-data-loader/pull/31","diff_url":"https://github.com/DataBiosphere/cgp-dss-data-loader/pull/31.diff","patch_url":"https://github.com/DataBiosphere/cgp-dss-data-loader/pull/31.patch","issue_url":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/issues/31","number":31,"state":"open","locked":false,"title":"Add more tests for loader (resolves LOAD-30, LOAD-23)","user":{"login":"jessebrennan","id":10734740,"node_id":"MDQ6VXNlcjEwNzM0NzQw","avatar_url":"https://avatars1.githubusercontent.com/u/10734740?v=4","gravatar_id":"","url":"https://api.github.com/users/jessebrennan","html_url":"https://github.com/jessebrennan","followers_url":"https://api.github.com/users/jessebrennan/followers","following_url":"https://api.github.com/users/jessebrennan/following{/other_user}","gists_url":"https://api.github.com/users/jessebrennan/gists{/gist_id}","starred_url":"https://api.github.com/users/jessebrennan/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jessebrennan/subscriptions","organizations_url":"https://api.github.com/users/jessebrennan/orgs","repos_url":"https://api.github.com/users/jessebrennan/repos","events_url":"https://api.github.com/users/jessebrennan/events{/privacy}","received_events_url":"https://api.github.com/users/jessebrennan/received_events","type":"User","site_admin":false},"body":"A lot has been added. Here's a summary of all of the changes in no particular order:\n- If a file has a bad url the bundle will fail to load. There is a test to confirm this behavior.\n- There is now a test to make sure that if a file is already uploaded it will not be loaded twice. (this resolves LOAD-23)\n- Named tuples were prettied up \n- Minor clean up, out dated todos removed, etc\n- If a timestamp has no zone info assume utc. There is also a test to confirm this behavior.\n- Make the global arrays of bundles into instance variables. This is a little tidier than before.\n- A test for _parse_all_bundles is added.\n- Tests for other parsing functionality are added\n- We now also test the loading mechanism directly (instead of just through integration tests.\n- This includes testing a 'minimal' bundle.\n- debug is turned off for testing\n\n┆Issue is synchronized with this [JIRA Task](https://ucsc-cgl.atlassian.net/browse/LOAD-36)\n┆Project Name: CGP-Data Loader\n┆Issue Number: LOAD-36\n","created_at":"2018-07-12T23:22:53Z","updated_at":"2018-07-17T19:23:38Z","closed_at":null,"merged_at":null,"merge_commit_sha":"62268bcb0aa17e766701256724c128eecbdd4622","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/pulls/31/commits","review_comments_url":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/pulls/31/comments","review_comment_url":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/pulls/comments{/number}","comments_url":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/issues/31/comments","statuses_url":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/statuses/c729bcfb9cf233c7f78e8e48cdeafcfd0fe68c5c","head":{"label":"DataBiosphere:feature/better-testing","ref":"feature/better-testing","sha":"c729bcfb9cf233c7f78e8e48cdeafcfd0fe68c5c","user":{"login":"DataBiosphere","id":32805087,"node_id":"MDEyOk9yZ2FuaXphdGlvbjMyODA1MDg3","avatar_url":"https://avatars0.githubusercontent.com/u/32805087?v=4","gravatar_id":"","url":"https://api.github.com/users/DataBiosphere","html_url":"https://github.com/DataBiosphere","followers_url":"https://api.github.com/users/DataBiosphere/followers","following_url":"https://api.github.com/users/DataBiosphere/following{/other_user}","gists_url":"https://api.github.com/users/DataBiosphere/gists{/gist_id}","starred_url":"https://api.github.com/users/DataBiosphere/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/DataBiosphere/subscriptions","organizations_url":"https://api.github.com/users/DataBiosphere/orgs","repos_url":"https://api.github.com/users/DataBiosphere/repos","events_url":"https://api.github.com/users/DataBiosphere/events{/privacy}","received_events_url":"https://api.github.com/users/DataBiosphere/received_events","type":"Organization","site_admin":false},"repo":{"id":132820416,"node_id":"MDEwOlJlcG9zaXRvcnkxMzI4MjA0MTY=","name":"cgp-dss-data-loader","full_name":"DataBiosphere/cgp-dss-data-loader","owner":{"login":"DataBiosphere","id":32805087,"node_id":"MDEyOk9yZ2FuaXphdGlvbjMyODA1MDg3","avatar_url":"https://avatars0.githubusercontent.com/u/32805087?v=4","gravatar_id":"","url":"https://api.github.com/users/DataBiosphere","html_url":"https://github.com/DataBiosphere","followers_url":"https://api.github.com/users/DataBiosphere/followers","following_url":"https://api.github.com/users/DataBiosphere/following{/other_user}","gists_url":"https://api.github.com/users/DataBiosphere/gists{/gist_id}","starred_url":"https://api.github.com/users/DataBiosphere/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/DataBiosphere/subscriptions","organizations_url":"https://api.github.com/users/DataBiosphere/orgs","repos_url":"https://api.github.com/users/DataBiosphere/repos","events_url":"https://api.github.com/users/DataBiosphere/events{/privacy}","received_events_url":"https://api.github.com/users/DataBiosphere/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/DataBiosphere/cgp-dss-data-loader","description":"Simple data loader for CGP HCA Data Store","fork":false,"url":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader","forks_url":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/forks","keys_url":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/keys{/key_id}","collaborators_url":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/teams","hooks_url":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/hooks","issue_events_url":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/issues/events{/number}","events_url":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/events","assignees_url":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/assignees{/user}","branches_url":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/branches{/branch}","tags_url":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/tags","blobs_url":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/git/refs{/sha}","trees_url":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/git/trees{/sha}","statuses_url":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/statuses/{sha}","languages_url":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/languages","stargazers_url":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/stargazers","contributors_url":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/contributors","subscribers_url":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/subscribers","subscription_url":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/subscription","commits_url":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/commits{/sha}","git_commits_url":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/git/commits{/sha}","comments_url":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/comments{/number}","issue_comment_url":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/issues/comments{/number}","contents_url":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/contents/{+path}","compare_url":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/compare/{base}...{head}","merges_url":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/merges","archive_url":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/downloads","issues_url":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/issues{/number}","pulls_url":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/pulls{/number}","milestones_url":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/milestones{/number}","notifications_url":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/labels{/name}","releases_url":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/releases{/id}","deployments_url":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/deployments","created_at":"2018-05-09T22:46:08Z","updated_at":"2018-07-12T19:44:09Z","pushed_at":"2018-07-12T23:22:54Z","git_url":"git://github.com/DataBiosphere/cgp-dss-data-loader.git","ssh_url":"git@github.com:DataBiosphere/cgp-dss-data-loader.git","clone_url":"https://github.com/DataBiosphere/cgp-dss-data-loader.git","svn_url":"https://github.com/DataBiosphere/cgp-dss-data-loader","homepage":null,"size":325,"stargazers_count":1,"watchers_count":1,"language":"Python","has_issues":true,"has_projects":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":2,"mirror_url":null,"archived":false,"open_issues_count":11,"license":{"key":"apache-2.0","name":"Apache License 2.0","spdx_id":"Apache-2.0","url":"https://api.github.com/licenses/apache-2.0","node_id":"MDc6TGljZW5zZTI="},"forks":2,"open_issues":11,"watchers":1,"default_branch":"develop"}},"base":{"label":"DataBiosphere:develop","ref":"develop","sha":"338a9a42ee85a8867f110fc916ef9db2fe54b7b4","user":{"login":"DataBiosphere","id":32805087,"node_id":"MDEyOk9yZ2FuaXphdGlvbjMyODA1MDg3","avatar_url":"https://avatars0.githubusercontent.com/u/32805087?v=4","gravatar_id":"","url":"https://api.github.com/users/DataBiosphere","html_url":"https://github.com/DataBiosphere","followers_url":"https://api.github.com/users/DataBiosphere/followers","following_url":"https://api.github.com/users/DataBiosphere/following{/other_user}","gists_url":"https://api.github.com/users/DataBiosphere/gists{/gist_id}","starred_url":"https://api.github.com/users/DataBiosphere/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/DataBiosphere/subscriptions","organizations_url":"https://api.github.com/users/DataBiosphere/orgs","repos_url":"https://api.github.com/users/DataBiosphere/repos","events_url":"https://api.github.com/users/DataBiosphere/events{/privacy}","received_events_url":"https://api.github.com/users/DataBiosphere/received_events","type":"Organization","site_admin":false},"repo":{"id":132820416,"node_id":"MDEwOlJlcG9zaXRvcnkxMzI4MjA0MTY=","name":"cgp-dss-data-loader","full_name":"DataBiosphere/cgp-dss-data-loader","owner":{"login":"DataBiosphere","id":32805087,"node_id":"MDEyOk9yZ2FuaXphdGlvbjMyODA1MDg3","avatar_url":"https://avatars0.githubusercontent.com/u/32805087?v=4","gravatar_id":"","url":"https://api.github.com/users/DataBiosphere","html_url":"https://github.com/DataBiosphere","followers_url":"https://api.github.com/users/DataBiosphere/followers","following_url":"https://api.github.com/users/DataBiosphere/following{/other_user}","gists_url":"https://api.github.com/users/DataBiosphere/gists{/gist_id}","starred_url":"https://api.github.com/users/DataBiosphere/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/DataBiosphere/subscriptions","organizations_url":"https://api.github.com/users/DataBiosphere/orgs","repos_url":"https://api.github.com/users/DataBiosphere/repos","events_url":"https://api.github.com/users/DataBiosphere/events{/privacy}","received_events_url":"https://api.github.com/users/DataBiosphere/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/DataBiosphere/cgp-dss-data-loader","description":"Simple data loader for CGP HCA Data Store","fork":false,"url":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader","forks_url":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/forks","keys_url":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/keys{/key_id}","collaborators_url":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/teams","hooks_url":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/hooks","issue_events_url":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/issues/events{/number}","events_url":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/events","assignees_url":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/assignees{/user}","branches_url":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/branches{/branch}","tags_url":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/tags","blobs_url":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/git/refs{/sha}","trees_url":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/git/trees{/sha}","statuses_url":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/statuses/{sha}","languages_url":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/languages","stargazers_url":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/stargazers","contributors_url":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/contributors","subscribers_url":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/subscribers","subscription_url":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/subscription","commits_url":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/commits{/sha}","git_commits_url":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/git/commits{/sha}","comments_url":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/comments{/number}","issue_comment_url":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/issues/comments{/number}","contents_url":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/contents/{+path}","compare_url":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/compare/{base}...{head}","merges_url":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/merges","archive_url":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/downloads","issues_url":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/issues{/number}","pulls_url":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/pulls{/number}","milestones_url":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/milestones{/number}","notifications_url":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/labels{/name}","releases_url":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/releases{/id}","deployments_url":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/deployments","created_at":"2018-05-09T22:46:08Z","updated_at":"2018-07-12T19:44:09Z","pushed_at":"2018-07-12T23:22:54Z","git_url":"git://github.com/DataBiosphere/cgp-dss-data-loader.git","ssh_url":"git@github.com:DataBiosphere/cgp-dss-data-loader.git","clone_url":"https://github.com/DataBiosphere/cgp-dss-data-loader.git","svn_url":"https://github.com/DataBiosphere/cgp-dss-data-loader","homepage":null,"size":325,"stargazers_count":1,"watchers_count":1,"language":"Python","has_issues":true,"has_projects":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":2,"mirror_url":null,"archived":false,"open_issues_count":11,"license":{"key":"apache-2.0","name":"Apache License 2.0","spdx_id":"Apache-2.0","url":"https://api.github.com/licenses/apache-2.0","node_id":"MDc6TGljZW5zZTI="},"forks":2,"open_issues":11,"watchers":1,"default_branch":"develop"}},"_links":{"self":{"href":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/pulls/31"},"html":{"href":"https://github.com/DataBiosphere/cgp-dss-data-loader/pull/31"},"issue":{"href":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/issues/31"},"comments":{"href":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/issues/31/comments"},"review_comments":{"href":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/pulls/31/comments"},"review_comment":{"href":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/pulls/31/commits"},"statuses":{"href":"https://api.github.com/repos/DataBiosphere/cgp-dss-data-loader/statuses/c729bcfb9cf233c7f78e8e48cdeafcfd0fe68c5c"}},"author_association":"CONTRIBUTOR"}}
{"actor":{"display_login":"jessebrennan"}}