3 Commits
7 changed files with 47 additions and 7 deletions
+3 -3
View File
@@ -28,7 +28,7 @@ powershell -c "irm https://astral.sh/uv/install.sh | iex"
uv tool install https://github.com/shadoll/moma/releases/latest/download/moma-latest.tar.gz
# Specific version
uv tool install https://github.com/shadoll/moma/releases/download/v0.9.7/moma-0.9.7-py3-none-any.whl
uv tool install https://github.com/shadoll/moma/releases/download/v0.9.9/moma-0.9.9-py3-none-any.whl
# From PyPI (when published)
uv tool install moma
@@ -40,7 +40,7 @@ uv tool install moma
uv tool install --force https://github.com/shadoll/moma/releases/latest/download/moma-latest.tar.gz
# Upgrade to a newer specific version
uv tool install --force https://github.com/shadoll/moma/releases/download/v0.9.7/moma-0.9.7-py3-none-any.whl
uv tool install --force https://github.com/shadoll/moma/releases/download/v0.9.9/moma-0.9.9-py3-none-any.whl
```
#### Usage
@@ -56,7 +56,7 @@ moma /path/to/directory # Scan specific directory
pip install https://github.com/shadoll/moma/releases/latest/download/moma-latest.tar.gz
# Specific version
pip install https://github.com/shadoll/moma/releases/download/v0.9.7/moma-0.9.7-py3-none-any.whl
pip install https://github.com/shadoll/moma/releases/download/v0.9.9/moma-0.9.9-py3-none-any.whl
```
### Method 3: Development Installation
+1 -1
View File
@@ -1,6 +1,6 @@
[project]
name = "moma"
version = "0.9.7"
version = "0.9.9"
description = "Terminal-based media file renamer and metadata viewer"
readme = "README.md"
requires-python = ">=3.12"
+1
View File
@@ -123,6 +123,7 @@ class MediaExtractor:
"3d_layout": {
"sources": [
("MediaInfo", "extract_3d_layout"),
("Filename", "extract_3d_layout"),
("Default", "extract_3d_layout"),
],
},
+27
View File
@@ -251,6 +251,33 @@ class FilenameExtractor:
return None
@cached_method()
def extract_3d_layout(self) -> str | None:
"""Extract 3D stereoscopic layout from filename or extension"""
# Ordered by specificity: most specific patterns first
patterns = [
(r'\b3D-SBS\b', '3D-SBS'),
(r'\b3D-OU\b', '3D-OU'),
(r'\b3D-HSBS\b', '3D-HSBS'),
(r'\b3D-HOU\b', '3D-HOU'),
(r'\bHalf[-.]?SBS\b', '3D-HSBS'),
(r'\bHalf[-.]?OU\b', '3D-HOU'),
(r'\bHSBS\b', '3D-HSBS'),
(r'\bHOU\b', '3D-HOU'),
(r'\bSBS\b', '3D-SBS'),
(r'\bOU\b', '3D-OU'),
(r'\b3D\b', '3D'),
]
for pattern, result in patterns:
if re.search(pattern, self.file_name, re.IGNORECASE):
return result
# Fall back to mk3d extension as a 3D indicator
if self.file_path.suffix.lower() == '.mk3d':
return '3D'
return None
@cached_method()
def extract_movie_db(self) -> list[str] | None:
"""Extract movie database identifier from filename"""
+7 -1
View File
@@ -213,7 +213,8 @@ class MediaInfoExtractor:
# Determine scan type from available attributes
# Check scan_type first (e.g., "Interlaced", "Progressive", "MBAFF")
if scan_type_attr and isinstance(scan_type_attr, str):
scan_type = "i" if "interlaced" in scan_type_attr.lower() else "p"
scan_lower = scan_type_attr.lower()
scan_type = "i" if ("interlaced" in scan_lower or "mbaff" in scan_lower) else "p"
logger.debug(
f"[{self.file_path.name}] Using scan_type: {scan_type_attr!r} -> scan_type={scan_type!r}"
)
@@ -388,6 +389,11 @@ class MediaInfoExtractor:
# Use the constants function to get extension from format
ext = get_extension_from_format(format_)
# Preserve mk3d extension when the source file already has it,
# even if MediaInfo doesn't report stereoscopic metadata
if self.file_path.suffix.lower() == '.mk3d':
return 'mk3d'
# Special case: Matroska 3D uses mk3d extension
if ext == "mkv" and self.is_3d():
return "mk3d"
+7 -1
View File
@@ -48,6 +48,12 @@ class ProposedFilenameView:
"""Get the frame class"""
return self._extractor.get("frame_class") or ""
@property
@conditional_decorators.wrap(",")
def _3d_layout(self) -> str:
"""Get the 3D layout formatted with a leading comma if present"""
return self._extractor.get("3d_layout")
@property
@conditional_decorators.wrap(",")
def _hdr(self) -> str:
@@ -81,7 +87,7 @@ class ProposedFilenameView:
@property
def rename_line(self) -> str:
"""Generate the proposed filename."""
result = f"{self._order}{self._title}{self._year}{self._special_info}{self._source} [{self._frame_class}{self._hdr},{self._audio_langs}]{self._db_info}.{self._extension}"
result = f"{self._order}{self._title}{self._year}{self._special_info}{self._source} [{self._frame_class}{self._3d_layout}{self._hdr},{self._audio_langs}]{self._db_info}.{self._extension}"
return result.replace("/", "-").replace("\\", "-")
def rename_line_formatted(self, file_path) -> str:
Generated
+1 -1
View File
@@ -208,7 +208,7 @@ wheels = [
[[package]]
name = "moma"
version = "0.9.7"
version = "0.9.9"
source = { editable = "." }
dependencies = [
{ name = "langcodes" },