Eleanor v0.19.0
Summary
v0.19.0 is a major architectural release. The plugin system has been overhauled to use Python entry points, making all executors, kernels, navigators, output sinks, and CLI commands fully discoverable without hard-coded imports. The CLI has been migrated from argparse to Click, gaining shell completion and a more consistent command hierarchy. The Postgres output layer has been rewritten on psycopg3 with per-batch transactions and savepoint-per-point error isolation. Eleanor itself is now an optional context manager that can reuse resources across multiple runs. Several long-standing internal concepts have been renamed or removed to clarify the API surface: Sailor → Runner, Boatswain → PointBuilder, *Exception → *Error, and the suborder, Huffer, and order-transformer features have been dropped entirely.
NOTE: This is a massive change that likely includes a number of bugs and issues. We decided to get these changes out now and hope that you will report any issues and contribute to discussions over here 👉 #188.
What's New
Eleanor Query Language (EQL)
A typed, consumer-agnostic query language for filtering and projecting simulation results. Any output sink (Postgres, CSV, memory, etc.) or navigator feedback logic can consume the same query.
Database Migration System
eleanor postgres migrate applies versioned schema migrations automatically on each run.
New Output Sinks
csv, memory, and null sink types are now built in alongside the existing postgres sink.
New CLI Commands & Flags
eleanor doctor— prints install and plugin diagnostics.eleanor gen config|order— emits starter config and order templates in YAML, TOML, or JSON.eleanor postgres— groupsbulkload drop/recreate,schema verify/scratch, andmigrateunder a single subcommand.--null-sink— discards all writes for a run without editing the config file.--max-nav-attempts— controls navigator retry count per point.--(no-)bulk-load— enables/disables Postgres bulk-load mode (drops secondary indexes during ingestion, recreates at finalize) for a single run.--order-id— resumes or extends an existing order row in the database.
Other Additions
ELEANOR_EQ36_DATA1_DIRenvironment variable for setting the EQ3/6 data directory without a config file.- Multiple tags per order (stored as a JSON array).
- Navigator-owned batching with retry logic wired to
--max-nav-attempts. LinearConstraintbuilt-in constraint type.- Separate tqdm progress bars for kernel execution and output writes.
- Plugin versioning with compatibility validation at load time.
Kernel.get_molar_massandKernel.get_atomic_weightinterface methods.Order.volumeproperty andwater_massorder field.- Graceful SIGINT/SIGTERM shutdown — flushes in-flight results before exit.
CombinedReactantreplacesGlassReactants, with optional fraction-proportional rate support.min_log_activity,min_log_molality, andwrite_unformedsettings for the Postgres sink.errorcolumn in thevariable_spacetable for failed simulation points.- Comprehensive database indices on the Postgres schema.
EleanorWarningbase class for non-fatal warnings.- Backtraces always printed on error in
eleanor run. - Reactant fractions can now be
ValueParameterinstances. @config_optionsdecorator is now parameterizable withrequired.
Breaking Changes
Renames
Sailor→Runner;Boatswain→PointBuilder.- All
*Exceptionclasses renamed to*Error(e.g.EleanorException→EleanorError,Eq36Exception→Eq36Error).
API Changes
- CLI migrated to Click — all commands and flags have changed; shell completion available via
_ELEANOR_COMPLETE. - Plugin system now uses Python entry points — plugins must register via
project.entry-pointsinpyproject.toml. - Eleanor is now an optional context manager — resources are reused across
runcalls inside awithblock; single-shot usage still works without one. - Executor lifecycle is now caller-owned — Eleanor no longer tears down an executor passed at construction time.
- All
Eleanor.__init__arguments are now keyword-only. Eleanor.runnow accepts kernel arguments directly rather than via a wrapper.ConstraintConfig,NavigatorConfig, andOutputConfigmoved to dedicated modules.Configrefactored; per-subsystem config classes are loaded independently.Parameter.nameretired; names are managed at theVariableSpacelevel.load_executor,load_navigator, andload_output_sinkinterfaces redesigned for consistency.TypedDicts at interface boundaries replaced with typed**kwargs(Unpack).- Obscure equilibrium-space scalar properties moved from top-level columns into a
custom_propertiesJSONB column. - Stoichiometric ionic asymmetry now stored in place of
log_activity/log_molalityvalues. data1_dirnow acceptsstr | Path.- Multiprocessing executor replaced busy-polling with a queue-draining implementation.
- Switched to absolute imports throughout; scipy imports are now deferred.
- Transitioned to
np.float64throughout the kernel layer.
Removed Features
- Suborder feature — use separate orders instead.
- Huffer — removed entirely.
GlassReactantEmbedder— superseded byCombinedReactant.- Order Transformers — removed entirely.
- Success-sampling support — removed.
Parameter.typeproperty.parallelkwarg fromEleanor.run.- Per-run executor support — executor is now session-scoped.
idfields fromOrder,VariableSpace, andEquilibriumSpacedataclasses — moved into the output layer.- mypy, pylsp-mypy, and maccabe removed as dev dependencies; replaced by basedpyright.
Bug Fixes
- Fixed always-true condition in kernel model-type check that silently accepted invalid states.
- Fixed infinite recursion in certain kernel code paths.
- Fixed incorrect exit code detection when kernel returned a soft-exit code.
Full Changelog: v0.18.2...v0.19.0