{"action":"created","comment":{"url":"https://api.github.com/repos/hyperspy/hyperspy/pulls/comments/50580030","id":50580030,"diff_hunk":"@@ -269,6 +286,15 @@ def _set_free(self, arg):\n             self.component._update_free_parameters()\n         self.trait_property_changed('free', old_value, self.__free)\n \n+    def _on_twin_update(self, value, twin=None):\n+        if (twin is None or not hasattr(twin, 'events') or\n+                not hasattr(twin.events, 'value_changed')):\n+            self.events.value_changed.trigger(value=value, parameter=self)\n+        else:\n+            with twin.events.value_changed.suppress_callback(\n+                    self._on_twin_update):\n+                self.events.value_changed.trigger(value=value, parameter=self)\n+","path":"hyperspy/component.py","position":89,"original_position":89,"commit_id":"fed34745a2076ad6ab532e5e449b25be900fd71c","original_commit_id":"fed34745a2076ad6ab532e5e449b25be900fd71c","user":{"login":"vidartf","id":510760,"avatar_url":"https://avatars.githubusercontent.com/u/510760?v=3","gravatar_id":"","url":"https://api.github.com/users/vidartf","html_url":"https://github.com/vidartf","followers_url":"https://api.github.com/users/vidartf/followers","following_url":"https://api.github.com/users/vidartf/following{/other_user}","gists_url":"https://api.github.com/users/vidartf/gists{/gist_id}","starred_url":"https://api.github.com/users/vidartf/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/vidartf/subscriptions","organizations_url":"https://api.github.com/users/vidartf/orgs","repos_url":"https://api.github.com/users/vidartf/repos","events_url":"https://api.github.com/users/vidartf/events{/privacy}","received_events_url":"https://api.github.com/users/vidartf/received_events","type":"User","site_admin":false},"body":"I guess it is probably I who wrote this, but I would invert the logic and switch the order of the if/else brackets:\r\n```python\r\nif (twin is not None and hasattr(twin, 'events') and hasattr(twin.events, 'value_changed')):\r\n```","created_at":"2016-01-22T19:32:31Z","updated_at":"2016-01-22T19:32:31Z","html_url":"https://github.com/hyperspy/hyperspy/pull/423#discussion_r50580030","pull_request_url":"https://api.github.com/repos/hyperspy/hyperspy/pulls/423","_links":{"self":{"href":"https://api.github.com/repos/hyperspy/hyperspy/pulls/comments/50580030"},"html":{"href":"https://github.com/hyperspy/hyperspy/pull/423#discussion_r50580030"},"pull_request":{"href":"https://api.github.com/repos/hyperspy/hyperspy/pulls/423"}}},"pull_request":{"url":"https://api.github.com/repos/hyperspy/hyperspy/pulls/423","id":27361434,"html_url":"https://github.com/hyperspy/hyperspy/pull/423","diff_url":"https://github.com/hyperspy/hyperspy/pull/423.diff","patch_url":"https://github.com/hyperspy/hyperspy/pull/423.patch","issue_url":"https://api.github.com/repos/hyperspy/hyperspy/issues/423","number":423,"state":"open","locked":false,"title":"General events implementation","user":{"login":"francisco-dlp","id":989719,"avatar_url":"https://avatars.githubusercontent.com/u/989719?v=3","gravatar_id":"","url":"https://api.github.com/users/francisco-dlp","html_url":"https://github.com/francisco-dlp","followers_url":"https://api.github.com/users/francisco-dlp/followers","following_url":"https://api.github.com/users/francisco-dlp/following{/other_user}","gists_url":"https://api.github.com/users/francisco-dlp/gists{/gist_id}","starred_url":"https://api.github.com/users/francisco-dlp/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/francisco-dlp/subscriptions","organizations_url":"https://api.github.com/users/francisco-dlp/orgs","repos_url":"https://api.github.com/users/francisco-dlp/repos","events_url":"https://api.github.com/users/francisco-dlp/events{/privacy}","received_events_url":"https://api.github.com/users/francisco-dlp/received_events","type":"User","site_admin":false},"body":"At present some HyperSpy objects have a very primitive events implementation that is inconsistent and limiting. Given the increasing interest in implementing interactive features in HyperSpy, the time has come to get a more general event system for it.\r\n\r\nI have considered using a third party solution such as pydispatcher. However, because HyperSpy's main interface is IPython, I think that it'll better to implement our own IPython friendly events. Any opinions on this?\r\n\r\nUsage\r\n--------\r\n\r\n```python\r\n\r\n>>> from hyperspy.events import Event, Events\r\n>>> events = Events()\r\n>>> events.speak = Event()\r\n>>> def say_hi(n):\r\n...         print(\" Hi.\" * n)\r\n...     \r\n>>> def say_bye(n):\r\n...         print(\" Bye.\" * n)\r\n...     \r\n>>> events.speak.connect(say_hi)\r\n>>> events.speak.connect(say_bye)\r\n>>> events.speak.connected\r\nset([<function say_hi at 0x7f062c065758>, <function say_bye at 0x7f062c0656e0>])\r\n>>> events.speak.trigger(3)\r\n Hi. Hi. Hi.\r\n Bye. Bye. Bye.\r\n>>> events.speak.disconnect(say_hi)\r\n>>> events.speak.trigger(1)\r\n Bye.\r\n\r\n```\r\n\r\n\r\n\r\nTODO\r\n--------\r\n- [x] unittests\r\n- [x] docstrings\r\n- [ ] User guide\r\n- [x] Reimplement old events using the new infraestructure.\r\n- [ ] Implement more explicit connection syntax:\r\n```python\r\nindex_changed.connect(f, [\"axis\"]) # pass just the axis kwarg\r\nindex_changed.connect(f) # pass all events\r\nindex_changed.connect(f, {\"axis\" : \"ax\", \"index\": \"idx\"}) # Map the event kwargs to match those in the function\r\nindex_changed.connect(f, []) # don't pass any event\r\nindex_changed.connect(f, \"auto\")\r\n\r\n```\r\n\r\n```\r\n","created_at":"2015-01-14T16:17:29Z","updated_at":"2016-01-22T19:32:32Z","closed_at":null,"merged_at":null,"merge_commit_sha":"2a148a273fb3e41496e45f1b85f87bbdde9a0990","assignee":null,"milestone":{"url":"https://api.github.com/repos/hyperspy/hyperspy/milestones/8","html_url":"https://github.com/hyperspy/hyperspy/milestones/0.9","labels_url":"https://api.github.com/repos/hyperspy/hyperspy/milestones/8/labels","id":856137,"number":8,"title":"0.9","description":"","creator":{"login":"francisco-dlp","id":989719,"avatar_url":"https://avatars.githubusercontent.com/u/989719?v=3","gravatar_id":"","url":"https://api.github.com/users/francisco-dlp","html_url":"https://github.com/francisco-dlp","followers_url":"https://api.github.com/users/francisco-dlp/followers","following_url":"https://api.github.com/users/francisco-dlp/following{/other_user}","gists_url":"https://api.github.com/users/francisco-dlp/gists{/gist_id}","starred_url":"https://api.github.com/users/francisco-dlp/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/francisco-dlp/subscriptions","organizations_url":"https://api.github.com/users/francisco-dlp/orgs","repos_url":"https://api.github.com/users/francisco-dlp/repos","events_url":"https://api.github.com/users/francisco-dlp/events{/privacy}","received_events_url":"https://api.github.com/users/francisco-dlp/received_events","type":"User","site_admin":false},"open_issues":60,"closed_issues":41,"state":"open","created_at":"2014-11-06T15:54:23Z","updated_at":"2016-01-22T18:26:11Z","due_on":null,"closed_at":null},"commits_url":"https://api.github.com/repos/hyperspy/hyperspy/pulls/423/commits","review_comments_url":"https://api.github.com/repos/hyperspy/hyperspy/pulls/423/comments","review_comment_url":"https://api.github.com/repos/hyperspy/hyperspy/pulls/comments{/number}","comments_url":"https://api.github.com/repos/hyperspy/hyperspy/issues/423/comments","statuses_url":"https://api.github.com/repos/hyperspy/hyperspy/statuses/fed34745a2076ad6ab532e5e449b25be900fd71c","head":{"label":"francisco-dlp:NEW_Events","ref":"NEW_Events","sha":"fed34745a2076ad6ab532e5e449b25be900fd71c","user":{"login":"francisco-dlp","id":989719,"avatar_url":"https://avatars.githubusercontent.com/u/989719?v=3","gravatar_id":"","url":"https://api.github.com/users/francisco-dlp","html_url":"https://github.com/francisco-dlp","followers_url":"https://api.github.com/users/francisco-dlp/followers","following_url":"https://api.github.com/users/francisco-dlp/following{/other_user}","gists_url":"https://api.github.com/users/francisco-dlp/gists{/gist_id}","starred_url":"https://api.github.com/users/francisco-dlp/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/francisco-dlp/subscriptions","organizations_url":"https://api.github.com/users/francisco-dlp/orgs","repos_url":"https://api.github.com/users/francisco-dlp/repos","events_url":"https://api.github.com/users/francisco-dlp/events{/privacy}","received_events_url":"https://api.github.com/users/francisco-dlp/received_events","type":"User","site_admin":false},"repo":{"id":10522613,"name":"hyperspy","full_name":"francisco-dlp/hyperspy","owner":{"login":"francisco-dlp","id":989719,"avatar_url":"https://avatars.githubusercontent.com/u/989719?v=3","gravatar_id":"","url":"https://api.github.com/users/francisco-dlp","html_url":"https://github.com/francisco-dlp","followers_url":"https://api.github.com/users/francisco-dlp/followers","following_url":"https://api.github.com/users/francisco-dlp/following{/other_user}","gists_url":"https://api.github.com/users/francisco-dlp/gists{/gist_id}","starred_url":"https://api.github.com/users/francisco-dlp/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/francisco-dlp/subscriptions","organizations_url":"https://api.github.com/users/francisco-dlp/orgs","repos_url":"https://api.github.com/users/francisco-dlp/repos","events_url":"https://api.github.com/users/francisco-dlp/events{/privacy}","received_events_url":"https://api.github.com/users/francisco-dlp/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/francisco-dlp/hyperspy","description":"A toolbox for hyperspectra data analysis","fork":true,"url":"https://api.github.com/repos/francisco-dlp/hyperspy","forks_url":"https://api.github.com/repos/francisco-dlp/hyperspy/forks","keys_url":"https://api.github.com/repos/francisco-dlp/hyperspy/keys{/key_id}","collaborators_url":"https://api.github.com/repos/francisco-dlp/hyperspy/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/francisco-dlp/hyperspy/teams","hooks_url":"https://api.github.com/repos/francisco-dlp/hyperspy/hooks","issue_events_url":"https://api.github.com/repos/francisco-dlp/hyperspy/issues/events{/number}","events_url":"https://api.github.com/repos/francisco-dlp/hyperspy/events","assignees_url":"https://api.github.com/repos/francisco-dlp/hyperspy/assignees{/user}","branches_url":"https://api.github.com/repos/francisco-dlp/hyperspy/branches{/branch}","tags_url":"https://api.github.com/repos/francisco-dlp/hyperspy/tags","blobs_url":"https://api.github.com/repos/francisco-dlp/hyperspy/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/francisco-dlp/hyperspy/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/francisco-dlp/hyperspy/git/refs{/sha}","trees_url":"https://api.github.com/repos/francisco-dlp/hyperspy/git/trees{/sha}","statuses_url":"https://api.github.com/repos/francisco-dlp/hyperspy/statuses/{sha}","languages_url":"https://api.github.com/repos/francisco-dlp/hyperspy/languages","stargazers_url":"https://api.github.com/repos/francisco-dlp/hyperspy/stargazers","contributors_url":"https://api.github.com/repos/francisco-dlp/hyperspy/contributors","subscribers_url":"https://api.github.com/repos/francisco-dlp/hyperspy/subscribers","subscription_url":"https://api.github.com/repos/francisco-dlp/hyperspy/subscription","commits_url":"https://api.github.com/repos/francisco-dlp/hyperspy/commits{/sha}","git_commits_url":"https://api.github.com/repos/francisco-dlp/hyperspy/git/commits{/sha}","comments_url":"https://api.github.com/repos/francisco-dlp/hyperspy/comments{/number}","issue_comment_url":"https://api.github.com/repos/francisco-dlp/hyperspy/issues/comments{/number}","contents_url":"https://api.github.com/repos/francisco-dlp/hyperspy/contents/{+path}","compare_url":"https://api.github.com/repos/francisco-dlp/hyperspy/compare/{base}...{head}","merges_url":"https://api.github.com/repos/francisco-dlp/hyperspy/merges","archive_url":"https://api.github.com/repos/francisco-dlp/hyperspy/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/francisco-dlp/hyperspy/downloads","issues_url":"https://api.github.com/repos/francisco-dlp/hyperspy/issues{/number}","pulls_url":"https://api.github.com/repos/francisco-dlp/hyperspy/pulls{/number}","milestones_url":"https://api.github.com/repos/francisco-dlp/hyperspy/milestones{/number}","notifications_url":"https://api.github.com/repos/francisco-dlp/hyperspy/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/francisco-dlp/hyperspy/labels{/name}","releases_url":"https://api.github.com/repos/francisco-dlp/hyperspy/releases{/id}","deployments_url":"https://api.github.com/repos/francisco-dlp/hyperspy/deployments","created_at":"2013-06-06T09:01:00Z","updated_at":"2015-04-07T09:32:13Z","pushed_at":"2016-01-22T18:56:12Z","git_url":"git://github.com/francisco-dlp/hyperspy.git","ssh_url":"git@github.com:francisco-dlp/hyperspy.git","clone_url":"https://github.com/francisco-dlp/hyperspy.git","svn_url":"https://github.com/francisco-dlp/hyperspy","homepage":"http://www.hyperspy.org","size":72043,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":1,"forks":0,"open_issues":1,"watchers":0,"default_branch":"master"}},"base":{"label":"hyperspy:master","ref":"master","sha":"78caa72cc04994fadf961d1fc2f8e5e17610ccb6","user":{"login":"hyperspy","id":989756,"avatar_url":"https://avatars.githubusercontent.com/u/989756?v=3","gravatar_id":"","url":"https://api.github.com/users/hyperspy","html_url":"https://github.com/hyperspy","followers_url":"https://api.github.com/users/hyperspy/followers","following_url":"https://api.github.com/users/hyperspy/following{/other_user}","gists_url":"https://api.github.com/users/hyperspy/gists{/gist_id}","starred_url":"https://api.github.com/users/hyperspy/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hyperspy/subscriptions","organizations_url":"https://api.github.com/users/hyperspy/orgs","repos_url":"https://api.github.com/users/hyperspy/repos","events_url":"https://api.github.com/users/hyperspy/events{/privacy}","received_events_url":"https://api.github.com/users/hyperspy/received_events","type":"Organization","site_admin":false},"repo":{"id":2233998,"name":"hyperspy","full_name":"hyperspy/hyperspy","owner":{"login":"hyperspy","id":989756,"avatar_url":"https://avatars.githubusercontent.com/u/989756?v=3","gravatar_id":"","url":"https://api.github.com/users/hyperspy","html_url":"https://github.com/hyperspy","followers_url":"https://api.github.com/users/hyperspy/followers","following_url":"https://api.github.com/users/hyperspy/following{/other_user}","gists_url":"https://api.github.com/users/hyperspy/gists{/gist_id}","starred_url":"https://api.github.com/users/hyperspy/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hyperspy/subscriptions","organizations_url":"https://api.github.com/users/hyperspy/orgs","repos_url":"https://api.github.com/users/hyperspy/repos","events_url":"https://api.github.com/users/hyperspy/events{/privacy}","received_events_url":"https://api.github.com/users/hyperspy/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/hyperspy/hyperspy","description":"Multidimensional data analysis","fork":false,"url":"https://api.github.com/repos/hyperspy/hyperspy","forks_url":"https://api.github.com/repos/hyperspy/hyperspy/forks","keys_url":"https://api.github.com/repos/hyperspy/hyperspy/keys{/key_id}","collaborators_url":"https://api.github.com/repos/hyperspy/hyperspy/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/hyperspy/hyperspy/teams","hooks_url":"https://api.github.com/repos/hyperspy/hyperspy/hooks","issue_events_url":"https://api.github.com/repos/hyperspy/hyperspy/issues/events{/number}","events_url":"https://api.github.com/repos/hyperspy/hyperspy/events","assignees_url":"https://api.github.com/repos/hyperspy/hyperspy/assignees{/user}","branches_url":"https://api.github.com/repos/hyperspy/hyperspy/branches{/branch}","tags_url":"https://api.github.com/repos/hyperspy/hyperspy/tags","blobs_url":"https://api.github.com/repos/hyperspy/hyperspy/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/hyperspy/hyperspy/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/hyperspy/hyperspy/git/refs{/sha}","trees_url":"https://api.github.com/repos/hyperspy/hyperspy/git/trees{/sha}","statuses_url":"https://api.github.com/repos/hyperspy/hyperspy/statuses/{sha}","languages_url":"https://api.github.com/repos/hyperspy/hyperspy/languages","stargazers_url":"https://api.github.com/repos/hyperspy/hyperspy/stargazers","contributors_url":"https://api.github.com/repos/hyperspy/hyperspy/contributors","subscribers_url":"https://api.github.com/repos/hyperspy/hyperspy/subscribers","subscription_url":"https://api.github.com/repos/hyperspy/hyperspy/subscription","commits_url":"https://api.github.com/repos/hyperspy/hyperspy/commits{/sha}","git_commits_url":"https://api.github.com/repos/hyperspy/hyperspy/git/commits{/sha}","comments_url":"https://api.github.com/repos/hyperspy/hyperspy/comments{/number}","issue_comment_url":"https://api.github.com/repos/hyperspy/hyperspy/issues/comments{/number}","contents_url":"https://api.github.com/repos/hyperspy/hyperspy/contents/{+path}","compare_url":"https://api.github.com/repos/hyperspy/hyperspy/compare/{base}...{head}","merges_url":"https://api.github.com/repos/hyperspy/hyperspy/merges","archive_url":"https://api.github.com/repos/hyperspy/hyperspy/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/hyperspy/hyperspy/downloads","issues_url":"https://api.github.com/repos/hyperspy/hyperspy/issues{/number}","pulls_url":"https://api.github.com/repos/hyperspy/hyperspy/pulls{/number}","milestones_url":"https://api.github.com/repos/hyperspy/hyperspy/milestones{/number}","notifications_url":"https://api.github.com/repos/hyperspy/hyperspy/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/hyperspy/hyperspy/labels{/name}","releases_url":"https://api.github.com/repos/hyperspy/hyperspy/releases{/id}","deployments_url":"https://api.github.com/repos/hyperspy/hyperspy/deployments","created_at":"2011-08-19T13:14:36Z","updated_at":"2015-12-15T14:25:54Z","pushed_at":"2016-01-22T18:56:13Z","git_url":"git://github.com/hyperspy/hyperspy.git","ssh_url":"git@github.com:hyperspy/hyperspy.git","clone_url":"https://github.com/hyperspy/hyperspy.git","svn_url":"https://github.com/hyperspy/hyperspy","homepage":"http://www.hyperspy.org","size":77457,"stargazers_count":51,"watchers_count":51,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":38,"mirror_url":null,"open_issues_count":148,"forks":38,"open_issues":148,"watchers":51,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/hyperspy/hyperspy/pulls/423"},"html":{"href":"https://github.com/hyperspy/hyperspy/pull/423"},"issue":{"href":"https://api.github.com/repos/hyperspy/hyperspy/issues/423"},"comments":{"href":"https://api.github.com/repos/hyperspy/hyperspy/issues/423/comments"},"review_comments":{"href":"https://api.github.com/repos/hyperspy/hyperspy/pulls/423/comments"},"review_comment":{"href":"https://api.github.com/repos/hyperspy/hyperspy/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/hyperspy/hyperspy/pulls/423/commits"},"statuses":{"href":"https://api.github.com/repos/hyperspy/hyperspy/statuses/fed34745a2076ad6ab532e5e449b25be900fd71c"}}}}