From d8cb46d2c913033f7fbfe61acc50c5d5e661dbf1 Mon Sep 17 00:00:00 2001 From: Conor Bronsdon Date: Tue, 11 Aug 2026 16:48:34 -0700 Subject: [PATCH] Migrate to released Mojo 1.0 and cut 0.2.0 Re-pin pixi to the max channel and mojo >=1.0,<2; CI installs mojo==1.0.0 from PyPI instead of the nightly index with --prerelease allow. The weekly drift check still runs against the latest nightly. Two source fixes: 1.0 builds a bare list expression as an Array, so parse_body's stops and _make_loop's keys/values are now annotated. README test counts and measured figures re-checked against a full run on Mojo 1.0. Co-Authored-By: Claude Opus 5 (1M context) --- .github/workflows/docs.yaml | 6 ++---- .github/workflows/test.yml | 16 +++++++--------- CHANGELOG.md | 14 +++++++++++++- README.md | 10 +++++----- pixi.toml | 6 +++--- recipe.yaml | 4 ++-- src/template/parser.mojo | 6 +++++- src/template/render.mojo | 4 ++-- 8 files changed, 39 insertions(+), 27 deletions(-) diff --git a/.github/workflows/docs.yaml b/.github/workflows/docs.yaml index 08f589b..8db7cf3 100644 --- a/.github/workflows/docs.yaml +++ b/.github/workflows/docs.yaml @@ -17,7 +17,7 @@ concurrency: env: # Keep in step with test.yml's pin -- docs runs `mojo doc`, which compiles the # sources and so breaks on the same stdlib changes the tests do. - MOJO_VERSION: "1.0.0b3.dev2026073014" + MOJO_VERSION: "1.0.0" jobs: build-deploy: @@ -35,9 +35,7 @@ jobs: - name: Install Mojo run: | uv venv - uv pip install "mojo==$MOJO_VERSION" \ - --index https://whl.modular.com/nightly/simple/ \ - --prerelease allow + uv pip install "mojo==$MOJO_VERSION" - name: Generate API reference run: | diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 7294938..de5d15d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -12,11 +12,11 @@ on: workflow_dispatch: env: - # The nightly this repo is known to build and pass on. CI installs exactly - # this for pushes and PRs, so upstream churn cannot turn a green repo red - # without a commit. Bump it when the weekly drift check goes green on a newer - # one, or after fixing whatever it caught. - MOJO_VERSION: "1.0.0b3.dev2026073014" + # The released Mojo this repo is known to build and pass on. CI installs + # exactly this for pushes and PRs, so upstream churn cannot turn a green repo + # red without a commit. Bump it when the weekly drift check goes green on a + # newer one, or after fixing whatever it caught. + MOJO_VERSION: "1.0.0" jobs: test: @@ -40,9 +40,7 @@ jobs: --index https://whl.modular.com/nightly/simple/ \ --prerelease allow else - uv pip install "mojo==$MOJO_VERSION" \ - --index https://whl.modular.com/nightly/simple/ \ - --prerelease allow + uv pip install "mojo==$MOJO_VERSION" fi .venv/bin/mojo --version @@ -75,7 +73,7 @@ jobs: Run: $GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID Fix the breakage, then bump MOJO_VERSION in .github/workflows/test.yml - and .github/workflows/docs.yaml to the nightly that passes. + and .github/workflows/docs.yaml to the release that passes. EOF ) existing=$(gh issue list --repo "$GITHUB_REPOSITORY" --state open \ diff --git a/CHANGELOG.md b/CHANGELOG.md index d273323..2c5b570 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,18 @@ # Changelog -## Unreleased +## 0.2.0 — 2026-08-11 + +- **Builds on released Mojo 1.0.** The pixi channel moved from + `max-nightly` to `max` and the dependency pin from `>=1.0.0b3.dev…` to + `>=1.0,<2`; CI installs `mojo==1.0.0` from PyPI instead of the nightly + index with `--prerelease allow`. The weekly drift check still runs + against the latest nightly, so the repo still reports when the language + moves under it. +- **1.0 source fixes.** `_Parser.parse_body`'s `stops` list and + `_make_loop`'s `keys`/`values` are now annotated (`List[String]` and + `List[TemplateValue]`). Under 1.0 a bare list expression builds an + `Array`, which no longer converts to a `List` parameter. +- README test count corrected: 59 → 104. - New `template.errors` module (exported from the package), following the error-reporting pattern shared across the mojo-* parser suite: diff --git a/README.md b/README.md index 002692d..72c06bd 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ **A Jinja-flavored template engine in pure Mojo, verified byte-for-byte against Jinja2. No Python dependencies, no FFI.** [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg?style=flat-square)](LICENSE) -[![Mojo](https://img.shields.io/badge/Mojo-1.0.0b3%2B_nightly-orange?style=flat-square)](https://mojolang.org) +[![Mojo](https://img.shields.io/badge/Mojo-1.0-orange?style=flat-square)](https://mojolang.org) [![Podcast](https://img.shields.io/badge/Podcast-Chain_of_Thought-purple?style=flat-square)](https://chainofthought.show/?utm_source=github&utm_medium=referral&utm_campaign=repo-readme&utm_content=mojo-template) [![X](https://img.shields.io/badge/X-@ConorBronsdon-black?style=flat-square&logo=x)](https://x.com/ConorBronsdon) @@ -157,11 +157,11 @@ Or with uv: ```bash uv venv -uv pip install mojo --index https://whl.modular.com/nightly/simple/ --prerelease allow +uv pip install mojo .venv/bin/mojo run -I src test/test_template.mojo ``` -Requires a Mojo nightly (`>=1.0.0b3`). +Requires Mojo 1.0 or newer. ## Usage @@ -175,12 +175,12 @@ body built from a nested context with a loop and a conditional). ## Tests ```bash -pixi run test # 59 tests: per-feature + Jinja2 fixture parity +pixi run test # 104 tests: per-feature, Jinja2 parity, error positions pixi run demo # render the example email pixi run fuzz "{% for x in items %}{{ x }}{% endfor %}" ``` -59 tests total, all green, plus Jinja2 byte-compatibility: Jinja2's +104 tests total, all green, plus Jinja2 byte-compatibility: Jinja2's escaping and whitespace defaults (`autoescape=True`) are the spec. `test/data/gen_fixtures.py` renders 43 templates against a shared context with Jinja2 and writes the outputs to `test/data/fixtures/manifest.txt`; diff --git a/pixi.toml b/pixi.toml index 4065e59..662be4e 100644 --- a/pixi.toml +++ b/pixi.toml @@ -1,10 +1,10 @@ [workspace] authors = ["Conor Bronsdon "] -channels = ["https://conda.modular.com/max-nightly", "conda-forge"] +channels = ["https://conda.modular.com/max", "conda-forge"] name = "mojo-template" description = "A standalone Jinja-flavored template engine in pure Mojo" platforms = ["linux-64", "osx-arm64"] -version = "0.1.0" +version = "0.2.0" [tasks] test = "mojo run -I src test/test_template.mojo && mojo run -I src test/test_errors.mojo" @@ -15,4 +15,4 @@ fmt = "mojo format src/ test/ examples/ bench/" docs = "mojo doc -o docs/api.json -I src src/template && python3 docs/render_api.py docs/api.json docs/api.html" [dependencies] -mojo = ">=1.0.0b3.dev0,<2" +mojo = ">=1.0,<2" diff --git a/recipe.yaml b/recipe.yaml index 7b412c1..ef31807 100755 --- a/recipe.yaml +++ b/recipe.yaml @@ -11,7 +11,7 @@ # Build locally with: rattler-build build --recipe recipe.yaml context: - version: "0.1.0" + version: "0.2.0" package: name: mojo-template @@ -29,7 +29,7 @@ build: requirements: run: - - mojo >=1.0.0b3.dev0,<2 + - mojo >=1.0,<2 about: homepage: https://github.com/conorbronsdon/mojo-template diff --git a/src/template/parser.mojo b/src/template/parser.mojo index b2ad2a9..389e878 100644 --- a/src/template/parser.mojo +++ b/src/template/parser.mojo @@ -697,7 +697,11 @@ struct _Parser(Copyable, Movable): var cond_base = content_off + self._word_end(inner, String("if")) conds.append(self.parse_expr_string(cond_src, cond_base)) self.pos += 1 # consume the {% if %} - var stops = [String("elif"), String("else"), String("endif")] + var stops: List[String] = [ + String("elif"), + String("else"), + String("endif"), + ] branches.append(self.parse_body(stops, depth + 1, opened_at)) var else_body = List[Int]() var has_else = False diff --git a/src/template/render.mojo b/src/template/render.mojo index 5a9e6bf..b956a15 100644 --- a/src/template/render.mojo +++ b/src/template/render.mojo @@ -356,7 +356,7 @@ def _apply_filter( def _make_loop(index0: Int, length: Int) raises -> TemplateValue: - var keys = [ + var keys: List[String] = [ String("index"), String("index0"), String("first"), @@ -365,7 +365,7 @@ def _make_loop(index0: Int, length: Int) raises -> TemplateValue: String("revindex"), String("revindex0"), ] - var values = [ + var values: List[TemplateValue] = [ TemplateValue(index0 + 1), TemplateValue(index0), TemplateValue(index0 == 0),