Open
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
This PR makes the public waxy enum symbols iterable from Python (e.g., list(waxy.BoxSizing)), by adding a Rust-side variants() classmethod for each enum and wrapping the exported enums in Python so iter(enum) yields the variants in definition order.
Changes:
- Added
variants()classmethods to each PyO3 enum insrc/enums.rs. - Wrapped exported enums in
python/waxy/__init__.pyto provide class-level iteration, and updated stubs/tests accordingly. - Documented the feature in the changelog and design notes.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
src/enums.rs |
Adds variants() classmethod returning definition-ordered variant lists for each enum. |
python/waxy/__init__.py |
Re-exports enums via a Python proxy that implements __iter__ by calling the Rust variants(). |
python/waxy/__init__.pyi |
Changes enum stubs to enum.IntEnum member syntax (int-valued) for type-checker iteration support. |
tests/test_enums.py |
Updates enum variant expectations and adds an iteration test. |
docs/changelog.md |
Notes the new iterability and variants() method in Unreleased. |
CLAUDE.md |
Adds rationale/design notes for the enum iterability approach. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+458
to
468
| class Display(enum.IntEnum): | ||
| """How the node should be displayed.""" | ||
|
|
||
| Block: Display | ||
| Block = 0 | ||
| """Block layout.""" | ||
| Flex: Display | ||
| Flex = 1 | ||
| """Flexbox layout.""" | ||
| Grid: Display | ||
| Grid = 2 | ||
| """CSS Grid layout.""" | ||
| Nil: Display | ||
| Nil = 3 | ||
| """No display (maps to CSS `display: none`).""" |
Comment on lines
+72
to
+81
| @pytest.mark.parametrize( | ||
| ("enum_class", "variants"), | ||
| ENUM_VARIANTS, | ||
| ids=[cls.__name__ for cls, _ in ENUM_VARIANTS], | ||
| ) | ||
| def test_enum_iterable(enum_class: _EnumLike, variants: list[str]) -> None: | ||
| result = list(enum_class) | ||
| assert len(result) == len(variants) | ||
| for variant, name in zip(result, variants, strict=True): | ||
| assert variant == getattr(enum_class, name) |
Comment on lines
40
to
+68
| ) | ||
| from waxy._waxy import ( | ||
| AlignContent as _AlignContent, | ||
| ) | ||
| from waxy._waxy import ( | ||
| AlignItems as _AlignItems, | ||
| ) | ||
| from waxy._waxy import ( | ||
| BoxSizing as _BoxSizing, | ||
| ) | ||
| from waxy._waxy import ( | ||
| Display as _Display, | ||
| ) | ||
| from waxy._waxy import ( | ||
| FlexDirection as _FlexDirection, | ||
| ) | ||
| from waxy._waxy import ( | ||
| FlexWrap as _FlexWrap, | ||
| ) | ||
| from waxy._waxy import ( | ||
| GridAutoFlow as _GridAutoFlow, | ||
| ) | ||
| from waxy._waxy import ( | ||
| Overflow as _Overflow, | ||
| ) | ||
| from waxy._waxy import ( | ||
| Position as _Position, | ||
| ) | ||
| from waxy._waxy import ( |
Comment on lines
+112
to
+116
| AlignContent = _EnumProxy(_AlignContent) | ||
| AlignItems = _EnumProxy(_AlignItems) | ||
| BoxSizing = _EnumProxy(_BoxSizing) | ||
| Display = _EnumProxy(_Display) | ||
| FlexDirection = _EnumProxy(_FlexDirection) |
| - **Value types** (`Length`, `Percent`, `Auto`, `MinContent`, `MaxContent`, `Definite`, `Fraction`, `FitContent`, `Minmax`, `GridLine`, `GridSpan`) are standalone frozen pyclasses, not enum variants. They support `match`/`case` pattern matching via `__match_args__`. Module-level constants `AUTO`, `MIN_CONTENT`, `MAX_CONTENT` are provided for the zero-argument types. | ||
| - **Exception hierarchy**: `WaxyException(Exception)` is the root. `TaffyException(WaxyException)` covers taffy errors. `InvalidNodeId` is `TaffyException + KeyError` (raised when accessing a removed node). Validation exceptions are `WaxyException + ValueError` via multi-inheritance (achieved by setting `__bases__` in `register()` in `src/errors.rs`): `InvalidPercent` (Percent outside [0.0, 1.0]), `InvalidLength` (NaN), `InvalidGridLine` (index 0), `InvalidGridSpan` (count 0). | ||
| - **`Display.Nil`** maps to taffy's `Display::None`. We use `#[pyo3(name = "Nil")]` because `None` is a Python keyword. | ||
| - **Enum iterability** — PyO3 enum pyclasses don't support Python subclassing (`subclass`) and their `FromPyObject` impl uses downcast (not integer extraction), so Python `IntEnum` wrappers can't be passed back to Rust. Instead, each enum is wrapped at module level in `_EnumProxy` (defined in `python/waxy/__init__.py`). The proxy's `__iter__` calls the Rust `variants()` classmethod (added to each enum in `src/enums.rs`) and its `__instancecheck__` delegates to the underlying Rust class. Variant attribute access (e.g., `Display.Flex`) goes through `_EnumProxy.__getattr__` and returns the actual Rust singleton, so all Rust interop is unaffected. The `.pyi` stub declares the enums as `enum.IntEnum` subclasses (with `= value` member syntax) so that type checkers understand iteration, isinstance, and equality. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.