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
|
||||
.venv
|
||||
# Test-generated files
|
||||
renamer/test/datasets/sample_mediafiles/
|
||||
src/test/datasets/sample_mediafiles/
|
||||
|
||||
Vendored
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"python.testing.pytestArgs": [
|
||||
"renamer"
|
||||
"src"
|
||||
],
|
||||
"python.testing.unittestEnabled": false,
|
||||
"python.testing.pytestEnabled": true
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
# Renamer Engineering Guide
|
||||
# moma Engineering Guide
|
||||
|
||||
**Version**: 0.7.0-dev
|
||||
**Last Updated**: 2026-01-01
|
||||
**Python**: 3.11+
|
||||
**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
|
||||
|
||||
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**:
|
||||
- **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)
|
||||
- **Python**: 3.11+
|
||||
- **License**: Not specified
|
||||
- **Repository**: `/home/sha/bin/renamer`
|
||||
- **Repository**: `/Users/sha/Developer/sha.dev/moma`
|
||||
|
||||
### Technology Stack
|
||||
|
||||
@@ -118,9 +118,9 @@ Renamer is a sophisticated Terminal User Interface (TUI) application for managin
|
||||
|
||||
## Core Components
|
||||
|
||||
### 1. Main Application (`renamer/app.py`)
|
||||
### 1. Main Application (`src/app.py`)
|
||||
|
||||
**Class**: `RenamerApp(App)`
|
||||
**Class**: `MomaApp(App)`
|
||||
|
||||
**Responsibilities**:
|
||||
- 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)
|
||||
- Real-time metadata display
|
||||
|
||||
### 2. Service Layer (`renamer/services/`)
|
||||
### 2. Service Layer (`src/services/`)
|
||||
|
||||
#### FileTreeService (`file_tree_service.py`)
|
||||
- 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
|
||||
- Markup tag stripping
|
||||
|
||||
### 3. Extractor System (`renamer/extractors/`)
|
||||
### 3. Extractor System (`src/extractors/`)
|
||||
|
||||
#### Base Protocol (`base.py`)
|
||||
```python
|
||||
@@ -232,7 +232,7 @@ year = extractor.get("year", source="Filename") # Force specific source
|
||||
- Returns None or empty collections
|
||||
- Safe final fallback in extractor chain
|
||||
|
||||
### 4. Formatter System (`renamer/formatters/`)
|
||||
### 4. Formatter System (`src/formatters/`)
|
||||
|
||||
#### Base Classes (`base.py`)
|
||||
- `Formatter`: Base ABC with abstract `format()` method
|
||||
@@ -271,7 +271,7 @@ result = FormatterApplier.apply_formatters(1024, formatters)
|
||||
- **SpecialInfoFormatter**: Edition/source formatting
|
||||
- **TextFormatter**: Text styling utilities
|
||||
|
||||
### 5. Utility Modules (`renamer/utils/`)
|
||||
### 5. Utility Modules (`src/utils/`)
|
||||
|
||||
#### PatternExtractor (`pattern_utils.py`)
|
||||
**Centralized regex pattern matching**:
|
||||
@@ -320,7 +320,7 @@ langs = extractor.extract_from_brackets("[2xUKR_ENG]")
|
||||
3. Closest height match
|
||||
4. Non-standard quality indicator detection
|
||||
|
||||
### 6. Constants (`renamer/constants/`)
|
||||
### 6. Constants (`src/constants/`)
|
||||
|
||||
**Modular organization** (8 files):
|
||||
|
||||
@@ -335,12 +335,12 @@ langs = extractor.extract_from_brackets("[2xUKR_ENG]")
|
||||
|
||||
**Backward Compatibility**: All constants exported via `__init__.py`
|
||||
|
||||
### 7. Cache Subsystem (`renamer/cache/`)
|
||||
### 7. Cache Subsystem (`src/cache/`)
|
||||
|
||||
**Unified, modular architecture**:
|
||||
|
||||
```
|
||||
renamer/cache/
|
||||
src/cache/
|
||||
├── __init__.py # Exports and convenience functions
|
||||
├── core.py # Core Cache class (thread-safe with RLock)
|
||||
├── types.py # CacheEntry, CacheStats TypedDicts
|
||||
@@ -386,16 +386,16 @@ Access via Ctrl+P:
|
||||
- Safe for concurrent extractor access
|
||||
- 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
|
||||
2. **HelpScreen**: Comprehensive help with key bindings
|
||||
3. **RenameConfirmScreen**: File rename confirmation with error handling
|
||||
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**:
|
||||
```json
|
||||
@@ -420,30 +420,30 @@ Automatic save/load with defaults.
|
||||
curl -LsSf https://astral.sh/uv/install.sh | sh
|
||||
|
||||
# Clone and sync
|
||||
cd /home/sha/bin/renamer
|
||||
cd /Users/sha/Developer/sha.dev/moma
|
||||
uv sync
|
||||
|
||||
# Install dev dependencies
|
||||
uv sync --extra dev
|
||||
|
||||
# Run from source
|
||||
uv run python renamer/main.py [directory]
|
||||
uv run python src/main.py [directory]
|
||||
```
|
||||
|
||||
### Development Commands
|
||||
|
||||
```bash
|
||||
# Run installed version
|
||||
uv run renamer [directory]
|
||||
uv run moma [directory]
|
||||
|
||||
# Run tests
|
||||
uv run pytest
|
||||
|
||||
# Run tests with coverage
|
||||
uv run pytest --cov=renamer
|
||||
uv run pytest --cov=src
|
||||
|
||||
# Type checking
|
||||
uv run mypy renamer/extractors/default_extractor.py
|
||||
uv run mypy src/extractors/default_extractor.py
|
||||
|
||||
# Version management
|
||||
uv run bump-version # Increment patch version
|
||||
@@ -460,7 +460,7 @@ uv tool install .
|
||||
|
||||
```bash
|
||||
# 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
|
||||
```
|
||||
|
||||
@@ -471,7 +471,7 @@ FORMATTER_LOG=1 uv run renamer /path/to/directory
|
||||
### Test Organization
|
||||
|
||||
```
|
||||
renamer/test/
|
||||
src/test/
|
||||
├── datasets/ # Test data
|
||||
│ ├── filenames/
|
||||
│ │ ├── filename_patterns.json # 46 test cases
|
||||
@@ -504,7 +504,7 @@ renamer/test/
|
||||
|
||||
```bash
|
||||
# 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
|
||||
@@ -524,13 +524,13 @@ file_path = get_test_file_path("movie.mkv")
|
||||
uv run pytest
|
||||
|
||||
# Specific test file
|
||||
uv run pytest renamer/test/test_services.py
|
||||
uv run pytest src/test/test_services.py
|
||||
|
||||
# With verbose output
|
||||
uv run pytest -xvs
|
||||
|
||||
# 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
|
||||
|
||||
- [ ] 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)
|
||||
- [ ] Version bumped in `pyproject.toml`
|
||||
- [ ] Dependencies synced: `uv sync`
|
||||
@@ -777,8 +777,8 @@ uv run release # Bump + sync + build
|
||||
|
||||
```
|
||||
dist/
|
||||
├── renamer-0.7.0-py3-none-any.whl # Wheel distribution
|
||||
└── renamer-0.7.0.tar.gz # Source distribution
|
||||
├── moma-0.7.0-py3-none-any.whl # Wheel distribution
|
||||
└── moma-0.7.0.tar.gz # Source distribution
|
||||
```
|
||||
|
||||
---
|
||||
@@ -788,7 +788,7 @@ dist/
|
||||
### TMDB API
|
||||
|
||||
**Configuration**:
|
||||
- API key stored in `renamer/secrets.py`
|
||||
- API key stored in `src/secrets.py`
|
||||
- Base URL: `https://api.themoviedb.org/3/`
|
||||
- Image base URL for poster downloads
|
||||
|
||||
@@ -801,7 +801,7 @@ dist/
|
||||
**Caching**:
|
||||
- API responses cached for 6 hours
|
||||
- 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
|
||||
**Maintainer**: sha
|
||||
**For**: AI Assistants and Developers
|
||||
**Repository**: `/home/sha/bin/renamer`
|
||||
**Repository**: `/Users/sha/Developer/sha.dev/moma`
|
||||
+3
-3
@@ -1,6 +1,6 @@
|
||||
# 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/),
|
||||
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`
|
||||
|
||||
#### 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
|
||||
|
||||
---
|
||||
@@ -141,7 +141,7 @@ This development version represents a significant refactoring effort focused on
|
||||
|
||||
#### Cache System
|
||||
- **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
|
||||
|
||||
#### Dependencies
|
||||
|
||||
@@ -22,7 +22,7 @@ Please read **[ENGINEERING_GUIDE.md](ENGINEERING_GUIDE.md)** for complete projec
|
||||
```bash
|
||||
uv sync --extra dev # Setup
|
||||
uv run pytest # Test
|
||||
uv run renamer [dir] # Run
|
||||
uv run moma [dir] # Run
|
||||
```
|
||||
|
||||
## Essential Principles
|
||||
|
||||
+10
-10
@@ -5,7 +5,7 @@
|
||||
|
||||
> **📘 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
|
||||
|
||||
# Clone and setup
|
||||
cd /home/sha/bin/renamer
|
||||
cd /Users/sha/Developer/sha.dev/moma
|
||||
uv sync --extra dev
|
||||
```
|
||||
|
||||
@@ -26,16 +26,16 @@ uv sync --extra dev
|
||||
|
||||
```bash
|
||||
# Run from source
|
||||
uv run renamer [directory]
|
||||
uv run moma [directory]
|
||||
|
||||
# Run tests
|
||||
uv run pytest
|
||||
|
||||
# Run with coverage
|
||||
uv run pytest --cov=renamer
|
||||
uv run pytest --cov=src
|
||||
|
||||
# Type check
|
||||
uv run mypy renamer/
|
||||
uv run mypy src/
|
||||
|
||||
# Version bump
|
||||
uv run bump-version
|
||||
@@ -53,13 +53,13 @@ uv build
|
||||
|
||||
```bash
|
||||
# Enable detailed logging
|
||||
FORMATTER_LOG=1 uv run renamer /path/to/directory
|
||||
FORMATTER_LOG=1 uv run moma /path/to/directory
|
||||
|
||||
# Check logs
|
||||
cat formatter.log
|
||||
|
||||
# Clear cache
|
||||
rm -rf ~/.cache/renamer/
|
||||
rm -rf ~/.cache/moma/
|
||||
```
|
||||
|
||||
---
|
||||
@@ -71,13 +71,13 @@ rm -rf ~/.cache/renamer/
|
||||
uv run pytest
|
||||
|
||||
# Specific file
|
||||
uv run pytest renamer/test/test_services.py
|
||||
uv run pytest src/test/test_services.py
|
||||
|
||||
# Verbose
|
||||
uv run pytest -xvs
|
||||
|
||||
# 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)
|
||||
@@ -97,7 +97,7 @@ uv run release
|
||||
uv tool install .
|
||||
|
||||
# 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)
|
||||
|
||||
+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
|
||||
|
||||
@@ -11,7 +11,7 @@ Renamer is a terminal-based media file renamer and metadata viewer built with Py
|
||||
|
||||
### 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)
|
||||
```bash
|
||||
@@ -22,22 +22,22 @@ curl -LsSf https://astral.sh/uv/install.sh | sh
|
||||
powershell -c "irm https://astral.sh/uv/install.sh | iex"
|
||||
```
|
||||
|
||||
#### Install Renamer
|
||||
#### Install moma
|
||||
```bash
|
||||
# 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)
|
||||
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)
|
||||
uv tool install renamer
|
||||
uv tool install moma
|
||||
```
|
||||
|
||||
#### Usage
|
||||
```bash
|
||||
renamer # Scan current directory
|
||||
renamer /path/to/directory # Scan specific directory
|
||||
moma # Scan current directory
|
||||
moma /path/to/directory # Scan specific directory
|
||||
```
|
||||
|
||||
### Method 2: pip Install from Wheel
|
||||
@@ -46,10 +46,10 @@ If you have the wheel file, you can install it with pip.
|
||||
|
||||
```bash
|
||||
# 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)
|
||||
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
|
||||
@@ -59,7 +59,7 @@ For development or if you want to run from source:
|
||||
#### Clone and Setup
|
||||
```bash
|
||||
git clone <repository-url>
|
||||
cd renamer
|
||||
cd moma
|
||||
|
||||
# Install dependencies
|
||||
uv sync
|
||||
@@ -120,12 +120,12 @@ python3 main.py /path/to/directory
|
||||
After installation, verify it works:
|
||||
|
||||
```bash
|
||||
renamer --help
|
||||
moma --help
|
||||
# or
|
||||
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
|
||||
|
||||
@@ -158,17 +158,17 @@ If you encounter issues:
|
||||
|
||||
### UV Tool Uninstall
|
||||
```bash
|
||||
uv tool uninstall renamer
|
||||
uv tool uninstall moma
|
||||
```
|
||||
|
||||
### pip Uninstall
|
||||
```bash
|
||||
pip uninstall renamer
|
||||
pip uninstall moma
|
||||
```
|
||||
|
||||
### Development Uninstall
|
||||
```bash
|
||||
uv tool uninstall renamer
|
||||
uv tool uninstall moma
|
||||
# Remove the cloned directory if desired
|
||||
```</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
|
||||
curl -LsSf https://astral.sh/uv/install.sh | sh
|
||||
|
||||
# Install Renamer
|
||||
cd /path/to/renamer
|
||||
# Install moma
|
||||
cd /Users/sha/Developer/sha.dev/moma
|
||||
uv sync
|
||||
uv tool install .
|
||||
```
|
||||
@@ -39,10 +39,9 @@ See [INSTALL.md](INSTALL.md) for detailed installation instructions.
|
||||
|
||||
```bash
|
||||
# Scan current directory
|
||||
renamer
|
||||
|
||||
moma
|
||||
# Scan specific directory
|
||||
renamer /path/to/media
|
||||
moma /path/to/media
|
||||
```
|
||||
|
||||
---
|
||||
@@ -97,7 +96,7 @@ Toggle with `m` key.
|
||||
|
||||
## Configuration
|
||||
|
||||
**Location**: `~/.config/renamer/config.json`
|
||||
**Location**: `~/.config/moma/config.json`
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -124,7 +123,7 @@ Access via `Ctrl+S` or edit file directly.
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
renamer/
|
||||
src/
|
||||
├── app.py # Main TUI application
|
||||
├── services/ # Business logic
|
||||
├── extractors/ # Metadata extraction
|
||||
@@ -148,7 +147,7 @@ uv sync --extra dev
|
||||
uv run pytest
|
||||
|
||||
# Run from source
|
||||
uv run renamer [directory]
|
||||
uv run moma [directory]
|
||||
```
|
||||
|
||||
See [DEVELOP.md](DEVELOP.md) for development documentation.
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
# Renamer - Refactoring Roadmap
|
||||
# moma - Refactoring Roadmap
|
||||
|
||||
**Version**: 0.7.0-dev
|
||||
**Last Updated**: 2026-01-01
|
||||
|
||||
> **📋 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
|
||||
|
||||
**Files to Modify**:
|
||||
- `renamer/formatters/proposed_name_formatter.py`
|
||||
- `src/formatters/proposed_name_formatter.py`
|
||||
- Update all usages in `app.py`, `screens.py`, etc.
|
||||
|
||||
---
|
||||
@@ -79,33 +79,33 @@ class ProposedNameFormatter:
|
||||
#### 3.6.2 Clean Up Decorators Directory
|
||||
**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**:
|
||||
```
|
||||
renamer/decorators/
|
||||
src/decorators/
|
||||
├── caching.py # ⚠️ LEGACY - Remove
|
||||
└── __init__.py # Import from renamer.cache
|
||||
└── __init__.py # Import from src.cache
|
||||
```
|
||||
|
||||
**Actions**:
|
||||
1. **Verify no direct imports** of `renamer.decorators.caching`
|
||||
2. **Remove `caching.py`** - All functionality now in `renamer/cache/decorators.py`
|
||||
3. **Keep `__init__.py`** for backward compatibility (imports from `renamer.cache`)
|
||||
4. **Update any direct imports** to use `from renamer.cache import cached_method`
|
||||
1. **Verify no direct imports** of `src.decorators.caching`
|
||||
2. **Remove `caching.py`** - All functionality now in `src/cache/decorators.py`
|
||||
3. **Keep `__init__.py`** for backward compatibility (imports from `src.cache`)
|
||||
4. **Update any direct imports** to use `from src.cache import cached_method`
|
||||
|
||||
**Verification**:
|
||||
```bash
|
||||
# Check for direct imports of old caching module
|
||||
grep -r "from renamer.decorators.caching" renamer/
|
||||
grep -r "import renamer.decorators.caching" renamer/
|
||||
grep -r "from src.decorators.caching" src/
|
||||
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**:
|
||||
- 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`
|
||||
|
||||
---
|
||||
@@ -142,7 +142,7 @@ grep -r "import renamer.decorators.caching" renamer/
|
||||
- `proposed_name_formatter.py`
|
||||
- All specialized formatters
|
||||
|
||||
#### 4.3 Integrate RenamerApp with Services
|
||||
#### 4.3 Integrate MomaApp with Services
|
||||
- Refactor `app.py` to use service layer
|
||||
- Replace direct extractor calls with `MetadataService`
|
||||
- Replace direct file operations with `RenameService`
|
||||
@@ -357,7 +357,7 @@ grep -r "import renamer.decorators.caching" renamer/
|
||||
### Phase 4 Complete When:
|
||||
- [ ] All extractors implement Protocol
|
||||
- [ ] All formatters use base classes
|
||||
- [ ] RenamerApp uses services exclusively
|
||||
- [ ] MomaApp uses services exclusively
|
||||
- [ ] No direct business logic in UI
|
||||
- [ ] All tests passing
|
||||
- [ ] No performance regression
|
||||
@@ -1,4 +1,4 @@
|
||||
# Renamer - Future Tasks
|
||||
# moma - Future Tasks
|
||||
|
||||
**Version**: 0.7.0-dev
|
||||
**Last Updated**: 2026-01-01
|
||||
@@ -18,7 +18,7 @@ This file tracks future feature enhancements and improvements.
|
||||
- [ ] **Phase 4: Refactor to New Architecture**
|
||||
- Refactor existing extractors to use Protocol
|
||||
- Refactor existing formatters to use base classes
|
||||
- Integrate RenamerApp with services
|
||||
- Integrate MomaApp with services
|
||||
- Update all imports and dependencies
|
||||
- See [REFACTORING_PROGRESS.md](REFACTORING_PROGRESS.md) for details
|
||||
|
||||
+5
-5
@@ -1,5 +1,5 @@
|
||||
[project]
|
||||
name = "renamer"
|
||||
name = "moma"
|
||||
version = "0.8.11"
|
||||
description = "Terminal-based media file renamer and metadata viewer"
|
||||
readme = "README.md"
|
||||
@@ -21,16 +21,16 @@ dev = [
|
||||
]
|
||||
|
||||
[project.scripts]
|
||||
renamer = "renamer.main:main"
|
||||
bump-version = "renamer.bump:main"
|
||||
release = "renamer.release:main"
|
||||
moma = "src.main:main"
|
||||
bump-version = "src.bump:main"
|
||||
release = "src.release:main"
|
||||
|
||||
[tool.uv]
|
||||
package = true
|
||||
|
||||
[tool.pytest.ini_options]
|
||||
addopts = "--strict-markers"
|
||||
testpaths = ["renamer/test"]
|
||||
testpaths = ["src/test"]
|
||||
python_files = ["test_*.py"]
|
||||
python_classes = ["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 = """
|
||||
/* Default technical mode: 2 columns */
|
||||
#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:
|
||||
- Multiple cache key generation strategies
|
||||
@@ -9,7 +9,7 @@ This module provides a flexible caching system with:
|
||||
|
||||
Usage Examples:
|
||||
# Using decorators
|
||||
from renamer.cache import cached, cached_api
|
||||
from src.cache import cached, cached_api
|
||||
|
||||
class MyExtractor:
|
||||
def __init__(self, file_path, cache, settings):
|
||||
@@ -28,7 +28,7 @@ Usage Examples:
|
||||
return api_call(movie_id)
|
||||
|
||||
# Using cache manager
|
||||
from renamer.cache import Cache, CacheManager
|
||||
from src.cache import Cache, CacheManager
|
||||
|
||||
cache = Cache()
|
||||
manager = CacheManager(cache)
|
||||
+2
-2
@@ -30,7 +30,7 @@ class Cache:
|
||||
"""Initialize cache with optional custom directory (only once).
|
||||
|
||||
Args:
|
||||
cache_dir: Optional cache directory path. Defaults to ~/.cache/renamer/
|
||||
cache_dir: Optional cache directory path. Defaults to ~/.cache/moma/
|
||||
"""
|
||||
# Only initialize once
|
||||
if self._initialized:
|
||||
@@ -38,7 +38,7 @@ class Cache:
|
||||
|
||||
# Always use the default cache dir to avoid creating cache in scan dir
|
||||
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.mkdir(parents=True, exist_ok=True)
|
||||
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:
|
||||
- media_constants.py: Media type definitions (MEDIA_TYPES)
|
||||
@@ -1,5 +1,5 @@
|
||||
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
|
||||
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
|
||||
once and used throughout the application.
|
||||
@@ -1,12 +1,12 @@
|
||||
import argparse
|
||||
from renamer.app import RenamerApp
|
||||
from src.app import MomaApp
|
||||
|
||||
|
||||
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")
|
||||
args = parser.parse_args()
|
||||
app = RenamerApp(args.directory)
|
||||
app = MomaApp(args.directory)
|
||||
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
|
||||
coordinate between different components. Services provide a clean separation
|
||||
@@ -15,7 +15,7 @@ import re
|
||||
from pathlib import Path
|
||||
from typing import Optional, List, Dict, Tuple
|
||||
|
||||
from renamer.extractors.extractor import MediaExtractor
|
||||
from src.extractors.extractor import MediaExtractor
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -9,7 +9,7 @@ from pathlib import Path
|
||||
from typing import Optional, Callable
|
||||
from rich.markup import escape
|
||||
|
||||
from renamer.constants import MEDIA_TYPES
|
||||
from src.constants import MEDIA_TYPES
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -13,12 +13,12 @@ from typing import Optional, Callable
|
||||
from concurrent.futures import ThreadPoolExecutor, Future
|
||||
from threading import Lock
|
||||
|
||||
from renamer.cache import Cache
|
||||
from renamer.settings import Settings
|
||||
from renamer.extractors.extractor import MediaExtractor
|
||||
from renamer.views import MediaPanelView, ProposedFilenameView
|
||||
from renamer.formatters.catalog_formatter import CatalogFormatter
|
||||
from renamer.formatters.text_formatter import TextFormatter
|
||||
from src.cache import Cache
|
||||
from src.settings import Settings
|
||||
from src.extractors.extractor import MediaExtractor
|
||||
from src.views import MediaPanelView, ProposedFilenameView
|
||||
from src.formatters.catalog_formatter import CatalogFormatter
|
||||
from src.formatters.text_formatter import TextFormatter
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -13,8 +13,8 @@ import re
|
||||
from pathlib import Path
|
||||
from typing import Optional, Callable
|
||||
|
||||
from renamer.extractors.extractor import MediaExtractor
|
||||
from renamer.views import ProposedFilenameView
|
||||
from src.extractors.extractor import MediaExtractor
|
||||
from src.views import ProposedFilenameView
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -37,7 +37,7 @@ class Settings:
|
||||
return
|
||||
|
||||
if config_dir is None:
|
||||
config_dir = Path.home() / ".config" / "renamer"
|
||||
config_dir = Path.home() / ".config" / "moma"
|
||||
self.config_dir = config_dir
|
||||
self.config_file = self.config_dir / "config.json"
|
||||
self._settings = self.DEFAULTS.copy()
|
||||
@@ -1,6 +1,6 @@
|
||||
# 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
|
||||
|
||||
@@ -17,7 +17,7 @@ datasets/
|
||||
```
|
||||
|
||||
**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
|
||||
|
||||
@@ -157,7 +157,7 @@ from pathlib import Path
|
||||
|
||||
def load_dataset(dataset_name):
|
||||
"""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)
|
||||
|
||||
# Load filename patterns
|
||||
@@ -173,7 +173,7 @@ frame_tests = load_dataset("frame_class_tests")
|
||||
```python
|
||||
import pytest
|
||||
from pathlib import Path
|
||||
from renamer.extractors.filename_extractor import FilenameExtractor
|
||||
from src.extractors.filename_extractor import FilenameExtractor
|
||||
|
||||
# Load test cases at module level
|
||||
def load_test_cases():
|
||||
@@ -224,7 +224,7 @@ def test_cyrillic_titles(load_filename_patterns):
|
||||
### Using Sample Files
|
||||
|
||||
```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
|
||||
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:**
|
||||
```bash
|
||||
# From project root
|
||||
uv run python renamer/test/fill_sample_mediafiles.py
|
||||
uv run python src/test/fill_sample_mediafiles.py
|
||||
```
|
||||
|
||||
**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
|
||||
|
||||
✅ Created: Movie Title (2020) BDRip [1080p,ukr,eng].mkv
|
||||
-18
@@ -848,24 +848,6 @@
|
||||
"category": "edge_cases",
|
||||
"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",
|
||||
"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.
|
||||
|
||||
Usage:
|
||||
uv run python renamer/test/fill_sample_mediafiles.py
|
||||
uv run python src/test/fill_sample_mediafiles.py
|
||||
|
||||
This script:
|
||||
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()
|
||||
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")
|
||||
|
||||
return True
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import pytest
|
||||
from pathlib import Path
|
||||
from renamer.cache import (
|
||||
from src.cache import (
|
||||
Cache,
|
||||
CacheManager,
|
||||
cached,
|
||||
@@ -239,13 +239,13 @@ class TestCachePackageImports:
|
||||
"""Test cache package import paths."""
|
||||
|
||||
def test_import_cache_from_package(self):
|
||||
"""Test importing Cache from renamer.cache package."""
|
||||
from renamer.cache import Cache as PackageCache
|
||||
"""Test importing Cache from src.cache package."""
|
||||
from src.cache import Cache as PackageCache
|
||||
assert PackageCache is not None
|
||||
|
||||
def test_import_decorators_from_cache(self):
|
||||
"""Test importing decorators from renamer.cache."""
|
||||
from renamer.cache import cached_method, cached, cached_api, cached_property
|
||||
"""Test importing decorators from src.cache."""
|
||||
from src.cache import cached_method, cached, cached_api, cached_property
|
||||
assert cached_method is not None
|
||||
assert cached is not None
|
||||
assert cached_api is not None
|
||||
@@ -253,7 +253,7 @@ class TestCachePackageImports:
|
||||
|
||||
def test_create_cache_convenience_function(self):
|
||||
"""Test the create_cache convenience function."""
|
||||
from renamer.cache import create_cache
|
||||
from src.cache import create_cache
|
||||
cache, manager = create_cache()
|
||||
assert cache is not None
|
||||
assert manager is not None
|
||||
@@ -1,7 +1,7 @@
|
||||
"""Tests for formatter decorators."""
|
||||
|
||||
import pytest
|
||||
from renamer.formatters import (
|
||||
from src.formatters import (
|
||||
date_decorators,
|
||||
special_info_decorators,
|
||||
text_decorators,
|
||||
@@ -1,6 +1,6 @@
|
||||
import pytest
|
||||
from pathlib import Path
|
||||
from renamer.extractors.fileinfo_extractor import FileInfoExtractor
|
||||
from src.extractors.fileinfo_extractor import FileInfoExtractor
|
||||
|
||||
|
||||
class TestFileInfoExtractor:
|
||||
@@ -7,7 +7,7 @@ import json
|
||||
from pathlib import Path
|
||||
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():
|
||||
# Load test cases from new dataset location
|
||||
@@ -4,7 +4,7 @@ Tests for base formatter classes and concrete formatter implementations.
|
||||
"""
|
||||
|
||||
import pytest
|
||||
from renamer.formatters import (
|
||||
from src.formatters import (
|
||||
Formatter,
|
||||
DataFormatter,
|
||||
MarkupFormatter,
|
||||
@@ -1,7 +1,7 @@
|
||||
import pytest
|
||||
from pathlib import Path
|
||||
from unittest.mock import MagicMock
|
||||
from renamer.extractors.mediainfo_extractor import MediaInfoExtractor
|
||||
from src.extractors.mediainfo_extractor import MediaInfoExtractor
|
||||
import json
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import sys
|
||||
import os
|
||||
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
|
||||
|
||||
# Load test cases from dataset using context manager
|
||||
@@ -1,7 +1,7 @@
|
||||
import pytest
|
||||
import json
|
||||
from pathlib import Path
|
||||
from renamer.extractors.metadata_extractor import MetadataExtractor
|
||||
from src.extractors.metadata_extractor import MetadataExtractor
|
||||
|
||||
|
||||
class TestMetadataExtractor:
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
|
||||
import pytest
|
||||
from pathlib import Path
|
||||
from renamer.views import ProposedFilenameView
|
||||
from src.views import ProposedFilenameView
|
||||
|
||||
|
||||
class TestProposedFilenameView:
|
||||
@@ -9,9 +9,9 @@ from unittest.mock import Mock, MagicMock, patch
|
||||
import tempfile
|
||||
import os
|
||||
|
||||
from renamer.services import FileTreeService, MetadataService, RenameService
|
||||
from renamer.cache import Cache
|
||||
from renamer.settings import Settings
|
||||
from src.services import FileTreeService, MetadataService, RenameService
|
||||
from src.cache import Cache
|
||||
from src.settings import Settings
|
||||
|
||||
|
||||
class TestFileTreeService:
|
||||
@@ -4,7 +4,7 @@ Tests for LanguageCodeExtractor, PatternExtractor, and FrameClassMatcher.
|
||||
"""
|
||||
|
||||
import pytest
|
||||
from renamer.utils import LanguageCodeExtractor, PatternExtractor, FrameClassMatcher
|
||||
from src.utils import LanguageCodeExtractor, PatternExtractor, FrameClassMatcher
|
||||
|
||||
|
||||
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
|
||||
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
|
||||
from typing import Optional
|
||||
|
||||
from renamer.constants import FRAME_CLASSES
|
||||
from src.constants import FRAME_CLASSES
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -9,7 +9,7 @@ import re
|
||||
from typing import Optional, Dict
|
||||
from datetime import datetime
|
||||
|
||||
from renamer.constants import MOVIE_DB_DICT
|
||||
from src.constants import MOVIE_DB_DICT
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -7,12 +7,12 @@ class HelpScreen(Screen):
|
||||
def compose(self):
|
||||
try:
|
||||
from importlib.metadata import version
|
||||
app_version = version("renamer")
|
||||
app_version = version("moma")
|
||||
except Exception:
|
||||
app_version = "unknown"
|
||||
|
||||
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.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user