Skip to content

Commit b931d39

Browse files
committed
#1: Refactor _cffi_api_util.py module into a class to reduce code redundancy between classic and PM versions.
1 parent 6c016d7 commit b931d39

File tree

4 files changed

+99
-229
lines changed

4 files changed

+99
-229
lines changed

dss/_cffi_api_util.py

Lines changed: 73 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
from __future__ import absolute_import
2-
from ._dss_capi import lib, ffi
32
import numpy as np
43

54
freeze = True
@@ -41,99 +40,97 @@ def __getattr__(self, key):
4140

4241

4342
def __setattr__(self, key, value):
44-
4543
if _case_insensitive:
4644
okey = key
4745
key = self._dss_atributes.get(key.lower(), None)
4846
if key is None:
49-
raise TypeError( "%r is a frozen class" % self)
47+
raise TypeError("%r is a frozen class" % self)
5048

5149
if self._isfrozen and not hasattr(self, key):
52-
raise TypeError( "%r is a frozen class" % self )
50+
raise TypeError("%r is a frozen class" % self)
5351

5452
object.__setattr__(self, key, value)
5553

5654

57-
def get_string(b):
58-
return ffi.string(b).decode(codec)
59-
60-
def get_float64_array(func, *args):
61-
ptr = ffi.new('double**')
62-
cnt = ffi.new('int32_t*')
63-
func(ptr, cnt, *args)
64-
if not cnt[0]:
65-
res = None
66-
else:
67-
res = np.frombuffer(ffi.buffer(ptr[0], cnt[0] * 8), dtype=np.float).copy()
6855

69-
lib.DSS_Dispose_PDouble(ptr)
70-
return res
56+
class CffiApiUtil(object):
57+
def __init__(self, ffi, lib):
58+
self.ffi = ffi
59+
self.lib = lib
7160

72-
73-
74-
def get_int32_array(func, *args):
75-
ptr = ffi.new('int32_t**')
76-
cnt = ffi.new('int32_t*')
77-
func(ptr, cnt, *args)
78-
if not cnt[0]:
79-
res = None
80-
else:
81-
res = np.frombuffer(ffi.buffer(ptr[0], cnt[0] * 4), dtype=np.int32).copy()
82-
83-
lib.DSS_Dispose_PInteger(ptr)
84-
return res
61+
def get_string(self, b):
62+
return self.ffi.string(b).decode(codec)
8563

64+
def get_float64_array(self, func, *args):
65+
ptr = self.ffi.new('double**')
66+
cnt = self.ffi.new('int32_t*')
67+
func(ptr, cnt, *args)
68+
if not cnt[0]:
69+
res = None
70+
else:
71+
res = np.frombuffer(self.ffi.buffer(ptr[0], cnt[0] * 8), dtype=np.float).copy()
72+
73+
self.lib.DSS_Dispose_PDouble(ptr)
74+
return res
8675

87-
def get_int8_array(func, *args):
88-
ptr = ffi.new('int8_t**')
89-
cnt = ffi.new('int32_t*')
90-
func(ptr, cnt, *args)
91-
if not cnt[0]:
92-
res = None
93-
else:
94-
res = np.frombuffer(ffi.buffer(ptr[0], cnt[0] * 1), dtype=np.int8).copy()
95-
96-
lib.DSS_Dispose_PByte(ptr)
97-
return res
98-
76+
def get_int32_array(self, func, *args):
77+
ptr = self.ffi.new('int32_t**')
78+
cnt = self.ffi.new('int32_t*')
79+
func(ptr, cnt, *args)
80+
if not cnt[0]:
81+
res = None
82+
else:
83+
res = np.frombuffer(self.ffi.buffer(ptr[0], cnt[0] * 4), dtype=np.int32).copy()
84+
85+
self.lib.DSS_Dispose_PInteger(ptr)
86+
return res
87+
88+
def get_int8_array(self, func, *args):
89+
ptr = self.ffi.new('int8_t**')
90+
cnt = self.ffi.new('int32_t*')
91+
func(ptr, cnt, *args)
92+
if not cnt[0]:
93+
res = None
94+
else:
95+
res = np.frombuffer(self.ffi.buffer(ptr[0], cnt[0] * 1), dtype=np.int8).copy()
9996

100-
def get_string_array(func, *args):
101-
ptr = ffi.new('char***')
102-
cnt = ffi.new('int32_t*')
103-
func(ptr, cnt, *args)
104-
if not cnt[0]:
105-
res = []
106-
else:
107-
actual_ptr = ptr[0]
108-
if actual_ptr == ffi.NULL:
97+
self.lib.DSS_Dispose_PByte(ptr)
98+
return res
99+
100+
def get_string_array(self, func, *args):
101+
ptr = self.ffi.new('char***')
102+
cnt = self.ffi.new('int32_t*')
103+
func(ptr, cnt, *args)
104+
if not cnt[0]:
109105
res = []
110106
else:
111-
res = [(str(ffi.string(actual_ptr[i]).decode(codec)) if (actual_ptr[i] != ffi.NULL) else None) for i in range(cnt[0])]
112-
113-
lib.DSS_Dispose_PPAnsiChar(ptr, cnt[0])
114-
return res
115-
116-
117-
118-
def prepare_float64_array(value):
119-
if type(value) is not np.ndarray or value.dtype != np.float64:
120-
value = np.array(value, dtype=np.float64)
121-
122-
ptr = ffi.cast('double*', ffi.from_buffer(data.data))
123-
cnt = data.size
124-
return value, ptr, cnt
125-
126-
def prepare_int32_array(value):
127-
if type(value) is not np.ndarray or value.dtype != np.int32:
128-
value = np.array(value, dtype=np.int32)
129-
130-
ptr = ffi.cast('int32_t*', ffi.from_buffer(data.data))
131-
cnt = data.size
132-
return value, ptr, cnt
133-
107+
actual_ptr = ptr[0]
108+
if actual_ptr == self.ffi.NULL:
109+
res = []
110+
else:
111+
res = [(str(self.ffi.string(actual_ptr[i]).decode(codec)) if (actual_ptr[i] != self.ffi.NULL) else None) for i in range(cnt[0])]
112+
113+
self.lib.DSS_Dispose_PPAnsiChar(ptr, cnt[0])
114+
return res
115+
116+
def prepare_float64_array(self, value):
117+
if type(value) is not np.ndarray or value.dtype != np.float64:
118+
value = np.array(value, dtype=np.float64)
119+
120+
ptr = self.ffi.cast('double*', self.ffi.from_buffer(data.data))
121+
cnt = data.size
122+
return value, ptr, cnt
123+
124+
def prepare_int32_array(self, value):
125+
if type(value) is not np.ndarray or value.dtype != np.int32:
126+
value = np.array(value, dtype=np.int32)
127+
128+
ptr = self.ffi.cast('int32_t*', self.ffi.from_buffer(data.data))
129+
cnt = data.size
130+
return value, ptr, cnt
134131

135-
def prepare_string_array(value):
136-
raise NotImplementedError
132+
def prepare_string_array(self, value):
133+
raise NotImplementedError
137134

138135

139136
# This might be useful for methods like Get_Channel that are exposed as Channel[] and Channel()

dss/dss_capi.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,21 @@
44
Copyright (c) 2016-2018 Paulo Meira
55
'''
66
from __future__ import absolute_import
7-
from ._dss_capi import lib, ffi
8-
from ._cffi_api_util import * # one for each version (parallel, classic), already bound to the cffi module
7+
from ._dss_capi import ffi, lib
8+
from ._cffi_api_util import *
99
import numpy as np
1010

11+
# Bind to the FFI module instance for OpenDSS-Classic
12+
api_util = CffiApiUtil(ffi, lib)
13+
get_string = api_util.get_string
14+
get_float64_array = api_util.get_float64_array
15+
get_int32_array = api_util.get_int32_array
16+
get_int8_array = api_util.get_int8_array
17+
get_string_array = api_util.get_string_array
18+
prepare_float64_array = api_util.prepare_float64_array
19+
prepare_int32_array = api_util.prepare_int32_array
20+
prepare_string_array = api_util.prepare_string_array
21+
1122
if not freeze:
1223
FrozenClass = object
1324

dss/pm/_cffi_api_util.py

Lines changed: 0 additions & 149 deletions
This file was deleted.

dss/pm/dsspm_capi.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,21 @@
44
Copyright (c) 2016-2018 Paulo Meira
55
'''
66
from __future__ import absolute_import
7-
from .._dsspm_capi import lib, ffi
8-
from ._cffi_api_util import * # one for each version (parallel, classic), already bound to the cffi module
7+
from .._dsspm_capi import ffi, lib
8+
from .._cffi_api_util import *
99
import numpy as np
1010

11+
# Bind to the FFI module instance for OpenDSS-PM
12+
api_util = CffiApiUtil(ffi, lib)
13+
get_string = api_util.get_string
14+
get_float64_array = api_util.get_float64_array
15+
get_int32_array = api_util.get_int32_array
16+
get_int8_array = api_util.get_int8_array
17+
get_string_array = api_util.get_string_array
18+
prepare_float64_array = api_util.prepare_float64_array
19+
prepare_int32_array = api_util.prepare_int32_array
20+
prepare_string_array = api_util.prepare_string_array
21+
1122
if not freeze:
1223
FrozenClass = object
1324

0 commit comments

Comments
 (0)