461bf6fd40
CI / lint (3.11) (push) Blocked by required conditions
CI / lint (3.12) (push) Blocked by required conditions
CI / lint (3.13) (push) Blocked by required conditions
CI / shellcheck (push) Waiting to run
CI / shfmt (push) Waiting to run
CI / setup (3.11) (push) Waiting to run
CI / setup (3.12) (push) Waiting to run
CI / setup (3.13) (push) Waiting to run
CI / check-licenses (3.12) (push) Blocked by required conditions
CI / test_unit (3.11) (push) Blocked by required conditions
CI / test_unit (3.12) (push) Blocked by required conditions
CI / test_unit (3.13) (push) Blocked by required conditions
CI / test_unit_no_extras (3.11) (push) Blocked by required conditions
CI / test_unit_no_extras (3.12) (push) Blocked by required conditions
CI / test_json_to_html (3.12) (push) Blocked by required conditions
CI / test_unit_no_extras (3.13) (push) Blocked by required conditions
CI / test_unit_dependency_extras (csv, 3.11, --extra csv) (push) Blocked by required conditions
CI / test_unit_dependency_extras (csv, 3.12, --extra csv) (push) Blocked by required conditions
CI / test_unit_dependency_extras (csv, 3.13, --extra csv) (push) Blocked by required conditions
CI / test_unit_dependency_extras (docx, 3.11, --extra docx) (push) Blocked by required conditions
CI / test_unit_dependency_extras (docx, 3.12, --extra docx) (push) Blocked by required conditions
CI / test_unit_dependency_extras (docx, 3.13, --extra docx) (push) Blocked by required conditions
CI / test_unit_dependency_extras (markdown, 3.11, --extra md) (push) Blocked by required conditions
CI / test_unit_dependency_extras (markdown, 3.12, --extra md) (push) Blocked by required conditions
CI / test_unit_dependency_extras (markdown, 3.13, --extra md) (push) Blocked by required conditions
CI / test_unit_dependency_extras (odt, 3.11, --extra odt) (push) Blocked by required conditions
CI / test_unit_dependency_extras (odt, 3.12, --extra odt) (push) Blocked by required conditions
CI / test_unit_dependency_extras (pdf-image, 3.12, --extra pdf --extra image --extra paddleocr) (push) Blocked by required conditions
CI / test_unit_dependency_extras (pdf-image, 3.13, --extra pdf --extra image --extra paddleocr) (push) Blocked by required conditions
CI / test_unit_dependency_extras (pptx, 3.13, --extra pptx) (push) Blocked by required conditions
CI / test_unit_dependency_extras (odt, 3.13, --extra odt) (push) Blocked by required conditions
CI / test_unit_dependency_extras (pdf-image, 3.11, --extra pdf --extra image --extra paddleocr) (push) Blocked by required conditions
CI / test_unit_dependency_extras (pptx, 3.11, --extra pptx) (push) Blocked by required conditions
CI / test_unit_dependency_extras (pptx, 3.12, --extra pptx) (push) Blocked by required conditions
CI / test_unit_dependency_extras (pypandoc, 3.11, --extra epub --extra org --extra rtf --extra rst) (push) Blocked by required conditions
CI / test_unit_dependency_extras (pypandoc, 3.12, --extra epub --extra org --extra rtf --extra rst) (push) Blocked by required conditions
CI / test_unit_dependency_extras (pypandoc, 3.13, --extra epub --extra org --extra rtf --extra rst) (push) Blocked by required conditions
CI / test_unit_dependency_extras (xlsx, 3.11, --extra xlsx) (push) Blocked by required conditions
CI / test_unit_dependency_extras (xlsx, 3.12, --extra xlsx) (push) Blocked by required conditions
CI / test_unit_dependency_extras (xlsx, 3.13, --extra xlsx) (push) Blocked by required conditions
CI / test_ingest_src (3.12) (push) Blocked by required conditions
CI / test_json_to_markdown (3.12) (push) Blocked by required conditions
CI / changelog (push) Waiting to run
CI / test_dockerfile (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Build And Push Docker Image / set-short-sha (push) Waiting to run
Build And Push Docker Image / build-images (linux/amd64, opensource-linux-8core) (push) Blocked by required conditions
Build And Push Docker Image / build-images (linux/arm64, ubuntu-24.04-arm) (push) Blocked by required conditions
Build And Push Docker Image / publish-images (push) Blocked by required conditions
Partition Benchmark / setup (push) Waiting to run
Partition Benchmark / Measure and compare partition() runtime (push) Blocked by required conditions
592 lines
18 KiB
Python
592 lines
18 KiB
Python
"""Domain-model for file-types."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import enum
|
|
from typing import TYPE_CHECKING, Callable, Iterable, Type, cast
|
|
|
|
from typing_extensions import ParamSpec
|
|
|
|
if TYPE_CHECKING:
|
|
from unstructured.documents.elements import Element
|
|
else:
|
|
Element = None
|
|
|
|
|
|
def _create_file_type_enum(
|
|
cls: Type["FileType"],
|
|
value: str,
|
|
partitioner_shortname: str | None,
|
|
importable_package_dependencies: Iterable[str],
|
|
extra_name: str | None,
|
|
extensions: Iterable[str],
|
|
canonical_mime_type: str,
|
|
alias_mime_types: Iterable[str],
|
|
partitioner_full_module_path: str | None = None,
|
|
) -> "FileType":
|
|
"""
|
|
Moving here instead of directly in the FileType.__new__ allows us
|
|
to dynamically create new enum properties.
|
|
|
|
FileType.__new__ does not work with dynamic properties.
|
|
"""
|
|
val = object.__new__(cls)
|
|
val._value_ = value
|
|
val._partitioner_shortname = partitioner_shortname
|
|
val._importable_package_dependencies = tuple(importable_package_dependencies)
|
|
val._extra_name = extra_name
|
|
val._extensions = tuple(extensions)
|
|
val._canonical_mime_type = canonical_mime_type
|
|
val._alias_mime_types = tuple(alias_mime_types)
|
|
val._partitioner_full_module_path = partitioner_full_module_path
|
|
return val
|
|
|
|
|
|
class FileType(enum.Enum):
|
|
"""The collection of file-types recognized by `unstructured`.
|
|
|
|
Note not all of these can be partitioned, e.g. ZIP has no partitioner.
|
|
"""
|
|
|
|
_partitioner_shortname: str | None
|
|
"""Like "docx", from which partitioner module and function-name can be derived via template."""
|
|
|
|
_importable_package_dependencies: tuple[str, ...]
|
|
"""Packages that must be available for import for this file-type's partitioner to work."""
|
|
|
|
_extra_name: str | None
|
|
"""`pip install` extra that provides package dependencies for this file-type."""
|
|
|
|
_extensions: tuple[str, ...]
|
|
"""Filename-extensions recognized as this file-type. Use for secondary identification only."""
|
|
|
|
_canonical_mime_type: str
|
|
"""The MIME-type used as `.metadata.filetype` for this file-type."""
|
|
|
|
_alias_mime_types: tuple[str, ...]
|
|
"""MIME-types accepted as identifying this file-type."""
|
|
|
|
_partitioner_full_module_path: str | None
|
|
"""Fully-qualified name of module providing partitioner for this file-type."""
|
|
|
|
def __new__(
|
|
cls,
|
|
value: str,
|
|
partitioner_shortname: str | None,
|
|
importable_package_dependencies: Iterable[str],
|
|
extra_name: str | None,
|
|
extensions: Iterable[str],
|
|
canonical_mime_type: str,
|
|
alias_mime_types: Iterable[str],
|
|
partitioner_full_module_path: str | None = None,
|
|
):
|
|
return _create_file_type_enum(
|
|
cls,
|
|
value,
|
|
partitioner_shortname,
|
|
importable_package_dependencies,
|
|
extra_name,
|
|
extensions,
|
|
canonical_mime_type,
|
|
alias_mime_types,
|
|
partitioner_full_module_path,
|
|
)
|
|
|
|
def __lt__(self, other: FileType) -> bool:
|
|
"""Makes `FileType` members comparable with relational operators, at least with `<`.
|
|
|
|
This makes them sortable, in particular it supports sorting for pandas groupby functions.
|
|
"""
|
|
return self.name < other.name
|
|
|
|
@classmethod
|
|
def from_extension(cls, extension: str | None) -> FileType | None:
|
|
"""Select a FileType member based on an extension.
|
|
|
|
`extension` must include the leading period, like `".pdf"`. Extension is suitable as a
|
|
secondary file-type identification method but is unreliable for primary identification.
|
|
|
|
Returns `None` when `extension` is not registered for any supported file-type.
|
|
"""
|
|
if extension in (None, "", "."):
|
|
return None
|
|
# -- not super efficient but plenty fast enough for once-or-twice-per-file use and avoids
|
|
# -- limitations on defining a class variable on an Enum.
|
|
for m in cls.__members__.values():
|
|
if extension in m._extensions:
|
|
return m
|
|
return None
|
|
|
|
@classmethod
|
|
def from_mime_type(cls, mime_type: str | None) -> FileType | None:
|
|
"""Select a FileType member based on a MIME-type.
|
|
|
|
Returns `None` when `mime_type` is `None` or does not map to the canonical MIME-type of a
|
|
`FileType` member or one of its alias MIME-types.
|
|
"""
|
|
if mime_type is None:
|
|
return None
|
|
# -- not super efficient but plenty fast enough for once-or-twice-per-file use and avoids
|
|
# -- limitations on defining a class variable on an Enum.
|
|
for m in cls.__members__.values():
|
|
if mime_type == m._canonical_mime_type or mime_type in m._alias_mime_types:
|
|
return m
|
|
return None
|
|
|
|
@property
|
|
def extra_name(self) -> str | None:
|
|
"""The `pip` "extra" that must be installed to provide this file-type's dependencies.
|
|
|
|
Like "image" for PNG, as in `pip install "unstructured[image]"`.
|
|
|
|
`None` when partitioning this file-type requires only the base `unstructured` install.
|
|
"""
|
|
return self._extra_name
|
|
|
|
@property
|
|
def importable_package_dependencies(self) -> tuple[str, ...]:
|
|
"""Packages that must be importable for this file-type's partitioner to work.
|
|
|
|
In general, these are the packages provided by the `pip install` "extra" for this file-type,
|
|
like `pip install "unstructured[docx]"` loads the `python-docx` package.
|
|
|
|
Note that these names are the ones used in an `import` statement, which is not necessarily
|
|
the same as the _distribution_ package name used by `pip`. For example, the DOCX
|
|
distribution package name is `"python-docx"` whereas the _importable_ package name is
|
|
`"docx"`. This latter name as it appears like `import docx` is what is provided by this
|
|
property.
|
|
|
|
The return value is an empty tuple for file-types that do not require optional dependencies.
|
|
|
|
Note this property does not complain when accessed on a non-partitionable file-type, it
|
|
simply returns an empty tuple because file-types that are not partitionable require no
|
|
optional dependencies.
|
|
"""
|
|
return self._importable_package_dependencies
|
|
|
|
@property
|
|
def is_partitionable(self) -> bool:
|
|
"""True when there is a partitioner for this file-type.
|
|
|
|
Note this does not check whether the dependencies for this file-type are installed so
|
|
attempting to partition a file of this type may still fail. This is meant for
|
|
distinguishing file-types like ZIP, EMPTY, and UNK which are legitimate file-types
|
|
but have no associated partitioner.
|
|
"""
|
|
return bool(self._partitioner_shortname) or bool(self._partitioner_full_module_path)
|
|
|
|
@property
|
|
def mime_type(self) -> str:
|
|
"""The canonical MIME-type for this file-type, suitable for use in metadata.
|
|
|
|
This value is used in `.metadata.filetype` for elements partitioned from files of this
|
|
type. In general it is the "offical", "recommended", or "defacto-standard" MIME-type for
|
|
files of this type, in that order, as available.
|
|
"""
|
|
return self._canonical_mime_type
|
|
|
|
@property
|
|
def partitioner_function_name(self) -> str:
|
|
"""Name of partitioner function for this file-type. Like "partition_docx".
|
|
|
|
Raises when this property is accessed on a file-type that is not partitionable. Use
|
|
`.is_partitionable` to avoid exceptions when partitionability is unknown.
|
|
"""
|
|
# -- Raise when this property is accessed on a FileType member that has no partitioner
|
|
# -- shortname. This prevents a harder-to-find bug from appearing far away from this call
|
|
# -- when code would try to `getattr(module, None)` or whatever.
|
|
if full_module_path := self._partitioner_full_module_path:
|
|
return full_module_path.split(".")[-1]
|
|
|
|
if (shortname := self._partitioner_shortname) is None:
|
|
raise ValueError(
|
|
f"`.partitioner_function_name` is undefined because FileType.{self.name} is not"
|
|
f" partitionable. Use `.is_partitionable` to determine whether a `FileType`"
|
|
f" is partitionable."
|
|
)
|
|
return f"partition_{shortname}"
|
|
|
|
@property
|
|
def partitioner_module_qname(self) -> str:
|
|
"""Fully-qualified name of module providing partitioner for this file-type.
|
|
|
|
e.g. "unstructured.partition.docx" for FileType.DOCX.
|
|
"""
|
|
# -- Raise when this property is accessed on a FileType member that has no partitioner
|
|
# -- shortname. This prevents a harder-to-find bug from appearing far away from this call
|
|
# -- when code would try to `importlib.import_module(None)` or whatever.
|
|
if full_module_path := self._partitioner_full_module_path:
|
|
return ".".join(full_module_path.split(".")[:-1])
|
|
|
|
if (shortname := self._partitioner_shortname) is None:
|
|
raise ValueError(
|
|
f"`.partitioner_module_qname` is undefined because FileType.{self.name} is not"
|
|
f" partitionable. Use `.is_partitionable` to determine whether a `FileType`"
|
|
f" is partitionable."
|
|
)
|
|
return f"unstructured.partition.{shortname}"
|
|
|
|
@property
|
|
def partitioner_shortname(self) -> str | None:
|
|
"""Familiar name of partitioner, like "image" for file-types that use `partition_image()`.
|
|
|
|
One use is to determine whether a file-type is one of the five image types, all of which
|
|
are processed by `partition_image()`.
|
|
|
|
`None` for file-types that are not partitionable, although `.is_partitionable` is the
|
|
preferred way of discovering that.
|
|
"""
|
|
return self._partitioner_shortname
|
|
|
|
BMP = (
|
|
"bmp", # -- value for this Enum member, like BMP = "bmp" in a simple enum --
|
|
"image", # -- partitioner_shortname --
|
|
["unstructured_inference"], # -- importable_package_dependencies --
|
|
"image", # -- extra_name - like `pip install "unstructured[image]"` in this case --
|
|
[".bmp"], # -- extensions - filename extensions that map to this file-type --
|
|
"image/bmp", # -- canonical_mime_type - MIME-type written to `.metadata.filetype` --
|
|
[
|
|
"image/x-bmp",
|
|
"image/x-ms-bmp", # returned by older libmagic versions
|
|
],
|
|
)
|
|
CSV = (
|
|
"csv",
|
|
"csv",
|
|
["pandas"],
|
|
"csv",
|
|
[".csv"],
|
|
"text/csv",
|
|
[
|
|
"application/csv",
|
|
"application/x-csv",
|
|
"text/comma-separated-values",
|
|
"text/x-comma-separated-values",
|
|
"text/x-csv",
|
|
],
|
|
)
|
|
DOC = ("doc", "doc", ["docx"], "doc", [".doc"], "application/msword", cast(list[str], []))
|
|
DOCX = (
|
|
"docx",
|
|
"docx",
|
|
["docx"],
|
|
"docx",
|
|
[".docx"],
|
|
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
|
cast(list[str], []),
|
|
)
|
|
EML = (
|
|
"eml",
|
|
"email",
|
|
cast(list[str], []),
|
|
None,
|
|
[".eml", ".p7s"],
|
|
"message/rfc822",
|
|
cast(list[str], []),
|
|
)
|
|
EPUB = (
|
|
"epub",
|
|
"epub",
|
|
["pypandoc"],
|
|
"epub",
|
|
[".epub"],
|
|
"application/epub",
|
|
["application/epub+zip"],
|
|
)
|
|
FLAC = (
|
|
"flac",
|
|
"audio",
|
|
cast(list[str], []), # STT agent deps validated at runtime by the chosen agent
|
|
"audio",
|
|
[".flac"],
|
|
"audio/flac",
|
|
["audio/x-flac"],
|
|
)
|
|
HEIC = (
|
|
"heic",
|
|
"image",
|
|
["unstructured_inference"],
|
|
"image",
|
|
[".heic"],
|
|
"image/heic",
|
|
["image/x-heic"],
|
|
)
|
|
HTML = (
|
|
"html",
|
|
"html",
|
|
cast(list[str], []),
|
|
None,
|
|
[".html", ".htm"],
|
|
"text/html",
|
|
cast(list[str], []),
|
|
)
|
|
JPG = (
|
|
"jpg",
|
|
"image",
|
|
["unstructured_inference"],
|
|
"image",
|
|
[".jpeg", ".jpg"],
|
|
"image/jpeg",
|
|
cast(list[str], []),
|
|
)
|
|
JSON = (
|
|
"json",
|
|
"json",
|
|
cast(list[str], []),
|
|
None,
|
|
[".json"],
|
|
"application/json",
|
|
cast(list[str], []),
|
|
)
|
|
M4A = (
|
|
"m4a",
|
|
"audio",
|
|
cast(list[str], []), # STT agent deps validated at runtime by the chosen agent
|
|
"audio",
|
|
[".m4a"],
|
|
"audio/mp4",
|
|
["audio/x-m4a"],
|
|
)
|
|
MD = ("md", "md", ["markdown"], "md", [".md"], "text/markdown", ["text/x-markdown"])
|
|
MP3 = (
|
|
"mp3",
|
|
"audio",
|
|
cast(list[str], []), # STT agent deps validated at runtime by the chosen agent
|
|
"audio",
|
|
[".mp3"],
|
|
"audio/mpeg",
|
|
["audio/mp3", "audio/x-mp3", "audio/x-mpeg"],
|
|
)
|
|
MSG = (
|
|
"msg",
|
|
"msg",
|
|
["oxmsg"],
|
|
"msg",
|
|
[".msg"],
|
|
"application/vnd.ms-outlook",
|
|
cast(list[str], []),
|
|
)
|
|
NDJSON = (
|
|
"ndjson",
|
|
"ndjson",
|
|
cast(list[str], []),
|
|
None,
|
|
[".ndjson"],
|
|
"application/x-ndjson",
|
|
cast(list[str], []),
|
|
)
|
|
ODT = (
|
|
"odt",
|
|
"odt",
|
|
["docx", "pypandoc"],
|
|
"odt",
|
|
[".odt"],
|
|
"application/vnd.oasis.opendocument.text",
|
|
cast(list[str], []),
|
|
)
|
|
OGG = (
|
|
"ogg",
|
|
"audio",
|
|
cast(list[str], []), # STT agent deps validated at runtime by the chosen agent
|
|
"audio",
|
|
[".ogg", ".oga"],
|
|
"audio/ogg",
|
|
["audio/x-ogg"],
|
|
)
|
|
OPUS = (
|
|
"opus",
|
|
"audio",
|
|
cast(list[str], []), # STT agent deps validated at runtime by the chosen agent
|
|
"audio",
|
|
[".opus"],
|
|
"audio/opus",
|
|
cast(list[str], []),
|
|
)
|
|
ORG = ("org", "org", ["pypandoc"], "org", [".org"], "text/org", cast(list[str], []))
|
|
PDF = (
|
|
"pdf",
|
|
"pdf",
|
|
["pdf2image", "pdfminer", "PIL"],
|
|
"pdf",
|
|
[".pdf"],
|
|
"application/pdf",
|
|
cast(list[str], []),
|
|
)
|
|
PNG = (
|
|
"png",
|
|
"image",
|
|
["unstructured_inference"],
|
|
"image",
|
|
[".png"],
|
|
"image/png",
|
|
cast(list[str], []),
|
|
)
|
|
PPT = (
|
|
"ppt",
|
|
"ppt",
|
|
["pptx"],
|
|
"ppt",
|
|
[".ppt"],
|
|
"application/vnd.ms-powerpoint",
|
|
cast(list[str], []),
|
|
)
|
|
PPTX = (
|
|
"pptx",
|
|
"pptx",
|
|
["pptx"],
|
|
"pptx",
|
|
[".pptx"],
|
|
"application/vnd.openxmlformats-officedocument.presentationml.presentation",
|
|
cast(list[str], []),
|
|
)
|
|
RST = ("rst", "rst", ["pypandoc"], "rst", [".rst"], "text/x-rst", cast(list[str], []))
|
|
RTF = ("rtf", "rtf", ["pypandoc"], "rtf", [".rtf"], "text/rtf", ["application/rtf"])
|
|
TIFF = (
|
|
"tiff",
|
|
"image",
|
|
["unstructured_inference"],
|
|
"image",
|
|
[".tiff"],
|
|
"image/tiff",
|
|
cast(list[str], []),
|
|
)
|
|
TSV = ("tsv", "tsv", ["pandas"], "tsv", [".tab", ".tsv"], "text/tsv", cast(list[str], []))
|
|
TXT = (
|
|
"txt",
|
|
"text",
|
|
cast(list[str], []),
|
|
None,
|
|
[
|
|
".txt",
|
|
".text",
|
|
# NOTE(robinson) - for now we are treating code files as plain text
|
|
".c",
|
|
".cc",
|
|
".cpp",
|
|
".cs",
|
|
".cxx",
|
|
".go",
|
|
".java",
|
|
".js",
|
|
".log",
|
|
".php",
|
|
".py",
|
|
".rb",
|
|
".swift",
|
|
".ts",
|
|
".yaml",
|
|
".yml",
|
|
],
|
|
"text/plain",
|
|
[
|
|
# NOTE(robinson) - In the future, we may have special processing for YAML files
|
|
# instead of treating them as plaintext.
|
|
"text/yaml",
|
|
"application/x-yaml",
|
|
"application/yaml",
|
|
"text/x-yaml",
|
|
],
|
|
)
|
|
WAV = (
|
|
"wav",
|
|
"audio",
|
|
cast(list[str], []), # STT agent deps validated at runtime by the chosen agent
|
|
"audio",
|
|
[".wav"],
|
|
"audio/wav",
|
|
[
|
|
"audio/vnd.wav",
|
|
"audio/vnd.wave",
|
|
"audio/wave",
|
|
"audio/x-pn-wav",
|
|
"audio/x-wav",
|
|
],
|
|
)
|
|
WEBM = (
|
|
"webm",
|
|
"audio",
|
|
cast(list[str], []), # STT agent deps validated at runtime by the chosen agent
|
|
"audio",
|
|
[".webm"],
|
|
"audio/webm",
|
|
[], # Do not alias video/webm: WebM is a container; this type is for audio-only.
|
|
)
|
|
XLS = (
|
|
"xls",
|
|
"xlsx",
|
|
["pandas", "openpyxl"],
|
|
"xlsx",
|
|
[".xls"],
|
|
"application/vnd.ms-excel",
|
|
cast(list[str], []),
|
|
)
|
|
XLSX = (
|
|
"xlsx",
|
|
"xlsx",
|
|
["pandas", "openpyxl"],
|
|
"xlsx",
|
|
[".xlsx"],
|
|
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
|
cast(list[str], []),
|
|
)
|
|
XML = ("xml", "xml", cast(list[str], []), None, [".xml"], "application/xml", ["text/xml"])
|
|
ZIP = ("zip", None, cast(list[str], []), None, [".zip"], "application/zip", cast(list[str], []))
|
|
|
|
UNK = (
|
|
"unk",
|
|
None,
|
|
cast(list[str], []),
|
|
None,
|
|
cast(list[str], []),
|
|
"application/octet-stream",
|
|
cast(list[str], []),
|
|
)
|
|
EMPTY = (
|
|
"empty",
|
|
None,
|
|
cast(list[str], []),
|
|
None,
|
|
cast(list[str], []),
|
|
"inode/x-empty",
|
|
cast(list[str], []),
|
|
)
|
|
|
|
|
|
def create_file_type(
|
|
name: str,
|
|
*,
|
|
canonical_mime_type: str,
|
|
importable_package_dependencies: Iterable[str] | None = None,
|
|
extra_name: str | None = None,
|
|
extensions: Iterable[str] | None = None,
|
|
alias_mime_types: Iterable[str] | None = None,
|
|
) -> FileType:
|
|
"""Register a new FileType member."""
|
|
type_ = _create_file_type_enum(
|
|
FileType,
|
|
name,
|
|
None,
|
|
importable_package_dependencies or cast(list[str], []),
|
|
extra_name,
|
|
extensions or cast(list[str], []),
|
|
canonical_mime_type,
|
|
alias_mime_types or cast(list[str], []),
|
|
None,
|
|
)
|
|
type_._name_ = name
|
|
FileType._member_map_[name] = type_
|
|
return type_
|
|
|
|
|
|
_P = ParamSpec("_P")
|
|
|
|
|
|
def register_partitioner(
|
|
file_type: FileType,
|
|
) -> Callable[[Callable[_P, list[Element]]], Callable[_P, list[Element]]]:
|
|
def decorator(func: Callable[_P, list[Element]]) -> Callable[_P, list[Element]]:
|
|
file_type._partitioner_full_module_path = func.__module__ + "." + func.__name__
|
|
return func
|
|
|
|
return decorator
|