diff --git a/PROJECT.md b/PROJECT.md index 6295619..c44c2f3 100644 --- a/PROJECT.md +++ b/PROJECT.md @@ -28,15 +28,15 @@ Compose(`androidx.compose.*`)를 파이썬에서 쓰기 위한 pip 패키지 **` | 상태 | 항목 | |---|---| | 구현 | 매핑 매니페스트 `pythonx-map.toml`, `@Composable` 항등 데코레이터, 실제 디스크 패키지 `pythonx` 와 모듈 수준 규칙 기반 재노출(snake_case 이름·키워드·시그니처, 오버로드 디스패치, 값 클래스 허용 목록), 실제 Compose 1.11.1 에서 생성한 `.pyi` 스텁과 `py.typed`(wheel 포함, mypy 로 검사), `Alignment`/`Arrangement` 상수(평면 `Alignment.End` 와 묶음 `Alignment.Horizontal.End` 모두, #9), proxy 메서드의 snake_case 키워드 인자(`m.padding(padding_values=...)`, python-multiplatform `describe_member` 필요; Kotlin 이름도 실행 시 그대로 통하고 스텁은 snake_case 만) | -| 부분 | 선언형 앱 루트 `@app`·`state`·`app_root`(#11; 로직은 테스트됨, 바인더 경로는 #38 모양의 가짜 호스트로 테스트됨, 실제 Compose 증거는 E2E 모듈 #19, 바인더가 `Any?` 칸의 int 를 거부하므로 `state(1)` 은 아직 TypeError, python-multiplatform #69 대기), 배포 설정, Material 3 위젯(렌더 증거는 python-multiplatform 에만), `Icon`·색 스킴(import 만 됨) | -| 계획 | `remember_saveable`·`DefaultIcons`·코루틴 스코프 | +| 부분 | 선언형 앱 루트 `@app`·`state`·`app_root`(#11; 로직은 테스트됨, 바인더 경로는 #38 모양의 가짜 호스트로 테스트됨, 실제 Compose 증거는 E2E 모듈 #19, 바인더가 `Any?` 칸의 int 를 거부하므로 `state(1)` 은 아직 TypeError, python-multiplatform #69 대기), 배포 설정, Material 3 위젯(렌더 증거는 python-multiplatform 에만), `Icon`(import 만 됨)·`DefaultIcons`(`Icons.Default` alias, 가짜 호스트로만 테스트됨; `DefaultIcons.Add` 로 쓴다 — 노트북의 `DefaultIcons.Add()` 가 아님) | +| 계획 | `remember_saveable`·색 스킴·코루틴 스코프 | ### 테스트 기준선 ``` python3 -m pytest tests -q - PythonMultiplatform 체크아웃 없음 116 passed, 87 skipped - python-multiplatform develop 31c092f0+ 202 passed, 1 skipped + PythonMultiplatform 체크아웃 없음 124 passed, 98 skipped + python-multiplatform develop 31c092f0+ 221 passed, 1 skipped describe_member 없는 체크아웃 같은 수, 그중 7 개 건너뜀 (python-multiplatform #54 이전) describe(module, name) 없는 체크아웃 같은 수, 그중 13 개 건너뜀 (python-multiplatform #36 이전) 그보다 오래된 체크아웃 거기에 5 개 더 건너뜀 (member resolver 없음) @@ -45,7 +45,7 @@ python3 -m pytest tests -q `describe_member`(python-multiplatform #54)가 없는 바인더에서는 메서드 키워드를 확인하는 7 개가(Kotlin 키워드로 되돌아가는 2 개는 실행됨), `describe(module, name)`(python-multiplatform #36)이 없는 바인더에서는 묶음 상수를 확인하는 13 개가, member resolver(python-multiplatform `ba4c6f49`)가 없는 바인더에서는 proxy 의 snake_case 메서드를 부르는 5 개가 더 건너뛴다. 두 환경 모두의 건너뜀 1 개는 worktree 에 없는 `UI.ipynb` 의 테스트다. 건너뜀은 통과가 아니다. -체크아웃 없이 통과하는 116 개 중 48 개는 타입 스텁과 wheel 을 검사하고(SPEC S1.2), 나머지 다수는 *부재*(옛 토큰·삭제된 +체크아웃 없이 통과하는 124 개 중 51 개는 타입 스텁과 wheel 을 검사하고(SPEC S1.2), 나머지 다수는 *부재*(옛 토큰·삭제된 파일이 없음)를 확인하는 것이라 기능 진척으로 세지 않는다. ### 마일스톤 @@ -128,7 +128,7 @@ python3 tools/check_guide.py # 가이드: HTML 파싱, 링 - **정렬 상수** 는 `Alignment.End` 와 `Alignment.Horizontal.End` 둘 다 지원한다. - 소문자 `modifier` 는 두지 않는다(`Modifier` 로 쓴다). ARGB 정수 색은 받지 않는다 (`Color(0xFFFF0000)`). `Spacer(start=...)` 는 지원하지 않는다(`Modifier.padding`). `DefaultIcons` 는 - `Icons.Default` 의 alias(python-multiplatform #37 뒤). — `docs/INTENT.md` §5.4–5.7 + `Icons.Default` 의 alias(매니페스트 `[aliases]` 의 `{ DefaultIcons = "Icons.Default" }`, 읽을 때마다 해석). — `docs/INTENT.md` §5.4–5.7 - 합성된 `pythonx` 를 전제한 테스트·독스트링은 #7 에서 정리했다. ## 8. 관련 저장소 diff --git a/README.md b/README.md index 6ea5263..d499e8d 100644 --- a/README.md +++ b/README.md @@ -160,7 +160,8 @@ standalone desktop toolkit. | Distribution (`pythonx-compose`) | 🟡 partial — the wheel carries the manifest, the re-export rule, the stubs and `py.typed` | | Declared app root (`@app`) and Pythonic state (`state`), no update call | 🟡 partial — binder path tested against a fake host shaped after python-multiplatform #38; real Compose is the E2E module (#11, #19); `state(1)` is refused by the binder (int in an `Any?` slot) | | `TextField` input-method (IME) handling | ⏳ planned (#10) | -| `Icon`, `DefaultIcons`, colour schemes | ⏳ planned (python-multiplatform #37) | +| `DefaultIcons` (`Icons.Default`), written `DefaultIcons.Add` | 🟡 partial — tested against a fake host shaped after python-multiplatform #37/#38; `Icon(DefaultIcons.Add, …)` is drawn in python-multiplatform's render test | +| Colour schemes | ⏳ planned | | `remember_saveable`, coroutine scopes | ⏳ planned | The full list is on the guide's [Status page](docs/guide/status.html). diff --git a/docs/SPEC.md b/docs/SPEC.md index ea673ae..432b606 100644 --- a/docs/SPEC.md +++ b/docs/SPEC.md @@ -14,21 +14,21 @@ Each item carries a status: A behaviour change starts here, then becomes a failing test, then code (`AGENTS.md` §5). -## 0. Test baseline (2026-10-03, after method keywords) +## 0. Test baseline (2026-10-03, after DefaultIcons) Run from a worktree with `python -m pytest tests -q -rs` (pytest 8, mypy 2.4, CPython 3.13), where `UI.ipynb` is absent and its one test skips: | Environment | Result | |---|---| -| No `PythonMultiplatform` checkout found | **116 passed, 87 skipped**, 128 subtests passed | -| python-multiplatform `develop` at `31c092f0` or later (property rows, #38; `describe_member`, #54; besides `add_member_resolver` and `describe(module, name)`) | **202 passed, 1 skipped**, 155 subtests passed | +| No `PythonMultiplatform` checkout found | **124 passed, 98 skipped**, 157 subtests passed | +| python-multiplatform `develop` at `31c092f0` or later (property rows, #38; `describe_member`, #54; besides `add_member_resolver` and `describe(module, name)`) | **221 passed, 1 skipped**, 184 subtests passed | | an older checkout, without `describe_member` (python-multiplatform #54) | the same, with 7 more skipped | | an older one, without `describe(module, name)` (python-multiplatform #36) | with 13 more skipped again | | an older one still, without `add_member_resolver` | with 5 more skipped again | Measured in a worktree, which has `.tmp/kotlin-stubs.zip` but no `UI.ipynb`. Without a checkout, the -86 tests that install the binder's layers through `tests/adapter.py` skip, plus the notebook test. +97 tests that install the binder's layers through `tests/adapter.py` skip, plus the notebook test. Against a binder without `describe(module, name)`, the 13 that check grouped constants (§7, S7.1) skip. Against a binder without `describe_member`, the 7 that check a method's keywords (S4.1) skip; the 2 that check the fallback (Kotlin keywords, names resolved) run. Against a binder older than `ba4c6f49`, the 5 that call a snake_case method on a proxy the @@ -36,7 +36,7 @@ binder returned skip as well, because that needs its member resolver (python-mul `TheBinderPath` tests (S5.4). `tests/test_typing.py` skips where mypy is not installed. A skip is not a pass. -Of the 116 that pass without a checkout, 48 check the type stubs and the wheel (S1.2); most of the +Of the 124 that pass without a checkout, 51 check the type stubs and the wheel (S1.2); most of the rest assert **absence** (a retired token, a deleted file, a docstring that exists). Those are listed in §9 and are not counted as features. @@ -104,7 +104,8 @@ and the name the interpreter resolves cannot drift. - a module that maps the same Kotlin package as an earlier one (`pythonx.compose.foundation.layout`) re-exports it (`from pythonx.compose.layout import *`), since at run time both names reach the same objects; `[aliases]` become re-exports too (`material3` exports `Column`, `Row`, `Spacer` - from `pythonx.compose.layout`); names a package defines itself (`runtime.Composable`) are + from `pythonx.compose.layout`; a name lent under another one is assigned its path in the + source's stub, `DefaultIcons = Icons.Default`, which upstream types as `Icons.Filled`); names a package defines itself (`runtime.Composable`) are carried over. - **How it is verified.** `tests/test_stubs.py` converts three fixtures: the fake host's declarations in the old and the current upstream format (and the current format with an object @@ -126,7 +127,7 @@ and the name the interpreter resolves cannot drift. - Many parameter and return types are `Any`: upstream emits `Any` for a class that shares its name with a function (`PaddingValues`, `TextStyle`, `Color`), for packages it does not stub, and for an object's own type (`Alignment.Center: Alignment`, python-multiplatform's object self-type); - `Icons.Default.Add` is not stubbed upstream (python-multiplatform #68); `Dp` is `float`; + `Icons.Default` is typed `Icons.Filled`, but each icon on it (`Add`) is `Any` (python-multiplatform #68); `Dp` is `float`; `Arrangement.HorizontalOrVertical` constants and `spaced_by` return `Any` (above). - The `pythonx.compose` root module maps `androidx.compose`, which has no stub, so its stub is empty. @@ -154,6 +155,21 @@ Current mapping: | `pythonx.compose.ui` (+ `.unit`, `.text`, `.graphics`) | `androidx.compose.ui` (+ same) | | `pythonx.compose.layout` | `androidx.compose.foundation.layout` | | `pythonx.compose.material3` | `androidx.compose.material3` | +| `pythonx.compose.material.icons` | `androidx.compose.material.icons` | + +**`[aliases]`** lends a module names from another mapped module, as data. Two forms, both under +`[aliases.""]` keyed by the source module: a list of names lent under the **same** +name (`"pythonx.compose.layout" = ["Column", "Row", "Spacer"]`), or a table `{ lent = "Path.To.Attr" }` +that lends the attribute path under a **different** name +(`"pythonx.compose.material.icons" = { DefaultIcons = "Icons.Default" }`, INTENT §5.7). The first +segment of a path is a name of the source module; each further one is an attribute read. A name with +no dot is resolved once and kept in the owner's namespace, as before. **A path with a dot is resolved +on every read and never kept**: `Icons.Default` is a property of an object, which the binder serves +live (a `STATIC_GETTER` is never cached, python-multiplatform `_adapt`), and the alias reads as the +binder does, so `from pythonx.compose.material3 import DefaultIcons` gives the Kotlin object +`Icons.Default` gives (a new proxy for the same Kotlin object on each read). `dir()` lists every +lent name. `tests/test_pythonx_map.py::TestAliasSection` checks both forms against the manifest; +`tests/test_chain.py::DefaultIconsAlias` checks them at run time. Caveat: `test_the_specification_resolves` reads `UI.ipynb` from the checkout it runs in. The notebook is git-ignored, so in a worktree or CI checkout it is absent, the expected set is empty, @@ -272,11 +288,22 @@ 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 — `planned` - -`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 +### S5.3 `DefaultIcons`, `Icon` and colour schemes — `partial` + +`DefaultIcons` is `implemented` against the fake host: `pythonx.compose.material.icons` +(`androidx.compose.material.icons`) serves `Icons`; `Icons.Default` resolves to `Icons.Filled` +and `Icons.Default.Add` is a top-level extension-property getter on `Icons.Filled` (a `GETTER` row, +python-multiplatform #37/#38, read on the proxy); `from pythonx.compose.material3 import DefaultIcons` +is `Icons.Default` by the manifest's `[aliases]` (§2), so `DefaultIcons.Add` is the `ImageVector` and +an unknown icon is an `AttributeError`. An icon is a **property read, written without parentheses**: +the notebook's `DefaultIcons.Add()` would call an `ImageVector`, which is not callable; INTENT §5.7 +says the intent is `DefaultIcons.Add`. The rows are shaped after python-multiplatform `31c092f0` +(`_PROPERTIES`, `_read_property`) and the ecosystem report for #37; no walked +`material-icons-core` row exists here, and `Icon(DefaultIcons.Add, ...)` is drawn only in +python-multiplatform's render test. Tests: `tests/test_chain.py::DefaultIconsAlias`; stubs: the +`material3` stub assigns `DefaultIcons = Icons.Default` (typed `Icons.Filled`; `Add` is `Any` until +python-multiplatform #68), checked by `tests/test_typing.py::test_default_icons_imports_from_material3`. `Icon` itself is a Material 3 composable, served by the §3 rule. +Still `planned`: 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). @@ -406,7 +433,7 @@ the binder lists no member that would win over these groups. |---|---|---| | `remember_saveable` | imported from `pythonx.compose.runtime`; state read/written with `getValue()` / `setValue()` | INTENT §5.1: `state(initial)` read and written through `.value` (S5.4, `partial`, #11; an `int` initial value is refused by the binder until python-multiplatform #69); keeping a value across recreation is not provided | | `DefaultCoroutineScope`, `MainCoroutineScope` | imported from `pythonx.compose.runtime` | INTENT §4.1, open | -| `DefaultIcons` | `DefaultIcons.Add()` | INTENT §5.7: `Icons.Default` by alias, once python-multiplatform #37 binds `material-icons-core` | +| `DefaultIcons` | `DefaultIcons.Add()` | INTENT §5.7, `implemented` as `DefaultIcons.Add`. The notebook's `Add()` is the spelling of its time; the current spelling is `Add`, a property read without parentheses, as for every constant (decided with the ecosystem lead; S5.3, `tests/test_chain.py::DefaultIconsAlias`, fake host) | | `modifier` | lower-case instance from `pythonx.compose.ui` | INTENT §5.4: not provided; written `Modifier` | | `color=0xFFFF0000` | ARGB integer for a colour | INTENT §5.5: not accepted; written `Color(0xFFFF0000)` | | `Spacer(start=..., top=...)` | spacing parameters | INTENT §5.6: not supported; written `Spacer(modifier=Modifier.padding(...))` | diff --git a/docs/guide/guide-composables.html b/docs/guide/guide-composables.html index 7d7278c..aafed8d 100644 --- a/docs/guide/guide-composables.html +++ b/docs/guide/guide-composables.html @@ -94,10 +94,10 @@

Spellings that changed바

What does not work yet아직 안 되는 것

    -
  • Icon and the colour-scheme factories cannot be called yet: nothing bound can produce an ImageVector until the binder walks material-icons-core (python-multiplatform #37; then DefaultIcons is Icons.Default), and the factories take 36 colour parameters.Icon 과 색 스킴 팩토리는 아직 호출할 수 없습니다: 바인더가 material-icons-core 를 읽기 전에는(python-multiplatform #37, 그 뒤 DefaultIcons 는 Icons.Default) 바인딩된 어떤 것도 ImageVector 를 만들 수 없고, 팩토리는 색 매개변수 36 개를 받습니다.
  • +
  • The colour-scheme factories cannot be called yet: they take 36 colour parameters. DefaultIcons is Icons.Default, an icon is a value read without parentheses — Icon(DefaultIcons.Add, content_description=None), not the notebook's DefaultIcons.Add() — and it is tested here against a fake host only; the real draw is in python-multiplatform's render test.색 스킴 팩토리는 색 매개변수를 36 개 받아 아직 호출할 수 없습니다. DefaultIcons 는 Icons.Default 이고, 아이콘은 괄호 없이 읽는 값입니다 — 노트북의 DefaultIcons.Add() 가 아니라 Icon(DefaultIcons.Add, content_description=None). 여기서는 가짜 호스트로만 테스트되며, 실제 그리기는 python-multiplatform 의 렌더 테스트에 있습니다.
  • A declared app root and Pythonic state — redefining a screen replaces it, with no update call — are planned (issue #11).선언형 앱 루트와 파이썬다운 상태 — 화면을 다시 정의하면 교체되고, 갱신 호출은 없음 — 는 계획 단계입니다(이슈 #11).
  • TextField input-method (IME) handling is pending (issue #10).TextField 의 입력기(IME) 처리는 대기 중입니다(이슈 #10).
  • -
  • remember_saveable, DefaultIcons and the coroutine scopes the notebook imports are planned.노트북이 import 하는 remember_saveable, DefaultIcons, 코루틴 스코프는 계획 단계입니다.
  • +
  • remember_saveable and the coroutine scopes the notebook imports are planned.노트북이 import 하는 remember_saveable, 코루틴 스코프는 계획 단계입니다.
diff --git a/docs/guide/status.html b/docs/guide/status.html index 73d0e18..2e2e6ce 100644 --- a/docs/guide/status.html +++ b/docs/guide/status.html @@ -34,7 +34,7 @@

Implemented means code in this repository and a passing test that exercises it. Tests that only assert an absence are not counted.

구현은 이 저장소의 코드와 그것을 실행하는 통과 테스트가 함께 있다는 뜻입니다. 부재만 확인하는 테스트는 세지 않습니다.

- +
State상태Item항목
implemented구현Mapping manifest pythonx/compose/pythonx-map.toml — inside the package, ships in the wheel매핑 매니페스트 pythonx/compose/pythonx-map.toml — 패키지 안에 있으며 wheel 에 포함
implemented구현@Composable identity decorator@Composable 항등 데코레이터
implemented구현pythonx as a real on-disk package re-exporting androidx.compose.* by one rule — names, keywords, signatures, Dp allowlistandroidx.compose.* 를 규칙 하나로 재노출하는 실제 디스크 패키지 pythonx — 이름, 키워드, 시그니처, Dp 허용 목록
implemented구현Modifier chains with snake_case methods, overload dispatch, Dp as a numbersnake_case 메서드를 쓰는 Modifier 체인, 오버로드 디스패치, 숫자 Dp
implemented구현Column, Row, Spacer importable from material3 as well as layout (manifest [aliases])layout 뿐 아니라 material3 에서도 import 되는 Column, Row, Spacer (매니페스트 [aliases])
implemented구현Type stubs (.pyi) generated from real Compose 1.11.1 by the runtime's naming rule, with py.typed, checked with mypy (#12); many types are still Any런타임과 같은 이름 규칙으로 실제 Compose 1.11.1 에서 생성한 타입 스텁(.pyi)과 py.typed, mypy 로 검사(#12); 아직 많은 타입이 Any 입니다
implemented구현Snake-case names, keywords and signatures — modules and methods; a method's keywords need python-multiplatform's describe_member, and Kotlin's own spelling still works at run timesnake_case 이름·키워드·시그니처 — 모듈과 메서드; 메서드 키워드에는 python-multiplatform 의 describe_member 가 필요하고, Kotlin 이름도 실행 시에는 그대로 통합니다
partial부분The empty Modifier — Modifier.padding(16) from the class needs an app-supplied factory against real Compose빈 Modifier — 클래스에서 시작하는 Modifier.padding(16) 은 실제 Compose 에서 앱이 제공하는 팩토리가 필요
implemented구현Alignment / Arrangement — Alignment.Center, Arrangement.End, Arrangement.spaced_by(8), and the grouped Alignment.Horizontal.End beside Alignment.EndAlignment / Arrangement — Alignment.Center, Arrangement.End, Arrangement.spaced_by(8), 그리고 Alignment.End 와 나란히 묶음 표기 Alignment.Horizontal.End
partial부분Material 3 widgets — re-exported by rule; render proofs per widget pending (#9)Material 3 위젯 — 규칙으로 재노출됨; 위젯별 렌더 증거 대기(#9)
partial부분Distribution as pythonx-compose — the wheel carries the manifest, the re-export rule, the type stubs and py.typedpythonx-compose 배포 — wheel 에 매니페스트, 재노출 규칙, 타입 스텁, py.typed 포함
partial부분A declared app root (@app) and Pythonic state (state), with no update call — binder path tested against a fake host shaped after python-multiplatform #38; real Compose is the E2E module (#11, #19)갱신 호출 없는 선언형 앱 루트(@app)와 파이썬다운 상태(state) — 바인더 경로는 python-multiplatform #38 모양의 가짜 호스트로 테스트됨, 실제 Compose 는 E2E 모듈(#11, #19)
planned계획TextField input-method (IME) handling (#10)TextField 입력기(IME) 처리(#10)
planned계획Icon, DefaultIcons (python-multiplatform #37), colour schemesIcon, DefaultIcons (python-multiplatform #37), 색 스킴
planned계획remember_saveable, coroutine scopesremember_saveable, 코루틴 스코프
implemented구현Mapping manifest pythonx/compose/pythonx-map.toml — inside the package, ships in the wheel매핑 매니페스트 pythonx/compose/pythonx-map.toml — 패키지 안에 있으며 wheel 에 포함
implemented구현@Composable identity decorator@Composable 항등 데코레이터
implemented구현pythonx as a real on-disk package re-exporting androidx.compose.* by one rule — names, keywords, signatures, Dp allowlistandroidx.compose.* 를 규칙 하나로 재노출하는 실제 디스크 패키지 pythonx — 이름, 키워드, 시그니처, Dp 허용 목록
implemented구현Modifier chains with snake_case methods, overload dispatch, Dp as a numbersnake_case 메서드를 쓰는 Modifier 체인, 오버로드 디스패치, 숫자 Dp
implemented구현Column, Row, Spacer importable from material3 as well as layout (manifest [aliases])layout 뿐 아니라 material3 에서도 import 되는 Column, Row, Spacer (매니페스트 [aliases])
implemented구현Type stubs (.pyi) generated from real Compose 1.11.1 by the runtime's naming rule, with py.typed, checked with mypy (#12); many types are still Any런타임과 같은 이름 규칙으로 실제 Compose 1.11.1 에서 생성한 타입 스텁(.pyi)과 py.typed, mypy 로 검사(#12); 아직 많은 타입이 Any 입니다
implemented구현Snake-case names, keywords and signatures — modules and methods; a method's keywords need python-multiplatform's describe_member, and Kotlin's own spelling still works at run timesnake_case 이름·키워드·시그니처 — 모듈과 메서드; 메서드 키워드에는 python-multiplatform 의 describe_member 가 필요하고, Kotlin 이름도 실행 시에는 그대로 통합니다
partial부분The empty Modifier — Modifier.padding(16) from the class needs an app-supplied factory against real Compose빈 Modifier — 클래스에서 시작하는 Modifier.padding(16) 은 실제 Compose 에서 앱이 제공하는 팩토리가 필요
implemented구현Alignment / Arrangement — Alignment.Center, Arrangement.End, Arrangement.spaced_by(8), and the grouped Alignment.Horizontal.End beside Alignment.EndAlignment / Arrangement — Alignment.Center, Arrangement.End, Arrangement.spaced_by(8), 그리고 Alignment.End 와 나란히 묶음 표기 Alignment.Horizontal.End
partial부분Material 3 widgets — re-exported by rule; render proofs per widget pending (#9)Material 3 위젯 — 규칙으로 재노출됨; 위젯별 렌더 증거 대기(#9)
partial부분Distribution as pythonx-compose — the wheel carries the manifest, the re-export rule, the type stubs and py.typedpythonx-compose 배포 — wheel 에 매니페스트, 재노출 규칙, 타입 스텁, py.typed 포함
partial부분A declared app root (@app) and Pythonic state (state), with no update call — binder path tested against a fake host shaped after python-multiplatform #38; real Compose is the E2E module (#11, #19)갱신 호출 없는 선언형 앱 루트(@app)와 파이썬다운 상태(state) — 바인더 경로는 python-multiplatform #38 모양의 가짜 호스트로 테스트됨, 실제 Compose 는 E2E 모듈(#11, #19)
partial부분DefaultIcons is Icons.Default, written DefaultIcons.Add — tested against a fake host shaped after python-multiplatform #37/#38; the real draw is in python-multiplatform's render testDefaultIcons 는 Icons.Default 이며 DefaultIcons.Add 로 씁니다 — python-multiplatform #37/#38 모양의 가짜 호스트로 테스트됨; 실제 그리기는 python-multiplatform 의 렌더 테스트에 있음
planned계획TextField input-method (IME) handling (#10)TextField 입력기(IME) 처리(#10)
planned계획Colour schemes (36 colour parameters)색 스킴 (색 매개변수 36 개)
planned계획remember_saveable, coroutine scopesremember_saveable, 코루틴 스코프

Test baseline: 116 passed, 87 skipped without a python-multiplatform checkout; 202 passed, 1 skipped with a current one. The one skip with a current checkout reads the maintainer's UI.ipynb.

테스트 기준선: python-multiplatform 체크아웃이 없으면 116 passed, 87 skipped, 최신 체크아웃이면 202 passed, 1 skipped. 최신 체크아웃에서 건너뛰는 1 개는 메인테이너의 UI.ipynb 를 읽는 테스트입니다.

diff --git a/docs/locale/README_ko.md b/docs/locale/README_ko.md index d894204..4470274 100644 --- a/docs/locale/README_ko.md +++ b/docs/locale/README_ko.md @@ -157,7 +157,8 @@ pip 패키지 **`pythonx-compose`**(파이썬 3.11 이상)로 배포되며, impo | 배포 (`pythonx-compose`) | 🟡 부분 — wheel 에 매니페스트, 재노출 규칙, 스텁, `py.typed` 포함 | | 갱신 호출 없는 선언형 앱 루트(`@app`)와 파이썬다운 상태(`state`) | 🟡 부분 — 바인더 경로는 python-multiplatform #38 모양의 가짜 호스트로 테스트됨, 실제 Compose 는 E2E 모듈(#11, #19), 바인더가 `Any?` 칸의 int 를 거부해 `state(1)` 은 거부됨 | | `TextField` 입력기(IME) 처리 | ⏳ 계획(#10) | -| `Icon`, `DefaultIcons`, 색 스킴 | ⏳ 계획(python-multiplatform #37) | +| `DefaultIcons`(`Icons.Default`), `DefaultIcons.Add` 로 씀 | 🟡 부분 — python-multiplatform #37/#38 모양의 가짜 호스트로 테스트됨; `Icon(DefaultIcons.Add, …)` 의 실제 그리기는 python-multiplatform 의 렌더 테스트에 있음 | +| 색 스킴 | ⏳ 계획 | | `remember_saveable`, 코루틴 스코프 | ⏳ 계획 | 전체 목록은 가이드의 [현황 페이지](../guide/status.html)에 있습니다. diff --git a/pythonx/compose/_reexport.py b/pythonx/compose/_reexport.py index 81f346b..a38afb7 100644 --- a/pythonx/compose/_reexport.py +++ b/pythonx/compose/_reexport.py @@ -36,7 +36,10 @@ A module may also answer for names the manifest's `[aliases]` section lends it from another mapped module (`material3` answers for `Column`, `Row`, `Spacer` from `layout`, as the notebook imports -them); the object is the same one either way. +them); the object is the same one either way. An alias may also lend a name under a different one, +through an attribute path (`DefaultIcons` is `Icons.Default` of `pythonx.compose.material.icons`, +INTENT section 5.7); a path with attribute steps is read afresh on every access, as the binder +serves a live property. Nothing here names a Kotlin declaration. Names defined in the package's own `__init__.py` (such as `runtime.Composable`) are ordinary module attributes and win, because `__getattr__` only runs for a @@ -434,14 +437,35 @@ def __repr__(self): def _aliases(module_name: str) -> dict: - """Name -> the `pythonx.compose` module it is borrowed from, per the manifest's `[aliases]`.""" + """Name -> `(source module, attribute path in it)`, per the manifest's `[aliases]`. + + An entry under a source module is a list of names (lent under the same name, path = the name) or + a table `{ lent = "Path.To.Attr" }` (a different name, through an attribute path). + """ borrowed = {} - for source, names in manifest().get("aliases", {}).get(module_name, {}).items(): - for name in names: - borrowed[name] = source + for source, lent in manifest().get("aliases", {}).get(module_name, {}).items(): + pairs = ((name, name) for name in lent) if isinstance(lent, list) else lent.items() + for name, path in pairs: + borrowed[name] = (source, path) return borrowed +def _borrow(module_name: str, name: str, source: str, path: str): + """The value of the alias [name]: [path] read in [source]. + + A bare name is resolved once and kept in the owner's namespace. A path with attribute steps is + read on every access and not kept, because what it ends in may be a live property -- the binder + serves `Icons.Default` afresh on every read and this layer does not freeze it either. + """ + head, *rest = path.split(".") + value = getattr(importlib.import_module(source), head) + for step in rest: + value = getattr(value, step) + if not rest: + setattr(sys.modules[module_name], name, value) + return value + + def reexport(module_name: str): """The module-level `__getattr__` and `__dir__` for the mapped package `module_name`. @@ -457,11 +481,9 @@ def __getattr__(name): # the attribute before it imports a submodule, and only an AttributeError lets it # fall back -- so this has to answer before anything that needs the binder. return importlib.import_module(module_name + "." + name) - source = _aliases(module_name).get(name) - if source is not None: - value = getattr(importlib.import_module(source), name) - setattr(sys.modules[module_name], name, value) - return value + borrowed = _aliases(module_name).get(name) + if borrowed is not None: + return _borrow(module_name, name, *borrowed) try: kotlin = kotlin_module(module_name) except ImportError as missing: diff --git a/pythonx/compose/material/__init__.py b/pythonx/compose/material/__init__.py new file mode 100644 index 0000000..41e5ace --- /dev/null +++ b/pythonx/compose/material/__init__.py @@ -0,0 +1,8 @@ +"""`pythonx.compose.material` -- the Pythonic view of `androidx.compose.material` (see `pythonx/compose/_reexport.py`). + +Material 2's own composables are not bound; this package is here for `material.icons`. +""" + +from pythonx.compose._reexport import reexport + +__getattr__, __dir__ = reexport(__name__) diff --git a/pythonx/compose/material/__init__.pyi b/pythonx/compose/material/__init__.pyi new file mode 100644 index 0000000..02ce842 --- /dev/null +++ b/pythonx/compose/material/__init__.pyi @@ -0,0 +1 @@ +# GENERATED by tools/gen_stubs.py from python-multiplatform's Kotlin-named stubs (artifact kotlin-stubs, workflow run 37098191598, commit fa2558e3, Compose 1.11.1). Do not edit. diff --git a/pythonx/compose/material/icons/__init__.py b/pythonx/compose/material/icons/__init__.py new file mode 100644 index 0000000..f02a782 --- /dev/null +++ b/pythonx/compose/material/icons/__init__.py @@ -0,0 +1,9 @@ +"""`pythonx.compose.material.icons` -- the Pythonic view of `androidx.compose.material.icons` (see `pythonx/compose/_reexport.py`). + +`Icons.Default.Add` is served by the rule; `material3` lends `Icons.Default` as `DefaultIcons` +(`[aliases]` in `pythonx-map.toml`, INTENT section 5.7). +""" + +from pythonx.compose._reexport import reexport + +__getattr__, __dir__ = reexport(__name__) diff --git a/pythonx/compose/material/icons/__init__.pyi b/pythonx/compose/material/icons/__init__.pyi new file mode 100644 index 0000000..49001bc --- /dev/null +++ b/pythonx/compose/material/icons/__init__.pyi @@ -0,0 +1,1158 @@ +# GENERATED by tools/gen_stubs.py from python-multiplatform's Kotlin-named stubs (artifact kotlin-stubs, workflow run 37098191598, commit fa2558e3, Compose 1.11.1). Do not edit. +import typing as _t + +def material_icon(name: str, auto_mirror: bool = ..., *, block: _t.Callable[[_t.Any], _t.Any]) -> _t.Any: + """Kotlin: androidx.compose.material.icons.materialIcon(name: kotlin.String, autoMirror: kotlin.Boolean, block: kotlin.Function1): androidx.compose.ui.graphics.vector.ImageVector""" + ... + +def material_path(receiver: _t.Any, /, fill_alpha: float = ..., stroke_alpha: float = ..., path_fill_type: _t.Any = ..., *, path_builder: _t.Callable[[_t.Any], None]) -> _t.Any: + """Kotlin: androidx.compose.ui.graphics.vector.ImageVector.Builder.materialPath(fillAlpha: kotlin.Float, strokeAlpha: kotlin.Float, pathFillType: androidx.compose.ui.graphics.PathFillType, pathBuilder: kotlin.Function1): androidx.compose.ui.graphics.vector.ImageVector.Builder""" + ... + +class Icons: + """Kotlin: androidx.compose.material.icons.Icons""" + class AutoMirrored: + """Kotlin: container of nested classes""" + class Filled: + """Kotlin: androidx.compose.material.icons.Icons.AutoMirrored.Filled""" + @property + def ArrowBack(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.automirrored.filled.ArrowBack (androidx.compose.material.icons.Icons.AutoMirrored.Filled.ArrowBack: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def ArrowForward(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.automirrored.filled.ArrowForward (androidx.compose.material.icons.Icons.AutoMirrored.Filled.ArrowForward: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def ExitToApp(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.automirrored.filled.ExitToApp (androidx.compose.material.icons.Icons.AutoMirrored.Filled.ExitToApp: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def KeyboardArrowLeft(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.automirrored.filled.KeyboardArrowLeft (androidx.compose.material.icons.Icons.AutoMirrored.Filled.KeyboardArrowLeft: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def KeyboardArrowRight(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.automirrored.filled.KeyboardArrowRight (androidx.compose.material.icons.Icons.AutoMirrored.Filled.KeyboardArrowRight: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def List(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.automirrored.filled.List (androidx.compose.material.icons.Icons.AutoMirrored.Filled.List: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Send(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.automirrored.filled.Send (androidx.compose.material.icons.Icons.AutoMirrored.Filled.Send: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + class Outlined: + """Kotlin: androidx.compose.material.icons.Icons.AutoMirrored.Outlined""" + @property + def ArrowBack(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.automirrored.outlined.ArrowBack (androidx.compose.material.icons.Icons.AutoMirrored.Outlined.ArrowBack: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def ArrowForward(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.automirrored.outlined.ArrowForward (androidx.compose.material.icons.Icons.AutoMirrored.Outlined.ArrowForward: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def ExitToApp(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.automirrored.outlined.ExitToApp (androidx.compose.material.icons.Icons.AutoMirrored.Outlined.ExitToApp: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def KeyboardArrowLeft(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.automirrored.outlined.KeyboardArrowLeft (androidx.compose.material.icons.Icons.AutoMirrored.Outlined.KeyboardArrowLeft: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def KeyboardArrowRight(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.automirrored.outlined.KeyboardArrowRight (androidx.compose.material.icons.Icons.AutoMirrored.Outlined.KeyboardArrowRight: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def List(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.automirrored.outlined.List (androidx.compose.material.icons.Icons.AutoMirrored.Outlined.List: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Send(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.automirrored.outlined.Send (androidx.compose.material.icons.Icons.AutoMirrored.Outlined.Send: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + class Rounded: + """Kotlin: androidx.compose.material.icons.Icons.AutoMirrored.Rounded""" + @property + def ArrowBack(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.automirrored.rounded.ArrowBack (androidx.compose.material.icons.Icons.AutoMirrored.Rounded.ArrowBack: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def ArrowForward(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.automirrored.rounded.ArrowForward (androidx.compose.material.icons.Icons.AutoMirrored.Rounded.ArrowForward: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def ExitToApp(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.automirrored.rounded.ExitToApp (androidx.compose.material.icons.Icons.AutoMirrored.Rounded.ExitToApp: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def KeyboardArrowLeft(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.automirrored.rounded.KeyboardArrowLeft (androidx.compose.material.icons.Icons.AutoMirrored.Rounded.KeyboardArrowLeft: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def KeyboardArrowRight(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.automirrored.rounded.KeyboardArrowRight (androidx.compose.material.icons.Icons.AutoMirrored.Rounded.KeyboardArrowRight: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def List(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.automirrored.rounded.List (androidx.compose.material.icons.Icons.AutoMirrored.Rounded.List: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Send(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.automirrored.rounded.Send (androidx.compose.material.icons.Icons.AutoMirrored.Rounded.Send: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + class Sharp: + """Kotlin: androidx.compose.material.icons.Icons.AutoMirrored.Sharp""" + @property + def ArrowBack(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.automirrored.sharp.ArrowBack (androidx.compose.material.icons.Icons.AutoMirrored.Sharp.ArrowBack: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def ArrowForward(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.automirrored.sharp.ArrowForward (androidx.compose.material.icons.Icons.AutoMirrored.Sharp.ArrowForward: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def ExitToApp(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.automirrored.sharp.ExitToApp (androidx.compose.material.icons.Icons.AutoMirrored.Sharp.ExitToApp: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def KeyboardArrowLeft(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.automirrored.sharp.KeyboardArrowLeft (androidx.compose.material.icons.Icons.AutoMirrored.Sharp.KeyboardArrowLeft: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def KeyboardArrowRight(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.automirrored.sharp.KeyboardArrowRight (androidx.compose.material.icons.Icons.AutoMirrored.Sharp.KeyboardArrowRight: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def List(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.automirrored.sharp.List (androidx.compose.material.icons.Icons.AutoMirrored.Sharp.List: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Send(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.automirrored.sharp.Send (androidx.compose.material.icons.Icons.AutoMirrored.Sharp.Send: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + class TwoTone: + """Kotlin: androidx.compose.material.icons.Icons.AutoMirrored.TwoTone""" + @property + def ArrowBack(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.automirrored.twotone.ArrowBack (androidx.compose.material.icons.Icons.AutoMirrored.TwoTone.ArrowBack: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def ArrowForward(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.automirrored.twotone.ArrowForward (androidx.compose.material.icons.Icons.AutoMirrored.TwoTone.ArrowForward: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def ExitToApp(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.automirrored.twotone.ExitToApp (androidx.compose.material.icons.Icons.AutoMirrored.TwoTone.ExitToApp: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def KeyboardArrowLeft(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.automirrored.twotone.KeyboardArrowLeft (androidx.compose.material.icons.Icons.AutoMirrored.TwoTone.KeyboardArrowLeft: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def KeyboardArrowRight(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.automirrored.twotone.KeyboardArrowRight (androidx.compose.material.icons.Icons.AutoMirrored.TwoTone.KeyboardArrowRight: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def List(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.automirrored.twotone.List (androidx.compose.material.icons.Icons.AutoMirrored.TwoTone.List: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Send(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.automirrored.twotone.Send (androidx.compose.material.icons.Icons.AutoMirrored.TwoTone.Send: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + class Filled: + """Kotlin: androidx.compose.material.icons.Icons.Filled""" + @property + def AccountBox(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.filled.AccountBox (androidx.compose.material.icons.Icons.Filled.AccountBox: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def AccountCircle(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.filled.AccountCircle (androidx.compose.material.icons.Icons.Filled.AccountCircle: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Add(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.filled.Add (androidx.compose.material.icons.Icons.Filled.Add: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def AddCircle(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.filled.AddCircle (androidx.compose.material.icons.Icons.Filled.AddCircle: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def ArrowBack(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.filled.ArrowBack (androidx.compose.material.icons.Icons.Filled.ArrowBack: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def ArrowDropDown(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.filled.ArrowDropDown (androidx.compose.material.icons.Icons.Filled.ArrowDropDown: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def ArrowForward(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.filled.ArrowForward (androidx.compose.material.icons.Icons.Filled.ArrowForward: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Build(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.filled.Build (androidx.compose.material.icons.Icons.Filled.Build: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Call(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.filled.Call (androidx.compose.material.icons.Icons.Filled.Call: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Check(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.filled.Check (androidx.compose.material.icons.Icons.Filled.Check: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def CheckCircle(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.filled.CheckCircle (androidx.compose.material.icons.Icons.Filled.CheckCircle: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Clear(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.filled.Clear (androidx.compose.material.icons.Icons.Filled.Clear: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Close(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.filled.Close (androidx.compose.material.icons.Icons.Filled.Close: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Create(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.filled.Create (androidx.compose.material.icons.Icons.Filled.Create: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def DateRange(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.filled.DateRange (androidx.compose.material.icons.Icons.Filled.DateRange: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Delete(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.filled.Delete (androidx.compose.material.icons.Icons.Filled.Delete: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Done(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.filled.Done (androidx.compose.material.icons.Icons.Filled.Done: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Edit(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.filled.Edit (androidx.compose.material.icons.Icons.Filled.Edit: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Email(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.filled.Email (androidx.compose.material.icons.Icons.Filled.Email: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def ExitToApp(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.filled.ExitToApp (androidx.compose.material.icons.Icons.Filled.ExitToApp: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Face(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.filled.Face (androidx.compose.material.icons.Icons.Filled.Face: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Favorite(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.filled.Favorite (androidx.compose.material.icons.Icons.Filled.Favorite: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def FavoriteBorder(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.filled.FavoriteBorder (androidx.compose.material.icons.Icons.Filled.FavoriteBorder: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Home(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.filled.Home (androidx.compose.material.icons.Icons.Filled.Home: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Info(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.filled.Info (androidx.compose.material.icons.Icons.Filled.Info: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def KeyboardArrowDown(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.filled.KeyboardArrowDown (androidx.compose.material.icons.Icons.Filled.KeyboardArrowDown: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def KeyboardArrowLeft(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.filled.KeyboardArrowLeft (androidx.compose.material.icons.Icons.Filled.KeyboardArrowLeft: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def KeyboardArrowRight(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.filled.KeyboardArrowRight (androidx.compose.material.icons.Icons.Filled.KeyboardArrowRight: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def KeyboardArrowUp(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.filled.KeyboardArrowUp (androidx.compose.material.icons.Icons.Filled.KeyboardArrowUp: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def List(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.filled.List (androidx.compose.material.icons.Icons.Filled.List: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def LocationOn(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.filled.LocationOn (androidx.compose.material.icons.Icons.Filled.LocationOn: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Lock(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.filled.Lock (androidx.compose.material.icons.Icons.Filled.Lock: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def MailOutline(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.filled.MailOutline (androidx.compose.material.icons.Icons.Filled.MailOutline: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Menu(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.filled.Menu (androidx.compose.material.icons.Icons.Filled.Menu: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def MoreVert(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.filled.MoreVert (androidx.compose.material.icons.Icons.Filled.MoreVert: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Notifications(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.filled.Notifications (androidx.compose.material.icons.Icons.Filled.Notifications: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Person(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.filled.Person (androidx.compose.material.icons.Icons.Filled.Person: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Phone(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.filled.Phone (androidx.compose.material.icons.Icons.Filled.Phone: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Place(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.filled.Place (androidx.compose.material.icons.Icons.Filled.Place: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def PlayArrow(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.filled.PlayArrow (androidx.compose.material.icons.Icons.Filled.PlayArrow: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Refresh(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.filled.Refresh (androidx.compose.material.icons.Icons.Filled.Refresh: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Search(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.filled.Search (androidx.compose.material.icons.Icons.Filled.Search: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Send(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.filled.Send (androidx.compose.material.icons.Icons.Filled.Send: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Settings(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.filled.Settings (androidx.compose.material.icons.Icons.Filled.Settings: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Share(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.filled.Share (androidx.compose.material.icons.Icons.Filled.Share: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def ShoppingCart(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.filled.ShoppingCart (androidx.compose.material.icons.Icons.Filled.ShoppingCart: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Star(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.filled.Star (androidx.compose.material.icons.Icons.Filled.Star: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def ThumbUp(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.filled.ThumbUp (androidx.compose.material.icons.Icons.Filled.ThumbUp: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Warning(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.filled.Warning (androidx.compose.material.icons.Icons.Filled.Warning: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + Default: _t.ClassVar[Icons.Filled] + class Outlined: + """Kotlin: androidx.compose.material.icons.Icons.Outlined""" + @property + def AccountBox(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.outlined.AccountBox (androidx.compose.material.icons.Icons.Outlined.AccountBox: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def AccountCircle(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.outlined.AccountCircle (androidx.compose.material.icons.Icons.Outlined.AccountCircle: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Add(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.outlined.Add (androidx.compose.material.icons.Icons.Outlined.Add: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def AddCircle(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.outlined.AddCircle (androidx.compose.material.icons.Icons.Outlined.AddCircle: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def ArrowBack(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.outlined.ArrowBack (androidx.compose.material.icons.Icons.Outlined.ArrowBack: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def ArrowDropDown(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.outlined.ArrowDropDown (androidx.compose.material.icons.Icons.Outlined.ArrowDropDown: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def ArrowForward(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.outlined.ArrowForward (androidx.compose.material.icons.Icons.Outlined.ArrowForward: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Build(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.outlined.Build (androidx.compose.material.icons.Icons.Outlined.Build: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Call(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.outlined.Call (androidx.compose.material.icons.Icons.Outlined.Call: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Check(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.outlined.Check (androidx.compose.material.icons.Icons.Outlined.Check: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def CheckCircle(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.outlined.CheckCircle (androidx.compose.material.icons.Icons.Outlined.CheckCircle: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Clear(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.outlined.Clear (androidx.compose.material.icons.Icons.Outlined.Clear: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Close(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.outlined.Close (androidx.compose.material.icons.Icons.Outlined.Close: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Create(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.outlined.Create (androidx.compose.material.icons.Icons.Outlined.Create: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def DateRange(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.outlined.DateRange (androidx.compose.material.icons.Icons.Outlined.DateRange: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Delete(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.outlined.Delete (androidx.compose.material.icons.Icons.Outlined.Delete: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Done(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.outlined.Done (androidx.compose.material.icons.Icons.Outlined.Done: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Edit(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.outlined.Edit (androidx.compose.material.icons.Icons.Outlined.Edit: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Email(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.outlined.Email (androidx.compose.material.icons.Icons.Outlined.Email: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def ExitToApp(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.outlined.ExitToApp (androidx.compose.material.icons.Icons.Outlined.ExitToApp: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Face(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.outlined.Face (androidx.compose.material.icons.Icons.Outlined.Face: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Favorite(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.outlined.Favorite (androidx.compose.material.icons.Icons.Outlined.Favorite: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def FavoriteBorder(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.outlined.FavoriteBorder (androidx.compose.material.icons.Icons.Outlined.FavoriteBorder: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Home(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.outlined.Home (androidx.compose.material.icons.Icons.Outlined.Home: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Info(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.outlined.Info (androidx.compose.material.icons.Icons.Outlined.Info: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def KeyboardArrowDown(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.outlined.KeyboardArrowDown (androidx.compose.material.icons.Icons.Outlined.KeyboardArrowDown: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def KeyboardArrowLeft(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.outlined.KeyboardArrowLeft (androidx.compose.material.icons.Icons.Outlined.KeyboardArrowLeft: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def KeyboardArrowRight(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.outlined.KeyboardArrowRight (androidx.compose.material.icons.Icons.Outlined.KeyboardArrowRight: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def KeyboardArrowUp(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.outlined.KeyboardArrowUp (androidx.compose.material.icons.Icons.Outlined.KeyboardArrowUp: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def List(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.outlined.List (androidx.compose.material.icons.Icons.Outlined.List: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def LocationOn(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.outlined.LocationOn (androidx.compose.material.icons.Icons.Outlined.LocationOn: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Lock(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.outlined.Lock (androidx.compose.material.icons.Icons.Outlined.Lock: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def MailOutline(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.outlined.MailOutline (androidx.compose.material.icons.Icons.Outlined.MailOutline: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Menu(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.outlined.Menu (androidx.compose.material.icons.Icons.Outlined.Menu: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def MoreVert(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.outlined.MoreVert (androidx.compose.material.icons.Icons.Outlined.MoreVert: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Notifications(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.outlined.Notifications (androidx.compose.material.icons.Icons.Outlined.Notifications: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Person(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.outlined.Person (androidx.compose.material.icons.Icons.Outlined.Person: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Phone(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.outlined.Phone (androidx.compose.material.icons.Icons.Outlined.Phone: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Place(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.outlined.Place (androidx.compose.material.icons.Icons.Outlined.Place: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def PlayArrow(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.outlined.PlayArrow (androidx.compose.material.icons.Icons.Outlined.PlayArrow: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Refresh(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.outlined.Refresh (androidx.compose.material.icons.Icons.Outlined.Refresh: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Search(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.outlined.Search (androidx.compose.material.icons.Icons.Outlined.Search: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Send(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.outlined.Send (androidx.compose.material.icons.Icons.Outlined.Send: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Settings(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.outlined.Settings (androidx.compose.material.icons.Icons.Outlined.Settings: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Share(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.outlined.Share (androidx.compose.material.icons.Icons.Outlined.Share: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def ShoppingCart(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.outlined.ShoppingCart (androidx.compose.material.icons.Icons.Outlined.ShoppingCart: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Star(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.outlined.Star (androidx.compose.material.icons.Icons.Outlined.Star: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def ThumbUp(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.outlined.ThumbUp (androidx.compose.material.icons.Icons.Outlined.ThumbUp: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Warning(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.outlined.Warning (androidx.compose.material.icons.Icons.Outlined.Warning: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + class Rounded: + """Kotlin: androidx.compose.material.icons.Icons.Rounded""" + @property + def AccountBox(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.rounded.AccountBox (androidx.compose.material.icons.Icons.Rounded.AccountBox: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def AccountCircle(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.rounded.AccountCircle (androidx.compose.material.icons.Icons.Rounded.AccountCircle: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Add(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.rounded.Add (androidx.compose.material.icons.Icons.Rounded.Add: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def AddCircle(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.rounded.AddCircle (androidx.compose.material.icons.Icons.Rounded.AddCircle: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def ArrowBack(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.rounded.ArrowBack (androidx.compose.material.icons.Icons.Rounded.ArrowBack: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def ArrowDropDown(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.rounded.ArrowDropDown (androidx.compose.material.icons.Icons.Rounded.ArrowDropDown: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def ArrowForward(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.rounded.ArrowForward (androidx.compose.material.icons.Icons.Rounded.ArrowForward: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Build(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.rounded.Build (androidx.compose.material.icons.Icons.Rounded.Build: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Call(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.rounded.Call (androidx.compose.material.icons.Icons.Rounded.Call: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Check(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.rounded.Check (androidx.compose.material.icons.Icons.Rounded.Check: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def CheckCircle(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.rounded.CheckCircle (androidx.compose.material.icons.Icons.Rounded.CheckCircle: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Clear(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.rounded.Clear (androidx.compose.material.icons.Icons.Rounded.Clear: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Close(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.rounded.Close (androidx.compose.material.icons.Icons.Rounded.Close: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Create(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.rounded.Create (androidx.compose.material.icons.Icons.Rounded.Create: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def DateRange(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.rounded.DateRange (androidx.compose.material.icons.Icons.Rounded.DateRange: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Delete(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.rounded.Delete (androidx.compose.material.icons.Icons.Rounded.Delete: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Done(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.rounded.Done (androidx.compose.material.icons.Icons.Rounded.Done: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Edit(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.rounded.Edit (androidx.compose.material.icons.Icons.Rounded.Edit: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Email(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.rounded.Email (androidx.compose.material.icons.Icons.Rounded.Email: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def ExitToApp(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.rounded.ExitToApp (androidx.compose.material.icons.Icons.Rounded.ExitToApp: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Face(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.rounded.Face (androidx.compose.material.icons.Icons.Rounded.Face: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Favorite(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.rounded.Favorite (androidx.compose.material.icons.Icons.Rounded.Favorite: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def FavoriteBorder(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.rounded.FavoriteBorder (androidx.compose.material.icons.Icons.Rounded.FavoriteBorder: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Home(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.rounded.Home (androidx.compose.material.icons.Icons.Rounded.Home: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Info(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.rounded.Info (androidx.compose.material.icons.Icons.Rounded.Info: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def KeyboardArrowDown(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.rounded.KeyboardArrowDown (androidx.compose.material.icons.Icons.Rounded.KeyboardArrowDown: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def KeyboardArrowLeft(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.rounded.KeyboardArrowLeft (androidx.compose.material.icons.Icons.Rounded.KeyboardArrowLeft: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def KeyboardArrowRight(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.rounded.KeyboardArrowRight (androidx.compose.material.icons.Icons.Rounded.KeyboardArrowRight: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def KeyboardArrowUp(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.rounded.KeyboardArrowUp (androidx.compose.material.icons.Icons.Rounded.KeyboardArrowUp: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def List(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.rounded.List (androidx.compose.material.icons.Icons.Rounded.List: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def LocationOn(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.rounded.LocationOn (androidx.compose.material.icons.Icons.Rounded.LocationOn: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Lock(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.rounded.Lock (androidx.compose.material.icons.Icons.Rounded.Lock: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def MailOutline(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.rounded.MailOutline (androidx.compose.material.icons.Icons.Rounded.MailOutline: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Menu(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.rounded.Menu (androidx.compose.material.icons.Icons.Rounded.Menu: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def MoreVert(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.rounded.MoreVert (androidx.compose.material.icons.Icons.Rounded.MoreVert: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Notifications(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.rounded.Notifications (androidx.compose.material.icons.Icons.Rounded.Notifications: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Person(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.rounded.Person (androidx.compose.material.icons.Icons.Rounded.Person: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Phone(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.rounded.Phone (androidx.compose.material.icons.Icons.Rounded.Phone: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Place(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.rounded.Place (androidx.compose.material.icons.Icons.Rounded.Place: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def PlayArrow(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.rounded.PlayArrow (androidx.compose.material.icons.Icons.Rounded.PlayArrow: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Refresh(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.rounded.Refresh (androidx.compose.material.icons.Icons.Rounded.Refresh: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Search(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.rounded.Search (androidx.compose.material.icons.Icons.Rounded.Search: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Send(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.rounded.Send (androidx.compose.material.icons.Icons.Rounded.Send: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Settings(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.rounded.Settings (androidx.compose.material.icons.Icons.Rounded.Settings: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Share(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.rounded.Share (androidx.compose.material.icons.Icons.Rounded.Share: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def ShoppingCart(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.rounded.ShoppingCart (androidx.compose.material.icons.Icons.Rounded.ShoppingCart: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Star(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.rounded.Star (androidx.compose.material.icons.Icons.Rounded.Star: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def ThumbUp(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.rounded.ThumbUp (androidx.compose.material.icons.Icons.Rounded.ThumbUp: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Warning(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.rounded.Warning (androidx.compose.material.icons.Icons.Rounded.Warning: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + class Sharp: + """Kotlin: androidx.compose.material.icons.Icons.Sharp""" + @property + def AccountBox(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.sharp.AccountBox (androidx.compose.material.icons.Icons.Sharp.AccountBox: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def AccountCircle(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.sharp.AccountCircle (androidx.compose.material.icons.Icons.Sharp.AccountCircle: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Add(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.sharp.Add (androidx.compose.material.icons.Icons.Sharp.Add: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def AddCircle(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.sharp.AddCircle (androidx.compose.material.icons.Icons.Sharp.AddCircle: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def ArrowBack(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.sharp.ArrowBack (androidx.compose.material.icons.Icons.Sharp.ArrowBack: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def ArrowDropDown(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.sharp.ArrowDropDown (androidx.compose.material.icons.Icons.Sharp.ArrowDropDown: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def ArrowForward(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.sharp.ArrowForward (androidx.compose.material.icons.Icons.Sharp.ArrowForward: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Build(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.sharp.Build (androidx.compose.material.icons.Icons.Sharp.Build: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Call(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.sharp.Call (androidx.compose.material.icons.Icons.Sharp.Call: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Check(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.sharp.Check (androidx.compose.material.icons.Icons.Sharp.Check: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def CheckCircle(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.sharp.CheckCircle (androidx.compose.material.icons.Icons.Sharp.CheckCircle: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Clear(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.sharp.Clear (androidx.compose.material.icons.Icons.Sharp.Clear: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Close(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.sharp.Close (androidx.compose.material.icons.Icons.Sharp.Close: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Create(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.sharp.Create (androidx.compose.material.icons.Icons.Sharp.Create: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def DateRange(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.sharp.DateRange (androidx.compose.material.icons.Icons.Sharp.DateRange: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Delete(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.sharp.Delete (androidx.compose.material.icons.Icons.Sharp.Delete: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Done(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.sharp.Done (androidx.compose.material.icons.Icons.Sharp.Done: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Edit(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.sharp.Edit (androidx.compose.material.icons.Icons.Sharp.Edit: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Email(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.sharp.Email (androidx.compose.material.icons.Icons.Sharp.Email: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def ExitToApp(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.sharp.ExitToApp (androidx.compose.material.icons.Icons.Sharp.ExitToApp: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Face(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.sharp.Face (androidx.compose.material.icons.Icons.Sharp.Face: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Favorite(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.sharp.Favorite (androidx.compose.material.icons.Icons.Sharp.Favorite: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def FavoriteBorder(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.sharp.FavoriteBorder (androidx.compose.material.icons.Icons.Sharp.FavoriteBorder: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Home(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.sharp.Home (androidx.compose.material.icons.Icons.Sharp.Home: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Info(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.sharp.Info (androidx.compose.material.icons.Icons.Sharp.Info: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def KeyboardArrowDown(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.sharp.KeyboardArrowDown (androidx.compose.material.icons.Icons.Sharp.KeyboardArrowDown: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def KeyboardArrowLeft(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.sharp.KeyboardArrowLeft (androidx.compose.material.icons.Icons.Sharp.KeyboardArrowLeft: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def KeyboardArrowRight(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.sharp.KeyboardArrowRight (androidx.compose.material.icons.Icons.Sharp.KeyboardArrowRight: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def KeyboardArrowUp(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.sharp.KeyboardArrowUp (androidx.compose.material.icons.Icons.Sharp.KeyboardArrowUp: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def List(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.sharp.List (androidx.compose.material.icons.Icons.Sharp.List: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def LocationOn(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.sharp.LocationOn (androidx.compose.material.icons.Icons.Sharp.LocationOn: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Lock(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.sharp.Lock (androidx.compose.material.icons.Icons.Sharp.Lock: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def MailOutline(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.sharp.MailOutline (androidx.compose.material.icons.Icons.Sharp.MailOutline: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Menu(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.sharp.Menu (androidx.compose.material.icons.Icons.Sharp.Menu: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def MoreVert(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.sharp.MoreVert (androidx.compose.material.icons.Icons.Sharp.MoreVert: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Notifications(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.sharp.Notifications (androidx.compose.material.icons.Icons.Sharp.Notifications: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Person(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.sharp.Person (androidx.compose.material.icons.Icons.Sharp.Person: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Phone(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.sharp.Phone (androidx.compose.material.icons.Icons.Sharp.Phone: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Place(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.sharp.Place (androidx.compose.material.icons.Icons.Sharp.Place: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def PlayArrow(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.sharp.PlayArrow (androidx.compose.material.icons.Icons.Sharp.PlayArrow: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Refresh(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.sharp.Refresh (androidx.compose.material.icons.Icons.Sharp.Refresh: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Search(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.sharp.Search (androidx.compose.material.icons.Icons.Sharp.Search: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Send(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.sharp.Send (androidx.compose.material.icons.Icons.Sharp.Send: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Settings(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.sharp.Settings (androidx.compose.material.icons.Icons.Sharp.Settings: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Share(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.sharp.Share (androidx.compose.material.icons.Icons.Sharp.Share: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def ShoppingCart(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.sharp.ShoppingCart (androidx.compose.material.icons.Icons.Sharp.ShoppingCart: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Star(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.sharp.Star (androidx.compose.material.icons.Icons.Sharp.Star: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def ThumbUp(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.sharp.ThumbUp (androidx.compose.material.icons.Icons.Sharp.ThumbUp: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Warning(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.sharp.Warning (androidx.compose.material.icons.Icons.Sharp.Warning: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + class TwoTone: + """Kotlin: androidx.compose.material.icons.Icons.TwoTone""" + @property + def AccountBox(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.twotone.AccountBox (androidx.compose.material.icons.Icons.TwoTone.AccountBox: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def AccountCircle(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.twotone.AccountCircle (androidx.compose.material.icons.Icons.TwoTone.AccountCircle: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Add(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.twotone.Add (androidx.compose.material.icons.Icons.TwoTone.Add: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def AddCircle(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.twotone.AddCircle (androidx.compose.material.icons.Icons.TwoTone.AddCircle: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def ArrowBack(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.twotone.ArrowBack (androidx.compose.material.icons.Icons.TwoTone.ArrowBack: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def ArrowDropDown(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.twotone.ArrowDropDown (androidx.compose.material.icons.Icons.TwoTone.ArrowDropDown: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def ArrowForward(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.twotone.ArrowForward (androidx.compose.material.icons.Icons.TwoTone.ArrowForward: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Build(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.twotone.Build (androidx.compose.material.icons.Icons.TwoTone.Build: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Call(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.twotone.Call (androidx.compose.material.icons.Icons.TwoTone.Call: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Check(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.twotone.Check (androidx.compose.material.icons.Icons.TwoTone.Check: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def CheckCircle(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.twotone.CheckCircle (androidx.compose.material.icons.Icons.TwoTone.CheckCircle: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Clear(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.twotone.Clear (androidx.compose.material.icons.Icons.TwoTone.Clear: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Close(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.twotone.Close (androidx.compose.material.icons.Icons.TwoTone.Close: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Create(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.twotone.Create (androidx.compose.material.icons.Icons.TwoTone.Create: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def DateRange(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.twotone.DateRange (androidx.compose.material.icons.Icons.TwoTone.DateRange: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Delete(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.twotone.Delete (androidx.compose.material.icons.Icons.TwoTone.Delete: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Done(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.twotone.Done (androidx.compose.material.icons.Icons.TwoTone.Done: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Edit(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.twotone.Edit (androidx.compose.material.icons.Icons.TwoTone.Edit: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Email(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.twotone.Email (androidx.compose.material.icons.Icons.TwoTone.Email: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def ExitToApp(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.twotone.ExitToApp (androidx.compose.material.icons.Icons.TwoTone.ExitToApp: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Face(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.twotone.Face (androidx.compose.material.icons.Icons.TwoTone.Face: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Favorite(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.twotone.Favorite (androidx.compose.material.icons.Icons.TwoTone.Favorite: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def FavoriteBorder(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.twotone.FavoriteBorder (androidx.compose.material.icons.Icons.TwoTone.FavoriteBorder: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Home(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.twotone.Home (androidx.compose.material.icons.Icons.TwoTone.Home: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Info(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.twotone.Info (androidx.compose.material.icons.Icons.TwoTone.Info: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def KeyboardArrowDown(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.twotone.KeyboardArrowDown (androidx.compose.material.icons.Icons.TwoTone.KeyboardArrowDown: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def KeyboardArrowLeft(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.twotone.KeyboardArrowLeft (androidx.compose.material.icons.Icons.TwoTone.KeyboardArrowLeft: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def KeyboardArrowRight(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.twotone.KeyboardArrowRight (androidx.compose.material.icons.Icons.TwoTone.KeyboardArrowRight: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def KeyboardArrowUp(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.twotone.KeyboardArrowUp (androidx.compose.material.icons.Icons.TwoTone.KeyboardArrowUp: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def List(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.twotone.List (androidx.compose.material.icons.Icons.TwoTone.List: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def LocationOn(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.twotone.LocationOn (androidx.compose.material.icons.Icons.TwoTone.LocationOn: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Lock(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.twotone.Lock (androidx.compose.material.icons.Icons.TwoTone.Lock: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def MailOutline(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.twotone.MailOutline (androidx.compose.material.icons.Icons.TwoTone.MailOutline: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Menu(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.twotone.Menu (androidx.compose.material.icons.Icons.TwoTone.Menu: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def MoreVert(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.twotone.MoreVert (androidx.compose.material.icons.Icons.TwoTone.MoreVert: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Notifications(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.twotone.Notifications (androidx.compose.material.icons.Icons.TwoTone.Notifications: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Person(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.twotone.Person (androidx.compose.material.icons.Icons.TwoTone.Person: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Phone(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.twotone.Phone (androidx.compose.material.icons.Icons.TwoTone.Phone: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Place(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.twotone.Place (androidx.compose.material.icons.Icons.TwoTone.Place: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def PlayArrow(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.twotone.PlayArrow (androidx.compose.material.icons.Icons.TwoTone.PlayArrow: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Refresh(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.twotone.Refresh (androidx.compose.material.icons.Icons.TwoTone.Refresh: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Search(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.twotone.Search (androidx.compose.material.icons.Icons.TwoTone.Search: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Send(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.twotone.Send (androidx.compose.material.icons.Icons.TwoTone.Send: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Settings(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.twotone.Settings (androidx.compose.material.icons.Icons.TwoTone.Settings: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Share(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.twotone.Share (androidx.compose.material.icons.Icons.TwoTone.Share: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def ShoppingCart(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.twotone.ShoppingCart (androidx.compose.material.icons.Icons.TwoTone.ShoppingCart: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Star(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.twotone.Star (androidx.compose.material.icons.Icons.TwoTone.Star: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def ThumbUp(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.twotone.ThumbUp (androidx.compose.material.icons.Icons.TwoTone.ThumbUp: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + @property + def Warning(self) -> _t.Any: + """Kotlin property: androidx.compose.material.icons.twotone.Warning (androidx.compose.material.icons.Icons.TwoTone.Warning: androidx.compose.ui.graphics.vector.ImageVector)""" + ... + Default: _t.ClassVar[Icons.Filled] + """Kotlin: androidx.compose.material.icons.Icons.Default(): androidx.compose.material.icons.Icons.Filled""" diff --git a/pythonx/compose/material3/__init__.pyi b/pythonx/compose/material3/__init__.pyi index 999964f..65a9fa6 100644 --- a/pythonx/compose/material3/__init__.pyi +++ b/pythonx/compose/material3/__init__.pyi @@ -8,6 +8,9 @@ import pythonx.compose.ui.text from pythonx.compose.layout import Column as Column from pythonx.compose.layout import Row as Row from pythonx.compose.layout import Spacer as Spacer +import pythonx.compose.material.icons as _alias_0 + +DefaultIcons = _alias_0.Icons.Default class _ColorScheme_contentColorFor(_t.Protocol): def __call__(self, background_color: _t.Any) -> _t.Any: ... diff --git a/pythonx/compose/pythonx-map.toml b/pythonx/compose/pythonx-map.toml index 2e0b8bc..a3eb5d0 100644 --- a/pythonx/compose/pythonx-map.toml +++ b/pythonx/compose/pythonx-map.toml @@ -21,6 +21,11 @@ "pythonx.compose.runtime" = "androidx.compose.runtime" "pythonx.compose.ui" = "androidx.compose.ui" +# `DefaultIcons` (INTENT section 5.7) is `Icons.Default`, which lives here: `Icons` is an object of +# `material-icons-core`, and `Icons.Default.Add` is an extension property read on `Icons.Filled`. +"pythonx.compose.material" = "androidx.compose.material" +"pythonx.compose.material.icons" = "androidx.compose.material.icons" + # Reached through the four above rather than imported directly: a `Modifier` chain returns into # `ui.unit` and `ui.graphics`, and `ui.text` is where `TextStyle` lives. "pythonx.compose.ui.unit" = "androidx.compose.ui.unit" @@ -52,3 +57,10 @@ raw-primitive-allowed = [ # `androidx.compose.foundation.layout`. Each is the same object as in its home module; this is data, # not a wrapper, and the rule that serves it is the one in `_reexport.py`. "pythonx.compose.layout" = ["Column", "Row", "Spacer"] +# +# An entry is a list of names lent under the SAME name, or a table `{ lent name = "Path.To.Attr" }` +# that lends an attribute path of the source under a DIFFERENT name: the notebook's `DefaultIcons` +# is Kotlin's `Icons.Default` (INTENT section 5.7). The first segment is a name of the source module, +# each further one an attribute read. A path with a dot is read afresh on every access and never kept, +# the way the binder serves `Icons.Default` (a live property); a plain name is resolved once. +"pythonx.compose.material.icons" = { DefaultIcons = "Icons.Default" } diff --git a/tests/fake_host.py b/tests/fake_host.py index 8773530..ca8a880 100644 --- a/tests/fake_host.py +++ b/tests/fake_host.py @@ -52,6 +52,11 @@ RUNTIME = "androidx.compose.runtime" MUTABLE_STATE = RUNTIME + ".MutableState" +ICONS_PACKAGE = "androidx.compose.material.icons" +ICONS = ICONS_PACKAGE + ".Icons" +ICONS_FILLED = ICONS + ".Filled" +IMAGE_VECTOR = "androidx.compose.ui.graphics.vector.ImageVector" + EMPTY_MODIFIER = "androidx.compose.ui.emptyModifier" """The one entry the real walker does **not** produce; see `ComposeShapedFragment.EMPTY_MODIFIER`. @@ -86,6 +91,12 @@ def __init__(self, label): self.label = label +class StubIconSet: + """`Icons.Filled`: the one object `Icons.Default` resolves to, so a test can tell it was reached.""" + + __slots__ = () + + class StubPaddingValues: """An ordinary object parameter, so two arity-2 overloads differ by declared type alone.""" @@ -124,6 +135,7 @@ def __init__(self): self._order = [] self._handles = {} self._next_handle = 1 + self.filled = StubIconSet() self._build() # ------------------------------------------------------------------ the boundary (3 names) @@ -340,6 +352,21 @@ def _build(self): lambda args: StubConstant(f"spacedBy({_dp(args[0])})"), ) + # Icons, shaped after python-multiplatform #37/#38 as the ecosystem reports them: `Icons.Default` + # is a `STATIC_GETTER` of the object `Icons` whose declared type is `Icons.Filled` (the + # property's type, not `Default`'s own), and `Icons.Default.Add` is the top-level extension + # property `AddKt.getAdd(Icons$Filled)` -- a `GETTER` named by its package and property, read on + # `Icons.Filled`, whose receiver is `args[0]` and not a slot, returning an `ImageVector`. + self._add( + f"{ICONS}.Default", 0, (), (), (), "OBJECT", ICONS_FILLED, False, None, (), + lambda args: self.filled, kind="STATIC_GETTER", + ) + for icon in ("Add", "Edit"): + self._add( + f"{ICONS_PACKAGE}.filled.{icon}", 0, (), (), (), "OBJECT", IMAGE_VECTOR, False, + ICONS_FILLED, (), + lambda args, icon=icon: self._read_icon(icon), kind="GETTER", + ) self._add( # A generic function: `T` is unbounded, so its slot is declared `kotlin.Any`. f"{RUNTIME}.mutableStateOf", 1, ("value",), ("OBJECT",), (KOTLIN_ANY,), @@ -356,6 +383,10 @@ def _build(self): lambda args: args[0].write(args[1]), kind="SETTER", ) + def _read_icon(self, icon): + self.calls.append(f"Icons.Filled.{icon}") + return StubConstant(icon) + def _constant(self, name, declared): self._add(name, 0, (), (), (), "OBJECT", declared, False, None, (), lambda args, label=name.rpartition(".")[2]: StubConstant(label), kind="STATIC_GETTER") diff --git a/tests/test_chain.py b/tests/test_chain.py index 923de36..723546c 100644 --- a/tests/test_chain.py +++ b/tests/test_chain.py @@ -649,6 +649,83 @@ def test_a_name_not_listed_is_not_borrowed(self): material3.padding_values_of # noqa: B018 +class DefaultIconsAlias(AdapterCase): + """INTENT 5.7: `DefaultIcons` is `Icons.Default`, lent by `material3` under another name and path.""" + + def label_of(self, proxy): + return self.host._object(proxy._pm_handle).label + + def test_the_icons_module_serves_icons_by_the_rule(self): + from pythonx.compose.material.icons import Icons + + default = Icons.Default # held: dropping a proxy releases its handle + self.assertIs(self.host.filled, self.host._object(default._pm_handle)) + + def test_the_icon_is_the_extension_property_getter_on_icons_filled(self): + from pythonx.compose.material.icons import Icons + + self.assertEqual("Add", self.label_of(Icons.Default.Add)) + self.assertEqual(["Icons.Filled.Add"], self.host.calls) + + def test_the_notebook_import_resolves(self): + from pythonx.compose.material3 import DefaultIcons + + self.assertIsNotNone(DefaultIcons) + + def test_default_icons_is_icons_default(self): + from pythonx.compose.material.icons import Icons + from pythonx.compose.material3 import DefaultIcons + + # The same Kotlin object: a read yields a proxy, and both reads reach the one `Icons.Filled`. + default = Icons.Default + self.assertIs(self.host._object(default._pm_handle), self.host._object(DefaultIcons._pm_handle)) + self.assertIs(self.host.filled, self.host._object(DefaultIcons._pm_handle)) + + def test_the_alias_reaches_the_getter(self): + from pythonx.compose.material3 import DefaultIcons + + self.assertEqual("Add", self.label_of(DefaultIcons.Add)) + self.assertEqual("Edit", self.label_of(DefaultIcons.Edit)) + self.assertEqual(["Icons.Filled.Add", "Icons.Filled.Edit"], self.host.calls) + + def test_the_alias_is_read_again_each_time_as_the_binder_serves_icons_default(self): + import pythonx.compose.material3 as material3 + + first, second = material3.DefaultIcons, material3.DefaultIcons + self.assertIsNot(first, second) + self.assertNotIn("DefaultIcons", vars(material3)) + + def test_dir_of_material3_lists_default_icons(self): + import pythonx.compose.material3 as material3 + + self.assertIn("DefaultIcons", dir(material3)) + + def test_an_unknown_icon_is_an_attribute_error(self): + from pythonx.compose.material3 import DefaultIcons + + with self.assertRaises(AttributeError): + DefaultIcons.NoSuchIcon # noqa: B018 + + def test_the_icon_is_a_value_not_a_call(self): + # The notebook writes `DefaultIcons.Add()`; an icon is a property read, so a call is refused. + from pythonx.compose.material3 import DefaultIcons + + with self.assertRaises(TypeError): + DefaultIcons.Add() + + def test_the_name_is_not_borrowed_by_another_module(self): + import pythonx.compose.layout as layout + + with self.assertRaises(AttributeError): + layout.DefaultIcons # noqa: B018 + + def test_the_list_form_still_lends_under_the_same_name(self): + from pythonx.compose.layout import Spacer as home + from pythonx.compose.material3 import Spacer + + self.assertIs(home, Spacer) + + class SubmodulesWithoutABinder(unittest.TestCase): """`from pythonx.compose.ui import modifier` reaches the file even when no binder is installed. diff --git a/tests/test_pythonx_map.py b/tests/test_pythonx_map.py index 45fd63a..b3faf8e 100644 --- a/tests/test_pythonx_map.py +++ b/tests/test_pythonx_map.py @@ -76,6 +76,13 @@ def test_the_short_layout_spelling_drops_foundation(self) -> None: ) +def _lent_names(lent) -> dict: + """Both forms of one source's entry as {name lent: attribute path in the source}.""" + if isinstance(lent, list): + return {name: name for name in lent} + return dict(lent) + + class TestAliasSection(unittest.TestCase): def test_every_alias_points_between_mapped_modules(self) -> None: manifest = _manifest() @@ -86,10 +93,48 @@ def test_every_alias_points_between_mapped_modules(self) -> None: for source in sources: self.assertIn(source, modules) + def test_an_entry_is_a_list_of_names_or_a_table_of_name_to_path(self) -> None: + for owner, sources in _manifest().get("aliases", {}).items(): + for source, lent in sources.items(): + with self.subTest(owner=owner, source=source): + if isinstance(lent, list): + self.assertTrue(lent and all(isinstance(name, str) for name in lent)) + else: + self.assertIsInstance(lent, dict) + for name, path in lent.items(): + self.assertTrue(name.isidentifier(), name) + self.assertTrue( + all(part.isidentifier() for part in path.split(".")), + f"{name} = {path!r} is not an attribute path", + ) + + def test_no_owner_lends_one_name_twice(self) -> None: + for owner, sources in _manifest().get("aliases", {}).items(): + names = [name for lent in sources.values() for name in _lent_names(lent)] + with self.subTest(owner=owner): + self.assertEqual(sorted(set(names)), sorted(names)) + def test_material3_answers_for_the_layout_composables_the_notebook_imports(self) -> None: aliases = _manifest()["aliases"]["pythonx.compose.material3"]["pythonx.compose.layout"] self.assertEqual(["Column", "Row", "Spacer"], aliases) + def test_material3_answers_for_default_icons_as_icons_default(self) -> None: + # INTENT 5.7: a different name, through an attribute path, and the icons package is mapped. + manifest = _manifest() + lent = manifest["aliases"]["pythonx.compose.material3"]["pythonx.compose.material.icons"] + self.assertEqual({"DefaultIcons": "Icons.Default"}, lent) + self.assertEqual( + "androidx.compose.material.icons", manifest["modules"]["pythonx.compose.material.icons"] + ) + + def test_every_mapped_module_is_a_package_on_disk(self) -> None: + # AGENTS.md 12: `pythonx/` is a real package; a manifest row without its file is a module + # the stubs describe and the interpreter cannot import. + for module in _manifest()["modules"]: + with self.subTest(module=module): + init = REPO.joinpath(*module.split(".")) / "__init__.py" + self.assertTrue(init.is_file(), f"{module} has a manifest row but no {init}") + class TestValueClassSection(unittest.TestCase): def test_dp_is_allowed_and_packed_classes_are_not(self) -> None: diff --git a/tests/test_stubs.py b/tests/test_stubs.py index f9df16a..d1619a6 100644 --- a/tests/test_stubs.py +++ b/tests/test_stubs.py @@ -48,6 +48,7 @@ class per bound Kotlin type with its extension members as `ClassVar`s of callabl UI = COMPOSE / "ui" / "__init__.pyi" TEXT = COMPOSE / "ui" / "text" / "__init__.pyi" MATERIAL3 = COMPOSE / "material3" / "__init__.pyi" +ICONS = COMPOSE / "material" / "icons" / "__init__.pyi" def _generated(root: Path = KOTLIN_STUBS) -> dict[Path, str]: @@ -248,7 +249,10 @@ def test_unmapped_or_undeclared_references_become_any(self): ) self.assertEqual( ["import typing as _t", "import pythonx.compose.ui", "import pythonx.compose.ui.text"], - [line for line in _imports(self.stubs[MATERIAL3]) if not line.startswith("from ")], + [ + line for line in _imports(self.stubs[MATERIAL3]) + if not line.startswith("from ") and " as _alias_" not in line # the DefaultIcons path alias + ], ) def test_an_object_sub_package_becomes_a_class_in_its_parent(self): @@ -289,6 +293,19 @@ def test_aliases_are_re_exported(self): for name in ("Column", "Row", "Spacer"): self.assertIn(f"from pythonx.compose.layout import {name} as {name}", imports) + def test_a_renamed_path_alias_is_the_same_path_in_the_owners_stub(self): + # `DefaultIcons` is `Icons.Default` of the icons module: not an import of that name (it + # differs), but the same expression, so a checker reads what the icons stub says it is. + text = self.stubs[MATERIAL3] + self.assertIn("import pythonx.compose.material.icons as _alias_0", text) + assigned = { + n.targets[0].id: ast.unparse(n.value) + for n in gen_stubs.parse(text).body + if isinstance(n, ast.Assign) and isinstance(n.targets[0], ast.Name) + } + self.assertEqual("_alias_0.Icons.Default", assigned.get("DefaultIcons")) + self.assertNotIn("DefaultIcons as", text) + def test_a_constant_named_like_a_python_keyword_is_left_out(self): source = ( "import typing as _t\n\nNone: _t.Any\n\"\"\"Kotlin: a.B.None(): a.B\"\"\"\n\n" @@ -486,6 +503,11 @@ def test_the_committed_stubs_are_exactly_what_the_artefact_generates(self): with self.subTest(stub=str(path.relative_to(REPO))): self.assertEqual(text, path.read_text(encoding="utf-8")) + def test_the_committed_icons_stub_declares_icons_and_material3_declares_default_icons(self): + icons = ICONS.read_text(encoding="utf-8") + self.assertIn("Icons", _classes(icons)) + self.assertIn("DefaultIcons = _alias_0.Icons.Default", MATERIAL3.read_text(encoding="utf-8")) + def test_the_committed_alignment_and_arrangement_carry_their_groups(self): alignment = _nested(_classes(UI.read_text(encoding="utf-8"))["Alignment"]) self.assertEqual({"CenterHorizontally", "End", "Start"}, _constants(alignment["Horizontal"])) diff --git a/tests/test_typing.py b/tests/test_typing.py index 4dfada1..16ba869 100644 --- a/tests/test_typing.py +++ b/tests/test_typing.py @@ -165,6 +165,25 @@ def flip(scene: ImageComposeScene) -> None: scene.layout_direction = scene.layout_direction """) + def test_default_icons_imports_from_material3(self): + """INTENT 5.7: the alias is `Icons.Default`, which the stub types as `Icons.Filled`. + `Icons.Filled.Add` is typed `Any` until python-multiplatform #68 stubs it properly.""" + self.assertPasses(""" + from pythonx.compose.material3 import DefaultIcons, Icon + from pythonx.compose.material.icons import Icons + + same: Icons.Filled = DefaultIcons + Icon(DefaultIcons.Add, content_description=None) + Icon(Icons.Default.Add, content_description=None) + """) + + def test_an_unknown_default_icon_fails(self): + self.assertFails(""" + from pythonx.compose.material3 import DefaultIcons + + DefaultIcons.NoSuchIcon + """, "NoSuchIcon", "[attr-defined]") + def test_a_kotlin_spelled_module_function_fails(self): self.assertFails(""" from pythonx.compose.layout import fillMaxWidth diff --git a/tools/gen_stubs.py b/tools/gen_stubs.py index 136683e..2e9c439 100644 --- a/tools/gen_stubs.py +++ b/tools/gen_stubs.py @@ -39,7 +39,8 @@ for it, and its import is rewritten to match; a package the manifest does not map, or a name the target stub does not declare as a class, becomes `typing.Any`; - a module that maps a Kotlin package an earlier module already maps re-exports that module, and - the manifest's `[aliases]` are re-exported, because at run time those names are the same objects; + the manifest's `[aliases]` are re-exported, because at run time those names are the same objects + (a name lent under another one, through an attribute path, is assigned that path of the source's stub); - names the module's own `__init__.py` defines (`runtime.Composable`) are carried over, because a `.pyi` beside a module replaces everything a type checker knows about it; so is a bare annotation (`app_root: State`), the way a module declares a name its `__getattr__` creates. @@ -445,9 +446,22 @@ def convert(self, source: str, kotlin_package: str = "", module_name: str = "") lines = [header(self.stubs.provenance), "import typing as _t\n"] lines.extend(f"import {module}\n" for module in sorted(references.used)) - for source_module, names in sorted(manifest().get("aliases", {}).get(module_name, {}).items()): - lines.extend(f"from {source_module} import {name} as {name}\n" for name in sorted(names)) + declared: list[str] = [] + for source_module, lent in sorted(manifest().get("aliases", {}).get(module_name, {}).items()): + pairs = {name: name for name in lent} if isinstance(lent, list) else dict(lent) + for name, path in sorted(pairs.items()): + if path == name: + lines.append(f"from {source_module} import {name} as {name}\n") + else: + # A name lent under another one, through an attribute path (`DefaultIcons` is + # `Icons.Default`): not an import but the same expression, so the type checker + # reads whatever the source's own stub says `Icons.Default` is. + lines.append(f"import {source_module} as _alias_{len(declared)}\n") + declared.append(f"{name} = _alias_{len(declared)}.{path}\n") lines.append("\n") + lines.extend(declared) + if declared: + lines.append("\n") lines.append(_emit_module(body)) return "".join(lines)