docs: def items(self, view=None, prefetch=None, cache=True):
          """ Get list of download items.
  
              @param view: Name of the view.
              @param prefetch: OPtional list of field names to fetch initially.
              @param cache: Cache items for the given view?
          """
          # TODO: Cache should be by hash.
          # Then get the initial data when cache is empty,
          # else get a list of hashes from the view, make a diff
          # to what's in the cache, fetch the rest. Getting the
          # fields for one hash might be done by a special view
          # (filter: $d.hash == hashvalue)
  
          if view is None:
              view = engine.TorrentView(self, "default")
          elif isinstance(view, basestring):
              view = engine.TorrentView(self, self._resolve_viewname(view))
          else:
              view.viewname = self._resolve_viewname(view.viewname)
  
          if not cache or view.viewname not in self._item_cache:
              # Map pyroscope names to rTorrent ones
              if prefetch:
                  prefetch = self.CORE_FIELDS | set((self.PYRO2RT_MAPPING.get(i, i) for i in prefetch))
              else:
                  prefetch = self.PREFETCH_FIELDS
  
              # Fetch items
              items = []
              try:
                  # Prepare multi-call arguments
                  args = ["d.%s%s" % ("" if field.startswith("is_") else "get_", field)
                      for field in prefetch
                  ]
  
                  infohash = view._check_hash_view()
                  if infohash:
                      multi_call = self.open().system.multicall
                      args = [dict(methodName=field.rsplit('=', 1)[0],
                                   params=[infohash] + (field.rsplit('=', 1)[1].split(',') if '=' in field else []))
                              for field in args]
                      raw_items = [[i[0] for i in multi_call(args)]]
                  else:
                      multi_call = self.open().d.multicall
                      args = [view.viewname] + [field if '=' in field else field + '=' for field in args]
                      if view.matcher and int(config.fast_query):
                          pre_filter = matching.unquote_pre_filter(view.matcher.pre_filter())
                          self.LOG.info("!!! pre-filter: {}".format(pre_filter or 'N/A'))
                          if pre_filter:
                              multi_call = self.open().d.multicall.filtered
                              args.insert(1, pre_filter)
                      raw_items = multi_call(*tuple(args))
  
                  ##self.LOG.debug("multicall %r" % (args,))
                  ##import pprint; self.LOG.debug(pprint.pformat(raw_items))
                  self.LOG.debug("Got %d items with %d attributes from %r [%s]" % (
                      len(raw_items), len(prefetch), self.engine_id, multi_call))
  
                  for item in raw_items:
                      items.append(RtorrentItem(self, zip(
                          [self.RT2PYRO_MAPPING.get(i, i) for i in prefetch], item
                      )))
                      yield items[-1]
              except xmlrpc.ERRORS as exc:
                  raise error.EngineError("While getting download items from %r: %s" % (self, exc))
  
              # Everything yielded, store for next iteration
              if cache:
                  self._item_cache[view.viewname] = items
          else:
              # Yield prefetched results
              for item in self._item_cache[view.viewname]:
                  yield item