{"action":"created","comment":{"url":"https://api.github.com/repos/nipy/nibabel/pulls/comments/55765753","id":55765753,"diff_hunk":"@@ -0,0 +1,188 @@\n+# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*-\n+# vi: set ft=python sts=4 ts=4 sw=4 et:\n+'''Containers for storing \"elements\" which have both a core data value as well\n+as some additional meta data. When indexing into these containers it is this\n+core value that is returned, which allows for much cleaner and more readable\n+access to nested structures.\n+\n+Each object stored in these containers must have an attribute `value` which\n+provides the core data value for the element. To get the element object itself\n+the `get_elem` method must be used.\n+'''\n+from collections import MutableMapping, MutableSequence\n+\n+from .externals import OrderedDict\n+from .externals.six import iteritems\n+\n+\n+class Elem(object):\n+    '''Basic element type has a `value` and a `meta` attribute.'''\n+    def __init__(self, value, meta=None):\n+        self.value = value\n+        self.meta = {} if meta is None else meta\n+\n+\n+class InvalidElemError(Exception):\n+    '''Raised when trying to add an object without a `value` attribute to an\n+    `ElemDict`.'''\n+    def __init__(self, invalid_val):\n+        self.invalid_val = invalid_val\n+        message = (\"Provided value '%s' of type %s does not have a 'value' \"\n+                   \"attribute\" % (self.invalid_val, type(invalid_val)))\n+        super(InvalidElemError, self).__init__(message)\n+\n+\n+class ElemDict(MutableMapping):\n+    '''Ordered dict-like where each value is an \"element\", which is defined as\n+    any object which has a `value` attribute.\n+\n+    When looking up an item in the dict, it is this `value` attribute that\n+    is returned. To get the element itself use the `get_elem` method.\n+    '''\n+\n+    def __init__(self, *args, **kwargs):\n+        if len(args) > 1:\n+            raise TypeError(\"At most one arg expected, got %d\" % len(args))\n+        self._elems = OrderedDict()\n+        if len(args) == 1:\n+            arg = args[0]\n+            if hasattr(arg, 'get_elem'):\n+                it = ((k, arg.get_elem(k)) for k in arg)\n+            elif hasattr(arg, 'items'):\n+                it = iteritems(arg)\n+            else:\n+                it = arg\n+            for key, val in it:\n+                self[key] = val\n+        for key, val in iteritems(kwargs):\n+            self[key] = val\n+\n+    def __getitem__(self, key):\n+        return self._elems[key].value\n+\n+    def __setitem__(self, key, val):\n+        if not hasattr(val, 'value'):\n+            raise InvalidElemError(val)\n+        self._elems[key] = val\n+\n+    def __delitem__(self, key):\n+        del self._elems[key]\n+\n+    def __iter__(self):\n+        return iter(self._elems)\n+\n+    def __len__(self):\n+        return len(self._elems)\n+\n+    def __repr__(self):\n+        return ('ElemDict(%s)' %\n+                ', '.join(['%r=%r' % x for x in self.items()]))\n+\n+    def update(self, other):\n+        if hasattr(other, 'get_elem'):\n+            for key in other:\n+                self[key] = other.get_elem(key)\n+        else:\n+            for key, elem in iteritems(other):\n+                self[key] = elem\n+\n+    def get_elem(self, key):\n+        return self._elems[key]\n+\n+\n+class ElemList(MutableSequence):\n+    '''A list-like container where each value is an \"element\", which is\n+    defined as any object which has a `value` attribute.\n+\n+    When looking up an item in the list, it is this `value` attribute that\n+    is returned. To get the element itself use the `get_elem` method.\n+    '''\n+    def __init__(self, data=None):\n+        self._elems = list()\n+        if data is not None:","path":"nibabel/elemcont.py","position":102,"original_position":102,"commit_id":"17e893980c655050f43f1916f1128199ecb1761c","original_commit_id":"17e893980c655050f43f1916f1128199ecb1761c","user":{"login":"matthew-brett","id":67612,"avatar_url":"https://avatars.githubusercontent.com/u/67612?v=3","gravatar_id":"","url":"https://api.github.com/users/matthew-brett","html_url":"https://github.com/matthew-brett","followers_url":"https://api.github.com/users/matthew-brett/followers","following_url":"https://api.github.com/users/matthew-brett/following{/other_user}","gists_url":"https://api.github.com/users/matthew-brett/gists{/gist_id}","starred_url":"https://api.github.com/users/matthew-brett/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/matthew-brett/subscriptions","organizations_url":"https://api.github.com/users/matthew-brett/orgs","repos_url":"https://api.github.com/users/matthew-brett/repos","events_url":"https://api.github.com/users/matthew-brett/events{/privacy}","received_events_url":"https://api.github.com/users/matthew-brett/received_events","type":"User","site_admin":false},"body":"Reduce indentation with `if data is None: return`. ","created_at":"2016-03-10T23:09:46Z","updated_at":"2016-03-10T23:09:46Z","html_url":"https://github.com/nipy/nibabel/pull/416#discussion_r55765753","pull_request_url":"https://api.github.com/repos/nipy/nibabel/pulls/416","_links":{"self":{"href":"https://api.github.com/repos/nipy/nibabel/pulls/comments/55765753"},"html":{"href":"https://github.com/nipy/nibabel/pull/416#discussion_r55765753"},"pull_request":{"href":"https://api.github.com/repos/nipy/nibabel/pulls/416"}}},"pull_request":{"url":"https://api.github.com/repos/nipy/nibabel/pulls/416","id":61510120,"html_url":"https://github.com/nipy/nibabel/pull/416","diff_url":"https://github.com/nipy/nibabel/pull/416.diff","patch_url":"https://github.com/nipy/nibabel/pull/416.patch","issue_url":"https://api.github.com/repos/nipy/nibabel/issues/416","number":416,"state":"open","locked":false,"title":"ENH: Add \"element\" containers and make dicom wrappers compatible","user":{"login":"moloney","id":1376566,"avatar_url":"https://avatars.githubusercontent.com/u/1376566?v=3","gravatar_id":"","url":"https://api.github.com/users/moloney","html_url":"https://github.com/moloney","followers_url":"https://api.github.com/users/moloney/followers","following_url":"https://api.github.com/users/moloney/following{/other_user}","gists_url":"https://api.github.com/users/moloney/gists{/gist_id}","starred_url":"https://api.github.com/users/moloney/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/moloney/subscriptions","organizations_url":"https://api.github.com/users/moloney/orgs","repos_url":"https://api.github.com/users/moloney/repos","events_url":"https://api.github.com/users/moloney/events{/privacy}","received_events_url":"https://api.github.com/users/moloney/received_events","type":"User","site_admin":false},"body":"Add two main types: `ElemDict` and `ElemList`. Each can only store\r\nobjects with an attribute `value`. Standard lookups with\r\n`__getitem__` and `get` return just this `value` attribute. To\r\naccess the underlying object, a `get_elem` method is provided.\r\n\r\nAlso updated the DICOM wrappers to provide a `get_elem` method that\r\nreturns the full DICOM element rather than just the value. Added a\r\n`__iter__` method that returns the available DICOM keys.\r\n","created_at":"2016-03-03T04:45:10Z","updated_at":"2016-03-10T23:09:46Z","closed_at":null,"merged_at":null,"merge_commit_sha":"aa51798602cf67f13b8cfdc991c1f7624e563a24","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/nipy/nibabel/pulls/416/commits","review_comments_url":"https://api.github.com/repos/nipy/nibabel/pulls/416/comments","review_comment_url":"https://api.github.com/repos/nipy/nibabel/pulls/comments{/number}","comments_url":"https://api.github.com/repos/nipy/nibabel/issues/416/comments","statuses_url":"https://api.github.com/repos/nipy/nibabel/statuses/17e893980c655050f43f1916f1128199ecb1761c","head":{"label":"moloney:enh-elem-cont","ref":"enh-elem-cont","sha":"17e893980c655050f43f1916f1128199ecb1761c","user":{"login":"moloney","id":1376566,"avatar_url":"https://avatars.githubusercontent.com/u/1376566?v=3","gravatar_id":"","url":"https://api.github.com/users/moloney","html_url":"https://github.com/moloney","followers_url":"https://api.github.com/users/moloney/followers","following_url":"https://api.github.com/users/moloney/following{/other_user}","gists_url":"https://api.github.com/users/moloney/gists{/gist_id}","starred_url":"https://api.github.com/users/moloney/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/moloney/subscriptions","organizations_url":"https://api.github.com/users/moloney/orgs","repos_url":"https://api.github.com/users/moloney/repos","events_url":"https://api.github.com/users/moloney/events{/privacy}","received_events_url":"https://api.github.com/users/moloney/received_events","type":"User","site_admin":false},"repo":{"id":3348774,"name":"nibabel","full_name":"moloney/nibabel","owner":{"login":"moloney","id":1376566,"avatar_url":"https://avatars.githubusercontent.com/u/1376566?v=3","gravatar_id":"","url":"https://api.github.com/users/moloney","html_url":"https://github.com/moloney","followers_url":"https://api.github.com/users/moloney/followers","following_url":"https://api.github.com/users/moloney/following{/other_user}","gists_url":"https://api.github.com/users/moloney/gists{/gist_id}","starred_url":"https://api.github.com/users/moloney/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/moloney/subscriptions","organizations_url":"https://api.github.com/users/moloney/orgs","repos_url":"https://api.github.com/users/moloney/repos","events_url":"https://api.github.com/users/moloney/events{/privacy}","received_events_url":"https://api.github.com/users/moloney/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/moloney/nibabel","description":"Python package to access a cacophony of neuro-imaging file formats","fork":true,"url":"https://api.github.com/repos/moloney/nibabel","forks_url":"https://api.github.com/repos/moloney/nibabel/forks","keys_url":"https://api.github.com/repos/moloney/nibabel/keys{/key_id}","collaborators_url":"https://api.github.com/repos/moloney/nibabel/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/moloney/nibabel/teams","hooks_url":"https://api.github.com/repos/moloney/nibabel/hooks","issue_events_url":"https://api.github.com/repos/moloney/nibabel/issues/events{/number}","events_url":"https://api.github.com/repos/moloney/nibabel/events","assignees_url":"https://api.github.com/repos/moloney/nibabel/assignees{/user}","branches_url":"https://api.github.com/repos/moloney/nibabel/branches{/branch}","tags_url":"https://api.github.com/repos/moloney/nibabel/tags","blobs_url":"https://api.github.com/repos/moloney/nibabel/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/moloney/nibabel/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/moloney/nibabel/git/refs{/sha}","trees_url":"https://api.github.com/repos/moloney/nibabel/git/trees{/sha}","statuses_url":"https://api.github.com/repos/moloney/nibabel/statuses/{sha}","languages_url":"https://api.github.com/repos/moloney/nibabel/languages","stargazers_url":"https://api.github.com/repos/moloney/nibabel/stargazers","contributors_url":"https://api.github.com/repos/moloney/nibabel/contributors","subscribers_url":"https://api.github.com/repos/moloney/nibabel/subscribers","subscription_url":"https://api.github.com/repos/moloney/nibabel/subscription","commits_url":"https://api.github.com/repos/moloney/nibabel/commits{/sha}","git_commits_url":"https://api.github.com/repos/moloney/nibabel/git/commits{/sha}","comments_url":"https://api.github.com/repos/moloney/nibabel/comments{/number}","issue_comment_url":"https://api.github.com/repos/moloney/nibabel/issues/comments{/number}","contents_url":"https://api.github.com/repos/moloney/nibabel/contents/{+path}","compare_url":"https://api.github.com/repos/moloney/nibabel/compare/{base}...{head}","merges_url":"https://api.github.com/repos/moloney/nibabel/merges","archive_url":"https://api.github.com/repos/moloney/nibabel/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/moloney/nibabel/downloads","issues_url":"https://api.github.com/repos/moloney/nibabel/issues{/number}","pulls_url":"https://api.github.com/repos/moloney/nibabel/pulls{/number}","milestones_url":"https://api.github.com/repos/moloney/nibabel/milestones{/number}","notifications_url":"https://api.github.com/repos/moloney/nibabel/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/moloney/nibabel/labels{/name}","releases_url":"https://api.github.com/repos/moloney/nibabel/releases{/id}","deployments_url":"https://api.github.com/repos/moloney/nibabel/deployments","created_at":"2012-02-03T22:07:19Z","updated_at":"2015-04-22T05:48:01Z","pushed_at":"2016-03-06T08:40:55Z","git_url":"git://github.com/moloney/nibabel.git","ssh_url":"git@github.com:moloney/nibabel.git","clone_url":"https://github.com/moloney/nibabel.git","svn_url":"https://github.com/moloney/nibabel","homepage":"http://nipy.org/nibabel/","size":7921,"stargazers_count":1,"watchers_count":1,"language":"Python","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":2,"forks":0,"open_issues":2,"watchers":1,"default_branch":"master"}},"base":{"label":"nipy:master","ref":"master","sha":"5a42cb36f0593b754149f6345ff20d75b8956205","user":{"login":"nipy","id":233707,"avatar_url":"https://avatars.githubusercontent.com/u/233707?v=3","gravatar_id":"","url":"https://api.github.com/users/nipy","html_url":"https://github.com/nipy","followers_url":"https://api.github.com/users/nipy/followers","following_url":"https://api.github.com/users/nipy/following{/other_user}","gists_url":"https://api.github.com/users/nipy/gists{/gist_id}","starred_url":"https://api.github.com/users/nipy/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nipy/subscriptions","organizations_url":"https://api.github.com/users/nipy/orgs","repos_url":"https://api.github.com/users/nipy/repos","events_url":"https://api.github.com/users/nipy/events{/privacy}","received_events_url":"https://api.github.com/users/nipy/received_events","type":"Organization","site_admin":false},"repo":{"id":791352,"name":"nibabel","full_name":"nipy/nibabel","owner":{"login":"nipy","id":233707,"avatar_url":"https://avatars.githubusercontent.com/u/233707?v=3","gravatar_id":"","url":"https://api.github.com/users/nipy","html_url":"https://github.com/nipy","followers_url":"https://api.github.com/users/nipy/followers","following_url":"https://api.github.com/users/nipy/following{/other_user}","gists_url":"https://api.github.com/users/nipy/gists{/gist_id}","starred_url":"https://api.github.com/users/nipy/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nipy/subscriptions","organizations_url":"https://api.github.com/users/nipy/orgs","repos_url":"https://api.github.com/users/nipy/repos","events_url":"https://api.github.com/users/nipy/events{/privacy}","received_events_url":"https://api.github.com/users/nipy/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/nipy/nibabel","description":"Python package to access a cacophony of neuro-imaging file formats","fork":false,"url":"https://api.github.com/repos/nipy/nibabel","forks_url":"https://api.github.com/repos/nipy/nibabel/forks","keys_url":"https://api.github.com/repos/nipy/nibabel/keys{/key_id}","collaborators_url":"https://api.github.com/repos/nipy/nibabel/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/nipy/nibabel/teams","hooks_url":"https://api.github.com/repos/nipy/nibabel/hooks","issue_events_url":"https://api.github.com/repos/nipy/nibabel/issues/events{/number}","events_url":"https://api.github.com/repos/nipy/nibabel/events","assignees_url":"https://api.github.com/repos/nipy/nibabel/assignees{/user}","branches_url":"https://api.github.com/repos/nipy/nibabel/branches{/branch}","tags_url":"https://api.github.com/repos/nipy/nibabel/tags","blobs_url":"https://api.github.com/repos/nipy/nibabel/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/nipy/nibabel/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/nipy/nibabel/git/refs{/sha}","trees_url":"https://api.github.com/repos/nipy/nibabel/git/trees{/sha}","statuses_url":"https://api.github.com/repos/nipy/nibabel/statuses/{sha}","languages_url":"https://api.github.com/repos/nipy/nibabel/languages","stargazers_url":"https://api.github.com/repos/nipy/nibabel/stargazers","contributors_url":"https://api.github.com/repos/nipy/nibabel/contributors","subscribers_url":"https://api.github.com/repos/nipy/nibabel/subscribers","subscription_url":"https://api.github.com/repos/nipy/nibabel/subscription","commits_url":"https://api.github.com/repos/nipy/nibabel/commits{/sha}","git_commits_url":"https://api.github.com/repos/nipy/nibabel/git/commits{/sha}","comments_url":"https://api.github.com/repos/nipy/nibabel/comments{/number}","issue_comment_url":"https://api.github.com/repos/nipy/nibabel/issues/comments{/number}","contents_url":"https://api.github.com/repos/nipy/nibabel/contents/{+path}","compare_url":"https://api.github.com/repos/nipy/nibabel/compare/{base}...{head}","merges_url":"https://api.github.com/repos/nipy/nibabel/merges","archive_url":"https://api.github.com/repos/nipy/nibabel/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/nipy/nibabel/downloads","issues_url":"https://api.github.com/repos/nipy/nibabel/issues{/number}","pulls_url":"https://api.github.com/repos/nipy/nibabel/pulls{/number}","milestones_url":"https://api.github.com/repos/nipy/nibabel/milestones{/number}","notifications_url":"https://api.github.com/repos/nipy/nibabel/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/nipy/nibabel/labels{/name}","releases_url":"https://api.github.com/repos/nipy/nibabel/releases{/id}","deployments_url":"https://api.github.com/repos/nipy/nibabel/deployments","created_at":"2010-07-22T16:28:30Z","updated_at":"2016-03-04T04:54:44Z","pushed_at":"2016-03-07T21:25:32Z","git_url":"git://github.com/nipy/nibabel.git","ssh_url":"git@github.com:nipy/nibabel.git","clone_url":"https://github.com/nipy/nibabel.git","svn_url":"https://github.com/nipy/nibabel","homepage":"http://nipy.org/nibabel/","size":19944,"stargazers_count":102,"watchers_count":102,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":103,"mirror_url":null,"open_issues_count":62,"forks":103,"open_issues":62,"watchers":102,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/nipy/nibabel/pulls/416"},"html":{"href":"https://github.com/nipy/nibabel/pull/416"},"issue":{"href":"https://api.github.com/repos/nipy/nibabel/issues/416"},"comments":{"href":"https://api.github.com/repos/nipy/nibabel/issues/416/comments"},"review_comments":{"href":"https://api.github.com/repos/nipy/nibabel/pulls/416/comments"},"review_comment":{"href":"https://api.github.com/repos/nipy/nibabel/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/nipy/nibabel/pulls/416/commits"},"statuses":{"href":"https://api.github.com/repos/nipy/nibabel/statuses/17e893980c655050f43f1916f1128199ecb1761c"}}}}