code: def summarize(self):
      source_reports = []
  
      def add_source_reports(transfer_report):
          if isinstance(transfer_report._source_report, SourceReport):
              source_reports.append(transfer_report._source_report)
          else:
              source_reports.extend(transfer_report._source_report)
  
      if isinstance(self._transfer_report, TransferReport):
          total_transfers = 1
          add_source_reports(self._transfer_report)
      else:
          total_transfers = len(self._transfer_report)
          for t in self._transfer_report:
              add_source_reports(t)
  
      total_sources = len(source_reports)
      total_files = sum(sr._files for sr in source_reports)
      total_bytes = sum(sr._bytes for sr in source_reports)
  
      print("Transfer summary:")
      print(f"  Transfers: {total_transfers}")
      print(f"  Sources: {total_sources}")
      print(f"  Files: {total_files}")
      print(f"  Bytes: {humanize.naturalsize(total_bytes)}")
      print(f"  Time: {humanize_timedelta_msecs(self._duration)}")
      assert self._duration is not None
      if self._duration > 0:
          bandwidth = humanize.naturalsize(
              total_bytes / (self._duration / 1000)
          )
          print(f"  Average bandwidth: {bandwidth}/s")
          file_rate = total_files / (self._duration / 1000)
          print(f"  Average file rate: {file_rate:,.1f}/s")
  
      print("Sources:")
      for sr in source_reports:
          print(
              f"  {sr._source}: {sr._files} files, {humanize.naturalsize(sr._bytes)}"
          )
  
imports: from typing import Any, AsyncIterator, Awaitable, Optional, List, Union, Dict, Callable, Tuple
  import os
  import os.path
  import asyncio
  import functools
  import humanize
  from ...utils import retry_transient_errors, url_basename, url_join, bounded_gather2, time_msecs, humanize_timedelta_msecs
  from ..weighted_semaphore import WeightedSemaphore
  from .exceptions import FileAndDirectoryError, UnexpectedEOFError
  from .fs import MultiPartCreate, FileStatus, AsyncFS, FileListEntry
label_desc: Use image node_id 4 for calling the CopyReport obj's underlying member method code with example usage: obj.summarize() without return types