{"action":"created","comment":{"url":"https://api.github.com/repos/NSLS-II/bluesky/pulls/comments/241179317","pull_request_review_id":184387410,"id":241179317,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDI0MTE3OTMxNw==","diff_hunk":"@@ -50,6 +78,125 @@ def stop(self, doc):\n         pass\n \n \n+class RunRouter(CallbackBase):\n+    \"\"\"\n+    Routes documents, by run, to callbacks it creates from factory functions.\n+\n+    A RunRouter is callable, and it is has the signature ``router(name, doc)``,\n+    suitable for subscribing to the RunEngine.\n+\n+    The RunRouter maintains a list of factory functions with the signature\n+    ``callback_factory(start_doc)``. When the router receives a RunStart\n+    document, it passes it to each ``callback_factory`` function. Each factory\n+    should return ``None`` (\"I am not interested in this run,\") or a callback\n+    function with the signature ``cb(name, doc)``. All future documents related\n+    to that run will be forwarded to ``cb``. When the run is complete, the\n+    RunRouter will drop all its references to ``cb``. It is up to\n+    ``callback_factory`` whether to return a new callable each time (having a\n+    lifecycle of one run, garbage collected thereafter), or to return the same\n+    object every time, or some other pattern.\n+    \n+    To summarize, the RunRouter's promise is that it will call each\n+    ``callback_factory`` with each new RunStart document and that it will\n+    forward all other documents from that run to whatever ``callback_factory``\n+    returns (if not None).\n+\n+    Parameters\n+    ----------\n+    callback_factories : list\n+        A list of callables with the signature:\n+\n+            callback_factory(start_doc)\n+\n+        which should return ``None`` or another callable with this signature:\n+\n+            callback(name, doc)\n+    \"\"\"\n+    def __init__(self, callback_factories):\n+        self.callback_factories = callback_factories\n+        self.callbacks = defaultdict(list)  # start uid -> callbacks\n+        self.descriptors = {}  # descriptor uid -> start uid\n+        self.resources = {}  # resource uid -> start uid\n+\n+    def _event_or_bulk_event(self, doc):\n+        descriptor_uid = doc['descriptor']\n+        try:\n+            start_uid = self.descriptors[descriptor_uid]\n+        except KeyError:\n+            # The belongs to a run that we are not interested in.\n+            return []\n+        return self.callbacks[start_uid]\n+\n+    def event(self, doc):\n+        for cb in self._event_or_bulk_event(doc):\n+            cb('event', doc)\n+\n+    def bulk_event(self, doc):\n+        for cb in self._event_or_bulk_event(doc):\n+            cb('bulk_event', doc)\n+\n+    def _datum_or_bulk_datum(self, doc):\n+        resource_uid = doc['resource']\n+        try:\n+            start_uid = self.resources[resource_uid]\n+        except KeyError:\n+            # The belongs to a run that we are not interested in.\n+            return []\n+        return self.callbacks[start_uid]\n+\n+    def datum(self, doc):\n+        for cb in self._datum_or_bulk_datum(doc):\n+            cb('datum', doc)\n+\n+    def bulk_datum(self, doc):\n+        for cb in self._datum_or_bulk_datum(doc):\n+            cb('bulk_datum', doc)\n+\n+    def descriptor(self, doc):\n+        start_uid = doc['run_start']\n+        cbs = self.callbacks[start_uid]\n+        if not cbs:\n+            # This belongs to a run we are not interested in.\n+            return\n+        self.descriptors[doc['uid']] = start_uid\n+        for cb in cbs:\n+            cb('descriptor', doc)\n+\n+    def resource(self, doc):\n+        start_uid = doc['run_start']\n+        cbs = self.callbacks[start_uid]\n+        if not cbs:\n+            # This belongs to a run we are not interested in.\n+            return\n+        self.resources[doc['uid']] = start_uid\n+        for cb in cbs:\n+            cb('resource', doc)\n+\n+    def start(self, doc):\n+        for callback_factory in self.callback_factories:\n+            cb = callback_factory(doc)","path":"bluesky/callbacks/core.py","position":144,"original_position":144,"commit_id":"f5a4b3664bed01ee695156f5bf3f9e1a5417f0cf","original_commit_id":"f5a4b3664bed01ee695156f5bf3f9e1a5417f0cf","user":{"login":"CJ-Wright","id":6740689,"node_id":"MDQ6VXNlcjY3NDA2ODk=","avatar_url":"https://avatars3.githubusercontent.com/u/6740689?v=4","gravatar_id":"","url":"https://api.github.com/users/CJ-Wright","html_url":"https://github.com/CJ-Wright","followers_url":"https://api.github.com/users/CJ-Wright/followers","following_url":"https://api.github.com/users/CJ-Wright/following{/other_user}","gists_url":"https://api.github.com/users/CJ-Wright/gists{/gist_id}","starred_url":"https://api.github.com/users/CJ-Wright/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/CJ-Wright/subscriptions","organizations_url":"https://api.github.com/users/CJ-Wright/orgs","repos_url":"https://api.github.com/users/CJ-Wright/repos","events_url":"https://api.github.com/users/CJ-Wright/events{/privacy}","received_events_url":"https://api.github.com/users/CJ-Wright/received_events","type":"User","site_admin":false},"body":"Do we need a mechanism for pushing more information into the `callback_factory`? One could imagine wanting to pass information into the callback at init time which is not in the document. For instance, if I build a `callback_factory` which returns a `LiveScatter` how do I change the colormap of the scatter plot for the next scan?","created_at":"2018-12-12T20:47:06Z","updated_at":"2018-12-12T20:47:07Z","html_url":"https://github.com/NSLS-II/bluesky/pull/1076#discussion_r241179317","pull_request_url":"https://api.github.com/repos/NSLS-II/bluesky/pulls/1076","author_association":"MEMBER","_links":{"self":{"href":"https://api.github.com/repos/NSLS-II/bluesky/pulls/comments/241179317"},"html":{"href":"https://github.com/NSLS-II/bluesky/pull/1076#discussion_r241179317"},"pull_request":{"href":"https://api.github.com/repos/NSLS-II/bluesky/pulls/1076"}}},"pull_request":{"url":"https://api.github.com/repos/NSLS-II/bluesky/pulls/1076","id":205847185,"node_id":"MDExOlB1bGxSZXF1ZXN0MjA1ODQ3MTg1","html_url":"https://github.com/NSLS-II/bluesky/pull/1076","diff_url":"https://github.com/NSLS-II/bluesky/pull/1076.diff","patch_url":"https://github.com/NSLS-II/bluesky/pull/1076.patch","issue_url":"https://api.github.com/repos/NSLS-II/bluesky/issues/1076","number":1076,"state":"open","locked":false,"title":"Implement new callbacks mechanism","user":{"login":"danielballan","id":2279598,"node_id":"MDQ6VXNlcjIyNzk1OTg=","avatar_url":"https://avatars3.githubusercontent.com/u/2279598?v=4","gravatar_id":"","url":"https://api.github.com/users/danielballan","html_url":"https://github.com/danielballan","followers_url":"https://api.github.com/users/danielballan/followers","following_url":"https://api.github.com/users/danielballan/following{/other_user}","gists_url":"https://api.github.com/users/danielballan/gists{/gist_id}","starred_url":"https://api.github.com/users/danielballan/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/danielballan/subscriptions","organizations_url":"https://api.github.com/users/danielballan/orgs","repos_url":"https://api.github.com/users/danielballan/repos","events_url":"https://api.github.com/users/danielballan/events{/privacy}","received_events_url":"https://api.github.com/users/danielballan/received_events","type":"User","site_admin":false},"body":"**Do not review yet -- this is still a moving target.**","created_at":"2018-08-02T20:09:33Z","updated_at":"2018-12-12T20:47:07Z","closed_at":null,"merged_at":null,"merge_commit_sha":"d05373c736ca62e79980b0fe99fa9bbecbf40fe4","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/NSLS-II/bluesky/pulls/1076/commits","review_comments_url":"https://api.github.com/repos/NSLS-II/bluesky/pulls/1076/comments","review_comment_url":"https://api.github.com/repos/NSLS-II/bluesky/pulls/comments{/number}","comments_url":"https://api.github.com/repos/NSLS-II/bluesky/issues/1076/comments","statuses_url":"https://api.github.com/repos/NSLS-II/bluesky/statuses/f5a4b3664bed01ee695156f5bf3f9e1a5417f0cf","head":{"label":"danielballan:one-run-callbacks","ref":"one-run-callbacks","sha":"f5a4b3664bed01ee695156f5bf3f9e1a5417f0cf","user":{"login":"danielballan","id":2279598,"node_id":"MDQ6VXNlcjIyNzk1OTg=","avatar_url":"https://avatars3.githubusercontent.com/u/2279598?v=4","gravatar_id":"","url":"https://api.github.com/users/danielballan","html_url":"https://github.com/danielballan","followers_url":"https://api.github.com/users/danielballan/followers","following_url":"https://api.github.com/users/danielballan/following{/other_user}","gists_url":"https://api.github.com/users/danielballan/gists{/gist_id}","starred_url":"https://api.github.com/users/danielballan/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/danielballan/subscriptions","organizations_url":"https://api.github.com/users/danielballan/orgs","repos_url":"https://api.github.com/users/danielballan/repos","events_url":"https://api.github.com/users/danielballan/events{/privacy}","received_events_url":"https://api.github.com/users/danielballan/received_events","type":"User","site_admin":false},"repo":{"id":39904738,"node_id":"MDEwOlJlcG9zaXRvcnkzOTkwNDczOA==","name":"bluesky","full_name":"danielballan/bluesky","private":false,"owner":{"login":"danielballan","id":2279598,"node_id":"MDQ6VXNlcjIyNzk1OTg=","avatar_url":"https://avatars3.githubusercontent.com/u/2279598?v=4","gravatar_id":"","url":"https://api.github.com/users/danielballan","html_url":"https://github.com/danielballan","followers_url":"https://api.github.com/users/danielballan/followers","following_url":"https://api.github.com/users/danielballan/following{/other_user}","gists_url":"https://api.github.com/users/danielballan/gists{/gist_id}","starred_url":"https://api.github.com/users/danielballan/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/danielballan/subscriptions","organizations_url":"https://api.github.com/users/danielballan/orgs","repos_url":"https://api.github.com/users/danielballan/repos","events_url":"https://api.github.com/users/danielballan/events{/privacy}","received_events_url":"https://api.github.com/users/danielballan/received_events","type":"User","site_admin":false},"html_url":"https://github.com/danielballan/bluesky","description":"a data collection interface","fork":true,"url":"https://api.github.com/repos/danielballan/bluesky","forks_url":"https://api.github.com/repos/danielballan/bluesky/forks","keys_url":"https://api.github.com/repos/danielballan/bluesky/keys{/key_id}","collaborators_url":"https://api.github.com/repos/danielballan/bluesky/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/danielballan/bluesky/teams","hooks_url":"https://api.github.com/repos/danielballan/bluesky/hooks","issue_events_url":"https://api.github.com/repos/danielballan/bluesky/issues/events{/number}","events_url":"https://api.github.com/repos/danielballan/bluesky/events","assignees_url":"https://api.github.com/repos/danielballan/bluesky/assignees{/user}","branches_url":"https://api.github.com/repos/danielballan/bluesky/branches{/branch}","tags_url":"https://api.github.com/repos/danielballan/bluesky/tags","blobs_url":"https://api.github.com/repos/danielballan/bluesky/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/danielballan/bluesky/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/danielballan/bluesky/git/refs{/sha}","trees_url":"https://api.github.com/repos/danielballan/bluesky/git/trees{/sha}","statuses_url":"https://api.github.com/repos/danielballan/bluesky/statuses/{sha}","languages_url":"https://api.github.com/repos/danielballan/bluesky/languages","stargazers_url":"https://api.github.com/repos/danielballan/bluesky/stargazers","contributors_url":"https://api.github.com/repos/danielballan/bluesky/contributors","subscribers_url":"https://api.github.com/repos/danielballan/bluesky/subscribers","subscription_url":"https://api.github.com/repos/danielballan/bluesky/subscription","commits_url":"https://api.github.com/repos/danielballan/bluesky/commits{/sha}","git_commits_url":"https://api.github.com/repos/danielballan/bluesky/git/commits{/sha}","comments_url":"https://api.github.com/repos/danielballan/bluesky/comments{/number}","issue_comment_url":"https://api.github.com/repos/danielballan/bluesky/issues/comments{/number}","contents_url":"https://api.github.com/repos/danielballan/bluesky/contents/{+path}","compare_url":"https://api.github.com/repos/danielballan/bluesky/compare/{base}...{head}","merges_url":"https://api.github.com/repos/danielballan/bluesky/merges","archive_url":"https://api.github.com/repos/danielballan/bluesky/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/danielballan/bluesky/downloads","issues_url":"https://api.github.com/repos/danielballan/bluesky/issues{/number}","pulls_url":"https://api.github.com/repos/danielballan/bluesky/pulls{/number}","milestones_url":"https://api.github.com/repos/danielballan/bluesky/milestones{/number}","notifications_url":"https://api.github.com/repos/danielballan/bluesky/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/danielballan/bluesky/labels{/name}","releases_url":"https://api.github.com/repos/danielballan/bluesky/releases{/id}","deployments_url":"https://api.github.com/repos/danielballan/bluesky/deployments","created_at":"2015-07-29T16:42:41Z","updated_at":"2018-06-06T12:17:01Z","pushed_at":"2018-12-12T16:54:35Z","git_url":"git://github.com/danielballan/bluesky.git","ssh_url":"git@github.com:danielballan/bluesky.git","clone_url":"https://github.com/danielballan/bluesky.git","svn_url":"https://github.com/danielballan/bluesky","homepage":"http://danielballan.github.io/bluesky","size":5524,"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":1,"mirror_url":null,"archived":false,"open_issues_count":3,"license":{"key":"other","name":"Other","spdx_id":"NOASSERTION","url":null,"node_id":"MDc6TGljZW5zZTA="},"forks":1,"open_issues":3,"watchers":0,"default_branch":"master"}},"base":{"label":"NSLS-II:master","ref":"master","sha":"7cd0e9ccbf5fe986d326fbac5f1205decc6d862a","user":{"login":"NSLS-II","id":8700262,"node_id":"MDEyOk9yZ2FuaXphdGlvbjg3MDAyNjI=","avatar_url":"https://avatars3.githubusercontent.com/u/8700262?v=4","gravatar_id":"","url":"https://api.github.com/users/NSLS-II","html_url":"https://github.com/NSLS-II","followers_url":"https://api.github.com/users/NSLS-II/followers","following_url":"https://api.github.com/users/NSLS-II/following{/other_user}","gists_url":"https://api.github.com/users/NSLS-II/gists{/gist_id}","starred_url":"https://api.github.com/users/NSLS-II/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/NSLS-II/subscriptions","organizations_url":"https://api.github.com/users/NSLS-II/orgs","repos_url":"https://api.github.com/users/NSLS-II/repos","events_url":"https://api.github.com/users/NSLS-II/events{/privacy}","received_events_url":"https://api.github.com/users/NSLS-II/received_events","type":"Organization","site_admin":false},"repo":{"id":36754446,"node_id":"MDEwOlJlcG9zaXRvcnkzNjc1NDQ0Ng==","name":"bluesky","full_name":"NSLS-II/bluesky","private":false,"owner":{"login":"NSLS-II","id":8700262,"node_id":"MDEyOk9yZ2FuaXphdGlvbjg3MDAyNjI=","avatar_url":"https://avatars3.githubusercontent.com/u/8700262?v=4","gravatar_id":"","url":"https://api.github.com/users/NSLS-II","html_url":"https://github.com/NSLS-II","followers_url":"https://api.github.com/users/NSLS-II/followers","following_url":"https://api.github.com/users/NSLS-II/following{/other_user}","gists_url":"https://api.github.com/users/NSLS-II/gists{/gist_id}","starred_url":"https://api.github.com/users/NSLS-II/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/NSLS-II/subscriptions","organizations_url":"https://api.github.com/users/NSLS-II/orgs","repos_url":"https://api.github.com/users/NSLS-II/repos","events_url":"https://api.github.com/users/NSLS-II/events{/privacy}","received_events_url":"https://api.github.com/users/NSLS-II/received_events","type":"Organization","site_admin":false},"html_url":"https://github.com/NSLS-II/bluesky","description":"a data collection interface","fork":false,"url":"https://api.github.com/repos/NSLS-II/bluesky","forks_url":"https://api.github.com/repos/NSLS-II/bluesky/forks","keys_url":"https://api.github.com/repos/NSLS-II/bluesky/keys{/key_id}","collaborators_url":"https://api.github.com/repos/NSLS-II/bluesky/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/NSLS-II/bluesky/teams","hooks_url":"https://api.github.com/repos/NSLS-II/bluesky/hooks","issue_events_url":"https://api.github.com/repos/NSLS-II/bluesky/issues/events{/number}","events_url":"https://api.github.com/repos/NSLS-II/bluesky/events","assignees_url":"https://api.github.com/repos/NSLS-II/bluesky/assignees{/user}","branches_url":"https://api.github.com/repos/NSLS-II/bluesky/branches{/branch}","tags_url":"https://api.github.com/repos/NSLS-II/bluesky/tags","blobs_url":"https://api.github.com/repos/NSLS-II/bluesky/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/NSLS-II/bluesky/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/NSLS-II/bluesky/git/refs{/sha}","trees_url":"https://api.github.com/repos/NSLS-II/bluesky/git/trees{/sha}","statuses_url":"https://api.github.com/repos/NSLS-II/bluesky/statuses/{sha}","languages_url":"https://api.github.com/repos/NSLS-II/bluesky/languages","stargazers_url":"https://api.github.com/repos/NSLS-II/bluesky/stargazers","contributors_url":"https://api.github.com/repos/NSLS-II/bluesky/contributors","subscribers_url":"https://api.github.com/repos/NSLS-II/bluesky/subscribers","subscription_url":"https://api.github.com/repos/NSLS-II/bluesky/subscription","commits_url":"https://api.github.com/repos/NSLS-II/bluesky/commits{/sha}","git_commits_url":"https://api.github.com/repos/NSLS-II/bluesky/git/commits{/sha}","comments_url":"https://api.github.com/repos/NSLS-II/bluesky/comments{/number}","issue_comment_url":"https://api.github.com/repos/NSLS-II/bluesky/issues/comments{/number}","contents_url":"https://api.github.com/repos/NSLS-II/bluesky/contents/{+path}","compare_url":"https://api.github.com/repos/NSLS-II/bluesky/compare/{base}...{head}","merges_url":"https://api.github.com/repos/NSLS-II/bluesky/merges","archive_url":"https://api.github.com/repos/NSLS-II/bluesky/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/NSLS-II/bluesky/downloads","issues_url":"https://api.github.com/repos/NSLS-II/bluesky/issues{/number}","pulls_url":"https://api.github.com/repos/NSLS-II/bluesky/pulls{/number}","milestones_url":"https://api.github.com/repos/NSLS-II/bluesky/milestones{/number}","notifications_url":"https://api.github.com/repos/NSLS-II/bluesky/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/NSLS-II/bluesky/labels{/name}","releases_url":"https://api.github.com/repos/NSLS-II/bluesky/releases{/id}","deployments_url":"https://api.github.com/repos/NSLS-II/bluesky/deployments","created_at":"2015-06-02T18:50:18Z","updated_at":"2018-12-10T18:35:54Z","pushed_at":"2018-12-12T17:50:17Z","git_url":"git://github.com/NSLS-II/bluesky.git","ssh_url":"git@github.com:NSLS-II/bluesky.git","clone_url":"https://github.com/NSLS-II/bluesky.git","svn_url":"https://github.com/NSLS-II/bluesky","homepage":"http://nsls-ii.github.io/bluesky","size":4563,"stargazers_count":36,"watchers_count":36,"language":"Python","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":34,"mirror_url":null,"archived":false,"open_issues_count":138,"license":{"key":"other","name":"Other","spdx_id":"NOASSERTION","url":null,"node_id":"MDc6TGljZW5zZTA="},"forks":34,"open_issues":138,"watchers":36,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/NSLS-II/bluesky/pulls/1076"},"html":{"href":"https://github.com/NSLS-II/bluesky/pull/1076"},"issue":{"href":"https://api.github.com/repos/NSLS-II/bluesky/issues/1076"},"comments":{"href":"https://api.github.com/repos/NSLS-II/bluesky/issues/1076/comments"},"review_comments":{"href":"https://api.github.com/repos/NSLS-II/bluesky/pulls/1076/comments"},"review_comment":{"href":"https://api.github.com/repos/NSLS-II/bluesky/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/NSLS-II/bluesky/pulls/1076/commits"},"statuses":{"href":"https://api.github.com/repos/NSLS-II/bluesky/statuses/f5a4b3664bed01ee695156f5bf3f9e1a5417f0cf"}},"author_association":"CONTRIBUTOR"}}
{"actor":{"display_login":"CJ-Wright"}}