From 5fbbdb19bf810d7e602dbca98d059f34562cb2cb Mon Sep 17 00:00:00 2001 From: Alan Garny Date: Thu, 23 Jul 2026 10:49:08 +1200 Subject: [PATCH 1/3] New version. --- VERSION.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION.txt b/VERSION.txt index eca4808fc..8f0b140aa 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -1.20260722.0 +1.20260723.0 From 6c38dd7844bddbedc8e4c5f81ed86331645a53a2 Mon Sep 17 00:00:00 2001 From: Alan Garny Date: Thu, 23 Jul 2026 11:17:05 +1200 Subject: [PATCH 2/3] SedInstance: replaced `isRunning()` with `status()`. --- src/api/libopencor/sedinstance.h | 33 +++++++++++----- src/bindings/javascript/sed.cpp | 15 +++++++- src/bindings/python/sed.cpp | 10 ++++- src/sed/sedinstance.cpp | 28 +++++++++----- src/sed/sedinstance_p.h | 3 +- tests/api/sed/concurrenttests.cpp | 2 +- tests/api/sed/instancetests.cpp | 38 +++++++++---------- .../bindings/javascript/res/res/libopencor.js | 4 +- .../javascript/sed.concurrent.test.js | 2 +- .../bindings/javascript/sed.instance.test.js | 38 +++++++++---------- tests/bindings/python/test_sed_concurrent.py | 2 +- tests/bindings/python/test_sed_instance.py | 38 +++++++++---------- 12 files changed, 127 insertions(+), 86 deletions(-) diff --git a/src/api/libopencor/sedinstance.h b/src/api/libopencor/sedinstance.h index 255e6920c..bed4af382 100644 --- a/src/api/libopencor/sedinstance.h +++ b/src/api/libopencor/sedinstance.h @@ -43,6 +43,29 @@ class LIBOPENCOR_EXPORT SedInstance: public Logger SedInstance &operator=(const SedInstance &pRhs) = delete; /**< No copy assignment operator allowed, @private. */ SedInstance &operator=(SedInstance &&pRhs) noexcept = delete; /**< No move assignment operator allowed, @private. */ + /** + * @brief The status of an instance. + * + * The status of an instance, i.e. whether it is idle, running, or paused. + */ + + enum class Status + { + IDLE, /**< The instance is idle. */ + RUNNING, /**< The instance is currently running. */ + PAUSED /**< The instance is currently paused. */ + }; + + /** + * @brief Return the status of this instance. + * + * Return the status of this instance. + * + * @return The status of this instance. + */ + + Status status() const noexcept; + /** * @brief Run all the tasks associated with this instance. * @@ -63,16 +86,6 @@ class LIBOPENCOR_EXPORT SedInstance: public Logger bool startRun(); - /** - * @brief Return whether this instance is currently running. - * - * Return whether this instance is currently running. - * - * @return @c true if this instance is running, @c false otherwise. - */ - - bool isRunning() const noexcept; - /** * @brief Wait for any currently-running instance to complete. * diff --git a/src/bindings/javascript/sed.cpp b/src/bindings/javascript/sed.cpp index e8292b529..c1f964668 100644 --- a/src/bindings/javascript/sed.cpp +++ b/src/bindings/javascript/sed.cpp @@ -86,11 +86,16 @@ void sedApi() // SedInstance API. + emscripten::enum_("SedInstance.Status") + .value("IDLE", libOpenCOR::SedInstance::Status::IDLE) + .value("RUNNING", libOpenCOR::SedInstance::Status::RUNNING) + .value("PAUSED", libOpenCOR::SedInstance::Status::PAUSED); + emscripten::class_>("SedInstance") .smart_ptr("SedInstance") + .property("status", &libOpenCOR::SedInstance::status) .function("run", &libOpenCOR::SedInstance::run) .function("startRun", &libOpenCOR::SedInstance::startRun) - .property("isRunning", &libOpenCOR::SedInstance::isRunning) .function("waitForRun", &libOpenCOR::SedInstance::waitForRun) .function("pauseRun", &libOpenCOR::SedInstance::pauseRun) .function("resumeRun", &libOpenCOR::SedInstance::resumeRun) @@ -101,6 +106,14 @@ void sedApi() .property("tasks", &libOpenCOR::SedInstance::tasks) .function("task", &libOpenCOR::SedInstance::task); + EM_ASM({ + if (Module["SedInstance"]) { + Module["SedInstance"]["Status"] = Module["SedInstance.Status"]; + + delete Module["SedInstance.Status"]; + } + }); + // SedInstanceTask API. emscripten::class_>("SedInstanceTask") diff --git a/src/bindings/python/sed.cpp b/src/bindings/python/sed.cpp index 7098a14ac..9259997f6 100644 --- a/src/bindings/python/sed.cpp +++ b/src/bindings/python/sed.cpp @@ -96,9 +96,15 @@ void sedApi(nb::module_ &m) nb::class_ sedInstance(m, "SedInstance"); - sedInstance.def("run", &libOpenCOR::SedInstance::run, "Run all the tasks associated with this instance.", nb::call_guard()) + nb::enum_(sedInstance, "Status") + .value("Idle", libOpenCOR::SedInstance::Status::IDLE) + .value("Running", libOpenCOR::SedInstance::Status::RUNNING) + .value("Paused", libOpenCOR::SedInstance::Status::PAUSED) + .export_values(); + + sedInstance.def_prop_ro("status", &libOpenCOR::SedInstance::status, "Return the status of this instance.") + .def("run", &libOpenCOR::SedInstance::run, "Run all the tasks associated with this instance.", nb::call_guard()) .def("start_run", &libOpenCOR::SedInstance::startRun, "Start running, in a background thread, all the tasks associated with this instance.") - .def_prop_ro("is_running", &libOpenCOR::SedInstance::isRunning, "Return whether this instance is currently running.") .def("wait_for_run", &libOpenCOR::SedInstance::waitForRun, "Wait for any currently-running instance to complete.", nb::call_guard()) .def("pause_run", &libOpenCOR::SedInstance::pauseRun, "Pause a currently-running instance.") .def("resume_run", &libOpenCOR::SedInstance::resumeRun, "Resume a currently-paused instance.") diff --git a/src/sed/sedinstance.cpp b/src/sed/sedinstance.cpp index 31465998c..8ff17ecaf 100644 --- a/src/sed/sedinstance.cpp +++ b/src/sed/sedinstance.cpp @@ -87,6 +87,19 @@ SedInstance::Impl::Impl(const SedDocumentPtr &pDocument) } } +SedInstance::Status SedInstance::Impl::status() const +{ + if (!mRunning.load(std::memory_order_acquire)) { + return Status::IDLE; + } + + if ((mRunControl.load(std::memory_order_relaxed) & INSTANCE_RUN_CONTROL_PAUSE) != 0U) { + return Status::PAUSED; + } + + return Status::RUNNING; +} + double SedInstance::Impl::run() { // Reset ourselves. @@ -171,11 +184,6 @@ bool SedInstance::Impl::startRun() return true; } -bool SedInstance::Impl::isRunning() const -{ - return mRunning.load(std::memory_order_acquire); -} - double SedInstance::Impl::waitForRun() { const std::scoped_lock runLock(mRunMutex); @@ -270,6 +278,11 @@ const SedInstance::Impl *SedInstance::pimpl() const return static_cast(Logger::mPimpl.get()); } +SedInstance::Status SedInstance::status() const noexcept +{ + return pimpl()->status(); +} + double SedInstance::run() { return pimpl()->run(); @@ -280,11 +293,6 @@ bool SedInstance::startRun() return pimpl()->startRun(); } -bool SedInstance::isRunning() const noexcept -{ - return pimpl()->isRunning(); -} - double SedInstance::waitForRun() { return pimpl()->waitForRun(); diff --git a/src/sed/sedinstance_p.h b/src/sed/sedinstance_p.h index 4694bc2c5..a68da67ca 100644 --- a/src/sed/sedinstance_p.h +++ b/src/sed/sedinstance_p.h @@ -47,9 +47,10 @@ class SedInstance::Impl: public Logger::Impl explicit Impl(const SedDocumentPtr &pDocument); + Status status() const; + double run(); bool startRun(); - bool isRunning() const; double waitForRun(); void pauseRun(); void resumeRun(); diff --git a/tests/api/sed/concurrenttests.cpp b/tests/api/sed/concurrenttests.cpp index 6ff5c9a8c..05636a649 100644 --- a/tests/api/sed/concurrenttests.cpp +++ b/tests/api/sed/concurrenttests.cpp @@ -146,7 +146,7 @@ TEST(ConcurrentSedTest, parallelAsyncLifecycle) } for (const auto &instance : instances) { - EXPECT_FALSE(instance->isRunning()); + EXPECT_EQ(instance->status(), libOpenCOR::SedInstance::Status::IDLE); EXPECT_FALSE(instance->hasIssues()); } } diff --git a/tests/api/sed/instancetests.cpp b/tests/api/sed/instancetests.cpp index f287b9f4e..5219d7fe2 100644 --- a/tests/api/sed/instancetests.cpp +++ b/tests/api/sed/instancetests.cpp @@ -109,7 +109,7 @@ TEST(InstanceSedTest, asynchronousRunWithoutActiveRun) auto document {libOpenCOR::SedDocument::create(file)}; auto instance {document->instantiate()}; - EXPECT_FALSE(instance->isRunning()); + EXPECT_EQ(instance->status(), libOpenCOR::SedInstance::Status::IDLE); EXPECT_EQ(instance->waitForRun(), 0.0); } @@ -124,14 +124,14 @@ TEST(InstanceSedTest, asynchronousRunLifecycle) EXPECT_TRUE(instance->startRun()); for (size_t i {0}; i < WAIT_ITERATIONS; ++i) { - if (!instance->isRunning()) { + if (instance->status() == libOpenCOR::SedInstance::Status::IDLE) { break; } std::this_thread::sleep_for(std::chrono::milliseconds(1)); } - EXPECT_FALSE(instance->isRunning()); + EXPECT_EQ(instance->status(), libOpenCOR::SedInstance::Status::IDLE); EXPECT_GT(instance->waitForRun(), 0.0); EXPECT_FALSE(instance->hasIssues()); } @@ -218,7 +218,7 @@ TEST(InstanceSedTest, stopRun) instance->stopRun(); for (size_t i {0}; i < WAIT_ITERATIONS; ++i) { - if (!instance->isRunning()) { + if (instance->status() == libOpenCOR::SedInstance::Status::IDLE) { break; } @@ -237,7 +237,7 @@ TEST(InstanceSedTest, stopRunWhenNotRunning) instance->stopRun(); - EXPECT_FALSE(instance->isRunning()); + EXPECT_EQ(instance->status(), libOpenCOR::SedInstance::Status::IDLE); EXPECT_DOUBLE_EQ(instance->progress(), 0.0); } @@ -268,7 +268,7 @@ TEST(InstanceSedTest, stopRunResultsHaveNans) instance->stopRun(); for (size_t i {0}; i < WAIT_ITERATIONS; ++i) { - if (!instance->isRunning()) { + if (instance->status() == libOpenCOR::SedInstance::Status::IDLE) { break; } @@ -336,14 +336,14 @@ TEST(InstanceSedTest, pauseRunAndResumeRun) instance->stopRun(); for (size_t i {0}; i < WAIT_ITERATIONS; ++i) { - if (!instance->isRunning()) { + if (instance->status() == libOpenCOR::SedInstance::Status::IDLE) { break; } std::this_thread::sleep_for(std::chrono::milliseconds(1)); } - EXPECT_FALSE(instance->isRunning()); + EXPECT_EQ(instance->status(), libOpenCOR::SedInstance::Status::IDLE); EXPECT_LT(instance->progress(), 1.0); EXPECT_FALSE(instance->hasIssues()); } @@ -357,7 +357,7 @@ TEST(InstanceSedTest, pauseRunAndResumeRunWhenNotRunning) instance->pauseRun(); instance->resumeRun(); - EXPECT_FALSE(instance->isRunning()); + EXPECT_EQ(instance->status(), libOpenCOR::SedInstance::Status::IDLE); EXPECT_DOUBLE_EQ(instance->progress(), 0.0); } @@ -393,14 +393,14 @@ TEST(InstanceSedTest, pauseRunThenStopRun) instance->stopRun(); for (size_t i {0}; i < WAIT_ITERATIONS; ++i) { - if (!instance->isRunning()) { + if (instance->status() == libOpenCOR::SedInstance::Status::IDLE) { break; } std::this_thread::sleep_for(std::chrono::milliseconds(1)); } - EXPECT_FALSE(instance->isRunning()); + EXPECT_EQ(instance->status(), libOpenCOR::SedInstance::Status::IDLE); EXPECT_LT(instance->progress(), 1.0); EXPECT_FALSE(instance->hasIssues()); } @@ -437,14 +437,14 @@ TEST(InstanceSedTest, pauseRunAndResumeRunWithNaturalCompletion) instance->resumeRun(); for (size_t i {0}; i < WAIT_ITERATIONS; ++i) { - if (!instance->isRunning()) { + if (instance->status() == libOpenCOR::SedInstance::Status::IDLE) { break; } std::this_thread::sleep_for(std::chrono::milliseconds(1)); } - EXPECT_FALSE(instance->isRunning()); + EXPECT_EQ(instance->status(), libOpenCOR::SedInstance::Status::IDLE); EXPECT_GT(instance->waitForRun(), 0.0); EXPECT_FALSE(instance->hasIssues()); } @@ -478,14 +478,14 @@ TEST(InstanceSedTest, startRunWhileAlreadyRunning) instance->stopRun(); for (size_t i {0}; i < WAIT_ITERATIONS; ++i) { - if (!instance->isRunning()) { + if (instance->status() == libOpenCOR::SedInstance::Status::IDLE) { break; } std::this_thread::sleep_for(std::chrono::milliseconds(1)); } - EXPECT_FALSE(instance->isRunning()); + EXPECT_EQ(instance->status(), libOpenCOR::SedInstance::Status::IDLE); EXPECT_LT(instance->progress(), 1.0); EXPECT_FALSE(instance->hasIssues()); } @@ -501,26 +501,26 @@ TEST(InstanceSedTest, startRunAfterPreviousRunCompleted) EXPECT_TRUE(instance->startRun()); for (size_t i {0}; i < WAIT_ITERATIONS; ++i) { - if (!instance->isRunning()) { + if (instance->status() == libOpenCOR::SedInstance::Status::IDLE) { break; } std::this_thread::sleep_for(std::chrono::milliseconds(1)); } - EXPECT_FALSE(instance->isRunning()); + EXPECT_EQ(instance->status(), libOpenCOR::SedInstance::Status::IDLE); EXPECT_TRUE(instance->startRun()); for (size_t i {0}; i < WAIT_ITERATIONS; ++i) { - if (!instance->isRunning()) { + if (instance->status() == libOpenCOR::SedInstance::Status::IDLE) { break; } std::this_thread::sleep_for(std::chrono::milliseconds(1)); } - EXPECT_FALSE(instance->isRunning()); + EXPECT_EQ(instance->status(), libOpenCOR::SedInstance::Status::IDLE); EXPECT_GT(instance->waitForRun(), 0.0); EXPECT_FALSE(instance->hasIssues()); } diff --git a/tests/bindings/javascript/res/res/libopencor.js b/tests/bindings/javascript/res/res/libopencor.js index 25bb494a1..0db7faa49 100644 --- a/tests/bindings/javascript/res/res/libopencor.js +++ b/tests/bindings/javascript/res/res/libopencor.js @@ -115,7 +115,7 @@ function populateAxis(axisId) { } export function run() { - if (instance.isRunning) { + if (instance.status !== loc.SedInstance.Status.IDLE) { // Toggle between pause and resume. if (isPaused) { @@ -260,7 +260,7 @@ function runAsync() { updatePlottingAreaAndAxesInfo(completedSteps + 1); } - if (!instance.isRunning) { + if (instance.status === loc.SedInstance.Status.IDLE) { clearInterval(intervalId); instance.waitForRun(); console.timeEnd('Computing time'); diff --git a/tests/bindings/javascript/sed.concurrent.test.js b/tests/bindings/javascript/sed.concurrent.test.js index a72dfd887..98e7fa1f2 100644 --- a/tests/bindings/javascript/sed.concurrent.test.js +++ b/tests/bindings/javascript/sed.concurrent.test.js @@ -124,7 +124,7 @@ test.describe('Sed concurrent tests', () => { } for (const instance of instances) { - assert.strictEqual(instance.isRunning, false); + assert.strictEqual(instance.status, loc.SedInstance.Status.IDLE); assert.strictEqual(instance.hasIssues, false); } }); diff --git a/tests/bindings/javascript/sed.instance.test.js b/tests/bindings/javascript/sed.instance.test.js index 7c3c4c6a1..98e8942a0 100644 --- a/tests/bindings/javascript/sed.instance.test.js +++ b/tests/bindings/javascript/sed.instance.test.js @@ -136,7 +136,7 @@ test.describe('Sed instance tests', () => { const document = new loc.SedDocument(file); const instance = document.instantiate(); - assert.strictEqual(instance.isRunning, false); + assert.strictEqual(instance.status, loc.SedInstance.Status.IDLE); assert.strictEqual(instance.waitForRun(), 0.0); }); @@ -151,14 +151,14 @@ test.describe('Sed instance tests', () => { assert.strictEqual(instance.startRun(), true); for (let i = 0; i < 200; ++i) { - if (!instance.isRunning) { + if (instance.status === loc.SedInstance.Status.IDLE) { break; } await sleep(1); } - assert.strictEqual(instance.isRunning, false); + assert.strictEqual(instance.status, loc.SedInstance.Status.IDLE); assert.ok(instance.waitForRun() > 0.0); assert.strictEqual(instance.hasIssues, false); }); @@ -255,7 +255,7 @@ test.describe('Sed instance tests', () => { instance.stopRun(); for (let i = 0; i < WAIT_ITERATIONS; ++i) { - if (!instance.isRunning) { + if (instance.status === loc.SedInstance.Status.IDLE) { break; } @@ -295,7 +295,7 @@ test.describe('Sed instance tests', () => { instance.stopRun(); for (let i = 0; i < WAIT_ITERATIONS; ++i) { - if (!instance.isRunning) { + if (instance.status === loc.SedInstance.Status.IDLE) { break; } @@ -340,7 +340,7 @@ test.describe('Sed instance tests', () => { instance.stopRun(); - assert.strictEqual(instance.isRunning, false); + assert.strictEqual(instance.status, loc.SedInstance.Status.IDLE); assert.strictEqual(instance.progress, 0.0); }); @@ -378,14 +378,14 @@ test.describe('Sed instance tests', () => { instance.stopRun(); for (let i = 0; i < WAIT_ITERATIONS; ++i) { - if (!instance.isRunning) { + if (instance.status === loc.SedInstance.Status.IDLE) { break; } await sleep(1); } - assert.strictEqual(instance.isRunning, false); + assert.strictEqual(instance.status, loc.SedInstance.Status.IDLE); assert.ok(instance.progress < 1.0); assert.strictEqual(instance.hasIssues, false); }); @@ -401,7 +401,7 @@ test.describe('Sed instance tests', () => { instance.pauseRun(); instance.resumeRun(); - assert.strictEqual(instance.isRunning, false); + assert.strictEqual(instance.status, loc.SedInstance.Status.IDLE); assert.strictEqual(instance.progress, 0.0); }); @@ -438,14 +438,14 @@ test.describe('Sed instance tests', () => { instance.stopRun(); for (let i = 0; i < WAIT_ITERATIONS; ++i) { - if (!instance.isRunning) { + if (instance.status === loc.SedInstance.Status.IDLE) { break; } await sleep(1); } - assert.strictEqual(instance.isRunning, false); + assert.strictEqual(instance.status, loc.SedInstance.Status.IDLE); assert.ok(instance.progress < 1.0); assert.strictEqual(instance.hasIssues, false); }); @@ -483,14 +483,14 @@ test.describe('Sed instance tests', () => { instance.resumeRun(); for (let i = 0; i < WAIT_ITERATIONS; ++i) { - if (!instance.isRunning) { + if (instance.status === loc.SedInstance.Status.IDLE) { break; } await sleep(1); } - assert.strictEqual(instance.isRunning, false); + assert.strictEqual(instance.status, loc.SedInstance.Status.IDLE); assert.ok(instance.waitForRun() > 0.0); assert.strictEqual(instance.hasIssues, false); }); @@ -526,14 +526,14 @@ test.describe('Sed instance tests', () => { instance.stopRun(); for (let i = 0; i < WAIT_ITERATIONS; ++i) { - if (!instance.isRunning) { + if (instance.status === loc.SedInstance.Status.IDLE) { break; } await sleep(1); } - assert.strictEqual(instance.isRunning, false); + assert.strictEqual(instance.status, loc.SedInstance.Status.IDLE); assert.ok(instance.progress < 1.0); assert.strictEqual(instance.hasIssues, false); }); @@ -551,26 +551,26 @@ test.describe('Sed instance tests', () => { assert.strictEqual(instance.startRun(), true); for (let i = 0; i < WAIT_ITERATIONS; ++i) { - if (!instance.isRunning) { + if (instance.status === loc.SedInstance.Status.IDLE) { break; } await sleep(1); } - assert.strictEqual(instance.isRunning, false); + assert.strictEqual(instance.status, loc.SedInstance.Status.IDLE); assert.strictEqual(instance.startRun(), true); for (let i = 0; i < WAIT_ITERATIONS; ++i) { - if (!instance.isRunning) { + if (instance.status === loc.SedInstance.Status.IDLE) { break; } await sleep(1); } - assert.strictEqual(instance.isRunning, false); + assert.strictEqual(instance.status, loc.SedInstance.Status.IDLE); assert.ok(instance.waitForRun() > 0.0); assert.strictEqual(instance.hasIssues, false); }); diff --git a/tests/bindings/python/test_sed_concurrent.py b/tests/bindings/python/test_sed_concurrent.py index 66734fc35..f2d706f79 100644 --- a/tests/bindings/python/test_sed_concurrent.py +++ b/tests/bindings/python/test_sed_concurrent.py @@ -134,5 +134,5 @@ def test_parallel_async_lifecycle(): assert instance.wait_for_run() > 0.0 for instance in instances: - assert instance.is_running is False + assert instance.status == loc.SedInstance.Status.Idle assert not instance.has_issues diff --git a/tests/bindings/python/test_sed_instance.py b/tests/bindings/python/test_sed_instance.py index a1cd79f99..14408e5cd 100644 --- a/tests/bindings/python/test_sed_instance.py +++ b/tests/bindings/python/test_sed_instance.py @@ -135,7 +135,7 @@ def test_asynchronous_run_without_active_run(): document = loc.SedDocument(file) instance = document.instantiate() - assert instance.is_running is False + assert instance.status == loc.SedInstance.Status.Idle assert instance.wait_for_run() == 0.0 @@ -147,12 +147,12 @@ def test_asynchronous_run_lifecycle(): assert instance.start_run() is True for _ in range(200): - if not instance.is_running: + if instance.status == loc.SedInstance.Status.Idle: break time.sleep(0.001) - assert instance.is_running is False + assert instance.status == loc.SedInstance.Status.Idle assert instance.wait_for_run() > 0.0 assert not instance.has_issues @@ -231,7 +231,7 @@ def test_stop_run(): instance.stop_run() for _ in range(WAIT_ITERATIONS): - if not instance.is_running: + if instance.status == loc.SedInstance.Status.Idle: break time.sleep(0.001) @@ -263,7 +263,7 @@ def test_stop_run_results_have_nans(): instance.stop_run() for _ in range(WAIT_ITERATIONS): - if not instance.is_running: + if instance.status == loc.SedInstance.Status.Idle: break time.sleep(0.001) @@ -303,7 +303,7 @@ def test_stop_run_when_not_running(): instance.stop_run() - assert instance.is_running is False + assert instance.status == loc.SedInstance.Status.Idle assert instance.progress == 0.0 @@ -336,12 +336,12 @@ def test_pause_run_and_resume_run(): instance.stop_run() for _ in range(WAIT_ITERATIONS): - if not instance.is_running: + if instance.status == loc.SedInstance.Status.Idle: break time.sleep(0.001) - assert instance.is_running is False + assert instance.status == loc.SedInstance.Status.Idle assert instance.progress < 1.0 assert not instance.has_issues @@ -354,7 +354,7 @@ def test_pause_run_and_resume_run_when_not_running(): instance.pause_run() instance.resume_run() - assert instance.is_running is False + assert instance.status == loc.SedInstance.Status.Idle assert instance.progress == 0.0 @@ -386,12 +386,12 @@ def test_pause_run_then_stop_run(): instance.stop_run() for _ in range(WAIT_ITERATIONS): - if not instance.is_running: + if instance.status == loc.SedInstance.Status.Idle: break time.sleep(0.001) - assert instance.is_running is False + assert instance.status == loc.SedInstance.Status.Idle assert instance.progress < 1.0 assert not instance.has_issues @@ -424,12 +424,12 @@ def test_pause_run_and_resume_run_with_natural_completion(): instance.resume_run() for _ in range(WAIT_ITERATIONS): - if not instance.is_running: + if instance.status == loc.SedInstance.Status.Idle: break time.sleep(0.001) - assert instance.is_running is False + assert instance.status == loc.SedInstance.Status.Idle assert instance.wait_for_run() > 0.0 assert not instance.has_issues @@ -460,12 +460,12 @@ def test_start_run_while_already_running(): instance.stop_run() for _ in range(WAIT_ITERATIONS): - if not instance.is_running: + if instance.status == loc.SedInstance.Status.Idle: break time.sleep(0.001) - assert instance.is_running is False + assert instance.status == loc.SedInstance.Status.Idle assert instance.progress < 1.0 assert not instance.has_issues @@ -480,22 +480,22 @@ def test_start_run_after_previous_run_completed(): assert instance.start_run() is True for _ in range(WAIT_ITERATIONS): - if not instance.is_running: + if instance.status == loc.SedInstance.Status.Idle: break time.sleep(0.001) - assert instance.is_running is False + assert instance.status == loc.SedInstance.Status.Idle assert instance.start_run() is True for _ in range(WAIT_ITERATIONS): - if not instance.is_running: + if instance.status == loc.SedInstance.Status.Idle: break time.sleep(0.001) - assert instance.is_running is False + assert instance.status == loc.SedInstance.Status.Idle assert instance.wait_for_run() > 0.0 assert not instance.has_issues From 83e132711b9d4499b794dc30528a13d130677288 Mon Sep 17 00:00:00 2001 From: Alan Garny Date: Thu, 23 Jul 2026 11:23:34 +1200 Subject: [PATCH 3/3] Python: stop exporting enum values. Indeed, we don't currently take advantage of it (in our tests, at least) and it could result in name collision, not to mention that standard Python enums don't do this. --- src/bindings/python/file.cpp | 3 +-- src/bindings/python/logger.cpp | 3 +-- src/bindings/python/sed.cpp | 3 +-- src/bindings/python/solver.cpp | 18 ++++++------------ 4 files changed, 9 insertions(+), 18 deletions(-) diff --git a/src/bindings/python/file.cpp b/src/bindings/python/file.cpp index 55b6cde0f..b39973a71 100644 --- a/src/bindings/python/file.cpp +++ b/src/bindings/python/file.cpp @@ -33,8 +33,7 @@ void fileApi(nb::module_ &m) .value("CellmlFile", libOpenCOR::File::Type::CELLML_FILE) .value("SedmlFile", libOpenCOR::File::Type::SEDML_FILE) .value("CombineArchive", libOpenCOR::File::Type::COMBINE_ARCHIVE) - .value("IrretrievableFile", libOpenCOR::File::Type::IRRETRIEVABLE_FILE) - .export_values(); + .value("IrretrievableFile", libOpenCOR::File::Type::IRRETRIEVABLE_FILE); file.def(nb::new_(&libOpenCOR::File::create), "Create a File object.", nb::arg("file_name_or_url"), nb::arg("retrieve_contents") = true) .def_prop_ro("type", &libOpenCOR::File::type, "Return the type.") diff --git a/src/bindings/python/logger.cpp b/src/bindings/python/logger.cpp index ec1013521..d6c75c3e6 100644 --- a/src/bindings/python/logger.cpp +++ b/src/bindings/python/logger.cpp @@ -47,8 +47,7 @@ void loggerApi(nb::module_ &m) nb::enum_(issue, "Type") .value("Error", libOpenCOR::Issue::Type::ERROR) - .value("Warning", libOpenCOR::Issue::Type::WARNING) - .export_values(); + .value("Warning", libOpenCOR::Issue::Type::WARNING); issue.def_prop_ro("type", &libOpenCOR::Issue::type, "Return the type.") .def_prop_ro("type_as_string", &libOpenCOR::Issue::typeAsString, "Return the type as a string.") diff --git a/src/bindings/python/sed.cpp b/src/bindings/python/sed.cpp index 9259997f6..71dd9d6d1 100644 --- a/src/bindings/python/sed.cpp +++ b/src/bindings/python/sed.cpp @@ -99,8 +99,7 @@ void sedApi(nb::module_ &m) nb::enum_(sedInstance, "Status") .value("Idle", libOpenCOR::SedInstance::Status::IDLE) .value("Running", libOpenCOR::SedInstance::Status::RUNNING) - .value("Paused", libOpenCOR::SedInstance::Status::PAUSED) - .export_values(); + .value("Paused", libOpenCOR::SedInstance::Status::PAUSED); sedInstance.def_prop_ro("status", &libOpenCOR::SedInstance::status, "Return the status of this instance.") .def("run", &libOpenCOR::SedInstance::run, "Run all the tasks associated with this instance.", nb::call_guard()) diff --git a/src/bindings/python/solver.cpp b/src/bindings/python/solver.cpp index b7e2cdcec..0a2217ced 100644 --- a/src/bindings/python/solver.cpp +++ b/src/bindings/python/solver.cpp @@ -29,8 +29,7 @@ void solverApi(nb::module_ &m) nb::enum_(solver, "Type") .value("Ode", libOpenCOR::Solver::Type::ODE) - .value("Nla", libOpenCOR::Solver::Type::NLA) - .export_values(); + .value("Nla", libOpenCOR::Solver::Type::NLA); solver.def_prop_ro("type", &libOpenCOR::Solver::type, "Return the type.") .def_prop_ro("id", &libOpenCOR::Solver::id, "Return the (KiSAO) id.") @@ -59,13 +58,11 @@ void solverApi(nb::module_ &m) nb::enum_(solverCvode, "IntegrationMethod") .value("AdamsMoulton", libOpenCOR::SolverCvode::IntegrationMethod::ADAMS_MOULTON) - .value("Bdf", libOpenCOR::SolverCvode::IntegrationMethod::BDF) - .export_values(); + .value("Bdf", libOpenCOR::SolverCvode::IntegrationMethod::BDF); nb::enum_(solverCvode, "IterationType") .value("Functional", libOpenCOR::SolverCvode::IterationType::FUNCTIONAL) - .value("Newton", libOpenCOR::SolverCvode::IterationType::NEWTON) - .export_values(); + .value("Newton", libOpenCOR::SolverCvode::IterationType::NEWTON); nb::enum_(solverCvode, "LinearSolver") .value("Dense", libOpenCOR::SolverCvode::LinearSolver::DENSE) @@ -73,13 +70,11 @@ void solverApi(nb::module_ &m) .value("Diagonal", libOpenCOR::SolverCvode::LinearSolver::DIAGONAL) .value("Gmres", libOpenCOR::SolverCvode::LinearSolver::GMRES) .value("Bicgstab", libOpenCOR::SolverCvode::LinearSolver::BICGSTAB) - .value("Tfqmr", libOpenCOR::SolverCvode::LinearSolver::TFQMR) - .export_values(); + .value("Tfqmr", libOpenCOR::SolverCvode::LinearSolver::TFQMR); nb::enum_(solverCvode, "Preconditioner") .value("No", libOpenCOR::SolverCvode::Preconditioner::NO) - .value("Banded", libOpenCOR::SolverCvode::Preconditioner::BANDED) - .export_values(); + .value("Banded", libOpenCOR::SolverCvode::Preconditioner::BANDED); solverCvode.def(nb::new_(&libOpenCOR::SolverCvode::create), "Create a SolverCvode object.") .def_prop_rw("maximum_step", &libOpenCOR::SolverCvode::maximumStep, &libOpenCOR::SolverCvode::setMaximumStep, "The maximum step.") @@ -121,8 +116,7 @@ void solverApi(nb::module_ &m) .value("Banded", libOpenCOR::SolverKinsol::LinearSolver::BANDED) .value("Gmres", libOpenCOR::SolverKinsol::LinearSolver::GMRES) .value("Bicgstab", libOpenCOR::SolverKinsol::LinearSolver::BICGSTAB) - .value("Tfqmr", libOpenCOR::SolverKinsol::LinearSolver::TFQMR) - .export_values(); + .value("Tfqmr", libOpenCOR::SolverKinsol::LinearSolver::TFQMR); solverKinsol.def(nb::new_(&libOpenCOR::SolverKinsol::create), "Create a SolverKinsol object.") .def_prop_rw("maximum_number_of_iterations", &libOpenCOR::SolverKinsol::maximumNumberOfIterations, &libOpenCOR::SolverKinsol::setMaximumNumberOfIterations, "The maximum number of iterations.")