markitdown-pro 1.3.3__tar.gz → 1.3.5__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 (63) hide show
  1. {markitdown_pro-1.3.3 → markitdown_pro-1.3.5}/PKG-INFO +1 -1
  2. markitdown_pro-1.3.5/markitdown_pro/common/schemas.py +20 -0
  3. {markitdown_pro-1.3.3 → markitdown_pro-1.3.5}/markitdown_pro/conversion_pipeline.py +99 -68
  4. {markitdown_pro-1.3.3 → markitdown_pro-1.3.5}/markitdown_pro/converters/azure_doc_intel_wrapper.py +4 -0
  5. {markitdown_pro-1.3.3 → markitdown_pro-1.3.5}/markitdown_pro/converters/markitdown_wrapper.py +2 -1
  6. {markitdown_pro-1.3.3 → markitdown_pro-1.3.5}/markitdown_pro/converters/pymupdf_wrapper.py +2 -5
  7. {markitdown_pro-1.3.3 → markitdown_pro-1.3.5}/markitdown_pro/handlers/audio_handler.py +5 -19
  8. {markitdown_pro-1.3.3 → markitdown_pro-1.3.5}/markitdown_pro/handlers/image_handler.py +23 -0
  9. {markitdown_pro-1.3.3 → markitdown_pro-1.3.5}/markitdown_pro/handlers/office_handler.py +3 -8
  10. markitdown_pro-1.3.5/markitdown_pro/handlers/pdf_handler.py +377 -0
  11. {markitdown_pro-1.3.3 → markitdown_pro-1.3.5}/markitdown_pro/services/azure_doc_intelligence.py +6 -16
  12. markitdown_pro-1.3.5/markitdown_pro/services/azure_speech.py +473 -0
  13. {markitdown_pro-1.3.3 → markitdown_pro-1.3.5}/markitdown_pro.egg-info/PKG-INFO +1 -1
  14. {markitdown_pro-1.3.3 → markitdown_pro-1.3.5}/markitdown_pro.egg-info/SOURCES.txt +5 -2
  15. {markitdown_pro-1.3.3 → markitdown_pro-1.3.5}/setup.py +1 -1
  16. markitdown_pro-1.3.5/tests/conversion_pipeline/test_conversion_pipeline.py +31 -0
  17. markitdown_pro-1.3.5/tests/handlers/__init__.py +0 -0
  18. markitdown_pro-1.3.5/tests/page_count/__init__.py +0 -0
  19. markitdown_pro-1.3.5/tests/page_count/test_pdf_page_count.py +30 -0
  20. markitdown_pro-1.3.3/markitdown_pro/common/schemas.py +0 -7
  21. markitdown_pro-1.3.3/markitdown_pro/handlers/pdf_handler.py +0 -194
  22. markitdown_pro-1.3.3/markitdown_pro/services/azure_speech.py +0 -274
  23. markitdown_pro-1.3.3/tests/test_conversion_pipeline.py +0 -25
  24. {markitdown_pro-1.3.3 → markitdown_pro-1.3.5}/README.md +0 -0
  25. {markitdown_pro-1.3.3 → markitdown_pro-1.3.5}/markitdown_pro/__init__.py +0 -0
  26. {markitdown_pro-1.3.3 → markitdown_pro-1.3.5}/markitdown_pro/common/__init__.py +0 -0
  27. {markitdown_pro-1.3.3 → markitdown_pro-1.3.5}/markitdown_pro/common/isolated_worker.py +0 -0
  28. {markitdown_pro-1.3.3 → markitdown_pro-1.3.5}/markitdown_pro/common/logger.py +0 -0
  29. {markitdown_pro-1.3.3 → markitdown_pro-1.3.5}/markitdown_pro/common/utils.py +0 -0
  30. {markitdown_pro-1.3.3 → markitdown_pro-1.3.5}/markitdown_pro/converters/__init__.py +0 -0
  31. {markitdown_pro-1.3.3 → markitdown_pro-1.3.5}/markitdown_pro/converters/azure_speech_wrapper.py +0 -0
  32. {markitdown_pro-1.3.3 → markitdown_pro-1.3.5}/markitdown_pro/converters/base.py +0 -0
  33. {markitdown_pro-1.3.3 → markitdown_pro-1.3.5}/markitdown_pro/converters/gpt_vision_wrapper.py +0 -0
  34. {markitdown_pro-1.3.3 → markitdown_pro-1.3.5}/markitdown_pro/converters/tabular_wrapper.py +0 -0
  35. {markitdown_pro-1.3.3 → markitdown_pro-1.3.5}/markitdown_pro/converters/unstructured_wrapper.py +0 -0
  36. {markitdown_pro-1.3.3 → markitdown_pro-1.3.5}/markitdown_pro/converters/youtube_wrapper.py +0 -0
  37. {markitdown_pro-1.3.3 → markitdown_pro-1.3.5}/markitdown_pro/handlers/__init__.py +0 -0
  38. {markitdown_pro-1.3.3 → markitdown_pro-1.3.5}/markitdown_pro/handlers/base_handler.py +0 -0
  39. {markitdown_pro-1.3.3 → markitdown_pro-1.3.5}/markitdown_pro/handlers/email_handler.py +0 -0
  40. {markitdown_pro-1.3.3 → markitdown_pro-1.3.5}/markitdown_pro/handlers/epub_handler.py +0 -0
  41. {markitdown_pro-1.3.3 → markitdown_pro-1.3.5}/markitdown_pro/handlers/ipynb_handler.py +0 -0
  42. {markitdown_pro-1.3.3 → markitdown_pro-1.3.5}/markitdown_pro/handlers/markitdown_handler.py +0 -0
  43. {markitdown_pro-1.3.3 → markitdown_pro-1.3.5}/markitdown_pro/handlers/markup_handler.py +0 -0
  44. {markitdown_pro-1.3.3 → markitdown_pro-1.3.5}/markitdown_pro/handlers/pst_handler.py +0 -0
  45. {markitdown_pro-1.3.3 → markitdown_pro-1.3.5}/markitdown_pro/handlers/tabular_handler.py +0 -0
  46. {markitdown_pro-1.3.3 → markitdown_pro-1.3.5}/markitdown_pro/handlers/text_handler.py +0 -0
  47. {markitdown_pro-1.3.3 → markitdown_pro-1.3.5}/markitdown_pro/services/__init__.py +0 -0
  48. {markitdown_pro-1.3.3 → markitdown_pro-1.3.5}/markitdown_pro/services/openai_services.py +0 -0
  49. {markitdown_pro-1.3.3 → markitdown_pro-1.3.5}/markitdown_pro.egg-info/dependency_links.txt +0 -0
  50. {markitdown_pro-1.3.3 → markitdown_pro-1.3.5}/markitdown_pro.egg-info/requires.txt +0 -0
  51. {markitdown_pro-1.3.3 → markitdown_pro-1.3.5}/markitdown_pro.egg-info/top_level.txt +0 -0
  52. {markitdown_pro-1.3.3 → markitdown_pro-1.3.5}/pyproject.toml +0 -0
  53. {markitdown_pro-1.3.3 → markitdown_pro-1.3.5}/setup.cfg +0 -0
  54. {markitdown_pro-1.3.3/tests/handlers → markitdown_pro-1.3.5/tests/conversion_pipeline}/__init__.py +0 -0
  55. {markitdown_pro-1.3.3 → markitdown_pro-1.3.5}/tests/handlers/test_email_handler.py +0 -0
  56. {markitdown_pro-1.3.3 → markitdown_pro-1.3.5}/tests/handlers/test_epub_handler.py +0 -0
  57. {markitdown_pro-1.3.3 → markitdown_pro-1.3.5}/tests/handlers/test_image_handler.py +0 -0
  58. {markitdown_pro-1.3.3 → markitdown_pro-1.3.5}/tests/handlers/test_ipynb_handler.py +0 -0
  59. {markitdown_pro-1.3.3 → markitdown_pro-1.3.5}/tests/handlers/test_markitdown_handler.py +0 -0
  60. {markitdown_pro-1.3.3 → markitdown_pro-1.3.5}/tests/handlers/test_markup_handler.py +0 -0
  61. {markitdown_pro-1.3.3 → markitdown_pro-1.3.5}/tests/handlers/test_pst_handler.py +0 -0
  62. {markitdown_pro-1.3.3 → markitdown_pro-1.3.5}/tests/handlers/test_tabular_handler.py +0 -0
  63. {markitdown_pro-1.3.3 → markitdown_pro-1.3.5}/tests/handlers/test_text_handler.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: markitdown-pro
3
- Version: 1.3.3
3
+ Version: 1.3.5
4
4
  Summary: A package that converts almost any file format to Markdown.
5
5
  Author: Developer
6
6
  Classifier: Programming Language :: Python :: 3
@@ -0,0 +1,20 @@
1
+ import enum
2
+ from io import BytesIO
3
+
4
+
5
+ class NamedBytesIO(BytesIO):
6
+ def __init__(self, data: bytes, name: str):
7
+ super().__init__(data)
8
+ self.name = name
9
+
10
+
11
+ class ExtensionCategory(enum.Enum):
12
+ IMAGE = "image"
13
+ AUDIO = "audio"
14
+ VIDEO = "video"
15
+ PDF = "pdf"
16
+ OFFICE = "office"
17
+ TABULAR = "tabular"
18
+ LIGHTWEIGHT_TEXT = "lightweight_text"
19
+ FORMATTED_DOCS = "formatted_docs"
20
+ OTHER = "other"
@@ -38,7 +38,9 @@ from typing import Optional
38
38
  import httpx
39
39
 
40
40
  from .common.logger import logger
41
+ from .common.schemas import ExtensionCategory
41
42
  from .common.utils import clean_markdown, detect_extension, ensure_minimum_content
43
+ from .converters.azure_doc_intel_wrapper import DocIntelligenceWrapper
42
44
  from .handlers.audio_handler import AudioHandler
43
45
  from .handlers.base_handler import BaseHandler
44
46
  from .handlers.email_handler import EmailHandler
@@ -88,80 +90,82 @@ class ConversionPipeline:
88
90
  self.pst_handler = PSTHandler()
89
91
  self.ipynb_handler = IpynbHandler()
90
92
  self.markitdown_handler = MarkItDownHandler()
91
-
92
- # Map extensions to handlers (normalized lowercase with dot)
93
- self.handlers_mapping: dict[str, BaseHandler] = {
94
- # region PDFs
95
- ".pdf": self.pdf_handler,
96
- # endregion
97
- # region Audio
98
- ".mp3": self.audio_handler,
99
- ".wav": self.audio_handler,
100
- # ".ogg": self.audio_handler,
101
- # ".flac": self.audio_handler,
102
- # ".m4a": self.audio_handler,
103
- # ".aac": self.audio_handler,
104
- # ".wma": self.audio_handler,
105
- # ".webm": self.audio_handler,
106
- # ".opus": self.audio_handler,
107
- # endregion
108
- # region Images
109
- ".bmp": self.image_handler,
110
- ".gif": self.image_handler,
111
- ".heic": self.image_handler,
112
- ".jpeg": self.image_handler,
113
- ".jpg": self.image_handler,
114
- ".png": self.image_handler,
115
- # ".prn": self.image_handler,
116
- ".svg": self.image_handler,
117
- ".tiff": self.image_handler,
118
- ".webp": self.image_handler,
119
- ".heif": self.image_handler,
120
- # endregion
121
- # region Plain/code text
122
- ".txt": self.text_handler,
123
- ".md": self.text_handler,
124
- ".py": self.text_handler,
125
- ".go": self.text_handler,
126
- # endregion
127
- # region Tabular (via MarkItDown)
128
- ".csv": self.tabular_handler,
129
- ".tsv": self.tabular_handler,
130
- # endregion
131
- # region Office/Spreadsheet/Slides
132
- ".xls": self.office_handler,
133
- ".xlsx": self.office_handler,
134
- ".docx": self.office_handler,
135
- # ".odt": self.office_handler,
136
- # ".rtf": self.office_handler,
137
- # ".ppt": self.office_handler,
138
- ".pptx": self.office_handler,
139
- # endregion
140
- # region Markup/serialization
141
- ".html": self.markup_handler,
142
- ".htm": self.markup_handler,
143
- ".xml": self.markup_handler,
144
- ".json": self.markup_handler,
145
- ".ndjson": self.markup_handler,
146
- ".yaml": self.markup_handler,
147
- ".yml": self.markup_handler,
148
- # endregion
149
- # region Others
150
- ".epub": self.epub_handler,
151
- ".eml": self.email_handler,
152
- ".p7s": self.email_handler,
153
- ".msg": self.email_handler,
154
- ".pst": self.pst_handler,
155
- ".ipynb": self.ipynb_handler,
156
- # endregion
93
+ self.doc_intel_wrapper = DocIntelligenceWrapper()
94
+
95
+ self.handlers_categories: dict[ExtensionCategory, dict[str, BaseHandler]] = {
96
+ ExtensionCategory.IMAGE: {
97
+ ".bmp": self.image_handler,
98
+ ".gif": self.image_handler,
99
+ # ".heic": self.image_handler,
100
+ ".jpeg": self.image_handler,
101
+ ".jpg": self.image_handler,
102
+ ".png": self.image_handler,
103
+ # ".prn": self.image_handler,
104
+ ".svg": self.image_handler,
105
+ ".tiff": self.image_handler,
106
+ ".webp": self.image_handler,
107
+ ".heif": self.image_handler,
108
+ },
109
+ ExtensionCategory.AUDIO: {
110
+ ".mp3": self.audio_handler,
111
+ ".wav": self.audio_handler,
112
+ # ".ogg": self.audio_handler,
113
+ # ".flac": self.audio_handler,
114
+ # ".m4a": self.audio_handler,
115
+ # ".aac": self.audio_handler,
116
+ # ".wma": self.audio_handler,
117
+ # ".webm": self.audio_handler,
118
+ # ".opus": self.audio_handler,
119
+ },
120
+ ExtensionCategory.LIGHTWEIGHT_TEXT: {
121
+ ".txt": self.text_handler,
122
+ ".md": self.text_handler,
123
+ ".py": self.text_handler,
124
+ ".go": self.text_handler,
125
+ ".csv": self.tabular_handler,
126
+ ".tsv": self.tabular_handler,
127
+ ".html": self.markup_handler,
128
+ ".htm": self.markup_handler,
129
+ ".xml": self.markup_handler,
130
+ ".json": self.markup_handler,
131
+ ".ndjson": self.markup_handler,
132
+ ".yaml": self.markup_handler,
133
+ ".yml": self.markup_handler,
134
+ ".epub": self.epub_handler,
135
+ ".eml": self.email_handler,
136
+ ".p7s": self.email_handler,
137
+ ".msg": self.email_handler,
138
+ ".pst": self.pst_handler,
139
+ ".ipynb": self.ipynb_handler,
140
+ },
141
+ ExtensionCategory.FORMATTED_DOCS: {
142
+ ".pdf": self.pdf_handler,
143
+ ".xls": self.tabular_handler,
144
+ ".xlsx": self.tabular_handler,
145
+ ".docx": self.office_handler,
146
+ # ".odt": self.office_handler,
147
+ # ".rtf": self.office_handler,
148
+ # ".ppt": self.office_handler,
149
+ ".pptx": self.office_handler,
150
+ },
157
151
  }
158
152
 
153
+ # Normalize map of extensions to handlers
154
+ self.handlers_mapping: dict[str, BaseHandler] = {}
155
+ for handlers in self.handlers_categories.values():
156
+ for ext, handler in handlers.items():
157
+ self.handlers_mapping[ext] = handler
158
+
159
159
  # ---------------------------------------------------------------------
160
160
  # Public APIs
161
161
  # ---------------------------------------------------------------------
162
162
 
163
163
  async def convert_document_to_md(
164
- self, file_path: str | Path, output_md: Optional[str | Path] = None
164
+ self,
165
+ file_path: str | Path,
166
+ output_md: Optional[str | Path] = None,
167
+ *args,
168
+ **kwargs,
165
169
  ) -> Optional[str]:
166
170
  """
167
171
  Convert a **local file** to Markdown.
@@ -193,7 +197,7 @@ class ConversionPipeline:
193
197
  raise RuntimeError(f"No handler for extension '{extension}'.")
194
198
 
195
199
  try:
196
- md_content = await handler.handle(str(file_path))
200
+ md_content = await handler.handle(str(file_path), *args, **kwargs)
197
201
  if not md_content or not ensure_minimum_content(md_content):
198
202
  return None
199
203
 
@@ -281,3 +285,30 @@ class ConversionPipeline:
281
285
  return await self.convert_document_to_md(local_path, output_md=output_md)
282
286
  finally:
283
287
  local_path.unlink(missing_ok=True)
288
+
289
+ async def get_page_count(self, file_path: str | Path) -> Optional[int]:
290
+ """
291
+ Get the page count of a document if supported by its handler.
292
+
293
+ Parameters
294
+ ----------
295
+ file_path : str | Path
296
+ Path to the local file.
297
+ """
298
+ file_path = Path(file_path)
299
+ if not file_path.is_file():
300
+ raise ValueError(f"The provided path '{file_path}' is not a valid file.")
301
+
302
+ # handle file extensions individually to avoid using the wrong handlers
303
+ extension = detect_extension(str(file_path)).lower()
304
+
305
+ if extension in self.image_handler.SUPPORTED_EXTENSIONS:
306
+ return await self.image_handler.get_page_count(file_path)
307
+ elif extension in self.pdf_handler.SUPPORTED_EXTENSIONS:
308
+ return await self.doc_intel_wrapper.get_page_count(file_path)
309
+ # elif extension in self.doc_intel_wrapper.SUPPORTED_EXTENSIONS:
310
+ # return await self.doc_intel_wrapper.get_page_count(file_path)
311
+ else:
312
+ logger.warning(f"ConversionPipeline: No page count support for extension '{extension}'")
313
+ return None
314
+ return None
@@ -1,3 +1,4 @@
1
+ from pathlib import Path
1
2
  from typing import Optional
2
3
 
3
4
  from ..services.azure_doc_intelligence import DocumentIntelligenceHandler
@@ -16,3 +17,6 @@ class DocIntelligenceWrapper(ConverterWrapper):
16
17
  markdown = await self.converter.convert_to_md(file_path)
17
18
  await self.converter.aclose()
18
19
  return markdown
20
+
21
+ async def get_page_count(self, file_path: str | Path) -> Optional[int]:
22
+ return await self.converter.get_page_count(file_path)
@@ -3,6 +3,7 @@ from typing import Optional
3
3
  from markitdown_pro.handlers.markitdown_handler import MarkItDownHandler
4
4
 
5
5
  from ..common.logger import logger
6
+ from ..common.utils import detect_extension
6
7
  from .base import ConverterWrapper
7
8
 
8
9
 
@@ -14,7 +15,7 @@ class MarkItDownWrapper(ConverterWrapper):
14
15
  self.handler = MarkItDownHandler(*args, **kwargs)
15
16
 
16
17
  async def convert(self, file_path: str) -> Optional[str]:
17
- file_extension = f".{file_path.split('.')[-1].lower()}"
18
+ file_extension = detect_extension(file_path)
18
19
  if file_extension not in self.SUPPORTED_EXTENSIONS:
19
20
  logger.warning(f"MarkItDownWrapper: Unsupported file format: {file_extension}")
20
21
  return None
@@ -3,6 +3,7 @@ from typing import Optional
3
3
  import fitz # PyMuPDF
4
4
 
5
5
  from ..common.logger import logger
6
+ from ..common.utils import detect_extension
6
7
  from .base import ConverterWrapper
7
8
 
8
9
 
@@ -13,11 +14,7 @@ class PyMuPDFWrapper(ConverterWrapper):
13
14
  super().__init__("PyMuPDF")
14
15
 
15
16
  async def convert(self, file_path: str) -> Optional[str]:
16
- file_extension = file_path.split(".")[-1].lower()
17
- logger.info(
18
- f"PyMuPDFWrapper: Processing file: {file_path} with extension: {file_extension}"
19
- )
20
-
17
+ file_extension = detect_extension(file_path)
21
18
  if file_extension not in self.SUPPORTED_EXTENSIONS:
22
19
  logger.warning(f"PyMuPDFWrapper: Unsupported file format: {file_extension}")
23
20
  return None
@@ -3,9 +3,9 @@ from __future__ import annotations
3
3
  from typing import Optional
4
4
 
5
5
  from ..common.logger import logger
6
+ from ..common.utils import ensure_minimum_content
6
7
  from ..converters.azure_speech_wrapper import AzureSpeechWrapper
7
8
  from ..converters.base import ConverterWrapper
8
- from ..converters.markitdown_wrapper import MarkItDownWrapper
9
9
  from ..handlers.base_handler import BaseHandler
10
10
 
11
11
 
@@ -13,8 +13,7 @@ class AudioHandler(BaseHandler):
13
13
  """
14
14
  Convert audio files to Markdown by trying two converters in order:
15
15
 
16
- 1) **MarkItDown** — fast local extractor (works when the file format is supported).
17
- 2) **Azure Speech** — cloud speech-to-text fallback for actual audio transcription.
16
+ 1) **Azure Speech** — cloud speech-to-text fallback for actual audio transcription.
18
17
 
19
18
  The first converter that yields non-trivial Markdown (as determined by
20
19
  `ensure_minimum_content`) is returned. If both fail, `None` is returned.
@@ -26,27 +25,13 @@ class AudioHandler(BaseHandler):
26
25
  - This handler runs converters **sequentially** to avoid unnecessary API calls.
27
26
  """
28
27
 
29
- SUPPORTED_EXTENSIONS = frozenset(
30
- {
31
- ".mp3",
32
- ".wav",
33
- ".ogg",
34
- ".flac",
35
- ".m4a",
36
- ".aac",
37
- ".wma",
38
- ".webm",
39
- ".opus",
40
- }
41
- )
28
+ SUPPORTED_EXTENSIONS = AzureSpeechWrapper.SUPPORTED_EXTENSIONS
42
29
 
43
30
  def __init__(self, *args, **kwargs) -> None:
44
31
  super().__init__(*args, **kwargs)
45
- self.markitdown = MarkItDownWrapper()
46
32
  self.azure_speech = AzureSpeechWrapper()
47
33
 
48
34
  self._pipeline: list[tuple[ConverterWrapper, str]] = [
49
- (self.markitdown, "MarkItDown"),
50
35
  (self.azure_speech, "Azure Speech"),
51
36
  ]
52
37
 
@@ -71,7 +56,8 @@ class AudioHandler(BaseHandler):
71
56
  logger.info(f"AudioHandler: Trying {name} for '{file_path}'")
72
57
  try:
73
58
  md = await converter.convert(file_path)
74
- return md
59
+ if md and ensure_minimum_content(md):
60
+ return md
75
61
  except Exception as e:
76
62
  logger.error(f"AudioHandler: {name} failed for '{file_path}': {e}")
77
63
 
@@ -1,7 +1,9 @@
1
1
  import contextlib
2
+ from pathlib import Path
2
3
  from typing import Optional
3
4
 
4
5
  from ..common.logger import logger
6
+ from ..common.utils import detect_extension
5
7
  from ..converters.gpt_vision_wrapper import GPTVisionWrapper
6
8
  from .base_handler import BaseHandler
7
9
 
@@ -37,6 +39,27 @@ class ImageHandler(BaseHandler):
37
39
  if hasattr(self.gpt_vision, "gpt_vision"):
38
40
  await self.gpt_vision.gpt_vision.aclose()
39
41
 
42
+ async def get_page_count(self, file_path: str | Path) -> Optional[int]:
43
+ """
44
+ Determines the number of pages in the given image file.
45
+ """
46
+ p = Path(file_path)
47
+ ext = detect_extension(str(p.absolute()))
48
+ if ext not in self.SUPPORTED_EXTENSIONS:
49
+ logger.warning(f"ImageHandler: Unsupported file format: {ext}")
50
+ return None
51
+
52
+ if ext in {".tif", ".tiff"}:
53
+ try:
54
+ from PIL import Image, ImageSequence # optional dependency
55
+
56
+ with Image.open(str(p)) as im:
57
+ return sum(1 for _ in ImageSequence.Iterator(im)) or 1
58
+ except Exception as e_tiff:
59
+ logger.warning(f"ImageHandler: local TIFF page count failed for '{p}': {e_tiff}")
60
+ else:
61
+ return 1
62
+
40
63
  async def aclose(self) -> None:
41
64
  if hasattr(self, "gpt_vision") and self.gpt_vision:
42
65
  await self.gpt_vision.aclose()
@@ -4,7 +4,6 @@ from ..common.logger import logger
4
4
  from ..converters.azure_doc_intel_wrapper import DocIntelligenceWrapper
5
5
  from ..converters.base import ConverterWrapper
6
6
  from ..converters.markitdown_wrapper import MarkItDownWrapper
7
- from ..converters.tabular_wrapper import TabularWrapper
8
7
  from ..converters.unstructured_wrapper import UnstructuredWrapper
9
8
  from .base_handler import BaseHandler
10
9
 
@@ -13,10 +12,9 @@ class OfficeHandler(BaseHandler):
13
12
  """
14
13
  Convert Office documents to Markdown by trying a series of converters in order:
15
14
 
16
- 1) TabularHandler (specialized handler for tabular data)
17
- 2) MarkItDown (fast, local parsing for Office formats)
18
- 3) Azure Document Intelligence (cloud extraction + OCR for embedded images)
19
- 4) Unstructured (robust fallback parser)
15
+ 1) MarkItDown (fast, local parsing for Office formats)
16
+ 2) Azure Document Intelligence (cloud extraction + OCR for embedded images)
17
+ 3) Unstructured (robust fallback parser)
20
18
 
21
19
  The first converter that returns non-trivial Markdown (as judged by
22
20
  `ensure_minimum_content`) wins. If all fail, `None` is returned.
@@ -28,21 +26,18 @@ class OfficeHandler(BaseHandler):
28
26
  avoid unnecessary API calls when earlier options succeed.
29
27
  """
30
28
 
31
- # Supported Office-like extensions (lowercase with dot)
32
29
  SUPPORTED_EXTENSIONS = frozenset({".doc", ".docx", ".odt", ".rtf", ".ppt", ".pptx"})
33
30
 
34
31
  def __init__(self, *args, **kwargs) -> None:
35
32
  super().__init__(*args, **kwargs)
36
33
 
37
34
  # Ordered, fastest → most comprehensive
38
- self.tabular = TabularWrapper()
39
35
  self.markitdown = MarkItDownWrapper()
40
36
  self.doc_intelligence = DocIntelligenceWrapper()
41
37
  self.unstructured = UnstructuredWrapper()
42
38
 
43
39
  # (converter, human_readable_name) in the exact order to try
44
40
  self._pipeline: list[tuple[ConverterWrapper, str]] = [
45
- (self.tabular, "TabularHandler"),
46
41
  (self.markitdown, "MarkItDown"),
47
42
  (self.doc_intelligence, "Azure Document Intelligence"),
48
43
  (self.unstructured, "Unstructured"),