From cadda45ef2e0ce37de41eacbec311faeb26bc753 Mon Sep 17 00:00:00 2001
From: BREW <81044362+b-re-w@users.noreply.github.com>
Date: Sat, 3 Oct 2026 07:30:30 +0900
Subject: [PATCH] Chore: Delete the dead material3 records, the empty
placeholders and wrapper/
icon.py and color_scheme.py looked Kotlin functions up by mangled-name prefix,
the reflection INTENT section 3 excludes, and nothing has imported them since
#28. The 29 other material3/*.py files were zero bytes and always had been.
wrapper/ was a retired 2024 shell. Every Material 3 composable is served by
the re-export rule, so none of these carried anything. What icon.py recorded
-- Icon needs an ImageVector nothing bound produces, the colour schemes need
36 Color parameters -- is SPEC S5.3, which now also points at
python-multiplatform #37 for the icons.
Approved by the ecosystem lead. lite/ and test/ are the maintainer's decision
(AGENTS.md section 16) and are untouched.
material3/__init__.py's long history comment of files that no longer exist is
replaced by a docstring that says what the package is and points at git log.
deleted: material3/icon.py, color_scheme.py, 29 empty material3/*.py,
wrapper/__init__.py (32 files).
test added: TheDeadFilesAreGone (2), red before the deletion. Removed the
tests that loaded icon.py / color_scheme.py (3) and wrapper's token check (1).
documentation corrected: SPEC S5.3, 9, Outside intent 5 and 7, PROJECT.md,
guide baseline.
Suite against python-multiplatform ba4c6f49 and the current sibling: 111 ->
109 passed. Without a checkout: 55 -> 53 passed, 56 skipped. The wheel test
still builds and passes. check_guide.py: 0.
Refs #31
---
PROJECT.md | 8 +-
docs/SPEC.md | 36 +-
docs/guide/getting-started.html | 2 +-
docs/guide/status.html | 2 +-
pythonx/compose/material3/__init__.py | 96 +----
pythonx/compose/material3/bottom_app_bar.py | 0
pythonx/compose/material3/bottom_sheet.py | 0
pythonx/compose/material3/checkbox.py | 0
pythonx/compose/material3/color_scheme.py | 361 ------------------
pythonx/compose/material3/date_picker.py | 0
pythonx/compose/material3/dialogs.py | 0
pythonx/compose/material3/dividers.py | 0
pythonx/compose/material3/dynamic_color.py | 0
pythonx/compose/material3/extended_fab.py | 0
pythonx/compose/material3/fab.py | 0
pythonx/compose/material3/icon.py | 61 ---
pythonx/compose/material3/menus.py | 0
pythonx/compose/material3/navigation_bar.py | 0
.../compose/material3/navigation_drawer.py | 0
pythonx/compose/material3/navigation_rail.py | 0
.../compose/material3/progress_indicators.py | 0
pythonx/compose/material3/radio_button.py | 0
pythonx/compose/material3/scaffold.py | 0
pythonx/compose/material3/search_bar.py | 0
pythonx/compose/material3/segmented_button.py | 0
pythonx/compose/material3/shape.py | 0
pythonx/compose/material3/sliders.py | 0
pythonx/compose/material3/snackbars.py | 0
pythonx/compose/material3/surfaces.py | 0
pythonx/compose/material3/swipe_to_dismiss.py | 0
pythonx/compose/material3/switch.py | 0
pythonx/compose/material3/tabs.py | 0
pythonx/compose/material3/time_picker.py | 0
pythonx/compose/material3/tool_tip.py | 0
pythonx/compose/material3/top_app_bar.py | 0
pythonx/compose/material3/typography.py | 0
pythonx/compose/wrapper/__init__.py | 11 -
tests/test_legacy_modules.py | 14 -
tests/test_material3_module.py | 83 +---
39 files changed, 54 insertions(+), 620 deletions(-)
delete mode 100644 pythonx/compose/material3/bottom_app_bar.py
delete mode 100644 pythonx/compose/material3/bottom_sheet.py
delete mode 100644 pythonx/compose/material3/checkbox.py
delete mode 100644 pythonx/compose/material3/color_scheme.py
delete mode 100644 pythonx/compose/material3/date_picker.py
delete mode 100644 pythonx/compose/material3/dialogs.py
delete mode 100644 pythonx/compose/material3/dividers.py
delete mode 100644 pythonx/compose/material3/dynamic_color.py
delete mode 100644 pythonx/compose/material3/extended_fab.py
delete mode 100644 pythonx/compose/material3/fab.py
delete mode 100644 pythonx/compose/material3/icon.py
delete mode 100644 pythonx/compose/material3/menus.py
delete mode 100644 pythonx/compose/material3/navigation_bar.py
delete mode 100644 pythonx/compose/material3/navigation_drawer.py
delete mode 100644 pythonx/compose/material3/navigation_rail.py
delete mode 100644 pythonx/compose/material3/progress_indicators.py
delete mode 100644 pythonx/compose/material3/radio_button.py
delete mode 100644 pythonx/compose/material3/scaffold.py
delete mode 100644 pythonx/compose/material3/search_bar.py
delete mode 100644 pythonx/compose/material3/segmented_button.py
delete mode 100644 pythonx/compose/material3/shape.py
delete mode 100644 pythonx/compose/material3/sliders.py
delete mode 100644 pythonx/compose/material3/snackbars.py
delete mode 100644 pythonx/compose/material3/surfaces.py
delete mode 100644 pythonx/compose/material3/swipe_to_dismiss.py
delete mode 100644 pythonx/compose/material3/switch.py
delete mode 100644 pythonx/compose/material3/tabs.py
delete mode 100644 pythonx/compose/material3/time_picker.py
delete mode 100644 pythonx/compose/material3/tool_tip.py
delete mode 100644 pythonx/compose/material3/top_app_bar.py
delete mode 100644 pythonx/compose/material3/typography.py
delete mode 100644 pythonx/compose/wrapper/__init__.py
diff --git a/PROJECT.md b/PROJECT.md
index 9358df9..4ed2a79 100644
--- a/PROJECT.md
+++ b/PROJECT.md
@@ -35,14 +35,14 @@ Compose(`androidx.compose.*`)를 파이썬에서 쓰기 위한 pip 패키지 **`
```
python3 -m pytest tests -q
- PythonMultiplatform 체크아웃 없음 55 passed, 56 skipped
- python-multiplatform develop ba4c6f49+ 111 passed
+ PythonMultiplatform 체크아웃 없음 53 passed, 56 skipped
+ python-multiplatform develop ba4c6f49+ 109 passed
그보다 오래된 체크아웃 같은 수, 그중 5 개 건너뜀 (member resolver 없음)
```
member resolver(python-multiplatform `ba4c6f49`)가 없는 바인더에서는 proxy 의 snake_case 메서드를 부르는
5 개가 건너뛴다. 건너뜀은 통과가 아니다.
-체크아웃 없이 통과하는 55 개 중 다수는 *부재*(옛 토큰·삭제된 파일이 없음)를 확인하는 것이라 기능 진척으로 세지
+체크아웃 없이 통과하는 53 개 중 다수는 *부재*(옛 토큰·삭제된 파일이 없음)를 확인하는 것이라 기능 진척으로 세지
않는다.
### 마일스톤
@@ -70,7 +70,7 @@ pythonx/compose/ import 패키지 (현재 대부분 독스트링만 있
_reexport.py 매니페스트 모듈 전체에 적용되는 재노출 규칙 하나
ui/ modifier.py (빈 Modifier 등록 지점), alignment.py
layout/ arrangement.py
- material3/ icon.py, color_scheme.py (호출 불가 기록용), 빈 파일 28 개
+ material3/ __init__.py 하나 (위젯은 모두 재노출 규칙으로)
lite/ 2024 JPype 프로토타입 (은퇴, 바이너리 97 개 추적 중)
native/ 서브모듈 → thisisthepy/swing-graalvm-demo
tests/ pytest (unittest 스타일)
diff --git a/docs/SPEC.md b/docs/SPEC.md
index 3174022..65b092a 100644
--- a/docs/SPEC.md
+++ b/docs/SPEC.md
@@ -20,8 +20,8 @@ Run from a worktree with `python3 -m pytest tests -q` (pytest 8, CPython 3.13):
| Environment | Result |
|---|---|
-| No `PythonMultiplatform` checkout found | **55 passed, 56 skipped**, 67 subtests passed |
-| python-multiplatform `develop` at `ba4c6f49` or later (has `add_member_resolver`) | **111 passed**, 73 subtests passed |
+| No `PythonMultiplatform` checkout found | **53 passed, 56 skipped**, 66 subtests passed |
+| python-multiplatform `develop` at `ba4c6f49` or later (has `add_member_resolver`) | **109 passed**, 72 subtests passed |
| an older checkout, without `add_member_resolver` | the same, with 5 of them skipped |
Without a checkout, the 56 tests that install the binder's layers through `tests/adapter.py` skip.
@@ -29,7 +29,7 @@ Against a binder older than `ba4c6f49`, the 5 that call a snake_case method on a
returned skip, because that needs its member resolver (python-multiplatform #17). A skip is not a
pass.
-Of the 55 that pass without a checkout, most assert **absence** (a retired token, a deleted file, a docstring that
+Of the 53 that pass without a checkout, most assert **absence** (a retired token, a deleted file, a docstring that
exists). Those are listed in §9 and are not counted as features.
---
@@ -163,13 +163,13 @@ toggle family, `TextField`, `Checkbox` and `Switch` are meant to be reached thro
host binds no material3 declaration, so no test here exercises one; the render proof per widget
is issue #9.
-### S5.3 `Icon` and colour schemes — `partial`
+### S5.3 `Icon` and colour schemes — `planned`
-`pythonx/compose/material3/icon.py` and `color_scheme.py` import without raising
-(`tests/test_material3_module.py::TheTwoUnreachableWrappersLoadWithoutCrashing`) but are **not
-callable**: `Icon` needs an `ImageBitmap` / `ImageVector` / `Painter` nothing bound can produce, and
-the two colour-scheme factories take 36 `Color` parameters. The notebook uses `Icon` and
-`DefaultIcons` (§8).
+`Icon` needs an `ImageBitmap` / `ImageVector` / `Painter`, and nothing bound produces one until the
+binder walks `material-icons-core` (python-multiplatform #37; then `DefaultIcons` is
+`Icons.Default`, INTENT §5.7). The two colour-scheme factories take 36 `Color` parameters against
+the binding's omission cap (python-multiplatform `a6742a1c`). The hand-written `icon.py` /
+`color_scheme.py` that recorded this were dead code and are deleted (#31).
## 6. Modifiers — extension functions as methods
@@ -258,9 +258,11 @@ name)` (python-multiplatform #36; issue #9).
These tests pass and assert that retired 2024 mechanisms are gone. They are not features:
-- `tests/test_legacy_modules.py` (7 tests): no chaquopy / JPype tokens or dead relative imports in
- `layout/__init__.py`, `lite/*.py`, `test/main.py`, `ui/unit/__init__.py`, `wrapper/__init__.py`,
+- `tests/test_legacy_modules.py` (6 tests): no chaquopy / JPype tokens or dead relative imports in
+ `layout/__init__.py`, `lite/*.py`, `test/main.py`, `ui/unit/__init__.py`,
`material3/__init__.py`; each retired module carries a real docstring.
+- `tests/test_material3_module.py::TheDeadFilesAreGone` (2 tests): `material3/` holds only its
+ `__init__.py`, and `wrapper/` is gone (#31).
- `tests/test_ui_init_module.py::TheChaquopyUiInitMechanismIsGone` (1 test).
---
@@ -282,15 +284,9 @@ Found in the repository; not covered by `docs/INTENT.md`, or in conflict with it
4. **Two spellings for one module.** The manifest maps both `pythonx.compose.layout` and
`pythonx.compose.foundation.layout` (plus `pythonx.compose.foundation` and `pythonx.compose`)
"while the spelling settles".
-5. **A removed mechanism kept as a record.** `material3/icon.py` and `color_scheme.py` still import
- `androidx.compose.material3.IconKt` and scan for mangled JVM names (`"Icon-"`), the reflection
- approach INTENT §3 excludes.
- The package no longer imports them: star-importing them made `import pythonx.compose.material3`
- fail wherever `androidx.compose.material3` was not bound, and shadowed the binder's `Icon`.
- Whether the files stay is still open.
+5. *(Resolved, #31.)* `material3/icon.py` and `color_scheme.py`, dead reflection code, are deleted.
6. *(Decided, INTENT §5.3.)* Grouped alignment constants: both spellings are to be served; the grouped one is not built yet (§7).
-7. **28 empty `material3/*.py` files** (`checkbox.py`, `switch.py`, `scaffold.py`, ...), and the
- submodule `pythonx/compose/native` → `thisisthepy/swing-graalvm-demo`, which INTENT does not
- mention.
+7. The submodule `pythonx/compose/native` → `thisisthepy/swing-graalvm-demo`, which INTENT does not
+ mention. (The 29 empty `material3/*.py` files are deleted, #31.)
8. **The `test/` directory** — a 2023–2024 Kotlin Multiplatform sample (`pycomposeui`, chaquopy
era). Kept as-is pending the maintainer's decision (INTENT §4.2).
diff --git a/docs/guide/getting-started.html b/docs/guide/getting-started.html
index b980a55..33fb8f5 100644
--- a/docs/guide/getting-started.html
+++ b/docs/guide/getting-started.html
@@ -43,7 +43,7 @@
1. Get the source1. 소스
2. Run the tests2. 테스트 실행
python3 -m pytest tests -q
-Expect 55 passed, 56 skipped. The skipped tests drive the binder's adaptation layer and need a python-multiplatform checkout beside this one, or:
55 passed, 56 skipped 가 정상입니다. 건너뛴 테스트는 바인더의 적응 계층을 구동하며, 옆에 python-multiplatform 체크아웃이 있거나 다음이 필요합니다:
+Expect 53 passed, 56 skipped. The skipped tests drive the binder's adaptation layer and need a python-multiplatform checkout beside this one, or:
53 passed, 56 skipped 가 정상입니다. 건너뛴 테스트는 바인더의 적응 계층을 구동하며, 옆에 python-multiplatform 체크아웃이 있거나 다음이 필요합니다:
PYTHONMULTIPLATFORM_HOME=/path/to/python-multiplatform python3 -m pytest tests -q
With a current one (ba4c6f49 or later) all pass; an older one skips 5 that call a snake_case method on a proxy the binder returned. That is expected and recorded.
최신 체크아웃(ba4c6f49 이후)이면 전부 통과하고, 오래된 체크아웃은 바인더가 돌려준 proxy 의 snake_case 메서드를 부르는 5 개를 건너뜁니다. 예상된 상태이며 기록되어 있습니다.
diff --git a/docs/guide/status.html b/docs/guide/status.html
index 4e416d5..dfee6f9 100644
--- a/docs/guide/status.html
+++ b/docs/guide/status.html
@@ -36,7 +36,7 @@
| State상태 | Item항목 |
| implemented구현 | Mapping manifest pythonx-map.toml매핑 매니페스트 pythonx-map.toml |
| implemented구현 | @Composable identity decorator@Composable 항등 데코레이터 |
| partial부분 | Distribution as pythonx-compose — configured; no stubs yet, manifest outside the package directorypythonx-compose 배포 — 설정됨; 스텁 없음, 매니페스트가 패키지 디렉터리 밖 |
| implemented구현 | Modifier chains, overload dispatch, Dp as a numberModifier 체인, 오버로드 디스패치, 숫자 Dp |
| partial부분 | Snake-case names, keywords and signatures — done for modules and method names; method keywords are still Kotlin'ssnake_case 이름·키워드·시그니처 — 모듈과 메서드 이름 완료, 메서드 키워드는 아직 Kotlin 이름 |
| partial부분 | Material 3 widgets — re-exported by rule; render proofs per widget pending (#9)Material 3 위젯 — 규칙으로 재노출됨; 위젯별 렌더 증거 대기(#9) |
| partial부분 | Icon, colour schemes — importable, not callableIcon, 색 스킴 — import 가능, 호출 불가 |
| partial부분 | Alignment / Arrangement constants — reached from pythonx; grouped spelling pendingAlignment / Arrangement 상수 — pythonx 에서 읽힘; 묶음 표기 대기 |
| implemented구현 | pythonx as a real on-disk package re-exporting androidx.compose.* by one ruleandroidx.compose.* 를 규칙 하나로 재노출하는 실제 디스크 패키지 pythonx |
| planned계획 | .pyi stubs in the wheelwheel 안의 .pyi 스텁 |
| planned계획 | remember_saveable, DefaultIcons, coroutine scopesremember_saveable, DefaultIcons, 코루틴 스코프 |
-Test baseline: 55 passed, 56 skipped without a python-multiplatform checkout; 111 passed with a current one.
테스트 기준선: python-multiplatform 체크아웃이 없으면 55 passed, 56 skipped, 최신 체크아웃이면 111 passed.
+Test baseline: 53 passed, 56 skipped without a python-multiplatform checkout; 109 passed with a current one.
테스트 기준선: python-multiplatform 체크아웃이 없으면 53 passed, 56 skipped, 최신 체크아웃이면 109 passed.
FAQ
diff --git a/pythonx/compose/material3/__init__.py b/pythonx/compose/material3/__init__.py
index 5c43820..2973b78 100644
--- a/pythonx/compose/material3/__init__.py
+++ b/pythonx/compose/material3/__init__.py
@@ -1,83 +1,23 @@
-# `icon.py` and `color_scheme.py` are records, not part of this package's surface, and are not
-# imported here. Star-importing them made `import pythonx.compose.material3` import
-# `androidx.compose.material3` at load time -- failing wherever that Kotlin package is not bound --
-# and put their dead `Icon` / `ColorScheme` classes in front of the binder's real ones, which the
-# re-export rule below serves. Whether the two files stay is an open question (SPEC, Outside intent 5).
+"""`pythonx.compose.material3` -- the Pythonic view of `androidx.compose.material3`.
+Every Material 3 composable (`Text`, `Button`, `Card`, `TextField`, `Checkbox`, ...) is served by
+the one rule in `pythonx/compose/_reexport.py`: Kotlin's own declaration, upper-case names kept,
+keyword arguments in snake_case (`on_click=`). There is no per-widget file here, on purpose
+(AGENTS.md section 13). The notebook's `Column`, `Row` and `Spacer` are answered from
+`pythonx.compose.layout` by the manifest's `[aliases]` (INTENT section 5.2).
-# `Text` is not here. `pythonx.compose.material3.Text` is a walked declaration -- the adaptation
-# layer builds it from the artefact table, the same way `pythonx.compose.ui.Modifier.padding` is
-# built and not hand-written (`pythonx/compose/ui/modifier.py`). A per-declaration `text.py` used to
-# be imported here; it duplicated what the layer already does and could not be repaired (it looked
-# `Text-` up by a name-prefix search Kotlin's value-class mangling makes impossible -- see
-# `modifier.py`'s module docstring for why). `tests/test_material3_module.py` is what checks this.
-#
-# `Button`, `Card`, `ListItem`, `Badge`/`BadgedBox` and `MaterialTheme` are not here either, for the
-# same reason and on the same evidence shape: `PythonMultiplatform` commit `a6742a1c`
-# (`ComposableRenderTest.kt`) renders each of them from Python with no wrapper at all, content
-# lambda and (where present) `on_click` included, against the real `material3` jar --
-#
-# buttonComposesItsClickHandlerAndItsRowScopedContent -> buttons.py (Button et al.)
-# cardResolvesToTheNonClickableOverloadAndDrawsItsContent -> cards.py (Card et al.)
-# listItemComposesItsHeadlineContentUnderItsSnakeCasedName -> lists.py (ListItem)
-# badgeDrawsItsLeafFormWithNoArgumentsAndMoreWithContent -> badge.py (Badge)
-# badgedBoxComposesBothItsBadgeAndItsContentScopes -> badge.py (BadgedBox)
-# materialThemeComposesAZeroArgumentContentLambda -> material_theming.py (MaterialTheme)
-#
-# Each of those files was a copy of the same `__COMPILED_CODE__` / `find_composable` /
-# `name.startswith("-")` template `text.py` and `modifier.py` used -- the sibling declarations
-# in each file (`ElevatedButton`, `OutlinedCard`, ...) were never individually rendered, but they are
-# the identical template with only the `*Kt` attribute name changed, so the one proof per file is the
-# same class of evidence the `Text` deletion already established: the template is dead, not the
-# specific name. `tests/test_material3_module.py` asserts each file is gone.
-#
-# `icon_button.py` is now gone entirely, not just half. `IconButton` and its plain siblings already
-# had the render proof (`iconButtonComposesItsClickHandlerAndItsContent`, `a6742a1c`). The
-# `IconToggleButton` family (`checked: Boolean`, `onCheckedChange: (Boolean) -> Unit`) needed a
-# different shape of proof -- a static render delivers no events, so nothing about a callback slot
-# could be shown by rasterising -- and `PythonMultiplatform` commit `3fde8bd6`
-# (`CallbackDrivenRenderTest.kt`) supplies it: a real pointer press and release through
-# `ImageComposeScene.sendPointerEvent`, asserted to invoke the Python callback with the value Compose
-# handed it, on **two** declarations deliberately (`Checkbox` in `CheckboxKt`, then `Switch` in
-# `SwitchKt`, specifically to rule out a mechanism that only happens to work for one file). The
-# `IconToggleButton` family is a third declaration, in a third file (`IconButtonKt`), with that exact
-# same `(Boolean) -> Unit` shape -- the same class of generalisation this module already applies
-# within a single file for `Button`'s and `IconButton`'s untested siblings, extended here across
-# files because the render test itself was built to cross that boundary.
-#
-# `text_field.py` is now gone too. `on_value_change` is `(String) -> Unit` -- a shape
-# `CallbackDrivenRenderTest.kt` did not used to drive, only `(Boolean) -> Unit` -- so it stayed
-# hand-written after `icon_button.py` went. `PythonMultiplatform` commit `cac8243f` closes that gap:
-# `typingIntoATextFieldInvokesThePythonCallbackWithTheStringAndTheNextRenderShowsIt` types a real key
-# event into a `pythonx`-bound `TextField`, asserts the Python callback received the string, and
-# asserts a fresh render shows it; `twoKeystrokesAccumulateAcrossTwoFreshScenes` repeats it across two
-# scenes to show the string accumulates rather than just landing once. Same bar the toggle buttons
-# met, same conclusion. `tests/test_material3_module.py` is what checks all of this.
-#
-# `icon.py` and `color_scheme.py` do **not** get the same conclusion, and are not going anywhere:
-# `PythonMultiplatform` commit `a6742a1c` pinned `Icon`, `lightColorScheme` and `darkColorScheme` as
-# *unreachable* through the walked table -- `Icon` needs an `ImageBitmap`/`ImageVector`/`Painter`
-# nothing walked can produce, and the two color-scheme factories need 36 `Color` parameters against a
-# 6-parameter omission cap -- which is a stronger, opposite finding from the one that deleted
-# `text.py`/`icon_button.py`/`text_field.py` (those were proven *redundant*; these were proven
-# *uncallable any way at all*). The hand-written wrapper is the only Python-facing record of that, so
-# it stays. What it no longer does is subclass `pythonx.compose.runtime.Composable`: `7d6c0a1`
-# replaced that name's 2024 *class* with a plain identity-decorator *function*, and a function cannot
-# be a base class -- `class Icon(Composable):` raised `TypeError` the moment this package was
-# imported, which broke every other, working declaration in this package along with it, not just the
-# two that are genuinely unreachable. Both classes are now defined plain, without a base, so importing
-# this package no longer depends on two declarations that can never be called anyway. Calling either
-# still fails (`self.composer` is never set -- nothing sets it, because the composer-threading base
-# class it depended on is exactly what `7d6c0a1` retired), which is accurate: neither declaration
-# works, before or after this fix. `tests/test_material3_module.py` checks the import no longer
-# raises.
-#
-# `checkbox.py` and `switch.py` are not files in the sense any of the above are: both have been
-# empty since before this package had an adaptation layer to defer to (`git log -p` on either shows
-# no non-empty version). `Checkbox`/`Switch` reach Python entirely through the walked table -- which
-# is exactly what `CallbackDrivenRenderTest.kt` exercises above -- and the empty files cost nothing
-# and assert nothing; they are left as they are rather than deleted, so as not to conflate "always
-# empty" with "emptied on evidence" in the file history.
+## What used to be here
+
+Per-widget wrappers from 2024 (`text.py`, `buttons.py`, `cards.py`, `icon_button.py`,
+`text_field.py`, ...), each a copy of one template that looked a Kotlin function up by a
+mangled-name prefix (`name.startswith("Button-")`), which Kotlin's value-class mangling makes
+impossible. They were deleted as the binder rendered each declaration with no wrapper
+(python-multiplatform `c60bcfeb`, `a6742a1c`, `3fde8bd6`, `cac8243f`). `icon.py` and
+`color_scheme.py` were kept as records of two declarations that cannot be called yet, and 29
+sibling files had always been empty; all were deleted in pythonx-compose #31. What `icon.py`
+recorded -- `Icon` needs an `ImageVector` nothing bound produces -- is SPEC S5.3. `git log` on this
+directory has the rest.
+"""
from pythonx.compose._reexport import reexport
diff --git a/pythonx/compose/material3/bottom_app_bar.py b/pythonx/compose/material3/bottom_app_bar.py
deleted file mode 100644
index e69de29..0000000
diff --git a/pythonx/compose/material3/bottom_sheet.py b/pythonx/compose/material3/bottom_sheet.py
deleted file mode 100644
index e69de29..0000000
diff --git a/pythonx/compose/material3/checkbox.py b/pythonx/compose/material3/checkbox.py
deleted file mode 100644
index e69de29..0000000
diff --git a/pythonx/compose/material3/color_scheme.py b/pythonx/compose/material3/color_scheme.py
deleted file mode 100644
index df7b962..0000000
--- a/pythonx/compose/material3/color_scheme.py
+++ /dev/null
@@ -1,361 +0,0 @@
-from androidx.compose.material3 import ColorSchemeKt
-from androidx.compose.material3 import ColorScheme
-
-__COMPILED_CODE__ = None
-Unit = None
-
-class ColorScheme:
- """ M3 color scheme.
-
- Not usable -- kept only because `PythonMultiplatform` commit `a6742a1c` pinned `ColorScheme`'s
- factories as unreachable through the walked adaptation table (36 `Color` parameters, all
- defaulted in Kotlin, none omittable in the binding, against a 6-parameter omission cap), so this
- hand-written wrapper is the only Python-facing record of that. It does not subclass
- `pythonx.compose.runtime.Composable` (`7d6c0a1` made that name a plain identity-decorator
- function, not a base class -- inheriting from it raises `TypeError` at class-definition time,
- which used to break importing this whole package, not just this declaration). `compose()` below
- still reaches for `self.composer`, which nothing sets; calling it fails, which is correct, since
- the declaration cannot be reached this way either.
- """
-
- def __init__(self):
- super().__init__()
- self.__kotlin_composable = None
-
- def find_composable(self):
- super().__init__()
-
- if self.__kotlin_composable is None:
- try:
- self.__kotlin_composable = ColorScheme
- except Exception:
- for name, obj in ColorSchemeKt.__dict__.items():
- if name.startswith("ColorScheme-"):
- self.__kotlin_composable = obj
- break
-
- if not self.__kotlin_composable:
- raise Exception("ColorScheme is cannot be found")
-
- def compose(
- self,
- primary=__COMPILED_CODE__,
- on_primary=__COMPILED_CODE__,
- primary_container=__COMPILED_CODE__,
- on_primary_container=__COMPILED_CODE__,
- inverse_primary=__COMPILED_CODE__,
- secondary=__COMPILED_CODE__,
- on_secondary=__COMPILED_CODE__,
- secondary_container=__COMPILED_CODE__,
- on_secondary_container=__COMPILED_CODE__,
- tertiary=__COMPILED_CODE__,
- on_tertiary=__COMPILED_CODE__,
- tertiary_container=__COMPILED_CODE__,
- on_tertiary_container=__COMPILED_CODE__,
- background=__COMPILED_CODE__,
- on_background=__COMPILED_CODE__,
- surface=__COMPILED_CODE__,
- on_surface=__COMPILED_CODE__,
- surface_variant=__COMPILED_CODE__,
- on_surface_variant=__COMPILED_CODE__,
- surface_tint=__COMPILED_CODE__,
- inverse_surface=__COMPILED_CODE__,
- inverse_on_surface=__COMPILED_CODE__,
- error=__COMPILED_CODE__,
- on_error=__COMPILED_CODE__,
- error_container=__COMPILED_CODE__,
- on_error_container=__COMPILED_CODE__,
- outline=__COMPILED_CODE__,
- outline_variant=__COMPILED_CODE__,
- scrim=__COMPILED_CODE__,
- surface_bright=__COMPILED_CODE__,
- surface_dim=__COMPILED_CODE__,
- surface_container=__COMPILED_CODE__,
- surface_container_high=__COMPILED_CODE__,
- surface_container_highest=__COMPILED_CODE__,
- surface_container_low=__COMPILED_CODE__,
- surface_container_lowest=__COMPILED_CODE__,
- ):
- kwargs = { key: value for key, value in dict(
- primary=primary,
- onPrimary=on_primary,
- primaryContainer=primary_container,
- onPrimaryContainer=on_primary_container,
- inversePrimary=inverse_primary,
- secondary=secondary,
- onSecondary=on_secondary,
- secondaryContainer=secondary_container,
- onSecondaryContainer=on_secondary_container,
- tertiary=tertiary,
- onTertiary=on_tertiary,
- tertiaryContainer=tertiary_container,
- onTertiaryContainer=on_tertiary_container,
- background=background,
- onBackground=on_background,
- surface=surface,
- onSurface=on_surface,
- surfaceVariant=surface_variant,
- onSurfaceVariant=on_surface_variant,
- surfaceTint=surface_tint,
- inverseSurface=inverse_surface,
- inverseOnSurface=inverse_on_surface,
- error=error,
- onError=on_error,
- errorContainer=error_container,
- onErrorContainer=on_error_container,
- outline=outline,
- outlineVariant=outline_variant,
- scrim=scrim,
- surfaceBright=surface_bright,
- surfaceDim=surface_dim,
- surfaceContainer=surface_container,
- surfaceContainerHigh=surface_container_high,
- surfaceContainerHighest=surface_container_highest,
- surfaceContainerLow=surface_container_low,
- surfaceContainerLowest=surface_container_lowest
-
-
- ) if value is not __COMPILED_CODE__ }
-
- if self.__kotlin_composable is None:
- self.find_composable()
-
- self.__kotlin_composable(
- **kwargs,
- c=self.composer,
- changed=1
- )
-
-
-class lightColorScheme:
- """ M3 light color scheme.
-
- Not usable -- see `ColorScheme`'s docstring above: `a6742a1c` pinned this factory unreachable
- (36 `Color` parameters against a 6-parameter omission cap), and this no longer subclasses
- `pythonx.compose.runtime.Composable` for the same class-definition-time `TypeError` reason.
- """
-
- def __init__(self):
- super().__init__()
- self.__kotlin_composable = None
-
- def find_composable(self):
- super().__init__()
-
- if self.__kotlin_composable is None:
- try:
- self.__kotlin_composable = ColorSchemeKt.lightColorScheme
- except Exception:
- for name, obj in ColorSchemeKt.__dict__.items():
- if name.startswith("lightColorScheme-"):
- self.__kotlin_composable = obj
- break
-
- if not self.__kotlin_composable:
- raise Exception("lightColorScheme is cannot be found")
-
- def compose(
- self,
- primary=__COMPILED_CODE__,
- on_primary=__COMPILED_CODE__,
- primary_container=__COMPILED_CODE__,
- on_primary_container=__COMPILED_CODE__,
- inverse_primary=__COMPILED_CODE__,
- secondary=__COMPILED_CODE__,
- on_secondary=__COMPILED_CODE__,
- secondary_container=__COMPILED_CODE__,
- on_secondary_container=__COMPILED_CODE__,
- tertiary=__COMPILED_CODE__,
- on_tertiary=__COMPILED_CODE__,
- tertiary_container=__COMPILED_CODE__,
- on_tertiary_container=__COMPILED_CODE__,
- background=__COMPILED_CODE__,
- on_background=__COMPILED_CODE__,
- surface=__COMPILED_CODE__,
- on_surface=__COMPILED_CODE__,
- surface_variant=__COMPILED_CODE__,
- on_surface_variant=__COMPILED_CODE__,
- surface_tint=__COMPILED_CODE__,
- inverse_surface=__COMPILED_CODE__,
- inverse_on_surface=__COMPILED_CODE__,
- error=__COMPILED_CODE__,
- on_error=__COMPILED_CODE__,
- error_container=__COMPILED_CODE__,
- on_error_container=__COMPILED_CODE__,
- outline=__COMPILED_CODE__,
- outline_variant=__COMPILED_CODE__,
- scrim=__COMPILED_CODE__,
- surface_bright=__COMPILED_CODE__,
- surface_dim=__COMPILED_CODE__,
- surface_container=__COMPILED_CODE__,
- surface_container_high=__COMPILED_CODE__,
- surface_container_highest=__COMPILED_CODE__,
- surface_container_low=__COMPILED_CODE__,
- surface_container_lowest=__COMPILED_CODE__,
- ):
- kwargs = { key: value for key, value in dict(
- primary=primary,
- onPrimary=on_primary,
- primaryContainer=primary_container,
- onPrimaryContainer=on_primary_container,
- inversePrimary=inverse_primary,
- secondary=secondary,
- onSecondary=on_secondary,
- secondaryContainer=secondary_container,
- onSecondaryContainer=on_secondary_container,
- tertiary=tertiary,
- onTertiary=on_tertiary,
- tertiaryContainer=tertiary_container,
- onTertiaryContainer=on_tertiary_container,
- background=background,
- onBackground=on_background,
- surface=surface,
- onSurface=on_surface,
- surfaceVariant=surface_variant,
- onSurfaceVariant=on_surface_variant,
- surfaceTint=surface_tint,
- inverseSurface=inverse_surface,
- inverseOnSurface=inverse_on_surface,
- error=error,
- onError=on_error,
- errorContainer=error_container,
- onErrorContainer=on_error_container,
- outline=outline,
- outlineVariant=outline_variant,
- scrim=scrim,
- surfaceBright=surface_bright,
- surfaceDim=surface_dim,
- surfaceContainer=surface_container,
- surfaceContainerHigh=surface_container_high,
- surfaceContainerHighest=surface_container_highest,
- surfaceContainerLow=surface_container_low,
- surfaceContainerLowest=surface_container_lowest
-
-
- ) if value is not __COMPILED_CODE__ }
-
- if self.__kotlin_composable is None:
- self.find_composable()
-
- self.__kotlin_composable(
- **kwargs,
- c=self.composer,
- changed=1
- )
-
-
-class darkColorScheme:
- """ M3 dark color scheme.
-
- Not usable -- see `ColorScheme`'s docstring above: `a6742a1c` pinned this factory unreachable
- (36 `Color` parameters against a 6-parameter omission cap), and this no longer subclasses
- `pythonx.compose.runtime.Composable` for the same class-definition-time `TypeError` reason.
- """
-
- def __init__(self):
- super().__init__()
- self.__kotlin_composable = None
-
- def find_composable(self):
- super().__init__()
-
- if self.__kotlin_composable is None:
- try:
- self.__kotlin_composable = ColorSchemeKt.darkColorScheme
- except Exception:
- for name, obj in ColorSchemeKt.__dict__.items():
- if name.startswith("darkColorScheme-"):
- self.__kotlin_composable = obj
- break
-
- if not self.__kotlin_composable:
- raise Exception("darkColorScheme is cannot be found")
-
- def compose(
- self,
- primary=__COMPILED_CODE__,
- on_primary=__COMPILED_CODE__,
- primary_container=__COMPILED_CODE__,
- on_primary_container=__COMPILED_CODE__,
- inverse_primary=__COMPILED_CODE__,
- secondary=__COMPILED_CODE__,
- on_secondary=__COMPILED_CODE__,
- secondary_container=__COMPILED_CODE__,
- on_secondary_container=__COMPILED_CODE__,
- tertiary=__COMPILED_CODE__,
- on_tertiary=__COMPILED_CODE__,
- tertiary_container=__COMPILED_CODE__,
- on_tertiary_container=__COMPILED_CODE__,
- background=__COMPILED_CODE__,
- on_background=__COMPILED_CODE__,
- surface=__COMPILED_CODE__,
- on_surface=__COMPILED_CODE__,
- surface_variant=__COMPILED_CODE__,
- on_surface_variant=__COMPILED_CODE__,
- surface_tint=__COMPILED_CODE__,
- inverse_surface=__COMPILED_CODE__,
- inverse_on_surface=__COMPILED_CODE__,
- error=__COMPILED_CODE__,
- on_error=__COMPILED_CODE__,
- error_container=__COMPILED_CODE__,
- on_error_container=__COMPILED_CODE__,
- outline=__COMPILED_CODE__,
- outline_variant=__COMPILED_CODE__,
- scrim=__COMPILED_CODE__,
- surface_bright=__COMPILED_CODE__,
- surface_dim=__COMPILED_CODE__,
- surface_container=__COMPILED_CODE__,
- surface_container_high=__COMPILED_CODE__,
- surface_container_highest=__COMPILED_CODE__,
- surface_container_low=__COMPILED_CODE__,
- surface_container_lowest=__COMPILED_CODE__,
- ):
- kwargs = { key: value for key, value in dict(
- primary=primary,
- onPrimary=on_primary,
- primaryContainer=primary_container,
- onPrimaryContainer=on_primary_container,
- inversePrimary=inverse_primary,
- secondary=secondary,
- onSecondary=on_secondary,
- secondaryContainer=secondary_container,
- onSecondaryContainer=on_secondary_container,
- tertiary=tertiary,
- onTertiary=on_tertiary,
- tertiaryContainer=tertiary_container,
- onTertiaryContainer=on_tertiary_container,
- background=background,
- onBackground=on_background,
- surface=surface,
- onSurface=on_surface,
- surfaceVariant=surface_variant,
- onSurfaceVariant=on_surface_variant,
- surfaceTint=surface_tint,
- inverseSurface=inverse_surface,
- inverseOnSurface=inverse_on_surface,
- error=error,
- onError=on_error,
- errorContainer=error_container,
- onErrorContainer=on_error_container,
- outline=outline,
- outlineVariant=outline_variant,
- scrim=scrim,
- surfaceBright=surface_bright,
- surfaceDim=surface_dim,
- surfaceContainer=surface_container,
- surfaceContainerHigh=surface_container_high,
- surfaceContainerHighest=surface_container_highest,
- surfaceContainerLow=surface_container_low,
- surfaceContainerLowest=surface_container_lowest
-
-
- ) if value is not __COMPILED_CODE__ }
-
- if self.__kotlin_composable is None:
- self.find_composable()
-
- self.__kotlin_composable(
- **kwargs,
- c=self.composer,
- changed=1
- )
\ No newline at end of file
diff --git a/pythonx/compose/material3/date_picker.py b/pythonx/compose/material3/date_picker.py
deleted file mode 100644
index e69de29..0000000
diff --git a/pythonx/compose/material3/dialogs.py b/pythonx/compose/material3/dialogs.py
deleted file mode 100644
index e69de29..0000000
diff --git a/pythonx/compose/material3/dividers.py b/pythonx/compose/material3/dividers.py
deleted file mode 100644
index e69de29..0000000
diff --git a/pythonx/compose/material3/dynamic_color.py b/pythonx/compose/material3/dynamic_color.py
deleted file mode 100644
index e69de29..0000000
diff --git a/pythonx/compose/material3/extended_fab.py b/pythonx/compose/material3/extended_fab.py
deleted file mode 100644
index e69de29..0000000
diff --git a/pythonx/compose/material3/fab.py b/pythonx/compose/material3/fab.py
deleted file mode 100644
index e69de29..0000000
diff --git a/pythonx/compose/material3/icon.py b/pythonx/compose/material3/icon.py
deleted file mode 100644
index 47125c7..0000000
--- a/pythonx/compose/material3/icon.py
+++ /dev/null
@@ -1,61 +0,0 @@
-from androidx.compose.material3 import IconKt
-
-__COMPILED_CODE__ = None
-Unit = None
-
-class Icon:
- """ M3 icon.
-
- Not usable -- kept only because `PythonMultiplatform` commit `a6742a1c` pinned `Icon` as
- unreachable through the walked adaptation table (every overload needs an `ImageBitmap`,
- `ImageVector` or `Painter`, and nothing walked produces one), so this hand-written wrapper is the
- only Python-facing record of that. It does not subclass `pythonx.compose.runtime.Composable`
- (`7d6c0a1` made that name a plain identity-decorator function, not a base class -- inheriting from
- it raises `TypeError` at class-definition time, which used to break importing this whole package,
- not just this declaration). `compose()` below still reaches for `self.composer`, which nothing
- sets; calling it fails, which is correct, since the declaration cannot be reached this way either.
- """
-
- def __init__(self):
- super().__init__()
- self.__kotlin_composable = None
-
- def find_composable(self):
- super().__init__()
-
- if self.__kotlin_composable is None:
- try:
- self.__kotlin_composable = IconKt.Icon
- except Exception:
- for name, obj in IconKt.__dict__.items():
- if name.startswith("Icon-"):
- self.__kotlin_composable = obj
- break
-
- if not self.__kotlin_composable:
- raise Exception("Icon is cannot be found")
-
- def compose(
- self,
- bitmap=__COMPILED_CODE__,
- content_description=__COMPILED_CODE__,
- modifier=__COMPILED_CODE__,
- tint=__COMPILED_CODE__,
- content=__COMPILED_CODE__
- ):
- kwargs = { key: value for key, value in dict(
- bitmap=bitmap,
- contentDescription=content_description,
- modifier=modifier,
- tint=tint,
- content=content
- ) if value is not __COMPILED_CODE__ }
-
- if self.__kotlin_composable is None:
- self.find_composable()
-
- self.__kotlin_composable(
- **kwargs,
- c=self.composer,
- changed=1
- )
\ No newline at end of file
diff --git a/pythonx/compose/material3/menus.py b/pythonx/compose/material3/menus.py
deleted file mode 100644
index e69de29..0000000
diff --git a/pythonx/compose/material3/navigation_bar.py b/pythonx/compose/material3/navigation_bar.py
deleted file mode 100644
index e69de29..0000000
diff --git a/pythonx/compose/material3/navigation_drawer.py b/pythonx/compose/material3/navigation_drawer.py
deleted file mode 100644
index e69de29..0000000
diff --git a/pythonx/compose/material3/navigation_rail.py b/pythonx/compose/material3/navigation_rail.py
deleted file mode 100644
index e69de29..0000000
diff --git a/pythonx/compose/material3/progress_indicators.py b/pythonx/compose/material3/progress_indicators.py
deleted file mode 100644
index e69de29..0000000
diff --git a/pythonx/compose/material3/radio_button.py b/pythonx/compose/material3/radio_button.py
deleted file mode 100644
index e69de29..0000000
diff --git a/pythonx/compose/material3/scaffold.py b/pythonx/compose/material3/scaffold.py
deleted file mode 100644
index e69de29..0000000
diff --git a/pythonx/compose/material3/search_bar.py b/pythonx/compose/material3/search_bar.py
deleted file mode 100644
index e69de29..0000000
diff --git a/pythonx/compose/material3/segmented_button.py b/pythonx/compose/material3/segmented_button.py
deleted file mode 100644
index e69de29..0000000
diff --git a/pythonx/compose/material3/shape.py b/pythonx/compose/material3/shape.py
deleted file mode 100644
index e69de29..0000000
diff --git a/pythonx/compose/material3/sliders.py b/pythonx/compose/material3/sliders.py
deleted file mode 100644
index e69de29..0000000
diff --git a/pythonx/compose/material3/snackbars.py b/pythonx/compose/material3/snackbars.py
deleted file mode 100644
index e69de29..0000000
diff --git a/pythonx/compose/material3/surfaces.py b/pythonx/compose/material3/surfaces.py
deleted file mode 100644
index e69de29..0000000
diff --git a/pythonx/compose/material3/swipe_to_dismiss.py b/pythonx/compose/material3/swipe_to_dismiss.py
deleted file mode 100644
index e69de29..0000000
diff --git a/pythonx/compose/material3/switch.py b/pythonx/compose/material3/switch.py
deleted file mode 100644
index e69de29..0000000
diff --git a/pythonx/compose/material3/tabs.py b/pythonx/compose/material3/tabs.py
deleted file mode 100644
index e69de29..0000000
diff --git a/pythonx/compose/material3/time_picker.py b/pythonx/compose/material3/time_picker.py
deleted file mode 100644
index e69de29..0000000
diff --git a/pythonx/compose/material3/tool_tip.py b/pythonx/compose/material3/tool_tip.py
deleted file mode 100644
index e69de29..0000000
diff --git a/pythonx/compose/material3/top_app_bar.py b/pythonx/compose/material3/top_app_bar.py
deleted file mode 100644
index e69de29..0000000
diff --git a/pythonx/compose/material3/typography.py b/pythonx/compose/material3/typography.py
deleted file mode 100644
index e69de29..0000000
diff --git a/pythonx/compose/wrapper/__init__.py b/pythonx/compose/wrapper/__init__.py
deleted file mode 100644
index 79d80a5..0000000
--- a/pythonx/compose/wrapper/__init__.py
+++ /dev/null
@@ -1,11 +0,0 @@
-"""`pythonx/compose/wrapper/__init__.py` -- 2024 `KotlinWrapper` class mutation trick, retired.
-
-## What used to be here, and why it is gone
-
-`KotlinWrapper` reclassed live Java objects onto a Python class (`kotlin_object.__class__ = cls`).
-That trick was Chaquopy-specific.
-
-Under `PythonMultiplatform`, Kotlin objects are represented as `ObjectReference` integer handles in a
-`HandleTable`, and an `int` does not support `__class__` assignment. Proxy classes and method attachment
-are now handled by `PythonxAdapter`.
-"""
diff --git a/tests/test_legacy_modules.py b/tests/test_legacy_modules.py
index e801682..ef43f0a 100644
--- a/tests/test_legacy_modules.py
+++ b/tests/test_legacy_modules.py
@@ -5,7 +5,6 @@
- `pythonx/compose/lite/app.py`, `jvm.py`, `material3.py`, `runtime.py`
- `pythonx/compose/test/main.py`
- `pythonx/compose/ui/unit/__init__.py` and `pythonx/compose/ui/unit/dp.py`
-- `pythonx/compose/wrapper/__init__.py`
- `pythonx/compose/material3/__init__.py`
"""
@@ -25,7 +24,6 @@
TEST_MAIN = REPO / "pythonx" / "compose" / "test" / "main.py"
UI_UNIT_INIT = REPO / "pythonx" / "compose" / "ui" / "unit" / "__init__.py"
UI_UNIT_DP = REPO / "pythonx" / "compose" / "ui" / "unit" / "dp.py"
-WRAPPER_INIT = REPO / "pythonx" / "compose" / "wrapper" / "__init__.py"
MATERIAL3_INIT = REPO / "pythonx" / "compose" / "material3" / "__init__.py"
@@ -96,17 +94,6 @@ def test_ui_unit_init_has_no_dead_relative_import_tokens(self) -> None:
)
-class TestWrapperModuleNoDeadTokens(unittest.TestCase):
- def test_wrapper_init_has_no_chaquopy_class_mutation_tokens(self) -> None:
- tokens = _get_executable_tokens(WRAPPER_INIT)
- for banned in ("KotlinWrapper", "__class__"):
- self.assertNotIn(
- banned,
- tokens,
- f"pythonx/compose/wrapper/__init__.py still contains Chaquopy wrapper token: {banned}",
- )
-
-
class TestMaterial3InitNoPlaceholderStarImports(unittest.TestCase):
def test_material3_init_has_no_dead_star_imports_of_placeholder_files(self) -> None:
tokens = _get_executable_tokens(MATERIAL3_INIT)
@@ -143,7 +130,6 @@ class TestRetiredModulesExposeTheirExplanationAsADocstring(unittest.TestCase):
"pythonx/compose/ui/unit/dp.py",
"pythonx/compose/ui/unit/__init__.py",
"pythonx/compose/test/main.py",
- "pythonx/compose/wrapper/__init__.py",
"pythonx/compose/lite/material3.py",
"pythonx/compose/lite/runtime.py",
"pythonx/compose/lite/app.py",
diff --git a/tests/test_material3_module.py b/tests/test_material3_module.py
index 8543470..7224424 100644
--- a/tests/test_material3_module.py
+++ b/tests/test_material3_module.py
@@ -222,77 +222,22 @@ def test_the_package_imports_with_no_binder_installed(self):
self.assertNotIn("Icon", vars(module))
-class TheTwoUnreachableWrappersLoadWithoutCrashing(unittest.TestCase):
- """`icon.py` (`Icon`) and `color_scheme.py` (`ColorScheme`/`lightColorScheme`/`darkColorScheme`)
- are the two declarations `PythonMultiplatform` commit `a6742a1c` pinned as *unreachable* through
- the walked table, not merely unconfirmed: `Icon` needs an `ImageBitmap`/`ImageVector`/`Painter`
- nothing walked can produce, and the two color-scheme factories need 36 `Color` parameters against
- the binding's 6-parameter omission cap. "Pinned unreachable" is a different conclusion from the
- evidence that deleted `text.py`, `icon_button.py` and now `text_field.py`: those were proven
- *redundant* (the walked table draws the same declaration with no wrapper), so the wrapper could
- go. `Icon`/`ColorScheme` were proven *uncallable any way at all*, which makes the hand-written
- wrapper the only Python-facing record of that fact -- so `text_field.py`'s reasoning does not
- apply and these two files stay, per this task's own instruction.
-
- Both files still wrote the 2024 shape, `class Icon(Composable):` /
- `class ColorScheme(Composable):`, inheriting from `pythonx.compose.runtime.Composable`. Commit
- `7d6c0a1` replaced that name's *class* with a plain identity-decorator *function* -- correct for
- `UI.ipynb`'s `@Composable def Screen(): ...` usage, but a function cannot be a base class, so the
- `class` statement itself now raises `TypeError` the moment either file is loaded. Because
- `pythonx/compose/material3/__init__.py` imports both unconditionally (`from .icon import *`,
- `from .color_scheme import *`), that `TypeError` previously took down `import
- pythonx.compose.material3` as a whole -- every other, working declaration (`Button`, `Card`,
- `Text`, ...) included, not just the two that are genuinely unreachable. That is the regression
- this class checks is fixed: loading each file must not raise, which it can satisfy without
- claiming `Icon`/`ColorScheme` now render (they still cannot -- see the class docstrings in each
- file) by simply not inheriting from something that is no longer a class.
+class TheDeadFilesAreGone(unittest.TestCase):
+ """`material3/` holds the package `__init__.py` and nothing else.
+
+ `icon.py` and `color_scheme.py` were dead reflection code (a mangled-name search INTENT section 3
+ excludes) that nothing imported any more, and 29 sibling files were zero bytes since before the
+ adaptation layer existed. What `icon.py` recorded -- `Icon` needs an `ImageVector` nothing bound
+ produces, and the colour-scheme factories need 36 `Color` parameters -- is in SPEC S5.3. Deleted
+ with the ecosystem lead's approval (pythonx-compose #31).
"""
- def setUp(self):
- # `androidx` is not installed in this pure-Python checkout (`docs/pythonx-adapter-design.md`
- # explains why: the real binding lives across a JVM/native boundary this repository's test
- # suite has no access to). Both files only *reference* a handful of attributes off
- # `androidx.compose.material3` at module scope and never call anything on them at import
- # time, so a bare stand-in that has those attributes is enough to reach the `class` statement
- # this test is actually about.
- stub = types.ModuleType("androidx.compose.material3")
- stub.IconKt = object()
- stub.ColorSchemeKt = object()
- stub.ColorScheme = object()
- self._previous = {
- name: sys.modules.get(name)
- for name in ("androidx", "androidx.compose", "androidx.compose.material3")
- }
- sys.modules["androidx"] = types.ModuleType("androidx")
- sys.modules["androidx.compose"] = types.ModuleType("androidx.compose")
- sys.modules["androidx.compose.material3"] = stub
- self.addCleanup(self._restore_androidx)
-
- def _restore_androidx(self):
- for name, previous in self._previous.items():
- if previous is None:
- sys.modules.pop(name, None)
- else:
- sys.modules[name] = previous
-
- def test_icon_module_loads_without_raising(self):
- module = _load_by_path(MATERIAL3_DIR / "icon.py", "_test_material3_icon")
- self.assertTrue(hasattr(module, "Icon"))
-
- def test_color_scheme_module_loads_without_raising(self):
- module = _load_by_path(MATERIAL3_DIR / "color_scheme.py", "_test_material3_color_scheme")
- self.assertTrue(hasattr(module, "ColorScheme"))
- self.assertTrue(hasattr(module, "lightColorScheme"))
- self.assertTrue(hasattr(module, "darkColorScheme"))
-
- def test_neither_file_inherits_from_the_now_functional_composable(self):
- for filename in ("icon.py", "color_scheme.py"):
- source = (MATERIAL3_DIR / filename).read_text(encoding="utf-8")
- self.assertNotIn(
- "(Composable)", source,
- f"{filename} still subclasses Composable, which 7d6c0a1 made a plain function -- "
- "that raises TypeError the moment the class statement runs",
- )
+ def test_only_the_package_init_remains(self):
+ files = sorted(p.name for p in MATERIAL3_DIR.glob("*.py"))
+ self.assertEqual(["__init__.py"], files)
+
+ def test_the_wrapper_package_is_gone(self):
+ self.assertFalse((REPO / "pythonx" / "compose" / "wrapper").exists())
if __name__ == "__main__":