monarch_hyperactor/selection.rs
1/*
2 * Copyright (c) Meta Platforms, Inc. and affiliates.
3 * All rights reserved.
4 *
5 * This source code is licensed under the BSD-style license found in the
6 * LICENSE file in the root directory of this source tree.
7 */
8
9use hyperactor_mesh::sel;
10use ndslice::selection::Selection;
11use pyo3::PyResult;
12use pyo3::prelude::*;
13use pyo3::types::PyType;
14
15#[pyclass(
16 name = "Selection",
17 module = "monarch._rust_bindings.monarch_hyperactor.selection",
18 frozen
19)]
20pub struct PySelection {
21 inner: Selection,
22}
23
24impl PySelection {
25 #[allow(dead_code)]
26 pub(crate) fn inner(&self) -> &Selection {
27 &self.inner
28 }
29}
30
31impl From<Selection> for PySelection {
32 fn from(inner: Selection) -> Self {
33 Self { inner }
34 }
35}
36
37#[pymethods]
38impl PySelection {
39 #[getter]
40 fn __repr__(&self) -> String {
41 format!("{:?}", self.inner)
42 }
43
44 /// Parses a selection expression from a string.
45 ///
46 /// This allows you to construct a `PySelection` using the
47 /// selection algebra surface syntax, such as `"(*, 0:4, ?)"`.
48 ///
49 /// Raises:
50 /// ValueError: If the input string is not a valid selection
51 /// expression.
52 ///
53 /// Example:
54 /// PySelection.from_string("(*, 1:3, ?)") # subset of a mesh
55 #[classmethod]
56 #[pyo3(name = "from_string")]
57 pub fn parse(_cls: Bound<'_, PyType>, input: &str) -> PyResult<Self> {
58 let selection = ndslice::selection::parse::parse(input).map_err(|err| {
59 pyo3::exceptions::PyValueError::new_err(format!("parse error: {err}"))
60 })?;
61
62 Ok(PySelection::from(selection))
63 }
64
65 /// Selects all elements in the mesh — use this to mean "route to
66 /// all nodes".
67 ///
68 /// The '*' expression is automatically expanded to match the
69 /// dimensionality of the slice. For example, in a 3D slice, the
70 /// selection becomes `*, *, *`.
71 #[classmethod]
72 pub fn all(_cls: Bound<'_, PyType>) -> Self {
73 PySelection::from(sel!(*))
74 }
75
76 /// Selects one element nondeterministically — use this to mean
77 /// "route to a single random node".
78 ///
79 /// The '?' expression is automatically expanded to match the
80 /// dimensionality of the slice. For example, in a 3D slice, the
81 /// selection becomes `?, ?, ?`.
82 #[classmethod]
83 pub fn any(_cls: Bound<'_, PyType>) -> Self {
84 PySelection::from(sel!(?))
85 }
86}
87
88pub fn register_python_bindings(module: &Bound<'_, PyModule>) -> PyResult<()> {
89 module.add_class::<PySelection>()?;
90 Ok(())
91}