flutter-setup 2.1.0__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.
@@ -0,0 +1,140 @@
1
+ """Linux prerequisites management for Flutter setup."""
2
+
3
+ import shutil
4
+ import subprocess
5
+
6
+ from rich.console import Console
7
+
8
+ from .config import Config
9
+ from .exceptions import PrerequisitesError
10
+
11
+ console = Console()
12
+
13
+ # Core system utilities
14
+ CORE_PACKAGES = [
15
+ "git",
16
+ "curl",
17
+ "unzip",
18
+ "xz-utils",
19
+ "zip",
20
+ ]
21
+
22
+ # Linux desktop development requirements
23
+ LINUX_DESKTOP_PACKAGES = [
24
+ "libglu1-mesa",
25
+ "clang",
26
+ "cmake",
27
+ "ninja-build",
28
+ "pkg-config",
29
+ "libgtk-3-dev",
30
+ "libayatana-appindicator3-dev",
31
+ "liblzma-dev",
32
+ ]
33
+
34
+ # Android development requirements
35
+ ANDROID_PACKAGES = [
36
+ "openjdk-17-jdk",
37
+ ]
38
+
39
+
40
+ class LinuxPrerequisites:
41
+ """Manages Linux prerequisites for Flutter development."""
42
+
43
+ def __init__(self, config: Config):
44
+ """Initialize Linux prerequisites manager."""
45
+ self.config = config
46
+ self._check_package_manager()
47
+
48
+ def _check_package_manager(self) -> None:
49
+ """Ensure we are on a supported Debian-based system with APT."""
50
+ if not shutil.which("apt-get") or not shutil.which("dpkg"):
51
+ raise PrerequisitesError(
52
+ "Unsupported Linux distribution. Only Debian-based distributions (using APT) are currently supported for automated prerequisite installation."
53
+ )
54
+
55
+ def check_and_install(self) -> None:
56
+ """Check and install Linux prerequisites."""
57
+ if self.config.dry_run:
58
+ console.print(
59
+ "[yellow]DRY RUN: Would check and install Linux prerequisites[/yellow]"
60
+ )
61
+ console.print(
62
+ f"[yellow]DRY RUN: Would run: {self.install_command()}[/yellow]"
63
+ )
64
+ return
65
+
66
+ missing = self._missing_packages()
67
+ if missing:
68
+ console.print(f" πŸ“¦ Missing Linux packages: {', '.join(missing)}")
69
+ console.print(" πŸ”§ Installing Linux prerequisites via APT...")
70
+ try:
71
+ subprocess.run(["sudo", "apt-get", "update"], check=True)
72
+ subprocess.run(
73
+ ["sudo", "apt-get", "install", "-y", *missing],
74
+ check=True,
75
+ )
76
+ console.print(" βœ… Linux prerequisites installed")
77
+ except subprocess.CalledProcessError as e:
78
+ raise PrerequisitesError(f"Failed to install Linux prerequisites: {e}")
79
+ else:
80
+ console.print(" βœ… Linux prerequisites already installed")
81
+
82
+ if "android" in self.config.platforms:
83
+ self._setup_android_tools()
84
+
85
+ def _setup_android_tools(self) -> None:
86
+ """Additional Android toolchain setup instructions."""
87
+ console.print(" πŸ€– Android JDK installed (openjdk-17-jdk)")
88
+ console.print(
89
+ " ℹ️ Note: You may still need to install Android Command Line Tools manually"
90
+ )
91
+ console.print(
92
+ " ℹ️ Download from: https://developer.android.com/studio#command-tools"
93
+ )
94
+
95
+ def _get_required_packages(self) -> list[str]:
96
+ """Get the full list of required packages based on target platforms."""
97
+ packages = list(CORE_PACKAGES)
98
+
99
+ if "linux" in self.config.platforms:
100
+ packages.extend(LINUX_DESKTOP_PACKAGES)
101
+
102
+ if "android" in self.config.platforms:
103
+ packages.extend(ANDROID_PACKAGES)
104
+
105
+ return sorted(list(set(packages)))
106
+
107
+ def install_command(self) -> str:
108
+ """Return the APT command users can run manually."""
109
+ packages = self._get_required_packages()
110
+ return f"sudo apt-get update && sudo apt-get install -y {' '.join(packages)}"
111
+
112
+ def _missing_packages(self) -> list[str]:
113
+ """Return missing APT packages."""
114
+ required = self._get_required_packages()
115
+ missing: list[str] = []
116
+ for package in required:
117
+ if not self._is_package_installed(package):
118
+ missing.append(package)
119
+ return missing
120
+
121
+ def _is_package_installed(self, package: str) -> bool:
122
+ """Check whether a package is installed via dpkg."""
123
+ result = subprocess.run(
124
+ ["dpkg", "-s", package],
125
+ capture_output=True,
126
+ text=True,
127
+ check=False,
128
+ )
129
+ return result.returncode == 0
130
+
131
+ def check_only(self) -> bool:
132
+ """Check Linux prerequisites without installing."""
133
+ missing = self._missing_packages()
134
+ if not missing:
135
+ console.print(" βœ… Linux prerequisites found")
136
+ return True
137
+
138
+ console.print(f" ❌ Missing Linux prerequisites: {', '.join(missing)}")
139
+ console.print(f" ℹ️ Install with: {self.install_command()}")
140
+ return False
@@ -0,0 +1,226 @@
1
+ """macOS prerequisites management for Flutter setup."""
2
+
3
+ import subprocess
4
+ from pathlib import Path
5
+
6
+ from rich.console import Console
7
+
8
+ from .config import Config
9
+ from .exceptions import PrerequisitesError
10
+
11
+ console = Console()
12
+
13
+
14
+ class MacOSPrerequisites:
15
+ """Manages macOS prerequisites for Flutter development."""
16
+
17
+ def __init__(self, config: Config):
18
+ """Initialize macOS prerequisites manager."""
19
+ self.config = config
20
+ self.home = Path.home()
21
+
22
+ def check_and_install(self) -> None:
23
+ """Check and install all required prerequisites."""
24
+ if self.config.dry_run:
25
+ console.print(
26
+ "[yellow]DRY RUN: Would check and install macOS prerequisites[/yellow]"
27
+ )
28
+ return
29
+
30
+ self._check_xcode_tools()
31
+ self._check_homebrew()
32
+ self._install_packages()
33
+ self._setup_platform_tools()
34
+
35
+ def _check_xcode_tools(self) -> None:
36
+ """Check and install Xcode Command Line Tools."""
37
+ console.print(" πŸ“± Checking Xcode Command Line Tools...")
38
+
39
+ try:
40
+ result = subprocess.run(
41
+ ["xcode-select", "-p"], capture_output=True, text=True, check=False
42
+ )
43
+
44
+ if result.returncode != 0:
45
+ console.print(" ⚠️ Xcode Command Line Tools not found, installing...")
46
+ subprocess.run(["xcode-select", "--install"], check=True)
47
+ console.print(" βœ… Xcode Command Line Tools installation initiated")
48
+ console.print(
49
+ " ℹ️ Please complete the installation in the popup window"
50
+ )
51
+ console.print(
52
+ " ℹ️ You may need to restart the setup after installation"
53
+ )
54
+ raise PrerequisitesError(
55
+ "Xcode Command Line Tools installation required"
56
+ )
57
+
58
+ console.print(" βœ… Xcode Command Line Tools found")
59
+ except subprocess.CalledProcessError as e:
60
+ raise PrerequisitesError(f"Failed to check Xcode tools: {e}")
61
+
62
+ def _check_homebrew(self) -> None:
63
+ """Check and install Homebrew."""
64
+ console.print(" 🍺 Checking Homebrew...")
65
+
66
+ try:
67
+ result = subprocess.run(
68
+ ["brew", "--version"], capture_output=True, text=True, check=False
69
+ )
70
+
71
+ if result.returncode != 0:
72
+ console.print(" ⚠️ Homebrew not found, installing...")
73
+ self._install_homebrew()
74
+ else:
75
+ console.print(" βœ… Homebrew found")
76
+ self._ensure_homebrew_path()
77
+ except subprocess.CalledProcessError as e:
78
+ raise PrerequisitesError(f"Failed to check Homebrew: {e}")
79
+
80
+ def _install_homebrew(self) -> None:
81
+ """Install Homebrew."""
82
+ try:
83
+ install_script = (
84
+ "https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh"
85
+ )
86
+ subprocess.run(
87
+ ["/bin/bash", "-c", f'curl -fsSL "{install_script}" | bash'],
88
+ env={"NONINTERACTIVE": "1"},
89
+ check=True,
90
+ )
91
+ console.print(" βœ… Homebrew installed")
92
+ self._ensure_homebrew_path()
93
+ except subprocess.CalledProcessError as e:
94
+ raise PrerequisitesError(f"Failed to install Homebrew: {e}")
95
+
96
+ def _ensure_homebrew_path(self) -> None:
97
+ """Ensure Homebrew is in PATH."""
98
+ try:
99
+ if Path("/opt/homebrew/bin/brew").exists():
100
+ subprocess.run(["/opt/homebrew/bin/brew", "shellenv"], check=True)
101
+ console.print(" βœ… Homebrew path configured")
102
+ except subprocess.CalledProcessError:
103
+ console.print(
104
+ " ⚠️ Homebrew path configuration failed (may need manual setup)"
105
+ )
106
+
107
+ def _install_packages(self) -> None:
108
+ """Install required packages via Homebrew."""
109
+ required_packages = ["git", "cocoapods"]
110
+
111
+ for package in required_packages:
112
+ console.print(f" πŸ“¦ Installing {package}...")
113
+ try:
114
+ subprocess.run(
115
+ ["brew", "install", package], check=True, capture_output=True
116
+ )
117
+ console.print(f" βœ… {package} installed")
118
+ except subprocess.CalledProcessError as e:
119
+ result = subprocess.run(
120
+ ["brew", "list", package],
121
+ capture_output=True,
122
+ text=True,
123
+ check=False,
124
+ )
125
+ if result.returncode == 0:
126
+ console.print(f" βœ… {package} already installed")
127
+ else:
128
+ raise PrerequisitesError(f"Failed to install {package}: {e}")
129
+
130
+ def _setup_platform_tools(self) -> None:
131
+ """Setup platform-specific development tools."""
132
+ if "android" in self.config.platforms:
133
+ self._setup_android_tools()
134
+ if "ios" in self.config.platforms:
135
+ self._setup_ios_tools()
136
+
137
+ def _setup_android_tools(self) -> None:
138
+ """Setup Android development tools."""
139
+ console.print(" πŸ€– Setting up Android development tools...")
140
+
141
+ android_packages = [
142
+ ("--cask", "temurin"),
143
+ ("--cask", "android-commandlinetools"),
144
+ ]
145
+
146
+ for args in android_packages:
147
+ package = args[1]
148
+ try:
149
+ subprocess.run(
150
+ ["brew", "install"] + list(args), check=True, capture_output=True
151
+ )
152
+ console.print(f" βœ… {package} installed")
153
+ except subprocess.CalledProcessError as e:
154
+ result = subprocess.run(
155
+ ["brew", "list", "--cask", package],
156
+ capture_output=True,
157
+ text=True,
158
+ check=False,
159
+ )
160
+ if result.returncode == 0:
161
+ console.print(f" βœ… {package} already installed")
162
+ else:
163
+ console.print(f" ⚠️ Failed to install {package}: {e}")
164
+
165
+ def _setup_ios_tools(self) -> None:
166
+ """Setup iOS development tools."""
167
+ console.print(" 🍎 Setting up iOS development tools...")
168
+
169
+ try:
170
+ subprocess.run(["pod", "repo", "update"], check=False, capture_output=True)
171
+ console.print(" βœ… iOS tools configured")
172
+ except Exception as e:
173
+ console.print(f" ⚠️ iOS tools configuration warning: {e}")
174
+
175
+ def check_only(self) -> bool:
176
+ """Check prerequisites without installing."""
177
+ all_ok = True
178
+
179
+ console.print(" πŸ“± Checking Xcode Command Line Tools...")
180
+ try:
181
+ result = subprocess.run(
182
+ ["xcode-select", "-p"], capture_output=True, text=True, check=False
183
+ )
184
+ if result.returncode == 0:
185
+ console.print(" βœ… Xcode Command Line Tools found")
186
+ else:
187
+ console.print(" ❌ Xcode Command Line Tools not found")
188
+ all_ok = False
189
+ except Exception as e:
190
+ console.print(f" ❌ Failed to check Xcode tools: {e}")
191
+ all_ok = False
192
+
193
+ console.print(" 🍺 Checking Homebrew...")
194
+ try:
195
+ result = subprocess.run(
196
+ ["brew", "--version"], capture_output=True, text=True, check=False
197
+ )
198
+ if result.returncode == 0:
199
+ console.print(" βœ… Homebrew found")
200
+ else:
201
+ console.print(" ❌ Homebrew not found")
202
+ all_ok = False
203
+ except Exception as e:
204
+ console.print(f" ❌ Failed to check Homebrew: {e}")
205
+ all_ok = False
206
+
207
+ required_packages = ["git", "cocoapods"]
208
+ for package in required_packages:
209
+ console.print(f" πŸ“¦ Checking {package}...")
210
+ try:
211
+ result = subprocess.run(
212
+ ["brew", "list", package],
213
+ capture_output=True,
214
+ text=True,
215
+ check=False,
216
+ )
217
+ if result.returncode == 0:
218
+ console.print(f" βœ… {package} installed")
219
+ else:
220
+ console.print(f" ❌ {package} not installed")
221
+ all_ok = False
222
+ except Exception as e:
223
+ console.print(f" ❌ Failed to check {package}: {e}")
224
+ all_ok = False
225
+
226
+ return all_ok
@@ -0,0 +1,82 @@
1
+ """Project creation for Flutter setup."""
2
+
3
+ import subprocess
4
+ from typing import List
5
+
6
+ from rich.console import Console
7
+
8
+ from .config import Config
9
+ from .exceptions import ProjectCreationError
10
+
11
+ console = Console()
12
+
13
+
14
+ class ProjectCreator:
15
+ """Creates Flutter projects with specified configuration."""
16
+
17
+ def __init__(self, config: Config):
18
+ """Initialize ProjectCreator."""
19
+ self.config = config
20
+ self.flutter_root = config.flutter_location
21
+
22
+ def create_project(self) -> None:
23
+ """Create the Flutter project."""
24
+ if self.config.dry_run:
25
+ console.print("[yellow]DRY RUN: Would create Flutter project[/yellow]")
26
+ return
27
+
28
+ # Check if project already exists
29
+ if self.config.project_path.exists():
30
+ console.print(
31
+ f" ⚠️ Directory '{self.config.project_path}' existsβ€”skipping create."
32
+ )
33
+ return
34
+
35
+ # Create output directory
36
+ self.config.output_dir.mkdir(parents=True, exist_ok=True)
37
+
38
+ # Build flutter create command
39
+ create_cmd = self._build_create_command()
40
+
41
+ # Execute flutter create
42
+ console.print(
43
+ f" πŸ—οΈ Creating Flutter project at {self.config.project_path}..."
44
+ )
45
+
46
+ try:
47
+ subprocess.run(create_cmd, check=True, capture_output=True, text=True)
48
+ console.print(f" βœ… Project created at: {self.config.project_path}")
49
+
50
+ except subprocess.CalledProcessError as e:
51
+ raise ProjectCreationError(f"Failed to create project: {e}")
52
+
53
+ def _build_create_command(self) -> List[str]:
54
+ """Build the flutter create command."""
55
+ cmd = [
56
+ str(self.flutter_root / "bin" / "flutter"),
57
+ "create",
58
+ "--org",
59
+ self.config.org,
60
+ "--project-name",
61
+ self.config.package_name,
62
+ "--platforms",
63
+ self.config.platforms_csv,
64
+ "--template",
65
+ self.config.template,
66
+ ]
67
+
68
+ # Add template-specific options
69
+ if self.config.template == "plugin":
70
+ cmd.extend(
71
+ [
72
+ "--ios-language",
73
+ self.config.ios_language,
74
+ "--android-language",
75
+ self.config.android_language,
76
+ ]
77
+ )
78
+
79
+ # Add output path
80
+ cmd.append(str(self.config.project_path))
81
+
82
+ return cmd