{"action":"created","comment":{"url":"https://api.github.com/repos/numpy/numpy/pulls/comments/218303174","pull_request_review_id":156208968,"id":218303174,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDIxODMwMzE3NA==","diff_hunk":"@@ -423,32 +437,90 @@ def format_index(index):\n         return parent_index, _nx.ndim(arrays)\n \n \n-def _block(arrays, max_depth, result_ndim):\n-    \"\"\"\n-    Internal implementation of block. `arrays` is the argument passed to\n-    block. `max_depth` is the depth of nested lists within `arrays` and\n-    `result_ndim` is the greatest of the dimensions of the arrays in\n-    `arrays` and the depth of the lists in `arrays` (see block docstring\n-    for details).\n+def _concatenate_shapes(shapes, axis):\n+    \"\"\"Given array shapes, return the resulting shape that would occur\n+    after array concatenation.\n+\n+    concatenate(arrs, axis).shape == _concatenate_shapes([a.shape for a in arrs], axis)\n     \"\"\"\n-    def atleast_nd(a, ndim):\n-        # Ensures `a` has at least `ndim` dimensions by prepending\n-        # ones to `a.shape` as necessary\n-        return array(a, ndmin=ndim, copy=False, subok=True)\n-\n-    @recursive\n-    def block_recursion(self, arrays, depth=0):\n-        if depth < max_depth:\n-            if len(arrays) == 0:\n-                raise ValueError('Lists cannot be empty')\n-            arrs = [self(arr, depth+1) for arr in arrays]\n-            return _nx.concatenate(arrs, axis=-(max_depth-depth))\n-        else:\n-            # We've 'bottomed out' - arrays is either a scalar or an array\n-            # type(arrays) is not list\n-            return atleast_nd(arrays, result_ndim)\n+    # Take a shape, any shape\n+    first_shape = shapes[0]\n+    for shape in shapes[1:]:\n+        if (shape[:axis] != first_shape[:axis] or\n+                shape[axis+1:] != first_shape[axis+1:]):\n+            raise ValueError('Mismatched array shapes in block.')\n+    shape_on_dim = sum(shape[axis] for shape in shapes)\n+    return first_shape[:axis] + (shape_on_dim,) + first_shape[axis+1:]\n+\n \n-    return block_recursion(arrays)\n+def _atleast_nd(a, ndim):\n+    # Ensures `a` has at least `ndim` dimensions by prepending\n+    # ones to `a.shape` as necessary\n+    return array(a, ndmin=ndim, copy=False, subok=True)\n+\n+\n+def _accumulate(values):\n+    # Helper function because Python 2.7 doesn't have\n+    # itertools.accumulate\n+    value = 0\n+    accumulated = []\n+    for v in values:\n+        value += v\n+        accumulated.append(value)\n+\n+    return tuple(accumulated)\n+\n+\n+def _block_info_recursion(arrays, list_ndim, result_ndim, depth=0):\n+    \"\"\"Form required information to block the arrays using a flat iterator.\n+\n+    Returns\n+    -------\n+    shape: tuple of ints\n+        the resulting shape of the final array\n+    region_slices: iterable of indices\n+        slices into the full array required for assignment\n+    region_data: iterable of ndarray\n+        the data to assign to each slice of the full array\n+\n+    \"\"\"\n+    if depth < list_ndim:\n+        axis = result_ndim - list_ndim + depth\n+        info = [_block_info_recursion(arr, list_ndim, result_ndim, depth + 1)\n+                for arr in arrays]\n+        shapes, slices, arrays = zip(*info)\n+        # Compute the offset for each array\n+        offsets = (0,) + tuple(_accumulate(shape[axis]\n+                                           for shape in shapes[:-1]))\n+        # `slices` and `arrays` contain lists that have the information\n+        # from the inner lists provided to the concatenation function.\n+        # To create the correct offset, one needs to prepend the appropriate\n+        # offset to each of them. Each list (containing one or more arrays)\n+        # will require the matching offset (computed above with accumulate)\n+        slice_prefixes = [(slice(offset, offset + shape[axis]),)\n+                          for offset, shape in zip(offsets, shapes)]","path":"numpy/core/shape_base.py","position":null,"original_position":177,"commit_id":"cc8de62c049cf4f58a8f7665aa88bb4f67f11d89","original_commit_id":"c2ba6e56633a7f63e13ce57455ec39f13aeca013","user":{"login":"eric-wieser","id":425260,"node_id":"MDQ6VXNlcjQyNTI2MA==","avatar_url":"https://avatars3.githubusercontent.com/u/425260?v=4","gravatar_id":"","url":"https://api.github.com/users/eric-wieser","html_url":"https://github.com/eric-wieser","followers_url":"https://api.github.com/users/eric-wieser/followers","following_url":"https://api.github.com/users/eric-wieser/following{/other_user}","gists_url":"https://api.github.com/users/eric-wieser/gists{/gist_id}","starred_url":"https://api.github.com/users/eric-wieser/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/eric-wieser/subscriptions","organizations_url":"https://api.github.com/users/eric-wieser/orgs","repos_url":"https://api.github.com/users/eric-wieser/repos","events_url":"https://api.github.com/users/eric-wieser/events{/privacy}","received_events_url":"https://api.github.com/users/eric-wieser/received_events","type":"User","site_admin":false},"body":"> I don't really see the point of having so many helper functions. \r\n\r\nIt's not just about code reuse - it's about using function names to describe pieces of your algorithm instead of comments, and allowing the reader to reason about your code in pieces rather than all at once.","created_at":"2018-09-18T05:35:03Z","updated_at":"2018-09-18T05:35:04Z","html_url":"https://github.com/numpy/numpy/pull/11971#discussion_r218303174","pull_request_url":"https://api.github.com/repos/numpy/numpy/pulls/11971","author_association":"MEMBER","_links":{"self":{"href":"https://api.github.com/repos/numpy/numpy/pulls/comments/218303174"},"html":{"href":"https://github.com/numpy/numpy/pull/11971#discussion_r218303174"},"pull_request":{"href":"https://api.github.com/repos/numpy/numpy/pulls/11971"}},"in_reply_to_id":218297522},"pull_request":{"url":"https://api.github.com/repos/numpy/numpy/pulls/11971","id":215878195,"node_id":"MDExOlB1bGxSZXF1ZXN0MjE1ODc4MTk1","html_url":"https://github.com/numpy/numpy/pull/11971","diff_url":"https://github.com/numpy/numpy/pull/11971.diff","patch_url":"https://github.com/numpy/numpy/pull/11971.patch","issue_url":"https://api.github.com/repos/numpy/numpy/issues/11971","number":11971,"state":"open","locked":false,"title":"MAINT: Block algorithm with a single copy per call to `block`","user":{"login":"hmaarrfk","id":90008,"node_id":"MDQ6VXNlcjkwMDA4","avatar_url":"https://avatars0.githubusercontent.com/u/90008?v=4","gravatar_id":"","url":"https://api.github.com/users/hmaarrfk","html_url":"https://github.com/hmaarrfk","followers_url":"https://api.github.com/users/hmaarrfk/followers","following_url":"https://api.github.com/users/hmaarrfk/following{/other_user}","gists_url":"https://api.github.com/users/hmaarrfk/gists{/gist_id}","starred_url":"https://api.github.com/users/hmaarrfk/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hmaarrfk/subscriptions","organizations_url":"https://api.github.com/users/hmaarrfk/orgs","repos_url":"https://api.github.com/users/hmaarrfk/repos","events_url":"https://api.github.com/users/hmaarrfk/events{/privacy}","received_events_url":"https://api.github.com/users/hmaarrfk/received_events","type":"User","site_admin":false},"body":"Block used to make repeated calls to concatenate. For a 3D block, this would copy the arrays 3 times. 1 time for each dimension of the block. This is 2 times too many.\r\n\r\nThis proposed algorithm does so with 1 memory copy.\r\n\r\nIt:\r\n\r\n1. Calls `asanyarray` to make make the following logic easier.\r\n2. Finds the shape of the final array\r\n3. Finds the dtype of the final array.\r\n4. Allocates the necessary memory.\r\n5. Copies the memory in.\r\n\r\nAs is:\r\n- [x] Passes all tests.\r\n- [x] Code is clean\r\n- [x] Code is commented\r\n- [x] Improves on benchmark\r\n\r\n\r\nFor large arrays, the benchmark https://github.com/numpy/numpy/pull/11965 shows that there is now little room to improve compared to a straight concatenate operation.\r\n\r\nThe benchmarks show results for a final array of size `5 n`^3. Therefore, for n=10, the final array has 125,000 elements.\r\n\r\nNew results\r\n```\r\n===== ========== =============\r\n--              mode          \r\n----- ------------------------\r\nn     block     concatenate \r\n===== ========== =============\r\n1    130±5μs    2.57±0.07μs \r\n10   245±30μs     53.9±3μs  \r\n100   503±4ms      555±9ms   \r\n===== ========== =============\r\n```\r\n\r\nImprovement compared to the old results\r\n\r\n```\r\nasv continuous -E conda:3.6 -b Block.time_3d master block_single_concatenate_call \r\n```\r\n```\r\n       before           after         ratio\r\n     [58da5687]       [66baab20]\r\n     <master>         <block_single_concatenate_call>\r\n+        49.4±1μs          130±5μs     2.64  bench_shape_base.Block.time_3d(1, 'block')\r\n-      1.48±0.04s          503±4ms     0.34  bench_shape_base.Block.time_3d(100, 'block')\r\n-      1.08±0.2ms         245±30μs     0.23  bench_shape_base.Block.time_3d(10, 'block')\r\n```\r\n\r\nImmediate things to improve on might be avoiding 3 calls to recursive functions. `asanyarray`, `shape` and `dtype` recursions can likely be combined.\r\n\r\nFinally, this probably lends itself well to offering options like `order`, which would allow one to choose the order of the final array, or even to specify the array that they want to provide through an `out` parameter.\r\n\r\n\r\nClosures are avoided entirely, so I  think that gh-10620 is not an issue.","created_at":"2018-09-17T05:48:32Z","updated_at":"2018-09-18T05:35:04Z","closed_at":null,"merged_at":null,"merge_commit_sha":"5fabae93c070881176290b39ebe835be2964594a","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[{"id":36825825,"node_id":"MDU6TGFiZWwzNjgyNTgyNQ==","url":"https://api.github.com/repos/numpy/numpy/labels/03%20-%20Maintenance","name":"03 - Maintenance","color":"fef2c0","default":false},{"id":16917029,"node_id":"MDU6TGFiZWwxNjkxNzAyOQ==","url":"https://api.github.com/repos/numpy/numpy/labels/component:%20numpy.core","name":"component: numpy.core","color":"009800","default":false}],"milestone":null,"commits_url":"https://api.github.com/repos/numpy/numpy/pulls/11971/commits","review_comments_url":"https://api.github.com/repos/numpy/numpy/pulls/11971/comments","review_comment_url":"https://api.github.com/repos/numpy/numpy/pulls/comments{/number}","comments_url":"https://api.github.com/repos/numpy/numpy/issues/11971/comments","statuses_url":"https://api.github.com/repos/numpy/numpy/statuses/cc8de62c049cf4f58a8f7665aa88bb4f67f11d89","head":{"label":"hmaarrfk:block_single_concatenate_call","ref":"block_single_concatenate_call","sha":"cc8de62c049cf4f58a8f7665aa88bb4f67f11d89","user":{"login":"hmaarrfk","id":90008,"node_id":"MDQ6VXNlcjkwMDA4","avatar_url":"https://avatars0.githubusercontent.com/u/90008?v=4","gravatar_id":"","url":"https://api.github.com/users/hmaarrfk","html_url":"https://github.com/hmaarrfk","followers_url":"https://api.github.com/users/hmaarrfk/followers","following_url":"https://api.github.com/users/hmaarrfk/following{/other_user}","gists_url":"https://api.github.com/users/hmaarrfk/gists{/gist_id}","starred_url":"https://api.github.com/users/hmaarrfk/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hmaarrfk/subscriptions","organizations_url":"https://api.github.com/users/hmaarrfk/orgs","repos_url":"https://api.github.com/users/hmaarrfk/repos","events_url":"https://api.github.com/users/hmaarrfk/events{/privacy}","received_events_url":"https://api.github.com/users/hmaarrfk/received_events","type":"User","site_admin":false},"repo":{"id":135739763,"node_id":"MDEwOlJlcG9zaXRvcnkxMzU3Mzk3NjM=","name":"numpy","full_name":"hmaarrfk/numpy","private":false,"owner":{"login":"hmaarrfk","id":90008,"node_id":"MDQ6VXNlcjkwMDA4","avatar_url":"https://avatars0.githubusercontent.com/u/90008?v=4","gravatar_id":"","url":"https://api.github.com/users/hmaarrfk","html_url":"https://github.com/hmaarrfk","followers_url":"https://api.github.com/users/hmaarrfk/followers","following_url":"https://api.github.com/users/hmaarrfk/following{/other_user}","gists_url":"https://api.github.com/users/hmaarrfk/gists{/gist_id}","starred_url":"https://api.github.com/users/hmaarrfk/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hmaarrfk/subscriptions","organizations_url":"https://api.github.com/users/hmaarrfk/orgs","repos_url":"https://api.github.com/users/hmaarrfk/repos","events_url":"https://api.github.com/users/hmaarrfk/events{/privacy}","received_events_url":"https://api.github.com/users/hmaarrfk/received_events","type":"User","site_admin":false},"html_url":"https://github.com/hmaarrfk/numpy","description":"Numpy main repository","fork":true,"url":"https://api.github.com/repos/hmaarrfk/numpy","forks_url":"https://api.github.com/repos/hmaarrfk/numpy/forks","keys_url":"https://api.github.com/repos/hmaarrfk/numpy/keys{/key_id}","collaborators_url":"https://api.github.com/repos/hmaarrfk/numpy/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/hmaarrfk/numpy/teams","hooks_url":"https://api.github.com/repos/hmaarrfk/numpy/hooks","issue_events_url":"https://api.github.com/repos/hmaarrfk/numpy/issues/events{/number}","events_url":"https://api.github.com/repos/hmaarrfk/numpy/events","assignees_url":"https://api.github.com/repos/hmaarrfk/numpy/assignees{/user}","branches_url":"https://api.github.com/repos/hmaarrfk/numpy/branches{/branch}","tags_url":"https://api.github.com/repos/hmaarrfk/numpy/tags","blobs_url":"https://api.github.com/repos/hmaarrfk/numpy/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/hmaarrfk/numpy/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/hmaarrfk/numpy/git/refs{/sha}","trees_url":"https://api.github.com/repos/hmaarrfk/numpy/git/trees{/sha}","statuses_url":"https://api.github.com/repos/hmaarrfk/numpy/statuses/{sha}","languages_url":"https://api.github.com/repos/hmaarrfk/numpy/languages","stargazers_url":"https://api.github.com/repos/hmaarrfk/numpy/stargazers","contributors_url":"https://api.github.com/repos/hmaarrfk/numpy/contributors","subscribers_url":"https://api.github.com/repos/hmaarrfk/numpy/subscribers","subscription_url":"https://api.github.com/repos/hmaarrfk/numpy/subscription","commits_url":"https://api.github.com/repos/hmaarrfk/numpy/commits{/sha}","git_commits_url":"https://api.github.com/repos/hmaarrfk/numpy/git/commits{/sha}","comments_url":"https://api.github.com/repos/hmaarrfk/numpy/comments{/number}","issue_comment_url":"https://api.github.com/repos/hmaarrfk/numpy/issues/comments{/number}","contents_url":"https://api.github.com/repos/hmaarrfk/numpy/contents/{+path}","compare_url":"https://api.github.com/repos/hmaarrfk/numpy/compare/{base}...{head}","merges_url":"https://api.github.com/repos/hmaarrfk/numpy/merges","archive_url":"https://api.github.com/repos/hmaarrfk/numpy/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/hmaarrfk/numpy/downloads","issues_url":"https://api.github.com/repos/hmaarrfk/numpy/issues{/number}","pulls_url":"https://api.github.com/repos/hmaarrfk/numpy/pulls{/number}","milestones_url":"https://api.github.com/repos/hmaarrfk/numpy/milestones{/number}","notifications_url":"https://api.github.com/repos/hmaarrfk/numpy/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/hmaarrfk/numpy/labels{/name}","releases_url":"https://api.github.com/repos/hmaarrfk/numpy/releases{/id}","deployments_url":"https://api.github.com/repos/hmaarrfk/numpy/deployments","created_at":"2018-06-01T16:21:29Z","updated_at":"2018-09-18T04:31:49Z","pushed_at":"2018-09-18T05:23:22Z","git_url":"git://github.com/hmaarrfk/numpy.git","ssh_url":"git@github.com:hmaarrfk/numpy.git","clone_url":"https://github.com/hmaarrfk/numpy.git","svn_url":"https://github.com/hmaarrfk/numpy","homepage":"http://www.numpy.org/","size":59289,"stargazers_count":0,"watchers_count":0,"language":"C","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":{"key":"other","name":"Other","spdx_id":null,"url":null,"node_id":"MDc6TGljZW5zZTA="},"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"numpy:master","ref":"master","sha":"b5f56572ac656f95c8ecc19bf506983e9df78df9","user":{"login":"numpy","id":288276,"node_id":"MDEyOk9yZ2FuaXphdGlvbjI4ODI3Ng==","avatar_url":"https://avatars2.githubusercontent.com/u/288276?v=4","gravatar_id":"","url":"https://api.github.com/users/numpy","html_url":"https://github.com/numpy","followers_url":"https://api.github.com/users/numpy/followers","following_url":"https://api.github.com/users/numpy/following{/other_user}","gists_url":"https://api.github.com/users/numpy/gists{/gist_id}","starred_url":"https://api.github.com/users/numpy/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/numpy/subscriptions","organizations_url":"https://api.github.com/users/numpy/orgs","repos_url":"https://api.github.com/users/numpy/repos","events_url":"https://api.github.com/users/numpy/events{/privacy}","received_events_url":"https://api.github.com/users/numpy/received_events","type":"Organization","site_admin":false},"repo":{"id":908607,"node_id":"MDEwOlJlcG9zaXRvcnk5MDg2MDc=","name":"numpy","full_name":"numpy/numpy","private":false,"owner":{"login":"numpy","id":288276,"node_id":"MDEyOk9yZ2FuaXphdGlvbjI4ODI3Ng==","avatar_url":"https://avatars2.githubusercontent.com/u/288276?v=4","gravatar_id":"","url":"https://api.github.com/users/numpy","html_url":"https://github.com/numpy","followers_url":"https://api.github.com/users/numpy/followers","following_url":"https://api.github.com/users/numpy/following{/other_user}","gists_url":"https://api.github.com/users/numpy/gists{/gist_id}","starred_url":"https://api.github.com/users/numpy/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/numpy/subscriptions","organizations_url":"https://api.github.com/users/numpy/orgs","repos_url":"https://api.github.com/users/numpy/repos","events_url":"https://api.github.com/users/numpy/events{/privacy}","received_events_url":"https://api.github.com/users/numpy/received_events","type":"Organization","site_admin":false},"html_url":"https://github.com/numpy/numpy","description":"Numpy main repository","fork":false,"url":"https://api.github.com/repos/numpy/numpy","forks_url":"https://api.github.com/repos/numpy/numpy/forks","keys_url":"https://api.github.com/repos/numpy/numpy/keys{/key_id}","collaborators_url":"https://api.github.com/repos/numpy/numpy/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/numpy/numpy/teams","hooks_url":"https://api.github.com/repos/numpy/numpy/hooks","issue_events_url":"https://api.github.com/repos/numpy/numpy/issues/events{/number}","events_url":"https://api.github.com/repos/numpy/numpy/events","assignees_url":"https://api.github.com/repos/numpy/numpy/assignees{/user}","branches_url":"https://api.github.com/repos/numpy/numpy/branches{/branch}","tags_url":"https://api.github.com/repos/numpy/numpy/tags","blobs_url":"https://api.github.com/repos/numpy/numpy/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/numpy/numpy/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/numpy/numpy/git/refs{/sha}","trees_url":"https://api.github.com/repos/numpy/numpy/git/trees{/sha}","statuses_url":"https://api.github.com/repos/numpy/numpy/statuses/{sha}","languages_url":"https://api.github.com/repos/numpy/numpy/languages","stargazers_url":"https://api.github.com/repos/numpy/numpy/stargazers","contributors_url":"https://api.github.com/repos/numpy/numpy/contributors","subscribers_url":"https://api.github.com/repos/numpy/numpy/subscribers","subscription_url":"https://api.github.com/repos/numpy/numpy/subscription","commits_url":"https://api.github.com/repos/numpy/numpy/commits{/sha}","git_commits_url":"https://api.github.com/repos/numpy/numpy/git/commits{/sha}","comments_url":"https://api.github.com/repos/numpy/numpy/comments{/number}","issue_comment_url":"https://api.github.com/repos/numpy/numpy/issues/comments{/number}","contents_url":"https://api.github.com/repos/numpy/numpy/contents/{+path}","compare_url":"https://api.github.com/repos/numpy/numpy/compare/{base}...{head}","merges_url":"https://api.github.com/repos/numpy/numpy/merges","archive_url":"https://api.github.com/repos/numpy/numpy/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/numpy/numpy/downloads","issues_url":"https://api.github.com/repos/numpy/numpy/issues{/number}","pulls_url":"https://api.github.com/repos/numpy/numpy/pulls{/number}","milestones_url":"https://api.github.com/repos/numpy/numpy/milestones{/number}","notifications_url":"https://api.github.com/repos/numpy/numpy/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/numpy/numpy/labels{/name}","releases_url":"https://api.github.com/repos/numpy/numpy/releases{/id}","deployments_url":"https://api.github.com/repos/numpy/numpy/deployments","created_at":"2010-09-13T23:02:39Z","updated_at":"2018-09-18T04:57:05Z","pushed_at":"2018-09-18T05:23:25Z","git_url":"git://github.com/numpy/numpy.git","ssh_url":"git@github.com:numpy/numpy.git","clone_url":"https://github.com/numpy/numpy.git","svn_url":"https://github.com/numpy/numpy","homepage":"https://www.numpy.org/","size":60474,"stargazers_count":8170,"watchers_count":8170,"language":"C","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":2994,"mirror_url":null,"archived":false,"open_issues_count":1976,"license":{"key":"other","name":"Other","spdx_id":null,"url":null,"node_id":"MDc6TGljZW5zZTA="},"forks":2994,"open_issues":1976,"watchers":8170,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/numpy/numpy/pulls/11971"},"html":{"href":"https://github.com/numpy/numpy/pull/11971"},"issue":{"href":"https://api.github.com/repos/numpy/numpy/issues/11971"},"comments":{"href":"https://api.github.com/repos/numpy/numpy/issues/11971/comments"},"review_comments":{"href":"https://api.github.com/repos/numpy/numpy/pulls/11971/comments"},"review_comment":{"href":"https://api.github.com/repos/numpy/numpy/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/numpy/numpy/pulls/11971/commits"},"statuses":{"href":"https://api.github.com/repos/numpy/numpy/statuses/cc8de62c049cf4f58a8f7665aa88bb4f67f11d89"}},"author_association":"CONTRIBUTOR"}}
{"actor":{"display_login":"eric-wieser"}}