pixi-ros 0.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.
- pixi_ros/__init__.py +3 -0
- pixi_ros/cli.py +77 -0
- pixi_ros/config.py +34 -0
- pixi_ros/data/README.md +56 -0
- pixi_ros/data/README_PIXI.md.template +125 -0
- pixi_ros/data/conda-forge.yaml +1049 -0
- pixi_ros/init.py +548 -0
- pixi_ros/mappings.py +298 -0
- pixi_ros/package_xml.py +183 -0
- pixi_ros/utils.py +80 -0
- pixi_ros/workspace.py +213 -0
- pixi_ros-0.1.0.dist-info/METADATA +212 -0
- pixi_ros-0.1.0.dist-info/RECORD +15 -0
- pixi_ros-0.1.0.dist-info/WHEEL +4 -0
- pixi_ros-0.1.0.dist-info/entry_points.txt +2 -0
pixi_ros/__init__.py
ADDED
pixi_ros/cli.py
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
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_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
|
+
):
|
|
31
|
+
"""Initialize pixi.toml for a ROS workspace."""
|
|
32
|
+
# If distro not provided, prompt user to select one
|
|
33
|
+
if distro is None:
|
|
34
|
+
available_distros = get_ros_distros()
|
|
35
|
+
typer.echo("Available ROS distributions:")
|
|
36
|
+
for i, d in enumerate(available_distros, 1):
|
|
37
|
+
typer.echo(f" {i}. {d}")
|
|
38
|
+
|
|
39
|
+
# Prompt for selection
|
|
40
|
+
selection = typer.prompt(
|
|
41
|
+
"\nSelect a distribution (enter number or name)",
|
|
42
|
+
type=str,
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
# Parse selection (either number or name)
|
|
46
|
+
try:
|
|
47
|
+
selection_num = int(selection)
|
|
48
|
+
dist_count = len(available_distros)
|
|
49
|
+
if 1 <= selection_num <= dist_count:
|
|
50
|
+
distro = available_distros[selection_num - 1]
|
|
51
|
+
else:
|
|
52
|
+
typer.echo(
|
|
53
|
+
f"Error: Invalid selection.Please choose 1-{dist_count}",
|
|
54
|
+
err=True,
|
|
55
|
+
)
|
|
56
|
+
raise typer.Exit(code=1)
|
|
57
|
+
except ValueError as err:
|
|
58
|
+
# User entered a name instead of number
|
|
59
|
+
if selection in available_distros:
|
|
60
|
+
distro = selection
|
|
61
|
+
else:
|
|
62
|
+
typer.echo(
|
|
63
|
+
f"Error: '{selection}' is not a valid ROS distribution", err=True
|
|
64
|
+
)
|
|
65
|
+
typer.echo(f"Available: {', '.join(available_distros)}", err=True)
|
|
66
|
+
raise typer.Exit(code=1) from err
|
|
67
|
+
|
|
68
|
+
init_workspace(distro)
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def main():
|
|
72
|
+
"""Entry point for the CLI."""
|
|
73
|
+
app()
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
if __name__ == "__main__":
|
|
77
|
+
main()
|
pixi_ros/config.py
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"""Configuration handling for pixi-ros."""
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def find_config_file(start_path: Path | None = None) -> Path | None:
|
|
7
|
+
"""
|
|
8
|
+
Search for .pixi-ros.toml configuration file.
|
|
9
|
+
|
|
10
|
+
Searches upward from start_path (or cwd) until a config file is found.
|
|
11
|
+
|
|
12
|
+
Args:
|
|
13
|
+
start_path: Starting directory for search (defaults to cwd)
|
|
14
|
+
|
|
15
|
+
Returns:
|
|
16
|
+
Path to config file if found, None otherwise
|
|
17
|
+
"""
|
|
18
|
+
if start_path is None:
|
|
19
|
+
start_path = Path.cwd()
|
|
20
|
+
|
|
21
|
+
current = start_path.resolve()
|
|
22
|
+
|
|
23
|
+
# Search upward until we hit the root
|
|
24
|
+
while True:
|
|
25
|
+
config_path = current / ".pixi-ros.toml"
|
|
26
|
+
if config_path.exists():
|
|
27
|
+
return config_path
|
|
28
|
+
|
|
29
|
+
parent = current.parent
|
|
30
|
+
if parent == current: # Reached root
|
|
31
|
+
break
|
|
32
|
+
current = parent
|
|
33
|
+
|
|
34
|
+
return None
|
pixi_ros/data/README.md
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Mapping files
|
|
2
|
+
|
|
3
|
+
This file contains mappings from ROS package names to their conda package equivalents.
|
|
4
|
+
These are split by channel. e.g. conda-forge.
|
|
5
|
+
|
|
6
|
+
## Format
|
|
7
|
+
|
|
8
|
+
The file is based on the rosdep format, with the following structure:
|
|
9
|
+
|
|
10
|
+
- Keys are ROS package names, as presented in the package.xml (e.g. `udev`, `uncrustify`, `uuid`).
|
|
11
|
+
- Values are dictionaries mapping channels to lists of conda package names.
|
|
12
|
+
|
|
13
|
+
Example:
|
|
14
|
+
|
|
15
|
+
```yaml
|
|
16
|
+
udev:
|
|
17
|
+
pixi:
|
|
18
|
+
linux: [libusb, libudev]
|
|
19
|
+
osx: [libusb]
|
|
20
|
+
win64: [libusb]
|
|
21
|
+
uncrustify:
|
|
22
|
+
pixi: [uncrustify]
|
|
23
|
+
unzip:
|
|
24
|
+
pixi: [unzip]
|
|
25
|
+
uuid:
|
|
26
|
+
pixi:
|
|
27
|
+
linux: [libuuid]
|
|
28
|
+
osx: []
|
|
29
|
+
win64: []
|
|
30
|
+
virtualenv:
|
|
31
|
+
pixi: [virtualenv]
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Customization
|
|
35
|
+
|
|
36
|
+
You can override these mappings by creating your own `pixi-ros/channel.yaml` file in:
|
|
37
|
+
|
|
38
|
+
1. **Workspace directory** (highest priority): `./pixi-ros/channel.yaml`
|
|
39
|
+
2. **User config directory**: `~/.pixi-ros/channel.yaml`
|
|
40
|
+
3. **Built-in defaults** (these file): Used if no custom file is found
|
|
41
|
+
|
|
42
|
+
If you use the same channel name it will override the file completely.
|
|
43
|
+
The channel names are not used for specific package lookups, only to find the correct mapping file.
|
|
44
|
+
e.g. if you name the file `foobar.yaml` it will still be able to fetch the packages from other channels.
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
## Fallback Behavior
|
|
48
|
+
|
|
49
|
+
If a package is not found in channel.yaml, pixi-ros will automatically:
|
|
50
|
+
1. Convert underscores to dashes
|
|
51
|
+
2. Prepend `ros-{distro}-`
|
|
52
|
+
|
|
53
|
+
For example, `my_custom_package` becomes `ros-humble-my-custom-package`.
|
|
54
|
+
|
|
55
|
+
## Local packages
|
|
56
|
+
If a package is found in the `src` folder and also defined in the mapping, it will use the local package.
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
# Pixi-ROS Workspace
|
|
2
|
+
|
|
3
|
+
This ROS {distro} workspace is configured to use [Pixi](https://pixi.sh) for dependency management.
|
|
4
|
+
|
|
5
|
+
## What is Pixi?
|
|
6
|
+
|
|
7
|
+
Pixi is a modern package manager that uses conda packages. It provides:
|
|
8
|
+
- Fast, reproducible dependency resolution
|
|
9
|
+
- Automatic environment management
|
|
10
|
+
- Reproducible with a lockfile
|
|
11
|
+
- Cross-platform support (Linux, macOS, Windows)
|
|
12
|
+
|
|
13
|
+
## Getting Started
|
|
14
|
+
|
|
15
|
+
### 1. Install Dependencies
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
pixi install
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
This installs all dependencies specified in `pixi.toml` from the configured channels.
|
|
22
|
+
|
|
23
|
+
### 2. Build the Workspace
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
pixi run build
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
This runs `colcon build` to compile your ROS packages.
|
|
30
|
+
|
|
31
|
+
### 3. Run Tests
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
pixi run test
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
This runs `colcon test` to execute your test suite.
|
|
38
|
+
|
|
39
|
+
### 4. Clean Build Artifacts
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
pixi run clean
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Removes `build/`, `install/`, and `log/` directories.
|
|
46
|
+
|
|
47
|
+
### 5. Add additional dependencies
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
pixi add <package-name>
|
|
51
|
+
# or for packages you would install with pip/uv/poetry:
|
|
52
|
+
pixi add --pypi <package-name>
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
This adds new dependencies to `pixi.toml` and installs them.
|
|
56
|
+
|
|
57
|
+
## Environment Activation
|
|
58
|
+
|
|
59
|
+
After the first build, pixi will automatically source the ROS setup script (`install/setup.bash`)
|
|
60
|
+
when you enter the pixi environment. This means you don't need to manually source it!
|
|
61
|
+
|
|
62
|
+
To activate the environment, run:
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
pixi shell
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
This starts a new shell with the ROS environment activated.
|
|
69
|
+
|
|
70
|
+
The environment will also be automatically activated when you run commands with `pixi run <command>`.
|
|
71
|
+
|
|
72
|
+
## Adding Dependencies
|
|
73
|
+
|
|
74
|
+
### Add a Conda Package
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
pixi add <package-name>
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Add ROS Dependencies
|
|
81
|
+
|
|
82
|
+
When you add dependencies to your `package.xml` files, run:
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
pixi ros init --distro {distro}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
This will update `pixi.toml` with the new dependencies.
|
|
89
|
+
|
|
90
|
+
## Unavailable Packages
|
|
91
|
+
|
|
92
|
+
If you see commented-out packages in `pixi.toml` with `# NOT FOUND`, these packages
|
|
93
|
+
were not found in the configured channels. You may need to:
|
|
94
|
+
- Check if the package name is correct
|
|
95
|
+
- Add additional channels with `pixi project channel add <channel-url>`
|
|
96
|
+
- Install the package through pip: `pixi add --pypi <package-name>`
|
|
97
|
+
- Add it to [conda-forge](https://github.com/conda-forge/staged-recipes) or [RoboStack](https://robostack.github.io/Contributing.html)
|
|
98
|
+
|
|
99
|
+
## Common Issues
|
|
100
|
+
|
|
101
|
+
### Build Fails
|
|
102
|
+
|
|
103
|
+
If `pixi run build` fails:
|
|
104
|
+
1. Make sure all dependencies are installed: `pixi install`
|
|
105
|
+
2. Clean and rebuild: `pixi run clean && pixi run build`
|
|
106
|
+
3. Validate the build task is correct for your workspace.
|
|
107
|
+
|
|
108
|
+
### Environment Issues
|
|
109
|
+
|
|
110
|
+
If `ros2` commands aren't found:
|
|
111
|
+
1. Run commands through pixi: `pixi run <command>`
|
|
112
|
+
2. Or use a pixi shell: `pixi shell`
|
|
113
|
+
|
|
114
|
+
## Learn More
|
|
115
|
+
|
|
116
|
+
- **Pixi Documentation**: https://pixi.sh
|
|
117
|
+
- **RoboStack Documentation**: https://robostack.github.io/
|
|
118
|
+
- **ROS {distro} Documentation**: https://docs.ros.org/en/{distro}/
|
|
119
|
+
- **pixi-ros GitHub**: https://github.com/prefix-dev/pixi-ros
|
|
120
|
+
|
|
121
|
+
## Channels
|
|
122
|
+
|
|
123
|
+
This workspace uses the following channels:
|
|
124
|
+
- `https://prefix.dev/robostack-{distro}` - ROS packages
|
|
125
|
+
- `https://prefix.dev/conda-forge` - System dependencies
|