flet-cli 1.1.0.dev1__py3-none-any.whl → 1.1.0.dev2__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.
- flet_cli/__pyinstaller/__init__.py +1 -1
- flet_cli/__pyinstaller/config.py +14 -0
- flet_cli/__pyinstaller/extensions.py +177 -0
- flet_cli/__pyinstaller/hook-flet_desktop.py +3 -0
- flet_cli/__pyinstaller/macos_utils.py +18 -16
- flet_cli/__pyinstaller/utils.py +3 -2
- flet_cli/__pyinstaller/win_utils.py +33 -14
- flet_cli/commands/build.py +4 -3
- flet_cli/commands/build_base.py +341 -16
- flet_cli/commands/create.py +143 -11
- flet_cli/commands/debug.py +1 -0
- flet_cli/commands/flutter_base.py +4 -5
- flet_cli/commands/pack.py +82 -3
- flet_cli/commands/test.py +1 -0
- flet_cli/utils/android.py +329 -0
- flet_cli/utils/examples.py +275 -0
- flet_cli/utils/extension_settings.py +353 -0
- flet_cli/utils/project_dependencies.py +75 -0
- flet_cli/utils/python_versions.py +1 -1
- flet_cli/version.py +1 -1
- {flet_cli-1.1.0.dev1.dist-info → flet_cli-1.1.0.dev2.dist-info}/METADATA +3 -3
- {flet_cli-1.1.0.dev1.dist-info → flet_cli-1.1.0.dev2.dist-info}/RECORD +25 -21
- {flet_cli-1.1.0.dev1.dist-info → flet_cli-1.1.0.dev2.dist-info}/WHEEL +1 -1
- {flet_cli-1.1.0.dev1.dist-info → flet_cli-1.1.0.dev2.dist-info}/entry_points.txt +0 -0
- {flet_cli-1.1.0.dev1.dist-info → flet_cli-1.1.0.dev2.dist-info}/top_level.txt +0 -0
flet_cli/__pyinstaller/config.py
CHANGED
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import ast
|
|
2
|
+
import importlib.metadata
|
|
3
|
+
import re
|
|
4
|
+
import sys
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
from typing import Optional
|
|
8
|
+
|
|
9
|
+
_PACKAGE_URI = re.compile(rb"package:([a-z][a-z0-9_]*)/")
|
|
10
|
+
|
|
11
|
+
# Directories that hold no app code, skipped when looking for the app's imports.
|
|
12
|
+
_SKIPPED_DIRS = {"__pycache__", "build", "dist", "node_modules", "site-packages"}
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@dataclass
|
|
16
|
+
class InstalledExtension:
|
|
17
|
+
"""
|
|
18
|
+
A Flet extension installed in the current environment.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
package: str
|
|
22
|
+
"""
|
|
23
|
+
Name of the extension's Flutter package.
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
distribution: Optional[str]
|
|
27
|
+
"""
|
|
28
|
+
Name of the distribution that installed it, if known.
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
modules: set[str]
|
|
32
|
+
"""
|
|
33
|
+
Top-level Python modules the extension provides.
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def get_client_extensions(snapshot_path: str) -> Optional[set[str]]:
|
|
38
|
+
"""
|
|
39
|
+
Return the Flutter packages compiled into a prebuilt Flet client.
|
|
40
|
+
|
|
41
|
+
Release builds keep the `package:<name>/` URI of every Dart library in the
|
|
42
|
+
app's AOT snapshot: `data/app.so` on Windows, `lib/libapp.so` on Linux and
|
|
43
|
+
`Contents/Frameworks/App.framework/App` in a macOS app bundle.
|
|
44
|
+
|
|
45
|
+
Args:
|
|
46
|
+
snapshot_path: Path to the client's AOT snapshot.
|
|
47
|
+
|
|
48
|
+
Returns:
|
|
49
|
+
Names of the packages, or `None` when the snapshot is missing or names no
|
|
50
|
+
`flet` library, so the client's extensions can't be told.
|
|
51
|
+
"""
|
|
52
|
+
|
|
53
|
+
path = Path(snapshot_path)
|
|
54
|
+
if not path.is_file():
|
|
55
|
+
return None
|
|
56
|
+
packages = {m.decode() for m in _PACKAGE_URI.findall(path.read_bytes())}
|
|
57
|
+
return packages if "flet" in packages else None
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def find_installed_extensions() -> list[InstalledExtension]:
|
|
61
|
+
"""
|
|
62
|
+
Return the Flet extensions installed in the current environment.
|
|
63
|
+
|
|
64
|
+
An extension is a distribution that installs a `flutter/<package>/pubspec.yaml`
|
|
65
|
+
file. Editable installs list no such file in their `RECORD`, so a
|
|
66
|
+
`flutter/<package>` folder on `sys.path` that no distribution owns is reported
|
|
67
|
+
too when the same `sys.path` entry has a Python module named `<package>`.
|
|
68
|
+
"""
|
|
69
|
+
|
|
70
|
+
extensions: dict[str, InstalledExtension] = {}
|
|
71
|
+
for dist in importlib.metadata.distributions():
|
|
72
|
+
files = dist.files or []
|
|
73
|
+
packages = {
|
|
74
|
+
f.parts[1]
|
|
75
|
+
for f in files
|
|
76
|
+
if len(f.parts) == 3
|
|
77
|
+
and f.parts[0] == "flutter"
|
|
78
|
+
and f.parts[2] == "pubspec.yaml"
|
|
79
|
+
}
|
|
80
|
+
if not packages:
|
|
81
|
+
continue
|
|
82
|
+
modules = {
|
|
83
|
+
Path(f.parts[0]).stem
|
|
84
|
+
for f in files
|
|
85
|
+
if f.parts[0] not in ("flutter", "..", "__pycache__")
|
|
86
|
+
and not f.parts[0].endswith((".dist-info", ".data", ".pth"))
|
|
87
|
+
and (len(f.parts) > 1 or f.suffix == ".py")
|
|
88
|
+
}
|
|
89
|
+
for package in packages:
|
|
90
|
+
extensions.setdefault(
|
|
91
|
+
package,
|
|
92
|
+
InstalledExtension(package, dist.metadata["Name"], modules),
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
for entry in sys.path:
|
|
96
|
+
entry_dir = Path(entry or ".")
|
|
97
|
+
if not (entry_dir / "flutter").is_dir():
|
|
98
|
+
continue
|
|
99
|
+
for pubspec in sorted((entry_dir / "flutter").glob("*/pubspec.yaml")):
|
|
100
|
+
package = pubspec.parent.name
|
|
101
|
+
if (entry_dir / package).is_dir() or (
|
|
102
|
+
entry_dir / f"{package}.py"
|
|
103
|
+
).is_file():
|
|
104
|
+
extensions.setdefault(
|
|
105
|
+
package, InstalledExtension(package, None, {package})
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
return sorted(extensions.values(), key=lambda e: e.package)
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def find_imported_modules(app_dir: Path) -> set[str]:
|
|
112
|
+
"""
|
|
113
|
+
Return the top-level modules the app's Python files import.
|
|
114
|
+
|
|
115
|
+
Virtual environments, hidden folders, build output and symlinked folders in
|
|
116
|
+
`app_dir` are skipped, as are files that can't be read or don't parse.
|
|
117
|
+
|
|
118
|
+
Args:
|
|
119
|
+
app_dir: Directory of the app's main script.
|
|
120
|
+
"""
|
|
121
|
+
|
|
122
|
+
modules: set[str] = set()
|
|
123
|
+
for path in _iter_app_files(app_dir):
|
|
124
|
+
try:
|
|
125
|
+
tree = ast.parse(path.read_bytes(), filename=str(path))
|
|
126
|
+
except (OSError, SyntaxError, ValueError):
|
|
127
|
+
continue
|
|
128
|
+
for node in ast.walk(tree):
|
|
129
|
+
if isinstance(node, ast.Import):
|
|
130
|
+
modules.update(alias.name.split(".")[0] for alias in node.names)
|
|
131
|
+
elif isinstance(node, ast.ImportFrom) and node.module and not node.level:
|
|
132
|
+
modules.add(node.module.split(".")[0])
|
|
133
|
+
return modules
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
def find_missing_extensions(
|
|
137
|
+
app_dir: Path, client_extensions: set[str]
|
|
138
|
+
) -> list[InstalledExtension]:
|
|
139
|
+
"""
|
|
140
|
+
Return the installed extensions the app imports but the client lacks.
|
|
141
|
+
|
|
142
|
+
Args:
|
|
143
|
+
app_dir: Directory of the app's main script.
|
|
144
|
+
client_extensions: Flutter packages compiled into the client, as
|
|
145
|
+
returned by `get_client_extensions()`.
|
|
146
|
+
"""
|
|
147
|
+
|
|
148
|
+
candidates = [
|
|
149
|
+
e for e in find_installed_extensions() if e.package not in client_extensions
|
|
150
|
+
]
|
|
151
|
+
if not candidates:
|
|
152
|
+
return []
|
|
153
|
+
imported = find_imported_modules(app_dir)
|
|
154
|
+
return [e for e in candidates if e.modules & imported]
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
def _iter_app_files(directory: Path):
|
|
158
|
+
"""
|
|
159
|
+
Yield the Python files of an app folder, recursively.
|
|
160
|
+
"""
|
|
161
|
+
|
|
162
|
+
try:
|
|
163
|
+
paths = sorted(directory.iterdir())
|
|
164
|
+
except OSError:
|
|
165
|
+
return
|
|
166
|
+
for path in paths:
|
|
167
|
+
if path.is_dir():
|
|
168
|
+
if (
|
|
169
|
+
path.is_symlink()
|
|
170
|
+
or path.name.startswith(".")
|
|
171
|
+
or path.name in _SKIPPED_DIRS
|
|
172
|
+
or (path / "pyvenv.cfg").exists()
|
|
173
|
+
):
|
|
174
|
+
continue
|
|
175
|
+
yield from _iter_app_files(path)
|
|
176
|
+
elif path.suffix == ".py":
|
|
177
|
+
yield path
|
|
@@ -5,14 +5,16 @@ import shutil
|
|
|
5
5
|
import subprocess
|
|
6
6
|
import tarfile
|
|
7
7
|
from pathlib import Path
|
|
8
|
+
from typing import Any, Optional
|
|
8
9
|
|
|
9
10
|
from PyInstaller.building.icon import normalize_icon_type
|
|
10
11
|
|
|
12
|
+
import flet_cli.__pyinstaller.config as hook_config
|
|
11
13
|
from flet.utils import safe_tar_extractall
|
|
12
14
|
from flet_cli.__pyinstaller.utils import normalize_tar_entry
|
|
13
15
|
|
|
14
16
|
|
|
15
|
-
def unpack_app_bundle(tar_path):
|
|
17
|
+
def unpack_app_bundle(tar_path: str) -> str:
|
|
16
18
|
"""
|
|
17
19
|
Extract a macOS app bundle archive and remove the source tarball.
|
|
18
20
|
|
|
@@ -32,7 +34,7 @@ def unpack_app_bundle(tar_path):
|
|
|
32
34
|
return os.path.join(bin_dir, "Flet.app")
|
|
33
35
|
|
|
34
36
|
|
|
35
|
-
def update_flet_view_icon(app_path, icon_path):
|
|
37
|
+
def update_flet_view_icon(app_path: str, icon_path: str) -> None:
|
|
36
38
|
"""
|
|
37
39
|
Replace app icon in a macOS app bundle and update Info.plist metadata.
|
|
38
40
|
|
|
@@ -41,7 +43,7 @@ def update_flet_view_icon(app_path, icon_path):
|
|
|
41
43
|
icon_path: Path to source icon file.
|
|
42
44
|
"""
|
|
43
45
|
|
|
44
|
-
|
|
46
|
+
hook_config.log_progress("Updating Flet View icon", app_path, icon_path)
|
|
45
47
|
|
|
46
48
|
icon_file = "AppIcon.icns"
|
|
47
49
|
|
|
@@ -51,7 +53,7 @@ def update_flet_view_icon(app_path, icon_path):
|
|
|
51
53
|
)
|
|
52
54
|
|
|
53
55
|
# patch icon
|
|
54
|
-
|
|
56
|
+
hook_config.log_progress("Copying icons from", normalized_icon_path)
|
|
55
57
|
shutil.copy(
|
|
56
58
|
normalized_icon_path,
|
|
57
59
|
os.path.join(app_path, "Contents", "Resources", icon_file),
|
|
@@ -65,12 +67,12 @@ def update_flet_view_icon(app_path, icon_path):
|
|
|
65
67
|
|
|
66
68
|
|
|
67
69
|
def update_flet_view_version_info(
|
|
68
|
-
app_path,
|
|
69
|
-
bundle_id,
|
|
70
|
-
product_name,
|
|
71
|
-
product_version,
|
|
72
|
-
copyright,
|
|
73
|
-
):
|
|
70
|
+
app_path: str,
|
|
71
|
+
bundle_id: Optional[str],
|
|
72
|
+
product_name: Optional[str],
|
|
73
|
+
product_version: Optional[str],
|
|
74
|
+
copyright: Optional[str],
|
|
75
|
+
) -> str:
|
|
74
76
|
"""
|
|
75
77
|
Update selected Info.plist metadata fields in a macOS app bundle.
|
|
76
78
|
|
|
@@ -85,7 +87,7 @@ def update_flet_view_version_info(
|
|
|
85
87
|
Final app bundle path (may change when app bundle is renamed).
|
|
86
88
|
"""
|
|
87
89
|
|
|
88
|
-
|
|
90
|
+
hook_config.log_progress("Updating Flet View plist", app_path)
|
|
89
91
|
|
|
90
92
|
pl = __load_info_plist(app_path)
|
|
91
93
|
|
|
@@ -109,7 +111,7 @@ def update_flet_view_version_info(
|
|
|
109
111
|
return app_path
|
|
110
112
|
|
|
111
113
|
|
|
112
|
-
def assemble_app_bundle(app_path, tar_path):
|
|
114
|
+
def assemble_app_bundle(app_path: str, tar_path: str) -> None:
|
|
113
115
|
"""
|
|
114
116
|
Code-sign a macOS app bundle, package it as tar.gz, and remove unpacked bundle.
|
|
115
117
|
|
|
@@ -122,7 +124,7 @@ def assemble_app_bundle(app_path, tar_path):
|
|
|
122
124
|
"""
|
|
123
125
|
|
|
124
126
|
# sign app bundle
|
|
125
|
-
|
|
127
|
+
hook_config.log_progress(f"Signing file {app_path}")
|
|
126
128
|
cmd_args = [
|
|
127
129
|
"codesign",
|
|
128
130
|
"-s",
|
|
@@ -162,7 +164,7 @@ def assemble_app_bundle(app_path, tar_path):
|
|
|
162
164
|
shutil.rmtree(app_path, ignore_errors=True)
|
|
163
165
|
|
|
164
166
|
|
|
165
|
-
def __load_info_plist(app_path):
|
|
167
|
+
def __load_info_plist(app_path: str) -> dict[str, Any]:
|
|
166
168
|
"""
|
|
167
169
|
Load Info.plist content from a macOS app bundle.
|
|
168
170
|
"""
|
|
@@ -171,7 +173,7 @@ def __load_info_plist(app_path):
|
|
|
171
173
|
return plistlib.load(fp)
|
|
172
174
|
|
|
173
175
|
|
|
174
|
-
def __save_info_plist(app_path, pl):
|
|
176
|
+
def __save_info_plist(app_path: str, pl: dict[str, Any]) -> None:
|
|
175
177
|
"""
|
|
176
178
|
Save Info.plist content to a macOS app bundle.
|
|
177
179
|
|
|
@@ -184,7 +186,7 @@ def __save_info_plist(app_path, pl):
|
|
|
184
186
|
plistlib.dump(pl, fp)
|
|
185
187
|
|
|
186
188
|
|
|
187
|
-
def __get_plist_path(app_path):
|
|
189
|
+
def __get_plist_path(app_path: str) -> str:
|
|
188
190
|
"""
|
|
189
191
|
Return path to `Info.plist` inside a macOS app bundle.
|
|
190
192
|
"""
|
flet_cli/__pyinstaller/utils.py
CHANGED
|
@@ -3,12 +3,13 @@ import tarfile
|
|
|
3
3
|
import tempfile
|
|
4
4
|
import uuid
|
|
5
5
|
from pathlib import Path
|
|
6
|
+
from typing import Optional
|
|
6
7
|
|
|
7
8
|
from flet.utils import copy_tree
|
|
8
9
|
from flet_desktop import ensure_client_cached
|
|
9
10
|
|
|
10
11
|
|
|
11
|
-
def get_flet_bin_path():
|
|
12
|
+
def get_flet_bin_path() -> Optional[str]:
|
|
12
13
|
"""
|
|
13
14
|
Return path to Flet desktop binaries, if available.
|
|
14
15
|
|
|
@@ -52,7 +53,7 @@ def normalize_tar_entry(tarinfo: tarfile.TarInfo) -> tarfile.TarInfo:
|
|
|
52
53
|
return tarinfo
|
|
53
54
|
|
|
54
55
|
|
|
55
|
-
def copy_flet_bin():
|
|
56
|
+
def copy_flet_bin() -> Optional[str]:
|
|
56
57
|
"""
|
|
57
58
|
Copy packaged Flet desktop binaries into a temporary directory.
|
|
58
59
|
|
|
@@ -1,26 +1,34 @@
|
|
|
1
1
|
import os
|
|
2
|
+
import shutil
|
|
2
3
|
import tempfile
|
|
3
4
|
import uuid
|
|
4
5
|
from pathlib import Path
|
|
6
|
+
from typing import Optional
|
|
5
7
|
|
|
6
8
|
import pefile
|
|
7
9
|
from packaging import version
|
|
8
|
-
from PyInstaller.building.icon import normalize_icon_type
|
|
9
10
|
from PyInstaller.compat import win32api
|
|
10
11
|
from PyInstaller.utils.win32 import versioninfo
|
|
11
12
|
from PyInstaller.utils.win32.icon import IconFile, normalize_icon_type
|
|
12
13
|
|
|
14
|
+
import flet_cli.__pyinstaller.config as hook_config
|
|
13
15
|
|
|
14
|
-
|
|
16
|
+
|
|
17
|
+
def update_flet_view_icon(exe_path: str, icon_path: str) -> None:
|
|
15
18
|
"""
|
|
16
19
|
Replace icon resources in a Windows executable.
|
|
17
20
|
|
|
21
|
+
When the icon is an `.ico` file, or an image converted to one, it is also
|
|
22
|
+
written to `data/app_icon.ico` next to the executable: Windows shows the icon
|
|
23
|
+
of an app without package identity on its notifications from an image file,
|
|
24
|
+
not from the executable's resources.
|
|
25
|
+
|
|
18
26
|
Args:
|
|
19
27
|
exe_path: Path to target executable file.
|
|
20
28
|
icon_path: Path to source icon file or executable resource.
|
|
21
29
|
"""
|
|
22
30
|
|
|
23
|
-
|
|
31
|
+
hook_config.log_progress("Updating Flet View icon", exe_path, icon_path)
|
|
24
32
|
|
|
25
33
|
RT_ICON = 3
|
|
26
34
|
RT_GROUP_ICON = 14
|
|
@@ -29,7 +37,7 @@ def update_flet_view_icon(exe_path, icon_path):
|
|
|
29
37
|
icon_path, ("exe", "ico"), "ico", os.getcwd()
|
|
30
38
|
)
|
|
31
39
|
icon = IconFile(normalized_icon_path)
|
|
32
|
-
|
|
40
|
+
hook_config.log_progress("Copying icons from", normalized_icon_path)
|
|
33
41
|
|
|
34
42
|
hdst = win32api.BeginUpdateResource(exe_path, 0)
|
|
35
43
|
|
|
@@ -40,23 +48,34 @@ def update_flet_view_icon(exe_path, icon_path):
|
|
|
40
48
|
data = icon.grp_icon_dir()
|
|
41
49
|
data = data + icon.grp_icondir_entries(iconid)
|
|
42
50
|
win32api.UpdateResource(hdst, RT_GROUP_ICON, i, data, 1033)
|
|
43
|
-
|
|
51
|
+
hook_config.log_progress(
|
|
52
|
+
f"Writing RT_GROUP_ICON {i} resource with {len(data)} bytes"
|
|
53
|
+
)
|
|
44
54
|
for data in icon.images:
|
|
45
55
|
win32api.UpdateResource(hdst, RT_ICON, iconid, data, 1033)
|
|
46
|
-
|
|
56
|
+
hook_config.log_progress(
|
|
57
|
+
f"Writing RT_ICON {iconid} resource with {len(data)} bytes"
|
|
58
|
+
)
|
|
47
59
|
iconid = iconid + 1
|
|
48
60
|
|
|
49
61
|
win32api.EndUpdateResource(hdst, 0)
|
|
50
62
|
|
|
63
|
+
# Copy the icon only when normalize_icon_type() produced an .ico file.
|
|
64
|
+
if Path(normalized_icon_path).suffix.lower() == ".ico":
|
|
65
|
+
icon_file = Path(exe_path).parent / "data" / "app_icon.ico"
|
|
66
|
+
icon_file.parent.mkdir(parents=True, exist_ok=True)
|
|
67
|
+
shutil.copyfile(normalized_icon_path, icon_file)
|
|
68
|
+
hook_config.log_progress("Writing", icon_file)
|
|
69
|
+
|
|
51
70
|
|
|
52
71
|
def update_flet_view_version_info(
|
|
53
|
-
exe_path,
|
|
54
|
-
product_name,
|
|
55
|
-
file_description,
|
|
56
|
-
product_version,
|
|
57
|
-
file_version,
|
|
58
|
-
company_name,
|
|
59
|
-
copyright,
|
|
72
|
+
exe_path: str,
|
|
73
|
+
product_name: Optional[str],
|
|
74
|
+
file_description: Optional[str],
|
|
75
|
+
product_version: Optional[str],
|
|
76
|
+
file_version: Optional[str],
|
|
77
|
+
company_name: Optional[str],
|
|
78
|
+
copyright: Optional[str],
|
|
60
79
|
) -> str:
|
|
61
80
|
"""
|
|
62
81
|
Update VERSIONINFO resources in a Windows executable.
|
|
@@ -74,7 +93,7 @@ def update_flet_view_version_info(
|
|
|
74
93
|
Path to a temporary text file containing serialized version info.
|
|
75
94
|
"""
|
|
76
95
|
|
|
77
|
-
|
|
96
|
+
hook_config.log_progress("Updating Flet View version info", exe_path)
|
|
78
97
|
|
|
79
98
|
# load versioninfo from exe
|
|
80
99
|
if versioninfo.read_version_info_from_executable:
|
flet_cli/commands/build.py
CHANGED
|
@@ -109,6 +109,7 @@ class Command(BaseBuildCommand):
|
|
|
109
109
|
self.update_flutter_dependencies()
|
|
110
110
|
self.customize_icons()
|
|
111
111
|
self.customize_splash_images()
|
|
112
|
+
self.copy_android_resources()
|
|
112
113
|
self.run_flutter()
|
|
113
114
|
self.copy_build_output()
|
|
114
115
|
if self.target_platform == "macos":
|
|
@@ -178,14 +179,14 @@ class Command(BaseBuildCommand):
|
|
|
178
179
|
|
|
179
180
|
if (
|
|
180
181
|
self.target_platform in ("apk", "aab")
|
|
181
|
-
and self.template_data["
|
|
182
|
+
and self.template_data["_options"]["target_arch"]
|
|
182
183
|
):
|
|
183
184
|
args.extend(
|
|
184
185
|
[
|
|
185
186
|
"--target-platform",
|
|
186
187
|
",".join(
|
|
187
188
|
flutter_target_platforms(
|
|
188
|
-
self.template_data["
|
|
189
|
+
self.template_data["_options"]["target_arch"]
|
|
189
190
|
)
|
|
190
191
|
),
|
|
191
192
|
]
|
|
@@ -575,7 +576,7 @@ class Command(BaseBuildCommand):
|
|
|
575
576
|
# The authoritative check reads the built app's Info.plist; this
|
|
576
577
|
# one catches the common case — the key not configured at all —
|
|
577
578
|
# before the build.
|
|
578
|
-
if not self.template_data["
|
|
579
|
+
if not self.template_data["_options"]["info_plist"].get(
|
|
579
580
|
"LSApplicationCategoryType"
|
|
580
581
|
):
|
|
581
582
|
self.cleanup(
|