tutordraw 0.1.0a3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. tutordraw-0.1.0a3/AGENTS.md +42 -0
  2. tutordraw-0.1.0a3/CHANGELOG.md +27 -0
  3. tutordraw-0.1.0a3/CONTRIBUTING.md +27 -0
  4. tutordraw-0.1.0a3/LICENSE +21 -0
  5. tutordraw-0.1.0a3/MANIFEST.in +6 -0
  6. tutordraw-0.1.0a3/PKG-INFO +139 -0
  7. tutordraw-0.1.0a3/README.md +111 -0
  8. tutordraw-0.1.0a3/docs/API.md +102 -0
  9. tutordraw-0.1.0a3/docs/ARCHITECTURE.md +207 -0
  10. tutordraw-0.1.0a3/docs/COMPATIBILITY.md +55 -0
  11. tutordraw-0.1.0a3/docs/DECISIONS.md +85 -0
  12. tutordraw-0.1.0a3/docs/HANDOFF.md +147 -0
  13. tutordraw-0.1.0a3/docs/PRODUCT.md +81 -0
  14. tutordraw-0.1.0a3/docs/RELEASING.md +73 -0
  15. tutordraw-0.1.0a3/docs/ROADMAP.md +82 -0
  16. tutordraw-0.1.0a3/docs/TUTORIAL.md +60 -0
  17. tutordraw-0.1.0a3/examples/cell_tutorial.py +55 -0
  18. tutordraw-0.1.0a3/examples/group_focus.py +30 -0
  19. tutordraw-0.1.0a3/pyproject.toml +37 -0
  20. tutordraw-0.1.0a3/setup.cfg +4 -0
  21. tutordraw-0.1.0a3/src/tutordraw/__init__.py +10 -0
  22. tutordraw-0.1.0a3/src/tutordraw/adapters/__init__.py +1 -0
  23. tutordraw-0.1.0a3/src/tutordraw/adapters/drawcv.py +48 -0
  24. tutordraw-0.1.0a3/src/tutordraw/attention.py +70 -0
  25. tutordraw-0.1.0a3/src/tutordraw/errors.py +28 -0
  26. tutordraw-0.1.0a3/src/tutordraw/export.py +59 -0
  27. tutordraw-0.1.0a3/src/tutordraw/layout.py +96 -0
  28. tutordraw-0.1.0a3/src/tutordraw/model.py +179 -0
  29. tutordraw-0.1.0a3/src/tutordraw/themes.py +40 -0
  30. tutordraw-0.1.0a3/src/tutordraw/tutorial.py +87 -0
  31. tutordraw-0.1.0a3/src/tutordraw/validation.py +20 -0
  32. tutordraw-0.1.0a3/src/tutordraw.egg-info/PKG-INFO +139 -0
  33. tutordraw-0.1.0a3/src/tutordraw.egg-info/SOURCES.txt +40 -0
  34. tutordraw-0.1.0a3/src/tutordraw.egg-info/dependency_links.txt +1 -0
  35. tutordraw-0.1.0a3/src/tutordraw.egg-info/requires.txt +8 -0
  36. tutordraw-0.1.0a3/src/tutordraw.egg-info/top_level.txt +1 -0
  37. tutordraw-0.1.0a3/tests/test_drawcv_compatibility.py +45 -0
  38. tutordraw-0.1.0a3/tests/test_presentation.py +285 -0
  39. tutordraw-0.1.0a3/tests/test_tutorial.py +186 -0
  40. tutordraw-0.1.0a3/tools/check_docs.py +31 -0
  41. tutordraw-0.1.0a3/tools/check_installed.py +50 -0
  42. tutordraw-0.1.0a3/tools/check_release.py +69 -0
@@ -0,0 +1,42 @@
1
+ # Working on TutorDraw
2
+
3
+ ## Start here
4
+
5
+ Read `README.md`, `docs/HANDOFF.md`, `docs/ARCHITECTURE.md`, and
6
+ `docs/ROADMAP.md` before implementing. Consult `docs/DECISIONS.md` for rationale.
7
+ Inspect actual repository files rather than assuming the handoff is current.
8
+
9
+ ## Project boundary
10
+
11
+ - This is TutorDraw, a Python tutorial-authoring library using DrawCV.
12
+ - Depend on the `pydrawcv` distribution, imported as `drawcv`.
13
+ - Do not modify `C:/Projects/DrawCV` as part of ordinary TutorDraw work.
14
+ If an upstream limitation blocks progress, document it and seek a TutorDraw
15
+ adapter or a reduced, explicitly documented feature first.
16
+ - Keep drawing/rendering concerns in DrawCV and teaching concerns in TutorDraw.
17
+ - The owner wants useful documentation for switching between AI models.
18
+ - Proposed APIs are not existing APIs. Update documentation as implementation
19
+ settles, and keep examples clearly marked until verified runnable.
20
+
21
+ ## Development conventions
22
+
23
+ - Target Python 3.12+ initially. Use a `src/tutordraw/` layout when code begins.
24
+ - Prefer small typed public APIs and explicit validation errors.
25
+ - Isolate DrawCV-specific lookups, bounds, and cloning in an adapter.
26
+ - Preserve the user's source scene when producing tutorial output.
27
+ - Prefer independent step state over replay-dependent actions for static export.
28
+ - Test meaningful behavior: references, transformed anchors, source preservation,
29
+ step independence, errors, and actual image export.
30
+ - Visually inspect rendered examples in addition to numerical tests.
31
+ - Do not hardcode local checkout paths or invent dependency compatibility claims.
32
+ - Do not publish a package unless the owner explicitly requests publication.
33
+
34
+ ## Before handing off
35
+
36
+ Update `docs/HANDOFF.md` with implemented capabilities, changed files,
37
+ commands actually run and their outcomes, unresolved issues, and the next
38
+ concrete task. Update the roadmap checkboxes and record material design changes
39
+ in `docs/DECISIONS.md`. Never mark a check complete without evidence.
40
+
41
+ Keep these documents concise enough that another model can resume without the
42
+ previous conversation. Never include credentials, tokens, or private indexes.
@@ -0,0 +1,27 @@
1
+ # Changelog
2
+
3
+ The first public release candidate is 0.1.0a3; earlier versions were local development milestones.
4
+
5
+ ## 0.1.0a3 — first alpha
6
+
7
+ - Add installed-wheel CI for Windows, Linux, and macOS on Python 3.12–3.14.
8
+ - Add repeatable distribution, documentation, and installed-example checks.
9
+ - Add MIT license and author metadata approved by Nuh Yamin.
10
+ - Document compatibility evidence, the tutorial authoring workflow, alpha API
11
+ expectations, and a manual publishing procedure.
12
+ - Keep `pydrawcv==0.10.0.post1` as the tested dependency contract.
13
+
14
+ No intentional public API or drawing behavior changes from 0.1.0a2.
15
+ CI configuration alone is not evidence that every matrix environment passes.
16
+
17
+ ## 0.1.0a2 — static tutorial workflow
18
+
19
+ - Wrapped callouts, rectangular highlights, group-aware dimming, and shared themes.
20
+ - Ordered PNG export with collision checks and partial-failure reporting.
21
+ - Three-step cell lesson and nested-group example; 54 passing local tests.
22
+
23
+ ## 0.1.0a1 — initial rendering API
24
+
25
+ - Teaching targets, reusable labels, straight leader lines, independent steps,
26
+ and source-preserving PNG rendering.
27
+ - Installable src-layout package, example, 30 tests, and AI handoff documentation.
@@ -0,0 +1,27 @@
1
+ # Contributing
2
+
3
+ Use Python 3.12 or newer. Work in a virtual environment, install from the project
4
+ root with `python -m pip install -e ".[dev]"`, and run `python -m pytest -q`.
5
+ On Windows the existing environment uses `.venv/Scripts/python.exe`.
6
+
7
+ Read [the architecture](docs/ARCHITECTURE.md), [API guide](docs/API.md), and
8
+ [agent instructions](AGENTS.md). Keep DrawCV rendering code upstream; implement
9
+ teaching behavior here through the adapter.
10
+
11
+ Before submitting:
12
+
13
+ 1. Test meaningful behavior, especially independent steps, source preservation,
14
+ group transforms/dimming, and export failures.
15
+ 2. Run `python tools/check_docs.py` to verify links and the README example.
16
+ 3. Run examples and inspect images after visual changes.
17
+ 4. Update the changelog and documentation for public API changes.
18
+ 5. Update [the handoff](docs/HANDOFF.md) with verification and remaining work.
19
+
20
+ The installed-package check intentionally rejects editable source imports.
21
+ Build a wheel, install it in a separate environment, and run
22
+ `python -I tools/check_installed.py` using that environment's Python.
23
+ CI performs this check on the built wheel automatically.
24
+
25
+ The project is currently alpha. Avoid breaking public methods without documenting
26
+ migration instructions. Do not widen the DrawCV dependency pin without testing
27
+ released wheels. See [release preparation](docs/RELEASING.md) for package checks.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Nuh Yamin
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,6 @@
1
+ include AGENTS.md
2
+ include CHANGELOG.md
3
+ include CONTRIBUTING.md
4
+ recursive-include docs *.md
5
+ recursive-include examples *.py
6
+ recursive-include tools *.py
@@ -0,0 +1,139 @@
1
+ Metadata-Version: 2.4
2
+ Name: tutordraw
3
+ Version: 0.1.0a3
4
+ Summary: Author step-by-step visual tutorials using DrawCV drawings.
5
+ Author: Nuh Yamin
6
+ License-Expression: MIT
7
+ Project-URL: Repository, https://github.com/nuhyamin1/tutordraw
8
+ Project-URL: Issues, https://github.com/nuhyamin1/tutordraw/issues
9
+ Project-URL: Documentation, https://github.com/nuhyamin1/tutordraw#readme
10
+ Keywords: tutorial,drawing,education,diagram,drawcv
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Intended Audience :: Education
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Topic :: Education
16
+ Classifier: Topic :: Multimedia :: Graphics
17
+ Requires-Python: >=3.12
18
+ Description-Content-Type: text/markdown
19
+ License-File: LICENSE
20
+ Requires-Dist: pydrawcv==0.10.0.post1
21
+ Provides-Extra: dev
22
+ Requires-Dist: pytest>=8; extra == "dev"
23
+ Requires-Dist: build>=1; extra == "dev"
24
+ Requires-Dist: setuptools>=77; extra == "dev"
25
+ Requires-Dist: wheel; extra == "dev"
26
+ Requires-Dist: twine>=6; extra == "dev"
27
+ Dynamic: license-file
28
+
29
+ # TutorDraw
30
+
31
+ **Explain what you draw, one step at a time.**
32
+
33
+ TutorDraw is a Python library for authoring visual tutorials using [DrawCV](https://pypi.org/project/pydrawcv/). DrawCV supplies drawing objects and rendering; TutorDraw attaches teaching annotations and organizes them into independent lesson steps.
34
+
35
+ ## Status
36
+
37
+ **Early alpha `0.1.0a3`.** TutorDraw provides the static tutorial workflow described below. Licensed under MIT, authored by Nuh Yamin. See the compatibility notes before relying on it in production.
38
+
39
+ Implemented:
40
+
41
+ - Register existing DrawCV objects or groups as teaching targets.
42
+ - Attach labels with optional straight leader lines.
43
+ - Configure bounds anchors, gap, offset, padding, and font scale.
44
+ - Keep labels attached when targets move, including through group transforms.
45
+ - Define independent steps and render them to DrawCV canvases and PNG images.
46
+ - Preserve source content and undo history, including on rendering failure.
47
+ - Add step-local wrapped callouts, rectangular highlights, and group-aware dimming.
48
+ - Customize shared typography, spacing, and colors through an immutable theme.
49
+ - Export ordered PNGs with collision checks and partial-failure reporting.
50
+ - Validate references/options and warn about off-canvas annotations.
51
+
52
+ Video, interactive playback, rich typography, and automatic collision avoidance remain planned.
53
+
54
+ ## Install the alpha
55
+
56
+ ```shell
57
+ python -m pip install tutordraw==0.1.0a3
58
+ ```
59
+
60
+ The exact version selects this prerelease explicitly. Requires Python 3.12+.
61
+
62
+ ## Develop from this repository
63
+
64
+ Requires **Python 3.12+**. From the repository root:
65
+
66
+ ```powershell
67
+ python -m venv .venv
68
+ .\.venv\Scripts\python.exe -m pip install -e ".[dev]"
69
+ .\.venv\Scripts\python.exe -m pytest -q
70
+ .\.venv\Scripts\python.exe examples/cell_tutorial.py
71
+ ```
72
+
73
+ On macOS/Linux, use `.venv/bin/python` instead. Windows/Python 3.12 passes 62 tests. CI is configured for Windows, Linux, and macOS on Python 3.12–3.14; hosted results are pending. If `python` is unavailable, use the absolute path to an installed Python 3.12+ executable for the first command.
74
+
75
+ No DrawCV checkout is needed. TutorDraw pins the tested published dependency `pydrawcv==0.10.0.post1`, which imports as `drawcv`. A broader compatibility range is future work. Use an explicit version or `--pre` when selecting an alpha release.
76
+
77
+ ## Working example
78
+
79
+ ```python
80
+ from drawcv import Circle, Color, FillStyle, Point, Scene
81
+ from tutordraw import Tutorial
82
+
83
+ scene = Scene(640, 360, background=Color.white())
84
+ shape = Circle(
85
+ center=Point(180, 180), radius=45,
86
+ fill=FillStyle(color=Color(131, 151, 218)),
87
+ )
88
+ scene.add(shape)
89
+
90
+ tutorial = Tutorial(scene, title="Inside a cell")
91
+ nucleus = tutorial.target(shape, name="nucleus")
92
+ label = nucleus.label("Nucleus", anchor="top", leader=True)
93
+
94
+ intro = tutorial.step("Meet the nucleus").show(label)
95
+ intro.highlight(nucleus)
96
+ intro.explain(nucleus, "The nucleus contains the cell's DNA.", max_width=220)
97
+ tutorial.step("Review the drawing")
98
+
99
+ tutorial.render_step(0).save("output/nucleus.png")
100
+ tutorial.render_step(1).save("output/plain.png")
101
+ # Batch export refuses existing files unless overwrite=True is explicit.
102
+ tutorial.export_steps("output/readme", overwrite=True)
103
+ ```
104
+
105
+ Each step starts from the current source scene. The second step has no labels because it does not explicitly show any. Rendering order does not affect results. Tutorial and step titles are metadata; add DrawCV text if you want visible titles.
106
+
107
+ Run [the cell example](https://github.com/nuhyamin1/tutordraw/blob/master/examples/cell_tutorial.py) for a composed diagram. It writes `output/cell/step-001.png` through `step-003.png`. Rerunning explicitly overwrites these example images. [The nested-group example](https://github.com/nuhyamin1/tutordraw/blob/master/examples/group_focus.py) illustrates focusing a child while dimming its siblings.
108
+
109
+ ## Current limits
110
+
111
+ - Labels support **single-line printable ASCII**; callouts additionally support newlines and measured word wrapping. Other scripts and rich typography are not implemented yet.
112
+ - Anchors use transformed axis-aligned `get_bounds()` results, including supported shape strokes but excluding post-processing effect extents.
113
+ - Labels stay upright and spacing uses canvas pixels. Automatic collision avoidance and routed leaders are deferred.
114
+ - Off-canvas annotations issue `LayoutWarning` and may be clipped. Callout widths measure the text area; padding adds to the panel width.
115
+ - Dimming multiplies artwork opacity, not the background. Complex masks, blend modes, and occlusion are not pixel-level spotlight isolation. Hidden or zero-opacity attention targets are rejected; clipping and masks are not used to infer visibility.
116
+ - Scenes must round-trip through DrawCV serialization; unsupported copying raises `SceneCopyError`. Arbitrary custom drawables/assets are not guaranteed supported.
117
+ - Rendering uses authored scene state without sampling a timeline. Concurrent source edits during rendering are unsupported.
118
+ - Missing registered targets fail rendering, even if their label is not shown in that step. Hidden artwork does not suppress an explicitly shown label.
119
+
120
+ ## Documentation and continuation
121
+
122
+ - [Practical tutorial](https://github.com/nuhyamin1/tutordraw/blob/master/docs/TUTORIAL.md): build a lesson from a DrawCV scene.
123
+ - [API guide](https://github.com/nuhyamin1/tutordraw/blob/master/docs/API.md): implemented methods and errors.
124
+ - [Compatibility](https://github.com/nuhyamin1/tutordraw/blob/master/docs/COMPATIBILITY.md): evidence, fonts, and alpha API expectations.
125
+ - [Release procedure](https://github.com/nuhyamin1/tutordraw/blob/master/docs/RELEASING.md): exact artifact checks and manual publishing.
126
+ - [Changelog](https://github.com/nuhyamin1/tutordraw/blob/master/CHANGELOG.md): milestone history.
127
+ - [Contributing](https://github.com/nuhyamin1/tutordraw/blob/master/CONTRIBUTING.md): local development and installed-package checks.
128
+ - [Product scope](https://github.com/nuhyamin1/tutordraw/blob/master/docs/PRODUCT.md): intended tutorial capabilities.
129
+ - [Architecture](https://github.com/nuhyamin1/tutordraw/blob/master/docs/ARCHITECTURE.md): foundation and future design.
130
+ - [Roadmap](https://github.com/nuhyamin1/tutordraw/blob/master/docs/ROADMAP.md): milestones and acceptance checks.
131
+ - [AI handoff](https://github.com/nuhyamin1/tutordraw/blob/master/docs/HANDOFF.md): current state, verification, and continuation prompt.
132
+ - [Decisions](https://github.com/nuhyamin1/tutordraw/blob/master/docs/DECISIONS.md): choices and remaining questions.
133
+ - [Agent instructions](https://github.com/nuhyamin1/tutordraw/blob/master/AGENTS.md): repository conventions.
134
+
135
+ To continue with another AI model, ask it to read `AGENTS.md` and `docs/HANDOFF.md` first. Hosted CI verification remains pending; see the handoff for the latest release state. DrawCV remains a separate project.
136
+
137
+ ## License
138
+
139
+ [MIT](https://github.com/nuhyamin1/tutordraw/blob/master/LICENSE), copyright 2026 Nuh Yamin.
@@ -0,0 +1,111 @@
1
+ # TutorDraw
2
+
3
+ **Explain what you draw, one step at a time.**
4
+
5
+ TutorDraw is a Python library for authoring visual tutorials using [DrawCV](https://pypi.org/project/pydrawcv/). DrawCV supplies drawing objects and rendering; TutorDraw attaches teaching annotations and organizes them into independent lesson steps.
6
+
7
+ ## Status
8
+
9
+ **Early alpha `0.1.0a3`.** TutorDraw provides the static tutorial workflow described below. Licensed under MIT, authored by Nuh Yamin. See the compatibility notes before relying on it in production.
10
+
11
+ Implemented:
12
+
13
+ - Register existing DrawCV objects or groups as teaching targets.
14
+ - Attach labels with optional straight leader lines.
15
+ - Configure bounds anchors, gap, offset, padding, and font scale.
16
+ - Keep labels attached when targets move, including through group transforms.
17
+ - Define independent steps and render them to DrawCV canvases and PNG images.
18
+ - Preserve source content and undo history, including on rendering failure.
19
+ - Add step-local wrapped callouts, rectangular highlights, and group-aware dimming.
20
+ - Customize shared typography, spacing, and colors through an immutable theme.
21
+ - Export ordered PNGs with collision checks and partial-failure reporting.
22
+ - Validate references/options and warn about off-canvas annotations.
23
+
24
+ Video, interactive playback, rich typography, and automatic collision avoidance remain planned.
25
+
26
+ ## Install the alpha
27
+
28
+ ```shell
29
+ python -m pip install tutordraw==0.1.0a3
30
+ ```
31
+
32
+ The exact version selects this prerelease explicitly. Requires Python 3.12+.
33
+
34
+ ## Develop from this repository
35
+
36
+ Requires **Python 3.12+**. From the repository root:
37
+
38
+ ```powershell
39
+ python -m venv .venv
40
+ .\.venv\Scripts\python.exe -m pip install -e ".[dev]"
41
+ .\.venv\Scripts\python.exe -m pytest -q
42
+ .\.venv\Scripts\python.exe examples/cell_tutorial.py
43
+ ```
44
+
45
+ On macOS/Linux, use `.venv/bin/python` instead. Windows/Python 3.12 passes 62 tests. CI is configured for Windows, Linux, and macOS on Python 3.12–3.14; hosted results are pending. If `python` is unavailable, use the absolute path to an installed Python 3.12+ executable for the first command.
46
+
47
+ No DrawCV checkout is needed. TutorDraw pins the tested published dependency `pydrawcv==0.10.0.post1`, which imports as `drawcv`. A broader compatibility range is future work. Use an explicit version or `--pre` when selecting an alpha release.
48
+
49
+ ## Working example
50
+
51
+ ```python
52
+ from drawcv import Circle, Color, FillStyle, Point, Scene
53
+ from tutordraw import Tutorial
54
+
55
+ scene = Scene(640, 360, background=Color.white())
56
+ shape = Circle(
57
+ center=Point(180, 180), radius=45,
58
+ fill=FillStyle(color=Color(131, 151, 218)),
59
+ )
60
+ scene.add(shape)
61
+
62
+ tutorial = Tutorial(scene, title="Inside a cell")
63
+ nucleus = tutorial.target(shape, name="nucleus")
64
+ label = nucleus.label("Nucleus", anchor="top", leader=True)
65
+
66
+ intro = tutorial.step("Meet the nucleus").show(label)
67
+ intro.highlight(nucleus)
68
+ intro.explain(nucleus, "The nucleus contains the cell's DNA.", max_width=220)
69
+ tutorial.step("Review the drawing")
70
+
71
+ tutorial.render_step(0).save("output/nucleus.png")
72
+ tutorial.render_step(1).save("output/plain.png")
73
+ # Batch export refuses existing files unless overwrite=True is explicit.
74
+ tutorial.export_steps("output/readme", overwrite=True)
75
+ ```
76
+
77
+ Each step starts from the current source scene. The second step has no labels because it does not explicitly show any. Rendering order does not affect results. Tutorial and step titles are metadata; add DrawCV text if you want visible titles.
78
+
79
+ Run [the cell example](https://github.com/nuhyamin1/tutordraw/blob/master/examples/cell_tutorial.py) for a composed diagram. It writes `output/cell/step-001.png` through `step-003.png`. Rerunning explicitly overwrites these example images. [The nested-group example](https://github.com/nuhyamin1/tutordraw/blob/master/examples/group_focus.py) illustrates focusing a child while dimming its siblings.
80
+
81
+ ## Current limits
82
+
83
+ - Labels support **single-line printable ASCII**; callouts additionally support newlines and measured word wrapping. Other scripts and rich typography are not implemented yet.
84
+ - Anchors use transformed axis-aligned `get_bounds()` results, including supported shape strokes but excluding post-processing effect extents.
85
+ - Labels stay upright and spacing uses canvas pixels. Automatic collision avoidance and routed leaders are deferred.
86
+ - Off-canvas annotations issue `LayoutWarning` and may be clipped. Callout widths measure the text area; padding adds to the panel width.
87
+ - Dimming multiplies artwork opacity, not the background. Complex masks, blend modes, and occlusion are not pixel-level spotlight isolation. Hidden or zero-opacity attention targets are rejected; clipping and masks are not used to infer visibility.
88
+ - Scenes must round-trip through DrawCV serialization; unsupported copying raises `SceneCopyError`. Arbitrary custom drawables/assets are not guaranteed supported.
89
+ - Rendering uses authored scene state without sampling a timeline. Concurrent source edits during rendering are unsupported.
90
+ - Missing registered targets fail rendering, even if their label is not shown in that step. Hidden artwork does not suppress an explicitly shown label.
91
+
92
+ ## Documentation and continuation
93
+
94
+ - [Practical tutorial](https://github.com/nuhyamin1/tutordraw/blob/master/docs/TUTORIAL.md): build a lesson from a DrawCV scene.
95
+ - [API guide](https://github.com/nuhyamin1/tutordraw/blob/master/docs/API.md): implemented methods and errors.
96
+ - [Compatibility](https://github.com/nuhyamin1/tutordraw/blob/master/docs/COMPATIBILITY.md): evidence, fonts, and alpha API expectations.
97
+ - [Release procedure](https://github.com/nuhyamin1/tutordraw/blob/master/docs/RELEASING.md): exact artifact checks and manual publishing.
98
+ - [Changelog](https://github.com/nuhyamin1/tutordraw/blob/master/CHANGELOG.md): milestone history.
99
+ - [Contributing](https://github.com/nuhyamin1/tutordraw/blob/master/CONTRIBUTING.md): local development and installed-package checks.
100
+ - [Product scope](https://github.com/nuhyamin1/tutordraw/blob/master/docs/PRODUCT.md): intended tutorial capabilities.
101
+ - [Architecture](https://github.com/nuhyamin1/tutordraw/blob/master/docs/ARCHITECTURE.md): foundation and future design.
102
+ - [Roadmap](https://github.com/nuhyamin1/tutordraw/blob/master/docs/ROADMAP.md): milestones and acceptance checks.
103
+ - [AI handoff](https://github.com/nuhyamin1/tutordraw/blob/master/docs/HANDOFF.md): current state, verification, and continuation prompt.
104
+ - [Decisions](https://github.com/nuhyamin1/tutordraw/blob/master/docs/DECISIONS.md): choices and remaining questions.
105
+ - [Agent instructions](https://github.com/nuhyamin1/tutordraw/blob/master/AGENTS.md): repository conventions.
106
+
107
+ To continue with another AI model, ask it to read `AGENTS.md` and `docs/HANDOFF.md` first. Hosted CI verification remains pending; see the handoff for the latest release state. DrawCV remains a separate project.
108
+
109
+ ## License
110
+
111
+ [MIT](https://github.com/nuhyamin1/tutordraw/blob/master/LICENSE), copyright 2026 Nuh Yamin.
@@ -0,0 +1,102 @@
1
+ # Implemented API — 0.1.0a3
2
+
3
+ Public symbols import from `tutordraw`. Create targets/annotations/steps through the factory methods below rather than calling their constructors directly.
4
+
5
+ ## Tutorial
6
+
7
+ `Tutorial(scene, *, title="", theme=None)` holds a DrawCV Scene reference and a Theme (defaults to `Theme()`). The scene is read at each render. Titles are metadata, not automatically drawn text.
8
+
9
+ `tutorial.target(drawable, *, name=None) -> Target` registers an existing object/group, including nested children. Re-registration returns the same target. Explicit names must be nonempty and unique; conflicting names raise `ValidationError`.
10
+
11
+ `tutorial.step(title) -> Step` appends an independent step. Nonempty titles are required; duplicate titles are allowed. `tutorial.steps` returns a tuple.
12
+
13
+ `tutorial.render_step(index, *, alpha=False) -> drawcv.Canvas` renders a zero-based step through a copied scene. Negative indices and booleans are rejected. Use `alpha=True` for BGRA output; source background transparency is respected. `canvas.save(path)` uses DrawCV's save behavior and can overwrite existing files.
14
+
15
+ ## Labels
16
+
17
+ ```python
18
+ label = target.label(
19
+ "Nucleus", anchor="right", leader=True,
20
+ gap=None, offset=(0, 0), font_scale=None, padding=None,
21
+ )
22
+ step.show(label)
23
+ ```
24
+
25
+ Labels are immutable reusable definitions, absent until explicitly shown. Target fields `id`, `drawable_id`, and `name` are immutable.
26
+
27
+ | Option | Behavior |
28
+ | --- | --- |
29
+ | `text` | Nonempty, single-line printable ASCII |
30
+ | `anchor` | `left`, `right`, `top`, `bottom`, or `center` of world-space bounds |
31
+ | `leader` | Boolean, enables a straight leader |
32
+ | `gap` | Nonnegative pixel distance from anchor to panel edge; theme default 32 |
33
+ | `offset` | Additional `(x, y)` pixels, either sign |
34
+ | `font_scale` | Hershey scale, >0 and <=10; theme default 0.7 |
35
+ | `padding` | Nonnegative pixels around text; theme default 10 |
36
+
37
+ `None` uses the theme default at authoring time. Center-anchored labels are placed to the right of the target center. Text remains upright. Leaders terminate on panel edges; if the target lies within the panel, its leader is omitted. Spacing uses canvas pixels and does not inherit object scaling.
38
+
39
+ `step.show(*labels) -> Step` accepts registered labels from the same tutorial, ignores duplicates, and leaves the step unchanged if any argument is invalid. `step.labels` is a tuple. Steps never inherit presentation state from each other.
40
+
41
+ ## Callouts
42
+
43
+ ```python
44
+ callout = step.explain(
45
+ target, "The nucleus contains DNA.\nThis information guides cell activity.",
46
+ anchor="right", max_width=260, gap=40,
47
+ )
48
+ ```
49
+
50
+ `step.explain` accepts all label layout options plus `max_width=None` and `line_spacing=None`. It returns a `Callout` and automatically shows it only in this step. Callouts cannot be passed to `show` in another step; call `explain` there instead. `step.callouts` returns a tuple.
51
+
52
+ `max_width` limits the **text area**, excluding panel padding. Default: theme `callout_width=260`. Words wrap using DrawCV measurements. Oversized words split at characters; a width too narrow for one character raises `ValidationError` when rendered. Explicit newlines preserve paragraph breaks, including blank lines; other spaces normalize. Text remains printable ASCII plus newlines. Line spacing is at least 1, default 1.35 times measured line height.
53
+
54
+ ## Highlights and dimming
55
+
56
+ ```python
57
+ step.highlight(target, padding=8, color=(226, 146, 33), width=3)
58
+ step.dim_others(target, another_target, opacity=0.25)
59
+ ```
60
+
61
+ `highlight(target, *, padding=None, color=None, width=None) -> Step` creates a rectangular outline around transformed axis-aligned bounds. None uses theme defaults. Width must be positive; padding nonnegative; color is an RGB tuple. Repeating this call for the same target replaces its settings. `step.highlights` exposes a tuple of definitions.
62
+
63
+ `dim_others(*targets, opacity=None) -> Step` preserves one or more targets and multiplies unrelated artwork opacity by a factor in [0,1]. The theme default is 0.25. Repeating it replaces the focus set. A selected group preserves its subtree; a selected child preserves its ancestors while unrelated branches dim exactly once. Existing ancestor opacity still applies. Annotations are never dimmed.
64
+
65
+ Highlight/focus requests for targets under hidden or zero-opacity objects/layers fail at render time. Empty/all-hidden groups are rejected. Masks, clipping, blend modes, and occlusion are not visibility tests. Dimming is opacity reduction, not pixel-level spotlight isolation. Background color is unchanged. Titles drawn into the source are artwork too; register and focus them if they should stay undimmed.
66
+
67
+ ## Theme
68
+
69
+ `Theme(...)` is an immutable set of validated defaults:
70
+
71
+ | Field | Default |
72
+ | --- | --- |
73
+ | `text_color` | `(28, 43, 65)` |
74
+ | `panel_color` | `(255, 255, 255)` |
75
+ | `border_color` | `(194, 207, 223)` |
76
+ | `leader_color` | `(75, 104, 140)` |
77
+ | `highlight_color` | `(226, 146, 33)` |
78
+ | `font_scale`, `padding`, `gap` | `0.7`, `10`, `32` |
79
+ | `leader_width`, `border_width`, `highlight_width` | `2`, `1`, `3` |
80
+ | `highlight_padding` | `8` |
81
+ | `callout_width`, `line_spacing` | `260`, `1.35` |
82
+ | `dim_opacity` | `0.25` |
83
+
84
+ Colors are immutable RGB tuples, channels 0–255. Numeric annotation defaults and highlight settings resolve at creation time. Panel/text/leader colors and border/leader widths come from the tutorial's current theme at render time. Supply a theme when constructing the tutorial for consistent styling.
85
+
86
+ ## Ordered PNG export
87
+
88
+ `tutorial.export_steps(directory, *, overwrite=False, alpha=False) -> list[Path]` writes `step-001.png`, `step-002.png`, etc. Returned paths follow step order. Empty tutorials raise `ValidationError`. Titles never become filesystem paths.
89
+
90
+ Every filename is checked before export; collisions raise `FileExistsError` unless overwrite is explicit. Symlinks and non-file destinations are rejected even with overwrite. Concurrent file creation after preflight also cannot overwrite a file when overwrite is false.
91
+
92
+ Frames encode in temporary files. Explicit overwrite replaces an existing file only after successful encoding; a failed newly-created file is removed. This is not a transaction across the batch: successful earlier files remain if a later step fails. A new file may be visible during its copy. Permission/directory failures during preflight can propagate as filesystem exceptions.
93
+
94
+ ## Errors and warnings
95
+
96
+ - `TutorDrawError`: base exception.
97
+ - `ValidationError`: invalid options/references/indices, hidden attention targets, or layout that cannot fit a character. Also a ValueError.
98
+ - `SceneCopyError`: failure copying through DrawCV's document API, with chained cause.
99
+ - `ExportError`: failure after export starts. Inspect zero-based `step_index`, `path`, `completed_paths` (tuple), and `__cause__`.
100
+ - `LayoutWarning`: an annotation extends outside the canvas. Rendering proceeds and may clip it.
101
+
102
+ Direct render/save errors from DrawCV propagate; batch export wraps per-step failures in ExportError. Rendering preserves source content and history even on failure. Automatic label collision avoidance, rich fonts, timeline sampling, and concurrent source editing are not supported.