class_docstr: Converts PDF files to Document objects.
  It uses a converter that follows the PyPDFConverter protocol to perform the conversion.
  A default text extraction converter is used if no custom converter is provided.
  
  Usage example:
  ```python
  from haystack.components.converters.pypdf import PyPDFToDocument
  
  converter = PyPDFToDocument()
  results = converter.run(sources=["sample.pdf"], meta={"date_added": datetime.now().isoformat()})
  documents = results["documents"]
  print(documents[0].content)
  # 'This is a text from the PDF file.'
  ```
class_docstr_tok: ["Converts","PDF","files","to","Document","objects",".","It","uses","a","converter","that","follows","the","PyPDFConverter","protocol","to","perform","the","conversion",".","A","default","text","extraction","converter","is","used","if","no","custom","converter","is","provided",".","Usage","example",":","``","`","python","from","haystack.components.converters.pypdf","import","PyPDFToDocument","converter","=","PyPDFToDocument","(",")","results","=","converter.run","(","sources=","[","``","sample.pdf","''","]",",","meta=","{","``","date_added","''",":","datetime.now","(",")",".isoformat","(",")","}",")","documents","=","results","[","``","documents","''","]","print","(","documents","[","0","]",".content",")","#","'This","is","a","text","from","the","PDF","file",".","'","``","`"]
docstr: Converts a list of PDF sources into Document objects using the configured converter.
  
  :param sources: A list of PDF data sources, which can be file paths or ByteStream objects.
  :param meta: Optional metadata to attach to the Documents.
    This value can be either a list of dictionaries or a single dictionary.
    If it's a single dictionary, its content is added to the metadata of all produced Documents.
    If it's a list, the length of the list must match the number of sources, because the two lists will be zipped.
    Defaults to `None`.
  :return: A dictionary containing a list of Document objects under the 'documents' key.
docstr_tok: ["Converts","a","list","of","PDF","sources","into","Document","objects","using","the","configured","converter",".",":","param","sources",":","A","list","of","PDF","data","sources",",","which","can","be","file","paths","or","ByteStream","objects",".",":","param","meta",":","Optional","metadata","to","attach","to","the","Documents",".","This","value","can","be","either","a","list","of","dictionaries","or","a","single","dictionary",".","If","it","'s","a","single","dictionary",",","its","content","is","added","to","the","metadata","of","all","produced","Documents",".","If","it","'s","a","list",",","the","length","of","the","list","must","match","the","number","of","sources",",","because","the","two","lists","will","be","zipped",".","Defaults","to","`","None","`",".",":","return",":","A","dictionary","containing","a","list","of","Document","objects","under","the","'documents","'","key","."]
code: def run(
      self,
      sources: List[Union[str, Path, ByteStream]],
      meta: Optional[
          Union[Dict[str, Any], List[Dict[str, Any]]]
      ] = None,
  ):
      """
      Converts a list of PDF sources into Document objects using the configured converter.
  
      :param sources: A list of PDF data sources, which can be file paths or ByteStream objects.
      :param meta: Optional metadata to attach to the Documents.
        This value can be either a list of dictionaries or a single dictionary.
        If it's a single dictionary, its content is added to the metadata of all produced Documents.
        If it's a list, the length of the list must match the number of sources, because the two lists will be zipped.
        Defaults to `None`.
      :return: A dictionary containing a list of Document objects under the 'documents' key.
      """
      documents = []
      meta_list = normalize_metadata(meta, sources_count=len(sources))
  
      for source, metadata in zip(sources, meta_list):
          try:
              bytestream = get_bytestream_from_source(source)
          except Exception as e:
              logger.warning(
                  "Could not read %s. Skipping it. Error: %s", source, e
              )
              continue
          try:
              pdf_reader = PdfReader(io.BytesIO(bytestream.data))
              document = self._converter.convert(pdf_reader)
          except Exception as e:
              logger.warning(
                  "Could not read %s and convert it to Document, skipping. %s",
                  source,
                  e,
              )
              continue
  
          merged_metadata = {**bytestream.meta, **metadata}
          document.meta = merged_metadata
          documents.append(document)
  
      return {"documents": documents}
  
file_path: haystack/haystack/components/converters/pypdf.py
imports: import io
  import logging
  from typing import List, Union, Protocol, Dict, Any, Optional
  from pathlib import Path
  from haystack.dataclasses import ByteStream
  from haystack.lazy_imports import LazyImport
  from haystack import Document, component, default_to_dict
  from haystack.components.converters.utils import get_bytestream_from_source, normalize_metadata
label_desc: Use image node_id 3 for calling the PyPDFToDocument obj's underlying member method code with example usage: obj.run(sources, meta) and returns: dict