Skip to content

Commit 89dabac

Browse files
Add new CI, and tests (#48)
1 parent 058dc2b commit 89dabac

File tree

6 files changed

+196
-54
lines changed

6 files changed

+196
-54
lines changed

.github/workflows/CI.yml

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [ "main" ]
6+
tags:
7+
- v*
8+
pull_request:
9+
branches: [ "main" ]
10+
11+
jobs:
12+
check-python-style:
13+
runs-on: ubuntu-latest
14+
steps:
15+
- uses: actions/checkout@v4
16+
with:
17+
submodules: recursive
18+
19+
- name: Set up Python 3.9
20+
uses: actions/setup-python@v5
21+
with:
22+
python-version: 3.9
23+
24+
- name: Setup UV
25+
uses: astral-sh/setup-uv@v5
26+
with:
27+
version: "latest"
28+
29+
- name: Install dependencies
30+
run: |
31+
uv pip install --system black==24.* flake8==7.* flake8-pyproject==1.* isort==5.*
32+
33+
- name: Check code format with Black
34+
run: |
35+
black --check ctc_forced_aligner/*.py
36+
37+
- name: Check imports order with isort
38+
run: |
39+
isort --check-only ctc_forced_aligner/*.py
40+
41+
- name: Check code style with Flake8
42+
run: |
43+
flake8 ctc_forced_aligner/*.py
44+
45+
build-python-wheels:
46+
needs: [check-python-style]
47+
runs-on: ${{ matrix.os }}
48+
strategy:
49+
matrix:
50+
os: [ubuntu-20.04, windows-2019, macos-14]
51+
arch: [auto64]
52+
include:
53+
- os: ubuntu-20.04
54+
arch: aarch64
55+
- os: windows-2019
56+
arch: ARM64
57+
58+
steps:
59+
- uses: actions/checkout@v4
60+
with:
61+
submodules: recursive
62+
63+
- uses: docker/setup-qemu-action@v3
64+
if: ${{ matrix.arch == 'aarch64' }}
65+
name: Set up QEMU
66+
67+
- name: Setup UV
68+
uses: astral-sh/setup-uv@v5
69+
with:
70+
version: "latest"
71+
72+
- name: Build wheels
73+
uses: pypa/[email protected]
74+
with:
75+
output-dir: python/wheelhouse
76+
env:
77+
CIBW_MANYLINUX_X86_64_IMAGE: manylinux2014
78+
CIBW_MANYLINUX_AARCH64_IMAGE: manylinux2014
79+
CIBW_ARCHS: ${{ matrix.arch }}
80+
CIBW_SKIP: pp* *-musllinux_*
81+
CIBW_BUILD_FRONTEND: "build[uv]"
82+
83+
- name: Upload Python wheels
84+
uses: actions/upload-artifact@v4
85+
with:
86+
name: python-wheels-${{ runner.os }}-${{ matrix.arch }}
87+
path: python/wheelhouse
88+
89+
test-python-wheels:
90+
# We could test the Python wheels using cibuildwheel but we prefer to run the tests outside
91+
# the build environment to ensure wheels correctly embed all dependencies.
92+
needs: [build-python-wheels]
93+
runs-on: ${{ matrix.os }}
94+
strategy:
95+
matrix:
96+
python-version: ["3.9", "3.10", "3.11", "3.12"]
97+
os: [ubuntu-20.04, windows-2019, macos-14]
98+
arch: [auto64]
99+
100+
steps:
101+
- uses: actions/checkout@v4
102+
with:
103+
submodules: recursive
104+
105+
- name: Set up Python ${{ matrix.python-version }}
106+
uses: actions/setup-python@v5
107+
with:
108+
python-version: ${{ matrix.python-version }}
109+
110+
- name: Download Python wheels
111+
uses: actions/download-artifact@v4
112+
with:
113+
pattern: python-wheels-${{ runner.os }}-${{ matrix.arch }}
114+
merge-multiple: true
115+
path: wheels
116+
117+
- name: Setup UV
118+
uses: astral-sh/setup-uv@v5
119+
with:
120+
version: "latest"
121+
122+
- name: Install wheel
123+
shell: bash
124+
run: |
125+
wheel_name=$(find wheels -type f -name "*$(echo ${{ matrix.python-version }} | tr -d '.')*")
126+
uv pip install --system "pytest-xdist" "$wheel_name[dev]" --extra-index-url https://download.pytorch.org/whl/cpu
127+
128+
- name: Run tests
129+
shell: bash
130+
run: |
131+
pytest -v -n auto tests/
132+
133+
publish-python-wheels-on-pypi:
134+
needs: [test-python-wheels]
135+
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags')
136+
runs-on: ubuntu-latest
137+
steps:
138+
- name: Download Python wheels
139+
uses: actions/download-artifact@v4
140+
with:
141+
pattern: python-wheels-*
142+
merge-multiple: true
143+
path: .
144+
145+
- name: Publish Python wheels to PyPI
146+
uses: pypa/gh-action-pypi-publish@release/v1
147+
with:
148+
user: __token__
149+
password: ${{ secrets.PYPI_API_TOKEN }}
150+
packages-dir: .

.github/workflows/test_build.yml

Lines changed: 0 additions & 50 deletions
This file was deleted.

ctc_forced_aligner/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,5 @@
1616
split_text,
1717
text_normalize,
1818
)
19+
20+
__version__ = "0.3.0"

pyproject.toml

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,20 @@ build-backend = "setuptools.build_meta"
44

55
[project]
66
name = "ctc-forced-aligner"
7-
version = "0.2"
87
description = "Text to speech alignment using CTC forced alignment"
98
license = { text = "CC-BY-NC 4.0" }
109
authors = [
1110
{name = "Mahmoud Ashraf", email = "[email protected]"},]
12-
dynamic = ["dependencies"]
11+
dynamic = ["version", "dependencies"]
12+
requires-python = ">= 3.9"
1313

1414
[tool.setuptools.dynamic]
15+
version = {attr = "ctc_forced_aligner.__version__"}
1516
dependencies = {file = ["requirements.txt"]}
1617

18+
[project.optional-dependencies]
19+
dev = ["black==23.*", "flake8==7.*", "flake8-pyproject==1.*", "isort==5.*", "pytest==7.*"]
20+
1721
[project.urls]
1822
repository = "https://github.com/MahmoudAshraf97/ctc-forced-aligner"
1923

@@ -26,4 +30,12 @@ ctc-forced-aligner = "ctc_forced_aligner.align:cli"
2630
"uroman/bin/**/*.*",
2731
"uroman/data/**/*.*",
2832
"uroman/lib/**/*.*",
29-
]
33+
]
34+
35+
[tool.flake8]
36+
max-line-length = 100
37+
ignore = ["E203", "W503"]
38+
39+
[tool.isort]
40+
profile = "black"
41+
lines_between_types = 1

setup.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
from pybind11.setup_helpers import Pybind11Extension, build_ext
22
from setuptools import setup
3+
import sys
34

45
ext_modules = [
56
Pybind11Extension(
67
"ctc_forced_aligner.ctc_forced_aligner",
78
["ctc_forced_aligner/forced_align_impl.cpp"],
8-
extra_compile_args=["-O3"],
9+
extra_compile_args=["/O2"] if sys.platform == "win32" else ["-O3"],
910
)
1011
]
1112

tests/test_alignment.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import numpy as np
2+
import pytest
3+
import torch
4+
import torchaudio.functional as F
5+
6+
from ctc_forced_aligner.alignment_utils import forced_align
7+
8+
9+
@pytest.mark.parametrize(
10+
"logprobs_size, vocab_size, targets_size",
11+
[
12+
(l, t, int(l * ratio))
13+
for l in range(100, 60101, 20000)
14+
for t in range(30, 41, 10)
15+
for ratio in [0.4, 0.6]
16+
],
17+
)
18+
def test_alignment(logprobs_size, vocab_size, targets_size):
19+
blank = 0
20+
targets = torch.randint(blank + 1, vocab_size, (1, targets_size))
21+
logprobs = torch.randn((1, logprobs_size, vocab_size + 1))
22+
logprobs = 6.5 * logprobs - 13 # same distribution as default model logits
23+
24+
ctc_alignment = forced_align(logprobs.numpy(), targets.numpy())
25+
torch_alignment = F.forced_align(logprobs, targets)
26+
27+
assert np.allclose(ctc_alignment[0], torch_alignment[0].numpy())

0 commit comments

Comments
 (0)