release: v0.2.0 repository hygiene, CI, and docs sync
Stop tracking personal workflow artifacts at repo root, add CI and MIT license, align README and agent skills with artifacts/ defaults, and enable Ruff in dev/CI so releases are verifiable without local-only runs. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.5
Cursor
parent
e70bd35498
commit
6f0df5a774
@@ -3,11 +3,11 @@
|
||||
Tests series completeness analysis, duplicate detection, and quality comparison.
|
||||
"""
|
||||
|
||||
import pytest
|
||||
from pathlib import Path
|
||||
from datetime import datetime, timezone
|
||||
from vlm.models import SeriesIdentity, SeasonCompleteness, MovieIdentity, VideoFile, DuplicateGroup
|
||||
from vlm.analysis import analyze_series_completeness, detect_duplicates, compare_quality
|
||||
from pathlib import Path
|
||||
|
||||
from vlm.analysis import analyze_series_completeness, compare_quality, detect_duplicates
|
||||
from vlm.models import MovieIdentity, SeriesIdentity, VideoFile
|
||||
|
||||
|
||||
class TestSeriesCompletenessAnalysis:
|
||||
|
||||
@@ -4,18 +4,19 @@ Tests universal correctness properties using Hypothesis with minimum 100 iterati
|
||||
Each test validates a specific property from the design document.
|
||||
"""
|
||||
|
||||
import pytest
|
||||
from pathlib import Path
|
||||
from datetime import datetime, timezone
|
||||
from hypothesis import given, strategies as st, settings
|
||||
from vlm.models import (
|
||||
SeriesIdentity, SeasonCompleteness, MovieIdentity, VideoFile, DuplicateGroup
|
||||
)
|
||||
from vlm.analysis import analyze_series_completeness, detect_duplicates, compare_quality
|
||||
from vlm.reports import (
|
||||
generate_completeness_report, generate_duplicate_report, generate_summary_report
|
||||
)
|
||||
from pathlib import Path
|
||||
|
||||
from hypothesis import given, settings
|
||||
from hypothesis import strategies as st
|
||||
|
||||
from vlm.analysis import analyze_series_completeness, detect_duplicates
|
||||
from vlm.models import DuplicateGroup, MovieIdentity, SeasonCompleteness, SeriesIdentity, VideoFile
|
||||
from vlm.reports import (
|
||||
generate_completeness_report,
|
||||
generate_duplicate_report,
|
||||
generate_summary_report,
|
||||
)
|
||||
|
||||
# Custom strategies for generating test data
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
"""Tests for the parse CLI command."""
|
||||
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
from click.testing import CliRunner
|
||||
|
||||
|
||||
@@ -3,13 +3,10 @@
|
||||
This module tests the CLI interface for quarantine operations.
|
||||
"""
|
||||
|
||||
import json
|
||||
from pathlib import Path
|
||||
from click.testing import CliRunner
|
||||
import pytest
|
||||
from click.testing import CliRunner
|
||||
|
||||
from vlm.cli import main
|
||||
from vlm.config import Config
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
|
||||
@@ -4,10 +4,9 @@ Tests the report commands to ensure they properly wire to the Report Generator.
|
||||
"""
|
||||
|
||||
import json
|
||||
import csv
|
||||
from pathlib import Path
|
||||
from datetime import datetime, timezone
|
||||
|
||||
from click.testing import CliRunner
|
||||
|
||||
from vlm.cli import main
|
||||
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
"""Tests for CLI rollback command."""
|
||||
|
||||
import json
|
||||
from pathlib import Path
|
||||
from datetime import datetime, timezone
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
from click.testing import CliRunner
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
"""Tests for CLI scan command options."""
|
||||
|
||||
from pathlib import Path
|
||||
from unittest.mock import patch
|
||||
|
||||
from click.testing import CliRunner
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
"""Tests for CLI state commands."""
|
||||
|
||||
import json
|
||||
import tempfile
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
from click.testing import CliRunner
|
||||
|
||||
from vlm.cli import main, default_config_path
|
||||
from vlm.cli import default_config_path, main
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
"""Unit tests for Configuration Manager."""
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
import yaml
|
||||
from pathlib import Path
|
||||
from vlm.config import Config, load_config, create_default_config, validate_config
|
||||
|
||||
from vlm.config import Config, create_default_config, load_config, validate_config
|
||||
|
||||
|
||||
class TestConfig:
|
||||
@@ -311,8 +313,8 @@ class TestCreateDefaultConfig:
|
||||
"""Test that create_default_config creates parent directories."""
|
||||
config_file = tmp_path / "subdir" / "config.yaml"
|
||||
|
||||
config = create_default_config(config_file)
|
||||
|
||||
create_default_config(config_file)
|
||||
|
||||
assert config_file.exists()
|
||||
assert config_file.parent.exists()
|
||||
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
"""Integration tests for duplicate resolution with embedded video metadata."""
|
||||
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
from vlm.io import load_identities_json, identities_to_analysis_input
|
||||
from vlm.analysis import detect_duplicates
|
||||
from vlm.io import identities_to_analysis_input, load_identities_json
|
||||
|
||||
|
||||
class TestDuplicateQualityWithMetadata:
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
"""Unit tests for duplicate resolution strategies."""
|
||||
|
||||
import pytest
|
||||
from pathlib import Path
|
||||
|
||||
from vlm.models import MovieIdentity
|
||||
import pytest
|
||||
|
||||
from vlm.duplicate_resolve import DuplicateResolutionError, choose_keep_index
|
||||
from vlm.models import MovieIdentity
|
||||
|
||||
|
||||
def _mi(title: str = "Test", year: int | None = 2020) -> MovieIdentity:
|
||||
|
||||
@@ -5,7 +5,6 @@ Tests execution mode handling, dry-run simulation, and actual file operations.
|
||||
|
||||
import logging
|
||||
from datetime import datetime, timezone
|
||||
from pathlib import Path
|
||||
from uuid import uuid4
|
||||
|
||||
import pytest
|
||||
@@ -573,7 +572,7 @@ class TestRollbackLogSaving:
|
||||
data = json.load(f)
|
||||
|
||||
# Verify timestamps are in ISO format
|
||||
from datetime import datetime, timezone
|
||||
from datetime import datetime
|
||||
executed_at = datetime.fromisoformat(data["executed_at"])
|
||||
assert executed_at is not None
|
||||
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@ from vlm.io import (
|
||||
save_execution_plan,
|
||||
save_identities_json,
|
||||
)
|
||||
from vlm.models import ExecutionPlan, FileOperation, VideoFile
|
||||
from vlm.models import ExecutionPlan, FileOperation
|
||||
|
||||
|
||||
class TestVideoFileFromRecord:
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
"""Unit tests for logging configuration."""
|
||||
|
||||
import logging
|
||||
import tempfile
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
from vlm.logging_config import (
|
||||
setup_logging,
|
||||
get_logger,
|
||||
log_operation,
|
||||
MAX_LOG_SIZE,
|
||||
default_log_dir,
|
||||
get_logger,
|
||||
log_operation,
|
||||
setup_logging,
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
"""Tests for the identity parser module."""
|
||||
|
||||
import pytest
|
||||
from hypothesis import assume, given, settings
|
||||
from hypothesis import strategies as st
|
||||
|
||||
from vlm.parser import (
|
||||
group_episodes,
|
||||
normalize_title,
|
||||
parse_movie,
|
||||
parse_series,
|
||||
normalize_title,
|
||||
remove_quality_tags,
|
||||
remove_release_groups,
|
||||
)
|
||||
@@ -506,10 +509,6 @@ class TestEpisodeGrouping:
|
||||
# Property-Based Tests
|
||||
# ============================================================================
|
||||
|
||||
from hypothesis import given, strategies as st, assume, settings
|
||||
from vlm.parser import group_episodes
|
||||
import logging
|
||||
|
||||
|
||||
# Custom strategies for generating test data
|
||||
@st.composite
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
"""Security tests for path generation and execution boundaries."""
|
||||
|
||||
from datetime import datetime, timezone
|
||||
from pathlib import Path
|
||||
from uuid import uuid4
|
||||
|
||||
from vlm.config import Config
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
"""Tests for plan review helpers."""
|
||||
|
||||
import csv
|
||||
from pathlib import Path
|
||||
|
||||
from vlm.models import ExecutionPlan, FileOperation
|
||||
from vlm.plan_render import render_review_verdict
|
||||
from vlm.plan_review import (
|
||||
REVIEW_APPLIED_AT_KEY,
|
||||
build_duplicate_path_maps,
|
||||
build_identity_lookup,
|
||||
check_review_requirements,
|
||||
@@ -15,7 +13,6 @@ from vlm.plan_review import (
|
||||
review_plan,
|
||||
save_review_csv,
|
||||
)
|
||||
from vlm.plan_render import render_review_verdict
|
||||
from vlm.plan_structure_preview import build_structure_preview_lines
|
||||
from vlm.planner import apply_review_to_plan, load_plan, save_plan
|
||||
from vlm.utils import utc_now
|
||||
|
||||
+10
-7
@@ -1,10 +1,11 @@
|
||||
"""Unit tests for plan generator."""
|
||||
|
||||
import json
|
||||
import pytest
|
||||
from datetime import datetime, timezone
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
from vlm.config import Config
|
||||
from vlm.models import (
|
||||
ExecutionPlan,
|
||||
@@ -1011,7 +1012,7 @@ def test_save_plan_to_json(config, tmp_path):
|
||||
|
||||
def test_load_plan_from_json(config, tmp_path):
|
||||
"""Test loading execution plan from JSON file."""
|
||||
from vlm.planner import save_plan, load_plan
|
||||
from vlm.planner import load_plan, save_plan
|
||||
|
||||
# Create and save a plan
|
||||
video_file = VideoFile(
|
||||
@@ -1058,7 +1059,7 @@ def test_load_plan_from_json(config, tmp_path):
|
||||
|
||||
def test_save_and_load_plan_with_conflicts(config, tmp_path):
|
||||
"""Test saving and loading plan with conflict information."""
|
||||
from vlm.planner import save_plan, load_plan
|
||||
from vlm.planner import load_plan, save_plan
|
||||
|
||||
# Set up config with tmp_path as library root
|
||||
config.library_root = tmp_path
|
||||
@@ -1102,7 +1103,7 @@ def test_save_and_load_plan_with_conflicts(config, tmp_path):
|
||||
|
||||
def test_save_and_load_plan_with_no_op_operations(config, tmp_path):
|
||||
"""Test saving and loading plan with no-op operations."""
|
||||
from vlm.planner import save_plan, load_plan
|
||||
from vlm.planner import load_plan, save_plan
|
||||
|
||||
# Create files that will generate no-op operations
|
||||
files_and_identities = [
|
||||
@@ -1189,7 +1190,7 @@ def test_save_plan_json_is_human_readable(config, tmp_path):
|
||||
|
||||
def test_save_plan_with_multiple_operations(config, tmp_path):
|
||||
"""Test saving plan with multiple operations of different types."""
|
||||
from vlm.planner import save_plan, load_plan
|
||||
from vlm.planner import load_plan, save_plan
|
||||
|
||||
files_and_identities = [
|
||||
# Movie (move)
|
||||
@@ -1265,8 +1266,9 @@ def test_load_plan_file_not_found(tmp_path):
|
||||
|
||||
def test_load_plan_invalid_json(tmp_path):
|
||||
"""Test loading plan from invalid JSON raises JSONDecodeError."""
|
||||
from vlm.planner import load_plan
|
||||
import json
|
||||
|
||||
from vlm.planner import load_plan
|
||||
|
||||
invalid_json_path = tmp_path / "invalid.json"
|
||||
with open(invalid_json_path, 'w') as f:
|
||||
@@ -1278,8 +1280,9 @@ def test_load_plan_invalid_json(tmp_path):
|
||||
|
||||
def test_plan_json_includes_all_required_fields(config, tmp_path):
|
||||
"""Test that saved JSON includes plan_id, created_at, operations, and summary."""
|
||||
from vlm.planner import save_plan
|
||||
import json
|
||||
|
||||
from vlm.planner import save_plan
|
||||
|
||||
video_file = VideoFile(
|
||||
path=Path("/mnt/nas/videos/movie/Movie.2020.mkv"),
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
"""Tests for quarantine manager."""
|
||||
|
||||
import json
|
||||
import pytest
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
from datetime import datetime, timezone
|
||||
|
||||
from vlm.quarantine import QuarantineManager
|
||||
import pytest
|
||||
|
||||
from vlm.config import Config
|
||||
from vlm.models import QuarantineEntry, QuarantineManifest
|
||||
from vlm.models import QuarantineManifest
|
||||
from vlm.quarantine import QuarantineManager
|
||||
|
||||
|
||||
class TestQuarantineManager:
|
||||
|
||||
+10
-9
@@ -7,19 +7,20 @@ import csv
|
||||
import json
|
||||
import os
|
||||
import time
|
||||
import pytest
|
||||
from io import StringIO
|
||||
from pathlib import Path
|
||||
from datetime import datetime, timezone
|
||||
from vlm.models import SeasonCompleteness, DuplicateGroup, VideoFile, MovieIdentity, SeriesIdentity
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
from vlm.models import DuplicateGroup, MovieIdentity, SeasonCompleteness, SeriesIdentity, VideoFile
|
||||
from vlm.reports import (
|
||||
generate_inventory_report,
|
||||
generate_completeness_report,
|
||||
generate_duplicate_report,
|
||||
generate_summary_report,
|
||||
_format_duration,
|
||||
_format_episode_list,
|
||||
_format_size,
|
||||
_format_duration
|
||||
generate_completeness_report,
|
||||
generate_duplicate_report,
|
||||
generate_inventory_report,
|
||||
generate_summary_report,
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -4,11 +4,16 @@ Tests the complete workflow from analysis to report generation.
|
||||
"""
|
||||
|
||||
import json
|
||||
from pathlib import Path
|
||||
from datetime import datetime, timezone
|
||||
from vlm.models import SeriesIdentity, VideoFile, MovieIdentity
|
||||
from pathlib import Path
|
||||
|
||||
from vlm.analysis import analyze_series_completeness, detect_duplicates
|
||||
from vlm.reports import generate_completeness_report, generate_duplicate_report, generate_summary_report
|
||||
from vlm.models import MovieIdentity, SeriesIdentity, VideoFile
|
||||
from vlm.reports import (
|
||||
generate_completeness_report,
|
||||
generate_duplicate_report,
|
||||
generate_summary_report,
|
||||
)
|
||||
|
||||
|
||||
class TestReportsIntegration:
|
||||
|
||||
+8
-11
@@ -1,15 +1,14 @@
|
||||
"""Unit tests for the inventory scanner module."""
|
||||
|
||||
import os
|
||||
import threading
|
||||
import tempfile
|
||||
import time
|
||||
import csv
|
||||
import json
|
||||
import os
|
||||
import subprocess
|
||||
import threading
|
||||
import time
|
||||
from datetime import datetime, timezone
|
||||
from pathlib import Path
|
||||
from unittest.mock import patch, MagicMock
|
||||
import subprocess
|
||||
import json
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
import pytest
|
||||
|
||||
@@ -17,10 +16,10 @@ from vlm.config import Config
|
||||
from vlm.models import VideoFile
|
||||
from vlm.scanner import (
|
||||
categorize_file,
|
||||
scan_library,
|
||||
extract_metadata,
|
||||
save_inventory_csv,
|
||||
load_inventory_csv,
|
||||
save_inventory_csv,
|
||||
scan_library,
|
||||
)
|
||||
|
||||
|
||||
@@ -932,7 +931,6 @@ class TestInventoryReports:
|
||||
assert output_file.exists()
|
||||
|
||||
# Read and verify content
|
||||
import csv
|
||||
with open(output_file, 'r', encoding='utf-8') as f:
|
||||
# Skip comment lines
|
||||
lines = [line for line in f if not line.startswith('#')]
|
||||
@@ -1179,7 +1177,6 @@ class TestInventoryReports:
|
||||
save_inventory_json(video_files, json_file, library_root)
|
||||
|
||||
# Read CSV data
|
||||
import csv
|
||||
with open(csv_file, 'r', encoding='utf-8') as f:
|
||||
lines = [line for line in f if not line.startswith('#')]
|
||||
reader = csv.DictReader(lines)
|
||||
|
||||
+4
-7
@@ -2,16 +2,13 @@
|
||||
|
||||
import json
|
||||
import os
|
||||
import pytest
|
||||
from datetime import datetime, timezone
|
||||
from pathlib import Path
|
||||
from vlm.state import (
|
||||
load_state,
|
||||
save_state,
|
||||
StateManager,
|
||||
VALID_STATUSES
|
||||
)
|
||||
|
||||
import pytest
|
||||
|
||||
from vlm.models import FileState, StateStore
|
||||
from vlm.state import VALID_STATUSES, StateManager, load_state, save_state
|
||||
|
||||
|
||||
class TestLoadSaveState:
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
"""Tests for utility functions."""
|
||||
|
||||
import tempfile
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
from vlm.utils import canonical_path, canonical_path_str, format_size, utc_now
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user