mirror of
https://github.com/shadoll/moma.git
synced 2026-08-28 11:33:25 +00:00
Add comprehensive tests for formatter classes, services, and utilities
- Introduced tests for various formatter classes including TextFormatter, DurationFormatter, SizeFormatter, DateFormatter, and more to ensure correct formatting behavior. - Added tests for service classes such as FileTreeService, MetadataService, and RenameService, covering directory validation, metadata extraction, and file renaming functionalities. - Implemented utility tests for LanguageCodeExtractor, PatternExtractor, and FrameClassMatcher to validate their extraction and matching capabilities. - Updated test cases to use datasets for better maintainability and clarity. - Enhanced error handling tests to ensure robustness against missing or invalid data.
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
"""Constants package for Renamer.
|
||||
|
||||
This package contains constants split into logical modules:
|
||||
- media_constants.py: Media type definitions (MEDIA_TYPES)
|
||||
- source_constants.py: Video source types (SOURCE_DICT)
|
||||
- frame_constants.py: Resolution/frame classes (FRAME_CLASSES)
|
||||
- moviedb_constants.py: Movie database identifiers (MOVIE_DB_DICT)
|
||||
- edition_constants.py: Special edition types (SPECIAL_EDITIONS)
|
||||
- lang_constants.py: Language-related constants (SKIP_WORDS)
|
||||
- year_constants.py: Year validation (CURRENT_YEAR, MIN_VALID_YEAR, etc.)
|
||||
- cyrillic_constants.py: Cyrillic character normalization (CYRILLIC_TO_ENGLISH)
|
||||
"""
|
||||
|
||||
# Import from all constant modules
|
||||
from .media_constants import MEDIA_TYPES
|
||||
from .source_constants import SOURCE_DICT
|
||||
from .frame_constants import FRAME_CLASSES, NON_STANDARD_QUALITY_INDICATORS
|
||||
from .moviedb_constants import MOVIE_DB_DICT
|
||||
from .edition_constants import SPECIAL_EDITIONS
|
||||
from .lang_constants import SKIP_WORDS
|
||||
from .year_constants import CURRENT_YEAR, MIN_VALID_YEAR, YEAR_FUTURE_BUFFER, is_valid_year
|
||||
from .cyrillic_constants import CYRILLIC_TO_ENGLISH
|
||||
|
||||
__all__ = [
|
||||
# Media types
|
||||
'MEDIA_TYPES',
|
||||
# Source types
|
||||
'SOURCE_DICT',
|
||||
# Frame classes
|
||||
'FRAME_CLASSES',
|
||||
'NON_STANDARD_QUALITY_INDICATORS',
|
||||
# Movie databases
|
||||
'MOVIE_DB_DICT',
|
||||
# Special editions
|
||||
'SPECIAL_EDITIONS',
|
||||
# Language constants
|
||||
'SKIP_WORDS',
|
||||
# Year validation
|
||||
'CURRENT_YEAR',
|
||||
'MIN_VALID_YEAR',
|
||||
'YEAR_FUTURE_BUFFER',
|
||||
'is_valid_year',
|
||||
# Cyrillic normalization
|
||||
'CYRILLIC_TO_ENGLISH',
|
||||
]
|
||||
@@ -0,0 +1,21 @@
|
||||
"""Cyrillic character normalization constants.
|
||||
|
||||
This module contains mappings for normalizing Cyrillic characters to their
|
||||
English equivalents for parsing filenames.
|
||||
"""
|
||||
|
||||
# Cyrillic to English character mappings
|
||||
# Used for normalizing Cyrillic characters that look like English letters
|
||||
CYRILLIC_TO_ENGLISH = {
|
||||
'р': 'p', # Cyrillic 'er' looks like Latin 'p'
|
||||
'і': 'i', # Cyrillic 'i' looks like Latin 'i'
|
||||
'о': 'o', # Cyrillic 'o' looks like Latin 'o'
|
||||
'с': 'c', # Cyrillic 'es' looks like Latin 'c'
|
||||
'е': 'e', # Cyrillic 'ie' looks like Latin 'e'
|
||||
'а': 'a', # Cyrillic 'a' looks like Latin 'a'
|
||||
'т': 't', # Cyrillic 'te' looks like Latin 't'
|
||||
'у': 'y', # Cyrillic 'u' looks like Latin 'y'
|
||||
'к': 'k', # Cyrillic 'ka' looks like Latin 'k'
|
||||
'х': 'x', # Cyrillic 'ha' looks like Latin 'x
|
||||
# Add more mappings as needed
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
"""Special edition constants.
|
||||
|
||||
This module defines special edition types (Director's Cut, Extended Edition, etc.)
|
||||
and their aliases for detection in filenames.
|
||||
"""
|
||||
|
||||
SPECIAL_EDITIONS = {
|
||||
"Theatrical Cut": ["Theatrical Cut"],
|
||||
"Director's Cut": ["Director's Cut", "Director Cut"],
|
||||
"Extended Edition": ["Extended Edition", "Ultimate Extended Edition"],
|
||||
"Special Edition": ["Special Edition"],
|
||||
"Collector's Edition": ["Collector's Edition"],
|
||||
"Criterion Collection": ["Criterion Collection"],
|
||||
"Anniversary Edition": ["Anniversary Edition"],
|
||||
"Redux": ["Redux"],
|
||||
"Final Cut": ["Final Cut"],
|
||||
"Alternate Cut": ["Alternate Cut"],
|
||||
"International Cut": ["International Cut"],
|
||||
"Restored Edition": [
|
||||
"Restored Edition",
|
||||
"Restored Version",
|
||||
"4K Restoration",
|
||||
"Restoration",
|
||||
],
|
||||
"Remastered": ["Remastered", "Remaster", "HD Remaster"],
|
||||
"Unrated": ["Unrated"],
|
||||
"Uncensored": ["Uncensored"],
|
||||
"Definitive Edition": ["Definitive Edition"],
|
||||
"Platinum Edition": ["Platinum Edition"],
|
||||
"Gold Edition": ["Gold Edition"],
|
||||
"Diamond Edition": ["Diamond Edition"],
|
||||
"Steelbook Edition": ["Steelbook Edition"],
|
||||
"Limited Edition": ["Limited Edition"],
|
||||
"Deluxe Edition": ["Deluxe Edition"],
|
||||
"Premium Edition": ["Premium Edition"],
|
||||
"Complete Edition": ["Complete Edition"],
|
||||
"AI Remaster": ["AI Remaster", "AI Remastered"],
|
||||
"Upscaled": [
|
||||
"AI Upscaled",
|
||||
"AI Enhanced",
|
||||
"AI Upscale",
|
||||
"Upscaled",
|
||||
"Upscale",
|
||||
"Upscaling",
|
||||
],
|
||||
"Director's Definitive Cut": ["Director's Definitive Cut"],
|
||||
"Extended Director's Cut": ["Extended Director's Cut", "Ultimate Director's Cut"],
|
||||
"Original Cut": ["Original Cut"],
|
||||
"Cinematic Cut": ["Cinematic Cut"],
|
||||
"Roadshow Cut": ["Roadshow Cut"],
|
||||
"Premiere Cut": ["Premiere Cut"],
|
||||
"Festival Cut": ["Festival Cut"],
|
||||
"Workprint": ["Workprint"],
|
||||
"Rough Cut": ["Rough Cut"],
|
||||
"Special Assembly Cut": ["Special Assembly Cut"],
|
||||
"Amazon Edition": ["Amazon Edition", "Amazon", "AMZN"],
|
||||
"Netflix Edition": ["Netflix Edition"],
|
||||
"HBO Edition": ["HBO Edition"],
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
"""Frame class and resolution constants.
|
||||
|
||||
This module defines video resolution frame classes (480p, 720p, 1080p, 4K, 8K, etc.)
|
||||
and their nominal heights and typical widths.
|
||||
|
||||
Also includes non-standard quality indicators that appear in filenames but don't
|
||||
represent specific resolutions.
|
||||
"""
|
||||
|
||||
# Non-standard quality indicators that don't have specific resolution values
|
||||
# These are used in filenames to indicate quality but aren't proper frame classes
|
||||
# When found, we return None instead of trying to classify them
|
||||
# Note: We have specific frame classes like "2160p" (4K) and "4320p" (8K),
|
||||
# but when files use just "4K" or "8K" without the "p" suffix, we can't determine
|
||||
# the exact resolution, so we treat them as non-standard indicators
|
||||
NON_STANDARD_QUALITY_INDICATORS = ['SD', 'LQ', 'HD', 'QHD', 'FHD', 'FullHD', '4K', '8K']
|
||||
|
||||
FRAME_CLASSES = {
|
||||
"480p": {
|
||||
"nominal_height": 480,
|
||||
"typical_widths": [640, 704, 720],
|
||||
"description": "Standard Definition (SD) - DVD quality",
|
||||
},
|
||||
"480i": {
|
||||
"nominal_height": 480,
|
||||
"typical_widths": [640, 704, 720],
|
||||
"description": "Standard Definition (SD) interlaced - NTSC quality",
|
||||
},
|
||||
"360p": {
|
||||
"nominal_height": 360,
|
||||
"typical_widths": [480, 640],
|
||||
"description": "Low Definition (LD) - 360p",
|
||||
},
|
||||
"576p": {
|
||||
"nominal_height": 576,
|
||||
"typical_widths": [720, 768],
|
||||
"description": "PAL Standard Definition (SD) - European DVD quality",
|
||||
},
|
||||
"576i": {
|
||||
"nominal_height": 576,
|
||||
"typical_widths": [720, 768],
|
||||
"description": "PAL Standard Definition (SD) interlaced - European quality",
|
||||
},
|
||||
"720p": {
|
||||
"nominal_height": 720,
|
||||
"typical_widths": [1280],
|
||||
"description": "High Definition (HD) - 720p HD",
|
||||
},
|
||||
"1080p": {
|
||||
"nominal_height": 1080,
|
||||
"typical_widths": [1920],
|
||||
"description": "Full High Definition (FHD) - 1080p HD",
|
||||
},
|
||||
"1080i": {
|
||||
"nominal_height": 1080,
|
||||
"typical_widths": [1920],
|
||||
"description": "Full High Definition (FHD) interlaced - 1080i HD",
|
||||
},
|
||||
"1440p": {
|
||||
"nominal_height": 1440,
|
||||
"typical_widths": [2560],
|
||||
"description": "Quad High Definition (QHD) - 1440p 2K",
|
||||
},
|
||||
"2160p": {
|
||||
"nominal_height": 2160,
|
||||
"typical_widths": [3840],
|
||||
"description": "Ultra High Definition (UHD) - 2160p 4K",
|
||||
},
|
||||
"4320p": {
|
||||
"nominal_height": 4320,
|
||||
"typical_widths": [7680],
|
||||
"description": "Ultra High Definition (UHD) - 4320p 8K",
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
"""Language-related constants for filename parsing.
|
||||
|
||||
This module contains sets of words and patterns used to identify and skip
|
||||
non-language codes when extracting language information from filenames.
|
||||
"""
|
||||
|
||||
# Words to skip when looking for language codes in filenames
|
||||
# These are common words, file extensions, or technical terms that might
|
||||
# look like language codes but aren't
|
||||
SKIP_WORDS = {
|
||||
# Common English words that might look like language codes (2-3 letters)
|
||||
'the', 'and', 'for', 'are', 'but', 'not', 'you', 'all', 'can', 'had',
|
||||
'her', 'was', 'one', 'our', 'out', 'day', 'get', 'has', 'him', 'his',
|
||||
'how', 'its', 'may', 'new', 'now', 'old', 'see', 'two', 'way', 'who',
|
||||
'boy', 'did', 'let', 'put', 'say', 'she', 'too', 'use',
|
||||
|
||||
# File extensions (video)
|
||||
'avi', 'mkv', 'mp4', 'mpg', 'mov', 'wmv', 'flv', 'webm', 'm4v', 'm2ts',
|
||||
'ts', 'vob', 'iso', 'img',
|
||||
|
||||
# Quality/resolution indicators
|
||||
'sd', 'hd', 'lq', 'qhd', 'uhd', 'p', 'i', 'hdr', 'sdr', '4k', '8k',
|
||||
'2160p', '1080p', '720p', '480p', '360p', '240p', '144p',
|
||||
|
||||
# Source/codec indicators
|
||||
'web', 'dl', 'rip', 'bluray', 'dvd', 'hdtv', 'bdrip', 'dvdrip', 'xvid',
|
||||
'divx', 'h264', 'h265', 'x264', 'x265', 'hevc', 'avc',
|
||||
|
||||
# Audio codecs
|
||||
'ma', 'atmos', 'dts', 'aac', 'ac3', 'mp3', 'flac', 'wav', 'wma', 'ogg', 'opus'
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
"""Media type constants for supported video formats.
|
||||
|
||||
This module defines all supported video container formats and their metadata.
|
||||
"""
|
||||
|
||||
MEDIA_TYPES = {
|
||||
"mkv": {
|
||||
"description": "Matroska multimedia container",
|
||||
"meta_type": "Matroska",
|
||||
"mime": "video/x-matroska",
|
||||
},
|
||||
"mk3d": {
|
||||
"description": "Matroska 3D multimedia container",
|
||||
"meta_type": "Matroska",
|
||||
"mime": "video/x-matroska",
|
||||
},
|
||||
"avi": {
|
||||
"description": "Audio Video Interleave",
|
||||
"meta_type": "AVI",
|
||||
"mime": "video/x-msvideo",
|
||||
},
|
||||
"mov": {
|
||||
"description": "QuickTime movie",
|
||||
"meta_type": "QuickTime",
|
||||
"mime": "video/quicktime",
|
||||
},
|
||||
"mp4": {
|
||||
"description": "MPEG-4 video container",
|
||||
"meta_type": "MP4",
|
||||
"mime": "video/mp4",
|
||||
},
|
||||
"wmv": {
|
||||
"description": "Windows Media Video",
|
||||
"meta_type": "ASF",
|
||||
"mime": "video/x-ms-wmv",
|
||||
},
|
||||
"flv": {"description": "Flash Video", "meta_type": "FLV", "mime": "video/x-flv"},
|
||||
"webm": {
|
||||
"description": "WebM multimedia",
|
||||
"meta_type": "WebM",
|
||||
"mime": "video/webm",
|
||||
},
|
||||
"m4v": {"description": "MPEG-4 video", "meta_type": "MP4", "mime": "video/mp4"},
|
||||
"3gp": {"description": "3GPP multimedia", "meta_type": "MP4", "mime": "video/3gpp"},
|
||||
"ogv": {"description": "Ogg Video", "meta_type": "Ogg", "mime": "video/ogg"},
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
"""Movie database identifier constants.
|
||||
|
||||
This module defines movie and TV database services (TMDB, IMDB, Trakt, TVDB)
|
||||
and their identifier patterns.
|
||||
"""
|
||||
|
||||
MOVIE_DB_DICT = {
|
||||
"tmdb": {
|
||||
"name": "The Movie Database (TMDb)",
|
||||
"description": "Community built movie and TV database",
|
||||
"url": "https://www.themoviedb.org/",
|
||||
"patterns": ["tmdbid", "tmdb", "tmdbid-", "tmdb-"],
|
||||
},
|
||||
"imdb": {
|
||||
"name": "Internet Movie Database (IMDb)",
|
||||
"description": "Comprehensive movie, TV, and celebrity database",
|
||||
"url": "https://www.imdb.com/",
|
||||
"patterns": ["imdbid", "imdb", "imdbid-", "imdb-"],
|
||||
},
|
||||
"trakt": {
|
||||
"name": "Trakt.tv",
|
||||
"description": "Service that integrates with media centers for scrobbling",
|
||||
"url": "https://trakt.tv/",
|
||||
"patterns": ["traktid", "trakt", "traktid-", "trakt-"],
|
||||
},
|
||||
"tvdb": {
|
||||
"name": "The TV Database (TVDB)",
|
||||
"description": "Community driven TV database",
|
||||
"url": "https://thetvdb.com/",
|
||||
"patterns": ["tvdbid", "tvdb", "tvdbid-", "tvdb-"],
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
"""Video source type constants.
|
||||
|
||||
This module defines video source types (WEB-DL, BDRip, etc.) and their aliases.
|
||||
"""
|
||||
|
||||
SOURCE_DICT = {
|
||||
"WEB-DL": ["WEB-DL", "WEBRip", "WEB-Rip", "WEB", "WEB-DLRip"],
|
||||
"BDRip": ["BDRip", "BD-Rip", "BDRIP"],
|
||||
"BDRemux": ["BDRemux", "BD-Remux", "BDREMUX"],
|
||||
"DVDRip": ["DVDRip", "DVD-Rip", "DVDRIP"],
|
||||
"HDTVRip": ["HDTVRip", "HDTV"],
|
||||
"BluRay": ["BluRay", "BLURAY", "Blu-ray"],
|
||||
"SATRip": ["SATRip", "SAT-Rip", "SATRIP"],
|
||||
"VHSRecord": [
|
||||
"VHSRecord",
|
||||
"VHS Record",
|
||||
"VHS-Rip",
|
||||
"VHSRip",
|
||||
"VHS",
|
||||
"VHS Tape",
|
||||
"VHS-Tape",
|
||||
],
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
"""Year validation constants for filename parsing.
|
||||
|
||||
This module contains constants used for validating years extracted from filenames.
|
||||
"""
|
||||
|
||||
import datetime
|
||||
|
||||
# Current year for validation
|
||||
CURRENT_YEAR = datetime.datetime.now().year
|
||||
|
||||
# Minimum valid year for movies/media (start of cinema era)
|
||||
MIN_VALID_YEAR = 1900
|
||||
|
||||
# Allow years slightly into the future (for upcoming releases)
|
||||
YEAR_FUTURE_BUFFER = 10
|
||||
|
||||
# Valid year range: MIN_VALID_YEAR to (CURRENT_YEAR + YEAR_FUTURE_BUFFER)
|
||||
def is_valid_year(year: int) -> bool:
|
||||
"""Check if a year is within the valid range for media files."""
|
||||
return MIN_VALID_YEAR <= year <= CURRENT_YEAR + YEAR_FUTURE_BUFFER
|
||||
Reference in New Issue
Block a user