From dc2c69b11c1483bbec04222e01f49b64812b7374 Mon Sep 17 00:00:00 2001 From: Laurent Date: Thu, 19 Feb 2026 23:01:46 +0100 Subject: [PATCH 1/3] Fix "can't decode byte 0x97" error caused by em dashes --- doc/03_signals_and_types.md | 2 +- doc/06_functions.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/03_signals_and_types.md b/doc/03_signals_and_types.md index 7f9dadd..fbf0c96 100644 --- a/doc/03_signals_and_types.md +++ b/doc/03_signals_and_types.md @@ -609,7 +609,7 @@ Signal copper = ("copper-plate", 0); Signal iron_limited = iron; Signal copper_limited = copper / 3; -# Minimum determines capacity — using conditional values +# Minimum determines capacity using conditional values Signal can_make = ((iron_limited < copper_limited) : iron_limited) + ((copper_limited <= iron_limited) : copper_limited); ``` diff --git a/doc/06_functions.md b/doc/06_functions.md index cd2cc4e..682b549 100644 --- a/doc/06_functions.md +++ b/doc/06_functions.md @@ -367,12 +367,12 @@ func calc(Signal a, Signal b) { ... } **Use conditional values (`:`) over multiplication:** ```facto -# Efficient — one decider combinator +# Efficient: one decider combinator func select(Signal cond, Signal a, Signal b) { return ((cond != 0) : a) + ((cond == 0) : b); } -# Less efficient — extra arithmetic +# Less efficient: extra arithmetic func select_old(Signal cond, Signal a, Signal b) { return (cond != 0) * a + (cond == 0) * b; } From 78c65386ba1028f6031b4c1cba0bd755ace2e166 Mon Sep 17 00:00:00 2001 From: Laurent Date: Thu, 19 Feb 2026 23:02:06 +0100 Subject: [PATCH 2/3] Skip chmod tests on Windows --- tests/test_cli.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/test_cli.py b/tests/test_cli.py index d87873b..72aa03f 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -5,6 +5,7 @@ """ import json +import os import click import pytest @@ -365,13 +366,13 @@ def test_compile_complex_program(self): success, result, messages = compile_dsl_source(code) assert success is True + @pytest.mark.skipif(os.name == "nt", reason="chmod permission test not reliable on Windows") def test_read_file_error_unreadable_file(self, runner, tmp_path): """Cover lines 234-236: error handling when reading input file fails. Click validates file readability before our code runs, so we test that Click properly reports unreadable files. """ - import os import stat # Create a file, then make it unreadable @@ -395,12 +396,12 @@ def test_read_file_error_nonexistent_file(self, runner, tmp_path): result = runner.invoke(main, [str(tmp_path / "nonexistent.facto")]) assert result.exit_code != 0 + @pytest.mark.skipif(os.name == "nt", reason="chmod permission test not reliable on Windows") def test_write_file_error_unwritable_directory(self, runner, tmp_path): """Cover lines 261-264: error handling when writing output file fails. Tests the exception handler for file write errors. """ - import os import stat # Create a valid input file From e377dc1b8e1ee00839f02ea390131244729e9e47 Mon Sep 17 00:00:00 2001 From: Laurent Date: Thu, 19 Feb 2026 23:02:24 +0100 Subject: [PATCH 3/3] Read file as utf-8 to avoid cp1252 errors --- example_programs/tests/test_markdown_examples.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example_programs/tests/test_markdown_examples.py b/example_programs/tests/test_markdown_examples.py index ae3d46c..03a2f25 100644 --- a/example_programs/tests/test_markdown_examples.py +++ b/example_programs/tests/test_markdown_examples.py @@ -219,7 +219,7 @@ def extract_facto_blocks(markdown_path: Path) -> list[tuple[str, int, str]]: Returns: List of (code, line_number, first_30_chars) tuples """ - content = markdown_path.read_text() + content = markdown_path.read_text(encoding="utf-8") blocks = [] # Find all ```facto ... ``` blocks