class_docstr: Interact with FTP.
  
  Errors that may occur throughout but should be handled downstream.
  You can specify mode for data transfers in the extra field of your
  connection as ``{"passive": "true"}``.
  
  :param ftp_conn_id: The :ref:`ftp connection id <howto/connection:ftp>`
      reference.
class_docstr_tok: ["Interact","with","FTP",".","Errors","that","may","occur","throughout","but","should","be","handled","downstream",".","You","can","specify","mode","for","data","transfers","in","the","extra","field","of","your","connection","as","``","{","``","passive","''",":","``","true","''","}","``",".",":","param","ftp_conn_id",":","The",":","ref",":","`","ftp","connection","id","<","howto\/connection",":","ftp",">","`","reference","."]
docstr: Transfer the remote file to a local location.
  
  If local_full_path_or_buffer is a string path, the file will be put
  at that location; if it is a file-like buffer, the file will
  be written to the buffer but not closed.
  
  :param remote_full_path: full path to the remote file
  :param local_full_path_or_buffer: full path to the local file or a
      file-like buffer
  :param callback: callback which is called each time a block of data
      is read. if you do not use a callback, these blocks will be written
      to the file or buffer passed in. if you do pass in a callback, note
      that writing to a file or buffer will need to be handled inside the
      callback.
      [default: output_handle.write()]
  :param block_size: file is transferred in chunks of default size 8192
      or as set by user
  
  .. code-block:: python
  
      hook = FTPHook(ftp_conn_id="my_conn")
  
      remote_path = "/path/to/remote/file"
      local_path = "/path/to/local/file"
  
  
      # with a custom callback (in this case displaying progress on each read)
      def print_progress(percent_progress):
          self.log.info("Percent Downloaded: %s%%" % percent_progress)
  
  
      total_downloaded = 0
      total_file_size = hook.get_size(remote_path)
      output_handle = open(local_path, "wb")
  
  
      def write_to_file_with_progress(data):
          total_downloaded += len(data)
          output_handle.write(data)
          percent_progress = (total_downloaded / total_file_size) * 100
          print_progress(percent_progress)
  
  
      hook.retrieve_file(remote_path, None, callback=write_to_file_with_progress)
  
      # without a custom callback data is written to the local_path
      hook.retrieve_file(remote_path, local_path)
docstr_tok: ["Transfer","the","remote","file","to","a","local","location",".","If","local_full_path_or_buffer","is","a","string","path",",","the","file","will","be","put","at","that","location",";","if","it","is","a","file-like","buffer",",","the","file","will","be","written","to","the","buffer","but","not","closed",".",":","param","remote_full_path",":","full","path","to","the","remote","file",":","param","local_full_path_or_buffer",":","full","path","to","the","local","file","or","a","file-like","buffer",":","param","callback",":","callback","which","is","called","each","time","a","block","of","data","is","read",".","if","you","do","not","use","a","callback",",","these","blocks","will","be","written","to","the","file","or","buffer","passed","in",".","if","you","do","pass","in","a","callback",",","note","that","writing","to","a","file","or","buffer","will","need","to","be","handled","inside","the","callback",".","[","default",":","output_handle.write","(",")","]",":","param","block_size",":","file","is","transferred","in","chunks","of","default","size","8192","or","as","set","by","user","..","code-block",":",":","python","hook","=","FTPHook","(","ftp_conn_id=","''","my_conn","''",")","remote_path","=","``","\/path\/to\/remote\/file","''","local_path","=","``","\/path\/to\/local\/file","''","#","with","a","custom","callback","(","in","this","case","displaying","progress","on","each","read",")","def","print_progress","(","percent_progress",")",":","self.log.info","(","``","Percent","Downloaded",":","%","s","%","%","''","%","percent_progress",")","total_downloaded","=","0","total_file_size","=","hook.get_size","(","remote_path",")","output_handle","=","open","(","local_path",",","``","wb","''",")","def","write_to_file_with_progress","(","data",")",":","total_downloaded","+=","len","(","data",")","output_handle.write","(","data",")","percent_progress","=","(","total_downloaded","\/","total_file_size",")","*","100","print_progress","(","percent_progress",")","hook.retrieve_file","(","remote_path",",","None",",","callback=write_to_file_with_progress",")","#","without","a","custom","callback","data","is","written","to","the","local_path","hook.retrieve_file","(","remote_path",",","local_path",")"]
code: def retrieve_file(
      self,
      remote_full_path: str,
      local_full_path_or_buffer: Any,
      callback: Callable | None = None,
      block_size: int = 8192,
  ) -> None:
      """
      Transfer the remote file to a local location.
  
      If local_full_path_or_buffer is a string path, the file will be put
      at that location; if it is a file-like buffer, the file will
      be written to the buffer but not closed.
  
      :param remote_full_path: full path to the remote file
      :param local_full_path_or_buffer: full path to the local file or a
          file-like buffer
      :param callback: callback which is called each time a block of data
          is read. if you do not use a callback, these blocks will be written
          to the file or buffer passed in. if you do pass in a callback, note
          that writing to a file or buffer will need to be handled inside the
          callback.
          [default: output_handle.write()]
      :param block_size: file is transferred in chunks of default size 8192
          or as set by user
  
      .. code-block:: python
  
          hook = FTPHook(ftp_conn_id="my_conn")
  
          remote_path = "/path/to/remote/file"
          local_path = "/path/to/local/file"
  
  
          # with a custom callback (in this case displaying progress on each read)
          def print_progress(percent_progress):
              self.log.info("Percent Downloaded: %s%%" % percent_progress)
  
  
          total_downloaded = 0
          total_file_size = hook.get_size(remote_path)
          output_handle = open(local_path, "wb")
  
  
          def write_to_file_with_progress(data):
              total_downloaded += len(data)
              output_handle.write(data)
              percent_progress = (total_downloaded / total_file_size) * 100
              print_progress(percent_progress)
  
  
          hook.retrieve_file(remote_path, None, callback=write_to_file_with_progress)
  
          # without a custom callback data is written to the local_path
          hook.retrieve_file(remote_path, local_path)
  
      """
      conn = self.get_conn()
      is_path = isinstance(local_full_path_or_buffer, str)
  
      # without a callback, default to writing to a user-provided file or
      # file-like buffer
      if not callback:
          if is_path:
              output_handle = open(local_full_path_or_buffer, "wb")
          else:
              output_handle = local_full_path_or_buffer
  
          callback = output_handle.write
  
      self.log.info("Retrieving file from FTP: %s", remote_full_path)
      conn.retrbinary(f"RETR {remote_full_path}", callback, block_size)
      self.log.info(
          "Finished retrieving file from FTP: %s", remote_full_path
      )
  
      if is_path and output_handle:
          output_handle.close()
  
imports: from __future__ import annotations
  import datetime
  import ftplib
  from typing import Any, Callable
  from airflow.hooks.base import BaseHook
label_desc: Use image node_id 10 for calling the FTPHook obj's underlying member method code with example usage: obj.retrieve_file(remote_full_path, local_full_path_or_buffer, callback, block_size) without return types