azure-doc-intelligence-haystack 1.0.0__tar.gz → 1.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (20) hide show
  1. azure_doc_intelligence_haystack-1.2.0/CHANGELOG.md +36 -0
  2. azure_doc_intelligence_haystack-1.0.0/LICENSE → azure_doc_intelligence_haystack-1.2.0/LICENSE.txt +1 -1
  3. {azure_doc_intelligence_haystack-1.0.0 → azure_doc_intelligence_haystack-1.2.0}/PKG-INFO +7 -3
  4. {azure_doc_intelligence_haystack-1.0.0 → azure_doc_intelligence_haystack-1.2.0}/README.md +3 -0
  5. azure_doc_intelligence_haystack-1.2.0/pydoc/config_docusaurus.yml +13 -0
  6. {azure_doc_intelligence_haystack-1.0.0 → azure_doc_intelligence_haystack-1.2.0}/pyproject.toml +9 -5
  7. {azure_doc_intelligence_haystack-1.0.0 → azure_doc_intelligence_haystack-1.2.0}/src/haystack_integrations/components/converters/azure_doc_intelligence/converter.py +11 -7
  8. {azure_doc_intelligence_haystack-1.0.0 → azure_doc_intelligence_haystack-1.2.0}/tests/test_azure_document_intelligence_converter.py +199 -10
  9. azure_doc_intelligence_haystack-1.0.0/pydoc/config_docusaurus.yml +0 -28
  10. azure_doc_intelligence_haystack-1.0.0/src/haystack_integrations/components/__init__.py +0 -3
  11. azure_doc_intelligence_haystack-1.0.0/src/haystack_integrations/components/converters/__init__.py +0 -3
  12. azure_doc_intelligence_haystack-1.0.0/tests/__init__.py +0 -3
  13. {azure_doc_intelligence_haystack-1.0.0 → azure_doc_intelligence_haystack-1.2.0}/.gitignore +0 -0
  14. {azure_doc_intelligence_haystack-1.0.0 → azure_doc_intelligence_haystack-1.2.0}/src/haystack_integrations/components/converters/azure_doc_intelligence/__init__.py +0 -0
  15. {azure_doc_intelligence_haystack-1.0.0 → azure_doc_intelligence_haystack-1.2.0}/src/haystack_integrations/components/converters/py.typed +0 -0
  16. {azure_doc_intelligence_haystack-1.0.0/src/haystack_integrations → azure_doc_intelligence_haystack-1.2.0/tests}/__init__.py +0 -0
  17. {azure_doc_intelligence_haystack-1.0.0 → azure_doc_intelligence_haystack-1.2.0}/tests/test_files/docx/sample.docx +0 -0
  18. {azure_doc_intelligence_haystack-1.0.0 → azure_doc_intelligence_haystack-1.2.0}/tests/test_files/images/sample_text.jpg +0 -0
  19. {azure_doc_intelligence_haystack-1.0.0 → azure_doc_intelligence_haystack-1.2.0}/tests/test_files/pdf/sample_pdf_1.pdf +0 -0
  20. {azure_doc_intelligence_haystack-1.0.0 → azure_doc_intelligence_haystack-1.2.0}/tests/test_files/pdf/sample_pdf_2.pdf +0 -0
@@ -0,0 +1,36 @@
1
+ # Changelog
2
+
3
+ ## [integrations/azure_doc_intelligence-v1.1.0] - 2026-08-17
4
+
5
+ ### 🐛 Bug Fixes
6
+
7
+ - Fix new issues raised by ruff 0.16.0 (#3670)
8
+ - Standardize license files (#3771)
9
+ - Azure Document Intelligence - fix default model (#3769)
10
+
11
+ ### 📚 Documentation
12
+
13
+ - Simplify pydoc configs (#2855)
14
+
15
+ ### 🧪 Testing
16
+
17
+ - Test compatible integrations with python 3.14; update pyproject (#3001)
18
+ - Track test coverage for all integrations (#3065)
19
+ - AzureDocumentIntelligenceConverter - add tests (#3205)
20
+
21
+ ### 🧹 Chores
22
+
23
+ - Remove unused allow-direct-references (#2866)
24
+ - Enable ANN ruff ruleset for azure_doc_intelligence integration (#2981)
25
+ - Enforce ruff docstring rules (D102/D103/D205/D209/D213/D417/D419) in first 10 integrations (#3008)
26
+ - Improve consistency of integrations folder structure (#3430)
27
+ - Re-standardize READMEs (#3768)
28
+
29
+
30
+ ## [integrations/azure_doc_intelligence-v1.0.0] - 2026-01-19
31
+
32
+ ### 🚀 Features
33
+
34
+ - Add azure-doc-intelligence integration (#2717)
35
+
36
+ <!-- generated by git-cliff -->
@@ -186,7 +186,7 @@
186
186
  same "printed page" as the copyright notice for easier
187
187
  identification within third-party archives.
188
188
 
189
- Copyright 2023 deepset GmbH
189
+ Copyright 2023-present deepset GmbH
190
190
 
191
191
  Licensed under the Apache License, Version 2.0 (the "License");
192
192
  you may not use this file except in compliance with the License.
@@ -1,13 +1,13 @@
1
- Metadata-Version: 2.4
1
+ Metadata-Version: 2.5
2
2
  Name: azure-doc-intelligence-haystack
3
- Version: 1.0.0
3
+ Version: 1.2.0
4
4
  Summary: Haystack integration for Azure Document Intelligence
5
5
  Project-URL: Documentation, https://github.com/deepset-ai/haystack-core-integrations/tree/main/integrations/azure_doc_intelligence#readme
6
6
  Project-URL: Issues, https://github.com/deepset-ai/haystack-core-integrations/issues
7
7
  Project-URL: Source, https://github.com/deepset-ai/haystack-core-integrations/tree/main/integrations/azure_doc_intelligence
8
8
  Author-email: deepset GmbH <info@deepset.ai>
9
9
  License-Expression: Apache-2.0
10
- License-File: LICENSE
10
+ License-File: LICENSE.txt
11
11
  Keywords: Azure,Document Converter,Document Intelligence,Haystack,OCR,PDF
12
12
  Classifier: Development Status :: 4 - Beta
13
13
  Classifier: License :: OSI Approved :: Apache Software License
@@ -16,6 +16,7 @@ Classifier: Programming Language :: Python :: 3.10
16
16
  Classifier: Programming Language :: Python :: 3.11
17
17
  Classifier: Programming Language :: Python :: 3.12
18
18
  Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Programming Language :: Python :: 3.14
19
20
  Classifier: Programming Language :: Python :: Implementation :: CPython
20
21
  Requires-Python: >=3.10
21
22
  Requires-Dist: azure-ai-documentintelligence>=1.0.0
@@ -27,6 +28,7 @@ Description-Content-Type: text/markdown
27
28
  [![PyPI - Version](https://img.shields.io/pypi/v/azure-doc-intelligence-haystack.svg)](https://pypi.org/project/azure-doc-intelligence-haystack)
28
29
  [![PyPI - Python Version](https://img.shields.io/pypi/pyversions/azure-doc-intelligence-haystack.svg)](https://pypi.org/project/azure-doc-intelligence-haystack)
29
30
 
31
+ - [Integration page](https://haystack.deepset.ai/integrations/azure-doc-intelligence)
30
32
  - [Changelog](https://github.com/deepset-ai/haystack-core-integrations/blob/main/integrations/azure_doc_intelligence/CHANGELOG.md)
31
33
 
32
34
  ---
@@ -34,3 +36,5 @@ Description-Content-Type: text/markdown
34
36
  ## Contributing
35
37
 
36
38
  Refer to the general [Contribution Guidelines](https://github.com/deepset-ai/haystack-core-integrations/blob/main/CONTRIBUTING.md).
39
+
40
+ To run integration tests locally, you need to export the `AZURE_DI_ENDPOINT` and `AZURE_DI_API_KEY` environment variables.
@@ -3,6 +3,7 @@
3
3
  [![PyPI - Version](https://img.shields.io/pypi/v/azure-doc-intelligence-haystack.svg)](https://pypi.org/project/azure-doc-intelligence-haystack)
4
4
  [![PyPI - Python Version](https://img.shields.io/pypi/pyversions/azure-doc-intelligence-haystack.svg)](https://pypi.org/project/azure-doc-intelligence-haystack)
5
5
 
6
+ - [Integration page](https://haystack.deepset.ai/integrations/azure-doc-intelligence)
6
7
  - [Changelog](https://github.com/deepset-ai/haystack-core-integrations/blob/main/integrations/azure_doc_intelligence/CHANGELOG.md)
7
8
 
8
9
  ---
@@ -10,3 +11,5 @@
10
11
  ## Contributing
11
12
 
12
13
  Refer to the general [Contribution Guidelines](https://github.com/deepset-ai/haystack-core-integrations/blob/main/CONTRIBUTING.md).
14
+
15
+ To run integration tests locally, you need to export the `AZURE_DI_ENDPOINT` and `AZURE_DI_API_KEY` environment variables.
@@ -0,0 +1,13 @@
1
+ loaders:
2
+ - modules:
3
+ - haystack_integrations.components.converters.azure_doc_intelligence.converter
4
+ search_path: [../src]
5
+ processors:
6
+ - type: filter
7
+ documented_only: true
8
+ skip_empty_modules: true
9
+ renderer:
10
+ description: Azure Document Intelligence integration for Haystack
11
+ id: integrations-azure_doc_intelligence
12
+ filename: azure_doc_intelligence.md
13
+ title: Azure Document Intelligence
@@ -28,6 +28,7 @@ classifiers = [
28
28
  "Programming Language :: Python :: 3.11",
29
29
  "Programming Language :: Python :: 3.12",
30
30
  "Programming Language :: Python :: 3.13",
31
+ "Programming Language :: Python :: 3.14",
31
32
  "Programming Language :: Python :: Implementation :: CPython",
32
33
  ]
33
34
  dependencies = [
@@ -56,7 +57,7 @@ installer = "uv"
56
57
  dependencies = ["haystack-pydoc-tools", "ruff"]
57
58
 
58
59
  [tool.hatch.envs.default.scripts]
59
- docs = ["pydoc-markdown pydoc/config_docusaurus.yml"]
60
+ docs = ["haystack-pydoc pydoc/config_docusaurus.yml"]
60
61
  fmt = "ruff check --fix {args}; ruff format {args}"
61
62
  fmt-check = "ruff check {args} && ruff format --check {args}"
62
63
 
@@ -74,7 +75,8 @@ dependencies = [
74
75
  unit = 'pytest -m "not integration" {args:tests}'
75
76
  integration = 'pytest -m "integration" {args:tests}'
76
77
  all = 'pytest {args:tests}'
77
- cov-retry = 'pytest --cov=haystack_integrations --reruns 3 --reruns-delay 30 -x {args:tests}'
78
+ unit-cov-retry = 'pytest --cov=haystack_integrations --reruns 3 --reruns-delay 30 -x -m "not integration" {args:tests}'
79
+ integration-cov-append-retry = 'pytest --cov=haystack_integrations --cov-append --reruns 3 --reruns-delay 30 -x -m "integration" {args:tests}'
78
80
  types = "mypy -p haystack_integrations.components.converters.azure_doc_intelligence {args}"
79
81
 
80
82
  [tool.mypy]
@@ -83,8 +85,6 @@ non_interactive = true
83
85
  check_untyped_defs = true
84
86
  disallow_incomplete_defs = true
85
87
 
86
- [tool.hatch.metadata]
87
- allow-direct-references = true
88
88
 
89
89
  [tool.ruff]
90
90
  line-length = 120
@@ -92,6 +92,7 @@ line-length = 120
92
92
  [tool.ruff.lint]
93
93
  select = [
94
94
  "A",
95
+ "ANN",
95
96
  "ARG",
96
97
  "B",
97
98
  "C",
@@ -117,6 +118,7 @@ select = [
117
118
  "YTT",
118
119
  ]
119
120
  ignore = [
121
+ "ANN401", # Allow Any - used legitimately for dynamic types and SDK boundaries
120
122
  # Allow non-abstract empty methods in abstract base classes
121
123
  "B027",
122
124
  # Allow function calls in argument defaults (common Haystack pattern for Secret.from_env_var)
@@ -133,6 +135,7 @@ ignore = [
133
135
  "PLR0912",
134
136
  "PLR0913",
135
137
  "PLR0915",
138
+ "PLR0917",
136
139
  ]
137
140
  unfixable = [
138
141
  # Don't touch unused imports
@@ -147,11 +150,12 @@ ban-relative-imports = "parents"
147
150
 
148
151
  [tool.ruff.lint.per-file-ignores]
149
152
  # Tests can use magic values, assertions, and relative imports
150
- "tests/**/*" = ["PLR2004", "S101", "TID252"]
153
+ "tests/**/*" = ["PLR2004", "S101", "TID252", "D", "ANN"]
151
154
 
152
155
  [tool.coverage.run]
153
156
  source = ["haystack_integrations"]
154
157
  branch = true
158
+ relative_files = true
155
159
  parallel = false
156
160
 
157
161
  [tool.coverage.report]
@@ -65,9 +65,9 @@ class AzureDocumentIntelligenceConverter:
65
65
  endpoint: str,
66
66
  *,
67
67
  api_key: Secret = Secret.from_env_var("AZURE_DI_API_KEY"),
68
- model_id: str = "prebuilt-document",
68
+ model_id: str = "prebuilt-layout",
69
69
  store_full_path: bool = False,
70
- ):
70
+ ) -> None:
71
71
  """
72
72
  Creates an AzureDocumentIntelligenceConverter component.
73
73
 
@@ -79,9 +79,8 @@ class AzureDocumentIntelligenceConverter:
79
79
  to load from AZURE_DI_API_KEY environment variable.
80
80
  :param model_id:
81
81
  Azure model to use for analysis. Options:
82
- - "prebuilt-document": General document analysis (default)
82
+ - "prebuilt-layout": Layout analysis with table and structure detection (default)
83
83
  - "prebuilt-read": Fast OCR for text extraction
84
- - "prebuilt-layout": Enhanced layout analysis with better table/structure detection
85
84
  - Custom model IDs from your Azure resource
86
85
  :param store_full_path:
87
86
  If True, stores complete file path in metadata.
@@ -93,7 +92,7 @@ class AzureDocumentIntelligenceConverter:
93
92
  self.store_full_path = store_full_path
94
93
  self.client: DocumentIntelligenceClient | None = None
95
94
 
96
- def warm_up(self):
95
+ def warm_up(self) -> None:
97
96
  """
98
97
  Initializes the Azure Document Intelligence client.
99
98
  """
@@ -102,6 +101,12 @@ class AzureDocumentIntelligenceConverter:
102
101
  endpoint=self.endpoint, credential=AzureKeyCredential(self.api_key.resolve_value() or "")
103
102
  )
104
103
 
104
+ def close(self) -> None:
105
+ """Close the Azure Document Intelligence client."""
106
+ if self.client is not None:
107
+ self.client.close()
108
+ self.client = None
109
+
105
110
  @component.output_types(documents=list[Document], raw_azure_response=list[dict])
106
111
  def run(
107
112
  self,
@@ -125,8 +130,7 @@ class AzureDocumentIntelligenceConverter:
125
130
  - `documents`: List of created Documents
126
131
  - `raw_azure_response`: List of raw Azure responses used to create the Documents
127
132
  """
128
- if self.client is None:
129
- self.warm_up()
133
+ self.warm_up()
130
134
 
131
135
  documents = []
132
136
  azure_responses = []
@@ -4,14 +4,35 @@
4
4
 
5
5
  import os
6
6
  from pathlib import Path
7
+ from unittest.mock import MagicMock, patch
7
8
 
8
9
  import pytest
10
+ from haystack.dataclasses import ByteStream
9
11
  from haystack.utils import Secret
10
12
 
11
13
  from haystack_integrations.components.converters.azure_doc_intelligence import AzureDocumentIntelligenceConverter
12
14
 
13
15
 
14
- class TestAzureDocumentIntelligenceConverter:
16
+ def make_mock_analyze_result(content="# Title\n\nBody", pages=("p1",), as_dict_value=None):
17
+ result = MagicMock()
18
+ result.content = content
19
+ result.pages = list(pages) if pages is not None else None
20
+ result.as_dict.return_value = as_dict_value if as_dict_value is not None else {"content": content}
21
+ return result
22
+
23
+
24
+ @pytest.fixture
25
+ def warmed_converter():
26
+ converter = AzureDocumentIntelligenceConverter(
27
+ endpoint="https://test.cognitiveservices.azure.com/",
28
+ api_key=Secret.from_token("test_api_key"),
29
+ )
30
+ converter.client = MagicMock()
31
+ converter.client.begin_analyze_document.return_value.result.return_value = make_mock_analyze_result()
32
+ return converter
33
+
34
+
35
+ class TestAzureDocumentIntelligenceConverterInitSerde:
15
36
  def test_init_default(self):
16
37
  """Test basic initialization with defaults"""
17
38
  converter = AzureDocumentIntelligenceConverter(
@@ -20,28 +41,30 @@ class TestAzureDocumentIntelligenceConverter:
20
41
  )
21
42
 
22
43
  assert converter.endpoint == "https://test.cognitiveservices.azure.com/"
23
- assert converter.model_id == "prebuilt-document"
44
+ assert converter.model_id == "prebuilt-layout"
24
45
  assert converter.store_full_path is False
46
+ assert converter.client is None
25
47
 
26
48
  def test_init_custom_params(self):
27
49
  """Test initialization with custom parameters"""
28
50
  converter = AzureDocumentIntelligenceConverter(
29
51
  endpoint="https://test.cognitiveservices.azure.com/",
30
52
  api_key=Secret.from_token("test_api_key"),
31
- model_id="prebuilt-layout",
53
+ model_id="prebuilt-read",
32
54
  store_full_path=True,
33
55
  )
34
56
 
35
57
  assert converter.endpoint == "https://test.cognitiveservices.azure.com/"
36
- assert converter.model_id == "prebuilt-layout"
58
+ assert converter.model_id == "prebuilt-read"
37
59
  assert converter.store_full_path is True
60
+ assert converter.client is None
38
61
 
39
62
  def test_to_dict(self):
40
63
  """Test serialization with Secret handling"""
41
64
  converter = AzureDocumentIntelligenceConverter(
42
65
  endpoint="https://test.cognitiveservices.azure.com/",
43
66
  api_key=Secret.from_env_var("AZURE_DI_API_KEY"),
44
- model_id="prebuilt-layout",
67
+ model_id="prebuilt-read",
45
68
  store_full_path=True,
46
69
  )
47
70
 
@@ -56,7 +79,7 @@ class TestAzureDocumentIntelligenceConverter:
56
79
  "init_parameters": {
57
80
  "api_key": {"type": "env_var", "env_vars": ["AZURE_DI_API_KEY"], "strict": True},
58
81
  "endpoint": "https://test.cognitiveservices.azure.com/",
59
- "model_id": "prebuilt-layout",
82
+ "model_id": "prebuilt-read",
60
83
  "store_full_path": True,
61
84
  },
62
85
  }
@@ -71,7 +94,7 @@ class TestAzureDocumentIntelligenceConverter:
71
94
  data = converter.to_dict()
72
95
 
73
96
  assert data["init_parameters"]["endpoint"] == "https://test.cognitiveservices.azure.com/"
74
- assert data["init_parameters"]["model_id"] == "prebuilt-document"
97
+ assert data["init_parameters"]["model_id"] == "prebuilt-layout"
75
98
  assert data["init_parameters"]["store_full_path"] is False
76
99
 
77
100
  def test_from_dict(self):
@@ -85,7 +108,7 @@ class TestAzureDocumentIntelligenceConverter:
85
108
  "init_parameters": {
86
109
  "api_key": {"type": "env_var", "env_vars": ["AZURE_DI_API_KEY"], "strict": True},
87
110
  "endpoint": "https://test.cognitiveservices.azure.com/",
88
- "model_id": "prebuilt-layout",
111
+ "model_id": "prebuilt-read",
89
112
  "store_full_path": False,
90
113
  },
91
114
  }
@@ -93,8 +116,174 @@ class TestAzureDocumentIntelligenceConverter:
93
116
  converter = AzureDocumentIntelligenceConverter.from_dict(data)
94
117
 
95
118
  assert converter.endpoint == "https://test.cognitiveservices.azure.com/"
96
- assert converter.model_id == "prebuilt-layout"
119
+ assert converter.model_id == "prebuilt-read"
97
120
  assert converter.store_full_path is False
121
+ assert converter.client is None
122
+
123
+
124
+ class TestComponentLifecycle:
125
+ def test_key_resolved_at_warm_up_not_init(self, monkeypatch):
126
+ monkeypatch.delenv("MISSING_AZURE_DI_API_KEY", raising=False)
127
+ converter = AzureDocumentIntelligenceConverter(
128
+ endpoint="https://test.cognitiveservices.azure.com/",
129
+ api_key=Secret.from_env_var("MISSING_AZURE_DI_API_KEY"),
130
+ )
131
+
132
+ assert converter.client is None
133
+ with pytest.raises(ValueError, match="MISSING_AZURE_DI_API_KEY"):
134
+ converter.warm_up()
135
+
136
+ def test_sync_lifecycle(self):
137
+ converter = AzureDocumentIntelligenceConverter(
138
+ endpoint="https://test.cognitiveservices.azure.com/",
139
+ api_key=Secret.from_token("test_api_key"),
140
+ )
141
+ with patch(
142
+ "haystack_integrations.components.converters.azure_doc_intelligence.converter.DocumentIntelligenceClient"
143
+ ) as mock_client_cls:
144
+ client = mock_client_cls.return_value
145
+ converter.warm_up()
146
+ assert converter.client is client
147
+ converter.close()
148
+ client.close.assert_called_once_with()
149
+ assert converter.client is None
150
+ converter.warm_up()
151
+ assert mock_client_cls.call_count == 2
152
+
153
+ def test_warm_up_is_idempotent(self):
154
+ converter = AzureDocumentIntelligenceConverter(
155
+ endpoint="https://test.cognitiveservices.azure.com/",
156
+ api_key=Secret.from_token("test_api_key"),
157
+ )
158
+ with patch(
159
+ "haystack_integrations.components.converters.azure_doc_intelligence.converter.DocumentIntelligenceClient"
160
+ ) as mock_client_cls:
161
+ converter.warm_up()
162
+ converter.warm_up()
163
+
164
+ mock_client_cls.assert_called_once()
165
+
166
+ def test_close_is_safe_without_warm_up(self):
167
+ converter = AzureDocumentIntelligenceConverter(
168
+ endpoint="https://test.cognitiveservices.azure.com/",
169
+ api_key=Secret.from_token("test_api_key"),
170
+ )
171
+
172
+ converter.close()
173
+
174
+ assert converter.client is None
175
+
176
+
177
+ class TestAzureDocumentIntelligenceConverterRun:
178
+ def test_run_calls_warm_up(self):
179
+ converter = AzureDocumentIntelligenceConverter(
180
+ endpoint="https://test.cognitiveservices.azure.com/",
181
+ api_key=Secret.from_token("test_api_key"),
182
+ )
183
+ with patch(
184
+ "haystack_integrations.components.converters.azure_doc_intelligence.converter.DocumentIntelligenceClient"
185
+ ) as mock_client_cls:
186
+ mock_client_cls.return_value.begin_analyze_document.return_value.result.return_value = (
187
+ make_mock_analyze_result()
188
+ )
189
+ result = converter.run(sources=[ByteStream.from_string("data")])
190
+
191
+ assert converter.client is mock_client_cls.return_value
192
+ assert len(result["documents"]) == 1
193
+
194
+ def test_run_returns_document_with_markdown_content_and_meta(self, warmed_converter):
195
+ warmed_converter.client.begin_analyze_document.return_value.result.return_value = make_mock_analyze_result(
196
+ content="# Heading\n\nHello", pages=("p1", "p2", "p3")
197
+ )
198
+
199
+ result = warmed_converter.run(sources=[ByteStream.from_string("data")])
200
+
201
+ assert len(result["documents"]) == 1
202
+ doc = result["documents"][0]
203
+ assert doc.content == "# Heading\n\nHello"
204
+ assert doc.meta["model_id"] == "prebuilt-layout"
205
+ assert doc.meta["page_count"] == 3
206
+
207
+ def test_run_returns_raw_azure_response(self, warmed_converter):
208
+ raw_dict = {"content": "text", "pages": [{"page_number": 1}]}
209
+ warmed_converter.client.begin_analyze_document.return_value.result.return_value = make_mock_analyze_result(
210
+ content="text", as_dict_value=raw_dict
211
+ )
212
+
213
+ result = warmed_converter.run(sources=[ByteStream.from_string("data")])
214
+
215
+ assert result["raw_azure_response"] == [raw_dict]
216
+
217
+ def test_run_with_multiple_sources(self, warmed_converter):
218
+ sources = [ByteStream.from_string("one"), ByteStream.from_string("two")]
219
+
220
+ result = warmed_converter.run(sources=sources)
221
+
222
+ assert len(result["documents"]) == 2
223
+ assert len(result["raw_azure_response"]) == 2
224
+
225
+ @pytest.mark.parametrize("store_full_path", [True, False])
226
+ def test_run_respects_store_full_path(self, store_full_path):
227
+ pdf_path = Path(__file__).parent / "test_files" / "pdf" / "sample_pdf_1.pdf"
228
+ converter = AzureDocumentIntelligenceConverter(
229
+ endpoint="https://test.cognitiveservices.azure.com/",
230
+ api_key=Secret.from_token("test_api_key"),
231
+ store_full_path=store_full_path,
232
+ )
233
+ converter.client = MagicMock()
234
+ converter.client.begin_analyze_document.return_value.result.return_value = make_mock_analyze_result()
235
+
236
+ result = converter.run(sources=[str(pdf_path)])
237
+
238
+ expected_path = str(pdf_path) if store_full_path else "sample_pdf_1.pdf"
239
+ assert result["documents"][0].meta["file_path"] == expected_path
240
+
241
+ def test_run_applies_single_meta_dict_to_all_documents(self, warmed_converter):
242
+ sources = [ByteStream.from_string("one"), ByteStream.from_string("two")]
243
+
244
+ result = warmed_converter.run(sources=sources, meta={"shared": "value"})
245
+
246
+ assert all(doc.meta["shared"] == "value" for doc in result["documents"])
247
+
248
+ def test_run_applies_meta_list_pairwise(self, warmed_converter):
249
+ sources = [ByteStream.from_string("a"), ByteStream.from_string("b")]
250
+
251
+ result = warmed_converter.run(sources=sources, meta=[{"index": 0}, {"index": 1}])
252
+
253
+ assert result["documents"][0].meta["index"] == 0
254
+ assert result["documents"][1].meta["index"] == 1
255
+
256
+ def test_run_skips_unreadable_source(self, warmed_converter):
257
+ result = warmed_converter.run(sources=["/nonexistent/missing.pdf"])
258
+
259
+ assert result["documents"] == []
260
+ assert result["raw_azure_response"] == []
261
+
262
+ def test_run_skips_source_when_azure_analysis_fails(self, warmed_converter):
263
+ warmed_converter.client.begin_analyze_document.side_effect = RuntimeError("Azure failure")
264
+
265
+ result = warmed_converter.run(sources=[ByteStream.from_string("data")])
266
+
267
+ assert result["documents"] == []
268
+ assert result["raw_azure_response"] == []
269
+
270
+ def test_run_uses_empty_string_when_result_content_is_none(self, warmed_converter):
271
+ warmed_converter.client.begin_analyze_document.return_value.result.return_value = make_mock_analyze_result(
272
+ content=None
273
+ )
274
+
275
+ result = warmed_converter.run(sources=[ByteStream.from_string("data")])
276
+
277
+ assert result["documents"][0].content == ""
278
+
279
+ def test_run_sets_page_count_zero_when_result_has_no_pages(self, warmed_converter):
280
+ warmed_converter.client.begin_analyze_document.return_value.result.return_value = make_mock_analyze_result(
281
+ pages=None
282
+ )
283
+
284
+ result = warmed_converter.run(sources=[ByteStream.from_string("data")])
285
+
286
+ assert result["documents"][0].meta["page_count"] == 0
98
287
 
99
288
 
100
289
  @pytest.mark.integration
@@ -117,7 +306,7 @@ class TestAzureDocumentIntelligenceConverterIntegration:
117
306
  assert "documents" in results
118
307
  assert len(results["documents"]) == 1
119
308
  assert len(results["documents"][0].content) > 0
120
- assert results["documents"][0].meta["model_id"] == "prebuilt-document"
309
+ assert results["documents"][0].meta["model_id"] == "prebuilt-layout"
121
310
 
122
311
  @pytest.mark.skipif(not os.environ.get("AZURE_DI_ENDPOINT"), reason="Azure endpoint not available")
123
312
  @pytest.mark.skipif(not os.environ.get("AZURE_DI_API_KEY"), reason="Azure credentials not available")
@@ -1,28 +0,0 @@
1
- loaders:
2
- - ignore_when_discovered:
3
- - __init__
4
- modules:
5
- - haystack_integrations.components.converters.azure_doc_intelligence.converter
6
- search_path:
7
- - ../src
8
- type: haystack_pydoc_tools.loaders.CustomPythonLoader
9
- processors:
10
- - do_not_filter_modules: false
11
- documented_only: true
12
- expression: null
13
- skip_empty_modules: true
14
- type: filter
15
- - type: smart
16
- - type: crossref
17
- renderer:
18
- description: Azure Document Intelligence integration for Haystack
19
- id: integrations-azure_doc_intelligence
20
- markdown:
21
- add_member_class_prefix: false
22
- add_method_class_prefix: true
23
- classdef_code_block: false
24
- descriptive_class_title: false
25
- descriptive_module_title: true
26
- filename: azure_doc_intelligence.md
27
- title: Azure Document Intelligence
28
- type: haystack_pydoc_tools.renderers.DocusaurusRenderer
@@ -1,3 +0,0 @@
1
- # SPDX-FileCopyrightText: 2022-present deepset GmbH <info@deepset.ai>
2
- #
3
- # SPDX-License-Identifier: Apache-2.0
@@ -1,3 +0,0 @@
1
- # SPDX-FileCopyrightText: 2022-present deepset GmbH <info@deepset.ai>
2
- #
3
- # SPDX-License-Identifier: Apache-2.0
@@ -1,3 +0,0 @@
1
- # SPDX-FileCopyrightText: 2022-present deepset GmbH <info@deepset.ai>
2
- #
3
- # SPDX-License-Identifier: Apache-2.0