Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
ad8021f
rename `MINIMAL_FLUTTER_VERSION` to `FLUTTER_VERSION`
ndonkoHenri Dec 15, 2025
d78987e
feat: expose Flutter SDK version in CLI and version module
ndonkoHenri Dec 15, 2025
2ddc8e8
`flet build --flutter-version`
ndonkoHenri Dec 15, 2025
d9c1b1f
ci: read Flutter version from .fvmrc and update version.py
ndonkoHenri Dec 15, 2025
9ea3a90
ci: enforce stricter error handling and streamline version patching
ndonkoHenri Dec 15, 2025
e9f2e4c
`flet.version.version` can't be empty
ndonkoHenri Dec 15, 2025
e744eb8
improve error handling for Flutter version retrieval and streamline v…
ndonkoHenri Dec 15, 2025
db82fd4
ci: dynamically retrieve Pyodide version in CI configuration
ndonkoHenri Dec 15, 2025
6952b0b
fix error
ndonkoHenri Dec 15, 2025
eb3118a
`flet.__version__`
ndonkoHenri Dec 16, 2025
de09875
isolate patch_python_package_versions
ndonkoHenri Dec 16, 2025
58e7442
ci: update working directory for version patching and improve Pyodide…
ndonkoHenri Dec 16, 2025
67edca1
ci: fix web job
ndonkoHenri Dec 16, 2025
25d6a53
cleanup
ndonkoHenri Dec 16, 2025
023d9dc
enable macos-integration-tests
ndonkoHenri Dec 16, 2025
fbb458e
update help message
ndonkoHenri Dec 16, 2025
d9092be
renaming: `flet_version`, `flutter_version`, `pyodide_version`
ndonkoHenri Dec 17, 2025
0662abe
refactor: update User-Agent to use flet_version
ndonkoHenri Dec 17, 2025
a3a1e18
feat: enhance version flag to display detailed version information
ndonkoHenri Dec 20, 2025
e64bb9f
feat: implement custom help formatter to display informative default …
ndonkoHenri Dec 20, 2025
ddfc51f
improve flet doctor
ndonkoHenri Dec 20, 2025
bb153dc
Merge branch 'main' into expose-flutter-version
ndonkoHenri Dec 20, 2025
b44fe70
fix plotly chart
ndonkoHenri Dec 20, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions .github/scripts/common.sh
Original file line number Diff line number Diff line change
@@ -1,16 +1,22 @@
function patch_python_package_versions() {
function patch_python_package_versions() (
set -euo pipefail
cd "$SDK_PYTHON" || exit 1

# Install dependencies
uv sync --no-default-groups || true

# Update package versions in version.py and pyproject.toml files
for pkg in flet flet-cli flet-desktop flet-web; do
sed -i -e "s/version = \"\"/version = \"$PYPI_VER\"/g" packages/$pkg/src/${pkg//-/_}/version.py
sed -i -e "s/flet_version = \"\"/flet_version = \"$PYPI_VER\"/g" packages/$pkg/src/${pkg//-/_}/version.py
uv version --package "$pkg" "$PYPI_VER"
echo "Patched version for $pkg to $PYPI_VER"
done
}

# Get Flutter version from .fvmrc and set it in version.py
FLUTTER_VERSION="$( uv run "$SCRIPTS/read_fvmrc.py" "${ROOT}/.fvmrc" )"
sed -i -e "s/flutter_version = \"\"/flutter_version = \"$FLUTTER_VERSION\"/g" packages/flet/src/flet/version.py
echo "Patched Flutter SDK version to $FLUTTER_VERSION"
)


update_flet_wheel_deps() {
Expand Down
25 changes: 25 additions & 0 deletions .github/scripts/read_fvmrc.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
"""
Reads the Flutter version from a .fvmrc file and prints it.
Usage:
uv run read_fvmrc.py <fvmrc_file>
"""

import json
import sys


def main() -> None:
try:
with open(sys.argv[1], encoding="utf-8") as f:
v = json.load(f)["flutter"].strip()
if not v:
raise ValueError("Empty or missing 'flutter' value")
print(v)
except Exception as e:
print(f"Error parsing {sys.argv[1]!r}: {e}", file=sys.stderr)
sys.exit(1)


if __name__ == "__main__":
main()
24 changes: 19 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,7 @@ env:
ROOT: "${{ github.workspace }}"
SDK_PYTHON: "${{ github.workspace }}/sdk/python"
SCRIPTS: "${{ github.workspace }}/.github/scripts"
UV_PYTHON: "3.12"
PYODIDE_VERSION: "0.27.7"
UV_PYTHON: "3.12.7"

jobs:
# ============
Expand Down Expand Up @@ -159,10 +158,11 @@ jobs:

- name: Prepare env and patch versions
shell: bash
working-directory: ${{ env.SDK_PYTHON }}
run: |
source "$SCRIPTS/common.sh"
patch_python_package_versions
patch_toml_versions "${SDK_PYTHON}/packages/flet-desktop/pyproject.toml" "$PYPI_VER"
patch_toml_versions "packages/flet-desktop/pyproject.toml" "$PYPI_VER"

- name: Build Flutter Windows client
env:
Expand Down Expand Up @@ -497,6 +497,21 @@ jobs:
path: '.fvmrc'
cache: true

- name: Patch Python and Flutter versions
shell: bash
working-directory: ${{ env.SDK_PYTHON }}
run: |
source "$SCRIPTS/common.sh"
patch_python_package_versions

- name: Get Pyodide version
shell: bash
working-directory: ${{ env.SDK_PYTHON }}
run: |
PYODIDE_VERSION="$( uv run python -c 'import flet.version; print(flet.version.pyodide_version)' )"
echo "PYODIDE_VERSION=$PYODIDE_VERSION" >> "$GITHUB_ENV"
echo "Pyodide version: $PYODIDE_VERSION"

- name: Build Web client
shell: bash
working-directory: client
Expand Down Expand Up @@ -530,8 +545,6 @@ jobs:
shell: bash
working-directory: ${{ env.SDK_PYTHON }}
run: |
source "$SCRIPTS/common.sh"
patch_python_package_versions
uv build --package flet-web --wheel

rm -rf "packages/flet-web/src/flet_web/web"
Expand Down Expand Up @@ -639,6 +652,7 @@ jobs:

- name: Build Python packages
shell: bash
working-directory: ${{ env.SDK_PYTHON }}
run: |
source "$SCRIPTS/common.sh"
patch_python_package_versions
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ class PlotlyChart(ft.Container):
def init(self):
_require_plotly()
self.alignment = ft.Alignment.CENTER
self.__img = ft.Image(fit=ft.BoxFit.FILL)
self.__img = ft.Image(src="", fit=ft.BoxFit.FILL)
self.content = self.__img

def before_update(self):
Expand Down
12 changes: 8 additions & 4 deletions sdk/python/packages/flet-cli/src/flet_cli/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,16 +64,20 @@ def set_default_subparser(

def get_parser() -> argparse.ArgumentParser:
"""Construct and return the CLI argument parser."""
parser = argparse.ArgumentParser()
parser = argparse.ArgumentParser(
formatter_class=argparse.RawDescriptionHelpFormatter
)

# add version flag
parser.add_argument(
"--version",
"-V",
action="version",
version=flet.version.version
if flet.version.version
else flet.version.from_git(),
version=(
f"Flet: {flet.version.flet_version}\n"
f"Flutter: {flet.version.flutter_version}\n"
f"Pyodide: {flet.version.pyodide_version}"
),
)

sp = parser.add_subparsers(dest="command")
Expand Down
35 changes: 34 additions & 1 deletion sdk/python/packages/flet-cli/src/flet_cli/commands/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,39 @@
from flet_cli.commands.options import Option, verbose_option


class CustomArgumentDefaultsHelpFormatter(argparse.HelpFormatter):
"""
An argparse help formatter that appends default values to help text
selectively.
Defaults are added only when they are informative and not already
present in the help string. Noisy or redundant defaults (such as
None, empty lists, booleans for flag arguments, or suppressed values)
are omitted.
"""

def _get_help_string(self, action: argparse.Action) -> str:
help_text = action.help or ""
default = action.default

# skip appending a default
if (
default is None
or default == []
or isinstance(default, bool) # store_true / store_false flags
or default is argparse.SUPPRESS
or any(token in help_text for token in ("%(default)", "(default:"))
):
return help_text

# only add defaults for optionals or for nargs implying optional values
defaulting_nargs = (argparse.OPTIONAL, argparse.ZERO_OR_MORE)
if action.option_strings or action.nargs in defaulting_nargs:
help_text += " (default: %(default)s)"

return help_text


class BaseCommand:
"""A CLI subcommand"""

Expand Down Expand Up @@ -41,7 +74,7 @@ def register_to(
name,
description=help_text,
help=help_text,
# formatter_class=PdmFormatter,
formatter_class=CustomArgumentDefaultsHelpFormatter,
**kwargs,
)
command = cls(parser)
Expand Down
16 changes: 3 additions & 13 deletions sdk/python/packages/flet-cli/src/flet_cli/commands/build_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@
)
from flet_cli.utils.pyproject_toml import load_pyproject_toml

PYODIDE_ROOT_URL = "https://cdn.jsdelivr.net/pyodide/v0.27.7/full"
DEFAULT_TEMPLATE_URL = "gh:flet-dev/flet-build-template"


Expand Down Expand Up @@ -544,7 +543,7 @@ def add_arguments(self, parser: argparse.ArgumentParser) -> None:
"--android-signing-key-alias",
dest="android_signing_key_alias",
default="upload",
help="Android signing key alias (default: upload)",
help="Android signing key alias",
)
parser.add_argument(
"--build-number",
Expand Down Expand Up @@ -1016,11 +1015,7 @@ def create_flutter_project(self, second_pass=False):
"tool.flet.template.ref"
)
if not template_ref:
template_ref = (
version.Version(flet.version.version).base_version
if flet.version.version
else flet.version.from_git()
)
template_ref = version.Version(flet.version.flet_version).base_version
hash.update(template_ref)

template_dir = self.options.template_dir or self.get_pyproject(
Expand Down Expand Up @@ -1622,12 +1617,7 @@ def package_python_app(self):
hash.update(reqs_txt_contents)
package_args.extend(["-r", "-r", "-r", str(requirements_txt)])
else:
flet_version = (
flet.version.version
if flet.version.version
else flet.version.from_git()
)
package_args.extend(["-r", f"flet=={flet_version}"])
package_args.extend(["-r", f"flet=={flet.version.flet_version}"])

# site-packages variable
if self.package_platform != "Pyodide":
Expand Down
6 changes: 3 additions & 3 deletions sdk/python/packages/flet-cli/src/flet_cli/commands/create.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,13 +70,13 @@ def handle(self, options: argparse.Namespace) -> None:

template_data = {
"template_name": options.template,
"flet_version": flet.version.version,
"flet_version": flet.version.flet_version,
"sep": os.sep,
}

template_ref = options.template_ref
if not template_ref and flet.version.version:
template_ref = version.Version(flet.version.version).base_version
if not template_ref:
template_ref = version.Version(flet.version.flet_version).base_version

out_dir = Path(options.output_directory).resolve()
template_data["out_dir"] = out_dir.name
Expand Down
5 changes: 2 additions & 3 deletions sdk/python/packages/flet-cli/src/flet_cli/commands/devices.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,15 @@ def add_arguments(self, parser: argparse.ArgumentParser) -> None:
type=int,
default=10,
dest="device_timeout",
help="Time (in seconds) to wait for devices to attach (default: 10).",
help="Time (in seconds) to wait for devices to attach",
)
parser.add_argument(
"--device-connection",
type=str.lower,
choices=["both", "attached", "wireless"],
default="both",
dest="device_connection",
help="Filter devices by connection type: attached (USB) or wireless "
"(default: both).",
help="Filter devices by connection type: attached (USB) or wireless",
)
super().add_arguments(parser)

Expand Down
58 changes: 17 additions & 41 deletions sdk/python/packages/flet-cli/src/flet_cli/commands/doctor.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import argparse
import os
import platform
import sys

Expand All @@ -21,43 +20,20 @@ def handle(self, options: argparse.Namespace) -> None:
"""Handle the 'doctor' command."""
verbose = options.verbose

# Step-by-step checks (No need to store results)
self.check_flet_version()
self.check_python_version()
self.check_os_info()

# Extra details in verbose mode
if verbose:
self.check_virtual_env()

def check_flet_version(self) -> None:
"""Check and print Flet version."""
with console.status("[bold white]Checking Flet version..."):
flet_version = flet.version.version or "Unknown"
console.print(f"[green]✔ Flet Version:[/green] {flet_version}")

def check_python_version(self) -> None:
"""Check and print Python version."""
with console.status("[bold white]Checking Python version..."):
console.print(f"[green]✔ Python Version:[/green] {sys.version}")

def check_os_info(self) -> None:
"""Check and print OS information."""
with console.status("[bold white]Checking OS information..."):
os_info = f"{platform.system()} {platform.release()} ({platform.version()})"
console.print(f"[green]✔ Operating System:[/green] {os_info}")

def check_virtual_env(self) -> None:
"""Check if a Python virtual environment is active."""
with console.status("[bold white]Checking Python virtual environment..."):
venv = os.getenv("VIRTUAL_ENV")
conda_env = os.getenv("CONDA_PREFIX")

if venv:
console.print(f"[green]✔ Virtual Environment active:[/green] {venv}")
elif conda_env:
console.print(f"[green]✔ Conda Environment active:[/green] {conda_env}")
else:
console.print(
"[yellow]⚠ No virtual environment or Conda detected[/yellow]"
)
os_name = platform.system()
if os_name == "Darwin":
os_name = "macOS"
os_version = platform.mac_ver()[0]
else:
os_version = platform.release()

arch = platform.machine()
console.print(
f"Flet {flet.version.flet_version} on {os_name} {os_version} ({arch})"
if arch
else f"Flet {flet.version.flet_version} on {os_name} {os_version}"
)

console.print(f"Python {platform.python_version()} ({sys.executable})")

# TODO: output Flutter version, if installed
Loading