diff --git a/python/sdist/amici/swig.py b/python/sdist/amici/swig.py index b2ab7c090c..ed1aeb8534 100644 --- a/python/sdist/amici/swig.py +++ b/python/sdist/amici/swig.py @@ -133,6 +133,10 @@ def visit_FunctionDef(self, node): for arg in node.args.args: if not arg.annotation: continue + if isinstance(arg.annotation, ast.Name): + # there is already proper annotation + continue + arg.annotation = self._new_annot(arg.annotation.value) return node diff --git a/python/tests/test_swig_interface.py b/python/tests/test_swig_interface.py index c23eaaad00..5418b0b9ef 100644 --- a/python/tests/test_swig_interface.py +++ b/python/tests/test_swig_interface.py @@ -403,3 +403,15 @@ def test_model_instance_settings_custom_x0(pysb_example_presimulation_module): assert model2.getInitialStateSensitivities() == sx0 assert settings == amici.get_model_settings(model2) + +def test_solver_repr(): + for solver in (amici.CVodeSolver(), amici.IDASolver()): + assert "maxsteps" in str(solver) + assert "maxsteps" in repr(solver) + + solver_ptr = amici.SolverPtr(solver.this) + assert "maxsteps" in str(solver_ptr) + assert "maxsteps" in repr(solver_ptr) + # avoid double delete!! + solver_ptr.release() + diff --git a/swig/solver.i b/swig/solver.i index 853edae9bd..319e654530 100644 --- a/swig/solver.i +++ b/swig/solver.i @@ -40,6 +40,67 @@ using namespace amici; %ignore getRootInfo; %ignore updateAndReinitStatesAndSensitivities; +// Solver.__repr__ +%pythoncode %{ +def _solver_repr(self: "Solver"): + return "\n".join([ + self.this.__repr__()[:-1], + " reporting_mode: " + f"{RDataReporting(self.getReturnDataReportingMode())!r}", + f" sens_meth: {SensitivityMethod(self.getSensitivityMethod())!r}", + f" sens_order: {SensitivityOrder(self.getSensitivityOrder())!r}", + f" sens_meth_preeq: {SensitivityMethod(self.getSensitivityMethodPreequilibration())!r}", + f" maxsteps: {self.getMaxSteps()}", + f" maxtime: {self.getMaxTime()}s", + f" abs_tol: {self.getAbsoluteTolerance()}", + f" rel_tol: {self.getRelativeTolerance()}", + f" abs_tol_b: {self.getAbsoluteToleranceB()}", + f" rel_tol_b: {self.getRelativeToleranceB()}", + f" abs_tol_fsa: {self.getAbsoluteToleranceFSA()}", + f" rel_tol_fsa: {self.getRelativeToleranceFSA()}", + f" abs_tol_quad: {self.getAbsoluteToleranceQuadratures()}", + f" rel_tol_quad: {self.getRelativeToleranceQuadratures()}", + f" abs_tol_ss: {self.getAbsoluteToleranceSteadyState()}", + f" rel_tol_ss: {self.getRelativeToleranceSteadyState()}", + f" abs_tol_sss: {self.getAbsoluteToleranceSteadyStateSensi()}", + f" rel_tol_sss: {self.getRelativeToleranceSteadyStateSensi()}", + f" int_sens_meth: {InternalSensitivityMethod(self.getInternalSensitivityMethod())!r}", + f" int_type: {InterpolationType(self.getInterpolationType())!r}", + f" linsol: {LinearSolver(self.getLinearSolver())!r}", + f" lmm: {LinearMultistepMethod(self.getLinearMultistepMethod())!r}", + f" newton_damp_mode: {NewtonDampingFactorMode(self.getNewtonDampingFactorMode())!r}", + f" newton_damp_lb: {self.getNewtonDampingFactorLowerBound()}", + f" newton_maxsteps: {self.getNewtonMaxSteps()}", + f" newton_ss_check: {self.getNewtonStepSteadyStateCheck()}", + f" sens_ss_check: {self.getSensiSteadyStateCheck()}", + f" interpolation_type: {InterpolationType(self.getInterpolationType())!r}", + f" ism: {InternalSensitivityMethod(self.getInternalSensitivityMethod())!r}", + f" nlsol_iter: {NonlinearSolverIteration(self.getNonlinearSolverIteration())!r}", + f" stability_limit: {self.getStabilityLimitFlag()}", + f" state_ordering: {self.getStateOrdering()}", + ">" + ]) +%} +%extend amici::CVodeSolver { +%pythoncode %{ +def __repr__(self): + return _solver_repr(self) +%} +}; +%extend amici::IDASolver { +%pythoncode %{ +def __repr__(self): + return _solver_repr(self) +%} +}; + +%extend std::unique_ptr { +%pythoncode %{ +def __repr__(self): + return _solver_repr(self) +%} +}; + %newobject amici::Solver::clone; // Process symbols in header