mirror of
https://github.com/shadoll/moma.git
synced 2026-08-28 03:27:34 +00:00
feat: Add OpenScreen for directory input and validation
feat: Introduce poster rendering views with multiple engines feat: Implement ASCII art poster renderer using PIL feat: Create base class for poster renderers feat: Add RichPixels renderer for high-quality terminal image display feat: Implement Viu terminal image viewer renderer feat: Add ProposedFilenameView for generating standardized filenames feat: Create RenameConfirmScreen for renaming files with confirmation feat: Implement SettingsScreen for configuring application settings feat: Add custom PosterWidget for rendering poster images
This commit is contained in:
+1
-1
@@ -8,4 +8,4 @@ wheels/
|
|||||||
# Virtual environments
|
# Virtual environments
|
||||||
.venv
|
.venv
|
||||||
# Test-generated files
|
# Test-generated files
|
||||||
renamer/test/datasets/sample_mediafiles/
|
src/test/datasets/sample_mediafiles/
|
||||||
|
|||||||
Vendored
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"python.testing.pytestArgs": [
|
"python.testing.pytestArgs": [
|
||||||
"renamer"
|
"src"
|
||||||
],
|
],
|
||||||
"python.testing.unittestEnabled": false,
|
"python.testing.unittestEnabled": false,
|
||||||
"python.testing.pytestEnabled": true
|
"python.testing.pytestEnabled": true
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
# Renamer Engineering Guide
|
# moma Engineering Guide
|
||||||
|
|
||||||
**Version**: 0.7.0-dev
|
**Version**: 0.7.0-dev
|
||||||
**Last Updated**: 2026-01-01
|
**Last Updated**: 2026-01-01
|
||||||
**Python**: 3.11+
|
**Python**: 3.11+
|
||||||
**Status**: Active Development
|
**Status**: Active Development
|
||||||
|
|
||||||
This is the comprehensive technical reference for the Renamer project. It contains all architectural information, implementation details, development workflows, and AI assistant instructions.
|
This is the comprehensive technical reference for the moma project. It contains all architectural information, implementation details, development workflows, and AI assistant instructions.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -26,7 +26,7 @@ This is the comprehensive technical reference for the Renamer project. It contai
|
|||||||
|
|
||||||
### Purpose
|
### Purpose
|
||||||
|
|
||||||
Renamer is a sophisticated Terminal User Interface (TUI) application for managing, viewing metadata, and renaming media files. Built with Python and the Textual framework.
|
moma is a sophisticated Terminal User Interface (TUI) application for managing, viewing metadata, and renaming media files. Built with Python and the Textual framework.
|
||||||
|
|
||||||
**Dual-Mode Operation**:
|
**Dual-Mode Operation**:
|
||||||
- **Technical Mode**: Detailed technical metadata (video tracks, audio streams, codecs, bitrates)
|
- **Technical Mode**: Detailed technical metadata (video tracks, audio streams, codecs, bitrates)
|
||||||
@@ -37,7 +37,7 @@ Renamer is a sophisticated Terminal User Interface (TUI) application for managin
|
|||||||
- **Version**: 0.7.0-dev (in development)
|
- **Version**: 0.7.0-dev (in development)
|
||||||
- **Python**: 3.11+
|
- **Python**: 3.11+
|
||||||
- **License**: Not specified
|
- **License**: Not specified
|
||||||
- **Repository**: `/home/sha/bin/renamer`
|
- **Repository**: `/Users/sha/Developer/sha.dev/moma`
|
||||||
|
|
||||||
### Technology Stack
|
### Technology Stack
|
||||||
|
|
||||||
@@ -118,9 +118,9 @@ Renamer is a sophisticated Terminal User Interface (TUI) application for managin
|
|||||||
|
|
||||||
## Core Components
|
## Core Components
|
||||||
|
|
||||||
### 1. Main Application (`renamer/app.py`)
|
### 1. Main Application (`src/app.py`)
|
||||||
|
|
||||||
**Class**: `RenamerApp(App)`
|
**Class**: `MomaApp(App)`
|
||||||
|
|
||||||
**Responsibilities**:
|
**Responsibilities**:
|
||||||
- TUI layout management (split view: file tree + details panel)
|
- TUI layout management (split view: file tree + details panel)
|
||||||
@@ -134,7 +134,7 @@ Renamer is a sophisticated Terminal User Interface (TUI) application for managin
|
|||||||
- Dual-mode support (technical/catalog)
|
- Dual-mode support (technical/catalog)
|
||||||
- Real-time metadata display
|
- Real-time metadata display
|
||||||
|
|
||||||
### 2. Service Layer (`renamer/services/`)
|
### 2. Service Layer (`src/services/`)
|
||||||
|
|
||||||
#### FileTreeService (`file_tree_service.py`)
|
#### FileTreeService (`file_tree_service.py`)
|
||||||
- Directory scanning and validation
|
- Directory scanning and validation
|
||||||
@@ -166,7 +166,7 @@ Renamer is a sophisticated Terminal User Interface (TUI) application for managin
|
|||||||
- Callback-based rename with success/error handlers
|
- Callback-based rename with success/error handlers
|
||||||
- Markup tag stripping
|
- Markup tag stripping
|
||||||
|
|
||||||
### 3. Extractor System (`renamer/extractors/`)
|
### 3. Extractor System (`src/extractors/`)
|
||||||
|
|
||||||
#### Base Protocol (`base.py`)
|
#### Base Protocol (`base.py`)
|
||||||
```python
|
```python
|
||||||
@@ -232,7 +232,7 @@ year = extractor.get("year", source="Filename") # Force specific source
|
|||||||
- Returns None or empty collections
|
- Returns None or empty collections
|
||||||
- Safe final fallback in extractor chain
|
- Safe final fallback in extractor chain
|
||||||
|
|
||||||
### 4. Formatter System (`renamer/formatters/`)
|
### 4. Formatter System (`src/formatters/`)
|
||||||
|
|
||||||
#### Base Classes (`base.py`)
|
#### Base Classes (`base.py`)
|
||||||
- `Formatter`: Base ABC with abstract `format()` method
|
- `Formatter`: Base ABC with abstract `format()` method
|
||||||
@@ -271,7 +271,7 @@ result = FormatterApplier.apply_formatters(1024, formatters)
|
|||||||
- **SpecialInfoFormatter**: Edition/source formatting
|
- **SpecialInfoFormatter**: Edition/source formatting
|
||||||
- **TextFormatter**: Text styling utilities
|
- **TextFormatter**: Text styling utilities
|
||||||
|
|
||||||
### 5. Utility Modules (`renamer/utils/`)
|
### 5. Utility Modules (`src/utils/`)
|
||||||
|
|
||||||
#### PatternExtractor (`pattern_utils.py`)
|
#### PatternExtractor (`pattern_utils.py`)
|
||||||
**Centralized regex pattern matching**:
|
**Centralized regex pattern matching**:
|
||||||
@@ -320,7 +320,7 @@ langs = extractor.extract_from_brackets("[2xUKR_ENG]")
|
|||||||
3. Closest height match
|
3. Closest height match
|
||||||
4. Non-standard quality indicator detection
|
4. Non-standard quality indicator detection
|
||||||
|
|
||||||
### 6. Constants (`renamer/constants/`)
|
### 6. Constants (`src/constants/`)
|
||||||
|
|
||||||
**Modular organization** (8 files):
|
**Modular organization** (8 files):
|
||||||
|
|
||||||
@@ -335,12 +335,12 @@ langs = extractor.extract_from_brackets("[2xUKR_ENG]")
|
|||||||
|
|
||||||
**Backward Compatibility**: All constants exported via `__init__.py`
|
**Backward Compatibility**: All constants exported via `__init__.py`
|
||||||
|
|
||||||
### 7. Cache Subsystem (`renamer/cache/`)
|
### 7. Cache Subsystem (`src/cache/`)
|
||||||
|
|
||||||
**Unified, modular architecture**:
|
**Unified, modular architecture**:
|
||||||
|
|
||||||
```
|
```
|
||||||
renamer/cache/
|
src/cache/
|
||||||
├── __init__.py # Exports and convenience functions
|
├── __init__.py # Exports and convenience functions
|
||||||
├── core.py # Core Cache class (thread-safe with RLock)
|
├── core.py # Core Cache class (thread-safe with RLock)
|
||||||
├── types.py # CacheEntry, CacheStats TypedDicts
|
├── types.py # CacheEntry, CacheStats TypedDicts
|
||||||
@@ -386,16 +386,16 @@ Access via Ctrl+P:
|
|||||||
- Safe for concurrent extractor access
|
- Safe for concurrent extractor access
|
||||||
- Memory cache synchronized with file cache
|
- Memory cache synchronized with file cache
|
||||||
|
|
||||||
### 8. UI Screens (`renamer/screens.py`)
|
### 8. UI Screens (`src/screens.py`)
|
||||||
|
|
||||||
1. **OpenScreen**: Directory selection dialog with validation
|
1. **OpenScreen**: Directory selection dialog with validation
|
||||||
2. **HelpScreen**: Comprehensive help with key bindings
|
2. **HelpScreen**: Comprehensive help with key bindings
|
||||||
3. **RenameConfirmScreen**: File rename confirmation with error handling
|
3. **RenameConfirmScreen**: File rename confirmation with error handling
|
||||||
4. **SettingsScreen**: Settings configuration interface
|
4. **SettingsScreen**: Settings configuration interface
|
||||||
|
|
||||||
### 9. Settings System (`renamer/settings.py`)
|
### 9. Settings System (`src/settings.py`)
|
||||||
|
|
||||||
**Configuration**: `~/.config/renamer/config.json`
|
**Configuration**: `~/.config/moma/config.json`
|
||||||
|
|
||||||
**Options**:
|
**Options**:
|
||||||
```json
|
```json
|
||||||
@@ -420,30 +420,30 @@ Automatic save/load with defaults.
|
|||||||
curl -LsSf https://astral.sh/uv/install.sh | sh
|
curl -LsSf https://astral.sh/uv/install.sh | sh
|
||||||
|
|
||||||
# Clone and sync
|
# Clone and sync
|
||||||
cd /home/sha/bin/renamer
|
cd /Users/sha/Developer/sha.dev/moma
|
||||||
uv sync
|
uv sync
|
||||||
|
|
||||||
# Install dev dependencies
|
# Install dev dependencies
|
||||||
uv sync --extra dev
|
uv sync --extra dev
|
||||||
|
|
||||||
# Run from source
|
# Run from source
|
||||||
uv run python renamer/main.py [directory]
|
uv run python src/main.py [directory]
|
||||||
```
|
```
|
||||||
|
|
||||||
### Development Commands
|
### Development Commands
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Run installed version
|
# Run installed version
|
||||||
uv run renamer [directory]
|
uv run moma [directory]
|
||||||
|
|
||||||
# Run tests
|
# Run tests
|
||||||
uv run pytest
|
uv run pytest
|
||||||
|
|
||||||
# Run tests with coverage
|
# Run tests with coverage
|
||||||
uv run pytest --cov=renamer
|
uv run pytest --cov=src
|
||||||
|
|
||||||
# Type checking
|
# Type checking
|
||||||
uv run mypy renamer/extractors/default_extractor.py
|
uv run mypy src/extractors/default_extractor.py
|
||||||
|
|
||||||
# Version management
|
# Version management
|
||||||
uv run bump-version # Increment patch version
|
uv run bump-version # Increment patch version
|
||||||
@@ -460,7 +460,7 @@ uv tool install .
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Enable formatter logging
|
# Enable formatter logging
|
||||||
FORMATTER_LOG=1 uv run renamer /path/to/directory
|
FORMATTER_LOG=1 uv run moma /path/to/directory
|
||||||
# Creates formatter.log with detailed call traces
|
# Creates formatter.log with detailed call traces
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -471,7 +471,7 @@ FORMATTER_LOG=1 uv run renamer /path/to/directory
|
|||||||
### Test Organization
|
### Test Organization
|
||||||
|
|
||||||
```
|
```
|
||||||
renamer/test/
|
src/test/
|
||||||
├── datasets/ # Test data
|
├── datasets/ # Test data
|
||||||
│ ├── filenames/
|
│ ├── filenames/
|
||||||
│ │ ├── filename_patterns.json # 46 test cases
|
│ │ ├── filename_patterns.json # 46 test cases
|
||||||
@@ -504,7 +504,7 @@ renamer/test/
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Generate 46 test files from filename_patterns.json
|
# Generate 46 test files from filename_patterns.json
|
||||||
uv run python renamer/test/fill_sample_mediafiles.py
|
uv run python src/test/fill_sample_mediafiles.py
|
||||||
```
|
```
|
||||||
|
|
||||||
### Test Fixtures
|
### Test Fixtures
|
||||||
@@ -524,13 +524,13 @@ file_path = get_test_file_path("movie.mkv")
|
|||||||
uv run pytest
|
uv run pytest
|
||||||
|
|
||||||
# Specific test file
|
# Specific test file
|
||||||
uv run pytest renamer/test/test_services.py
|
uv run pytest src/test/test_services.py
|
||||||
|
|
||||||
# With verbose output
|
# With verbose output
|
||||||
uv run pytest -xvs
|
uv run pytest -xvs
|
||||||
|
|
||||||
# With coverage
|
# With coverage
|
||||||
uv run pytest --cov=renamer --cov-report=html
|
uv run pytest --cov=src --cov-report=html
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -765,7 +765,7 @@ uv run release # Bump + sync + build
|
|||||||
### Release Checklist
|
### Release Checklist
|
||||||
|
|
||||||
- [ ] All tests passing: `uv run pytest`
|
- [ ] All tests passing: `uv run pytest`
|
||||||
- [ ] Type checking passes: `uv run mypy renamer/`
|
- [ ] Type checking passes: `uv run mypy src/`
|
||||||
- [ ] Documentation updated (CHANGELOG.md, README.md)
|
- [ ] Documentation updated (CHANGELOG.md, README.md)
|
||||||
- [ ] Version bumped in `pyproject.toml`
|
- [ ] Version bumped in `pyproject.toml`
|
||||||
- [ ] Dependencies synced: `uv sync`
|
- [ ] Dependencies synced: `uv sync`
|
||||||
@@ -777,8 +777,8 @@ uv run release # Bump + sync + build
|
|||||||
|
|
||||||
```
|
```
|
||||||
dist/
|
dist/
|
||||||
├── renamer-0.7.0-py3-none-any.whl # Wheel distribution
|
├── moma-0.7.0-py3-none-any.whl # Wheel distribution
|
||||||
└── renamer-0.7.0.tar.gz # Source distribution
|
└── moma-0.7.0.tar.gz # Source distribution
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -788,7 +788,7 @@ dist/
|
|||||||
### TMDB API
|
### TMDB API
|
||||||
|
|
||||||
**Configuration**:
|
**Configuration**:
|
||||||
- API key stored in `renamer/secrets.py`
|
- API key stored in `src/secrets.py`
|
||||||
- Base URL: `https://api.themoviedb.org/3/`
|
- Base URL: `https://api.themoviedb.org/3/`
|
||||||
- Image base URL for poster downloads
|
- Image base URL for poster downloads
|
||||||
|
|
||||||
@@ -801,7 +801,7 @@ dist/
|
|||||||
**Caching**:
|
**Caching**:
|
||||||
- API responses cached for 6 hours
|
- API responses cached for 6 hours
|
||||||
- Posters cached for 30 days
|
- Posters cached for 30 days
|
||||||
- Cache location: `~/.cache/renamer/tmdb/`, `~/.cache/renamer/posters/`
|
- Cache location: `~/.cache/moma/tmdb/`, `~/.cache/moma/posters/`
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -941,4 +941,4 @@ Title (Year) [Resolution Source Edition].ext
|
|||||||
**Last Updated**: 2026-01-01
|
**Last Updated**: 2026-01-01
|
||||||
**Maintainer**: sha
|
**Maintainer**: sha
|
||||||
**For**: AI Assistants and Developers
|
**For**: AI Assistants and Developers
|
||||||
**Repository**: `/home/sha/bin/renamer`
|
**Repository**: `/Users/sha/Developer/sha.dev/moma`
|
||||||
+3
-3
@@ -1,6 +1,6 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
All notable changes to the Renamer project are documented in this file.
|
All notable changes to the moma project are documented in this file.
|
||||||
|
|
||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
@@ -114,7 +114,7 @@ This development version represents a significant refactoring effort focused on
|
|||||||
- Dataset loaders in `conftest.py`
|
- Dataset loaders in `conftest.py`
|
||||||
|
|
||||||
#### Changed
|
#### Changed
|
||||||
- **Test Organization**: Consolidated test data into `renamer/test/datasets/`
|
- **Test Organization**: Consolidated test data into `src/test/datasets/`
|
||||||
- **Total Tests**: 560 tests (1 skipped), all passing
|
- **Total Tests**: 560 tests (1 skipped), all passing
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -141,7 +141,7 @@ This development version represents a significant refactoring effort focused on
|
|||||||
|
|
||||||
#### Cache System
|
#### Cache System
|
||||||
- **Cache key format changed**: Old cache files are invalid
|
- **Cache key format changed**: Old cache files are invalid
|
||||||
- **Migration**: Users should clear cache: `rm -rf ~/.cache/renamer/`
|
- **Migration**: Users should clear cache: `rm -rf ~/.cache/moma/`
|
||||||
- **Impact**: No data loss, just cache miss on first run after upgrade
|
- **Impact**: No data loss, just cache miss on first run after upgrade
|
||||||
|
|
||||||
#### Dependencies
|
#### Dependencies
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ Please read **[ENGINEERING_GUIDE.md](ENGINEERING_GUIDE.md)** for complete projec
|
|||||||
```bash
|
```bash
|
||||||
uv sync --extra dev # Setup
|
uv sync --extra dev # Setup
|
||||||
uv run pytest # Test
|
uv run pytest # Test
|
||||||
uv run renamer [dir] # Run
|
uv run moma [dir] # Run
|
||||||
```
|
```
|
||||||
|
|
||||||
## Essential Principles
|
## Essential Principles
|
||||||
|
|||||||
+10
-10
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
> **📘 For complete development documentation, see [ENGINEERING_GUIDE.md](ENGINEERING_GUIDE.md)**
|
> **📘 For complete development documentation, see [ENGINEERING_GUIDE.md](ENGINEERING_GUIDE.md)**
|
||||||
|
|
||||||
Quick reference for developers working on the Renamer project.
|
Quick reference for developers working on the moma project.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@ Quick reference for developers working on the Renamer project.
|
|||||||
curl -LsSf https://astral.sh/uv/install.sh | sh
|
curl -LsSf https://astral.sh/uv/install.sh | sh
|
||||||
|
|
||||||
# Clone and setup
|
# Clone and setup
|
||||||
cd /home/sha/bin/renamer
|
cd /Users/sha/Developer/sha.dev/moma
|
||||||
uv sync --extra dev
|
uv sync --extra dev
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -26,16 +26,16 @@ uv sync --extra dev
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Run from source
|
# Run from source
|
||||||
uv run renamer [directory]
|
uv run moma [directory]
|
||||||
|
|
||||||
# Run tests
|
# Run tests
|
||||||
uv run pytest
|
uv run pytest
|
||||||
|
|
||||||
# Run with coverage
|
# Run with coverage
|
||||||
uv run pytest --cov=renamer
|
uv run pytest --cov=src
|
||||||
|
|
||||||
# Type check
|
# Type check
|
||||||
uv run mypy renamer/
|
uv run mypy src/
|
||||||
|
|
||||||
# Version bump
|
# Version bump
|
||||||
uv run bump-version
|
uv run bump-version
|
||||||
@@ -53,13 +53,13 @@ uv build
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Enable detailed logging
|
# Enable detailed logging
|
||||||
FORMATTER_LOG=1 uv run renamer /path/to/directory
|
FORMATTER_LOG=1 uv run moma /path/to/directory
|
||||||
|
|
||||||
# Check logs
|
# Check logs
|
||||||
cat formatter.log
|
cat formatter.log
|
||||||
|
|
||||||
# Clear cache
|
# Clear cache
|
||||||
rm -rf ~/.cache/renamer/
|
rm -rf ~/.cache/moma/
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -71,13 +71,13 @@ rm -rf ~/.cache/renamer/
|
|||||||
uv run pytest
|
uv run pytest
|
||||||
|
|
||||||
# Specific file
|
# Specific file
|
||||||
uv run pytest renamer/test/test_services.py
|
uv run pytest src/test/test_services.py
|
||||||
|
|
||||||
# Verbose
|
# Verbose
|
||||||
uv run pytest -xvs
|
uv run pytest -xvs
|
||||||
|
|
||||||
# Generate sample files
|
# Generate sample files
|
||||||
uv run python renamer/test/fill_sample_mediafiles.py
|
uv run python src/test/fill_sample_mediafiles.py
|
||||||
```
|
```
|
||||||
|
|
||||||
See [ENGINEERING_GUIDE.md - Testing Strategy](ENGINEERING_GUIDE.md#testing-strategy)
|
See [ENGINEERING_GUIDE.md - Testing Strategy](ENGINEERING_GUIDE.md#testing-strategy)
|
||||||
@@ -97,7 +97,7 @@ uv run release
|
|||||||
uv tool install .
|
uv tool install .
|
||||||
|
|
||||||
# 4. Manual testing
|
# 4. Manual testing
|
||||||
uv run renamer /path/to/test/media
|
uv run moma /path/to/test/media
|
||||||
```
|
```
|
||||||
|
|
||||||
See [ENGINEERING_GUIDE.md - Release Process](ENGINEERING_GUIDE.md#release-process)
|
See [ENGINEERING_GUIDE.md - Release Process](ENGINEERING_GUIDE.md#release-process)
|
||||||
|
|||||||
+18
-18
@@ -1,6 +1,6 @@
|
|||||||
# Installation Guide for Renamer
|
# Installation Guide for moma
|
||||||
|
|
||||||
Renamer is a terminal-based media file renamer and metadata viewer built with Python and Textual.
|
moma is a terminal-based media file renamer and metadata viewer built with Python and Textual.
|
||||||
|
|
||||||
## Prerequisites
|
## Prerequisites
|
||||||
|
|
||||||
@@ -11,7 +11,7 @@ Renamer is a terminal-based media file renamer and metadata viewer built with Py
|
|||||||
|
|
||||||
### Method 1: UV Tool Install (Recommended)
|
### Method 1: UV Tool Install (Recommended)
|
||||||
|
|
||||||
This is the easiest way to install and use Renamer globally on your system.
|
This is the easiest way to install and use moma globally on your system.
|
||||||
|
|
||||||
#### Install UV (if not already installed)
|
#### Install UV (if not already installed)
|
||||||
```bash
|
```bash
|
||||||
@@ -22,22 +22,22 @@ curl -LsSf https://astral.sh/uv/install.sh | sh
|
|||||||
powershell -c "irm https://astral.sh/uv/install.sh | iex"
|
powershell -c "irm https://astral.sh/uv/install.sh | iex"
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Install Renamer
|
#### Install moma
|
||||||
```bash
|
```bash
|
||||||
# One-command install from remote wheel
|
# One-command install from remote wheel
|
||||||
uv tool install https://git.shadoll.dev/sha/renamer/raw/branch/main/dist/renamer-0.2.4-py3-none-any.whl
|
uv tool install https://github.com/shadoll/moma/raw/branch/main/dist/moma-0.2.4-py3-none-any.whl
|
||||||
|
|
||||||
# Or from local wheel (if downloaded)
|
# Or from local wheel (if downloaded)
|
||||||
uv tool install dist/renamer-0.2.4-py3-none-any.whl
|
uv tool install dist/moma-0.2.4-py3-none-any.whl
|
||||||
|
|
||||||
# Or from PyPI (when published)
|
# Or from PyPI (when published)
|
||||||
uv tool install renamer
|
uv tool install moma
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Usage
|
#### Usage
|
||||||
```bash
|
```bash
|
||||||
renamer # Scan current directory
|
moma # Scan current directory
|
||||||
renamer /path/to/directory # Scan specific directory
|
moma /path/to/directory # Scan specific directory
|
||||||
```
|
```
|
||||||
|
|
||||||
### Method 2: pip Install from Wheel
|
### Method 2: pip Install from Wheel
|
||||||
@@ -46,10 +46,10 @@ If you have the wheel file, you can install it with pip.
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Install the wheel
|
# Install the wheel
|
||||||
pip install dist/renamer-0.2.0-py3-none-any.whl
|
pip install dist/moma-0.2.0-py3-none-any.whl
|
||||||
|
|
||||||
# Or install globally (may require sudo)
|
# Or install globally (may require sudo)
|
||||||
sudo pip install dist/renamer-0.2.0-py3-none-any.whl
|
sudo pip install dist/moma-0.2.0-py3-none-any.whl
|
||||||
```
|
```
|
||||||
|
|
||||||
### Method 3: Development Installation
|
### Method 3: Development Installation
|
||||||
@@ -59,7 +59,7 @@ For development or if you want to run from source:
|
|||||||
#### Clone and Setup
|
#### Clone and Setup
|
||||||
```bash
|
```bash
|
||||||
git clone <repository-url>
|
git clone <repository-url>
|
||||||
cd renamer
|
cd moma
|
||||||
|
|
||||||
# Install dependencies
|
# Install dependencies
|
||||||
uv sync
|
uv sync
|
||||||
@@ -120,12 +120,12 @@ python3 main.py /path/to/directory
|
|||||||
After installation, verify it works:
|
After installation, verify it works:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
renamer --help
|
moma --help
|
||||||
# or
|
# or
|
||||||
python3 main.py --help
|
python3 main.py --help
|
||||||
```
|
```
|
||||||
|
|
||||||
You should see the help text for the Renamer application.
|
You should see the help text for the moma application.
|
||||||
|
|
||||||
## Troubleshooting
|
## Troubleshooting
|
||||||
|
|
||||||
@@ -158,17 +158,17 @@ If you encounter issues:
|
|||||||
|
|
||||||
### UV Tool Uninstall
|
### UV Tool Uninstall
|
||||||
```bash
|
```bash
|
||||||
uv tool uninstall renamer
|
uv tool uninstall moma
|
||||||
```
|
```
|
||||||
|
|
||||||
### pip Uninstall
|
### pip Uninstall
|
||||||
```bash
|
```bash
|
||||||
pip uninstall renamer
|
pip uninstall moma
|
||||||
```
|
```
|
||||||
|
|
||||||
### Development Uninstall
|
### Development Uninstall
|
||||||
```bash
|
```bash
|
||||||
uv tool uninstall renamer
|
uv tool uninstall moma
|
||||||
# Remove the cloned directory if desired
|
# Remove the cloned directory if desired
|
||||||
```</content>
|
```</content>
|
||||||
<parameter name="filePath">/home/sha/bin/renamer/INSTALL.md
|
<parameter name="filePath">/Users/sha/Developer/sha.dev/moma/INSTALL.md
|
||||||
@@ -27,8 +27,8 @@ A powerful Terminal User Interface (TUI) for managing media collections. View de
|
|||||||
# Install UV
|
# Install UV
|
||||||
curl -LsSf https://astral.sh/uv/install.sh | sh
|
curl -LsSf https://astral.sh/uv/install.sh | sh
|
||||||
|
|
||||||
# Install Renamer
|
# Install moma
|
||||||
cd /path/to/renamer
|
cd /Users/sha/Developer/sha.dev/moma
|
||||||
uv sync
|
uv sync
|
||||||
uv tool install .
|
uv tool install .
|
||||||
```
|
```
|
||||||
@@ -39,10 +39,9 @@ See [INSTALL.md](INSTALL.md) for detailed installation instructions.
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Scan current directory
|
# Scan current directory
|
||||||
renamer
|
moma
|
||||||
|
|
||||||
# Scan specific directory
|
# Scan specific directory
|
||||||
renamer /path/to/media
|
moma /path/to/media
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -97,7 +96,7 @@ Toggle with `m` key.
|
|||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
**Location**: `~/.config/renamer/config.json`
|
**Location**: `~/.config/moma/config.json`
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
@@ -124,7 +123,7 @@ Access via `Ctrl+S` or edit file directly.
|
|||||||
## Project Structure
|
## Project Structure
|
||||||
|
|
||||||
```
|
```
|
||||||
renamer/
|
src/
|
||||||
├── app.py # Main TUI application
|
├── app.py # Main TUI application
|
||||||
├── services/ # Business logic
|
├── services/ # Business logic
|
||||||
├── extractors/ # Metadata extraction
|
├── extractors/ # Metadata extraction
|
||||||
@@ -148,7 +147,7 @@ uv sync --extra dev
|
|||||||
uv run pytest
|
uv run pytest
|
||||||
|
|
||||||
# Run from source
|
# Run from source
|
||||||
uv run renamer [directory]
|
uv run moma [directory]
|
||||||
```
|
```
|
||||||
|
|
||||||
See [DEVELOP.md](DEVELOP.md) for development documentation.
|
See [DEVELOP.md](DEVELOP.md) for development documentation.
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
# Renamer - Refactoring Roadmap
|
# moma - Refactoring Roadmap
|
||||||
|
|
||||||
**Version**: 0.7.0-dev
|
**Version**: 0.7.0-dev
|
||||||
**Last Updated**: 2026-01-01
|
**Last Updated**: 2026-01-01
|
||||||
|
|
||||||
> **📋 For completed work, see [CHANGELOG.md](CHANGELOG.md)**
|
> **📋 For completed work, see [CHANGELOG.md](CHANGELOG.md)**
|
||||||
|
|
||||||
This document tracks the future refactoring plan for Renamer v0.7.0+.
|
This document tracks the future refactoring plan for moma v0.7.0+.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -71,7 +71,7 @@ class ProposedNameFormatter:
|
|||||||
- No coupling to extractor instance
|
- No coupling to extractor instance
|
||||||
|
|
||||||
**Files to Modify**:
|
**Files to Modify**:
|
||||||
- `renamer/formatters/proposed_name_formatter.py`
|
- `src/formatters/proposed_name_formatter.py`
|
||||||
- Update all usages in `app.py`, `screens.py`, etc.
|
- Update all usages in `app.py`, `screens.py`, etc.
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -79,33 +79,33 @@ class ProposedNameFormatter:
|
|||||||
#### 3.6.2 Clean Up Decorators Directory
|
#### 3.6.2 Clean Up Decorators Directory
|
||||||
**Status**: NOT STARTED
|
**Status**: NOT STARTED
|
||||||
|
|
||||||
**Current Issue**: `renamer/decorators/` directory contains legacy `caching.py` file that's no longer used. All cache decorators were moved to `renamer/cache/decorators.py` in Phase 1.
|
**Current Issue**: `src/decorators/` directory contains legacy `caching.py` file that's no longer used. All cache decorators were moved to `src/cache/decorators.py` in Phase 1.
|
||||||
|
|
||||||
**Current Structure**:
|
**Current Structure**:
|
||||||
```
|
```
|
||||||
renamer/decorators/
|
src/decorators/
|
||||||
├── caching.py # ⚠️ LEGACY - Remove
|
├── caching.py # ⚠️ LEGACY - Remove
|
||||||
└── __init__.py # Import from renamer.cache
|
└── __init__.py # Import from src.cache
|
||||||
```
|
```
|
||||||
|
|
||||||
**Actions**:
|
**Actions**:
|
||||||
1. **Verify no direct imports** of `renamer.decorators.caching`
|
1. **Verify no direct imports** of `src.decorators.caching`
|
||||||
2. **Remove `caching.py`** - All functionality now in `renamer/cache/decorators.py`
|
2. **Remove `caching.py`** - All functionality now in `src/cache/decorators.py`
|
||||||
3. **Keep `__init__.py`** for backward compatibility (imports from `renamer.cache`)
|
3. **Keep `__init__.py`** for backward compatibility (imports from `src.cache`)
|
||||||
4. **Update any direct imports** to use `from renamer.cache import cached_method`
|
4. **Update any direct imports** to use `from src.cache import cached_method`
|
||||||
|
|
||||||
**Verification**:
|
**Verification**:
|
||||||
```bash
|
```bash
|
||||||
# Check for direct imports of old caching module
|
# Check for direct imports of old caching module
|
||||||
grep -r "from renamer.decorators.caching" renamer/
|
grep -r "from src.decorators.caching" src/
|
||||||
grep -r "import renamer.decorators.caching" renamer/
|
grep -r "import src.decorators.caching" src/
|
||||||
|
|
||||||
# Should only find imports from __init__.py that re-export from renamer.cache
|
# Should only find imports from __init__.py that re-export from src.cache
|
||||||
```
|
```
|
||||||
|
|
||||||
**Benefits**:
|
**Benefits**:
|
||||||
- Removes dead code
|
- Removes dead code
|
||||||
- Clarifies that all caching is in `renamer/cache/`
|
- Clarifies that all caching is in `src/cache/`
|
||||||
- Maintains backward compatibility via `__init__.py`
|
- Maintains backward compatibility via `__init__.py`
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -142,7 +142,7 @@ grep -r "import renamer.decorators.caching" renamer/
|
|||||||
- `proposed_name_formatter.py`
|
- `proposed_name_formatter.py`
|
||||||
- All specialized formatters
|
- All specialized formatters
|
||||||
|
|
||||||
#### 4.3 Integrate RenamerApp with Services
|
#### 4.3 Integrate MomaApp with Services
|
||||||
- Refactor `app.py` to use service layer
|
- Refactor `app.py` to use service layer
|
||||||
- Replace direct extractor calls with `MetadataService`
|
- Replace direct extractor calls with `MetadataService`
|
||||||
- Replace direct file operations with `RenameService`
|
- Replace direct file operations with `RenameService`
|
||||||
@@ -357,7 +357,7 @@ grep -r "import renamer.decorators.caching" renamer/
|
|||||||
### Phase 4 Complete When:
|
### Phase 4 Complete When:
|
||||||
- [ ] All extractors implement Protocol
|
- [ ] All extractors implement Protocol
|
||||||
- [ ] All formatters use base classes
|
- [ ] All formatters use base classes
|
||||||
- [ ] RenamerApp uses services exclusively
|
- [ ] MomaApp uses services exclusively
|
||||||
- [ ] No direct business logic in UI
|
- [ ] No direct business logic in UI
|
||||||
- [ ] All tests passing
|
- [ ] All tests passing
|
||||||
- [ ] No performance regression
|
- [ ] No performance regression
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
# Renamer - Future Tasks
|
# moma - Future Tasks
|
||||||
|
|
||||||
**Version**: 0.7.0-dev
|
**Version**: 0.7.0-dev
|
||||||
**Last Updated**: 2026-01-01
|
**Last Updated**: 2026-01-01
|
||||||
@@ -18,7 +18,7 @@ This file tracks future feature enhancements and improvements.
|
|||||||
- [ ] **Phase 4: Refactor to New Architecture**
|
- [ ] **Phase 4: Refactor to New Architecture**
|
||||||
- Refactor existing extractors to use Protocol
|
- Refactor existing extractors to use Protocol
|
||||||
- Refactor existing formatters to use base classes
|
- Refactor existing formatters to use base classes
|
||||||
- Integrate RenamerApp with services
|
- Integrate MomaApp with services
|
||||||
- Update all imports and dependencies
|
- Update all imports and dependencies
|
||||||
- See [REFACTORING_PROGRESS.md](REFACTORING_PROGRESS.md) for details
|
- See [REFACTORING_PROGRESS.md](REFACTORING_PROGRESS.md) for details
|
||||||
|
|
||||||
+5
-5
@@ -1,5 +1,5 @@
|
|||||||
[project]
|
[project]
|
||||||
name = "renamer"
|
name = "moma"
|
||||||
version = "0.8.11"
|
version = "0.8.11"
|
||||||
description = "Terminal-based media file renamer and metadata viewer"
|
description = "Terminal-based media file renamer and metadata viewer"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
@@ -21,16 +21,16 @@ dev = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[project.scripts]
|
[project.scripts]
|
||||||
renamer = "renamer.main:main"
|
moma = "src.main:main"
|
||||||
bump-version = "renamer.bump:main"
|
bump-version = "src.bump:main"
|
||||||
release = "renamer.release:main"
|
release = "src.release:main"
|
||||||
|
|
||||||
[tool.uv]
|
[tool.uv]
|
||||||
package = true
|
package = true
|
||||||
|
|
||||||
[tool.pytest.ini_options]
|
[tool.pytest.ini_options]
|
||||||
addopts = "--strict-markers"
|
addopts = "--strict-markers"
|
||||||
testpaths = ["renamer/test"]
|
testpaths = ["src/test"]
|
||||||
python_files = ["test_*.py"]
|
python_files = ["test_*.py"]
|
||||||
python_classes = ["Test*"]
|
python_classes = ["Test*"]
|
||||||
python_functions = ["test_*"]
|
python_functions = ["test_*"]
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
# Renamer package
|
|
||||||
|
|
||||||
from .app import RenamerApp
|
|
||||||
from .extractors.extractor import MediaExtractor
|
|
||||||
from .views import MediaPanelView, ProposedFilenameView
|
|
||||||
|
|
||||||
__all__ = ['RenamerApp', 'MediaExtractor', 'MediaPanelView', 'ProposedFilenameView']
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
TMDB_API_KEY="19af49e6d33ad124b3c3dfbf1114b714"
|
|
||||||
TMDB_ACCESS_TOKEN="eyJhbGciOiJIUzI1NiJ9.eyJhdWQiOiIxOWFmNDllNmQzM2FkMTI0YjNjM2RmYmYxMTE0YjcxNCIsIm5iZiI6MTQxNDMzODgxOS4zODMwMDAxLCJzdWIiOiI1NDRkMTkwM2MzYTM2ODcyZTAwMDI3ZmIiLCJzY29wZXMiOlsiYXBpX3JlYWQiXSwidmVyc2lvbiI6MX0.O4xnCs8Z7PJ_BQS6ZdU9yvvZ38Z8EsBBmjrYqvIY0aQ"
|
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
# moma package
|
||||||
|
|
||||||
|
from .app import MomaApp
|
||||||
|
from .extractors.extractor import MediaExtractor
|
||||||
|
from .views import MediaPanelView, ProposedFilenameView
|
||||||
|
|
||||||
|
__all__ = ['MomaApp', 'MediaExtractor', 'MediaPanelView', 'ProposedFilenameView']
|
||||||
@@ -79,7 +79,7 @@ class AppCommandProvider(Provider):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class RenamerApp(App):
|
class MomaApp(App):
|
||||||
CSS = """
|
CSS = """
|
||||||
/* Default technical mode: 2 columns */
|
/* Default technical mode: 2 columns */
|
||||||
#left {
|
#left {
|
||||||
+3
-3
@@ -1,4 +1,4 @@
|
|||||||
"""Unified caching subsystem for Renamer.
|
"""Unified caching subsystem for moma.
|
||||||
|
|
||||||
This module provides a flexible caching system with:
|
This module provides a flexible caching system with:
|
||||||
- Multiple cache key generation strategies
|
- Multiple cache key generation strategies
|
||||||
@@ -9,7 +9,7 @@ This module provides a flexible caching system with:
|
|||||||
|
|
||||||
Usage Examples:
|
Usage Examples:
|
||||||
# Using decorators
|
# Using decorators
|
||||||
from renamer.cache import cached, cached_api
|
from src.cache import cached, cached_api
|
||||||
|
|
||||||
class MyExtractor:
|
class MyExtractor:
|
||||||
def __init__(self, file_path, cache, settings):
|
def __init__(self, file_path, cache, settings):
|
||||||
@@ -28,7 +28,7 @@ Usage Examples:
|
|||||||
return api_call(movie_id)
|
return api_call(movie_id)
|
||||||
|
|
||||||
# Using cache manager
|
# Using cache manager
|
||||||
from renamer.cache import Cache, CacheManager
|
from src.cache import Cache, CacheManager
|
||||||
|
|
||||||
cache = Cache()
|
cache = Cache()
|
||||||
manager = CacheManager(cache)
|
manager = CacheManager(cache)
|
||||||
+2
-2
@@ -30,7 +30,7 @@ class Cache:
|
|||||||
"""Initialize cache with optional custom directory (only once).
|
"""Initialize cache with optional custom directory (only once).
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
cache_dir: Optional cache directory path. Defaults to ~/.cache/renamer/
|
cache_dir: Optional cache directory path. Defaults to ~/.cache/moma/
|
||||||
"""
|
"""
|
||||||
# Only initialize once
|
# Only initialize once
|
||||||
if self._initialized:
|
if self._initialized:
|
||||||
@@ -38,7 +38,7 @@ class Cache:
|
|||||||
|
|
||||||
# Always use the default cache dir to avoid creating cache in scan dir
|
# Always use the default cache dir to avoid creating cache in scan dir
|
||||||
if cache_dir is None:
|
if cache_dir is None:
|
||||||
cache_dir = Path.home() / ".cache" / "renamer"
|
cache_dir = Path.home() / ".cache" / "moma"
|
||||||
self.cache_dir = cache_dir
|
self.cache_dir = cache_dir
|
||||||
self.cache_dir.mkdir(parents=True, exist_ok=True)
|
self.cache_dir.mkdir(parents=True, exist_ok=True)
|
||||||
self._memory_cache: Dict[str, Dict[str, Any]] = {} # In-memory cache for faster access
|
self._memory_cache: Dict[str, Dict[str, Any]] = {} # In-memory cache for faster access
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
"""Constants package for Renamer.
|
"""Constants package for moma.
|
||||||
|
|
||||||
This package contains constants split into logical modules:
|
This package contains constants split into logical modules:
|
||||||
- media_constants.py: Media type definitions (MEDIA_TYPES)
|
- media_constants.py: Media type definitions (MEDIA_TYPES)
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
from .text_formatter import TextFormatter
|
from .text_formatter import TextFormatter
|
||||||
from renamer.views.posters import AsciiPosterRenderer, ViuPosterRenderer, RichPixelsPosterRenderer
|
from src.views.posters import AsciiPosterRenderer, ViuPosterRenderer, RichPixelsPosterRenderer
|
||||||
from typing import Union
|
from typing import Union
|
||||||
import os
|
import os
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
"""Singleton logging configuration for the renamer application.
|
"""Singleton logging configuration for the moma application.
|
||||||
|
|
||||||
This module provides centralized logging configuration that is initialized
|
This module provides centralized logging configuration that is initialized
|
||||||
once and used throughout the application.
|
once and used throughout the application.
|
||||||
@@ -1,12 +1,12 @@
|
|||||||
import argparse
|
import argparse
|
||||||
from renamer.app import RenamerApp
|
from src.app import MomaApp
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
parser = argparse.ArgumentParser(description="Media file renamer")
|
parser = argparse.ArgumentParser(description="moma - media file manager")
|
||||||
parser.add_argument("directory", nargs="?", default=".", help="Directory to scan")
|
parser.add_argument("directory", nargs="?", default=".", help="Directory to scan")
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
app = RenamerApp(args.directory)
|
app = MomaApp(args.directory)
|
||||||
app.run()
|
app.run()
|
||||||
|
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
"""Services package - business logic layer for the Renamer application.
|
"""Services package - business logic layer for the moma application.
|
||||||
|
|
||||||
This package contains service classes that encapsulate business logic and
|
This package contains service classes that encapsulate business logic and
|
||||||
coordinate between different components. Services provide a clean separation
|
coordinate between different components. Services provide a clean separation
|
||||||
@@ -15,7 +15,7 @@ import re
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Optional, List, Dict, Tuple
|
from typing import Optional, List, Dict, Tuple
|
||||||
|
|
||||||
from renamer.extractors.extractor import MediaExtractor
|
from src.extractors.extractor import MediaExtractor
|
||||||
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
@@ -9,7 +9,7 @@ from pathlib import Path
|
|||||||
from typing import Optional, Callable
|
from typing import Optional, Callable
|
||||||
from rich.markup import escape
|
from rich.markup import escape
|
||||||
|
|
||||||
from renamer.constants import MEDIA_TYPES
|
from src.constants import MEDIA_TYPES
|
||||||
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
@@ -13,12 +13,12 @@ from typing import Optional, Callable
|
|||||||
from concurrent.futures import ThreadPoolExecutor, Future
|
from concurrent.futures import ThreadPoolExecutor, Future
|
||||||
from threading import Lock
|
from threading import Lock
|
||||||
|
|
||||||
from renamer.cache import Cache
|
from src.cache import Cache
|
||||||
from renamer.settings import Settings
|
from src.settings import Settings
|
||||||
from renamer.extractors.extractor import MediaExtractor
|
from src.extractors.extractor import MediaExtractor
|
||||||
from renamer.views import MediaPanelView, ProposedFilenameView
|
from src.views import MediaPanelView, ProposedFilenameView
|
||||||
from renamer.formatters.catalog_formatter import CatalogFormatter
|
from src.formatters.catalog_formatter import CatalogFormatter
|
||||||
from renamer.formatters.text_formatter import TextFormatter
|
from src.formatters.text_formatter import TextFormatter
|
||||||
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
@@ -13,8 +13,8 @@ import re
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Optional, Callable
|
from typing import Optional, Callable
|
||||||
|
|
||||||
from renamer.extractors.extractor import MediaExtractor
|
from src.extractors.extractor import MediaExtractor
|
||||||
from renamer.views import ProposedFilenameView
|
from src.views import ProposedFilenameView
|
||||||
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
@@ -37,7 +37,7 @@ class Settings:
|
|||||||
return
|
return
|
||||||
|
|
||||||
if config_dir is None:
|
if config_dir is None:
|
||||||
config_dir = Path.home() / ".config" / "renamer"
|
config_dir = Path.home() / ".config" / "moma"
|
||||||
self.config_dir = config_dir
|
self.config_dir = config_dir
|
||||||
self.config_file = self.config_dir / "config.json"
|
self.config_file = self.config_dir / "config.json"
|
||||||
self._settings = self.DEFAULTS.copy()
|
self._settings = self.DEFAULTS.copy()
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
# Test Datasets
|
# Test Datasets
|
||||||
|
|
||||||
This directory contains organized test data for the Renamer test suite.
|
This directory contains organized test data for the Moma test suite.
|
||||||
|
|
||||||
## Directory Structure
|
## Directory Structure
|
||||||
|
|
||||||
@@ -17,7 +17,7 @@ datasets/
|
|||||||
```
|
```
|
||||||
|
|
||||||
**Note**: The `sample_mediafiles/` directory is generated by running `fill_sample_mediafiles.py`
|
**Note**: The `sample_mediafiles/` directory is generated by running `fill_sample_mediafiles.py`
|
||||||
and is excluded from git. Run `uv run python renamer/test/fill_sample_mediafiles.py` to create these files.
|
and is excluded from git. Run `uv run python src/test/fill_sample_mediafiles.py` to create these files.
|
||||||
|
|
||||||
## Dataset Files
|
## Dataset Files
|
||||||
|
|
||||||
@@ -157,7 +157,7 @@ from pathlib import Path
|
|||||||
|
|
||||||
def load_dataset(dataset_name):
|
def load_dataset(dataset_name):
|
||||||
"""Load a dataset file from datasets directory."""
|
"""Load a dataset file from datasets directory."""
|
||||||
from renamer.test.conftest import load_dataset
|
from src.test.conftest import load_dataset
|
||||||
return load_dataset(dataset_name)
|
return load_dataset(dataset_name)
|
||||||
|
|
||||||
# Load filename patterns
|
# Load filename patterns
|
||||||
@@ -173,7 +173,7 @@ frame_tests = load_dataset("frame_class_tests")
|
|||||||
```python
|
```python
|
||||||
import pytest
|
import pytest
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from renamer.extractors.filename_extractor import FilenameExtractor
|
from src.extractors.filename_extractor import FilenameExtractor
|
||||||
|
|
||||||
# Load test cases at module level
|
# Load test cases at module level
|
||||||
def load_test_cases():
|
def load_test_cases():
|
||||||
@@ -224,7 +224,7 @@ def test_cyrillic_titles(load_filename_patterns):
|
|||||||
### Using Sample Files
|
### Using Sample Files
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from renamer.test.conftest import get_test_file_path
|
from src.test.conftest import get_test_file_path
|
||||||
|
|
||||||
# Get path to a sample file from the dataset
|
# Get path to a sample file from the dataset
|
||||||
sample_file = get_test_file_path("Movie Title (2020) BDRip [1080p,ukr,eng].mkv")
|
sample_file = get_test_file_path("Movie Title (2020) BDRip [1080p,ukr,eng].mkv")
|
||||||
@@ -242,12 +242,12 @@ These files are generated automatically and should not be committed to git.
|
|||||||
**Generate files:**
|
**Generate files:**
|
||||||
```bash
|
```bash
|
||||||
# From project root
|
# From project root
|
||||||
uv run python renamer/test/fill_sample_mediafiles.py
|
uv run python src/test/fill_sample_mediafiles.py
|
||||||
```
|
```
|
||||||
|
|
||||||
**Output:**
|
**Output:**
|
||||||
```
|
```
|
||||||
Creating sample media files in: /path/to/renamer/test/datasets/sample_mediafiles
|
Creating sample media files in: /path/to/src/test/datasets/sample_mediafiles
|
||||||
Test cases in dataset: 46
|
Test cases in dataset: 46
|
||||||
|
|
||||||
✅ Created: Movie Title (2020) BDRip [1080p,ukr,eng].mkv
|
✅ Created: Movie Title (2020) BDRip [1080p,ukr,eng].mkv
|
||||||
-18
@@ -848,24 +848,6 @@
|
|||||||
"category": "edge_cases",
|
"category": "edge_cases",
|
||||||
"description": "No year present"
|
"description": "No year present"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"testname": "edge-multipart-001",
|
|
||||||
"filename": "Золотє теля.pt1.(1968).[SD,ukr].avi",
|
|
||||||
"expected": {
|
|
||||||
"order": "1",
|
|
||||||
"title": "Золотє теля",
|
|
||||||
"year": "1968",
|
|
||||||
"source": null,
|
|
||||||
"frame_class": null,
|
|
||||||
"hdr": null,
|
|
||||||
"movie_db": null,
|
|
||||||
"special_info": null,
|
|
||||||
"audio_langs": "rus",
|
|
||||||
"extension": "avi"
|
|
||||||
},
|
|
||||||
"category": "edge_cases",
|
|
||||||
"description": "Multi-part film (pt1)"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"testname": "edge-remastered-001",
|
"testname": "edge-remastered-001",
|
||||||
"filename": "Apple 1984 (1984) [Remastered] [2160p,eng] [imdbid-tt4227346].mkv",
|
"filename": "Apple 1984 (1984) [Remastered] [2160p,eng] [imdbid-tt4227346].mkv",
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
Script to generate empty media test files from filename_patterns.json dataset.
|
Script to generate empty media test files from filename_patterns.json dataset.
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
uv run python renamer/test/fill_sample_mediafiles.py
|
uv run python src/test/fill_sample_mediafiles.py
|
||||||
|
|
||||||
This script:
|
This script:
|
||||||
1. Creates the sample_mediafiles directory if it doesn't exist
|
1. Creates the sample_mediafiles directory if it doesn't exist
|
||||||
@@ -90,7 +90,7 @@ def create_sample_mediafiles():
|
|||||||
print("✅ Sample media files generation complete!")
|
print("✅ Sample media files generation complete!")
|
||||||
print()
|
print()
|
||||||
print("Next steps:")
|
print("Next steps:")
|
||||||
print("1. Add 'renamer/test/datasets/sample_mediafiles/' to .gitignore")
|
print("1. Add 'src/test/datasets/sample_mediafiles/' to .gitignore")
|
||||||
print("2. Run tests to verify files are accessible")
|
print("2. Run tests to verify files are accessible")
|
||||||
|
|
||||||
return True
|
return True
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from renamer.cache import (
|
from src.cache import (
|
||||||
Cache,
|
Cache,
|
||||||
CacheManager,
|
CacheManager,
|
||||||
cached,
|
cached,
|
||||||
@@ -239,13 +239,13 @@ class TestCachePackageImports:
|
|||||||
"""Test cache package import paths."""
|
"""Test cache package import paths."""
|
||||||
|
|
||||||
def test_import_cache_from_package(self):
|
def test_import_cache_from_package(self):
|
||||||
"""Test importing Cache from renamer.cache package."""
|
"""Test importing Cache from src.cache package."""
|
||||||
from renamer.cache import Cache as PackageCache
|
from src.cache import Cache as PackageCache
|
||||||
assert PackageCache is not None
|
assert PackageCache is not None
|
||||||
|
|
||||||
def test_import_decorators_from_cache(self):
|
def test_import_decorators_from_cache(self):
|
||||||
"""Test importing decorators from renamer.cache."""
|
"""Test importing decorators from src.cache."""
|
||||||
from renamer.cache import cached_method, cached, cached_api, cached_property
|
from src.cache import cached_method, cached, cached_api, cached_property
|
||||||
assert cached_method is not None
|
assert cached_method is not None
|
||||||
assert cached is not None
|
assert cached is not None
|
||||||
assert cached_api is not None
|
assert cached_api is not None
|
||||||
@@ -253,7 +253,7 @@ class TestCachePackageImports:
|
|||||||
|
|
||||||
def test_create_cache_convenience_function(self):
|
def test_create_cache_convenience_function(self):
|
||||||
"""Test the create_cache convenience function."""
|
"""Test the create_cache convenience function."""
|
||||||
from renamer.cache import create_cache
|
from src.cache import create_cache
|
||||||
cache, manager = create_cache()
|
cache, manager = create_cache()
|
||||||
assert cache is not None
|
assert cache is not None
|
||||||
assert manager is not None
|
assert manager is not None
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
"""Tests for formatter decorators."""
|
"""Tests for formatter decorators."""
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from renamer.formatters import (
|
from src.formatters import (
|
||||||
date_decorators,
|
date_decorators,
|
||||||
special_info_decorators,
|
special_info_decorators,
|
||||||
text_decorators,
|
text_decorators,
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import pytest
|
import pytest
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from renamer.extractors.fileinfo_extractor import FileInfoExtractor
|
from src.extractors.fileinfo_extractor import FileInfoExtractor
|
||||||
|
|
||||||
|
|
||||||
class TestFileInfoExtractor:
|
class TestFileInfoExtractor:
|
||||||
@@ -7,7 +7,7 @@ import json
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))
|
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))
|
||||||
|
|
||||||
from renamer.extractors.filename_extractor import FilenameExtractor
|
from src.extractors.filename_extractor import FilenameExtractor
|
||||||
|
|
||||||
def test_detection():
|
def test_detection():
|
||||||
# Load test cases from new dataset location
|
# Load test cases from new dataset location
|
||||||
@@ -4,7 +4,7 @@ Tests for base formatter classes and concrete formatter implementations.
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from renamer.formatters import (
|
from src.formatters import (
|
||||||
Formatter,
|
Formatter,
|
||||||
DataFormatter,
|
DataFormatter,
|
||||||
MarkupFormatter,
|
MarkupFormatter,
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import pytest
|
import pytest
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from unittest.mock import MagicMock
|
from unittest.mock import MagicMock
|
||||||
from renamer.extractors.mediainfo_extractor import MediaInfoExtractor
|
from src.extractors.mediainfo_extractor import MediaInfoExtractor
|
||||||
import json
|
import json
|
||||||
|
|
||||||
|
|
||||||
@@ -8,7 +8,7 @@ import sys
|
|||||||
import os
|
import os
|
||||||
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))
|
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))
|
||||||
|
|
||||||
from renamer.extractors.mediainfo_extractor import MediaInfoExtractor
|
from src.extractors.mediainfo_extractor import MediaInfoExtractor
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
# Load test cases from dataset using context manager
|
# Load test cases from dataset using context manager
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import pytest
|
import pytest
|
||||||
import json
|
import json
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from renamer.extractors.metadata_extractor import MetadataExtractor
|
from src.extractors.metadata_extractor import MetadataExtractor
|
||||||
|
|
||||||
|
|
||||||
class TestMetadataExtractor:
|
class TestMetadataExtractor:
|
||||||
+1
-1
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from renamer.views import ProposedFilenameView
|
from src.views import ProposedFilenameView
|
||||||
|
|
||||||
|
|
||||||
class TestProposedFilenameView:
|
class TestProposedFilenameView:
|
||||||
@@ -9,9 +9,9 @@ from unittest.mock import Mock, MagicMock, patch
|
|||||||
import tempfile
|
import tempfile
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from renamer.services import FileTreeService, MetadataService, RenameService
|
from src.services import FileTreeService, MetadataService, RenameService
|
||||||
from renamer.cache import Cache
|
from src.cache import Cache
|
||||||
from renamer.settings import Settings
|
from src.settings import Settings
|
||||||
|
|
||||||
|
|
||||||
class TestFileTreeService:
|
class TestFileTreeService:
|
||||||
@@ -4,7 +4,7 @@ Tests for LanguageCodeExtractor, PatternExtractor, and FrameClassMatcher.
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from renamer.utils import LanguageCodeExtractor, PatternExtractor, FrameClassMatcher
|
from src.utils import LanguageCodeExtractor, PatternExtractor, FrameClassMatcher
|
||||||
|
|
||||||
|
|
||||||
class TestLanguageCodeExtractor:
|
class TestLanguageCodeExtractor:
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
"""Utils package - shared utility functions for the Renamer application.
|
"""Utils package - shared utility functions for the moma application.
|
||||||
|
|
||||||
This package contains utility modules that provide common functionality
|
This package contains utility modules that provide common functionality
|
||||||
used across multiple parts of the application. This eliminates code
|
used across multiple parts of the application. This eliminates code
|
||||||
@@ -7,7 +7,7 @@ This module provides centralized logic for determining frame class
|
|||||||
import logging
|
import logging
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
from renamer.constants import FRAME_CLASSES
|
from src.constants import FRAME_CLASSES
|
||||||
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
@@ -9,7 +9,7 @@ import re
|
|||||||
from typing import Optional, Dict
|
from typing import Optional, Dict
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
from renamer.constants import MOVIE_DB_DICT
|
from src.constants import MOVIE_DB_DICT
|
||||||
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
@@ -7,12 +7,12 @@ class HelpScreen(Screen):
|
|||||||
def compose(self):
|
def compose(self):
|
||||||
try:
|
try:
|
||||||
from importlib.metadata import version
|
from importlib.metadata import version
|
||||||
app_version = version("renamer")
|
app_version = version("moma")
|
||||||
except Exception:
|
except Exception:
|
||||||
app_version = "unknown"
|
app_version = "unknown"
|
||||||
|
|
||||||
help_text = f"""
|
help_text = f"""
|
||||||
Media File Renamer v{app_version}
|
moma v{app_version}
|
||||||
|
|
||||||
A powerful tool for analyzing and renaming media files with intelligent metadata extraction.
|
A powerful tool for analyzing and renaming media files with intelligent metadata extraction.
|
||||||
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user