From 09b7c2cf1e03802406aac1786906afdf4e88e707 Mon Sep 17 00:00:00 2001 From: remsky Date: Sun, 9 Feb 2025 23:01:53 -0700 Subject: [PATCH] Update README badges and add script to automate badge updates --- README.md | 8 ++- pyproject.toml | 1 + scripts/update_badges.py | 138 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 144 insertions(+), 3 deletions(-) create mode 100644 scripts/update_badges.py diff --git a/README.md b/README.md index 55088f8..c8a26ef 100644 --- a/README.md +++ b/README.md @@ -4,12 +4,14 @@ # _`FastKoko`_ [![Tests](https://img.shields.io/badge/tests-69%20passed-darkgreen)]() -[![Coverage](https://img.shields.io/badge/coverage-51%25-tan)]() +[![Coverage](https://img.shields.io/badge/coverage-52%25-tan)]() [![Try on Spaces](https://img.shields.io/badge/%F0%9F%A4%97%20Try%20on-Spaces-blue)](https://huggingface.co/spaces/Remsky/Kokoro-TTS-Zero) +[![Kokoro](https://img.shields.io/badge/kokoro-v0.7.9::31a2b63-BB5420)]() +[![Misaki](https://img.shields.io/badge/misaki-v0.7.9::ebc76c2-B8860B)]() + [![Tested at Model Commit](https://img.shields.io/badge/last--tested--model--commit-1.0::9901c2b-blue)](https://huggingface.co/hexgrad/Kokoro-82M/commit/9901c2b79161b6e898b7ea857ae5298f47b8b0d6) -[![Kokoro](https://img.shields.io/badge/kokoro-v0.7.9-BB5420)]() -[![Misaki](https://img.shields.io/badge/misaki-v0.7.9-B8860B)]() + Dockerized FastAPI wrapper for [Kokoro-82M](https://huggingface.co/hexgrad/Kokoro-82M) text-to-speech model - Multi-language support (English, Japanese, Korean, Chinese, Vietnamese) diff --git a/pyproject.toml b/pyproject.toml index 2c9ebda..336519e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -52,6 +52,7 @@ test = [ "httpx==0.26.0", "pytest-asyncio==0.23.5", "openai>=1.59.6", + "tomli>=2.0.1", ] [tool.uv] diff --git a/scripts/update_badges.py b/scripts/update_badges.py new file mode 100644 index 0000000..dd5d6c4 --- /dev/null +++ b/scripts/update_badges.py @@ -0,0 +1,138 @@ +import re +import subprocess +import tomli +from pathlib import Path + +def extract_dependency_info(): + """Extract version and commit hash for kokoro and misaki from pyproject.toml""" + with open("pyproject.toml", "rb") as f: + pyproject = tomli.load(f) + + deps = pyproject["project"]["dependencies"] + info = {} + + # Extract kokoro info + for dep in deps: + if dep.startswith("kokoro @"): + # Extract version from the dependency string if available + version_match = re.search(r"kokoro @ git\+https://github\.com/hexgrad/kokoro\.git@", dep) + if version_match: + # If no explicit version, use v0.7.9 as shown in the README + version = "v0.7.9" + commit_match = re.search(r"@([a-f0-9]{7})", dep) + if commit_match: + info["kokoro"] = { + "version": version, + "commit": commit_match.group(1) + } + elif dep.startswith("misaki["): + # Extract version from the dependency string if available + version_match = re.search(r"misaki\[.*?\] @ git\+https://github\.com/hexgrad/misaki\.git@", dep) + if version_match: + # If no explicit version, use v0.7.9 as shown in the README + version = "v0.7.9" + commit_match = re.search(r"@([a-f0-9]{7})", dep) + if commit_match: + info["misaki"] = { + "version": version, + "commit": commit_match.group(1) + } + + return info + +def run_pytest_with_coverage(): + """Run pytest with coverage and return the results""" + try: + # Run pytest with coverage + result = subprocess.run( + ["pytest", "--cov=api", "-v"], + capture_output=True, + text=True, + check=True + ) + + # Extract test results + test_output = result.stdout + passed_tests = len(re.findall(r"PASSED", test_output)) + + # Extract coverage from .coverage file + coverage_output = subprocess.run( + ["coverage", "report"], + capture_output=True, + text=True, + check=True + ).stdout + + # Extract total coverage percentage + coverage_match = re.search(r"TOTAL\s+\d+\s+\d+\s+(\d+)%", coverage_output) + coverage_percentage = coverage_match.group(1) if coverage_match else "0" + + return passed_tests, coverage_percentage + except subprocess.CalledProcessError as e: + print(f"Error running tests: {e}") + print(f"Output: {e.output}") + return 0, "0" + +def update_readme_badges(passed_tests, coverage_percentage, dep_info): + """Update the badges in the README file""" + readme_path = Path("README.md") + if not readme_path.exists(): + print("README.md not found") + return False + + content = readme_path.read_text() + + # Update tests badge + content = re.sub( + r'!\[Tests\]\(https://img\.shields\.io/badge/tests-\d+%20passed-[a-zA-Z]+\)', + f'![Tests](https://img.shields.io/badge/tests-{passed_tests}%20passed-darkgreen)', + content + ) + + # Update coverage badge + content = re.sub( + r'!\[Coverage\]\(https://img\.shields\.io/badge/coverage-\d+%25-[a-zA-Z]+\)', + f'![Coverage](https://img.shields.io/badge/coverage-{coverage_percentage}%25-tan)', + content + ) + + # Update kokoro badge + if "kokoro" in dep_info: + content = re.sub( + r'!\[Kokoro\]\(https://img\.shields\.io/badge/kokoro-[^)]+\)', + f'![Kokoro](https://img.shields.io/badge/kokoro-{dep_info["kokoro"]["version"]}::{dep_info["kokoro"]["commit"]}-BB5420)', + content + ) + + # Update misaki badge + if "misaki" in dep_info: + content = re.sub( + r'!\[Misaki\]\(https://img\.shields\.io/badge/misaki-[^)]+\)', + f'![Misaki](https://img.shields.io/badge/misaki-{dep_info["misaki"]["version"]}::{dep_info["misaki"]["commit"]}-B8860B)', + content + ) + + readme_path.write_text(content) + return True + +def main(): + # Get dependency info + dep_info = extract_dependency_info() + + # Run tests and get coverage + passed_tests, coverage_percentage = run_pytest_with_coverage() + + # Update badges + if update_readme_badges(passed_tests, coverage_percentage, dep_info): + print(f"Updated badges:") + print(f"- Tests: {passed_tests} passed") + print(f"- Coverage: {coverage_percentage}%") + if "kokoro" in dep_info: + print(f"- Kokoro: {dep_info['kokoro']['version']}::{dep_info['kokoro']['commit']}") + if "misaki" in dep_info: + print(f"- Misaki: {dep_info['misaki']['version']}::{dep_info['misaki']['commit']}") + else: + print("Failed to update badges") + +if __name__ == "__main__": + main() \ No newline at end of file