flet-cli 0.86.2__tar.gz → 0.86.4__tar.gz
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-0.86.2 → flet_cli-0.86.4}/PKG-INFO +2 -2
- {flet_cli-0.86.2 → flet_cli-0.86.4}/pyproject.toml +2 -2
- {flet_cli-0.86.2 → flet_cli-0.86.4}/src/flet_cli/cli.py +86 -24
- {flet_cli-0.86.2 → flet_cli-0.86.4}/src/flet_cli/commands/build_base.py +69 -17
- {flet_cli-0.86.2 → flet_cli-0.86.4}/src/flet_cli/commands/run.py +12 -1
- {flet_cli-0.86.2 → flet_cli-0.86.4}/src/flet_cli/utils/python_versions.py +1 -1
- flet_cli-0.86.4/src/flet_cli/version.py +1 -0
- {flet_cli-0.86.2 → flet_cli-0.86.4}/src/flet_cli.egg-info/PKG-INFO +2 -2
- {flet_cli-0.86.2 → flet_cli-0.86.4}/src/flet_cli.egg-info/SOURCES.txt +3 -1
- {flet_cli-0.86.2 → flet_cli-0.86.4}/src/flet_cli.egg-info/requires.txt +1 -1
- flet_cli-0.86.4/tests/test_find_platform_image.py +67 -0
- flet_cli-0.86.4/tests/test_run_script_args.py +103 -0
- flet_cli-0.86.2/src/flet_cli/version.py +0 -1
- {flet_cli-0.86.2 → flet_cli-0.86.4}/README.md +0 -0
- {flet_cli-0.86.2 → flet_cli-0.86.4}/setup.cfg +0 -0
- {flet_cli-0.86.2 → flet_cli-0.86.4}/src/flet_cli/__pyinstaller/__init__.py +0 -0
- {flet_cli-0.86.2 → flet_cli-0.86.4}/src/flet_cli/__pyinstaller/config.py +0 -0
- {flet_cli-0.86.2 → flet_cli-0.86.4}/src/flet_cli/__pyinstaller/hook-flet.py +0 -0
- {flet_cli-0.86.2 → flet_cli-0.86.4}/src/flet_cli/__pyinstaller/macos_utils.py +0 -0
- {flet_cli-0.86.2 → flet_cli-0.86.4}/src/flet_cli/__pyinstaller/rthooks/pyi_rth_localhost_fletd.py +0 -0
- {flet_cli-0.86.2 → flet_cli-0.86.4}/src/flet_cli/__pyinstaller/utils.py +0 -0
- {flet_cli-0.86.2 → flet_cli-0.86.4}/src/flet_cli/__pyinstaller/win_utils.py +0 -0
- {flet_cli-0.86.2 → flet_cli-0.86.4}/src/flet_cli/commands/base.py +0 -0
- {flet_cli-0.86.2 → flet_cli-0.86.4}/src/flet_cli/commands/build.py +0 -0
- {flet_cli-0.86.2 → flet_cli-0.86.4}/src/flet_cli/commands/clean.py +0 -0
- {flet_cli-0.86.2 → flet_cli-0.86.4}/src/flet_cli/commands/create.py +0 -0
- {flet_cli-0.86.2 → flet_cli-0.86.4}/src/flet_cli/commands/debug.py +0 -0
- {flet_cli-0.86.2 → flet_cli-0.86.4}/src/flet_cli/commands/devices.py +0 -0
- {flet_cli-0.86.2 → flet_cli-0.86.4}/src/flet_cli/commands/doctor.py +0 -0
- {flet_cli-0.86.2 → flet_cli-0.86.4}/src/flet_cli/commands/emulators.py +0 -0
- {flet_cli-0.86.2 → flet_cli-0.86.4}/src/flet_cli/commands/flutter_base.py +0 -0
- {flet_cli-0.86.2 → flet_cli-0.86.4}/src/flet_cli/commands/mcp.py +0 -0
- {flet_cli-0.86.2 → flet_cli-0.86.4}/src/flet_cli/commands/options.py +0 -0
- {flet_cli-0.86.2 → flet_cli-0.86.4}/src/flet_cli/commands/pack.py +0 -0
- {flet_cli-0.86.2 → flet_cli-0.86.4}/src/flet_cli/commands/publish.py +0 -0
- {flet_cli-0.86.2 → flet_cli-0.86.4}/src/flet_cli/commands/serve.py +0 -0
- {flet_cli-0.86.2 → flet_cli-0.86.4}/src/flet_cli/commands/test.py +0 -0
- {flet_cli-0.86.2 → flet_cli-0.86.4}/src/flet_cli/commands/test_host.py +0 -0
- {flet_cli-0.86.2 → flet_cli-0.86.4}/src/flet_cli/utils/android.py +0 -0
- {flet_cli-0.86.2 → flet_cli-0.86.4}/src/flet_cli/utils/android_sdk.py +0 -0
- {flet_cli-0.86.2 → flet_cli-0.86.4}/src/flet_cli/utils/cli.py +0 -0
- {flet_cli-0.86.2 → flet_cli-0.86.4}/src/flet_cli/utils/distros.py +0 -0
- {flet_cli-0.86.2 → flet_cli-0.86.4}/src/flet_cli/utils/flutter.py +0 -0
- {flet_cli-0.86.2 → flet_cli-0.86.4}/src/flet_cli/utils/hash_stamp.py +0 -0
- {flet_cli-0.86.2 → flet_cli-0.86.4}/src/flet_cli/utils/jdk.py +0 -0
- {flet_cli-0.86.2 → flet_cli-0.86.4}/src/flet_cli/utils/linux_deps.py +0 -0
- {flet_cli-0.86.2 → flet_cli-0.86.4}/src/flet_cli/utils/merge.py +0 -0
- {flet_cli-0.86.2 → flet_cli-0.86.4}/src/flet_cli/utils/plist.py +0 -0
- {flet_cli-0.86.2 → flet_cli-0.86.4}/src/flet_cli/utils/processes.py +0 -0
- {flet_cli-0.86.2 → flet_cli-0.86.4}/src/flet_cli/utils/project_dependencies.py +0 -0
- {flet_cli-0.86.2 → flet_cli-0.86.4}/src/flet_cli/utils/pyodide.py +0 -0
- {flet_cli-0.86.2 → flet_cli-0.86.4}/src/flet_cli/utils/pyproject_toml.py +0 -0
- {flet_cli-0.86.2 → flet_cli-0.86.4}/src/flet_cli/utils/template_cache.py +0 -0
- {flet_cli-0.86.2 → flet_cli-0.86.4}/src/flet_cli.egg-info/dependency_links.txt +0 -0
- {flet_cli-0.86.2 → flet_cli-0.86.4}/src/flet_cli.egg-info/entry_points.txt +0 -0
- {flet_cli-0.86.2 → flet_cli-0.86.4}/src/flet_cli.egg-info/top_level.txt +0 -0
- {flet_cli-0.86.2 → flet_cli-0.86.4}/tests/test_clean.py +0 -0
- {flet_cli-0.86.2 → flet_cli-0.86.4}/tests/test_plist.py +0 -0
- {flet_cli-0.86.2 → flet_cli-0.86.4}/tests/test_project_dependencies.py +0 -0
- {flet_cli-0.86.2 → flet_cli-0.86.4}/tests/test_python_versions.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: flet-cli
|
|
3
|
-
Version: 0.86.
|
|
3
|
+
Version: 0.86.4
|
|
4
4
|
Summary: Flet CLI
|
|
5
5
|
Author-email: "Appveyor Systems Inc." <hello@flet.dev>
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -9,7 +9,7 @@ Project-URL: Repository, https://github.com/flet-dev/flet
|
|
|
9
9
|
Project-URL: Documentation, https://flet.dev/docs
|
|
10
10
|
Requires-Python: >=3.10
|
|
11
11
|
Description-Content-Type: text/markdown
|
|
12
|
-
Requires-Dist: flet==0.86.
|
|
12
|
+
Requires-Dist: flet==0.86.4
|
|
13
13
|
Requires-Dist: watchdog>=4.0.0
|
|
14
14
|
Requires-Dist: packaging>=25.0
|
|
15
15
|
Requires-Dist: qrcode>=7.4.2
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "flet-cli"
|
|
3
|
-
version = "0.86.
|
|
3
|
+
version = "0.86.4"
|
|
4
4
|
description = "Flet CLI"
|
|
5
5
|
authors = [{ name = "Appveyor Systems Inc.", email = "hello@flet.dev" }]
|
|
6
6
|
license = "Apache-2.0"
|
|
7
7
|
readme = "README.md"
|
|
8
8
|
requires-python = ">=3.10"
|
|
9
9
|
dependencies = [
|
|
10
|
-
"flet==0.86.
|
|
10
|
+
"flet==0.86.4",
|
|
11
11
|
"watchdog >=4.0.0",
|
|
12
12
|
"packaging >=25.0",
|
|
13
13
|
"qrcode >=7.4.2",
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import argparse
|
|
2
2
|
import json
|
|
3
3
|
import sys
|
|
4
|
+
from typing import Optional
|
|
4
5
|
|
|
5
6
|
import flet.version
|
|
6
7
|
import flet_cli.commands.build
|
|
@@ -41,23 +42,25 @@ def _render_version(as_json: bool) -> str:
|
|
|
41
42
|
|
|
42
43
|
# Source https://stackoverflow.com/a/26379693
|
|
43
44
|
def set_default_subparser(
|
|
44
|
-
parser: argparse.ArgumentParser, name: str, args: list
|
|
45
|
-
):
|
|
45
|
+
parser: argparse.ArgumentParser, name: str, args: list
|
|
46
|
+
) -> list:
|
|
46
47
|
"""
|
|
47
|
-
|
|
48
|
+
Prepend a default subparser name when the command line doesn't name one.
|
|
48
49
|
This should be called after setting up the argument parser but before
|
|
49
50
|
`parse_args()`.
|
|
50
51
|
|
|
51
52
|
Args:
|
|
53
|
+
parser: The root argument parser.
|
|
52
54
|
name: The name of the default subparser to use.
|
|
53
|
-
args:
|
|
54
|
-
|
|
55
|
-
|
|
55
|
+
args: The command-line arguments, without the program name.
|
|
56
|
+
|
|
57
|
+
Returns:
|
|
58
|
+
`args`, with the default subparser name prepended when applicable.
|
|
56
59
|
"""
|
|
57
60
|
|
|
58
|
-
# exit if help or version flags are present
|
|
59
|
-
if any(flag in
|
|
60
|
-
return
|
|
61
|
+
# exit if no arguments, or help or version flags are present
|
|
62
|
+
if not args or any(flag in args for flag in {"-h", "--help", "-V", "--version"}):
|
|
63
|
+
return args
|
|
61
64
|
|
|
62
65
|
# all subparser actions
|
|
63
66
|
subparser_actions = [
|
|
@@ -72,19 +75,14 @@ def set_default_subparser(
|
|
|
72
75
|
]
|
|
73
76
|
|
|
74
77
|
# if an existing subparser is provided, skip setting a default
|
|
75
|
-
if any(arg in subparser_names for arg in
|
|
76
|
-
return
|
|
78
|
+
if any(arg in subparser_names for arg in args):
|
|
79
|
+
return args
|
|
77
80
|
|
|
78
81
|
# if the default subparser doesn't exist, register it in the first subparser action
|
|
79
82
|
if (name not in subparser_names) and subparser_actions:
|
|
80
83
|
subparser_actions[0].add_parser(name)
|
|
81
84
|
|
|
82
|
-
|
|
83
|
-
if args is None:
|
|
84
|
-
if len(sys.argv) > 1:
|
|
85
|
-
sys.argv.insert(index, name)
|
|
86
|
-
else:
|
|
87
|
-
args.insert(index, name)
|
|
85
|
+
return [name, *args]
|
|
88
86
|
|
|
89
87
|
|
|
90
88
|
def get_parser() -> argparse.ArgumentParser:
|
|
@@ -132,22 +130,86 @@ def get_parser() -> argparse.ArgumentParser:
|
|
|
132
130
|
except ImportError:
|
|
133
131
|
pass
|
|
134
132
|
|
|
135
|
-
# set "run" as the default subparser
|
|
136
|
-
set_default_subparser(parser, name="run", index=1)
|
|
137
|
-
|
|
138
133
|
return parser
|
|
139
134
|
|
|
140
135
|
|
|
141
|
-
def
|
|
136
|
+
def split_script_args(argv: list) -> tuple[list, Optional[list]]:
|
|
137
|
+
"""
|
|
138
|
+
Split a command line at the first bare `--` separator.
|
|
139
|
+
|
|
140
|
+
Everything after the separator is meant for the app script, not for Flet
|
|
141
|
+
itself, so it must be removed before the parser (and `set_default_subparser`)
|
|
142
|
+
sees it - otherwise `flet run app.py -- --web` would be read as Flet's own
|
|
143
|
+
`--web` option, and `flet app.py -- build` would suppress the default `run`
|
|
144
|
+
subcommand.
|
|
145
|
+
|
|
146
|
+
Args:
|
|
147
|
+
argv: Command-line arguments, without the program name.
|
|
148
|
+
|
|
149
|
+
Returns:
|
|
150
|
+
A `(argv, script_args)` tuple, where `script_args` is `None` when no
|
|
151
|
+
`--` separator is present.
|
|
152
|
+
"""
|
|
153
|
+
try:
|
|
154
|
+
index = argv.index("--")
|
|
155
|
+
except ValueError:
|
|
156
|
+
return argv, None
|
|
157
|
+
return argv[:index], argv[index + 1 :]
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def parse_command_line(argv: list) -> argparse.Namespace:
|
|
161
|
+
"""
|
|
162
|
+
Parse a Flet command line into the namespace passed to a command handler.
|
|
163
|
+
|
|
164
|
+
Exits the process with a usage message when the command line is invalid.
|
|
165
|
+
|
|
166
|
+
Args:
|
|
167
|
+
argv: Command-line arguments, without the program name.
|
|
168
|
+
|
|
169
|
+
Returns:
|
|
170
|
+
The parsed arguments. For `flet run`, `script_args` holds the arguments
|
|
171
|
+
to forward to the app script.
|
|
172
|
+
"""
|
|
173
|
+
|
|
174
|
+
# pull off the arguments meant for the app script before the parser sees them
|
|
175
|
+
argv, script_args = split_script_args(argv)
|
|
176
|
+
|
|
142
177
|
parser = get_parser()
|
|
143
178
|
|
|
179
|
+
# "run" is the default subcommand
|
|
180
|
+
argv = set_default_subparser(parser, name="run", args=argv)
|
|
181
|
+
|
|
182
|
+
args, unrecognized = parser.parse_known_args(argv)
|
|
183
|
+
|
|
184
|
+
if unrecognized:
|
|
185
|
+
message = f"unrecognized arguments: {' '.join(unrecognized)}"
|
|
186
|
+
if getattr(args, "command", None) == "run":
|
|
187
|
+
message += (
|
|
188
|
+
"\nIf these are arguments for your app script, put them after "
|
|
189
|
+
"a `--` separator, e.g. "
|
|
190
|
+
f"`flet run {args.script} -- {' '.join(unrecognized)}`"
|
|
191
|
+
)
|
|
192
|
+
parser.error(message)
|
|
193
|
+
|
|
194
|
+
# forward the arguments that followed `--` to the app script
|
|
195
|
+
if script_args is not None:
|
|
196
|
+
if getattr(args, "command", None) != "run":
|
|
197
|
+
parser.error(
|
|
198
|
+
"the `--` separator is only supported by `flet run`, to pass "
|
|
199
|
+
"the arguments that follow it to your app script"
|
|
200
|
+
)
|
|
201
|
+
args.script_args = list(args.script_args) + script_args
|
|
202
|
+
|
|
203
|
+
return args
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
def main():
|
|
144
207
|
# print usage/help if called without arguments
|
|
145
208
|
if len(sys.argv) == 1:
|
|
146
|
-
|
|
209
|
+
get_parser().print_help(sys.stdout)
|
|
147
210
|
sys.exit(1)
|
|
148
211
|
|
|
149
|
-
|
|
150
|
-
args = parser.parse_args()
|
|
212
|
+
args = parse_command_line(sys.argv[1:])
|
|
151
213
|
|
|
152
214
|
# handle `flet --version [--json]` (no subcommand/handler is set)
|
|
153
215
|
if getattr(args, "version", False):
|
|
@@ -2290,6 +2290,13 @@ class BaseBuildCommand(BaseFlutterCommand):
|
|
|
2290
2290
|
# app here (no app.zip on native); the platform native build copies
|
|
2291
2291
|
# it into the bundle (Android zips it as a stored asset).
|
|
2292
2292
|
package_env["SERIOUS_PYTHON_APP"] = str(self.build_dir / "python-app")
|
|
2293
|
+
# app bundle id: serious_python (>= 4.4.2) namespaces the generated
|
|
2294
|
+
# iOS framework bundle identifiers under it. Without it they keep a
|
|
2295
|
+
# shared `org.python.*` default that is byte-identical in every Flet
|
|
2296
|
+
# app — see flet-dev/flet#6724.
|
|
2297
|
+
bundle_id = (self.template_data or {}).get("bundle_id")
|
|
2298
|
+
if bundle_id:
|
|
2299
|
+
package_env["SERIOUS_PYTHON_BUNDLE_ID"] = bundle_id
|
|
2293
2300
|
|
|
2294
2301
|
# Swift Package Manager (darwin): tell serious_python's package command to
|
|
2295
2302
|
# do the host-side SPM staging (the podspec prepare_command doesn't run
|
|
@@ -2565,6 +2572,15 @@ class BaseBuildCommand(BaseFlutterCommand):
|
|
|
2565
2572
|
# into the bundle.
|
|
2566
2573
|
env["SERIOUS_PYTHON_APP"] = str(build_dir / "python-app")
|
|
2567
2574
|
|
|
2575
|
+
# app bundle id: the CocoaPods `prepare_command` re-runs the darwin sync
|
|
2576
|
+
# at `flutter build` time, so it needs the same value the package step
|
|
2577
|
+
# got or the framework identifiers fall back to `org.python.*`. Read
|
|
2578
|
+
# defensively — this method is documented as safe to call before the
|
|
2579
|
+
# pipeline has populated every attribute.
|
|
2580
|
+
bundle_id = (getattr(self, "template_data", None) or {}).get("bundle_id")
|
|
2581
|
+
if bundle_id:
|
|
2582
|
+
env["SERIOUS_PYTHON_BUNDLE_ID"] = bundle_id
|
|
2583
|
+
|
|
2568
2584
|
# Swift Package Manager (darwin): export the cache-bust key the package
|
|
2569
2585
|
# step computed so the plugin's Package.swift re-resolves when the staged
|
|
2570
2586
|
# native set changes (SwiftPM caches its graph on manifest text + env).
|
|
@@ -2854,11 +2870,14 @@ class BaseBuildCommand(BaseFlutterCommand):
|
|
|
2854
2870
|
"""
|
|
2855
2871
|
Find the best matching image file for the current target platform.
|
|
2856
2872
|
|
|
2857
|
-
When multiple files share the same base name (e.g. `icon.
|
|
2858
|
-
`icon.
|
|
2859
|
-
|
|
2860
|
-
|
|
2861
|
-
|
|
2873
|
+
When multiple files share the same base name (e.g. `icon.png` and
|
|
2874
|
+
`icon.svg`), incompatible formats are filtered out and the rest are
|
|
2875
|
+
ranked so a raster image (`.png` first) always wins, making the
|
|
2876
|
+
choice deterministic regardless of filesystem ordering. Formats the
|
|
2877
|
+
icon/splash generators cannot decode are dropped: `.svg` (vector,
|
|
2878
|
+
never supported), `.icns` (macOS-only) and `.ico` (Windows-only). If
|
|
2879
|
+
the only candidate is a vector image, a warning is logged and `None`
|
|
2880
|
+
is returned so the default icon is used.
|
|
2862
2881
|
|
|
2863
2882
|
Args:
|
|
2864
2883
|
src_path: Source assets directory.
|
|
@@ -2871,21 +2890,54 @@ class BaseBuildCommand(BaseFlutterCommand):
|
|
|
2871
2890
|
File name of matched image, or `None` if not found.
|
|
2872
2891
|
"""
|
|
2873
2892
|
|
|
2874
|
-
#
|
|
2875
|
-
#
|
|
2876
|
-
|
|
2877
|
-
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
|
|
2881
|
-
|
|
2882
|
-
|
|
2883
|
-
|
|
2884
|
-
|
|
2885
|
-
|
|
2893
|
+
# flutter_launcher_icons / flutter_native_splash decode raster images
|
|
2894
|
+
# only, so drop any candidate they can't read: .svg is vector (never
|
|
2895
|
+
# supported), .icns is macOS-only and .ico is Windows-only.
|
|
2896
|
+
def _incompatible(p: str) -> bool:
|
|
2897
|
+
ext = Path(p).suffix.lower()
|
|
2898
|
+
return (
|
|
2899
|
+
ext == ".svg"
|
|
2900
|
+
or (ext == ".icns" and self.target_platform != "macos")
|
|
2901
|
+
or (ext == ".ico" and self.target_platform != "windows")
|
|
2902
|
+
)
|
|
2903
|
+
|
|
2904
|
+
# glob order is filesystem-dependent — sort so the choice is
|
|
2905
|
+
# deterministic across machines, then rank by format so a raster
|
|
2906
|
+
# icon (.png first) always wins when several candidates share a base
|
|
2907
|
+
# name (e.g. both icon.png and icon.svg present).
|
|
2908
|
+
ext_priority = {
|
|
2909
|
+
".png": 0,
|
|
2910
|
+
".webp": 1,
|
|
2911
|
+
".jpg": 2,
|
|
2912
|
+
".jpeg": 2,
|
|
2913
|
+
".gif": 3,
|
|
2914
|
+
".bmp": 4,
|
|
2915
|
+
".tif": 5,
|
|
2916
|
+
".tiff": 5,
|
|
2917
|
+
".ico": 6,
|
|
2918
|
+
".icns": 6,
|
|
2919
|
+
}
|
|
2920
|
+
candidates = sorted(glob.glob(str(src_path.joinpath(f"{image_name}.*"))))
|
|
2921
|
+
images = sorted(
|
|
2922
|
+
(p for p in candidates if not _incompatible(p)),
|
|
2923
|
+
key=lambda p: (ext_priority.get(Path(p).suffix.lower(), 99), p),
|
|
2886
2924
|
)
|
|
2887
2925
|
|
|
2888
2926
|
if not images:
|
|
2927
|
+
# Nothing usable. If the only candidate was a vector image (e.g.
|
|
2928
|
+
# an icon.svg with no raster sibling), say why it's ignored
|
|
2929
|
+
# instead of silently falling back to the default icon.
|
|
2930
|
+
svg = next(
|
|
2931
|
+
(p for p in candidates if Path(p).suffix.lower() == ".svg"), None
|
|
2932
|
+
)
|
|
2933
|
+
if svg:
|
|
2934
|
+
console.log(
|
|
2935
|
+
f'Warning: "{Path(svg).name}" is a vector (SVG) image and '
|
|
2936
|
+
f'cannot be used for "{image_name}". Provide a raster '
|
|
2937
|
+
f'"{image_name}.png" to customize it — using the default '
|
|
2938
|
+
f"for now.",
|
|
2939
|
+
style=warning_style,
|
|
2940
|
+
)
|
|
2889
2941
|
return None
|
|
2890
2942
|
|
|
2891
2943
|
best = images[0]
|
|
@@ -47,6 +47,16 @@ class Command(BaseCommand):
|
|
|
47
47
|
default=".",
|
|
48
48
|
help="Path to the Python script that starts your Flet app",
|
|
49
49
|
)
|
|
50
|
+
parser.add_argument(
|
|
51
|
+
"script_args",
|
|
52
|
+
type=str,
|
|
53
|
+
nargs="*",
|
|
54
|
+
default=[],
|
|
55
|
+
metavar="args",
|
|
56
|
+
help="Arguments to pass to your app script, available there as "
|
|
57
|
+
"`sys.argv[1:]`. Separate them from Flet's own options with `--`, "
|
|
58
|
+
"e.g. `flet run --web app.py -- --verbose`",
|
|
59
|
+
)
|
|
50
60
|
parser.add_argument(
|
|
51
61
|
"-p",
|
|
52
62
|
"--port",
|
|
@@ -287,7 +297,8 @@ class Command(BaseCommand):
|
|
|
287
297
|
my_event_handler = Handler(
|
|
288
298
|
args=[sys.executable, "-u"]
|
|
289
299
|
+ ["-m"] * options.module
|
|
290
|
-
+ [options.script if options.module else script_path]
|
|
300
|
+
+ [options.script if options.module else script_path]
|
|
301
|
+
+ list(options.script_args),
|
|
291
302
|
watch_directory=options.directory or options.recursive,
|
|
292
303
|
script_path=str(script_path),
|
|
293
304
|
port=port,
|
|
@@ -28,7 +28,7 @@ from flet_cli.utils.template_cache import get_cache_root
|
|
|
28
28
|
# python-build release this flet pins. Keep in sync with serious_python's
|
|
29
29
|
# `pythonReleaseDate` (lib/src/python_versions.dart) — both should track the
|
|
30
30
|
# same python-build release.
|
|
31
|
-
PYTHON_BUILD_RELEASE_DATE = "
|
|
31
|
+
PYTHON_BUILD_RELEASE_DATE = "20260727"
|
|
32
32
|
|
|
33
33
|
RELEASE_DATE_ENV = "FLET_PYTHON_BUILD_RELEASE_DATE"
|
|
34
34
|
MANIFEST_PATH_ENV = "FLET_PYTHON_BUILD_MANIFEST"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
version = "0.86.4"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: flet-cli
|
|
3
|
-
Version: 0.86.
|
|
3
|
+
Version: 0.86.4
|
|
4
4
|
Summary: Flet CLI
|
|
5
5
|
Author-email: "Appveyor Systems Inc." <hello@flet.dev>
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -9,7 +9,7 @@ Project-URL: Repository, https://github.com/flet-dev/flet
|
|
|
9
9
|
Project-URL: Documentation, https://flet.dev/docs
|
|
10
10
|
Requires-Python: >=3.10
|
|
11
11
|
Description-Content-Type: text/markdown
|
|
12
|
-
Requires-Dist: flet==0.86.
|
|
12
|
+
Requires-Dist: flet==0.86.4
|
|
13
13
|
Requires-Dist: watchdog>=4.0.0
|
|
14
14
|
Requires-Dist: packaging>=25.0
|
|
15
15
|
Requires-Dist: qrcode>=7.4.2
|
|
@@ -50,6 +50,8 @@ src/flet_cli/utils/pyproject_toml.py
|
|
|
50
50
|
src/flet_cli/utils/python_versions.py
|
|
51
51
|
src/flet_cli/utils/template_cache.py
|
|
52
52
|
tests/test_clean.py
|
|
53
|
+
tests/test_find_platform_image.py
|
|
53
54
|
tests/test_plist.py
|
|
54
55
|
tests/test_project_dependencies.py
|
|
55
|
-
tests/test_python_versions.py
|
|
56
|
+
tests/test_python_versions.py
|
|
57
|
+
tests/test_run_script_args.py
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"""Icon/splash image selection in `flet build`.
|
|
2
|
+
|
|
3
|
+
`find_platform_image` must pick a *decodable* image deterministically when
|
|
4
|
+
several files share a base name — otherwise the choice depends on filesystem
|
|
5
|
+
glob order and an `icon.svg` can slip through to `flutter_launcher_icons`,
|
|
6
|
+
which crashes with `NoDecoderForImageFormatException`.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from types import SimpleNamespace
|
|
10
|
+
|
|
11
|
+
from flet_cli.commands.build_base import BaseBuildCommand
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class _FakeHash:
|
|
15
|
+
def update(self, *_):
|
|
16
|
+
pass
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def _find(tmp_path, filenames, *, image_name="icon", target_platform="web"):
|
|
20
|
+
assets = tmp_path / "assets"
|
|
21
|
+
assets.mkdir(exist_ok=True)
|
|
22
|
+
for name in filenames:
|
|
23
|
+
(assets / name).write_bytes(b"x")
|
|
24
|
+
dest = tmp_path / "images"
|
|
25
|
+
dest.mkdir(exist_ok=True)
|
|
26
|
+
fake_self = SimpleNamespace(target_platform=target_platform, verbose=0)
|
|
27
|
+
copy_ops: list = []
|
|
28
|
+
result = BaseBuildCommand.find_platform_image(
|
|
29
|
+
fake_self, assets, dest, image_name, copy_ops, _FakeHash()
|
|
30
|
+
)
|
|
31
|
+
return result, copy_ops
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def test_prefers_raster_over_svg(tmp_path):
|
|
35
|
+
# Both present: the raster png must win regardless of glob order.
|
|
36
|
+
result, copy_ops = _find(tmp_path, ["icon.svg", "icon.png"])
|
|
37
|
+
assert result == "icon.png"
|
|
38
|
+
assert copy_ops and str(copy_ops[0][0]).endswith("icon.png")
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def test_png_preferred_over_other_raster(tmp_path):
|
|
42
|
+
# Ranking, not alphabetical order (jpg < png alphabetically).
|
|
43
|
+
result, _ = _find(tmp_path, ["icon.jpg", "icon.png"])
|
|
44
|
+
assert result == "icon.png"
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def test_svg_only_returns_none_with_warning(tmp_path, capsys):
|
|
48
|
+
result, copy_ops = _find(tmp_path, ["icon.svg"])
|
|
49
|
+
assert result is None
|
|
50
|
+
assert copy_ops == []
|
|
51
|
+
combined = capsys.readouterr()
|
|
52
|
+
assert "icon.svg" in (combined.out + combined.err)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def test_no_candidates_is_silent_none(tmp_path, capsys):
|
|
56
|
+
result, copy_ops = _find(tmp_path, [])
|
|
57
|
+
assert result is None
|
|
58
|
+
assert copy_ops == []
|
|
59
|
+
combined = capsys.readouterr()
|
|
60
|
+
assert "Warning" not in (combined.out + combined.err)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def test_ico_is_windows_only(tmp_path):
|
|
64
|
+
# ico is incompatible on web (no raster sibling) -> default icon.
|
|
65
|
+
assert _find(tmp_path, ["icon.ico"], target_platform="web")[0] is None
|
|
66
|
+
# ...but valid on a windows build.
|
|
67
|
+
assert _find(tmp_path, ["icon.ico"], target_platform="windows")[0] == "icon.ico"
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
|
|
3
|
+
from flet_cli.cli import parse_command_line
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def _parse(*argv):
|
|
7
|
+
"""Parse a Flet command line given as separate arguments."""
|
|
8
|
+
return parse_command_line(list(argv))
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def test_no_script_args():
|
|
12
|
+
"""A plain `flet run app.py` passes nothing to the script."""
|
|
13
|
+
args = _parse("run", "app.py")
|
|
14
|
+
|
|
15
|
+
assert args.script == "app.py"
|
|
16
|
+
assert args.script_args == []
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def test_script_args_after_separator():
|
|
20
|
+
"""Arguments after `--` are forwarded to the script, options and all."""
|
|
21
|
+
args = _parse("run", "app.py", "--", "--manual", "-x", "1")
|
|
22
|
+
|
|
23
|
+
assert args.script == "app.py"
|
|
24
|
+
assert args.script_args == ["--manual", "-x", "1"]
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def test_flet_options_are_not_forwarded():
|
|
28
|
+
"""Flet's own options before `--` stay with Flet."""
|
|
29
|
+
args = _parse("run", "-w", "app.py", "--", "--web")
|
|
30
|
+
|
|
31
|
+
assert args.web is True
|
|
32
|
+
assert args.script == "app.py"
|
|
33
|
+
assert args.script_args == ["--web"]
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def test_flet_options_between_script_and_separator():
|
|
37
|
+
"""Flet's options may follow the script path and precede `--`."""
|
|
38
|
+
args = _parse("run", "app.py", "--web", "--port", "8080", "--", "--manual")
|
|
39
|
+
|
|
40
|
+
assert args.web is True
|
|
41
|
+
assert args.port == 8080
|
|
42
|
+
assert args.script_args == ["--manual"]
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def test_positional_script_args_need_no_separator():
|
|
46
|
+
"""Arguments that don't look like options are forwarded without `--`."""
|
|
47
|
+
args = _parse("run", "app.py", "foo", "bar")
|
|
48
|
+
|
|
49
|
+
assert args.script == "app.py"
|
|
50
|
+
assert args.script_args == ["foo", "bar"]
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def test_positional_and_separated_script_args_are_combined():
|
|
54
|
+
"""Arguments before and after `--` are forwarded in command-line order."""
|
|
55
|
+
args = _parse("run", "app.py", "foo", "--", "--manual")
|
|
56
|
+
|
|
57
|
+
assert args.script_args == ["foo", "--manual"]
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def test_script_args_with_module():
|
|
61
|
+
"""`-m` module invocations forward script arguments too."""
|
|
62
|
+
args = _parse("run", "-m", "my_app.main", "--", "--manual")
|
|
63
|
+
|
|
64
|
+
assert args.module is True
|
|
65
|
+
assert args.script == "my_app.main"
|
|
66
|
+
assert args.script_args == ["--manual"]
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def test_script_args_with_implicit_run_command():
|
|
70
|
+
"""The default `run` subcommand is applied even with a `--` separator."""
|
|
71
|
+
args = _parse("app.py", "--", "--manual")
|
|
72
|
+
|
|
73
|
+
assert args.command == "run"
|
|
74
|
+
assert args.script == "app.py"
|
|
75
|
+
assert args.script_args == ["--manual"]
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def test_script_args_named_like_a_subcommand():
|
|
79
|
+
"""A script argument matching a subcommand name doesn't select it."""
|
|
80
|
+
args = _parse("app.py", "--", "build", "test")
|
|
81
|
+
|
|
82
|
+
assert args.command == "run"
|
|
83
|
+
assert args.script == "app.py"
|
|
84
|
+
assert args.script_args == ["build", "test"]
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def test_unknown_flet_option_is_rejected(capsys):
|
|
88
|
+
"""A mistyped Flet option still errors instead of reaching the script."""
|
|
89
|
+
with pytest.raises(SystemExit):
|
|
90
|
+
_parse("run", "app.py", "--wev")
|
|
91
|
+
|
|
92
|
+
err = capsys.readouterr().err
|
|
93
|
+
assert "unrecognized arguments: --wev" in err
|
|
94
|
+
# ...and the error suggests the `--` separator
|
|
95
|
+
assert "flet run app.py -- --wev" in err
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def test_separator_rejected_for_other_commands(capsys):
|
|
99
|
+
"""Only `flet run` accepts a `--` separator."""
|
|
100
|
+
with pytest.raises(SystemExit):
|
|
101
|
+
_parse("build", "apk", "--", "--manual")
|
|
102
|
+
|
|
103
|
+
assert "only supported by `flet run`" in capsys.readouterr().err
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
version = "0.86.2"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{flet_cli-0.86.2 → flet_cli-0.86.4}/src/flet_cli/__pyinstaller/rthooks/pyi_rth_localhost_fletd.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|