FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

feat!: close React Native parity gaps, and fix correctness bugs by owenthcarey · Pull Request #104 · pythonnative/pythonnative · GitHub

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension .css  (1) .gradle  (1) .html  (1) .js  (4) .json  (1) .kt  (52) .lock  (1) .md  (48) .mjs  (1) .pbxproj  (1) .py  (168) .sh  (1) .swift  (39) .toml  (1) .xml  (14) .yaml  (49) .yml  (2) All 17 file types selected
Only manifest files
Deleted files Viewed files
Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Unified
Split
Hide whitespace
Diff view
Unified
Split
Hide whitespace
  •  
  •  
  •  
28 changes: 17 additions & 11 deletions .github/workflows/e2e.yml
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
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,11 @@ jobs:
# app, dies). Sharding the run into a few balanced groups, each on
# its own freshly booted emulator, keeps every session under the
# limit, and parallelizes the Android pass as a bonus. Groups are
# sized so none exceeds ~12 heavy flows: ``components`` (35 flows
# after the graphics additions) dropped offline at ~11.5 minutes
# when split in two, so it runs as three parts; ``hooks`` (23 quick
# flows, ~10 minutes of driving) gets a dedicated emulator; the
# remaining categories are grouped to similar totals.
# sized to about nine minutes of driving or less: ``components``
# (39 flows) runs as three parts; ``hooks`` (26 flows) dropped
# offline at ~11.5 minutes in one session, so it runs as two parts;
# the remaining categories pair up to similar totals, and ``misc``
# (14 flows) runs alone.
# ``fail-fast: false`` so one shard's failure still lets the others
# report.
strategy:
Expand All @@ -49,12 +49,18 @@ jobs:
suites: components-b
- name: components-c
suites: components-c
- name: hooks
suites: hooks
- name: nav-gestures-layout-styling
suites: navigation gestures layout styling
- name: anim-misc
suites: animations assets misc
- name: hooks-a
suites: hooks-a
- name: hooks-b
suites: hooks-b
- name: nav-gestures
suites: navigation gestures
- name: layout-styling
suites: layout styling
- name: anim-assets
suites: animations assets
- name: misc
suites: misc
- name: inbox
suites: inbox

Expand Down
27 changes: 20 additions & 7 deletions CONTRIBUTING.md
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
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,13 @@ Unsolicited pull requests for issues that are already assigned or already have a

- `src/pythonnative/`: installable library and CLI
- Core Python modules, UI components, and utilities
- `components/`: element factories and the typed event records (`components/events.py`)
- `handles.py`: typed imperative handles published on `ref.current`
- `journal.py`: the undo journal a failed render pass rolls back through
- `native_views/`: the thin backend accessor (`get_backend` / `set_backend`) and the bridge backend that serializes commits
- `native_modules/`: device module facades and their Python fallbacks
- `navigation/`: navigators, container, hooks, linking, theme, and the navigation ref
- `testing/`: the headless testing library and the shipped pytest plugin (`testing/pytest_plugin.py`)
- `bridge/`: JSON codec and per-platform transports into the native rendering core
- `cli/`: `pn` command
- `project/`: config loading, template configuration, native plugin staging, and the builder behind `pn`
Expand Down Expand Up @@ -198,16 +205,18 @@ Recommended scopes (choose the smallest, most accurate unit; prefer module/direc
- `element`: Element descriptor class (`element.py`)
- `events`: tag-based event routing between native views and Python callbacks (`events.py`)
- `gestures`: gesture descriptors and the pure-Python recognition arbiter (`gestures.py`)
- `handles`: typed imperative handles published on refs (`handles.py`)
- `hooks`: hooks and contexts (`hooks.py`)
- `hosts`: screen hosts, lifecycle forwarding, and render scheduling (`hosts/`)
- `devserver`: dev server, file watcher, and WebSocket implementation (`devserver/`)
- `devclient`: on-device dev client that syncs sources and Fast Refreshes (`devclient.py`)
- `hot_reload`: module reloader and Fast Refresh (`hot_reload.py`)
- `journal`: render undo journal (`journal.py`)
- `layout`: Yoga layout integration and the host binding (`layout.py`, `native/yoga/`)
- `mutations`: batched mutation ops between reconciler and native backends (`mutations.py`)
- `native_modules`: native module registry, Python facades, and Python fallbacks (`native_modules/`)
- `native_views`: view registry protocol and bridge backend (`native_views/`)
- `navigation`: navigation state, container, navigators, hooks, and linking (`navigation/`)
- `native_views`: view backend accessor and bridge backend (`native_views/`)
- `navigation`: navigation state, container, navigators, hooks, linking, theme, and ref (`navigation/`)
- `net`: awaitable HTTP client (`net.py`)
- `package`: `src/pythonnative/__init__.py` exports and package boundary
- `platform`: `Platform.OS`/`Platform.select` and version detection (`platform.py`)
Expand All @@ -220,7 +229,7 @@ Recommended scopes (choose the smallest, most accurate unit; prefer module/direc
- `storage`: AsyncStorage key/value persistence and `use_persisted_state` (`storage.py`)
- `scheduler`: render batching and transition queues (`scheduler.py`)
- `style`: StyleSheet and theming (`style.py`)
- `testing`: public test utilities (`testing/`)
- `testing`: public test utilities and the pytest plugin (`testing/`)
- `utils`: shared utilities (`utils.py`)

- Other scopes:
Expand Down Expand Up @@ -328,7 +337,7 @@ Co-authored-by: Name <email>
- PR title: Conventional Commits format (CI-enforced by `pr-lint.yml`).
- Tests: added/updated; `uv run pytest` passes.
- Lint/format: `uv run ruff check .` and `uv run black --check src examples tests` pass.
- Docs: update `README.md` if behavior changes.
- Docs: update `README.md` and the affected pages under `docs/` if behavior changes; `uv run --group docs mkdocs build --strict` must pass.
- Templates: update `src/pythonnative/templates/` if generator output changes.
- Generated contracts and example schemas are regenerated and reviewed when changed; vendored dependencies retain their licenses and provenance.
- No local build outputs, caches, credentials, or machine-specific files are committed.
Expand Down Expand Up @@ -431,10 +440,14 @@ For tight iteration, run a single category instead of the full pass:

```bash
uv run ./scripts/run-e2e.sh android hooks
uv run ./scripts/run-e2e.sh ios components
uv run ./scripts/run-e2e.sh ios navigation
```

Available categories: `components`, `hooks`, `navigation`, `layout`, `styling`, `animations`, `misc`.
Each category is one file under `tests/e2e/suites/` (`hooks.yaml`, `navigation.yaml`, `gestures.yaml`, and so on; large areas are split into lettered parts such as `components-a.yaml`). List the directory for the current set:

```bash
ls tests/e2e/suites
```

A coverage checker, `scripts/check-e2e-coverage.py`, gates CI: every name in `pythonnative.__all__` must be covered by a demo + flow, or listed in `INTENTIONAL_EXEMPTIONS` with a justification.

Expand All @@ -443,7 +456,7 @@ When you add a new public symbol you must also:
1. Add a demo screen under `examples/e2e-suite/app/screens/<category>/`.
2. Append a `DemoEntry` in `examples/e2e-suite/app/registry.py`.
3. Add a Maestro flow at `tests/e2e/flows/<category>/<name>.yaml`.
4. Append the flow to the top-level `tests/e2e/android.yaml`, `tests/e2e/ios.yaml`, and the matching `tests/e2e/suites/<category>.yaml`.
4. Append the flow to the top-level `tests/e2e/android.yaml`, `tests/e2e/ios.yaml`, and the matching `tests/e2e/suites/<category>.yaml` (or the lettered part it belongs to).
5. Confirm `uv run python scripts/check-e2e-coverage.py` exits 0.

`tests/e2e/AGENTS.md` is the deeper reference (label conventions, failure triage, naming rules); AI agents should read it before touching the suite. The `e2e.yml` workflow runs the suite automatically on pushes to `main` and PRs.
Expand Down
12 changes: 7 additions & 5 deletions README.md
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
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,17 @@ PythonNative is a cross-platform toolkit for building native Android and iOS app

## Features

- **Declarative components and hooks:** Describe native UI with Python functions, immutable elements, and typed styles. State, effects, context, and suspense boundaries follow one logical application tree across screens, overlays, and mounted list rows.
- **Declarative components and hooks:** Describe native UI with Python functions, immutable elements, and typed styles. State, effects, context, and suspense boundaries follow one logical application tree across screens, overlays, and mounted list rows. State updates batch automatically, effect errors reach the nearest error boundary, and event callbacks receive typed records instead of dicts.
- **React Native's core surface:** `Pressable`, `ScrollView`, `Text`, `TextInput`, `Image`, `Modal`, `FlatList`, and `SectionList` carry the props a React Native developer expects (disabled state and ripples, content insets and snapping, ellipsize modes and pressable spans, controlled selection and key events, sticky headers and inverted lists), plus typed imperative handles on `ref.current` and the full accessibility prop set.
- **Native widgets and layout:** Swift and Kotlin component managers own UIKit and Android widgets. The shared Yoga C++ engine computes layout beside the controls, using platform measurements for text and intrinsic sizes.
- **Standard asyncio:** Components, effects, event handlers, and tasks run on a dedicated Python application thread. Native UI threads handle widgets, scrolling, and animation frames. Component-owned tasks are canceled on unmount.
- **Incremental reconciliation:** State changes update affected component subtrees. Versioned bridge commits validate operations and acknowledge revisions; events and controlled text inputs carry identities that prevent stale updates.
- **Native lists and navigation:** UIKit collection views and Android recycler views recycle cells for fixed or variable row sizes, grids, sections, and horizontal lists. Native navigation containers present logical screen roots while providers and component state remain in the shared Python tree.
- **Animation and gestures:** Serialized animation graphs support timing, springs, decay, arithmetic, interpolation, and native scroll and gesture bindings. Swift and Kotlin recognize mobile gestures and update supported animation bindings without Python work on every frame.
- **Native lists and navigation:** UIKit collection views and Android recycler views recycle cells for fixed or variable row sizes, grids, sections, and horizontal lists. Native navigation containers present logical screen roots at every nesting level while providers and component state remain in the shared Python tree; navigators take screen options, groups, themes, tab-bar styles, and a navigation ref usable outside components.
- **Animation and gestures:** Serialized animation graphs support timing with named or bezier easing, springs, React Native's decay model, arithmetic, interpolation, and native scroll and gesture bindings. Swift and Kotlin recognize mobile gestures with Gesture Handler-style activation offsets and update supported animation bindings without Python work on every frame.
- **Assets and graphics:** Drop images, fonts, and SVGs under `app/assets/` and reference them by path. Density variants, bundled fonts, a vector `Icon` set, `Svg` drawing, gradients, and blur render natively on both platforms and in the browser preview.
- **Device APIs:** Python facades expose camera, location, notifications, storage, permissions, and other native services. Test permissions and platform behavior on your deployment targets.
- **Native extension SDK:** Python dataclasses and protocols define contracts; `pn codegen` generates props and module adapters for Swift and Kotlin. Plugins package native sources and resources, and builds verify matching contracts at startup.
- **Device APIs:** Python facades expose camera, location, notifications, storage, permissions, keyboard, dimensions and pixel ratio, device info, localization, accessibility settings, and other native services, with a Python fallback for headless tests. Test permissions and platform behavior on your deployment targets.
- **Native extension SDK:** Python dataclasses and protocols define contracts; `define_component` returns a typed element factory and `pn codegen` generates props and module adapters for Swift and Kotlin. Plugins package native sources and resources, and builds verify matching contracts at startup.
- **Testing library:** `pythonnative.testing` renders components headlessly with Testing Library-style queries (`get_by_role`, `get_by_placeholder_text`, `within`, `find_by_*`), a virtual clock for timers, and a pytest plugin that resets the runtime between tests.
- **Development tools:** `pn start` serves the browser preview and connected mobile dev clients. Fast Refresh preserves compatible component state, while diagnostics report errors and invalid hook usage. Changes to native inputs trigger a rebuild.
- **Browser preview:** `pn preview` runs your Python application against a browser renderer with DOM widgets, Yoga WebAssembly layout, and JavaScript animation graphs. It supports iteration on application logic and UI; fonts, platform controls, and device APIs require mobile testing.
- **App packaging and dependency locks:** `pn run` and `pn build` stage bundled app templates, native libraries, and Python sources. Target-specific wheel locks record dependency versions and hashes for mobile builds. Binary dependencies need compatible mobile wheels; `pn deps` reports target resolution.
Expand Down
21 changes: 20 additions & 1 deletion docs/api/animated.md
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
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,24 @@ Python reconciliation on each frame. Unattached values, Python listeners,
callable easing functions, and backends that decline native animation use
the Python ticker.

A few types frame the surface:

- [`Easing`][pythonnative.animated.Easing] is a namespace of
serializable [`EasingSpec`][pythonnative.animated.EasingSpec] curves
(`Easing.ease_out`, `Easing.bezier(...)`) accepted by
`Animated.timing(easing=...)`; a misspelled easing name raises
`ValueError` instead of falling back.
- `await handle` and `handle.start(callback)` deliver an
[`AnimationResult`][pythonnative.animated.AnimationResult] whose
`finished` flag tells a stopped or superseded animation from one that
ran to completion.
- [`ANIMATABLE_PROPS`][pythonnative.animated.ANIMATABLE_PROPS] lists
the style keys an animated node may drive; binding a layout key such
as `width` raises `ValueError` at element construction.
- `Animated.decay` uses React Native's model on every platform:
velocity in points per millisecond decays as
`v0 * deceleration ** t`, with `deceleration` defaulting to `0.998`.

::: pythonnative.animated
options:
show_root_heading: false
Expand All @@ -21,6 +39,7 @@ the Python ticker.
## See also

- The [Animations guide](../guides/animations.md) walks through
fade-ins, springs, sequences, and gesture-driven animations.
fade-ins, springs, sequences, easing, decay, and gesture-driven
animations.
- [`use_ref`][pythonnative.use_ref] explains the `ref` semantics that
back `Animated.View`.
Loading
Loading

Back | FazBrowse Home | New Git URL