flutter-dev 0.1.12__tar.gz → 0.1.13__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.
Files changed (43) hide show
  1. {flutter_dev-0.1.12 → flutter_dev-0.1.13}/CHANGELOG.md +11 -0
  2. {flutter_dev-0.1.12 → flutter_dev-0.1.13}/PKG-INFO +6 -4
  3. {flutter_dev-0.1.12 → flutter_dev-0.1.13}/README.md +5 -3
  4. {flutter_dev-0.1.12 → flutter_dev-0.1.13}/fdev.py +5 -0
  5. {flutter_dev-0.1.12 → flutter_dev-0.1.13}/managers/package.py +74 -10
  6. {flutter_dev-0.1.12 → flutter_dev-0.1.13}/pyproject.toml +1 -1
  7. {flutter_dev-0.1.12 → flutter_dev-0.1.13}/tests/test_fdev_cli.py +20 -0
  8. {flutter_dev-0.1.12 → flutter_dev-0.1.13}/tests/test_package_commands.py +125 -9
  9. {flutter_dev-0.1.12 → flutter_dev-0.1.13}/.env.example +0 -0
  10. {flutter_dev-0.1.12 → flutter_dev-0.1.13}/LICENSE +0 -0
  11. {flutter_dev-0.1.12 → flutter_dev-0.1.13}/MANIFEST.in +0 -0
  12. {flutter_dev-0.1.12 → flutter_dev-0.1.13}/common_utils.py +0 -0
  13. {flutter_dev-0.1.12 → flutter_dev-0.1.13}/core/__init__.py +0 -0
  14. {flutter_dev-0.1.12 → flutter_dev-0.1.13}/core/ai_config.py +0 -0
  15. {flutter_dev-0.1.12 → flutter_dev-0.1.13}/core/constants.py +0 -0
  16. {flutter_dev-0.1.12 → flutter_dev-0.1.13}/core/state.py +0 -0
  17. {flutter_dev-0.1.12 → flutter_dev-0.1.13}/create_page.py +0 -0
  18. {flutter_dev-0.1.12 → flutter_dev-0.1.13}/flutter_dev.egg-info/SOURCES.txt +0 -0
  19. {flutter_dev-0.1.12 → flutter_dev-0.1.13}/gemini_api.py +0 -0
  20. {flutter_dev-0.1.12 → flutter_dev-0.1.13}/git_diff_output_editor.py +0 -0
  21. {flutter_dev-0.1.12 → flutter_dev-0.1.13}/install_legacy.py +0 -0
  22. {flutter_dev-0.1.12 → flutter_dev-0.1.13}/managers/__init__.py +0 -0
  23. {flutter_dev-0.1.12 → flutter_dev-0.1.13}/managers/ai.py +0 -0
  24. {flutter_dev-0.1.12 → flutter_dev-0.1.13}/managers/app.py +0 -0
  25. {flutter_dev-0.1.12 → flutter_dev-0.1.13}/managers/brew.py +0 -0
  26. {flutter_dev-0.1.12 → flutter_dev-0.1.13}/managers/build.py +0 -0
  27. {flutter_dev-0.1.12 → flutter_dev-0.1.13}/managers/datetime.py +0 -0
  28. {flutter_dev-0.1.12 → flutter_dev-0.1.13}/managers/device.py +0 -0
  29. {flutter_dev-0.1.12 → flutter_dev-0.1.13}/managers/doctor.py +0 -0
  30. {flutter_dev-0.1.12 → flutter_dev-0.1.13}/managers/git.py +0 -0
  31. {flutter_dev-0.1.12 → flutter_dev-0.1.13}/managers/git_account.py +0 -0
  32. {flutter_dev-0.1.12 → flutter_dev-0.1.13}/managers/localization.py +0 -0
  33. {flutter_dev-0.1.12 → flutter_dev-0.1.13}/managers/merge.py +0 -0
  34. {flutter_dev-0.1.12 → flutter_dev-0.1.13}/managers/mirror.py +0 -0
  35. {flutter_dev-0.1.12 → flutter_dev-0.1.13}/managers/project.py +0 -0
  36. {flutter_dev-0.1.12 → flutter_dev-0.1.13}/managers/web_deploy.py +0 -0
  37. {flutter_dev-0.1.12 → flutter_dev-0.1.13}/requirements.txt +0 -0
  38. {flutter_dev-0.1.12 → flutter_dev-0.1.13}/setup.cfg +0 -0
  39. {flutter_dev-0.1.12 → flutter_dev-0.1.13}/setup.py +0 -0
  40. {flutter_dev-0.1.12 → flutter_dev-0.1.13}/switch_ai.py +0 -0
  41. {flutter_dev-0.1.12 → flutter_dev-0.1.13}/tests/test_ai_config.py +0 -0
  42. {flutter_dev-0.1.12 → flutter_dev-0.1.13}/tests/test_app_commands.py +0 -0
  43. {flutter_dev-0.1.12 → flutter_dev-0.1.13}/tests/test_localization.py +0 -0
@@ -2,6 +2,17 @@
2
2
 
3
3
  All notable changes to this project are documented in this file.
4
4
 
5
+ ## 0.1.13 - 2026-07-22
6
+
7
+ ### Added
8
+
9
+ - Added `fdev -v` and `fdev --version` for showing the installed package version.
10
+
11
+ ### Changed
12
+
13
+ - Changed `fdev upgrade` to check PyPI before invoking pip, skip installation when already current, suppress routine pip dependency output, and report verified before→after versions after a successful upgrade.
14
+ - Kept the terminal-restart reminder after an actual successful version change.
15
+
5
16
  ## 0.1.12 - 2026-07-22
6
17
 
7
18
  ### Changed
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: flutter-dev
3
- Version: 0.1.12
3
+ Version: 0.1.13
4
4
  Summary: A cross-platform CLI toolkit for Flutter development workflows.
5
5
  Author: Royal Court BD
6
6
  License-Expression: MIT
@@ -42,7 +42,7 @@ The package is published on PyPI as `flutter-dev` and installs console commands
42
42
  python -m pip install flutter-dev
43
43
  ```
44
44
 
45
- Current package metadata declares version `0.1.12`, Python `>=3.8`, MIT license, and support for macOS, Linux, and Windows.
45
+ Current package metadata declares version `0.1.13`, Python `>=3.8`, MIT license, and support for macOS, Linux, and Windows.
46
46
 
47
47
  ## Key Features
48
48
 
@@ -241,9 +241,10 @@ Switching GitHub accounts runs `gh auth switch` and `gh auth setup-git`, but it
241
241
  | --- | --- |
242
242
  | `fdev` | Shows command help. |
243
243
  | `fdev help` | Shows command help. |
244
+ | `fdev -v` / `fdev --version` | Shows the version installed in the active fdev Python environment. |
244
245
  | `fdev doctor` | Checks platform, Python, Flutter/Dart/Git, Python packages, Android/iOS tools, optional CLIs, `.env`, Flutter project detection, and global `fdev` availability. |
245
246
  | `fdev init` | Creates or repairs the persistent AI `.env` with safe provider defaults and empty API keys. |
246
- | `fdev upgrade` | Shows the current version, Python environment, package location, and PyPI source, then upgrades with `python -m pip install --upgrade flutter-dev` and reports the resulting version. |
247
+ | `fdev upgrade` | Checks the latest PyPI version first. If already current, skips pip and prints one up-to-date notice; otherwise upgrades quietly and reports the previous and installed versions. |
247
248
  | `fdev delete` | Detects the OS, asks for confirmation, then uninstalls the active Python environment's `flutter-dev` package. Use `fdev delete --yes` to skip confirmation. |
248
249
  | `fdev ai` | Shows the current AI provider and opens an interactive provider switch prompt. |
249
250
  | `fdev ai <provider>` | Switches `DEFAULT_AI_SERVICE` to `groq`, `mistral`, `sambanova`, or `openrouter`. |
@@ -451,11 +452,12 @@ where fdev
451
452
  Use the built-in package management commands from the Python environment where `fdev` is installed:
452
453
 
453
454
  ```bash
455
+ fdev -v
454
456
  fdev upgrade
455
457
  fdev delete
456
458
  ```
457
459
 
458
- Both commands print the detected OS and exact Python executable before running. They use that executable with `-m pip`, not a hardcoded `python`, `python3`, `pip`, or `pip3`, so the active venv/global Python that launched `fdev` is the environment that gets upgraded or deleted. On Windows, `fdev delete` and `fdev upgrade` schedule the same `sys.executable -m pip ...` operation in a delayed command process so the currently running console launcher can exit first.
460
+ The upgrade and delete commands print the detected OS and exact Python executable. Upgrade checks PyPI first and avoids running pip when the installed version is current. When pip is needed, both commands use the active executable with `-m pip`, not a hardcoded `python`, `python3`, `pip`, or `pip3`. On Windows, `fdev delete` and a required `fdev upgrade` schedule the same `sys.executable -m pip ...` operation in a delayed command process so the currently running console launcher can exit first.
459
461
 
460
462
  ### Flutter Project Not Detected
461
463
 
@@ -8,7 +8,7 @@ The package is published on PyPI as `flutter-dev` and installs console commands
8
8
  python -m pip install flutter-dev
9
9
  ```
10
10
 
11
- Current package metadata declares version `0.1.12`, Python `>=3.8`, MIT license, and support for macOS, Linux, and Windows.
11
+ Current package metadata declares version `0.1.13`, Python `>=3.8`, MIT license, and support for macOS, Linux, and Windows.
12
12
 
13
13
  ## Key Features
14
14
 
@@ -207,9 +207,10 @@ Switching GitHub accounts runs `gh auth switch` and `gh auth setup-git`, but it
207
207
  | --- | --- |
208
208
  | `fdev` | Shows command help. |
209
209
  | `fdev help` | Shows command help. |
210
+ | `fdev -v` / `fdev --version` | Shows the version installed in the active fdev Python environment. |
210
211
  | `fdev doctor` | Checks platform, Python, Flutter/Dart/Git, Python packages, Android/iOS tools, optional CLIs, `.env`, Flutter project detection, and global `fdev` availability. |
211
212
  | `fdev init` | Creates or repairs the persistent AI `.env` with safe provider defaults and empty API keys. |
212
- | `fdev upgrade` | Shows the current version, Python environment, package location, and PyPI source, then upgrades with `python -m pip install --upgrade flutter-dev` and reports the resulting version. |
213
+ | `fdev upgrade` | Checks the latest PyPI version first. If already current, skips pip and prints one up-to-date notice; otherwise upgrades quietly and reports the previous and installed versions. |
213
214
  | `fdev delete` | Detects the OS, asks for confirmation, then uninstalls the active Python environment's `flutter-dev` package. Use `fdev delete --yes` to skip confirmation. |
214
215
  | `fdev ai` | Shows the current AI provider and opens an interactive provider switch prompt. |
215
216
  | `fdev ai <provider>` | Switches `DEFAULT_AI_SERVICE` to `groq`, `mistral`, `sambanova`, or `openrouter`. |
@@ -417,11 +418,12 @@ where fdev
417
418
  Use the built-in package management commands from the Python environment where `fdev` is installed:
418
419
 
419
420
  ```bash
421
+ fdev -v
420
422
  fdev upgrade
421
423
  fdev delete
422
424
  ```
423
425
 
424
- Both commands print the detected OS and exact Python executable before running. They use that executable with `-m pip`, not a hardcoded `python`, `python3`, `pip`, or `pip3`, so the active venv/global Python that launched `fdev` is the environment that gets upgraded or deleted. On Windows, `fdev delete` and `fdev upgrade` schedule the same `sys.executable -m pip ...` operation in a delayed command process so the currently running console launcher can exit first.
426
+ The upgrade and delete commands print the detected OS and exact Python executable. Upgrade checks PyPI first and avoids running pip when the installed version is current. When pip is needed, both commands use the active executable with `-m pip`, not a hardcoded `python`, `python3`, `pip`, or `pip3`. On Windows, `fdev delete` and a required `fdev upgrade` schedule the same `sys.executable -m pip ...` operation in a delayed command process so the currently running console launcher can exit first.
425
427
 
426
428
  ### Flutter Project Not Detected
427
429
 
@@ -73,6 +73,7 @@ from managers.git_account import (
73
73
  )
74
74
  from managers.package import (
75
75
  delete_fdev_command,
76
+ show_fdev_version,
76
77
  upgrade_fdev_command,
77
78
  )
78
79
 
@@ -124,6 +125,7 @@ def show_usage(exit_code=1):
124
125
  print(" brew Interactive Homebrew package manager")
125
126
  print(" upgrade Upgrade fdev from PyPI")
126
127
  print(" delete Uninstall fdev from this computer")
128
+ print(" -v, --version Show the installed fdev version")
127
129
  print(" help Show this help")
128
130
  print(" merge Merge files from paths.txt into single output file")
129
131
  print(" ai Show current AI service or switch to another")
@@ -167,6 +169,9 @@ def main():
167
169
 
168
170
  command = sys.argv[1].lower()
169
171
 
172
+ if command in ("-v", "--version"):
173
+ return show_fdev_version()
174
+
170
175
  if command in ("apk", "apk-split", "aab", "ipa", "release-run", "install"):
171
176
  os.makedirs("build/app/outputs/flutter-apk", exist_ok=True)
172
177
  os.makedirs("build/app/outputs/bundle/release", exist_ok=True)
@@ -9,9 +9,12 @@ import platform
9
9
  import subprocess
10
10
  import sys
11
11
 
12
+ import requests
13
+
12
14
  from common_utils import BLUE, GREEN, RED, YELLOW, NC
13
15
 
14
16
  PACKAGE_NAME = "flutter-dev"
17
+ PYPI_JSON_URL = f"https://pypi.org/pypi/{PACKAGE_NAME}/json"
15
18
 
16
19
 
17
20
  def get_os_info():
@@ -59,6 +62,32 @@ def _print_installed_package_info(version, package_location):
59
62
  print(f"{BLUE}Package location: {GREEN}{package_location}{NC}")
60
63
 
61
64
 
65
+ def show_fdev_version():
66
+ """Print the version installed in the Python environment running fdev."""
67
+ version, _ = _get_installed_package_info()
68
+ if version == "not installed":
69
+ print(f"{RED}Could not determine the installed fdev version.{NC}")
70
+ return 1
71
+
72
+ print(f"fdev {version}")
73
+ return 0
74
+
75
+
76
+ def _get_latest_pypi_version():
77
+ """Return the latest published PyPI version, or None when unavailable."""
78
+ try:
79
+ response = requests.get(
80
+ PYPI_JSON_URL,
81
+ headers={"Accept": "application/json"},
82
+ timeout=10,
83
+ )
84
+ response.raise_for_status()
85
+ version = response.json()["info"]["version"]
86
+ return version.strip() if isinstance(version, str) and version.strip() else None
87
+ except (requests.RequestException, KeyError, TypeError, ValueError):
88
+ return None
89
+
90
+
62
91
  def _build_pip_command(pip_args):
63
92
  return [sys.executable, "-m", "pip", *pip_args]
64
93
 
@@ -68,6 +97,23 @@ def _run_pip_direct(pip_args):
68
97
  return result.returncode
69
98
 
70
99
 
100
+ def _run_pip_quiet(pip_args):
101
+ """Run pip without streaming routine dependency output to the terminal."""
102
+ result = subprocess.run(
103
+ _build_pip_command(pip_args),
104
+ capture_output=True,
105
+ text=True,
106
+ encoding="utf-8",
107
+ errors="replace",
108
+ )
109
+ if result.returncode != 0:
110
+ if result.stdout:
111
+ print(f"{GREEN}Output:\n{result.stdout.strip()}{NC}")
112
+ if result.stderr:
113
+ print(f"{RED}Error Output:\n{result.stderr.strip()}{NC}")
114
+ return result.returncode
115
+
116
+
71
117
  def _build_windows_detached_command(pip_args):
72
118
  pip_command = subprocess.list2cmdline(_build_pip_command(pip_args))
73
119
  delayed_command = f"timeout /t 2 /nobreak > nul & {pip_command}"
@@ -158,12 +204,24 @@ def upgrade_fdev_command(argv=None):
158
204
 
159
205
  pip_args = ["install", "--upgrade", PACKAGE_NAME]
160
206
  print(f"{BLUE}Upgrade source: {GREEN}PyPI{NC}")
161
- print(f"{YELLOW}Upgrading {PACKAGE_NAME} from PyPI...{NC}")
207
+ latest_version = _get_latest_pypi_version()
208
+
209
+ if latest_version == current_version:
210
+ print(f"{GREEN}✓ Already up to date: {current_version}{NC}")
211
+ return 0
212
+
213
+ if latest_version:
214
+ print(
215
+ f"{YELLOW}Upgrading {PACKAGE_NAME}: "
216
+ f"{current_version} → {latest_version}...{NC}"
217
+ )
218
+ else:
219
+ print(f"{YELLOW}Could not verify the latest PyPI version; checking with pip...{NC}")
162
220
 
163
221
  if os_key == "windows":
164
222
  return _run_windows_detached(pip_args, "Upgrade")
165
223
 
166
- result = _run_pip_direct(pip_args)
224
+ result = _run_pip_quiet(pip_args)
167
225
  if result == 0:
168
226
  installed_version, installed_location = _get_installed_package_info()
169
227
  if current_version != installed_version:
@@ -171,14 +229,20 @@ def upgrade_fdev_command(argv=None):
171
229
  f"{GREEN}✓ {PACKAGE_NAME} upgraded successfully: "
172
230
  f"{current_version} → {installed_version}.{NC}"
173
231
  )
174
- else:
232
+ if installed_location != package_location:
233
+ print(f"{BLUE}Installed at: {GREEN}{installed_location}{NC}")
234
+ print(f"{BLUE}Restart your terminal if the fdev command still uses the old version.{NC}")
235
+ return 0
236
+
237
+ if latest_version and latest_version != installed_version:
175
238
  print(
176
- f"{GREEN} {PACKAGE_NAME} upgrade completed. "
177
- f"Installed version: {installed_version}.{NC}"
239
+ f"{RED} Upgrade did not change the installed version. "
240
+ f"Installed: {installed_version}; PyPI: {latest_version}.{NC}"
178
241
  )
179
- if installed_location != package_location:
180
- print(f"{BLUE}Installed at: {GREEN}{installed_location}{NC}")
181
- print(f"{BLUE}Restart your terminal if the fdev command still uses the old version.{NC}")
182
- else:
183
- print(f"{RED}✗ Failed to upgrade {PACKAGE_NAME}.{NC}")
242
+ return 1
243
+
244
+ print(f"{GREEN} Already up to date: {installed_version}{NC}")
245
+ return 0
246
+
247
+ print(f"{RED}✗ Failed to upgrade {PACKAGE_NAME}.{NC}")
184
248
  return result
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "flutter-dev"
7
- version = "0.1.12"
7
+ version = "0.1.13"
8
8
  description = "A cross-platform CLI toolkit for Flutter development workflows."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.8"
@@ -26,6 +26,26 @@ class FdevCliTests(unittest.TestCase):
26
26
  self.assertEqual(result, 0)
27
27
  show_usage.assert_called_once_with(exit_code=0)
28
28
 
29
+ def test_short_version_flag_prints_installed_version(self):
30
+ with (
31
+ patch.object(sys, "argv", ["fdev", "-v"]),
32
+ patch.object(fdev, "show_fdev_version", return_value=0) as show_version,
33
+ ):
34
+ result = fdev.main()
35
+
36
+ self.assertEqual(result, 0)
37
+ show_version.assert_called_once_with()
38
+
39
+ def test_long_version_flag_prints_installed_version(self):
40
+ with (
41
+ patch.object(sys, "argv", ["fdev", "--version"]),
42
+ patch.object(fdev, "show_fdev_version", return_value=0) as show_version,
43
+ ):
44
+ result = fdev.main()
45
+
46
+ self.assertEqual(result, 0)
47
+ show_version.assert_called_once_with()
48
+
29
49
  def test_unknown_command_prints_usage_and_exits_with_error(self):
30
50
  with (
31
51
  patch.object(sys, "argv", ["fdev", "unknown"]),
@@ -2,7 +2,7 @@ import io
2
2
  import subprocess
3
3
  import unittest
4
4
  from contextlib import redirect_stdout
5
- from unittest.mock import patch
5
+ from unittest.mock import Mock, patch
6
6
 
7
7
  from managers import package
8
8
 
@@ -38,23 +38,96 @@ class PackageCommandTests(unittest.TestCase):
38
38
  run.assert_not_called()
39
39
 
40
40
  def test_upgrade_runs_pip_upgrade_in_current_python_environment(self):
41
+ with (
42
+ patch.object(package.platform, "system", return_value="Linux"),
43
+ patch.object(package.sys, "executable", "/venv/bin/python"),
44
+ patch.object(package, "_get_latest_pypi_version", return_value="0.1.13"),
45
+ patch.object(
46
+ package,
47
+ "_get_installed_package_info",
48
+ side_effect=[
49
+ ("0.1.12", "/venv/lib/python/site-packages"),
50
+ ("0.1.13", "/venv/lib/python/site-packages"),
51
+ ],
52
+ ),
53
+ patch.object(package, "_run_pip_quiet", return_value=0) as run,
54
+ ):
55
+ result = package.upgrade_fdev_command([])
56
+
57
+ self.assertEqual(result, 0)
58
+ run.assert_called_once_with(["install", "--upgrade", "flutter-dev"])
59
+
60
+ def test_upgrade_skips_pip_when_already_up_to_date(self):
61
+ output = io.StringIO()
62
+
63
+ with (
64
+ patch.object(package.platform, "system", return_value="Linux"),
65
+ patch.object(
66
+ package,
67
+ "_get_installed_package_info",
68
+ return_value=("0.1.12", "/venv/lib/python/site-packages"),
69
+ ),
70
+ patch.object(package, "_get_latest_pypi_version", return_value="0.1.12"),
71
+ patch.object(package, "_run_pip_quiet") as run,
72
+ redirect_stdout(output),
73
+ ):
74
+ result = package.upgrade_fdev_command([])
75
+
76
+ self.assertEqual(result, 0)
77
+ run.assert_not_called()
78
+ self.assertIn("✓ Already up to date: 0.1.12", output.getvalue())
79
+
80
+ def test_quiet_pip_hides_routine_success_output(self):
41
81
  completed = subprocess.CompletedProcess(
42
82
  ["/venv/bin/python", "-m", "pip", "install", "--upgrade", "flutter-dev"],
43
83
  0,
84
+ stdout="Requirement already satisfied: flutter-dev (0.1.12)\n",
85
+ stderr="",
44
86
  )
87
+ output = io.StringIO()
45
88
 
46
89
  with (
47
- patch.object(package.platform, "system", return_value="Linux"),
48
90
  patch.object(package.sys, "executable", "/venv/bin/python"),
49
91
  patch.object(package.subprocess, "run", return_value=completed) as run,
92
+ redirect_stdout(output),
50
93
  ):
51
- result = package.upgrade_fdev_command([])
94
+ result = package._run_pip_quiet(["install", "--upgrade", "flutter-dev"])
52
95
 
53
96
  self.assertEqual(result, 0)
97
+ self.assertEqual(output.getvalue(), "")
54
98
  run.assert_called_once_with(
55
- ["/venv/bin/python", "-m", "pip", "install", "--upgrade", "flutter-dev"]
99
+ ["/venv/bin/python", "-m", "pip", "install", "--upgrade", "flutter-dev"],
100
+ capture_output=True,
101
+ text=True,
102
+ encoding="utf-8",
103
+ errors="replace",
56
104
  )
57
105
 
106
+ def test_latest_pypi_version_uses_package_json_metadata(self):
107
+ response = Mock()
108
+ response.json.return_value = {"info": {"version": "0.1.13"}}
109
+
110
+ with patch.object(package.requests, "get", return_value=response) as get:
111
+ version = package._get_latest_pypi_version()
112
+
113
+ self.assertEqual(version, "0.1.13")
114
+ response.raise_for_status.assert_called_once_with()
115
+ get.assert_called_once_with(
116
+ package.PYPI_JSON_URL,
117
+ headers={"Accept": "application/json"},
118
+ timeout=10,
119
+ )
120
+
121
+ def test_latest_pypi_version_returns_none_when_lookup_fails(self):
122
+ with patch.object(
123
+ package.requests,
124
+ "get",
125
+ side_effect=package.requests.RequestException("offline"),
126
+ ):
127
+ version = package._get_latest_pypi_version()
128
+
129
+ self.assertIsNone(version)
130
+
58
131
  def test_windows_delete_schedules_detached_uninstall(self):
59
132
  with (
60
133
  patch.object(package.platform, "system", return_value="Windows"),
@@ -100,16 +173,17 @@ class PackageCommandTests(unittest.TestCase):
100
173
  )
101
174
 
102
175
  def test_upgrade_prints_target_python_environment(self):
103
- completed = subprocess.CompletedProcess(
104
- ["/home/user/project/.venv/bin/python", "-m", "pip", "install", "--upgrade", "flutter-dev"],
105
- 0,
106
- )
107
176
  output = io.StringIO()
108
177
 
109
178
  with (
110
179
  patch.object(package.platform, "system", return_value="Linux"),
111
180
  patch.object(package.sys, "executable", "/home/user/project/.venv/bin/python"),
112
- patch.object(package.subprocess, "run", return_value=completed),
181
+ patch.object(
182
+ package,
183
+ "_get_installed_package_info",
184
+ return_value=("0.1.12", "/home/user/project/.venv/lib/python/site-packages"),
185
+ ),
186
+ patch.object(package, "_get_latest_pypi_version", return_value="0.1.12"),
113
187
  redirect_stdout(output),
114
188
  ):
115
189
  result = package.upgrade_fdev_command([])
@@ -118,6 +192,48 @@ class PackageCommandTests(unittest.TestCase):
118
192
  self.assertIn("Python environment:", output.getvalue())
119
193
  self.assertIn("/home/user/project/.venv/bin/python", output.getvalue())
120
194
 
195
+ def test_successful_upgrade_prints_before_and_after_versions(self):
196
+ output = io.StringIO()
197
+
198
+ with (
199
+ patch.object(package.platform, "system", return_value="Linux"),
200
+ patch.object(
201
+ package,
202
+ "_get_installed_package_info",
203
+ side_effect=[
204
+ ("0.1.12", "/venv/lib/python/site-packages"),
205
+ ("0.1.13", "/venv/lib/python/site-packages"),
206
+ ],
207
+ ),
208
+ patch.object(package, "_get_latest_pypi_version", return_value="0.1.13"),
209
+ patch.object(package, "_run_pip_quiet", return_value=0),
210
+ redirect_stdout(output),
211
+ ):
212
+ result = package.upgrade_fdev_command([])
213
+
214
+ self.assertEqual(result, 0)
215
+ self.assertIn("0.1.12 → 0.1.13", output.getvalue())
216
+ self.assertIn(
217
+ "Restart your terminal if the fdev command still uses the old version.",
218
+ output.getvalue(),
219
+ )
220
+
221
+ def test_show_fdev_version_prints_installed_version(self):
222
+ output = io.StringIO()
223
+
224
+ with (
225
+ patch.object(
226
+ package,
227
+ "_get_installed_package_info",
228
+ return_value=("0.1.13", "/venv/lib/python/site-packages"),
229
+ ),
230
+ redirect_stdout(output),
231
+ ):
232
+ result = package.show_fdev_version()
233
+
234
+ self.assertEqual(result, 0)
235
+ self.assertEqual(output.getvalue().strip(), "fdev 0.1.13")
236
+
121
237
  def test_command_help_returns_zero(self):
122
238
  with self.assertRaises(SystemExit) as raised:
123
239
  package.delete_fdev_command(["--help"])
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes