pixi-ros 0.1.2__tar.gz → 0.2.0__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.
- {pixi_ros-0.1.2 → pixi_ros-0.2.0}/.github/workflows/ci.yml +2 -0
- {pixi_ros-0.1.2 → pixi_ros-0.2.0}/PKG-INFO +86 -6
- {pixi_ros-0.1.2 → pixi_ros-0.2.0}/README.md +85 -5
- {pixi_ros-0.1.2 → pixi_ros-0.2.0}/pyproject.toml +1 -1
- pixi_ros-0.2.0/src/pixi_ros/cli.py +134 -0
- {pixi_ros-0.1.2 → pixi_ros-0.2.0}/src/pixi_ros/init.py +273 -66
- {pixi_ros-0.1.2 → pixi_ros-0.2.0}/src/pixi_ros/mappings.py +35 -0
- pixi_ros-0.2.0/tests/test_init.py +366 -0
- pixi_ros-0.1.2/src/pixi_ros/cli.py +0 -77
- pixi_ros-0.1.2/tests/test_init.py +0 -144
- {pixi_ros-0.1.2 → pixi_ros-0.2.0}/.gitattributes +0 -0
- {pixi_ros-0.1.2 → pixi_ros-0.2.0}/.github/workflows/publish-pypi.yml +0 -0
- {pixi_ros-0.1.2 → pixi_ros-0.2.0}/.gitignore +0 -0
- {pixi_ros-0.1.2 → pixi_ros-0.2.0}/LICENSE +0 -0
- {pixi_ros-0.1.2 → pixi_ros-0.2.0}/pixi.lock +0 -0
- {pixi_ros-0.1.2 → pixi_ros-0.2.0}/pixi.toml +0 -0
- {pixi_ros-0.1.2 → pixi_ros-0.2.0}/src/pixi_ros/__init__.py +0 -0
- {pixi_ros-0.1.2 → pixi_ros-0.2.0}/src/pixi_ros/config.py +0 -0
- {pixi_ros-0.1.2 → pixi_ros-0.2.0}/src/pixi_ros/data/README.md +0 -0
- {pixi_ros-0.1.2 → pixi_ros-0.2.0}/src/pixi_ros/data/README_PIXI.md.template +0 -0
- {pixi_ros-0.1.2 → pixi_ros-0.2.0}/src/pixi_ros/data/conda-forge.yaml +0 -0
- {pixi_ros-0.1.2 → pixi_ros-0.2.0}/src/pixi_ros/package_xml.py +0 -0
- {pixi_ros-0.1.2 → pixi_ros-0.2.0}/src/pixi_ros/utils.py +0 -0
- {pixi_ros-0.1.2 → pixi_ros-0.2.0}/src/pixi_ros/workspace.py +0 -0
- {pixi_ros-0.1.2 → pixi_ros-0.2.0}/tests/examples/ws1/pixi.lock +0 -0
- {pixi_ros-0.1.2 → pixi_ros-0.2.0}/tests/examples/ws1/pixi.toml +0 -0
- {pixi_ros-0.1.2 → pixi_ros-0.2.0}/tests/examples/ws1/src/package-a/CMakeLists.txt +0 -0
- {pixi_ros-0.1.2 → pixi_ros-0.2.0}/tests/examples/ws1/src/package-a/LICENSE +0 -0
- {pixi_ros-0.1.2 → pixi_ros-0.2.0}/tests/examples/ws1/src/package-a/package.xml +0 -0
- {pixi_ros-0.1.2 → pixi_ros-0.2.0}/tests/examples/ws1/src/package-b/package-b/__init__.py +0 -0
- {pixi_ros-0.1.2 → pixi_ros-0.2.0}/tests/examples/ws1/src/package-b/package.xml +0 -0
- {pixi_ros-0.1.2 → pixi_ros-0.2.0}/tests/examples/ws1/src/package-b/setup.cfg +0 -0
- {pixi_ros-0.1.2 → pixi_ros-0.2.0}/tests/examples/ws1/src/package-b/setup.py +0 -0
- {pixi_ros-0.1.2 → pixi_ros-0.2.0}/tests/examples/ws1/src/package-b/test/test_copyright.py +0 -0
- {pixi_ros-0.1.2 → pixi_ros-0.2.0}/tests/examples/ws1/src/package-b/test/test_flake8.py +0 -0
- {pixi_ros-0.1.2 → pixi_ros-0.2.0}/tests/examples/ws1/src/package-b/test/test_pep257.py +0 -0
- {pixi_ros-0.1.2 → pixi_ros-0.2.0}/tests/fixtures/mock_workspace/README.md +0 -0
- {pixi_ros-0.1.2 → pixi_ros-0.2.0}/tests/fixtures/mock_workspace/src/legacy_pkg/package.xml +0 -0
- {pixi_ros-0.1.2 → pixi_ros-0.2.0}/tests/fixtures/mock_workspace/src/my_cpp_pkg/CMakeLists.txt +0 -0
- {pixi_ros-0.1.2 → pixi_ros-0.2.0}/tests/fixtures/mock_workspace/src/my_cpp_pkg/package.xml +0 -0
- {pixi_ros-0.1.2 → pixi_ros-0.2.0}/tests/fixtures/mock_workspace/src/my_mixed_pkg/package.xml +0 -0
- {pixi_ros-0.1.2 → pixi_ros-0.2.0}/tests/fixtures/mock_workspace/src/my_python_pkg/package.xml +0 -0
- {pixi_ros-0.1.2 → pixi_ros-0.2.0}/tests/fixtures/mock_workspace/src/my_python_pkg/setup.py +0 -0
- {pixi_ros-0.1.2 → pixi_ros-0.2.0}/tests/test_cli.py +0 -0
- {pixi_ros-0.1.2 → pixi_ros-0.2.0}/tests/test_config.py +0 -0
- {pixi_ros-0.1.2 → pixi_ros-0.2.0}/tests/test_gateway_availability.py +0 -0
- {pixi_ros-0.1.2 → pixi_ros-0.2.0}/tests/test_mappings.py +0 -0
- {pixi_ros-0.1.2 → pixi_ros-0.2.0}/tests/test_package_xml.py +0 -0
- {pixi_ros-0.1.2 → pixi_ros-0.2.0}/tests/test_utils.py +0 -0
- {pixi_ros-0.1.2 → pixi_ros-0.2.0}/tests/test_workspace.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pixi-ros
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0
|
|
4
4
|
Summary: Pixi extension for ROS package management
|
|
5
5
|
Project-URL: Homepage, https://github.com/ruben-arts/pixi-ros
|
|
6
6
|
Project-URL: Repository, https://github.com/ruben-arts/pixi-ros
|
|
@@ -90,13 +90,16 @@ pixi shell
|
|
|
90
90
|
|
|
91
91
|
### Dependency Mapping
|
|
92
92
|
|
|
93
|
-
`pixi-ros` reads all dependency types from `package.xml` files.
|
|
93
|
+
`pixi-ros` reads all dependency types from `package.xml` files.
|
|
94
94
|
It then does a best effort mapping of ROS package names to conda packages.
|
|
95
95
|
|
|
96
96
|
- **ROS packages**: `ros-{distro}-{package}` from robostack channels (e.g., `ros-humble-rclcpp`)
|
|
97
97
|
- **System packages**: Mapped to conda-forge equivalents (e.g., `cmake`, `eigen`)
|
|
98
|
+
- **Platform-specific packages**: Different mappings per platform (e.g., OpenGL → `libgl-devel` on Linux, X11 packages on macOS)
|
|
98
99
|
|
|
99
|
-
|
|
100
|
+
The mapping rules are defined in YAML files (see `src/pixi_ros/data/conda-forge.yaml`) and can be customized by placing your own mapping files in `pixi-ros/*.yaml` or `~/.pixi-ros/*.yaml`.
|
|
101
|
+
|
|
102
|
+
After the mapping, it validates package availability in the configured channels for each target platform. This starts a connection with `https://prefix.dev` to check if packages exist.
|
|
100
103
|
|
|
101
104
|
### Example
|
|
102
105
|
|
|
@@ -132,24 +135,101 @@ Initialize or update a ROS workspace's `pixi.toml`.
|
|
|
132
135
|
|
|
133
136
|
```bash
|
|
134
137
|
pixi-ros init --distro <ros_distro>
|
|
138
|
+
pixi-ros init --distro humble --platform linux-64 --platform osx-arm64
|
|
135
139
|
pixi-ros init
|
|
136
140
|
```
|
|
137
141
|
|
|
138
142
|
**Options:**
|
|
139
|
-
- `--distro`, `-d`: ROS distribution (optional)
|
|
143
|
+
- `--distro`, `-d`: ROS distribution (optional, will prompt if not provided)
|
|
144
|
+
- `--platform`, `-p`: Target platforms (optional, can be specified multiple times, will prompt if not provided)
|
|
145
|
+
- Available: `linux-64`, `osx-64`, `osx-arm64`, `win-64`
|
|
146
|
+
- Platforms come from the mapping files and determine which dependencies are available
|
|
140
147
|
|
|
141
148
|
**What it does:**
|
|
142
149
|
- Scans workspace for `package.xml` files
|
|
143
150
|
- Reads all dependency types (build, exec, test)
|
|
144
|
-
- Maps ROS dependencies to conda packages
|
|
151
|
+
- Maps ROS dependencies to conda packages for each platform
|
|
145
152
|
- Configures robostack channels
|
|
146
|
-
- Checks package availability
|
|
153
|
+
- Checks package availability per platform
|
|
147
154
|
- Creates build tasks using colcon
|
|
148
155
|
- Generates helpful `README_PIXI.md`
|
|
156
|
+
- Sets up platform-specific dependencies in `pixi.toml`
|
|
149
157
|
|
|
150
158
|
**Running multiple times:**
|
|
151
159
|
The command is idempotent - you can run it multiple times to update dependencies as your workspace changes.
|
|
152
160
|
|
|
161
|
+
## Multi-Platform Support
|
|
162
|
+
|
|
163
|
+
`pixi-ros` supports generating cross-platform configurations. When you specify multiple platforms, it:
|
|
164
|
+
|
|
165
|
+
1. **Analyzes dependencies per platform**: Some packages have platform-specific mappings (e.g., OpenGL requirements differ between Linux and macOS)
|
|
166
|
+
|
|
167
|
+
2. **Organizes dependencies intelligently**:
|
|
168
|
+
- **Common dependencies** (available on all platforms) → `[dependencies]`
|
|
169
|
+
- **Unix dependencies** (available on Linux and macOS, but not Windows) → `[target.unix.dependencies]`
|
|
170
|
+
- **Platform-specific dependencies** → `[target.linux.dependencies]`, `[target.osx.dependencies]`, etc.
|
|
171
|
+
|
|
172
|
+
3. **Sets up correct platform list**: The `[workspace]` section gets the appropriate pixi platform names
|
|
173
|
+
|
|
174
|
+
### Platform Naming
|
|
175
|
+
|
|
176
|
+
pixi-ros uses standard pixi platform names:
|
|
177
|
+
- `linux-64` - Linux x86_64
|
|
178
|
+
- `osx-64` - macOS Intel
|
|
179
|
+
- `osx-arm64` - macOS Apple Silicon (M1/M2/M3)
|
|
180
|
+
- `win-64` - Windows x86_64
|
|
181
|
+
|
|
182
|
+
Internally, mapping files use a simplified format (`linux`, `osx`, `win64`), but this is transparent to users. When you specify `osx-64` and `osx-arm64`, they both use the same `osx` mapping rules since package availability is typically the same for both architectures.
|
|
183
|
+
|
|
184
|
+
### Example: Multi-Platform Setup
|
|
185
|
+
|
|
186
|
+
```bash
|
|
187
|
+
pixi-ros init --distro humble --platform linux-64 --platform osx-arm64
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
Generates:
|
|
191
|
+
|
|
192
|
+
```toml
|
|
193
|
+
[workspace]
|
|
194
|
+
name = "my_workspace"
|
|
195
|
+
channels = [
|
|
196
|
+
"https://prefix.dev/robostack-humble",
|
|
197
|
+
"https://prefix.dev/conda-forge",
|
|
198
|
+
]
|
|
199
|
+
platforms = ["linux-64", "osx-arm64"]
|
|
200
|
+
|
|
201
|
+
[dependencies]
|
|
202
|
+
# Common dependencies (available on all platforms)
|
|
203
|
+
ros-humble-rclcpp = "*"
|
|
204
|
+
ros-humble-std-msgs = "*"
|
|
205
|
+
|
|
206
|
+
[target.unix.dependencies]
|
|
207
|
+
# Unix-specific dependencies (Linux and macOS)
|
|
208
|
+
xorg-libx11 = "*"
|
|
209
|
+
xorg-libxext = "*"
|
|
210
|
+
|
|
211
|
+
[target.linux.dependencies]
|
|
212
|
+
# Linux-specific dependencies
|
|
213
|
+
libgl-devel = "*"
|
|
214
|
+
libopengl-devel = "*"
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
### Interactive Platform Selection
|
|
218
|
+
|
|
219
|
+
If you don't specify platforms, you'll be prompted:
|
|
220
|
+
|
|
221
|
+
```bash
|
|
222
|
+
$ pixi-ros init --distro humble
|
|
223
|
+
|
|
224
|
+
Available target platforms:
|
|
225
|
+
1. linux-64
|
|
226
|
+
2. osx-64
|
|
227
|
+
3. osx-arm64
|
|
228
|
+
4. win-64
|
|
229
|
+
|
|
230
|
+
Select platforms (enter numbers or names, comma or space separated): 1 3
|
|
231
|
+
```
|
|
232
|
+
|
|
153
233
|
## Philosophy
|
|
154
234
|
|
|
155
235
|
`pixi-ros` aims to be a quick **gateway drug**. It:
|
|
@@ -71,13 +71,16 @@ pixi shell
|
|
|
71
71
|
|
|
72
72
|
### Dependency Mapping
|
|
73
73
|
|
|
74
|
-
`pixi-ros` reads all dependency types from `package.xml` files.
|
|
74
|
+
`pixi-ros` reads all dependency types from `package.xml` files.
|
|
75
75
|
It then does a best effort mapping of ROS package names to conda packages.
|
|
76
76
|
|
|
77
77
|
- **ROS packages**: `ros-{distro}-{package}` from robostack channels (e.g., `ros-humble-rclcpp`)
|
|
78
78
|
- **System packages**: Mapped to conda-forge equivalents (e.g., `cmake`, `eigen`)
|
|
79
|
+
- **Platform-specific packages**: Different mappings per platform (e.g., OpenGL → `libgl-devel` on Linux, X11 packages on macOS)
|
|
79
80
|
|
|
80
|
-
|
|
81
|
+
The mapping rules are defined in YAML files (see `src/pixi_ros/data/conda-forge.yaml`) and can be customized by placing your own mapping files in `pixi-ros/*.yaml` or `~/.pixi-ros/*.yaml`.
|
|
82
|
+
|
|
83
|
+
After the mapping, it validates package availability in the configured channels for each target platform. This starts a connection with `https://prefix.dev` to check if packages exist.
|
|
81
84
|
|
|
82
85
|
### Example
|
|
83
86
|
|
|
@@ -113,24 +116,101 @@ Initialize or update a ROS workspace's `pixi.toml`.
|
|
|
113
116
|
|
|
114
117
|
```bash
|
|
115
118
|
pixi-ros init --distro <ros_distro>
|
|
119
|
+
pixi-ros init --distro humble --platform linux-64 --platform osx-arm64
|
|
116
120
|
pixi-ros init
|
|
117
121
|
```
|
|
118
122
|
|
|
119
123
|
**Options:**
|
|
120
|
-
- `--distro`, `-d`: ROS distribution (optional)
|
|
124
|
+
- `--distro`, `-d`: ROS distribution (optional, will prompt if not provided)
|
|
125
|
+
- `--platform`, `-p`: Target platforms (optional, can be specified multiple times, will prompt if not provided)
|
|
126
|
+
- Available: `linux-64`, `osx-64`, `osx-arm64`, `win-64`
|
|
127
|
+
- Platforms come from the mapping files and determine which dependencies are available
|
|
121
128
|
|
|
122
129
|
**What it does:**
|
|
123
130
|
- Scans workspace for `package.xml` files
|
|
124
131
|
- Reads all dependency types (build, exec, test)
|
|
125
|
-
- Maps ROS dependencies to conda packages
|
|
132
|
+
- Maps ROS dependencies to conda packages for each platform
|
|
126
133
|
- Configures robostack channels
|
|
127
|
-
- Checks package availability
|
|
134
|
+
- Checks package availability per platform
|
|
128
135
|
- Creates build tasks using colcon
|
|
129
136
|
- Generates helpful `README_PIXI.md`
|
|
137
|
+
- Sets up platform-specific dependencies in `pixi.toml`
|
|
130
138
|
|
|
131
139
|
**Running multiple times:**
|
|
132
140
|
The command is idempotent - you can run it multiple times to update dependencies as your workspace changes.
|
|
133
141
|
|
|
142
|
+
## Multi-Platform Support
|
|
143
|
+
|
|
144
|
+
`pixi-ros` supports generating cross-platform configurations. When you specify multiple platforms, it:
|
|
145
|
+
|
|
146
|
+
1. **Analyzes dependencies per platform**: Some packages have platform-specific mappings (e.g., OpenGL requirements differ between Linux and macOS)
|
|
147
|
+
|
|
148
|
+
2. **Organizes dependencies intelligently**:
|
|
149
|
+
- **Common dependencies** (available on all platforms) → `[dependencies]`
|
|
150
|
+
- **Unix dependencies** (available on Linux and macOS, but not Windows) → `[target.unix.dependencies]`
|
|
151
|
+
- **Platform-specific dependencies** → `[target.linux.dependencies]`, `[target.osx.dependencies]`, etc.
|
|
152
|
+
|
|
153
|
+
3. **Sets up correct platform list**: The `[workspace]` section gets the appropriate pixi platform names
|
|
154
|
+
|
|
155
|
+
### Platform Naming
|
|
156
|
+
|
|
157
|
+
pixi-ros uses standard pixi platform names:
|
|
158
|
+
- `linux-64` - Linux x86_64
|
|
159
|
+
- `osx-64` - macOS Intel
|
|
160
|
+
- `osx-arm64` - macOS Apple Silicon (M1/M2/M3)
|
|
161
|
+
- `win-64` - Windows x86_64
|
|
162
|
+
|
|
163
|
+
Internally, mapping files use a simplified format (`linux`, `osx`, `win64`), but this is transparent to users. When you specify `osx-64` and `osx-arm64`, they both use the same `osx` mapping rules since package availability is typically the same for both architectures.
|
|
164
|
+
|
|
165
|
+
### Example: Multi-Platform Setup
|
|
166
|
+
|
|
167
|
+
```bash
|
|
168
|
+
pixi-ros init --distro humble --platform linux-64 --platform osx-arm64
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
Generates:
|
|
172
|
+
|
|
173
|
+
```toml
|
|
174
|
+
[workspace]
|
|
175
|
+
name = "my_workspace"
|
|
176
|
+
channels = [
|
|
177
|
+
"https://prefix.dev/robostack-humble",
|
|
178
|
+
"https://prefix.dev/conda-forge",
|
|
179
|
+
]
|
|
180
|
+
platforms = ["linux-64", "osx-arm64"]
|
|
181
|
+
|
|
182
|
+
[dependencies]
|
|
183
|
+
# Common dependencies (available on all platforms)
|
|
184
|
+
ros-humble-rclcpp = "*"
|
|
185
|
+
ros-humble-std-msgs = "*"
|
|
186
|
+
|
|
187
|
+
[target.unix.dependencies]
|
|
188
|
+
# Unix-specific dependencies (Linux and macOS)
|
|
189
|
+
xorg-libx11 = "*"
|
|
190
|
+
xorg-libxext = "*"
|
|
191
|
+
|
|
192
|
+
[target.linux.dependencies]
|
|
193
|
+
# Linux-specific dependencies
|
|
194
|
+
libgl-devel = "*"
|
|
195
|
+
libopengl-devel = "*"
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### Interactive Platform Selection
|
|
199
|
+
|
|
200
|
+
If you don't specify platforms, you'll be prompted:
|
|
201
|
+
|
|
202
|
+
```bash
|
|
203
|
+
$ pixi-ros init --distro humble
|
|
204
|
+
|
|
205
|
+
Available target platforms:
|
|
206
|
+
1. linux-64
|
|
207
|
+
2. osx-64
|
|
208
|
+
3. osx-arm64
|
|
209
|
+
4. win-64
|
|
210
|
+
|
|
211
|
+
Select platforms (enter numbers or names, comma or space separated): 1 3
|
|
212
|
+
```
|
|
213
|
+
|
|
134
214
|
## Philosophy
|
|
135
215
|
|
|
136
216
|
`pixi-ros` aims to be a quick **gateway drug**. It:
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
"""Main CLI entry point for pixi-ros."""
|
|
2
|
+
|
|
3
|
+
from typing import Annotated
|
|
4
|
+
|
|
5
|
+
import typer
|
|
6
|
+
|
|
7
|
+
from pixi_ros.init import init_workspace
|
|
8
|
+
from pixi_ros.mappings import get_platforms, get_ros_distros
|
|
9
|
+
|
|
10
|
+
app = typer.Typer(
|
|
11
|
+
name="pixi-ros",
|
|
12
|
+
help="Pixi extension for ROS package management",
|
|
13
|
+
no_args_is_help=True,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
pkg_app = typer.Typer(help="Manage ROS packages")
|
|
17
|
+
app.add_typer(pkg_app, name="pkg")
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@app.command()
|
|
21
|
+
def init(
|
|
22
|
+
distro: Annotated[
|
|
23
|
+
str | None,
|
|
24
|
+
typer.Option(
|
|
25
|
+
"--distro",
|
|
26
|
+
"-d",
|
|
27
|
+
help="ROS distribution (e.g., humble, iron, jazzy)",
|
|
28
|
+
),
|
|
29
|
+
] = None,
|
|
30
|
+
platforms: Annotated[
|
|
31
|
+
list[str] | None,
|
|
32
|
+
typer.Option(
|
|
33
|
+
"--platform",
|
|
34
|
+
"-p",
|
|
35
|
+
help="Target platforms (e.g., linux-64, osx-arm64, win-64). Can be specified multiple times.",
|
|
36
|
+
),
|
|
37
|
+
] = None,
|
|
38
|
+
):
|
|
39
|
+
"""Initialize pixi.toml for a ROS workspace."""
|
|
40
|
+
# If distro not provided, prompt user to select one
|
|
41
|
+
if distro is None:
|
|
42
|
+
available_distros = get_ros_distros()
|
|
43
|
+
typer.echo("Available ROS distributions:")
|
|
44
|
+
for i, d in enumerate(available_distros, 1):
|
|
45
|
+
typer.echo(f" {i}. {d}")
|
|
46
|
+
|
|
47
|
+
# Prompt for selection
|
|
48
|
+
selection = typer.prompt(
|
|
49
|
+
"\nSelect a distribution (enter number or name)",
|
|
50
|
+
type=str,
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
# Parse selection (either number or name)
|
|
54
|
+
try:
|
|
55
|
+
selection_num = int(selection)
|
|
56
|
+
dist_count = len(available_distros)
|
|
57
|
+
if 1 <= selection_num <= dist_count:
|
|
58
|
+
distro = available_distros[selection_num - 1]
|
|
59
|
+
else:
|
|
60
|
+
typer.echo(
|
|
61
|
+
f"Error: Invalid selection. Please choose 1-{dist_count}",
|
|
62
|
+
err=True,
|
|
63
|
+
)
|
|
64
|
+
raise typer.Exit(code=1)
|
|
65
|
+
except ValueError as err:
|
|
66
|
+
# User entered a name instead of number
|
|
67
|
+
if selection in available_distros:
|
|
68
|
+
distro = selection
|
|
69
|
+
else:
|
|
70
|
+
typer.echo(
|
|
71
|
+
f"Error: '{selection}' is not a valid ROS distribution", err=True
|
|
72
|
+
)
|
|
73
|
+
typer.echo(f"Available: {', '.join(available_distros)}", err=True)
|
|
74
|
+
raise typer.Exit(code=1) from err
|
|
75
|
+
|
|
76
|
+
# If platforms not provided, prompt user to select
|
|
77
|
+
if platforms is None or len(platforms) == 0:
|
|
78
|
+
available_platforms = get_platforms()
|
|
79
|
+
typer.echo("\nAvailable target platforms:")
|
|
80
|
+
for i, p in enumerate(available_platforms, 1):
|
|
81
|
+
typer.echo(f" {i}. {p}")
|
|
82
|
+
|
|
83
|
+
# Prompt for selection (can be comma-separated or space-separated)
|
|
84
|
+
selection = typer.prompt(
|
|
85
|
+
"\nSelect platforms (enter numbers or names, comma or space separated)",
|
|
86
|
+
type=str,
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
# Parse selection (can be numbers or names, comma or space separated)
|
|
90
|
+
platforms = []
|
|
91
|
+
# Split by comma or space
|
|
92
|
+
selections = selection.replace(",", " ").split()
|
|
93
|
+
|
|
94
|
+
for sel in selections:
|
|
95
|
+
sel = sel.strip()
|
|
96
|
+
if not sel:
|
|
97
|
+
continue
|
|
98
|
+
|
|
99
|
+
try:
|
|
100
|
+
# Try parsing as number
|
|
101
|
+
sel_num = int(sel)
|
|
102
|
+
if 1 <= sel_num <= len(available_platforms):
|
|
103
|
+
platforms.append(available_platforms[sel_num - 1])
|
|
104
|
+
else:
|
|
105
|
+
typer.echo(
|
|
106
|
+
f"Error: Invalid selection {sel_num}. Please choose 1-{len(available_platforms)}",
|
|
107
|
+
err=True,
|
|
108
|
+
)
|
|
109
|
+
raise typer.Exit(code=1)
|
|
110
|
+
except ValueError:
|
|
111
|
+
# User entered a name instead of number
|
|
112
|
+
if sel in available_platforms:
|
|
113
|
+
platforms.append(sel)
|
|
114
|
+
else:
|
|
115
|
+
typer.echo(
|
|
116
|
+
f"Error: '{sel}' is not a valid platform", err=True
|
|
117
|
+
)
|
|
118
|
+
typer.echo(f"Available: {', '.join(available_platforms)}", err=True)
|
|
119
|
+
raise typer.Exit(code=1)
|
|
120
|
+
|
|
121
|
+
if not platforms:
|
|
122
|
+
typer.echo("Error: No platforms selected", err=True)
|
|
123
|
+
raise typer.Exit(code=1)
|
|
124
|
+
|
|
125
|
+
init_workspace(distro, platforms=platforms)
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def main():
|
|
129
|
+
"""Entry point for the CLI."""
|
|
130
|
+
app()
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
if __name__ == "__main__":
|
|
134
|
+
main()
|