code: def add_data_file(self, from_fp, timestamp=None, content_type=None):
          # type: (IO, Optional[datetime.datetime], Optional[str]) -> Text
          
          self.self_check()
          tmp_dir, tmp_prefix = os.path.split(self.temp_prefix)
          with tempfile.NamedTemporaryFile(
                  prefix=tmp_prefix, dir=tmp_dir, delete=False) as tmp:
              checksum = checksum_copy(from_fp, tmp)
  
          # Calculate hash-based file path
          folder = os.path.join(self.folder, DATA, checksum[0:2])
          path = os.path.join(folder, checksum)
          # os.rename assumed safe, as our temp file should
          # be in same file system as our temp folder
          if not os.path.isdir(folder):
              os.makedirs(folder)
          os.rename(tmp.name, path)
  
          # Relative posix path
          # (to avoid \ on Windows)
          rel_path = _posix_path(os.path.relpath(path, self.folder))
  
          # Register in bagit checksum
          if Hasher == hashlib.sha1:
              self._add_to_bagit(rel_path, sha1=checksum)
          else:
              _logger.warning(
                  u"[provenance] Unknown hash method %s for bagit manifest",
                  Hasher)
              # Inefficient, bagit support need to checksum again
              self._add_to_bagit(rel_path)
          _logger.debug(u"[provenance] Added data file %s", path)
          if timestamp is not None:
              self._file_provenance[rel_path] = self._self_made(timestamp)
          _logger.debug(u"[provenance] Relative path for data file %s", rel_path)
  
          if content_type is not None:
              self._content_types[rel_path] = content_type
          return rel_path
docs: Copy inputs to data/ folder.