RC 0.2.0
Changes based on code review feedback.
Merge request reports
Activity
requested review from @normann
assigned to @salid
Hi Daniel,
Thanks a lot for your MR. You did a very good job!
For the record, going through each point raised in the code review and in our email exchange:
-
Dynare preprocessor options are now supported via thedynare_options
argument in thedynare()
function. -
PyIndices
has been unified in a newindices.py
module. -
No remaining use ofSelf
: all class methods now use either quoted class names or omit return annotations. -
Docstrings have been added to allfrom_julia
routines. -
PyGsSolverWs.from_julia
is now a fully functional method. The former placeholderconvert_jl_distribution
has been removed, and a cleandistribution_from_julia
routine now returns properscipy.stats
objects. Much better! -
Logging is now configurable viasetup_logging()
and respects theDYNARE_PYTHON_LOGLEVEL
environment variable (DEBUG
,INFO
,WARNING
,ERROR
,CRITICAL
). -
Enum parsing has been cleaned up: fragilerepr()
-based parsing was replaced bycls[str(jl_enum)]
inSymbolType.from_julia
,EstimatedParameterType.from_julia
, andPySGSolver.from_julia
. -
Dynamic loading of external libraries (e.g., Tasmanian) is still a bit fragile:- If
LIBTASMANIAN_PATH
is wrong or the file is corrupted, the current implementation may crash without a clear error. - Required functions (like
tsgConstructTasmanianSparseGrid
) aren’t checked explicitly. - The library is loaded at module scope, which introduces side effects on import even if Tasmanian features aren’t used.
- Although Tasmanian handles its own memory, the global
ctypes.CDLL
reference keeps the library loaded for the entire Python session, which could limit flexibility in modular or long-running applications.
- If
A lazy-loading helper such as the following would improve safety and control:
_TASlib = None def get_tasmanian_lib(): global _TASlib if _TASlib is not None: return _TASlib libtas_path = os.getenv("LIBTASMANIAN_PATH") if not libtas_path: logger.warning("LIBTASMANIAN_PATH not set. Tasmanian-dependent features will be unavailable.") return None try: _TASlib = ctypes.CDLL(libtas_path) for name in ["tsgConstructTasmanianSparseGrid", ...]: getattr(_TASlib, name) return _TASlib except Exception as e: logger.error(f"Failed to load Tasmanian library: {e}") return None
Each method needing Tasmanian would then call:
lib = get_tasmanian_lib() if lib is None: raise RuntimeError("Tasmanian is not available.")
I noticed you implemented a related pattern in
PyTasmanianSG.__del__
, which is great, but we may want to consolidate this logic into a central function likeget_tasmanian_lib()
for reuse and extensibility.-
UnusedTypeVar
declarations inPyGeneralizedFirstOrderAlgorithm
were removed. -
The typoList(int)
was corrected toList[int]
inPyLUWs
. -
Global initialization is now deferred vialazy_init
. Initialization happens only on first use ofdynare()
(viaensure_initialized()
and the_has_run
flag). Users can also callensure_initialized()
manually to trigger setup earlier or outside ofdynare()
.
Let me know what you think of the remaining points, especially regarding the Tasmanian loading strategy. Once that's settled, I believe the code will be ready for release. Thanks again for the quality of your work and your responsiveness throughout! It's a real pleasure working with you on this.
-