Skip to content

Commit e77e478

Browse files
authored
Merge pull request #255 from ReadAlongs/dev.ej/pyproject.toml
Perform a complete environment refresh for Studio install, build, deploy
2 parents 75d7e27 + 15c8745 commit e77e478

18 files changed

+324
-139
lines changed

.github/workflows/matrix-tests.yml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ jobs:
2323
python-version: ${{ matrix.python-version }}
2424
- name: Install Python dependencies
2525
run: |
26-
pip install wheel
27-
pip install -r requirements.txt -r requirements.dev.txt -r requirements.ci.txt -e .
26+
pip install -e .[all]
2827
- name: Run tests
2928
run: cd test && python run.py prod

.github/workflows/tests.yml

Lines changed: 42 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,8 @@ jobs:
2424
run: |
2525
# Keep pip up to date
2626
python -m pip install --upgrade pip
27-
# Some dependencies are built using wheel
28-
pip install wheel
2927
# Install all Python dependencies in just one pip call, including Studio itself
30-
pip install -r requirements.txt \
31-
-r requirements.dev.txt \
32-
-r requirements.ci.txt \
33-
-e .
28+
pip install -e .[all]
3429
3530
- name: Run tests
3631
run: |
@@ -40,22 +35,16 @@ jobs:
4035
coverage combine
4136
coverage xml
4237
43-
- name: Exercise the Heroku Procfile
44-
run: |
45-
cmd=$(grep web: Procfile | cut -d' ' -f2-)
46-
echo "Running $cmd"
47-
$cmd &
48-
curl --retry 20 --retry-delay 1 --retry-all-errors http://127.0.0.1:8000/api/v1/docs | grep SwaggerUIBundle
49-
curl http://127.0.0.1:8000/api/v1/langs | grep Cree
50-
kill %1
51-
5238
- name: Make sure pre-commit hooks pass
5339
uses: pre-commit/action@v3.0.1
5440

55-
- name: Minimalist license check
56-
run: |
57-
# Legal check: make sure we don't have or introduce GPL dependencies
58-
if pip-licenses | grep -v 'Artistic License' | grep -v LGPL | grep GNU; then echo 'Please avoid introducing *GPL dependencies'; false; fi
41+
- name: Automated license checking
42+
# Make sure we don't have or introduce dependencies with incompatible licenses.
43+
# Exclusions where auto detection and analysis do not work:
44+
# - pympi-ling is MIT, but not auto-detected. https://github.com/dopefishh/pympi
45+
# - text-unidecode is Artistic License or GPL (at our choice): MIT is
46+
# compatible with the former. https://github.com/kmike/text-unidecode/
47+
run: licensecheck --zero --ignore-packages pympi-ling text-unidecode
5948

6049
- uses: codecov/codecov-action@v4
6150
with:
@@ -107,11 +96,7 @@ jobs:
10796
- name: Install Python dependencies
10897
run: |
10998
python -m pip install --upgrade pip
110-
pip install wheel
111-
pip install -r requirements.txt `
112-
-r requirements.dev.txt `
113-
-r requirements.ci.txt `
114-
-e .
99+
pip install -e .[all]
115100
116101
- name: Run tests on Windows
117102
run: cd test && python run.py prod
@@ -128,3 +113,36 @@ jobs:
128113
echo Reference ====
129114
cat test/data/cs-ref.readalong
130115
if (diff (cat cs.readalong) (cat test/data/cs-ref.readalong)) { throw "Output did not match reference" }
116+
117+
test-heroku-env:
118+
runs-on: ubuntu-24.04
119+
steps:
120+
- uses: actions/checkout@v4
121+
122+
- name: Read the Heroku run time env and cmd
123+
run: |
124+
echo "PYTHON_VERSION=$(cat runtime.txt | sed 's/python-//')" >> $GITHUB_ENV
125+
echo "RUNTIME_CMD=$(cat Procfile | grep web: | sed 's/web: *//')" >> $GITHUB_ENV
126+
127+
- name: Set up Python
128+
uses: actions/setup-python@v5
129+
with:
130+
python-version: ${{ env.PYTHON_VERSION }}
131+
cache: "pip"
132+
133+
- name: Install Python dependencies the way Heroku would
134+
run: |
135+
pip install -r requirements.txt
136+
bin/post_compile
137+
138+
- name: Launch the API via the Heroku Procfile
139+
run: |
140+
${{ env.RUNTIME_CMD }} &
141+
curl --retry 20 --retry-delay 1 --retry-all-errors http://127.0.0.1:8000/api/v1/docs | grep SwaggerUIBundle
142+
curl http://127.0.0.1:8000/api/v1/langs | grep Cree
143+
kill %1
144+
145+
- name: unit test the web API
146+
run: |
147+
pip install -e .[dev]
148+
python test/test_web_api.py

Contributing.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ commits.
1616
Run these commands in each of your sandboxes to enable our pre-commit hooks and commitlint:
1717

1818
```sh
19-
pip install -r requirements.dev.txt
19+
pip install -e .[dev]
2020
pre-commit install
2121
gitlint install-hook
2222
```
@@ -49,10 +49,10 @@ All the pre-commit hooks are executed using a tool called
4949
hooks each time you try to commit anything in this repo.
5050

5151
We've listed all the developper dependencies for the project in
52-
[requirements.dev.txt](requirements.dev.txt) to make them easy to install:
52+
[pyproject.toml](pyproject.toml) to make them easy to install:
5353

5454
```sh
55-
pip install -r requirements.dev.txt
55+
pip install -e .[dev]
5656
pre-commit install
5757
```
5858

@@ -114,7 +114,7 @@ commit-msg hook in Git.
114114
Run this command in your g2p sandbox to install and enable the commit-msg hook:
115115

116116
```sh
117-
pip install -r requirements/requirements.dev.txt
117+
pip install -e .[dev]
118118
gitlint install-hook
119119
```
120120

MANIFEST.in

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

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ This repo follows the [Contributor Covenant](http://contributor-covenant.org/ver
236236
You can install our standard Git hooks by running these commands in your sandbox:
237237

238238
```sh
239-
pip install -r requirements.dev.txt
239+
pip install -e .[dev]
240240
pre-commit install
241241
gitlint install-hook
242242
```

bin/post_compile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#!/bin/sh
2+
3+
# Heroku expects to run your app in place, but doesn't actually do this for you
4+
pip install -e .

docs/requirements.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,3 @@ mkdocs-material>=9.5.27
44
mkdocs-autorefs>=1.0.1
55
mkdocstrings[python]>=0.25.1
66
mike>=2.1.1
7-
-r ../requirements.min.txt

pyproject.toml

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
[build-system]
2+
requires = ["hatchling"]
3+
build-backend = "hatchling.build"
4+
5+
[project]
6+
name = "readalongs"
7+
dynamic = ["version"]
8+
requires-python = ">= 3.8"
9+
description = "ReadAlong Studio: Audiobook alignment for Indigenous languages"
10+
readme = "README.md"
11+
authors = [
12+
{ name = "Aidan Pine", email = "Aidan.Pine@nrc-cnrc.gc.ca" },
13+
{ name = "David Huggins-Daines", email = "dhd@ecolingui.ca" },
14+
{ name = "Eric Joanis", email = "Eric.Joanis@nrc-cnrc.gc.ca" },
15+
{ name = "Patrick Littell", email = "Patrick.Littell@nrc-cnrc.gc.ca" },
16+
{ name = "Delasie Torkornoo", email = "Delasie.Torkornoo@nrc-cnrc.gc.ca" },
17+
]
18+
maintainers = [
19+
{ name = "Eric Joanis", email = "Eric.Joanis@nrc-cnrc.gc.ca" },
20+
{ name = "Aidan Pine", email = "Aidan.Pine@nrc-cnrc.gc.ca" },
21+
{ name = "David Huggins-Daines", email = "dhd@ecolingui.ca" },
22+
]
23+
24+
classifiers = [
25+
"Intended Audience :: Education",
26+
"License :: OSI Approved :: MIT License",
27+
"Operating System :: OS Independent",
28+
"Programming Language :: Python :: 3",
29+
"Programming Language :: Python :: 3.8",
30+
"Programming Language :: Python :: 3.9",
31+
"Programming Language :: Python :: 3.10",
32+
"Programming Language :: Python :: 3.11",
33+
"Programming Language :: Python :: 3.12",
34+
"Programming Language :: Python :: 3.13",
35+
"Topic :: Multimedia :: Sound/Audio :: Speech",
36+
"Typing :: Typed",
37+
]
38+
39+
dependencies = [
40+
"audioop-lts; python_version>='3.13'",
41+
"chevron==0.14.0",
42+
"click>=8.0.4",
43+
"coloredlogs>=10.0",
44+
"fastapi>=0.103.0",
45+
"g2p>=1.1.20230822, <3",
46+
"lxml>=4.9.4",
47+
"numpy>=1.20.2",
48+
"pydantic>=1.8.2,<3",
49+
"pydub>=0.23.1",
50+
"pympi-ling>=1.69,<2.0",
51+
"python-slugify==5.0.0",
52+
"requests>=2.31.0",
53+
"soundswallower~=0.6.0",
54+
"webvtt-py==0.4.2",
55+
]
56+
57+
[project.optional-dependencies]
58+
dev = [
59+
"readalongs[api]",
60+
"gitlint-core>=0.17.0",
61+
"httpx>=0.24.1",
62+
"pep440>=0.1.2",
63+
"pre-commit>=2.6.0",
64+
]
65+
66+
api = [
67+
# gunivorn is only available on *nix, but it's only required for production deployments
68+
"gunicorn>=23.0.0; platform_system != 'Windows'",
69+
# uvicorn works on all platforms and is required for both dev and prod deployments
70+
"uvicorn>=0.30.1",
71+
]
72+
73+
ci = [
74+
"readalongs[api]",
75+
"coverage",
76+
"licensecheck",
77+
]
78+
79+
all = [
80+
"readalongs[dev]",
81+
"readalongs[ci]",
82+
]
83+
84+
[project.scripts]
85+
readalongs = "readalongs.cli:cli"
86+
87+
[tool.hatch.version]
88+
path = "readalongs/_version.py"
89+
90+
[tool.hatch.build.targets.sdist]
91+
include = [
92+
"/readalongs",
93+
]
94+
95+
[tool.hatch.envs.prod]
96+
features = [ "api" ]
97+
type = "pip-compile"
98+
python = "3.13"
99+
lock-filename = "requirements.txt"
100+
101+
[project.urls]
102+
Homepage = "https://github.com/ReadAlongs/"
103+
Documentation = "https://readalongs.github.io/Studio/"
104+
Repository = "https://github.com/ReadAlongs/Studio"
105+
Issues = "https://github.com/ReadAlongs/Studio/issues"
106+
Changelog = "https://github.com/ReadAlongs/Studio/releases"
107+
108+
[tool.mypy]
109+
plugins = ["pydantic.mypy"]
110+
ignore_missing_imports = true
111+
112+
[tool.isort]
113+
profile = "black"

readalongs/web_api.py

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
(or in a dashboard) and will depend on your hosting environment.
2121
2222
You can also spin up the API server grade (on Linux, not Windows) with gunicorn:
23-
pip install -r requirements.api.txt
23+
pip install -e .[api]
2424
gunicorn -w 4 -k uvicorn.workers.UvicornWorker readalongs.web_api:web_api_app
2525
2626
Once spun up, the documentation and API playground will be visible at
@@ -124,17 +124,22 @@ async def langs() -> List[SupportedLanguage]:
124124
"""Return the list of supported languages and their names as a dict.
125125
126126
Returns:
127-
Supported languages as list with language codes and mapping of
128-
language code to name, including minimally the key "_" for the
129-
default display name (usually, but not always, in English).
130-
For example:
127+
Supported languages as a list with language codes and a mapping
128+
`{ "_": "Default Display Name" }`, where the language's default display name is
129+
usually (but not always) in English.
130+
For example:
131131
132132
[
133-
{"code": "alq", names: { "alq": "Anishinaabemowin", "_": "Algonquin" }},
134-
{"code": "atj", names: { "atj": "Nehiromowin", "_": "Atikamekw" }},
135-
{"code": "fra", names: { "fra": "Français", "_": "French" }},
133+
{"code": "alq", names: { "_": "Algonquin" }},
134+
{"code": "atj", names: { "_": "Atikamekw" }},
135+
{"code": "fra", names: { "_": "French" }},
136136
...
137137
]
138+
139+
In the future, we may add localized names to this mapping with language
140+
codes as the keys, e.g.,
141+
142+
[ {"code": "alq", names: { "alq": "Anishinaabemowin", "_": "Algonquin" }}, ... ]
138143
"""
139144
langs, lang_names = LANGS
140145
return [

readme-heroku.md

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,27 @@
11
Our production Heroku deployment is controlled by the following files:
22
- `Procfile`: tells Heroku what command to launch in each Dyno;
33
- `runtime.txt`: tells Heroku which run-time engine to use (i.e., which version of Python);
4+
- `requirements.txt`: tells Heroku what our production dependencies are;
5+
- `bin/post_compile`: Heroku builds run this after doing `pip install -r requirements.txt`.
46

5-
Heroku detects Python by default, but `runtime.txt` lets us specify/bump the version as needed;
6-
- `requirements.txt`: tells Heroku what our production dependencies are.
7+
Updating dependencies:
8+
- Our dependencies are declared in `pyproject.toml`. This is where changes should be made first.
9+
- `requirements.txt` is the generated "lock" file that Heroku uses. To update it,
10+
run these commands, preferably from a Linux machine to match the Heroku context:
11+
12+
hatch env remove prod
13+
rm requirements.txt
14+
hatch env create prod
15+
16+
It is also possible to edit it manually, e.g., to handle a critical vulnerability report,
17+
but an occasional full rebuild is a good idea, to keep things up to date.
718

819
Updating `g2p`:
920
- By default, `g2p` only gets updated for `readalong-studio` on Heroku when:
10-
- we make a new release of `g2p` on PyPI
11-
- we update `requirements.min.txt` here to ask for that release
21+
- we make a new release of `g2p` on PyPI, **and**
22+
- we update `requirements.txt` here to ask for that release
1223
- Manual override: it is also possible to update g2p to the current commit on the `main` branch using this procedure:
13-
- Change `requirements.min.txt` to specify `g2p @ git+https://github.com/roedoejet/g2p@main`.
24+
- Change `requirements.txt` to specify `g2p @ git+https://github.com/roedoejet/g2p@main`.
1425
- Commit that change to `main` in a sandbox connected to Heroku.
1526
- `git push heroku main`
1627
- This will force a build which will fetch the main branch of g2p from GitHub.

requirements.api.txt

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

requirements.ci.txt

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

requirements.dev.txt

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

requirements.min.txt

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

0 commit comments

Comments
 (0)