Skip to content

Commit e7e4279

Browse files
Put Python resources into a bundle inside a framework (#139)
* Put python resources into bundle * echo "$SERIOUS_PYTHON_SITE_PACKAGES" * Fix setting readme * iOS packaging improved with bundles * macOS to store site-packages in python.bundle, not app archive * Improved structure and reliability * Fix macOS test * Fix .origin path * site-packages-hash arg * Windows: include site-packages to an app directory, not app.zip * Fix Windows test * Copy site-packages to app for Linux * Fix Linux tests * Install packages to site-packages for all platforms * --skip-site-packages option * Rename --cleanup-packages-files -> --cleanup-package-files * --arch option to allow a list * Version bumped to 0.9.0, changelog updated * Try to fix Android test
1 parent 36ef98f commit e7e4279

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+535
-304
lines changed

.appveyor.yml

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
skip_branch_with_pr: true
22

33
environment:
4-
FLUTTER_VERSION: 3.24.5
4+
FLUTTER_VERSION: 3.27.4
55
GITHUB_TOKEN:
66
secure: 9SKIwc3VSfYJ5IChvNR74mEv2nb0ZFftUzn3sGRdXipXEfKSxY50DoodChHvlqZduQNhjg0oyLWAAa3n+iwWvVM2yI7Cgb14lFNClijz/kHI/PibnjDMNvLKaAygcfAc
77

@@ -59,6 +59,7 @@ for:
5959
build: off
6060

6161
test_script:
62+
- export SERIOUS_PYTHON_SITE_PACKAGES=$APPVEYOR_BUILD_FOLDER/site-packages
6263
- cd src/serious_python/example/flet_example
6364
- dart run serious_python:main package app/src -p Darwin -r flet,--pre
6465
- flutter test integration_test -d macos
@@ -149,6 +150,7 @@ for:
149150
build: off
150151

151152
test_script:
153+
- set SERIOUS_PYTHON_SITE_PACKAGES=%APPVEYOR_BUILD_FOLDER%\site-packages
152154
- cd src/serious_python/example/flet_example
153155
- dart run serious_python:main package app/src -p Windows -r flet,--pre
154156
- flutter test integration_test -d windows
@@ -169,6 +171,7 @@ for:
169171
build: off
170172

171173
test_script:
174+
- export SERIOUS_PYTHON_SITE_PACKAGES=$APPVEYOR_BUILD_FOLDER/site-packages
172175
- cd src/serious_python/example/flet_example
173176
- dart run serious_python:main package app/src -p Linux -r flet,--pre
174177
- xvfb-run flutter test integration_test -d linux
@@ -193,6 +196,7 @@ for:
193196
build: off
194197

195198
test_script:
199+
- export SERIOUS_PYTHON_SITE_PACKAGES=$APPVEYOR_BUILD_FOLDER/site-packages
196200
- cd src/serious_python/example/flet_example
197201
- dart run serious_python:main package app/src -p Linux -r flet,--pre
198202
- xvfb-run flutter test integration_test -d linux

src/serious_python/CHANGELOG.md

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,14 @@
1-
## 0.8.8
1+
## 0.9.0
22

33
* Set `MinimumOSVersion` to `13.0` for generated Python frameworks.
4+
* iOS and macOS packaging: Python system libraries are put into `python.bundle` to pass App Store verification.
5+
* On macOS, Windows, and Linux, application site packages are copied in an unpacked state to the application bundle to speed up the first launch.
46
* Pyodide 0.27.2
57
* Python 3.12.9
8+
* Packaging `--cleanup` option replaced with two separate `--cleanup-app` and `--cleanup-packages` options.
9+
* New packaging options `--cleanup-app-files` and `--cleanup-package-files` to specify a list of globs to exclude files and directories from app and site packages.
10+
* New packaging `--skip-site-packages` option to skip site packages installation for faster re-builds.
11+
* Packaging `--arch` option accepts a list now.
612

713
## 0.8.7
814

src/serious_python/bin/package_command.dart

+36-33
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ const pyodideLockFile = "pyodide-lock.json";
2020

2121
const buildPythonVersion = "3.12.9";
2222
const buildPythonReleaseDate = "20250205";
23-
const defaultSitePackagesDir = "__pypackages__";
2423
const sitePackagesEnvironmentVariable = "SERIOUS_PYTHON_SITE_PACKAGES";
2524
const flutterPackagesFlutterEnvironmentVariable =
2625
"SERIOUS_PYTHON_FLUTTER_PACKAGES";
@@ -100,9 +99,9 @@ class PackageCommand extends Command {
10099
allowed: ["iOS", "Android", "Pyodide", "Windows", "Linux", "Darwin"],
101100
mandatory: true,
102101
help: "Install dependencies for specific platform, e.g. 'Android'.");
103-
argParser.addOption('arch',
102+
argParser.addMultiOption('arch',
104103
help:
105-
"Install dependencies for specific architecture only. Leave empty to install all supported architectures.");
104+
"Install dependencies for specific architectures only. Leave empty to install all supported architectures.");
106105
argParser.addMultiOption('requirements',
107106
abbr: "r",
108107
help:
@@ -114,6 +113,8 @@ class PackageCommand extends Command {
114113
argParser.addMultiOption('exclude',
115114
help:
116115
"List of relative paths to exclude from app package, e.g. \"assets,build\".");
116+
argParser.addFlag("skip-site-packages",
117+
help: "Skip installation of site packages.", negatable: false);
117118
argParser.addFlag("compile-app",
118119
help: "Compile Python application before packaging.", negatable: false);
119120
argParser.addFlag("compile-packages",
@@ -131,7 +132,7 @@ class PackageCommand extends Command {
131132
argParser.addFlag("cleanup-packages",
132133
help: "Cleanup packages from unneccessary files and directories.",
133134
negatable: false);
134-
argParser.addMultiOption('cleanup-packages-files',
135+
argParser.addMultiOption('cleanup-package-files',
135136
help: "List of globs to delete extra packages files and directories.");
136137
argParser.addFlag("verbose", help: "Verbose output.", negatable: false);
137138
}
@@ -157,17 +158,18 @@ class PackageCommand extends Command {
157158
// args
158159
String? sourceDirPath = argResults!.rest.first;
159160
String platform = argResults?['platform'];
160-
String? archArg = argResults?['arch'];
161+
List<String> archArg = argResults?['arch'];
161162
List<String> requirements = argResults?['requirements'];
162163
String? assetPath = argResults?['asset'];
163164
List<String> exclude = argResults?['exclude'];
165+
bool skipSitePackages = argResults?["skip-site-packages"];
164166
bool compileApp = argResults?["compile-app"];
165167
bool compilePackages = argResults?["compile-packages"];
166168
bool cleanup = argResults?["cleanup"];
167169
bool cleanupApp = argResults?["cleanup-app"];
168170
List<String> cleanupAppFiles = argResults?['cleanup-app-files'];
169171
bool cleanupPackages = argResults?["cleanup-packages"];
170-
List<String> cleanupPackagesFiles = argResults?['cleanup-packages-files'];
172+
List<String> cleanupPackageFiles = argResults?['cleanup-package-files'];
171173
_verbose = argResults?["verbose"];
172174

173175
if (path.isRelative(sourceDirPath)) {
@@ -259,13 +261,29 @@ class PackageCommand extends Command {
259261
}
260262

261263
// install requirements
262-
if (requirements.isNotEmpty) {
264+
if (requirements.isNotEmpty && !skipSitePackages) {
263265
String? sitePackagesRoot;
264-
bool sitePackagesRootDeleted = false;
266+
267+
if (Platform.environment.containsKey(sitePackagesEnvironmentVariable)) {
268+
sitePackagesRoot =
269+
Platform.environment[sitePackagesEnvironmentVariable];
270+
}
271+
if (sitePackagesRoot == null || sitePackagesRoot.isEmpty) {
272+
sitePackagesRoot = path.join(currentPath, "build", "site-packages");
273+
}
274+
275+
if (await Directory(sitePackagesRoot).exists()) {
276+
await for (var f in Directory(sitePackagesRoot)
277+
.list()
278+
.where((f) => !path.basename(f.path).startsWith("."))) {
279+
await f.delete(recursive: true);
280+
}
281+
}
282+
265283
bool flutterPackagesCopied = false;
266284
// invoke pip for every platform arch
267285
for (var arch in platforms[platform]!.entries) {
268-
if (archArg != null && arch.key != archArg) {
286+
if (archArg.isNotEmpty && !archArg.contains(arch.key)) {
269287
continue;
270288
}
271289
String? sitePackagesDir;
@@ -300,28 +318,6 @@ class PackageCommand extends Command {
300318
[sitecustomizeDir.path].join(Platform.isWindows ? ";" : ":"),
301319
};
302320

303-
if (isMobile) {
304-
if (!Platform.environment
305-
.containsKey(sitePackagesEnvironmentVariable)) {
306-
throw "Environment variable is not set: $sitePackagesEnvironmentVariable";
307-
}
308-
sitePackagesRoot =
309-
Platform.environment[sitePackagesEnvironmentVariable];
310-
if (sitePackagesRoot!.isEmpty) {
311-
throw "Environment variable cannot be empty: $sitePackagesEnvironmentVariable";
312-
}
313-
} else {
314-
sitePackagesRoot =
315-
path.join(tempDir.path, defaultSitePackagesDir);
316-
}
317-
318-
if (!sitePackagesRootDeleted) {
319-
if (await Directory(sitePackagesRoot).exists()) {
320-
await Directory(sitePackagesRoot).delete(recursive: true);
321-
}
322-
sitePackagesRootDeleted = true;
323-
}
324-
325321
sitePackagesDir = arch.key.isNotEmpty
326322
? path.join(sitePackagesRoot, arch.key)
327323
: sitePackagesRoot;
@@ -394,7 +390,7 @@ class PackageCommand extends Command {
394390

395391
// cleanup packages
396392
if (cleanupPackages || cleanup) {
397-
var allJunkFiles = [...junkFiles, ...cleanupPackagesFiles];
393+
var allJunkFiles = [...junkFiles, ...cleanupPackageFiles];
398394
if (_verbose) {
399395
verbose(
400396
"Delete unnecessary package files and directories: $allJunkFiles");
@@ -414,11 +410,18 @@ class PackageCommand extends Command {
414410

415411
if (platform == "Darwin") {
416412
await macos_utils.mergeMacOsSitePackages(
417-
path.join(sitePackagesRoot!, "arm64"),
413+
path.join(sitePackagesRoot, "arm64"),
418414
path.join(sitePackagesRoot, "x86_64"),
419415
path.join(sitePackagesRoot),
420416
_verbose);
421417
}
418+
419+
// synchronize pod
420+
var syncSh =
421+
File(path.join(sitePackagesRoot, ".pod", "sync_site_packages.sh"));
422+
if (await syncSh.exists()) {
423+
await runExec("/bin/sh", [syncSh.path]);
424+
}
422425
}
423426

424427
// create archive

0 commit comments

Comments
 (0)