From db8b857a966d71e549440f006890e3591c6b1685 Mon Sep 17 00:00:00 2001 From: BREW <81044362+b-re-w@users.noreply.github.com> Date: Sun, 4 Oct 2026 04:29:10 +0900 Subject: [PATCH] Refactor: Fixtures live inside the modules they test; root ksp-fixtures/ removed (#108) KSP consumers under python-multiplatform-ksp/fixtures, artifact-walker consumers under python-multiplatform-gradle-plugin/fixtures (root-build projects, the plugin being an included build), Compose host consumers under python-multiplatform-compose/fixtures. Tests unchanged except the derived module-name strings that follow the new project paths. --- .github/scripts/stubs/check-stubs.sh | 2 +- .github/workflows/stubs.yml | 18 +++---- .github/workflows/typedpython.yml | 12 ++--- AGENTS.md | 16 ++++-- PROJECT.md | 6 +-- docs/SPEC.md | 48 +++++++++--------- docs/design/architecture.md | 2 +- docs/design/ecosystem.md | 8 +-- docs/design/kotlin-extensions-in-python.md | 4 +- docs/design/pyi-generation-design.md | 4 +- docs/design/upcall.md | 34 ++++++------- docs/guide/getting-started.html | 6 +-- docs/guide/index.html | 2 +- docs/roadmap/ROADMAP.md | 24 ++++----- .../fixtures}/compose/build.gradle.kts | 6 +-- .../fixture/compose/ModifierComparisons.kt | 0 .../compose/PythonAnchoredDraggable.kt | 0 .../kotlin/fixture/compose/PythonComposed.kt | 0 .../fixture/compose/PythonComposition.kt | 2 +- .../compose/PythonContextMenuOpenDetector.kt | 0 .../compose/PythonDragAndDropSource.kt | 0 .../kotlin/fixture/compose/PythonDraggable.kt | 0 .../kotlin/fixture/compose/PythonLayoutId.kt | 0 .../fixture/compose/PythonModifierLocal.kt | 0 .../fixture/compose/PythonPointerInput.kt | 0 .../fixture/compose/PythonPullRefresh.kt | 0 .../kotlin/fixture/compose/PythonSwipeable.kt | 0 .../compose/AnchoredDraggableRenderTest.kt | 0 .../compose/AnySlotScalarRenderTest.kt | 0 .../compose/CallbackDrivenRenderTest.kt | 0 .../fixture/compose/ColorFactoryTest.kt | 0 .../fixture/compose/ComposableRenderTest.kt | 0 .../fixture/compose/ComposedRenderTest.kt | 0 .../ContextMenuOpenDetectorRenderTest.kt | 0 .../compose/DragAndDropSourceRenderTest.kt | 0 .../fixture/compose/DraggableLeakTest.kt | 0 .../fixture/compose/DraggableRenderTest.kt | 0 .../kotlin/fixture/compose/IconRenderTest.kt | 0 .../compose/KotlinSignatureMetadataTest.kt | 0 .../fixture/compose/LayoutIdRenderTest.kt | 0 .../fixture/compose/M3ProofRenderTest.kt | 0 .../compose/MaterialIconsRenderTest.kt | 0 .../compose/MemberResolverComposeTest.kt | 0 .../compose/ModifierLocalRenderTest.kt | 0 .../compose/ModifierSeededRenderTest.kt | 4 +- .../compose/ObjectConstantRenderTest.kt | 0 .../fixture/compose/PointerInputRenderTest.kt | 0 .../fixture/compose/PullRefreshRenderTest.kt | 0 .../compose/PythonAppViewRenderTest.kt | 0 .../kotlin/fixture/compose/PythonxModules.kt | 0 .../compose/RecompositionAccumulationTest.kt | 0 .../compose/RememberSaveableRenderTest.kt | 0 .../RetainedSlotSweepPreconditionTest.kt | 0 .../fixture/compose/SwipeableRenderTest.kt | 0 .../compose/TextFieldStateRenderTest.kt | 0 .../desktopTest/resources/opaque-square.png | Bin .../fixtures}/notebook-e2e/README.md | 8 +-- .../fixtures}/notebook-e2e/build.gradle.kts | 8 +-- .../kotlin/fixture/notebook/EmptyModifier.kt | 0 .../fixture/notebook/InputMethodScene.kt | 0 .../kotlin/fixture/notebook/NotebookHost.kt | 0 .../fixture/notebook/NotebookPracticeTest.kt | 0 .../fixture/notebook/NotebookRootTest.kt | 0 .../fixture/notebook/NotebookTextFieldTest.kt | 0 .../src/desktopTest/python/main.py | 0 .../build.gradle.kts | 4 +- .../artifact-valueclass/build.gradle.kts | 2 +- .../main/kotlin/fixture/valueclass/Meters.kt | 2 +- .../fixtures}/artifact/build.gradle.kts | 8 +-- .../fixture/artifact/OwnDeclarations.kt | 0 .../kotlin/fixture/artifact/ComposeSeed.kt | 0 .../kotlin/fixture/artifact/PythonxModules.kt | 0 .../StubSignatureAgreesWithRuntimeTest.kt | 0 .../artifact/WalkedArtifactCallbackTest.kt | 2 +- .../WalkedArtifactComposeModifierTest.kt | 0 .../WalkedArtifactDefaultOmissionTest.kt | 0 .../WalkedArtifactPythonImportTest.kt | 2 +- .../artifact/WalkedArtifactStubTest.kt | 0 .../artifact/WalkedArtifactTableTest.kt | 6 +-- .../WalkedArtifactValueClassBoxTest.kt | 0 .../fixtures}/klib-artifact/build.gradle.kts | 8 +-- .../WalkedKlibArtifactPythonImportTest.kt | 2 +- .../artifact/WalkedKlibArtifactTableTest.kt | 2 +- .../fixture/artifact/OwnDeclarations.kt | 2 +- .../gradle/PythonBindingsPlugin.kt | 8 +-- .../gradle/artifact/ArtifactScanner.kt | 2 +- .../gradle/artifact/KlibScanWorkAction.kt | 2 +- .../gradle/artifact/KlibScanner.kt | 2 +- .../python/multiplatform/gradle/WiringTest.kt | 12 ++--- .../gradle/artifact/ArtifactScannerTest.kt | 2 +- .../artifact/ArtifactTableRenderingTest.kt | 2 +- .../artifact/FunctionSlotBindingTest.kt | 2 +- .../gradle/artifact/KlibScannerTest.kt | 2 +- .../gradle/artifact/PropertyBindingTest.kt | 2 +- .../gradle/artifact/ReturnSupertypeTest.kt | 2 +- .../gradle/artifact/TextStateBindingTest.kt | 4 +- .../valueclassfixture/ValueClassFixtures.kt | 2 +- .../fixtures}/android/build.gradle.kts | 8 +-- .../android/GeneratedAndroidTableTest.kt | 6 +-- .../fixture/android/AndroidFunctions.kt | 4 +- .../android/GeneratedAndroidTableTest.kt | 4 +- .../kotlin/fixture/android/TableInstall.kt | 2 +- .../fixtures}/app/build.gradle.kts | 2 +- .../kotlin/fixture/app/NativeSmokeTest.kt | 0 .../kotlin/fixture/app/NativeInstall.kt | 2 +- .../kotlin/fixture/app/AppExtras.kt | 0 .../kotlin/fixture/app/AppFunctions.kt | 0 .../kotlin/fixture/app/ArgumentRelease.kt | 0 .../kotlin/fixture/app/TableInstall.kt | 6 +-- .../kotlin/fixture/app/TypedPythonBridge.kt | 0 .../kotlin/fixture/app/CommonInstallTest.kt | 2 +- .../app/GeneratedDeclarationKindsTest.kt | 2 +- .../app/GeneratedStaticPropertyProxyTest.kt | 0 .../fixture/app/GeneratedSuspendTest.kt | 2 +- .../kotlin/fixture/app/GeneratedTableTest.kt | 4 +- .../fixture/app/KspClassResultProxyTest.kt | 0 .../fixture/app/ProxyObjectArgumentTest.kt | 0 .../app/PyObjectArgumentReleaseTest.kt | 0 .../app/RefHolderCycleCollectionTest.kt | 0 .../fixture/app/TypedPythonKotlinCallTest.kt | 2 +- .../typedpython/fixture/__init__.pyi | 0 .../typedpython/fixture/app/__init__.pyi | 2 +- .../typedpython/tp_kotlin_bridge.py | 0 .../fixtures}/app/typedpython/build_bridge.py | 2 +- .../fixtures}/library/build.gradle.kts | 2 +- .../kotlin/fixture/library/Declarations.kt | 2 +- .../kotlin/fixture/library/LibFunctions.kt | 0 .../kotlin/fixture/library/Suspending.kt | 0 .../python/multiplatform/ksp/BindingPolicy.kt | 2 +- .../ffi/pythonx/PythonCallables.kt | 4 +- .../ffi/upcall/PythonProxySource.kt | 2 +- .../reflection/InstallsUpcallTable.kt | 2 +- .../ffi/pythonx/ComposableShapedFragment.kt | 2 +- .../ffi/pythonx/ComposeShapedFragment.kt | 2 +- .../ffi/pythonx/PythonxCallableTest.kt | 4 +- .../ffi/pythonx/PythonxComposableTest.kt | 2 +- .../ffi/upcall/PythonProxySourceTest.kt | 4 +- .../ffi/upcall/UpcallBootstrapTest.kt | 2 +- .../multiplatform/reflection/TestFragments.kt | 2 +- sample/build.gradle.kts | 2 +- .../demo/bindings/UpcallDemo.ios.kt | 2 +- settings.gradle.kts | 43 +++++++++++----- 142 files changed, 226 insertions(+), 201 deletions(-) rename {ksp-fixtures => python-multiplatform-compose/fixtures}/compose/build.gradle.kts (95%) rename {ksp-fixtures => python-multiplatform-compose/fixtures}/compose/src/desktopMain/kotlin/fixture/compose/ModifierComparisons.kt (100%) rename {ksp-fixtures => python-multiplatform-compose/fixtures}/compose/src/desktopMain/kotlin/fixture/compose/PythonAnchoredDraggable.kt (100%) rename {ksp-fixtures => python-multiplatform-compose/fixtures}/compose/src/desktopMain/kotlin/fixture/compose/PythonComposed.kt (100%) rename {ksp-fixtures => python-multiplatform-compose/fixtures}/compose/src/desktopMain/kotlin/fixture/compose/PythonComposition.kt (98%) rename {ksp-fixtures => python-multiplatform-compose/fixtures}/compose/src/desktopMain/kotlin/fixture/compose/PythonContextMenuOpenDetector.kt (100%) rename {ksp-fixtures => python-multiplatform-compose/fixtures}/compose/src/desktopMain/kotlin/fixture/compose/PythonDragAndDropSource.kt (100%) rename {ksp-fixtures => python-multiplatform-compose/fixtures}/compose/src/desktopMain/kotlin/fixture/compose/PythonDraggable.kt (100%) rename {ksp-fixtures => python-multiplatform-compose/fixtures}/compose/src/desktopMain/kotlin/fixture/compose/PythonLayoutId.kt (100%) rename {ksp-fixtures => python-multiplatform-compose/fixtures}/compose/src/desktopMain/kotlin/fixture/compose/PythonModifierLocal.kt (100%) rename {ksp-fixtures => python-multiplatform-compose/fixtures}/compose/src/desktopMain/kotlin/fixture/compose/PythonPointerInput.kt (100%) rename {ksp-fixtures => python-multiplatform-compose/fixtures}/compose/src/desktopMain/kotlin/fixture/compose/PythonPullRefresh.kt (100%) rename {ksp-fixtures => python-multiplatform-compose/fixtures}/compose/src/desktopMain/kotlin/fixture/compose/PythonSwipeable.kt (100%) rename {ksp-fixtures => python-multiplatform-compose/fixtures}/compose/src/desktopTest/kotlin/fixture/compose/AnchoredDraggableRenderTest.kt (100%) rename {ksp-fixtures => python-multiplatform-compose/fixtures}/compose/src/desktopTest/kotlin/fixture/compose/AnySlotScalarRenderTest.kt (100%) rename {ksp-fixtures => python-multiplatform-compose/fixtures}/compose/src/desktopTest/kotlin/fixture/compose/CallbackDrivenRenderTest.kt (100%) rename {ksp-fixtures => python-multiplatform-compose/fixtures}/compose/src/desktopTest/kotlin/fixture/compose/ColorFactoryTest.kt (100%) rename {ksp-fixtures => python-multiplatform-compose/fixtures}/compose/src/desktopTest/kotlin/fixture/compose/ComposableRenderTest.kt (100%) rename {ksp-fixtures => python-multiplatform-compose/fixtures}/compose/src/desktopTest/kotlin/fixture/compose/ComposedRenderTest.kt (100%) rename {ksp-fixtures => python-multiplatform-compose/fixtures}/compose/src/desktopTest/kotlin/fixture/compose/ContextMenuOpenDetectorRenderTest.kt (100%) rename {ksp-fixtures => python-multiplatform-compose/fixtures}/compose/src/desktopTest/kotlin/fixture/compose/DragAndDropSourceRenderTest.kt (100%) rename {ksp-fixtures => python-multiplatform-compose/fixtures}/compose/src/desktopTest/kotlin/fixture/compose/DraggableLeakTest.kt (100%) rename {ksp-fixtures => python-multiplatform-compose/fixtures}/compose/src/desktopTest/kotlin/fixture/compose/DraggableRenderTest.kt (100%) rename {ksp-fixtures => python-multiplatform-compose/fixtures}/compose/src/desktopTest/kotlin/fixture/compose/IconRenderTest.kt (100%) rename {ksp-fixtures => python-multiplatform-compose/fixtures}/compose/src/desktopTest/kotlin/fixture/compose/KotlinSignatureMetadataTest.kt (100%) rename {ksp-fixtures => python-multiplatform-compose/fixtures}/compose/src/desktopTest/kotlin/fixture/compose/LayoutIdRenderTest.kt (100%) rename {ksp-fixtures => python-multiplatform-compose/fixtures}/compose/src/desktopTest/kotlin/fixture/compose/M3ProofRenderTest.kt (100%) rename {ksp-fixtures => python-multiplatform-compose/fixtures}/compose/src/desktopTest/kotlin/fixture/compose/MaterialIconsRenderTest.kt (100%) rename {ksp-fixtures => python-multiplatform-compose/fixtures}/compose/src/desktopTest/kotlin/fixture/compose/MemberResolverComposeTest.kt (100%) rename {ksp-fixtures => python-multiplatform-compose/fixtures}/compose/src/desktopTest/kotlin/fixture/compose/ModifierLocalRenderTest.kt (100%) rename {ksp-fixtures => python-multiplatform-compose/fixtures}/compose/src/desktopTest/kotlin/fixture/compose/ModifierSeededRenderTest.kt (97%) rename {ksp-fixtures => python-multiplatform-compose/fixtures}/compose/src/desktopTest/kotlin/fixture/compose/ObjectConstantRenderTest.kt (100%) rename {ksp-fixtures => python-multiplatform-compose/fixtures}/compose/src/desktopTest/kotlin/fixture/compose/PointerInputRenderTest.kt (100%) rename {ksp-fixtures => python-multiplatform-compose/fixtures}/compose/src/desktopTest/kotlin/fixture/compose/PullRefreshRenderTest.kt (100%) rename {ksp-fixtures => python-multiplatform-compose/fixtures}/compose/src/desktopTest/kotlin/fixture/compose/PythonAppViewRenderTest.kt (100%) rename {ksp-fixtures => python-multiplatform-compose/fixtures}/compose/src/desktopTest/kotlin/fixture/compose/PythonxModules.kt (100%) rename {ksp-fixtures => python-multiplatform-compose/fixtures}/compose/src/desktopTest/kotlin/fixture/compose/RecompositionAccumulationTest.kt (100%) rename {ksp-fixtures => python-multiplatform-compose/fixtures}/compose/src/desktopTest/kotlin/fixture/compose/RememberSaveableRenderTest.kt (100%) rename {ksp-fixtures => python-multiplatform-compose/fixtures}/compose/src/desktopTest/kotlin/fixture/compose/RetainedSlotSweepPreconditionTest.kt (100%) rename {ksp-fixtures => python-multiplatform-compose/fixtures}/compose/src/desktopTest/kotlin/fixture/compose/SwipeableRenderTest.kt (100%) rename {ksp-fixtures => python-multiplatform-compose/fixtures}/compose/src/desktopTest/kotlin/fixture/compose/TextFieldStateRenderTest.kt (100%) rename {ksp-fixtures => python-multiplatform-compose/fixtures}/compose/src/desktopTest/resources/opaque-square.png (100%) rename {ksp-fixtures => python-multiplatform-compose/fixtures}/notebook-e2e/README.md (93%) rename {ksp-fixtures => python-multiplatform-compose/fixtures}/notebook-e2e/build.gradle.kts (94%) rename {ksp-fixtures => python-multiplatform-compose/fixtures}/notebook-e2e/src/desktopMain/kotlin/fixture/notebook/EmptyModifier.kt (100%) rename {ksp-fixtures => python-multiplatform-compose/fixtures}/notebook-e2e/src/desktopTest/kotlin/fixture/notebook/InputMethodScene.kt (100%) rename {ksp-fixtures => python-multiplatform-compose/fixtures}/notebook-e2e/src/desktopTest/kotlin/fixture/notebook/NotebookHost.kt (100%) rename {ksp-fixtures => python-multiplatform-compose/fixtures}/notebook-e2e/src/desktopTest/kotlin/fixture/notebook/NotebookPracticeTest.kt (100%) rename {ksp-fixtures => python-multiplatform-compose/fixtures}/notebook-e2e/src/desktopTest/kotlin/fixture/notebook/NotebookRootTest.kt (100%) rename {ksp-fixtures => python-multiplatform-compose/fixtures}/notebook-e2e/src/desktopTest/kotlin/fixture/notebook/NotebookTextFieldTest.kt (100%) rename {ksp-fixtures => python-multiplatform-compose/fixtures}/notebook-e2e/src/desktopTest/python/main.py (100%) rename {ksp-fixtures => python-multiplatform-gradle-plugin/fixtures}/artifact-valueclass/build.gradle.kts (90%) rename {ksp-fixtures => python-multiplatform-gradle-plugin/fixtures}/artifact-valueclass/src/main/kotlin/fixture/valueclass/Meters.kt (82%) rename {ksp-fixtures => python-multiplatform-gradle-plugin/fixtures}/artifact/build.gradle.kts (96%) rename {ksp-fixtures => python-multiplatform-gradle-plugin/fixtures}/artifact/src/commonMain/kotlin/fixture/artifact/OwnDeclarations.kt (100%) rename {ksp-fixtures => python-multiplatform-gradle-plugin/fixtures}/artifact/src/desktopMain/kotlin/fixture/artifact/ComposeSeed.kt (100%) rename {ksp-fixtures => python-multiplatform-gradle-plugin/fixtures}/artifact/src/desktopTest/kotlin/fixture/artifact/PythonxModules.kt (100%) rename {ksp-fixtures => python-multiplatform-gradle-plugin/fixtures}/artifact/src/desktopTest/kotlin/fixture/artifact/StubSignatureAgreesWithRuntimeTest.kt (100%) rename {ksp-fixtures => python-multiplatform-gradle-plugin/fixtures}/artifact/src/desktopTest/kotlin/fixture/artifact/WalkedArtifactCallbackTest.kt (99%) rename {ksp-fixtures => python-multiplatform-gradle-plugin/fixtures}/artifact/src/desktopTest/kotlin/fixture/artifact/WalkedArtifactComposeModifierTest.kt (100%) rename {ksp-fixtures => python-multiplatform-gradle-plugin/fixtures}/artifact/src/desktopTest/kotlin/fixture/artifact/WalkedArtifactDefaultOmissionTest.kt (100%) rename {ksp-fixtures => python-multiplatform-gradle-plugin/fixtures}/artifact/src/desktopTest/kotlin/fixture/artifact/WalkedArtifactPythonImportTest.kt (98%) rename {ksp-fixtures => python-multiplatform-gradle-plugin/fixtures}/artifact/src/desktopTest/kotlin/fixture/artifact/WalkedArtifactStubTest.kt (100%) rename {ksp-fixtures => python-multiplatform-gradle-plugin/fixtures}/artifact/src/desktopTest/kotlin/fixture/artifact/WalkedArtifactTableTest.kt (95%) rename {ksp-fixtures => python-multiplatform-gradle-plugin/fixtures}/artifact/src/desktopTest/kotlin/fixture/artifact/WalkedArtifactValueClassBoxTest.kt (100%) rename {ksp-fixtures => python-multiplatform-gradle-plugin/fixtures}/klib-artifact/build.gradle.kts (90%) rename {ksp-fixtures => python-multiplatform-gradle-plugin/fixtures}/klib-artifact/src/androidNativeArm64Test/kotlin/fixture/artifact/WalkedKlibArtifactPythonImportTest.kt (97%) rename {ksp-fixtures => python-multiplatform-gradle-plugin/fixtures}/klib-artifact/src/androidNativeArm64Test/kotlin/fixture/artifact/WalkedKlibArtifactTableTest.kt (97%) rename {ksp-fixtures => python-multiplatform-gradle-plugin/fixtures}/klib-artifact/src/commonMain/kotlin/fixture/artifact/OwnDeclarations.kt (88%) rename {ksp-fixtures => python-multiplatform-ksp/fixtures}/android/build.gradle.kts (87%) rename {ksp-fixtures => python-multiplatform-ksp/fixtures}/android/src/androidInstrumentedTest/kotlin/fixture/android/GeneratedAndroidTableTest.kt (93%) rename {ksp-fixtures => python-multiplatform-ksp/fixtures}/android/src/androidMain/kotlin/fixture/android/AndroidFunctions.kt (84%) rename {ksp-fixtures => python-multiplatform-ksp/fixtures}/android/src/androidUnitTest/kotlin/fixture/android/GeneratedAndroidTableTest.kt (96%) rename {ksp-fixtures => python-multiplatform-ksp/fixtures}/android/src/commonMain/kotlin/fixture/android/TableInstall.kt (92%) rename {ksp-fixtures => python-multiplatform-ksp/fixtures}/app/build.gradle.kts (99%) rename {ksp-fixtures => python-multiplatform-ksp/fixtures}/app/src/androidNativeArm64Test/kotlin/fixture/app/NativeSmokeTest.kt (100%) rename {ksp-fixtures => python-multiplatform-ksp/fixtures}/app/src/androidNativeMain/kotlin/fixture/app/NativeInstall.kt (87%) rename {ksp-fixtures => python-multiplatform-ksp/fixtures}/app/src/commonMain/kotlin/fixture/app/AppExtras.kt (100%) rename {ksp-fixtures => python-multiplatform-ksp/fixtures}/app/src/commonMain/kotlin/fixture/app/AppFunctions.kt (100%) rename {ksp-fixtures => python-multiplatform-ksp/fixtures}/app/src/commonMain/kotlin/fixture/app/ArgumentRelease.kt (100%) rename {ksp-fixtures => python-multiplatform-ksp/fixtures}/app/src/commonMain/kotlin/fixture/app/TableInstall.kt (80%) rename {ksp-fixtures => python-multiplatform-ksp/fixtures}/app/src/commonMain/kotlin/fixture/app/TypedPythonBridge.kt (100%) rename {ksp-fixtures => python-multiplatform-ksp/fixtures}/app/src/desktopTest/kotlin/fixture/app/CommonInstallTest.kt (95%) rename {ksp-fixtures => python-multiplatform-ksp/fixtures}/app/src/desktopTest/kotlin/fixture/app/GeneratedDeclarationKindsTest.kt (99%) rename {ksp-fixtures => python-multiplatform-ksp/fixtures}/app/src/desktopTest/kotlin/fixture/app/GeneratedStaticPropertyProxyTest.kt (100%) rename {ksp-fixtures => python-multiplatform-ksp/fixtures}/app/src/desktopTest/kotlin/fixture/app/GeneratedSuspendTest.kt (99%) rename {ksp-fixtures => python-multiplatform-ksp/fixtures}/app/src/desktopTest/kotlin/fixture/app/GeneratedTableTest.kt (96%) rename {ksp-fixtures => python-multiplatform-ksp/fixtures}/app/src/desktopTest/kotlin/fixture/app/KspClassResultProxyTest.kt (100%) rename {ksp-fixtures => python-multiplatform-ksp/fixtures}/app/src/desktopTest/kotlin/fixture/app/ProxyObjectArgumentTest.kt (100%) rename {ksp-fixtures => python-multiplatform-ksp/fixtures}/app/src/desktopTest/kotlin/fixture/app/PyObjectArgumentReleaseTest.kt (100%) rename {ksp-fixtures => python-multiplatform-ksp/fixtures}/app/src/desktopTest/kotlin/fixture/app/RefHolderCycleCollectionTest.kt (100%) rename {ksp-fixtures => python-multiplatform-ksp/fixtures}/app/src/desktopTest/kotlin/fixture/app/TypedPythonKotlinCallTest.kt (99%) rename {ksp-fixtures => python-multiplatform-ksp/fixtures}/app/src/desktopTest/typedpython/fixture/__init__.pyi (100%) rename {ksp-fixtures => python-multiplatform-ksp/fixtures}/app/src/desktopTest/typedpython/fixture/app/__init__.pyi (86%) rename {ksp-fixtures => python-multiplatform-ksp/fixtures}/app/src/desktopTest/typedpython/tp_kotlin_bridge.py (100%) rename {ksp-fixtures => python-multiplatform-ksp/fixtures}/app/typedpython/build_bridge.py (97%) rename {ksp-fixtures => python-multiplatform-ksp/fixtures}/library/build.gradle.kts (93%) rename {ksp-fixtures => python-multiplatform-ksp/fixtures}/library/src/commonMain/kotlin/fixture/library/Declarations.kt (97%) rename {ksp-fixtures => python-multiplatform-ksp/fixtures}/library/src/commonMain/kotlin/fixture/library/LibFunctions.kt (100%) rename {ksp-fixtures => python-multiplatform-ksp/fixtures}/library/src/commonMain/kotlin/fixture/library/Suspending.kt (100%) diff --git a/.github/scripts/stubs/check-stubs.sh b/.github/scripts/stubs/check-stubs.sh index 01cfe30a9..5e74fa0f8 100755 --- a/.github/scripts/stubs/check-stubs.sh +++ b/.github/scripts/stubs/check-stubs.sh @@ -4,7 +4,7 @@ # .github/scripts/stubs/check-stubs.sh [venv-dir] # # is what `generatePythonStubs` wrote, e.g. -# ksp-fixtures/compose/build/generated/pythonStubs/desktopMain +# python-multiplatform-compose/fixtures/compose/build/generated/pythonStubs/desktopMain # The venv defaults to /.tmp/stubs-venv (git-ignored) and is created on first use. set -euo pipefail diff --git a/.github/workflows/stubs.yml b/.github/workflows/stubs.yml index f7c28305f..fed91fe9d 100644 --- a/.github/workflows/stubs.yml +++ b/.github/workflows/stubs.yml @@ -16,7 +16,7 @@ on: branches: [ "develop" ] paths: - "python-multiplatform-gradle-plugin/**" - - "ksp-fixtures/compose/**" + - "python-multiplatform-compose/fixtures/compose/**" - ".github/scripts/stubs/**" - "gradle/libs.versions.toml" - ".github/workflows/stubs.yml" @@ -52,10 +52,10 @@ jobs: python-version: '3.13' - name: Generate the stubs over the Compose jars - run: ./gradlew :ksp-fixtures:compose:generatePythonStubs --console=plain + run: ./gradlew :python-multiplatform-compose:fixtures:compose:generatePythonStubs --console=plain - name: Type-check a consumer against them (mypy) - run: .github/scripts/stubs/check-stubs.sh ksp-fixtures/compose/build/generated/pythonStubs/desktopMain + run: .github/scripts/stubs/check-stubs.sh python-multiplatform-compose/fixtures/compose/build/generated/pythonStubs/desktopMain - name: Assemble the artifact run: | @@ -65,7 +65,7 @@ jobs: out=build/kotlin-stubs rm -rf "$out" mkdir -p "$out" - cp -R ksp-fixtures/compose/build/generated/pythonStubs/desktopMain/. "$out/" + cp -R python-multiplatform-compose/fixtures/compose/build/generated/pythonStubs/desktopMain/. "$out/" cat > "$out/README.md" <\`, or the @@ -129,11 +129,11 @@ jobs: python-version: '3.13' - name: Generate the stubs over the Compose jars - run: ./gradlew :ksp-fixtures:compose:generatePythonStubs --console=plain + run: ./gradlew :python-multiplatform-compose:fixtures:compose:generatePythonStubs --console=plain - name: No two stub paths are equal under case folding run: | - python3 - ksp-fixtures/compose/build/generated/pythonStubs/desktopMain <<'PY' + python3 - python-multiplatform-compose/fixtures/compose/build/generated/pythonStubs/desktopMain <<'PY' import os, sys seen = {} for root, dirs, files in os.walk(sys.argv[1]): @@ -146,4 +146,4 @@ jobs: PY - name: Type-check a consumer against them (mypy) - run: .github/scripts/stubs/check-stubs.sh ksp-fixtures/compose/build/generated/pythonStubs/desktopMain + run: .github/scripts/stubs/check-stubs.sh python-multiplatform-compose/fixtures/compose/build/generated/pythonStubs/desktopMain diff --git a/.github/workflows/typedpython.yml b/.github/workflows/typedpython.yml index c03f0ea4d..ee436ba35 100644 --- a/.github/workflows/typedpython.yml +++ b/.github/workflows/typedpython.yml @@ -5,10 +5,10 @@ name: TypedPython CI on: push: branches: [ "develop", "main" ] - paths: [ "python-multiplatform-ksp/**", "ksp-fixtures/app/**", ".github/workflows/typedpython.yml" ] + paths: [ "python-multiplatform-ksp/**", "python-multiplatform-ksp/fixtures/app/**", ".github/workflows/typedpython.yml" ] pull_request: branches: [ "develop", "main" ] - paths: [ "python-multiplatform-ksp/**", "ksp-fixtures/app/**", ".github/workflows/typedpython.yml" ] + paths: [ "python-multiplatform-ksp/**", "python-multiplatform-ksp/fixtures/app/**", ".github/workflows/typedpython.yml" ] concurrency: # A newer push to the same ref supersedes this run; frees the shared macOS runners. @@ -86,7 +86,7 @@ jobs: # fixture's desktop JVM. buildTypedPythonBridge needs a host Python with pyrefly; without one the # four TypedPythonKotlinCallTest tests skip. Locally that is allowed; here a skip fails the job. # macOS only: elsewhere the JVM does not load libpython with global symbols, so the - # dynamic_lookup extension cannot resolve the C API (ksp-fixtures/app/build.gradle.kts). + # dynamic_lookup extension cannot resolve the C API (python-multiplatform-ksp/fixtures/app/build.gradle.kts). name: TypedPython from Kotlin, app fixture (macos-latest) runs-on: macos-latest steps: @@ -108,15 +108,15 @@ jobs: - name: App fixture tests run: | - rm -rf ksp-fixtures/app/build/test-results/desktopTest - ./gradlew :ksp-fixtures:app:desktopTest --rerun --console=plain \ + rm -rf python-multiplatform-ksp/fixtures/app/build/test-results/desktopTest + ./gradlew :python-multiplatform-ksp:fixtures:app:desktopTest --rerun --console=plain \ -PtypedpythonPython="$PWD/python-multiplatform-ksp/.venv/bin/python" - name: The TypedPython tests ran (none skipped) run: | python3 - <<'PY' import glob, sys, xml.etree.ElementTree as ET - cases = [c for p in glob.glob("ksp-fixtures/app/build/test-results/desktopTest/*.xml") + cases = [c for p in glob.glob("python-multiplatform-ksp/fixtures/app/build/test-results/desktopTest/*.xml") for c in ET.parse(p).getroot().iter("testcase") if c.get("classname") == "fixture.app.TypedPythonKotlinCallTest"] skipped = [c.get("name") for c in cases if c.find("skipped") is not None] diff --git a/AGENTS.md b/AGENTS.md index d0b53d728..0c2002030 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -184,7 +184,7 @@ interoperability in both directions: | `python-multiplatform/` | The library: FFI layer, object model, upcall runtime | | `python-multiplatform-ksp/` | KSP processor that generates the upcall table from Kotlin sources | | `python-multiplatform-gradle-plugin/` | Gradle plugin: `PYTHONHOME` staging, artifact walker (binds prebuilt jars/klibs), `.pyi` stub generation | -| `ksp-fixtures/` | Consumer modules that exercise what the generators produce | +| `/fixtures/` | Consumer modules that exercise what the generators produce, each inside the module whose output it checks (`python-multiplatform-ksp`, `python-multiplatform-gradle-plugin`, `python-multiplatform-compose`) | | `sample/` | Compose Multiplatform demo app (desktop, Android, iOS, wasmJs, GraalVM native image) | | `binary/` | Source archives of per-platform CPython distributions | | `python_for_kotlin_binding.mermaid` | User-authored sketch of the object model (see rule 14) | @@ -296,16 +296,22 @@ Rule 5 applies. In addition: checking only iOS lets androidNative break unnoticed (an `actual` placed only in `iosMain` once did, for days). -### The generator consumers: `ksp-fixtures` +### The generator consumers: `/fixtures` `:python-multiplatform-gradle-plugin:test` alone does not verify the code that **uses** what the generators emit. Run each fixture module as a **separate** Gradle invocation (rule 8): | Task | Catches | |---|---| -| `:ksp-fixtures:app:desktopTest` | Upcall and proxy runtime | -| `:ksp-fixtures:compose:desktopTest` | Compose bindings and render proofs | -| `:ksp-fixtures:artifact:desktopTest` | Artifact walker and `.pyi` stubs | +| `:python-multiplatform-ksp:fixtures:app:desktopTest` | Upcall and proxy runtime | +| `:python-multiplatform-compose:fixtures:compose:desktopTest` | Compose bindings and render proofs | +| `:python-multiplatform-gradle-plugin-fixtures:artifact:desktopTest` | Artifact walker and `.pyi` stubs | + +Where each lives: `python-multiplatform-ksp/fixtures/{library,app,android}` (KSP processor), +`python-multiplatform-gradle-plugin/fixtures/{artifact,artifact-valueclass,klib-artifact}` (artifact +walker; the plugin is an included build, so their Gradle path is +`:python-multiplatform-gradle-plugin-fixtures:`) and +`python-multiplatform-compose/fixtures/{compose,notebook-e2e}` (Compose host). Forgetting `artifact` has put red tests on `develop` twice; plugin unit tests cannot see them. Running the three in one invocation once hid 24 failures caused by an ordering dependency. diff --git a/PROJECT.md b/PROJECT.md index 267eefc8d..872ae70bd 100644 --- a/PROJECT.md +++ b/PROJECT.md @@ -48,7 +48,7 @@ Kotlin Multiplatform 에 CPython 을 임베딩해 **Kotlin 과 Python 이 서로 | `python-multiplatform/` | 라이브러리, FFI 계층(`python/native/ffi/`), 객체 모델(`python/multiplatform/ffi/`), 업콜 런타임 | | `python-multiplatform-ksp/` | 업콜 테이블을 생성하는 KSP 프로세서 | | `python-multiplatform-gradle-plugin/` | `stagePythonHome`, 아티팩트 워커(빌드된 jar/klib 바인딩), `.pyi` 스텁 생성 | -| `ksp-fixtures/` | 생성기 산출물을 실제로 쓰는 소비자 모듈 (`app`, `compose`, `artifact`, …) | +| `python-multiplatform-ksp/fixtures/`, `python-multiplatform-gradle-plugin/fixtures/`, `python-multiplatform-compose/fixtures/` | 생성기 산출물을 실제로 쓰는 소비자 모듈, 검증 대상 모듈 안에 둔다 (`app`, `compose`, `artifact`, ...) | | `sample/` | Compose Multiplatform 데모 앱 (데스크톱·Android·iOS·wasmJs·GraalVM 네이티브 이미지) | | `python_for_kotlin_binding.mermaid` | 사용자가 그린 객체 모델 스케치 (확정 스펙 아님) | | `docs/` | `INTENT.md`, `SPEC.md`, `design/`, `platforms/`, `investigations/`, `roadmap/`, `guide/`, `locale/` | @@ -68,8 +68,8 @@ Kotlin Multiplatform 에 CPython 을 임베딩해 **Kotlin 과 Python 이 서로 - 컴파일 확인은 세 타깃: `compileKotlinAndroidNativeArm64`(기본 루프), `compileKotlinIosSimulatorArm64`, `compileKotlinDesktop`. **androidNative 를 빼먹지 않는다**, `nativeMain` 을 iOS 와 공유한다. -- 생성기 소비자 검증은 **모듈마다 따로**: `:ksp-fixtures:app:desktopTest`, - `:ksp-fixtures:compose:desktopTest`, `:ksp-fixtures:artifact:desktopTest`. +- 생성기 소비자 검증은 **모듈마다 따로**: `:python-multiplatform-ksp:fixtures:app:desktopTest`, + `:python-multiplatform-compose:fixtures:compose:desktopTest`, `:python-multiplatform-gradle-plugin-fixtures:artifact:desktopTest`. - 결과는 `build/test-results//*.xml` 을 지우고 `--rerun` 으로 다시 돌려 센다. - 종료 코드는 파이프로 읽지 않는다. 상세 규정은 `AGENTS.md` §15. - CPython 은 저장소에 벤더링하지 않는다. Gradle 이 플랫폼별로 내려받아 검증·추출한다 diff --git a/docs/SPEC.md b/docs/SPEC.md index b21edbb33..3002fb15f 100644 --- a/docs/SPEC.md +++ b/docs/SPEC.md @@ -191,7 +191,7 @@ All in `PM/commonTest`, so they run wherever the interpreter loads. - **M-3** Reference cycles that cross the boundary (Python → Kotlin proxy → Python) are collected by Python's cyclic GC, including on threads CPython created and for Python subclasses of proxies. `Status: implemented` on desktop (`PM/desktopTest/.../ref/CycleCollectionTest.kt`, - `ksp-fixtures/app/.../RefHolderCycleCollectionTest.kt`); `partial` elsewhere, tests exist for + `python-multiplatform-ksp/fixtures/app/.../RefHolderCycleCollectionTest.kt`); `partial` elsewhere, tests exist for native, Android and wasm (`PM/nativeTest/.../CycleCollectionTest.kt`, `PM/androidInstrumentedTest/.../CycleCollectionTest.kt`, `PM/wasmJsTest/.../WasmCycleCollectionTest.kt`) but `docs/roadmap/ROADMAP.md` §7 records remaining per-target gaps. @@ -205,7 +205,7 @@ All in `PM/commonTest`, so they run wherever the interpreter loads. declaration in a module; `@PythonInternal` excludes a class or member. Fragments from several modules aggregate; a name claimed twice is an error. No runtime reflection is used. `Status: implemented`, `PM/commonTest/.../reflection/UpcallTableTest.kt`, - `ksp-fixtures/app/src/desktopTest/.../GeneratedTableTest.kt`, `python-multiplatform-ksp/src/test/.../SourceRenderingTest.kt`. + `python-multiplatform-ksp/fixtures/app/src/desktopTest/.../GeneratedTableTest.kt`, `python-multiplatform-ksp/src/test/.../SourceRenderingTest.kt`. - **U-2** One entry point per platform marshals arguments (int, float, bool, str, bytes with NUL, objects), turns a Kotlin exception into a Python exception and a `Unit` return into `None`. `Status: implemented`, `PM/commonTest/.../UpcallEntryTest.kt`, `UpcallTrampolineTest.kt`, @@ -213,9 +213,9 @@ All in `PM/commonTest`, so they run wherever the interpreter loads. - **U-3** Generated Python proxies let Python write ordinary Python against Kotlin: construct a class, call methods, get/set properties (a `private set` is read-only), read companion / static members. A Kotlin package is importable under its own name. `Status: implemented` on desktop, - `PM/commonTest/.../upcall/PythonProxyInstallTest.kt`, `ksp-fixtures/app/.../GeneratedDeclarationKindsTest.kt`, - `GeneratedStaticPropertyProxyTest.kt`; `partial` elsewhere, only `ksp-fixtures/app/.../NativeSmokeTest.kt` - (androidNative) and `ksp-fixtures/android/.../GeneratedAndroidTableTest.kt` run outside desktop. + `PM/commonTest/.../upcall/PythonProxyInstallTest.kt`, `python-multiplatform-ksp/fixtures/app/.../GeneratedDeclarationKindsTest.kt`, + `GeneratedStaticPropertyProxyTest.kt`; `partial` elsewhere, only `python-multiplatform-ksp/fixtures/app/.../NativeSmokeTest.kt` + (androidNative) and `python-multiplatform-ksp/fixtures/android/.../GeneratedAndroidTableTest.kt` run outside desktop. - **U-4** Declaration kinds: objects, companions, interfaces (not constructible), enum entries as statics, abstract classes (no constructor), nested classes. Not exposed: annotation classes, generic declarations, data-class synthetics. `Status: implemented` on desktop, @@ -224,7 +224,7 @@ All in `PM/commonTest`, so they run wherever the interpreter loads. suspends completes without a Future; cancelling the Python future cancels the Kotlin coroutine. `Status: implemented` on desktop and Kotlin/Native, `PM/desktopTest/.../upcall/AsyncUpcallDeliveryTest.kt`, `AsyncUpcallCancellationTest.kt`, `AsyncUpcallEarlyCancellationTest.kt`, `PM/nativeTest/.../AsyncUpcallNative*Test.kt`, - `ksp-fixtures/app/.../GeneratedSuspendTest.kt`; `planned` on wasm (no threads). + `python-multiplatform-ksp/fixtures/app/.../GeneratedSuspendTest.kt`; `planned` on wasm (no threads). - **U-6** Upcalls work in a GraalVM native image (desktop). `Status: implemented` with manual verification, procedure and record in `docs/platforms/graal-native-image-verification.md` (`:sample:nativeCompile`, Liberica NIK), guarded automatically by `ReachabilityMetadataTest.kt` (C-2). @@ -233,7 +233,7 @@ All in `PM/commonTest`, so they run wherever the interpreter loads. (`Modifier.padding(16).size(24)`). `Status: partial`, asserted against a hand-written, Compose-shaped table (`PM/commonTest/.../pythonx/PythonxAdapterTest.kt` `anExtensionIsAMethodOnItsReceiverAndTheChainComposes`) and against the real Compose jars through - the artifact walker (`ksp-fixtures/artifact/.../WalkedArtifactComposeModifierTest.kt`); not + the artifact walker (`python-multiplatform-gradle-plugin/fixtures/artifact/.../WalkedArtifactComposeModifierTest.kt`); not asserted for KSP-generated proxies. - **U-8** A function on a Kotlin-named module carries Kotlin's surface: the Kotlin declaration name, keyword arguments by **Kotlin parameter names**, Kotlin defaults for omitted parameters, overload sets @@ -257,7 +257,7 @@ All in `PM/commonTest`, so they run wherever the interpreter loads. companion's constants and functions. One rule with the class case (#73): a Kotlin name that is a constructor or factory is what calling it does, whatever else lives under that name. `Status: implemented` on desktop, - `PM/desktopTest/.../pythonx/KotlinNamedSurfaceTest.kt`, `BinderNamespaceTest.kt`, `ksp-fixtures/compose/.../KotlinSignatureMetadataTest.kt`. + `PM/desktopTest/.../pythonx/KotlinNamedSurfaceTest.kt`, `BinderNamespaceTest.kt`, `python-multiplatform-compose/fixtures/compose/.../KotlinSignatureMetadataTest.kt`. - **U-9** A Pythonic package can serve extra member names on a Kotlin proxy through one hook, `python_multiplatform.binding.add_member_resolver(fn)`, `fn(kotlin_type_name, requested_name, kotlin_member_names) -> kotlin_name | (kotlin_name, keyword_map) | None`, asked when no Kotlin member @@ -268,7 +268,7 @@ All in `PM/commonTest`, so they run wherever the interpreter loads. `AttributeError`. Aliases are cached in the registry, not written on the proxy class (`dir()` stays Kotlin-only). Contract in `KotlinSurface.kt`'s KDoc. `Status: implemented` on desktop, `PM/desktopTest/.../pythonx/MemberResolverTest.kt`, - `ksp-fixtures/compose/.../MemberResolverComposeTest.kt`. + `python-multiplatform-compose/fixtures/compose/.../MemberResolverComposeTest.kt`. A resolver (or anything else) reads a member's declaration rows from the receiver type alone with `python_multiplatform.describe_member(kotlin_type_name, kotlin_member_name)`: `describe()`'s tuple-of-dicts for every extension overload or the property getter/setter that type's proxy serves @@ -289,14 +289,14 @@ All in `PM/commonTest`, so they run wherever the interpreter loads. function result, or a callback argument, gives the Python scalar for a Kotlin `Int`/`Long`/`Short`/`Byte` (`int`), `Double`/`Float` (`float`), `Boolean` (`bool`), `String`/`Char` (`str`), and a proxy for any other Kotlin object. `Status: implemented`, - `PM/commonTest/.../pythonx/PythonxPropertyTest.kt`, `ksp-fixtures/compose/.../PythonAppViewRenderTest.kt`, + `PM/commonTest/.../pythonx/PythonxPropertyTest.kt`, `python-multiplatform-compose/fixtures/compose/.../PythonAppViewRenderTest.kt`, `AnySlotScalarRenderTest.kt`, `MaterialIconsRenderTest.kt`. - **U-11** A KSP-bound function, method or property whose declared return type is a Kotlin class that has a generated proxy returns an instance of **that class's proxy** (#94), not a generic owner: its methods and properties work and `isinstance(result, TheClass)` holds. The class is found by the declared return type's Kotlin name; a return type with no generated proxy stays a generic owner object. The result's ownership is the same as for any owned result. `Status: implemented`, - `ksp-fixtures/app/.../KspClassResultProxyTest.kt` (red until #94 lands). + `python-multiplatform-ksp/fixtures/app/.../KspClassResultProxyTest.kt` (red until #94 lands). - **U-12** Pythonic names (#131). On a Kotlin-named module every declaration, proxy member and keyword parameter is reachable by its Kotlin name **and** by its Pythonic name; the Kotlin name keeps working. The namespace is never converted: `androidx.compose.material3` is a module under exactly @@ -338,7 +338,7 @@ All in `PM/commonTest`, so they run wherever the interpreter loads. `PythonxAdapterTest.kt` (`theNameRuleConvertsKotlinToPythonAndEitherSpellingReachesOneDeclaration`, `everyBoundNameSurvivesTheRoundTripThroughItsPythonicName`), `PM/desktopTest/.../pythonx/KotlinNamedSurfaceTest.kt`, `PythonxComposeCompatibilityTest.kt`, `MemberResolverTest.kt`, and the Compose render tests written - with Pythonic names (`ksp-fixtures/compose/.../M3ProofRenderTest.kt`, `CallbackDrivenRenderTest.kt`, + with Pythonic names (`python-multiplatform-compose/fixtures/compose/.../M3ProofRenderTest.kt`, `CallbackDrivenRenderTest.kt`, `TextFieldStateRenderTest.kt`). ## 6. Binding prebuilt libraries (Gradle plugin) @@ -347,7 +347,7 @@ All in `PM/commonTest`, so they run wherever the interpreter loads. overloads suffixed, multi-file facades reachable) by generating Kotlin source that `kotlinc` compiles, never by JVM name lookup. KSP and the walker share one Python namespace. `Status: implemented` on desktop, `GP/artifact/ArtifactScannerTest.kt`, - `ksp-fixtures/artifact/.../WalkedArtifactTableTest.kt`, `WalkedArtifactPythonImportTest.kt`. + `python-multiplatform-gradle-plugin/fixtures/artifact/.../WalkedArtifactTableTest.kt`, `WalkedArtifactPythonImportTest.kt`. Beside functions and object constants it binds (#38): generic functions whose type parameters are unbounded and not reified, each read as `kotlin.Any?` and written out at the call (`mutableStateOf(...)`), a bounded or reified one still declined; member properties of @@ -368,27 +368,27 @@ All in `PM/commonTest`, so they run wherever the interpreter loads. getter or an object constant, crosses as a Python `str` (the generated body returns Kotlin's `toString()` of it; `null` stays `None` for `CharSequence?`); a `CharSequence` parameter is still declined (#73). `Status: implemented`, `GP/artifact/TextStateBindingTest.kt`, - `ksp-fixtures/compose/.../TextFieldStateRenderTest.kt`. + `python-multiplatform-compose/fixtures/compose/.../TextFieldStateRenderTest.kt`. - **B-2** The walker on **klibs** (Kotlin/Native libraries). `Status: partial`, - `GP/artifact/KlibScannerTest.kt` and `ksp-fixtures/klib-artifact` assert that the scanned klib's + `GP/artifact/KlibScannerTest.kt` and `python-multiplatform-gradle-plugin/fixtures/klib-artifact` assert that the scanned klib's declarations are declined with reasons; no klib declaration is bound at run time yet. - **B-3** Default arguments can be omitted from Python (a call per subset of defaulted parameters, ambiguous omissions refused). `Status: implemented`, `GP/artifact/DefaultOmissionTest.kt`, - `ksp-fixtures/artifact/.../WalkedArtifactDefaultOmissionTest.kt`, `PM/commonTest/.../PythonxDefaultsTest.kt`. + `python-multiplatform-gradle-plugin/fixtures/artifact/.../WalkedArtifactDefaultOmissionTest.kt`, `PM/commonTest/.../PythonxDefaultsTest.kt`. - **B-4** Value classes round-trip; only allow-listed ones (e.g. `Dp`) may be written as their raw primitive. `Status: implemented`, `GP/artifact/ComposableValueClassSlotTest.kt`, `WalkedArtifactPythonImportTest.kt`. A value class is opened as its raw primitive only when both its constructor and its underlying property are public; otherwise (`TextUnitType`) it crosses as a boxed handle, so a parameter of it takes the boxed value of its own class (`TextUnit(30, TextUnitType.Sp)`) and a raw number is refused (#168, - `ksp-fixtures/artifact/.../WalkedArtifactValueClassBoxTest.kt`). + `python-multiplatform-gradle-plugin/fixtures/artifact/.../WalkedArtifactValueClassBoxTest.kt`). - **B-5** Python callables can fill Kotlin function-typed parameters (arity and callability checked). - `Status: partial`, `ksp-fixtures/artifact/.../WalkedArtifactCallbackTest.kt`; a value-returning slot + `Status: partial`, `python-multiplatform-gradle-plugin/fixtures/artifact/.../WalkedArtifactCallbackTest.kt`; a value-returning slot (`() -> Float`) does not yet accept a Python callable (`M3ProofRenderTest.kt` `aValueReturningFunctionSlotDoesNotYetAcceptAPythonCallable`). - **B-6** `@Composable` functions are callable from Python inside a composition; a Python click reaches a Kotlin callback and the redraw shows it. `Status: implemented` on desktop, - `ksp-fixtures/compose/src/desktopTest/` (`ComposableRenderTest.kt`, `M3ProofRenderTest.kt`, + `python-multiplatform-compose/fixtures/compose/src/desktopTest/` (`ComposableRenderTest.kt`, `M3ProofRenderTest.kt`, `CallbackDrivenRenderTest.kt`, pointer/drag render tests), `GP/artifact/ComposableBindingTest.kt`; `planned` on Android, iOS and wasm. - **B-8** A host draws a Python-declared application root with @@ -398,7 +398,7 @@ All in `PM/commonTest`, so they run wherever the interpreter loads. callable. The state is read inside the composition, so a Python write into it replaces the root on the next frame with no host call; Python callables a root passed into composables are released when that root is replaced or the composition is disposed. The entry point names no library. - `Status: implemented` on desktop, `ksp-fixtures/compose/.../PythonAppViewRenderTest.kt`; the module + `Status: implemented` on desktop, `python-multiplatform-compose/fixtures/compose/.../PythonAppViewRenderTest.kt`; the module compiles for Android, nothing runs there yet. - **B-9** A Python root keeps state across the recreation of its composition with `python.multiplatform.compose.rememberSaveableWrapper(initial)` (the pycomposeui function of that name), @@ -408,7 +408,7 @@ All in `PM/commonTest`, so they run wherever the interpreter loads. `SaveableStateRegistry.performSave()` and a new composition over a registry built from the saved map; without a registry the new composition starts at `initial`. Any other value (a Python `list`) raises an error that names its type. `Status: implemented` on desktop (#174), - `ksp-fixtures/compose/.../RememberSaveableRenderTest.kt`. + `python-multiplatform-compose/fixtures/compose/.../RememberSaveableRenderTest.kt`. - **B-7** The plugin generates `.pyi` stubs for the Kotlin-named modules only, under Kotlin names plus their U-12 Pythonic aliases (`fill_max_width = fillMaxWidth` beside each module `def`, a second `ClassVar` or `@property` on a receiver's class, a second member of a callable module), parameters @@ -422,7 +422,7 @@ All in `PM/commonTest`, so they run wherever the interpreter loads. `@overload`ed under its base name in table-key order; a required parameter after a defaulted one is keyword-only like `inspect.signature`. It emits nothing under `pythonx` and converts no namespace. `Status: partial` - `GP/stubs/PyiRenderingTest.kt`, `GP/stubs/TypedStubTest.kt`, `GP/stubs/KotlinNamesOnlyStubTest.kt`, - `ksp-fixtures/artifact/.../WalkedArtifactStubTest.kt`, `.../StubSignatureAgreesWithRuntimeTest.kt`, + `python-multiplatform-gradle-plugin/fixtures/artifact/.../WalkedArtifactStubTest.kt`, `.../StubSignatureAgreesWithRuntimeTest.kt`, `GP/stubs/CompanionFactoryStubTest.kt` (#78: a name that is both a function and a Kotlin-named module is stubbed in its parent package as one attribute whose type has `__call__` (the function or its `@overload`s) and the module's constants and functions as members, never as a bare `def`, which @@ -433,7 +433,7 @@ All in `PM/commonTest`, so they run wherever the interpreter loads. docstring carries its table key after `Kotlin constructor: `; its `__`-suffixed table-key spellings stay module functions; a value class bound as its primitive keeps its constructor as a module function returning the primitive (#73, `GP/artifact/TextStateBindingTest.kt`, - `ksp-fixtures/artifact/.../WalkedArtifactStubTest.kt`). In Python the class name is the constructor, + `python-multiplatform-gradle-plugin/fixtures/artifact/.../WalkedArtifactStubTest.kt`). In Python the class name is the constructor, as `Typography(...)` already was (`M3ProofRenderTest.kt`). A property is a `@property` (with a setter for a `var`) of its receiver's stub class, its docstring carrying its table key after `Kotlin property: `; where that class has no stub, a comment with the same marker says so (`GP/stubs/PropertyStubTest.kt`). An object constant is annotated with its @@ -467,7 +467,7 @@ All in `PM/commonTest`, so they run wherever the interpreter loads. Hangul input-method composition with no Python function started and the root not rerun, holds the composing range in Compose, and the notebook reads the committed text; a write from Python outside the composition reaches the screen within four frames. Notebook content with no decided or Kotlin - counterpart is listed, not imitated. `Status: implemented` on desktop: `ksp-fixtures/notebook-e2e/` (20 tests, and a + counterpart is listed, not imitated. `Status: implemented` on desktop: `python-multiplatform-compose/fixtures/notebook-e2e/` (20 tests, and a README with the cell map, the wheel commands and the gaps), 20 passed, 0 failed against the pythonx-compose `develop` wheel on 2026-10-04 (after #146, #168 and pythonx-compose #88), and again with the notebook's own state spelling (`main.App.messages.getValue()` / `setValue(...)`, #174) diff --git a/docs/design/architecture.md b/docs/design/architecture.md index cc85a8448..a2bbb3ca4 100644 --- a/docs/design/architecture.md +++ b/docs/design/architecture.md @@ -100,7 +100,7 @@ Kotlin 제약 때문에 다이어그램대로 갈 수 없던 지점들: ## 검증 수단 명령 목록과 어떤 소스셋을 덮는지는 AGENTS.md §15 가 기준이다 (`compileKotlinAndroidNativeArm64`, -`compileKotlinIosSimulatorArm64`, `compileKotlinDesktop`, 그리고 `ksp-fixtures` 세 모듈을 각각 따로). +`compileKotlinIosSimulatorArm64`, `compileKotlinDesktop`, 그리고 `fixtures/` 아래 세 모듈을 각각 따로). 테스트는 컴파일 검증만이 아니다, 데스크톱(`desktopTest`), iOS 시뮬레이터, 안드로이드 기기, wasm(Node) 에서 실제 CPython 을 구동하는 스위트가 있다 (SPEC §0 의 "Test path" 열). diff --git a/docs/design/ecosystem.md b/docs/design/ecosystem.md index acbf57f8a..1da450830 100644 --- a/docs/design/ecosystem.md +++ b/docs/design/ecosystem.md @@ -174,7 +174,7 @@ leave chaquopy until this is designed. *(read from source; not runtime-verified. smallest and most blocking item, and it is entirely inside this repository. > **Closed, see `docs/archive/pythonx-adapter-design.md` §5.6.** `Text('hi')` written in Python now draws -> through the real `androidx.compose.material3.Text` (`:ksp-fixtures:compose`'s +> through the real `androidx.compose.material3.Text` (`:python-multiplatform-compose:fixtures:compose`'s > `ComposableRenderTest`: 71 non-background pixels against 0 for an empty body). The paragraph above > is right that a *generated Kotlin* entry for a widget cannot compile, and that is not the route > taken: an artefact composable's call site is emitted as **bytecode**, with `$composer`, `$changed` @@ -239,7 +239,7 @@ This section documents the current state, language/build system/distribution art - **Gap to Goal** (status notes added 2026-10-03, read from code and SPEC, not re-run): - `@Composable`-capable callable shape: `ExposedCallable` typed `(Array) -> Any?` cannot invoke `@Composable` functions taking synthetic `$composer` / `$changed` parameters. Needs dedicated `CallableKind` or opt-in annotation handling., *Closed on desktop by bytecode thunks (`ComposableThunks.kt`), SPEC B-6; Android, iOS and wasm planned (SPEC N-2).* - Python-side `sys.meta_path` finder for lazy import resolution of Kotlin namespaces ~~(`pythonx.*` or FQCNs)~~ upon import., *Exists for Kotlin FQNs in `python_multiplatform.binding` (SPEC U-8). `pythonx.*` is not the binder's to resolve (`AGENTS.md` §12.2).* - - Opaque Kotlin object round-tripping for Compose `Composer` (`HandleTable` and `ObjectReference` exist, but runtime hand-off to Python needs verification)., *Done on desktop: one hand-written `@Composable` pushes the live composer as a handle onto the binding layer's stack (`push_composer`), proven by the `ksp-fixtures/compose` render tests.* + - Opaque Kotlin object round-tripping for Compose `Composer` (`HandleTable` and `ObjectReference` exist, but runtime hand-off to Python needs verification)., *Done on desktop: one hand-written `@Composable` pushes the live composer as a handle onto the binding layer's stack (`push_composer`), proven by the `python-multiplatform-compose/fixtures/compose` render tests.* - Lifetime and storage of Python callables passed into Kotlin across Compose recompositions (`content=lambda: ...`, `onClick=...`)., *Partly addressed: `PythonCallableScope` (`PythonCallables.kt`) holds the callables a composition hands to Kotlin and is closed by a Compose-side `RememberObserver` in `onForgotten`; several hand-written fixture wrappers (`pythonDraggable`, `pythonComposed`, the swipe/anchor wrappers) still leak their callbacks by design, pinned by `DraggableLeakTest`. Not verified here beyond reading the sources.* - Retire `stagePythonHome` in favor of `pypackpack`'s Python distribution management. - Hand `stageWasmBrowserRuntime` logic to `toolchain`. @@ -634,7 +634,7 @@ to at runtime with no JVM underneath, is the open question, not AndroidX. **Update, the walker now exists on one path, and both of those questions have answers.** `python-multiplatform-gradle-plugin` gained `generatePythonArtifactBindings`, and -`ksp-fixtures/artifact` carries a resolved `junit:junit:4.13.2` through ASM, a generated +`python-multiplatform-gradle-plugin/fixtures/artifact` carries a resolved `junit:junit:4.13.2` through ASM, a generated `FunctionTableFragment`, `UpcallTable` and `PythonProxySource` to `from junit.runner.Version import id` answering `"4.13.2"`. ROADMAP §16 records it in full; three things in it change what this section says: @@ -642,7 +642,7 @@ things in it change what this section says: - **The walker's fragments are a second aggregator (`ArtifactTable`), not additions to KSP's `FunctionTable`.** One `UpcallTable`, one fragment interface, one Python namespace, but `FunctionTable` keeps meaning "every module in this graph compiled with the processor", which is - what `ksp-fixtures/app` asserts and what a consumer's own table should not silently outgrow. + what `python-multiplatform-ksp/fixtures/app` asserts and what a consumer's own table should not silently outgrow. Install site: `UpcallTable.install(FunctionTable.fragments + ArtifactTable.fragments)`. - **ASM alone does not reach `androidx.compose.material3`.** It reaches Java statics and Kotlin `@JvmStatic`s. A Kotlin *top-level* function compiles onto a package-private multi-file part diff --git a/docs/design/kotlin-extensions-in-python.md b/docs/design/kotlin-extensions-in-python.md index 6e78e06f6..33cb62f61 100644 --- a/docs/design/kotlin-extensions-in-python.md +++ b/docs/design/kotlin-extensions-in-python.md @@ -648,9 +648,9 @@ it is why composables remain blocked while the `Modifier` chain of §3.2 runs. descriptor copied from the walked `MethodNode` at build time; no runtime lookup. - The binding layer (`python_multiplatform.binding`) computes the `$default` mask from which arguments the Python call wrote and threads the composer from a stack that one hand-written - `@Composable` entry pushes (`PythonComposition` in `ksp-fixtures/compose`). + `@Composable` entry pushes (`PythonComposition` in `python-multiplatform-compose/fixtures/compose`). -Proven by `ksp-fixtures/compose`'s render tests (`ComposableRenderTest`, `M3ProofRenderTest`, +Proven by `python-multiplatform-compose/fixtures/compose`'s render tests (`ComposableRenderTest`, `M3ProofRenderTest`, `CallbackDrivenRenderTest`) on desktop only; Android, iOS and wasm are planned (SPEC N-2). Extension composables and recomposition skipping remain open. diff --git a/docs/design/pyi-generation-design.md b/docs/design/pyi-generation-design.md index 13fd7405c..2e5b0c69f 100644 --- a/docs/design/pyi-generation-design.md +++ b/docs/design/pyi-generation-design.md @@ -33,7 +33,7 @@ does not revisit it. What this file answers: **what the generator reads**, **what it writes**, and **where the result goes**. The generator is `PythonStubsTask` + `renderKotlinFqnStubs` (`PyiRendering.kt`, in `python-multiplatform-gradle-plugin/src/main/kotlin/python/multiplatform/gradle/stubs/`); its tests are -`PyiRenderingTest`, `KotlinNamesOnlyStubTest` and `ksp-fixtures/artifact`'s `WalkedArtifactStubTest`. +`PyiRenderingTest`, `KotlinNamesOnlyStubTest` and `python-multiplatform-gradle-plugin/fixtures/artifact`'s `WalkedArtifactStubTest`. Everything under "Observed" was read from working copies or run as a command on 2026-08-14, with the path or the command given, unless dated otherwise. Everything under "Judged" is a decision, and the @@ -630,7 +630,7 @@ merges an overlap. - `.github/scripts/stubs/check-stubs.sh ` runs `mypy --strict` over `.github/scripts/stubs/consumer.py` (a `Modifier` chain from the class and from an instance, `Checkbox`, `Text`, `Column` with its keyword `content`, and four lines that must be rejected) against stubs generated for the real Compose jars - (`:ksp-fixtures:compose:generatePythonStubs`, which `ksp-fixtures/compose` now enables). Errors inside + (`:python-multiplatform-compose:fixtures:compose:generatePythonStubs`, which `python-multiplatform-compose/fixtures/compose` now enables). Errors inside the stubs are reported as well, not only in the consumer. - `.github/workflows/stubs.yml` runs the stub task and that check on every push to `develop`, uploads the stubs as the workflow artifact `kotlin-stubs` (with a README naming the Compose version and the diff --git a/docs/design/upcall.md b/docs/design/upcall.md index 92600a5cf..761fd17c6 100644 --- a/docs/design/upcall.md +++ b/docs/design/upcall.md @@ -132,8 +132,8 @@ point. Each module emits one **fragment object** into the well-known package // GENERATED by python-multiplatform-ksp. Do not edit. package python.multiplatform.generated.fragments -object Fragment_io_github_thisisthepy_ksp_fixtures_library : python.multiplatform.reflection.FunctionTableFragment { - override val moduleName: String = "io_github_thisisthepy_ksp_fixtures_library" +object Fragment_io_github_thisisthepy_python_multiplatform_ksp_fixtures_library : python.multiplatform.reflection.FunctionTableFragment { + override val moduleName: String = "io_github_thisisthepy_python_multiplatform_ksp_fixtures_library" override fun entries(): List = listOf( ExposedCallable(name = "fixture.library.greet", arity = 1, paramTypes = listOf(TypeTag.STRING), returnType = TypeTag.STRING, paramNames = listOf("name"), callable = { args -> fixture.library.greet(args[0] as String) }), @@ -147,8 +147,8 @@ object Fragment_io_github_thisisthepy_ksp_fixtures_library : python.multiplatfor - **Name**: `Fragment_`, where `moduleName` is the KSP option `python.multiplatform.moduleName` with `.` and `-` replaced by `_` (`Constants.kt`). The Gradle plugin - derives it from the **Maven group plus the project path** (`:ksp-fixtures:app` with group - `io.github.thisisthepy` → `io_github_thisisthepy_ksp_fixtures_app`), because fragments from every + derives it from the **Maven group plus the project path** (`:python-multiplatform-ksp:fixtures:app` with group + `io.github.thisisthepy` → `io_github_thisisthepy_python_multiplatform_ksp_fixtures_app`), because fragments from every artifact share one package and two libraries both called `:core` would otherwise collide. The name is not load-bearing for discovery (the whole package is scanned) but prevents collisions. - **Visibility: `public`.** An `internal` fragment does not work: `internal` is enforced per Kotlin @@ -191,7 +191,7 @@ object Fragment_io_github_thisisthepy_ksp_fixtures_library : python.multiplatfor | `@PythonInternal` | no | opt-out | Asserted against KSP-generated fragments, not hand-written ones: -`ksp-fixtures/app/src/desktopTest/.../GeneratedDeclarationKindsTest.kt`, +`python-multiplatform-ksp/fixtures/app/src/desktopTest/.../GeneratedDeclarationKindsTest.kt`, `GeneratedSuspendTest.kt`, `GeneratedTableTest.kt` (which runs `UpcallTableTest`'s scenarios, constructor / method / getter / setter round trip through `HandleTable`, `@PythonInternal` exclusion, narrow `Int`/`Float` widening, `tp_traverse` field detection, against a generated table), and @@ -244,10 +244,10 @@ The same mechanism serves every target: | Platform | Discovery source | Status | |---|---|---| -| JVM desktop | JARs on the classpath | `ksp-fixtures/app` desktop tests | -| Android | JAR/AAR classpath | `ksp-fixtures/android` (`GeneratedAndroidTableTest`, unit and instrumented) | +| JVM desktop | JARs on the classpath | `python-multiplatform-ksp/fixtures/app` desktop tests | +| Android | JAR/AAR classpath | `python-multiplatform-ksp/fixtures/android` (`GeneratedAndroidTableTest`, unit and instrumented) | | GraalVM native image | classpath at build time; the table is statically reachable, so no reflection config | verified manually, [`graal-native-image-verification.md`](../platforms/graal-native-image-verification.md) (SPEC U-6) | -| Kotlin/Native | klib metadata | `ksp-fixtures/{library,app}` on `androidNativeArm64`: round 2 found the library's fragment in its `.klib`, `FunctionTable` compiled and linked, and `ksp-fixtures/app/src/androidNativeArm64Test/.../NativeSmokeTest.kt` runs it (SPEC U-3) | +| Kotlin/Native | klib metadata | `python-multiplatform-ksp/fixtures/{library,app}` on `androidNativeArm64`: round 2 found the library's fragment in its `.klib`, `FunctionTable` compiled and linked, and `python-multiplatform-ksp/fixtures/app/src/androidNativeArm64Test/.../NativeSmokeTest.kt` runs it (SPEC U-3) | `ServiceLoader` could work on JVM/Android, but one aggregator everywhere avoids a platform split and runtime classpath scanning. @@ -309,7 +309,7 @@ derives `moduleName`. Notes from building it: through one reflective lookup of `arg(String, String)`. - **Test configurations are matched as a camel-case word `Test`.** AGP puts the build type last (`kspAndroidTestDebug`), so an `endsWith("Test")` check once put the processor on a unit-test - compilation, which emitted a duplicate fragment shadowing `main`'s. `ksp-fixtures/android` carries the + compilation, which emitted a duplicate fragment shadowing `main`'s. `python-multiplatform-ksp/fixtures/android` carries the Android plugin for this reason ([ROADMAP](../roadmap/ROADMAP.md) §13). ### 2.6 Tree shaking, decision: accept the cost (measured) @@ -331,8 +331,8 @@ remaining options, one line each: | D. `ServiceLoader` on JVM, aggregator on Native | A platform split for no gain: the JVM does not tree-shake anyway | | E. Two-tier table (skeleton + lazily initialised body) | Saves runtime lambda objects, **not binary size**: the `when` arms still statically reference every target on Kotlin/Native | -**Measured.** `ksp-fixtures/library` got 200 synthetic top-level functions (`fun bulkN(x: Long): Long = x + N`); -`ksp-fixtures/app`'s `androidNativeArm64` debug test binary was linked before and after +**Measured.** `python-multiplatform-ksp/fixtures/library` got 200 synthetic top-level functions (`fun bulkN(x: Long): Long = x + N`); +`python-multiplatform-ksp/fixtures/app`'s `androidNativeArm64` debug test binary was linked before and after (`linkDebugTestAndroidNativeArm64`) and stripped with the NDK's `aarch64-linux-android-strip`: | | bytes | delta | @@ -352,7 +352,7 @@ mitigation would be changing the exposure model, which is settled. `Dependencies(false)` would never regenerate the aggregator and miss a newly added fragment; `Dependencies.ALL_FILES` is correct but reprocesses on every change. A narrower declaration buys nothing. -Measured with `ksp.incremental.log=true` on `:ksp-fixtures:app` (two files), modifying one: +Measured with `ksp.incremental.log=true` on `:python-multiplatform-ksp:fixtures:app` (two files), modifying one: | aggregator `Dependencies` | dirty / all | |---|---| @@ -361,7 +361,7 @@ Measured with `ksp.incremental.log=true` on `:ksp-fixtures:app` (two files), mod A module's own `Fragment_` is an *aggregating* output over every source file, correctly, since under blacklist exposure any file can add an entry, so any change regenerates it and KSP marks every source that -maps to it dirty. A classpath-only change behaves the same (adding a function to `:ksp-fixtures:library` +maps to it dirty. A classpath-only change behaves the same (adding a function to `:python-multiplatform-ksp:fixtures:library` dirtied both app files with `CP changes` listing `Fragment_ksp_fixture_library`). The only route to real incrementality is **per-file fragments**, which changes fragment naming, `UpcallTable`'s per-module idempotency and where duplicate names are detected, a design change, not done. @@ -677,7 +677,7 @@ lives at `python_multiplatform.binding`). Its KDoc is the contract (SPEC U-8): No namespace is renamed and the binder creates no `pythonx` module; a real `pythonx` package on disk is what `import pythonx` loads. Members and keywords also answer to their Pythonic aliases, and the signature shows the Pythonic keyword (SPEC U-12). Tests: `desktopTest/.../pythonx/KotlinNamedSurfaceTest.kt`, -`ksp-fixtures/compose/.../KotlinSignatureMetadataTest.kt`. `.pyi` stubs are generated by the Gradle plugin +`python-multiplatform-compose/fixtures/compose/.../KotlinSignatureMetadataTest.kt`. `.pyi` stubs are generated by the Gradle plugin under Kotlin module paths only (SPEC B-7). ### 4.4 Inheritance @@ -758,8 +758,8 @@ The braces are a `suspend` lambda; it compiles with the stdlib only. `kind` is u member is still `METHOD`, receiver in `args[0]`) and `returnType` is the **declared** return type, so the fast path marshals exactly like a synchronous entry. `ExposedCallable.isSuspend` is a flag rather than `SUSPEND_*` variants of `CallableKind` because the axes are orthogonal: `kind` says where the arguments are, -`isSuspend` what comes back. Pinned by `ksp-fixtures/app/.../GeneratedSuspendTest.kt` against -`ksp-fixtures/library/.../Suspending.kt`, which pairs every suspending declaration (top-level, member, +`isSuspend` what comes back. Pinned by `python-multiplatform-ksp/fixtures/app/.../GeneratedSuspendTest.kt` against +`python-multiplatform-ksp/fixtures/library/.../Suspending.kt`, which pairs every suspending declaration (top-level, member, companion, interface, object) with a non-suspending control in the same scope. A `suspend` **function type** (`val h: suspend (Long) -> Long`, a parameter or return of that type, nullable, @@ -972,7 +972,7 @@ reflection-based binding cannot afford this, which is why mature ones document " instead. Generated proxies reach the traversable type through the GC base of §4.2. Status: SPEC M-3, implemented on desktop (`desktopTest/.../ref/CycleCollectionTest.kt`, -`ksp-fixtures/app/.../RefHolderCycleCollectionTest.kt`), partial elsewhere. Mechanism and the hard parts +`python-multiplatform-ksp/fixtures/app/.../RefHolderCycleCollectionTest.kt`), partial elsewhere. Mechanism and the hard parts (traverse during collection, `tp_clear` mutating Kotlin state, cycles closing on the Kotlin side) are in [`object-lifetime.md`](object-lifetime.md). diff --git a/docs/guide/getting-started.html b/docs/guide/getting-started.html index e02e311aa..61f3d1b07 100644 --- a/docs/guide/getting-started.html +++ b/docs/guide/getting-started.html @@ -72,9 +72,9 @@

03Your first call04Verify a change변경 검증하기

./gradlew :python-multiplatform:compileKotlinAndroidNativeArm64 --console=plain > .tmp/build.log 2>&1; echo "EXIT=$?"
 ./gradlew :python-multiplatform:desktopTest --rerun --console=plain > .tmp/test.log 2>&1; echo "EXIT=$?"
-./gradlew :ksp-fixtures:app:desktopTest --rerun
-./gradlew :ksp-fixtures:compose:desktopTest --rerun
-./gradlew :ksp-fixtures:artifact:desktopTest --rerun
+./gradlew :python-multiplatform-ksp:fixtures:app:desktopTest --rerun +./gradlew :python-multiplatform-compose:fixtures:compose:desktopTest --rerun +./gradlew :python-multiplatform-gradle-plugin-fixtures:artifact:desktopTest --rerun

Run the fixture modules one by one: a single invocation has hidden an ordering dependency before. Read exit codes from a file, never through a pipe.픽스처 모듈은 하나씩 따로 돌린다. 한 번에 돌리면 순서 의존성이 가려진 적이 있다. 종료 코드는 파이프가 아니라 파일에서 읽는다.

diff --git a/docs/guide/index.html b/docs/guide/index.html index 25fa6def0..0d8b0c737 100644 --- a/docs/guide/index.html +++ b/docs/guide/index.html @@ -93,7 +93,7 @@

ContributingCheck that the change serves the project's intent (docs/INTENT.md on the develop branch).변경이 프로젝트의 의도(develop 브랜치의 docs/INTENT.md)에 맞는지 확인한다.
  • Describe the behaviour in the specification (docs/SPEC.md), marked planned.동작을 스펙(docs/SPEC.md)에 planned 로 적는다.
  • Write the test, run it, and include the red output in the pull request.테스트를 쓰고 돌려서, 빨간 출력을 풀 리퀘스트에 함께 올린다.
  • -
  • Implement; include the androidNative compile and each ksp-fixtures module, run separately, in your verification.구현한다. 검증에는 androidNative 컴파일과 ksp-fixtures 모듈 각각(따로 실행)을 포함한다.
  • +
  • Implement; include the androidNative compile and each fixtures/ module, run separately, in your verification.구현한다. 검증에는 androidNative 컴파일과 fixtures/ 모듈 각각(따로 실행)을 포함한다.
  • Work on a work/<topic> branch and open the pull request against develop.work/<topic> 브랜치에서 작업하고 develop 을 대상으로 풀 리퀘스트를 연다.

    diff --git a/docs/roadmap/ROADMAP.md b/docs/roadmap/ROADMAP.md index 3a6261a14..9b7832d23 100644 --- a/docs/roadmap/ROADMAP.md +++ b/docs/roadmap/ROADMAP.md @@ -99,20 +99,20 @@ String-carrying operations: **closed**, interning beats composing on every API l Closed in its core: build-time table, KSP generator, one entry point per platform, generated proxies, `tp_traverse` handle slot on all five targets, GraalVM native image (SPEC U-1…U-6, M-3, M-4; -`ksp-fixtures/app/src/desktopTest/`, `PM/commonTest/.../reflection/UpcallTableTest.kt`, +`python-multiplatform-ksp/fixtures/app/src/desktopTest/`, `PM/commonTest/.../reflection/UpcallTableTest.kt`, `PM/*Test/.../ref/CycleCollectionTest.kt`). Upcall cost is measured (`PM/commonTest/.../reflection/UpcallOverheadTest.kt`, `PM/commonTest/.../ffi/upcall/GeneratedProxyCostTest.kt`). - **7.1 Generated proxies exercised outside desktop, partial.** SPEC U-3: the full proxy behaviour (construct, methods, properties, companions) is asserted on desktop only; outside it there are - `ksp-fixtures/app/src/androidNativeArm64Test/.../NativeSmokeTest.kt` and - `ksp-fixtures/android/.../GeneratedAndroidTableTest.kt`. The KSP-generated-proxy cycle proof - (`ksp-fixtures/app/src/desktopTest/.../RefHolderCycleCollectionTest.kt`) likewise exists on desktop - only, because `ksp-fixtures/app` has no iOS or device leaf; other targets prove the slot with a + `python-multiplatform-ksp/fixtures/app/src/androidNativeArm64Test/.../NativeSmokeTest.kt` and + `python-multiplatform-ksp/fixtures/android/.../GeneratedAndroidTableTest.kt`. The KSP-generated-proxy cycle proof + (`python-multiplatform-ksp/fixtures/app/src/desktopTest/.../RefHolderCycleCollectionTest.kt`) likewise exists on desktop + only, because `python-multiplatform-ksp/fixtures/app` has no iOS or device leaf; other targets prove the slot with a hand-built subclass (`PM/nativeTest/.../CycleCollectionTest.kt`). - **7.2 Extension functions as methods on KSP-generated proxies, partial.** SPEC U-7: asserted for a hand-written table (`PM/commonTest/.../pythonx/PythonxAdapterTest.kt`) and for walked jars - (`ksp-fixtures/artifact/.../WalkedArtifactComposeModifierTest.kt`); not for a table KSP generated. + (`python-multiplatform-gradle-plugin/fixtures/artifact/.../WalkedArtifactComposeModifierTest.kt`); not for a table KSP generated. - **7.3 Incremental KSP, open (deferred design change).** A one-file change regenerates the module's whole `Fragment_` (100 % dirty, measured with `ksp.incremental.log`). The only route is per-file fragments, which changes fragment naming and `UpcallTable`'s duplicate detection; @@ -257,7 +257,7 @@ pre-release URL, `PyList.subList` (a live `PySubList`), the `TODO` triage, `runM ## 13. The sample, and the AGP version that shapes it The sample runs on desktop, Android (both emulators), the iOS simulator and in a browser; the bindings -plugin applies to Android modules (AGP 8.10.1); `ksp-fixtures/android` exists; the generated +plugin applies to Android modules (AGP 8.10.1); `python-multiplatform-ksp/fixtures/android` exists; the generated `installGeneratedUpcallTable` `actual` reaches intermediate source sets; the per-platform upcall trampolines exist. GraalVM native image upcalls are verified by hand (`docs/platforms/graal-native-image-verification.md`, `PM/desktopTest/.../ReachabilityMetadataTest.kt`). @@ -334,7 +334,7 @@ Old §15a, §15b, §15d, §15f, §15g, §15h are closed; §15e item 4 is closed The walker binds jar declarations, statics, top-level functions, extensions, constructors, value classes, defaults, callbacks, `@Composable`s, by generating Kotlin source (SPEC B-1, B-3, B-4, B-6; -`GP/test/.../artifact/ArtifactScannerTest.kt`, `ksp-fixtures/artifact/`, `ksp-fixtures/compose/`), +`GP/test/.../artifact/ArtifactScannerTest.kt`, `python-multiplatform-gradle-plugin/fixtures/artifact/`, `python-multiplatform-compose/fixtures/compose/`), reads Kotlin metadata (`GP/main/.../artifact/KotlinMetadata.kt`), walks klibs through an isolated worker (`KlibScanner.kt`, `KlibScanWorkAction.kt`), and takes several targets (`artifactTargets`, `GP/test/.../ArtifactTargetsWiringTest.kt`). Consumers bootstrap `_pm_resolve`/`_pm_invoke` through @@ -342,11 +342,11 @@ worker (`KlibScanner.kt`, `KlibScanWorkAction.kt`), and takes several targets (` description, §16e/§16f's open remainder is below. - **16.1 klib declarations bound at run time, partial.** SPEC B-2/N-3. `KlibScannerTest` reads real - klibs and declines with reasons; `ksp-fixtures/klib-artifact` walks + klibs and declines with reasons; `python-multiplatform-gradle-plugin/fixtures/klib-artifact` walks `androidNativeArm64CompileKlibraries` through the plugin, but the namespace it walks (`kotlinx.coroutines`) yields **zero** bindings by design, so a successful read and a silently failed one still produce the same empty `ArtifactTable` - (`ksp-fixtures/klib-artifact/src/androidNativeArm64Test/.../WalkedKlibArtifactTableTest.kt`). And no + (`python-multiplatform-gradle-plugin/fixtures/klib-artifact/src/androidNativeArm64Test/.../WalkedKlibArtifactTableTest.kt`). And no Gradle task runs that fixture's tests, they are compiled and linked, and run only by pushing `test.kexe` by hand. Next: a namespace that yields at least one binding, and a run task. - **16.2 The product klib path under a Kotlin version skew, open.** `KlibScannerTest` reads klibs @@ -361,7 +361,7 @@ description, §16e/§16f's open remainder is below. SPEC B-5; pinned red-by-design by `M3ProofRenderTest.aValueReturningFunctionSlotDoesNotYetAcceptAPythonCallable`. - **16.6 `.pyi` stubs for handle-returning functions are not wrapped, open.** SPEC B-7. - **16.7 Compose through Python on Android, iOS and wasm, open.** SPEC B-6/N-2: the render proofs - (`ksp-fixtures/compose/src/desktopTest/`) are desktop only. + (`python-multiplatform-compose/fixtures/compose/src/desktopTest/`) are desktop only. - **16.8 Two material3 components not reachable from Python, open.** The dynamic `ColorScheme` factory is Android-only. Since #73 the class name resolves to `ColorScheme`'s own constructor (its `Color` parameters no longer hide it), which needs every colour written out; nothing renders with one @@ -375,7 +375,7 @@ From `docs/design/ecosystem.md` §5, "What each repository owes, PythonMultiplat the `@Composable` callable shape, the `sys.meta_path` finder (`_Finder` in `PM/commonMain/kotlin/python/multiplatform/ffi/pythonx/PythonxAdapter.kt`, tested in `PythonxAdapterTest.kt`), the `Composer` hand-off and Python-callable lifetime across recompositions -(`ksp-fixtures/compose/src/desktopTest/.../ComposableRenderTest.kt`, `RecompositionAccumulationTest.kt`) +(`python-multiplatform-compose/fixtures/compose/src/desktopTest/.../ComposableRenderTest.kt`, `RecompositionAccumulationTest.kt`) are done on desktop; the other platforms are 16.7. The production-bundler question is 10.4. - **17.1 Retire `stagePythonHome` in favour of pypackpack's Python distribution, open (cross-repo).** diff --git a/ksp-fixtures/compose/build.gradle.kts b/python-multiplatform-compose/fixtures/compose/build.gradle.kts similarity index 95% rename from ksp-fixtures/compose/build.gradle.kts rename to python-multiplatform-compose/fixtures/compose/build.gradle.kts index c7e52cd9f..b953f711e 100644 --- a/ksp-fixtures/compose/build.gradle.kts +++ b/python-multiplatform-compose/fixtures/compose/build.gradle.kts @@ -5,7 +5,7 @@ import org.jetbrains.kotlin.gradle.dsl.JvmTarget * The other end of `docs/archive/pythonx-adapter-design.md` §5: a real `@Composable`, called from Python, * inside a real composition, drawing a real pixel. * - * ### Why this is not `:ksp-fixtures:artifact` + * ### Why this is not `:python-multiplatform-gradle-plugin-fixtures:artifact` * * That module takes Compose as **plain Maven coordinates with no Compose plugin**, and its own * `build.gradle.kts` says why: what makes `Modifier.padding(16.dp)` reachable is the walker's gates @@ -69,7 +69,7 @@ pythonBindings { artifactConfiguration.set("desktopCompileClasspath") artifactSourceSet.set("desktopMain") - // Narrow on purpose, and narrower than `:ksp-fixtures:artifact`'s: binding all of Compose would + // Narrow on purpose, and narrower than `:python-multiplatform-gradle-plugin-fixtures:artifact`'s: binding all of Compose would // make this fixture's compile time the cost of a proof it does not need. Each entry earns its // place. // @@ -124,7 +124,7 @@ pythonBindings { } /** - * The same JVM `:ksp-fixtures:artifact`'s tests need: JDK 21 with the preview FFM API, and a + * The same JVM `:python-multiplatform-gradle-plugin-fixtures:artifact`'s tests need: JDK 21 with the preview FFM API, and a * `java.library.path` for the `libpython` that `manager.loadLibPython` extracts next to the working * directory. */ diff --git a/ksp-fixtures/compose/src/desktopMain/kotlin/fixture/compose/ModifierComparisons.kt b/python-multiplatform-compose/fixtures/compose/src/desktopMain/kotlin/fixture/compose/ModifierComparisons.kt similarity index 100% rename from ksp-fixtures/compose/src/desktopMain/kotlin/fixture/compose/ModifierComparisons.kt rename to python-multiplatform-compose/fixtures/compose/src/desktopMain/kotlin/fixture/compose/ModifierComparisons.kt diff --git a/ksp-fixtures/compose/src/desktopMain/kotlin/fixture/compose/PythonAnchoredDraggable.kt b/python-multiplatform-compose/fixtures/compose/src/desktopMain/kotlin/fixture/compose/PythonAnchoredDraggable.kt similarity index 100% rename from ksp-fixtures/compose/src/desktopMain/kotlin/fixture/compose/PythonAnchoredDraggable.kt rename to python-multiplatform-compose/fixtures/compose/src/desktopMain/kotlin/fixture/compose/PythonAnchoredDraggable.kt diff --git a/ksp-fixtures/compose/src/desktopMain/kotlin/fixture/compose/PythonComposed.kt b/python-multiplatform-compose/fixtures/compose/src/desktopMain/kotlin/fixture/compose/PythonComposed.kt similarity index 100% rename from ksp-fixtures/compose/src/desktopMain/kotlin/fixture/compose/PythonComposed.kt rename to python-multiplatform-compose/fixtures/compose/src/desktopMain/kotlin/fixture/compose/PythonComposed.kt diff --git a/ksp-fixtures/compose/src/desktopMain/kotlin/fixture/compose/PythonComposition.kt b/python-multiplatform-compose/fixtures/compose/src/desktopMain/kotlin/fixture/compose/PythonComposition.kt similarity index 98% rename from ksp-fixtures/compose/src/desktopMain/kotlin/fixture/compose/PythonComposition.kt rename to python-multiplatform-compose/fixtures/compose/src/desktopMain/kotlin/fixture/compose/PythonComposition.kt index 31d8dda11..564ad6fa6 100644 --- a/ksp-fixtures/compose/src/desktopMain/kotlin/fixture/compose/PythonComposition.kt +++ b/python-multiplatform-compose/fixtures/compose/src/desktopMain/kotlin/fixture/compose/PythonComposition.kt @@ -130,7 +130,7 @@ class CountingCallableArena : PythonCallableArena() { * nor `pythonx` can supply on their own: a `Modifier` chain has to start somewhere, and the thing it * starts from is `Modifier` the *expression* -- `androidx.compose.ui.Modifier.Companion`, an object * instance the walker cannot hand out because it only binds functions. - * `ksp-fixtures/artifact`'s `ComposeSeed.kt` solved the exact same gap the same way, for the + * `python-multiplatform-gradle-plugin/fixtures/artifact`'s `ComposeSeed.kt` solved the exact same gap the same way, for the * non-composable half of Compose's surface; this is that solution, in this module, so `Spacer` -- * whose one parameter has no default and is therefore not omittable -- has something to be given. * diff --git a/ksp-fixtures/compose/src/desktopMain/kotlin/fixture/compose/PythonContextMenuOpenDetector.kt b/python-multiplatform-compose/fixtures/compose/src/desktopMain/kotlin/fixture/compose/PythonContextMenuOpenDetector.kt similarity index 100% rename from ksp-fixtures/compose/src/desktopMain/kotlin/fixture/compose/PythonContextMenuOpenDetector.kt rename to python-multiplatform-compose/fixtures/compose/src/desktopMain/kotlin/fixture/compose/PythonContextMenuOpenDetector.kt diff --git a/ksp-fixtures/compose/src/desktopMain/kotlin/fixture/compose/PythonDragAndDropSource.kt b/python-multiplatform-compose/fixtures/compose/src/desktopMain/kotlin/fixture/compose/PythonDragAndDropSource.kt similarity index 100% rename from ksp-fixtures/compose/src/desktopMain/kotlin/fixture/compose/PythonDragAndDropSource.kt rename to python-multiplatform-compose/fixtures/compose/src/desktopMain/kotlin/fixture/compose/PythonDragAndDropSource.kt diff --git a/ksp-fixtures/compose/src/desktopMain/kotlin/fixture/compose/PythonDraggable.kt b/python-multiplatform-compose/fixtures/compose/src/desktopMain/kotlin/fixture/compose/PythonDraggable.kt similarity index 100% rename from ksp-fixtures/compose/src/desktopMain/kotlin/fixture/compose/PythonDraggable.kt rename to python-multiplatform-compose/fixtures/compose/src/desktopMain/kotlin/fixture/compose/PythonDraggable.kt diff --git a/ksp-fixtures/compose/src/desktopMain/kotlin/fixture/compose/PythonLayoutId.kt b/python-multiplatform-compose/fixtures/compose/src/desktopMain/kotlin/fixture/compose/PythonLayoutId.kt similarity index 100% rename from ksp-fixtures/compose/src/desktopMain/kotlin/fixture/compose/PythonLayoutId.kt rename to python-multiplatform-compose/fixtures/compose/src/desktopMain/kotlin/fixture/compose/PythonLayoutId.kt diff --git a/ksp-fixtures/compose/src/desktopMain/kotlin/fixture/compose/PythonModifierLocal.kt b/python-multiplatform-compose/fixtures/compose/src/desktopMain/kotlin/fixture/compose/PythonModifierLocal.kt similarity index 100% rename from ksp-fixtures/compose/src/desktopMain/kotlin/fixture/compose/PythonModifierLocal.kt rename to python-multiplatform-compose/fixtures/compose/src/desktopMain/kotlin/fixture/compose/PythonModifierLocal.kt diff --git a/ksp-fixtures/compose/src/desktopMain/kotlin/fixture/compose/PythonPointerInput.kt b/python-multiplatform-compose/fixtures/compose/src/desktopMain/kotlin/fixture/compose/PythonPointerInput.kt similarity index 100% rename from ksp-fixtures/compose/src/desktopMain/kotlin/fixture/compose/PythonPointerInput.kt rename to python-multiplatform-compose/fixtures/compose/src/desktopMain/kotlin/fixture/compose/PythonPointerInput.kt diff --git a/ksp-fixtures/compose/src/desktopMain/kotlin/fixture/compose/PythonPullRefresh.kt b/python-multiplatform-compose/fixtures/compose/src/desktopMain/kotlin/fixture/compose/PythonPullRefresh.kt similarity index 100% rename from ksp-fixtures/compose/src/desktopMain/kotlin/fixture/compose/PythonPullRefresh.kt rename to python-multiplatform-compose/fixtures/compose/src/desktopMain/kotlin/fixture/compose/PythonPullRefresh.kt diff --git a/ksp-fixtures/compose/src/desktopMain/kotlin/fixture/compose/PythonSwipeable.kt b/python-multiplatform-compose/fixtures/compose/src/desktopMain/kotlin/fixture/compose/PythonSwipeable.kt similarity index 100% rename from ksp-fixtures/compose/src/desktopMain/kotlin/fixture/compose/PythonSwipeable.kt rename to python-multiplatform-compose/fixtures/compose/src/desktopMain/kotlin/fixture/compose/PythonSwipeable.kt diff --git a/ksp-fixtures/compose/src/desktopTest/kotlin/fixture/compose/AnchoredDraggableRenderTest.kt b/python-multiplatform-compose/fixtures/compose/src/desktopTest/kotlin/fixture/compose/AnchoredDraggableRenderTest.kt similarity index 100% rename from ksp-fixtures/compose/src/desktopTest/kotlin/fixture/compose/AnchoredDraggableRenderTest.kt rename to python-multiplatform-compose/fixtures/compose/src/desktopTest/kotlin/fixture/compose/AnchoredDraggableRenderTest.kt diff --git a/ksp-fixtures/compose/src/desktopTest/kotlin/fixture/compose/AnySlotScalarRenderTest.kt b/python-multiplatform-compose/fixtures/compose/src/desktopTest/kotlin/fixture/compose/AnySlotScalarRenderTest.kt similarity index 100% rename from ksp-fixtures/compose/src/desktopTest/kotlin/fixture/compose/AnySlotScalarRenderTest.kt rename to python-multiplatform-compose/fixtures/compose/src/desktopTest/kotlin/fixture/compose/AnySlotScalarRenderTest.kt diff --git a/ksp-fixtures/compose/src/desktopTest/kotlin/fixture/compose/CallbackDrivenRenderTest.kt b/python-multiplatform-compose/fixtures/compose/src/desktopTest/kotlin/fixture/compose/CallbackDrivenRenderTest.kt similarity index 100% rename from ksp-fixtures/compose/src/desktopTest/kotlin/fixture/compose/CallbackDrivenRenderTest.kt rename to python-multiplatform-compose/fixtures/compose/src/desktopTest/kotlin/fixture/compose/CallbackDrivenRenderTest.kt diff --git a/ksp-fixtures/compose/src/desktopTest/kotlin/fixture/compose/ColorFactoryTest.kt b/python-multiplatform-compose/fixtures/compose/src/desktopTest/kotlin/fixture/compose/ColorFactoryTest.kt similarity index 100% rename from ksp-fixtures/compose/src/desktopTest/kotlin/fixture/compose/ColorFactoryTest.kt rename to python-multiplatform-compose/fixtures/compose/src/desktopTest/kotlin/fixture/compose/ColorFactoryTest.kt diff --git a/ksp-fixtures/compose/src/desktopTest/kotlin/fixture/compose/ComposableRenderTest.kt b/python-multiplatform-compose/fixtures/compose/src/desktopTest/kotlin/fixture/compose/ComposableRenderTest.kt similarity index 100% rename from ksp-fixtures/compose/src/desktopTest/kotlin/fixture/compose/ComposableRenderTest.kt rename to python-multiplatform-compose/fixtures/compose/src/desktopTest/kotlin/fixture/compose/ComposableRenderTest.kt diff --git a/ksp-fixtures/compose/src/desktopTest/kotlin/fixture/compose/ComposedRenderTest.kt b/python-multiplatform-compose/fixtures/compose/src/desktopTest/kotlin/fixture/compose/ComposedRenderTest.kt similarity index 100% rename from ksp-fixtures/compose/src/desktopTest/kotlin/fixture/compose/ComposedRenderTest.kt rename to python-multiplatform-compose/fixtures/compose/src/desktopTest/kotlin/fixture/compose/ComposedRenderTest.kt diff --git a/ksp-fixtures/compose/src/desktopTest/kotlin/fixture/compose/ContextMenuOpenDetectorRenderTest.kt b/python-multiplatform-compose/fixtures/compose/src/desktopTest/kotlin/fixture/compose/ContextMenuOpenDetectorRenderTest.kt similarity index 100% rename from ksp-fixtures/compose/src/desktopTest/kotlin/fixture/compose/ContextMenuOpenDetectorRenderTest.kt rename to python-multiplatform-compose/fixtures/compose/src/desktopTest/kotlin/fixture/compose/ContextMenuOpenDetectorRenderTest.kt diff --git a/ksp-fixtures/compose/src/desktopTest/kotlin/fixture/compose/DragAndDropSourceRenderTest.kt b/python-multiplatform-compose/fixtures/compose/src/desktopTest/kotlin/fixture/compose/DragAndDropSourceRenderTest.kt similarity index 100% rename from ksp-fixtures/compose/src/desktopTest/kotlin/fixture/compose/DragAndDropSourceRenderTest.kt rename to python-multiplatform-compose/fixtures/compose/src/desktopTest/kotlin/fixture/compose/DragAndDropSourceRenderTest.kt diff --git a/ksp-fixtures/compose/src/desktopTest/kotlin/fixture/compose/DraggableLeakTest.kt b/python-multiplatform-compose/fixtures/compose/src/desktopTest/kotlin/fixture/compose/DraggableLeakTest.kt similarity index 100% rename from ksp-fixtures/compose/src/desktopTest/kotlin/fixture/compose/DraggableLeakTest.kt rename to python-multiplatform-compose/fixtures/compose/src/desktopTest/kotlin/fixture/compose/DraggableLeakTest.kt diff --git a/ksp-fixtures/compose/src/desktopTest/kotlin/fixture/compose/DraggableRenderTest.kt b/python-multiplatform-compose/fixtures/compose/src/desktopTest/kotlin/fixture/compose/DraggableRenderTest.kt similarity index 100% rename from ksp-fixtures/compose/src/desktopTest/kotlin/fixture/compose/DraggableRenderTest.kt rename to python-multiplatform-compose/fixtures/compose/src/desktopTest/kotlin/fixture/compose/DraggableRenderTest.kt diff --git a/ksp-fixtures/compose/src/desktopTest/kotlin/fixture/compose/IconRenderTest.kt b/python-multiplatform-compose/fixtures/compose/src/desktopTest/kotlin/fixture/compose/IconRenderTest.kt similarity index 100% rename from ksp-fixtures/compose/src/desktopTest/kotlin/fixture/compose/IconRenderTest.kt rename to python-multiplatform-compose/fixtures/compose/src/desktopTest/kotlin/fixture/compose/IconRenderTest.kt diff --git a/ksp-fixtures/compose/src/desktopTest/kotlin/fixture/compose/KotlinSignatureMetadataTest.kt b/python-multiplatform-compose/fixtures/compose/src/desktopTest/kotlin/fixture/compose/KotlinSignatureMetadataTest.kt similarity index 100% rename from ksp-fixtures/compose/src/desktopTest/kotlin/fixture/compose/KotlinSignatureMetadataTest.kt rename to python-multiplatform-compose/fixtures/compose/src/desktopTest/kotlin/fixture/compose/KotlinSignatureMetadataTest.kt diff --git a/ksp-fixtures/compose/src/desktopTest/kotlin/fixture/compose/LayoutIdRenderTest.kt b/python-multiplatform-compose/fixtures/compose/src/desktopTest/kotlin/fixture/compose/LayoutIdRenderTest.kt similarity index 100% rename from ksp-fixtures/compose/src/desktopTest/kotlin/fixture/compose/LayoutIdRenderTest.kt rename to python-multiplatform-compose/fixtures/compose/src/desktopTest/kotlin/fixture/compose/LayoutIdRenderTest.kt diff --git a/ksp-fixtures/compose/src/desktopTest/kotlin/fixture/compose/M3ProofRenderTest.kt b/python-multiplatform-compose/fixtures/compose/src/desktopTest/kotlin/fixture/compose/M3ProofRenderTest.kt similarity index 100% rename from ksp-fixtures/compose/src/desktopTest/kotlin/fixture/compose/M3ProofRenderTest.kt rename to python-multiplatform-compose/fixtures/compose/src/desktopTest/kotlin/fixture/compose/M3ProofRenderTest.kt diff --git a/ksp-fixtures/compose/src/desktopTest/kotlin/fixture/compose/MaterialIconsRenderTest.kt b/python-multiplatform-compose/fixtures/compose/src/desktopTest/kotlin/fixture/compose/MaterialIconsRenderTest.kt similarity index 100% rename from ksp-fixtures/compose/src/desktopTest/kotlin/fixture/compose/MaterialIconsRenderTest.kt rename to python-multiplatform-compose/fixtures/compose/src/desktopTest/kotlin/fixture/compose/MaterialIconsRenderTest.kt diff --git a/ksp-fixtures/compose/src/desktopTest/kotlin/fixture/compose/MemberResolverComposeTest.kt b/python-multiplatform-compose/fixtures/compose/src/desktopTest/kotlin/fixture/compose/MemberResolverComposeTest.kt similarity index 100% rename from ksp-fixtures/compose/src/desktopTest/kotlin/fixture/compose/MemberResolverComposeTest.kt rename to python-multiplatform-compose/fixtures/compose/src/desktopTest/kotlin/fixture/compose/MemberResolverComposeTest.kt diff --git a/ksp-fixtures/compose/src/desktopTest/kotlin/fixture/compose/ModifierLocalRenderTest.kt b/python-multiplatform-compose/fixtures/compose/src/desktopTest/kotlin/fixture/compose/ModifierLocalRenderTest.kt similarity index 100% rename from ksp-fixtures/compose/src/desktopTest/kotlin/fixture/compose/ModifierLocalRenderTest.kt rename to python-multiplatform-compose/fixtures/compose/src/desktopTest/kotlin/fixture/compose/ModifierLocalRenderTest.kt diff --git a/ksp-fixtures/compose/src/desktopTest/kotlin/fixture/compose/ModifierSeededRenderTest.kt b/python-multiplatform-compose/fixtures/compose/src/desktopTest/kotlin/fixture/compose/ModifierSeededRenderTest.kt similarity index 97% rename from ksp-fixtures/compose/src/desktopTest/kotlin/fixture/compose/ModifierSeededRenderTest.kt rename to python-multiplatform-compose/fixtures/compose/src/desktopTest/kotlin/fixture/compose/ModifierSeededRenderTest.kt index 263996e41..e2e21f9db 100644 --- a/ksp-fixtures/compose/src/desktopTest/kotlin/fixture/compose/ModifierSeededRenderTest.kt +++ b/python-multiplatform-compose/fixtures/compose/src/desktopTest/kotlin/fixture/compose/ModifierSeededRenderTest.kt @@ -29,7 +29,7 @@ import kotlin.test.assertTrue * `Box__Modifier`, has the identical shape and is left equally unreached here). Filling that slot * needs a `Modifier` *value*, and nothing the artefact walker binds can produce one on its own: * `Modifier`'s only source is `androidx.compose.ui.Modifier.Companion`, an object instance, and - * `ArtifactScanner` binds functions, not statics of an arbitrary object. `ksp-fixtures/artifact`'s + * `ArtifactScanner` binds functions, not statics of an arbitrary object. `python-multiplatform-gradle-plugin/fixtures/artifact`'s * `ComposeSeed.kt` hit exactly this wall and solved it with one hand-written Kotlin function that * KSP binds instead; `fixture.compose.emptyModifier` (`PythonComposition.kt`) is that same seed, * placed in this module so `Spacer` has something to receive. @@ -40,7 +40,7 @@ import kotlin.test.assertTrue * reached through `pythonx` (`docs/archive/pythonx-adapter-design.md`'s dynamic loader is for the * composable half of the surface). They come from the *other* producer, * `PythonProxySource` + `FunctionTable`, the route `WalkedArtifactComposeModifierTest` uses for the - * identical seed in `ksp-fixtures/artifact`. Both producers run in the same test here -- + * identical seed in `python-multiplatform-gradle-plugin/fixtures/artifact`. Both producers run in the same test here -- * `PythonxAdapter.install(PYTHONX_RAW_VALUE_CLASSES)` for `Spacer` itself, `PythonProxySource.install()` for the `Modifier` * chain that fills its one argument -- kept out of `ComposableRenderTest`'s shared setup so a * regression in this newer combination cannot fail ten unrelated tests that never asked for it. diff --git a/ksp-fixtures/compose/src/desktopTest/kotlin/fixture/compose/ObjectConstantRenderTest.kt b/python-multiplatform-compose/fixtures/compose/src/desktopTest/kotlin/fixture/compose/ObjectConstantRenderTest.kt similarity index 100% rename from ksp-fixtures/compose/src/desktopTest/kotlin/fixture/compose/ObjectConstantRenderTest.kt rename to python-multiplatform-compose/fixtures/compose/src/desktopTest/kotlin/fixture/compose/ObjectConstantRenderTest.kt diff --git a/ksp-fixtures/compose/src/desktopTest/kotlin/fixture/compose/PointerInputRenderTest.kt b/python-multiplatform-compose/fixtures/compose/src/desktopTest/kotlin/fixture/compose/PointerInputRenderTest.kt similarity index 100% rename from ksp-fixtures/compose/src/desktopTest/kotlin/fixture/compose/PointerInputRenderTest.kt rename to python-multiplatform-compose/fixtures/compose/src/desktopTest/kotlin/fixture/compose/PointerInputRenderTest.kt diff --git a/ksp-fixtures/compose/src/desktopTest/kotlin/fixture/compose/PullRefreshRenderTest.kt b/python-multiplatform-compose/fixtures/compose/src/desktopTest/kotlin/fixture/compose/PullRefreshRenderTest.kt similarity index 100% rename from ksp-fixtures/compose/src/desktopTest/kotlin/fixture/compose/PullRefreshRenderTest.kt rename to python-multiplatform-compose/fixtures/compose/src/desktopTest/kotlin/fixture/compose/PullRefreshRenderTest.kt diff --git a/ksp-fixtures/compose/src/desktopTest/kotlin/fixture/compose/PythonAppViewRenderTest.kt b/python-multiplatform-compose/fixtures/compose/src/desktopTest/kotlin/fixture/compose/PythonAppViewRenderTest.kt similarity index 100% rename from ksp-fixtures/compose/src/desktopTest/kotlin/fixture/compose/PythonAppViewRenderTest.kt rename to python-multiplatform-compose/fixtures/compose/src/desktopTest/kotlin/fixture/compose/PythonAppViewRenderTest.kt diff --git a/ksp-fixtures/compose/src/desktopTest/kotlin/fixture/compose/PythonxModules.kt b/python-multiplatform-compose/fixtures/compose/src/desktopTest/kotlin/fixture/compose/PythonxModules.kt similarity index 100% rename from ksp-fixtures/compose/src/desktopTest/kotlin/fixture/compose/PythonxModules.kt rename to python-multiplatform-compose/fixtures/compose/src/desktopTest/kotlin/fixture/compose/PythonxModules.kt diff --git a/ksp-fixtures/compose/src/desktopTest/kotlin/fixture/compose/RecompositionAccumulationTest.kt b/python-multiplatform-compose/fixtures/compose/src/desktopTest/kotlin/fixture/compose/RecompositionAccumulationTest.kt similarity index 100% rename from ksp-fixtures/compose/src/desktopTest/kotlin/fixture/compose/RecompositionAccumulationTest.kt rename to python-multiplatform-compose/fixtures/compose/src/desktopTest/kotlin/fixture/compose/RecompositionAccumulationTest.kt diff --git a/ksp-fixtures/compose/src/desktopTest/kotlin/fixture/compose/RememberSaveableRenderTest.kt b/python-multiplatform-compose/fixtures/compose/src/desktopTest/kotlin/fixture/compose/RememberSaveableRenderTest.kt similarity index 100% rename from ksp-fixtures/compose/src/desktopTest/kotlin/fixture/compose/RememberSaveableRenderTest.kt rename to python-multiplatform-compose/fixtures/compose/src/desktopTest/kotlin/fixture/compose/RememberSaveableRenderTest.kt diff --git a/ksp-fixtures/compose/src/desktopTest/kotlin/fixture/compose/RetainedSlotSweepPreconditionTest.kt b/python-multiplatform-compose/fixtures/compose/src/desktopTest/kotlin/fixture/compose/RetainedSlotSweepPreconditionTest.kt similarity index 100% rename from ksp-fixtures/compose/src/desktopTest/kotlin/fixture/compose/RetainedSlotSweepPreconditionTest.kt rename to python-multiplatform-compose/fixtures/compose/src/desktopTest/kotlin/fixture/compose/RetainedSlotSweepPreconditionTest.kt diff --git a/ksp-fixtures/compose/src/desktopTest/kotlin/fixture/compose/SwipeableRenderTest.kt b/python-multiplatform-compose/fixtures/compose/src/desktopTest/kotlin/fixture/compose/SwipeableRenderTest.kt similarity index 100% rename from ksp-fixtures/compose/src/desktopTest/kotlin/fixture/compose/SwipeableRenderTest.kt rename to python-multiplatform-compose/fixtures/compose/src/desktopTest/kotlin/fixture/compose/SwipeableRenderTest.kt diff --git a/ksp-fixtures/compose/src/desktopTest/kotlin/fixture/compose/TextFieldStateRenderTest.kt b/python-multiplatform-compose/fixtures/compose/src/desktopTest/kotlin/fixture/compose/TextFieldStateRenderTest.kt similarity index 100% rename from ksp-fixtures/compose/src/desktopTest/kotlin/fixture/compose/TextFieldStateRenderTest.kt rename to python-multiplatform-compose/fixtures/compose/src/desktopTest/kotlin/fixture/compose/TextFieldStateRenderTest.kt diff --git a/ksp-fixtures/compose/src/desktopTest/resources/opaque-square.png b/python-multiplatform-compose/fixtures/compose/src/desktopTest/resources/opaque-square.png similarity index 100% rename from ksp-fixtures/compose/src/desktopTest/resources/opaque-square.png rename to python-multiplatform-compose/fixtures/compose/src/desktopTest/resources/opaque-square.png diff --git a/ksp-fixtures/notebook-e2e/README.md b/python-multiplatform-compose/fixtures/notebook-e2e/README.md similarity index 93% rename from ksp-fixtures/notebook-e2e/README.md rename to python-multiplatform-compose/fixtures/notebook-e2e/README.md index f08931eee..dcba884bd 100644 --- a/ksp-fixtures/notebook-e2e/README.md +++ b/python-multiplatform-compose/fixtures/notebook-e2e/README.md @@ -1,4 +1,4 @@ -# `:ksp-fixtures:notebook-e2e`: pythonx-compose's `UI.ipynb`, end to end +# `:python-multiplatform-compose:fixtures:notebook-e2e`: pythonx-compose's `UI.ipynb`, end to end Issue #26. A desktop host draws a Python-declared root through `python-multiplatform-compose` (`PythonAppView(module = "pythonx.compose.runtime", attribute = "app_root")`, #18), with the **pythonx-compose wheel @@ -30,7 +30,7 @@ The result is `.tmp/pythonx-compose-dist/pythonx_compose--py3-none-any. ## Running ```bash -JAVA_HOME= ./gradlew :ksp-fixtures:notebook-e2e:desktopTest --rerun \ +JAVA_HOME= ./gradlew :python-multiplatform-compose:fixtures:notebook-e2e:desktopTest --rerun \ -PpythonxComposeWheel=.tmp/pythonx-compose-dist --console=plain > .tmp/notebook-e2e.log 2>&1; echo "EXIT=$?" ``` @@ -99,10 +99,10 @@ if (composing.isNotEmpty()) setComposingText(composing, 1) }`. Not exercised: th | cells 2–3 (`print`, numpy) | not UI | | cell 5: `remember_saveable`, `DefaultCoroutineScope`, `MainCoroutineScope` | undecided in pythonx-compose (INTENT §4.1, SPEC §8); nothing provides them | | cell 5/25/35/…: lower-case `modifier`, `modifier=modifier` | INTENT §5.4 replaces it with `modifier=Modifier`. The binder has no conversion for a proxy **class** passed as an argument (`Modifier.empty()` is used only for the class-spelling *method call*, `PythonxAdapter.kt` `_BoundMember`), so `Card(modifier=Modifier)` is not expected to work; the argument is left out, which is the same Kotlin default (`Modifier`). Not run to confirm. | -| cell 22/23/30/35: `corner_radius=` on `Button`; cell 25/40: on `Card` | Kotlin's counterpart is `shape=RoundedCornerShape(...)` from `androidx.compose.foundation.shape`, which this fixture does not walk (its package list is `:ksp-fixtures:compose`'s). Adding `"androidx.compose.foundation.shape"` to `artifactIncludePackages` is the next step; not tried. | +| cell 22/23/30/35: `corner_radius=` on `Button`; cell 25/40: on `Card` | Kotlin's counterpart is `shape=RoundedCornerShape(...)` from `androidx.compose.foundation.shape`, which this fixture does not walk (its package list is `:python-multiplatform-compose:fixtures:compose`'s). Adding `"androidx.compose.foundation.shape"` to `artifactIncludePackages` is the next step; not tried. | | cell 22/23/25/…: `color=` on `Button`/`Card` | written as Kotlin's `colors=ButtonColors(...)` / `CardColors(...)` constructors. `ButtonDefaults.buttonColors(...)`, the usual Kotlin spelling, is a `@Composable` object function, which the walker declines (SPEC B-1). | | cell 27: `help(DefaultIcons)` | prints documentation; nothing to assert on screen | | cells 42, 48: empty; "채팅 화면 디자인하기" | no content | | cells 44–47: `from ws import client` | a websocket client outside pythonx-compose; marked "재 구현 필요" in the notebook | | cells 51–56: Llama 3.1 streaming into the UI | needs a model and `main.run_llama3`; the state half (writing `.value` from a loop) is cell 12's mechanism | -| cell 54: `onclick=lambda: {...}` driving a state change | a click from Python reaching a Kotlin callback is `:ksp-fixtures:compose`'s `CallbackDrivenRenderTest`; not repeated here | +| cell 54: `onclick=lambda: {...}` driving a state change | a click from Python reaching a Kotlin callback is `:python-multiplatform-compose:fixtures:compose`'s `CallbackDrivenRenderTest`; not repeated here | diff --git a/ksp-fixtures/notebook-e2e/build.gradle.kts b/python-multiplatform-compose/fixtures/notebook-e2e/build.gradle.kts similarity index 94% rename from ksp-fixtures/notebook-e2e/build.gradle.kts rename to python-multiplatform-compose/fixtures/notebook-e2e/build.gradle.kts index 8670f33a9..c944ec2eb 100644 --- a/ksp-fixtures/notebook-e2e/build.gradle.kts +++ b/python-multiplatform-compose/fixtures/notebook-e2e/build.gradle.kts @@ -24,7 +24,7 @@ import org.jetbrains.kotlin.gradle.dsl.JvmTarget * [installPythonxComposeWheel] unpacks it into `build/pythonx-compose/site-packages`. * * The rest -- the Compose compiler plugin, the walked packages, the JVM flags -- is - * `:ksp-fixtures:compose`'s configuration, kept identical where it can be so that a difference in + * `:python-multiplatform-compose:fixtures:compose`'s configuration, kept identical where it can be so that a difference in * result is a difference in what the notebook asks for, not in the build. */ plugins { @@ -73,7 +73,7 @@ pythonBindings { artifactConfiguration.set("desktopCompileClasspath") artifactSourceSet.set("desktopMain") - // The same list as `:ksp-fixtures:compose` (its build file says what each entry is for). Every + // The same list as `:python-multiplatform-compose:fixtures:compose` (its build file says what each entry is for). Every // `pythonx.compose.*` module the notebook imports maps onto one of these Kotlin packages // (pythonx-compose's `pythonx-map.toml`); a package not walked here is a name pythonx cannot // resolve, which is a fixture gap, not a pythonx one. @@ -106,7 +106,7 @@ val notebookSkipped: Boolean = providers.gradleProperty("notebookE2e.skip") /** The wheel to install, or why there is none. Exactly one of the two is non-null. */ fun resolveWheel(): Pair { - val howTo = "Build it (ksp-fixtures/notebook-e2e/README.md) and pass -PpythonxComposeWheel= " + + val howTo = "Build it (python-multiplatform-compose/fixtures/notebook-e2e/README.md) and pass -PpythonxComposeWheel= " + "(or PYTHONX_COMPOSE_WHEEL); to skip the notebook scenarios deliberately pass -PnotebookE2e.skip=true." val input = wheelInput ?: return null to "No pythonx-compose wheel was given, so the UI.ipynb scenarios cannot run. $howTo" @@ -153,7 +153,7 @@ if (notebookSkipped) { } /** - * The same JVM `:ksp-fixtures:compose`'s tests need: JDK 21 with the preview FFM API, a + * The same JVM `:python-multiplatform-compose:fixtures:compose`'s tests need: JDK 21 with the preview FFM API, a * `java.library.path` for the extracted `libpython`, and a headless AWT. */ tasks.named("desktopTest") { diff --git a/ksp-fixtures/notebook-e2e/src/desktopMain/kotlin/fixture/notebook/EmptyModifier.kt b/python-multiplatform-compose/fixtures/notebook-e2e/src/desktopMain/kotlin/fixture/notebook/EmptyModifier.kt similarity index 100% rename from ksp-fixtures/notebook-e2e/src/desktopMain/kotlin/fixture/notebook/EmptyModifier.kt rename to python-multiplatform-compose/fixtures/notebook-e2e/src/desktopMain/kotlin/fixture/notebook/EmptyModifier.kt diff --git a/ksp-fixtures/notebook-e2e/src/desktopTest/kotlin/fixture/notebook/InputMethodScene.kt b/python-multiplatform-compose/fixtures/notebook-e2e/src/desktopTest/kotlin/fixture/notebook/InputMethodScene.kt similarity index 100% rename from ksp-fixtures/notebook-e2e/src/desktopTest/kotlin/fixture/notebook/InputMethodScene.kt rename to python-multiplatform-compose/fixtures/notebook-e2e/src/desktopTest/kotlin/fixture/notebook/InputMethodScene.kt diff --git a/ksp-fixtures/notebook-e2e/src/desktopTest/kotlin/fixture/notebook/NotebookHost.kt b/python-multiplatform-compose/fixtures/notebook-e2e/src/desktopTest/kotlin/fixture/notebook/NotebookHost.kt similarity index 100% rename from ksp-fixtures/notebook-e2e/src/desktopTest/kotlin/fixture/notebook/NotebookHost.kt rename to python-multiplatform-compose/fixtures/notebook-e2e/src/desktopTest/kotlin/fixture/notebook/NotebookHost.kt diff --git a/ksp-fixtures/notebook-e2e/src/desktopTest/kotlin/fixture/notebook/NotebookPracticeTest.kt b/python-multiplatform-compose/fixtures/notebook-e2e/src/desktopTest/kotlin/fixture/notebook/NotebookPracticeTest.kt similarity index 100% rename from ksp-fixtures/notebook-e2e/src/desktopTest/kotlin/fixture/notebook/NotebookPracticeTest.kt rename to python-multiplatform-compose/fixtures/notebook-e2e/src/desktopTest/kotlin/fixture/notebook/NotebookPracticeTest.kt diff --git a/ksp-fixtures/notebook-e2e/src/desktopTest/kotlin/fixture/notebook/NotebookRootTest.kt b/python-multiplatform-compose/fixtures/notebook-e2e/src/desktopTest/kotlin/fixture/notebook/NotebookRootTest.kt similarity index 100% rename from ksp-fixtures/notebook-e2e/src/desktopTest/kotlin/fixture/notebook/NotebookRootTest.kt rename to python-multiplatform-compose/fixtures/notebook-e2e/src/desktopTest/kotlin/fixture/notebook/NotebookRootTest.kt diff --git a/ksp-fixtures/notebook-e2e/src/desktopTest/kotlin/fixture/notebook/NotebookTextFieldTest.kt b/python-multiplatform-compose/fixtures/notebook-e2e/src/desktopTest/kotlin/fixture/notebook/NotebookTextFieldTest.kt similarity index 100% rename from ksp-fixtures/notebook-e2e/src/desktopTest/kotlin/fixture/notebook/NotebookTextFieldTest.kt rename to python-multiplatform-compose/fixtures/notebook-e2e/src/desktopTest/kotlin/fixture/notebook/NotebookTextFieldTest.kt diff --git a/ksp-fixtures/notebook-e2e/src/desktopTest/python/main.py b/python-multiplatform-compose/fixtures/notebook-e2e/src/desktopTest/python/main.py similarity index 100% rename from ksp-fixtures/notebook-e2e/src/desktopTest/python/main.py rename to python-multiplatform-compose/fixtures/notebook-e2e/src/desktopTest/python/main.py diff --git a/python-multiplatform-gradle-plugin/build.gradle.kts b/python-multiplatform-gradle-plugin/build.gradle.kts index 4f767181e..98bf33ff3 100644 --- a/python-multiplatform-gradle-plugin/build.gradle.kts +++ b/python-multiplatform-gradle-plugin/build.gradle.kts @@ -72,7 +72,7 @@ dependencies { // - not in the library. `python-multiplatform` does not depend on this plugin; // `:python-multiplatform:dependencies` reports `kotlin-compiler-embeddable:2.0.20` in no // configuration at all, `desktopRuntimeClasspath` included. - // - not on a consumer's *application* classpath. `:ksp-fixtures:app:dependencies` reports zero + // - not on a consumer's *application* classpath. `:python-multiplatform-ksp:fixtures:app:dependencies` reports zero // occurrences of `2.0.20`. (It does report `kotlin-compiler-embeddable:2.4.0` and // `2.4.20-Beta2` under `kotlinCompilerPluginClasspath*` and the commonizer's configurations // -- KGP's own, present before this dependency existed.) @@ -125,7 +125,7 @@ dependencies { // classloader's parent is Gradle's own minimal worker infrastructure, not that root scope, so // `org.jetbrains.kotlin.library.*` has exactly one source inside the worker. Confirmed against a // real consumer build, not only this plugin's own unit tests: - // `:ksp-fixtures:klib-artifact:generatePythonArtifactBindings` and `:generatePythonStubs` both + // `:python-multiplatform-gradle-plugin-fixtures:klib-artifact:generatePythonArtifactBindings` and `:generatePythonStubs` both // pass and emit the walker's real output (`kotlinx.coroutines.flow.internal.checkIndexOverflow`). // // ### Compile-only here, resolved by the consumer at klib-walking time diff --git a/ksp-fixtures/artifact-valueclass/build.gradle.kts b/python-multiplatform-gradle-plugin/fixtures/artifact-valueclass/build.gradle.kts similarity index 90% rename from ksp-fixtures/artifact-valueclass/build.gradle.kts rename to python-multiplatform-gradle-plugin/fixtures/artifact-valueclass/build.gradle.kts index 5c12a588a..7a0218307 100644 --- a/ksp-fixtures/artifact-valueclass/build.gradle.kts +++ b/python-multiplatform-gradle-plugin/fixtures/artifact-valueclass/build.gradle.kts @@ -4,7 +4,7 @@ * * `kotlin.time.Duration` (the real-world case `ArtifactScanner`'s KDoc discusses) cannot prove a * *positive* round trip: its constructor is `internal`, so no generated Kotlin outside - * `kotlin-stdlib` can ever build one. This module exists only to be walked -- like `:ksp-fixtures + * `kotlin-stdlib` can ever build one. This module exists only to be walked -- like `:python-multiplatform-gradle-plugin-fixtures * :artifact`'s `junit` dependency, it is a plain `kotlin("jvm")` library with no bindings plugin of * its own applied, resolved as an ordinary dependency and never compiled by the module that walks * it. diff --git a/ksp-fixtures/artifact-valueclass/src/main/kotlin/fixture/valueclass/Meters.kt b/python-multiplatform-gradle-plugin/fixtures/artifact-valueclass/src/main/kotlin/fixture/valueclass/Meters.kt similarity index 82% rename from ksp-fixtures/artifact-valueclass/src/main/kotlin/fixture/valueclass/Meters.kt rename to python-multiplatform-gradle-plugin/fixtures/artifact-valueclass/src/main/kotlin/fixture/valueclass/Meters.kt index e627cab6a..92d67b377 100644 --- a/ksp-fixtures/artifact-valueclass/src/main/kotlin/fixture/valueclass/Meters.kt +++ b/python-multiplatform-gradle-plugin/fixtures/artifact-valueclass/src/main/kotlin/fixture/valueclass/Meters.kt @@ -1,4 +1,4 @@ -// Never compiled by `:ksp-fixtures:artifact`, which only ever sees this module's resolved jar -- +// Never compiled by `:python-multiplatform-gradle-plugin-fixtures:artifact`, which only ever sees this module's resolved jar -- // see the `build.gradle.kts` doc comment on why this module exists at all. package fixture.valueclass diff --git a/ksp-fixtures/artifact/build.gradle.kts b/python-multiplatform-gradle-plugin/fixtures/artifact/build.gradle.kts similarity index 96% rename from ksp-fixtures/artifact/build.gradle.kts rename to python-multiplatform-gradle-plugin/fixtures/artifact/build.gradle.kts index c8857893c..f7369a9c5 100644 --- a/ksp-fixtures/artifact/build.gradle.kts +++ b/python-multiplatform-gradle-plugin/fixtures/artifact/build.gradle.kts @@ -6,11 +6,11 @@ import org.jetbrains.kotlin.gradle.dsl.JvmTarget * installed into the same `UpcallTable` KSP's own fragments go into, and imported from Python. * * `docs/design/ecosystem.md` §5b names two producers of bindings and splits them by *what they look at* -- - * KSP the consumer's own source, the walker everything the build resolves. `:ksp-fixtures:app` + * KSP the consumer's own source, the walker everything the build resolves. `:python-multiplatform-ksp:fixtures:app` * covers the first. Nothing covered the second, which is why `androidx.compose.material3` was * believed to be unreachable. * - * Deliberately a module of its own rather than another target in `:ksp-fixtures:app`: that module's + * Deliberately a module of its own rather than another target in `:python-multiplatform-ksp:fixtures:app`: that module's * `CommonInstallTest` asserts `UpcallTable.moduleNames` **exactly**, and a walked artefact appearing * there would be a change to what `FunctionTable` means rather than an addition beside it. Keeping * the two apart in the build is the same judgement `ArtifactTableRenderingTest` records for the @@ -46,7 +46,7 @@ kotlin { implementation(libs.junit) // See its own `build.gradle.kts`: a real jar for the value-class round trip // `kotlin.time.Duration` cannot prove. - implementation(projects.kspFixtures.artifactValueclass) + implementation(projects.pythonMultiplatformGradlePluginFixtures.artifactValueclass) // Compose Multiplatform, as plain Maven coordinates and **without** the Compose // Gradle or compiler plugin. That is deliberate and is the whole shape of the claim: @@ -99,7 +99,7 @@ pythonBindings { // `ArtifactScanner`'s KDoc names as unreachable before it read `@Metadata` -- a top-level // extension function behind a `MULTI_FILE_CLASS_FACADE`. `WalkedArtifactPythonImportTest` calls // it from real Python. - // `fixture.valueclass` is `:ksp-fixtures:artifact-valueclass`'s `Meters`/`sumMeters` -- see that + // `fixture.valueclass` is `:python-multiplatform-gradle-plugin-fixtures:artifact-valueclass`'s `Meters`/`sumMeters` -- see that // module's `build.gradle.kts` for why `kotlin.time.Duration` cannot stand in for it. // // `androidx.compose.foundation.layout` is the scorecard of diff --git a/ksp-fixtures/artifact/src/commonMain/kotlin/fixture/artifact/OwnDeclarations.kt b/python-multiplatform-gradle-plugin/fixtures/artifact/src/commonMain/kotlin/fixture/artifact/OwnDeclarations.kt similarity index 100% rename from ksp-fixtures/artifact/src/commonMain/kotlin/fixture/artifact/OwnDeclarations.kt rename to python-multiplatform-gradle-plugin/fixtures/artifact/src/commonMain/kotlin/fixture/artifact/OwnDeclarations.kt diff --git a/ksp-fixtures/artifact/src/desktopMain/kotlin/fixture/artifact/ComposeSeed.kt b/python-multiplatform-gradle-plugin/fixtures/artifact/src/desktopMain/kotlin/fixture/artifact/ComposeSeed.kt similarity index 100% rename from ksp-fixtures/artifact/src/desktopMain/kotlin/fixture/artifact/ComposeSeed.kt rename to python-multiplatform-gradle-plugin/fixtures/artifact/src/desktopMain/kotlin/fixture/artifact/ComposeSeed.kt diff --git a/ksp-fixtures/artifact/src/desktopTest/kotlin/fixture/artifact/PythonxModules.kt b/python-multiplatform-gradle-plugin/fixtures/artifact/src/desktopTest/kotlin/fixture/artifact/PythonxModules.kt similarity index 100% rename from ksp-fixtures/artifact/src/desktopTest/kotlin/fixture/artifact/PythonxModules.kt rename to python-multiplatform-gradle-plugin/fixtures/artifact/src/desktopTest/kotlin/fixture/artifact/PythonxModules.kt diff --git a/ksp-fixtures/artifact/src/desktopTest/kotlin/fixture/artifact/StubSignatureAgreesWithRuntimeTest.kt b/python-multiplatform-gradle-plugin/fixtures/artifact/src/desktopTest/kotlin/fixture/artifact/StubSignatureAgreesWithRuntimeTest.kt similarity index 100% rename from ksp-fixtures/artifact/src/desktopTest/kotlin/fixture/artifact/StubSignatureAgreesWithRuntimeTest.kt rename to python-multiplatform-gradle-plugin/fixtures/artifact/src/desktopTest/kotlin/fixture/artifact/StubSignatureAgreesWithRuntimeTest.kt diff --git a/ksp-fixtures/artifact/src/desktopTest/kotlin/fixture/artifact/WalkedArtifactCallbackTest.kt b/python-multiplatform-gradle-plugin/fixtures/artifact/src/desktopTest/kotlin/fixture/artifact/WalkedArtifactCallbackTest.kt similarity index 99% rename from ksp-fixtures/artifact/src/desktopTest/kotlin/fixture/artifact/WalkedArtifactCallbackTest.kt rename to python-multiplatform-gradle-plugin/fixtures/artifact/src/desktopTest/kotlin/fixture/artifact/WalkedArtifactCallbackTest.kt index a37599f4e..8c6447608 100644 --- a/ksp-fixtures/artifact/src/desktopTest/kotlin/fixture/artifact/WalkedArtifactCallbackTest.kt +++ b/python-multiplatform-gradle-plugin/fixtures/artifact/src/desktopTest/kotlin/fixture/artifact/WalkedArtifactCallbackTest.kt @@ -41,7 +41,7 @@ import kotlin.test.assertTrue * () -> Unit)` has the identical slot (`kotlin.Function0()->kotlin.Unit`, same walker, same * fragment, same `PythonFunction` wrapper) and invokes it at the moment it is called, so it is what * makes "the callback is called" a measurement rather than an inference. Rendering a real click is - * `:ksp-fixtures:compose`'s job and needs the Compose compiler plugin this module deliberately does + * `:python-multiplatform-compose:fixtures:compose`'s job and needs the Compose compiler plugin this module deliberately does * not apply. * * ### Lifetime diff --git a/ksp-fixtures/artifact/src/desktopTest/kotlin/fixture/artifact/WalkedArtifactComposeModifierTest.kt b/python-multiplatform-gradle-plugin/fixtures/artifact/src/desktopTest/kotlin/fixture/artifact/WalkedArtifactComposeModifierTest.kt similarity index 100% rename from ksp-fixtures/artifact/src/desktopTest/kotlin/fixture/artifact/WalkedArtifactComposeModifierTest.kt rename to python-multiplatform-gradle-plugin/fixtures/artifact/src/desktopTest/kotlin/fixture/artifact/WalkedArtifactComposeModifierTest.kt diff --git a/ksp-fixtures/artifact/src/desktopTest/kotlin/fixture/artifact/WalkedArtifactDefaultOmissionTest.kt b/python-multiplatform-gradle-plugin/fixtures/artifact/src/desktopTest/kotlin/fixture/artifact/WalkedArtifactDefaultOmissionTest.kt similarity index 100% rename from ksp-fixtures/artifact/src/desktopTest/kotlin/fixture/artifact/WalkedArtifactDefaultOmissionTest.kt rename to python-multiplatform-gradle-plugin/fixtures/artifact/src/desktopTest/kotlin/fixture/artifact/WalkedArtifactDefaultOmissionTest.kt diff --git a/ksp-fixtures/artifact/src/desktopTest/kotlin/fixture/artifact/WalkedArtifactPythonImportTest.kt b/python-multiplatform-gradle-plugin/fixtures/artifact/src/desktopTest/kotlin/fixture/artifact/WalkedArtifactPythonImportTest.kt similarity index 98% rename from ksp-fixtures/artifact/src/desktopTest/kotlin/fixture/artifact/WalkedArtifactPythonImportTest.kt rename to python-multiplatform-gradle-plugin/fixtures/artifact/src/desktopTest/kotlin/fixture/artifact/WalkedArtifactPythonImportTest.kt index ae8d02744..e7bc5d65d 100644 --- a/ksp-fixtures/artifact/src/desktopTest/kotlin/fixture/artifact/WalkedArtifactPythonImportTest.kt +++ b/python-multiplatform-gradle-plugin/fixtures/artifact/src/desktopTest/kotlin/fixture/artifact/WalkedArtifactPythonImportTest.kt @@ -137,7 +137,7 @@ class WalkedArtifactPythonImportTest { /** * `fixture.valueclass.sumMeters`: both parameters and the return are a public - * `@JvmInline value class` (`Meters`), from `:ksp-fixtures:artifact-valueclass` -- a jar built + * `@JvmInline value class` (`Meters`), from `:python-multiplatform-gradle-plugin-fixtures:artifact-valueclass` -- a jar built * for exactly this proof, since `kotlin.time.Duration` (the real-world case) has an `internal` * constructor and so can never round-trip. `12.0` is not producible except by unwrapping two * `Meters` arguments, adding them, and wrapping the sum back up. diff --git a/ksp-fixtures/artifact/src/desktopTest/kotlin/fixture/artifact/WalkedArtifactStubTest.kt b/python-multiplatform-gradle-plugin/fixtures/artifact/src/desktopTest/kotlin/fixture/artifact/WalkedArtifactStubTest.kt similarity index 100% rename from ksp-fixtures/artifact/src/desktopTest/kotlin/fixture/artifact/WalkedArtifactStubTest.kt rename to python-multiplatform-gradle-plugin/fixtures/artifact/src/desktopTest/kotlin/fixture/artifact/WalkedArtifactStubTest.kt diff --git a/ksp-fixtures/artifact/src/desktopTest/kotlin/fixture/artifact/WalkedArtifactTableTest.kt b/python-multiplatform-gradle-plugin/fixtures/artifact/src/desktopTest/kotlin/fixture/artifact/WalkedArtifactTableTest.kt similarity index 95% rename from ksp-fixtures/artifact/src/desktopTest/kotlin/fixture/artifact/WalkedArtifactTableTest.kt rename to python-multiplatform-gradle-plugin/fixtures/artifact/src/desktopTest/kotlin/fixture/artifact/WalkedArtifactTableTest.kt index 569fa47bf..9a6454e2e 100644 --- a/ksp-fixtures/artifact/src/desktopTest/kotlin/fixture/artifact/WalkedArtifactTableTest.kt +++ b/python-multiplatform-gradle-plugin/fixtures/artifact/src/desktopTest/kotlin/fixture/artifact/WalkedArtifactTableTest.kt @@ -32,7 +32,7 @@ class WalkedArtifactTableTest { /** * The wiring, pinned against the two artefacts this fixture fully controls. * - * `junit:junit:4.13.2` and `:ksp-fixtures:artifact-valueclass` are both version-pinned by this + * `junit:junit:4.13.2` and `:python-multiplatform-gradle-plugin-fixtures:artifact-valueclass` are both version-pinned by this * build, so their contribution is a fixed list and `ArtifactScannerTest * .theWholeJUnitJarYieldsExactlyTheseUnsuffixedDeclarations` pins the same seven names from the * other end -- that test walks the jar directly in a plugin unit test, this one reads what the @@ -53,10 +53,10 @@ class WalkedArtifactTableTest { assertEquals( listOf( - // `:ksp-fixtures:artifact-valueclass`, built for exactly one proof: see that + // `:python-multiplatform-gradle-plugin-fixtures:artifact-valueclass`, built for exactly one proof: see that // module's `build.gradle.kts`. `Meters` is the value class's own constructor, // bound since `e2d75100` -- this list predates that and was never updated, which - // nothing noticed because `ksp-fixtures:artifact` is not in the usual verification + // nothing noticed because `python-multiplatform-gradle-plugin-fixtures:artifact` is not in the usual verification // set. `ArtifactScannerTest` pins the same constructor from the plugin side. "fixture.valueclass.Meters", "fixture.valueclass.sumMeters", diff --git a/ksp-fixtures/artifact/src/desktopTest/kotlin/fixture/artifact/WalkedArtifactValueClassBoxTest.kt b/python-multiplatform-gradle-plugin/fixtures/artifact/src/desktopTest/kotlin/fixture/artifact/WalkedArtifactValueClassBoxTest.kt similarity index 100% rename from ksp-fixtures/artifact/src/desktopTest/kotlin/fixture/artifact/WalkedArtifactValueClassBoxTest.kt rename to python-multiplatform-gradle-plugin/fixtures/artifact/src/desktopTest/kotlin/fixture/artifact/WalkedArtifactValueClassBoxTest.kt diff --git a/ksp-fixtures/klib-artifact/build.gradle.kts b/python-multiplatform-gradle-plugin/fixtures/klib-artifact/build.gradle.kts similarity index 90% rename from ksp-fixtures/klib-artifact/build.gradle.kts rename to python-multiplatform-gradle-plugin/fixtures/klib-artifact/build.gradle.kts index cfb76ef3a..fb5f8962f 100644 --- a/ksp-fixtures/klib-artifact/build.gradle.kts +++ b/python-multiplatform-gradle-plugin/fixtures/klib-artifact/build.gradle.kts @@ -3,7 +3,7 @@ * walked at build time by `KlibScanner`, installed into the same `UpcallTable` KSP's own fragments * go into. * - * `:ksp-fixtures:artifact` is `docs/design/ecosystem.md` §5b's second producer over a **jar** -- this is + * `:python-multiplatform-gradle-plugin-fixtures:artifact` is `docs/design/ecosystem.md` §5b's second producer over a **jar** -- this is * the same producer over a **klib**, ROADMAP §16e's "investigated, not implemented" half. One target * only, and it is `androidNativeArm64` rather than `desktop`: a jar is what a JVM target resolves, a * klib is what a Kotlin/Native target resolves, and `PythonArtifactBindingsTask @@ -24,9 +24,9 @@ * suite runs like this, reusing the payload that task already stages on the device: * * ./gradlew :python-multiplatform:androidNativeArm64Test # once: stages lib/ and the stdlib - * ./gradlew :ksp-fixtures:klib-artifact:linkDebugTestAndroidNativeArm64 + * ./gradlew :python-multiplatform-gradle-plugin-fixtures:klib-artifact:linkDebugTestAndroidNativeArm64 * D=/data/local/tmp/pmp-nativetest-arm64-v8a - * adb push ksp-fixtures/klib-artifact/build/bin/androidNativeArm64/debugTest/test.kexe \ + * adb push python-multiplatform-gradle-plugin/fixtures/klib-artifact/build/bin/androidNativeArm64/debugTest/test.kexe \ * $D/klibtest.kexe * adb shell "chmod 755 $D/klibtest.kexe && cd $D && \ * LD_LIBRARY_PATH=$D/lib PYTHONHOME=$D ./klibtest.kexe --ktest_logger=TEAMCITY" @@ -40,7 +40,7 @@ plugins { kotlin { androidNativeArm64 { - // Mirrors `:ksp-fixtures:app`'s own androidNativeArm64 linker config: the test binary needs + // Mirrors `:python-multiplatform-ksp:fixtures:app`'s own androidNativeArm64 linker config: the test binary needs // the same CPython symbols resolved at final link time, since `python-multiplatform`'s klib // only declares them via cinterop and does not itself embed a static libpython. val downloadDir = project(":python-multiplatform").layout.buildDirectory.dir("python-standalone").get().asFile diff --git a/ksp-fixtures/klib-artifact/src/androidNativeArm64Test/kotlin/fixture/artifact/WalkedKlibArtifactPythonImportTest.kt b/python-multiplatform-gradle-plugin/fixtures/klib-artifact/src/androidNativeArm64Test/kotlin/fixture/artifact/WalkedKlibArtifactPythonImportTest.kt similarity index 97% rename from ksp-fixtures/klib-artifact/src/androidNativeArm64Test/kotlin/fixture/artifact/WalkedKlibArtifactPythonImportTest.kt rename to python-multiplatform-gradle-plugin/fixtures/klib-artifact/src/androidNativeArm64Test/kotlin/fixture/artifact/WalkedKlibArtifactPythonImportTest.kt index 388e20a0f..a9e748d4c 100644 --- a/ksp-fixtures/klib-artifact/src/androidNativeArm64Test/kotlin/fixture/artifact/WalkedKlibArtifactPythonImportTest.kt +++ b/python-multiplatform-gradle-plugin/fixtures/klib-artifact/src/androidNativeArm64Test/kotlin/fixture/artifact/WalkedKlibArtifactPythonImportTest.kt @@ -14,7 +14,7 @@ import kotlin.test.Test * The whole klib path in one interpreter, on a **Kotlin/Native** target: a `.klib` the build * resolved -> `KlibScanner` -> an (empty) `ArtifactTable` -> `UpcallTable` -> `PythonProxySource`. * - * `:ksp-fixtures:artifact`'s `WalkedArtifactPythonImportTest` made a *positive* version of this claim + * `:python-multiplatform-gradle-plugin-fixtures:artifact`'s `WalkedArtifactPythonImportTest` made a *positive* version of this claim * for a **jar** on **desktop**: a bound declaration reaches Python and is callable. This class makes * the negative half instead -- see `WalkedKlibArtifactTableTest`'s KDoc for why `kotlinx-coroutines * -core`'s klib half of the shared namespace is correctly *empty*, not merely small. Both matter: a diff --git a/ksp-fixtures/klib-artifact/src/androidNativeArm64Test/kotlin/fixture/artifact/WalkedKlibArtifactTableTest.kt b/python-multiplatform-gradle-plugin/fixtures/klib-artifact/src/androidNativeArm64Test/kotlin/fixture/artifact/WalkedKlibArtifactTableTest.kt similarity index 97% rename from ksp-fixtures/klib-artifact/src/androidNativeArm64Test/kotlin/fixture/artifact/WalkedKlibArtifactTableTest.kt rename to python-multiplatform-gradle-plugin/fixtures/klib-artifact/src/androidNativeArm64Test/kotlin/fixture/artifact/WalkedKlibArtifactTableTest.kt index 77c635a40..e31dc8fc1 100644 --- a/ksp-fixtures/klib-artifact/src/androidNativeArm64Test/kotlin/fixture/artifact/WalkedKlibArtifactTableTest.kt +++ b/python-multiplatform-gradle-plugin/fixtures/klib-artifact/src/androidNativeArm64Test/kotlin/fixture/artifact/WalkedKlibArtifactTableTest.kt @@ -21,7 +21,7 @@ import kotlin.test.assertTrue * among them) that `KlibScanner` **used to** bind before this suite ever ran on a device: it is * binary-visible so an inline call site inside `kotlinx-coroutines-core` itself can resolve it, but * not source-visible from a generated fragment in a *different* module, and - * `:ksp-fixtures:klib-artifact:compileKotlinAndroidNativeArm64` failing with "it is internal in file" + * `:python-multiplatform-gradle-plugin-fixtures:klib-artifact:compileKotlinAndroidNativeArm64` failing with "it is internal in file" * -- the first time this walker's generated Kotlin was ever actually compiled rather than only * unit-tested -- is what caught it. `KlibScanWorkAction`'s KDoc has the full story; `KlibScannerTest * .aPublishedApiInternalDeclarationIsDeclinedWithItsOwnReason` pins the fix on the JVM side, and this diff --git a/ksp-fixtures/klib-artifact/src/commonMain/kotlin/fixture/artifact/OwnDeclarations.kt b/python-multiplatform-gradle-plugin/fixtures/klib-artifact/src/commonMain/kotlin/fixture/artifact/OwnDeclarations.kt similarity index 88% rename from ksp-fixtures/klib-artifact/src/commonMain/kotlin/fixture/artifact/OwnDeclarations.kt rename to python-multiplatform-gradle-plugin/fixtures/klib-artifact/src/commonMain/kotlin/fixture/artifact/OwnDeclarations.kt index 363edd21e..276ce3031 100644 --- a/ksp-fixtures/klib-artifact/src/commonMain/kotlin/fixture/artifact/OwnDeclarations.kt +++ b/python-multiplatform-gradle-plugin/fixtures/klib-artifact/src/commonMain/kotlin/fixture/artifact/OwnDeclarations.kt @@ -7,7 +7,7 @@ package fixture.artifact * `ArtifactTable`. * * **Kept, not deleted with the rest of the copied-from-`:artifact` fixture.** Everything else this - * module inherited from `:ksp-fixtures:artifact` was a *jar*-path duplicate and went, but this file + * module inherited from `:python-multiplatform-gradle-plugin-fixtures:artifact` was a *jar*-path duplicate and went, but this file * is not about jars: `pythonBindings.role.set("app")` makes this module the aggregator, and an * aggregator with no source declarations of its own emits an **empty** `FunctionTable`. That * compiles and passes, and it quietly stops the fixture from demonstrating the one property diff --git a/python-multiplatform-gradle-plugin/src/main/kotlin/python/multiplatform/gradle/PythonBindingsPlugin.kt b/python-multiplatform-gradle-plugin/src/main/kotlin/python/multiplatform/gradle/PythonBindingsPlugin.kt index 37bc48745..14755281b 100644 --- a/python-multiplatform-gradle-plugin/src/main/kotlin/python/multiplatform/gradle/PythonBindingsPlugin.kt +++ b/python-multiplatform-gradle-plugin/src/main/kotlin/python/multiplatform/gradle/PythonBindingsPlugin.kt @@ -12,7 +12,7 @@ import python.multiplatform.gradle.stubs.PythonStubsTask * KSP option names. Copied rather than imported: these are the processor's * `python.multiplatform.ksp.Constants`, and this plugin ships as a separate build so that a * consumer resolves it from the plugin portal without also resolving the processor's compile - * classpath. Changing one without the other shows up in `ksp-fixtures` as an unwired module. + * classpath. Changing one without the other shows up in the `fixtures/` modules as an unwired module. */ private const val OPTION_ROLE = "python.multiplatform.role" private const val OPTION_MODULE_NAME = "python.multiplatform.moduleName" @@ -53,7 +53,7 @@ private const val TYPEDPYTHON_STUBS_CONFIGURATION = "typedpythonStubs" * and a second `FunctionTable` -- into the test compilation, where they shadowed the real ones * from `main`, because a compilation's own generated sources win over its classpath. The symptom * is a table holding the test classes and nothing the module actually exposes. - * `ksp-fixtures/android` is what surfaced this; no module without an Android plugin can. + * `python-multiplatform-ksp/fixtures/android` is what surfaced this; no module without an Android plugin can. * * `Test` is therefore matched as a camel-case *word* rather than as a suffix: it must start a word * and end one. A target or product flavour genuinely named `testing` is not a test compilation and @@ -96,7 +96,7 @@ internal fun deriveModuleName(group: String, path: String, name: String): String * package, so two of them collide. Gradle has no general notion of "the module that ships", and * a Kotlin Multiplatform module that builds a framework or a native executable carries no plugin * that distinguishes it -- hence the explicit `role` override on the extension, which is what - * `ksp-fixtures/app` uses. + * `python-multiplatform-ksp/fixtures/app` uses. */ internal fun inferRole(hasApplicationPlugin: Boolean, hasAndroidApplicationPlugin: Boolean): String = if (hasApplicationPlugin || hasAndroidApplicationPlugin) ROLE_APP else ROLE_LIBRARY @@ -186,7 +186,7 @@ interface PythonBindingsExtension { * Named explicitly rather than derived, because this plugin carries no Kotlin Gradle Plugin * types (see [TEST_WORD]) and so cannot ask a target what its compile classpath is called. One * configuration and one source set is also the honest scope of what has been verified: see - * `ksp-fixtures/artifact`, and ROADMAP §16 for the generalisation. + * `python-multiplatform-gradle-plugin/fixtures/artifact`, and ROADMAP §16 for the generalisation. */ val artifactConfiguration: Property diff --git a/python-multiplatform-gradle-plugin/src/main/kotlin/python/multiplatform/gradle/artifact/ArtifactScanner.kt b/python-multiplatform-gradle-plugin/src/main/kotlin/python/multiplatform/gradle/artifact/ArtifactScanner.kt index e90cee6d5..99e36f925 100644 --- a/python-multiplatform-gradle-plugin/src/main/kotlin/python/multiplatform/gradle/artifact/ArtifactScanner.kt +++ b/python-multiplatform-gradle-plugin/src/main/kotlin/python/multiplatform/gradle/artifact/ArtifactScanner.kt @@ -1642,7 +1642,7 @@ internal object ArtifactScanner { * *different* limit from the one this method opens, which is why it is named rather than left * to fail as a compile error in somebody's generated fragment. * - **`@Composable`, inside a declaration that is not.** `Modifier.composed(factory:)` is the - * case. The fragment is compiled without the Compose plugin (`:ksp-fixtures:artifact`'s + * case. The fragment is compiled without the Compose plugin (`:python-multiplatform-gradle-plugin-fixtures:artifact`'s * `build.gradle.kts` says so, and it is the whole shape of that fixture's claim), so * `@Composable Modifier.() -> Modifier` written there is an ordinary `Function1` while the slot * is a lowered `Function3`. **This one does not fail as a compile error**, which is why it is diff --git a/python-multiplatform-gradle-plugin/src/main/kotlin/python/multiplatform/gradle/artifact/KlibScanWorkAction.kt b/python-multiplatform-gradle-plugin/src/main/kotlin/python/multiplatform/gradle/artifact/KlibScanWorkAction.kt index 5674f73b4..ea44881f5 100644 --- a/python-multiplatform-gradle-plugin/src/main/kotlin/python/multiplatform/gradle/artifact/KlibScanWorkAction.kt +++ b/python-multiplatform-gradle-plugin/src/main/kotlin/python/multiplatform/gradle/artifact/KlibScanWorkAction.kt @@ -99,7 +99,7 @@ internal data class KlibScanResult( * list into the worker copied the collision in with it, and * `:generatePythonArtifactBindings` failed with the same * `NoSuchMethodError: KotlinLibraryImplKt.createKotlinLibrary$default` the isolation was introduced to - * fix. In this repository it happened to work: `ksp-fixtures` resolves the plugin from an *included + * fix. In this repository it happened to work: the `fixtures/` modules resolve the plugin from an *included * build*, which does get a scope of its own, so no in-repo fixture can see this. * * The worker classpath is therefore built from an explicit coordinate list diff --git a/python-multiplatform-gradle-plugin/src/main/kotlin/python/multiplatform/gradle/artifact/KlibScanner.kt b/python-multiplatform-gradle-plugin/src/main/kotlin/python/multiplatform/gradle/artifact/KlibScanner.kt index 450c95f28..e4a29d1ee 100644 --- a/python-multiplatform-gradle-plugin/src/main/kotlin/python/multiplatform/gradle/artifact/KlibScanner.kt +++ b/python-multiplatform-gradle-plugin/src/main/kotlin/python/multiplatform/gradle/artifact/KlibScanner.kt @@ -36,7 +36,7 @@ import java.io.File * proved it and both attempts at aligning the version that failed before classloader isolation was * tried. [KlibScanWorkAction] is that isolation: every caller of this object goes through * [WorkerExecutor.scanKlibIsolated][python.multiplatform.gradle.artifact.scanKlibIsolated] rather than - * calling [scanKlib]/[scanKlibDeclarations] directly, and `:ksp-fixtures:klib-artifact + * calling [scanKlib]/[scanKlibDeclarations] directly, and `:python-multiplatform-gradle-plugin-fixtures:klib-artifact * :generatePythonArtifactBindings`/`:generatePythonStubs` passing is what confirms the isolation * actually holds in a consumer build, not only in this file's own unit tests. * diff --git a/python-multiplatform-gradle-plugin/src/test/kotlin/python/multiplatform/gradle/WiringTest.kt b/python-multiplatform-gradle-plugin/src/test/kotlin/python/multiplatform/gradle/WiringTest.kt index 2fb225019..30710976d 100644 --- a/python-multiplatform-gradle-plugin/src/test/kotlin/python/multiplatform/gradle/WiringTest.kt +++ b/python-multiplatform-gradle-plugin/src/test/kotlin/python/multiplatform/gradle/WiringTest.kt @@ -8,12 +8,12 @@ import kotlin.test.assertTrue /** * The three decisions the plugin makes for the user, as pure functions. * - * The plugin's real proof is `ksp-fixtures`, which applies it and runs its generated table; these + * The plugin's real proof is the `fixtures/` modules, which apply it and runs its generated table; these * pin the parts that would otherwise only be observable as a missing fragment or a duplicate one. */ class WiringTest { - // Observed on `:ksp-fixtures:app` (`gradlew dependencies`), Kotlin 2.4.20-Beta2 + KSP 2.3.11. + // Observed on `:python-multiplatform-ksp:fixtures:app` (`gradlew dependencies`), Kotlin 2.4.20-Beta2 + KSP 2.3.11. private val observedConfigurations = listOf( "ksp", "kspAndroidNativeArm64", @@ -46,7 +46,7 @@ class WiringTest { assertTrue(isBindingKspConfiguration("ksp", isMultiplatform = false)) } - // Observed on `:ksp-fixtures:android` (`gradlew :ksp-fixtures:android:dependencies`), the + // Observed on `:python-multiplatform-ksp:fixtures:android` (`gradlew :python-multiplatform-ksp:fixtures:android:dependencies`), the // fixture that carries `com.android.library`. AGP names its source sets with the build type // *last*, so the test configurations here do not end in `Test` the way the Kotlin-target ones // above do. Every one of the nine `...Test...` names below was receiving the processor before @@ -95,7 +95,7 @@ class WiringTest { // The ROADMAP §13 defect: `kspAndroidTestDebug` does not end in `Test`, so the processor // ran over the unit-test sources and emitted a `Fragment_`/`FunctionTable` pair // that shadowed `main`'s inside the test compilation. Observed on - // `:ksp-fixtures:android` before this filter was widened. + // `:python-multiplatform-ksp:fixtures:android` before this filter was widened. for (name in listOf( "kspAndroidTestDebug", "kspAndroidTestRelease", @@ -147,8 +147,8 @@ class WiringTest { // Two independent libraries both called `:core` would otherwise both emit // `python.multiplatform.generated.fragments.Fragment_core` and collide on one classpath. assertEquals( - "io_github_thisisthepy_ksp_fixtures_app", - deriveModuleName(group = "io.github.thisisthepy", path = ":ksp-fixtures:app", name = "app"), + "io_github_thisisthepy_python_multiplatform_ksp_fixtures_app", + deriveModuleName(group = "io.github.thisisthepy", path = ":python-multiplatform-ksp:fixtures:app", name = "app"), ) assertEquals( "com_example_core", diff --git a/python-multiplatform-gradle-plugin/src/test/kotlin/python/multiplatform/gradle/artifact/ArtifactScannerTest.kt b/python-multiplatform-gradle-plugin/src/test/kotlin/python/multiplatform/gradle/artifact/ArtifactScannerTest.kt index b89dffd3f..1c303ec99 100644 --- a/python-multiplatform-gradle-plugin/src/test/kotlin/python/multiplatform/gradle/artifact/ArtifactScannerTest.kt +++ b/python-multiplatform-gradle-plugin/src/test/kotlin/python/multiplatform/gradle/artifact/ArtifactScannerTest.kt @@ -548,7 +548,7 @@ class ArtifactScannerTest { * fail this. What the floors pin is that the two gates are open, which is the fact under test. * * `docs/design/ecosystem.md` §5b's own target (calling a composable) is out of scope here on purpose -- - * this counts declarations, and `:ksp-fixtures:artifact` is where a call is actually made. + * this counts declarations, and `:python-multiplatform-gradle-plugin-fixtures:artifact` is where a call is actually made. */ @Test fun composeModifierExtensionsSurviveBothGates() { diff --git a/python-multiplatform-gradle-plugin/src/test/kotlin/python/multiplatform/gradle/artifact/ArtifactTableRenderingTest.kt b/python-multiplatform-gradle-plugin/src/test/kotlin/python/multiplatform/gradle/artifact/ArtifactTableRenderingTest.kt index 3c3ac51ad..efbb90b40 100644 --- a/python-multiplatform-gradle-plugin/src/test/kotlin/python/multiplatform/gradle/artifact/ArtifactTableRenderingTest.kt +++ b/python-multiplatform-gradle-plugin/src/test/kotlin/python/multiplatform/gradle/artifact/ArtifactTableRenderingTest.kt @@ -14,7 +14,7 @@ import kotlin.test.assertEquals * * 1. **`FunctionTable` already means something.** `PackageScanFragmentDiscovery` builds it from * `Resolver.getDeclarationsFromPackage(python.multiplatform.generated.fragments)` -- "every - * module in this graph that was compiled with the processor". `ksp-fixtures/app`'s + * module in this graph that was compiled with the processor". `python-multiplatform-ksp/fixtures/app`'s * `CommonInstallTest` asserts that set exactly. Putting walked artefacts in it would silently * change a shipped contract, and would make a consumer's table grow when they added an unrelated * dependency. diff --git a/python-multiplatform-gradle-plugin/src/test/kotlin/python/multiplatform/gradle/artifact/FunctionSlotBindingTest.kt b/python-multiplatform-gradle-plugin/src/test/kotlin/python/multiplatform/gradle/artifact/FunctionSlotBindingTest.kt index d6f04774d..d9c03a48d 100644 --- a/python-multiplatform-gradle-plugin/src/test/kotlin/python/multiplatform/gradle/artifact/FunctionSlotBindingTest.kt +++ b/python-multiplatform-gradle-plugin/src/test/kotlin/python/multiplatform/gradle/artifact/FunctionSlotBindingTest.kt @@ -249,7 +249,7 @@ class FunctionSlotBindingTest { } /** - * `kotlin.system.measureTimeMillis`, which is the shape `:ksp-fixtures:artifact` calls from real + * `kotlin.system.measureTimeMillis`, which is the shape `:python-multiplatform-gradle-plugin-fixtures:artifact` calls from real * Python: the same `() -> Unit` slot `clickable.onClick` has, on a declaration that **invokes** * it rather than storing it for a composition to invoke later. * diff --git a/python-multiplatform-gradle-plugin/src/test/kotlin/python/multiplatform/gradle/artifact/KlibScannerTest.kt b/python-multiplatform-gradle-plugin/src/test/kotlin/python/multiplatform/gradle/artifact/KlibScannerTest.kt index 5a5e77f7d..cc9477871 100644 --- a/python-multiplatform-gradle-plugin/src/test/kotlin/python/multiplatform/gradle/artifact/KlibScannerTest.kt +++ b/python-multiplatform-gradle-plugin/src/test/kotlin/python/multiplatform/gradle/artifact/KlibScannerTest.kt @@ -130,7 +130,7 @@ class KlibScannerTest { * test pinned one -- `checkIndexOverflow`, `kotlinx.coroutines.flow.internal`'s bounds check -- as * bound. It was wrong: `checkIndexOverflow` is `@PublishedApi internal`, binary-visible so an * inline call site elsewhere in the *same* library can resolve it, but not source-visible outside - * that module. `KlibScanWorkAction`'s KDoc records how this was found -- `:ksp-fixtures + * that module. `KlibScanWorkAction`'s KDoc records how this was found -- `:python-multiplatform-gradle-plugin-fixtures * :klib-artifact:compileKotlinAndroidNativeArm64` failing to compile the generated fragment with * "it is internal in file", the first time this walker's output was ever actually compiled rather * than only unit-tested. `KlibScanner`'s `PUBLISHED_API` constant has the rest. Every other candidate in diff --git a/python-multiplatform-gradle-plugin/src/test/kotlin/python/multiplatform/gradle/artifact/PropertyBindingTest.kt b/python-multiplatform-gradle-plugin/src/test/kotlin/python/multiplatform/gradle/artifact/PropertyBindingTest.kt index c7aadb5f3..f26a7c19a 100644 --- a/python-multiplatform-gradle-plugin/src/test/kotlin/python/multiplatform/gradle/artifact/PropertyBindingTest.kt +++ b/python-multiplatform-gradle-plugin/src/test/kotlin/python/multiplatform/gradle/artifact/PropertyBindingTest.kt @@ -172,7 +172,7 @@ class PropertyBindingTest { // ----------------------------------------------------- a receiver the classpath cannot see /** - * The `:ksp-fixtures:compose` compile failure on ui-desktop 1.11's + * The `:python-multiplatform-compose:fixtures:compose` compile failure on ui-desktop 1.11's * `DefaultArchitectureComponentsOwner`: its supertypes live in lifecycle jars that the consumer's * compile classpath does not carry, so `(args[0] as Owner).lifecycle` does not compile. Declined * with a reason naming the missing supertype -- for a member property and an extension property diff --git a/python-multiplatform-gradle-plugin/src/test/kotlin/python/multiplatform/gradle/artifact/ReturnSupertypeTest.kt b/python-multiplatform-gradle-plugin/src/test/kotlin/python/multiplatform/gradle/artifact/ReturnSupertypeTest.kt index f6c9d3979..a045c2426 100644 --- a/python-multiplatform-gradle-plugin/src/test/kotlin/python/multiplatform/gradle/artifact/ReturnSupertypeTest.kt +++ b/python-multiplatform-gradle-plugin/src/test/kotlin/python/multiplatform/gradle/artifact/ReturnSupertypeTest.kt @@ -132,7 +132,7 @@ class ReturnSupertypeTest { } /** - * **The price.** Over the four packages `:ksp-fixtures:compose` actually walks, how many entries + * **The price.** Over the four packages `:python-multiplatform-compose:fixtures:compose` actually walks, how many entries * gain anything, how many characters that is against the rendered fragments, and how long the * longest chain gets. * diff --git a/python-multiplatform-gradle-plugin/src/test/kotlin/python/multiplatform/gradle/artifact/TextStateBindingTest.kt b/python-multiplatform-gradle-plugin/src/test/kotlin/python/multiplatform/gradle/artifact/TextStateBindingTest.kt index c13a41294..15bd4a625 100644 --- a/python-multiplatform-gradle-plugin/src/test/kotlin/python/multiplatform/gradle/artifact/TextStateBindingTest.kt +++ b/python-multiplatform-gradle-plugin/src/test/kotlin/python/multiplatform/gradle/artifact/TextStateBindingTest.kt @@ -25,7 +25,7 @@ import kotlin.test.assertTrue * file, so the object-handle case could not name it and `TextFieldState.text` was declined * ("no boundary type for property type kotlin.CharSequence"). * - * (The third cause, that `:ksp-fixtures:compose` did not walk `androidx.compose.foundation.text.input` + * (The third cause, that `:python-multiplatform-compose:fixtures:compose` did not walk `androidx.compose.foundation.text.input` * at all, is configuration, and `TextFieldStateRenderTest` there is its test.) * * ### Red before the implementation @@ -168,7 +168,7 @@ class TextStateBindingTest { * A value class the boundary opens (`Meters(value: Double)`, bound as `FLOAT`) is built and returned * as its raw number, so its constructor must stay a module function returning that number: an * `__init__` would promise a `Meters` instance the runtime never gives. Found by - * `:ksp-fixtures:artifact`'s `everyStubbedFunctionIsATableKeyAndEveryTableKeyIsStubbed` reporting + * `:python-multiplatform-gradle-plugin-fixtures:artifact`'s `everyStubbedFunctionIsATableKeyAndEveryTableKeyIsStubbed` reporting * `fixture.valueclass.Meters` as "callable but not stubbed" after the first version of this change. */ @Test diff --git a/python-multiplatform-gradle-plugin/src/test/kotlin/python/multiplatform/gradle/artifact/valueclassfixture/ValueClassFixtures.kt b/python-multiplatform-gradle-plugin/src/test/kotlin/python/multiplatform/gradle/artifact/valueclassfixture/ValueClassFixtures.kt index 30b77d2f2..59e69a8a7 100644 --- a/python-multiplatform-gradle-plugin/src/test/kotlin/python/multiplatform/gradle/artifact/valueclassfixture/ValueClassFixtures.kt +++ b/python-multiplatform-gradle-plugin/src/test/kotlin/python/multiplatform/gradle/artifact/valueclassfixture/ValueClassFixtures.kt @@ -90,7 +90,7 @@ fun Meters.tagged(): String = "meters" * `Function0` has no class file to name, and `DeclarationModelTest` used it for the other half of * `docs/design/pyi-generation-design.md` §2.2's third property. It binds now, so the declined witness moved * to [withSuspendCallback] and this one records the positive: a declaration that **invokes** what it - * is handed, which is what `:ksp-fixtures:artifact` exercises against `kotlin.system.measureTimeMillis` + * is handed, which is what `:python-multiplatform-gradle-plugin-fixtures:artifact` exercises against `kotlin.system.measureTimeMillis` * for real. */ fun withCallback(action: () -> Unit): Int { diff --git a/ksp-fixtures/android/build.gradle.kts b/python-multiplatform-ksp/fixtures/android/build.gradle.kts similarity index 87% rename from ksp-fixtures/android/build.gradle.kts rename to python-multiplatform-ksp/fixtures/android/build.gradle.kts index b1f642744..61eb70d21 100644 --- a/ksp-fixtures/android/build.gradle.kts +++ b/python-multiplatform-ksp/fixtures/android/build.gradle.kts @@ -11,10 +11,10 @@ import org.jetbrains.kotlin.gradle.dsl.JvmTarget * java.lang.NoSuchMethodError: 'void com.android.build.api.variant * .AndroidComponentsExtension.addKspConfigurations(boolean)' * - * in every module carrying an Android plugin. Neither `:ksp-fixtures:library` nor - * `:ksp-fixtures:app` applies one, so both stayed green while every Android consumer of the + * in every module carrying an Android plugin. Neither `:python-multiplatform-ksp:fixtures:library` nor + * `:python-multiplatform-ksp:fixtures:app` applies one, so both stayed green while every Android consumer of the * plugin was broken. **This module exists to fail in that situation**: if the AGP/KSP pair ever - * drifts back apart, `gradlew :ksp-fixtures:android:testDebugUnitTest` stops configuring at all. + * drifts back apart, `gradlew :python-multiplatform-ksp:fixtures:android:testDebugUnitTest` stops configuring at all. * * It paid for itself on its first run by failing for a *second* reason: AGP names its KSP * configurations with the build type last (`kspAndroidTestDebug`), so the plugin's @@ -79,7 +79,7 @@ android { pythonBindings { // `com.android.library` is not `com.android.application`, so the aggregating role is not - // inferred -- stated for the same reason `:ksp-fixtures:app` states it. Aggregating is what + // inferred -- stated for the same reason `:python-multiplatform-ksp:fixtures:app` states it. Aggregating is what // puts a `FunctionTable` in front of the test below; a `library` role would only emit a // fragment, and the test would be asserting on the generator rather than on the table. role.set("app") diff --git a/ksp-fixtures/android/src/androidInstrumentedTest/kotlin/fixture/android/GeneratedAndroidTableTest.kt b/python-multiplatform-ksp/fixtures/android/src/androidInstrumentedTest/kotlin/fixture/android/GeneratedAndroidTableTest.kt similarity index 93% rename from ksp-fixtures/android/src/androidInstrumentedTest/kotlin/fixture/android/GeneratedAndroidTableTest.kt rename to python-multiplatform-ksp/fixtures/android/src/androidInstrumentedTest/kotlin/fixture/android/GeneratedAndroidTableTest.kt index 813f13200..fa4e90300 100644 --- a/ksp-fixtures/android/src/androidInstrumentedTest/kotlin/fixture/android/GeneratedAndroidTableTest.kt +++ b/python-multiplatform-ksp/fixtures/android/src/androidInstrumentedTest/kotlin/fixture/android/GeneratedAndroidTableTest.kt @@ -14,7 +14,7 @@ import kotlin.test.assertNull import kotlin.test.assertTrue /** - * On-device instrumented execution of ksp-fixtures:android upcall table tests. + * On-device instrumented execution of python-multiplatform-ksp:fixtures:android upcall table tests. */ class GeneratedAndroidTableTest { @@ -31,7 +31,7 @@ class GeneratedAndroidTableTest { @Test fun theAndroidModulesFragmentIsInTheAggregatedTable() { - assertEquals(setOf("io_github_thisisthepy_ksp_fixtures_android"), UpcallTable.moduleNames) + assertEquals(setOf("io_github_thisisthepy_python_multiplatform_ksp_fixtures_android"), UpcallTable.moduleNames) assertTrue(UpcallTable.resolve("fixture.android.androidDouble").isValid) } @@ -115,7 +115,7 @@ class GeneratedAndroidTableTest { val count = installAndCountEntries() assertTrue(count > 0) - assertEquals(setOf("io_github_thisisthepy_ksp_fixtures_android"), UpcallTable.moduleNames) + assertEquals(setOf("io_github_thisisthepy_python_multiplatform_ksp_fixtures_android"), UpcallTable.moduleNames) assertTrue(UpcallTable.resolve("fixture.android.androidDouble").isValid) assertFalse( UpcallTable.resolve("fixture.android.installGeneratedUpcallTable").isValid, diff --git a/ksp-fixtures/android/src/androidMain/kotlin/fixture/android/AndroidFunctions.kt b/python-multiplatform-ksp/fixtures/android/src/androidMain/kotlin/fixture/android/AndroidFunctions.kt similarity index 84% rename from ksp-fixtures/android/src/androidMain/kotlin/fixture/android/AndroidFunctions.kt rename to python-multiplatform-ksp/fixtures/android/src/androidMain/kotlin/fixture/android/AndroidFunctions.kt index a4fc0d6f4..eef121880 100644 --- a/ksp-fixtures/android/src/androidMain/kotlin/fixture/android/AndroidFunctions.kt +++ b/python-multiplatform-ksp/fixtures/android/src/androidMain/kotlin/fixture/android/AndroidFunctions.kt @@ -5,7 +5,7 @@ import python.multiplatform.reflection.PythonInternal /** * The Python-facing surface of the Android fixture. * - * Deliberately the same shapes `ksp-fixtures/library` uses on desktop -- a top-level function, a + * Deliberately the same shapes `python-multiplatform-ksp/fixtures/library` uses on desktop -- a top-level function, a * narrowing `Int` signature, a `Unit` return, a class with a method and a mutable property, and * one `@PythonInternal` exclusion. The point is not to re-test the generator's policy (the * desktop fixture does that against a far bigger surface) but to prove the *same* generator @@ -26,7 +26,7 @@ fun androidHidden(): String = "must not appear in the generated table" class AndroidCounter(var count: Long = 0) { /** ROADMAP §13's second defect, on the AGP side of the generator: `isMutable` is true and the - * setter is not something generated code may name. `ksp-fixtures/library` pins all three + * setter is not something generated code may name. `python-multiplatform-ksp/fixtures/library` pins all three * restricted visibilities; this one only checks the same decision is made over here. */ var lastLabel: String = "" private set diff --git a/ksp-fixtures/android/src/androidUnitTest/kotlin/fixture/android/GeneratedAndroidTableTest.kt b/python-multiplatform-ksp/fixtures/android/src/androidUnitTest/kotlin/fixture/android/GeneratedAndroidTableTest.kt similarity index 96% rename from ksp-fixtures/android/src/androidUnitTest/kotlin/fixture/android/GeneratedAndroidTableTest.kt rename to python-multiplatform-ksp/fixtures/android/src/androidUnitTest/kotlin/fixture/android/GeneratedAndroidTableTest.kt index 26c1f121c..3876b6492 100644 --- a/ksp-fixtures/android/src/androidUnitTest/kotlin/fixture/android/GeneratedAndroidTableTest.kt +++ b/python-multiplatform-ksp/fixtures/android/src/androidUnitTest/kotlin/fixture/android/GeneratedAndroidTableTest.kt @@ -44,7 +44,7 @@ class GeneratedAndroidTableTest { // The name the gradle plugin derives from this module's group and path. Its presence is // what says KSP ran here at all -- the state ROADMAP §13 describes has no fragment // because the build never got past configuration. - assertEquals(setOf("io_github_thisisthepy_ksp_fixtures_android"), UpcallTable.moduleNames) + assertEquals(setOf("io_github_thisisthepy_python_multiplatform_ksp_fixtures_android"), UpcallTable.moduleNames) assertTrue(UpcallTable.resolve("fixture.android.androidDouble").isValid) } @@ -132,7 +132,7 @@ class GeneratedAndroidTableTest { val count = installAndCountEntries() assertTrue(count > 0) - assertEquals(setOf("io_github_thisisthepy_ksp_fixtures_android"), UpcallTable.moduleNames) + assertEquals(setOf("io_github_thisisthepy_python_multiplatform_ksp_fixtures_android"), UpcallTable.moduleNames) assertTrue(UpcallTable.resolve("fixture.android.androidDouble").isValid) assertFalse( UpcallTable.resolve("fixture.android.installGeneratedUpcallTable").isValid, diff --git a/ksp-fixtures/android/src/commonMain/kotlin/fixture/android/TableInstall.kt b/python-multiplatform-ksp/fixtures/android/src/commonMain/kotlin/fixture/android/TableInstall.kt similarity index 92% rename from ksp-fixtures/android/src/commonMain/kotlin/fixture/android/TableInstall.kt rename to python-multiplatform-ksp/fixtures/android/src/commonMain/kotlin/fixture/android/TableInstall.kt index ac3370ec7..a01c677dc 100644 --- a/ksp-fixtures/android/src/commonMain/kotlin/fixture/android/TableInstall.kt +++ b/python-multiplatform-ksp/fixtures/android/src/commonMain/kotlin/fixture/android/TableInstall.kt @@ -13,7 +13,7 @@ import python.multiplatform.reflection.UpcallTable * exactly one. * * Nothing shared code writes should have to know any of that, which is what this file asserts by - * being identical in shape to `ksp-fixtures/app`'s. + * being identical in shape to `python-multiplatform-ksp/fixtures/app`'s. */ @InstallsUpcallTable expect fun installGeneratedUpcallTable() diff --git a/ksp-fixtures/app/build.gradle.kts b/python-multiplatform-ksp/fixtures/app/build.gradle.kts similarity index 99% rename from ksp-fixtures/app/build.gradle.kts rename to python-multiplatform-ksp/fixtures/app/build.gradle.kts index 8f136bb14..8404411cd 100644 --- a/ksp-fixtures/app/build.gradle.kts +++ b/python-multiplatform-ksp/fixtures/app/build.gradle.kts @@ -40,7 +40,7 @@ kotlin { val commonMain by getting { dependencies { implementation(projects.pythonMultiplatform) - implementation(projects.kspFixtures.library) + implementation(projects.pythonMultiplatformKsp.fixtures.library) } } val desktopTest by getting { diff --git a/ksp-fixtures/app/src/androidNativeArm64Test/kotlin/fixture/app/NativeSmokeTest.kt b/python-multiplatform-ksp/fixtures/app/src/androidNativeArm64Test/kotlin/fixture/app/NativeSmokeTest.kt similarity index 100% rename from ksp-fixtures/app/src/androidNativeArm64Test/kotlin/fixture/app/NativeSmokeTest.kt rename to python-multiplatform-ksp/fixtures/app/src/androidNativeArm64Test/kotlin/fixture/app/NativeSmokeTest.kt diff --git a/ksp-fixtures/app/src/androidNativeMain/kotlin/fixture/app/NativeInstall.kt b/python-multiplatform-ksp/fixtures/app/src/androidNativeMain/kotlin/fixture/app/NativeInstall.kt similarity index 87% rename from ksp-fixtures/app/src/androidNativeMain/kotlin/fixture/app/NativeInstall.kt rename to python-multiplatform-ksp/fixtures/app/src/androidNativeMain/kotlin/fixture/app/NativeInstall.kt index 85adc2b61..77625f03a 100644 --- a/ksp-fixtures/app/src/androidNativeMain/kotlin/fixture/app/NativeInstall.kt +++ b/python-multiplatform-ksp/fixtures/app/src/androidNativeMain/kotlin/fixture/app/NativeInstall.kt @@ -10,6 +10,6 @@ package fixture.app * found. Before the seam, the only way out was one hand-written `actual` per leaf. * * That it compiles for both leaves is the whole assertion; there is no test binary here. - * Verified with `:ksp-fixtures:app:compileKotlinAndroidNativeArm64` and `...X64`. + * Verified with `:python-multiplatform-ksp:fixtures:app:compileKotlinAndroidNativeArm64` and `...X64`. */ fun installOnNative(): String = installAndDescribeTable() diff --git a/ksp-fixtures/app/src/commonMain/kotlin/fixture/app/AppExtras.kt b/python-multiplatform-ksp/fixtures/app/src/commonMain/kotlin/fixture/app/AppExtras.kt similarity index 100% rename from ksp-fixtures/app/src/commonMain/kotlin/fixture/app/AppExtras.kt rename to python-multiplatform-ksp/fixtures/app/src/commonMain/kotlin/fixture/app/AppExtras.kt diff --git a/ksp-fixtures/app/src/commonMain/kotlin/fixture/app/AppFunctions.kt b/python-multiplatform-ksp/fixtures/app/src/commonMain/kotlin/fixture/app/AppFunctions.kt similarity index 100% rename from ksp-fixtures/app/src/commonMain/kotlin/fixture/app/AppFunctions.kt rename to python-multiplatform-ksp/fixtures/app/src/commonMain/kotlin/fixture/app/AppFunctions.kt diff --git a/ksp-fixtures/app/src/commonMain/kotlin/fixture/app/ArgumentRelease.kt b/python-multiplatform-ksp/fixtures/app/src/commonMain/kotlin/fixture/app/ArgumentRelease.kt similarity index 100% rename from ksp-fixtures/app/src/commonMain/kotlin/fixture/app/ArgumentRelease.kt rename to python-multiplatform-ksp/fixtures/app/src/commonMain/kotlin/fixture/app/ArgumentRelease.kt diff --git a/ksp-fixtures/app/src/commonMain/kotlin/fixture/app/TableInstall.kt b/python-multiplatform-ksp/fixtures/app/src/commonMain/kotlin/fixture/app/TableInstall.kt similarity index 80% rename from ksp-fixtures/app/src/commonMain/kotlin/fixture/app/TableInstall.kt rename to python-multiplatform-ksp/fixtures/app/src/commonMain/kotlin/fixture/app/TableInstall.kt index 0c28391a4..0a9cfbfc7 100644 --- a/ksp-fixtures/app/src/commonMain/kotlin/fixture/app/TableInstall.kt +++ b/python-multiplatform-ksp/fixtures/app/src/commonMain/kotlin/fixture/app/TableInstall.kt @@ -10,15 +10,15 @@ import python.multiplatform.reflection.UpcallTable * compilation, so this file -- `commonMain`, which every leaf depends on -- cannot name it. * Written the obvious way, the fixture does not compile: * - * e: ksp-fixtures/app/src/commonMain/kotlin/fixture/app/TableInstall.kt:4:39 + * e: python-multiplatform-ksp/fixtures/app/src/commonMain/kotlin/fixture/app/TableInstall.kt:4:39 * Unresolved reference 'FunctionTable'. * - * observed on `:ksp-fixtures:app:compileKotlinDesktop`. No fixture had this shape before, which + * observed on `:python-multiplatform-ksp:fixtures:app:compileKotlinDesktop`. No fixture had this shape before, which * is why the whole defect only turned up in `sample`: both existing fixtures reached the table * from `desktopTest`, a *leaf* compilation, where it resolves fine. * * The seam: one `expect` here, and `python-multiplatform-ksp` emits the `actual` into every leaf - * it generates a `FunctionTable` for. `:ksp-fixtures:app` has three leaves (`desktop`, + * it generates a `FunctionTable` for. `:python-multiplatform-ksp:fixtures:app` has three leaves (`desktop`, * `androidNativeArm64`, `androidNativeX64`) and not one of them needs a hand-written line. */ @InstallsUpcallTable diff --git a/ksp-fixtures/app/src/commonMain/kotlin/fixture/app/TypedPythonBridge.kt b/python-multiplatform-ksp/fixtures/app/src/commonMain/kotlin/fixture/app/TypedPythonBridge.kt similarity index 100% rename from ksp-fixtures/app/src/commonMain/kotlin/fixture/app/TypedPythonBridge.kt rename to python-multiplatform-ksp/fixtures/app/src/commonMain/kotlin/fixture/app/TypedPythonBridge.kt diff --git a/ksp-fixtures/app/src/desktopTest/kotlin/fixture/app/CommonInstallTest.kt b/python-multiplatform-ksp/fixtures/app/src/desktopTest/kotlin/fixture/app/CommonInstallTest.kt similarity index 95% rename from ksp-fixtures/app/src/desktopTest/kotlin/fixture/app/CommonInstallTest.kt rename to python-multiplatform-ksp/fixtures/app/src/desktopTest/kotlin/fixture/app/CommonInstallTest.kt index e7db0e188..e30de7b5b 100644 --- a/ksp-fixtures/app/src/desktopTest/kotlin/fixture/app/CommonInstallTest.kt +++ b/python-multiplatform-ksp/fixtures/app/src/desktopTest/kotlin/fixture/app/CommonInstallTest.kt @@ -38,7 +38,7 @@ class CommonInstallTest { assertTrue(UpcallTable.callableCount > 0, "commonMain installed nothing: $summary") assertEquals( - setOf("io_github_thisisthepy_ksp_fixtures_library", "io_github_thisisthepy_ksp_fixtures_app"), + setOf("io_github_thisisthepy_python_multiplatform_ksp_fixtures_library", "io_github_thisisthepy_python_multiplatform_ksp_fixtures_app"), UpcallTable.moduleNames, "the seam must install the same aggregate FunctionTable.fragments does", ) diff --git a/ksp-fixtures/app/src/desktopTest/kotlin/fixture/app/GeneratedDeclarationKindsTest.kt b/python-multiplatform-ksp/fixtures/app/src/desktopTest/kotlin/fixture/app/GeneratedDeclarationKindsTest.kt similarity index 99% rename from ksp-fixtures/app/src/desktopTest/kotlin/fixture/app/GeneratedDeclarationKindsTest.kt rename to python-multiplatform-ksp/fixtures/app/src/desktopTest/kotlin/fixture/app/GeneratedDeclarationKindsTest.kt index abe21e012..d30ab0784 100644 --- a/ksp-fixtures/app/src/desktopTest/kotlin/fixture/app/GeneratedDeclarationKindsTest.kt +++ b/python-multiplatform-ksp/fixtures/app/src/desktopTest/kotlin/fixture/app/GeneratedDeclarationKindsTest.kt @@ -23,7 +23,7 @@ import kotlin.test.assertTrue /** * ROADMAP §7's "companion-object members, interfaces, enums and annotation classes are not - * exposed", closed against the table KSP generated from `ksp-fixtures/library` -- not against a + * exposed", closed against the table KSP generated from `python-multiplatform-ksp/fixtures/library` -- not against a * hand-written fragment. * * Two of these tests assert an *absence* (annotation classes, generics). They are not diff --git a/ksp-fixtures/app/src/desktopTest/kotlin/fixture/app/GeneratedStaticPropertyProxyTest.kt b/python-multiplatform-ksp/fixtures/app/src/desktopTest/kotlin/fixture/app/GeneratedStaticPropertyProxyTest.kt similarity index 100% rename from ksp-fixtures/app/src/desktopTest/kotlin/fixture/app/GeneratedStaticPropertyProxyTest.kt rename to python-multiplatform-ksp/fixtures/app/src/desktopTest/kotlin/fixture/app/GeneratedStaticPropertyProxyTest.kt diff --git a/ksp-fixtures/app/src/desktopTest/kotlin/fixture/app/GeneratedSuspendTest.kt b/python-multiplatform-ksp/fixtures/app/src/desktopTest/kotlin/fixture/app/GeneratedSuspendTest.kt similarity index 99% rename from ksp-fixtures/app/src/desktopTest/kotlin/fixture/app/GeneratedSuspendTest.kt rename to python-multiplatform-ksp/fixtures/app/src/desktopTest/kotlin/fixture/app/GeneratedSuspendTest.kt index 49ba2299f..be5a1b147 100644 --- a/ksp-fixtures/app/src/desktopTest/kotlin/fixture/app/GeneratedSuspendTest.kt +++ b/python-multiplatform-ksp/fixtures/app/src/desktopTest/kotlin/fixture/app/GeneratedSuspendTest.kt @@ -21,7 +21,7 @@ import kotlin.test.assertTrue /** * What the generator does with `suspend`, pinned against the table KSP actually produced from - * `ksp-fixtures/library/.../Suspending.kt`. + * `python-multiplatform-ksp/fixtures/library/.../Suspending.kt`. * * The answer used to be **silently skipped** -- `BindingPolicy.isExposedFunctionShape` dropped any * declaration carrying `Modifier.SUSPEND`, so nothing was emitted and nothing was logged, and a diff --git a/ksp-fixtures/app/src/desktopTest/kotlin/fixture/app/GeneratedTableTest.kt b/python-multiplatform-ksp/fixtures/app/src/desktopTest/kotlin/fixture/app/GeneratedTableTest.kt similarity index 96% rename from ksp-fixtures/app/src/desktopTest/kotlin/fixture/app/GeneratedTableTest.kt rename to python-multiplatform-ksp/fixtures/app/src/desktopTest/kotlin/fixture/app/GeneratedTableTest.kt index 1be5539ff..b3ec843dd 100644 --- a/ksp-fixtures/app/src/desktopTest/kotlin/fixture/app/GeneratedTableTest.kt +++ b/python-multiplatform-ksp/fixtures/app/src/desktopTest/kotlin/fixture/app/GeneratedTableTest.kt @@ -21,7 +21,7 @@ import kotlin.test.assertTrue * This is the whole point of ROADMAP §7's generator half: everything * `python.multiplatform.reflection.UpcallTableTest` proves against hand-written fragments in * `TestFragments.kt`, proved here against a `FunctionTable` that KSP actually generated from - * `ksp-fixtures/library`'s and this module's own sources -- no hand-written fragment anywhere in + * `python-multiplatform-ksp/fixtures/library`'s and this module's own sources -- no hand-written fragment anywhere in * this file. */ class GeneratedTableTest { @@ -46,7 +46,7 @@ class GeneratedTableTest { // group and path -- neither fixture states a module name any more, and the group is in // there because every fragment object in every artifact shares one package. assertEquals( - setOf("io_github_thisisthepy_ksp_fixtures_library", "io_github_thisisthepy_ksp_fixtures_app"), + setOf("io_github_thisisthepy_python_multiplatform_ksp_fixtures_library", "io_github_thisisthepy_python_multiplatform_ksp_fixtures_app"), UpcallTable.moduleNames, ) assertTrue(UpcallTable.resolve("fixture.library.add").isValid) diff --git a/ksp-fixtures/app/src/desktopTest/kotlin/fixture/app/KspClassResultProxyTest.kt b/python-multiplatform-ksp/fixtures/app/src/desktopTest/kotlin/fixture/app/KspClassResultProxyTest.kt similarity index 100% rename from ksp-fixtures/app/src/desktopTest/kotlin/fixture/app/KspClassResultProxyTest.kt rename to python-multiplatform-ksp/fixtures/app/src/desktopTest/kotlin/fixture/app/KspClassResultProxyTest.kt diff --git a/ksp-fixtures/app/src/desktopTest/kotlin/fixture/app/ProxyObjectArgumentTest.kt b/python-multiplatform-ksp/fixtures/app/src/desktopTest/kotlin/fixture/app/ProxyObjectArgumentTest.kt similarity index 100% rename from ksp-fixtures/app/src/desktopTest/kotlin/fixture/app/ProxyObjectArgumentTest.kt rename to python-multiplatform-ksp/fixtures/app/src/desktopTest/kotlin/fixture/app/ProxyObjectArgumentTest.kt diff --git a/ksp-fixtures/app/src/desktopTest/kotlin/fixture/app/PyObjectArgumentReleaseTest.kt b/python-multiplatform-ksp/fixtures/app/src/desktopTest/kotlin/fixture/app/PyObjectArgumentReleaseTest.kt similarity index 100% rename from ksp-fixtures/app/src/desktopTest/kotlin/fixture/app/PyObjectArgumentReleaseTest.kt rename to python-multiplatform-ksp/fixtures/app/src/desktopTest/kotlin/fixture/app/PyObjectArgumentReleaseTest.kt diff --git a/ksp-fixtures/app/src/desktopTest/kotlin/fixture/app/RefHolderCycleCollectionTest.kt b/python-multiplatform-ksp/fixtures/app/src/desktopTest/kotlin/fixture/app/RefHolderCycleCollectionTest.kt similarity index 100% rename from ksp-fixtures/app/src/desktopTest/kotlin/fixture/app/RefHolderCycleCollectionTest.kt rename to python-multiplatform-ksp/fixtures/app/src/desktopTest/kotlin/fixture/app/RefHolderCycleCollectionTest.kt diff --git a/ksp-fixtures/app/src/desktopTest/kotlin/fixture/app/TypedPythonKotlinCallTest.kt b/python-multiplatform-ksp/fixtures/app/src/desktopTest/kotlin/fixture/app/TypedPythonKotlinCallTest.kt similarity index 99% rename from ksp-fixtures/app/src/desktopTest/kotlin/fixture/app/TypedPythonKotlinCallTest.kt rename to python-multiplatform-ksp/fixtures/app/src/desktopTest/kotlin/fixture/app/TypedPythonKotlinCallTest.kt index 805106f9b..101d0d7a6 100644 --- a/ksp-fixtures/app/src/desktopTest/kotlin/fixture/app/TypedPythonKotlinCallTest.kt +++ b/python-multiplatform-ksp/fixtures/app/src/desktopTest/kotlin/fixture/app/TypedPythonKotlinCallTest.kt @@ -52,7 +52,7 @@ class TypedPythonKotlinCallTest { val propertiesPath = System.getProperty("typedpython.bridge.properties") assumeTrue( "TypedPython bridge extension not built: system property typedpython.bridge.properties is unset " + - "(run through :ksp-fixtures:app:desktopTest)", + "(run through :python-multiplatform-ksp:fixtures:app:desktopTest)", propertiesPath != null, ) val file = File(propertiesPath!!) diff --git a/ksp-fixtures/app/src/desktopTest/typedpython/fixture/__init__.pyi b/python-multiplatform-ksp/fixtures/app/src/desktopTest/typedpython/fixture/__init__.pyi similarity index 100% rename from ksp-fixtures/app/src/desktopTest/typedpython/fixture/__init__.pyi rename to python-multiplatform-ksp/fixtures/app/src/desktopTest/typedpython/fixture/__init__.pyi diff --git a/ksp-fixtures/app/src/desktopTest/typedpython/fixture/app/__init__.pyi b/python-multiplatform-ksp/fixtures/app/src/desktopTest/typedpython/fixture/app/__init__.pyi similarity index 86% rename from ksp-fixtures/app/src/desktopTest/typedpython/fixture/app/__init__.pyi rename to python-multiplatform-ksp/fixtures/app/src/desktopTest/typedpython/fixture/app/__init__.pyi index 267595828..6e9f44cac 100644 --- a/ksp-fixtures/app/src/desktopTest/typedpython/fixture/app/__init__.pyi +++ b/python-multiplatform-ksp/fixtures/app/src/desktopTest/typedpython/fixture/app/__init__.pyi @@ -1,5 +1,5 @@ # Type-checking stub for the TypedPython gate only (issue #45). It mirrors the part of -# `ksp-fixtures/app/src/commonMain/kotlin/fixture/app/TypedPythonBridge.kt` that +# `python-multiplatform-ksp/fixtures/app/src/commonMain/kotlin/fixture/app/TypedPythonBridge.kt` that # `tp_kotlin_bridge.py` uses. Kotlin `Long` is `int`, `Double` is `float`, `PyObject?` is `object`. # If this drifts from the Kotlin, the gate still passes and the run-time test fails at the call. diff --git a/ksp-fixtures/app/src/desktopTest/typedpython/tp_kotlin_bridge.py b/python-multiplatform-ksp/fixtures/app/src/desktopTest/typedpython/tp_kotlin_bridge.py similarity index 100% rename from ksp-fixtures/app/src/desktopTest/typedpython/tp_kotlin_bridge.py rename to python-multiplatform-ksp/fixtures/app/src/desktopTest/typedpython/tp_kotlin_bridge.py diff --git a/ksp-fixtures/app/typedpython/build_bridge.py b/python-multiplatform-ksp/fixtures/app/typedpython/build_bridge.py similarity index 97% rename from ksp-fixtures/app/typedpython/build_bridge.py rename to python-multiplatform-ksp/fixtures/app/typedpython/build_bridge.py index cd754b3e6..d1cbeb698 100644 --- a/ksp-fixtures/app/typedpython/build_bridge.py +++ b/python-multiplatform-ksp/fixtures/app/typedpython/build_bridge.py @@ -1,6 +1,6 @@ """Builds `tp_kotlin_bridge.py` into a TypedPython extension for the CPython this fixture embeds (#45). -Run by the `buildTypedPythonBridge` task in `ksp-fixtures/app/build.gradle.kts` with a *host* +Run by the `buildTypedPythonBridge` task in `python-multiplatform-ksp/fixtures/app/build.gradle.kts` with a *host* interpreter that has Pyrefly 1.3.2 (the gate needs it; `-PtypedpythonPython`, default `python-multiplatform-ksp/.venv/bin/python`). The host interpreter only runs the compiler; the extension is built for the embedded one: diff --git a/ksp-fixtures/library/build.gradle.kts b/python-multiplatform-ksp/fixtures/library/build.gradle.kts similarity index 93% rename from ksp-fixtures/library/build.gradle.kts rename to python-multiplatform-ksp/fixtures/library/build.gradle.kts index 4b52c23bd..417ec00b7 100644 --- a/ksp-fixtures/library/build.gradle.kts +++ b/python-multiplatform-ksp/fixtures/library/build.gradle.kts @@ -20,7 +20,7 @@ kotlin { // (docs/design/upcall.md §2.9's open question). Compile-only here: androidNativeArm64 // targets a device/emulator this workspace does not run tests against. androidNativeArm64() - // `:ksp-fixtures:app` grew a second Native leaf so that it would have an intermediate + // `:python-multiplatform-ksp:fixtures:app` grew a second Native leaf so that it would have an intermediate // `androidNativeMain` -- ROADMAP §13's `iosMain` shape, without Xcode. A consumer's targets // have to be a subset of its dependency's, so this one follows or the app module fails // dependency resolution ("Unresolved platforms: [androidNativeX64]") before compiling. diff --git a/ksp-fixtures/library/src/commonMain/kotlin/fixture/library/Declarations.kt b/python-multiplatform-ksp/fixtures/library/src/commonMain/kotlin/fixture/library/Declarations.kt similarity index 97% rename from ksp-fixtures/library/src/commonMain/kotlin/fixture/library/Declarations.kt rename to python-multiplatform-ksp/fixtures/library/src/commonMain/kotlin/fixture/library/Declarations.kt index 75a27a9c1..94456be08 100644 --- a/ksp-fixtures/library/src/commonMain/kotlin/fixture/library/Declarations.kt +++ b/python-multiplatform-ksp/fixtures/library/src/commonMain/kotlin/fixture/library/Declarations.kt @@ -8,7 +8,7 @@ import python.multiplatform.reflection.PythonInternal * before the generator learned about them (generics, abstract classes). * * Everything here exists to be asserted against in - * `ksp-fixtures/app/src/desktopTest/.../GeneratedDeclarationKindsTest.kt`, against the table KSP + * `python-multiplatform-ksp/fixtures/app/src/desktopTest/.../GeneratedDeclarationKindsTest.kt`, against the table KSP * actually generated rather than a hand-written fragment. */ diff --git a/ksp-fixtures/library/src/commonMain/kotlin/fixture/library/LibFunctions.kt b/python-multiplatform-ksp/fixtures/library/src/commonMain/kotlin/fixture/library/LibFunctions.kt similarity index 100% rename from ksp-fixtures/library/src/commonMain/kotlin/fixture/library/LibFunctions.kt rename to python-multiplatform-ksp/fixtures/library/src/commonMain/kotlin/fixture/library/LibFunctions.kt diff --git a/ksp-fixtures/library/src/commonMain/kotlin/fixture/library/Suspending.kt b/python-multiplatform-ksp/fixtures/library/src/commonMain/kotlin/fixture/library/Suspending.kt similarity index 100% rename from ksp-fixtures/library/src/commonMain/kotlin/fixture/library/Suspending.kt rename to python-multiplatform-ksp/fixtures/library/src/commonMain/kotlin/fixture/library/Suspending.kt diff --git a/python-multiplatform-ksp/src/main/kotlin/python/multiplatform/ksp/BindingPolicy.kt b/python-multiplatform-ksp/src/main/kotlin/python/multiplatform/ksp/BindingPolicy.kt index 04995ed70..c2765b9ac 100644 --- a/python-multiplatform-ksp/src/main/kotlin/python/multiplatform/ksp/BindingPolicy.kt +++ b/python-multiplatform-ksp/src/main/kotlin/python/multiplatform/ksp/BindingPolicy.kt @@ -132,7 +132,7 @@ object BindingPolicy { * Cannot access 'privateSet': it is private in 'fixture.library.RestrictedSetters'. * Cannot access 'topLevelPrivateSet': it is private in file. * - * -- observed on `ksp-fixtures/library`'s `RestrictedSetters` before this check existed. + * -- observed on `python-multiplatform-ksp/fixtures/library`'s `RestrictedSetters` before this check existed. * * `internal set` is excluded for a different reason, and the difference is worth stating * because it does *not* announce itself: `internal` is enforced per Kotlin module and the diff --git a/python-multiplatform/src/commonMain/kotlin/python/multiplatform/ffi/pythonx/PythonCallables.kt b/python-multiplatform/src/commonMain/kotlin/python/multiplatform/ffi/pythonx/PythonCallables.kt index 5304789c4..c1e85ea97 100644 --- a/python-multiplatform/src/commonMain/kotlin/python/multiplatform/ffi/pythonx/PythonCallables.kt +++ b/python-multiplatform/src/commonMain/kotlin/python/multiplatform/ffi/pythonx/PythonCallables.kt @@ -64,7 +64,7 @@ import python.multiplatform.reflection.TypeTag * * So this file owns the first three quarters of that -- creating, holding and releasing -- and the * one Compose type involved, `RememberObserver`, stays in the module that has Compose - * (`:ksp-fixtures:compose`'s `PythonComposition`). `docs/archive/pythonx-adapter-design.md` §6 item 1 names + * (`:python-multiplatform-compose:fixtures:compose`'s `PythonComposition`). `docs/archive/pythonx-adapter-design.md` §6 item 1 names * `onForgotten` as "the one that fails silently and should be tested first"; the seam is here and the * test is there. * @@ -106,7 +106,7 @@ import python.multiplatform.reflection.TypeTag * else. Interning bounds the case that actually recurs; the sweep needed that measurement first. * * **That measurement now exists, and the verdict is that a same-pass sweep is unsafe.** - * `:ksp-fixtures:compose`'s `RetainedSlotSweepPreconditionTest + * `:python-multiplatform-compose:fixtures:compose`'s `RetainedSlotSweepPreconditionTest * .aRetainingSlotKeepsPassZerosWrapperWhileLaterPassesCrossAndGoUntouched` drives a real * `remember(key)` (the mechanism `LaunchedEffect(key)` is built on) with a constant key across six * recompositions of one composition, each supplying a callable with a distinct capture -- so each diff --git a/python-multiplatform/src/commonMain/kotlin/python/multiplatform/ffi/upcall/PythonProxySource.kt b/python-multiplatform/src/commonMain/kotlin/python/multiplatform/ffi/upcall/PythonProxySource.kt index 4b941f078..b32203d30 100644 --- a/python-multiplatform/src/commonMain/kotlin/python/multiplatform/ffi/upcall/PythonProxySource.kt +++ b/python-multiplatform/src/commonMain/kotlin/python/multiplatform/ffi/upcall/PythonProxySource.kt @@ -230,7 +230,7 @@ import python.multiplatform.reflection.UpcallTable * A class with static members already has a metaclass, and the two requirements do not both fit in * a base list: Python has no syntax for a base *after* a keyword, so the only spelling available is * `class Foo(_PmObject, metaclass=_pm_t_1):` -- which separates the class from the metaclass a - * reader is pairing it with, and did more than that. `ksp-fixtures:app` locates a companion by + * reader is pairing it with, and did more than that. `python-multiplatform-ksp:fixtures:app` locates a companion by * matching `class (_pm_t_\d+)\(type\):` lazily through to `class Foo\(metaclass=\1\):`, and once * that terminator no longer existed the match could not complete: `java.util.regex`'s lazy loop * recurses once per character, so it scanned the rest of a 30 KB module and raised diff --git a/python-multiplatform/src/commonMain/kotlin/python/multiplatform/reflection/InstallsUpcallTable.kt b/python-multiplatform/src/commonMain/kotlin/python/multiplatform/reflection/InstallsUpcallTable.kt index 358421489..cd55edc82 100644 --- a/python-multiplatform/src/commonMain/kotlin/python/multiplatform/reflection/InstallsUpcallTable.kt +++ b/python-multiplatform/src/commonMain/kotlin/python/multiplatform/reflection/InstallsUpcallTable.kt @@ -12,7 +12,7 @@ package python.multiplatform.reflection * * e: TableInstall.kt: Unresolved reference 'FunctionTable'. * - * observed on `ksp-fixtures/app`'s `commonMain`. ROADMAP §13 recorded the consequence: every + * observed on `python-multiplatform-ksp/fixtures/app`'s `commonMain`. ROADMAP §13 recorded the consequence: every * consumer wrote the same one-line `actual` once per leaf target, and shared code that wanted the * table had nothing to call. `androidMain` is the exception that proves the rule -- it *is* the * Android target's own source set, so it can name `FunctionTable` -- and an exception per platform diff --git a/python-multiplatform/src/commonTest/kotlin/python/multiplatform/ffi/pythonx/ComposableShapedFragment.kt b/python-multiplatform/src/commonTest/kotlin/python/multiplatform/ffi/pythonx/ComposableShapedFragment.kt index 79e746bac..f9a68f247 100644 --- a/python-multiplatform/src/commonTest/kotlin/python/multiplatform/ffi/pythonx/ComposableShapedFragment.kt +++ b/python-multiplatform/src/commonTest/kotlin/python/multiplatform/ffi/pythonx/ComposableShapedFragment.kt @@ -18,7 +18,7 @@ import python.multiplatform.reflection.TypeTag * `$default` bits a Python call sets, what goes in the slots it left out, and what `$changed` is. * * The real end of it -- `androidx.compose.material3.Text` drawing "hi" -- is - * `:ksp-fixtures:compose`'s `ComposableRenderTest`, which is desktop-only for exactly those reasons. + * `:python-multiplatform-compose:fixtures:compose`'s `ComposableRenderTest`, which is desktop-only for exactly those reasons. * * ### The shape, and why every field of it matters * diff --git a/python-multiplatform/src/commonTest/kotlin/python/multiplatform/ffi/pythonx/ComposeShapedFragment.kt b/python-multiplatform/src/commonTest/kotlin/python/multiplatform/ffi/pythonx/ComposeShapedFragment.kt index e071d7148..fec320e1b 100644 --- a/python-multiplatform/src/commonTest/kotlin/python/multiplatform/ffi/pythonx/ComposeShapedFragment.kt +++ b/python-multiplatform/src/commonTest/kotlin/python/multiplatform/ffi/pythonx/ComposeShapedFragment.kt @@ -11,7 +11,7 @@ import python.multiplatform.reflection.TypeTag * * ### Why a stand-in rather than the real jars * - * `WalkedArtifactComposeModifierTest` (in `ksp-fixtures/artifact`) already proves that the walker + * `WalkedArtifactComposeModifierTest` (in `python-multiplatform-gradle-plugin/fixtures/artifact`) already proves that the walker * produces these entries out of `foundation-layout-desktop-1.6.11.jar` and that Compose's own * `padding` runs when Python calls them. What it cannot do is run anywhere but desktop, because it * needs a JVM classpath. The adapter under test here is `commonMain` Python, so its tests belong in diff --git a/python-multiplatform/src/commonTest/kotlin/python/multiplatform/ffi/pythonx/PythonxCallableTest.kt b/python-multiplatform/src/commonTest/kotlin/python/multiplatform/ffi/pythonx/PythonxCallableTest.kt index 3b342a6e9..8140363d7 100644 --- a/python-multiplatform/src/commonTest/kotlin/python/multiplatform/ffi/pythonx/PythonxCallableTest.kt +++ b/python-multiplatform/src/commonTest/kotlin/python/multiplatform/ffi/pythonx/PythonxCallableTest.kt @@ -29,7 +29,7 @@ import kotlin.test.assertTrue * | | where | * |---|---| * | does a Python callable become a Kotlin `FunctionN`, with the composer threaded through | here, on all five targets, against [ComposableShapedFragment] | - * | does a real `androidx.compose.foundation.layout.Column` then draw its content | `:ksp-fixtures:compose`'s `ComposableRenderTest`, desktop only | + * | does a real `androidx.compose.foundation.layout.Column` then draw its content | `:python-multiplatform-compose:fixtures:compose`'s `ComposableRenderTest`, desktop only | * | does Compose give the callable back when it drops the slot | `ComposableRenderTest.aDisposedCompositionGivesEveryPythonCallableBack`, because `RememberObserver` is a Compose type | * * The split is [ComposableShapedFragment]'s: `commonTest` runs where there is no Compose runtime, no @@ -254,7 +254,7 @@ class PythonxCallableTest { * * This used to assert the opposite, and the opposite was true: one wrapper per crossing, nothing * interned, so *n* crossings cost *n* Python references and *n* `HandleTable` roots held until - * the scope closed. `:ksp-fixtures:compose`'s `RecompositionAccumulationTest` measured what that + * the scope closed. `:python-multiplatform-compose:fixtures:compose`'s `RecompositionAccumulationTest` measured what that * came to for a real composition -- **twelve** wrappers for one `content=` composed twelve times, * and twenty-four for a `Button` -- and `PythonCallableScope` now keys them. The number here is 1. * diff --git a/python-multiplatform/src/commonTest/kotlin/python/multiplatform/ffi/pythonx/PythonxComposableTest.kt b/python-multiplatform/src/commonTest/kotlin/python/multiplatform/ffi/pythonx/PythonxComposableTest.kt index 65fb0fe36..1a9f7ab68 100644 --- a/python-multiplatform/src/commonTest/kotlin/python/multiplatform/ffi/pythonx/PythonxComposableTest.kt +++ b/python-multiplatform/src/commonTest/kotlin/python/multiplatform/ffi/pythonx/PythonxComposableTest.kt @@ -40,7 +40,7 @@ import kotlin.test.assertTrue * * It is not a proof that Compose draws anything. The fragment behind it is Kotlin this repository * owns ([ComposableShapedFragment]), because `commonTest` runs on Kotlin/Native where there is no - * Compose runtime and no generated thunk class. `:ksp-fixtures:compose`'s `ComposableRenderTest` is + * Compose runtime and no generated thunk class. `:python-multiplatform-compose:fixtures:compose`'s `ComposableRenderTest` is * the other half, and it renders a real `Text` through a real `Composer`. */ class PythonxComposableTest { diff --git a/python-multiplatform/src/commonTest/kotlin/python/multiplatform/ffi/upcall/PythonProxySourceTest.kt b/python-multiplatform/src/commonTest/kotlin/python/multiplatform/ffi/upcall/PythonProxySourceTest.kt index 4105d343f..848bf40b4 100644 --- a/python-multiplatform/src/commonTest/kotlin/python/multiplatform/ffi/upcall/PythonProxySourceTest.kt +++ b/python-multiplatform/src/commonTest/kotlin/python/multiplatform/ffi/upcall/PythonProxySourceTest.kt @@ -842,7 +842,7 @@ class PythonProxySourceTest { // A rendered class must be a `_PmObject` (so `_pm_unwrap` accepts an instance of one) *and* // its statics must sit on a metaclass. Written the obvious way those two read as // `class Foo(_PmObject, metaclass=_pm_t_1):`, and that spelling is what broke - // `ksp-fixtures:app`: see [theCompanionShapeAConsumerMatchesWithALazyRegexStaysAdjacent]. + // `python-multiplatform-ksp:fixtures:app`: see [theCompanionShapeAConsumerMatchesWithALazyRegexStaysAdjacent]. // // Python has no syntax for putting a base *after* a keyword, so the base has to come from // somewhere other than the base list, and the metaclass is the only thing left holding the @@ -876,7 +876,7 @@ class PythonProxySourceTest { @Test fun theCompanionShapeAConsumerMatchesWithALazyRegexStaysAdjacent() { // Pinned here because the consumer that reads it cannot pin it for itself, and because the - // way it failed hid what had happened. `ksp-fixtures:app`'s + // way it failed hid what had happened. `python-multiplatform-ksp:fixtures:app`'s // `GeneratedStaticPropertyProxyTest` locates a companion's metaclass with // // class (_pm_t_\d+)\(type\):\n(?:.|\n)*?class Foo\(metaclass=\1\): diff --git a/python-multiplatform/src/commonTest/kotlin/python/multiplatform/ffi/upcall/UpcallBootstrapTest.kt b/python-multiplatform/src/commonTest/kotlin/python/multiplatform/ffi/upcall/UpcallBootstrapTest.kt index 0d20f9a4b..6171499d4 100644 --- a/python-multiplatform/src/commonTest/kotlin/python/multiplatform/ffi/upcall/UpcallBootstrapTest.kt +++ b/python-multiplatform/src/commonTest/kotlin/python/multiplatform/ffi/upcall/UpcallBootstrapTest.kt @@ -11,7 +11,7 @@ import kotlin.test.assertTrue * existed, a consumer outside `python-multiplatform` had no route to the four names * [PythonProxySource.install]'s entry-point guard requires -- only this module's own **test** * source (`UpcallEntryBridge.desktop.kt`) rebuilt them, by hand, from the public - * `python.native.ffi.UpcallStub` addresses. `ksp-fixtures/artifact`'s + * `python.native.ffi.UpcallStub` addresses. `python-multiplatform-gradle-plugin/fixtures/artifact`'s * `WalkedArtifactPythonImportTest` copied that workaround because there was nothing else to call; * it now calls this instead. */ diff --git a/python-multiplatform/src/commonTest/kotlin/python/multiplatform/reflection/TestFragments.kt b/python-multiplatform/src/commonTest/kotlin/python/multiplatform/reflection/TestFragments.kt index 4ac437839..d49da0286 100644 --- a/python-multiplatform/src/commonTest/kotlin/python/multiplatform/reflection/TestFragments.kt +++ b/python-multiplatform/src/commonTest/kotlin/python/multiplatform/reflection/TestFragments.kt @@ -174,7 +174,7 @@ enum class TestColor(val weight: Long) { /** * The declaration kinds whose members do not take a receiver -- companion/object members and * enum entries -- plus the class descriptors that tell the Python side what shape to build. - * Written the way `python-multiplatform-ksp` emits them; `ksp-fixtures` proves the generator + * Written the way `python-multiplatform-ksp` emits them; `python-multiplatform-ksp/fixtures` proves the generator * actually does. */ object TestStaticsFragment : FunctionTableFragment { diff --git a/sample/build.gradle.kts b/sample/build.gradle.kts index c16bd4af8..c80d43103 100644 --- a/sample/build.gradle.kts +++ b/sample/build.gradle.kts @@ -34,7 +34,7 @@ plugins { // Gradle 8.11.1, which AGP 8.10 requires), so the split is gone and this module holds its own // Python-facing declarations again -- `src/*/kotlin/.../demo/bindings/`. // - // `ksp-fixtures/android` is the regression test. It is the first fixture to apply an Android + // `python-multiplatform-ksp/fixtures/android` is the regression test. It is the first fixture to apply an Android // plugin, which is exactly why nothing caught this. id("io.github.thisisthepy.python.multiplatform.bindings") } diff --git a/sample/src/iosMain/kotlin/org/thisisthepy/python/multiplatform/demo/bindings/UpcallDemo.ios.kt b/sample/src/iosMain/kotlin/org/thisisthepy/python/multiplatform/demo/bindings/UpcallDemo.ios.kt index cbb0aeaaa..324c95226 100644 --- a/sample/src/iosMain/kotlin/org/thisisthepy/python/multiplatform/demo/bindings/UpcallDemo.ios.kt +++ b/sample/src/iosMain/kotlin/org/thisisthepy/python/multiplatform/demo/bindings/UpcallDemo.ios.kt @@ -17,7 +17,7 @@ import python.multiplatform.reflection.UpcallTable * `@InstallsUpcallTable expect fun installGeneratedUpcallTable()` and every leaf gets its own * one-liner generated into it. The constraint is unchanged -- the generated table is reachable * only from the source set of the target that generated it -- but nothing shared code writes has - * to know that any more. `ksp-fixtures/app`'s `androidNativeMain` pins the same shape. + * to know that any more. `python-multiplatform-ksp/fixtures/app`'s `androidNativeMain` pins the same shape. */ /** diff --git a/settings.gradle.kts b/settings.gradle.kts index 08847bea3..fadc453a2 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -44,30 +44,49 @@ include(":python-multiplatform-ksp") // The Compose host: the `@Composable` that draws a Python-declared root. Its own module so that // `:python-multiplatform` never depends on Compose. include(":python-multiplatform-compose") -include(":ksp-fixtures:library") -include(":ksp-fixtures:app") +// Fixtures live inside the module whose output they check (issue #108), as nested Gradle projects. +// The KSP processor's consumers are `python-multiplatform-ksp/fixtures/*`. The intermediate +// `:python-multiplatform-ksp:fixtures` project that Gradle creates for the path has no build file +// and no plugins; it is only a container. +include(":python-multiplatform-ksp:fixtures:library") +include(":python-multiplatform-ksp:fixtures:app") // The fixture that carries an Android plugin. `:library` and `:app` apply none, which is why the // KSP/AGP minimum-version wall of ROADMAP §13 stayed invisible to them while it broke every // Android consumer of the bindings plugin. -include(":ksp-fixtures:android") +include(":python-multiplatform-ksp:fixtures:android") + +// The Gradle plugin is an *included build* (see `pluginManagement` above), so it cannot own +// subprojects of this build. Its fixtures are therefore root-build projects whose directory is +// `python-multiplatform-gradle-plugin/fixtures/` (the plugin build's own settings never +// look there). The project path is `:python-multiplatform-gradle-plugin-fixtures:`: a path +// `:python-multiplatform-gradle-plugin:...` would share its name with the included build. // The fixture for the *other* binding producer: `docs/design/ecosystem.md` §5b's artefact walker, which // reads the jars the build resolves rather than the source it compiles. `:library` and `:app` cover // KSP only, so nothing here exercised a third-party binary until this module existed. -include(":ksp-fixtures:artifact") -// The composable half of the same claim, and the one module in this build that applies the Compose -// compiler plugin for a *test*: `:ksp-fixtures:artifact` deliberately has none (its own -// `build.gradle.kts` says why), and a `Composer` cannot exist without one. See its -// `PythonComposition.kt` -- one hand-written `@Composable`, for every composable in every artefact. -include(":ksp-fixtures:compose") +include(":python-multiplatform-gradle-plugin-fixtures:artifact") // A real, separately-compiled jar for the walker's value-class handling -- `kotlin.time.Duration` // cannot prove a positive round trip (its constructor is `internal`), so this stands in for it. See // its own `build.gradle.kts`. -include(":ksp-fixtures:artifact-valueclass") +include(":python-multiplatform-gradle-plugin-fixtures:artifact-valueclass") // The same walker, pointed at a Kotlin/Native compile classpath instead of a JVM one -- // ROADMAP §16e's "investigated, not implemented" half. `KlibScanner` reads `.klib` metadata with // `LibraryAbiReader` instead of ASM. -include(":ksp-fixtures:klib-artifact") +include(":python-multiplatform-gradle-plugin-fixtures:klib-artifact") +// The container project for the three above (no build file, no plugins), then each fixture. +project(":python-multiplatform-gradle-plugin-fixtures").projectDir = + file("python-multiplatform-gradle-plugin/fixtures") +for (name in listOf("artifact", "artifact-valueclass", "klib-artifact")) { + project(":python-multiplatform-gradle-plugin-fixtures:$name").projectDir = + file("python-multiplatform-gradle-plugin/fixtures/$name") +} + +// The Compose host's consumers: `python-multiplatform-compose/fixtures/*`. +// The composable half of the same claim, and the one module in this build that applies the Compose +// compiler plugin for a *test*: `:python-multiplatform-gradle-plugin-fixtures:artifact` deliberately +// has none (its own `build.gradle.kts` says why), and a `Composer` cannot exist without one. See its +// `PythonComposition.kt` -- one hand-written `@Composable`, for every composable in every artefact. +include(":python-multiplatform-compose:fixtures:compose") // pythonx-compose's `UI.ipynb` scenarios end to end (issue #26): the installed pythonx-compose wheel, // drawn by `PythonContent`. A fixture and not `sample/`, which is user-authored spec material. Its // desktopTest needs `-PpythonxComposeWheel=`; see its README. -include(":ksp-fixtures:notebook-e2e") +include(":python-multiplatform-compose:fixtures:notebook-e2e")