docs: def read_tree_newick(newick):
      '''Read a tree from a Newick string or file
  
      Args:
          ``newick`` (``str``): Either a Newick string or the path to a Newick file (plain-text or gzipped)
  
      Returns:
          ``Tree``: The tree represented by ``newick``. If the Newick file has multiple trees (one per line), a ``list`` of ``Tree`` objects will be returned
      '''
      if not isinstance(newick, str):
          try:
              newick = str(newick)
          except:
              raise TypeError("newick must be a str")
      if newick.lower().endswith('.gz'): # gzipped file
          f = gopen(expanduser(newick)); ts = f.read().decode().strip(); f.close()
      elif isfile(expanduser(newick)): # plain-text file
          f = open(expanduser(newick)); ts = f.read().strip(); f.close()
      else:
          ts = newick.strip()
      lines = ts.splitlines()
      if len(lines) != 1:
          return [read_tree_newick(l) for l in lines]
      try:
          t = Tree(); t.is_rooted = ts.startswith('[&R]')
          if ts[0] == '[':
              ts = ']'.join(ts.split(']')[1:]).strip(); ts = ts.replace(', ',',')
          n = t.root; i = 0
          while i < len(ts):
              if ts[i] == ';':
                  if i != len(ts)-1 or n != t.root:
                      raise RuntimeError(INVALID_NEWICK)
              elif ts[i] == '(':
                  c = Node(); n.add_child(c); n = c
              elif ts[i] == ')':
                  n = n.parent
              elif ts[i] == ',':
                  n = n.parent; c = Node(); n.add_child(c); n = c
              elif ts[i] == ':':
                  i += 1; ls = ''
                  while ts[i] != ',' and ts[i] != ')' and ts[i] != ';':
                      ls += ts[i]; i += 1
                  n.edge_length = float(ls); i -= 1
              else:
                  label = ''
                  while ts[i] != ':' and ts[i] != ',' and ts[i] != ';' and ts[i] != ')':
                      label += ts[i]; i += 1
                  i -= 1; n.label = label
              i += 1
      except Exception as e:
          raise RuntimeError("Failed to parse string as Newick: %s"%ts)
      return t