Completed
Push — 0.7.dev ( 125b80...91561c )
by Andrei
01:13
created

package_builder.__create_package()   A

Complexity

Conditions 2

Size

Total Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
dl 0
loc 15
rs 9.4285
c 0
b 0
f 0
1
"""!
2
3
@brief Pyclustering package that is used to exchange between python core and 'ccore'.
4
5
@authors Andrei Novikov ([email protected])
6
@date 2014-2017
7
@copyright GNU Public License
8
9
@cond GNU_PUBLIC_LICENSE
10
    PyClustering is free software: you can redistribute it and/or modify
11
    it under the terms of the GNU General Public License as published by
12
    the Free Software Foundation, either version 3 of the License, or
13
    (at your option) any later version.
14
    
15
    PyClustering is distributed in the hope that it will be useful,
16
    but WITHOUT ANY WARRANTY; without even the implied warranty of
17
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
    GNU General Public License for more details.
19
    
20
    You should have received a copy of the GNU General Public License
21
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
22
@endcond
23
24
"""
25
26
27
28
from ctypes import *;
0 ignored issues
show
Unused Code introduced by
get_errno was imported with wildcard, but is not used.
Loading history...
Unused Code introduced by
Union was imported with wildcard, but is not used.
Loading history...
Unused Code introduced by
c_wchar was imported with wildcard, but is not used.
Loading history...
Unused Code introduced by
c_uint64 was imported with wildcard, but is not used.
Loading history...
Unused Code introduced by
SetPointerType was imported with wildcard, but is not used.
Loading history...
Unused Code introduced by
BigEndianStructure was imported with wildcard, but is not used.
Loading history...
Unused Code introduced by
pydll was imported with wildcard, but is not used.
Loading history...
Unused Code introduced by
wstring_at was imported with wildcard, but is not used.
Loading history...
Unused Code introduced by
c_int64 was imported with wildcard, but is not used.
Loading history...
Unused Code introduced by
OleDLL was imported with wildcard, but is not used.
Loading history...
Unused Code introduced by
DllCanUnloadNow was imported with wildcard, but is not used.
Loading history...
Unused Code introduced by
c_ulonglong was imported with wildcard, but is not used.
Loading history...
Unused Code introduced by
oledll was imported with wildcard, but is not used.
Loading history...
Unused Code introduced by
c_int16 was imported with wildcard, but is not used.
Loading history...
Unused Code introduced by
c_bool was imported with wildcard, but is not used.
Loading history...
Unused Code introduced by
PYFUNCTYPE was imported with wildcard, but is not used.
Loading history...
Unused Code introduced by
c_char was imported with wildcard, but is not used.
Loading history...
Unused Code introduced by
alignment was imported with wildcard, but is not used.
Loading history...
Unused Code introduced by
get_last_error was imported with wildcard, but is not used.
Loading history...
Unused Code introduced by
DEFAULT_MODE was imported with wildcard, but is not used.
Loading history...
Unused Code introduced by
WinDLL was imported with wildcard, but is not used.
Loading history...
Unused Code introduced by
FormatError was imported with wildcard, but is not used.
Loading history...
Unused Code introduced by
PyDLL was imported with wildcard, but is not used.
Loading history...
Unused Code introduced by
RTLD_LOCAL was imported with wildcard, but is not used.
Loading history...
Unused Code introduced by
pythonapi was imported with wildcard, but is not used.
Loading history...
Unused Code introduced by
ARRAY was imported with wildcard, but is not used.
Loading history...
Unused Code introduced by
CFUNCTYPE was imported with wildcard, but is not used.
Loading history...
Unused Code introduced by
memmove was imported with wildcard, but is not used.
Loading history...
Unused Code introduced by
c_wchar_p was imported with wildcard, but is not used.
Loading history...
Unused Code introduced by
c_uint8 was imported with wildcard, but is not used.
Loading history...
Unused Code introduced by
c_voidp was imported with wildcard, but is not used.
Loading history...
Unused Code introduced by
c_buffer was imported with wildcard, but is not used.
Loading history...
Unused Code introduced by
c_ushort was imported with wildcard, but is not used.
Loading history...
Unused Code introduced by
HRESULT was imported with wildcard, but is not used.
Loading history...
Unused Code introduced by
c_longdouble was imported with wildcard, but is not used.
Loading history...
Unused Code introduced by
ArgumentError was imported with wildcard, but is not used.
Loading history...
Unused Code introduced by
sizeof was imported with wildcard, but is not used.
Loading history...
Unused Code introduced by
c_int32 was imported with wildcard, but is not used.
Loading history...
Unused Code introduced by
create_string_buffer was imported with wildcard, but is not used.
Loading history...
Unused Code introduced by
resize was imported with wildcard, but is not used.
Loading history...
Unused Code introduced by
addressof was imported with wildcard, but is not used.
Loading history...
Unused Code introduced by
set_last_error was imported with wildcard, but is not used.
Loading history...
Unused Code introduced by
c_int8 was imported with wildcard, but is not used.
Loading history...
Unused Code introduced by
c_ssize_t was imported with wildcard, but is not used.
Loading history...
Unused Code introduced by
WINFUNCTYPE was imported with wildcard, but is not used.
Loading history...
Unused Code introduced by
Array was imported with wildcard, but is not used.
Loading history...
Unused Code introduced by
LibraryLoader was imported with wildcard, but is not used.
Loading history...
Unused Code introduced by
LittleEndianStructure was imported with wildcard, but is not used.
Loading history...
Unused Code introduced by
WinError was imported with wildcard, but is not used.
Loading history...
Unused Code introduced by
c_ubyte was imported with wildcard, but is not used.
Loading history...
Unused Code introduced by
set_errno was imported with wildcard, but is not used.
Loading history...
Unused Code introduced by
create_unicode_buffer was imported with wildcard, but is not used.
Loading history...
Unused Code introduced by
c_char_p was imported with wildcard, but is not used.
Loading history...
Unused Code introduced by
string_at was imported with wildcard, but is not used.
Loading history...
Unused Code introduced by
windll was imported with wildcard, but is not used.
Loading history...
Unused Code introduced by
py_object was imported with wildcard, but is not used.
Loading history...
Unused Code introduced by
c_uint32 was imported with wildcard, but is not used.
Loading history...
Unused Code introduced by
CDLL was imported with wildcard, but is not used.
Loading history...
Unused Code introduced by
cdll was imported with wildcard, but is not used.
Loading history...
Unused Code introduced by
RTLD_GLOBAL was imported with wildcard, but is not used.
Loading history...
Unused Code introduced by
GetLastError was imported with wildcard, but is not used.
Loading history...
Unused Code introduced by
DllGetClassObject was imported with wildcard, but is not used.
Loading history...
Unused Code introduced by
c_longlong was imported with wildcard, but is not used.
Loading history...
Unused Code introduced by
c_short was imported with wildcard, but is not used.
Loading history...
Unused Code introduced by
c_byte was imported with wildcard, but is not used.
Loading history...
Unused Code introduced by
kind was imported with wildcard, but is not used.
Loading history...
Unused Code introduced by
byref was imported with wildcard, but is not used.
Loading history...
Unused Code introduced by
memset was imported with wildcard, but is not used.
Loading history...
Unused Code introduced by
c_uint16 was imported with wildcard, but is not used.
Loading history...
29
30
31
32
class pyclustering_package(Structure):
33
    """!
34
    @brief pyclustering_package description in memory.
35
    @details Represents following C++ structure:
36
    
37
            typedef struct pyclustering_package {
38
                std::size_t      size;
39
                unsigned int     type;
40
                void *           data;
41
            }
42
    """
43
    
44
    _fields_ = [ ("size", c_size_t),
45
                 ("type", c_uint),
46
                 ("data", POINTER(c_void_p)) ];
47
48
49
50
class pyclustering_type_data:
51
    """!
52
    @brief Contains constants that defines type of package.
53
    
54
    """
55
    
56
    PYCLUSTERING_TYPE_INT               = 0x00;
57
    PYCLUSTERING_TYPE_UNSIGNED_INT      = 0x01;
58
    PYCLUSTERING_TYPE_FLOAT             = 0x02;
59
    PYCLUSTERING_TYPE_DOUBLE            = 0x03;
60
    PYCLUSTERING_TYPE_LONG              = 0x04;
61
    PYCLUSTERING_TYPE_UNSIGNED_LONG     = 0x05;
62
    PYCLUSTERING_TYPE_LIST              = 0x06;
63
    PYCLUSTERING_TYPE_SIZE_T            = 0x07;
64
    PYCLUSTERING_TYPE_UNDEFINED         = 0x08;
65
66
    __CTYPE_PYCLUSTERING_MAP = { 
67
        c_int                           : PYCLUSTERING_TYPE_INT,
68
        c_uint                          : PYCLUSTERING_TYPE_UNSIGNED_INT,
69
        c_float                         : PYCLUSTERING_TYPE_FLOAT,
70
        c_double                        : PYCLUSTERING_TYPE_DOUBLE,
71
        c_long                          : PYCLUSTERING_TYPE_LONG,
72
        c_ulong                         : PYCLUSTERING_TYPE_UNSIGNED_LONG,
73
        POINTER(pyclustering_package)   : PYCLUSTERING_TYPE_LIST,
74
        c_size_t                        : PYCLUSTERING_TYPE_SIZE_T,
75
        None                            : PYCLUSTERING_TYPE_UNDEFINED
76
    }
77
78
    __PYCLUSTERING_CTYPE_MAP = {
79
        PYCLUSTERING_TYPE_INT             : c_int,
80
        PYCLUSTERING_TYPE_UNSIGNED_INT    : c_uint,
81
        PYCLUSTERING_TYPE_FLOAT           : c_float,
82
        PYCLUSTERING_TYPE_DOUBLE          : c_double,
83
        PYCLUSTERING_TYPE_LONG            : c_long,
84
        PYCLUSTERING_TYPE_UNSIGNED_LONG   : c_ulong,
85
        PYCLUSTERING_TYPE_LIST            : POINTER(pyclustering_package),
86
        PYCLUSTERING_TYPE_SIZE_T          : c_size_t,
87
        PYCLUSTERING_TYPE_UNDEFINED       : None
88
    }
89
90
    @staticmethod
91
    def get_ctype(pyclustering_package_type):
92
        """!
93
        @return (ctype) Return ctype that corresponds to pyclustering type data.
94
        
95
        """
96
        return pyclustering_type_data.__PYCLUSTERING_CTYPE_MAP[pyclustering_package_type];
97
98
    @staticmethod
99
    def get_pyclustering_type(data_ctype):
100
        """!
101
        @return (unit) Return pyclustering data type that corresponds to ctype.
102
        
103
        """
104
        return pyclustering_type_data.__CTYPE_PYCLUSTERING_MAP[data_ctype];
105
106
107
class package_builder:
108
    """!
109
    @brief Package builder provides service to create 'pyclustering_package' from data that is stored in 'list' container.
110
111
    """
112
    def __init__(self, dataset, c_data_type = None):
113
        """!
114
        @brief Initialize package builder object by dataset.
115
        
116
        @param[in] dataset (list): Data that should be packed in 'pyclustering_package'.
117
        @param[in] c_data_type (ctype.type): If specified than specified data type is used for data storing in package. 
118
        
119
        """
120
        self.__dataset = dataset;
121
        self.__c_data_type = c_data_type;
122
123
124
    def create(self):
125
        """!
126
        @brief Performs packing procedure of the data to the package.
127
        
128
        @return (pointer) ctype-pointer to pyclustering package.
129
        
130
        """
131
        return self.__create_package(self.__dataset);
132
133
134
    def __get_type(self, pyclustering_type_data):
0 ignored issues
show
Comprehensibility Bug introduced by
pyclustering_type_data is re-defining a name which is already available in the outer-scope (previously defined on line 50).

It is generally a bad practice to shadow variables from the outer-scope. In most cases, this is done unintentionally and might lead to unexpected behavior:

param = 5

class Foo:
    def __init__(self, param):   # "param" would be flagged here
        self.param = param
Loading history...
135
        if (self.__c_data_type is None):
136
            return pyclustering_type_data;
137
        
138
        return self.__c_data_type;
139
140
141
    def __create_package(self, dataset):
142
        dataset_package = pyclustering_package();
143
        
144
        dataset_package.size = len(dataset);
145
    
146
        if (len(dataset) == 0):
147
            dataset_package.type = pyclustering_type_data.PYCLUSTERING_TYPE_UNDEFINED;
148
            dataset_package.data = None;
149
    
150
            return pointer(dataset_package);
151
    
152
        c_data_type = self.__fill_type(dataset_package, dataset);
153
        self.__fill_data(dataset_package, c_data_type, dataset);
154
        
155
        return pointer(dataset_package);
156
157
158
    def __fill_dataset_type(self, dataset_package, dataset):
159
        if (isinstance(dataset[0], list)):
160
            dataset_package.type = pyclustering_type_data.PYCLUSTERING_TYPE_LIST;
161
        
162
        elif (isinstance(dataset[0], int)):
163
            dataset_package.type = pyclustering_type_data.PYCLUSTERING_TYPE_LONG;
164
        
165
        elif (isinstance(dataset[0], float)):
166
            dataset_package.type = pyclustering_type_data.PYCLUSTERING_TYPE_DOUBLE;
167
        
168
        else:
169
            raise NameError("Not supported type of pyclustering package.");
170
        
171
        return pyclustering_type_data.get_ctype(dataset_package.type);
172
173
174
    def __fill_specify_type(self, dataset_package):
175
        dataset_package.type = pyclustering_type_data.get_pyclustering_type(self.__c_data_type);
176
        return self.__c_data_type;
177
178
179
    def __fill_type(self, dataset_package, dataset):
180
        if (isinstance(dataset[0], list)):
181
            dataset_package.type = pyclustering_type_data.PYCLUSTERING_TYPE_LIST;
182
            return None;
183
        
184
        if (self.__c_data_type is None):
185
            return self.__fill_dataset_type(dataset_package, dataset);
186
        
187
        return self.__fill_specify_type(dataset_package);
188
189
190
    def __fill_data(self, dataset_package, c_data_type, dataset):
191
        if (dataset_package.type == pyclustering_type_data.PYCLUSTERING_TYPE_LIST):
192
            package_data = (POINTER(pyclustering_package) * len(dataset))();
193
            for index in range(len(dataset)):
194
                package_data[index] = self.__create_package(dataset[index]);
195
            
196
            dataset_package.data = cast(package_data, POINTER(c_void_p));
197
        else:
198
            array_object = (c_data_type * len(dataset))(*dataset);
199
            dataset_package.data = cast(array_object, POINTER(c_void_p));
200
201
202
203
class package_extractor:
204
    """!
205
    @brief Package extractor provides servies to unpack pyclustering package.
206
    
207
    """
208
    def __init__(self, package_pointer):
209
        """!
210
        @brief Initialize package extractor object by ctype-pointer to 'pyclustering_package'.
211
        
212
        @param[in] package_pointer (pointer): ctype-pointer to 'pyclustering_package' that should be used for unpacking.
213
        
214
        """
215
        self.__package_pointer = package_pointer;
216
217
218
    def extract(self):
219
        """!
220
        @brief Performs unpacking procedure of the pyclustering package to the data.
221
        
222
        @return (list) Extracted data from the pyclustering package.
223
        
224
        """
225
        return self.__extract_data(self.__package_pointer);
226
227
228
    def __extract_data(self, ccore_package_pointer):
229
        if (ccore_package_pointer == 0):
230
            return [];
231
        
232
        pointer_package = cast(ccore_package_pointer, POINTER(pyclustering_package));
233
        return self.__unpack_pointer_data(pointer_package);
234
    
235
    
236
    def __unpack_data(self, pointer_package, pointer_data, type_package):
237
        result = [];
238
        
239
        for index in range(0, pointer_package[0].size):
240
            if (type_package == pyclustering_type_data.PYCLUSTERING_TYPE_LIST):
241
                pointer_package = cast(pointer_data[index], (POINTER(pyclustering_package)));
242
                result.append(self.__extract_data(pointer_package));
243
            
244
            else:
245
                result.append(pointer_data[index]);
246
        
247
        return result;
248
249
250
    def __unpack_pointer_data(self, pointer_package):
251
        type_package = pointer_package[0].type;
252
        pointer_data = None;
253
        
254
        if (pointer_package[0].size == 0):
255
            return [];
256
        
257
        if (type_package == pyclustering_type_data.PYCLUSTERING_TYPE_INT):
258
            pointer_data = cast(pointer_package[0].data, POINTER(c_int));
259
        
260
        elif (type_package == pyclustering_type_data.PYCLUSTERING_TYPE_UNSIGNED_INT):
261
            pointer_data = cast(pointer_package[0].data, POINTER(c_uint));
262
        
263
        elif (type_package == pyclustering_type_data.PYCLUSTERING_TYPE_FLOAT):
264
            pointer_data = cast(pointer_package[0].data, POINTER(c_float));
265
        
266
        elif (type_package == pyclustering_type_data.PYCLUSTERING_TYPE_DOUBLE):
267
            pointer_data = cast(pointer_package[0].data, POINTER(c_double));
268
        
269
        elif (type_package == pyclustering_type_data.PYCLUSTERING_TYPE_LONG):
270
            pointer_data = cast(pointer_package[0].data, POINTER(c_long));
271
        
272
        elif (type_package == pyclustering_type_data.PYCLUSTERING_TYPE_UNSIGNED_LONG):
273
            pointer_data = cast(pointer_package[0].data, POINTER(c_ulong));
274
        
275
        elif (type_package == pyclustering_type_data.PYCLUSTERING_TYPE_SIZE_T):
276
            pointer_data = cast(pointer_package[0].data, POINTER(c_size_t));
277
        
278
        elif (type_package == pyclustering_type_data.PYCLUSTERING_TYPE_LIST):
279
            pointer_data = cast(pointer_package[0].data, POINTER(POINTER(pyclustering_package)));
280
    
281
        else:
282
            raise NameError("Not supported type of pyclustering package.");
283
        
284
        return self.__unpack_data(pointer_package, pointer_data, type_package);