{"action":"created","comment":{"url":"https://api.github.com/repos/tesserae/tesserae-v5/pulls/comments/243031746","pull_request_review_id":186693511,"id":243031746,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDI0MzAzMTc0Ng==","diff_hunk":"@@ -0,0 +1,242 @@\n+import pymongo\n+\n+from tesserae.db import Match, MatchSet\n+\n+\n+class DefaultMatcher(object):\n+    \"\"\"Intertext matching using the Tesserae v3 similarity scoreself.\n+\n+    Based on the similarity score described in [tess]_ .\n+\n+    Parameters\n+    ----------\n+    connection : tesserae.db.TessMongoConnection\n+        Open connection to the Tesserae MongoDB instanceself.\n+\n+    Attributes\n+    ----------\n+    connection : tesserae.db.TessMongoConnection\n+        Open connection to the Tesserae MongoDB instanceself.\n+    matches : list of tesserae.db.Match\n+\n+    References\n+    ----------\n+    .. [tess] Forstall, C., Coffee, N., Buck, T., Roache, K., & Jacobson, S.\n+       (2014). Modeling the scholars: Detecting intertextuality through\n+       enhanced word-level n-gram matching. Digital Scholarship in the\n+       Humanities, 30(4), 503-515.\n+    \"\"\"\n+    def __init__(self, connection):\n+        self.connection = connection\n+        self.clear()\n+\n+    def clear(self):\n+        \"\"\"Reset this Matcher to its initial state.\"\"\"\n+        self.matches = []\n+\n+    def create_stoplist(self, n, feature, basis=None):\n+        \"\"\"Compute a stoplist of `n` tokens.\n+\n+        Parameters\n+        ----------\n+        n : int\n+            The number of tokens to include in the stoplist.\n+        basis : list of tesserae.db.entities.Text, optional\n+            The texts to use as the frequency basis. If None, use frequencies\n+            across the entire corpus.\n+\n+        Returns\n+        -------\n+        stoplist : list of str\n+            The `n` most frequent tokens in the basis texts.\n+        \"\"\"\n+        pipeline = []\n+\n+        if basis is not None:\n+            pipeline.append(\n+                {'$match': {'text': {'$in': [t.id for t in basis]}}})\n+\n+        pipeline.extend([\n+            {'$group': {'_id': '$form', 'frequency': {'$push': '$frequency'}}},\n+            {'$project': {'form': 1, 'frequency': {'$sum': '$frequency'}}},\n+            {'$sort': {'frequency': -1}},\n+            {'$limit': n}\n+        ])\n+\n+        stoplist = connection.aggregate('frequencies', pipeline)\n+\n+        return stoplist\n+\n+    def match(self, texts, unit_type, feature, stopwords=10,\n+              stopword_basis='corpus', score_basis='word',\n+              frequency_basis='texts', max_distance=10,\n+              distance_metric='frequency'):\n+        \"\"\"Find matches between one or more texts.\n+\n+        Texts will contain lines or phrases with matching tokens, with varying\n+        degrees of strength to the match. If one text is provided, each unit in\n+        the text will be matched with every subsequent unit.\n+\n+        Parameters\n+        ----------\n+        texts : list of tesserae.db.Text\n+            The texts to match. Texts are matched in\n+        unit_type : {'line','phrase'}\n+            The type of unit to match on.\n+        feature : {'form','lemmata','semantic','lemmata + semantic','sound'}\n+            The token feature to match on.\n+        stopwords : int or list of str\n+            The number of stopwords to use, to be retrieved from the database,\n+            or else a list of words to use as stopwords.\n+        stopword_basis : {'corpus','texts'} or slice or tesserae.db.Text\n+            Which frequencies to use when calculating the stoplist.\n+            - 'corpus': use the combined frequencies of the entire corpus\n+            - 'texts': use the combined frequencies of all texts in the match\n+            - slice: use the texts returned from `texts` by the slice\n+            - Text: use a single text\n+        score_basis : {'word','stem'}\n+            Whether to score based on the words (normalized text) or stems\n+            (lemmata).\n+        frequency_basis : {'texts','corpus'}\n+            Take frequencies from the texts being matched or from the entire\n+            corpus.\n+        max_distance : float\n+            The maximum inter-word distance to use in a match.\n+        distance_metric : {'frequency', 'span'}\n+            The methods used to compute distance.\n+            - 'frequency': the distance between the two least frequent words\n+            - 'span': the greatest distance between any two matching words\n+        \"\"\"\n+        stoplist = self.create_stoplist(stopwords, basis=stopword_basis)\n+\n+        pipeline = []\n+\n+        match_on_text = \\\n+            {'$match': {\n+                'text': {'$in': [t.id for t in texts]},\n+                'feature_set': {'$ne': None}}}\n+\n+        lookup_frequencies = \\\n+            {'$lookup': {\n+                'from': 'feature_sets',\n+                'localField': 'feature_set',\n+                'foreignField': '_id',\n+                'as': 'features'}}\n+\n+        remove_stopwords = \\\n+            {'$match': {\n+                'features.' + feature: {'$nin': stoplist + [None]}}}\n+\n+        reshape_relevant_fields = \\\n+            {'$project': {\n+                'text': True,\n+                'index': True,\n+                'unit': '$' + unit_type,\n+                'feature': {'$arrayElemAt': ['$features.' + feature, 0]},\n+                'frequency': {'$arrayElemAt': ['$features.frequency', 0]}}}\n+\n+        flatten_features = \\\n+            {'$unwind': '$feature'}\n+\n+        group_by_feature = \\\n+            {'$group': {'_id': '$feature'}}\n+        group_by_feature['$group'].update(\n+            {str(t.id): {\n+                '$push': {\n+                    '$cond': [\n+                        {'$eq': ['$text', t.id]},\n+                        {\n+                            '_id': '$_id',\n+                            'unit': '$unit',\n+                            'feature': '$feature',\n+                            'index': '$index',\n+                            'frequency': '$frequency.' + str(t.id)\n+                        },\n+                        None]}}\n+            for t in texts})\n+\n+        remove_null_entries = \\\n+            {'$project': {\n+                str(t.id): {\n+                    '$setDifference': ['$' + str(t.id), [None]]}\n+                for t in texts}}\n+\n+        flatten_by_text = [{'$unwind': '$' + str(t.id)} for t in texts]\n+\n+        group_by_common_unit = \\\n+            {'$group':\n+                '_id': {str(t.id): '$' + str(t.id) + '.unit' for t in texts}}\n+        group_by_common_unit['$group'].update(\n+            {str(t.id): {'$push': '$' + str(t.id)}})\n+\n+        determine_if_match = \\\n+            {'$project': {\n+                str(t.id): True,\n+                str(t.id) + '_arraySize': {'$size': '$' + str(t.id)}\n+            for t in texts}}\n+\n+        remove_non_matches = \\\n+            {'$match': {str(t.id) + '_arraySize': {'$gt': 1} for t in texts}}\n+\n+        if distance_metric == 'span':\n+            compute_similarity_components = \\\n+                {'$project': {\n+                    str(t.id): True,\n+                    str(t.id) + '_distance':\n+                        {'$subtract': [\n+                            {'$max': '$' + str(t.id) + '.index'},\n+                            {'$min': '$' + str(t.id) + '.index'}]},\n+                    str(t.id) + '_frequency': {\n+                        '$pow': [{'$sum': '$' + str(t.id) + '.frequency'}, -1]\n+                    },\n+                for t in texts}}\n+\n+        remove_zero_dist = \\\n+            {'$match':\n+                {str(t.id) + '_distance': {'$gt': 0} for t in texts}}\n+\n+        format_score = \\\n+            {'$addFields': {\n+                'score': {\n+                    '$ln': {\n+                        '$divide': [\n+                            {'$sum':\n+                                ['$' + str(t.id) + '_frequency'\n+                                 for t in texts]}\n+                            {'$sum':\n+                                ['$' + str(t.id) + '_distance'\n+                                 for t in texts]}\n+            ]}}}}\n+\n+        sort_matches = {'$sort': {'score': -1}}\n+\n+        pipeline = [match_on_text, lookup_frequencies, remove_stopwords,\n+                    reshape_relevant_fields, flatten_features,\n+                    group_by_feature, remove_null_entries, flatten_by_text,\n+                    group_by_common_unit, determine_if_match,\n+                    remove_non_matches, compute_similarity_components,\n+                    remove_zero_dist, format_score, sort_matches]\n+\n+        agg_matches = self.connection.aggregate('tokens', pipeline)\n+\n+        match_set = MatchSet(\n+            texts=texts,\n+            unit_type=unit_type,\n+            feature=feature,\n+            parameters={\n+                'stopwords': stoplist,\n+                'stopword_basis': stopword_basis,\n+                'score_basis': score_basis,\n+                'frequency_basis': frequency_basis,\n+                'max_distance': max_distance,\n+                'distance_metric': distance_metric\n+            })\n+\n+        matches = []\n+        for match in agg_matches:\n+            matches.append(Match(\n+                units=[v for v in match['_id'].values()],\n+                tokens=[],\n+                score=match['score'],\n+                match_set=match_set\n+            ))","path":"tesserae/matchers/aggregator.py","position":242,"original_position":242,"commit_id":"600500d3137a827dc4dff9fb09ee8f5387cba877","original_commit_id":"600500d3137a827dc4dff9fb09ee8f5387cba877","user":{"login":"jeffkinnison","id":3553147,"node_id":"MDQ6VXNlcjM1NTMxNDc=","avatar_url":"https://avatars0.githubusercontent.com/u/3553147?v=4","gravatar_id":"","url":"https://api.github.com/users/jeffkinnison","html_url":"https://github.com/jeffkinnison","followers_url":"https://api.github.com/users/jeffkinnison/followers","following_url":"https://api.github.com/users/jeffkinnison/following{/other_user}","gists_url":"https://api.github.com/users/jeffkinnison/gists{/gist_id}","starred_url":"https://api.github.com/users/jeffkinnison/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jeffkinnison/subscriptions","organizations_url":"https://api.github.com/users/jeffkinnison/orgs","repos_url":"https://api.github.com/users/jeffkinnison/repos","events_url":"https://api.github.com/users/jeffkinnison/events{/privacy}","received_events_url":"https://api.github.com/users/jeffkinnison/received_events","type":"User","site_admin":false},"body":"They get returned. I've since made some changes that aren't yet pushed.","created_at":"2018-12-19T18:45:42Z","updated_at":"2018-12-19T18:45:42Z","html_url":"https://github.com/tesserae/tesserae-v5/pull/16#discussion_r243031746","pull_request_url":"https://api.github.com/repos/tesserae/tesserae-v5/pulls/16","author_association":"COLLABORATOR","_links":{"self":{"href":"https://api.github.com/repos/tesserae/tesserae-v5/pulls/comments/243031746"},"html":{"href":"https://github.com/tesserae/tesserae-v5/pull/16#discussion_r243031746"},"pull_request":{"href":"https://api.github.com/repos/tesserae/tesserae-v5/pulls/16"}},"in_reply_to_id":243031541},"pull_request":{"url":"https://api.github.com/repos/tesserae/tesserae-v5/pulls/16","id":231268083,"node_id":"MDExOlB1bGxSZXF1ZXN0MjMxMjY4MDgz","html_url":"https://github.com/tesserae/tesserae-v5/pull/16","diff_url":"https://github.com/tesserae/tesserae-v5/pull/16.diff","patch_url":"https://github.com/tesserae/tesserae-v5/pull/16.patch","issue_url":"https://api.github.com/repos/tesserae/tesserae-v5/issues/16","number":16,"state":"open","locked":false,"title":"Entity update","user":{"login":"jeffkinnison","id":3553147,"node_id":"MDQ6VXNlcjM1NTMxNDc=","avatar_url":"https://avatars0.githubusercontent.com/u/3553147?v=4","gravatar_id":"","url":"https://api.github.com/users/jeffkinnison","html_url":"https://github.com/jeffkinnison","followers_url":"https://api.github.com/users/jeffkinnison/followers","following_url":"https://api.github.com/users/jeffkinnison/following{/other_user}","gists_url":"https://api.github.com/users/jeffkinnison/gists{/gist_id}","starred_url":"https://api.github.com/users/jeffkinnison/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jeffkinnison/subscriptions","organizations_url":"https://api.github.com/users/jeffkinnison/orgs","repos_url":"https://api.github.com/users/jeffkinnison/repos","events_url":"https://api.github.com/users/jeffkinnison/events{/privacy}","received_events_url":"https://api.github.com/users/jeffkinnison/received_events","type":"User","site_admin":false},"body":"Update Tv5 with the FeatureSet and MatchSet Entities, which will make managing matches and token features sustainable in the long run.\r\n\r\nAdditionally, this adds support for dereferencing Entity relationships as MongoDB ObjectIDs, allowing a more natural way of interacting with Entity objects.","created_at":"2018-11-15T17:02:45Z","updated_at":"2018-12-19T18:45:42Z","closed_at":null,"merged_at":null,"merge_commit_sha":"4667714958c77dddcaea3182ce0447141931cc15","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/tesserae/tesserae-v5/pulls/16/commits","review_comments_url":"https://api.github.com/repos/tesserae/tesserae-v5/pulls/16/comments","review_comment_url":"https://api.github.com/repos/tesserae/tesserae-v5/pulls/comments{/number}","comments_url":"https://api.github.com/repos/tesserae/tesserae-v5/issues/16/comments","statuses_url":"https://api.github.com/repos/tesserae/tesserae-v5/statuses/600500d3137a827dc4dff9fb09ee8f5387cba877","head":{"label":"jeffkinnison:entity_update","ref":"entity_update","sha":"600500d3137a827dc4dff9fb09ee8f5387cba877","user":{"login":"jeffkinnison","id":3553147,"node_id":"MDQ6VXNlcjM1NTMxNDc=","avatar_url":"https://avatars0.githubusercontent.com/u/3553147?v=4","gravatar_id":"","url":"https://api.github.com/users/jeffkinnison","html_url":"https://github.com/jeffkinnison","followers_url":"https://api.github.com/users/jeffkinnison/followers","following_url":"https://api.github.com/users/jeffkinnison/following{/other_user}","gists_url":"https://api.github.com/users/jeffkinnison/gists{/gist_id}","starred_url":"https://api.github.com/users/jeffkinnison/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jeffkinnison/subscriptions","organizations_url":"https://api.github.com/users/jeffkinnison/orgs","repos_url":"https://api.github.com/users/jeffkinnison/repos","events_url":"https://api.github.com/users/jeffkinnison/events{/privacy}","received_events_url":"https://api.github.com/users/jeffkinnison/received_events","type":"User","site_admin":false},"repo":{"id":132156515,"node_id":"MDEwOlJlcG9zaXRvcnkxMzIxNTY1MTU=","name":"tesserae-v5","full_name":"jeffkinnison/tesserae-v5","private":false,"owner":{"login":"jeffkinnison","id":3553147,"node_id":"MDQ6VXNlcjM1NTMxNDc=","avatar_url":"https://avatars0.githubusercontent.com/u/3553147?v=4","gravatar_id":"","url":"https://api.github.com/users/jeffkinnison","html_url":"https://github.com/jeffkinnison","followers_url":"https://api.github.com/users/jeffkinnison/followers","following_url":"https://api.github.com/users/jeffkinnison/following{/other_user}","gists_url":"https://api.github.com/users/jeffkinnison/gists{/gist_id}","starred_url":"https://api.github.com/users/jeffkinnison/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jeffkinnison/subscriptions","organizations_url":"https://api.github.com/users/jeffkinnison/orgs","repos_url":"https://api.github.com/users/jeffkinnison/repos","events_url":"https://api.github.com/users/jeffkinnison/events{/privacy}","received_events_url":"https://api.github.com/users/jeffkinnison/received_events","type":"User","site_admin":false},"html_url":"https://github.com/jeffkinnison/tesserae-v5","description":null,"fork":true,"url":"https://api.github.com/repos/jeffkinnison/tesserae-v5","forks_url":"https://api.github.com/repos/jeffkinnison/tesserae-v5/forks","keys_url":"https://api.github.com/repos/jeffkinnison/tesserae-v5/keys{/key_id}","collaborators_url":"https://api.github.com/repos/jeffkinnison/tesserae-v5/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/jeffkinnison/tesserae-v5/teams","hooks_url":"https://api.github.com/repos/jeffkinnison/tesserae-v5/hooks","issue_events_url":"https://api.github.com/repos/jeffkinnison/tesserae-v5/issues/events{/number}","events_url":"https://api.github.com/repos/jeffkinnison/tesserae-v5/events","assignees_url":"https://api.github.com/repos/jeffkinnison/tesserae-v5/assignees{/user}","branches_url":"https://api.github.com/repos/jeffkinnison/tesserae-v5/branches{/branch}","tags_url":"https://api.github.com/repos/jeffkinnison/tesserae-v5/tags","blobs_url":"https://api.github.com/repos/jeffkinnison/tesserae-v5/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/jeffkinnison/tesserae-v5/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/jeffkinnison/tesserae-v5/git/refs{/sha}","trees_url":"https://api.github.com/repos/jeffkinnison/tesserae-v5/git/trees{/sha}","statuses_url":"https://api.github.com/repos/jeffkinnison/tesserae-v5/statuses/{sha}","languages_url":"https://api.github.com/repos/jeffkinnison/tesserae-v5/languages","stargazers_url":"https://api.github.com/repos/jeffkinnison/tesserae-v5/stargazers","contributors_url":"https://api.github.com/repos/jeffkinnison/tesserae-v5/contributors","subscribers_url":"https://api.github.com/repos/jeffkinnison/tesserae-v5/subscribers","subscription_url":"https://api.github.com/repos/jeffkinnison/tesserae-v5/subscription","commits_url":"https://api.github.com/repos/jeffkinnison/tesserae-v5/commits{/sha}","git_commits_url":"https://api.github.com/repos/jeffkinnison/tesserae-v5/git/commits{/sha}","comments_url":"https://api.github.com/repos/jeffkinnison/tesserae-v5/comments{/number}","issue_comment_url":"https://api.github.com/repos/jeffkinnison/tesserae-v5/issues/comments{/number}","contents_url":"https://api.github.com/repos/jeffkinnison/tesserae-v5/contents/{+path}","compare_url":"https://api.github.com/repos/jeffkinnison/tesserae-v5/compare/{base}...{head}","merges_url":"https://api.github.com/repos/jeffkinnison/tesserae-v5/merges","archive_url":"https://api.github.com/repos/jeffkinnison/tesserae-v5/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/jeffkinnison/tesserae-v5/downloads","issues_url":"https://api.github.com/repos/jeffkinnison/tesserae-v5/issues{/number}","pulls_url":"https://api.github.com/repos/jeffkinnison/tesserae-v5/pulls{/number}","milestones_url":"https://api.github.com/repos/jeffkinnison/tesserae-v5/milestones{/number}","notifications_url":"https://api.github.com/repos/jeffkinnison/tesserae-v5/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/jeffkinnison/tesserae-v5/labels{/name}","releases_url":"https://api.github.com/repos/jeffkinnison/tesserae-v5/releases{/id}","deployments_url":"https://api.github.com/repos/jeffkinnison/tesserae-v5/deployments","created_at":"2018-05-04T15:18:13Z","updated_at":"2018-10-30T18:29:49Z","pushed_at":"2018-12-19T15:15:44Z","git_url":"git://github.com/jeffkinnison/tesserae-v5.git","ssh_url":"git@github.com:jeffkinnison/tesserae-v5.git","clone_url":"https://github.com/jeffkinnison/tesserae-v5.git","svn_url":"https://github.com/jeffkinnison/tesserae-v5","homepage":null,"size":34477,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":0,"license":null,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"tesserae:master","ref":"master","sha":"08c20a52f3a1af4c041bfb8268a71df08e4449de","user":{"login":"tesserae","id":2402550,"node_id":"MDQ6VXNlcjI0MDI1NTA=","avatar_url":"https://avatars1.githubusercontent.com/u/2402550?v=4","gravatar_id":"","url":"https://api.github.com/users/tesserae","html_url":"https://github.com/tesserae","followers_url":"https://api.github.com/users/tesserae/followers","following_url":"https://api.github.com/users/tesserae/following{/other_user}","gists_url":"https://api.github.com/users/tesserae/gists{/gist_id}","starred_url":"https://api.github.com/users/tesserae/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tesserae/subscriptions","organizations_url":"https://api.github.com/users/tesserae/orgs","repos_url":"https://api.github.com/users/tesserae/repos","events_url":"https://api.github.com/users/tesserae/events{/privacy}","received_events_url":"https://api.github.com/users/tesserae/received_events","type":"User","site_admin":false},"repo":{"id":131435486,"node_id":"MDEwOlJlcG9zaXRvcnkxMzE0MzU0ODY=","name":"tesserae-v5","full_name":"tesserae/tesserae-v5","private":false,"owner":{"login":"tesserae","id":2402550,"node_id":"MDQ6VXNlcjI0MDI1NTA=","avatar_url":"https://avatars1.githubusercontent.com/u/2402550?v=4","gravatar_id":"","url":"https://api.github.com/users/tesserae","html_url":"https://github.com/tesserae","followers_url":"https://api.github.com/users/tesserae/followers","following_url":"https://api.github.com/users/tesserae/following{/other_user}","gists_url":"https://api.github.com/users/tesserae/gists{/gist_id}","starred_url":"https://api.github.com/users/tesserae/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tesserae/subscriptions","organizations_url":"https://api.github.com/users/tesserae/orgs","repos_url":"https://api.github.com/users/tesserae/repos","events_url":"https://api.github.com/users/tesserae/events{/privacy}","received_events_url":"https://api.github.com/users/tesserae/received_events","type":"User","site_admin":false},"html_url":"https://github.com/tesserae/tesserae-v5","description":null,"fork":false,"url":"https://api.github.com/repos/tesserae/tesserae-v5","forks_url":"https://api.github.com/repos/tesserae/tesserae-v5/forks","keys_url":"https://api.github.com/repos/tesserae/tesserae-v5/keys{/key_id}","collaborators_url":"https://api.github.com/repos/tesserae/tesserae-v5/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/tesserae/tesserae-v5/teams","hooks_url":"https://api.github.com/repos/tesserae/tesserae-v5/hooks","issue_events_url":"https://api.github.com/repos/tesserae/tesserae-v5/issues/events{/number}","events_url":"https://api.github.com/repos/tesserae/tesserae-v5/events","assignees_url":"https://api.github.com/repos/tesserae/tesserae-v5/assignees{/user}","branches_url":"https://api.github.com/repos/tesserae/tesserae-v5/branches{/branch}","tags_url":"https://api.github.com/repos/tesserae/tesserae-v5/tags","blobs_url":"https://api.github.com/repos/tesserae/tesserae-v5/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/tesserae/tesserae-v5/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/tesserae/tesserae-v5/git/refs{/sha}","trees_url":"https://api.github.com/repos/tesserae/tesserae-v5/git/trees{/sha}","statuses_url":"https://api.github.com/repos/tesserae/tesserae-v5/statuses/{sha}","languages_url":"https://api.github.com/repos/tesserae/tesserae-v5/languages","stargazers_url":"https://api.github.com/repos/tesserae/tesserae-v5/stargazers","contributors_url":"https://api.github.com/repos/tesserae/tesserae-v5/contributors","subscribers_url":"https://api.github.com/repos/tesserae/tesserae-v5/subscribers","subscription_url":"https://api.github.com/repos/tesserae/tesserae-v5/subscription","commits_url":"https://api.github.com/repos/tesserae/tesserae-v5/commits{/sha}","git_commits_url":"https://api.github.com/repos/tesserae/tesserae-v5/git/commits{/sha}","comments_url":"https://api.github.com/repos/tesserae/tesserae-v5/comments{/number}","issue_comment_url":"https://api.github.com/repos/tesserae/tesserae-v5/issues/comments{/number}","contents_url":"https://api.github.com/repos/tesserae/tesserae-v5/contents/{+path}","compare_url":"https://api.github.com/repos/tesserae/tesserae-v5/compare/{base}...{head}","merges_url":"https://api.github.com/repos/tesserae/tesserae-v5/merges","archive_url":"https://api.github.com/repos/tesserae/tesserae-v5/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/tesserae/tesserae-v5/downloads","issues_url":"https://api.github.com/repos/tesserae/tesserae-v5/issues{/number}","pulls_url":"https://api.github.com/repos/tesserae/tesserae-v5/pulls{/number}","milestones_url":"https://api.github.com/repos/tesserae/tesserae-v5/milestones{/number}","notifications_url":"https://api.github.com/repos/tesserae/tesserae-v5/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/tesserae/tesserae-v5/labels{/name}","releases_url":"https://api.github.com/repos/tesserae/tesserae-v5/releases{/id}","deployments_url":"https://api.github.com/repos/tesserae/tesserae-v5/deployments","created_at":"2018-04-28T18:46:36Z","updated_at":"2018-10-30T18:29:38Z","pushed_at":"2018-12-19T15:15:46Z","git_url":"git://github.com/tesserae/tesserae-v5.git","ssh_url":"git@github.com:tesserae/tesserae-v5.git","clone_url":"https://github.com/tesserae/tesserae-v5.git","svn_url":"https://github.com/tesserae/tesserae-v5","homepage":null,"size":34457,"stargazers_count":1,"watchers_count":1,"language":"Python","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":3,"mirror_url":null,"archived":false,"open_issues_count":11,"license":null,"forks":3,"open_issues":11,"watchers":1,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/tesserae/tesserae-v5/pulls/16"},"html":{"href":"https://github.com/tesserae/tesserae-v5/pull/16"},"issue":{"href":"https://api.github.com/repos/tesserae/tesserae-v5/issues/16"},"comments":{"href":"https://api.github.com/repos/tesserae/tesserae-v5/issues/16/comments"},"review_comments":{"href":"https://api.github.com/repos/tesserae/tesserae-v5/pulls/16/comments"},"review_comment":{"href":"https://api.github.com/repos/tesserae/tesserae-v5/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/tesserae/tesserae-v5/pulls/16/commits"},"statuses":{"href":"https://api.github.com/repos/tesserae/tesserae-v5/statuses/600500d3137a827dc4dff9fb09ee8f5387cba877"}},"author_association":"COLLABORATOR"}}
{"actor":{"display_login":"jeffkinnison"}}