From ced27f050dc0b0765aba5bb33a8d1bf1168e27a2 Mon Sep 17 00:00:00 2001 From: Andrei Cravtov Date: Thu, 11 Jun 2026 19:28:51 +0100 Subject: [PATCH] rename to bootstrap --- rust/exo_rs/exo_rs.pyi | 190 +++++++++--------- .../src/config/{locator.rs => bootstrap.rs} | 34 ++-- rust/exo_rs/src/config/cli.rs | 27 ++- rust/exo_rs/src/config/defaults.rs | 1 - rust/exo_rs/src/config/mod.rs | 17 +- 5 files changed, 139 insertions(+), 130 deletions(-) rename rust/exo_rs/src/config/{locator.rs => bootstrap.rs} (90%) delete mode 100644 rust/exo_rs/src/config/defaults.rs diff --git a/rust/exo_rs/exo_rs.pyi b/rust/exo_rs/exo_rs.pyi index 96e13f55a..ae281171f 100644 --- a/rust/exo_rs/exo_rs.pyi +++ b/rust/exo_rs/exo_rs.pyi @@ -7,13 +7,13 @@ import os import pathlib import typing __all__ = [ + "BootstrapArgs", + "BootstrapSettings", "CliArgs", "ConfigArgs", "DeprecatedArgs", "ExoHome", "FromSwarm", - "LocatorArgs", - "LocatorConfig", "LogFiles", "ModelsDirs", "NetworkingHandle", @@ -22,6 +22,95 @@ __all__ = [ "Verbosity", ] +@typing.final +class BootstrapArgs: + r""" + Arguments that are needed to resolve bootstrap settings. + + These values are resolved before `config.toml` can be loaded. For example, the + `config.toml` path itself depends on these values, so these arguments cannot be + specified by `config.toml`. + + By default, any path-like argument goes here, but it can be moved to [`ConfigArgs`] + if it no longer participates in bootstrap resolution. + """ + @property + def exo_home(self) -> typing.Optional[pathlib.Path]: ... + @exo_home.setter + def exo_home(self, value: typing.Optional[builtins.str | os.PathLike | pathlib.Path]) -> None: ... + @property + def default_models_dir(self) -> typing.Optional[pathlib.Path]: ... + @default_models_dir.setter + def default_models_dir(self, value: typing.Optional[builtins.str | os.PathLike | pathlib.Path]) -> None: ... + @property + def models_read_only_dirs(self) -> typing.Optional[builtins.list[pathlib.Path]]: ... + @models_read_only_dirs.setter + def models_read_only_dirs(self, value: typing.Optional[typing.Sequence[builtins.str | os.PathLike | pathlib.Path]]) -> None: ... + @property + def models_dirs(self) -> typing.Optional[builtins.list[pathlib.Path]]: ... + @models_dirs.setter + def models_dirs(self, value: typing.Optional[typing.Sequence[builtins.str | os.PathLike | pathlib.Path]]) -> None: ... + @property + def config_file(self) -> typing.Optional[pathlib.Path]: ... + @config_file.setter + def config_file(self, value: typing.Optional[builtins.str | os.PathLike | pathlib.Path]) -> None: ... + +@typing.final +class BootstrapSettings: + @property + def exo_home(self) -> ExoHome: ... + @property + def models_dirs(self) -> ModelsDirs: ... + @property + def log_files(self) -> LogFiles: ... + @property + def pid_file(self) -> pathlib.Path: ... + @pid_file.setter + def pid_file(self, value: builtins.str | os.PathLike | pathlib.Path) -> None: ... + @property + def node_zid(self) -> pathlib.Path: ... + @node_zid.setter + def node_zid(self, value: builtins.str | os.PathLike | pathlib.Path) -> None: ... + @property + def config_file(self) -> pathlib.Path: ... + @config_file.setter + def config_file(self, value: builtins.str | os.PathLike | pathlib.Path) -> None: ... + @property + def custom_model_cards_dir(self) -> pathlib.Path: ... + @custom_model_cards_dir.setter + def custom_model_cards_dir(self, value: builtins.str | os.PathLike | pathlib.Path) -> None: ... + @property + def event_log_dir(self) -> pathlib.Path: ... + @event_log_dir.setter + def event_log_dir(self, value: builtins.str | os.PathLike | pathlib.Path) -> None: ... + @property + def image_cache_dir(self) -> pathlib.Path: ... + @image_cache_dir.setter + def image_cache_dir(self, value: builtins.str | os.PathLike | pathlib.Path) -> None: ... + @property + def tracing_cache_dir(self) -> pathlib.Path: ... + @tracing_cache_dir.setter + def tracing_cache_dir(self, value: builtins.str | os.PathLike | pathlib.Path) -> None: ... + @staticmethod + def default() -> BootstrapSettings: + r""" + Create default instance + """ + @staticmethod + def from_env_only() -> BootstrapSettings: + r""" + Create only from env-variables + """ + @staticmethod + def resolve(args: BootstrapArgs) -> BootstrapSettings: ... + def set_exo_home(self, exo_home: ExoHome) -> None: ... + def set_models_dirs(self, models_dirs: ModelsDirs) -> None: ... + def set_log_files(self, log_files: LogFiles) -> None: ... + def to_bytes(self) -> builtins.list[builtins.int]: ... + @staticmethod + def from_bytes(bytes: typing.Sequence[builtins.int]) -> BootstrapSettings: ... + def __reduce__(self) -> tuple[typing.Any, tuple]: ... + @typing.final class CliArgs: @property @@ -81,7 +170,7 @@ class CliArgs: @fast_synch.setter def fast_synch(self, value: typing.Optional[builtins.bool]) -> None: ... @property - def locator(self) -> LocatorArgs: ... + def bootstrap(self) -> BootstrapArgs: ... @property def config(self) -> ConfigArgs: ... @property @@ -95,7 +184,7 @@ class CliArgs: def parse_from(argv: typing.Sequence[builtins.str]) -> CliArgs: ... @staticmethod def parse() -> CliArgs: ... - def set_locator(self, locator: LocatorArgs) -> None: ... + def set_bootstrap(self, bootstrap: BootstrapArgs) -> None: ... def set_config(self, config: ConfigArgs) -> None: ... def set_deprecated(self, deprecated: DeprecatedArgs) -> None: ... def to_bytes(self) -> builtins.list[builtins.int]: ... @@ -106,14 +195,14 @@ class CliArgs: @typing.final class ConfigArgs: r""" - Arguments that will end up in the final configuration go here. + Arguments that will end up in application settings go here. - The precedence of the final configuration object will be: + The precedence of application settings will be: - Defaults < Config file < Env < Cli args # Important - Make sure all are [`Option`] so we can make it combinable with other - sources of configuration + settings sources """ ... @@ -166,93 +255,6 @@ class FromSwarm: ... -@typing.final -class LocatorArgs: - r""" - Arguments that are needed to resolve paths to files go here. - - This is needed for such things as resolving the path of the configuration `.toml` file, - therefore any args here cannot be specified by the configuration `.toml` file. - - By default, any path-like argument goes here, but can be moved to [`ConfigArgs`] if needed. - """ - @property - def exo_home(self) -> typing.Optional[pathlib.Path]: ... - @exo_home.setter - def exo_home(self, value: typing.Optional[builtins.str | os.PathLike | pathlib.Path]) -> None: ... - @property - def default_models_dir(self) -> typing.Optional[pathlib.Path]: ... - @default_models_dir.setter - def default_models_dir(self, value: typing.Optional[builtins.str | os.PathLike | pathlib.Path]) -> None: ... - @property - def models_read_only_dirs(self) -> typing.Optional[builtins.list[pathlib.Path]]: ... - @models_read_only_dirs.setter - def models_read_only_dirs(self, value: typing.Optional[typing.Sequence[builtins.str | os.PathLike | pathlib.Path]]) -> None: ... - @property - def models_dirs(self) -> typing.Optional[builtins.list[pathlib.Path]]: ... - @models_dirs.setter - def models_dirs(self, value: typing.Optional[typing.Sequence[builtins.str | os.PathLike | pathlib.Path]]) -> None: ... - @property - def config_file(self) -> typing.Optional[pathlib.Path]: ... - @config_file.setter - def config_file(self, value: typing.Optional[builtins.str | os.PathLike | pathlib.Path]) -> None: ... - -@typing.final -class LocatorConfig: - @property - def exo_home(self) -> ExoHome: ... - @property - def models_dirs(self) -> ModelsDirs: ... - @property - def log_files(self) -> LogFiles: ... - @property - def pid_file(self) -> pathlib.Path: ... - @pid_file.setter - def pid_file(self, value: builtins.str | os.PathLike | pathlib.Path) -> None: ... - @property - def node_zid(self) -> pathlib.Path: ... - @node_zid.setter - def node_zid(self, value: builtins.str | os.PathLike | pathlib.Path) -> None: ... - @property - def config_file(self) -> pathlib.Path: ... - @config_file.setter - def config_file(self, value: builtins.str | os.PathLike | pathlib.Path) -> None: ... - @property - def custom_model_cards_dir(self) -> pathlib.Path: ... - @custom_model_cards_dir.setter - def custom_model_cards_dir(self, value: builtins.str | os.PathLike | pathlib.Path) -> None: ... - @property - def event_log_dir(self) -> pathlib.Path: ... - @event_log_dir.setter - def event_log_dir(self, value: builtins.str | os.PathLike | pathlib.Path) -> None: ... - @property - def image_cache_dir(self) -> pathlib.Path: ... - @image_cache_dir.setter - def image_cache_dir(self, value: builtins.str | os.PathLike | pathlib.Path) -> None: ... - @property - def tracing_cache_dir(self) -> pathlib.Path: ... - @tracing_cache_dir.setter - def tracing_cache_dir(self, value: builtins.str | os.PathLike | pathlib.Path) -> None: ... - @staticmethod - def default() -> LocatorConfig: - r""" - Create default instance - """ - @staticmethod - def from_env_only() -> LocatorConfig: - r""" - Create only from env-variables - """ - @staticmethod - def resolve(args: LocatorArgs) -> LocatorConfig: ... - def set_exo_home(self, exo_home: ExoHome) -> None: ... - def set_models_dirs(self, models_dirs: ModelsDirs) -> None: ... - def set_log_files(self, log_files: LogFiles) -> None: ... - def to_bytes(self) -> builtins.list[builtins.int]: ... - @staticmethod - def from_bytes(bytes: typing.Sequence[builtins.int]) -> LocatorConfig: ... - def __reduce__(self) -> tuple[typing.Any, tuple]: ... - @typing.final class LogFiles: @property diff --git a/rust/exo_rs/src/config/locator.rs b/rust/exo_rs/src/config/bootstrap.rs similarity index 90% rename from rust/exo_rs/src/config/locator.rs rename to rust/exo_rs/src/config/bootstrap.rs index 5e8ed104f..eee08d11c 100644 --- a/rust/exo_rs/src/config/locator.rs +++ b/rust/exo_rs/src/config/bootstrap.rs @@ -2,7 +2,7 @@ use crate::config::cli::CliArgs; use crate::config::path::{PathBufValueParserExt, parse_path}; use crate::ext::ResultExt; use crate::pickle_reduce; -use pyo3::prelude::{PyAnyMethods, PyModule, PyModuleMethods}; +use pyo3::prelude::{PyModule, PyModuleMethods}; use pyo3::types::PyTuple; use pyo3::{Bound, PyAny, PyResult, pyclass, pymethods}; use pyo3_stub_gen::derive::{gen_stub_pyclass, gen_stub_pymethods}; @@ -12,17 +12,19 @@ use std::{fs, io}; use util::VecExt; use util::path::PathExt; -/// Arguments that are needed to resolve paths to files go here. +/// Arguments that are needed to resolve bootstrap settings. /// -/// This is needed for such things as resolving the path of the configuration `.toml` file, -/// therefore any args here cannot be specified by the configuration `.toml` file. +/// These values are resolved before `config.toml` can be loaded. For example, the +/// `config.toml` path itself depends on these values, so these arguments cannot be +/// specified by `config.toml`. /// -/// By default, any path-like argument goes here, but can be moved to [`ConfigArgs`] if needed. +/// By default, any path-like argument goes here, but it can be moved to [`ConfigArgs`] +/// if it no longer participates in bootstrap resolution. #[gen_stub_pyclass] #[pyclass(from_py_object)] #[derive(Debug, Clone, PartialEq, Eq, Default, Serialize, Deserialize, clap::Args)] #[command(about = None, long_about = None)] -pub struct LocatorArgs { +pub struct BootstrapArgs { #[arg( long, env = "EXO_HOME", @@ -79,7 +81,7 @@ pub struct LocatorArgs { #[gen_stub_pyclass] #[pyclass(module = "exo_rs", from_py_object)] #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] -pub struct LocatorConfig { +pub struct BootstrapSettings { #[pyo3(get)] pub exo_home: ExoHome, @@ -114,24 +116,24 @@ pub struct LocatorConfig { #[gen_stub_pymethods] #[pymethods] -impl LocatorConfig { +impl BootstrapSettings { /// Create default instance #[staticmethod] #[pyo3(name = "default")] pub fn py_default() -> PyResult { // resolve from env only - Self::resolve(&LocatorArgs::default()) + Self::resolve(&BootstrapArgs::default()) } /// Create only from env-variables #[staticmethod] pub fn from_env_only() -> PyResult { // resolve from env only - Self::resolve(&CliArgs::from_env_only().locator) + Self::resolve(&CliArgs::from_env_only().bootstrap) } #[staticmethod] - pub fn resolve(args: &LocatorArgs) -> PyResult { + pub fn resolve(args: &BootstrapArgs) -> PyResult { let exo_home = ExoHome::resolve(args)?; let models_dirs = ModelsDirs::resolve(args, &exo_home)?; let log_files = LogFiles::resolve(&exo_home)?; @@ -240,7 +242,7 @@ impl ExoHome { Ok(home) } - pub fn resolve(args: &LocatorArgs) -> io::Result { + pub fn resolve(args: &BootstrapArgs) -> io::Result { // create config/data/cache folders which the rest of the paths are derived from Ok(Self { config: Self::get_home_dir(&args.exo_home, dirs::config_dir)?, @@ -263,7 +265,7 @@ pub struct ModelsDirs { } impl ModelsDirs { - pub fn resolve(args: &LocatorArgs, exo_home: &ExoHome) -> io::Result { + pub fn resolve(args: &BootstrapArgs, exo_home: &ExoHome) -> io::Result { // create default models dir let default_models_dir = args .default_models_dir @@ -330,9 +332,9 @@ impl LogFiles { } } -pub fn locator_submodule(m: &Bound) -> PyResult<()> { - m.add_class::()?; - m.add_class::()?; +pub fn bootstrap_submodule(m: &Bound) -> PyResult<()> { + m.add_class::()?; + m.add_class::()?; m.add_class::()?; m.add_class::()?; m.add_class::()?; diff --git a/rust/exo_rs/src/config/cli.rs b/rust/exo_rs/src/config/cli.rs index e2a4ac190..ead4ee15b 100644 --- a/rust/exo_rs/src/config/cli.rs +++ b/rust/exo_rs/src/config/cli.rs @@ -1,8 +1,8 @@ -use crate::config::locator::LocatorArgs; +use crate::config::bootstrap::BootstrapArgs; use crate::ext::ResultExt; use crate::{pickle_reduce, version}; use clap::{ArgAction, Parser, ValueEnum}; -use pyo3::prelude::PyAnyMethods; +use pyo3::prelude::{PyAnyMethods, PyModuleMethods}; use pyo3::types::{PyModule, PyTuple}; use pyo3::{Bound, PyAny, PyResult, Python, pyclass, pymethods}; use pyo3_stub_gen::derive::{gen_stub_pyclass, gen_stub_pyclass_enum, gen_stub_pymethods}; @@ -146,6 +146,7 @@ pub struct CliArgs { #[arg( long, + env = "EXO_FAST_SYNCH", value_name = "BOOL", help = "Force MLX FAST_SYNCH on/off (for JACCL backend); omit for auto" )] @@ -154,7 +155,7 @@ pub struct CliArgs { #[command(flatten)] #[pyo3(get)] - pub locator: LocatorArgs, + pub bootstrap: BootstrapArgs, #[command(flatten)] #[pyo3(get)] @@ -190,8 +191,8 @@ impl CliArgs { Ok(CliArgs::parse_from(argv)) } - pub fn set_locator(&mut self, locator: LocatorArgs) { - self.locator = locator; + pub fn set_bootstrap(&mut self, bootstrap: BootstrapArgs) { + self.bootstrap = bootstrap; } pub fn set_config(&mut self, config: ConfigArgs) { @@ -218,14 +219,14 @@ impl CliArgs { } } -/// Arguments that will end up in the final configuration go here. +/// Arguments that will end up in application settings go here. /// -/// The precedence of the final configuration object will be: +/// The precedence of application settings will be: /// - Defaults < Config file < Env < Cli args /// /// # Important /// - Make sure all are [`Option`] so we can make it combinable with other -/// sources of configuration +/// settings sources #[gen_stub_pyclass] #[pyclass(from_py_object)] #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, clap::Args)] @@ -249,6 +250,7 @@ pub struct DeprecatedArgs { } impl DeprecatedArgs { + // TODO: actually run these at some point - maybe automatically..? pub fn get_error(&self) -> Option { // destructure: don't change because this becomes compile error when new options are // moved into here or removed from here @@ -266,3 +268,12 @@ impl DeprecatedArgs { } } } + +pub fn cli_submodule(m: &Bound) -> PyResult<()> { + m.add_class::()?; + m.add_class::()?; + m.add_class::()?; + m.add_class::()?; + + Ok(()) +} diff --git a/rust/exo_rs/src/config/defaults.rs b/rust/exo_rs/src/config/defaults.rs deleted file mode 100644 index 8b1378917..000000000 --- a/rust/exo_rs/src/config/defaults.rs +++ /dev/null @@ -1 +0,0 @@ - diff --git a/rust/exo_rs/src/config/mod.rs b/rust/exo_rs/src/config/mod.rs index e99a23bf8..a224cff3b 100644 --- a/rust/exo_rs/src/config/mod.rs +++ b/rust/exo_rs/src/config/mod.rs @@ -1,20 +1,15 @@ -use crate::config::cli::{CliArgs, ConfigArgs, DeprecatedArgs, Verbosity}; -use crate::config::locator::locator_submodule; -use pyo3::prelude::{PyModule, PyModuleMethods}; +use crate::config::bootstrap::bootstrap_submodule; +use crate::config::cli::cli_submodule; +use pyo3::prelude::PyModule; use pyo3::{Bound, PyResult}; +pub mod bootstrap; pub mod cli; -pub mod defaults; -pub mod locator; pub mod path; pub fn config_submodule(m: &Bound) -> PyResult<()> { - locator_submodule(m)?; - - m.add_class::()?; - m.add_class::()?; - m.add_class::()?; - m.add_class::()?; + bootstrap_submodule(m)?; + cli_submodule(m)?; Ok(()) }