kivyforge 3.0.0.dev0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- kivyforge/__init__.py +9 -0
- kivyforge/artifacts/__init__.py +41 -0
- kivyforge/artifacts/cache.py +81 -0
- kivyforge/artifacts/collect.py +354 -0
- kivyforge/artifacts/download.py +125 -0
- kivyforge/artifacts/frameworks.py +240 -0
- kivyforge/artifacts/native_stage_util.py +346 -0
- kivyforge/artifacts/runtime.py +65 -0
- kivyforge/artifacts/verify.py +45 -0
- kivyforge/artifacts/wheels.py +89 -0
- kivyforge/bundle/__init__.py +1 -0
- kivyforge/bundle/pycompile.py +161 -0
- kivyforge/cli/__init__.py +52 -0
- kivyforge/cli/_common.py +62 -0
- kivyforge/cli/_platform.py +84 -0
- kivyforge/cli/build.py +111 -0
- kivyforge/cli/clean.py +135 -0
- kivyforge/cli/doctor.py +52 -0
- kivyforge/cli/init.py +612 -0
- kivyforge/cli/init_writer.py +716 -0
- kivyforge/cli/lock.py +261 -0
- kivyforge/cli/open_cmd.py +15 -0
- kivyforge/cli/package.py +134 -0
- kivyforge/cli/run.py +162 -0
- kivyforge/cli/status.py +20 -0
- kivyforge/cli/upgrade.py +314 -0
- kivyforge/config/__init__.py +46 -0
- kivyforge/config/errors.py +43 -0
- kivyforge/config/icons.py +60 -0
- kivyforge/config/loader.py +3079 -0
- kivyforge/config/model.py +817 -0
- kivyforge/doctor/__init__.py +19 -0
- kivyforge/doctor/checks_common.py +95 -0
- kivyforge/doctor/probe.py +357 -0
- kivyforge/doctor/result.py +41 -0
- kivyforge/lock/__init__.py +42 -0
- kivyforge/lock/_pip_shim.py +63 -0
- kivyforge/lock/find_links.py +182 -0
- kivyforge/lock/model.py +69 -0
- kivyforge/lock/pep751.py +111 -0
- kivyforge/lock/reader.py +30 -0
- kivyforge/lock/resolver.py +124 -0
- kivyforge/lock/wheelruntime/__init__.py +70 -0
- kivyforge/lock/wheelruntime/builder.py +280 -0
- kivyforge/lock/wheelruntime/model.py +94 -0
- kivyforge/lock/wheelruntime/native_binaries.py +127 -0
- kivyforge/lock/wheelruntime/pbs_github.py +133 -0
- kivyforge/lock/wheelruntime/profile.py +104 -0
- kivyforge/lock/wheelruntime/resolver.py +248 -0
- kivyforge/lock/wheelruntime/runtime.py +161 -0
- kivyforge/lock/wheelruntime/serialize.py +245 -0
- kivyforge/platforms/__init__.py +114 -0
- kivyforge/platforms/android/__init__.py +140 -0
- kivyforge/platforms/android/adb.py +215 -0
- kivyforge/platforms/android/bootstrap/__init__.py +7 -0
- kivyforge/platforms/android/bootstrap/contract.py +166 -0
- kivyforge/platforms/android/bootstrap/render.py +244 -0
- kivyforge/platforms/android/bootstrap/templates/androidtest/KivyforgeContractTest.java +76 -0
- kivyforge/platforms/android/bootstrap/templates/bootstrap_py/_kivy_bootstrap.py +50 -0
- kivyforge/platforms/android/bootstrap/templates/bootstrap_py/_kivyforge_bootstrap.py +54 -0
- kivyforge/platforms/android/bootstrap/templates/bootstrap_py/_kivyforge_selftest.py +97 -0
- kivyforge/platforms/android/bootstrap/templates/cpp/CMakeLists.txt +20 -0
- kivyforge/platforms/android/bootstrap/templates/cpp/main.c +150 -0
- kivyforge/platforms/android/bootstrap/templates/java/org/jnius/NativeInvocationHandler.java +48 -0
- kivyforge/platforms/android/bootstrap/templates/java/org/kivy/android/PythonActivity.java +75 -0
- kivyforge/platforms/android/bootstrap/templates/java/org/kivy/android/PythonBundle.java +132 -0
- kivyforge/platforms/android/bootstrap/templates/java/org/kivy/android/PythonService.java +189 -0
- kivyforge/platforms/android/bootstrap/templates/java/org/renpy/android/Hardware.java +276 -0
- kivyforge/platforms/android/bootstrap/templates/sdl2/LICENSE-SDL.txt +18 -0
- kivyforge/platforms/android/bootstrap/templates/sdl2/SDL_REVISION.txt +3 -0
- kivyforge/platforms/android/bootstrap/templates/sdl2/org/libsdl/app/HIDDevice.java +22 -0
- kivyforge/platforms/android/bootstrap/templates/sdl2/org/libsdl/app/HIDDeviceBLESteamController.java +650 -0
- kivyforge/platforms/android/bootstrap/templates/sdl2/org/libsdl/app/HIDDeviceManager.java +698 -0
- kivyforge/platforms/android/bootstrap/templates/sdl2/org/libsdl/app/HIDDeviceUSB.java +309 -0
- kivyforge/platforms/android/bootstrap/templates/sdl2/org/libsdl/app/SDL.java +90 -0
- kivyforge/platforms/android/bootstrap/templates/sdl2/org/libsdl/app/SDLActivity.java +2120 -0
- kivyforge/platforms/android/bootstrap/templates/sdl2/org/libsdl/app/SDLAudioManager.java +514 -0
- kivyforge/platforms/android/bootstrap/templates/sdl2/org/libsdl/app/SDLControllerManager.java +856 -0
- kivyforge/platforms/android/bootstrap/templates/sdl2/org/libsdl/app/SDLSurface.java +405 -0
- kivyforge/platforms/android/bootstrap/templates/sdl3/LICENSE-SDL.txt +18 -0
- kivyforge/platforms/android/bootstrap/templates/sdl3/SDL_REVISION.txt +3 -0
- kivyforge/platforms/android/bootstrap/templates/sdl3/org/libsdl/app/HIDDevice.java +21 -0
- kivyforge/platforms/android/bootstrap/templates/sdl3/org/libsdl/app/HIDDeviceBLESteamController.java +829 -0
- kivyforge/platforms/android/bootstrap/templates/sdl3/org/libsdl/app/HIDDeviceManager.java +698 -0
- kivyforge/platforms/android/bootstrap/templates/sdl3/org/libsdl/app/HIDDeviceUSB.java +354 -0
- kivyforge/platforms/android/bootstrap/templates/sdl3/org/libsdl/app/SDL.java +90 -0
- kivyforge/platforms/android/bootstrap/templates/sdl3/org/libsdl/app/SDLActivity.java +2240 -0
- kivyforge/platforms/android/bootstrap/templates/sdl3/org/libsdl/app/SDLAudioManager.java +126 -0
- kivyforge/platforms/android/bootstrap/templates/sdl3/org/libsdl/app/SDLControllerManager.java +1010 -0
- kivyforge/platforms/android/bootstrap/templates/sdl3/org/libsdl/app/SDLDummyEdit.java +66 -0
- kivyforge/platforms/android/bootstrap/templates/sdl3/org/libsdl/app/SDLInputConnection.java +136 -0
- kivyforge/platforms/android/bootstrap/templates/sdl3/org/libsdl/app/SDLSensorManager.java +73 -0
- kivyforge/platforms/android/bootstrap/templates/sdl3/org/libsdl/app/SDLSurface.java +464 -0
- kivyforge/platforms/android/cli.py +1023 -0
- kivyforge/platforms/android/doctor.py +899 -0
- kivyforge/platforms/android/elf.py +148 -0
- kivyforge/platforms/android/generate/__init__.py +1 -0
- kivyforge/platforms/android/generate/manifest.py +261 -0
- kivyforge/platforms/android/generate/project.py +462 -0
- kivyforge/platforms/android/generate/services.py +187 -0
- kivyforge/platforms/android/gradle_wrapper/NOTICE +3 -0
- kivyforge/platforms/android/gradle_wrapper/SHA256SUMS +1 -0
- kivyforge/platforms/android/gradle_wrapper/gradle-wrapper.jar +0 -0
- kivyforge/platforms/android/gradle_wrapper/gradlew +164 -0
- kivyforge/platforms/android/gradle_wrapper/gradlew.bat +90 -0
- kivyforge/platforms/android/gradlew.py +60 -0
- kivyforge/platforms/android/icons.py +237 -0
- kivyforge/platforms/android/lock/__init__.py +1 -0
- kivyforge/platforms/android/lock/archives.py +109 -0
- kivyforge/platforms/android/lock/builder.py +387 -0
- kivyforge/platforms/android/lock/markers.py +71 -0
- kivyforge/platforms/android/lock/maven.py +252 -0
- kivyforge/platforms/android/lock/model.py +113 -0
- kivyforge/platforms/android/lock/python_meta.py +199 -0
- kivyforge/platforms/android/lock/reader.py +206 -0
- kivyforge/platforms/android/lock/resolver.py +276 -0
- kivyforge/platforms/android/lock/writer.py +121 -0
- kivyforge/platforms/android/policy.py +214 -0
- kivyforge/platforms/android/signing.py +145 -0
- kivyforge/platforms/android/smoke.py +43 -0
- kivyforge/platforms/android/splash.py +293 -0
- kivyforge/platforms/android/stage/__init__.py +1 -0
- kivyforge/platforms/android/stage/bundle.py +295 -0
- kivyforge/platforms/android/stage/jnilibs.py +186 -0
- kivyforge/platforms/android/stage/runtime.py +61 -0
- kivyforge/platforms/android/stage/wheels.py +106 -0
- kivyforge/platforms/android/toolchain.py +29 -0
- kivyforge/platforms/base.py +157 -0
- kivyforge/platforms/ios/__init__.py +129 -0
- kivyforge/platforms/ios/assets.py +193 -0
- kivyforge/platforms/ios/buildsettings.py +128 -0
- kivyforge/platforms/ios/cli.py +543 -0
- kivyforge/platforms/ios/doctor.py +410 -0
- kivyforge/platforms/ios/entitlements.py +34 -0
- kivyforge/platforms/ios/generator.py +318 -0
- kivyforge/platforms/ios/lock/__init__.py +71 -0
- kivyforge/platforms/ios/lock/builder.py +393 -0
- kivyforge/platforms/ios/lock/markers.py +69 -0
- kivyforge/platforms/ios/lock/model.py +95 -0
- kivyforge/platforms/ios/lock/python_meta.py +187 -0
- kivyforge/platforms/ios/lock/reader.py +191 -0
- kivyforge/platforms/ios/lock/resolver.py +304 -0
- kivyforge/platforms/ios/lock/spm.py +217 -0
- kivyforge/platforms/ios/lock/writer.py +114 -0
- kivyforge/platforms/ios/lock/xcframework.py +188 -0
- kivyforge/platforms/ios/materialize.py +59 -0
- kivyforge/platforms/ios/plist.py +91 -0
- kivyforge/platforms/ios/privacy.py +39 -0
- kivyforge/platforms/ios/skeleton.py +165 -0
- kivyforge/platforms/ios/sources.py +63 -0
- kivyforge/platforms/ios/staging.py +225 -0
- kivyforge/platforms/ios/swift_packages.py +324 -0
- kivyforge/platforms/ios/templates/kivyforge_bootstrap.h +34 -0
- kivyforge/platforms/ios/templates/kivyforge_bootstrap.m +146 -0
- kivyforge/platforms/ios/templates/main.m +15 -0
- kivyforge/platforms/ios/templates/main_config.h.in +12 -0
- kivyforge/platforms/ios/xcframeworks.py +194 -0
- kivyforge/platforms/ios/xcode/__init__.py +76 -0
- kivyforge/platforms/ios/xcode/commands.py +296 -0
- kivyforge/platforms/ios/xcode/runner.py +316 -0
- kivyforge/platforms/linux/__init__.py +120 -0
- kivyforge/platforms/linux/appimage.py +169 -0
- kivyforge/platforms/linux/bundle.py +235 -0
- kivyforge/platforms/linux/cli.py +232 -0
- kivyforge/platforms/linux/desktop.py +71 -0
- kivyforge/platforms/linux/doctor.py +438 -0
- kivyforge/platforms/linux/elftools.py +95 -0
- kivyforge/platforms/linux/icons.py +129 -0
- kivyforge/platforms/linux/launcher.py +107 -0
- kivyforge/platforms/linux/lock/__init__.py +126 -0
- kivyforge/platforms/linux/lock/profile.py +254 -0
- kivyforge/platforms/linux/lock/runtime.py +75 -0
- kivyforge/platforms/linux/native_stage.py +47 -0
- kivyforge/platforms/linux/runtime_stage.py +107 -0
- kivyforge/platforms/linux/wheels_stage.py +103 -0
- kivyforge/platforms/macos/__init__.py +121 -0
- kivyforge/platforms/macos/bundle.py +255 -0
- kivyforge/platforms/macos/cli.py +269 -0
- kivyforge/platforms/macos/doctor.py +480 -0
- kivyforge/platforms/macos/icns.py +75 -0
- kivyforge/platforms/macos/launcher.py +118 -0
- kivyforge/platforms/macos/lock/__init__.py +112 -0
- kivyforge/platforms/macos/lock/profile.py +119 -0
- kivyforge/platforms/macos/lock/runtime.py +58 -0
- kivyforge/platforms/macos/machotools.py +138 -0
- kivyforge/platforms/macos/native_stage.py +47 -0
- kivyforge/platforms/macos/notarize.py +143 -0
- kivyforge/platforms/macos/plist.py +37 -0
- kivyforge/platforms/macos/runtime_stage.py +110 -0
- kivyforge/platforms/macos/signing.py +78 -0
- kivyforge/platforms/macos/wheels_stage.py +108 -0
- kivyforge/platforms/windows/__init__.py +133 -0
- kivyforge/platforms/windows/assets.py +76 -0
- kivyforge/platforms/windows/bundle.py +298 -0
- kivyforge/platforms/windows/cli.py +314 -0
- kivyforge/platforms/windows/doctor.py +563 -0
- kivyforge/platforms/windows/fsswap.py +87 -0
- kivyforge/platforms/windows/icons.py +64 -0
- kivyforge/platforms/windows/launcher/__init__.py +193 -0
- kivyforge/platforms/windows/launcher/build_launcher.py +507 -0
- kivyforge/platforms/windows/launcher/launcher.c +379 -0
- kivyforge/platforms/windows/lock/__init__.py +112 -0
- kivyforge/platforms/windows/lock/profile.py +101 -0
- kivyforge/platforms/windows/lock/runtime.py +64 -0
- kivyforge/platforms/windows/naming.py +52 -0
- kivyforge/platforms/windows/native_stage.py +66 -0
- kivyforge/platforms/windows/petools.py +98 -0
- kivyforge/platforms/windows/rcedit.py +116 -0
- kivyforge/platforms/windows/runtime_stage.py +221 -0
- kivyforge/platforms/windows/signing.py +168 -0
- kivyforge/platforms/windows/vendor/LICENSE.rcedit +29 -0
- kivyforge/platforms/windows/vendor/NOTICE +17 -0
- kivyforge/platforms/windows/vendor/SHA256SUMS +4 -0
- kivyforge/platforms/windows/vendor/TOOLSET.txt +4 -0
- kivyforge/platforms/windows/vendor/__init__.py +12 -0
- kivyforge/platforms/windows/vendor/fetch_rcedit.py +97 -0
- kivyforge/platforms/windows/vendor/launcher-amd64.exe +0 -0
- kivyforge/platforms/windows/vendor/rcedit-x64.exe +0 -0
- kivyforge/platforms/windows/wheels_stage.py +139 -0
- kivyforge-3.0.0.dev0.dist-info/METADATA +609 -0
- kivyforge-3.0.0.dev0.dist-info/RECORD +225 -0
- kivyforge-3.0.0.dev0.dist-info/WHEEL +5 -0
- kivyforge-3.0.0.dev0.dist-info/entry_points.txt +3 -0
- kivyforge-3.0.0.dev0.dist-info/licenses/LICENSE +21 -0
- kivyforge-3.0.0.dev0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
|
|
3
|
+
##############################################################################
|
|
4
|
+
##
|
|
5
|
+
## Gradle start up script for UN*X
|
|
6
|
+
##
|
|
7
|
+
##############################################################################
|
|
8
|
+
|
|
9
|
+
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
|
10
|
+
DEFAULT_JVM_OPTS=""
|
|
11
|
+
|
|
12
|
+
APP_NAME="Gradle"
|
|
13
|
+
APP_BASE_NAME=`basename "$0"`
|
|
14
|
+
|
|
15
|
+
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
|
16
|
+
MAX_FD="maximum"
|
|
17
|
+
|
|
18
|
+
warn ( ) {
|
|
19
|
+
echo "$*"
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
die ( ) {
|
|
23
|
+
echo
|
|
24
|
+
echo "$*"
|
|
25
|
+
echo
|
|
26
|
+
exit 1
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
# OS specific support (must be 'true' or 'false').
|
|
30
|
+
cygwin=false
|
|
31
|
+
msys=false
|
|
32
|
+
darwin=false
|
|
33
|
+
case "`uname`" in
|
|
34
|
+
CYGWIN* )
|
|
35
|
+
cygwin=true
|
|
36
|
+
;;
|
|
37
|
+
Darwin* )
|
|
38
|
+
darwin=true
|
|
39
|
+
;;
|
|
40
|
+
MINGW* )
|
|
41
|
+
msys=true
|
|
42
|
+
;;
|
|
43
|
+
esac
|
|
44
|
+
|
|
45
|
+
# For Cygwin, ensure paths are in UNIX format before anything is touched.
|
|
46
|
+
if $cygwin ; then
|
|
47
|
+
[ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
|
|
48
|
+
fi
|
|
49
|
+
|
|
50
|
+
# Attempt to set APP_HOME
|
|
51
|
+
# Resolve links: $0 may be a link
|
|
52
|
+
PRG="$0"
|
|
53
|
+
# Need this for relative symlinks.
|
|
54
|
+
while [ -h "$PRG" ] ; do
|
|
55
|
+
ls=`ls -ld "$PRG"`
|
|
56
|
+
link=`expr "$ls" : '.*-> \(.*\)$'`
|
|
57
|
+
if expr "$link" : '/.*' > /dev/null; then
|
|
58
|
+
PRG="$link"
|
|
59
|
+
else
|
|
60
|
+
PRG=`dirname "$PRG"`"/$link"
|
|
61
|
+
fi
|
|
62
|
+
done
|
|
63
|
+
SAVED="`pwd`"
|
|
64
|
+
cd "`dirname \"$PRG\"`/" >&-
|
|
65
|
+
APP_HOME="`pwd -P`"
|
|
66
|
+
cd "$SAVED" >&-
|
|
67
|
+
|
|
68
|
+
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
|
69
|
+
|
|
70
|
+
# Determine the Java command to use to start the JVM.
|
|
71
|
+
if [ -n "$JAVA_HOME" ] ; then
|
|
72
|
+
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
|
73
|
+
# IBM's JDK on AIX uses strange locations for the executables
|
|
74
|
+
JAVACMD="$JAVA_HOME/jre/sh/java"
|
|
75
|
+
else
|
|
76
|
+
JAVACMD="$JAVA_HOME/bin/java"
|
|
77
|
+
fi
|
|
78
|
+
if [ ! -x "$JAVACMD" ] ; then
|
|
79
|
+
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
|
80
|
+
|
|
81
|
+
Please set the JAVA_HOME variable in your environment to match the
|
|
82
|
+
location of your Java installation."
|
|
83
|
+
fi
|
|
84
|
+
else
|
|
85
|
+
JAVACMD="java"
|
|
86
|
+
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
|
87
|
+
|
|
88
|
+
Please set the JAVA_HOME variable in your environment to match the
|
|
89
|
+
location of your Java installation."
|
|
90
|
+
fi
|
|
91
|
+
|
|
92
|
+
# Increase the maximum file descriptors if we can.
|
|
93
|
+
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
|
|
94
|
+
MAX_FD_LIMIT=`ulimit -H -n`
|
|
95
|
+
if [ $? -eq 0 ] ; then
|
|
96
|
+
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
|
97
|
+
MAX_FD="$MAX_FD_LIMIT"
|
|
98
|
+
fi
|
|
99
|
+
ulimit -n $MAX_FD
|
|
100
|
+
if [ $? -ne 0 ] ; then
|
|
101
|
+
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
|
102
|
+
fi
|
|
103
|
+
else
|
|
104
|
+
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
|
105
|
+
fi
|
|
106
|
+
fi
|
|
107
|
+
|
|
108
|
+
# For Darwin, add options to specify how the application appears in the dock
|
|
109
|
+
if $darwin; then
|
|
110
|
+
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
|
111
|
+
fi
|
|
112
|
+
|
|
113
|
+
# For Cygwin, switch paths to Windows format before running java
|
|
114
|
+
if $cygwin ; then
|
|
115
|
+
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
|
116
|
+
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
|
117
|
+
|
|
118
|
+
# We build the pattern for arguments to be converted via cygpath
|
|
119
|
+
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
|
120
|
+
SEP=""
|
|
121
|
+
for dir in $ROOTDIRSRAW ; do
|
|
122
|
+
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
|
123
|
+
SEP="|"
|
|
124
|
+
done
|
|
125
|
+
OURCYGPATTERN="(^($ROOTDIRS))"
|
|
126
|
+
# Add a user-defined pattern to the cygpath arguments
|
|
127
|
+
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
|
128
|
+
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
|
129
|
+
fi
|
|
130
|
+
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
|
131
|
+
i=0
|
|
132
|
+
for arg in "$@" ; do
|
|
133
|
+
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
|
134
|
+
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
|
135
|
+
|
|
136
|
+
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
|
137
|
+
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
|
138
|
+
else
|
|
139
|
+
eval `echo args$i`="\"$arg\""
|
|
140
|
+
fi
|
|
141
|
+
i=$((i+1))
|
|
142
|
+
done
|
|
143
|
+
case $i in
|
|
144
|
+
(0) set -- ;;
|
|
145
|
+
(1) set -- "$args0" ;;
|
|
146
|
+
(2) set -- "$args0" "$args1" ;;
|
|
147
|
+
(3) set -- "$args0" "$args1" "$args2" ;;
|
|
148
|
+
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
|
149
|
+
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
|
150
|
+
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
|
151
|
+
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
|
152
|
+
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
|
153
|
+
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
|
154
|
+
esac
|
|
155
|
+
fi
|
|
156
|
+
|
|
157
|
+
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
|
|
158
|
+
function splitJvmOpts() {
|
|
159
|
+
JVM_OPTS=("$@")
|
|
160
|
+
}
|
|
161
|
+
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
|
|
162
|
+
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
|
|
163
|
+
|
|
164
|
+
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
@if "%DEBUG%" == "" @echo off
|
|
2
|
+
@rem ##########################################################################
|
|
3
|
+
@rem
|
|
4
|
+
@rem Gradle startup script for Windows
|
|
5
|
+
@rem
|
|
6
|
+
@rem ##########################################################################
|
|
7
|
+
|
|
8
|
+
@rem Set local scope for the variables with windows NT shell
|
|
9
|
+
if "%OS%"=="Windows_NT" setlocal
|
|
10
|
+
|
|
11
|
+
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
|
12
|
+
set DEFAULT_JVM_OPTS=
|
|
13
|
+
|
|
14
|
+
set DIRNAME=%~dp0
|
|
15
|
+
if "%DIRNAME%" == "" set DIRNAME=.
|
|
16
|
+
set APP_BASE_NAME=%~n0
|
|
17
|
+
set APP_HOME=%DIRNAME%
|
|
18
|
+
|
|
19
|
+
@rem Find java.exe
|
|
20
|
+
if defined JAVA_HOME goto findJavaFromJavaHome
|
|
21
|
+
|
|
22
|
+
set JAVA_EXE=java.exe
|
|
23
|
+
%JAVA_EXE% -version >NUL 2>&1
|
|
24
|
+
if "%ERRORLEVEL%" == "0" goto init
|
|
25
|
+
|
|
26
|
+
echo.
|
|
27
|
+
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
|
28
|
+
echo.
|
|
29
|
+
echo Please set the JAVA_HOME variable in your environment to match the
|
|
30
|
+
echo location of your Java installation.
|
|
31
|
+
|
|
32
|
+
goto fail
|
|
33
|
+
|
|
34
|
+
:findJavaFromJavaHome
|
|
35
|
+
set JAVA_HOME=%JAVA_HOME:"=%
|
|
36
|
+
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
|
37
|
+
|
|
38
|
+
if exist "%JAVA_EXE%" goto init
|
|
39
|
+
|
|
40
|
+
echo.
|
|
41
|
+
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
|
42
|
+
echo.
|
|
43
|
+
echo Please set the JAVA_HOME variable in your environment to match the
|
|
44
|
+
echo location of your Java installation.
|
|
45
|
+
|
|
46
|
+
goto fail
|
|
47
|
+
|
|
48
|
+
:init
|
|
49
|
+
@rem Get command-line arguments, handling Windowz variants
|
|
50
|
+
|
|
51
|
+
if not "%OS%" == "Windows_NT" goto win9xME_args
|
|
52
|
+
if "%@eval[2+2]" == "4" goto 4NT_args
|
|
53
|
+
|
|
54
|
+
:win9xME_args
|
|
55
|
+
@rem Slurp the command line arguments.
|
|
56
|
+
set CMD_LINE_ARGS=
|
|
57
|
+
set _SKIP=2
|
|
58
|
+
|
|
59
|
+
:win9xME_args_slurp
|
|
60
|
+
if "x%~1" == "x" goto execute
|
|
61
|
+
|
|
62
|
+
set CMD_LINE_ARGS=%*
|
|
63
|
+
goto execute
|
|
64
|
+
|
|
65
|
+
:4NT_args
|
|
66
|
+
@rem Get arguments from the 4NT Shell from JP Software
|
|
67
|
+
set CMD_LINE_ARGS=%$
|
|
68
|
+
|
|
69
|
+
:execute
|
|
70
|
+
@rem Setup the command line
|
|
71
|
+
|
|
72
|
+
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
|
73
|
+
|
|
74
|
+
@rem Execute Gradle
|
|
75
|
+
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
|
|
76
|
+
|
|
77
|
+
:end
|
|
78
|
+
@rem End local scope for the variables with windows NT shell
|
|
79
|
+
if "%ERRORLEVEL%"=="0" goto mainEnd
|
|
80
|
+
|
|
81
|
+
:fail
|
|
82
|
+
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
|
83
|
+
rem the _cmd.exe /c_ return code!
|
|
84
|
+
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
|
85
|
+
exit /b 1
|
|
86
|
+
|
|
87
|
+
:mainEnd
|
|
88
|
+
if "%OS%"=="Windows_NT" endlocal
|
|
89
|
+
|
|
90
|
+
:omega
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"""Invoke the generated project's Gradle wrapper (android/06)."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import os
|
|
6
|
+
import subprocess
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class GradleError(Exception):
|
|
11
|
+
pass
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def run_gradle(
|
|
15
|
+
project_dir: Path,
|
|
16
|
+
tasks: list[str],
|
|
17
|
+
*,
|
|
18
|
+
env_overrides: dict[str, str] | None = None,
|
|
19
|
+
) -> None:
|
|
20
|
+
script = project_dir / ("gradlew.bat" if os.name == "nt" else "gradlew")
|
|
21
|
+
if not script.is_file():
|
|
22
|
+
raise GradleError(
|
|
23
|
+
f"no Gradle wrapper at {script}; run `kivyforge build` to "
|
|
24
|
+
"(re)generate the project."
|
|
25
|
+
)
|
|
26
|
+
env = dict(os.environ)
|
|
27
|
+
if env_overrides:
|
|
28
|
+
env.update(env_overrides)
|
|
29
|
+
cmd = [str(script), "--console=plain", *tasks]
|
|
30
|
+
proc = subprocess.run(cmd, cwd=project_dir, env=env, text=True)
|
|
31
|
+
if proc.returncode != 0:
|
|
32
|
+
raise GradleError(
|
|
33
|
+
f"Gradle failed (exit {proc.returncode}) running: {' '.join(tasks)}\n"
|
|
34
|
+
f" See the Gradle output above; `kivyforge doctor -p android` "
|
|
35
|
+
f"checks the JDK/SDK/NDK prerequisites."
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def stop_gradle_daemon(project_dir: Path) -> bool:
|
|
40
|
+
"""Best-effort ``gradlew --stop``; returns whether the wrapper ran.
|
|
41
|
+
|
|
42
|
+
`clean` needs this before removing ``<app>-android/``: a live daemon keeps
|
|
43
|
+
file handles open under ``app/build``, which makes the removal fail outright
|
|
44
|
+
on Windows. Every failure mode here is benign — no wrapper, no JDK, no
|
|
45
|
+
daemon — so this reports rather than raises.
|
|
46
|
+
"""
|
|
47
|
+
script = project_dir / ("gradlew.bat" if os.name == "nt" else "gradlew")
|
|
48
|
+
if not script.is_file():
|
|
49
|
+
return False
|
|
50
|
+
try:
|
|
51
|
+
subprocess.run(
|
|
52
|
+
[str(script), "--console=plain", "--stop"],
|
|
53
|
+
cwd=project_dir,
|
|
54
|
+
capture_output=True,
|
|
55
|
+
text=True,
|
|
56
|
+
timeout=120,
|
|
57
|
+
)
|
|
58
|
+
except (OSError, subprocess.SubprocessError):
|
|
59
|
+
return False
|
|
60
|
+
return True
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
"""Generate the launcher-icon resources (android/01 §icons, android/04).
|
|
2
|
+
|
|
3
|
+
The generated manifest always names ``@mipmap/ic_launcher``, so *something* must
|
|
4
|
+
exist at that resource name in every build or AAPT fails the whole project. Two
|
|
5
|
+
paths lead there:
|
|
6
|
+
|
|
7
|
+
- **No configured source** — a plain generated default icon (standard library
|
|
8
|
+
only, no Pillow), so a freshly-``init``-ed project builds out of the box.
|
|
9
|
+
- **A configured 1024x1024 source** — the full **adaptive icon** set, resized
|
|
10
|
+
with [Pillow](https://python-pillow.org/) (the optional ``kivyforge[android]``
|
|
11
|
+
extra): a per-density legacy ``ic_launcher`` for API 24/25 launchers, the
|
|
12
|
+
``mipmap-anydpi-v26`` adaptive-icon pair for API 26+, and the round variants.
|
|
13
|
+
|
|
14
|
+
**Safe zone.** An adaptive icon's outer ring is cropped by whatever mask the
|
|
15
|
+
launcher applies: only the central 66 of 108 dp is guaranteed visible. The
|
|
16
|
+
source artwork is therefore scaled *into* that safe zone on a transparent
|
|
17
|
+
canvas rather than filling the layer edge to edge, which is what keeps a
|
|
18
|
+
1024x1024 source — the one thing the docs ask for — from being cropped.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
from __future__ import annotations
|
|
22
|
+
|
|
23
|
+
import struct
|
|
24
|
+
import zlib
|
|
25
|
+
from pathlib import Path
|
|
26
|
+
|
|
27
|
+
from kivyforge.config.icons import IconSourceError, validate_icon_source
|
|
28
|
+
from kivyforge.config.model import AndroidConfig, Config
|
|
29
|
+
|
|
30
|
+
# Launcher-icon densities: dpi bucket -> px for a 48dp legacy icon.
|
|
31
|
+
LEGACY_SIZES = {
|
|
32
|
+
"mdpi": 48,
|
|
33
|
+
"hdpi": 72,
|
|
34
|
+
"xhdpi": 96,
|
|
35
|
+
"xxhdpi": 144,
|
|
36
|
+
"xxxhdpi": 192,
|
|
37
|
+
}
|
|
38
|
+
# The same buckets for a 108dp adaptive-icon layer.
|
|
39
|
+
ADAPTIVE_SIZES = {
|
|
40
|
+
"mdpi": 108,
|
|
41
|
+
"hdpi": 162,
|
|
42
|
+
"xhdpi": 216,
|
|
43
|
+
"xxhdpi": 324,
|
|
44
|
+
"xxxhdpi": 432,
|
|
45
|
+
}
|
|
46
|
+
# Of the 108dp layer, the central 66dp is the guaranteed-visible safe zone.
|
|
47
|
+
SAFE_ZONE_RATIO = 66 / 108
|
|
48
|
+
# <monochrome> in an adaptive icon is an API 33 attribute; AAPT rejects it when
|
|
49
|
+
# compiling against anything older.
|
|
50
|
+
MONOCHROME_MIN_COMPILE_SDK = 33
|
|
51
|
+
|
|
52
|
+
DEFAULT_BACKGROUND = "#ffffff"
|
|
53
|
+
# The generated default icon's fill (a Kivy-ish blue-grey).
|
|
54
|
+
_DEFAULT_RGBA = (52, 73, 94, 255)
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
class IconError(Exception):
|
|
58
|
+
"""The configured icon set could not be generated."""
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def write_icons(
|
|
62
|
+
res: Path, config: Config, android: AndroidConfig, project_root: Path
|
|
63
|
+
) -> bool:
|
|
64
|
+
"""Write the icon resources under *res*; return ``True`` if a source was used."""
|
|
65
|
+
icons = android.icons
|
|
66
|
+
if not icons.source:
|
|
67
|
+
_write_default(res)
|
|
68
|
+
return False
|
|
69
|
+
|
|
70
|
+
source = _open(project_root / icons.source)
|
|
71
|
+
background = icons.background or DEFAULT_BACKGROUND
|
|
72
|
+
if not background.startswith("#"):
|
|
73
|
+
background_image = _open(project_root / background)
|
|
74
|
+
else:
|
|
75
|
+
background_image = None
|
|
76
|
+
_write_background_color(res, background)
|
|
77
|
+
monochrome = _open(project_root / icons.monochrome) if icons.monochrome else None
|
|
78
|
+
if monochrome is not None and android.compile_sdk < MONOCHROME_MIN_COMPILE_SDK:
|
|
79
|
+
raise IconError(
|
|
80
|
+
"[tool.kivy.android.icons].monochrome needs compile_sdk >= "
|
|
81
|
+
f"{MONOCHROME_MIN_COMPILE_SDK} (the themed-icon <monochrome> layer "
|
|
82
|
+
f"is an API {MONOCHROME_MIN_COMPILE_SDK} attribute); this project "
|
|
83
|
+
f"compiles against android-{android.compile_sdk}.\n"
|
|
84
|
+
" Raise [tool.kivy.android].compile_sdk, or drop the monochrome "
|
|
85
|
+
"layer."
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
for bucket, size in LEGACY_SIZES.items():
|
|
89
|
+
mipmap = res / f"mipmap-{bucket}"
|
|
90
|
+
mipmap.mkdir(parents=True, exist_ok=True)
|
|
91
|
+
legacy = _fit(source, size)
|
|
92
|
+
_save(legacy, mipmap / "ic_launcher.png")
|
|
93
|
+
_save(_circular(legacy), mipmap / "ic_launcher_round.png")
|
|
94
|
+
|
|
95
|
+
for bucket, size in ADAPTIVE_SIZES.items():
|
|
96
|
+
mipmap = res / f"mipmap-{bucket}"
|
|
97
|
+
mipmap.mkdir(parents=True, exist_ok=True)
|
|
98
|
+
_save(_safe_zone_layer(source, size), mipmap / "ic_launcher_foreground.png")
|
|
99
|
+
if background_image is not None:
|
|
100
|
+
_save(_fit(background_image, size), mipmap / "ic_launcher_background.png")
|
|
101
|
+
if monochrome is not None:
|
|
102
|
+
_save(
|
|
103
|
+
_safe_zone_layer(monochrome, size),
|
|
104
|
+
mipmap / "ic_launcher_monochrome.png",
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
anydpi = res / "mipmap-anydpi-v26"
|
|
108
|
+
anydpi.mkdir(parents=True, exist_ok=True)
|
|
109
|
+
xml = adaptive_icon_xml(
|
|
110
|
+
background_is_color=background_image is None,
|
|
111
|
+
monochrome=monochrome is not None,
|
|
112
|
+
)
|
|
113
|
+
for name in ("ic_launcher.xml", "ic_launcher_round.xml"):
|
|
114
|
+
(anydpi / name).write_text(xml, encoding="utf-8", newline="\n")
|
|
115
|
+
return True
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def adaptive_icon_xml(*, background_is_color: bool, monochrome: bool) -> str:
|
|
119
|
+
"""The ``mipmap-anydpi-v26`` adaptive-icon drawable (pure/testable)."""
|
|
120
|
+
background = (
|
|
121
|
+
"@color/ic_launcher_background"
|
|
122
|
+
if background_is_color
|
|
123
|
+
else "@mipmap/ic_launcher_background"
|
|
124
|
+
)
|
|
125
|
+
lines = [
|
|
126
|
+
'<?xml version="1.0" encoding="utf-8"?>',
|
|
127
|
+
'<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">',
|
|
128
|
+
f' <background android:drawable="{background}" />',
|
|
129
|
+
' <foreground android:drawable="@mipmap/ic_launcher_foreground" />',
|
|
130
|
+
]
|
|
131
|
+
if monochrome:
|
|
132
|
+
lines.append(
|
|
133
|
+
' <monochrome android:drawable="@mipmap/ic_launcher_monochrome" />'
|
|
134
|
+
)
|
|
135
|
+
lines.append("</adaptive-icon>")
|
|
136
|
+
return "\n".join(lines) + "\n"
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
def _write_background_color(res: Path, color: str) -> None:
|
|
140
|
+
values = res / "values"
|
|
141
|
+
values.mkdir(parents=True, exist_ok=True)
|
|
142
|
+
(values / "ic_launcher_background.xml").write_text(
|
|
143
|
+
"<resources>\n"
|
|
144
|
+
f' <color name="ic_launcher_background">{color}</color>\n'
|
|
145
|
+
"</resources>\n",
|
|
146
|
+
encoding="utf-8",
|
|
147
|
+
newline="\n",
|
|
148
|
+
)
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def _write_default(res: Path) -> None:
|
|
152
|
+
"""Emit the one density AAPT needs for @mipmap/ic_launcher to resolve."""
|
|
153
|
+
mipmap = res / "mipmap-mdpi"
|
|
154
|
+
mipmap.mkdir(parents=True, exist_ok=True)
|
|
155
|
+
(mipmap / "ic_launcher.png").write_bytes(
|
|
156
|
+
default_icon_png(LEGACY_SIZES["mdpi"], _DEFAULT_RGBA)
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def default_icon_png(size: int, rgba: tuple[int, int, int, int]) -> bytes:
|
|
161
|
+
"""A valid solid-colour 8-bit RGBA PNG, built without any imaging library."""
|
|
162
|
+
row = b"\x00" + bytes(rgba) * size # per-scanline filter byte (0) + pixels
|
|
163
|
+
|
|
164
|
+
def chunk(tag: bytes, data: bytes) -> bytes:
|
|
165
|
+
body = tag + data
|
|
166
|
+
return (
|
|
167
|
+
struct.pack(">I", len(data))
|
|
168
|
+
+ body
|
|
169
|
+
+ struct.pack(">I", zlib.crc32(body) & 0xFFFFFFFF)
|
|
170
|
+
)
|
|
171
|
+
|
|
172
|
+
ihdr = struct.pack(">IIBBBBB", size, size, 8, 6, 0, 0, 0)
|
|
173
|
+
return (
|
|
174
|
+
b"\x89PNG\r\n\x1a\n"
|
|
175
|
+
+ chunk(b"IHDR", ihdr)
|
|
176
|
+
+ chunk(b"IDAT", zlib.compress(row * size, 9))
|
|
177
|
+
+ chunk(b"IEND", b"")
|
|
178
|
+
)
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
def _open(path: Path):
|
|
182
|
+
try:
|
|
183
|
+
validate_icon_source(path)
|
|
184
|
+
except IconSourceError as exc:
|
|
185
|
+
raise IconError(str(exc)) from exc
|
|
186
|
+
image_module = _pillow()
|
|
187
|
+
try:
|
|
188
|
+
return image_module.open(path).convert("RGBA")
|
|
189
|
+
except OSError as exc:
|
|
190
|
+
raise IconError(f"cannot read icon layer {path}: {exc}") from exc
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
def _fit(image, size: int):
|
|
194
|
+
from PIL import Image
|
|
195
|
+
|
|
196
|
+
return image.resize((size, size), Image.LANCZOS)
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
def _safe_zone_layer(image, size: int):
|
|
200
|
+
"""*image* scaled into the adaptive safe zone, centered on transparency."""
|
|
201
|
+
from PIL import Image
|
|
202
|
+
|
|
203
|
+
inner = max(1, round(size * SAFE_ZONE_RATIO))
|
|
204
|
+
layer = Image.new("RGBA", (size, size), (0, 0, 0, 0))
|
|
205
|
+
offset = (size - inner) // 2
|
|
206
|
+
layer.paste(_fit(image, inner), (offset, offset))
|
|
207
|
+
return layer
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
def _circular(image):
|
|
211
|
+
"""The legacy round-icon variant: *image* masked to a centered circle."""
|
|
212
|
+
from PIL import Image, ImageDraw
|
|
213
|
+
|
|
214
|
+
size = image.size[0]
|
|
215
|
+
mask = Image.new("L", (size, size), 0)
|
|
216
|
+
ImageDraw.Draw(mask).ellipse((0, 0, size - 1, size - 1), fill=255)
|
|
217
|
+
out = Image.new("RGBA", (size, size), (0, 0, 0, 0))
|
|
218
|
+
out.paste(image, (0, 0), mask)
|
|
219
|
+
return out
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
def _save(image, dest: Path) -> None:
|
|
223
|
+
image.save(dest, format="PNG")
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
def _pillow():
|
|
227
|
+
try:
|
|
228
|
+
from PIL import Image
|
|
229
|
+
except ModuleNotFoundError as exc:
|
|
230
|
+
raise IconError(
|
|
231
|
+
"generating the Android adaptive icon needs Pillow, which is not "
|
|
232
|
+
"installed.\n"
|
|
233
|
+
" Install the Android extra: pip install 'kivyforge[android]'\n"
|
|
234
|
+
" (or unset [tool.kivy.android.icons].source to build with the "
|
|
235
|
+
"default launcher icon)."
|
|
236
|
+
) from exc
|
|
237
|
+
return Image
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Android lock engine (android/02): per-ABI wheels + runtime + channels 3/4."""
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
"""Resolve declared ``.aar``/``.jar`` archives to lock pins (android/02, channel 3).
|
|
2
|
+
|
|
3
|
+
Each ``[tool.kivy.android.native.aars]`` / ``.jars`` entry has an explicit
|
|
4
|
+
``source`` — a direct URL or a repo-relative vendored path. ``kivyforge lock``
|
|
5
|
+
reads the artifact (download for a URL, local read for a path) and pins its
|
|
6
|
+
SHA-256 into ``[[tool.kivyforge.android_libs]]``. Mirrors the iOS xcframework
|
|
7
|
+
resolver's posture, minus slice enumeration (an archive is a single flat file).
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
import tempfile
|
|
13
|
+
from pathlib import Path
|
|
14
|
+
|
|
15
|
+
from kivyforge.artifacts.cache import ArtifactCache
|
|
16
|
+
from kivyforge.artifacts.download import Downloader, DownloadError, UrllibDownloader
|
|
17
|
+
from kivyforge.artifacts.verify import sha256_file
|
|
18
|
+
from kivyforge.config.model import AndroidArchiveDep
|
|
19
|
+
|
|
20
|
+
from .model import LockedAndroidLib
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class ArchiveResolverError(Exception):
|
|
24
|
+
pass
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def resolve_android_libs(
|
|
28
|
+
declared: tuple[AndroidArchiveDep, ...],
|
|
29
|
+
*,
|
|
30
|
+
project_root: Path,
|
|
31
|
+
downloader: Downloader | None = None,
|
|
32
|
+
cache: ArtifactCache | None = None,
|
|
33
|
+
offline: bool = False,
|
|
34
|
+
) -> list[LockedAndroidLib]:
|
|
35
|
+
"""Pin every declared archive; deterministic (name, version) order."""
|
|
36
|
+
out: list[LockedAndroidLib] = []
|
|
37
|
+
for dep in sorted(declared, key=lambda d: (d.name.lower(), d.version)):
|
|
38
|
+
out.append(
|
|
39
|
+
_resolve_one(
|
|
40
|
+
dep,
|
|
41
|
+
project_root=project_root,
|
|
42
|
+
downloader=downloader,
|
|
43
|
+
cache=cache,
|
|
44
|
+
offline=offline,
|
|
45
|
+
)
|
|
46
|
+
)
|
|
47
|
+
return out
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def _resolve_one(
|
|
51
|
+
dep: AndroidArchiveDep,
|
|
52
|
+
*,
|
|
53
|
+
project_root: Path,
|
|
54
|
+
downloader: Downloader | None,
|
|
55
|
+
cache: ArtifactCache | None,
|
|
56
|
+
offline: bool,
|
|
57
|
+
) -> LockedAndroidLib:
|
|
58
|
+
if dep.source.startswith(("http://", "https://")):
|
|
59
|
+
sha256 = _hash_remote(dep, downloader=downloader, cache=cache, offline=offline)
|
|
60
|
+
return LockedAndroidLib(
|
|
61
|
+
name=dep.name,
|
|
62
|
+
kind=dep.kind,
|
|
63
|
+
version=dep.version,
|
|
64
|
+
url=dep.source,
|
|
65
|
+
sha256=sha256,
|
|
66
|
+
)
|
|
67
|
+
local = (project_root / dep.source).resolve()
|
|
68
|
+
if not local.is_file():
|
|
69
|
+
raise ArchiveResolverError(
|
|
70
|
+
f"{dep.kind} {dep.name!r}: vendored source does not exist: "
|
|
71
|
+
f"{dep.source} (resolved to {local})"
|
|
72
|
+
)
|
|
73
|
+
return LockedAndroidLib(
|
|
74
|
+
name=dep.name,
|
|
75
|
+
kind=dep.kind,
|
|
76
|
+
version=dep.version,
|
|
77
|
+
path=dep.source,
|
|
78
|
+
sha256=sha256_file(local),
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def _hash_remote(
|
|
83
|
+
dep: AndroidArchiveDep,
|
|
84
|
+
*,
|
|
85
|
+
downloader: Downloader | None,
|
|
86
|
+
cache: ArtifactCache | None,
|
|
87
|
+
offline: bool,
|
|
88
|
+
) -> str:
|
|
89
|
+
filename = dep.source.rsplit("/", 1)[-1]
|
|
90
|
+
store = cache or ArtifactCache()
|
|
91
|
+
cached = store.find_by_filename(filename)
|
|
92
|
+
if cached is not None:
|
|
93
|
+
return sha256_file(cached)
|
|
94
|
+
if offline:
|
|
95
|
+
raise ArchiveResolverError(
|
|
96
|
+
f"{dep.kind} {dep.name!r} ({filename}) is not in the artifact cache "
|
|
97
|
+
f"and --offline was passed.\n"
|
|
98
|
+
f" Run `kivyforge lock` online once, then retry."
|
|
99
|
+
)
|
|
100
|
+
fetcher = downloader or UrllibDownloader()
|
|
101
|
+
with tempfile.TemporaryDirectory(prefix="kivyforge-lib-") as tmp:
|
|
102
|
+
dest = Path(tmp) / filename
|
|
103
|
+
try:
|
|
104
|
+
fetcher.fetch_to(dep.source, dest)
|
|
105
|
+
except DownloadError as exc:
|
|
106
|
+
raise ArchiveResolverError(
|
|
107
|
+
f"could not fetch {dep.kind} {dep.name!r} from {dep.source}: {exc}"
|
|
108
|
+
) from exc
|
|
109
|
+
return sha256_file(dest)
|