From 9bac0eda6b16bedcfc21dfe626e3fb892e7884da Mon Sep 17 00:00:00 2001 From: Alan Garny Date: Thu, 28 May 2026 23:52:07 +1200 Subject: [PATCH 1/5] New version. --- VERSION.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION.txt b/VERSION.txt index 77621095f..4c2294992 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -0.20260528.2 +0.20260529.0 From 9ee5c6517ac9011f1b135e0a7018fb93b28d72bc Mon Sep 17 00:00:00 2001 From: Alan Garny Date: Fri, 29 May 2026 00:22:57 +1200 Subject: [PATCH 2/5] JavaScript: improved our bindings. --- src/bindings/javascript/logger.cpp | 5 ++++ src/bindings/javascript/main.cpp | 42 ++++++++++++++++++++++++++++++ src/bindings/javascript/solver.cpp | 5 ++++ 3 files changed, 52 insertions(+) diff --git a/src/bindings/javascript/logger.cpp b/src/bindings/javascript/logger.cpp index 9f4715411..7f1ed02f0 100644 --- a/src/bindings/javascript/logger.cpp +++ b/src/bindings/javascript/logger.cpp @@ -50,5 +50,10 @@ void loggerApi() Module["Issue"]["Type"] = Module["Issue.Type"]; delete Module["Issue.Type"]; + + Module["Issue"].prototype.toString = function() + { + return this.description; + }; }); } diff --git a/src/bindings/javascript/main.cpp b/src/bindings/javascript/main.cpp index ecf4f8c4d..43eedfca6 100644 --- a/src/bindings/javascript/main.cpp +++ b/src/bindings/javascript/main.cpp @@ -48,4 +48,46 @@ EMSCRIPTEN_BINDINGS(libOpenCOR) sedApi(); solverApi(); versionApi(); + + // Make all registered vectors behave like native JavaScript arrays: expose a .length property and [Symbol.iterator] + // so that for-of loops, spread syntax, and destructuring work without requiring callers to use .size()/.get(). + // Note: the code within the EM_ASM() block is such that it doesn't rely on top-level comma-heavy literals since + // those commas can get interpreted as macro argument separators by the C++ preprocessor, which causes + // compilation errors. + + EM_ASM({ + let vectorNames = 'Doubles|FilePtrs|IssuePtrs|SedAbstractTaskPtrs|SedChangePtrs|SedDataDescriptionPtrs|SedDataGeneratorPtrs|SedInstanceTaskPtrs|SedModelPtrs|SedOutputPtrs|SedSimulationPtrs|SedStylePtrs|Strings'.split('|'); + + vectorNames.forEach(function(name) { + let prototype = Module[name].prototype; + + Object.defineProperty(prototype, 'length', { + get: function() { return this.size(); } + }); + + prototype[Symbol.iterator] = function() + { + let i = 0; + let n = this.size(); + let iterator = {}; + + iterator.next = () => + { + let result = {}; + + if (i < n) { + result.value = this.get(i++); + result.done = false; + } else { + result.value = undefined; + result.done = true; + } + + return result; + }; + + return iterator; + }; +}); +}); } diff --git a/src/bindings/javascript/solver.cpp b/src/bindings/javascript/solver.cpp index cafd378ba..3b9eaf0e4 100644 --- a/src/bindings/javascript/solver.cpp +++ b/src/bindings/javascript/solver.cpp @@ -35,6 +35,11 @@ void solverApi() Module["Solver"]["Type"] = Module["Solver.Type"]; delete Module["Solver.Type"]; + + Module["Solver"].prototype.toString = function() + { + return this.name; + }; }); // SolverOde API. From 51d8bf34b3ce5506a154acff24668f61eb42b6b6 Mon Sep 17 00:00:00 2001 From: Alan Garny Date: Fri, 29 May 2026 00:30:47 +1200 Subject: [PATCH 3/5] JavaScript: improved our tests. --- tests/bindings/javascript/file.basic.test.js | 12 ++--- tests/bindings/javascript/file.child.test.js | 8 +-- .../javascript/logger.coverage.test.js | 17 ++++-- .../bindings/javascript/res/res/libopencor.js | 12 ++--- .../bindings/javascript/sed.coverage.test.js | 52 +++++++++---------- tests/bindings/javascript/utils.in.js | 14 ++--- 6 files changed, 62 insertions(+), 53 deletions(-) diff --git a/tests/bindings/javascript/file.basic.test.js b/tests/bindings/javascript/file.basic.test.js index 475f0b1af..8e7177433 100644 --- a/tests/bindings/javascript/file.basic.test.js +++ b/tests/bindings/javascript/file.basic.test.js @@ -89,7 +89,7 @@ test.describe('File basic tests', () => { assert.strictEqual(fileManager.hasFiles, false); assert.strictEqual(fileManager.fileCount, 0); - assert.strictEqual(fileManager.files.size(), 0); + assert.strictEqual(fileManager.files.length, 0); assert.strictEqual(fileManager.file(0), null); assert.strictEqual(fileManager.fileFromFileNameOrUrl(utils.LOCAL_FILE), null); @@ -98,7 +98,7 @@ test.describe('File basic tests', () => { assert.strictEqual(sameFileManager.hasFiles, true); assert.strictEqual(sameFileManager.fileCount, 1); - assert.strictEqual(sameFileManager.files.size(), 1); + assert.strictEqual(sameFileManager.files.length, 1); assert.deepStrictEqual(fileManager.file(0), localFile); assert.deepStrictEqual(sameFileManager.fileFromFileNameOrUrl(utils.LOCAL_FILE), localFile); @@ -106,7 +106,7 @@ test.describe('File basic tests', () => { assert.strictEqual(fileManager.hasFiles, true); assert.strictEqual(fileManager.fileCount, 2); - assert.strictEqual(fileManager.files.size(), 2); + assert.strictEqual(fileManager.files.length, 2); assert.deepStrictEqual(fileManager.file(1), remoteFile); assert.deepStrictEqual(fileManager.fileFromFileNameOrUrl(utils.REMOTE_FILE), remoteFile); @@ -114,7 +114,7 @@ test.describe('File basic tests', () => { assert.strictEqual(sameFileManager.hasFiles, true); assert.strictEqual(sameFileManager.fileCount, 1); - assert.strictEqual(sameFileManager.files.size(), 1); + assert.strictEqual(sameFileManager.files.length, 1); assert.deepStrictEqual(fileManager.file(1), null); assert.deepStrictEqual(sameFileManager.fileFromFileNameOrUrl(utils.LOCAL_FILE), null); @@ -122,7 +122,7 @@ test.describe('File basic tests', () => { assert.strictEqual(sameFileManager.hasFiles, true); assert.strictEqual(sameFileManager.fileCount, 2); - assert.strictEqual(sameFileManager.files.size(), 2); + assert.strictEqual(sameFileManager.files.length, 2); assert.deepStrictEqual(fileManager.file(1), localFile); assert.deepStrictEqual(sameFileManager.fileFromFileNameOrUrl(utils.LOCAL_FILE), localFile); @@ -130,7 +130,7 @@ test.describe('File basic tests', () => { assert.strictEqual(fileManager.hasFiles, false); assert.strictEqual(fileManager.fileCount, 0); - assert.strictEqual(fileManager.files.size(), 0); + assert.strictEqual(fileManager.files.length, 0); assert.deepStrictEqual(fileManager.file(0), null); assert.deepStrictEqual(fileManager.file(1), null); assert.deepStrictEqual(fileManager.fileFromFileNameOrUrl(utils.REMOTE_FILE), null); diff --git a/tests/bindings/javascript/file.child.test.js b/tests/bindings/javascript/file.child.test.js index f8dc88af7..ed53e9d31 100644 --- a/tests/bindings/javascript/file.child.test.js +++ b/tests/bindings/javascript/file.child.test.js @@ -34,8 +34,8 @@ test.describe('File type tests', () => { assert.strictEqual(file.hasChildFiles, true); assert.strictEqual(file.childFileCount, specificChildFileNames.length + 1); - assert.strictEqual(file.childFileNames.size(), specificChildFileNames.length + 1); - assert.strictEqual(file.childFiles.size(), specificChildFileNames.length + 1); + assert.strictEqual(file.childFileNames.length, specificChildFileNames.length + 1); + assert.strictEqual(file.childFiles.length, specificChildFileNames.length + 1); let index = -1; const simulationFile = file.childFileFromFileName('simulation.json'); @@ -59,8 +59,8 @@ test.describe('File type tests', () => { assert.strictEqual(file.hasChildFiles, false); assert.strictEqual(file.childFileCount, 0); - assert.strictEqual(file.childFileNames.size(), 0); - assert.strictEqual(file.childFiles.size(), 0); + assert.strictEqual(file.childFileNames.length, 0); + assert.strictEqual(file.childFiles.length, 0); assert.strictEqual(file.childFile(0), null); assert.strictEqual(file.childFileFromFileName(utils.UNKNOWN_FILE), null); }); diff --git a/tests/bindings/javascript/logger.coverage.test.js b/tests/bindings/javascript/logger.coverage.test.js index 03b2af404..e431e921e 100644 --- a/tests/bindings/javascript/logger.coverage.test.js +++ b/tests/bindings/javascript/logger.coverage.test.js @@ -48,7 +48,7 @@ test.describe('Issue coverage tests', () => { file.setContents(utils.CELLML_CONTENTS); - assert.strictEqual(file.issues.size(), 0); + assert.strictEqual(file.issues.length, 0); }); test('issue()', () => { @@ -81,7 +81,7 @@ test.describe('Issue coverage tests', () => { file.setContents(utils.CELLML_CONTENTS); - assert.strictEqual(file.errors.size(), 0); + assert.strictEqual(file.errors.length, 0); }); test('error()', () => { @@ -114,7 +114,7 @@ test.describe('Issue coverage tests', () => { file.setContents(utils.CELLML_CONTENTS); - assert.strictEqual(file.warnings.size(), 0); + assert.strictEqual(file.warnings.length, 0); }); test('warning()', () => { @@ -127,4 +127,15 @@ test.describe('Issue coverage tests', () => { assert.notStrictEqual(document.warning(0), null); assert.strictEqual(document.warning(document.warningCount), null); }); + + test('toString()', () => { + const file = new loc.File(utils.ERROR_CELLML_FILE); + + file.setContents(utils.fileContents(utils.resourcePath('error.cellml'))); + + const issue = file.issue(0); + + assert.notStrictEqual(issue, null); + assert.strictEqual(String(issue), issue.description); + }); }); diff --git a/tests/bindings/javascript/res/res/libopencor.js b/tests/bindings/javascript/res/res/libopencor.js index edf04a80b..5d927b89e 100644 --- a/tests/bindings/javascript/res/res/libopencor.js +++ b/tests/bindings/javascript/res/res/libopencor.js @@ -33,13 +33,11 @@ function showIssues(issues) { issuesElement.empty(); if (Array.isArray(issues)) { - for (let i = 0; i < issues.length; ++i) { - issuesElement.append(`
  • Error:·${formattedIssueDescription(issues[i])}
  • `); + for (const issue of issues) { + issuesElement.append(`
  • Error:·${formattedIssueDescription(issue)}
  • `); } } else { - for (let i = 0; i < issues.size(); ++i) { - const issue = issues.get(i); - + for (const issue of issues) { issuesElement.append( '
  • ' + issue.typeAsString + @@ -61,8 +59,8 @@ function listFiles() { const files = fileManager.files; - for (let i = 0; i < files.size(); ++i) { - console.log(` - ${files.get(i).fileName}`); + for (const file of files) { + console.log(` - ${file.fileName}`); } } else { console.log('No files.'); diff --git a/tests/bindings/javascript/sed.coverage.test.js b/tests/bindings/javascript/sed.coverage.test.js index 8b39186de..44693b791 100644 --- a/tests/bindings/javascript/sed.coverage.test.js +++ b/tests/bindings/javascript/sed.coverage.test.js @@ -53,7 +53,7 @@ test.describe('Sed coverage tests', () => { assert.strictEqual(document.hasModels, false); assert.strictEqual(document.modelCount, 0); - assert.strictEqual(document.models.size(), 0); + assert.strictEqual(document.models.length, 0); assert.strictEqual(document.addModel(null), false); const file = new loc.File(utils.SEDML_FILE); @@ -65,7 +65,7 @@ test.describe('Sed coverage tests', () => { assert.strictEqual(document.hasModels, true); assert.strictEqual(document.modelCount, 1); - assert.strictEqual(document.models.size(), 1); + assert.strictEqual(document.models.length, 1); assert.deepStrictEqual(document.models.get(0), model); assert.deepStrictEqual(document.model(0), model); assert.deepStrictEqual(document.model(1), null); @@ -75,7 +75,7 @@ test.describe('Sed coverage tests', () => { assert.strictEqual(document.hasModels, false); assert.strictEqual(document.modelCount, 0); - assert.strictEqual(document.models.size(), 0); + assert.strictEqual(document.models.length, 0); assert.strictEqual(document.removeModel(null), false); assert.strictEqual(document.removeAllModels(), false); @@ -85,7 +85,7 @@ test.describe('Sed coverage tests', () => { assert.strictEqual(model.hasChanges, false); assert.strictEqual(model.changeCount, 0); - assert.strictEqual(model.changes.size(), 0); + assert.strictEqual(model.changes.length, 0); assert.strictEqual(model.addChange(null), false); assert.strictEqual(model.removeAllChanges(), false); @@ -95,7 +95,7 @@ test.describe('Sed coverage tests', () => { assert.strictEqual(model.hasChanges, true); assert.strictEqual(model.changeCount, 1); - assert.strictEqual(model.changes.size(), 1); + assert.strictEqual(model.changes.length, 1); assert.deepStrictEqual(model.changes.get(0), changeAttribute); assert.deepStrictEqual(model.change(0), changeAttribute); assert.deepStrictEqual(model.change(1), null); @@ -108,7 +108,7 @@ test.describe('Sed coverage tests', () => { assert.strictEqual(model.hasChanges, false); assert.strictEqual(model.changeCount, 0); - assert.strictEqual(model.changes.size(), 0); + assert.strictEqual(model.changes.length, 0); assert.strictEqual(model.removeChange(null), false); }); @@ -186,7 +186,7 @@ test.describe('Sed coverage tests', () => { assert.strictEqual(document.hasSimulations, false); assert.strictEqual(document.simulationCount, 0); - assert.strictEqual(document.simulations.size(), 0); + assert.strictEqual(document.simulations.length, 0); assert.strictEqual(document.addSimulation(null), false); const uniform_time_course = new loc.SedUniformTimeCourse(document); @@ -201,7 +201,7 @@ test.describe('Sed coverage tests', () => { assert.strictEqual(document.hasSimulations, true); assert.strictEqual(document.simulationCount, 4); - assert.strictEqual(document.simulations.size(), 4); + assert.strictEqual(document.simulations.length, 4); assert.deepStrictEqual(document.simulations.get(0), uniform_time_course); assert.deepStrictEqual(document.simulations.get(1), one_step); assert.deepStrictEqual(document.simulations.get(2), steady_state); @@ -226,7 +226,7 @@ test.describe('Sed coverage tests', () => { assert.strictEqual(document.hasSimulations, false); assert.strictEqual(document.simulationCount, 0); - assert.strictEqual(document.simulations.size(), 0); + assert.strictEqual(document.simulations.length, 0); assert.strictEqual(document.removeSimulation(null), false); assert.strictEqual(document.removeAllSimulations(), false); @@ -240,7 +240,7 @@ test.describe('Sed coverage tests', () => { assert.strictEqual(document.hasTasks, false); assert.strictEqual(document.taskCount, 0); - assert.strictEqual(document.tasks.size(), 0); + assert.strictEqual(document.tasks.length, 0); assert.strictEqual(document.addTask(null), false); const file = new loc.File(utils.SEDML_FILE); @@ -255,7 +255,7 @@ test.describe('Sed coverage tests', () => { assert.strictEqual(document.hasTasks, true); assert.strictEqual(document.taskCount, 1); - assert.strictEqual(document.tasks.size(), 1); + assert.strictEqual(document.tasks.length, 1); assert.deepStrictEqual(document.tasks.get(0), task); assert.deepStrictEqual(document.task(0), task); assert.deepStrictEqual(document.task(1), null); @@ -282,7 +282,7 @@ test.describe('Sed coverage tests', () => { assert.strictEqual(document.hasTasks, false); assert.strictEqual(document.taskCount, 0); - assert.strictEqual(document.tasks.size(), 0); + assert.strictEqual(document.tasks.length, 0); assert.strictEqual(document.removeTask(null), false); assert.strictEqual(document.removeAllTasks(), false); @@ -377,15 +377,15 @@ test.describe('Sed coverage tests', () => { assert.deepStrictEqual(instance.task(0), instanceTask); assert.strictEqual(instance.task(1), null); - assert.strictEqual(instanceTask.voi.size(), 0); + assert.strictEqual(instanceTask.voi.length, 0); assert.deepStrictEqual(instanceTask.voiAsArray, emptyFloat64Array); assert.strictEqual(instanceTask.voiName, 'environment/time'); assert.strictEqual(instanceTask.voiUnit, 'millisecond'); assert.strictEqual(instanceTask.stateCount, 4); - assert.strictEqual(instanceTask.state(0).size(), 0); + assert.strictEqual(instanceTask.state(0).length, 0); assert.deepStrictEqual(instanceTask.stateAsArray(0), emptyFloat64Array); - assert.strictEqual(instanceTask.state(4).size(), 0); + assert.strictEqual(instanceTask.state(4).length, 0); assert.deepStrictEqual(instanceTask.stateAsArray(4), emptyFloat64Array); assert.strictEqual(instanceTask.stateName(0), 'membrane/V'); assert.strictEqual(instanceTask.stateName(4), ''); @@ -393,9 +393,9 @@ test.describe('Sed coverage tests', () => { assert.strictEqual(instanceTask.stateUnit(4), ''); assert.strictEqual(instanceTask.rateCount, 4); - assert.strictEqual(instanceTask.rate(0).size(), 0); + assert.strictEqual(instanceTask.rate(0).length, 0); assert.deepStrictEqual(instanceTask.rateAsArray(0), emptyFloat64Array); - assert.strictEqual(instanceTask.rate(4).size(), 0); + assert.strictEqual(instanceTask.rate(4).length, 0); assert.deepStrictEqual(instanceTask.rateAsArray(4), emptyFloat64Array); assert.strictEqual(instanceTask.rateName(0), "membrane/V'"); assert.strictEqual(instanceTask.rateName(4), ''); @@ -403,9 +403,9 @@ test.describe('Sed coverage tests', () => { assert.strictEqual(instanceTask.rateUnit(4), ''); assert.strictEqual(instanceTask.constantCount, 5); - assert.strictEqual(instanceTask.constant(0).size(), 0); + assert.strictEqual(instanceTask.constant(0).length, 0); assert.deepStrictEqual(instanceTask.constantAsArray(0), emptyFloat64Array); - assert.strictEqual(instanceTask.constant(5).size(), 0); + assert.strictEqual(instanceTask.constant(5).length, 0); assert.deepStrictEqual(instanceTask.constantAsArray(5), emptyFloat64Array); assert.strictEqual(instanceTask.constantName(0), 'membrane/Cm'); assert.strictEqual(instanceTask.constantName(5), ''); @@ -413,9 +413,9 @@ test.describe('Sed coverage tests', () => { assert.strictEqual(instanceTask.constantUnit(5), ''); assert.strictEqual(instanceTask.computedConstantCount, 3); - assert.strictEqual(instanceTask.computedConstant(0).size(), 0); + assert.strictEqual(instanceTask.computedConstant(0).length, 0); assert.deepStrictEqual(instanceTask.computedConstantAsArray(0), emptyFloat64Array); - assert.strictEqual(instanceTask.computedConstant(3).size(), 0); + assert.strictEqual(instanceTask.computedConstant(3).length, 0); assert.deepStrictEqual(instanceTask.computedConstantAsArray(3), emptyFloat64Array); assert.strictEqual(instanceTask.computedConstantName(0), 'leakage_current/E_L'); assert.strictEqual(instanceTask.computedConstantName(3), ''); @@ -423,9 +423,9 @@ test.describe('Sed coverage tests', () => { assert.strictEqual(instanceTask.computedConstantUnit(3), ''); assert.strictEqual(instanceTask.algebraicVariableCount, 10); - assert.strictEqual(instanceTask.algebraicVariable(0).size(), 0); + assert.strictEqual(instanceTask.algebraicVariable(0).length, 0); assert.deepStrictEqual(instanceTask.algebraicVariableAsArray(0), emptyFloat64Array); - assert.strictEqual(instanceTask.algebraicVariable(10).size(), 0); + assert.strictEqual(instanceTask.algebraicVariable(10).length, 0); assert.deepStrictEqual(instanceTask.algebraicVariableAsArray(10), emptyFloat64Array); assert.strictEqual(instanceTask.algebraicVariableName(0), 'membrane/i_Stim'); assert.strictEqual(instanceTask.algebraicVariableName(10), ''); @@ -452,19 +452,19 @@ test.describe('Sed coverage tests', () => { const instance = document.instantiate(); const instanceTask = instance.tasks.get(0); - assert.strictEqual(instanceTask.voi.size(), 0); + assert.strictEqual(instanceTask.voi.length, 0); assert.deepStrictEqual(instanceTask.voiAsArray, emptyFloat64Array); assert.strictEqual(instanceTask.voiName, ''); assert.strictEqual(instanceTask.voiUnit, ''); assert.strictEqual(instanceTask.stateCount, 0); - assert.strictEqual(instanceTask.state(0).size(), 0); + assert.strictEqual(instanceTask.state(0).length, 0); assert.deepStrictEqual(instanceTask.stateAsArray(0), emptyFloat64Array); assert.strictEqual(instanceTask.stateName(0), ''); assert.strictEqual(instanceTask.stateUnit(0), ''); assert.strictEqual(instanceTask.rateCount, 0); - assert.strictEqual(instanceTask.rate(0).size(), 0); + assert.strictEqual(instanceTask.rate(0).length, 0); assert.deepStrictEqual(instanceTask.rateAsArray(0), emptyFloat64Array); assert.strictEqual(instanceTask.rateName(0), ''); assert.strictEqual(instanceTask.rateUnit(0), ''); diff --git a/tests/bindings/javascript/utils.in.js b/tests/bindings/javascript/utils.in.js index 8dadeb77c..8a3e1b86b 100644 --- a/tests/bindings/javascript/utils.in.js +++ b/tests/bindings/javascript/utils.in.js @@ -51,16 +51,16 @@ export const COMBINE_ARCHIVE_CONTENTS = stringToArrayBuffer(atob('@BASE64_COMBIN export function assertIssues(loc, logger, expectedIssues) { const issues = logger.issues; - assert.strictEqual(issues.size(), expectedIssues.length); + assert.strictEqual(issues.length, expectedIssues.length); - for (let i = 0; i < issues.size(); ++i) { - assert.strictEqual(issues.get(i).type.value, expectedIssues[i][0].value); - assert.strictEqual(issues.get(i).description, expectedIssues[i][1]); + for (const [i, issue] of Array.from(issues).entries()) { + assert.strictEqual(issue.type.value, expectedIssues[i][0].value); + assert.strictEqual(issue.description, expectedIssues[i][1]); - if (issues.get(i).type === loc.Issue.Type.ERROR) { - assert.strictEqual(issues.get(i).typeAsString, 'Error'); + if (issue.type === loc.Issue.Type.ERROR) { + assert.strictEqual(issue.typeAsString, 'Error'); } else { - assert.strictEqual(issues.get(i).typeAsString, 'Warning'); + assert.strictEqual(issue.typeAsString, 'Warning'); } } } From c80dc1bead9f043ac8e9d6cf85adab354ff112d8 Mon Sep 17 00:00:00 2001 From: Alan Garny Date: Thu, 28 May 2026 23:58:27 +1200 Subject: [PATCH 4/5] Python: improved our bindings. Added `__iter__()`, `__len__()`, `__repr__()`, and `__str__()` wherever it makes sense. --- src/bindings/python/file.cpp | 13 +++++++++++-- src/bindings/python/logger.cpp | 8 +++++++- src/bindings/python/sed.cpp | 6 +++++- src/bindings/python/solver.cpp | 5 ++++- 4 files changed, 27 insertions(+), 5 deletions(-) diff --git a/src/bindings/python/file.cpp b/src/bindings/python/file.cpp index 1981fcdf4..638a1dcd8 100644 --- a/src/bindings/python/file.cpp +++ b/src/bindings/python/file.cpp @@ -47,7 +47,12 @@ void fileApi(nb::module_ &m) .def_prop_ro("child_file_names", &libOpenCOR::File::childFileNames, "Return the child file names for this File object.") .def_prop_ro("child_files", &libOpenCOR::File::childFiles, "Return the child files for this File object.") .def("child_file", nb::overload_cast(&libOpenCOR::File::childFile, nb::const_), "Get the requested child file for this File object.", nb::arg("index")) - .def("child_file", nb::overload_cast(&libOpenCOR::File::childFile, nb::const_), "Get the requested child file for this File object.", nb::arg("file_name")); + .def("child_file", nb::overload_cast(&libOpenCOR::File::childFile, nb::const_), "Get the requested child file for this File object.", nb::arg("file_name")) + .def("__repr__", [](const libOpenCOR::File &self) { + std::string loc = self.path().empty() ? self.url() : self.path(); + + return "File(\"" + loc + "\")"; + }); // FileManager API. @@ -61,5 +66,9 @@ void fileApi(nb::module_ &m) .def_prop_ro("file_count", &libOpenCOR::FileManager::fileCount, "Return the number of managed files.") .def_prop_ro("files", &libOpenCOR::FileManager::files, "Return the managed files.") .def("file", nb::overload_cast(&libOpenCOR::FileManager::file, nb::const_), "Get the requested managed file.", nb::arg("index")) - .def("file", nb::overload_cast(&libOpenCOR::FileManager::file, nb::const_), "Get the requested managed file.", nb::arg("file_name_or_url")); + .def("file", nb::overload_cast(&libOpenCOR::FileManager::file, nb::const_), "Get the requested managed file.", nb::arg("file_name_or_url")) + .def("__len__", &libOpenCOR::FileManager::fileCount) + .def("__iter__", [](const libOpenCOR::FileManager &self) { + return nb::cast(self.files()).attr("__iter__")(); + }); } diff --git a/src/bindings/python/logger.cpp b/src/bindings/python/logger.cpp index 2ea612be9..369f16961 100644 --- a/src/bindings/python/logger.cpp +++ b/src/bindings/python/logger.cpp @@ -52,5 +52,11 @@ void loggerApi(nb::module_ &m) issue.def_prop_ro("type", &libOpenCOR::Issue::type, "Get the type of this Issue object.") .def_prop_ro("type_as_string", &libOpenCOR::Issue::typeAsString, "Get the type of this Issue object as a string.") - .def_prop_ro("description", &libOpenCOR::Issue::description, "Get the description for this Issue object."); + .def_prop_ro("description", &libOpenCOR::Issue::description, "Get the description for this Issue object.") + .def("__repr__", [](const libOpenCOR::Issue &self) { + return "Issue(" + self.typeAsString() + ": \"" + self.description() + "\")"; + }) + .def("__str__", [](const libOpenCOR::Issue &self) { + return self.description(); + }); } diff --git a/src/bindings/python/sed.cpp b/src/bindings/python/sed.cpp index f19aebeab..3fbd20e75 100644 --- a/src/bindings/python/sed.cpp +++ b/src/bindings/python/sed.cpp @@ -99,7 +99,11 @@ void sedApi(nb::module_ &m) .def_prop_ro("has_tasks", &libOpenCOR::SedInstance::hasTasks, "Return whether there are some tasks.") .def_prop_ro("task_count", &libOpenCOR::SedInstance::taskCount, "Return the number of tasks.") .def_prop_ro("tasks", &libOpenCOR::SedInstance::tasks, "Return the tasks.") - .def("task", &libOpenCOR::SedInstance::task, "Return the task."); + .def("task", &libOpenCOR::SedInstance::task, "Return the task.") + .def("__len__", &libOpenCOR::SedInstance::taskCount) + .def("__iter__", [](const libOpenCOR::SedInstance &self) { + return nb::cast(self.tasks()).attr("__iter__")(); + }); // SedInstanceTask API. diff --git a/src/bindings/python/solver.cpp b/src/bindings/python/solver.cpp index 74ae76ed5..04fd2fd29 100644 --- a/src/bindings/python/solver.cpp +++ b/src/bindings/python/solver.cpp @@ -34,7 +34,10 @@ void solverApi(nb::module_ &m) solver.def_prop_ro("type", &libOpenCOR::Solver::type, "Get the type of the Solver object.") .def_prop_ro("id", &libOpenCOR::Solver::id, "Get the (KiSAO) id of the Solver object.") - .def_prop_ro("name", &libOpenCOR::Solver::name, "Get the name of the Solver object."); + .def_prop_ro("name", &libOpenCOR::Solver::name, "Get the name of the Solver object.") + .def("__repr__", [](const libOpenCOR::Solver &self) { + return "Solver(name=\"" + self.name() + "\")"; + }); // SolverOde API. From 10a1dc786ba7a2cdef59d78fa052d67775c411cf Mon Sep 17 00:00:00 2001 From: Alan Garny Date: Fri, 29 May 2026 00:30:55 +1200 Subject: [PATCH 5/5] Python: improved our tests. --- tests/bindings/python/test_file_basic.py | 41 ++--- tests/bindings/python/test_file_child.py | 4 +- tests/bindings/python/test_logger_coverage.py | 20 ++- tests/bindings/python/test_sed_basic.py | 20 +-- tests/bindings/python/test_sed_coverage.py | 140 +++++++++--------- tests/bindings/python/test_sed_instance.py | 44 +++--- tests/bindings/python/test_sed_serialise.py | 4 +- tests/bindings/python/test_solver_basic.py | 4 +- 8 files changed, 144 insertions(+), 133 deletions(-) diff --git a/tests/bindings/python/test_file_basic.py b/tests/bindings/python/test_file_basic.py index 42b4b0a6a..c5c318b3b 100644 --- a/tests/bindings/python/test_file_basic.py +++ b/tests/bindings/python/test_file_basic.py @@ -159,51 +159,52 @@ def test_remote_virtual_file(): def test_file_manager(): file_manager = loc.FileManager.instance() - assert file_manager.has_files == False + assert not file_manager.has_files assert file_manager.file_count == 0 - assert len(file_manager.files) == 0 - assert file_manager.file(0) == None - assert file_manager.file(utils.LocalFile) == None + assert len(file_manager) == 0 + assert file_manager.file(0) is None + assert file_manager.file(utils.LocalFile) is None local_file = loc.File(utils.LocalFile) same_file_manager = loc.FileManager.instance() - assert same_file_manager.has_files == True + assert same_file_manager.has_files assert same_file_manager.file_count == 1 - assert len(file_manager.files) == 1 + assert len(file_manager) == 1 + assert list(file_manager) == [local_file] assert file_manager.file(0) == local_file assert same_file_manager.file(utils.LocalFile) == local_file remote_file = loc.File(utils.RemoteFile) - assert file_manager.has_files == True + assert file_manager.has_files assert file_manager.file_count == 2 - assert len(file_manager.files) == 2 + assert len(file_manager) == 2 assert file_manager.file(1) == remote_file assert file_manager.file(utils.RemoteFile) == remote_file same_file_manager.unmanage(local_file) - assert same_file_manager.has_files == True + assert same_file_manager.has_files assert same_file_manager.file_count == 1 - assert len(file_manager.files) == 1 - assert file_manager.file(1) == None - assert same_file_manager.file(utils.LocalFile) == None + assert len(file_manager) == 1 + assert file_manager.file(1) is None + assert same_file_manager.file(utils.LocalFile) is None same_file_manager.manage(local_file) - assert same_file_manager.has_files == True + assert same_file_manager.has_files assert same_file_manager.file_count == 2 - assert len(file_manager.files) == 2 + assert len(file_manager) == 2 assert file_manager.file(1) == local_file assert same_file_manager.file(utils.LocalFile) == local_file file_manager.reset() - assert file_manager.has_files == False + assert not file_manager.has_files assert file_manager.file_count == 0 - assert len(file_manager.files) == 0 - assert file_manager.file(0) == None - assert file_manager.file(1) == None - assert file_manager.file(utils.RemoteFile) == None - assert file_manager.file(utils.UnknownFile) == None + assert len(file_manager) == 0 + assert file_manager.file(0) is None + assert file_manager.file(1) is None + assert file_manager.file(utils.RemoteFile) is None + assert file_manager.file(utils.UnknownFile) is None diff --git a/tests/bindings/python/test_file_child.py b/tests/bindings/python/test_file_child.py index 3180e6a13..5edf500a1 100644 --- a/tests/bindings/python/test_file_child.py +++ b/tests/bindings/python/test_file_child.py @@ -21,7 +21,7 @@ def do_test_dataset(number, specific_child_file_names): file = File(utils.resource_path("api/file/dataset_" + str(number) + ".omex")) - assert file.has_child_files == True + assert file.has_child_files assert file.child_file_count == len(specific_child_file_names) + 1 assert len(file.child_file_names) == len(specific_child_file_names) + 1 assert len(file.child_files) == len(specific_child_file_names) + 1 @@ -49,7 +49,7 @@ def do_test_dataset(number, specific_child_file_names): def test_type_no_child_files(): file = File(utils.resource_path(utils.UnknownFile)) - assert file.has_child_files == False + assert not file.has_child_files assert file.child_file_count == 0 assert len(file.child_file_names) == 0 assert len(file.child_files) == 0 diff --git a/tests/bindings/python/test_logger_coverage.py b/tests/bindings/python/test_logger_coverage.py index 2a34bc553..c5465ea82 100644 --- a/tests/bindings/python/test_logger_coverage.py +++ b/tests/bindings/python/test_logger_coverage.py @@ -38,8 +38,16 @@ def test_issues(): def test_issue(): file = loc.File(utils.resource_path(utils.ErrorCellmlFile)) - assert file.issue(0) != None - assert file.issue(file.issue_count) == None + assert file.issue(0) is not None + assert file.issue(file.issue_count) is None + + +def test_issue_str(): + file = loc.File(utils.resource_path(utils.ErrorCellmlFile)) + issue = file.issue(0) + + assert issue is not None + assert str(issue) == issue.description def test_has_errors(): @@ -63,8 +71,8 @@ def test_errors(): def test_error(): file = loc.File(utils.resource_path(utils.ErrorCellmlFile)) - assert file.error(0) != None - assert file.error(file.error_count) == None + assert file.error(0) is not None + assert file.error(file.error_count) is None def test_has_warnings(): @@ -89,5 +97,5 @@ def test_warning(): file = loc.File(utils.resource_path(utils.Sedml2File)) document = loc.SedDocument(file) - assert document.warning(0) != None - assert document.warning(document.warning_count) == None + assert document.warning(0) is not None + assert document.warning(document.warning_count) is None diff --git a/tests/bindings/python/test_sed_basic.py b/tests/bindings/python/test_sed_basic.py index adceab324..cea4fa8c9 100644 --- a/tests/bindings/python/test_sed_basic.py +++ b/tests/bindings/python/test_sed_basic.py @@ -21,11 +21,11 @@ def test_no_file(): document = loc.SedDocument() - assert document.has_issues == False + assert not document.has_issues document = loc.SedDocument(None) - assert document.has_issues == False + assert not document.has_issues def test_unknown_file(): @@ -46,53 +46,53 @@ def test_cellml_file(): file = loc.File(utils.resource_path(utils.Cellml2File)) document = loc.SedDocument(file) - assert document.has_issues == False + assert not document.has_issues def test_sedml_file(): file = loc.File(utils.resource_path(utils.Sedml2File)) document = loc.SedDocument(file) - assert document.has_issues == True + assert document.has_issues needed_file = loc.File(utils.resource_path(utils.Cellml2File)) document = loc.SedDocument(file) - assert document.has_issues == False + assert not document.has_issues def test_sedml_file_with_absolute_cellml_file(): file = loc.File(utils.resource_path("api/sed/absolute_cellml_file.sedml")) document = loc.SedDocument(file) - assert document.has_issues == True + assert document.has_issues needed_file = loc.File(utils.LocalFile) document = loc.SedDocument(file) - assert document.has_issues == False + assert not document.has_issues def test_sedml_file_with_remote_cellml_file(): file = loc.File(utils.resource_path("api/sed/remote_cellml_file.sedml")) document = loc.SedDocument(file) - assert document.has_issues == True + assert document.has_issues needed_file = loc.File(utils.RemoteFile) document = loc.SedDocument(file) - assert document.has_issues == False + assert not document.has_issues def test_combine_archive(): file = loc.File(utils.resource_path(utils.Combine2Archive)) document = loc.SedDocument(file) - assert document.has_issues == False + assert not document.has_issues def test_combine_archive_with_no_manifest_file(): diff --git a/tests/bindings/python/test_sed_coverage.py b/tests/bindings/python/test_sed_coverage.py index 36b195abb..b4a76497f 100644 --- a/tests/bindings/python/test_sed_coverage.py +++ b/tests/bindings/python/test_sed_coverage.py @@ -32,66 +32,66 @@ def test_initialise(): def test_models(): document = loc.SedDocument() - assert document.has_models == False + assert not document.has_models assert document.model_count == 0 assert len(document.models) == 0 - assert document.add_model(None) == False + assert not document.add_model(None) file = loc.File(utils.LocalFile) model = loc.SedModel(document, file) assert model.file == file - assert document.add_model(model) == True + assert document.add_model(model) - assert document.has_models == True + assert document.has_models assert document.model_count == 1 assert len(document.models) == 1 assert document.models[0] == model assert document.model(0) == model - assert document.model(1) == None + assert document.model(1) is None - assert document.add_model(model) == False - assert document.remove_model(model) == True + assert not document.add_model(model) + assert document.remove_model(model) - assert document.has_models == False + assert not document.has_models assert document.model_count == 0 assert len(document.models) == 0 - assert document.remove_model(None) == False - assert document.remove_all_models() == False + assert not document.remove_model(None) + assert not document.remove_all_models() - assert document.add_model(model) == True - assert document.remove_all_models() == True + assert document.add_model(model) + assert document.remove_all_models() - assert model.has_changes == False + assert not model.has_changes assert model.change_count == 0 assert len(model.changes) == 0 - assert model.add_change(None) == False - assert model.remove_all_changes() == False + assert not model.add_change(None) + assert not model.remove_all_changes() change_attribute = loc.SedChangeAttribute("component", "variable", "newValue") - assert model.add_change(change_attribute) == True + assert model.add_change(change_attribute) - assert model.has_changes == True + assert model.has_changes assert model.change_count == 1 assert len(model.changes) == 1 assert model.changes[0] == change_attribute assert model.change(0) == change_attribute - assert model.change(1) == None + assert model.change(1) is None - assert model.add_change(change_attribute) == False - assert model.remove_change(change_attribute) == True + assert not model.add_change(change_attribute) + assert model.remove_change(change_attribute) - assert model.add_change(change_attribute) == True - assert model.remove_all_changes() == True + assert model.add_change(change_attribute) + assert model.remove_all_changes() - assert model.has_changes == False + assert not model.has_changes assert model.change_count == 0 assert len(model.changes) == 0 - assert model.remove_change(None) == False + assert not model.remove_change(None) def test_changes(): @@ -164,22 +164,22 @@ def test_changes(): def test_simulations(): document = loc.SedDocument() - assert document.has_simulations == False + assert not document.has_simulations assert document.simulation_count == 0 assert len(document.simulations) == 0 - assert document.add_simulation(None) == False + assert not document.add_simulation(None) uniformTimeCourse = loc.SedUniformTimeCourse(document) oneStep = loc.SedOneStep(document) steadyState = loc.SedSteadyState(document) analysis = loc.SedAnalysis(document) - assert document.add_simulation(uniformTimeCourse) == True - assert document.add_simulation(oneStep) == True - assert document.add_simulation(steadyState) == True - assert document.add_simulation(analysis) == True + assert document.add_simulation(uniformTimeCourse) + assert document.add_simulation(oneStep) + assert document.add_simulation(steadyState) + assert document.add_simulation(analysis) - assert document.has_simulations == True + assert document.has_simulations assert document.simulation_count == 4 assert len(document.simulations) == 4 assert document.simulations[0] == uniformTimeCourse @@ -190,29 +190,29 @@ def test_simulations(): assert document.simulation(1) == oneStep assert document.simulation(2) == steadyState assert document.simulation(3) == analysis - assert document.simulation(4) == None + assert document.simulation(4) is None - assert document.add_simulation(uniformTimeCourse) == False - assert document.remove_simulation(uniformTimeCourse) == True + assert not document.add_simulation(uniformTimeCourse) + assert document.remove_simulation(uniformTimeCourse) - assert document.add_simulation(oneStep) == False - assert document.remove_simulation(oneStep) == True + assert not document.add_simulation(oneStep) + assert document.remove_simulation(oneStep) - assert document.add_simulation(steadyState) == False - assert document.remove_simulation(steadyState) == True + assert not document.add_simulation(steadyState) + assert document.remove_simulation(steadyState) - assert document.add_simulation(analysis) == False - assert document.remove_simulation(analysis) == True + assert not document.add_simulation(analysis) + assert document.remove_simulation(analysis) - assert document.has_simulations == False + assert not document.has_simulations assert document.simulation_count == 0 assert len(document.simulations) == 0 - assert document.remove_simulation(None) == False - assert document.remove_all_simulations() == False + assert not document.remove_simulation(None) + assert not document.remove_all_simulations() - assert document.add_simulation(uniformTimeCourse) == True - assert document.remove_all_simulations() == True + assert document.add_simulation(uniformTimeCourse) + assert document.remove_all_simulations() def sed_task_expected_serialisation(with_properties): @@ -234,10 +234,10 @@ def sed_task_expected_serialisation(with_properties): def test_tasks(): document = loc.SedDocument() - assert document.has_tasks == False + assert not document.has_tasks assert document.task_count == 0 assert len(document.tasks) == 0 - assert document.add_task(None) == False + assert not document.add_task(None) file = loc.File(utils.LocalFile) model = loc.SedModel(document, file) @@ -247,22 +247,22 @@ def test_tasks(): assert task.model == model assert task.simulation == simulation - assert document.add_task(task) == True + assert document.add_task(task) - assert document.has_tasks == True + assert document.has_tasks assert document.task_count == 1 assert len(document.tasks) == 1 assert document.tasks[0] == task assert document.task(0) == task - assert document.task(1) == None + assert document.task(1) is None assert document.serialise() == sed_task_expected_serialisation(True) task.model = None task.simulation = None - assert task.model == None - assert task.simulation == None + assert task.model is None + assert task.simulation is None assert document.serialise() == sed_task_expected_serialisation(False) @@ -281,25 +281,25 @@ def test_tasks(): assert_issues(instance, expected_issues) - assert document.add_task(task) == False - assert document.remove_task(task) == True + assert not document.add_task(task) + assert document.remove_task(task) - assert document.has_tasks == False + assert not document.has_tasks assert document.task_count == 0 assert len(document.tasks) == 0 - assert document.remove_task(None) == False - assert document.remove_all_tasks() == False + assert not document.remove_task(None) + assert not document.remove_all_tasks() - assert document.add_task(task) == True - assert document.remove_all_tasks() == True + assert document.add_task(task) + assert document.remove_all_tasks() def test_ode_solver(): document = loc.SedDocument() simulation = loc.SedUniformTimeCourse(document) - assert simulation.ode_solver == None + assert simulation.ode_solver is None solver = loc.SolverCvode() @@ -309,14 +309,14 @@ def test_ode_solver(): simulation.ode_solver = None - assert simulation.ode_solver == None + assert simulation.ode_solver is None def test_nla_solver(): document = loc.SedDocument() simulation = loc.SedUniformTimeCourse(document) - assert simulation.nla_solver == None + assert simulation.nla_solver is None solver = loc.SolverKinsol() @@ -326,7 +326,7 @@ def test_nla_solver(): simulation.nla_solver = None - assert simulation.nla_solver == None + assert simulation.nla_solver is None def test_sed_one_step(): @@ -380,10 +380,12 @@ def test_sed_instance_and_sed_instance_task_differential_model(): instance = document.instantiate() instance_task = instance.tasks[0] - assert instance.has_tasks == True + assert instance.has_tasks assert instance.task_count == 1 + assert len(instance) == 1 + assert list(instance)[0] == instance_task assert instance.task(0) == instance_task - assert instance.task(1) == None + assert instance.task(1) is None assert instance_task.voi == [] assert instance_task.voi_name == "environment/time" @@ -479,7 +481,7 @@ def test_solver(): instance.run() - assert instance.has_issues == False + assert not instance.has_issues document.simulations[0].ode_solver = loc.SolverFourthOrderRungeKutta() @@ -487,7 +489,7 @@ def test_solver(): instance.run() - assert instance.has_issues == False + assert not instance.has_issues document.simulations[0].ode_solver = loc.SolverHeun() @@ -495,7 +497,7 @@ def test_solver(): instance.run() - assert instance.has_issues == False + assert not instance.has_issues document.simulations[0].ode_solver = loc.SolverSecondOrderRungeKutta() @@ -503,7 +505,7 @@ def test_solver(): instance.run() - assert instance.has_issues == False + assert not instance.has_issues def test_math(): diff --git a/tests/bindings/python/test_sed_instance.py b/tests/bindings/python/test_sed_instance.py index b64ff8df9..c31f308fc 100644 --- a/tests/bindings/python/test_sed_instance.py +++ b/tests/bindings/python/test_sed_instance.py @@ -120,7 +120,7 @@ def run_algebraic_model(): instance.run() - assert instance.has_issues == False + assert not instance.has_issues def test_algebraic_model(): @@ -148,7 +148,7 @@ def run_ode_model(): instance = document.instantiate() - assert instance.has_issues == False + assert not instance.has_issues instance.run() @@ -160,7 +160,7 @@ def run_ode_model(): instance.run() - assert instance.has_issues == False + assert not instance.has_issues def test_ode_model(): @@ -209,7 +209,7 @@ def test_nla_model(): instance = document.instantiate() - assert instance.has_issues == False + assert not instance.has_issues def test_nla_model_with_no_nla_solver(): @@ -260,7 +260,7 @@ def test_dae_model(): instance.run() - assert instance.has_issues == False + assert not instance.has_issues def test_dae_model_with_no_ode_or_nla_solver(): @@ -294,7 +294,7 @@ def test_combine_archive(): instance.run() - assert instance.has_issues == False + assert not instance.has_issues def test_combine_archive_with_cellml_file_as_master_file(): @@ -309,22 +309,22 @@ def test_combine_archive_with_cellml_file_as_master_file(): document = loc.SedDocument(file) instance = document.instantiate() - assert instance.has_issues == False + assert not instance.has_issues def test_dae_model_from_cellml_file(): file = loc.File(utils.resource_path("api/sed/dae/model.cellml")) document = loc.SedDocument(file) - assert document.has_issues == False + assert not document.has_issues instance = document.instantiate() - assert instance.has_issues == False + assert not instance.has_issues instance.run() - assert instance.has_issues == False + assert not instance.has_issues def test_dae_model_from_sedml_file(): @@ -332,7 +332,7 @@ def test_dae_model_from_sedml_file(): sedml_file = loc.File(utils.resource_path("api/sed/dae/model.sedml")) document = loc.SedDocument(sedml_file) - assert document.has_issues == False + assert not document.has_issues nla_solver = document.simulations[0].nla_solver @@ -343,18 +343,18 @@ def test_dae_model_from_sedml_file(): instance = document.instantiate() - assert instance.has_issues == False + assert not instance.has_issues instance.run() - assert instance.has_issues == False + assert not instance.has_issues def test_dae_model_from_combine_archive(): combine_archive = loc.File(utils.resource_path("api/sed/dae/model.omex")) document = loc.SedDocument(combine_archive) - assert document.has_issues == False + assert not document.has_issues nla_solver = document.simulations[0].nla_solver @@ -365,11 +365,11 @@ def test_dae_model_from_combine_archive(): instance = document.instantiate() - assert instance.has_issues == False + assert not instance.has_issues instance.run() - assert instance.has_issues == False + assert not instance.has_issues def test_dae_model_from_legacy_sedml_file(): @@ -377,7 +377,7 @@ def test_dae_model_from_legacy_sedml_file(): sedml_file = loc.File(utils.resource_path("api/sed/dae/model_legacy.sedml")) document = loc.SedDocument(sedml_file) - assert document.has_issues == False + assert not document.has_issues nla_solver = document.simulations[0].nla_solver @@ -388,18 +388,18 @@ def test_dae_model_from_legacy_sedml_file(): instance = document.instantiate() - assert instance.has_issues == False + assert not instance.has_issues instance.run() - assert instance.has_issues == False + assert not instance.has_issues def test_dae_model_from_legacy_combine_archive(): combine_archive = loc.File(utils.resource_path("api/sed/dae/model_legacy.omex")) document = loc.SedDocument(combine_archive) - assert document.has_issues == False + assert not document.has_issues nla_solver = document.simulations[0].nla_solver @@ -410,8 +410,8 @@ def test_dae_model_from_legacy_combine_archive(): instance = document.instantiate() - assert instance.has_issues == False + assert not instance.has_issues instance.run() - assert instance.has_issues == False + assert not instance.has_issues diff --git a/tests/bindings/python/test_sed_serialise.py b/tests/bindings/python/test_sed_serialise.py index e3a06a47b..3bc6f9d74 100644 --- a/tests/bindings/python/test_sed_serialise.py +++ b/tests/bindings/python/test_sed_serialise.py @@ -310,8 +310,8 @@ def test_changes(): file = loc.File(utils.LocalFile) model = loc.SedModel(document, file) - assert model.add_change(change_attribute) == True - assert document.add_model(model) == True + assert model.add_change(change_attribute) + assert document.add_model(model) assert document.serialise() == sed_change_expected_serialisation( "component", "variable", "123.456789" diff --git a/tests/bindings/python/test_solver_basic.py b/tests/bindings/python/test_solver_basic.py index 3548aa3a7..4cd4960cd 100644 --- a/tests/bindings/python/test_solver_basic.py +++ b/tests/bindings/python/test_solver_basic.py @@ -33,7 +33,7 @@ def test_cvode_solver(): assert solver.lower_half_bandwidth == 0 assert solver.relative_tolerance == 1e-07 assert solver.absolute_tolerance == 1e-07 - assert solver.interpolate_solution == True + assert solver.interpolate_solution solver.maximum_step = 1.23 solver.maximum_number_of_steps = 123 @@ -57,7 +57,7 @@ def test_cvode_solver(): assert solver.lower_half_bandwidth == 5 assert solver.relative_tolerance == 1.23e-5 assert solver.absolute_tolerance == 3.45e-7 - assert solver.interpolate_solution == False + assert not solver.interpolate_solution def test_forward_euler_solver():