Skip to content

Commit c4b3726

Browse files
fix: Support reading from S3 (#27)
1 parent 0496ee9 commit c4b3726

4 files changed

Lines changed: 60 additions & 3 deletions

File tree

app/Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ FROM python:3.12-slim AS base
99

1010
# Install poetry, the package manager.
1111
# https://python-poetry.org
12-
RUN pip install --no-cache-dir poetry==1.5
12+
RUN pip install --no-cache-dir --upgrade pip==25.2 poetry==1.5
1313

1414
RUN apt-get update \
1515
# Install security updates

app/src/ingestion/extract_supports.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,15 @@
2828

2929

3030
def extract_from_pdf(pdf_filepath: str) -> Document: # pragma: no cover
31-
if not os.path.exists(pdf_filepath):
32-
raise FileNotFoundError(f"File not found: {pdf_filepath}")
31+
# Check if file exists locally or can be opened via smart_open
32+
file_exists = os.path.exists(pdf_filepath)
33+
if not file_exists:
34+
try:
35+
with smart_open(pdf_filepath, "rb"):
36+
# Just attempt to open, don't read anything
37+
pass
38+
except Exception as err:
39+
raise FileNotFoundError(f"File not found: {pdf_filepath}") from err
3340

3441
# There's also PDFMinerToDocument (for a different pdf extractor) and
3542
# MultiFileConverter (for variety of file types but requires more dependencies)
15.6 KB
Binary file not shown.

app/tests/src/ingestion/test_extract_supports.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1+
import boto3
12
import pytest
23
from haystack import component
34
from haystack.dataclasses import ChatMessage, Document
5+
from moto import mock_s3
46

57
from src.adapters import db
68
from src.common import haystack_utils
@@ -229,3 +231,51 @@ def test_save_to_db(db_session: db.Session):
229231
supports = {support.name: support for support in listing_record.supports}
230232
assert len(supports) == 1
231233
assert supports["Replacement"].description == "Replacement description"
234+
235+
236+
def test_extract_from_pdf_file_not_found():
237+
"""Test that FileNotFoundError is raised when file doesn't exist locally and smart_open fails."""
238+
nonexistent_path = "/path/to/nonexistent/file.pdf"
239+
240+
with pytest.raises(FileNotFoundError, match="File not found: /path/to/nonexistent/file.pdf"):
241+
extract_supports.extract_from_pdf(nonexistent_path)
242+
243+
244+
def test_extract_from_pdf_smart_open_exception():
245+
"""Test that FileNotFoundError is raised when smart_open throws an exception."""
246+
# Test with an invalid S3 URI that will cause smart_open to fail
247+
invalid_s3_uri = "s3://nonexistent-bucket/nonexistent-file.pdf"
248+
249+
with pytest.raises(
250+
FileNotFoundError, match="File not found: s3://nonexistent-bucket/nonexistent-file.pdf"
251+
):
252+
extract_supports.extract_from_pdf(invalid_s3_uri)
253+
254+
255+
@mock_s3
256+
def test_extract_from_pdf_with_s3_file():
257+
# Create mock S3 bucket and upload the sample PDF
258+
bucket_name = "test-bucket"
259+
key = "test-files/SampleBasicNeedsGuide.pdf"
260+
s3_uri = f"s3://{bucket_name}/{key}"
261+
262+
# Set up mock S3
263+
s3_client = boto3.client("s3", region_name="us-east-1")
264+
s3_client.create_bucket(Bucket=bucket_name)
265+
266+
# Read the sample PDF and upload to mock S3
267+
with open("tests/sample_data/SampleBasicNeedsGuide.pdf", "rb") as f:
268+
pdf_content = f.read()
269+
270+
s3_client.put_object(Bucket=bucket_name, Key=key, Body=pdf_content)
271+
272+
# Test extracting from S3 URI
273+
document = extract_supports.extract_from_pdf(s3_uri)
274+
275+
# Verify the document was extracted successfully
276+
assert document is not None
277+
assert document.content is not None
278+
assert len(document.content) > 0
279+
280+
# Verify it contains expected content from the PDF
281+
assert "Hope" in document.content and "Harbor" in document.content

0 commit comments

Comments
 (0)