{"action":"created","issue":{"url":"https://api.github.com/repos/ipython/ipython/issues/7603","labels_url":"https://api.github.com/repos/ipython/ipython/issues/7603/labels{/name}","comments_url":"https://api.github.com/repos/ipython/ipython/issues/7603/comments","events_url":"https://api.github.com/repos/ipython/ipython/issues/7603/events","html_url":"https://github.com/ipython/ipython/pull/7603","id":55557036,"number":7603,"title":"Early validation hook","user":{"login":"SylvainCorlay","id":2397974,"avatar_url":"https://avatars.githubusercontent.com/u/2397974?v=3","gravatar_id":"","url":"https://api.github.com/users/SylvainCorlay","html_url":"https://github.com/SylvainCorlay","followers_url":"https://api.github.com/users/SylvainCorlay/followers","following_url":"https://api.github.com/users/SylvainCorlay/following{/other_user}","gists_url":"https://api.github.com/users/SylvainCorlay/gists{/gist_id}","starred_url":"https://api.github.com/users/SylvainCorlay/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/SylvainCorlay/subscriptions","organizations_url":"https://api.github.com/users/SylvainCorlay/orgs","repos_url":"https://api.github.com/users/SylvainCorlay/repos","events_url":"https://api.github.com/users/SylvainCorlay/events{/privacy}","received_events_url":"https://api.github.com/users/SylvainCorlay/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/ipython/ipython/labels/api-review","name":"api-review","color":"fef2c0"},{"url":"https://api.github.com/repos/ipython/ipython/labels/needs-review","name":"needs-review","color":"bfe5bf"}],"state":"open","locked":false,"assignee":null,"milestone":{"url":"https://api.github.com/repos/ipython/ipython/milestones/21","labels_url":"https://api.github.com/repos/ipython/ipython/milestones/21/labels","id":811827,"number":21,"title":"4.0","description":"IPython 4.0","creator":{"login":"minrk","id":151929,"avatar_url":"https://avatars.githubusercontent.com/u/151929?v=3","gravatar_id":"","url":"https://api.github.com/users/minrk","html_url":"https://github.com/minrk","followers_url":"https://api.github.com/users/minrk/followers","following_url":"https://api.github.com/users/minrk/following{/other_user}","gists_url":"https://api.github.com/users/minrk/gists{/gist_id}","starred_url":"https://api.github.com/users/minrk/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/minrk/subscriptions","organizations_url":"https://api.github.com/users/minrk/orgs","repos_url":"https://api.github.com/users/minrk/repos","events_url":"https://api.github.com/users/minrk/events{/privacy}","received_events_url":"https://api.github.com/users/minrk/received_events","type":"User","site_admin":false},"open_issues":211,"closed_issues":0,"state":"open","created_at":"2014-10-02T18:55:15Z","updated_at":"2015-02-12T21:56:36Z","due_on":null,"closed_at":null},"comments":15,"created_at":"2015-01-27T00:09:16Z","updated_at":"2015-02-12T23:38:52Z","closed_at":null,"pull_request":{"url":"https://api.github.com/repos/ipython/ipython/pulls/7603","html_url":"https://github.com/ipython/ipython/pull/7603","diff_url":"https://github.com/ipython/ipython/pull/7603.diff","patch_url":"https://github.com/ipython/ipython/pull/7603.patch"},"body":"This allows one to add a validation hook in the traitlet metadata. \r\n\r\nFor example, define a \"Parity\" HasTraits instance:\r\n\r\n<del>\r\n```Python\r\nfrom IPython.utils.traitlets import *\r\n\r\ndef validate(self, value, trait):\r\n    if self.parity == 'even' and value % 2:\r\n        raise TraitError('Expected an even number')\r\n    if self.parity == 'odd' and (value % 2 == 0):\r\n        raise TraitError('Expected an odd number')\r\n    return value\r\n\r\nclass Parity(HasTraits):\r\n    value = Int(0, validate=validate)\r\n    parity = Enum(['odd', 'even'], default_value='even', allow_none=False)\r\n```\r\n</del>\r\n\r\n```python\r\nfrom IPython.utils.traitlets import *\r\n\r\nclass Parity(HasTraits):\r\n    \r\n    value = Int(0)\r\n    parity = Enum(['odd', 'even'], default_value='even', allow_none=False)\r\n    \r\n    def _value_validate(self, value, trait):\r\n        if self.parity == 'even' and value % 2:\r\n            raise TraitError('Expected an even number')\r\n        if self.parity == 'odd' and (value % 2 == 0):\r\n            raise TraitError('Expected an odd number')\r\n        return value \r\n    \r\nu = Parity()\r\n```\r\n\r\n```Python\r\nu = Parity()\r\nu.value = 1 # should raise a TraitError\r\n```\r\n```Python\r\nu.parity = 'odd'\r\nu.value = 1 # OK\r\nu.value = 2 # should raise a TraitError\r\n```\r\n\r\nThis is meant to allow custom attribute validation prior to assignment, for issues such as #6814."},"comment":{"url":"https://api.github.com/repos/ipython/ipython/issues/comments/74177324","html_url":"https://github.com/ipython/ipython/pull/7603#issuecomment-74177324","issue_url":"https://api.github.com/repos/ipython/ipython/issues/7603","id":74177324,"user":{"login":"SylvainCorlay","id":2397974,"avatar_url":"https://avatars.githubusercontent.com/u/2397974?v=3","gravatar_id":"","url":"https://api.github.com/users/SylvainCorlay","html_url":"https://github.com/SylvainCorlay","followers_url":"https://api.github.com/users/SylvainCorlay/followers","following_url":"https://api.github.com/users/SylvainCorlay/following{/other_user}","gists_url":"https://api.github.com/users/SylvainCorlay/gists{/gist_id}","starred_url":"https://api.github.com/users/SylvainCorlay/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/SylvainCorlay/subscriptions","organizations_url":"https://api.github.com/users/SylvainCorlay/orgs","repos_url":"https://api.github.com/users/SylvainCorlay/repos","events_url":"https://api.github.com/users/SylvainCorlay/events{/privacy}","received_events_url":"https://api.github.com/users/SylvainCorlay/received_events","type":"User","site_admin":false},"created_at":"2015-02-12T23:38:52Z","updated_at":"2015-02-12T23:38:52Z","body":"@takluyver do you have any more thoughts on this? "}}