Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Drop Python 3.9 support #255

Merged
merged 8 commits into from
Jan 16, 2025
Merged
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
5 changes: 3 additions & 2 deletions .github/actions/setup-uv/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ runs:
using: 'composite'
steps:
- name: Install uv
uses: astral-sh/setup-uv@v4
uses: astral-sh/setup-uv@v5
with:
version: "0.5.4"
version: "0.5.17"
enable-cache: true
cache-dependency-glob: "**/pyproject.toml"
python-version: ${{ matrix.python-version }}
6 changes: 0 additions & 6 deletions .github/workflows/style_check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,9 @@ on:
jobs:
lint:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: [3.9]
steps:
- uses: actions/checkout@v4
- name: Setup uv
uses: ./.github/actions/setup-uv
- name: Set up Python ${{ matrix.python-version }}
run: uv python install ${{ matrix.python-version }}
- name: Lint check
run: make lint
14 changes: 4 additions & 10 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,12 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: [3.9, "3.10", "3.11", "3.12"]
python-version: ["3.10", "3.11", "3.12"]
subset: ["data_tests", "inference_tests", "test_aux", "test_text"]
steps:
- uses: actions/checkout@v4
- name: Setup uv
uses: ./.github/actions/setup-uv
- name: Set up Python ${{ matrix.python-version }}
run: uv python install ${{ matrix.python-version }}
- name: Install Espeak
if: contains(fromJSON('["inference_tests", "test_text"]'), matrix.subset)
run: |
Expand All @@ -50,7 +48,7 @@ jobs:
- name: Unit tests
run: |
resolution=highest
if [ "${{ matrix.python-version }}" == "3.9" ]; then
if [ "${{ matrix.python-version }}" == "3.10" ]; then
resolution=lowest-direct
fi
uv run --resolution=$resolution --extra server --extra languages make ${{ matrix.subset }}
Expand All @@ -66,14 +64,12 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: ["3.9", "3.12"]
python-version: ["3.10", "3.12"]
subset: ["test_tts", "test_tts2", "test_vocoder", "test_xtts"]
steps:
- uses: actions/checkout@v4
- name: Setup uv
uses: ./.github/actions/setup-uv
- name: Set up Python ${{ matrix.python-version }}
run: uv python install ${{ matrix.python-version }}
- name: Install Espeak
if: contains(fromJSON('["test_tts", "test_tts2", "test_xtts"]'), matrix.subset)
run: |
Expand All @@ -94,7 +90,7 @@ jobs:
- name: Integration tests
run: |
resolution=highest
if [ "${{ matrix.python-version }}" == "3.9" ]; then
if [ "${{ matrix.python-version }}" == "3.10" ]; then
resolution=lowest-direct
fi
uv run --resolution=$resolution --extra server --extra languages make ${{ matrix.subset }}
Expand All @@ -116,8 +112,6 @@ jobs:
- uses: actions/checkout@v4
- name: Setup uv
uses: ./.github/actions/setup-uv
- name: Set up Python ${{ matrix.python-version }}
run: uv python install ${{ matrix.python-version }}
- name: Install Espeak
run: |
sudo apt-get update
Expand Down
8 changes: 2 additions & 6 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,9 @@ repos:
- id: check-yaml
- id: end-of-file-fixer
- id: trailing-whitespace
- repo: "https://github.com/psf/black"
rev: 24.2.0
hooks:
- id: black
language_version: python3
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.7.0
rev: v0.9.1
hooks:
- id: ruff
args: [--fix, --exit-non-zero-on-fix]
- id: ruff-format
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ curl -LsSf https://astral.sh/uv/install.sh | sh
uv run make test_all # run all the tests, report all the errors
```

9. Format your code. We use ```black``` for code formatting.
9. Format your code. We use ```ruff``` for code formatting.

```bash
make style
Expand Down
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,11 @@ test_failed: ## only run tests failed the last time.
coverage run -m pytest -x -v --last-failed tests

style: ## update code style.
uv run --only-dev black ${target_dirs}
uv run --only-dev ruff format ${target_dirs}

lint: ## run linters.
uv run --only-dev ruff check ${target_dirs}
uv run --only-dev black ${target_dirs} --check
uv run --only-dev ruff format ${target_dirs} --check

system-deps: ## install linux system deps
sudo apt-get install -y libsndfile1-dev
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ You can also help us implement more models.
<!-- start installation -->
## Installation

🐸TTS is tested on Ubuntu 24.04 with **python >= 3.9, < 3.13**, but should also
🐸TTS is tested on Ubuntu 24.04 with **python >= 3.10, < 3.13**, but should also
work on Mac and Windows.

If you are only interested in [synthesizing speech](https://coqui-tts.readthedocs.io/en/latest/inference.html) with the pretrained 🐸TTS models, installing from PyPI is the easiest option.
Expand Down
77 changes: 38 additions & 39 deletions TTS/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import tempfile
import warnings
from pathlib import Path
from typing import Optional, Union

from torch import nn

Expand All @@ -22,15 +21,15 @@ def __init__(
self,
model_name: str = "",
*,
model_path: Optional[str] = None,
config_path: Optional[str] = None,
vocoder_name: Optional[str] = None,
vocoder_path: Optional[str] = None,
vocoder_config_path: Optional[str] = None,
encoder_path: Optional[str] = None,
encoder_config_path: Optional[str] = None,
speakers_file_path: Optional[str] = None,
language_ids_file_path: Optional[str] = None,
model_path: str | None = None,
config_path: str | None = None,
vocoder_name: str | None = None,
vocoder_path: str | None = None,
vocoder_config_path: str | None = None,
encoder_path: str | None = None,
encoder_config_path: str | None = None,
speakers_file_path: str | None = None,
language_ids_file_path: str | None = None,
progress_bar: bool = True,
gpu: bool = False,
) -> None:
Expand Down Expand Up @@ -77,8 +76,8 @@ def __init__(
super().__init__()
self.manager = ModelManager(models_file=self.get_models_file_path(), progress_bar=progress_bar)
self.config = load_config(config_path) if config_path else None
self.synthesizer: Optional[Synthesizer] = None
self.voice_converter: Optional[Synthesizer] = None
self.synthesizer: Synthesizer | None = None
self.voice_converter: Synthesizer | None = None
self.model_name = ""

self.vocoder_path = vocoder_path
Expand Down Expand Up @@ -156,8 +155,8 @@ def list_models() -> list[str]:
return ModelManager(models_file=TTS.get_models_file_path(), progress_bar=False).list_models()

def download_model_by_name(
self, model_name: str, vocoder_name: Optional[str] = None
) -> tuple[Optional[Path], Optional[Path], Optional[Path], Optional[Path], Optional[Path]]:
self, model_name: str, vocoder_name: str | None = None
) -> tuple[Path | None, Path | None, Path | None, Path | None, Path | None]:
model_path, config_path, model_item = self.manager.download_model(model_name)
if "fairseq" in model_name or (model_item is not None and isinstance(model_item["model_url"], list)):
# return model directory if there are multiple files
Expand All @@ -176,7 +175,7 @@ def download_model_by_name(
vocoder_path, vocoder_config_path, _ = self.manager.download_model(vocoder_name)
return model_path, config_path, vocoder_path, vocoder_config_path, None

def load_model_by_name(self, model_name: str, vocoder_name: Optional[str] = None, *, gpu: bool = False) -> None:
def load_model_by_name(self, model_name: str, vocoder_name: str | None = None, *, gpu: bool = False) -> None:
"""Load one of the 🐸TTS models by name.

Args:
Expand All @@ -185,7 +184,7 @@ def load_model_by_name(self, model_name: str, vocoder_name: Optional[str] = None
"""
self.load_tts_model_by_name(model_name, vocoder_name, gpu=gpu)

def load_vc_model_by_name(self, model_name: str, vocoder_name: Optional[str] = None, *, gpu: bool = False) -> None:
def load_vc_model_by_name(self, model_name: str, vocoder_name: str | None = None, *, gpu: bool = False) -> None:
"""Load one of the voice conversion models by name.

Args:
Expand All @@ -205,7 +204,7 @@ def load_vc_model_by_name(self, model_name: str, vocoder_name: Optional[str] = N
use_cuda=gpu,
)

def load_tts_model_by_name(self, model_name: str, vocoder_name: Optional[str] = None, *, gpu: bool = False) -> None:
def load_tts_model_by_name(self, model_name: str, vocoder_name: str | None = None, *, gpu: bool = False) -> None:
"""Load one of 🐸TTS models by name.

Args:
Expand Down Expand Up @@ -261,11 +260,11 @@ def load_tts_model_by_path(self, model_path: str, config_path: str, *, gpu: bool

def _check_arguments(
self,
speaker: Optional[str] = None,
language: Optional[str] = None,
speaker_wav: Optional[str] = None,
emotion: Optional[str] = None,
speed: Optional[float] = None,
speaker: str | None = None,
language: str | None = None,
speaker_wav: str | None = None,
emotion: str | None = None,
speed: float | None = None,
**kwargs,
) -> None:
"""Check if the arguments are valid for the model."""
Expand All @@ -284,11 +283,11 @@ def _check_arguments(
def tts(
self,
text: str,
speaker: Optional[str] = None,
language: Optional[str] = None,
speaker_wav: Optional[str] = None,
emotion: Optional[str] = None,
speed: Optional[float] = None,
speaker: str | None = None,
language: str | None = None,
speaker_wav: str | None = None,
emotion: str | None = None,
speed: float | None = None,
split_sentences: bool = True,
**kwargs,
):
Expand Down Expand Up @@ -333,10 +332,10 @@ def tts(
def tts_to_file(
self,
text: str,
speaker: Optional[str] = None,
language: Optional[str] = None,
speaker_wav: Optional[str] = None,
emotion: Optional[str] = None,
speaker: str | None = None,
language: str | None = None,
speaker_wav: str | None = None,
emotion: str | None = None,
speed: float = 1.0,
pipe_out=None,
file_path: str = "output.wav",
Expand Down Expand Up @@ -388,7 +387,7 @@ def tts_to_file(
def voice_conversion(
self,
source_wav: str,
target_wav: Union[str, list[str]],
target_wav: str | list[str],
):
"""Voice conversion with FreeVC. Convert source wav to target speaker.

Expand All @@ -406,7 +405,7 @@ def voice_conversion(
def voice_conversion_to_file(
self,
source_wav: str,
target_wav: Union[str, list[str]],
target_wav: str | list[str],
file_path: str = "output.wav",
pipe_out=None,
) -> str:
Expand All @@ -430,9 +429,9 @@ def tts_with_vc(
self,
text: str,
*,
language: Optional[str] = None,
speaker_wav: Union[str, list[str]],
speaker: Optional[str] = None,
language: str | None = None,
speaker_wav: str | list[str],
speaker: str | None = None,
split_sentences: bool = True,
):
"""Convert text to speech with voice conversion.
Expand Down Expand Up @@ -473,10 +472,10 @@ def tts_with_vc_to_file(
self,
text: str,
*,
language: Optional[str] = None,
speaker_wav: Union[str, list[str]],
language: str | None = None,
speaker_wav: str | list[str],
file_path: str = "output.wav",
speaker: Optional[str] = None,
speaker: str | None = None,
split_sentences: bool = True,
pipe_out=None,
) -> str:
Expand Down
5 changes: 2 additions & 3 deletions TTS/bin/compute_embeddings.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import os
import sys
from argparse import RawTextHelpFormatter
from typing import Optional

import torch
from tqdm import tqdm
Expand All @@ -16,7 +15,7 @@
from TTS.utils.generic_utils import ConsoleFormatter, setup_logger


def parse_args(arg_list: Optional[list[str]]) -> argparse.Namespace:
def parse_args(arg_list: list[str] | None) -> argparse.Namespace:
parser = argparse.ArgumentParser(
description="""Compute embedding vectors for each audio file in a dataset and store them keyed by `{dataset_name}#{file_path}` in a .pth file\n\n"""
"""
Expand Down Expand Up @@ -185,7 +184,7 @@ def compute_embeddings(
print("Speaker embeddings saved at:", mapping_file_path)


def main(arg_list: Optional[list[str]] = None):
def main(arg_list: list[str] | None = None):
setup_logger("TTS", level=logging.INFO, stream=sys.stdout, formatter=ConsoleFormatter())
args = parse_args(arg_list)

Expand Down
6 changes: 2 additions & 4 deletions TTS/bin/compute_statistics.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import argparse
import glob
import logging
import os
import sys
from typing import Optional

import numpy as np
from tqdm import tqdm
Expand All @@ -18,7 +16,7 @@
from TTS.utils.generic_utils import ConsoleFormatter, setup_logger


def parse_args(arg_list: Optional[list[str]]) -> tuple[argparse.Namespace, list[str]]:
def parse_args(arg_list: list[str] | None) -> tuple[argparse.Namespace, list[str]]:
parser = argparse.ArgumentParser(description="Compute mean and variance of spectrogtram features.")
parser.add_argument("config_path", type=str, help="TTS config file path to define audio processin parameters.")
parser.add_argument("out_path", type=str, help="save path (directory and filename).")
Expand All @@ -31,7 +29,7 @@ def parse_args(arg_list: Optional[list[str]]) -> tuple[argparse.Namespace, list[
return parser.parse_known_args(arg_list)


def main(arg_list: Optional[list[str]] = None):
def main(arg_list: list[str] | None = None):
"""Run preprocessing process."""
setup_logger("TTS", level=logging.INFO, stream=sys.stderr, formatter=ConsoleFormatter())
args, overrides = parse_args(arg_list)
Expand Down
5 changes: 2 additions & 3 deletions TTS/bin/extract_tts_spectrograms.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import logging
import sys
from pathlib import Path
from typing import Optional

import numpy as np
import torch
Expand All @@ -27,7 +26,7 @@
use_cuda = torch.cuda.is_available()


def parse_args(arg_list: Optional[list[str]]) -> argparse.Namespace:
def parse_args(arg_list: list[str] | None) -> argparse.Namespace:
parser = argparse.ArgumentParser()
parser.add_argument("--config_path", type=str, help="Path to config file for training.", required=True)
parser.add_argument("--checkpoint_path", type=str, help="Model file to be restored.", required=True)
Expand Down Expand Up @@ -244,7 +243,7 @@ def extract_spectrograms(
f.write(f"{data[0] / data[1]}.npy\n")


def main(arg_list: Optional[list[str]] = None) -> None:
def main(arg_list: list[str] | None = None) -> None:
setup_logger("TTS", level=logging.INFO, stream=sys.stdout, formatter=ConsoleFormatter())
args = parse_args(arg_list)
config = load_config(args.config_path)
Expand Down
Loading