1SEP = "/" 2 3 4def _splitnode(nodeid): 5 """Split a nodeid into constituent 'parts'. 6 7 Node IDs are strings, and can be things like: 8 '' 9 'testing/code' 10 'testing/code/test_excinfo.py' 11 'testing/code/test_excinfo.py::TestFormattedExcinfo::()' 12 13 Return values are lists e.g. 14 [] 15 ['testing', 'code'] 16 ['testing', 'code', 'test_excinfo.py'] 17 ['testing', 'code', 'test_excinfo.py', 'TestFormattedExcinfo', '()'] 18 """ 19 if nodeid == '': 20 # If there is no root node at all, return an empty list so the caller's logic can remain sane 21 return [] 22 parts = nodeid.split(SEP) 23 # Replace single last element 'test_foo.py::Bar::()' with multiple elements 'test_foo.py', 'Bar', '()' 24 parts[-1:] = parts[-1].split("::") 25 return parts 26 27 28def ischildnode(baseid, nodeid): 29 """Return True if the nodeid is a child node of the baseid. 30 31 E.g. 'foo/bar::Baz::()' is a child of 'foo', 'foo/bar' and 'foo/bar::Baz', but not of 'foo/blorp' 32 """ 33 base_parts = _splitnode(baseid) 34 node_parts = _splitnode(nodeid) 35 if len(node_parts) < len(base_parts): 36 return False 37 return node_parts[:len(base_parts)] == base_parts 38