refactor: consolidate FileInput and MIME type definitions

This commit is contained in:
Greyson LaLonde
2026-01-22 10:15:32 -05:00
parent da930fa1df
commit e2a5177da2
12 changed files with 54 additions and 130 deletions

View File

@@ -6,24 +6,25 @@ from crewai.files.cleanup import (
cleanup_uploaded_files,
)
from crewai.files.content_types import (
AudioContentType,
AudioExtension,
AudioFile,
AudioMimeType,
BaseFile,
File,
FileInput,
FileMode,
ImageContentType,
ImageExtension,
ImageFile,
ImageMimeType,
PDFContentType,
PDFExtension,
PDFFile,
TextContentType,
TextExtension,
TextFile,
VideoContentType,
VideoExtension,
VideoFile,
VideoMimeType,
)
from crewai.files.file import (
FileBytes,
@@ -74,9 +75,6 @@ from crewai.files.upload_cache import (
from crewai.files.uploaders import FileUploader, UploadResult, get_uploader
FileInput = AudioFile | File | ImageFile | PDFFile | TextFile | VideoFile
def wrap_file_source(source: FileSource) -> FileInput:
"""Wrap a FileSource in the appropriate typed FileInput wrapper.
@@ -146,9 +144,9 @@ __all__ = [
"GEMINI_CONSTRAINTS",
"OPENAI_CONSTRAINTS",
"AudioConstraints",
"AudioContentType",
"AudioExtension",
"AudioFile",
"AudioMimeType",
"BaseFile",
"CachedUpload",
"File",
@@ -169,9 +167,9 @@ __all__ = [
"FileUploader",
"FileValidationError",
"ImageConstraints",
"ImageContentType",
"ImageExtension",
"ImageFile",
"ImageMimeType",
"InlineBase64",
"InlineBytes",
"PDFConstraints",
@@ -191,9 +189,9 @@ __all__ = [
"UploadResult",
"UrlReference",
"VideoConstraints",
"VideoContentType",
"VideoExtension",
"VideoFile",
"VideoMimeType",
"cleanup_expired_files",
"cleanup_provider_files",
"cleanup_uploaded_files",

View File

@@ -70,9 +70,19 @@ FileMode = Literal["strict", "auto", "warn", "chunk"]
ImageExtension = Literal[
".png", ".jpg", ".jpeg", ".gif", ".webp", ".bmp", ".tiff", ".tif", ".svg"
".png",
".jpg",
".jpeg",
".gif",
".webp",
".bmp",
".tiff",
".tif",
".svg",
".heic",
".heif",
]
ImageContentType = Literal[
ImageMimeType = Literal[
"image/png",
"image/jpeg",
"image/gif",
@@ -80,6 +90,8 @@ ImageContentType = Literal[
"image/bmp",
"image/tiff",
"image/svg+xml",
"image/heic",
"image/heif",
]
PDFExtension = Literal[".pdf"]
@@ -116,13 +128,15 @@ TextContentType = Literal[
AudioExtension = Literal[
".mp3", ".wav", ".ogg", ".flac", ".aac", ".m4a", ".wma", ".aiff", ".opus"
]
AudioContentType = Literal[
AudioMimeType = Literal[
"audio/mp3",
"audio/mpeg",
"audio/wav",
"audio/x-wav",
"audio/ogg",
"audio/flac",
"audio/aac",
"audio/m4a",
"audio/mp4",
"audio/x-ms-wma",
"audio/aiff",
@@ -132,15 +146,15 @@ AudioContentType = Literal[
VideoExtension = Literal[
".mp4", ".avi", ".mkv", ".mov", ".webm", ".flv", ".wmv", ".m4v", ".mpeg", ".mpg"
]
VideoContentType = Literal[
VideoMimeType = Literal[
"video/mp4",
"video/mpeg",
"video/webm",
"video/quicktime",
"video/x-msvideo",
"video/x-matroska",
"video/quicktime",
"video/webm",
"video/x-flv",
"video/x-ms-wmv",
"video/mpeg",
]
@@ -265,3 +279,6 @@ class File(BaseFile):
>>> image_file = File(source="./image.png")
>>> bytes_file = File(source=b"file content")
"""
FileInput = AudioFile | File | ImageFile | PDFFile | TextFile | VideoFile

View File

@@ -3,35 +3,12 @@
from dataclasses import dataclass
from typing import Literal
from crewai.files.content_types import (
AudioMimeType,
ImageMimeType,
VideoMimeType,
)
ImageFormat = Literal[
"image/png",
"image/jpeg",
"image/gif",
"image/webp",
"image/heic",
"image/heif",
]
AudioFormat = Literal[
"audio/mp3",
"audio/mpeg",
"audio/wav",
"audio/ogg",
"audio/flac",
"audio/aac",
"audio/m4a",
"audio/opus",
]
VideoFormat = Literal[
"video/mp4",
"video/mpeg",
"video/webm",
"video/quicktime",
"video/x-msvideo",
"video/x-flv",
]
ProviderName = Literal[
"anthropic",
@@ -41,15 +18,14 @@ ProviderName = Literal[
"azure",
]
# Pre-typed format tuples for common combinations
DEFAULT_IMAGE_FORMATS: tuple[ImageFormat, ...] = (
DEFAULT_IMAGE_FORMATS: tuple[ImageMimeType, ...] = (
"image/png",
"image/jpeg",
"image/gif",
"image/webp",
)
GEMINI_IMAGE_FORMATS: tuple[ImageFormat, ...] = (
GEMINI_IMAGE_FORMATS: tuple[ImageMimeType, ...] = (
"image/png",
"image/jpeg",
"image/gif",
@@ -58,7 +34,7 @@ GEMINI_IMAGE_FORMATS: tuple[ImageFormat, ...] = (
"image/heif",
)
DEFAULT_AUDIO_FORMATS: tuple[AudioFormat, ...] = (
DEFAULT_AUDIO_FORMATS: tuple[AudioMimeType, ...] = (
"audio/mp3",
"audio/mpeg",
"audio/wav",
@@ -68,7 +44,7 @@ DEFAULT_AUDIO_FORMATS: tuple[AudioFormat, ...] = (
"audio/m4a",
)
GEMINI_AUDIO_FORMATS: tuple[AudioFormat, ...] = (
GEMINI_AUDIO_FORMATS: tuple[AudioMimeType, ...] = (
"audio/mp3",
"audio/mpeg",
"audio/wav",
@@ -79,14 +55,14 @@ GEMINI_AUDIO_FORMATS: tuple[AudioFormat, ...] = (
"audio/opus",
)
DEFAULT_VIDEO_FORMATS: tuple[VideoFormat, ...] = (
DEFAULT_VIDEO_FORMATS: tuple[VideoMimeType, ...] = (
"video/mp4",
"video/mpeg",
"video/webm",
"video/quicktime",
)
GEMINI_VIDEO_FORMATS: tuple[VideoFormat, ...] = (
GEMINI_VIDEO_FORMATS: tuple[VideoMimeType, ...] = (
"video/mp4",
"video/mpeg",
"video/webm",
@@ -112,7 +88,7 @@ class ImageConstraints:
max_width: int | None = None
max_height: int | None = None
max_images_per_request: int | None = None
supported_formats: tuple[ImageFormat, ...] = DEFAULT_IMAGE_FORMATS
supported_formats: tuple[ImageMimeType, ...] = DEFAULT_IMAGE_FORMATS
@dataclass(frozen=True)
@@ -140,7 +116,7 @@ class AudioConstraints:
max_size_bytes: int
max_duration_seconds: int | None = None
supported_formats: tuple[AudioFormat, ...] = DEFAULT_AUDIO_FORMATS
supported_formats: tuple[AudioMimeType, ...] = DEFAULT_AUDIO_FORMATS
@dataclass(frozen=True)
@@ -155,7 +131,7 @@ class VideoConstraints:
max_size_bytes: int
max_duration_seconds: int | None = None
supported_formats: tuple[VideoFormat, ...] = DEFAULT_VIDEO_FORMATS
supported_formats: tuple[VideoMimeType, ...] = DEFAULT_VIDEO_FORMATS
@dataclass(frozen=True)

View File

@@ -7,6 +7,7 @@ import logging
from crewai.files.content_types import (
AudioFile,
File,
FileInput,
ImageFile,
PDFFile,
TextFile,
@@ -36,8 +37,6 @@ from crewai.files.processing.validators import validate_file
logger = logging.getLogger(__name__)
FileInput = AudioFile | File | ImageFile | PDFFile | TextFile | VideoFile
class FileProcessor:
"""Processes files according to provider constraints and per-file mode mode.

View File

@@ -6,7 +6,7 @@ import logging
from crewai.files.content_types import (
AudioFile,
File,
FileInput,
ImageFile,
PDFFile,
TextFile,
@@ -28,8 +28,6 @@ from crewai.files.processing.exceptions import (
logger = logging.getLogger(__name__)
FileInput = AudioFile | File | ImageFile | PDFFile | TextFile | VideoFile
def _get_image_dimensions(content: bytes) -> tuple[int, int] | None:
"""Get image dimensions using Pillow if available.

View File

@@ -6,14 +6,7 @@ from dataclasses import dataclass, field
import hashlib
import logging
from crewai.files.content_types import (
AudioFile,
File,
ImageFile,
PDFFile,
TextFile,
VideoFile,
)
from crewai.files.content_types import FileInput
from crewai.files.metrics import measure_operation
from crewai.files.processing.constraints import (
AudioConstraints,
@@ -36,8 +29,6 @@ from crewai.files.uploaders.base import FileUploader
logger = logging.getLogger(__name__)
FileInput = AudioFile | File | ImageFile | PDFFile | TextFile | VideoFile
UPLOAD_MAX_RETRIES = 3
UPLOAD_RETRY_DELAY_BASE = 2

View File

@@ -17,16 +17,7 @@ from aiocache.serializers import PickleSerializer # type: ignore[import-untyped
if TYPE_CHECKING:
from crewai.files.content_types import (
AudioFile,
File,
ImageFile,
PDFFile,
TextFile,
VideoFile,
)
FileInput = AudioFile | File | ImageFile | PDFFile | TextFile | VideoFile
from crewai.files.content_types import FileInput
logger = logging.getLogger(__name__)

View File

@@ -7,22 +7,13 @@ import logging
import os
from typing import Any
from crewai.files.content_types import (
AudioFile,
File,
ImageFile,
PDFFile,
TextFile,
VideoFile,
)
from crewai.files.content_types import FileInput
from crewai.files.processing.exceptions import classify_upload_error
from crewai.files.uploaders.base import FileUploader, UploadResult
logger = logging.getLogger(__name__)
FileInput = AudioFile | File | ImageFile | PDFFile | TextFile | VideoFile
class AnthropicFileUploader(FileUploader):
"""Uploader for Anthropic Files API.

View File

@@ -6,17 +6,7 @@ from dataclasses import dataclass
from datetime import datetime
from typing import Any
from crewai.files.content_types import (
AudioFile,
File,
ImageFile,
PDFFile,
TextFile,
VideoFile,
)
FileInput = AudioFile | File | ImageFile | PDFFile | TextFile | VideoFile
from crewai.files.content_types import FileInput
@dataclass

View File

@@ -8,14 +8,7 @@ import os
from pathlib import Path
from typing import Any
from crewai.files.content_types import (
AudioFile,
File,
ImageFile,
PDFFile,
TextFile,
VideoFile,
)
from crewai.files.content_types import FileInput
from crewai.files.file import FileBytes, FilePath
from crewai.files.processing.exceptions import (
PermanentUploadError,
@@ -26,8 +19,6 @@ from crewai.files.uploaders.base import FileUploader, UploadResult
logger = logging.getLogger(__name__)
FileInput = AudioFile | File | ImageFile | PDFFile | TextFile | VideoFile
MULTIPART_THRESHOLD = 8 * 1024 * 1024
MULTIPART_CHUNKSIZE = 8 * 1024 * 1024
MAX_CONCURRENCY = 10

View File

@@ -12,14 +12,7 @@ import random
import time
from typing import Any
from crewai.files.content_types import (
AudioFile,
File,
ImageFile,
PDFFile,
TextFile,
VideoFile,
)
from crewai.files.content_types import FileInput
from crewai.files.file import FilePath
from crewai.files.processing.exceptions import (
PermanentUploadError,
@@ -31,8 +24,6 @@ from crewai.files.uploaders.base import FileUploader, UploadResult
logger = logging.getLogger(__name__)
FileInput = AudioFile | File | ImageFile | PDFFile | TextFile | VideoFile
GEMINI_FILE_TTL = timedelta(hours=48)
BACKOFF_BASE_DELAY = 1.0

View File

@@ -8,14 +8,7 @@ import logging
import os
from typing import Any
from crewai.files.content_types import (
AudioFile,
File,
ImageFile,
PDFFile,
TextFile,
VideoFile,
)
from crewai.files.content_types import FileInput
from crewai.files.file import FileBytes, FilePath, FileStream
from crewai.files.processing.exceptions import (
PermanentUploadError,
@@ -27,8 +20,6 @@ from crewai.files.uploaders.base import FileUploader, UploadResult
logger = logging.getLogger(__name__)
FileInput = AudioFile | File | ImageFile | PDFFile | TextFile | VideoFile
FILES_API_MAX_SIZE = 512 * 1024 * 1024
DEFAULT_UPLOAD_CHUNK_SIZE = 64 * 1024 * 1024