{"action":"created","comment":{"url":"https://api.github.com/repos/ros/ros_comm/pulls/comments/31559315","id":31559315,"diff_hunk":"@@ -280,50 +280,62 @@ def _rostopic_bw(topic, window_size=-1):\n     # we use a large buffer size as we don't know what sort of messages we're dealing with.\n     # may parameterize this in the future\n     sub = rospy.Subscriber(real_topic, rospy.AnyMsg, rt.callback)\n-    print(\"subscribed to [%s]\"%real_topic)\n+    print(\"subscribed to [%s]\" % real_topic)\n     while not rospy.is_shutdown():\n         _sleep(1.0)\n         rt.print_bw()\n \n-# TODO: port to the version I wrote for rxplot instead as it should be more efficient\n-\n+# code adapted from rqt_plot\n def msgevalgen(pattern):\n     \"\"\"\n-    Generates a function that returns the relevant field (aka 'subtopic') of a Message object\n-    :param pattern: subtopic, e.g. /x. Must have a leading '/' if specified, ``str``\n+    Generates a function that returns the relevant field(s) (aka 'subtopic(s)') of a Message object\n+    :param pattern: subtopic, e.g. /x[2:]/y[:-1]/z, ``str``\n     :returns: function that converts a message into the desired value, ``fn(Message) -> value``\n     \"\"\"\n-    if not pattern or pattern == '/':\n-        return None\n-    assert pattern[0] == '/'\n-    msg_attribute = pattern[1:]\n-\n-    # use slice arguments if present\n-    array_index_or_slice_object = None\n-    index = msg_attribute.find('[')\n-    if index != -1:\n-        if not msg_attribute.endswith(']'):\n-            sys.stderr.write(\"Topic name '%s' contains '[' but does not end with ']'\\n\" % msg_attribute)\n-            return None\n-        index_string = msg_attribute[index + 1:-1]\n-        try:\n-            array_index_or_slice_object = _get_array_index_or_slice_object(index_string)\n-        except AssertionError as e:\n-            sys.stderr.write(\"Topic name '%s' contains invalid slice argument '%s': %s\\n\" % (msg_attribute, index_string, str(e)))\n-            return None\n-        msg_attribute = msg_attribute[:index]\n+    evals = []  # list of (field_name, slice_object) pairs\n+    fields = [f for f in pattern.split('/') if f]\n+    for f in fields:\n+        if '[' in f:\n+            field_name, rest = f.split('[', 1)\n+            rest = rest[:-1]  # slice content, removing closing bracket\n+            try:\n+                array_index_or_slice_object = _get_array_index_or_slice_object(rest)\n+            except AssertionError as e:\n+                print(\"field '%s' has invalid slice argument '%s': %s\"\n+                      % (field_name, rest, str(e)), file=sys.stderr)\n+                return None\n+            evals.append((field_name, array_index_or_slice_object))\n+        else:\n+            evals.append((f, None))\n+\n+    def _msgeval(msg, evals):\n+        for i, (field_name, slice_object) in enumerate(evals):\n+            try: # access field first\n+                msg = getattr(msg, field_name)\n+            except AttributeError:\n+                print(\"no field named %s in %s\" % (field_name, pattern), file=sys.stderr)\n+                return None\n+\n+            if slice_object is not None: # access slice\n+                try:\n+                    msg = msg.__getitem__(slice_object)\n+                except IndexError as e:\n+                    print(\"%s: %s\" % (str(e), pattern), file=sys.stderr)\n+                    return None\n+\n+                # if a list is returned here (i.e. not only a single element accessed),\n+                # we need to recursively call msg_eval() with the rest of evals\n+                # in order to handle nested slices\n+                if isinstance(msg, list):\n+                    rest = evals[i + 1:]\n+                    return [_msgeval(m, rest) for m in msg]\n+        return msg\n \n     def msgeval(msg):\n-        # I will probably replace this with some less beautiful but more efficient\n-        try:\n-            value = _get_nested_attribute(msg, msg_attribute)\n-        except AttributeError as e:\n-            sys.stdout.write(\"no field named [%s]\"%pattern+\"\\n\")\n-            return None\n-        if array_index_or_slice_object is not None:\n-            value = value[array_index_or_slice_object]\n-        return value\n-    return msgeval\n+        return _msgeval(msg, evals)","path":"tools/rostopic/src/rostopic/__init__.py","position":99,"original_position":99,"commit_id":"e3bee0409278488e45a2b95c87b3de774a11daa3","original_commit_id":"4b3cdbca590df537654631d9cede218cb0a428e4","user":{"login":"rhaschke","id":5376030,"avatar_url":"https://avatars.githubusercontent.com/u/5376030?v=3","gravatar_id":"","url":"https://api.github.com/users/rhaschke","html_url":"https://github.com/rhaschke","followers_url":"https://api.github.com/users/rhaschke/followers","following_url":"https://api.github.com/users/rhaschke/following{/other_user}","gists_url":"https://api.github.com/users/rhaschke/gists{/gist_id}","starred_url":"https://api.github.com/users/rhaschke/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rhaschke/subscriptions","organizations_url":"https://api.github.com/users/rhaschke/orgs","repos_url":"https://api.github.com/users/rhaschke/repos","events_url":"https://api.github.com/users/rhaschke/events{/privacy}","received_events_url":"https://api.github.com/users/rhaschke/received_events","type":"User","site_admin":false},"body":"No, it cannot be removed easily. _msgeval() is called recursively with different arguments.\r\nmsgeval() defines the one-arg function to be returned, while _msgeval() is a two-arg function.\r\nProbably I could use a lambda expression to mediate the arguments. But, IMHO, that wouldn't increase readability.","created_at":"2015-06-02T19:08:09Z","updated_at":"2015-06-02T19:08:09Z","html_url":"https://github.com/ros/ros_comm/pull/606#discussion_r31559315","pull_request_url":"https://api.github.com/repos/ros/ros_comm/pulls/606","_links":{"self":{"href":"https://api.github.com/repos/ros/ros_comm/pulls/comments/31559315"},"html":{"href":"https://github.com/ros/ros_comm/pull/606#discussion_r31559315"},"pull_request":{"href":"https://api.github.com/repos/ros/ros_comm/pulls/606"}}},"pull_request":{"url":"https://api.github.com/repos/ros/ros_comm/pulls/606","id":33671919,"html_url":"https://github.com/ros/ros_comm/pull/606","diff_url":"https://github.com/ros/ros_comm/pull/606.diff","patch_url":"https://github.com/ros/ros_comm/pull/606.patch","issue_url":"https://api.github.com/repos/ros/ros_comm/issues/606","number":606,"state":"open","locked":false,"title":"rostopic: handling multiple array index specifications","user":{"login":"rhaschke","id":5376030,"avatar_url":"https://avatars.githubusercontent.com/u/5376030?v=3","gravatar_id":"","url":"https://api.github.com/users/rhaschke","html_url":"https://github.com/rhaschke","followers_url":"https://api.github.com/users/rhaschke/followers","following_url":"https://api.github.com/users/rhaschke/following{/other_user}","gists_url":"https://api.github.com/users/rhaschke/gists{/gist_id}","starred_url":"https://api.github.com/users/rhaschke/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rhaschke/subscriptions","organizations_url":"https://api.github.com/users/rhaschke/orgs","repos_url":"https://api.github.com/users/rhaschke/repos","events_url":"https://api.github.com/users/rhaschke/events{/privacy}","received_events_url":"https://api.github.com/users/rhaschke/received_events","type":"User","site_admin":false},"body":"Please consider this patch that fixes an issue with multiple array index specifications for subfields in rostopic echo. E.g.\r\n- `rostopic echo /tactile_mid_prox/sensors[1]/proximal[1]` failed with\r\n\r\n> Topic name 'sensors[1]/proximal' contains '[' but does not end with ']'\r\n\r\n- `rostopic echo /tactile_mid_prox/sensors[1]/proximal[1]` failed with\r\n\r\n> Topic name 'sensors[1]/proximal[1]' contains invalid slice argument '1]/proximal[1': non-integer array index step '1]/proximal[1'\r\n\r\nThe reason were two issues:\r\n- First, in function `msgevalgen`, it was assumed that there will be only a single index specification. I fixed, that by a) looking for the matching closing bracket (instead of using the whole rest of the string) and b) calling `msgevalgen` recursively on trailing sub fields.\r\n- Second, in function `_rostopic_echo` when extracting the `type_information` for the to-be-displayed values, a second index specification was not expected too, resulting in an attempt to extract the type for `subtype[]` instead of `subtype`. This was easily fixed, dropping the brackets.","created_at":"2015-04-20T14:42:06Z","updated_at":"2015-06-02T19:08:09Z","closed_at":null,"merged_at":null,"merge_commit_sha":"e598db444da9de50996f97cabc539cfbc89b81d3","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/ros/ros_comm/pulls/606/commits","review_comments_url":"https://api.github.com/repos/ros/ros_comm/pulls/606/comments","review_comment_url":"https://api.github.com/repos/ros/ros_comm/pulls/comments{/number}","comments_url":"https://api.github.com/repos/ros/ros_comm/issues/606/comments","statuses_url":"https://api.github.com/repos/ros/ros_comm/statuses/e3bee0409278488e45a2b95c87b3de774a11daa3","head":{"label":"ubi-agni:indigo-devel","ref":"indigo-devel","sha":"e3bee0409278488e45a2b95c87b3de774a11daa3","user":{"login":"ubi-agni","id":7883789,"avatar_url":"https://avatars.githubusercontent.com/u/7883789?v=3","gravatar_id":"","url":"https://api.github.com/users/ubi-agni","html_url":"https://github.com/ubi-agni","followers_url":"https://api.github.com/users/ubi-agni/followers","following_url":"https://api.github.com/users/ubi-agni/following{/other_user}","gists_url":"https://api.github.com/users/ubi-agni/gists{/gist_id}","starred_url":"https://api.github.com/users/ubi-agni/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ubi-agni/subscriptions","organizations_url":"https://api.github.com/users/ubi-agni/orgs","repos_url":"https://api.github.com/users/ubi-agni/repos","events_url":"https://api.github.com/users/ubi-agni/events{/privacy}","received_events_url":"https://api.github.com/users/ubi-agni/received_events","type":"Organization","site_admin":false},"repo":{"id":34263661,"name":"ros_comm","full_name":"ubi-agni/ros_comm","owner":{"login":"ubi-agni","id":7883789,"avatar_url":"https://avatars.githubusercontent.com/u/7883789?v=3","gravatar_id":"","url":"https://api.github.com/users/ubi-agni","html_url":"https://github.com/ubi-agni","followers_url":"https://api.github.com/users/ubi-agni/followers","following_url":"https://api.github.com/users/ubi-agni/following{/other_user}","gists_url":"https://api.github.com/users/ubi-agni/gists{/gist_id}","starred_url":"https://api.github.com/users/ubi-agni/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ubi-agni/subscriptions","organizations_url":"https://api.github.com/users/ubi-agni/orgs","repos_url":"https://api.github.com/users/ubi-agni/repos","events_url":"https://api.github.com/users/ubi-agni/events{/privacy}","received_events_url":"https://api.github.com/users/ubi-agni/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/ubi-agni/ros_comm","description":"ROS communications-related packages, including core client libraries (roscpp, rospy, roslisp) and graph introspection tools (rostopic, rosnode, rosservice, rosparam).","fork":true,"url":"https://api.github.com/repos/ubi-agni/ros_comm","forks_url":"https://api.github.com/repos/ubi-agni/ros_comm/forks","keys_url":"https://api.github.com/repos/ubi-agni/ros_comm/keys{/key_id}","collaborators_url":"https://api.github.com/repos/ubi-agni/ros_comm/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/ubi-agni/ros_comm/teams","hooks_url":"https://api.github.com/repos/ubi-agni/ros_comm/hooks","issue_events_url":"https://api.github.com/repos/ubi-agni/ros_comm/issues/events{/number}","events_url":"https://api.github.com/repos/ubi-agni/ros_comm/events","assignees_url":"https://api.github.com/repos/ubi-agni/ros_comm/assignees{/user}","branches_url":"https://api.github.com/repos/ubi-agni/ros_comm/branches{/branch}","tags_url":"https://api.github.com/repos/ubi-agni/ros_comm/tags","blobs_url":"https://api.github.com/repos/ubi-agni/ros_comm/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/ubi-agni/ros_comm/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/ubi-agni/ros_comm/git/refs{/sha}","trees_url":"https://api.github.com/repos/ubi-agni/ros_comm/git/trees{/sha}","statuses_url":"https://api.github.com/repos/ubi-agni/ros_comm/statuses/{sha}","languages_url":"https://api.github.com/repos/ubi-agni/ros_comm/languages","stargazers_url":"https://api.github.com/repos/ubi-agni/ros_comm/stargazers","contributors_url":"https://api.github.com/repos/ubi-agni/ros_comm/contributors","subscribers_url":"https://api.github.com/repos/ubi-agni/ros_comm/subscribers","subscription_url":"https://api.github.com/repos/ubi-agni/ros_comm/subscription","commits_url":"https://api.github.com/repos/ubi-agni/ros_comm/commits{/sha}","git_commits_url":"https://api.github.com/repos/ubi-agni/ros_comm/git/commits{/sha}","comments_url":"https://api.github.com/repos/ubi-agni/ros_comm/comments{/number}","issue_comment_url":"https://api.github.com/repos/ubi-agni/ros_comm/issues/comments{/number}","contents_url":"https://api.github.com/repos/ubi-agni/ros_comm/contents/{+path}","compare_url":"https://api.github.com/repos/ubi-agni/ros_comm/compare/{base}...{head}","merges_url":"https://api.github.com/repos/ubi-agni/ros_comm/merges","archive_url":"https://api.github.com/repos/ubi-agni/ros_comm/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/ubi-agni/ros_comm/downloads","issues_url":"https://api.github.com/repos/ubi-agni/ros_comm/issues{/number}","pulls_url":"https://api.github.com/repos/ubi-agni/ros_comm/pulls{/number}","milestones_url":"https://api.github.com/repos/ubi-agni/ros_comm/milestones{/number}","notifications_url":"https://api.github.com/repos/ubi-agni/ros_comm/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/ubi-agni/ros_comm/labels{/name}","releases_url":"https://api.github.com/repos/ubi-agni/ros_comm/releases{/id}","created_at":"2015-04-20T13:59:08Z","updated_at":"2015-04-23T14:43:52Z","pushed_at":"2015-06-02T19:02:43Z","git_url":"git://github.com/ubi-agni/ros_comm.git","ssh_url":"git@github.com:ubi-agni/ros_comm.git","clone_url":"https://github.com/ubi-agni/ros_comm.git","svn_url":"https://github.com/ubi-agni/ros_comm","homepage":"http://wiki.ros.org/ros_comm","size":11612,"stargazers_count":0,"watchers_count":0,"language":"C++","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"indigo-devel"}},"base":{"label":"ros:indigo-devel","ref":"indigo-devel","sha":"bd10f702dcf4c447cc421ed3fd4838f9173afe28","user":{"login":"ros","id":547448,"avatar_url":"https://avatars.githubusercontent.com/u/547448?v=3","gravatar_id":"","url":"https://api.github.com/users/ros","html_url":"https://github.com/ros","followers_url":"https://api.github.com/users/ros/followers","following_url":"https://api.github.com/users/ros/following{/other_user}","gists_url":"https://api.github.com/users/ros/gists{/gist_id}","starred_url":"https://api.github.com/users/ros/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ros/subscriptions","organizations_url":"https://api.github.com/users/ros/orgs","repos_url":"https://api.github.com/users/ros/repos","events_url":"https://api.github.com/users/ros/events{/privacy}","received_events_url":"https://api.github.com/users/ros/received_events","type":"Organization","site_admin":false},"repo":{"id":5474834,"name":"ros_comm","full_name":"ros/ros_comm","owner":{"login":"ros","id":547448,"avatar_url":"https://avatars.githubusercontent.com/u/547448?v=3","gravatar_id":"","url":"https://api.github.com/users/ros","html_url":"https://github.com/ros","followers_url":"https://api.github.com/users/ros/followers","following_url":"https://api.github.com/users/ros/following{/other_user}","gists_url":"https://api.github.com/users/ros/gists{/gist_id}","starred_url":"https://api.github.com/users/ros/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ros/subscriptions","organizations_url":"https://api.github.com/users/ros/orgs","repos_url":"https://api.github.com/users/ros/repos","events_url":"https://api.github.com/users/ros/events{/privacy}","received_events_url":"https://api.github.com/users/ros/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/ros/ros_comm","description":"ROS communications-related packages, including core client libraries (roscpp, rospy, roslisp) and graph introspection tools (rostopic, rosnode, rosservice, rosparam).","fork":false,"url":"https://api.github.com/repos/ros/ros_comm","forks_url":"https://api.github.com/repos/ros/ros_comm/forks","keys_url":"https://api.github.com/repos/ros/ros_comm/keys{/key_id}","collaborators_url":"https://api.github.com/repos/ros/ros_comm/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/ros/ros_comm/teams","hooks_url":"https://api.github.com/repos/ros/ros_comm/hooks","issue_events_url":"https://api.github.com/repos/ros/ros_comm/issues/events{/number}","events_url":"https://api.github.com/repos/ros/ros_comm/events","assignees_url":"https://api.github.com/repos/ros/ros_comm/assignees{/user}","branches_url":"https://api.github.com/repos/ros/ros_comm/branches{/branch}","tags_url":"https://api.github.com/repos/ros/ros_comm/tags","blobs_url":"https://api.github.com/repos/ros/ros_comm/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/ros/ros_comm/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/ros/ros_comm/git/refs{/sha}","trees_url":"https://api.github.com/repos/ros/ros_comm/git/trees{/sha}","statuses_url":"https://api.github.com/repos/ros/ros_comm/statuses/{sha}","languages_url":"https://api.github.com/repos/ros/ros_comm/languages","stargazers_url":"https://api.github.com/repos/ros/ros_comm/stargazers","contributors_url":"https://api.github.com/repos/ros/ros_comm/contributors","subscribers_url":"https://api.github.com/repos/ros/ros_comm/subscribers","subscription_url":"https://api.github.com/repos/ros/ros_comm/subscription","commits_url":"https://api.github.com/repos/ros/ros_comm/commits{/sha}","git_commits_url":"https://api.github.com/repos/ros/ros_comm/git/commits{/sha}","comments_url":"https://api.github.com/repos/ros/ros_comm/comments{/number}","issue_comment_url":"https://api.github.com/repos/ros/ros_comm/issues/comments{/number}","contents_url":"https://api.github.com/repos/ros/ros_comm/contents/{+path}","compare_url":"https://api.github.com/repos/ros/ros_comm/compare/{base}...{head}","merges_url":"https://api.github.com/repos/ros/ros_comm/merges","archive_url":"https://api.github.com/repos/ros/ros_comm/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/ros/ros_comm/downloads","issues_url":"https://api.github.com/repos/ros/ros_comm/issues{/number}","pulls_url":"https://api.github.com/repos/ros/ros_comm/pulls{/number}","milestones_url":"https://api.github.com/repos/ros/ros_comm/milestones{/number}","notifications_url":"https://api.github.com/repos/ros/ros_comm/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/ros/ros_comm/labels{/name}","releases_url":"https://api.github.com/repos/ros/ros_comm/releases{/id}","created_at":"2012-08-19T22:26:34Z","updated_at":"2015-05-22T08:35:15Z","pushed_at":"2015-06-02T19:02:44Z","git_url":"git://github.com/ros/ros_comm.git","ssh_url":"git@github.com:ros/ros_comm.git","clone_url":"https://github.com/ros/ros_comm.git","svn_url":"https://github.com/ros/ros_comm","homepage":"http://wiki.ros.org/ros_comm","size":29668,"stargazers_count":54,"watchers_count":54,"language":"C++","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":152,"mirror_url":null,"open_issues_count":141,"forks":152,"open_issues":141,"watchers":54,"default_branch":"indigo-devel"}},"_links":{"self":{"href":"https://api.github.com/repos/ros/ros_comm/pulls/606"},"html":{"href":"https://github.com/ros/ros_comm/pull/606"},"issue":{"href":"https://api.github.com/repos/ros/ros_comm/issues/606"},"comments":{"href":"https://api.github.com/repos/ros/ros_comm/issues/606/comments"},"review_comments":{"href":"https://api.github.com/repos/ros/ros_comm/pulls/606/comments"},"review_comment":{"href":"https://api.github.com/repos/ros/ros_comm/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/ros/ros_comm/pulls/606/commits"},"statuses":{"href":"https://api.github.com/repos/ros/ros_comm/statuses/e3bee0409278488e45a2b95c87b3de774a11daa3"}}}}