docs: def csv(self, sep=',', branches=None,
              include_labels=True, limit=None,
              stream=None):
          """
          Print csv representation of tree only including branches
          of basic types (no objects, vectors, etc..)
  
          Parameters
          ----------
          sep : str, optional (default=',')
              The delimiter used to separate columns
  
          branches : list, optional (default=None)
              Only include these branches in the CSV output. If None, then all
              basic types will be included.
  
          include_labels : bool, optional (default=True)
              Include a first row of branch names labelling each column.
  
          limit : int, optional (default=None)
              Only include up to a maximum of ``limit`` rows in the CSV.
  
          stream : file, (default=None)
              Stream to write the CSV output on. By default the CSV will be
              written to ``sys.stdout``.
          """
          supported_types = (Scalar, Array, stl.string)
          if stream is None:
              stream = sys.stdout
          if not self._buffer:
              self.create_buffer(ignore_unsupported=True)
          if branches is None:
              branchdict = OrderedDict([
                  (name, self._buffer[name])
                  for name in self.iterbranchnames()
                  if isinstance(self._buffer[name], supported_types)])
          else:
              branchdict = OrderedDict()
              for name in branches:
                  if not isinstance(self._buffer[name], supported_types):
                      raise TypeError(
                          "selected branch `{0}` "
                          "is not a scalar or array type".format(name))
                  branchdict[name] = self._buffer[name]
          if not branchdict:
              raise RuntimeError(
                  "no branches selected or no "
                  "branches of scalar or array types exist")
          if include_labels:
              # expand array types to f[0],f[1],f[2],...
              print(sep.join(
                  name if isinstance(value, (Scalar, BaseChar, stl.string))
                      else sep.join('{0}[{1:d}]'.format(name, idx)
                                    for idx in range(len(value)))
                          for name, value in branchdict.items()),
                  file=stream)
          # even though 'entry' is not used, enumerate or simply iterating over
          # self is required to update the buffer with the new branch values at
          # each tree entry.
          for i, entry in enumerate(self):
              line = []
              for value in branchdict.values():
                  if isinstance(value, (Scalar, BaseChar)):
                      token = str(value.value)
                  elif isinstance(value, stl.string):
                      token = str(value)
                  else:
                      token = sep.join(map(str, value))
                  line.append(token)
              print(sep.join(line), file=stream)
              if limit is not None and i + 1 == limit:
                  break