| 175 | ## Returns the item at `path`. Supports multiple path components. |
| 176 | # If no item is found, return `None` |
| 177 | def item( self, searchPath ): |
| 178 | strippedPath = searchPath.strip( '/' ) |
| 179 | |
| 180 | # single component path |
| 181 | for path, item in self.__items: |
| 182 | if strippedPath == path.strip( '/' ): |
| 183 | return item |
| 184 | |
| 185 | # multi component path, e.g. `my/item/path` |
| 186 | if '/' in strippedPath: |
| 187 | rootPath, _, childPath = strippedPath.partition( '/' ) |
| 188 | rootConformed = "/{}/".format( rootPath ) |
| 189 | |
| 190 | rootedItems = [] |
| 191 | for path, itemDict in self.items() : |
| 192 | if path.startswith( rootConformed ) : |
| 193 | rootedItems.append( ( path[ len( rootConformed )-1 : ], itemDict ) ) |
| 194 | elif path == rootConformed[:-1] and isinstance( itemDict.subMenu, MenuDefinition ): |
| 195 | # NOTE: subMenu values that are `callable` won't be searched because the definition is not persistent and mutable |
| 196 | rootedItems += itemDict.subMenu.items() |
| 197 | |
| 198 | rootedDef = MenuDefinition( rootedItems ) |
| 199 | if rootedDef.size(): |
| 200 | return rootedDef.item( childPath ) |
| 201 | |
| 202 | |
| 203 | def __repr__( self ) : |