msgflux 0.1.0__py3-none-any.whl

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 (165) hide show
  1. msgflux/__init__.py +104 -0
  2. msgflux/_private/__init__.py +0 -0
  3. msgflux/_private/client.py +105 -0
  4. msgflux/_private/core.py +14 -0
  5. msgflux/_private/executor.py +134 -0
  6. msgflux/_private/response.py +230 -0
  7. msgflux/auto/__init__.py +5 -0
  8. msgflux/auto/params.py +167 -0
  9. msgflux/cache.py +54 -0
  10. msgflux/core/__init__.py +5 -0
  11. msgflux/core/dotdict.py +264 -0
  12. msgflux/core/examples.py +169 -0
  13. msgflux/core/message.py +45 -0
  14. msgflux/data/__init__.py +0 -0
  15. msgflux/data/audio.py +1 -0
  16. msgflux/data/dbs/__init__.py +16 -0
  17. msgflux/data/dbs/base.py +124 -0
  18. msgflux/data/dbs/db.py +65 -0
  19. msgflux/data/dbs/providers/__init__.py +0 -0
  20. msgflux/data/dbs/providers/cachetools.py +57 -0
  21. msgflux/data/dbs/providers/diskcache.py +48 -0
  22. msgflux/data/dbs/providers/faiss.py +220 -0
  23. msgflux/data/dbs/registry.py +19 -0
  24. msgflux/data/dbs/response.py +10 -0
  25. msgflux/data/dbs/types.py +26 -0
  26. msgflux/data/parsers/__init__.py +16 -0
  27. msgflux/data/parsers/base.py +325 -0
  28. msgflux/data/parsers/parser.py +101 -0
  29. msgflux/data/parsers/providers/__init__.py +32 -0
  30. msgflux/data/parsers/providers/csv_parser.py +278 -0
  31. msgflux/data/parsers/providers/email_parser.py +264 -0
  32. msgflux/data/parsers/providers/html_parser.py +265 -0
  33. msgflux/data/parsers/providers/openpyxl.py +333 -0
  34. msgflux/data/parsers/providers/pypdf.py +186 -0
  35. msgflux/data/parsers/providers/python_docx.py +334 -0
  36. msgflux/data/parsers/providers/python_pptx.py +197 -0
  37. msgflux/data/parsers/registry.py +19 -0
  38. msgflux/data/parsers/response.py +32 -0
  39. msgflux/data/parsers/types.py +110 -0
  40. msgflux/data/retrievers/__init__.py +16 -0
  41. msgflux/data/retrievers/base.py +185 -0
  42. msgflux/data/retrievers/providers/__init__.py +0 -0
  43. msgflux/data/retrievers/providers/bm25.py +230 -0
  44. msgflux/data/retrievers/providers/bm25s.py +221 -0
  45. msgflux/data/retrievers/providers/rank_bm25.py +148 -0
  46. msgflux/data/retrievers/providers/rapidfuzz.py +125 -0
  47. msgflux/data/retrievers/providers/wikipedia.py +281 -0
  48. msgflux/data/retrievers/registry.py +19 -0
  49. msgflux/data/retrievers/retriever.py +83 -0
  50. msgflux/data/retrievers/types.py +24 -0
  51. msgflux/data/types/__init__.py +29 -0
  52. msgflux/data/types/audio.py +112 -0
  53. msgflux/data/types/base.py +70 -0
  54. msgflux/data/types/file.py +114 -0
  55. msgflux/data/types/image.py +134 -0
  56. msgflux/data/types/video.py +121 -0
  57. msgflux/dsl/__init__.py +0 -0
  58. msgflux/dsl/inline.py +484 -0
  59. msgflux/dsl/signature.py +393 -0
  60. msgflux/dsl/typed_parsers/__init__.py +19 -0
  61. msgflux/dsl/typed_parsers/base.py +24 -0
  62. msgflux/dsl/typed_parsers/providers/__init__.py +0 -0
  63. msgflux/dsl/typed_parsers/providers/xml.py +259 -0
  64. msgflux/dsl/typed_parsers/registry.py +14 -0
  65. msgflux/envs.py +100 -0
  66. msgflux/exceptions.py +84 -0
  67. msgflux/generation/__init__.py +0 -0
  68. msgflux/generation/control_flow.py +163 -0
  69. msgflux/generation/reasoning/__init__.py +5 -0
  70. msgflux/generation/reasoning/cot.py +7 -0
  71. msgflux/generation/reasoning/react.py +289 -0
  72. msgflux/generation/reasoning/self_consistency.py +16 -0
  73. msgflux/generation/templates.py +53 -0
  74. msgflux/logger.py +159 -0
  75. msgflux/models/__init__.py +16 -0
  76. msgflux/models/base.py +39 -0
  77. msgflux/models/cache.py +125 -0
  78. msgflux/models/gateway.py +466 -0
  79. msgflux/models/httpx.py +81 -0
  80. msgflux/models/model.py +122 -0
  81. msgflux/models/profiles/__init__.py +48 -0
  82. msgflux/models/profiles/base.py +122 -0
  83. msgflux/models/profiles/loader.py +264 -0
  84. msgflux/models/profiles/registry.py +207 -0
  85. msgflux/models/providers/__init__.py +0 -0
  86. msgflux/models/providers/cerebras.py +30 -0
  87. msgflux/models/providers/groq.py +52 -0
  88. msgflux/models/providers/imagerouter.py +33 -0
  89. msgflux/models/providers/jinaai.py +331 -0
  90. msgflux/models/providers/ollama.py +51 -0
  91. msgflux/models/providers/openai.py +1884 -0
  92. msgflux/models/providers/openrouter.py +64 -0
  93. msgflux/models/providers/replicate.py +218 -0
  94. msgflux/models/providers/sambanova.py +38 -0
  95. msgflux/models/providers/together.py +57 -0
  96. msgflux/models/providers/vllm.py +131 -0
  97. msgflux/models/registry.py +19 -0
  98. msgflux/models/response.py +26 -0
  99. msgflux/models/tool_call_agg.py +85 -0
  100. msgflux/models/types.py +196 -0
  101. msgflux/nn/__init__.py +57 -0
  102. msgflux/nn/functional.py +645 -0
  103. msgflux/nn/hooks/__init__.py +24 -0
  104. msgflux/nn/hooks/guard.py +109 -0
  105. msgflux/nn/hooks/hook.py +123 -0
  106. msgflux/nn/modules/__init__.py +68 -0
  107. msgflux/nn/modules/agent.py +1927 -0
  108. msgflux/nn/modules/container.py +672 -0
  109. msgflux/nn/modules/embedder.py +261 -0
  110. msgflux/nn/modules/generator.py +21 -0
  111. msgflux/nn/modules/mediamaker.py +285 -0
  112. msgflux/nn/modules/module.py +2106 -0
  113. msgflux/nn/modules/predictor.py +238 -0
  114. msgflux/nn/modules/searcher.py +383 -0
  115. msgflux/nn/modules/speaker.py +222 -0
  116. msgflux/nn/modules/tool.py +839 -0
  117. msgflux/nn/modules/transcriber.py +273 -0
  118. msgflux/nn/parameter.py +77 -0
  119. msgflux/protocols/__init__.py +1 -0
  120. msgflux/protocols/mcp/__init__.py +61 -0
  121. msgflux/protocols/mcp/auth/__init__.py +17 -0
  122. msgflux/protocols/mcp/auth/apikey.py +70 -0
  123. msgflux/protocols/mcp/auth/base.py +83 -0
  124. msgflux/protocols/mcp/auth/basic.py +57 -0
  125. msgflux/protocols/mcp/auth/bearer.py +97 -0
  126. msgflux/protocols/mcp/auth/custom.py +76 -0
  127. msgflux/protocols/mcp/auth/oauth2.py +133 -0
  128. msgflux/protocols/mcp/client.py +454 -0
  129. msgflux/protocols/mcp/exceptions.py +25 -0
  130. msgflux/protocols/mcp/integration.py +95 -0
  131. msgflux/protocols/mcp/loglevels.py +16 -0
  132. msgflux/protocols/mcp/transports.py +435 -0
  133. msgflux/protocols/mcp/types.py +51 -0
  134. msgflux/py.typed +0 -0
  135. msgflux/telemetry/__init__.py +22 -0
  136. msgflux/telemetry/config.py +104 -0
  137. msgflux/telemetry/span.py +245 -0
  138. msgflux/tools/__init__.py +10 -0
  139. msgflux/tools/builtin/__init__.py +5 -0
  140. msgflux/tools/builtin/web_fetch.py +121 -0
  141. msgflux/tools/config.py +196 -0
  142. msgflux/tools/definitions.py +11 -0
  143. msgflux/utils/__init__.py +0 -0
  144. msgflux/utils/chat.py +682 -0
  145. msgflux/utils/common.py +36 -0
  146. msgflux/utils/console.py +55 -0
  147. msgflux/utils/convert.py +20 -0
  148. msgflux/utils/encode.py +192 -0
  149. msgflux/utils/html.py +171 -0
  150. msgflux/utils/imports.py +115 -0
  151. msgflux/utils/inspect.py +81 -0
  152. msgflux/utils/logging.py +15 -0
  153. msgflux/utils/mermaid.py +20 -0
  154. msgflux/utils/msgspec.py +1116 -0
  155. msgflux/utils/pooling.py +51 -0
  156. msgflux/utils/templates.py +51 -0
  157. msgflux/utils/tenacity.py +38 -0
  158. msgflux/utils/torch.py +7 -0
  159. msgflux/utils/validation.py +31 -0
  160. msgflux/utils/xml.py +7 -0
  161. msgflux/version.py +1 -0
  162. msgflux-0.1.0.dist-info/METADATA +170 -0
  163. msgflux-0.1.0.dist-info/RECORD +165 -0
  164. msgflux-0.1.0.dist-info/WHEEL +4 -0
  165. msgflux-0.1.0.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,325 @@
1
+ import base64
2
+ import pathlib
3
+ from io import BytesIO
4
+ from typing import Dict, Mapping, Union
5
+
6
+ try:
7
+ import httpx
8
+ except ImportError:
9
+ httpx = None
10
+
11
+ from msgflux._private.client import BaseClient
12
+
13
+
14
+ class BaseParser(BaseClient):
15
+ """Base class for all parsers.
16
+
17
+ Provides common functionality for file parsing operations including:
18
+ - File loading from various sources (path, URL, bytes)
19
+ - File type validation
20
+ - Image encoding utilities
21
+ """
22
+
23
+ msgflux_type = "parser"
24
+ to_ignore = ["client"]
25
+
26
+ def instance_type(self) -> Mapping[str, str]:
27
+ return {"parser_type": self.parser_type}
28
+
29
+ def _validate_file_type(
30
+ self, file_path: str, expected_extensions: Union[str, list[str]]
31
+ ) -> bool:
32
+ """Validate that a file has the expected extension.
33
+
34
+ Args:
35
+ file_path:
36
+ Path to the file to validate.
37
+ expected_extensions:
38
+ Single extension string (e.g., ".pdf") or list of valid extensions.
39
+
40
+ Returns:
41
+ True if file extension is valid.
42
+
43
+ Raises:
44
+ ValueError:
45
+ If file extension doesn't match expected extensions.
46
+ """
47
+ if isinstance(expected_extensions, str):
48
+ expected_extensions = [expected_extensions]
49
+
50
+ file_ext = pathlib.Path(file_path).suffix.lower()
51
+ if file_ext not in expected_extensions:
52
+ expected_str = ", ".join(expected_extensions)
53
+ raise ValueError(
54
+ f"Invalid file type. Expected {expected_str}, got {file_ext}"
55
+ )
56
+ return True
57
+
58
+ def _load_file(self, data: Union[str, bytes, BytesIO]) -> bytes:
59
+ """Load file from various sources.
60
+
61
+ Args:
62
+ data:
63
+ Can be:
64
+ - str: file path or URL
65
+ - bytes: raw file data
66
+ - BytesIO: file buffer
67
+
68
+ Returns:
69
+ File content as bytes.
70
+
71
+ Raises:
72
+ ValueError:
73
+ If data type is not supported.
74
+ FileNotFoundError:
75
+ If file path doesn't exist.
76
+ """
77
+ if isinstance(data, bytes):
78
+ return data
79
+
80
+ if isinstance(data, BytesIO):
81
+ return data.getvalue()
82
+
83
+ if isinstance(data, str):
84
+ # Check if it's a URL
85
+ if data.startswith(("http://", "https://")):
86
+ if httpx is None:
87
+ raise ImportError(
88
+ "`httpx` is required to load files from URLs. "
89
+ "Install with `pip install httpx`"
90
+ )
91
+ response = httpx.get(data)
92
+ response.raise_for_status()
93
+ return response.content
94
+
95
+ # Otherwise treat as file path
96
+ file_path = pathlib.Path(data)
97
+ if not file_path.exists():
98
+ raise FileNotFoundError(f"File not found: {data}")
99
+
100
+ with open(file_path, "rb") as f:
101
+ return f.read()
102
+
103
+ raise ValueError(
104
+ f"Unsupported data type: {type(data)}. "
105
+ "Expected str (path/URL), bytes, or BytesIO"
106
+ )
107
+
108
+ def _encode_image_to_base64(self, image_data: bytes) -> str:
109
+ """Encode image bytes to base64 string.
110
+
111
+ Args:
112
+ image_data:
113
+ Raw image bytes.
114
+
115
+ Returns:
116
+ Base64 encoded string.
117
+ """
118
+ return base64.b64encode(image_data).decode("utf-8")
119
+
120
+ def _prepare_images_dict(
121
+ self, images: Dict[str, bytes], encode_base64: bool = False
122
+ ) -> Dict[str, Union[bytes, str]]:
123
+ """Prepare images dictionary for response.
124
+
125
+ Args:
126
+ images:
127
+ Dictionary mapping image names to raw bytes.
128
+ encode_base64:
129
+ If True, encode images as base64 strings.
130
+
131
+ Returns:
132
+ Dictionary with optionally encoded images.
133
+ """
134
+ if encode_base64:
135
+ return {
136
+ name: self._encode_image_to_base64(data)
137
+ for name, data in images.items()
138
+ }
139
+ return images
140
+
141
+ def chunk_text(
142
+ self,
143
+ text: str,
144
+ chunk_size: int = 1000,
145
+ chunk_overlap: int = 200,
146
+ separator: str = "\n\n",
147
+ ) -> list[str]:
148
+ """Split text into chunks with overlap.
149
+
150
+ Useful for processing long documents that need to be broken into
151
+ smaller pieces for embedding or LLM processing.
152
+
153
+ Args:
154
+ text:
155
+ Text to split into chunks.
156
+ chunk_size:
157
+ Target size for each chunk (in characters).
158
+ chunk_overlap:
159
+ Number of characters to overlap between chunks.
160
+ separator:
161
+ Separator to use for splitting (default: double newline).
162
+
163
+ Returns:
164
+ List of text chunks.
165
+
166
+ Example:
167
+ >>> parser = Parser.pdf("pypdf")
168
+ >>> response = parser("document.pdf")
169
+ >>> chunks = parser.chunk_text(
170
+ ... response.data["text"],
171
+ ... chunk_size=1000,
172
+ ... chunk_overlap=200
173
+ ... )
174
+ """
175
+ if not text:
176
+ return []
177
+
178
+ # Try to split on separator first
179
+ splits = text.split(separator)
180
+
181
+ chunks = []
182
+ current_chunk = []
183
+ current_size = 0
184
+
185
+ for split in splits:
186
+ split_size = len(split)
187
+
188
+ # If single split is larger than chunk_size, split it further
189
+ if split_size > chunk_size:
190
+ # Add current chunk if it exists
191
+ if current_chunk:
192
+ chunks.append(separator.join(current_chunk))
193
+ current_chunk = []
194
+ current_size = 0
195
+
196
+ # Split the large piece by words
197
+ words = split.split()
198
+ word_chunk = []
199
+ word_chunk_size = 0
200
+
201
+ for word in words:
202
+ word_size = len(word) + 1 # +1 for space
203
+ if word_chunk_size + word_size > chunk_size and word_chunk:
204
+ chunks.append(" ".join(word_chunk))
205
+ # Keep overlap
206
+ overlap_words = []
207
+ overlap_size = 0
208
+ for w in reversed(word_chunk):
209
+ if overlap_size + len(w) + 1 <= chunk_overlap:
210
+ overlap_words.insert(0, w)
211
+ overlap_size += len(w) + 1
212
+ else:
213
+ break
214
+ word_chunk = overlap_words
215
+ word_chunk_size = overlap_size
216
+
217
+ word_chunk.append(word)
218
+ word_chunk_size += word_size
219
+
220
+ if word_chunk:
221
+ chunks.append(" ".join(word_chunk))
222
+
223
+ elif current_size + split_size + len(separator) > chunk_size:
224
+ # Current chunk is full, save it
225
+ if current_chunk:
226
+ chunks.append(separator.join(current_chunk))
227
+
228
+ # Start new chunk with overlap from previous
229
+ overlap_text = separator.join(current_chunk)
230
+ if len(overlap_text) > chunk_overlap:
231
+ # Take last chunk_overlap characters
232
+ overlap_text = overlap_text[-chunk_overlap:]
233
+ # Find last separator to avoid cutting mid-sentence
234
+ last_sep = overlap_text.rfind(separator)
235
+ if last_sep > 0:
236
+ overlap_text = overlap_text[last_sep + len(separator) :]
237
+
238
+ current_chunk = [overlap_text, split] if overlap_text else [split]
239
+ else:
240
+ current_chunk = [split]
241
+
242
+ current_size = sum(len(s) for s in current_chunk) + len(separator) * (
243
+ len(current_chunk) - 1
244
+ )
245
+
246
+ else:
247
+ # Add to current chunk
248
+ current_chunk.append(split)
249
+ current_size += split_size + len(separator)
250
+
251
+ # Add final chunk
252
+ if current_chunk:
253
+ chunks.append(separator.join(current_chunk))
254
+
255
+ return chunks
256
+
257
+ def chunk_by_tokens(
258
+ self,
259
+ text: str,
260
+ max_tokens: int = 512,
261
+ overlap_tokens: int = 50,
262
+ encoding_name: str = "cl100k_base",
263
+ ) -> list[str]:
264
+ """Split text into chunks based on token count.
265
+
266
+ Uses tiktoken library for accurate token counting.
267
+ Falls back to character-based chunking if tiktoken not available.
268
+
269
+ Args:
270
+ text:
271
+ Text to split into chunks.
272
+ max_tokens:
273
+ Maximum tokens per chunk.
274
+ overlap_tokens:
275
+ Number of tokens to overlap between chunks.
276
+ encoding_name:
277
+ Tiktoken encoding name (default: cl100k_base for GPT-4).
278
+
279
+ Returns:
280
+ List of text chunks.
281
+
282
+ Example:
283
+ >>> parser = Parser.pdf("pypdf")
284
+ >>> response = parser("document.pdf")
285
+ >>> chunks = parser.chunk_by_tokens(
286
+ ... response.data["text"],
287
+ ... max_tokens=512,
288
+ ... overlap_tokens=50
289
+ ... )
290
+ """
291
+ try:
292
+ import tiktoken
293
+
294
+ encoding = tiktoken.get_encoding(encoding_name)
295
+
296
+ # Tokenize the text
297
+ tokens = encoding.encode(text)
298
+
299
+ if len(tokens) <= max_tokens:
300
+ return [text]
301
+
302
+ chunks = []
303
+ start = 0
304
+
305
+ while start < len(tokens):
306
+ # Get chunk tokens
307
+ end = start + max_tokens
308
+ chunk_tokens = tokens[start:end]
309
+
310
+ # Decode back to text
311
+ chunk_text = encoding.decode(chunk_tokens)
312
+ chunks.append(chunk_text)
313
+
314
+ # Move start position (with overlap)
315
+ start = end - overlap_tokens
316
+
317
+ return chunks
318
+
319
+ except ImportError:
320
+ # Fallback: estimate 1 token ≈ 4 characters
321
+ char_chunk_size = max_tokens * 4
322
+ char_overlap = overlap_tokens * 4
323
+ return self.chunk_text(
324
+ text, chunk_size=char_chunk_size, chunk_overlap=char_overlap
325
+ )
@@ -0,0 +1,101 @@
1
+ from typing import TYPE_CHECKING, Any, Mapping
2
+
3
+ from msgflux.data.parsers.registry import parser_registry
4
+
5
+ if TYPE_CHECKING:
6
+ from msgflux.data.parsers.base import BaseParser
7
+
8
+ from msgflux.data.parsers.types import (
9
+ CsvParser,
10
+ DocxParser,
11
+ EmailParser,
12
+ HtmlParser,
13
+ MarkdownParser,
14
+ PdfParser,
15
+ PptxParser,
16
+ XlsxParser,
17
+ )
18
+
19
+
20
+ class Parser:
21
+ @classmethod
22
+ def providers(cls):
23
+ return {k: list(v.keys()) for k, v in parser_registry.items()}
24
+
25
+ @classmethod
26
+ def parser_types(cls):
27
+ return list(parser_registry.keys())
28
+
29
+ @classmethod
30
+ def _get_parser_class(cls, parser_type: str, provider: str) -> type["BaseParser"]:
31
+ if parser_type not in parser_registry:
32
+ raise ValueError(f"Parser type `{parser_type}` is not supported")
33
+ if provider not in parser_registry[parser_type]:
34
+ raise ValueError(
35
+ f"Provider `{provider}` not registered for type `{parser_type}`"
36
+ )
37
+ parser_cls = parser_registry[parser_type][provider]
38
+ return parser_cls
39
+
40
+ @classmethod
41
+ def _create_parser(
42
+ cls, parser_type: str, provider: str, **kwargs
43
+ ) -> type["BaseParser"]:
44
+ parser_cls = cls._get_parser_class(parser_type, provider)
45
+ return parser_cls(**kwargs)
46
+
47
+ @classmethod
48
+ def from_serialized(
49
+ cls, provider: str, parser_type: str, params: Mapping[str, Any]
50
+ ) -> type["BaseParser"]:
51
+ """Creates a parser instance from serialized parameters.
52
+
53
+ Args:
54
+ provider:
55
+ The parser provider (e.g., "pypdf").
56
+ parser_type:
57
+ The type of parser (e.g., "pdf", "pptx").
58
+ params:
59
+ Dictionary containing the serialized parser parameters.
60
+
61
+ Returns:
62
+ An instance of the appropriate parser class with restored state.
63
+ """
64
+ parser_cls = cls._get_parser_class(parser_type, provider)
65
+ # Create instance without calling __init__
66
+ instance = object.__new__(parser_cls)
67
+ # Restore the instance state
68
+ instance.from_serialized(params)
69
+ return instance
70
+
71
+ @classmethod
72
+ def pdf(cls, provider: str, **kwargs) -> PdfParser:
73
+ return cls._create_parser("pdf", provider, **kwargs)
74
+
75
+ @classmethod
76
+ def pptx(cls, provider: str, **kwargs) -> PptxParser:
77
+ return cls._create_parser("pptx", provider, **kwargs)
78
+
79
+ @classmethod
80
+ def xlsx(cls, provider: str, **kwargs) -> XlsxParser:
81
+ return cls._create_parser("xlsx", provider, **kwargs)
82
+
83
+ @classmethod
84
+ def docx(cls, provider: str, **kwargs) -> DocxParser:
85
+ return cls._create_parser("docx", provider, **kwargs)
86
+
87
+ @classmethod
88
+ def csv(cls, provider: str, **kwargs) -> CsvParser:
89
+ return cls._create_parser("csv", provider, **kwargs)
90
+
91
+ @classmethod
92
+ def html(cls, provider: str, **kwargs) -> HtmlParser:
93
+ return cls._create_parser("html", provider, **kwargs)
94
+
95
+ @classmethod
96
+ def markdown(cls, provider: str, **kwargs) -> MarkdownParser:
97
+ return cls._create_parser("markdown", provider, **kwargs)
98
+
99
+ @classmethod
100
+ def email(cls, provider: str, **kwargs) -> EmailParser:
101
+ return cls._create_parser("email", provider, **kwargs)
@@ -0,0 +1,32 @@
1
+ """Parser providers package.
2
+
3
+ This package contains implementations of parsers for different file formats.
4
+ Each parser provider follows the standard msgflux parser interface.
5
+
6
+ Available parsers:
7
+ - PyPDFPdfParser: PDF parsing using pypdf
8
+ - OpenPyxlXlsxParser: Excel parsing using openpyxl
9
+ - PythonPptxPptxParser: PowerPoint parsing using python-pptx
10
+ - PythonDocxDocxParser: Word document parsing using python-docx
11
+ - StandardCsvParser: CSV/TSV parsing using Python csv module
12
+ - BeautifulSoupHtmlParser: HTML parsing using BeautifulSoup4
13
+ - StandardEmailParser: Email (.eml) parsing using Python email module
14
+ """
15
+
16
+ from msgflux.data.parsers.providers.csv_parser import StandardCsvParser
17
+ from msgflux.data.parsers.providers.email_parser import StandardEmailParser
18
+ from msgflux.data.parsers.providers.html_parser import BeautifulSoupHtmlParser
19
+ from msgflux.data.parsers.providers.openpyxl import OpenPyxlXlsxParser
20
+ from msgflux.data.parsers.providers.pypdf import PyPDFPdfParser
21
+ from msgflux.data.parsers.providers.python_docx import PythonDocxDocxParser
22
+ from msgflux.data.parsers.providers.python_pptx import PythonPptxPptxParser
23
+
24
+ __all__ = [
25
+ "BeautifulSoupHtmlParser",
26
+ "OpenPyxlXlsxParser",
27
+ "PyPDFPdfParser",
28
+ "PythonDocxDocxParser",
29
+ "PythonPptxPptxParser",
30
+ "StandardCsvParser",
31
+ "StandardEmailParser",
32
+ ]