docs: def hydrate_size(data, force=False):
      """Add file and dir sizes.
  
      Add sizes to ``basic:file:``, ``list:basic:file``, ``basic:dir:``
      and ``list:basic:dir:`` fields.
  
      ``force`` parameter is used to recompute file sizes also on objects
      that already have these values, e.g. in migrations.
      """
      from .data import Data  # prevent circular import
  
      def get_dir_size(path):
          """Get directory size."""
          total_size = 0
          for dirpath, _, filenames in os.walk(path):
              for file_name in filenames:
                  file_path = os.path.join(dirpath, file_name)
                  if not os.path.isfile(file_path):  # Skip all "not normal" files (links, ...)
                      continue
                  total_size += os.path.getsize(file_path)
          return total_size
  
      def get_refs_size(obj, obj_path):
          """Calculate size of all references of ``obj``.
  
          :param dict obj: Data object's output field (of type file/dir).
          :param str obj_path: Path to ``obj``.
          """
          total_size = 0
          for ref in obj.get('refs', []):
              ref_path = data.location.get_path(filename=ref)
              if ref_path in obj_path:
                  # It is a common case that ``obj['file']`` is also contained in
                  # one of obj['ref']. In that case, we need to make sure that it's
                  # size is not counted twice:
                  continue
              if os.path.isfile(ref_path):
                  total_size += os.path.getsize(ref_path)
              elif os.path.isdir(ref_path):
                  total_size += get_dir_size(ref_path)
  
          return total_size
  
      def add_file_size(obj):
          """Add file size to the basic:file field."""
          if data.status in [Data.STATUS_DONE, Data.STATUS_ERROR] and 'size' in obj and not force:
              return
  
          path = data.location.get_path(filename=obj['file'])
          if not os.path.isfile(path):
              raise ValidationError("Referenced file does not exist ({})".format(path))
  
          obj['size'] = os.path.getsize(path)
          obj['total_size'] = obj['size'] + get_refs_size(obj, path)
  
      def add_dir_size(obj):
          """Add directory size to the basic:dir field."""
          if data.status in [Data.STATUS_DONE, Data.STATUS_ERROR] and 'size' in obj and not force:
              return
  
          path = data.location.get_path(filename=obj['dir'])
          if not os.path.isdir(path):
              raise ValidationError("Referenced dir does not exist ({})".format(path))
  
          obj['size'] = get_dir_size(path)
          obj['total_size'] = obj['size'] + get_refs_size(obj, path)
  
      data_size = 0
      for field_schema, fields in iterate_fields(data.output, data.process.output_schema):
          name = field_schema['name']
          value = fields[name]
          if 'type' in field_schema:
              if field_schema['type'].startswith('basic:file:'):
                  add_file_size(value)
                  data_size += value.get('total_size', 0)
              elif field_schema['type'].startswith('list:basic:file:'):
                  for obj in value:
                      add_file_size(obj)
                      data_size += obj.get('total_size', 0)
              elif field_schema['type'].startswith('basic:dir:'):
                  add_dir_size(value)
                  data_size += value.get('total_size', 0)
              elif field_schema['type'].startswith('list:basic:dir:'):
                  for obj in value:
                      add_dir_size(obj)
                      data_size += obj.get('total_size', 0)
  
      data.size = data_size