@@ -56,7 +56,6 @@ def __init__(self, parser: argparse.ArgumentParser) -> None:
5656 self .flutter_dependencies = None
5757 self .package_app_path = None
5858 self .options = None
59- self .pubspec = None
6059 self .template_data = None
6160 self .python_module_filename = None
6261 self .out_dir = None
@@ -69,6 +68,7 @@ def __init__(self, parser: argparse.ArgumentParser) -> None:
6968 self .verbose = False
7069 self .build_dir = None
7170 self .flutter_dir : Optional [Path ] = None
71+ self .flutter_packages_dir = None
7272 self .flutter_exe = None
7373 self .skip_flutter_doctor = get_bool_env_var ("FLET_CLI_SKIP_FLUTTER_DOCTOR" )
7474 self .no_rich_output = get_bool_env_var ("FLET_CLI_NO_RICH_OUTPUT" )
@@ -553,10 +553,11 @@ def handle(self, options: argparse.Namespace) -> None:
553553 self .validate_entry_point ()
554554 self .setup_template_data ()
555555 self .create_flutter_project ()
556- self .load_pubspec ()
556+ self .update_flutter_dependencies ()
557557 self .customize_icons_and_splash_images ()
558558 self .generate_icons_and_splash_screens ()
559559 self .package_python_app ()
560+ self .register_flutter_extensions ()
560561 self .flutter_build ()
561562 self .copy_build_output ()
562563
@@ -614,7 +615,8 @@ def initialize_build(self):
614615 )
615616
616617 self .build_dir = self .python_app_path .joinpath ("build" )
617- self .flutter_dir = Path (self .build_dir ).joinpath ("flutter" )
618+ self .flutter_dir = self .build_dir .joinpath ("flutter" )
619+ self .flutter_packages_dir = self .build_dir .joinpath ("flutter-packages" )
618620 self .out_dir = (
619621 Path (self .options .output_dir ).resolve ()
620622 if self .options .output_dir
@@ -1009,52 +1011,58 @@ def create_flutter_project(self):
10091011 f"Created Flutter bootstrap project from { template_url } with ref { template_ref } { self .emojis ['checkmark' ]} "
10101012 )
10111013
1012- def load_pubspec (self ):
1014+ def update_flutter_dependencies (self ):
10131015 assert self .pubspec_path
10141016 assert self .template_data
10151017 assert self .get_pyproject
10161018 assert isinstance (self .flutter_dependencies , dict )
10171019
10181020 with open (self .pubspec_path , encoding = "utf8" ) as f :
1019- self . pubspec = yaml .safe_load (f )
1021+ pubspec = yaml .safe_load (f )
10201022
10211023 # merge dependencies to a dest pubspec.yaml
10221024 for k , v in self .flutter_dependencies .items ():
1023- self . pubspec ["dependencies" ][k ] = v
1025+ pubspec ["dependencies" ][k ] = v
10241026
1025- self . pubspec = merge_dict (
1026- self . pubspec , self .get_pyproject ("tool.flet.flutter.pubspec" ) or {}
1027+ pubspec = merge_dict (
1028+ pubspec , self .get_pyproject ("tool.flet.flutter.pubspec" ) or {}
10271029 )
10281030
10291031 # make sure project_name is not named as any of the dependencies
1030- for dep in self . pubspec ["dependencies" ].keys ():
1032+ for dep in pubspec ["dependencies" ].keys ():
10311033 if dep == self .template_data ["project_name" ]:
10321034 self .cleanup (
10331035 1 ,
10341036 f"Project name cannot have the same name as one of its dependencies: { dep } . "
10351037 f"Use --project option to specify a different project name." ,
10361038 )
10371039
1040+ # save pubspec.yaml
1041+ with open (self .pubspec_path , "w" , encoding = "utf8" ) as f :
1042+ yaml .dump (pubspec , f )
1043+
10381044 def customize_icons_and_splash_images (self ):
10391045 assert self .package_app_path
10401046 assert self .flutter_dir
10411047 assert self .options
10421048 assert self .get_pyproject
1043- assert self .pubspec
10441049 assert self .pubspec_path
10451050
10461051 self .status .update (
10471052 f"[bold blue]Customizing app icons and splash images { self .emojis ['loading' ]} ... "
10481053 )
1054+
1055+ with open (self .pubspec_path , encoding = "utf8" ) as f :
1056+ pubspec = yaml .safe_load (f )
1057+
10491058 self .assets_path = self .package_app_path .joinpath ("assets" )
10501059 if self .assets_path .exists ():
10511060 images_dir = "images"
10521061 images_path = self .flutter_dir .joinpath (images_dir )
10531062 images_path .mkdir (exist_ok = True )
10541063
10551064 def fallback_image (yaml_path : str , images : list ):
1056- assert self .pubspec
1057- d = self .pubspec
1065+ d = pubspec
10581066 pp = yaml_path .split ("/" )
10591067 for p in pp [:- 1 ]:
10601068 d = d [p ]
@@ -1196,16 +1204,14 @@ def fallback_image(yaml_path: str, images: list):
11961204 "tool.flet.splash.color"
11971205 )
11981206 if splash_color :
1199- self .pubspec ["flutter_native_splash" ]["color" ] = splash_color
1200- self .pubspec ["flutter_native_splash" ]["android_12" ][
1201- "color"
1202- ] = splash_color
1207+ pubspec ["flutter_native_splash" ]["color" ] = splash_color
1208+ pubspec ["flutter_native_splash" ]["android_12" ]["color" ] = splash_color
12031209 splash_dark_color = self .options .splash_dark_color or self .get_pyproject (
12041210 "tool.flet.splash.dark_color"
12051211 )
12061212 if splash_dark_color :
1207- self . pubspec ["flutter_native_splash" ]["color_dark" ] = splash_dark_color
1208- self . pubspec ["flutter_native_splash" ]["android_12" ][
1213+ pubspec ["flutter_native_splash" ]["color_dark" ] = splash_dark_color
1214+ pubspec ["flutter_native_splash" ]["android_12" ][
12091215 "color_dark"
12101216 ] = splash_dark_color
12111217
@@ -1214,12 +1220,12 @@ def fallback_image(yaml_path: str, images: list):
12141220 or self .get_pyproject ("tool.flet.android.adaptive_icon_background" )
12151221 )
12161222 if adaptive_icon_background :
1217- self . pubspec ["flutter_launcher_icons" ][
1223+ pubspec ["flutter_launcher_icons" ][
12181224 "adaptive_icon_background"
12191225 ] = adaptive_icon_background
12201226
12211227 # enable/disable splashes
1222- self . pubspec ["flutter_native_splash" ]["web" ] = (
1228+ pubspec ["flutter_native_splash" ]["web" ] = (
12231229 not self .options .no_web_splash
12241230 if self .options .no_web_splash is not None
12251231 else (
@@ -1228,7 +1234,7 @@ def fallback_image(yaml_path: str, images: list):
12281234 else True
12291235 )
12301236 )
1231- self . pubspec ["flutter_native_splash" ]["ios" ] = (
1237+ pubspec ["flutter_native_splash" ]["ios" ] = (
12321238 not self .options .no_ios_splash
12331239 if self .options .no_ios_splash is not None
12341240 else (
@@ -1237,7 +1243,7 @@ def fallback_image(yaml_path: str, images: list):
12371243 else True
12381244 )
12391245 )
1240- self . pubspec ["flutter_native_splash" ]["android" ] = (
1246+ pubspec ["flutter_native_splash" ]["android" ] = (
12411247 not self .options .no_android_splash
12421248 if self .options .no_android_splash is not None
12431249 else (
@@ -1249,7 +1255,7 @@ def fallback_image(yaml_path: str, images: list):
12491255
12501256 # save pubspec.yaml
12511257 with open (self .pubspec_path , "w" , encoding = "utf8" ) as f :
1252- yaml .dump (self . pubspec , f )
1258+ yaml .dump (pubspec , f )
12531259
12541260 console .log (
12551261 f"Customized app icons and splash images { self .emojis ['checkmark' ]} "
@@ -1300,6 +1306,7 @@ def package_python_app(self):
13001306 assert self .package_app_path
13011307 assert self .build_dir
13021308 assert self .flutter_dir
1309+ assert self .flutter_packages_dir
13031310
13041311 self .status .update (
13051312 f"[bold blue]Packaging Python app { self .emojis ['loading' ]} ... "
@@ -1332,13 +1339,22 @@ def package_python_app(self):
13321339 ) or get_project_dependencies (self .get_pyproject ("project.dependencies" ))
13331340
13341341 if toml_dependencies :
1342+ platform_dependencies = get_project_dependencies (
1343+ self .get_pyproject (f"tool.flet.{ self .config_platform } .dependencies" )
1344+ )
1345+ if platform_dependencies :
1346+ toml_dependencies .extend (platform_dependencies )
1347+
13351348 package_args .extend (
13361349 [
13371350 "--requirements" ,
13381351 "," .join (toml_dependencies ),
13391352 ]
13401353 )
13411354 elif requirements_txt .exists ():
1355+ if self .verbose > 1 :
1356+ with open (requirements_txt , "r" ) as f :
1357+ console .log (f"Contents of requirements.txt: { f .read ()} " )
13421358 package_args .extend (["--requirements" , f"-r,{ requirements_txt } " ])
13431359
13441360 # site-packages variable
@@ -1347,6 +1363,12 @@ def package_python_app(self):
13471363 self .build_dir / "site-packages"
13481364 )
13491365
1366+ # flutter-packages variable
1367+ if self .flutter_packages_dir .exists ():
1368+ shutil .rmtree (self .flutter_packages_dir )
1369+
1370+ package_env ["SERIOUS_PYTHON_FLUTTER_PACKAGES" ] = str (self .flutter_packages_dir )
1371+
13501372 # exclude
13511373 exclude_list = ["build" ]
13521374
@@ -1417,6 +1439,29 @@ def package_python_app(self):
14171439
14181440 console .log (f"Packaged Python app { self .emojis ['checkmark' ]} " )
14191441
1442+ def register_flutter_extensions (self ):
1443+ assert self .flutter_packages_dir
1444+ assert self .pubspec_path
1445+
1446+ self .status .update (
1447+ f"[bold blue]Registering Flutter user extensions { self .emojis ['loading' ]} ... "
1448+ )
1449+
1450+ with open (self .pubspec_path , encoding = "utf8" ) as f :
1451+ pubspec = yaml .safe_load (f )
1452+
1453+ for fp in os .listdir (self .flutter_packages_dir ):
1454+ if (self .flutter_packages_dir / fp / "pubspec.yaml" ).exists ():
1455+ pubspec ["dependencies" ][fp ] = {
1456+ "path" : str (self .flutter_packages_dir / fp )
1457+ }
1458+
1459+ # save pubspec.yaml
1460+ with open (self .pubspec_path , "w" , encoding = "utf8" ) as f :
1461+ yaml .dump (pubspec , f )
1462+
1463+ console .log (f"Registered Flutter user extensions { self .emojis ['checkmark' ]} " )
1464+
14201465 def flutter_build (self ):
14211466 assert self .options
14221467 assert self .build_dir
0 commit comments