Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 60 additions & 10 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,10 +1,60 @@
nodes/__pycache__
__pycache__
/nodes/__pycache__
/nodes/ChatTTS/__pycache__
*.pyc
/__pycache__
/nodes/__pycache__
/nodes/__pycache__
/nodes/__pycache__
*.pyc
# Python cache files
__pycache__/
*.py[cod]
*$py.class
*.so

# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# Testing
.pytest_cache/
.coverage
htmlcov/
coverage.xml
.tox/
.nox/

# Virtual environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/

# IDE files
.vscode/
.idea/
*.swp
*.swo
*~

# Claude settings
.claude/*

# OS files
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
ehthumbs.db
Thumbs.db
Binary file modified __pycache__/__init__.cpython-311.pyc
Binary file not shown.
Binary file modified nodes/__pycache__/chat_tts.cpython-311.pyc
Binary file not shown.
3,707 changes: 3,707 additions & 0 deletions poetry.lock

Large diffs are not rendered by default.

97 changes: 97 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"

[tool.poetry]
name = "chatts-project"
version = "0.1.0"
description = "ChatTTS and OpenVoice integration project"
authors = ["Your Name <your.email@example.com>"]
readme = "README.md"
packages = [{include = "nodes"}]
exclude = ["__init__.py"]

[tool.poetry.dependencies]
python = "^3.8"
omegaconf = "~2.3.0"
tqdm = "*"
einops = "*"
vector_quantize_pytorch = "*"
vocos = "*"
pydub = "*"
faster_whisper = "*"
whisper_timestamped = "*"
inflect = "*"
unidecode = "*"
eng_to_ipa = "*"
cn2an = "*"
jieba = "*"
pybase16384 = "*"

[tool.poetry.group.test.dependencies]
pytest = "^7.4.0"
pytest-cov = "^4.1.0"
pytest-mock = "^3.11.0"


[tool.pytest.ini_options]
minversion = "6.0"
addopts = [
"-ra",
"--strict-markers",
"--strict-config",
"--cov-report=html",
"--cov-report=xml",
"--cov-report=term-missing"
]
testpaths = [
"tests",
]
norecursedirs = ["__init__.py", "*.egg", ".tox", "dist", "build"]
python_files = [
"test_*.py",
"*_test.py",
]
python_classes = [
"Test*",
]
python_functions = [
"test_*",
]
markers = [
"unit: marks tests as unit tests",
"integration: marks tests as integration tests",
"slow: marks tests as slow running",
]

[tool.coverage.run]
source = ["nodes"]
omit = [
"*/tests/*",
"*/__init__.py",
"*/conftest.py",
"*/test_*.py",
"*/*_test.py",
]

[tool.coverage.report]
exclude_lines = [
"pragma: no cover",
"def __repr__",
"if self.debug:",
"if settings.DEBUG",
"raise AssertionError",
"raise NotImplementedError",
"if 0:",
"if __name__ == .__main__.:",
"class .*\\bProtocol\\):",
"@(abc\\.)?abstractmethod",
]
show_missing = true
skip_covered = false

[tool.coverage.html]
directory = "htmlcov"

[tool.coverage.xml]
output = "coverage.xml"
Empty file added tests/__init__.py
Empty file.
168 changes: 168 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
"""
Shared pytest fixtures for the testing suite.
"""

import os
import sys
import tempfile
from pathlib import Path
from typing import Generator
import pytest
from unittest.mock import MagicMock, patch

# Mock ComfyUI dependencies before they're imported
sys.modules['folder_paths'] = MagicMock()
sys.modules['comfy'] = MagicMock()
sys.modules['comfy.model_management'] = MagicMock()


@pytest.fixture
def temp_dir() -> Generator[Path, None, None]:
"""Create a temporary directory for tests."""
with tempfile.TemporaryDirectory() as tmpdir:
yield Path(tmpdir)


@pytest.fixture
def temp_file(temp_dir: Path) -> Generator[Path, None, None]:
"""Create a temporary file in the temp directory."""
temp_file_path = temp_dir / "test_file.txt"
temp_file_path.write_text("test content")
yield temp_file_path


@pytest.fixture
def mock_config():
"""Mock configuration object."""
config = MagicMock()
config.model_path = "/mock/model/path"
config.device = "cpu"
config.sample_rate = 24000
config.temperature = 0.3
config.top_p = 0.7
config.top_k = 20
return config


@pytest.fixture
def mock_audio_data():
"""Mock audio data for testing."""
return {
"wav": [0.1, -0.2, 0.3, -0.4, 0.5] * 1000, # Mock audio samples
"sample_rate": 24000,
"duration": 2.083 # seconds
}


@pytest.fixture
def mock_text_input():
"""Mock text input for testing."""
return {
"text": "Hello, this is a test sentence for TTS.",
"language": "en",
"speaker": "default"
}


@pytest.fixture
def mock_model():
"""Mock model object."""
model = MagicMock()
model.generate = MagicMock(return_value=([0.1, -0.2, 0.3], 24000))
model.load_model = MagicMock()
model.is_loaded = True
return model


@pytest.fixture
def mock_device():
"""Mock device configuration."""
with patch('torch.cuda.is_available', return_value=False):
yield "cpu"


@pytest.fixture
def mock_logger():
"""Mock logger for testing."""
logger = MagicMock()
logger.info = MagicMock()
logger.warning = MagicMock()
logger.error = MagicMock()
logger.debug = MagicMock()
return logger


@pytest.fixture
def sample_json_data():
"""Sample JSON data for testing."""
return {
"config": {
"model_name": "ChatTTS",
"version": "1.0",
"settings": {
"temperature": 0.3,
"top_p": 0.7,
"max_length": 1000
}
},
"metadata": {
"created": "2024-01-01",
"author": "test"
}
}


@pytest.fixture
def mock_file_system(temp_dir: Path):
"""Mock file system with common test files."""
# Create mock model files
model_dir = temp_dir / "models"
model_dir.mkdir()
(model_dir / "model.pt").write_text("mock model data")
(model_dir / "config.json").write_text('{"model_type": "ChatTTS"}')

# Create mock audio files
audio_dir = temp_dir / "audio"
audio_dir.mkdir()
(audio_dir / "sample.wav").write_bytes(b"RIFF\x00\x00\x00\x00WAVEfmt ")

# Create mock output directory
output_dir = temp_dir / "output"
output_dir.mkdir()

return {
"base": temp_dir,
"models": model_dir,
"audio": audio_dir,
"output": output_dir
}


@pytest.fixture(autouse=True)
def reset_environment():
"""Reset environment variables before each test."""
# Store original values
original_env = dict(os.environ)

# Set test defaults
os.environ.setdefault('PYTEST_RUNNING', '1')

yield

# Restore original environment
os.environ.clear()
os.environ.update(original_env)


@pytest.fixture
def mock_torch_device():
"""Mock torch device selection."""
with patch('torch.cuda.is_available', return_value=False), \
patch('torch.device', return_value="cpu"):
yield


@pytest.fixture
def capture_logs(caplog):
"""Fixture to capture and provide logs for testing."""
return caplog
Empty file added tests/integration/__init__.py
Empty file.
21 changes: 21 additions & 0 deletions tests/mock_modules.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
"""
Mock modules for ComfyUI dependencies used in testing.
"""

import sys
from unittest.mock import MagicMock

# Create mock modules
folder_paths = MagicMock()
folder_paths.get_output_directory = MagicMock(return_value="/tmp/output")
folder_paths.get_temp_directory = MagicMock(return_value="/tmp/temp")
folder_paths.get_input_directory = MagicMock(return_value="/tmp/input")

comfy_module = MagicMock()
comfy_model_management = MagicMock()
comfy_model_management.get_torch_device = MagicMock(return_value="cpu")

# Install the mocks
sys.modules['folder_paths'] = folder_paths
sys.modules['comfy'] = comfy_module
sys.modules['comfy.model_management'] = comfy_model_management
Loading