Coverage for haystack/components/converters/txt.py: 91%
34 statements
« prev ^ index » next coverage.py v7.15.4, created at 2026-08-21 13:53 +0000
« prev ^ index » next coverage.py v7.15.4, created at 2026-08-21 13:53 +0000
1# SPDX-FileCopyrightText: 2022-present deepset GmbH <info@deepset.ai>
2#
3# SPDX-License-Identifier: Apache-2.0
5import os
6from pathlib import Path
7from typing import Any
9from haystack import Document, component, logging
10from haystack.components.converters.utils import get_bytestream_from_source, normalize_metadata
11from haystack.dataclasses import ByteStream
13logger = logging.getLogger(__name__)
16@component
17class TextFileToDocument:
18 """
19 Converts text files to documents your pipeline can query.
21 By default, it uses UTF-8 encoding when converting files but
22 you can also set custom encoding.
23 It can attach metadata to the resulting documents.
25 ### Usage example
27 ```python
28 from haystack.components.converters.txt import TextFileToDocument
30 converter = TextFileToDocument()
31 results = converter.run(sources=["test/test_files/txt/doc_1.txt"])
32 documents = results["documents"]
34 print(documents[0].content)
35 # >> 'This is the content from the txt file.'
36 ```
37 """
39 def __init__(self, encoding: str = "utf-8", store_full_path: bool = False) -> None:
40 """
41 Creates a TextFileToDocument component.
43 :param encoding:
44 The encoding of the text files to convert.
45 If the encoding is specified in the metadata of a source ByteStream,
46 it overrides this value.
47 :param store_full_path:
48 If True, the full path of the file is stored in the metadata of the document.
49 If False, only the file name is stored.
50 """
51 self.encoding = encoding
52 self.store_full_path = store_full_path
54 @component.output_types(documents=list[Document])
55 def run(
56 self, sources: list[str | Path | ByteStream], meta: dict[str, Any] | list[dict[str, Any]] | None = None
57 ) -> dict[str, list[Document]]:
58 """
59 Converts text files to documents.
61 :param sources:
62 List of text file paths or ByteStream objects to convert.
63 :param meta:
64 Optional metadata to attach to the documents.
65 This value can be a list of dictionaries or a single dictionary.
66 If it's a single dictionary, its content is added to the metadata of all produced documents.
67 If it's a list, its length must match the number of sources as they're zipped together.
68 For ByteStream objects, their `meta` is added to the output documents.
70 :returns:
71 A dictionary with the following keys:
72 - `documents`: A list of converted documents.
73 """
74 documents = []
76 meta_list = normalize_metadata(meta, sources_count=len(sources))
78 for source, metadata in zip(sources, meta_list, strict=True):
79 try:
80 bytestream = get_bytestream_from_source(source)
81 except Exception as e:
82 logger.warning("Could not read {source}. Skipping it. Error: {error}", source=source, error=e)
83 continue
84 try:
85 encoding = bytestream.meta.get("encoding", self.encoding)
86 text = bytestream.data.decode(encoding)
87 except Exception as e:
88 logger.warning(
89 "Could not convert file {source}. Skipping it. Error message: {error}", source=source, error=e
90 )
91 continue
93 merged_metadata = {**bytestream.meta, **metadata}
95 if not self.store_full_path and (file_path := bytestream.meta.get("file_path")):
96 merged_metadata["file_path"] = os.path.basename(file_path)
97 document = Document(content=text, meta=merged_metadata)
98 documents.append(document)
100 return {"documents": documents}