Skip to content

Commit edfa117

Browse files
committed
migrate poetry -> uv
1 parent 14c10a4 commit edfa117

14 files changed

Lines changed: 2070 additions & 2097 deletions

File tree

‎.claude/archive/AGENT_PROMPT_WRITE_TESTS.md‎

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ Tests for the `flm.main` module and its submodules go in `test/main/`. All other
1010

1111
**flm-core** is a Python library implementing *Flexible Latex-like Markup* (FLM): an approximate subset of LaTeX syntax parsed via `pylatexenc` (v3 pre-release) and rendered to multiple output formats (HTML, LaTeX, plain text, Markdown). The codebase is also transpiled to JavaScript via Transcrypt, which constrains Python idioms.
1212

13-
Packages are managed via `poetry`. Run tests with `poetry run python -m pytest test/ -v`.
13+
Packages are managed via `uv`. Run tests with `uv run python -m pytest test/ -v`.
1414

1515
## Critical Rules
1616

@@ -36,7 +36,7 @@ If you need an "in" check, write `self.assertTrue(x in items)`.
3636
### Test Quality Requirements
3737

3838
1. **Exact output matching**: Use `self.assertEqual(result, expected)` with the full expected output. Do NOT use `self.assertTrue(substring in result)` for testing rendered output.
39-
2. **To get exact outputs**: render the FLM input first by running the code, capture the actual output, then verify it is correct, then use that as the assertEqual expectation. You can run snippets via `poetry run python -c "..."` to see actual outputs before writing assertions.
39+
2. **To get exact outputs**: render the FLM input first by running the code, capture the actual output, then verify it is correct, then use that as the assertEqual expectation. You can run snippets via `uv run python -c "..."` to see actual outputs before writing assertions.
4040
3. **Test file naming**: `test/test_<module>.py` for core and feature modules, `test/main/test_main_<submodule>.py` for main submodules.
4141
4. **One test class per logical group** (e.g. `TestFeatureQuoteRendering`, `TestFeatureQuoteInit`, `TestFeatureQuoteRecomposer`).
4242
5. **Set `maxDiff = None`** on test classes that compare rendered output.
@@ -166,7 +166,7 @@ Skip these main submodules (they involve filesystem/process operations not suita
166166
3. **Decide**: if existing tests are already high quality with exact assertions and good coverage, skip to the next module. If they need improvement, **keep the existing tests** and add any additional test cases you deem necessary. If existing tests are incomplete, add more tests to test other inputs or edge cases that were missed.
167167
4. **Capture actual outputs** by running the code first:
168168
```bash
169-
poetry run python -c "
169+
uv run python -c "
170170
from flm.flmenvironment import make_standard_environment
171171
from flm.stdfeatures import standard_features
172172
from flm.fragmentrenderer.html import HtmlFragmentRenderer
@@ -177,11 +177,11 @@ Skip these main submodules (they involve filesystem/process operations not suita
177177
```
178178
5. **CHECK THE OUTPUTS**: Make sure that the outputs are indeed expected for the test code you designed. Flag any suspicious behavior or suspected bug with a comment `# REVIEW: <note>` in the source code. Only fix the source code itself if the error is a typo or a missing import. In all other cases, keep the failing test and mark it to be skipped pending code review.
179179
6. **Write the test file** with exact assertEqual assertions using the captured outputs, for test cases whose outputs match the expected output.
180-
7. **Run the tests** for that module: `poetry run python -m pytest test/test_<module>.py -v`
180+
7. **Run the tests** for that module: `uv run python -m pytest test/test_<module>.py -v`
181181
8. **Fix any failures** — if the expected output doesn't match, re-capture and correct. Flag suspicious behavior (see point 5.) instead of adapting the test itself to the suspicious behavior.
182-
9. **Run the full test suite** periodically: `poetry run python -m pytest test/ -v` to check for regressions.
182+
9. **Run the full test suite** periodically: `uv run python -m pytest test/ -v` to check for regressions.
183183
10. **When you're finished with the module** — read the module again and identify classes, functions, methods, or attributes that are not sufficiently well tested according to the standards specified here. If you find any, complete the tests.
184-
11. **Check also the JS-transpiled tests** — by running `(cd flm-js && poetry run python ./generate_flm_js.py --pylatexenc-src-dir=../../pylatexenc --delete-target-dir --compile-tests && node test-flm-js/runtests.js)`. If tests fail, identify the failure location and identify its cause. Do not change the test logic. Remove the test only if it is clearly unnecessary. Ask for the user's input if fixing the test involves anything else than minor refactoring to remove a feature not supported by transcrypt. JS output and Python output must be the same (except for string-formatted floating-point numbers).
184+
11. **Check also the JS-transpiled tests** — by running `(cd flm-js && uv run --group buildjslib python ./generate_flm_js.py --pylatexenc-src-dir=../../pylatexenc --delete-target-dir --compile-tests && node test-flm-js/runtests.js)`. If tests fail, identify the failure location and identify its cause. Do not change the test logic. Remove the test only if it is clearly unnecessary. Ask for the user's input if fixing the test involves anything else than minor refactoring to remove a feature not supported by transcrypt. JS output and Python output must be the same (except for string-formatted floating-point numbers).
185185

186186

187187
## What to Test Per Module

‎.github/workflows/deploy-pypi.yml‎

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,26 +13,20 @@ jobs:
1313
strategy:
1414
matrix:
1515
python-version: ["3.11"]
16-
poetry-version: ["1.4"]
1716

1817
environment: env-deploy-pypi
1918

2019
steps:
2120
- uses: actions/checkout@v3
2221

23-
- uses: actions/setup-python@v4
22+
- name: 'Set up uv'
23+
uses: astral-sh/setup-uv@v5
2424
with:
25+
enable-cache: true
2526
python-version: '${{ matrix.python-version }}'
2627

27-
- name: 'Set up poetry - Run image'
28-
uses: abatilo/actions-poetry@v2
29-
with:
30-
poetry-version: '${{ matrix.poetry-version }}'
31-
32-
- name: 'Poetry Build Package'
33-
run: poetry build
34-
35-
- name: 'Poetry Publish package'
36-
run: 'poetry publish -p ${{ secrets.PYPI_API_TOKEN}} -u __token__'
28+
- name: 'uv Build Package'
29+
run: 'uv build'
3730

38-
31+
- name: 'uv Publish package'
32+
run: 'uv publish --token ${{ secrets.PYPI_API_TOKEN }}'

‎.github/workflows/tests-ci-js.yml‎

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,6 @@ jobs:
1818
matrix:
1919
python-version:
2020
- "3.11"
21-
poetry-version:
22-
- "1.4"
2321
node-version:
2422
- "14"
2523
- "19"
@@ -39,24 +37,23 @@ jobs:
3937
- name: 'Setting up some node packages'
4038
run: 'npm i debug'
4139

42-
# Poetry & Python are needed to transpile Python library
43-
- uses: actions/setup-python@v4
40+
# uv & Python are needed to transpile Python library
41+
- name: 'Set up uv'
42+
uses: astral-sh/setup-uv@v5
4443
with:
44+
enable-cache: true
4545
python-version: '${{ matrix.python-version }}'
4646

47-
- name: 'Set up poetry - Run image'
48-
uses: abatilo/actions-poetry@v2
49-
50-
- name: 'Poetry Install (with buildjslib)'
51-
run: 'poetry install --with buildjslib'
47+
- name: 'uv sync (with buildjslib)'
48+
run: 'uv sync --group buildjslib'
5249

5350
- name: 'Check out pylatexenc v3 sources'
5451
working-directory: 'flm-js'
5552
run: 'git clone https://github.com/phfaist/pylatexenc.git pylatexenc-src --depth=1'
5653

5754
- name: 'Generate LLM JS library'
5855
working-directory: 'flm-js'
59-
run: 'poetry run python ./generate_flm_js.py --pylatexenc-src-dir=./pylatexenc-src/ --compile-tests'
56+
run: 'uv run --no-sync python ./generate_flm_js.py --pylatexenc-src-dir=./pylatexenc-src/ --compile-tests'
6057

6158
- name: 'Run JS tests'
6259
working-directory: 'flm-js'

‎.github/workflows/tests-ci.yml‎

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,24 +21,22 @@ jobs:
2121
- "3.11"
2222
- "3.12"
2323
- "3.13"
24-
poetry-version:
25-
- "1.4"
2624
os:
2725
- 'ubuntu-latest'
2826

2927
runs-on: '${{ matrix.os }}'
3028

3129
steps:
3230
- uses: actions/checkout@v3
33-
- uses: actions/setup-python@v4
31+
32+
- name: 'Set up uv'
33+
uses: astral-sh/setup-uv@v5
3434
with:
35+
enable-cache: true
3536
python-version: '${{ matrix.python-version }}'
36-
- name: 'Set up poetry - Run image'
37-
uses: abatilo/actions-poetry@v2
38-
with:
39-
poetry-version: '${{ matrix.poetry-version }}'
40-
- name: 'Poetry Install'
41-
run: poetry install -E maincmdl
37+
38+
- name: 'uv sync'
39+
run: 'uv sync --extra maincmdl'
4240

4341
- name: 'Run tests'
44-
run: poetry run pytest
42+
run: 'uv run --no-sync pytest'

‎.readthedocs.yaml‎

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
# Read the Docs configuration file
22
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
33

4-
# See poetry builds on RTD:
5-
# https://docs.readthedocs.io/en/stable/build-customization.html#install-dependencies-with-poetry
4+
# See uv builds on RTD:
5+
# https://docs.readthedocs.io/en/stable/build-customization.html#install-dependencies-with-uv
66

77
# Required
88
version: 2
@@ -17,16 +17,16 @@ build:
1717
jobs:
1818

1919
post_create_environment:
20-
# Install poetry
21-
# https://python-poetry.org/docs/#installing-manually
22-
- 'pip install "poetry>=1.4"'
20+
# Install uv
21+
# https://docs.astral.sh/uv/getting-started/installation/
22+
- 'pip install uv'
2323

2424
post_install:
25-
# Install dependencies with 'docs' dependency group
26-
# https://python-poetry.org/docs/managing-dependencies/#dependency-groups
27-
# VIRTUAL_ENV needs to be set manually for now.
28-
# See https://github.com/readthedocs/readthedocs.org/pull/11152/
29-
- 'VIRTUAL_ENV=$READTHEDOCS_VIRTUALENV_PATH poetry install --extras maincmdl --with builddoc'
25+
# Install dependencies with the 'builddoc' dependency group.
26+
# '--active' installs into the virtualenv that RTD created for us rather
27+
# than into a project-local '.venv'; '--inexact' leaves the packages that
28+
# RTD itself put there alone.
29+
- 'VIRTUAL_ENV=$READTHEDOCS_VIRTUALENV_PATH uv sync --active --inexact --extra maincmdl --group builddoc'
3030

3131

3232
sphinx:

‎CLAUDE.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
The codebase is also transpiled to JavaScript via **Transcrypt** (`flm-js/`). This constrains what Python idioms are usable.
88

9-
Packages are managed via `poetry`. Prefix test and python-specific calls appropriately, e.g. `poetry run python -m pytest ...`
9+
Packages are managed via `uv`. Prefix test and python-specific calls appropriately, e.g. `uv run python -m pytest ...`
1010

1111
## Structure
1212

@@ -120,4 +120,4 @@ Used for forward references (`\ref`, `\eqref`, `\cite`). The mechanism:
120120

121121
## Documentation
122122

123-
Sphinx docs live in `doc/`. Build with `poetry run sphinx-build -b html doc doc/_build/html`. API docs use `autodoc` directives pulling from source docstrings. User guide pages (overview, standard-syntax, configuration, features, model, lib) are hand-written RST. The build generates `flm-config-json-schema.json` in the HTML output root via a `build-finished` hook in `conf.py`. CLI flags `--validate-config-only` and `--print-config-json-schema` expose schema validation and generation.
123+
Sphinx docs live in `doc/`. Build with `uv run --group builddoc sphinx-build -b html doc doc/_build/html`. API docs use `autodoc` directives pulling from source docstrings. User guide pages (overview, standard-syntax, configuration, features, model, lib) are hand-written RST. The build generates `flm-config-json-schema.json` in the HTML output root via a `build-finished` hook in `conf.py`. CLI flags `--validate-config-only` and `--print-config-json-schema` expose schema validation and generation.

‎README.md‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -528,14 +528,14 @@ See [the `flm-js` subfolder](flm-js/README.md) for more details.
528528
One-time setup:
529529

530530
```bash
531-
> poetry install --extras maincmdl --with builddoc
531+
> uv sync --extra maincmdl --group builddoc
532532
```
533533

534534
Compile docs:
535535

536536
```bash
537537
> cd doc
538-
doc> poetry run make html
538+
doc> uv run make html
539539
```
540540

541541
### Build JS lib
@@ -547,13 +547,13 @@ rebuilds in final mode. Assumes a sibling `pylatexenc/` folder where to get the
547547
pylatexenc sources. Run:
548548

549549
```bash
550-
(cd flm-js && poetry run python ./generate_flm_js.py --pylatexenc-src-dir=../../pylatexenc --delete-target-dir --compile-tests && node test-flm-js/runtests.js && poetry run python ./generate_flm_js.py --pylatexenc-src-dir=../../pylatexenc --delete-target-dir)
550+
(cd flm-js && uv run --group buildjslib python ./generate_flm_js.py --pylatexenc-src-dir=../../pylatexenc --delete-target-dir --compile-tests && node test-flm-js/runtests.js && uv run --group buildjslib python ./generate_flm_js.py --pylatexenc-src-dir=../../pylatexenc --delete-target-dir)
551551
```
552552

553553

554554
### Make a JSON schema for config
555555

556556
```bash
557-
> poetry run python -m flm --print-config-json-schema >flm-config-json-schema.json
557+
> uv run python -m flm --print-config-json-schema >flm-config-json-schema.json
558558
```
559559

‎doc/conf.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
from datetime import datetime
1717
from pathlib import Path
1818
_pyproject = toml.load(Path(__file__).resolve().parent.parent / "pyproject.toml")
19-
_author = ", ".join(_pyproject["tool"]["poetry"]["authors"])
19+
_author = ", ".join(a["name"] for a in _pyproject["project"]["authors"])
2020
_year = datetime.now().year
2121

2222

‎flm-js/README.md‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ read on below.
1515
The JS version of FLM's core modules is obtained by using the great tool
1616
[Transcrypt](https://www.transcrypt.org/).
1717

18-
Set up your poetry environment with the 'buildjslib' dependency group:
18+
Set up your uv environment with the 'buildjslib' dependency group:
1919

20-
> poetry install --with buildjslib
20+
> uv sync --group buildjslib
2121

2222
Check out the pylatexenc sources. (If you've done this in the past, you might
2323
want to do `git pull` in that directory to get the latest version.)
@@ -28,7 +28,7 @@ want to do `git pull` in that directory to get the latest version.)
2828

2929
Generate the relevant JavaScript FLM Sources by running the build script:
3030

31-
> poetry run python generate_flm_js.py --pylatexenc-src-dir=./pylatexenc-src/
31+
> uv run --group buildjslib python generate_flm_js.py --pylatexenc-src-dir=./pylatexenc-src/
3232

3333
Result: A new folder `flm-js/` with a flat layout of JS modules (with qualified
3434
names such as `flm.feature.math.js`) that you can import in your code.
@@ -42,5 +42,5 @@ Check the ZooDb sources to get a hang of it.
4242
To compile and run the tests, you can use the following command (WILL OVERWRITE
4343
TARGET DIRECTORY `test-flm-js`):
4444

45-
> poetry run python generate_flm_js.py --pylatexenc-src-dir=./pylatexenc-src/ --delete-target-dir --compile-tests
45+
> uv run --group buildjslib python generate_flm_js.py --pylatexenc-src-dir=./pylatexenc-src/ --delete-target-dir --compile-tests
4646
> node test-flm-js/runtests.js

‎flm/main/watch.py‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,8 +112,9 @@ def workflow_postprocess_actions_fn(rendered_content, document, render_context):
112112
'targets': d_refs,
113113
}
114114
s_refs_info_json = json.dumps(d_refs_info, cls=ReprValueFallbackJsonEncoder)
115+
s_refs_info_json_insertcode = s_refs_info_json.replace('</script>','<\\/script>')
115116
rendered_content = rendered_content + f"""
116-
<script id="FlmRefsData" type="application/json">{s_refs_info_json.replace('</script>','<\\/script>')}</script>
117+
<script id="FlmRefsData" type="application/json">{s_refs_info_json_insertcode}</script>
117118
"""
118119
return rendered_content
119120

0 commit comments

Comments
 (0)