The rattler crates can be used to build custom applications leveraging Conda packages. Download repodata, solve for package specs and install packages in a few lines of code. The powerful Python bindings allow for even more flexible use cases.
The rattler crate gives you access to high-level functionality to download channel index data, solve for `MatchSpec`s, and install packages. On top of rattler you can build bespoke tooling to set up custom environments with maximum parallelism and speed – rattler will handle the low-level details.
It's our core building block for Pixi, rattler-build and the backend of the prefix.dev Website.
We expose the power of rattler with Python bindings to make rapid iteration for custom development possible. The bindings give you all the power of rattler in a very convenient form. We think py-rattler is the best way to interact with Conda environments programmatically.
Install them with:
pixi add py-rattler
or even from PyPI:
uv add py-rattler
pub async fn create(opt: Opt) -> anyhow::Result<()> {
let channel_config = ChannelConfig::default_with_root_dir(env::current_dir()?);
let current_dir = env::current_dir()?;
let target_prefix = opt
.target_prefix
.unwrap_or_else(|| current_dir.join(".prefix"));
// Make the target prefix absolute
let target_prefix = std::path::absolute(target_prefix)?;
println!("Target prefix: {}", target_prefix.display());
// Determine the platform we're going to install for
let install_platform = if let Some(platform) = opt.platform {
Platform::from_str(&platform)?
} else {
Platform::current()
};
println!("Installing for platform: {install_platform:?}");
// Parse the specs from the command line. We do this explicitly instead of allow
// clap to deal with this because we need to parse the `channel_config` when
// parsing matchspecs.
let specs = opt
.specs
.iter()
.map(|spec| MatchSpec::from_str(spec, ParseStrictness::Strict))
.collect::<Result<Vec<_>, _>>()?;
import asyncio
import tempfile
from rattler import solve, install, VirtualPackage
async def main() -> None:
# Start by solving the environment.
#
# Solving is the process of going from specifications of package and their
# version requirements to a list of concrete packages.
print("started solving the environment")
solved_records = await solve(
# Channels to use for solving
channels=["conda-forge"],
# The specs to solve for
specs=["python ~=3.12.0", "pip", "requests 2.31.0"],
# Virtual packages define the specifications of the environment
virtual_packages=VirtualPackage.detect(),
)
print("solved required dependencies")
# Install the packages into a new environment (or updates it if it already
# existed).
env_path = tempfile.mkdtemp()
await install(
records=solved_records,
target_prefix=env_path,
)
print(f"created environment: {env_path}")
if __name__ == "__main__":
asyncio.run(main())