Skip to content

Commit 55f3597

Browse files
committed
For AltDSS: fix reprocess_buses_callback; should refactor to move it there
1 parent f8c11b5 commit 55f3597

File tree

3 files changed

+41
-11
lines changed

3 files changed

+41
-11
lines changed

docs/changelog.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,11 @@ relevant. See [DSS C-API's repository](https://github.com/dss-extensions/dss_cap
77

88
### 0.15.3
99

10-
Released on 2024-02-23.
10+
Released on 2024-02-26.
1111

1212
- Upgrade the backend to [**DSS C-API 0.14.2**](https://github.com/dss-extensions/dss_capi/releases/tag/0.14.2). There are a couple of minor fixes, including for `Lines.Parent`.
1313
- `patch_dss_com`: Allow the DSS instance to be callable for better compatibility with our DSS engine. Note that this won't have performance benefits nor handles complex scripts.
14+
- Fix Bus callback integration with AltDSS-Python. The relevant code should be moved there later.
1415

1516
### 0.15.2
1617

dss/__init__.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,13 @@
2323

2424
DssException = DSSException
2525

26-
# Bind to the FFI module instance for OpenDSS-v7
27-
api_util: CffiApiUtil = CffiApiUtil(ffi, lib) #: API utility functions and low-level access to the classic API
28-
2926
if not hasattr(lib, 'ctx_New'):
3027
# Module was built without the context API
28+
api_util: CffiApiUtil = CffiApiUtil(ffi, lib) #: API utility functions and low-level access to the classic API
3129
prime_api_util = None
3230
DSS_GR: IDSS = IDSS(api_util) #: GR (Global Result) interface
3331
else:
34-
prime_api_util = CffiApiUtil(ffi, lib, lib.ctx_Get_Prime()) #: API utility functions and low-level access for DSSContext API
32+
api_util = prime_api_util = CffiApiUtil(ffi, lib, lib.ctx_Get_Prime()) #: API utility functions and low-level access for DSSContext API
3533
DSS_GR: IDSS = IDSS(prime_api_util) #: GR (Global Result) interface using the new DSSContext API
3634

3735
DSS_IR: IDSS = DSS_GR #: IR was removed in DSS-Python v0.13.x, we'll keep mapping it to DSS_GR for this version

dss/_cffi_api_util.py

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -360,31 +360,51 @@ def __init__(self, ffi, lib, ctx=None):
360360
self.register_callbacks()
361361

362362

363+
def _check_for_error(self, result=None):
364+
"""
365+
Checks for a DSS engine error (on the default configuration).
366+
367+
By default, raises an exception if any error is detected, otherwise returns the `result` parameter.
368+
369+
If the user disabled exceptions, any error is simply ignored. Note that, in this case, manually
370+
calling this function would have no purpose/effects.
371+
372+
Note that, **in the future**, we may try showing a popup form like the official OpenDSS does on Windows
373+
if AllowForms is True. This behavior is not very portable though and not adequate for automated scripts.
374+
"""
375+
if self._errorPtr[0] and Base._use_exceptions:
376+
error_num = self._errorPtr[0]
377+
self._errorPtr[0] = 0
378+
raise DSSException(error_num, self.get_string(self.lib.Error_Get_Description()))
379+
380+
return result
381+
382+
363383
def reprocess_buses_callback(self, step: int):
364384
'''
365385
Used internally to remap buses to Python objects after the bus list is built.
366386
'''
367387
if self._is_clearing:
368388
return
369-
389+
370390
if step == 0:
371391
# Drop dead references
372392
self._bus_refs = [b for b in self._bus_refs if b() is not None]
373393

374394
# Create a name to object dict, dropping the weakref wrapper
375-
self._bus_ref_to_name = {
376-
b(): b().name
395+
self._bus_ref_to_name = [
396+
(b(), b().Name)
377397
for b in self._bus_refs
378-
}
398+
]
379399
return
380400

381401
if step != 1:
382402
return
383403

384404
# Now try to remap the objects; on exception, just invalidate everything
385405
try:
386-
ptrs = self._lib.Alt_Bus_GetListPtr()
387-
names = self._check_for_error(self._get_string_array(self._lib.Circuit_Get_AllBusNames))
406+
ptrs = self.lib.Alt_Bus_GetListPtr()
407+
names = self._check_for_error(self.get_string_array(self.lib.Circuit_Get_AllBusNames))
388408
except:
389409
for bus_ref in self._bus_refs:
390410
bus_ref()._invalidate_ptr()
@@ -393,6 +413,14 @@ def reprocess_buses_callback(self, step: int):
393413
return
394414

395415
self._bus_refs.clear()
416+
417+
if len(names) == 0:
418+
# No buses to rebind, invalidate all
419+
for old_bus, _ in self._bus_ref_to_name:
420+
old_bus._invalidate_ptr()
421+
422+
return
423+
396424
name_to_new_ptr = {name: ptrs[idx] for idx, name in enumerate(names)}
397425
for old_bus, old_name in self._bus_ref_to_name:
398426
new_ptr = name_to_new_ptr.get(old_name)
@@ -497,6 +525,9 @@ def init_buffers(self):
497525
# also keep a casted version for complex floats
498526
self.gr_cfloat64_pointers = (self.ffi.cast('double _Complex**', tmp_float64_pointers[0][0]), tmp_float64_pointers[1][0])
499527

528+
self._errorPtr = self.lib.Error_Get_NumberPtr()
529+
530+
500531
def clear_buffers(self):
501532
self.lib.DSS_DisposeGRData()
502533
self.lib.DSS_ResetStringBuffer()

0 commit comments

Comments
 (0)