docs: def path_components(path):
      """Convert a path into group and channel name components"""
  
      def yield_components(path):
          # Iterate over each character and the next character
          chars = zip_longest(path, path[1:])
          try:
              # Iterate over components
              while True:
                  c, n = next(chars)
                  if c != '/':
                      raise ValueError("Invalid path, expected \"/\"")
                  elif (n is not None and n != "'"):
                      raise ValueError("Invalid path, expected \"'\"")
                  else:
                      # Consume "'" or raise StopIteration if at the end
                      next(chars)
                  component = []
                  # Iterate over characters in component name
                  while True:
                      c, n = next(chars)
                      if c == "'" and n == "'":
                          component += "'"
                          # Consume second "'"
                          next(chars)
                      elif c == "'":
                          yield "".join(component)
                          break
                      else:
                          component += c
          except StopIteration:
              return
  
      return list(yield_components(path))